1 /******************************************************************************
3 * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
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.
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
14 ******************************************************************************/
17 #include <osdep_service.h>
18 #include <drv_types.h>
19 #include <linux/ieee80211.h>
21 #include <rtl8723a_cmd.h>
22 #include <rtl8723a_hal.h>
23 #include <asm/unaligned.h>
24 #include <rtw_mlme_ext.h>
26 void init_mlme_ap_info23a(struct rtw_adapter
*padapter
)
28 struct mlme_priv
*pmlmepriv
= &padapter
->mlmepriv
;
29 struct sta_priv
*pstapriv
= &padapter
->stapriv
;
30 struct wlan_acl_pool
*pacl_list
= &pstapriv
->acl_list
;
32 spin_lock_init(&pmlmepriv
->bcn_update_lock
);
35 _rtw_init_queue23a(&pacl_list
->acl_node_q
);
37 start_ap_mode23a(padapter
);
40 void free_mlme_ap_info23a(struct rtw_adapter
*padapter
)
42 struct sta_info
*psta
= NULL
;
43 struct sta_priv
*pstapriv
= &padapter
->stapriv
;
44 struct mlme_priv
*pmlmepriv
= &padapter
->mlmepriv
;
45 struct mlme_ext_priv
*pmlmeext
= &padapter
->mlmeextpriv
;
46 struct mlme_ext_info
*pmlmeinfo
= &pmlmeext
->mlmext_info
;
48 pmlmepriv
->update_bcn
= false;
49 pmlmeext
->bstart_bss
= false;
51 rtw_sta_flush23a(padapter
);
53 pmlmeinfo
->state
= MSR_NOLINK
;
55 /* free_assoc_sta_resources */
56 rtw_free_all_stainfo23a(padapter
);
58 /* free bc/mc sta_info */
59 psta
= rtw_get_bcmc_stainfo23a(padapter
);
60 spin_lock_bh(&pstapriv
->sta_hash_lock
);
61 rtw_free_stainfo23a(padapter
, psta
);
62 spin_unlock_bh(&pstapriv
->sta_hash_lock
);
65 static void update_BCNTIM(struct rtw_adapter
*padapter
)
67 struct sta_priv
*pstapriv
= &padapter
->stapriv
;
68 struct mlme_ext_priv
*pmlmeext
= &padapter
->mlmeextpriv
;
69 struct mlme_ext_info
*pmlmeinfo
= &pmlmeext
->mlmext_info
;
70 struct wlan_bssid_ex
*pnetwork_mlmeext
= &pmlmeinfo
->network
;
71 unsigned char *pie
= pnetwork_mlmeext
->IEs
;
72 u8
*p
, *dst_ie
, *premainder_ie
= NULL
, *pbackup_remainder_ie
= NULL
;
73 uint offset
, tmp_len
, tim_ielen
, tim_ie_offset
, remainder_ielen
;
75 p
= rtw_get_ie23a(pie
, WLAN_EID_TIM
, &tim_ielen
,
76 pnetwork_mlmeext
->IELength
);
77 if (p
!= NULL
&& tim_ielen
> 0) {
80 premainder_ie
= p
+tim_ielen
;
82 tim_ie_offset
= (int)(p
- pie
);
84 remainder_ielen
= pnetwork_mlmeext
->IELength
- tim_ie_offset
- tim_ielen
;
86 /* append TIM IE from dst_ie offset */
91 /* calculate head_len */
95 p
= rtw_get_ie23a(pie
, WLAN_EID_SSID
,
96 &tmp_len
, pnetwork_mlmeext
->IELength
);
100 /* get supported rates len */
101 p
= rtw_get_ie23a(pie
, WLAN_EID_SUPP_RATES
,
102 &tmp_len
, pnetwork_mlmeext
->IELength
);
106 /* DS Parameter Set IE, len = 3 */
109 premainder_ie
= pie
+ offset
;
111 remainder_ielen
= pnetwork_mlmeext
->IELength
- offset
- tim_ielen
;
113 /* append TIM IE from offset */
114 dst_ie
= pie
+ offset
;
117 if (remainder_ielen
> 0) {
118 pbackup_remainder_ie
= kmalloc(remainder_ielen
, GFP_ATOMIC
);
119 if (pbackup_remainder_ie
&& premainder_ie
)
120 memcpy(pbackup_remainder_ie
, premainder_ie
, remainder_ielen
);
123 *dst_ie
++ = WLAN_EID_TIM
;
125 if ((pstapriv
->tim_bitmap
&0xff00) && (pstapriv
->tim_bitmap
&0x00fc))
130 *dst_ie
++ = tim_ielen
;
132 *dst_ie
++ = 0; /* DTIM count */
133 *dst_ie
++ = 1; /* DTIM period */
135 if (pstapriv
->tim_bitmap
& BIT(0)) /* for bc/mc frames */
136 *dst_ie
++ = BIT(0); /* bitmap ctrl */
140 if (tim_ielen
== 4) {
141 *dst_ie
++ = pstapriv
->tim_bitmap
& 0xff;
142 } else if (tim_ielen
== 5) {
143 put_unaligned_le16(pstapriv
->tim_bitmap
, dst_ie
);
147 /* copy remainder IE */
148 if (pbackup_remainder_ie
) {
149 memcpy(dst_ie
, pbackup_remainder_ie
, remainder_ielen
);
151 kfree(pbackup_remainder_ie
);
154 offset
= (uint
)(dst_ie
- pie
);
155 pnetwork_mlmeext
->IELength
= offset
+ remainder_ielen
;
157 set_tx_beacon_cmd23a(padapter
);
160 static u8
chk_sta_is_alive(struct sta_info
*psta
)
164 if ((psta
->sta_stats
.last_rx_data_pkts
+
165 psta
->sta_stats
.last_rx_ctrl_pkts
) !=
166 (psta
->sta_stats
.rx_data_pkts
+ psta
->sta_stats
.rx_ctrl_pkts
))
169 sta_update_last_rx_pkts(psta
);
174 void expire_timeout_chk23a(struct rtw_adapter
*padapter
)
176 struct list_head
*phead
;
178 struct sta_info
*psta
, *ptmp
;
179 struct sta_priv
*pstapriv
= &padapter
->stapriv
;
180 u8 chk_alive_num
= 0;
181 struct sta_info
*chk_alive_list
[NUM_STA
];
184 spin_lock_bh(&pstapriv
->auth_list_lock
);
185 phead
= &pstapriv
->auth_list
;
186 /* check auth_queue */
187 list_for_each_entry_safe(psta
, ptmp
, phead
, auth_list
) {
188 if (psta
->expire_to
> 0) {
190 if (psta
->expire_to
== 0) {
191 list_del_init(&psta
->auth_list
);
192 pstapriv
->auth_list_cnt
--;
194 DBG_8723A("auth expire %pM\n", psta
->hwaddr
);
196 spin_unlock_bh(&pstapriv
->auth_list_lock
);
198 spin_lock_bh(&pstapriv
->sta_hash_lock
);
199 rtw_free_stainfo23a(padapter
, psta
);
200 spin_unlock_bh(&pstapriv
->sta_hash_lock
);
202 spin_lock_bh(&pstapriv
->auth_list_lock
);
206 spin_unlock_bh(&pstapriv
->auth_list_lock
);
208 spin_lock_bh(&pstapriv
->asoc_list_lock
);
209 phead
= &pstapriv
->asoc_list
;
210 /* check asoc_queue */
211 list_for_each_entry_safe(psta
, ptmp
, phead
, asoc_list
) {
212 if (chk_sta_is_alive(psta
) || !psta
->expire_to
) {
213 psta
->expire_to
= pstapriv
->expire_to
;
214 psta
->keep_alive_trycnt
= 0;
219 if (psta
->expire_to
<= 0) {
220 struct mlme_ext_priv
*pmlmeext
= &padapter
->mlmeextpriv
;
222 if (padapter
->registrypriv
.wifi_spec
== 1) {
223 psta
->expire_to
= pstapriv
->expire_to
;
227 if (psta
->state
& WIFI_SLEEP_STATE
) {
228 if (!(psta
->state
& WIFI_STA_ALIVE_CHK_STATE
)) {
230 * check if alive by another method
231 * if station is at ps mode.
233 psta
->expire_to
= pstapriv
->expire_to
;
234 psta
->state
|= WIFI_STA_ALIVE_CHK_STATE
;
236 * update bcn with tim_bitmap
239 pstapriv
->tim_bitmap
|= CHKBIT(psta
->aid
);
240 update_beacon23a(padapter
, WLAN_EID_TIM
, NULL
, false);
242 if (!pmlmeext
->active_keep_alive_check
)
247 if (pmlmeext
->active_keep_alive_check
) {
248 chk_alive_list
[chk_alive_num
++] = psta
;
252 list_del_init(&psta
->asoc_list
);
253 pstapriv
->asoc_list_cnt
--;
255 DBG_8723A("asoc expire %pM, state = 0x%x\n",
256 psta
->hwaddr
, psta
->state
);
257 updated
= ap_free_sta23a(padapter
, psta
, false, WLAN_REASON_DEAUTH_LEAVING
);
260 * TODO: Aging mechanism to digest frames in
261 * sleep_q to avoid running out of xmitframe
263 if (psta
->sleepq_len
> (NR_XMITFRAME
/pstapriv
->asoc_list_cnt
)
264 && padapter
->xmitpriv
.free_xmitframe_cnt
< ((NR_XMITFRAME
/pstapriv
->asoc_list_cnt
)/2)
266 DBG_8723A("%s sta:%pM, sleepq_len:%u, free_xmitframe_cnt:%u, asoc_list_cnt:%u, clear sleep_q\n",
270 padapter
->xmitpriv
.free_xmitframe_cnt
,
271 pstapriv
->asoc_list_cnt
);
272 wakeup_sta_to_xmit23a(padapter
, psta
);
276 spin_unlock_bh(&pstapriv
->asoc_list_lock
);
280 u8 backup_oper_channel
= 0;
281 struct mlme_ext_priv
*pmlmeext
= &padapter
->mlmeextpriv
;
283 * switch to correct channel of current
284 * network before issue keep-alive frames
286 if (rtw_get_oper_ch23a(padapter
) != pmlmeext
->cur_channel
) {
287 backup_oper_channel
= rtw_get_oper_ch23a(padapter
);
288 SelectChannel23a(padapter
, pmlmeext
->cur_channel
);
291 /* issue null data to check sta alive */
292 for (i
= 0; i
< chk_alive_num
; i
++) {
296 psta
= chk_alive_list
[i
];
297 if (!(psta
->state
& _FW_LINKED
))
300 if (psta
->state
& WIFI_SLEEP_STATE
)
301 ret
= issue_nulldata23a(padapter
, psta
->hwaddr
, 0, 1, 50);
303 ret
= issue_nulldata23a(padapter
, psta
->hwaddr
, 0, 3, 50);
305 psta
->keep_alive_trycnt
++;
306 if (ret
== _SUCCESS
) {
307 DBG_8723A("asoc check, sta(%pM) is alive\n",
309 psta
->expire_to
= pstapriv
->expire_to
;
310 psta
->keep_alive_trycnt
= 0;
312 } else if (psta
->keep_alive_trycnt
<= 3) {
313 DBG_8723A("ack check for asoc expire, keep_alive_trycnt =%d\n", psta
->keep_alive_trycnt
);
318 psta
->keep_alive_trycnt
= 0;
320 DBG_8723A("asoc expire %pM, state = 0x%x\n",
321 psta
->hwaddr
, psta
->state
);
322 spin_lock_bh(&pstapriv
->asoc_list_lock
);
323 if (!list_empty(&psta
->asoc_list
)) {
324 list_del_init(&psta
->asoc_list
);
325 pstapriv
->asoc_list_cnt
--;
326 updated
= ap_free_sta23a(padapter
, psta
, false, WLAN_REASON_DEAUTH_LEAVING
);
328 spin_unlock_bh(&pstapriv
->asoc_list_lock
);
332 if (backup_oper_channel
> 0) /* back to original operation channel */
333 SelectChannel23a(padapter
, backup_oper_channel
);
336 associated_clients_update23a(padapter
, updated
);
339 void add_RATid23a(struct rtw_adapter
*padapter
, struct sta_info
*psta
, u8 rssi_level
)
344 unsigned char sta_band
= 0, raid
, shortGIrate
= false;
346 unsigned int tx_ra_bitmap
= 0;
347 struct ht_priv
*psta_ht
= NULL
;
348 struct mlme_priv
*pmlmepriv
= &padapter
->mlmepriv
;
349 struct wlan_bssid_ex
*pcur_network
= &pmlmepriv
->cur_network
.network
;
352 psta_ht
= &psta
->htpriv
;
356 if (!(psta
->state
& _FW_LINKED
))
359 /* b/g mode ra_bitmap */
360 for (i
= 0; i
< sizeof(psta
->bssrateset
); i
++) {
361 if (psta
->bssrateset
[i
])
362 tx_ra_bitmap
|= rtw_get_bit_value_from_ieee_value23a(psta
->bssrateset
[i
]&0x7f);
364 /* n mode ra_bitmap */
365 if (psta_ht
->ht_option
) {
366 rf_type
= rtl8723a_get_rf_type(padapter
);
368 if (rf_type
== RF_2T2R
)
373 for (i
= 0; i
< limit
; i
++) {
374 if (psta_ht
->ht_cap
.mcs
.rx_mask
[i
/ 8] & BIT(i
% 8))
375 tx_ra_bitmap
|= BIT(i
+ 12);
378 /* max short GI rate */
379 shortGIrate
= psta_ht
->sgi
;
382 if (pcur_network
->DSConfig
> 14) {
384 if (tx_ra_bitmap
& 0xffff000)
385 sta_band
|= WIRELESS_11_5N
| WIRELESS_11A
;
387 sta_band
|= WIRELESS_11A
;
389 if (tx_ra_bitmap
& 0xffff000)
390 sta_band
|= WIRELESS_11_24N
| WIRELESS_11G
| WIRELESS_11B
;
391 else if (tx_ra_bitmap
& 0xff0)
392 sta_band
|= WIRELESS_11G
| WIRELESS_11B
;
394 sta_band
|= WIRELESS_11B
;
397 psta
->wireless_mode
= sta_band
;
399 raid
= networktype_to_raid23a(sta_band
);
400 init_rate
= get_highest_rate_idx23a(tx_ra_bitmap
&0x0fffffff)&0x3f;
402 if (psta
->aid
< NUM_STA
) {
405 arg
= psta
->mac_id
&0x1f;
407 arg
|= BIT(7); /* support entry 2~31 */
409 if (shortGIrate
== true)
412 tx_ra_bitmap
|= ((raid
<<28)&0xf0000000);
414 DBG_8723A("%s => mac_id:%d , raid:%d , bitmap = 0x%x, arg = "
416 __func__
, psta
->mac_id
, raid
, tx_ra_bitmap
, arg
);
418 /* bitmap[0:27] = tx_rate_bitmap */
419 /* bitmap[28:31]= Rate Adaptive id */
420 /* arg[0:4] = macid */
421 /* arg[5] = Short GI */
422 rtl8723a_add_rateatid(padapter
, tx_ra_bitmap
, arg
, rssi_level
);
424 if (shortGIrate
== true)
427 /* set ra_id, init_rate */
429 psta
->init_rate
= init_rate
;
432 DBG_8723A("station aid %d exceed the max number\n", psta
->aid
);
435 static void update_bmc_sta(struct rtw_adapter
*padapter
)
438 unsigned char network_type
, raid
;
439 int i
, supportRateNum
= 0;
440 unsigned int tx_ra_bitmap
= 0;
441 struct mlme_priv
*pmlmepriv
= &padapter
->mlmepriv
;
442 struct wlan_bssid_ex
*pcur_network
= &pmlmepriv
->cur_network
.network
;
443 struct sta_info
*psta
= rtw_get_bcmc_stainfo23a(padapter
);
446 psta
->aid
= 0; /* default set to 0 */
447 psta
->mac_id
= psta
->aid
+ 1;
449 psta
->qos_option
= 0;
450 psta
->htpriv
.ht_option
= false;
452 psta
->ieee8021x_blocked
= 0;
454 memset((void *)&psta
->sta_stats
, 0,
455 sizeof(struct stainfo_stats
));
457 /* prepare for add_RATid23a */
458 supportRateNum
= rtw_get_rateset_len23a((u8
*)&pcur_network
->SupportedRates
);
459 network_type
= rtw_check_network_type23a((u8
*)&pcur_network
->SupportedRates
, supportRateNum
, 1);
461 memcpy(psta
->bssrateset
, &pcur_network
->SupportedRates
, supportRateNum
);
462 psta
->bssratelen
= supportRateNum
;
464 /* b/g mode ra_bitmap */
465 for (i
= 0; i
< supportRateNum
; i
++) {
466 if (psta
->bssrateset
[i
])
467 tx_ra_bitmap
|= rtw_get_bit_value_from_ieee_value23a(psta
->bssrateset
[i
]&0x7f);
470 if (pcur_network
->DSConfig
> 14) {
471 /* force to A mode. 5G doesn't support CCK rates */
472 network_type
= WIRELESS_11A
;
473 tx_ra_bitmap
= 0x150; /* 6, 12, 24 Mbps */
475 /* force to b mode */
476 network_type
= WIRELESS_11B
;
480 raid
= networktype_to_raid23a(network_type
);
481 init_rate
= get_highest_rate_idx23a(tx_ra_bitmap
&0x0fffffff)&0x3f;
484 rtl8723a_SetHalODMVar(padapter
, HAL_ODM_STA_INFO
, psta
, true);
489 arg
= psta
->mac_id
&0x1f;
493 tx_ra_bitmap
|= ((raid
<<28)&0xf0000000);
495 DBG_8723A("update_bmc_sta, mask = 0x%x, arg = 0x%x\n", tx_ra_bitmap
, arg
);
497 /* bitmap[0:27] = tx_rate_bitmap */
498 /* bitmap[28:31]= Rate Adaptive id */
499 /* arg[0:4] = macid */
500 /* arg[5] = Short GI */
501 rtl8723a_add_rateatid(padapter
, tx_ra_bitmap
, arg
, 0);
504 /* set ra_id, init_rate */
506 psta
->init_rate
= init_rate
;
508 spin_lock_bh(&psta
->lock
);
509 psta
->state
= _FW_LINKED
;
510 spin_unlock_bh(&psta
->lock
);
513 DBG_8723A("add_RATid23a_bmc_sta error!\n");
517 * AID: 1~MAX for sta and 0 for bc/mc in ap/adhoc mode
518 * MAC_ID = AID+1 for sta in ap/adhoc mode
519 * MAC_ID = 1 for bc/mc for sta/ap/adhoc
520 * MAC_ID = 0 for bssid for sta/ap/adhoc
521 * CAM_ID = 0~3 for default key, cmd_id = macid + 3, macid = aid + 1;
523 void update_sta_info23a_apmode23a(struct rtw_adapter
*padapter
, struct sta_info
*psta
)
525 struct mlme_priv
*pmlmepriv
= &padapter
->mlmepriv
;
526 struct security_priv
*psecuritypriv
= &padapter
->securitypriv
;
527 struct mlme_ext_priv
*pmlmeext
= &padapter
->mlmeextpriv
;
528 struct ht_priv
*phtpriv_ap
= &pmlmepriv
->htpriv
;
529 struct ht_priv
*phtpriv_sta
= &psta
->htpriv
;
530 /* set intf_tag to if1 */
532 psta
->mac_id
= psta
->aid
+1;
533 DBG_8723A("%s\n", __func__
);
536 rtl8723a_SetHalODMVar(padapter
, HAL_ODM_STA_INFO
, psta
, true);
538 if (psecuritypriv
->dot11AuthAlgrthm
== dot11AuthAlgrthm_8021X
)
539 psta
->ieee8021x_blocked
= true;
541 psta
->ieee8021x_blocked
= false;
543 /* update sta's cap */
546 VCS_update23a(padapter
, psta
);
548 if (phtpriv_sta
->ht_option
) {
549 /* check if sta supports rx ampdu */
550 phtpriv_sta
->ampdu_enable
= phtpriv_ap
->ampdu_enable
;
552 /* check if sta support s Short GI */
553 if ((phtpriv_sta
->ht_cap
.cap_info
& phtpriv_ap
->ht_cap
.cap_info
) & cpu_to_le16(IEEE80211_HT_CAP_SGI_20
|IEEE80211_HT_CAP_SGI_40
))
554 phtpriv_sta
->sgi
= true;
557 if ((phtpriv_sta
->ht_cap
.cap_info
& phtpriv_ap
->ht_cap
.cap_info
) & cpu_to_le16(IEEE80211_HT_CAP_SUP_WIDTH_20_40
)) {
558 /* phtpriv_sta->bwmode = HT_CHANNEL_WIDTH_40; */
559 phtpriv_sta
->bwmode
= pmlmeext
->cur_bwmode
;
560 phtpriv_sta
->ch_offset
= pmlmeext
->cur_ch_offset
;
564 psta
->qos_option
= true;
567 phtpriv_sta
->ampdu_enable
= false;
569 phtpriv_sta
->sgi
= false;
570 phtpriv_sta
->bwmode
= HT_CHANNEL_WIDTH_20
;
571 phtpriv_sta
->ch_offset
= HAL_PRIME_CHNL_OFFSET_DONT_CARE
;
575 send_delba23a(padapter
, 0, psta
->hwaddr
); /* recipient */
578 send_delba23a(padapter
, 1, psta
->hwaddr
); /* originator */
579 phtpriv_sta
->agg_enable_bitmap
= 0x0;/* reset */
580 phtpriv_sta
->candidate_tid_bitmap
= 0x0;/* reset */
582 /* todo: init other variables */
584 memset((void *)&psta
->sta_stats
, 0, sizeof(struct stainfo_stats
));
586 spin_lock_bh(&psta
->lock
);
587 psta
->state
|= _FW_LINKED
;
588 spin_unlock_bh(&psta
->lock
);
591 static void update_hw_ht_param(struct rtw_adapter
*padapter
)
593 unsigned char max_AMPDU_len
;
594 unsigned char min_MPDU_spacing
;
595 struct mlme_ext_priv
*pmlmeext
= &padapter
->mlmeextpriv
;
596 struct mlme_ext_info
*pmlmeinfo
= &pmlmeext
->mlmext_info
;
598 DBG_8723A("%s\n", __func__
);
600 * handle A-MPDU parameter field
601 * AMPDU_para [1:0]:Max AMPDU Len => 0:8k, 1:16k, 2:32k, 3:64k
602 * AMPDU_para [4:2]:Min MPDU Start Spacing
604 max_AMPDU_len
= pmlmeinfo
->ht_cap
.ampdu_params_info
&
605 IEEE80211_HT_AMPDU_PARM_FACTOR
;
607 min_MPDU_spacing
= (pmlmeinfo
->ht_cap
.ampdu_params_info
&
608 IEEE80211_HT_AMPDU_PARM_DENSITY
) >> 2;
610 rtl8723a_set_ampdu_min_space(padapter
, min_MPDU_spacing
);
611 rtl8723a_set_ampdu_factor(padapter
, max_AMPDU_len
);
613 /* Config SM Power Save setting */
614 pmlmeinfo
->SM_PS
= (le16_to_cpu(pmlmeinfo
->ht_cap
.cap_info
) &
615 IEEE80211_HT_CAP_SM_PS
) >> 2;
616 if (pmlmeinfo
->SM_PS
== WLAN_HT_CAP_SM_PS_STATIC
)
617 DBG_8723A("%s(): WLAN_HT_CAP_SM_PS_STATIC\n", __func__
);
620 static void start_bss_network(struct rtw_adapter
*padapter
, u8
*pbuf
)
623 u8 val8
, cur_channel
, cur_bwmode
, cur_ch_offset
;
626 struct registry_priv
*pregpriv
= &padapter
->registrypriv
;
627 struct mlme_priv
*pmlmepriv
= &padapter
->mlmepriv
;
628 struct security_priv
*psecuritypriv
= &padapter
->securitypriv
;
629 struct wlan_bssid_ex
*pnetwork
= &pmlmepriv
->cur_network
.network
;
630 struct mlme_ext_priv
*pmlmeext
= &padapter
->mlmeextpriv
;
631 struct mlme_ext_info
*pmlmeinfo
= &pmlmeext
->mlmext_info
;
632 struct wlan_bssid_ex
*pnetwork_mlmeext
= &pmlmeinfo
->network
;
633 struct ieee80211_ht_operation
*pht_info
= NULL
;
635 bcn_interval
= (u16
)pnetwork
->beacon_interval
;
636 cur_channel
= pnetwork
->DSConfig
;
637 cur_bwmode
= HT_CHANNEL_WIDTH_20
;
638 cur_ch_offset
= HAL_PRIME_CHNL_OFFSET_DONT_CARE
;
641 * check if there is wps ie
642 * if there is wpsie in beacon the hostapd will
643 * update beacon twice when stating hostapd
644 * and at first time the security
645 * ie (RSN/WPA IE) will not include in beacon
647 if (!cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT
,
648 WLAN_OUI_TYPE_MICROSOFT_WPS
,
651 pmlmeext
->bstart_bss
= true;
653 /* todo: update wmm, ht cap */
654 /* pmlmeinfo->WMM_enable; */
655 /* pmlmeinfo->HT_enable; */
656 if (pmlmepriv
->qos_option
)
657 pmlmeinfo
->WMM_enable
= true;
658 if (pmlmepriv
->htpriv
.ht_option
) {
659 pmlmeinfo
->WMM_enable
= true;
660 pmlmeinfo
->HT_enable
= true;
662 update_hw_ht_param(padapter
);
665 if (pmlmepriv
->cur_network
.join_res
!= true) {
667 * setting only at first time
668 * WEP Key will be set before this
669 * function, do not clear CAM.
671 if (psecuritypriv
->dot11PrivacyAlgrthm
!=
672 WLAN_CIPHER_SUITE_WEP40
&&
673 psecuritypriv
->dot11PrivacyAlgrthm
!=
674 WLAN_CIPHER_SUITE_WEP104
)
675 flush_all_cam_entry23a(padapter
); /* clear CAM */
678 /* set MSR to AP_Mode */
679 rtl8723a_set_media_status(padapter
, MSR_AP
);
682 hw_var_set_bssid(padapter
, pnetwork
->MacAddress
);
684 /* Set EDCA param reg */
685 acparm
= 0x002F3217; /* VO */
686 rtl8723a_set_ac_param_vo(padapter
, acparm
);
687 acparm
= 0x005E4317; /* VI */
688 rtl8723a_set_ac_param_vi(padapter
, acparm
);
690 rtl8723a_set_ac_param_be(padapter
, acparm
);
691 acparm
= 0x0000A444; /* BK */
692 rtl8723a_set_ac_param_bk(padapter
, acparm
);
695 val8
= (psecuritypriv
->dot11AuthAlgrthm
== dot11AuthAlgrthm_8021X
) ?
697 rtl8723a_set_sec_cfg(padapter
, val8
);
699 /* Beacon Control related register */
700 rtl8723a_set_beacon_interval(padapter
, bcn_interval
);
702 UpdateBrateTbl23a(padapter
, pnetwork
->SupportedRates
);
703 HalSetBrateCfg23a(padapter
, pnetwork
->SupportedRates
);
705 if (!pmlmepriv
->cur_network
.join_res
) {
706 /* setting only at first time */
708 /* disable dynamic functions, such as high power, DIG */
710 /* turn on all dynamic functions */
711 rtl8723a_odm_support_ability_set(padapter
,
712 DYNAMIC_ALL_FUNC_ENABLE
);
714 /* set channel, bwmode */
716 p
= cfg80211_find_ie(WLAN_EID_HT_OPERATION
, pnetwork
->IEs
,
719 pht_info
= (struct ieee80211_ht_operation
*)(p
+ 2);
721 if (pregpriv
->cbw40_enable
&& pht_info
->ht_param
&
722 IEEE80211_HT_PARAM_CHAN_WIDTH_ANY
) {
723 /* switch to the 40M Hz mode */
724 cur_bwmode
= HT_CHANNEL_WIDTH_40
;
725 switch (pht_info
->ht_param
&
726 IEEE80211_HT_PARAM_CHA_SEC_OFFSET
) {
727 case IEEE80211_HT_PARAM_CHA_SEC_ABOVE
:
729 * pmlmeext->cur_ch_offset =
730 * HAL_PRIME_CHNL_OFFSET_LOWER;
732 cur_ch_offset
= HAL_PRIME_CHNL_OFFSET_LOWER
;
734 case IEEE80211_HT_PARAM_CHA_SEC_BELOW
:
735 cur_ch_offset
= HAL_PRIME_CHNL_OFFSET_UPPER
;
738 cur_ch_offset
= HAL_PRIME_CHNL_OFFSET_DONT_CARE
;
744 * TODO: need to judge the phy parameters
745 * on concurrent mode for single phy
747 set_channel_bwmode23a(padapter
, cur_channel
, cur_ch_offset
, cur_bwmode
);
749 DBG_8723A("CH =%d, BW =%d, offset =%d\n", cur_channel
, cur_bwmode
,
752 pmlmeext
->cur_channel
= cur_channel
;
753 pmlmeext
->cur_bwmode
= cur_bwmode
;
754 pmlmeext
->cur_ch_offset
= cur_ch_offset
;
755 pmlmeext
->cur_wireless_mode
= pmlmepriv
->cur_network
.network_type
;
757 /* update cur_wireless_mode */
758 update_wireless_mode23a(padapter
);
760 /* update capability after cur_wireless_mode updated */
761 update_capinfo23a(padapter
, pnetwork
->capability
);
763 /* let pnetwork_mlmeext == pnetwork_mlme. */
764 memcpy(pnetwork_mlmeext
, pnetwork
, pnetwork
->Length
);
766 if (pmlmeext
->bstart_bss
) {
767 update_beacon23a(padapter
, WLAN_EID_TIM
, NULL
, false);
769 /* issue beacon frame */
770 if (send_beacon23a(padapter
) == _FAIL
)
771 DBG_8723A("issue_beacon23a, fail!\n");
774 /* update bc/mc sta_info */
775 update_bmc_sta(padapter
);
778 int rtw_check_beacon_data23a(struct rtw_adapter
*padapter
,
779 struct ieee80211_mgmt
*mgmt
, unsigned int len
)
783 u8
*pHT_caps_ie
= NULL
;
784 u8
*pHT_info_ie
= NULL
;
785 struct sta_info
*psta
= NULL
;
788 int group_cipher
, pairwise_cipher
;
789 u8 channel
, network_type
, supportRate
[NDIS_802_11_LENGTH_RATES_EX
];
790 int supportRateNum
= 0;
791 u8 WMM_PARA_IE
[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01};
792 struct registry_priv
*pregistrypriv
= &padapter
->registrypriv
;
793 struct security_priv
*psecuritypriv
= &padapter
->securitypriv
;
794 struct mlme_priv
*pmlmepriv
= &padapter
->mlmepriv
;
795 struct wlan_bssid_ex
*pbss_network
= &pmlmepriv
->cur_network
.network
;
796 u8
*ie
= pbss_network
->IEs
;
797 u8
*pbuf
= mgmt
->u
.beacon
.variable
;
799 len
-= offsetof(struct ieee80211_mgmt
, u
.beacon
.variable
);
801 /* Supported rates */
803 /* WLAN_EID_COUNTRY */
804 /* ERP Information element */
805 /* Extended supported rates */
807 /* Wi-Fi Wireless Multimedia Extensions */
808 /* ht_capab, ht_oper */
811 DBG_8723A("%s, len =%d\n", __func__
, len
);
813 if (!check_fwstate(pmlmepriv
, WIFI_AP_STATE
))
819 pbss_network
->IELength
= len
;
821 memset(ie
, 0, MAX_IE_SZ
);
823 memcpy(ie
, pbuf
, pbss_network
->IELength
);
825 if (pbss_network
->ifmode
!= NL80211_IFTYPE_AP
&&
826 pbss_network
->ifmode
!= NL80211_IFTYPE_P2P_GO
)
829 pbss_network
->Rssi
= 0;
831 memcpy(pbss_network
->MacAddress
, myid(&padapter
->eeprompriv
), ETH_ALEN
);
834 p
= rtw_get_ie23a(ie
, WLAN_EID_SSID
, &ie_len
, pbss_network
->IELength
);
835 if (p
&& ie_len
> 0) {
836 memset(&pbss_network
->Ssid
, 0, sizeof(struct cfg80211_ssid
));
837 memcpy(pbss_network
->Ssid
.ssid
, (p
+ 2), ie_len
);
838 pbss_network
->Ssid
.ssid_len
= ie_len
;
843 p
= rtw_get_ie23a(ie
, WLAN_EID_DS_PARAMS
, &ie_len
,
844 pbss_network
->IELength
);
848 pbss_network
->DSConfig
= channel
;
850 memset(supportRate
, 0, NDIS_802_11_LENGTH_RATES_EX
);
851 /* get supported rates */
852 p
= rtw_get_ie23a(ie
, WLAN_EID_SUPP_RATES
, &ie_len
,
853 pbss_network
->IELength
);
855 memcpy(supportRate
, p
+2, ie_len
);
856 supportRateNum
= ie_len
;
859 /* get ext_supported rates */
860 p
= rtw_get_ie23a(ie
, WLAN_EID_EXT_SUPP_RATES
,
861 &ie_len
, pbss_network
->IELength
);
863 memcpy(supportRate
+supportRateNum
, p
+2, ie_len
);
864 supportRateNum
+= ie_len
;
867 network_type
= rtw_check_network_type23a(supportRate
,
868 supportRateNum
, channel
);
870 rtw_set_supported_rate23a(pbss_network
->SupportedRates
, network_type
);
873 p
= rtw_get_ie23a(ie
, WLAN_EID_ERP_INFO
, &ie_len
,
874 pbss_network
->IELength
);
876 ERP_IE_handler23a(padapter
, p
);
878 /* update privacy/security */
879 if (pbss_network
->capability
& BIT(4))
880 pbss_network
->Privacy
= 1;
882 pbss_network
->Privacy
= 0;
884 psecuritypriv
->wpa_psk
= 0;
887 group_cipher
= 0; pairwise_cipher
= 0;
888 psecuritypriv
->wpa2_group_cipher
= 0;
889 psecuritypriv
->wpa2_pairwise_cipher
= 0;
890 p
= rtw_get_ie23a(ie
, WLAN_EID_RSN
, &ie_len
,
891 pbss_network
->IELength
);
892 if (p
&& ie_len
> 0) {
893 if (rtw_parse_wpa2_ie23a(p
, ie_len
+2, &group_cipher
,
894 &pairwise_cipher
, NULL
) == _SUCCESS
) {
895 psecuritypriv
->dot11AuthAlgrthm
= dot11AuthAlgrthm_8021X
;
897 psecuritypriv
->dot8021xalg
= 1; /* psk, todo:802.1x */
898 psecuritypriv
->wpa_psk
|= BIT(1);
900 psecuritypriv
->wpa2_group_cipher
= group_cipher
;
901 psecuritypriv
->wpa2_pairwise_cipher
= pairwise_cipher
;
909 psecuritypriv
->wpa_group_cipher
= 0;
910 psecuritypriv
->wpa_pairwise_cipher
= 0;
911 for (p
= ie
; ; p
+= (ie_len
+ 2)) {
912 p
= rtw_get_ie23a(p
, WLAN_EID_VENDOR_SPECIFIC
, &ie_len
,
913 pbss_network
->IELength
- (ie_len
+ 2));
914 if ((p
) && (!memcmp(p
+2, RTW_WPA_OUI23A_TYPE
, 4))) {
915 if (rtw_parse_wpa_ie23a(p
, ie_len
+2, &group_cipher
,
916 &pairwise_cipher
, NULL
) == _SUCCESS
) {
917 psecuritypriv
->dot11AuthAlgrthm
= dot11AuthAlgrthm_8021X
;
919 /* psk, todo:802.1x */
920 psecuritypriv
->dot8021xalg
= 1;
922 psecuritypriv
->wpa_psk
|= BIT(0);
924 psecuritypriv
->wpa_group_cipher
= group_cipher
;
925 psecuritypriv
->wpa_pairwise_cipher
= pairwise_cipher
;
936 pmlmepriv
->qos_option
= 0;
937 if (pregistrypriv
->wmm_enable
) {
938 for (p
= ie
; ; p
+= (ie_len
+ 2)) {
939 p
= rtw_get_ie23a(p
, WLAN_EID_VENDOR_SPECIFIC
, &ie_len
,
940 (pbss_network
->IELength
-
942 if ((p
) && !memcmp(p
+2, WMM_PARA_IE
, 6)) {
943 pmlmepriv
->qos_option
= 1;
945 *(p
+ 8) |= BIT(7);/* QoS Info:support U-APSD */
947 /* disable all ACM bits since the WMM admission
948 * control is not supported
950 *(p
+ 10) &= ~BIT(4); /* BE */
951 *(p
+ 14) &= ~BIT(4); /* BK */
952 *(p
+ 18) &= ~BIT(4); /* VI */
953 *(p
+ 22) &= ~BIT(4); /* VO */
956 if ((p
== NULL
) || (ie_len
== 0))
960 /* parsing HT_CAP_IE */
961 p
= rtw_get_ie23a(ie
, WLAN_EID_HT_CAPABILITY
, &ie_len
,
962 pbss_network
->IELength
);
963 if (p
&& ie_len
> 0) {
966 struct ieee80211_ht_cap
*pht_cap
= (struct ieee80211_ht_cap
*)(p
+2);
971 network_type
|= WIRELESS_11_24N
;
973 rf_type
= rtl8723a_get_rf_type(padapter
);
975 if ((psecuritypriv
->wpa_pairwise_cipher
& WPA_CIPHER_CCMP
) ||
976 (psecuritypriv
->wpa2_pairwise_cipher
& WPA_CIPHER_CCMP
))
977 pht_cap
->ampdu_params_info
|= (IEEE80211_HT_AMPDU_PARM_DENSITY
& (0x07<<2));
979 pht_cap
->ampdu_params_info
|= (IEEE80211_HT_AMPDU_PARM_DENSITY
&0x00);
981 /* set Max Rx AMPDU size to 64K */
982 pht_cap
->ampdu_params_info
|= (IEEE80211_HT_AMPDU_PARM_FACTOR
& 0x03);
984 if (rf_type
== RF_1T1R
) {
985 pht_cap
->mcs
.rx_mask
[0] = 0xff;
986 pht_cap
->mcs
.rx_mask
[1] = 0x0;
989 memcpy(&pmlmepriv
->htpriv
.ht_cap
, p
+2, ie_len
);
992 /* parsing HT_INFO_IE */
993 p
= rtw_get_ie23a(ie
, WLAN_EID_HT_OPERATION
, &ie_len
,
994 pbss_network
->IELength
);
998 pmlmepriv
->cur_network
.network_type
= network_type
;
1000 pmlmepriv
->htpriv
.ht_option
= false;
1003 if (pregistrypriv
->ht_enable
&& ht_cap
) {
1004 pmlmepriv
->htpriv
.ht_option
= true;
1005 pmlmepriv
->qos_option
= 1;
1007 if (pregistrypriv
->ampdu_enable
== 1)
1008 pmlmepriv
->htpriv
.ampdu_enable
= true;
1010 HT_caps_handler23a(padapter
, pHT_caps_ie
);
1012 HT_info_handler23a(padapter
, pHT_info_ie
);
1015 pbss_network
->Length
= get_wlan_bssid_ex_sz(pbss_network
);
1017 /* issue beacon to start bss network */
1018 start_bss_network(padapter
, (u8
*)pbss_network
);
1020 /* alloc sta_info for ap itself */
1021 psta
= rtw_get_stainfo23a(&padapter
->stapriv
, pbss_network
->MacAddress
);
1023 psta
= rtw_alloc_stainfo23a(&padapter
->stapriv
,
1024 pbss_network
->MacAddress
,
1029 /* fix bug of flush_cam_entry at STOP AP mode */
1030 psta
->state
|= WIFI_AP_STATE
;
1031 rtw_indicate_connect23a(padapter
);
1033 /* for check if already set beacon */
1034 pmlmepriv
->cur_network
.join_res
= true;
1039 void rtw_set_macaddr_acl23a(struct rtw_adapter
*padapter
, int mode
)
1041 struct sta_priv
*pstapriv
= &padapter
->stapriv
;
1042 struct wlan_acl_pool
*pacl_list
= &pstapriv
->acl_list
;
1044 DBG_8723A("%s, mode =%d\n", __func__
, mode
);
1046 pacl_list
->mode
= mode
;
1049 static void update_bcn_erpinfo_ie(struct rtw_adapter
*padapter
)
1051 struct mlme_priv
*pmlmepriv
= &padapter
->mlmepriv
;
1052 struct mlme_ext_priv
*pmlmeext
= &padapter
->mlmeextpriv
;
1053 struct mlme_ext_info
*pmlmeinfo
= &pmlmeext
->mlmext_info
;
1054 struct wlan_bssid_ex
*pnetwork
= &pmlmeinfo
->network
;
1055 unsigned char *p
, *ie
= pnetwork
->IEs
;
1058 DBG_8723A("%s, ERP_enable =%d\n", __func__
, pmlmeinfo
->ERP_enable
);
1060 if (!pmlmeinfo
->ERP_enable
)
1063 /* parsing ERP_IE */
1064 p
= rtw_get_ie23a(ie
, WLAN_EID_ERP_INFO
, &len
, pnetwork
->IELength
);
1066 if (pmlmepriv
->num_sta_non_erp
== 1)
1067 p
[2] |= WLAN_ERP_NON_ERP_PRESENT
|
1068 WLAN_ERP_USE_PROTECTION
;
1070 p
[2] &= ~(WLAN_ERP_NON_ERP_PRESENT
|
1071 WLAN_ERP_USE_PROTECTION
);
1073 if (pmlmepriv
->num_sta_no_short_preamble
> 0)
1074 p
[2] |= WLAN_ERP_BARKER_PREAMBLE
;
1076 p
[2] &= ~(WLAN_ERP_BARKER_PREAMBLE
);
1078 ERP_IE_handler23a(padapter
, p
);
1082 static void update_bcn_wpa_ie(struct rtw_adapter
*padapter
)
1084 DBG_8723A("%s\n", __func__
);
1087 static void update_bcn_wmm_ie(struct rtw_adapter
*padapter
)
1089 DBG_8723A("%s\n", __func__
);
1092 static void update_bcn_wps_ie(struct rtw_adapter
*padapter
)
1094 DBG_8723A("%s\n", __func__
);
1097 static void update_bcn_p2p_ie(struct rtw_adapter
*padapter
)
1101 static void update_bcn_vendor_spec_ie(struct rtw_adapter
*padapter
, u8
*oui
)
1103 DBG_8723A("%s\n", __func__
);
1105 if (!memcmp(RTW_WPA_OUI23A_TYPE
, oui
, 4))
1106 update_bcn_wpa_ie(padapter
);
1107 else if (!memcmp(WMM_OUI23A
, oui
, 4))
1108 update_bcn_wmm_ie(padapter
);
1109 else if (!memcmp(WPS_OUI23A
, oui
, 4))
1110 update_bcn_wps_ie(padapter
);
1111 else if (!memcmp(P2P_OUI23A
, oui
, 4))
1112 update_bcn_p2p_ie(padapter
);
1114 DBG_8723A("unknown OUI type!\n");
1117 void update_beacon23a(struct rtw_adapter
*padapter
, u8 ie_id
, u8
*oui
, u8 tx
)
1119 struct mlme_priv
*pmlmepriv
;
1120 struct mlme_ext_priv
*pmlmeext
;
1121 /* struct mlme_ext_info *pmlmeinfo; */
1123 /* DBG_8723A("%s\n", __func__); */
1128 pmlmepriv
= &padapter
->mlmepriv
;
1129 pmlmeext
= &padapter
->mlmeextpriv
;
1130 /* pmlmeinfo = &pmlmeext->mlmext_info; */
1132 if (false == pmlmeext
->bstart_bss
)
1135 spin_lock_bh(&pmlmepriv
->bcn_update_lock
);
1139 update_BCNTIM(padapter
);
1142 case WLAN_EID_ERP_INFO
:
1143 update_bcn_erpinfo_ie(padapter
);
1146 case WLAN_EID_VENDOR_SPECIFIC
:
1147 update_bcn_vendor_spec_ie(padapter
, oui
);
1154 pmlmepriv
->update_bcn
= true;
1156 spin_unlock_bh(&pmlmepriv
->bcn_update_lock
);
1159 set_tx_beacon_cmd23a(padapter
);
1164 * Set to 0 (HT pure) under the following conditions
1165 * - all STAs in the BSS are 20/40 MHz HT in 20/40 MHz BSS or
1166 * - all STAs in the BSS are 20 MHz HT in 20 MHz BSS
1167 * Set to 1 (HT non-member protection) if there may be non-HT STAs
1168 * in both the primary and the secondary channel
1169 * Set to 2 if only HT STAs are associated in BSS,
1170 * however and at least one 20 MHz HT STA is associated
1171 * Set to 3 (HT mixed mode) when one or more non-HT STAs are associated
1172 * (currently non-GF HT station is considered as non-HT STA also)
1174 static int rtw_ht_operation_update(struct rtw_adapter
*padapter
)
1176 u16 cur_op_mode
, new_op_mode
;
1177 int op_mode_changes
= 0;
1178 struct mlme_priv
*pmlmepriv
= &padapter
->mlmepriv
;
1179 struct ht_priv
*phtpriv_ap
= &pmlmepriv
->htpriv
;
1181 if (pmlmepriv
->htpriv
.ht_option
)
1184 /* if (!iface->conf->ieee80211n || iface->conf->ht_op_mode_fixed) */
1187 DBG_8723A("%s current operation mode = 0x%X\n",
1188 __func__
, pmlmepriv
->ht_op_mode
);
1190 if (!(pmlmepriv
->ht_op_mode
& IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT
)
1191 && pmlmepriv
->num_sta_ht_no_gf
) {
1192 pmlmepriv
->ht_op_mode
|=
1193 IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT
;
1195 } else if ((pmlmepriv
->ht_op_mode
&
1196 IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT
) &&
1197 pmlmepriv
->num_sta_ht_no_gf
== 0) {
1198 pmlmepriv
->ht_op_mode
&=
1199 ~IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT
;
1203 if (!(pmlmepriv
->ht_op_mode
& IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT
) &&
1204 (pmlmepriv
->num_sta_no_ht
|| pmlmepriv
->olbc_ht
)) {
1205 pmlmepriv
->ht_op_mode
|= IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT
;
1207 } else if ((pmlmepriv
->ht_op_mode
&
1208 IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT
) &&
1209 (pmlmepriv
->num_sta_no_ht
== 0 && !pmlmepriv
->olbc_ht
)) {
1210 pmlmepriv
->ht_op_mode
&=
1211 ~IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT
;
1216 * Note: currently we switch to the MIXED op mode if HT non-greenfield
1217 * station is associated. Probably it's a theoretical case, since
1218 * it looks like all known HT STAs support greenfield.
1220 if (pmlmepriv
->num_sta_no_ht
||
1221 (pmlmepriv
->ht_op_mode
& IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT
))
1222 new_op_mode
= IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED
;
1223 else if ((le16_to_cpu(phtpriv_ap
->ht_cap
.cap_info
) &
1224 IEEE80211_HT_CAP_SUP_WIDTH_20_40
) &&
1225 pmlmepriv
->num_sta_ht_20mhz
)
1226 new_op_mode
= IEEE80211_HT_OP_MODE_PROTECTION_20MHZ
;
1227 else if (pmlmepriv
->olbc_ht
)
1228 new_op_mode
= IEEE80211_HT_OP_MODE_PROTECTION_NONMEMBER
;
1230 new_op_mode
= IEEE80211_HT_OP_MODE_PROTECTION_NONE
;
1232 cur_op_mode
= pmlmepriv
->ht_op_mode
& IEEE80211_HT_OP_MODE_PROTECTION
;
1233 if (cur_op_mode
!= new_op_mode
) {
1234 pmlmepriv
->ht_op_mode
&= ~IEEE80211_HT_OP_MODE_PROTECTION
;
1235 pmlmepriv
->ht_op_mode
|= new_op_mode
;
1239 DBG_8723A("%s new operation mode = 0x%X changes =%d\n",
1240 __func__
, pmlmepriv
->ht_op_mode
, op_mode_changes
);
1242 return op_mode_changes
;
1245 void associated_clients_update23a(struct rtw_adapter
*padapter
, u8 updated
)
1247 /* update associated stations cap. */
1248 if (updated
== true) {
1249 struct list_head
*phead
;
1250 struct sta_info
*psta
, *ptmp
;
1251 struct sta_priv
*pstapriv
= &padapter
->stapriv
;
1253 spin_lock_bh(&pstapriv
->asoc_list_lock
);
1254 phead
= &pstapriv
->asoc_list
;
1255 list_for_each_entry_safe(psta
, ptmp
, phead
, asoc_list
)
1256 VCS_update23a(padapter
, psta
);
1257 spin_unlock_bh(&pstapriv
->asoc_list_lock
);
1261 /* called > TSR LEVEL for USB or SDIO Interface */
1262 void bss_cap_update_on_sta_join23a(struct rtw_adapter
*padapter
, struct sta_info
*psta
)
1264 u8 beacon_updated
= false;
1265 struct mlme_priv
*pmlmepriv
= &padapter
->mlmepriv
;
1266 struct mlme_ext_priv
*pmlmeext
= &padapter
->mlmeextpriv
;
1268 if (!(psta
->flags
& WLAN_STA_SHORT_PREAMBLE
)) {
1269 if (!psta
->no_short_preamble_set
) {
1270 psta
->no_short_preamble_set
= 1;
1272 pmlmepriv
->num_sta_no_short_preamble
++;
1274 if ((pmlmeext
->cur_wireless_mode
> WIRELESS_11B
) &&
1275 (pmlmepriv
->num_sta_no_short_preamble
== 1)) {
1276 beacon_updated
= true;
1277 update_beacon23a(padapter
, 0xFF, NULL
, true);
1282 if (psta
->no_short_preamble_set
) {
1283 psta
->no_short_preamble_set
= 0;
1285 pmlmepriv
->num_sta_no_short_preamble
--;
1287 if ((pmlmeext
->cur_wireless_mode
> WIRELESS_11B
) &&
1288 (pmlmepriv
->num_sta_no_short_preamble
== 0)) {
1289 beacon_updated
= true;
1290 update_beacon23a(padapter
, 0xFF, NULL
, true);
1296 if (psta
->flags
& WLAN_STA_NONERP
) {
1297 if (!psta
->nonerp_set
) {
1298 psta
->nonerp_set
= 1;
1300 pmlmepriv
->num_sta_non_erp
++;
1302 if (pmlmepriv
->num_sta_non_erp
== 1) {
1303 beacon_updated
= true;
1304 update_beacon23a(padapter
, WLAN_EID_ERP_INFO
, NULL
, true);
1309 if (psta
->nonerp_set
) {
1310 psta
->nonerp_set
= 0;
1312 pmlmepriv
->num_sta_non_erp
--;
1314 if (pmlmepriv
->num_sta_non_erp
== 0) {
1315 beacon_updated
= true;
1316 update_beacon23a(padapter
, WLAN_EID_ERP_INFO
, NULL
, true);
1322 if (!(psta
->capability
& WLAN_CAPABILITY_SHORT_SLOT_TIME
)) {
1323 if (!psta
->no_short_slot_time_set
) {
1324 psta
->no_short_slot_time_set
= 1;
1326 pmlmepriv
->num_sta_no_short_slot_time
++;
1328 if ((pmlmeext
->cur_wireless_mode
> WIRELESS_11B
) &&
1329 (pmlmepriv
->num_sta_no_short_slot_time
== 1)) {
1330 beacon_updated
= true;
1331 update_beacon23a(padapter
, 0xFF, NULL
, true);
1336 if (psta
->no_short_slot_time_set
) {
1337 psta
->no_short_slot_time_set
= 0;
1339 pmlmepriv
->num_sta_no_short_slot_time
--;
1341 if ((pmlmeext
->cur_wireless_mode
> WIRELESS_11B
) &&
1342 (pmlmepriv
->num_sta_no_short_slot_time
== 0)) {
1343 beacon_updated
= true;
1344 update_beacon23a(padapter
, 0xFF, NULL
, true);
1349 if (psta
->flags
& WLAN_STA_HT
) {
1350 u16 ht_capab
= le16_to_cpu(psta
->htpriv
.ht_cap
.cap_info
);
1352 DBG_8723A("HT: STA %pM HT Capabilities Info: 0x%04x\n",
1353 psta
->hwaddr
, ht_capab
);
1355 if (psta
->no_ht_set
) {
1356 psta
->no_ht_set
= 0;
1357 pmlmepriv
->num_sta_no_ht
--;
1360 if ((ht_capab
& IEEE80211_HT_CAP_GRN_FLD
) == 0) {
1361 if (!psta
->no_ht_gf_set
) {
1362 psta
->no_ht_gf_set
= 1;
1363 pmlmepriv
->num_sta_ht_no_gf
++;
1365 DBG_8723A("%s STA %pM - no greenfield, num of non-gf stations %d\n",
1366 __func__
, psta
->hwaddr
,
1367 pmlmepriv
->num_sta_ht_no_gf
);
1370 if ((ht_capab
& IEEE80211_HT_CAP_SUP_WIDTH_20_40
) == 0) {
1371 if (!psta
->ht_20mhz_set
) {
1372 psta
->ht_20mhz_set
= 1;
1373 pmlmepriv
->num_sta_ht_20mhz
++;
1375 DBG_8723A("%s STA %pM - 20 MHz HT, num of 20MHz HT STAs %d\n",
1376 __func__
, psta
->hwaddr
,
1377 pmlmepriv
->num_sta_ht_20mhz
);
1381 if (!psta
->no_ht_set
) {
1382 psta
->no_ht_set
= 1;
1383 pmlmepriv
->num_sta_no_ht
++;
1385 if (pmlmepriv
->htpriv
.ht_option
) {
1386 DBG_8723A("%s STA %pM - no HT, num of non-HT stations %d\n",
1387 __func__
, psta
->hwaddr
,
1388 pmlmepriv
->num_sta_no_ht
);
1392 if (rtw_ht_operation_update(padapter
) > 0) {
1393 update_beacon23a(padapter
, WLAN_EID_HT_CAPABILITY
, NULL
, false);
1394 update_beacon23a(padapter
, WLAN_EID_HT_OPERATION
, NULL
, true);
1397 /* update associated stations cap. */
1398 associated_clients_update23a(padapter
, beacon_updated
);
1400 DBG_8723A("%s, updated =%d\n", __func__
, beacon_updated
);
1403 u8
bss_cap_update_on_sta_leave23a(struct rtw_adapter
*padapter
, struct sta_info
*psta
)
1405 u8 beacon_updated
= false;
1406 struct mlme_priv
*pmlmepriv
= &padapter
->mlmepriv
;
1407 struct mlme_ext_priv
*pmlmeext
= &padapter
->mlmeextpriv
;
1410 return beacon_updated
;
1412 if (psta
->no_short_preamble_set
) {
1413 psta
->no_short_preamble_set
= 0;
1414 pmlmepriv
->num_sta_no_short_preamble
--;
1415 if (pmlmeext
->cur_wireless_mode
> WIRELESS_11B
1416 && pmlmepriv
->num_sta_no_short_preamble
== 0) {
1417 beacon_updated
= true;
1418 update_beacon23a(padapter
, 0xFF, NULL
, true);
1422 if (psta
->nonerp_set
) {
1423 psta
->nonerp_set
= 0;
1424 pmlmepriv
->num_sta_non_erp
--;
1425 if (pmlmepriv
->num_sta_non_erp
== 0) {
1426 beacon_updated
= true;
1427 update_beacon23a(padapter
, WLAN_EID_ERP_INFO
,
1432 if (psta
->no_short_slot_time_set
) {
1433 psta
->no_short_slot_time_set
= 0;
1434 pmlmepriv
->num_sta_no_short_slot_time
--;
1435 if (pmlmeext
->cur_wireless_mode
> WIRELESS_11B
1436 && pmlmepriv
->num_sta_no_short_slot_time
== 0) {
1437 beacon_updated
= true;
1438 update_beacon23a(padapter
, 0xFF, NULL
, true);
1442 if (psta
->no_ht_gf_set
) {
1443 psta
->no_ht_gf_set
= 0;
1444 pmlmepriv
->num_sta_ht_no_gf
--;
1447 if (psta
->no_ht_set
) {
1448 psta
->no_ht_set
= 0;
1449 pmlmepriv
->num_sta_no_ht
--;
1452 if (psta
->ht_20mhz_set
) {
1453 psta
->ht_20mhz_set
= 0;
1454 pmlmepriv
->num_sta_ht_20mhz
--;
1457 if (rtw_ht_operation_update(padapter
) > 0) {
1458 update_beacon23a(padapter
, WLAN_EID_HT_CAPABILITY
, NULL
, false);
1459 update_beacon23a(padapter
, WLAN_EID_HT_OPERATION
, NULL
, true);
1462 /* update associated stations cap. */
1464 DBG_8723A("%s, updated =%d\n", __func__
, beacon_updated
);
1466 return beacon_updated
;
1469 u8
ap_free_sta23a(struct rtw_adapter
*padapter
, struct sta_info
*psta
, bool active
, u16 reason
)
1471 struct sta_priv
*pstapriv
= &padapter
->stapriv
;
1472 u8 beacon_updated
= false;
1475 return beacon_updated
;
1478 /* tear down Rx AMPDU */
1479 send_delba23a(padapter
, 0, psta
->hwaddr
); /* recipient */
1481 /* tear down TX AMPDU */
1482 send_delba23a(padapter
, 1, psta
->hwaddr
); /* originator */
1484 issue_deauth23a(padapter
, psta
->hwaddr
, reason
);
1487 psta
->htpriv
.agg_enable_bitmap
= 0x0; /* reset */
1488 psta
->htpriv
.candidate_tid_bitmap
= 0x0; /* reset */
1490 /* report_del_sta_event23a(padapter, psta->hwaddr, reason); */
1492 /* clear cam entry / key */
1493 /* clear_cam_entry23a(padapter, (psta->mac_id + 3)); */
1494 rtw_clearstakey_cmd23a(padapter
, (u8
*)psta
, (u8
)(psta
->mac_id
+ 3),
1497 spin_lock_bh(&psta
->lock
);
1498 psta
->state
&= ~_FW_LINKED
;
1499 spin_unlock_bh(&psta
->lock
);
1501 rtw_cfg80211_indicate_sta_disassoc(padapter
, psta
->hwaddr
, reason
);
1503 report_del_sta_event23a(padapter
, psta
->hwaddr
, reason
);
1505 beacon_updated
= bss_cap_update_on_sta_leave23a(padapter
, psta
);
1507 spin_lock_bh(&pstapriv
->sta_hash_lock
);
1508 rtw_free_stainfo23a(padapter
, psta
);
1509 spin_unlock_bh(&pstapriv
->sta_hash_lock
);
1511 return beacon_updated
;
1514 int rtw_sta_flush23a(struct rtw_adapter
*padapter
)
1516 struct list_head
*phead
;
1517 struct sta_info
*psta
, *ptmp
;
1518 struct sta_priv
*pstapriv
= &padapter
->stapriv
;
1519 struct mlme_ext_priv
*pmlmeext
= &padapter
->mlmeextpriv
;
1520 struct mlme_ext_info
*pmlmeinfo
= &pmlmeext
->mlmext_info
;
1521 u8 bc_addr
[ETH_ALEN
] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
1522 u8 chk_alive_num
= 0;
1523 struct sta_info
*chk_alive_list
[NUM_STA
];
1526 DBG_8723A("%s(%s)\n", __func__
, padapter
->pnetdev
->name
);
1528 if ((pmlmeinfo
->state
&0x03) != MSR_AP
)
1531 spin_lock_bh(&pstapriv
->asoc_list_lock
);
1532 phead
= &pstapriv
->asoc_list
;
1533 list_for_each_entry_safe(psta
, ptmp
, phead
, asoc_list
) {
1534 /* Remove sta from asoc_list */
1535 list_del_init(&psta
->asoc_list
);
1536 pstapriv
->asoc_list_cnt
--;
1538 /* Keep sta for ap_free_sta23a() beyond this asoc_list loop */
1539 chk_alive_list
[chk_alive_num
++] = psta
;
1541 spin_unlock_bh(&pstapriv
->asoc_list_lock
);
1543 /* For each sta in chk_alive_list, call ap_free_sta23a */
1544 for (i
= 0; i
< chk_alive_num
; i
++)
1545 ap_free_sta23a(padapter
, chk_alive_list
[i
], true,
1546 WLAN_REASON_DEAUTH_LEAVING
);
1548 issue_deauth23a(padapter
, bc_addr
, WLAN_REASON_DEAUTH_LEAVING
);
1550 associated_clients_update23a(padapter
, true);
1555 /* called > TSR LEVEL for USB or SDIO Interface */
1556 void sta_info_update23a(struct rtw_adapter
*padapter
, struct sta_info
*psta
)
1558 int flags
= psta
->flags
;
1559 struct mlme_priv
*pmlmepriv
= &padapter
->mlmepriv
;
1561 /* update wmm cap. */
1562 if (WLAN_STA_WME
&flags
)
1563 psta
->qos_option
= 1;
1565 psta
->qos_option
= 0;
1567 if (pmlmepriv
->qos_option
== 0)
1568 psta
->qos_option
= 0;
1570 /* update 802.11n ht cap. */
1571 if (WLAN_STA_HT
&flags
) {
1572 psta
->htpriv
.ht_option
= true;
1573 psta
->qos_option
= 1;
1575 psta
->htpriv
.ht_option
= false;
1578 if (!pmlmepriv
->htpriv
.ht_option
)
1579 psta
->htpriv
.ht_option
= false;
1581 update_sta_info23a_apmode23a(padapter
, psta
);
1584 /* called >= TSR LEVEL for USB or SDIO Interface */
1585 void ap_sta_info_defer_update23a(struct rtw_adapter
*padapter
, struct sta_info
*psta
)
1587 if (psta
->state
& _FW_LINKED
) {
1589 add_RATid23a(padapter
, psta
, 0);/* DM_RATR_STA_INIT */
1593 /* restore hw setting from sw data structures */
1594 void rtw_ap_restore_network(struct rtw_adapter
*padapter
)
1596 struct mlme_priv
*mlmepriv
= &padapter
->mlmepriv
;
1597 struct mlme_ext_priv
*pmlmeext
= &padapter
->mlmeextpriv
;
1598 struct sta_priv
*pstapriv
= &padapter
->stapriv
;
1599 struct sta_info
*psta
, *ptmp
;
1600 struct security_priv
*psecuritypriv
= &padapter
->securitypriv
;
1601 struct list_head
*phead
;
1602 u8 chk_alive_num
= 0;
1603 struct sta_info
*chk_alive_list
[NUM_STA
];
1606 rtw_setopmode_cmd23a(padapter
, NL80211_IFTYPE_AP
);
1608 set_channel_bwmode23a(padapter
, pmlmeext
->cur_channel
, pmlmeext
->cur_ch_offset
, pmlmeext
->cur_bwmode
);
1610 start_bss_network(padapter
, (u8
*)&mlmepriv
->cur_network
.network
);
1612 if (padapter
->securitypriv
.dot11PrivacyAlgrthm
==
1613 WLAN_CIPHER_SUITE_TKIP
||
1614 padapter
->securitypriv
.dot11PrivacyAlgrthm
==
1615 WLAN_CIPHER_SUITE_CCMP
) {
1616 /* restore group key, WEP keys is restored in ips_leave23a() */
1617 rtw_set_key23a(padapter
, psecuritypriv
,
1618 psecuritypriv
->dot118021XGrpKeyid
, 0);
1621 /* per sta pairwise key and settings */
1622 if (padapter
->securitypriv
.dot11PrivacyAlgrthm
!=
1623 WLAN_CIPHER_SUITE_TKIP
&&
1624 padapter
->securitypriv
.dot11PrivacyAlgrthm
!=
1625 WLAN_CIPHER_SUITE_CCMP
) {
1629 spin_lock_bh(&pstapriv
->asoc_list_lock
);
1630 phead
= &pstapriv
->asoc_list
;
1631 list_for_each_entry_safe(psta
, ptmp
, phead
, asoc_list
)
1632 chk_alive_list
[chk_alive_num
++] = psta
;
1633 spin_unlock_bh(&pstapriv
->asoc_list_lock
);
1635 for (i
= 0; i
< chk_alive_num
; i
++) {
1636 psta
= chk_alive_list
[i
];
1638 if (psta
->state
& _FW_LINKED
) {
1639 Update_RA_Entry23a(padapter
, psta
);
1641 rtw_setstakey_cmd23a(padapter
, (unsigned char *)psta
, true);
1646 void start_ap_mode23a(struct rtw_adapter
*padapter
)
1649 struct mlme_priv
*pmlmepriv
= &padapter
->mlmepriv
;
1650 struct sta_priv
*pstapriv
= &padapter
->stapriv
;
1651 struct mlme_ext_priv
*pmlmeext
= &padapter
->mlmeextpriv
;
1652 struct wlan_acl_pool
*pacl_list
= &pstapriv
->acl_list
;
1654 pmlmepriv
->update_bcn
= false;
1656 /* init_mlme_ap_info23a(padapter); */
1657 pmlmeext
->bstart_bss
= false;
1659 pmlmepriv
->num_sta_non_erp
= 0;
1661 pmlmepriv
->num_sta_no_short_slot_time
= 0;
1663 pmlmepriv
->num_sta_no_short_preamble
= 0;
1665 pmlmepriv
->num_sta_ht_no_gf
= 0;
1666 pmlmepriv
->num_sta_no_ht
= 0;
1667 pmlmepriv
->num_sta_ht_20mhz
= 0;
1669 pmlmepriv
->olbc
= false;
1671 pmlmepriv
->olbc_ht
= false;
1673 pmlmepriv
->ht_op_mode
= 0;
1675 for (i
= 0; i
< NUM_STA
; i
++)
1676 pstapriv
->sta_aid
[i
] = NULL
;
1679 INIT_LIST_HEAD(&pacl_list
->acl_node_q
.queue
);
1681 pacl_list
->mode
= 0;
1682 for (i
= 0; i
< NUM_ACL
; i
++) {
1683 INIT_LIST_HEAD(&pacl_list
->aclnode
[i
].list
);
1684 pacl_list
->aclnode
[i
].valid
= false;
1688 void stop_ap_mode23a(struct rtw_adapter
*padapter
)
1690 struct list_head
*phead
;
1691 struct rtw_wlan_acl_node
*paclnode
, *ptmp
;
1692 struct sta_info
*psta
= NULL
;
1693 struct sta_priv
*pstapriv
= &padapter
->stapriv
;
1694 struct mlme_priv
*pmlmepriv
= &padapter
->mlmepriv
;
1695 struct mlme_ext_priv
*pmlmeext
= &padapter
->mlmeextpriv
;
1696 struct wlan_acl_pool
*pacl_list
= &pstapriv
->acl_list
;
1697 struct rtw_queue
*pacl_node_q
= &pacl_list
->acl_node_q
;
1699 pmlmepriv
->update_bcn
= false;
1700 pmlmeext
->bstart_bss
= false;
1703 * reset and init security priv , this can
1704 * refine with rtw_reset_securitypriv23a
1706 memset((unsigned char *)&padapter
->securitypriv
, 0, sizeof(struct security_priv
));
1707 padapter
->securitypriv
.ndisauthtype
= Ndis802_11AuthModeOpen
;
1708 padapter
->securitypriv
.ndisencryptstatus
= Ndis802_11WEPDisabled
;
1711 spin_lock_bh(&pacl_node_q
->lock
);
1712 phead
= get_list_head(pacl_node_q
);
1713 list_for_each_entry_safe(paclnode
, ptmp
, phead
, list
) {
1714 if (paclnode
->valid
== true) {
1715 paclnode
->valid
= false;
1716 list_del_init(&paclnode
->list
);
1720 spin_unlock_bh(&pacl_node_q
->lock
);
1722 DBG_8723A("%s, free acl_node_queue, num =%d\n",
1723 __func__
, pacl_list
->num
);
1725 rtw_sta_flush23a(padapter
);
1727 /* free_assoc_sta_resources */
1728 rtw_free_all_stainfo23a(padapter
);
1730 psta
= rtw_get_bcmc_stainfo23a(padapter
);
1731 spin_lock_bh(&pstapriv
->sta_hash_lock
);
1732 rtw_free_stainfo23a(padapter
, psta
);
1733 spin_unlock_bh(&pstapriv
->sta_hash_lock
);
1735 rtw_init_bcmc_stainfo23a(padapter
);
1737 rtw23a_free_mlme_priv_ie_data(pmlmepriv
);