OSDN Git Service

03508e908f615ee29c7ce905fd74b20fa4b8bd08
[android-x86/external-modules-rtl8723au.git] / core / rtw_ap.c
1 /******************************************************************************
2  *
3  * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
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  * You should have received a copy of the GNU General Public License along with
15  * this program; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
17  *
18  *
19  ******************************************************************************/
20 #define _RTW_AP_C_
21
22 #include <drv_conf.h>
23 #include <osdep_service.h>
24 #include <drv_types.h>
25 #include <wifi.h>
26
27 #ifdef CONFIG_AP_MODE
28
29 extern unsigned char    RTW_WPA_OUI[];
30 extern unsigned char    WMM_OUI[];
31 extern unsigned char    WPS_OUI[];
32 extern unsigned char    P2P_OUI[];
33 extern unsigned char    WFD_OUI[];
34
35 void init_mlme_ap_info(_adapter *padapter)
36 {
37         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
38         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
39         struct sta_priv *pstapriv = &padapter->stapriv;
40         struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;
41
42         spin_lock_init(&pmlmepriv->bcn_update_lock);
43
44         /* for ACL */
45         _rtw_init_queue(&pacl_list->acl_node_q);
46
47         start_ap_mode(padapter);
48 }
49
50 void free_mlme_ap_info(_adapter *padapter)
51 {
52         _irqL irqL;
53         struct sta_info *psta=NULL;
54         struct sta_priv *pstapriv = &padapter->stapriv;
55         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
56         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
57         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
58
59         pmlmepriv->update_bcn = _FALSE;
60         pmlmeext->bstart_bss = _FALSE;
61
62         rtw_sta_flush(padapter);
63
64         pmlmeinfo->state = _HW_STATE_NOLINK_;
65
66         /* free_assoc_sta_resources */
67         rtw_free_all_stainfo(padapter);
68
69         /* free bc/mc sta_info */
70         psta = rtw_get_bcmc_stainfo(padapter);
71         spin_lock_bh(&(pstapriv->sta_hash_lock));
72         rtw_free_stainfo(padapter, psta);
73         spin_unlock_bh(&(pstapriv->sta_hash_lock));
74 }
75
76 static void update_BCNTIM(_adapter *padapter)
77 {
78         struct sta_priv *pstapriv = &padapter->stapriv;
79         struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
80         struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
81         WLAN_BSSID_EX *pnetwork_mlmeext = &(pmlmeinfo->network);
82         unsigned char *pie = pnetwork_mlmeext->IEs;
83         u8 *p, *dst_ie, *premainder_ie=NULL, *pbackup_remainder_ie=NULL;
84         u16 tim_bitmap_le;
85         uint offset, tmp_len, tim_ielen, tim_ie_offset, remainder_ielen;
86
87         tim_bitmap_le = cpu_to_le16(pstapriv->tim_bitmap);
88
89         p = rtw_get_ie(pie + _FIXED_IE_LENGTH_, _TIM_IE_, &tim_ielen, pnetwork_mlmeext->IELength - _FIXED_IE_LENGTH_);
90         if (p != NULL && tim_ielen>0) {
91                 tim_ielen += 2;
92
93                 premainder_ie = p+tim_ielen;
94
95                 tim_ie_offset = (int)(p -pie);
96
97                 remainder_ielen = pnetwork_mlmeext->IELength - tim_ie_offset - tim_ielen;
98
99                 /* append TIM IE from dst_ie offset */
100                 dst_ie = p;
101         } else {
102                 tim_ielen = 0;
103
104                 /* calulate head_len */
105                 offset = _FIXED_IE_LENGTH_;
106
107                 /* get ssid_ie len */
108                 p = rtw_get_ie(pie + _BEACON_IE_OFFSET_, _SSID_IE_, &tmp_len, (pnetwork_mlmeext->IELength - _BEACON_IE_OFFSET_));
109                 if (p != NULL)
110                         offset += tmp_len+2;
111
112                 /*  get supported rates len */
113                 p = rtw_get_ie(pie + _BEACON_IE_OFFSET_, _SUPPORTEDRATES_IE_, &tmp_len, (pnetwork_mlmeext->IELength - _BEACON_IE_OFFSET_));
114                 if (p !=  NULL)
115                         offset += tmp_len+2;
116
117                 /* DS Parameter Set IE, len=3 */
118                 offset += 3;
119
120                 premainder_ie = pie + offset;
121
122                 remainder_ielen = pnetwork_mlmeext->IELength - offset - tim_ielen;
123
124                 /* append TIM IE from offset */
125                 dst_ie = pie + offset;
126         }
127
128         if(remainder_ielen>0) {
129                 pbackup_remainder_ie = rtw_malloc(remainder_ielen);
130                 if(pbackup_remainder_ie && premainder_ie)
131                         memcpy(pbackup_remainder_ie, premainder_ie, remainder_ielen);
132         }
133
134         *dst_ie++=_TIM_IE_;
135
136         if((pstapriv->tim_bitmap&0xff00) && (pstapriv->tim_bitmap&0x00fc))
137                 tim_ielen = 5;
138         else
139                 tim_ielen = 4;
140
141         *dst_ie++= tim_ielen;
142
143         *dst_ie++=0;/* DTIM count */
144         *dst_ie++=1;/* DTIM peroid */
145
146         if(pstapriv->tim_bitmap&BIT(0))/* for bc/mc frames */
147                 *dst_ie++ = BIT(0);/* bitmap ctrl */
148         else
149                 *dst_ie++ = 0;
150
151         if(tim_ielen==4) {
152                 *dst_ie++ = *(u8*)&tim_bitmap_le;
153         } else if(tim_ielen==5) {
154                 memcpy(dst_ie, &tim_bitmap_le, 2);
155                 dst_ie+=2;
156         }
157
158         /* copy remainder IE */
159         if(pbackup_remainder_ie) {
160                 memcpy(dst_ie, pbackup_remainder_ie, remainder_ielen);
161
162                 rtw_mfree(pbackup_remainder_ie, remainder_ielen);
163         }
164
165         offset =  (uint)(dst_ie - pie);
166         pnetwork_mlmeext->IELength = offset + remainder_ielen;
167
168 #ifndef CONFIG_INTERRUPT_BASED_TXBCN
169 #if defined(CONFIG_USB_HCI) || defined(CONFIG_GSPI_HCI)
170         set_tx_beacon_cmd(padapter);
171 #endif
172 #endif /* CONFIG_INTERRUPT_BASED_TXBCN */
173 }
174
175 void rtw_add_bcn_ie(_adapter *padapter, WLAN_BSSID_EX *pnetwork, u8 index, u8 *data, u8 len)
176 {
177         PNDIS_802_11_VARIABLE_IEs       pIE;
178         u8      bmatch = _FALSE;
179         u8      *pie = pnetwork->IEs;
180         u8      *p, *dst_ie, *premainder_ie=NULL, *pbackup_remainder_ie=NULL;
181         u32     i, offset, ielen, ie_offset, remainder_ielen = 0;
182
183         for (i = sizeof(NDIS_802_11_FIXED_IEs); i < pnetwork->IELength;)
184         {
185                 pIE = (PNDIS_802_11_VARIABLE_IEs)(pnetwork->IEs + i);
186
187                 if (pIE->ElementID > index)
188                 {
189                         break;
190                 }
191                 else if(pIE->ElementID == index) /*  already exist the same IE */
192                 {
193                         p = (u8 *)pIE;
194                         ielen = pIE->Length;
195                         bmatch = _TRUE;
196                         break;
197                 }
198
199                 p = (u8 *)pIE;
200                 ielen = pIE->Length;
201                 i += (pIE->Length + 2);
202         }
203
204         if (p != NULL && ielen>0)
205         {
206                 ielen += 2;
207
208                 premainder_ie = p+ielen;
209
210                 ie_offset = (int)(p -pie);
211
212                 remainder_ielen = pnetwork->IELength - ie_offset - ielen;
213
214                 if(bmatch)
215                         dst_ie = p;
216                 else
217                         dst_ie = (p+ielen);
218         }
219
220         if(remainder_ielen>0)
221         {
222                 pbackup_remainder_ie = rtw_malloc(remainder_ielen);
223                 if(pbackup_remainder_ie && premainder_ie)
224                         memcpy(pbackup_remainder_ie, premainder_ie, remainder_ielen);
225         }
226
227         *dst_ie++=index;
228         *dst_ie++=len;
229
230         memcpy(dst_ie, data, len);
231         dst_ie+=len;
232
233         /* copy remainder IE */
234         if(pbackup_remainder_ie)
235         {
236                 memcpy(dst_ie, pbackup_remainder_ie, remainder_ielen);
237
238                 rtw_mfree(pbackup_remainder_ie, remainder_ielen);
239         }
240
241         offset =  (uint)(dst_ie - pie);
242         pnetwork->IELength = offset + remainder_ielen;
243 }
244
245 void rtw_remove_bcn_ie(_adapter *padapter, WLAN_BSSID_EX *pnetwork, u8 index)
246 {
247         u8 *p, *dst_ie, *premainder_ie=NULL, *pbackup_remainder_ie=NULL;
248         uint offset, ielen, ie_offset, remainder_ielen = 0;
249         u8      *pie = pnetwork->IEs;
250
251         p = rtw_get_ie(pie + _FIXED_IE_LENGTH_, index, &ielen, pnetwork->IELength - _FIXED_IE_LENGTH_);
252         if (p != NULL && ielen>0)
253         {
254                 ielen += 2;
255
256                 premainder_ie = p+ielen;
257
258                 ie_offset = (int)(p -pie);
259
260                 remainder_ielen = pnetwork->IELength - ie_offset - ielen;
261
262                 dst_ie = p;
263         }
264
265         if(remainder_ielen>0)
266         {
267                 pbackup_remainder_ie = rtw_malloc(remainder_ielen);
268                 if(pbackup_remainder_ie && premainder_ie)
269                         memcpy(pbackup_remainder_ie, premainder_ie, remainder_ielen);
270         }
271
272         /* copy remainder IE */
273         if(pbackup_remainder_ie)
274         {
275                 memcpy(dst_ie, pbackup_remainder_ie, remainder_ielen);
276
277                 rtw_mfree(pbackup_remainder_ie, remainder_ielen);
278         }
279
280         offset =  (uint)(dst_ie - pie);
281         pnetwork->IELength = offset + remainder_ielen;
282 }
283
284 u8 chk_sta_is_alive(struct sta_info *psta)
285 {
286         u8 ret = _FALSE;
287         #ifdef DBG_EXPIRATION_CHK
288         DBG_8723A("sta:"MAC_FMT", rssi:%d, rx:"STA_PKTS_FMT", expire_to:%u, %s%ssq_len:%u\n"
289                 , MAC_ARG(psta->hwaddr)
290                 , psta->rssi_stat.UndecoratedSmoothedPWDB
291                 , STA_RX_PKTS_DIFF_ARG(psta)
292                 , psta->expire_to
293                 , psta->state&WIFI_SLEEP_STATE?"PS, ":""
294                 , psta->state&WIFI_STA_ALIVE_CHK_STATE?"SAC, ":""
295                 , psta->sleepq_len
296         );
297         #endif
298
299         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))
300                 ret = _TRUE;
301
302         sta_update_last_rx_pkts(psta);
303
304         return ret;
305 }
306
307 void    expire_timeout_chk(_adapter *padapter)
308 {
309         _irqL irqL;
310         _list   *phead, *plist;
311         u8 updated;
312         struct sta_info *psta=NULL;
313         struct sta_priv *pstapriv = &padapter->stapriv;
314         u8 chk_alive_num = 0;
315         char chk_alive_list[NUM_STA];
316         int i;
317
318         spin_lock_bh(&pstapriv->auth_list_lock);
319
320         phead = &pstapriv->auth_list;
321         plist = get_next(phead);
322
323         /* check auth_queue */
324         #ifdef DBG_EXPIRATION_CHK
325         if (rtw_end_of_queue_search(phead, plist) == _FALSE) {
326                 DBG_8723A(FUNC_NDEV_FMT" auth_list, cnt:%u\n"
327                         , FUNC_NDEV_ARG(padapter->pnetdev), pstapriv->auth_list_cnt);
328         }
329         #endif
330         while ((rtw_end_of_queue_search(phead, plist)) == _FALSE)
331         {
332                 psta = LIST_CONTAINOR(plist, struct sta_info, auth_list);
333                 plist = get_next(plist);
334
335                 if(psta->expire_to>0)
336                 {
337                         psta->expire_to--;
338                         if (psta->expire_to == 0)
339                         {
340                                 rtw_list_delete(&psta->auth_list);
341                                 pstapriv->auth_list_cnt--;
342
343                                 DBG_8723A("auth expire %02X%02X%02X%02X%02X%02X\n",
344                                         psta->hwaddr[0],psta->hwaddr[1],psta->hwaddr[2],psta->hwaddr[3],psta->hwaddr[4],psta->hwaddr[5]);
345
346                                 spin_unlock_bh(&pstapriv->auth_list_lock);
347
348                                 spin_lock_bh(&(pstapriv->sta_hash_lock));
349                                 rtw_free_stainfo(padapter, psta);
350                                 spin_unlock_bh(&(pstapriv->sta_hash_lock));
351
352                                 spin_lock_bh(&pstapriv->auth_list_lock);
353                         }
354                 }
355
356         }
357
358         spin_unlock_bh(&pstapriv->auth_list_lock);
359
360         psta = NULL;
361
362         spin_lock_bh(&pstapriv->asoc_list_lock);
363
364         phead = &pstapriv->asoc_list;
365         plist = get_next(phead);
366
367         /* check asoc_queue */
368         #ifdef DBG_EXPIRATION_CHK
369         if (rtw_end_of_queue_search(phead, plist) == _FALSE) {
370                 DBG_8723A(FUNC_NDEV_FMT" asoc_list, cnt:%u\n"
371                         , FUNC_NDEV_ARG(padapter->pnetdev), pstapriv->asoc_list_cnt);
372         }
373         #endif
374         while ((rtw_end_of_queue_search(phead, plist)) == _FALSE)
375         {
376                 psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);
377                 plist = get_next(plist);
378
379                 if (chk_sta_is_alive(psta) || !psta->expire_to) {
380                         psta->expire_to = pstapriv->expire_to;
381                         psta->keep_alive_trycnt = 0;
382                         #ifdef CONFIG_TX_MCAST2UNI
383                         psta->under_exist_checking = 0;
384                         #endif  /*  CONFIG_TX_MCAST2UNI */
385                 } else {
386                         psta->expire_to--;
387                 }
388
389 #ifndef CONFIG_ACTIVE_KEEP_ALIVE_CHECK
390 #ifdef CONFIG_TX_MCAST2UNI
391 #ifdef CONFIG_80211N_HT
392                 if ( (psta->flags & WLAN_STA_HT) && (psta->htpriv.agg_enable_bitmap || psta->under_exist_checking) ) {
393                         /*  check sta by delba(addba) for 11n STA */
394                         /*  ToDo: use CCX report to check for all STAs */
395                         if ( psta->expire_to <= (pstapriv->expire_to - 50 ) ) {
396                                 DBG_8723A("asoc expire by DELBA/ADDBA! (%d s)\n", (pstapriv->expire_to-psta->expire_to)*2);
397                                 psta->under_exist_checking = 0;
398                                 psta->expire_to = 0;
399                         } else if ( psta->expire_to <= (pstapriv->expire_to - 3) && (psta->under_exist_checking==0)) {
400                                 DBG_8723A("asoc check by DELBA/ADDBA! (%d s)\n", (pstapriv->expire_to-psta->expire_to)*2);
401                                 psta->under_exist_checking = 1;
402                                 /* tear down TX AMPDU */
403                                 send_delba(padapter, 1, psta->hwaddr);/*  originator */
404                                 psta->htpriv.agg_enable_bitmap = 0x0;/* reset */
405                                 psta->htpriv.candidate_tid_bitmap = 0x0;/* reset */
406                         }
407                 }
408 #endif /* CONFIG_80211N_HT */
409 #endif /*  CONFIG_TX_MCAST2UNI */
410 #endif /* CONFIG_ACTIVE_KEEP_ALIVE_CHECK */
411
412                 if (psta->expire_to <= 0)
413                 {
414                         #ifdef CONFIG_ACTIVE_KEEP_ALIVE_CHECK
415                         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
416
417                         if (padapter->registrypriv.wifi_spec == 1)
418                         {
419                                 psta->expire_to = pstapriv->expire_to;
420                                 continue;
421                         }
422
423                         if (psta->state & WIFI_SLEEP_STATE) {
424                                 if (!(psta->state & WIFI_STA_ALIVE_CHK_STATE)) {
425                                         /* to check if alive by another methods if staion is at ps mode. */
426                                         psta->expire_to = pstapriv->expire_to;
427                                         psta->state |= WIFI_STA_ALIVE_CHK_STATE;
428
429                                         /* to update bcn with tim_bitmap for this station */
430                                         pstapriv->tim_bitmap |= BIT(psta->aid);
431                                         update_beacon(padapter, _TIM_IE_, NULL, _FALSE);
432
433                                         if(!pmlmeext->active_keep_alive_check)
434                                                 continue;
435                                 }
436                         }
437
438                         if (pmlmeext->active_keep_alive_check) {
439                                 int stainfo_offset;
440
441                                 stainfo_offset = rtw_stainfo_offset(pstapriv, psta);
442                                 if (stainfo_offset_valid(stainfo_offset)) {
443                                         chk_alive_list[chk_alive_num++] = stainfo_offset;
444                                 }
445
446                                 continue;
447                         }
448                         #endif /* CONFIG_ACTIVE_KEEP_ALIVE_CHECK */
449
450                         rtw_list_delete(&psta->asoc_list);
451                         pstapriv->asoc_list_cnt--;
452
453                         DBG_8723A("asoc expire "MAC_FMT", state=0x%x\n", MAC_ARG(psta->hwaddr), psta->state);
454                         updated = ap_free_sta(padapter, psta, _FALSE, WLAN_REASON_DEAUTH_LEAVING);
455                 }
456                 else
457                 {
458                         /* TODO: Aging mechanism to digest frames in sleep_q to avoid running out of xmitframe */
459                         if (psta->sleepq_len > (NR_XMITFRAME/pstapriv->asoc_list_cnt)
460                                 && padapter->xmitpriv.free_xmitframe_cnt < ((NR_XMITFRAME/pstapriv->asoc_list_cnt)/2)
461                         ){
462                                 DBG_8723A("%s sta:"MAC_FMT", sleepq_len:%u, free_xmitframe_cnt:%u, asoc_list_cnt:%u, clear sleep_q\n", __func__
463                                         , MAC_ARG(psta->hwaddr)
464                                         , psta->sleepq_len, padapter->xmitpriv.free_xmitframe_cnt, pstapriv->asoc_list_cnt);
465                                 wakeup_sta_to_xmit(padapter, psta);
466                         }
467                 }
468         }
469
470         spin_unlock_bh(&pstapriv->asoc_list_lock);
471
472 #ifdef CONFIG_ACTIVE_KEEP_ALIVE_CHECK
473 if (chk_alive_num) {
474
475         u8 backup_oper_channel=0;
476         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
477         /* switch to correct channel of current network  before issue keep-alive frames */
478         if (rtw_get_oper_ch(padapter) != pmlmeext->cur_channel) {
479                 backup_oper_channel = rtw_get_oper_ch(padapter);
480                 SelectChannel(padapter, pmlmeext->cur_channel);
481         }
482
483         /* issue null data to check sta alive*/
484         for (i = 0; i < chk_alive_num; i++) {
485
486                 int ret = _FAIL;
487
488                 psta = rtw_get_stainfo_by_offset(pstapriv, chk_alive_list[i]);
489                 if(!(psta->state &_FW_LINKED))
490                         continue;
491
492                 if (psta->state & WIFI_SLEEP_STATE)
493                         ret = issue_nulldata(padapter, psta->hwaddr, 0, 1, 50);
494                 else
495                         ret = issue_nulldata(padapter, psta->hwaddr, 0, 3, 50);
496
497                 psta->keep_alive_trycnt++;
498                 if (ret == _SUCCESS)
499                 {
500                         DBG_8723A("asoc check, sta(" MAC_FMT ") is alive\n", MAC_ARG(psta->hwaddr));
501                         psta->expire_to = pstapriv->expire_to;
502                         psta->keep_alive_trycnt = 0;
503                         continue;
504                 }
505                 else if (psta->keep_alive_trycnt <= 3)
506                 {
507                         DBG_8723A("ack check for asoc expire, keep_alive_trycnt=%d\n", psta->keep_alive_trycnt);
508                         psta->expire_to = 1;
509                         continue;
510                 }
511
512                 psta->keep_alive_trycnt = 0;
513
514                 DBG_8723A("asoc expire "MAC_FMT", state=0x%x\n", MAC_ARG(psta->hwaddr), psta->state);
515                 spin_lock_bh(&pstapriv->asoc_list_lock);
516                 if (rtw_is_list_empty(&psta->asoc_list)==_FALSE) {
517                         rtw_list_delete(&psta->asoc_list);
518                         pstapriv->asoc_list_cnt--;
519                         updated = ap_free_sta(padapter, psta, _FALSE, WLAN_REASON_DEAUTH_LEAVING);
520                 }
521                 spin_unlock_bh(&pstapriv->asoc_list_lock);
522
523         }
524
525         if (backup_oper_channel>0) /* back to the original operation channel */
526                 SelectChannel(padapter, backup_oper_channel);
527 }
528 #endif /* CONFIG_ACTIVE_KEEP_ALIVE_CHECK */
529
530         associated_clients_update(padapter, updated);
531 }
532
533 void add_RATid(_adapter *padapter, struct sta_info *psta, u8 rssi_level)
534 {
535         int i;
536         u8 rf_type;
537         u32 init_rate=0;
538         unsigned char sta_band = 0, raid, shortGIrate = _FALSE;
539         unsigned char limit;
540         unsigned int tx_ra_bitmap=0;
541         struct ht_priv  *psta_ht = NULL;
542         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
543         WLAN_BSSID_EX *pcur_network = (WLAN_BSSID_EX *)&pmlmepriv->cur_network.network;
544
545 #ifdef CONFIG_80211N_HT
546         if(psta)
547                 psta_ht = &psta->htpriv;
548         else
549                 return;
550 #endif /* CONFIG_80211N_HT */
551
552         if(!(psta->state & _FW_LINKED))
553                 return;
554
555         /* b/g mode ra_bitmap */
556         for (i=0; i<sizeof(psta->bssrateset); i++)
557         {
558                 if (psta->bssrateset[i])
559                         tx_ra_bitmap |= rtw_get_bit_value_from_ieee_value(psta->bssrateset[i]&0x7f);
560         }
561 #ifdef CONFIG_80211N_HT
562         /* n mode ra_bitmap */
563         if(psta_ht->ht_option)
564         {
565                 rtw_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
566                 if(rf_type == RF_2T2R)
567                         limit=16;/*  2R */
568                 else
569                         limit=8;/*   1R */
570
571                 for (i=0; i<limit; i++) {
572                         if (psta_ht->ht_cap.supp_mcs_set[i/8] & BIT(i%8))
573                                 tx_ra_bitmap |= BIT(i+12);
574                 }
575
576                 /* max short GI rate */
577                 shortGIrate = psta_ht->sgi;
578         }
579 #endif /* CONFIG_80211N_HT */
580
581         if ( pcur_network->Configuration.DSConfig > 14 ) {
582                 /*  5G band */
583                 if (tx_ra_bitmap & 0xffff000)
584                         sta_band |= WIRELESS_11_5N | WIRELESS_11A;
585                 else
586                         sta_band |= WIRELESS_11A;
587         } else {
588                 if (tx_ra_bitmap & 0xffff000)
589                         sta_band |= WIRELESS_11_24N | WIRELESS_11G | WIRELESS_11B;
590                 else if (tx_ra_bitmap & 0xff0)
591                         sta_band |= WIRELESS_11G |WIRELESS_11B;
592                 else
593                         sta_band |= WIRELESS_11B;
594         }
595
596         psta->wireless_mode = sta_band;
597
598         raid = networktype_to_raid(sta_band);
599         init_rate = get_highest_rate_idx(tx_ra_bitmap&0x0fffffff)&0x3f;
600
601         if (psta->aid < NUM_STA)
602         {
603                 u8 arg = 0;
604
605                 arg = psta->mac_id&0x1f;
606
607                 arg |= BIT(7);/* support entry 2~31 */
608
609                 if (shortGIrate==_TRUE)
610                         arg |= BIT(5);
611
612                 tx_ra_bitmap |= ((raid<<28)&0xf0000000);
613
614                 DBG_8723A("%s=> mac_id:%d , raid:%d , bitmap=0x%x, arg=0x%x\n",
615                         __FUNCTION__ , psta->mac_id, raid ,tx_ra_bitmap, arg);
616
617                 /* bitmap[0:27] = tx_rate_bitmap */
618                 /* bitmap[28:31]= Rate Adaptive id */
619                 /* arg[0:4] = macid */
620                 /* arg[5] = Short GI */
621                 rtw_hal_add_ra_tid(padapter, tx_ra_bitmap, arg, rssi_level);
622
623                 if (shortGIrate==_TRUE)
624                         init_rate |= BIT(6);
625
626                 /* set ra_id, init_rate */
627                 psta->raid = raid;
628                 psta->init_rate = init_rate;
629
630         }
631         else
632         {
633                 DBG_8723A("station aid %d exceed the max number\n", psta->aid);
634         }
635 }
636
637 static void update_bmc_sta(_adapter *padapter)
638 {
639         _irqL   irqL;
640         u32 init_rate=0;
641         unsigned char   network_type, raid;
642         int i, supportRateNum = 0;
643         unsigned int tx_ra_bitmap=0;
644         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
645         WLAN_BSSID_EX *pcur_network = (WLAN_BSSID_EX *)&pmlmepriv->cur_network.network;
646         struct sta_info *psta = rtw_get_bcmc_stainfo(padapter);
647
648         if(psta)
649         {
650                 psta->aid = 0;/* default set to 0 */
651                 psta->mac_id = psta->aid + 1;
652
653                 psta->qos_option = 0;
654 #ifdef CONFIG_80211N_HT
655                 psta->htpriv.ht_option = _FALSE;
656 #endif /* CONFIG_80211N_HT */
657
658                 psta->ieee8021x_blocked = 0;
659
660                 memset((void*)&psta->sta_stats, 0, sizeof(struct stainfo_stats));
661
662                 /* prepare for add_RATid */
663                 supportRateNum = rtw_get_rateset_len((u8*)&pcur_network->SupportedRates);
664                 network_type = rtw_check_network_type((u8*)&pcur_network->SupportedRates, supportRateNum, 1);
665
666                 memcpy(psta->bssrateset, &pcur_network->SupportedRates, supportRateNum);
667                 psta->bssratelen = supportRateNum;
668
669                 /* b/g mode ra_bitmap */
670                 for (i=0; i<supportRateNum; i++)
671                 {
672                         if (psta->bssrateset[i])
673                                 tx_ra_bitmap |= rtw_get_bit_value_from_ieee_value(psta->bssrateset[i]&0x7f);
674                 }
675
676                 if ( pcur_network->Configuration.DSConfig > 14 ) {
677                         /* force to A mode. 5G doesn't support CCK rates */
678                         network_type = WIRELESS_11A;
679                         tx_ra_bitmap = 0x150; /*  6, 12, 24 Mbps */
680                 } else {
681                         /* force to b mode */
682                         network_type = WIRELESS_11B;
683                         tx_ra_bitmap = 0xf;
684                 }
685
686                 raid = networktype_to_raid(network_type);
687                 init_rate = get_highest_rate_idx(tx_ra_bitmap&0x0fffffff)&0x3f;
688
689                 /* ap mode */
690                 rtw_hal_set_odm_var(padapter, HAL_ODM_STA_INFO, psta, _TRUE);
691
692                 {
693                         u8 arg = 0;
694
695                         arg = psta->mac_id&0x1f;
696
697                         arg |= BIT(7);
698
699                         tx_ra_bitmap |= ((raid<<28)&0xf0000000);
700
701                         DBG_8723A("update_bmc_sta, mask=0x%x, arg=0x%x\n", tx_ra_bitmap, arg);
702
703                         /* bitmap[0:27] = tx_rate_bitmap */
704                         /* bitmap[28:31]= Rate Adaptive id */
705                         /* arg[0:4] = macid */
706                         /* arg[5] = Short GI */
707                         rtw_hal_add_ra_tid(padapter, tx_ra_bitmap, arg, 0);
708
709                 }
710
711                 /* set ra_id, init_rate */
712                 psta->raid = raid;
713                 psta->init_rate = init_rate;
714
715                 rtw_stassoc_hw_rpt(padapter, psta);
716
717                 spin_lock_bh(&psta->lock);
718                 psta->state = _FW_LINKED;
719                 spin_unlock_bh(&psta->lock);
720
721         }
722         else
723         {
724                 DBG_8723A("add_RATid_bmc_sta error!\n");
725         }
726 }
727
728 /* notes: */
729 /* AID: 1~MAX for sta and 0 for bc/mc in ap/adhoc mode */
730 /* MAC_ID = AID+1 for sta in ap/adhoc mode */
731 /* MAC_ID = 1 for bc/mc for sta/ap/adhoc */
732 /* MAC_ID = 0 for bssid for sta/ap/adhoc */
733 /* CAM_ID = 0~3 for default key, cmd_id=macid + 3, macid=aid+1; */
734
735 void update_sta_info_apmode(_adapter *padapter, struct sta_info *psta)
736 {
737         _irqL   irqL;
738         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
739         struct security_priv *psecuritypriv = &padapter->securitypriv;
740         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
741 #ifdef CONFIG_80211N_HT
742         struct ht_priv  *phtpriv_ap = &pmlmepriv->htpriv;
743         struct ht_priv  *phtpriv_sta = &psta->htpriv;
744 #endif /* CONFIG_80211N_HT */
745         /* set intf_tag to if1 */
746
747         psta->mac_id = psta->aid+1;
748         DBG_8723A("%s\n",__FUNCTION__);
749
750         /* ap mode */
751         rtw_hal_set_odm_var(padapter,HAL_ODM_STA_INFO,psta,_TRUE);
752
753         if(psecuritypriv->dot11AuthAlgrthm==dot11AuthAlgrthm_8021X)
754                 psta->ieee8021x_blocked = _TRUE;
755         else
756                 psta->ieee8021x_blocked = _FALSE;
757
758         /* update sta's cap */
759
760         /* ERP */
761         VCS_update(padapter, psta);
762 #ifdef CONFIG_80211N_HT
763         /* HT related cap */
764         if(phtpriv_sta->ht_option)
765         {
766                 /* check if sta supports rx ampdu */
767                 phtpriv_sta->ampdu_enable = phtpriv_ap->ampdu_enable;
768
769                 /* check if sta support s Short GI */
770                 if((phtpriv_sta->ht_cap.cap_info & phtpriv_ap->ht_cap.cap_info) & cpu_to_le16(IEEE80211_HT_CAP_SGI_20|IEEE80211_HT_CAP_SGI_40))
771                         phtpriv_sta->sgi = _TRUE;
772
773                 /*  bwmode */
774                 if((phtpriv_sta->ht_cap.cap_info & phtpriv_ap->ht_cap.cap_info) & cpu_to_le16(IEEE80211_HT_CAP_SUP_WIDTH)) {
775                         /* phtpriv_sta->bwmode = HT_CHANNEL_WIDTH_40; */
776                         phtpriv_sta->bwmode = pmlmeext->cur_bwmode;
777                         phtpriv_sta->ch_offset = pmlmeext->cur_ch_offset;
778
779                 }
780
781                 psta->qos_option = _TRUE;
782
783         }
784         else
785         {
786                 phtpriv_sta->ampdu_enable = _FALSE;
787
788                 phtpriv_sta->sgi = _FALSE;
789                 phtpriv_sta->bwmode = HT_CHANNEL_WIDTH_20;
790                 phtpriv_sta->ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
791         }
792
793         /* Rx AMPDU */
794         send_delba(padapter, 0, psta->hwaddr);/*  recipient */
795
796         /* TX AMPDU */
797         send_delba(padapter, 1, psta->hwaddr);/*  originator */
798         phtpriv_sta->agg_enable_bitmap = 0x0;/* reset */
799         phtpriv_sta->candidate_tid_bitmap = 0x0;/* reset */
800 #endif /* CONFIG_80211N_HT */
801
802         /* todo: init other variables */
803
804         memset((void*)&psta->sta_stats, 0, sizeof(struct stainfo_stats));
805
806         spin_lock_bh(&psta->lock);
807         psta->state |= _FW_LINKED;
808         spin_unlock_bh(&psta->lock);
809 }
810
811 static void update_hw_ht_param(_adapter *padapter)
812 {
813         unsigned char           max_AMPDU_len;
814         unsigned char           min_MPDU_spacing;
815         struct registry_priv     *pregpriv = &padapter->registrypriv;
816         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
817         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
818
819         DBG_8723A("%s\n", __FUNCTION__);
820
821         /* handle A-MPDU parameter field */
822         /*
823                 AMPDU_para [1:0]:Max AMPDU Len => 0:8k , 1:16k, 2:32k, 3:64k
824                 AMPDU_para [4:2]:Min MPDU Start Spacing
825         */
826         max_AMPDU_len = pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x03;
827
828         min_MPDU_spacing = (pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x1c) >> 2;
829
830         rtw_hal_set_hwreg(padapter, HW_VAR_AMPDU_MIN_SPACE, (u8 *)(&min_MPDU_spacing));
831
832         rtw_hal_set_hwreg(padapter, HW_VAR_AMPDU_FACTOR, (u8 *)(&max_AMPDU_len));
833
834         /*  */
835         /*  Config SM Power Save setting */
836         /*  */
837         pmlmeinfo->SM_PS = (pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info & 0x0C) >> 2;
838         if(pmlmeinfo->SM_PS == WLAN_HT_CAP_SM_PS_STATIC)
839                 DBG_8723A("%s(): WLAN_HT_CAP_SM_PS_STATIC\n",__FUNCTION__);
840
841         /*  */
842         /*  Config current HT Protection mode. */
843         /*  */
844         /* pmlmeinfo->HT_protection = pmlmeinfo->HT_info.infos[1] & 0x3; */
845 }
846
847 static void start_bss_network(_adapter *padapter, u8 *pbuf)
848 {
849         u8 *p;
850         u8 val8, cur_channel, cur_bwmode, cur_ch_offset;
851         u16 bcn_interval;
852         u32     acparm;
853         int     ie_len;
854         struct registry_priv     *pregpriv = &padapter->registrypriv;
855         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
856         struct security_priv* psecuritypriv=&(padapter->securitypriv);
857         WLAN_BSSID_EX *pnetwork = (WLAN_BSSID_EX *)&pmlmepriv->cur_network.network;
858         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
859         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
860         WLAN_BSSID_EX *pnetwork_mlmeext = &(pmlmeinfo->network);
861         struct HT_info_element *pht_info=NULL;
862 #ifdef CONFIG_P2P
863         struct wifidirect_info  *pwdinfo = &(padapter->wdinfo);
864 #endif /* CONFIG_P2P */
865
866         bcn_interval = (u16)pnetwork->Configuration.BeaconPeriod;
867         cur_channel = pnetwork->Configuration.DSConfig;
868         cur_bwmode = HT_CHANNEL_WIDTH_20;;
869         cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
870
871         /* check if there is wps ie, */
872         /* if there is wpsie in beacon, the hostapd will update beacon twice when stating hostapd, */
873         /* and at first time the security ie ( RSN/WPA IE) will not include in beacon. */
874         if(NULL == rtw_get_wps_ie(pnetwork->IEs+_FIXED_IE_LENGTH_, pnetwork->IELength-_FIXED_IE_LENGTH_, NULL, NULL))
875         {
876                 pmlmeext->bstart_bss = _TRUE;
877         }
878
879         /* todo: update wmm, ht cap */
880         /* pmlmeinfo->WMM_enable; */
881         /* pmlmeinfo->HT_enable; */
882         if(pmlmepriv->qospriv.qos_option)
883                 pmlmeinfo->WMM_enable = _TRUE;
884 #ifdef CONFIG_80211N_HT
885         if(pmlmepriv->htpriv.ht_option)
886         {
887                 pmlmeinfo->WMM_enable = _TRUE;
888                 pmlmeinfo->HT_enable = _TRUE;
889
890                 update_hw_ht_param(padapter);
891         }
892 #endif /* CONFIG_80211N_HT */
893
894         if(pmlmepriv->cur_network.join_res != _TRUE) /* setting only at  first time */
895         {
896                 /* WEP Key will be set before this function, do not clear CAM. */
897                 if ((psecuritypriv->dot11PrivacyAlgrthm != _WEP40_) && (psecuritypriv->dot11PrivacyAlgrthm != _WEP104_))
898                         flush_all_cam_entry(padapter);  /* clear CAM */
899         }
900
901         /* set MSR to AP_Mode */
902         Set_MSR(padapter, _HW_STATE_AP_);
903
904         /* Set BSSID REG */
905         rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, pnetwork->MacAddress);
906
907         /* Set EDCA param reg */
908 #ifdef CONFIG_CONCURRENT_MODE
909         acparm = 0x005ea42b;
910 #else
911         acparm = 0x002F3217; /*  VO */
912 #endif
913         rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VO, (u8 *)(&acparm));
914         acparm = 0x005E4317; /*  VI */
915         rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VI, (u8 *)(&acparm));
916         acparm = 0x005ea42b;
917         rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BE, (u8 *)(&acparm));
918         acparm = 0x0000A444; /*  BK */
919         rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BK, (u8 *)(&acparm));
920
921         /* Set Security */
922         val8 = (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X)? 0xcc: 0xcf;
923         rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8));
924
925         /* Beacon Control related register */
926         rtw_hal_set_hwreg(padapter, HW_VAR_BEACON_INTERVAL, (u8 *)(&bcn_interval));
927
928         UpdateBrateTbl(padapter, pnetwork->SupportedRates);
929         rtw_hal_set_hwreg(padapter, HW_VAR_BASIC_RATE, pnetwork->SupportedRates);
930
931         if(pmlmepriv->cur_network.join_res != _TRUE) /* setting only at  first time */
932         {
933                 /* u32 initialgain; */
934
935                 /* initialgain = 0x1e; */
936
937                 /* disable dynamic functions, such as high power, DIG */
938                 /* Save_DM_Func_Flag(padapter); */
939                 /* Switch_DM_Func(padapter, DYNAMIC_FUNC_DISABLE, _FALSE); */
940
941 #ifdef CONFIG_CONCURRENT_MODE
942                 if(padapter->adapter_type > PRIMARY_ADAPTER)
943                 {
944                         if(rtw_buddy_adapter_up(padapter))
945                         {
946                                 _adapter *pbuddy_adapter = padapter->pbuddy_adapter;
947
948                                 /* turn on all dynamic functions on PRIMARY_ADAPTER, dynamic functions only runs at PRIMARY_ADAPTER */
949                                 Switch_DM_Func(pbuddy_adapter, DYNAMIC_ALL_FUNC_ENABLE, _TRUE);
950
951                                 /* rtw_hal_set_hwreg(pbuddy_adapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain)); */
952                         }
953                 }
954                 else
955 #endif
956                 {
957                         /* turn on all dynamic functions */
958                         Switch_DM_Func(padapter, DYNAMIC_ALL_FUNC_ENABLE, _TRUE);
959
960                         /* rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain)); */
961                 }
962
963         }
964 #ifdef CONFIG_80211N_HT
965         /* set channel, bwmode */
966         p = rtw_get_ie((pnetwork->IEs + sizeof(NDIS_802_11_FIXED_IEs)), _HT_ADD_INFO_IE_, &ie_len, (pnetwork->IELength - sizeof(NDIS_802_11_FIXED_IEs)));
967         if( p && ie_len)
968         {
969                 pht_info = (struct HT_info_element *)(p+2);
970
971                 if ((pregpriv->cbw40_enable) &&  (pht_info->infos[0] & BIT(2)))
972                 {
973                         /* switch to the 40M Hz mode */
974                         /* pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_40; */
975                         cur_bwmode = HT_CHANNEL_WIDTH_40;
976                         switch (pht_info->infos[0] & 0x3)
977                         {
978                                 case 1:
979                                         /* pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER; */
980                                         cur_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER;
981                                         break;
982
983                                 case 3:
984                                         /* pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER; */
985                                         cur_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER;
986                                         break;
987
988                                 default:
989                                         /* pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; */
990                                         cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
991                                         break;
992                         }
993
994                 }
995
996         }
997 #endif /* CONFIG_80211N_HT */
998 #ifdef CONFIG_DUALMAC_CONCURRENT
999         dc_set_ap_channel_bandwidth(padapter, cur_channel, cur_ch_offset, cur_bwmode);
1000 #else
1001         /* TODO: need to judge the phy parameters on concurrent mode for single phy */
1002         /* set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); */
1003 #ifdef CONFIG_CONCURRENT_MODE
1004         if(!check_buddy_fwstate(padapter, _FW_LINKED|_FW_UNDER_LINKING|_FW_UNDER_SURVEY))
1005         {
1006         set_channel_bwmode(padapter, cur_channel, cur_ch_offset, cur_bwmode);
1007         }
1008         else if(check_buddy_fwstate(padapter, _FW_LINKED)==_TRUE)/* only second adapter can enter AP Mode */
1009         {
1010                 _adapter *pbuddy_adapter = padapter->pbuddy_adapter;
1011                 struct mlme_ext_priv *pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
1012
1013                 /* To sync cur_channel/cur_bwmode/cur_ch_offset with primary adapter */
1014                 DBG_8723A("primary iface is at linked state, sync cur_channel/cur_bwmode/cur_ch_offset\n");
1015                 DBG_8723A("primary adapter, CH=%d, BW=%d, offset=%d\n", pbuddy_mlmeext->cur_channel, pbuddy_mlmeext->cur_bwmode, pbuddy_mlmeext->cur_ch_offset);
1016                 DBG_8723A("second adapter, CH=%d, BW=%d, offset=%d\n", cur_channel, cur_bwmode, cur_ch_offset);
1017
1018                 cur_channel = pbuddy_mlmeext->cur_channel;
1019                 if(cur_bwmode == HT_CHANNEL_WIDTH_40)
1020                 {
1021                         if(pht_info)
1022                                 pht_info->infos[0] &= ~(BIT(0)|BIT(1));
1023
1024                         if(pbuddy_mlmeext->cur_bwmode == HT_CHANNEL_WIDTH_40)
1025                         {
1026                                 cur_ch_offset = pbuddy_mlmeext->cur_ch_offset;
1027
1028                                 /* to update cur_ch_offset value in beacon */
1029                                 if(pht_info)
1030                                 {
1031                                         switch(cur_ch_offset)
1032                                         {
1033                                                 case HAL_PRIME_CHNL_OFFSET_LOWER:
1034                                                         pht_info->infos[0] |= 0x1;
1035                                                         break;
1036                                                 case HAL_PRIME_CHNL_OFFSET_UPPER:
1037                                                         pht_info->infos[0] |= 0x3;
1038                                                         break;
1039                                                 case HAL_PRIME_CHNL_OFFSET_DONT_CARE:
1040                                                 default:
1041                                                         break;
1042                                         }
1043                                 }
1044
1045                         }
1046                         else if(pbuddy_mlmeext->cur_bwmode == HT_CHANNEL_WIDTH_20)
1047                         {
1048                                 cur_bwmode = HT_CHANNEL_WIDTH_20;
1049                                 cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
1050
1051                                 if(cur_channel>0 && cur_channel<5)
1052                                 {
1053                                         if(pht_info)
1054                                                 pht_info->infos[0] |= 0x1;
1055
1056                                         cur_bwmode = HT_CHANNEL_WIDTH_40;
1057                                         cur_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER;
1058                                 }
1059
1060                                 if(cur_channel>7 && cur_channel<(14+1))
1061                                 {
1062                                         if(pht_info)
1063                                                 pht_info->infos[0] |= 0x3;
1064
1065                                         cur_bwmode = HT_CHANNEL_WIDTH_40;
1066                                         cur_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER;
1067                                 }
1068
1069                                 set_channel_bwmode(padapter, cur_channel, cur_ch_offset, cur_bwmode);
1070                         }
1071
1072                 }
1073
1074                 /*  to update channel value in beacon */
1075                 pnetwork->Configuration.DSConfig = cur_channel;
1076                 p = rtw_get_ie((pnetwork->IEs + sizeof(NDIS_802_11_FIXED_IEs)), _DSSET_IE_, &ie_len, (pnetwork->IELength - sizeof(NDIS_802_11_FIXED_IEs)));
1077                 if(p && ie_len>0)
1078                         *(p + 2) = cur_channel;
1079
1080                 if(pht_info)
1081                         pht_info->primary_channel = cur_channel;
1082         }
1083 #else
1084         set_channel_bwmode(padapter, cur_channel, cur_ch_offset, cur_bwmode);
1085 #endif /* CONFIG_CONCURRENT_MODE */
1086
1087         DBG_8723A("CH=%d, BW=%d, offset=%d\n", cur_channel, cur_bwmode, cur_ch_offset);
1088
1089         /*  */
1090         pmlmeext->cur_channel = cur_channel;
1091         pmlmeext->cur_bwmode = cur_bwmode;
1092         pmlmeext->cur_ch_offset = cur_ch_offset;
1093 #endif /* CONFIG_DUALMAC_CONCURRENT */
1094         pmlmeext->cur_wireless_mode = pmlmepriv->cur_network.network_type;
1095
1096         /* update cur_wireless_mode */
1097         update_wireless_mode(padapter);
1098
1099         /* udpate capability after cur_wireless_mode updated */
1100         update_capinfo(padapter, rtw_get_capability((WLAN_BSSID_EX *)pnetwork));
1101
1102         /* let pnetwork_mlmeext == pnetwork_mlme. */
1103         memcpy(pnetwork_mlmeext, pnetwork, pnetwork->Length);
1104
1105 #ifdef CONFIG_P2P
1106         memcpy(pwdinfo->p2p_group_ssid, pnetwork->Ssid.Ssid, pnetwork->Ssid.SsidLength);
1107         pwdinfo->p2p_group_ssid_len = pnetwork->Ssid.SsidLength;
1108 #endif /* CONFIG_P2P */
1109
1110         if(_TRUE == pmlmeext->bstart_bss)
1111         {
1112                 update_beacon(padapter, _TIM_IE_, NULL, _FALSE);
1113
1114 #ifndef CONFIG_INTERRUPT_BASED_TXBCN /* other case will  tx beacon when bcn interrupt coming in. */
1115 #if defined(CONFIG_USB_HCI) || defined(CONFIG_GSPI_HCI)
1116                 /* issue beacon frame */
1117                 if(send_beacon(padapter)==_FAIL)
1118                 {
1119                         DBG_8723A("issue_beacon, fail!\n");
1120                 }
1121 #endif
1122 #endif /* CONFIG_INTERRUPT_BASED_TXBCN */
1123
1124         }
1125
1126         /* update bc/mc sta_info */
1127         update_bmc_sta(padapter);
1128
1129         /* pmlmeext->bstart_bss = _TRUE; */
1130 }
1131
1132 int rtw_check_beacon_data(_adapter *padapter, u8 *pbuf,  int len)
1133 {
1134         int ret=_SUCCESS;
1135         u8 *p;
1136         u8 *pHT_caps_ie=NULL;
1137         u8 *pHT_info_ie=NULL;
1138         struct sta_info *psta = NULL;
1139         u16 cap, ht_cap=_FALSE;
1140         uint ie_len = 0;
1141         int group_cipher, pairwise_cipher;
1142         u8      channel, network_type, supportRate[NDIS_802_11_LENGTH_RATES_EX];
1143         int supportRateNum = 0;
1144         u8 OUI1[] = {0x00, 0x50, 0xf2,0x01};
1145         u8 wps_oui[4]={0x0,0x50,0xf2,0x04};
1146         u8 WMM_PARA_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01};
1147         struct registry_priv *pregistrypriv = &padapter->registrypriv;
1148         struct security_priv *psecuritypriv = &padapter->securitypriv;
1149         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1150         WLAN_BSSID_EX *pbss_network = (WLAN_BSSID_EX *)&pmlmepriv->cur_network.network;
1151         struct sta_priv *pstapriv = &padapter->stapriv;
1152         u8 *ie = pbss_network->IEs;
1153
1154         /* SSID */
1155         /* Supported rates */
1156         /* DS Params */
1157         /* WLAN_EID_COUNTRY */
1158         /* ERP Information element */
1159         /* Extended supported rates */
1160         /* WPA/WPA2 */
1161         /* Wi-Fi Wireless Multimedia Extensions */
1162         /* ht_capab, ht_oper */
1163         /* WPS IE */
1164
1165         DBG_8723A("%s, len=%d\n", __FUNCTION__, len);
1166
1167         if(check_fwstate(pmlmepriv, WIFI_AP_STATE) != _TRUE)
1168                 return _FAIL;
1169
1170         if(len>MAX_IE_SZ)
1171                 return _FAIL;
1172
1173         pbss_network->IELength = len;
1174
1175         memset(ie, 0, MAX_IE_SZ);
1176
1177         memcpy(ie, pbuf, pbss_network->IELength);
1178
1179         if(pbss_network->InfrastructureMode!=Ndis802_11APMode)
1180                 return _FAIL;
1181
1182         pbss_network->Rssi = 0;
1183
1184         memcpy(pbss_network->MacAddress, myid(&(padapter->eeprompriv)), ETH_ALEN);
1185
1186         /* beacon interval */
1187         p = rtw_get_beacon_interval_from_ie(ie);/* ie + 8;  8: TimeStamp, 2: Beacon Interval 2:Capability */
1188         /* pbss_network->Configuration.BeaconPeriod = le16_to_cpu(*(unsigned short*)p); */
1189         pbss_network->Configuration.BeaconPeriod = RTW_GET_LE16(p);
1190
1191         /* capability */
1192         /* cap = *(unsigned short *)rtw_get_capability_from_ie(ie); */
1193         /* cap = le16_to_cpu(cap); */
1194         cap = RTW_GET_LE16(ie);
1195
1196         /* SSID */
1197         p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _SSID_IE_, &ie_len, (pbss_network->IELength -_BEACON_IE_OFFSET_));
1198         if(p && ie_len>0)
1199         {
1200                 memset(&pbss_network->Ssid, 0, sizeof(NDIS_802_11_SSID));
1201                 memcpy(pbss_network->Ssid.Ssid, (p + 2), ie_len);
1202                 pbss_network->Ssid.SsidLength = ie_len;
1203         }
1204
1205         /* chnnel */
1206         channel = 0;
1207         pbss_network->Configuration.Length = 0;
1208         p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _DSSET_IE_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_));
1209         if(p && ie_len>0)
1210                 channel = *(p + 2);
1211
1212         pbss_network->Configuration.DSConfig = channel;
1213
1214         memset(supportRate, 0, NDIS_802_11_LENGTH_RATES_EX);
1215         /*  get supported rates */
1216         p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _SUPPORTEDRATES_IE_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_));
1217         if (p !=  NULL)
1218         {
1219                 memcpy(supportRate, p+2, ie_len);
1220                 supportRateNum = ie_len;
1221         }
1222
1223         /* get ext_supported rates */
1224         p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _EXT_SUPPORTEDRATES_IE_, &ie_len, pbss_network->IELength - _BEACON_IE_OFFSET_);
1225         if (p !=  NULL)
1226         {
1227                 memcpy(supportRate+supportRateNum, p+2, ie_len);
1228                 supportRateNum += ie_len;
1229
1230         }
1231
1232         network_type = rtw_check_network_type(supportRate, supportRateNum, channel);
1233
1234         rtw_set_supported_rate(pbss_network->SupportedRates, network_type);
1235
1236         /* parsing ERP_IE */
1237         p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _ERPINFO_IE_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_));
1238         if(p && ie_len>0)
1239         {
1240                 ERP_IE_handler(padapter, (PNDIS_802_11_VARIABLE_IEs)p);
1241         }
1242
1243         /* update privacy/security */
1244         if (cap & BIT(4))
1245                 pbss_network->Privacy = 1;
1246         else
1247                 pbss_network->Privacy = 0;
1248
1249         psecuritypriv->wpa_psk = 0;
1250
1251         /* wpa2 */
1252         group_cipher = 0; pairwise_cipher = 0;
1253         psecuritypriv->wpa2_group_cipher = _NO_PRIVACY_;
1254         psecuritypriv->wpa2_pairwise_cipher = _NO_PRIVACY_;
1255         p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _RSN_IE_2_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_));
1256         if(p && ie_len>0)
1257         {
1258                 if(rtw_parse_wpa2_ie(p, ie_len+2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS)
1259                 {
1260                         psecuritypriv->dot11AuthAlgrthm= dot11AuthAlgrthm_8021X;
1261
1262                         psecuritypriv->dot8021xalg = 1;/* psk,  todo:802.1x */
1263                         psecuritypriv->wpa_psk |= BIT(1);
1264
1265                         psecuritypriv->wpa2_group_cipher = group_cipher;
1266                         psecuritypriv->wpa2_pairwise_cipher = pairwise_cipher;
1267 #if 0
1268                         switch(group_cipher)
1269                         {
1270                                 case WPA_CIPHER_NONE:
1271                                 psecuritypriv->wpa2_group_cipher = _NO_PRIVACY_;
1272                                 break;
1273                                 case WPA_CIPHER_WEP40:
1274                                 psecuritypriv->wpa2_group_cipher = _WEP40_;
1275                                 break;
1276                                 case WPA_CIPHER_TKIP:
1277                                 psecuritypriv->wpa2_group_cipher = _TKIP_;
1278                                 break;
1279                                 case WPA_CIPHER_CCMP:
1280                                 psecuritypriv->wpa2_group_cipher = _AES_;
1281                                 break;
1282                                 case WPA_CIPHER_WEP104:
1283                                 psecuritypriv->wpa2_group_cipher = _WEP104_;
1284                                 break;
1285                         }
1286
1287                         switch(pairwise_cipher)
1288                         {
1289                                 case WPA_CIPHER_NONE:
1290                                 psecuritypriv->wpa2_pairwise_cipher = _NO_PRIVACY_;
1291                                 break;
1292                                 case WPA_CIPHER_WEP40:
1293                                 psecuritypriv->wpa2_pairwise_cipher = _WEP40_;
1294                                 break;
1295                                 case WPA_CIPHER_TKIP:
1296                                 psecuritypriv->wpa2_pairwise_cipher = _TKIP_;
1297                                 break;
1298                                 case WPA_CIPHER_CCMP:
1299                                 psecuritypriv->wpa2_pairwise_cipher = _AES_;
1300                                 break;
1301                                 case WPA_CIPHER_WEP104:
1302                                 psecuritypriv->wpa2_pairwise_cipher = _WEP104_;
1303                                 break;
1304                         }
1305 #endif
1306                 }
1307
1308         }
1309
1310         /* wpa */
1311         ie_len = 0;
1312         group_cipher = 0; pairwise_cipher = 0;
1313         psecuritypriv->wpa_group_cipher = _NO_PRIVACY_;
1314         psecuritypriv->wpa_pairwise_cipher = _NO_PRIVACY_;
1315         for (p = ie + _BEACON_IE_OFFSET_; ;p += (ie_len + 2))
1316         {
1317                 p = rtw_get_ie(p, _SSN_IE_1_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_ - (ie_len + 2)));
1318                 if ((p) && (!memcmp(p+2, OUI1, 4)))
1319                 {
1320                         if(rtw_parse_wpa_ie(p, ie_len+2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS)
1321                         {
1322                                 psecuritypriv->dot11AuthAlgrthm= dot11AuthAlgrthm_8021X;
1323
1324                                 psecuritypriv->dot8021xalg = 1;/* psk,  todo:802.1x */
1325
1326                                 psecuritypriv->wpa_psk |= BIT(0);
1327
1328                                 psecuritypriv->wpa_group_cipher = group_cipher;
1329                                 psecuritypriv->wpa_pairwise_cipher = pairwise_cipher;
1330
1331 #if 0
1332                                 switch(group_cipher)
1333                                 {
1334                                         case WPA_CIPHER_NONE:
1335                                         psecuritypriv->wpa_group_cipher = _NO_PRIVACY_;
1336                                         break;
1337                                         case WPA_CIPHER_WEP40:
1338                                         psecuritypriv->wpa_group_cipher = _WEP40_;
1339                                         break;
1340                                         case WPA_CIPHER_TKIP:
1341                                         psecuritypriv->wpa_group_cipher = _TKIP_;
1342                                         break;
1343                                         case WPA_CIPHER_CCMP:
1344                                         psecuritypriv->wpa_group_cipher = _AES_;
1345                                         break;
1346                                         case WPA_CIPHER_WEP104:
1347                                         psecuritypriv->wpa_group_cipher = _WEP104_;
1348                                         break;
1349                                 }
1350
1351                                 switch(pairwise_cipher)
1352                                 {
1353                                         case WPA_CIPHER_NONE:
1354                                         psecuritypriv->wpa_pairwise_cipher = _NO_PRIVACY_;
1355                                         break;
1356                                         case WPA_CIPHER_WEP40:
1357                                         psecuritypriv->wpa_pairwise_cipher = _WEP40_;
1358                                         break;
1359                                         case WPA_CIPHER_TKIP:
1360                                         psecuritypriv->wpa_pairwise_cipher = _TKIP_;
1361                                         break;
1362                                         case WPA_CIPHER_CCMP:
1363                                         psecuritypriv->wpa_pairwise_cipher = _AES_;
1364                                         break;
1365                                         case WPA_CIPHER_WEP104:
1366                                         psecuritypriv->wpa_pairwise_cipher = _WEP104_;
1367                                         break;
1368                                 }
1369 #endif
1370                         }
1371
1372                         break;
1373
1374                 }
1375
1376                 if ((p == NULL) || (ie_len == 0))
1377                 {
1378                                 break;
1379                 }
1380
1381         }
1382
1383         /* wmm */
1384         ie_len = 0;
1385         pmlmepriv->qospriv.qos_option = 0;
1386         if(pregistrypriv->wmm_enable)
1387         {
1388                 for (p = ie + _BEACON_IE_OFFSET_; ;p += (ie_len + 2))
1389                 {
1390                         p = rtw_get_ie(p, _VENDOR_SPECIFIC_IE_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_ - (ie_len + 2)));
1391                         if((p) && !memcmp(p+2, WMM_PARA_IE, 6))
1392                         {
1393                                 pmlmepriv->qospriv.qos_option = 1;
1394
1395                                 *(p+8) |= BIT(7);/* QoS Info, support U-APSD */
1396
1397                                 /* disable all ACM bits since the WMM admission control is not supported */
1398                                 *(p + 10) &= ~BIT(4); /* BE */
1399                                 *(p + 14) &= ~BIT(4); /* BK */
1400                                 *(p + 18) &= ~BIT(4); /* VI */
1401                                 *(p + 22) &= ~BIT(4); /* VO */
1402
1403                                 break;
1404                         }
1405
1406                         if ((p == NULL) || (ie_len == 0))
1407                         {
1408                                 break;
1409                         }
1410                 }
1411         }
1412 #ifdef CONFIG_80211N_HT
1413         /* parsing HT_CAP_IE */
1414         p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_CAPABILITY_IE_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_));
1415         if(p && ie_len>0)
1416         {
1417                 u8 rf_type;
1418
1419                 struct rtw_ieee80211_ht_cap *pht_cap = (struct rtw_ieee80211_ht_cap *)(p+2);
1420
1421                 pHT_caps_ie=p;
1422
1423                 ht_cap = _TRUE;
1424                 network_type |= WIRELESS_11_24N;
1425
1426                 rtw_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
1427
1428                 if((psecuritypriv->wpa_pairwise_cipher & WPA_CIPHER_CCMP) ||
1429                         (psecuritypriv->wpa2_pairwise_cipher & WPA_CIPHER_CCMP))
1430                 {
1431                         pht_cap->ampdu_params_info |= (IEEE80211_HT_CAP_AMPDU_DENSITY&(0x07<<2));
1432                 }
1433                 else
1434                 {
1435                         pht_cap->ampdu_params_info |= (IEEE80211_HT_CAP_AMPDU_DENSITY&0x00);
1436                 }
1437
1438                 pht_cap->ampdu_params_info |= (IEEE80211_HT_CAP_AMPDU_FACTOR & 0x03); /* set  Max Rx AMPDU size  to 64K */
1439
1440                 if(rf_type == RF_1T1R)
1441                 {
1442                         pht_cap->supp_mcs_set[0] = 0xff;
1443                         pht_cap->supp_mcs_set[1] = 0x0;
1444                 }
1445
1446                 memcpy(&pmlmepriv->htpriv.ht_cap, p+2, ie_len);
1447
1448         }
1449
1450         /* parsing HT_INFO_IE */
1451         p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_ADD_INFO_IE_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_));
1452         if(p && ie_len>0)
1453         {
1454                 pHT_info_ie=p;
1455         }
1456 #endif /* CONFIG_80211N_HT */
1457         switch(network_type)
1458         {
1459                 case WIRELESS_11B:
1460                         pbss_network->NetworkTypeInUse = Ndis802_11DS;
1461                         break;
1462                 case WIRELESS_11G:
1463                 case WIRELESS_11BG:
1464              case WIRELESS_11G_24N:
1465                 case WIRELESS_11BG_24N:
1466                         pbss_network->NetworkTypeInUse = Ndis802_11OFDM24;
1467                         break;
1468                 case WIRELESS_11A:
1469                         pbss_network->NetworkTypeInUse = Ndis802_11OFDM5;
1470                         break;
1471                 default :
1472                         pbss_network->NetworkTypeInUse = Ndis802_11OFDM24;
1473                         break;
1474         }
1475
1476         pmlmepriv->cur_network.network_type = network_type;
1477
1478 #ifdef CONFIG_80211N_HT
1479         pmlmepriv->htpriv.ht_option = _FALSE;
1480
1481         if( (psecuritypriv->wpa2_pairwise_cipher&WPA_CIPHER_TKIP) ||
1482                       (psecuritypriv->wpa_pairwise_cipher&WPA_CIPHER_TKIP))
1483         {
1484                 /* todo: */
1485                 /* ht_cap = _FALSE; */
1486         }
1487
1488         /* ht_cap */
1489         if(pregistrypriv->ht_enable && ht_cap==_TRUE)
1490         {
1491                 pmlmepriv->htpriv.ht_option = _TRUE;
1492                 pmlmepriv->qospriv.qos_option = 1;
1493
1494                 if(pregistrypriv->ampdu_enable==1)
1495                 {
1496                         pmlmepriv->htpriv.ampdu_enable = _TRUE;
1497                 }
1498
1499                 HT_caps_handler(padapter, (PNDIS_802_11_VARIABLE_IEs)pHT_caps_ie);
1500
1501                 HT_info_handler(padapter, (PNDIS_802_11_VARIABLE_IEs)pHT_info_ie);
1502         }
1503 #endif
1504
1505         pbss_network->Length = get_WLAN_BSSID_EX_sz((WLAN_BSSID_EX  *)pbss_network);
1506
1507         /* issue beacon to start bss network */
1508         start_bss_network(padapter, (u8*)pbss_network);
1509
1510         /* alloc sta_info for ap itself */
1511         psta = rtw_get_stainfo(&padapter->stapriv, pbss_network->MacAddress);
1512         if(!psta)
1513         {
1514                 psta = rtw_alloc_stainfo(&padapter->stapriv, pbss_network->MacAddress);
1515                 if (psta == NULL)
1516                 {
1517                         return _FAIL;
1518                 }
1519         }
1520         psta->state |= WIFI_AP_STATE;           /* Aries, add,fix bug of flush_cam_entry at STOP AP mode , 0724 */
1521         rtw_indicate_connect( padapter);
1522
1523         pmlmepriv->cur_network.join_res = _TRUE;/* for check if already set beacon */
1524
1525         /* update bc/mc sta_info */
1526         /* update_bmc_sta(padapter); */
1527
1528         return ret;
1529 }
1530
1531 void rtw_set_macaddr_acl(_adapter *padapter, int mode)
1532 {
1533         struct sta_priv *pstapriv = &padapter->stapriv;
1534         struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;
1535
1536         DBG_8723A("%s, mode=%d\n", __func__, mode);
1537
1538         pacl_list->mode = mode;
1539 }
1540
1541 int rtw_acl_add_sta(_adapter *padapter, u8 *addr)
1542 {
1543         _irqL irqL;
1544         _list   *plist, *phead;
1545         u8 added = _FALSE;
1546         int i, ret=0;
1547         struct rtw_wlan_acl_node *paclnode;
1548         struct sta_priv *pstapriv = &padapter->stapriv;
1549         struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;
1550         _queue  *pacl_node_q =&pacl_list->acl_node_q;
1551
1552         DBG_8723A("%s(acl_num=%d)=" MAC_FMT "\n", __func__, pacl_list->num, MAC_ARG(addr));
1553
1554         if((NUM_ACL-1) < pacl_list->num)
1555                 return (-1);
1556
1557         spin_lock_bh(&(pacl_node_q->lock));
1558
1559         phead = get_list_head(pacl_node_q);
1560         plist = get_next(phead);
1561
1562         while ((rtw_end_of_queue_search(phead, plist)) == _FALSE)
1563         {
1564                 paclnode = LIST_CONTAINOR(plist, struct rtw_wlan_acl_node, list);
1565                 plist = get_next(plist);
1566
1567                 if(!memcmp(paclnode->addr, addr, ETH_ALEN))
1568                 {
1569                         if(paclnode->valid == _TRUE)
1570                         {
1571                                 added = _TRUE;
1572                                 DBG_8723A("%s, sta has been added\n", __func__);
1573                                 break;
1574                         }
1575                 }
1576         }
1577
1578         spin_unlock_bh(&(pacl_node_q->lock));
1579
1580         if(added == _TRUE)
1581                 return ret;
1582
1583         spin_lock_bh(&(pacl_node_q->lock));
1584
1585         for(i=0; i< NUM_ACL; i++)
1586         {
1587                 paclnode = &pacl_list->aclnode[i];
1588
1589                 if(paclnode->valid == _FALSE)
1590                 {
1591                         _rtw_init_listhead(&paclnode->list);
1592
1593                         memcpy(paclnode->addr, addr, ETH_ALEN);
1594
1595                         paclnode->valid = _TRUE;
1596
1597                         rtw_list_insert_tail(&paclnode->list, get_list_head(pacl_node_q));
1598
1599                         pacl_list->num++;
1600
1601                         break;
1602                 }
1603         }
1604
1605         DBG_8723A("%s, acl_num=%d\n", __func__, pacl_list->num);
1606
1607         spin_unlock_bh(&(pacl_node_q->lock));
1608
1609         return ret;
1610 }
1611
1612 int rtw_acl_remove_sta(_adapter *padapter, u8 *addr)
1613 {
1614         _irqL irqL;
1615         _list   *plist, *phead;
1616         int i, ret=0;
1617         struct rtw_wlan_acl_node *paclnode;
1618         struct sta_priv *pstapriv = &padapter->stapriv;
1619         struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;
1620         _queue  *pacl_node_q =&pacl_list->acl_node_q;
1621
1622         DBG_8723A("%s(acl_num=%d)=" MAC_FMT "\n", __func__, pacl_list->num, MAC_ARG(addr));
1623
1624         spin_lock_bh(&(pacl_node_q->lock));
1625
1626         phead = get_list_head(pacl_node_q);
1627         plist = get_next(phead);
1628
1629         while ((rtw_end_of_queue_search(phead, plist)) == _FALSE)
1630         {
1631                 paclnode = LIST_CONTAINOR(plist, struct rtw_wlan_acl_node, list);
1632                 plist = get_next(plist);
1633
1634                 if(!memcmp(paclnode->addr, addr, ETH_ALEN))
1635                 {
1636                         if(paclnode->valid == _TRUE)
1637                         {
1638                                 paclnode->valid = _FALSE;
1639
1640                                 rtw_list_delete(&paclnode->list);
1641
1642                                 pacl_list->num--;
1643                         }
1644                 }
1645         }
1646
1647         spin_unlock_bh(&(pacl_node_q->lock));
1648
1649         DBG_8723A("%s, acl_num=%d\n", __func__, pacl_list->num);
1650
1651         return ret;
1652 }
1653
1654 #ifdef CONFIG_NATIVEAP_MLME
1655
1656 static void update_bcn_fixed_ie(_adapter *padapter)
1657 {
1658         DBG_8723A("%s\n", __FUNCTION__);
1659 }
1660
1661 static void update_bcn_erpinfo_ie(_adapter *padapter)
1662 {
1663         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1664         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
1665         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
1666         WLAN_BSSID_EX *pnetwork = &(pmlmeinfo->network);
1667         unsigned char *p, *ie = pnetwork->IEs;
1668         u32 len = 0;
1669
1670         DBG_8723A("%s, ERP_enable=%d\n", __FUNCTION__, pmlmeinfo->ERP_enable);
1671
1672         if(!pmlmeinfo->ERP_enable)
1673                 return;
1674
1675         /* parsing ERP_IE */
1676         p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _ERPINFO_IE_, &len, (pnetwork->IELength - _BEACON_IE_OFFSET_));
1677         if(p && len>0)
1678         {
1679                 PNDIS_802_11_VARIABLE_IEs pIE = (PNDIS_802_11_VARIABLE_IEs)p;
1680
1681                 if (pmlmepriv->num_sta_non_erp == 1)
1682                         pIE->data[0] |= RTW_ERP_INFO_NON_ERP_PRESENT|RTW_ERP_INFO_USE_PROTECTION;
1683                 else
1684                         pIE->data[0] &= ~(RTW_ERP_INFO_NON_ERP_PRESENT|RTW_ERP_INFO_USE_PROTECTION);
1685
1686                 if(pmlmepriv->num_sta_no_short_preamble > 0)
1687                         pIE->data[0] |= RTW_ERP_INFO_BARKER_PREAMBLE_MODE;
1688                 else
1689                         pIE->data[0] &= ~(RTW_ERP_INFO_BARKER_PREAMBLE_MODE);
1690
1691                 ERP_IE_handler(padapter, pIE);
1692         }
1693 }
1694
1695 static void update_bcn_htcap_ie(_adapter *padapter)
1696 {
1697         DBG_8723A("%s\n", __FUNCTION__);
1698 }
1699
1700 static void update_bcn_htinfo_ie(_adapter *padapter)
1701 {
1702         DBG_8723A("%s\n", __FUNCTION__);
1703 }
1704
1705 static void update_bcn_rsn_ie(_adapter *padapter)
1706 {
1707         DBG_8723A("%s\n", __FUNCTION__);
1708 }
1709
1710 static void update_bcn_wpa_ie(_adapter *padapter)
1711 {
1712         DBG_8723A("%s\n", __FUNCTION__);
1713 }
1714
1715 static void update_bcn_wmm_ie(_adapter *padapter)
1716 {
1717         DBG_8723A("%s\n", __FUNCTION__);
1718 }
1719
1720 static void update_bcn_wps_ie(_adapter *padapter)
1721 {
1722         u8 *pwps_ie=NULL, *pwps_ie_src, *premainder_ie, *pbackup_remainder_ie=NULL;
1723         uint wps_ielen=0, wps_offset, remainder_ielen;
1724         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1725         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
1726         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
1727         WLAN_BSSID_EX *pnetwork = &(pmlmeinfo->network);
1728         unsigned char *ie = pnetwork->IEs;
1729         u32 ielen = pnetwork->IELength;
1730
1731         DBG_8723A("%s\n", __FUNCTION__);
1732
1733         pwps_ie = rtw_get_wps_ie(ie+_FIXED_IE_LENGTH_, ielen-_FIXED_IE_LENGTH_, NULL, &wps_ielen);
1734
1735         if(pwps_ie==NULL || wps_ielen==0)
1736                 return;
1737
1738         wps_offset = (uint)(pwps_ie-ie);
1739
1740         premainder_ie = pwps_ie + wps_ielen;
1741
1742         remainder_ielen = ielen - wps_offset - wps_ielen;
1743
1744         if(remainder_ielen>0)
1745         {
1746                 pbackup_remainder_ie = rtw_malloc(remainder_ielen);
1747                 if(pbackup_remainder_ie)
1748                         memcpy(pbackup_remainder_ie, premainder_ie, remainder_ielen);
1749         }
1750
1751         pwps_ie_src = pmlmepriv->wps_beacon_ie;
1752         if(pwps_ie_src == NULL)
1753                 return;
1754
1755         wps_ielen = (uint)pwps_ie_src[1];/* to get ie data len */
1756         if((wps_offset+wps_ielen+2+remainder_ielen)<=MAX_IE_SZ)
1757         {
1758                 memcpy(pwps_ie, pwps_ie_src, wps_ielen+2);
1759                 pwps_ie += (wps_ielen+2);
1760
1761                 if(pbackup_remainder_ie)
1762                         memcpy(pwps_ie, pbackup_remainder_ie, remainder_ielen);
1763
1764                 /* update IELength */
1765                 pnetwork->IELength = wps_offset + (wps_ielen+2) + remainder_ielen;
1766         }
1767
1768         if(pbackup_remainder_ie)
1769                 rtw_mfree(pbackup_remainder_ie, remainder_ielen);
1770 }
1771
1772 static void update_bcn_p2p_ie(_adapter *padapter)
1773 {
1774 }
1775
1776 static void update_bcn_vendor_spec_ie(_adapter *padapter, u8*oui)
1777 {
1778         DBG_8723A("%s\n", __FUNCTION__);
1779
1780         if (!memcmp(RTW_WPA_OUI, oui, 4))
1781         {
1782                 update_bcn_wpa_ie(padapter);
1783         }
1784         else if (!memcmp(WMM_OUI, oui, 4))
1785         {
1786                 update_bcn_wmm_ie(padapter);
1787         }
1788         else if (!memcmp(WPS_OUI, oui, 4))
1789         {
1790                 update_bcn_wps_ie(padapter);
1791         }
1792         else if (!memcmp(P2P_OUI, oui, 4))
1793         {
1794                 update_bcn_p2p_ie(padapter);
1795         }
1796         else
1797         {
1798                 DBG_8723A("unknown OUI type!\n");
1799         }
1800 }
1801
1802 void update_beacon(_adapter *padapter, u8 ie_id, u8 *oui, u8 tx)
1803 {
1804         _irqL irqL;
1805         struct mlme_priv *pmlmepriv;
1806         struct mlme_ext_priv    *pmlmeext;
1807         /* struct mlme_ext_info *pmlmeinfo; */
1808
1809         /* DBG_8723A("%s\n", __FUNCTION__); */
1810
1811         if(!padapter)
1812                 return;
1813
1814         pmlmepriv = &(padapter->mlmepriv);
1815         pmlmeext = &(padapter->mlmeextpriv);
1816         /* pmlmeinfo = &(pmlmeext->mlmext_info); */
1817
1818         if(_FALSE == pmlmeext->bstart_bss)
1819                 return;
1820
1821         spin_lock_bh(&pmlmepriv->bcn_update_lock);
1822
1823         switch(ie_id)
1824         {
1825                 case 0xFF:
1826
1827                         update_bcn_fixed_ie(padapter);/* 8: TimeStamp, 2: Beacon Interval 2:Capability */
1828
1829                         break;
1830
1831                 case _TIM_IE_:
1832
1833                         update_BCNTIM(padapter);
1834
1835                         break;
1836
1837                 case _ERPINFO_IE_:
1838
1839                         update_bcn_erpinfo_ie(padapter);
1840
1841                         break;
1842
1843                 case _HT_CAPABILITY_IE_:
1844
1845                         update_bcn_htcap_ie(padapter);
1846
1847                         break;
1848
1849                 case _RSN_IE_2_:
1850
1851                         update_bcn_rsn_ie(padapter);
1852
1853                         break;
1854
1855                 case _HT_ADD_INFO_IE_:
1856
1857                         update_bcn_htinfo_ie(padapter);
1858
1859                         break;
1860
1861                 case _VENDOR_SPECIFIC_IE_:
1862
1863                         update_bcn_vendor_spec_ie(padapter, oui);
1864
1865                         break;
1866
1867                 default:
1868                         break;
1869         }
1870
1871         pmlmepriv->update_bcn = _TRUE;
1872
1873         spin_unlock_bh(&pmlmepriv->bcn_update_lock);
1874
1875 #ifndef CONFIG_INTERRUPT_BASED_TXBCN
1876 #if defined(CONFIG_USB_HCI) || defined(CONFIG_GSPI_HCI)
1877         if(tx)
1878         {
1879                 set_tx_beacon_cmd(padapter);
1880         }
1881 #else
1882         {
1883                 /* PCI will issue beacon when BCN interrupt occurs. */
1884         }
1885 #endif
1886 #endif /* CONFIG_INTERRUPT_BASED_TXBCN */
1887 }
1888
1889 #ifdef CONFIG_80211N_HT
1890
1891 /*
1892 op_mode
1893 Set to 0 (HT pure) under the followign conditions
1894         - all STAs in the BSS are 20/40 MHz HT in 20/40 MHz BSS or
1895         - all STAs in the BSS are 20 MHz HT in 20 MHz BSS
1896 Set to 1 (HT non-member protection) if there may be non-HT STAs
1897         in both the primary and the secondary channel
1898 Set to 2 if only HT STAs are associated in BSS,
1899         however and at least one 20 MHz HT STA is associated
1900 Set to 3 (HT mixed mode) when one or more non-HT STAs are associated
1901         (currently non-GF HT station is considered as non-HT STA also)
1902 */
1903 static int rtw_ht_operation_update(_adapter *padapter)
1904 {
1905         u16 cur_op_mode, new_op_mode;
1906         int op_mode_changes = 0;
1907         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1908         struct ht_priv  *phtpriv_ap = &pmlmepriv->htpriv;
1909
1910         if(pmlmepriv->htpriv.ht_option == _TRUE)
1911                 return 0;
1912
1913         /* if (!iface->conf->ieee80211n || iface->conf->ht_op_mode_fixed) */
1914         /*      return 0; */
1915
1916         DBG_8723A("%s current operation mode=0x%X\n",
1917                    __FUNCTION__, pmlmepriv->ht_op_mode);
1918
1919         if (!(pmlmepriv->ht_op_mode & HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT)
1920             && pmlmepriv->num_sta_ht_no_gf) {
1921                 pmlmepriv->ht_op_mode |=
1922                         HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT;
1923                 op_mode_changes++;
1924         } else if ((pmlmepriv->ht_op_mode &
1925                     HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT) &&
1926                    pmlmepriv->num_sta_ht_no_gf == 0) {
1927                 pmlmepriv->ht_op_mode &=
1928                         ~HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT;
1929                 op_mode_changes++;
1930         }
1931
1932         if (!(pmlmepriv->ht_op_mode & HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT) &&
1933             (pmlmepriv->num_sta_no_ht || pmlmepriv->olbc_ht)) {
1934                 pmlmepriv->ht_op_mode |= HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT;
1935                 op_mode_changes++;
1936         } else if ((pmlmepriv->ht_op_mode &
1937                     HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT) &&
1938                    (pmlmepriv->num_sta_no_ht == 0 && !pmlmepriv->olbc_ht)) {
1939                 pmlmepriv->ht_op_mode &=
1940                         ~HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT;
1941                 op_mode_changes++;
1942         }
1943
1944         /* Note: currently we switch to the MIXED op mode if HT non-greenfield
1945          * station is associated. Probably it's a theoretical case, since
1946          * it looks like all known HT STAs support greenfield.
1947          */
1948         new_op_mode = 0;
1949         if (pmlmepriv->num_sta_no_ht ||
1950             (pmlmepriv->ht_op_mode & HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT))
1951                 new_op_mode = OP_MODE_MIXED;
1952         else if ((phtpriv_ap->ht_cap.cap_info & IEEE80211_HT_CAP_SUP_WIDTH)
1953                  && pmlmepriv->num_sta_ht_20mhz)
1954                 new_op_mode = OP_MODE_20MHZ_HT_STA_ASSOCED;
1955         else if (pmlmepriv->olbc_ht)
1956                 new_op_mode = OP_MODE_MAY_BE_LEGACY_STAS;
1957         else
1958                 new_op_mode = OP_MODE_PURE;
1959
1960         cur_op_mode = pmlmepriv->ht_op_mode & HT_INFO_OPERATION_MODE_OP_MODE_MASK;
1961         if (cur_op_mode != new_op_mode) {
1962                 pmlmepriv->ht_op_mode &= ~HT_INFO_OPERATION_MODE_OP_MODE_MASK;
1963                 pmlmepriv->ht_op_mode |= new_op_mode;
1964                 op_mode_changes++;
1965         }
1966
1967         DBG_8723A("%s new operation mode=0x%X changes=%d\n",
1968                    __FUNCTION__, pmlmepriv->ht_op_mode, op_mode_changes);
1969
1970         return op_mode_changes;
1971 }
1972
1973 #endif /* CONFIG_80211N_HT */
1974
1975 void associated_clients_update(_adapter *padapter, u8 updated)
1976 {
1977         /* update associcated stations cap. */
1978         if(updated == _TRUE)
1979         {
1980                 _irqL irqL;
1981                 _list   *phead, *plist;
1982                 struct sta_info *psta=NULL;
1983                 struct sta_priv *pstapriv = &padapter->stapriv;
1984
1985                 spin_lock_bh(&pstapriv->asoc_list_lock);
1986
1987                 phead = &pstapriv->asoc_list;
1988                 plist = get_next(phead);
1989
1990                 /* check asoc_queue */
1991                 while ((rtw_end_of_queue_search(phead, plist)) == _FALSE)
1992                 {
1993                         psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);
1994
1995                         plist = get_next(plist);
1996
1997                         VCS_update(padapter, psta);
1998                 }
1999
2000                 spin_unlock_bh(&pstapriv->asoc_list_lock);
2001
2002         }
2003 }
2004
2005 /* called > TSR LEVEL for USB or SDIO Interface*/
2006 void bss_cap_update_on_sta_join(_adapter *padapter, struct sta_info *psta)
2007 {
2008         u8 beacon_updated = _FALSE;
2009         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
2010         struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
2011
2012 #if 0
2013         if (!(psta->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) &&
2014             !psta->no_short_preamble_set) {
2015                 psta->no_short_preamble_set = 1;
2016                 pmlmepriv->num_sta_no_short_preamble++;
2017                 if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) &&
2018                      (pmlmepriv->num_sta_no_short_preamble == 1))
2019                         ieee802_11_set_beacons(hapd->iface);
2020         }
2021 #endif
2022
2023         if(!(psta->flags & WLAN_STA_SHORT_PREAMBLE))
2024         {
2025                 if(!psta->no_short_preamble_set)
2026                 {
2027                         psta->no_short_preamble_set = 1;
2028
2029                         pmlmepriv->num_sta_no_short_preamble++;
2030
2031                         if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) &&
2032                                 (pmlmepriv->num_sta_no_short_preamble == 1))
2033                         {
2034                                 beacon_updated = _TRUE;
2035                                 update_beacon(padapter, 0xFF, NULL, _TRUE);
2036                         }
2037
2038                 }
2039         }
2040         else
2041         {
2042                 if(psta->no_short_preamble_set)
2043                 {
2044                         psta->no_short_preamble_set = 0;
2045
2046                         pmlmepriv->num_sta_no_short_preamble--;
2047
2048                         if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) &&
2049                                 (pmlmepriv->num_sta_no_short_preamble == 0))
2050                         {
2051                                 beacon_updated = _TRUE;
2052                                 update_beacon(padapter, 0xFF, NULL, _TRUE);
2053                         }
2054
2055                 }
2056         }
2057
2058 #if 0
2059         if (psta->flags & WLAN_STA_NONERP && !psta->nonerp_set) {
2060                 psta->nonerp_set = 1;
2061                 pmlmepriv->num_sta_non_erp++;
2062                 if (pmlmepriv->num_sta_non_erp == 1)
2063                         ieee802_11_set_beacons(hapd->iface);
2064         }
2065 #endif
2066
2067         if(psta->flags & WLAN_STA_NONERP)
2068         {
2069                 if(!psta->nonerp_set)
2070                 {
2071                         psta->nonerp_set = 1;
2072
2073                         pmlmepriv->num_sta_non_erp++;
2074
2075                         if (pmlmepriv->num_sta_non_erp == 1)
2076                         {
2077                                 beacon_updated = _TRUE;
2078                                 update_beacon(padapter, _ERPINFO_IE_, NULL, _TRUE);
2079                         }
2080                 }
2081
2082         }
2083         else
2084         {
2085                 if(psta->nonerp_set)
2086                 {
2087                         psta->nonerp_set = 0;
2088
2089                         pmlmepriv->num_sta_non_erp--;
2090
2091                         if (pmlmepriv->num_sta_non_erp == 0)
2092                         {
2093                                 beacon_updated = _TRUE;
2094                                 update_beacon(padapter, _ERPINFO_IE_, NULL, _TRUE);
2095                         }
2096                 }
2097
2098         }
2099
2100 #if 0
2101         if (!(psta->capability & WLAN_CAPABILITY_SHORT_SLOT) &&
2102             !psta->no_short_slot_time_set) {
2103                 psta->no_short_slot_time_set = 1;
2104                 pmlmepriv->num_sta_no_short_slot_time++;
2105                 if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) &&
2106                     (pmlmepriv->num_sta_no_short_slot_time == 1))
2107                         ieee802_11_set_beacons(hapd->iface);
2108         }
2109 #endif
2110
2111         if(!(psta->capability & WLAN_CAPABILITY_SHORT_SLOT))
2112         {
2113                 if(!psta->no_short_slot_time_set)
2114                 {
2115                         psta->no_short_slot_time_set = 1;
2116
2117                         pmlmepriv->num_sta_no_short_slot_time++;
2118
2119                         if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) &&
2120                                  (pmlmepriv->num_sta_no_short_slot_time == 1))
2121                         {
2122                                 beacon_updated = _TRUE;
2123                                 update_beacon(padapter, 0xFF, NULL, _TRUE);
2124                         }
2125
2126                 }
2127         }
2128         else
2129         {
2130                 if(psta->no_short_slot_time_set)
2131                 {
2132                         psta->no_short_slot_time_set = 0;
2133
2134                         pmlmepriv->num_sta_no_short_slot_time--;
2135
2136                         if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) &&
2137                                  (pmlmepriv->num_sta_no_short_slot_time == 0))
2138                         {
2139                                 beacon_updated = _TRUE;
2140                                 update_beacon(padapter, 0xFF, NULL, _TRUE);
2141                         }
2142                 }
2143         }
2144
2145 #ifdef CONFIG_80211N_HT
2146
2147         if (psta->flags & WLAN_STA_HT)
2148         {
2149                 u16 ht_capab = le16_to_cpu(psta->htpriv.ht_cap.cap_info);
2150
2151                 DBG_8723A("HT: STA " MAC_FMT " HT Capabilities "
2152                            "Info: 0x%04x\n", MAC_ARG(psta->hwaddr), ht_capab);
2153
2154                 if (psta->no_ht_set) {
2155                         psta->no_ht_set = 0;
2156                         pmlmepriv->num_sta_no_ht--;
2157                 }
2158
2159                 if ((ht_capab & IEEE80211_HT_CAP_GRN_FLD) == 0) {
2160                         if (!psta->no_ht_gf_set) {
2161                                 psta->no_ht_gf_set = 1;
2162                                 pmlmepriv->num_sta_ht_no_gf++;
2163                         }
2164                         DBG_8723A("%s STA " MAC_FMT " - no "
2165                                    "greenfield, num of non-gf stations %d\n",
2166                                    __FUNCTION__, MAC_ARG(psta->hwaddr),
2167                                    pmlmepriv->num_sta_ht_no_gf);
2168                 }
2169
2170                 if ((ht_capab & IEEE80211_HT_CAP_SUP_WIDTH) == 0) {
2171                         if (!psta->ht_20mhz_set) {
2172                                 psta->ht_20mhz_set = 1;
2173                                 pmlmepriv->num_sta_ht_20mhz++;
2174                         }
2175                         DBG_8723A("%s STA " MAC_FMT " - 20 MHz HT, "
2176                                    "num of 20MHz HT STAs %d\n",
2177                                    __FUNCTION__, MAC_ARG(psta->hwaddr),
2178                                    pmlmepriv->num_sta_ht_20mhz);
2179                 }
2180
2181         }
2182         else
2183         {
2184                 if (!psta->no_ht_set) {
2185                         psta->no_ht_set = 1;
2186                         pmlmepriv->num_sta_no_ht++;
2187                 }
2188                 if(pmlmepriv->htpriv.ht_option == _TRUE) {
2189                         DBG_8723A("%s STA " MAC_FMT
2190                                    " - no HT, num of non-HT stations %d\n",
2191                                    __FUNCTION__, MAC_ARG(psta->hwaddr),
2192                                    pmlmepriv->num_sta_no_ht);
2193                 }
2194         }
2195
2196         if (rtw_ht_operation_update(padapter) > 0)
2197         {
2198                 update_beacon(padapter, _HT_CAPABILITY_IE_, NULL, _FALSE);
2199                 update_beacon(padapter, _HT_ADD_INFO_IE_, NULL, _TRUE);
2200         }
2201
2202 #endif /* CONFIG_80211N_HT */
2203
2204         /* update associcated stations cap. */
2205         associated_clients_update(padapter,  beacon_updated);
2206
2207         DBG_8723A("%s, updated=%d\n", __func__, beacon_updated);
2208 }
2209
2210 u8 bss_cap_update_on_sta_leave(_adapter *padapter, struct sta_info *psta)
2211 {
2212         u8 beacon_updated = _FALSE;
2213         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
2214         struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
2215
2216         if(!psta)
2217                 return beacon_updated;
2218
2219         if (psta->no_short_preamble_set) {
2220                 psta->no_short_preamble_set = 0;
2221                 pmlmepriv->num_sta_no_short_preamble--;
2222                 if (pmlmeext->cur_wireless_mode > WIRELESS_11B
2223                     && pmlmepriv->num_sta_no_short_preamble == 0)
2224                 {
2225                         beacon_updated = _TRUE;
2226                         update_beacon(padapter, 0xFF, NULL, _TRUE);
2227                 }
2228         }
2229
2230         if (psta->nonerp_set) {
2231                 psta->nonerp_set = 0;
2232                 pmlmepriv->num_sta_non_erp--;
2233                 if (pmlmepriv->num_sta_non_erp == 0)
2234                 {
2235                         beacon_updated = _TRUE;
2236                         update_beacon(padapter, _ERPINFO_IE_, NULL, _TRUE);
2237                 }
2238         }
2239
2240         if (psta->no_short_slot_time_set) {
2241                 psta->no_short_slot_time_set = 0;
2242                 pmlmepriv->num_sta_no_short_slot_time--;
2243                 if (pmlmeext->cur_wireless_mode > WIRELESS_11B
2244                     && pmlmepriv->num_sta_no_short_slot_time == 0)
2245                 {
2246                         beacon_updated = _TRUE;
2247                         update_beacon(padapter, 0xFF, NULL, _TRUE);
2248                 }
2249         }
2250
2251 #ifdef CONFIG_80211N_HT
2252
2253         if (psta->no_ht_gf_set) {
2254                 psta->no_ht_gf_set = 0;
2255                 pmlmepriv->num_sta_ht_no_gf--;
2256         }
2257
2258         if (psta->no_ht_set) {
2259                 psta->no_ht_set = 0;
2260                 pmlmepriv->num_sta_no_ht--;
2261         }
2262
2263         if (psta->ht_20mhz_set) {
2264                 psta->ht_20mhz_set = 0;
2265                 pmlmepriv->num_sta_ht_20mhz--;
2266         }
2267
2268         if (rtw_ht_operation_update(padapter) > 0)
2269         {
2270                 update_beacon(padapter, _HT_CAPABILITY_IE_, NULL, _FALSE);
2271                 update_beacon(padapter, _HT_ADD_INFO_IE_, NULL, _TRUE);
2272         }
2273
2274 #endif /* CONFIG_80211N_HT */
2275
2276         /* update associcated stations cap. */
2277
2278         DBG_8723A("%s, updated=%d\n", __func__, beacon_updated);
2279
2280         return beacon_updated;
2281 }
2282
2283 u8 ap_free_sta(_adapter *padapter, struct sta_info *psta, bool active, u16 reason)
2284 {
2285         _irqL irqL;
2286         u8 beacon_updated = _FALSE;
2287         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
2288         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
2289         struct sta_priv *pstapriv = &padapter->stapriv;
2290
2291         if(!psta)
2292                 return beacon_updated;
2293
2294         if (active == _TRUE)
2295         {
2296 #ifdef CONFIG_80211N_HT
2297                 /* tear down Rx AMPDU */
2298                 send_delba(padapter, 0, psta->hwaddr);/*  recipient */
2299
2300                 /* tear down TX AMPDU */
2301                 send_delba(padapter, 1, psta->hwaddr);/* originator */
2302
2303 #endif /* CONFIG_80211N_HT */
2304
2305                 issue_deauth(padapter, psta->hwaddr, reason);
2306         }
2307
2308         psta->htpriv.agg_enable_bitmap = 0x0;/* reset */
2309         psta->htpriv.candidate_tid_bitmap = 0x0;/* reset */
2310
2311         /* report_del_sta_event(padapter, psta->hwaddr, reason); */
2312
2313         /* clear cam entry / key */
2314         /* clear_cam_entry(padapter, (psta->mac_id + 3)); */
2315         rtw_clearstakey_cmd(padapter, (u8*)psta, (u8)(psta->mac_id + 3), _TRUE);
2316
2317         spin_lock_bh(&psta->lock);
2318         psta->state &= ~_FW_LINKED;
2319         spin_unlock_bh(&psta->lock);
2320
2321         #ifdef CONFIG_IOCTL_CFG80211
2322         if (1) {
2323                 #ifdef COMPAT_KERNEL_RELEASE
2324                 rtw_cfg80211_indicate_sta_disassoc(padapter, psta->hwaddr, reason);
2325                 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) && !defined(CONFIG_CFG80211_FORCE_COMPATIBLE_2_6_37_UNDER)
2326                 rtw_cfg80211_indicate_sta_disassoc(padapter, psta->hwaddr, reason);
2327                 #else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) && !defined(CONFIG_CFG80211_FORCE_COMPATIBLE_2_6_37_UNDER) */
2328                 /* will call rtw_cfg80211_indicate_sta_disassoc() in cmd_thread for old API context */
2329                 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) && !defined(CONFIG_CFG80211_FORCE_COMPATIBLE_2_6_37_UNDER) */
2330         } else
2331         #endif /* CONFIG_IOCTL_CFG80211 */
2332         {
2333                 rtw_indicate_sta_disassoc_event(padapter, psta);
2334         }
2335
2336         report_del_sta_event(padapter, psta->hwaddr, reason);
2337
2338         beacon_updated = bss_cap_update_on_sta_leave(padapter, psta);
2339
2340         spin_lock_bh(&(pstapriv->sta_hash_lock));
2341         rtw_free_stainfo(padapter, psta);
2342         spin_unlock_bh(&(pstapriv->sta_hash_lock));
2343
2344         return beacon_updated;
2345 }
2346
2347 int rtw_ap_inform_ch_switch(_adapter *padapter, u8 new_ch, u8 ch_offset)
2348 {
2349         _irqL irqL;
2350         _list   *phead, *plist;
2351         int ret=0;
2352         struct sta_info *psta = NULL;
2353         struct sta_priv *pstapriv = &padapter->stapriv;
2354         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2355         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
2356         u8 bc_addr[ETH_ALEN] = {0xff,0xff,0xff,0xff,0xff,0xff};
2357
2358         if((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE)
2359                 return ret;
2360
2361         DBG_8723A(FUNC_NDEV_FMT" with ch:%u, offset:%u\n",
2362                 FUNC_NDEV_ARG(padapter->pnetdev), new_ch, ch_offset);
2363
2364         spin_lock_bh(&pstapriv->asoc_list_lock);
2365         phead = &pstapriv->asoc_list;
2366         plist = get_next(phead);
2367
2368         /* for each sta in asoc_queue */
2369         while ((rtw_end_of_queue_search(phead, plist)) == _FALSE)
2370         {
2371                 psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);
2372                 plist = get_next(plist);
2373
2374                 issue_action_spct_ch_switch(padapter, psta->hwaddr, new_ch, ch_offset);
2375                 psta->expire_to = ((pstapriv->expire_to * 2) > 5) ? 5 : (pstapriv->expire_to * 2);
2376         }
2377         spin_unlock_bh(&pstapriv->asoc_list_lock);
2378
2379         issue_action_spct_ch_switch(padapter, bc_addr, new_ch, ch_offset);
2380
2381         return ret;
2382 }
2383
2384 int rtw_sta_flush(_adapter *padapter)
2385 {
2386         _irqL irqL;
2387         _list   *phead, *plist;
2388         int ret=0;
2389         struct sta_info *psta = NULL;
2390         struct sta_priv *pstapriv = &padapter->stapriv;
2391         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2392         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
2393         u8 bc_addr[ETH_ALEN] = {0xff,0xff,0xff,0xff,0xff,0xff};
2394         u8 chk_alive_num = 0;
2395         char chk_alive_list[NUM_STA];
2396         int i;
2397
2398         DBG_8723A(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(padapter->pnetdev));
2399
2400         if((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE)
2401                 return ret;
2402
2403         spin_lock_bh(&pstapriv->asoc_list_lock);
2404         phead = &pstapriv->asoc_list;
2405         plist = get_next(phead);
2406
2407         while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {
2408                 int stainfo_offset;
2409
2410                 psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);
2411                 plist = get_next(plist);
2412
2413                 /* Remove sta from asoc_list */
2414                 rtw_list_delete(&psta->asoc_list);
2415                 pstapriv->asoc_list_cnt--;
2416
2417                 /* Keep sta for ap_free_sta() beyond this asoc_list loop */
2418                 stainfo_offset = rtw_stainfo_offset(pstapriv, psta);
2419                 if (stainfo_offset_valid(stainfo_offset)) {
2420                         chk_alive_list[chk_alive_num++] = stainfo_offset;
2421                 }
2422         }
2423         spin_unlock_bh(&pstapriv->asoc_list_lock);
2424
2425         /* For each sta in chk_alive_list, call ap_free_sta */
2426         for (i = 0; i < chk_alive_num; i++) {
2427                 psta = rtw_get_stainfo_by_offset(pstapriv, chk_alive_list[i]);
2428                 ap_free_sta(padapter, psta, _TRUE, WLAN_REASON_DEAUTH_LEAVING);
2429         }
2430
2431         issue_deauth(padapter, bc_addr, WLAN_REASON_DEAUTH_LEAVING);
2432
2433         associated_clients_update(padapter, _TRUE);
2434
2435         return ret;
2436 }
2437
2438 /* called > TSR LEVEL for USB or SDIO Interface*/
2439 void sta_info_update(_adapter *padapter, struct sta_info *psta)
2440 {
2441         int flags = psta->flags;
2442         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
2443
2444         /* update wmm cap. */
2445         if(WLAN_STA_WME&flags)
2446                 psta->qos_option = 1;
2447         else
2448                 psta->qos_option = 0;
2449
2450         if(pmlmepriv->qospriv.qos_option == 0)
2451                 psta->qos_option = 0;
2452
2453 #ifdef CONFIG_80211N_HT
2454         /* update 802.11n ht cap. */
2455         if(WLAN_STA_HT&flags)
2456         {
2457                 psta->htpriv.ht_option = _TRUE;
2458                 psta->qos_option = 1;
2459         }
2460         else
2461         {
2462                 psta->htpriv.ht_option = _FALSE;
2463         }
2464
2465         if(pmlmepriv->htpriv.ht_option == _FALSE)
2466                 psta->htpriv.ht_option = _FALSE;
2467 #endif
2468
2469         update_sta_info_apmode(padapter, psta);
2470 }
2471
2472 /* called >= TSR LEVEL for USB or SDIO Interface*/
2473 void ap_sta_info_defer_update(_adapter *padapter, struct sta_info *psta)
2474 {
2475         if(psta->state & _FW_LINKED)
2476         {
2477                 /* add ratid */
2478                 add_RATid(padapter, psta, 0);/* DM_RATR_STA_INIT */
2479         }
2480 }
2481
2482 /* restore hw setting from sw data structures */
2483 void rtw_ap_restore_network(_adapter *padapter)
2484 {
2485         struct mlme_priv *mlmepriv = &padapter->mlmepriv;
2486         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
2487         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
2488         struct sta_priv * pstapriv = &padapter->stapriv;
2489         struct sta_info *psta;
2490         struct security_priv* psecuritypriv=&(padapter->securitypriv);
2491         _irqL irqL;
2492         _list   *phead, *plist;
2493         u8 chk_alive_num = 0;
2494         char chk_alive_list[NUM_STA];
2495         int i;
2496
2497         rtw_setopmode_cmd(padapter, Ndis802_11APMode);
2498
2499         set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
2500
2501         start_bss_network(padapter, (u8*)&mlmepriv->cur_network.network);
2502
2503         if((padapter->securitypriv.dot11PrivacyAlgrthm == _TKIP_) ||
2504                 (padapter->securitypriv.dot11PrivacyAlgrthm == _AES_))
2505         {
2506                 /* restore group key, WEP keys is restored in ips_leave() */
2507                 rtw_set_key(padapter, psecuritypriv, psecuritypriv->dot118021XGrpKeyid, 0);
2508         }
2509
2510         /* per sta pairwise key and settings */
2511         if((padapter->securitypriv.dot11PrivacyAlgrthm != _TKIP_) &&
2512                 (padapter->securitypriv.dot11PrivacyAlgrthm != _AES_)) {
2513                 return;
2514         }
2515
2516         spin_lock_bh(&pstapriv->asoc_list_lock);
2517
2518         phead = &pstapriv->asoc_list;
2519         plist = get_next(phead);
2520
2521         while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {
2522                 int stainfo_offset;
2523
2524                 psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);
2525                 plist = get_next(plist);
2526
2527                 stainfo_offset = rtw_stainfo_offset(pstapriv, psta);
2528                 if (stainfo_offset_valid(stainfo_offset)) {
2529                         chk_alive_list[chk_alive_num++] = stainfo_offset;
2530                 }
2531         }
2532
2533         spin_unlock_bh(&pstapriv->asoc_list_lock);
2534
2535         for (i = 0; i < chk_alive_num; i++) {
2536                 psta = rtw_get_stainfo_by_offset(pstapriv, chk_alive_list[i]);
2537
2538                 if (psta == NULL) {
2539                         DBG_8723A(FUNC_ADPT_FMT" sta_info is null\n", FUNC_ADPT_ARG(padapter));
2540                 }
2541                 else if(psta->state &_FW_LINKED)
2542                 {
2543                         Update_RA_Entry(padapter, psta);
2544                         /* pairwise key */
2545                         rtw_setstakey_cmd(padapter, (unsigned char *)psta, _TRUE);
2546                 }
2547         }
2548 }
2549
2550 void start_ap_mode(_adapter *padapter)
2551 {
2552         int i;
2553         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
2554         struct sta_priv *pstapriv = &padapter->stapriv;
2555         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2556         struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;
2557
2558         pmlmepriv->update_bcn = _FALSE;
2559
2560         /* init_mlme_ap_info(padapter); */
2561         pmlmeext->bstart_bss = _FALSE;
2562
2563         pmlmepriv->num_sta_non_erp = 0;
2564
2565         pmlmepriv->num_sta_no_short_slot_time = 0;
2566
2567         pmlmepriv->num_sta_no_short_preamble = 0;
2568
2569         pmlmepriv->num_sta_ht_no_gf = 0;
2570 #ifdef CONFIG_80211N_HT
2571         pmlmepriv->num_sta_no_ht = 0;
2572 #endif /* CONFIG_80211N_HT */
2573         pmlmepriv->num_sta_ht_20mhz = 0;
2574
2575         pmlmepriv->olbc = _FALSE;
2576
2577         pmlmepriv->olbc_ht = _FALSE;
2578
2579 #ifdef CONFIG_80211N_HT
2580         pmlmepriv->ht_op_mode = 0;
2581 #endif
2582
2583         for(i=0; i<NUM_STA; i++)
2584                 pstapriv->sta_aid[i] = NULL;
2585
2586         pmlmepriv->wps_beacon_ie = NULL;
2587         pmlmepriv->wps_probe_resp_ie = NULL;
2588         pmlmepriv->wps_assoc_resp_ie = NULL;
2589
2590         pmlmepriv->p2p_beacon_ie = NULL;
2591         pmlmepriv->p2p_probe_resp_ie = NULL;
2592
2593         /* for ACL */
2594         _rtw_init_listhead(&(pacl_list->acl_node_q.queue));
2595         pacl_list->num = 0;
2596         pacl_list->mode = 0;
2597         for(i = 0; i < NUM_ACL; i++) {
2598                 _rtw_init_listhead(&pacl_list->aclnode[i].list);
2599                 pacl_list->aclnode[i].valid = _FALSE;
2600         }
2601 }
2602
2603 void stop_ap_mode(_adapter *padapter)
2604 {
2605         _irqL irqL;
2606         _list   *phead, *plist;
2607         struct rtw_wlan_acl_node *paclnode;
2608         struct sta_info *psta=NULL;
2609         struct sta_priv *pstapriv = &padapter->stapriv;
2610         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
2611         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2612         struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;
2613         _queue  *pacl_node_q =&pacl_list->acl_node_q;
2614
2615         pmlmepriv->update_bcn = _FALSE;
2616         pmlmeext->bstart_bss = _FALSE;
2617
2618         /* reset and init security priv , this can refine with rtw_reset_securitypriv */
2619         memset((unsigned char *)&padapter->securitypriv, 0, sizeof (struct security_priv));
2620         padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeOpen;
2621         padapter->securitypriv.ndisencryptstatus = Ndis802_11WEPDisabled;
2622
2623         /* for ACL */
2624         spin_lock_bh(&(pacl_node_q->lock));
2625         phead = get_list_head(pacl_node_q);
2626         plist = get_next(phead);
2627         while ((rtw_end_of_queue_search(phead, plist)) == _FALSE)
2628         {
2629                 paclnode = LIST_CONTAINOR(plist, struct rtw_wlan_acl_node, list);
2630                 plist = get_next(plist);
2631
2632                 if(paclnode->valid == _TRUE)
2633                 {
2634                         paclnode->valid = _FALSE;
2635
2636                         rtw_list_delete(&paclnode->list);
2637
2638                         pacl_list->num--;
2639                 }
2640         }
2641         spin_unlock_bh(&(pacl_node_q->lock));
2642
2643         DBG_8723A("%s, free acl_node_queue, num=%d\n", __func__, pacl_list->num);
2644
2645         rtw_sta_flush(padapter);
2646
2647         /* free_assoc_sta_resources */
2648         rtw_free_all_stainfo(padapter);
2649
2650         psta = rtw_get_bcmc_stainfo(padapter);
2651         spin_lock_bh(&(pstapriv->sta_hash_lock));
2652         rtw_free_stainfo(padapter, psta);
2653         spin_unlock_bh(&(pstapriv->sta_hash_lock));
2654
2655         rtw_init_bcmc_stainfo(padapter);
2656
2657         rtw_free_mlme_priv_ie_data(pmlmepriv);
2658 }
2659
2660 #endif /* CONFIG_NATIVEAP_MLME */
2661 #endif /* CONFIG_AP_MODE */