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 ¶m);
3347 #endif
3348
3349 pstatus = rtw_phl_ecsa_start(phl_info,
3350 ap_wr,
3351 ¶m);
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, ¶m);
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