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