| /* |
| * Copyright (c) 2011-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 limApi.cc contains the functions that are |
| * exported by LIM to other modules. |
| * |
| * Author: Chandra Modumudi |
| * Date: 02/11/02 |
| * History:- |
| * Date Modified by Modification Information |
| * -------------------------------------------------------------------- |
| * |
| */ |
| #include "palTypes.h" |
| #include "wni_cfg.h" |
| #include "wniApi.h" |
| #include "sirCommon.h" |
| #include "sirDebug.h" |
| #include "cfgApi.h" |
| |
| #include "schApi.h" |
| #include "utilsApi.h" |
| #include "limApi.h" |
| #include "limGlobal.h" |
| #include "limTypes.h" |
| #include "limUtils.h" |
| #include "limAssocUtils.h" |
| #include "limPropExtsUtils.h" |
| #include "limSerDesUtils.h" |
| #include "limIbssPeerMgmt.h" |
| #include "limAdmitControl.h" |
| #include "pmmApi.h" |
| #include "logDump.h" |
| #include "limSendSmeRspMessages.h" |
| #include "wmmApsd.h" |
| #include "limTrace.h" |
| #ifdef WLAN_FEATURE_VOWIFI_11R |
| #include "limFTDefs.h" |
| #endif |
| #include "limSession.h" |
| #include "wlan_qct_wda.h" |
| |
| #if defined WLAN_FEATURE_VOWIFI |
| #include "rrmApi.h" |
| #endif |
| |
| #include <limFT.h> |
| #include "vos_types.h" |
| #include "vos_packet.h" |
| #include "vos_utils.h" |
| #include "wlan_qct_tl.h" |
| #include "sysStartup.h" |
| #include "pktlog_ac_fmt.h" |
| |
| static tp_pe_packetdump_cb gpe_packetdump_cb; |
| |
| static void __limInitScanVars(tpAniSirGlobal pMac) |
| { |
| pMac->lim.gLimUseScanModeForLearnMode = 1; |
| |
| pMac->lim.gLimSystemInScanLearnMode = 0; |
| |
| // Scan related globals on STA |
| pMac->lim.gLimReturnAfterFirstMatch = 0; |
| pMac->lim.gLim24Band11dScanDone = 0; |
| pMac->lim.gLim50Band11dScanDone = 0; |
| pMac->lim.gLimReturnUniqueResults = 0; |
| |
| // Background Scan related globals on STA |
| pMac->lim.gLimNumOfBackgroundScanSuccess = 0; |
| pMac->lim.gLimNumOfConsecutiveBkgndScanFailure = 0; |
| pMac->lim.gLimNumOfForcedBkgndScan = 0; |
| pMac->lim.gLimBackgroundScanDisable = false; //based on BG timer |
| pMac->lim.gLimForceBackgroundScanDisable = false; //debug control flag |
| pMac->lim.gLimBackgroundScanTerminate = TRUE; //controlled by SME |
| pMac->lim.gLimReportBackgroundScanResults = FALSE; //controlled by SME |
| |
| pMac->lim.gLimCurrentScanChannelId = 0; |
| pMac->lim.gpLimMlmScanReq = NULL; |
| pMac->lim.gDeferMsgTypeForNOA = 0; |
| pMac->lim.gpDefdSmeMsgForNOA = NULL; |
| pMac->lim.gLimMlmScanResultLength = 0; |
| pMac->lim.gLimSmeScanResultLength = 0; |
| |
| vos_mem_set(pMac->lim.gLimCachedScanHashTable, |
| sizeof(pMac->lim.gLimCachedScanHashTable), 0); |
| |
| #ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD |
| |
| pMac->lim.gLimMlmLfrScanResultLength = 0; |
| pMac->lim.gLimSmeLfrScanResultLength = 0; |
| |
| vos_mem_set(pMac->lim.gLimCachedLfrScanHashTable, |
| sizeof(pMac->lim.gLimCachedLfrScanHashTable), 0); |
| #endif |
| pMac->lim.gLimBackgroundScanChannelId = 0; |
| pMac->lim.gLimBackgroundScanStarted = 0; |
| pMac->lim.gLimRestoreCBNumScanInterval = LIM_RESTORE_CB_NUM_SCAN_INTERVAL_DEFAULT; |
| pMac->lim.gLimRestoreCBCount = 0; |
| vos_mem_set(pMac->lim.gLimLegacyBssidList, |
| sizeof(pMac->lim.gLimLegacyBssidList), 0); |
| |
| /* Fill in default values */ |
| pMac->lim.gLimTriggerBackgroundScanDuringQuietBss = 0; |
| |
| // abort scan is used to abort an on-going scan |
| pMac->lim.abortScan = 0; |
| vos_mem_set(&pMac->lim.scanChnInfo, sizeof(tLimScanChnInfo), 0); |
| vos_mem_set(&pMac->lim.dfschannelList, sizeof(tSirDFSChannelList), 0); |
| |
| //WLAN_SUSPEND_LINK Related |
| pMac->lim.gpLimSuspendCallback = NULL; |
| pMac->lim.gpLimResumeCallback = NULL; |
| //end WLAN_SUSPEND_LINK Related |
| } |
| |
| |
| static void __limInitBssVars(tpAniSirGlobal pMac) |
| { |
| vos_mem_set((void*)pMac->lim.gpSession, |
| sizeof(*pMac->lim.gpSession)*pMac->lim.maxBssId, 0); |
| |
| /* This is for testing purposes only, be default should always be off */ |
| pMac->lim.gLimForceNoPropIE = 0; |
| pMac->lim.gpLimMlmSetKeysReq = NULL; |
| pMac->lim.gpLimMlmRemoveKeyReq = NULL; |
| } |
| |
| |
| static void __limInitStatsVars(tpAniSirGlobal pMac) |
| { |
| pMac->lim.gLimNumBeaconsRcvd = 0; |
| pMac->lim.gLimNumBeaconsIgnored = 0; |
| |
| pMac->lim.gLimNumDeferredMsgs = 0; |
| |
| /// Variable to keep track of number of currently associated STAs |
| pMac->lim.gLimNumOfAniSTAs = 0; // count of ANI peers |
| |
| // Heart-Beat interval value |
| pMac->lim.gLimHeartBeatCount = 0; |
| |
| vos_mem_zero(pMac->lim.gLimHeartBeatApMac[0], |
| sizeof(tSirMacAddr)); |
| vos_mem_zero(pMac->lim.gLimHeartBeatApMac[1], |
| sizeof(tSirMacAddr)); |
| pMac->lim.gLimHeartBeatApMacIndex = 0; |
| |
| // Statistics to keep track of no. beacons rcvd in heart beat interval |
| vos_mem_set(pMac->lim.gLimHeartBeatBeaconStats, |
| sizeof(pMac->lim.gLimHeartBeatBeaconStats), 0); |
| |
| #ifdef WLAN_DEBUG |
| // Debug counters |
| pMac->lim.numTot = 0; |
| pMac->lim.numBbt = 0; |
| pMac->lim.numProtErr = 0; |
| pMac->lim.numLearn = 0; |
| pMac->lim.numLearnIgnore = 0; |
| pMac->lim.numSme = 0; |
| vos_mem_set(pMac->lim.numMAC, sizeof(pMac->lim.numMAC), 0); |
| pMac->lim.gLimNumAssocReqDropInvldState = 0; |
| pMac->lim.gLimNumAssocReqDropACRejectTS = 0; |
| pMac->lim.gLimNumAssocReqDropACRejectSta = 0; |
| pMac->lim.gLimNumReassocReqDropInvldState = 0; |
| pMac->lim.gLimNumHashMissIgnored = 0; |
| pMac->lim.gLimUnexpBcnCnt = 0; |
| pMac->lim.gLimBcnSSIDMismatchCnt = 0; |
| pMac->lim.gLimNumLinkEsts = 0; |
| pMac->lim.gLimNumRxCleanup = 0; |
| pMac->lim.gLim11bStaAssocRejectCount = 0; |
| #endif |
| } |
| |
| static void __limInitStates(tpAniSirGlobal pMac) |
| { |
| // Counts Heartbeat failures |
| pMac->lim.gLimHBfailureCntInLinkEstState = 0; |
| pMac->lim.gLimProbeFailureAfterHBfailedCnt = 0; |
| pMac->lim.gLimHBfailureCntInOtherStates = 0; |
| pMac->lim.gLimRspReqd = 0; |
| pMac->lim.gLimPrevSmeState = eLIM_SME_OFFLINE_STATE; |
| |
| /// MLM State visible across all Sirius modules |
| MTRACE(macTrace(pMac, TRACE_CODE_MLM_STATE, NO_SESSION, eLIM_MLM_IDLE_STATE)); |
| pMac->lim.gLimMlmState = eLIM_MLM_IDLE_STATE; |
| |
| /// Previous MLM State |
| pMac->lim.gLimPrevMlmState = eLIM_MLM_OFFLINE_STATE; |
| |
| // LIM to HAL SCAN Management Message Interface states |
| pMac->lim.gLimHalScanState = eLIM_HAL_IDLE_SCAN_STATE; |
| |
| /** |
| * Initialize state to eLIM_SME_OFFLINE_STATE |
| */ |
| pMac->lim.gLimSmeState = eLIM_SME_OFFLINE_STATE; |
| |
| /** |
| * By default assume 'unknown' role. This will be updated |
| * when SME_START_BSS_REQ is received. |
| */ |
| |
| vos_mem_set(&pMac->lim.gLimOverlap11gParams, sizeof(tLimProtStaParams), 0); |
| vos_mem_set(&pMac->lim.gLimOverlap11aParams, sizeof(tLimProtStaParams), 0); |
| vos_mem_set(&pMac->lim.gLimOverlapHt20Params, sizeof(tLimProtStaParams), 0); |
| vos_mem_set(&pMac->lim.gLimOverlapNonGfParams, sizeof(tLimProtStaParams), 0); |
| vos_mem_set(&pMac->lim.gLimNoShortParams, sizeof(tLimNoShortParams), 0); |
| vos_mem_set(&pMac->lim.gLimNoShortSlotParams, sizeof(tLimNoShortSlotParams), 0); |
| |
| pMac->lim.gLimPhyMode = 0; |
| pMac->lim.scanStartTime = 0; // used to measure scan time |
| |
| vos_mem_set(pMac->lim.gLimMyMacAddr, sizeof(pMac->lim.gLimMyMacAddr), 0); |
| pMac->lim.ackPolicy = 0; |
| |
| pMac->lim.gLimProbeRespDisableFlag = 0; // control over probe response |
| } |
| |
| #ifdef FEATURE_OEM_DATA_SUPPORT |
| static void lim_set_oem_data_req(tpAniSirGlobal mac) |
| { |
| mac->lim.gpLimMlmOemDataReq = NULL; |
| } |
| #else |
| static inline void lim_set_oem_data_req(tpAniSirGlobal mac) |
| { |
| } |
| #endif |
| |
| static void __limInitVars(tpAniSirGlobal pMac) |
| { |
| // Place holder for Measurement Req/Rsp/Ind related info |
| |
| // Deferred Queue Paramters |
| vos_mem_set(&pMac->lim.gLimDeferredMsgQ, sizeof(tSirAddtsReq), 0); |
| |
| // addts request if any - only one can be outstanding at any time |
| vos_mem_set(&pMac->lim.gLimAddtsReq, sizeof(tSirAddtsReq) , 0); |
| pMac->lim.gLimAddtsSent = 0; |
| pMac->lim.gLimAddtsRspTimerCount = 0; |
| |
| //protection related config cache |
| vos_mem_set(&pMac->lim.cfgProtection, sizeof(tCfgProtection), 0); |
| pMac->lim.gLimProtectionControl = 0; |
| vos_mem_set(&pMac->lim.gLimAlternateRadio, sizeof(tSirAlternateRadioInfo), 0); |
| SET_LIM_PROCESS_DEFD_MESGS(pMac, true); |
| |
| // WMM Related Flag |
| pMac->lim.gUapsdEnable = 0; |
| pMac->lim.gUapsdPerAcBitmask = 0; |
| pMac->lim.gUapsdPerAcTriggerEnableMask = 0; |
| pMac->lim.gUapsdPerAcDeliveryEnableMask = 0; |
| |
| // QoS-AC Downgrade: Initially, no AC is admitted |
| pMac->lim.gAcAdmitMask[SIR_MAC_DIRECTION_UPLINK] = 0; |
| pMac->lim.gAcAdmitMask[SIR_MAC_DIRECTION_DNLINK] = 0; |
| |
| //dialogue token List head/tail for Action frames request sent. |
| pMac->lim.pDialogueTokenHead = NULL; |
| pMac->lim.pDialogueTokenTail = NULL; |
| |
| vos_mem_set(&pMac->lim.tspecInfo, |
| sizeof(tLimTspecInfo) * LIM_NUM_TSPEC_MAX, 0); |
| |
| // admission control policy information |
| vos_mem_set(&pMac->lim.admitPolicyInfo, sizeof(tLimAdmitPolicyInfo), 0); |
| |
| pMac->lim.gLastBeaconDtimCount = 0; |
| pMac->lim.gLastBeaconDtimPeriod = 0; |
| |
| //Scan in Power Save Flag |
| pMac->lim.gScanInPowersave = 0; |
| pMac->lim.probeCounter = 0; |
| pMac->lim.maxProbe = 0; |
| |
| #ifdef SAP_AUTH_OFFLOAD |
| /* Init SAP deffered Q Head */ |
| lim_init_sap_deferred_msg_queue(pMac); |
| #endif |
| lim_set_oem_data_req(pMac); |
| } |
| |
| static void __limInitAssocVars(tpAniSirGlobal pMac) |
| { |
| tANI_U32 val; |
| if(wlan_cfgGetInt(pMac, WNI_CFG_ASSOC_STA_LIMIT, &val) != eSIR_SUCCESS) |
| { |
| limLog( pMac, LOGP, FL( "cfg get assoc sta limit failed" )); |
| } |
| pMac->lim.gLimAssocStaLimit = val; |
| pMac->lim.gLimIbssStaLimit = val; |
| if(wlan_cfgGetInt(pMac, WNI_CFG_ASSOC_STA_LIMIT_AP, &val) != eSIR_SUCCESS) |
| limLog( pMac, LOGP, FL( "cfg get assoc sta of AP limit failed" )); |
| |
| pMac->lim.glim_assoc_sta_limit_ap = val; |
| |
| if(wlan_cfgGetInt(pMac, WNI_CFG_ASSOC_STA_LIMIT_GO, &val) != eSIR_SUCCESS) |
| limLog( pMac, LOGP, FL( "cfg get assoc sta of GO limit failed" )); |
| |
| pMac->lim.glim_assoc_sta_limit_go = val; |
| |
| limLog(pMac, LOG1, FL("max_peer:%d ap_peer:%d go_peer:%d"), |
| pMac->lim.gLimAssocStaLimit, pMac->lim.glim_assoc_sta_limit_ap, |
| pMac->lim.glim_assoc_sta_limit_go); |
| // Place holder for current authentication request |
| // being handled |
| pMac->lim.gpLimMlmAuthReq = NULL; |
| |
| /// MAC level Pre-authentication related globals |
| pMac->lim.gLimPreAuthChannelNumber = 0; |
| pMac->lim.gLimPreAuthType = eSIR_OPEN_SYSTEM; |
| vos_mem_set(&pMac->lim.gLimPreAuthPeerAddr, sizeof(tSirMacAddr), 0); |
| pMac->lim.gLimNumPreAuthContexts = 0; |
| vos_mem_set(&pMac->lim.gLimPreAuthTimerTable, sizeof(tLimPreAuthTable), 0); |
| |
| // Placed holder to deauth reason |
| pMac->lim.gLimDeauthReasonCode = 0; |
| |
| // Place holder for Pre-authentication node list |
| pMac->lim.pLimPreAuthList = NULL; |
| |
| //One cache for each overlap and associated case. |
| vos_mem_set(pMac->lim.protStaOverlapCache, |
| sizeof(tCacheParams) * LIM_PROT_STA_OVERLAP_CACHE_SIZE, 0); |
| vos_mem_set(pMac->lim.protStaCache, |
| sizeof(tCacheParams) * LIM_PROT_STA_CACHE_SIZE, 0); |
| |
| #if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) |
| pMac->lim.pSessionEntry = NULL; |
| pMac->lim.reAssocRetryAttempt = 0; |
| #endif |
| |
| } |
| |
| static void __limInitHTVars(tpAniSirGlobal pMac) |
| { |
| pMac->lim.htCapabilityPresentInBeacon = 0; |
| pMac->lim.gHTGreenfield = 0; |
| pMac->lim.gHTShortGI40Mhz = 0; |
| pMac->lim.gHTShortGI20Mhz = 0; |
| pMac->lim.gHTMaxAmsduLength = 0; |
| pMac->lim.gHTDsssCckRate40MHzSupport = 0; |
| pMac->lim.gHTPSMPSupport = 0; |
| pMac->lim.gHTLsigTXOPProtection = 0; |
| pMac->lim.gHTMIMOPSState = eSIR_HT_MIMO_PS_STATIC; |
| pMac->lim.gHTAMpduDensity = 0; |
| |
| pMac->lim.gMaxAmsduSizeEnabled = false; |
| pMac->lim.gHTMaxRxAMpduFactor = 0; |
| pMac->lim.gHTServiceIntervalGranularity = 0; |
| pMac->lim.gHTControlledAccessOnly = 0; |
| pMac->lim.gHTOperMode = eSIR_HT_OP_MODE_PURE; |
| pMac->lim.gHTPCOActive = 0; |
| |
| pMac->lim.gHTPCOPhase = 0; |
| pMac->lim.gHTSecondaryBeacon = 0; |
| pMac->lim.gHTDualCTSProtection = 0; |
| pMac->lim.gHTSTBCBasicMCS = 0; |
| pMac->lim.gAddBA_Declined = 0; // Flag to Decline the BAR if the particular bit (0-7) is being set |
| } |
| |
| static tSirRetStatus __limInitConfig( tpAniSirGlobal pMac ) |
| { |
| tANI_U32 val1, val2, val3; |
| tANI_U16 val16; |
| tANI_U8 val8; |
| tSirMacHTCapabilityInfo *pHTCapabilityInfo; |
| tSirMacHTInfoField1 *pHTInfoField1; |
| tpSirPowerSaveCfg pPowerSaveConfig; |
| tSirMacHTParametersInfo *pAmpduParamInfo; |
| |
| /* Read all the CFGs here that were updated before peStart is called */ |
| /* All these CFG READS/WRITES are only allowed in init, at start when there is no session |
| * and they will be used throughout when there is no session |
| */ |
| |
| if(wlan_cfgGetInt(pMac, WNI_CFG_HT_CAP_INFO, &val1) != eSIR_SUCCESS) |
| { |
| PELOGE(limLog(pMac, LOGE, FL("could not retrieve HT Cap CFG"));) |
| return eSIR_FAILURE; |
| } |
| |
| if(wlan_cfgGetInt(pMac, WNI_CFG_CHANNEL_BONDING_MODE, &val2) != eSIR_SUCCESS) |
| { |
| PELOGE(limLog(pMac, LOGE, FL("could not retrieve Channel Bonding CFG"));) |
| return eSIR_FAILURE; |
| } |
| val16 = ( tANI_U16 ) val1; |
| pHTCapabilityInfo = ( tSirMacHTCapabilityInfo* ) &val16; |
| |
| pHTCapabilityInfo->supportedChannelWidthSet = val2 ? |
| WNI_CFG_CHANNEL_BONDING_MODE_ENABLE : WNI_CFG_CHANNEL_BONDING_MODE_DISABLE; |
| if(cfgSetInt(pMac, WNI_CFG_HT_CAP_INFO, *(tANI_U16*)pHTCapabilityInfo) |
| != eSIR_SUCCESS) |
| { |
| PELOGE(limLog(pMac, LOGE, FL("could not update HT Cap Info CFG"));) |
| return eSIR_FAILURE; |
| } |
| |
| if(wlan_cfgGetInt(pMac, WNI_CFG_HT_INFO_FIELD1, &val1) != eSIR_SUCCESS) |
| { |
| PELOGE(limLog(pMac, LOGE, FL("could not retrieve HT INFO Field1 CFG"));) |
| return eSIR_FAILURE; |
| } |
| |
| val8 = ( tANI_U8 ) val1; |
| pHTInfoField1 = ( tSirMacHTInfoField1* ) &val8; |
| pHTInfoField1->recommendedTxWidthSet = |
| (tANI_U8)pHTCapabilityInfo->supportedChannelWidthSet; |
| if(cfgSetInt(pMac, WNI_CFG_HT_INFO_FIELD1, *(tANI_U8*)pHTInfoField1) |
| != eSIR_SUCCESS) |
| { |
| PELOGE(limLog(pMac, LOGE, FL("could not update HT Info Field"));) |
| return eSIR_FAILURE; |
| } |
| |
| /* WNI_CFG_HEART_BEAT_THRESHOLD */ |
| |
| if( wlan_cfgGetInt(pMac, WNI_CFG_HEART_BEAT_THRESHOLD, &val1) != |
| eSIR_SUCCESS ) |
| { |
| PELOGE(limLog(pMac, LOGE, FL("could not retrieve WNI_CFG_HEART_BEAT_THRESHOLD CFG"));) |
| return eSIR_FAILURE; |
| } |
| if(!val1) |
| { |
| limDeactivateAndChangeTimer(pMac, eLIM_HEART_BEAT_TIMER); |
| pMac->sys.gSysEnableLinkMonitorMode = 0; |
| } |
| else |
| { |
| //No need to activate the timer during init time. |
| pMac->sys.gSysEnableLinkMonitorMode = 1; |
| } |
| |
| /* WNI_CFG_SHORT_GI_20MHZ */ |
| |
| if (wlan_cfgGetInt(pMac, WNI_CFG_HT_CAP_INFO, &val1) != eSIR_SUCCESS) |
| { |
| PELOGE(limLog(pMac, LOGE, FL("could not retrieve HT Cap CFG"));) |
| return eSIR_FAILURE; |
| } |
| if (wlan_cfgGetInt(pMac, WNI_CFG_SHORT_GI_20MHZ, &val2) != eSIR_SUCCESS) |
| { |
| PELOGE(limLog(pMac, LOGE, FL("could not retrieve shortGI 20Mhz CFG"));) |
| return eSIR_FAILURE; |
| } |
| if (wlan_cfgGetInt(pMac, WNI_CFG_SHORT_GI_40MHZ, &val3) != eSIR_SUCCESS) |
| { |
| PELOGE(limLog(pMac, LOGE, FL("could not retrieve shortGI 40Mhz CFG"));) |
| return eSIR_FAILURE; |
| } |
| |
| val16 = ( tANI_U16 ) val1; |
| pHTCapabilityInfo = ( tSirMacHTCapabilityInfo* ) &val16; |
| pHTCapabilityInfo->shortGI20MHz = (tANI_U16)val2; |
| pHTCapabilityInfo->shortGI40MHz = (tANI_U16)val3; |
| |
| if(cfgSetInt(pMac, WNI_CFG_HT_CAP_INFO, *(tANI_U16*)pHTCapabilityInfo) != |
| eSIR_SUCCESS) |
| { |
| PELOGE(limLog(pMac, LOGE, FL("could not update HT Cap Info CFG"));) |
| return eSIR_FAILURE; |
| } |
| |
| /* WNI_CFG_MAX_RX_AMPDU_FACTOR */ |
| |
| if (wlan_cfgGetInt(pMac, WNI_CFG_HT_AMPDU_PARAMS, &val1) != eSIR_SUCCESS) |
| { |
| PELOGE(limLog(pMac, LOGE, FL("could not retrieve HT AMPDU Param CFG"));) |
| return eSIR_FAILURE; |
| } |
| if (wlan_cfgGetInt(pMac, WNI_CFG_MAX_RX_AMPDU_FACTOR, &val2) != eSIR_SUCCESS) |
| { |
| PELOGE(limLog(pMac, LOGE, FL("could not retrieve AMPDU Factor CFG"));) |
| } |
| if (wlan_cfgGetInt(pMac, WNI_CFG_MPDU_DENSITY, &val3) != eSIR_SUCCESS) { |
| limLog(pMac, LOGE, FL("could not retrieve MPDU Density CFG")); |
| return eSIR_FAILURE; |
| } |
| |
| val16 = ( tANI_U16 ) val1; |
| pAmpduParamInfo = ( tSirMacHTParametersInfo* ) &val16; |
| pAmpduParamInfo->maxRxAMPDUFactor = (tANI_U8)val2; |
| pAmpduParamInfo->mpduDensity = (uint8_t)val3; |
| |
| if(cfgSetInt(pMac, WNI_CFG_HT_AMPDU_PARAMS, *(tANI_U8*)pAmpduParamInfo) != |
| eSIR_SUCCESS) |
| { |
| limLog(pMac, LOGE, FL("cfg get short preamble failed")); |
| return eSIR_FAILURE; |
| } |
| |
| /* WNI_CFG_SHORT_PREAMBLE - this one is not updated in |
| limHandleCFGparamUpdate do we want to update this? */ |
| if(wlan_cfgGetInt(pMac, WNI_CFG_SHORT_PREAMBLE, &val1) != eSIR_SUCCESS) |
| { |
| limLog(pMac, LOGP, FL("cfg get short preamble failed")); |
| return eSIR_FAILURE; |
| } |
| |
| /* WNI_CFG_MAX_PS_POLL */ |
| |
| if (!pMac->psOffloadEnabled) |
| { |
| /* Allocate and fill in power save configuration. */ |
| pPowerSaveConfig = vos_mem_malloc(sizeof(tSirPowerSaveCfg)); |
| if (NULL == pPowerSaveConfig) |
| { |
| PELOGE(limLog(pMac, LOGE, |
| FL("LIM: Cannot allocate memory for power save configuration"));) |
| return eSIR_FAILURE; |
| } |
| |
| /* This context should be valid if power-save configuration message has |
| * been already dispatched during initialization process. Re-using the |
| * present configuration mask |
| */ |
| vos_mem_copy(pPowerSaveConfig, (tANI_U8 *)&pMac->pmm.gPmmCfg, |
| sizeof(tSirPowerSaveCfg)); |
| |
| /* Note: it is okay to do this since DAL/HAL is alrady started */ |
| if ( (pmmSendPowerSaveCfg(pMac, pPowerSaveConfig)) != eSIR_SUCCESS) |
| { |
| PELOGE(limLog(pMac, LOGE, |
| FL("LIM: pmmSendPowerSaveCfg() failed "));) |
| return eSIR_FAILURE; |
| } |
| } |
| |
| /* WNI_CFG_BG_SCAN_CHANNEL_LIST_CHANNEL_LIST */ |
| |
| PELOG1(limLog(pMac, LOG1, |
| FL("VALID_CHANNEL_LIST has changed, reset next bg scan channel"));) |
| pMac->lim.gLimBackgroundScanChannelId = 0; |
| |
| /* WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA - not needed */ |
| |
| /* This was initially done after resume notification from HAL. Now, DAL is |
| started before PE so this can be done here */ |
| handleHTCapabilityandHTInfo(pMac, NULL); |
| if (eSIR_SUCCESS != wlan_cfgGetInt(pMac, WNI_CFG_DISABLE_LDPC_WITH_TXBF_AP, |
| (tANI_U32 *) &pMac->lim.disableLDPCWithTxbfAP)) |
| { |
| limLog(pMac, LOGP, FL("cfg get disableLDPCWithTxbfAP failed")); |
| return eSIR_FAILURE; |
| } |
| #ifdef FEATURE_WLAN_TDLS |
| if (eSIR_SUCCESS != wlan_cfgGetInt(pMac, WNI_CFG_TDLS_BUF_STA_ENABLED, |
| (tANI_U32 *) &pMac->lim.gLimTDLSBufStaEnabled)) |
| { |
| limLog(pMac, LOGP, FL("cfg get LimTDLSBufStaEnabled failed")); |
| return eSIR_FAILURE; |
| } |
| if (eSIR_SUCCESS != wlan_cfgGetInt(pMac, WNI_CFG_TDLS_QOS_WMM_UAPSD_MASK, |
| (tANI_U32 *) &pMac->lim.gLimTDLSUapsdMask)) |
| { |
| limLog(pMac, LOGP, FL("cfg get LimTDLSUapsdMask failed")); |
| return eSIR_FAILURE; |
| } |
| if (eSIR_SUCCESS != wlan_cfgGetInt(pMac, WNI_CFG_TDLS_OFF_CHANNEL_ENABLED, |
| (tANI_U32 *) &pMac->lim.gLimTDLSOffChannelEnabled)) |
| { |
| limLog(pMac, LOGP, FL("cfg get LimTDLSUapsdMask failed")); |
| return eSIR_FAILURE; |
| } |
| |
| if (eSIR_SUCCESS != wlan_cfgGetInt(pMac, WNI_CFG_TDLS_WMM_MODE_ENABLED, |
| (tANI_U32 *) &pMac->lim.gLimTDLSWmmMode)) |
| { |
| limLog(pMac, LOGP, FL("cfg get LimTDLSWmmMode failed")); |
| return eSIR_FAILURE; |
| } |
| #endif |
| return eSIR_SUCCESS; |
| } |
| |
| /* |
| limStart |
| This function is to replace the __limProcessSmeStartReq since there is no |
| eWNI_SME_START_REQ post to PE. |
| */ |
| tSirRetStatus limStart(tpAniSirGlobal pMac) |
| { |
| tSirResultCodes retCode = eSIR_SUCCESS; |
| |
| PELOG1(limLog(pMac, LOG1, FL(" enter"));) |
| |
| if (pMac->lim.gLimSmeState == eLIM_SME_OFFLINE_STATE) |
| { |
| pMac->lim.gLimSmeState = eLIM_SME_IDLE_STATE; |
| |
| MTRACE(macTrace(pMac, TRACE_CODE_SME_STATE, NO_SESSION, pMac->lim.gLimSmeState)); |
| |
| // By default do not return after first scan match |
| pMac->lim.gLimReturnAfterFirstMatch = 0; |
| |
| // Initialize MLM state machine |
| if (eSIR_SUCCESS != limInitMlm(pMac)) { |
| limLog(pMac, LOGE, FL("Init MLM failed.")); |
| return eSIR_FAILURE; |
| } |
| |
| // By default return unique scan results |
| pMac->lim.gLimReturnUniqueResults = true; |
| pMac->lim.gLimSmeScanResultLength = 0; |
| #ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD |
| pMac->lim.gLimSmeLfrScanResultLength = 0; |
| #endif |
| } |
| else |
| { |
| /** |
| * Should not have received eWNI_SME_START_REQ in states |
| * other than OFFLINE. Return response to host and |
| * log error |
| */ |
| limLog(pMac, LOGE, FL("Invalid SME state %X"),pMac->lim.gLimSmeState ); |
| retCode = eSIR_FAILURE; |
| } |
| |
| return retCode; |
| } |
| |
| /** |
| * limInitialize() |
| * |
| *FUNCTION: |
| * This function is called from LIM thread entry function. |
| * LIM related global data structures are initialized in this function. |
| * |
| *LOGIC: |
| * NA |
| * |
| *ASSUMPTIONS: |
| * NA |
| * |
| *NOTE: |
| * NA |
| * |
| * @param pMac - Pointer to global MAC structure |
| * @return None |
| */ |
| |
| tSirRetStatus |
| limInitialize(tpAniSirGlobal pMac) |
| { |
| tSirRetStatus status = eSIR_SUCCESS; |
| |
| __limInitAssocVars(pMac); |
| __limInitVars(pMac); |
| __limInitStates(pMac); |
| __limInitStatsVars(pMac); |
| __limInitBssVars(pMac); |
| __limInitScanVars(pMac); |
| __limInitHTVars(pMac); |
| |
| status = limStart(pMac); |
| if(eSIR_SUCCESS != status) |
| { |
| return status; |
| } |
| |
| // Initializations for maintaining peers in IBSS |
| limIbssInit(pMac); |
| |
| if(!pMac->psOffloadEnabled) |
| pmmInitialize(pMac); |
| |
| #if defined WLAN_FEATURE_VOWIFI |
| rrmInitialize(pMac); |
| #endif |
| |
| vos_list_init(&pMac->lim.gLimMgmtFrameRegistratinQueue); |
| |
| //Initialize the configurations needed by PE |
| if( eSIR_FAILURE == __limInitConfig(pMac)) |
| { |
| //We need to undo everything in limStart |
| limCleanupMlm(pMac); |
| return eSIR_FAILURE; |
| } |
| |
| //initialize the TSPEC admission control table. |
| //Note that this was initially done after resume notification from HAL. |
| //Now, DAL is started before PE so this can be done here |
| limAdmitControlInit(pMac); |
| limRegisterHalIndCallBack(pMac); |
| |
| return status; |
| |
| } /*** end limInitialize() ***/ |
| |
| |
| |
| /** |
| * limCleanup() |
| * |
| *FUNCTION: |
| * This function is called upon reset or persona change |
| * to cleanup LIM state |
| * |
| *LOGIC: |
| * NA |
| * |
| *ASSUMPTIONS: |
| * NA |
| * |
| *NOTE: |
| * NA |
| * |
| * @param pMac - Pointer to Global MAC structure |
| * @return None |
| */ |
| |
| void |
| limCleanup(tpAniSirGlobal pMac) |
| { |
| //Before destroying the list making sure all the nodes have been deleted. |
| //Which should be the normal case, but a memory leak has been reported. |
| uint8_t i; |
| |
| tpLimMgmtFrameRegistration pLimMgmtRegistration = NULL; |
| |
| while(vos_list_remove_front(&pMac->lim.gLimMgmtFrameRegistratinQueue, |
| (vos_list_node_t**)&pLimMgmtRegistration) == VOS_STATUS_SUCCESS) |
| { |
| VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, |
| FL("Fixing leak! Deallocating pLimMgmtRegistration node")); |
| |
| vos_mem_free(pLimMgmtRegistration); |
| } |
| |
| vos_list_destroy(&pMac->lim.gLimMgmtFrameRegistratinQueue); |
| |
| limCleanupMlm(pMac); |
| limCleanupLmm(pMac); |
| |
| // free up preAuth table |
| if (pMac->lim.gLimPreAuthTimerTable.pTable != NULL) |
| { |
| for (i = 0; i < pMac->lim.gLimPreAuthTimerTable.numEntry; i++) |
| vos_mem_free(pMac->lim.gLimPreAuthTimerTable.pTable[i]); |
| vos_mem_free(pMac->lim.gLimPreAuthTimerTable.pTable); |
| pMac->lim.gLimPreAuthTimerTable.pTable = NULL; |
| pMac->lim.gLimPreAuthTimerTable.numEntry = 0; |
| } |
| |
| if(NULL != pMac->lim.pDialogueTokenHead) |
| { |
| limDeleteDialogueTokenList(pMac); |
| } |
| |
| if(NULL != pMac->lim.pDialogueTokenTail) |
| { |
| vos_mem_free(pMac->lim.pDialogueTokenTail); |
| pMac->lim.pDialogueTokenTail = NULL; |
| } |
| |
| if (pMac->lim.gpLimMlmSetKeysReq != NULL) |
| { |
| vos_mem_free(pMac->lim.gpLimMlmSetKeysReq); |
| pMac->lim.gpLimMlmSetKeysReq = NULL; |
| } |
| |
| if (pMac->lim.gpLimMlmAuthReq != NULL) |
| { |
| vos_mem_free(pMac->lim.gpLimMlmAuthReq); |
| pMac->lim.gpLimMlmAuthReq = NULL; |
| } |
| |
| if (pMac->lim.gpLimMlmRemoveKeyReq != NULL) |
| { |
| vos_mem_free(pMac->lim.gpLimMlmRemoveKeyReq); |
| pMac->lim.gpLimMlmRemoveKeyReq = NULL; |
| } |
| |
| if (pMac->lim.gpDefdSmeMsgForNOA != NULL) |
| { |
| vos_mem_free(pMac->lim.gpDefdSmeMsgForNOA); |
| pMac->lim.gpDefdSmeMsgForNOA = NULL; |
| } |
| |
| if (pMac->lim.gpLimMlmScanReq != NULL) |
| { |
| vos_mem_free(pMac->lim.gpLimMlmScanReq); |
| pMac->lim.gpLimMlmScanReq = NULL; |
| } |
| |
| // Now, finally reset the deferred message queue pointers |
| limResetDeferredMsgQ(pMac); |
| |
| #if defined WLAN_FEATURE_VOWIFI |
| rrmCleanup(pMac); |
| #endif |
| |
| #if defined WLAN_FEATURE_VOWIFI_11R |
| limFTCleanupAllFTSessions(pMac); |
| #endif |
| |
| #ifdef SAP_AUTH_OFFLOAD |
| lim_cleanup_sap_deferred_msg_queue(pMac); |
| #endif |
| |
| } /*** end limCleanup() ***/ |
| |
| /** |
| * lim_state_info_dump() - print state information of lim layer |
| * @buf: buffer pointer |
| * @size: size of buffer to be filled |
| * |
| * This function is used to print state information of lim layer |
| * |
| * Return: None |
| */ |
| static void lim_state_info_dump(char **buf_ptr, uint16_t *size) |
| { |
| tHalHandle hal; |
| tpAniSirGlobal mac; |
| v_CONTEXT_t vos_ctx_ptr; |
| uint16_t len = 0; |
| char *buf = *buf_ptr; |
| |
| /* get the global voss context */ |
| vos_ctx_ptr = vos_get_global_context(VOS_MODULE_ID_VOSS, NULL); |
| |
| if (NULL == vos_ctx_ptr) { |
| VOS_ASSERT(0); |
| return; |
| } |
| |
| hal = vos_get_context(VOS_MODULE_ID_PE, vos_ctx_ptr); |
| if (NULL == hal) { |
| VOS_ASSERT(0); |
| return; |
| } |
| |
| mac = PMAC_STRUCT(hal); |
| |
| limLog(mac, LOG1, FL("size of buffer: %d"), *size); |
| |
| len += vos_scnprintf(buf + len, *size - len, |
| "\n SmeState: %d", mac->lim.gLimSmeState); |
| len += vos_scnprintf(buf + len, *size - len, |
| "\n PrevSmeState: %d", mac->lim.gLimPrevSmeState); |
| len += vos_scnprintf(buf + len, *size - len, |
| "\n MlmState: %d", mac->lim.gLimMlmState); |
| len += vos_scnprintf(buf + len, *size - len, |
| "\n PrevMlmState: %d", mac->lim.gLimPrevMlmState); |
| len += vos_scnprintf(buf + len, *size - len, |
| "\n SystemInScanLearnMode: %d", |
| mac->lim.gLimSystemInScanLearnMode); |
| len += vos_scnprintf(buf + len, *size - len, |
| "\n ProcessDefdMsgs: %d", mac->lim.gLimProcessDefdMsgs); |
| len += vos_scnprintf(buf + len, *size - len, |
| "\n gLimHalScanState: %d", mac->lim.gLimHalScanState); |
| |
| *size -= len; |
| *buf_ptr += len; |
| } |
| |
| /** |
| * lim_register_debug_callback() - registration function for lim layer |
| * to print lim state information |
| * |
| * Return: None |
| */ |
| static void lim_register_debug_callback(void) |
| { |
| vos_register_debug_callback(VOS_MODULE_ID_PE, &lim_state_info_dump); |
| } |
| |
| /** ------------------------------------------------------------- |
| \fn peOpen |
| \brief will be called in Open sequence from macOpen |
| \param tpAniSirGlobal pMac |
| \param tHalOpenParameters *pHalOpenParam |
| \return tSirRetStatus |
| -------------------------------------------------------------*/ |
| |
| tSirRetStatus peOpen(tpAniSirGlobal pMac, tMacOpenParameters *pMacOpenParam) |
| { |
| tSirRetStatus status = eSIR_SUCCESS; |
| |
| if (eDRIVER_TYPE_MFG == pMacOpenParam->driverType) |
| return eSIR_SUCCESS; |
| |
| pMac->lim.maxBssId = pMacOpenParam->maxBssId; |
| pMac->lim.maxStation = pMacOpenParam->maxStation; |
| |
| if ((pMac->lim.maxBssId == 0) || (pMac->lim.maxStation == 0)) { |
| PELOGE(limLog(pMac, LOGE, |
| FL("max number of Bssid or Stations cannot be zero!"));) |
| return eSIR_FAILURE; |
| } |
| |
| pMac->lim.limTimers.gpLimCnfWaitTimer = vos_mem_malloc(sizeof(TX_TIMER) * |
| (pMac->lim.maxStation + 1)); |
| if (NULL == pMac->lim.limTimers.gpLimCnfWaitTimer) { |
| PELOGE(limLog(pMac, LOGE, FL("memory allocate failed!"));) |
| return eSIR_FAILURE; |
| } |
| |
| pMac->lim.gpSession = vos_mem_malloc(sizeof(tPESession)* |
| pMac->lim.maxBssId); |
| if (NULL == pMac->lim.gpSession) { |
| limLog(pMac, LOGE, FL("memory allocate failed!")); |
| status = eSIR_FAILURE; |
| goto pe_open_psession_fail; |
| } |
| |
| vos_mem_set(pMac->lim.gpSession, sizeof(tPESession) * |
| pMac->lim.maxBssId, 0); |
| |
| pMac->pmm.gPmmTim.pTim = vos_mem_malloc(sizeof(tANI_U8) * |
| pMac->lim.maxStation); |
| if (NULL == pMac->pmm.gPmmTim.pTim) { |
| PELOGE(limLog(pMac, LOGE, FL("memory allocate failed for pTim!"));) |
| status = eSIR_FAILURE; |
| goto pe_open_ptim_fail; |
| } |
| vos_mem_set(pMac->pmm.gPmmTim.pTim, sizeof(tANI_U8) * |
| pMac->lim.maxStation, 0); |
| |
| pMac->lim.mgmtFrameSessionId = 0xff; |
| pMac->lim.tdls_frm_session_id = 0xff; |
| pMac->lim.deferredMsgCnt = 0; |
| |
| if (!VOS_IS_STATUS_SUCCESS(vos_lock_init(&pMac->lim.lkPeGlobalLock))) { |
| PELOGE(limLog(pMac, LOGE, FL("pe lock init failed!"));) |
| status = eSIR_FAILURE; |
| goto pe_open_lock_fail; |
| } |
| pMac->lim.deauthMsgCnt = 0; |
| pMac->lim.retry_packet_cnt = 0; |
| pMac->lim.gLimIbssRetryCnt = 0; |
| |
| /* |
| * peOpen is successful by now, so it is right time to initialize |
| * MTRACE for PE module. if LIM_TRACE_RECORD is not defined in build file |
| * then nothing will be logged for PE module. |
| */ |
| #ifdef LIM_TRACE_RECORD |
| MTRACE(limTraceInit(pMac)); |
| #endif |
| lim_register_debug_callback(); |
| |
| return status; /* status here will be eSIR_SUCCESS */ |
| |
| pe_open_lock_fail: |
| vos_mem_free(pMac->pmm.gPmmTim.pTim); |
| pMac->pmm.gPmmTim.pTim = NULL; |
| pe_open_ptim_fail: |
| vos_mem_free(pMac->lim.gpSession); |
| pMac->lim.gpSession = NULL; |
| pe_open_psession_fail: |
| vos_mem_free(pMac->lim.limTimers.gpLimCnfWaitTimer); |
| pMac->lim.limTimers.gpLimCnfWaitTimer = NULL; |
| |
| return status; |
| } |
| |
| #ifdef FEATURE_OEM_DATA_SUPPORT |
| static void lim_free_oem_data_req(tpAniSirGlobal mac) |
| { |
| if (mac->lim.gpLimMlmOemDataReq) { |
| if (mac->lim.gpLimMlmOemDataReq->data) { |
| vos_mem_free(mac->lim.gpLimMlmOemDataReq->data); |
| mac->lim.gpLimMlmOemDataReq->data = NULL; |
| } |
| vos_mem_free(mac->lim.gpLimMlmOemDataReq); |
| mac->lim.gpLimMlmOemDataReq = NULL; |
| } |
| } |
| #else |
| static inline void lim_free_oem_data_req(tpAniSirGlobal mac) |
| { |
| } |
| #endif |
| |
| /** ------------------------------------------------------------- |
| \fn peClose |
| \brief will be called in close sequence from macClose |
| \param tpAniSirGlobal pMac |
| \return tSirRetStatus |
| -------------------------------------------------------------*/ |
| |
| tSirRetStatus peClose(tpAniSirGlobal pMac) |
| { |
| tANI_U8 i; |
| |
| if (ANI_DRIVER_TYPE(pMac) == eDRIVER_TYPE_MFG) |
| return eSIR_SUCCESS; |
| |
| for(i =0; i < pMac->lim.maxBssId; i++) |
| { |
| if(pMac->lim.gpSession[i].valid == TRUE) |
| { |
| peDeleteSession(pMac,&pMac->lim.gpSession[i]); |
| } |
| } |
| vos_mem_free(pMac->lim.limTimers.gpLimCnfWaitTimer); |
| pMac->lim.limTimers.gpLimCnfWaitTimer = NULL; |
| lim_free_oem_data_req(pMac); |
| vos_mem_free(pMac->lim.gpSession); |
| pMac->lim.gpSession = NULL; |
| vos_mem_free(pMac->pmm.gPmmTim.pTim); |
| pMac->pmm.gPmmTim.pTim = NULL; |
| if( !VOS_IS_STATUS_SUCCESS( vos_lock_destroy( &pMac->lim.lkPeGlobalLock ) ) ) |
| { |
| return eSIR_FAILURE; |
| } |
| return eSIR_SUCCESS; |
| } |
| |
| /** ------------------------------------------------------------- |
| \fn peStart |
| \brief will be called in start sequence from macStart |
| \param tpAniSirGlobal pMac |
| \return none |
| -------------------------------------------------------------*/ |
| |
| tSirRetStatus peStart(tpAniSirGlobal pMac) |
| { |
| tSirRetStatus status = eSIR_SUCCESS; |
| |
| status = limInitialize(pMac); |
| #if defined(ANI_LOGDUMP) |
| limDumpInit(pMac); |
| #endif //#if defined(ANI_LOGDUMP) |
| |
| return status; |
| } |
| |
| /** ------------------------------------------------------------- |
| \fn peStop |
| \brief will be called in stop sequence from macStop |
| \param tpAniSirGlobal pMac |
| \return none |
| -------------------------------------------------------------*/ |
| |
| void peStop(tpAniSirGlobal pMac) |
| { |
| limCleanup(pMac); |
| SET_LIM_MLM_STATE(pMac, eLIM_MLM_OFFLINE_STATE); |
| return; |
| } |
| |
| /** ------------------------------------------------------------- |
| \fn peFreeMsg |
| \brief Called by VOS scheduler (function vos_sched_flush_mc_mqs) |
| \ to free a given PE message on the TX and MC thread. |
| \ This happens when there are messages pending in the PE |
| \ queue when system is being stopped and reset. |
| \param tpAniSirGlobal pMac |
| \param tSirMsgQ pMsg |
| \return none |
| -----------------------------------------------------------------*/ |
| v_VOID_t peFreeMsg( tpAniSirGlobal pMac, tSirMsgQ* pMsg) |
| { |
| if (pMsg != NULL) |
| { |
| if (NULL != pMsg->bodyptr) |
| { |
| if (SIR_BB_XPORT_MGMT_MSG == pMsg->type) |
| { |
| vos_pkt_return_packet((vos_pkt_t *)pMsg->bodyptr); |
| } |
| else |
| { |
| vos_mem_free((v_VOID_t*)pMsg->bodyptr); |
| } |
| } |
| pMsg->bodyptr = 0; |
| pMsg->bodyval = 0; |
| pMsg->type = 0; |
| } |
| return; |
| } |
| |
| |
| /** |
| * The function checks if a particular timer should be allowed |
| * into LIM while device is sleeping |
| */ |
| tANI_U8 limIsTimerAllowedInPowerSaveState(tpAniSirGlobal pMac, tSirMsgQ *pMsg) |
| { |
| tANI_U8 retStatus = TRUE; |
| |
| if(!limIsSystemInActiveState(pMac)) |
| { |
| switch(pMsg->type) |
| { |
| /* Don't allow following timer messages if in sleep */ |
| case SIR_LIM_MIN_CHANNEL_TIMEOUT: |
| case SIR_LIM_MAX_CHANNEL_TIMEOUT: |
| case SIR_LIM_PERIODIC_PROBE_REQ_TIMEOUT: |
| retStatus = FALSE; |
| break; |
| /* Safe to allow as of today, this triggers background scan |
| * which will not be started if the device is in power-save mode |
| * might need to block in the future if we decide to implement |
| * spectrum management |
| */ |
| case SIR_LIM_QUIET_TIMEOUT: |
| |
| /* Safe to allow as of today, this triggers background scan |
| * which will not be started if the device is in power-save mode |
| * might need to block in the future if we decide to implement |
| * spectrum management |
| */ |
| case SIR_LIM_QUIET_BSS_TIMEOUT: |
| |
| /* Safe to allow this timermessage, triggers background scan |
| * which is blocked in sleep mode |
| */ |
| case SIR_LIM_CHANNEL_SCAN_TIMEOUT: |
| |
| /* Safe to allow this timer, since, while in IMPS this timer will not |
| * be started. In case of BMPS sleep, SoftMAC handles the heart-beat |
| * when heart-beat control is handled back to PE, device would have |
| * already woken-up due to EXIT_BMPS_IND mesage from SoftMAC |
| */ |
| case SIR_LIM_HEART_BEAT_TIMEOUT: |
| case SIR_LIM_PROBE_HB_FAILURE_TIMEOUT: |
| |
| /* Safe to allow, PE is not handling this message as of now. May need |
| * to block it, basically, free the buffer and restart the timer |
| */ |
| case SIR_LIM_REASSOC_FAIL_TIMEOUT: |
| case SIR_LIM_JOIN_FAIL_TIMEOUT: |
| case SIR_LIM_PERIODIC_JOIN_PROBE_REQ_TIMEOUT: |
| case SIR_LIM_ASSOC_FAIL_TIMEOUT: |
| case SIR_LIM_AUTH_FAIL_TIMEOUT: |
| case SIR_LIM_ADDTS_RSP_TIMEOUT: |
| case SIR_LIM_AUTH_RETRY_TIMEOUT: |
| retStatus = TRUE; |
| break; |
| |
| /* by default allow rest of messages */ |
| default: |
| retStatus = TRUE; |
| break; |
| |
| |
| } |
| } |
| |
| return retStatus; |
| |
| } |
| |
| |
| |
| /** |
| * limPostMsgApi() |
| * |
| *FUNCTION: |
| * This function is called from other thread while posting a |
| * message to LIM message Queue gSirLimMsgQ. |
| * |
| *LOGIC: |
| * NA |
| * |
| *ASSUMPTIONS: |
| * NA |
| * |
| *NOTE: |
| * NA |
| * |
| * @param pMac - Pointer to Global MAC structure |
| * @param pMsg - Pointer to the message structure |
| * @return None |
| */ |
| |
| tANI_U32 |
| limPostMsgApi(tpAniSirGlobal pMac, tSirMsgQ *pMsg) |
| { |
| return vos_mq_post_message(VOS_MQ_ID_PE, (vos_msg_t *) pMsg); |
| |
| |
| } /*** end limPostMsgApi() ***/ |
| |
| /** |
| * lim_post_msg_high_pri() - posts high priority pe message |
| * @mac: mac context |
| * @msg: message to be posted |
| * |
| * This function is used to post high priority pe message |
| * |
| * Return: returns value returned by vos_mq_post_message_by_priority |
| */ |
| uint32_t |
| lim_post_msg_high_pri(tpAniSirGlobal mac, tSirMsgQ *msg) |
| { |
| return vos_mq_post_message_by_priority(VOS_MQ_ID_PE, (vos_msg_t *)msg, |
| HIGH_PRIORITY); |
| } |
| |
| /*-------------------------------------------------------------------------- |
| |
| \brief pePostMsgApi() - A wrapper function to post message to Voss msg queues |
| |
| This function can be called by legacy code to post message to voss queues OR |
| legacy code may keep on invoking 'limPostMsgApi' to post the message to voss queue |
| for dispatching it later. |
| |
| \param pMac - Pointer to Global MAC structure |
| \param pMsg - Pointer to the message structure |
| |
| \return tANI_U32 - TX_SUCCESS for success. |
| |
| --------------------------------------------------------------------------*/ |
| |
| tSirRetStatus pePostMsgApi(tpAniSirGlobal pMac, tSirMsgQ *pMsg) |
| { |
| return (tSirRetStatus)limPostMsgApi(pMac, pMsg); |
| } |
| |
| /*-------------------------------------------------------------------------- |
| |
| \brief peProcessMessages() - Message Processor for PE |
| |
| Voss calls this function to dispatch the message to PE |
| |
| \param pMac - Pointer to Global MAC structure |
| \param pMsg - Pointer to the message structure |
| |
| \return tANI_U32 - TX_SUCCESS for success. |
| |
| --------------------------------------------------------------------------*/ |
| |
| tSirRetStatus peProcessMessages(tpAniSirGlobal pMac, tSirMsgQ* pMsg) |
| { |
| if (ANI_DRIVER_TYPE(pMac) == eDRIVER_TYPE_MFG) { |
| return eSIR_SUCCESS; |
| } |
| /** |
| * If the Message to be handled is for CFG Module call the CFG Msg Handler |
| * and for all the other cases post it to LIM |
| */ |
| if ( SIR_CFG_PARAM_UPDATE_IND != pMsg->type && IS_CFG_MSG(pMsg->type)) |
| cfgProcessMbMsg(pMac, (tSirMbMsg*)pMsg->bodyptr); |
| else |
| limMessageProcessor(pMac, pMsg); |
| return eSIR_SUCCESS; |
| } |
| |
| |
| |
| // --------------------------------------------------------------------------- |
| /** |
| * peHandleMgmtFrame |
| * |
| * FUNCTION: |
| * Process the Management frames from TL |
| * |
| * LOGIC: |
| * |
| * ASSUMPTIONS: TL sends the packet along with the VOS GlobalContext |
| * |
| * NOTE: |
| * |
| * @param pvosGCtx Global Vos Context |
| * @param vossBuff Packet |
| * @return None |
| */ |
| |
| VOS_STATUS peHandleMgmtFrame( v_PVOID_t pvosGCtx, v_PVOID_t vosBuff) |
| { |
| tpAniSirGlobal pMac; |
| tpSirMacMgmtHdr mHdr; |
| tSirMsgQ msg; |
| vos_pkt_t *pVosPkt; |
| VOS_STATUS vosStatus; |
| v_U8_t *pRxPacketInfo; |
| |
| pVosPkt = (vos_pkt_t *)vosBuff; |
| if (NULL == pVosPkt) |
| { |
| return VOS_STATUS_E_FAILURE; |
| } |
| |
| pMac = (tpAniSirGlobal)vos_get_context(VOS_MODULE_ID_PE, pvosGCtx); |
| if (NULL == pMac) |
| { |
| // cannot log a failure without a valid pMac |
| vos_pkt_return_packet(pVosPkt); |
| pVosPkt = NULL; |
| return VOS_STATUS_E_FAILURE; |
| } |
| |
| vosStatus = WDA_DS_PeekRxPacketInfo( pVosPkt, (void *)&pRxPacketInfo, VOS_FALSE ); |
| |
| if(!VOS_IS_STATUS_SUCCESS(vosStatus)) |
| { |
| vos_pkt_return_packet(pVosPkt); |
| pVosPkt = NULL; |
| return VOS_STATUS_E_FAILURE; |
| } |
| |
| |
| // |
| // The MPDU header is now present at a certain "offset" in |
| // the BD and is specified in the BD itself |
| // |
| |
| mHdr = WDA_GET_RX_MAC_HEADER(pRxPacketInfo); |
| if(mHdr->fc.type == SIR_MAC_MGMT_FRAME) { |
| limLog(pMac, LOG2, |
| FL("Type: %d Subtype: %d from: " MAC_ADDRESS_STR " with Seq no %d"), |
| mHdr->fc.type, mHdr->fc.subType, MAC_ADDR_ARRAY(mHdr->sa), |
| ((mHdr->seqControl.seqNumHi << 4) | |
| (mHdr->seqControl.seqNumLo))); |
| |
| #ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD |
| if (WDA_GET_ROAMCANDIDATEIND(pRxPacketInfo)) |
| limLog(pMac, LOG1, FL("roamCandidateInd %d"), |
| WDA_GET_ROAMCANDIDATEIND(pRxPacketInfo)); |
| |
| if (WDA_GET_OFFLOADSCANLEARN(pRxPacketInfo)) |
| limLog(pMac, LOG1, FL("offloadScanLearn %d"), |
| WDA_GET_OFFLOADSCANLEARN(pRxPacketInfo)); |
| #endif |
| |
| if ((mHdr->fc.subType != SIR_MAC_MGMT_BEACON) && gpe_packetdump_cb) |
| gpe_packetdump_cb(pVosPkt->pkt_buf, VOS_STATUS_SUCCESS, |
| pVosPkt->pkt_meta.sessionId, RX_MGMT_PKT); |
| } |
| |
| |
| // Forward to MAC via mesg = SIR_BB_XPORT_MGMT_MSG |
| msg.type = SIR_BB_XPORT_MGMT_MSG; |
| msg.bodyptr = vosBuff; |
| msg.bodyval = 0; |
| |
| if( eSIR_SUCCESS != sysBbtProcessMessageCore( pMac, |
| &msg, |
| mHdr->fc.type, |
| mHdr->fc.subType )) |
| { |
| vos_pkt_return_packet(pVosPkt); |
| pVosPkt = NULL; |
| return VOS_STATUS_E_FAILURE; |
| } |
| |
| return VOS_STATUS_SUCCESS; |
| } |
| |
| // --------------------------------------------------------------------------- |
| /** |
| * peRegisterTLHandle |
| * |
| * FUNCTION: |
| * Registers the Handler which, process the Management frames from TL |
| * |
| * LOGIC: |
| * |
| * ASSUMPTIONS: |
| * |
| * NOTE: |
| * |
| * @return None |
| */ |
| |
| void peRegisterTLHandle(tpAniSirGlobal pMac) |
| { |
| v_PVOID_t pvosGCTx; |
| VOS_STATUS retStatus; |
| |
| pvosGCTx = vos_get_global_context(VOS_MODULE_ID_PE, (v_VOID_t *) pMac); |
| |
| retStatus = WLANTL_RegisterMgmtFrmClient(pvosGCTx, peHandleMgmtFrame); |
| |
| if (retStatus != VOS_STATUS_SUCCESS) |
| limLog( pMac, LOGP, FL("Registering the PE Handle with TL has failed bailing out...")); |
| |
| } |
| |
| |
| /** |
| * limIsSystemInScanState() |
| * |
| *FUNCTION: |
| * This function is called by various MAC software modules to |
| * determine if System is in Scan/Learn state |
| * |
| *LOGIC: |
| * NA |
| * |
| *ASSUMPTIONS: |
| * NA |
| * |
| *NOTE: |
| * |
| * @param pMac - Pointer to Global MAC structure |
| * @return true - System is in Scan/Learn state |
| * false - System is NOT in Scan/Learn state |
| */ |
| |
| tANI_U8 |
| limIsSystemInScanState(tpAniSirGlobal pMac) |
| { |
| switch (pMac->lim.gLimSmeState) |
| { |
| case eLIM_SME_CHANNEL_SCAN_STATE: |
| case eLIM_SME_NORMAL_CHANNEL_SCAN_STATE: |
| case eLIM_SME_LINK_EST_WT_SCAN_STATE: |
| case eLIM_SME_WT_SCAN_STATE: |
| // System is in Learn mode |
| return true; |
| |
| default: |
| // System is NOT in Learn mode |
| return false; |
| } |
| } /*** end limIsSystemInScanState() ***/ |
| |
| |
| |
| /** |
| * limIsSystemInActiveState() |
| * |
| *FUNCTION: |
| * This function is called by various MAC software modules to |
| * determine if System is in Active/Wakeup state |
| * |
| *LOGIC: |
| * NA |
| * |
| *ASSUMPTIONS: |
| * NA |
| * |
| *NOTE: |
| * |
| * @param pMac - Pointer to Global MAC structure |
| * @return true - System is in Active state |
| * false - System is not in Active state |
| */ |
| |
| tANI_U8 limIsSystemInActiveState(tpAniSirGlobal pMac) |
| { |
| switch (pMac->pmm.gPmmState) |
| { |
| case ePMM_STATE_BMPS_WAKEUP: |
| case ePMM_STATE_IMPS_WAKEUP: |
| case ePMM_STATE_READY: |
| // System is in Active mode |
| return true; |
| default: |
| return false; |
| // System is NOT in Active mode |
| } |
| } |
| |
| |
| |
| |
| |
| /** |
| *\brief limReceivedHBHandler() |
| * |
| * This function is called by schBeaconProcess() upon |
| * receiving a Beacon on STA. This also gets called upon |
| * receiving Probe Response after heat beat failure is |
| * detected. |
| * |
| * param pMac - global mac structure |
| * param channel - channel number indicated in Beacon, Probe Response |
| * return - none |
| */ |
| |
| |
| void |
| limReceivedHBHandler(tpAniSirGlobal pMac, tANI_U8 channelId, tpPESession psessionEntry) |
| { |
| if((channelId == 0 ) || (channelId == psessionEntry->currentOperChannel) ) |
| psessionEntry->LimRxedBeaconCntDuringHB++; |
| |
| if(pMac->psOffloadEnabled) |
| psessionEntry->pmmOffloadInfo.bcnmiss = FALSE; |
| else |
| pMac->pmm.inMissedBeaconScenario = FALSE; |
| } /*** end limReceivedHBHandler() ***/ |
| |
| |
| |
| /** ------------------------------------------------------------- |
| \fn limUpdateOverlapStaParam |
| \brief Updates overlap cache and param data structure |
| \param tpAniSirGlobal pMac |
| \param tSirMacAddr bssId |
| \param tpLimProtStaParams pStaParams |
| \return None |
| -------------------------------------------------------------*/ |
| void |
| limUpdateOverlapStaParam(tpAniSirGlobal pMac, tSirMacAddr bssId, tpLimProtStaParams pStaParams) |
| { |
| int i; |
| if (!pStaParams->numSta) |
| { |
| vos_mem_copy(pMac->lim.protStaOverlapCache[0].addr, |
| bssId, |
| sizeof(tSirMacAddr)); |
| pMac->lim.protStaOverlapCache[0].active = true; |
| |
| pStaParams->numSta = 1; |
| |
| return; |
| } |
| |
| for (i=0; i<LIM_PROT_STA_OVERLAP_CACHE_SIZE; i++) |
| { |
| if (pMac->lim.protStaOverlapCache[i].active) |
| { |
| if (vos_mem_compare( pMac->lim.protStaOverlapCache[i].addr, |
| bssId, |
| sizeof(tSirMacAddr))) { |
| return; } |
| } |
| else |
| break; |
| } |
| |
| if (i == LIM_PROT_STA_OVERLAP_CACHE_SIZE) |
| { |
| PELOG1(limLog(pMac, LOGW, FL("Overlap cache is full"));) |
| } |
| else |
| { |
| vos_mem_copy(pMac->lim.protStaOverlapCache[i].addr, |
| bssId, |
| sizeof(tSirMacAddr)); |
| pMac->lim.protStaOverlapCache[i].active = true; |
| |
| pStaParams->numSta++; |
| } |
| } |
| |
| |
| /** |
| * limIbssEncTypeMatched |
| * |
| *FUNCTION: |
| * This function compares the encryption type of the peer with self |
| * while operating in IBSS mode and detects mismatch. |
| * |
| *LOGIC: |
| * |
| *ASSUMPTIONS: |
| * |
| *NOTE: |
| * |
| * @param pBeacon - Parsed Beacon Frame structure |
| * @param pSession - Pointer to the PE session |
| * |
| * @return eSIR_TRUE if encryption type is matched; eSIR_FALSE otherwise |
| */ |
| static tAniBool limIbssEncTypeMatched(tpSchBeaconStruct pBeacon, |
| tpPESession pSession) |
| { |
| if (!pBeacon || !pSession) |
| return eSIR_FALSE; |
| |
| /* Open case */ |
| if (pBeacon->capabilityInfo.privacy == 0 |
| && pSession->encryptType == eSIR_ED_NONE) |
| return eSIR_TRUE; |
| |
| /* WEP case */ |
| if (pBeacon->capabilityInfo.privacy == 1 && pBeacon->wpaPresent == 0 |
| && pBeacon->rsnPresent == 0 |
| && (pSession->encryptType == eSIR_ED_WEP40 |
| || pSession->encryptType == eSIR_ED_WEP104)) |
| return eSIR_TRUE; |
| |
| /* WPA-None case */ |
| if (pBeacon->capabilityInfo.privacy == 1 && pBeacon->wpaPresent == 1 |
| && pBeacon->rsnPresent == 0 |
| && ((pSession->encryptType == eSIR_ED_CCMP) || |
| (pSession->encryptType == eSIR_ED_TKIP))) |
| return eSIR_TRUE; |
| |
| return eSIR_FALSE; |
| } |
| |
| |
| /** |
| * limHandleIBSScoalescing() |
| * |
| *FUNCTION: |
| * This function is called upon receiving Beacon/Probe Response |
| * while operating in IBSS mode. |
| * |
| *LOGIC: |
| * |
| *ASSUMPTIONS: |
| * |
| *NOTE: |
| * |
| * @param pMac - Pointer to Global MAC structure |
| * @param pBeacon - Parsed Beacon Frame structure |
| * @param pRxPacketInfo - Pointer to RX packet info structure |
| * |
| * @return Status whether to process or ignore received Beacon Frame |
| */ |
| |
| tSirRetStatus |
| limHandleIBSScoalescing( |
| tpAniSirGlobal pMac, |
| tpSchBeaconStruct pBeacon, |
| tANI_U8 *pRxPacketInfo,tpPESession psessionEntry) |
| { |
| tpSirMacMgmtHdr pHdr; |
| tSirRetStatus retCode; |
| |
| pHdr = WDA_GET_RX_MAC_HEADER(pRxPacketInfo); |
| |
| /* Ignore the beacon when any of the conditions below is met: |
| 1. The beacon claims no IBSS network |
| 2. SSID in the beacon does not match SSID of self station |
| 3. Operational channel in the beacon does not match self station |
| 4. Encyption type in the beacon does not match with self station |
| */ |
| if ( (!pBeacon->capabilityInfo.ibss) || |
| (limCmpSSid(pMac, &pBeacon->ssId,psessionEntry) != true) || |
| (psessionEntry->currentOperChannel != pBeacon->channelNumber) ) |
| retCode = eSIR_LIM_IGNORE_BEACON; |
| else if (limIbssEncTypeMatched(pBeacon, psessionEntry) != eSIR_TRUE) |
| { |
| PELOG3(limLog(pMac, LOG3, |
| FL("peer privacy %d peer wpa %d peer rsn %d self encType %d"), |
| pBeacon->capabilityInfo.privacy, |
| pBeacon->wpaPresent, |
| pBeacon->rsnPresent, |
| psessionEntry->encryptType);) |
| retCode = eSIR_LIM_IGNORE_BEACON; |
| } |
| else |
| { |
| tANI_U32 ieLen; |
| tANI_U16 tsfLater; |
| tANI_U8 *pIEs; |
| ieLen = WDA_GET_RX_PAYLOAD_LEN(pRxPacketInfo); |
| tsfLater = WDA_GET_RX_TSF_LATER(pRxPacketInfo); |
| pIEs = WDA_GET_RX_MPDU_DATA(pRxPacketInfo); |
| PELOG3(limLog(pMac, LOG3, FL("BEFORE Coalescing tsfLater val :%d"), tsfLater);) |
| retCode = limIbssCoalesce(pMac, pHdr, pBeacon, pIEs, ieLen, tsfLater,psessionEntry); |
| } |
| return retCode; |
| } /*** end limHandleIBSScoalescing() ***/ |
| |
| /** |
| * lim_enc_type_matched() - matches security type of incoming beracon with |
| * current |
| * @mac_ctx Pointer to Global MAC structure |
| * @bcn Pointer to parsed Beacon structure |
| * @session PE session entry |
| * |
| * This function matches security type of incoming beracon with current |
| * |
| * @return true if matched, false otherwise |
| */ |
| static bool |
| lim_enc_type_matched(tpAniSirGlobal mac_ctx, |
| tpSchBeaconStruct bcn, |
| tpPESession session) |
| { |
| if (!bcn || !session) |
| return false; |
| |
| limLog(mac_ctx, LOG1, |
| FL("Beacon/Probe:: Privacy :%d WPA Present:%d RSN Present: %d"), |
| bcn->capabilityInfo.privacy, bcn->wpaPresent, |
| bcn->rsnPresent); |
| limLog(mac_ctx, LOG1, |
| FL("session:: Privacy :%d EncyptionType: %d OSEN %d WPS %d"), |
| SIR_MAC_GET_PRIVACY(session->limCurrentBssCaps), |
| session->encryptType, session->osen_association, |
| session->wps_registration); |
| |
| /* This is handled by sending probe req due to IOT issues so return TRUE */ |
| if ((bcn->capabilityInfo.privacy) != |
| SIR_MAC_GET_PRIVACY(session->limCurrentBssCaps)) { |
| limLog(mac_ctx, LOGW, FL("Privacy bit miss match\n")); |
| return true; |
| } |
| |
| /* Open */ |
| if ((bcn->capabilityInfo.privacy == 0) |
| && (session->encryptType == eSIR_ED_NONE)) |
| return true; |
| |
| /* WEP */ |
| if ((bcn->capabilityInfo.privacy == 1) |
| && (bcn->wpaPresent == 0) |
| && (bcn->rsnPresent == 0) |
| && ((session->encryptType == eSIR_ED_WEP40) |
| || (session->encryptType == eSIR_ED_WEP104) |
| #ifdef FEATURE_WLAN_WAPI |
| || (session->encryptType == eSIR_ED_WPI) |
| #endif |
| )) |
| return true; |
| |
| /* WPA OR RSN*/ |
| if ((bcn->capabilityInfo.privacy == 1) |
| && ((bcn->wpaPresent == 1) || (bcn->rsnPresent == 1)) |
| && ((session->encryptType == eSIR_ED_TKIP) |
| || (session->encryptType == eSIR_ED_CCMP) |
| || (session->encryptType == eSIR_ED_AES_128_CMAC))) |
| return true; |
| |
| /* For HS2.0, RSN ie is not present |
| * in beacon. Therefore no need to |
| * check for security type in case |
| * OSEN session. |
| * For WPS registration session no need to |
| * detect security mismatch as it won't match and |
| * driver may end up sending probe request without |
| * WPS IE during WPS registration process. |
| */ |
| /*TODO: AP capability mismatch |
| * is not checked here because |
| * no logic for beacon parsing |
| * is avilable for HS2.0 |
| */ |
| if (session->osen_association || |
| session->wps_registration) |
| return eSIR_TRUE; |
| |
| return false; |
| } |
| |
| /** |
| * limDetectChangeInApCapabilities() |
| * |
| *FUNCTION: |
| * This function is called while SCH is processing |
| * received Beacon from AP on STA to detect any |
| * change in AP's capabilities. If there any change |
| * is detected, Roaming is informed of such change |
| * so that it can trigger reassociation. |
| * |
| *LOGIC: |
| * |
| *ASSUMPTIONS: |
| * |
| *NOTE: |
| * Notification is enabled for STA product only since |
| * it is not a requirement on BP side. |
| * |
| * @param pMac Pointer to Global MAC structure |
| * @param pBeacon Pointer to parsed Beacon structure |
| * @return None |
| */ |
| |
| void |
| limDetectChangeInApCapabilities(tpAniSirGlobal pMac, |
| tpSirProbeRespBeacon pBeacon, |
| tpPESession psessionEntry) |
| { |
| tANI_U8 len; |
| tSirSmeApNewCaps apNewCaps; |
| tANI_U8 newChannel; |
| bool security_caps_matched = true; |
| tSirRetStatus status = eSIR_SUCCESS; |
| apNewCaps.capabilityInfo = limGetU16((tANI_U8 *) &pBeacon->capabilityInfo); |
| newChannel = (tANI_U8) pBeacon->channelNumber; |
| |
| security_caps_matched = lim_enc_type_matched(pMac, pBeacon, psessionEntry); |
| if ( ( false == psessionEntry->limSentCapsChangeNtf ) && |
| ( ( ( !limIsNullSsid(&pBeacon->ssId) ) && |
| ( false == limCmpSSid(pMac, &pBeacon->ssId, psessionEntry) ) ) || |
| ( (SIR_MAC_GET_ESS(apNewCaps.capabilityInfo) != |
| SIR_MAC_GET_ESS(psessionEntry->limCurrentBssCaps) ) || |
| ( SIR_MAC_GET_PRIVACY(apNewCaps.capabilityInfo) != |
| SIR_MAC_GET_PRIVACY(psessionEntry->limCurrentBssCaps) ) || |
| ( SIR_MAC_GET_SHORT_PREAMBLE(apNewCaps.capabilityInfo) != |
| SIR_MAC_GET_SHORT_PREAMBLE(psessionEntry->limCurrentBssCaps) ) || |
| ( SIR_MAC_GET_QOS(apNewCaps.capabilityInfo) != |
| SIR_MAC_GET_QOS(psessionEntry->limCurrentBssCaps) ) || |
| ( (newChannel != psessionEntry->currentOperChannel) && |
| (newChannel != 0) ) || |
| (eSIR_FALSE == security_caps_matched) |
| ) ) ) |
| { |
| if (false == psessionEntry->fWaitForProbeRsp) |
| { |
| /* If Beacon capabilities is not matching with the current capability, |
| * then send unicast probe request to AP and take decision after |
| * receiving probe response */ |
| if ( true == psessionEntry->fIgnoreCapsChange ) |
| { |
| limLog(pMac, LOGW, FL("Ignoring the Capability change as it is false alarm")); |
| return; |
| } |
| psessionEntry->fWaitForProbeRsp = true; |
| limLog(pMac, LOGW, FL("AP capabilities are not matching," |
| "sending directed probe request.. ")); |
| status = limSendProbeReqMgmtFrame(pMac, &psessionEntry->ssId, psessionEntry->bssId, |
| psessionEntry->currentOperChannel,psessionEntry->selfMacAddr, |
| psessionEntry->dot11mode, 0, NULL); |
| |
| if ( eSIR_SUCCESS != status ) |
| { |
| limLog(pMac, LOGE, FL("send ProbeReq failed")); |
| psessionEntry->fWaitForProbeRsp = false; |
| } |
| return; |
| } |
| /** |
| * BSS capabilities have changed. |
| * Inform Roaming. |
| */ |
| len = sizeof(tSirMacCapabilityInfo) + |
| sizeof(tSirMacAddr) + sizeof(tANI_U8) + |
| 3 * sizeof(tANI_U8) + // reserved fields |
| pBeacon->ssId.length + 1; |
| |
| vos_mem_copy(apNewCaps.bssId, |
| psessionEntry->bssId, |
| sizeof(tSirMacAddr)); |
| if (newChannel != psessionEntry->currentOperChannel) |
| { |
| PELOGE(limLog(pMac, LOGE, FL("Channel Change from %d --> %d - " |
| "Ignoring beacon!"), |
| psessionEntry->currentOperChannel, newChannel);) |
| return; |
| } |
| |
| /** |
| * When Cisco 1262 Enterprise APs are configured with WPA2-PSK with |
| * AES+TKIP Pairwise ciphers and WEP-40 Group cipher, they do not set |
| * the privacy bit in Beacons (wpa/rsnie is still present in beacons), |
| * the privacy bit is set in Probe and association responses. |
| * Due to this anomaly, we detect a change in |
| * AP capabilities when we receive a beacon after association and |
| * disconnect from the AP. The following check makes sure that we can |
| * connect to such APs |
| */ |
| else if ((SIR_MAC_GET_PRIVACY(apNewCaps.capabilityInfo) == 0) && |
| (pBeacon->rsnPresent || pBeacon->wpaPresent)) |
| { |
| PELOGE(limLog(pMac, LOGE, FL("BSS Caps (Privacy) bit 0 in beacon," |
| " but WPA or RSN IE present, Ignore Beacon!"));) |
| return; |
| } |
| else |
| apNewCaps.channelId = psessionEntry->currentOperChannel; |
| vos_mem_copy((tANI_U8 *) &apNewCaps.ssId, |
| (tANI_U8 *) &pBeacon->ssId, |
| pBeacon->ssId.length + 1); |
| |
| psessionEntry->fIgnoreCapsChange = false; |
| psessionEntry->fWaitForProbeRsp = false; |
| psessionEntry->limSentCapsChangeNtf = true; |
| limSendSmeWmStatusChangeNtf(pMac, eSIR_SME_AP_CAPS_CHANGED, |
| (tANI_U32 *) &apNewCaps, |
| len, psessionEntry->smeSessionId); |
| } |
| else if ( true == psessionEntry->fWaitForProbeRsp ) |
| { |
| /* Only for probe response frames and matching capabilities the control |
| * will come here. If beacon is with broadcast ssid then fWaitForProbeRsp |
| * will be false, the control will not come here*/ |
| |
| limLog(pMac, LOG1, FL("capabilities in probe response are" |
| "matching with the current setting," |
| "Ignoring subsequent capability" |
| "mismatch")); |
| psessionEntry->fIgnoreCapsChange = true; |
| psessionEntry->fWaitForProbeRsp = false; |
| } |
| |
| } /*** limDetectChangeInApCapabilities() ***/ |
| |
| |
| |
| |
| // --------------------------------------------------------------------- |
| /** |
| * limUpdateShortSlot |
| * |
| * FUNCTION: |
| * Enable/Disable short slot |
| * |
| * LOGIC: |
| * |
| * ASSUMPTIONS: |
| * |
| * NOTE: |
| * |
| * @param enable Flag to enable/disable short slot |
| * @return None |
| */ |
| |
| tSirRetStatus limUpdateShortSlot(tpAniSirGlobal pMac, tpSirProbeRespBeacon pBeacon, tpUpdateBeaconParams pBeaconParams,tpPESession psessionEntry) |
| { |
| |
| tSirSmeApNewCaps apNewCaps; |
| tANI_U32 nShortSlot; |
| tANI_U32 val = 0; |
| tANI_U32 phyMode; |
| |
| // Check Admin mode first. If it is disabled just return |
| if (wlan_cfgGetInt(pMac, WNI_CFG_11G_SHORT_SLOT_TIME_ENABLED, &val) |
| != eSIR_SUCCESS) |
| { |
| limLog(pMac, LOGP, |
| FL("cfg get WNI_CFG_11G_SHORT_SLOT_TIME failed")); |
| return eSIR_FAILURE; |
| } |
| if (val == false) |
| return eSIR_SUCCESS; |
| |
| // Check for 11a mode or 11b mode. In both cases return since slot time is constant and cannot/should not change in beacon |
| limGetPhyMode(pMac, &phyMode, psessionEntry); |
| if ((phyMode == WNI_CFG_PHY_MODE_11A) || (phyMode == WNI_CFG_PHY_MODE_11B)) |
| return eSIR_SUCCESS; |
| |
| apNewCaps.capabilityInfo = limGetU16((tANI_U8 *) &pBeacon->capabilityInfo); |
| |
| // Earlier implementation: determine the appropriate short slot mode based on AP advertised modes |
| // when erp is present, apply short slot always unless, prot=on && shortSlot=off |
| // if no erp present, use short slot based on current ap caps |
| |
| // Issue with earlier implementation : Cisco 1231 BG has shortSlot = 0, erpIEPresent and useProtection = 0 (Case4); |
| |
| //Resolution : always use the shortSlot setting the capability info to decide slot time. |
| // The difference between the earlier implementation and the new one is only Case4. |
| /* |
| ERP IE Present | useProtection | shortSlot = QC STA Short Slot |
| Case1 1 1 1 1 //AP should not advertise this combination. |
| Case2 1 1 0 0 |
| Case3 1 0 1 1 |
| Case4 1 0 0 0 |
| Case5 0 1 1 1 |
| Case6 0 1 0 0 |
| Case7 0 0 1 1 |
| Case8 0 0 0 0 |
| */ |
| nShortSlot = SIR_MAC_GET_SHORT_SLOT_TIME(apNewCaps.capabilityInfo); |
| |
| if (nShortSlot != psessionEntry->shortSlotTimeSupported) |
| { |
| // Short slot time capability of AP has changed. Adopt to it. |
| PELOG1(limLog(pMac, LOG1, FL("Shortslot capability of AP changed: %d"), nShortSlot);) |
| ((tpSirMacCapabilityInfo)&psessionEntry->limCurrentBssCaps)->shortSlotTime = (tANI_U16)nShortSlot; |
| psessionEntry->shortSlotTimeSupported = nShortSlot; |
| pBeaconParams->fShortSlotTime = (tANI_U8) nShortSlot; |
| pBeaconParams->paramChangeBitmap |= PARAM_SHORT_SLOT_TIME_CHANGED; |
| } |
| return eSIR_SUCCESS; |
| } |
| |
| /** ----------------------------------------------------------------- |
| \brief limHandleMissedBeaconInd() - handles missed beacon indication |
| |
| This function process the SIR_HAL_MISSED_BEACON_IND message from HAL, |
| and invokes limSendExitBmpsInd( ) to send an eWNI_PMC_EXIT_BMPS_IND |
| to SME with reason code 'eSME_MISSED_BEACON_IND_RCVD'. |
| |
| \param pMac - global mac structure |
| \return - none |
| \sa |
| ----------------------------------------------------------------- */ |
| void limHandleMissedBeaconInd(tpAniSirGlobal pMac, tpSirMsgQ pMsg) |
| { |
| #ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE |
| tpSirSmeMissedBeaconInd pSirMissedBeaconInd = |
| (tpSirSmeMissedBeaconInd)pMsg->bodyptr; |
| tpPESession psessionEntry = peFindSessionByBssIdx(pMac,pSirMissedBeaconInd->bssIdx); |
| if (psessionEntry == NULL) |
| { |
| limLog(pMac, LOGE, |
| FL("session does not exist for given BSSIdx:%d"), |
| pSirMissedBeaconInd->bssIdx); |
| return; |
| } |
| #endif |
| if ( (pMac->pmm.gPmmState == ePMM_STATE_BMPS_SLEEP) || |
| (pMac->pmm.gPmmState == ePMM_STATE_UAPSD_SLEEP)|| |
| (pMac->pmm.gPmmState == ePMM_STATE_WOWLAN) ) |
| { |
| pMac->pmm.inMissedBeaconScenario = TRUE; |
| PELOGE(limLog(pMac, LOGE, |
| FL("Sending EXIT_BMPS_IND to SME due to Missed beacon from FW"));) |
| limSendExitBmpsInd(pMac, eSME_MISSED_BEACON_IND_RCVD, psessionEntry); |
| } |
| /* ACTIVE_MODE_HB_OFFLOAD */ |
| #ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE |
| else if(((pMac->pmm.gPmmState == ePMM_STATE_READY) || |
| (pMac->pmm.gPmmState == ePMM_STATE_BMPS_WAKEUP)) && |
| (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE)) |
| { |
| pMac->pmm.inMissedBeaconScenario = TRUE; |
| PELOGE(limLog(pMac, LOGE, FL("Received Heart Beat Failure"));) |
| limMissedBeaconInActiveMode(pMac, psessionEntry); |
| } |
| #endif |
| if (pMac->pmm.inMissedBeaconScenario == TRUE) { |
| limLog(pMac, LOGW, |
| FL("beacon miss handling is already going on for BSSIdx:%d"), |
| pSirMissedBeaconInd->bssIdx); |
| return; |
| } |
| else |
| { |
| limLog(pMac, LOGE, |
| FL("Received SIR_HAL_MISSED_BEACON_IND while in incorrect state: %d"), |
| pMac->pmm.gPmmState); |
| } |
| return; |
| } |
| |
| /** |
| * lim_smps_force_mode_ind() - Process smps force mode event |
| * @mac_ctx: Global MAC pointer |
| * @data: message containing the parameters of the event |
| * |
| * Process the smps force mode event and post message to SME to |
| * invoke the HDD callback |
| * |
| * Return: None |
| */ |
| void lim_smps_force_mode_ind(tpAniSirGlobal mac_ctx, tpSirMsgQ data) |
| { |
| tSirMsgQ msg; |
| tpPESession psession_entry; |
| struct sir_smps_force_mode_event *smps_ind, *param; |
| |
| smps_ind = data->bodyptr; |
| psession_entry = pe_find_session_by_sme_session_id(mac_ctx, |
| smps_ind->vdev_id); |
| if (psession_entry == NULL) { |
| limLog(mac_ctx, LOGE, |
| FL("session does not exist for given BSSIdx: %d"), |
| smps_ind->vdev_id); |
| return; |
| } |
| |
| param = vos_mem_malloc(sizeof(*param)); |
| if (NULL == param) { |
| limLog(mac_ctx, LOGE, FL("Failed to allocate memory")); |
| return; |
| } |
| *param = *smps_ind; |
| |
| msg.type = eWNI_SME_SMPS_FORCE_MODE_IND; |
| msg.bodyptr = param; |
| msg.bodyval = 0; |
| limLog(mac_ctx, LOGE, |
| FL("send eWNI_SME_SMPS_FORCE_MODE_IND to SME")); |
| |
| limSysProcessMmhMsgApi(mac_ctx, &msg, ePROT); |
| return; |
| } |
| |
| void |
| limSendHeartBeatTimeoutInd(tpAniSirGlobal pMac, tpPESession psessionEntry) |
| { |
| tANI_U32 statusCode; |
| tSirMsgQ msg; |
| |
| /* Prepare and post message to LIM Message Queue */ |
| msg.type = (tANI_U16) SIR_LIM_HEART_BEAT_TIMEOUT; |
| msg.bodyptr = psessionEntry; |
| msg.bodyval = 0; |
| limLog(pMac, LOGE, |
| FL("Heartbeat failure from Fw")); |
| |
| statusCode = limPostMsgApi(pMac, &msg); |
| |
| if(statusCode != eSIR_SUCCESS) |
| { |
| limLog(pMac, LOGE, |
| FL("posting message %X to LIM failed, reason=%d"), |
| msg.type, statusCode); |
| } |
| } |
| |
| /** ----------------------------------------------------------------- |
| \brief limPsOffloadHandleMissedBeaconInd() - handles missed beacon indication |
| |
| This function process the SIR_HAL_MISSED_BEACON_IND message from HAL, |
| and invokes limSendExitBmpsInd( ) to send an eWNI_PMC_EXIT_BMPS_IND |
| to SME with reason code 'eSME_MISSED_BEACON_IND_RCVD'. |
| |
| \param pMac - global mac structure |
| \return - none |
| \sa |
| ----------------------------------------------------------------- */ |
| void limPsOffloadHandleMissedBeaconInd(tpAniSirGlobal pMac, tpSirMsgQ pMsg) |
| { |
| tpSirSmeMissedBeaconInd pSirMissedBeaconInd = |
| (tpSirSmeMissedBeaconInd)pMsg->bodyptr; |
| tpPESession psessionEntry = |
| peFindSessionByBssIdx(pMac,pSirMissedBeaconInd->bssIdx); |
| |
| if(!psessionEntry) |
| { |
| limLog(pMac, LOGE, |
| FL("session does not exist for given BSSId")); |
| return; |
| } |
| |
| /* Set Beacon Miss in Powersave Offload */ |
| psessionEntry->pmmOffloadInfo.bcnmiss = TRUE; |
| |
| /* |
| * If the session is in power save state then |
| * first need to come out of power save before |
| * triggering ap probing |
| */ |
| if(psessionEntry->pmmOffloadInfo.psstate == PMM_POWER_SAVE) |
| { |
| PELOGE(limLog(pMac, LOGE, |
| FL("Received Heart Beat Failure in Power Save State"));) |
| |
| /* Send Request for Full Power to SME */ |
| limSendExitBmpsInd(pMac, eSME_MISSED_BEACON_IND_RCVD, psessionEntry); |
| } |
| else |
| { |
| PELOGE(limLog(pMac, LOGE, |
| FL("Received Heart Beat Failure in active state"));) |
| /* Incase of Active state do AP probing immediately */ |
| limSendHeartBeatTimeoutInd(pMac, psessionEntry); |
| } |
| return; |
| } |
| |
| #ifdef WLAN_FEATURE_ROAM_OFFLOAD |
| eHalStatus limRoamFillBssDescr(tpAniSirGlobal pMac, |
| tSirRoamOffloadSynchInd *pRoamOffloadSynchInd) |
| { |
| v_U32_t uLen = 0; |
| tpSirProbeRespBeacon pParsedFrame; |
| tpSirMacMgmtHdr macHeader; |
| tANI_U8 *pBeaconProbeResp; |
| tSirBssDescription *pBssDescr = NULL; |
| |
| pBeaconProbeResp = (tANI_U8 *)pRoamOffloadSynchInd + |
| pRoamOffloadSynchInd->beaconProbeRespOffset; |
| macHeader = (tpSirMacMgmtHdr)pBeaconProbeResp; |
| pParsedFrame = |
| (tpSirProbeRespBeacon) vos_mem_malloc(sizeof(tSirProbeRespBeacon)); |
| if (NULL == pParsedFrame) |
| { |
| VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, |
| "%s: fail to allocate memory for frame",__func__); |
| return eHAL_STATUS_RESOURCES; |
| } |
| |
| if ( pRoamOffloadSynchInd->beaconProbeRespLength <= SIR_MAC_HDR_LEN_3A ) |
| { |
| VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, |
| "%s: Very few bytes in synchInd beacon / probe resp frame! length=%d", |
| __func__, pRoamOffloadSynchInd->beaconProbeRespLength); |
| vos_mem_free(pParsedFrame); |
| return eHAL_STATUS_FAILURE; |
| } |
| |
| VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,"LFR3: Beacon/Prb Rsp:"); |
| VOS_TRACE_HEX_DUMP(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, |
| pBeaconProbeResp, pRoamOffloadSynchInd->beaconProbeRespLength); |
| if (pRoamOffloadSynchInd->isBeacon) { |
| if (sirParseBeaconIE(pMac, pParsedFrame, |
| &pBeaconProbeResp[SIR_MAC_HDR_LEN_3A + SIR_MAC_B_PR_SSID_OFFSET], |
| pRoamOffloadSynchInd->beaconProbeRespLength - |
| SIR_MAC_HDR_LEN_3A) != eSIR_SUCCESS || !pParsedFrame->ssidPresent) { |
| VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, |
| "Parse error Beacon, length=%d", |
| pRoamOffloadSynchInd->beaconProbeRespLength); |
| vos_mem_free(pParsedFrame); |
| return eHAL_STATUS_FAILURE; |
| } |
| } |
| else { |
| if (sirConvertProbeFrame2Struct(pMac, |
| &pBeaconProbeResp[SIR_MAC_HDR_LEN_3A], |
| pRoamOffloadSynchInd->beaconProbeRespLength - SIR_MAC_HDR_LEN_3A, |
| pParsedFrame) != eSIR_SUCCESS || |
| !pParsedFrame->ssidPresent) { |
| VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, |
| "Parse error ProbeResponse, length=%d", |
| pRoamOffloadSynchInd->beaconProbeRespLength); |
| vos_mem_free(pParsedFrame); |
| return eHAL_STATUS_FAILURE; |
| } |
| } |
| /* 24 byte MAC header and 12 byte to ssid IE */ |
| if (pRoamOffloadSynchInd->beaconProbeRespLength > |
| (SIR_MAC_HDR_LEN_3A + SIR_MAC_B_PR_SSID_OFFSET)) { |
| uLen = pRoamOffloadSynchInd->beaconProbeRespLength - |
| (SIR_MAC_HDR_LEN_3A + SIR_MAC_B_PR_SSID_OFFSET); |
| } |
| pRoamOffloadSynchInd->pbssDescription = |
| vos_mem_malloc(sizeof (tSirBssDescription) + uLen); /*De-allocated in |
| csrProcessRoamOffloadSynchInd*/ |
| pBssDescr = pRoamOffloadSynchInd->pbssDescription; |
| if (NULL == pBssDescr) |
| { |
| PELOGE(limLog( pMac, LOGE, "LFR3:Failed to allocate memory");) |
| VOS_ASSERT(pBssDescr != NULL); |
| return eHAL_STATUS_RESOURCES; |
| } |
| vos_mem_zero(pBssDescr, sizeof(tSirBssDescription)); |
| |
| /** |
| * Length of BSS desription is without length of |
| * length itself and length of pointer |
| * that holds ieFields |
| * |
| * tSirBssDescription |
| * +--------+---------------------------------+---------------+ |
| * | length | other fields | pointer to IEs| |
| * +--------+---------------------------------+---------------+ |
| * ^ |
| * ieFields |
| */ |
| pBssDescr->length = (tANI_U16)(offsetof(tSirBssDescription, ieFields[0]) - |
| sizeof(pBssDescr->length) + uLen); |
| |
| if (pParsedFrame->dsParamsPresent) |
| { |
| pBssDescr->channelId = pParsedFrame->channelNumber; |
| } |
| else if (pParsedFrame->HTInfo.present) |
| { |
| pBssDescr->channelId = pParsedFrame->HTInfo.primaryChannel; |
| } |
| else |
| { |
| /*If DS Params or HTIE is not present in the probe resp or beacon, |
| * then use the channel frequency provided by firmware to fill the |
| * channel in the BSS descriptor.*/ |
| pBssDescr->channelId = vos_freq_to_chan(pRoamOffloadSynchInd->chan_freq); |
| } |
| pBssDescr->channelIdSelf = pBssDescr->channelId; |
| |
| if ((pBssDescr->channelId > 0) && (pBssDescr->channelId < 15)) |
| { |
| int i; |
| /* 11b or 11g packet |
| * 11g if extended Rate IE is present or |
| * if there is an A rate in suppRate IE */ |
| for (i = 0; i < pParsedFrame->supportedRates.numRates; i++) { |
| if (sirIsArate(pParsedFrame->supportedRates.rate[i] & 0x7f)) { |
| pBssDescr->nwType = eSIR_11G_NW_TYPE; |
| break; |
| } |
| } |
| if (pParsedFrame->extendedRatesPresent) { |
| pBssDescr->nwType = eSIR_11G_NW_TYPE; |
| } |
| } else { |
| /* 11a packet */ |
| pBssDescr->nwType = eSIR_11A_NW_TYPE; |
| } |
| |
| pBssDescr->sinr = 0; |
| pBssDescr->beaconInterval = pParsedFrame->beaconInterval; |
| pBssDescr->timeStamp[0] = pParsedFrame->timeStamp[0]; |
| pBssDescr->timeStamp[1] = pParsedFrame->timeStamp[1]; |
| vos_mem_copy(&pBssDescr->capabilityInfo, |
| &pBeaconProbeResp[SIR_MAC_HDR_LEN_3A + SIR_MAC_B_PR_CAPAB_OFFSET], 2); |
| vos_mem_copy((tANI_U8 *) &pBssDescr->bssId, |
| (tANI_U8 *) macHeader->bssId, |
| sizeof(tSirMacAddr)); |
| pBssDescr->nReceivedTime = (tANI_TIMESTAMP)palGetTickCount(pMac->hHdd); |
| if(pParsedFrame->mdiePresent) { |
| pBssDescr->mdiePresent = pParsedFrame->mdiePresent; |
| vos_mem_copy((tANI_U8 *)pBssDescr->mdie, (tANI_U8 *)pParsedFrame->mdie, |
| SIR_MDIE_SIZE); |
| } |
| VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_DEBUG, |
| "LFR3:%s:BssDescr Info:", __func__); |
| VOS_TRACE_HEX_DUMP(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_DEBUG, |
| pBssDescr->bssId, sizeof(tSirMacAddr)); |
| VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_DEBUG, |
| "chan=%d, rssi=%d",pBssDescr->channelId,pBssDescr->rssi); |
| if (uLen) |
| { |
| vos_mem_copy(&pBssDescr->ieFields, |
| pBeaconProbeResp + (SIR_MAC_HDR_LEN_3A + SIR_MAC_B_PR_SSID_OFFSET), |
| uLen); |
| } |
| vos_mem_free(pParsedFrame); |
| return eHAL_STATUS_SUCCESS; |
| } |
| |
| /** ----------------------------------------------------------------- |
| * brief limRoamOffloadSynchInd() - Handles Roam Synch Indication |
| * param pMac - global mac structure |
| * return - none |
| ----------------------------------------------------------------- */ |
| void limRoamOffloadSynchInd(tpAniSirGlobal pMac, tpSirMsgQ pMsg) |
| { |
| tpPESession psessionEntry; |
| tpPESession pftSessionEntry; |
| tANI_U8 sessionId; |
| tSirMsgQ mmhMsg; |
| tSirBssDescription *pbssDescription = NULL; |
| tpSirRoamOffloadSynchInd pRoamOffloadSynchInd = |
| (tpSirRoamOffloadSynchInd)pMsg->bodyptr; |
| |
| if (!pRoamOffloadSynchInd) { |
| VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, |
| "LFR3:%s:pRoamOffloadSynchInd is NULL", __func__); |
| return; |
| } |
| VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, |
| "LFR3: Received WDA_ROAM_OFFLOAD_SYNCH_IND"); |
| VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_DEBUG, |
| "LFR3:%s:authStatus=%d, vdevId=%d", __func__, |
| pRoamOffloadSynchInd->authStatus, |
| pRoamOffloadSynchInd->roamedVdevId); |
| VOS_TRACE_HEX_DUMP(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_DEBUG, |
| pRoamOffloadSynchInd->bssId,6); |
| psessionEntry = peFindSessionByBssIdx(pMac, |
| pRoamOffloadSynchInd->roamedVdevId); |
| if (psessionEntry == NULL) { |
| PELOGE(limLog( pMac, LOGE, |
| "%s: LFR3:Unable to find session", __func__);) |
| return; |
| } |
| /* Nothing to be done if the session is not in STA mode */ |
| if (!LIM_IS_STA_ROLE(psessionEntry)) { |
| PELOGE(limLog(pMac, LOGE, FL("psessionEntry is not in STA mode"));) |
| return; |
| } |
| if (!HAL_STATUS_SUCCESS(limRoamFillBssDescr(pMac, |
| pRoamOffloadSynchInd))) { |
| VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, |
| "LFR3:%s:Failed to fill Bss Descr", __func__); |
| return; |
| } |
| pbssDescription = pRoamOffloadSynchInd->pbssDescription; |
| if((pftSessionEntry = peCreateSession(pMac, pbssDescription->bssId, |
| &sessionId, pMac->lim.maxStation, |
| eSIR_INFRASTRUCTURE_MODE)) == NULL) { |
| limLog(pMac, LOGE, FL("LFR3: Session Can not be created for new AP" |
| "during Roam Offload Synch")); |
| limPrintMacAddr( pMac, pbssDescription->bssId, LOGE ); |
| return; |
| } |
| pftSessionEntry->peSessionId = sessionId; |
| sirCopyMacAddr(pftSessionEntry->selfMacAddr, psessionEntry->selfMacAddr); |
| sirCopyMacAddr(pftSessionEntry->limReAssocbssId, pbssDescription->bssId); |
| pftSessionEntry->bssType = eSIR_INFRASTRUCTURE_MODE; |
| /*Set bRoamSynchInProgress here since this session is |
| * specific to roam synch indication. This flag will |
| * later be used to differentiate LFR3 with LFR2 in LIM |
| */ |
| pftSessionEntry->bRoamSynchInProgress = VOS_TRUE; |
| |
| if (pftSessionEntry->bssType == eSIR_INFRASTRUCTURE_MODE) |
| pftSessionEntry->limSystemRole = eLIM_STA_ROLE; |
| else { |
| limLog(pMac, LOGE, FL("LFR3:Invalid bss type")); |
| return; |
| } |
| pftSessionEntry->limPrevSmeState = pftSessionEntry->limSmeState; |
| pftSessionEntry->limSmeState = eLIM_SME_WT_REASSOC_STATE; |
| VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_DEBUG, |
| "LFR3:%s:created session (%pK) with id = %d", |
| __func__, pftSessionEntry, pftSessionEntry->peSessionId); |
| /* Update the ReAssoc BSSID of the current session */ |
| sirCopyMacAddr(psessionEntry->limReAssocbssId, pbssDescription->bssId); |
| limPrintMacAddr(pMac, psessionEntry->limReAssocbssId, LOG2); |
| |
| /* Prepare the session right now with as much as possible */ |
| limFillFTSession(pMac, pbssDescription, pftSessionEntry, psessionEntry); |
| limFTPrepareAddBssReq( pMac, FALSE, pftSessionEntry, pbssDescription ); |
| mmhMsg.type = |
| pRoamOffloadSynchInd->messageType;/* eWNI_SME_ROAM_OFFLOAD_SYNCH_IND */ |
| mmhMsg.bodyptr = pRoamOffloadSynchInd; |
| mmhMsg.bodyval = 0; |
| |
| VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_DEBUG, |
| "LFR3:%s:sending eWNI_SME_ROAM_OFFLOAD_SYNCH_IND", __func__); |
| limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT); |
| } |
| |
| #endif |
| |
| /** |
| * lim_mon_init_session() - create PE session for monitor mode operation |
| * @mac_ptr: mac pointer |
| * @msg: Pointer to struct sir_create_session type. |
| * |
| * Return: NONE |
| */ |
| void lim_mon_init_session(tpAniSirGlobal mac_ptr, |
| struct sir_create_session *msg) |
| { |
| tpPESession psession_entry; |
| uint8_t session_id; |
| |
| if((psession_entry = peCreateSession(mac_ptr, msg->bss_id, |
| &session_id, mac_ptr->lim.maxStation, |
| eSIR_MONITOR_MODE)) == NULL) { |
| limLog(mac_ptr, LOGE, |
| FL("Monitor mode: Session Can not be created")); |
| limPrintMacAddr(mac_ptr, msg->bss_id, LOGE); |
| return; |
| } |
| psession_entry->vhtCapability = 1; |
| psession_entry->sub20_channelwidth = mac_ptr->sub20_channelwidth; |
| } |
| |
| /** ----------------------------------------------------------------- |
| \brief limMicFailureInd() - handles mic failure indication |
| |
| This function process the SIR_HAL_MIC_FAILURE_IND message from HAL, |
| |
| \param pMac - global mac structure |
| \return - none |
| \sa |
| ----------------------------------------------------------------- */ |
| void limMicFailureInd(tpAniSirGlobal pMac, tpSirMsgQ pMsg) |
| { |
| tpSirSmeMicFailureInd pSirSmeMicFailureInd; |
| tpSirSmeMicFailureInd pSirMicFailureInd = (tpSirSmeMicFailureInd)pMsg->bodyptr; |
| tSirMsgQ mmhMsg; |
| tpPESession psessionEntry ; |
| tANI_U8 sessionId; |
| |
| if((psessionEntry = peFindSessionByBssid(pMac,pSirMicFailureInd->bssId,&sessionId))== NULL) |
| { |
| limLog(pMac, LOGE, |
| FL("session does not exist for given BSSId")); |
| return; |
| } |
| |
| pSirSmeMicFailureInd = vos_mem_malloc(sizeof(*pSirSmeMicFailureInd)); |
| if (NULL == pSirSmeMicFailureInd) |
| { |
| // Log error |
| limLog(pMac, LOGP, |
| FL("memory allocate failed for eWNI_SME_MIC_FAILURE_IND")); |
| return; |
| } |
| |
| *pSirSmeMicFailureInd = *pSirMicFailureInd; |
| pSirSmeMicFailureInd->sessionId = psessionEntry->smeSessionId; |
| |
| mmhMsg.type = eWNI_SME_MIC_FAILURE_IND; |
| mmhMsg.bodyptr = pSirSmeMicFailureInd; |
| mmhMsg.bodyval = 0; |
| MTRACE(macTrace(pMac, TRACE_CODE_TX_SME_MSG, sessionId, mmhMsg.type)); |
| limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT); |
| return; |
| } |
| |
| tANI_U8 limIsBeaconMissScenario(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo) |
| { |
| if(pMac->psOffloadEnabled) |
| { |
| tpSirMacMgmtHdr pHdr = WDA_GET_RX_MAC_HEADER(pRxPacketInfo); |
| tANI_U8 sessionId; |
| tpPESession psessionEntry = |
| peFindSessionByBssid(pMac,pHdr->bssId,&sessionId); |
| |
| if(psessionEntry && psessionEntry->pmmOffloadInfo.bcnmiss) |
| return true; |
| } |
| else if(pMac->pmm.inMissedBeaconScenario) |
| { |
| return true; |
| } |
| return false; |
| } |
| |
| /** ----------------------------------------------------------------- |
| \brief limIsPktCandidateForDrop() - decides whether to drop the frame or not |
| |
| This function is called before enqueuing the frame to PE queue for further processing. |
| This prevents unnecessary frames getting into PE Queue and drops them right away. |
| Frames will be droped in the following scenarios: |
| |
| - In Scan State, drop the frames which are not marked as scan frames |
| - In non-Scan state, drop the frames which are marked as scan frames. |
| - Drop INFRA Beacons and Probe Responses in IBSS Mode |
| - Drop the Probe Request in IBSS mode, if STA did not send out the last beacon |
| |
| \param pMac - global mac structure |
| \return - none |
| \sa |
| ----------------------------------------------------------------- */ |
| |
| tMgmtFrmDropReason limIsPktCandidateForDrop(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tANI_U32 subType) |
| { |
| tANI_U32 framelen; |
| tANI_U8 *pBody; |
| tSirMacCapabilityInfo capabilityInfo; |
| tpSirMacMgmtHdr pHdr=NULL; |
| tpPESession psessionEntry=NULL; |
| tANI_U8 sessionId; |
| |
| /* |
| * |
| * In scan mode, drop only Beacon/Probe Response which are NOT marked as scan-frames. |
| * In non-scan mode, drop only Beacon/Probe Response which are marked as scan frames. |
| * Allow other mgmt frames, they must be from our own AP, as we don't allow |
| * other than beacons or probe responses in scan state. |
| */ |
| if( (subType == SIR_MAC_MGMT_BEACON) || |
| (subType == SIR_MAC_MGMT_PROBE_RSP)) |
| { |
| if(limIsBeaconMissScenario(pMac, pRxPacketInfo)) |
| { |
| MTRACE(macTrace(pMac, TRACE_CODE_INFO_LOG, 0, eLOG_NODROP_MISSED_BEACON_SCENARIO)); |
| return eMGMT_DROP_NO_DROP; |
| } |
| if (limIsSystemInScanState(pMac)) |
| { |
| return eMGMT_DROP_NO_DROP; |
| } |
| #ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD |
| else if (WDA_GET_OFFLOADSCANLEARN(pRxPacketInfo) || WDA_GET_ROAMCANDIDATEIND(pRxPacketInfo)) |
| { |
| return eMGMT_DROP_NO_DROP; |
| } |
| #endif |
| else if (WDA_IS_RX_IN_SCAN(pRxPacketInfo)) |
| { |
| return eMGMT_DROP_SCAN_MODE_FRAME; |
| } |
| } |
| |
| framelen = WDA_GET_RX_PAYLOAD_LEN(pRxPacketInfo); |
| pBody = WDA_GET_RX_MPDU_DATA(pRxPacketInfo); |
| |
| //Drop INFRA Beacons and Probe Responses in IBSS Mode |
| if( (subType == SIR_MAC_MGMT_BEACON) || |
| (subType == SIR_MAC_MGMT_PROBE_RSP)) |
| { |
| //drop the frame if length is less than 12 |
| if(framelen < LIM_MIN_BCN_PR_LENGTH) |
| return eMGMT_DROP_INVALID_SIZE; |
| |
| *((tANI_U16*) &capabilityInfo) = sirReadU16(pBody+ LIM_BCN_PR_CAPABILITY_OFFSET); |
| |
| /* Note sure if this is sufficient, basically this condition allows all probe responses and |
| * beacons from an infrastructure network |
| */ |
| if(!capabilityInfo.ibss) |
| return eMGMT_DROP_NO_DROP; |
| |
| //This can be enhanced to even check the SSID before deciding to enque the frame. |
| if(capabilityInfo.ess) |
| return eMGMT_DROP_INFRA_BCN_IN_IBSS; |
| } |
| else if( (subType == SIR_MAC_MGMT_PROBE_REQ) && |
| (!WDA_GET_RX_BEACON_SENT(pRxPacketInfo))) |
| { |
| pHdr = WDA_GET_RX_MAC_HEADER(pRxPacketInfo); |
| psessionEntry = peFindSessionByBssid(pMac, pHdr->bssId, &sessionId); |
| if ((psessionEntry && !LIM_IS_IBSS_ROLE(psessionEntry)) || |
| (!psessionEntry)) |
| return eMGMT_DROP_NO_DROP; |
| |
| //Drop the Probe Request in IBSS mode, if STA did not send out the last beacon |
| //In IBSS, the node which sends out the beacon, is supposed to respond to ProbeReq |
| return eMGMT_DROP_NOT_LAST_IBSS_BCN; |
| } |
| |
| return eMGMT_DROP_NO_DROP; |
| } |
| |
| /** |
| * lim_update_lost_link_info() - update lost link information to SME |
| * @mac: global MAC handle |
| * @session: PE session |
| * @rssi: rssi value from the received frame |
| * |
| * Return: none |
| */ |
| void lim_update_lost_link_info(tpAniSirGlobal mac, tpPESession session, |
| int8_t rssi) |
| { |
| struct sir_lost_link_info *lost_link_info; |
| tSirMsgQ mmh_msg; |
| if ((NULL == mac) || (NULL == session)) { |
| VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, |
| "%s: parameter NULL", __func__); |
| return; |
| } |
| if (!LIM_IS_STA_ROLE(session)) { |
| VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, |
| "%s: not STA mode, do nothing", __func__); |
| return; |
| } |
| |
| lost_link_info = vos_mem_malloc(sizeof(*lost_link_info)); |
| if (NULL == lost_link_info) { |
| VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, |
| "%s: lost_link_info allocation failure", __func__); |
| return; |
| } |
| |
| lost_link_info->vdev_id = session->smeSessionId; |
| lost_link_info->rssi = rssi; |
| mmh_msg.type = eWNI_SME_LOST_LINK_INFO_IND; |
| mmh_msg.bodyptr = lost_link_info; |
| mmh_msg.bodyval = 0; |
| VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, |
| "%s: post eWNI_SME_LOST_LINK_INFO_IND, bss_idx %d, rssi %d", |
| __func__, lost_link_info->vdev_id, lost_link_info->rssi); |
| |
| limSysProcessMmhMsgApi(mac, &mmh_msg, ePROT); |
| } |
| |
| eHalStatus pe_AcquireGlobalLock( tAniSirLim *psPe) |
| { |
| eHalStatus status = eHAL_STATUS_INVALID_PARAMETER; |
| |
| if(psPe) |
| { |
| if( VOS_IS_STATUS_SUCCESS( vos_lock_acquire( &psPe->lkPeGlobalLock) ) ) |
| { |
| status = eHAL_STATUS_SUCCESS; |
| } |
| } |
| return (status); |
| } |
| eHalStatus pe_ReleaseGlobalLock( tAniSirLim *psPe) |
| { |
| eHalStatus status = eHAL_STATUS_INVALID_PARAMETER; |
| if(psPe) |
| { |
| if( VOS_IS_STATUS_SUCCESS( vos_lock_release( &psPe->lkPeGlobalLock) ) ) |
| { |
| status = eHAL_STATUS_SUCCESS; |
| } |
| } |
| return (status); |
| } |
| |
| /** |
| * pe_register_packetdump_callback() - stores rx packet dump |
| * callback handler |
| * @pe_packetdump_cb: packetdump cb |
| * |
| * This function is used to store rx packet dump callback |
| * |
| * Return: None |
| * |
| */ |
| void pe_register_packetdump_callback(tp_pe_packetdump_cb pe_packetdump_cb) |
| { |
| gpe_packetdump_cb = pe_packetdump_cb; |
| } |
| |
| /** |
| * pe_deregister_packetdump_callback() - removes tx packet dump |
| * callback handler |
| * |
| * This function is used to remove rx packet dump callback |
| * |
| * Return: None |
| * |
| */ |
| void pe_deregister_packetdump_callback(void) |
| { |
| gpe_packetdump_cb = NULL; |
| } |