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