xref: /OK3568_Linux_fs/external/rkwifibt/drivers/rtl8852be/phl/phl_role.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /******************************************************************************
2  *
3  * Copyright(c) 2019 Realtek Corporation.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of version 2 of the GNU General Public License as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12  * more details.
13  *
14  *****************************************************************************/
15 #define _PHL_ROLE_C_
16 #include "phl_headers.h"
17 
18 
19 static enum rtw_phl_status
_phl_alloc_hw_resource(struct phl_info_t * phl,struct rtw_wifi_role_t * wrole,u8 hw_band)20 _phl_alloc_hw_resource(struct phl_info_t *phl,
21 				struct rtw_wifi_role_t *wrole, u8 hw_band)
22 {
23 	enum rtw_phl_status psts = RTW_PHL_STATUS_FAILURE;
24 	void *drv = phl_to_drvpriv(phl);
25 	struct rtw_phl_com_t *phl_com = phl->phl_com;
26 	struct mr_ctl_t *mr_ctl = phlcom_to_mr_ctrl(phl_com);
27 	struct hal_spec_t *hal_spec = phl_get_ic_spec(phl_com);
28 	struct hw_band_ctl_t *band_ctrl;
29 	u8 port_num, max_port_num;
30 	u8 wmm_num, max_wmm_num;
31 	int ridx;
32 
33 	band_ctrl = &mr_ctl->band_ctrl[hw_band];
34 	max_port_num = hal_spec->port_num;
35 	max_wmm_num = hal_spec->wmm_num;
36 	ridx = wrole->id;
37 
38 	_os_spinlock(drv, &band_ctrl->lock, _ps, NULL);
39 	/*alloc hw_port*/
40 	for (port_num = 0; port_num < max_port_num; port_num++) {
41 		if (!(band_ctrl->port_map & BIT(port_num))) {
42 			band_ctrl->port_map |= BIT(port_num);
43 			break;
44 		}
45 	}
46 	if (port_num == max_port_num) {
47 		PHL_ERR("%s Can't allocate hw port\n", __func__);
48 		_os_warn_on(1);
49 		goto _exit;
50 	}
51 	wrole->hw_port = port_num;
52 
53 	/*alloc hw_wmm*/
54 	for (wmm_num = 0; wmm_num < max_wmm_num; wmm_num++) {
55 		if (!(band_ctrl->wmm_map & BIT(wmm_num))) {
56 			band_ctrl->wmm_map |= BIT(wmm_num);
57 			break;
58 		}
59 	}
60 	if (wmm_num == max_wmm_num) {
61 		PHL_INFO("%s WID:%d - assigne wmm_id to 0\n", __func__, ridx);
62 		wrole->hw_wmm = 0;
63 	} else {
64 		wrole->hw_wmm = wmm_num;
65 	}
66 	#ifdef RTW_WKARD_HW_WMM_ALLOCATE
67 	if (wrole->hw_wmm == 0)
68 		_os_atomic_inc(phl_to_drvpriv(phl), &wrole->hw_wmm0_ref_cnt);
69 	#endif
70 
71 	/*set mr_role_map*/
72 	band_ctrl->role_map |= BIT(ridx);
73 	wrole->hw_band = hw_band;
74 	psts = RTW_PHL_STATUS_SUCCESS;
75 _exit:
76 	_os_spinunlock(drv, &band_ctrl->lock, _ps, NULL);
77 
78 	if (psts == RTW_PHL_STATUS_SUCCESS) {
79 		PHL_INFO("%s wridx:%d success\n", __func__, ridx);
80 		PHL_DUMP_ROLE_EX(phl, wrole);
81 	}
82 	return psts;
83 }
84 
85 static enum rtw_phl_status
_phl_free_hw_resource(struct phl_info_t * phl,struct rtw_wifi_role_t * wrole)86 _phl_free_hw_resource(struct phl_info_t *phl,
87 			struct rtw_wifi_role_t *wrole)
88 {
89 	enum rtw_phl_status psts = RTW_PHL_STATUS_FAILURE;
90 	void *drv = phl_to_drvpriv(phl);
91 	struct rtw_phl_com_t *phl_com = phl->phl_com;
92 	struct mr_ctl_t *mr_ctl = phlcom_to_mr_ctrl(phl_com);
93 	struct hw_band_ctl_t *band_ctrl;
94 	int ridx = wrole->id;
95 	u8 hw_band = wrole->hw_band;
96 
97 	band_ctrl = &mr_ctl->band_ctrl[hw_band];
98 	PHL_DUMP_ROLE_EX(phl, wrole);
99 
100 	_os_spinlock(drv, &band_ctrl->lock, _ps, NULL);
101 	/*release hw_port*/
102 	band_ctrl->port_map &= ~BIT(wrole->hw_port);
103 
104 	/*release hw_wmm*/
105 	#ifdef RTW_WKARD_HW_WMM_ALLOCATE
106 	if (wrole->hw_wmm == 0) {
107 		_os_atomic_dec(phl_to_drvpriv(phl), &wrole->hw_wmm0_ref_cnt);
108 		if (_os_atomic_read(phl_to_drvpriv(phl), &wrole->hw_wmm0_ref_cnt) == 0)
109 			band_ctrl->wmm_map &= ~BIT(wrole->hw_wmm);
110 	} else
111 	#endif
112 	{
113 		band_ctrl->wmm_map &= ~BIT(wrole->hw_wmm);
114 	}
115 	/*release mr_role_map*/
116 	band_ctrl->role_map &= ~BIT(ridx);
117 	_os_spinunlock(drv, &band_ctrl->lock, _ps, NULL);
118 
119 	psts = RTW_PHL_STATUS_SUCCESS;
120 	PHL_INFO("%s wr-id:%d success\n", __func__, ridx);
121 	return psts;
122 }
123 
124 #if 0 /*TODO:DBCC*/
125 static enum rtw_phl_status
126 _phl_realloc_hw_resource(struct phl_info_t *phl,
127 					struct rtw_wifi_role_t *wrole, u8 new_band)
128 {
129 	enum rtw_phl_status psts = RTW_PHL_STATUS_FAILURE;
130 
131 	if (new_band == wrole->hw_band) {
132 		PHL_ERR("%s widx:%d at the same band(%d)\n", __func__, wrole->id, new_band);
133 		return psts;
134 	}
135 
136 	_phl_free_hw_resource(phl, wrole);
137 	_phl_alloc_hw_resource(phl, wrole, new_band);
138 	return psts;
139 }
140 #endif
_phl_search_roleidx_by_addr(struct phl_info_t * phl_info,u8 * mac_addr)141 static u8 _phl_search_roleidx_by_addr(
142 			struct phl_info_t *phl_info, u8 *mac_addr)
143 {
144 	struct rtw_phl_com_t *phl_com = phl_info->phl_com;
145 	u8 ridx = MAX_WIFI_ROLE_NUMBER;
146 	struct mr_ctl_t *mr_ctl = phlcom_to_mr_ctrl(phl_com);
147 
148 	for (ridx = 0; ridx < MAX_WIFI_ROLE_NUMBER; ridx++) {
149 		if (mr_ctl->role_map & BIT(ridx)) {
150 			if (_os_mem_cmp(phl_to_drvpriv(phl_info),
151 				phl_com->wifi_roles[ridx].mac_addr,
152 				mac_addr, MAC_ALEN) == 0)
153 				break;
154 		}
155 	}
156 
157 	#if 0
158 	if (ridx == MAX_WIFI_ROLE_NUMBER)
159 		PHL_INFO("%s cannot get rid\n", __func__);
160 	#endif
161 	return ridx;
162 }
163 
164 struct rtw_wifi_role_t *
phl_get_wrole_by_addr(struct phl_info_t * phl_info,u8 * mac_addr)165 phl_get_wrole_by_addr(struct phl_info_t *phl_info, u8 *mac_addr)
166 {
167 	struct rtw_phl_com_t *phl_com = phl_info->phl_com;
168 	int ridx = MAX_WIFI_ROLE_NUMBER;
169 	struct mr_ctl_t *mr_ctl = phlcom_to_mr_ctrl(phl_com);
170 	struct rtw_wifi_role_t *wrole = NULL;
171 	bool found = false;
172 
173 	for (ridx = 0; ridx < MAX_WIFI_ROLE_NUMBER; ridx++) {
174 		if (mr_ctl->role_map & BIT(ridx)) {
175 			wrole = &(phl_com->wifi_roles[ridx]);
176 			if (_os_mem_cmp(phl_to_drvpriv(phl_info),
177 				wrole->mac_addr, mac_addr, MAC_ALEN) == 0) {
178 				found = true;
179 				break;
180 			}
181 		}
182 	}
183 
184 	if (found == false)
185 		wrole = NULL;
186 
187 	return wrole;
188 }
189 
190 struct rtw_wifi_role_t *
rtw_phl_get_wrole_by_ridx(struct rtw_phl_com_t * phl_com,u8 rold_idx)191 rtw_phl_get_wrole_by_ridx(struct rtw_phl_com_t *phl_com, u8 rold_idx)
192 {
193 	if (rold_idx < MAX_WIFI_ROLE_NUMBER)
194 		return &(phl_com->wifi_roles[rold_idx]);
195 
196 	return NULL;
197 }
198 
199 static void
_phl_role_notify_buf_done(void * priv,struct phl_msg * msg)200 _phl_role_notify_buf_done(void* priv, struct phl_msg* msg)
201 {
202 	struct phl_info_t *phl_info = (struct phl_info_t *)priv;
203 
204 	if(msg->inbuf && msg->inlen){
205 		_os_mem_free(phl_to_drvpriv(phl_info), msg->inbuf, msg->inlen);
206 	}
207 }
208 
209 #ifdef CONFIG_CMD_DISP
210 static void
_phl_role_cmd_done(void * priv,struct phl_msg * msg)211 _phl_role_cmd_done(void* priv, struct phl_msg* msg)
212 {
213 	struct phl_info_t *phl_info = (struct phl_info_t *)priv;
214 
215 	if(msg->inbuf && msg->inlen){
216 		_os_kmem_free(phl_to_drvpriv(phl_info),
217 			msg->inbuf, msg->inlen);
218 	}
219 }
220 
221 static void
_phl_send_role_notify_cmd(struct phl_info_t * phl_info,struct rtw_wifi_role_t * wrole,enum role_state rstate)222 _phl_send_role_notify_cmd(struct phl_info_t *phl_info,
223 			struct rtw_wifi_role_t *wrole, enum role_state rstate)
224 {
225 	struct phl_msg msg = {0};
226 	struct phl_msg_attribute attr = {0};
227 	struct rtw_role_cmd *rcmd = NULL;
228 
229 	rcmd = (struct rtw_role_cmd *)_os_kmem_alloc(
230 		phl_to_drvpriv(phl_info), sizeof(struct rtw_role_cmd));
231 	if (rcmd == NULL) {
232 		PHL_ERR("%s: alloc role cmd fail.\n", __func__);
233 		return;
234 	}
235 
236 	rcmd->wrole = wrole;
237 	rcmd->rstate = rstate;
238 	msg.inbuf = (u8 *)rcmd;
239 	msg.inlen = sizeof(struct rtw_role_cmd);
240 
241 	SET_MSG_MDL_ID_FIELD(msg.msg_id, PHL_MDL_MRC);
242 	SET_MSG_EVT_ID_FIELD(msg.msg_id, MSG_EVT_ROLE_NTFY);
243 	msg.band_idx = HW_BAND_0;
244 	attr.completion.completion = _phl_role_cmd_done;
245 	attr.completion.priv = phl_info;
246 
247 	if (phl_disp_eng_send_msg(phl_info, &msg, &attr, NULL) !=
248 				RTW_PHL_STATUS_SUCCESS) {
249 		PHL_ERR("%s: dispr_send_msg failed !\n", __func__);
250 		goto cmd_fail;
251 	}
252 
253 	return;
254 
255 cmd_fail:
256 	_os_mem_free(phl_to_drvpriv(phl_info), rcmd,
257 				sizeof(struct rtw_role_cmd));
258 }
259 #endif
260 
261 static enum rtw_phl_status
_phl_role_notify(struct phl_info_t * phl_info,struct rtw_wifi_role_t * wrole,enum role_state rstate)262 _phl_role_notify(struct phl_info_t *phl_info,
263 		struct rtw_wifi_role_t *wrole,
264 		enum role_state rstate)
265 {
266 	if (rstate >= PHL_ROLE_STATE_UNKNOWN) {
267 		PHL_ERR("%s unknow rstate:%d\n", __func__, rstate);
268 		return RTW_PHL_STATUS_FAILURE;
269 	}
270 
271 #ifdef CONFIG_PHL_CMD_BTC
272 	_phl_send_role_notify_cmd(phl_info, wrole, rstate);
273 #else
274 #ifdef CONFIG_BTCOEX
275 	rtw_phl_btc_role_notify(phl_info, wrole->id, rstate);
276 #endif
277 #endif
278 
279 	return RTW_PHL_STATUS_SUCCESS;
280 }
281 
282 static struct rtw_wifi_role_t *
_phl_wifi_role_alloc_sw(struct phl_info_t * phl_info,u8 * mac_addr,enum role_type type,u8 ridx)283 _phl_wifi_role_alloc_sw(struct phl_info_t *phl_info,
284 				u8 *mac_addr, enum role_type type, u8 ridx)
285 {
286 	struct rtw_phl_com_t *phl_com = phl_info->phl_com;
287 	struct rtw_wifi_role_t *role = NULL;
288 	struct mr_ctl_t *mr_ctl = phlcom_to_mr_ctrl(phl_com);
289 	u8 role_idx = INVALID_WIFI_ROLE_IDX;
290 	u8 hw_band;
291 
292 	_os_spinlock(phl_to_drvpriv(phl_info), &mr_ctl->lock, _ps, NULL);
293 	if (ridx == UNSPECIFIED_ROLE_ID) {
294 		/*search avaliable rid */
295 		for (role_idx = 0; role_idx < MAX_WIFI_ROLE_NUMBER; role_idx++) {
296 			if (!(mr_ctl->role_map & BIT(role_idx))) {
297 				mr_ctl->role_map |= BIT(role_idx);
298 				break;
299 			}
300 		}
301 	} else {
302 		if (mr_ctl->role_map & BIT(ridx)) {
303 			PHL_ERR("role_idx:%d has used\n", ridx);
304 			_os_warn_on(1);
305 		} else {
306 			mr_ctl->role_map |= BIT(ridx);
307 			role_idx = ridx;
308 		}
309 	}
310 	_os_spinunlock(phl_to_drvpriv(phl_info), &mr_ctl->lock, _ps, NULL);
311 
312 	if (role_idx == INVALID_WIFI_ROLE_IDX) {
313 		PHL_ERR("%s Can't get available role idx\n", __func__);
314 		_os_warn_on(1);
315 		return role;
316 	}
317 
318 	role = &phl_com->wifi_roles[role_idx];
319 	role->type = type;
320 	role->mstate = MLME_NO_LINK;
321 	role->chanctx = NULL;
322 	hw_band = 0;
323 
324 	/*alloc hw_band and hw_port,hw_wmm*/
325 	if (_phl_alloc_hw_resource(phl_info, role, hw_band) != RTW_PHL_STATUS_SUCCESS) {
326 		PHL_ERR("%s alloc_hw resource failed\n", __func__);
327 		_os_warn_on(1);
328 		role = NULL;
329 		return role;
330 	}
331 
332 #ifdef RTW_WKARD_STA_BCN_INTERVAL
333 #ifdef RTW_PHL_BCN
334 	if (role->type == PHL_RTYPE_AP) {
335 		role->bcn_cmn.bcn_interval = 100;
336 		role->mstate = MLME_LINKED;
337 	}
338 #endif
339 #endif
340 
341 	_os_mem_cpy(phl_to_drvpriv(phl_info),
342 			role->mac_addr, mac_addr, MAC_ALEN);
343 
344 	phl_init_role_cap(phl_info, role);
345 	phl_init_protocol_cap(phl_info, role);
346 
347 	return role;
348 }
349 
350 static enum rtw_phl_status
_phl_wifi_role_start(struct phl_info_t * phl_info,struct rtw_wifi_role_t * wrole,struct rtw_phl_stainfo_t * sta)351 _phl_wifi_role_start(struct phl_info_t *phl_info,
352 				struct rtw_wifi_role_t *wrole,
353 				struct rtw_phl_stainfo_t *sta)
354 {
355 	enum rtw_phl_status psts = RTW_PHL_STATUS_FAILURE;
356 	enum rtw_hal_status hsts = RTW_HAL_STATUS_FAILURE;
357 
358 	if (sta->active == false) {
359 		psts = phl_alloc_stainfo_hw(phl_info, sta);
360 		if (psts != RTW_PHL_STATUS_SUCCESS) {
361 			PHL_ERR("%s can't alloc self stainfo_hw\n", __func__);
362 			_os_warn_on(1);
363 			goto _exit;
364 		}
365 		PHL_INFO("%s sta_info hw - macid:%u %02x:%02x:%02x:%02x:%02x:%02x\n",
366 			__func__, sta->macid,
367 			sta->mac_addr[0], sta->mac_addr[1], sta->mac_addr[2],
368 			sta->mac_addr[3], sta->mac_addr[4], sta->mac_addr[5]);
369 	}
370 
371 	hsts = rtw_hal_role_cfg(phl_info->hal, wrole);
372 	if(hsts != RTW_HAL_STATUS_SUCCESS) {
373 		PHL_ERR("%s hal role cfg failed\n", __func__);
374 		_os_warn_on(1);
375 		goto _exit;
376 	}
377 	wrole->active = true;
378 	_phl_role_notify(phl_info, wrole, PHL_ROLE_START);
379 	psts = RTW_PHL_STATUS_SUCCESS;
380 	return psts;
381 
382 _exit:
383 	return psts;
384 }
385 
386 static enum rtw_phl_status
_phl_wifi_role_free_sw(struct phl_info_t * phl_info,struct rtw_wifi_role_t * wrole)387 _phl_wifi_role_free_sw(struct phl_info_t *phl_info, struct rtw_wifi_role_t *wrole)
388 {
389 	struct rtw_phl_com_t *phl_com = phl_info->phl_com;
390 	struct mr_ctl_t *mr_ctl = phlcom_to_mr_ctrl(phl_com);
391 
392 	_phl_free_hw_resource(phl_info, wrole);
393 	_os_mem_set(phl_to_drvpriv(phl_info), wrole->mac_addr, 0, MAC_ALEN);
394 	_os_spinlock(phl_to_drvpriv(phl_info), &mr_ctl->lock, _ps, NULL);
395 	mr_ctl->role_map &= ~BIT(wrole->id);
396 	_os_spinunlock(phl_to_drvpriv(phl_info), &mr_ctl->lock, _ps, NULL);
397 	wrole->active = false;
398 	wrole->mstate = MLME_NO_LINK;
399 	wrole->type = PHL_RTYPE_NONE;
400 	return RTW_PHL_STATUS_SUCCESS;
401 }
402 
403 #ifdef CONFIG_CMD_DISP
404 struct wr_start_param {
405 	struct rtw_wifi_role_t *wrole;
406 	struct rtw_phl_stainfo_t *sta;
407 };
408 
409 enum rtw_phl_status
phl_wifi_role_start_hdl(struct phl_info_t * phl_info,u8 * param)410 phl_wifi_role_start_hdl(struct phl_info_t *phl_info, u8 *param)
411 {
412 	struct wr_start_param *cmd_wr = (struct wr_start_param *)param;
413 
414 	return _phl_wifi_role_start(phl_info, cmd_wr->wrole, cmd_wr->sta);
415 }
416 
phl_wifi_role_start_done(void * drv_priv,u8 * cmd,u32 cmd_len,enum rtw_phl_status status)417 void phl_wifi_role_start_done(void *drv_priv, u8 *cmd, u32 cmd_len,
418 						enum rtw_phl_status status)
419 {
420 	if (cmd) {
421 		_os_kmem_free(drv_priv, cmd, cmd_len);
422 		cmd = NULL;
423 		PHL_INFO("%s.....\n", __func__);
424 	}
425 }
426 
427 enum rtw_phl_status
phl_wifi_role_start(struct phl_info_t * phl_info,struct rtw_wifi_role_t * wrole,struct rtw_phl_stainfo_t * sta)428 phl_wifi_role_start(struct phl_info_t *phl_info,
429 				struct rtw_wifi_role_t *wrole,
430 				struct rtw_phl_stainfo_t *sta)
431 {
432 	enum rtw_phl_status psts = RTW_PHL_STATUS_FAILURE;
433 	struct wr_start_param *wr_start = NULL;
434 	void *drv = phl_to_drvpriv(phl_info);
435 	u32 wr_start_len;
436 
437 	wr_start_len = sizeof(struct wr_start_param);
438 	wr_start = _os_kmem_alloc(drv, wr_start_len);
439 	if (wr_start == NULL) {
440 		PHL_ERR("%s: alloc wr_start_param failed!\n", __func__);
441 		psts = RTW_PHL_STATUS_RESOURCE;
442 		goto _exit;
443 	}
444 	wr_start->wrole = wrole;
445 	wr_start->sta = sta;
446 
447 	psts = phl_cmd_enqueue(phl_info,
448 				wrole->hw_band,
449 				MSG_EVT_ROLE_START,
450 				(u8*)wr_start,
451 				wr_start_len,
452 				phl_wifi_role_start_done,
453 				PHL_CMD_WAIT,
454 				0);
455 
456 	if (is_cmd_failure(psts)) {
457 		/* Send cmd success, but wait cmd fail*/
458 		psts = RTW_PHL_STATUS_FAILURE;
459 		PHL_INFO("%s wr-id:%d failure\n", __func__, wrole->id);
460 	} else if (psts != RTW_PHL_STATUS_SUCCESS) {
461 		/* Send cmd fail */
462 		_os_kmem_free(drv, wr_start, wr_start_len);
463 		psts = RTW_PHL_STATUS_FAILURE;
464 		PHL_INFO("%s wr-id:%d failure\n", __func__, wrole->id);
465 	} else {
466 		PHL_INFO("%s wr-id:%d success\n", __func__, wrole->id);
467 	}
468 
469 _exit:
470 	return psts;
471 }
472 #else
473 enum rtw_phl_status
phl_wifi_role_start(struct phl_info_t * phl_info,struct rtw_wifi_role_t * wrole,struct rtw_phl_stainfo_t * sta)474 phl_wifi_role_start(struct phl_info_t *phl_info,
475 				struct rtw_wifi_role_t *wrole,
476 				struct rtw_phl_stainfo_t *sta)
477 {
478 	return _phl_wifi_role_start(phl_info, wrole, sta);
479 }
480 #endif
481 
rtw_phl_wifi_role_alloc(void * phl,u8 * mac_addr,enum role_type type,u8 ridx,struct rtw_wifi_role_t ** wifi_role,bool ignore_hw_fail)482 u8 rtw_phl_wifi_role_alloc(void *phl, u8 *mac_addr, enum role_type type,
483 				u8 ridx, struct rtw_wifi_role_t **wifi_role, bool ignore_hw_fail)
484 {
485 	struct phl_info_t *phl_info = (struct phl_info_t *)phl;
486 	struct rtw_phl_com_t *phl_com = phl_info->phl_com;
487 	u8 role_idx = INVALID_WIFI_ROLE_IDX;
488 	struct rtw_wifi_role_t *role = NULL;
489 	struct rtw_phl_stainfo_t *phl_sta = NULL;
490 	enum rtw_phl_status psts = RTW_PHL_STATUS_FAILURE;
491 
492 	if (mac_addr == NULL) {
493 		PHL_ERR("%s mac_addr == NULL\n", __func__);
494 		goto _exit;
495 	}
496 
497 	/*search rid by mac_addr, if had assigned then return role index*/
498 	role_idx = _phl_search_roleidx_by_addr(phl_info, mac_addr);
499 	if (role_idx != INVALID_WIFI_ROLE_IDX) {
500 		PHL_INFO("%s wifi-role(%d) had allociated\n", __func__, role_idx);
501 		*wifi_role = &phl_com->wifi_roles[role_idx];
502 		goto _exit;
503 	}
504 
505 	role = _phl_wifi_role_alloc_sw(phl_info, mac_addr, type, ridx);
506 	if (role == NULL) {
507 		PHL_ERR("%s role alloc sw failed\n", __func__);
508 		_os_warn_on(1);
509 		goto _exit;
510 	}
511 
512 	/*alloc sta_info for self*/
513 	phl_sta = phl_alloc_stainfo_sw(phl_info, role->mac_addr, role);
514 	if (phl_sta == NULL) {
515 		PHL_ERR("%s can't alloc self stainfo_sw\n", __func__);
516 		_os_warn_on(1);
517 		goto _err_stainfo_sw;
518 	}
519 
520 	psts = phl_wifi_role_start(phl_info, role, phl_sta);
521 	if (psts != RTW_PHL_STATUS_SUCCESS) {
522 		PHL_ERR("%s role start failed\n", __func__);
523 		if (!ignore_hw_fail) {
524 			_os_warn_on(1);
525 			goto _err_role_start;
526 		}
527 	}
528 
529 	*wifi_role = role;
530 	role_idx = role->id;
531 	PHL_DUMP_MR_EX(phl_info);
532 	return role_idx;
533 
534 _err_role_start:
535 	phl_wifi_role_free_stainfo_sw(phl_info, role);
536 
537 _err_stainfo_sw:
538 	_phl_wifi_role_free_sw(phl_info, role);
539 
540 _exit:
541 	return role_idx;
542 }
543 
544 enum rtw_phl_status
phl_role_noa_notify(struct phl_info_t * phl_info,struct rtw_wifi_role_t * wrole)545 phl_role_noa_notify(struct phl_info_t *phl_info, struct rtw_wifi_role_t *wrole)
546 {
547 	_phl_role_notify(phl_info, wrole, PHL_ROLE_UPDATE_NOA);
548 
549 	return RTW_PHL_STATUS_SUCCESS;
550 }
551 
552 enum rtw_phl_status
phl_role_ap_client_notify(struct phl_info_t * phl_info,struct rtw_wifi_role_t * wrole,u8 link_sts)553 phl_role_ap_client_notify(struct phl_info_t *phl_info,
554 			struct rtw_wifi_role_t *wrole, u8 link_sts)
555 {
556 	enum role_state rstate;
557 
558 	if (link_sts == MLME_LINKING)
559 		rstate = PHL_ROLE_MSTS_STA_CONN_START;
560 	else if (link_sts == MLME_LINKED)
561 		rstate = PHL_ROLE_MSTS_STA_CONN_END;
562 	else
563 		rstate = PHL_ROLE_MSTS_STA_DIS_CONN;
564 
565 	_phl_role_notify(phl_info, wrole, rstate);
566 #ifdef CONFIG_MCC_SUPPORT
567 	phl_mcc_client_link_notify_for_ap(phl_info, wrole, rstate);
568 #endif /* CONFIG_MCC_SUPPORT */
569 	return RTW_PHL_STATUS_SUCCESS;
570 }
571 
572 enum rtw_phl_status
phl_role_notify(struct phl_info_t * phl_info,struct rtw_wifi_role_t * wrole)573 phl_role_notify(struct phl_info_t *phl_info, struct rtw_wifi_role_t *wrole)
574 {
575 	enum role_state rstate = PHL_ROLE_STATE_UNKNOWN;
576 
577 	switch (wrole->type) {
578 	case PHL_RTYPE_STATION:
579 	case PHL_RTYPE_P2P_GC:
580 	{
581 		if (wrole->mstate == MLME_LINKING)
582 			rstate = PHL_ROLE_MSTS_STA_CONN_START;
583 		else if (wrole->mstate == MLME_LINKED)
584 			rstate = PHL_ROLE_MSTS_STA_CONN_END;
585 		else
586 			rstate = PHL_ROLE_MSTS_STA_DIS_CONN;
587 	}
588 	break;
589 
590 	case PHL_RTYPE_AP:
591 	case PHL_RTYPE_VAP:
592 	case PHL_RTYPE_MESH:
593 	case PHL_RTYPE_P2P_GO:
594 	{
595 		rstate = (wrole->mstate == MLME_NO_LINK)
596 			? PHL_ROLE_MSTS_AP_STOP
597 			: PHL_ROLE_MSTS_AP_START;
598 	}
599 	break;
600 
601 	case PHL_RTYPE_NONE:
602 	case PHL_RTYPE_ADHOC:
603 	case PHL_RTYPE_ADHOC_MASTER:
604 	case PHL_RTYPE_MONITOR:
605 	case PHL_RTYPE_P2P_DEVICE:
606 	case PHL_RTYPE_NAN:
607 	case PHL_MLME_MAX:
608 		PHL_TRACE(COMP_PHL_DBG, _PHL_ERR_,
609 			"%s: Unsupported case:%d in wrole notify, please check it\n",
610 			__func__, wrole->type);
611 		break;
612 	default:
613 		PHL_TRACE(COMP_PHL_DBG, _PHL_ERR_,
614 			"%s role-type(%d) not support\n",
615 			__func__, wrole->type);
616 		break;
617 	}
618 
619 	_phl_role_notify(phl_info, wrole, rstate);
620 	return RTW_PHL_STATUS_SUCCESS;
621 }
622 
623 
624 /**
625  * This function is called once wifi info changed
626  * (see enum wr_chg_id)
627  * @phl: see phl_info_t
628  * @wrole: information is updated for this wifi role
629  * @chg_id: see enum wr_chg_id
630  * @chg_info: the change info to be update
631  */
632 enum rtw_phl_status
phl_wifi_role_change(struct phl_info_t * phl_info,struct rtw_wifi_role_t * wrole,enum wr_chg_id chg_id,void * chg_info)633 phl_wifi_role_change(struct phl_info_t *phl_info,
634 				struct rtw_wifi_role_t *wrole,
635 				enum wr_chg_id chg_id, void *chg_info)
636 {
637 	enum rtw_phl_status pstate = RTW_PHL_STATUS_FAILURE;
638 	enum rtw_hal_status hstate;
639 
640 	struct rtw_phl_stainfo_t *sta = NULL;
641 	enum phl_upd_mode mode = PHL_UPD_ROLE_MAX;
642 	void *drv = phl_to_drvpriv(phl_info);
643 
644 	switch (chg_id) {
645 	case WR_CHG_TYPE:
646 	{
647 		enum role_type type = *(enum role_type *)chg_info;
648 
649 		if (wrole->type == type) {
650 			PHL_WARN("wrole type(%d) not change\n", wrole->type);
651 			pstate = RTW_PHL_STATUS_SUCCESS;
652 			return pstate;
653 		}
654 		PHL_INFO("wrole type(%d) change to type(%d)\n",
655 							wrole->type, type);
656 
657 		sta = rtw_phl_get_stainfo_self(phl_info, wrole);
658 		if (sta) {
659 			if (type == PHL_RTYPE_TDLS || wrole->type == PHL_RTYPE_TDLS) {
660 				wrole->type = type;
661 				pstate = RTW_PHL_STATUS_SUCCESS;
662 			}
663 			else {
664 				wrole->type = type;
665 				wrole->mstate = MLME_NO_LINK;
666 
667 				#ifdef RTW_WKARD_STA_BCN_INTERVAL
668 				#ifdef RTW_PHL_BCN
669 				if (wrole->type == PHL_RTYPE_AP) {
670 					wrole->bcn_cmn.bcn_interval = 100;
671 					wrole->mstate = MLME_LINKED;
672 					wrole->hiq_win = 16; /* unit: ms */
673 				}
674 				#endif
675 				#endif
676 				phl_init_role_cap(phl_info, wrole);
677 				phl_init_protocol_cap(phl_info, wrole);
678 
679 				rtw_hal_role_cfg(phl_info->hal, wrole);
680 
681 				mode = PHL_UPD_ROLE_TYPE_CHANGE;
682 				_os_mem_cpy(drv, sta->mac_addr, wrole->mac_addr, MAC_ALEN);
683 				pstate = phl_change_stainfo(phl_info, sta, mode);
684 				/*rtw_hal_change_sta_entry(phl_info->hal, sta);*/
685 				_phl_role_notify(phl_info, wrole, PHL_ROLE_CHG_TYPE);
686 			}
687 		}
688 		else {
689 			PHL_ERR("cannot get stainfo_self\n");
690 		}
691 		PHL_DUMP_MR_EX(phl_info);
692 	}
693 		break;
694 	case WR_CHG_MADDR:
695 	{
696 		u8 *maddr = (u8 *)chg_info;
697 
698 		if(_os_mem_cmp(drv, wrole->mac_addr, maddr,  MAC_ALEN) == 0) {
699 			PHL_WARN("wrole maddr %02x:%02x:%02x:%02x:%02x:%02x not change\n",
700 			         maddr[0], maddr[1], maddr[2],
701 			         maddr[3], maddr[4], maddr[5]);
702 			return RTW_PHL_STATUS_SUCCESS;
703 		}
704 		PHL_INFO("wrole maddr %02x:%02x:%02x:%02x:%02x:%02x change to %02x:%02x:%02x:%02x:%02x:%02x\n",
705 		         wrole->mac_addr[0], wrole->mac_addr[1],
706 		         wrole->mac_addr[2], wrole->mac_addr[3],
707 		         wrole->mac_addr[4], wrole->mac_addr[5],
708 		         maddr[0], maddr[1], maddr[2],
709 		         maddr[3], maddr[4], maddr[5]);
710 
711 		_os_mem_cpy(drv, wrole->mac_addr, maddr, MAC_ALEN);
712 		sta = rtw_phl_get_stainfo_self(phl_info, wrole);
713 		if (sta) {
714 			mode = PHL_UPD_ROLE_INFO_CHANGE;
715 			_os_mem_cpy(drv, sta->mac_addr, wrole->mac_addr, MAC_ALEN);
716 			pstate = phl_change_stainfo(phl_info, sta, mode);
717 			/*rtw_hal_change_sta_entry(phl_info->hal, sta);*/
718 		}
719 	}
720 		break;
721 	case WR_CHG_AP_PARAM:
722 	{
723 		struct rtw_ap_param *param = (struct rtw_ap_param *)chg_info;
724 
725 		if (wrole->type != PHL_RTYPE_AP)
726 			break;
727 
728 		if (param->cfg_id == CFG_BSS_CLR) {
729 			u32 bsscolor = param->value;
730 
731 			wrole->proto_role_cap.bsscolor = (u8)bsscolor;
732 			rtw_hal_role_cfg_ex(phl_info->hal, wrole, PCFG_BSS_CLR, &bsscolor);
733 		}
734 		/* else if (param->cfg_id == CFG_HIQ_DTIM) */
735 		else {
736 			PHL_INFO("wrole->type(%d) WR_CHG_AP_PARAM todo.....\n", wrole->type);
737 		}
738 
739 		pstate = RTW_PHL_STATUS_SUCCESS;
740 	}
741 		break;
742 	case WR_CHG_EDCA_PARAM:
743 	{
744 		struct rtw_edca_param *param = (struct rtw_edca_param*)chg_info;
745 
746 		hstate = rtw_hal_set_edca(phl_info->hal, wrole, param->ac,
747 						param->param);
748 		if (hstate == RTW_HAL_STATUS_SUCCESS)
749 			pstate = RTW_PHL_STATUS_SUCCESS;
750 	}
751 		break;
752 	case WR_CHG_MU_EDCA_PARAM:
753 	{
754 		struct rtw_mu_edca_param *param = (struct rtw_mu_edca_param*)chg_info;
755 		hstate = rtw_hal_set_mu_edca(phl_info->hal, wrole->hw_band, param->ac,
756 					param->timer, (param->cw & 0x0f), (param->cw>>4),
757 					param->aifsn);
758 		if (hstate == RTW_HAL_STATUS_SUCCESS)
759 			pstate = RTW_PHL_STATUS_SUCCESS;
760 	}
761 		break;
762 	case WR_CHG_MU_EDCA_CFG:
763 	{
764 		u8 val = *(u8 *)chg_info;
765 		hstate = rtw_hal_set_mu_edca_ctrl(phl_info->hal,
766 					wrole->hw_band, wrole->hw_wmm, val);
767 		if (hstate == RTW_HAL_STATUS_SUCCESS)
768 			pstate = RTW_PHL_STATUS_SUCCESS;
769 	}
770 		break;
771 	case WR_CHG_BSS_COLOR:
772 	{
773 		u32 val = *(u8 *)chg_info;
774 		hstate = rtw_hal_role_cfg_ex(phl_info->hal, wrole, PCFG_BSS_CLR, &val);
775 		if (hstate == RTW_HAL_STATUS_SUCCESS)
776 			pstate = RTW_PHL_STATUS_SUCCESS;
777 	}
778 		break;
779 	case WR_CHG_RTS_TH:
780 	{
781 		struct rtw_rts_threshold *val =
782 				(struct rtw_rts_threshold *)chg_info;
783 
784 		hstate = rtw_hal_config_rts_th(phl_info->hal,
785 					       wrole->hw_band,
786 					       val->rts_time_th,
787 					       val->rts_len_th);
788 		if (hstate == RTW_HAL_STATUS_SUCCESS)
789 			pstate = RTW_PHL_STATUS_SUCCESS;
790 	}
791 	break;
792 	case WR_CHG_DFS_HE_TB_CFG:
793 	{
794 		u8 val = *(u8 *)chg_info;
795 
796 		hstate = rtw_hal_set_dfs_tb_ctrl(phl_info->hal, val);
797 		if (hstate == RTW_HAL_STATUS_SUCCESS)
798 			pstate = RTW_PHL_STATUS_SUCCESS;
799 	}
800 	break;
801 	case WR_CHG_TRX_PATH:
802 	{
803 		struct rtw_trx_path_param *param = (struct rtw_trx_path_param*)chg_info;
804 
805 		hstate = rtw_hal_cfg_trx_path(phl_info->hal,
806 					      param->tx,
807 					      param->tx_nss,
808 					      param->rx,
809 					      param->rx_nss);
810 
811 		if (hstate == RTW_HAL_STATUS_SUCCESS)
812 			pstate = RTW_PHL_STATUS_SUCCESS;
813 	}
814 	break;
815 	case WR_CHG_STBC_CFG:
816 	{
817 		phl_init_proto_stbc_cap(wrole, phl_info, &wrole->proto_role_cap);
818 	}
819 	break;
820 	case WR_CHG_MAX:
821 		PHL_TRACE(COMP_PHL_DBG, _PHL_ERR_,
822 				"%s: Unsupported case:%d, please check it\n",
823 				__func__, chg_id);
824 		break;
825 	default :
826 		PHL_TRACE(COMP_PHL_DBG, _PHL_ERR_,
827 				"%s: unknown chg_id(%d), please check it\n",
828 				__func__, chg_id);
829 		break;
830 	};
831 	return pstate;
832 }
833 
834 #ifdef CONFIG_CMD_DISP
835 struct wr_chg_param {
836 	struct rtw_wifi_role_t *wrole;
837 	enum wr_chg_id id;
838 	u8 *info;
839 	u8 info_len;
840 };
841 
842 enum rtw_phl_status
phl_wifi_role_chg_hdl(struct phl_info_t * phl_info,u8 * param)843 phl_wifi_role_chg_hdl(struct phl_info_t *phl_info, u8 *param)
844 {
845 	struct wr_chg_param *wr_chg = (struct wr_chg_param *)param;
846 
847 	return phl_wifi_role_change(phl_info, wr_chg->wrole, wr_chg->id, wr_chg->info);
848 }
849 
phl_wifi_role_chg_done(void * drv_priv,u8 * cmd,u32 cmd_len,enum rtw_phl_status status)850 void phl_wifi_role_chg_done(void *drv_priv, u8 *cmd, u32 cmd_len,
851 						enum rtw_phl_status status)
852 {
853 	struct wr_chg_param *wr_chg = NULL;
854 
855 	if (cmd == NULL || cmd_len == 0) {
856 		PHL_ERR("%s buf == NULL || buf_len == 0\n", __func__);
857 		_os_warn_on(1);
858 		return;
859 	}
860 
861 	wr_chg = (struct wr_chg_param *)cmd;
862 	PHL_INFO("%s - id:%d .....\n", __func__, wr_chg->id);
863 
864 	if (wr_chg->info)
865 		_os_kmem_free(drv_priv, wr_chg->info, wr_chg->info_len);
866 
867 	_os_kmem_free(drv_priv, cmd, cmd_len);
868 	cmd = NULL;
869 }
870 
871 enum rtw_phl_status
rtw_phl_cmd_wrole_change(void * phl,struct rtw_wifi_role_t * wrole,enum wr_chg_id chg_id,u8 * chg_info,u8 chg_info_len,enum phl_cmd_type cmd_type,u32 cmd_timeout)872 rtw_phl_cmd_wrole_change(void *phl,
873                          struct rtw_wifi_role_t *wrole,
874                          enum wr_chg_id chg_id,
875                          u8 *chg_info,
876                          u8 chg_info_len,
877                          enum phl_cmd_type cmd_type,
878                          u32 cmd_timeout)
879 {
880 
881 	enum rtw_phl_status psts = RTW_PHL_STATUS_FAILURE;
882 	struct phl_info_t *phl_info = (struct phl_info_t *)phl;
883 	void *drv = phl_to_drvpriv(phl_info);
884 	struct wr_chg_param *wr_chg = NULL;
885 	u32 wr_chg_len = 0;
886 
887 	if (cmd_type == PHL_CMD_DIRECTLY) {
888 		psts = phl_wifi_role_change(phl_info, wrole, chg_id, chg_info);
889 		goto _exit;
890 	}
891 
892 	wr_chg_len = sizeof(struct wr_chg_param);
893 	wr_chg = _os_kmem_alloc(drv, wr_chg_len);
894 	if (wr_chg == NULL) {
895 		PHL_ERR("%s: alloc wr_chg_param failed!\n", __func__);
896 		psts = RTW_PHL_STATUS_RESOURCE;
897 		goto _exit;
898 	}
899 	_os_mem_set(drv, wr_chg, 0, wr_chg_len);
900 	wr_chg->wrole = wrole;
901 	wr_chg->id = chg_id;
902 
903 	wr_chg->info_len = chg_info_len;
904 	wr_chg->info = _os_kmem_alloc(drv, chg_info_len);
905 	if (wr_chg->info == NULL) {
906 		PHL_ERR("%s: alloc wr_chg_info failed!\n", __func__);
907 		psts = RTW_PHL_STATUS_RESOURCE;
908 		goto _err_info;
909 	}
910 	_os_mem_set(drv, wr_chg->info, 0, chg_info_len);
911 	_os_mem_cpy(drv, wr_chg->info, chg_info, chg_info_len);
912 
913 	psts = phl_cmd_enqueue(phl_info,
914 	                       wrole->hw_band,
915 	                       MSG_EVT_ROLE_CHANGE,
916 	                       (u8*)wr_chg,
917 	                       wr_chg_len,
918 	                       phl_wifi_role_chg_done,
919 	                       cmd_type,
920 	                       cmd_timeout);
921 
922 	if (is_cmd_failure(psts)) {
923 		/* Send cmd success, but wait cmd fail*/
924 		psts = RTW_PHL_STATUS_FAILURE;
925 		PHL_INFO("%s wr-id:%d failure\n", __func__, wrole->id);
926 	} else if (psts != RTW_PHL_STATUS_SUCCESS) {
927 		/* Send cmd fail */
928 		psts = RTW_PHL_STATUS_FAILURE;
929 		PHL_INFO("%s wr-id:%d failure\n", __func__, wrole->id);
930 		goto _err_cmd;
931 	} else {
932 		PHL_INFO("%s wr-id:%d success\n", __func__, wrole->id);
933 	}
934 
935 	return psts;
936 
937 _err_cmd:
938 	if (wr_chg->info)
939 		_os_kmem_free(drv, wr_chg->info, wr_chg->info_len);
940 _err_info:
941 	if (wr_chg)
942 		_os_kmem_free(drv, wr_chg, wr_chg_len);
943 _exit:
944 	return psts;
945 }
946 
947 #else
948 enum rtw_phl_status
rtw_phl_cmd_wrole_change(void * phl,struct rtw_wifi_role_t * wrole,enum wr_chg_id chg_id,u8 * chg_info,u8 chg_info_len,enum phl_cmd_type cmd_type,u32 cmd_timeout)949 rtw_phl_cmd_wrole_change(void *phl,
950 			struct rtw_wifi_role_t *wrole,
951 			enum wr_chg_id chg_id, u8 *chg_info, u8 chg_info_len,
952 			enum phl_cmd_type cmd_type, u32 cmd_timeout)
953 {
954 	return phl_wifi_role_change((struct phl_info_t *)phl, wrole, chg_id, chg_info);
955 }
956 #endif /*CONFIG_CMD_DISP*/
957 
958 enum rtw_phl_status
_phl_wifi_role_stop(struct phl_info_t * phl_info,struct rtw_wifi_role_t * wrole)959 _phl_wifi_role_stop(struct phl_info_t *phl_info, struct rtw_wifi_role_t *wrole)
960 {
961 	enum rtw_phl_status psts = RTW_PHL_STATUS_FAILURE;
962 
963 	wrole->active = false;
964 	_phl_role_notify(phl_info, wrole, PHL_ROLE_STOP);
965 	psts = phl_wifi_role_free_stainfo_hw(phl_info, wrole);
966 	if (psts != RTW_PHL_STATUS_SUCCESS) {
967 		PHL_ERR("%s wr free stainfo_hw failed\n", __func__);
968 		_os_warn_on(1);
969 	}
970 
971 	/*hw port cfg - mac_port_deinit*/
972 	return psts;
973 }
974 #ifdef CONFIG_CMD_DISP
975 enum rtw_phl_status
phl_wifi_role_stop_hdl(struct phl_info_t * phl_info,u8 * param)976 phl_wifi_role_stop_hdl(struct phl_info_t *phl_info, u8 *param)
977 {
978 	struct rtw_wifi_role_t *wrole = (struct rtw_wifi_role_t *)param;
979 
980 	return _phl_wifi_role_stop(phl_info, wrole);
981 }
phl_wifi_role_stop_done(void * drv_priv,u8 * cmd,u32 cmd_len,enum rtw_phl_status status)982 void phl_wifi_role_stop_done(void *drv_priv, u8 *cmd, u32 cmd_len,
983 						enum rtw_phl_status status)
984 {
985 	if (cmd) {
986 		struct rtw_wifi_role_t *wrole = NULL;
987 
988 		wrole = (struct rtw_wifi_role_t *)cmd;
989 		if (is_cmd_failure(status) && (RTW_PHL_STATUS_SUCCESS != status))
990 			PHL_ERR("%s wrole(%d) fail status(%d).....\n",
991 				__func__, wrole->id, status);
992 		else
993 			PHL_INFO("%s wrole(%d) success.....\n",
994 				__func__, wrole->id);
995 	}
996 }
997 
998 enum rtw_phl_status
phl_wifi_role_stop(struct phl_info_t * phl_info,struct rtw_wifi_role_t * wrole)999 phl_wifi_role_stop(struct phl_info_t *phl_info, struct rtw_wifi_role_t *wrole)
1000 {
1001 	enum rtw_phl_status psts = RTW_PHL_STATUS_FAILURE;
1002 
1003 	psts = phl_cmd_enqueue(phl_info,
1004 			wrole->hw_band,
1005 			MSG_EVT_ROLE_STOP,
1006 			(u8 *)wrole,
1007 			0,
1008 			phl_wifi_role_stop_done,
1009 			PHL_CMD_WAIT, 0);
1010 
1011 	if (is_cmd_failure(psts)) {
1012 		/* Send cmd success, but wait cmd fail*/
1013 		psts = RTW_PHL_STATUS_FAILURE;
1014 		PHL_INFO("%s wr-id:%d failure\n", __func__, wrole->id);
1015 	} else if (psts != RTW_PHL_STATUS_SUCCESS) {
1016 		/* Send cmd fail */
1017 		psts = RTW_PHL_STATUS_FAILURE;
1018 		PHL_INFO("%s wr-id:%d failure\n", __func__, wrole->id);
1019 	} else {
1020 		PHL_INFO("%s wr-id:%d success\n", __func__, wrole->id);
1021 	}
1022 
1023 	return psts;
1024 }
1025 #else
1026 enum rtw_phl_status
phl_wifi_role_stop(struct phl_info_t * phl_info,struct rtw_wifi_role_t * wrole)1027 phl_wifi_role_stop(struct phl_info_t *phl_info, struct rtw_wifi_role_t *wrole)
1028 {
1029 	return _phl_wifi_role_stop(phl_info, wrole);
1030 }
1031 #endif
rtw_phl_wifi_role_free(void * phl,u8 role_idx)1032 void rtw_phl_wifi_role_free(void *phl, u8 role_idx)
1033 {
1034 	struct phl_info_t *phl_info = (struct phl_info_t *)phl;
1035 	struct rtw_phl_com_t *phl_com = phl_info->phl_com;
1036 	struct rtw_wifi_role_t *wrole = NULL;
1037 
1038 	if (role_idx >= MAX_WIFI_ROLE_NUMBER) {
1039 		PHL_ERR("%s invalid role index :%d", __func__, role_idx);
1040 		return;
1041 	}
1042 
1043 	wrole = &phl_com->wifi_roles[role_idx];
1044 
1045 	if (phl_wifi_role_stop(phl_info, wrole) != RTW_PHL_STATUS_SUCCESS) {
1046 		PHL_ERR("%s role_stop failed :%d", __func__, role_idx);
1047 		_os_warn_on(1);
1048 	}
1049 
1050 	if (phl_wifi_role_free_stainfo_sw(phl_info, wrole) != RTW_PHL_STATUS_SUCCESS) {
1051 		PHL_ERR("%s wr free stainfo_sw failed\n", __func__);
1052 		_os_warn_on(1);
1053 	}
1054 	_phl_wifi_role_free_sw(phl_info, wrole);
1055 	PHL_DUMP_MR_EX(phl_info);
1056 }
1057 
1058 #ifdef CONFIG_CMD_DISP
1059 enum rtw_phl_status
phl_register_mrc_module(struct phl_info_t * phl_info)1060 phl_register_mrc_module(struct phl_info_t *phl_info)
1061 {
1062 	enum rtw_phl_status phl_status = RTW_PHL_STATUS_FAILURE;
1063 	struct mr_ctl_t *mr_ctl = phlcom_to_mr_ctrl(phl_info->phl_com);
1064 	struct phl_bk_module_ops bk_ops = mr_ctl->bk_ops;
1065 	struct phl_cmd_dispatch_engine *disp_eng = &(phl_info->disp_eng);
1066 	u8 i = 0;
1067 
1068 	for(i = 0; i < disp_eng->phy_num; i++)
1069 	{
1070 		phl_status = phl_disp_eng_register_module(phl_info, i,
1071 						       PHL_MDL_MRC,
1072 						       &bk_ops);
1073 		if (RTW_PHL_STATUS_SUCCESS != phl_status) {
1074 			PHL_ERR("%s register MRC module in cmd disp failed :%d\n", __func__, i+1);
1075 			goto error_register_bk;
1076 		}
1077 	}
1078 
1079 	return phl_status;
1080 
1081 error_register_bk:
1082 	while(i > 0){
1083 		phl_status = phl_disp_eng_deregister_module(phl_info, --i,
1084 							 PHL_MDL_MRC);
1085 		if (RTW_PHL_STATUS_SUCCESS != phl_status) {
1086 			PHL_ERR("%s deregister MRC module in cmd disp failed :%d\n", __func__, i+1);
1087 		}
1088 	}
1089 	return RTW_PHL_STATUS_FAILURE;
1090 }
1091 #endif
1092 
1093 enum rtw_phl_status
phl_role_recover(struct phl_info_t * phl_info)1094 phl_role_recover(struct phl_info_t *phl_info)
1095 {
1096 	u8 role_idx;
1097 	struct rtw_wifi_role_t *wrole;
1098 	struct rtw_phl_stainfo_t *sta;
1099 	enum rtw_phl_status pstatus;
1100 
1101 	for (role_idx = 0; role_idx < MAX_WIFI_ROLE_NUMBER; role_idx++) {
1102 		wrole = rtw_phl_get_wrole_by_ridx(phl_info->phl_com, role_idx);
1103 		if(wrole == NULL)
1104 			continue;
1105 
1106 		PHL_INFO("%s with role_idx %d\n", __func__, role_idx);
1107 
1108 		sta = rtw_phl_get_stainfo_self(phl_info, wrole);
1109 		if(sta == NULL)
1110 			continue;
1111 
1112 		pstatus = _phl_wifi_role_start(phl_info, wrole, sta);
1113 		if (pstatus != RTW_PHL_STATUS_SUCCESS) {
1114 			PHL_ERR("%s wifi role start failed\n", __func__);
1115 			return RTW_PHL_STATUS_FAILURE;
1116 		}
1117 
1118 		if (wrole->target_type != PHL_RTYPE_NONE) {
1119 			PHL_INFO("%s with role_idx %d change to role type %d\n", __func__, role_idx, wrole->target_type);
1120 			phl_wifi_role_change(phl_info, wrole, WR_CHG_TYPE, (u8 *)&wrole->target_type);
1121 			wrole->target_type = PHL_RTYPE_NONE;
1122 		}
1123 	}
1124 
1125 	return RTW_PHL_STATUS_SUCCESS;
1126 }
1127 
1128 enum rtw_phl_status
phl_cmd_role_recover(struct phl_info_t * phl_info)1129 phl_cmd_role_recover(struct phl_info_t *phl_info)
1130 {
1131 	enum rtw_phl_status pstatus = RTW_PHL_STATUS_FAILURE;
1132 
1133 #ifdef CONFIG_CMD_DISP
1134 	pstatus = phl_cmd_enqueue(phl_info, HW_BAND_0, MSG_EVT_ROLE_RECOVER, NULL, 0, NULL, PHL_CMD_WAIT, 0);
1135 	if (is_cmd_failure(pstatus)) {
1136 		/* Send cmd success, but wait cmd fail*/
1137 		pstatus = RTW_PHL_STATUS_FAILURE;
1138 	} else if (pstatus != RTW_PHL_STATUS_SUCCESS) {
1139 		/* Send cmd fail */
1140 		pstatus = RTW_PHL_STATUS_FAILURE;
1141 	}
1142 #else
1143 	pstatus = phl_role_recover(phl_info);
1144 #endif
1145 	return pstatus;
1146 }
1147 
1148 enum rtw_phl_status
phl_role_suspend(struct phl_info_t * phl_info)1149 phl_role_suspend(struct phl_info_t *phl_info)
1150 {
1151 	u8 role_idx;
1152 	struct rtw_wifi_role_t *wrole;
1153 	enum rtw_phl_status pstatus;
1154 
1155 	for (role_idx = 0; role_idx < MAX_WIFI_ROLE_NUMBER; role_idx++) {
1156 		wrole = rtw_phl_get_wrole_by_ridx(phl_info->phl_com, role_idx);
1157 		if (wrole == NULL)
1158 			continue;
1159 
1160 		if (wrole->active == false)
1161 			continue;
1162 
1163 		PHL_INFO("%s with role_idx %d\n", __func__, role_idx);
1164 
1165 		pstatus = _phl_wifi_role_stop(phl_info, wrole);
1166 		if (pstatus != RTW_PHL_STATUS_SUCCESS) {
1167 			PHL_ERR("%s wifi role stop failed\n", __func__);
1168 			return RTW_PHL_STATUS_FAILURE;
1169 		}
1170 	}
1171 
1172 	return RTW_PHL_STATUS_SUCCESS;
1173 }
1174 enum rtw_phl_status
phl_cmd_role_suspend(struct phl_info_t * phl_info)1175 phl_cmd_role_suspend(struct phl_info_t *phl_info)
1176 {
1177 	enum rtw_phl_status pstatus = RTW_PHL_STATUS_FAILURE;
1178 
1179 #ifdef CONFIG_CMD_DISP
1180 	pstatus = phl_cmd_enqueue(phl_info, HW_BAND_0, MSG_EVT_ROLE_SUSPEND, NULL, 0, NULL, PHL_CMD_WAIT, 0);
1181 	if (is_cmd_failure(pstatus)) {
1182 		/* Send cmd success, but wait cmd fail*/
1183 		pstatus = RTW_PHL_STATUS_FAILURE;
1184 	} else if (pstatus != RTW_PHL_STATUS_SUCCESS) {
1185 		/* Send cmd fail */
1186 		pstatus = RTW_PHL_STATUS_FAILURE;
1187 	}
1188 #else
1189 	pstatus = phl_role_suspend(phl_info);
1190 #endif
1191 	return pstatus;
1192 }
1193 
phl_role_get_bcn_intvl(struct phl_info_t * phl,struct rtw_wifi_role_t * wrole)1194 u16 phl_role_get_bcn_intvl(struct phl_info_t *phl, struct rtw_wifi_role_t *wrole)
1195 {
1196 	struct rtw_phl_stainfo_t *sta = rtw_phl_get_stainfo_self(phl, wrole);
1197 	u16 bcn_intvl = 0;
1198 
1199 	if (phl_role_is_client_category(wrole)) {
1200 		bcn_intvl = sta->asoc_cap.bcn_interval;
1201 #ifdef RTW_PHL_BCN
1202 	} else if (phl_role_is_ap_category(wrole)) {
1203 		bcn_intvl = (u16)wrole->bcn_cmn.bcn_interval;
1204 #endif
1205 	} else {
1206 		PHL_WARN("phl_role_get_bcn_intvl() Unknown category, role id(%d), type(%d)\n",
1207 			wrole->id, wrole->type);
1208 	}
1209 	return bcn_intvl;
1210 }
1211 
1212 enum rtw_phl_status
phl_wifi_role_macid_all_pause(struct phl_info_t * phl_info,struct rtw_wifi_role_t * wrole,bool pause)1213 phl_wifi_role_macid_all_pause(struct phl_info_t *phl_info, struct rtw_wifi_role_t *wrole, bool pause)
1214 {
1215 	enum rtw_hal_status hstatus = RTW_HAL_STATUS_SUCCESS;
1216 	enum rtw_phl_status pstatus = RTW_PHL_STATUS_SUCCESS;
1217 	u8 mutli_macid = false;
1218 
1219 	switch (wrole->type) {
1220 	case PHL_RTYPE_NONE:
1221 	case PHL_RTYPE_STATION:
1222 	case PHL_RTYPE_ADHOC:
1223 	case PHL_RTYPE_P2P_DEVICE:
1224 	case PHL_RTYPE_P2P_GC:
1225 		mutli_macid = false;
1226 		break;
1227 	default:
1228 		mutli_macid = true;
1229 		break;
1230 	}
1231 
1232 	if (mutli_macid) {
1233 		void *drv = phl_to_drvpriv(phl_info);
1234 		struct macid_ctl_t *mctrl = phl_to_mac_ctrl(phl_info);
1235 		u32 macid_pause[PHL_MACID_MAX_ARRAY_NUM] = {0};
1236 
1237 		_os_spinlock(phl_to_drvpriv(phl_info), &mctrl->lock, _bh, NULL);
1238 		_os_mem_cpy(drv, macid_pause, &mctrl->wifi_role_usedmap[wrole->id][0], PHL_MACID_MAX_ARRAY_NUM);
1239 		_os_spinunlock(phl_to_drvpriv(phl_info), &mctrl->lock, _bh, NULL);
1240 		hstatus = rtw_hal_set_macid_grp_pause(phl_info->hal, macid_pause, PHL_MACID_MAX_ARRAY_NUM, pause);
1241 		if (hstatus != RTW_HAL_STATUS_SUCCESS) {
1242 			PHL_INFO("%s fail(hstatus=%d)\n", __func__, hstatus);
1243 			pstatus = RTW_PHL_STATUS_FAILURE;
1244 		}
1245 	} else {
1246 		struct rtw_phl_stainfo_t * self_sta = rtw_phl_get_stainfo_self((void *)phl_info, wrole);
1247 
1248 		hstatus = rtw_hal_set_macid_pause(phl_info->hal, self_sta->macid, pause);
1249 		if (hstatus != RTW_HAL_STATUS_SUCCESS) {
1250 			PHL_INFO("%s fail(hstatus=%d)\n", __func__, hstatus);
1251 			pstatus = RTW_PHL_STATUS_FAILURE;
1252 		}
1253 	}
1254 
1255 	return pstatus;
1256 }
1257