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