1 /******************************************************************************
2 *
3 * Copyright(c) 2007 - 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 _RTW_AP_C_
16
17 #include <drv_types.h>
18
19 #ifdef CONFIG_AP_MODE
20
21 extern unsigned char RTW_WPA_OUI[];
22 extern unsigned char WMM_OUI[];
23 extern unsigned char WPS_OUI[];
24 extern unsigned char P2P_OUI[];
25 extern unsigned char WFD_OUI[];
26
init_mlme_ap_info(_adapter * padapter)27 void init_mlme_ap_info(_adapter *padapter)
28 {
29 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
30
31 _rtw_spinlock_init(&pmlmepriv->bcn_update_lock);
32 /* pmlmeext->bstart_bss = _FALSE; */
33 }
34
free_mlme_ap_info(_adapter * padapter)35 void free_mlme_ap_info(_adapter *padapter)
36 {
37 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
38
39 stop_ap_mode(padapter);
40 _rtw_spinlock_free(&pmlmepriv->bcn_update_lock);
41
42 }
43
44 /*
45 * Set TIM IE
46 * return length of total TIM IE
47 */
rtw_set_tim_ie(u8 dtim_cnt,u8 dtim_period,const u8 * tim_bmp,u8 tim_bmp_len,u8 * tim_ie)48 u8 rtw_set_tim_ie(u8 dtim_cnt, u8 dtim_period
49 , const u8 *tim_bmp, u8 tim_bmp_len, u8 *tim_ie)
50 {
51 u8 *p = tim_ie;
52 u8 i, n1, n2;
53 u8 bmp_len;
54
55 if (rtw_bmp_not_empty(tim_bmp, tim_bmp_len)) {
56 /* find the first nonzero octet in tim_bitmap */
57 for (i = 0; i < tim_bmp_len; i++)
58 if (tim_bmp[i])
59 break;
60 n1 = i & 0xFE;
61
62 /* find the last nonzero octet in tim_bitmap, except octet 0 */
63 for (i = tim_bmp_len - 1; i > 0; i--)
64 if (tim_bmp[i])
65 break;
66 n2 = i;
67 bmp_len = n2 - n1 + 1;
68 } else {
69 n1 = n2 = 0;
70 bmp_len = 1;
71 }
72
73 *p++ = WLAN_EID_TIM;
74 *p++ = 2 + 1 + bmp_len;
75 *p++ = dtim_cnt;
76 *p++ = dtim_period;
77 *p++ = (rtw_bmp_is_set(tim_bmp, tim_bmp_len, 0) ? BIT0 : 0) | n1;
78 _rtw_memcpy(p, tim_bmp + n1, bmp_len);
79
80 #if 0
81 RTW_INFO("n1:%u, n2:%u, bmp_offset:%u, bmp_len:%u\n", n1, n2, n1 / 2, bmp_len);
82 RTW_INFO_DUMP("tim_ie: ", tim_ie + 2, 2 + 1 + bmp_len);
83 #endif
84 return 2 + 2 + 1 + bmp_len;
85 }
86
update_BCNTIM(_adapter * padapter)87 static void update_BCNTIM(_adapter *padapter)
88 {
89 struct sta_priv *pstapriv = &padapter->stapriv;
90 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
91 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
92 WLAN_BSSID_EX *pnetwork_mlmeext = &(pmlmeinfo->network);
93 unsigned char *pie = pnetwork_mlmeext->IEs;
94
95 #if 0
96
97
98 /* update TIM IE */
99 /* if(rtw_tim_map_anyone_be_set(padapter, pstapriv->tim_bitmap)) */
100 #endif
101 if (_TRUE) {
102 u8 *p, *dst_ie, *premainder_ie = NULL, *pbackup_remainder_ie = NULL;
103 uint offset, tmp_len, tim_ielen, tim_ie_offset, remainder_ielen;
104
105 p = rtw_get_ie(pie + _FIXED_IE_LENGTH_, _TIM_IE_, &tim_ielen, pnetwork_mlmeext->IELength - _FIXED_IE_LENGTH_);
106 if (p != NULL && tim_ielen > 0) {
107 tim_ielen += 2;
108
109 premainder_ie = p + tim_ielen;
110
111 tim_ie_offset = (sint)(p - pie);
112
113 remainder_ielen = pnetwork_mlmeext->IELength - tim_ie_offset - tim_ielen;
114
115 /*append TIM IE from dst_ie offset*/
116 dst_ie = p;
117 } else {
118 tim_ielen = 0;
119
120 /*calculate head_len*/
121 offset = _FIXED_IE_LENGTH_;
122
123 /* get ssid_ie len */
124 p = rtw_get_ie(pie + _BEACON_IE_OFFSET_, _SSID_IE_, &tmp_len, (pnetwork_mlmeext->IELength - _BEACON_IE_OFFSET_));
125 if (p != NULL)
126 offset += tmp_len + 2;
127
128 /*get supported rates len*/
129 p = rtw_get_ie(pie + _BEACON_IE_OFFSET_, _SUPPORTEDRATES_IE_, &tmp_len, (pnetwork_mlmeext->IELength - _BEACON_IE_OFFSET_));
130 if (p != NULL)
131 offset += tmp_len + 2;
132
133 /*DS Parameter Set IE, len=3*/
134 offset += 3;
135
136 premainder_ie = pie + offset;
137
138 remainder_ielen = pnetwork_mlmeext->IELength - offset - tim_ielen;
139
140 /*append TIM IE from offset*/
141 dst_ie = pie + offset;
142
143 }
144
145 if (remainder_ielen > 0) {
146 pbackup_remainder_ie = rtw_malloc(remainder_ielen);
147 if (pbackup_remainder_ie && premainder_ie)
148 _rtw_memcpy(pbackup_remainder_ie, premainder_ie, remainder_ielen);
149 }
150
151 /* append TIM IE */
152 dst_ie += rtw_set_tim_ie(0, 1, pstapriv->tim_bitmap, pstapriv->aid_bmp_len, dst_ie);
153
154 /*copy remainder IE*/
155 if (pbackup_remainder_ie) {
156 _rtw_memcpy(dst_ie, pbackup_remainder_ie, remainder_ielen);
157
158 rtw_mfree(pbackup_remainder_ie, remainder_ielen);
159 }
160
161 offset = (uint)(dst_ie - pie);
162 pnetwork_mlmeext->IELength = offset + remainder_ielen;
163
164 }
165 }
166
rtw_add_bcn_ie(_adapter * padapter,WLAN_BSSID_EX * pnetwork,u8 index,u8 * data,u8 len)167 void rtw_add_bcn_ie(_adapter *padapter, WLAN_BSSID_EX *pnetwork, u8 index, u8 *data, u8 len)
168 {
169 PNDIS_802_11_VARIABLE_IEs pIE;
170 u8 bmatch = _FALSE;
171 u8 *pie = pnetwork->IEs;
172 u8 *p = NULL, *dst_ie = NULL, *premainder_ie = NULL, *pbackup_remainder_ie = NULL;
173 u32 i, offset, ielen = 0, ie_offset, remainder_ielen = 0;
174
175 if (pnetwork->IELength + len > MAX_IE_SZ) {
176 RTW_ERR("Can't add IE to beacon, because size is more than MAX_IE_SZ\n");
177 return;
178 }
179
180 /* Search element id (index) exits or not */
181 for (i = sizeof(NDIS_802_11_FIXED_IEs); i < pnetwork->IELength;) {
182 pIE = (PNDIS_802_11_VARIABLE_IEs)(pnetwork->IEs + i);
183
184 if (pIE->ElementID > index)
185 break;
186 else if (pIE->ElementID == index) { /* already exist the same IE */
187 p = (u8 *)pIE;
188 ielen = pIE->Length;
189 bmatch = _TRUE;
190 break;
191 }
192
193 p = (u8 *)pIE;
194 ielen = pIE->Length;
195 i += (pIE->Length + 2);
196 }
197
198 /* Backup remainder IE */
199 if (p != NULL && ielen > 0) {
200 ielen += 2;
201
202 premainder_ie = p + ielen;
203
204 ie_offset = (sint)(p - pie);
205
206 remainder_ielen = pnetwork->IELength - ie_offset - ielen;
207
208 if (bmatch)
209 dst_ie = p;
210 else
211 dst_ie = (p + ielen);
212 }
213
214 if (dst_ie == NULL)
215 return;
216
217 if (remainder_ielen > 0) {
218 pbackup_remainder_ie = rtw_malloc(remainder_ielen);
219 if (pbackup_remainder_ie && premainder_ie)
220 _rtw_memcpy(pbackup_remainder_ie, premainder_ie, remainder_ielen);
221 }
222
223 *dst_ie++ = index;
224 *dst_ie++ = len;
225
226 _rtw_memcpy(dst_ie, data, len);
227 dst_ie += len;
228
229 /* Append remainder IE */
230 if (pbackup_remainder_ie) {
231 _rtw_memcpy(dst_ie, pbackup_remainder_ie, remainder_ielen);
232
233 rtw_mfree(pbackup_remainder_ie, remainder_ielen);
234 }
235
236 offset = (uint)(dst_ie - pie);
237 pnetwork->IELength = offset + remainder_ielen;
238 }
239
rtw_remove_bcn_ie(_adapter * padapter,WLAN_BSSID_EX * pnetwork,u8 index)240 void rtw_remove_bcn_ie(_adapter *padapter, WLAN_BSSID_EX *pnetwork, u8 index)
241 {
242 u8 *p, *dst_ie = NULL, *premainder_ie = NULL, *pbackup_remainder_ie = NULL;
243 uint offset, ielen, ie_offset, remainder_ielen = 0;
244 u8 *pie = pnetwork->IEs;
245
246 p = rtw_get_ie(pie + _FIXED_IE_LENGTH_, index, &ielen, pnetwork->IELength - _FIXED_IE_LENGTH_);
247 if (p != NULL && ielen > 0) {
248 ielen += 2;
249
250 premainder_ie = p + ielen;
251
252 ie_offset = (sint)(p - pie);
253
254 remainder_ielen = pnetwork->IELength - ie_offset - ielen;
255
256 dst_ie = p;
257 } else
258 return;
259
260 if (remainder_ielen > 0) {
261 pbackup_remainder_ie = rtw_malloc(remainder_ielen);
262 if (pbackup_remainder_ie && premainder_ie)
263 _rtw_memcpy(pbackup_remainder_ie, premainder_ie, remainder_ielen);
264 }
265
266 /* copy remainder IE */
267 if (pbackup_remainder_ie) {
268 _rtw_memcpy(dst_ie, pbackup_remainder_ie, remainder_ielen);
269
270 rtw_mfree(pbackup_remainder_ie, remainder_ielen);
271 }
272
273 offset = (uint)(dst_ie - pie);
274 pnetwork->IELength = offset + remainder_ielen;
275 }
276
277 /**
278 * rtw_add_bcn_ie_ex - Add Element ID Extension into Element ID (0xff)
279 * Frame format: | element id (0xff) | length | element id extension | content |
280 *
281 * @eid_ex: element id extension
282 * @data: eid_ex + content
283 * @len: length
284 */
rtw_add_bcn_ie_ex(_adapter * padapter,WLAN_BSSID_EX * pnetwork,u8 eid_ex,u8 * data,u8 len)285 void rtw_add_bcn_ie_ex(_adapter *padapter, WLAN_BSSID_EX *pnetwork, u8 eid_ex, u8 *data, u8 len)
286 {
287 struct ieee80211_info_element *pie;
288 bool find_ex_ie = _FALSE;
289 bool bmatch = _FALSE;
290 u8 *ies = pnetwork->IEs;
291 u8 *p = NULL, *dst_ie = NULL, *premainder_ie = NULL, *pbackup_remainder_ie = NULL;
292 u32 i, offset, ielen = 0, ie_offset, remainder_ielen = 0;
293
294 if (pnetwork->IELength + len > MAX_IE_SZ) {
295 RTW_ERR("Can't add IE to beacon, because size is more than MAX_IE_SZ\n");
296 return;
297 }
298
299 /* Search element id extension exits or not */
300 for (i = sizeof(NDIS_802_11_FIXED_IEs); i < pnetwork->IELength;) {
301 pie = (struct ieee80211_info_element *)(ies + i);
302
303 if (pie->id == WLAN_EID_EXTENSION) {
304 find_ex_ie = _TRUE;
305 if (pie->data[0] > eid_ex) { /* first byte of data is element id extension */
306 break;
307 } else if (pie->data[0] == eid_ex) { /* already exist the same Element ID Extension */
308 p = (u8 *)pie;
309 ielen = pie->len;
310 bmatch = _TRUE;
311 break;
312 }
313 } else if (find_ex_ie) { /* append to last element id (0xff) */
314 break;
315 }
316
317 p = (u8 *)pie;
318 ielen = pie->len;
319 i += (pie->len + 2);
320 }
321
322 /* Backup remainder IE */
323 if (p != NULL && ielen > 0) {
324 ielen += 2;
325 premainder_ie = p + ielen;
326 ie_offset = (sint)(p - ies);
327 remainder_ielen = pnetwork->IELength - ie_offset - ielen;
328
329 if (bmatch)
330 dst_ie = p;
331 else
332 dst_ie = (p + ielen);
333 }
334
335 if (dst_ie == NULL)
336 return;
337
338 if (remainder_ielen > 0) {
339 pbackup_remainder_ie = rtw_malloc(remainder_ielen);
340 if (pbackup_remainder_ie && premainder_ie)
341 _rtw_memcpy(pbackup_remainder_ie, premainder_ie, remainder_ielen);
342 }
343
344 *dst_ie++ = WLAN_EID_EXTENSION;
345 *dst_ie++ = len;
346
347 _rtw_memcpy(dst_ie, data, len);
348 dst_ie += len;
349
350 /* Append remainder IE */
351 if (pbackup_remainder_ie) {
352 _rtw_memcpy(dst_ie, pbackup_remainder_ie, remainder_ielen);
353
354 rtw_mfree(pbackup_remainder_ie, remainder_ielen);
355 }
356
357 offset = (uint)(dst_ie - ies);
358 pnetwork->IELength = offset + remainder_ielen;
359 }
360
rtw_remove_bcn_ie_ex(_adapter * padapter,WLAN_BSSID_EX * pnetwork,u8 index,u8 * pindex_ex,u8 index_ex_len)361 void rtw_remove_bcn_ie_ex(_adapter *padapter, WLAN_BSSID_EX *pnetwork, u8 index, u8* pindex_ex, u8 index_ex_len)
362 {
363 u8 *p, *dst_ie = NULL, *premainder_ie = NULL, *pbackup_remainder_ie = NULL;
364 uint offset, ielen, ie_offset, remainder_ielen = 0;
365 u8 *pie = pnetwork->IEs;
366
367 p = rtw_get_ie_ex(pie + _FIXED_IE_LENGTH_, pnetwork->IELength - _FIXED_IE_LENGTH_, index, pindex_ex, index_ex_len, NULL, &ielen);
368 if (p != NULL && ielen > 0) {
369 premainder_ie = p + ielen;
370
371 ie_offset = (sint)(p - pie);
372
373 remainder_ielen = pnetwork->IELength - ie_offset - ielen;
374
375 dst_ie = p;
376 } else
377 return;
378
379 if (remainder_ielen > 0) {
380 pbackup_remainder_ie = rtw_malloc(remainder_ielen);
381 if (pbackup_remainder_ie && premainder_ie)
382 _rtw_memcpy(pbackup_remainder_ie, premainder_ie, remainder_ielen);
383 }
384
385 /* copy remainder IE */
386 if (pbackup_remainder_ie) {
387 _rtw_memcpy(dst_ie, pbackup_remainder_ie, remainder_ielen);
388
389 rtw_mfree(pbackup_remainder_ie, remainder_ielen);
390 }
391
392 offset = (uint)(dst_ie - pie);
393 pnetwork->IELength = offset + remainder_ielen;
394 }
395
396 u8 chk_sta_is_alive(struct sta_info *psta);
chk_sta_is_alive(struct sta_info * psta)397 u8 chk_sta_is_alive(struct sta_info *psta)
398 {
399 u8 ret = _FALSE;
400 #ifdef DBG_EXPIRATION_CHK
401 RTW_INFO("sta:"MAC_FMT", rssi:%d, rx:"STA_PKTS_FMT", expire_to:%u, %s%ssq_len:%u\n"
402 , MAC_ARG(psta->phl_sta->mac_addr)
403 , 0 /* TODO: psta->phl_sta->hal_sta->rssi_stat.rssi */
404 /* , STA_RX_PKTS_ARG(psta) */
405 , STA_RX_PKTS_DIFF_ARG(psta)
406 , psta->expire_to
407 , psta->state & WIFI_SLEEP_STATE ? "PS, " : ""
408 , psta->state & WIFI_STA_ALIVE_CHK_STATE ? "SAC, " : ""
409 , psta->sleepq_len
410 );
411 #endif
412
413 /* if(sta_last_rx_pkts(psta) == sta_rx_pkts(psta)) */
414 if ((psta->sta_stats.last_rx_data_pkts + psta->sta_stats.last_rx_ctrl_pkts) == (psta->sta_stats.rx_data_pkts + psta->sta_stats.rx_ctrl_pkts)) {
415 #if 0
416 if (psta->state & WIFI_SLEEP_STATE)
417 ret = _TRUE;
418 #endif
419 } else
420 ret = _TRUE;
421
422 #ifdef CONFIG_RTW_MESH
423 if (MLME_IS_MESH(psta->padapter)) {
424 u8 bcn_alive, hwmp_alive;
425
426 hwmp_alive = (psta->sta_stats.rx_hwmp_pkts !=
427 psta->sta_stats.last_rx_hwmp_pkts);
428 bcn_alive = (psta->sta_stats.rx_beacon_pkts !=
429 psta->sta_stats.last_rx_beacon_pkts);
430 /* The reference for nexthop_lookup */
431 psta->alive = ret || hwmp_alive || bcn_alive;
432 /* The reference for expire_timeout_chk */
433 /* Exclude bcn_alive to avoid a misjudge condition
434 that a peer unexpectedly leave and restart quickly*/
435 ret = ret || hwmp_alive;
436 }
437 #endif
438
439 sta_update_last_rx_pkts(psta);
440
441 return ret;
442 }
443
444 /**
445 * issue_aka_chk_frame - issue active keep alive check frame
446 * aka = active keep alive
447 */
448 #ifdef CONFIG_ACTIVE_KEEP_ALIVE_CHECK
issue_aka_chk_frame(_adapter * adapter,struct sta_info * psta)449 static int issue_aka_chk_frame(_adapter *adapter, struct sta_info *psta)
450 {
451 int ret = _FAIL;
452 u8 *target_addr = psta->phl_sta->mac_addr;
453
454 if (MLME_IS_AP(adapter)) {
455 /* issue null data to check sta alive */
456 if (psta->state & WIFI_SLEEP_STATE)
457 ret = issue_nulldata(adapter, target_addr, 0, 1, 50);
458 else
459 ret = issue_nulldata(adapter, target_addr, 0, 3, 50);
460 }
461
462 #ifdef CONFIG_RTW_MESH
463 if (MLME_IS_MESH(adapter)) {
464 struct rtw_mesh_path *mpath;
465
466 rtw_rcu_read_lock();
467 mpath = rtw_mesh_path_lookup(adapter, target_addr);
468 if (!mpath) {
469 mpath = rtw_mesh_path_add(adapter, target_addr);
470 if (IS_ERR(mpath)) {
471 rtw_rcu_read_unlock();
472 RTW_ERR(FUNC_ADPT_FMT" rtw_mesh_path_add for "MAC_FMT" fail.\n",
473 FUNC_ADPT_ARG(adapter), MAC_ARG(target_addr));
474 return _FAIL;
475 }
476 }
477 if (mpath->flags & RTW_MESH_PATH_ACTIVE)
478 ret = _SUCCESS;
479 else {
480 u8 flags = RTW_PREQ_Q_F_START | RTW_PREQ_Q_F_PEER_AKA;
481 /* issue PREQ to check peer alive */
482 rtw_mesh_queue_preq(mpath, flags);
483 ret = _FALSE;
484 }
485 rtw_rcu_read_unlock();
486 }
487 #endif
488 return ret;
489 }
490 #endif
491
expire_timeout_chk(_adapter * padapter)492 void expire_timeout_chk(_adapter *padapter)
493 {
494 _list *phead, *plist;
495 u8 updated = _FALSE;
496 struct sta_info *psta = NULL;
497 struct sta_priv *pstapriv = &padapter->stapriv;
498 u8 chk_alive_num = 0;
499 char chk_alive_list[NUM_STA];
500 int i;
501 int stainfo_offset;
502 u8 flush_num = 0;
503 char flush_list[NUM_STA]={0};
504
505 #ifdef CONFIG_RTW_MESH
506 if (MLME_IS_MESH(padapter)
507 && check_fwstate(&padapter->mlmepriv, WIFI_ASOC_STATE)
508 ) {
509 struct rtw_mesh_cfg *mcfg = &padapter->mesh_cfg;
510
511 rtw_mesh_path_expire(padapter);
512
513 /* TBD: up layer timeout mechanism */
514 /* if (!mcfg->plink_timeout)
515 return; */
516 #ifndef CONFIG_ACTIVE_KEEP_ALIVE_CHECK
517 return;
518 #endif
519 }
520 #endif
521
522 #ifdef CONFIG_RTW_WDS
523 rtw_wds_path_expire(padapter);
524 #endif
525
526 _rtw_spinlock_bh(&pstapriv->auth_list_lock);
527
528 phead = &pstapriv->auth_list;
529 plist = get_next(phead);
530
531 /* check auth_queue */
532 #ifdef DBG_EXPIRATION_CHK
533 if (rtw_end_of_queue_search(phead, plist) == _FALSE) {
534 RTW_INFO(FUNC_ADPT_FMT" auth_list, cnt:%u\n"
535 , FUNC_ADPT_ARG(padapter), pstapriv->auth_list_cnt);
536 }
537 #endif
538 while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {
539 psta = LIST_CONTAINOR(plist, struct sta_info, auth_list);
540
541 plist = get_next(plist);
542
543
544 #ifdef CONFIG_ATMEL_RC_PATCH
545 if (_rtw_memcmp((void *)(pstapriv->atmel_rc_pattern), (void *)(psta->phl_sta->mac_addr), ETH_ALEN) == _TRUE)
546 continue;
547 if (psta->flag_atmel_rc)
548 continue;
549 #endif
550 if (psta->expire_to > 0) {
551 psta->expire_to--;
552 if (psta->expire_to == 0) {
553 stainfo_offset = rtw_stainfo_offset(pstapriv, psta);
554 if (stainfo_offset_valid(stainfo_offset))
555 flush_list[flush_num++] = stainfo_offset;
556 else
557 rtw_warn_on(1);
558 }
559 }
560
561 }
562
563 _rtw_spinunlock_bh(&pstapriv->auth_list_lock);
564 for (i = 0; i < flush_num; i++) {
565 psta = rtw_get_stainfo_by_offset(pstapriv, flush_list[i]);
566 RTW_INFO(FUNC_ADPT_FMT" auth expire "MAC_FMT"\n"
567 , FUNC_ADPT_ARG(padapter), MAC_ARG(psta->phl_sta->mac_addr));
568 rtw_free_stainfo(padapter, psta);
569 psta = NULL;
570 }
571
572 _rtw_spinlock_bh(&pstapriv->asoc_list_lock);
573
574 phead = &pstapriv->asoc_list;
575 plist = get_next(phead);
576
577 /* check asoc_queue */
578 #ifdef DBG_EXPIRATION_CHK
579 if (rtw_end_of_queue_search(phead, plist) == _FALSE) {
580 RTW_INFO(FUNC_ADPT_FMT" asoc_list, cnt:%u\n"
581 , FUNC_ADPT_ARG(padapter), pstapriv->asoc_list_cnt);
582 }
583 #endif
584 while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {
585 psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);
586 plist = get_next(plist);
587 #ifdef CONFIG_ATMEL_RC_PATCH
588 RTW_INFO("%s:%d psta=%p, %02x,%02x||%02x,%02x \n\n", __func__, __LINE__,
589 psta, pstapriv->atmel_rc_pattern[0], pstapriv->atmel_rc_pattern[5], psta->phl_sta->mac_addr[0], psta->phl_sta->mac_addr[5]);
590 if (_rtw_memcmp((void *)pstapriv->atmel_rc_pattern, (void *)(psta->phl_sta->mac_addr), ETH_ALEN) == _TRUE)
591 continue;
592 if (psta->flag_atmel_rc)
593 continue;
594 RTW_INFO("%s: debug line:%d\n", __func__, __LINE__);
595 #endif
596 #ifdef CONFIG_AUTO_AP_MODE
597 if (psta->isrc)
598 continue;
599 #endif
600 if (chk_sta_is_alive(psta) || !psta->expire_to) {
601 psta->expire_to = pstapriv->expire_to;
602 psta->keep_alive_trycnt = 0;
603 #if !defined(CONFIG_ACTIVE_KEEP_ALIVE_CHECK) && defined(CONFIG_80211N_HT)
604 psta->under_exist_checking = 0;
605 #endif
606 } else
607 psta->expire_to--;
608
609 #if !defined(CONFIG_ACTIVE_KEEP_ALIVE_CHECK) && defined(CONFIG_80211N_HT)
610 if ((psta->flags & WLAN_STA_HT) && (psta->htpriv.agg_enable_bitmap || psta->under_exist_checking)) {
611 /* check sta by delba(addba) for 11n STA */
612 /* ToDo: use CCX report to check for all STAs */
613 /* RTW_INFO("asoc check by DELBA/ADDBA! (pstapriv->expire_to=%d s)(psta->expire_to=%d s), [%02x, %d]\n", pstapriv->expire_to*2, psta->expire_to*2, psta->htpriv.agg_enable_bitmap, psta->under_exist_checking); */
614
615 if (psta->expire_to <= (pstapriv->expire_to - 50)) {
616 RTW_INFO("asoc expire by DELBA/ADDBA! (%d s)\n", (pstapriv->expire_to - psta->expire_to) * 2);
617 psta->under_exist_checking = 0;
618 psta->expire_to = 0;
619 } else if (psta->expire_to <= (pstapriv->expire_to - 3) && (psta->under_exist_checking == 0)) {
620 RTW_INFO("asoc check by DELBA/ADDBA! (%d s)\n", (pstapriv->expire_to - psta->expire_to) * 2);
621 psta->under_exist_checking = 1;
622 /* tear down TX AMPDU */
623 send_delba(padapter, 1, psta->phl_sta->mac_addr);/* */ /* originator */
624 psta->htpriv.agg_enable_bitmap = 0x0;/* reset */
625 psta->htpriv.candidate_tid_bitmap = 0x0;/* reset */
626 }
627 }
628 #endif /* !defined(CONFIG_ACTIVE_KEEP_ALIVE_CHECK) && defined(CONFIG_80211N_HT) */
629
630 if (psta->expire_to <= 0) {
631 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
632
633 if (padapter->registrypriv.wifi_spec == 1) {
634 psta->expire_to = pstapriv->expire_to;
635 continue;
636 }
637
638 #ifndef CONFIG_ACTIVE_KEEP_ALIVE_CHECK
639 #ifdef CONFIG_80211N_HT
640
641 #define KEEP_ALIVE_TRYCNT (3)
642
643 if (psta->keep_alive_trycnt > 0 && psta->keep_alive_trycnt <= KEEP_ALIVE_TRYCNT) {
644 if (psta->state & WIFI_STA_ALIVE_CHK_STATE)
645 psta->state ^= WIFI_STA_ALIVE_CHK_STATE;
646 else
647 psta->keep_alive_trycnt = 0;
648
649 } else if ((psta->keep_alive_trycnt > KEEP_ALIVE_TRYCNT) && !(psta->state & WIFI_STA_ALIVE_CHK_STATE))
650 psta->keep_alive_trycnt = 0;
651 if ((psta->htpriv.ht_option == _TRUE) && (psta->htpriv.ampdu_enable == _TRUE)) {
652 uint priority = 1; /* test using BK */
653 u8 issued = 0;
654
655 /* issued = (psta->htpriv.agg_enable_bitmap>>priority)&0x1; */
656 issued |= (psta->htpriv.candidate_tid_bitmap >> priority) & 0x1;
657
658 if (0 == issued) {
659 if (!(psta->state & WIFI_STA_ALIVE_CHK_STATE)) {
660 psta->htpriv.candidate_tid_bitmap |= BIT((u8)priority);
661
662 if (psta->state & WIFI_SLEEP_STATE)
663 psta->expire_to = 2; /* 2x2=4 sec */
664 else
665 psta->expire_to = 1; /* 2 sec */
666
667 psta->state |= WIFI_STA_ALIVE_CHK_STATE;
668
669 /* add_ba_hdl(padapter, (u8*)paddbareq_parm); */
670
671 RTW_INFO("issue addba_req to check if sta alive, keep_alive_trycnt=%d\n", psta->keep_alive_trycnt);
672
673 issue_addba_req(padapter, psta->phl_sta->mac_addr, (u8)priority);
674
675 _set_timer(&psta->addba_retry_timer, ADDBA_TO);
676
677 psta->keep_alive_trycnt++;
678
679 continue;
680 }
681 }
682 }
683 if (psta->keep_alive_trycnt > 0 && psta->state & WIFI_STA_ALIVE_CHK_STATE) {
684 psta->keep_alive_trycnt = 0;
685 psta->state ^= WIFI_STA_ALIVE_CHK_STATE;
686 RTW_INFO("change to another methods to check alive if staion is at ps mode\n");
687 }
688
689 #endif /* CONFIG_80211N_HT */
690 #endif /* CONFIG_ACTIVE_KEEP_ALIVE_CHECK */
691 if (psta->state & WIFI_SLEEP_STATE) {
692 if (!(psta->state & WIFI_STA_ALIVE_CHK_STATE)) {
693 /* to check if alive by another methods if staion is at ps mode. */
694 psta->expire_to = pstapriv->expire_to;
695 psta->state |= WIFI_STA_ALIVE_CHK_STATE;
696
697 /* RTW_INFO("alive chk, sta:" MAC_FMT " is at ps mode!\n", MAC_ARG(psta->phl_sta->mac_addr)); */
698
699 /* to update bcn with tim_bitmap for this station */
700 rtw_tim_map_set(padapter, pstapriv->tim_bitmap, psta->phl_sta->aid);
701 rtw_update_beacon(padapter, _TIM_IE_, NULL, _TRUE, 0);
702
703 if (!pmlmeext->active_keep_alive_check)
704 continue;
705 }
706 }
707
708 {
709 int stainfo_offset;
710
711 stainfo_offset = rtw_stainfo_offset(pstapriv, psta);
712 if (stainfo_offset_valid(stainfo_offset))
713 chk_alive_list[chk_alive_num++] = stainfo_offset;
714 continue;
715 }
716 } else {
717 /* TODO: Aging mechanism to digest frames in sleep_q to avoid running out of xmitframe */
718 if (psta->sleepq_len > (NR_XMITFRAME / pstapriv->asoc_list_cnt)
719 && padapter->xmitpriv.free_xmitframe_cnt < ((NR_XMITFRAME / pstapriv->asoc_list_cnt) / 2)
720 ) {
721 RTW_INFO(FUNC_ADPT_FMT" sta:"MAC_FMT", sleepq_len:%u, free_xmitframe_cnt:%u, asoc_list_cnt:%u, clear sleep_q\n"
722 , FUNC_ADPT_ARG(padapter), MAC_ARG(psta->phl_sta->mac_addr)
723 , psta->sleepq_len, padapter->xmitpriv.free_xmitframe_cnt, pstapriv->asoc_list_cnt);
724 wakeup_sta_to_xmit(padapter, psta);
725 }
726 }
727 }
728
729 _rtw_spinunlock_bh(&pstapriv->asoc_list_lock);
730
731 if (chk_alive_num) {
732 #if defined(CONFIG_ACTIVE_KEEP_ALIVE_CHECK)
733 u8 backup_ch = 0, backup_bw = 0, backup_offset = 0;
734 u8 union_ch = 0, union_bw = 0, union_offset = 0;
735 u8 switch_channel_by_drv = _TRUE;
736 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
737 #endif
738 char del_asoc_list[NUM_STA];
739
740 _rtw_memset(del_asoc_list, NUM_STA, NUM_STA);
741
742 #ifdef CONFIG_ACTIVE_KEEP_ALIVE_CHECK
743 if (pmlmeext->active_keep_alive_check) {
744
745 if (!rtw_mi_get_ch_setting_union(padapter, &union_ch, &union_bw, &union_offset)
746 || pmlmeext->chandef.chan != union_ch)
747 switch_channel_by_drv = _FALSE;
748
749 /* switch to correct channel of current network before issue keep-alive frames */
750 if (switch_channel_by_drv == _TRUE && rtw_get_oper_ch(padapter) != pmlmeext->chandef.chan) {
751 backup_ch = rtw_get_oper_ch(padapter);
752 backup_bw = rtw_get_oper_bw(padapter);
753 backup_offset = rtw_get_oper_choffset(padapter);
754 set_channel_bwmode(padapter, union_ch, union_offset, union_bw, _FALSE);
755 }
756 }
757 #endif /* CONFIG_ACTIVE_KEEP_ALIVE_CHECK */
758
759 /* check loop */
760 for (i = 0; i < chk_alive_num; i++) {
761 #ifdef CONFIG_ACTIVE_KEEP_ALIVE_CHECK
762 int ret = _FAIL;
763 #endif
764
765 psta = rtw_get_stainfo_by_offset(pstapriv, chk_alive_list[i]);
766
767 #ifdef CONFIG_ATMEL_RC_PATCH
768 if (_rtw_memcmp(pstapriv->atmel_rc_pattern, psta->phl_sta->mac_addr, ETH_ALEN) == _TRUE)
769 continue;
770 if (psta->flag_atmel_rc)
771 continue;
772 #endif
773
774 if (!(psta->state & WIFI_ASOC_STATE))
775 continue;
776
777 #ifdef CONFIG_ACTIVE_KEEP_ALIVE_CHECK
778 if (pmlmeext->active_keep_alive_check) {
779 /* issue active keep alive frame to check */
780 ret = issue_aka_chk_frame(padapter, psta);
781
782 psta->keep_alive_trycnt++;
783 if (ret == _SUCCESS) {
784 RTW_INFO(FUNC_ADPT_FMT" asoc check, "MAC_FMT" is alive\n"
785 , FUNC_ADPT_ARG(padapter), MAC_ARG(psta->phl_sta->mac_addr));
786 psta->expire_to = pstapriv->expire_to;
787 psta->keep_alive_trycnt = 0;
788 continue;
789 } else if (psta->keep_alive_trycnt <= 3) {
790 RTW_INFO(FUNC_ADPT_FMT" asoc check, "MAC_FMT" keep_alive_trycnt=%d\n"
791 , FUNC_ADPT_ARG(padapter) , MAC_ARG(psta->phl_sta->mac_addr), psta->keep_alive_trycnt);
792 psta->expire_to = 1;
793 continue;
794 }
795 }
796 #endif /* CONFIG_ACTIVE_KEEP_ALIVE_CHECK */
797
798 psta->keep_alive_trycnt = 0;
799 del_asoc_list[i] = chk_alive_list[i];
800 _rtw_spinlock_bh(&pstapriv->asoc_list_lock);
801 if (rtw_is_list_empty(&psta->asoc_list) == _FALSE) {
802 rtw_list_delete(&psta->asoc_list);
803 pstapriv->asoc_list_cnt--;
804 #ifdef CONFIG_RTW_TOKEN_BASED_XMIT
805 if (psta->tbtx_enable)
806 pstapriv->tbtx_asoc_list_cnt--;
807 #endif
808 STA_SET_MESH_PLINK(psta, NULL);
809 }
810 _rtw_spinunlock_bh(&pstapriv->asoc_list_lock);
811 }
812
813 /* delete loop */
814 for (i = 0; i < chk_alive_num; i++) {
815 u8 sta_addr[ETH_ALEN];
816
817 if (del_asoc_list[i] >= NUM_STA)
818 continue;
819
820 psta = rtw_get_stainfo_by_offset(pstapriv, del_asoc_list[i]);
821 _rtw_memcpy(sta_addr, psta->phl_sta->mac_addr, ETH_ALEN);
822
823 RTW_INFO(FUNC_ADPT_FMT" asoc expire "MAC_FMT", state=0x%x\n"
824 , FUNC_ADPT_ARG(padapter), MAC_ARG(psta->phl_sta->mac_addr), psta->state);
825 updated |= ap_free_sta(padapter, psta, _FALSE, WLAN_REASON_DEAUTH_LEAVING, _FALSE, _FALSE);
826 #ifdef CONFIG_RTW_MESH
827 if (MLME_IS_MESH(padapter))
828 rtw_mesh_expire_peer(padapter, sta_addr);
829 #endif
830 }
831
832 #ifdef CONFIG_ACTIVE_KEEP_ALIVE_CHECK
833 if (pmlmeext->active_keep_alive_check) {
834 /* back to the original operation channel */
835 if (switch_channel_by_drv == _TRUE && backup_ch > 0)
836 set_channel_bwmode(padapter, backup_ch, backup_offset, backup_bw, _FALSE);
837 }
838 #endif
839 }
840
841 associated_clients_update(padapter, updated, STA_INFO_UPDATE_ALL);
842 }
843
844 #ifdef CONFIG_BMC_TX_RATE_SELECT
rtw_ap_find_mini_tx_rate(_adapter * adapter)845 u8 rtw_ap_find_mini_tx_rate(_adapter *adapter)
846 {
847 _list *phead, *plist;
848 u8 mini_tx_rate = DESC_RATEVHTSS4MCS9, sta_tx_rate;
849 struct sta_info *psta = NULL;
850 struct sta_priv *pstapriv = &adapter->stapriv;
851
852 _rtw_spinlock_bh(&pstapriv->asoc_list_lock);
853 phead = &pstapriv->asoc_list;
854 plist = get_next(phead);
855 while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {
856 psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);
857 plist = get_next(plist);
858
859 sta_tx_rate = psta->phl_sta->ra_info.curr_tx_rate & 0x7F;
860 if (sta_tx_rate < mini_tx_rate)
861 mini_tx_rate = sta_tx_rate;
862 }
863 _rtw_spinunlock_bh(&pstapriv->asoc_list_lock);
864
865 return mini_tx_rate;
866 }
867
rtw_ap_find_bmc_rate(_adapter * adapter,u8 tx_rate)868 u8 rtw_ap_find_bmc_rate(_adapter *adapter, u8 tx_rate)
869 {
870 u8 tx_ini_rate = DESC_RATE6M;
871
872 switch (tx_rate) {
873 case DESC_RATEVHTSS3MCS9:
874 case DESC_RATEVHTSS3MCS8:
875 case DESC_RATEVHTSS3MCS7:
876 case DESC_RATEVHTSS3MCS6:
877 case DESC_RATEVHTSS3MCS5:
878 case DESC_RATEVHTSS3MCS4:
879 case DESC_RATEVHTSS3MCS3:
880 case DESC_RATEVHTSS2MCS9:
881 case DESC_RATEVHTSS2MCS8:
882 case DESC_RATEVHTSS2MCS7:
883 case DESC_RATEVHTSS2MCS6:
884 case DESC_RATEVHTSS2MCS5:
885 case DESC_RATEVHTSS2MCS4:
886 case DESC_RATEVHTSS2MCS3:
887 case DESC_RATEVHTSS1MCS9:
888 case DESC_RATEVHTSS1MCS8:
889 case DESC_RATEVHTSS1MCS7:
890 case DESC_RATEVHTSS1MCS6:
891 case DESC_RATEVHTSS1MCS5:
892 case DESC_RATEVHTSS1MCS4:
893 case DESC_RATEVHTSS1MCS3:
894 case DESC_RATEMCS15:
895 case DESC_RATEMCS14:
896 case DESC_RATEMCS13:
897 case DESC_RATEMCS12:
898 case DESC_RATEMCS11:
899 case DESC_RATEMCS7:
900 case DESC_RATEMCS6:
901 case DESC_RATEMCS5:
902 case DESC_RATEMCS4:
903 case DESC_RATEMCS3:
904 case DESC_RATE54M:
905 case DESC_RATE48M:
906 case DESC_RATE36M:
907 case DESC_RATE24M:
908 tx_ini_rate = DESC_RATE24M;
909 break;
910 case DESC_RATEVHTSS3MCS2:
911 case DESC_RATEVHTSS3MCS1:
912 case DESC_RATEVHTSS2MCS2:
913 case DESC_RATEVHTSS2MCS1:
914 case DESC_RATEVHTSS1MCS2:
915 case DESC_RATEVHTSS1MCS1:
916 case DESC_RATEMCS10:
917 case DESC_RATEMCS9:
918 case DESC_RATEMCS2:
919 case DESC_RATEMCS1:
920 case DESC_RATE18M:
921 case DESC_RATE12M:
922 tx_ini_rate = DESC_RATE12M;
923 break;
924 case DESC_RATEVHTSS3MCS0:
925 case DESC_RATEVHTSS2MCS0:
926 case DESC_RATEVHTSS1MCS0:
927 case DESC_RATEMCS8:
928 case DESC_RATEMCS0:
929 case DESC_RATE9M:
930 case DESC_RATE6M:
931 tx_ini_rate = DESC_RATE6M;
932 break;
933 case DESC_RATE11M:
934 case DESC_RATE5_5M:
935 case DESC_RATE2M:
936 case DESC_RATE1M:
937 tx_ini_rate = DESC_RATE1M;
938 break;
939 default:
940 tx_ini_rate = DESC_RATE6M;
941 break;
942 }
943
944 if (WIFI_ROLE_IS_ON_5G(adapter))
945 if (tx_ini_rate < DESC_RATE6M)
946 tx_ini_rate = DESC_RATE6M;
947
948 return tx_ini_rate;
949 }
950
rtw_update_bmc_sta_tx_rate(_adapter * adapter)951 void rtw_update_bmc_sta_tx_rate(_adapter *adapter)
952 {
953 struct sta_info *psta = NULL;
954 u8 tx_rate;
955
956 psta = rtw_get_bcmc_stainfo(adapter);
957 if (psta == NULL) {
958 RTW_ERR(ADPT_FMT "could not get bmc_sta !!\n", ADPT_ARG(adapter));
959 return;
960 }
961
962 if (adapter->bmc_tx_rate != MGN_UNKNOWN) {
963 psta->init_rate = adapter->bmc_tx_rate;
964 goto _exit;
965 }
966
967 if (adapter->stapriv.asoc_sta_count <= 2)
968 goto _exit;
969
970 tx_rate = rtw_ap_find_mini_tx_rate(adapter);
971 #ifdef CONFIG_BMC_TX_LOW_RATE
972 tx_rate = rtw_ap_find_bmc_rate(adapter, tx_rate);
973 #endif
974
975 psta->init_rate = hwrate_to_mrate(tx_rate);
976
977 _exit:
978 RTW_INFO(ADPT_FMT" BMC Tx rate - %s\n", ADPT_ARG(adapter), MGN_RATE_STR(psta->init_rate));
979 }
980 #endif
981
rtw_init_bmc_sta_tx_rate(_adapter * padapter,struct sta_info * psta)982 void rtw_init_bmc_sta_tx_rate(_adapter *padapter, struct sta_info *psta)
983 {
984 /* ToDo: need API to query hal_sta->ra_info.ramask */
985 #if 0
986 #ifdef CONFIG_BMC_TX_LOW_RATE
987 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
988 #endif
989 u8 rate_idx = 0;
990 u8 brate_table[] = {MGN_1M, MGN_2M, MGN_5_5M, MGN_11M,
991 MGN_6M, MGN_9M, MGN_12M, MGN_18M, MGN_24M, MGN_36M, MGN_48M, MGN_54M};
992
993 if (!MLME_IS_AP(padapter) && !MLME_IS_MESH(padapter))
994 return;
995
996 if (padapter->bmc_tx_rate != MGN_UNKNOWN)
997 psta->init_rate = padapter->bmc_tx_rate;
998 else {
999 #ifdef CONFIG_BMC_TX_LOW_RATE
1000 if (IsEnableHWOFDM(pmlmeext->cur_wireless_mode) && (psta->phl_sta->ra_info.ramask && 0xFF0))
1001 rate_idx = get_lowest_rate_idx_ex(psta->phl_sta->ra_info.ramask, 4); /*from basic rate*/
1002 else
1003 rate_idx = get_lowest_rate_idx(psta->phl_sta->ra_info.ramask); /*from basic rate*/
1004 #else
1005 rate_idx = get_highest_rate_idx(psta->phl_sta->ra_info.ramask); /*from basic rate*/
1006 #endif
1007 if (rate_idx < 12)
1008 psta->init_rate = brate_table[rate_idx];
1009 else
1010 psta->init_rate = MGN_1M;
1011 }
1012 #endif
1013 RTW_INFO(ADPT_FMT" BMC Init Tx rate - %s\n", ADPT_ARG(padapter), MGN_RATE_STR(psta->init_rate));
1014 }
1015
1016 #if defined(CONFIG_80211N_HT) && defined(CONFIG_BEAMFORMING)
update_sta_info_apmode_ht_bf_cap(_adapter * padapter,struct sta_info * psta)1017 void update_sta_info_apmode_ht_bf_cap(_adapter *padapter, struct sta_info *psta)
1018 {
1019 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1020 struct ht_priv *phtpriv_ap = &pmlmepriv->htpriv;
1021 struct ht_priv *phtpriv_sta = &psta->htpriv;
1022
1023 u8 cur_beamform_cap = 0;
1024
1025 /*Config Tx beamforming setting*/
1026 if (TEST_FLAG(phtpriv_ap->beamform_cap, BEAMFORMING_HT_BEAMFORMEE_ENABLE) &&
1027 GET_HT_CAP_TXBF_EXPLICIT_COMP_STEERING_CAP((u8 *)(&phtpriv_sta->ht_cap))) {
1028 SET_FLAG(cur_beamform_cap, BEAMFORMING_HT_BEAMFORMER_ENABLE);
1029 /*Shift to BEAMFORMING_HT_BEAMFORMEE_CHNL_EST_CAP*/
1030 SET_FLAG(cur_beamform_cap, GET_HT_CAP_TXBF_CHNL_ESTIMATION_NUM_ANTENNAS((u8 *)(&phtpriv_sta->ht_cap)) << 6);
1031 }
1032
1033 if (TEST_FLAG(phtpriv_ap->beamform_cap, BEAMFORMING_HT_BEAMFORMER_ENABLE) &&
1034 GET_HT_CAP_TXBF_EXPLICIT_COMP_FEEDBACK_CAP((u8 *)(&phtpriv_sta->ht_cap))) {
1035 SET_FLAG(cur_beamform_cap, BEAMFORMING_HT_BEAMFORMEE_ENABLE);
1036 /*Shift to BEAMFORMING_HT_BEAMFORMER_STEER_NUM*/
1037 SET_FLAG(cur_beamform_cap, GET_HT_CAP_TXBF_COMP_STEERING_NUM_ANTENNAS((u8 *)(&phtpriv_sta->ht_cap)) << 4);
1038 }
1039 if (cur_beamform_cap)
1040 RTW_INFO("Client STA(%d) HT Beamforming Cap = 0x%02X\n", psta->phl_sta->aid, cur_beamform_cap);
1041
1042 phtpriv_sta->beamform_cap = cur_beamform_cap;
1043 }
1044 #endif /*CONFIG_80211N_HT && CONFIG_BEAMFORMING*/
1045
1046 /* notes:
1047 * AID: 1~MAX for sta and 0 for bc/mc in ap/adhoc mode */
update_sta_info_apmode(_adapter * padapter,struct sta_info * psta)1048 void update_sta_info_apmode(_adapter *padapter, struct sta_info *psta)
1049 {
1050 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1051 struct security_priv *psecuritypriv = &padapter->securitypriv;
1052 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
1053 struct rtw_wifi_role_t *wrole = padapter->phl_role;
1054 struct protocol_cap_t *proto_role_cap = &(wrole->proto_role_cap);
1055 #ifdef CONFIG_80211N_HT
1056 struct ht_priv *phtpriv_ap = &pmlmepriv->htpriv;
1057 struct ht_priv *phtpriv_sta = &psta->htpriv;
1058 #endif /* CONFIG_80211N_HT */
1059 u8 cur_ldpc_cap = 0, cur_stbc_cap = 0;
1060 /* set intf_tag to if1 */
1061 /* psta->intf_tag = 0; */
1062
1063 RTW_INFO("%s\n", __FUNCTION__);
1064
1065 /*alloc macid when call rtw_alloc_stainfo(),release macid when call rtw_free_stainfo()*/
1066
1067 if (!MLME_IS_MESH(padapter) && psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X)
1068 psta->ieee8021x_blocked = _TRUE;
1069 else
1070 psta->ieee8021x_blocked = _FALSE;
1071
1072
1073 /* update sta's cap */
1074
1075 psta->phl_sta->chandef.chan = pmlmeext->chandef.chan;
1076 psta->phl_sta->chandef.band = (psta->phl_sta->chandef.chan > 14) ? BAND_ON_5G : BAND_ON_24G;
1077
1078 /* ERP */
1079 VCS_update(padapter, psta);
1080 #ifdef CONFIG_80211N_HT
1081 /* HT related cap */
1082 if (phtpriv_sta->ht_option) {
1083 /* check if sta supports rx ampdu */
1084 phtpriv_sta->ampdu_enable = phtpriv_ap->ampdu_enable;
1085
1086 phtpriv_sta->rx_ampdu_min_spacing = (phtpriv_sta->ht_cap.ampdu_params_info & IEEE80211_HT_CAP_AMPDU_DENSITY) >> 2;
1087
1088 /* bwmode */
1089 if ((phtpriv_sta->ht_cap.cap_info & phtpriv_ap->ht_cap.cap_info) & cpu_to_le16(IEEE80211_HT_CAP_SUP_WIDTH))
1090 psta->phl_sta->chandef.bw = CHANNEL_WIDTH_40;
1091 else
1092 psta->phl_sta->chandef.bw = CHANNEL_WIDTH_20;
1093
1094 if (phtpriv_sta->op_present
1095 && !GET_HT_OP_ELE_STA_CHL_WIDTH(phtpriv_sta->ht_op))
1096 psta->phl_sta->chandef.bw = CHANNEL_WIDTH_20;
1097
1098 if (psta->ht_40mhz_intolerant)
1099 psta->phl_sta->chandef.bw = CHANNEL_WIDTH_20;
1100
1101 if (pmlmeext->chandef.bw < psta->phl_sta->chandef.bw)
1102 psta->phl_sta->chandef.bw = pmlmeext->chandef.bw;
1103
1104 phtpriv_sta->ch_offset = pmlmeext->chandef.offset;
1105
1106
1107 /* check if sta support s Short GI 20M */
1108 if ((phtpriv_sta->ht_cap.cap_info & phtpriv_ap->ht_cap.cap_info) & cpu_to_le16(IEEE80211_HT_CAP_SGI_20))
1109 phtpriv_sta->sgi_20m = _TRUE;
1110
1111 /* check if sta support s Short GI 40M */
1112 if ((phtpriv_sta->ht_cap.cap_info & phtpriv_ap->ht_cap.cap_info) & cpu_to_le16(IEEE80211_HT_CAP_SGI_40)) {
1113 if (psta->phl_sta->chandef.bw == CHANNEL_WIDTH_40) /* according to psta->bw_mode */
1114 phtpriv_sta->sgi_40m = _TRUE;
1115 else
1116 phtpriv_sta->sgi_40m = _FALSE;
1117 }
1118
1119 psta->qos_option = _TRUE;
1120
1121 /* B0 Config LDPC Coding Capability */
1122 if (TEST_FLAG(phtpriv_ap->ldpc_cap, LDPC_HT_ENABLE_TX) &&
1123 GET_HT_CAP_ELE_LDPC_CAP((u8 *)(&phtpriv_sta->ht_cap))) {
1124 SET_FLAG(cur_ldpc_cap, (LDPC_HT_ENABLE_TX | LDPC_HT_CAP_TX));
1125 RTW_INFO("Enable HT Tx LDPC for STA(%d)\n", psta->phl_sta->aid);
1126 }
1127
1128 /* B7 B8 B9 Config STBC setting */
1129 if (TEST_FLAG(phtpriv_ap->stbc_cap, STBC_HT_ENABLE_TX) &&
1130 GET_HT_CAP_ELE_RX_STBC((u8 *)(&phtpriv_sta->ht_cap))) {
1131 SET_FLAG(cur_stbc_cap, (STBC_HT_ENABLE_TX | STBC_HT_CAP_TX));
1132 RTW_INFO("Enable HT Tx STBC for STA(%d)\n", psta->phl_sta->aid);
1133 }
1134
1135 psta->phl_sta->asoc_cap.stbc_ht_tx =
1136 GET_HT_CAP_ELE_TX_STBC((u8 *)(&phtpriv_sta->ht_cap));
1137 psta->phl_sta->asoc_cap.stbc_ht_rx =
1138 proto_role_cap->stbc_ht_tx ?
1139 GET_HT_CAP_ELE_RX_STBC((u8 *)(&phtpriv_sta->ht_cap)) : 0;
1140
1141 #ifdef CONFIG_BEAMFORMING
1142 update_sta_info_apmode_ht_bf_cap(padapter, psta);
1143 #endif
1144 } else {
1145 phtpriv_sta->ampdu_enable = _FALSE;
1146
1147 phtpriv_sta->sgi_20m = _FALSE;
1148 phtpriv_sta->sgi_40m = _FALSE;
1149 psta->phl_sta->chandef.bw = CHANNEL_WIDTH_20;
1150 phtpriv_sta->ch_offset = CHAN_OFFSET_NO_EXT;
1151 }
1152
1153 phtpriv_sta->ldpc_cap = cur_ldpc_cap;
1154 phtpriv_sta->stbc_cap = cur_stbc_cap;
1155
1156 /* Rx AMPDU */
1157 send_delba(padapter, 0, psta->phl_sta->mac_addr);/* recipient */
1158
1159 /* TX AMPDU */
1160 send_delba(padapter, 1, psta->phl_sta->mac_addr);/* */ /* originator */
1161 phtpriv_sta->agg_enable_bitmap = 0x0;/* reset */
1162 phtpriv_sta->candidate_tid_bitmap = 0x0;/* reset */
1163 #endif /* CONFIG_80211N_HT */
1164
1165 #ifdef CONFIG_80211AC_VHT
1166 update_sta_vht_info_apmode(padapter, psta);
1167 #endif
1168
1169 #ifdef CONFIG_80211AX_HE
1170 update_sta_he_info_apmode(padapter, psta);
1171 #endif
1172
1173 psta->phl_sta->chandef.offset = (psta->phl_sta->chandef.bw > CHANNEL_WIDTH_20) ?
1174 pmlmeext->chandef.offset : CHAN_OFFSET_NO_EXT;
1175
1176 /* ToDo: need API to inform hal_sta->ra_info.is_support_sgi */
1177 /* psta->phl_sta->ra_info.is_support_sgi = query_ra_short_GI(psta, rtw_get_tx_bw_mode(padapter, psta)); */
1178 update_ldpc_stbc_cap(psta);
1179
1180 /* todo: init other variables */
1181
1182 _rtw_memset((void *)&psta->sta_stats, 0, sizeof(struct stainfo_stats));
1183
1184 _rtw_spinlock_bh(&psta->lock);
1185
1186 /* Check encryption */
1187 if (!MLME_IS_MESH(padapter) && psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X)
1188 psta->state |= WIFI_UNDER_KEY_HANDSHAKE;
1189
1190 psta->state |= WIFI_ASOC_STATE;
1191
1192 _rtw_spinunlock_bh(&psta->lock);
1193 }
1194
update_ap_info(_adapter * padapter,struct sta_info * psta)1195 static void update_ap_info(_adapter *padapter, struct sta_info *psta)
1196 {
1197 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1198 WLAN_BSSID_EX *pnetwork = (WLAN_BSSID_EX *)&pmlmepriv->cur_network.network;
1199 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
1200 #ifdef CONFIG_80211N_HT
1201 struct ht_priv *phtpriv_ap = &pmlmepriv->htpriv;
1202 #endif /* CONFIG_80211N_HT */
1203
1204 #ifdef CONFIG_RTW_MESH
1205 if (MLME_IS_MESH(padapter))
1206 psta->qos_option = 1;
1207 #endif
1208
1209 psta->phl_sta->wmode = pmlmeext->cur_wireless_mode;
1210
1211 psta->bssratelen = rtw_get_rateset_len(pnetwork->SupportedRates);
1212 _rtw_memcpy(psta->bssrateset, pnetwork->SupportedRates, psta->bssratelen);
1213
1214 #ifdef CONFIG_80211N_HT
1215 /* HT related cap */
1216 if (phtpriv_ap->ht_option) {
1217 /* check if sta supports rx ampdu */
1218 /* phtpriv_ap->ampdu_enable = phtpriv_ap->ampdu_enable; */
1219
1220 /* check if sta support s Short GI 20M */
1221 if ((phtpriv_ap->ht_cap.cap_info) & cpu_to_le16(IEEE80211_HT_CAP_SGI_20))
1222 phtpriv_ap->sgi_20m = _TRUE;
1223 /* check if sta support s Short GI 40M */
1224 if ((phtpriv_ap->ht_cap.cap_info) & cpu_to_le16(IEEE80211_HT_CAP_SGI_40))
1225 phtpriv_ap->sgi_40m = _TRUE;
1226
1227 psta->qos_option = _TRUE;
1228 } else {
1229 phtpriv_ap->ampdu_enable = _FALSE;
1230
1231 phtpriv_ap->sgi_20m = _FALSE;
1232 phtpriv_ap->sgi_40m = _FALSE;
1233 }
1234
1235 psta->phl_sta->chandef.bw = pmlmeext->chandef.bw;
1236 phtpriv_ap->ch_offset = pmlmeext->chandef.offset;
1237
1238 phtpriv_ap->agg_enable_bitmap = 0x0;/* reset */
1239 phtpriv_ap->candidate_tid_bitmap = 0x0;/* reset */
1240
1241 _rtw_memcpy(&psta->htpriv, &pmlmepriv->htpriv, sizeof(struct ht_priv));
1242
1243 #ifdef CONFIG_80211AC_VHT
1244 _rtw_memcpy(&psta->vhtpriv, &pmlmepriv->vhtpriv, sizeof(struct vht_priv));
1245
1246 #ifdef CONFIG_80211AX_HE
1247 _rtw_memcpy(&psta->hepriv, &pmlmepriv->hepriv, sizeof(struct he_priv));
1248 #endif /* CONFIG_80211AX_HE */
1249
1250 #endif /* CONFIG_80211AC_VHT */
1251
1252 #endif /* CONFIG_80211N_HT */
1253
1254 _rtw_spinlock_bh(&psta->lock);
1255 psta->state |= WIFI_AP_STATE; /* Aries, add,fix bug of flush_cam_entry at STOP AP mode , 0724 */
1256 psta->state |= WIFI_ASOC_STATE;
1257 _rtw_spinunlock_bh(&psta->lock);
1258
1259 rtw_init_bmc_sta_tx_rate(padapter, psta);
1260 }
1261
rtw_ap_set_edca(_adapter * padapter,enum rtw_ac ac,u32 parm)1262 void rtw_ap_set_edca(_adapter *padapter, enum rtw_ac ac, u32 parm)
1263 {
1264 struct sta_priv *pstapriv = &padapter->stapriv;
1265 struct sta_info *psta = rtw_get_stainfo(pstapriv, padapter->phl_role->mac_addr);
1266
1267 if (psta && psta->phl_sta) {
1268 psta->phl_sta->asoc_cap.edca[ac].ac = ac;
1269 psta->phl_sta->asoc_cap.edca[ac].param = parm;
1270 }
1271 rtw_hw_set_edca(padapter, ac, parm);
1272 }
1273
rtw_set_hw_wmm_param(_adapter * padapter)1274 static void rtw_set_hw_wmm_param(_adapter *padapter)
1275 {
1276 u8 AIFS, ECWMin, ECWMax, aSifsTime;
1277 u8 acm_mask;
1278 u16 TXOP;
1279 u32 acParm, i;
1280 u32 edca[4], inx[4];
1281 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1282 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
1283 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
1284 struct registry_priv *pregpriv = &padapter->registrypriv;
1285
1286 acm_mask = 0;
1287 #ifdef CONFIG_80211N_HT
1288 if (pregpriv->ht_enable &&
1289 (WIFI_ROLE_IS_ON_5G(padapter) ||
1290 (pmlmeext->cur_wireless_mode & WLAN_MD_11N)))
1291 aSifsTime = 16;
1292 else
1293 #endif /* CONFIG_80211N_HT */
1294 aSifsTime = 10;
1295
1296 if (pmlmeinfo->WMM_enable == 0) {
1297 padapter->mlmepriv.acm_mask = 0;
1298
1299 AIFS = aSifsTime + (2 * pmlmeinfo->slotTime);
1300
1301 if (pmlmeext->cur_wireless_mode & (WLAN_MD_11G | WLAN_MD_11A)) {
1302 ECWMin = 4;
1303 ECWMax = 10;
1304 } else if (pmlmeext->cur_wireless_mode & WLAN_MD_11B) {
1305 ECWMin = 5;
1306 ECWMax = 10;
1307 } else {
1308 ECWMin = 4;
1309 ECWMax = 10;
1310 }
1311
1312 TXOP = 0;
1313 acParm = AIFS | (ECWMin << 8) | (ECWMax << 12) | (TXOP << 16);
1314 rtw_ap_set_edca(padapter, 0, acParm);
1315 rtw_ap_set_edca(padapter, 1, acParm);
1316 rtw_ap_set_edca(padapter, 2, acParm);
1317
1318 ECWMin = 2;
1319 ECWMax = 3;
1320 TXOP = 0x2f;
1321 acParm = AIFS | (ECWMin << 8) | (ECWMax << 12) | (TXOP << 16);
1322 rtw_ap_set_edca(padapter, 3, acParm);
1323
1324 } else {
1325 edca[0] = edca[1] = edca[2] = edca[3] = 0;
1326
1327 /*TODO:*/
1328 acm_mask = 0;
1329 padapter->mlmepriv.acm_mask = acm_mask;
1330
1331 #if 0
1332 /* BK */
1333 /* AIFS = AIFSN * slot time + SIFS - r2t phy delay */
1334 #endif
1335 AIFS = (7 * pmlmeinfo->slotTime) + aSifsTime;
1336 ECWMin = 4;
1337 ECWMax = 10;
1338 TXOP = 0;
1339 acParm = AIFS | (ECWMin << 8) | (ECWMax << 12) | (TXOP << 16);
1340 rtw_ap_set_edca(padapter, 1, acParm);
1341 edca[XMIT_BK_QUEUE] = acParm;
1342 RTW_INFO("WMM(BK): %x\n", acParm);
1343
1344 /* BE */
1345 AIFS = (3 * pmlmeinfo->slotTime) + aSifsTime;
1346 ECWMin = 4;
1347 ECWMax = 6;
1348 TXOP = 0;
1349 acParm = AIFS | (ECWMin << 8) | (ECWMax << 12) | (TXOP << 16);
1350 rtw_ap_set_edca(padapter, 0, acParm);
1351 edca[XMIT_BE_QUEUE] = acParm;
1352 RTW_INFO("WMM(BE): %x\n", acParm);
1353
1354 /* VI */
1355 AIFS = (1 * pmlmeinfo->slotTime) + aSifsTime;
1356 ECWMin = 3;
1357 ECWMax = 4;
1358 TXOP = 94;
1359 acParm = AIFS | (ECWMin << 8) | (ECWMax << 12) | (TXOP << 16);
1360 rtw_ap_set_edca(padapter, 2, acParm);
1361 edca[XMIT_VI_QUEUE] = acParm;
1362 RTW_INFO("WMM(VI): %x\n", acParm);
1363
1364 /* VO */
1365 AIFS = (1 * pmlmeinfo->slotTime) + aSifsTime;
1366 ECWMin = 2;
1367 ECWMax = 3;
1368 TXOP = 47;
1369 acParm = AIFS | (ECWMin << 8) | (ECWMax << 12) | (TXOP << 16);
1370 rtw_ap_set_edca(padapter, 3, acParm);
1371 edca[XMIT_VO_QUEUE] = acParm;
1372 RTW_INFO("WMM(VO): %x\n", acParm);
1373
1374
1375 if (padapter->registrypriv.acm_method == 1)
1376 rtw_hal_set_hwreg(padapter, HW_VAR_ACM_CTRL, (u8 *)(&acm_mask));
1377 else
1378 padapter->mlmepriv.acm_mask = acm_mask;
1379
1380 inx[0] = 0;
1381 inx[1] = 1;
1382 inx[2] = 2;
1383 inx[3] = 3;
1384
1385 if (pregpriv->wifi_spec == 1) {
1386 u32 j, tmp, change_inx = _FALSE;
1387
1388 /* entry indx: 0->vo, 1->vi, 2->be, 3->bk. */
1389 for (i = 0 ; i < 4 ; i++) {
1390 for (j = i + 1 ; j < 4 ; j++) {
1391 /* compare CW and AIFS */
1392 if ((edca[j] & 0xFFFF) < (edca[i] & 0xFFFF))
1393 change_inx = _TRUE;
1394 else if ((edca[j] & 0xFFFF) == (edca[i] & 0xFFFF)) {
1395 /* compare TXOP */
1396 if ((edca[j] >> 16) > (edca[i] >> 16))
1397 change_inx = _TRUE;
1398 }
1399
1400 if (change_inx) {
1401 tmp = edca[i];
1402 edca[i] = edca[j];
1403 edca[j] = tmp;
1404
1405 tmp = inx[i];
1406 inx[i] = inx[j];
1407 inx[j] = tmp;
1408
1409 change_inx = _FALSE;
1410 }
1411 }
1412 }
1413 }
1414
1415 for (i = 0 ; i < 4 ; i++) {
1416 pxmitpriv->wmm_para_seq[i] = inx[i];
1417 RTW_INFO("wmm_para_seq(%d): %d\n", i, pxmitpriv->wmm_para_seq[i]);
1418 }
1419
1420 }
1421
1422 }
1423 #ifdef CONFIG_80211N_HT
update_hw_ht_param(_adapter * padapter)1424 static void update_hw_ht_param(_adapter *padapter)
1425 {
1426 unsigned char max_AMPDU_len;
1427 unsigned char min_MPDU_spacing;
1428 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1429 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
1430
1431 RTW_INFO("%s\n", __FUNCTION__);
1432
1433
1434 /* handle A-MPDU parameter field */
1435 /*
1436 AMPDU_para [1:0]:Max AMPDU Len => 0:8k , 1:16k, 2:32k, 3:64k
1437 AMPDU_para [4:2]:Min MPDU Start Spacing
1438 */
1439 max_AMPDU_len = pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x03;
1440
1441 min_MPDU_spacing = (pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x1c) >> 2;
1442
1443 rtw_hal_set_hwreg(padapter, HW_VAR_AMPDU_MIN_SPACE, (u8 *)(&min_MPDU_spacing));
1444
1445 rtw_hal_set_hwreg(padapter, HW_VAR_AMPDU_FACTOR, (u8 *)(&max_AMPDU_len));
1446
1447 /* */
1448 /* Config SM Power Save setting */
1449 /* */
1450 pmlmeinfo->SM_PS = (pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info & 0x0C) >> 2;
1451 if (pmlmeinfo->SM_PS == WLAN_HT_CAP_SM_PS_STATIC) {
1452 #if 0
1453 u8 i;
1454 /* update the MCS rates */
1455 for (i = 0; i < 16; i++)
1456 pmlmeinfo->HT_caps.HT_cap_element.MCS_rate[i] &= MCS_rate_1R[i];
1457 #endif
1458 RTW_INFO("%s(): WLAN_HT_CAP_SM_PS_STATIC\n", __FUNCTION__);
1459 }
1460
1461 /* */
1462 /* Config current HT Protection mode. */
1463 /* */
1464 /* pmlmeinfo->HT_protection = pmlmeinfo->HT_info.infos[1] & 0x3; */
1465
1466 }
1467 #endif /* CONFIG_80211N_HT */
rtw_ap_check_scan(_adapter * padapter)1468 static void rtw_ap_check_scan(_adapter *padapter)
1469 {
1470 _list *plist, *phead;
1471 u32 delta_time, lifetime;
1472 struct wlan_network *pnetwork = NULL;
1473 WLAN_BSSID_EX *pbss = NULL;
1474 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1475 _queue *queue = &(pmlmepriv->scanned_queue);
1476 u8 do_scan = _FALSE;
1477 u8 reason = RTW_AUTO_SCAN_REASON_UNSPECIFIED;
1478
1479 lifetime = SCANQUEUE_LIFETIME; /* 20 sec */
1480
1481 _rtw_spinlock_bh(&(pmlmepriv->scanned_queue.lock));
1482 phead = get_list_head(queue);
1483 if (rtw_end_of_queue_search(phead, get_next(phead)) == _TRUE)
1484 if (padapter->registrypriv.wifi_spec) {
1485 do_scan = _TRUE;
1486 reason |= RTW_AUTO_SCAN_REASON_2040_BSS;
1487 }
1488 _rtw_spinunlock_bh(&(pmlmepriv->scanned_queue.lock));
1489
1490 #if defined(CONFIG_RTW_ACS) && defined(WKARD_ACS)
1491 if (padapter->registrypriv.acs_auto_scan) {
1492 do_scan = _TRUE;
1493 reason |= RTW_AUTO_SCAN_REASON_ACS;
1494 rtw_acs_start(padapter);
1495 }
1496 #endif/*CONFIG_RTW_ACS*/
1497
1498 if (_TRUE == do_scan) {
1499 RTW_INFO("%s : drv scans by itself and wait_completed\n", __func__);
1500 rtw_drv_scan_by_self(padapter, reason);
1501 rtw_scan_abort(padapter, 0);
1502 }
1503
1504 #if defined(CONFIG_RTW_ACS) && defined(WKARD_ACS)
1505 if (padapter->registrypriv.acs_auto_scan)
1506 rtw_acs_stop(padapter);
1507 #endif
1508
1509 _rtw_spinlock_bh(&(pmlmepriv->scanned_queue.lock));
1510
1511 phead = get_list_head(queue);
1512 plist = get_next(phead);
1513
1514 while (1) {
1515
1516 if (rtw_end_of_queue_search(phead, plist) == _TRUE)
1517 break;
1518
1519 pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
1520
1521 if (rtw_chset_search_ch(adapter_to_chset(padapter), pnetwork->network.Configuration.DSConfig) >= 0
1522 && rtw_mlme_band_check(padapter, pnetwork->network.Configuration.DSConfig) == _TRUE
1523 && _TRUE == rtw_validate_ssid(&(pnetwork->network.Ssid))) {
1524 delta_time = (u32) rtw_get_passing_time_ms(pnetwork->last_scanned);
1525
1526 if (delta_time < lifetime) {
1527
1528 uint ie_len = 0;
1529 u8 *pbuf = NULL;
1530 u8 *ie = NULL;
1531
1532 pbss = &pnetwork->network;
1533 ie = pbss->IEs;
1534
1535 /*check if HT CAP INFO IE exists or not*/
1536 pbuf = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_CAPABILITY_IE_, &ie_len, (pbss->IELength - _BEACON_IE_OFFSET_));
1537 if (pbuf == NULL) {
1538 /* HT CAP INFO IE don't exist, it is b/g mode bss.*/
1539
1540 if (_FALSE == ATOMIC_READ(&pmlmepriv->olbc))
1541 ATOMIC_SET(&pmlmepriv->olbc, _TRUE);
1542
1543 if (_FALSE == ATOMIC_READ(&pmlmepriv->olbc_ht))
1544 ATOMIC_SET(&pmlmepriv->olbc_ht, _TRUE);
1545
1546 if (padapter->registrypriv.wifi_spec)
1547 RTW_INFO("%s: %s is a/b/g ap\n", __func__, pnetwork->network.Ssid.Ssid);
1548 }
1549 }
1550 }
1551
1552 plist = get_next(plist);
1553
1554 }
1555
1556 _rtw_spinunlock_bh(&(pmlmepriv->scanned_queue.lock));
1557 #ifdef CONFIG_80211N_HT
1558 pmlmepriv->num_sta_no_ht = 0; /* reset to 0 after ap do scanning*/
1559 #endif
1560 }
1561
rtw_start_bss_hdl_after_chbw_decided(_adapter * adapter)1562 void rtw_start_bss_hdl_after_chbw_decided(_adapter *adapter)
1563 {
1564 WLAN_BSSID_EX *pnetwork = &(adapter->mlmepriv.cur_network.network);
1565 struct sta_info *sta = NULL;
1566
1567 /* update cur_wireless_mode */
1568 update_wireless_mode(adapter);
1569
1570 /* update RRSR and RTS_INIT_RATE register after set channel and bandwidth */
1571 UpdateBrateTbl(adapter, pnetwork->SupportedRates);
1572 rtw_hal_set_hwreg(adapter, HW_VAR_BASIC_RATE, pnetwork->SupportedRates);
1573
1574 /* update capability after cur_wireless_mode updated */
1575 update_capinfo(adapter, rtw_get_capability(pnetwork));
1576
1577 /* update AP's sta info */
1578 sta = rtw_get_stainfo(&adapter->stapriv, pnetwork->MacAddress);
1579 if (!sta) {
1580 RTW_INFO(FUNC_ADPT_FMT" !sta for macaddr="MAC_FMT"\n", FUNC_ADPT_ARG(adapter), MAC_ARG(pnetwork->MacAddress));
1581 rtw_warn_on(1);
1582 return;
1583 }
1584
1585 update_ap_info(adapter, sta);
1586 }
1587
_rtw_iface_undersurvey_chk(const char * func,_adapter * adapter)1588 static void _rtw_iface_undersurvey_chk(const char *func, _adapter *adapter)
1589 {
1590 int i;
1591 _adapter *iface;
1592 struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
1593 struct mlme_priv *pmlmepriv;
1594
1595 for (i = 0; i < dvobj->iface_nums; i++) {
1596 iface = dvobj->padapters[i];
1597 if ((iface) && rtw_is_adapter_up(iface)) {
1598 pmlmepriv = &iface->mlmepriv;
1599 if (check_fwstate(pmlmepriv, WIFI_UNDER_SURVEY))
1600 RTW_ERR("%s ("ADPT_FMT") under survey\n", func, ADPT_ARG(iface));
1601 }
1602 }
1603 }
1604
rtw_core_ap_swch_start(_adapter * padapter,struct createbss_parm * parm)1605 void rtw_core_ap_swch_start(_adapter *padapter, struct createbss_parm *parm)
1606 {
1607 struct dvobj_priv *pdvobj = padapter->dvobj;
1608 int i;
1609 u8 ht_option = 0;
1610 RTW_INFO("%s\n", __func__);
1611
1612 if (!IS_CH_WAITING(adapter_to_rfctl(padapter)))
1613 parm->do_rfk = _TRUE;
1614
1615 if (parm->ch_to_set != 0) {
1616 set_channel_bwmode(padapter, parm->ch_to_set, parm->offset_to_set, parm->bw_to_set, parm->do_rfk);
1617 rtw_phl_mr_dump_cur_chandef(adapter_to_dvobj(padapter)->phl, padapter->phl_role);
1618 }
1619
1620 #if defined(CONFIG_IOCTL_CFG80211) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
1621 for (i = 0; i < pdvobj->iface_nums; i++) {
1622 if (!(parm->ifbmp_ch_changed & BIT(i)) || !pdvobj->padapters[i])
1623 continue;
1624
1625 #ifdef CONFIG_80211N_HT
1626 ht_option = pdvobj->padapters[i]->mlmepriv.htpriv.ht_option;
1627 #endif
1628
1629 rtw_cfg80211_ch_switch_notify(pdvobj->padapters[i]
1630 , pdvobj->padapters[i]->mlmeextpriv.chandef.chan
1631 , pdvobj->padapters[i]->mlmeextpriv.chandef.bw
1632 , pdvobj->padapters[i]->mlmeextpriv.chandef.offset
1633 , ht_option, 0);
1634
1635 }
1636 #endif /* defined(CONFIG_IOCTL_CFG80211) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)) */
1637 rtw_rfctl_update_op_mode(adapter_to_rfctl(padapter), parm->ifbmp, 1);
1638 }
1639
rtw_core_ap_start(_adapter * padapter,struct createbss_parm * parm)1640 void rtw_core_ap_start(_adapter *padapter, struct createbss_parm *parm)
1641 {
1642 #define DUMP_ADAPTERS_STATUS 0
1643 struct dvobj_priv *pdvobj = padapter->dvobj;
1644 int i;
1645 RTW_INFO("%s\n", __func__);
1646 if (DUMP_ADAPTERS_STATUS) {
1647 RTW_INFO(FUNC_ADPT_FMT" done\n", FUNC_ADPT_ARG(padapter));
1648 dump_adapters_status(RTW_DBGDUMP , adapter_to_dvobj(padapter));
1649 }
1650
1651 for (i = 0; i < pdvobj->iface_nums; i++) {
1652 struct mlme_priv *mlme;
1653
1654 if (!(parm->ifbmp & BIT(i)) || !pdvobj->padapters[i])
1655 continue;
1656
1657 /* update beacon content only if bstart_bss is _TRUE */
1658 if (pdvobj->padapters[i]->mlmeextpriv.bstart_bss != _TRUE)
1659 continue;
1660
1661 mlme = &(pdvobj->padapters[i]->mlmepriv);
1662
1663 #ifdef CONFIG_80211N_HT
1664 if ((ATOMIC_READ(&mlme->olbc) == _TRUE) || (ATOMIC_READ(&mlme->olbc_ht) == _TRUE)) {
1665 /* AP is not starting a 40 MHz BSS in presence of an 802.11g BSS. */
1666 mlme->ht_op_mode &= (~HT_INFO_OPERATION_MODE_OP_MODE_MASK);
1667 mlme->ht_op_mode |= OP_MODE_MAY_BE_LEGACY_STAS;
1668 rtw_update_beacon(pdvobj->padapters[i], _HT_ADD_INFO_IE_, NULL, _FALSE, 0);
1669 }
1670 #endif
1671
1672 rtw_update_beacon(pdvobj->padapters[i], _TIM_IE_, NULL, _FALSE, 0);
1673 }
1674
1675 /* after chanctx_add & before send bcn */
1676 #ifndef CONFIG_AP_CMD_DISPR
1677 rtw_hw_start_bss_network(padapter);
1678 #endif
1679
1680 rtw_scan_abort(padapter, 0);
1681
1682 _rtw_iface_undersurvey_chk(__func__, padapter);
1683 /* send beacon */
1684 rtw_hal_set_hwreg(padapter, HW_VAR_RESUME_BCN, NULL);
1685 {
1686 #if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI) || defined(CONFIG_PCI_BCN_POLLING) || defined(CONFIG_HWSIM)
1687
1688 for (i = 0; i < pdvobj->iface_nums; i++) {
1689 if (!(parm->ifbmp & BIT(i)) || !pdvobj->padapters[i])
1690 continue;
1691
1692 if (send_beacon(pdvobj->padapters[i]) == _FAIL)
1693 RTW_INFO(ADPT_FMT" issue_beacon, fail!\n", ADPT_ARG(pdvobj->padapters[i]));
1694 }
1695 #endif
1696 }
1697 #ifdef CONFIG_RTW_TOKEN_BASED_XMIT
1698 if (MLME_IS_AP(padapter) && padapter->tbtx_capability == _TRUE) {
1699 _set_timer(&pmlmeext->tbtx_token_dispatch_timer, 1);
1700 RTW_INFO("Start token dispatch\n");
1701 }
1702 #endif
1703 }
1704
start_bss_network(_adapter * padapter,struct createbss_parm * parm)1705 void start_bss_network(_adapter *padapter, struct createbss_parm *parm)
1706 {
1707 #define DUMP_ADAPTERS_STATUS 0
1708 u8 mlme_act = MLME_ACTION_UNKNOWN;
1709 u16 bcn_interval;
1710 u32 acparm;
1711 struct registry_priv *pregpriv = &padapter->registrypriv;
1712 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1713 struct security_priv *psecuritypriv = &(padapter->securitypriv);
1714 WLAN_BSSID_EX *pnetwork = (WLAN_BSSID_EX *)&pmlmepriv->cur_network.network; /* used as input */
1715 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
1716 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
1717 WLAN_BSSID_EX *pnetwork_mlmeext = &(pmlmeinfo->network);
1718 struct dvobj_priv *pdvobj = padapter->dvobj;
1719 s16 req_ch = REQ_CH_NONE, req_bw = REQ_BW_NONE, req_offset = REQ_OFFSET_NONE;
1720 struct rtw_chan_def chdef_to_set = {0};
1721 u8 do_rfk = _FALSE;
1722 int i;
1723 u8 ifbmp_ch_changed = 0;
1724 #ifdef CONFIG_MCC_MODE
1725 struct rtw_phl_com_t *phl_com = GET_PHL_COM(pdvobj);
1726 u8 mcc_sup = phl_com->dev_cap.mcc_sup;
1727 #endif
1728 if (parm->req_ch != 0) {
1729 /* bypass other setting, go checking ch, bw, offset */
1730 mlme_act = MLME_OPCH_SWITCH;
1731 req_ch = parm->req_ch;
1732 req_bw = parm->req_bw;
1733 req_offset = parm->req_offset;
1734 goto chbw_decision;
1735 } else {
1736 /* request comes from upper layer */
1737 if (MLME_IS_AP(padapter))
1738 mlme_act = MLME_AP_STARTED;
1739 else if (MLME_IS_MESH(padapter))
1740 mlme_act = MLME_MESH_STARTED;
1741 else
1742 rtw_warn_on(1);
1743 req_ch = 0;
1744 _rtw_memcpy(pnetwork_mlmeext, pnetwork, pnetwork->Length);
1745 }
1746
1747 bcn_interval = (u16)pnetwork->Configuration.BeaconPeriod;
1748 pmlmeinfo->bcn_interval = bcn_interval;
1749
1750 /* check if there is wps ie, */
1751 /* if there is wpsie in beacon, the hostapd will update beacon twice when stating hostapd, */
1752 /* and at first time the security ie ( RSN/WPA IE) will not include in beacon. */
1753 if (NULL == rtw_get_wps_ie(pnetwork->IEs + _FIXED_IE_LENGTH_, pnetwork->IELength - _FIXED_IE_LENGTH_, NULL, NULL))
1754 pmlmeext->bstart_bss = _TRUE;
1755
1756 /* todo: update wmm, ht cap */
1757 /* pmlmeinfo->WMM_enable; */
1758 /* pmlmeinfo->HT_enable; */
1759 if (pmlmepriv->qospriv.qos_option)
1760 pmlmeinfo->WMM_enable = _TRUE;
1761 #ifdef CONFIG_80211N_HT
1762 if (pmlmepriv->htpriv.ht_option) {
1763 pmlmeinfo->WMM_enable = _TRUE;
1764 pmlmeinfo->HT_enable = _TRUE;
1765 /* pmlmeinfo->HT_info_enable = _TRUE; */
1766 /* pmlmeinfo->HT_caps_enable = _TRUE; */
1767
1768 update_hw_ht_param(padapter);
1769 } else
1770 pmlmeinfo->HT_enable = _FALSE;
1771 #endif /* #CONFIG_80211N_HT */
1772
1773 #ifdef CONFIG_80211AC_VHT
1774 if (pmlmepriv->vhtpriv.vht_option) {
1775 pmlmeinfo->VHT_enable = _TRUE;
1776 update_hw_vht_param(padapter);
1777 } else
1778 pmlmeinfo->VHT_enable = _FALSE;
1779 #endif /* CONFIG_80211AC_VHT */
1780
1781 #ifdef CONFIG_80211AX_HE
1782 if (pmlmepriv->hepriv.he_option) {
1783 pmlmeinfo->HE_enable = _TRUE;
1784 update_hw_he_param(padapter);
1785 } else
1786 pmlmeinfo->HE_enable = _FALSE;
1787 #endif /* CONFIG_80211AX_HE */
1788
1789 if (pmlmepriv->cur_network.join_res != _TRUE) { /* setting only at first time */
1790 /* WEP Key will be set before this function, do not clear CAM. */
1791 if ((psecuritypriv->dot11PrivacyAlgrthm != _WEP40_) && (psecuritypriv->dot11PrivacyAlgrthm != _WEP104_)
1792 && !MLME_IS_MESH(padapter) /* mesh group key is set before this function */
1793 )
1794 flush_all_cam_entry(padapter, PHL_CMD_DIRECTLY, 0); /* clear CAM */
1795 }
1796
1797 #ifdef CONFIG_RTW_MULTI_AP
1798 rtw_map_config_monitor(padapter, mlme_act);
1799 #endif
1800
1801 chbw_decision:
1802 ifbmp_ch_changed = rtw_ap_chbw_decision(padapter, parm->ifbmp, parm->excl_ifbmp
1803 , req_ch, req_bw, req_offset, &chdef_to_set);
1804
1805 for (i = 0; i < pdvobj->iface_nums; i++) {
1806 if (!(parm->ifbmp & BIT(i)) || !pdvobj->padapters[i])
1807 continue;
1808
1809 /* let pnetwork_mlme == pnetwork_mlmeext */
1810 _rtw_memcpy(&(pdvobj->padapters[i]->mlmepriv.cur_network.network)
1811 , &(pdvobj->padapters[i]->mlmeextpriv.mlmext_info.network)
1812 , pdvobj->padapters[i]->mlmeextpriv.mlmext_info.network.Length);
1813
1814 rtw_start_bss_hdl_after_chbw_decided(pdvobj->padapters[i]);
1815
1816 /* Set EDCA param reg after update cur_wireless_mode & update_capinfo */
1817 if (pregpriv->wifi_spec == 1)
1818 rtw_set_hw_wmm_param(pdvobj->padapters[i]);
1819 }
1820
1821 #if defined(CONFIG_DFS_MASTER)
1822 rtw_dfs_rd_en_decision(padapter, mlme_act, parm->excl_ifbmp);
1823 #endif
1824
1825 {
1826 u8 phl_uch = pmlmeext->chandef.chan;
1827 enum channel_width phl_ubw = pmlmeext->chandef.bw;
1828 enum chan_offset phl_uoffset = pmlmeext->chandef.offset;
1829 bool is_chctx_add = false;
1830 struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
1831
1832 is_chctx_add = rtw_phl_chanctx_add(dvobj->phl, padapter->phl_role,
1833 &phl_uch, &phl_ubw, &phl_uoffset);
1834
1835 rtw_hw_update_chan_def(padapter);
1836 rtw_mi_update_union_chan_inf(padapter, phl_uch, phl_uoffset, phl_ubw);
1837
1838 RTW_INFO("%s => chctx_add:%s\n", __func__, (is_chctx_add) ? "Y" : "N");
1839 RTW_INFO("Core - CH:%d, BW:%d OFF:%d\n", chdef_to_set.chan, chdef_to_set.bw, chdef_to_set.offset);
1840 RTW_INFO("PHL- CH:%d, BW:%d OFF:%d\n",phl_uch, phl_ubw, phl_uoffset);
1841 }
1842
1843
1844 parm->ifbmp_ch_changed = ifbmp_ch_changed;
1845 parm->ch_to_set = chdef_to_set.chan;
1846 parm->offset_to_set = chdef_to_set.offset;
1847 parm->bw_to_set = chdef_to_set.bw;
1848 parm->do_rfk = do_rfk;
1849
1850 }
1851
rtw_check_beacon_data(_adapter * padapter,u8 * pbuf,int len)1852 int rtw_check_beacon_data(_adapter *padapter, u8 *pbuf, int len)
1853 {
1854 int ret = _SUCCESS;
1855 u8 *p;
1856 u8 *pHT_caps_ie = NULL;
1857 u8 *pHT_info_ie = NULL;
1858 u16 cap, ht_cap = _FALSE;
1859 uint ie_len = 0;
1860 int group_cipher, pairwise_cipher, gmcs;
1861 u32 akm;
1862 u8 mfp_opt = MFP_NO;
1863 u8 channel, network_type;
1864 u8 OUI1[] = {0x00, 0x50, 0xf2, 0x01};
1865 u8 WMM_PARA_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01};
1866 u8 WIFI_ALLIANCE_OUI[] = {0x50, 0x6f, 0x9a};
1867 HT_CAP_AMPDU_DENSITY best_ampdu_density = 0;
1868 struct registry_priv *pregistrypriv = &padapter->registrypriv;
1869 struct security_priv *psecuritypriv = &padapter->securitypriv;
1870 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1871 WLAN_BSSID_EX *pbss_network = (WLAN_BSSID_EX *)&pmlmepriv->cur_network.network;
1872 u8 *ie = pbss_network->IEs;
1873 u8 vht_cap = _FALSE;
1874 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
1875 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
1876 struct rf_ctl_t *rfctl = adapter_to_rfctl(padapter);
1877 u8 rf_num = 0;
1878 int ret_rm;
1879 /* SSID */
1880 /* Supported rates */
1881 /* DS Params */
1882 /* WLAN_EID_COUNTRY */
1883 /* ERP Information element */
1884 /* Extended supported rates */
1885 /* WPA/WPA2 */
1886 /* Radio Resource Management */
1887 /* Wi-Fi Wireless Multimedia Extensions */
1888 /* ht_capab, ht_oper */
1889 /* WPS IE */
1890
1891 RTW_INFO("%s, len=%d\n", __FUNCTION__, len);
1892
1893 if (!MLME_IS_AP(padapter) && !MLME_IS_MESH(padapter))
1894 return _FAIL;
1895
1896
1897 if (len > MAX_IE_SZ)
1898 return _FAIL;
1899
1900 pbss_network->IELength = len;
1901
1902 _rtw_memset(ie, 0, MAX_IE_SZ);
1903
1904 _rtw_memcpy(ie, pbuf, pbss_network->IELength);
1905
1906
1907 if (pbss_network->InfrastructureMode != Ndis802_11APMode
1908 && pbss_network->InfrastructureMode != Ndis802_11_mesh
1909 ) {
1910 rtw_warn_on(1);
1911 return _FAIL;
1912 }
1913
1914
1915 rtw_ap_check_scan(padapter);
1916
1917
1918 pbss_network->PhyInfo.rssi= 0;
1919
1920 _rtw_memcpy(pbss_network->MacAddress, adapter_mac_addr(padapter), ETH_ALEN);
1921
1922 /* beacon interval */
1923 p = rtw_get_beacon_interval_from_ie(ie);/* ie + 8; */ /* 8: TimeStamp, 2: Beacon Interval 2:Capability */
1924 /* pbss_network->Configuration.BeaconPeriod = le16_to_cpu(*(unsigned short*)p); */
1925 pbss_network->Configuration.BeaconPeriod = RTW_GET_LE16(p);
1926
1927 /* capability */
1928 p = rtw_get_capability_from_ie(ie);
1929 cap = RTW_GET_LE16(p);
1930
1931 /* SSID */
1932 p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _SSID_IE_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_));
1933 if (p && ie_len > 0) {
1934 _rtw_memset(&pbss_network->Ssid, 0, sizeof(NDIS_802_11_SSID));
1935 _rtw_memcpy(pbss_network->Ssid.Ssid, (p + 2), ie_len);
1936 pbss_network->Ssid.SsidLength = ie_len;
1937 }
1938
1939 #ifdef CONFIG_RTW_MESH
1940 /* Mesh ID */
1941 if (MLME_IS_MESH(padapter)) {
1942 p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, WLAN_EID_MESH_ID, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_));
1943 if (p && ie_len > 0) {
1944 _rtw_memset(&pbss_network->mesh_id, 0, sizeof(NDIS_802_11_SSID));
1945 _rtw_memcpy(pbss_network->mesh_id.Ssid, (p + 2), ie_len);
1946 pbss_network->mesh_id.SsidLength = ie_len;
1947 }
1948 }
1949 #endif
1950
1951 /* Parsing extended capabilities IE */
1952 rtw_parse_ext_cap_ie(pmlmepriv->ext_capab_ie_data, &(pmlmepriv->ext_capab_ie_len), ie \
1953 , pbss_network->IELength, _BEACON_IE_OFFSET_);
1954
1955 /* chnnel */
1956 channel = 0;
1957 pbss_network->Configuration.Length = 0;
1958 p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _DSSET_IE_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_));
1959 if (p && ie_len > 0)
1960 channel = *(p + 2);
1961
1962 pbss_network->Configuration.DSConfig = channel;
1963
1964 /* support rate ie & ext support ie & IElen & SupportedRates */
1965 network_type = rtw_update_rate_bymode(pbss_network, pregistrypriv->wireless_mode);
1966
1967 /* parsing ERP_IE */
1968 p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _ERPINFO_IE_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_));
1969 if (p && ie_len > 0) {
1970 if(padapter->registrypriv.wireless_mode == WLAN_MD_11B) {
1971
1972 pbss_network->IELength = pbss_network->IELength - *(p+1) - 2;
1973 ret_rm = rtw_ies_remove_ie(ie , &len, _BEACON_IE_OFFSET_, _ERPINFO_IE_,NULL,0);
1974 RTW_DBG("%s, remove_ie of ERP_IE=%d\n", __FUNCTION__, ret_rm);
1975 } else
1976 ERP_IE_handler(padapter, (PNDIS_802_11_VARIABLE_IEs)p);
1977
1978 }
1979
1980 /* update privacy/security */
1981 if (cap & BIT(4))
1982 pbss_network->Privacy = 1;
1983 else
1984 pbss_network->Privacy = 0;
1985
1986 psecuritypriv->wpa_psk = 0;
1987
1988 /* wpa2 */
1989 akm = 0;
1990 gmcs = 0;
1991 group_cipher = 0;
1992 pairwise_cipher = 0;
1993 psecuritypriv->wpa2_group_cipher = _NO_PRIVACY_;
1994 psecuritypriv->wpa2_pairwise_cipher = _NO_PRIVACY_;
1995 psecuritypriv->akmp = 0;
1996 p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _RSN_IE_2_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_));
1997 if (p && ie_len > 0) {
1998 if (rtw_parse_wpa2_ie(p, ie_len + 2, &group_cipher, &pairwise_cipher, &gmcs, &akm, &mfp_opt, NULL) == _SUCCESS) {
1999 psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
2000 psecuritypriv->ndisauthtype = Ndis802_11AuthModeWPA2PSK;
2001 psecuritypriv->dot8021xalg = 1;/* psk, todo:802.1x */
2002 psecuritypriv->wpa_psk |= BIT(1);
2003
2004 psecuritypriv->wpa2_group_cipher = group_cipher;
2005 psecuritypriv->wpa2_pairwise_cipher = pairwise_cipher;
2006 psecuritypriv->akmp = akm;
2007
2008 #ifdef CONFIG_IOCTL_CFG80211
2009 /**
2010 * Kernel < v5.x, the auth_type set as
2011 * NL80211_AUTHTYPE_AUTOMATIC in
2012 * cfg80211_rtw_start_ap(). if the AKM SAE in the RSN
2013 * IE, we have to update the auth_type for SAE in
2014 * rtw_check_beacon_data()
2015 */
2016 if (CHECK_BIT(WLAN_AKM_TYPE_SAE, akm)) {
2017 RTW_INFO("%s: Auth type as SAE\n", __func__);
2018 psecuritypriv->auth_type = MLME_AUTHTYPE_SAE;
2019 psecuritypriv->auth_alg = WLAN_AUTH_SAE;
2020 }
2021 #endif /* CONFIG_IOCTL_CFG80211 */
2022 #if 0
2023 switch (group_cipher) {
2024 case WPA_CIPHER_NONE:
2025 psecuritypriv->wpa2_group_cipher = _NO_PRIVACY_;
2026 break;
2027 case WPA_CIPHER_WEP40:
2028 psecuritypriv->wpa2_group_cipher = _WEP40_;
2029 break;
2030 case WPA_CIPHER_TKIP:
2031 psecuritypriv->wpa2_group_cipher = _TKIP_;
2032 break;
2033 case WPA_CIPHER_CCMP:
2034 psecuritypriv->wpa2_group_cipher = _AES_;
2035 break;
2036 case WPA_CIPHER_WEP104:
2037 psecuritypriv->wpa2_group_cipher = _WEP104_;
2038 break;
2039 }
2040
2041 switch (pairwise_cipher) {
2042 case WPA_CIPHER_NONE:
2043 psecuritypriv->wpa2_pairwise_cipher = _NO_PRIVACY_;
2044 break;
2045 case WPA_CIPHER_WEP40:
2046 psecuritypriv->wpa2_pairwise_cipher = _WEP40_;
2047 break;
2048 case WPA_CIPHER_TKIP:
2049 psecuritypriv->wpa2_pairwise_cipher = _TKIP_;
2050 break;
2051 case WPA_CIPHER_CCMP:
2052 psecuritypriv->wpa2_pairwise_cipher = _AES_;
2053 break;
2054 case WPA_CIPHER_WEP104:
2055 psecuritypriv->wpa2_pairwise_cipher = _WEP104_;
2056 break;
2057 }
2058 #endif
2059 }
2060
2061 }
2062
2063 /* wpa */
2064 ie_len = 0;
2065 group_cipher = 0;
2066 pairwise_cipher = 0;
2067 psecuritypriv->wpa_group_cipher = _NO_PRIVACY_;
2068 psecuritypriv->wpa_pairwise_cipher = _NO_PRIVACY_;
2069 for (p = ie + _BEACON_IE_OFFSET_; ; p += (ie_len + 2)) {
2070 p = rtw_get_ie(p, _SSN_IE_1_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_ - (ie_len + 2)));
2071 if ((p) && (_rtw_memcmp(p + 2, OUI1, 4))) {
2072 if (rtw_parse_wpa_ie(p, ie_len + 2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) {
2073 psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
2074 psecuritypriv->ndisauthtype = Ndis802_11AuthModeWPAPSK;
2075 psecuritypriv->dot8021xalg = 1;/* psk, todo:802.1x */
2076
2077 psecuritypriv->wpa_psk |= BIT(0);
2078
2079 psecuritypriv->wpa_group_cipher = group_cipher;
2080 psecuritypriv->wpa_pairwise_cipher = pairwise_cipher;
2081
2082 #if 0
2083 switch (group_cipher) {
2084 case WPA_CIPHER_NONE:
2085 psecuritypriv->wpa_group_cipher = _NO_PRIVACY_;
2086 break;
2087 case WPA_CIPHER_WEP40:
2088 psecuritypriv->wpa_group_cipher = _WEP40_;
2089 break;
2090 case WPA_CIPHER_TKIP:
2091 psecuritypriv->wpa_group_cipher = _TKIP_;
2092 break;
2093 case WPA_CIPHER_CCMP:
2094 psecuritypriv->wpa_group_cipher = _AES_;
2095 break;
2096 case WPA_CIPHER_WEP104:
2097 psecuritypriv->wpa_group_cipher = _WEP104_;
2098 break;
2099 }
2100
2101 switch (pairwise_cipher) {
2102 case WPA_CIPHER_NONE:
2103 psecuritypriv->wpa_pairwise_cipher = _NO_PRIVACY_;
2104 break;
2105 case WPA_CIPHER_WEP40:
2106 psecuritypriv->wpa_pairwise_cipher = _WEP40_;
2107 break;
2108 case WPA_CIPHER_TKIP:
2109 psecuritypriv->wpa_pairwise_cipher = _TKIP_;
2110 break;
2111 case WPA_CIPHER_CCMP:
2112 psecuritypriv->wpa_pairwise_cipher = _AES_;
2113 break;
2114 case WPA_CIPHER_WEP104:
2115 psecuritypriv->wpa_pairwise_cipher = _WEP104_;
2116 break;
2117 }
2118 #endif
2119 }
2120
2121 break;
2122
2123 }
2124
2125 if ((p == NULL) || (ie_len == 0))
2126 break;
2127
2128 }
2129
2130 if (mfp_opt == MFP_INVALID) {
2131 RTW_INFO(FUNC_ADPT_FMT" invalid MFP setting\n", FUNC_ADPT_ARG(padapter));
2132 return _FAIL;
2133 }
2134 psecuritypriv->mfp_opt = mfp_opt;
2135
2136 /* RRM */
2137 rm_update_cap(pbuf, padapter, len, _BEACON_IE_OFFSET_);
2138
2139 /* wmm */
2140 ie_len = 0;
2141 pmlmepriv->qospriv.qos_option = 0;
2142 #ifdef CONFIG_RTW_MESH
2143 if (MLME_IS_MESH(padapter))
2144 pmlmepriv->qospriv.qos_option = 1;
2145 #endif
2146 if (pregistrypriv->wmm_enable) {
2147 for (p = ie + _BEACON_IE_OFFSET_; ; p += (ie_len + 2)) {
2148 p = rtw_get_ie(p, _VENDOR_SPECIFIC_IE_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_ - (ie_len + 2)));
2149 if ((p) && _rtw_memcmp(p + 2, WMM_PARA_IE, 6)) {
2150 pmlmepriv->qospriv.qos_option = 1;
2151
2152 *(p + 8) |= BIT(7); /* QoS Info, support U-APSD */
2153
2154 /* disable all ACM bits since the WMM admission control is not supported */
2155 *(p + 10) &= ~BIT(4); /* BE */
2156 *(p + 14) &= ~BIT(4); /* BK */
2157 *(p + 18) &= ~BIT(4); /* VI */
2158 *(p + 22) &= ~BIT(4); /* VO */
2159
2160 WMM_param_handler(padapter, (PNDIS_802_11_VARIABLE_IEs)p);
2161
2162 break;
2163 }
2164
2165 if ((p == NULL) || (ie_len == 0))
2166 break;
2167 }
2168 }
2169 #ifdef CONFIG_80211N_HT
2170 if(padapter->registrypriv.ht_enable &&
2171 is_supported_ht(padapter->registrypriv.wireless_mode)) {
2172 /* parsing HT_CAP_IE */
2173 p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_CAPABILITY_IE_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_));
2174 if (p && ie_len > 0) {
2175 HT_CAP_AMPDU_FACTOR max_rx_ampdu_factor = MAX_AMPDU_FACTOR_64K;
2176 struct rtw_ieee80211_ht_cap *pht_cap = (struct rtw_ieee80211_ht_cap *)(p + 2);
2177
2178 if (0) {
2179 RTW_INFO(FUNC_ADPT_FMT" HT_CAP_IE from upper layer:\n", FUNC_ADPT_ARG(padapter));
2180 dump_ht_cap_ie_content(RTW_DBGDUMP, p + 2, ie_len);
2181 }
2182
2183 pHT_caps_ie = p;
2184
2185 ht_cap = _TRUE;
2186 network_type |= WLAN_MD_11N;
2187
2188 rtw_ht_use_default_setting(padapter);
2189
2190 /* Update HT Capabilities Info field */
2191 if (pmlmepriv->htpriv.sgi_20m == _FALSE)
2192 pht_cap->cap_info &= ~(IEEE80211_HT_CAP_SGI_20);
2193
2194 if (pmlmepriv->htpriv.sgi_40m == _FALSE)
2195 pht_cap->cap_info &= ~(IEEE80211_HT_CAP_SGI_40);
2196
2197 if (!TEST_FLAG(pmlmepriv->htpriv.ldpc_cap, LDPC_HT_ENABLE_RX))
2198 pht_cap->cap_info &= ~(IEEE80211_HT_CAP_LDPC_CODING);
2199
2200 if (!TEST_FLAG(pmlmepriv->htpriv.stbc_cap, STBC_HT_ENABLE_TX))
2201 pht_cap->cap_info &= ~(IEEE80211_HT_CAP_TX_STBC);
2202
2203 if (!TEST_FLAG(pmlmepriv->htpriv.stbc_cap, STBC_HT_ENABLE_RX))
2204 pht_cap->cap_info &= ~(IEEE80211_HT_CAP_RX_STBC_3R);
2205
2206 /* Update A-MPDU Parameters field */
2207 pht_cap->ampdu_params_info &= ~(IEEE80211_HT_CAP_AMPDU_FACTOR | IEEE80211_HT_CAP_AMPDU_DENSITY);
2208
2209 if ((psecuritypriv->wpa_pairwise_cipher & WPA_CIPHER_CCMP) ||
2210 (psecuritypriv->wpa2_pairwise_cipher & WPA_CIPHER_CCMP)) {
2211 rtw_hal_get_def_var(padapter, HW_VAR_BEST_AMPDU_DENSITY, &best_ampdu_density);
2212 pht_cap->ampdu_params_info |= (IEEE80211_HT_CAP_AMPDU_DENSITY & (best_ampdu_density << 2));
2213 } else
2214 pht_cap->ampdu_params_info |= (IEEE80211_HT_CAP_AMPDU_DENSITY & 0x00);
2215
2216 rtw_hal_get_def_var(padapter, HW_VAR_MAX_RX_AMPDU_FACTOR, &max_rx_ampdu_factor);
2217 pht_cap->ampdu_params_info |= (IEEE80211_HT_CAP_AMPDU_FACTOR & max_rx_ampdu_factor); /* set Max Rx AMPDU size to 64K */
2218
2219 _rtw_memcpy(&(pmlmeinfo->HT_caps), pht_cap, sizeof(struct HT_caps_element));
2220
2221 /* Update Supported MCS Set field */
2222 {
2223 u8 rx_nss = 0;
2224 int i;
2225
2226 rx_nss = get_phy_rx_nss(padapter);
2227
2228 /* RX MCS Bitmask */
2229 switch (rx_nss) {
2230 case 1:
2231 set_mcs_rate_by_mask(HT_CAP_ELE_RX_MCS_MAP(pht_cap), MCS_RATE_1R);
2232 break;
2233 case 2:
2234 set_mcs_rate_by_mask(HT_CAP_ELE_RX_MCS_MAP(pht_cap), MCS_RATE_2R);
2235 break;
2236 case 3:
2237 set_mcs_rate_by_mask(HT_CAP_ELE_RX_MCS_MAP(pht_cap), MCS_RATE_3R);
2238 break;
2239 case 4:
2240 set_mcs_rate_by_mask(HT_CAP_ELE_RX_MCS_MAP(pht_cap), MCS_RATE_4R);
2241 break;
2242 default:
2243 RTW_WARN("rf_type:%d or rx_nss:%u is not expected\n",
2244 GET_HAL_RFPATH(adapter_to_dvobj(padapter)), rx_nss);
2245 }
2246 for (i = 0; i < 10; i++)
2247 *(HT_CAP_ELE_RX_MCS_MAP(pht_cap) + i) &= padapter->mlmeextpriv.default_supported_mcs_set[i];
2248 }
2249
2250 #ifdef CONFIG_BEAMFORMING
2251 /* Use registry value to enable HT Beamforming. */
2252 /* ToDo: use configure file to set these capability. */
2253 pht_cap->tx_BF_cap_info = 0;
2254
2255 /* HT Beamformer */
2256 if (TEST_FLAG(pmlmepriv->htpriv.beamform_cap, BEAMFORMING_HT_BEAMFORMER_ENABLE)) {
2257 /* Transmit NDP Capable */
2258 SET_HT_CAP_TXBF_TRANSMIT_NDP_CAP(pht_cap, 1);
2259 /* Explicit Compressed Steering Capable */
2260 SET_HT_CAP_TXBF_EXPLICIT_COMP_STEERING_CAP(pht_cap, 1);
2261 /* Compressed Steering Number Antennas */
2262 SET_HT_CAP_TXBF_COMP_STEERING_NUM_ANTENNAS(pht_cap, 1);
2263 rtw_hal_get_def_var(padapter, HAL_DEF_BEAMFORMER_CAP, (u8 *)&rf_num);
2264 if (rf_num > 3)
2265 rf_num = 3;
2266 SET_HT_CAP_TXBF_CHNL_ESTIMATION_NUM_ANTENNAS(pht_cap, rf_num);
2267 }
2268
2269 /* HT Beamformee */
2270 if (TEST_FLAG(pmlmepriv->htpriv.beamform_cap, BEAMFORMING_HT_BEAMFORMEE_ENABLE)) {
2271 /* Receive NDP Capable */
2272 SET_HT_CAP_TXBF_RECEIVE_NDP_CAP(pht_cap, 1);
2273 /* Explicit Compressed Beamforming Feedback Capable */
2274 SET_HT_CAP_TXBF_EXPLICIT_COMP_FEEDBACK_CAP(pht_cap, 2);
2275 rtw_hal_get_def_var(padapter, HAL_DEF_BEAMFORMEE_CAP, (u8 *)&rf_num);
2276 if (rf_num > 3)
2277 rf_num = 3;
2278 SET_HT_CAP_TXBF_COMP_STEERING_NUM_ANTENNAS(pht_cap, rf_num);
2279 }
2280 #endif /* CONFIG_BEAMFORMING */
2281
2282 _rtw_memcpy(&pmlmepriv->htpriv.ht_cap, p + 2, ie_len);
2283
2284 if (0) {
2285 RTW_INFO(FUNC_ADPT_FMT" HT_CAP_IE driver masked:\n", FUNC_ADPT_ARG(padapter));
2286 dump_ht_cap_ie_content(RTW_DBGDUMP, p + 2, ie_len);
2287 }
2288 }
2289
2290 /* parsing HT_INFO_IE */
2291 p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_ADD_INFO_IE_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_));
2292 if (p && ie_len > 0) {
2293 pHT_info_ie = p;
2294 if (channel == 0)
2295 pbss_network->Configuration.DSConfig = GET_HT_OP_ELE_PRI_CHL(pHT_info_ie + 2);
2296 else if (channel != GET_HT_OP_ELE_PRI_CHL(pHT_info_ie + 2)) {
2297 RTW_INFO(FUNC_ADPT_FMT" ch inconsistent, DSSS:%u, HT primary:%u\n"
2298 , FUNC_ADPT_ARG(padapter), channel, GET_HT_OP_ELE_PRI_CHL(pHT_info_ie + 2));
2299 }
2300 }
2301 }
2302 #endif /* CONFIG_80211N_HT */
2303 pmlmepriv->cur_network.network_type = network_type;
2304
2305 #ifdef CONFIG_80211N_HT
2306 pmlmepriv->htpriv.ht_option = _FALSE;
2307
2308 if ((psecuritypriv->wpa2_pairwise_cipher & WPA_CIPHER_TKIP) ||
2309 (psecuritypriv->wpa_pairwise_cipher & WPA_CIPHER_TKIP)) {
2310 /* todo: */
2311 /* ht_cap = _FALSE; */
2312 }
2313
2314 /* ht_cap */
2315 if (padapter->registrypriv.ht_enable &&
2316 is_supported_ht(padapter->registrypriv.wireless_mode) && ht_cap == _TRUE) {
2317
2318 pmlmepriv->htpriv.ht_option = _TRUE;
2319 pmlmepriv->qospriv.qos_option = 1;
2320
2321 pmlmepriv->htpriv.ampdu_enable = pregistrypriv->ampdu_enable ? _TRUE : _FALSE;
2322
2323 HT_caps_handler(padapter, (PNDIS_802_11_VARIABLE_IEs)pHT_caps_ie);
2324
2325 HT_info_handler(padapter, (PNDIS_802_11_VARIABLE_IEs)pHT_info_ie);
2326 }
2327 #endif
2328
2329 pmlmepriv->upper_layer_setting = _FALSE;
2330
2331 #ifdef CONFIG_80211AC_VHT
2332 pmlmepriv->vhtpriv.vht_option = _FALSE;
2333
2334 if (pmlmepriv->htpriv.ht_option == _TRUE
2335 && pbss_network->Configuration.DSConfig > 14
2336 && REGSTY_IS_11AC_ENABLE(pregistrypriv)
2337 && is_supported_vht(pregistrypriv->wireless_mode)
2338 && RFCTL_REG_EN_11AC(rfctl)
2339 ) {
2340 /* Parsing VHT_CAP_IE */
2341 p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, WLAN_EID_VHT_CAPABILITY,
2342 &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_));
2343 if (p && ie_len > 0)
2344 vht_cap = _TRUE;
2345 else
2346 RTW_INFO(FUNC_ADPT_FMT" No vht_capability_ie from hostapd/wpa_supplicant\n", FUNC_ADPT_ARG(padapter));
2347
2348 /* Update VHT related IEs */
2349 if (vht_cap == _TRUE) {
2350 RTW_INFO(FUNC_ADPT_FMT" VHT IEs is configured by hostapd/wpa_supplicant\n", FUNC_ADPT_ARG(padapter));
2351 pmlmepriv->upper_layer_setting = _TRUE;
2352 pmlmepriv->vhtpriv.vht_option = _TRUE;
2353
2354 rtw_check_for_vht20(padapter, ie + _BEACON_IE_OFFSET_,
2355 pbss_network->IELength - _BEACON_IE_OFFSET_);
2356 rtw_check_vht_ies(padapter, pbss_network);
2357 } else if (REGSTY_IS_11AC_AUTO(pregistrypriv)) {
2358 rtw_vht_ies_detach(padapter, pbss_network);
2359 rtw_vht_ies_attach(padapter, pbss_network);
2360 }
2361 }
2362
2363 if (pmlmepriv->vhtpriv.vht_option == _FALSE)
2364 rtw_vht_ies_detach(padapter, pbss_network);
2365 #endif /* CONFIG_80211AC_VHT */
2366
2367 #ifdef CONFIG_80211AX_HE
2368 pmlmepriv->hepriv.he_option = _FALSE;
2369
2370 /* An HE STA is also a VHT STA if operating in the 5 GHz band */
2371 /* An HE STA is also a HT STA in the 2GHz band */
2372 if (REGSTY_IS_11AX_ENABLE(pregistrypriv)
2373 && is_supported_he(pregistrypriv->wireless_mode)
2374 && RFCTL_REG_EN_11AX(rfctl)
2375 && ((channel > 14 && pmlmepriv->vhtpriv.vht_option == _TRUE) ||
2376 (channel <= 14 && pmlmepriv->htpriv.ht_option == _TRUE))
2377 ) {
2378 u8 he_cap = _FALSE;
2379 u8 he_cap_eid_ext = WLAN_EID_EXTENSION_HE_CAPABILITY;
2380
2381 p = rtw_get_ie_ex(ie + _BEACON_IE_OFFSET_, pbss_network->IELength - _BEACON_IE_OFFSET_,
2382 WLAN_EID_EXTENSION, &he_cap_eid_ext, 1, NULL, &ie_len);
2383 if (p && ie_len > 0)
2384 he_cap = _TRUE;
2385
2386 /* If He capability is in beacon IE, enable he_option */
2387 pmlmepriv->hepriv.he_option = he_cap;
2388
2389 /* Update HE related IEs */
2390 if (he_cap == _TRUE) {
2391 RTW_INFO(FUNC_ADPT_FMT" HE IEs is configured by hostapd/wpa_supplicant\n", FUNC_ADPT_ARG(padapter));
2392 pmlmepriv->upper_layer_setting = _TRUE;
2393
2394 rtw_update_he_ies(padapter, pbss_network);
2395 } else if (REGSTY_IS_11AX_AUTO(pregistrypriv)) {
2396 rtw_he_ies_detach(padapter, pbss_network);
2397 rtw_he_ies_attach(padapter, pbss_network);
2398 }
2399 }
2400 if (pmlmepriv->hepriv.he_option == _FALSE)
2401 rtw_he_ies_detach(padapter, pbss_network);
2402 #endif
2403
2404 #ifdef CONFIG_80211N_HT
2405 if(padapter->registrypriv.ht_enable &&
2406 is_supported_ht(padapter->registrypriv.wireless_mode) &&
2407 pbss_network->Configuration.DSConfig <= 14 /*&& padapter->registrypriv.wifi_spec == 1*/) {
2408
2409 #ifdef CONFIG_RTW_WNM
2410 rtw_wnm_add_btm_ext_cap(pmlmepriv->ext_capab_ie_data,
2411 &(pmlmepriv->ext_capab_ie_len));
2412 #endif
2413 #ifdef CONFIG_RTW_MBO
2414 rtw_mbo_add_internw_ext_cap(pmlmepriv->ext_capab_ie_data,
2415 &(pmlmepriv->ext_capab_ie_len));
2416 #endif
2417 rtw_add_ext_cap_info(pmlmepriv->ext_capab_ie_data, &(pmlmepriv->ext_capab_ie_len), BSS_COEXT);
2418 rtw_update_ext_cap_ie(pmlmepriv->ext_capab_ie_data, pmlmepriv->ext_capab_ie_len, pbss_network->IEs, \
2419 &(pbss_network->IELength), _BEACON_IE_OFFSET_);
2420 }
2421 #endif /* CONFIG_80211N_HT */
2422
2423 #ifdef CONFIG_RTW_80211K
2424 padapter->rmpriv.enable = _FALSE;
2425 p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, EID_RMEnabledCapability, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_));
2426 if (p && ie_len) {
2427 RTW_INFO("[%s]Get EID_RMEnabledCapability, len = %d\n", __func__, ie_len);
2428 padapter->rmpriv.enable = _TRUE;
2429 _rtw_memcpy(padapter->rmpriv.rm_en_cap_def, p + 2, ie_len);
2430 }
2431 #endif /* CONFIG_RTW_80211K */
2432
2433 #ifdef CONFIG_RTW_MBO
2434 ie_len = 0;
2435 pmlmepriv->mbopriv.enable = _FALSE;
2436 for (p = ie + _BEACON_IE_OFFSET_; ; p += (ie_len + 2)) {
2437 p = rtw_get_ie(p, _SSN_IE_1_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_ - (ie_len + 2)));
2438 if ((p) && (_rtw_memcmp(p + 2, WIFI_ALLIANCE_OUI, 3)) && (*(p+5) == MBO_OUI_TYPE)) {
2439 /* find MBO-OCE information element */
2440 pmlmepriv->mbopriv.enable = _TRUE;
2441 rtw_mbo_ie_handler(padapter, &pmlmepriv->mbopriv, p + 6, ie_len - 4);
2442 break;
2443 }
2444 if ((p == NULL) || (ie_len == 0))
2445 break;
2446 }
2447 #endif /* CONFIG_RTW_MBO */
2448
2449 pbss_network->Length = get_WLAN_BSSID_EX_sz((WLAN_BSSID_EX *)pbss_network);
2450
2451 rtw_ies_get_chbw(pbss_network->IEs + _BEACON_IE_OFFSET_, pbss_network->IELength - _BEACON_IE_OFFSET_
2452 , &pmlmepriv->ori_chandef.chan, (u8 *)&pmlmepriv->ori_chandef.bw, (u8 *)&pmlmepriv->ori_chandef.offset, 1, 1);
2453 rtw_warn_on(pmlmepriv->ori_chandef.chan == 0);
2454
2455 ret = rtw_startbss_cmd(padapter, RTW_CMDF_WAIT_ACK);
2456 {
2457 int sk_band = RTW_GET_SCAN_BAND_SKIP(padapter);
2458
2459 if (sk_band)
2460 RTW_CLR_SCAN_BAND_SKIP(padapter, sk_band);
2461 }
2462
2463 if (ret) {
2464 rtw_indicate_connect(padapter);
2465 pmlmepriv->cur_network.join_res = _TRUE;/* for check if already set beacon */
2466 }
2467
2468 return ret;
2469
2470 }
2471
2472 #if CONFIG_RTW_MACADDR_ACL
rtw_macaddr_acl_init(_adapter * adapter,u8 period)2473 void rtw_macaddr_acl_init(_adapter *adapter, u8 period)
2474 {
2475 struct sta_priv *stapriv = &adapter->stapriv;
2476 struct wlan_acl_pool *acl;
2477 _queue *acl_node_q;
2478 int i;
2479
2480 if (period >= RTW_ACL_PERIOD_NUM) {
2481 rtw_warn_on(1);
2482 return;
2483 }
2484
2485 acl = &stapriv->acl_list[period];
2486 acl_node_q = &acl->acl_node_q;
2487
2488 _rtw_spinlock_init(&(acl_node_q->lock));
2489
2490 _rtw_spinlock_bh(&(acl_node_q->lock));
2491 _rtw_init_listhead(&(acl_node_q->queue));
2492 acl->num = 0;
2493 acl->mode = RTW_ACL_MODE_DISABLED;
2494 for (i = 0; i < NUM_ACL; i++) {
2495 _rtw_init_listhead(&acl->aclnode[i].list);
2496 acl->aclnode[i].valid = _FALSE;
2497 }
2498 _rtw_spinunlock_bh(&(acl_node_q->lock));
2499 }
2500
_rtw_macaddr_acl_deinit(_adapter * adapter,u8 period,bool clear_only)2501 static void _rtw_macaddr_acl_deinit(_adapter *adapter, u8 period, bool clear_only)
2502 {
2503 struct sta_priv *stapriv = &adapter->stapriv;
2504 struct wlan_acl_pool *acl;
2505 _queue *acl_node_q;
2506 _list *head, *list;
2507 struct rtw_wlan_acl_node *acl_node;
2508
2509 if (period >= RTW_ACL_PERIOD_NUM) {
2510 rtw_warn_on(1);
2511 return;
2512 }
2513
2514 acl = &stapriv->acl_list[period];
2515 acl_node_q = &acl->acl_node_q;
2516
2517 _rtw_spinlock_bh(&(acl_node_q->lock));
2518 head = get_list_head(acl_node_q);
2519 list = get_next(head);
2520 while (rtw_end_of_queue_search(head, list) == _FALSE) {
2521 acl_node = LIST_CONTAINOR(list, struct rtw_wlan_acl_node, list);
2522 list = get_next(list);
2523
2524 if (acl_node->valid == _TRUE) {
2525 acl_node->valid = _FALSE;
2526 rtw_list_delete(&acl_node->list);
2527 acl->num--;
2528 }
2529 }
2530 _rtw_spinunlock_bh(&(acl_node_q->lock));
2531
2532 if (!clear_only)
2533 _rtw_spinlock_free(&(acl_node_q->lock));
2534
2535 rtw_warn_on(acl->num);
2536 acl->mode = RTW_ACL_MODE_DISABLED;
2537 }
2538
rtw_macaddr_acl_deinit(_adapter * adapter,u8 period)2539 void rtw_macaddr_acl_deinit(_adapter *adapter, u8 period)
2540 {
2541 _rtw_macaddr_acl_deinit(adapter, period, 0);
2542 }
2543
rtw_macaddr_acl_clear(_adapter * adapter,u8 period)2544 void rtw_macaddr_acl_clear(_adapter *adapter, u8 period)
2545 {
2546 _rtw_macaddr_acl_deinit(adapter, period, 1);
2547 }
2548
rtw_set_macaddr_acl(_adapter * adapter,u8 period,int mode)2549 void rtw_set_macaddr_acl(_adapter *adapter, u8 period, int mode)
2550 {
2551 struct sta_priv *stapriv = &adapter->stapriv;
2552 struct wlan_acl_pool *acl;
2553
2554 if (period >= RTW_ACL_PERIOD_NUM) {
2555 rtw_warn_on(1);
2556 return;
2557 }
2558
2559 acl = &stapriv->acl_list[period];
2560
2561 RTW_INFO(FUNC_ADPT_FMT" p=%u, mode=%d\n"
2562 , FUNC_ADPT_ARG(adapter), period, mode);
2563
2564 acl->mode = mode;
2565 }
2566
rtw_acl_add_sta(_adapter * adapter,u8 period,const u8 * addr)2567 int rtw_acl_add_sta(_adapter *adapter, u8 period, const u8 *addr)
2568 {
2569 _list *list, *head;
2570 u8 existed = 0;
2571 int i = -1, ret = 0;
2572 struct rtw_wlan_acl_node *acl_node;
2573 struct sta_priv *stapriv = &adapter->stapriv;
2574 struct wlan_acl_pool *acl;
2575 _queue *acl_node_q;
2576
2577 if (period >= RTW_ACL_PERIOD_NUM) {
2578 rtw_warn_on(1);
2579 ret = -1;
2580 goto exit;
2581 }
2582
2583 acl = &stapriv->acl_list[period];
2584 acl_node_q = &acl->acl_node_q;
2585
2586 _rtw_spinlock_bh(&(acl_node_q->lock));
2587
2588 head = get_list_head(acl_node_q);
2589 list = get_next(head);
2590
2591 /* search for existed entry */
2592 while (rtw_end_of_queue_search(head, list) == _FALSE) {
2593 acl_node = LIST_CONTAINOR(list, struct rtw_wlan_acl_node, list);
2594 list = get_next(list);
2595
2596 if (_rtw_memcmp(acl_node->addr, addr, ETH_ALEN)) {
2597 if (acl_node->valid == _TRUE) {
2598 existed = 1;
2599 break;
2600 }
2601 }
2602 }
2603 if (existed)
2604 goto release_lock;
2605
2606 if (acl->num >= NUM_ACL)
2607 goto release_lock;
2608
2609 /* find empty one and use */
2610 for (i = 0; i < NUM_ACL; i++) {
2611
2612 acl_node = &acl->aclnode[i];
2613 if (acl_node->valid == _FALSE) {
2614
2615 _rtw_init_listhead(&acl_node->list);
2616 _rtw_memcpy(acl_node->addr, addr, ETH_ALEN);
2617 acl_node->valid = _TRUE;
2618
2619 rtw_list_insert_tail(&acl_node->list, get_list_head(acl_node_q));
2620 acl->num++;
2621 break;
2622 }
2623 }
2624
2625 release_lock:
2626 _rtw_spinunlock_bh(&(acl_node_q->lock));
2627
2628 if (!existed && (i < 0 || i >= NUM_ACL))
2629 ret = -1;
2630
2631 RTW_INFO(FUNC_ADPT_FMT" p=%u "MAC_FMT" %s (acl_num=%d)\n"
2632 , FUNC_ADPT_ARG(adapter), period, MAC_ARG(addr)
2633 , (existed ? "existed" : ((i < 0 || i >= NUM_ACL) ? "no room" : "added"))
2634 , acl->num);
2635 exit:
2636 return ret;
2637 }
2638
rtw_acl_remove_sta(_adapter * adapter,u8 period,const u8 * addr)2639 int rtw_acl_remove_sta(_adapter *adapter, u8 period, const u8 *addr)
2640 {
2641 _list *list, *head;
2642 int ret = 0;
2643 struct rtw_wlan_acl_node *acl_node;
2644 struct sta_priv *stapriv = &adapter->stapriv;
2645 struct wlan_acl_pool *acl;
2646 _queue *acl_node_q;
2647 u8 is_baddr = is_broadcast_mac_addr(addr);
2648 u8 match = 0;
2649
2650 if (period >= RTW_ACL_PERIOD_NUM) {
2651 rtw_warn_on(1);
2652 goto exit;
2653 }
2654
2655 acl = &stapriv->acl_list[period];
2656 acl_node_q = &acl->acl_node_q;
2657
2658 _rtw_spinlock_bh(&(acl_node_q->lock));
2659
2660 head = get_list_head(acl_node_q);
2661 list = get_next(head);
2662
2663 while (rtw_end_of_queue_search(head, list) == _FALSE) {
2664 acl_node = LIST_CONTAINOR(list, struct rtw_wlan_acl_node, list);
2665 list = get_next(list);
2666
2667 if (is_baddr || _rtw_memcmp(acl_node->addr, addr, ETH_ALEN)) {
2668 if (acl_node->valid == _TRUE) {
2669 acl_node->valid = _FALSE;
2670 rtw_list_delete(&acl_node->list);
2671 acl->num--;
2672 match = 1;
2673 }
2674 }
2675 }
2676
2677 _rtw_spinunlock_bh(&(acl_node_q->lock));
2678
2679 RTW_INFO(FUNC_ADPT_FMT" p=%u "MAC_FMT" %s (acl_num=%d)\n"
2680 , FUNC_ADPT_ARG(adapter), period, MAC_ARG(addr)
2681 , is_baddr ? "clear all" : (match ? "match" : "no found")
2682 , acl->num);
2683
2684 exit:
2685 return ret;
2686 }
2687 #endif /* CONFIG_RTW_MACADDR_ACL */
2688 #ifdef CONFIG_CMD_DISP
rtw_ap_set_sta_key(_adapter * adapter,const u8 * addr,u8 alg,const u8 * key,u8 keyid,u8 gk)2689 u8 rtw_ap_set_sta_key(_adapter *adapter, const u8 *addr, u8 alg, const u8 *key, u8 keyid, u8 gk)
2690 {
2691 struct set_stakey_parm param;
2692 u8 res = _SUCCESS;
2693
2694 _rtw_memcpy(param.addr, addr, ETH_ALEN);
2695 param.algorithm = alg;
2696 param.keyid = keyid;
2697 if (!!(alg & _SEC_TYPE_256_))
2698 _rtw_memcpy(param.key, key, 32);
2699 else
2700 _rtw_memcpy(param.key, key, 16);
2701 param.gk = gk;
2702
2703 set_stakey_hdl(adapter, ¶m, PHL_CMD_NO_WAIT, 0);
2704 exit:
2705 return res;
2706 }
2707
rtw_ap_set_pairwise_key(_adapter * padapter,struct sta_info * psta)2708 u8 rtw_ap_set_pairwise_key(_adapter *padapter, struct sta_info *psta)
2709 {
2710 return rtw_ap_set_sta_key(padapter
2711 , psta->phl_sta->mac_addr
2712 , psta->dot118021XPrivacy
2713 , psta->dot118021x_UncstKey.skey
2714 , 0
2715 , 0
2716 );
2717 }
2718
rtw_ap_set_key(_adapter * padapter,u8 * key,u8 alg,int keyid,u8 set_tx)2719 static int rtw_ap_set_key(_adapter *padapter, u8 *key, u8 alg, int keyid, u8 set_tx)
2720 {
2721 u8 keylen;
2722 struct setkey_parm setkeyparm;
2723 int res = _SUCCESS;
2724
2725 /* RTW_INFO("%s\n", __FUNCTION__); */
2726
2727 _rtw_memset(&setkeyparm, 0, sizeof(struct setkey_parm));
2728
2729 setkeyparm.keyid = (u8)keyid;
2730 if (is_wep_enc(alg))
2731 padapter->securitypriv.key_mask |= BIT(setkeyparm.keyid);
2732
2733 setkeyparm.algorithm = alg;
2734
2735 setkeyparm.set_tx = set_tx;
2736
2737 switch (alg) {
2738 case _WEP40_:
2739 keylen = 5;
2740 break;
2741 case _WEP104_:
2742 keylen = 13;
2743 break;
2744 case _GCMP_256_:
2745 case _CCMP_256_:
2746 keylen = 32;
2747 break;
2748 case _TKIP_:
2749 case _TKIP_WTMIC_:
2750 case _AES_:
2751 case _GCMP_:
2752 #ifdef CONFIG_IEEE80211W
2753 case _BIP_CMAC_128_:
2754 #endif
2755 default:
2756 keylen = 16;
2757 }
2758
2759 _rtw_memcpy(&(setkeyparm.key[0]), key, keylen);
2760 setkey_hdl(padapter, &setkeyparm, PHL_CMD_NO_WAIT, 0);
2761
2762 exit:
2763 return res;
2764 }
2765 #else /* CONFIG_FSM */
rtw_ap_set_sta_key(_adapter * adapter,const u8 * addr,u8 alg,const u8 * key,u8 keyid,u8 gk)2766 u8 rtw_ap_set_sta_key(_adapter *adapter, const u8 *addr, u8 alg, const u8 *key, u8 keyid, u8 gk)
2767 {
2768 struct cmd_priv *cmdpriv = &adapter_to_dvobj(adapter)->cmdpriv;
2769 struct cmd_obj *cmd;
2770 struct set_stakey_parm *param;
2771 u8 res = _SUCCESS;
2772
2773 cmd = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
2774 if (cmd == NULL) {
2775 res = _FAIL;
2776 goto exit;
2777 }
2778 cmd->padapter = adapter;
2779
2780 param = (struct set_stakey_parm *)rtw_zmalloc(sizeof(struct set_stakey_parm));
2781 if (param == NULL) {
2782 rtw_mfree((u8 *) cmd, sizeof(struct cmd_obj));
2783 res = _FAIL;
2784 goto exit;
2785 }
2786
2787 init_h2fwcmd_w_parm_no_rsp(cmd, param, CMD_SET_STAKEY);
2788
2789 _rtw_memcpy(param->addr, addr, ETH_ALEN);
2790 param->algorithm = alg;
2791 param->keyid = keyid;
2792 if (!!(alg & _SEC_TYPE_256_))
2793 _rtw_memcpy(param->key, key, 32);
2794 else
2795 _rtw_memcpy(param->key, key, 16);
2796 param->gk = gk;
2797
2798 res = rtw_enqueue_cmd(cmdpriv, cmd);
2799
2800 exit:
2801 return res;
2802 }
2803
rtw_ap_set_pairwise_key(_adapter * padapter,struct sta_info * psta)2804 u8 rtw_ap_set_pairwise_key(_adapter *padapter, struct sta_info *psta)
2805 {
2806 return rtw_ap_set_sta_key(padapter
2807 , psta->phl_sta->mac_addr
2808 , psta->dot118021XPrivacy
2809 , psta->dot118021x_UncstKey.skey
2810 , 0
2811 , 0
2812 );
2813 }
2814
rtw_ap_set_key(_adapter * padapter,u8 * key,u8 alg,int keyid,u8 set_tx)2815 static int rtw_ap_set_key(_adapter *padapter, u8 *key, u8 alg, int keyid, u8 set_tx)
2816 {
2817 u8 keylen;
2818 struct cmd_obj *pcmd;
2819 struct setkey_parm *psetkeyparm;
2820 struct cmd_priv *pcmdpriv = &(adapter_to_dvobj(padapter)->cmdpriv);
2821 int res = _SUCCESS;
2822
2823 /* RTW_INFO("%s\n", __FUNCTION__); */
2824
2825 pcmd = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
2826 if (pcmd == NULL) {
2827 res = _FAIL;
2828 goto exit;
2829 }
2830 pcmd->padapter = padapter;
2831
2832 psetkeyparm = (struct setkey_parm *)rtw_zmalloc(sizeof(struct setkey_parm));
2833 if (psetkeyparm == NULL) {
2834 rtw_mfree((unsigned char *)pcmd, sizeof(struct cmd_obj));
2835 res = _FAIL;
2836 goto exit;
2837 }
2838
2839 _rtw_memset(psetkeyparm, 0, sizeof(struct setkey_parm));
2840
2841 psetkeyparm->keyid = (u8)keyid;
2842 if (is_wep_enc(alg))
2843 padapter->securitypriv.key_mask |= BIT(psetkeyparm->keyid);
2844
2845 psetkeyparm->algorithm = alg;
2846
2847 psetkeyparm->set_tx = set_tx;
2848
2849 switch (alg) {
2850 case _WEP40_:
2851 keylen = 5;
2852 break;
2853 case _WEP104_:
2854 keylen = 13;
2855 break;
2856 case _GCMP_256_:
2857 case _CCMP_256_:
2858 keylen = 32;
2859 break;
2860 case _TKIP_:
2861 case _TKIP_WTMIC_:
2862 case _AES_:
2863 case _GCMP_:
2864 #ifdef CONFIG_IEEE80211W
2865 case _BIP_CMAC_128_:
2866 #endif
2867 default:
2868 keylen = 16;
2869 }
2870
2871 _rtw_memcpy(&(psetkeyparm->key[0]), key, keylen);
2872
2873 pcmd->cmdcode = CMD_SET_KEY; /*_SetKey_CMD_*/
2874 pcmd->parmbuf = (u8 *)psetkeyparm;
2875 pcmd->cmdsz = (sizeof(struct setkey_parm));
2876 pcmd->rsp = NULL;
2877 pcmd->rspsz = 0;
2878
2879
2880 _rtw_init_listhead(&pcmd->list);
2881
2882 res = rtw_enqueue_cmd(pcmdpriv, pcmd);
2883
2884 exit:
2885
2886 return res;
2887 }
2888 #endif
rtw_ap_set_group_key(_adapter * padapter,u8 * key,u8 alg,int keyid)2889 int rtw_ap_set_group_key(_adapter *padapter, u8 *key, u8 alg, int keyid)
2890 {
2891 RTW_INFO("%s\n", __FUNCTION__);
2892
2893 return rtw_ap_set_key(padapter, key, alg, keyid, 1);
2894 }
2895
rtw_ap_set_wep_key(_adapter * padapter,u8 * key,u8 keylen,int keyid,u8 set_tx)2896 int rtw_ap_set_wep_key(_adapter *padapter, u8 *key, u8 keylen, int keyid, u8 set_tx)
2897 {
2898 u8 alg;
2899
2900 switch (keylen) {
2901 case 5:
2902 alg = _WEP40_;
2903 break;
2904 case 13:
2905 alg = _WEP104_;
2906 break;
2907 default:
2908 alg = _NO_PRIVACY_;
2909 }
2910
2911 RTW_INFO("%s\n", __FUNCTION__);
2912
2913 return rtw_ap_set_key(padapter, key, alg, keyid, set_tx);
2914 }
2915
rtw_ap_bmc_frames_hdl(_adapter * padapter)2916 u8 rtw_ap_bmc_frames_hdl(_adapter *padapter)
2917 {
2918 #define HIQ_XMIT_COUNTS (6)
2919 struct sta_info *psta_bmc;
2920 _list *xmitframe_plist, *xmitframe_phead;
2921 struct xmit_frame *pxmitframe = NULL;
2922 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
2923 struct sta_priv *pstapriv = &padapter->stapriv;
2924 bool update_tim = _FALSE;
2925
2926
2927 if (padapter->registrypriv.wifi_spec != 1)
2928 return H2C_SUCCESS;
2929
2930
2931 psta_bmc = rtw_get_bcmc_stainfo(padapter);
2932 if (!psta_bmc)
2933 return H2C_SUCCESS;
2934
2935
2936 _rtw_spinlock_bh(&pxmitpriv->lock);
2937
2938 if ((rtw_tim_map_is_set(padapter, pstapriv->tim_bitmap, 0)) && (psta_bmc->sleepq_len > 0)) {
2939 int tx_counts = 0;
2940
2941 _update_beacon(padapter, _TIM_IE_, NULL, _FALSE, 0, "update TIM with TIB=1");
2942
2943 RTW_INFO("sleepq_len of bmc_sta = %d\n", psta_bmc->sleepq_len);
2944
2945 xmitframe_phead = get_list_head(&psta_bmc->sleep_q);
2946 xmitframe_plist = get_next(xmitframe_phead);
2947
2948 while ((rtw_end_of_queue_search(xmitframe_phead, xmitframe_plist)) == _FALSE) {
2949 pxmitframe = LIST_CONTAINOR(xmitframe_plist, struct xmit_frame, list);
2950
2951 xmitframe_plist = get_next(xmitframe_plist);
2952
2953 rtw_list_delete(&pxmitframe->list);
2954
2955 psta_bmc->sleepq_len--;
2956 tx_counts++;
2957
2958 if (psta_bmc->sleepq_len > 0)
2959 pxmitframe->attrib.mdata = 1;
2960 else
2961 pxmitframe->attrib.mdata = 0;
2962
2963 if (tx_counts == HIQ_XMIT_COUNTS)
2964 pxmitframe->attrib.mdata = 0;
2965
2966 pxmitframe->attrib.triggered = 1;
2967
2968 if (xmitframe_hiq_filter(pxmitframe) == _TRUE)
2969 pxmitframe->attrib.qsel = rtw_hal_get_qsel(padapter,QSLT_HIGH_ID);/*HIQ*/
2970
2971 rtw_intf_xmitframe_enqueue(padapter, pxmitframe);
2972
2973 if (tx_counts == HIQ_XMIT_COUNTS)
2974 break;
2975
2976 }
2977
2978 } else {
2979 if (psta_bmc->sleepq_len == 0) {
2980
2981 /*RTW_INFO("sleepq_len of bmc_sta = %d\n", psta_bmc->sleepq_len);*/
2982
2983 if (rtw_tim_map_is_set(padapter, pstapriv->tim_bitmap, 0))
2984 update_tim = _TRUE;
2985
2986 rtw_tim_map_clear(padapter, pstapriv->tim_bitmap, 0);
2987 rtw_tim_map_clear(padapter, pstapriv->sta_dz_bitmap, 0);
2988
2989 if (update_tim == _TRUE) {
2990 RTW_INFO("clear TIB\n");
2991 _update_beacon(padapter, _TIM_IE_, NULL, _TRUE, 0, "bmc sleepq and HIQ empty");
2992 }
2993 }
2994 }
2995
2996 _rtw_spinunlock_bh(&pxmitpriv->lock);
2997
2998 #if 0
2999 /* HIQ Check */
3000 rtw_hal_get_hwreg(padapter, HW_VAR_CHK_HI_QUEUE_EMPTY, &empty);
3001
3002 while (_FALSE == empty && rtw_get_passing_time_ms(start) < 3000) {
3003 rtw_msleep_os(100);
3004 rtw_hal_get_hwreg(padapter, HW_VAR_CHK_HI_QUEUE_EMPTY, &empty);
3005 }
3006
3007
3008 printk("check if hiq empty=%d\n", empty);
3009 #endif
3010
3011 return H2C_SUCCESS;
3012 }
3013
3014 #ifdef CONFIG_NATIVEAP_MLME
3015
associated_stainfo_update(_adapter * padapter,struct sta_info * psta,u32 sta_info_type)3016 static void associated_stainfo_update(_adapter *padapter, struct sta_info *psta, u32 sta_info_type)
3017 {
3018 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
3019
3020 RTW_INFO("%s: "MAC_FMT", updated_type=0x%x\n", __func__, MAC_ARG(psta->phl_sta->mac_addr), sta_info_type);
3021 #ifdef CONFIG_80211N_HT
3022 if (sta_info_type & STA_INFO_UPDATE_BW) {
3023
3024 if ((psta->flags & WLAN_STA_HT) && !psta->ht_20mhz_set) {
3025 if (pmlmepriv->sw_to_20mhz) {
3026 psta->phl_sta->chandef.bw = CHANNEL_WIDTH_20;
3027 /*psta->htpriv.ch_offset = CHAN_OFFSET_NO_EXT;*/
3028 psta->htpriv.sgi_40m = _FALSE;
3029 } else {
3030 /*TODO: Switch back to 40MHZ?80MHZ*/
3031 }
3032 }
3033 }
3034 #endif /* CONFIG_80211N_HT */
3035 /*
3036 if (sta_info_type & STA_INFO_UPDATE_RATE) {
3037
3038 }
3039 */
3040
3041 if (sta_info_type & STA_INFO_UPDATE_PROTECTION_MODE)
3042 VCS_update(padapter, psta);
3043
3044 /*
3045 if (sta_info_type & STA_INFO_UPDATE_CAP) {
3046
3047 }
3048
3049 if (sta_info_type & STA_INFO_UPDATE_HT_CAP) {
3050
3051 }
3052
3053 if (sta_info_type & STA_INFO_UPDATE_VHT_CAP) {
3054
3055 }
3056 */
3057
3058 }
3059
update_bcn_erpinfo_ie(_adapter * padapter)3060 static void update_bcn_erpinfo_ie(_adapter *padapter)
3061 {
3062 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
3063 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
3064 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
3065 WLAN_BSSID_EX *pnetwork = &(pmlmeinfo->network);
3066 unsigned char *p, *ie = pnetwork->IEs;
3067 u32 len = 0;
3068
3069 RTW_INFO("%s, ERP_enable=%d\n", __FUNCTION__, pmlmeinfo->ERP_enable);
3070
3071 if (!pmlmeinfo->ERP_enable)
3072 return;
3073
3074 /* parsing ERP_IE */
3075 p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _ERPINFO_IE_, &len, (pnetwork->IELength - _BEACON_IE_OFFSET_));
3076 if (p && len > 0) {
3077 PNDIS_802_11_VARIABLE_IEs pIE = (PNDIS_802_11_VARIABLE_IEs)p;
3078
3079 if (pmlmepriv->num_sta_non_erp == 1)
3080 pIE->data[0] |= RTW_ERP_INFO_NON_ERP_PRESENT | RTW_ERP_INFO_USE_PROTECTION;
3081 else
3082 pIE->data[0] &= ~(RTW_ERP_INFO_NON_ERP_PRESENT | RTW_ERP_INFO_USE_PROTECTION);
3083
3084 if (pmlmepriv->num_sta_no_short_preamble > 0)
3085 pIE->data[0] |= RTW_ERP_INFO_BARKER_PREAMBLE_MODE;
3086 else
3087 pIE->data[0] &= ~(RTW_ERP_INFO_BARKER_PREAMBLE_MODE);
3088
3089 ERP_IE_handler(padapter, pIE);
3090 }
3091
3092 }
3093
update_bcn_htcap_ie(_adapter * padapter)3094 static void update_bcn_htcap_ie(_adapter *padapter)
3095 {
3096 RTW_INFO("%s\n", __FUNCTION__);
3097
3098 }
3099
update_bcn_htinfo_ie(_adapter * padapter)3100 static void update_bcn_htinfo_ie(_adapter *padapter)
3101 {
3102 #ifdef CONFIG_80211N_HT
3103 /*
3104 u8 beacon_updated = _FALSE;
3105 u32 sta_info_update_type = STA_INFO_UPDATE_NONE;
3106 */
3107 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
3108 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
3109 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
3110 WLAN_BSSID_EX *pnetwork = &(pmlmeinfo->network);
3111 unsigned char *p, *ie = pnetwork->IEs;
3112 u32 len = 0;
3113
3114 if (pmlmepriv->htpriv.ht_option == _FALSE)
3115 return;
3116
3117 if (pmlmeinfo->HT_info_enable != 1)
3118 return;
3119
3120
3121 RTW_INFO("%s current operation mode=0x%X\n",
3122 __FUNCTION__, pmlmepriv->ht_op_mode);
3123
3124 RTW_INFO("num_sta_40mhz_intolerant(%d), 20mhz_width_req(%d), intolerant_ch_rpt(%d), olbc(%d)\n",
3125 pmlmepriv->num_sta_40mhz_intolerant, pmlmepriv->ht_20mhz_width_req, pmlmepriv->ht_intolerant_ch_reported, ATOMIC_READ(&pmlmepriv->olbc));
3126
3127 /*parsing HT_INFO_IE, currently only update ht_op_mode - pht_info->infos[1] & pht_info->infos[2] for wifi logo test*/
3128 p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_ADD_INFO_IE_, &len, (pnetwork->IELength - _BEACON_IE_OFFSET_));
3129 if (p && len > 0) {
3130 struct HT_info_element *pht_info = NULL;
3131
3132 pht_info = (struct HT_info_element *)(p + 2);
3133
3134 /* for STA Channel Width/Secondary Channel Offset*/
3135 if ((pmlmepriv->sw_to_20mhz == 0) && (pmlmeext->chandef.chan <= 14)) {
3136 if ((pmlmepriv->num_sta_40mhz_intolerant > 0) || (pmlmepriv->ht_20mhz_width_req == _TRUE)
3137 || (pmlmepriv->ht_intolerant_ch_reported == _TRUE) || (ATOMIC_READ(&pmlmepriv->olbc) == _TRUE)) {
3138 SET_HT_OP_ELE_2ND_CHL_OFFSET(pht_info, 0);
3139 SET_HT_OP_ELE_STA_CHL_WIDTH(pht_info, 0);
3140
3141 pmlmepriv->sw_to_20mhz = 1;
3142 /*
3143 sta_info_update_type |= STA_INFO_UPDATE_BW;
3144 beacon_updated = _TRUE;
3145 */
3146
3147 RTW_INFO("%s:switching to 20Mhz\n", __FUNCTION__);
3148
3149 /*TODO : cur_bwmode/cur_ch_offset switches to 20Mhz*/
3150 }
3151 } else {
3152
3153 if ((pmlmepriv->num_sta_40mhz_intolerant == 0) && (pmlmepriv->ht_20mhz_width_req == _FALSE)
3154 && (pmlmepriv->ht_intolerant_ch_reported == _FALSE) && (ATOMIC_READ(&pmlmepriv->olbc) == _FALSE)) {
3155
3156 if (pmlmeext->chandef.bw >= CHANNEL_WIDTH_40) {
3157
3158 SET_HT_OP_ELE_STA_CHL_WIDTH(pht_info, 1);
3159
3160 SET_HT_OP_ELE_2ND_CHL_OFFSET(pht_info,
3161 (pmlmeext->chandef.offset == CHAN_OFFSET_UPPER) ?
3162 HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE : HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW);
3163
3164 pmlmepriv->sw_to_20mhz = 0;
3165 /*
3166 sta_info_update_type |= STA_INFO_UPDATE_BW;
3167 beacon_updated = _TRUE;
3168 */
3169
3170 RTW_INFO("%s:switching back to 40Mhz\n", __FUNCTION__);
3171 }
3172 }
3173 }
3174
3175 /* to update ht_op_mode*/
3176 *(u16 *)(pht_info->infos + 1) = cpu_to_le16(pmlmepriv->ht_op_mode);
3177
3178 }
3179
3180 /*associated_clients_update(padapter, beacon_updated, sta_info_update_type);*/
3181 #endif /* CONFIG_80211N_HT */
3182 }
3183
update_bcn_rsn_ie(_adapter * padapter)3184 static void update_bcn_rsn_ie(_adapter *padapter)
3185 {
3186 RTW_INFO("%s\n", __FUNCTION__);
3187
3188 }
3189
update_bcn_wpa_ie(_adapter * padapter)3190 static void update_bcn_wpa_ie(_adapter *padapter)
3191 {
3192 RTW_INFO("%s\n", __FUNCTION__);
3193
3194 }
3195
update_bcn_wmm_ie(_adapter * padapter)3196 static void update_bcn_wmm_ie(_adapter *padapter)
3197 {
3198 RTW_INFO("%s\n", __FUNCTION__);
3199
3200 }
3201
update_bcn_wps_ie(_adapter * padapter)3202 static void update_bcn_wps_ie(_adapter *padapter)
3203 {
3204 u8 *pwps_ie = NULL, *pwps_ie_src, *premainder_ie, *pbackup_remainder_ie = NULL;
3205 uint wps_ielen = 0, wps_offset, remainder_ielen;
3206 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
3207 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
3208 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
3209 WLAN_BSSID_EX *pnetwork = &(pmlmeinfo->network);
3210 unsigned char *ie = pnetwork->IEs;
3211 u32 ielen = pnetwork->IELength;
3212
3213
3214 RTW_INFO("%s\n", __FUNCTION__);
3215
3216 pwps_ie = rtw_get_wps_ie(ie + _FIXED_IE_LENGTH_, ielen - _FIXED_IE_LENGTH_, NULL, &wps_ielen);
3217
3218 if (pwps_ie == NULL || wps_ielen == 0)
3219 return;
3220
3221 pwps_ie_src = pmlmepriv->wps_beacon_ie;
3222 if (pwps_ie_src == NULL)
3223 return;
3224
3225 wps_offset = (uint)(pwps_ie - ie);
3226
3227 premainder_ie = pwps_ie + wps_ielen;
3228
3229 remainder_ielen = ielen - wps_offset - wps_ielen;
3230
3231 if (remainder_ielen > 0) {
3232 pbackup_remainder_ie = rtw_malloc(remainder_ielen);
3233 if (pbackup_remainder_ie)
3234 _rtw_memcpy(pbackup_remainder_ie, premainder_ie, remainder_ielen);
3235 }
3236
3237 wps_ielen = (uint)pwps_ie_src[1];/* to get ie data len */
3238 if ((wps_offset + wps_ielen + 2 + remainder_ielen) <= MAX_IE_SZ) {
3239 _rtw_memcpy(pwps_ie, pwps_ie_src, wps_ielen + 2);
3240 pwps_ie += (wps_ielen + 2);
3241
3242 if (pbackup_remainder_ie)
3243 _rtw_memcpy(pwps_ie, pbackup_remainder_ie, remainder_ielen);
3244
3245 /* update IELength */
3246 pnetwork->IELength = wps_offset + (wps_ielen + 2) + remainder_ielen;
3247 }
3248
3249 if (pbackup_remainder_ie)
3250 rtw_mfree(pbackup_remainder_ie, remainder_ielen);
3251
3252 /* deal with the case without set_tx_beacon_cmd() in rtw_update_beacon() */
3253 #if defined(CONFIG_INTERRUPT_BASED_TXBCN) || defined(CONFIG_PCI_HCI)
3254 if ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE) {
3255 u8 sr = 0;
3256 rtw_get_wps_attr_content(pwps_ie_src, wps_ielen, WPS_ATTR_SELECTED_REGISTRAR, (u8 *)(&sr), NULL);
3257
3258 if (sr) {
3259 set_fwstate(pmlmepriv, WIFI_UNDER_WPS);
3260 RTW_INFO("%s, set WIFI_UNDER_WPS\n", __func__);
3261 } else {
3262 clr_fwstate(pmlmepriv, WIFI_UNDER_WPS);
3263 RTW_INFO("%s, clr WIFI_UNDER_WPS\n", __func__);
3264 }
3265 }
3266 #endif
3267 }
3268
update_bcn_p2p_ie(_adapter * padapter)3269 static void update_bcn_p2p_ie(_adapter *padapter)
3270 {
3271
3272 }
3273
update_csa_ie(_adapter * padapter)3274 static u8 update_csa_ie(_adapter *padapter)
3275 {
3276 u8 update = _FALSE;
3277 #ifdef CONFIG_ECSA_PHL
3278 struct core_ecsa_info *ecsa_info = &(padapter->ecsa_info);
3279 struct rtw_phl_ecsa_param *ecsa_param = &(ecsa_info->phl_ecsa_param);
3280 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
3281 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
3282 WLAN_BSSID_EX *pnetwork = &(pmlmeinfo->network);
3283 u8 csa_data[CSA_IE_LEN] = {0};
3284 u8 csa_ch = ecsa_param->new_chan_def.chan;
3285 u8 csa_count = ecsa_param->count;
3286 u8 *ies = pnetwork->IEs + _BEACON_IE_OFFSET_;
3287 sint ies_len = pnetwork->IELength - _BEACON_IE_OFFSET_;
3288 u8 *csa_ie;
3289 sint csa_ie_len;
3290
3291 if (!CHK_ECSA_STATE(padapter, ECSA_ST_SW_START))
3292 return update;
3293
3294 csa_ie = rtw_get_ie(ies, WLAN_EID_CHANNEL_SWITCH, &csa_ie_len, ies_len);
3295
3296 if (csa_ie == NULL) {
3297 if (csa_count > 0) {
3298 /* add new CSA IE */
3299 RTW_INFO("CSA : "FUNC_ADPT_FMT" ch=%u, count=%u, add CSA IE\n",
3300 FUNC_ADPT_ARG(padapter), csa_ch, csa_count);
3301
3302 csa_data[CSA_SWITCH_MODE] = ecsa_param->mode;
3303 csa_data[CSA_NEW_CH] = csa_ch;
3304 csa_data[CSA_SWITCH_COUNT] = csa_count;
3305 rtw_add_bcn_ie(padapter, pnetwork, WLAN_EID_CHANNEL_SWITCH, csa_data, CSA_IE_LEN);
3306 update = _TRUE;
3307 } else if (csa_ch > 0) {
3308 /* count = 0, means switching channel immediately */
3309 RTW_INFO("CSA : "FUNC_ADPT_FMT" ch=%d, count=0, switch channel immediately\n",
3310 FUNC_ADPT_ARG(padapter), csa_ch);
3311 SET_ECSA_STATE(padapter, ECSA_ST_SW_DONE);
3312 }
3313 } else if (csa_ie && csa_ie_len == CSA_IE_LEN) {
3314 if (csa_count > 0) {
3315 /* update CSA IE */
3316 #ifdef DBG_CSA
3317 RTW_INFO("CSA : "FUNC_ADPT_FMT" ch=%u, count=%u, update CSA IE\n",
3318 FUNC_ADPT_ARG(padapter), csa_ch, csa_count);
3319 #endif
3320
3321 csa_ie[2 + CSA_SWITCH_COUNT] = csa_count;
3322 } else {
3323 /* remove CSA IE */
3324 RTW_INFO("CSA : "FUNC_ADPT_FMT" ch=%u, count=%u, remove CSA IE\n",
3325 FUNC_ADPT_ARG(padapter), csa_ch, csa_count);
3326
3327 rtw_remove_bcn_ie(padapter, pnetwork, WLAN_EID_CHANNEL_SWITCH);
3328 SET_ECSA_STATE(padapter, ECSA_ST_SW_DONE);
3329 }
3330 update = _TRUE;
3331 } else {
3332 RTW_ERR("CSA : "FUNC_ADPT_FMT" unexpected case\n", FUNC_ADPT_ARG(padapter));
3333 }
3334
3335 if (ecsa_param->count > 0)
3336 ecsa_param->count--;
3337
3338 #endif /* CONFIG_ECSA_PHL */
3339 return update;
3340 }
3341
update_bcn_vendor_spec_ie(_adapter * padapter,u8 * oui)3342 static void update_bcn_vendor_spec_ie(_adapter *padapter, u8 *oui)
3343 {
3344 RTW_INFO("%s\n", __FUNCTION__);
3345
3346 if (_rtw_memcmp(RTW_WPA_OUI, oui, 4))
3347 update_bcn_wpa_ie(padapter);
3348 else if (_rtw_memcmp(WMM_OUI, oui, 4))
3349 update_bcn_wmm_ie(padapter);
3350 else if (_rtw_memcmp(WPS_OUI, oui, 4))
3351 update_bcn_wps_ie(padapter);
3352 else if (_rtw_memcmp(P2P_OUI, oui, 4))
3353 update_bcn_p2p_ie(padapter);
3354 else
3355 RTW_INFO("unknown OUI type!\n");
3356
3357
3358 }
3359
_update_beacon(_adapter * padapter,u8 ie_id,u8 * oui,u8 tx,u8 flags,const char * tag)3360 void _update_beacon(_adapter *padapter, u8 ie_id, u8 *oui, u8 tx, u8 flags, const char *tag)
3361 {
3362 struct mlme_priv *pmlmepriv;
3363 struct mlme_ext_priv *pmlmeext;
3364 bool updated = 1; /* treat as upadated by default */
3365
3366 if (!padapter)
3367 return;
3368
3369 pmlmepriv = &(padapter->mlmepriv);
3370 pmlmeext = &(padapter->mlmeextpriv);
3371
3372 if (pmlmeext->bstart_bss == _FALSE)
3373 return;
3374
3375 _rtw_spinlock_bh(&pmlmepriv->bcn_update_lock);
3376
3377 switch (ie_id) {
3378 case _TIM_IE_:
3379 update_BCNTIM(padapter);
3380 break;
3381
3382 case _ERPINFO_IE_:
3383 update_bcn_erpinfo_ie(padapter);
3384 break;
3385
3386 case _HT_CAPABILITY_IE_:
3387 update_bcn_htcap_ie(padapter);
3388 break;
3389
3390 case _RSN_IE_2_:
3391 update_bcn_rsn_ie(padapter);
3392 break;
3393
3394 case _HT_ADD_INFO_IE_:
3395 update_bcn_htinfo_ie(padapter);
3396 break;
3397
3398 #ifdef CONFIG_RTW_MESH
3399 case WLAN_EID_MESH_CONFIG:
3400 updated = rtw_mesh_update_bss_peering_status(padapter, &(pmlmeext->mlmext_info.network));
3401 updated |= rtw_mesh_update_bss_formation_info(padapter, &(pmlmeext->mlmext_info.network));
3402 updated |= rtw_mesh_update_bss_forwarding_state(padapter, &(pmlmeext->mlmext_info.network));
3403 break;
3404 #endif
3405 case WLAN_EID_CHANNEL_SWITCH:
3406 updated = update_csa_ie(padapter);
3407 break;
3408
3409 case _VENDOR_SPECIFIC_IE_:
3410 update_bcn_vendor_spec_ie(padapter, oui);
3411 break;
3412
3413 case 0xFF:
3414 default:
3415 break;
3416 }
3417
3418 if (updated)
3419 pmlmepriv->update_bcn = _TRUE;
3420
3421 _rtw_spinunlock_bh(&pmlmepriv->bcn_update_lock);
3422
3423 #ifndef CONFIG_INTERRUPT_BASED_TXBCN
3424 #if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI) || defined(CONFIG_PCI_BCN_POLLING)
3425 if (tx && updated) {
3426 /* send_beacon(padapter); */ /* send_beacon must execute on TSR level */
3427 if (0)
3428 RTW_INFO(FUNC_ADPT_FMT" ie_id:%u - %s\n", FUNC_ADPT_ARG(padapter), ie_id, tag);
3429 if(flags == RTW_CMDF_WAIT_ACK)
3430 set_tx_beacon_cmd(padapter, RTW_CMDF_WAIT_ACK);
3431 else
3432 set_tx_beacon_cmd(padapter, 0);
3433 }
3434 #else
3435 {
3436 /* PCI will issue beacon when BCN interrupt occurs. */
3437 }
3438 #endif
3439 #endif /* !CONFIG_INTERRUPT_BASED_TXBCN */
3440 }
3441
3442 #ifdef CONFIG_80211N_HT
3443
rtw_process_public_act_bsscoex(_adapter * padapter,u8 * pframe,uint frame_len)3444 void rtw_process_public_act_bsscoex(_adapter *padapter, u8 *pframe, uint frame_len)
3445 {
3446 struct sta_info *psta;
3447 struct sta_priv *pstapriv = &padapter->stapriv;
3448 u8 beacon_updated = _FALSE;
3449 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
3450 u8 *frame_body = pframe + sizeof(struct rtw_ieee80211_hdr_3addr);
3451 uint frame_body_len = frame_len - sizeof(struct rtw_ieee80211_hdr_3addr);
3452 u8 category, action;
3453
3454 psta = rtw_get_stainfo(pstapriv, get_addr2_ptr(pframe));
3455 if (psta == NULL)
3456 return;
3457
3458
3459 category = frame_body[0];
3460 action = frame_body[1];
3461
3462 if (frame_body_len > 0) {
3463 if ((frame_body[2] == EID_BSSCoexistence) && (frame_body[3] > 0)) {
3464 u8 ie_data = frame_body[4];
3465
3466 if (ie_data & RTW_WLAN_20_40_BSS_COEX_40MHZ_INTOL) {
3467 if (psta->ht_40mhz_intolerant == 0) {
3468 psta->ht_40mhz_intolerant = 1;
3469 pmlmepriv->num_sta_40mhz_intolerant++;
3470 beacon_updated = _TRUE;
3471 }
3472 } else if (ie_data & RTW_WLAN_20_40_BSS_COEX_20MHZ_WIDTH_REQ) {
3473 if (pmlmepriv->ht_20mhz_width_req == _FALSE) {
3474 pmlmepriv->ht_20mhz_width_req = _TRUE;
3475 beacon_updated = _TRUE;
3476 }
3477 } else
3478 beacon_updated = _FALSE;
3479 }
3480 }
3481
3482 if (frame_body_len > 8) {
3483 /* if EID_BSSIntolerantChlReport ie exists */
3484 if ((frame_body[5] == EID_BSSIntolerantChlReport) && (frame_body[6] > 0)) {
3485 /*todo:*/
3486 if (pmlmepriv->ht_intolerant_ch_reported == _FALSE) {
3487 pmlmepriv->ht_intolerant_ch_reported = _TRUE;
3488 beacon_updated = _TRUE;
3489 }
3490 }
3491 }
3492
3493 if (beacon_updated) {
3494
3495 rtw_update_beacon(padapter, _HT_ADD_INFO_IE_, NULL, _TRUE, 0);
3496
3497 associated_stainfo_update(padapter, psta, STA_INFO_UPDATE_BW);
3498 }
3499
3500
3501
3502 }
3503
rtw_process_ht_action_smps(_adapter * padapter,u8 * ta,u8 ctrl_field)3504 void rtw_process_ht_action_smps(_adapter *padapter, u8 *ta, u8 ctrl_field)
3505 {
3506 u8 e_field, m_field;
3507 struct sta_info *psta;
3508 struct sta_priv *pstapriv = &padapter->stapriv;
3509
3510 psta = rtw_get_stainfo(pstapriv, ta);
3511 if (psta == NULL)
3512 return;
3513
3514 e_field = (ctrl_field & BIT(0)) ? 1 : 0; /*SM Power Save Enabled*/
3515 m_field = (ctrl_field & BIT(1)) ? 1 : 0; /*SM Mode, 0:static SMPS, 1:dynamic SMPS*/
3516
3517 if (e_field) {
3518 if (m_field) { /*mode*/
3519 psta->htpriv.smps_cap = WLAN_HT_CAP_SM_PS_DYNAMIC;
3520 RTW_ERR("Don't support dynamic SMPS\n");
3521 }
3522 else
3523 psta->htpriv.smps_cap = WLAN_HT_CAP_SM_PS_STATIC;
3524 } else {
3525 /*disable*/
3526 psta->htpriv.smps_cap = WLAN_HT_CAP_SM_PS_DISABLED;
3527 }
3528
3529 if (psta->htpriv.smps_cap != WLAN_HT_CAP_SM_PS_DYNAMIC)
3530 rtw_ssmps_wk_cmd(padapter, psta, e_field, 1);
3531 }
3532
3533 /*
3534 op_mode
3535 Set to 0 (HT pure) under the followign conditions
3536 - all STAs in the BSS are 20/40 MHz HT in 20/40 MHz BSS or
3537 - all STAs in the BSS are 20 MHz HT in 20 MHz BSS
3538 Set to 1 (HT non-member protection) if there may be non-HT STAs
3539 in both the primary and the secondary channel
3540 Set to 2 if only HT STAs are associated in BSS,
3541 however and at least one 20 MHz HT STA is associated
3542 Set to 3 (HT mixed mode) when one or more non-HT STAs are associated
3543 (currently non-GF HT station is considered as non-HT STA also)
3544 */
rtw_ht_operation_update(_adapter * padapter)3545 int rtw_ht_operation_update(_adapter *padapter)
3546 {
3547 u16 cur_op_mode, new_op_mode;
3548 int op_mode_changes = 0;
3549 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
3550 struct ht_priv *phtpriv_ap = &pmlmepriv->htpriv;
3551
3552 if (pmlmepriv->htpriv.ht_option == _FALSE)
3553 return 0;
3554
3555 /*if (!iface->conf->ieee80211n || iface->conf->ht_op_mode_fixed)
3556 return 0;*/
3557
3558 RTW_INFO("%s current operation mode=0x%X\n",
3559 __FUNCTION__, pmlmepriv->ht_op_mode);
3560
3561 if (!(pmlmepriv->ht_op_mode & HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT)
3562 && pmlmepriv->num_sta_ht_no_gf) {
3563 pmlmepriv->ht_op_mode |=
3564 HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT;
3565 op_mode_changes++;
3566 } else if ((pmlmepriv->ht_op_mode &
3567 HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT) &&
3568 pmlmepriv->num_sta_ht_no_gf == 0) {
3569 pmlmepriv->ht_op_mode &=
3570 ~HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT;
3571 op_mode_changes++;
3572 }
3573
3574 if (!(pmlmepriv->ht_op_mode & HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT) &&
3575 (pmlmepriv->num_sta_no_ht || ATOMIC_READ(&pmlmepriv->olbc_ht))) {
3576 pmlmepriv->ht_op_mode |= HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT;
3577 op_mode_changes++;
3578 } else if ((pmlmepriv->ht_op_mode &
3579 HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT) &&
3580 (pmlmepriv->num_sta_no_ht == 0 && !ATOMIC_READ(&pmlmepriv->olbc_ht))) {
3581 pmlmepriv->ht_op_mode &=
3582 ~HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT;
3583 op_mode_changes++;
3584 }
3585
3586 /* Note: currently we switch to the MIXED op mode if HT non-greenfield
3587 * station is associated. Probably it's a theoretical case, since
3588 * it looks like all known HT STAs support greenfield.
3589 */
3590 new_op_mode = 0;
3591 if (pmlmepriv->num_sta_no_ht /*||
3592 (pmlmepriv->ht_op_mode & HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT)*/)
3593 new_op_mode = OP_MODE_MIXED;
3594 else if ((phtpriv_ap->ht_cap.cap_info & IEEE80211_HT_CAP_SUP_WIDTH)
3595 && pmlmepriv->num_sta_ht_20mhz)
3596 new_op_mode = OP_MODE_20MHZ_HT_STA_ASSOCED;
3597 else if (ATOMIC_READ(&pmlmepriv->olbc_ht))
3598 new_op_mode = OP_MODE_MAY_BE_LEGACY_STAS;
3599 else
3600 new_op_mode = OP_MODE_PURE;
3601
3602 cur_op_mode = pmlmepriv->ht_op_mode & HT_INFO_OPERATION_MODE_OP_MODE_MASK;
3603 if (cur_op_mode != new_op_mode) {
3604 pmlmepriv->ht_op_mode &= ~HT_INFO_OPERATION_MODE_OP_MODE_MASK;
3605 pmlmepriv->ht_op_mode |= new_op_mode;
3606 op_mode_changes++;
3607 }
3608
3609 RTW_INFO("%s new operation mode=0x%X changes=%d\n",
3610 __FUNCTION__, pmlmepriv->ht_op_mode, op_mode_changes);
3611
3612 return op_mode_changes;
3613
3614 }
3615
3616 #endif /* CONFIG_80211N_HT */
3617
associated_clients_update(_adapter * padapter,u8 updated,u32 sta_info_type)3618 void associated_clients_update(_adapter *padapter, u8 updated, u32 sta_info_type)
3619 {
3620 /* update associcated stations cap. */
3621 if (updated == _TRUE) {
3622 _list *phead, *plist;
3623 struct sta_info *psta = NULL;
3624 struct sta_priv *pstapriv = &padapter->stapriv;
3625
3626 _rtw_spinlock_bh(&pstapriv->asoc_list_lock);
3627
3628 phead = &pstapriv->asoc_list;
3629 plist = get_next(phead);
3630
3631 /* check asoc_queue */
3632 while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {
3633 psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);
3634
3635 plist = get_next(plist);
3636
3637 associated_stainfo_update(padapter, psta, sta_info_type);
3638 }
3639
3640 _rtw_spinunlock_bh(&pstapriv->asoc_list_lock);
3641
3642 }
3643
3644 }
3645
3646 /* called > TSR LEVEL for USB or SDIO Interface*/
bss_cap_update_on_sta_join(_adapter * padapter,struct sta_info * psta)3647 void bss_cap_update_on_sta_join(_adapter *padapter, struct sta_info *psta)
3648 {
3649 u8 beacon_updated = _FALSE;
3650 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
3651 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
3652
3653
3654 #if 0
3655 if (!(psta->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) &&
3656 !psta->no_short_preamble_set) {
3657 psta->no_short_preamble_set = 1;
3658 pmlmepriv->num_sta_no_short_preamble++;
3659 if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) &&
3660 (pmlmepriv->num_sta_no_short_preamble == 1))
3661 ieee802_11_set_beacons(hapd->iface);
3662 }
3663 #endif
3664
3665
3666 if (!(psta->flags & WLAN_STA_SHORT_PREAMBLE)) {
3667 if (!psta->no_short_preamble_set) {
3668 psta->no_short_preamble_set = 1;
3669
3670 pmlmepriv->num_sta_no_short_preamble++;
3671
3672 if ((pmlmeext->cur_wireless_mode > WLAN_MD_11B) &&
3673 (pmlmepriv->num_sta_no_short_preamble == 1))
3674 beacon_updated = _TRUE;
3675 }
3676 } else {
3677 if (psta->no_short_preamble_set) {
3678 psta->no_short_preamble_set = 0;
3679
3680 pmlmepriv->num_sta_no_short_preamble--;
3681
3682 if ((pmlmeext->cur_wireless_mode > WLAN_MD_11B) &&
3683 (pmlmepriv->num_sta_no_short_preamble == 0))
3684 beacon_updated = _TRUE;
3685 }
3686 }
3687
3688 #if 0
3689 if (psta->flags & WLAN_STA_NONERP && !psta->nonerp_set) {
3690 psta->nonerp_set = 1;
3691 pmlmepriv->num_sta_non_erp++;
3692 if (pmlmepriv->num_sta_non_erp == 1)
3693 ieee802_11_set_beacons(hapd->iface);
3694 }
3695 #endif
3696
3697 if (psta->flags & WLAN_STA_NONERP) {
3698 if (!psta->nonerp_set) {
3699 psta->nonerp_set = 1;
3700
3701 pmlmepriv->num_sta_non_erp++;
3702
3703 if (pmlmepriv->num_sta_non_erp == 1) {
3704 beacon_updated = _TRUE;
3705 rtw_update_beacon(padapter, _ERPINFO_IE_, NULL, _FALSE, 0);
3706 }
3707 }
3708
3709 } else {
3710 if (psta->nonerp_set) {
3711 psta->nonerp_set = 0;
3712
3713 pmlmepriv->num_sta_non_erp--;
3714
3715 if (pmlmepriv->num_sta_non_erp == 0) {
3716 beacon_updated = _TRUE;
3717 rtw_update_beacon(padapter, _ERPINFO_IE_, NULL, _FALSE, 0);
3718 }
3719 }
3720
3721 }
3722
3723
3724 #if 0
3725 if (!(psta->capability & WLAN_CAPABILITY_SHORT_SLOT) &&
3726 !psta->no_short_slot_time_set) {
3727 psta->no_short_slot_time_set = 1;
3728 pmlmepriv->num_sta_no_short_slot_time++;
3729 if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) &&
3730 (pmlmepriv->num_sta_no_short_slot_time == 1))
3731 ieee802_11_set_beacons(hapd->iface);
3732 }
3733 #endif
3734
3735 if (!(psta->capability & WLAN_CAPABILITY_SHORT_SLOT)) {
3736 if (!psta->no_short_slot_time_set) {
3737 psta->no_short_slot_time_set = 1;
3738
3739 pmlmepriv->num_sta_no_short_slot_time++;
3740
3741 if ((pmlmeext->cur_wireless_mode > WLAN_MD_11B) &&
3742 (pmlmepriv->num_sta_no_short_slot_time == 1))
3743 beacon_updated = _TRUE;
3744 }
3745 } else {
3746 if (psta->no_short_slot_time_set) {
3747 psta->no_short_slot_time_set = 0;
3748
3749 pmlmepriv->num_sta_no_short_slot_time--;
3750
3751 if ((pmlmeext->cur_wireless_mode > WLAN_MD_11B) &&
3752 (pmlmepriv->num_sta_no_short_slot_time == 0))
3753 beacon_updated = _TRUE;
3754 }
3755 }
3756
3757 #ifdef CONFIG_80211N_HT
3758 if(padapter->registrypriv.ht_enable &&
3759 is_supported_ht(padapter->registrypriv.wireless_mode)) {
3760 if (psta->flags & WLAN_STA_HT) {
3761 u16 ht_capab = le16_to_cpu(psta->htpriv.ht_cap.cap_info);
3762
3763 RTW_INFO("HT: STA " MAC_FMT " HT Capabilities Info: 0x%04x\n",
3764 MAC_ARG(psta->phl_sta->mac_addr), ht_capab);
3765
3766 if (psta->no_ht_set) {
3767 psta->no_ht_set = 0;
3768 pmlmepriv->num_sta_no_ht--;
3769 }
3770
3771 if ((ht_capab & IEEE80211_HT_CAP_GRN_FLD) == 0) {
3772 if (!psta->no_ht_gf_set) {
3773 psta->no_ht_gf_set = 1;
3774 pmlmepriv->num_sta_ht_no_gf++;
3775 }
3776 RTW_INFO("%s STA " MAC_FMT " - no "
3777 "greenfield, num of non-gf stations %d\n",
3778 __FUNCTION__, MAC_ARG(psta->phl_sta->mac_addr),
3779 pmlmepriv->num_sta_ht_no_gf);
3780 }
3781
3782 if ((ht_capab & IEEE80211_HT_CAP_SUP_WIDTH) == 0) {
3783 if (!psta->ht_20mhz_set) {
3784 psta->ht_20mhz_set = 1;
3785 pmlmepriv->num_sta_ht_20mhz++;
3786 }
3787 RTW_INFO("%s STA " MAC_FMT " - 20 MHz HT, "
3788 "num of 20MHz HT STAs %d\n",
3789 __FUNCTION__, MAC_ARG(psta->phl_sta->mac_addr),
3790 pmlmepriv->num_sta_ht_20mhz);
3791 }
3792
3793 if (((ht_capab & RTW_IEEE80211_HT_CAP_40MHZ_INTOLERANT) != 0) &&
3794 (psta->ht_40mhz_intolerant == 0)) {
3795 psta->ht_40mhz_intolerant = 1;
3796 pmlmepriv->num_sta_40mhz_intolerant++;
3797 RTW_INFO("%s STA " MAC_FMT " - 40MHZ_INTOLERANT, ",
3798 __FUNCTION__, MAC_ARG(psta->phl_sta->mac_addr));
3799 }
3800
3801 } else {
3802 if (!psta->no_ht_set) {
3803 psta->no_ht_set = 1;
3804 pmlmepriv->num_sta_no_ht++;
3805 }
3806 if (pmlmepriv->htpriv.ht_option == _TRUE) {
3807 RTW_INFO("%s STA " MAC_FMT
3808 " - no HT, num of non-HT stations %d\n",
3809 __FUNCTION__, MAC_ARG(psta->phl_sta->mac_addr),
3810 pmlmepriv->num_sta_no_ht);
3811 }
3812 }
3813
3814 if (rtw_ht_operation_update(padapter) > 0) {
3815 rtw_update_beacon(padapter, _HT_CAPABILITY_IE_, NULL, _FALSE, 0);
3816 rtw_update_beacon(padapter, _HT_ADD_INFO_IE_, NULL, _FALSE, 0);
3817 beacon_updated = _TRUE;
3818 }
3819 }
3820 #endif /* CONFIG_80211N_HT */
3821
3822 #ifdef CONFIG_RTW_MESH
3823 if (MLME_IS_MESH(padapter)) {
3824 struct sta_priv *pstapriv = &padapter->stapriv;
3825
3826 rtw_update_beacon(padapter, WLAN_EID_MESH_CONFIG, NULL, _FALSE, 0);
3827 if (pstapriv->asoc_list_cnt == 1)
3828 _set_timer(&padapter->mesh_atlm_param_req_timer, 0);
3829 beacon_updated = _TRUE;
3830 }
3831 #endif
3832
3833 if (beacon_updated)
3834 rtw_update_beacon(padapter, 0xFF, NULL, _TRUE, 0);
3835
3836 /* update associcated stations cap. */
3837 associated_clients_update(padapter, beacon_updated, STA_INFO_UPDATE_ALL);
3838
3839 RTW_INFO("%s, updated=%d\n", __func__, beacon_updated);
3840
3841 }
3842
bss_cap_update_on_sta_leave(_adapter * padapter,struct sta_info * psta)3843 u8 bss_cap_update_on_sta_leave(_adapter *padapter, struct sta_info *psta)
3844 {
3845 u8 beacon_updated = _FALSE;
3846 struct sta_priv *pstapriv = &padapter->stapriv;
3847 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
3848 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
3849
3850 if (!psta)
3851 return beacon_updated;
3852
3853 if (rtw_tim_map_is_set(padapter, pstapriv->tim_bitmap, psta->phl_sta->aid)) {
3854 rtw_tim_map_clear(padapter, pstapriv->tim_bitmap, psta->phl_sta->aid);
3855 beacon_updated = _TRUE;
3856 rtw_update_beacon(padapter, _TIM_IE_, NULL, _FALSE, 0);
3857 }
3858
3859 if (psta->no_short_preamble_set) {
3860 psta->no_short_preamble_set = 0;
3861 pmlmepriv->num_sta_no_short_preamble--;
3862 if (pmlmeext->cur_wireless_mode > WLAN_MD_11B
3863 && pmlmepriv->num_sta_no_short_preamble == 0)
3864 beacon_updated = _TRUE;
3865 }
3866
3867 if (psta->nonerp_set) {
3868 psta->nonerp_set = 0;
3869 pmlmepriv->num_sta_non_erp--;
3870 if (pmlmepriv->num_sta_non_erp == 0) {
3871 beacon_updated = _TRUE;
3872 rtw_update_beacon(padapter, _ERPINFO_IE_, NULL, _FALSE, 0);
3873 }
3874 }
3875
3876 if (psta->no_short_slot_time_set) {
3877 psta->no_short_slot_time_set = 0;
3878 pmlmepriv->num_sta_no_short_slot_time--;
3879 if (pmlmeext->cur_wireless_mode > WLAN_MD_11B
3880 && pmlmepriv->num_sta_no_short_slot_time == 0)
3881 beacon_updated = _TRUE;
3882 }
3883
3884 #ifdef CONFIG_80211N_HT
3885 if (psta->no_ht_gf_set) {
3886 psta->no_ht_gf_set = 0;
3887 pmlmepriv->num_sta_ht_no_gf--;
3888 }
3889
3890 if (psta->no_ht_set) {
3891 psta->no_ht_set = 0;
3892 pmlmepriv->num_sta_no_ht--;
3893 }
3894
3895 if (psta->ht_20mhz_set) {
3896 psta->ht_20mhz_set = 0;
3897 pmlmepriv->num_sta_ht_20mhz--;
3898 }
3899
3900 if (psta->ht_40mhz_intolerant) {
3901 psta->ht_40mhz_intolerant = 0;
3902 if (pmlmepriv->num_sta_40mhz_intolerant > 0)
3903 pmlmepriv->num_sta_40mhz_intolerant--;
3904 else
3905 rtw_warn_on(1);
3906 }
3907
3908 if (rtw_ht_operation_update(padapter) > 0) {
3909 rtw_update_beacon(padapter, _HT_CAPABILITY_IE_, NULL, _FALSE, 0);
3910 rtw_update_beacon(padapter, _HT_ADD_INFO_IE_, NULL, _FALSE, 0);
3911 }
3912 #endif /* CONFIG_80211N_HT */
3913
3914 #ifdef CONFIG_RTW_MESH
3915 if (MLME_IS_MESH(padapter)) {
3916 rtw_update_beacon(padapter, WLAN_EID_MESH_CONFIG, NULL, _FALSE, 0);
3917 if (pstapriv->asoc_list_cnt == 0)
3918 _cancel_timer_ex(&padapter->mesh_atlm_param_req_timer);
3919 beacon_updated = _TRUE;
3920 }
3921 #endif
3922
3923 if (beacon_updated == _TRUE)
3924 rtw_update_beacon(padapter, 0xFF, NULL, _TRUE, 0);
3925
3926 #if 0
3927 /* update associated stations cap. */
3928 associated_clients_update(padapter, beacon_updated, STA_INFO_UPDATE_ALL); /* move it to avoid deadlock */
3929 #endif
3930
3931 RTW_INFO("%s, updated=%d\n", __func__, beacon_updated);
3932
3933 return beacon_updated;
3934
3935 }
3936
ap_free_sta(_adapter * padapter,struct sta_info * psta,bool active,u16 reason,bool enqueue,u8 disassoc)3937 u8 ap_free_sta(_adapter *padapter, struct sta_info *psta, bool active, u16 reason, bool enqueue, u8 disassoc)
3938 {
3939 u8 beacon_updated = _FALSE;
3940
3941 if (!psta)
3942 return beacon_updated;
3943
3944 RTW_INFO("%s sta "MAC_FMT"\n", __func__, MAC_ARG(psta->phl_sta->mac_addr));
3945
3946 if (active == _TRUE) {
3947 #ifdef CONFIG_80211N_HT
3948 /* tear down Rx AMPDU */
3949 send_delba(padapter, 0, psta->phl_sta->mac_addr);/* recipient */
3950
3951 /* tear down TX AMPDU */
3952 send_delba(padapter, 1, psta->phl_sta->mac_addr);/* */ /* originator */
3953
3954 #endif /* CONFIG_80211N_HT */
3955
3956 if (!MLME_IS_MESH(padapter)) {
3957 if (disassoc == _TRUE)
3958 issue_disassoc(padapter, psta->phl_sta->mac_addr, reason);
3959 else
3960 issue_deauth(padapter, psta->phl_sta->mac_addr, reason);
3961 }
3962 }
3963
3964 #ifdef CONFIG_RTW_MESH
3965 if (MLME_IS_MESH(padapter))
3966 rtw_mesh_path_flush_by_nexthop(psta);
3967 #endif
3968
3969 #ifdef CONFIG_80211N_HT
3970 psta->htpriv.agg_enable_bitmap = 0x0;/* reset */
3971 psta->htpriv.candidate_tid_bitmap = 0x0;/* reset */
3972 #endif
3973
3974 /* clear cam entry / key */
3975 rtw_clearstakey_cmd(padapter, psta, enqueue);
3976
3977
3978 _rtw_spinlock_bh(&psta->lock);
3979 psta->state &= ~(WIFI_ASOC_STATE | WIFI_UNDER_KEY_HANDSHAKE);
3980
3981 #ifdef CONFIG_IOCTL_CFG80211
3982 if ((psta->auth_len != 0) && (psta->pauth_frame != NULL)) {
3983 rtw_mfree(psta->pauth_frame, psta->auth_len);
3984 psta->pauth_frame = NULL;
3985 psta->auth_len = 0;
3986 }
3987
3988 if (psta->passoc_req && psta->assoc_req_len > 0) {
3989 rtw_mfree(psta->passoc_req, psta->assoc_req_len);
3990 psta->passoc_req = NULL;
3991 psta->assoc_req_len = 0;
3992 }
3993 #endif /* CONFIG_IOCTL_CFG80211 */
3994 _rtw_spinunlock_bh(&psta->lock);
3995
3996 if (!MLME_IS_MESH(padapter)) {
3997 #ifdef CONFIG_RTW_WDS
3998 rtw_wds_path_flush_by_nexthop(psta);
3999 #endif
4000
4001 #ifdef CONFIG_IOCTL_CFG80211
4002 #ifdef COMPAT_KERNEL_RELEASE
4003 rtw_cfg80211_indicate_sta_disassoc(padapter, psta->phl_sta->mac_addr, reason);
4004 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) && !defined(CONFIG_CFG80211_FORCE_COMPATIBLE_2_6_37_UNDER)
4005 rtw_cfg80211_indicate_sta_disassoc(padapter, psta->phl_sta->mac_addr, reason);
4006 #else /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) && !defined(CONFIG_CFG80211_FORCE_COMPATIBLE_2_6_37_UNDER) */
4007 /* will call rtw_cfg80211_indicate_sta_disassoc() in cmd_thread for old API context */
4008 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) && !defined(CONFIG_CFG80211_FORCE_COMPATIBLE_2_6_37_UNDER) */
4009 #else
4010 rtw_indicate_sta_disassoc_event(padapter, psta);
4011 #endif
4012 }
4013
4014 beacon_updated = bss_cap_update_on_sta_leave(padapter, psta);
4015
4016 report_del_sta_event(padapter, psta->phl_sta->mac_addr, reason, enqueue, _FALSE);
4017
4018 return beacon_updated;
4019
4020 }
4021
rtw_ap_inform_ch_switch(_adapter * padapter,u8 new_ch,u8 ch_offset)4022 int rtw_ap_inform_ch_switch(_adapter *padapter, u8 new_ch, u8 ch_offset)
4023 {
4024 _list *phead, *plist;
4025 int ret = 0;
4026 struct sta_info *psta = NULL;
4027 struct sta_priv *pstapriv = &padapter->stapriv;
4028 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4029 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
4030 u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
4031
4032 if ((pmlmeinfo->state & 0x03) != WIFI_FW_AP_STATE)
4033 return ret;
4034
4035 RTW_INFO(FUNC_NDEV_FMT" with ch:%u, offset:%u\n",
4036 FUNC_NDEV_ARG(padapter->pnetdev), new_ch, ch_offset);
4037
4038 _rtw_spinlock_bh(&pstapriv->asoc_list_lock);
4039 phead = &pstapriv->asoc_list;
4040 plist = get_next(phead);
4041
4042 /* for each sta in asoc_queue */
4043 while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {
4044 psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);
4045 plist = get_next(plist);
4046
4047 issue_action_spct_ch_switch(padapter, psta->phl_sta->mac_addr, new_ch, ch_offset);
4048 psta->expire_to = ((pstapriv->expire_to * 2) > 5) ? 5 : (pstapriv->expire_to * 2);
4049 }
4050 _rtw_spinunlock_bh(&pstapriv->asoc_list_lock);
4051
4052 issue_action_spct_ch_switch(padapter, bc_addr, new_ch, ch_offset);
4053
4054 return ret;
4055 }
4056
rtw_sta_flush(_adapter * padapter,bool enqueue)4057 int rtw_sta_flush(_adapter *padapter, bool enqueue)
4058 {
4059 _list *phead, *plist;
4060 int ret = 0;
4061 struct sta_info *psta = NULL;
4062 struct sta_priv *pstapriv = &padapter->stapriv;
4063 u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
4064 u8 flush_num = 0;
4065 char flush_list[NUM_STA];
4066 int i;
4067
4068 if (!MLME_IS_AP(padapter) && !MLME_IS_MESH(padapter))
4069 return ret;
4070
4071 /* pick sta from sta asoc_queue */
4072 _rtw_spinlock_bh(&pstapriv->asoc_list_lock);
4073 phead = &pstapriv->asoc_list;
4074 plist = get_next(phead);
4075 while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {
4076 int stainfo_offset;
4077
4078 psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);
4079 plist = get_next(plist);
4080
4081 rtw_list_delete(&psta->asoc_list);
4082 pstapriv->asoc_list_cnt--;
4083 #ifdef CONFIG_RTW_TOKEN_BASED_XMIT
4084 if (psta->tbtx_enable)
4085 pstapriv->tbtx_asoc_list_cnt--;
4086 #endif
4087 STA_SET_MESH_PLINK(psta, NULL);
4088
4089 stainfo_offset = rtw_stainfo_offset(pstapriv, psta);
4090 if (stainfo_offset_valid(stainfo_offset))
4091 flush_list[flush_num++] = stainfo_offset;
4092 else
4093 rtw_warn_on(1);
4094 }
4095 _rtw_spinunlock_bh(&pstapriv->asoc_list_lock);
4096
4097 RTW_INFO(FUNC_NDEV_FMT" flush_num:%d\n", FUNC_NDEV_ARG(padapter->pnetdev), flush_num);
4098
4099 /* call ap_free_sta() for each sta picked */
4100 for (i = 0; i < flush_num; i++) {
4101 u8 sta_addr[ETH_ALEN];
4102
4103 psta = rtw_get_stainfo_by_offset(pstapriv, flush_list[i]);
4104 if (psta != NULL) {
4105 _rtw_memcpy(sta_addr, psta->phl_sta->mac_addr, ETH_ALEN);
4106 ap_free_sta(padapter, psta, _TRUE, WLAN_REASON_DEAUTH_LEAVING, enqueue, _FALSE);
4107 }
4108 #ifdef CONFIG_RTW_MESH
4109 if (MLME_IS_MESH(padapter))
4110 rtw_mesh_expire_peer(padapter, sta_addr);
4111 #endif
4112 }
4113
4114 if (!MLME_IS_MESH(padapter))
4115 issue_deauth(padapter, bc_addr, WLAN_REASON_DEAUTH_LEAVING);
4116
4117 associated_clients_update(padapter, _TRUE, STA_INFO_UPDATE_ALL);
4118
4119 return ret;
4120 }
4121
4122 /* called > TSR LEVEL for USB or SDIO Interface*/
sta_info_update(_adapter * padapter,struct sta_info * psta)4123 void sta_info_update(_adapter *padapter, struct sta_info *psta)
4124 {
4125 int flags = psta->flags;
4126 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
4127
4128
4129 /* update wmm cap. */
4130 if (WLAN_STA_WME & flags)
4131 psta->qos_option = 1;
4132 else
4133 psta->qos_option = 0;
4134
4135 if (pmlmepriv->qospriv.qos_option == 0)
4136 psta->qos_option = 0;
4137
4138
4139 #ifdef CONFIG_80211N_HT
4140 /* update 802.11n ht cap. */
4141 if (WLAN_STA_HT & flags) {
4142 psta->htpriv.ht_option = _TRUE;
4143 psta->qos_option = 1;
4144
4145 psta->htpriv.smps_cap = (psta->htpriv.ht_cap.cap_info & IEEE80211_HT_CAP_SM_PS) >> 2;
4146 } else
4147 psta->htpriv.ht_option = _FALSE;
4148
4149 if (pmlmepriv->htpriv.ht_option == _FALSE)
4150 psta->htpriv.ht_option = _FALSE;
4151 #endif
4152
4153 #ifdef CONFIG_80211AC_VHT
4154 /* update 802.11AC vht cap. */
4155 if (WLAN_STA_VHT & flags)
4156 psta->vhtpriv.vht_option = _TRUE;
4157 else
4158 psta->vhtpriv.vht_option = _FALSE;
4159
4160 if (pmlmepriv->vhtpriv.vht_option == _FALSE)
4161 psta->vhtpriv.vht_option = _FALSE;
4162 #endif
4163
4164 #ifdef CONFIG_80211AX_HE
4165 /* update 802.11AX he cap. */
4166 if (WLAN_STA_HE & flags)
4167 psta->hepriv.he_option = _TRUE;
4168 else
4169 psta->hepriv.he_option = _FALSE;
4170
4171 if (pmlmepriv->hepriv.he_option == _FALSE)
4172 psta->hepriv.he_option = _FALSE;
4173 #endif
4174
4175 update_sta_info_apmode(padapter, psta);
4176 }
4177
4178 /* restore hw setting from sw data structures */
rtw_ap_restore_network(_adapter * padapter)4179 void rtw_ap_restore_network(_adapter *padapter)
4180 {
4181 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4182 struct sta_priv *pstapriv = &padapter->stapriv;
4183 struct sta_info *psta;
4184 struct security_priv *psecuritypriv = &(padapter->securitypriv);
4185 _list *phead, *plist;
4186 u8 chk_alive_num = 0;
4187 char chk_alive_list[NUM_STA];
4188 int i;
4189
4190 rtw_setopmode_cmd(padapter
4191 , MLME_IS_AP(padapter) ? Ndis802_11APMode : Ndis802_11_mesh
4192 , RTW_CMDF_DIRECTLY
4193 );
4194
4195 set_channel_bwmode(padapter,
4196 pmlmeext->chandef.chan,
4197 pmlmeext->chandef.offset,
4198 pmlmeext->chandef.bw,
4199 _FALSE);
4200
4201 rtw_startbss_cmd(padapter, RTW_CMDF_DIRECTLY);
4202
4203 if ((padapter->securitypriv.dot11PrivacyAlgrthm == _TKIP_) ||
4204 (padapter->securitypriv.dot11PrivacyAlgrthm == _AES_)) {
4205 /* restore group key, WEP keys is restored in ips_leave() */
4206 rtw_set_key(padapter, psecuritypriv, psecuritypriv->dot118021XGrpKeyid, 0, _FALSE);
4207 }
4208
4209 _rtw_spinlock_bh(&pstapriv->asoc_list_lock);
4210
4211 phead = &pstapriv->asoc_list;
4212 plist = get_next(phead);
4213
4214 while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {
4215 int stainfo_offset;
4216
4217 psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);
4218 plist = get_next(plist);
4219
4220 stainfo_offset = rtw_stainfo_offset(pstapriv, psta);
4221 if (stainfo_offset_valid(stainfo_offset))
4222 chk_alive_list[chk_alive_num++] = stainfo_offset;
4223 }
4224
4225 _rtw_spinunlock_bh(&pstapriv->asoc_list_lock);
4226
4227 for (i = 0; i < chk_alive_num; i++) {
4228 psta = rtw_get_stainfo_by_offset(pstapriv, chk_alive_list[i]);
4229
4230 if (psta == NULL){
4231 RTW_INFO(FUNC_ADPT_FMT" sta_info is null\n", FUNC_ADPT_ARG(padapter));
4232 } else if (psta->state & WIFI_ASOC_STATE) {
4233 rtw_sta_media_status_rpt(padapter, psta, 1);
4234 /*
4235 rtw_phl_cmd_change_stainfo(adapter_to_dvobj(adapter)->phl,
4236 sta->phl_sta,
4237 STA_CHG_RAMASK,
4238 NULL,
4239 0,
4240 PHL_CMD_DIRECTLY,
4241 0);
4242 */
4243 /* pairwise key */
4244 /* per sta pairwise key and settings */
4245 if ((padapter->securitypriv.dot11PrivacyAlgrthm == _TKIP_) ||
4246 (padapter->securitypriv.dot11PrivacyAlgrthm == _AES_))
4247 rtw_setstakey_cmd(padapter, psta, UNICAST_KEY, _FALSE);
4248 }
4249 }
4250
4251 }
4252
start_ap_mode(_adapter * padapter)4253 void start_ap_mode(_adapter *padapter)
4254 {
4255 int i;
4256 struct sta_info *psta = NULL;
4257 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
4258 struct sta_priv *pstapriv = &padapter->stapriv;
4259 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4260 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
4261 #ifdef CONFIG_CONCURRENT_MODE
4262 struct security_priv *psecuritypriv = &padapter->securitypriv;
4263 #endif
4264
4265 pmlmepriv->update_bcn = _FALSE;
4266
4267 /*init_mlme_ap_info(padapter);*/
4268
4269 pmlmeext->bstart_bss = _FALSE;
4270
4271 pmlmepriv->num_sta_non_erp = 0;
4272
4273 pmlmepriv->num_sta_no_short_slot_time = 0;
4274
4275 pmlmepriv->num_sta_no_short_preamble = 0;
4276
4277 pmlmepriv->num_sta_ht_no_gf = 0;
4278 #ifdef CONFIG_80211N_HT
4279 pmlmepriv->num_sta_no_ht = 0;
4280 #endif /* CONFIG_80211N_HT */
4281 pmlmeinfo->HT_info_enable = 0;
4282 pmlmeinfo->HT_caps_enable = 0;
4283 pmlmeinfo->HT_enable = 0;
4284
4285 pmlmepriv->num_sta_ht_20mhz = 0;
4286 pmlmepriv->num_sta_40mhz_intolerant = 0;
4287 ATOMIC_SET(&pmlmepriv->olbc, _FALSE);
4288 ATOMIC_SET(&pmlmepriv->olbc_ht, _FALSE);
4289
4290 #ifdef CONFIG_80211N_HT
4291 pmlmepriv->ht_20mhz_width_req = _FALSE;
4292 pmlmepriv->ht_intolerant_ch_reported = _FALSE;
4293 pmlmepriv->ht_op_mode = 0;
4294 pmlmepriv->sw_to_20mhz = 0;
4295 #endif
4296
4297 _rtw_memset(pmlmepriv->ext_capab_ie_data, 0, sizeof(pmlmepriv->ext_capab_ie_data));
4298 pmlmepriv->ext_capab_ie_len = 0;
4299
4300 #ifdef CONFIG_CONCURRENT_MODE
4301 psecuritypriv->dot118021x_bmc_cam_id = INVALID_SEC_MAC_CAM_ID;
4302 #endif
4303
4304 for (i = 0 ; i < pstapriv->max_aid; i++)
4305 pstapriv->sta_aid[i] = NULL;
4306
4307 #ifdef CONFIG_RTW_WDS
4308 if (MLME_IS_AP(padapter))
4309 rtw_wds_pathtbl_init(padapter);
4310 #endif
4311
4312 if (rtw_mi_get_ap_num(padapter))
4313 RTW_SET_SCAN_BAND_SKIP(padapter, BAND_5G);
4314 }
4315
stop_ap_mode(_adapter * padapter)4316 void stop_ap_mode(_adapter *padapter)
4317 {
4318 u8 self_action = MLME_ACTION_UNKNOWN;
4319 struct sta_info *psta = NULL;
4320 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
4321 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4322 int chanctx_num = 0;
4323 struct rtw_chan_def chan_def = {0};
4324
4325 RTW_INFO("%s -"ADPT_FMT"\n", __func__, ADPT_ARG(padapter));
4326
4327 if (MLME_IS_AP(padapter))
4328 self_action = MLME_AP_STOPPED;
4329 else if (MLME_IS_MESH(padapter))
4330 self_action = MLME_MESH_STOPPED;
4331 else
4332 rtw_warn_on(1);
4333
4334 pmlmepriv->update_bcn = _FALSE;
4335 /*pmlmeext->bstart_bss = _FALSE;*/
4336 padapter->netif_up = _FALSE;
4337 /* _rtw_spinlock_free(&pmlmepriv->bcn_update_lock); */
4338
4339 /* reset and init security priv , this can refine with rtw_reset_securitypriv */
4340 _rtw_memset((unsigned char *)&padapter->securitypriv, 0, sizeof(struct security_priv));
4341 padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeOpen;
4342 padapter->securitypriv.ndisencryptstatus = Ndis802_11WEPDisabled;
4343
4344 #ifdef CONFIG_DFS_MASTER
4345 rtw_dfs_rd_en_decision(padapter, self_action, 0);
4346 #endif
4347
4348 rtw_rfctl_update_op_mode(adapter_to_rfctl(padapter), BIT(padapter->iface_id), 0);
4349
4350 /* free scan queue */
4351 rtw_free_network_queue(padapter, _TRUE);
4352
4353 #if CONFIG_RTW_MACADDR_ACL
4354 rtw_macaddr_acl_clear(padapter, RTW_ACL_PERIOD_BSS);
4355 #endif
4356
4357 rtw_sta_flush(padapter, _TRUE);
4358
4359 /* free_assoc_sta_resources */
4360 rtw_free_all_stainfo(padapter);
4361
4362 #ifdef CONFIG_RTW_WDS
4363 adapter_set_use_wds(padapter, 0);
4364 #endif
4365 #ifdef CONFIG_RTW_MULTI_AP
4366 padapter->multi_ap = 0;
4367 #endif
4368 rtw_free_mlme_priv_ie_data(pmlmepriv);
4369
4370 pmlmeext->bstart_bss = _FALSE;
4371
4372 rtw_hal_rcr_set_chk_bssid(padapter, self_action);
4373 #ifdef CONFIG_RTW_MULTI_AP
4374 rtw_map_config_monitor(padapter, self_action);
4375 #endif
4376 #if 0
4377 chanctx_num = rtw_phl_chanctx_del(adapter_to_dvobj(padapter)->phl,
4378 padapter->phl_role, &chan_def);
4379
4380 if (chanctx_num && chan_def.chan != 0) {
4381 set_channel_bwmode(padapter, chan_def.chan, chan_def.offset, chan_def.bw, _FALSE);
4382 rtw_mi_update_union_chan_inf(padapter, chan_def.chan, chan_def.offset, chan_def.bw);
4383 }
4384 #endif
4385
4386 #ifdef CONFIG_RTW_WDS
4387 if (MLME_IS_AP(padapter))
4388 rtw_wds_pathtbl_unregister(padapter);
4389 #endif
4390 }
4391
4392 #endif /* CONFIG_NATIVEAP_MLME */
4393
rtw_ap_update_clients_rainfo(struct _ADAPTER * a,enum phl_cmd_type flag)4394 void rtw_ap_update_clients_rainfo(struct _ADAPTER *a, enum phl_cmd_type flag)
4395 {
4396 struct dvobj_priv *d = adapter_to_dvobj(a);
4397 struct mlme_ext_priv *pmlmeext = &(a->mlmeextpriv);
4398 struct sta_priv *pstapriv = &a->stapriv;
4399 struct sta_info *psta;
4400 const struct sta_info *ap_self_psta = rtw_get_stainfo(pstapriv, a->phl_role->mac_addr);
4401 _list *plist, *phead;
4402 u8 i;
4403
4404 /* update RA mask of all clients */
4405 _rtw_spinlock_bh(&pstapriv->sta_hash_lock);
4406 for (i = 0; i < NUM_STA; i++) {
4407 phead = &(pstapriv->sta_hash[i]);
4408 plist = get_next(phead);
4409
4410 while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {
4411 psta = LIST_CONTAINOR(plist, struct sta_info, hash_list);
4412 plist = get_next(plist);
4413
4414 /* no need to update RA info of ap self */
4415 if (psta && psta != ap_self_psta) {
4416 psta->phl_sta->chandef.bw = pmlmeext->chandef.bw;
4417 rtw_phl_cmd_change_stainfo(GET_PHL_INFO(d),
4418 psta->phl_sta,
4419 STA_CHG_RAMASK,
4420 NULL,
4421 0,
4422 flag,
4423 0);
4424 }
4425 }
4426 }
4427 _rtw_spinunlock_bh(&pstapriv->sta_hash_lock);
4428 }
4429
rtw_ap_update_bss_chbw(_adapter * adapter,WLAN_BSSID_EX * bss,u8 ch,u8 bw,u8 offset)4430 void rtw_ap_update_bss_chbw(_adapter *adapter, WLAN_BSSID_EX *bss, u8 ch, u8 bw, u8 offset)
4431 {
4432 #define UPDATE_VHT_CAP 1
4433 #define UPDATE_HT_CAP 1
4434 #ifdef CONFIG_80211AC_VHT
4435 struct vht_priv *vhtpriv = &adapter->mlmepriv.vhtpriv;
4436 #endif
4437 #ifdef CONFIG_80211AX_HE
4438 struct he_priv *hepriv = &adapter->mlmepriv.hepriv;
4439 #endif
4440 {
4441 u8 *p;
4442 int ie_len;
4443 u8 old_ch = bss->Configuration.DSConfig;
4444 bool change_band = _FALSE;
4445
4446 if ((ch <= 14 && old_ch >= 36) || (ch >= 36 && old_ch <= 14))
4447 change_band = _TRUE;
4448
4449 /* update channel in IE */
4450 p = rtw_get_ie((bss->IEs + sizeof(NDIS_802_11_FIXED_IEs)), _DSSET_IE_, &ie_len, (bss->IELength - sizeof(NDIS_802_11_FIXED_IEs)));
4451 if (p && ie_len > 0)
4452 *(p + 2) = ch;
4453
4454 bss->Configuration.DSConfig = ch;
4455
4456 /* band is changed, update ERP, support rate, ext support rate IE */
4457 if (change_band == _TRUE)
4458 change_band_update_ie(adapter, bss, ch);
4459 }
4460
4461 #ifdef CONFIG_80211AX_HE
4462 if (hepriv->he_option == _TRUE) {
4463 /* CONFIG_80211AX_HE_TODO */
4464 }
4465 #endif
4466
4467 #ifdef CONFIG_80211AC_VHT
4468 if (vhtpriv->vht_option == _TRUE) {
4469 u8 *vht_cap_ie, *vht_op_ie;
4470 int vht_cap_ielen, vht_op_ielen;
4471 u8 center_freq;
4472
4473 vht_cap_ie = rtw_get_ie((bss->IEs + sizeof(NDIS_802_11_FIXED_IEs)), WLAN_EID_VHT_CAPABILITY, &vht_cap_ielen, (bss->IELength - sizeof(NDIS_802_11_FIXED_IEs)));
4474 vht_op_ie = rtw_get_ie((bss->IEs + sizeof(NDIS_802_11_FIXED_IEs)), WLAN_EID_VHT_OPERATION, &vht_op_ielen, (bss->IELength - sizeof(NDIS_802_11_FIXED_IEs)));
4475 center_freq = rtw_phl_get_center_ch(ch, bw, offset);
4476
4477 /* update vht cap ie */
4478 if (vht_cap_ie && vht_cap_ielen) {
4479 #if UPDATE_VHT_CAP
4480 /* if ((bw == CHANNEL_WIDTH_160 || bw == CHANNEL_WIDTH_80_80) && pvhtpriv->sgi_160m)
4481 SET_VHT_CAPABILITY_ELE_SHORT_GI160M(pvht_cap_ie + 2, 1);
4482 else */
4483 SET_VHT_CAPABILITY_ELE_SHORT_GI160M(vht_cap_ie + 2, 0);
4484
4485 if (bw >= CHANNEL_WIDTH_80 && vhtpriv->sgi_80m)
4486 SET_VHT_CAPABILITY_ELE_SHORT_GI80M(vht_cap_ie + 2, 1);
4487 else
4488 SET_VHT_CAPABILITY_ELE_SHORT_GI80M(vht_cap_ie + 2, 0);
4489 #endif
4490 }
4491
4492 /* update vht op ie */
4493 if (vht_op_ie && vht_op_ielen) {
4494 if (bw < CHANNEL_WIDTH_80) {
4495 RTW_INFO(FUNC_ADPT_FMT" update VHT 20/40M\n", FUNC_ADPT_ARG(adapter));
4496 SET_VHT_OPERATION_ELE_CHL_WIDTH(vht_op_ie + 2, 0);
4497 SET_VHT_OPERATION_ELE_CHL_CENTER_FREQ1(vht_op_ie + 2, 0);
4498 SET_VHT_OPERATION_ELE_CHL_CENTER_FREQ2(vht_op_ie + 2, 0);
4499 } else if (bw == CHANNEL_WIDTH_80) {
4500 RTW_INFO(FUNC_ADPT_FMT" update VHT 80M, center_freq = %u\n", FUNC_ADPT_ARG(adapter), center_freq);
4501 SET_VHT_OPERATION_ELE_CHL_WIDTH(vht_op_ie + 2, 1);
4502 SET_VHT_OPERATION_ELE_CHL_CENTER_FREQ1(vht_op_ie + 2, center_freq);
4503 SET_VHT_OPERATION_ELE_CHL_CENTER_FREQ2(vht_op_ie + 2, 0);
4504 } else {
4505 RTW_ERR(FUNC_ADPT_FMT" unsupported BW:%u\n", FUNC_ADPT_ARG(adapter), bw);
4506 rtw_warn_on(1);
4507 }
4508 }
4509 }
4510 #endif /* CONFIG_80211AC_VHT */
4511 #ifdef CONFIG_80211N_HT
4512 {
4513 struct ht_priv *htpriv = &adapter->mlmepriv.htpriv;
4514 u8 *ht_cap_ie, *ht_op_ie;
4515 int ht_cap_ielen, ht_op_ielen;
4516
4517 ht_cap_ie = rtw_get_ie((bss->IEs + sizeof(NDIS_802_11_FIXED_IEs)), EID_HTCapability, &ht_cap_ielen, (bss->IELength - sizeof(NDIS_802_11_FIXED_IEs)));
4518 ht_op_ie = rtw_get_ie((bss->IEs + sizeof(NDIS_802_11_FIXED_IEs)), EID_HTInfo, &ht_op_ielen, (bss->IELength - sizeof(NDIS_802_11_FIXED_IEs)));
4519
4520 /* update ht cap ie */
4521 if (ht_cap_ie && ht_cap_ielen) {
4522 #if UPDATE_HT_CAP
4523 if (bw >= CHANNEL_WIDTH_40)
4524 SET_HT_CAP_ELE_CHL_WIDTH(ht_cap_ie + 2, 1);
4525 else
4526 SET_HT_CAP_ELE_CHL_WIDTH(ht_cap_ie + 2, 0);
4527
4528 if (bw >= CHANNEL_WIDTH_40 && htpriv->sgi_40m)
4529 SET_HT_CAP_ELE_SHORT_GI40M(ht_cap_ie + 2, 1);
4530 else
4531 SET_HT_CAP_ELE_SHORT_GI40M(ht_cap_ie + 2, 0);
4532
4533 if (htpriv->sgi_20m)
4534 SET_HT_CAP_ELE_SHORT_GI20M(ht_cap_ie + 2, 1);
4535 else
4536 SET_HT_CAP_ELE_SHORT_GI20M(ht_cap_ie + 2, 0);
4537 #endif
4538 }
4539
4540 /* update ht op ie */
4541 if (ht_op_ie && ht_op_ielen) {
4542 SET_HT_OP_ELE_PRI_CHL(ht_op_ie + 2, ch);
4543 switch (offset) {
4544 case CHAN_OFFSET_UPPER:
4545 SET_HT_OP_ELE_2ND_CHL_OFFSET(ht_op_ie + 2, IEEE80211_SCA);
4546 break;
4547 case CHAN_OFFSET_LOWER:
4548 SET_HT_OP_ELE_2ND_CHL_OFFSET(ht_op_ie + 2, IEEE80211_SCB);
4549 break;
4550 case CHAN_OFFSET_NO_EXT:
4551 default:
4552 break;
4553 SET_HT_OP_ELE_2ND_CHL_OFFSET(ht_op_ie + 2, IEEE80211_SCN);
4554 }
4555
4556 if (bw >= CHANNEL_WIDTH_40)
4557 SET_HT_OP_ELE_STA_CHL_WIDTH(ht_op_ie + 2, 1);
4558 else
4559 SET_HT_OP_ELE_STA_CHL_WIDTH(ht_op_ie + 2, 0);
4560 }
4561 }
4562 #endif /* CONFIG_80211N_HT */
4563 }
4564
rtw_ap_update_chbw_by_ifbmp(struct dvobj_priv * dvobj,u8 ifbmp,u8 cur_ie_ch[],u8 cur_ie_bw[],u8 cur_ie_offset[],u8 dec_ch[],u8 dec_bw[],u8 dec_offset[],const char * caller)4565 static u8 rtw_ap_update_chbw_by_ifbmp(struct dvobj_priv *dvobj, u8 ifbmp
4566 , u8 cur_ie_ch[], u8 cur_ie_bw[], u8 cur_ie_offset[]
4567 , u8 dec_ch[], u8 dec_bw[], u8 dec_offset[]
4568 , const char *caller)
4569 {
4570 _adapter *iface;
4571 struct mlme_ext_priv *mlmeext;
4572 WLAN_BSSID_EX *network;
4573 u8 ifbmp_ch_changed = 0;
4574 int i;
4575
4576 for (i = 0; i < dvobj->iface_nums; i++) {
4577 if (!(ifbmp & BIT(i)) || !dvobj->padapters[i])
4578 continue;
4579
4580 iface = dvobj->padapters[i];
4581 mlmeext = &(iface->mlmeextpriv);
4582
4583 if (MLME_IS_ASOC(iface)) {
4584 RTW_INFO(FUNC_ADPT_FMT" %u,%u,%u => %u,%u,%u%s\n", caller, ADPT_ARG(iface)
4585 , mlmeext->chandef.chan, mlmeext->chandef.bw, mlmeext->chandef.offset
4586 , dec_ch[i], dec_bw[i], dec_offset[i]
4587 , MLME_IS_OPCH_SW(iface) ? " OPCH_SW" : "");
4588 } else {
4589 RTW_INFO(FUNC_ADPT_FMT" %u,%u,%u => %u,%u,%u%s\n", caller, ADPT_ARG(iface)
4590 , cur_ie_ch[i], cur_ie_bw[i], cur_ie_offset[i]
4591 , dec_ch[i], dec_bw[i], dec_offset[i]
4592 , MLME_IS_OPCH_SW(iface) ? " OPCH_SW" : "");
4593 }
4594 }
4595
4596 for (i = 0; i < dvobj->iface_nums; i++) {
4597 if (!(ifbmp & BIT(i)) || !dvobj->padapters[i])
4598 continue;
4599
4600 iface = dvobj->padapters[i];
4601 mlmeext = &(iface->mlmeextpriv);
4602 network = &(mlmeext->mlmext_info.network);
4603
4604 /* ch setting differs from mlmeext.network IE */
4605 if (cur_ie_ch[i] != dec_ch[i]
4606 || cur_ie_bw[i] != dec_bw[i]
4607 || cur_ie_offset[i] != dec_offset[i])
4608 ifbmp_ch_changed |= BIT(i);
4609
4610 /* ch setting differs from existing one */
4611 if (MLME_IS_ASOC(iface)
4612 && (mlmeext->chandef.chan != dec_ch[i]
4613 || mlmeext->chandef.bw != dec_bw[i]
4614 || mlmeext->chandef.offset != dec_offset[i])
4615 ) {
4616 if (rtw_linked_check(iface) == _TRUE) {
4617 #ifdef CONFIG_SPCT_CH_SWITCH
4618 if (1)
4619 rtw_ap_inform_ch_switch(iface, dec_ch[i], dec_offset[i]);
4620 else
4621 #endif
4622 #ifdef CONFIG_ECSA_PHL
4623 if (CHK_ECSA_STATE(iface, ECSA_ST_NONE))
4624 #endif
4625 rtw_sta_flush(iface, _FALSE);
4626 }
4627 }
4628
4629 mlmeext->chandef.chan = dec_ch[i];
4630 mlmeext->chandef.bw = dec_bw[i];
4631 mlmeext->chandef.offset = dec_offset[i];
4632
4633 rtw_ap_update_bss_chbw(iface, network, dec_ch[i], dec_bw[i], dec_offset[i]);
4634 }
4635
4636 return ifbmp_ch_changed;
4637 }
4638
rtw_ap_ch_specific_chk(_adapter * adapter,u8 ch,u8 * bw,u8 * offset,const char * caller)4639 static u8 rtw_ap_ch_specific_chk(_adapter *adapter, u8 ch, u8 *bw, u8 *offset, const char *caller)
4640 {
4641 struct rf_ctl_t *rfctl = adapter_to_rfctl(adapter);
4642 RT_CHANNEL_INFO *chset = adapter_to_chset(adapter);
4643 int ch_idx;
4644 u8 ret = _SUCCESS;
4645
4646 ch_idx = rtw_chset_search_ch(chset, ch);
4647 if (ch_idx < 0) {
4648 RTW_WARN("%s ch:%u doesn't fit in chplan\n", caller, ch);
4649 ret = _FAIL;
4650 goto exit;
4651 }
4652 if (chset[ch_idx].flags & RTW_CHF_NO_IR) {
4653 RTW_WARN("%s ch:%u is passive\n", caller, ch);
4654 ret = _FAIL;
4655 goto exit;
4656 }
4657
4658 rtw_adjust_chbw(adapter, ch, bw, offset);
4659
4660 if (!rtw_get_offset_by_chbw(ch, *bw, offset)) {
4661 RTW_WARN("%s %u,%u has no valid offset\n", caller, ch, *bw);
4662 ret = _FAIL;
4663 goto exit;
4664 }
4665
4666 while (!rtw_chset_is_chbw_valid(chset, ch, *bw, *offset, 0, 0)
4667 || (rtw_rfctl_dfs_domain_unknown(rfctl) && rtw_chset_is_dfs_chbw(chset, ch, *bw, *offset))
4668 ) {
4669 if (*bw > CHANNEL_WIDTH_20)
4670 (*bw)--;
4671 if (*bw == CHANNEL_WIDTH_20) {
4672 *offset = CHAN_OFFSET_NO_EXT;
4673 break;
4674 }
4675 }
4676
4677
4678 if (rtw_rfctl_dfs_domain_unknown(rfctl) && rtw_chset_is_dfs_chbw(chset, ch, *bw, *offset)) {
4679 RTW_WARN("%s DFS channel %u can't be used\n", caller, ch);
4680 ret = _FAIL;
4681 goto exit;
4682 }
4683
4684 exit:
4685 return ret;
4686 }
4687
rtw_ap_choose_chbw(_adapter * adapter,u8 sel_ch,u8 max_bw,u8 cur_ch,u8 * ch,u8 * bw,u8 * offset,bool by_int_info,u8 mesh_only,const char * caller)4688 static bool rtw_ap_choose_chbw(_adapter *adapter, u8 sel_ch, u8 max_bw, u8 cur_ch
4689 , u8 *ch, u8 *bw, u8 *offset, bool by_int_info, u8 mesh_only, const char *caller)
4690 {
4691 struct rf_ctl_t *rfctl = adapter_to_rfctl(adapter);
4692 bool ch_avail = _FALSE;
4693
4694 #if defined(CONFIG_DFS_MASTER)
4695 if (!rtw_rfctl_dfs_domain_unknown(rfctl)) {
4696 if (rfctl->radar_detected
4697 && rfctl->dbg_dfs_choose_dfs_ch_first
4698 ) {
4699 ch_avail = rtw_choose_shortest_waiting_ch(rfctl, sel_ch, max_bw
4700 , ch, bw, offset
4701 , RTW_CHF_DFS, 0
4702 , cur_ch, by_int_info, mesh_only);
4703 if (ch_avail == _TRUE) {
4704 RTW_INFO("%s choose 5G DFS channel for debug\n", caller);
4705 goto exit;
4706 }
4707 }
4708
4709 if (rfctl->radar_detected
4710 && (rfctl->dfs_ch_sel_e_flags || rfctl->dfs_ch_sel_d_flags)
4711 ) {
4712 ch_avail = rtw_choose_shortest_waiting_ch(rfctl, sel_ch, max_bw
4713 , ch, bw, offset
4714 , rfctl->dfs_ch_sel_e_flags, rfctl->dfs_ch_sel_d_flags
4715 , cur_ch, by_int_info, mesh_only);
4716 if (ch_avail == _TRUE) {
4717 RTW_INFO("%s choose with dfs_ch_sel_ e_flags:0x%02x d_flags:0x%02x for debug\n"
4718 , caller, rfctl->dfs_ch_sel_e_flags, rfctl->dfs_ch_sel_d_flags);
4719 goto exit;
4720 }
4721 }
4722
4723 ch_avail = rtw_choose_shortest_waiting_ch(rfctl, sel_ch, max_bw
4724 , ch, bw, offset
4725 , 0, 0
4726 , cur_ch, by_int_info, mesh_only);
4727 } else
4728 #endif /* defined(CONFIG_DFS_MASTER) */
4729 {
4730 ch_avail = rtw_choose_shortest_waiting_ch(rfctl, sel_ch, max_bw
4731 , ch, bw, offset
4732 , 0, RTW_CHF_DFS
4733 , cur_ch, by_int_info, mesh_only);
4734 }
4735 #if defined(CONFIG_DFS_MASTER)
4736 exit:
4737 #endif
4738 if (ch_avail == _FALSE)
4739 RTW_WARN("%s no available channel\n", caller);
4740
4741 return ch_avail;
4742 }
4743
rtw_ap_chbw_decision(_adapter * adapter,u8 ifbmp,u8 excl_ifbmp,s16 req_ch,s8 req_bw,s8 req_offset,struct rtw_chan_def * chdef)4744 u8 rtw_ap_chbw_decision(_adapter *adapter, u8 ifbmp, u8 excl_ifbmp
4745 , s16 req_ch, s8 req_bw, s8 req_offset, struct rtw_chan_def *chdef)
4746 {
4747 struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
4748 RT_CHANNEL_INFO *chset = adapter_to_chset(adapter);
4749 struct rf_ctl_t *rfctl = adapter_to_rfctl(adapter);
4750 bool ch_avail = _FALSE;
4751 u8 cur_ie_ch[CONFIG_IFACE_NUMBER] = {0};
4752 u8 cur_ie_bw[CONFIG_IFACE_NUMBER] = {0};
4753 u8 cur_ie_offset[CONFIG_IFACE_NUMBER] = {0};
4754 u8 dec_ch[CONFIG_IFACE_NUMBER] = {0};
4755 u8 dec_bw[CONFIG_IFACE_NUMBER] = {0};
4756 u8 dec_offset[CONFIG_IFACE_NUMBER] = {0};
4757 u8 u_ch = 0, u_bw = 0, u_offset = 0;
4758 struct mlme_ext_priv *mlmeext;
4759 WLAN_BSSID_EX *network;
4760 struct mi_state mstate;
4761 struct mi_state mstate_others;
4762 bool set_u_ch = _FALSE;
4763 u8 ifbmp_others = 0xFF & ~ifbmp & ~excl_ifbmp;
4764 u8 ifbmp_ch_changed = 0;
4765 bool ifbmp_all_mesh = 0;
4766 _adapter *iface;
4767 int i;
4768 #ifdef CONFIG_MCC_MODE
4769 struct rtw_phl_com_t *phl_com = GET_PHL_COM(dvobj);
4770 u8 mcc_sup = phl_com->dev_cap.mcc_sup;
4771 #endif
4772 #ifdef CONFIG_RTW_MESH
4773 for (i = 0; i < dvobj->iface_nums; i++)
4774 if ((ifbmp & BIT(i)) && dvobj->padapters)
4775 if (!MLME_IS_MESH(dvobj->padapters[i]))
4776 break;
4777 ifbmp_all_mesh = i >= dvobj->iface_nums ? 1 : 0;
4778 #endif
4779
4780 RTW_INFO("%s ifbmp:0x%02x excl_ifbmp:0x%02x req:%d,%d,%d\n", __func__
4781 , ifbmp, excl_ifbmp, req_ch, req_bw, req_offset);
4782 rtw_mi_status_by_ifbmp(dvobj, ifbmp, &mstate);
4783 rtw_mi_status_by_ifbmp(dvobj, ifbmp_others, &mstate_others);
4784 RTW_INFO("%s others ld_sta_num:%u, lg_sta_num:%u, ap_num:%u, mesh_num:%u\n"
4785 , __func__, MSTATE_STA_LD_NUM(&mstate_others), MSTATE_STA_LG_NUM(&mstate_others)
4786 , MSTATE_AP_NUM(&mstate_others), MSTATE_MESH_NUM(&mstate_others));
4787
4788 for (i = 0; i < dvobj->iface_nums; i++) {
4789 if (!(ifbmp & BIT(i)) || !dvobj->padapters[i])
4790 continue;
4791 iface = dvobj->padapters[i];
4792 mlmeext = &(iface->mlmeextpriv);
4793 network = &(mlmeext->mlmext_info.network);
4794
4795 /* get current IE channel settings */
4796 rtw_ies_get_chbw(BSS_EX_TLV_IES(network), BSS_EX_TLV_IES_LEN(network)
4797 , &cur_ie_ch[i], &cur_ie_bw[i], &cur_ie_offset[i], 1, 1);
4798
4799 /* prepare temporary channel setting decision */
4800 if (req_ch == 0) {
4801 /* request comes from upper layer, use cur_ie values */
4802 dec_ch[i] = cur_ie_ch[i];
4803 dec_bw[i] = cur_ie_bw[i];
4804 dec_offset[i] = cur_ie_offset[i];
4805 } else {
4806 /* use chbw of cur_ie updated with specifying req as temporary decision */
4807 dec_ch[i] = (req_ch <= REQ_CH_NONE) ? cur_ie_ch[i] : req_ch;
4808 if (req_bw <= REQ_BW_NONE) {
4809 if (req_bw == REQ_BW_ORI)
4810 dec_bw[i] = iface->mlmepriv.ori_chandef.bw;
4811 else
4812 dec_bw[i] = cur_ie_bw[i];
4813 } else
4814 dec_bw[i] = req_bw;
4815 dec_offset[i] = (req_offset <= REQ_OFFSET_NONE) ? cur_ie_offset[i] : req_offset;
4816 }
4817 }
4818
4819 if (MSTATE_STA_LD_NUM(&mstate_others) || MSTATE_STA_LG_NUM(&mstate_others)
4820 || MSTATE_AP_NUM(&mstate_others) || MSTATE_MESH_NUM(&mstate_others)
4821 ) {
4822 /* has linked/linking STA or has AP/Mesh mode */
4823 rtw_warn_on(!rtw_mi_get_ch_setting_union_by_ifbmp(dvobj, ifbmp_others, &u_ch, &u_bw, &u_offset));
4824 RTW_INFO("%s others union:%u,%u,%u\n", __func__, u_ch, u_bw, u_offset);
4825 }
4826
4827 #ifdef CONFIG_MCC_MODE
4828 if (mcc_sup && req_ch == 0) {
4829 /* will disable MCC in ap starter prepare after v10 merge */
4830 if (rtw_hw_mcc_chk_inprogress(adapter)) {
4831 u8 if_id = adapter->iface_id;
4832
4833 mlmeext = &(adapter->mlmeextpriv);
4834 /* check channel settings are the same */
4835 if (cur_ie_ch[if_id] == mlmeext->chandef.chan
4836 && cur_ie_bw[if_id] == mlmeext->chandef.bw
4837 && cur_ie_offset[if_id] == mlmeext->chandef.offset) {
4838
4839 RTW_INFO(FUNC_ADPT_FMT"req ch settings are the same as current ch setting, go to exit\n"
4840 , FUNC_ADPT_ARG(adapter));
4841 goto exit;
4842 } else {
4843 RTW_WARN(FUNC_ADPT_FMT"request channel settings are different from current channel setting(%d,%d,%d,%d,%d,%d), restart MCC\n"
4844 , FUNC_ADPT_ARG(adapter)
4845 , cur_ie_ch[if_id], cur_ie_bw[if_id], cur_ie_offset[if_id]
4846 , mlmeext->chandef.chan, mlmeext->chandef.bw, mlmeext->chandef.offset);
4847 #if 0
4848 rtw_hal_set_mcc_setting_disconnect(adapter);
4849 #endif
4850 }
4851 }
4852 }
4853 #endif /* CONFIG_MCC_MODE */
4854
4855 if (MSTATE_STA_LG_NUM(&mstate_others) && !MSTATE_STA_LD_NUM(&mstate_others)) {
4856 /* has linking STA but no linked STA */
4857
4858 for (i = 0; i < dvobj->iface_nums; i++) {
4859 if (!(ifbmp & BIT(i)) || !dvobj->padapters[i])
4860 continue;
4861 iface = dvobj->padapters[i];
4862
4863 rtw_adjust_chbw(iface, dec_ch[i], &dec_bw[i], &dec_offset[i]);
4864 #ifdef CONFIG_RTW_MESH
4865 if (MLME_IS_MESH(iface))
4866 rtw_mesh_adjust_chbw(dec_ch[i], &dec_bw[i], &dec_offset[i]);
4867 #endif
4868
4869 if (rtw_is_chbw_grouped(u_ch, u_bw, u_offset, dec_ch[i], dec_bw[i], dec_offset[i])) {
4870 rtw_chset_sync_chbw(chset
4871 , &dec_ch[i], &dec_bw[i], &dec_offset[i]
4872 , &u_ch, &u_bw, &u_offset, 1, 0);
4873 set_u_ch = _TRUE;
4874 } else {
4875 #ifdef CONFIG_MCC_MODE
4876 if (mcc_sup) {
4877 mlmeext = &(iface->mlmeextpriv);
4878 mlmeext->chandef.chan = chdef->chan= dec_ch[i];
4879 mlmeext->chandef.bw = chdef->bw= dec_bw[i];
4880 mlmeext->chandef.offset = chdef->offset= dec_offset[i];
4881
4882 RTW_INFO(FUNC_ADPT_FMT" enable mcc: %u,%u,%u\n", FUNC_ADPT_ARG(iface)
4883 , chdef->chan, chdef->bw, chdef->offset);
4884 goto exit;
4885 }
4886 #endif /* CONFIG_MCC_MODE */
4887 /* set this for possible ch change when join down*/
4888 set_fwstate(&iface->mlmepriv, WIFI_OP_CH_SWITCHING);
4889 }
4890 }
4891
4892 } else if (MSTATE_STA_LD_NUM(&mstate_others)
4893 || MSTATE_AP_NUM(&mstate_others) || MSTATE_MESH_NUM(&mstate_others)
4894 ) {
4895 /* has linked STA mode or AP/Mesh mode */
4896
4897 for (i = 0; i < dvobj->iface_nums; i++) {
4898 if (!(ifbmp & BIT(i)) || !dvobj->padapters[i])
4899 continue;
4900 iface = dvobj->padapters[i];
4901 #ifdef CONFIG_MCC_MODE
4902 if (mcc_sup) {
4903 if (!rtw_is_chbw_grouped(u_ch, u_bw, u_offset, dec_ch[i], dec_bw[i], dec_offset[i])) {
4904 mlmeext = &(iface->mlmeextpriv);
4905 mlmeext->chandef.chan = chdef->chan = dec_ch[i] = cur_ie_ch[i];
4906 mlmeext->chandef.bw = chdef->bw = dec_bw[i] = cur_ie_bw[i];
4907 mlmeext->chandef.offset = chdef->offset = dec_offset[i] = cur_ie_offset[i];
4908 RTW_INFO(FUNC_ADPT_FMT" enable mcc: %u,%u,%u\n", FUNC_ADPT_ARG(iface)
4909 , chdef->chan, chdef->bw, chdef->offset);
4910 goto exit;
4911 }
4912 }
4913 #endif /* CONFIG_MCC_MODE */
4914
4915 rtw_adjust_chbw(iface, u_ch, &dec_bw[i], &dec_offset[i]);
4916 #ifdef CONFIG_RTW_MESH
4917 if (MLME_IS_MESH(iface))
4918 rtw_mesh_adjust_chbw(u_ch, &dec_bw[i], &dec_offset[i]);
4919 #endif
4920
4921 if (req_ch == 0 && dec_bw[i] > u_bw
4922 && rtw_chset_is_dfs_chbw(chset, u_ch, u_bw, u_offset)
4923 ) {
4924 /* request comes from upper layer, prevent from additional channel waiting */
4925 dec_bw[i] = u_bw;
4926 if (dec_bw[i] == CHANNEL_WIDTH_20)
4927 dec_offset[i] = CHAN_OFFSET_NO_EXT;
4928 }
4929
4930 /* follow */
4931 rtw_chset_sync_chbw(chset
4932 , &dec_ch[i], &dec_bw[i], &dec_offset[i]
4933 , &u_ch, &u_bw, &u_offset, 1, 0);
4934 }
4935
4936 set_u_ch = _TRUE;
4937
4938 } else {
4939 /* autonomous decision */
4940 u8 ori_ch = 0;
4941 u8 max_bw;
4942 bool by_int_info;
4943
4944 if (req_ch <= REQ_CH_NONE) /* channel is not specified */
4945 goto choose_chbw;
4946
4947 /* get tmp dec union of ifbmp */
4948 for (i = 0; i < dvobj->iface_nums; i++) {
4949 if (!(ifbmp & BIT(i)) || !dvobj->padapters[i])
4950 continue;
4951 if (u_ch == 0) {
4952 u_ch = dec_ch[i];
4953 u_bw = dec_bw[i];
4954 u_offset = dec_offset[i];
4955 rtw_adjust_chbw(adapter, u_ch, &u_bw, &u_offset);
4956 rtw_get_offset_by_chbw(u_ch, u_bw, &u_offset);
4957 } else {
4958 u8 tmp_ch = dec_ch[i];
4959 u8 tmp_bw = dec_bw[i];
4960 u8 tmp_offset = dec_offset[i];
4961
4962 rtw_adjust_chbw(adapter, tmp_ch, &tmp_bw, &tmp_offset);
4963 rtw_get_offset_by_chbw(tmp_ch, tmp_bw, &tmp_offset);
4964
4965 rtw_warn_on(!rtw_is_chbw_grouped(u_ch, u_bw, u_offset, tmp_ch, tmp_bw, tmp_offset));
4966 rtw_sync_chbw(&tmp_ch, &tmp_bw, &tmp_offset, &u_ch, &u_bw, &u_offset);
4967 }
4968 }
4969
4970 #ifdef CONFIG_RTW_MESH
4971 /* if ifbmp are all mesh, apply bw restriction */
4972 if (ifbmp_all_mesh)
4973 rtw_mesh_adjust_chbw(u_ch, &u_bw, &u_offset);
4974 #endif
4975
4976 RTW_INFO("%s ifbmp:0x%02x tmp union:%u,%u,%u\n", __func__, ifbmp, u_ch, u_bw, u_offset);
4977
4978 /* check if tmp dec union is usable */
4979 if (rtw_ap_ch_specific_chk(adapter, u_ch, &u_bw, &u_offset, __func__) == _FAIL) {
4980 /* channel can't be used */
4981 if (req_ch > 0) {
4982 /* specific channel and not from IE => don't change channel setting */
4983 goto exit;
4984 }
4985 goto choose_chbw;
4986 } else if (rtw_chset_is_chbw_non_ocp(chset, u_ch, u_bw, u_offset)) {
4987 RTW_WARN("%s DFS channel %u,%u under non ocp\n", __func__, u_ch, u_bw);
4988 if (req_ch > 0 && req_bw > REQ_BW_NONE) {
4989 /* change_chbw with specific channel and specific bw, goto update_bss_chbw directly */
4990 goto update_bss_chbw;
4991 }
4992 } else
4993 goto update_bss_chbw;
4994
4995 choose_chbw:
4996 by_int_info = req_ch == REQ_CH_INT_INFO ? 1 : 0;
4997 req_ch = req_ch > 0 ? req_ch : 0;
4998 max_bw = req_bw > REQ_BW_NONE ? req_bw : CHANNEL_WIDTH_20;
4999 for (i = 0; i < dvobj->iface_nums; i++) {
5000 if (!(ifbmp & BIT(i)) || !dvobj->padapters[i])
5001 continue;
5002 iface = dvobj->padapters[i];
5003 mlmeext = &(iface->mlmeextpriv);
5004
5005 if (req_bw <= REQ_BW_NONE) {
5006 if (req_bw == REQ_BW_ORI) {
5007 if (max_bw < iface->mlmepriv.ori_chandef.bw)
5008 max_bw = iface->mlmepriv.ori_chandef.bw;
5009 } else {
5010 if (max_bw < cur_ie_bw[i])
5011 max_bw = cur_ie_bw[i];
5012 }
5013 }
5014
5015 if (MSTATE_AP_NUM(&mstate) || MSTATE_MESH_NUM(&mstate)) {
5016 if (ori_ch == 0)
5017 ori_ch = mlmeext->chandef.chan;
5018 else if (ori_ch != mlmeext->chandef.chan)
5019 rtw_warn_on(1);
5020 } else {
5021 if (ori_ch == 0)
5022 ori_ch = cur_ie_ch[i];
5023 else if (ori_ch != cur_ie_ch[i])
5024 rtw_warn_on(1);
5025 }
5026 }
5027
5028 ch_avail = rtw_ap_choose_chbw(adapter, req_ch, max_bw
5029 , ori_ch, &u_ch, &u_bw, &u_offset, by_int_info, ifbmp_all_mesh, __func__);
5030 if (ch_avail == _FALSE)
5031 goto exit;
5032
5033 update_bss_chbw:
5034 for (i = 0; i < dvobj->iface_nums; i++) {
5035 if (!(ifbmp & BIT(i)) || !dvobj->padapters[i])
5036 continue;
5037 iface = dvobj->padapters[i];
5038
5039 dec_ch[i] = u_ch;
5040 if (dec_bw[i] > u_bw)
5041 dec_bw[i] = u_bw;
5042 if (dec_bw[i] == CHANNEL_WIDTH_20)
5043 dec_offset[i] = CHAN_OFFSET_NO_EXT;
5044 else
5045 dec_offset[i] = u_offset;
5046
5047 #ifdef CONFIG_RTW_MESH
5048 if (MLME_IS_MESH(iface))
5049 rtw_mesh_adjust_chbw(dec_ch[i], &dec_bw[i], &dec_offset[i]);
5050 #endif
5051 }
5052
5053 set_u_ch = _TRUE;
5054 }
5055
5056 ifbmp_ch_changed = rtw_ap_update_chbw_by_ifbmp(dvobj, ifbmp
5057 , cur_ie_ch, cur_ie_bw, cur_ie_offset
5058 , dec_ch, dec_bw, dec_offset
5059 , __func__);
5060
5061 if (u_ch != 0)
5062 RTW_INFO("%s union:%u,%u,%u\n", __func__, u_ch, u_bw, u_offset);
5063
5064 if (rtw_mi_check_fwstate(adapter, WIFI_UNDER_SURVEY)) {
5065 /* scanning, leave ch setting to scan state machine */
5066 set_u_ch = _FALSE;
5067 }
5068
5069 if (set_u_ch == _TRUE) {
5070 chdef->chan= u_ch;
5071 chdef->bw = u_bw;
5072 chdef->offset= u_offset;
5073 }
5074 exit:
5075 return ifbmp_ch_changed;
5076 }
5077
rtw_ap_sta_states_check(_adapter * adapter)5078 u8 rtw_ap_sta_states_check(_adapter *adapter)
5079 {
5080 struct sta_info *psta;
5081 struct sta_priv *pstapriv = &adapter->stapriv;
5082 _list *plist, *phead;
5083 u8 rst = _FALSE;
5084
5085 if (!MLME_IS_AP(adapter) && !MLME_IS_MESH(adapter))
5086 return _FALSE;
5087
5088 if (pstapriv->auth_list_cnt !=0)
5089 return _TRUE;
5090
5091 _rtw_spinlock_bh(&pstapriv->asoc_list_lock);
5092 phead = &pstapriv->asoc_list;
5093 plist = get_next(phead);
5094 while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {
5095
5096 psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);
5097 plist = get_next(plist);
5098
5099 if (!(psta->state & WIFI_ASOC_STATE)) {
5100 RTW_INFO(ADPT_FMT"- SoftAP/Mesh - sta under linking, its state = 0x%x\n", ADPT_ARG(adapter), psta->state);
5101 rst = _TRUE;
5102 break;
5103 } else if (psta->state & WIFI_UNDER_KEY_HANDSHAKE) {
5104 RTW_INFO(ADPT_FMT"- SoftAP/Mesh - sta under key handshaking, its state = 0x%x\n", ADPT_ARG(adapter), psta->state);
5105 rst = _TRUE;
5106 break;
5107 }
5108 }
5109 _rtw_spinunlock_bh(&pstapriv->asoc_list_lock);
5110 return rst;
5111 }
5112
rtw_ap_parse_sta_capability(_adapter * adapter,struct sta_info * sta,u8 * cap)5113 void rtw_ap_parse_sta_capability(_adapter *adapter, struct sta_info *sta, u8 *cap)
5114 {
5115 sta->capability = RTW_GET_LE16(cap);
5116 if (sta->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
5117 sta->flags |= WLAN_STA_SHORT_PREAMBLE;
5118 else
5119 sta->flags &= ~WLAN_STA_SHORT_PREAMBLE;
5120 }
5121
rtw_ap_parse_sta_supported_rates(_adapter * adapter,struct sta_info * sta,u8 * tlv_ies,u16 tlv_ies_len)5122 u16 rtw_ap_parse_sta_supported_rates(_adapter *adapter, struct sta_info *sta, u8 *tlv_ies, u16 tlv_ies_len)
5123 {
5124 u8 rate_set[12];
5125 u8 rate_num;
5126 int i;
5127 u16 status = _STATS_SUCCESSFUL_;
5128
5129 rtw_ies_get_supported_rate(tlv_ies, tlv_ies_len, rate_set, &rate_num);
5130 if (rate_num == 0) {
5131 RTW_INFO(FUNC_ADPT_FMT" sta "MAC_FMT" with no supported rate\n"
5132 , FUNC_ADPT_ARG(adapter), MAC_ARG(sta->phl_sta->mac_addr));
5133 status = _STATS_FAILURE_;
5134 goto exit;
5135 }
5136
5137 _rtw_memcpy(sta->bssrateset, rate_set, rate_num);
5138 sta->bssratelen = rate_num;
5139
5140 if (MLME_IS_AP(adapter)) {
5141 /* this function force only CCK rates to be bassic rate... */
5142 UpdateBrateTblForSoftAP(sta->bssrateset, sta->bssratelen);
5143 }
5144
5145 /* if (hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G) */ /* ? */
5146 sta->flags |= WLAN_STA_NONERP;
5147 for (i = 0; i < sta->bssratelen; i++) {
5148 if ((sta->bssrateset[i] & 0x7f) > 22) {
5149 sta->flags &= ~WLAN_STA_NONERP;
5150 break;
5151 }
5152 }
5153
5154 exit:
5155 return status;
5156 }
5157
rtw_ap_parse_sta_security_ie(_adapter * adapter,struct sta_info * sta,struct rtw_ieee802_11_elems * elems)5158 u16 rtw_ap_parse_sta_security_ie(_adapter *adapter, struct sta_info *sta, struct rtw_ieee802_11_elems *elems)
5159 {
5160 struct security_priv *sec = &adapter->securitypriv;
5161 u8 *wpa_ie;
5162 int wpa_ie_len;
5163 int group_cipher = 0, pairwise_cipher = 0, gmcs = 0;
5164 u32 akm = 0;
5165 u8 mfp_opt = MFP_NO;
5166 u8 spp_opt = 0;
5167 u16 status = _STATS_SUCCESSFUL_;
5168
5169 sta->dot8021xalg = 0;
5170 sta->wpa_psk = 0;
5171 sta->wpa_group_cipher = 0;
5172 sta->wpa2_group_cipher = 0;
5173 sta->wpa_pairwise_cipher = 0;
5174 sta->wpa2_pairwise_cipher = 0;
5175 sta->akm_suite_type = 0;
5176 _rtw_memset(sta->wpa_ie, 0, sizeof(sta->wpa_ie));
5177
5178 if ((sec->wpa_psk & BIT(1)) && elems->rsn_ie) {
5179 wpa_ie = elems->rsn_ie;
5180 wpa_ie_len = elems->rsn_ie_len;
5181
5182 if (rtw_parse_wpa2_ie(wpa_ie - 2, wpa_ie_len + 2, &group_cipher, &pairwise_cipher, &gmcs, &akm, &mfp_opt, &spp_opt) == _SUCCESS) {
5183 sta->dot8021xalg = 1;/* psk, todo:802.1x */
5184 sta->wpa_psk |= BIT(1);
5185
5186 /* RSN optional field absent; the validation is already checked in rtw_rsne_info_parse() */
5187 if (!group_cipher) {
5188 RTW_INFO("STA lacks WPA2 Group Suite Cipher --> Default\n");
5189 group_cipher = sec->wpa2_group_cipher;
5190 }
5191 if (!pairwise_cipher) {
5192 RTW_INFO("STA lacks WPA2 Pairwise Suite Cipher --> Default\n");
5193 pairwise_cipher = sec->wpa2_pairwise_cipher;
5194 }
5195 if (!akm) {
5196 RTW_INFO("STA lacks WPA2 AKM Cipher --> Default\n");
5197 akm = sec->akmp;
5198 }
5199
5200 sta->wpa2_group_cipher = group_cipher & sec->wpa2_group_cipher;
5201 sta->wpa2_pairwise_cipher = pairwise_cipher & sec->wpa2_pairwise_cipher;
5202 sta->akm_suite_type = akm;
5203
5204 if (MLME_IS_AP(adapter) && (CHECK_BIT(WLAN_AKM_TYPE_SAE, akm)) && (MFP_NO == mfp_opt)) {
5205 status = WLAN_STATUS_ROBUST_MGMT_FRAME_POLICY_VIOLATION;
5206 goto exit;
5207 }
5208
5209 /* RSN optional field exists but no match */
5210 if (!sta->wpa2_group_cipher) {
5211 status = WLAN_STATUS_GROUP_CIPHER_NOT_VALID;
5212 goto exit;
5213 }
5214 if (!sta->wpa2_pairwise_cipher) {
5215 status = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID;
5216 goto exit;
5217 }
5218 if (MLME_IS_AP(adapter) && (!CHECK_BIT(sec->akmp, akm))) {
5219 status = WLAN_STATUS_AKMP_NOT_VALID;
5220 goto exit;
5221 }
5222 }
5223 else {
5224 status = WLAN_STATUS_INVALID_IE;
5225 goto exit;
5226 }
5227 }
5228 else if ((sec->wpa_psk & BIT(0)) && elems->wpa_ie) {
5229 wpa_ie = elems->wpa_ie;
5230 wpa_ie_len = elems->wpa_ie_len;
5231
5232 if (rtw_parse_wpa_ie(wpa_ie - 2, wpa_ie_len + 2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) {
5233 sta->dot8021xalg = 1;/* psk, todo:802.1x */
5234 sta->wpa_psk |= BIT(0);
5235
5236 sta->wpa_group_cipher = group_cipher & sec->wpa_group_cipher;
5237 sta->wpa_pairwise_cipher = pairwise_cipher & sec->wpa_pairwise_cipher;
5238
5239 if (!sta->wpa_group_cipher) {
5240 status = WLAN_STATUS_GROUP_CIPHER_NOT_VALID;
5241 goto exit;
5242 }
5243
5244 if (!sta->wpa_pairwise_cipher) {
5245 status = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID;
5246 goto exit;
5247 }
5248 } else {
5249 status = WLAN_STATUS_INVALID_IE;
5250 goto exit;
5251 }
5252
5253 } else {
5254 wpa_ie = NULL;
5255 wpa_ie_len = 0;
5256 }
5257
5258 if (sec->dot11PrivacyAlgrthm != _NO_PRIVACY_) {
5259 /*check if amsdu is allowed */
5260 if (rtw_check_amsdu_disable(adapter->registrypriv.amsdu_mode, spp_opt) == _TRUE)
5261 sta->flags |= WLAN_STA_AMSDU_DISABLE;
5262 }
5263 if ((sec->mfp_opt == MFP_REQUIRED && mfp_opt < MFP_OPTIONAL)
5264 || (mfp_opt == MFP_REQUIRED && sec->mfp_opt < MFP_OPTIONAL)
5265 ) {
5266 status = WLAN_STATUS_ROBUST_MGMT_FRAME_POLICY_VIOLATION;
5267 goto exit;
5268 }
5269
5270 #ifdef CONFIG_RTW_MESH
5271 if (MLME_IS_MESH(adapter)) {
5272 /* MFP is mandatory for secure mesh */
5273 if (adapter->mesh_info.mesh_auth_id)
5274 sta->flags |= WLAN_STA_MFP;
5275 } else
5276 #endif
5277 if (sec->mfp_opt >= MFP_OPTIONAL && mfp_opt >= MFP_OPTIONAL)
5278 sta->flags |= WLAN_STA_MFP;
5279
5280 #ifdef CONFIG_IEEE80211W
5281 if ((sta->flags & WLAN_STA_MFP)
5282 && (sec->mfp_opt >= MFP_OPTIONAL && mfp_opt >= MFP_OPTIONAL)
5283 && security_type_bip_to_gmcs(sec->dot11wCipher) != gmcs
5284 ) {
5285 status = WLAN_STATUS_CIPHER_REJECTED_PER_POLICY;
5286 goto exit;
5287 }
5288 #endif
5289
5290 #ifdef CONFIG_IOCTL_CFG80211
5291 if (MLME_IS_AP(adapter) &&
5292 (sec->auth_type == MLME_AUTHTYPE_SAE) &&
5293 (CHECK_BIT(WLAN_AKM_TYPE_SAE, sta->akm_suite_type)) &&
5294 (WLAN_AUTH_OPEN == sta->authalg)) {
5295 /* WPA3-SAE, PMK caching */
5296 if (rtw_cached_pmkid(adapter, sta->phl_sta->mac_addr) == -1) {
5297 RTW_INFO("SAE: No PMKSA cache entry found\n");
5298 status = WLAN_STATUS_INVALID_PMKID;
5299 goto exit;
5300 } else {
5301 RTW_INFO("SAE: PMKSA cache entry found\n");
5302 }
5303 }
5304 #endif /* CONFIG_IOCTL_CFG80211 */
5305
5306 if (!MLME_IS_AP(adapter))
5307 goto exit;
5308
5309 sta->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS);
5310 /* if (hapd->conf->wps_state && wpa_ie == NULL) { */ /* todo: to check ap if supporting WPS */
5311 if (wpa_ie == NULL) {
5312 if (elems->wps_ie) {
5313 RTW_INFO("STA included WPS IE in "
5314 "(Re)Association Request - assume WPS is "
5315 "used\n");
5316 sta->flags |= WLAN_STA_WPS;
5317 /* wpabuf_free(sta->wps_ie); */
5318 /* sta->wps_ie = wpabuf_alloc_copy(elems.wps_ie + 4, */
5319 /* elems.wps_ie_len - 4); */
5320 } else {
5321 RTW_INFO("STA did not include WPA/RSN IE "
5322 "in (Re)Association Request - possible WPS "
5323 "use\n");
5324 sta->flags |= WLAN_STA_MAYBE_WPS;
5325 }
5326
5327 /* AP support WPA/RSN, and sta is going to do WPS, but AP is not ready */
5328 /* that the selected registrar of AP is _FLASE */
5329 if ((sec->wpa_psk > 0)
5330 && (sta->flags & (WLAN_STA_WPS | WLAN_STA_MAYBE_WPS))
5331 ) {
5332 struct mlme_priv *mlme = &adapter->mlmepriv;
5333
5334 if (mlme->wps_beacon_ie) {
5335 u8 selected_registrar = 0;
5336
5337 rtw_get_wps_attr_content(mlme->wps_beacon_ie, mlme->wps_beacon_ie_len, WPS_ATTR_SELECTED_REGISTRAR, &selected_registrar, NULL);
5338
5339 if (!selected_registrar) {
5340 RTW_INFO("selected_registrar is _FALSE , or AP is not ready to do WPS\n");
5341 status = _STATS_UNABLE_HANDLE_STA_;
5342 goto exit;
5343 }
5344 }
5345 }
5346
5347 } else {
5348 int copy_len;
5349
5350 if (sec->wpa_psk == 0) {
5351 RTW_INFO("STA " MAC_FMT
5352 ": WPA/RSN IE in association request, but AP don't support WPA/RSN\n",
5353 MAC_ARG(sta->phl_sta->mac_addr));
5354 status = WLAN_STATUS_INVALID_IE;
5355 goto exit;
5356 }
5357
5358 if (elems->wps_ie) {
5359 RTW_INFO("STA included WPS IE in "
5360 "(Re)Association Request - WPS is "
5361 "used\n");
5362 sta->flags |= WLAN_STA_WPS;
5363 copy_len = 0;
5364 } else
5365 copy_len = ((wpa_ie_len + 2) > sizeof(sta->wpa_ie)) ? (sizeof(sta->wpa_ie)) : (wpa_ie_len + 2);
5366
5367 if (copy_len > 0)
5368 _rtw_memcpy(sta->wpa_ie, wpa_ie - 2, copy_len);
5369 }
5370
5371 exit:
5372 return status;
5373 }
5374
rtw_ap_parse_sta_wmm_ie(_adapter * adapter,struct sta_info * sta,u8 * tlv_ies,u16 tlv_ies_len)5375 void rtw_ap_parse_sta_wmm_ie(_adapter *adapter, struct sta_info *sta, u8 *tlv_ies, u16 tlv_ies_len)
5376 {
5377 struct mlme_priv *mlme = &adapter->mlmepriv;
5378 unsigned char WMM_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01};
5379 u8 *p;
5380
5381 sta->flags &= ~WLAN_STA_WME;
5382 sta->qos_option = 0;
5383 sta->qos_info = 0;
5384 sta->has_legacy_ac = _TRUE;
5385 sta->uapsd_vo = 0;
5386 sta->uapsd_vi = 0;
5387 sta->uapsd_be = 0;
5388 sta->uapsd_bk = 0;
5389
5390 if (!mlme->qospriv.qos_option)
5391 goto exit;
5392
5393 #ifdef CONFIG_RTW_MESH
5394 if (MLME_IS_MESH(adapter)) {
5395 /* QoS is mandatory in mesh */
5396 sta->flags |= WLAN_STA_WME;
5397 }
5398 #endif
5399
5400 p = rtw_get_ie_ex(tlv_ies, tlv_ies_len, WLAN_EID_VENDOR_SPECIFIC, WMM_IE, 6, NULL, NULL);
5401 if (!p)
5402 goto exit;
5403
5404 sta->flags |= WLAN_STA_WME;
5405 sta->qos_option = 1;
5406 sta->qos_info = *(p + 8);
5407 sta->max_sp_len = (sta->qos_info >> 5) & 0x3;
5408
5409 if ((sta->qos_info & 0xf) != 0xf)
5410 sta->has_legacy_ac = _TRUE;
5411 else
5412 sta->has_legacy_ac = _FALSE;
5413
5414 if (sta->qos_info & 0xf) {
5415 if (sta->qos_info & BIT(0))
5416 sta->uapsd_vo = BIT(0) | BIT(1);
5417 else
5418 sta->uapsd_vo = 0;
5419
5420 if (sta->qos_info & BIT(1))
5421 sta->uapsd_vi = BIT(0) | BIT(1);
5422 else
5423 sta->uapsd_vi = 0;
5424
5425 if (sta->qos_info & BIT(2))
5426 sta->uapsd_bk = BIT(0) | BIT(1);
5427 else
5428 sta->uapsd_bk = 0;
5429
5430 if (sta->qos_info & BIT(3))
5431 sta->uapsd_be = BIT(0) | BIT(1);
5432 else
5433 sta->uapsd_be = 0;
5434 }
5435
5436 exit:
5437 return;
5438 }
5439
rtw_ap_parse_sta_ht_ie(_adapter * adapter,struct sta_info * sta,struct rtw_ieee802_11_elems * elems)5440 void rtw_ap_parse_sta_ht_ie(_adapter *adapter, struct sta_info *sta, struct rtw_ieee802_11_elems *elems)
5441 {
5442 struct mlme_priv *mlme = &adapter->mlmepriv;
5443
5444 sta->flags &= ~WLAN_STA_HT;
5445
5446 #ifdef CONFIG_80211N_HT
5447 if (mlme->htpriv.ht_option == _FALSE)
5448 goto exit;
5449
5450 /* save HT capabilities in the sta object */
5451 _rtw_memset(&sta->htpriv.ht_cap, 0, sizeof(struct rtw_ieee80211_ht_cap));
5452 if (elems->ht_capabilities && elems->ht_capabilities_len >= sizeof(struct rtw_ieee80211_ht_cap)) {
5453 sta->flags |= WLAN_STA_HT;
5454 sta->flags |= WLAN_STA_WME;
5455 _rtw_memcpy(&sta->htpriv.ht_cap, elems->ht_capabilities, sizeof(struct rtw_ieee80211_ht_cap));
5456
5457 if (elems->ht_operation && elems->ht_operation_len == HT_OP_IE_LEN) {
5458 _rtw_memcpy(sta->htpriv.ht_op, elems->ht_operation, HT_OP_IE_LEN);
5459 sta->htpriv.op_present = 1;
5460 }
5461 }
5462 exit:
5463 #endif
5464
5465 return;
5466 }
5467
rtw_ap_parse_sta_vht_ie(_adapter * adapter,struct sta_info * sta,struct rtw_ieee802_11_elems * elems)5468 void rtw_ap_parse_sta_vht_ie(_adapter *adapter, struct sta_info *sta, struct rtw_ieee802_11_elems *elems)
5469 {
5470 struct mlme_priv *mlme = &adapter->mlmepriv;
5471
5472 sta->flags &= ~WLAN_STA_VHT;
5473
5474 #ifdef CONFIG_80211AC_VHT
5475 if (mlme->vhtpriv.vht_option == _FALSE)
5476 goto exit;
5477
5478 _rtw_memset(&sta->vhtpriv, 0, sizeof(struct vht_priv));
5479 if (elems->vht_capabilities && elems->vht_capabilities_len == VHT_CAP_IE_LEN) {
5480 sta->flags |= WLAN_STA_VHT;
5481 _rtw_memcpy(sta->vhtpriv.vht_cap, elems->vht_capabilities, VHT_CAP_IE_LEN);
5482
5483 if (elems->vht_operation && elems->vht_operation_len== VHT_OP_IE_LEN) {
5484 _rtw_memcpy(sta->vhtpriv.vht_op, elems->vht_operation, VHT_OP_IE_LEN);
5485 sta->vhtpriv.op_present = 1;
5486 }
5487
5488 if (elems->vht_op_mode_notify && elems->vht_op_mode_notify_len == 1) {
5489 _rtw_memcpy(&sta->vhtpriv.vht_op_mode_notify, elems->vht_op_mode_notify, 1);
5490 sta->vhtpriv.notify_present = 1;
5491 }
5492 }
5493 exit:
5494 #endif
5495
5496 return;
5497 }
5498
rtw_ap_parse_sta_he_ie(_adapter * adapter,struct sta_info * sta,struct rtw_ieee802_11_elems * elems)5499 void rtw_ap_parse_sta_he_ie(_adapter *adapter, struct sta_info *sta, struct rtw_ieee802_11_elems *elems)
5500 {
5501 struct mlme_priv *mlme = &adapter->mlmepriv;
5502
5503 sta->flags &= ~WLAN_STA_HE;
5504
5505 #ifdef CONFIG_80211AX_HE
5506 if (mlme->hepriv.he_option == _FALSE)
5507 goto exit;
5508
5509 _rtw_memset(&sta->hepriv, 0, sizeof(struct he_priv));
5510 if (elems->he_capabilities && (elems->he_capabilities_len <= HE_CAP_ELE_MAX_LEN)) {
5511 sta->flags |= WLAN_STA_HE;
5512 _rtw_memcpy(sta->hepriv.he_cap, elems->he_capabilities, elems->he_capabilities_len);
5513
5514 if (elems->he_operation && (elems->he_operation_len <= HE_OPER_ELE_MAX_LEN)) {
5515 _rtw_memcpy(sta->hepriv.he_op, elems->he_operation, elems->he_operation_len);
5516 sta->hepriv.op_present = 1;
5517 }
5518
5519 #if 0
5520 if (elems->vht_op_mode_notify && elems->vht_op_mode_notify_len == 1) {
5521 _rtw_memcpy(&sta->vhtpriv.vht_op_mode_notify, elems->vht_op_mode_notify, 1);
5522 sta->vhtpriv.notify_present = 1;
5523 }
5524 #endif
5525 }
5526 exit:
5527 #endif
5528
5529 return;
5530 }
5531
rtw_ap_parse_sta_multi_ap_ie(_adapter * adapter,struct sta_info * sta,u8 * ies,int ies_len)5532 void rtw_ap_parse_sta_multi_ap_ie(_adapter *adapter, struct sta_info *sta, u8 *ies, int ies_len)
5533 {
5534 sta->flags &= ~WLAN_STA_MULTI_AP;
5535
5536 #ifdef CONFIG_RTW_MULTI_AP
5537 if (adapter->multi_ap
5538 && (rtw_get_multi_ap_ie_ext(ies, ies_len) & MULTI_AP_BACKHAUL_STA)
5539 ) {
5540 if (adapter->multi_ap & MULTI_AP_BACKHAUL_BSS) /* with backhaul bss, enable WDS */
5541 sta->flags |= WLAN_STA_MULTI_AP | WLAN_STA_WDS;
5542 else if (adapter->multi_ap & MULTI_AP_FRONTHAUL_BSS) /* fronthaul bss only */
5543 sta->flags |= WLAN_STA_MULTI_AP;
5544 }
5545 #endif
5546 }
5547
5548 #if CONFIG_RTW_AP_DATA_BMC_TO_UC
rtw_ap_data_bmc_to_uc(_adapter * adapter,const u8 * da,const u8 * sa,const u8 * ori_ta,u16 os_qid,_list * b2u_list)5549 static bool rtw_ap_data_bmc_to_uc(_adapter *adapter
5550 , const u8 *da, const u8 *sa, const u8 *ori_ta
5551 , u16 os_qid, _list *b2u_list)
5552 {
5553 struct sta_priv *stapriv = &adapter->stapriv;
5554 struct xmit_priv *xmitpriv = &adapter->xmitpriv;
5555 _list *head, *list;
5556 struct sta_info *sta;
5557 char b2u_sta_id[NUM_STA];
5558 u8 b2u_sta_num = 0;
5559 bool bmc_need = _FALSE;
5560 int i;
5561
5562 _rtw_spinlock_bh(&stapriv->asoc_list_lock);
5563 head = &stapriv->asoc_list;
5564 list = get_next(head);
5565
5566 while ((rtw_end_of_queue_search(head, list)) == _FALSE) {
5567 int stainfo_offset;
5568
5569 sta = LIST_CONTAINOR(list, struct sta_info, asoc_list);
5570 list = get_next(list);
5571
5572 stainfo_offset = rtw_stainfo_offset(stapriv, sta);
5573 if (stainfo_offset_valid(stainfo_offset))
5574 b2u_sta_id[b2u_sta_num++] = stainfo_offset;
5575 }
5576 _rtw_spinunlock_bh(&stapriv->asoc_list_lock);
5577
5578 if (!b2u_sta_num)
5579 goto exit;
5580
5581 for (i = 0; i < b2u_sta_num; i++) {
5582 struct xmit_frame *b2uframe = NULL;
5583 struct pkt_attrib *attrib;
5584
5585 sta = rtw_get_stainfo_by_offset(stapriv, b2u_sta_id[i]);
5586 if (!(sta->state & WIFI_ASOC_STATE)
5587 || _rtw_memcmp(sta->phl_sta->mac_addr, sa, ETH_ALEN) == _TRUE
5588 || (ori_ta && _rtw_memcmp(sta->phl_sta->mac_addr, ori_ta, ETH_ALEN) == _TRUE)
5589 || is_broadcast_mac_addr(sta->phl_sta->mac_addr)
5590 || is_zero_mac_addr(sta->phl_sta->mac_addr))
5591 continue;
5592
5593 if (core_tx_alloc_xmitframe(adapter, &b2uframe, os_qid) == FAIL) {
5594 bmc_need = _TRUE;
5595 break;
5596 }
5597
5598 attrib = &b2uframe->attrib;
5599
5600 _rtw_memcpy(attrib->ra, sta->phl_sta->mac_addr, ETH_ALEN);
5601 _rtw_memcpy(attrib->ta, adapter_mac_addr(adapter), ETH_ALEN);
5602 #ifdef CONFIG_RTW_WDS
5603 if (adapter_use_wds(adapter) && (sta->flags & WLAN_STA_WDS)) {
5604 _rtw_memcpy(attrib->dst, da, ETH_ALEN);
5605 attrib->wds = 1;
5606 } else
5607 #endif
5608 _rtw_memcpy(attrib->dst, attrib->ra, ETH_ALEN);
5609 _rtw_memcpy(attrib->src, sa, ETH_ALEN);
5610
5611 rtw_list_insert_tail(&b2uframe->list, b2u_list);
5612 }
5613
5614 exit:
5615 return bmc_need;
5616 }
5617
dump_ap_b2u_flags(void * sel,_adapter * adapter)5618 void dump_ap_b2u_flags(void *sel, _adapter *adapter)
5619 {
5620 RTW_PRINT_SEL(sel, "%4s %4s\n", "src", "fwd");
5621 RTW_PRINT_SEL(sel, "0x%02x 0x%02x\n", adapter->b2u_flags_ap_src, adapter->b2u_flags_ap_fwd);
5622 }
5623 #endif /* CONFIG_RTW_AP_DATA_BMC_TO_UC */
5624
rtw_ap_nexthop_resolve(_adapter * adapter,struct xmit_frame * xframe)5625 static int rtw_ap_nexthop_resolve(_adapter *adapter, struct xmit_frame *xframe)
5626 {
5627 struct pkt_attrib *attrib = &xframe->attrib;
5628 int ret = _SUCCESS;
5629
5630 #ifdef CONFIG_RTW_WDS
5631 if (adapter_use_wds(adapter)) {
5632 if (rtw_wds_nexthop_lookup(adapter, attrib->dst, attrib->ra) == 0) {
5633 if (_rtw_memcmp(attrib->dst, attrib->ra, ETH_ALEN) == _FALSE)
5634 attrib->wds = 1;
5635 } else {
5636 ret = _FAIL;
5637 }
5638 } else
5639 #endif
5640 _rtw_memcpy(attrib->ra, attrib->dst, ETH_ALEN);
5641
5642 return ret;
5643 }
5644
5645 #ifdef CONFIG_RTW_WDS
rtw_ap_data_flood_for_unknown_da(_adapter * adapter,const u8 * da,const u8 * sa,const u8 * ori_ta,u16 os_qid,_list * f_list)5646 static void rtw_ap_data_flood_for_unknown_da(_adapter *adapter, const u8 *da,
5647 const u8 *sa, const u8 *ori_ta,
5648 u16 os_qid, _list *f_list)
5649 {
5650 struct sta_priv *stapriv = &adapter->stapriv;
5651 struct xmit_priv *xmitpriv = &adapter->xmitpriv;
5652 _list *head, *list;
5653 struct sta_info *sta;
5654 char sta_id[NUM_STA];
5655 u8 sta_num = 0;
5656 int i;
5657
5658 _rtw_spinlock_bh(&stapriv->asoc_list_lock);
5659 head = &stapriv->asoc_list;
5660 list = get_next(head);
5661
5662 while ((rtw_end_of_queue_search(head, list)) == _FALSE) {
5663 int stainfo_offset;
5664
5665 sta = LIST_CONTAINOR(list, struct sta_info, asoc_list);
5666 list = get_next(list);
5667
5668 stainfo_offset = rtw_stainfo_offset(stapriv, sta);
5669 if (stainfo_offset_valid(stainfo_offset))
5670 sta_id[sta_num++] = stainfo_offset;
5671 }
5672
5673 _rtw_spinunlock_bh(&stapriv->asoc_list_lock);
5674
5675 if (!sta_num)
5676 goto exit;
5677
5678 for (i = 0; i < sta_num; i++) {
5679 struct xmit_frame *frame;
5680 struct pkt_attrib *attrib;
5681
5682 sta = rtw_get_stainfo_by_offset(stapriv, sta_id[i]);
5683 if (!(sta->state & WIFI_ASOC_STATE)
5684 || !(sta->flags & WLAN_STA_WDS)
5685 || _rtw_memcmp(sta->phl_sta->mac_addr, sa, ETH_ALEN) == _TRUE
5686 || (ori_ta && _rtw_memcmp(sta->phl_sta->mac_addr, ori_ta, ETH_ALEN) == _TRUE)
5687 || is_broadcast_mac_addr(sta->phl_sta->mac_addr)
5688 || is_zero_mac_addr(sta->phl_sta->mac_addr))
5689 continue;
5690
5691 if (core_tx_alloc_xmitframe(adapter, &frame, os_qid) == FAIL)
5692 break;
5693
5694 attrib = &frame->attrib;
5695
5696 _rtw_memcpy(attrib->ra, sta->phl_sta->mac_addr, ETH_ALEN);
5697 _rtw_memcpy(attrib->ta, adapter_mac_addr(adapter), ETH_ALEN);
5698 _rtw_memcpy(attrib->dst, da, ETH_ALEN);
5699 _rtw_memcpy(attrib->src, sa, ETH_ALEN);
5700 attrib->wds = 1;
5701
5702 rtw_list_insert_tail(&frame->list, f_list);
5703 }
5704
5705 exit:
5706 return;
5707 }
5708 #endif /* CONFIG_RTW_WDS */
5709
rtw_ap_addr_resolve(_adapter * adapter,u16 os_qid,struct xmit_frame * xframe,struct sk_buff * pkt,_list * f_list)5710 int rtw_ap_addr_resolve(_adapter *adapter, u16 os_qid, struct xmit_frame *xframe,
5711 struct sk_buff *pkt, _list *f_list)
5712 {
5713 struct pkt_file pktfile;
5714 struct ethhdr etherhdr;
5715 struct pkt_attrib *attrib;
5716 u8 is_da_mcast;
5717
5718 int res = _SUCCESS;
5719
5720 _rtw_open_pktfile(pkt, &pktfile);
5721 if (_rtw_pktfile_read(&pktfile, (u8 *)ðerhdr, ETH_HLEN) != ETH_HLEN) {
5722 res = _FAIL;
5723 goto exit;
5724 }
5725
5726 xframe->pkt = pkt;
5727 #if defined(CONFIG_RTW_WDS) || CONFIG_RTW_AP_DATA_BMC_TO_UC
5728 _rtw_init_listhead(f_list);
5729 #endif
5730
5731 is_da_mcast = IS_MCAST(etherhdr.h_dest);
5732 if (is_da_mcast) {
5733 #if CONFIG_RTW_AP_DATA_BMC_TO_UC
5734 if (rtw_ap_src_b2u_policy_chk(adapter->b2u_flags_ap_src, etherhdr.h_dest)
5735 && adapter->registrypriv.wifi_spec == 0
5736 && adapter->xmitpriv.free_xmitframe_cnt > (NR_XMITFRAME / 4)) {
5737 if (rtw_ap_data_bmc_to_uc(adapter, etherhdr.h_dest,
5738 etherhdr.h_source, NULL,
5739 os_qid, f_list) == 0) {
5740 res = RTW_ORI_NO_NEED;
5741 goto exit;
5742 }
5743 }
5744 #endif
5745 }
5746
5747 attrib = &xframe->attrib;
5748
5749 _rtw_memcpy(attrib->dst, etherhdr.h_dest, ETH_ALEN);
5750 _rtw_memcpy(attrib->src, etherhdr.h_source, ETH_ALEN);
5751 _rtw_memcpy(attrib->ta, adapter_mac_addr(adapter), ETH_ALEN);
5752
5753 if (is_da_mcast) {
5754 _rtw_memcpy(attrib->ra, attrib->dst, ETH_ALEN);
5755 } else {
5756 res = rtw_ap_nexthop_resolve(adapter, xframe);
5757 #ifdef CONFIG_RTW_WDS
5758 if (res != _SUCCESS) {
5759 /* unknown DA, flood frame to every WDS STA */
5760 rtw_ap_data_flood_for_unknown_da(adapter, etherhdr.h_dest,
5761 etherhdr.h_source, NULL,
5762 os_qid, f_list);
5763 res = RTW_ORI_NO_NEED;
5764 }
5765 #endif
5766 }
5767
5768 exit:
5769 return res;
5770 }
5771
rtw_ap_rx_data_validate_hdr(_adapter * adapter,union recv_frame * rframe,struct sta_info ** sta)5772 int rtw_ap_rx_data_validate_hdr(_adapter *adapter, union recv_frame *rframe, struct sta_info **sta)
5773 {
5774 struct sta_priv *stapriv = &adapter->stapriv;
5775 struct rx_pkt_attrib *rattrib = &rframe->u.hdr.attrib;
5776 u8 *whdr = get_recvframe_data(rframe);
5777 u8 is_ra_bmc = 0;
5778 sint ret = _FAIL;
5779
5780 if (!(MLME_STATE(adapter) & WIFI_ASOC_STATE))
5781 goto exit;
5782
5783 switch (rattrib->to_fr_ds) {
5784 case 2:
5785 if (IS_MCAST(GetAddr1Ptr(whdr)))
5786 goto exit;
5787 _rtw_memcpy(rattrib->ra, GetAddr1Ptr(whdr), ETH_ALEN);
5788 _rtw_memcpy(rattrib->ta, get_addr2_ptr(whdr), ETH_ALEN);
5789 _rtw_memcpy(rattrib->dst, GetAddr3Ptr(whdr), ETH_ALEN); /* may change after checking AMSDU subframe header */
5790 _rtw_memcpy(rattrib->src, get_addr2_ptr(whdr), ETH_ALEN);
5791 _rtw_memcpy(rattrib->bssid, GetAddr1Ptr(whdr), ETH_ALEN);
5792 break;
5793 case 3:
5794 is_ra_bmc = IS_MCAST(GetAddr1Ptr(whdr)) ? 1 : 0;
5795 _rtw_memcpy(rattrib->ra, GetAddr1Ptr(whdr), ETH_ALEN);
5796 _rtw_memcpy(rattrib->ta, get_addr2_ptr(whdr), ETH_ALEN);
5797 _rtw_memcpy(rattrib->dst, GetAddr3Ptr(whdr), ETH_ALEN); /* may change after checking AMSDU subframe header */
5798 _rtw_memcpy(rattrib->src, GetAddr4Ptr(whdr), ETH_ALEN); /* may change after checking AMSDU subframe header */
5799 if (!is_ra_bmc)
5800 _rtw_memcpy(rattrib->bssid, GetAddr1Ptr(whdr), ETH_ALEN);
5801 break;
5802 default:
5803 ret = RTW_RX_HANDLED; /* don't count for drop */
5804 goto exit;
5805 }
5806
5807 *sta = rtw_get_stainfo(stapriv, rattrib->ta);
5808 if (*sta == NULL) {
5809 if (!is_ra_bmc && !IS_RADAR_DETECTED(adapter_to_rfctl(adapter))) {
5810 #ifndef CONFIG_CUSTOMER_ALIBABA_GENERAL
5811 RTW_INFO(FUNC_ADPT_FMT" issue_deauth to "MAC_FMT" with reason(7), unknown TA\n"
5812 , FUNC_ADPT_ARG(adapter), MAC_ARG(rattrib->ta));
5813 issue_deauth(adapter, rattrib->ta, WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
5814 #endif
5815 }
5816 ret = RTW_RX_HANDLED;
5817 goto exit;
5818 }
5819
5820 #ifdef CONFIG_RTW_WDS_AUTO_EN
5821 if (rattrib->to_fr_ds == 3 && !(sta->flags & WLAN_STA_WDS))
5822 sta->flags |= WLAN_STA_WDS;
5823 #endif
5824
5825 process_pwrbit_data(adapter, rframe, *sta);
5826
5827 if ((get_frame_sub_type(whdr) & WIFI_QOS_DATA_TYPE) == WIFI_QOS_DATA_TYPE)
5828 process_wmmps_data(adapter, rframe, *sta);
5829
5830 if (get_frame_sub_type(whdr) & BIT(6)) {
5831 /* No data, will not indicate to upper layer, temporily count it here */
5832 count_rx_stats(adapter, rframe, *sta);
5833 ret = RTW_RX_HANDLED;
5834 goto exit;
5835 }
5836
5837 ret = _SUCCESS;
5838
5839 exit:
5840 return ret;
5841 }
5842
rtw_ap_rx_msdu_act_check(union recv_frame * rframe,const u8 * da,const u8 * sa,u8 * msdu,enum rtw_rx_llc_hdl llc_hdl,struct xmit_frame ** fwd_frame,_list * f_list)5843 int rtw_ap_rx_msdu_act_check(union recv_frame *rframe
5844 , const u8 *da, const u8 *sa
5845 , u8 *msdu, enum rtw_rx_llc_hdl llc_hdl
5846 , struct xmit_frame **fwd_frame, _list *f_list)
5847 {
5848 _adapter *adapter = rframe->u.hdr.adapter;
5849 struct rx_pkt_attrib *rattrib = &rframe->u.hdr.attrib;
5850 struct rtw_wds_path *wpath;
5851 u8 is_da_bmc = IS_MCAST(da);
5852 u8 is_da_self = !is_da_bmc && _rtw_memcmp(da, adapter_mac_addr(adapter), ETH_ALEN);
5853 u8 is_da_peer = 0;
5854 int in_wds_tbl = 0;
5855 u16 os_qid;
5856 struct xmit_frame *xframe;
5857 struct pkt_attrib *xattrib;
5858 u8 fwd_ra[ETH_ALEN] = {0};
5859 int act = 0;
5860
5861 #ifdef CONFIG_RTW_WDS
5862 /* update/create wds info for SA, RA */
5863 if (adapter_use_wds(adapter)
5864 && (rframe->u.hdr.psta->state & WIFI_ASOC_STATE)
5865 && _rtw_memcmp(sa, rframe->u.hdr.psta->phl_sta->mac_addr, ETH_ALEN) == _FALSE
5866 ) {
5867 rtw_rcu_read_lock();
5868 wpath = rtw_wds_path_lookup(adapter, sa);
5869 if (!wpath)
5870 rtw_wds_path_add(adapter, sa, rframe->u.hdr.psta);
5871 else {
5872 rtw_wds_path_assign_nexthop(wpath, rframe->u.hdr.psta);
5873 wpath->last_update = rtw_get_current_time();
5874 }
5875 rtw_rcu_read_unlock();
5876 }
5877 #endif
5878
5879 /* SA is self, need no further process */
5880 if (_rtw_memcmp(sa, adapter_mac_addr(adapter), ETH_ALEN) == _TRUE)
5881 goto exit;
5882
5883 if (is_da_bmc) {
5884 /* DA is bmc addr */
5885 act |= RTW_RX_MSDU_ACT_INDICATE;
5886 #if 0 /* TODO: ap_isolate */
5887 if (adapter->mlmepriv.ap_isolate)
5888 goto exit;
5889 #endif
5890 goto fwd_chk;
5891
5892 }
5893
5894 if (is_da_self) {
5895 /* DA is self, indicate */
5896 act |= RTW_RX_MSDU_ACT_INDICATE;
5897 goto exit;
5898 }
5899
5900 /* DA is not self */
5901 #ifdef CONFIG_RTW_WDS
5902 if (adapter_use_wds(adapter))
5903 in_wds_tbl = rtw_wds_nexthop_lookup(adapter, da, fwd_ra) == 0;
5904 #endif
5905 if (!in_wds_tbl)
5906 is_da_peer = rtw_get_stainfo(&adapter->stapriv, da) ? 1 : 0;
5907
5908 if (in_wds_tbl || is_da_peer) {
5909 /* DA is known (peer or can be forwarded by peer) */
5910 #if 0 /* TODO: ap_isolate */
5911 if (adapter->mlmepriv.ap_isolate) {
5912 #if defined(DBG_RX_DROP_FRAME)
5913 RTW_INFO("DBG_RX_DROP_FRAME "FUNC_ADPT_FMT" DA("MAC_FMT") through peer, ap_isolate\n"
5914 , FUNC_ADPT_ARG(adapter), MAC_ARG(da));
5915 #endif
5916 goto exit;
5917 }
5918 #endif
5919 goto fwd_chk;
5920 }
5921
5922 /* DA is unknown*/
5923 act |= RTW_RX_MSDU_ACT_INDICATE;
5924 #if 0 /* TODO: ap_isolate */
5925 if (adapter->mlmepriv.ap_isolate) {
5926 /*
5927 * unknown DA and ap_isolate, indicate only
5928 * (bridge will not forward packets to originating port)
5929 */
5930 goto exit;
5931 }
5932 #endif
5933
5934 fwd_chk:
5935
5936 if (adapter->stapriv.asoc_list_cnt <= 1)
5937 goto exit;
5938
5939 os_qid = rtw_os_recv_select_queue(msdu, llc_hdl);
5940
5941 #if defined(CONFIG_RTW_WDS) || CONFIG_RTW_AP_DATA_BMC_TO_UC
5942 _rtw_init_listhead(f_list);
5943 #endif
5944
5945 #if CONFIG_RTW_AP_DATA_BMC_TO_UC
5946 if (is_da_bmc) {
5947 if (rtw_ap_fwd_b2u_policy_chk(adapter->b2u_flags_ap_fwd, da, rattrib->to_fr_ds == 3 && !IS_MCAST(rattrib->ra))
5948 && adapter->registrypriv.wifi_spec == 0
5949 && adapter->xmitpriv.free_xmitframe_cnt > (NR_XMITFRAME / 4)
5950 ) {
5951 if (rtw_ap_data_bmc_to_uc(adapter
5952 , da, sa, rframe->u.hdr.psta->phl_sta->mac_addr
5953 , os_qid, f_list) == 0
5954 ) {
5955 if (!rtw_is_list_empty(f_list))
5956 goto set_act_fwd;
5957 else
5958 goto exit;
5959 }
5960 }
5961 } else
5962 #endif
5963 #ifdef CONFIG_RTW_WDS
5964 if (adapter_use_wds(adapter) && !in_wds_tbl && !is_da_peer) {
5965 /* unknown DA, flood frame to every WDS STA except receiving one */
5966 rtw_ap_data_flood_for_unknown_da(adapter
5967 , da, sa, rframe->u.hdr.psta->phl_sta->mac_addr
5968 , os_qid, f_list);
5969 if (!rtw_is_list_empty(f_list))
5970 goto set_act_fwd;
5971 else
5972 goto exit;
5973 } else
5974 #endif
5975 ;
5976
5977 if (core_tx_alloc_xmitframe(adapter, &xframe, os_qid) == FAIL) {
5978 #ifdef DBG_TX_DROP_FRAME
5979 RTW_INFO("DBG_TX_DROP_FRAME "FUNC_ADPT_FMT" core_tx_alloc_xmitframe fail\n"
5980 , FUNC_ADPT_ARG(adapter));
5981 #endif
5982 goto exit;
5983 }
5984
5985 xattrib = &xframe->attrib;
5986
5987 _rtw_memcpy(xattrib->dst, da, ETH_ALEN);
5988 _rtw_memcpy(xattrib->src, sa, ETH_ALEN);
5989 _rtw_memcpy(xattrib->ta, adapter_mac_addr(adapter), ETH_ALEN);
5990
5991 #ifdef CONFIG_RTW_WDS
5992 if (in_wds_tbl && _rtw_memcmp(da, fwd_ra, ETH_ALEN) == _FALSE) {
5993 _rtw_memcpy(xattrib->ra, fwd_ra, ETH_ALEN);
5994 xattrib->wds = 1;
5995 } else
5996 #endif
5997 _rtw_memcpy(xattrib->ra, da, ETH_ALEN);
5998
5999 *fwd_frame = xframe;
6000
6001 #if defined(CONFIG_RTW_WDS) || CONFIG_RTW_AP_DATA_BMC_TO_UC
6002 set_act_fwd:
6003 #endif
6004 act |= RTW_RX_MSDU_ACT_FORWARD;
6005
6006 exit:
6007 return act;
6008 }
6009
6010 #ifdef CONFIG_RTW_TOKEN_BASED_XMIT
rtw_issue_action_token_req(_adapter * padapter,struct sta_info * pstat)6011 void rtw_issue_action_token_req(_adapter *padapter, struct sta_info *pstat)
6012 {
6013 /* Token Request Format
6014 Category code : 1 Byte
6015 Action code : 1 Byte
6016 Element field: 4 Bytes, the duration of data transmission requested for the station.
6017 */
6018
6019 u8 val = 0x0;
6020 u8 category = RTW_WLAN_CATEGORY_TBTX;
6021 u32 tbtx_duration = TBTX_TX_DURATION*1000;
6022 u8 *pframe;
6023 unsigned short *fctrl;
6024 struct xmit_frame *pmgntframe;
6025 struct pkt_attrib *pattrib;
6026 struct rtw_ieee80211_hdr *pwlanhdr;
6027 struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
6028 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
6029 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
6030 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
6031 WLAN_BSSID_EX *pnetwork = &(pmlmeinfo->network);
6032
6033
6034 if (rtw_rfctl_is_tx_blocked_by_ch_waiting(adapter_to_rfctl(padapter)))
6035 return;
6036
6037 RTW_DBG("%s: %6ph\n", __FUNCTION__, pstat->phl_sta->mac_addr);
6038 pmgntframe = alloc_mgtxmitframe(pxmitpriv);
6039 if (pmgntframe == NULL)
6040 return;
6041
6042 /* update attribute */
6043 pattrib = &pmgntframe->attrib;
6044 update_mgnt_tx_rate(padapter, IEEE80211_OFDM_RATE_24MB); // issue action request using OFDM rate? 20190320 Bruce add
6045 update_mgntframe_attrib(padapter, pattrib);
6046
6047 _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
6048
6049 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
6050 pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
6051
6052 fctrl = &(pwlanhdr->frame_ctl);
6053 *(fctrl) = 0;
6054
6055 _rtw_memcpy((void *)GetAddr1Ptr(pwlanhdr), pstat->phl_sta->mac_addr, ETH_ALEN);
6056 _rtw_memcpy((void *)get_addr2_ptr(pwlanhdr), adapter_mac_addr(padapter), ETH_ALEN);
6057 _rtw_memcpy((void *)GetAddr3Ptr(pwlanhdr), get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
6058
6059
6060 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
6061 pmlmeext->mgnt_seq++;
6062 set_frame_sub_type(pframe, WIFI_ACTION);
6063
6064 pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
6065 pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
6066
6067 pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
6068 pframe = rtw_set_fixed_ie(pframe, 1, &(val), &(pattrib->pktlen));
6069 pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *)&(tbtx_duration), &(pattrib->pktlen));
6070
6071 pattrib->last_txcmdsz = pattrib->pktlen;
6072 padapter->stapriv.last_token_holder = pstat;
6073 dump_mgntframe(padapter, pmgntframe);
6074
6075 }
6076 #endif /* CONFIG_RTW_TOKEN_BASED_XMIT */
6077
rtw_ap_set_sta_wmode(_adapter * padapter,struct sta_info * sta)6078 void rtw_ap_set_sta_wmode(_adapter *padapter, struct sta_info *sta)
6079 {
6080 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
6081 WLAN_BSSID_EX *pcur_network = (WLAN_BSSID_EX *)&pmlmepriv->cur_network.network;
6082 enum wlan_mode network_type = WLAN_MD_INVALID;
6083
6084 #ifdef CONFIG_80211AX_HE
6085 if (sta->hepriv.he_option == _TRUE)
6086 network_type = WLAN_MD_11AX;
6087 #endif
6088 #ifdef CONFIG_80211AC_VHT
6089 if (network_type == WLAN_MD_INVALID) {
6090 if (sta->vhtpriv.vht_option == _TRUE)
6091 network_type = WLAN_MD_11AC;
6092 }
6093 #endif
6094 #ifdef CONFIG_80211N_HT
6095 if (network_type == WLAN_MD_INVALID) {
6096 if (sta->htpriv.ht_option == _TRUE)
6097 network_type = WLAN_MD_11N;
6098 }
6099 #endif
6100
6101 if (pcur_network->Configuration.DSConfig > 14)
6102 network_type |= WLAN_MD_11A;
6103 else {
6104 if ((cckratesonly_included(sta->bssrateset, sta->bssratelen)) == _TRUE)
6105 network_type |= WLAN_MD_11B;
6106 else if ((cckrates_included(sta->bssrateset, sta->bssratelen)) == _TRUE)
6107 network_type |= WLAN_MD_11BG;
6108 else
6109 network_type |= WLAN_MD_11G;
6110 }
6111
6112 sta->phl_sta->wmode = network_type;
6113 }
6114
6115 #if defined(CONFIG_RTW_ACS) && defined(WKARD_ACS)
rtw_acs_start(_adapter * padapter)6116 void rtw_acs_start(_adapter *padapter)
6117 {
6118 RTW_INFO(FUNC_ADPT_FMT" not support\n", FUNC_ADPT_ARG(padapter));
6119 }
6120
rtw_acs_stop(_adapter * padapter)6121 void rtw_acs_stop(_adapter *padapter)
6122 {
6123 RTW_INFO(FUNC_ADPT_FMT" not support\n", FUNC_ADPT_ARG(padapter));
6124 }
6125 #endif /* defined(CONFIG_RTW_ACS) && defined(WKARD_ACS) */
6126
6127 #ifdef CONFIG_AP_CMD_DISPR
6128
_ap_start_swch_start_notify(struct _ADAPTER * padapter)6129 static enum rtw_phl_status _ap_start_swch_start_notify(struct _ADAPTER *padapter)
6130 {
6131 struct dvobj_priv *d = adapter_to_dvobj(padapter);
6132 struct rtw_wifi_role_t *role = padapter->phl_role;
6133 enum rtw_phl_status status;
6134 struct phl_msg msg = {0};
6135 struct phl_msg_attribute attr = {0};
6136
6137 SET_MSG_MDL_ID_FIELD(msg.msg_id, PHL_FG_MDL_AP_START);
6138 SET_MSG_EVT_ID_FIELD(msg.msg_id, MSG_EVT_SWCH_START);
6139
6140 msg.band_idx = padapter->phl_role->hw_band;
6141 msg.rsvd[0] = (u8*)role;
6142
6143 status = rtw_phl_send_msg_to_dispr(GET_PHL_INFO(d),
6144 &msg, &attr, NULL);
6145
6146 return status;
6147 }
6148
_ap_start_swch_done_notify_cb(void * priv,struct phl_msg * msg)6149 static void _ap_start_swch_done_notify_cb(void *priv, struct phl_msg *msg)
6150 {
6151 struct _ADAPTER *a = (struct _ADAPTER *)priv;
6152
6153
6154 RTW_DBG(FUNC_ADPT_FMT ": ap_start_cmd_state=%u\n",
6155 FUNC_ADPT_ARG(a), a->ap_start_cmd_state);
6156
6157 if (msg->inbuf) {
6158 rtw_vmfree(msg->inbuf, msg->inlen);
6159 msg->inbuf = NULL;
6160 }
6161 }
6162
6163 static enum rtw_phl_status
_ap_start_swch_done_notify(struct _ADAPTER * a,struct rtw_chan_def * chandef)6164 _ap_start_swch_done_notify(struct _ADAPTER *a, struct rtw_chan_def *chandef)
6165 {
6166 struct dvobj_priv *d = adapter_to_dvobj(a);
6167 struct phl_msg msg = {0};
6168 struct phl_msg_attribute attr = {0};
6169 u8 *info = NULL;
6170 enum rtw_phl_status status;
6171
6172
6173 info = rtw_vmalloc(sizeof(struct rtw_chan_def));
6174 if (!info) {
6175 RTW_ERR(FUNC_ADPT_FMT ": Allocate msg hub buffer fail!\n",
6176 FUNC_ADPT_ARG(a));
6177 return RTW_PHL_STATUS_RESOURCE;
6178 }
6179 _rtw_memcpy(info, chandef, sizeof(struct rtw_chan_def));
6180
6181 SET_MSG_MDL_ID_FIELD(msg.msg_id, PHL_FG_MDL_AP_START);
6182 SET_MSG_EVT_ID_FIELD(msg.msg_id, MSG_EVT_SWCH_DONE);
6183 msg.band_idx = a->phl_role->hw_band;
6184 msg.inbuf = info;
6185 msg.inlen = sizeof(struct rtw_chan_def);
6186
6187 attr.completion.completion = _ap_start_swch_done_notify_cb;
6188 attr.completion.priv = a;
6189
6190 status = rtw_phl_send_msg_to_dispr(GET_PHL_INFO(d),
6191 &msg, &attr, NULL);
6192 if (status != RTW_PHL_STATUS_SUCCESS) {
6193 rtw_vmfree(info, sizeof(struct rtw_chan_def));
6194 RTW_ERR(FUNC_ADPT_FMT ": send_msg_to_dispr fail(0x%x)!\n",
6195 FUNC_ADPT_ARG(a), status);
6196 }
6197
6198 return status;
6199 }
6200
_ap_start_end_notify_cb(void * priv,struct phl_msg * msg)6201 static void _ap_start_end_notify_cb(void *priv, struct phl_msg *msg)
6202 {
6203
6204 if (msg->inbuf) {
6205 rtw_vmfree(msg->inbuf, msg->inlen);
6206 msg->inbuf = NULL;
6207 }
6208 }
6209
6210 static enum rtw_phl_status
_ap_start_end_notify(struct _ADAPTER * padapter,bool success,bool abort)6211 _ap_start_end_notify(struct _ADAPTER *padapter, bool success, bool abort)
6212 {
6213 struct rtw_wifi_role_t *role = padapter->phl_role;
6214 struct dvobj_priv *d = adapter_to_dvobj(padapter);
6215 enum rtw_phl_status status = RTW_PHL_STATUS_SUCCESS;
6216 struct phl_msg msg = {0};
6217 struct phl_msg_attribute attr = {0};
6218 u8 *info = NULL;
6219
6220 RTW_DBG(FUNC_ADPT_FMT ": MSG_EVT_AP_START\n", FUNC_ADPT_ARG(padapter));
6221
6222 info = rtw_vmalloc(sizeof(u8));
6223 if (info == NULL) {
6224 RTW_ERR("%s: alloc buffer failed!\n", __func__);
6225 return RTW_PHL_STATUS_RESOURCE;
6226 }
6227
6228 SET_MSG_MDL_ID_FIELD(msg.msg_id, PHL_FG_MDL_AP_START);
6229 SET_MSG_EVT_ID_FIELD(msg.msg_id, MSG_EVT_AP_START_END);
6230 if (success) {
6231 *info = RTW_PHL_STATUS_SUCCESS;
6232 } else {
6233 *info = RTW_PHL_STATUS_FAILURE;
6234 }
6235
6236 msg.inbuf = info;
6237 msg.inlen = 1;
6238 msg.band_idx = role->hw_band;
6239 msg.rsvd[0] = (u8*)role;
6240
6241 if(abort)
6242 attr.opt = MSG_OPT_SEND_IN_ABORT;
6243 attr.completion.completion = _ap_start_end_notify_cb;
6244 attr.completion.priv = padapter;
6245
6246
6247 status = rtw_phl_send_msg_to_dispr(GET_PHL_INFO(d),
6248 &msg, &attr, NULL);
6249 if (status != RTW_PHL_STATUS_SUCCESS) {
6250 rtw_vmfree(info, sizeof(u8));
6251 RTW_ERR(FUNC_ADPT_FMT ": send_msg_to_dispr fail(0x%x)!\n",
6252 FUNC_ADPT_ARG(padapter), status);
6253 }
6254
6255 return status;
6256 }
6257
ap_free_cmdobj(struct cmd_obj * pcmd)6258 static void ap_free_cmdobj(struct cmd_obj *pcmd)
6259 {
6260 struct _ADAPTER *padapter = pcmd->padapter;
6261
6262 if (!pcmd)
6263 return;
6264
6265
6266 if (pcmd->sctx) {
6267 if (pcmd->res == H2C_SUCCESS)
6268 rtw_sctx_done(&pcmd->sctx);
6269 else
6270 rtw_sctx_done_err(&pcmd->sctx, RTW_SCTX_DONE_CMD_ERROR);
6271 }
6272
6273 rtw_free_cmd_obj(pcmd);
6274
6275 return;
6276 }
6277
_ap_start_cmd_done(struct cmd_obj * pcmd)6278 static void _ap_start_cmd_done(struct cmd_obj *pcmd)
6279 {
6280 struct _ADAPTER *padapter = pcmd->padapter;
6281 struct dvobj_priv *d = adapter_to_dvobj(padapter);
6282 struct rtw_wifi_role_t *role = padapter->phl_role;
6283 enum rtw_phl_status status;
6284
6285 RTW_INFO("%s: +\n", __func__);
6286
6287 if (!padapter->ap_start_cmd_token){
6288 RTW_ERR("%s : token is NULL!\n", __func__);
6289 return;
6290 }
6291
6292 status = rtw_phl_free_cmd_token(GET_PHL_INFO(d),
6293 role->hw_band, &padapter->ap_start_cmd_token);
6294
6295 padapter->ap_start_cmd_token = 0;
6296 padapter->ap_start_cmd_state = 0;
6297
6298 if (status != RTW_PHL_STATUS_SUCCESS)
6299 RTW_ERR(FUNC_ADPT_FMT ": free_cmd_token fail(0x%x)!\n",
6300 FUNC_ADPT_ARG(padapter), status);
6301
6302 ap_free_cmdobj(pcmd);
6303
6304 RTW_INFO("%s: -\n", __func__);
6305 }
6306
rtw_free_bcn_entry(struct _ADAPTER * padapter)6307 enum rtw_phl_status rtw_free_bcn_entry(struct _ADAPTER *padapter){
6308
6309 struct dvobj_priv *d = adapter_to_dvobj(padapter);
6310 enum rtw_phl_status status = RTW_PHL_STATUS_SUCCESS;
6311
6312 #ifdef RTW_PHL_BCN
6313 status = rtw_phl_free_bcn_entry(d->phl, padapter->phl_role);
6314 if (status != RTW_PHL_STATUS_SUCCESS) {
6315 RTW_INFO("%s - phl_free_bcn_entry failed\n", __func__);
6316 }
6317 #endif
6318
6319 return status;
6320 }
6321
_ap_start_req_acquired(void * dispr,void * priv)6322 static enum phl_mdl_ret_code _ap_start_req_acquired(void *dispr, void *priv)
6323 {
6324 struct cmd_obj *pcmd = (struct cmd_obj *)priv;
6325 struct _ADAPTER *padapter = pcmd->padapter;
6326 struct createbss_parm *parm = (struct createbss_parm *)pcmd->parmbuf;
6327 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
6328 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
6329 struct rtw_wifi_role_t *role = padapter->phl_role;
6330 struct rtw_phl_com_t *phl_com = role->phl_com;
6331 struct phl_info_t *phl_info = phl_com->phl_priv;
6332 struct phl_msg msg = {0};
6333 struct phl_msg_attribute attr = {0};
6334 enum rtw_phl_status status = RTW_PHL_STATUS_SUCCESS;
6335
6336 RTW_DBG(FUNC_ADPT_FMT ": +\n", FUNC_ADPT_ARG(padapter));
6337
6338 if ((parm->req_ch == 0 && pmlmeinfo->state == WIFI_FW_AP_STATE)
6339 || parm->req_ch != 0
6340 ){
6341 start_bss_network(padapter, parm);
6342 }
6343
6344 SET_MSG_MDL_ID_FIELD(msg.msg_id, PHL_FG_MDL_AP_START);
6345 SET_MSG_EVT_ID_FIELD(msg.msg_id, MSG_EVT_AP_START_PREPARE);
6346 msg.band_idx = role->hw_band;
6347
6348 status = rtw_phl_send_msg_to_dispr(phl_info,
6349 &msg,
6350 &attr,
6351 NULL);
6352 if (status != RTW_PHL_STATUS_SUCCESS) {
6353 return MDL_RET_FAIL;
6354 } else {
6355 SET_STATUS_FLAG(padapter->ap_start_cmd_state, CMD_APSTART_ACQUIRE);
6356 return MDL_RET_SUCCESS;
6357 }
6358 }
6359
_ap_start_req_abort(void * dispr,void * priv)6360 static enum phl_mdl_ret_code _ap_start_req_abort(void *dispr, void *priv)
6361 {
6362 struct cmd_obj *pcmd = (struct cmd_obj *)priv;
6363 struct _ADAPTER *padapter = pcmd->padapter;
6364 enum rtw_phl_status status = RTW_PHL_STATUS_FAILURE;
6365
6366 if (TEST_STATUS_FLAG(padapter->ap_start_cmd_state, CMD_APSTART_ACQUIRE)) {
6367 status = _ap_start_end_notify(padapter, false, true);
6368 }
6369
6370 padapter->ap_start_cmd_state = 0;
6371 RTW_INFO("%s\n", __func__);
6372 return MDL_RET_SUCCESS;
6373 }
6374
_ap_start_req_ev_hdlr(void * dispr,void * priv,struct phl_msg * msg)6375 static enum phl_mdl_ret_code _ap_start_req_ev_hdlr(void *dispr, void *priv, struct phl_msg* msg)
6376 {
6377 struct cmd_obj *pcmd = (struct cmd_obj *)priv;
6378 struct _ADAPTER *padapter = pcmd->padapter;
6379 struct createbss_parm *parm = (struct createbss_parm *)pcmd->parmbuf;
6380 struct rtw_wifi_role_t *wifi_role = padapter->phl_role;
6381 struct rtw_phl_com_t *phl_com = wifi_role->phl_com;
6382 void *d = phlcom_to_drvpriv(phl_com);
6383 struct phl_msg nextmsg = {0};
6384 enum rtw_phl_status status = RTW_PHL_STATUS_SUCCESS;
6385
6386 RTW_DBG(FUNC_ADPT_FMT ": + msg_id=0x%08x\n",
6387 FUNC_ADPT_ARG(padapter), msg->msg_id);
6388
6389 if (MSG_MDL_ID_FIELD(msg->msg_id) != PHL_FG_MDL_AP_START) {
6390 RTW_INFO(FUNC_ADPT_FMT ": Message is not from ap start module, "
6391 "skip msg_id=0x%08x\n", FUNC_ADPT_ARG(padapter), msg->msg_id);
6392 RTW_DBG(FUNC_ADPT_FMT ": -\n", FUNC_ADPT_ARG(padapter));
6393 return MDL_RET_IGNORE;
6394 }
6395
6396 if (IS_MSG_FAIL(msg->msg_id)) {
6397 RTW_WARN(FUNC_ADPT_FMT ": cmd dispatcher notify cmd failure on "
6398 "msg_id=0x%08x\n", FUNC_ADPT_ARG(padapter), msg->msg_id);
6399 }
6400
6401 SET_MSG_MDL_ID_FIELD(nextmsg.msg_id, PHL_FG_MDL_AP_START);
6402 nextmsg.band_idx = wifi_role->hw_band;
6403
6404 switch(MSG_EVT_ID_FIELD(msg->msg_id)) {
6405 case MSG_EVT_AP_START_PREPARE:
6406 {
6407 RTW_DBG(FUNC_ADPT_FMT ": MSG_EVT_AP_START_PREPARE\n", FUNC_ADPT_ARG(padapter));
6408 status = _ap_start_swch_start_notify(padapter);
6409 if(status != RTW_PHL_STATUS_SUCCESS)
6410 RTW_ERR("%s :: [MSG_EVT_AP_START_PREPARE] rtw_phl_send_msg_to_dispr failed\n", __func__);
6411 break;
6412 }
6413 case MSG_EVT_SWCH_START:
6414 {
6415 RTW_DBG(FUNC_ADPT_FMT ": MSG_EVT_SWCH_START\n", FUNC_ADPT_ARG(padapter));
6416 rtw_core_ap_swch_start(padapter, parm);
6417 status = _ap_start_swch_done_notify(padapter, &wifi_role->chandef);
6418 if(status != RTW_PHL_STATUS_SUCCESS)
6419 RTW_ERR("%s :: [SWCH_START] rtw_phl_send_msg_to_dispr failed\n", __func__);
6420 break;
6421 }
6422
6423 case MSG_EVT_SWCH_DONE:
6424 {
6425 RTW_DBG(FUNC_ADPT_FMT ": MSG_EVT_SWCH_DONE\n", FUNC_ADPT_ARG(padapter));
6426 status = rtw_phl_ap_started(adapter_to_dvobj(padapter)->phl, padapter->phl_role);
6427 if(status != RTW_PHL_STATUS_SUCCESS)
6428 RTW_ERR("%s :: [MSG_EVT_SWCH_DONE] rtw_phl_send_msg_to_dispr failed\n", __func__);
6429 break;
6430 }
6431 case MSG_EVT_AP_START:
6432 {
6433 RTW_DBG(FUNC_ADPT_FMT ": MSG_EVT_AP_START\n", FUNC_ADPT_ARG(padapter));
6434 rtw_core_ap_start(padapter, parm); /* send beacon */
6435 status = _ap_start_end_notify(padapter, true, false);
6436 break;
6437 }
6438
6439 case MSG_EVT_AP_START_END:
6440 {
6441 RTW_DBG(FUNC_ADPT_FMT ": MSG_EVT_AP_START_END\n", FUNC_ADPT_ARG(padapter));
6442 if (msg->inbuf == NULL) {
6443 RTW_WARN("[MSG_EVT_AP_START_END] Msg info buffer NULL!\n");
6444 break;
6445 }
6446
6447 if (*(msg->inbuf) == RTW_PHL_STATUS_FAILURE){
6448 RTW_WARN("[MSG_EVT_AP_START_END] Msg_inbuf is FAIL!\n");
6449 stop_ap_hdl(padapter);
6450 }
6451
6452 _ap_start_cmd_done(pcmd);
6453 break;
6454 }
6455
6456 default:
6457 /* unknown state */
6458 break;
6459 }
6460
6461
6462 if (status != RTW_PHL_STATUS_SUCCESS) {
6463 /* Trigger stop AP flow when start AP failure */
6464 stop_ap_hdl(padapter);
6465 _ap_start_cmd_done(pcmd);
6466 }
6467
6468 return MDL_RET_SUCCESS;
6469 }
6470
_ap_start_req_set_info(void * dispr,void * priv,struct phl_module_op_info * info)6471 static enum phl_mdl_ret_code _ap_start_req_set_info(void *dispr, void *priv, struct phl_module_op_info* info)
6472 {
6473 struct cmd_obj *pcmd = (struct cmd_obj *)priv;
6474 struct _ADAPTER *padapter = pcmd->padapter;
6475
6476 RTW_DBG(FUNC_ADPT_FMT ": +\n", FUNC_ADPT_ARG(padapter));
6477 RTW_DBG(FUNC_ADPT_FMT ": -\n", FUNC_ADPT_ARG(padapter));
6478
6479 return MDL_RET_IGNORE;
6480 }
6481
_ap_start_req_query_info(void * dispr,void * priv,struct phl_module_op_info * info)6482 static enum phl_mdl_ret_code _ap_start_req_query_info(void *dispr, void *priv, struct phl_module_op_info* info)
6483 {
6484 struct cmd_obj *pcmd = (struct cmd_obj *)priv;
6485 struct _ADAPTER *padapter = pcmd->padapter;
6486 enum phl_mdl_ret_code ret = MDL_RET_IGNORE;
6487
6488
6489 RTW_DBG(FUNC_ADPT_FMT ": +\n", FUNC_ADPT_ARG(padapter));
6490
6491 switch (info->op_code) {
6492 case FG_REQ_OP_GET_ROLE:
6493 info->outbuf = (u8*)padapter->phl_role;
6494 ret = MDL_RET_SUCCESS;
6495 break;
6496
6497 default:
6498 break;
6499 }
6500
6501 RTW_DBG(FUNC_ADPT_FMT ": -\n", FUNC_ADPT_ARG(padapter));
6502 return ret;
6503 }
6504
rtw_cmd_ap_start_req_init(struct cmd_obj * pcmd,struct phl_cmd_token_req * fgreq)6505 static void rtw_cmd_ap_start_req_init(struct cmd_obj *pcmd, struct phl_cmd_token_req *fgreq)
6506 {
6507 struct _ADAPTER *padapter = pcmd->padapter;
6508 u8 res = _SUCCESS;
6509
6510 /* Fill foreground command request */
6511 fgreq->module_id= PHL_FG_MDL_AP_START;
6512 fgreq->priv = pcmd;
6513 fgreq->role = padapter->phl_role;
6514
6515 fgreq->acquired = _ap_start_req_acquired;
6516 fgreq->abort = _ap_start_req_abort;
6517 fgreq->msg_hdlr = _ap_start_req_ev_hdlr;
6518 fgreq->set_info = _ap_start_req_set_info;
6519 fgreq->query_info = _ap_start_req_query_info;
6520
6521 padapter->ap_start_cmd_state = 0;
6522 padapter->ap_start_cmd_token = 0;
6523
6524 RTW_INFO("%s\n", __func__);
6525 }
6526
rtw_ap_start_cmd(struct cmd_obj * pcmd)6527 enum rtw_phl_status rtw_ap_start_cmd(struct cmd_obj *pcmd)
6528 {
6529 struct _ADAPTER *padapter = pcmd->padapter;
6530 struct phl_cmd_token_req fgreq={0};
6531 struct dvobj_priv *d = adapter_to_dvobj(padapter);
6532 enum rtw_phl_status status;
6533 struct rtw_wifi_role_t *role = padapter->phl_role;
6534
6535 rtw_cmd_ap_start_req_init(pcmd, &fgreq);
6536
6537 RTW_DBG(FUNC_ADPT_FMT ": \n", FUNC_ADPT_ARG(padapter));
6538
6539 /* cmd_dispatcher would copy whole phl_cmd_token_req */
6540 status = rtw_phl_add_cmd_token_req(d->phl, role->hw_band, &fgreq, &padapter->ap_start_cmd_token);
6541 if((status != RTW_PHL_STATUS_SUCCESS) &&
6542 (status != RTW_PHL_STATUS_PENDING))
6543 goto error;
6544
6545 status = RTW_PHL_STATUS_SUCCESS;
6546
6547 error:
6548 return status;
6549
6550 }
6551
_ap_stop_cmd_done(struct cmd_obj * pcmd)6552 static void _ap_stop_cmd_done(struct cmd_obj *pcmd)
6553 {
6554 struct _ADAPTER *padapter = pcmd->padapter;
6555 struct dvobj_priv *d = adapter_to_dvobj(padapter);
6556 struct rtw_wifi_role_t *role = padapter->phl_role;
6557 enum rtw_phl_status status;
6558
6559 RTW_DBG(FUNC_ADPT_FMT ": +\n", FUNC_ADPT_ARG(padapter));
6560
6561 if (!padapter->ap_stop_cmd_token){
6562 RTW_ERR("%s : token is NULL!\n", __func__);
6563 return;
6564 }
6565
6566 status = rtw_phl_free_cmd_token(GET_PHL_INFO(d),
6567 role->hw_band, &padapter->ap_stop_cmd_token);
6568
6569 padapter->ap_stop_cmd_token = 0;
6570 padapter->ap_stop_cmd_state = 0;
6571 if (status != RTW_PHL_STATUS_SUCCESS)
6572 RTW_ERR(FUNC_ADPT_FMT ": free_cmd_token fail(0x%x)!\n",
6573 FUNC_ADPT_ARG(padapter), status);
6574
6575 ap_free_cmdobj(pcmd);
6576
6577 RTW_DBG(FUNC_ADPT_FMT ": -\n", FUNC_ADPT_ARG(padapter));
6578 }
6579
_ap_stop_ap_stop_notify(struct _ADAPTER * adapter)6580 static enum rtw_phl_status _ap_stop_ap_stop_notify(struct _ADAPTER *adapter)
6581 {
6582 struct dvobj_priv *d = adapter_to_dvobj(adapter);
6583 struct rtw_wifi_role_t *role = adapter->phl_role;
6584 enum rtw_phl_status status;
6585 struct phl_msg msg = {0};
6586 struct phl_msg_attribute attr = {0};
6587
6588 SET_MSG_MDL_ID_FIELD(msg.msg_id, PHL_FG_MDL_AP_STOP);
6589 SET_MSG_EVT_ID_FIELD(msg.msg_id, MSG_EVT_AP_STOP);
6590
6591 msg.band_idx = adapter->phl_role->hw_band;
6592 msg.rsvd[0] = (u8*)role;
6593
6594 status = rtw_phl_send_msg_to_dispr(GET_PHL_INFO(d),
6595 &msg, &attr, NULL);
6596
6597 if (status != RTW_PHL_STATUS_SUCCESS) {
6598 RTW_ERR(FUNC_ADPT_FMT ": send_msg_to_dispr fail(0x%x)!\n", FUNC_ADPT_ARG(adapter), status);
6599 }
6600 return status;
6601 }
6602
_ap_stop_abort_notify_cb(void * priv,struct phl_msg * msg)6603 static void _ap_stop_abort_notify_cb(void *priv, struct phl_msg *msg)
6604 {
6605 _adapter *padapter = (_adapter *)priv;
6606 struct dvobj_priv *d = adapter_to_dvobj(padapter);
6607 struct _ADAPTER *adapter = (struct _ADAPTER *)priv;
6608 enum rtw_phl_status phl_status = RTW_PHL_STATUS_SUCCESS;
6609 struct rtw_chan_def chan_def = {0};
6610 u8 chctx_num = 0;
6611
6612 #ifdef RTW_PHL_BCN
6613 phl_status = rtw_phl_free_bcn_entry(d->phl, adapter->phl_role);
6614 if (phl_status != RTW_PHL_STATUS_SUCCESS) {
6615 RTW_INFO("%s - phl_free_bcn_entry failed\n", __func__);
6616 }
6617 #endif
6618 }
6619
_ap_stop_abort_notify(struct _ADAPTER * adapter,bool abort)6620 static enum rtw_phl_status _ap_stop_abort_notify(struct _ADAPTER *adapter, bool abort)
6621 {
6622 struct dvobj_priv *d = adapter_to_dvobj(adapter);
6623 struct rtw_wifi_role_t *role = adapter->phl_role;
6624 enum rtw_phl_status status = RTW_PHL_STATUS_SUCCESS;
6625 struct phl_msg msg = {0};
6626 struct phl_msg_attribute attr = {0};
6627
6628 SET_MSG_MDL_ID_FIELD(msg.msg_id, PHL_FG_MDL_AP_STOP);
6629 SET_MSG_EVT_ID_FIELD(msg.msg_id, MSG_EVT_AP_STOP);
6630 msg.band_idx = role->hw_band;
6631 msg.rsvd[0] = (u8*)role;
6632
6633 if(abort)
6634 attr.opt = MSG_OPT_SEND_IN_ABORT;
6635 attr.completion.completion = _ap_stop_abort_notify_cb;
6636 attr.completion.priv = adapter;
6637
6638 status = rtw_phl_send_msg_to_dispr(d->phl,
6639 &msg,
6640 &attr,
6641 NULL);
6642 if (status != RTW_PHL_STATUS_SUCCESS) {
6643 RTW_INFO("[%s] Abort send msg fail!\n", __func__);
6644 }
6645
6646 return status;
6647 }
6648
_ap_stop_req_acquired(void * dispr,void * priv)6649 static enum phl_mdl_ret_code _ap_stop_req_acquired(void *dispr, void *priv)
6650 {
6651 struct cmd_obj *pcmd = (struct cmd_obj *)priv;
6652 struct _ADAPTER *padapter = pcmd->padapter;
6653 struct rtw_wifi_role_t *role = padapter->phl_role;
6654 struct rtw_phl_com_t *phl_com = role->phl_com;
6655 struct phl_info_t *phl_info = phl_com->phl_priv;
6656 struct phl_msg msg = {0};
6657
6658 RTW_DBG(FUNC_ADPT_FMT ": +\n", FUNC_ADPT_ARG(padapter));
6659
6660 SET_STATUS_FLAG(padapter->ap_stop_cmd_state, CMD_APSTOP_ACQUIRE);
6661
6662 rtw_phl_ap_stop(adapter_to_dvobj(padapter)->phl, role);
6663
6664 RTW_DBG(FUNC_ADPT_FMT ": -\n", FUNC_ADPT_ARG(padapter));
6665
6666 return MDL_RET_SUCCESS;
6667
6668 }
6669
_ap_stop_req_abort(void * dispr,void * priv)6670 static enum phl_mdl_ret_code _ap_stop_req_abort(void *dispr, void *priv)
6671 {
6672 struct cmd_obj *pcmd = (struct cmd_obj *)priv;
6673 struct _ADAPTER *padapter = pcmd->padapter;
6674
6675 if(TEST_STATUS_FLAG(padapter->ap_stop_cmd_state, CMD_APSTOP_STARTED)){
6676 /* case1: MSG_EVT_AP_STOP has been processed*/
6677 }
6678 else if(TEST_STATUS_FLAG(padapter->ap_stop_cmd_state, CMD_APSTOP_ACQUIRE)){
6679 /* case2: MSG_EVT_AP_STOP in msgQ
6680 case3: MSG_EVT_AP_STOP doesn't back to msg_hdlr yet */
6681 if (RTW_PHL_STATUS_SUCCESS != _ap_stop_abort_notify(padapter, true)) {
6682 /* do not execute core_mr_handle because do not know if the I/O operation is acceptable */
6683 //core_mr_delete_chctx(adapter, &chctx_num, &chan_def);
6684 }
6685 }
6686 else{
6687 /* apstop token stay in tokenOpQ */
6688 }
6689
6690 padapter->ap_stop_cmd_state = 0;
6691 RTW_INFO("%s\n", __func__);
6692 return MDL_RET_SUCCESS;
6693 }
6694
_ap_stop_req_ev_hdlr(void * dispr,void * priv,struct phl_msg * msg)6695 static enum phl_mdl_ret_code _ap_stop_req_ev_hdlr(void *dispr, void *priv, struct phl_msg* msg)
6696 {
6697 struct cmd_obj *pcmd = (struct cmd_obj *)priv;
6698 struct _ADAPTER *padapter = pcmd->padapter;
6699 struct rtw_wifi_role_t *wifi_role = padapter->phl_role;
6700 struct rtw_phl_com_t *phl_com = wifi_role->phl_com;
6701 struct phl_info_t *phl_info = phl_com->phl_priv;
6702 void *d = phlcom_to_drvpriv(phl_com);
6703 struct phl_msg nextmsg = {0};
6704 enum rtw_phl_status status = RTW_PHL_STATUS_SUCCESS;
6705
6706 RTW_DBG(FUNC_ADPT_FMT ": + msg_id=0x%08x\n",
6707 FUNC_ADPT_ARG(padapter), msg->msg_id);
6708
6709 if (MSG_MDL_ID_FIELD(msg->msg_id) != PHL_FG_MDL_AP_STOP) {
6710 RTW_INFO(FUNC_ADPT_FMT ": Message is not from ap stop module, "
6711 "skip msg_id=0x%08x\n", FUNC_ADPT_ARG(padapter), msg->msg_id);
6712 RTW_DBG(FUNC_ADPT_FMT ": -\n", FUNC_ADPT_ARG(padapter));
6713 return MDL_RET_IGNORE;
6714 }
6715
6716 if (IS_MSG_FAIL(msg->msg_id)) {
6717 RTW_WARN(FUNC_ADPT_FMT ": cmd dispatcher notify cmd failure on "
6718 "msg_id=0x%08x\n", FUNC_ADPT_ARG(padapter), msg->msg_id);
6719 }
6720
6721 SET_MSG_MDL_ID_FIELD(nextmsg.msg_id, PHL_FG_MDL_AP_STOP);
6722 nextmsg.band_idx = wifi_role->hw_band;
6723
6724 switch(MSG_EVT_ID_FIELD(msg->msg_id)) {
6725 case MSG_EVT_AP_STOP_PREPARE:
6726 {
6727 RTW_DBG(FUNC_ADPT_FMT ": MSG_EVT_AP_STOP_PREPARE\n", FUNC_ADPT_ARG(padapter));
6728 status = _ap_stop_ap_stop_notify(padapter);
6729 if (status != RTW_PHL_STATUS_SUCCESS) {
6730 RTW_ERR("%s :: [MSG_EVT_AP_STOP_PREPARE] ap_stop_notify fail\n", __func__);
6731 _ap_stop_cmd_done(pcmd);
6732 }
6733 break;
6734 }
6735 case MSG_EVT_AP_STOP:
6736 {
6737 RTW_DBG(FUNC_ADPT_FMT ": MSG_EVT_SWCH_START\n", FUNC_ADPT_ARG(padapter));
6738 stop_ap_hdl(padapter);
6739 rtw_phl_ap_stop_resume_hdlr(phl_info, wifi_role);
6740 _ap_stop_cmd_done(pcmd);
6741 break;
6742 }
6743 default:
6744 /* unknown state */
6745 break;
6746 }
6747
6748 return MDL_RET_SUCCESS;
6749 }
6750
_ap_stop_req_set_info(void * dispr,void * priv,struct phl_module_op_info * info)6751 static enum phl_mdl_ret_code _ap_stop_req_set_info(void *dispr, void *priv, struct phl_module_op_info* info)
6752 {
6753 struct cmd_obj *pcmd = (struct cmd_obj *)priv;
6754 struct _ADAPTER *padapter = pcmd->padapter;
6755
6756 RTW_DBG(FUNC_ADPT_FMT ": +\n", FUNC_ADPT_ARG(padapter));
6757 RTW_DBG(FUNC_ADPT_FMT ": -\n", FUNC_ADPT_ARG(padapter));
6758
6759 return MDL_RET_IGNORE;
6760 }
6761
_ap_stop_req_query_info(void * dispr,void * priv,struct phl_module_op_info * info)6762 static enum phl_mdl_ret_code _ap_stop_req_query_info(void *dispr, void *priv, struct phl_module_op_info* info)
6763 {
6764 struct cmd_obj *pcmd = (struct cmd_obj *)priv;
6765 struct _ADAPTER *a = pcmd->padapter;
6766 enum phl_mdl_ret_code ret = MDL_RET_IGNORE;
6767
6768
6769 RTW_DBG(FUNC_ADPT_FMT ": +\n", FUNC_ADPT_ARG(a));
6770
6771 switch (info->op_code) {
6772 case FG_REQ_OP_GET_ROLE:
6773 info->outbuf = (u8*)a->phl_role;
6774 ret = MDL_RET_SUCCESS;
6775 break;
6776
6777 default:
6778 break;
6779 }
6780
6781 RTW_DBG(FUNC_ADPT_FMT ": -\n", FUNC_ADPT_ARG(a));
6782 return ret;
6783 }
6784
rtw_cmd_ap_stop_req_init(struct cmd_obj * pcmd,struct phl_cmd_token_req * fgreq)6785 static void rtw_cmd_ap_stop_req_init(struct cmd_obj *pcmd, struct phl_cmd_token_req *fgreq)
6786 {
6787 struct _ADAPTER *padapter = pcmd->padapter;
6788
6789 RTW_DBG(FUNC_ADPT_FMT ": \n", FUNC_ADPT_ARG(padapter));
6790 /* Fill foreground command request */
6791 fgreq->module_id= PHL_FG_MDL_AP_STOP;
6792 fgreq->priv = pcmd;
6793 fgreq->role = padapter->phl_role;
6794
6795 fgreq->acquired = _ap_stop_req_acquired;
6796 fgreq->abort = _ap_stop_req_abort;
6797 fgreq->msg_hdlr = _ap_stop_req_ev_hdlr;
6798 fgreq->set_info = _ap_stop_req_set_info;
6799 fgreq->query_info = _ap_stop_req_query_info;
6800
6801 padapter->ap_stop_cmd_state = 0;
6802 padapter->ap_stop_cmd_token = 0;
6803 }
6804
rtw_ap_stop_cmd(struct cmd_obj * pcmd)6805 enum rtw_phl_status rtw_ap_stop_cmd(struct cmd_obj *pcmd)
6806 {
6807 struct _ADAPTER *padapter = pcmd->padapter;
6808 struct phl_cmd_token_req fgreq={0};
6809 struct dvobj_priv *d = adapter_to_dvobj(padapter);
6810 enum rtw_phl_status pstatus;
6811 struct rtw_wifi_role_t *role = padapter->phl_role;
6812
6813 RTW_DBG(FUNC_ADPT_FMT ": +\n", FUNC_ADPT_ARG(padapter));
6814
6815 rtw_cmd_ap_stop_req_init(pcmd, &fgreq);
6816
6817 /* cmd_dispatcher would copy whole phl_cmd_token_req */
6818 pstatus = rtw_phl_add_cmd_token_req(d->phl, role->hw_band, &fgreq, &padapter->ap_stop_cmd_token);
6819 if((pstatus != RTW_PHL_STATUS_SUCCESS) &&
6820 (pstatus != RTW_PHL_STATUS_PENDING))
6821 goto error;
6822
6823 pstatus = RTW_PHL_STATUS_SUCCESS;
6824
6825 error:
6826 return pstatus;
6827
6828 }
6829
6830 #endif
6831 #endif /* CONFIG_AP_MODE */
6832