1 /******************************************************************************
3 * Copyright(c) 2007 - 2017 Realtek Corporation.
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 <drv_types.h>
22 extern unsigned char RTW_WPA_OUI[];
23 extern unsigned char WMM_OUI[];
24 extern unsigned char WPS_OUI[];
25 extern unsigned char P2P_OUI[];
26 extern unsigned char WFD_OUI[];
28 void init_mlme_ap_info(_adapter *padapter)
30 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
32 _rtw_spinlock_init(&pmlmepriv->bcn_update_lock);
33 /* pmlmeext->bstart_bss = _FALSE; */
36 void free_mlme_ap_info(_adapter *padapter)
38 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
40 stop_ap_mode(padapter);
41 _rtw_spinlock_free(&pmlmepriv->bcn_update_lock);
47 * return length of total TIM IE
49 u8 rtw_set_tim_ie(u8 dtim_cnt, u8 dtim_period
50 , const u8 *tim_bmp, u8 tim_bmp_len, u8 *tim_ie)
56 if (rtw_bmp_not_empty(tim_bmp, tim_bmp_len)) {
57 /* find the first nonzero octet in tim_bitmap */
58 for (i = 0; i < tim_bmp_len; i++)
63 /* find the last nonzero octet in tim_bitmap, except octet 0 */
64 for (i = tim_bmp_len - 1; i > 0; i--)
68 bmp_len = n2 - n1 + 1;
75 *p++ = 2 + 1 + bmp_len;
78 *p++ = (rtw_bmp_is_set(tim_bmp, tim_bmp_len, 0) ? BIT0 : 0) | n1;
79 _rtw_memcpy(p, tim_bmp + n1, bmp_len);
82 RTW_INFO("n1:%u, n2:%u, bmp_offset:%u, bmp_len:%u\n", n1, n2, n1 / 2, bmp_len);
83 RTW_INFO_DUMP("tim_ie: ", tim_ie + 2, 2 + 1 + bmp_len);
85 return 2 + 2 + 1 + bmp_len;
88 static void update_BCNTIM(_adapter *padapter)
90 struct sta_priv *pstapriv = &padapter->stapriv;
91 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
92 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
93 WLAN_BSSID_EX *pnetwork_mlmeext = &(pmlmeinfo->network);
94 unsigned char *pie = pnetwork_mlmeext->IEs;
100 /* if(rtw_tim_map_anyone_be_set(padapter, pstapriv->tim_bitmap)) */
103 u8 *p, *dst_ie, *premainder_ie = NULL, *pbackup_remainder_ie = NULL;
104 uint offset, tmp_len, tim_ielen, tim_ie_offset, remainder_ielen;
106 p = rtw_get_ie(pie + _FIXED_IE_LENGTH_, _TIM_IE_, &tim_ielen, pnetwork_mlmeext->IELength - _FIXED_IE_LENGTH_);
107 if (p != NULL && tim_ielen > 0) {
110 premainder_ie = p + tim_ielen;
112 tim_ie_offset = (sint)(p - pie);
114 remainder_ielen = pnetwork_mlmeext->IELength - tim_ie_offset - tim_ielen;
116 /*append TIM IE from dst_ie offset*/
121 /*calculate head_len*/
122 offset = _FIXED_IE_LENGTH_;
124 /* get ssid_ie len */
125 p = rtw_get_ie(pie + _BEACON_IE_OFFSET_, _SSID_IE_, &tmp_len, (pnetwork_mlmeext->IELength - _BEACON_IE_OFFSET_));
127 offset += tmp_len + 2;
129 /*get supported rates len*/
130 p = rtw_get_ie(pie + _BEACON_IE_OFFSET_, _SUPPORTEDRATES_IE_, &tmp_len, (pnetwork_mlmeext->IELength - _BEACON_IE_OFFSET_));
132 offset += tmp_len + 2;
134 /*DS Parameter Set IE, len=3*/
137 premainder_ie = pie + offset;
139 remainder_ielen = pnetwork_mlmeext->IELength - offset - tim_ielen;
141 /*append TIM IE from offset*/
142 dst_ie = pie + offset;
146 if (remainder_ielen > 0) {
147 pbackup_remainder_ie = rtw_malloc(remainder_ielen);
148 if (pbackup_remainder_ie && premainder_ie)
149 _rtw_memcpy(pbackup_remainder_ie, premainder_ie, remainder_ielen);
153 dst_ie += rtw_set_tim_ie(0, 1, pstapriv->tim_bitmap, pstapriv->aid_bmp_len, dst_ie);
155 /*copy remainder IE*/
156 if (pbackup_remainder_ie) {
157 _rtw_memcpy(dst_ie, pbackup_remainder_ie, remainder_ielen);
159 rtw_mfree(pbackup_remainder_ie, remainder_ielen);
162 offset = (uint)(dst_ie - pie);
163 pnetwork_mlmeext->IELength = offset + remainder_ielen;
168 void rtw_add_bcn_ie(_adapter *padapter, WLAN_BSSID_EX *pnetwork, u8 index, u8 *data, u8 len)
170 PNDIS_802_11_VARIABLE_IEs pIE;
172 u8 *pie = pnetwork->IEs;
173 u8 *p = NULL, *dst_ie = NULL, *premainder_ie = NULL, *pbackup_remainder_ie = NULL;
174 u32 i, offset, ielen = 0, ie_offset, remainder_ielen = 0;
176 for (i = sizeof(NDIS_802_11_FIXED_IEs); i < pnetwork->IELength;) {
177 pIE = (PNDIS_802_11_VARIABLE_IEs)(pnetwork->IEs + i);
179 if (pIE->ElementID > index)
181 else if (pIE->ElementID == index) { /* already exist the same IE */
190 i += (pIE->Length + 2);
193 if (p != NULL && ielen > 0) {
196 premainder_ie = p + ielen;
198 ie_offset = (sint)(p - pie);
200 remainder_ielen = pnetwork->IELength - ie_offset - ielen;
205 dst_ie = (p + ielen);
211 if (remainder_ielen > 0) {
212 pbackup_remainder_ie = rtw_malloc(remainder_ielen);
213 if (pbackup_remainder_ie && premainder_ie)
214 _rtw_memcpy(pbackup_remainder_ie, premainder_ie, remainder_ielen);
220 _rtw_memcpy(dst_ie, data, len);
223 /* copy remainder IE */
224 if (pbackup_remainder_ie) {
225 _rtw_memcpy(dst_ie, pbackup_remainder_ie, remainder_ielen);
227 rtw_mfree(pbackup_remainder_ie, remainder_ielen);
230 offset = (uint)(dst_ie - pie);
231 pnetwork->IELength = offset + remainder_ielen;
234 void rtw_remove_bcn_ie(_adapter *padapter, WLAN_BSSID_EX *pnetwork, u8 index)
236 u8 *p, *dst_ie = NULL, *premainder_ie = NULL, *pbackup_remainder_ie = NULL;
237 uint offset, ielen, ie_offset, remainder_ielen = 0;
238 u8 *pie = pnetwork->IEs;
240 p = rtw_get_ie(pie + _FIXED_IE_LENGTH_, index, &ielen, pnetwork->IELength - _FIXED_IE_LENGTH_);
241 if (p != NULL && ielen > 0) {
244 premainder_ie = p + ielen;
246 ie_offset = (sint)(p - pie);
248 remainder_ielen = pnetwork->IELength - ie_offset - ielen;
254 if (remainder_ielen > 0) {
255 pbackup_remainder_ie = rtw_malloc(remainder_ielen);
256 if (pbackup_remainder_ie && premainder_ie)
257 _rtw_memcpy(pbackup_remainder_ie, premainder_ie, remainder_ielen);
260 /* copy remainder IE */
261 if (pbackup_remainder_ie) {
262 _rtw_memcpy(dst_ie, pbackup_remainder_ie, remainder_ielen);
264 rtw_mfree(pbackup_remainder_ie, remainder_ielen);
267 offset = (uint)(dst_ie - pie);
268 pnetwork->IELength = offset + remainder_ielen;
272 u8 chk_sta_is_alive(struct sta_info *psta);
273 u8 chk_sta_is_alive(struct sta_info *psta)
276 #ifdef DBG_EXPIRATION_CHK
277 RTW_INFO("sta:"MAC_FMT", rssi:%d, rx:"STA_PKTS_FMT", expire_to:%u, %s%ssq_len:%u\n"
278 , MAC_ARG(psta->cmn.mac_addr)
279 , psta->cmn.rssi_stat.rssi
280 /* , STA_RX_PKTS_ARG(psta) */
281 , STA_RX_PKTS_DIFF_ARG(psta)
283 , psta->state & WIFI_SLEEP_STATE ? "PS, " : ""
284 , psta->state & WIFI_STA_ALIVE_CHK_STATE ? "SAC, " : ""
289 /* if(sta_last_rx_pkts(psta) == sta_rx_pkts(psta)) */
290 if ((psta->sta_stats.last_rx_data_pkts + psta->sta_stats.last_rx_ctrl_pkts) == (psta->sta_stats.rx_data_pkts + psta->sta_stats.rx_ctrl_pkts)) {
292 if (psta->state & WIFI_SLEEP_STATE)
295 #ifdef CONFIG_RTW_MESH
296 if (MLME_IS_MESH(psta->padapter) &&
297 (psta->sta_stats.last_rx_hwmp_pkts !=
298 psta->sta_stats.rx_hwmp_pkts))
304 sta_update_last_rx_pkts(psta);
310 * issue_aka_chk_frame - issue active keep alive check frame
311 * aka = active keep alive
313 static int issue_aka_chk_frame(_adapter *adapter, struct sta_info *psta)
316 u8 *target_addr = psta->cmn.mac_addr;
318 if (MLME_IS_AP(adapter)) {
319 /* issue null data to check sta alive */
320 if (psta->state & WIFI_SLEEP_STATE)
321 ret = issue_nulldata(adapter, target_addr, 0, 1, 50);
323 ret = issue_nulldata(adapter, target_addr, 0, 3, 50);
326 #ifdef CONFIG_RTW_MESH
327 if (MLME_IS_MESH(adapter)) {
328 struct rtw_mesh_path *mpath;
331 mpath = rtw_mesh_path_lookup(adapter, target_addr);
333 mpath = rtw_mesh_path_add(adapter, target_addr);
335 rtw_rcu_read_unlock();
336 RTW_ERR(FUNC_ADPT_FMT" rtw_mesh_path_add for "MAC_FMT" fail.\n",
337 FUNC_ADPT_ARG(adapter), MAC_ARG(target_addr));
341 if (mpath->flags & RTW_MESH_PATH_ACTIVE)
344 u8 flags = RTW_PREQ_Q_F_START | RTW_PREQ_Q_F_PEER_AKA;
345 /* issue PREQ to check peer alive */
346 rtw_mesh_queue_preq(mpath, flags);
349 rtw_rcu_read_unlock();
355 #ifdef RTW_CONFIG_RFREG18_WA
356 static void rtw_check_restore_rf18(_adapter *padapter)
358 PHAL_DATA_TYPE pHalData = GET_HAL_DATA(padapter);
359 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
361 u8 union_ch = 0, union_bw = 0, union_offset = 0, setchbw = _FALSE;
363 reg = rtw_hal_read_rfreg(padapter, 0, 0x18, 0x3FF);
364 if ((reg & 0xFF) == 0)
366 reg = rtw_hal_read_rfreg(padapter, 1, 0x18, 0x3FF);
367 if ((reg & 0xFF) == 0)
371 if (!rtw_mi_get_ch_setting_union(padapter, &union_ch, &union_bw, &union_offset)) {
372 RTW_INFO("Hit RF(0x18)=0!! restore original channel setting.\n");
373 union_ch = pmlmeext->cur_channel;
374 union_offset = pmlmeext->cur_ch_offset ;
375 union_bw = pmlmeext->cur_bwmode;
377 RTW_INFO("Hit RF(0x18)=0!! set ch(%x) offset(%x) bwmode(%x)\n", union_ch, union_offset, union_bw);
379 /* Initial the channel_bw setting procedure. */
380 pHalData->current_channel = 0;
381 set_channel_bwmode(padapter, union_ch, union_offset, union_bw);
386 void expire_timeout_chk(_adapter *padapter)
389 _list *phead, *plist;
391 struct sta_info *psta = NULL;
392 struct sta_priv *pstapriv = &padapter->stapriv;
393 u8 chk_alive_num = 0;
394 char chk_alive_list[NUM_STA];
397 #ifdef CONFIG_RTW_MESH
398 if (MLME_IS_MESH(padapter)
399 && check_fwstate(&padapter->mlmepriv, WIFI_ASOC_STATE)
401 struct rtw_mesh_cfg *mcfg = &padapter->mesh_cfg;
403 rtw_mesh_path_expire(padapter);
405 /* TBD: up layer timeout mechanism */
406 /* if (!mcfg->plink_timeout)
408 #ifndef CONFIG_ACTIVE_KEEP_ALIVE_CHECK
414 #ifdef CONFIG_MCC_MODE
415 /* then driver may check fail due to not recv client's frame under sitesurvey,
416 * don't expire timeout chk under MCC under sitesurvey */
418 if (rtw_hal_mcc_link_status_chk(padapter, __func__) == _FALSE)
422 _enter_critical_bh(&pstapriv->auth_list_lock, &irqL);
424 phead = &pstapriv->auth_list;
425 plist = get_next(phead);
427 /* check auth_queue */
428 #ifdef DBG_EXPIRATION_CHK
429 if (rtw_end_of_queue_search(phead, plist) == _FALSE) {
430 RTW_INFO(FUNC_ADPT_FMT" auth_list, cnt:%u\n"
431 , FUNC_ADPT_ARG(padapter), pstapriv->auth_list_cnt);
434 while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {
435 psta = LIST_CONTAINOR(plist, struct sta_info, auth_list);
437 plist = get_next(plist);
440 #ifdef CONFIG_ATMEL_RC_PATCH
441 if (_rtw_memcmp((void *)(pstapriv->atmel_rc_pattern), (void *)(psta->cmn.mac_addr), ETH_ALEN) == _TRUE)
443 if (psta->flag_atmel_rc)
446 if (psta->expire_to > 0) {
448 if (psta->expire_to == 0) {
449 rtw_list_delete(&psta->auth_list);
450 pstapriv->auth_list_cnt--;
452 RTW_INFO(FUNC_ADPT_FMT" auth expire "MAC_FMT"\n"
453 , FUNC_ADPT_ARG(padapter), MAC_ARG(psta->cmn.mac_addr));
455 _exit_critical_bh(&pstapriv->auth_list_lock, &irqL);
457 /* _enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL); */
458 rtw_free_stainfo(padapter, psta);
459 /* _exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL); */
461 _enter_critical_bh(&pstapriv->auth_list_lock, &irqL);
467 _exit_critical_bh(&pstapriv->auth_list_lock, &irqL);
471 _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
473 phead = &pstapriv->asoc_list;
474 plist = get_next(phead);
476 /* check asoc_queue */
477 #ifdef DBG_EXPIRATION_CHK
478 if (rtw_end_of_queue_search(phead, plist) == _FALSE) {
479 RTW_INFO(FUNC_ADPT_FMT" asoc_list, cnt:%u\n"
480 , FUNC_ADPT_ARG(padapter), pstapriv->asoc_list_cnt);
483 while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {
484 psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);
485 plist = get_next(plist);
486 #ifdef CONFIG_ATMEL_RC_PATCH
487 RTW_INFO("%s:%d psta=%p, %02x,%02x||%02x,%02x \n\n", __func__, __LINE__,
488 psta, pstapriv->atmel_rc_pattern[0], pstapriv->atmel_rc_pattern[5], psta->cmn.mac_addr[0], psta->cmn.mac_addr[5]);
489 if (_rtw_memcmp((void *)pstapriv->atmel_rc_pattern, (void *)(psta->cmn.mac_addr), ETH_ALEN) == _TRUE)
491 if (psta->flag_atmel_rc)
493 RTW_INFO("%s: debug line:%d\n", __func__, __LINE__);
495 #ifdef CONFIG_AUTO_AP_MODE
499 if (chk_sta_is_alive(psta) || !psta->expire_to) {
500 psta->expire_to = pstapriv->expire_to;
501 psta->keep_alive_trycnt = 0;
502 #ifdef CONFIG_TX_MCAST2UNI
503 psta->under_exist_checking = 0;
504 #endif /* CONFIG_TX_MCAST2UNI */
508 #ifndef CONFIG_ACTIVE_KEEP_ALIVE_CHECK
509 #ifdef CONFIG_80211N_HT
510 #ifdef CONFIG_TX_MCAST2UNI
511 if ((psta->flags & WLAN_STA_HT) && (psta->htpriv.agg_enable_bitmap || psta->under_exist_checking)) {
512 /* check sta by delba(addba) for 11n STA */
513 /* ToDo: use CCX report to check for all STAs */
514 /* RTW_INFO("asoc check by DELBA/ADDBA! (pstapriv->expire_to=%d s)(psta->expire_to=%d s), [%02x, %d]\n", pstapriv->expire_to*2, psta->expire_to*2, psta->htpriv.agg_enable_bitmap, psta->under_exist_checking); */
516 if (psta->expire_to <= (pstapriv->expire_to - 50)) {
517 RTW_INFO("asoc expire by DELBA/ADDBA! (%d s)\n", (pstapriv->expire_to - psta->expire_to) * 2);
518 psta->under_exist_checking = 0;
520 } else if (psta->expire_to <= (pstapriv->expire_to - 3) && (psta->under_exist_checking == 0)) {
521 RTW_INFO("asoc check by DELBA/ADDBA! (%d s)\n", (pstapriv->expire_to - psta->expire_to) * 2);
522 psta->under_exist_checking = 1;
523 /* tear down TX AMPDU */
524 send_delba(padapter, 1, psta->cmn.mac_addr);/* */ /* originator */
525 psta->htpriv.agg_enable_bitmap = 0x0;/* reset */
526 psta->htpriv.candidate_tid_bitmap = 0x0;/* reset */
529 #endif /* CONFIG_TX_MCAST2UNI */
530 #endif /* CONFIG_80211N_HT */
531 #endif /* CONFIG_ACTIVE_KEEP_ALIVE_CHECK */
533 if (psta->expire_to <= 0) {
534 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
536 if (padapter->registrypriv.wifi_spec == 1) {
537 psta->expire_to = pstapriv->expire_to;
541 #ifndef CONFIG_ACTIVE_KEEP_ALIVE_CHECK
542 #ifdef CONFIG_80211N_HT
544 #define KEEP_ALIVE_TRYCNT (3)
546 if (psta->keep_alive_trycnt > 0 && psta->keep_alive_trycnt <= KEEP_ALIVE_TRYCNT) {
547 if (psta->state & WIFI_STA_ALIVE_CHK_STATE)
548 psta->state ^= WIFI_STA_ALIVE_CHK_STATE;
550 psta->keep_alive_trycnt = 0;
552 } else if ((psta->keep_alive_trycnt > KEEP_ALIVE_TRYCNT) && !(psta->state & WIFI_STA_ALIVE_CHK_STATE))
553 psta->keep_alive_trycnt = 0;
554 if ((psta->htpriv.ht_option == _TRUE) && (psta->htpriv.ampdu_enable == _TRUE)) {
555 uint priority = 1; /* test using BK */
558 /* issued = (psta->htpriv.agg_enable_bitmap>>priority)&0x1; */
559 issued |= (psta->htpriv.candidate_tid_bitmap >> priority) & 0x1;
562 if (!(psta->state & WIFI_STA_ALIVE_CHK_STATE)) {
563 psta->htpriv.candidate_tid_bitmap |= BIT((u8)priority);
565 if (psta->state & WIFI_SLEEP_STATE)
566 psta->expire_to = 2; /* 2x2=4 sec */
568 psta->expire_to = 1; /* 2 sec */
570 psta->state |= WIFI_STA_ALIVE_CHK_STATE;
572 /* add_ba_hdl(padapter, (u8*)paddbareq_parm); */
574 RTW_INFO("issue addba_req to check if sta alive, keep_alive_trycnt=%d\n", psta->keep_alive_trycnt);
576 issue_addba_req(padapter, psta->cmn.mac_addr, (u8)priority);
578 _set_timer(&psta->addba_retry_timer, ADDBA_TO);
580 psta->keep_alive_trycnt++;
586 if (psta->keep_alive_trycnt > 0 && psta->state & WIFI_STA_ALIVE_CHK_STATE) {
587 psta->keep_alive_trycnt = 0;
588 psta->state ^= WIFI_STA_ALIVE_CHK_STATE;
589 RTW_INFO("change to another methods to check alive if staion is at ps mode\n");
592 #endif /* CONFIG_80211N_HT */
593 #endif /* CONFIG_ACTIVE_KEEP_ALIVE_CHECK */
594 if (psta->state & WIFI_SLEEP_STATE) {
595 if (!(psta->state & WIFI_STA_ALIVE_CHK_STATE)) {
596 /* to check if alive by another methods if staion is at ps mode. */
597 psta->expire_to = pstapriv->expire_to;
598 psta->state |= WIFI_STA_ALIVE_CHK_STATE;
600 /* RTW_INFO("alive chk, sta:" MAC_FMT " is at ps mode!\n", MAC_ARG(psta->cmn.mac_addr)); */
602 /* to update bcn with tim_bitmap for this station */
603 rtw_tim_map_set(padapter, pstapriv->tim_bitmap, psta->cmn.aid);
604 update_beacon(padapter, _TIM_IE_, NULL, _TRUE);
606 if (!pmlmeext->active_keep_alive_check)
614 stainfo_offset = rtw_stainfo_offset(pstapriv, psta);
615 if (stainfo_offset_valid(stainfo_offset))
616 chk_alive_list[chk_alive_num++] = stainfo_offset;
620 /* TODO: Aging mechanism to digest frames in sleep_q to avoid running out of xmitframe */
621 if (psta->sleepq_len > (NR_XMITFRAME / pstapriv->asoc_list_cnt)
622 && padapter->xmitpriv.free_xmitframe_cnt < ((NR_XMITFRAME / pstapriv->asoc_list_cnt) / 2)
624 RTW_INFO(FUNC_ADPT_FMT" sta:"MAC_FMT", sleepq_len:%u, free_xmitframe_cnt:%u, asoc_list_cnt:%u, clear sleep_q\n"
625 , FUNC_ADPT_ARG(padapter), MAC_ARG(psta->cmn.mac_addr)
626 , psta->sleepq_len, padapter->xmitpriv.free_xmitframe_cnt, pstapriv->asoc_list_cnt);
627 wakeup_sta_to_xmit(padapter, psta);
632 _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
635 #if defined(CONFIG_ACTIVE_KEEP_ALIVE_CHECK)
636 u8 backup_ch = 0, backup_bw = 0, backup_offset = 0;
637 u8 union_ch = 0, union_bw = 0, union_offset = 0;
638 u8 switch_channel_by_drv = _TRUE;
639 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
641 char del_asoc_list[NUM_STA];
643 _rtw_memset(del_asoc_list, NUM_STA, NUM_STA);
645 #ifdef CONFIG_ACTIVE_KEEP_ALIVE_CHECK
646 if (pmlmeext->active_keep_alive_check) {
647 #ifdef CONFIG_MCC_MODE
648 if (MCC_EN(padapter)) {
649 /* driver doesn't switch channel under MCC */
650 if (rtw_hal_check_mcc_status(padapter, MCC_STATUS_DOING_MCC))
651 switch_channel_by_drv = _FALSE;
655 if (!rtw_mi_get_ch_setting_union(padapter, &union_ch, &union_bw, &union_offset)
656 || pmlmeext->cur_channel != union_ch)
657 switch_channel_by_drv = _FALSE;
659 /* switch to correct channel of current network before issue keep-alive frames */
660 if (switch_channel_by_drv == _TRUE && rtw_get_oper_ch(padapter) != pmlmeext->cur_channel) {
661 backup_ch = rtw_get_oper_ch(padapter);
662 backup_bw = rtw_get_oper_bw(padapter);
663 backup_offset = rtw_get_oper_choffset(padapter);
664 set_channel_bwmode(padapter, union_ch, union_offset, union_bw);
667 #endif /* CONFIG_ACTIVE_KEEP_ALIVE_CHECK */
670 for (i = 0; i < chk_alive_num; i++) {
671 #ifdef CONFIG_ACTIVE_KEEP_ALIVE_CHECK
675 psta = rtw_get_stainfo_by_offset(pstapriv, chk_alive_list[i]);
677 #ifdef CONFIG_ATMEL_RC_PATCH
678 if (_rtw_memcmp(pstapriv->atmel_rc_pattern, psta->cmn.mac_addr, ETH_ALEN) == _TRUE)
680 if (psta->flag_atmel_rc)
684 if (!(psta->state & _FW_LINKED))
687 #ifdef CONFIG_ACTIVE_KEEP_ALIVE_CHECK
688 if (pmlmeext->active_keep_alive_check) {
689 /* issue active keep alive frame to check */
690 ret = issue_aka_chk_frame(padapter, psta);
692 psta->keep_alive_trycnt++;
693 if (ret == _SUCCESS) {
694 RTW_INFO(FUNC_ADPT_FMT" asoc check, "MAC_FMT" is alive\n"
695 , FUNC_ADPT_ARG(padapter), MAC_ARG(psta->cmn.mac_addr));
696 psta->expire_to = pstapriv->expire_to;
697 psta->keep_alive_trycnt = 0;
699 } else if (psta->keep_alive_trycnt <= 3) {
700 RTW_INFO(FUNC_ADPT_FMT" asoc check, "MAC_FMT" keep_alive_trycnt=%d\n"
701 , FUNC_ADPT_ARG(padapter) , MAC_ARG(psta->cmn.mac_addr), psta->keep_alive_trycnt);
706 #endif /* CONFIG_ACTIVE_KEEP_ALIVE_CHECK */
708 psta->keep_alive_trycnt = 0;
709 del_asoc_list[i] = chk_alive_list[i];
710 _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
711 if (rtw_is_list_empty(&psta->asoc_list) == _FALSE) {
712 rtw_list_delete(&psta->asoc_list);
713 pstapriv->asoc_list_cnt--;
714 STA_SET_MESH_PLINK(psta, NULL);
716 _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
720 for (i = 0; i < chk_alive_num; i++) {
721 u8 sta_addr[ETH_ALEN];
723 if (del_asoc_list[i] >= NUM_STA)
726 psta = rtw_get_stainfo_by_offset(pstapriv, del_asoc_list[i]);
727 _rtw_memcpy(sta_addr, psta->cmn.mac_addr, ETH_ALEN);
729 RTW_INFO(FUNC_ADPT_FMT" asoc expire "MAC_FMT", state=0x%x\n"
730 , FUNC_ADPT_ARG(padapter), MAC_ARG(psta->cmn.mac_addr), psta->state);
731 #ifdef CONFIG_ACTIVE_KEEP_ALIVE_CHECK
732 updated |= ap_free_sta(padapter, psta, _FALSE, WLAN_REASON_DEAUTH_LEAVING, _FALSE);
734 updated |= ap_free_sta(padapter, psta, _FALSE, WLAN_REASON_DEAUTH_LEAVING, _TRUE);
736 #ifdef CONFIG_RTW_MESH
737 if (MLME_IS_MESH(padapter))
738 rtw_mesh_expire_peer(padapter, sta_addr);
742 #ifdef CONFIG_ACTIVE_KEEP_ALIVE_CHECK
743 if (pmlmeext->active_keep_alive_check) {
744 /* back to the original operation channel */
745 if (switch_channel_by_drv == _TRUE && backup_ch > 0)
746 set_channel_bwmode(padapter, backup_ch, backup_offset, backup_bw);
751 #ifdef RTW_CONFIG_RFREG18_WA
752 rtw_check_restore_rf18(padapter);
754 associated_clients_update(padapter, updated, STA_INFO_UPDATE_ALL);
757 void rtw_ap_update_sta_ra_info(_adapter *padapter, struct sta_info *psta)
759 unsigned char sta_band = 0;
760 u64 tx_ra_bitmap = 0;
761 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
762 WLAN_BSSID_EX *pcur_network = (WLAN_BSSID_EX *)&pmlmepriv->cur_network.network;
767 if (!(psta->state & _FW_LINKED))
770 rtw_hal_update_sta_ra_info(padapter, psta);
771 tx_ra_bitmap = psta->cmn.ra_info.ramask;
773 if (pcur_network->Configuration.DSConfig > 14) {
775 if (tx_ra_bitmap & 0xffff000)
776 sta_band |= WIRELESS_11_5N;
778 if (tx_ra_bitmap & 0xff0)
779 sta_band |= WIRELESS_11A;
782 #ifdef CONFIG_80211AC_VHT
783 if (psta->vhtpriv.vht_option)
784 sta_band = WIRELESS_11_5AC;
787 if (tx_ra_bitmap & 0xffff000)
788 sta_band |= WIRELESS_11_24N;
790 if (tx_ra_bitmap & 0xff0)
791 sta_band |= WIRELESS_11G;
793 if (tx_ra_bitmap & 0x0f)
794 sta_band |= WIRELESS_11B;
797 psta->wireless_mode = sta_band;
798 rtw_hal_update_sta_wset(padapter, psta);
799 RTW_INFO("%s=> mac_id:%d , tx_ra_bitmap:0x%016llx, networkType:0x%02x\n",
800 __FUNCTION__, psta->cmn.mac_id, tx_ra_bitmap, psta->wireless_mode);
803 #ifdef CONFIG_BMC_TX_RATE_SELECT
804 u8 rtw_ap_find_mini_tx_rate(_adapter *adapter)
807 _list *phead, *plist;
808 u8 miini_tx_rate = ODM_RATEVHTSS4MCS9, sta_tx_rate;
809 struct sta_info *psta = NULL;
810 struct sta_priv *pstapriv = &adapter->stapriv;
812 _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
813 phead = &pstapriv->asoc_list;
814 plist = get_next(phead);
815 while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {
816 psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);
817 plist = get_next(plist);
819 sta_tx_rate = psta->cmn.ra_info.curr_tx_rate & 0x7F;
820 if (sta_tx_rate < miini_tx_rate)
821 miini_tx_rate = sta_tx_rate;
823 _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
825 return miini_tx_rate;
828 u8 rtw_ap_find_bmc_rate(_adapter *adapter, u8 tx_rate)
830 PHAL_DATA_TYPE hal_data = GET_HAL_DATA(adapter);
831 u8 tx_ini_rate = ODM_RATE6M;
834 case ODM_RATEVHTSS3MCS9:
835 case ODM_RATEVHTSS3MCS8:
836 case ODM_RATEVHTSS3MCS7:
837 case ODM_RATEVHTSS3MCS6:
838 case ODM_RATEVHTSS3MCS5:
839 case ODM_RATEVHTSS3MCS4:
840 case ODM_RATEVHTSS3MCS3:
841 case ODM_RATEVHTSS2MCS9:
842 case ODM_RATEVHTSS2MCS8:
843 case ODM_RATEVHTSS2MCS7:
844 case ODM_RATEVHTSS2MCS6:
845 case ODM_RATEVHTSS2MCS5:
846 case ODM_RATEVHTSS2MCS4:
847 case ODM_RATEVHTSS2MCS3:
848 case ODM_RATEVHTSS1MCS9:
849 case ODM_RATEVHTSS1MCS8:
850 case ODM_RATEVHTSS1MCS7:
851 case ODM_RATEVHTSS1MCS6:
852 case ODM_RATEVHTSS1MCS5:
853 case ODM_RATEVHTSS1MCS4:
854 case ODM_RATEVHTSS1MCS3:
869 tx_ini_rate = ODM_RATE24M;
871 case ODM_RATEVHTSS3MCS2:
872 case ODM_RATEVHTSS3MCS1:
873 case ODM_RATEVHTSS2MCS2:
874 case ODM_RATEVHTSS2MCS1:
875 case ODM_RATEVHTSS1MCS2:
876 case ODM_RATEVHTSS1MCS1:
883 tx_ini_rate = ODM_RATE12M;
885 case ODM_RATEVHTSS3MCS0:
886 case ODM_RATEVHTSS2MCS0:
887 case ODM_RATEVHTSS1MCS0:
892 tx_ini_rate = ODM_RATE6M;
898 tx_ini_rate = ODM_RATE1M;
901 tx_ini_rate = ODM_RATE6M;
905 if (hal_data->current_band_type == BAND_ON_5G)
906 if (tx_ini_rate < ODM_RATE6M)
907 tx_ini_rate = ODM_RATE6M;
912 void rtw_update_bmc_sta_tx_rate(_adapter *adapter)
914 struct sta_info *psta = NULL;
917 psta = rtw_get_bcmc_stainfo(adapter);
919 RTW_ERR(ADPT_FMT "could not get bmc_sta !!\n", ADPT_ARG(adapter));
923 if (adapter->bmc_tx_rate != MGN_UNKNOWN) {
924 psta->init_rate = adapter->bmc_tx_rate;
928 if (adapter->stapriv.asoc_sta_count <= 2)
931 tx_rate = rtw_ap_find_mini_tx_rate(adapter);
932 #ifdef CONFIG_BMC_TX_LOW_RATE
933 tx_rate = rtw_ap_find_bmc_rate(adapter, tx_rate);
936 psta->init_rate = hw_rate_to_m_rate(tx_rate);
939 RTW_INFO(ADPT_FMT" BMC Tx rate - %s\n", ADPT_ARG(adapter), MGN_RATE_STR(psta->init_rate));
943 void rtw_init_bmc_sta_tx_rate(_adapter *padapter, struct sta_info *psta)
945 #ifdef CONFIG_BMC_TX_LOW_RATE
946 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
949 u8 brate_table[] = {MGN_1M, MGN_2M, MGN_5_5M, MGN_11M,
950 MGN_6M, MGN_9M, MGN_12M, MGN_18M, MGN_24M, MGN_36M, MGN_48M, MGN_54M};
952 if (!MLME_IS_AP(padapter) && !MLME_IS_MESH(padapter))
955 if (padapter->bmc_tx_rate != MGN_UNKNOWN)
956 psta->init_rate = padapter->bmc_tx_rate;
958 #ifdef CONFIG_BMC_TX_LOW_RATE
959 if (IsEnableHWOFDM(pmlmeext->cur_wireless_mode) && (psta->cmn.ra_info.ramask && 0xFF0))
960 rate_idx = get_lowest_rate_idx_ex(psta->cmn.ra_info.ramask, 4); /*from basic rate*/
962 rate_idx = get_lowest_rate_idx(psta->cmn.ra_info.ramask); /*from basic rate*/
964 rate_idx = get_highest_rate_idx(psta->cmn.ra_info.ramask); /*from basic rate*/
967 psta->init_rate = brate_table[rate_idx];
969 psta->init_rate = MGN_1M;
972 RTW_INFO(ADPT_FMT" BMC Init Tx rate - %s\n", ADPT_ARG(padapter), MGN_RATE_STR(psta->init_rate));
975 void update_bmc_sta(_adapter *padapter)
978 unsigned char network_type;
979 int supportRateNum = 0;
980 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
981 WLAN_BSSID_EX *pcur_network = (WLAN_BSSID_EX *)&pmlmepriv->cur_network.network;
982 struct sta_info *psta = rtw_get_bcmc_stainfo(padapter);
985 psta->cmn.aid = 0;/* default set to 0 */
986 #ifdef CONFIG_RTW_MESH
987 if (MLME_IS_MESH(padapter))
988 psta->qos_option = 1;
991 psta->qos_option = 0;
992 #ifdef CONFIG_80211N_HT
993 psta->htpriv.ht_option = _FALSE;
994 #endif /* CONFIG_80211N_HT */
996 psta->ieee8021x_blocked = 0;
998 _rtw_memset((void *)&psta->sta_stats, 0, sizeof(struct stainfo_stats));
1000 /* psta->dot118021XPrivacy = _NO_PRIVACY_; */ /* !!! remove it, because it has been set before this. */
1002 supportRateNum = rtw_get_rateset_len((u8 *)&pcur_network->SupportedRates);
1003 network_type = rtw_check_network_type((u8 *)&pcur_network->SupportedRates, supportRateNum, pcur_network->Configuration.DSConfig);
1004 if (IsSupportedTxCCK(network_type))
1005 network_type = WIRELESS_11B;
1006 else if (network_type == WIRELESS_INVALID) { /* error handling */
1007 if (pcur_network->Configuration.DSConfig > 14)
1008 network_type = WIRELESS_11A;
1010 network_type = WIRELESS_11B;
1012 update_sta_basic_rate(psta, network_type);
1013 psta->wireless_mode = network_type;
1015 rtw_hal_update_sta_ra_info(padapter, psta);
1017 _enter_critical_bh(&psta->lock, &irqL);
1018 psta->state = _FW_LINKED;
1019 _exit_critical_bh(&psta->lock, &irqL);
1021 rtw_sta_media_status_rpt(padapter, psta, 1);
1022 rtw_init_bmc_sta_tx_rate(padapter, psta);
1025 RTW_INFO("add_RATid_bmc_sta error!\n");
1029 #if defined(CONFIG_80211N_HT) && defined(CONFIG_BEAMFORMING)
1030 void update_sta_info_apmode_ht_bf_cap(_adapter *padapter, struct sta_info *psta)
1032 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1033 struct ht_priv *phtpriv_ap = &pmlmepriv->htpriv;
1034 struct ht_priv *phtpriv_sta = &psta->htpriv;
1036 u8 cur_beamform_cap = 0;
1038 /*Config Tx beamforming setting*/
1039 if (TEST_FLAG(phtpriv_ap->beamform_cap, BEAMFORMING_HT_BEAMFORMEE_ENABLE) &&
1040 GET_HT_CAP_TXBF_EXPLICIT_COMP_STEERING_CAP((u8 *)(&phtpriv_sta->ht_cap))) {
1041 SET_FLAG(cur_beamform_cap, BEAMFORMING_HT_BEAMFORMER_ENABLE);
1042 /*Shift to BEAMFORMING_HT_BEAMFORMEE_CHNL_EST_CAP*/
1043 SET_FLAG(cur_beamform_cap, GET_HT_CAP_TXBF_CHNL_ESTIMATION_NUM_ANTENNAS((u8 *)(&phtpriv_sta->ht_cap)) << 6);
1046 if (TEST_FLAG(phtpriv_ap->beamform_cap, BEAMFORMING_HT_BEAMFORMER_ENABLE) &&
1047 GET_HT_CAP_TXBF_EXPLICIT_COMP_FEEDBACK_CAP((u8 *)(&phtpriv_sta->ht_cap))) {
1048 SET_FLAG(cur_beamform_cap, BEAMFORMING_HT_BEAMFORMEE_ENABLE);
1049 /*Shift to BEAMFORMING_HT_BEAMFORMER_STEER_NUM*/
1050 SET_FLAG(cur_beamform_cap, GET_HT_CAP_TXBF_COMP_STEERING_NUM_ANTENNAS((u8 *)(&phtpriv_sta->ht_cap)) << 4);
1052 if (cur_beamform_cap)
1053 RTW_INFO("Client STA(%d) HT Beamforming Cap = 0x%02X\n", psta->cmn.aid, cur_beamform_cap);
1055 phtpriv_sta->beamform_cap = cur_beamform_cap;
1056 psta->cmn.bf_info.ht_beamform_cap = cur_beamform_cap;
1059 #endif /*CONFIG_80211N_HT && CONFIG_BEAMFORMING*/
1062 * AID: 1~MAX for sta and 0 for bc/mc in ap/adhoc mode */
1063 void update_sta_info_apmode(_adapter *padapter, struct sta_info *psta)
1066 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1067 struct security_priv *psecuritypriv = &padapter->securitypriv;
1068 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
1069 #ifdef CONFIG_80211N_HT
1070 struct ht_priv *phtpriv_ap = &pmlmepriv->htpriv;
1071 struct ht_priv *phtpriv_sta = &psta->htpriv;
1072 #endif /* CONFIG_80211N_HT */
1073 u8 cur_ldpc_cap = 0, cur_stbc_cap = 0;
1074 /* set intf_tag to if1 */
1075 /* psta->intf_tag = 0; */
1077 RTW_INFO("%s\n", __FUNCTION__);
1079 /*alloc macid when call rtw_alloc_stainfo(),release macid when call rtw_free_stainfo()*/
1081 if (!MLME_IS_MESH(padapter) && psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X)
1082 psta->ieee8021x_blocked = _TRUE;
1084 psta->ieee8021x_blocked = _FALSE;
1087 /* update sta's cap */
1090 VCS_update(padapter, psta);
1091 #ifdef CONFIG_80211N_HT
1092 /* HT related cap */
1093 if (phtpriv_sta->ht_option) {
1094 /* check if sta supports rx ampdu */
1095 phtpriv_sta->ampdu_enable = phtpriv_ap->ampdu_enable;
1097 phtpriv_sta->rx_ampdu_min_spacing = (phtpriv_sta->ht_cap.ampdu_params_info & IEEE80211_HT_CAP_AMPDU_DENSITY) >> 2;
1100 if ((phtpriv_sta->ht_cap.cap_info & phtpriv_ap->ht_cap.cap_info) & cpu_to_le16(IEEE80211_HT_CAP_SUP_WIDTH))
1101 psta->cmn.bw_mode = CHANNEL_WIDTH_40;
1103 psta->cmn.bw_mode = CHANNEL_WIDTH_20;
1105 if (phtpriv_sta->op_present
1106 && !GET_HT_OP_ELE_STA_CHL_WIDTH(phtpriv_sta->ht_op))
1107 psta->cmn.bw_mode = CHANNEL_WIDTH_20;
1109 if (psta->ht_40mhz_intolerant)
1110 psta->cmn.bw_mode = CHANNEL_WIDTH_20;
1112 if (pmlmeext->cur_bwmode < psta->cmn.bw_mode)
1113 psta->cmn.bw_mode = pmlmeext->cur_bwmode;
1115 phtpriv_sta->ch_offset = pmlmeext->cur_ch_offset;
1118 /* check if sta support s Short GI 20M */
1119 if ((phtpriv_sta->ht_cap.cap_info & phtpriv_ap->ht_cap.cap_info) & cpu_to_le16(IEEE80211_HT_CAP_SGI_20))
1120 phtpriv_sta->sgi_20m = _TRUE;
1122 /* check if sta support s Short GI 40M */
1123 if ((phtpriv_sta->ht_cap.cap_info & phtpriv_ap->ht_cap.cap_info) & cpu_to_le16(IEEE80211_HT_CAP_SGI_40)) {
1124 if (psta->cmn.bw_mode == CHANNEL_WIDTH_40) /* according to psta->bw_mode */
1125 phtpriv_sta->sgi_40m = _TRUE;
1127 phtpriv_sta->sgi_40m = _FALSE;
1130 psta->qos_option = _TRUE;
1132 /* B0 Config LDPC Coding Capability */
1133 if (TEST_FLAG(phtpriv_ap->ldpc_cap, LDPC_HT_ENABLE_TX) &&
1134 GET_HT_CAP_ELE_LDPC_CAP((u8 *)(&phtpriv_sta->ht_cap))) {
1135 SET_FLAG(cur_ldpc_cap, (LDPC_HT_ENABLE_TX | LDPC_HT_CAP_TX));
1136 RTW_INFO("Enable HT Tx LDPC for STA(%d)\n", psta->cmn.aid);
1139 /* B7 B8 B9 Config STBC setting */
1140 if (TEST_FLAG(phtpriv_ap->stbc_cap, STBC_HT_ENABLE_TX) &&
1141 GET_HT_CAP_ELE_RX_STBC((u8 *)(&phtpriv_sta->ht_cap))) {
1142 SET_FLAG(cur_stbc_cap, (STBC_HT_ENABLE_TX | STBC_HT_CAP_TX));
1143 RTW_INFO("Enable HT Tx STBC for STA(%d)\n", psta->cmn.aid);
1146 #ifdef CONFIG_BEAMFORMING
1147 update_sta_info_apmode_ht_bf_cap(padapter, psta);
1150 phtpriv_sta->ampdu_enable = _FALSE;
1152 phtpriv_sta->sgi_20m = _FALSE;
1153 phtpriv_sta->sgi_40m = _FALSE;
1154 psta->cmn.bw_mode = CHANNEL_WIDTH_20;
1155 phtpriv_sta->ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
1158 phtpriv_sta->ldpc_cap = cur_ldpc_cap;
1159 phtpriv_sta->stbc_cap = cur_stbc_cap;
1162 send_delba(padapter, 0, psta->cmn.mac_addr);/* recipient */
1165 send_delba(padapter, 1, psta->cmn.mac_addr);/* */ /* originator */
1166 phtpriv_sta->agg_enable_bitmap = 0x0;/* reset */
1167 phtpriv_sta->candidate_tid_bitmap = 0x0;/* reset */
1168 #endif /* CONFIG_80211N_HT */
1170 #ifdef CONFIG_80211AC_VHT
1171 update_sta_vht_info_apmode(padapter, psta);
1173 psta->cmn.ra_info.is_support_sgi = query_ra_short_GI(psta, rtw_get_tx_bw_mode(padapter, psta));
1174 update_ldpc_stbc_cap(psta);
1176 /* todo: init other variables */
1178 _rtw_memset((void *)&psta->sta_stats, 0, sizeof(struct stainfo_stats));
1182 /* add_RATid(padapter, psta); */ /* move to ap_sta_info_defer_update() */
1185 rtw_hal_set_odm_var(padapter, HAL_ODM_STA_INFO, psta, _TRUE);
1187 _enter_critical_bh(&psta->lock, &irqL);
1189 /* Check encryption */
1190 if (!MLME_IS_MESH(padapter) && psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X)
1191 psta->state |= WIFI_UNDER_KEY_HANDSHAKE;
1193 psta->state |= _FW_LINKED;
1195 _exit_critical_bh(&psta->lock, &irqL);
1198 static void update_ap_info(_adapter *padapter, struct sta_info *psta)
1200 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1201 WLAN_BSSID_EX *pnetwork = (WLAN_BSSID_EX *)&pmlmepriv->cur_network.network;
1202 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
1203 #ifdef CONFIG_80211N_HT
1204 struct ht_priv *phtpriv_ap = &pmlmepriv->htpriv;
1205 #endif /* CONFIG_80211N_HT */
1207 psta->wireless_mode = pmlmeext->cur_wireless_mode;
1209 psta->bssratelen = rtw_get_rateset_len(pnetwork->SupportedRates);
1210 _rtw_memcpy(psta->bssrateset, pnetwork->SupportedRates, psta->bssratelen);
1212 #ifdef CONFIG_80211N_HT
1213 /* HT related cap */
1214 if (phtpriv_ap->ht_option) {
1215 /* check if sta supports rx ampdu */
1216 /* phtpriv_ap->ampdu_enable = phtpriv_ap->ampdu_enable; */
1218 /* check if sta support s Short GI 20M */
1219 if ((phtpriv_ap->ht_cap.cap_info) & cpu_to_le16(IEEE80211_HT_CAP_SGI_20))
1220 phtpriv_ap->sgi_20m = _TRUE;
1221 /* check if sta support s Short GI 40M */
1222 if ((phtpriv_ap->ht_cap.cap_info) & cpu_to_le16(IEEE80211_HT_CAP_SGI_40))
1223 phtpriv_ap->sgi_40m = _TRUE;
1225 psta->qos_option = _TRUE;
1227 phtpriv_ap->ampdu_enable = _FALSE;
1229 phtpriv_ap->sgi_20m = _FALSE;
1230 phtpriv_ap->sgi_40m = _FALSE;
1233 psta->cmn.bw_mode = pmlmeext->cur_bwmode;
1234 phtpriv_ap->ch_offset = pmlmeext->cur_ch_offset;
1236 phtpriv_ap->agg_enable_bitmap = 0x0;/* reset */
1237 phtpriv_ap->candidate_tid_bitmap = 0x0;/* reset */
1239 _rtw_memcpy(&psta->htpriv, &pmlmepriv->htpriv, sizeof(struct ht_priv));
1241 #ifdef CONFIG_80211AC_VHT
1242 _rtw_memcpy(&psta->vhtpriv, &pmlmepriv->vhtpriv, sizeof(struct vht_priv));
1243 #endif /* CONFIG_80211AC_VHT */
1245 #endif /* CONFIG_80211N_HT */
1247 psta->state |= WIFI_AP_STATE; /* Aries, add,fix bug of flush_cam_entry at STOP AP mode , 0724 */
1250 static void rtw_set_hw_wmm_param(_adapter *padapter)
1252 u8 AIFS, ECWMin, ECWMax, aSifsTime;
1256 u32 edca[4], inx[4];
1257 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1258 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
1259 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
1260 struct registry_priv *pregpriv = &padapter->registrypriv;
1263 #ifdef CONFIG_80211N_HT
1264 if (pregpriv->ht_enable &&
1265 (is_supported_5g(pmlmeext->cur_wireless_mode) ||
1266 (pmlmeext->cur_wireless_mode & WIRELESS_11_24N)))
1269 #endif /* CONFIG_80211N_HT */
1272 if (pmlmeinfo->WMM_enable == 0) {
1273 padapter->mlmepriv.acm_mask = 0;
1275 AIFS = aSifsTime + (2 * pmlmeinfo->slotTime);
1277 if (pmlmeext->cur_wireless_mode & (WIRELESS_11G | WIRELESS_11A)) {
1280 } else if (pmlmeext->cur_wireless_mode & WIRELESS_11B) {
1289 acParm = AIFS | (ECWMin << 8) | (ECWMax << 12) | (TXOP << 16);
1290 rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BE, (u8 *)(&acParm));
1291 rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BK, (u8 *)(&acParm));
1292 rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VI, (u8 *)(&acParm));
1297 acParm = AIFS | (ECWMin << 8) | (ECWMax << 12) | (TXOP << 16);
1298 rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VO, (u8 *)(&acParm));
1301 edca[0] = edca[1] = edca[2] = edca[3] = 0;
1305 padapter->mlmepriv.acm_mask = acm_mask;
1309 /* AIFS = AIFSN * slot time + SIFS - r2t phy delay */
1311 AIFS = (7 * pmlmeinfo->slotTime) + aSifsTime;
1315 acParm = AIFS | (ECWMin << 8) | (ECWMax << 12) | (TXOP << 16);
1316 rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BK, (u8 *)(&acParm));
1317 edca[XMIT_BK_QUEUE] = acParm;
1318 RTW_INFO("WMM(BK): %x\n", acParm);
1321 AIFS = (3 * pmlmeinfo->slotTime) + aSifsTime;
1325 acParm = AIFS | (ECWMin << 8) | (ECWMax << 12) | (TXOP << 16);
1326 rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BE, (u8 *)(&acParm));
1327 edca[XMIT_BE_QUEUE] = acParm;
1328 RTW_INFO("WMM(BE): %x\n", acParm);
1331 AIFS = (1 * pmlmeinfo->slotTime) + aSifsTime;
1335 acParm = AIFS | (ECWMin << 8) | (ECWMax << 12) | (TXOP << 16);
1336 rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VI, (u8 *)(&acParm));
1337 edca[XMIT_VI_QUEUE] = acParm;
1338 RTW_INFO("WMM(VI): %x\n", acParm);
1341 AIFS = (1 * pmlmeinfo->slotTime) + aSifsTime;
1345 acParm = AIFS | (ECWMin << 8) | (ECWMax << 12) | (TXOP << 16);
1346 rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VO, (u8 *)(&acParm));
1347 edca[XMIT_VO_QUEUE] = acParm;
1348 RTW_INFO("WMM(VO): %x\n", acParm);
1351 if (padapter->registrypriv.acm_method == 1)
1352 rtw_hal_set_hwreg(padapter, HW_VAR_ACM_CTRL, (u8 *)(&acm_mask));
1354 padapter->mlmepriv.acm_mask = acm_mask;
1361 if (pregpriv->wifi_spec == 1) {
1362 u32 j, tmp, change_inx = _FALSE;
1364 /* entry indx: 0->vo, 1->vi, 2->be, 3->bk. */
1365 for (i = 0 ; i < 4 ; i++) {
1366 for (j = i + 1 ; j < 4 ; j++) {
1367 /* compare CW and AIFS */
1368 if ((edca[j] & 0xFFFF) < (edca[i] & 0xFFFF))
1370 else if ((edca[j] & 0xFFFF) == (edca[i] & 0xFFFF)) {
1372 if ((edca[j] >> 16) > (edca[i] >> 16))
1385 change_inx = _FALSE;
1391 for (i = 0 ; i < 4 ; i++) {
1392 pxmitpriv->wmm_para_seq[i] = inx[i];
1393 RTW_INFO("wmm_para_seq(%d): %d\n", i, pxmitpriv->wmm_para_seq[i]);
1399 #ifdef CONFIG_80211N_HT
1400 static void update_hw_ht_param(_adapter *padapter)
1402 unsigned char max_AMPDU_len;
1403 unsigned char min_MPDU_spacing;
1404 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1405 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
1407 RTW_INFO("%s\n", __FUNCTION__);
1410 /* handle A-MPDU parameter field */
1412 AMPDU_para [1:0]:Max AMPDU Len => 0:8k , 1:16k, 2:32k, 3:64k
1413 AMPDU_para [4:2]:Min MPDU Start Spacing
1415 max_AMPDU_len = pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x03;
1417 min_MPDU_spacing = (pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x1c) >> 2;
1419 rtw_hal_set_hwreg(padapter, HW_VAR_AMPDU_MIN_SPACE, (u8 *)(&min_MPDU_spacing));
1421 rtw_hal_set_hwreg(padapter, HW_VAR_AMPDU_FACTOR, (u8 *)(&max_AMPDU_len));
1424 /* Config SM Power Save setting */
1426 pmlmeinfo->SM_PS = (pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info & 0x0C) >> 2;
1427 if (pmlmeinfo->SM_PS == WLAN_HT_CAP_SM_PS_STATIC) {
1430 /* update the MCS rates */
1431 for (i = 0; i < 16; i++)
1432 pmlmeinfo->HT_caps.HT_cap_element.MCS_rate[i] &= MCS_rate_1R[i];
1434 RTW_INFO("%s(): WLAN_HT_CAP_SM_PS_STATIC\n", __FUNCTION__);
1438 /* Config current HT Protection mode. */
1440 /* pmlmeinfo->HT_protection = pmlmeinfo->HT_info.infos[1] & 0x3; */
1443 #endif /* CONFIG_80211N_HT */
1444 static void rtw_ap_check_scan(_adapter *padapter)
1447 _list *plist, *phead;
1448 u32 delta_time, lifetime;
1449 struct wlan_network *pnetwork = NULL;
1450 WLAN_BSSID_EX *pbss = NULL;
1451 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1452 _queue *queue = &(pmlmepriv->scanned_queue);
1453 u8 do_scan = _FALSE;
1454 u8 reason = RTW_AUTO_SCAN_REASON_UNSPECIFIED;
1456 lifetime = SCANQUEUE_LIFETIME; /* 20 sec */
1458 _enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
1459 phead = get_list_head(queue);
1460 if (rtw_end_of_queue_search(phead, get_next(phead)) == _TRUE)
1461 if (padapter->registrypriv.wifi_spec) {
1463 reason |= RTW_AUTO_SCAN_REASON_2040_BSS;
1465 _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
1467 #ifdef CONFIG_RTW_ACS
1468 if (padapter->registrypriv.acs_auto_scan) {
1470 reason |= RTW_AUTO_SCAN_REASON_ACS;
1471 rtw_acs_start(padapter);
1473 #endif/*CONFIG_RTW_ACS*/
1475 if (_TRUE == do_scan) {
1476 RTW_INFO("%s : drv scans by itself and wait_completed\n", __func__);
1477 rtw_drv_scan_by_self(padapter, reason);
1478 rtw_scan_wait_completed(padapter);
1481 #ifdef CONFIG_RTW_ACS
1482 if (padapter->registrypriv.acs_auto_scan)
1483 rtw_acs_stop(padapter);
1486 _enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
1488 phead = get_list_head(queue);
1489 plist = get_next(phead);
1493 if (rtw_end_of_queue_search(phead, plist) == _TRUE)
1496 pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
1498 if (rtw_chset_search_ch(adapter_to_chset(padapter), pnetwork->network.Configuration.DSConfig) >= 0
1499 && rtw_mlme_band_check(padapter, pnetwork->network.Configuration.DSConfig) == _TRUE
1500 && _TRUE == rtw_validate_ssid(&(pnetwork->network.Ssid))) {
1501 delta_time = (u32) rtw_get_passing_time_ms(pnetwork->last_scanned);
1503 if (delta_time < lifetime) {
1509 pbss = &pnetwork->network;
1512 /*check if HT CAP INFO IE exists or not*/
1513 pbuf = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_CAPABILITY_IE_, &ie_len, (pbss->IELength - _BEACON_IE_OFFSET_));
1515 /* HT CAP INFO IE don't exist, it is b/g mode bss.*/
1517 if (_FALSE == ATOMIC_READ(&pmlmepriv->olbc))
1518 ATOMIC_SET(&pmlmepriv->olbc, _TRUE);
1520 if (_FALSE == ATOMIC_READ(&pmlmepriv->olbc_ht))
1521 ATOMIC_SET(&pmlmepriv->olbc_ht, _TRUE);
1523 if (padapter->registrypriv.wifi_spec)
1524 RTW_INFO("%s: %s is a/b/g ap\n", __func__, pnetwork->network.Ssid.Ssid);
1529 plist = get_next(plist);
1533 _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
1534 #ifdef CONFIG_80211N_HT
1535 pmlmepriv->num_sta_no_ht = 0; /* reset to 0 after ap do scanning*/
1539 void rtw_start_bss_hdl_after_chbw_decided(_adapter *adapter)
1541 WLAN_BSSID_EX *pnetwork = &(adapter->mlmepriv.cur_network.network);
1542 struct sta_info *sta = NULL;
1544 /* update cur_wireless_mode */
1545 update_wireless_mode(adapter);
1547 /* update RRSR and RTS_INIT_RATE register after set channel and bandwidth */
1548 UpdateBrateTbl(adapter, pnetwork->SupportedRates);
1549 rtw_hal_set_hwreg(adapter, HW_VAR_BASIC_RATE, pnetwork->SupportedRates);
1551 /* update capability after cur_wireless_mode updated */
1552 update_capinfo(adapter, rtw_get_capability(pnetwork));
1554 /* update bc/mc sta_info */
1555 update_bmc_sta(adapter);
1557 /* update AP's sta info */
1558 sta = rtw_get_stainfo(&adapter->stapriv, pnetwork->MacAddress);
1560 RTW_INFO(FUNC_ADPT_FMT" !sta for macaddr="MAC_FMT"\n", FUNC_ADPT_ARG(adapter), MAC_ARG(pnetwork->MacAddress));
1565 update_ap_info(adapter, sta);
1568 #ifdef CONFIG_FW_HANDLE_TXBCN
1569 bool rtw_ap_nums_check(_adapter *adapter)
1571 if (rtw_ap_get_nums(adapter) < CONFIG_LIMITED_AP_NUM)
1575 u8 rtw_ap_allocate_vapid(struct dvobj_priv *dvobj)
1579 for (vap_id = 0; vap_id < CONFIG_LIMITED_AP_NUM; vap_id++) {
1580 if (!(dvobj->vap_map & BIT(vap_id)))
1584 if (vap_id < CONFIG_LIMITED_AP_NUM)
1585 dvobj->vap_map |= BIT(vap_id);
1589 u8 rtw_ap_release_vapid(struct dvobj_priv *dvobj, u8 vap_id)
1591 if (vap_id >= CONFIG_LIMITED_AP_NUM) {
1592 RTW_ERR("%s - vapid(%d) failed\n", __func__, vap_id);
1596 dvobj->vap_map &= ~ BIT(vap_id);
1600 static void _rtw_iface_undersurvey_chk(const char *func, _adapter *adapter)
1604 struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
1605 struct mlme_priv *pmlmepriv;
1607 for (i = 0; i < dvobj->iface_nums; i++) {
1608 iface = dvobj->padapters[i];
1609 if ((iface) && rtw_is_adapter_up(iface)) {
1610 pmlmepriv = &iface->mlmepriv;
1611 if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY))
1612 RTW_ERR("%s ("ADPT_FMT") under survey\n", func, ADPT_ARG(iface));
1616 void start_bss_network(_adapter *padapter, struct createbss_parm *parm)
1618 #define DUMP_ADAPTERS_STATUS 0
1619 u8 mlme_act = MLME_ACTION_UNKNOWN;
1623 struct registry_priv *pregpriv = &padapter->registrypriv;
1624 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1625 struct security_priv *psecuritypriv = &(padapter->securitypriv);
1626 WLAN_BSSID_EX *pnetwork = (WLAN_BSSID_EX *)&pmlmepriv->cur_network.network; /* used as input */
1627 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
1628 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
1629 WLAN_BSSID_EX *pnetwork_mlmeext = &(pmlmeinfo->network);
1630 struct dvobj_priv *pdvobj = padapter->dvobj;
1631 s16 req_ch = REQ_CH_NONE, req_bw = REQ_BW_NONE, req_offset = REQ_OFFSET_NONE;
1632 u8 ch_to_set = 0, bw_to_set, offset_to_set;
1634 /* use for check ch bw offset can be allowed or not */
1635 u8 chbw_allow = _TRUE;
1637 u8 ifbmp_ch_changed = 0;
1639 if (parm->req_ch != 0) {
1640 /* bypass other setting, go checking ch, bw, offset */
1641 mlme_act = MLME_OPCH_SWITCH;
1642 req_ch = parm->req_ch;
1643 req_bw = parm->req_bw;
1644 req_offset = parm->req_offset;
1647 /* request comes from upper layer */
1648 if (MLME_IS_AP(padapter))
1649 mlme_act = MLME_AP_STARTED;
1650 else if (MLME_IS_MESH(padapter))
1651 mlme_act = MLME_MESH_STARTED;
1655 _rtw_memcpy(pnetwork_mlmeext, pnetwork, pnetwork->Length);
1658 bcn_interval = (u16)pnetwork->Configuration.BeaconPeriod;
1660 /* check if there is wps ie, */
1661 /* if there is wpsie in beacon, the hostapd will update beacon twice when stating hostapd, */
1662 /* and at first time the security ie ( RSN/WPA IE) will not include in beacon. */
1663 if (NULL == rtw_get_wps_ie(pnetwork->IEs + _FIXED_IE_LENGTH_, pnetwork->IELength - _FIXED_IE_LENGTH_, NULL, NULL))
1664 pmlmeext->bstart_bss = _TRUE;
1666 /* todo: update wmm, ht cap */
1667 /* pmlmeinfo->WMM_enable; */
1668 /* pmlmeinfo->HT_enable; */
1669 if (pmlmepriv->qospriv.qos_option)
1670 pmlmeinfo->WMM_enable = _TRUE;
1671 #ifdef CONFIG_80211N_HT
1672 if (pmlmepriv->htpriv.ht_option) {
1673 pmlmeinfo->WMM_enable = _TRUE;
1674 pmlmeinfo->HT_enable = _TRUE;
1675 /* pmlmeinfo->HT_info_enable = _TRUE; */
1676 /* pmlmeinfo->HT_caps_enable = _TRUE; */
1678 update_hw_ht_param(padapter);
1680 #endif /* #CONFIG_80211N_HT */
1682 #ifdef CONFIG_80211AC_VHT
1683 if (pmlmepriv->vhtpriv.vht_option) {
1684 pmlmeinfo->VHT_enable = _TRUE;
1685 update_hw_vht_param(padapter);
1687 #endif /* CONFIG_80211AC_VHT */
1689 if (pmlmepriv->cur_network.join_res != _TRUE) { /* setting only at first time */
1690 /* WEP Key will be set before this function, do not clear CAM. */
1691 if ((psecuritypriv->dot11PrivacyAlgrthm != _WEP40_) && (psecuritypriv->dot11PrivacyAlgrthm != _WEP104_)
1692 && !MLME_IS_MESH(padapter) /* mesh group key is set before this function */
1694 flush_all_cam_entry(padapter); /* clear CAM */
1697 /* set MSR to AP_Mode */
1698 Set_MSR(padapter, _HW_STATE_AP_);
1701 rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, pnetwork->MacAddress);
1704 val8 = (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) ? 0xcc : 0xcf;
1705 rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8));
1707 /* Beacon Control related register */
1708 rtw_hal_set_hwreg(padapter, HW_VAR_BEACON_INTERVAL, (u8 *)(&bcn_interval));
1710 rtw_hal_rcr_set_chk_bssid(padapter, mlme_act);
1713 ifbmp_ch_changed = rtw_ap_chbw_decision(padapter, parm->ifbmp, parm->excl_ifbmp
1714 , req_ch, req_bw, req_offset
1715 , &ch_to_set, &bw_to_set, &offset_to_set, &chbw_allow);
1717 for (i = 0; i < pdvobj->iface_nums; i++) {
1718 if (!(parm->ifbmp & BIT(i)) || !pdvobj->padapters[i])
1721 /* let pnetwork_mlme == pnetwork_mlmeext */
1722 _rtw_memcpy(&(pdvobj->padapters[i]->mlmepriv.cur_network.network)
1723 , &(pdvobj->padapters[i]->mlmeextpriv.mlmext_info.network)
1724 , pdvobj->padapters[i]->mlmeextpriv.mlmext_info.network.Length);
1726 rtw_start_bss_hdl_after_chbw_decided(pdvobj->padapters[i]);
1728 /* Set EDCA param reg after update cur_wireless_mode & update_capinfo */
1729 if (pregpriv->wifi_spec == 1)
1730 rtw_set_hw_wmm_param(pdvobj->padapters[i]);
1733 #if defined(CONFIG_DFS_MASTER)
1734 rtw_dfs_rd_en_decision(padapter, mlme_act, parm->excl_ifbmp);
1737 #ifdef CONFIG_MCC_MODE
1738 if (MCC_EN(padapter)) {
1740 * due to check under rtw_ap_chbw_decision
1741 * if under MCC mode, means req channel setting is the same as current channel setting
1742 * if not under MCC mode, mean req channel setting is not the same as current channel setting
1744 if (rtw_hal_check_mcc_status(padapter, MCC_STATUS_DOING_MCC)) {
1745 RTW_INFO(FUNC_ADPT_FMT": req channel setting is the same as current channel setting, go to update BCN\n"
1746 , FUNC_ADPT_ARG(padapter));
1753 /* issue null data to AP for all interface connecting to AP before switch channel setting for softap */
1754 rtw_hal_mcc_issue_null_data(padapter, chbw_allow, 1);
1755 #endif /* CONFIG_MCC_MODE */
1757 if (!IS_CH_WAITING(adapter_to_rfctl(padapter))) {
1759 rtw_hal_set_hwreg(padapter , HW_VAR_DO_IQK , &doiqk);
1762 if (ch_to_set != 0) {
1763 set_channel_bwmode(padapter, ch_to_set, offset_to_set, bw_to_set);
1764 rtw_mi_update_union_chan_inf(padapter, ch_to_set, offset_to_set, bw_to_set);
1768 rtw_hal_set_hwreg(padapter , HW_VAR_DO_IQK , &doiqk);
1770 #ifdef CONFIG_MCC_MODE
1771 /* after set_channel_bwmode for backup IQK */
1772 rtw_hal_set_mcc_setting_start_bss_network(padapter, chbw_allow);
1775 #if defined(CONFIG_IOCTL_CFG80211) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
1776 for (i = 0; i < pdvobj->iface_nums; i++) {
1777 if (!(ifbmp_ch_changed & BIT(i)) || !pdvobj->padapters[i])
1780 /* pure AP is not needed*/
1781 if (MLME_IS_GO(pdvobj->padapters[i])
1782 || MLME_IS_MESH(pdvobj->padapters[i])
1786 #ifdef CONFIG_80211N_HT
1787 ht_option = pdvobj->padapters[i]->mlmepriv.htpriv.ht_option;
1790 rtw_cfg80211_ch_switch_notify(pdvobj->padapters[i]
1791 , pdvobj->padapters[i]->mlmeextpriv.cur_channel
1792 , pdvobj->padapters[i]->mlmeextpriv.cur_bwmode
1793 , pdvobj->padapters[i]->mlmeextpriv.cur_ch_offset
1797 #endif /* defined(CONFIG_IOCTL_CFG80211) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)) */
1799 if (DUMP_ADAPTERS_STATUS) {
1800 RTW_INFO(FUNC_ADPT_FMT" done\n", FUNC_ADPT_ARG(padapter));
1801 dump_adapters_status(RTW_DBGDUMP , adapter_to_dvobj(padapter));
1804 #ifdef CONFIG_MCC_MODE
1808 for (i = 0; i < pdvobj->iface_nums; i++) {
1809 struct mlme_priv *mlme;
1811 if (!(parm->ifbmp & BIT(i)) || !pdvobj->padapters[i])
1814 /* update beacon content only if bstart_bss is _TRUE */
1815 if (pdvobj->padapters[i]->mlmeextpriv.bstart_bss != _TRUE)
1818 mlme = &(pdvobj->padapters[i]->mlmepriv);
1820 #ifdef CONFIG_80211N_HT
1821 if ((ATOMIC_READ(&mlme->olbc) == _TRUE) || (ATOMIC_READ(&mlme->olbc_ht) == _TRUE)) {
1822 /* AP is not starting a 40 MHz BSS in presence of an 802.11g BSS. */
1823 mlme->ht_op_mode &= (~HT_INFO_OPERATION_MODE_OP_MODE_MASK);
1824 mlme->ht_op_mode |= OP_MODE_MAY_BE_LEGACY_STAS;
1825 update_beacon(pdvobj->padapters[i], _HT_ADD_INFO_IE_, NULL, _FALSE);
1829 update_beacon(pdvobj->padapters[i], _TIM_IE_, NULL, _FALSE);
1832 if (mlme_act != MLME_OPCH_SWITCH
1833 && pmlmeext->bstart_bss == _TRUE
1835 #ifdef CONFIG_SUPPORT_MULTI_BCN
1838 _enter_critical_bh(&pdvobj->ap_if_q.lock, &irqL);
1839 if (rtw_is_list_empty(&padapter->list)) {
1840 #ifdef CONFIG_FW_HANDLE_TXBCN
1841 padapter->vap_id = rtw_ap_allocate_vapid(pdvobj);
1843 rtw_list_insert_tail(&padapter->list, get_list_head(&pdvobj->ap_if_q));
1845 pdvobj->inter_bcn_space = DEFAULT_BCN_INTERVAL / pdvobj->nr_ap_if;
1847 _exit_critical_bh(&pdvobj->ap_if_q.lock, &irqL);
1849 #ifdef CONFIG_SWTIMER_BASED_TXBCN
1850 rtw_ap_set_mbid_num(padapter, pdvobj->nr_ap_if);
1851 rtw_hal_set_hwreg(padapter, HW_VAR_BEACON_INTERVAL, (u8 *)(&pdvobj->inter_bcn_space));
1852 #endif /*CONFIG_SWTIMER_BASED_TXBCN*/
1854 #endif /*CONFIG_SUPPORT_MULTI_BCN*/
1856 #ifdef CONFIG_HW_P0_TSF_SYNC
1857 correct_TSF(padapter, mlme_act);
1861 rtw_scan_wait_completed(padapter);
1863 _rtw_iface_undersurvey_chk(__func__, padapter);
1865 ResumeTxBeacon(padapter);
1867 #if !defined(CONFIG_INTERRUPT_BASED_TXBCN)
1868 #if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI) || defined(CONFIG_PCI_BCN_POLLING)
1869 #ifdef CONFIG_SWTIMER_BASED_TXBCN
1870 if (pdvobj->nr_ap_if == 1
1871 && mlme_act != MLME_OPCH_SWITCH
1873 RTW_INFO("start SW BCN TIMER!\n");
1874 _set_timer(&pdvobj->txbcn_timer, bcn_interval);
1877 for (i = 0; i < pdvobj->iface_nums; i++) {
1878 if (!(parm->ifbmp & BIT(i)) || !pdvobj->padapters[i])
1881 if (send_beacon(pdvobj->padapters[i]) == _FAIL)
1882 RTW_INFO(ADPT_FMT" issue_beacon, fail!\n", ADPT_ARG(pdvobj->padapters[i]));
1886 #endif /* !defined(CONFIG_INTERRUPT_BASED_TXBCN) */
1888 #ifdef CONFIG_FW_HANDLE_TXBCN
1889 if (mlme_act != MLME_OPCH_SWITCH)
1890 rtw_ap_mbid_bcn_en(padapter, padapter->vap_id);
1895 int rtw_check_beacon_data(_adapter *padapter, u8 *pbuf, int len)
1899 u8 *pHT_caps_ie = NULL;
1900 u8 *pHT_info_ie = NULL;
1901 u16 cap, ht_cap = _FALSE;
1903 int group_cipher, pairwise_cipher;
1905 u8 mfp_opt = MFP_NO;
1906 u8 channel, network_type, supportRate[NDIS_802_11_LENGTH_RATES_EX];
1907 int supportRateNum = 0;
1908 u8 OUI1[] = {0x00, 0x50, 0xf2, 0x01};
1909 u8 WMM_PARA_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01};
1910 HT_CAP_AMPDU_DENSITY best_ampdu_density;
1911 struct registry_priv *pregistrypriv = &padapter->registrypriv;
1912 struct security_priv *psecuritypriv = &padapter->securitypriv;
1913 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1914 WLAN_BSSID_EX *pbss_network = (WLAN_BSSID_EX *)&pmlmepriv->cur_network.network;
1915 u8 *ie = pbss_network->IEs;
1916 u8 vht_cap = _FALSE;
1917 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
1918 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
1919 struct rf_ctl_t *rfctl = adapter_to_rfctl(padapter);
1923 /* Supported rates */
1925 /* WLAN_EID_COUNTRY */
1926 /* ERP Information element */
1927 /* Extended supported rates */
1929 /* Wi-Fi Wireless Multimedia Extensions */
1930 /* ht_capab, ht_oper */
1933 RTW_INFO("%s, len=%d\n", __FUNCTION__, len);
1935 if (!MLME_IS_AP(padapter) && !MLME_IS_MESH(padapter))
1939 if (len > MAX_IE_SZ)
1942 pbss_network->IELength = len;
1944 _rtw_memset(ie, 0, MAX_IE_SZ);
1946 _rtw_memcpy(ie, pbuf, pbss_network->IELength);
1949 if (pbss_network->InfrastructureMode != Ndis802_11APMode
1950 && pbss_network->InfrastructureMode != Ndis802_11_mesh
1957 rtw_ap_check_scan(padapter);
1960 pbss_network->Rssi = 0;
1962 _rtw_memcpy(pbss_network->MacAddress, adapter_mac_addr(padapter), ETH_ALEN);
1964 /* beacon interval */
1965 p = rtw_get_beacon_interval_from_ie(ie);/* ie + 8; */ /* 8: TimeStamp, 2: Beacon Interval 2:Capability */
1966 /* pbss_network->Configuration.BeaconPeriod = le16_to_cpu(*(unsigned short*)p); */
1967 pbss_network->Configuration.BeaconPeriod = RTW_GET_LE16(p);
1970 /* cap = *(unsigned short *)rtw_get_capability_from_ie(ie); */
1971 /* cap = le16_to_cpu(cap); */
1972 cap = RTW_GET_LE16(ie);
1975 p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _SSID_IE_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_));
1976 if (p && ie_len > 0) {
1977 _rtw_memset(&pbss_network->Ssid, 0, sizeof(NDIS_802_11_SSID));
1978 _rtw_memcpy(pbss_network->Ssid.Ssid, (p + 2), ie_len);
1979 pbss_network->Ssid.SsidLength = ie_len;
1981 _rtw_memcpy(padapter->wdinfo.p2p_group_ssid, pbss_network->Ssid.Ssid, pbss_network->Ssid.SsidLength);
1982 padapter->wdinfo.p2p_group_ssid_len = pbss_network->Ssid.SsidLength;
1986 #ifdef CONFIG_RTW_MESH
1988 if (MLME_IS_MESH(padapter)) {
1989 p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, WLAN_EID_MESH_ID, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_));
1990 if (p && ie_len > 0) {
1991 _rtw_memset(&pbss_network->mesh_id, 0, sizeof(NDIS_802_11_SSID));
1992 _rtw_memcpy(pbss_network->mesh_id.Ssid, (p + 2), ie_len);
1993 pbss_network->mesh_id.SsidLength = ie_len;
2000 pbss_network->Configuration.Length = 0;
2001 p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _DSSET_IE_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_));
2002 if (p && ie_len > 0)
2005 pbss_network->Configuration.DSConfig = channel;
2008 _rtw_memset(supportRate, 0, NDIS_802_11_LENGTH_RATES_EX);
2009 /* get supported rates */
2010 p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _SUPPORTEDRATES_IE_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_));
2012 if (padapter->registrypriv.wireless_mode == WIRELESS_11B) {
2013 ret_rm = rtw_remove_ie_g_rate(ie , &len, _BEACON_IE_OFFSET_, _SUPPORTEDRATES_IE_);
2014 RTW_DBG("%s, rtw_remove_ie_g_rate=%d\n", __FUNCTION__,ret_rm);
2015 ie_len = ie_len - ret_rm;
2016 pbss_network->IELength=pbss_network->IELength - ret_rm;
2018 RTW_DBG("%s, ie_len=%u\n", __FUNCTION__, ie_len);
2019 _rtw_memcpy(supportRate, p + 2, ie_len);
2020 supportRateNum = ie_len;
2023 /* get ext_supported rates */
2024 p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _EXT_SUPPORTEDRATES_IE_, &ie_len, pbss_network->IELength - _BEACON_IE_OFFSET_);
2026 if (padapter->registrypriv.wireless_mode == WIRELESS_11B) {
2027 pbss_network->IELength = pbss_network->IELength-*(p+1) -2;
2028 ret_rm = rtw_ies_remove_ie(ie , &len,_BEACON_IE_OFFSET_,
2029 _EXT_SUPPORTEDRATES_IE_,NULL,0);
2030 RTW_DBG("%s, remove_ie of ext_supported rates =%d\n", __FUNCTION__, ret_rm);
2032 _rtw_memcpy(supportRate + supportRateNum, p + 2, ie_len);
2033 supportRateNum += ie_len;
2038 network_type = rtw_check_network_type(supportRate, supportRateNum, channel);
2040 rtw_set_supported_rate(pbss_network->SupportedRates, network_type);
2043 /* parsing ERP_IE */
2044 p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _ERPINFO_IE_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_));
2045 if (p && ie_len > 0) {
2046 if(padapter->registrypriv.wireless_mode == WIRELESS_11B ) {
2048 pbss_network->IELength = pbss_network->IELength - *(p+1) - 2;
2049 ret_rm = rtw_ies_remove_ie(ie , &len, _BEACON_IE_OFFSET_, _ERPINFO_IE_,NULL,0);
2050 RTW_DBG("%s, remove_ie of ERP_IE=%d\n", __FUNCTION__, ret_rm);
2052 ERP_IE_handler(padapter, (PNDIS_802_11_VARIABLE_IEs)p);
2056 /* update privacy/security */
2058 pbss_network->Privacy = 1;
2060 pbss_network->Privacy = 0;
2062 psecuritypriv->wpa_psk = 0;
2067 pairwise_cipher = 0;
2068 psecuritypriv->wpa2_group_cipher = _NO_PRIVACY_;
2069 psecuritypriv->wpa2_pairwise_cipher = _NO_PRIVACY_;
2070 p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _RSN_IE_2_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_));
2071 if (p && ie_len > 0) {
2072 if (rtw_parse_wpa2_ie(p, ie_len + 2, &group_cipher, &pairwise_cipher, &akm, &mfp_opt) == _SUCCESS) {
2073 psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
2074 psecuritypriv->ndisauthtype = Ndis802_11AuthModeWPA2PSK;
2075 psecuritypriv->dot8021xalg = 1;/* psk, todo:802.1x */
2076 psecuritypriv->wpa_psk |= BIT(1);
2078 psecuritypriv->wpa2_group_cipher = group_cipher;
2079 psecuritypriv->wpa2_pairwise_cipher = pairwise_cipher;
2082 Kernel < v5.1, the auth_type set as NL80211_AUTHTYPE_AUTOMATIC
2083 in cfg80211_rtw_start_ap().
2084 if the AKM SAE in the RSN IE, we have to update the auth_type for SAE
2085 in rtw_check_beacon_data().
2087 if (CHECK_BIT(WLAN_AKM_TYPE_SAE, akm))
2088 psecuritypriv->auth_type = NL80211_AUTHTYPE_SAE;
2090 switch (group_cipher) {
2091 case WPA_CIPHER_NONE:
2092 psecuritypriv->wpa2_group_cipher = _NO_PRIVACY_;
2094 case WPA_CIPHER_WEP40:
2095 psecuritypriv->wpa2_group_cipher = _WEP40_;
2097 case WPA_CIPHER_TKIP:
2098 psecuritypriv->wpa2_group_cipher = _TKIP_;
2100 case WPA_CIPHER_CCMP:
2101 psecuritypriv->wpa2_group_cipher = _AES_;
2103 case WPA_CIPHER_WEP104:
2104 psecuritypriv->wpa2_group_cipher = _WEP104_;
2108 switch (pairwise_cipher) {
2109 case WPA_CIPHER_NONE:
2110 psecuritypriv->wpa2_pairwise_cipher = _NO_PRIVACY_;
2112 case WPA_CIPHER_WEP40:
2113 psecuritypriv->wpa2_pairwise_cipher = _WEP40_;
2115 case WPA_CIPHER_TKIP:
2116 psecuritypriv->wpa2_pairwise_cipher = _TKIP_;
2118 case WPA_CIPHER_CCMP:
2119 psecuritypriv->wpa2_pairwise_cipher = _AES_;
2121 case WPA_CIPHER_WEP104:
2122 psecuritypriv->wpa2_pairwise_cipher = _WEP104_;
2133 pairwise_cipher = 0;
2134 psecuritypriv->wpa_group_cipher = _NO_PRIVACY_;
2135 psecuritypriv->wpa_pairwise_cipher = _NO_PRIVACY_;
2136 for (p = ie + _BEACON_IE_OFFSET_; ; p += (ie_len + 2)) {
2137 p = rtw_get_ie(p, _SSN_IE_1_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_ - (ie_len + 2)));
2138 if ((p) && (_rtw_memcmp(p + 2, OUI1, 4))) {
2139 if (rtw_parse_wpa_ie(p, ie_len + 2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) {
2140 psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
2141 psecuritypriv->ndisauthtype = Ndis802_11AuthModeWPAPSK;
2142 psecuritypriv->dot8021xalg = 1;/* psk, todo:802.1x */
2144 psecuritypriv->wpa_psk |= BIT(0);
2146 psecuritypriv->wpa_group_cipher = group_cipher;
2147 psecuritypriv->wpa_pairwise_cipher = pairwise_cipher;
2150 switch (group_cipher) {
2151 case WPA_CIPHER_NONE:
2152 psecuritypriv->wpa_group_cipher = _NO_PRIVACY_;
2154 case WPA_CIPHER_WEP40:
2155 psecuritypriv->wpa_group_cipher = _WEP40_;
2157 case WPA_CIPHER_TKIP:
2158 psecuritypriv->wpa_group_cipher = _TKIP_;
2160 case WPA_CIPHER_CCMP:
2161 psecuritypriv->wpa_group_cipher = _AES_;
2163 case WPA_CIPHER_WEP104:
2164 psecuritypriv->wpa_group_cipher = _WEP104_;
2168 switch (pairwise_cipher) {
2169 case WPA_CIPHER_NONE:
2170 psecuritypriv->wpa_pairwise_cipher = _NO_PRIVACY_;
2172 case WPA_CIPHER_WEP40:
2173 psecuritypriv->wpa_pairwise_cipher = _WEP40_;
2175 case WPA_CIPHER_TKIP:
2176 psecuritypriv->wpa_pairwise_cipher = _TKIP_;
2178 case WPA_CIPHER_CCMP:
2179 psecuritypriv->wpa_pairwise_cipher = _AES_;
2181 case WPA_CIPHER_WEP104:
2182 psecuritypriv->wpa_pairwise_cipher = _WEP104_;
2192 if ((p == NULL) || (ie_len == 0))
2197 #ifdef CONFIG_RTW_MESH
2198 if (MLME_IS_MESH(padapter)) {
2199 /* MFP is mandatory for secure mesh */
2200 if (padapter->mesh_info.mesh_auth_id)
2201 mfp_opt = MFP_REQUIRED;
2204 if (mfp_opt == MFP_INVALID) {
2205 RTW_INFO(FUNC_ADPT_FMT" invalid MFP setting\n", FUNC_ADPT_ARG(padapter));
2208 psecuritypriv->mfp_opt = mfp_opt;
2212 pmlmepriv->qospriv.qos_option = 0;
2213 #ifdef CONFIG_RTW_MESH
2214 if (MLME_IS_MESH(padapter))
2215 pmlmepriv->qospriv.qos_option = 1;
2217 if (pregistrypriv->wmm_enable) {
2218 for (p = ie + _BEACON_IE_OFFSET_; ; p += (ie_len + 2)) {
2219 p = rtw_get_ie(p, _VENDOR_SPECIFIC_IE_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_ - (ie_len + 2)));
2220 if ((p) && _rtw_memcmp(p + 2, WMM_PARA_IE, 6)) {
2221 pmlmepriv->qospriv.qos_option = 1;
2223 *(p + 8) |= BIT(7); /* QoS Info, support U-APSD */
2225 /* disable all ACM bits since the WMM admission control is not supported */
2226 *(p + 10) &= ~BIT(4); /* BE */
2227 *(p + 14) &= ~BIT(4); /* BK */
2228 *(p + 18) &= ~BIT(4); /* VI */
2229 *(p + 22) &= ~BIT(4); /* VO */
2231 WMM_param_handler(padapter, (PNDIS_802_11_VARIABLE_IEs)p);
2236 if ((p == NULL) || (ie_len == 0))
2240 #ifdef CONFIG_80211N_HT
2241 if(padapter->registrypriv.ht_enable &&
2242 is_supported_ht(padapter->registrypriv.wireless_mode)) {
2243 /* parsing HT_CAP_IE */
2244 p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_CAPABILITY_IE_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_));
2245 if (p && ie_len > 0) {
2247 HT_CAP_AMPDU_FACTOR max_rx_ampdu_factor = MAX_AMPDU_FACTOR_64K;
2248 struct rtw_ieee80211_ht_cap *pht_cap = (struct rtw_ieee80211_ht_cap *)(p + 2);
2251 RTW_INFO(FUNC_ADPT_FMT" HT_CAP_IE from upper layer:\n", FUNC_ADPT_ARG(padapter));
2252 dump_ht_cap_ie_content(RTW_DBGDUMP, p + 2, ie_len);
2258 network_type |= WIRELESS_11_24N;
2260 rtw_ht_use_default_setting(padapter);
2262 /* Update HT Capabilities Info field */
2263 if (pmlmepriv->htpriv.sgi_20m == _FALSE)
2264 pht_cap->cap_info &= ~(IEEE80211_HT_CAP_SGI_20);
2266 if (pmlmepriv->htpriv.sgi_40m == _FALSE)
2267 pht_cap->cap_info &= ~(IEEE80211_HT_CAP_SGI_40);
2269 if (!TEST_FLAG(pmlmepriv->htpriv.ldpc_cap, LDPC_HT_ENABLE_RX))
2270 pht_cap->cap_info &= ~(IEEE80211_HT_CAP_LDPC_CODING);
2272 if (!TEST_FLAG(pmlmepriv->htpriv.stbc_cap, STBC_HT_ENABLE_TX))
2273 pht_cap->cap_info &= ~(IEEE80211_HT_CAP_TX_STBC);
2275 if (!TEST_FLAG(pmlmepriv->htpriv.stbc_cap, STBC_HT_ENABLE_RX))
2276 pht_cap->cap_info &= ~(IEEE80211_HT_CAP_RX_STBC_3R);
2278 /* Update A-MPDU Parameters field */
2279 pht_cap->ampdu_params_info &= ~(IEEE80211_HT_CAP_AMPDU_FACTOR | IEEE80211_HT_CAP_AMPDU_DENSITY);
2281 if ((psecuritypriv->wpa_pairwise_cipher & WPA_CIPHER_CCMP) ||
2282 (psecuritypriv->wpa2_pairwise_cipher & WPA_CIPHER_CCMP)) {
2283 rtw_hal_get_def_var(padapter, HW_VAR_BEST_AMPDU_DENSITY, &best_ampdu_density);
2284 pht_cap->ampdu_params_info |= (IEEE80211_HT_CAP_AMPDU_DENSITY & (best_ampdu_density << 2));
2286 pht_cap->ampdu_params_info |= (IEEE80211_HT_CAP_AMPDU_DENSITY & 0x00);
2288 rtw_hal_get_def_var(padapter, HW_VAR_MAX_RX_AMPDU_FACTOR, &max_rx_ampdu_factor);
2289 pht_cap->ampdu_params_info |= (IEEE80211_HT_CAP_AMPDU_FACTOR & max_rx_ampdu_factor); /* set Max Rx AMPDU size to 64K */
2291 _rtw_memcpy(&(pmlmeinfo->HT_caps), pht_cap, sizeof(struct HT_caps_element));
2293 /* Update Supported MCS Set field */
2295 struct hal_spec_t *hal_spec = GET_HAL_SPEC(padapter);
2299 rtw_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
2300 rx_nss = rtw_min(rf_type_to_rf_rx_cnt(rf_type), hal_spec->rx_nss_num);
2302 /* RX MCS Bitmask */
2305 set_mcs_rate_by_mask(HT_CAP_ELE_RX_MCS_MAP(pht_cap), MCS_RATE_1R);
2308 set_mcs_rate_by_mask(HT_CAP_ELE_RX_MCS_MAP(pht_cap), MCS_RATE_2R);
2311 set_mcs_rate_by_mask(HT_CAP_ELE_RX_MCS_MAP(pht_cap), MCS_RATE_3R);
2314 set_mcs_rate_by_mask(HT_CAP_ELE_RX_MCS_MAP(pht_cap), MCS_RATE_4R);
2317 RTW_WARN("rf_type:%d or rx_nss:%u is not expected\n", rf_type, hal_spec->rx_nss_num);
2319 for (i = 0; i < 10; i++)
2320 *(HT_CAP_ELE_RX_MCS_MAP(pht_cap) + i) &= padapter->mlmeextpriv.default_supported_mcs_set[i];
2323 #ifdef CONFIG_BEAMFORMING
2324 /* Use registry value to enable HT Beamforming. */
2325 /* ToDo: use configure file to set these capability. */
2326 pht_cap->tx_BF_cap_info = 0;
2329 if (TEST_FLAG(pmlmepriv->htpriv.beamform_cap, BEAMFORMING_HT_BEAMFORMER_ENABLE)) {
2330 /* Transmit NDP Capable */
2331 SET_HT_CAP_TXBF_TRANSMIT_NDP_CAP(pht_cap, 1);
2332 /* Explicit Compressed Steering Capable */
2333 SET_HT_CAP_TXBF_EXPLICIT_COMP_STEERING_CAP(pht_cap, 1);
2334 /* Compressed Steering Number Antennas */
2335 SET_HT_CAP_TXBF_COMP_STEERING_NUM_ANTENNAS(pht_cap, 1);
2336 rtw_hal_get_def_var(padapter, HAL_DEF_BEAMFORMER_CAP, (u8 *)&rf_num);
2337 SET_HT_CAP_TXBF_CHNL_ESTIMATION_NUM_ANTENNAS(pht_cap, rf_num);
2341 if (TEST_FLAG(pmlmepriv->htpriv.beamform_cap, BEAMFORMING_HT_BEAMFORMEE_ENABLE)) {
2342 /* Receive NDP Capable */
2343 SET_HT_CAP_TXBF_RECEIVE_NDP_CAP(pht_cap, 1);
2344 /* Explicit Compressed Beamforming Feedback Capable */
2345 SET_HT_CAP_TXBF_EXPLICIT_COMP_FEEDBACK_CAP(pht_cap, 2);
2346 rtw_hal_get_def_var(padapter, HAL_DEF_BEAMFORMEE_CAP, (u8 *)&rf_num);
2347 SET_HT_CAP_TXBF_COMP_STEERING_NUM_ANTENNAS(pht_cap, rf_num);
2349 #endif /* CONFIG_BEAMFORMING */
2351 _rtw_memcpy(&pmlmepriv->htpriv.ht_cap, p + 2, ie_len);
2354 RTW_INFO(FUNC_ADPT_FMT" HT_CAP_IE driver masked:\n", FUNC_ADPT_ARG(padapter));
2355 dump_ht_cap_ie_content(RTW_DBGDUMP, p + 2, ie_len);
2359 /* parsing HT_INFO_IE */
2360 p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_ADD_INFO_IE_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_));
2361 if (p && ie_len > 0) {
2364 pbss_network->Configuration.DSConfig = GET_HT_OP_ELE_PRI_CHL(pHT_info_ie + 2);
2365 else if (channel != GET_HT_OP_ELE_PRI_CHL(pHT_info_ie + 2)) {
2366 RTW_INFO(FUNC_ADPT_FMT" ch inconsistent, DSSS:%u, HT primary:%u\n"
2367 , FUNC_ADPT_ARG(padapter), channel, GET_HT_OP_ELE_PRI_CHL(pHT_info_ie + 2));
2371 #endif /* CONFIG_80211N_HT */
2373 switch (network_type) {
2375 pbss_network->NetworkTypeInUse = Ndis802_11DS;
2379 case WIRELESS_11G_24N:
2380 case WIRELESS_11BG_24N:
2381 pbss_network->NetworkTypeInUse = Ndis802_11OFDM24;
2384 pbss_network->NetworkTypeInUse = Ndis802_11OFDM5;
2387 pbss_network->NetworkTypeInUse = Ndis802_11OFDM24;
2391 pmlmepriv->cur_network.network_type = network_type;
2393 #ifdef CONFIG_80211N_HT
2394 pmlmepriv->htpriv.ht_option = _FALSE;
2396 if ((psecuritypriv->wpa2_pairwise_cipher & WPA_CIPHER_TKIP) ||
2397 (psecuritypriv->wpa_pairwise_cipher & WPA_CIPHER_TKIP)) {
2399 /* ht_cap = _FALSE; */
2403 if (padapter->registrypriv.ht_enable &&
2404 is_supported_ht(padapter->registrypriv.wireless_mode) && ht_cap == _TRUE) {
2406 pmlmepriv->htpriv.ht_option = _TRUE;
2407 pmlmepriv->qospriv.qos_option = 1;
2409 pmlmepriv->htpriv.ampdu_enable = pregistrypriv->ampdu_enable ? _TRUE : _FALSE;
2411 HT_caps_handler(padapter, (PNDIS_802_11_VARIABLE_IEs)pHT_caps_ie);
2413 HT_info_handler(padapter, (PNDIS_802_11_VARIABLE_IEs)pHT_info_ie);
2417 #ifdef CONFIG_80211AC_VHT
2418 pmlmepriv->ori_vht_en = 0;
2419 pmlmepriv->vhtpriv.vht_option = _FALSE;
2421 if (pmlmepriv->htpriv.ht_option == _TRUE
2422 && pbss_network->Configuration.DSConfig > 14
2423 && REGSTY_IS_11AC_ENABLE(pregistrypriv)
2424 && is_supported_vht(pregistrypriv->wireless_mode)
2425 && (!rfctl->country_ent || COUNTRY_CHPLAN_EN_11AC(rfctl->country_ent))
2427 /* Parsing VHT CAP IE */
2428 p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, EID_VHTCapability, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_));
2429 if (p && ie_len > 0)
2432 /* Parsing VHT OPERATION IE */
2434 if (vht_cap == _TRUE
2436 if(MLME_IS_MESH(padapter)) /* allow only mesh temporarily before VHT IE checking is ready */
2437 rtw_check_for_vht20(padapter, ie + _BEACON_IE_OFFSET_, pbss_network->IELength - _BEACON_IE_OFFSET_);
2438 pmlmepriv->ori_vht_en = 1;
2439 pmlmepriv->vhtpriv.vht_option = _TRUE;
2440 } else if (REGSTY_IS_11AC_AUTO(pregistrypriv)) {
2441 rtw_vht_ies_detach(padapter, pbss_network);
2442 rtw_vht_ies_attach(padapter, pbss_network);
2446 if (pmlmepriv->vhtpriv.vht_option == _FALSE)
2447 rtw_vht_ies_detach(padapter, pbss_network);
2448 #endif /* CONFIG_80211AC_VHT */
2450 #ifdef CONFIG_80211N_HT
2451 if(padapter->registrypriv.ht_enable &&
2452 is_supported_ht(padapter->registrypriv.wireless_mode) &&
2453 pbss_network->Configuration.DSConfig <= 14 && padapter->registrypriv.wifi_spec == 1 &&
2454 pbss_network->IELength + 10 <= MAX_IE_SZ) {
2457 SET_EXT_CAPABILITY_ELE_BSS_COEXIST(pmlmepriv->ext_capab_ie_data, 1);
2458 pmlmepriv->ext_capab_ie_len = 10;
2459 rtw_set_ie(pbss_network->IEs + pbss_network->IELength, EID_EXTCapability, 8, pmlmepriv->ext_capab_ie_data, &len);
2460 pbss_network->IELength += pmlmepriv->ext_capab_ie_len;
2462 #endif /* CONFIG_80211N_HT */
2464 pbss_network->Length = get_WLAN_BSSID_EX_sz((WLAN_BSSID_EX *)pbss_network);
2466 rtw_ies_get_chbw(pbss_network->IEs + _BEACON_IE_OFFSET_, pbss_network->IELength - _BEACON_IE_OFFSET_
2467 , &pmlmepriv->ori_ch, &pmlmepriv->ori_bw, &pmlmepriv->ori_offset, 1, 1);
2468 rtw_warn_on(pmlmepriv->ori_ch == 0);
2471 /* alloc sta_info for ap itself */
2473 struct sta_info *sta;
2475 sta = rtw_get_stainfo(&padapter->stapriv, pbss_network->MacAddress);
2477 sta = rtw_alloc_stainfo(&padapter->stapriv, pbss_network->MacAddress);
2483 rtw_startbss_cmd(padapter, RTW_CMDF_WAIT_ACK);
2485 int sk_band = RTW_GET_SCAN_BAND_SKIP(padapter);
2488 RTW_CLR_SCAN_BAND_SKIP(padapter, sk_band);
2491 rtw_indicate_connect(padapter);
2493 pmlmepriv->cur_network.join_res = _TRUE;/* for check if already set beacon */
2495 /* update bc/mc sta_info */
2496 /* update_bmc_sta(padapter); */
2502 #if CONFIG_RTW_MACADDR_ACL
2503 void rtw_macaddr_acl_init(_adapter *adapter, u8 period)
2505 struct sta_priv *stapriv = &adapter->stapriv;
2506 struct wlan_acl_pool *acl;
2511 if (period >= RTW_ACL_PERIOD_NUM) {
2516 acl = &stapriv->acl_list[period];
2517 acl_node_q = &acl->acl_node_q;
2519 _rtw_spinlock_init(&(acl_node_q->lock));
2521 _enter_critical_bh(&(acl_node_q->lock), &irqL);
2522 _rtw_init_listhead(&(acl_node_q->queue));
2524 acl->mode = RTW_ACL_MODE_DISABLED;
2525 for (i = 0; i < NUM_ACL; i++) {
2526 _rtw_init_listhead(&acl->aclnode[i].list);
2527 acl->aclnode[i].valid = _FALSE;
2529 _exit_critical_bh(&(acl_node_q->lock), &irqL);
2532 static void _rtw_macaddr_acl_deinit(_adapter *adapter, u8 period, bool clear_only)
2534 struct sta_priv *stapriv = &adapter->stapriv;
2535 struct wlan_acl_pool *acl;
2539 struct rtw_wlan_acl_node *acl_node;
2541 if (period >= RTW_ACL_PERIOD_NUM) {
2546 acl = &stapriv->acl_list[period];
2547 acl_node_q = &acl->acl_node_q;
2549 _enter_critical_bh(&(acl_node_q->lock), &irqL);
2550 head = get_list_head(acl_node_q);
2551 list = get_next(head);
2552 while (rtw_end_of_queue_search(head, list) == _FALSE) {
2553 acl_node = LIST_CONTAINOR(list, struct rtw_wlan_acl_node, list);
2554 list = get_next(list);
2556 if (acl_node->valid == _TRUE) {
2557 acl_node->valid = _FALSE;
2558 rtw_list_delete(&acl_node->list);
2562 _exit_critical_bh(&(acl_node_q->lock), &irqL);
2565 _rtw_spinlock_free(&(acl_node_q->lock));
2567 rtw_warn_on(acl->num);
2568 acl->mode = RTW_ACL_MODE_DISABLED;
2571 void rtw_macaddr_acl_deinit(_adapter *adapter, u8 period)
2573 _rtw_macaddr_acl_deinit(adapter, period, 0);
2576 void rtw_macaddr_acl_clear(_adapter *adapter, u8 period)
2578 _rtw_macaddr_acl_deinit(adapter, period, 1);
2581 void rtw_set_macaddr_acl(_adapter *adapter, u8 period, int mode)
2583 struct sta_priv *stapriv = &adapter->stapriv;
2584 struct wlan_acl_pool *acl;
2586 if (period >= RTW_ACL_PERIOD_NUM) {
2591 acl = &stapriv->acl_list[period];
2593 RTW_INFO(FUNC_ADPT_FMT" p=%u, mode=%d\n"
2594 , FUNC_ADPT_ARG(adapter), period, mode);
2599 int rtw_acl_add_sta(_adapter *adapter, u8 period, const u8 *addr)
2604 int i = -1, ret = 0;
2605 struct rtw_wlan_acl_node *acl_node;
2606 struct sta_priv *stapriv = &adapter->stapriv;
2607 struct wlan_acl_pool *acl;
2610 if (period >= RTW_ACL_PERIOD_NUM) {
2616 acl = &stapriv->acl_list[period];
2617 acl_node_q = &acl->acl_node_q;
2619 _enter_critical_bh(&(acl_node_q->lock), &irqL);
2621 head = get_list_head(acl_node_q);
2622 list = get_next(head);
2624 /* search for existed entry */
2625 while (rtw_end_of_queue_search(head, list) == _FALSE) {
2626 acl_node = LIST_CONTAINOR(list, struct rtw_wlan_acl_node, list);
2627 list = get_next(list);
2629 if (_rtw_memcmp(acl_node->addr, addr, ETH_ALEN)) {
2630 if (acl_node->valid == _TRUE) {
2639 if (acl->num >= NUM_ACL)
2642 /* find empty one and use */
2643 for (i = 0; i < NUM_ACL; i++) {
2645 acl_node = &acl->aclnode[i];
2646 if (acl_node->valid == _FALSE) {
2648 _rtw_init_listhead(&acl_node->list);
2649 _rtw_memcpy(acl_node->addr, addr, ETH_ALEN);
2650 acl_node->valid = _TRUE;
2652 rtw_list_insert_tail(&acl_node->list, get_list_head(acl_node_q));
2659 _exit_critical_bh(&(acl_node_q->lock), &irqL);
2661 if (!existed && (i < 0 || i >= NUM_ACL))
2664 RTW_INFO(FUNC_ADPT_FMT" p=%u "MAC_FMT" %s (acl_num=%d)\n"
2665 , FUNC_ADPT_ARG(adapter), period, MAC_ARG(addr)
2666 , (existed ? "existed" : ((i < 0 || i >= NUM_ACL) ? "no room" : "added"))
2672 int rtw_acl_remove_sta(_adapter *adapter, u8 period, const u8 *addr)
2677 struct rtw_wlan_acl_node *acl_node;
2678 struct sta_priv *stapriv = &adapter->stapriv;
2679 struct wlan_acl_pool *acl;
2681 u8 is_baddr = is_broadcast_mac_addr(addr);
2684 if (period >= RTW_ACL_PERIOD_NUM) {
2689 acl = &stapriv->acl_list[period];
2690 acl_node_q = &acl->acl_node_q;
2692 _enter_critical_bh(&(acl_node_q->lock), &irqL);
2694 head = get_list_head(acl_node_q);
2695 list = get_next(head);
2697 while (rtw_end_of_queue_search(head, list) == _FALSE) {
2698 acl_node = LIST_CONTAINOR(list, struct rtw_wlan_acl_node, list);
2699 list = get_next(list);
2701 if (is_baddr || _rtw_memcmp(acl_node->addr, addr, ETH_ALEN)) {
2702 if (acl_node->valid == _TRUE) {
2703 acl_node->valid = _FALSE;
2704 rtw_list_delete(&acl_node->list);
2711 _exit_critical_bh(&(acl_node_q->lock), &irqL);
2713 RTW_INFO(FUNC_ADPT_FMT" p=%u "MAC_FMT" %s (acl_num=%d)\n"
2714 , FUNC_ADPT_ARG(adapter), period, MAC_ARG(addr)
2715 , is_baddr ? "clear all" : (match ? "match" : "no found")
2721 #endif /* CONFIG_RTW_MACADDR_ACL */
2723 u8 rtw_ap_set_sta_key(_adapter *adapter, const u8 *addr, u8 alg, const u8 *key, u8 keyid, u8 gk)
2725 struct cmd_priv *cmdpriv = &adapter->cmdpriv;
2726 struct cmd_obj *cmd;
2727 struct set_stakey_parm *param;
2730 cmd = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
2736 param = (struct set_stakey_parm *)rtw_zmalloc(sizeof(struct set_stakey_parm));
2737 if (param == NULL) {
2738 rtw_mfree((u8 *) cmd, sizeof(struct cmd_obj));
2743 init_h2fwcmd_w_parm_no_rsp(cmd, param, _SetStaKey_CMD_);
2745 _rtw_memcpy(param->addr, addr, ETH_ALEN);
2746 param->algorithm = alg;
2747 param->keyid = keyid;
2748 _rtw_memcpy(param->key, key, 16);
2751 res = rtw_enqueue_cmd(cmdpriv, cmd);
2757 u8 rtw_ap_set_pairwise_key(_adapter *padapter, struct sta_info *psta)
2759 return rtw_ap_set_sta_key(padapter
2760 , psta->cmn.mac_addr
2761 , psta->dot118021XPrivacy
2762 , psta->dot118021x_UncstKey.skey
2768 static int rtw_ap_set_key(_adapter *padapter, u8 *key, u8 alg, int keyid, u8 set_tx)
2771 struct cmd_obj *pcmd;
2772 struct setkey_parm *psetkeyparm;
2773 struct cmd_priv *pcmdpriv = &(padapter->cmdpriv);
2776 /* RTW_INFO("%s\n", __FUNCTION__); */
2778 pcmd = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
2783 psetkeyparm = (struct setkey_parm *)rtw_zmalloc(sizeof(struct setkey_parm));
2784 if (psetkeyparm == NULL) {
2785 rtw_mfree((unsigned char *)pcmd, sizeof(struct cmd_obj));
2790 _rtw_memset(psetkeyparm, 0, sizeof(struct setkey_parm));
2792 psetkeyparm->keyid = (u8)keyid;
2793 if (is_wep_enc(alg))
2794 padapter->securitypriv.key_mask |= BIT(psetkeyparm->keyid);
2796 psetkeyparm->algorithm = alg;
2798 psetkeyparm->set_tx = set_tx;
2814 _rtw_memcpy(&(psetkeyparm->key[0]), key, keylen);
2816 pcmd->cmdcode = _SetKey_CMD_;
2817 pcmd->parmbuf = (u8 *)psetkeyparm;
2818 pcmd->cmdsz = (sizeof(struct setkey_parm));
2823 _rtw_init_listhead(&pcmd->list);
2825 res = rtw_enqueue_cmd(pcmdpriv, pcmd);
2832 int rtw_ap_set_group_key(_adapter *padapter, u8 *key, u8 alg, int keyid)
2834 RTW_INFO("%s\n", __FUNCTION__);
2836 return rtw_ap_set_key(padapter, key, alg, keyid, 1);
2839 int rtw_ap_set_wep_key(_adapter *padapter, u8 *key, u8 keylen, int keyid, u8 set_tx)
2854 RTW_INFO("%s\n", __FUNCTION__);
2856 return rtw_ap_set_key(padapter, key, alg, keyid, set_tx);
2859 u8 rtw_ap_bmc_frames_hdl(_adapter *padapter)
2861 #define HIQ_XMIT_COUNTS (6)
2863 struct sta_info *psta_bmc;
2864 _list *xmitframe_plist, *xmitframe_phead;
2865 struct xmit_frame *pxmitframe = NULL;
2866 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
2867 struct sta_priv *pstapriv = &padapter->stapriv;
2868 bool update_tim = _FALSE;
2871 if (padapter->registrypriv.wifi_spec != 1)
2875 psta_bmc = rtw_get_bcmc_stainfo(padapter);
2880 _enter_critical_bh(&pxmitpriv->lock, &irqL);
2882 if ((rtw_tim_map_is_set(padapter, pstapriv->tim_bitmap, 0)) && (psta_bmc->sleepq_len > 0)) {
2885 _update_beacon(padapter, _TIM_IE_, NULL, _FALSE, "update TIM with TIB=1");
2887 RTW_INFO("sleepq_len of bmc_sta = %d\n", psta_bmc->sleepq_len);
2889 xmitframe_phead = get_list_head(&psta_bmc->sleep_q);
2890 xmitframe_plist = get_next(xmitframe_phead);
2892 while ((rtw_end_of_queue_search(xmitframe_phead, xmitframe_plist)) == _FALSE) {
2893 pxmitframe = LIST_CONTAINOR(xmitframe_plist, struct xmit_frame, list);
2895 xmitframe_plist = get_next(xmitframe_plist);
2897 rtw_list_delete(&pxmitframe->list);
2899 psta_bmc->sleepq_len--;
2902 if (psta_bmc->sleepq_len > 0)
2903 pxmitframe->attrib.mdata = 1;
2905 pxmitframe->attrib.mdata = 0;
2907 if (tx_counts == HIQ_XMIT_COUNTS)
2908 pxmitframe->attrib.mdata = 0;
2910 pxmitframe->attrib.triggered = 1;
2912 if (xmitframe_hiq_filter(pxmitframe) == _TRUE)
2913 pxmitframe->attrib.qsel = QSLT_HIGH;/*HIQ*/
2915 rtw_hal_xmitframe_enqueue(padapter, pxmitframe);
2917 if (tx_counts == HIQ_XMIT_COUNTS)
2923 if (psta_bmc->sleepq_len == 0) {
2925 /*RTW_INFO("sleepq_len of bmc_sta = %d\n", psta_bmc->sleepq_len);*/
2927 if (rtw_tim_map_is_set(padapter, pstapriv->tim_bitmap, 0))
2930 rtw_tim_map_clear(padapter, pstapriv->tim_bitmap, 0);
2931 rtw_tim_map_clear(padapter, pstapriv->sta_dz_bitmap, 0);
2933 if (update_tim == _TRUE) {
2934 RTW_INFO("clear TIB\n");
2935 _update_beacon(padapter, _TIM_IE_, NULL, _TRUE, "bmc sleepq and HIQ empty");
2940 _exit_critical_bh(&pxmitpriv->lock, &irqL);
2944 rtw_hal_get_hwreg(padapter, HW_VAR_CHK_HI_QUEUE_EMPTY, &empty);
2946 while (_FALSE == empty && rtw_get_passing_time_ms(start) < 3000) {
2948 rtw_hal_get_hwreg(padapter, HW_VAR_CHK_HI_QUEUE_EMPTY, &empty);
2952 printk("check if hiq empty=%d\n", empty);
2958 #ifdef CONFIG_NATIVEAP_MLME
2960 static void associated_stainfo_update(_adapter *padapter, struct sta_info *psta, u32 sta_info_type)
2962 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
2964 RTW_INFO("%s: "MAC_FMT", updated_type=0x%x\n", __func__, MAC_ARG(psta->cmn.mac_addr), sta_info_type);
2965 #ifdef CONFIG_80211N_HT
2966 if (sta_info_type & STA_INFO_UPDATE_BW) {
2968 if ((psta->flags & WLAN_STA_HT) && !psta->ht_20mhz_set) {
2969 if (pmlmepriv->sw_to_20mhz) {
2970 psta->cmn.bw_mode = CHANNEL_WIDTH_20;
2971 /*psta->htpriv.ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;*/
2972 psta->htpriv.sgi_40m = _FALSE;
2974 /*TODO: Switch back to 40MHZ?80MHZ*/
2978 #endif /* CONFIG_80211N_HT */
2980 if (sta_info_type & STA_INFO_UPDATE_RATE) {
2985 if (sta_info_type & STA_INFO_UPDATE_PROTECTION_MODE)
2986 VCS_update(padapter, psta);
2989 if (sta_info_type & STA_INFO_UPDATE_CAP) {
2993 if (sta_info_type & STA_INFO_UPDATE_HT_CAP) {
2997 if (sta_info_type & STA_INFO_UPDATE_VHT_CAP) {
3004 static void update_bcn_ext_capab_ie(_adapter *padapter)
3007 unsigned char *pbuf;
3008 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
3009 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
3010 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
3011 WLAN_BSSID_EX *pnetwork = &(pmlmeinfo->network);
3012 u8 *ie = pnetwork->IEs;
3013 u8 null_extcap_data[8] = {0};
3015 pbuf = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _EXT_CAP_IE_, &ie_len, (pnetwork->IELength - _BEACON_IE_OFFSET_));
3016 if (pbuf && ie_len > 0)
3017 rtw_remove_bcn_ie(padapter, pnetwork, _EXT_CAP_IE_);
3019 if ((pmlmepriv->ext_capab_ie_len > 0) &&
3020 (_rtw_memcmp(pmlmepriv->ext_capab_ie_data, null_extcap_data, sizeof(null_extcap_data)) == _FALSE))
3021 rtw_add_bcn_ie(padapter, pnetwork, _EXT_CAP_IE_, pmlmepriv->ext_capab_ie_data, pmlmepriv->ext_capab_ie_len);
3025 static void update_bcn_erpinfo_ie(_adapter *padapter)
3027 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
3028 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
3029 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
3030 WLAN_BSSID_EX *pnetwork = &(pmlmeinfo->network);
3031 unsigned char *p, *ie = pnetwork->IEs;
3034 RTW_INFO("%s, ERP_enable=%d\n", __FUNCTION__, pmlmeinfo->ERP_enable);
3036 if (!pmlmeinfo->ERP_enable)
3039 /* parsing ERP_IE */
3040 p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _ERPINFO_IE_, &len, (pnetwork->IELength - _BEACON_IE_OFFSET_));
3042 PNDIS_802_11_VARIABLE_IEs pIE = (PNDIS_802_11_VARIABLE_IEs)p;
3044 if (pmlmepriv->num_sta_non_erp == 1)
3045 pIE->data[0] |= RTW_ERP_INFO_NON_ERP_PRESENT | RTW_ERP_INFO_USE_PROTECTION;
3047 pIE->data[0] &= ~(RTW_ERP_INFO_NON_ERP_PRESENT | RTW_ERP_INFO_USE_PROTECTION);
3049 if (pmlmepriv->num_sta_no_short_preamble > 0)
3050 pIE->data[0] |= RTW_ERP_INFO_BARKER_PREAMBLE_MODE;
3052 pIE->data[0] &= ~(RTW_ERP_INFO_BARKER_PREAMBLE_MODE);
3054 ERP_IE_handler(padapter, pIE);
3059 static void update_bcn_htcap_ie(_adapter *padapter)
3061 RTW_INFO("%s\n", __FUNCTION__);
3065 static void update_bcn_htinfo_ie(_adapter *padapter)
3067 #ifdef CONFIG_80211N_HT
3069 u8 beacon_updated = _FALSE;
3070 u32 sta_info_update_type = STA_INFO_UPDATE_NONE;
3072 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
3073 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
3074 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
3075 WLAN_BSSID_EX *pnetwork = &(pmlmeinfo->network);
3076 unsigned char *p, *ie = pnetwork->IEs;
3079 if (pmlmepriv->htpriv.ht_option == _FALSE)
3082 if (pmlmeinfo->HT_info_enable != 1)
3086 RTW_INFO("%s current operation mode=0x%X\n",
3087 __FUNCTION__, pmlmepriv->ht_op_mode);
3089 RTW_INFO("num_sta_40mhz_intolerant(%d), 20mhz_width_req(%d), intolerant_ch_rpt(%d), olbc(%d)\n",
3090 pmlmepriv->num_sta_40mhz_intolerant, pmlmepriv->ht_20mhz_width_req, pmlmepriv->ht_intolerant_ch_reported, ATOMIC_READ(&pmlmepriv->olbc));
3092 /*parsing HT_INFO_IE, currently only update ht_op_mode - pht_info->infos[1] & pht_info->infos[2] for wifi logo test*/
3093 p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_ADD_INFO_IE_, &len, (pnetwork->IELength - _BEACON_IE_OFFSET_));
3095 struct HT_info_element *pht_info = NULL;
3097 pht_info = (struct HT_info_element *)(p + 2);
3099 /* for STA Channel Width/Secondary Channel Offset*/
3100 if ((pmlmepriv->sw_to_20mhz == 0) && (pmlmeext->cur_channel <= 14)) {
3101 if ((pmlmepriv->num_sta_40mhz_intolerant > 0) || (pmlmepriv->ht_20mhz_width_req == _TRUE)
3102 || (pmlmepriv->ht_intolerant_ch_reported == _TRUE) || (ATOMIC_READ(&pmlmepriv->olbc) == _TRUE)) {
3103 SET_HT_OP_ELE_2ND_CHL_OFFSET(pht_info, 0);
3104 SET_HT_OP_ELE_STA_CHL_WIDTH(pht_info, 0);
3106 pmlmepriv->sw_to_20mhz = 1;
3108 sta_info_update_type |= STA_INFO_UPDATE_BW;
3109 beacon_updated = _TRUE;
3112 RTW_INFO("%s:switching to 20Mhz\n", __FUNCTION__);
3114 /*TODO : cur_bwmode/cur_ch_offset switches to 20Mhz*/
3118 if ((pmlmepriv->num_sta_40mhz_intolerant == 0) && (pmlmepriv->ht_20mhz_width_req == _FALSE)
3119 && (pmlmepriv->ht_intolerant_ch_reported == _FALSE) && (ATOMIC_READ(&pmlmepriv->olbc) == _FALSE)) {
3121 if (pmlmeext->cur_bwmode >= CHANNEL_WIDTH_40) {
3123 SET_HT_OP_ELE_STA_CHL_WIDTH(pht_info, 1);
3125 SET_HT_OP_ELE_2ND_CHL_OFFSET(pht_info,
3126 (pmlmeext->cur_ch_offset == HAL_PRIME_CHNL_OFFSET_LOWER) ?
3127 HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE : HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW);
3129 pmlmepriv->sw_to_20mhz = 0;
3131 sta_info_update_type |= STA_INFO_UPDATE_BW;
3132 beacon_updated = _TRUE;
3135 RTW_INFO("%s:switching back to 40Mhz\n", __FUNCTION__);
3140 /* to update ht_op_mode*/
3141 *(u16 *)(pht_info->infos + 1) = cpu_to_le16(pmlmepriv->ht_op_mode);
3145 /*associated_clients_update(padapter, beacon_updated, sta_info_update_type);*/
3146 #endif /* CONFIG_80211N_HT */
3149 static void update_bcn_rsn_ie(_adapter *padapter)
3151 RTW_INFO("%s\n", __FUNCTION__);
3155 static void update_bcn_wpa_ie(_adapter *padapter)
3157 RTW_INFO("%s\n", __FUNCTION__);
3161 static void update_bcn_wmm_ie(_adapter *padapter)
3163 RTW_INFO("%s\n", __FUNCTION__);
3167 static void update_bcn_wps_ie(_adapter *padapter)
3169 u8 *pwps_ie = NULL, *pwps_ie_src, *premainder_ie, *pbackup_remainder_ie = NULL;
3170 uint wps_ielen = 0, wps_offset, remainder_ielen;
3171 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
3172 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
3173 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
3174 WLAN_BSSID_EX *pnetwork = &(pmlmeinfo->network);
3175 unsigned char *ie = pnetwork->IEs;
3176 u32 ielen = pnetwork->IELength;
3179 RTW_INFO("%s\n", __FUNCTION__);
3181 pwps_ie = rtw_get_wps_ie(ie + _FIXED_IE_LENGTH_, ielen - _FIXED_IE_LENGTH_, NULL, &wps_ielen);
3183 if (pwps_ie == NULL || wps_ielen == 0)
3186 pwps_ie_src = pmlmepriv->wps_beacon_ie;
3187 if (pwps_ie_src == NULL)
3190 wps_offset = (uint)(pwps_ie - ie);
3192 premainder_ie = pwps_ie + wps_ielen;
3194 remainder_ielen = ielen - wps_offset - wps_ielen;
3196 if (remainder_ielen > 0) {
3197 pbackup_remainder_ie = rtw_malloc(remainder_ielen);
3198 if (pbackup_remainder_ie)
3199 _rtw_memcpy(pbackup_remainder_ie, premainder_ie, remainder_ielen);
3202 wps_ielen = (uint)pwps_ie_src[1];/* to get ie data len */
3203 if ((wps_offset + wps_ielen + 2 + remainder_ielen) <= MAX_IE_SZ) {
3204 _rtw_memcpy(pwps_ie, pwps_ie_src, wps_ielen + 2);
3205 pwps_ie += (wps_ielen + 2);
3207 if (pbackup_remainder_ie)
3208 _rtw_memcpy(pwps_ie, pbackup_remainder_ie, remainder_ielen);
3210 /* update IELength */
3211 pnetwork->IELength = wps_offset + (wps_ielen + 2) + remainder_ielen;
3214 if (pbackup_remainder_ie)
3215 rtw_mfree(pbackup_remainder_ie, remainder_ielen);
3217 /* deal with the case without set_tx_beacon_cmd() in update_beacon() */
3218 #if defined(CONFIG_INTERRUPT_BASED_TXBCN) || defined(CONFIG_PCI_HCI)
3219 if ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE) {
3221 rtw_get_wps_attr_content(pwps_ie_src, wps_ielen, WPS_ATTR_SELECTED_REGISTRAR, (u8 *)(&sr), NULL);
3224 set_fwstate(pmlmepriv, WIFI_UNDER_WPS);
3225 RTW_INFO("%s, set WIFI_UNDER_WPS\n", __func__);
3227 clr_fwstate(pmlmepriv, WIFI_UNDER_WPS);
3228 RTW_INFO("%s, clr WIFI_UNDER_WPS\n", __func__);
3234 static void update_bcn_p2p_ie(_adapter *padapter)
3239 static void update_bcn_vendor_spec_ie(_adapter *padapter, u8 *oui)
3241 RTW_INFO("%s\n", __FUNCTION__);
3243 if (_rtw_memcmp(RTW_WPA_OUI, oui, 4))
3244 update_bcn_wpa_ie(padapter);
3245 else if (_rtw_memcmp(WMM_OUI, oui, 4))
3246 update_bcn_wmm_ie(padapter);
3247 else if (_rtw_memcmp(WPS_OUI, oui, 4))
3248 update_bcn_wps_ie(padapter);
3249 else if (_rtw_memcmp(P2P_OUI, oui, 4))
3250 update_bcn_p2p_ie(padapter);
3252 RTW_INFO("unknown OUI type!\n");
3257 void _update_beacon(_adapter *padapter, u8 ie_id, u8 *oui, u8 tx, const char *tag)
3260 struct mlme_priv *pmlmepriv;
3261 struct mlme_ext_priv *pmlmeext;
3262 bool updated = 1; /* treat as upadated by default */
3267 pmlmepriv = &(padapter->mlmepriv);
3268 pmlmeext = &(padapter->mlmeextpriv);
3270 if (pmlmeext->bstart_bss == _FALSE)
3273 _enter_critical_bh(&pmlmepriv->bcn_update_lock, &irqL);
3277 update_BCNTIM(padapter);
3281 update_bcn_erpinfo_ie(padapter);
3284 case _HT_CAPABILITY_IE_:
3285 update_bcn_htcap_ie(padapter);
3289 update_bcn_rsn_ie(padapter);
3292 case _HT_ADD_INFO_IE_:
3293 update_bcn_htinfo_ie(padapter);
3297 update_bcn_ext_capab_ie(padapter);
3300 #ifdef CONFIG_RTW_MESH
3301 case WLAN_EID_MESH_CONFIG:
3302 updated = rtw_mesh_update_bss_peering_status(padapter, &(pmlmeext->mlmext_info.network));
3303 updated |= rtw_mesh_update_bss_formation_info(padapter, &(pmlmeext->mlmext_info.network));
3304 updated |= rtw_mesh_update_bss_forwarding_state(padapter, &(pmlmeext->mlmext_info.network));
3308 case _VENDOR_SPECIFIC_IE_:
3309 update_bcn_vendor_spec_ie(padapter, oui);
3318 pmlmepriv->update_bcn = _TRUE;
3320 _exit_critical_bh(&pmlmepriv->bcn_update_lock, &irqL);
3322 #ifndef CONFIG_INTERRUPT_BASED_TXBCN
3323 #if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI) || defined(CONFIG_PCI_BCN_POLLING)
3324 if (tx && updated) {
3325 /* send_beacon(padapter); */ /* send_beacon must execute on TSR level */
3327 RTW_INFO(FUNC_ADPT_FMT" ie_id:%u - %s\n", FUNC_ADPT_ARG(padapter), ie_id, tag);
3328 set_tx_beacon_cmd(padapter);
3332 /* PCI will issue beacon when BCN interrupt occurs. */
3335 #endif /* !CONFIG_INTERRUPT_BASED_TXBCN */
3338 #ifdef CONFIG_80211N_HT
3340 void rtw_process_public_act_bsscoex(_adapter *padapter, u8 *pframe, uint frame_len)
3342 struct sta_info *psta;
3343 struct sta_priv *pstapriv = &padapter->stapriv;
3344 u8 beacon_updated = _FALSE;
3345 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
3346 u8 *frame_body = pframe + sizeof(struct rtw_ieee80211_hdr_3addr);
3347 uint frame_body_len = frame_len - sizeof(struct rtw_ieee80211_hdr_3addr);
3348 u8 category, action;
3350 psta = rtw_get_stainfo(pstapriv, get_addr2_ptr(pframe));
3355 category = frame_body[0];
3356 action = frame_body[1];
3358 if (frame_body_len > 0) {
3359 if ((frame_body[2] == EID_BSSCoexistence) && (frame_body[3] > 0)) {
3360 u8 ie_data = frame_body[4];
3362 if (ie_data & RTW_WLAN_20_40_BSS_COEX_40MHZ_INTOL) {
3363 if (psta->ht_40mhz_intolerant == 0) {
3364 psta->ht_40mhz_intolerant = 1;
3365 pmlmepriv->num_sta_40mhz_intolerant++;
3366 beacon_updated = _TRUE;
3368 } else if (ie_data & RTW_WLAN_20_40_BSS_COEX_20MHZ_WIDTH_REQ) {
3369 if (pmlmepriv->ht_20mhz_width_req == _FALSE) {
3370 pmlmepriv->ht_20mhz_width_req = _TRUE;
3371 beacon_updated = _TRUE;
3374 beacon_updated = _FALSE;
3378 if (frame_body_len > 8) {
3379 /* if EID_BSSIntolerantChlReport ie exists */
3380 if ((frame_body[5] == EID_BSSIntolerantChlReport) && (frame_body[6] > 0)) {
3382 if (pmlmepriv->ht_intolerant_ch_reported == _FALSE) {
3383 pmlmepriv->ht_intolerant_ch_reported = _TRUE;
3384 beacon_updated = _TRUE;
3389 if (beacon_updated) {
3391 update_beacon(padapter, _HT_ADD_INFO_IE_, NULL, _TRUE);
3393 associated_stainfo_update(padapter, psta, STA_INFO_UPDATE_BW);
3400 void rtw_process_ht_action_smps(_adapter *padapter, u8 *ta, u8 ctrl_field)
3402 u8 e_field, m_field;
3403 struct sta_info *psta;
3404 struct sta_priv *pstapriv = &padapter->stapriv;
3406 psta = rtw_get_stainfo(pstapriv, ta);
3410 e_field = (ctrl_field & BIT(0)) ? 1 : 0; /*SM Power Save Enabled*/
3411 m_field = (ctrl_field & BIT(1)) ? 1 : 0; /*SM Mode, 0:static SMPS, 1:dynamic SMPS*/
3414 if (m_field) { /*mode*/
3415 psta->htpriv.smps_cap = WLAN_HT_CAP_SM_PS_DYNAMIC;
3416 RTW_ERR("Don't support dynamic SMPS\n");
3419 psta->htpriv.smps_cap = WLAN_HT_CAP_SM_PS_STATIC;
3422 psta->htpriv.smps_cap = WLAN_HT_CAP_SM_PS_DISABLED;
3425 if (psta->htpriv.smps_cap != WLAN_HT_CAP_SM_PS_DYNAMIC)
3426 rtw_ssmps_wk_cmd(padapter, psta, e_field, 1);
3431 Set to 0 (HT pure) under the followign conditions
3432 - all STAs in the BSS are 20/40 MHz HT in 20/40 MHz BSS or
3433 - all STAs in the BSS are 20 MHz HT in 20 MHz BSS
3434 Set to 1 (HT non-member protection) if there may be non-HT STAs
3435 in both the primary and the secondary channel
3436 Set to 2 if only HT STAs are associated in BSS,
3437 however and at least one 20 MHz HT STA is associated
3438 Set to 3 (HT mixed mode) when one or more non-HT STAs are associated
3439 (currently non-GF HT station is considered as non-HT STA also)
3441 int rtw_ht_operation_update(_adapter *padapter)
3443 u16 cur_op_mode, new_op_mode;
3444 int op_mode_changes = 0;
3445 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
3446 struct ht_priv *phtpriv_ap = &pmlmepriv->htpriv;
3448 if (pmlmepriv->htpriv.ht_option == _FALSE)
3451 /*if (!iface->conf->ieee80211n || iface->conf->ht_op_mode_fixed)
3454 RTW_INFO("%s current operation mode=0x%X\n",
3455 __FUNCTION__, pmlmepriv->ht_op_mode);
3457 if (!(pmlmepriv->ht_op_mode & HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT)
3458 && pmlmepriv->num_sta_ht_no_gf) {
3459 pmlmepriv->ht_op_mode |=
3460 HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT;
3462 } else if ((pmlmepriv->ht_op_mode &
3463 HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT) &&
3464 pmlmepriv->num_sta_ht_no_gf == 0) {
3465 pmlmepriv->ht_op_mode &=
3466 ~HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT;
3470 if (!(pmlmepriv->ht_op_mode & HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT) &&
3471 (pmlmepriv->num_sta_no_ht || ATOMIC_READ(&pmlmepriv->olbc_ht))) {
3472 pmlmepriv->ht_op_mode |= HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT;
3474 } else if ((pmlmepriv->ht_op_mode &
3475 HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT) &&
3476 (pmlmepriv->num_sta_no_ht == 0 && !ATOMIC_READ(&pmlmepriv->olbc_ht))) {
3477 pmlmepriv->ht_op_mode &=
3478 ~HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT;
3482 /* Note: currently we switch to the MIXED op mode if HT non-greenfield
3483 * station is associated. Probably it's a theoretical case, since
3484 * it looks like all known HT STAs support greenfield.
3487 if (pmlmepriv->num_sta_no_ht /*||
3488 (pmlmepriv->ht_op_mode & HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT)*/)
3489 new_op_mode = OP_MODE_MIXED;
3490 else if ((phtpriv_ap->ht_cap.cap_info & IEEE80211_HT_CAP_SUP_WIDTH)
3491 && pmlmepriv->num_sta_ht_20mhz)
3492 new_op_mode = OP_MODE_20MHZ_HT_STA_ASSOCED;
3493 else if (ATOMIC_READ(&pmlmepriv->olbc_ht))
3494 new_op_mode = OP_MODE_MAY_BE_LEGACY_STAS;
3496 new_op_mode = OP_MODE_PURE;
3498 cur_op_mode = pmlmepriv->ht_op_mode & HT_INFO_OPERATION_MODE_OP_MODE_MASK;
3499 if (cur_op_mode != new_op_mode) {
3500 pmlmepriv->ht_op_mode &= ~HT_INFO_OPERATION_MODE_OP_MODE_MASK;
3501 pmlmepriv->ht_op_mode |= new_op_mode;
3505 RTW_INFO("%s new operation mode=0x%X changes=%d\n",
3506 __FUNCTION__, pmlmepriv->ht_op_mode, op_mode_changes);
3508 return op_mode_changes;
3512 #endif /* CONFIG_80211N_HT */
3514 void associated_clients_update(_adapter *padapter, u8 updated, u32 sta_info_type)
3516 /* update associcated stations cap. */
3517 if (updated == _TRUE) {
3519 _list *phead, *plist;
3520 struct sta_info *psta = NULL;
3521 struct sta_priv *pstapriv = &padapter->stapriv;
3523 _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
3525 phead = &pstapriv->asoc_list;
3526 plist = get_next(phead);
3528 /* check asoc_queue */
3529 while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {
3530 psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);
3532 plist = get_next(plist);
3534 associated_stainfo_update(padapter, psta, sta_info_type);
3537 _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
3543 /* called > TSR LEVEL for USB or SDIO Interface*/
3544 void bss_cap_update_on_sta_join(_adapter *padapter, struct sta_info *psta)
3546 u8 beacon_updated = _FALSE;
3547 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
3548 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
3552 if (!(psta->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) &&
3553 !psta->no_short_preamble_set) {
3554 psta->no_short_preamble_set = 1;
3555 pmlmepriv->num_sta_no_short_preamble++;
3556 if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) &&
3557 (pmlmepriv->num_sta_no_short_preamble == 1))
3558 ieee802_11_set_beacons(hapd->iface);
3563 if (!(psta->flags & WLAN_STA_SHORT_PREAMBLE)) {
3564 if (!psta->no_short_preamble_set) {
3565 psta->no_short_preamble_set = 1;
3567 pmlmepriv->num_sta_no_short_preamble++;
3569 if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) &&
3570 (pmlmepriv->num_sta_no_short_preamble == 1))
3571 beacon_updated = _TRUE;
3574 if (psta->no_short_preamble_set) {
3575 psta->no_short_preamble_set = 0;
3577 pmlmepriv->num_sta_no_short_preamble--;
3579 if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) &&
3580 (pmlmepriv->num_sta_no_short_preamble == 0))
3581 beacon_updated = _TRUE;
3586 if (psta->flags & WLAN_STA_NONERP && !psta->nonerp_set) {
3587 psta->nonerp_set = 1;
3588 pmlmepriv->num_sta_non_erp++;
3589 if (pmlmepriv->num_sta_non_erp == 1)
3590 ieee802_11_set_beacons(hapd->iface);
3594 if (psta->flags & WLAN_STA_NONERP) {
3595 if (!psta->nonerp_set) {
3596 psta->nonerp_set = 1;
3598 pmlmepriv->num_sta_non_erp++;
3600 if (pmlmepriv->num_sta_non_erp == 1) {
3601 beacon_updated = _TRUE;
3602 update_beacon(padapter, _ERPINFO_IE_, NULL, _FALSE);
3607 if (psta->nonerp_set) {
3608 psta->nonerp_set = 0;
3610 pmlmepriv->num_sta_non_erp--;
3612 if (pmlmepriv->num_sta_non_erp == 0) {
3613 beacon_updated = _TRUE;
3614 update_beacon(padapter, _ERPINFO_IE_, NULL, _FALSE);
3622 if (!(psta->capability & WLAN_CAPABILITY_SHORT_SLOT) &&
3623 !psta->no_short_slot_time_set) {
3624 psta->no_short_slot_time_set = 1;
3625 pmlmepriv->num_sta_no_short_slot_time++;
3626 if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) &&
3627 (pmlmepriv->num_sta_no_short_slot_time == 1))
3628 ieee802_11_set_beacons(hapd->iface);
3632 if (!(psta->capability & WLAN_CAPABILITY_SHORT_SLOT)) {
3633 if (!psta->no_short_slot_time_set) {
3634 psta->no_short_slot_time_set = 1;
3636 pmlmepriv->num_sta_no_short_slot_time++;
3638 if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) &&
3639 (pmlmepriv->num_sta_no_short_slot_time == 1))
3640 beacon_updated = _TRUE;
3643 if (psta->no_short_slot_time_set) {
3644 psta->no_short_slot_time_set = 0;
3646 pmlmepriv->num_sta_no_short_slot_time--;
3648 if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) &&
3649 (pmlmepriv->num_sta_no_short_slot_time == 0))
3650 beacon_updated = _TRUE;
3654 #ifdef CONFIG_80211N_HT
3655 if(padapter->registrypriv.ht_enable &&
3656 is_supported_ht(padapter->registrypriv.wireless_mode)) {
3657 if (psta->flags & WLAN_STA_HT) {
3658 u16 ht_capab = le16_to_cpu(psta->htpriv.ht_cap.cap_info);
3660 RTW_INFO("HT: STA " MAC_FMT " HT Capabilities Info: 0x%04x\n",
3661 MAC_ARG(psta->cmn.mac_addr), ht_capab);
3663 if (psta->no_ht_set) {
3664 psta->no_ht_set = 0;
3665 pmlmepriv->num_sta_no_ht--;
3668 if ((ht_capab & IEEE80211_HT_CAP_GRN_FLD) == 0) {
3669 if (!psta->no_ht_gf_set) {
3670 psta->no_ht_gf_set = 1;
3671 pmlmepriv->num_sta_ht_no_gf++;
3673 RTW_INFO("%s STA " MAC_FMT " - no "
3674 "greenfield, num of non-gf stations %d\n",
3675 __FUNCTION__, MAC_ARG(psta->cmn.mac_addr),
3676 pmlmepriv->num_sta_ht_no_gf);
3679 if ((ht_capab & IEEE80211_HT_CAP_SUP_WIDTH) == 0) {
3680 if (!psta->ht_20mhz_set) {
3681 psta->ht_20mhz_set = 1;
3682 pmlmepriv->num_sta_ht_20mhz++;
3684 RTW_INFO("%s STA " MAC_FMT " - 20 MHz HT, "
3685 "num of 20MHz HT STAs %d\n",
3686 __FUNCTION__, MAC_ARG(psta->cmn.mac_addr),
3687 pmlmepriv->num_sta_ht_20mhz);
3690 if (((ht_capab & RTW_IEEE80211_HT_CAP_40MHZ_INTOLERANT) != 0) &&
3691 (psta->ht_40mhz_intolerant == 0)) {
3692 psta->ht_40mhz_intolerant = 1;
3693 pmlmepriv->num_sta_40mhz_intolerant++;
3694 RTW_INFO("%s STA " MAC_FMT " - 40MHZ_INTOLERANT, ",
3695 __FUNCTION__, MAC_ARG(psta->cmn.mac_addr));
3699 if (!psta->no_ht_set) {
3700 psta->no_ht_set = 1;
3701 pmlmepriv->num_sta_no_ht++;
3703 if (pmlmepriv->htpriv.ht_option == _TRUE) {
3704 RTW_INFO("%s STA " MAC_FMT
3705 " - no HT, num of non-HT stations %d\n",
3706 __FUNCTION__, MAC_ARG(psta->cmn.mac_addr),
3707 pmlmepriv->num_sta_no_ht);
3711 if (rtw_ht_operation_update(padapter) > 0) {
3712 update_beacon(padapter, _HT_CAPABILITY_IE_, NULL, _FALSE);
3713 update_beacon(padapter, _HT_ADD_INFO_IE_, NULL, _FALSE);
3714 beacon_updated = _TRUE;
3717 #endif /* CONFIG_80211N_HT */
3719 #ifdef CONFIG_RTW_MESH
3720 if (MLME_IS_MESH(padapter)) {
3721 struct sta_priv *pstapriv = &padapter->stapriv;
3723 update_beacon(padapter, WLAN_EID_MESH_CONFIG, NULL, _FALSE);
3724 if (pstapriv->asoc_list_cnt == 1)
3725 _set_timer(&padapter->mesh_atlm_param_req_timer, 0);
3726 beacon_updated = _TRUE;
3731 update_beacon(padapter, 0xFF, NULL, _TRUE);
3733 /* update associcated stations cap. */
3734 associated_clients_update(padapter, beacon_updated, STA_INFO_UPDATE_ALL);
3736 RTW_INFO("%s, updated=%d\n", __func__, beacon_updated);
3740 u8 bss_cap_update_on_sta_leave(_adapter *padapter, struct sta_info *psta)
3742 u8 beacon_updated = _FALSE;
3743 struct sta_priv *pstapriv = &padapter->stapriv;
3744 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
3745 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
3748 return beacon_updated;
3750 if (rtw_tim_map_is_set(padapter, pstapriv->tim_bitmap, psta->cmn.aid)) {
3751 rtw_tim_map_clear(padapter, pstapriv->tim_bitmap, psta->cmn.aid);
3752 beacon_updated = _TRUE;
3753 update_beacon(padapter, _TIM_IE_, NULL, _FALSE);
3756 if (psta->no_short_preamble_set) {
3757 psta->no_short_preamble_set = 0;
3758 pmlmepriv->num_sta_no_short_preamble--;
3759 if (pmlmeext->cur_wireless_mode > WIRELESS_11B
3760 && pmlmepriv->num_sta_no_short_preamble == 0)
3761 beacon_updated = _TRUE;
3764 if (psta->nonerp_set) {
3765 psta->nonerp_set = 0;
3766 pmlmepriv->num_sta_non_erp--;
3767 if (pmlmepriv->num_sta_non_erp == 0) {
3768 beacon_updated = _TRUE;
3769 update_beacon(padapter, _ERPINFO_IE_, NULL, _FALSE);
3773 if (psta->no_short_slot_time_set) {
3774 psta->no_short_slot_time_set = 0;
3775 pmlmepriv->num_sta_no_short_slot_time--;
3776 if (pmlmeext->cur_wireless_mode > WIRELESS_11B
3777 && pmlmepriv->num_sta_no_short_slot_time == 0)
3778 beacon_updated = _TRUE;
3781 #ifdef CONFIG_80211N_HT
3782 if (psta->no_ht_gf_set) {
3783 psta->no_ht_gf_set = 0;
3784 pmlmepriv->num_sta_ht_no_gf--;
3787 if (psta->no_ht_set) {
3788 psta->no_ht_set = 0;
3789 pmlmepriv->num_sta_no_ht--;
3792 if (psta->ht_20mhz_set) {
3793 psta->ht_20mhz_set = 0;
3794 pmlmepriv->num_sta_ht_20mhz--;
3797 if (psta->ht_40mhz_intolerant) {
3798 psta->ht_40mhz_intolerant = 0;
3799 if (pmlmepriv->num_sta_40mhz_intolerant > 0)
3800 pmlmepriv->num_sta_40mhz_intolerant--;
3805 if (rtw_ht_operation_update(padapter) > 0) {
3806 update_beacon(padapter, _HT_CAPABILITY_IE_, NULL, _FALSE);
3807 update_beacon(padapter, _HT_ADD_INFO_IE_, NULL, _FALSE);
3809 #endif /* CONFIG_80211N_HT */
3811 #ifdef CONFIG_RTW_MESH
3812 if (MLME_IS_MESH(padapter)) {
3813 update_beacon(padapter, WLAN_EID_MESH_CONFIG, NULL, _FALSE);
3814 if (pstapriv->asoc_list_cnt == 0)
3815 _cancel_timer_ex(&padapter->mesh_atlm_param_req_timer);
3816 beacon_updated = _TRUE;
3820 if (beacon_updated == _TRUE)
3821 update_beacon(padapter, 0xFF, NULL, _TRUE);
3824 /* update associated stations cap. */
3825 associated_clients_update(padapter, beacon_updated, STA_INFO_UPDATE_ALL); /* move it to avoid deadlock */
3828 RTW_INFO("%s, updated=%d\n", __func__, beacon_updated);
3830 return beacon_updated;
3834 u8 ap_free_sta(_adapter *padapter, struct sta_info *psta, bool active, u16 reason, bool enqueue)
3837 u8 beacon_updated = _FALSE;
3840 return beacon_updated;
3842 if (active == _TRUE) {
3843 #ifdef CONFIG_80211N_HT
3844 /* tear down Rx AMPDU */
3845 send_delba(padapter, 0, psta->cmn.mac_addr);/* recipient */
3847 /* tear down TX AMPDU */
3848 send_delba(padapter, 1, psta->cmn.mac_addr);/* */ /* originator */
3850 #endif /* CONFIG_80211N_HT */
3852 if (!MLME_IS_MESH(padapter))
3853 issue_deauth(padapter, psta->cmn.mac_addr, reason);
3856 #ifdef CONFIG_RTW_MESH
3857 if (MLME_IS_MESH(padapter))
3858 rtw_mesh_path_flush_by_nexthop(psta);
3861 #ifdef CONFIG_BEAMFORMING
3862 beamforming_wk_cmd(padapter, BEAMFORMING_CTRL_LEAVE, psta->cmn.mac_addr, ETH_ALEN, 1);
3865 #ifdef CONFIG_80211N_HT
3866 psta->htpriv.agg_enable_bitmap = 0x0;/* reset */
3867 psta->htpriv.candidate_tid_bitmap = 0x0;/* reset */
3870 /* clear cam entry / key */
3871 rtw_clearstakey_cmd(padapter, psta, enqueue);
3874 _enter_critical_bh(&psta->lock, &irqL);
3875 psta->state &= ~(_FW_LINKED | WIFI_UNDER_KEY_HANDSHAKE);
3877 if ((psta->auth_len != 0) && (psta->pauth_frame != NULL)) {
3878 rtw_mfree(psta->pauth_frame, psta->auth_len);
3879 psta->pauth_frame = NULL;
3882 _exit_critical_bh(&psta->lock, &irqL);
3884 if (!MLME_IS_MESH(padapter)) {
3885 #ifdef CONFIG_IOCTL_CFG80211
3886 #ifdef COMPAT_KERNEL_RELEASE
3887 rtw_cfg80211_indicate_sta_disassoc(padapter, psta->cmn.mac_addr, reason);
3888 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) && !defined(CONFIG_CFG80211_FORCE_COMPATIBLE_2_6_37_UNDER)
3889 rtw_cfg80211_indicate_sta_disassoc(padapter, psta->cmn.mac_addr, reason);
3890 #else /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) && !defined(CONFIG_CFG80211_FORCE_COMPATIBLE_2_6_37_UNDER) */
3891 /* will call rtw_cfg80211_indicate_sta_disassoc() in cmd_thread for old API context */
3892 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) && !defined(CONFIG_CFG80211_FORCE_COMPATIBLE_2_6_37_UNDER) */
3894 rtw_indicate_sta_disassoc_event(padapter, psta);
3898 beacon_updated = bss_cap_update_on_sta_leave(padapter, psta);
3900 report_del_sta_event(padapter, psta->cmn.mac_addr, reason, enqueue, _FALSE);
3902 return beacon_updated;
3906 int rtw_ap_inform_ch_switch(_adapter *padapter, u8 new_ch, u8 ch_offset)
3909 _list *phead, *plist;
3911 struct sta_info *psta = NULL;
3912 struct sta_priv *pstapriv = &padapter->stapriv;
3913 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3914 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
3915 u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
3917 if ((pmlmeinfo->state & 0x03) != WIFI_FW_AP_STATE)
3920 RTW_INFO(FUNC_NDEV_FMT" with ch:%u, offset:%u\n",
3921 FUNC_NDEV_ARG(padapter->pnetdev), new_ch, ch_offset);
3923 _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
3924 phead = &pstapriv->asoc_list;
3925 plist = get_next(phead);
3927 /* for each sta in asoc_queue */
3928 while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {
3929 psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);
3930 plist = get_next(plist);
3932 issue_action_spct_ch_switch(padapter, psta->cmn.mac_addr, new_ch, ch_offset);
3933 psta->expire_to = ((pstapriv->expire_to * 2) > 5) ? 5 : (pstapriv->expire_to * 2);
3935 _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
3937 issue_action_spct_ch_switch(padapter, bc_addr, new_ch, ch_offset);
3942 int rtw_sta_flush(_adapter *padapter, bool enqueue)
3945 _list *phead, *plist;
3947 struct sta_info *psta = NULL;
3948 struct sta_priv *pstapriv = &padapter->stapriv;
3949 u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
3951 char flush_list[NUM_STA];
3954 if (!MLME_IS_AP(padapter) && !MLME_IS_MESH(padapter))
3957 RTW_INFO(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(padapter->pnetdev));
3959 /* pick sta from sta asoc_queue */
3960 _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
3961 phead = &pstapriv->asoc_list;
3962 plist = get_next(phead);
3963 while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {
3966 psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);
3967 plist = get_next(plist);
3969 rtw_list_delete(&psta->asoc_list);
3970 pstapriv->asoc_list_cnt--;
3971 STA_SET_MESH_PLINK(psta, NULL);
3973 stainfo_offset = rtw_stainfo_offset(pstapriv, psta);
3974 if (stainfo_offset_valid(stainfo_offset))
3975 flush_list[flush_num++] = stainfo_offset;
3979 _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
3981 /* call ap_free_sta() for each sta picked */
3982 for (i = 0; i < flush_num; i++) {
3983 u8 sta_addr[ETH_ALEN];
3985 psta = rtw_get_stainfo_by_offset(pstapriv, flush_list[i]);
3986 _rtw_memcpy(sta_addr, psta->cmn.mac_addr, ETH_ALEN);
3988 ap_free_sta(padapter, psta, _TRUE, WLAN_REASON_DEAUTH_LEAVING, enqueue);
3989 #ifdef CONFIG_RTW_MESH
3990 if (MLME_IS_MESH(padapter))
3991 rtw_mesh_expire_peer(padapter, sta_addr);
3995 if (!MLME_IS_MESH(padapter))
3996 issue_deauth(padapter, bc_addr, WLAN_REASON_DEAUTH_LEAVING);
3998 associated_clients_update(padapter, _TRUE, STA_INFO_UPDATE_ALL);
4003 /* called > TSR LEVEL for USB or SDIO Interface*/
4004 void sta_info_update(_adapter *padapter, struct sta_info *psta)
4006 int flags = psta->flags;
4007 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
4010 /* update wmm cap. */
4011 if (WLAN_STA_WME & flags)
4012 psta->qos_option = 1;
4014 psta->qos_option = 0;
4016 if (pmlmepriv->qospriv.qos_option == 0)
4017 psta->qos_option = 0;
4020 #ifdef CONFIG_80211N_HT
4021 /* update 802.11n ht cap. */
4022 if (WLAN_STA_HT & flags) {
4023 psta->htpriv.ht_option = _TRUE;
4024 psta->qos_option = 1;
4026 psta->htpriv.smps_cap = (psta->htpriv.ht_cap.cap_info & IEEE80211_HT_CAP_SM_PS) >> 2;
4028 psta->htpriv.ht_option = _FALSE;
4030 if (pmlmepriv->htpriv.ht_option == _FALSE)
4031 psta->htpriv.ht_option = _FALSE;
4034 #ifdef CONFIG_80211AC_VHT
4035 /* update 802.11AC vht cap. */
4036 if (WLAN_STA_VHT & flags)
4037 psta->vhtpriv.vht_option = _TRUE;
4039 psta->vhtpriv.vht_option = _FALSE;
4041 if (pmlmepriv->vhtpriv.vht_option == _FALSE)
4042 psta->vhtpriv.vht_option = _FALSE;
4045 update_sta_info_apmode(padapter, psta);
4048 /* called >= TSR LEVEL for USB or SDIO Interface*/
4049 void ap_sta_info_defer_update(_adapter *padapter, struct sta_info *psta)
4051 if (psta->state & _FW_LINKED)
4052 rtw_hal_update_ra_mask(psta); /* DM_RATR_STA_INIT */
4054 /* restore hw setting from sw data structures */
4055 void rtw_ap_restore_network(_adapter *padapter)
4057 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4058 struct sta_priv *pstapriv = &padapter->stapriv;
4059 struct sta_info *psta;
4060 struct security_priv *psecuritypriv = &(padapter->securitypriv);
4062 _list *phead, *plist;
4063 u8 chk_alive_num = 0;
4064 char chk_alive_list[NUM_STA];
4067 rtw_setopmode_cmd(padapter
4068 , MLME_IS_AP(padapter) ? Ndis802_11APMode : Ndis802_11_mesh
4072 set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
4074 rtw_startbss_cmd(padapter, RTW_CMDF_DIRECTLY);
4076 if ((padapter->securitypriv.dot11PrivacyAlgrthm == _TKIP_) ||
4077 (padapter->securitypriv.dot11PrivacyAlgrthm == _AES_)) {
4078 /* restore group key, WEP keys is restored in ips_leave() */
4079 rtw_set_key(padapter, psecuritypriv, psecuritypriv->dot118021XGrpKeyid, 0, _FALSE);
4082 _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
4084 phead = &pstapriv->asoc_list;
4085 plist = get_next(phead);
4087 while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {
4090 psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);
4091 plist = get_next(plist);
4093 stainfo_offset = rtw_stainfo_offset(pstapriv, psta);
4094 if (stainfo_offset_valid(stainfo_offset))
4095 chk_alive_list[chk_alive_num++] = stainfo_offset;
4098 _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
4100 for (i = 0; i < chk_alive_num; i++) {
4101 psta = rtw_get_stainfo_by_offset(pstapriv, chk_alive_list[i]);
4104 RTW_INFO(FUNC_ADPT_FMT" sta_info is null\n", FUNC_ADPT_ARG(padapter));
4105 else if (psta->state & _FW_LINKED) {
4106 rtw_sta_media_status_rpt(padapter, psta, 1);
4107 Update_RA_Entry(padapter, psta);
4109 /* per sta pairwise key and settings */
4110 if ((padapter->securitypriv.dot11PrivacyAlgrthm == _TKIP_) ||
4111 (padapter->securitypriv.dot11PrivacyAlgrthm == _AES_))
4112 rtw_setstakey_cmd(padapter, psta, UNICAST_KEY, _FALSE);
4118 void start_ap_mode(_adapter *padapter)
4121 struct sta_info *psta = NULL;
4122 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
4123 struct sta_priv *pstapriv = &padapter->stapriv;
4124 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4125 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
4126 #ifdef CONFIG_CONCURRENT_MODE
4127 struct security_priv *psecuritypriv = &padapter->securitypriv;
4130 pmlmepriv->update_bcn = _FALSE;
4132 /*init_mlme_ap_info(padapter);*/
4134 pmlmeext->bstart_bss = _FALSE;
4136 pmlmepriv->num_sta_non_erp = 0;
4138 pmlmepriv->num_sta_no_short_slot_time = 0;
4140 pmlmepriv->num_sta_no_short_preamble = 0;
4142 pmlmepriv->num_sta_ht_no_gf = 0;
4143 #ifdef CONFIG_80211N_HT
4144 pmlmepriv->num_sta_no_ht = 0;
4145 #endif /* CONFIG_80211N_HT */
4146 pmlmeinfo->HT_info_enable = 0;
4147 pmlmeinfo->HT_caps_enable = 0;
4148 pmlmeinfo->HT_enable = 0;
4150 pmlmepriv->num_sta_ht_20mhz = 0;
4151 pmlmepriv->num_sta_40mhz_intolerant = 0;
4152 ATOMIC_SET(&pmlmepriv->olbc, _FALSE);
4153 ATOMIC_SET(&pmlmepriv->olbc_ht, _FALSE);
4155 #ifdef CONFIG_80211N_HT
4156 pmlmepriv->ht_20mhz_width_req = _FALSE;
4157 pmlmepriv->ht_intolerant_ch_reported = _FALSE;
4158 pmlmepriv->ht_op_mode = 0;
4159 pmlmepriv->sw_to_20mhz = 0;
4162 _rtw_memset(pmlmepriv->ext_capab_ie_data, 0, sizeof(pmlmepriv->ext_capab_ie_data));
4163 pmlmepriv->ext_capab_ie_len = 0;
4165 #ifdef CONFIG_CONCURRENT_MODE
4166 psecuritypriv->dot118021x_bmc_cam_id = INVALID_SEC_MAC_CAM_ID;
4169 for (i = 0 ; i < pstapriv->max_aid; i++)
4170 pstapriv->sta_aid[i] = NULL;
4172 psta = rtw_get_bcmc_stainfo(padapter);
4173 /*_enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL);*/
4175 rtw_free_stainfo(padapter, psta);
4176 /*_exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL);*/
4178 rtw_init_bcmc_stainfo(padapter);
4180 if (rtw_mi_get_ap_num(padapter))
4181 RTW_SET_SCAN_BAND_SKIP(padapter, BAND_5G);
4185 void rtw_ap_bcmc_sta_flush(_adapter *padapter)
4187 #ifdef CONFIG_CONCURRENT_MODE
4189 u8 *addr = adapter_mac_addr(padapter);
4191 cam_id = rtw_iface_bcmc_id_get(padapter);
4192 if (cam_id != INVALID_SEC_MAC_CAM_ID) {
4193 RTW_PRINT("clear group key for "ADPT_FMT" addr:"MAC_FMT", camid:%d\n",
4194 ADPT_ARG(padapter), MAC_ARG(addr), cam_id);
4195 clear_cam_entry(padapter, cam_id);
4196 rtw_camid_free(padapter, cam_id);
4197 rtw_iface_bcmc_id_set(padapter, INVALID_SEC_MAC_CAM_ID); /*init default value*/
4200 invalidate_cam_all(padapter);
4204 void stop_ap_mode(_adapter *padapter)
4206 u8 self_action = MLME_ACTION_UNKNOWN;
4207 struct sta_info *psta = NULL;
4208 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
4209 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4210 #ifdef CONFIG_SUPPORT_MULTI_BCN
4211 struct dvobj_priv *pdvobj = padapter->dvobj;
4215 RTW_INFO("%s -"ADPT_FMT"\n", __func__, ADPT_ARG(padapter));
4217 if (MLME_IS_AP(padapter))
4218 self_action = MLME_AP_STOPPED;
4219 else if (MLME_IS_MESH(padapter))
4220 self_action = MLME_MESH_STOPPED;
4224 pmlmepriv->update_bcn = _FALSE;
4225 /*pmlmeext->bstart_bss = _FALSE;*/
4226 padapter->netif_up = _FALSE;
4227 /* _rtw_spinlock_free(&pmlmepriv->bcn_update_lock); */
4229 /* reset and init security priv , this can refine with rtw_reset_securitypriv */
4230 _rtw_memset((unsigned char *)&padapter->securitypriv, 0, sizeof(struct security_priv));
4231 padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeOpen;
4232 padapter->securitypriv.ndisencryptstatus = Ndis802_11WEPDisabled;
4234 #ifdef CONFIG_DFS_MASTER
4235 rtw_dfs_rd_en_decision(padapter, self_action, 0);
4238 /* free scan queue */
4239 rtw_free_network_queue(padapter, _TRUE);
4241 #if CONFIG_RTW_MACADDR_ACL
4242 rtw_macaddr_acl_clear(padapter, RTW_ACL_PERIOD_BSS);
4245 rtw_sta_flush(padapter, _TRUE);
4246 rtw_ap_bcmc_sta_flush(padapter);
4248 /* free_assoc_sta_resources */
4249 rtw_free_all_stainfo(padapter);
4251 psta = rtw_get_bcmc_stainfo(padapter);
4253 rtw_sta_mstatus_disc_rpt(padapter, psta->cmn.mac_id);
4254 /* _enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL); */
4255 rtw_free_stainfo(padapter, psta);
4256 /*_exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL);*/
4259 rtw_free_mlme_priv_ie_data(pmlmepriv);
4261 #ifdef CONFIG_SUPPORT_MULTI_BCN
4262 if (pmlmeext->bstart_bss == _TRUE) {
4263 #ifdef CONFIG_FW_HANDLE_TXBCN
4264 u8 free_apid = CONFIG_LIMITED_AP_NUM;
4267 _enter_critical_bh(&pdvobj->ap_if_q.lock, &irqL);
4269 if (pdvobj->nr_ap_if > 0)
4270 pdvobj->inter_bcn_space = DEFAULT_BCN_INTERVAL / pdvobj->nr_ap_if;
4272 pdvobj->inter_bcn_space = DEFAULT_BCN_INTERVAL;
4273 #ifdef CONFIG_FW_HANDLE_TXBCN
4274 rtw_ap_release_vapid(pdvobj, padapter->vap_id);
4275 free_apid = padapter->vap_id;
4276 padapter->vap_id = CONFIG_LIMITED_AP_NUM;
4278 rtw_list_delete(&padapter->list);
4279 _exit_critical_bh(&pdvobj->ap_if_q.lock, &irqL);
4280 #ifdef CONFIG_FW_HANDLE_TXBCN
4281 rtw_ap_mbid_bcn_dis(padapter, free_apid);
4284 #ifdef CONFIG_SWTIMER_BASED_TXBCN
4285 rtw_hal_set_hwreg(padapter, HW_VAR_BEACON_INTERVAL, (u8 *)(&pdvobj->inter_bcn_space));
4287 if (pdvobj->nr_ap_if == 0)
4288 _cancel_timer_ex(&pdvobj->txbcn_timer);
4293 pmlmeext->bstart_bss = _FALSE;
4295 rtw_hal_rcr_set_chk_bssid(padapter, self_action);
4297 #ifdef CONFIG_HW_P0_TSF_SYNC
4298 correct_TSF(padapter, self_action);
4301 #ifdef CONFIG_BT_COEXIST
4302 rtw_btcoex_MediaStatusNotify(padapter, 0); /* disconnect */
4307 #endif /* CONFIG_NATIVEAP_MLME */
4309 void rtw_ap_update_bss_chbw(_adapter *adapter, WLAN_BSSID_EX *bss, u8 ch, u8 bw, u8 offset)
4311 #define UPDATE_VHT_CAP 1
4312 #define UPDATE_HT_CAP 1
4313 #ifdef CONFIG_80211AC_VHT
4314 struct vht_priv *vhtpriv = &adapter->mlmepriv.vhtpriv;
4319 u8 old_ch = bss->Configuration.DSConfig;
4320 bool change_band = _FALSE;
4322 if ((ch <= 14 && old_ch >= 36) || (ch >= 36 && old_ch <= 14))
4323 change_band = _TRUE;
4325 /* update channel in IE */
4326 p = rtw_get_ie((bss->IEs + sizeof(NDIS_802_11_FIXED_IEs)), _DSSET_IE_, &ie_len, (bss->IELength - sizeof(NDIS_802_11_FIXED_IEs)));
4327 if (p && ie_len > 0)
4330 bss->Configuration.DSConfig = ch;
4332 /* band is changed, update ERP, support rate, ext support rate IE */
4333 if (change_band == _TRUE)
4334 change_band_update_ie(adapter, bss, ch);
4337 #ifdef CONFIG_80211AC_VHT
4338 if (vhtpriv->vht_option == _TRUE) {
4339 u8 *vht_cap_ie, *vht_op_ie;
4340 int vht_cap_ielen, vht_op_ielen;
4343 vht_cap_ie = rtw_get_ie((bss->IEs + sizeof(NDIS_802_11_FIXED_IEs)), EID_VHTCapability, &vht_cap_ielen, (bss->IELength - sizeof(NDIS_802_11_FIXED_IEs)));
4344 vht_op_ie = rtw_get_ie((bss->IEs + sizeof(NDIS_802_11_FIXED_IEs)), EID_VHTOperation, &vht_op_ielen, (bss->IELength - sizeof(NDIS_802_11_FIXED_IEs)));
4345 center_freq = rtw_get_center_ch(ch, bw, offset);
4347 /* update vht cap ie */
4348 if (vht_cap_ie && vht_cap_ielen) {
4350 /* if ((bw == CHANNEL_WIDTH_160 || bw == CHANNEL_WIDTH_80_80) && pvhtpriv->sgi_160m)
4351 SET_VHT_CAPABILITY_ELE_SHORT_GI160M(pvht_cap_ie + 2, 1);
4353 SET_VHT_CAPABILITY_ELE_SHORT_GI160M(vht_cap_ie + 2, 0);
4355 if (bw >= CHANNEL_WIDTH_80 && vhtpriv->sgi_80m)
4356 SET_VHT_CAPABILITY_ELE_SHORT_GI80M(vht_cap_ie + 2, 1);
4358 SET_VHT_CAPABILITY_ELE_SHORT_GI80M(vht_cap_ie + 2, 0);
4362 /* update vht op ie */
4363 if (vht_op_ie && vht_op_ielen) {
4364 if (bw < CHANNEL_WIDTH_80) {
4365 SET_VHT_OPERATION_ELE_CHL_WIDTH(vht_op_ie + 2, 0);
4366 SET_VHT_OPERATION_ELE_CHL_CENTER_FREQ1(vht_op_ie + 2, 0);
4367 SET_VHT_OPERATION_ELE_CHL_CENTER_FREQ2(vht_op_ie + 2, 0);
4368 } else if (bw == CHANNEL_WIDTH_80) {
4369 SET_VHT_OPERATION_ELE_CHL_WIDTH(vht_op_ie + 2, 1);
4370 SET_VHT_OPERATION_ELE_CHL_CENTER_FREQ1(vht_op_ie + 2, center_freq);
4371 SET_VHT_OPERATION_ELE_CHL_CENTER_FREQ2(vht_op_ie + 2, 0);
4373 RTW_ERR(FUNC_ADPT_FMT" unsupported BW:%u\n", FUNC_ADPT_ARG(adapter), bw);
4378 #endif /* CONFIG_80211AC_VHT */
4379 #ifdef CONFIG_80211N_HT
4381 struct ht_priv *htpriv = &adapter->mlmepriv.htpriv;
4382 u8 *ht_cap_ie, *ht_op_ie;
4383 int ht_cap_ielen, ht_op_ielen;
4385 ht_cap_ie = rtw_get_ie((bss->IEs + sizeof(NDIS_802_11_FIXED_IEs)), EID_HTCapability, &ht_cap_ielen, (bss->IELength - sizeof(NDIS_802_11_FIXED_IEs)));
4386 ht_op_ie = rtw_get_ie((bss->IEs + sizeof(NDIS_802_11_FIXED_IEs)), EID_HTInfo, &ht_op_ielen, (bss->IELength - sizeof(NDIS_802_11_FIXED_IEs)));
4388 /* update ht cap ie */
4389 if (ht_cap_ie && ht_cap_ielen) {
4391 if (bw >= CHANNEL_WIDTH_40)
4392 SET_HT_CAP_ELE_CHL_WIDTH(ht_cap_ie + 2, 1);
4394 SET_HT_CAP_ELE_CHL_WIDTH(ht_cap_ie + 2, 0);
4396 if (bw >= CHANNEL_WIDTH_40 && htpriv->sgi_40m)
4397 SET_HT_CAP_ELE_SHORT_GI40M(ht_cap_ie + 2, 1);
4399 SET_HT_CAP_ELE_SHORT_GI40M(ht_cap_ie + 2, 0);
4401 if (htpriv->sgi_20m)
4402 SET_HT_CAP_ELE_SHORT_GI20M(ht_cap_ie + 2, 1);
4404 SET_HT_CAP_ELE_SHORT_GI20M(ht_cap_ie + 2, 0);
4408 /* update ht op ie */
4409 if (ht_op_ie && ht_op_ielen) {
4410 SET_HT_OP_ELE_PRI_CHL(ht_op_ie + 2, ch);
4412 case HAL_PRIME_CHNL_OFFSET_LOWER:
4413 SET_HT_OP_ELE_2ND_CHL_OFFSET(ht_op_ie + 2, SCA);
4415 case HAL_PRIME_CHNL_OFFSET_UPPER:
4416 SET_HT_OP_ELE_2ND_CHL_OFFSET(ht_op_ie + 2, SCB);
4418 case HAL_PRIME_CHNL_OFFSET_DONT_CARE:
4420 SET_HT_OP_ELE_2ND_CHL_OFFSET(ht_op_ie + 2, SCN);
4424 if (bw >= CHANNEL_WIDTH_40)
4425 SET_HT_OP_ELE_STA_CHL_WIDTH(ht_op_ie + 2, 1);
4427 SET_HT_OP_ELE_STA_CHL_WIDTH(ht_op_ie + 2, 0);
4430 #endif /* CONFIG_80211N_HT */
4433 static u8 rtw_ap_update_chbw_by_ifbmp(struct dvobj_priv *dvobj, u8 ifbmp
4434 , u8 cur_ie_ch[], u8 cur_ie_bw[], u8 cur_ie_offset[]
4435 , u8 dec_ch[], u8 dec_bw[], u8 dec_offset[]
4436 , const char *caller)
4439 struct mlme_ext_priv *mlmeext;
4440 WLAN_BSSID_EX *network;
4441 u8 ifbmp_ch_changed = 0;
4444 for (i = 0; i < dvobj->iface_nums; i++) {
4445 if (!(ifbmp & BIT(i)) || !dvobj->padapters)
4448 iface = dvobj->padapters[i];
4449 mlmeext = &(iface->mlmeextpriv);
4451 if (MLME_IS_ASOC(iface)) {
4452 RTW_INFO(FUNC_ADPT_FMT" %u,%u,%u => %u,%u,%u%s\n", caller, ADPT_ARG(iface)
4453 , mlmeext->cur_channel, mlmeext->cur_bwmode, mlmeext->cur_ch_offset
4454 , dec_ch[i], dec_bw[i], dec_offset[i]
4455 , MLME_IS_OPCH_SW(iface) ? " OPCH_SW" : "");
4457 RTW_INFO(FUNC_ADPT_FMT" %u,%u,%u => %u,%u,%u%s\n", caller, ADPT_ARG(iface)
4458 , cur_ie_ch[i], cur_ie_bw[i], cur_ie_offset[i]
4459 , dec_ch[i], dec_bw[i], dec_offset[i]
4460 , MLME_IS_OPCH_SW(iface) ? " OPCH_SW" : "");
4464 for (i = 0; i < dvobj->iface_nums; i++) {
4465 if (!(ifbmp & BIT(i)) || !dvobj->padapters)
4468 iface = dvobj->padapters[i];
4469 mlmeext = &(iface->mlmeextpriv);
4470 network = &(mlmeext->mlmext_info.network);
4472 /* ch setting differs from mlmeext.network IE */
4473 if (cur_ie_ch[i] != dec_ch[i]
4474 || cur_ie_bw[i] != dec_bw[i]
4475 || cur_ie_offset[i] != dec_offset[i])
4476 ifbmp_ch_changed |= BIT(i);
4478 /* ch setting differs from existing one */
4479 if (MLME_IS_ASOC(iface)
4480 && (mlmeext->cur_channel != dec_ch[i]
4481 || mlmeext->cur_bwmode != dec_bw[i]
4482 || mlmeext->cur_ch_offset != dec_offset[i])
4484 if (rtw_linked_check(iface) == _TRUE) {
4485 #ifdef CONFIG_SPCT_CH_SWITCH
4487 rtw_ap_inform_ch_switch(iface, dec_ch[i], dec_offset[i]);
4490 rtw_sta_flush(iface, _FALSE);
4494 mlmeext->cur_channel = dec_ch[i];
4495 mlmeext->cur_bwmode = dec_bw[i];
4496 mlmeext->cur_ch_offset = dec_offset[i];
4498 rtw_ap_update_bss_chbw(iface, network, dec_ch[i], dec_bw[i], dec_offset[i]);
4501 return ifbmp_ch_changed;
4504 static u8 rtw_ap_ch_specific_chk(_adapter *adapter, u8 ch, u8 *bw, u8 *offset, const char *caller)
4506 struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
4507 RT_CHANNEL_INFO *chset = adapter_to_chset(adapter);
4510 if (rtw_chset_search_ch(chset, ch) < 0) {
4511 RTW_WARN("%s ch:%u doesn't fit in chplan\n", caller, ch);
4516 rtw_adjust_chbw(adapter, ch, bw, offset);
4518 if (!rtw_get_offset_by_chbw(ch, *bw, offset)) {
4519 RTW_WARN("%s %u,%u has no valid offset\n", caller, ch, *bw);
4524 while (!rtw_chset_is_chbw_valid(chset, ch, *bw, *offset)
4525 || (rtw_odm_dfs_domain_unknown(dvobj) && rtw_is_dfs_chbw(ch, *bw, *offset))
4527 if (*bw > CHANNEL_WIDTH_20)
4529 if (*bw == CHANNEL_WIDTH_20) {
4530 *offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
4535 if (rtw_odm_dfs_domain_unknown(dvobj) && rtw_is_dfs_chbw(ch, *bw, *offset)) {
4536 RTW_WARN("%s DFS channel %u can't be used\n", caller, ch);
4545 static bool rtw_ap_choose_chbw(_adapter *adapter, u8 sel_ch, u8 max_bw, u8 cur_ch
4546 , u8 *ch, u8 *bw, u8 *offset, u8 mesh_only, const char *caller)
4548 struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
4549 struct rf_ctl_t *rfctl = adapter_to_rfctl(adapter);
4550 bool ch_avail = _FALSE;
4552 #if defined(CONFIG_DFS_MASTER)
4553 if (!rtw_odm_dfs_domain_unknown(dvobj)) {
4554 if (rfctl->radar_detected
4555 && rfctl->dbg_dfs_choose_dfs_ch_first
4557 ch_avail = rtw_choose_shortest_waiting_ch(rfctl, sel_ch, max_bw
4559 , RTW_CHF_2G | RTW_CHF_NON_DFS
4561 , rfctl->ch_sel_same_band_prefer, mesh_only);
4562 if (ch_avail == _TRUE) {
4563 RTW_INFO("%s choose 5G DFS channel for debug\n", caller);
4568 if (rfctl->radar_detected
4569 && rfctl->dfs_ch_sel_d_flags
4571 ch_avail = rtw_choose_shortest_waiting_ch(rfctl, sel_ch, max_bw
4573 , rfctl->dfs_ch_sel_d_flags
4575 , rfctl->ch_sel_same_band_prefer, mesh_only);
4576 if (ch_avail == _TRUE) {
4577 RTW_INFO("%s choose with dfs_ch_sel_d_flags:0x%02x for debug\n"
4578 , caller, rfctl->dfs_ch_sel_d_flags);
4583 ch_avail = rtw_choose_shortest_waiting_ch(rfctl, sel_ch, max_bw
4587 , rfctl->ch_sel_same_band_prefer, mesh_only);
4589 #endif /* defined(CONFIG_DFS_MASTER) */
4591 ch_avail = rtw_choose_shortest_waiting_ch(rfctl, sel_ch, max_bw
4595 , rfctl->ch_sel_same_band_prefer, mesh_only);
4599 if (ch_avail == _FALSE)
4600 RTW_WARN("%s no available channel\n", caller);
4605 u8 rtw_ap_chbw_decision(_adapter *adapter, u8 ifbmp, u8 excl_ifbmp
4606 , s16 req_ch, s8 req_bw, s8 req_offset
4607 , u8 *ch, u8 *bw, u8 *offset, u8 *chbw_allow)
4609 struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
4610 RT_CHANNEL_INFO *chset = adapter_to_chset(adapter);
4611 struct rf_ctl_t *rfctl = adapter_to_rfctl(adapter);
4612 bool ch_avail = _FALSE;
4613 u8 cur_ie_ch[CONFIG_IFACE_NUMBER] = {0};
4614 u8 cur_ie_bw[CONFIG_IFACE_NUMBER] = {0};
4615 u8 cur_ie_offset[CONFIG_IFACE_NUMBER] = {0};
4616 u8 dec_ch[CONFIG_IFACE_NUMBER] = {0};
4617 u8 dec_bw[CONFIG_IFACE_NUMBER] = {0};
4618 u8 dec_offset[CONFIG_IFACE_NUMBER] = {0};
4619 u8 u_ch = 0, u_bw = 0, u_offset = 0;
4620 struct mlme_ext_priv *mlmeext;
4621 WLAN_BSSID_EX *network;
4622 struct mi_state mstate;
4623 struct mi_state mstate_others;
4624 bool set_u_ch = _FALSE;
4625 u8 ifbmp_others = 0xFF & ~ifbmp & ~excl_ifbmp;
4626 u8 ifbmp_ch_changed = 0;
4627 bool ifbmp_all_mesh = 0;
4631 #ifdef CONFIG_RTW_MESH
4632 for (i = 0; i < dvobj->iface_nums; i++)
4633 if ((ifbmp & BIT(i)) && dvobj->padapters)
4634 if (!MLME_IS_MESH(dvobj->padapters[i]))
4636 ifbmp_all_mesh = i >= dvobj->iface_nums ? 1 : 0;
4639 RTW_INFO("%s ifbmp:0x%02x excl_ifbmp:0x%02x req:%d,%d,%d\n", __func__
4640 , ifbmp, excl_ifbmp, req_ch, req_bw, req_offset);
4641 rtw_mi_status_by_ifbmp(dvobj, ifbmp, &mstate);
4642 rtw_mi_status_by_ifbmp(dvobj, ifbmp_others, &mstate_others);
4643 RTW_INFO("%s others ld_sta_num:%u, lg_sta_num:%u, ap_num:%u, mesh_num:%u\n"
4644 , __func__, MSTATE_STA_LD_NUM(&mstate_others), MSTATE_STA_LG_NUM(&mstate_others)
4645 , MSTATE_AP_NUM(&mstate_others), MSTATE_MESH_NUM(&mstate_others));
4647 for (i = 0; i < dvobj->iface_nums; i++) {
4648 if (!(ifbmp & BIT(i)) || !dvobj->padapters[i])
4650 iface = dvobj->padapters[i];
4651 mlmeext = &(iface->mlmeextpriv);
4652 network = &(mlmeext->mlmext_info.network);
4654 /* get current IE channel settings */
4655 rtw_ies_get_chbw(BSS_EX_TLV_IES(network), BSS_EX_TLV_IES_LEN(network)
4656 , &cur_ie_ch[i], &cur_ie_bw[i], &cur_ie_offset[i], 1, 1);
4658 /* prepare temporary channel setting decision */
4660 /* request comes from upper layer, use cur_ie values */
4661 dec_ch[i] = cur_ie_ch[i];
4662 dec_bw[i] = cur_ie_bw[i];
4663 dec_offset[i] = cur_ie_offset[i];
4665 /* use chbw of cur_ie updated with specifying req as temporary decision */
4666 dec_ch[i] = (req_ch <= REQ_CH_NONE) ? cur_ie_ch[i] : req_ch;
4667 if (req_bw <= REQ_BW_NONE) {
4668 if (req_bw == REQ_BW_ORI)
4669 dec_bw[i] = iface->mlmepriv.ori_bw;
4671 dec_bw[i] = cur_ie_bw[i];
4674 dec_offset[i] = (req_offset <= REQ_OFFSET_NONE) ? cur_ie_offset[i] : req_offset;
4678 if (MSTATE_STA_LD_NUM(&mstate_others) || MSTATE_STA_LG_NUM(&mstate_others)
4679 || MSTATE_AP_NUM(&mstate_others) || MSTATE_MESH_NUM(&mstate_others)
4681 /* has linked/linking STA or has AP/Mesh mode */
4682 rtw_warn_on(!rtw_mi_get_ch_setting_union_by_ifbmp(dvobj, ifbmp_others, &u_ch, &u_bw, &u_offset));
4683 RTW_INFO("%s others union:%u,%u,%u\n", __func__, u_ch, u_bw, u_offset);
4686 #ifdef CONFIG_MCC_MODE
4687 if (MCC_EN(adapter) && req_ch == 0) {
4688 if (rtw_hal_check_mcc_status(adapter, MCC_STATUS_DOING_MCC)) {
4689 u8 if_id = adapter->iface_id;
4691 mlmeext = &(adapter->mlmeextpriv);
4693 /* check channel settings are the same */
4694 if (cur_ie_ch[if_id] == mlmeext->cur_channel
4695 && cur_ie_bw[if_id] == mlmeext->cur_bwmode
4696 && cur_ie_offset[if_id] == mlmeext->cur_ch_offset) {
4698 RTW_INFO(FUNC_ADPT_FMT"req ch settings are the same as current ch setting, go to exit\n"
4699 , FUNC_ADPT_ARG(adapter));
4701 *chbw_allow = _FALSE;
4704 RTW_INFO(FUNC_ADPT_FMT"request channel settings are not the same as current channel setting(%d,%d,%d,%d,%d,%d), restart MCC\n"
4705 , FUNC_ADPT_ARG(adapter)
4706 , cur_ie_ch[if_id], cur_ie_bw[if_id], cur_ie_offset[if_id]
4707 , mlmeext->cur_channel, mlmeext->cur_bwmode, mlmeext->cur_ch_offset);
4709 rtw_hal_set_mcc_setting_disconnect(adapter);
4713 #endif /* CONFIG_MCC_MODE */
4715 if (MSTATE_STA_LG_NUM(&mstate_others) && !MSTATE_STA_LD_NUM(&mstate_others)) {
4716 /* has linking STA but no linked STA */
4718 for (i = 0; i < dvobj->iface_nums; i++) {
4719 if (!(ifbmp & BIT(i)) || !dvobj->padapters[i])
4721 iface = dvobj->padapters[i];
4723 rtw_adjust_chbw(iface, dec_ch[i], &dec_bw[i], &dec_offset[i]);
4724 #ifdef CONFIG_RTW_MESH
4725 if (MLME_IS_MESH(iface))
4726 rtw_mesh_adjust_chbw(dec_ch[i], &dec_bw[i], &dec_offset[i]);
4729 if (rtw_is_chbw_grouped(u_ch, u_bw, u_offset, dec_ch[i], dec_bw[i], dec_offset[i])) {
4730 rtw_chset_sync_chbw(chset
4731 , &dec_ch[i], &dec_bw[i], &dec_offset[i]
4732 , &u_ch, &u_bw, &u_offset);
4735 /* channel bw offset can be allowed, not need MCC */
4736 *chbw_allow = _TRUE;
4738 #ifdef CONFIG_MCC_MODE
4739 if (MCC_EN(iface)) {
4740 mlmeext = &(iface->mlmeextpriv);
4741 mlmeext->cur_channel = *ch = dec_ch[i];
4742 mlmeext->cur_bwmode = *bw = dec_bw[i];
4743 mlmeext->cur_ch_offset = *offset = dec_offset[i];
4745 /* channel bw offset can not be allowed, need MCC */
4746 *chbw_allow = _FALSE;
4747 RTW_INFO(FUNC_ADPT_FMT" enable mcc: %u,%u,%u\n", FUNC_ADPT_ARG(iface)
4748 , *ch, *bw, *offset);
4751 #endif /* CONFIG_MCC_MODE */
4753 /* set this for possible ch change when join down*/
4754 set_fwstate(&iface->mlmepriv, WIFI_OP_CH_SWITCHING);
4758 } else if (MSTATE_STA_LD_NUM(&mstate_others)
4759 || MSTATE_AP_NUM(&mstate_others) || MSTATE_MESH_NUM(&mstate_others)
4761 /* has linked STA mode or AP/Mesh mode */
4763 for (i = 0; i < dvobj->iface_nums; i++) {
4764 if (!(ifbmp & BIT(i)) || !dvobj->padapters[i])
4766 iface = dvobj->padapters[i];
4768 rtw_adjust_chbw(iface, u_ch, &dec_bw[i], &dec_offset[i]);
4769 #ifdef CONFIG_RTW_MESH
4770 if (MLME_IS_MESH(iface))
4771 rtw_mesh_adjust_chbw(u_ch, &dec_bw[i], &dec_offset[i]);
4774 #ifdef CONFIG_MCC_MODE
4775 if (MCC_EN(iface)) {
4776 if (!rtw_is_chbw_grouped(u_ch, u_bw, u_offset, dec_ch[i], dec_bw[i], dec_offset[i])) {
4777 mlmeext = &(iface->mlmeextpriv);
4778 mlmeext->cur_channel = *ch = dec_ch[i] = cur_ie_ch[i];
4779 mlmeext->cur_bwmode = *bw = dec_bw[i] = cur_ie_bw[i];
4780 mlmeext->cur_ch_offset = *offset = dec_offset[i] = cur_ie_offset[i];
4781 /* channel bw offset can not be allowed, need MCC */
4782 *chbw_allow = _FALSE;
4783 RTW_INFO(FUNC_ADPT_FMT" enable mcc: %u,%u,%u\n", FUNC_ADPT_ARG(iface)
4784 , *ch, *bw, *offset);
4787 /* channel bw offset can be allowed, not need MCC */
4788 *chbw_allow = _TRUE;
4790 #endif /* CONFIG_MCC_MODE */
4792 if (req_ch == 0 && dec_bw[i] > u_bw
4793 && rtw_is_dfs_chbw(u_ch, u_bw, u_offset)
4795 /* request comes from upper layer, prevent from additional channel waiting */
4797 if (dec_bw[i] == CHANNEL_WIDTH_20)
4798 dec_offset[i] = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
4802 rtw_chset_sync_chbw(chset
4803 , &dec_ch[i], &dec_bw[i], &dec_offset[i]
4804 , &u_ch, &u_bw, &u_offset);
4810 /* autonomous decision */
4814 /* autonomous decision, not need MCC */
4815 *chbw_allow = _TRUE;
4817 if (req_ch <= REQ_CH_NONE) /* channel is not specified */
4820 /* get tmp dec union of ifbmp */
4821 for (i = 0; i < dvobj->iface_nums; i++) {
4822 if (!(ifbmp & BIT(i)) || !dvobj->padapters[i])
4827 u_offset = dec_offset[i];
4828 rtw_adjust_chbw(adapter, u_ch, &u_bw, &u_offset);
4829 rtw_get_offset_by_chbw(u_ch, u_bw, &u_offset);
4831 u8 tmp_ch = dec_ch[i];
4832 u8 tmp_bw = dec_bw[i];
4833 u8 tmp_offset = dec_offset[i];
4835 rtw_adjust_chbw(adapter, tmp_ch, &tmp_bw, &tmp_offset);
4836 rtw_get_offset_by_chbw(tmp_ch, tmp_bw, &tmp_offset);
4838 rtw_warn_on(!rtw_is_chbw_grouped(u_ch, u_bw, u_offset, tmp_ch, tmp_bw, tmp_offset));
4839 rtw_sync_chbw(&tmp_ch, &tmp_bw, &tmp_offset, &u_ch, &u_bw, &u_offset);
4843 #ifdef CONFIG_RTW_MESH
4844 /* if ifbmp are all mesh, apply bw restriction */
4846 rtw_mesh_adjust_chbw(u_ch, &u_bw, &u_offset);
4849 RTW_INFO("%s ifbmp:0x%02x tmp union:%u,%u,%u\n", __func__, ifbmp, u_ch, u_bw, u_offset);
4851 /* check if tmp dec union is usable */
4852 if (rtw_ap_ch_specific_chk(adapter, u_ch, &u_bw, &u_offset, __func__) == _FAIL) {
4853 /* channel can't be used */
4855 /* specific channel and not from IE => don't change channel setting */
4859 } else if (rtw_chset_is_chbw_non_ocp(chset, u_ch, u_bw, u_offset)) {
4860 RTW_WARN("%s DFS channel %u,%u under non ocp\n", __func__, u_ch, u_bw);
4861 if (req_ch > 0 && req_bw > REQ_BW_NONE) {
4862 /* change_chbw with specific channel and specific bw, goto update_bss_chbw directly */
4863 goto update_bss_chbw;
4866 goto update_bss_chbw;
4869 req_ch = req_ch > 0 ? req_ch : 0;
4870 max_bw = req_bw > REQ_BW_NONE ? req_bw : CHANNEL_WIDTH_20;
4871 for (i = 0; i < dvobj->iface_nums; i++) {
4872 if (!(ifbmp & BIT(i)) || !dvobj->padapters[i])
4874 iface = dvobj->padapters[i];
4875 mlmeext = &(iface->mlmeextpriv);
4877 if (req_bw <= REQ_BW_NONE) {
4878 if (req_bw == REQ_BW_ORI) {
4879 if (max_bw < iface->mlmepriv.ori_bw)
4880 max_bw = iface->mlmepriv.ori_bw;
4882 if (max_bw < cur_ie_bw[i])
4883 max_bw = cur_ie_bw[i];
4887 if (MSTATE_AP_NUM(&mstate) || MSTATE_MESH_NUM(&mstate)) {
4889 ori_ch = mlmeext->cur_channel;
4890 else if (ori_ch != mlmeext->cur_channel)
4894 ori_ch = cur_ie_ch[i];
4895 else if (ori_ch != cur_ie_ch[i])
4900 ch_avail = rtw_ap_choose_chbw(adapter, req_ch, max_bw
4901 , ori_ch, &u_ch, &u_bw, &u_offset, ifbmp_all_mesh, __func__);
4902 if (ch_avail == _FALSE)
4906 for (i = 0; i < dvobj->iface_nums; i++) {
4907 if (!(ifbmp & BIT(i)) || !dvobj->padapters[i])
4909 iface = dvobj->padapters[i];
4912 if (dec_bw[i] > u_bw)
4914 if (dec_bw[i] == CHANNEL_WIDTH_20)
4915 dec_offset[i] = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
4917 dec_offset[i] = u_offset;
4919 #ifdef CONFIG_RTW_MESH
4920 if (MLME_IS_MESH(iface))
4921 rtw_mesh_adjust_chbw(dec_ch[i], &dec_bw[i], &dec_offset[i]);
4928 ifbmp_ch_changed = rtw_ap_update_chbw_by_ifbmp(dvobj, ifbmp
4929 , cur_ie_ch, cur_ie_bw, cur_ie_offset
4930 , dec_ch, dec_bw, dec_offset
4934 RTW_INFO("%s union:%u,%u,%u\n", __func__, u_ch, u_bw, u_offset);
4936 if (rtw_mi_check_fwstate(adapter, _FW_UNDER_SURVEY)) {
4937 /* scanning, leave ch setting to scan state machine */
4941 if (set_u_ch == _TRUE) {
4947 return ifbmp_ch_changed;
4950 u8 rtw_ap_sta_states_check(_adapter *adapter)
4952 struct sta_info *psta;
4953 struct sta_priv *pstapriv = &adapter->stapriv;
4954 _list *plist, *phead;
4958 if (!MLME_IS_AP(adapter) && !MLME_IS_MESH(adapter))
4961 if (pstapriv->auth_list_cnt !=0)
4964 _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
4965 phead = &pstapriv->asoc_list;
4966 plist = get_next(phead);
4967 while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {
4969 psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);
4970 plist = get_next(plist);
4972 if (!(psta->state & _FW_LINKED)) {
4973 RTW_INFO(ADPT_FMT"- SoftAP/Mesh - sta under linking, its state = 0x%x\n", ADPT_ARG(adapter), psta->state);
4976 } else if (psta->state & WIFI_UNDER_KEY_HANDSHAKE) {
4977 RTW_INFO(ADPT_FMT"- SoftAP/Mesh - sta under key handshaking, its state = 0x%x\n", ADPT_ARG(adapter), psta->state);
4982 _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
4986 /*#define DBG_SWTIMER_BASED_TXBCN*/
4987 #ifdef CONFIG_SWTIMER_BASED_TXBCN
4988 void tx_beacon_handlder(struct dvobj_priv *pdvobj)
4990 #define BEACON_EARLY_TIME 20 /* unit:TU*/
4992 _list *plist, *phead;
4994 u32 bcn_interval_us; /* unit : usec */
4996 u32 cur_tick, time_offset; /* unit : usec */
4997 u32 inter_bcn_space_us; /* unit : usec */
4998 u32 txbcn_timer_ms; /* unit : ms */
4999 int nr_vap, idx, bcn_idx;
5002 _adapter *padapter = NULL;
5006 /* get first ap mode interface */
5007 _enter_critical_bh(&pdvobj->ap_if_q.lock, &irqL);
5008 if (rtw_is_list_empty(&pdvobj->ap_if_q.queue) || (pdvobj->nr_ap_if == 0)) {
5009 RTW_INFO("[%s] ERROR: ap_if_q is empty!or nr_ap = %d\n", __func__, pdvobj->nr_ap_if);
5010 _exit_critical_bh(&pdvobj->ap_if_q.lock, &irqL);
5013 padapter = LIST_CONTAINOR(get_next(&(pdvobj->ap_if_q.queue)), struct _ADAPTER, list);
5014 _exit_critical_bh(&pdvobj->ap_if_q.lock, &irqL);
5016 if (NULL == padapter) {
5017 RTW_INFO("[%s] ERROR: no any ap interface!\n", __func__);
5022 bcn_interval_us = DEFAULT_BCN_INTERVAL * NET80211_TU_TO_US;
5023 if (0 == bcn_interval_us) {
5024 RTW_INFO("[%s] ERROR: beacon interval = 0\n", __func__);
5029 timestamp[1] = rtw_read32(padapter, 0x560 + 4);
5030 timestamp[0] = rtw_read32(padapter, 0x560);
5031 while (timestamp[1]) {
5032 time = (0xFFFFFFFF % bcn_interval_us + 1) * timestamp[1] + timestamp[0];
5033 timestamp[0] = (u32)time;
5034 timestamp[1] = (u32)(time >> 32);
5036 cur_tick = timestamp[0] % bcn_interval_us;
5039 _enter_critical_bh(&pdvobj->ap_if_q.lock, &irqL);
5041 nr_vap = (pdvobj->nr_ap_if - 1);
5043 inter_bcn_space_us = pdvobj->inter_bcn_space * NET80211_TU_TO_US; /* beacon_interval / (nr_vap+1); */
5044 idx = cur_tick / inter_bcn_space_us;
5045 if (idx < nr_vap) /* if (idx < (nr_vap+1))*/
5046 bcn_idx = idx + 1; /* bcn_idx = (idx + 1) % (nr_vap+1);*/
5050 /* to get padapter based on bcn_idx */
5052 phead = get_list_head(&pdvobj->ap_if_q);
5053 plist = get_next(phead);
5054 while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {
5055 padapter = LIST_CONTAINOR(plist, struct _ADAPTER, list);
5057 plist = get_next(plist);
5064 if ((NULL == padapter) || (i > pdvobj->nr_ap_if)) {
5065 RTW_INFO("[%s] ERROR: nr_ap_if = %d, padapter=%p, bcn_idx=%d, index=%d\n",
5066 __func__, pdvobj->nr_ap_if, padapter, bcn_idx, i);
5067 _exit_critical_bh(&pdvobj->ap_if_q.lock, &irqL);
5070 #ifdef DBG_SWTIMER_BASED_TXBCN
5071 RTW_INFO("BCN_IDX=%d, cur_tick=%d, padapter=%p\n", bcn_idx, cur_tick, padapter);
5073 if (((idx + 2 == nr_vap + 1) && (idx < nr_vap + 1)) || (0 == bcn_idx)) {
5074 time_offset = bcn_interval_us - cur_tick - BEACON_EARLY_TIME * NET80211_TU_TO_US;
5075 if ((s32)time_offset < 0)
5076 time_offset += inter_bcn_space_us;
5079 time_offset = (idx + 2) * inter_bcn_space_us - cur_tick - BEACON_EARLY_TIME * NET80211_TU_TO_US;
5080 if (time_offset > (inter_bcn_space_us + (inter_bcn_space_us >> 1))) {
5081 time_offset -= inter_bcn_space_us;
5086 /*#endif*/ { /* MBSSID */
5087 time_offset = 2 * bcn_interval_us - cur_tick - BEACON_EARLY_TIME * NET80211_TU_TO_US;
5088 if (time_offset > (bcn_interval_us + (bcn_interval_us >> 1))) {
5089 time_offset -= bcn_interval_us;
5093 _exit_critical_bh(&pdvobj->ap_if_q.lock, &irqL);
5095 #ifdef DBG_SWTIMER_BASED_TXBCN
5096 RTW_INFO("set sw bcn timer %d us\n", time_offset);
5098 txbcn_timer_ms = time_offset / NET80211_TU_TO_US;
5099 _set_timer(&pdvobj->txbcn_timer, txbcn_timer_ms);
5102 #ifdef CONFIG_BCN_RECOVERY
5103 rtw_ap_bcn_recovery(padapter);
5104 #endif /*CONFIG_BCN_RECOVERY*/
5106 #ifdef CONFIG_BCN_XMIT_PROTECT
5107 rtw_ap_bcn_queue_empty_check(padapter, txbcn_timer_ms);
5108 #endif /*CONFIG_BCN_XMIT_PROTECT*/
5110 #ifdef DBG_SWTIMER_BASED_TXBCN
5111 RTW_INFO("padapter=%p, PORT=%d\n", padapter, padapter->hw_port);
5113 /* bypass TX BCN queue if op ch is switching/waiting */
5114 if (!check_fwstate(&padapter->mlmepriv, WIFI_OP_CH_SWITCHING)
5115 && !IS_CH_WAITING(adapter_to_rfctl(padapter))
5117 /*update_beacon(padapter, _TIM_IE_, NULL, _FALSE);*/
5118 /*issue_beacon(padapter, 0);*/
5119 send_beacon(padapter);
5124 /* handle any buffered BC/MC frames*/
5125 /* Don't dynamically change DIS_ATIM due to HW will auto send ACQ after HIQ empty.*/
5126 val8 = *((unsigned char *)priv->beaconbuf + priv->timoffset + 4);
5128 process_mcast_dzqueue(priv);
5129 priv->pkt_in_dtimQ = 0;
5135 void tx_beacon_timer_handlder(void *ctx)
5137 struct dvobj_priv *pdvobj = (struct dvobj_priv *)ctx;
5138 _adapter *padapter = pdvobj->padapters[0];
5141 set_tx_beacon_cmd(padapter);
5145 void rtw_ap_parse_sta_capability(_adapter *adapter, struct sta_info *sta, u8 *cap)
5147 sta->capability = RTW_GET_LE16(cap);
5148 if (sta->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
5149 sta->flags |= WLAN_STA_SHORT_PREAMBLE;
5151 sta->flags &= ~WLAN_STA_SHORT_PREAMBLE;
5154 u16 rtw_ap_parse_sta_supported_rates(_adapter *adapter, struct sta_info *sta, u8 *tlv_ies, u16 tlv_ies_len)
5159 u16 status = _STATS_SUCCESSFUL_;
5161 rtw_ies_get_supported_rate(tlv_ies, tlv_ies_len, rate_set, &rate_num);
5162 if (rate_num == 0) {
5163 RTW_INFO(FUNC_ADPT_FMT" sta "MAC_FMT" with no supported rate\n"
5164 , FUNC_ADPT_ARG(adapter), MAC_ARG(sta->cmn.mac_addr));
5165 status = _STATS_FAILURE_;
5169 _rtw_memcpy(sta->bssrateset, rate_set, rate_num);
5170 sta->bssratelen = rate_num;
5172 if (MLME_IS_AP(adapter)) {
5173 /* this function force only CCK rates to be bassic rate... */
5174 UpdateBrateTblForSoftAP(sta->bssrateset, sta->bssratelen);
5177 /* if (hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G) */ /* ? */
5178 sta->flags |= WLAN_STA_NONERP;
5179 for (i = 0; i < sta->bssratelen; i++) {
5180 if ((sta->bssrateset[i] & 0x7f) > 22) {
5181 sta->flags &= ~WLAN_STA_NONERP;
5190 u16 rtw_ap_parse_sta_security_ie(_adapter *adapter, struct sta_info *sta, struct rtw_ieee802_11_elems *elems)
5192 struct security_priv *sec = &adapter->securitypriv;
5195 int group_cipher = 0, pairwise_cipher = 0;
5197 u8 mfp_opt = MFP_NO;
5198 u16 status = _STATS_SUCCESSFUL_;
5200 sta->dot8021xalg = 0;
5202 sta->wpa_group_cipher = 0;
5203 sta->wpa2_group_cipher = 0;
5204 sta->wpa_pairwise_cipher = 0;
5205 sta->wpa2_pairwise_cipher = 0;
5206 _rtw_memset(sta->wpa_ie, 0, sizeof(sta->wpa_ie));
5208 if ((sec->wpa_psk & BIT(1)) && elems->rsn_ie) {
5209 wpa_ie = elems->rsn_ie;
5210 wpa_ie_len = elems->rsn_ie_len;
5212 if (rtw_parse_wpa2_ie(wpa_ie - 2, wpa_ie_len + 2, &group_cipher, &pairwise_cipher, &akm, &mfp_opt) == _SUCCESS) {
5213 sta->dot8021xalg = 1;/* psk, todo:802.1x */
5214 sta->wpa_psk |= BIT(1);
5216 sta->wpa2_group_cipher = group_cipher & sec->wpa2_group_cipher;
5217 sta->wpa2_pairwise_cipher = pairwise_cipher & sec->wpa2_pairwise_cipher;
5219 sta->akm_suite_type = akm;
5220 if ((CHECK_BIT(WLAN_AKM_TYPE_SAE, akm)) && (MFP_NO == mfp_opt))
5221 status = WLAN_STATUS_ROBUST_MGMT_FRAME_POLICY_VIOLATION;
5223 if (!sta->wpa2_group_cipher)
5224 status = WLAN_STATUS_GROUP_CIPHER_NOT_VALID;
5226 if (!sta->wpa2_pairwise_cipher)
5227 status = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID;
5229 status = WLAN_STATUS_INVALID_IE;
5232 else if ((sec->wpa_psk & BIT(0)) && elems->wpa_ie) {
5233 wpa_ie = elems->wpa_ie;
5234 wpa_ie_len = elems->wpa_ie_len;
5236 if (rtw_parse_wpa_ie(wpa_ie - 2, wpa_ie_len + 2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) {
5237 sta->dot8021xalg = 1;/* psk, todo:802.1x */
5238 sta->wpa_psk |= BIT(0);
5240 sta->wpa_group_cipher = group_cipher & sec->wpa_group_cipher;
5241 sta->wpa_pairwise_cipher = pairwise_cipher & sec->wpa_pairwise_cipher;
5243 if (!sta->wpa_group_cipher)
5244 status = WLAN_STATUS_GROUP_CIPHER_NOT_VALID;
5246 if (!sta->wpa_pairwise_cipher)
5247 status = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID;
5249 status = WLAN_STATUS_INVALID_IE;
5256 #ifdef CONFIG_RTW_MESH
5257 if (MLME_IS_MESH(adapter)) {
5258 /* MFP is mandatory for secure mesh */
5259 if (adapter->mesh_info.mesh_auth_id)
5260 sta->flags |= WLAN_STA_MFP;
5263 if ((sec->mfp_opt == MFP_REQUIRED && mfp_opt == MFP_NO) || mfp_opt == MFP_INVALID)
5264 status = WLAN_STATUS_ROBUST_MGMT_FRAME_POLICY_VIOLATION;
5265 else if (sec->mfp_opt >= MFP_OPTIONAL && mfp_opt >= MFP_OPTIONAL)
5266 sta->flags |= WLAN_STA_MFP;
5268 if ((sec->auth_type == NL80211_AUTHTYPE_SAE) &&
5269 (CHECK_BIT(WLAN_AKM_TYPE_SAE, sta->akm_suite_type)) &&
5270 (WLAN_AUTH_OPEN == sta->authalg)) {
5271 /* WPA3-SAE, PMK caching */
5272 if (rtw_cached_pmkid(adapter, sta->cmn.mac_addr) == -1) {
5273 RTW_INFO("SAE: No PMKSA cache entry found\n");
5274 status = WLAN_STATUS_INVALID_PMKID;
5276 RTW_INFO("SAE: PMKSA cache entry found\n");
5280 if (status != _STATS_SUCCESSFUL_)
5283 if (!MLME_IS_AP(adapter))
5286 sta->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS);
5287 /* if (hapd->conf->wps_state && wpa_ie == NULL) { */ /* todo: to check ap if supporting WPS */
5288 if (wpa_ie == NULL) {
5289 if (elems->wps_ie) {
5290 RTW_INFO("STA included WPS IE in "
5291 "(Re)Association Request - assume WPS is "
5293 sta->flags |= WLAN_STA_WPS;
5294 /* wpabuf_free(sta->wps_ie); */
5295 /* sta->wps_ie = wpabuf_alloc_copy(elems.wps_ie + 4, */
5296 /* elems.wps_ie_len - 4); */
5298 RTW_INFO("STA did not include WPA/RSN IE "
5299 "in (Re)Association Request - possible WPS "
5301 sta->flags |= WLAN_STA_MAYBE_WPS;
5304 /* AP support WPA/RSN, and sta is going to do WPS, but AP is not ready */
5305 /* that the selected registrar of AP is _FLASE */
5306 if ((sec->wpa_psk > 0)
5307 && (sta->flags & (WLAN_STA_WPS | WLAN_STA_MAYBE_WPS))
5309 struct mlme_priv *mlme = &adapter->mlmepriv;
5311 if (mlme->wps_beacon_ie) {
5312 u8 selected_registrar = 0;
5314 rtw_get_wps_attr_content(mlme->wps_beacon_ie, mlme->wps_beacon_ie_len, WPS_ATTR_SELECTED_REGISTRAR, &selected_registrar, NULL);
5316 if (!selected_registrar) {
5317 RTW_INFO("selected_registrar is _FALSE , or AP is not ready to do WPS\n");
5318 status = _STATS_UNABLE_HANDLE_STA_;
5327 if (sec->wpa_psk == 0) {
5328 RTW_INFO("STA " MAC_FMT
5329 ": WPA/RSN IE in association request, but AP don't support WPA/RSN\n",
5330 MAC_ARG(sta->cmn.mac_addr));
5331 status = WLAN_STATUS_INVALID_IE;
5335 if (elems->wps_ie) {
5336 RTW_INFO("STA included WPS IE in "
5337 "(Re)Association Request - WPS is "
5339 sta->flags |= WLAN_STA_WPS;
5342 copy_len = ((wpa_ie_len + 2) > sizeof(sta->wpa_ie)) ? (sizeof(sta->wpa_ie)) : (wpa_ie_len + 2);
5345 _rtw_memcpy(sta->wpa_ie, wpa_ie - 2, copy_len);
5352 void rtw_ap_parse_sta_wmm_ie(_adapter *adapter, struct sta_info *sta, u8 *tlv_ies, u16 tlv_ies_len)
5354 struct mlme_priv *mlme = &adapter->mlmepriv;
5355 unsigned char WMM_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01};
5358 sta->flags &= ~WLAN_STA_WME;
5359 sta->qos_option = 0;
5361 sta->has_legacy_ac = _TRUE;
5367 if (!mlme->qospriv.qos_option)
5370 #ifdef CONFIG_RTW_MESH
5371 if (MLME_IS_MESH(adapter)) {
5372 /* QoS is mandatory in mesh */
5373 sta->flags |= WLAN_STA_WME;
5377 p = rtw_get_ie_ex(tlv_ies, tlv_ies_len, WLAN_EID_VENDOR_SPECIFIC, WMM_IE, 6, NULL, NULL);
5381 sta->flags |= WLAN_STA_WME;
5382 sta->qos_option = 1;
5383 sta->qos_info = *(p + 8);
5384 sta->max_sp_len = (sta->qos_info >> 5) & 0x3;
5386 if ((sta->qos_info & 0xf) != 0xf)
5387 sta->has_legacy_ac = _TRUE;
5389 sta->has_legacy_ac = _FALSE;
5391 if (sta->qos_info & 0xf) {
5392 if (sta->qos_info & BIT(0))
5393 sta->uapsd_vo = BIT(0) | BIT(1);
5397 if (sta->qos_info & BIT(1))
5398 sta->uapsd_vi = BIT(0) | BIT(1);
5402 if (sta->qos_info & BIT(2))
5403 sta->uapsd_bk = BIT(0) | BIT(1);
5407 if (sta->qos_info & BIT(3))
5408 sta->uapsd_be = BIT(0) | BIT(1);
5417 void rtw_ap_parse_sta_ht_ie(_adapter *adapter, struct sta_info *sta, struct rtw_ieee802_11_elems *elems)
5419 struct mlme_priv *mlme = &adapter->mlmepriv;
5421 sta->flags &= ~WLAN_STA_HT;
5423 #ifdef CONFIG_80211N_HT
5424 if (mlme->htpriv.ht_option == _FALSE)
5427 /* save HT capabilities in the sta object */
5428 _rtw_memset(&sta->htpriv.ht_cap, 0, sizeof(struct rtw_ieee80211_ht_cap));
5429 if (elems->ht_capabilities && elems->ht_capabilities_len >= sizeof(struct rtw_ieee80211_ht_cap)) {
5430 sta->flags |= WLAN_STA_HT;
5431 sta->flags |= WLAN_STA_WME;
5432 _rtw_memcpy(&sta->htpriv.ht_cap, elems->ht_capabilities, sizeof(struct rtw_ieee80211_ht_cap));
5434 if (elems->ht_operation && elems->ht_operation_len == HT_OP_IE_LEN) {
5435 _rtw_memcpy(sta->htpriv.ht_op, elems->ht_operation, HT_OP_IE_LEN);
5436 sta->htpriv.op_present = 1;
5445 void rtw_ap_parse_sta_vht_ie(_adapter *adapter, struct sta_info *sta, struct rtw_ieee802_11_elems *elems)
5447 struct mlme_priv *mlme = &adapter->mlmepriv;
5449 sta->flags &= ~WLAN_STA_VHT;
5451 #ifdef CONFIG_80211AC_VHT
5452 if (mlme->vhtpriv.vht_option == _FALSE)
5455 _rtw_memset(&sta->vhtpriv, 0, sizeof(struct vht_priv));
5456 if (elems->vht_capabilities && elems->vht_capabilities_len == VHT_CAP_IE_LEN) {
5457 sta->flags |= WLAN_STA_VHT;
5458 _rtw_memcpy(sta->vhtpriv.vht_cap, elems->vht_capabilities, VHT_CAP_IE_LEN);
5460 if (elems->vht_operation && elems->vht_operation_len== VHT_OP_IE_LEN) {
5461 _rtw_memcpy(sta->vhtpriv.vht_op, elems->vht_operation, VHT_OP_IE_LEN);
5462 sta->vhtpriv.op_present = 1;
5465 if (elems->vht_op_mode_notify && elems->vht_op_mode_notify_len == 1) {
5466 _rtw_memcpy(&sta->vhtpriv.vht_op_mode_notify, elems->vht_op_mode_notify, 1);
5467 sta->vhtpriv.notify_present = 1;
5475 #endif /* CONFIG_AP_MODE */