xref: /OK3568_Linux_fs/external/rkwifibt/drivers/rtl8852bs/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 	return RTW_PHL_STATUS_SUCCESS;
399 }
400 
401 #ifdef CONFIG_CMD_DISP
402 struct wr_start_param {
403 	struct rtw_wifi_role_t *wrole;
404 	struct rtw_phl_stainfo_t *sta;
405 };
406 
407 enum rtw_phl_status
phl_wifi_role_start_hdl(struct phl_info_t * phl_info,u8 * param)408 phl_wifi_role_start_hdl(struct phl_info_t *phl_info, u8 *param)
409 {
410 	struct wr_start_param *cmd_wr = (struct wr_start_param *)param;
411 
412 	return _phl_wifi_role_start(phl_info, cmd_wr->wrole, cmd_wr->sta);
413 }
414 
phl_wifi_role_start_done(void * drv_priv,u8 * cmd,u32 cmd_len,enum rtw_phl_status status)415 void phl_wifi_role_start_done(void *drv_priv, u8 *cmd, u32 cmd_len,
416 						enum rtw_phl_status status)
417 {
418 	if (cmd) {
419 		_os_kmem_free(drv_priv, cmd, cmd_len);
420 		cmd = NULL;
421 		PHL_INFO("%s.....\n", __func__);
422 	}
423 }
424 
425 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)426 phl_wifi_role_start(struct phl_info_t *phl_info,
427 				struct rtw_wifi_role_t *wrole,
428 				struct rtw_phl_stainfo_t *sta)
429 {
430 	enum rtw_phl_status psts = RTW_PHL_STATUS_FAILURE;
431 	struct wr_start_param *wr_start = NULL;
432 	void *drv = phl_to_drvpriv(phl_info);
433 	u32 wr_start_len;
434 
435 	wr_start_len = sizeof(struct wr_start_param);
436 	wr_start = _os_kmem_alloc(drv, wr_start_len);
437 	if (wr_start == NULL) {
438 		PHL_ERR("%s: alloc wr_start_param failed!\n", __func__);
439 		psts = RTW_PHL_STATUS_RESOURCE;
440 		goto _exit;
441 	}
442 	wr_start->wrole = wrole;
443 	wr_start->sta = sta;
444 
445 	psts = phl_cmd_enqueue(phl_info,
446 				wrole->hw_band,
447 				MSG_EVT_ROLE_START,
448 				(u8*)wr_start,
449 				wr_start_len,
450 				phl_wifi_role_start_done,
451 				PHL_CMD_WAIT,
452 				0);
453 
454 	if (is_cmd_failure(psts)) {
455 		/* Send cmd success, but wait cmd fail*/
456 		psts = RTW_PHL_STATUS_FAILURE;
457 		PHL_INFO("%s wr-id:%d failure\n", __func__, wrole->id);
458 	} else if (psts != RTW_PHL_STATUS_SUCCESS) {
459 		/* Send cmd fail */
460 		_os_kmem_free(drv, wr_start, wr_start_len);
461 		psts = RTW_PHL_STATUS_FAILURE;
462 		PHL_INFO("%s wr-id:%d failure\n", __func__, wrole->id);
463 	} else {
464 		PHL_INFO("%s wr-id:%d success\n", __func__, wrole->id);
465 	}
466 
467 _exit:
468 	return psts;
469 }
470 #else
471 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)472 phl_wifi_role_start(struct phl_info_t *phl_info,
473 				struct rtw_wifi_role_t *wrole,
474 				struct rtw_phl_stainfo_t *sta)
475 {
476 	return _phl_wifi_role_start(phl_info, wrole, sta);
477 }
478 #endif
479 
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)480 u8 rtw_phl_wifi_role_alloc(void *phl, u8 *mac_addr, enum role_type type,
481 				u8 ridx, struct rtw_wifi_role_t **wifi_role, bool ignore_hw_fail)
482 {
483 	struct phl_info_t *phl_info = (struct phl_info_t *)phl;
484 	struct rtw_phl_com_t *phl_com = phl_info->phl_com;
485 	u8 role_idx = INVALID_WIFI_ROLE_IDX;
486 	struct rtw_wifi_role_t *role = NULL;
487 	struct rtw_phl_stainfo_t *phl_sta = NULL;
488 	enum rtw_phl_status psts = RTW_PHL_STATUS_FAILURE;
489 
490 	if (mac_addr == NULL) {
491 		PHL_ERR("%s mac_addr == NULL\n", __func__);
492 		goto _exit;
493 	}
494 
495 	/*search rid by mac_addr, if had assigned then return role index*/
496 	role_idx = _phl_search_roleidx_by_addr(phl_info, mac_addr);
497 	if (role_idx != INVALID_WIFI_ROLE_IDX) {
498 		PHL_INFO("%s wifi-role(%d) had allociated\n", __func__, role_idx);
499 		*wifi_role = &phl_com->wifi_roles[role_idx];
500 		goto _exit;
501 	}
502 
503 	role = _phl_wifi_role_alloc_sw(phl_info, mac_addr, type, ridx);
504 	if (role == NULL) {
505 		PHL_ERR("%s role alloc sw failed\n", __func__);
506 		_os_warn_on(1);
507 		goto _exit;
508 	}
509 
510 	/*alloc sta_info for self*/
511 	phl_sta = phl_alloc_stainfo_sw(phl_info, role->mac_addr, role);
512 	if (phl_sta == NULL) {
513 		PHL_ERR("%s can't alloc self stainfo_sw\n", __func__);
514 		_os_warn_on(1);
515 		goto _err_stainfo_sw;
516 	}
517 
518 	psts = phl_wifi_role_start(phl_info, role, phl_sta);
519 	if (psts != RTW_PHL_STATUS_SUCCESS) {
520 		PHL_ERR("%s role start failed\n", __func__);
521 		if (!ignore_hw_fail) {
522 			_os_warn_on(1);
523 			goto _err_role_start;
524 		}
525 	}
526 
527 	*wifi_role = role;
528 	role_idx = role->id;
529 	PHL_DUMP_MR_EX(phl_info);
530 	return role_idx;
531 
532 _err_role_start:
533 	phl_wifi_role_free_stainfo_sw(phl_info, role);
534 
535 _err_stainfo_sw:
536 	_phl_wifi_role_free_sw(phl_info, role);
537 
538 _exit:
539 	return role_idx;
540 }
541 
542 enum rtw_phl_status
phl_role_noa_notify(struct phl_info_t * phl_info,struct rtw_wifi_role_t * wrole)543 phl_role_noa_notify(struct phl_info_t *phl_info, struct rtw_wifi_role_t *wrole)
544 {
545 	_phl_role_notify(phl_info, wrole, PHL_ROLE_UPDATE_NOA);
546 
547 	return RTW_PHL_STATUS_SUCCESS;
548 }
549 
550 enum rtw_phl_status
phl_role_ap_client_notify(struct phl_info_t * phl_info,struct rtw_wifi_role_t * wrole,u8 link_sts)551 phl_role_ap_client_notify(struct phl_info_t *phl_info,
552 			struct rtw_wifi_role_t *wrole, u8 link_sts)
553 {
554 	enum role_state rstate;
555 
556 	if (link_sts == MLME_LINKING)
557 		rstate = PHL_ROLE_MSTS_STA_CONN_START;
558 	else if (link_sts == MLME_LINKED)
559 		rstate = PHL_ROLE_MSTS_STA_CONN_END;
560 	else
561 		rstate = PHL_ROLE_MSTS_STA_DIS_CONN;
562 
563 	_phl_role_notify(phl_info, wrole, rstate);
564 #ifdef CONFIG_MCC_SUPPORT
565 	phl_mcc_client_link_notify_for_ap(phl_info, wrole, rstate);
566 #endif /* CONFIG_MCC_SUPPORT */
567 	return RTW_PHL_STATUS_SUCCESS;
568 }
569 
570 enum rtw_phl_status
phl_role_notify(struct phl_info_t * phl_info,struct rtw_wifi_role_t * wrole)571 phl_role_notify(struct phl_info_t *phl_info, struct rtw_wifi_role_t *wrole)
572 {
573 	enum role_state rstate = PHL_ROLE_STATE_UNKNOWN;
574 
575 	switch (wrole->type) {
576 	case PHL_RTYPE_STATION:
577 	case PHL_RTYPE_P2P_GC:
578 	{
579 		if (wrole->mstate == MLME_LINKING)
580 			rstate = PHL_ROLE_MSTS_STA_CONN_START;
581 		else if (wrole->mstate == MLME_LINKED)
582 			rstate = PHL_ROLE_MSTS_STA_CONN_END;
583 		else
584 			rstate = PHL_ROLE_MSTS_STA_DIS_CONN;
585 	}
586 	break;
587 
588 	case PHL_RTYPE_AP:
589 	case PHL_RTYPE_VAP:
590 	case PHL_RTYPE_MESH:
591 	case PHL_RTYPE_P2P_GO:
592 	{
593 		rstate = (wrole->mstate == MLME_NO_LINK)
594 			? PHL_ROLE_MSTS_AP_STOP
595 			: PHL_ROLE_MSTS_AP_START;
596 	}
597 	break;
598 
599 	case PHL_RTYPE_NONE:
600 	case PHL_RTYPE_ADHOC:
601 	case PHL_RTYPE_ADHOC_MASTER:
602 	case PHL_RTYPE_MONITOR:
603 	case PHL_RTYPE_P2P_DEVICE:
604 	case PHL_RTYPE_NAN:
605 	case PHL_MLME_MAX:
606 		PHL_TRACE(COMP_PHL_DBG, _PHL_ERR_,
607 			"%s: Unsupported case:%d in wrole notify, please check it\n",
608 			__func__, wrole->type);
609 		break;
610 	default:
611 		PHL_TRACE(COMP_PHL_DBG, _PHL_ERR_,
612 			"%s role-type(%d) not support\n",
613 			__func__, wrole->type);
614 		break;
615 	}
616 
617 	_phl_role_notify(phl_info, wrole, rstate);
618 	return RTW_PHL_STATUS_SUCCESS;
619 }
620 
621 
622 /**
623  * This function is called once wifi info changed
624  * (see enum wr_chg_id)
625  * @phl: see phl_info_t
626  * @wrole: information is updated for this wifi role
627  * @chg_id: see enum wr_chg_id
628  * @chg_info: the change info to be update
629  */
630 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)631 phl_wifi_role_change(struct phl_info_t *phl_info,
632 				struct rtw_wifi_role_t *wrole,
633 				enum wr_chg_id chg_id, void *chg_info)
634 {
635 	enum rtw_phl_status pstate = RTW_PHL_STATUS_FAILURE;
636 	enum rtw_hal_status hstate;
637 
638 	struct rtw_phl_stainfo_t *sta = NULL;
639 	enum phl_upd_mode mode = PHL_UPD_ROLE_MAX;
640 	void *drv = phl_to_drvpriv(phl_info);
641 
642 	switch (chg_id) {
643 	case WR_CHG_TYPE:
644 	{
645 		enum role_type type = *(enum role_type *)chg_info;
646 
647 		if (wrole->type == type) {
648 			PHL_WARN("wrole type(%d) not change\n", wrole->type);
649 			pstate = RTW_PHL_STATUS_SUCCESS;
650 			return pstate;
651 		}
652 		PHL_INFO("wrole type(%d) change to type(%d)\n",
653 							wrole->type, type);
654 
655 		sta = rtw_phl_get_stainfo_self(phl_info, wrole);
656 		if (sta) {
657 			if (type == PHL_RTYPE_TDLS || wrole->type == PHL_RTYPE_TDLS) {
658 				wrole->type = type;
659 				pstate = RTW_PHL_STATUS_SUCCESS;
660 			}
661 			else {
662 				wrole->type = type;
663 				wrole->mstate = MLME_NO_LINK;
664 
665 				#ifdef RTW_WKARD_STA_BCN_INTERVAL
666 				#ifdef RTW_PHL_BCN
667 				if (wrole->type == PHL_RTYPE_AP) {
668 					wrole->bcn_cmn.bcn_interval = 100;
669 					wrole->mstate = MLME_LINKED;
670 					wrole->hiq_win = 16; /* unit: ms */
671 				}
672 				#endif
673 				#endif
674 				phl_init_role_cap(phl_info, wrole);
675 				phl_init_protocol_cap(phl_info, wrole);
676 
677 				rtw_hal_role_cfg(phl_info->hal, wrole);
678 
679 				mode = PHL_UPD_ROLE_TYPE_CHANGE;
680 				_os_mem_cpy(drv, sta->mac_addr, wrole->mac_addr, MAC_ALEN);
681 				pstate = phl_change_stainfo(phl_info, sta, mode);
682 				/*rtw_hal_change_sta_entry(phl_info->hal, sta);*/
683 				_phl_role_notify(phl_info, wrole, PHL_ROLE_CHG_TYPE);
684 			}
685 		}
686 		else {
687 			PHL_ERR("cannot get stainfo_self\n");
688 		}
689 		PHL_DUMP_MR_EX(phl_info);
690 	}
691 		break;
692 	case WR_CHG_MADDR:
693 	{
694 		u8 *maddr = (u8 *)chg_info;
695 
696 		if(_os_mem_cmp(drv, wrole->mac_addr, maddr,  MAC_ALEN) == 0) {
697 			PHL_WARN("wrole maddr %02x:%02x:%02x:%02x:%02x:%02x not change\n",
698 			         maddr[0], maddr[1], maddr[2],
699 			         maddr[3], maddr[4], maddr[5]);
700 			return RTW_PHL_STATUS_SUCCESS;
701 		}
702 		PHL_INFO("wrole maddr %02x:%02x:%02x:%02x:%02x:%02x change to %02x:%02x:%02x:%02x:%02x:%02x\n",
703 		         wrole->mac_addr[0], wrole->mac_addr[1],
704 		         wrole->mac_addr[2], wrole->mac_addr[3],
705 		         wrole->mac_addr[4], wrole->mac_addr[5],
706 		         maddr[0], maddr[1], maddr[2],
707 		         maddr[3], maddr[4], maddr[5]);
708 
709 		_os_mem_cpy(drv, wrole->mac_addr, maddr, MAC_ALEN);
710 		sta = rtw_phl_get_stainfo_self(phl_info, wrole);
711 		if (sta) {
712 			mode = PHL_UPD_ROLE_INFO_CHANGE;
713 			_os_mem_cpy(drv, sta->mac_addr, wrole->mac_addr, MAC_ALEN);
714 			pstate = phl_change_stainfo(phl_info, sta, mode);
715 			/*rtw_hal_change_sta_entry(phl_info->hal, sta);*/
716 		}
717 	}
718 		break;
719 	case WR_CHG_AP_PARAM:
720 	{
721 		struct rtw_ap_param *param = (struct rtw_ap_param *)chg_info;
722 
723 		if (wrole->type != PHL_RTYPE_AP)
724 			break;
725 
726 		if (param->cfg_id == CFG_BSS_CLR) {
727 			u32 bsscolor = param->value;
728 
729 			wrole->proto_role_cap.bsscolor = (u8)bsscolor;
730 			rtw_hal_role_cfg_ex(phl_info->hal, wrole, PCFG_BSS_CLR, &bsscolor);
731 		}
732 		/* else if (param->cfg_id == CFG_HIQ_DTIM) */
733 		else {
734 			PHL_INFO("wrole->type(%d) WR_CHG_AP_PARAM todo.....\n", wrole->type);
735 		}
736 
737 		pstate = RTW_PHL_STATUS_SUCCESS;
738 	}
739 		break;
740 	case WR_CHG_EDCA_PARAM:
741 	{
742 		struct rtw_edca_param *param = (struct rtw_edca_param*)chg_info;
743 
744 		hstate = rtw_hal_set_edca(phl_info->hal, wrole, param->ac,
745 						param->param);
746 		if (hstate == RTW_HAL_STATUS_SUCCESS)
747 			pstate = RTW_PHL_STATUS_SUCCESS;
748 	}
749 		break;
750 	case WR_CHG_MU_EDCA_PARAM:
751 	{
752 		struct rtw_mu_edca_param *param = (struct rtw_mu_edca_param*)chg_info;
753 		hstate = rtw_hal_set_mu_edca(phl_info->hal, wrole->hw_band, param->ac,
754 					param->timer, (param->cw & 0x0f), (param->cw>>4),
755 					param->aifsn);
756 		if (hstate == RTW_HAL_STATUS_SUCCESS)
757 			pstate = RTW_PHL_STATUS_SUCCESS;
758 	}
759 		break;
760 	case WR_CHG_MU_EDCA_CFG:
761 	{
762 		u8 val = *(u8 *)chg_info;
763 		hstate = rtw_hal_set_mu_edca_ctrl(phl_info->hal,
764 					wrole->hw_band, wrole->hw_wmm, val);
765 		if (hstate == RTW_HAL_STATUS_SUCCESS)
766 			pstate = RTW_PHL_STATUS_SUCCESS;
767 	}
768 		break;
769 	case WR_CHG_BSS_COLOR:
770 	{
771 		u32 val = *(u8 *)chg_info;
772 		hstate = rtw_hal_role_cfg_ex(phl_info->hal, wrole, PCFG_BSS_CLR, &val);
773 		if (hstate == RTW_HAL_STATUS_SUCCESS)
774 			pstate = RTW_PHL_STATUS_SUCCESS;
775 	}
776 		break;
777 	case WR_CHG_RTS_TH:
778 	{
779 		struct rtw_rts_threshold *val =
780 				(struct rtw_rts_threshold *)chg_info;
781 
782 		hstate = rtw_hal_config_rts_th(phl_info->hal,
783 					       wrole->hw_band,
784 					       val->rts_time_th,
785 					       val->rts_len_th);
786 		if (hstate == RTW_HAL_STATUS_SUCCESS)
787 			pstate = RTW_PHL_STATUS_SUCCESS;
788 	}
789 	break;
790 	case WR_CHG_DFS_HE_TB_CFG:
791 	{
792 		u8 val = *(u8 *)chg_info;
793 
794 		hstate = rtw_hal_set_dfs_tb_ctrl(phl_info->hal, val);
795 		if (hstate == RTW_HAL_STATUS_SUCCESS)
796 			pstate = RTW_PHL_STATUS_SUCCESS;
797 	}
798 	break;
799 	case WR_CHG_TRX_PATH:
800 	{
801 		struct rtw_trx_path_param *param = (struct rtw_trx_path_param*)chg_info;
802 
803 		hstate = rtw_hal_cfg_trx_path(phl_info->hal,
804 					      param->tx,
805 					      param->tx_nss,
806 					      param->rx,
807 					      param->rx_nss);
808 
809 		if (hstate == RTW_HAL_STATUS_SUCCESS)
810 			pstate = RTW_PHL_STATUS_SUCCESS;
811 	}
812 	break;
813 	case WR_CHG_MAX:
814 		PHL_TRACE(COMP_PHL_DBG, _PHL_ERR_,
815 				"%s: Unsupported case:%d, please check it\n",
816 				__func__, chg_id);
817 		break;
818 	default :
819 		PHL_TRACE(COMP_PHL_DBG, _PHL_ERR_,
820 				"%s: unknown chg_id(%d), please check it\n",
821 				__func__, chg_id);
822 		break;
823 	};
824 	return pstate;
825 }
826 
827 #ifdef CONFIG_CMD_DISP
828 struct wr_chg_param {
829 	struct rtw_wifi_role_t *wrole;
830 	enum wr_chg_id id;
831 	u8 *info;
832 	u8 info_len;
833 };
834 
835 enum rtw_phl_status
phl_wifi_role_chg_hdl(struct phl_info_t * phl_info,u8 * param)836 phl_wifi_role_chg_hdl(struct phl_info_t *phl_info, u8 *param)
837 {
838 	struct wr_chg_param *wr_chg = (struct wr_chg_param *)param;
839 
840 	return phl_wifi_role_change(phl_info, wr_chg->wrole, wr_chg->id, wr_chg->info);
841 }
842 
phl_wifi_role_chg_done(void * drv_priv,u8 * cmd,u32 cmd_len,enum rtw_phl_status status)843 void phl_wifi_role_chg_done(void *drv_priv, u8 *cmd, u32 cmd_len,
844 						enum rtw_phl_status status)
845 {
846 	struct wr_chg_param *wr_chg = NULL;
847 
848 	if (cmd == NULL || cmd_len == 0) {
849 		PHL_ERR("%s buf == NULL || buf_len == 0\n", __func__);
850 		_os_warn_on(1);
851 		return;
852 	}
853 
854 	wr_chg = (struct wr_chg_param *)cmd;
855 	PHL_INFO("%s - id:%d .....\n", __func__, wr_chg->id);
856 
857 	if (wr_chg->info)
858 		_os_kmem_free(drv_priv, wr_chg->info, wr_chg->info_len);
859 
860 	_os_kmem_free(drv_priv, cmd, cmd_len);
861 	cmd = NULL;
862 }
863 
864 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)865 rtw_phl_cmd_wrole_change(void *phl,
866                          struct rtw_wifi_role_t *wrole,
867                          enum wr_chg_id chg_id,
868                          u8 *chg_info,
869                          u8 chg_info_len,
870                          enum phl_cmd_type cmd_type,
871                          u32 cmd_timeout)
872 {
873 
874 	enum rtw_phl_status psts = RTW_PHL_STATUS_FAILURE;
875 	struct phl_info_t *phl_info = (struct phl_info_t *)phl;
876 	void *drv = phl_to_drvpriv(phl_info);
877 	struct wr_chg_param *wr_chg = NULL;
878 	u32 wr_chg_len = 0;
879 
880 	if (cmd_type == PHL_CMD_DIRECTLY) {
881 		psts = phl_wifi_role_change(phl_info, wrole, chg_id, chg_info);
882 		goto _exit;
883 	}
884 
885 	wr_chg_len = sizeof(struct wr_chg_param);
886 	wr_chg = _os_kmem_alloc(drv, wr_chg_len);
887 	if (wr_chg == NULL) {
888 		PHL_ERR("%s: alloc wr_chg_param failed!\n", __func__);
889 		psts = RTW_PHL_STATUS_RESOURCE;
890 		goto _exit;
891 	}
892 	_os_mem_set(drv, wr_chg, 0, wr_chg_len);
893 	wr_chg->wrole = wrole;
894 	wr_chg->id = chg_id;
895 
896 	wr_chg->info_len = chg_info_len;
897 	wr_chg->info = _os_kmem_alloc(drv, chg_info_len);
898 	if (wr_chg->info == NULL) {
899 		PHL_ERR("%s: alloc wr_chg_info failed!\n", __func__);
900 		psts = RTW_PHL_STATUS_RESOURCE;
901 		goto _err_info;
902 	}
903 	_os_mem_set(drv, wr_chg->info, 0, chg_info_len);
904 	_os_mem_cpy(drv, wr_chg->info, chg_info, chg_info_len);
905 
906 	psts = phl_cmd_enqueue(phl_info,
907 	                       wrole->hw_band,
908 	                       MSG_EVT_ROLE_CHANGE,
909 	                       (u8*)wr_chg,
910 	                       wr_chg_len,
911 	                       phl_wifi_role_chg_done,
912 	                       cmd_type,
913 	                       cmd_timeout);
914 
915 	if (is_cmd_failure(psts)) {
916 		/* Send cmd success, but wait cmd fail*/
917 		psts = RTW_PHL_STATUS_FAILURE;
918 		PHL_INFO("%s wr-id:%d failure\n", __func__, wrole->id);
919 	} else if (psts != RTW_PHL_STATUS_SUCCESS) {
920 		/* Send cmd fail */
921 		psts = RTW_PHL_STATUS_FAILURE;
922 		PHL_INFO("%s wr-id:%d failure\n", __func__, wrole->id);
923 		goto _err_cmd;
924 	} else {
925 		PHL_INFO("%s wr-id:%d success\n", __func__, wrole->id);
926 	}
927 
928 	return psts;
929 
930 _err_cmd:
931 	if (wr_chg->info)
932 		_os_kmem_free(drv, wr_chg->info, wr_chg->info_len);
933 _err_info:
934 	if (wr_chg)
935 		_os_kmem_free(drv, wr_chg, wr_chg_len);
936 _exit:
937 	return psts;
938 }
939 
940 #else
941 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)942 rtw_phl_cmd_wrole_change(void *phl,
943 			struct rtw_wifi_role_t *wrole,
944 			enum wr_chg_id chg_id, u8 *chg_info, u8 chg_info_len,
945 			enum phl_cmd_type cmd_type, u32 cmd_timeout)
946 {
947 	return phl_wifi_role_change((struct phl_info_t *)phl, wrole, chg_id, chg_info);
948 }
949 #endif /*CONFIG_CMD_DISP*/
950 
951 enum rtw_phl_status
_phl_wifi_role_stop(struct phl_info_t * phl_info,struct rtw_wifi_role_t * wrole)952 _phl_wifi_role_stop(struct phl_info_t *phl_info, struct rtw_wifi_role_t *wrole)
953 {
954 	enum rtw_phl_status psts = RTW_PHL_STATUS_FAILURE;
955 
956 	wrole->active = false;
957 	_phl_role_notify(phl_info, wrole, PHL_ROLE_STOP);
958 	psts = phl_wifi_role_free_stainfo_hw(phl_info, wrole);
959 	if (psts != RTW_PHL_STATUS_SUCCESS) {
960 		PHL_ERR("%s wr free stainfo_hw failed\n", __func__);
961 		_os_warn_on(1);
962 	}
963 
964 	/*hw port cfg - mac_port_deinit*/
965 	return psts;
966 }
967 #ifdef CONFIG_CMD_DISP
968 enum rtw_phl_status
phl_wifi_role_stop_hdl(struct phl_info_t * phl_info,u8 * param)969 phl_wifi_role_stop_hdl(struct phl_info_t *phl_info, u8 *param)
970 {
971 	struct rtw_wifi_role_t *wrole = (struct rtw_wifi_role_t *)param;
972 
973 	return _phl_wifi_role_stop(phl_info, wrole);
974 }
phl_wifi_role_stop_done(void * drv_priv,u8 * cmd,u32 cmd_len,enum rtw_phl_status status)975 void phl_wifi_role_stop_done(void *drv_priv, u8 *cmd, u32 cmd_len,
976 						enum rtw_phl_status status)
977 {
978 	if (cmd) {
979 		struct rtw_wifi_role_t *wrole = NULL;
980 
981 		wrole = (struct rtw_wifi_role_t *)cmd;
982 		if (is_cmd_failure(status) && (RTW_PHL_STATUS_SUCCESS != status))
983 			PHL_ERR("%s wrole(%d) fail status(%d).....\n",
984 				__func__, wrole->id, status);
985 		else
986 			PHL_INFO("%s wrole(%d) success.....\n",
987 				__func__, wrole->id);
988 	}
989 }
990 
991 enum rtw_phl_status
phl_wifi_role_stop(struct phl_info_t * phl_info,struct rtw_wifi_role_t * wrole)992 phl_wifi_role_stop(struct phl_info_t *phl_info, struct rtw_wifi_role_t *wrole)
993 {
994 	enum rtw_phl_status psts = RTW_PHL_STATUS_FAILURE;
995 
996 	psts = phl_cmd_enqueue(phl_info,
997 			wrole->hw_band,
998 			MSG_EVT_ROLE_STOP,
999 			(u8 *)wrole,
1000 			0,
1001 			phl_wifi_role_stop_done,
1002 			PHL_CMD_WAIT, 0);
1003 
1004 	if (is_cmd_failure(psts)) {
1005 		/* Send cmd success, but wait cmd fail*/
1006 		psts = RTW_PHL_STATUS_FAILURE;
1007 		PHL_INFO("%s wr-id:%d failure\n", __func__, wrole->id);
1008 	} else if (psts != RTW_PHL_STATUS_SUCCESS) {
1009 		/* Send cmd fail */
1010 		psts = RTW_PHL_STATUS_FAILURE;
1011 		PHL_INFO("%s wr-id:%d failure\n", __func__, wrole->id);
1012 	} else {
1013 		PHL_INFO("%s wr-id:%d success\n", __func__, wrole->id);
1014 	}
1015 
1016 	return psts;
1017 }
1018 #else
1019 enum rtw_phl_status
phl_wifi_role_stop(struct phl_info_t * phl_info,struct rtw_wifi_role_t * wrole)1020 phl_wifi_role_stop(struct phl_info_t *phl_info, struct rtw_wifi_role_t *wrole)
1021 {
1022 	return _phl_wifi_role_stop(phl_info, wrole);
1023 }
1024 #endif
rtw_phl_wifi_role_free(void * phl,u8 role_idx)1025 void rtw_phl_wifi_role_free(void *phl, u8 role_idx)
1026 {
1027 	struct phl_info_t *phl_info = (struct phl_info_t *)phl;
1028 	struct rtw_phl_com_t *phl_com = phl_info->phl_com;
1029 	struct rtw_wifi_role_t *wrole = NULL;
1030 
1031 	if (role_idx >= MAX_WIFI_ROLE_NUMBER) {
1032 		PHL_ERR("%s invalid role index :%d", __func__, role_idx);
1033 		return;
1034 	}
1035 
1036 	wrole = &phl_com->wifi_roles[role_idx];
1037 
1038 	if (phl_wifi_role_stop(phl_info, wrole) != RTW_PHL_STATUS_SUCCESS) {
1039 		PHL_ERR("%s role_stop failed :%d", __func__, role_idx);
1040 		_os_warn_on(1);
1041 	}
1042 
1043 	if (phl_wifi_role_free_stainfo_sw(phl_info, wrole) != RTW_PHL_STATUS_SUCCESS) {
1044 		PHL_ERR("%s wr free stainfo_sw failed\n", __func__);
1045 		_os_warn_on(1);
1046 	}
1047 	_phl_wifi_role_free_sw(phl_info, wrole);
1048 	PHL_DUMP_MR_EX(phl_info);
1049 }
1050 
1051 #ifdef CONFIG_CMD_DISP
1052 enum rtw_phl_status
phl_register_mrc_module(struct phl_info_t * phl_info)1053 phl_register_mrc_module(struct phl_info_t *phl_info)
1054 {
1055 	enum rtw_phl_status phl_status = RTW_PHL_STATUS_FAILURE;
1056 	struct mr_ctl_t *mr_ctl = phlcom_to_mr_ctrl(phl_info->phl_com);
1057 	struct phl_bk_module_ops bk_ops = mr_ctl->bk_ops;
1058 	struct phl_cmd_dispatch_engine *disp_eng = &(phl_info->disp_eng);
1059 	u8 i = 0;
1060 
1061 	for(i = 0; i < disp_eng->phy_num; i++)
1062 	{
1063 		phl_status = phl_disp_eng_register_module(phl_info, i,
1064 						       PHL_MDL_MRC,
1065 						       &bk_ops);
1066 		if (RTW_PHL_STATUS_SUCCESS != phl_status) {
1067 			PHL_ERR("%s register MRC module in cmd disp failed :%d\n", __func__, i+1);
1068 			goto error_register_bk;
1069 		}
1070 	}
1071 
1072 	return phl_status;
1073 
1074 error_register_bk:
1075 	while(i > 0){
1076 		phl_status = phl_disp_eng_deregister_module(phl_info, --i,
1077 							 PHL_MDL_MRC);
1078 		if (RTW_PHL_STATUS_SUCCESS != phl_status) {
1079 			PHL_ERR("%s deregister MRC module in cmd disp failed :%d\n", __func__, i+1);
1080 		}
1081 	}
1082 	return RTW_PHL_STATUS_FAILURE;
1083 }
1084 #endif
1085 
1086 enum rtw_phl_status
phl_role_recover(struct phl_info_t * phl_info)1087 phl_role_recover(struct phl_info_t *phl_info)
1088 {
1089 	u8 role_idx;
1090 	struct rtw_wifi_role_t *wrole;
1091 	struct rtw_phl_stainfo_t *sta;
1092 	enum rtw_phl_status pstatus;
1093 
1094 	for (role_idx = 0; role_idx < MAX_WIFI_ROLE_NUMBER; role_idx++) {
1095 		wrole = rtw_phl_get_wrole_by_ridx(phl_info->phl_com, role_idx);
1096 		if(wrole == NULL)
1097 			continue;
1098 
1099 		PHL_INFO("%s with role_idx %d\n", __func__, role_idx);
1100 
1101 		sta = rtw_phl_get_stainfo_self(phl_info, wrole);
1102 		if(sta == NULL)
1103 			continue;
1104 
1105 		pstatus = _phl_wifi_role_start(phl_info, wrole, sta);
1106 		if (pstatus != RTW_PHL_STATUS_SUCCESS) {
1107 			PHL_ERR("%s wifi role start failed\n", __func__);
1108 			return RTW_PHL_STATUS_FAILURE;
1109 		}
1110 
1111 		if (wrole->target_type != PHL_RTYPE_NONE) {
1112 			PHL_INFO("%s with role_idx %d change to role type %d\n", __func__, role_idx, wrole->target_type);
1113 			phl_wifi_role_change(phl_info, wrole, WR_CHG_TYPE, (u8 *)&wrole->target_type);
1114 			wrole->target_type = PHL_RTYPE_NONE;
1115 		}
1116 	}
1117 
1118 	return RTW_PHL_STATUS_SUCCESS;
1119 }
1120 
1121 enum rtw_phl_status
phl_cmd_role_recover(struct phl_info_t * phl_info)1122 phl_cmd_role_recover(struct phl_info_t *phl_info)
1123 {
1124 	enum rtw_phl_status pstatus = RTW_PHL_STATUS_FAILURE;
1125 
1126 #ifdef CONFIG_CMD_DISP
1127 	pstatus = phl_cmd_enqueue(phl_info, HW_BAND_0, MSG_EVT_ROLE_RECOVER, NULL, 0, NULL, PHL_CMD_WAIT, 0);
1128 	if (is_cmd_failure(pstatus)) {
1129 		/* Send cmd success, but wait cmd fail*/
1130 		pstatus = RTW_PHL_STATUS_FAILURE;
1131 	} else if (pstatus != RTW_PHL_STATUS_SUCCESS) {
1132 		/* Send cmd fail */
1133 		pstatus = RTW_PHL_STATUS_FAILURE;
1134 	}
1135 #else
1136 	pstatus = phl_role_recover(phl_info);
1137 #endif
1138 	return pstatus;
1139 }
1140 
1141 enum rtw_phl_status
phl_role_suspend(struct phl_info_t * phl_info)1142 phl_role_suspend(struct phl_info_t *phl_info)
1143 {
1144 	u8 role_idx;
1145 	struct rtw_wifi_role_t *wrole;
1146 	enum rtw_phl_status pstatus;
1147 
1148 	for (role_idx = 0; role_idx < MAX_WIFI_ROLE_NUMBER; role_idx++) {
1149 		wrole = rtw_phl_get_wrole_by_ridx(phl_info->phl_com, role_idx);
1150 		if (wrole == NULL)
1151 			continue;
1152 
1153 		if (wrole->active == false)
1154 			continue;
1155 
1156 		PHL_INFO("%s with role_idx %d\n", __func__, role_idx);
1157 
1158 		pstatus = _phl_wifi_role_stop(phl_info, wrole);
1159 		if (pstatus != RTW_PHL_STATUS_SUCCESS) {
1160 			PHL_ERR("%s wifi role stop failed\n", __func__);
1161 			return RTW_PHL_STATUS_FAILURE;
1162 		}
1163 	}
1164 
1165 	return RTW_PHL_STATUS_SUCCESS;
1166 }
1167 enum rtw_phl_status
phl_cmd_role_suspend(struct phl_info_t * phl_info)1168 phl_cmd_role_suspend(struct phl_info_t *phl_info)
1169 {
1170 	enum rtw_phl_status pstatus = RTW_PHL_STATUS_FAILURE;
1171 
1172 #ifdef CONFIG_CMD_DISP
1173 	pstatus = phl_cmd_enqueue(phl_info, HW_BAND_0, MSG_EVT_ROLE_SUSPEND, NULL, 0, NULL, PHL_CMD_WAIT, 0);
1174 	if (is_cmd_failure(pstatus)) {
1175 		/* Send cmd success, but wait cmd fail*/
1176 		pstatus = RTW_PHL_STATUS_FAILURE;
1177 	} else if (pstatus != RTW_PHL_STATUS_SUCCESS) {
1178 		/* Send cmd fail */
1179 		pstatus = RTW_PHL_STATUS_FAILURE;
1180 	}
1181 #else
1182 	pstatus = phl_role_suspend(phl_info);
1183 #endif
1184 	return pstatus;
1185 }
1186 
rtw_phl_role_is_client_category(struct rtw_wifi_role_t * wrole)1187 bool rtw_phl_role_is_client_category(struct rtw_wifi_role_t *wrole)
1188 {
1189 	bool ret = false;
1190 
1191 	if (wrole->type == PHL_RTYPE_STATION || wrole->type == PHL_RTYPE_P2P_GC)
1192 		ret = true;
1193 	return ret;
1194 }
1195 
phl_role_get_bcn_intvl(struct phl_info_t * phl,struct rtw_wifi_role_t * wrole)1196 u16 phl_role_get_bcn_intvl(struct phl_info_t *phl, struct rtw_wifi_role_t *wrole)
1197 {
1198 	struct rtw_phl_stainfo_t *sta = rtw_phl_get_stainfo_self(phl, wrole);
1199 	u16 bcn_intvl = 0;
1200 
1201 	if (phl_role_is_client_category(wrole)) {
1202 		bcn_intvl = sta->asoc_cap.bcn_interval;
1203 #ifdef RTW_PHL_BCN
1204 	} else if (phl_role_is_ap_category(wrole)) {
1205 		bcn_intvl = (u16)wrole->bcn_cmn.bcn_interval;
1206 #endif
1207 	} else {
1208 		PHL_WARN("phl_role_get_bcn_intvl() Unknown category, role id(%d), type(%d)\n",
1209 			wrole->id, wrole->type);
1210 	}
1211 	return bcn_intvl;
1212 }
1213 
1214 enum rtw_phl_status
phl_wifi_role_macid_all_pause(struct phl_info_t * phl_info,struct rtw_wifi_role_t * wrole,bool pause)1215 phl_wifi_role_macid_all_pause(struct phl_info_t *phl_info, struct rtw_wifi_role_t *wrole, bool pause)
1216 {
1217 	enum rtw_hal_status hstatus = RTW_HAL_STATUS_SUCCESS;
1218 	enum rtw_phl_status pstatus = RTW_PHL_STATUS_SUCCESS;
1219 	u8 mutli_macid = false;
1220 
1221 	switch (wrole->type) {
1222 	case PHL_RTYPE_NONE:
1223 	case PHL_RTYPE_STATION:
1224 	case PHL_RTYPE_ADHOC:
1225 	case PHL_RTYPE_P2P_DEVICE:
1226 	case PHL_RTYPE_P2P_GC:
1227 		mutli_macid = false;
1228 		break;
1229 	default:
1230 		mutli_macid = true;
1231 		break;
1232 	}
1233 
1234 	if (mutli_macid) {
1235 		void *drv = phl_to_drvpriv(phl_info);
1236 		struct macid_ctl_t *mctrl = phl_to_mac_ctrl(phl_info);
1237 		u32 macid_pause[PHL_MACID_MAX_ARRAY_NUM] = {0};
1238 
1239 		_os_spinlock(phl_to_drvpriv(phl_info), &mctrl->lock, _bh, NULL);
1240 		_os_mem_cpy(drv, macid_pause, &mctrl->wifi_role_usedmap[wrole->id][0], PHL_MACID_MAX_ARRAY_NUM);
1241 		_os_spinunlock(phl_to_drvpriv(phl_info), &mctrl->lock, _bh, NULL);
1242 		hstatus = rtw_hal_set_macid_grp_pause(phl_info->hal, macid_pause, PHL_MACID_MAX_ARRAY_NUM, pause);
1243 		if (hstatus != RTW_HAL_STATUS_SUCCESS) {
1244 			PHL_INFO("%s fail(hstatus=%d)\n", __func__, hstatus);
1245 			pstatus = RTW_PHL_STATUS_FAILURE;
1246 		}
1247 	} else {
1248 		struct rtw_phl_stainfo_t * self_sta = rtw_phl_get_stainfo_self((void *)phl_info, wrole);
1249 
1250 		hstatus = rtw_hal_set_macid_pause(phl_info->hal, self_sta->macid, pause);
1251 		if (hstatus != RTW_HAL_STATUS_SUCCESS) {
1252 			PHL_INFO("%s fail(hstatus=%d)\n", __func__, hstatus);
1253 			pstatus = RTW_PHL_STATUS_FAILURE;
1254 		}
1255 	}
1256 
1257 	return pstatus;
1258 }
1259