xref: /OK3568_Linux_fs/external/rkwifibt/drivers/rtl8852be/phl/phl_mr.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /******************************************************************************
2  *
3  * Copyright(c) 2019 Realtek Corporation.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of version 2 of the GNU General Public License as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12  * more details.
13  *
14  *****************************************************************************/
15 #define _PHL_MR_C_
16 #include "phl_headers.h"
17 #ifdef RTW_WKARD_MRC_ISSUE_NULL_WITH_SCAN_OPS
18 #include "phl_scan.h"
19 #endif
20 
21 #ifdef DBG_PHL_MR
phl_mr_dump_role_info(const char * caller,const int line,bool show_caller,struct phl_info_t * phl_info,struct rtw_wifi_role_t * wrole)22 void phl_mr_dump_role_info(const char *caller, const int line, bool show_caller,
23 	struct phl_info_t *phl_info, struct rtw_wifi_role_t *wrole)
24 {
25 	if (show_caller)
26 		PHL_INFO("###### FUN - %s LINE - %d #######\n", caller, line);
27 
28 	PHL_INFO("\t[WROLE] RIDX:%d - MAC-Addr:%02x-%02x-%02x-%02x-%02x-%02x RTYPE:%d MSTS:%d\n",
29 		wrole->id, wrole->mac_addr[0], wrole->mac_addr[1], wrole->mac_addr[2],
30 		wrole->mac_addr[3], wrole->mac_addr[4], wrole->mac_addr[5],
31 		wrole->type, wrole->mstate);
32 	PHL_INFO("\t[WROLE] HW Band_idx:%d, Port_idx:%d, WMM_idx:%d\n", wrole->hw_band, wrole->hw_port, wrole->hw_wmm);
33 
34 	if (wrole->type == PHL_RTYPE_AP || wrole->type == PHL_RTYPE_P2P_GO || wrole->type == PHL_RTYPE_MESH) {
35 		#ifdef RTW_PHL_BCN
36 		PHL_INFO("\t[WROLE AP] BSSID:%02x-%02x-%02x-%02x-%02x-%02x\n",
37 			wrole->bcn_cmn.bssid[0], wrole->bcn_cmn.bssid[1], wrole->bcn_cmn.bssid[2],
38 			wrole->bcn_cmn.bssid[3], wrole->bcn_cmn.bssid[4], wrole->bcn_cmn.bssid[5]);
39 		PHL_INFO("\t[WROLE AP] BCN id:%d, interval:%d, rate:0x%04x, DTIM:%d\n",
40 			wrole->bcn_cmn.bcn_id, wrole->bcn_cmn.bcn_interval,
41 			wrole->bcn_cmn.bcn_rate, wrole->bcn_cmn.bcn_dtim);
42 		PHL_INFO("\t[WROLE AP] HW MBSSID idx:%d, MBID NUM:%d\n",
43 			wrole->hw_mbssid, wrole->mbid_num);
44 		#endif
45 	}
46 	PHL_INFO("\n");
47 	if (show_caller)
48 		PHL_INFO("#################################\n");
49 }
50 
51 
phl_mr_dump_chctx_info(const char * caller,const int line,bool show_caller,struct phl_info_t * phl_info,struct phl_queue * chan_ctx_queue,struct rtw_chan_ctx * chanctx)52 void phl_mr_dump_chctx_info(const char *caller, const int line, bool show_caller,
53 	struct phl_info_t *phl_info, struct phl_queue *chan_ctx_queue, struct rtw_chan_ctx *chanctx)
54 {
55 	u8 role_num = 0;
56 	role_num = phl_chanctx_get_rnum(phl_info, chan_ctx_queue, chanctx);
57 
58 	if (show_caller)
59 		PHL_INFO("###### FUN - %s LINE - %d #######\n", caller, line);
60 
61 	PHL_INFO("\t[CH-CTX] role num:%d map:0x%02x, DFS enable:%s\n",
62 		role_num, chanctx->role_map,
63 		(chanctx->dfs_enabled) ? "Y" : "N");
64 	PHL_DUMP_CHAN_DEF(&chanctx->chan_def);
65 
66 	if (show_caller)
67 		PHL_INFO("#################################\n");
68 }
69 
70 const char *const _opmod_str[] = {
71 	"MR_OP_NON",
72 	"MR_OP_SCC",
73 	"MR_OP_MCC",
74 	"MR_OP_MAX"
75 };
76 #define _get_opmod_str(opmod) (((opmod) >= MR_OP_MAX) ? _opmod_str[MR_OP_MAX] : _opmod_str[(opmod)])
77 
phl_mr_dump_band_info(const char * caller,const int line,bool show_caller,struct phl_info_t * phl_info,struct hw_band_ctl_t * band_ctrl)78 void phl_mr_dump_band_info(const char *caller, const int line, bool show_caller,
79 	struct phl_info_t *phl_info, struct hw_band_ctl_t *band_ctrl)
80 {
81 	u8 role_num = 0;
82 	int chanctx_num = phl_mr_get_chanctx_num(phl_info, band_ctrl);
83 
84 	role_num = phl_mr_get_role_num(phl_info, band_ctrl);
85 
86 	if (show_caller)
87 		PHL_INFO("###### FUN - %s LINE - %d #######\n", caller, line);
88 
89 	PHL_INFO("\t[BAND-%d] op_mode:%s port map:0x%02x, role num:%d map:0x%02x\n",
90 		band_ctrl->id, _get_opmod_str(band_ctrl->op_mode),
91 		band_ctrl->port_map, role_num, band_ctrl->role_map);
92 
93 	/*dump mr_info*/
94 	PHL_INFO("\t[BAND-%d] sta_num:%d, ld_sta_num:%d, lg_sta_num:%d\n",
95 		band_ctrl->id, band_ctrl->cur_info.sta_num,
96 		band_ctrl->cur_info.ld_sta_num, band_ctrl->cur_info.lg_sta_num);
97 	PHL_INFO("\t[BAND-%d] ap_num:%d, ld_ap_num:%d\n",
98 		band_ctrl->id, band_ctrl->cur_info.ap_num, band_ctrl->cur_info.ld_ap_num);
99 
100 	PHL_INFO("\t[BAND-%d] chan_ctx num:%d\n", band_ctrl->id, chanctx_num);
101 
102 	if (chanctx_num) {
103 		struct rtw_chan_ctx *chanctx = NULL;
104 		_os_list *chctx_list = &band_ctrl->chan_ctx_queue.queue;
105 		void *drv = phl_to_drvpriv(phl_info);
106 
107 		_os_spinlock(drv, &band_ctrl->chan_ctx_queue.lock, _ps, NULL);
108 		phl_list_for_loop(chanctx, struct rtw_chan_ctx, chctx_list, list) {
109 			PHL_DUMP_CHAN_CTX(phl_info, &band_ctrl->chan_ctx_queue, chanctx);
110 		}
111 		_os_spinunlock(drv, &band_ctrl->chan_ctx_queue.lock, _ps, NULL);
112 	}
113 	PHL_INFO("\n");
114 	if (show_caller)
115 		PHL_INFO("#################################\n");
116 }
117 
phl_mr_dump_info(const char * caller,const int line,bool show_caller,struct phl_info_t * phl_info)118 void phl_mr_dump_info(const char *caller, const int line, bool show_caller,
119 	struct phl_info_t *phl_info)
120 {
121 	struct rtw_phl_com_t *phl_com = phl_info->phl_com;
122 	struct mr_ctl_t *mr_ctl = phlcom_to_mr_ctrl(phl_com);
123 	struct rtw_wifi_role_t *wrole;
124 	u8 i;
125 	u8 role_num = 0;
126 
127 	if (show_caller)
128 		PHL_INFO("###### FUN - %s LINE - %d #######\n", caller, line);
129 
130 	for (i = 0; i < MAX_WIFI_ROLE_NUMBER; i++) {
131 		if (mr_ctl->role_map & BIT(i))
132 			role_num++;
133 	}
134 
135 	PHL_INFO("[MR] MAX wrole num:%d, created num:%d map:0x%02x\n",
136 			MAX_WIFI_ROLE_NUMBER, role_num, mr_ctl->role_map);
137 	PHL_INFO("[MR] is_sb:%s\n", (mr_ctl->is_sb) ? "Y" : "N");
138 
139 	for (i = 0; i < MAX_WIFI_ROLE_NUMBER; i++) {
140 		if (mr_ctl->role_map & BIT(i)) {
141 			wrole = rtw_phl_get_wrole_by_ridx(phl_info->phl_com, i);
142 			PHL_DUMP_ROLE(phl_info, wrole);
143 		}
144 	}
145 
146 	for (i = 0; i < MAX_BAND_NUM; i++)
147 		PHL_DUMP_BAND_CTL(phl_info, &mr_ctl->band_ctrl[i]);
148 
149 	if (show_caller)
150 		PHL_INFO("#################################\n");
151 }
152 
phl_mr_dump_cur_chandef(const char * caller,const int line,bool show_caller,struct phl_info_t * phl_info,struct rtw_wifi_role_t * wifi_role)153 void phl_mr_dump_cur_chandef(const char *caller, const int line, bool show_caller,
154 		struct phl_info_t *phl_info, struct rtw_wifi_role_t *wifi_role)
155 {
156 	struct rtw_phl_com_t *phl_com = phl_info->phl_com;
157 	struct mr_ctl_t *mr_ctl = phlcom_to_mr_ctrl(phl_com);
158 	struct rtw_chan_def *chan_def = NULL;
159 
160 	if (show_caller)
161 		PHL_INFO("###### FUN - %s LINE - %d #######\n", caller, line);
162 
163 	if (wifi_role->chanctx) {
164 		chan_def = &wifi_role->chanctx->chan_def;
165 		PHL_INFO("==== MR Chan-def ===\n");
166 		PHL_DUMP_CHAN_DEF(chan_def);
167 	}
168 
169 	chan_def = &wifi_role->chandef;
170 	PHL_INFO("==== WR-%d Chan-def ===\n", wifi_role->id);
171 	PHL_DUMP_CHAN_DEF(chan_def);
172 
173 	chan_def = &mr_ctl->hal_com->band[wifi_role->hw_band].cur_chandef;
174 	PHL_INFO("==== HAL Band-%d Chan-def ===\n", wifi_role->hw_band);
175 	PHL_DUMP_CHAN_DEF(chan_def);
176 
177 	if (show_caller)
178 		PHL_INFO("#################################\n");
179 }
180 
181 #ifdef	PHL_MR_PROC_CMD
rtw_phl_mr_dump_info(void * phl,bool show_caller)182 void rtw_phl_mr_dump_info(void *phl, bool show_caller)
183 {
184 	struct phl_info_t *phl_info = (struct phl_info_t *)phl;
185 
186 	if (show_caller)
187 		PHL_DUMP_MR(phl_info);
188 	else
189 		PHL_DUMP_MR_EX(phl_info);
190 }
rtw_phl_mr_dump_band_ctl(void * phl,bool show_caller)191 void rtw_phl_mr_dump_band_ctl(void *phl, bool show_caller)
192 {
193 	struct phl_info_t *phl_info = (struct phl_info_t *)phl;
194 	struct rtw_phl_com_t *phl_com = phl_info->phl_com;
195 	struct mr_ctl_t *mr_ctl = phlcom_to_mr_ctrl(phl_com);
196 	int i;
197 
198 	for (i = 0; i < MAX_BAND_NUM; i++) {
199 		if (show_caller)
200 			PHL_DUMP_BAND_CTL(phl_info, &mr_ctl->band_ctrl[i]);
201 		else
202 			PHL_DUMP_BAND_CTL_EX(phl_info, &mr_ctl->band_ctrl[i]);
203 
204 	}
205 }
206 #endif /*PHL_MR_PROC_CMD*/
207 #endif /*DBG_PHL_MR*/
208 
_search_ld_sta_wrole(struct rtw_wifi_role_t * wrole,u8 exclude_self)209 static struct rtw_wifi_role_t *_search_ld_sta_wrole(struct rtw_wifi_role_t *wrole, u8 exclude_self)
210 {
211 	u8 ridx = 0;
212 	struct rtw_phl_com_t *phl_com = wrole->phl_com;
213 	struct rtw_chan_ctx *chanctx = wrole->chanctx;
214 	struct rtw_wifi_role_t *wr = NULL;
215 
216 	if (chanctx == NULL) {
217 		PHL_ERR("%s wifi role(%d) chan ctx is null\n", __func__, wrole->id);
218 		goto exit;
219 	}
220 
221 	for (ridx = 0; ridx < MAX_WIFI_ROLE_NUMBER; ridx++) {
222 		if (chanctx->role_map & BIT(ridx)) {
223 			wr = &phl_com->wifi_roles[ridx];
224 			if (wr) {
225 				if ((exclude_self) && (wr == wrole))
226 					continue;
227 				if (wr->type == PHL_RTYPE_STATION || wr->type == PHL_RTYPE_TDLS)
228 					break;
229 			}
230 		}
231 	}
232 
233 	if (wr)
234 		PHL_INFO("search Linked STA wifi role (%d)\n", wr->id);
235 exit:
236 	return wr;
237 }
238 
rtw_phl_mr_dump_cur_chandef(void * phl,struct rtw_wifi_role_t * wrole)239 void rtw_phl_mr_dump_cur_chandef(void *phl, struct rtw_wifi_role_t *wrole)
240 {
241 	#ifdef	PHL_MR_PROC_CMD
242 	struct phl_info_t *phl_info = (struct phl_info_t *)phl;
243 
244 	PHL_DUMP_CUR_CHANDEF(phl_info, wrole);
245 	#endif
246 }
247 
248 
249 static enum rtw_phl_status
_phl_band_ctrl_init(struct phl_info_t * phl_info)250 _phl_band_ctrl_init(struct phl_info_t *phl_info)
251 {
252 	void *drv = phl_to_drvpriv(phl_info);
253 	struct mr_ctl_t *mr_ctl = phlcom_to_mr_ctrl(phl_info->phl_com);
254 	struct hw_band_ctl_t *band_ctrl;
255 	u8 band_idx = 0;
256 
257 	for (band_idx = 0; band_idx < MAX_BAND_NUM; band_idx++) {
258 		band_ctrl = &(mr_ctl->band_ctrl[band_idx]);
259 		band_ctrl->id = band_idx;
260 		_os_spinlock_init(drv, &(band_ctrl->lock));
261 		pq_init(drv, &band_ctrl->chan_ctx_queue);
262 		band_ctrl->op_mode = MR_OP_NON;
263 		band_ctrl->tsf_sync_port = HW_PORT_MAX;
264 	}
265 
266 	return RTW_PHL_STATUS_SUCCESS;
267 }
268 
269 #ifdef CONFIG_CMD_DISP
270 static enum phl_mdl_ret_code
_phl_mrc_module_init(void * phl_info,void * dispr,void ** priv)271 _phl_mrc_module_init(void *phl_info, void *dispr, void **priv)
272 {
273 	enum phl_mdl_ret_code ret = MDL_RET_FAIL;
274 
275 	FUNCIN();
276 	*priv = phl_info;
277 	FUNCOUT();
278 
279 	ret = MDL_RET_SUCCESS;
280 	return ret;
281 }
282 
283 static void
_phl_mrc_module_deinit(void * dispr,void * priv)284 _phl_mrc_module_deinit(void *dispr, void *priv)
285 {
286 	enum phl_mdl_ret_code ret = MDL_RET_FAIL;
287 
288 	FUNCIN();
289 	FUNCOUT();
290 
291 	ret = MDL_RET_SUCCESS;
292 }
293 
294 static enum phl_mdl_ret_code
_phl_mrc_module_start(void * dispr,void * priv)295 _phl_mrc_module_start(void *dispr, void *priv)
296 {
297 	enum phl_mdl_ret_code ret = MDL_RET_FAIL;
298 
299 	FUNCIN();
300 	FUNCOUT();
301 
302 	ret = MDL_RET_SUCCESS;
303 	return ret;
304 }
305 
306 static enum phl_mdl_ret_code
_phl_mrc_module_stop(void * dispr,void * priv)307 _phl_mrc_module_stop(void *dispr, void *priv)
308 {
309 	enum phl_mdl_ret_code ret = MDL_RET_FAIL;
310 
311 	FUNCIN();
312 	FUNCOUT();
313 
314 	ret = MDL_RET_SUCCESS;
315 	return ret;
316 }
317 
318 /* Same behaviour as rtw_phl_connect_prepare without cmd dispr */
319 enum rtw_phl_status
_phl_mrc_module_connect_start_hdlr(struct phl_info_t * phl_info,struct rtw_wifi_role_t * wrole)320 _phl_mrc_module_connect_start_hdlr(struct phl_info_t *phl_info,
321 				   struct rtw_wifi_role_t *wrole)
322 {
323 	enum rtw_phl_status psts = RTW_PHL_STATUS_FAILURE;
324 
325 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "%s: wrole->id(%d)\n",
326 		  __func__, wrole->id);
327 	wrole->mstate = MLME_LINKING;
328 	psts = phl_role_notify(phl_info, wrole);
329 	if (psts != RTW_PHL_STATUS_SUCCESS) {
330 		PHL_ERR("%s role notify failed\n", __func__);
331 		goto _exit;
332 	}
333 	psts = phl_mr_info_upt(phl_info, wrole);
334 	if (psts != RTW_PHL_STATUS_SUCCESS) {
335 		PHL_ERR("%s mr info upt failed\n", __func__);
336 		goto _exit;
337 	}
338 
339 	psts = rtw_phl_mr_rx_filter(phl_info, wrole);
340 	if (psts != RTW_PHL_STATUS_SUCCESS) {
341 		PHL_ERR("%s set mr_rx_filter failed\n", __func__);
342 		goto _exit;
343 	}
344 
345 #ifdef CONFIG_PHL_P2PPS
346 	phl_p2pps_noa_all_role_pause(phl_info, wrole->hw_band);
347 #endif
348 #ifdef CONFIG_MCC_SUPPORT
349 	/* disable MR coex mechanism(if runing) */
350 	psts = phl_mr_coex_disable(phl_info, wrole, wrole->hw_band,
351 					MR_COEX_TRIG_BY_LINKING);
352 	if (psts != RTW_PHL_STATUS_SUCCESS) {
353 		PHL_ERR("%s: MR coex disable fail\n", __func__);
354 		goto _exit;
355 	}
356 #endif
357 	PHL_DUMP_MR_EX(phl_info);
358 _exit:
359 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "%s: psts(%d)\n",
360 		  __func__, psts);
361 	return psts;
362 }
363 
364 /* Same behaviour as rtw_phl_connected without cmd dispr */
365 enum rtw_phl_status
_phl_mrc_module_connect_end_hdlr(struct phl_info_t * phl_info,struct rtw_wifi_role_t * wrole)366 _phl_mrc_module_connect_end_hdlr(struct phl_info_t *phl_info,
367 				 struct rtw_wifi_role_t *wrole)
368 {
369 	enum rtw_phl_status psts = RTW_PHL_STATUS_FAILURE;
370 
371 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "%s: wrole->id(%d)\n",
372 		  __func__, wrole->id);
373 	if (wrole->type == PHL_RTYPE_STATION || wrole->type == PHL_RTYPE_P2P_GC) {
374 		psts = phl_role_notify(phl_info, wrole);
375 		if (psts != RTW_PHL_STATUS_SUCCESS) {
376 			PHL_ERR("%s role notify failed\n", __func__);
377 			goto _exit;
378 		}
379 	}
380 
381 	psts = phl_mr_info_upt(phl_info, wrole);
382 	if (psts != RTW_PHL_STATUS_SUCCESS) {
383 		PHL_ERR("%s mr info upt failed\n", __func__);
384 		goto _exit;
385 	}
386 
387 	psts = rtw_phl_mr_rx_filter(phl_info, wrole);
388 	if (psts != RTW_PHL_STATUS_SUCCESS) {
389 		PHL_ERR("%s set mr_rx_filter failed\n", __func__);
390 		goto _exit;
391 	}
392 
393 	psts = phl_mr_tsf_sync(phl_info, wrole, PHL_ROLE_MSTS_STA_CONN_END);
394 	if (psts != RTW_PHL_STATUS_SUCCESS) {
395 		PHL_ERR("%s set mr_tsf_sync failed\n", __func__);
396 		goto _exit;
397 	}
398 	#if 0
399 	psts = phl_mr_state_upt(phl_info, wrole);
400 	if (psts != RTW_PHL_STATUS_SUCCESS) {
401 		PHL_ERR("%s phl_mr_state_upt failed\n", __func__);
402 		goto _exit;
403 	}
404 	#endif
405 
406 	PHL_DUMP_MR_EX(phl_info);
407 _exit:
408 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "%s: psts(%d)\n",
409 		  __func__, psts);
410 	return psts;
411 }
412 
413 enum rtw_phl_status
_phl_mrc_module_disconnect_pre_hdlr(struct phl_info_t * phl_info,struct rtw_wifi_role_t * wrole)414 _phl_mrc_module_disconnect_pre_hdlr(struct phl_info_t *phl_info,
415 				struct rtw_wifi_role_t *wrole)
416 {
417 	enum rtw_phl_status psts = RTW_PHL_STATUS_SUCCESS;
418 
419 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "%s: wrole->id(%d)\n",
420 		  __func__, wrole->id);
421 
422 #ifdef CONFIG_PHL_P2PPS
423 	/* disable NoA for this role */
424 	phl_p2pps_noa_disable_all(phl_info, wrole);
425 	/* pasue buddy NoA */
426 	phl_p2pps_noa_all_role_pause(phl_info, wrole->hw_band);
427 #endif
428 
429 #ifdef CONFIG_MCC_SUPPORT
430 	/* disable MR coex mechanism(if runing) */
431 	psts = phl_mr_coex_disable(phl_info, wrole, wrole->hw_band,
432 					MR_COEX_TRIG_BY_DIS_LINKING);
433 	if (psts != RTW_PHL_STATUS_SUCCESS) {
434 		PHL_ERR("%s: MR coex disable fail\n", __func__);
435 		goto _exit;
436 	}
437 #endif
438 
439 _exit:
440 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "%s: psts(%d)\n",
441 		  __func__, psts);
442 	return psts;
443 }
444 
445 /* Same behaviour as rtw_phl_disconnect without cmd dispr */
446 enum rtw_phl_status
_phl_mrc_module_disconnect_hdlr(struct phl_info_t * phl_info,struct rtw_wifi_role_t * wrole)447 _phl_mrc_module_disconnect_hdlr(struct phl_info_t *phl_info,
448 				struct rtw_wifi_role_t *wrole)
449 {
450 	enum rtw_phl_status psts = RTW_PHL_STATUS_FAILURE;
451 #ifdef CONFIG_PHL_TDLS
452 	enum role_type rtype = PHL_RTYPE_STATION;
453 #endif
454 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "%s: wrole->id(%d)\n",
455 		  __func__, wrole->id);
456 #ifdef CONFIG_PHL_TDLS
457 	/* Disconnected with AP while there still exist linked TDLS peers */
458 	if (wrole->type == PHL_RTYPE_TDLS && wrole->mstate != MLME_LINKED) {
459 		psts = phl_wifi_role_change(phl_info, wrole, WR_CHG_TYPE, (u8*)&rtype);
460 		if (psts != RTW_PHL_STATUS_SUCCESS) {
461 			RTW_ERR("%s - change to phl role type = %d fail with error = %d\n", __func__, rtype, psts);
462 			goto _exit;
463 		}
464 	}
465 #endif
466 
467 	if (wrole->type == PHL_RTYPE_STATION || wrole->type == PHL_RTYPE_P2P_GC) {
468 		psts = phl_role_notify(phl_info, wrole);
469 		if (psts != RTW_PHL_STATUS_SUCCESS) {
470 			PHL_ERR("%s role notify failed\n", __func__);
471 			goto _exit;
472 		}
473 	}
474 
475 	psts = phl_mr_info_upt(phl_info, wrole);
476 	if (psts != RTW_PHL_STATUS_SUCCESS) {
477 		PHL_ERR("%s mr info upt failed\n", __func__);
478 		goto _exit;
479 	}
480 
481 	psts = rtw_phl_mr_rx_filter(phl_info, wrole);
482 	if (psts != RTW_PHL_STATUS_SUCCESS) {
483 		PHL_ERR("%s set mr_rx_filter failed\n", __func__);
484 		goto _exit;
485 	}
486 
487 	psts = phl_mr_tsf_sync(phl_info, wrole, PHL_ROLE_MSTS_STA_DIS_CONN);
488 	if (psts != RTW_PHL_STATUS_SUCCESS) {
489 		PHL_ERR("%s set mr_tsf_sync failed\n", __func__);
490 		goto _exit;
491 	}
492 
493 	rtw_hal_disconnect_notify(phl_info->hal, &wrole->chandef);
494 	PHL_DUMP_MR_EX(phl_info);
495 _exit:
496 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "%s: psts(%d)\n",
497 		  __func__, psts);
498 	return psts;
499 }
500 
501 enum rtw_phl_status
_phl_mrc_module_tsf_sync_done_hdlr(struct phl_info_t * phl_info,struct rtw_wifi_role_t * wrole)502 _phl_mrc_module_tsf_sync_done_hdlr(struct phl_info_t *phl_info,
503 				struct rtw_wifi_role_t *wrole)
504 {
505 	SET_STATUS_FLAG(wrole->status, WR_STATUS_TSF_SYNC);
506 	return phl_mr_state_upt(phl_info, wrole);
507 }
508 
509 enum rtw_phl_status
_phl_mrc_module_ap_start_pre_hdlr(struct phl_info_t * phl_info,struct rtw_wifi_role_t * wrole)510 _phl_mrc_module_ap_start_pre_hdlr(struct phl_info_t *phl_info,
511 				struct rtw_wifi_role_t *wrole)
512 {
513 	enum rtw_phl_status psts = RTW_PHL_STATUS_SUCCESS;
514 
515 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "%s: wrole->id(%d)\n",
516 		  __func__, wrole->id);
517 #ifdef CONFIG_PHL_P2PPS
518 	/* pasue all NoA */
519 	phl_p2pps_noa_all_role_pause(phl_info, wrole->hw_band);
520 #endif
521 #ifdef CONFIG_MCC_SUPPORT
522 	/* disable MR coex mechanism(if runing) */
523 	psts = phl_mr_coex_disable(phl_info, wrole, wrole->hw_band,
524 					MR_COEX_TRIG_BY_LINKING);
525 	if (psts != RTW_PHL_STATUS_SUCCESS) {
526 		PHL_ERR("%s: MR coex disable fail\n", __func__);
527 		goto _exit;
528 	}
529 #endif
530 
531 _exit:
532 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "%s: psts(%d)\n",
533 		  __func__, psts);
534 	return psts;
535 }
536 /* Same behaviour as rtw_phl_ap_started without cmd dispr */
537 enum rtw_phl_status
_phl_mrc_module_ap_started_hdlr(struct phl_info_t * phl_info,struct rtw_wifi_role_t * wrole)538 _phl_mrc_module_ap_started_hdlr(struct phl_info_t *phl_info,
539 				struct rtw_wifi_role_t *wrole)
540 {
541 	enum rtw_phl_status psts = RTW_PHL_STATUS_FAILURE;
542 
543 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "%s: wrole->id(%d)\n",
544 		  __func__, wrole->id);
545 	psts = phl_role_notify(phl_info, wrole);
546 	if (psts != RTW_PHL_STATUS_SUCCESS) {
547 		PHL_ERR("%s role notify failed\n", __func__);
548 		goto _exit;
549 	}
550 	psts = phl_mr_info_upt(phl_info, wrole);
551 	if (psts != RTW_PHL_STATUS_SUCCESS) {
552 		PHL_ERR("%s mr info upt failed\n", __func__);
553 		goto _exit;
554 	}
555 	psts = rtw_phl_mr_rx_filter(phl_info, wrole);
556 	if (psts != RTW_PHL_STATUS_SUCCESS) {
557 		PHL_ERR("%s set mr_rx_filter failed\n", __func__);
558 		goto _exit;
559 	}
560 
561 	psts = phl_mr_tsf_sync(phl_info, wrole, PHL_ROLE_MSTS_AP_START);
562 	if (psts != RTW_PHL_STATUS_SUCCESS) {
563 		PHL_ERR("%s set mr_tsf_sync failed\n", __func__);
564 		goto _exit;
565 	}
566 	psts = phl_mr_state_upt(phl_info, wrole);
567 	if (psts != RTW_PHL_STATUS_SUCCESS) {
568 		PHL_ERR("%s phl_mr_state_upt failed\n", __func__);
569 		goto _exit;
570 	}
571 
572 	PHL_DUMP_MR_EX(phl_info);
573 _exit:
574 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "%s: psts(%d)\n",
575 		  __func__, psts);
576 	return psts;
577 }
578 
579 enum rtw_phl_status
_phl_mrc_module_ap_stop_pre_hdlr(struct phl_info_t * phl_info,struct rtw_wifi_role_t * wrole)580 _phl_mrc_module_ap_stop_pre_hdlr(struct phl_info_t *phl_info,
581 				struct rtw_wifi_role_t *wrole)
582 {
583 	enum rtw_phl_status psts = RTW_PHL_STATUS_SUCCESS;
584 
585 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "%s: wrole->id(%d)\n",
586 		  __func__, wrole->id);
587 
588 #ifdef CONFIG_PHL_P2PPS
589 	/* disable NoA for this role */
590 	phl_p2pps_noa_disable_all(phl_info, wrole);
591 	/* pasue buddy NoA */
592 	phl_p2pps_noa_all_role_pause(phl_info, wrole->hw_band);
593 #endif
594 #ifdef CONFIG_MCC_SUPPORT
595 	/* disable MR coex mechanism(if runing) */
596 	psts = phl_mr_coex_disable(phl_info, wrole, wrole->hw_band,
597 					MR_COEX_TRIG_BY_DIS_LINKING);
598 	if (psts != RTW_PHL_STATUS_SUCCESS) {
599 		PHL_ERR("%s: MR coex disable fail\n", __func__);
600 		goto _exit;
601 	}
602 #endif
603 
604 _exit:
605 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "%s: psts(%d)\n",
606 		  __func__, psts);
607 	return psts;
608 }
609 
610 /* Same behaviour as rtw_phl_ap_stop without cmd dispr */
611 enum rtw_phl_status
_phl_mrc_module_ap_stop_hdlr(struct phl_info_t * phl_info,struct rtw_wifi_role_t * wrole)612 _phl_mrc_module_ap_stop_hdlr(struct phl_info_t *phl_info,
613 				struct rtw_wifi_role_t *wrole)
614 {
615 	enum rtw_phl_status psts = RTW_PHL_STATUS_FAILURE;
616 
617 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "%s: wrole->id(%d)\n",
618 		  __func__, wrole->id);
619 	wrole->mstate = MLME_NO_LINK;
620 	psts = phl_role_notify(phl_info, wrole);
621 	if (psts != RTW_PHL_STATUS_SUCCESS) {
622 		PHL_ERR("%s role notify failed\n", __func__);
623 		goto _exit;
624 	}
625 
626 	psts = phl_mr_info_upt(phl_info, wrole);
627 	if (psts != RTW_PHL_STATUS_SUCCESS) {
628 		PHL_ERR("%s mr info upt failed\n", __func__);
629 		goto _exit;
630 	}
631 	psts = rtw_phl_mr_rx_filter(phl_info, wrole);
632 	if (psts != RTW_PHL_STATUS_SUCCESS) {
633 		PHL_ERR("%s set mr_rx_filter failed\n", __func__);
634 		goto _exit;
635 	}
636 
637 	psts = phl_mr_tsf_sync(phl_info, wrole, PHL_ROLE_MSTS_AP_STOP);
638 	if (psts != RTW_PHL_STATUS_SUCCESS) {
639 		PHL_ERR("%s set mr_tsf_sync failed\n", __func__);
640 		goto _exit;
641 	}
642 
643 	rtw_hal_disconnect_notify(phl_info->hal, &wrole->chandef);
644 
645 	PHL_DUMP_MR_EX(phl_info);
646 _exit:
647 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "%s: psts(%d)\n",
648 		  __func__, psts);
649 	return psts;
650 }
651 
652 enum phl_mdl_ret_code
_phl_mrc_module_swch_start_hdlr(void * dispr,void * priv,struct phl_msg * msg)653 _phl_mrc_module_swch_start_hdlr(void *dispr,
654 				void *priv,
655 				struct phl_msg *msg)
656 {
657 	enum phl_mdl_ret_code ret = MDL_RET_FAIL;
658 	struct phl_info_t *phl_info = (struct phl_info_t *)priv;
659 	struct phl_module_op_info op_info = {0};
660 	struct rtw_wifi_role_t *role = NULL;
661 	struct rtw_chan_def chandef = {0};
662 	struct rtw_phl_com_t *phl_com = phl_info->phl_com;
663 	struct mr_ctl_t *mr_ctl = phlcom_to_mr_ctrl(phl_com);
664 	u8 module_id = MSG_MDL_ID_FIELD(msg->msg_id);
665 #ifdef RTW_WKARD_MRC_ISSUE_NULL_WITH_SCAN_OPS
666 	struct rtw_phl_scan_param* scan_param = NULL;
667 	u8 (*scan_issue_null_data)(void *, u8, bool) = NULL;
668 #endif
669 	u8 idx = 0xff;
670 
671 	phl_dispr_get_idx(dispr, &idx);
672 	/*
673 	* Handle mr offchan before switching channel when
674 	* STA connect & AP start.
675 	*/
676 	if((module_id != PHL_FG_MDL_CONNECT) &&
677 	   (module_id != PHL_FG_MDL_AP_START) &&
678 	   (module_id != PHL_FG_MDL_SCAN)){
679 		PHL_TRACE(COMP_PHL_DBG, _PHL_INFO_,
680 		"%s: not connect/apstart/scan\n", __FUNCTION__);
681 		ret = MDL_RET_IGNORE;
682 		goto _exit;
683 	}
684 	PHL_TRACE(COMP_PHL_DBG, _PHL_INFO_,
685 		"%s: MSG_EVT_SWCH_START\n", __FUNCTION__);
686 	op_info.op_code = FG_REQ_OP_GET_ROLE;
687 
688 	if(phl_disp_eng_query_cur_cmd_info(phl_info, idx, &op_info)
689 		!= RTW_PHL_STATUS_SUCCESS){
690 		PHL_TRACE(COMP_PHL_DBG, _PHL_WARNING_,
691 				"Query wifi role fail!\n");
692 		goto _exit;
693 	}
694 	role = (struct rtw_wifi_role_t *)op_info.outbuf;
695 
696 	if(role == NULL){
697 		PHL_TRACE(COMP_PHL_DBG, _PHL_WARNING_,
698 			"%s: role is NULL\n", __FUNCTION__);
699 		goto _exit;
700 	}
701 
702 	/*
703 	* If we are already on STA/AP channel,
704 	* offch is unnecessary.
705 	*/
706 	if((module_id == PHL_FG_MDL_CONNECT) ||
707 	   (module_id == PHL_FG_MDL_AP_START)){
708 	   	#ifdef CONFIG_MR_SUPPORT
709 		chandef = mr_ctl->hal_com->band[role->hw_band].cur_chandef;
710 
711 		if(role->chandef.chan == chandef.chan){
712 			ret = MDL_RET_SUCCESS;
713 			goto _exit;
714 		}
715 		#else
716 		ret = MDL_RET_SUCCESS;
717 		goto _exit;
718 		#endif
719 	}
720 #ifdef RTW_WKARD_MRC_ISSUE_NULL_WITH_SCAN_OPS
721 	if(module_id == PHL_FG_MDL_SCAN)
722 		op_info.op_code = FG_REQ_OP_GET_SCAN_PARAM;
723 	else
724 		op_info.op_code = FG_REQ_OP_GET_ISSUE_NULL_OPS;
725 
726 	if(phl_disp_eng_query_cur_cmd_info(phl_info, idx, &op_info)
727 		!= RTW_PHL_STATUS_SUCCESS){
728 		PHL_TRACE(COMP_PHL_DBG, _PHL_WARNING_,
729 			  "Query fail! (opcode %d)\n", op_info.op_code);
730 		goto _exit;
731 	}
732 
733 	if(op_info.outbuf == NULL){
734 		PHL_TRACE(COMP_PHL_DBG, _PHL_WARNING_,
735 			  "%s: op_info.outbuf is NULL (opcode %d)\n",
736 			  __FUNCTION__, op_info.op_code);
737 		goto _exit;
738 	}
739 	if(module_id == PHL_FG_MDL_SCAN){
740 		scan_param = (struct rtw_phl_scan_param*)op_info.outbuf;
741 		scan_issue_null_data = scan_param->ops->scan_issue_null_data;
742 	}
743 	else{
744 		scan_issue_null_data = (u8 (*)(void *, u8, bool))op_info.outbuf;
745 	}
746 
747 	phl_mr_offch_hdl(phl_info,
748 			  role,
749 			  true,
750 			  phl_com->drv_priv,
751 			  scan_issue_null_data);
752 #endif
753 	ret = MDL_RET_SUCCESS;
754 _exit:
755 	return ret;
756 }
757 
758 enum phl_mdl_ret_code
_phl_mrc_module_swch_done_hdlr(void * dispr,void * priv,struct phl_msg * msg)759 _phl_mrc_module_swch_done_hdlr(void *dispr,
760 			       void *priv,
761 			       struct phl_msg *msg)
762 {
763 	enum phl_mdl_ret_code ret = MDL_RET_FAIL;
764 	struct phl_info_t *phl_info = (struct phl_info_t *)priv;
765 	struct rtw_phl_com_t *phl_com = phl_info->phl_com;
766 	struct phl_module_op_info op_info = {0};
767 	struct rtw_wifi_role_t *role = NULL;
768 	u8 module_id = MSG_MDL_ID_FIELD(msg->msg_id);
769 	struct phl_scan_channel scan_ch = {0};
770 #ifdef RTW_WKARD_MRC_ISSUE_NULL_WITH_SCAN_OPS
771 	struct rtw_phl_scan_param* scan_param = NULL;
772 #endif
773 	u8 idx = 0xff;
774 
775 	phl_dispr_get_idx(dispr, &idx);
776 	/*
777 	* Handle mr offchan after switching channel to op channel
778 	*/
779 	if(module_id != PHL_FG_MDL_SCAN){
780 		ret = MDL_RET_IGNORE;
781 		goto _exit;
782 	}
783 	PHL_TRACE(COMP_PHL_DBG, _PHL_INFO_,
784 		"%s: MSG_EVT_SWCH_DONE\n", __FUNCTION__);
785 	scan_ch = *(struct phl_scan_channel *)(msg->inbuf);
786 
787 	/* Issue null 0 and resume beacon when BACKOP during scanning */
788 	if(scan_ch.scan_mode != BACKOP_MODE){
789 		ret = MDL_RET_SUCCESS;
790 		goto _exit;
791 	}
792 
793 	role = (struct rtw_wifi_role_t *)msg->rsvd[0];
794 #ifdef RTW_WKARD_MRC_ISSUE_NULL_WITH_SCAN_OPS
795 	op_info.op_code = FG_REQ_OP_GET_SCAN_PARAM;
796 
797 	if(phl_disp_eng_query_cur_cmd_info(phl_info, idx, &op_info)
798 		!= RTW_PHL_STATUS_SUCCESS){
799 		PHL_TRACE(COMP_PHL_DBG, _PHL_WARNING_,
800 			  "Query scan_param fail!\n");
801 		goto _exit;
802 	}
803 	scan_param = (struct rtw_phl_scan_param*)op_info.outbuf;
804 
805 	if(op_info.outbuf == NULL){
806 		PHL_TRACE(COMP_PHL_DBG, _PHL_WARNING_,
807 			  "%s: scan_param is NULL\n", __FUNCTION__);
808 		goto _exit;
809 	}
810 
811 	phl_mr_offch_hdl(phl_info,
812 			 role,
813 			 false,
814 			 phl_com->drv_priv,
815 			 scan_param->ops->scan_issue_null_data);
816 #endif
817 	ret = MDL_RET_SUCCESS;
818 _exit:
819 	return ret;
820 }
821 
822 static enum rtw_phl_status
_mrc_module_chg_op_chdef_start_pre_hdlr(u8 * param)823 _mrc_module_chg_op_chdef_start_pre_hdlr(u8 *param)
824 {
825 	enum rtw_phl_status psts = RTW_PHL_STATUS_FAILURE;
826 	struct chg_opch_param *ch_param = (struct chg_opch_param *)param;
827 	struct rtw_wifi_role_t *wrole = ch_param->wrole;
828 	struct phl_info_t *phl = wrole->phl_com->phl_priv;
829 
830 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "%s: wrole->id(%d)\n",
831 		  __func__, wrole->id);
832 #ifdef CONFIG_MCC_SUPPORT
833 	/* disable MR coex mechanism(if runing) */
834 	psts = phl_mr_coex_disable(phl, wrole, wrole->hw_band,
835 					MR_COEX_TRIG_BY_CHG_OP_CHDEF);
836 	if (psts != RTW_PHL_STATUS_SUCCESS) {
837 		PHL_ERR("%s: MR coex disable fail\n", __func__);
838 	}
839 #endif
840 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "%s: psts(%d)\n",
841 		  __func__, psts);
842 	return psts;
843 }
844 
845 static enum rtw_phl_status
_mrc_module_chg_op_chdef_end_pre_hdlr(u8 * param)846 _mrc_module_chg_op_chdef_end_pre_hdlr(u8 *param)
847 {
848 	enum rtw_phl_status psts = RTW_PHL_STATUS_FAILURE;
849 	struct chg_opch_param *ch_param = (struct chg_opch_param *)param;
850 	struct rtw_wifi_role_t *wrole = ch_param->wrole;
851 	struct phl_info_t *phl = wrole->phl_com->phl_priv;
852 	struct rtw_phl_evt_ops *ops = ops = &phl->phl_com->evt_ops;
853 	u8 (*core_issue_null)(void *, u8, bool) = NULL;
854 
855 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "%s: wrole->id(%d)\n",
856 		  __func__, wrole->id);
857 	/* Handle mr offchan after switching channel to new op channel */
858 	/* If the new pri-ch is as same as ori pri-ch, offch is unnecessary. */
859 	if(ch_param->new_chdef.chan == ch_param->ori_chdef.chan) {
860 		psts = RTW_PHL_STATUS_SUCCESS;
861 		goto exit;
862 	}
863 	if (ops->issue_null_data) {
864 		core_issue_null = ops->issue_null_data;
865 	} else {
866 		PHL_TRACE(COMP_PHL_DBG, _PHL_ERR_, "%s: Ops issue_null_data is NULL\n",
867 			__func__);
868 	}
869 	if (RTW_PHL_STATUS_SUCCESS != phl_mr_offch_hdl(phl, wrole, false,
870 				phl->phl_com->drv_priv, core_issue_null)) {
871 		PHL_TRACE(COMP_PHL_DBG, _PHL_WARNING_, "%s: Fail to offch\n",
872 			__func__);
873 		goto exit;
874 	}
875 	psts = RTW_PHL_STATUS_SUCCESS;
876 exit:
877 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "%s: psts(%d)\n",
878 		  __func__, psts);
879 	return psts;
880 }
881 
882 static enum phl_mdl_ret_code
_mrc_module_chg_op_chdef_start_hdlr(void * dispr,void * priv,struct phl_msg * msg)883 _mrc_module_chg_op_chdef_start_hdlr(void *dispr, void *priv,
884 			 struct phl_msg *msg)
885 {
886 	enum phl_mdl_ret_code ret = MDL_RET_FAIL;
887 	struct phl_info_t *phl = (struct phl_info_t *)priv;
888 	struct rtw_phl_evt_ops *ops = &phl->phl_com->evt_ops;
889 	struct chg_opch_param *ch_param = NULL;
890 	struct rtw_wifi_role_t *wrole = NULL;
891 	u8 (*core_issue_null)(void *, u8, bool) = NULL;
892 	u8 *cmd = NULL;
893 	u32 cmd_len;
894 
895 	if (MSG_MDL_ID_FIELD(msg->msg_id) != PHL_MDL_GENERAL) {
896 		ret = MDL_RET_IGNORE;
897 		goto exit;
898 	}
899 	if (phl_cmd_get_cur_cmdinfo(phl, msg->band_idx, msg, &cmd, &cmd_len)
900 						!= RTW_PHL_STATUS_SUCCESS) {
901 		PHL_TRACE(COMP_PHL_DBG, _PHL_ERR_, "%s: Fail to get cmd info \n",
902 			  __func__);
903 		goto exit;
904 	}
905 	ch_param = (struct chg_opch_param *)cmd;
906 	wrole = ch_param->wrole;
907 	PHL_TRACE(COMP_PHL_DBG, _PHL_INFO_, "%s: wrole->id(%d)\n",
908 		  __func__, wrole->id);
909 	/* Handle mr offchan before switching channel */
910 	/* If the new pri-ch is as same as old pri-ch, offch is unnecessary. */
911 	if (ch_param->new_chdef.chan == ch_param->ori_chdef.chan) {
912 		ret = MDL_RET_SUCCESS;
913 		goto exit;
914 	}
915 	if (ops->issue_null_data) {
916 		core_issue_null = ops->issue_null_data;
917 	} else {
918 		PHL_TRACE(COMP_PHL_DBG, _PHL_ERR_, "%s: Ops issue_null_data is NULL\n",
919 			__func__);
920 	}
921 	if (RTW_PHL_STATUS_SUCCESS != phl_mr_offch_hdl(phl, wrole, true,
922 				phl->phl_com->drv_priv, core_issue_null)) {
923 		PHL_TRACE(COMP_PHL_DBG, _PHL_WARNING_, "%s: Fail to offch\n",
924 			__func__);
925 		goto exit;
926 	}
927 	ret = MDL_RET_SUCCESS;
928 exit:
929 	return ret;
930 }
931 
932 enum phl_mdl_ret_code
_mrc_module_chg_op_chdef_end_hdlr(void * dispr,void * priv,struct phl_msg * msg)933 _mrc_module_chg_op_chdef_end_hdlr(void *dispr, void *priv,
934 				struct phl_msg *msg)
935 {
936 	enum phl_mdl_ret_code ret = MDL_RET_FAIL;
937 	struct phl_info_t *phl = (struct phl_info_t *)priv;
938 	struct chg_opch_param *ch_param = NULL;
939 	struct rtw_wifi_role_t *wrole = NULL;
940 	u8 *cmd = NULL;
941 	u32 cmd_len;
942 
943 	if (MSG_MDL_ID_FIELD(msg->msg_id) != PHL_MDL_GENERAL) {
944 		ret = MDL_RET_IGNORE;
945 		goto exit;
946 	}
947 	if (phl_cmd_get_cur_cmdinfo(phl, msg->band_idx, msg, &cmd, &cmd_len)
948 						!= RTW_PHL_STATUS_SUCCESS) {
949 		PHL_TRACE(COMP_PHL_DBG, _PHL_ERR_, "%s: Fail to get cmd info \n",
950 			  __func__);
951 		goto exit;
952 	}
953 	ch_param = (struct chg_opch_param *)cmd;
954 	wrole = ch_param->wrole;
955 	PHL_TRACE(COMP_PHL_DBG, _PHL_INFO_, "%s: wrole->id(%d)\n",
956 		  __func__, wrole->id);
957 	if (RTW_PHL_STATUS_SUCCESS != phl_role_notify(phl, wrole)) {
958 		PHL_ERR("%s role notify failed\n", __func__);
959 		goto exit;
960 	}
961 #ifdef CONFIG_MCC_SUPPORT
962 	/* Enable MR coex mechanism(if needed) */
963 	if (RTW_PHL_STATUS_SUCCESS != phl_mr_coex_handle(phl, wrole, 0,
964 				wrole->hw_band, MR_COEX_TRIG_BY_CHG_OP_CHDEF)) {
965 		PHL_ERR("%s: MR coex handle fail\n", __func__);
966 		goto exit;
967 	}
968 #endif
969 	ret = MDL_RET_SUCCESS;
970 exit:
971 	PHL_INFO("%s: ret(%d)\n", __func__, ret);
972 	return ret;
973 }
974 
975 static enum phl_mdl_ret_code
_mrc_module_msg_pre_hdlr(void * dispr,void * priv,struct phl_msg * msg)976 _mrc_module_msg_pre_hdlr(void *dispr, void *priv, struct phl_msg *msg)
977 {
978 	enum phl_mdl_ret_code ret = MDL_RET_FAIL;
979 	struct phl_info_t *phl = (struct phl_info_t *)priv;
980 	u8 *cmd = NULL;
981 	u32 cmd_len;
982 
983 	switch (MSG_EVT_ID_FIELD(msg->msg_id)) {
984 	case MSG_EVT_CHG_OP_CH_DEF_START:
985 		if (MSG_MDL_ID_FIELD(msg->msg_id) != PHL_MDL_GENERAL) {
986 			ret = MDL_RET_IGNORE;
987 			break;
988 		}
989 		PHL_TRACE(COMP_PHL_DBG, _PHL_INFO_, "%s: MSG_EVT_CHG_OP_CH_DEF_START\n",
990 			__FUNCTION__);
991 		if (RTW_PHL_STATUS_SUCCESS != phl_cmd_get_cur_cmdinfo(phl,
992 					msg->band_idx, msg, &cmd, &cmd_len)) {
993 			PHL_TRACE(COMP_PHL_DBG, _PHL_ERR_, "%s: Fail to get cmd info \n",
994 				  __func__);
995 			break;
996 		}
997 		if (RTW_PHL_STATUS_SUCCESS !=
998 			_mrc_module_chg_op_chdef_start_pre_hdlr(cmd)) {
999 			break;
1000 		}
1001 		ret = MDL_RET_SUCCESS;
1002 		break;
1003 	case MSG_EVT_CHG_OP_CH_DEF_END:
1004 		if (MSG_MDL_ID_FIELD(msg->msg_id) != PHL_MDL_GENERAL) {
1005 			ret = MDL_RET_IGNORE;
1006 			break;
1007 		}
1008 		PHL_TRACE(COMP_PHL_DBG, _PHL_INFO_, "%s: MSG_EVT_CHG_OP_CH_DEF_END\n",
1009 			__FUNCTION__);
1010 		if (RTW_PHL_STATUS_SUCCESS != phl_cmd_get_cur_cmdinfo(phl,
1011 					msg->band_idx, msg, &cmd, &cmd_len)) {
1012 			PHL_TRACE(COMP_PHL_DBG, _PHL_ERR_, "%s: Fail to get cmd info \n",
1013 				  __func__);
1014 			break;
1015 		}
1016 		if (RTW_PHL_STATUS_SUCCESS !=
1017 			_mrc_module_chg_op_chdef_end_pre_hdlr(cmd)) {
1018 			break;
1019 		}
1020 		ret = MDL_RET_SUCCESS;
1021 		break;
1022 	default:
1023 		PHL_TRACE(COMP_PHL_DBG, _PHL_DEBUG_, "%s: MDL ID(%d), Event ID(%d), Not handle event in pre-phase\n",
1024 			__FUNCTION__, MSG_MDL_ID_FIELD(msg->msg_id),
1025 			MSG_EVT_ID_FIELD(msg->msg_id));
1026 		ret = MDL_RET_IGNORE;
1027 		break;
1028 	}
1029 	return ret;
1030 }
1031 
1032 static enum phl_mdl_ret_code
_mrc_module_msg_post_hdl(void * dispr,void * priv,struct phl_msg * msg)1033 _mrc_module_msg_post_hdl(void *dispr, void *priv, struct phl_msg *msg)
1034 {
1035 	enum phl_mdl_ret_code ret = MDL_RET_FAIL;
1036 	struct phl_info_t *phl_info = (struct phl_info_t *)priv;
1037 	struct phl_module_op_info op_info = {0};
1038 	struct rtw_wifi_role_t *role = NULL;
1039 	struct rtw_chan_def chandef = {0};
1040 	struct rtw_phl_com_t *phl_com = phl_info->phl_com;
1041 #ifdef RTW_WKARD_MRC_ISSUE_NULL_WITH_SCAN_OPS
1042 	struct rtw_phl_scan_param* scan_param = NULL;
1043 	u8 (*scan_issue_null_data)(void *, u8, bool) = NULL;
1044 #endif
1045 	u8 idx = 0xff;
1046 
1047 	phl_dispr_get_idx(dispr, &idx);
1048 	switch (MSG_EVT_ID_FIELD(msg->msg_id)) {
1049 	case MSG_EVT_CHG_OP_CH_DEF_START:
1050 		PHL_TRACE(COMP_PHL_DBG, _PHL_INFO_,
1051 			  "%s: MSG_EVT_CHG_OP_CH_DEF_START\n", __FUNCTION__);
1052 		ret = _mrc_module_chg_op_chdef_start_hdlr(dispr, priv, msg);
1053 		break;
1054 	case MSG_EVT_CHG_OP_CH_DEF_END:
1055 		PHL_TRACE(COMP_PHL_DBG, _PHL_INFO_,
1056 			  "%s: MSG_EVT_CHG_OP_CH_DEF_END\n", __FUNCTION__);
1057 		ret = _mrc_module_chg_op_chdef_end_hdlr(dispr, priv, msg);
1058 		break;
1059 	case MSG_EVT_SWCH_START:
1060 	ret = _phl_mrc_module_swch_start_hdlr(dispr, priv, msg);
1061 		break;
1062 	case MSG_EVT_SWCH_DONE:
1063 	ret = _phl_mrc_module_swch_done_hdlr(dispr, priv, msg);
1064 		break;
1065 	case MSG_EVT_TSF_SYNC_DONE:
1066 		if (MSG_MDL_ID_FIELD(msg->msg_id) != PHL_MDL_MRC) {
1067 			return MDL_RET_IGNORE;
1068 		}
1069 
1070 		/*
1071 		 * MR decides to call mcc enable or not
1072 		 */
1073 		PHL_TRACE(COMP_PHL_DBG, _PHL_INFO_,
1074 			  "%s: MSG_EVT_TSF_SYNC_DONE\n", __FUNCTION__);
1075 		role = (struct rtw_wifi_role_t *)msg->inbuf;
1076 		if (role == NULL) {
1077 			PHL_TRACE(COMP_PHL_DBG, _PHL_WARNING_,
1078 				  "%s: role is NULL\n", __FUNCTION__);
1079 			break;
1080 		}
1081 		if (_phl_mrc_module_tsf_sync_done_hdlr(phl_info, role) != RTW_PHL_STATUS_SUCCESS) {
1082 			PHL_TRACE(COMP_PHL_DBG, _PHL_WARNING_,
1083 				  "phl_mr_state_upt failed\n");
1084 			break;
1085 		}
1086 		ret = MDL_RET_SUCCESS;
1087 		break;
1088 	case MSG_EVT_TDLS_SYNC:
1089 		if (MSG_MDL_ID_FIELD(msg->msg_id) != PHL_MDL_MRC) {
1090 			return MDL_RET_IGNORE;
1091 		}
1092 
1093 		/*
1094 		 * MR decides to call mcc enable or not
1095 		 */
1096 		PHL_TRACE(COMP_PHL_DBG, _PHL_INFO_,
1097 			  "%s: MSG_EVT_TDLS_SYNC\n", __FUNCTION__);
1098 
1099 		role = (struct rtw_wifi_role_t *)msg->inbuf;
1100 
1101 		if (role == NULL) {
1102 			PHL_TRACE(COMP_PHL_DBG, _PHL_WARNING_,
1103 				  "%s: role is NULL\n", __FUNCTION__);
1104 			break;
1105 		}
1106 
1107 		if (phl_mr_info_upt(phl_info, role) != RTW_PHL_STATUS_SUCCESS) {
1108 			PHL_TRACE(COMP_PHL_DBG, _PHL_WARNING_,
1109 				  "phl_mr_info_upt failed\n");
1110 			break;
1111 		}
1112 		ret = MDL_RET_SUCCESS;
1113 		break;
1114 	case MSG_EVT_TX_RESUME:
1115 		if (MSG_MDL_ID_FIELD(msg->msg_id) != PHL_MDL_MRC) {
1116 			return MDL_RET_IGNORE;
1117 		}
1118 
1119 		/*
1120 		 * MR resume the tx of the role in remain chanctx
1121 		 */
1122 		PHL_TRACE(COMP_PHL_DBG, _PHL_INFO_,
1123 			  "%s:MSG_EVT_TX_RESUME\n", __FUNCTION__);
1124 		role = (struct rtw_wifi_role_t *)msg->rsvd[0];
1125 		if (role == NULL) {
1126 			PHL_TRACE(COMP_PHL_DBG, _PHL_WARNING_,
1127 				  "%s: role is NULL\n", __FUNCTION__);
1128 			break;
1129 		}
1130 #ifdef RTW_WKARD_MRC_ISSUE_NULL_WITH_SCAN_OPS
1131 		scan_issue_null_data = (u8 (*)(void *, u8, bool))msg->rsvd[1];
1132 		phl_mr_offch_hdl(phl_info,
1133 				 role,
1134 				 false,
1135 				 phl_com->drv_priv,
1136 				 scan_issue_null_data);
1137 #endif
1138 		ret = MDL_RET_SUCCESS;
1139 		break;
1140 	case MSG_EVT_CONNECT_START:
1141 #ifdef CONFIG_STA_CMD_DISPR
1142 		if (MSG_MDL_ID_FIELD(msg->msg_id) != PHL_FG_MDL_CONNECT) {
1143 			return MDL_RET_IGNORE;
1144 		}
1145 		PHL_TRACE(COMP_PHL_DBG, _PHL_INFO_,
1146 			  "%s: MSG_EVT_CONNECT_START\n", __FUNCTION__);
1147 
1148 		op_info.op_code = FG_REQ_OP_GET_ROLE;
1149 		if (phl_disp_eng_query_cur_cmd_info(phl_info, idx, &op_info)
1150 			!= RTW_PHL_STATUS_SUCCESS) {
1151 			PHL_TRACE(COMP_PHL_DBG, _PHL_WARNING_,
1152 				  "Query wifi role fail!\n");
1153 			break;
1154 		}
1155 		role = (struct rtw_wifi_role_t *)op_info.outbuf;
1156 		if (role == NULL) {
1157 			PHL_TRACE(COMP_PHL_DBG, _PHL_WARNING_,
1158 				  "%s: role is NULL\n", __FUNCTION__);
1159 			break;
1160 
1161 		}
1162 		if (_phl_mrc_module_connect_start_hdlr(phl_info, role) !=
1163 			RTW_PHL_STATUS_SUCCESS) {
1164 			break;
1165 		}
1166 		rtw_hal_notification(phl_info->hal, MSG_EVT_ID_FIELD(msg->msg_id),
1167 				     role->hw_band);
1168 #endif
1169 		ret = MDL_RET_SUCCESS;
1170 		break;
1171 	case MSG_EVT_CONNECT_END:
1172 #ifdef CONFIG_STA_CMD_DISPR
1173 		if (MSG_MDL_ID_FIELD(msg->msg_id) != PHL_FG_MDL_CONNECT) {
1174 			return MDL_RET_IGNORE;
1175 		}
1176 		PHL_TRACE(COMP_PHL_DBG, _PHL_INFO_,
1177 			  "%s: MSG_EVT_CONNECT_END\n", __FUNCTION__);
1178 		op_info.op_code = FG_REQ_OP_GET_ROLE;
1179 		if (phl_disp_eng_query_cur_cmd_info(phl_info, idx, &op_info)
1180 			!= RTW_PHL_STATUS_SUCCESS) {
1181 			PHL_TRACE(COMP_PHL_DBG, _PHL_WARNING_,
1182 				  "Query wifi role fail!\n");
1183 			break;
1184 		}
1185 		role = (struct rtw_wifi_role_t *)op_info.outbuf;
1186 		if (role == NULL) {
1187 			PHL_TRACE(COMP_PHL_DBG, _PHL_WARNING_,
1188 				  "%s: role is NULL\n", __FUNCTION__);
1189 			break;
1190 		}
1191 		if (_phl_mrc_module_connect_end_hdlr(phl_info, role) !=
1192 			RTW_PHL_STATUS_SUCCESS) {
1193 			break;
1194 		}
1195 		rtw_hal_notification(phl_info->hal, MSG_EVT_ID_FIELD(msg->msg_id),
1196 				     role->hw_band);
1197 #endif
1198 		ret = MDL_RET_SUCCESS;
1199 		break;
1200 	case MSG_EVT_DISCONNECT_PREPARE:
1201 #ifdef CONFIG_STA_CMD_DISPR
1202 		if (MSG_MDL_ID_FIELD(msg->msg_id) != PHL_FG_MDL_CONNECT &&
1203 		    MSG_MDL_ID_FIELD(msg->msg_id) != PHL_FG_MDL_DISCONNECT) {
1204 			return MDL_RET_IGNORE;
1205 		}
1206 		PHL_TRACE(COMP_PHL_DBG, _PHL_INFO_,
1207 			  "%s: MSG_EVT_DISCONNECT_PREPARE\n", __FUNCTION__);
1208 		role = (struct rtw_wifi_role_t *)msg->rsvd[0];
1209 		if (role == NULL) {
1210 			PHL_TRACE(COMP_PHL_DBG, _PHL_WARNING_,
1211 				  "%s: role is NULL\n", __FUNCTION__);
1212 			break;
1213 		}
1214 		if (_phl_mrc_module_disconnect_pre_hdlr(phl_info, role) !=
1215 			RTW_PHL_STATUS_SUCCESS) {
1216 			break;
1217 		}
1218 #ifdef CONFIG_TWT
1219 		rtw_phl_twt_disable_all_twt_by_role(phl_info, role);
1220 #endif
1221 #endif
1222 		ret = MDL_RET_SUCCESS;
1223 		break;
1224 	case MSG_EVT_DISCONNECT:
1225 #ifdef CONFIG_STA_CMD_DISPR
1226 		if (MSG_MDL_ID_FIELD(msg->msg_id) != PHL_FG_MDL_CONNECT &&
1227 		   MSG_MDL_ID_FIELD(msg->msg_id) != PHL_FG_MDL_DISCONNECT) {
1228 			return MDL_RET_IGNORE;
1229 		}
1230 		PHL_TRACE(COMP_PHL_DBG, _PHL_INFO_,
1231 			  "%s: MSG_EVT_DISCONNECT\n", __FUNCTION__);
1232 
1233 		role = (struct rtw_wifi_role_t *)msg->rsvd[0];
1234 		if (role == NULL) {
1235 			PHL_TRACE(COMP_PHL_DBG, _PHL_WARNING_,
1236 				  "%s: role is NULL\n", __FUNCTION__);
1237 			break;
1238 		}
1239 		if (_phl_mrc_module_disconnect_hdlr(phl_info, role) !=
1240 			RTW_PHL_STATUS_SUCCESS) {
1241 			break;
1242 		}
1243 #endif
1244 		ret = MDL_RET_SUCCESS;
1245 		break;
1246 	case MSG_EVT_AP_START_PREPARE:
1247 #ifdef CONFIG_AP_CMD_DISPR
1248 		if (MSG_MDL_ID_FIELD(msg->msg_id) != PHL_FG_MDL_AP_START) {
1249 			return MDL_RET_IGNORE;
1250 		}
1251 		PHL_TRACE(COMP_PHL_DBG, _PHL_INFO_,
1252 			  "%s: MSG_EVT_AP_START_PREPARE\n", __FUNCTION__);
1253 		op_info.op_code = FG_REQ_OP_GET_ROLE;
1254 		if (phl_disp_eng_query_cur_cmd_info(phl_info, idx, &op_info)
1255 			!= RTW_PHL_STATUS_SUCCESS) {
1256 			PHL_TRACE(COMP_PHL_DBG, _PHL_WARNING_,
1257 				  "Query wifi role fail!\n");
1258 			break;
1259 		}
1260 		role = (struct rtw_wifi_role_t *)op_info.outbuf;
1261 		if (role == NULL){
1262 			PHL_TRACE(COMP_PHL_DBG, _PHL_WARNING_,
1263 				  "%s: role is NULL\n", __FUNCTION__);
1264 			break;
1265 		}
1266 		if (_phl_mrc_module_ap_start_pre_hdlr(phl_info, role) !=
1267 			RTW_PHL_STATUS_SUCCESS) {
1268 			break;
1269 		}
1270 #endif
1271 		ret = MDL_RET_SUCCESS;
1272 		break;
1273 	case MSG_EVT_AP_START:
1274 #ifdef CONFIG_AP_CMD_DISPR
1275 		if (MSG_MDL_ID_FIELD(msg->msg_id) != PHL_FG_MDL_AP_START) {
1276 			return MDL_RET_IGNORE;
1277 		}
1278 		PHL_TRACE(COMP_PHL_DBG, _PHL_INFO_,
1279 			  "%s: MSG_EVT_AP_START\n", __FUNCTION__);
1280 		op_info.op_code = FG_REQ_OP_GET_ROLE;
1281 		if (phl_disp_eng_query_cur_cmd_info(phl_info, idx, &op_info)
1282 			!= RTW_PHL_STATUS_SUCCESS) {
1283 			PHL_TRACE(COMP_PHL_DBG, _PHL_WARNING_,
1284 				  "Query wifi role fail!\n");
1285 			break;
1286 		}
1287 		role = (struct rtw_wifi_role_t *)op_info.outbuf;
1288 		if (role == NULL) {
1289 			PHL_TRACE(COMP_PHL_DBG, _PHL_WARNING_,
1290 				  "%s: role is NULL\n", __FUNCTION__);
1291 			break;
1292 		}
1293 		if (_phl_mrc_module_ap_started_hdlr(phl_info, role) !=
1294 			RTW_PHL_STATUS_SUCCESS) {
1295 			break;
1296 		}
1297 #endif
1298 		ret = MDL_RET_SUCCESS;
1299 		break;
1300 	case MSG_EVT_AP_START_END:
1301 #ifdef CONFIG_AP_CMD_DISPR
1302 		if (MSG_MDL_ID_FIELD(msg->msg_id) != PHL_FG_MDL_AP_START) {
1303 			return MDL_RET_IGNORE;
1304 		}
1305 		PHL_TRACE(COMP_PHL_DBG, _PHL_INFO_,
1306 			  "%s: MSG_EVT_AP_START_END\n", __FUNCTION__);
1307 
1308 		role = (struct rtw_wifi_role_t *)msg->rsvd[0];
1309 		if (role == NULL) {
1310 			PHL_TRACE(COMP_PHL_DBG, _PHL_WARNING_,
1311 				  "%s: role is NULL\n", __FUNCTION__);
1312 			break;
1313 		}
1314 		if (msg->inbuf == NULL) {
1315 			PHL_TRACE(COMP_PHL_DBG, _PHL_WARNING_,
1316 				  "%s:AP start status info not found!\n",
1317 				  __FUNCTION__);
1318 			ret = MDL_RET_FAIL;
1319 			break;
1320 		}
1321 		if (*(msg->inbuf) != RTW_PHL_STATUS_SUCCESS) {
1322 			if (_phl_mrc_module_ap_stop_hdlr(phl_info, role)
1323 			   != RTW_PHL_STATUS_SUCCESS) {
1324 				break;
1325 			}
1326 		}
1327 #endif
1328 		ret = MDL_RET_SUCCESS;
1329 		break;
1330 	case MSG_EVT_AP_STOP_PREPARE:
1331 #ifdef CONFIG_AP_CMD_DISPR
1332 		if (MSG_MDL_ID_FIELD(msg->msg_id) != PHL_FG_MDL_AP_STOP) {
1333 			return MDL_RET_IGNORE;
1334 		}
1335 		PHL_TRACE(COMP_PHL_DBG, _PHL_INFO_,
1336 			  "%s: MSG_EVT_AP_STOP_PREPARE\n", __FUNCTION__);
1337 
1338 		role = (struct rtw_wifi_role_t *)msg->rsvd[0];
1339 		if (role == NULL) {
1340 			PHL_TRACE(COMP_PHL_DBG, _PHL_WARNING_,
1341 				  "%s: role is NULL\n", __FUNCTION__);
1342 			break;
1343 		}
1344 		if (_phl_mrc_module_ap_stop_pre_hdlr(phl_info, role) !=
1345 			RTW_PHL_STATUS_SUCCESS) {
1346 			break;
1347 		}
1348 #endif
1349 		ret = MDL_RET_SUCCESS;
1350 		break;
1351 	case MSG_EVT_AP_STOP:
1352 #ifdef CONFIG_AP_CMD_DISPR
1353 		if (MSG_MDL_ID_FIELD(msg->msg_id) != PHL_FG_MDL_AP_STOP) {
1354 			return MDL_RET_IGNORE;
1355 		}
1356 		PHL_TRACE(COMP_PHL_DBG, _PHL_INFO_,
1357 			  "%s: MSG_EVT_AP_STOP\n", __FUNCTION__);
1358 
1359 		role = (struct rtw_wifi_role_t *)msg->rsvd[0];
1360 		if (role == NULL) {
1361 			PHL_TRACE(COMP_PHL_DBG, _PHL_WARNING_,
1362 				  "%s: role is NULL\n", __FUNCTION__);
1363 			break;
1364 		}
1365 		if (_phl_mrc_module_ap_stop_hdlr(phl_info, role) !=
1366 			RTW_PHL_STATUS_SUCCESS) {
1367 			break;
1368 		}
1369 #endif
1370 		ret = MDL_RET_SUCCESS;
1371 		break;
1372 	case MSG_EVT_SCAN_START:
1373 		if (MSG_MDL_ID_FIELD(msg->msg_id) != PHL_FG_MDL_SCAN) {
1374 			return MDL_RET_IGNORE;
1375 		}
1376 		PHL_TRACE(COMP_PHL_DBG, _PHL_INFO_,
1377 			  "%s: MSG_EVT_SCAN_START\n", __FUNCTION__);
1378 		role = (struct rtw_wifi_role_t *)msg->rsvd[0];
1379 #ifdef CONFIG_MCC_SUPPORT
1380 		if (phl_mr_coex_disable(phl_info, role, role->hw_band,
1381 			MR_COEX_TRIG_BY_SCAN) != RTW_PHL_STATUS_SUCCESS)
1382 			PHL_TRACE(COMP_PHL_DBG, _PHL_WARNING_, "disable TDMRA fail!\n");
1383 #endif /* CONFIG_MCC_SUPPORT */
1384 		phl_p2pps_noa_pause_all(phl_info, role);
1385 #ifdef RTW_WKARD_MRC_ISSUE_NULL_WITH_SCAN_OPS
1386 		op_info.op_code = FG_REQ_OP_GET_SCAN_PARAM;
1387 		if (phl_disp_eng_query_cur_cmd_info(phl_info, idx, &op_info)
1388 			!= RTW_PHL_STATUS_SUCCESS) {
1389 			PHL_TRACE(COMP_PHL_DBG, _PHL_WARNING_,
1390 				  "Query scan_param fail!\n");
1391 			break;
1392 		}
1393 		scan_param = (struct rtw_phl_scan_param*)op_info.outbuf;
1394 		if (op_info.outbuf == NULL) {
1395 			PHL_TRACE(COMP_PHL_DBG, _PHL_WARNING_,
1396 				  "%s: scan_param is NULL\n", __FUNCTION__);
1397 			break;
1398 		}
1399 		phl_mr_offch_hdl(phl_info,
1400 				  role,
1401 				  true,
1402 				  phl_com->drv_priv,
1403 				  scan_param->ops->scan_issue_null_data);
1404 #endif
1405 		ret = MDL_RET_SUCCESS;
1406 		break;
1407 	case MSG_EVT_SCAN_END:
1408 		if (MSG_MDL_ID_FIELD(msg->msg_id) != PHL_FG_MDL_SCAN) {
1409 				return MDL_RET_IGNORE;
1410 		}
1411 		PHL_TRACE(COMP_PHL_DBG, _PHL_INFO_,
1412 			  "%s: MSG_EVT_SCAN_END\n", __FUNCTION__);
1413 		role = (struct rtw_wifi_role_t *)msg->rsvd[0];
1414 		if (role == NULL) {
1415 			PHL_TRACE(COMP_PHL_DBG, _PHL_WARNING_,
1416 				  "%s: role is NULL\n", __FUNCTION__);
1417 			break;
1418 		}
1419 		if (phl_mr_get_chandef(phl_info,
1420 				       role,
1421 				       false,
1422 				       &chandef) !=
1423 				RTW_PHL_STATUS_SUCCESS) {
1424 			PHL_ERR("%s phl_mr_get_chandef failed\n", __func__);
1425 			break;
1426 		}
1427 		PHL_DUMP_CHAN_DEF_EX(&chandef);
1428 		phl_set_ch_bw(role, &chandef, false);
1429 #ifdef RTW_WKARD_MRC_ISSUE_NULL_WITH_SCAN_OPS
1430 		/*
1431 		 * Use msg to send ops pointer to prevent query fail in
1432 		 * abort case
1433 		 */
1434 		scan_issue_null_data = (u8 (*)(void *, u8, bool))msg->rsvd[1];
1435 		phl_mr_offch_hdl(phl_info,
1436 				  role,
1437 				  false,
1438 				  phl_com->drv_priv,
1439 				  scan_issue_null_data);
1440 #endif
1441 		phl_p2pps_noa_resume_all(phl_info, role);
1442 #ifdef CONFIG_MCC_SUPPORT
1443 		/* Enable MR coex mechanism(if needed) */
1444 		if (phl_mr_coex_handle(phl_info, role, 0, role->hw_band,
1445 						MR_COEX_TRIG_BY_SCAN)
1446 					!= RTW_PHL_STATUS_SUCCESS) {
1447 			PHL_TRACE(COMP_PHL_DBG, _PHL_WARNING_,
1448 				  "enable MCC fail!\n");
1449 		}
1450 #endif /* CONFIG_MCC_SUPPORT */
1451 		ret = MDL_RET_SUCCESS;
1452 		break;
1453 	case MSG_EVT_ECSA_SWITCH_START:
1454 #ifdef CONFIG_PHL_ECSA
1455 		if (MSG_MDL_ID_FIELD(msg->msg_id) != PHL_FG_MDL_ECSA) {
1456 				return MDL_RET_IGNORE;
1457 		}
1458 		PHL_TRACE(COMP_PHL_DBG, _PHL_INFO_,
1459 			  "%s: MSG_EVT_ECSA_SWITCH_START\n", __FUNCTION__);
1460 		role = (struct rtw_wifi_role_t *)msg->rsvd[0];
1461 
1462 		if (role == NULL) {
1463 			PHL_TRACE(COMP_PHL_DBG, _PHL_WARNING_,
1464 				  "%s: role is NULL\n", __FUNCTION__);
1465 			break;
1466 		}
1467 #ifdef CONFIG_MCC_SUPPORT
1468 		if (phl_mr_coex_disable(phl_info, role, role->hw_band,
1469 			MR_COEX_TRIG_BY_ECSA) != RTW_PHL_STATUS_SUCCESS) {
1470 			PHL_TRACE(COMP_PHL_ECSA, _PHL_WARNING_,
1471 				  "Disable MCC failed\n");
1472 			break;
1473 		}
1474 #endif /* CONFIG_MCC_SUPPORT */
1475 #endif /* CONFIG_PHL_ECSA */
1476 		ret = MDL_RET_SUCCESS;
1477 		break;
1478 	case MSG_EVT_ECSA_SWITCH_DONE:
1479 #ifdef CONFIG_PHL_ECSA
1480 		if (MSG_MDL_ID_FIELD(msg->msg_id) != PHL_FG_MDL_ECSA) {
1481 				return MDL_RET_IGNORE;
1482 		}
1483 		PHL_TRACE(COMP_PHL_DBG, _PHL_INFO_,
1484 			  "%s: MSG_EVT_ECSA_SWITCH_DONE\n", __FUNCTION__);
1485 		role = (struct rtw_wifi_role_t *)msg->rsvd[0];
1486 
1487 		if (role == NULL) {
1488 			PHL_TRACE(COMP_PHL_DBG, _PHL_WARNING_,
1489 				  "%s: role is NULL\n", __FUNCTION__);
1490 			break;
1491 		}
1492 		phl_mr_stop_all_beacon(phl_info, role, false);
1493 #ifdef CONFIG_MCC_SUPPORT
1494 		/* STA ECSA might switch to a channel still in MCC state */
1495 		/* Enable MR coex mechanism(if needed) */
1496 		if (phl_mr_coex_handle(phl_info, role, 0,
1497 				role->hw_band, MR_COEX_TRIG_BY_ECSA)
1498 						!= RTW_PHL_STATUS_SUCCESS) {
1499 			PHL_TRACE(COMP_PHL_ECSA, _PHL_WARNING_,
1500 				  "Enable TDMRA failed\n");
1501 			break;
1502 		}
1503 #endif /* CONFIG_MCC_SUPPORT */
1504 
1505 		if (RTW_PHL_STATUS_SUCCESS != phl_role_notify(phl_info, role)) {
1506 			PHL_ERR("%s role notify failed\n", __func__);
1507 			ret = MDL_RET_FAIL;
1508 		} else
1509 #endif /* CONFIG_PHL_ECSA */
1510 		ret = MDL_RET_SUCCESS;
1511 		break;
1512 	case MSG_EVT_BTC_REQ_BT_SLOT:
1513 #ifdef CONFIG_MCC_SUPPORT
1514 		if (MSG_MDL_ID_FIELD(msg->msg_id) != PHL_MDL_BTC)
1515 			return MDL_RET_IGNORE;
1516 
1517 		PHL_INFO("%s: MSG_EVT_BTC_REQ_BT_SLOT, BT slot = %d\n", __func__, (u16)(*(u32 *)msg->inbuf));
1518 		phl_mr_coex_handle(phl_info, NULL, (u16)(*(u32 *)msg->inbuf),
1519 			msg->band_idx, MR_COEX_TRIG_BY_BT);
1520 #endif
1521 		ret = MDL_RET_SUCCESS;
1522 		break;
1523 	case MSG_EVT_SER_M5_READY:
1524 		if (MSG_MDL_ID_FIELD(msg->msg_id) != PHL_MDL_SER)
1525 			return MDL_RET_IGNORE;
1526 
1527 		PHL_INFO("%s: MSG_EVT_SER_M5_READY\n", __func__);
1528 		phl_mr_err_recovery(phl_info, MSG_EVT_ID_FIELD(msg->msg_id));
1529 		ret = MDL_RET_SUCCESS;
1530 		break;
1531 	default:
1532 		ret = MDL_RET_SUCCESS;
1533 		break;
1534 	}
1535 	FUNCOUT();
1536 	return ret;
1537 }
1538 
1539 static enum phl_mdl_ret_code
_phl_mrc_module_msg_hdlr(void * dispr,void * priv,struct phl_msg * msg)1540 _phl_mrc_module_msg_hdlr(void *dispr, void *priv, struct phl_msg *msg)
1541 {
1542 	enum phl_mdl_ret_code ret = MDL_RET_FAIL;
1543 
1544 	FUNCIN();
1545 	if (IS_MSG_FAIL(msg->msg_id)) {
1546 		PHL_TRACE(COMP_PHL_DBG, _PHL_WARNING_,
1547 			  "%s: cmd dispatcher notify cmd failure: 0x%x.\n",
1548 			   __FUNCTION__, msg->msg_id);
1549 	FUNCOUT();
1550 		return MDL_RET_FAIL;
1551 	}
1552 	if (IS_MSG_IN_PRE_PHASE(msg->msg_id)) {
1553 		ret = _mrc_module_msg_pre_hdlr(dispr, priv, msg);
1554 	} else {
1555 		ret = _mrc_module_msg_post_hdl(dispr, priv, msg);
1556 	}
1557 	FUNCOUT();
1558 	return ret;
1559 }
1560 
1561 static enum phl_mdl_ret_code
_phl_mrc_module_set_info(void * dispr,void * priv,struct phl_module_op_info * info)1562 _phl_mrc_module_set_info(void *dispr,
1563 			 void *priv,
1564 			 struct phl_module_op_info *info)
1565 {
1566 	enum phl_mdl_ret_code ret = MDL_RET_FAIL;
1567 
1568 	FUNCIN();
1569 	FUNCOUT();
1570 
1571 	ret = MDL_RET_SUCCESS;
1572 	return ret;
1573 }
1574 
1575 static enum phl_mdl_ret_code
_phl_mrc_module_query_info(void * dispr,void * priv,struct phl_module_op_info * info)1576 _phl_mrc_module_query_info(void *dispr,
1577 			   void *priv,
1578 			   struct phl_module_op_info *info)
1579 {
1580 	enum phl_mdl_ret_code ret = MDL_RET_FAIL;
1581 
1582 	FUNCIN();
1583 	FUNCOUT();
1584 
1585 	ret = MDL_RET_SUCCESS;
1586 	return ret;
1587 }
1588 
1589 static enum rtw_phl_status
_phl_role_bk_module_init(struct phl_info_t * phl_info)1590 _phl_role_bk_module_init(struct phl_info_t *phl_info)
1591 {
1592 	struct mr_ctl_t *mr_ctl = phlcom_to_mr_ctrl(phl_info->phl_com);
1593 	struct phl_bk_module_ops *bk_ops = &mr_ctl->bk_ops;
1594 
1595 	bk_ops->init = _phl_mrc_module_init;
1596 	bk_ops->deinit = _phl_mrc_module_deinit;
1597 	bk_ops->start = _phl_mrc_module_start;
1598 	bk_ops->stop = _phl_mrc_module_stop;
1599 	bk_ops->msg_hdlr = _phl_mrc_module_msg_hdlr;
1600 	bk_ops->set_info = _phl_mrc_module_set_info;
1601 	bk_ops->query_info = _phl_mrc_module_query_info;
1602 
1603 	return RTW_PHL_STATUS_SUCCESS;
1604 }
1605 #endif /*CONFIG_CMD_DISP*/
1606 /*
1607  * init wifi_role control components
1608  * init band_ctrl
1609  * init bk module
1610  * init wifi_role[]
1611  */
1612 enum rtw_phl_status
phl_mr_ctrl_init(struct phl_info_t * phl_info)1613 phl_mr_ctrl_init(struct phl_info_t *phl_info)
1614 {
1615 	struct rtw_phl_com_t *phl_com = phl_info->phl_com;
1616 	void *drv = phl_to_drvpriv(phl_info);
1617 	struct mr_ctl_t *mr_ctl = phlcom_to_mr_ctrl(phl_com);
1618 	u8 ridx = MAX_WIFI_ROLE_NUMBER;
1619 	struct rtw_wifi_role_t *role = NULL;
1620 	enum rtw_phl_status status = RTW_PHL_STATUS_FAILURE;
1621 
1622 	mr_ctl->hal_com = rtw_hal_get_halcom(phl_info->hal);
1623 	if (mr_ctl->hal_com == NULL) {
1624 		PHL_ERR("%s mr_ctl->hal_com is NULL\n", __func__);
1625 		_os_warn_on(1);
1626 		return RTW_PHL_STATUS_FAILURE;
1627 	}
1628 	_os_spinlock_init(drv, &(mr_ctl->lock));
1629 	mr_ctl->is_sb = true;
1630 	_phl_band_ctrl_init(phl_info);
1631 	#ifdef CONFIG_CMD_DISP
1632 	_phl_role_bk_module_init(phl_info);
1633 	#endif
1634 	_os_mem_set(phl_to_drvpriv(phl_info), phl_com->wifi_roles,
1635 		0, sizeof(*phl_com->wifi_roles));
1636 
1637 	for (ridx = 0; ridx < MAX_WIFI_ROLE_NUMBER; ridx++) {
1638 		role = &(phl_com->wifi_roles[ridx]);
1639 		pq_init(drv, &role->assoc_sta_queue);
1640 		role->phl_com = phl_com;
1641 		role->id = ridx;
1642 		role->active = false;
1643 		role->chanctx = NULL;
1644 	}
1645 	if (RTW_PHL_STATUS_SUCCESS != (status = rtw_phl_mcc_init(phl_info))) {
1646 		PHL_ERR("%s mcc init fail\n", __func__);
1647 		/* todo, need to discuss with Georgia*/
1648 	}
1649 	return RTW_PHL_STATUS_SUCCESS;
1650 }
1651 
1652 static enum rtw_phl_status
_phl_band_ctrl_deinit(struct phl_info_t * phl_info)1653 _phl_band_ctrl_deinit(struct phl_info_t *phl_info)
1654 {
1655 	void *drv = phl_to_drvpriv(phl_info);
1656 	struct mr_ctl_t *mr_ctl = phlcom_to_mr_ctrl(phl_info->phl_com);
1657 	struct hw_band_ctl_t *band_ctrl;
1658 	u8 band_idx = 0;
1659 
1660 	rtw_phl_mcc_deinit(phl_info);
1661 	for (band_idx = 0; band_idx < MAX_BAND_NUM; band_idx++) {
1662 		band_ctrl = &(mr_ctl->band_ctrl[band_idx]);
1663 		phl_chanctx_free(phl_info, band_ctrl);
1664 		_os_spinlock_free(drv, &(band_ctrl->lock));
1665 		pq_deinit(drv , &band_ctrl->chan_ctx_queue);
1666 	}
1667 
1668 	return RTW_PHL_STATUS_SUCCESS;
1669 }
1670 
1671 enum rtw_phl_status
phl_mr_ctrl_deinit(struct phl_info_t * phl_info)1672 phl_mr_ctrl_deinit(struct phl_info_t *phl_info)
1673 {
1674 	struct rtw_phl_com_t *phl_com = phl_info->phl_com;
1675 	u8 ridx = MAX_WIFI_ROLE_NUMBER;
1676 	struct rtw_wifi_role_t *role;
1677 	void *drv = phl_to_drvpriv(phl_info);
1678 	struct mr_ctl_t *mr_ctl = phlcom_to_mr_ctrl(phl_com);
1679 
1680 	_os_spinlock_free(drv, &(mr_ctl->lock));
1681 	_phl_band_ctrl_deinit(phl_info);
1682 
1683 	for (ridx = 0; ridx < MAX_WIFI_ROLE_NUMBER; ridx++) {
1684 		role = &(phl_com->wifi_roles[ridx]);
1685 		pq_deinit(drv, &role->assoc_sta_queue);
1686 	}
1687 
1688 	return RTW_PHL_STATUS_SUCCESS;
1689 }
1690 
1691 enum rtw_phl_status
phl_mr_chandef_sync(struct phl_info_t * phl_info,struct hw_band_ctl_t * band_ctrl,struct rtw_chan_ctx * chanctx,struct rtw_chan_def * chandef)1692 phl_mr_chandef_sync(struct phl_info_t *phl_info, struct hw_band_ctl_t *band_ctrl,
1693 			struct rtw_chan_ctx *chanctx, struct rtw_chan_def *chandef)
1694 {
1695 	void *drv = phl_to_drvpriv(phl_info);
1696 	u8 ridx;
1697 	u8 role_num = 0;
1698 	enum band_type band_ret = BAND_MAX;
1699 	u8 ch_ret = 0;
1700 	enum channel_width bw_ret = CHANNEL_WIDTH_20;
1701 	enum chan_offset offset_ret = CHAN_OFFSET_NO_EXT;
1702 	struct rtw_wifi_role_t *wrole;
1703 	enum rtw_phl_status phl_sts = RTW_PHL_STATUS_FAILURE;
1704 
1705 	if (!chanctx) {
1706 		PHL_ERR("%s failed, chanctx == NULL\n", __func__);
1707 		goto _exit;
1708 	}
1709 	if (!chandef) {
1710 		PHL_ERR("%s failed, chandef == NULL\n", __func__);
1711 		goto _exit;
1712 	}
1713 
1714 	_os_spinlock(drv, &band_ctrl->chan_ctx_queue.lock, _ps, NULL);
1715 	for (ridx = 0; ridx < MAX_WIFI_ROLE_NUMBER; ridx++) {
1716 		if (chanctx->role_map & BIT(ridx)) {
1717 			wrole = rtw_phl_get_wrole_by_ridx(phl_info->phl_com, ridx);
1718 			if (wrole == NULL) {
1719 				PHL_ERR("ridx :%d wrole == NULL\n", ridx);
1720 				_os_warn_on(1);
1721 				continue;
1722 			}
1723 			if (role_num == 0) {
1724 				band_ret = wrole->chandef.band;
1725 				ch_ret = wrole->chandef.chan;
1726 				bw_ret = wrole->chandef.bw;
1727 				offset_ret = wrole->chandef.offset;
1728 				role_num++;
1729 				continue;
1730 			}
1731 			if (band_ret != wrole->chandef.band) {
1732 				PHL_ERR("band_ret(%d) !=  ridx(%d)-band_ret(%d)\n",
1733 					band_ret, ridx, wrole->chandef.band);
1734 				_os_warn_on(1);
1735 				role_num = 0;
1736 				break;
1737 			}
1738 			if (ch_ret !=  wrole->chandef.chan) {
1739 				PHL_ERR("ch_ret(%d) !=  ridx(%d)-chan(%d)\n",
1740 					ch_ret, ridx, wrole->chandef.chan);
1741 				_os_warn_on(1);
1742 				role_num = 0;
1743 				break;
1744 			}
1745 
1746 			if (bw_ret < wrole->chandef.bw) {
1747 				bw_ret = wrole->chandef.bw;
1748 				offset_ret = wrole->chandef.offset;
1749 			} else if (bw_ret == wrole->chandef.bw && offset_ret != wrole->chandef.offset) {
1750 				role_num = 0;
1751 				break;
1752 			}
1753 			role_num++;
1754 		}
1755 	}
1756 	_os_spinunlock(drv, &band_ctrl->chan_ctx_queue.lock, _ps, NULL);
1757 
1758 	if (role_num == 0) {
1759 		PHL_ERR("%s role_num=0\n", __func__);
1760 		_os_warn_on(!role_num);
1761 		goto _exit;
1762 	}
1763 
1764 	PHL_INFO("%s org_chctx - band:%d, chan:%d, bw:%d, offset:%d\n",
1765 		__func__, chandef->band, chandef->chan, chandef->bw, chandef->offset);
1766 	PHL_INFO("%s mi_upt - band:%d, chan:%d, bw:%d, offset:%d\n",
1767 		__func__, band_ret, ch_ret, bw_ret, offset_ret);
1768 
1769 	chandef->band = band_ret;
1770 	chandef->chan = ch_ret;
1771 	chandef->bw = bw_ret;
1772 	chandef->offset = offset_ret;
1773 	phl_sts = RTW_PHL_STATUS_SUCCESS;
1774 
1775 _exit:
1776 	return phl_sts;
1777 }
1778 
1779 /*
1780  * MR change chctx from wrole->chdef to new chdef
1781  * @wrole: specific role, and we can get original chdef.
1782  * @new_chan: new chdef
1783  * @chctx_result: The final ch ctx after change new chdef to MR.
1784  * ex: In the scc case, it will be the group chdef.
1785  */
1786 enum rtw_phl_status
phl_mr_chandef_chg(struct phl_info_t * phl,struct rtw_wifi_role_t * wrole,struct rtw_chan_def * new_chan,struct rtw_chan_def * chctx_result)1787 phl_mr_chandef_chg(struct phl_info_t *phl,
1788 		struct rtw_wifi_role_t *wrole, struct rtw_chan_def *new_chan,
1789 		struct rtw_chan_def *chctx_result)
1790 {
1791 	enum rtw_phl_status psts = RTW_PHL_STATUS_FAILURE;
1792 	struct rtw_chan_def chan_def = {0};
1793 	void *drv = phl_to_drvpriv(phl);
1794 	u8 chanctx_num = 0;
1795 
1796 	chanctx_num = (u8)rtw_phl_chanctx_del(phl, wrole, &chan_def);
1797 	_os_mem_cpy(drv, &chan_def, new_chan, sizeof(struct rtw_chan_def));
1798 	if (rtw_phl_chanctx_add((void *)phl, wrole, &chan_def.chan,
1799 		&chan_def.bw, &chan_def.offset)) {
1800 		_os_mem_cpy(drv, chctx_result, &chan_def,
1801 				sizeof(struct rtw_chan_def));
1802 		psts = RTW_PHL_STATUS_SUCCESS;
1803 		goto exit;
1804 	}
1805 	PHL_TRACE(COMP_PHL_DBG, _PHL_ERR_, "%s: Add new chandef fail, something wrong!\n",
1806 		__FUNCTION__);
1807 	/* Error handle: Recover the chctx */
1808 	_os_mem_cpy(drv, &chan_def, &wrole->chandef,
1809 			sizeof(struct rtw_chan_def));
1810 	if (!rtw_phl_chanctx_add((void *)phl, wrole, &chan_def.chan,
1811 		&chan_def.bw, &chan_def.offset)) {
1812 		PHL_TRACE(COMP_PHL_DBG, _PHL_ERR_, "%s: Error handle failed for recovery!\n",
1813 			__FUNCTION__);
1814 		goto exit;
1815 	}
1816 exit:
1817 	return psts;
1818 }
1819 
1820 enum rtw_phl_status
phl_mr_chandef_upt(struct phl_info_t * phl_info,struct hw_band_ctl_t * band_ctrl,struct rtw_chan_ctx * chanctx)1821 phl_mr_chandef_upt(struct phl_info_t *phl_info,
1822 		struct hw_band_ctl_t *band_ctrl, struct rtw_chan_ctx *chanctx)
1823 {
1824 	enum rtw_phl_status phl_sts = RTW_PHL_STATUS_FAILURE;
1825 
1826 	if (!chanctx) {
1827 		PHL_ERR("%s chanctx == NULL\n", __func__);
1828 		goto _exit;
1829 	}
1830 
1831 	phl_sts = phl_mr_chandef_sync(phl_info, band_ctrl, chanctx, &chanctx->chan_def);
1832 	if (phl_sts != RTW_PHL_STATUS_SUCCESS)
1833 		PHL_ERR("%s phl_mr_sync_chandef failed\n", __func__);
1834 _exit:
1835 	return phl_sts;
1836 }
1837 
1838 enum rtw_phl_status
rtw_phl_mr_upt_chandef(void * phl,struct rtw_wifi_role_t * wifi_role)1839 rtw_phl_mr_upt_chandef(void *phl, struct rtw_wifi_role_t *wifi_role)
1840 {
1841 	struct phl_info_t *phl_info = (struct phl_info_t *)phl;
1842 	struct rtw_phl_com_t *phl_com = phl_info->phl_com;
1843 	struct mr_ctl_t *mr_ctl = phlcom_to_mr_ctrl(phl_com);
1844 	struct hw_band_ctl_t *band_ctrl = &(mr_ctl->band_ctrl[wifi_role->hw_band]);
1845 	enum rtw_phl_status phl_sts = RTW_PHL_STATUS_FAILURE;
1846 
1847 	if (!wifi_role->chanctx) {
1848 		PHL_ERR("%s failed - wifi_role->chanctx == NULL\n", __func__);
1849 		goto _exit;
1850 	}
1851 	phl_sts = phl_mr_chandef_upt(phl_info, band_ctrl, wifi_role->chanctx);
1852 	if (phl_sts != RTW_PHL_STATUS_SUCCESS)
1853 		PHL_ERR("%s phl_mr_chandef_upt failed\n", __func__);
1854 
1855 _exit:
1856 	return phl_sts;
1857 }
1858 
1859 enum rtw_phl_status
phl_mr_get_chandef(struct phl_info_t * phl_info,struct rtw_wifi_role_t * wifi_role,bool sync,struct rtw_chan_def * chandef)1860 phl_mr_get_chandef(struct phl_info_t *phl_info, struct rtw_wifi_role_t *wifi_role,
1861 			bool sync, struct rtw_chan_def *chandef)
1862 {
1863 	enum rtw_phl_status phl_sts = RTW_PHL_STATUS_SUCCESS;
1864 	void *drv = phl_to_drvpriv(phl_info);
1865 	struct rtw_phl_com_t *phl_com = phl_info->phl_com;
1866 	struct mr_ctl_t *mr_ctl = phlcom_to_mr_ctrl(phl_com);
1867 	struct hw_band_ctl_t *band_ctrl = &(mr_ctl->band_ctrl[wifi_role->hw_band]);
1868 	struct phl_queue *chan_ctx_queue = &band_ctrl->chan_ctx_queue;
1869 	struct rtw_chan_ctx *chanctx = NULL;
1870 	int chctx_num = 0;
1871 	u8 chctx_role_num = 0;
1872 
1873 	if (!chandef) {
1874 		PHL_ERR("%s failed - chandef == NULL\n", __func__);
1875 		phl_sts = RTW_PHL_STATUS_FAILURE;
1876 		goto _exit;
1877 	}
1878 
1879 	/*init chandef*/
1880 	chandef->chan = 0;
1881 	if (wifi_role->chanctx) {
1882 		chctx_role_num = phl_chanctx_get_rnum_with_lock(phl_info, chan_ctx_queue, wifi_role->chanctx);
1883 
1884 		if (chctx_role_num == 0) {
1885 			PHL_ERR("%s-%d chctx_role_num == 0\n", __FUNCTION__, __LINE__);
1886 			_os_warn_on(1);
1887 		}
1888 		if (sync && chctx_role_num >= 2) {
1889 			phl_sts = phl_mr_chandef_sync(phl_info, band_ctrl,
1890 						wifi_role->chanctx, chandef);
1891 			if (phl_sts != RTW_PHL_STATUS_SUCCESS) {
1892 				PHL_ERR("%s phl_mr_chandef_sync failed\n", __func__);
1893 				_os_warn_on(1);
1894 			}
1895 		} else { /*chctx_role_num == 1*/
1896 			_os_mem_cpy(drv, chandef, &wifi_role->chanctx->chan_def,
1897 							sizeof(struct rtw_chan_def));
1898 		}
1899 	}
1900 	else {
1901 		chctx_num = phl_mr_get_chanctx_num(phl_info, band_ctrl);
1902 		if (chctx_num == 0) {
1903 			_os_mem_cpy(drv, chandef, &wifi_role->chandef,
1904 						sizeof(struct rtw_chan_def));
1905 
1906 		} else if (chctx_num == 1) {
1907 			_os_spinlock(drv, &chan_ctx_queue->lock, _ps, NULL);
1908 			if (list_empty(&chan_ctx_queue->queue)) {
1909 				PHL_ERR("%s chan_ctx_queue->queue is empty\n", __func__);
1910 				_os_warn_on(1);
1911 			}
1912 
1913 			chanctx = list_first_entry(&chan_ctx_queue->queue,
1914 						struct rtw_chan_ctx, list);
1915 			chctx_role_num = phl_chanctx_get_rnum(phl_info, chan_ctx_queue, chanctx);
1916 			if (chctx_role_num == 0) {
1917 				PHL_ERR("%s-%d chctx_role_num == 0\n", __FUNCTION__, __LINE__);
1918 				_os_warn_on(1);
1919 			}
1920 			if (sync && chctx_role_num >= 2) {
1921 				phl_sts = phl_mr_chandef_sync(phl_info, band_ctrl,
1922 								chanctx, chandef);
1923 				if (phl_sts != RTW_PHL_STATUS_SUCCESS)
1924 					PHL_ERR("%s phl_mr_chandef_sync failed\n", __func__);
1925 			} else { /*chctx_role_num == 1*/
1926 				_os_mem_cpy(drv, chandef, &chanctx->chan_def,
1927 						sizeof(struct rtw_chan_def));
1928 			}
1929 			_os_spinunlock(drv, &chan_ctx_queue->lock, _ps, NULL);
1930 
1931 		} else if (chctx_num == 2) { /*MCC*/
1932 
1933 		} else {
1934 			PHL_ERR("%s chctx_num(%d) is invalid\n", __func__, chctx_num);
1935 			_os_warn_on(1);
1936 			goto _exit;
1937 		}
1938 	}
1939 
1940 _exit:
1941 	return phl_sts;
1942 }
1943 enum rtw_phl_status
rtw_phl_mr_get_chandef(void * phl,struct rtw_wifi_role_t * wifi_role,struct rtw_chan_def * chandef)1944 rtw_phl_mr_get_chandef(void *phl, struct rtw_wifi_role_t *wifi_role,
1945 					struct rtw_chan_def *chandef)
1946 {
1947 	struct phl_info_t *phl_info = (struct phl_info_t *)phl;
1948 
1949 	return phl_mr_get_chandef(phl_info, wifi_role, false, chandef);
1950 
1951 }
rtw_phl_mr_get_chanctx_num(void * phl,struct rtw_wifi_role_t * wifi_role)1952 int rtw_phl_mr_get_chanctx_num(void *phl, struct rtw_wifi_role_t *wifi_role)
1953 {
1954 	struct phl_info_t *phl_info = (struct phl_info_t *)phl;
1955 	struct mr_ctl_t *mr_ctl = phlcom_to_mr_ctrl(phl_info->phl_com);
1956 	u8 band_idx = wifi_role->hw_band;
1957 	struct hw_band_ctl_t *band_ctrl = &(mr_ctl->band_ctrl[band_idx]);
1958 
1959 	return phl_mr_get_chanctx_num(phl_info, band_ctrl);
1960 }
1961 
1962 enum rtw_phl_status
rtw_phl_mr_rx_filter(void * phl,struct rtw_wifi_role_t * wrole)1963 rtw_phl_mr_rx_filter(void *phl, struct rtw_wifi_role_t *wrole)
1964 {
1965 	struct phl_info_t *phl_info = (struct phl_info_t *)phl;
1966 	enum rtw_rx_fltr_mode mode = RX_FLTR_MODE_STA_NORMAL;
1967 #ifdef CONFIG_MR_SUPPORT
1968 	struct mr_ctl_t *mr_ctl = phlcom_to_mr_ctrl(phl_info->phl_com);
1969 	struct hw_band_ctl_t *band_ctrl = &(mr_ctl->band_ctrl[wrole->hw_band]);
1970 
1971 	if (band_ctrl->cur_info.lg_sta_num >= 1)
1972 		mode = RX_FLTR_MODE_STA_LINKING;
1973 	else if (band_ctrl->cur_info.ap_num >= 1)
1974 		mode = RX_FLTR_MODE_AP_NORMAL;
1975 	else if (band_ctrl->cur_info.ld_sta_num >= 1)
1976 		mode = RX_FLTR_MODE_STA_NORMAL;	/* Accpet BSSID matched frames */
1977 	else
1978 		mode = RX_FLTR_MODE_STA_NORMAL; /* For STA no link case */
1979 
1980 #else
1981 	if (wrole->type == PHL_RTYPE_STATION && wrole->mstate == MLME_LINKED)
1982 		mode = RX_FLTR_MODE_STA_NORMAL;
1983 	else if (wrole->type == PHL_RTYPE_STATION && wrole->mstate == MLME_LINKING)
1984 		mode = RX_FLTR_MODE_STA_LINKING;
1985 	else if (wrole->type == PHL_RTYPE_AP)
1986 		mode = RX_FLTR_MODE_AP_NORMAL;
1987 	else
1988 		mode = RX_FLTR_MODE_STA_NORMAL;/* For STA no link case */
1989 #endif /*CONFIG_MR_SUPPORT*/
1990 
1991 	rtw_hal_set_rxfltr_by_mode(phl_info->hal, wrole->hw_band, mode);
1992 	return RTW_PHL_STATUS_SUCCESS;
1993 }
1994 
1995 enum rtw_phl_status
phl_mr_tsf_sync(void * phl,struct rtw_wifi_role_t * wrole,enum role_state state)1996 phl_mr_tsf_sync(void *phl, struct rtw_wifi_role_t *wrole,
1997 					enum role_state state)
1998 {
1999 	enum rtw_phl_status ret = RTW_PHL_STATUS_SUCCESS;
2000 #ifdef CONFIG_MR_SUPPORT
2001 	struct phl_info_t *phl_info = (struct phl_info_t *)phl;
2002 	struct mr_ctl_t *mr_ctl = phlcom_to_mr_ctrl(phl_info->phl_com);
2003 	struct hw_band_ctl_t *band_ctl = &mr_ctl->band_ctrl[wrole->hw_band];
2004 	struct rtw_chan_ctx *chanctx = wrole->chanctx;
2005 	struct rtw_phl_com_t *phl_com = wrole->phl_com;
2006 	struct rtw_wifi_role_t *wr_sync_from = NULL;
2007 	struct rtw_wifi_role_t *wr_sync_to = NULL;
2008 	enum phl_band_idx band = wrole->hw_band;
2009 	s8 tsf_sync_offset_tu = 50;/* unit is TU(1024us) */
2010 	u8 ridx = 0;
2011 	u8 ap_num = band_ctl->cur_info.ap_num;
2012 	u8 ld_sta_num = band_ctl->cur_info.ld_sta_num;
2013 	int chanctx_num = 0;
2014 
2015 	chanctx_num = phl_mr_get_chanctx_num(phl_info, band_ctl);
2016 	PHL_INFO("%s:state(%d), ap_num=%d, ld_sta_num=%d, tsf_sync_port=%d,chanctx_num=%d\n",
2017 			__func__, state, ap_num, ld_sta_num, band_ctl->tsf_sync_port, chanctx_num);
2018 
2019 	#ifdef CONFIG_MCC_SUPPORT
2020 	if (chanctx_num > 1) {
2021 		if (phl_com->dev_cap.mcc_sup == true) {
2022 			PHL_INFO("%s: will process MCC, skip tsf sync\n", __func__);
2023 			ret = RTW_PHL_STATUS_SUCCESS;
2024 			goto exit;
2025 		} else {
2026 			PHL_ERR("%s: chanctx_num(%d) > 1, check chanctx\n", __func__, chanctx_num);
2027 			ret = RTW_PHL_STATUS_FAILURE;
2028 			goto exit;
2029 		}
2030 	}
2031 	#endif
2032 
2033 	switch (state) {
2034 	case PHL_ROLE_MSTS_STA_CONN_END:
2035 		if (chanctx == NULL) {
2036 			PHL_WARN("%s: state%d wifi role (id=%d)chanctx=NULL\n", __func__, state, wrole->id);
2037 			ret = RTW_PHL_STATUS_FAILURE;
2038 			goto exit;
2039 		}
2040 		/* SoftAP already started, and no tsf sync before */
2041 		if (ap_num >= 1 && band_ctl->tsf_sync_port == HW_PORT_MAX) {
2042 			/* tsf sync for all softap */
2043 			wr_sync_from = wrole;
2044 			for (ridx = 0; ridx < MAX_WIFI_ROLE_NUMBER; ridx++) {
2045 				if (chanctx->role_map & BIT(ridx)) {
2046 					wr_sync_to = &phl_com->wifi_roles[ridx];
2047 					if (wr_sync_to != wr_sync_from) {
2048 						switch (wr_sync_to->type) {
2049 						case PHL_RTYPE_AP:
2050 						case PHL_RTYPE_VAP:
2051 						case PHL_RTYPE_P2P_GO:
2052 						case PHL_RTYPE_MESH:
2053 							if (rtw_hal_tsf_sync(phl_info->hal, wr_sync_from->hw_port,
2054 								wr_sync_to->hw_port, band, tsf_sync_offset_tu, HAL_TSF_EN_SYNC_AUTO) == RTW_HAL_STATUS_SUCCESS) {
2055 								ret = RTW_PHL_STATUS_SUCCESS;
2056 								PHL_INFO("%s, enable wrole:%d(port:%d) sync from wrole:%d(port:%d) success\n",
2057 									__func__, wr_sync_to->id, wr_sync_to->hw_port,
2058 									wr_sync_from->id, wr_sync_from->hw_port);
2059 							} else {
2060 								ret = RTW_PHL_STATUS_FAILURE;
2061 								PHL_ERR("%s, enable wrole:%d(port:%d) sync from wrole:%d(port:%d) fail\n",
2062 									__func__, wr_sync_to->id, wr_sync_to->hw_port,
2063 									wr_sync_from->id, wr_sync_from->hw_port);
2064 								break;
2065 							}
2066 							break;
2067 						default :
2068 							break;
2069 						}
2070 					}
2071 				}
2072 			}
2073 
2074 			if (ret == RTW_PHL_STATUS_SUCCESS)
2075 				band_ctl->tsf_sync_port = wr_sync_from->hw_port;
2076 			else
2077 				band_ctl->tsf_sync_port = HW_PORT_MAX;
2078 		}
2079 		break;
2080 	case PHL_ROLE_MSTS_STA_DIS_CONN:
2081 		if (chanctx == NULL) {
2082 			PHL_WARN("%s: state%d wifi role (id=%d)chanctx=NULL\n", __func__, state, wrole->id);
2083 			ret = RTW_PHL_STATUS_FAILURE;
2084 			goto exit;
2085 		}
2086 
2087 		/* if TSF sync do not enable, skip disable flow */
2088 		if (band_ctl->tsf_sync_port == HW_PORT_MAX) {
2089 			ret = RTW_PHL_STATUS_SUCCESS;
2090 			goto exit;
2091 		}
2092 
2093 		/* if disconnected STA is sync port and SoftAP exists,
2094 		find new sync port */
2095 		if (wrole->hw_port == band_ctl->tsf_sync_port &&
2096 			ap_num >= 1 && ld_sta_num > 0) {
2097 			/* find linked sta */
2098 			wr_sync_from = _search_ld_sta_wrole(wrole, true);
2099 			if (wr_sync_from) {
2100 				/* re-sync tsf for all softap */
2101 				for (ridx = 0; ridx < MAX_WIFI_ROLE_NUMBER; ridx++) {
2102 					if (chanctx->role_map & BIT(ridx)) {
2103 						wr_sync_to = &phl_com->wifi_roles[ridx];
2104 						if (wr_sync_to != wr_sync_from) {
2105 							switch (wr_sync_to->type) {
2106 							case PHL_RTYPE_AP:
2107 							case PHL_RTYPE_VAP:
2108 							case PHL_RTYPE_P2P_GO:
2109 							case PHL_RTYPE_MESH:
2110 								if (rtw_hal_tsf_sync(phl_info->hal, wr_sync_from->hw_port,
2111 									wr_sync_to->hw_port, band, tsf_sync_offset_tu, HAL_TSF_EN_SYNC_AUTO) == RTW_HAL_STATUS_SUCCESS) {
2112 									ret = RTW_PHL_STATUS_SUCCESS;
2113 									PHL_INFO("%s, enable wrole:%d(port:%d) sync from wrole:%d(port:%d) success\n",
2114 										__func__, wr_sync_to->id, wr_sync_to->hw_port,
2115 										wr_sync_from->id, wr_sync_from->hw_port);
2116 								} else {
2117 									ret = RTW_PHL_STATUS_FAILURE;
2118 									PHL_ERR("%s, enable wrole:%d(port:%d) sync from wrole:%d(port:%d) fail\n",
2119 										__func__, wr_sync_to->id, wr_sync_to->hw_port,
2120 										wr_sync_from->id, wr_sync_from->hw_port);
2121 									break;
2122 								}
2123 								break;
2124 							default :
2125 								break;
2126 							}
2127 						}
2128 					}
2129 				}
2130 
2131 				if (ret == RTW_PHL_STATUS_SUCCESS)
2132 					band_ctl->tsf_sync_port = wr_sync_from->hw_port;
2133 				else
2134 					band_ctl->tsf_sync_port = HW_PORT_MAX;
2135 			}
2136 		}
2137 
2138 		/* if disconnected STA is sync port and no other linked sta exist,
2139 		disable sofap tsf sync */
2140 		if (wrole->hw_port == band_ctl->tsf_sync_port && ld_sta_num == 0) {
2141 			for (ridx = 0; ridx < MAX_WIFI_ROLE_NUMBER; ridx++) {
2142 				if (chanctx->role_map & BIT(ridx)){
2143 					wr_sync_to = &phl_com->wifi_roles[ridx];
2144 					if (wr_sync_to != wr_sync_from) {
2145 						switch (wr_sync_to->type) {
2146 						case PHL_RTYPE_AP:
2147 						case PHL_RTYPE_VAP:
2148 						case PHL_RTYPE_P2P_GO:
2149 						case PHL_RTYPE_MESH:
2150 							if (wr_sync_to->mstate == MLME_LINKED) {
2151 								if (rtw_hal_tsf_sync(phl_info->hal, band_ctl->tsf_sync_port,
2152 									wr_sync_to->hw_port, band, tsf_sync_offset_tu, HAL_TSF_DIS_SYNC_AUTO) == RTW_HAL_STATUS_SUCCESS) {
2153 									ret = RTW_PHL_STATUS_SUCCESS;
2154 									PHL_INFO("%s, disable wrole:%d(port:%d) sync from wrole (port:%d) success\n",
2155 										__func__, wr_sync_to->id, wr_sync_to->hw_port,
2156 										band_ctl->tsf_sync_port);
2157 								} else {
2158 									ret = RTW_PHL_STATUS_FAILURE;
2159 									PHL_ERR("%s, disable wrole:%d(port:%d) sync from wrole:(port:%d) fail\n",
2160 										__func__, wr_sync_to->id, wr_sync_to->hw_port,
2161 										band_ctl->tsf_sync_port);
2162 									break;
2163 								}
2164 							}
2165 							break;
2166 						default :
2167 							break;
2168 						}
2169 					}
2170 				}
2171 			}
2172 
2173 			if (ret == RTW_PHL_STATUS_SUCCESS)
2174 				band_ctl->tsf_sync_port = HW_PORT_MAX;
2175 		}
2176 		break;
2177 	case PHL_ROLE_MSTS_AP_START:
2178 		if (chanctx == NULL) {
2179 			PHL_WARN("%s: state%d wifi role (id=%d)chanctx=NULL\n", __func__, state, wrole->id);
2180 			ret = RTW_PHL_STATUS_FAILURE;
2181 			goto exit;
2182 		}
2183 		/* no linked sta, don't enable tsf sync */
2184 		if (ld_sta_num == 0)
2185 			break;
2186 		/* New softAP start, and no tsf sync before, find sync port  */
2187 		if (band_ctl->tsf_sync_port == HW_PORT_MAX) {
2188 			wr_sync_to = wrole;
2189 			wr_sync_from = _search_ld_sta_wrole(wrole, true);
2190 			if (wr_sync_from) {
2191 				if (rtw_hal_tsf_sync(phl_info->hal, wr_sync_from->hw_port,
2192 					wr_sync_to->hw_port, band, tsf_sync_offset_tu, HAL_TSF_EN_SYNC_AUTO) == RTW_HAL_STATUS_SUCCESS) {
2193 					band_ctl->tsf_sync_port = wr_sync_from->hw_port;
2194 					ret = RTW_PHL_STATUS_SUCCESS;
2195 					PHL_INFO("%s, enable wrole:%d(port:%d) sync from wrole:%d(port:%d) success\n",
2196 						__func__, wr_sync_to->id, wr_sync_to->hw_port,
2197 						wr_sync_from->id, wr_sync_from->hw_port);
2198 				} else {
2199 					ret = RTW_PHL_STATUS_FAILURE;
2200 					PHL_ERR("%s, enable wrole:%d(port:%d) sync from wrole:%d(port:%d) fail\n",
2201 						__func__, wr_sync_to->id, wr_sync_to->hw_port,
2202 						wr_sync_from->id, wr_sync_from->hw_port);
2203 				}
2204 			}
2205 		} else if (band_ctl->tsf_sync_port != HW_PORT_MAX) {
2206 			/* New softAP start, enable tsf sync before, follow original sync port  */
2207 			wr_sync_to = wrole;
2208 			if (rtw_hal_tsf_sync(phl_info->hal, band_ctl->tsf_sync_port,
2209 				wr_sync_to->hw_port, band, tsf_sync_offset_tu, HAL_TSF_EN_SYNC_AUTO) == RTW_HAL_STATUS_SUCCESS) {
2210 				ret = RTW_PHL_STATUS_SUCCESS;
2211 				PHL_INFO("%s, enable wrole:%d(port:%d) sync from wrole(port:%d) success\n",
2212 					__func__, wr_sync_to->id, wr_sync_to->hw_port,
2213 					band_ctl->tsf_sync_port);
2214 			} else {
2215 				ret = RTW_PHL_STATUS_FAILURE;
2216 				PHL_ERR("%s, enable wrole:%d(port:%d) sync from wrole(port:%d) fail\n",
2217 					__func__, wr_sync_to->id, wr_sync_to->hw_port,
2218 					band_ctl->tsf_sync_port);
2219 			}
2220 		}
2221 		break;
2222 	case PHL_ROLE_MSTS_AP_STOP:
2223 		/* if TSF sync do not enable, skip disable flow */
2224 		if (band_ctl->tsf_sync_port == HW_PORT_MAX) {
2225 			ret = RTW_PHL_STATUS_SUCCESS;
2226 			goto exit;
2227 		}
2228 		wr_sync_to = wrole;
2229 		if (rtw_hal_tsf_sync(phl_info->hal, band_ctl->tsf_sync_port,
2230 					wr_sync_to->hw_port, band, tsf_sync_offset_tu, HAL_TSF_DIS_SYNC_AUTO) == RTW_HAL_STATUS_SUCCESS) {
2231 			ret = RTW_PHL_STATUS_SUCCESS;
2232 			PHL_INFO("%s, disable wrole:%d(port:%d) sync from wrole(port:%d) success\n",
2233 				__func__, wr_sync_to->id, wr_sync_to->hw_port,
2234 				band_ctl->tsf_sync_port);
2235 		} else {
2236 			ret = RTW_PHL_STATUS_FAILURE;
2237 			PHL_ERR("%s, disable wrole:%d(port:%d) sync from wrole(port:%d) fail\n",
2238 				__func__, wr_sync_to->id, wr_sync_to->hw_port,
2239 				band_ctl->tsf_sync_port);
2240 		}
2241 
2242 		if (ap_num == 0)
2243 			band_ctl->tsf_sync_port = HW_PORT_MAX;
2244 		break;
2245 	default:
2246 		PHL_ERR("%s unsupport state(%d)\n", __func__, state);
2247 		ret = RTW_PHL_STATUS_FAILURE;
2248 		break;
2249 	}
2250 
2251 exit:
2252 #endif
2253 	return ret;
2254 }
2255 
2256 #ifdef RTW_WKARD_ISSUE_NULL_SLEEP_PROTECTION
2257 #define ISSUE_NULL_TIME 50
2258 #endif
2259 
2260 struct mr_scan_chctx {
2261 	struct rtw_chan_def *chandef;
2262 	u8 role_map_ps;/*STA, MESH*/
2263 	u8 role_map_ap;
2264 };
2265 enum rtw_phl_status
phl_mr_offch_hdl(struct phl_info_t * phl_info,struct rtw_wifi_role_t * wrole,bool off_ch,void * obj_priv,u8 (* issue_null_data)(void * priv,u8 ridx,bool ps))2266 phl_mr_offch_hdl(struct phl_info_t *phl_info,
2267 		 struct rtw_wifi_role_t *wrole,
2268 		 bool off_ch,
2269 		 void *obj_priv,
2270 		 u8 (*issue_null_data)(void *priv, u8 ridx, bool ps))
2271 {
2272 	enum rtw_phl_status psts = RTW_PHL_STATUS_SUCCESS;
2273 #ifdef CONFIG_MR_SUPPORT
2274 	struct rtw_phl_com_t *phl_com = wrole->phl_com;
2275 	struct mr_ctl_t *mr_ctl = phlcom_to_mr_ctrl(phl_com);
2276 	u8 hw_band = wrole->hw_band;
2277 	struct hw_band_ctl_t *band_ctrl = &(mr_ctl->band_ctrl[hw_band]);
2278 	void *drv = phl_to_drvpriv(phl_info);
2279 	struct rtw_chan_ctx *chanctx = NULL;
2280 	struct rtw_wifi_role_t *wr = NULL;
2281 	struct mr_scan_chctx mctx = {0};
2282 	int ctx_num = 0;
2283 	u8 ridx = 0;
2284 	u8 cur_ch = rtw_hal_get_cur_ch(phl_info->hal, hw_band);
2285 	bool found = false;
2286 
2287 	PHL_TRACE(COMP_PHL_DBG, _PHL_INFO_, "%s: wrole->id(%d, off_ch(%d)\n",
2288 		  __func__, wrole->id, off_ch);
2289 	ctx_num = phl_mr_get_chanctx_num(phl_info, band_ctrl);
2290 
2291 	if (ctx_num == 0){
2292 		PHL_DBG("ctx_num == 0!\n");
2293 		return psts;
2294 	}
2295 
2296 	_os_spinlock(drv, &band_ctrl->chan_ctx_queue.lock, _ps, NULL);
2297 	phl_list_for_loop(chanctx, struct rtw_chan_ctx, &band_ctrl->chan_ctx_queue.queue, list) {
2298 		/* Find the chanctx same as the current channel */
2299 		if(chanctx->chan_def.chan != cur_ch){
2300 			continue;
2301 		}
2302 		PHL_INFO("%s current chanctx found!\n", __FUNCTION__);
2303 		mctx.chandef = &chanctx->chan_def;
2304 		found = true;
2305 
2306 		for (ridx = 0; ridx < MAX_WIFI_ROLE_NUMBER; ridx++) {
2307 			if (chanctx->role_map & BIT(ridx)) {
2308 				wr = &phl_com->wifi_roles[ridx];
2309 				if(wr->mstate != MLME_LINKED)
2310 					continue;
2311 				if (wr->type == PHL_RTYPE_STATION || wr->type == PHL_RTYPE_MESH || wr->type == PHL_RTYPE_TDLS){
2312 					PHL_INFO("WR-ID:%d, STA found\n", ridx);
2313 					mctx.role_map_ps |= BIT(ridx);
2314 				}
2315 				else if (wr->type == PHL_RTYPE_AP || wr->type == PHL_RTYPE_VAP || wr->type == PHL_RTYPE_MESH){
2316 					PHL_INFO("WR-ID:%d, AP found\n", ridx);
2317 					mctx.role_map_ap |= BIT(ridx);
2318 				}
2319 			}
2320 		}
2321 	}
2322 	_os_spinunlock(drv, &band_ctrl->chan_ctx_queue.lock, _ps, NULL);
2323 
2324 	if(!found){
2325 		PHL_WARN("No chanctx is the same as current channel!\n");
2326 		return psts;
2327 	}
2328 
2329 	for (ridx = 0; ridx < MAX_WIFI_ROLE_NUMBER; ridx++) {
2330 		if ((mctx.role_map_ap) && (mctx.role_map_ap & BIT(ridx))) {
2331 			wr = &phl_com->wifi_roles[ridx];
2332 
2333 			if(((TEST_STATUS_FLAG(wr->status, WR_STATUS_BCN_STOP)) && off_ch) ||
2334 			   ((!TEST_STATUS_FLAG(wr->status, WR_STATUS_BCN_STOP)) && !off_ch))
2335 				continue;
2336 			if(off_ch){
2337 				rtw_hal_beacon_stop(phl_info->hal, wr, off_ch);
2338 				SET_STATUS_FLAG(wr->status, WR_STATUS_BCN_STOP);
2339 			}
2340 			else{
2341 				rtw_hal_beacon_stop(phl_info->hal, wr, off_ch);
2342 				CLEAR_STATUS_FLAG(wr->status, WR_STATUS_BCN_STOP);
2343 			}
2344 
2345 		}
2346 		/* issue null-data on current channel */
2347 		if ((mctx.role_map_ps) && (mctx.role_map_ps & BIT(ridx))) {
2348 			wr = &phl_com->wifi_roles[ridx];
2349 			if(issue_null_data == NULL){
2350 				PHL_ERR("WR-ID:%d, issue null_data function not found\n", ridx);
2351 				continue;
2352 			}
2353 
2354 			if(((TEST_STATUS_FLAG(wr->status, WR_STATUS_PS_ANN)) && off_ch) ||
2355 			   ((!TEST_STATUS_FLAG(wr->status, WR_STATUS_PS_ANN)) && !off_ch))
2356 				continue;
2357 
2358 			if (issue_null_data(obj_priv, ridx, off_ch) != _SUCCESS) {
2359 				PHL_ERR("WR-ID:%d, issue null_data failed\n", ridx);
2360 				_os_warn_on(1);
2361 				psts = RTW_PHL_STATUS_FAILURE;
2362 			}
2363 			else{
2364 				if(off_ch)
2365 					SET_STATUS_FLAG(wr->status, WR_STATUS_PS_ANN);
2366 				else
2367 					CLEAR_STATUS_FLAG(wr->status, WR_STATUS_PS_ANN);
2368 #ifdef RTW_WKARD_ISSUE_NULL_SLEEP_PROTECTION
2369 				if(off_ch)
2370 					_os_sleep_ms(phl_to_drvpriv(phl_info), ISSUE_NULL_TIME);
2371 #endif
2372 			}
2373 
2374 		}
2375 	}
2376 #else
2377 	if ((wrole->type == PHL_RTYPE_STATION || wrole->type == PHL_RTYPE_TDLS) && wrole->mstate == MLME_LINKED) {
2378 		if (issue_null_data && issue_null_data(obj_priv, wrole->id, off_ch) != _SUCCESS) {
2379 			PHL_ERR("WR-ID:%d, issue null_data failed\n", wrole->id);
2380 			_os_warn_on(1);
2381 			psts = RTW_PHL_STATUS_FAILURE;
2382 		}else{
2383 #ifdef RTW_WKARD_ISSUE_NULL_SLEEP_PROTECTION
2384 			if(off_ch)
2385 				_os_sleep_ms(phl_to_drvpriv(phl_info), ISSUE_NULL_TIME);
2386 #endif
2387 		}
2388 
2389 	} else if (wrole->type == PHL_RTYPE_AP) {
2390 		rtw_hal_beacon_stop(phl_info->hal, wrole, off_ch);
2391 	}
2392 #endif
2393 	return psts;
2394 }
2395 
2396 #ifdef CONFIG_FSM
2397 enum rtw_phl_status
rtw_phl_mr_offch_hdl(void * phl,struct rtw_wifi_role_t * wrole,bool off_ch,void * obj_priv,u8 (* issue_null_data)(void * priv,u8 ridx,bool ps),struct rtw_chan_def * chandef)2398 rtw_phl_mr_offch_hdl(void *phl,
2399 		     struct rtw_wifi_role_t *wrole,
2400 		     bool off_ch,
2401 		     void *obj_priv,
2402 		     u8 (*issue_null_data)(void *priv, u8 ridx, bool ps),
2403 		     struct rtw_chan_def *chandef)
2404 {
2405 	struct phl_info_t *phl_info = (struct phl_info_t *)phl;
2406 	enum rtw_phl_status psts = RTW_PHL_STATUS_SUCCESS;
2407 	u8 hw_band = wrole->hw_band;
2408 	u8 cur_ch = rtw_hal_get_cur_ch(phl_info->hal, hw_band);
2409 
2410 	if(off_ch){
2411 		if(chandef->chan != cur_ch)
2412 			psts = phl_mr_offch_hdl(phl_info,
2413 						wrole,
2414 						off_ch,
2415 						obj_priv,
2416 						issue_null_data);
2417 	}
2418 	else{
2419 		psts = phl_mr_offch_hdl(phl_info,
2420 					wrole,
2421 					off_ch,
2422 					obj_priv,
2423 					issue_null_data);
2424 	}
2425 
2426 	return psts;
2427 }
2428 #endif
2429 
phl_mr_stop_all_beacon(struct phl_info_t * phl_info,struct rtw_wifi_role_t * wrole,bool stop)2430 void phl_mr_stop_all_beacon(struct phl_info_t *phl_info,
2431 			    struct rtw_wifi_role_t *wrole,
2432 			    bool stop)
2433 {
2434 	struct rtw_phl_com_t *phl_com = phl_info->phl_com;
2435 	struct mr_ctl_t *mr_ctl = phlcom_to_mr_ctrl(phl_com);
2436 	struct hw_band_ctl_t *band_ctrl = &(mr_ctl->band_ctrl[wrole->hw_band]);
2437 	u8 role_map = band_ctrl->role_map;
2438 	struct rtw_wifi_role_t *wr = NULL;
2439 	u8 ridx;
2440 
2441 	for (ridx = 0; ridx < MAX_WIFI_ROLE_NUMBER; ridx++) {
2442 		if (role_map & BIT(ridx)) {
2443 			wr = &(phl_com->wifi_roles[ridx]);
2444 
2445 			if((wr->type == PHL_RTYPE_AP) ||
2446 			   (wr->type == PHL_RTYPE_VAP) ||
2447 			   (wr->type == PHL_RTYPE_P2P_GO) ||
2448 			   (wr->type == PHL_RTYPE_MESH)){
2449 				if(((TEST_STATUS_FLAG(wr->status, WR_STATUS_BCN_STOP)) && stop) ||
2450 				   ((!TEST_STATUS_FLAG(wr->status, WR_STATUS_BCN_STOP)) && !stop))
2451 					continue;
2452 
2453 				rtw_hal_beacon_stop(phl_info->hal, wr, stop);
2454 
2455 				if(stop)
2456 					SET_STATUS_FLAG(wr->status, WR_STATUS_BCN_STOP);
2457 				else
2458 					CLEAR_STATUS_FLAG(wr->status, WR_STATUS_BCN_STOP);
2459 			}
2460 		}
2461 	}
2462 }
2463 
2464 #ifdef DBG_PHL_MR
2465 enum rtw_phl_status
phl_mr_info_dbg(struct phl_info_t * phl_info)2466 phl_mr_info_dbg(struct phl_info_t *phl_info)
2467 {
2468 	struct rtw_phl_com_t *phl_com = phl_info->phl_com;
2469 	struct mr_ctl_t *mr_ctl = phlcom_to_mr_ctrl(phl_com);
2470 	u8 ridx = MAX_WIFI_ROLE_NUMBER;
2471 	u8 bidx = 0;
2472 	int chanctx_num = 0;
2473 	struct rtw_wifi_role_t *role = NULL;
2474 	struct hw_band_ctl_t *band_ctrl = NULL;
2475 
2476 	for (ridx = 0; ridx < MAX_WIFI_ROLE_NUMBER; ridx++) {
2477 		role = &(phl_com->wifi_roles[ridx]);
2478 		if (role->assoc_sta_queue.cnt) {
2479 			PHL_DUMP_STACTRL_EX(phl_info);
2480 			PHL_ERR("role_idx:%d assoc_sta_queue(%d) not empty!\n",
2481 				ridx, role->assoc_sta_queue.cnt);
2482 			_os_warn_on(1);
2483 		}
2484 	}
2485 	for (bidx = 0; bidx < MAX_BAND_NUM; bidx++) {
2486 		band_ctrl = &(mr_ctl->band_ctrl[bidx]);
2487 		chanctx_num = phl_mr_get_chanctx_num(phl_info, band_ctrl);
2488 		if (chanctx_num)
2489 			PHL_ERR("band_idx:%d chanctx_num(%d) not empty!\n", bidx, chanctx_num);
2490 	}
2491 
2492 	return RTW_PHL_STATUS_SUCCESS;
2493 }
2494 #endif
2495 
2496 #if defined(CONFIG_PHL_P2PPS) && defined(CONFIG_MCC_SUPPORT)
_noa_desc_to_mcc_limit_req_info(struct rtw_phl_noa_desc * noa_desc,struct phl_mcc_dur_lim_req_info * limit_req_info)2497 static void _noa_desc_to_mcc_limit_req_info(struct rtw_phl_noa_desc *noa_desc,
2498 	struct phl_mcc_dur_lim_req_info *limit_req_info)
2499 {
2500 	if (noa_desc->enable && (noa_desc->tag != P2PPS_TRIG_MCC)) {
2501 		/* limited by NoA */
2502 		limit_req_info->tag = RTW_MCC_DUR_LIM_NOA;
2503 		limit_req_info->enable = true;
2504 		limit_req_info->start_t_h = noa_desc->start_t_h;
2505 		limit_req_info->start_t_l = noa_desc->start_t_l;
2506 		limit_req_info->dur = noa_desc->duration;
2507 		limit_req_info->intvl = noa_desc->interval;
2508 	} else {
2509 		/* No limit for NoA disable */
2510 		limit_req_info->tag = RTW_MCC_DUR_LIM_NONE;
2511 		limit_req_info->enable = false;
2512 	}
2513 }
2514 #endif
2515 #ifdef CONFIG_MCC_SUPPORT
2516 
2517 /*
2518  * check all role state
2519  * Output: True: can enabe TDMRA, False: can't enable TDMRA
2520  */
_mr_tdmra_role_state_check(struct phl_info_t * phl,enum phl_band_idx band_idx)2521 static bool _mr_tdmra_role_state_check(struct phl_info_t *phl,
2522 				enum phl_band_idx band_idx)
2523 {
2524 	struct rtw_wifi_role_t *wr = NULL;
2525 	u8 ridx = INVALID_WIFI_ROLE_IDX, role_map = 0;
2526 
2527 	role_map = phl_get_chanctx_rolemap(phl, band_idx);
2528 	for (ridx = 0; ridx < MAX_WIFI_ROLE_NUMBER; ridx++) {
2529 		if (!(role_map & BIT(ridx)))
2530 			continue;
2531 		wr = &(phl->phl_com->wifi_roles[ridx]);
2532 		if (MLME_LINKED != wr->mstate) {
2533 			PHL_TRACE(COMP_PHL_MCC, _PHL_WARNING_, "%s: MLME_LINKED != wr->mstate, we can't enable tdmra now, ridx(%d), type(%d), mstate(%d)\n",
2534 				__FUNCTION__, ridx, wr->type, wr->mstate);
2535 			return false;
2536 		}
2537 		if (phl_role_is_client_category(wr)) {
2538 			if (!TEST_STATUS_FLAG(wr->status, WR_STATUS_TSF_SYNC)) {
2539 				PHL_TRACE(COMP_PHL_MCC, _PHL_WARNING_, "%s: Test WR_STATUS_TSF_SYNC fail, we can't enable tdmra now, ridx(%d), type(%d), status(%d)\n",
2540 					__FUNCTION__, ridx, wr->type,
2541 					wr->status);
2542 				return false;
2543 			}
2544 		}
2545 	}
2546 	return true;
2547 }
2548 
_mr_role_is_in_tdmra_chctx_q(struct phl_info_t * phl_info,struct rtw_wifi_role_t * wr)2549 static bool _mr_role_is_in_tdmra_chctx_q
2550 		(struct phl_info_t *phl_info, struct rtw_wifi_role_t *wr)
2551 {
2552 	bool ret = false;
2553 	struct rtw_phl_com_t *phl_com = phl_info->phl_com;
2554 	struct mr_ctl_t *mr_ctl = phlcom_to_mr_ctrl(phl_com);
2555 	void *drv = phl_to_drvpriv(phl_info);
2556 	struct hw_band_ctl_t *band_ctrl = NULL;
2557 	struct rtw_chan_ctx *chanctx = NULL;
2558 	_os_list *chan_ctx_list = NULL;
2559 	u8 role_map = 0;
2560 
2561 	if (wr == NULL)
2562 		goto exit;
2563 
2564 	band_ctrl = &(mr_ctl->band_ctrl[wr->hw_band]);
2565 	chan_ctx_list = &band_ctrl->chan_ctx_queue.queue;
2566 
2567 	/* find wr is under existed chanctx durin TDMRA */
2568 	_os_spinlock(drv, &band_ctrl->chan_ctx_queue.lock, _ps, NULL);
2569 	phl_list_for_loop(chanctx, struct rtw_chan_ctx, chan_ctx_list, list) {
2570 		role_map = chanctx->role_map;
2571 		if (role_map & BIT(wr->id)) {
2572 			ret = true;
2573 			break;
2574 		}
2575 	}
2576 	_os_spinunlock(drv, &band_ctrl->chan_ctx_queue.lock, _ps, NULL);
2577 exit:
2578 	return ret;
2579 }
2580 
_mr_tdmra_need(struct phl_info_t * phl_info,enum phl_band_idx band_idx,u8 * ap_role_idx)2581 static bool _mr_tdmra_need(struct phl_info_t *phl_info,
2582 				enum phl_band_idx band_idx, u8 *ap_role_idx)
2583 {
2584 	struct rtw_phl_com_t *phl_com = phl_info->phl_com;
2585 	struct mr_ctl_t *mr_ctl = phlcom_to_mr_ctrl(phl_com);
2586 	struct hw_band_ctl_t *band_ctrl = &(mr_ctl->band_ctrl[band_idx]);
2587 	struct mr_info *cur_info = &band_ctrl->cur_info;
2588 	u8 role_map = band_ctrl->role_map;
2589 	struct rtw_wifi_role_t *wr = NULL, *ap_wr = NULL;
2590 	struct rtw_chan_def *chandef = NULL;
2591 	int ctx_num = 0;
2592 	u8 ridx;
2593 	u8 tdmra_need = false;
2594 
2595 	if (phl_com->dev_cap.mcc_sup == false) {
2596 		PHL_INFO("%s: don't support MCC\n", __func__);
2597 		tdmra_need = false;
2598 		goto exit;
2599 	}
2600 
2601 	ctx_num = phl_mr_get_chanctx_num(phl_info, band_ctrl);
2602 	if (ctx_num == 0)
2603 		goto exit;
2604 
2605 	PHL_INFO("[MR]%s: band_idx=%d,ctx_num=%d,ap_num=%d,op_mode=%d\n",
2606 		__func__, band_idx, ctx_num, cur_info->ap_num, band_ctrl->op_mode);
2607 	if (ctx_num == 1) {
2608 		if (cur_info->ap_num == 1) {
2609 			/* only for sole AP, check op mode */
2610 			if (band_ctrl->op_mode == MR_OP_NON) {
2611 				/* find sole AP */
2612 				for (ridx = 0; ridx < MAX_WIFI_ROLE_NUMBER; ridx++) {
2613 					if (role_map & BIT(ridx)) {
2614 						wr = &(phl_com->wifi_roles[ridx]);
2615 						if (wr->type == PHL_RTYPE_AP && wr->mstate == MLME_LINKED) {
2616 							ap_wr = wr;
2617 							*ap_role_idx = ap_wr->id;
2618 							break;
2619 						}
2620 					}
2621 				}
2622 
2623 				chandef = &wr->chandef;
2624 				/* enable tdmra for 2.4G sole AP */
2625 				if (rtw_hal_get_btc_req_slot(phl_info->hal) > 0
2626 					&& chandef->band == BAND_ON_24G) {
2627 					tdmra_need = true;
2628 				} else {
2629 					tdmra_need = false;
2630 				}
2631 			} else {
2632 				/* SCC case */
2633 				tdmra_need = false;
2634 			}
2635 		} else {
2636 			if (rtw_hal_get_btc_req_slot(phl_info->hal) > 0)
2637 				PHL_INFO("[MR]%s: Do not support for nonAP + BT in one ch ctx\n", __func__);
2638 
2639 			tdmra_need = false;
2640 		}
2641 	} else if (ctx_num == 2) {
2642 		tdmra_need = true;
2643 	} else {
2644 		PHL_INFO("[MR]%s: Do not support ctx_num(%d)\n",
2645 			__func__, ctx_num);
2646 	}
2647 exit:
2648 	PHL_TRACE(COMP_PHL_DBG, _PHL_INFO_, "<<< %s: tdmra_need(%d)\n",
2649 		__func__, tdmra_need);
2650 	return tdmra_need;
2651 }
2652 
2653 /* find any existed role */
_mr_find_existed_role(struct phl_info_t * phl_info,enum phl_band_idx band_idx)2654 struct rtw_wifi_role_t *_mr_find_existed_role(struct phl_info_t *phl_info,
2655 							enum phl_band_idx band_idx)
2656 {
2657 	struct rtw_phl_com_t *phl_com = phl_info->phl_com;
2658 	struct rtw_wifi_role_t *wr = NULL;
2659 	u8 role_map;
2660 	u8 ridx = 0;
2661 
2662 	role_map = phl_get_chanctx_rolemap(phl_info, band_idx);
2663 	for (ridx = 0; ridx < MAX_WIFI_ROLE_NUMBER; ridx++) {
2664 		if (role_map & BIT(ridx)) {
2665 			wr = &phl_com->wifi_roles[ridx];
2666 			break;
2667 		}
2668 	}
2669 
2670 	return wr;
2671 }
2672 
_phl_mr_tdmra_disable(struct phl_info_t * phl_info,struct rtw_wifi_role_t * cur_wrole,enum phl_band_idx band_idx)2673 enum rtw_phl_status _phl_mr_tdmra_disable(struct phl_info_t *phl_info,
2674 			struct rtw_wifi_role_t *cur_wrole, enum phl_band_idx band_idx)
2675 {
2676 	enum rtw_phl_status psts = RTW_PHL_STATUS_SUCCESS;
2677 	struct rtw_wifi_role_t *spec_role = NULL;
2678 
2679 	if (!rtw_phl_mcc_inprogress(phl_info, band_idx)) {
2680 		psts = RTW_PHL_STATUS_SUCCESS;
2681 		goto exit;
2682 	} else {
2683 		/* find existed tdmra role */
2684 		spec_role = _mr_find_existed_role(phl_info, band_idx);
2685 		if (spec_role == NULL) {
2686 			PHL_ERR("%s: find no tdmra role for tdmra disable\n", __func__);
2687 			psts = RTW_PHL_STATUS_FAILURE;
2688 			goto exit;
2689 		}
2690 	}
2691 
2692 	if (cur_wrole == NULL) {
2693 		/* check wrole is null or not */
2694 		psts = rtw_phl_tdmra_disable(phl_info, spec_role);
2695 	} else {
2696 		/* check wrole is in chan ctx queue */
2697 		if (_mr_role_is_in_tdmra_chctx_q(phl_info, cur_wrole))
2698 			psts = rtw_phl_tdmra_disable(phl_info, cur_wrole);
2699 		else
2700 			psts = rtw_phl_tdmra_disable(phl_info, spec_role);
2701 	}
2702 
2703 exit:
2704 	return psts;
2705 }
2706 
2707 /*
2708  * Handle MR coex mechanism for 2g_1ap_btc, mcc, mcc_btc
2709  * Specific concurrent mode : 2g ap category x1 + BTC, MCC, MCC + BTC
2710  * @handle: True: handle specific concurrent mode for all interfaces; False: Not handleand maybe handle it by other coex mechanism.
2711  */
2712 enum rtw_phl_status
_phl_mr_tdmra_handle(struct phl_info_t * phl_info,struct rtw_wifi_role_t * cur_wrole,u16 slot,enum phl_band_idx band_idx,enum mr_coex_trigger trgger,enum mr_coex_mode * coex_mode)2713 _phl_mr_tdmra_handle(struct phl_info_t *phl_info,
2714 				struct rtw_wifi_role_t *cur_wrole, u16 slot,
2715 				enum phl_band_idx band_idx,
2716 				enum mr_coex_trigger trgger,
2717 				enum mr_coex_mode *coex_mode)
2718 {
2719 	struct rtw_phl_com_t *phl_com = phl_info->phl_com;
2720 	struct phl_tdmra_dur_change_info info = {0};
2721 	bool tdmra_inprogress = false, tdmra_need = false;
2722 	u8 ap_role_id = INVALID_WIFI_ROLE_IDX;
2723 	enum rtw_phl_status psts = RTW_PHL_STATUS_SUCCESS;
2724 	struct rtw_wifi_role_t * existed_role = NULL;
2725 
2726 	PHL_TRACE(COMP_PHL_DBG, _PHL_INFO_, ">>> %s: slot(%d), band_idx(%d), trgger(%d)\n",
2727 		__func__, slot, band_idx, trgger);
2728 	if (!_mr_tdmra_role_state_check(phl_info, band_idx)) {
2729 		PHL_TRACE(COMP_PHL_DBG, _PHL_WARNING_, "%s: Fail to check role state\n",
2730 			__func__);
2731 		goto exit;
2732 	}
2733 	tdmra_inprogress =  rtw_phl_mcc_inprogress(phl_info, band_idx);
2734 	tdmra_need = _mr_tdmra_need(phl_info, band_idx, &ap_role_id);
2735 	if (tdmra_need) {
2736 		switch (trgger){
2737 		case MR_COEX_TRIG_BY_BT:
2738 			if (tdmra_inprogress) {
2739 				/* update TDMRA (if TDMRAing) */
2740 				info.bt_role = true;
2741 				info.hw_band = band_idx;
2742 				/* find existed tdmra role */
2743 				info.role = _mr_find_existed_role(phl_info, band_idx);
2744 				info.dur = slot;
2745 				if (info.role != NULL)
2746 					psts = rtw_phl_tdmra_duration_change(phl_info, &info);
2747 				else
2748 					PHL_ERR("%s: find no tdmra role for tdmra duration change\n", __func__);
2749 			} else {
2750 				/* enable TDMRA under solo AP (no TDMRA) */
2751 				if (ap_role_id < INVALID_WIFI_ROLE_IDX) {
2752 					*coex_mode = MR_COEX_MODE_TDMRA;
2753 					psts = rtw_phl_tdmra_enable(phl_info, &phl_com->wifi_roles[ap_role_id]);
2754 				} else {
2755 					PHL_ERR("%s: Do not find solo AP\n", __func__);
2756 				}
2757 			}
2758 			break;
2759 		case MR_COEX_TRIG_BY_LINKING:
2760 			/* enable TDMRA (for link flow) */
2761 			if (cur_wrole != NULL) {
2762 				*coex_mode = MR_COEX_MODE_TDMRA;
2763 				phl_mr_stop_all_beacon(phl_info, cur_wrole, false);
2764 				psts = rtw_phl_tdmra_enable(phl_info, cur_wrole);
2765 			} else {
2766 				PHL_ERR("%s: cur_wrole = NULL, check code flow\n", __func__);
2767 			}
2768 			break;
2769 		case MR_COEX_TRIG_BY_DIS_LINKING:
2770 			*coex_mode = MR_COEX_MODE_TDMRA;
2771 			/* find any existed role to trigger TDMRA */
2772 			existed_role = _mr_find_existed_role(phl_info, band_idx);
2773 			psts = rtw_phl_tdmra_enable(phl_info, existed_role);
2774 			break;
2775 		case MR_COEX_TRIG_BY_CHG_SLOT:
2776 			if (tdmra_inprogress) {
2777 				/* update TDMRA (if TDMRAing) */
2778 				info.bt_role = false;
2779 				info.hw_band = band_idx;
2780 				/* find existed tdmra role */
2781 				info.role = _mr_find_existed_role(phl_info, band_idx);
2782 				info.dur = slot;
2783 				if (info.role != NULL)
2784 					psts = rtw_phl_tdmra_duration_change(phl_info, &info);
2785 				else
2786 					PHL_ERR("%s: find no tdmra role\n", __func__);
2787 			}
2788 			break;
2789 		case MR_COEX_TRIG_BY_SCAN:
2790 			*coex_mode = MR_COEX_MODE_TDMRA;
2791 			psts = rtw_phl_tdmra_enable(phl_info, cur_wrole);
2792 			break;
2793 		case MR_COEX_TRIG_BY_CHG_OP_CHDEF:
2794 			*coex_mode = MR_COEX_MODE_TDMRA;
2795 			psts = rtw_phl_tdmra_enable(phl_info, cur_wrole);
2796 			break;
2797 		default:
2798 			break;
2799 		}
2800 	} else {
2801 			/* disable TDMRA (if TDMRAing) */
2802 		if (*coex_mode == MR_COEX_MODE_TDMRA) {
2803 			psts = _phl_mr_tdmra_disable(phl_info, cur_wrole, band_idx);
2804 			if (psts != RTW_PHL_STATUS_SUCCESS)
2805 				PHL_ERR("%s: MR TDMRA disable fail\n", __func__);
2806 			else
2807 				*coex_mode = MR_COEX_MODE_NONE;
2808 		}
2809 	}
2810 exit:
2811 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "%s: coex_mode(%d), psts(%d)\n",
2812 		__func__, *coex_mode, psts);
2813 	return psts;
2814 }
2815 
2816 enum rtw_phl_status
phl_mr_mcc_query_role_time_slot_lim(struct phl_info_t * phl_info,struct rtw_wifi_role_t * wrole,struct phl_mcc_dur_lim_req_info * limit_req_info)2817 phl_mr_mcc_query_role_time_slot_lim (struct phl_info_t *phl_info, struct rtw_wifi_role_t *wrole,
2818 								struct phl_mcc_dur_lim_req_info *limit_req_info)
2819 {
2820 #ifdef CONFIG_PHL_P2PPS
2821 	struct rtw_phl_noa_desc noa_desc = {0};
2822 
2823 	/* limited by NoA */
2824 	phl_p2pps_query_noa_with_cnt255(phl_info, wrole, &noa_desc);
2825 	_noa_desc_to_mcc_limit_req_info(&noa_desc, limit_req_info);
2826 #else
2827 	/* No limit for NoA disable */
2828 	limit_req_info->tag = RTW_MCC_DUR_LIM_NONE;
2829 	limit_req_info->enable = false;
2830 #endif
2831 	return RTW_PHL_STATUS_SUCCESS;
2832 }
2833 #endif
2834 #ifdef CONFIG_PHL_P2PPS
2835 /* call by noa module for noa enable/disable */
phl_mr_noa_dur_lim_change(struct phl_info_t * phl_info,struct rtw_wifi_role_t * wrole,struct rtw_phl_noa_desc * noa_desc)2836 bool phl_mr_noa_dur_lim_change (struct phl_info_t *phl_info, struct rtw_wifi_role_t *wrole,
2837 								struct rtw_phl_noa_desc *noa_desc)
2838 {
2839 	u8 tdmra_inprogress = false, ctrl_by_tdmra = false, need_tdmra = false;
2840 #ifdef CONFIG_MCC_SUPPORT
2841 	struct phl_mcc_dur_lim_req_info lim_req = {0};
2842 	u8 ap_role_idx;
2843 #endif
2844 
2845 	tdmra_inprogress = rtw_phl_mcc_inprogress(phl_info, wrole->hw_band);
2846 
2847 	/* tdmra inprogress */
2848 	if (tdmra_inprogress) {
2849 		ctrl_by_tdmra = true;
2850 		#ifdef CONFIG_MCC_SUPPORT
2851 		/* under MCC, control by MCC module */
2852 		_noa_desc_to_mcc_limit_req_info(noa_desc, &lim_req);
2853 		rtw_phl_mcc_dur_lim_change(phl_info, wrole, &lim_req);
2854 		#endif
2855 	} else {
2856 		/*
2857 			tdmra not inprogress,
2858 			but will process tdmra if need_tdmra = true
2859 			then, tdmra will qurey NoA parameter
2860 		*/
2861 #ifdef CONFIG_MCC_SUPPORT
2862 		need_tdmra = _mr_tdmra_need(phl_info, wrole->hw_band, &ap_role_idx);
2863 #endif
2864 		if (need_tdmra)
2865 			ctrl_by_tdmra = true;
2866 		else
2867 			ctrl_by_tdmra = false;
2868 	}
2869 
2870 	return ctrl_by_tdmra;
2871 }
2872 #endif
2873 enum rtw_phl_status
phl_mr_info_upt(struct phl_info_t * phl_info,struct rtw_wifi_role_t * wrole)2874 phl_mr_info_upt(struct phl_info_t *phl_info, struct rtw_wifi_role_t *wrole)
2875 {
2876 	void *drv = phl_to_drvpriv(phl_info);
2877 	struct rtw_phl_com_t *phl_com = phl_info->phl_com;
2878 	struct mr_ctl_t *mr_ctl = phlcom_to_mr_ctrl(phl_com);
2879 	struct hw_band_ctl_t *band_ctrl = &(mr_ctl->band_ctrl[wrole->hw_band]);
2880 	u8 role_map = band_ctrl->role_map;
2881 	/*struct rtw_chan_ctx *chanctx = wrole->chanctx;
2882 	u8 role_map = chanctx->role_map;*/
2883 	struct rtw_wifi_role_t *wr = NULL;
2884 	u8 ridx;
2885 
2886 	_os_mem_set(drv, &band_ctrl->cur_info, 0, sizeof(struct mr_info));
2887 
2888 	for (ridx = 0; ridx < MAX_WIFI_ROLE_NUMBER; ridx++) {
2889 		if (role_map & BIT(ridx)) {
2890 			wr = &(phl_com->wifi_roles[ridx]);
2891 
2892 			switch (wr->type) {
2893 			case PHL_RTYPE_STATION:
2894 			case PHL_RTYPE_P2P_GC:
2895 			case PHL_RTYPE_P2P_DEVICE:
2896 			case PHL_RTYPE_TDLS:
2897 				band_ctrl->cur_info.sta_num++;
2898 				if (wr->mstate == MLME_LINKED)
2899 					band_ctrl->cur_info.ld_sta_num++;
2900 				if (wr->mstate == MLME_LINKING)
2901 					band_ctrl->cur_info.lg_sta_num++;
2902 				if (wr->type == PHL_RTYPE_P2P_GC)
2903 					band_ctrl->cur_info.p2p_gc_num++;
2904 				if (wr->type == PHL_RTYPE_P2P_DEVICE)
2905 					band_ctrl->cur_info.p2p_device_num++;
2906 			#ifdef CONFIG_PHL_TDLS
2907 				if (wr->type == PHL_RTYPE_TDLS)
2908 					band_ctrl->cur_info.ld_tdls_num++;
2909 			#endif
2910 				break;
2911 
2912 			case PHL_RTYPE_AP:
2913 			case PHL_RTYPE_VAP:
2914 			case PHL_RTYPE_P2P_GO:
2915 			case PHL_RTYPE_MESH:
2916 				if (wr->mstate == MLME_LINKED)
2917 					band_ctrl->cur_info.ap_num++;
2918 				if (wr->assoc_sta_queue.cnt >= 2)
2919 					band_ctrl->cur_info.ld_ap_num++;
2920 				if (wr->type == PHL_RTYPE_P2P_GO)
2921 					band_ctrl->cur_info.p2p_go_num++;
2922 				break;
2923 
2924 			case PHL_RTYPE_MONITOR:
2925 			default :
2926 				break;
2927 			}
2928 			#if 0
2929 			if (wr->type == PHL_RTYPE_STATION)
2930 				band_ctrl->cur_info.sta_num++;
2931 			else if (wr->type == PHL_RTYPE_AP || wr->type == PHL_RTYPE_VAP)
2932 				band_ctrl->cur_info.ap_num++;
2933 			else if (wr->type == PHL_RTYPE_ADHOC || wr->type == PHL_RTYPE_ADHOC_MASTER)
2934 			else if (wr->type == PHL_RTYPE_MESH)
2935 			else if (wr->type == PHL_RTYPE_MONITOR)
2936 			else if (wr->type == PHL_RTYPE_P2P_DEVICE)
2937 			else if (wr->type == PHL_RTYPE_P2P_GC)
2938 			else if (wr->type == PHL_RTYPE_P2P_GO)
2939 			else if (wr->type == PHL_RTYPE_TDLS)
2940 			else if (wr->type == PHL_RTYPE_NAN)
2941 			#endif
2942 		}
2943 	}
2944 	if(band_ctrl->op_mode == MR_OP_SCC ||
2945 	   band_ctrl->op_mode == MR_OP_MCC){
2946 		if(band_ctrl->cur_info.ld_sta_num && band_ctrl->cur_info.ap_num)
2947 			band_ctrl->op_type = MR_OP_TYPE_STATION_AP;
2948 		else if(band_ctrl->cur_info.ld_sta_num)
2949 			band_ctrl->op_type = MR_OP_TYPE_STATION_ONLY;
2950 		else
2951 			band_ctrl->op_type = MR_OP_TYPE_STATION_AP;
2952 	}
2953 	else{
2954 		band_ctrl->op_type = MR_OP_TYPE_NONE;
2955 	}
2956 	/*dump mr_info*/
2957 	PHL_INFO("%s sta_num:%d, ld_sta_num:%d, lg_sta_num:%d\n",
2958 		__func__, band_ctrl->cur_info.sta_num,
2959 		band_ctrl->cur_info.ld_sta_num, band_ctrl->cur_info.lg_sta_num);
2960 #ifdef CONFIG_PHL_TDLS
2961 	PHL_INFO("%s ld_tdls_num:%d\n", __func__, band_ctrl->cur_info.ld_tdls_num);
2962 #endif
2963 	PHL_INFO("%s ap_num:%d, ld_ap_num:%d\n",
2964 		__func__, band_ctrl->cur_info.ap_num, band_ctrl->cur_info.ld_ap_num);
2965 	PHL_INFO("%s op mode:%d op type:%d\n",
2966 		__func__, band_ctrl->op_mode, band_ctrl->op_type);
2967 	return RTW_PHL_STATUS_SUCCESS;
2968 }
2969 
2970 enum rtw_phl_status
phl_mr_state_upt(struct phl_info_t * phl_info,struct rtw_wifi_role_t * wrole)2971 phl_mr_state_upt(struct phl_info_t *phl_info, struct rtw_wifi_role_t *wrole)
2972 {
2973 	enum rtw_phl_status psts = RTW_PHL_STATUS_SUCCESS;
2974 #ifdef CONFIG_MR_SUPPORT
2975 	bool mcc_en = false;
2976 	struct rtw_phl_com_t *phl_com = phl_info->phl_com;
2977 	struct mr_ctl_t *mr_ctl = phlcom_to_mr_ctrl(phl_com);
2978 	struct hw_band_ctl_t *band_ctrl = &(mr_ctl->band_ctrl[wrole->hw_band]);
2979 	int chanctx_num = 0;
2980 
2981 	chanctx_num = phl_mr_get_chanctx_num(phl_info, band_ctrl);
2982 	PHL_INFO("%s chanctx_num:%d\n", __func__, chanctx_num);
2983 
2984 	if (chanctx_num == 2) {
2985 		/*MR - MCC section*/
2986 		mcc_en = (wrole->mstate == MLME_LINKED) ? true : false;
2987 		if(mcc_en == false)
2988 			phl_mr_check_ecsa_cancel(phl_info, wrole);
2989 	}
2990 #ifdef CONFIG_MCC_SUPPORT
2991 	/* Enable MR coex mechanism(if needed) */
2992 	psts = phl_mr_coex_handle(phl_info, wrole, 0, wrole->hw_band, MR_COEX_TRIG_BY_LINKING);
2993 	if (psts != RTW_PHL_STATUS_SUCCESS) {
2994 		PHL_ERR("%s: MR coex handle fail(%d)\n", __func__, psts);
2995 		goto exit;
2996 	}
2997 #endif /* CONFIG_MCC_SUPPORT */
2998 #ifdef CONFIG_PHL_P2PPS
2999 	/* Process NOA */
3000 	phl_p2pps_noa_all_role_resume(phl_info, wrole->hw_band);
3001 #endif
3002 
3003 	if(psts == RTW_PHL_STATUS_SUCCESS && mcc_en)
3004 		phl_mr_check_ecsa(phl_info, wrole);
3005 
3006 exit:
3007 #endif
3008 	return psts;
3009 }
3010 
phl_mr_watchdog(struct phl_info_t * phl_info)3011 enum rtw_phl_status phl_mr_watchdog(struct phl_info_t *phl_info)
3012 {
3013 	enum rtw_phl_status psts = RTW_PHL_STATUS_SUCCESS;
3014 #if defined(CONFIG_MR_SUPPORT) &&  defined(CONFIG_MCC_SUPPORT)
3015 	struct rtw_phl_com_t *phl_com = phl_info->phl_com;
3016 	struct mr_ctl_t *mr_ctl = phlcom_to_mr_ctrl(phl_com);
3017 	u8 band_idx = 0;
3018 	int chanctx_num = 0;
3019 	struct hw_band_ctl_t *band_ctrl = NULL;
3020 	#if 0
3021 	struct rtw_chan_ctx *chanctx = NULL;
3022 	void *drv = phl_to_drvpriv(phl_info);
3023 	struct rtw_wifi_role_t *wr = NULL;
3024 	#endif
3025 
3026 	for (band_idx = 0; band_idx < MAX_BAND_NUM; band_idx++) {
3027 		band_ctrl = &(mr_ctl->band_ctrl[band_idx]);
3028 		chanctx_num = phl_mr_get_chanctx_num(phl_info, band_ctrl);
3029 		if (chanctx_num == 0)
3030 			continue;
3031 
3032 		#if 0
3033 		_os_spinlock(drv, &band_ctrl->chan_ctx_queue.lock, _ps, NULL);
3034 		phl_list_for_loop(chanctx, struct rtw_chan_ctx, &band_ctrl->chan_ctx_queue.queue, list) {
3035 			for (ridx = 0; ridx < MAX_WIFI_ROLE_NUMBER; ridx++) {
3036 				if (chanctx->role_map & BIT(ridx)) {
3037 					wr = &phl_com->wifi_roles[ridx];
3038 					if(wr->type == PHL_RTYPE_STATION) {
3039 						/*Sounding check*/
3040 						/*phl_snd_watchdog(phl_info, wr);*/
3041 					}
3042 				}
3043 			}
3044 		}
3045 		_os_spinunlock(drv, &band_ctrl->chan_ctx_queue.lock, _ps, NULL);
3046 		#endif
3047 
3048 		if (chanctx_num == 2)
3049 			rtw_phl_mcc_watchdog(phl_info, band_idx);
3050 	}
3051 #endif /*CONFIG_MCC_SUPPORT*/
3052 	return psts;
3053 }
3054 
3055 static inline u8
__phl_mr_process(struct rtw_wifi_role_t * wrole,u8 role_map,bool exclude_self,void * data,u8 (* ops_func)(struct rtw_wifi_role_t * wrole,void * data))3056 __phl_mr_process(struct rtw_wifi_role_t *wrole,
3057 		u8 role_map, bool exclude_self, void *data,
3058 		u8(*ops_func)(struct rtw_wifi_role_t *wrole, void *data))
3059 {
3060 	u8 ridx = 0;
3061 	u8 ret = 0;
3062 	struct rtw_phl_com_t *phl_com = wrole->phl_com;
3063 	struct rtw_wifi_role_t *wr = NULL;
3064 
3065 	for (ridx = 0; ridx < MAX_WIFI_ROLE_NUMBER; ridx++) {
3066 		if (role_map & BIT(ridx)) {
3067 			wr = &phl_com->wifi_roles[ridx];
3068 			_os_warn_on(!wr->active);
3069 			if ((exclude_self) && (wr == wrole))
3070 				continue;
3071 			if (ops_func)
3072 				if (true == ops_func(wr, data))
3073 					ret++;
3074 		}
3075 	}
3076 	return ret;
3077 }
3078 
_phl_mr_process_by_mrc(struct phl_info_t * phl_info,struct rtw_wifi_role_t * wrole,bool exclude_self,void * data,u8 (* ops_func)(struct rtw_wifi_role_t * wrole,void * data))3079 static u8 _phl_mr_process_by_mrc(struct phl_info_t *phl_info,
3080 		struct rtw_wifi_role_t *wrole, bool exclude_self, void *data,
3081 		u8(*ops_func)(struct rtw_wifi_role_t *wrole, void *data))
3082 {
3083 	struct mr_ctl_t *mr_ctl = phlcom_to_mr_ctrl(wrole->phl_com);
3084 
3085 	return __phl_mr_process(wrole, mr_ctl->role_map, exclude_self, data, ops_func);
3086 }
3087 
_phl_mr_process_by_band(struct phl_info_t * phl_info,struct rtw_wifi_role_t * wrole,bool exclude_self,void * data,u8 (* ops_func)(struct rtw_wifi_role_t * wrole,void * data))3088 static u8 _phl_mr_process_by_band(struct phl_info_t *phl_info,
3089 		struct rtw_wifi_role_t *wrole, bool exclude_self, void *data,
3090 		u8(*ops_func)(struct rtw_wifi_role_t *wrole, void *data))
3091 {
3092 	struct mr_ctl_t *mr_ctl = phlcom_to_mr_ctrl(wrole->phl_com);
3093 	struct hw_band_ctl_t *band_ctrl = &(mr_ctl->band_ctrl[wrole->hw_band]);
3094 
3095 	return __phl_mr_process(wrole, band_ctrl->role_map, exclude_self, data, ops_func);
3096 }
3097 
_phl_mr_process_by_chctx(struct phl_info_t * phl_info,struct rtw_wifi_role_t * wrole,bool exclude_self,void * data,u8 (* ops_func)(struct rtw_wifi_role_t * wrole,void * data))3098 static u8 _phl_mr_process_by_chctx(struct phl_info_t *phl_info,
3099 		struct rtw_wifi_role_t *wrole, bool exclude_self, void *data,
3100 		u8(*ops_func)(struct rtw_wifi_role_t *wrole, void *data))
3101 {
3102 	struct rtw_chan_ctx *chanctx = wrole->chanctx;
3103 
3104 	if (!chanctx)
3105 		return 0;
3106 	return __phl_mr_process(wrole, chanctx->role_map, exclude_self, data, ops_func);
3107 }
3108 
_phl_mr_process(struct phl_info_t * phl_info,struct rtw_wifi_role_t * wrole,bool exclude_self,void * data,u8 (* ops_func)(struct rtw_wifi_role_t * wrole,void * data))3109 static u8 _phl_mr_process(struct phl_info_t *phl_info,
3110 		struct rtw_wifi_role_t *wrole, bool exclude_self, void *data,
3111 		u8(*ops_func)(struct rtw_wifi_role_t *wrole, void *data))
3112 {
3113 	u8 ridx = 0;
3114 	u8 ret = 0;
3115 	struct rtw_phl_com_t *phl_com = wrole->phl_com;
3116 	struct rtw_wifi_role_t *wr = NULL;
3117 
3118 	for (ridx = 0; ridx < MAX_WIFI_ROLE_NUMBER; ridx++) {
3119 		wr = &phl_com->wifi_roles[ridx];
3120 		if (wr && wr->active) {
3121 			if ((exclude_self) && (wr == wrole))
3122 				continue;
3123 			if (ops_func)
3124 				if (true == ops_func(wr, data))
3125 					ret++;
3126 		}
3127 	}
3128 	return ret;
3129 }
3130 
rtw_phl_mr_query_info(void * phl,struct rtw_wifi_role_t * wrole,struct mr_query_info * info)3131 bool rtw_phl_mr_query_info(void *phl, struct rtw_wifi_role_t *wrole,
3132 			struct mr_query_info *info)
3133 {
3134 	struct phl_info_t *phl_info = (struct phl_info_t *)phl;
3135 	struct rtw_phl_com_t *phl_com = phl_info->phl_com;
3136 	struct mr_ctl_t *mr_ctl = phlcom_to_mr_ctrl(phl_com);
3137 	struct hw_band_ctl_t *band_ctrl = &(mr_ctl->band_ctrl[wrole->hw_band]);
3138 
3139 	info->op_mode = band_ctrl->op_mode;
3140 	info->op_type = band_ctrl->op_type;
3141 	_os_mem_cpy(phl_to_drvpriv(phl_info), &info->cur_info,
3142 			&band_ctrl->cur_info, sizeof(struct mr_info));
3143 	return true;
3144 }
3145 
_phl_mr_dump_mac_addr(struct rtw_wifi_role_t * wrole,void * data)3146 static u8 _phl_mr_dump_mac_addr(struct rtw_wifi_role_t *wrole, void *data)
3147 {
3148 	PHL_INFO("RIDX:%d - MAC-Addr:%02x-%02x-%02x-%02x-%02x-%02x\n",
3149 			wrole->id, wrole->mac_addr[0], wrole->mac_addr[1], wrole->mac_addr[2],
3150 			wrole->mac_addr[3], wrole->mac_addr[4], wrole->mac_addr[5]);
3151 	return true;
3152 }
rtw_phl_mr_dump_mac_addr(void * phl,struct rtw_wifi_role_t * wifi_role)3153 u8 rtw_phl_mr_dump_mac_addr(void *phl,
3154 					struct rtw_wifi_role_t *wifi_role)
3155 {
3156 	struct phl_info_t *phl_info = (struct phl_info_t *)phl;
3157 
3158 	return _phl_mr_process(phl_info, wifi_role, false, NULL, _phl_mr_dump_mac_addr);
3159 }
rtw_phl_mr_buddy_dump_mac_addr(void * phl,struct rtw_wifi_role_t * wifi_role)3160 u8 rtw_phl_mr_buddy_dump_mac_addr(void *phl,
3161 					struct rtw_wifi_role_t *wifi_role)
3162 {
3163 	struct phl_info_t *phl_info = (struct phl_info_t *)phl;
3164 
3165 	return _phl_mr_process(phl_info, wifi_role, true, NULL, _phl_mr_dump_mac_addr);
3166 }
3167 
3168 
rtw_phl_mr_ops_init(void * phl,struct rtw_phl_mr_ops * mr_ops)3169 void rtw_phl_mr_ops_init(void *phl, struct rtw_phl_mr_ops *mr_ops)
3170 {
3171 	struct phl_info_t *phl_info = (struct phl_info_t *)phl;
3172 	struct rtw_phl_com_t *phl_com = phl_info->phl_com;
3173 	struct mr_ctl_t *mr_ctl = phlcom_to_mr_ctrl(phl_com);
3174 
3175 	mr_ctl->mr_ops.priv = mr_ops->priv;
3176 #ifdef CONFIG_PHL_P2PPS
3177 	mr_ctl->mr_ops.phl_mr_update_noa = mr_ops->phl_mr_update_noa;
3178 #endif /* CONFIG_PHL_P2PPS */
3179 #ifdef CONFIG_MCC_SUPPORT
3180 	if (phl_com->dev_cap.mcc_sup == true) {
3181 		rtw_phl_mcc_init_ops(phl_info, mr_ops->mcc_ops);
3182 	}
3183 #endif
3184 }
3185 
rtw_phl_mr_get_opch_list(void * phl,struct rtw_wifi_role_t * wifi_role,struct rtw_chan_def * chdef_list,u8 list_size)3186 u8 rtw_phl_mr_get_opch_list(void *phl, struct rtw_wifi_role_t *wifi_role,
3187 			    struct rtw_chan_def *chdef_list, u8 list_size)
3188 {
3189 	struct phl_info_t *phl_info = (struct phl_info_t *)phl;
3190 	struct rtw_phl_com_t *phl_com = phl_info->phl_com;
3191 	struct mr_ctl_t *mr_ctl = phlcom_to_mr_ctrl(phl_com);
3192 	struct hw_band_ctl_t *band_ctrl = &(mr_ctl->band_ctrl[wifi_role->hw_band]);
3193 	void *drv = phl_to_drvpriv(phl_info);
3194 	struct rtw_chan_ctx *chanctx = NULL;
3195 	int ctx_num = 0;
3196 	u8 total_op_num = 0;
3197 
3198 	if((chdef_list == NULL) || (list_size == 0)){
3199 		PHL_ERR("Parameter Invalid!\n");
3200 		goto _exit;
3201 	}
3202 
3203 	ctx_num = phl_mr_get_chanctx_num(phl_info, band_ctrl);
3204 
3205 	if (ctx_num == 0){
3206 		PHL_DBG("ctx_num == 0!\n");
3207 		goto _exit;
3208 	}
3209 
3210 	_os_spinlock(drv, &band_ctrl->chan_ctx_queue.lock, _ps, NULL);
3211 	phl_list_for_loop(chanctx, struct rtw_chan_ctx, &band_ctrl->chan_ctx_queue.queue, list) {
3212 		if(total_op_num >= list_size)
3213 			break;
3214 
3215 		*(chdef_list + total_op_num) = chanctx->chan_def;
3216 		total_op_num++;
3217 	}
3218 	_os_spinunlock(drv, &band_ctrl->chan_ctx_queue.lock, _ps, NULL);
3219 _exit:
3220 	return total_op_num;
3221 }
3222 
3223 enum mr_op_mode
rtw_phl_mr_get_opmode(void * phl,struct rtw_wifi_role_t * wrole)3224 rtw_phl_mr_get_opmode(void *phl, struct rtw_wifi_role_t *wrole)
3225 {
3226 	struct phl_info_t *phl_info = (struct phl_info_t *)phl;
3227 	struct rtw_phl_com_t *phl_com = phl_info->phl_com;
3228 	struct mr_ctl_t *mr_ctl = phlcom_to_mr_ctrl(phl_com);
3229 	struct hw_band_ctl_t *band_ctrl = &(mr_ctl->band_ctrl[wrole->hw_band]);
3230 
3231 	return band_ctrl->op_mode;
3232 }
3233 
3234 void
phl_mr_check_ecsa(struct phl_info_t * phl_info,struct rtw_wifi_role_t * wrole)3235 phl_mr_check_ecsa(struct phl_info_t *phl_info,
3236 		  struct rtw_wifi_role_t *wrole)
3237 {
3238 #ifdef CONFIG_PHL_ECSA
3239 	enum rtw_phl_status pstatus = RTW_PHL_STATUS_SUCCESS;
3240 	struct rtw_phl_com_t *phl_com = phl_info->phl_com;
3241 	struct mr_ctl_t *mr_ctl = phlcom_to_mr_ctrl(phl_com);
3242 	struct hw_band_ctl_t *band_ctrl = &(mr_ctl->band_ctrl[wrole->hw_band]);
3243 	u8 role_map = band_ctrl->role_map;
3244 	struct rtw_wifi_role_t *wr = NULL, *ap_wr = NULL, *sta_wr = NULL;
3245 	u8 ridx;
3246 	enum band_type ap_band_type = BAND_ON_24G, sta_band_type = BAND_ON_24G;
3247 	enum phl_ecsa_start_reason reason = ECSA_START_UNKNOWN;
3248 	u32 delay_start_ms = 0;
3249 #ifdef CONFIG_PHL_ECSA_EXTEND_OPTION
3250 	u32 extend_option = 0;
3251 #endif
3252 	bool ecsa_allow = false;
3253 	struct rtw_phl_ecsa_param param = {0};
3254 	void *d = phlcom_to_drvpriv(phl_com);
3255 
3256 
3257 	if(band_ctrl->op_mode != MR_OP_MCC)
3258 		return;
3259 	if(band_ctrl->op_type != MR_OP_TYPE_STATION_AP)
3260 		return;
3261 
3262 	for (ridx = 0; ridx < MAX_WIFI_ROLE_NUMBER; ridx++) {
3263 		if (role_map & BIT(ridx)) {
3264 			wr = &(phl_com->wifi_roles[ridx]);
3265 
3266 			switch (wr->type) {
3267 			case PHL_RTYPE_STATION:
3268 			case PHL_RTYPE_P2P_GC:
3269 			case PHL_RTYPE_TDLS:
3270 				if (wr->mstate == MLME_LINKED){
3271 					sta_band_type = wr->chandef.band;
3272 					sta_wr = wr;
3273 				}
3274 				break;
3275 			case PHL_RTYPE_AP:
3276 			case PHL_RTYPE_VAP:
3277 			case PHL_RTYPE_P2P_GO:
3278 			case PHL_RTYPE_MESH:
3279 				if (wr->mstate == MLME_LINKED){
3280 					ap_band_type = wr->chandef.band;
3281 					ap_wr = wr;
3282 				}
3283 				break;
3284 			case PHL_RTYPE_MONITOR:
3285 			case PHL_RTYPE_P2P_DEVICE:
3286 			default :
3287 				break;
3288 			}
3289 		}
3290 	}
3291 
3292 	if (sta_wr == NULL) {
3293 		PHL_TRACE(COMP_PHL_ECSA, _PHL_WARNING_, "[ECSA] Sta role not found!\n");
3294 		return;
3295 	}
3296 
3297 	if (ap_wr == NULL) {
3298 		PHL_TRACE(COMP_PHL_ECSA, _PHL_WARNING_, "[ECSA] AP role not found!\n");
3299 		return;
3300 	}
3301 
3302 	if(sta_band_type == BAND_ON_24G){
3303 		if(ap_band_type == BAND_ON_24G)
3304 			reason = ECSA_START_MCC_24G_TO_24G;
3305 		else if(ap_band_type == BAND_ON_5G)
3306 			reason = ECSA_START_MCC_5G_TO_24G;
3307 		else
3308 			reason = ECSA_START_UNKNOWN;
3309 	}
3310 	else if(sta_band_type == BAND_ON_5G){
3311 		if(ap_band_type == BAND_ON_24G)
3312 			reason = ECSA_START_MCC_24G_TO_5G;
3313 		else if(ap_band_type == BAND_ON_5G)
3314 			reason = ECSA_START_MCC_5G_TO_5G;
3315 		else
3316 			reason = ECSA_START_UNKNOWN;
3317 	}
3318 	else{
3319 		reason = ECSA_START_UNKNOWN;
3320 	}
3321 
3322 	if(reason != ECSA_START_UNKNOWN){
3323 		ecsa_allow = rtw_phl_ecsa_check_allow(phl_info,
3324 						      ap_wr,
3325 						      sta_wr->chandef,
3326 						      reason,
3327 #ifdef CONFIG_PHL_ECSA_EXTEND_OPTION
3328 						      &extend_option,
3329 #endif
3330 						      &delay_start_ms);
3331 	}
3332 
3333 	if(ecsa_allow){
3334 		param.ecsa_type = ECSA_TYPE_AP;
3335 		param.ch = sta_wr->chandef.chan;
3336 		param.op_class = rtw_phl_get_operating_class(sta_wr->chandef);
3337 		param.count = ECSA_DEFAULT_CHANNEL_SWITCH_COUNT;
3338 		param.delay_start_ms = delay_start_ms;
3339 		param.flag = 0;
3340 		param.mode = CHANNEL_SWITCH_MODE_NORMAL;
3341 		_os_mem_cpy(d, &(param.new_chan_def), &(sta_wr->chandef),
3342 			    sizeof(struct rtw_chan_def));
3343 
3344 #ifdef CONFIG_PHL_ECSA_EXTEND_OPTION
3345 		rtw_phl_ecsa_extend_option_hdlr(extend_option,
3346 						&param);
3347 #endif
3348 
3349 		pstatus = rtw_phl_ecsa_start(phl_info,
3350 					     ap_wr,
3351 					     &param);
3352 		if(pstatus == RTW_PHL_STATUS_SUCCESS)
3353 			PHL_INFO("%s: ECSA start OK!\n", __FUNCTION__);
3354 		else
3355 			PHL_INFO("%s: ECSA start fail!\n", __FUNCTION__);
3356 	}
3357 #endif /* CONFIG_PHL_ECSA */
3358 }
3359 
3360 void
phl_mr_check_ecsa_cancel(struct phl_info_t * phl_info,struct rtw_wifi_role_t * wrole)3361 phl_mr_check_ecsa_cancel(struct phl_info_t *phl_info,
3362 			 struct rtw_wifi_role_t *wrole)
3363 {
3364 #ifdef CONFIG_PHL_ECSA
3365 	enum rtw_phl_status pstatus = RTW_PHL_STATUS_SUCCESS;
3366 	struct rtw_phl_com_t *phl_com = phl_info->phl_com;
3367 	struct mr_ctl_t *mr_ctl = phlcom_to_mr_ctrl(phl_com);
3368 	struct hw_band_ctl_t *band_ctrl = &(mr_ctl->band_ctrl[wrole->hw_band]);
3369 
3370 	if(band_ctrl->op_mode != MR_OP_MCC)
3371 		return;
3372 	if(band_ctrl->op_type != MR_OP_TYPE_STATION_AP)
3373 		return;
3374 
3375 	pstatus = rtw_phl_ecsa_cancel(phl_info, wrole);
3376 	if(pstatus == RTW_PHL_STATUS_SUCCESS)
3377 		PHL_INFO("%s: ECSA cancel OK!\n", __FUNCTION__);
3378 	else
3379 		PHL_INFO("%s: ECSA cancel fail!\n", __FUNCTION__);
3380 #endif /* CONFIG_PHL_ECSA */
3381 }
3382 #ifdef CONFIG_MCC_SUPPORT
phl_mr_query_mcc_inprogress(struct phl_info_t * phl_info,struct rtw_wifi_role_t * wrole,enum rtw_phl_mcc_chk_inprocess_type check_type)3383 u8 phl_mr_query_mcc_inprogress (struct phl_info_t *phl_info, struct rtw_wifi_role_t *wrole,
3384 				enum rtw_phl_mcc_chk_inprocess_type check_type)
3385 {
3386 	struct rtw_phl_com_t *phl_com = phl_info->phl_com;
3387 	struct mr_ctl_t *mr_ctl = phlcom_to_mr_ctrl(phl_com);
3388 	struct hw_band_ctl_t *band_ctrl = &(mr_ctl->band_ctrl[wrole->hw_band]);
3389 	int chanctx_num = 0;
3390 	u8 ret = false;
3391 	u8 mcc_inprogress = false;
3392 
3393 	if (phl_com->dev_cap.mcc_sup == false) {
3394 		ret = false;
3395 		goto _exit;
3396 	}
3397 
3398 	chanctx_num = phl_mr_get_chanctx_num(phl_info, band_ctrl);
3399 	mcc_inprogress = rtw_phl_mcc_inprogress(phl_info, wrole->hw_band);
3400 
3401 	switch (check_type) {
3402 	case RTW_PHL_MCC_CHK_INPROGRESS:
3403 		ret = mcc_inprogress;
3404 		break;
3405 	case RTW_PHL_MCC_CHK_INPROGRESS_SINGLE_CH:
3406 		if (mcc_inprogress && chanctx_num == 1)
3407 			ret = true;
3408 		else
3409 			ret = false;
3410 		break;
3411 	case RTW_PHL_MCC_CHK_INPROGRESS_MULTI_CH:
3412 		if (mcc_inprogress && chanctx_num >= 2)
3413 			ret = true;
3414 		else
3415 			ret = false;
3416 		break;
3417 	case RTW_PHL_MCC_CHK_MAX:
3418 		ret = false;
3419 		break;
3420 	}
3421 
3422 _exit:
3423 	return ret;
3424 }
3425 
rtw_phl_mr_query_mcc_inprogress(void * phl,struct rtw_wifi_role_t * wrole,enum rtw_phl_mcc_chk_inprocess_type check_type)3426 u8 rtw_phl_mr_query_mcc_inprogress (void *phl, struct rtw_wifi_role_t *wrole,
3427 							enum rtw_phl_mcc_chk_inprocess_type check_type)
3428 {
3429 	struct phl_info_t *phl_info = (struct phl_info_t *)phl;
3430 
3431 	return phl_mr_query_mcc_inprogress(phl_info, wrole, check_type);
3432 }
3433 #endif
3434 
3435 enum rtw_phl_status
phl_mr_err_recovery(struct phl_info_t * phl,enum phl_msg_evt_id eid)3436 phl_mr_err_recovery(struct phl_info_t *phl, enum phl_msg_evt_id eid)
3437 {
3438 	enum rtw_phl_status status = RTW_PHL_STATUS_SUCCESS;
3439 
3440 	if (eid == MSG_EVT_SER_M5_READY) {
3441 		/* SER L1 DONE event */
3442 		rtw_phl_mcc_recovery(phl, HW_BAND_0);
3443 	}
3444 
3445 	return status;
3446 }
3447 
3448 /* MR coex related code */
3449 #ifdef CONFIG_MCC_SUPPORT
3450 #ifdef CONFIG_PHL_P2PPS
3451 static bool
_mr_coex_up_noa_for_bt_req(struct phl_info_t * phl,u16 bt_slot,struct rtw_wifi_role_t * wrole,enum p2pps_trig_tag tag)3452 _mr_coex_up_noa_for_bt_req(struct phl_info_t *phl, u16 bt_slot,
3453 	struct rtw_wifi_role_t *wrole, enum p2pps_trig_tag tag)
3454 {
3455 	bool ret = false;
3456 	struct mr_ctl_t *mr_ctl = phlcom_to_mr_ctrl(phl->phl_com);
3457 	struct rtw_phl_noa param = {0};
3458 	u32 tsf_h = 0, tsf_l = 0;
3459 	u64 tsf = 0, start_tsf = 0;
3460 	u16 offset = 0;
3461 
3462 	if (!mr_ctl->mr_ops.phl_mr_update_noa) {
3463 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "%s(): ops.phl_mr_update_noa == NULL\n",
3464 			__func__);
3465 		goto exit;
3466 	}
3467 	param.wrole = wrole;
3468 	param.tag = tag;
3469 	param.dur = bt_slot;
3470 	if (param.dur == 0)
3471 		goto _ops;
3472 	if (RTW_HAL_STATUS_SUCCESS != rtw_hal_get_tsf(phl->hal,
3473 				wrole->hw_port, &tsf_h, &tsf_l)) {
3474 		PHL_TRACE(COMP_PHL_MCC, _PHL_WARNING_, "%s(): Get tsf fail, hw port(%d)\n",
3475 			__func__, wrole->hw_port);
3476 		goto exit;
3477 	}
3478 	tsf = tsf_h;
3479 	tsf = tsf << 32;
3480 	tsf |= tsf_l;
3481 	if (!phl_calc_offset_from_tbtt(phl, wrole, tsf, &offset)) {
3482 		PHL_TRACE(COMP_PHL_MCC, _PHL_WARNING_, "%s(): Get offset fail\n",
3483 			__func__);
3484 		goto exit;
3485 	}
3486 	param.cnt = 255;
3487 	param.interval = phl_role_get_bcn_intvl(phl, wrole);
3488 	start_tsf = tsf - offset * TU + ((param.interval - param.dur) / 2) * TU;
3489 	start_tsf = start_tsf + param.interval;/*Next beacon start Noa*/
3490 	param.start_t_h = (u32)(start_tsf >> 32);
3491 	param.start_t_l = (u32)start_tsf;
3492 _ops:
3493 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "%s(): NOA_start(0x%08x %08x), dur(%d), cnt(%d), interval(%d)\n",
3494 		__func__, param.start_t_h, param.start_t_l, param.dur,
3495 		param.cnt, param.interval);
3496 	mr_ctl->mr_ops.phl_mr_update_noa(mr_ctl->mr_ops.priv, &param);
3497 	ret = true;
3498 exit:
3499 	return ret;
3500 }
3501 
3502 /*
3503  * Return True: If concurrent mode is ap category x1 and client category x1
3504  */
3505 static bool
_mr_is_2g_scc_1ap_1sta(struct phl_info_t * phl,enum phl_band_idx band_idx,struct rtw_wifi_role_t ** ap_wr)3506 _mr_is_2g_scc_1ap_1sta(struct phl_info_t *phl,
3507 			enum phl_band_idx band_idx, struct rtw_wifi_role_t **ap_wr)
3508 {
3509 	bool need = false;
3510 	struct hw_band_ctl_t *band_ctrl = get_band_ctrl(phl, band_idx);
3511 	struct mr_info *cur_info = &band_ctrl->cur_info;
3512 	u8 ridx = 0, role_map = band_ctrl->role_map;
3513 	struct rtw_wifi_role_t *wr = NULL;
3514 
3515 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "%s: band_idx(%d), op_mode(%d), ap_num(%d), p2p_go_num(%d), ld_sta_num(%d)\n",
3516 		__FUNCTION__, band_idx, band_ctrl->op_mode,
3517 		cur_info->ap_num, cur_info->p2p_go_num,
3518 		cur_info->ld_sta_num);
3519 	if (band_ctrl->op_mode != MR_OP_SCC)
3520 		goto exit;
3521 	if (!(1 == cur_info->ap_num || 1 == cur_info->p2p_go_num))
3522 		goto exit;
3523 	if (cur_info->ld_sta_num == 0)
3524 		goto exit;
3525 	/*get ap role*/
3526 	for (ridx = 0; ridx < MAX_WIFI_ROLE_NUMBER; ridx++) {
3527 		if (!(role_map & BIT(ridx)))
3528 			continue;
3529 		wr = &(phl->phl_com->wifi_roles[ridx]);
3530 		if (phl_role_is_ap_category(wr)&&
3531 			wr->mstate == MLME_LINKED) {
3532 			*ap_wr = wr;
3533 			break;
3534 		}
3535 	}
3536 	if (*ap_wr == NULL)
3537 		goto exit;
3538 	if ((*ap_wr)->chandef.band != BAND_ON_24G)
3539 		goto exit;
3540 	need = true;
3541 exit:
3542 	return need;
3543 }
3544 
3545 /*
3546  * Handle MR coex mechanism for 2g_scc_1ap_1sta_btc
3547  * Specific concurrent mode : ap category x1, client category x1 + BTC
3548  * @handle: True: handle specific concurrent mode for all interfaces; False: Not handleand maybe handle it by other coex mechanism.
3549  */
3550 static enum rtw_phl_status
_phl_mr_2g_scc_1ap_1sta_btc_handle(struct phl_info_t * phl,enum phl_band_idx band_idx,enum mr_coex_trigger trgger,enum mr_coex_mode * coex_mode)3551 _phl_mr_2g_scc_1ap_1sta_btc_handle(struct phl_info_t *phl,
3552 		enum phl_band_idx band_idx, enum mr_coex_trigger trgger,
3553 		enum mr_coex_mode *coex_mode)
3554 {
3555 	enum rtw_phl_status status = RTW_PHL_STATUS_SUCCESS;
3556 	struct rtw_wifi_role_t *ap_wr = NULL;
3557 	u16 bt_slot = 0;
3558 
3559 	if (!_mr_is_2g_scc_1ap_1sta(phl, band_idx, &ap_wr)) {
3560 		PHL_TRACE(COMP_PHL_MCC, _PHL_WARNING_, "%s: It's not 2g_scc_1ap_1sta\n",
3561 			__FUNCTION__);
3562 		goto exit;
3563 	}
3564 	bt_slot = (u16)rtw_hal_get_btc_req_slot(phl->hal);
3565 	if (trgger != MR_COEX_TRIG_BY_BT && bt_slot == 0)
3566 		goto exit;
3567 	if (_mr_coex_up_noa_for_bt_req(phl, bt_slot, ap_wr,
3568 						P2PPS_TRIG_2G_SCC_1AP_1STA_BT)) {
3569 		if (bt_slot > 0)
3570 			*coex_mode = MR_COEX_MODE_2GSCC_1AP_1STA_BTC;
3571 		else
3572 			*coex_mode = MR_COEX_MODE_NONE;
3573 		PHL_TRACE(COMP_PHL_MCC, _PHL_WARNING_, "%s: Up Noa ok\n",
3574 			__FUNCTION__);
3575 	} else {
3576 		status = RTW_PHL_STATUS_FAILURE;
3577 		PHL_TRACE(COMP_PHL_MCC, _PHL_WARNING_, "%s: Up Noa fail\n",
3578 			__FUNCTION__);
3579 	}
3580 exit:
3581 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "%s: coex_mode(%d), status(%d), trgger(%d), bt_slot(%d)\n",
3582 		__FUNCTION__, *coex_mode, status, trgger, bt_slot);
3583 	return status;
3584 }
3585 
3586 /*
3587  * Disable MR coex mechanism of 2g_scc_1ap_1sta_btc
3588  */
3589 enum rtw_phl_status
_phl_mr_2g_scc_1ap_1sta_btc_disable(struct phl_info_t * phl,enum phl_band_idx band_idx)3590 _phl_mr_2g_scc_1ap_1sta_btc_disable(struct phl_info_t *phl,
3591 			enum phl_band_idx band_idx)
3592 {
3593 	enum rtw_phl_status status = RTW_PHL_STATUS_FAILURE;
3594 	struct rtw_wifi_role_t *ap_wr = NULL;
3595 
3596 	if (!_mr_is_2g_scc_1ap_1sta(phl, band_idx, &ap_wr)) {
3597 		PHL_TRACE(COMP_PHL_MCC, _PHL_WARNING_, "%s: It��s not 2g_scc_1ap_1sta\n",
3598 			__FUNCTION__);
3599 		goto exit;
3600 	}
3601 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "%s: band_idx(%d)\n",
3602 		__FUNCTION__, band_idx);
3603 	if (_mr_coex_up_noa_for_bt_req(phl, 0, ap_wr, P2PPS_TRIG_2G_SCC_1AP_1STA_BT)) {
3604 		status = RTW_PHL_STATUS_SUCCESS;
3605 	} else {
3606 		status = RTW_PHL_STATUS_FAILURE;
3607 		PHL_TRACE(COMP_PHL_MCC, _PHL_WARNING_, "%s: Up Noa fail\n",
3608 			__FUNCTION__);
3609 	}
3610 exit:
3611 	return status;
3612 }
3613 #endif /* CONFIG_PHL_P2PPS */
3614 
3615 /*
3616  * Disable MR coex mechanism which is TDMRA or 2g_scc_1ap_1sta_btc mechanism
3617  */
3618 enum rtw_phl_status
phl_mr_coex_disable(struct phl_info_t * phl,struct rtw_wifi_role_t * cur_wrole,enum phl_band_idx band_idx,enum mr_coex_trigger trgger)3619 phl_mr_coex_disable(struct phl_info_t *phl,
3620 		struct rtw_wifi_role_t *cur_wrole, enum phl_band_idx band_idx,
3621 		enum mr_coex_trigger trgger)
3622 {
3623 	enum rtw_phl_status status = RTW_PHL_STATUS_FAILURE;
3624 	struct hw_band_ctl_t *band_ctrl = get_band_ctrl(phl, band_idx);
3625 
3626 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "%s: band_idx(%d), trgger(%d)\n",
3627 		__FUNCTION__, band_idx, trgger);
3628 #ifdef CONFIG_PHL_P2PPS
3629 	if (band_ctrl->coex_mode == MR_COEX_MODE_2GSCC_1AP_1STA_BTC) {
3630 		status = _phl_mr_2g_scc_1ap_1sta_btc_disable(phl, band_idx);
3631 		if (status == RTW_PHL_STATUS_SUCCESS)
3632 			band_ctrl->coex_mode = MR_COEX_MODE_NONE;
3633 	} else
3634 #endif /* CONFIG_PHL_P2PPS */
3635 #ifdef CONFIG_MCC_SUPPORT
3636 	if (band_ctrl->coex_mode == MR_COEX_MODE_TDMRA) {
3637 		status = _phl_mr_tdmra_disable(phl, cur_wrole, band_idx);
3638 		if (status == RTW_PHL_STATUS_SUCCESS)
3639 			band_ctrl->coex_mode = MR_COEX_MODE_NONE;
3640 	} else
3641 #endif /* CONFIG_MCC_SUPPORT */
3642 	{
3643 		status = RTW_PHL_STATUS_SUCCESS;
3644 	}
3645 	if (trgger == MR_COEX_TRIG_BY_SCAN) {
3646 		phl_mr_stop_all_beacon(phl, cur_wrole, true);
3647 	}
3648 	if (status != RTW_PHL_STATUS_SUCCESS) {
3649 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "%s: Handle by %d fail\n",
3650 			__FUNCTION__, band_ctrl->coex_mode);
3651 	}
3652 	return status;
3653 }
3654 
3655 /*
3656  * MR will excute suitable coex mechanism for Multi-interface
3657  * @cur_wrole: current role
3658  * @slot: time slot, Interpretation by trgger event.
3659  * Ignore it, if trgger event is MR_COEX_TRIG_BY_LINKING/MR_COEX_TRIG_BY_DIS_LINKING/
3660  * MR_COEX_TRIG_BY_SCAN/MR_COEX_TRIG_BY_ECSA.
3661  * @band_idx: hw band
3662  * @trgger: Trigger event
3663  */
3664 enum rtw_phl_status
phl_mr_coex_handle(struct phl_info_t * phl,struct rtw_wifi_role_t * cur_wrole,u16 slot,enum phl_band_idx band_idx,enum mr_coex_trigger trgger)3665 phl_mr_coex_handle(struct phl_info_t *phl, struct rtw_wifi_role_t *cur_wrole,
3666 	u16 slot, enum phl_band_idx band_idx, enum mr_coex_trigger trgger)
3667 {
3668 	enum rtw_phl_status status = RTW_PHL_STATUS_FAILURE;
3669 	struct hw_band_ctl_t *band_ctrl = get_band_ctrl(phl, band_idx);
3670 
3671 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "%s: band_idx(%d), trgger(%d), slot(%d)\n",
3672 		__FUNCTION__, band_idx, trgger, slot);
3673 #ifdef CONFIG_PHL_P2PPS
3674 	status = _phl_mr_2g_scc_1ap_1sta_btc_handle(phl, band_idx, trgger,
3675 							&band_ctrl->coex_mode);
3676 	if (status != RTW_PHL_STATUS_SUCCESS) {
3677 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "%s: Handle 2g_scc_1ap_1sta_btc fail\n",
3678 			__FUNCTION__);
3679 		goto exit;
3680 	}
3681 #endif /* CONFIG_PHL_P2PPS */
3682 #ifdef CONFIG_MCC_SUPPORT
3683 	if (band_ctrl->coex_mode != MR_COEX_MODE_2GSCC_1AP_1STA_BTC) {
3684 		status = _phl_mr_tdmra_handle(phl, cur_wrole, slot, band_idx,
3685 						trgger, &band_ctrl->coex_mode);
3686 		if (status != RTW_PHL_STATUS_SUCCESS) {
3687 			PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "%s: Handle TDMRA fail\n",
3688 			__FUNCTION__);
3689 			goto exit;
3690 		}
3691 	}
3692 #endif /* CONFIG_MCC_SUPPORT */
3693 	if (trgger == MR_COEX_TRIG_BY_SCAN) {
3694 		phl_mr_stop_all_beacon(phl, cur_wrole, false);
3695 	}
3696 exit:
3697 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "%s: status(%d), coex_mode %d\n",
3698 			__FUNCTION__, status, band_ctrl->coex_mode);
3699 	return status;
3700 }
3701 #endif /* CONFIG_MCC_SUPPORT */
3702