]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/blame - drivers/staging/rtl8188eu/core/rtw_ap.c
staging: rtl8188eu: core: rtw_ap : Remove unnecessary functions
[mirror_ubuntu-zesty-kernel.git] / drivers / staging / rtl8188eu / core / rtw_ap.c
CommitLineData
9a7fe54d
LF
1/******************************************************************************
2 *
3 * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
17 *
18 *
19 ******************************************************************************/
20#define _RTW_AP_C_
21
04fbf979
PG
22#include <linux/ieee80211.h>
23
9a7fe54d
LF
24#include <osdep_service.h>
25#include <drv_types.h>
26#include <wifi.h>
27#include <ieee80211.h>
e4504a15 28#include <asm/unaligned.h>
9a7fe54d
LF
29
30#ifdef CONFIG_88EU_AP_MODE
31
32void init_mlme_ap_info(struct adapter *padapter)
33{
34 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
35 struct sta_priv *pstapriv = &padapter->stapriv;
36 struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;
37
38
f214e521 39 spin_lock_init(&pmlmepriv->bcn_update_lock);
9a7fe54d
LF
40
41 /* for ACL */
42 _rtw_init_queue(&pacl_list->acl_node_q);
43
44 start_ap_mode(padapter);
45}
46
47void free_mlme_ap_info(struct adapter *padapter)
48{
9a7fe54d
LF
49 struct sta_info *psta = NULL;
50 struct sta_priv *pstapriv = &padapter->stapriv;
51 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
52 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
53 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
54
55 pmlmepriv->update_bcn = false;
56 pmlmeext->bstart_bss = false;
57
58 rtw_sta_flush(padapter);
59
60 pmlmeinfo->state = _HW_STATE_NOLINK_;
61
62 /* free_assoc_sta_resources */
63 rtw_free_all_stainfo(padapter);
64
65 /* free bc/mc sta_info */
66 psta = rtw_get_bcmc_stainfo(padapter);
7057dcb3 67 spin_lock_bh(&(pstapriv->sta_hash_lock));
9a7fe54d 68 rtw_free_stainfo(padapter, psta);
e02bcf61 69 spin_unlock_bh(&(pstapriv->sta_hash_lock));
9a7fe54d
LF
70}
71
72static void update_BCNTIM(struct adapter *padapter)
73{
74 struct sta_priv *pstapriv = &padapter->stapriv;
75 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
76 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
77 struct wlan_bssid_ex *pnetwork_mlmeext = &(pmlmeinfo->network);
78 unsigned char *pie = pnetwork_mlmeext->IEs;
79
80 /* update TIM IE */
81 if (true) {
82 u8 *p, *dst_ie, *premainder_ie = NULL;
83 u8 *pbackup_remainder_ie = NULL;
9a7fe54d
LF
84 uint offset, tmp_len, tim_ielen, tim_ie_offset, remainder_ielen;
85
0a36d5fb
JT
86 p = rtw_get_ie(pie + _FIXED_IE_LENGTH_, _TIM_IE_, &tim_ielen,
87 pnetwork_mlmeext->IELength - _FIXED_IE_LENGTH_);
9a7fe54d
LF
88 if (p != NULL && tim_ielen > 0) {
89 tim_ielen += 2;
90 premainder_ie = p+tim_ielen;
91 tim_ie_offset = (int)(p - pie);
0a36d5fb
JT
92 remainder_ielen = pnetwork_mlmeext->IELength -
93 tim_ie_offset - tim_ielen;
9a7fe54d
LF
94 /* append TIM IE from dst_ie offset */
95 dst_ie = p;
96 } else {
97 tim_ielen = 0;
98
40a46d8b 99 /* calculate head_len */
9a7fe54d
LF
100 offset = _FIXED_IE_LENGTH_;
101 offset += pnetwork_mlmeext->Ssid.SsidLength + 2;
102
103 /* get supported rates len */
0a36d5fb
JT
104 p = rtw_get_ie(pie + _BEACON_IE_OFFSET_,
105 _SUPPORTEDRATES_IE_, &tmp_len,
106 (pnetwork_mlmeext->IELength -
107 _BEACON_IE_OFFSET_));
9a7fe54d
LF
108 if (p != NULL)
109 offset += tmp_len+2;
110
111 /* DS Parameter Set IE, len = 3 */
112 offset += 3;
113
114 premainder_ie = pie + offset;
115
0a36d5fb
JT
116 remainder_ielen = pnetwork_mlmeext->IELength -
117 offset - tim_ielen;
9a7fe54d
LF
118
119 /* append TIM IE from offset */
120 dst_ie = pie + offset;
121 }
122
123 if (remainder_ielen > 0) {
124 pbackup_remainder_ie = rtw_malloc(remainder_ielen);
125 if (pbackup_remainder_ie && premainder_ie)
0a36d5fb
JT
126 memcpy(pbackup_remainder_ie,
127 premainder_ie, remainder_ielen);
9a7fe54d
LF
128 }
129 *dst_ie++ = _TIM_IE_;
130
0a36d5fb
JT
131 if ((pstapriv->tim_bitmap&0xff00) &&
132 (pstapriv->tim_bitmap&0x00fc))
9a7fe54d
LF
133 tim_ielen = 5;
134 else
135 tim_ielen = 4;
136
137 *dst_ie++ = tim_ielen;
138
139 *dst_ie++ = 0;/* DTIM count */
40a46d8b 140 *dst_ie++ = 1;/* DTIM period */
9a7fe54d
LF
141
142 if (pstapriv->tim_bitmap&BIT(0))/* for bc/mc frames */
143 *dst_ie++ = BIT(0);/* bitmap ctrl */
144 else
145 *dst_ie++ = 0;
146
147 if (tim_ielen == 4) {
e4504a15 148 *dst_ie++ = pstapriv->tim_bitmap & 0xff;
9a7fe54d 149 } else if (tim_ielen == 5) {
e4504a15 150 put_unaligned_le16(pstapriv->tim_bitmap, dst_ie);
9a7fe54d
LF
151 dst_ie += 2;
152 }
153
154 /* copy remainder IE */
155 if (pbackup_remainder_ie) {
156 memcpy(dst_ie, pbackup_remainder_ie, remainder_ielen);
157
158 kfree(pbackup_remainder_ie);
159 }
160 offset = (uint)(dst_ie - pie);
161 pnetwork_mlmeext->IELength = offset + remainder_ielen;
162 }
163
164 set_tx_beacon_cmd(padapter);
165}
166
0a36d5fb
JT
167void rtw_add_bcn_ie(struct adapter *padapter, struct wlan_bssid_ex *pnetwork,
168 u8 index, u8 *data, u8 len)
9a7fe54d
LF
169{
170 struct ndis_802_11_var_ie *pIE;
171 u8 bmatch = false;
172 u8 *pie = pnetwork->IEs;
173 u8 *p = NULL, *dst_ie = NULL, *premainder_ie = NULL;
174 u8 *pbackup_remainder_ie = NULL;
175 u32 i, offset, ielen = 0, ie_offset, remainder_ielen = 0;
176
177 for (i = sizeof(struct ndis_802_11_fixed_ie); i < pnetwork->IELength;) {
178 pIE = (struct ndis_802_11_var_ie *)(pnetwork->IEs + i);
179
180 if (pIE->ElementID > index) {
181 break;
0a36d5fb
JT
182 /* already exist the same IE */
183 } else if (pIE->ElementID == index) {
9a7fe54d
LF
184 p = (u8 *)pIE;
185 ielen = pIE->Length;
186 bmatch = true;
187 break;
188 }
189 p = (u8 *)pIE;
190 ielen = pIE->Length;
191 i += (pIE->Length + 2);
192 }
193
194 if (p != NULL && ielen > 0) {
195 ielen += 2;
196
197 premainder_ie = p+ielen;
198
199 ie_offset = (int)(p - pie);
200
201 remainder_ielen = pnetwork->IELength - ie_offset - ielen;
202
203 if (bmatch)
204 dst_ie = p;
205 else
206 dst_ie = (p+ielen);
207 }
208
209 if (remainder_ielen > 0) {
210 pbackup_remainder_ie = rtw_malloc(remainder_ielen);
211 if (pbackup_remainder_ie && premainder_ie)
0a36d5fb
JT
212 memcpy(pbackup_remainder_ie,
213 premainder_ie, remainder_ielen);
9a7fe54d
LF
214 }
215
216 *dst_ie++ = index;
217 *dst_ie++ = len;
218
219 memcpy(dst_ie, data, len);
220 dst_ie += len;
221
222 /* copy remainder IE */
223 if (pbackup_remainder_ie) {
224 memcpy(dst_ie, pbackup_remainder_ie, remainder_ielen);
225
226 kfree(pbackup_remainder_ie);
227 }
228
229 offset = (uint)(dst_ie - pie);
230 pnetwork->IELength = offset + remainder_ielen;
231}
232
0a36d5fb
JT
233void rtw_remove_bcn_ie(struct adapter *padapter, struct wlan_bssid_ex *pnetwork,
234 u8 index)
9a7fe54d
LF
235{
236 u8 *p, *dst_ie = NULL, *premainder_ie = NULL;
237 u8 *pbackup_remainder_ie = NULL;
238 uint offset, ielen, ie_offset, remainder_ielen = 0;
239 u8 *pie = pnetwork->IEs;
240
241 p = rtw_get_ie(pie + _FIXED_IE_LENGTH_, index, &ielen,
242 pnetwork->IELength - _FIXED_IE_LENGTH_);
243 if (p != NULL && ielen > 0) {
244 ielen += 2;
245
246 premainder_ie = p+ielen;
247
248 ie_offset = (int)(p - pie);
249
250 remainder_ielen = pnetwork->IELength - ie_offset - ielen;
251
252 dst_ie = p;
253 }
254
255 if (remainder_ielen > 0) {
256 pbackup_remainder_ie = rtw_malloc(remainder_ielen);
257 if (pbackup_remainder_ie && premainder_ie)
0a36d5fb
JT
258 memcpy(pbackup_remainder_ie,
259 premainder_ie, remainder_ielen);
9a7fe54d
LF
260 }
261
262 /* copy remainder IE */
263 if (pbackup_remainder_ie) {
264 memcpy(dst_ie, pbackup_remainder_ie, remainder_ielen);
265
266 kfree(pbackup_remainder_ie);
267 }
268
269 offset = (uint)(dst_ie - pie);
270 pnetwork->IELength = offset + remainder_ielen;
271}
272
273static u8 chk_sta_is_alive(struct sta_info *psta)
274{
275 u8 ret = false;
276
0a36d5fb
JT
277 if ((psta->sta_stats.last_rx_data_pkts +
278 psta->sta_stats.last_rx_ctrl_pkts) ==
279 (psta->sta_stats.rx_data_pkts +
280 psta->sta_stats.rx_ctrl_pkts))
9a7fe54d
LF
281 ;
282 else
283 ret = true;
284
285 sta_update_last_rx_pkts(psta);
286
287 return ret;
288}
289
290void expire_timeout_chk(struct adapter *padapter)
291{
9a7fe54d
LF
292 struct list_head *phead, *plist;
293 u8 updated = 0;
294 struct sta_info *psta = NULL;
295 struct sta_priv *pstapriv = &padapter->stapriv;
296 u8 chk_alive_num = 0;
297 char chk_alive_list[NUM_STA];
298 int i;
299
7057dcb3 300 spin_lock_bh(&pstapriv->auth_list_lock);
9a7fe54d
LF
301
302 phead = &pstapriv->auth_list;
c44e5e39 303 plist = phead->next;
9a7fe54d
LF
304
305 /* check auth_queue */
84660700 306 while (phead != plist) {
bea88100 307 psta = container_of(plist, struct sta_info, auth_list);
c44e5e39 308 plist = plist->next;
9a7fe54d
LF
309
310 if (psta->expire_to > 0) {
311 psta->expire_to--;
312 if (psta->expire_to == 0) {
8d5bdece 313 list_del_init(&psta->auth_list);
9a7fe54d
LF
314 pstapriv->auth_list_cnt--;
315
316 DBG_88E("auth expire %6ph\n",
317 psta->hwaddr);
318
e02bcf61 319 spin_unlock_bh(&pstapriv->auth_list_lock);
9a7fe54d 320
7057dcb3 321 spin_lock_bh(&(pstapriv->sta_hash_lock));
9a7fe54d 322 rtw_free_stainfo(padapter, psta);
e02bcf61 323 spin_unlock_bh(&(pstapriv->sta_hash_lock));
9a7fe54d 324
7057dcb3 325 spin_lock_bh(&pstapriv->auth_list_lock);
9a7fe54d
LF
326 }
327 }
328
329 }
e02bcf61 330 spin_unlock_bh(&pstapriv->auth_list_lock);
9a7fe54d
LF
331
332 psta = NULL;
333
7057dcb3 334 spin_lock_bh(&pstapriv->asoc_list_lock);
9a7fe54d
LF
335
336 phead = &pstapriv->asoc_list;
c44e5e39 337 plist = phead->next;
9a7fe54d
LF
338
339 /* check asoc_queue */
84660700 340 while (phead != plist) {
bea88100 341 psta = container_of(plist, struct sta_info, asoc_list);
c44e5e39 342 plist = plist->next;
9a7fe54d
LF
343
344 if (chk_sta_is_alive(psta) || !psta->expire_to) {
345 psta->expire_to = pstapriv->expire_to;
346 psta->keep_alive_trycnt = 0;
347 psta->under_exist_checking = 0;
348 } else {
349 psta->expire_to--;
350 }
351
352 if (psta->expire_to <= 0) {
353 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
354
355 if (padapter->registrypriv.wifi_spec == 1) {
356 psta->expire_to = pstapriv->expire_to;
357 continue;
358 }
359
360 if (psta->state & WIFI_SLEEP_STATE) {
361 if (!(psta->state & WIFI_STA_ALIVE_CHK_STATE)) {
0a36d5fb
JT
362 /* to check if alive by another methods
363 * if station is at ps mode.
364 */
9a7fe54d
LF
365 psta->expire_to = pstapriv->expire_to;
366 psta->state |= WIFI_STA_ALIVE_CHK_STATE;
367
0a36d5fb
JT
368 /* to update bcn with tim_bitmap
369 * for this station
370 */
9a7fe54d 371 pstapriv->tim_bitmap |= BIT(psta->aid);
0a36d5fb
JT
372 update_beacon(padapter, _TIM_IE_,
373 NULL, false);
9a7fe54d
LF
374
375 if (!pmlmeext->active_keep_alive_check)
376 continue;
377 }
378 }
379 if (pmlmeext->active_keep_alive_check) {
380 int stainfo_offset;
381
24947258
SM
382 stainfo_offset =
383 rtw_stainfo_offset(pstapriv, psta);
9a7fe54d
LF
384 if (stainfo_offset_valid(stainfo_offset))
385 chk_alive_list[chk_alive_num++] = stainfo_offset;
386 continue;
387 }
388
8d5bdece 389 list_del_init(&psta->asoc_list);
9a7fe54d
LF
390 pstapriv->asoc_list_cnt--;
391
392 DBG_88E("asoc expire %pM, state = 0x%x\n", (psta->hwaddr), psta->state);
393 updated = ap_free_sta(padapter, psta, true, WLAN_REASON_DEAUTH_LEAVING);
394 } else {
395 /* TODO: Aging mechanism to digest frames in sleep_q to avoid running out of xmitframe */
396 if (psta->sleepq_len > (NR_XMITFRAME/pstapriv->asoc_list_cnt) &&
397 padapter->xmitpriv.free_xmitframe_cnt < (NR_XMITFRAME/pstapriv->asoc_list_cnt/2)) {
398 DBG_88E("%s sta:%pM, sleepq_len:%u, free_xmitframe_cnt:%u, asoc_list_cnt:%u, clear sleep_q\n", __func__,
399 (psta->hwaddr), psta->sleepq_len,
400 padapter->xmitpriv.free_xmitframe_cnt,
401 pstapriv->asoc_list_cnt);
402 wakeup_sta_to_xmit(padapter, psta);
403 }
404 }
405 }
406
e02bcf61 407 spin_unlock_bh(&pstapriv->asoc_list_lock);
9a7fe54d
LF
408
409 if (chk_alive_num) {
410 u8 backup_oper_channel = 0;
411 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
412 /* switch to correct channel of current network before issue keep-alive frames */
413 if (rtw_get_oper_ch(padapter) != pmlmeext->cur_channel) {
414 backup_oper_channel = rtw_get_oper_ch(padapter);
415 SelectChannel(padapter, pmlmeext->cur_channel);
416 }
417
418 /* issue null data to check sta alive*/
419 for (i = 0; i < chk_alive_num; i++) {
420 int ret = _FAIL;
421
422 psta = rtw_get_stainfo_by_offset(pstapriv, chk_alive_list[i]);
423
424 if (psta->state & WIFI_SLEEP_STATE)
425 ret = issue_nulldata(padapter, psta->hwaddr, 0, 1, 50);
426 else
427 ret = issue_nulldata(padapter, psta->hwaddr, 0, 3, 50);
428
429 psta->keep_alive_trycnt++;
430 if (ret == _SUCCESS) {
431 DBG_88E("asoc check, sta(%pM) is alive\n", (psta->hwaddr));
432 psta->expire_to = pstapriv->expire_to;
433 psta->keep_alive_trycnt = 0;
434 continue;
435 } else if (psta->keep_alive_trycnt <= 3) {
436 DBG_88E("ack check for asoc expire, keep_alive_trycnt =%d\n", psta->keep_alive_trycnt);
437 psta->expire_to = 1;
438 continue;
439 }
440
441 psta->keep_alive_trycnt = 0;
442
443 DBG_88E("asoc expire %pM, state = 0x%x\n", (psta->hwaddr), psta->state);
7057dcb3 444 spin_lock_bh(&pstapriv->asoc_list_lock);
8d5bdece 445 list_del_init(&psta->asoc_list);
9a7fe54d
LF
446 pstapriv->asoc_list_cnt--;
447 updated = ap_free_sta(padapter, psta, true, WLAN_REASON_DEAUTH_LEAVING);
e02bcf61 448 spin_unlock_bh(&pstapriv->asoc_list_lock);
9a7fe54d
LF
449 }
450
451 if (backup_oper_channel > 0) /* back to the original operation channel */
452 SelectChannel(padapter, backup_oper_channel);
453 }
454
455 associated_clients_update(padapter, updated);
456}
457
458void add_RATid(struct adapter *padapter, struct sta_info *psta, u8 rssi_level)
459{
460 int i;
461 u8 rf_type;
462 u32 init_rate = 0;
463 unsigned char sta_band = 0, raid, shortGIrate = false;
464 unsigned char limit;
465 unsigned int tx_ra_bitmap = 0;
466 struct ht_priv *psta_ht = NULL;
467 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
468 struct wlan_bssid_ex *pcur_network = (struct wlan_bssid_ex *)&pmlmepriv->cur_network.network;
469
470 if (psta)
471 psta_ht = &psta->htpriv;
472 else
473 return;
474
475 if (!(psta->state & _FW_LINKED))
476 return;
477
478 /* b/g mode ra_bitmap */
479 for (i = 0; i < sizeof(psta->bssrateset); i++) {
480 if (psta->bssrateset[i])
481 tx_ra_bitmap |= rtw_get_bit_value_from_ieee_value(psta->bssrateset[i]&0x7f);
482 }
483 /* n mode ra_bitmap */
484 if (psta_ht->ht_option) {
485 rtw_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
486 if (rf_type == RF_2T2R)
487 limit = 16;/* 2R */
488 else
489 limit = 8;/* 1R */
490
491 for (i = 0; i < limit; i++) {
492 if (psta_ht->ht_cap.supp_mcs_set[i/8] & BIT(i%8))
493 tx_ra_bitmap |= BIT(i+12);
494 }
495
496 /* max short GI rate */
497 shortGIrate = psta_ht->sgi;
498 }
499
500 if (pcur_network->Configuration.DSConfig > 14) {
501 /* 5G band */
502 if (tx_ra_bitmap & 0xffff000)
503 sta_band |= WIRELESS_11_5N | WIRELESS_11A;
504 else
505 sta_band |= WIRELESS_11A;
506 } else {
507 if (tx_ra_bitmap & 0xffff000)
508 sta_band |= WIRELESS_11_24N | WIRELESS_11G | WIRELESS_11B;
509 else if (tx_ra_bitmap & 0xff0)
510 sta_band |= WIRELESS_11G | WIRELESS_11B;
511 else
512 sta_band |= WIRELESS_11B;
513 }
514
515 psta->wireless_mode = sta_band;
516
517 raid = networktype_to_raid(sta_band);
518 init_rate = get_highest_rate_idx(tx_ra_bitmap&0x0fffffff)&0x3f;
519
520 if (psta->aid < NUM_STA) {
521 u8 arg = 0;
522
523 arg = psta->mac_id&0x1f;
524
525 arg |= BIT(7);/* support entry 2~31 */
526
527 if (shortGIrate)
528 arg |= BIT(5);
529
530 tx_ra_bitmap |= ((raid<<28)&0xf0000000);
531
532 DBG_88E("%s => mac_id:%d , raid:%d , bitmap = 0x%x, arg = 0x%x\n",
7aa36b4b 533 __func__, psta->mac_id, raid, tx_ra_bitmap, arg);
9a7fe54d
LF
534
535 /* bitmap[0:27] = tx_rate_bitmap */
536 /* bitmap[28:31]= Rate Adaptive id */
537 /* arg[0:4] = macid */
538 /* arg[5] = Short GI */
539 rtw_hal_add_ra_tid(padapter, tx_ra_bitmap, arg, rssi_level);
540
541 if (shortGIrate)
542 init_rate |= BIT(6);
543
544 /* set ra_id, init_rate */
545 psta->raid = raid;
546 psta->init_rate = init_rate;
547
548 } else {
549 DBG_88E("station aid %d exceed the max number\n", psta->aid);
550 }
551}
552
553static void update_bmc_sta(struct adapter *padapter)
554{
9a7fe54d
LF
555 u32 init_rate = 0;
556 unsigned char network_type, raid;
557 int i, supportRateNum = 0;
558 unsigned int tx_ra_bitmap = 0;
559 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
560 struct wlan_bssid_ex *pcur_network = (struct wlan_bssid_ex *)&pmlmepriv->cur_network.network;
561 struct sta_info *psta = rtw_get_bcmc_stainfo(padapter);
562
563 if (psta) {
564 psta->aid = 0;/* default set to 0 */
565 psta->mac_id = psta->aid + 1;
566
567 psta->qos_option = 0;
568 psta->htpriv.ht_option = false;
569
570 psta->ieee8021x_blocked = 0;
571
1ce39848 572 memset((void *)&psta->sta_stats, 0, sizeof(struct stainfo_stats));
9a7fe54d
LF
573
574 /* prepare for add_RATid */
575 supportRateNum = rtw_get_rateset_len((u8 *)&pcur_network->SupportedRates);
576 network_type = rtw_check_network_type((u8 *)&pcur_network->SupportedRates, supportRateNum, 1);
577
578 memcpy(psta->bssrateset, &pcur_network->SupportedRates, supportRateNum);
579 psta->bssratelen = supportRateNum;
580
581 /* b/g mode ra_bitmap */
582 for (i = 0; i < supportRateNum; i++) {
583 if (psta->bssrateset[i])
584 tx_ra_bitmap |= rtw_get_bit_value_from_ieee_value(psta->bssrateset[i]&0x7f);
585 }
586
587 if (pcur_network->Configuration.DSConfig > 14) {
588 /* force to A mode. 5G doesn't support CCK rates */
589 network_type = WIRELESS_11A;
590 tx_ra_bitmap = 0x150; /* 6, 12, 24 Mbps */
591 } else {
592 /* force to b mode */
593 network_type = WIRELESS_11B;
594 tx_ra_bitmap = 0xf;
595 }
596
597 raid = networktype_to_raid(network_type);
598 init_rate = get_highest_rate_idx(tx_ra_bitmap&0x0fffffff)&0x3f;
599
600 /* ap mode */
601 rtw_hal_set_odm_var(padapter, HAL_ODM_STA_INFO, psta, true);
602
603 {
604 u8 arg = 0;
605
606 arg = psta->mac_id&0x1f;
607 arg |= BIT(7);
608 tx_ra_bitmap |= ((raid<<28)&0xf0000000);
609 DBG_88E("update_bmc_sta, mask = 0x%x, arg = 0x%x\n", tx_ra_bitmap, arg);
610
611 /* bitmap[0:27] = tx_rate_bitmap */
612 /* bitmap[28:31]= Rate Adaptive id */
613 /* arg[0:4] = macid */
614 /* arg[5] = Short GI */
615 rtw_hal_add_ra_tid(padapter, tx_ra_bitmap, arg, 0);
616 }
617 /* set ra_id, init_rate */
618 psta->raid = raid;
619 psta->init_rate = init_rate;
620
621 rtw_stassoc_hw_rpt(padapter, psta);
622
7057dcb3 623 spin_lock_bh(&psta->lock);
9a7fe54d 624 psta->state = _FW_LINKED;
e02bcf61 625 spin_unlock_bh(&psta->lock);
9a7fe54d
LF
626
627 } else {
628 DBG_88E("add_RATid_bmc_sta error!\n");
629 }
630}
631
632/* notes: */
633/* AID: 1~MAX for sta and 0 for bc/mc in ap/adhoc mode */
634/* MAC_ID = AID+1 for sta in ap/adhoc mode */
635/* MAC_ID = 1 for bc/mc for sta/ap/adhoc */
636/* MAC_ID = 0 for bssid for sta/ap/adhoc */
637/* CAM_ID = 0~3 for default key, cmd_id = macid + 3, macid = aid+1; */
638
639void update_sta_info_apmode(struct adapter *padapter, struct sta_info *psta)
640{
9a7fe54d
LF
641 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
642 struct security_priv *psecuritypriv = &padapter->securitypriv;
643 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
644 struct ht_priv *phtpriv_ap = &pmlmepriv->htpriv;
645 struct ht_priv *phtpriv_sta = &psta->htpriv;
646
647 psta->mac_id = psta->aid+1;
648 DBG_88E("%s\n", __func__);
649
650 /* ap mode */
651 rtw_hal_set_odm_var(padapter, HAL_ODM_STA_INFO, psta, true);
652
653 if (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X)
654 psta->ieee8021x_blocked = true;
655 else
656 psta->ieee8021x_blocked = false;
657
658
659 /* update sta's cap */
660
661 /* ERP */
662 VCS_update(padapter, psta);
663 /* HT related cap */
664 if (phtpriv_sta->ht_option) {
665 /* check if sta supports rx ampdu */
666 phtpriv_sta->ampdu_enable = phtpriv_ap->ampdu_enable;
667
668 /* check if sta support s Short GI */
669 if ((phtpriv_sta->ht_cap.cap_info & phtpriv_ap->ht_cap.cap_info) & (IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40))
670 phtpriv_sta->sgi = true;
671
672 /* bwmode */
673 if ((phtpriv_sta->ht_cap.cap_info & phtpriv_ap->ht_cap.cap_info) & IEEE80211_HT_CAP_SUP_WIDTH) {
674 phtpriv_sta->bwmode = pmlmeext->cur_bwmode;
675 phtpriv_sta->ch_offset = pmlmeext->cur_ch_offset;
676 }
677 psta->qos_option = true;
678 } else {
679 phtpriv_sta->ampdu_enable = false;
680 phtpriv_sta->sgi = false;
681 phtpriv_sta->bwmode = HT_CHANNEL_WIDTH_20;
682 phtpriv_sta->ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
683 }
684
685 /* Rx AMPDU */
686 send_delba(padapter, 0, psta->hwaddr);/* recipient */
687
688 /* TX AMPDU */
689 send_delba(padapter, 1, psta->hwaddr);/* originator */
690 phtpriv_sta->agg_enable_bitmap = 0x0;/* reset */
691 phtpriv_sta->candidate_tid_bitmap = 0x0;/* reset */
692
693 /* todo: init other variables */
694
1ce39848 695 memset((void *)&psta->sta_stats, 0, sizeof(struct stainfo_stats));
9a7fe54d 696
7057dcb3 697 spin_lock_bh(&psta->lock);
9a7fe54d 698 psta->state |= _FW_LINKED;
e02bcf61 699 spin_unlock_bh(&psta->lock);
9a7fe54d
LF
700}
701
702static void update_hw_ht_param(struct adapter *padapter)
703{
704 unsigned char max_AMPDU_len;
705 unsigned char min_MPDU_spacing;
706 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
707 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
708
709 DBG_88E("%s\n", __func__);
710
711 /* handle A-MPDU parameter field */
712 /*
713 AMPDU_para [1:0]:Max AMPDU Len => 0:8k , 1:16k, 2:32k, 3:64k
714 AMPDU_para [4:2]:Min MPDU Start Spacing
715 */
716 max_AMPDU_len = pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x03;
717
718 min_MPDU_spacing = (pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x1c) >> 2;
719
720 rtw_hal_set_hwreg(padapter, HW_VAR_AMPDU_MIN_SPACE, (u8 *)(&min_MPDU_spacing));
721
722 rtw_hal_set_hwreg(padapter, HW_VAR_AMPDU_FACTOR, (u8 *)(&max_AMPDU_len));
723
724 /* */
725 /* Config SM Power Save setting */
726 /* */
727 pmlmeinfo->SM_PS = (le16_to_cpu(pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info) & 0x0C) >> 2;
728 if (pmlmeinfo->SM_PS == WLAN_HT_CAP_SM_PS_STATIC)
729 DBG_88E("%s(): WLAN_HT_CAP_SM_PS_STATIC\n", __func__);
730}
731
732static void start_bss_network(struct adapter *padapter, u8 *pbuf)
733{
734 u8 *p;
735 u8 val8, cur_channel, cur_bwmode, cur_ch_offset;
736 u16 bcn_interval;
737 u32 acparm;
738 int ie_len;
739 struct registry_priv *pregpriv = &padapter->registrypriv;
740 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
741 struct security_priv *psecuritypriv = &(padapter->securitypriv);
742 struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)&pmlmepriv->cur_network.network;
743 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
744 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
745 struct wlan_bssid_ex *pnetwork_mlmeext = &(pmlmeinfo->network);
746 struct HT_info_element *pht_info = NULL;
9a7fe54d
LF
747
748 bcn_interval = (u16)pnetwork->Configuration.BeaconPeriod;
749 cur_channel = pnetwork->Configuration.DSConfig;
750 cur_bwmode = HT_CHANNEL_WIDTH_20;
751 cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
752
753
754 /* check if there is wps ie, */
755 /* if there is wpsie in beacon, the hostapd will update beacon twice when stating hostapd, */
756 /* and at first time the security ie (RSN/WPA IE) will not include in beacon. */
757 if (!rtw_get_wps_ie(pnetwork->IEs+_FIXED_IE_LENGTH_, pnetwork->IELength-_FIXED_IE_LENGTH_, NULL, NULL))
758 pmlmeext->bstart_bss = true;
759
760 /* todo: update wmm, ht cap */
761 if (pmlmepriv->qospriv.qos_option)
762 pmlmeinfo->WMM_enable = true;
763 if (pmlmepriv->htpriv.ht_option) {
764 pmlmeinfo->WMM_enable = true;
765 pmlmeinfo->HT_enable = true;
766
767 update_hw_ht_param(padapter);
768 }
769
770 if (pmlmepriv->cur_network.join_res != true) { /* setting only at first time */
771 /* WEP Key will be set before this function, do not clear CAM. */
772 if ((psecuritypriv->dot11PrivacyAlgrthm != _WEP40_) &&
773 (psecuritypriv->dot11PrivacyAlgrthm != _WEP104_))
774 flush_all_cam_entry(padapter); /* clear CAM */
775 }
776
777 /* set MSR to AP_Mode */
778 Set_MSR(padapter, _HW_STATE_AP_);
779
780 /* Set BSSID REG */
781 rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, pnetwork->MacAddress);
782
783 /* Set EDCA param reg */
784 acparm = 0x002F3217; /* VO */
785 rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VO, (u8 *)(&acparm));
786 acparm = 0x005E4317; /* VI */
787 rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VI, (u8 *)(&acparm));
788 acparm = 0x005ea42b;
789 rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BE, (u8 *)(&acparm));
790 acparm = 0x0000A444; /* BK */
791 rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BK, (u8 *)(&acparm));
792
793 /* Set Security */
794 val8 = (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) ? 0xcc : 0xcf;
795 rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8));
796
797 /* Beacon Control related register */
798 rtw_hal_set_hwreg(padapter, HW_VAR_BEACON_INTERVAL, (u8 *)(&bcn_interval));
799
800 UpdateBrateTbl(padapter, pnetwork->SupportedRates);
801 rtw_hal_set_hwreg(padapter, HW_VAR_BASIC_RATE, pnetwork->SupportedRates);
802
803 if (!pmlmepriv->cur_network.join_res) { /* setting only at first time */
804 /* turn on all dynamic functions */
805 Switch_DM_Func(padapter, DYNAMIC_ALL_FUNC_ENABLE, true);
806 }
807 /* set channel, bwmode */
808 p = rtw_get_ie((pnetwork->IEs + sizeof(struct ndis_802_11_fixed_ie)), _HT_ADD_INFO_IE_, &ie_len, (pnetwork->IELength - sizeof(struct ndis_802_11_fixed_ie)));
809 if (p && ie_len) {
810 pht_info = (struct HT_info_element *)(p+2);
811
812 if ((pregpriv->cbw40_enable) && (pht_info->infos[0] & BIT(2))) {
813 /* switch to the 40M Hz mode */
814 cur_bwmode = HT_CHANNEL_WIDTH_40;
815 switch (pht_info->infos[0] & 0x3) {
816 case 1:
817 cur_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER;
818 break;
819 case 3:
820 cur_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER;
821 break;
822 default:
823 cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
824 break;
825 }
826 }
827 }
828 /* TODO: need to judge the phy parameters on concurrent mode for single phy */
829 set_channel_bwmode(padapter, cur_channel, cur_ch_offset, cur_bwmode);
830
831 DBG_88E("CH =%d, BW =%d, offset =%d\n", cur_channel, cur_bwmode, cur_ch_offset);
832
833 /* */
834 pmlmeext->cur_channel = cur_channel;
835 pmlmeext->cur_bwmode = cur_bwmode;
836 pmlmeext->cur_ch_offset = cur_ch_offset;
837 pmlmeext->cur_wireless_mode = pmlmepriv->cur_network.network_type;
838
839 /* update cur_wireless_mode */
840 update_wireless_mode(padapter);
841
40a46d8b 842 /* update capability after cur_wireless_mode updated */
9a7fe54d
LF
843 update_capinfo(padapter, rtw_get_capability((struct wlan_bssid_ex *)pnetwork));
844
845 /* let pnetwork_mlmeext == pnetwork_mlme. */
846 memcpy(pnetwork_mlmeext, pnetwork, pnetwork->Length);
847
9a7fe54d
LF
848 if (pmlmeext->bstart_bss) {
849 update_beacon(padapter, _TIM_IE_, NULL, false);
850
851 /* issue beacon frame */
852 if (send_beacon(padapter) == _FAIL)
ebd21582 853 DBG_88E("send_beacon, fail!\n");
9a7fe54d
LF
854 }
855
856 /* update bc/mc sta_info */
857 update_bmc_sta(padapter);
858}
859
860int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len)
861{
862 int ret = _SUCCESS;
863 u8 *p;
864 u8 *pHT_caps_ie = NULL;
865 u8 *pHT_info_ie = NULL;
866 struct sta_info *psta = NULL;
867 u16 cap, ht_cap = false;
868 uint ie_len = 0;
869 int group_cipher, pairwise_cipher;
870 u8 channel, network_type, supportRate[NDIS_802_11_LENGTH_RATES_EX];
871 int supportRateNum = 0;
872 u8 OUI1[] = {0x00, 0x50, 0xf2, 0x01};
873 u8 WMM_PARA_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01};
874 struct registry_priv *pregistrypriv = &padapter->registrypriv;
875 struct security_priv *psecuritypriv = &padapter->securitypriv;
876 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
877 struct wlan_bssid_ex *pbss_network = (struct wlan_bssid_ex *)&pmlmepriv->cur_network.network;
878 u8 *ie = pbss_network->IEs;
879
880 /* SSID */
881 /* Supported rates */
882 /* DS Params */
883 /* WLAN_EID_COUNTRY */
884 /* ERP Information element */
885 /* Extended supported rates */
886 /* WPA/WPA2 */
887 /* Wi-Fi Wireless Multimedia Extensions */
888 /* ht_capab, ht_oper */
889 /* WPS IE */
890
891 DBG_88E("%s, len =%d\n", __func__, len);
892
893 if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
894 return _FAIL;
895
896
897 if (len > MAX_IE_SZ)
898 return _FAIL;
899
900 pbss_network->IELength = len;
901
1ce39848 902 memset(ie, 0, MAX_IE_SZ);
9a7fe54d
LF
903
904 memcpy(ie, pbuf, pbss_network->IELength);
905
906
907 if (pbss_network->InfrastructureMode != Ndis802_11APMode)
908 return _FAIL;
909
910 pbss_network->Rssi = 0;
911
6d36fe3e 912 ether_addr_copy(pbss_network->MacAddress, myid(&(padapter->eeprompriv)));
9a7fe54d
LF
913
914 /* beacon interval */
915 p = rtw_get_beacon_interval_from_ie(ie);/* 8: TimeStamp, 2: Beacon Interval 2:Capability */
4b49a5b3 916 pbss_network->Configuration.BeaconPeriod = get_unaligned_le16(p);
9a7fe54d
LF
917
918 /* capability */
4b49a5b3 919 cap = get_unaligned_le16(ie);
9a7fe54d
LF
920
921 /* SSID */
922 p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _SSID_IE_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_));
923 if (p && ie_len > 0) {
1ce39848 924 memset(&pbss_network->Ssid, 0, sizeof(struct ndis_802_11_ssid));
9a7fe54d
LF
925 memcpy(pbss_network->Ssid.Ssid, (p + 2), ie_len);
926 pbss_network->Ssid.SsidLength = ie_len;
927 }
928
929 /* channel */
930 channel = 0;
931 pbss_network->Configuration.Length = 0;
932 p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _DSSET_IE_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_));
933 if (p && ie_len > 0)
934 channel = *(p + 2);
935
936 pbss_network->Configuration.DSConfig = channel;
937
1ce39848 938 memset(supportRate, 0, NDIS_802_11_LENGTH_RATES_EX);
9a7fe54d
LF
939 /* get supported rates */
940 p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _SUPPORTEDRATES_IE_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_));
941 if (p != NULL) {
942 memcpy(supportRate, p+2, ie_len);
943 supportRateNum = ie_len;
944 }
945
946 /* get ext_supported rates */
947 p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _EXT_SUPPORTEDRATES_IE_, &ie_len, pbss_network->IELength - _BEACON_IE_OFFSET_);
948 if (p != NULL) {
949 memcpy(supportRate+supportRateNum, p+2, ie_len);
950 supportRateNum += ie_len;
951 }
952
953 network_type = rtw_check_network_type(supportRate, supportRateNum, channel);
954
955 rtw_set_supported_rate(pbss_network->SupportedRates, network_type);
956
957 /* parsing ERP_IE */
958 p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _ERPINFO_IE_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_));
959 if (p && ie_len > 0)
960 ERP_IE_handler(padapter, (struct ndis_802_11_var_ie *)p);
961
962 /* update privacy/security */
963 if (cap & BIT(4))
964 pbss_network->Privacy = 1;
965 else
966 pbss_network->Privacy = 0;
967
968 psecuritypriv->wpa_psk = 0;
969
970 /* wpa2 */
971 group_cipher = 0;
972 pairwise_cipher = 0;
973 psecuritypriv->wpa2_group_cipher = _NO_PRIVACY_;
974 psecuritypriv->wpa2_pairwise_cipher = _NO_PRIVACY_;
975 p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _RSN_IE_2_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_));
976 if (p && ie_len > 0) {
977 if (rtw_parse_wpa2_ie(p, ie_len+2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) {
978 psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
979
980 psecuritypriv->dot8021xalg = 1;/* psk, todo:802.1x */
981 psecuritypriv->wpa_psk |= BIT(1);
982
983 psecuritypriv->wpa2_group_cipher = group_cipher;
984 psecuritypriv->wpa2_pairwise_cipher = pairwise_cipher;
985 }
986 }
987 /* wpa */
988 ie_len = 0;
989 group_cipher = 0;
990 pairwise_cipher = 0;
991 psecuritypriv->wpa_group_cipher = _NO_PRIVACY_;
992 psecuritypriv->wpa_pairwise_cipher = _NO_PRIVACY_;
993 for (p = ie + _BEACON_IE_OFFSET_;; p += (ie_len + 2)) {
994 p = rtw_get_ie(p, _SSN_IE_1_, &ie_len,
995 (pbss_network->IELength - _BEACON_IE_OFFSET_ - (ie_len + 2)));
f42f52aa 996 if ((p) && (!memcmp(p+2, OUI1, 4))) {
9a7fe54d
LF
997 if (rtw_parse_wpa_ie(p, ie_len+2, &group_cipher,
998 &pairwise_cipher, NULL) == _SUCCESS) {
999 psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
1000
1001 psecuritypriv->dot8021xalg = 1;/* psk, todo:802.1x */
1002
1003 psecuritypriv->wpa_psk |= BIT(0);
1004
1005 psecuritypriv->wpa_group_cipher = group_cipher;
1006 psecuritypriv->wpa_pairwise_cipher = pairwise_cipher;
1007 }
1008 break;
1009 }
1010 if ((p == NULL) || (ie_len == 0))
1011 break;
1012 }
1013
1014 /* wmm */
1015 ie_len = 0;
1016 pmlmepriv->qospriv.qos_option = 0;
1017 if (pregistrypriv->wmm_enable) {
1018 for (p = ie + _BEACON_IE_OFFSET_;; p += (ie_len + 2)) {
1019 p = rtw_get_ie(p, _VENDOR_SPECIFIC_IE_, &ie_len,
1020 (pbss_network->IELength - _BEACON_IE_OFFSET_ - (ie_len + 2)));
f42f52aa 1021 if ((p) && !memcmp(p+2, WMM_PARA_IE, 6)) {
9a7fe54d
LF
1022 pmlmepriv->qospriv.qos_option = 1;
1023
1024 *(p+8) |= BIT(7);/* QoS Info, support U-APSD */
1025
1026 /* disable all ACM bits since the WMM admission control is not supported */
1027 *(p + 10) &= ~BIT(4); /* BE */
1028 *(p + 14) &= ~BIT(4); /* BK */
1029 *(p + 18) &= ~BIT(4); /* VI */
1030 *(p + 22) &= ~BIT(4); /* VO */
1031 break;
1032 }
1033
1034 if ((p == NULL) || (ie_len == 0))
1035 break;
1036 }
1037 }
1038 /* parsing HT_CAP_IE */
1039 p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_CAPABILITY_IE_, &ie_len,
1040 (pbss_network->IELength - _BEACON_IE_OFFSET_));
1041 if (p && ie_len > 0) {
1042 u8 rf_type;
1043 struct rtw_ieee80211_ht_cap *pht_cap = (struct rtw_ieee80211_ht_cap *)(p+2);
1044
1045 pHT_caps_ie = p;
1046 ht_cap = true;
1047 network_type |= WIRELESS_11_24N;
1048
1049 rtw_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
1050
1051 if ((psecuritypriv->wpa_pairwise_cipher & WPA_CIPHER_CCMP) ||
1052 (psecuritypriv->wpa2_pairwise_cipher & WPA_CIPHER_CCMP))
1053 pht_cap->ampdu_params_info |= (IEEE80211_HT_CAP_AMPDU_DENSITY&(0x07<<2));
1054 else
1055 pht_cap->ampdu_params_info |= (IEEE80211_HT_CAP_AMPDU_DENSITY&0x00);
1056
1057 /* set Max Rx AMPDU size to 64K */
1058 pht_cap->ampdu_params_info |= (IEEE80211_HT_CAP_AMPDU_FACTOR & 0x03);
1059
1060 if (rf_type == RF_1T1R) {
1061 pht_cap->supp_mcs_set[0] = 0xff;
1062 pht_cap->supp_mcs_set[1] = 0x0;
1063 }
1064 memcpy(&pmlmepriv->htpriv.ht_cap, p+2, ie_len);
1065 }
1066
1067 /* parsing HT_INFO_IE */
1068 p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_ADD_INFO_IE_, &ie_len,
1069 (pbss_network->IELength - _BEACON_IE_OFFSET_));
1070 if (p && ie_len > 0)
1071 pHT_info_ie = p;
1072 switch (network_type) {
1073 case WIRELESS_11B:
1074 pbss_network->NetworkTypeInUse = Ndis802_11DS;
1075 break;
1076 case WIRELESS_11G:
1077 case WIRELESS_11BG:
1078 case WIRELESS_11G_24N:
1079 case WIRELESS_11BG_24N:
1080 pbss_network->NetworkTypeInUse = Ndis802_11OFDM24;
1081 break;
1082 case WIRELESS_11A:
1083 pbss_network->NetworkTypeInUse = Ndis802_11OFDM5;
1084 break;
1085 default:
1086 pbss_network->NetworkTypeInUse = Ndis802_11OFDM24;
1087 break;
1088 }
1089
1090 pmlmepriv->cur_network.network_type = network_type;
1091
1092 pmlmepriv->htpriv.ht_option = false;
1093
1094 if ((psecuritypriv->wpa2_pairwise_cipher & WPA_CIPHER_TKIP) ||
1095 (psecuritypriv->wpa_pairwise_cipher & WPA_CIPHER_TKIP)) {
1096 /* todo: */
1097 /* ht_cap = false; */
1098 }
1099
1100 /* ht_cap */
1101 if (pregistrypriv->ht_enable && ht_cap) {
1102 pmlmepriv->htpriv.ht_option = true;
1103 pmlmepriv->qospriv.qos_option = 1;
1104
1105 if (pregistrypriv->ampdu_enable == 1)
1106 pmlmepriv->htpriv.ampdu_enable = true;
1107 HT_caps_handler(padapter, (struct ndis_802_11_var_ie *)pHT_caps_ie);
1108
1109 HT_info_handler(padapter, (struct ndis_802_11_var_ie *)pHT_info_ie);
1110 }
1111
1112 pbss_network->Length = get_wlan_bssid_ex_sz((struct wlan_bssid_ex *)pbss_network);
1113
1114 /* issue beacon to start bss network */
1115 start_bss_network(padapter, (u8 *)pbss_network);
1116
1117 /* alloc sta_info for ap itself */
1118 psta = rtw_get_stainfo(&padapter->stapriv, pbss_network->MacAddress);
1119 if (!psta) {
1120 psta = rtw_alloc_stainfo(&padapter->stapriv, pbss_network->MacAddress);
1121 if (psta == NULL)
1122 return _FAIL;
1123 }
1124
9ecfc0f4
LF
1125 /* fix bug of flush_cam_entry at STOP AP mode */
1126 psta->state |= WIFI_AP_STATE;
1127 rtw_indicate_connect(padapter);
9a7fe54d
LF
1128 pmlmepriv->cur_network.join_res = true;/* for check if already set beacon */
1129 return ret;
1130}
1131
1132void rtw_set_macaddr_acl(struct adapter *padapter, int mode)
1133{
1134 struct sta_priv *pstapriv = &padapter->stapriv;
1135 struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;
1136
1137 DBG_88E("%s, mode =%d\n", __func__, mode);
1138
1139 pacl_list->mode = mode;
1140}
1141
1142int rtw_acl_add_sta(struct adapter *padapter, u8 *addr)
1143{
9a7fe54d
LF
1144 struct list_head *plist, *phead;
1145 u8 added = false;
1146 int i, ret = 0;
1147 struct rtw_wlan_acl_node *paclnode;
1148 struct sta_priv *pstapriv = &padapter->stapriv;
1149 struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;
1150 struct __queue *pacl_node_q = &pacl_list->acl_node_q;
1151
1152 DBG_88E("%s(acl_num =%d) =%pM\n", __func__, pacl_list->num, (addr));
1153
1154 if ((NUM_ACL-1) < pacl_list->num)
1155 return -1;
1156
7057dcb3 1157 spin_lock_bh(&(pacl_node_q->lock));
9a7fe54d
LF
1158
1159 phead = get_list_head(pacl_node_q);
c44e5e39 1160 plist = phead->next;
9a7fe54d 1161
84660700 1162 while (phead != plist) {
bea88100 1163 paclnode = container_of(plist, struct rtw_wlan_acl_node, list);
c44e5e39 1164 plist = plist->next;
9a7fe54d 1165
f42f52aa 1166 if (!memcmp(paclnode->addr, addr, ETH_ALEN)) {
9a7fe54d
LF
1167 if (paclnode->valid) {
1168 added = true;
1169 DBG_88E("%s, sta has been added\n", __func__);
1170 break;
1171 }
1172 }
1173 }
1174
e02bcf61 1175 spin_unlock_bh(&(pacl_node_q->lock));
9a7fe54d
LF
1176
1177 if (added)
1178 return ret;
1179
7057dcb3 1180 spin_lock_bh(&(pacl_node_q->lock));
9a7fe54d
LF
1181
1182 for (i = 0; i < NUM_ACL; i++) {
1183 paclnode = &pacl_list->aclnode[i];
1184
1185 if (!paclnode->valid) {
aa3f5ccb 1186 INIT_LIST_HEAD(&paclnode->list);
9a7fe54d 1187
6d36fe3e 1188 ether_addr_copy(paclnode->addr, addr);
9a7fe54d
LF
1189
1190 paclnode->valid = true;
1191
ae6787ad 1192 list_add_tail(&paclnode->list, get_list_head(pacl_node_q));
9a7fe54d
LF
1193
1194 pacl_list->num++;
1195
1196 break;
1197 }
1198 }
1199
1200 DBG_88E("%s, acl_num =%d\n", __func__, pacl_list->num);
1201
e02bcf61 1202 spin_unlock_bh(&(pacl_node_q->lock));
9a7fe54d
LF
1203
1204 return ret;
1205}
1206
1207int rtw_acl_remove_sta(struct adapter *padapter, u8 *addr)
1208{
9a7fe54d 1209 struct list_head *plist, *phead;
9a7fe54d
LF
1210 struct rtw_wlan_acl_node *paclnode;
1211 struct sta_priv *pstapriv = &padapter->stapriv;
1212 struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;
1213 struct __queue *pacl_node_q = &pacl_list->acl_node_q;
1214
1215 DBG_88E("%s(acl_num =%d) =%pM\n", __func__, pacl_list->num, (addr));
1216
7057dcb3 1217 spin_lock_bh(&(pacl_node_q->lock));
9a7fe54d
LF
1218
1219 phead = get_list_head(pacl_node_q);
c44e5e39 1220 plist = phead->next;
9a7fe54d 1221
84660700 1222 while (phead != plist) {
bea88100 1223 paclnode = container_of(plist, struct rtw_wlan_acl_node, list);
c44e5e39 1224 plist = plist->next;
9a7fe54d 1225
f42f52aa 1226 if (!memcmp(paclnode->addr, addr, ETH_ALEN)) {
9a7fe54d
LF
1227 if (paclnode->valid) {
1228 paclnode->valid = false;
1229
8d5bdece 1230 list_del_init(&paclnode->list);
9a7fe54d
LF
1231
1232 pacl_list->num--;
1233 }
1234 }
1235 }
1236
e02bcf61 1237 spin_unlock_bh(&(pacl_node_q->lock));
9a7fe54d
LF
1238
1239 DBG_88E("%s, acl_num =%d\n", __func__, pacl_list->num);
9cc56fa8 1240 return 0;
9a7fe54d
LF
1241}
1242
9a7fe54d
LF
1243static void update_bcn_erpinfo_ie(struct adapter *padapter)
1244{
1245 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1246 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
1247 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
1248 struct wlan_bssid_ex *pnetwork = &(pmlmeinfo->network);
1249 unsigned char *p, *ie = pnetwork->IEs;
1250 u32 len = 0;
1251
1252 DBG_88E("%s, ERP_enable =%d\n", __func__, pmlmeinfo->ERP_enable);
1253
1254 if (!pmlmeinfo->ERP_enable)
1255 return;
1256
1257 /* parsing ERP_IE */
1258 p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _ERPINFO_IE_, &len,
1259 (pnetwork->IELength - _BEACON_IE_OFFSET_));
1260 if (p && len > 0) {
1261 struct ndis_802_11_var_ie *pIE = (struct ndis_802_11_var_ie *)p;
1262
1263 if (pmlmepriv->num_sta_non_erp == 1)
1264 pIE->data[0] |= RTW_ERP_INFO_NON_ERP_PRESENT|RTW_ERP_INFO_USE_PROTECTION;
1265 else
1266 pIE->data[0] &= ~(RTW_ERP_INFO_NON_ERP_PRESENT|RTW_ERP_INFO_USE_PROTECTION);
1267
1268 if (pmlmepriv->num_sta_no_short_preamble > 0)
1269 pIE->data[0] |= RTW_ERP_INFO_BARKER_PREAMBLE_MODE;
1270 else
1271 pIE->data[0] &= ~(RTW_ERP_INFO_BARKER_PREAMBLE_MODE);
1272
1273 ERP_IE_handler(padapter, pIE);
1274 }
1275}
1276
9a7fe54d
LF
1277static void update_bcn_wps_ie(struct adapter *padapter)
1278{
1279 u8 *pwps_ie = NULL, *pwps_ie_src;
1280 u8 *premainder_ie, *pbackup_remainder_ie = NULL;
1281 uint wps_ielen = 0, wps_offset, remainder_ielen;
1282 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1283 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
1284 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
1285 struct wlan_bssid_ex *pnetwork = &(pmlmeinfo->network);
1286 unsigned char *ie = pnetwork->IEs;
1287 u32 ielen = pnetwork->IELength;
1288
1289 DBG_88E("%s\n", __func__);
1290
c60a9607
CE
1291 pwps_ie_src = pmlmepriv->wps_beacon_ie;
1292 if (pwps_ie_src == NULL)
1293 return;
1294
9a7fe54d
LF
1295 pwps_ie = rtw_get_wps_ie(ie+_FIXED_IE_LENGTH_, ielen-_FIXED_IE_LENGTH_, NULL, &wps_ielen);
1296
1297 if (pwps_ie == NULL || wps_ielen == 0)
1298 return;
1299
1300 wps_offset = (uint)(pwps_ie-ie);
1301
1302 premainder_ie = pwps_ie + wps_ielen;
1303
1304 remainder_ielen = ielen - wps_offset - wps_ielen;
1305
1306 if (remainder_ielen > 0) {
1307 pbackup_remainder_ie = rtw_malloc(remainder_ielen);
1308 if (pbackup_remainder_ie)
1309 memcpy(pbackup_remainder_ie, premainder_ie, remainder_ielen);
1310 }
1311
9a7fe54d
LF
1312 wps_ielen = (uint)pwps_ie_src[1];/* to get ie data len */
1313 if ((wps_offset+wps_ielen+2+remainder_ielen) <= MAX_IE_SZ) {
1314 memcpy(pwps_ie, pwps_ie_src, wps_ielen+2);
1315 pwps_ie += (wps_ielen+2);
1316
1317 if (pbackup_remainder_ie)
1318 memcpy(pwps_ie, pbackup_remainder_ie, remainder_ielen);
1319
1320 /* update IELength */
1321 pnetwork->IELength = wps_offset + (wps_ielen+2) + remainder_ielen;
1322 }
1323
6fb08157 1324 kfree(pbackup_remainder_ie);
9a7fe54d
LF
1325}
1326
9a7fe54d
LF
1327static void update_bcn_vendor_spec_ie(struct adapter *padapter, u8 *oui)
1328{
1329 DBG_88E("%s\n", __func__);
1330
f3a2d1ad 1331 if (!memcmp(WPS_OUI, oui, 4))
9a7fe54d 1332 update_bcn_wps_ie(padapter);
9a7fe54d
LF
1333 else
1334 DBG_88E("unknown OUI type!\n");
1335}
1336
1337void update_beacon(struct adapter *padapter, u8 ie_id, u8 *oui, u8 tx)
1338{
9a7fe54d
LF
1339 struct mlme_priv *pmlmepriv;
1340 struct mlme_ext_priv *pmlmeext;
1341
1342 if (!padapter)
1343 return;
1344
1345 pmlmepriv = &(padapter->mlmepriv);
1346 pmlmeext = &(padapter->mlmeextpriv);
1347
1348 if (!pmlmeext->bstart_bss)
1349 return;
1350
7057dcb3 1351 spin_lock_bh(&pmlmepriv->bcn_update_lock);
9a7fe54d
LF
1352
1353 switch (ie_id) {
9a7fe54d
LF
1354 case _TIM_IE_:
1355 update_BCNTIM(padapter);
1356 break;
1357 case _ERPINFO_IE_:
1358 update_bcn_erpinfo_ie(padapter);
1359 break;
9a7fe54d
LF
1360 case _VENDOR_SPECIFIC_IE_:
1361 update_bcn_vendor_spec_ie(padapter, oui);
1362 break;
1363 default:
1364 break;
1365 }
1366
1367 pmlmepriv->update_bcn = true;
1368
e02bcf61 1369 spin_unlock_bh(&pmlmepriv->bcn_update_lock);
9a7fe54d
LF
1370
1371 if (tx)
1372 set_tx_beacon_cmd(padapter);
1373}
1374
1375/*
1376op_mode
40a46d8b 1377Set to 0 (HT pure) under the following conditions
9a7fe54d
LF
1378 - all STAs in the BSS are 20/40 MHz HT in 20/40 MHz BSS or
1379 - all STAs in the BSS are 20 MHz HT in 20 MHz BSS
1380Set to 1 (HT non-member protection) if there may be non-HT STAs
1381 in both the primary and the secondary channel
1382Set to 2 if only HT STAs are associated in BSS,
1383 however and at least one 20 MHz HT STA is associated
1384Set to 3 (HT mixed mode) when one or more non-HT STAs are associated
1385 (currently non-GF HT station is considered as non-HT STA also)
1386*/
1387static int rtw_ht_operation_update(struct adapter *padapter)
1388{
1389 u16 cur_op_mode, new_op_mode;
1390 int op_mode_changes = 0;
1391 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1392 struct ht_priv *phtpriv_ap = &pmlmepriv->htpriv;
1393
1394 if (pmlmepriv->htpriv.ht_option)
1395 return 0;
1396
1397 DBG_88E("%s current operation mode = 0x%X\n",
1398 __func__, pmlmepriv->ht_op_mode);
1399
1400 if (!(pmlmepriv->ht_op_mode & HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT) &&
1401 pmlmepriv->num_sta_ht_no_gf) {
1402 pmlmepriv->ht_op_mode |=
1403 HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT;
1404 op_mode_changes++;
1405 } else if ((pmlmepriv->ht_op_mode &
1406 HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT) &&
1407 pmlmepriv->num_sta_ht_no_gf == 0) {
1408 pmlmepriv->ht_op_mode &=
1409 ~HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT;
1410 op_mode_changes++;
1411 }
1412
1413 if (!(pmlmepriv->ht_op_mode & HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT) &&
1414 (pmlmepriv->num_sta_no_ht || pmlmepriv->olbc_ht)) {
1415 pmlmepriv->ht_op_mode |= HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT;
1416 op_mode_changes++;
1417 } else if ((pmlmepriv->ht_op_mode &
1418 HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT) &&
1419 (pmlmepriv->num_sta_no_ht == 0 && !pmlmepriv->olbc_ht)) {
1420 pmlmepriv->ht_op_mode &=
1421 ~HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT;
1422 op_mode_changes++;
1423 }
1424
1425 /* Note: currently we switch to the MIXED op mode if HT non-greenfield
1426 * station is associated. Probably it's a theoretical case, since
1427 * it looks like all known HT STAs support greenfield.
1428 */
1429 new_op_mode = 0;
1430 if (pmlmepriv->num_sta_no_ht ||
1431 (pmlmepriv->ht_op_mode & HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT))
1432 new_op_mode = OP_MODE_MIXED;
1433 else if ((phtpriv_ap->ht_cap.cap_info & IEEE80211_HT_CAP_SUP_WIDTH) &&
1434 pmlmepriv->num_sta_ht_20mhz)
1435 new_op_mode = OP_MODE_20MHZ_HT_STA_ASSOCED;
1436 else if (pmlmepriv->olbc_ht)
1437 new_op_mode = OP_MODE_MAY_BE_LEGACY_STAS;
1438 else
1439 new_op_mode = OP_MODE_PURE;
1440
1441 cur_op_mode = pmlmepriv->ht_op_mode & HT_INFO_OPERATION_MODE_OP_MODE_MASK;
1442 if (cur_op_mode != new_op_mode) {
1443 pmlmepriv->ht_op_mode &= ~HT_INFO_OPERATION_MODE_OP_MODE_MASK;
1444 pmlmepriv->ht_op_mode |= new_op_mode;
1445 op_mode_changes++;
1446 }
1447
1448 DBG_88E("%s new operation mode = 0x%X changes =%d\n",
1449 __func__, pmlmepriv->ht_op_mode, op_mode_changes);
1450
1451 return op_mode_changes;
1452}
1453
1454void associated_clients_update(struct adapter *padapter, u8 updated)
1455{
40a46d8b 1456 /* update associated stations cap. */
9a7fe54d 1457 if (updated) {
9a7fe54d
LF
1458 struct list_head *phead, *plist;
1459 struct sta_info *psta = NULL;
1460 struct sta_priv *pstapriv = &padapter->stapriv;
1461
7057dcb3 1462 spin_lock_bh(&pstapriv->asoc_list_lock);
9a7fe54d
LF
1463
1464 phead = &pstapriv->asoc_list;
c44e5e39 1465 plist = phead->next;
9a7fe54d
LF
1466
1467 /* check asoc_queue */
84660700 1468 while (phead != plist) {
bea88100 1469 psta = container_of(plist, struct sta_info, asoc_list);
9a7fe54d 1470
c44e5e39 1471 plist = plist->next;
9a7fe54d
LF
1472
1473 VCS_update(padapter, psta);
1474 }
e02bcf61 1475 spin_unlock_bh(&pstapriv->asoc_list_lock);
9a7fe54d
LF
1476 }
1477}
1478
1479/* called > TSR LEVEL for USB or SDIO Interface*/
1480void bss_cap_update_on_sta_join(struct adapter *padapter, struct sta_info *psta)
1481{
1482 u8 beacon_updated = false;
1483 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1484 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
1485
1486 if (!(psta->flags & WLAN_STA_SHORT_PREAMBLE)) {
1487 if (!psta->no_short_preamble_set) {
1488 psta->no_short_preamble_set = 1;
1489
1490 pmlmepriv->num_sta_no_short_preamble++;
1491
1492 if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) &&
1493 (pmlmepriv->num_sta_no_short_preamble == 1)) {
1494 beacon_updated = true;
1495 update_beacon(padapter, 0xFF, NULL, true);
1496 }
1497 }
1498 } else {
1499 if (psta->no_short_preamble_set) {
1500 psta->no_short_preamble_set = 0;
1501
1502 pmlmepriv->num_sta_no_short_preamble--;
1503
1504 if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) &&
1505 (pmlmepriv->num_sta_no_short_preamble == 0)) {
1506 beacon_updated = true;
1507 update_beacon(padapter, 0xFF, NULL, true);
1508 }
1509 }
1510 }
1511
1512 if (psta->flags & WLAN_STA_NONERP) {
1513 if (!psta->nonerp_set) {
1514 psta->nonerp_set = 1;
1515
1516 pmlmepriv->num_sta_non_erp++;
1517
1518 if (pmlmepriv->num_sta_non_erp == 1) {
1519 beacon_updated = true;
1520 update_beacon(padapter, _ERPINFO_IE_, NULL, true);
1521 }
1522 }
1523 } else {
1524 if (psta->nonerp_set) {
1525 psta->nonerp_set = 0;
1526
1527 pmlmepriv->num_sta_non_erp--;
1528
1529 if (pmlmepriv->num_sta_non_erp == 0) {
1530 beacon_updated = true;
1531 update_beacon(padapter, _ERPINFO_IE_, NULL, true);
1532 }
1533 }
1534 }
1535
027d3efd 1536 if (!(psta->capability & WLAN_CAPABILITY_SHORT_SLOT_TIME)) {
9a7fe54d
LF
1537 if (!psta->no_short_slot_time_set) {
1538 psta->no_short_slot_time_set = 1;
1539
1540 pmlmepriv->num_sta_no_short_slot_time++;
1541
1542 if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) &&
1543 (pmlmepriv->num_sta_no_short_slot_time == 1)) {
1544 beacon_updated = true;
1545 update_beacon(padapter, 0xFF, NULL, true);
1546 }
1547 }
1548 } else {
1549 if (psta->no_short_slot_time_set) {
1550 psta->no_short_slot_time_set = 0;
1551
1552 pmlmepriv->num_sta_no_short_slot_time--;
1553
1554 if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) &&
1555 (pmlmepriv->num_sta_no_short_slot_time == 0)) {
1556 beacon_updated = true;
1557 update_beacon(padapter, 0xFF, NULL, true);
1558 }
1559 }
1560 }
1561
1562 if (psta->flags & WLAN_STA_HT) {
1563 u16 ht_capab = psta->htpriv.ht_cap.cap_info;
1564
1565 DBG_88E("HT: STA %pM HT Capabilities Info: 0x%04x\n",
1566 (psta->hwaddr), ht_capab);
1567
1568 if (psta->no_ht_set) {
1569 psta->no_ht_set = 0;
1570 pmlmepriv->num_sta_no_ht--;
1571 }
1572
1573 if ((ht_capab & IEEE80211_HT_CAP_GRN_FLD) == 0) {
1574 if (!psta->no_ht_gf_set) {
1575 psta->no_ht_gf_set = 1;
1576 pmlmepriv->num_sta_ht_no_gf++;
1577 }
1578 DBG_88E("%s STA %pM - no greenfield, num of non-gf stations %d\n",
1579 __func__, (psta->hwaddr),
1580 pmlmepriv->num_sta_ht_no_gf);
1581 }
1582
1583 if ((ht_capab & IEEE80211_HT_CAP_SUP_WIDTH) == 0) {
1584 if (!psta->ht_20mhz_set) {
1585 psta->ht_20mhz_set = 1;
1586 pmlmepriv->num_sta_ht_20mhz++;
1587 }
1588 DBG_88E("%s STA %pM - 20 MHz HT, num of 20MHz HT STAs %d\n",
1589 __func__, (psta->hwaddr),
1590 pmlmepriv->num_sta_ht_20mhz);
1591 }
1592 } else {
1593 if (!psta->no_ht_set) {
1594 psta->no_ht_set = 1;
1595 pmlmepriv->num_sta_no_ht++;
1596 }
1597 if (pmlmepriv->htpriv.ht_option) {
1598 DBG_88E("%s STA %pM - no HT, num of non-HT stations %d\n",
1599 __func__, (psta->hwaddr),
1600 pmlmepriv->num_sta_no_ht);
1601 }
1602 }
1603
1604 if (rtw_ht_operation_update(padapter) > 0) {
1605 update_beacon(padapter, _HT_CAPABILITY_IE_, NULL, false);
1606 update_beacon(padapter, _HT_ADD_INFO_IE_, NULL, true);
1607 }
1608
40a46d8b 1609 /* update associated stations cap. */
9a7fe54d
LF
1610 associated_clients_update(padapter, beacon_updated);
1611
1612 DBG_88E("%s, updated =%d\n", __func__, beacon_updated);
1613}
1614
1615u8 bss_cap_update_on_sta_leave(struct adapter *padapter, struct sta_info *psta)
1616{
1617 u8 beacon_updated = false;
1618 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1619 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
1620
1621 if (!psta)
1622 return beacon_updated;
1623
1624 if (psta->no_short_preamble_set) {
1625 psta->no_short_preamble_set = 0;
1626 pmlmepriv->num_sta_no_short_preamble--;
1627 if (pmlmeext->cur_wireless_mode > WIRELESS_11B &&
1628 pmlmepriv->num_sta_no_short_preamble == 0) {
1629 beacon_updated = true;
1630 update_beacon(padapter, 0xFF, NULL, true);
1631 }
1632 }
1633
1634 if (psta->nonerp_set) {
1635 psta->nonerp_set = 0;
1636 pmlmepriv->num_sta_non_erp--;
1637 if (pmlmepriv->num_sta_non_erp == 0) {
1638 beacon_updated = true;
1639 update_beacon(padapter, _ERPINFO_IE_, NULL, true);
1640 }
1641 }
1642
1643 if (psta->no_short_slot_time_set) {
1644 psta->no_short_slot_time_set = 0;
1645 pmlmepriv->num_sta_no_short_slot_time--;
1646 if (pmlmeext->cur_wireless_mode > WIRELESS_11B &&
1647 pmlmepriv->num_sta_no_short_slot_time == 0) {
1648 beacon_updated = true;
1649 update_beacon(padapter, 0xFF, NULL, true);
1650 }
1651 }
1652
1653 if (psta->no_ht_gf_set) {
1654 psta->no_ht_gf_set = 0;
1655 pmlmepriv->num_sta_ht_no_gf--;
1656 }
1657
1658 if (psta->no_ht_set) {
1659 psta->no_ht_set = 0;
1660 pmlmepriv->num_sta_no_ht--;
1661 }
1662
1663 if (psta->ht_20mhz_set) {
1664 psta->ht_20mhz_set = 0;
1665 pmlmepriv->num_sta_ht_20mhz--;
1666 }
1667
1668 if (rtw_ht_operation_update(padapter) > 0) {
1669 update_beacon(padapter, _HT_CAPABILITY_IE_, NULL, false);
1670 update_beacon(padapter, _HT_ADD_INFO_IE_, NULL, true);
1671 }
1672
40a46d8b 1673 /* update associated stations cap. */
9a7fe54d
LF
1674
1675 DBG_88E("%s, updated =%d\n", __func__, beacon_updated);
1676
1677 return beacon_updated;
1678}
1679
1680u8 ap_free_sta(struct adapter *padapter, struct sta_info *psta,
1681 bool active, u16 reason)
1682{
9a7fe54d
LF
1683 u8 beacon_updated = false;
1684 struct sta_priv *pstapriv = &padapter->stapriv;
1685
1686 if (!psta)
1687 return beacon_updated;
1688
1689 /* tear down Rx AMPDU */
1690 send_delba(padapter, 0, psta->hwaddr);/* recipient */
1691
1692 /* tear down TX AMPDU */
1693 send_delba(padapter, 1, psta->hwaddr);/* originator */
1694 psta->htpriv.agg_enable_bitmap = 0x0;/* reset */
1695 psta->htpriv.candidate_tid_bitmap = 0x0;/* reset */
1696
1697 if (active)
1698 issue_deauth(padapter, psta->hwaddr, reason);
1699
1700 /* clear cam entry / key */
1701 rtw_clearstakey_cmd(padapter, (u8 *)psta, (u8)(psta->mac_id + 3), true);
1702
1703
7057dcb3 1704 spin_lock_bh(&psta->lock);
9a7fe54d 1705 psta->state &= ~_FW_LINKED;
e02bcf61 1706 spin_unlock_bh(&psta->lock);
9a7fe54d
LF
1707
1708 rtw_indicate_sta_disassoc_event(padapter, psta);
1709
1710 report_del_sta_event(padapter, psta->hwaddr, reason);
1711
1712 beacon_updated = bss_cap_update_on_sta_leave(padapter, psta);
1713
7057dcb3 1714 spin_lock_bh(&(pstapriv->sta_hash_lock));
9a7fe54d 1715 rtw_free_stainfo(padapter, psta);
e02bcf61 1716 spin_unlock_bh(&(pstapriv->sta_hash_lock));
9a7fe54d
LF
1717
1718 return beacon_updated;
1719}
1720
1721int rtw_ap_inform_ch_switch(struct adapter *padapter, u8 new_ch, u8 ch_offset)
1722{
9a7fe54d 1723 struct list_head *phead, *plist;
9a7fe54d
LF
1724 struct sta_info *psta = NULL;
1725 struct sta_priv *pstapriv = &padapter->stapriv;
1726 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1727 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
1728 u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
1729
1730 if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE)
9cc56fa8 1731 return 0;
9a7fe54d
LF
1732
1733 DBG_88E(FUNC_NDEV_FMT" with ch:%u, offset:%u\n",
1734 FUNC_NDEV_ARG(padapter->pnetdev), new_ch, ch_offset);
1735
7057dcb3 1736 spin_lock_bh(&pstapriv->asoc_list_lock);
9a7fe54d 1737 phead = &pstapriv->asoc_list;
c44e5e39 1738 plist = phead->next;
9a7fe54d
LF
1739
1740 /* for each sta in asoc_queue */
84660700 1741 while (phead != plist) {
bea88100 1742 psta = container_of(plist, struct sta_info, asoc_list);
c44e5e39 1743 plist = plist->next;
9a7fe54d
LF
1744
1745 issue_action_spct_ch_switch(padapter, psta->hwaddr, new_ch, ch_offset);
ad8d8cd3 1746 psta->expire_to = min_t(unsigned int, pstapriv->expire_to * 2, 5);
9a7fe54d 1747 }
e02bcf61 1748 spin_unlock_bh(&pstapriv->asoc_list_lock);
9a7fe54d
LF
1749
1750 issue_action_spct_ch_switch(padapter, bc_addr, new_ch, ch_offset);
1751
9cc56fa8 1752 return 0;
9a7fe54d
LF
1753}
1754
1755int rtw_sta_flush(struct adapter *padapter)
1756{
9a7fe54d 1757 struct list_head *phead, *plist;
9a7fe54d
LF
1758 struct sta_info *psta = NULL;
1759 struct sta_priv *pstapriv = &padapter->stapriv;
1760 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1761 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
1762 u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
1763
1764 DBG_88E(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(padapter->pnetdev));
1765
1766 if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE)
9cc56fa8 1767 return 0;
9a7fe54d 1768
7057dcb3 1769 spin_lock_bh(&pstapriv->asoc_list_lock);
9a7fe54d 1770 phead = &pstapriv->asoc_list;
c44e5e39 1771 plist = phead->next;
9a7fe54d
LF
1772
1773 /* free sta asoc_queue */
84660700 1774 while (phead != plist) {
bea88100 1775 psta = container_of(plist, struct sta_info, asoc_list);
9a7fe54d 1776
c44e5e39 1777 plist = plist->next;
9a7fe54d 1778
8d5bdece 1779 list_del_init(&psta->asoc_list);
9a7fe54d
LF
1780 pstapriv->asoc_list_cnt--;
1781
1782 ap_free_sta(padapter, psta, true, WLAN_REASON_DEAUTH_LEAVING);
1783 }
e02bcf61 1784 spin_unlock_bh(&pstapriv->asoc_list_lock);
9a7fe54d
LF
1785
1786
1787 issue_deauth(padapter, bc_addr, WLAN_REASON_DEAUTH_LEAVING);
1788
1789 associated_clients_update(padapter, true);
1790
9cc56fa8 1791 return 0;
9a7fe54d
LF
1792}
1793
1794/* called > TSR LEVEL for USB or SDIO Interface*/
1795void sta_info_update(struct adapter *padapter, struct sta_info *psta)
1796{
1797 int flags = psta->flags;
1798 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1799
1800 /* update wmm cap. */
1801 if (WLAN_STA_WME&flags)
1802 psta->qos_option = 1;
1803 else
1804 psta->qos_option = 0;
1805
1806 if (pmlmepriv->qospriv.qos_option == 0)
1807 psta->qos_option = 0;
1808
1809 /* update 802.11n ht cap. */
1810 if (WLAN_STA_HT&flags) {
1811 psta->htpriv.ht_option = true;
1812 psta->qos_option = 1;
1813 } else {
1814 psta->htpriv.ht_option = false;
1815 }
1816
1817 if (!pmlmepriv->htpriv.ht_option)
1818 psta->htpriv.ht_option = false;
1819
1820 update_sta_info_apmode(padapter, psta);
1821}
1822
1823/* called >= TSR LEVEL for USB or SDIO Interface*/
1824void ap_sta_info_defer_update(struct adapter *padapter, struct sta_info *psta)
1825{
1826 if (psta->state & _FW_LINKED) {
1827 /* add ratid */
1828 add_RATid(padapter, psta, 0);/* DM_RATR_STA_INIT */
1829 }
1830}
1831
1832void start_ap_mode(struct adapter *padapter)
1833{
1834 int i;
1835 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1836 struct sta_priv *pstapriv = &padapter->stapriv;
1837 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1838 struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;
1839
1840 pmlmepriv->update_bcn = false;
1841
1842 pmlmeext->bstart_bss = false;
1843
1844 pmlmepriv->num_sta_non_erp = 0;
1845
1846 pmlmepriv->num_sta_no_short_slot_time = 0;
1847
1848 pmlmepriv->num_sta_no_short_preamble = 0;
1849
1850 pmlmepriv->num_sta_ht_no_gf = 0;
1851 pmlmepriv->num_sta_no_ht = 0;
1852 pmlmepriv->num_sta_ht_20mhz = 0;
1853
1854 pmlmepriv->olbc = false;
1855
1856 pmlmepriv->olbc_ht = false;
1857
1858 pmlmepriv->ht_op_mode = 0;
1859
1860 for (i = 0; i < NUM_STA; i++)
1861 pstapriv->sta_aid[i] = NULL;
1862
1863 pmlmepriv->wps_beacon_ie = NULL;
1864 pmlmepriv->wps_probe_resp_ie = NULL;
1865 pmlmepriv->wps_assoc_resp_ie = NULL;
1866
1867 pmlmepriv->p2p_beacon_ie = NULL;
1868 pmlmepriv->p2p_probe_resp_ie = NULL;
1869
1870 /* for ACL */
aa3f5ccb 1871 INIT_LIST_HEAD(&(pacl_list->acl_node_q.queue));
9a7fe54d
LF
1872 pacl_list->num = 0;
1873 pacl_list->mode = 0;
1874 for (i = 0; i < NUM_ACL; i++) {
aa3f5ccb 1875 INIT_LIST_HEAD(&pacl_list->aclnode[i].list);
9a7fe54d
LF
1876 pacl_list->aclnode[i].valid = false;
1877 }
1878}
1879
1880void stop_ap_mode(struct adapter *padapter)
1881{
9a7fe54d
LF
1882 struct list_head *phead, *plist;
1883 struct rtw_wlan_acl_node *paclnode;
1884 struct sta_info *psta = NULL;
1885 struct sta_priv *pstapriv = &padapter->stapriv;
1886 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1887 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1888 struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;
1889 struct __queue *pacl_node_q = &pacl_list->acl_node_q;
1890
1891 pmlmepriv->update_bcn = false;
1892 pmlmeext->bstart_bss = false;
1893
1894 /* reset and init security priv , this can refine with rtw_reset_securitypriv */
1ce39848 1895 memset((unsigned char *)&padapter->securitypriv, 0, sizeof(struct security_priv));
9a7fe54d
LF
1896 padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeOpen;
1897 padapter->securitypriv.ndisencryptstatus = Ndis802_11WEPDisabled;
1898
1899 /* for ACL */
7057dcb3 1900 spin_lock_bh(&(pacl_node_q->lock));
9a7fe54d 1901 phead = get_list_head(pacl_node_q);
c44e5e39 1902 plist = phead->next;
84660700 1903 while (phead != plist) {
bea88100 1904 paclnode = container_of(plist, struct rtw_wlan_acl_node, list);
c44e5e39 1905 plist = plist->next;
9a7fe54d
LF
1906
1907 if (paclnode->valid) {
1908 paclnode->valid = false;
1909
8d5bdece 1910 list_del_init(&paclnode->list);
9a7fe54d
LF
1911
1912 pacl_list->num--;
1913 }
1914 }
e02bcf61 1915 spin_unlock_bh(&(pacl_node_q->lock));
9a7fe54d
LF
1916
1917 DBG_88E("%s, free acl_node_queue, num =%d\n", __func__, pacl_list->num);
1918
1919 rtw_sta_flush(padapter);
1920
1921 /* free_assoc_sta_resources */
1922 rtw_free_all_stainfo(padapter);
1923
1924 psta = rtw_get_bcmc_stainfo(padapter);
7057dcb3 1925 spin_lock_bh(&(pstapriv->sta_hash_lock));
9a7fe54d 1926 rtw_free_stainfo(padapter, psta);
e02bcf61 1927 spin_unlock_bh(&(pstapriv->sta_hash_lock));
9a7fe54d
LF
1928
1929 rtw_init_bcmc_stainfo(padapter);
1930
1931 rtw_free_mlme_priv_ie_data(pmlmepriv);
1932}
1933
1934#endif /* CONFIG_88EU_AP_MODE */