| /* |
| * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved. |
| * |
| * Previously licensed under the ISC license by Qualcomm Atheros, Inc. |
| * |
| * |
| * Permission to use, copy, modify, and/or distribute this software for |
| * any purpose with or without fee is hereby granted, provided that the |
| * above copyright notice and this permission notice appear in all |
| * copies. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL |
| * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED |
| * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE |
| * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL |
| * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR |
| * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER |
| * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR |
| * PERFORMANCE OF THIS SOFTWARE. |
| */ |
| |
| /* |
| * This file was originally distributed by Qualcomm Atheros, Inc. |
| * under proprietary terms before Copyright ownership was assigned |
| * to the Linux Foundation. |
| */ |
| |
| /* |
| * This file schBeaconProcess.cc contains beacon processing related |
| * functions |
| * |
| * Author: Sandesh Goel |
| * Date: 02/25/02 |
| * History:- |
| * Date Modified by Modification Information |
| * -------------------------------------------------------------------- |
| * |
| */ |
| |
| #include "palTypes.h" |
| #include "wni_cfg.h" |
| #include "cfgApi.h" |
| #include "pmmApi.h" |
| #include "limApi.h" |
| #include "utilsApi.h" |
| #include "schDebug.h" |
| #include "schApi.h" |
| |
| #include "wma.h" |
| |
| #include "limUtils.h" |
| #include "limSendMessages.h" |
| #include "limStaHashApi.h" |
| |
| #if defined WLAN_FEATURE_VOWIFI |
| #include "rrmApi.h" |
| #endif |
| |
| #ifdef FEATURE_WLAN_DIAG_SUPPORT |
| #include "vos_diag_core_log.h" |
| #endif //FEATURE_WLAN_DIAG_SUPPORT |
| |
| /** |
| * Number of bytes of variation in beacon length from the last beacon |
| * to trigger reprogramming of rx delay register |
| */ |
| #define SCH_BEACON_LEN_DELTA 3 |
| |
| // calculate 2^cw - 1 |
| #define CW_GET(cw) (((cw) == 0) ? 1 : ((1 << (cw)) - 1)) |
| |
| static void |
| ap_beacon_process( |
| tpAniSirGlobal pMac, |
| tANI_U8* pRxPacketInfo, |
| tpSchBeaconStruct pBcnStruct, |
| tpUpdateBeaconParams pBeaconParams, |
| tpPESession psessionEntry) |
| { |
| tpSirMacMgmtHdr pMh = WDA_GET_RX_MAC_HEADER(pRxPacketInfo); |
| tANI_U32 phyMode; |
| tSirRFBand rfBand = SIR_BAND_UNKNOWN; |
| //Get RF band from psessionEntry |
| rfBand = psessionEntry->limRFBand; |
| |
| limGetPhyMode(pMac, &phyMode, psessionEntry); |
| |
| if(SIR_BAND_5_GHZ == rfBand) |
| { |
| if (psessionEntry->htCapability) |
| { |
| if (pBcnStruct->channelNumber == psessionEntry->currentOperChannel) |
| { |
| //11a (non HT) AP overlaps or |
| //HT AP with HT op mode as mixed overlaps. |
| //HT AP with HT op mode as overlap legacy overlaps. |
| if ((!pBcnStruct->HTInfo.present) || |
| (eSIR_HT_OP_MODE_MIXED == pBcnStruct->HTInfo.opMode) || |
| (eSIR_HT_OP_MODE_OVERLAP_LEGACY == pBcnStruct->HTInfo.opMode)) |
| { |
| limUpdateOverlapStaParam(pMac, pMh->bssId, &(pMac->lim.gLimOverlap11aParams)); |
| |
| if (pMac->lim.gLimOverlap11aParams.numSta && |
| !pMac->lim.gLimOverlap11aParams.protectionEnabled) |
| { |
| limEnable11aProtection(pMac, true, true, pBeaconParams,psessionEntry); |
| } |
| } |
| //HT AP with HT20 op mode overlaps. |
| else if(eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT == pBcnStruct->HTInfo.opMode) |
| { |
| limUpdateOverlapStaParam(pMac, pMh->bssId, &(pMac->lim.gLimOverlapHt20Params)); |
| |
| if (pMac->lim.gLimOverlapHt20Params.numSta && |
| !pMac->lim.gLimOverlapHt20Params.protectionEnabled) |
| { |
| limEnableHT20Protection(pMac, true, true, pBeaconParams,psessionEntry); |
| } |
| } |
| } |
| } |
| } |
| else if(SIR_BAND_2_4_GHZ == rfBand) |
| { |
| //We are 11G AP. |
| if ((phyMode == WNI_CFG_PHY_MODE_11G) && |
| (false == psessionEntry->htCapability)) |
| { |
| if (pBcnStruct->channelNumber == psessionEntry->currentOperChannel) |
| { |
| if (((!(pBcnStruct->erpPresent)) && |
| !(pBcnStruct->HTInfo.present))|| |
| //if erp not present then 11B AP overlapping |
| (!pMac->roam.configParam.ignorePeerErpInfo && |
| pBcnStruct->erpPresent && |
| (pBcnStruct->erpIEInfo.useProtection || |
| pBcnStruct->erpIEInfo.nonErpPresent))) |
| { |
| #ifdef FEATURE_WLAN_ESE |
| if( psessionEntry->isESEconnection ) |
| { |
| VOS_TRACE (VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, |
| "%s: [INFOLOG]ESE 11g erpPresent=%d useProtection=%d nonErpPresent=%d", __func__, |
| pBcnStruct->erpPresent, |
| pBcnStruct->erpIEInfo.useProtection, |
| pBcnStruct->erpIEInfo.nonErpPresent); |
| } |
| #endif |
| limEnableOverlap11gProtection(pMac, pBeaconParams, pMh,psessionEntry); |
| } |
| |
| } |
| } |
| // handling the case when HT AP has overlapping legacy BSS. |
| else if(psessionEntry->htCapability) |
| { |
| if (pBcnStruct->channelNumber == psessionEntry->currentOperChannel) |
| { |
| if (((!(pBcnStruct->erpPresent)) && |
| !(pBcnStruct->HTInfo.present))|| |
| //if erp not present then 11B AP overlapping |
| (!pMac->roam.configParam.ignorePeerErpInfo && |
| pBcnStruct->erpPresent && |
| (pBcnStruct->erpIEInfo.useProtection || |
| pBcnStruct->erpIEInfo.nonErpPresent))) |
| { |
| #ifdef FEATURE_WLAN_ESE |
| if( psessionEntry->isESEconnection ) |
| { |
| VOS_TRACE (VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, |
| "%s: [INFOLOG]ESE 11g erpPresent=%d useProtection=%d nonErpPresent=%d", __func__, |
| pBcnStruct->erpPresent, |
| pBcnStruct->erpIEInfo.useProtection, |
| pBcnStruct->erpIEInfo.nonErpPresent); |
| } |
| #endif |
| limEnableOverlap11gProtection(pMac, pBeaconParams, pMh,psessionEntry); |
| } |
| |
| //11g device overlaps |
| if (pBcnStruct->erpPresent && |
| !(pBcnStruct->erpIEInfo.useProtection || |
| pBcnStruct->erpIEInfo.nonErpPresent) && !(pBcnStruct->HTInfo.present)) |
| { |
| limUpdateOverlapStaParam(pMac, pMh->bssId, &(psessionEntry->gLimOverlap11gParams)); |
| |
| if (psessionEntry->gLimOverlap11gParams.numSta && |
| !psessionEntry->gLimOverlap11gParams.protectionEnabled) |
| { |
| limEnableHtProtectionFrom11g(pMac, true, true, pBeaconParams,psessionEntry); |
| } |
| } |
| |
| //ht device overlaps. |
| //here we will check for HT related devices only which might need protection. |
| //check for 11b and 11g is already done in the previous blocks. |
| //so we will not check for HT operating mode as MIXED. |
| if (pBcnStruct->HTInfo.present) |
| { |
| //if we are not already in mixed mode or legacy mode as HT operating mode |
| //and received beacon has HT operating mode as legacy |
| //then we need to enable protection from 11g station. |
| //we don't need protection from 11b because if that's needed then our operating |
| //mode would have already been set to legacy in the previous blocks. |
| if((eSIR_HT_OP_MODE_OVERLAP_LEGACY == |
| pBcnStruct->HTInfo.opMode) && |
| !pMac->roam.configParam.ignore_peer_ht_opmode) |
| { |
| if((eSIR_HT_OP_MODE_MIXED != pMac->lim.gHTOperMode) && |
| (eSIR_HT_OP_MODE_OVERLAP_LEGACY != pMac->lim.gHTOperMode)) |
| { |
| limUpdateOverlapStaParam(pMac, pMh->bssId, &(psessionEntry->gLimOverlap11gParams)); |
| if (psessionEntry->gLimOverlap11gParams.numSta && |
| !psessionEntry->gLimOverlap11gParams.protectionEnabled) |
| { |
| limEnableHtProtectionFrom11g(pMac, true, true, pBeaconParams,psessionEntry); |
| } |
| } |
| } |
| else if(eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT == pBcnStruct->HTInfo.opMode) |
| { |
| limUpdateOverlapStaParam(pMac, pMh->bssId, &(psessionEntry->gLimOverlapHt20Params)); |
| if (psessionEntry->gLimOverlapHt20Params.numSta && |
| !psessionEntry->gLimOverlapHt20Params.protectionEnabled) |
| { |
| limEnableHT20Protection(pMac, true, true, pBeaconParams,psessionEntry); |
| } |
| } |
| } |
| |
| } |
| } |
| } |
| pMac->sch.gSchBcnIgnored++; |
| } |
| // -------------------------------------------------------------------- |
| |
| |
| |
| |
| /** |
| * __schBeaconProcessNoSession |
| * |
| * FUNCTION: |
| * Process the received beacon frame when |
| * -- Station is not scanning |
| * -- No corresponding session is found |
| * |
| * LOGIC: |
| * Following scenarios exist when Session Does not exist: |
| * * IBSS Beacons, when IBSS session already exists with same SSID, |
| * but from STA which has not yet joined and has a different BSSID. |
| * - invoke limHandleIBSScoalescing with the session context of existing IBSS session. |
| * |
| * * IBSS Beacons when IBSS session does not exist, only Infra or BT-AMP session exists, |
| * then save the beacon in the scan results and throw it away. |
| * |
| * * Infra Beacons |
| * - beacons received when no session active |
| * should not come here, it should be handled as part of scanning, |
| * else they should not be getting received, should update scan results and drop it if that happens. |
| * - beacons received when IBSS session active: |
| * update scan results and drop it. |
| * - beacons received when Infra session(STA) is active: |
| * update scan results and drop it |
| * - beacons received when BT-STA session is active: |
| * update scan results and drop it. |
| * - beacons received when Infra/BT-STA or Infra/IBSS is active. |
| * update scan results and drop it. |
| * |
| |
| */ |
| static void __schBeaconProcessNoSession(tpAniSirGlobal pMac, tpSchBeaconStruct pBeacon,tANI_U8* pRxPacketInfo) |
| { |
| tpPESession psessionEntry = NULL; |
| |
| if( (psessionEntry = limIsIBSSSessionActive(pMac)) != NULL) |
| { |
| limHandleIBSScoalescing(pMac, pBeacon, pRxPacketInfo, psessionEntry); |
| } |
| |
| /* |
| * If station(STA/BT-STA/BT-AP/IBSS) mode, Always save the beacon in the |
| * scan results, if at-least one session is active schBeaconProcessNoSession |
| * will be called only when there is at-least one session active, |
| * so not checking it again here. |
| */ |
| limCheckAndAddBssDescription(pMac, pBeacon, pRxPacketInfo, eANI_BOOLEAN_FALSE, eANI_BOOLEAN_FALSE); |
| return; |
| } |
| |
| |
| |
| /* |
| * __schBeaconProcessForSession |
| * |
| * FUNCTION: |
| * Process the received beacon frame when |
| * -- Station is not scanning |
| * -- Corresponding session is found |
| * |
| * LOGIC: |
| * Following scenarios exist when Session exists |
| * * IBSS STA receiving beacons from IBSS Peers, who are part of IBSS. |
| * - call limHandleIBSScoalescing with that session context. |
| * * Infra STA receiving beacons from AP to which it is connected |
| * - call schBeaconProcessFromAP with that session's context. |
| * * BTAMP STA receiving beacons from BTAMP AP |
| * - call schBeaconProcessFromAP with that session's context. |
| * * BTAMP AP receiving beacons from BTAMP STA |
| * (here need to make sure BTAP creates session entry for BT STA) |
| * - just update the beacon count for heart beat purposes for now, |
| * for now, don't process the beacon. |
| * * Infra/IBSS both active and receives IBSS beacon: |
| * - call limHandleIBSScoalescing with that session context. |
| * * Infra/IBSS both active and receives Infra beacon: |
| * - call schBeaconProcessFromAP with that session's context. |
| * any updates to EDCA parameters will be effective for IBSS as well, |
| * even though no WMM for IBSS ?? Need to figure out how to handle this scenario. |
| * * Infra/BTSTA both active and receive Infra beacon. |
| * - change in EDCA parameters on Infra affect the BTSTA link. |
| * Update the same parameters on BT link |
| * * Infra/BTSTA both active and receive BT-AP beacon. |
| * -update beacon cnt for heartbeat |
| * * Infra/BTAP both active and receive Infra beacon. |
| * - BT-AP starts advertising BE parameters from Infra AP, if they get changed. |
| * |
| * * Infra/BTAP both active and receive BTSTA beacon. |
| * - update beacon cnt for heartbeat |
| */ |
| |
| static void __schBeaconProcessForSession( tpAniSirGlobal pMac, |
| tpSchBeaconStruct pBeacon, |
| tANI_U8* pRxPacketInfo, |
| tpPESession psessionEntry) |
| { |
| tANI_U32 bi; |
| tANI_U8 bssIdx = 0; |
| //tpSirMacMgmtHdr pMh = SIR_MAC_BD_TO_MPDUHEADER(pRxPacketInfo); |
| //tANI_U8 bssid[sizeof(tSirMacAddr)]; |
| tUpdateBeaconParams beaconParams; |
| tANI_U8 sendProbeReq = FALSE; |
| tpDphHashNode pStaDs = NULL; |
| #ifdef WLAN_FEATURE_11AC |
| tpSirMacMgmtHdr pMh = WDA_GET_RX_MAC_HEADER(pRxPacketInfo); |
| tANI_U16 aid; |
| tANI_U8 operMode; |
| tANI_U8 chWidth = 0; |
| tANI_U8 skip_opmode_update = false; |
| WLAN_PHY_MODE chanMode; |
| ePhyChanBondState chanOffset; |
| #endif |
| #if defined FEATURE_WLAN_ESE || defined WLAN_FEATURE_VOWIFI |
| tPowerdBm regMax = 0,maxTxPower = 0; |
| #endif |
| tANI_U8 cbMode; |
| tPowerdBm localPowerConstraint; |
| |
| vos_mem_zero(&beaconParams, sizeof(tUpdateBeaconParams)); |
| beaconParams.paramChangeBitmap = 0; |
| |
| if (RF_CHAN_14 >= psessionEntry->currentOperChannel) { |
| if (psessionEntry->force_24ghz_in_ht20) |
| cbMode = |
| WNI_CFG_CHANNEL_BONDING_MODE_DISABLE; |
| else |
| cbMode = |
| pMac->roam.configParam.channelBondingMode24GHz; |
| } else { |
| cbMode = pMac->roam.configParam.channelBondingMode5GHz; |
| } |
| |
| if (LIM_IS_IBSS_ROLE(psessionEntry)) { |
| limHandleIBSScoalescing(pMac, pBeacon, pRxPacketInfo, psessionEntry); |
| } else if (LIM_IS_STA_ROLE(psessionEntry) || |
| LIM_IS_BT_AMP_STA_ROLE(psessionEntry)) { |
| /* |
| * This handles two cases: |
| * -- Infra STA receiving beacons from AP |
| * -- BTAMP_STA receiving beacons from BTAMP_AP |
| */ |
| //Always save the beacon into LIM's cached scan results |
| limCheckAndAddBssDescription(pMac, pBeacon, pRxPacketInfo, eANI_BOOLEAN_FALSE, eANI_BOOLEAN_FALSE); |
| |
| /** |
| * This is the Beacon received from the AP we're currently associated with. Check |
| * if there are any changes in AP's capabilities |
| */ |
| if((tANI_U8) pBeacon->channelNumber != psessionEntry->currentOperChannel) |
| { |
| PELOGE(schLog(pMac, LOGE, FL("Channel Change from %d --> %d - " |
| "Ignoring beacon!"), |
| psessionEntry->currentOperChannel, pBeacon->channelNumber);) |
| goto fail; |
| } |
| |
| limDetectChangeInApCapabilities(pMac, pBeacon, psessionEntry); |
| if(limGetStaHashBssidx(pMac, DPH_STA_HASH_INDEX_PEER, &bssIdx, psessionEntry) != eSIR_SUCCESS) |
| goto fail; |
| beaconParams.bssIdx = bssIdx; |
| vos_mem_copy(( tANI_U8* )&psessionEntry->lastBeaconTimeStamp, |
| ( tANI_U8* )pBeacon->timeStamp, sizeof(tANI_U64)); |
| psessionEntry->lastBeaconDtimCount = pBeacon->tim.dtimCount; |
| psessionEntry->lastBeaconDtimPeriod= pBeacon->tim.dtimPeriod; |
| psessionEntry->currentBssBeaconCnt++; |
| |
| |
| |
| MTRACE(macTrace(pMac, TRACE_CODE_RX_MGMT_TSF, psessionEntry->peSessionId, pBeacon->timeStamp[0]);) |
| MTRACE(macTrace(pMac, TRACE_CODE_RX_MGMT_TSF, psessionEntry->peSessionId, pBeacon->timeStamp[1]);) |
| |
| /* Read beacon interval session Entry */ |
| bi = psessionEntry->beaconParams.beaconInterval; |
| if (bi != pBeacon->beaconInterval) |
| { |
| PELOG1(schLog(pMac, LOG1, FL("Beacon interval changed from %d to %d"), |
| pBeacon->beaconInterval, bi);) |
| |
| bi = pBeacon->beaconInterval; |
| psessionEntry->beaconParams.beaconInterval = (tANI_U16) bi; |
| beaconParams.paramChangeBitmap |= PARAM_BCN_INTERVAL_CHANGED; |
| beaconParams.beaconInterval = (tANI_U16)bi; |
| } |
| |
| if (pBeacon->cfPresent) |
| { |
| cfgSetInt(pMac, WNI_CFG_CFP_PERIOD, pBeacon->cfParamSet.cfpPeriod); |
| limSendCFParams(pMac, bssIdx, pBeacon->cfParamSet.cfpCount, pBeacon->cfParamSet.cfpPeriod); |
| } |
| |
| if (pBeacon->timPresent) |
| { |
| cfgSetInt(pMac, WNI_CFG_DTIM_PERIOD, pBeacon->tim.dtimPeriod); |
| //No need to send DTIM Period and Count to HAL/SMAC |
| //SMAC already parses TIM bit. |
| } |
| |
| if(pMac->lim.gLimProtectionControl != WNI_CFG_FORCE_POLICY_PROTECTION_DISABLE) |
| |
| limDecideStaProtection(pMac, pBeacon, &beaconParams, psessionEntry); |
| if (pBeacon->erpPresent) |
| { |
| if (pBeacon->erpIEInfo.barkerPreambleMode) |
| limEnableShortPreamble(pMac, false, &beaconParams, psessionEntry); |
| else |
| limEnableShortPreamble(pMac, true, &beaconParams, psessionEntry); |
| } |
| limUpdateShortSlot(pMac, pBeacon, &beaconParams,psessionEntry); |
| |
| pStaDs = dphGetHashEntry(pMac, DPH_STA_HASH_INDEX_PEER, &psessionEntry->dph.dphHashTable); |
| if ((pBeacon->wmeEdcaPresent && (psessionEntry->limWmeEnabled)) || |
| (pBeacon->edcaPresent && (psessionEntry->limQosEnabled))) |
| { |
| if(pBeacon->edcaParams.qosInfo.count != psessionEntry->gLimEdcaParamSetCount) |
| { |
| if (schBeaconEdcaProcess(pMac, &pBeacon->edcaParams, psessionEntry) != eSIR_SUCCESS) |
| PELOGE(schLog(pMac, LOGE, FL("EDCA parameter processing error"));) |
| else if(pStaDs != NULL) |
| { |
| // If needed, downgrade the EDCA parameters |
| limSetActiveEdcaParams(pMac, psessionEntry->gLimEdcaParams, psessionEntry); |
| |
| limSendEdcaParams(pMac, psessionEntry->gLimEdcaParamsActive, |
| pStaDs->bssId); |
| } |
| else |
| PELOGE(schLog(pMac, LOGE, FL("Self Entry missing in Hash Table"));) |
| } |
| } |
| else if( (pBeacon->qosCapabilityPresent && psessionEntry->limQosEnabled) && |
| (pBeacon->qosCapability.qosInfo.count != psessionEntry->gLimEdcaParamSetCount)) |
| sendProbeReq = TRUE; |
| } |
| |
| if (psessionEntry->htCapability && pBeacon->HTInfo.present && |
| (!LIM_IS_IBSS_ROLE(psessionEntry))) |
| { |
| limUpdateStaRunTimeHTSwitchChnlParams( pMac, &pBeacon->HTInfo, bssIdx,psessionEntry); |
| } |
| |
| if (LIM_IS_STA_ROLE(psessionEntry) || |
| LIM_IS_BT_AMP_STA_ROLE(psessionEntry) || |
| LIM_IS_IBSS_ROLE(psessionEntry)) { |
| /* Channel Switch information element updated */ |
| if (pBeacon->channelSwitchPresent) { |
| #ifdef FEATURE_WLAN_TDLS |
| /* |
| * on receiving channel switch announcement from AP, delete all |
| * TDLS peers before leaving BSS and proceed for channel switch |
| */ |
| if (LIM_IS_STA_ROLE(psessionEntry)) |
| limDeleteTDLSPeers(pMac, psessionEntry); |
| #endif |
| limUpdateChannelSwitch(pMac, pBeacon, psessionEntry); |
| } else if (psessionEntry->gLimSpecMgmt.dot11hChanSwState == |
| eLIM_11H_CHANSW_RUNNING) { |
| limCancelDot11hChannelSwitch(pMac, psessionEntry); |
| } |
| } |
| |
| #ifdef WLAN_FEATURE_11AC |
| if (LIM_IS_STA_ROLE(psessionEntry) || |
| LIM_IS_BT_AMP_STA_ROLE(psessionEntry) || |
| LIM_IS_IBSS_ROLE(psessionEntry)) { |
| // check for VHT capability |
| pStaDs = dphLookupHashEntry(pMac, pMh->sa, &aid, |
| &psessionEntry->dph.dphHashTable); |
| if (NULL != pStaDs && (HAL_STA_INVALID_IDX != pStaDs->staIndex ) && |
| (WNI_CFG_CHANNEL_BONDING_MODE_DISABLE != cbMode)) |
| { |
| if (pBeacon->HTInfo.present && pBeacon->VHTOperation.present) { |
| chanOffset = limGet11ACPhyCBState(pMac, |
| pBeacon->channelNumber, |
| pBeacon->HTInfo.secondaryChannelOffset, |
| pBeacon->VHTOperation.chanCenterFreqSeg1, |
| psessionEntry); |
| chanMode = wma_chan_to_mode(pBeacon->channelNumber, |
| chanOffset, |
| psessionEntry->vhtCapability, |
| psessionEntry->dot11mode); |
| } else { |
| chanMode = MODE_MAX; |
| } |
| |
| if (psessionEntry->vhtCapability && pBeacon->OperatingMode.present ) |
| { |
| operMode = pStaDs->vhtSupportedChannelWidthSet ? |
| eHT_CHANNEL_WIDTH_80MHZ : |
| pStaDs->htSupportedChannelWidthSet ? |
| eHT_CHANNEL_WIDTH_40MHZ: eHT_CHANNEL_WIDTH_20MHZ; |
| if ((operMode == eHT_CHANNEL_WIDTH_80MHZ) && |
| (pBeacon->OperatingMode.chanWidth > |
| eHT_CHANNEL_WIDTH_80MHZ)) |
| skip_opmode_update = true; |
| |
| if (!skip_opmode_update && |
| ((operMode != pBeacon->OperatingMode.chanWidth) || |
| (pStaDs->vhtSupportedRxNss != |
| (pBeacon->OperatingMode.rxNSS + 1)))) { |
| uint32_t fw_vht_ch_wd = wma_get_vht_ch_width(); |
| PELOG1(schLog(pMac, LOG1, |
| FL(" received OpMode Chanwidth %d, staIdx = %d"), |
| pBeacon->OperatingMode.chanWidth, |
| pStaDs->staIndex);) |
| PELOG1(schLog(pMac, LOG1, FL(" MAC - %0x:%0x:%0x:%0x:%0x:%0x"), |
| pMh->sa[0], |
| pMh->sa[1], |
| pMh->sa[2], |
| pMh->sa[3], |
| pMh->sa[4], |
| pMh->sa[5]);) |
| |
| if ((pBeacon->OperatingMode.chanWidth > |
| eHT_CHANNEL_WIDTH_80MHZ) && |
| (fw_vht_ch_wd > eHT_CHANNEL_WIDTH_80MHZ)) { |
| pStaDs->vhtSupportedChannelWidthSet = |
| WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ; |
| chWidth = eHT_CHANNEL_WIDTH_160MHZ; |
| pStaDs->htSupportedChannelWidthSet = |
| eHT_CHANNEL_WIDTH_40MHZ; |
| } else if (pBeacon->OperatingMode.chanWidth >= |
| eHT_CHANNEL_WIDTH_80MHZ) { |
| PELOG1(schLog(pMac, LOG1, |
| FL("Updating the CH Width to 80MHz"));) |
| pStaDs->vhtSupportedChannelWidthSet = |
| WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ; |
| chWidth = eHT_CHANNEL_WIDTH_80MHZ; |
| pStaDs->htSupportedChannelWidthSet = |
| eHT_CHANNEL_WIDTH_40MHZ; |
| } else if (pBeacon->OperatingMode.chanWidth == |
| eHT_CHANNEL_WIDTH_40MHZ) { |
| PELOG1(schLog(pMac, LOG1, |
| FL("Updating the CH Width to 40MHz"));) |
| pStaDs->vhtSupportedChannelWidthSet = |
| WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ; |
| pStaDs->htSupportedChannelWidthSet = |
| eHT_CHANNEL_WIDTH_40MHZ; |
| chWidth = eHT_CHANNEL_WIDTH_40MHZ; |
| } else if (pBeacon->OperatingMode.chanWidth == |
| eHT_CHANNEL_WIDTH_20MHZ) { |
| PELOG1(schLog(pMac, LOG1, |
| FL("Updating the CH Width to 20MHz"));) |
| pStaDs->vhtSupportedChannelWidthSet = |
| WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ; |
| pStaDs->htSupportedChannelWidthSet = |
| eHT_CHANNEL_WIDTH_20MHZ; |
| chWidth = eHT_CHANNEL_WIDTH_20MHZ; |
| } |
| limCheckVHTOpModeChange(pMac, psessionEntry, |
| chWidth, chanMode, |
| pStaDs->staIndex, pMh->sa); |
| } |
| /* Update Nss setting */ |
| if (pStaDs->vhtSupportedRxNss != |
| (pBeacon->OperatingMode.rxNSS + 1)) { |
| pStaDs->vhtSupportedRxNss = |
| (pBeacon->OperatingMode.rxNSS + 1); |
| limSetNssChange( pMac, psessionEntry, |
| pStaDs->vhtSupportedRxNss, |
| pStaDs->staIndex, pMh->sa); |
| } |
| } |
| else if (psessionEntry->vhtCapability && pBeacon->VHTOperation.present) |
| { |
| operMode = pStaDs->vhtSupportedChannelWidthSet; |
| if ((operMode == WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ) && |
| (operMode < pBeacon->VHTOperation.chanWidth)) |
| skip_opmode_update = true; |
| |
| if (!skip_opmode_update && |
| (operMode != pBeacon->VHTOperation.chanWidth)) |
| { |
| uint32_t fw_vht_ch_wd = wma_get_vht_ch_width(); |
| PELOG1(schLog(pMac, LOG1, |
| FL(" received VHTOP CHWidth %d staIdx = %d"), |
| pBeacon->VHTOperation.chanWidth, |
| pStaDs->staIndex);) |
| PELOG1(schLog(pMac, LOG1, FL(" MAC - %0x:%0x:%0x:%0x:%0x:%0x"), |
| pMh->sa[0], |
| pMh->sa[1], |
| pMh->sa[2], |
| pMh->sa[3], |
| pMh->sa[4], |
| pMh->sa[5]);) |
| |
| if ((pBeacon->VHTOperation.chanWidth > |
| eHT_CHANNEL_WIDTH_80MHZ) && |
| (fw_vht_ch_wd > eHT_CHANNEL_WIDTH_80MHZ)) { |
| pStaDs->vhtSupportedChannelWidthSet = |
| WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ; |
| pStaDs->htSupportedChannelWidthSet = |
| eHT_CHANNEL_WIDTH_40MHZ; |
| chWidth = eHT_CHANNEL_WIDTH_160MHZ; |
| } else if (pBeacon->VHTOperation.chanWidth >= |
| WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ) { |
| PELOG1(schLog(pMac, LOG1, |
| FL("Updating the CH Width to 80MHz"));) |
| pStaDs->vhtSupportedChannelWidthSet = |
| WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ; |
| pStaDs->htSupportedChannelWidthSet = |
| eHT_CHANNEL_WIDTH_40MHZ; |
| chWidth = eHT_CHANNEL_WIDTH_80MHZ; |
| } else if (pBeacon->VHTOperation.chanWidth == |
| WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ) { |
| pStaDs->vhtSupportedChannelWidthSet = |
| WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ; |
| if (pBeacon->HTCaps.supportedChannelWidthSet) |
| { |
| PELOG1(schLog(pMac, LOG1, |
| FL("Updating the CH Width to 40MHz"));) |
| pStaDs->htSupportedChannelWidthSet = |
| eHT_CHANNEL_WIDTH_40MHZ; |
| chWidth = eHT_CHANNEL_WIDTH_40MHZ; |
| } |
| else |
| { |
| PELOG1(schLog(pMac, LOG1, |
| FL("Updating the CH Width to 20MHz"));) |
| pStaDs->htSupportedChannelWidthSet = |
| eHT_CHANNEL_WIDTH_20MHZ; |
| chWidth = eHT_CHANNEL_WIDTH_20MHZ; |
| } |
| } |
| limCheckVHTOpModeChange(pMac, psessionEntry, |
| chWidth, chanMode, pStaDs->staIndex, pMh->sa); |
| |
| } |
| } |
| } |
| } |
| #endif |
| |
| #if defined (FEATURE_WLAN_ESE) || defined (WLAN_FEATURE_VOWIFI) |
| /* Obtain the Max Tx power for the current regulatory */ |
| regMax = cfgGetRegulatoryMaxTransmitPower( pMac, psessionEntry->currentOperChannel ); |
| #endif |
| |
| localPowerConstraint = regMax; |
| |
| if (pMac->roam.configParam.allow_tpc_from_ap) { |
| #if defined FEATURE_WLAN_ESE |
| if (pBeacon->eseTxPwr.present) { |
| localPowerConstraint = pBeacon->eseTxPwr.power_limit; |
| schLog(pMac, LOG1, "ESE localPowerConstraint = %d,", |
| localPowerConstraint); |
| } |
| #endif |
| |
| #if defined WLAN_FEATURE_VOWIFI |
| if (pMac->rrm.rrmPEContext.rrmEnable && |
| pBeacon->powerConstraintPresent) { |
| localPowerConstraint = regMax; |
| localPowerConstraint -= pBeacon->localPowerConstraint. |
| localPowerConstraints; |
| schLog(pMac, LOG1, "localPowerConstraint = %d,", |
| localPowerConstraint); |
| } |
| #endif |
| } |
| |
| maxTxPower = limGetMaxTxPower(regMax, localPowerConstraint, |
| pMac->roam.configParam.nTxPowerCap); |
| |
| schLog(pMac, LOG1, "RegMax = %d, MaxTx pwr = %d", |
| regMax, maxTxPower); |
| |
| #if defined (FEATURE_WLAN_ESE) || defined (WLAN_FEATURE_VOWIFI) |
| { |
| //If maxTxPower is increased or decreased |
| if( maxTxPower != psessionEntry->maxTxPower ) |
| { |
| schLog(pMac, LOG1, "Local power constraint change..updating new maxTx power %d to HAL from old pwr %d", |
| maxTxPower, psessionEntry->maxTxPower); |
| if( limSendSetMaxTxPowerReq ( pMac, maxTxPower, psessionEntry ) == eSIR_SUCCESS ) |
| psessionEntry->maxTxPower = maxTxPower; |
| } |
| } |
| #endif |
| |
| // Indicate to LIM that Beacon is received |
| |
| if (pBeacon->HTInfo.present) |
| limReceivedHBHandler(pMac, (tANI_U8)pBeacon->HTInfo.primaryChannel, psessionEntry); |
| else |
| limReceivedHBHandler(pMac, (tANI_U8)pBeacon->channelNumber, psessionEntry); |
| |
| if (pBeacon->countryInfoPresent && pMac->sta_change_cc_via_beacon) { |
| schLog(pMac, LOG1, "beacon country code %c%c ssid: %s", |
| pBeacon->countryInfoParam.countryString[0], |
| pBeacon->countryInfoParam.countryString[1], |
| pBeacon->ssId.ssId); |
| lim_check_and_change_cc(pMac, pBeacon, psessionEntry); |
| } |
| |
| // I don't know if any additional IE is required here. Currently, not include addIE. |
| if(sendProbeReq) |
| limSendProbeReqMgmtFrame(pMac, &psessionEntry->ssId, |
| psessionEntry->bssId, psessionEntry->currentOperChannel,psessionEntry->selfMacAddr, |
| psessionEntry->dot11mode, 0, NULL); |
| |
| if ((VOS_FALSE == pMac->sap.SapDfsInfo.is_dfs_cac_timer_running) |
| && beaconParams.paramChangeBitmap) |
| { |
| PELOGW(schLog(pMac, LOGW, FL("Beacon for session[%d] got changed. "), psessionEntry->peSessionId);) |
| PELOGW(schLog(pMac, LOGW, FL("sending beacon param change bitmap: 0x%x "), beaconParams.paramChangeBitmap);) |
| limSendBeaconParams(pMac, &beaconParams, psessionEntry); |
| } |
| |
| fail: |
| return; |
| |
| } |
| |
| |
| |
| /** |
| * schBeaconProcess() - process the received beacon frame |
| * @pMac: mac global context |
| * @pRxPacketInfo: pointer to buffer descriptor |
| * |
| * Return: none |
| */ |
| |
| void schBeaconProcess(tpAniSirGlobal pMac, tANI_U8* pRxPacketInfo, tpPESession psessionEntry) |
| { |
| static tSchBeaconStruct beaconStruct; |
| tUpdateBeaconParams beaconParams; |
| tpPESession pAPSession = NULL; |
| tANI_U8 i; |
| |
| vos_mem_zero(&beaconParams, sizeof(tUpdateBeaconParams)); |
| beaconParams.paramChangeBitmap = 0; |
| |
| pMac->sch.gSchBcnRcvCnt++; |
| |
| // Convert the beacon frame into a structure |
| if (sirConvertBeaconFrame2Struct(pMac, (tANI_U8 *) pRxPacketInfo, &beaconStruct)!= eSIR_SUCCESS) |
| { |
| PELOGE(schLog(pMac, LOGE, FL("beacon parsing failed"));) |
| pMac->sch.gSchBcnParseErrorCnt++; |
| if ((NULL != psessionEntry) && |
| (!psessionEntry->currentBssBeaconCnt)) |
| lim_parse_beacon_for_tim(pMac, |
| pRxPacketInfo, psessionEntry); |
| return; |
| } |
| |
| if (beaconStruct.ssidPresent) |
| { |
| beaconStruct.ssId.ssId[beaconStruct.ssId.length] = 0; |
| } |
| |
| /* |
| * First process the beacon in the context of any existing AP or BTAP session. |
| * This takes cares of following two scenarios: |
| * - psessionEntry = NULL: |
| * e.g. beacon received from a neighboring BSS, you want to apply the protection settings to BTAP/InfraAP beacons |
| * - psessionEntry is non NULL: |
| * e.g. beacon received is from the INFRA AP to which you are connected on another concurrent link. |
| * In this case also, we want to apply the protection settings(as advertised by Infra AP) to BTAP beacons |
| * |
| * |
| */ |
| |
| |
| for (i =0; i < pMac->lim.maxBssId; i++) |
| { |
| if (((pAPSession = peFindSessionBySessionId(pMac, i)) != NULL) |
| #ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD |
| && (!(WDA_GET_OFFLOADSCANLEARN(pRxPacketInfo))) |
| #endif |
| ) |
| { |
| if (!LIM_IS_AP_ROLE(pAPSession)) { |
| continue; |
| } |
| |
| beaconParams.bssIdx = pAPSession->bssIdx; |
| if (pAPSession->gLimProtectionControl != |
| WNI_CFG_FORCE_POLICY_PROTECTION_DISABLE) |
| ap_beacon_process(pMac, pRxPacketInfo, &beaconStruct, |
| &beaconParams, pAPSession); |
| |
| if ((VOS_FALSE == pMac->sap.SapDfsInfo.is_dfs_cac_timer_running) |
| && beaconParams.paramChangeBitmap) |
| { |
| //Update the beacons and apply the new settings to HAL |
| schSetFixedBeaconFields(pMac, pAPSession); |
| PELOG1(schLog(pMac, LOG1, |
| FL("Beacon for PE session[%d] got changed."), |
| pAPSession->peSessionId);) |
| PELOG1(schLog(pMac, LOG1, |
| FL("sending beacon param change bitmap: 0x%x"), |
| beaconParams.paramChangeBitmap);) |
| limSendBeaconParams(pMac, &beaconParams, pAPSession); |
| } |
| } |
| } |
| |
| /* |
| * Now process the beacon in the context of the BSS which is transmitting the beacons, if one is found |
| */ |
| if(psessionEntry == NULL) |
| { |
| __schBeaconProcessNoSession(pMac, &beaconStruct, pRxPacketInfo ); |
| } |
| else |
| { |
| __schBeaconProcessForSession(pMac, &beaconStruct, pRxPacketInfo, psessionEntry ); |
| } |
| |
| } |
| |
| |
| |
| |
| |
| // -------------------------------------------------------------------- |
| /** |
| * schBeaconEdcaProcess |
| * |
| * FUNCTION: |
| * Process the EDCA parameter set in the received beacon frame |
| * |
| * LOGIC: |
| * |
| * ASSUMPTIONS: |
| * |
| * NOTE: |
| * |
| * @param edca reference to edca parameters in beacon struct |
| * @return success |
| */ |
| |
| tSirRetStatus schBeaconEdcaProcess(tpAniSirGlobal pMac, tSirMacEdcaParamSetIE *edca, tpPESession psessionEntry) |
| { |
| tANI_U8 i; |
| #ifdef FEATURE_WLAN_DIAG_SUPPORT |
| vos_log_qos_edca_pkt_type *log_ptr = NULL; |
| #endif //FEATURE_WLAN_DIAG_SUPPORT |
| |
| schLog(pMac, LOG2, FL("Updating parameter set count: Old %d ---> new %d"), |
| psessionEntry->gLimEdcaParamSetCount, edca->qosInfo.count); |
| |
| psessionEntry->gLimEdcaParamSetCount = edca->qosInfo.count; |
| psessionEntry->gLimEdcaParams[EDCA_AC_BE] = edca->acbe; |
| psessionEntry->gLimEdcaParams[EDCA_AC_BK] = edca->acbk; |
| psessionEntry->gLimEdcaParams[EDCA_AC_VI] = edca->acvi; |
| psessionEntry->gLimEdcaParams[EDCA_AC_VO] = edca->acvo; |
| |
| if (pMac->roam.configParam.enable_edca_params) { |
| psessionEntry->gLimEdcaParams[EDCA_AC_VO].aci.aifsn = |
| pMac->roam.configParam.edca_vo_aifs; |
| psessionEntry->gLimEdcaParams[EDCA_AC_VI].aci.aifsn = |
| pMac->roam.configParam.edca_vi_aifs; |
| psessionEntry->gLimEdcaParams[EDCA_AC_BK].aci.aifsn = |
| pMac->roam.configParam.edca_bk_aifs; |
| psessionEntry->gLimEdcaParams[EDCA_AC_BE].aci.aifsn = |
| pMac->roam.configParam.edca_be_aifs; |
| |
| psessionEntry->gLimEdcaParams[EDCA_AC_VO].cw.min = |
| pMac->roam.configParam.edca_vo_cwmin; |
| psessionEntry->gLimEdcaParams[EDCA_AC_VI].cw.min = |
| pMac->roam.configParam.edca_vi_cwmin; |
| psessionEntry->gLimEdcaParams[EDCA_AC_BK].cw.min = |
| pMac->roam.configParam.edca_bk_cwmin; |
| psessionEntry->gLimEdcaParams[EDCA_AC_BE].cw.min = |
| pMac->roam.configParam.edca_be_cwmin; |
| |
| psessionEntry->gLimEdcaParams[EDCA_AC_VO].cw.max = |
| pMac->roam.configParam.edca_vo_cwmax; |
| psessionEntry->gLimEdcaParams[EDCA_AC_VI].cw.max = |
| pMac->roam.configParam.edca_vi_cwmax; |
| psessionEntry->gLimEdcaParams[EDCA_AC_BK].cw.max = |
| pMac->roam.configParam.edca_bk_cwmax; |
| psessionEntry->gLimEdcaParams[EDCA_AC_BE].cw.max = |
| pMac->roam.configParam.edca_be_cwmax; |
| } |
| #ifdef FEATURE_WLAN_DIAG_SUPPORT |
| WLAN_VOS_DIAG_LOG_ALLOC(log_ptr, vos_log_qos_edca_pkt_type, LOG_WLAN_QOS_EDCA_C); |
| if(log_ptr) |
| { |
| log_ptr->aci_be = psessionEntry->gLimEdcaParams[EDCA_AC_BE].aci.aci; |
| log_ptr->cw_be = psessionEntry->gLimEdcaParams[EDCA_AC_BE].cw.max << 4 | |
| psessionEntry->gLimEdcaParams[EDCA_AC_BE].cw.min; |
| log_ptr->txoplimit_be = psessionEntry->gLimEdcaParams[EDCA_AC_BE].txoplimit; |
| log_ptr->aci_bk = psessionEntry->gLimEdcaParams[EDCA_AC_BK].aci.aci; |
| log_ptr->cw_bk = psessionEntry->gLimEdcaParams[EDCA_AC_BK].cw.max << 4 | |
| psessionEntry->gLimEdcaParams[EDCA_AC_BK].cw.min; |
| log_ptr->txoplimit_bk = psessionEntry->gLimEdcaParams[EDCA_AC_BK].txoplimit; |
| log_ptr->aci_vi = psessionEntry->gLimEdcaParams[EDCA_AC_VI].aci.aci; |
| log_ptr->cw_vi = psessionEntry->gLimEdcaParams[EDCA_AC_VI].cw.max << 4 | |
| psessionEntry->gLimEdcaParams[EDCA_AC_VI].cw.min; |
| log_ptr->txoplimit_vi = psessionEntry->gLimEdcaParams[EDCA_AC_VI].txoplimit; |
| log_ptr->aci_vo = psessionEntry->gLimEdcaParams[EDCA_AC_VO].aci.aci; |
| log_ptr->cw_vo = psessionEntry->gLimEdcaParams[EDCA_AC_VO].cw.max << 4 | |
| psessionEntry->gLimEdcaParams[EDCA_AC_VO].cw.min; |
| log_ptr->txoplimit_vo = psessionEntry->gLimEdcaParams[EDCA_AC_VO].txoplimit; |
| } |
| WLAN_VOS_DIAG_LOG_REPORT(log_ptr); |
| #endif //FEATURE_WLAN_DIAG_SUPPORT |
| schLog(pMac, LOG1, |
| FL("Edsa param enabled in ini %d. Updating Local EDCA Params(gLimEdcaParams) to: "), |
| pMac->roam.configParam.enable_edca_params); |
| for (i = 0; i < MAX_NUM_AC; i++) |
| { |
| schLog(pMac, LOG1, FL("AC[%d]: AIFSN: %d, ACM %d, CWmin %d, CWmax %d, TxOp %d"), |
| i, |
| psessionEntry->gLimEdcaParams[i].aci.aifsn, |
| psessionEntry->gLimEdcaParams[i].aci.acm, |
| psessionEntry->gLimEdcaParams[i].cw.min, |
| psessionEntry->gLimEdcaParams[i].cw.max, |
| psessionEntry->gLimEdcaParams[i].txoplimit); |
| } |
| |
| return eSIR_SUCCESS; |
| } |