Path: blob/master/ALFA-W1F1/RTL8814AU/core/rtw_ap.c
1307 views
/******************************************************************************1*2* Copyright(c) 2007 - 2017 Realtek Corporation.3*4* This program is free software; you can redistribute it and/or modify it5* under the terms of version 2 of the GNU General Public License as6* published by the Free Software Foundation.7*8* This program is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for11* more details.12*13*****************************************************************************/14#define _RTW_AP_C_1516#include <drv_types.h>17#include <hal_data.h>1819#ifdef CONFIG_AP_MODE2021extern unsigned char RTW_WPA_OUI[];22extern unsigned char WMM_OUI[];23extern unsigned char WPS_OUI[];24extern unsigned char P2P_OUI[];25extern unsigned char WFD_OUI[];2627void init_mlme_ap_info(_adapter *padapter)28{29struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);3031_rtw_spinlock_init(&pmlmepriv->bcn_update_lock);32/* pmlmeext->bstart_bss = _FALSE; */33}3435void free_mlme_ap_info(_adapter *padapter)36{37struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);3839stop_ap_mode(padapter);40_rtw_spinlock_free(&pmlmepriv->bcn_update_lock);4142}4344/*45* Set TIM IE46* return length of total TIM IE47*/48u8 rtw_set_tim_ie(u8 dtim_cnt, u8 dtim_period49, const u8 *tim_bmp, u8 tim_bmp_len, u8 *tim_ie)50{51u8 *p = tim_ie;52u8 i, n1, n2;53u8 bmp_len;5455if (rtw_bmp_not_empty(tim_bmp, tim_bmp_len)) {56/* find the first nonzero octet in tim_bitmap */57for (i = 0; i < tim_bmp_len; i++)58if (tim_bmp[i])59break;60n1 = i & 0xFE;6162/* find the last nonzero octet in tim_bitmap, except octet 0 */63for (i = tim_bmp_len - 1; i > 0; i--)64if (tim_bmp[i])65break;66n2 = i;67bmp_len = n2 - n1 + 1;68} else {69n1 = n2 = 0;70bmp_len = 1;71}7273*p++ = WLAN_EID_TIM;74*p++ = 2 + 1 + bmp_len;75*p++ = dtim_cnt;76*p++ = dtim_period;77*p++ = (rtw_bmp_is_set(tim_bmp, tim_bmp_len, 0) ? BIT0 : 0) | n1;78_rtw_memcpy(p, tim_bmp + n1, bmp_len);7980#if 081RTW_INFO("n1:%u, n2:%u, bmp_offset:%u, bmp_len:%u\n", n1, n2, n1 / 2, bmp_len);82RTW_INFO_DUMP("tim_ie: ", tim_ie + 2, 2 + 1 + bmp_len);83#endif84return 2 + 2 + 1 + bmp_len;85}8687static void update_BCNTIM(_adapter *padapter)88{89struct sta_priv *pstapriv = &padapter->stapriv;90struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);91struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);92WLAN_BSSID_EX *pnetwork_mlmeext = &(pmlmeinfo->network);93unsigned char *pie = pnetwork_mlmeext->IEs;9495#if 0969798/* update TIM IE */99/* if(rtw_tim_map_anyone_be_set(padapter, pstapriv->tim_bitmap)) */100#endif101if (_TRUE) {102u8 *p, *dst_ie, *premainder_ie = NULL, *pbackup_remainder_ie = NULL;103uint offset, tmp_len, tim_ielen, tim_ie_offset, remainder_ielen;104105p = rtw_get_ie(pie + _FIXED_IE_LENGTH_, _TIM_IE_, &tim_ielen, pnetwork_mlmeext->IELength - _FIXED_IE_LENGTH_);106if (p != NULL && tim_ielen > 0) {107tim_ielen += 2;108109premainder_ie = p + tim_ielen;110111tim_ie_offset = (sint)(p - pie);112113remainder_ielen = pnetwork_mlmeext->IELength - tim_ie_offset - tim_ielen;114115/*append TIM IE from dst_ie offset*/116dst_ie = p;117} else {118tim_ielen = 0;119120/*calculate head_len*/121offset = _FIXED_IE_LENGTH_;122123/* get ssid_ie len */124p = rtw_get_ie(pie + _BEACON_IE_OFFSET_, _SSID_IE_, &tmp_len, (pnetwork_mlmeext->IELength - _BEACON_IE_OFFSET_));125if (p != NULL)126offset += tmp_len + 2;127128/*get supported rates len*/129p = rtw_get_ie(pie + _BEACON_IE_OFFSET_, _SUPPORTEDRATES_IE_, &tmp_len, (pnetwork_mlmeext->IELength - _BEACON_IE_OFFSET_));130if (p != NULL)131offset += tmp_len + 2;132133/*DS Parameter Set IE, len=3*/134offset += 3;135136premainder_ie = pie + offset;137138remainder_ielen = pnetwork_mlmeext->IELength - offset - tim_ielen;139140/*append TIM IE from offset*/141dst_ie = pie + offset;142143}144145if (remainder_ielen > 0) {146pbackup_remainder_ie = rtw_malloc(remainder_ielen);147if (pbackup_remainder_ie && premainder_ie)148_rtw_memcpy(pbackup_remainder_ie, premainder_ie, remainder_ielen);149}150151/* append TIM IE */152dst_ie += rtw_set_tim_ie(0, 1, pstapriv->tim_bitmap, pstapriv->aid_bmp_len, dst_ie);153154/*copy remainder IE*/155if (pbackup_remainder_ie) {156_rtw_memcpy(dst_ie, pbackup_remainder_ie, remainder_ielen);157158rtw_mfree(pbackup_remainder_ie, remainder_ielen);159}160161offset = (uint)(dst_ie - pie);162pnetwork_mlmeext->IELength = offset + remainder_ielen;163164}165}166167void rtw_add_bcn_ie(_adapter *padapter, WLAN_BSSID_EX *pnetwork, u8 index, u8 *data, u8 len)168{169PNDIS_802_11_VARIABLE_IEs pIE;170u8 bmatch = _FALSE;171u8 *pie = pnetwork->IEs;172u8 *p = NULL, *dst_ie = NULL, *premainder_ie = NULL, *pbackup_remainder_ie = NULL;173u32 i, offset, ielen, ie_offset, remainder_ielen = 0;174175for (i = sizeof(NDIS_802_11_FIXED_IEs); i < pnetwork->IELength;) {176pIE = (PNDIS_802_11_VARIABLE_IEs)(pnetwork->IEs + i);177178if (pIE->ElementID > index)179break;180else if (pIE->ElementID == index) { /* already exist the same IE */181p = (u8 *)pIE;182ielen = pIE->Length;183bmatch = _TRUE;184break;185}186187p = (u8 *)pIE;188ielen = pIE->Length;189i += (pIE->Length + 2);190}191192if (p != NULL && ielen > 0) {193ielen += 2;194195premainder_ie = p + ielen;196197ie_offset = (sint)(p - pie);198199remainder_ielen = pnetwork->IELength - ie_offset - ielen;200201if (bmatch)202dst_ie = p;203else204dst_ie = (p + ielen);205}206207if (dst_ie == NULL)208return;209210if (remainder_ielen > 0) {211pbackup_remainder_ie = rtw_malloc(remainder_ielen);212if (pbackup_remainder_ie && premainder_ie)213_rtw_memcpy(pbackup_remainder_ie, premainder_ie, remainder_ielen);214}215216*dst_ie++ = index;217*dst_ie++ = len;218219_rtw_memcpy(dst_ie, data, len);220dst_ie += len;221222/* copy remainder IE */223if (pbackup_remainder_ie) {224_rtw_memcpy(dst_ie, pbackup_remainder_ie, remainder_ielen);225226rtw_mfree(pbackup_remainder_ie, remainder_ielen);227}228229offset = (uint)(dst_ie - pie);230pnetwork->IELength = offset + remainder_ielen;231}232233void rtw_remove_bcn_ie(_adapter *padapter, WLAN_BSSID_EX *pnetwork, u8 index)234{235u8 *p, *dst_ie = NULL, *premainder_ie = NULL, *pbackup_remainder_ie = NULL;236uint offset, ielen, ie_offset, remainder_ielen = 0;237u8 *pie = pnetwork->IEs;238239p = rtw_get_ie(pie + _FIXED_IE_LENGTH_, index, &ielen, pnetwork->IELength - _FIXED_IE_LENGTH_);240if (p != NULL && ielen > 0) {241ielen += 2;242243premainder_ie = p + ielen;244245ie_offset = (sint)(p - pie);246247remainder_ielen = pnetwork->IELength - ie_offset - ielen;248249dst_ie = p;250} else251return;252253if (remainder_ielen > 0) {254pbackup_remainder_ie = rtw_malloc(remainder_ielen);255if (pbackup_remainder_ie && premainder_ie)256_rtw_memcpy(pbackup_remainder_ie, premainder_ie, remainder_ielen);257}258259/* copy remainder IE */260if (pbackup_remainder_ie) {261_rtw_memcpy(dst_ie, pbackup_remainder_ie, remainder_ielen);262263rtw_mfree(pbackup_remainder_ie, remainder_ielen);264}265266offset = (uint)(dst_ie - pie);267pnetwork->IELength = offset + remainder_ielen;268}269270271u8 chk_sta_is_alive(struct sta_info *psta);272u8 chk_sta_is_alive(struct sta_info *psta)273{274u8 ret = _FALSE;275#ifdef DBG_EXPIRATION_CHK276RTW_INFO("sta:"MAC_FMT", rssi:%d, rx:"STA_PKTS_FMT", expire_to:%u, %s%ssq_len:%u\n"277, MAC_ARG(psta->cmn.mac_addr)278, psta->cmn.rssi_stat.rssi279/* , STA_RX_PKTS_ARG(psta) */280, STA_RX_PKTS_DIFF_ARG(psta)281, psta->expire_to282, psta->state & WIFI_SLEEP_STATE ? "PS, " : ""283, psta->state & WIFI_STA_ALIVE_CHK_STATE ? "SAC, " : ""284, psta->sleepq_len285);286#endif287288/* if(sta_last_rx_pkts(psta) == sta_rx_pkts(psta)) */289if ((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)) {290#if 0291if (psta->state & WIFI_SLEEP_STATE)292ret = _TRUE;293#endif294} else295ret = _TRUE;296297#ifdef CONFIG_RTW_MESH298if (MLME_IS_MESH(psta->padapter)) {299u8 bcn_alive, hwmp_alive;300301hwmp_alive = (psta->sta_stats.rx_hwmp_pkts !=302psta->sta_stats.last_rx_hwmp_pkts);303bcn_alive = (psta->sta_stats.rx_beacon_pkts !=304psta->sta_stats.last_rx_beacon_pkts);305/* The reference for nexthop_lookup */306psta->alive = ret || hwmp_alive || bcn_alive;307/* The reference for expire_timeout_chk */308/* Exclude bcn_alive to avoid a misjudge condition309that a peer unexpectedly leave and restart quickly*/310ret = ret || hwmp_alive;311}312#endif313314sta_update_last_rx_pkts(psta);315316return ret;317}318319/**320* issue_aka_chk_frame - issue active keep alive check frame321* aka = active keep alive322*/323#ifdef CONFIG_ACTIVE_KEEP_ALIVE_CHECK324static int issue_aka_chk_frame(_adapter *adapter, struct sta_info *psta)325{326int ret = _FAIL;327u8 *target_addr = psta->cmn.mac_addr;328329if (MLME_IS_AP(adapter)) {330/* issue null data to check sta alive */331if (psta->state & WIFI_SLEEP_STATE)332ret = issue_nulldata(adapter, target_addr, 0, 1, 50);333else334ret = issue_nulldata(adapter, target_addr, 0, 3, 50);335}336337#ifdef CONFIG_RTW_MESH338if (MLME_IS_MESH(adapter)) {339struct rtw_mesh_path *mpath;340341rtw_rcu_read_lock();342mpath = rtw_mesh_path_lookup(adapter, target_addr);343if (!mpath) {344mpath = rtw_mesh_path_add(adapter, target_addr);345if (IS_ERR(mpath)) {346rtw_rcu_read_unlock();347RTW_ERR(FUNC_ADPT_FMT" rtw_mesh_path_add for "MAC_FMT" fail.\n",348FUNC_ADPT_ARG(adapter), MAC_ARG(target_addr));349return _FAIL;350}351}352if (mpath->flags & RTW_MESH_PATH_ACTIVE)353ret = _SUCCESS;354else {355u8 flags = RTW_PREQ_Q_F_START | RTW_PREQ_Q_F_PEER_AKA;356/* issue PREQ to check peer alive */357rtw_mesh_queue_preq(mpath, flags);358ret = _FALSE;359}360rtw_rcu_read_unlock();361}362#endif363return ret;364}365#endif366367#ifdef RTW_CONFIG_RFREG18_WA368static void rtw_check_restore_rf18(_adapter *padapter)369{370PHAL_DATA_TYPE pHalData = GET_HAL_DATA(padapter);371struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);372u32 reg;373u8 union_ch = 0, union_bw = 0, union_offset = 0, setchbw = _FALSE;374375reg = rtw_hal_read_rfreg(padapter, 0, 0x18, 0x3FF);376if ((reg & 0xFF) == 0)377setchbw = _TRUE;378reg = rtw_hal_read_rfreg(padapter, 1, 0x18, 0x3FF);379if ((reg & 0xFF) == 0)380setchbw = _TRUE;381382if (setchbw) {383if (!rtw_mi_get_ch_setting_union(padapter, &union_ch, &union_bw, &union_offset)) {384RTW_INFO("Hit RF(0x18)=0!! restore original channel setting.\n");385union_ch = pmlmeext->cur_channel;386union_offset = pmlmeext->cur_ch_offset ;387union_bw = pmlmeext->cur_bwmode;388} else {389RTW_INFO("Hit RF(0x18)=0!! set ch(%x) offset(%x) bwmode(%x)\n", union_ch, union_offset, union_bw);390}391/* Initial the channel_bw setting procedure. */392pHalData->current_channel = 0;393set_channel_bwmode(padapter, union_ch, union_offset, union_bw);394}395}396#endif397398void expire_timeout_chk(_adapter *padapter)399{400_irqL irqL;401_list *phead, *plist;402u8 updated = _FALSE;403struct sta_info *psta = NULL;404struct sta_priv *pstapriv = &padapter->stapriv;405u8 chk_alive_num = 0;406char chk_alive_list[NUM_STA];407int i;408409#ifdef CONFIG_RTW_MESH410if (MLME_IS_MESH(padapter)411&& check_fwstate(&padapter->mlmepriv, WIFI_ASOC_STATE)412) {413struct rtw_mesh_cfg *mcfg = &padapter->mesh_cfg;414415rtw_mesh_path_expire(padapter);416417/* TBD: up layer timeout mechanism */418/* if (!mcfg->plink_timeout)419return; */420#ifndef CONFIG_ACTIVE_KEEP_ALIVE_CHECK421return;422#endif423}424#endif425426#ifdef CONFIG_MCC_MODE427/* then driver may check fail due to not recv client's frame under sitesurvey,428* don't expire timeout chk under MCC under sitesurvey */429430if (rtw_hal_mcc_link_status_chk(padapter, __func__) == _FALSE)431return;432#endif433434_enter_critical_bh(&pstapriv->auth_list_lock, &irqL);435436phead = &pstapriv->auth_list;437plist = get_next(phead);438439/* check auth_queue */440#ifdef DBG_EXPIRATION_CHK441if (rtw_end_of_queue_search(phead, plist) == _FALSE) {442RTW_INFO(FUNC_ADPT_FMT" auth_list, cnt:%u\n"443, FUNC_ADPT_ARG(padapter), pstapriv->auth_list_cnt);444}445#endif446while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {447psta = LIST_CONTAINOR(plist, struct sta_info, auth_list);448449plist = get_next(plist);450451452#ifdef CONFIG_ATMEL_RC_PATCH453if (_rtw_memcmp((void *)(pstapriv->atmel_rc_pattern), (void *)(psta->cmn.mac_addr), ETH_ALEN) == _TRUE)454continue;455if (psta->flag_atmel_rc)456continue;457#endif458if (psta->expire_to > 0) {459psta->expire_to--;460if (psta->expire_to == 0) {461rtw_list_delete(&psta->auth_list);462pstapriv->auth_list_cnt--;463464RTW_INFO(FUNC_ADPT_FMT" auth expire "MAC_FMT"\n"465, FUNC_ADPT_ARG(padapter), MAC_ARG(psta->cmn.mac_addr));466467_exit_critical_bh(&pstapriv->auth_list_lock, &irqL);468469/* _enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL); */470rtw_free_stainfo(padapter, psta);471/* _exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL); */472473_enter_critical_bh(&pstapriv->auth_list_lock, &irqL);474}475}476477}478479_exit_critical_bh(&pstapriv->auth_list_lock, &irqL);480psta = NULL;481482483_enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);484485phead = &pstapriv->asoc_list;486plist = get_next(phead);487488/* check asoc_queue */489#ifdef DBG_EXPIRATION_CHK490if (rtw_end_of_queue_search(phead, plist) == _FALSE) {491RTW_INFO(FUNC_ADPT_FMT" asoc_list, cnt:%u\n"492, FUNC_ADPT_ARG(padapter), pstapriv->asoc_list_cnt);493}494#endif495while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {496psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);497plist = get_next(plist);498#ifdef CONFIG_ATMEL_RC_PATCH499RTW_INFO("%s:%d psta=%p, %02x,%02x||%02x,%02x \n\n", __func__, __LINE__,500psta, pstapriv->atmel_rc_pattern[0], pstapriv->atmel_rc_pattern[5], psta->cmn.mac_addr[0], psta->cmn.mac_addr[5]);501if (_rtw_memcmp((void *)pstapriv->atmel_rc_pattern, (void *)(psta->cmn.mac_addr), ETH_ALEN) == _TRUE)502continue;503if (psta->flag_atmel_rc)504continue;505RTW_INFO("%s: debug line:%d\n", __func__, __LINE__);506#endif507#ifdef CONFIG_AUTO_AP_MODE508if (psta->isrc)509continue;510#endif511if (chk_sta_is_alive(psta) || !psta->expire_to) {512psta->expire_to = pstapriv->expire_to;513psta->keep_alive_trycnt = 0;514#ifdef CONFIG_TX_MCAST2UNI515psta->under_exist_checking = 0;516#endif /* CONFIG_TX_MCAST2UNI */517} else518psta->expire_to--;519520#ifndef CONFIG_ACTIVE_KEEP_ALIVE_CHECK521#ifdef CONFIG_80211N_HT522#ifdef CONFIG_TX_MCAST2UNI523if ((psta->flags & WLAN_STA_HT) && (psta->htpriv.agg_enable_bitmap || psta->under_exist_checking)) {524/* check sta by delba(addba) for 11n STA */525/* ToDo: use CCX report to check for all STAs */526/* 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); */527528if (psta->expire_to <= (pstapriv->expire_to - 50)) {529RTW_INFO("asoc expire by DELBA/ADDBA! (%d s)\n", (pstapriv->expire_to - psta->expire_to) * 2);530psta->under_exist_checking = 0;531psta->expire_to = 0;532} else if (psta->expire_to <= (pstapriv->expire_to - 3) && (psta->under_exist_checking == 0)) {533RTW_INFO("asoc check by DELBA/ADDBA! (%d s)\n", (pstapriv->expire_to - psta->expire_to) * 2);534psta->under_exist_checking = 1;535/* tear down TX AMPDU */536send_delba(padapter, 1, psta->cmn.mac_addr);/* */ /* originator */537psta->htpriv.agg_enable_bitmap = 0x0;/* reset */538psta->htpriv.candidate_tid_bitmap = 0x0;/* reset */539}540}541#endif /* CONFIG_TX_MCAST2UNI */542#endif /* CONFIG_80211N_HT */543#endif /* CONFIG_ACTIVE_KEEP_ALIVE_CHECK */544545if (psta->expire_to <= 0) {546struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;547548if (padapter->registrypriv.wifi_spec == 1) {549psta->expire_to = pstapriv->expire_to;550continue;551}552553#ifndef CONFIG_ACTIVE_KEEP_ALIVE_CHECK554#ifdef CONFIG_80211N_HT555556#define KEEP_ALIVE_TRYCNT (3)557558if (psta->keep_alive_trycnt > 0 && psta->keep_alive_trycnt <= KEEP_ALIVE_TRYCNT) {559if (psta->state & WIFI_STA_ALIVE_CHK_STATE)560psta->state ^= WIFI_STA_ALIVE_CHK_STATE;561else562psta->keep_alive_trycnt = 0;563564} else if ((psta->keep_alive_trycnt > KEEP_ALIVE_TRYCNT) && !(psta->state & WIFI_STA_ALIVE_CHK_STATE))565psta->keep_alive_trycnt = 0;566if ((psta->htpriv.ht_option == _TRUE) && (psta->htpriv.ampdu_enable == _TRUE)) {567uint priority = 1; /* test using BK */568u8 issued = 0;569570/* issued = (psta->htpriv.agg_enable_bitmap>>priority)&0x1; */571issued |= (psta->htpriv.candidate_tid_bitmap >> priority) & 0x1;572573if (0 == issued) {574if (!(psta->state & WIFI_STA_ALIVE_CHK_STATE)) {575psta->htpriv.candidate_tid_bitmap |= BIT((u8)priority);576577if (psta->state & WIFI_SLEEP_STATE)578psta->expire_to = 2; /* 2x2=4 sec */579else580psta->expire_to = 1; /* 2 sec */581582psta->state |= WIFI_STA_ALIVE_CHK_STATE;583584/* add_ba_hdl(padapter, (u8*)paddbareq_parm); */585586RTW_INFO("issue addba_req to check if sta alive, keep_alive_trycnt=%d\n", psta->keep_alive_trycnt);587588issue_addba_req(padapter, psta->cmn.mac_addr, (u8)priority);589590_set_timer(&psta->addba_retry_timer, ADDBA_TO);591592psta->keep_alive_trycnt++;593594continue;595}596}597}598if (psta->keep_alive_trycnt > 0 && psta->state & WIFI_STA_ALIVE_CHK_STATE) {599psta->keep_alive_trycnt = 0;600psta->state ^= WIFI_STA_ALIVE_CHK_STATE;601RTW_INFO("change to another methods to check alive if staion is at ps mode\n");602}603604#endif /* CONFIG_80211N_HT */605#endif /* CONFIG_ACTIVE_KEEP_ALIVE_CHECK */606if (psta->state & WIFI_SLEEP_STATE) {607if (!(psta->state & WIFI_STA_ALIVE_CHK_STATE)) {608/* to check if alive by another methods if staion is at ps mode. */609psta->expire_to = pstapriv->expire_to;610psta->state |= WIFI_STA_ALIVE_CHK_STATE;611612/* RTW_INFO("alive chk, sta:" MAC_FMT " is at ps mode!\n", MAC_ARG(psta->cmn.mac_addr)); */613614/* to update bcn with tim_bitmap for this station */615rtw_tim_map_set(padapter, pstapriv->tim_bitmap, psta->cmn.aid);616update_beacon(padapter, _TIM_IE_, NULL, _TRUE, 0);617618if (!pmlmeext->active_keep_alive_check)619continue;620}621}622623{624int stainfo_offset;625626stainfo_offset = rtw_stainfo_offset(pstapriv, psta);627if (stainfo_offset_valid(stainfo_offset))628chk_alive_list[chk_alive_num++] = stainfo_offset;629continue;630}631} else {632/* TODO: Aging mechanism to digest frames in sleep_q to avoid running out of xmitframe */633if (psta->sleepq_len > (NR_XMITFRAME / pstapriv->asoc_list_cnt)634&& padapter->xmitpriv.free_xmitframe_cnt < ((NR_XMITFRAME / pstapriv->asoc_list_cnt) / 2)635) {636RTW_INFO(FUNC_ADPT_FMT" sta:"MAC_FMT", sleepq_len:%u, free_xmitframe_cnt:%u, asoc_list_cnt:%u, clear sleep_q\n"637, FUNC_ADPT_ARG(padapter), MAC_ARG(psta->cmn.mac_addr)638, psta->sleepq_len, padapter->xmitpriv.free_xmitframe_cnt, pstapriv->asoc_list_cnt);639wakeup_sta_to_xmit(padapter, psta);640}641}642}643644_exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);645646if (chk_alive_num) {647#if defined(CONFIG_ACTIVE_KEEP_ALIVE_CHECK)648u8 backup_ch = 0, backup_bw = 0, backup_offset = 0;649u8 union_ch = 0, union_bw = 0, union_offset = 0;650u8 switch_channel_by_drv = _TRUE;651struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;652#endif653char del_asoc_list[NUM_STA];654655_rtw_memset(del_asoc_list, NUM_STA, NUM_STA);656657#ifdef CONFIG_ACTIVE_KEEP_ALIVE_CHECK658if (pmlmeext->active_keep_alive_check) {659#ifdef CONFIG_MCC_MODE660if (MCC_EN(padapter)) {661/* driver doesn't switch channel under MCC */662if (rtw_hal_check_mcc_status(padapter, MCC_STATUS_DOING_MCC))663switch_channel_by_drv = _FALSE;664}665#endif666667if (!rtw_mi_get_ch_setting_union(padapter, &union_ch, &union_bw, &union_offset)668|| pmlmeext->cur_channel != union_ch)669switch_channel_by_drv = _FALSE;670671/* switch to correct channel of current network before issue keep-alive frames */672if (switch_channel_by_drv == _TRUE && rtw_get_oper_ch(padapter) != pmlmeext->cur_channel) {673backup_ch = rtw_get_oper_ch(padapter);674backup_bw = rtw_get_oper_bw(padapter);675backup_offset = rtw_get_oper_choffset(padapter);676set_channel_bwmode(padapter, union_ch, union_offset, union_bw);677}678}679#endif /* CONFIG_ACTIVE_KEEP_ALIVE_CHECK */680681/* check loop */682for (i = 0; i < chk_alive_num; i++) {683#ifdef CONFIG_ACTIVE_KEEP_ALIVE_CHECK684int ret = _FAIL;685#endif686687psta = rtw_get_stainfo_by_offset(pstapriv, chk_alive_list[i]);688689#ifdef CONFIG_ATMEL_RC_PATCH690if (_rtw_memcmp(pstapriv->atmel_rc_pattern, psta->cmn.mac_addr, ETH_ALEN) == _TRUE)691continue;692if (psta->flag_atmel_rc)693continue;694#endif695696if (!(psta->state & _FW_LINKED))697continue;698699#ifdef CONFIG_ACTIVE_KEEP_ALIVE_CHECK700if (pmlmeext->active_keep_alive_check) {701/* issue active keep alive frame to check */702ret = issue_aka_chk_frame(padapter, psta);703704psta->keep_alive_trycnt++;705if (ret == _SUCCESS) {706RTW_INFO(FUNC_ADPT_FMT" asoc check, "MAC_FMT" is alive\n"707, FUNC_ADPT_ARG(padapter), MAC_ARG(psta->cmn.mac_addr));708psta->expire_to = pstapriv->expire_to;709psta->keep_alive_trycnt = 0;710continue;711} else if (psta->keep_alive_trycnt <= 3) {712RTW_INFO(FUNC_ADPT_FMT" asoc check, "MAC_FMT" keep_alive_trycnt=%d\n"713, FUNC_ADPT_ARG(padapter) , MAC_ARG(psta->cmn.mac_addr), psta->keep_alive_trycnt);714psta->expire_to = 1;715continue;716}717}718#endif /* CONFIG_ACTIVE_KEEP_ALIVE_CHECK */719720psta->keep_alive_trycnt = 0;721del_asoc_list[i] = chk_alive_list[i];722_enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);723if (rtw_is_list_empty(&psta->asoc_list) == _FALSE) {724rtw_list_delete(&psta->asoc_list);725pstapriv->asoc_list_cnt--;726STA_SET_MESH_PLINK(psta, NULL);727}728_exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);729}730731/* delete loop */732for (i = 0; i < chk_alive_num; i++) {733u8 sta_addr[ETH_ALEN];734735if (del_asoc_list[i] >= NUM_STA)736continue;737738psta = rtw_get_stainfo_by_offset(pstapriv, del_asoc_list[i]);739_rtw_memcpy(sta_addr, psta->cmn.mac_addr, ETH_ALEN);740741RTW_INFO(FUNC_ADPT_FMT" asoc expire "MAC_FMT", state=0x%x\n"742, FUNC_ADPT_ARG(padapter), MAC_ARG(psta->cmn.mac_addr), psta->state);743#ifdef CONFIG_ACTIVE_KEEP_ALIVE_CHECK744updated |= ap_free_sta(padapter, psta, _FALSE, WLAN_REASON_DEAUTH_LEAVING, _FALSE);745#else746updated |= ap_free_sta(padapter, psta, _FALSE, WLAN_REASON_DEAUTH_LEAVING, _TRUE);747#endif748#ifdef CONFIG_RTW_MESH749if (MLME_IS_MESH(padapter))750rtw_mesh_expire_peer(padapter, sta_addr);751#endif752}753754#ifdef CONFIG_ACTIVE_KEEP_ALIVE_CHECK755if (pmlmeext->active_keep_alive_check) {756/* back to the original operation channel */757if (switch_channel_by_drv == _TRUE && backup_ch > 0)758set_channel_bwmode(padapter, backup_ch, backup_offset, backup_bw);759}760#endif761}762763#ifdef RTW_CONFIG_RFREG18_WA764rtw_check_restore_rf18(padapter);765#endif766associated_clients_update(padapter, updated, STA_INFO_UPDATE_ALL);767}768769void rtw_ap_update_sta_ra_info(_adapter *padapter, struct sta_info *psta)770{771unsigned char sta_band = 0;772u64 tx_ra_bitmap = 0;773struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);774WLAN_BSSID_EX *pcur_network = (WLAN_BSSID_EX *)&pmlmepriv->cur_network.network;775776if (!psta)777return;778779if (!(psta->state & _FW_LINKED))780return;781782rtw_hal_update_sta_ra_info(padapter, psta);783tx_ra_bitmap = psta->cmn.ra_info.ramask;784785if (pcur_network->Configuration.DSConfig > 14) {786787if (tx_ra_bitmap & 0xffff000)788sta_band |= WIRELESS_11_5N;789790if (tx_ra_bitmap & 0xff0)791sta_band |= WIRELESS_11A;792793/* 5G band */794#ifdef CONFIG_80211AC_VHT795if (psta->vhtpriv.vht_option)796sta_band = WIRELESS_11_5AC;797#endif798} else {799if (tx_ra_bitmap & 0xffff000)800sta_band |= WIRELESS_11_24N;801802if (tx_ra_bitmap & 0xff0)803sta_band |= WIRELESS_11G;804805if (tx_ra_bitmap & 0x0f)806sta_band |= WIRELESS_11B;807}808809psta->wireless_mode = sta_band;810rtw_hal_update_sta_wset(padapter, psta);811RTW_INFO("%s=> mac_id:%d , tx_ra_bitmap:0x%016llx, networkType:0x%02x\n",812__FUNCTION__, psta->cmn.mac_id, tx_ra_bitmap, psta->wireless_mode);813}814815#ifdef CONFIG_BMC_TX_RATE_SELECT816u8 rtw_ap_find_mini_tx_rate(_adapter *adapter)817{818_irqL irqL;819_list *phead, *plist;820u8 miini_tx_rate = ODM_RATEVHTSS4MCS9, sta_tx_rate;821struct sta_info *psta = NULL;822struct sta_priv *pstapriv = &adapter->stapriv;823824_enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);825phead = &pstapriv->asoc_list;826plist = get_next(phead);827while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {828psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);829plist = get_next(plist);830831sta_tx_rate = psta->cmn.ra_info.curr_tx_rate & 0x7F;832if (sta_tx_rate < miini_tx_rate)833miini_tx_rate = sta_tx_rate;834}835_exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);836837return miini_tx_rate;838}839840u8 rtw_ap_find_bmc_rate(_adapter *adapter, u8 tx_rate)841{842PHAL_DATA_TYPE hal_data = GET_HAL_DATA(adapter);843u8 tx_ini_rate = ODM_RATE6M;844845switch (tx_rate) {846case ODM_RATEVHTSS3MCS9:847case ODM_RATEVHTSS3MCS8:848case ODM_RATEVHTSS3MCS7:849case ODM_RATEVHTSS3MCS6:850case ODM_RATEVHTSS3MCS5:851case ODM_RATEVHTSS3MCS4:852case ODM_RATEVHTSS3MCS3:853case ODM_RATEVHTSS2MCS9:854case ODM_RATEVHTSS2MCS8:855case ODM_RATEVHTSS2MCS7:856case ODM_RATEVHTSS2MCS6:857case ODM_RATEVHTSS2MCS5:858case ODM_RATEVHTSS2MCS4:859case ODM_RATEVHTSS2MCS3:860case ODM_RATEVHTSS1MCS9:861case ODM_RATEVHTSS1MCS8:862case ODM_RATEVHTSS1MCS7:863case ODM_RATEVHTSS1MCS6:864case ODM_RATEVHTSS1MCS5:865case ODM_RATEVHTSS1MCS4:866case ODM_RATEVHTSS1MCS3:867case ODM_RATEMCS15:868case ODM_RATEMCS14:869case ODM_RATEMCS13:870case ODM_RATEMCS12:871case ODM_RATEMCS11:872case ODM_RATEMCS7:873case ODM_RATEMCS6:874case ODM_RATEMCS5:875case ODM_RATEMCS4:876case ODM_RATEMCS3:877case ODM_RATE54M:878case ODM_RATE48M:879case ODM_RATE36M:880case ODM_RATE24M:881tx_ini_rate = ODM_RATE24M;882break;883case ODM_RATEVHTSS3MCS2:884case ODM_RATEVHTSS3MCS1:885case ODM_RATEVHTSS2MCS2:886case ODM_RATEVHTSS2MCS1:887case ODM_RATEVHTSS1MCS2:888case ODM_RATEVHTSS1MCS1:889case ODM_RATEMCS10:890case ODM_RATEMCS9:891case ODM_RATEMCS2:892case ODM_RATEMCS1:893case ODM_RATE18M:894case ODM_RATE12M:895tx_ini_rate = ODM_RATE12M;896break;897case ODM_RATEVHTSS3MCS0:898case ODM_RATEVHTSS2MCS0:899case ODM_RATEVHTSS1MCS0:900case ODM_RATEMCS8:901case ODM_RATEMCS0:902case ODM_RATE9M:903case ODM_RATE6M:904tx_ini_rate = ODM_RATE6M;905break;906case ODM_RATE11M:907case ODM_RATE5_5M:908case ODM_RATE2M:909case ODM_RATE1M:910tx_ini_rate = ODM_RATE1M;911break;912default:913tx_ini_rate = ODM_RATE6M;914break;915}916917if (hal_data->current_band_type == BAND_ON_5G)918if (tx_ini_rate < ODM_RATE6M)919tx_ini_rate = ODM_RATE6M;920921return tx_ini_rate;922}923924void rtw_update_bmc_sta_tx_rate(_adapter *adapter)925{926struct sta_info *psta = NULL;927u8 tx_rate;928929psta = rtw_get_bcmc_stainfo(adapter);930if (psta == NULL) {931RTW_ERR(ADPT_FMT "could not get bmc_sta !!\n", ADPT_ARG(adapter));932return;933}934935if (adapter->bmc_tx_rate != MGN_UNKNOWN) {936psta->init_rate = adapter->bmc_tx_rate;937goto _exit;938}939940if (adapter->stapriv.asoc_sta_count <= 2)941goto _exit;942943tx_rate = rtw_ap_find_mini_tx_rate(adapter);944#ifdef CONFIG_BMC_TX_LOW_RATE945tx_rate = rtw_ap_find_bmc_rate(adapter, tx_rate);946#endif947948psta->init_rate = hw_rate_to_m_rate(tx_rate);949950_exit:951RTW_INFO(ADPT_FMT" BMC Tx rate - %s\n", ADPT_ARG(adapter), MGN_RATE_STR(psta->init_rate));952}953#endif954955void rtw_init_bmc_sta_tx_rate(_adapter *padapter, struct sta_info *psta)956{957#ifdef CONFIG_BMC_TX_LOW_RATE958struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);959#endif960u8 rate_idx = 0;961u8 brate_table[] = {MGN_1M, MGN_2M, MGN_5_5M, MGN_11M,962MGN_6M, MGN_9M, MGN_12M, MGN_18M, MGN_24M, MGN_36M, MGN_48M, MGN_54M};963964if (!MLME_IS_AP(padapter) && !MLME_IS_MESH(padapter))965return;966967if (padapter->bmc_tx_rate != MGN_UNKNOWN)968psta->init_rate = padapter->bmc_tx_rate;969else {970#ifdef CONFIG_BMC_TX_LOW_RATE971if (IsEnableHWOFDM(pmlmeext->cur_wireless_mode) && (psta->cmn.ra_info.ramask && 0xFF0))972rate_idx = get_lowest_rate_idx_ex(psta->cmn.ra_info.ramask, 4); /*from basic rate*/973else974rate_idx = get_lowest_rate_idx(psta->cmn.ra_info.ramask); /*from basic rate*/975#else976rate_idx = get_highest_rate_idx(psta->cmn.ra_info.ramask); /*from basic rate*/977#endif978if (rate_idx < 12)979psta->init_rate = brate_table[rate_idx];980else981psta->init_rate = MGN_1M;982}983984RTW_INFO(ADPT_FMT" BMC Init Tx rate - %s\n", ADPT_ARG(padapter), MGN_RATE_STR(psta->init_rate));985}986987void update_bmc_sta(_adapter *padapter)988{989_irqL irqL;990unsigned char network_type;991int supportRateNum = 0;992struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);993WLAN_BSSID_EX *pcur_network = (WLAN_BSSID_EX *)&pmlmepriv->cur_network.network;994struct sta_info *psta = rtw_get_bcmc_stainfo(padapter);995996if (psta) {997psta->cmn.aid = 0;/* default set to 0 */998#ifdef CONFIG_RTW_MESH999if (MLME_IS_MESH(padapter))1000psta->qos_option = 1;1001else1002#endif1003psta->qos_option = 0;1004#ifdef CONFIG_80211N_HT1005psta->htpriv.ht_option = _FALSE;1006#endif /* CONFIG_80211N_HT */10071008psta->ieee8021x_blocked = 0;10091010_rtw_memset((void *)&psta->sta_stats, 0, sizeof(struct stainfo_stats));10111012/* psta->dot118021XPrivacy = _NO_PRIVACY_; */ /* !!! remove it, because it has been set before this. */10131014supportRateNum = rtw_get_rateset_len((u8 *)&pcur_network->SupportedRates);1015network_type = rtw_check_network_type((u8 *)&pcur_network->SupportedRates, supportRateNum, pcur_network->Configuration.DSConfig);1016if (IsSupportedTxCCK(network_type))1017network_type = WIRELESS_11B;1018else if (network_type == WIRELESS_INVALID) { /* error handling */1019if (pcur_network->Configuration.DSConfig > 14)1020network_type = WIRELESS_11A;1021else1022network_type = WIRELESS_11B;1023}1024update_sta_basic_rate(psta, network_type);1025psta->wireless_mode = network_type;10261027rtw_hal_update_sta_ra_info(padapter, psta);10281029_enter_critical_bh(&psta->lock, &irqL);1030psta->state = _FW_LINKED;1031_exit_critical_bh(&psta->lock, &irqL);10321033rtw_sta_media_status_rpt(padapter, psta, 1);1034rtw_init_bmc_sta_tx_rate(padapter, psta);10351036} else1037RTW_INFO("add_RATid_bmc_sta error!\n");10381039}10401041#if defined(CONFIG_80211N_HT) && defined(CONFIG_BEAMFORMING)1042void update_sta_info_apmode_ht_bf_cap(_adapter *padapter, struct sta_info *psta)1043{1044struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);1045struct ht_priv *phtpriv_ap = &pmlmepriv->htpriv;1046struct ht_priv *phtpriv_sta = &psta->htpriv;10471048u8 cur_beamform_cap = 0;10491050/*Config Tx beamforming setting*/1051if (TEST_FLAG(phtpriv_ap->beamform_cap, BEAMFORMING_HT_BEAMFORMEE_ENABLE) &&1052GET_HT_CAP_TXBF_EXPLICIT_COMP_STEERING_CAP((u8 *)(&phtpriv_sta->ht_cap))) {1053SET_FLAG(cur_beamform_cap, BEAMFORMING_HT_BEAMFORMER_ENABLE);1054/*Shift to BEAMFORMING_HT_BEAMFORMEE_CHNL_EST_CAP*/1055SET_FLAG(cur_beamform_cap, GET_HT_CAP_TXBF_CHNL_ESTIMATION_NUM_ANTENNAS((u8 *)(&phtpriv_sta->ht_cap)) << 6);1056}10571058if (TEST_FLAG(phtpriv_ap->beamform_cap, BEAMFORMING_HT_BEAMFORMER_ENABLE) &&1059GET_HT_CAP_TXBF_EXPLICIT_COMP_FEEDBACK_CAP((u8 *)(&phtpriv_sta->ht_cap))) {1060SET_FLAG(cur_beamform_cap, BEAMFORMING_HT_BEAMFORMEE_ENABLE);1061/*Shift to BEAMFORMING_HT_BEAMFORMER_STEER_NUM*/1062SET_FLAG(cur_beamform_cap, GET_HT_CAP_TXBF_COMP_STEERING_NUM_ANTENNAS((u8 *)(&phtpriv_sta->ht_cap)) << 4);1063}1064if (cur_beamform_cap)1065RTW_INFO("Client STA(%d) HT Beamforming Cap = 0x%02X\n", psta->cmn.aid, cur_beamform_cap);10661067phtpriv_sta->beamform_cap = cur_beamform_cap;1068psta->cmn.bf_info.ht_beamform_cap = cur_beamform_cap;10691070}1071#endif /*CONFIG_80211N_HT && CONFIG_BEAMFORMING*/10721073/* notes:1074* AID: 1~MAX for sta and 0 for bc/mc in ap/adhoc mode */1075void update_sta_info_apmode(_adapter *padapter, struct sta_info *psta)1076{1077_irqL irqL;1078struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);1079struct security_priv *psecuritypriv = &padapter->securitypriv;1080struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);1081#ifdef CONFIG_80211N_HT1082struct ht_priv *phtpriv_ap = &pmlmepriv->htpriv;1083struct ht_priv *phtpriv_sta = &psta->htpriv;1084#endif /* CONFIG_80211N_HT */1085u8 cur_ldpc_cap = 0, cur_stbc_cap = 0;1086/* set intf_tag to if1 */1087/* psta->intf_tag = 0; */10881089RTW_INFO("%s\n", __FUNCTION__);10901091/*alloc macid when call rtw_alloc_stainfo(),release macid when call rtw_free_stainfo()*/10921093if (!MLME_IS_MESH(padapter) && psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X)1094psta->ieee8021x_blocked = _TRUE;1095else1096psta->ieee8021x_blocked = _FALSE;109710981099/* update sta's cap */11001101/* ERP */1102VCS_update(padapter, psta);1103#ifdef CONFIG_80211N_HT1104/* HT related cap */1105if (phtpriv_sta->ht_option) {1106/* check if sta supports rx ampdu */1107phtpriv_sta->ampdu_enable = phtpriv_ap->ampdu_enable;11081109phtpriv_sta->rx_ampdu_min_spacing = (phtpriv_sta->ht_cap.ampdu_params_info & IEEE80211_HT_CAP_AMPDU_DENSITY) >> 2;11101111/* bwmode */1112if ((phtpriv_sta->ht_cap.cap_info & phtpriv_ap->ht_cap.cap_info) & cpu_to_le16(IEEE80211_HT_CAP_SUP_WIDTH))1113psta->cmn.bw_mode = CHANNEL_WIDTH_40;1114else1115psta->cmn.bw_mode = CHANNEL_WIDTH_20;11161117if (phtpriv_sta->op_present1118&& !GET_HT_OP_ELE_STA_CHL_WIDTH(phtpriv_sta->ht_op))1119psta->cmn.bw_mode = CHANNEL_WIDTH_20;11201121if (psta->ht_40mhz_intolerant)1122psta->cmn.bw_mode = CHANNEL_WIDTH_20;11231124if (pmlmeext->cur_bwmode < psta->cmn.bw_mode)1125psta->cmn.bw_mode = pmlmeext->cur_bwmode;11261127phtpriv_sta->ch_offset = pmlmeext->cur_ch_offset;112811291130/* check if sta support s Short GI 20M */1131if ((phtpriv_sta->ht_cap.cap_info & phtpriv_ap->ht_cap.cap_info) & cpu_to_le16(IEEE80211_HT_CAP_SGI_20))1132phtpriv_sta->sgi_20m = _TRUE;11331134/* check if sta support s Short GI 40M */1135if ((phtpriv_sta->ht_cap.cap_info & phtpriv_ap->ht_cap.cap_info) & cpu_to_le16(IEEE80211_HT_CAP_SGI_40)) {1136if (psta->cmn.bw_mode == CHANNEL_WIDTH_40) /* according to psta->bw_mode */1137phtpriv_sta->sgi_40m = _TRUE;1138else1139phtpriv_sta->sgi_40m = _FALSE;1140}11411142psta->qos_option = _TRUE;11431144/* B0 Config LDPC Coding Capability */1145if (TEST_FLAG(phtpriv_ap->ldpc_cap, LDPC_HT_ENABLE_TX) &&1146GET_HT_CAP_ELE_LDPC_CAP((u8 *)(&phtpriv_sta->ht_cap))) {1147SET_FLAG(cur_ldpc_cap, (LDPC_HT_ENABLE_TX | LDPC_HT_CAP_TX));1148RTW_INFO("Enable HT Tx LDPC for STA(%d)\n", psta->cmn.aid);1149}11501151/* B7 B8 B9 Config STBC setting */1152if (TEST_FLAG(phtpriv_ap->stbc_cap, STBC_HT_ENABLE_TX) &&1153GET_HT_CAP_ELE_RX_STBC((u8 *)(&phtpriv_sta->ht_cap))) {1154SET_FLAG(cur_stbc_cap, (STBC_HT_ENABLE_TX | STBC_HT_CAP_TX));1155RTW_INFO("Enable HT Tx STBC for STA(%d)\n", psta->cmn.aid);1156}11571158#ifdef CONFIG_BEAMFORMING1159update_sta_info_apmode_ht_bf_cap(padapter, psta);1160#endif1161} else {1162phtpriv_sta->ampdu_enable = _FALSE;11631164phtpriv_sta->sgi_20m = _FALSE;1165phtpriv_sta->sgi_40m = _FALSE;1166psta->cmn.bw_mode = CHANNEL_WIDTH_20;1167phtpriv_sta->ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;1168}11691170phtpriv_sta->ldpc_cap = cur_ldpc_cap;1171phtpriv_sta->stbc_cap = cur_stbc_cap;11721173/* Rx AMPDU */1174send_delba(padapter, 0, psta->cmn.mac_addr);/* recipient */11751176/* TX AMPDU */1177send_delba(padapter, 1, psta->cmn.mac_addr);/* */ /* originator */1178phtpriv_sta->agg_enable_bitmap = 0x0;/* reset */1179phtpriv_sta->candidate_tid_bitmap = 0x0;/* reset */1180#endif /* CONFIG_80211N_HT */11811182#ifdef CONFIG_80211AC_VHT1183update_sta_vht_info_apmode(padapter, psta);1184#endif1185psta->cmn.ra_info.is_support_sgi = query_ra_short_GI(psta, rtw_get_tx_bw_mode(padapter, psta));1186update_ldpc_stbc_cap(psta);11871188/* todo: init other variables */11891190_rtw_memset((void *)&psta->sta_stats, 0, sizeof(struct stainfo_stats));119111921193/* add ratid */1194/* add_RATid(padapter, psta); */ /* move to ap_sta_info_defer_update() */11951196/* ap mode */1197rtw_hal_set_odm_var(padapter, HAL_ODM_STA_INFO, psta, _TRUE);11981199_enter_critical_bh(&psta->lock, &irqL);12001201/* Check encryption */1202if (!MLME_IS_MESH(padapter) && psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X)1203psta->state |= WIFI_UNDER_KEY_HANDSHAKE;12041205psta->state |= _FW_LINKED;12061207_exit_critical_bh(&psta->lock, &irqL);1208}12091210static void update_ap_info(_adapter *padapter, struct sta_info *psta)1211{1212struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);1213WLAN_BSSID_EX *pnetwork = (WLAN_BSSID_EX *)&pmlmepriv->cur_network.network;1214struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);1215#ifdef CONFIG_80211N_HT1216struct ht_priv *phtpriv_ap = &pmlmepriv->htpriv;1217#endif /* CONFIG_80211N_HT */12181219psta->wireless_mode = pmlmeext->cur_wireless_mode;12201221psta->bssratelen = rtw_get_rateset_len(pnetwork->SupportedRates);1222_rtw_memcpy(psta->bssrateset, pnetwork->SupportedRates, psta->bssratelen);12231224#ifdef CONFIG_80211N_HT1225/* HT related cap */1226if (phtpriv_ap->ht_option) {1227/* check if sta supports rx ampdu */1228/* phtpriv_ap->ampdu_enable = phtpriv_ap->ampdu_enable; */12291230/* check if sta support s Short GI 20M */1231if ((phtpriv_ap->ht_cap.cap_info) & cpu_to_le16(IEEE80211_HT_CAP_SGI_20))1232phtpriv_ap->sgi_20m = _TRUE;1233/* check if sta support s Short GI 40M */1234if ((phtpriv_ap->ht_cap.cap_info) & cpu_to_le16(IEEE80211_HT_CAP_SGI_40))1235phtpriv_ap->sgi_40m = _TRUE;12361237psta->qos_option = _TRUE;1238} else {1239phtpriv_ap->ampdu_enable = _FALSE;12401241phtpriv_ap->sgi_20m = _FALSE;1242phtpriv_ap->sgi_40m = _FALSE;1243}12441245psta->cmn.bw_mode = pmlmeext->cur_bwmode;1246phtpriv_ap->ch_offset = pmlmeext->cur_ch_offset;12471248phtpriv_ap->agg_enable_bitmap = 0x0;/* reset */1249phtpriv_ap->candidate_tid_bitmap = 0x0;/* reset */12501251_rtw_memcpy(&psta->htpriv, &pmlmepriv->htpriv, sizeof(struct ht_priv));12521253#ifdef CONFIG_80211AC_VHT1254_rtw_memcpy(&psta->vhtpriv, &pmlmepriv->vhtpriv, sizeof(struct vht_priv));1255#endif /* CONFIG_80211AC_VHT */12561257#endif /* CONFIG_80211N_HT */12581259psta->state |= WIFI_AP_STATE; /* Aries, add,fix bug of flush_cam_entry at STOP AP mode , 0724 */1260}12611262static void rtw_set_hw_wmm_param(_adapter *padapter)1263{1264u8 AIFS, ECWMin, ECWMax, aSifsTime;1265u8 acm_mask;1266u16 TXOP;1267u32 acParm, i;1268u32 edca[4], inx[4];1269struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;1270struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);1271struct xmit_priv *pxmitpriv = &padapter->xmitpriv;1272struct registry_priv *pregpriv = &padapter->registrypriv;12731274acm_mask = 0;1275#ifdef CONFIG_80211N_HT1276if (pregpriv->ht_enable &&1277(is_supported_5g(pmlmeext->cur_wireless_mode) ||1278(pmlmeext->cur_wireless_mode & WIRELESS_11_24N)))1279aSifsTime = 16;1280else1281#endif /* CONFIG_80211N_HT */1282aSifsTime = 10;12831284if (pmlmeinfo->WMM_enable == 0) {1285padapter->mlmepriv.acm_mask = 0;12861287AIFS = aSifsTime + (2 * pmlmeinfo->slotTime);12881289if (pmlmeext->cur_wireless_mode & (WIRELESS_11G | WIRELESS_11A)) {1290ECWMin = 4;1291ECWMax = 10;1292} else if (pmlmeext->cur_wireless_mode & WIRELESS_11B) {1293ECWMin = 5;1294ECWMax = 10;1295} else {1296ECWMin = 4;1297ECWMax = 10;1298}12991300TXOP = 0;1301acParm = AIFS | (ECWMin << 8) | (ECWMax << 12) | (TXOP << 16);1302rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BE, (u8 *)(&acParm));1303rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BK, (u8 *)(&acParm));1304rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VI, (u8 *)(&acParm));13051306ECWMin = 2;1307ECWMax = 3;1308TXOP = 0x2f;1309acParm = AIFS | (ECWMin << 8) | (ECWMax << 12) | (TXOP << 16);1310rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VO, (u8 *)(&acParm));13111312} else {1313edca[0] = edca[1] = edca[2] = edca[3] = 0;13141315/*TODO:*/1316acm_mask = 0;1317padapter->mlmepriv.acm_mask = acm_mask;13181319#if 01320/* BK */1321/* AIFS = AIFSN * slot time + SIFS - r2t phy delay */1322#endif1323AIFS = (7 * pmlmeinfo->slotTime) + aSifsTime;1324ECWMin = 4;1325ECWMax = 10;1326TXOP = 0;1327acParm = AIFS | (ECWMin << 8) | (ECWMax << 12) | (TXOP << 16);1328rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BK, (u8 *)(&acParm));1329edca[XMIT_BK_QUEUE] = acParm;1330RTW_INFO("WMM(BK): %x\n", acParm);13311332/* BE */1333AIFS = (3 * pmlmeinfo->slotTime) + aSifsTime;1334ECWMin = 4;1335ECWMax = 6;1336TXOP = 0;1337acParm = AIFS | (ECWMin << 8) | (ECWMax << 12) | (TXOP << 16);1338rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BE, (u8 *)(&acParm));1339edca[XMIT_BE_QUEUE] = acParm;1340RTW_INFO("WMM(BE): %x\n", acParm);13411342/* VI */1343AIFS = (1 * pmlmeinfo->slotTime) + aSifsTime;1344ECWMin = 3;1345ECWMax = 4;1346TXOP = 94;1347acParm = AIFS | (ECWMin << 8) | (ECWMax << 12) | (TXOP << 16);1348rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VI, (u8 *)(&acParm));1349edca[XMIT_VI_QUEUE] = acParm;1350RTW_INFO("WMM(VI): %x\n", acParm);13511352/* VO */1353AIFS = (1 * pmlmeinfo->slotTime) + aSifsTime;1354ECWMin = 2;1355ECWMax = 3;1356TXOP = 47;1357acParm = AIFS | (ECWMin << 8) | (ECWMax << 12) | (TXOP << 16);1358rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VO, (u8 *)(&acParm));1359edca[XMIT_VO_QUEUE] = acParm;1360RTW_INFO("WMM(VO): %x\n", acParm);136113621363if (padapter->registrypriv.acm_method == 1)1364rtw_hal_set_hwreg(padapter, HW_VAR_ACM_CTRL, (u8 *)(&acm_mask));1365else1366padapter->mlmepriv.acm_mask = acm_mask;13671368inx[0] = 0;1369inx[1] = 1;1370inx[2] = 2;1371inx[3] = 3;13721373if (pregpriv->wifi_spec == 1) {1374u32 j, tmp, change_inx = _FALSE;13751376/* entry indx: 0->vo, 1->vi, 2->be, 3->bk. */1377for (i = 0 ; i < 4 ; i++) {1378for (j = i + 1 ; j < 4 ; j++) {1379/* compare CW and AIFS */1380if ((edca[j] & 0xFFFF) < (edca[i] & 0xFFFF))1381change_inx = _TRUE;1382else if ((edca[j] & 0xFFFF) == (edca[i] & 0xFFFF)) {1383/* compare TXOP */1384if ((edca[j] >> 16) > (edca[i] >> 16))1385change_inx = _TRUE;1386}13871388if (change_inx) {1389tmp = edca[i];1390edca[i] = edca[j];1391edca[j] = tmp;13921393tmp = inx[i];1394inx[i] = inx[j];1395inx[j] = tmp;13961397change_inx = _FALSE;1398}1399}1400}1401}14021403for (i = 0 ; i < 4 ; i++) {1404pxmitpriv->wmm_para_seq[i] = inx[i];1405RTW_INFO("wmm_para_seq(%d): %d\n", i, pxmitpriv->wmm_para_seq[i]);1406}14071408}14091410}1411#ifdef CONFIG_80211N_HT1412static void update_hw_ht_param(_adapter *padapter)1413{1414unsigned char max_AMPDU_len;1415unsigned char min_MPDU_spacing;1416struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;1417struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);14181419RTW_INFO("%s\n", __FUNCTION__);142014211422/* handle A-MPDU parameter field */1423/*1424AMPDU_para [1:0]:Max AMPDU Len => 0:8k , 1:16k, 2:32k, 3:64k1425AMPDU_para [4:2]:Min MPDU Start Spacing1426*/1427max_AMPDU_len = pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x03;14281429min_MPDU_spacing = (pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x1c) >> 2;14301431rtw_hal_set_hwreg(padapter, HW_VAR_AMPDU_MIN_SPACE, (u8 *)(&min_MPDU_spacing));14321433rtw_hal_set_hwreg(padapter, HW_VAR_AMPDU_FACTOR, (u8 *)(&max_AMPDU_len));14341435/* */1436/* Config SM Power Save setting */1437/* */1438pmlmeinfo->SM_PS = (pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info & 0x0C) >> 2;1439if (pmlmeinfo->SM_PS == WLAN_HT_CAP_SM_PS_STATIC) {1440#if 01441u8 i;1442/* update the MCS rates */1443for (i = 0; i < 16; i++)1444pmlmeinfo->HT_caps.HT_cap_element.MCS_rate[i] &= MCS_rate_1R[i];1445#endif1446RTW_INFO("%s(): WLAN_HT_CAP_SM_PS_STATIC\n", __FUNCTION__);1447}14481449/* */1450/* Config current HT Protection mode. */1451/* */1452/* pmlmeinfo->HT_protection = pmlmeinfo->HT_info.infos[1] & 0x3; */14531454}1455#endif /* CONFIG_80211N_HT */1456static void rtw_ap_check_scan(_adapter *padapter)1457{1458_irqL irqL;1459_list *plist, *phead;1460u32 delta_time, lifetime;1461struct wlan_network *pnetwork = NULL;1462WLAN_BSSID_EX *pbss = NULL;1463struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);1464_queue *queue = &(pmlmepriv->scanned_queue);1465u8 do_scan = _FALSE;1466u8 reason = RTW_AUTO_SCAN_REASON_UNSPECIFIED;14671468lifetime = SCANQUEUE_LIFETIME; /* 20 sec */14691470_enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);1471phead = get_list_head(queue);1472if (rtw_end_of_queue_search(phead, get_next(phead)) == _TRUE)1473if (padapter->registrypriv.wifi_spec) {1474do_scan = _TRUE;1475reason |= RTW_AUTO_SCAN_REASON_2040_BSS;1476}1477_exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);14781479#ifdef CONFIG_RTW_ACS1480if (padapter->registrypriv.acs_auto_scan) {1481do_scan = _TRUE;1482reason |= RTW_AUTO_SCAN_REASON_ACS;1483rtw_acs_start(padapter);1484}1485#endif/*CONFIG_RTW_ACS*/14861487if (_TRUE == do_scan) {1488RTW_INFO("%s : drv scans by itself and wait_completed\n", __func__);1489rtw_drv_scan_by_self(padapter, reason);1490rtw_scan_wait_completed(padapter);1491}14921493#ifdef CONFIG_RTW_ACS1494if (padapter->registrypriv.acs_auto_scan)1495rtw_acs_stop(padapter);1496#endif14971498_enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);14991500phead = get_list_head(queue);1501plist = get_next(phead);15021503while (1) {15041505if (rtw_end_of_queue_search(phead, plist) == _TRUE)1506break;15071508pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);15091510if (rtw_chset_search_ch(adapter_to_chset(padapter), pnetwork->network.Configuration.DSConfig) >= 01511&& rtw_mlme_band_check(padapter, pnetwork->network.Configuration.DSConfig) == _TRUE1512&& _TRUE == rtw_validate_ssid(&(pnetwork->network.Ssid))) {1513delta_time = (u32) rtw_get_passing_time_ms(pnetwork->last_scanned);15141515if (delta_time < lifetime) {15161517uint ie_len = 0;1518u8 *pbuf = NULL;1519u8 *ie = NULL;15201521pbss = &pnetwork->network;1522ie = pbss->IEs;15231524/*check if HT CAP INFO IE exists or not*/1525pbuf = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_CAPABILITY_IE_, &ie_len, (pbss->IELength - _BEACON_IE_OFFSET_));1526if (pbuf == NULL) {1527/* HT CAP INFO IE don't exist, it is b/g mode bss.*/15281529if (_FALSE == ATOMIC_READ(&pmlmepriv->olbc))1530ATOMIC_SET(&pmlmepriv->olbc, _TRUE);15311532if (_FALSE == ATOMIC_READ(&pmlmepriv->olbc_ht))1533ATOMIC_SET(&pmlmepriv->olbc_ht, _TRUE);15341535if (padapter->registrypriv.wifi_spec)1536RTW_INFO("%s: %s is a/b/g ap\n", __func__, pnetwork->network.Ssid.Ssid);1537}1538}1539}15401541plist = get_next(plist);15421543}15441545_exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);1546#ifdef CONFIG_80211N_HT1547pmlmepriv->num_sta_no_ht = 0; /* reset to 0 after ap do scanning*/1548#endif1549}15501551void rtw_start_bss_hdl_after_chbw_decided(_adapter *adapter)1552{1553WLAN_BSSID_EX *pnetwork = &(adapter->mlmepriv.cur_network.network);1554struct sta_info *sta = NULL;15551556/* update cur_wireless_mode */1557update_wireless_mode(adapter);15581559/* update RRSR and RTS_INIT_RATE register after set channel and bandwidth */1560UpdateBrateTbl(adapter, pnetwork->SupportedRates);1561rtw_hal_set_hwreg(adapter, HW_VAR_BASIC_RATE, pnetwork->SupportedRates);15621563/* update capability after cur_wireless_mode updated */1564update_capinfo(adapter, rtw_get_capability(pnetwork));15651566/* update bc/mc sta_info */1567update_bmc_sta(adapter);15681569/* update AP's sta info */1570sta = rtw_get_stainfo(&adapter->stapriv, pnetwork->MacAddress);1571if (!sta) {1572RTW_INFO(FUNC_ADPT_FMT" !sta for macaddr="MAC_FMT"\n", FUNC_ADPT_ARG(adapter), MAC_ARG(pnetwork->MacAddress));1573rtw_warn_on(1);1574return;1575}15761577update_ap_info(adapter, sta);1578}15791580#ifdef CONFIG_FW_HANDLE_TXBCN1581bool rtw_ap_nums_check(_adapter *adapter)1582{1583if (rtw_ap_get_nums(adapter) < CONFIG_LIMITED_AP_NUM)1584return _TRUE;1585return _FALSE;1586}1587u8 rtw_ap_allocate_vapid(struct dvobj_priv *dvobj)1588{1589u8 vap_id;15901591for (vap_id = 0; vap_id < CONFIG_LIMITED_AP_NUM; vap_id++) {1592if (!(dvobj->vap_map & BIT(vap_id)))1593break;1594}15951596if (vap_id < CONFIG_LIMITED_AP_NUM)1597dvobj->vap_map |= BIT(vap_id);15981599return vap_id;1600}1601u8 rtw_ap_release_vapid(struct dvobj_priv *dvobj, u8 vap_id)1602{1603if (vap_id >= CONFIG_LIMITED_AP_NUM) {1604RTW_ERR("%s - vapid(%d) failed\n", __func__, vap_id);1605rtw_warn_on(1);1606return _FAIL;1607}1608dvobj->vap_map &= ~ BIT(vap_id);1609return _SUCCESS;1610}1611#endif1612static void _rtw_iface_undersurvey_chk(const char *func, _adapter *adapter)1613{1614int i;1615_adapter *iface;1616struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);1617struct mlme_priv *pmlmepriv;16181619for (i = 0; i < dvobj->iface_nums; i++) {1620iface = dvobj->padapters[i];1621if ((iface) && rtw_is_adapter_up(iface)) {1622pmlmepriv = &iface->mlmepriv;1623if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY))1624RTW_ERR("%s ("ADPT_FMT") under survey\n", func, ADPT_ARG(iface));1625}1626}1627}1628void start_bss_network(_adapter *padapter, struct createbss_parm *parm)1629{1630#define DUMP_ADAPTERS_STATUS 01631u8 mlme_act = MLME_ACTION_UNKNOWN;1632u8 val8;1633u16 bcn_interval;1634u32 acparm;1635struct registry_priv *pregpriv = &padapter->registrypriv;1636struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);1637struct security_priv *psecuritypriv = &(padapter->securitypriv);1638WLAN_BSSID_EX *pnetwork = (WLAN_BSSID_EX *)&pmlmepriv->cur_network.network; /* used as input */1639struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);1640struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);1641WLAN_BSSID_EX *pnetwork_mlmeext = &(pmlmeinfo->network);1642struct dvobj_priv *pdvobj = padapter->dvobj;1643s16 req_ch = REQ_CH_NONE, req_bw = REQ_BW_NONE, req_offset = REQ_OFFSET_NONE;1644u8 ch_to_set = 0, bw_to_set, offset_to_set;1645u8 doiqk = _FALSE;1646/* use for check ch bw offset can be allowed or not */1647u8 chbw_allow = _TRUE;1648int i;1649u8 ifbmp_ch_changed = 0;16501651if (parm->req_ch != 0) {1652/* bypass other setting, go checking ch, bw, offset */1653mlme_act = MLME_OPCH_SWITCH;1654req_ch = parm->req_ch;1655req_bw = parm->req_bw;1656req_offset = parm->req_offset;1657goto chbw_decision;1658} else {1659/* request comes from upper layer */1660if (MLME_IS_AP(padapter))1661mlme_act = MLME_AP_STARTED;1662else if (MLME_IS_MESH(padapter))1663mlme_act = MLME_MESH_STARTED;1664else1665rtw_warn_on(1);1666req_ch = 0;1667_rtw_memcpy(pnetwork_mlmeext, pnetwork, pnetwork->Length);1668}16691670bcn_interval = (u16)pnetwork->Configuration.BeaconPeriod;16711672/* check if there is wps ie, */1673/* if there is wpsie in beacon, the hostapd will update beacon twice when stating hostapd, */1674/* and at first time the security ie ( RSN/WPA IE) will not include in beacon. */1675if (NULL == rtw_get_wps_ie(pnetwork->IEs + _FIXED_IE_LENGTH_, pnetwork->IELength - _FIXED_IE_LENGTH_, NULL, NULL))1676pmlmeext->bstart_bss = _TRUE;16771678/* todo: update wmm, ht cap */1679/* pmlmeinfo->WMM_enable; */1680/* pmlmeinfo->HT_enable; */1681if (pmlmepriv->qospriv.qos_option)1682pmlmeinfo->WMM_enable = _TRUE;1683#ifdef CONFIG_80211N_HT1684if (pmlmepriv->htpriv.ht_option) {1685pmlmeinfo->WMM_enable = _TRUE;1686pmlmeinfo->HT_enable = _TRUE;1687/* pmlmeinfo->HT_info_enable = _TRUE; */1688/* pmlmeinfo->HT_caps_enable = _TRUE; */16891690update_hw_ht_param(padapter);1691}1692#endif /* #CONFIG_80211N_HT */16931694#ifdef CONFIG_80211AC_VHT1695if (pmlmepriv->vhtpriv.vht_option) {1696pmlmeinfo->VHT_enable = _TRUE;1697update_hw_vht_param(padapter);1698}1699#endif /* CONFIG_80211AC_VHT */17001701if (pmlmepriv->cur_network.join_res != _TRUE) { /* setting only at first time */1702/* WEP Key will be set before this function, do not clear CAM. */1703if ((psecuritypriv->dot11PrivacyAlgrthm != _WEP40_) && (psecuritypriv->dot11PrivacyAlgrthm != _WEP104_)1704&& !MLME_IS_MESH(padapter) /* mesh group key is set before this function */1705)1706flush_all_cam_entry(padapter); /* clear CAM */1707}17081709/* set MSR to AP_Mode */1710Set_MSR(padapter, _HW_STATE_AP_);17111712/* Set BSSID REG */1713rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, pnetwork->MacAddress);17141715/* Set Security */1716val8 = (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) ? 0xcc : 0xcf;1717rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8));17181719/* Beacon Control related register */1720rtw_hal_set_hwreg(padapter, HW_VAR_BEACON_INTERVAL, (u8 *)(&bcn_interval));17211722rtw_hal_rcr_set_chk_bssid(padapter, mlme_act);17231724chbw_decision:1725ifbmp_ch_changed = rtw_ap_chbw_decision(padapter, parm->ifbmp, parm->excl_ifbmp1726, req_ch, req_bw, req_offset1727, &ch_to_set, &bw_to_set, &offset_to_set, &chbw_allow);17281729for (i = 0; i < pdvobj->iface_nums; i++) {1730if (!(parm->ifbmp & BIT(i)) || !pdvobj->padapters[i])1731continue;17321733/* let pnetwork_mlme == pnetwork_mlmeext */1734_rtw_memcpy(&(pdvobj->padapters[i]->mlmepriv.cur_network.network)1735, &(pdvobj->padapters[i]->mlmeextpriv.mlmext_info.network)1736, pdvobj->padapters[i]->mlmeextpriv.mlmext_info.network.Length);17371738rtw_start_bss_hdl_after_chbw_decided(pdvobj->padapters[i]);17391740/* Set EDCA param reg after update cur_wireless_mode & update_capinfo */1741if (pregpriv->wifi_spec == 1)1742rtw_set_hw_wmm_param(pdvobj->padapters[i]);1743}17441745#if defined(CONFIG_DFS_MASTER)1746rtw_dfs_rd_en_decision(padapter, mlme_act, parm->excl_ifbmp);1747#endif17481749#ifdef CONFIG_MCC_MODE1750if (MCC_EN(padapter)) {1751/*1752* due to check under rtw_ap_chbw_decision1753* if under MCC mode, means req channel setting is the same as current channel setting1754* if not under MCC mode, mean req channel setting is not the same as current channel setting1755*/1756if (rtw_hal_check_mcc_status(padapter, MCC_STATUS_DOING_MCC)) {1757RTW_INFO(FUNC_ADPT_FMT": req channel setting is the same as current channel setting, go to update BCN\n"1758, FUNC_ADPT_ARG(padapter));17591760goto update_beacon;17611762}1763}17641765/* issue null data to AP for all interface connecting to AP before switch channel setting for softap */1766rtw_hal_mcc_issue_null_data(padapter, chbw_allow, 1);1767#endif /* CONFIG_MCC_MODE */17681769if (!IS_CH_WAITING(adapter_to_rfctl(padapter))) {1770doiqk = _TRUE;1771rtw_hal_set_hwreg(padapter , HW_VAR_DO_IQK , &doiqk);1772}17731774if (ch_to_set != 0) {1775set_channel_bwmode(padapter, ch_to_set, offset_to_set, bw_to_set);1776rtw_mi_update_union_chan_inf(padapter, ch_to_set, offset_to_set, bw_to_set);1777}17781779doiqk = _FALSE;1780rtw_hal_set_hwreg(padapter , HW_VAR_DO_IQK , &doiqk);17811782#ifdef CONFIG_MCC_MODE1783/* after set_channel_bwmode for backup IQK */1784rtw_hal_set_mcc_setting_start_bss_network(padapter, chbw_allow);1785#endif17861787#if defined(CONFIG_IOCTL_CFG80211) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))1788for (i = 0; i < pdvobj->iface_nums; i++) {1789if (!(ifbmp_ch_changed & BIT(i)) || !pdvobj->padapters[i])1790continue;17911792{1793u8 ht_option = 0;17941795#ifdef CONFIG_80211N_HT1796ht_option = pdvobj->padapters[i]->mlmepriv.htpriv.ht_option;1797#endif17981799rtw_cfg80211_ch_switch_notify(pdvobj->padapters[i]1800, pdvobj->padapters[i]->mlmeextpriv.cur_channel1801, pdvobj->padapters[i]->mlmeextpriv.cur_bwmode1802, pdvobj->padapters[i]->mlmeextpriv.cur_ch_offset1803, ht_option1804, 0);1805}1806}1807#endif /* defined(CONFIG_IOCTL_CFG80211) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)) */18081809if (DUMP_ADAPTERS_STATUS) {1810RTW_INFO(FUNC_ADPT_FMT" done\n", FUNC_ADPT_ARG(padapter));1811dump_adapters_status(RTW_DBGDUMP , adapter_to_dvobj(padapter));1812}18131814#ifdef CONFIG_MCC_MODE1815update_beacon:1816#endif18171818for (i = 0; i < pdvobj->iface_nums; i++) {1819struct mlme_priv *mlme;18201821if (!(parm->ifbmp & BIT(i)) || !pdvobj->padapters[i])1822continue;18231824/* update beacon content only if bstart_bss is _TRUE */1825if (pdvobj->padapters[i]->mlmeextpriv.bstart_bss != _TRUE)1826continue;18271828mlme = &(pdvobj->padapters[i]->mlmepriv);18291830#ifdef CONFIG_80211N_HT1831if ((ATOMIC_READ(&mlme->olbc) == _TRUE) || (ATOMIC_READ(&mlme->olbc_ht) == _TRUE)) {1832/* AP is not starting a 40 MHz BSS in presence of an 802.11g BSS. */1833mlme->ht_op_mode &= (~HT_INFO_OPERATION_MODE_OP_MODE_MASK);1834mlme->ht_op_mode |= OP_MODE_MAY_BE_LEGACY_STAS;1835update_beacon(pdvobj->padapters[i], _HT_ADD_INFO_IE_, NULL, _FALSE, 0);1836}1837#endif18381839update_beacon(pdvobj->padapters[i], _TIM_IE_, NULL, _FALSE, 0);1840}18411842if (mlme_act != MLME_OPCH_SWITCH1843&& pmlmeext->bstart_bss == _TRUE1844) {1845#ifdef CONFIG_SUPPORT_MULTI_BCN1846_irqL irqL;18471848_enter_critical_bh(&pdvobj->ap_if_q.lock, &irqL);1849if (rtw_is_list_empty(&padapter->list)) {1850#ifdef CONFIG_FW_HANDLE_TXBCN1851padapter->vap_id = rtw_ap_allocate_vapid(pdvobj);1852#endif1853rtw_list_insert_tail(&padapter->list, get_list_head(&pdvobj->ap_if_q));1854pdvobj->nr_ap_if++;1855pdvobj->inter_bcn_space = DEFAULT_BCN_INTERVAL / pdvobj->nr_ap_if;1856}1857_exit_critical_bh(&pdvobj->ap_if_q.lock, &irqL);18581859#ifdef CONFIG_SWTIMER_BASED_TXBCN1860rtw_ap_set_mbid_num(padapter, pdvobj->nr_ap_if);1861rtw_hal_set_hwreg(padapter, HW_VAR_BEACON_INTERVAL, (u8 *)(&pdvobj->inter_bcn_space));1862#endif /*CONFIG_SWTIMER_BASED_TXBCN*/18631864#endif /*CONFIG_SUPPORT_MULTI_BCN*/18651866#ifdef CONFIG_HW_P0_TSF_SYNC1867correct_TSF(padapter, mlme_act);1868#endif1869}18701871rtw_scan_wait_completed(padapter);18721873_rtw_iface_undersurvey_chk(__func__, padapter);1874/* send beacon */1875ResumeTxBeacon(padapter);1876{1877#if !defined(CONFIG_INTERRUPT_BASED_TXBCN)1878#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI) || defined(CONFIG_PCI_BCN_POLLING)1879#ifdef CONFIG_SWTIMER_BASED_TXBCN1880if (pdvobj->nr_ap_if == 11881&& mlme_act != MLME_OPCH_SWITCH1882) {1883RTW_INFO("start SW BCN TIMER!\n");1884_set_timer(&pdvobj->txbcn_timer, bcn_interval);1885}1886#else1887for (i = 0; i < pdvobj->iface_nums; i++) {1888if (!(parm->ifbmp & BIT(i)) || !pdvobj->padapters[i])1889continue;18901891if (send_beacon(pdvobj->padapters[i]) == _FAIL)1892RTW_INFO(ADPT_FMT" issue_beacon, fail!\n", ADPT_ARG(pdvobj->padapters[i]));1893}1894#endif1895#endif1896#endif /* !defined(CONFIG_INTERRUPT_BASED_TXBCN) */18971898#ifdef CONFIG_FW_HANDLE_TXBCN1899if (mlme_act != MLME_OPCH_SWITCH)1900rtw_ap_mbid_bcn_en(padapter, padapter->vap_id);1901#endif1902}1903}19041905int rtw_check_beacon_data(_adapter *padapter, u8 *pbuf, int len)1906{1907int ret = _SUCCESS;1908u8 *p;1909u8 *pHT_caps_ie = NULL;1910u8 *pHT_info_ie = NULL;1911u16 cap, ht_cap = _FALSE;1912uint ie_len = 0;1913int group_cipher, pairwise_cipher;1914u32 akm;1915u8 mfp_opt = MFP_NO;1916u8 channel, network_type;1917u8 OUI1[] = {0x00, 0x50, 0xf2, 0x01};1918u8 WMM_PARA_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01};1919HT_CAP_AMPDU_DENSITY best_ampdu_density;1920struct registry_priv *pregistrypriv = &padapter->registrypriv;1921struct security_priv *psecuritypriv = &padapter->securitypriv;1922struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);1923WLAN_BSSID_EX *pbss_network = (WLAN_BSSID_EX *)&pmlmepriv->cur_network.network;1924u8 *ie = pbss_network->IEs;1925u8 vht_cap = _FALSE;1926struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);1927struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);1928struct rf_ctl_t *rfctl = adapter_to_rfctl(padapter);1929u8 rf_num = 0;1930int ret_rm;1931/* SSID */1932/* Supported rates */1933/* DS Params */1934/* WLAN_EID_COUNTRY */1935/* ERP Information element */1936/* Extended supported rates */1937/* WPA/WPA2 */1938/* Wi-Fi Wireless Multimedia Extensions */1939/* ht_capab, ht_oper */1940/* WPS IE */19411942RTW_INFO("%s, len=%d\n", __FUNCTION__, len);19431944if (!MLME_IS_AP(padapter) && !MLME_IS_MESH(padapter))1945return _FAIL;194619471948if (len > MAX_IE_SZ)1949return _FAIL;19501951pbss_network->IELength = len;19521953_rtw_memset(ie, 0, MAX_IE_SZ);19541955_rtw_memcpy(ie, pbuf, pbss_network->IELength);195619571958if (pbss_network->InfrastructureMode != Ndis802_11APMode1959&& pbss_network->InfrastructureMode != Ndis802_11_mesh1960) {1961rtw_warn_on(1);1962return _FAIL;1963}196419651966rtw_ap_check_scan(padapter);196719681969pbss_network->Rssi = 0;19701971_rtw_memcpy(pbss_network->MacAddress, adapter_mac_addr(padapter), ETH_ALEN);19721973/* beacon interval */1974p = rtw_get_beacon_interval_from_ie(ie);/* ie + 8; */ /* 8: TimeStamp, 2: Beacon Interval 2:Capability */1975/* pbss_network->Configuration.BeaconPeriod = le16_to_cpu(*(unsigned short*)p); */1976pbss_network->Configuration.BeaconPeriod = RTW_GET_LE16(p);19771978/* capability */1979/* cap = *(unsigned short *)rtw_get_capability_from_ie(ie); */1980/* cap = le16_to_cpu(cap); */1981cap = RTW_GET_LE16(ie);19821983/* SSID */1984p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _SSID_IE_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_));1985if (p && ie_len > 0) {1986_rtw_memset(&pbss_network->Ssid, 0, sizeof(NDIS_802_11_SSID));1987_rtw_memcpy(pbss_network->Ssid.Ssid, (p + 2), ie_len);1988pbss_network->Ssid.SsidLength = ie_len;1989#ifdef CONFIG_P2P1990_rtw_memcpy(padapter->wdinfo.p2p_group_ssid, pbss_network->Ssid.Ssid, pbss_network->Ssid.SsidLength);1991padapter->wdinfo.p2p_group_ssid_len = pbss_network->Ssid.SsidLength;1992#endif1993}19941995#ifdef CONFIG_RTW_MESH1996/* Mesh ID */1997if (MLME_IS_MESH(padapter)) {1998p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, WLAN_EID_MESH_ID, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_));1999if (p && ie_len > 0) {2000_rtw_memset(&pbss_network->mesh_id, 0, sizeof(NDIS_802_11_SSID));2001_rtw_memcpy(pbss_network->mesh_id.Ssid, (p + 2), ie_len);2002pbss_network->mesh_id.SsidLength = ie_len;2003}2004}2005#endif20062007/* chnnel */2008channel = 0;2009pbss_network->Configuration.Length = 0;2010p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _DSSET_IE_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_));2011if (p && ie_len > 0)2012channel = *(p + 2);20132014pbss_network->Configuration.DSConfig = channel;20152016/* support rate ie & ext support ie & IElen & SupportedRates */2017network_type = rtw_update_rate_bymode(pbss_network, pregistrypriv->wireless_mode);20182019/* parsing ERP_IE */2020p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _ERPINFO_IE_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_));2021if (p && ie_len > 0) {2022if(padapter->registrypriv.wireless_mode == WIRELESS_11B ) {20232024pbss_network->IELength = pbss_network->IELength - *(p+1) - 2;2025ret_rm = rtw_ies_remove_ie(ie , &len, _BEACON_IE_OFFSET_, _ERPINFO_IE_,NULL,0);2026RTW_DBG("%s, remove_ie of ERP_IE=%d\n", __FUNCTION__, ret_rm);2027} else2028ERP_IE_handler(padapter, (PNDIS_802_11_VARIABLE_IEs)p);20292030}20312032/* update privacy/security */2033if (cap & BIT(4))2034pbss_network->Privacy = 1;2035else2036pbss_network->Privacy = 0;20372038psecuritypriv->wpa_psk = 0;20392040/* wpa2 */2041akm = 0;2042group_cipher = 0;2043pairwise_cipher = 0;2044psecuritypriv->wpa2_group_cipher = _NO_PRIVACY_;2045psecuritypriv->wpa2_pairwise_cipher = _NO_PRIVACY_;2046p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _RSN_IE_2_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_));2047if (p && ie_len > 0) {2048if (rtw_parse_wpa2_ie(p, ie_len + 2, &group_cipher, &pairwise_cipher, &akm, &mfp_opt) == _SUCCESS) {2049psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;2050psecuritypriv->ndisauthtype = Ndis802_11AuthModeWPA2PSK;2051psecuritypriv->dot8021xalg = 1;/* psk, todo:802.1x */2052psecuritypriv->wpa_psk |= BIT(1);20532054psecuritypriv->wpa2_group_cipher = group_cipher;2055psecuritypriv->wpa2_pairwise_cipher = pairwise_cipher;20562057/*2058Kernel < v5.1, the auth_type set as NL80211_AUTHTYPE_AUTOMATIC2059in cfg80211_rtw_start_ap().2060if the AKM SAE in the RSN IE, we have to update the auth_type for SAE2061in rtw_check_beacon_data().2062*/2063if (CHECK_BIT(WLAN_AKM_TYPE_SAE, akm))2064psecuritypriv->auth_type = NL80211_AUTHTYPE_SAE;2065#if 02066switch (group_cipher) {2067case WPA_CIPHER_NONE:2068psecuritypriv->wpa2_group_cipher = _NO_PRIVACY_;2069break;2070case WPA_CIPHER_WEP40:2071psecuritypriv->wpa2_group_cipher = _WEP40_;2072break;2073case WPA_CIPHER_TKIP:2074psecuritypriv->wpa2_group_cipher = _TKIP_;2075break;2076case WPA_CIPHER_CCMP:2077psecuritypriv->wpa2_group_cipher = _AES_;2078break;2079case WPA_CIPHER_WEP104:2080psecuritypriv->wpa2_group_cipher = _WEP104_;2081break;2082}20832084switch (pairwise_cipher) {2085case WPA_CIPHER_NONE:2086psecuritypriv->wpa2_pairwise_cipher = _NO_PRIVACY_;2087break;2088case WPA_CIPHER_WEP40:2089psecuritypriv->wpa2_pairwise_cipher = _WEP40_;2090break;2091case WPA_CIPHER_TKIP:2092psecuritypriv->wpa2_pairwise_cipher = _TKIP_;2093break;2094case WPA_CIPHER_CCMP:2095psecuritypriv->wpa2_pairwise_cipher = _AES_;2096break;2097case WPA_CIPHER_WEP104:2098psecuritypriv->wpa2_pairwise_cipher = _WEP104_;2099break;2100}2101#endif2102}21032104}21052106/* wpa */2107ie_len = 0;2108group_cipher = 0;2109pairwise_cipher = 0;2110psecuritypriv->wpa_group_cipher = _NO_PRIVACY_;2111psecuritypriv->wpa_pairwise_cipher = _NO_PRIVACY_;2112for (p = ie + _BEACON_IE_OFFSET_; ; p += (ie_len + 2)) {2113p = rtw_get_ie(p, _SSN_IE_1_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_ - (ie_len + 2)));2114if ((p) && (_rtw_memcmp(p + 2, OUI1, 4))) {2115if (rtw_parse_wpa_ie(p, ie_len + 2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) {2116psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;2117psecuritypriv->ndisauthtype = Ndis802_11AuthModeWPAPSK;2118psecuritypriv->dot8021xalg = 1;/* psk, todo:802.1x */21192120psecuritypriv->wpa_psk |= BIT(0);21212122psecuritypriv->wpa_group_cipher = group_cipher;2123psecuritypriv->wpa_pairwise_cipher = pairwise_cipher;21242125#if 02126switch (group_cipher) {2127case WPA_CIPHER_NONE:2128psecuritypriv->wpa_group_cipher = _NO_PRIVACY_;2129break;2130case WPA_CIPHER_WEP40:2131psecuritypriv->wpa_group_cipher = _WEP40_;2132break;2133case WPA_CIPHER_TKIP:2134psecuritypriv->wpa_group_cipher = _TKIP_;2135break;2136case WPA_CIPHER_CCMP:2137psecuritypriv->wpa_group_cipher = _AES_;2138break;2139case WPA_CIPHER_WEP104:2140psecuritypriv->wpa_group_cipher = _WEP104_;2141break;2142}21432144switch (pairwise_cipher) {2145case WPA_CIPHER_NONE:2146psecuritypriv->wpa_pairwise_cipher = _NO_PRIVACY_;2147break;2148case WPA_CIPHER_WEP40:2149psecuritypriv->wpa_pairwise_cipher = _WEP40_;2150break;2151case WPA_CIPHER_TKIP:2152psecuritypriv->wpa_pairwise_cipher = _TKIP_;2153break;2154case WPA_CIPHER_CCMP:2155psecuritypriv->wpa_pairwise_cipher = _AES_;2156break;2157case WPA_CIPHER_WEP104:2158psecuritypriv->wpa_pairwise_cipher = _WEP104_;2159break;2160}2161#endif2162}21632164break;21652166}21672168if ((p == NULL) || (ie_len == 0))2169break;21702171}21722173#ifdef CONFIG_RTW_MESH2174if (MLME_IS_MESH(padapter)) {2175/* MFP is mandatory for secure mesh */2176if (padapter->mesh_info.mesh_auth_id)2177mfp_opt = MFP_REQUIRED;2178} else2179#endif2180if (mfp_opt == MFP_INVALID) {2181RTW_INFO(FUNC_ADPT_FMT" invalid MFP setting\n", FUNC_ADPT_ARG(padapter));2182return _FAIL;2183}2184psecuritypriv->mfp_opt = mfp_opt;21852186/* wmm */2187ie_len = 0;2188pmlmepriv->qospriv.qos_option = 0;2189#ifdef CONFIG_RTW_MESH2190if (MLME_IS_MESH(padapter))2191pmlmepriv->qospriv.qos_option = 1;2192#endif2193if (pregistrypriv->wmm_enable) {2194for (p = ie + _BEACON_IE_OFFSET_; ; p += (ie_len + 2)) {2195p = rtw_get_ie(p, _VENDOR_SPECIFIC_IE_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_ - (ie_len + 2)));2196if ((p) && _rtw_memcmp(p + 2, WMM_PARA_IE, 6)) {2197pmlmepriv->qospriv.qos_option = 1;21982199*(p + 8) |= BIT(7); /* QoS Info, support U-APSD */22002201/* disable all ACM bits since the WMM admission control is not supported */2202*(p + 10) &= ~BIT(4); /* BE */2203*(p + 14) &= ~BIT(4); /* BK */2204*(p + 18) &= ~BIT(4); /* VI */2205*(p + 22) &= ~BIT(4); /* VO */22062207WMM_param_handler(padapter, (PNDIS_802_11_VARIABLE_IEs)p);22082209break;2210}22112212if ((p == NULL) || (ie_len == 0))2213break;2214}2215}2216#ifdef CONFIG_80211N_HT2217if(padapter->registrypriv.ht_enable &&2218is_supported_ht(padapter->registrypriv.wireless_mode)) {2219/* parsing HT_CAP_IE */2220p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_CAPABILITY_IE_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_));2221if (p && ie_len > 0) {2222HT_CAP_AMPDU_FACTOR max_rx_ampdu_factor = MAX_AMPDU_FACTOR_64K;2223struct rtw_ieee80211_ht_cap *pht_cap = (struct rtw_ieee80211_ht_cap *)(p + 2);22242225if (0) {2226RTW_INFO(FUNC_ADPT_FMT" HT_CAP_IE from upper layer:\n", FUNC_ADPT_ARG(padapter));2227dump_ht_cap_ie_content(RTW_DBGDUMP, p + 2, ie_len);2228}22292230pHT_caps_ie = p;22312232ht_cap = _TRUE;2233network_type |= WIRELESS_11_24N;22342235rtw_ht_use_default_setting(padapter);22362237/* Update HT Capabilities Info field */2238if (pmlmepriv->htpriv.sgi_20m == _FALSE)2239pht_cap->cap_info &= ~(IEEE80211_HT_CAP_SGI_20);22402241if (pmlmepriv->htpriv.sgi_40m == _FALSE)2242pht_cap->cap_info &= ~(IEEE80211_HT_CAP_SGI_40);22432244if (!TEST_FLAG(pmlmepriv->htpriv.ldpc_cap, LDPC_HT_ENABLE_RX))2245pht_cap->cap_info &= ~(IEEE80211_HT_CAP_LDPC_CODING);22462247if (!TEST_FLAG(pmlmepriv->htpriv.stbc_cap, STBC_HT_ENABLE_TX))2248pht_cap->cap_info &= ~(IEEE80211_HT_CAP_TX_STBC);22492250if (!TEST_FLAG(pmlmepriv->htpriv.stbc_cap, STBC_HT_ENABLE_RX))2251pht_cap->cap_info &= ~(IEEE80211_HT_CAP_RX_STBC_3R);22522253/* Update A-MPDU Parameters field */2254pht_cap->ampdu_params_info &= ~(IEEE80211_HT_CAP_AMPDU_FACTOR | IEEE80211_HT_CAP_AMPDU_DENSITY);22552256if ((psecuritypriv->wpa_pairwise_cipher & WPA_CIPHER_CCMP) ||2257(psecuritypriv->wpa2_pairwise_cipher & WPA_CIPHER_CCMP)) {2258rtw_hal_get_def_var(padapter, HW_VAR_BEST_AMPDU_DENSITY, &best_ampdu_density);2259pht_cap->ampdu_params_info |= (IEEE80211_HT_CAP_AMPDU_DENSITY & (best_ampdu_density << 2));2260} else2261pht_cap->ampdu_params_info |= (IEEE80211_HT_CAP_AMPDU_DENSITY & 0x00);22622263rtw_hal_get_def_var(padapter, HW_VAR_MAX_RX_AMPDU_FACTOR, &max_rx_ampdu_factor);2264pht_cap->ampdu_params_info |= (IEEE80211_HT_CAP_AMPDU_FACTOR & max_rx_ampdu_factor); /* set Max Rx AMPDU size to 64K */22652266_rtw_memcpy(&(pmlmeinfo->HT_caps), pht_cap, sizeof(struct HT_caps_element));22672268/* Update Supported MCS Set field */2269{2270u8 rx_nss = 0;2271int i;22722273rx_nss = GET_HAL_RX_NSS(padapter);22742275/* RX MCS Bitmask */2276switch (rx_nss) {2277case 1:2278set_mcs_rate_by_mask(HT_CAP_ELE_RX_MCS_MAP(pht_cap), MCS_RATE_1R);2279break;2280case 2:2281set_mcs_rate_by_mask(HT_CAP_ELE_RX_MCS_MAP(pht_cap), MCS_RATE_2R);2282break;2283case 3:2284set_mcs_rate_by_mask(HT_CAP_ELE_RX_MCS_MAP(pht_cap), MCS_RATE_3R);2285break;2286case 4:2287set_mcs_rate_by_mask(HT_CAP_ELE_RX_MCS_MAP(pht_cap), MCS_RATE_4R);2288break;2289default:2290RTW_WARN("rf_type:%d or rx_nss:%u is not expected\n", GET_HAL_RFPATH(padapter), rx_nss);2291}2292for (i = 0; i < 10; i++)2293*(HT_CAP_ELE_RX_MCS_MAP(pht_cap) + i) &= padapter->mlmeextpriv.default_supported_mcs_set[i];2294}22952296#ifdef CONFIG_BEAMFORMING2297/* Use registry value to enable HT Beamforming. */2298/* ToDo: use configure file to set these capability. */2299pht_cap->tx_BF_cap_info = 0;23002301/* HT Beamformer */2302if (TEST_FLAG(pmlmepriv->htpriv.beamform_cap, BEAMFORMING_HT_BEAMFORMER_ENABLE)) {2303/* Transmit NDP Capable */2304SET_HT_CAP_TXBF_TRANSMIT_NDP_CAP(pht_cap, 1);2305/* Explicit Compressed Steering Capable */2306SET_HT_CAP_TXBF_EXPLICIT_COMP_STEERING_CAP(pht_cap, 1);2307/* Compressed Steering Number Antennas */2308SET_HT_CAP_TXBF_COMP_STEERING_NUM_ANTENNAS(pht_cap, 1);2309rtw_hal_get_def_var(padapter, HAL_DEF_BEAMFORMER_CAP, (u8 *)&rf_num);2310SET_HT_CAP_TXBF_CHNL_ESTIMATION_NUM_ANTENNAS(pht_cap, rf_num);2311}23122313/* HT Beamformee */2314if (TEST_FLAG(pmlmepriv->htpriv.beamform_cap, BEAMFORMING_HT_BEAMFORMEE_ENABLE)) {2315/* Receive NDP Capable */2316SET_HT_CAP_TXBF_RECEIVE_NDP_CAP(pht_cap, 1);2317/* Explicit Compressed Beamforming Feedback Capable */2318SET_HT_CAP_TXBF_EXPLICIT_COMP_FEEDBACK_CAP(pht_cap, 2);2319rtw_hal_get_def_var(padapter, HAL_DEF_BEAMFORMEE_CAP, (u8 *)&rf_num);2320SET_HT_CAP_TXBF_COMP_STEERING_NUM_ANTENNAS(pht_cap, rf_num);2321}2322#endif /* CONFIG_BEAMFORMING */23232324_rtw_memcpy(&pmlmepriv->htpriv.ht_cap, p + 2, ie_len);23252326if (0) {2327RTW_INFO(FUNC_ADPT_FMT" HT_CAP_IE driver masked:\n", FUNC_ADPT_ARG(padapter));2328dump_ht_cap_ie_content(RTW_DBGDUMP, p + 2, ie_len);2329}2330}23312332/* parsing HT_INFO_IE */2333p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_ADD_INFO_IE_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_));2334if (p && ie_len > 0) {2335pHT_info_ie = p;2336if (channel == 0)2337pbss_network->Configuration.DSConfig = GET_HT_OP_ELE_PRI_CHL(pHT_info_ie + 2);2338else if (channel != GET_HT_OP_ELE_PRI_CHL(pHT_info_ie + 2)) {2339RTW_INFO(FUNC_ADPT_FMT" ch inconsistent, DSSS:%u, HT primary:%u\n"2340, FUNC_ADPT_ARG(padapter), channel, GET_HT_OP_ELE_PRI_CHL(pHT_info_ie + 2));2341}2342}2343}2344#endif /* CONFIG_80211N_HT */2345pmlmepriv->cur_network.network_type = network_type;23462347#ifdef CONFIG_80211N_HT2348pmlmepriv->htpriv.ht_option = _FALSE;23492350if ((psecuritypriv->wpa2_pairwise_cipher & WPA_CIPHER_TKIP) ||2351(psecuritypriv->wpa_pairwise_cipher & WPA_CIPHER_TKIP)) {2352/* todo: */2353/* ht_cap = _FALSE; */2354}23552356/* ht_cap */2357if (padapter->registrypriv.ht_enable &&2358is_supported_ht(padapter->registrypriv.wireless_mode) && ht_cap == _TRUE) {23592360pmlmepriv->htpriv.ht_option = _TRUE;2361pmlmepriv->qospriv.qos_option = 1;23622363pmlmepriv->htpriv.ampdu_enable = pregistrypriv->ampdu_enable ? _TRUE : _FALSE;23642365HT_caps_handler(padapter, (PNDIS_802_11_VARIABLE_IEs)pHT_caps_ie);23662367HT_info_handler(padapter, (PNDIS_802_11_VARIABLE_IEs)pHT_info_ie);2368}2369#endif23702371#ifdef CONFIG_80211AC_VHT2372pmlmepriv->ori_vht_en = 0;2373pmlmepriv->vhtpriv.vht_option = _FALSE;23742375if (pmlmepriv->htpriv.ht_option == _TRUE2376&& pbss_network->Configuration.DSConfig > 142377&& REGSTY_IS_11AC_ENABLE(pregistrypriv)2378&& is_supported_vht(pregistrypriv->wireless_mode)2379&& (!rfctl->country_ent || COUNTRY_CHPLAN_EN_11AC(rfctl->country_ent))2380) {2381/* Parsing VHT CAP IE */2382p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, EID_VHTCapability, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_));2383if (p && ie_len > 0)2384vht_cap = _TRUE;23852386/* Parsing VHT OPERATION IE */23872388if (vht_cap == _TRUE2389&& MLME_IS_MESH(padapter) /* allow only mesh temporarily before VHT IE checking is ready */2390) {2391rtw_check_for_vht20(padapter, ie + _BEACON_IE_OFFSET_, pbss_network->IELength - _BEACON_IE_OFFSET_);2392pmlmepriv->ori_vht_en = 1;2393pmlmepriv->vhtpriv.vht_option = _TRUE;2394} else if (REGSTY_IS_11AC_AUTO(pregistrypriv)) {2395rtw_vht_ies_detach(padapter, pbss_network);2396rtw_vht_ies_attach(padapter, pbss_network);2397}2398}23992400if (pmlmepriv->vhtpriv.vht_option == _FALSE)2401rtw_vht_ies_detach(padapter, pbss_network);2402#endif /* CONFIG_80211AC_VHT */24032404#ifdef CONFIG_80211N_HT2405if(padapter->registrypriv.ht_enable &&2406is_supported_ht(padapter->registrypriv.wireless_mode) &&2407pbss_network->Configuration.DSConfig <= 14 && padapter->registrypriv.wifi_spec == 1 &&2408pbss_network->IELength + 10 <= MAX_IE_SZ) {2409uint len = 0;24102411SET_EXT_CAPABILITY_ELE_BSS_COEXIST(pmlmepriv->ext_capab_ie_data, 1);2412pmlmepriv->ext_capab_ie_len = 10;2413rtw_set_ie(pbss_network->IEs + pbss_network->IELength, EID_EXTCapability, 8, pmlmepriv->ext_capab_ie_data, &len);2414pbss_network->IELength += pmlmepriv->ext_capab_ie_len;2415}2416#endif /* CONFIG_80211N_HT */24172418pbss_network->Length = get_WLAN_BSSID_EX_sz((WLAN_BSSID_EX *)pbss_network);24192420rtw_ies_get_chbw(pbss_network->IEs + _BEACON_IE_OFFSET_, pbss_network->IELength - _BEACON_IE_OFFSET_2421, &pmlmepriv->ori_ch, &pmlmepriv->ori_bw, &pmlmepriv->ori_offset, 1, 1);2422rtw_warn_on(pmlmepriv->ori_ch == 0);24232424{2425/* alloc sta_info for ap itself */24262427struct sta_info *sta;24282429sta = rtw_get_stainfo(&padapter->stapriv, pbss_network->MacAddress);2430if (!sta) {2431sta = rtw_alloc_stainfo(&padapter->stapriv, pbss_network->MacAddress);2432if (sta == NULL)2433return _FAIL;2434}2435}24362437rtw_startbss_cmd(padapter, RTW_CMDF_WAIT_ACK);2438{2439int sk_band = RTW_GET_SCAN_BAND_SKIP(padapter);24402441if (sk_band)2442RTW_CLR_SCAN_BAND_SKIP(padapter, sk_band);2443}24442445rtw_indicate_connect(padapter);24462447pmlmepriv->cur_network.join_res = _TRUE;/* for check if already set beacon */24482449/* update bc/mc sta_info */2450/* update_bmc_sta(padapter); */24512452return ret;24532454}24552456#if CONFIG_RTW_MACADDR_ACL2457void rtw_macaddr_acl_init(_adapter *adapter, u8 period)2458{2459struct sta_priv *stapriv = &adapter->stapriv;2460struct wlan_acl_pool *acl;2461_queue *acl_node_q;2462int i;2463_irqL irqL;24642465if (period >= RTW_ACL_PERIOD_NUM) {2466rtw_warn_on(1);2467return;2468}24692470acl = &stapriv->acl_list[period];2471acl_node_q = &acl->acl_node_q;24722473_rtw_spinlock_init(&(acl_node_q->lock));24742475_enter_critical_bh(&(acl_node_q->lock), &irqL);2476_rtw_init_listhead(&(acl_node_q->queue));2477acl->num = 0;2478acl->mode = RTW_ACL_MODE_DISABLED;2479for (i = 0; i < NUM_ACL; i++) {2480_rtw_init_listhead(&acl->aclnode[i].list);2481acl->aclnode[i].valid = _FALSE;2482}2483_exit_critical_bh(&(acl_node_q->lock), &irqL);2484}24852486static void _rtw_macaddr_acl_deinit(_adapter *adapter, u8 period, bool clear_only)2487{2488struct sta_priv *stapriv = &adapter->stapriv;2489struct wlan_acl_pool *acl;2490_queue *acl_node_q;2491_irqL irqL;2492_list *head, *list;2493struct rtw_wlan_acl_node *acl_node;24942495if (period >= RTW_ACL_PERIOD_NUM) {2496rtw_warn_on(1);2497return;2498}24992500acl = &stapriv->acl_list[period];2501acl_node_q = &acl->acl_node_q;25022503_enter_critical_bh(&(acl_node_q->lock), &irqL);2504head = get_list_head(acl_node_q);2505list = get_next(head);2506while (rtw_end_of_queue_search(head, list) == _FALSE) {2507acl_node = LIST_CONTAINOR(list, struct rtw_wlan_acl_node, list);2508list = get_next(list);25092510if (acl_node->valid == _TRUE) {2511acl_node->valid = _FALSE;2512rtw_list_delete(&acl_node->list);2513acl->num--;2514}2515}2516_exit_critical_bh(&(acl_node_q->lock), &irqL);25172518if (!clear_only)2519_rtw_spinlock_free(&(acl_node_q->lock));25202521rtw_warn_on(acl->num);2522acl->mode = RTW_ACL_MODE_DISABLED;2523}25242525void rtw_macaddr_acl_deinit(_adapter *adapter, u8 period)2526{2527_rtw_macaddr_acl_deinit(adapter, period, 0);2528}25292530void rtw_macaddr_acl_clear(_adapter *adapter, u8 period)2531{2532_rtw_macaddr_acl_deinit(adapter, period, 1);2533}25342535void rtw_set_macaddr_acl(_adapter *adapter, u8 period, int mode)2536{2537struct sta_priv *stapriv = &adapter->stapriv;2538struct wlan_acl_pool *acl;25392540if (period >= RTW_ACL_PERIOD_NUM) {2541rtw_warn_on(1);2542return;2543}25442545acl = &stapriv->acl_list[period];25462547RTW_INFO(FUNC_ADPT_FMT" p=%u, mode=%d\n"2548, FUNC_ADPT_ARG(adapter), period, mode);25492550acl->mode = mode;2551}25522553int rtw_acl_add_sta(_adapter *adapter, u8 period, const u8 *addr)2554{2555_irqL irqL;2556_list *list, *head;2557u8 existed = 0;2558int i = -1, ret = 0;2559struct rtw_wlan_acl_node *acl_node;2560struct sta_priv *stapriv = &adapter->stapriv;2561struct wlan_acl_pool *acl;2562_queue *acl_node_q;25632564if (period >= RTW_ACL_PERIOD_NUM) {2565rtw_warn_on(1);2566ret = -1;2567goto exit;2568}25692570acl = &stapriv->acl_list[period];2571acl_node_q = &acl->acl_node_q;25722573_enter_critical_bh(&(acl_node_q->lock), &irqL);25742575head = get_list_head(acl_node_q);2576list = get_next(head);25772578/* search for existed entry */2579while (rtw_end_of_queue_search(head, list) == _FALSE) {2580acl_node = LIST_CONTAINOR(list, struct rtw_wlan_acl_node, list);2581list = get_next(list);25822583if (_rtw_memcmp(acl_node->addr, addr, ETH_ALEN)) {2584if (acl_node->valid == _TRUE) {2585existed = 1;2586break;2587}2588}2589}2590if (existed)2591goto release_lock;25922593if (acl->num >= NUM_ACL)2594goto release_lock;25952596/* find empty one and use */2597for (i = 0; i < NUM_ACL; i++) {25982599acl_node = &acl->aclnode[i];2600if (acl_node->valid == _FALSE) {26012602_rtw_init_listhead(&acl_node->list);2603_rtw_memcpy(acl_node->addr, addr, ETH_ALEN);2604acl_node->valid = _TRUE;26052606rtw_list_insert_tail(&acl_node->list, get_list_head(acl_node_q));2607acl->num++;2608break;2609}2610}26112612release_lock:2613_exit_critical_bh(&(acl_node_q->lock), &irqL);26142615if (!existed && (i < 0 || i >= NUM_ACL))2616ret = -1;26172618RTW_INFO(FUNC_ADPT_FMT" p=%u "MAC_FMT" %s (acl_num=%d)\n"2619, FUNC_ADPT_ARG(adapter), period, MAC_ARG(addr)2620, (existed ? "existed" : ((i < 0 || i >= NUM_ACL) ? "no room" : "added"))2621, acl->num);2622exit:2623return ret;2624}26252626int rtw_acl_remove_sta(_adapter *adapter, u8 period, const u8 *addr)2627{2628_irqL irqL;2629_list *list, *head;2630int ret = 0;2631struct rtw_wlan_acl_node *acl_node;2632struct sta_priv *stapriv = &adapter->stapriv;2633struct wlan_acl_pool *acl;2634_queue *acl_node_q;2635u8 is_baddr = is_broadcast_mac_addr(addr);2636u8 match = 0;26372638if (period >= RTW_ACL_PERIOD_NUM) {2639rtw_warn_on(1);2640goto exit;2641}26422643acl = &stapriv->acl_list[period];2644acl_node_q = &acl->acl_node_q;26452646_enter_critical_bh(&(acl_node_q->lock), &irqL);26472648head = get_list_head(acl_node_q);2649list = get_next(head);26502651while (rtw_end_of_queue_search(head, list) == _FALSE) {2652acl_node = LIST_CONTAINOR(list, struct rtw_wlan_acl_node, list);2653list = get_next(list);26542655if (is_baddr || _rtw_memcmp(acl_node->addr, addr, ETH_ALEN)) {2656if (acl_node->valid == _TRUE) {2657acl_node->valid = _FALSE;2658rtw_list_delete(&acl_node->list);2659acl->num--;2660match = 1;2661}2662}2663}26642665_exit_critical_bh(&(acl_node_q->lock), &irqL);26662667RTW_INFO(FUNC_ADPT_FMT" p=%u "MAC_FMT" %s (acl_num=%d)\n"2668, FUNC_ADPT_ARG(adapter), period, MAC_ARG(addr)2669, is_baddr ? "clear all" : (match ? "match" : "no found")2670, acl->num);26712672exit:2673return ret;2674}2675#endif /* CONFIG_RTW_MACADDR_ACL */26762677u8 rtw_ap_set_sta_key(_adapter *adapter, const u8 *addr, u8 alg, const u8 *key, u8 keyid, u8 gk)2678{2679struct cmd_priv *cmdpriv = &adapter->cmdpriv;2680struct cmd_obj *cmd;2681struct set_stakey_parm *param;2682u8 res = _SUCCESS;26832684cmd = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));2685if (cmd == NULL) {2686res = _FAIL;2687goto exit;2688}26892690param = (struct set_stakey_parm *)rtw_zmalloc(sizeof(struct set_stakey_parm));2691if (param == NULL) {2692rtw_mfree((u8 *) cmd, sizeof(struct cmd_obj));2693res = _FAIL;2694goto exit;2695}26962697init_h2fwcmd_w_parm_no_rsp(cmd, param, _SetStaKey_CMD_);26982699_rtw_memcpy(param->addr, addr, ETH_ALEN);2700param->algorithm = alg;2701param->keyid = keyid;2702_rtw_memcpy(param->key, key, 16);2703param->gk = gk;27042705res = rtw_enqueue_cmd(cmdpriv, cmd);27062707exit:2708return res;2709}27102711u8 rtw_ap_set_pairwise_key(_adapter *padapter, struct sta_info *psta)2712{2713return rtw_ap_set_sta_key(padapter2714, psta->cmn.mac_addr2715, psta->dot118021XPrivacy2716, psta->dot118021x_UncstKey.skey2717, 02718, 02719);2720}27212722static int rtw_ap_set_key(_adapter *padapter, u8 *key, u8 alg, int keyid, u8 set_tx)2723{2724u8 keylen;2725struct cmd_obj *pcmd;2726struct setkey_parm *psetkeyparm;2727struct cmd_priv *pcmdpriv = &(padapter->cmdpriv);2728int res = _SUCCESS;27292730/* RTW_INFO("%s\n", __FUNCTION__); */27312732pcmd = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));2733if (pcmd == NULL) {2734res = _FAIL;2735goto exit;2736}2737psetkeyparm = (struct setkey_parm *)rtw_zmalloc(sizeof(struct setkey_parm));2738if (psetkeyparm == NULL) {2739rtw_mfree((unsigned char *)pcmd, sizeof(struct cmd_obj));2740res = _FAIL;2741goto exit;2742}27432744_rtw_memset(psetkeyparm, 0, sizeof(struct setkey_parm));27452746psetkeyparm->keyid = (u8)keyid;2747if (is_wep_enc(alg))2748padapter->securitypriv.key_mask |= BIT(psetkeyparm->keyid);27492750psetkeyparm->algorithm = alg;27512752psetkeyparm->set_tx = set_tx;27532754switch (alg) {2755case _WEP40_:2756keylen = 5;2757break;2758case _WEP104_:2759keylen = 13;2760break;2761case _TKIP_:2762case _TKIP_WTMIC_:2763case _AES_:2764default:2765keylen = 16;2766}27672768_rtw_memcpy(&(psetkeyparm->key[0]), key, keylen);27692770pcmd->cmdcode = _SetKey_CMD_;2771pcmd->parmbuf = (u8 *)psetkeyparm;2772pcmd->cmdsz = (sizeof(struct setkey_parm));2773pcmd->rsp = NULL;2774pcmd->rspsz = 0;277527762777_rtw_init_listhead(&pcmd->list);27782779res = rtw_enqueue_cmd(pcmdpriv, pcmd);27802781exit:27822783return res;2784}27852786int rtw_ap_set_group_key(_adapter *padapter, u8 *key, u8 alg, int keyid)2787{2788RTW_INFO("%s\n", __FUNCTION__);27892790return rtw_ap_set_key(padapter, key, alg, keyid, 1);2791}27922793int rtw_ap_set_wep_key(_adapter *padapter, u8 *key, u8 keylen, int keyid, u8 set_tx)2794{2795u8 alg;27962797switch (keylen) {2798case 5:2799alg = _WEP40_;2800break;2801case 13:2802alg = _WEP104_;2803break;2804default:2805alg = _NO_PRIVACY_;2806}28072808RTW_INFO("%s\n", __FUNCTION__);28092810return rtw_ap_set_key(padapter, key, alg, keyid, set_tx);2811}28122813u8 rtw_ap_bmc_frames_hdl(_adapter *padapter)2814{2815#define HIQ_XMIT_COUNTS (6)2816_irqL irqL;2817struct sta_info *psta_bmc;2818_list *xmitframe_plist, *xmitframe_phead;2819struct xmit_frame *pxmitframe = NULL;2820struct xmit_priv *pxmitpriv = &padapter->xmitpriv;2821struct sta_priv *pstapriv = &padapter->stapriv;2822bool update_tim = _FALSE;282328242825if (padapter->registrypriv.wifi_spec != 1)2826return H2C_SUCCESS;282728282829psta_bmc = rtw_get_bcmc_stainfo(padapter);2830if (!psta_bmc)2831return H2C_SUCCESS;283228332834_enter_critical_bh(&pxmitpriv->lock, &irqL);28352836if ((rtw_tim_map_is_set(padapter, pstapriv->tim_bitmap, 0)) && (psta_bmc->sleepq_len > 0)) {2837int tx_counts = 0;28382839_update_beacon(padapter, _TIM_IE_, NULL, _FALSE, 0, "update TIM with TIB=1");28402841RTW_INFO("sleepq_len of bmc_sta = %d\n", psta_bmc->sleepq_len);28422843xmitframe_phead = get_list_head(&psta_bmc->sleep_q);2844xmitframe_plist = get_next(xmitframe_phead);28452846while ((rtw_end_of_queue_search(xmitframe_phead, xmitframe_plist)) == _FALSE) {2847pxmitframe = LIST_CONTAINOR(xmitframe_plist, struct xmit_frame, list);28482849xmitframe_plist = get_next(xmitframe_plist);28502851rtw_list_delete(&pxmitframe->list);28522853psta_bmc->sleepq_len--;2854tx_counts++;28552856if (psta_bmc->sleepq_len > 0)2857pxmitframe->attrib.mdata = 1;2858else2859pxmitframe->attrib.mdata = 0;28602861if (tx_counts == HIQ_XMIT_COUNTS)2862pxmitframe->attrib.mdata = 0;28632864pxmitframe->attrib.triggered = 1;28652866if (xmitframe_hiq_filter(pxmitframe) == _TRUE)2867pxmitframe->attrib.qsel = QSLT_HIGH;/*HIQ*/28682869rtw_hal_xmitframe_enqueue(padapter, pxmitframe);28702871if (tx_counts == HIQ_XMIT_COUNTS)2872break;28732874}28752876} else {2877if (psta_bmc->sleepq_len == 0) {28782879/*RTW_INFO("sleepq_len of bmc_sta = %d\n", psta_bmc->sleepq_len);*/28802881if (rtw_tim_map_is_set(padapter, pstapriv->tim_bitmap, 0))2882update_tim = _TRUE;28832884rtw_tim_map_clear(padapter, pstapriv->tim_bitmap, 0);2885rtw_tim_map_clear(padapter, pstapriv->sta_dz_bitmap, 0);28862887if (update_tim == _TRUE) {2888RTW_INFO("clear TIB\n");2889_update_beacon(padapter, _TIM_IE_, NULL, _TRUE, 0, "bmc sleepq and HIQ empty");2890}2891}2892}28932894_exit_critical_bh(&pxmitpriv->lock, &irqL);28952896#if 02897/* HIQ Check */2898rtw_hal_get_hwreg(padapter, HW_VAR_CHK_HI_QUEUE_EMPTY, &empty);28992900while (_FALSE == empty && rtw_get_passing_time_ms(start) < 3000) {2901rtw_msleep_os(100);2902rtw_hal_get_hwreg(padapter, HW_VAR_CHK_HI_QUEUE_EMPTY, &empty);2903}290429052906printk("check if hiq empty=%d\n", empty);2907#endif29082909return H2C_SUCCESS;2910}29112912#ifdef CONFIG_NATIVEAP_MLME29132914static void associated_stainfo_update(_adapter *padapter, struct sta_info *psta, u32 sta_info_type)2915{2916struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);29172918RTW_INFO("%s: "MAC_FMT", updated_type=0x%x\n", __func__, MAC_ARG(psta->cmn.mac_addr), sta_info_type);2919#ifdef CONFIG_80211N_HT2920if (sta_info_type & STA_INFO_UPDATE_BW) {29212922if ((psta->flags & WLAN_STA_HT) && !psta->ht_20mhz_set) {2923if (pmlmepriv->sw_to_20mhz) {2924psta->cmn.bw_mode = CHANNEL_WIDTH_20;2925/*psta->htpriv.ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;*/2926psta->htpriv.sgi_40m = _FALSE;2927} else {2928/*TODO: Switch back to 40MHZ?80MHZ*/2929}2930}2931}2932#endif /* CONFIG_80211N_HT */2933/*2934if (sta_info_type & STA_INFO_UPDATE_RATE) {29352936}2937*/29382939if (sta_info_type & STA_INFO_UPDATE_PROTECTION_MODE)2940VCS_update(padapter, psta);29412942/*2943if (sta_info_type & STA_INFO_UPDATE_CAP) {29442945}29462947if (sta_info_type & STA_INFO_UPDATE_HT_CAP) {29482949}29502951if (sta_info_type & STA_INFO_UPDATE_VHT_CAP) {29522953}2954*/29552956}29572958static void update_bcn_ext_capab_ie(_adapter *padapter)2959{2960sint ie_len = 0;2961unsigned char *pbuf;2962struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);2963struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);2964struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);2965WLAN_BSSID_EX *pnetwork = &(pmlmeinfo->network);2966u8 *ie = pnetwork->IEs;2967u8 null_extcap_data[8] = {0};29682969pbuf = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _EXT_CAP_IE_, &ie_len, (pnetwork->IELength - _BEACON_IE_OFFSET_));2970if (pbuf && ie_len > 0)2971rtw_remove_bcn_ie(padapter, pnetwork, _EXT_CAP_IE_);29722973if ((pmlmepriv->ext_capab_ie_len > 0) &&2974(_rtw_memcmp(pmlmepriv->ext_capab_ie_data, null_extcap_data, sizeof(null_extcap_data)) == _FALSE))2975rtw_add_bcn_ie(padapter, pnetwork, _EXT_CAP_IE_, pmlmepriv->ext_capab_ie_data, pmlmepriv->ext_capab_ie_len);29762977}29782979static void update_bcn_erpinfo_ie(_adapter *padapter)2980{2981struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);2982struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);2983struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);2984WLAN_BSSID_EX *pnetwork = &(pmlmeinfo->network);2985unsigned char *p, *ie = pnetwork->IEs;2986u32 len = 0;29872988RTW_INFO("%s, ERP_enable=%d\n", __FUNCTION__, pmlmeinfo->ERP_enable);29892990if (!pmlmeinfo->ERP_enable)2991return;29922993/* parsing ERP_IE */2994p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _ERPINFO_IE_, &len, (pnetwork->IELength - _BEACON_IE_OFFSET_));2995if (p && len > 0) {2996PNDIS_802_11_VARIABLE_IEs pIE = (PNDIS_802_11_VARIABLE_IEs)p;29972998if (pmlmepriv->num_sta_non_erp == 1)2999pIE->data[0] |= RTW_ERP_INFO_NON_ERP_PRESENT | RTW_ERP_INFO_USE_PROTECTION;3000else3001pIE->data[0] &= ~(RTW_ERP_INFO_NON_ERP_PRESENT | RTW_ERP_INFO_USE_PROTECTION);30023003if (pmlmepriv->num_sta_no_short_preamble > 0)3004pIE->data[0] |= RTW_ERP_INFO_BARKER_PREAMBLE_MODE;3005else3006pIE->data[0] &= ~(RTW_ERP_INFO_BARKER_PREAMBLE_MODE);30073008ERP_IE_handler(padapter, pIE);3009}30103011}30123013static void update_bcn_htcap_ie(_adapter *padapter)3014{3015RTW_INFO("%s\n", __FUNCTION__);30163017}30183019static void update_bcn_htinfo_ie(_adapter *padapter)3020{3021#ifdef CONFIG_80211N_HT3022/*3023u8 beacon_updated = _FALSE;3024u32 sta_info_update_type = STA_INFO_UPDATE_NONE;3025*/3026struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);3027struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);3028struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);3029WLAN_BSSID_EX *pnetwork = &(pmlmeinfo->network);3030unsigned char *p, *ie = pnetwork->IEs;3031u32 len = 0;30323033if (pmlmepriv->htpriv.ht_option == _FALSE)3034return;30353036if (pmlmeinfo->HT_info_enable != 1)3037return;303830393040RTW_INFO("%s current operation mode=0x%X\n",3041__FUNCTION__, pmlmepriv->ht_op_mode);30423043RTW_INFO("num_sta_40mhz_intolerant(%d), 20mhz_width_req(%d), intolerant_ch_rpt(%d), olbc(%d)\n",3044pmlmepriv->num_sta_40mhz_intolerant, pmlmepriv->ht_20mhz_width_req, pmlmepriv->ht_intolerant_ch_reported, ATOMIC_READ(&pmlmepriv->olbc));30453046/*parsing HT_INFO_IE, currently only update ht_op_mode - pht_info->infos[1] & pht_info->infos[2] for wifi logo test*/3047p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_ADD_INFO_IE_, &len, (pnetwork->IELength - _BEACON_IE_OFFSET_));3048if (p && len > 0) {3049struct HT_info_element *pht_info = NULL;30503051pht_info = (struct HT_info_element *)(p + 2);30523053/* for STA Channel Width/Secondary Channel Offset*/3054if ((pmlmepriv->sw_to_20mhz == 0) && (pmlmeext->cur_channel <= 14)) {3055if ((pmlmepriv->num_sta_40mhz_intolerant > 0) || (pmlmepriv->ht_20mhz_width_req == _TRUE)3056|| (pmlmepriv->ht_intolerant_ch_reported == _TRUE) || (ATOMIC_READ(&pmlmepriv->olbc) == _TRUE)) {3057SET_HT_OP_ELE_2ND_CHL_OFFSET(pht_info, 0);3058SET_HT_OP_ELE_STA_CHL_WIDTH(pht_info, 0);30593060pmlmepriv->sw_to_20mhz = 1;3061/*3062sta_info_update_type |= STA_INFO_UPDATE_BW;3063beacon_updated = _TRUE;3064*/30653066RTW_INFO("%s:switching to 20Mhz\n", __FUNCTION__);30673068/*TODO : cur_bwmode/cur_ch_offset switches to 20Mhz*/3069}3070} else {30713072if ((pmlmepriv->num_sta_40mhz_intolerant == 0) && (pmlmepriv->ht_20mhz_width_req == _FALSE)3073&& (pmlmepriv->ht_intolerant_ch_reported == _FALSE) && (ATOMIC_READ(&pmlmepriv->olbc) == _FALSE)) {30743075if (pmlmeext->cur_bwmode >= CHANNEL_WIDTH_40) {30763077SET_HT_OP_ELE_STA_CHL_WIDTH(pht_info, 1);30783079SET_HT_OP_ELE_2ND_CHL_OFFSET(pht_info,3080(pmlmeext->cur_ch_offset == HAL_PRIME_CHNL_OFFSET_LOWER) ?3081HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE : HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW);30823083pmlmepriv->sw_to_20mhz = 0;3084/*3085sta_info_update_type |= STA_INFO_UPDATE_BW;3086beacon_updated = _TRUE;3087*/30883089RTW_INFO("%s:switching back to 40Mhz\n", __FUNCTION__);3090}3091}3092}30933094/* to update ht_op_mode*/3095*(u16 *)(pht_info->infos + 1) = cpu_to_le16(pmlmepriv->ht_op_mode);30963097}30983099/*associated_clients_update(padapter, beacon_updated, sta_info_update_type);*/3100#endif /* CONFIG_80211N_HT */3101}31023103static void update_bcn_rsn_ie(_adapter *padapter)3104{3105RTW_INFO("%s\n", __FUNCTION__);31063107}31083109static void update_bcn_wpa_ie(_adapter *padapter)3110{3111RTW_INFO("%s\n", __FUNCTION__);31123113}31143115static void update_bcn_wmm_ie(_adapter *padapter)3116{3117RTW_INFO("%s\n", __FUNCTION__);31183119}31203121static void update_bcn_wps_ie(_adapter *padapter)3122{3123u8 *pwps_ie = NULL, *pwps_ie_src, *premainder_ie, *pbackup_remainder_ie = NULL;3124uint wps_ielen = 0, wps_offset, remainder_ielen;3125struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);3126struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);3127struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);3128WLAN_BSSID_EX *pnetwork = &(pmlmeinfo->network);3129unsigned char *ie = pnetwork->IEs;3130u32 ielen = pnetwork->IELength;313131323133RTW_INFO("%s\n", __FUNCTION__);31343135pwps_ie = rtw_get_wps_ie(ie + _FIXED_IE_LENGTH_, ielen - _FIXED_IE_LENGTH_, NULL, &wps_ielen);31363137if (pwps_ie == NULL || wps_ielen == 0)3138return;31393140pwps_ie_src = pmlmepriv->wps_beacon_ie;3141if (pwps_ie_src == NULL)3142return;31433144wps_offset = (uint)(pwps_ie - ie);31453146premainder_ie = pwps_ie + wps_ielen;31473148remainder_ielen = ielen - wps_offset - wps_ielen;31493150if (remainder_ielen > 0) {3151pbackup_remainder_ie = rtw_malloc(remainder_ielen);3152if (pbackup_remainder_ie)3153_rtw_memcpy(pbackup_remainder_ie, premainder_ie, remainder_ielen);3154}31553156wps_ielen = (uint)pwps_ie_src[1];/* to get ie data len */3157if ((wps_offset + wps_ielen + 2 + remainder_ielen) <= MAX_IE_SZ) {3158_rtw_memcpy(pwps_ie, pwps_ie_src, wps_ielen + 2);3159pwps_ie += (wps_ielen + 2);31603161if (pbackup_remainder_ie)3162_rtw_memcpy(pwps_ie, pbackup_remainder_ie, remainder_ielen);31633164/* update IELength */3165pnetwork->IELength = wps_offset + (wps_ielen + 2) + remainder_ielen;3166}31673168if (pbackup_remainder_ie)3169rtw_mfree(pbackup_remainder_ie, remainder_ielen);31703171/* deal with the case without set_tx_beacon_cmd() in update_beacon() */3172#if defined(CONFIG_INTERRUPT_BASED_TXBCN) || defined(CONFIG_PCI_HCI)3173if ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE) {3174u8 sr = 0;3175rtw_get_wps_attr_content(pwps_ie_src, wps_ielen, WPS_ATTR_SELECTED_REGISTRAR, (u8 *)(&sr), NULL);31763177if (sr) {3178set_fwstate(pmlmepriv, WIFI_UNDER_WPS);3179RTW_INFO("%s, set WIFI_UNDER_WPS\n", __func__);3180} else {3181clr_fwstate(pmlmepriv, WIFI_UNDER_WPS);3182RTW_INFO("%s, clr WIFI_UNDER_WPS\n", __func__);3183}3184}3185#endif3186}31873188static void update_bcn_p2p_ie(_adapter *padapter)3189{31903191}31923193static void update_bcn_vendor_spec_ie(_adapter *padapter, u8 *oui)3194{3195RTW_INFO("%s\n", __FUNCTION__);31963197if (_rtw_memcmp(RTW_WPA_OUI, oui, 4))3198update_bcn_wpa_ie(padapter);3199else if (_rtw_memcmp(WMM_OUI, oui, 4))3200update_bcn_wmm_ie(padapter);3201else if (_rtw_memcmp(WPS_OUI, oui, 4))3202update_bcn_wps_ie(padapter);3203else if (_rtw_memcmp(P2P_OUI, oui, 4))3204update_bcn_p2p_ie(padapter);3205else3206RTW_INFO("unknown OUI type!\n");320732083209}32103211void _update_beacon(_adapter *padapter, u8 ie_id, u8 *oui, u8 tx, u8 flags, const char *tag)3212{3213_irqL irqL;3214struct mlme_priv *pmlmepriv;3215struct mlme_ext_priv *pmlmeext;3216bool updated = 1; /* treat as upadated by default */32173218if (!padapter)3219return;32203221pmlmepriv = &(padapter->mlmepriv);3222pmlmeext = &(padapter->mlmeextpriv);32233224if (pmlmeext->bstart_bss == _FALSE)3225return;32263227_enter_critical_bh(&pmlmepriv->bcn_update_lock, &irqL);32283229switch (ie_id) {3230case _TIM_IE_:3231update_BCNTIM(padapter);3232break;32333234case _ERPINFO_IE_:3235update_bcn_erpinfo_ie(padapter);3236break;32373238case _HT_CAPABILITY_IE_:3239update_bcn_htcap_ie(padapter);3240break;32413242case _RSN_IE_2_:3243update_bcn_rsn_ie(padapter);3244break;32453246case _HT_ADD_INFO_IE_:3247update_bcn_htinfo_ie(padapter);3248break;32493250case _EXT_CAP_IE_:3251update_bcn_ext_capab_ie(padapter);3252break;32533254#ifdef CONFIG_RTW_MESH3255case WLAN_EID_MESH_CONFIG:3256updated = rtw_mesh_update_bss_peering_status(padapter, &(pmlmeext->mlmext_info.network));3257updated |= rtw_mesh_update_bss_formation_info(padapter, &(pmlmeext->mlmext_info.network));3258updated |= rtw_mesh_update_bss_forwarding_state(padapter, &(pmlmeext->mlmext_info.network));3259break;3260#endif32613262case _VENDOR_SPECIFIC_IE_:3263update_bcn_vendor_spec_ie(padapter, oui);3264break;32653266case 0xFF:3267default:3268break;3269}32703271if (updated)3272pmlmepriv->update_bcn = _TRUE;32733274_exit_critical_bh(&pmlmepriv->bcn_update_lock, &irqL);32753276#ifndef CONFIG_INTERRUPT_BASED_TXBCN3277#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI) || defined(CONFIG_PCI_BCN_POLLING)3278if (tx && updated) {3279/* send_beacon(padapter); */ /* send_beacon must execute on TSR level */3280if (0)3281RTW_INFO(FUNC_ADPT_FMT" ie_id:%u - %s\n", FUNC_ADPT_ARG(padapter), ie_id, tag);3282if(flags == RTW_CMDF_WAIT_ACK)3283set_tx_beacon_cmd(padapter, RTW_CMDF_WAIT_ACK);3284else3285set_tx_beacon_cmd(padapter, 0);3286}3287#else3288{3289/* PCI will issue beacon when BCN interrupt occurs. */3290}3291#endif3292#endif /* !CONFIG_INTERRUPT_BASED_TXBCN */3293}32943295#ifdef CONFIG_80211N_HT32963297void rtw_process_public_act_bsscoex(_adapter *padapter, u8 *pframe, uint frame_len)3298{3299struct sta_info *psta;3300struct sta_priv *pstapriv = &padapter->stapriv;3301u8 beacon_updated = _FALSE;3302struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);3303u8 *frame_body = pframe + sizeof(struct rtw_ieee80211_hdr_3addr);3304uint frame_body_len = frame_len - sizeof(struct rtw_ieee80211_hdr_3addr);3305u8 category, action;33063307psta = rtw_get_stainfo(pstapriv, get_addr2_ptr(pframe));3308if (psta == NULL)3309return;331033113312category = frame_body[0];3313action = frame_body[1];33143315if (frame_body_len > 0) {3316if ((frame_body[2] == EID_BSSCoexistence) && (frame_body[3] > 0)) {3317u8 ie_data = frame_body[4];33183319if (ie_data & RTW_WLAN_20_40_BSS_COEX_40MHZ_INTOL) {3320if (psta->ht_40mhz_intolerant == 0) {3321psta->ht_40mhz_intolerant = 1;3322pmlmepriv->num_sta_40mhz_intolerant++;3323beacon_updated = _TRUE;3324}3325} else if (ie_data & RTW_WLAN_20_40_BSS_COEX_20MHZ_WIDTH_REQ) {3326if (pmlmepriv->ht_20mhz_width_req == _FALSE) {3327pmlmepriv->ht_20mhz_width_req = _TRUE;3328beacon_updated = _TRUE;3329}3330} else3331beacon_updated = _FALSE;3332}3333}33343335if (frame_body_len > 8) {3336/* if EID_BSSIntolerantChlReport ie exists */3337if ((frame_body[5] == EID_BSSIntolerantChlReport) && (frame_body[6] > 0)) {3338/*todo:*/3339if (pmlmepriv->ht_intolerant_ch_reported == _FALSE) {3340pmlmepriv->ht_intolerant_ch_reported = _TRUE;3341beacon_updated = _TRUE;3342}3343}3344}33453346if (beacon_updated) {33473348update_beacon(padapter, _HT_ADD_INFO_IE_, NULL, _TRUE, 0);33493350associated_stainfo_update(padapter, psta, STA_INFO_UPDATE_BW);3351}3352335333543355}33563357void rtw_process_ht_action_smps(_adapter *padapter, u8 *ta, u8 ctrl_field)3358{3359u8 e_field, m_field;3360struct sta_info *psta;3361struct sta_priv *pstapriv = &padapter->stapriv;33623363psta = rtw_get_stainfo(pstapriv, ta);3364if (psta == NULL)3365return;33663367e_field = (ctrl_field & BIT(0)) ? 1 : 0; /*SM Power Save Enabled*/3368m_field = (ctrl_field & BIT(1)) ? 1 : 0; /*SM Mode, 0:static SMPS, 1:dynamic SMPS*/33693370if (e_field) {3371if (m_field) { /*mode*/3372psta->htpriv.smps_cap = WLAN_HT_CAP_SM_PS_DYNAMIC;3373RTW_ERR("Don't support dynamic SMPS\n");3374}3375else3376psta->htpriv.smps_cap = WLAN_HT_CAP_SM_PS_STATIC;3377} else {3378/*disable*/3379psta->htpriv.smps_cap = WLAN_HT_CAP_SM_PS_DISABLED;3380}33813382if (psta->htpriv.smps_cap != WLAN_HT_CAP_SM_PS_DYNAMIC)3383rtw_ssmps_wk_cmd(padapter, psta, e_field, 1);3384}33853386/*3387op_mode3388Set to 0 (HT pure) under the followign conditions3389- all STAs in the BSS are 20/40 MHz HT in 20/40 MHz BSS or3390- all STAs in the BSS are 20 MHz HT in 20 MHz BSS3391Set to 1 (HT non-member protection) if there may be non-HT STAs3392in both the primary and the secondary channel3393Set to 2 if only HT STAs are associated in BSS,3394however and at least one 20 MHz HT STA is associated3395Set to 3 (HT mixed mode) when one or more non-HT STAs are associated3396(currently non-GF HT station is considered as non-HT STA also)3397*/3398int rtw_ht_operation_update(_adapter *padapter)3399{3400u16 cur_op_mode, new_op_mode;3401int op_mode_changes = 0;3402struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);3403struct ht_priv *phtpriv_ap = &pmlmepriv->htpriv;34043405if (pmlmepriv->htpriv.ht_option == _FALSE)3406return 0;34073408/*if (!iface->conf->ieee80211n || iface->conf->ht_op_mode_fixed)3409return 0;*/34103411RTW_INFO("%s current operation mode=0x%X\n",3412__FUNCTION__, pmlmepriv->ht_op_mode);34133414if (!(pmlmepriv->ht_op_mode & HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT)3415&& pmlmepriv->num_sta_ht_no_gf) {3416pmlmepriv->ht_op_mode |=3417HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT;3418op_mode_changes++;3419} else if ((pmlmepriv->ht_op_mode &3420HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT) &&3421pmlmepriv->num_sta_ht_no_gf == 0) {3422pmlmepriv->ht_op_mode &=3423~HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT;3424op_mode_changes++;3425}34263427if (!(pmlmepriv->ht_op_mode & HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT) &&3428(pmlmepriv->num_sta_no_ht || ATOMIC_READ(&pmlmepriv->olbc_ht))) {3429pmlmepriv->ht_op_mode |= HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT;3430op_mode_changes++;3431} else if ((pmlmepriv->ht_op_mode &3432HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT) &&3433(pmlmepriv->num_sta_no_ht == 0 && !ATOMIC_READ(&pmlmepriv->olbc_ht))) {3434pmlmepriv->ht_op_mode &=3435~HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT;3436op_mode_changes++;3437}34383439/* Note: currently we switch to the MIXED op mode if HT non-greenfield3440* station is associated. Probably it's a theoretical case, since3441* it looks like all known HT STAs support greenfield.3442*/3443new_op_mode = 0;3444if (pmlmepriv->num_sta_no_ht /*||3445(pmlmepriv->ht_op_mode & HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT)*/)3446new_op_mode = OP_MODE_MIXED;3447else if ((phtpriv_ap->ht_cap.cap_info & IEEE80211_HT_CAP_SUP_WIDTH)3448&& pmlmepriv->num_sta_ht_20mhz)3449new_op_mode = OP_MODE_20MHZ_HT_STA_ASSOCED;3450else if (ATOMIC_READ(&pmlmepriv->olbc_ht))3451new_op_mode = OP_MODE_MAY_BE_LEGACY_STAS;3452else3453new_op_mode = OP_MODE_PURE;34543455cur_op_mode = pmlmepriv->ht_op_mode & HT_INFO_OPERATION_MODE_OP_MODE_MASK;3456if (cur_op_mode != new_op_mode) {3457pmlmepriv->ht_op_mode &= ~HT_INFO_OPERATION_MODE_OP_MODE_MASK;3458pmlmepriv->ht_op_mode |= new_op_mode;3459op_mode_changes++;3460}34613462RTW_INFO("%s new operation mode=0x%X changes=%d\n",3463__FUNCTION__, pmlmepriv->ht_op_mode, op_mode_changes);34643465return op_mode_changes;34663467}34683469#endif /* CONFIG_80211N_HT */34703471void associated_clients_update(_adapter *padapter, u8 updated, u32 sta_info_type)3472{3473/* update associcated stations cap. */3474if (updated == _TRUE) {3475_irqL irqL;3476_list *phead, *plist;3477struct sta_info *psta = NULL;3478struct sta_priv *pstapriv = &padapter->stapriv;34793480_enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);34813482phead = &pstapriv->asoc_list;3483plist = get_next(phead);34843485/* check asoc_queue */3486while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {3487psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);34883489plist = get_next(plist);34903491associated_stainfo_update(padapter, psta, sta_info_type);3492}34933494_exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);34953496}34973498}34993500/* called > TSR LEVEL for USB or SDIO Interface*/3501void bss_cap_update_on_sta_join(_adapter *padapter, struct sta_info *psta)3502{3503u8 beacon_updated = _FALSE;3504struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);3505struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);350635073508#if 03509if (!(psta->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) &&3510!psta->no_short_preamble_set) {3511psta->no_short_preamble_set = 1;3512pmlmepriv->num_sta_no_short_preamble++;3513if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) &&3514(pmlmepriv->num_sta_no_short_preamble == 1))3515ieee802_11_set_beacons(hapd->iface);3516}3517#endif351835193520if (!(psta->flags & WLAN_STA_SHORT_PREAMBLE)) {3521if (!psta->no_short_preamble_set) {3522psta->no_short_preamble_set = 1;35233524pmlmepriv->num_sta_no_short_preamble++;35253526if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) &&3527(pmlmepriv->num_sta_no_short_preamble == 1))3528beacon_updated = _TRUE;3529}3530} else {3531if (psta->no_short_preamble_set) {3532psta->no_short_preamble_set = 0;35333534pmlmepriv->num_sta_no_short_preamble--;35353536if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) &&3537(pmlmepriv->num_sta_no_short_preamble == 0))3538beacon_updated = _TRUE;3539}3540}35413542#if 03543if (psta->flags & WLAN_STA_NONERP && !psta->nonerp_set) {3544psta->nonerp_set = 1;3545pmlmepriv->num_sta_non_erp++;3546if (pmlmepriv->num_sta_non_erp == 1)3547ieee802_11_set_beacons(hapd->iface);3548}3549#endif35503551if (psta->flags & WLAN_STA_NONERP) {3552if (!psta->nonerp_set) {3553psta->nonerp_set = 1;35543555pmlmepriv->num_sta_non_erp++;35563557if (pmlmepriv->num_sta_non_erp == 1) {3558beacon_updated = _TRUE;3559update_beacon(padapter, _ERPINFO_IE_, NULL, _FALSE, 0);3560}3561}35623563} else {3564if (psta->nonerp_set) {3565psta->nonerp_set = 0;35663567pmlmepriv->num_sta_non_erp--;35683569if (pmlmepriv->num_sta_non_erp == 0) {3570beacon_updated = _TRUE;3571update_beacon(padapter, _ERPINFO_IE_, NULL, _FALSE, 0);3572}3573}35743575}357635773578#if 03579if (!(psta->capability & WLAN_CAPABILITY_SHORT_SLOT) &&3580!psta->no_short_slot_time_set) {3581psta->no_short_slot_time_set = 1;3582pmlmepriv->num_sta_no_short_slot_time++;3583if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) &&3584(pmlmepriv->num_sta_no_short_slot_time == 1))3585ieee802_11_set_beacons(hapd->iface);3586}3587#endif35883589if (!(psta->capability & WLAN_CAPABILITY_SHORT_SLOT)) {3590if (!psta->no_short_slot_time_set) {3591psta->no_short_slot_time_set = 1;35923593pmlmepriv->num_sta_no_short_slot_time++;35943595if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) &&3596(pmlmepriv->num_sta_no_short_slot_time == 1))3597beacon_updated = _TRUE;3598}3599} else {3600if (psta->no_short_slot_time_set) {3601psta->no_short_slot_time_set = 0;36023603pmlmepriv->num_sta_no_short_slot_time--;36043605if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) &&3606(pmlmepriv->num_sta_no_short_slot_time == 0))3607beacon_updated = _TRUE;3608}3609}36103611#ifdef CONFIG_80211N_HT3612if(padapter->registrypriv.ht_enable &&3613is_supported_ht(padapter->registrypriv.wireless_mode)) {3614if (psta->flags & WLAN_STA_HT) {3615u16 ht_capab = le16_to_cpu(psta->htpriv.ht_cap.cap_info);36163617RTW_INFO("HT: STA " MAC_FMT " HT Capabilities Info: 0x%04x\n",3618MAC_ARG(psta->cmn.mac_addr), ht_capab);36193620if (psta->no_ht_set) {3621psta->no_ht_set = 0;3622pmlmepriv->num_sta_no_ht--;3623}36243625if ((ht_capab & IEEE80211_HT_CAP_GRN_FLD) == 0) {3626if (!psta->no_ht_gf_set) {3627psta->no_ht_gf_set = 1;3628pmlmepriv->num_sta_ht_no_gf++;3629}3630RTW_INFO("%s STA " MAC_FMT " - no "3631"greenfield, num of non-gf stations %d\n",3632__FUNCTION__, MAC_ARG(psta->cmn.mac_addr),3633pmlmepriv->num_sta_ht_no_gf);3634}36353636if ((ht_capab & IEEE80211_HT_CAP_SUP_WIDTH) == 0) {3637if (!psta->ht_20mhz_set) {3638psta->ht_20mhz_set = 1;3639pmlmepriv->num_sta_ht_20mhz++;3640}3641RTW_INFO("%s STA " MAC_FMT " - 20 MHz HT, "3642"num of 20MHz HT STAs %d\n",3643__FUNCTION__, MAC_ARG(psta->cmn.mac_addr),3644pmlmepriv->num_sta_ht_20mhz);3645}36463647if (((ht_capab & RTW_IEEE80211_HT_CAP_40MHZ_INTOLERANT) != 0) &&3648(psta->ht_40mhz_intolerant == 0)) {3649psta->ht_40mhz_intolerant = 1;3650pmlmepriv->num_sta_40mhz_intolerant++;3651RTW_INFO("%s STA " MAC_FMT " - 40MHZ_INTOLERANT, ",3652__FUNCTION__, MAC_ARG(psta->cmn.mac_addr));3653}36543655} else {3656if (!psta->no_ht_set) {3657psta->no_ht_set = 1;3658pmlmepriv->num_sta_no_ht++;3659}3660if (pmlmepriv->htpriv.ht_option == _TRUE) {3661RTW_INFO("%s STA " MAC_FMT3662" - no HT, num of non-HT stations %d\n",3663__FUNCTION__, MAC_ARG(psta->cmn.mac_addr),3664pmlmepriv->num_sta_no_ht);3665}3666}36673668if (rtw_ht_operation_update(padapter) > 0) {3669update_beacon(padapter, _HT_CAPABILITY_IE_, NULL, _FALSE, 0);3670update_beacon(padapter, _HT_ADD_INFO_IE_, NULL, _FALSE, 0);3671beacon_updated = _TRUE;3672}3673}3674#endif /* CONFIG_80211N_HT */36753676#ifdef CONFIG_RTW_MESH3677if (MLME_IS_MESH(padapter)) {3678struct sta_priv *pstapriv = &padapter->stapriv;36793680update_beacon(padapter, WLAN_EID_MESH_CONFIG, NULL, _FALSE, 0);3681if (pstapriv->asoc_list_cnt == 1)3682_set_timer(&padapter->mesh_atlm_param_req_timer, 0);3683beacon_updated = _TRUE;3684}3685#endif36863687if (beacon_updated)3688update_beacon(padapter, 0xFF, NULL, _TRUE, 0);36893690/* update associcated stations cap. */3691associated_clients_update(padapter, beacon_updated, STA_INFO_UPDATE_ALL);36923693RTW_INFO("%s, updated=%d\n", __func__, beacon_updated);36943695}36963697u8 bss_cap_update_on_sta_leave(_adapter *padapter, struct sta_info *psta)3698{3699u8 beacon_updated = _FALSE;3700struct sta_priv *pstapriv = &padapter->stapriv;3701struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);3702struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);37033704if (!psta)3705return beacon_updated;37063707if (rtw_tim_map_is_set(padapter, pstapriv->tim_bitmap, psta->cmn.aid)) {3708rtw_tim_map_clear(padapter, pstapriv->tim_bitmap, psta->cmn.aid);3709beacon_updated = _TRUE;3710update_beacon(padapter, _TIM_IE_, NULL, _FALSE, 0);3711}37123713if (psta->no_short_preamble_set) {3714psta->no_short_preamble_set = 0;3715pmlmepriv->num_sta_no_short_preamble--;3716if (pmlmeext->cur_wireless_mode > WIRELESS_11B3717&& pmlmepriv->num_sta_no_short_preamble == 0)3718beacon_updated = _TRUE;3719}37203721if (psta->nonerp_set) {3722psta->nonerp_set = 0;3723pmlmepriv->num_sta_non_erp--;3724if (pmlmepriv->num_sta_non_erp == 0) {3725beacon_updated = _TRUE;3726update_beacon(padapter, _ERPINFO_IE_, NULL, _FALSE, 0);3727}3728}37293730if (psta->no_short_slot_time_set) {3731psta->no_short_slot_time_set = 0;3732pmlmepriv->num_sta_no_short_slot_time--;3733if (pmlmeext->cur_wireless_mode > WIRELESS_11B3734&& pmlmepriv->num_sta_no_short_slot_time == 0)3735beacon_updated = _TRUE;3736}37373738#ifdef CONFIG_80211N_HT3739if (psta->no_ht_gf_set) {3740psta->no_ht_gf_set = 0;3741pmlmepriv->num_sta_ht_no_gf--;3742}37433744if (psta->no_ht_set) {3745psta->no_ht_set = 0;3746pmlmepriv->num_sta_no_ht--;3747}37483749if (psta->ht_20mhz_set) {3750psta->ht_20mhz_set = 0;3751pmlmepriv->num_sta_ht_20mhz--;3752}37533754if (psta->ht_40mhz_intolerant) {3755psta->ht_40mhz_intolerant = 0;3756if (pmlmepriv->num_sta_40mhz_intolerant > 0)3757pmlmepriv->num_sta_40mhz_intolerant--;3758else3759rtw_warn_on(1);3760}37613762if (rtw_ht_operation_update(padapter) > 0) {3763update_beacon(padapter, _HT_CAPABILITY_IE_, NULL, _FALSE, 0);3764update_beacon(padapter, _HT_ADD_INFO_IE_, NULL, _FALSE, 0);3765}3766#endif /* CONFIG_80211N_HT */37673768#ifdef CONFIG_RTW_MESH3769if (MLME_IS_MESH(padapter)) {3770update_beacon(padapter, WLAN_EID_MESH_CONFIG, NULL, _FALSE, 0);3771if (pstapriv->asoc_list_cnt == 0)3772_cancel_timer_ex(&padapter->mesh_atlm_param_req_timer);3773beacon_updated = _TRUE;3774}3775#endif37763777if (beacon_updated == _TRUE)3778update_beacon(padapter, 0xFF, NULL, _TRUE, 0);37793780#if 03781/* update associated stations cap. */3782associated_clients_update(padapter, beacon_updated, STA_INFO_UPDATE_ALL); /* move it to avoid deadlock */3783#endif37843785RTW_INFO("%s, updated=%d\n", __func__, beacon_updated);37863787return beacon_updated;37883789}37903791u8 ap_free_sta(_adapter *padapter, struct sta_info *psta, bool active, u16 reason, bool enqueue)3792{3793_irqL irqL;3794u8 beacon_updated = _FALSE;37953796if (!psta)3797return beacon_updated;37983799if (active == _TRUE) {3800#ifdef CONFIG_80211N_HT3801/* tear down Rx AMPDU */3802send_delba(padapter, 0, psta->cmn.mac_addr);/* recipient */38033804/* tear down TX AMPDU */3805send_delba(padapter, 1, psta->cmn.mac_addr);/* */ /* originator */38063807#endif /* CONFIG_80211N_HT */38083809if (!MLME_IS_MESH(padapter))3810issue_deauth(padapter, psta->cmn.mac_addr, reason);3811}38123813#ifdef CONFIG_RTW_MESH3814if (MLME_IS_MESH(padapter))3815rtw_mesh_path_flush_by_nexthop(psta);3816#endif38173818#ifdef CONFIG_BEAMFORMING3819beamforming_wk_cmd(padapter, BEAMFORMING_CTRL_LEAVE, psta->cmn.mac_addr, ETH_ALEN, 1);3820#endif38213822#ifdef CONFIG_80211N_HT3823psta->htpriv.agg_enable_bitmap = 0x0;/* reset */3824psta->htpriv.candidate_tid_bitmap = 0x0;/* reset */3825#endif38263827/* clear cam entry / key */3828rtw_clearstakey_cmd(padapter, psta, enqueue);382938303831_enter_critical_bh(&psta->lock, &irqL);3832psta->state &= ~(_FW_LINKED | WIFI_UNDER_KEY_HANDSHAKE);38333834if ((psta->auth_len != 0) && (psta->pauth_frame != NULL)) {3835rtw_mfree(psta->pauth_frame, psta->auth_len);3836psta->pauth_frame = NULL;3837psta->auth_len = 0;3838}3839_exit_critical_bh(&psta->lock, &irqL);38403841if (!MLME_IS_MESH(padapter)) {3842#ifdef CONFIG_IOCTL_CFG802113843#ifdef COMPAT_KERNEL_RELEASE3844rtw_cfg80211_indicate_sta_disassoc(padapter, psta->cmn.mac_addr, reason);3845#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) && !defined(CONFIG_CFG80211_FORCE_COMPATIBLE_2_6_37_UNDER)3846rtw_cfg80211_indicate_sta_disassoc(padapter, psta->cmn.mac_addr, reason);3847#else /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) && !defined(CONFIG_CFG80211_FORCE_COMPATIBLE_2_6_37_UNDER) */3848/* will call rtw_cfg80211_indicate_sta_disassoc() in cmd_thread for old API context */3849#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) && !defined(CONFIG_CFG80211_FORCE_COMPATIBLE_2_6_37_UNDER) */3850#else3851rtw_indicate_sta_disassoc_event(padapter, psta);3852#endif3853}38543855beacon_updated = bss_cap_update_on_sta_leave(padapter, psta);38563857report_del_sta_event(padapter, psta->cmn.mac_addr, reason, enqueue, _FALSE);38583859return beacon_updated;38603861}38623863int rtw_ap_inform_ch_switch(_adapter *padapter, u8 new_ch, u8 ch_offset)3864{3865_irqL irqL;3866_list *phead, *plist;3867int ret = 0;3868struct sta_info *psta = NULL;3869struct sta_priv *pstapriv = &padapter->stapriv;3870struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;3871struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);3872u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};38733874if ((pmlmeinfo->state & 0x03) != WIFI_FW_AP_STATE)3875return ret;38763877RTW_INFO(FUNC_NDEV_FMT" with ch:%u, offset:%u\n",3878FUNC_NDEV_ARG(padapter->pnetdev), new_ch, ch_offset);38793880_enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);3881phead = &pstapriv->asoc_list;3882plist = get_next(phead);38833884/* for each sta in asoc_queue */3885while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {3886psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);3887plist = get_next(plist);38883889issue_action_spct_ch_switch(padapter, psta->cmn.mac_addr, new_ch, ch_offset);3890psta->expire_to = ((pstapriv->expire_to * 2) > 5) ? 5 : (pstapriv->expire_to * 2);3891}3892_exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);38933894issue_action_spct_ch_switch(padapter, bc_addr, new_ch, ch_offset);38953896return ret;3897}38983899int rtw_sta_flush(_adapter *padapter, bool enqueue)3900{3901_irqL irqL;3902_list *phead, *plist;3903int ret = 0;3904struct sta_info *psta = NULL;3905struct sta_priv *pstapriv = &padapter->stapriv;3906u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};3907u8 flush_num = 0;3908char flush_list[NUM_STA];3909int i;39103911if (!MLME_IS_AP(padapter) && !MLME_IS_MESH(padapter))3912return ret;39133914RTW_INFO(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(padapter->pnetdev));39153916/* pick sta from sta asoc_queue */3917_enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);3918phead = &pstapriv->asoc_list;3919plist = get_next(phead);3920while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {3921int stainfo_offset;39223923psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);3924plist = get_next(plist);39253926rtw_list_delete(&psta->asoc_list);3927pstapriv->asoc_list_cnt--;3928STA_SET_MESH_PLINK(psta, NULL);39293930stainfo_offset = rtw_stainfo_offset(pstapriv, psta);3931if (stainfo_offset_valid(stainfo_offset))3932flush_list[flush_num++] = stainfo_offset;3933else3934rtw_warn_on(1);3935}3936_exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);39373938/* call ap_free_sta() for each sta picked */3939for (i = 0; i < flush_num; i++) {3940u8 sta_addr[ETH_ALEN];39413942psta = rtw_get_stainfo_by_offset(pstapriv, flush_list[i]);3943_rtw_memcpy(sta_addr, psta->cmn.mac_addr, ETH_ALEN);39443945ap_free_sta(padapter, psta, _TRUE, WLAN_REASON_DEAUTH_LEAVING, enqueue);3946#ifdef CONFIG_RTW_MESH3947if (MLME_IS_MESH(padapter))3948rtw_mesh_expire_peer(padapter, sta_addr);3949#endif3950}39513952if (!MLME_IS_MESH(padapter))3953issue_deauth(padapter, bc_addr, WLAN_REASON_DEAUTH_LEAVING);39543955associated_clients_update(padapter, _TRUE, STA_INFO_UPDATE_ALL);39563957return ret;3958}39593960/* called > TSR LEVEL for USB or SDIO Interface*/3961void sta_info_update(_adapter *padapter, struct sta_info *psta)3962{3963int flags = psta->flags;3964struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);396539663967/* update wmm cap. */3968if (WLAN_STA_WME & flags)3969psta->qos_option = 1;3970else3971psta->qos_option = 0;39723973if (pmlmepriv->qospriv.qos_option == 0)3974psta->qos_option = 0;397539763977#ifdef CONFIG_80211N_HT3978/* update 802.11n ht cap. */3979if (WLAN_STA_HT & flags) {3980psta->htpriv.ht_option = _TRUE;3981psta->qos_option = 1;39823983psta->htpriv.smps_cap = (psta->htpriv.ht_cap.cap_info & IEEE80211_HT_CAP_SM_PS) >> 2;3984} else3985psta->htpriv.ht_option = _FALSE;39863987if (pmlmepriv->htpriv.ht_option == _FALSE)3988psta->htpriv.ht_option = _FALSE;3989#endif39903991#ifdef CONFIG_80211AC_VHT3992/* update 802.11AC vht cap. */3993if (WLAN_STA_VHT & flags)3994psta->vhtpriv.vht_option = _TRUE;3995else3996psta->vhtpriv.vht_option = _FALSE;39973998if (pmlmepriv->vhtpriv.vht_option == _FALSE)3999psta->vhtpriv.vht_option = _FALSE;4000#endif40014002update_sta_info_apmode(padapter, psta);4003}40044005/* called >= TSR LEVEL for USB or SDIO Interface*/4006void ap_sta_info_defer_update(_adapter *padapter, struct sta_info *psta)4007{4008if (psta->state & _FW_LINKED)4009rtw_hal_update_ra_mask(psta); /* DM_RATR_STA_INIT */4010}4011/* restore hw setting from sw data structures */4012void rtw_ap_restore_network(_adapter *padapter)4013{4014struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;4015struct sta_priv *pstapriv = &padapter->stapriv;4016struct sta_info *psta;4017struct security_priv *psecuritypriv = &(padapter->securitypriv);4018_irqL irqL;4019_list *phead, *plist;4020u8 chk_alive_num = 0;4021char chk_alive_list[NUM_STA];4022int i;40234024rtw_setopmode_cmd(padapter4025, MLME_IS_AP(padapter) ? Ndis802_11APMode : Ndis802_11_mesh4026, RTW_CMDF_DIRECTLY4027);40284029set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);40304031rtw_startbss_cmd(padapter, RTW_CMDF_DIRECTLY);40324033if ((padapter->securitypriv.dot11PrivacyAlgrthm == _TKIP_) ||4034(padapter->securitypriv.dot11PrivacyAlgrthm == _AES_)) {4035/* restore group key, WEP keys is restored in ips_leave() */4036rtw_set_key(padapter, psecuritypriv, psecuritypriv->dot118021XGrpKeyid, 0, _FALSE);4037}40384039_enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);40404041phead = &pstapriv->asoc_list;4042plist = get_next(phead);40434044while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {4045int stainfo_offset;40464047psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);4048plist = get_next(plist);40494050stainfo_offset = rtw_stainfo_offset(pstapriv, psta);4051if (stainfo_offset_valid(stainfo_offset))4052chk_alive_list[chk_alive_num++] = stainfo_offset;4053}40544055_exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);40564057for (i = 0; i < chk_alive_num; i++) {4058psta = rtw_get_stainfo_by_offset(pstapriv, chk_alive_list[i]);40594060if (psta == NULL)4061RTW_INFO(FUNC_ADPT_FMT" sta_info is null\n", FUNC_ADPT_ARG(padapter));4062else if (psta->state & _FW_LINKED) {4063rtw_sta_media_status_rpt(padapter, psta, 1);4064Update_RA_Entry(padapter, psta);4065/* pairwise key */4066/* per sta pairwise key and settings */4067if ((padapter->securitypriv.dot11PrivacyAlgrthm == _TKIP_) ||4068(padapter->securitypriv.dot11PrivacyAlgrthm == _AES_))4069rtw_setstakey_cmd(padapter, psta, UNICAST_KEY, _FALSE);4070}4071}40724073}40744075void start_ap_mode(_adapter *padapter)4076{4077int i;4078struct sta_info *psta = NULL;4079struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);4080struct sta_priv *pstapriv = &padapter->stapriv;4081struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;4082struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);4083#ifdef CONFIG_CONCURRENT_MODE4084struct security_priv *psecuritypriv = &padapter->securitypriv;4085#endif40864087pmlmepriv->update_bcn = _FALSE;40884089/*init_mlme_ap_info(padapter);*/40904091pmlmeext->bstart_bss = _FALSE;40924093pmlmepriv->num_sta_non_erp = 0;40944095pmlmepriv->num_sta_no_short_slot_time = 0;40964097pmlmepriv->num_sta_no_short_preamble = 0;40984099pmlmepriv->num_sta_ht_no_gf = 0;4100#ifdef CONFIG_80211N_HT4101pmlmepriv->num_sta_no_ht = 0;4102#endif /* CONFIG_80211N_HT */4103pmlmeinfo->HT_info_enable = 0;4104pmlmeinfo->HT_caps_enable = 0;4105pmlmeinfo->HT_enable = 0;41064107pmlmepriv->num_sta_ht_20mhz = 0;4108pmlmepriv->num_sta_40mhz_intolerant = 0;4109ATOMIC_SET(&pmlmepriv->olbc, _FALSE);4110ATOMIC_SET(&pmlmepriv->olbc_ht, _FALSE);41114112#ifdef CONFIG_80211N_HT4113pmlmepriv->ht_20mhz_width_req = _FALSE;4114pmlmepriv->ht_intolerant_ch_reported = _FALSE;4115pmlmepriv->ht_op_mode = 0;4116pmlmepriv->sw_to_20mhz = 0;4117#endif41184119_rtw_memset(pmlmepriv->ext_capab_ie_data, 0, sizeof(pmlmepriv->ext_capab_ie_data));4120pmlmepriv->ext_capab_ie_len = 0;41214122#ifdef CONFIG_CONCURRENT_MODE4123psecuritypriv->dot118021x_bmc_cam_id = INVALID_SEC_MAC_CAM_ID;4124#endif41254126for (i = 0 ; i < pstapriv->max_aid; i++)4127pstapriv->sta_aid[i] = NULL;41284129psta = rtw_get_bcmc_stainfo(padapter);4130/*_enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL);*/4131if (psta)4132rtw_free_stainfo(padapter, psta);4133/*_exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL);*/41344135rtw_init_bcmc_stainfo(padapter);41364137if (rtw_mi_get_ap_num(padapter))4138RTW_SET_SCAN_BAND_SKIP(padapter, BAND_5G);41394140}41414142void rtw_ap_bcmc_sta_flush(_adapter *padapter)4143{4144#ifdef CONFIG_CONCURRENT_MODE4145int cam_id = -1;4146u8 *addr = adapter_mac_addr(padapter);41474148cam_id = rtw_iface_bcmc_id_get(padapter);4149if (cam_id != INVALID_SEC_MAC_CAM_ID) {4150RTW_PRINT("clear group key for "ADPT_FMT" addr:"MAC_FMT", camid:%d\n",4151ADPT_ARG(padapter), MAC_ARG(addr), cam_id);4152clear_cam_entry(padapter, cam_id);4153rtw_camid_free(padapter, cam_id);4154rtw_iface_bcmc_id_set(padapter, INVALID_SEC_MAC_CAM_ID); /*init default value*/4155}4156#else4157invalidate_cam_all(padapter);4158#endif4159}41604161void stop_ap_mode(_adapter *padapter)4162{4163u8 self_action = MLME_ACTION_UNKNOWN;4164struct sta_info *psta = NULL;4165struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);4166struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;4167#ifdef CONFIG_SUPPORT_MULTI_BCN4168struct dvobj_priv *pdvobj = padapter->dvobj;4169_irqL irqL;4170#endif41714172RTW_INFO("%s -"ADPT_FMT"\n", __func__, ADPT_ARG(padapter));41734174if (MLME_IS_AP(padapter))4175self_action = MLME_AP_STOPPED;4176else if (MLME_IS_MESH(padapter))4177self_action = MLME_MESH_STOPPED;4178else4179rtw_warn_on(1);41804181pmlmepriv->update_bcn = _FALSE;4182/*pmlmeext->bstart_bss = _FALSE;*/4183padapter->netif_up = _FALSE;4184/* _rtw_spinlock_free(&pmlmepriv->bcn_update_lock); */41854186/* reset and init security priv , this can refine with rtw_reset_securitypriv */4187_rtw_memset((unsigned char *)&padapter->securitypriv, 0, sizeof(struct security_priv));4188padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeOpen;4189padapter->securitypriv.ndisencryptstatus = Ndis802_11WEPDisabled;41904191#ifdef CONFIG_DFS_MASTER4192rtw_dfs_rd_en_decision(padapter, self_action, 0);4193#endif41944195/* free scan queue */4196rtw_free_network_queue(padapter, _TRUE);41974198#if CONFIG_RTW_MACADDR_ACL4199rtw_macaddr_acl_clear(padapter, RTW_ACL_PERIOD_BSS);4200#endif42014202rtw_sta_flush(padapter, _TRUE);4203rtw_ap_bcmc_sta_flush(padapter);42044205/* free_assoc_sta_resources */4206rtw_free_all_stainfo(padapter);42074208psta = rtw_get_bcmc_stainfo(padapter);4209if (psta) {4210rtw_sta_mstatus_disc_rpt(padapter, psta->cmn.mac_id);4211/* _enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL); */4212rtw_free_stainfo(padapter, psta);4213/*_exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL);*/4214}42154216rtw_free_mlme_priv_ie_data(pmlmepriv);42174218#ifdef CONFIG_SUPPORT_MULTI_BCN4219if (pmlmeext->bstart_bss == _TRUE) {4220#ifdef CONFIG_FW_HANDLE_TXBCN4221u8 free_apid = CONFIG_LIMITED_AP_NUM;4222#endif42234224_enter_critical_bh(&pdvobj->ap_if_q.lock, &irqL);4225pdvobj->nr_ap_if--;4226if (pdvobj->nr_ap_if > 0)4227pdvobj->inter_bcn_space = DEFAULT_BCN_INTERVAL / pdvobj->nr_ap_if;4228else4229pdvobj->inter_bcn_space = DEFAULT_BCN_INTERVAL;4230#ifdef CONFIG_FW_HANDLE_TXBCN4231rtw_ap_release_vapid(pdvobj, padapter->vap_id);4232free_apid = padapter->vap_id;4233padapter->vap_id = CONFIG_LIMITED_AP_NUM;4234#endif4235rtw_list_delete(&padapter->list);4236_exit_critical_bh(&pdvobj->ap_if_q.lock, &irqL);4237#ifdef CONFIG_FW_HANDLE_TXBCN4238rtw_ap_mbid_bcn_dis(padapter, free_apid);4239#endif42404241#ifdef CONFIG_SWTIMER_BASED_TXBCN4242rtw_hal_set_hwreg(padapter, HW_VAR_BEACON_INTERVAL, (u8 *)(&pdvobj->inter_bcn_space));42434244if (pdvobj->nr_ap_if == 0)4245_cancel_timer_ex(&pdvobj->txbcn_timer);4246#endif4247}4248#endif42494250pmlmeext->bstart_bss = _FALSE;42514252rtw_hal_rcr_set_chk_bssid(padapter, self_action);42534254#ifdef CONFIG_HW_P0_TSF_SYNC4255correct_TSF(padapter, self_action);4256#endif42574258#ifdef CONFIG_BT_COEXIST4259rtw_btcoex_MediaStatusNotify(padapter, 0); /* disconnect */4260#endif42614262}42634264#endif /* CONFIG_NATIVEAP_MLME */42654266void rtw_ap_update_bss_chbw(_adapter *adapter, WLAN_BSSID_EX *bss, u8 ch, u8 bw, u8 offset)4267{4268#define UPDATE_VHT_CAP 14269#define UPDATE_HT_CAP 14270#ifdef CONFIG_80211AC_VHT4271struct vht_priv *vhtpriv = &adapter->mlmepriv.vhtpriv;4272#endif4273{4274u8 *p;4275int ie_len;4276u8 old_ch = bss->Configuration.DSConfig;4277bool change_band = _FALSE;42784279if ((ch <= 14 && old_ch >= 36) || (ch >= 36 && old_ch <= 14))4280change_band = _TRUE;42814282/* update channel in IE */4283p = rtw_get_ie((bss->IEs + sizeof(NDIS_802_11_FIXED_IEs)), _DSSET_IE_, &ie_len, (bss->IELength - sizeof(NDIS_802_11_FIXED_IEs)));4284if (p && ie_len > 0)4285*(p + 2) = ch;42864287bss->Configuration.DSConfig = ch;42884289/* band is changed, update ERP, support rate, ext support rate IE */4290if (change_band == _TRUE)4291change_band_update_ie(adapter, bss, ch);4292}42934294#ifdef CONFIG_80211AC_VHT4295if (vhtpriv->vht_option == _TRUE) {4296u8 *vht_cap_ie, *vht_op_ie;4297int vht_cap_ielen, vht_op_ielen;4298u8 center_freq;42994300vht_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)));4301vht_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)));4302center_freq = rtw_get_center_ch(ch, bw, offset);43034304/* update vht cap ie */4305if (vht_cap_ie && vht_cap_ielen) {4306#if UPDATE_VHT_CAP4307/* if ((bw == CHANNEL_WIDTH_160 || bw == CHANNEL_WIDTH_80_80) && pvhtpriv->sgi_160m)4308SET_VHT_CAPABILITY_ELE_SHORT_GI160M(pvht_cap_ie + 2, 1);4309else */4310SET_VHT_CAPABILITY_ELE_SHORT_GI160M(vht_cap_ie + 2, 0);43114312if (bw >= CHANNEL_WIDTH_80 && vhtpriv->sgi_80m)4313SET_VHT_CAPABILITY_ELE_SHORT_GI80M(vht_cap_ie + 2, 1);4314else4315SET_VHT_CAPABILITY_ELE_SHORT_GI80M(vht_cap_ie + 2, 0);4316#endif4317}43184319/* update vht op ie */4320if (vht_op_ie && vht_op_ielen) {4321if (bw < CHANNEL_WIDTH_80) {4322SET_VHT_OPERATION_ELE_CHL_WIDTH(vht_op_ie + 2, 0);4323SET_VHT_OPERATION_ELE_CHL_CENTER_FREQ1(vht_op_ie + 2, 0);4324SET_VHT_OPERATION_ELE_CHL_CENTER_FREQ2(vht_op_ie + 2, 0);4325} else if (bw == CHANNEL_WIDTH_80) {4326SET_VHT_OPERATION_ELE_CHL_WIDTH(vht_op_ie + 2, 1);4327SET_VHT_OPERATION_ELE_CHL_CENTER_FREQ1(vht_op_ie + 2, center_freq);4328SET_VHT_OPERATION_ELE_CHL_CENTER_FREQ2(vht_op_ie + 2, 0);4329} else {4330RTW_ERR(FUNC_ADPT_FMT" unsupported BW:%u\n", FUNC_ADPT_ARG(adapter), bw);4331rtw_warn_on(1);4332}4333}4334}4335#endif /* CONFIG_80211AC_VHT */4336#ifdef CONFIG_80211N_HT4337{4338struct ht_priv *htpriv = &adapter->mlmepriv.htpriv;4339u8 *ht_cap_ie, *ht_op_ie;4340int ht_cap_ielen, ht_op_ielen;43414342ht_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)));4343ht_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)));43444345/* update ht cap ie */4346if (ht_cap_ie && ht_cap_ielen) {4347#if UPDATE_HT_CAP4348if (bw >= CHANNEL_WIDTH_40)4349SET_HT_CAP_ELE_CHL_WIDTH(ht_cap_ie + 2, 1);4350else4351SET_HT_CAP_ELE_CHL_WIDTH(ht_cap_ie + 2, 0);43524353if (bw >= CHANNEL_WIDTH_40 && htpriv->sgi_40m)4354SET_HT_CAP_ELE_SHORT_GI40M(ht_cap_ie + 2, 1);4355else4356SET_HT_CAP_ELE_SHORT_GI40M(ht_cap_ie + 2, 0);43574358if (htpriv->sgi_20m)4359SET_HT_CAP_ELE_SHORT_GI20M(ht_cap_ie + 2, 1);4360else4361SET_HT_CAP_ELE_SHORT_GI20M(ht_cap_ie + 2, 0);4362#endif4363}43644365/* update ht op ie */4366if (ht_op_ie && ht_op_ielen) {4367SET_HT_OP_ELE_PRI_CHL(ht_op_ie + 2, ch);4368switch (offset) {4369case HAL_PRIME_CHNL_OFFSET_LOWER:4370SET_HT_OP_ELE_2ND_CHL_OFFSET(ht_op_ie + 2, SCA);4371break;4372case HAL_PRIME_CHNL_OFFSET_UPPER:4373SET_HT_OP_ELE_2ND_CHL_OFFSET(ht_op_ie + 2, SCB);4374break;4375case HAL_PRIME_CHNL_OFFSET_DONT_CARE:4376default:4377SET_HT_OP_ELE_2ND_CHL_OFFSET(ht_op_ie + 2, SCN);4378break;4379}43804381if (bw >= CHANNEL_WIDTH_40)4382SET_HT_OP_ELE_STA_CHL_WIDTH(ht_op_ie + 2, 1);4383else4384SET_HT_OP_ELE_STA_CHL_WIDTH(ht_op_ie + 2, 0);4385}4386}4387#endif /* CONFIG_80211N_HT */4388}43894390static u8 rtw_ap_update_chbw_by_ifbmp(struct dvobj_priv *dvobj, u8 ifbmp4391, u8 cur_ie_ch[], u8 cur_ie_bw[], u8 cur_ie_offset[]4392, u8 dec_ch[], u8 dec_bw[], u8 dec_offset[]4393, const char *caller)4394{4395_adapter *iface;4396struct mlme_ext_priv *mlmeext;4397WLAN_BSSID_EX *network;4398u8 ifbmp_ch_changed = 0;4399int i;44004401for (i = 0; i < dvobj->iface_nums; i++) {4402if (!(ifbmp & BIT(i)) || !dvobj->padapters)4403continue;44044405iface = dvobj->padapters[i];4406mlmeext = &(iface->mlmeextpriv);44074408if (MLME_IS_ASOC(iface)) {4409RTW_INFO(FUNC_ADPT_FMT" %u,%u,%u => %u,%u,%u%s\n", caller, ADPT_ARG(iface)4410, mlmeext->cur_channel, mlmeext->cur_bwmode, mlmeext->cur_ch_offset4411, dec_ch[i], dec_bw[i], dec_offset[i]4412, MLME_IS_OPCH_SW(iface) ? " OPCH_SW" : "");4413} else {4414RTW_INFO(FUNC_ADPT_FMT" %u,%u,%u => %u,%u,%u%s\n", caller, ADPT_ARG(iface)4415, cur_ie_ch[i], cur_ie_bw[i], cur_ie_offset[i]4416, dec_ch[i], dec_bw[i], dec_offset[i]4417, MLME_IS_OPCH_SW(iface) ? " OPCH_SW" : "");4418}4419}44204421for (i = 0; i < dvobj->iface_nums; i++) {4422if (!(ifbmp & BIT(i)) || !dvobj->padapters)4423continue;44244425iface = dvobj->padapters[i];4426mlmeext = &(iface->mlmeextpriv);4427network = &(mlmeext->mlmext_info.network);44284429/* ch setting differs from mlmeext.network IE */4430if (cur_ie_ch[i] != dec_ch[i]4431|| cur_ie_bw[i] != dec_bw[i]4432|| cur_ie_offset[i] != dec_offset[i])4433ifbmp_ch_changed |= BIT(i);44344435/* ch setting differs from existing one */4436if (MLME_IS_ASOC(iface)4437&& (mlmeext->cur_channel != dec_ch[i]4438|| mlmeext->cur_bwmode != dec_bw[i]4439|| mlmeext->cur_ch_offset != dec_offset[i])4440) {4441if (rtw_linked_check(iface) == _TRUE) {4442#ifdef CONFIG_SPCT_CH_SWITCH4443if (1)4444rtw_ap_inform_ch_switch(iface, dec_ch[i], dec_offset[i]);4445else4446#endif4447rtw_sta_flush(iface, _FALSE);4448}4449}44504451mlmeext->cur_channel = dec_ch[i];4452mlmeext->cur_bwmode = dec_bw[i];4453mlmeext->cur_ch_offset = dec_offset[i];44544455rtw_ap_update_bss_chbw(iface, network, dec_ch[i], dec_bw[i], dec_offset[i]);4456}44574458return ifbmp_ch_changed;4459}44604461static u8 rtw_ap_ch_specific_chk(_adapter *adapter, u8 ch, u8 *bw, u8 *offset, const char *caller)4462{4463struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);4464RT_CHANNEL_INFO *chset = adapter_to_chset(adapter);4465u8 ret = _SUCCESS;44664467if (rtw_chset_search_ch(chset, ch) < 0) {4468RTW_WARN("%s ch:%u doesn't fit in chplan\n", caller, ch);4469ret = _FAIL;4470goto exit;4471}44724473rtw_adjust_chbw(adapter, ch, bw, offset);44744475if (!rtw_get_offset_by_chbw(ch, *bw, offset)) {4476RTW_WARN("%s %u,%u has no valid offset\n", caller, ch, *bw);4477ret = _FAIL;4478goto exit;4479}44804481while (!rtw_chset_is_chbw_valid(chset, ch, *bw, *offset)4482|| (rtw_odm_dfs_domain_unknown(dvobj) && rtw_is_dfs_chbw(ch, *bw, *offset))4483) {4484if (*bw > CHANNEL_WIDTH_20)4485(*bw)--;4486if (*bw == CHANNEL_WIDTH_20) {4487*offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;4488break;4489}4490}44914492if (rtw_odm_dfs_domain_unknown(dvobj) && rtw_is_dfs_chbw(ch, *bw, *offset)) {4493RTW_WARN("%s DFS channel %u can't be used\n", caller, ch);4494ret = _FAIL;4495goto exit;4496}44974498exit:4499return ret;4500}45014502static bool rtw_ap_choose_chbw(_adapter *adapter, u8 sel_ch, u8 max_bw, u8 cur_ch4503, u8 *ch, u8 *bw, u8 *offset, u8 mesh_only, const char *caller)4504{4505struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);4506struct rf_ctl_t *rfctl = adapter_to_rfctl(adapter);4507bool ch_avail = _FALSE;45084509#if defined(CONFIG_DFS_MASTER)4510if (!rtw_odm_dfs_domain_unknown(dvobj)) {4511if (rfctl->radar_detected4512&& rfctl->dbg_dfs_choose_dfs_ch_first4513) {4514ch_avail = rtw_choose_shortest_waiting_ch(rfctl, sel_ch, max_bw4515, ch, bw, offset4516, RTW_CHF_2G | RTW_CHF_NON_DFS4517, cur_ch4518, rfctl->ch_sel_same_band_prefer, mesh_only);4519if (ch_avail == _TRUE) {4520RTW_INFO("%s choose 5G DFS channel for debug\n", caller);4521goto exit;4522}4523}45244525if (rfctl->radar_detected4526&& rfctl->dfs_ch_sel_d_flags4527) {4528ch_avail = rtw_choose_shortest_waiting_ch(rfctl, sel_ch, max_bw4529, ch, bw, offset4530, rfctl->dfs_ch_sel_d_flags4531, cur_ch4532, rfctl->ch_sel_same_band_prefer, mesh_only);4533if (ch_avail == _TRUE) {4534RTW_INFO("%s choose with dfs_ch_sel_d_flags:0x%02x for debug\n"4535, caller, rfctl->dfs_ch_sel_d_flags);4536goto exit;4537}4538}45394540ch_avail = rtw_choose_shortest_waiting_ch(rfctl, sel_ch, max_bw4541, ch, bw, offset4542, 04543, cur_ch4544, rfctl->ch_sel_same_band_prefer, mesh_only);4545} else4546#endif /* defined(CONFIG_DFS_MASTER) */4547{4548ch_avail = rtw_choose_shortest_waiting_ch(rfctl, sel_ch, max_bw4549, ch, bw, offset4550, RTW_CHF_DFS4551, cur_ch4552, rfctl->ch_sel_same_band_prefer, mesh_only);4553}4554#if defined(CONFIG_DFS_MASTER)4555exit:4556#endif4557if (ch_avail == _FALSE)4558RTW_WARN("%s no available channel\n", caller);45594560return ch_avail;4561}45624563u8 rtw_ap_chbw_decision(_adapter *adapter, u8 ifbmp, u8 excl_ifbmp4564, s16 req_ch, s8 req_bw, s8 req_offset4565, u8 *ch, u8 *bw, u8 *offset, u8 *chbw_allow)4566{4567struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);4568RT_CHANNEL_INFO *chset = adapter_to_chset(adapter);4569struct rf_ctl_t *rfctl = adapter_to_rfctl(adapter);4570bool ch_avail = _FALSE;4571u8 cur_ie_ch[CONFIG_IFACE_NUMBER] = {0};4572u8 cur_ie_bw[CONFIG_IFACE_NUMBER] = {0};4573u8 cur_ie_offset[CONFIG_IFACE_NUMBER] = {0};4574u8 dec_ch[CONFIG_IFACE_NUMBER] = {0};4575u8 dec_bw[CONFIG_IFACE_NUMBER] = {0};4576u8 dec_offset[CONFIG_IFACE_NUMBER] = {0};4577u8 u_ch = 0, u_bw = 0, u_offset = 0;4578struct mlme_ext_priv *mlmeext;4579WLAN_BSSID_EX *network;4580struct mi_state mstate;4581struct mi_state mstate_others;4582bool set_u_ch = _FALSE;4583u8 ifbmp_others = 0xFF & ~ifbmp & ~excl_ifbmp;4584u8 ifbmp_ch_changed = 0;4585bool ifbmp_all_mesh = 0;4586_adapter *iface;4587int i;45884589#ifdef CONFIG_RTW_MESH4590for (i = 0; i < dvobj->iface_nums; i++)4591if ((ifbmp & BIT(i)) && dvobj->padapters)4592if (!MLME_IS_MESH(dvobj->padapters[i]))4593break;4594ifbmp_all_mesh = i >= dvobj->iface_nums ? 1 : 0;4595#endif45964597RTW_INFO("%s ifbmp:0x%02x excl_ifbmp:0x%02x req:%d,%d,%d\n", __func__4598, ifbmp, excl_ifbmp, req_ch, req_bw, req_offset);4599rtw_mi_status_by_ifbmp(dvobj, ifbmp, &mstate);4600rtw_mi_status_by_ifbmp(dvobj, ifbmp_others, &mstate_others);4601RTW_INFO("%s others ld_sta_num:%u, lg_sta_num:%u, ap_num:%u, mesh_num:%u\n"4602, __func__, MSTATE_STA_LD_NUM(&mstate_others), MSTATE_STA_LG_NUM(&mstate_others)4603, MSTATE_AP_NUM(&mstate_others), MSTATE_MESH_NUM(&mstate_others));46044605for (i = 0; i < dvobj->iface_nums; i++) {4606if (!(ifbmp & BIT(i)) || !dvobj->padapters[i])4607continue;4608iface = dvobj->padapters[i];4609mlmeext = &(iface->mlmeextpriv);4610network = &(mlmeext->mlmext_info.network);46114612/* get current IE channel settings */4613rtw_ies_get_chbw(BSS_EX_TLV_IES(network), BSS_EX_TLV_IES_LEN(network)4614, &cur_ie_ch[i], &cur_ie_bw[i], &cur_ie_offset[i], 1, 1);46154616/* prepare temporary channel setting decision */4617if (req_ch == 0) {4618/* request comes from upper layer, use cur_ie values */4619dec_ch[i] = cur_ie_ch[i];4620dec_bw[i] = cur_ie_bw[i];4621dec_offset[i] = cur_ie_offset[i];4622} else {4623/* use chbw of cur_ie updated with specifying req as temporary decision */4624dec_ch[i] = (req_ch <= REQ_CH_NONE) ? cur_ie_ch[i] : req_ch;4625if (req_bw <= REQ_BW_NONE) {4626if (req_bw == REQ_BW_ORI)4627dec_bw[i] = iface->mlmepriv.ori_bw;4628else4629dec_bw[i] = cur_ie_bw[i];4630} else4631dec_bw[i] = req_bw;4632dec_offset[i] = (req_offset <= REQ_OFFSET_NONE) ? cur_ie_offset[i] : req_offset;4633}4634}46354636if (MSTATE_STA_LD_NUM(&mstate_others) || MSTATE_STA_LG_NUM(&mstate_others)4637|| MSTATE_AP_NUM(&mstate_others) || MSTATE_MESH_NUM(&mstate_others)4638) {4639/* has linked/linking STA or has AP/Mesh mode */4640rtw_warn_on(!rtw_mi_get_ch_setting_union_by_ifbmp(dvobj, ifbmp_others, &u_ch, &u_bw, &u_offset));4641RTW_INFO("%s others union:%u,%u,%u\n", __func__, u_ch, u_bw, u_offset);4642}46434644#ifdef CONFIG_MCC_MODE4645if (MCC_EN(adapter) && req_ch == 0) {4646if (rtw_hal_check_mcc_status(adapter, MCC_STATUS_DOING_MCC)) {4647u8 if_id = adapter->iface_id;46484649mlmeext = &(adapter->mlmeextpriv);46504651/* check channel settings are the same */4652if (cur_ie_ch[if_id] == mlmeext->cur_channel4653&& cur_ie_bw[if_id] == mlmeext->cur_bwmode4654&& cur_ie_offset[if_id] == mlmeext->cur_ch_offset) {46554656RTW_INFO(FUNC_ADPT_FMT"req ch settings are the same as current ch setting, go to exit\n"4657, FUNC_ADPT_ARG(adapter));46584659*chbw_allow = _FALSE;4660goto exit;4661} else {4662RTW_INFO(FUNC_ADPT_FMT"request channel settings are not the same as current channel setting(%d,%d,%d,%d,%d,%d), restart MCC\n"4663, FUNC_ADPT_ARG(adapter)4664, cur_ie_ch[if_id], cur_ie_bw[if_id], cur_ie_offset[if_id]4665, mlmeext->cur_channel, mlmeext->cur_bwmode, mlmeext->cur_ch_offset);46664667rtw_hal_set_mcc_setting_disconnect(adapter);4668}4669}4670}4671#endif /* CONFIG_MCC_MODE */46724673if (MSTATE_STA_LG_NUM(&mstate_others) && !MSTATE_STA_LD_NUM(&mstate_others)) {4674/* has linking STA but no linked STA */46754676for (i = 0; i < dvobj->iface_nums; i++) {4677if (!(ifbmp & BIT(i)) || !dvobj->padapters[i])4678continue;4679iface = dvobj->padapters[i];46804681rtw_adjust_chbw(iface, dec_ch[i], &dec_bw[i], &dec_offset[i]);4682#ifdef CONFIG_RTW_MESH4683if (MLME_IS_MESH(iface))4684rtw_mesh_adjust_chbw(dec_ch[i], &dec_bw[i], &dec_offset[i]);4685#endif46864687if (rtw_is_chbw_grouped(u_ch, u_bw, u_offset, dec_ch[i], dec_bw[i], dec_offset[i])) {4688rtw_chset_sync_chbw(chset4689, &dec_ch[i], &dec_bw[i], &dec_offset[i]4690, &u_ch, &u_bw, &u_offset);4691set_u_ch = _TRUE;46924693/* channel bw offset can be allowed, not need MCC */4694*chbw_allow = _TRUE;4695} else {4696#ifdef CONFIG_MCC_MODE4697if (MCC_EN(iface)) {4698mlmeext = &(iface->mlmeextpriv);4699mlmeext->cur_channel = *ch = dec_ch[i];4700mlmeext->cur_bwmode = *bw = dec_bw[i];4701mlmeext->cur_ch_offset = *offset = dec_offset[i];47024703/* channel bw offset can not be allowed, need MCC */4704*chbw_allow = _FALSE;4705RTW_INFO(FUNC_ADPT_FMT" enable mcc: %u,%u,%u\n", FUNC_ADPT_ARG(iface)4706, *ch, *bw, *offset);4707goto exit;4708}4709#endif /* CONFIG_MCC_MODE */47104711/* set this for possible ch change when join down*/4712set_fwstate(&iface->mlmepriv, WIFI_OP_CH_SWITCHING);4713}4714}47154716} else if (MSTATE_STA_LD_NUM(&mstate_others)4717|| MSTATE_AP_NUM(&mstate_others) || MSTATE_MESH_NUM(&mstate_others)4718) {4719/* has linked STA mode or AP/Mesh mode */47204721for (i = 0; i < dvobj->iface_nums; i++) {4722if (!(ifbmp & BIT(i)) || !dvobj->padapters[i])4723continue;4724iface = dvobj->padapters[i];47254726rtw_adjust_chbw(iface, u_ch, &dec_bw[i], &dec_offset[i]);4727#ifdef CONFIG_RTW_MESH4728if (MLME_IS_MESH(iface))4729rtw_mesh_adjust_chbw(u_ch, &dec_bw[i], &dec_offset[i]);4730#endif47314732#ifdef CONFIG_MCC_MODE4733if (MCC_EN(iface)) {4734if (!rtw_is_chbw_grouped(u_ch, u_bw, u_offset, dec_ch[i], dec_bw[i], dec_offset[i])) {4735mlmeext = &(iface->mlmeextpriv);4736mlmeext->cur_channel = *ch = dec_ch[i] = cur_ie_ch[i];4737mlmeext->cur_bwmode = *bw = dec_bw[i] = cur_ie_bw[i];4738mlmeext->cur_ch_offset = *offset = dec_offset[i] = cur_ie_offset[i];4739/* channel bw offset can not be allowed, need MCC */4740*chbw_allow = _FALSE;4741RTW_INFO(FUNC_ADPT_FMT" enable mcc: %u,%u,%u\n", FUNC_ADPT_ARG(iface)4742, *ch, *bw, *offset);4743goto exit;4744} else4745/* channel bw offset can be allowed, not need MCC */4746*chbw_allow = _TRUE;4747}4748#endif /* CONFIG_MCC_MODE */47494750if (req_ch == 0 && dec_bw[i] > u_bw4751&& rtw_is_dfs_chbw(u_ch, u_bw, u_offset)4752) {4753/* request comes from upper layer, prevent from additional channel waiting */4754dec_bw[i] = u_bw;4755if (dec_bw[i] == CHANNEL_WIDTH_20)4756dec_offset[i] = HAL_PRIME_CHNL_OFFSET_DONT_CARE;4757}47584759/* follow */4760rtw_chset_sync_chbw(chset4761, &dec_ch[i], &dec_bw[i], &dec_offset[i]4762, &u_ch, &u_bw, &u_offset);4763}47644765set_u_ch = _TRUE;47664767} else {4768/* autonomous decision */4769u8 ori_ch = 0;4770u8 max_bw;47714772/* autonomous decision, not need MCC */4773*chbw_allow = _TRUE;47744775if (req_ch <= REQ_CH_NONE) /* channel is not specified */4776goto choose_chbw;47774778/* get tmp dec union of ifbmp */4779for (i = 0; i < dvobj->iface_nums; i++) {4780if (!(ifbmp & BIT(i)) || !dvobj->padapters[i])4781continue;4782if (u_ch == 0) {4783u_ch = dec_ch[i];4784u_bw = dec_bw[i];4785u_offset = dec_offset[i];4786rtw_adjust_chbw(adapter, u_ch, &u_bw, &u_offset);4787rtw_get_offset_by_chbw(u_ch, u_bw, &u_offset);4788} else {4789u8 tmp_ch = dec_ch[i];4790u8 tmp_bw = dec_bw[i];4791u8 tmp_offset = dec_offset[i];47924793rtw_adjust_chbw(adapter, tmp_ch, &tmp_bw, &tmp_offset);4794rtw_get_offset_by_chbw(tmp_ch, tmp_bw, &tmp_offset);47954796rtw_warn_on(!rtw_is_chbw_grouped(u_ch, u_bw, u_offset, tmp_ch, tmp_bw, tmp_offset));4797rtw_sync_chbw(&tmp_ch, &tmp_bw, &tmp_offset, &u_ch, &u_bw, &u_offset);4798}4799}48004801#ifdef CONFIG_RTW_MESH4802/* if ifbmp are all mesh, apply bw restriction */4803if (ifbmp_all_mesh)4804rtw_mesh_adjust_chbw(u_ch, &u_bw, &u_offset);4805#endif48064807RTW_INFO("%s ifbmp:0x%02x tmp union:%u,%u,%u\n", __func__, ifbmp, u_ch, u_bw, u_offset);48084809/* check if tmp dec union is usable */4810if (rtw_ap_ch_specific_chk(adapter, u_ch, &u_bw, &u_offset, __func__) == _FAIL) {4811/* channel can't be used */4812if (req_ch > 0) {4813/* specific channel and not from IE => don't change channel setting */4814goto exit;4815}4816goto choose_chbw;4817} else if (rtw_chset_is_chbw_non_ocp(chset, u_ch, u_bw, u_offset)) {4818RTW_WARN("%s DFS channel %u,%u under non ocp\n", __func__, u_ch, u_bw);4819if (req_ch > 0 && req_bw > REQ_BW_NONE) {4820/* change_chbw with specific channel and specific bw, goto update_bss_chbw directly */4821goto update_bss_chbw;4822}4823} else4824goto update_bss_chbw;48254826choose_chbw:4827req_ch = req_ch > 0 ? req_ch : 0;4828max_bw = req_bw > REQ_BW_NONE ? req_bw : CHANNEL_WIDTH_20;4829for (i = 0; i < dvobj->iface_nums; i++) {4830if (!(ifbmp & BIT(i)) || !dvobj->padapters[i])4831continue;4832iface = dvobj->padapters[i];4833mlmeext = &(iface->mlmeextpriv);48344835if (req_bw <= REQ_BW_NONE) {4836if (req_bw == REQ_BW_ORI) {4837if (max_bw < iface->mlmepriv.ori_bw)4838max_bw = iface->mlmepriv.ori_bw;4839} else {4840if (max_bw < cur_ie_bw[i])4841max_bw = cur_ie_bw[i];4842}4843}48444845if (MSTATE_AP_NUM(&mstate) || MSTATE_MESH_NUM(&mstate)) {4846if (ori_ch == 0)4847ori_ch = mlmeext->cur_channel;4848else if (ori_ch != mlmeext->cur_channel)4849rtw_warn_on(1);4850} else {4851if (ori_ch == 0)4852ori_ch = cur_ie_ch[i];4853else if (ori_ch != cur_ie_ch[i])4854rtw_warn_on(1);4855}4856}48574858ch_avail = rtw_ap_choose_chbw(adapter, req_ch, max_bw4859, ori_ch, &u_ch, &u_bw, &u_offset, ifbmp_all_mesh, __func__);4860if (ch_avail == _FALSE)4861goto exit;48624863update_bss_chbw:4864for (i = 0; i < dvobj->iface_nums; i++) {4865if (!(ifbmp & BIT(i)) || !dvobj->padapters[i])4866continue;4867iface = dvobj->padapters[i];48684869dec_ch[i] = u_ch;4870if (dec_bw[i] > u_bw)4871dec_bw[i] = u_bw;4872if (dec_bw[i] == CHANNEL_WIDTH_20)4873dec_offset[i] = HAL_PRIME_CHNL_OFFSET_DONT_CARE;4874else4875dec_offset[i] = u_offset;48764877#ifdef CONFIG_RTW_MESH4878if (MLME_IS_MESH(iface))4879rtw_mesh_adjust_chbw(dec_ch[i], &dec_bw[i], &dec_offset[i]);4880#endif4881}48824883set_u_ch = _TRUE;4884}48854886ifbmp_ch_changed = rtw_ap_update_chbw_by_ifbmp(dvobj, ifbmp4887, cur_ie_ch, cur_ie_bw, cur_ie_offset4888, dec_ch, dec_bw, dec_offset4889, __func__);48904891if (u_ch != 0)4892RTW_INFO("%s union:%u,%u,%u\n", __func__, u_ch, u_bw, u_offset);48934894if (rtw_mi_check_fwstate(adapter, _FW_UNDER_SURVEY)) {4895/* scanning, leave ch setting to scan state machine */4896set_u_ch = _FALSE;4897}48984899if (set_u_ch == _TRUE) {4900*ch = u_ch;4901*bw = u_bw;4902*offset = u_offset;4903}4904exit:4905return ifbmp_ch_changed;4906}49074908u8 rtw_ap_sta_states_check(_adapter *adapter)4909{4910struct sta_info *psta;4911struct sta_priv *pstapriv = &adapter->stapriv;4912_list *plist, *phead;4913_irqL irqL;4914u8 rst = _FALSE;49154916if (!MLME_IS_AP(adapter) && !MLME_IS_MESH(adapter))4917return _FALSE;49184919if (pstapriv->auth_list_cnt !=0)4920return _TRUE;49214922_enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);4923phead = &pstapriv->asoc_list;4924plist = get_next(phead);4925while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {49264927psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);4928plist = get_next(plist);49294930if (!(psta->state & _FW_LINKED)) {4931RTW_INFO(ADPT_FMT"- SoftAP/Mesh - sta under linking, its state = 0x%x\n", ADPT_ARG(adapter), psta->state);4932rst = _TRUE;4933break;4934} else if (psta->state & WIFI_UNDER_KEY_HANDSHAKE) {4935RTW_INFO(ADPT_FMT"- SoftAP/Mesh - sta under key handshaking, its state = 0x%x\n", ADPT_ARG(adapter), psta->state);4936rst = _TRUE;4937break;4938}4939}4940_exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);4941return rst;4942}49434944/*#define DBG_SWTIMER_BASED_TXBCN*/4945#ifdef CONFIG_SWTIMER_BASED_TXBCN4946void tx_beacon_handlder(struct dvobj_priv *pdvobj)4947{4948#define BEACON_EARLY_TIME 20 /* unit:TU*/4949_irqL irqL;4950_list *plist, *phead;4951u32 timestamp[2];4952u32 bcn_interval_us; /* unit : usec */4953u64 time;4954u32 cur_tick, time_offset; /* unit : usec */4955u32 inter_bcn_space_us; /* unit : usec */4956u32 txbcn_timer_ms; /* unit : ms */4957int nr_vap, idx, bcn_idx;4958int i;4959u8 val8, late = 0;4960_adapter *padapter = NULL;49614962i = 0;49634964/* get first ap mode interface */4965_enter_critical_bh(&pdvobj->ap_if_q.lock, &irqL);4966if (rtw_is_list_empty(&pdvobj->ap_if_q.queue) || (pdvobj->nr_ap_if == 0)) {4967RTW_INFO("[%s] ERROR: ap_if_q is empty!or nr_ap = %d\n", __func__, pdvobj->nr_ap_if);4968_exit_critical_bh(&pdvobj->ap_if_q.lock, &irqL);4969return;4970} else4971padapter = LIST_CONTAINOR(get_next(&(pdvobj->ap_if_q.queue)), struct _ADAPTER, list);4972_exit_critical_bh(&pdvobj->ap_if_q.lock, &irqL);49734974if (NULL == padapter) {4975RTW_INFO("[%s] ERROR: no any ap interface!\n", __func__);4976return;4977}497849794980bcn_interval_us = DEFAULT_BCN_INTERVAL * NET80211_TU_TO_US;4981if (0 == bcn_interval_us) {4982RTW_INFO("[%s] ERROR: beacon interval = 0\n", __func__);4983return;4984}49854986/* read TSF */4987timestamp[1] = rtw_read32(padapter, 0x560 + 4);4988timestamp[0] = rtw_read32(padapter, 0x560);4989while (timestamp[1]) {4990time = (0xFFFFFFFF % bcn_interval_us + 1) * timestamp[1] + timestamp[0];4991timestamp[0] = (u32)time;4992timestamp[1] = (u32)(time >> 32);4993}4994cur_tick = timestamp[0] % bcn_interval_us;499549964997_enter_critical_bh(&pdvobj->ap_if_q.lock, &irqL);49984999nr_vap = (pdvobj->nr_ap_if - 1);5000if (nr_vap > 0) {5001inter_bcn_space_us = pdvobj->inter_bcn_space * NET80211_TU_TO_US; /* beacon_interval / (nr_vap+1); */5002idx = cur_tick / inter_bcn_space_us;5003if (idx < nr_vap) /* if (idx < (nr_vap+1))*/5004bcn_idx = idx + 1; /* bcn_idx = (idx + 1) % (nr_vap+1);*/5005else5006bcn_idx = 0;50075008/* to get padapter based on bcn_idx */5009padapter = NULL;5010phead = get_list_head(&pdvobj->ap_if_q);5011plist = get_next(phead);5012while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {5013padapter = LIST_CONTAINOR(plist, struct _ADAPTER, list);50145015plist = get_next(plist);50165017if (i == bcn_idx)5018break;50195020i++;5021}5022if ((NULL == padapter) || (i > pdvobj->nr_ap_if)) {5023RTW_INFO("[%s] ERROR: nr_ap_if = %d, padapter=%p, bcn_idx=%d, index=%d\n",5024__func__, pdvobj->nr_ap_if, padapter, bcn_idx, i);5025_exit_critical_bh(&pdvobj->ap_if_q.lock, &irqL);5026return;5027}5028#ifdef DBG_SWTIMER_BASED_TXBCN5029RTW_INFO("BCN_IDX=%d, cur_tick=%d, padapter=%p\n", bcn_idx, cur_tick, padapter);5030#endif5031if (((idx + 2 == nr_vap + 1) && (idx < nr_vap + 1)) || (0 == bcn_idx)) {5032time_offset = bcn_interval_us - cur_tick - BEACON_EARLY_TIME * NET80211_TU_TO_US;5033if ((s32)time_offset < 0)5034time_offset += inter_bcn_space_us;50355036} else {5037time_offset = (idx + 2) * inter_bcn_space_us - cur_tick - BEACON_EARLY_TIME * NET80211_TU_TO_US;5038if (time_offset > (inter_bcn_space_us + (inter_bcn_space_us >> 1))) {5039time_offset -= inter_bcn_space_us;5040late = 1;5041}5042}5043} else5044/*#endif*/ { /* MBSSID */5045time_offset = 2 * bcn_interval_us - cur_tick - BEACON_EARLY_TIME * NET80211_TU_TO_US;5046if (time_offset > (bcn_interval_us + (bcn_interval_us >> 1))) {5047time_offset -= bcn_interval_us;5048late = 1;5049}5050}5051_exit_critical_bh(&pdvobj->ap_if_q.lock, &irqL);50525053#ifdef DBG_SWTIMER_BASED_TXBCN5054RTW_INFO("set sw bcn timer %d us\n", time_offset);5055#endif5056txbcn_timer_ms = time_offset / NET80211_TU_TO_US;5057_set_timer(&pdvobj->txbcn_timer, txbcn_timer_ms);50585059if (padapter) {5060#ifdef CONFIG_BCN_RECOVERY5061rtw_ap_bcn_recovery(padapter);5062#endif /*CONFIG_BCN_RECOVERY*/50635064#ifdef CONFIG_BCN_XMIT_PROTECT5065rtw_ap_bcn_queue_empty_check(padapter, txbcn_timer_ms);5066#endif /*CONFIG_BCN_XMIT_PROTECT*/50675068#ifdef DBG_SWTIMER_BASED_TXBCN5069RTW_INFO("padapter=%p, PORT=%d\n", padapter, padapter->hw_port);5070#endif5071/* bypass TX BCN queue if op ch is switching/waiting */5072if (!check_fwstate(&padapter->mlmepriv, WIFI_OP_CH_SWITCHING)5073&& !IS_CH_WAITING(adapter_to_rfctl(padapter))5074) {5075/*update_beacon(padapter, _TIM_IE_, NULL, _FALSE, 0);*/5076/*issue_beacon(padapter, 0);*/5077send_beacon(padapter);5078}5079}50805081#if 05082/* handle any buffered BC/MC frames*/5083/* Don't dynamically change DIS_ATIM due to HW will auto send ACQ after HIQ empty.*/5084val8 = *((unsigned char *)priv->beaconbuf + priv->timoffset + 4);5085if (val8 & 0x01) {5086process_mcast_dzqueue(priv);5087priv->pkt_in_dtimQ = 0;5088}5089#endif50905091}50925093void tx_beacon_timer_handlder(void *ctx)5094{5095struct dvobj_priv *pdvobj = (struct dvobj_priv *)ctx;5096_adapter *padapter = pdvobj->padapters[0];50975098if (padapter)5099set_tx_beacon_cmd(padapter, 0);5100}5101#endif51025103void rtw_ap_parse_sta_capability(_adapter *adapter, struct sta_info *sta, u8 *cap)5104{5105sta->capability = RTW_GET_LE16(cap);5106if (sta->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)5107sta->flags |= WLAN_STA_SHORT_PREAMBLE;5108else5109sta->flags &= ~WLAN_STA_SHORT_PREAMBLE;5110}51115112u16 rtw_ap_parse_sta_supported_rates(_adapter *adapter, struct sta_info *sta, u8 *tlv_ies, u16 tlv_ies_len)5113{5114u8 rate_set[12];5115u8 rate_num;5116int i;5117u16 status = _STATS_SUCCESSFUL_;51185119rtw_ies_get_supported_rate(tlv_ies, tlv_ies_len, rate_set, &rate_num);5120if (rate_num == 0) {5121RTW_INFO(FUNC_ADPT_FMT" sta "MAC_FMT" with no supported rate\n"5122, FUNC_ADPT_ARG(adapter), MAC_ARG(sta->cmn.mac_addr));5123status = _STATS_FAILURE_;5124goto exit;5125}51265127_rtw_memcpy(sta->bssrateset, rate_set, rate_num);5128sta->bssratelen = rate_num;51295130if (MLME_IS_AP(adapter)) {5131/* this function force only CCK rates to be bassic rate... */5132UpdateBrateTblForSoftAP(sta->bssrateset, sta->bssratelen);5133}51345135/* if (hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G) */ /* ? */5136sta->flags |= WLAN_STA_NONERP;5137for (i = 0; i < sta->bssratelen; i++) {5138if ((sta->bssrateset[i] & 0x7f) > 22) {5139sta->flags &= ~WLAN_STA_NONERP;5140break;5141}5142}51435144exit:5145return status;5146}51475148u16 rtw_ap_parse_sta_security_ie(_adapter *adapter, struct sta_info *sta, struct rtw_ieee802_11_elems *elems)5149{5150struct security_priv *sec = &adapter->securitypriv;5151u8 *wpa_ie;5152int wpa_ie_len;5153int group_cipher = 0, pairwise_cipher = 0;5154u32 akm = 0;5155u8 mfp_opt = MFP_NO;5156u16 status = _STATS_SUCCESSFUL_;51575158sta->dot8021xalg = 0;5159sta->wpa_psk = 0;5160sta->wpa_group_cipher = 0;5161sta->wpa2_group_cipher = 0;5162sta->wpa_pairwise_cipher = 0;5163sta->wpa2_pairwise_cipher = 0;5164_rtw_memset(sta->wpa_ie, 0, sizeof(sta->wpa_ie));51655166if ((sec->wpa_psk & BIT(1)) && elems->rsn_ie) {5167wpa_ie = elems->rsn_ie;5168wpa_ie_len = elems->rsn_ie_len;51695170if (rtw_parse_wpa2_ie(wpa_ie - 2, wpa_ie_len + 2, &group_cipher, &pairwise_cipher, &akm, &mfp_opt) == _SUCCESS) {5171sta->dot8021xalg = 1;/* psk, todo:802.1x */5172sta->wpa_psk |= BIT(1);51735174sta->wpa2_group_cipher = group_cipher & sec->wpa2_group_cipher;5175sta->wpa2_pairwise_cipher = pairwise_cipher & sec->wpa2_pairwise_cipher;51765177sta->akm_suite_type = akm;5178if ((CHECK_BIT(WLAN_AKM_TYPE_SAE, akm)) && (MFP_NO == mfp_opt))5179status = WLAN_STATUS_ROBUST_MGMT_FRAME_POLICY_VIOLATION;51805181if (!sta->wpa2_group_cipher)5182status = WLAN_STATUS_GROUP_CIPHER_NOT_VALID;51835184if (!sta->wpa2_pairwise_cipher)5185status = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID;5186} else5187status = WLAN_STATUS_INVALID_IE;51885189}5190else if ((sec->wpa_psk & BIT(0)) && elems->wpa_ie) {5191wpa_ie = elems->wpa_ie;5192wpa_ie_len = elems->wpa_ie_len;51935194if (rtw_parse_wpa_ie(wpa_ie - 2, wpa_ie_len + 2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) {5195sta->dot8021xalg = 1;/* psk, todo:802.1x */5196sta->wpa_psk |= BIT(0);51975198sta->wpa_group_cipher = group_cipher & sec->wpa_group_cipher;5199sta->wpa_pairwise_cipher = pairwise_cipher & sec->wpa_pairwise_cipher;52005201if (!sta->wpa_group_cipher)5202status = WLAN_STATUS_GROUP_CIPHER_NOT_VALID;52035204if (!sta->wpa_pairwise_cipher)5205status = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID;5206} else5207status = WLAN_STATUS_INVALID_IE;52085209} else {5210wpa_ie = NULL;5211wpa_ie_len = 0;5212}52135214#ifdef CONFIG_RTW_MESH5215if (MLME_IS_MESH(adapter)) {5216/* MFP is mandatory for secure mesh */5217if (adapter->mesh_info.mesh_auth_id)5218sta->flags |= WLAN_STA_MFP;5219} else5220#endif5221if ((sec->mfp_opt == MFP_REQUIRED && mfp_opt == MFP_NO) || mfp_opt == MFP_INVALID)5222status = WLAN_STATUS_ROBUST_MGMT_FRAME_POLICY_VIOLATION;5223else if (sec->mfp_opt >= MFP_OPTIONAL && mfp_opt >= MFP_OPTIONAL)5224sta->flags |= WLAN_STA_MFP;52255226if ((sec->auth_type == NL80211_AUTHTYPE_SAE) &&5227(CHECK_BIT(WLAN_AKM_TYPE_SAE, sta->akm_suite_type)) &&5228(WLAN_AUTH_OPEN == sta->authalg)) {5229/* WPA3-SAE, PMK caching */5230if (rtw_cached_pmkid(adapter, sta->cmn.mac_addr) == -1) {5231RTW_INFO("SAE: No PMKSA cache entry found\n");5232status = WLAN_STATUS_INVALID_PMKID;5233} else {5234RTW_INFO("SAE: PMKSA cache entry found\n");5235}5236}52375238if (status != _STATS_SUCCESSFUL_)5239goto exit;52405241if (!MLME_IS_AP(adapter))5242goto exit;52435244sta->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS);5245/* if (hapd->conf->wps_state && wpa_ie == NULL) { */ /* todo: to check ap if supporting WPS */5246if (wpa_ie == NULL) {5247if (elems->wps_ie) {5248RTW_INFO("STA included WPS IE in "5249"(Re)Association Request - assume WPS is "5250"used\n");5251sta->flags |= WLAN_STA_WPS;5252/* wpabuf_free(sta->wps_ie); */5253/* sta->wps_ie = wpabuf_alloc_copy(elems.wps_ie + 4, */5254/* elems.wps_ie_len - 4); */5255} else {5256RTW_INFO("STA did not include WPA/RSN IE "5257"in (Re)Association Request - possible WPS "5258"use\n");5259sta->flags |= WLAN_STA_MAYBE_WPS;5260}52615262/* AP support WPA/RSN, and sta is going to do WPS, but AP is not ready */5263/* that the selected registrar of AP is _FLASE */5264if ((sec->wpa_psk > 0)5265&& (sta->flags & (WLAN_STA_WPS | WLAN_STA_MAYBE_WPS))5266) {5267struct mlme_priv *mlme = &adapter->mlmepriv;52685269if (mlme->wps_beacon_ie) {5270u8 selected_registrar = 0;52715272rtw_get_wps_attr_content(mlme->wps_beacon_ie, mlme->wps_beacon_ie_len, WPS_ATTR_SELECTED_REGISTRAR, &selected_registrar, NULL);52735274if (!selected_registrar) {5275RTW_INFO("selected_registrar is _FALSE , or AP is not ready to do WPS\n");5276status = _STATS_UNABLE_HANDLE_STA_;5277goto exit;5278}5279}5280}52815282} else {5283int copy_len;52845285if (sec->wpa_psk == 0) {5286RTW_INFO("STA " MAC_FMT5287": WPA/RSN IE in association request, but AP don't support WPA/RSN\n",5288MAC_ARG(sta->cmn.mac_addr));5289status = WLAN_STATUS_INVALID_IE;5290goto exit;5291}52925293if (elems->wps_ie) {5294RTW_INFO("STA included WPS IE in "5295"(Re)Association Request - WPS is "5296"used\n");5297sta->flags |= WLAN_STA_WPS;5298copy_len = 0;5299} else5300copy_len = ((wpa_ie_len + 2) > sizeof(sta->wpa_ie)) ? (sizeof(sta->wpa_ie)) : (wpa_ie_len + 2);53015302if (copy_len > 0)5303_rtw_memcpy(sta->wpa_ie, wpa_ie - 2, copy_len);5304}53055306exit:5307return status;5308}53095310void rtw_ap_parse_sta_wmm_ie(_adapter *adapter, struct sta_info *sta, u8 *tlv_ies, u16 tlv_ies_len)5311{5312struct mlme_priv *mlme = &adapter->mlmepriv;5313unsigned char WMM_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01};5314u8 *p;53155316sta->flags &= ~WLAN_STA_WME;5317sta->qos_option = 0;5318sta->qos_info = 0;5319sta->has_legacy_ac = _TRUE;5320sta->uapsd_vo = 0;5321sta->uapsd_vi = 0;5322sta->uapsd_be = 0;5323sta->uapsd_bk = 0;53245325if (!mlme->qospriv.qos_option)5326goto exit;53275328#ifdef CONFIG_RTW_MESH5329if (MLME_IS_MESH(adapter)) {5330/* QoS is mandatory in mesh */5331sta->flags |= WLAN_STA_WME;5332}5333#endif53345335p = rtw_get_ie_ex(tlv_ies, tlv_ies_len, WLAN_EID_VENDOR_SPECIFIC, WMM_IE, 6, NULL, NULL);5336if (!p)5337goto exit;53385339sta->flags |= WLAN_STA_WME;5340sta->qos_option = 1;5341sta->qos_info = *(p + 8);5342sta->max_sp_len = (sta->qos_info >> 5) & 0x3;53435344if ((sta->qos_info & 0xf) != 0xf)5345sta->has_legacy_ac = _TRUE;5346else5347sta->has_legacy_ac = _FALSE;53485349if (sta->qos_info & 0xf) {5350if (sta->qos_info & BIT(0))5351sta->uapsd_vo = BIT(0) | BIT(1);5352else5353sta->uapsd_vo = 0;53545355if (sta->qos_info & BIT(1))5356sta->uapsd_vi = BIT(0) | BIT(1);5357else5358sta->uapsd_vi = 0;53595360if (sta->qos_info & BIT(2))5361sta->uapsd_bk = BIT(0) | BIT(1);5362else5363sta->uapsd_bk = 0;53645365if (sta->qos_info & BIT(3))5366sta->uapsd_be = BIT(0) | BIT(1);5367else5368sta->uapsd_be = 0;5369}53705371exit:5372return;5373}53745375void rtw_ap_parse_sta_ht_ie(_adapter *adapter, struct sta_info *sta, struct rtw_ieee802_11_elems *elems)5376{5377struct mlme_priv *mlme = &adapter->mlmepriv;53785379sta->flags &= ~WLAN_STA_HT;53805381#ifdef CONFIG_80211N_HT5382if (mlme->htpriv.ht_option == _FALSE)5383goto exit;53845385/* save HT capabilities in the sta object */5386_rtw_memset(&sta->htpriv.ht_cap, 0, sizeof(struct rtw_ieee80211_ht_cap));5387if (elems->ht_capabilities && elems->ht_capabilities_len >= sizeof(struct rtw_ieee80211_ht_cap)) {5388sta->flags |= WLAN_STA_HT;5389sta->flags |= WLAN_STA_WME;5390_rtw_memcpy(&sta->htpriv.ht_cap, elems->ht_capabilities, sizeof(struct rtw_ieee80211_ht_cap));53915392if (elems->ht_operation && elems->ht_operation_len == HT_OP_IE_LEN) {5393_rtw_memcpy(sta->htpriv.ht_op, elems->ht_operation, HT_OP_IE_LEN);5394sta->htpriv.op_present = 1;5395}5396}5397exit:5398#endif53995400return;5401}54025403void rtw_ap_parse_sta_vht_ie(_adapter *adapter, struct sta_info *sta, struct rtw_ieee802_11_elems *elems)5404{5405struct mlme_priv *mlme = &adapter->mlmepriv;54065407sta->flags &= ~WLAN_STA_VHT;54085409#ifdef CONFIG_80211AC_VHT5410if (mlme->vhtpriv.vht_option == _FALSE)5411goto exit;54125413_rtw_memset(&sta->vhtpriv, 0, sizeof(struct vht_priv));5414if (elems->vht_capabilities && elems->vht_capabilities_len == VHT_CAP_IE_LEN) {5415sta->flags |= WLAN_STA_VHT;5416_rtw_memcpy(sta->vhtpriv.vht_cap, elems->vht_capabilities, VHT_CAP_IE_LEN);54175418if (elems->vht_operation && elems->vht_operation_len== VHT_OP_IE_LEN) {5419_rtw_memcpy(sta->vhtpriv.vht_op, elems->vht_operation, VHT_OP_IE_LEN);5420sta->vhtpriv.op_present = 1;5421}54225423if (elems->vht_op_mode_notify && elems->vht_op_mode_notify_len == 1) {5424_rtw_memcpy(&sta->vhtpriv.vht_op_mode_notify, elems->vht_op_mode_notify, 1);5425sta->vhtpriv.notify_present = 1;5426}5427}5428exit:5429#endif54305431return;5432}5433#endif /* CONFIG_AP_MODE */5434543554365437