blob: 9aa3d6a2e002d2783efe8b855c536720459c89cc [file] [log] [blame]
/*
* Copyright (c) 2011-2018 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 "wniCfg.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"
#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 "wlan_qct_tl.h"
#include "sysStartup.h"
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);
//pMac->lim.gpLimStartBssReq = NULL;
/* These global variables are moved to session table and intialization is done during session creation Oct 9th Review */
#if 0
// Place holder for BSS description that we're
// currently joined with
vos_mem_set(&pMac->lim.gLimCurrentBssId, sizeof(tSirMacAddr), 0);
pMac->lim.gLimCurrentChannelId = HAL_INVALID_CHANNEL_ID;
vos_mem_set(&pMac->lim.gLimCurrentSSID, sizeof(tSirMacSSid), 0);
pMac->lim.gLimCurrentBssCaps = 0;
QosCaps is a bit map of various qos capabilities - see defn above
pMac->lim.gLimCurrentBssQosCaps = 0;
pMac->lim.gLimCurrentBssPropCap = 0;
pMac->lim.gLimSentCapsChangeNtf = 0;
// Place holder for BSS description that
// we're currently Reassociating
vos_mem_set(&pMac->lim.gLimReassocBssId, sizeof(tSirMacAddr), 0);
pMac->lim.gLimReassocChannelId = 0;
vos_mem_set(&pMac->lim.gLimReassocSSID, sizeof(tSirMacSSid), 0);
pMac->lim.gLimReassocBssCaps = 0;
pMac->lim.gLimReassocBssQosCaps = 0;
pMac->lim.gLimReassocBssPropCap = 0;
#endif
/* This is for testing purposes only, be default should always be off */
pMac->lim.gLimForceNoPropIE = 0;
// pMac->lim.gLimBssIdx = 0;
pMac->lim.gpLimMlmSetKeysReq = NULL;
pMac->lim.gpLimMlmRemoveKeyReq = NULL;
// pMac->lim.gLimStaid = 0; //TO SUPPORT BT-AMP
}
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.gLimNumOfCurrentSTAs = 0;
pMac->lim.gLimNumOfAniSTAs = 0; // count of ANI peers
/// This indicates number of RXed Beacons during HB period
//pMac->lim.gLimRxedBeaconCntDuringHB = 0;
// 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;
#ifdef GEN4_SCAN
// LIM to HAL SCAN Management Message Interface states
pMac->lim.gLimHalScanState = eLIM_HAL_IDLE_SCAN_STATE;
#endif // GEN4_SCAN
/**
* 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;
#if 0 /* Moving all these to session specific elements */
pMac->lim.gLimQosEnabled = 0; //11E
pMac->lim.gLimWmeEnabled = 0; //WME
pMac->lim.gLimWsmEnabled = 0; //WSM
pMac->lim.gLimHcfEnabled = 0;
pMac->lim.gLim11dEnabled = 0;
#endif
pMac->lim.gLimProbeRespDisableFlag = 0; // control over probe response
}
static void __limInitVars(tpAniSirGlobal pMac)
{
// Place holder for Measurement Req/Rsp/Ind related info
// WDS info
pMac->lim.gLimNumWdsInfoInd = 0;
pMac->lim.gLimNumWdsInfoSet = 0;
vos_mem_set(&pMac->lim.gLimWdsInfo, sizeof(tSirWdsInfo), 0);
/* initialize some parameters */
limInitWdsInfoParams(pMac);
// 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);
#if 0
// 11h Spectrum Management Related Flag
LIM_SET_RADAR_DETECTED(pMac, eANI_BOOLEAN_FALSE);
pMac->sys.gSysEnableLearnMode = eANI_BOOLEAN_TRUE;
#endif
// 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;
pMac->lim.txBdToken = 0;
pMac->lim.EnableTdls2040BSSCoexIE = 1;
}
static void __limInitAssocVars(tpAniSirGlobal pMac)
{
tANI_U32 val;
#if 0
vos_mem_set(pMac->lim.gpLimAIDpool,
sizeof(*pMac->lim.gpLimAIDpool) * (WNI_CFG_ASSOC_STA_LIMIT_STAMAX+1), 0);
pMac->lim.freeAidHead = 0;
pMac->lim.freeAidTail = 0;
#endif
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;
// Place holder for current authentication request
// being handled
pMac->lim.gpLimMlmAuthReq = NULL;
//pMac->lim.gpLimMlmJoinReq = 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 __limInitTitanVars(tpAniSirGlobal pMac)
{
#if 0
vos_mem_set(&pMac->lim.gLimChannelSwitch, sizeof(tLimChannelSwitchInfo), 0);
pMac->lim.gLimChannelSwitch.state = eLIM_CHANNEL_SWITCH_IDLE;
pMac->lim.gLimChannelSwitch.secondarySubBand = PHY_SINGLE_CHANNEL_CENTERED;
#endif
// Debug workaround for BEACON's
// State change triggered by "dump 222"
pMac->lim.gLimScanOverride = 1;
pMac->lim.gLimScanOverrideSaved = eSIR_ACTIVE_SCAN;
pMac->lim.gLimTitanStaCount = 0;
pMac->lim.gLimBlockNonTitanSta = 0;
}
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
vos_mem_set(&pMac->lim.staBaInfo, sizeof(pMac->lim.staBaInfo), 0);
}
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;
//channel bonding mode could be set to anything from 0 to 4(Titan had these
// modes But for Taurus we have only two modes: enable(>0) or disable(=0)
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"));)
return eSIR_FAILURE;
}
val16 = ( tANI_U16 ) val1;
pAmpduParamInfo = ( tSirMacHTParametersInfo* ) &val16;
pAmpduParamInfo->maxRxAMPDUFactor = (tANI_U8)val2;
if(cfgSetInt(pMac, WNI_CFG_HT_AMPDU_PARAMS, *(tANI_U8*)pAmpduParamInfo) !=
eSIR_SUCCESS)
{
PELOGE(limLog(pMac, LOGE, FL("could not update HT AMPDU Param CFG"));)
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, LOGE, FL("cfg get short preamble failed"));
return eSIR_FAILURE;
}
/* WNI_CFG_MAX_PS_POLL */
/* 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(wlan_cfgGetInt(pMac, WNI_CFG_DISABLE_LDPC_WITH_TXBF_AP,(tANI_U32 *) &pMac->lim.disableLDPCWithTxbfAP) != eSIR_SUCCESS)
{
limLog(pMac, LOGP, FL("cfg get disableLDPCWithTxbfAP failed"));
return eSIR_FAILURE;
}
#ifdef FEATURE_WLAN_TDLS
if(wlan_cfgGetInt(pMac, WNI_CFG_TDLS_BUF_STA_ENABLED,(tANI_U32 *) &pMac->lim.gLimTDLSBufStaEnabled) != eSIR_SUCCESS)
{
limLog(pMac, LOGP, FL("cfg get LimTDLSBufStaEnabled failed"));
return eSIR_FAILURE;
}
if(wlan_cfgGetInt(pMac, WNI_CFG_TDLS_QOS_WMM_UAPSD_MASK,(tANI_U32 *) &pMac->lim.gLimTDLSUapsdMask) != eSIR_SUCCESS)
{
limLog(pMac, LOGP, FL("cfg get LimTDLSUapsdMask failed"));
return eSIR_FAILURE;
}
if(wlan_cfgGetInt(pMac, WNI_CFG_TDLS_OFF_CHANNEL_ENABLED,(tANI_U32 *) &pMac->lim.gLimTDLSOffChannelEnabled) != eSIR_SUCCESS)
{
limLog(pMac, LOGP, FL("cfg get LimTDLSUapsdMask failed"));
return eSIR_FAILURE;
}
if(wlan_cfgGetInt(pMac, WNI_CFG_TDLS_WMM_MODE_ENABLED,(tANI_U32 *) &pMac->lim.gLimTDLSWmmMode) != eSIR_SUCCESS)
{
limLog(pMac, LOGP, FL("cfg get LimTDLSWmmMode failed"));
return eSIR_FAILURE;
}
#endif
if (eSIR_SUCCESS !=
wlan_cfgGetInt(pMac, WNI_CFG_DEBUG_P2P_REMAIN_ON_CHANNEL,
(tANI_U32 *)&pMac->lim.gDebugP2pRemainOnChannel))
{
limLog( pMac, LOGE,
"%s: Couldn't get WNI_CFG_DEBUG_P2P_REMAIN_ON_CHANNEL value",
__func__);
pMac->lim.gDebugP2pRemainOnChannel = 0;
}
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;
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
limInitMlm(pMac);
// 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 %d"),pMac->lim.gLimSmeState );
retCode = eSIR_FAILURE;
}
return retCode;
}
static void
limInitAssocRspCompletiontionList(tpAniSirGlobal pMac)
{
vos_list_init(&pMac->assoc_rsp_completion_list);
}
static void
limDestroyAssocRspCompletiontionList(tpAniSirGlobal pMac)
{
assoc_rsp_tx_context *pAssocRspCtx;
while(vos_list_remove_front(&pMac->assoc_rsp_completion_list,
(vos_list_node_t**)&pAssocRspCtx) == VOS_STATUS_SUCCESS)
{
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
FL("Fixing leak! Deallocating pAssocRspCtx node %lu"),
(unsigned long)pAssocRspCtx);
vos_mem_free(pAssocRspCtx);
}
vos_list_destroy(&pMac->assoc_rsp_completion_list);
}
/**
* 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);
__limInitTitanVars(pMac);
status = limStart(pMac);
if(eSIR_SUCCESS != status)
{
return status;
}
/*
* MLM will be intitalized when 'START' request comes from SME.
* limInitMlm calls limCreateTimers, which actually relies on
* CFG to be downloaded. So it should not be called as part of
* peStart, as CFG download is happening after peStart.
*/
//limInitMlm(pMac);
// Initializations for maintaining peers in IBSS
limIbssInit(pMac);
limInitAssocRspCompletiontionList(pMac);
pmmInitialize(pMac);
#if defined WLAN_FEATURE_VOWIFI
rrmInitialize(pMac);
#endif
#if defined WLAN_FEATURE_VOWIFI_11R
limFTOpen(pMac);
#endif
#ifdef WLAN_FEATURE_RMC
limRmcInit(pMac);
#endif /* WLAN_FEATURE_RMC */
vos_list_init(&pMac->lim.gLimMgmtFrameRegistratinQueue);
#if 0
vos_trace_setLevel(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR);
vos_trace_setLevel(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_WARN);
vos_trace_setLevel(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_FATAL);
vos_trace_setLevel(VOS_MODULE_ID_HAL, VOS_TRACE_LEVEL_WARN);
vos_trace_setLevel(VOS_MODULE_ID_HAL, VOS_TRACE_LEVEL_ERROR);
vos_trace_setLevel(VOS_MODULE_ID_SYS, VOS_TRACE_LEVEL_WARN);
vos_trace_setLevel(VOS_MODULE_ID_SYS, VOS_TRACE_LEVEL_ERROR);
vos_trace_setLevel(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR);
vos_trace_setLevel(VOS_MODULE_ID_SAL, VOS_TRACE_LEVEL_ERROR);
vos_trace_setLevel(VOS_MODULE_ID_SSC, VOS_TRACE_LEVEL_ERROR);
vos_trace_setLevel(VOS_MODULE_ID_SAL, VOS_TRACE_LEVEL_ERROR);
vos_trace_setLevel(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR);
vos_trace_setLevel(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR);
vos_trace_setLevel(VOS_MODULE_ID_BAL, VOS_TRACE_LEVEL_ERROR);
vos_trace_setLevel(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR);
#endif
//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)
{
v_PVOID_t pvosGCTx;
VOS_STATUS retStatus;
//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.
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);
#ifdef WLAN_FEATURE_RMC
limRmcCleanup(pMac);
#endif /* WLAN_FEATURE_RMC */
// free up preAuth table
if (pMac->lim.gLimPreAuthTimerTable.pTable != NULL)
{
vos_mem_vfree(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 0
if (pMac->lim.gpLimStartBssReq != NULL)
{
vos_mem_free(pMac->lim.gpLimStartBssReq);
pMac->lim.gpLimStartBssReq = NULL;
}
#endif
if (pMac->lim.gpLimMlmSetKeysReq != NULL)
{
vos_mem_free(pMac->lim.gpLimMlmSetKeysReq);
pMac->lim.gpLimMlmSetKeysReq = NULL;
}
#if 0
if (pMac->lim.gpLimJoinReq != NULL)
{
vos_mem_free(pMac->lim.gpLimJoinReq);
pMac->lim.gpLimJoinReq = NULL;
}
#endif
if (pMac->lim.gpLimMlmAuthReq != NULL)
{
vos_mem_free(pMac->lim.gpLimMlmAuthReq);
pMac->lim.gpLimMlmAuthReq = NULL;
}
#if 0
if (pMac->lim.gpLimMlmJoinReq != NULL)
{
vos_mem_free(pMac->lim.gpLimMlmJoinReq);
pMac->lim.gpLimMlmJoinReq = NULL;
}
#endif
#if 0
if (pMac->lim.gpLimReassocReq != NULL)
{
vos_mem_free(pMac->lim.gpLimReassocReq);
pMac->lim.gpLimReassocReq = NULL;
}
#endif
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;
}
limDestroyAssocRspCompletiontionList(pMac);
#if 0
if(NULL != pMac->lim.beacon)
{
vos_mem_free((void*) pMac->lim.beacon);
pMac->lim.beacon = NULL;
}
#endif
#if 0
if(NULL != pMac->lim.assocReq)
{
vos_mem_free((void*) pMac->lim.assocReq);
pMac->lim.assocReq= NULL;
}
#endif
#if 0
if(NULL != pMac->lim.assocRsp)
{
vos_mem_free((void*) pMac->lim.assocRsp);
pMac->lim.assocRsp= NULL;
}
#endif
// Now, finally reset the deferred message queue pointers
limResetDeferredMsgQ(pMac);
pvosGCTx = vos_get_global_context(VOS_MODULE_ID_PE, (v_VOID_t *) pMac);
retStatus = WLANTL_DeRegisterMgmtFrmClient(pvosGCTx);
if ( retStatus != VOS_STATUS_SUCCESS )
PELOGE(limLog(pMac, LOGE, FL("DeRegistering the PE Handle with TL has failed bailing out..."));)
#if defined WLAN_FEATURE_VOWIFI
rrmCleanup(pMac);
#endif
#if defined WLAN_FEATURE_VOWIFI_11R
limFTCleanup(pMac);
#endif
} /*** end limCleanup() ***/
/** -------------------------------------------------------------
\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)
{
if (eDRIVER_TYPE_MFG == pMacOpenParam->driverType)
return eSIR_SUCCESS;
pMac->lim.maxBssId = pMacOpenParam->maxBssId;
pMac->lim.maxStation = pMacOpenParam->maxStation;
vos_spin_lock_init( &pMac->sys.lock );
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_vmalloc(sizeof(TX_TIMER) * pMac->lim.maxStation);
if (NULL == pMac->lim.limTimers.gpLimCnfWaitTimer)
{
PELOGE(limLog(pMac, LOGE, FL("memory allocate failed!"));)
return eSIR_FAILURE;
}
pMac->lim.gpSession = vos_mem_vmalloc(sizeof(tPESession)* pMac->lim.maxBssId);
if (NULL == pMac->lim.gpSession)
{
limLog(pMac, LOGE, FL("memory allocate failed!"));
vos_mem_vfree(pMac->lim.limTimers.gpLimCnfWaitTimer);
return eSIR_FAILURE;
}
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!"));)
vos_mem_vfree(pMac->lim.limTimers.gpLimCnfWaitTimer);
vos_mem_vfree(pMac->lim.gpSession);
return eSIR_FAILURE;
}
vos_mem_set(pMac->pmm.gPmmTim.pTim, sizeof(tANI_U8)*pMac->lim.maxStation, 0);
pMac->lim.mgmtFrameSessionId = 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!"));)
vos_mem_vfree(pMac->lim.limTimers.gpLimCnfWaitTimer);
pMac->lim.limTimers.gpLimCnfWaitTimer = NULL;
vos_mem_vfree(pMac->lim.gpSession);
pMac->lim.gpSession = NULL;
vos_mem_free(pMac->pmm.gPmmTim.pTim);
pMac->pmm.gPmmTim.pTim = NULL;
return eSIR_FAILURE;
}
pMac->lim.deauthMsgCnt = 0;
pMac->lim.retryPacketCnt = 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 eSIR_SUCCESS;
}
/** -------------------------------------------------------------
\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;
vos_spin_lock_destroy( &pMac->sys.lock );
for(i =0; i < pMac->lim.maxBssId; i++)
{
if(pMac->lim.gpSession[i].valid == TRUE)
{
peDeleteSession(pMac,&pMac->lim.gpSession[i]);
}
}
vos_mem_vfree(pMac->lim.limTimers.gpLimCnfWaitTimer);
pMac->lim.limTimers.gpLimCnfWaitTimer = NULL;
vos_mem_vfree(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;
/* May allow following timer messages in sleep mode */
/* 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() ***/
/**
* limPostMsgApiHighPri()
*
* 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
limPostMsgApiHighPri(tpAniSirGlobal pMac, tSirMsgQ *pMsg)
{
return vos_mq_post_message_high_pri(VOS_MQ_ID_PE, (vos_msg_t *) pMsg);
} /*** end limPostMsgApi() ***/
/*--------------------------------------------------------------------------
\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(pMac->gDriverType == 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;
}
#define RSRVD_MGMT_RX_PACKETS 10
// ---------------------------------------------------------------------------
/**
* 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;
tANI_U16 frameLen;
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);
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);
return VOS_STATUS_E_FAILURE;
}
frameLen = WDA_GET_RX_PAYLOAD_LEN(pRxPacketInfo);
if (frameLen > WDA_MAX_MGMT_MPDU_LEN) {
PELOG1(limLog(pMac, LOG1, FL("Dropping frame of len %d"), frameLen));
vos_pkt_return_packet(pVosPkt);
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)
{
PELOG1(limLog( pMac, LOG1,
FL ( "RxBd=%pK mHdr=%pK Type: %d Subtype: %d Sizes:FC%d Mgmt%d"),
pRxPacketInfo, mHdr, mHdr->fc.type, mHdr->fc.subType, sizeof(tSirMacFrameCtl), sizeof(tSirMacMgmtHdr) );)
#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
}
// Forward to MAC via mesg = SIR_BB_XPORT_MGMT_MSG
msg.type = SIR_BB_XPORT_MGMT_MSG;
msg.bodyptr = vosBuff;
msg.bodyval = 0;
vos_spin_lock_acquire( &pMac->sys.lock );
if( pMac->sys.gSysBbtPendingMgmtCount > (vos_pkt_get_num_of_rx_raw_pkts()/4) )
{
vos_spin_lock_release( &pMac->sys.lock );
// drop all management packets
limLog( pMac, LOGW,
FL ( "Management queue 1/4th full, dropping management packets" ));
vos_pkt_return_packet(pVosPkt);
return VOS_STATUS_SUCCESS;
}
if( pMac->sys.gSysBbtPendingMgmtCount > ( vos_pkt_get_num_of_rx_raw_pkts()/4
- RSRVD_MGMT_RX_PACKETS ))
{
// drop all probereq, proberesp and beacons
if( mHdr->fc.subType == SIR_MAC_MGMT_BEACON || mHdr->fc.subType ==
SIR_MAC_MGMT_PROBE_REQ || mHdr->fc.subType == SIR_MAC_MGMT_PROBE_RSP )
{
vos_spin_lock_release( &pMac->sys.lock );
limLog( pMac, LOGW,
FL ( "Dropping probe req, probe resp or beacon" ));
vos_pkt_return_packet(pVosPkt);
return VOS_STATUS_SUCCESS;
}
}
pMac->sys.gSysBbtPendingMgmtCount++;
vos_spin_lock_release( &pMac->sys.lock );
if( eSIR_SUCCESS != sysBbtProcessMessageCore( pMac,
&msg,
mHdr->fc.type,
mHdr->fc.subType ))
{
vos_pkt_return_packet(pVosPkt);
/* Decrement gSysBbtPendingMgmtCount if packet
* is dropped before posting to LIM
*/
limDecrementPendingMgmtCount(pMac);
limLog( pMac, LOGW,
FL ( "sysBbtProcessMessageCore failed to process SIR_BB_XPORT_MGMT_MSG" ));
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++;
pMac->pmm.inMissedBeaconScenario = FALSE;
} /*** end limReceivedHBHandler() ***/
#if 0
void limResetHBPktCount(tpPESession psessionEntry)
{
psessionEntry->LimRxedBeaconCntDuringHB = 0;
}
#endif
/*
* limProcessWdsInfo()
*
*FUNCTION:
* This function is called from schBeaconProcess in BP
*
*PARAMS:
* @param pMac - Pointer to Global MAC structure
* @param propIEInfo - proprietary IE info
*
*LOGIC:
*
*ASSUMPTIONS:
* NA
*
*NOTE:
*
*
*RETURNS:
*
*/
void limProcessWdsInfo(tpAniSirGlobal pMac,
tSirPropIEStruct propIEInfo)
{
}
/**
* limInitWdsInfoParams()
*
*FUNCTION:
* This function is called while processing
* START_BSS/JOIN/REASSOC_REQ to initialize WDS info
* ind/set related parameters.
*
*LOGIC:
*
*ASSUMPTIONS:
*
*NOTE:
*
* @param pMac Pointer to Global MAC structure
* @return None
*/
void
limInitWdsInfoParams(tpAniSirGlobal pMac)
{
pMac->lim.gLimWdsInfo.wdsLength = 0;
pMac->lim.gLimNumWdsInfoInd = 0;
pMac->lim.gLimNumWdsInfoSet = 0;
} /*** limInitWdsInfoParams() ***/
/** -------------------------------------------------------------
\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++;
}
}
/**
* 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);
if ( (!pBeacon->capabilityInfo.ibss) ||
( psessionEntry->privacy !=
(tANI_U8)pBeacon->capabilityInfo.privacy ) ||
(limCmpSSid(pMac, &pBeacon->ssId,psessionEntry) != true) ||
(psessionEntry->currentOperChannel != pBeacon->channelNumber) )
/* Received SSID does not match => Ignore received Beacon frame. */
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);
limLog(pMac, LOG1, FL("BEFORE Coalescing tsfLater val :%d"), tsfLater);
retCode = limIbssCoalesce(pMac, pHdr, pBeacon, pIEs, ieLen, tsfLater,psessionEntry);
}
return retCode;
} /*** end limHandleIBSScoalescing() ***/
tAniBool limEncTypeMatched(tpAniSirGlobal pMac, tpSchBeaconStruct pBeacon,
tpPESession pSession)
{
if (!pBeacon || !pSession)
return eSIR_FALSE;
limLog(pMac, LOG1,
FL("Beacon/Probe:: Privacy :%d WPA Present:%d RSN Present: %d"),
pBeacon->capabilityInfo.privacy, pBeacon->wpaPresent,
pBeacon->rsnPresent);
limLog(pMac, LOG1,
FL("pSession:: Privacy :%d EncyptionType: %d WPS %d OSEN %d"),
SIR_MAC_GET_PRIVACY(pSession->limCurrentBssCaps),
pSession->encryptType, pSession->bWPSAssociation,
pSession->bOSENAssociation);
/* This is handled by sending probe req due to IOT issues so return TRUE
*/
if ( (pBeacon->capabilityInfo.privacy) !=
SIR_MAC_GET_PRIVACY(pSession->limCurrentBssCaps))
{
limLog(pMac, LOG1, FL("Return for Privacy bit miss match, As "
"for this driver need to send the probe request to handle"
" IOT issues "));
return eSIR_TRUE;
}
/*Open*/
if( (pBeacon->capabilityInfo.privacy == 0) &&
(pSession->encryptType == eSIR_ED_NONE))
return eSIR_TRUE;
/* WEP */
if ( (pBeacon->capabilityInfo.privacy == 1) && (pBeacon->wpaPresent == 0) &&
(pBeacon->rsnPresent == 0) &&
( ( pSession->encryptType == eSIR_ED_WEP40 ) ||
( pSession->encryptType == eSIR_ED_WEP104 )
#ifdef FEATURE_WLAN_WAPI
|| ( pSession->encryptType == eSIR_ED_WPI )
#endif
))
return eSIR_TRUE;
/* WPA OR RSN*/
if ( (pBeacon->capabilityInfo.privacy == 1) &&
( (pBeacon->wpaPresent == 1) ||
( pBeacon->rsnPresent == 1)) &&
( (pSession->encryptType == eSIR_ED_TKIP) ||
(pSession->encryptType == eSIR_ED_CCMP) ||
(pSession->encryptType == eSIR_ED_AES_128_CMAC)))
return eSIR_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 wont match and
* driver may end up sending probe request without
* WPS IE during WPS registartion process.
*/
/*TODO: AP capability mismatch
* is not checked here because
* no logic for beacon parsing
* is avilable for HS2.0.
*/
if (pSession->bOSENAssociation ||
pSession->bWPSAssociation)
return eSIR_TRUE;
return eSIR_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;
tSirRetStatus status = eSIR_SUCCESS;
tAniBool securityCapsMatched = eSIR_TRUE;
apNewCaps.capabilityInfo = limGetU16((tANI_U8 *) &pBeacon->capabilityInfo);
newChannel = (tANI_U8) pBeacon->channelNumber;
securityCapsMatched = limEncTypeMatched(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 ) ||
(eSIR_FALSE == securityCapsMatched)
) ) )
{
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.
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 limHandleLowRssiInd() - handles low rssi indication
This function process the SIR_HAL_LOW_RSSI_IND message from
HAL, and sends a eWNI_SME_LOW_RSSI_IND to CSR.
\param pMac - global mac structure
\return
\sa
----------------------------------------------------------------- */
void limHandleLowRssiInd(tpAniSirGlobal pMac)
{
#if 0 //RSSI related indications will now go to TL and not PE
if ( (pMac->pmm.gPmmState == ePMM_STATE_BMPS_SLEEP) ||
(pMac->pmm.gPmmState == ePMM_STATE_UAPSD_SLEEP)||
(pMac->pmm.gPmmState == ePMM_STATE_WOWLAN) )
{
PELOG1(limLog(pMac, LOG1, FL("Sending LOW_RSSI_IND to SME "));)
limSendSmeRsp(pMac, eWNI_SME_LOW_RSSI_IND, eSIR_SME_SUCCESS, 0, 0);
}
else
{
limLog(pMac, LOGE,
FL("Received SIR_HAL_LOW_RSSI_IND while in incorrect state: %d"),
pMac->pmm.gPmmState);
}
return;
#endif
}
/** -----------------------------------------------------------------
\brief limHandleBmpsStatusInd() - handles BMPS status indication
This function process the SIR_HAL_BMPS_STATUS_IND message from HAL,
and invokes limSendExitBmpsInd( ) to send an eWNI_PMC_EXIT_BMPS_IND
to SME with reason code 'eSME_EXIT_BMPS_IND_RCVD'.
HAL sends this message when Firmware fails to enter BMPS mode 'AFTER'
HAL had already send PE a SIR_HAL_ENTER_BMPS_RSP with status
code "success". Hence, HAL needs to notify PE to get out of BMPS mode.
This message can also come from FW anytime after we have entered BMPS.
This means we should handle it in WoWL and UAPSD states as well
\param pMac - global mac structure
\return - none
\sa
----------------------------------------------------------------- */
void limHandleBmpsStatusInd(tpAniSirGlobal pMac)
{
switch(pMac->pmm.gPmmState)
{
case ePMM_STATE_BMPS_SLEEP:
case ePMM_STATE_UAPSD_WT_SLEEP_RSP:
case ePMM_STATE_UAPSD_SLEEP:
case ePMM_STATE_UAPSD_WT_WAKEUP_RSP:
case ePMM_STATE_WOWLAN:
limLog(pMac, LOG1, FL("Sending EXIT_BMPS_IND to SME "));
limSendExitBmpsInd(pMac, eSME_BMPS_STATUS_IND_RCVD);
break;
default:
limLog(pMac, LOGE,
FL("Received SIR_HAL_BMPS_STATUS_IND while in incorrect state: %d"),
pMac->pmm.gPmmState);
break;
}
return;
}
#ifdef WLAN_FEATURE_APFIND
void limHandleAPFindInd(tpAniSirGlobal pMac)
{
tANI_S8 pe_sessionid = -1;
/* Find STA connection session */
pe_sessionid = limGetInfraSessionId(pMac);
if (pe_sessionid != -1)
limTearDownLinkWithAp(pMac,
pe_sessionid,
eSIR_BEACON_MISSED);
else
limLog(pMac, LOGE,
FL("session id doesn't exist for infra"));
}
#endif
/** -----------------------------------------------------------------
\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.inMissedBeaconScenario == TRUE) {
limLog(pMac, LOGW,
FL("beacon miss handling is already going on for BSSIdx:%d"),
pSirMissedBeaconInd->bssIdx);
return;
}
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);
}
/* 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
else
{
limLog(pMac, LOGE,
FL("Received SIR_HAL_MISSED_BEACON_IND while in incorrect state: %d"),
pMac->pmm.gPmmState);
}
return;
}
void limUpdateLostLinkParams(tpAniSirGlobal pMac,
tpPESession psessionEntry, tANI_U8 *pRxPacketInfo)
{
tpSirSmeLostLinkParamsInd pSmeLostLinkParams;
tSirMsgQ mmhMsg;
if (NULL == pRxPacketInfo)
{
return;
}
pSmeLostLinkParams =
(tpSirSmeLostLinkParamsInd)vos_mem_malloc(sizeof(tSirSmeLostLinkParamsInd));
if (NULL == pSmeLostLinkParams)
{
limLog(pMac, LOGP,
FL("Failed to alloc mem of size %zu for tSirSmeLostLinkParamsInd"),
sizeof(*pSmeLostLinkParams));
return;
}
vos_mem_set(pSmeLostLinkParams, sizeof(tSirSmeLostLinkParamsInd), 0);
pSmeLostLinkParams->messageType = eWNI_SME_LOST_LINK_PARAMS_IND;
pSmeLostLinkParams->length = sizeof(tSirSmeLostLinkParamsInd);
pSmeLostLinkParams->sessionId = psessionEntry->smeSessionId;
pSmeLostLinkParams->info.bssIdx = psessionEntry->bssIdx;
/*
* Since FW adds 100 to RSSI, here also we are adding 100 so that
* HDD has common logic to subtract 100 from RSSI received
*/
pSmeLostLinkParams->info.rssi = WDA_GET_RX_RSSI_DB(pRxPacketInfo) + 100;
vos_mem_copy(pSmeLostLinkParams->info.selfMacAddr,
psessionEntry->selfMacAddr,
sizeof(tSirMacAddr));
pSmeLostLinkParams->info.lastDataRate = 0;
pSmeLostLinkParams->info.linkFlCnt = 0;
pSmeLostLinkParams->info.linkFlTx = 0;
pSmeLostLinkParams->info.rsvd1 = 0;
pSmeLostLinkParams->info.rsvd2 = 0;
mmhMsg.type = eWNI_SME_LOST_LINK_PARAMS_IND;
mmhMsg.bodyptr = pSmeLostLinkParams;
mmhMsg.bodyval = 0;
limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT);
}
/** -----------------------------------------------------------------
\brief limProcessLostLinkParamsInd() - handles lost link params indication
This function process the SIR_HAL_LOST_LINK_PARAMS_IND message from HAL,
\param pMac - global mac structure
\return - none
\sa
----------------------------------------------------------------- */
void limProcessLostLinkParamsInd(tpAniSirGlobal pMac, tpSirMsgQ pMsg)
{
tpSirSmeLostLinkParamsInd pSmeLostLinkParamsInd;
tpSirSmeLostLinkParamsInd pLostLInkParamsInd = (tpSirSmeLostLinkParamsInd)pMsg->bodyptr;
tpPESession psessionEntry ;
tSirMsgQ mmhMsg;
if (NULL == pLostLInkParamsInd)
{
limLog(pMac, LOGE,
FL("pLostLInkParamsInd is NULL"));
return;
}
psessionEntry = peFindSessionByBssIdx(pMac,pLostLInkParamsInd->info.bssIdx);
if (psessionEntry == NULL)
{
limLog(pMac, LOGE,
FL("session does not exist for bdssIdx : %d"),
pLostLInkParamsInd->info.bssIdx);
return;
}
pSmeLostLinkParamsInd = vos_mem_malloc(sizeof(tSirSmeLostLinkParamsInd));
if (pSmeLostLinkParamsInd == NULL)
{
limLog(pMac, LOGP,
FL("memory allocate failed for eWNI_SME_LOST_LINK_PARAMD_IND"));
return;
}
pSmeLostLinkParamsInd->messageType = eWNI_SME_LOST_LINK_PARAMS_IND;
pSmeLostLinkParamsInd->length = sizeof(tSirSmeLostLinkParamsInd);
pSmeLostLinkParamsInd->sessionId = psessionEntry->smeSessionId;
pSmeLostLinkParamsInd->info.bssIdx = pLostLInkParamsInd->info.bssIdx;
pSmeLostLinkParamsInd->info.rssi = pLostLInkParamsInd->info.rssi;
vos_mem_copy(pSmeLostLinkParamsInd->info.selfMacAddr,
pLostLInkParamsInd->info.selfMacAddr,
sizeof(tSirMacAddr));
pSmeLostLinkParamsInd->info.linkFlCnt = pLostLInkParamsInd->info.linkFlCnt;
pSmeLostLinkParamsInd->info.linkFlTx = pLostLInkParamsInd->info.linkFlTx;
pSmeLostLinkParamsInd->info.lastDataRate = pLostLInkParamsInd->info.lastDataRate;
pSmeLostLinkParamsInd->info.rsvd1 = pLostLInkParamsInd->info.rsvd1;
pSmeLostLinkParamsInd->info.rsvd2 = pLostLInkParamsInd->info.rsvd2;
mmhMsg.type = eWNI_SME_LOST_LINK_PARAMS_IND;
mmhMsg.bodyptr = pSmeLostLinkParamsInd;
mmhMsg.bodyval = 0;
limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT);
return;
}
/** -----------------------------------------------------------------
\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(tSirSmeMicFailureInd));
if (NULL == pSirSmeMicFailureInd)
{
// Log error
limLog(pMac, LOGP,
FL("memory allocate failed for eWNI_SME_MIC_FAILURE_IND"));
return;
}
pSirSmeMicFailureInd->messageType = eWNI_SME_MIC_FAILURE_IND;
pSirSmeMicFailureInd->length = sizeof(*pSirSmeMicFailureInd);
pSirSmeMicFailureInd->sessionId = psessionEntry->smeSessionId;
vos_mem_copy(pSirSmeMicFailureInd->bssId,
pSirMicFailureInd->bssId,
sizeof(tSirMacAddr));
vos_mem_copy(pSirSmeMicFailureInd->info.srcMacAddr,
pSirMicFailureInd->info.srcMacAddr,
sizeof(tSirMacAddr));
vos_mem_copy(pSirSmeMicFailureInd->info.taMacAddr,
pSirMicFailureInd->info.taMacAddr,
sizeof(tSirMacAddr));
vos_mem_copy(pSirSmeMicFailureInd->info.dstMacAddr,
pSirMicFailureInd->info.dstMacAddr,
sizeof(tSirMacAddr));
vos_mem_copy(pSirSmeMicFailureInd->info.rxMacAddr,
pSirMicFailureInd->info.rxMacAddr,
sizeof(tSirMacAddr));
pSirSmeMicFailureInd->info.multicast =
pSirMicFailureInd->info.multicast;
pSirSmeMicFailureInd->info.keyId=
pSirMicFailureInd->info.keyId;
pSirSmeMicFailureInd->info.IV1=
pSirMicFailureInd->info.IV1;
vos_mem_copy(pSirSmeMicFailureInd->info.TSC,
pSirMicFailureInd->info.TSC,SIR_CIPHER_SEQ_CTR_SIZE);
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;
}
#ifdef WLAN_FEATURE_11W
/** --------------------------------------------------------------------
* lim_is_assoc_req_for_drop()- function to decides to drop assoc\reassoc
* frames.
* @mac: pointer to global mac structure
* @rx_pkt_info: rx packet meta information
*
* This function is called before enqueuing the frame to PE queue to
* drop flooded assoc/reassoc frames getting into PE Queue.
*
* Return: true for dropping the frame otherwise false
----------------------------------------------------------------------*/
bool lim_is_assoc_req_for_drop(tpAniSirGlobal pMac, uint8_t *rx_pkt_info)
{
tANI_U8 session_id;
tANI_U16 aid;
tpPESession session_entry;
tpSirMacMgmtHdr pMacHdr;
tpDphHashNode sta_ds;
bool status;
eHalStatus lock_status = eHAL_STATUS_SUCCESS;
pMacHdr = WDA_GET_RX_MAC_HEADER(rx_pkt_info);
session_entry = peFindSessionByBssid(pMac, pMacHdr->bssId, &session_id);
if (!session_entry)
{
PELOG1(limLog(pMac, LOG1,
FL("session does not exist for given STA [%pM]"),
pMacHdr->sa););
return false;
}
lock_status = pe_AcquireGlobalLock(&pMac->lim);
if (lock_status != eHAL_STATUS_SUCCESS)
{
limLog(pMac, LOGE, FL("pe_AcquireGlobalLock error"));
return TRUE;
}
sta_ds = dphLookupHashEntry(pMac, pMacHdr->sa, &aid,
&session_entry->dph.dphHashTable);
if (!sta_ds)
{
PELOG1(limLog(pMac, LOG1, FL("pStaDs is NULL")););
status = false;
goto end;
}
if (!sta_ds->rmfEnabled) {
status = false;
goto end;
}
if (sta_ds->pmfSaQueryState == DPH_SA_QUERY_IN_PROGRESS) {
status = true;
goto end;
}
if (sta_ds->last_assoc_received_time &&
((vos_timer_get_system_time() -
sta_ds->last_assoc_received_time) < 1000)) {
status = true;
goto end;
}
sta_ds->last_assoc_received_time = vos_timer_get_system_time();
status = false;
end:
pe_ReleaseGlobalLock(&pMac->lim);
return status;
}
#endif
/** ----------------------------------------------------------------------
*\brief limIsDeauthDiassocForDrop()..decides to drop deauth\diassoc frames.
*This function is called before enqueuing the frame to PE queue.
*This prevents deauth/diassoc frames getting into PE Queue.
------------------------------------------------------------------------ */
boolean limIsDeauthDiassocForDrop(tpAniSirGlobal pMac,
tANI_U8 *pRxPacketInfo)
{
tANI_U8 sessionId;
tANI_U16 aid;
tpPESession psessionEntry;
tpSirMacMgmtHdr pMacHdr;
tpDphHashNode pStaDs;
eHalStatus lock_status = eHAL_STATUS_SUCCESS;
boolean ret = FALSE;
pMacHdr = WDA_GET_RX_MAC_HEADER(pRxPacketInfo);
psessionEntry = peFindSessionByBssid(pMac,pMacHdr->bssId,&sessionId);
if (!psessionEntry)
{
PELOG1(sysLog(pMac, LOG1,
FL("session does not exist for given STA [%pM]"),
pMacHdr->sa););
return TRUE;
}
lock_status = pe_AcquireGlobalLock(&pMac->lim);
if (lock_status != eHAL_STATUS_SUCCESS)
{
limLog(pMac, LOGE, FL("pe_AcquireGlobalLock error"));
return TRUE;
}
pStaDs = dphLookupHashEntry(pMac, pMacHdr->sa, &aid,
&psessionEntry->dph.dphHashTable);
if (!pStaDs)
{
PELOG1(sysLog(pMac, LOG1,FL("pStaDs is NULL")););
ret = TRUE;
goto end;
}
#ifdef WLAN_FEATURE_11W
if (psessionEntry->limRmfEnabled)
{
if ((WDA_GET_RX_DPU_FEEDBACK(pRxPacketInfo) &
DPU_FEEDBACK_UNPROTECTED_ERROR))
{
/* It may be possible that deauth/diassoc frames from a spoofy
* AP is received. So if all further deauth/diassoc frmaes are
* dropped, then it may result in lossing deauth/diassoc frames
* from genuine AP. So process all deauth/diassoc frames with
* a time difference of 1 sec.
*/
if (vos_timer_get_system_time() - pStaDs->last_unprot_deauth_disassoc < 1000)
{
ret = TRUE;
goto end;
}
pStaDs->last_unprot_deauth_disassoc =
vos_timer_get_system_time();
}
/* PMF enabed, Management frames are protected */
else
{
if (pStaDs->proct_deauh_disassoc_cnt)
{
ret = TRUE;
goto end;
}
else
pStaDs->proct_deauh_disassoc_cnt++;
}
}
else
#endif
/* PMF disabled */
{
if (pStaDs->isDisassocDeauthInProgress)
{
ret = TRUE;
goto end;
}
else
pStaDs->isDisassocDeauthInProgress++;
}
end:
pe_ReleaseGlobalLock(&pMac->lim);
return ret;
}
/** -----------------------------------------------------------------
\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;
/*
*
* 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(pMac->pmm.inMissedBeaconScenario)
{
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
#ifdef WLAN_FEATURE_EXTSCAN
else if (WDA_GET_EXTSCANFULLSCANRESIND(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);
/* Note sure if this is sufficient, basically this condition allows all probe responses and
* beacons from an infrastructure network
*/
*((tANI_U16*) &capabilityInfo) = sirReadU16(pBody+ LIM_BCN_PR_CAPABILITY_OFFSET);
if(!capabilityInfo.ibss)
return eMGMT_DROP_NO_DROP;
#if 0
//Allow the mgmt frames to be queued if STA not in IBSS mode.
if (pMac->lim.gLimSystemRole != eLIM_STA_IN_IBSS_ROLE)
return eMGMT_DROP_NO_DROP;
#endif
#ifdef WLAN_FEATURE_11W
if ((subType == SIR_MAC_MGMT_ASSOC_REQ ||
subType == SIR_MAC_MGMT_REASSOC_REQ) &&
lim_is_assoc_req_for_drop(pMac, pRxPacketInfo))
return eMGMT_DROP_SPURIOUS_FRAME;
#endif
//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);
//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)))
{
//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;
}
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);
}
/**
* lim_process_sme_cap_tsf_req()- send cap tsf request to WDA
* Get bss_idx from PE and fill in cap tsf request.
* @pMac:Mac ctx
* @pMsgBuf: message buffer from sme
* Returns success on post to WDA, otherwise failure
*/
tSirRetStatus lim_process_sme_cap_tsf_req(tpAniSirGlobal pMac,
tANI_U32 *pMsgBuf)
{
tSirCapTsfParams *pMsg = NULL;
tpPESession psessionEntry = NULL;
uint8_t sessionId;
tSirMsgQ msg;
tSirCapTsfParams *cap_tsf_params;
pMsg = (tSirCapTsfParams*)pMsgBuf;
if (pMsg == NULL) {
limLog(pMac, LOGE, FL("NULL pMsg"));
return eSIR_FAILURE;
}
psessionEntry = peFindSessionByBssid(pMac, pMsg->bssid, &sessionId);
if (NULL == psessionEntry)
{
limLog(pMac, LOGE, FL("NULL psessionEntry"));
return eSIR_FAILURE;
}
cap_tsf_params = (tSirCapTsfParams *)
vos_mem_malloc(sizeof(*cap_tsf_params));
if (!cap_tsf_params) {
limLog(pMac, LOGE, FL(" Unable to allocate memory for cap tsf params"));
return eSIR_MEM_ALLOC_FAILED;
}
vos_mem_copy (cap_tsf_params, pMsg, sizeof(*cap_tsf_params));
cap_tsf_params->bss_idx = psessionEntry->bssIdx;
msg.type = WDA_CAP_TSF_REQ;
msg.reserved = 0;
msg.bodyptr = cap_tsf_params;
msg.bodyval = 0;
if(eSIR_SUCCESS != wdaPostCtrlMsg(pMac, &msg))
{
limLog(pMac, LOGE, FL("lim_process_sme_cap_tsf_req failed\n"));
vos_mem_free(cap_tsf_params);
return eSIR_FAILURE;
}
return eSIR_SUCCESS;
}
/**
* lim_process_sme_get_tsf_req()- send get tsf request to WDA
* Get bss_idx from PE and fill in cap tsf request.
* @pMac:Mac ctx
* @pMsgBuf: message buffer from sme
* Returns success on post to WDA, otherwise failure
*/
tSirRetStatus lim_process_sme_get_tsf_req(tpAniSirGlobal pMac,
tANI_U32 *pMsgBuf)
{
tSirCapTsfParams *pMsg = NULL;
tpPESession psessionEntry = NULL;
uint8_t sessionId;
tSirMsgQ msg;
tSirCapTsfParams *get_tsf_params;
pMsg = (tSirCapTsfParams*)pMsgBuf;
if (pMsg == NULL) {
limLog(pMac, LOGE, FL("NULL pMsg"));
return eSIR_FAILURE;
}
psessionEntry = peFindSessionByBssid(pMac, pMsg->bssid, &sessionId);
if (NULL == psessionEntry)
{
limLog(pMac, LOGE, FL("NULL psessionEntry"));
return eSIR_FAILURE;
}
get_tsf_params = (tSirCapTsfParams *)
vos_mem_malloc(sizeof(*get_tsf_params));
if (!get_tsf_params) {
limLog(pMac, LOGE, FL(" Unable to allocate memory for cap tsf params"));
return eSIR_MEM_ALLOC_FAILED;
}
vos_mem_copy (get_tsf_params, pMsg, sizeof(*get_tsf_params));
get_tsf_params->bss_idx = psessionEntry->bssIdx;
msg.type = WDA_GET_TSF_REQ;
msg.reserved = 0;
msg.bodyptr = get_tsf_params;
msg.bodyval = 0;
if(eSIR_SUCCESS != wdaPostCtrlMsg(pMac, &msg))
{
limLog(pMac, LOGE, FL("lim_process_sme_cap_tsf_req failed\n"));
vos_mem_free(get_tsf_params);
return eSIR_FAILURE;
}
return eSIR_SUCCESS;
}
/**
* lim_process_sme_del_ba_ses_req()- process del ba req
* @pMac:Mac ctx
* @pMsgBuf: message buffer from sme
* Returns success on taking action based on cfg value, otherwise failure
*/
tSirRetStatus lim_process_sme_del_ba_ses_req(tpAniSirGlobal pMac,
tANI_U32 *pMsgBuf)
{
tDelBaParams *pMsg = NULL;
tpPESession psessionEntry = NULL;
int val;
pMsg = (tDelBaParams*)pMsgBuf;
if (pMsg == NULL) {
limLog(pMac, LOGE, FL("NULL pMsg"));
return eSIR_FAILURE;
}
psessionEntry = peFindSessionBySessionId(pMac, pMsg->session_id);
if (NULL == psessionEntry)
{
limLog(pMac, LOGE, FL("NULL psessionEntry"));
return eSIR_FAILURE;
}
if (wlan_cfgGetInt
(pMac, WNI_CFG_ENABLE_TX_RX_AGGREGATION, &val) !=
eSIR_SUCCESS)
{
limLog(pMac, LOGE,
FL( "Unable to get WNI_CFG_ENABLE_TX_RX_AGGREGATION"));
return eSIR_FAILURE;
}
if (!val)
{
limLog(pMac, LOGW,
FL("user requested to disable all RX BA sessions"));
limDeleteBASessions(pMac, psessionEntry, BA_BOTH_DIRECTIONS,
eSIR_MAC_PEER_TIMEDOUT_REASON);
}
return eSIR_SUCCESS;
}