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