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