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