| /* |
| * Copyright (c) 2012-2014, 2016 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 pmmApi.cc contains functions related to the API exposed |
| * by power management module |
| * |
| * Author: Sandesh Goel |
| * Date: 02/25/02 |
| * History:- |
| * Date Modified by Modification Information |
| * -------------------------------------------------------------------- |
| * |
| */ |
| |
| #include "palTypes.h" |
| #include "wni_cfg.h" |
| #include "sirCommon.h" |
| #include "aniGlobal.h" |
| |
| #include "schApi.h" |
| #include "limApi.h" |
| #include "limSendMessages.h" |
| #include "cfgApi.h" |
| #include "limSessionUtils.h" |
| #include "limFT.h" |
| |
| #include "pmmApi.h" |
| #include "pmmDebug.h" |
| #include "sirApi.h" |
| #include "wmmApsd.h" |
| |
| #include "limSendSmeRspMessages.h" |
| #include "limTimerUtils.h" |
| #include "limTrace.h" |
| #include "limUtils.h" |
| #include "VossWrapper.h" |
| #include "vos_status.h" //VOS_STATUS |
| #include "vos_mq.h" //vos_mq_post_message() |
| |
| #include "wlan_qct_wda.h" |
| |
| #define LIM_ADMIT_MASK_FLAG_ACBE 1 |
| #define LIM_ADMIT_MASK_FLAG_ACBK 2 |
| #define LIM_ADMIT_MASK_FLAG_ACVI 4 |
| #define LIM_ADMIT_MASK_FLAG_ACVO 8 |
| |
| // -------------------------------------------------------------------- |
| /** |
| * pmmInitialize |
| * |
| * FUNCTION: |
| * Initialize PMM module |
| * |
| * LOGIC: |
| * |
| * ASSUMPTIONS: |
| * |
| * NOTE: |
| * |
| * @param mode |
| * @param rate |
| * @return None |
| */ |
| |
| tSirRetStatus |
| pmmInitialize(tpAniSirGlobal pMac) |
| { |
| |
| |
| pmmResetStats(pMac); |
| |
| pMac->pmm.gPmmBeaconInterval = WNI_CFG_BEACON_INTERVAL_STADEF; |
| pMac->pmm.gPmmState = ePMM_STATE_READY; |
| |
| |
| |
| pMac->pmm.inMissedBeaconScenario = FALSE; |
| |
| return eSIR_SUCCESS; |
| } |
| |
| // -------------------------------------------------------------------- |
| /** |
| * pmmResetStats |
| * |
| * FUNCTION: |
| * Resets the statistics |
| * |
| * LOGIC: |
| * |
| * ASSUMPTIONS: |
| * |
| * NOTE: |
| * |
| * @param pMac |
| * |
| * @return None |
| */ |
| |
| void |
| pmmResetStats(void *pvMac) |
| { |
| tpAniSirGlobal pMac = (tpAniSirGlobal)pvMac; |
| |
| pMac->pmm.BmpsmaxSleepTime = 0; |
| pMac->pmm.BmpsavgSleepTime = 0; |
| pMac->pmm.BmpsminSleepTime = 0; |
| pMac->pmm.BmpscntSleep = 0; |
| |
| pMac->pmm.BmpsmaxTimeAwake = 0; |
| pMac->pmm.BmpsavgTimeAwake = 0; |
| pMac->pmm.BmpsminTimeAwake = 0; |
| pMac->pmm.BmpscntAwake = 0; |
| |
| pMac->pmm.BmpsWakeupTimeStamp = 0; |
| pMac->pmm.BmpsSleepTimeStamp = 0; |
| |
| pMac->pmm.BmpsHalReqFailCnt = 0; |
| pMac->pmm.BmpsInitFailCnt = 0; |
| pMac->pmm.BmpsInitFailCnt= 0; |
| pMac->pmm.BmpsInvStateCnt= 0; |
| pMac->pmm.BmpsPktDrpInSleepMode= 0; |
| pMac->pmm.BmpsReqInInvalidRoleCnt= 0; |
| pMac->pmm.BmpsSleeReqFailCnt= 0; |
| pMac->pmm.BmpsWakeupIndCnt= 0; |
| |
| pMac->pmm.ImpsWakeupTimeStamp = 0; |
| pMac->pmm.ImpsSleepTimeStamp = 0; |
| pMac->pmm.ImpsMaxTimeAwake = 0; |
| pMac->pmm.ImpsMinTimeAwake = 0; |
| pMac->pmm.ImpsAvgTimeAwake = 0; |
| pMac->pmm.ImpsCntAwake = 0; |
| |
| pMac->pmm.ImpsCntSleep = 0; |
| pMac->pmm.ImpsMaxSleepTime = 0; |
| pMac->pmm.ImpsMinSleepTime = 0; |
| pMac->pmm.ImpsAvgSleepTime = 0; |
| |
| pMac->pmm.ImpsSleepErrCnt = 0; |
| pMac->pmm.ImpsWakeupErrCnt = 0; |
| pMac->pmm.ImpsLastErr = 0; |
| pMac->pmm.ImpsInvalidStateCnt = 0; |
| |
| return; |
| } |
| |
| |
| |
| // -------------------------------------------------------------------- |
| /** |
| * pmmInitBmpsResponseHandler |
| * |
| * FUNCTION: |
| * This function processes the SIR_HAL_ENTER_BMPS_RSP from HAL. |
| * If the response is successful, it puts PMM in ePMM_STATE_BMP_SLEEP state |
| * and sends back success response to PMC. |
| * |
| * LOGIC: |
| * |
| * ASSUMPTIONS: |
| * |
| * NOTE: |
| * |
| * @param |
| * @return None |
| */ |
| |
| void pmmInitBmpsResponseHandler(tpAniSirGlobal pMac, tpSirMsgQ limMsg ) |
| { |
| |
| |
| tPmmState nextState = pMac->pmm.gPmmState; |
| tSirResultCodes retStatus = eSIR_SME_SUCCESS; |
| tpPESession psessionEntry; |
| tpEnterBmpsParams pEnterBmpsParams; |
| |
| /* we need to process all the deferred messages enqueued since |
| * the initiating the SIR_HAL_ENTER_BMPS_REQ. |
| */ |
| SET_LIM_PROCESS_DEFD_MESGS(pMac, true); |
| |
| if(pMac->pmm.gPmmState != ePMM_STATE_BMPS_WT_INIT_RSP) |
| { |
| PELOGE(pmmLog(pMac, LOGE, |
| FL("pmmBmps: Received 'InitPwrSaveRsp' while in incorrect state: %d"), |
| pMac->pmm.gPmmState);) |
| |
| retStatus = eSIR_SME_INVALID_PMM_STATE; |
| pmmBmpsUpdateInvalidStateCnt(pMac); |
| goto failure; |
| } |
| |
| if (NULL == limMsg->bodyptr) |
| { |
| PELOGE(pmmLog(pMac, LOGE, FL("pmmBmps: Received SIR_HAL_ENTER_BMPS_RSP with NULL "));) |
| goto failure; |
| } |
| pEnterBmpsParams = (tpEnterBmpsParams)(limMsg->bodyptr); |
| |
| //if response is success, then set PMM to BMPS_SLEEP state and send response back to PMC. |
| //If response is failure, then send the response back to PMC and reset its state. |
| if(pEnterBmpsParams->status == eHAL_STATUS_SUCCESS) |
| { |
| PELOG2(pmmLog(pMac, LOG2, |
| FL("pmmBmps: Received successful response from HAL to enter BMPS_POWER_SAVE "));) |
| |
| pMac->pmm.gPmmState = ePMM_STATE_BMPS_SLEEP; |
| |
| // Disable background scan mode |
| pMac->sys.gSysEnableScanMode = false; |
| |
| if (pMac->lim.gLimTimersCreated) |
| { |
| /* Disable heartbeat timer as well */ |
| if(pMac->lim.limTimers.gLimHeartBeatTimer.pMac) |
| { |
| MTRACE(macTrace(pMac, TRACE_CODE_TIMER_DEACTIVATE, NO_SESSION, eLIM_HEART_BEAT_TIMER)); |
| tx_timer_deactivate(&pMac->lim.limTimers.gLimHeartBeatTimer); |
| } |
| } |
| limSendSmeRsp(pMac, eWNI_PMC_ENTER_BMPS_RSP, retStatus, 0, 0); |
| } |
| else |
| { |
| //if init req failed, then go back to WAKEUP state. |
| PELOGE(pmmLog(pMac, LOGE, |
| FL("pmmBmps: BMPS_INIT_PWR_SAVE_REQ failed, informing SME"));) |
| |
| pmmBmpsUpdateInitFailureCnt(pMac); |
| nextState = ePMM_STATE_READY; |
| retStatus = eSIR_SME_BMPS_REQ_FAILED; |
| goto failure; |
| } |
| return; |
| |
| failure: |
| psessionEntry = peGetValidPowerSaveSession(pMac); |
| if(psessionEntry != NULL) |
| { |
| if (pMac->lim.gLimTimersCreated && pMac->lim.limTimers.gLimHeartBeatTimer.pMac) |
| { |
| if(VOS_TRUE != tx_timer_running(&pMac->lim.limTimers.gLimHeartBeatTimer)) |
| { |
| PELOGE(pmmLog(pMac, LOGE, FL("Unexpected heartbeat timer not running"));) |
| limReactivateHeartBeatTimer(pMac, psessionEntry); |
| } |
| } |
| } |
| |
| //Generate an error response back to PMC |
| pMac->pmm.gPmmState = nextState; |
| pmmBmpsUpdateSleepReqFailureCnt(pMac); |
| limSendSmeRsp(pMac, eWNI_PMC_ENTER_BMPS_RSP, retStatus, 0, 0); |
| return; |
| |
| } |
| |
| // -------------------------------------------------------------------- |
| /** |
| * pmmExitBmpsRequestHandler |
| * |
| * FUNCTION: |
| * This function will send the wakeup message to HAL |
| * |
| * LOGIC: |
| * |
| * ASSUMPTIONS: |
| * |
| * NOTE: |
| * |
| * @param pMac pointer to Global Mac structure. |
| |
| * @return None |
| */ |
| |
| void pmmExitBmpsRequestHandler(tpAniSirGlobal pMac, tpExitBmpsInfo pExitBmpsInfo) |
| { |
| tSirResultCodes respStatus = eSIR_SME_SUCCESS; |
| |
| tPmmState origState = pMac->pmm.gPmmState; |
| |
| if (NULL == pExitBmpsInfo) |
| { |
| respStatus = eSIR_SME_BMPS_REQ_REJECT; |
| PELOGW(pmmLog(pMac, LOGW, FL("pmmBmps: Rcvd EXIT_BMPS with NULL body"));) |
| goto failure; |
| } |
| |
| #ifdef FEATURE_WLAN_DIAG_SUPPORT |
| limDiagEventReport(pMac, WLAN_PE_DIAG_EXIT_BMPS_REQ_EVENT, |
| peGetValidPowerSaveSession(pMac), 0, |
| (tANI_U16)pExitBmpsInfo->exitBmpsReason); |
| #endif //FEATURE_WLAN_DIAG_SUPPORT |
| |
| /* PMC is not aware of Background scan, which is done in |
| * BMPS mode while Nth Beacon is delivered. Essentially, PMC |
| * can request the device to get out of power-save while |
| * background scanning is happening. since, the device is already |
| * out of power save, just inform that device is out of power save |
| */ |
| if(limIsSystemInScanState(pMac)) |
| { |
| PELOGW(pmmLog(pMac, LOGW, |
| FL("pmmBmps: Device is already awake and scanning, returning success to PMC "));) |
| limSendSmeRsp(pMac, eWNI_PMC_EXIT_BMPS_RSP, respStatus, 0, 0); |
| return; |
| } |
| |
| /* send wakeup request, only when in sleep state */ |
| PELOGW(pmmLog(pMac, LOGW, FL("pmmBmps: Sending eWNI_PMC_EXIT_BMPS_REQ to HAL"));) |
| if ((pMac->pmm.gPmmState == ePMM_STATE_BMPS_SLEEP) || |
| (pMac->pmm.gPmmState == ePMM_STATE_UAPSD_SLEEP)) |
| { |
| /* Store the reason code for exiting BMPS. This value will be |
| * checked when PMM receives SIR_HAL_EXIT_BMPS_RSP from HAL |
| */ |
| pMac->pmm.gPmmExitBmpsReasonCode = pExitBmpsInfo->exitBmpsReason; |
| vos_mem_free(pExitBmpsInfo); |
| |
| PELOGW(pmmLog(pMac, LOGW, |
| FL("pmmBmps: Rcvd EXIT_BMPS with reason code%d "), pMac->pmm.gPmmExitBmpsReasonCode);) |
| |
| |
| // Set PMM to BMPS_WT_WAKEUP_RSP state |
| pMac->pmm.gPmmState = ePMM_STATE_BMPS_WT_WAKEUP_RSP; |
| if(pmmSendChangePowerSaveMsg(pMac) != eSIR_SUCCESS) |
| { |
| /* Wakeup request failed */ |
| respStatus = eSIR_SME_BMPS_REQ_REJECT; |
| pmmBmpsUpdateHalReqFailureCnt(pMac); |
| goto failure; |
| } |
| else |
| { |
| PELOG1(pmmLog(pMac, LOG1, |
| FL("pmmBmps: eWNI_PMC_EXIT_BMPS_REQ was successfully sent to HAL"));) |
| } |
| } |
| else |
| { |
| PELOGE(pmmLog(pMac, LOGE, |
| FL("pmmBmps: eWNI_PMC_EXIT_BMPS_REQ received in invalid state: %d"), |
| pMac->pmm.gPmmState );) |
| |
| respStatus = eSIR_SME_INVALID_PMM_STATE; |
| pmmBmpsUpdateInvalidStateCnt(pMac); |
| vos_mem_free(pExitBmpsInfo); |
| goto failure; |
| } |
| return; |
| |
| failure: |
| pMac->pmm.gPmmState = origState; |
| pmmBmpsUpdateWakeupReqFailureCnt(pMac); |
| limSendSmeRsp(pMac, eWNI_PMC_EXIT_BMPS_RSP, respStatus, 0, 0); |
| } |
| |
| |
| // -------------------------------------------------------------------- |
| /** |
| * pmmInitBmpsPwrSave |
| * |
| * FUNCTION: |
| * This function process the eWNI_PMC_ENTER_PMC_REQ from PMC. |
| * It checks for certain conditions before it puts PMM into |
| * BMPS power save state: ePMM_STATE_BMPS_WT_INIT_RSP |
| * It also invokes pmmSendInitPowerSaveMsg() to send ENTER_BMPS_REQ |
| * to HAL. |
| * |
| * LOGIC: |
| * |
| * ASSUMPTIONS: |
| * |
| * NOTE: |
| * |
| * @param mode can be either 0(sleep mode) or 1 (active mode) |
| * @param pMac pointer to Global Mac structure. |
| |
| * @return None |
| */ |
| |
| |
| void pmmInitBmpsPwrSave(tpAniSirGlobal pMac) |
| { |
| tSirRetStatus retStatus = eSIR_SUCCESS; |
| tSirResultCodes respStatus = eSIR_SME_SUCCESS; |
| tpPESession psessionEntry; |
| |
| tPmmState origState = pMac->pmm.gPmmState; |
| |
| if((psessionEntry = peGetValidPowerSaveSession(pMac))== NULL) |
| { |
| respStatus = eSIR_SME_BMPS_REQ_REJECT; |
| goto failure; |
| } |
| #ifndef WLAN_ACTIVEMODE_OFFLOAD_FEATURE |
| // sending beacon filtering information down to HAL |
| if (limSendBeaconFilterInfo(pMac, psessionEntry) != eSIR_SUCCESS) |
| { |
| pmmLog(pMac, LOGE, FL("Fail to send Beacon Filter Info ")); |
| } |
| #else |
| if(!IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE) |
| { |
| if (limSendBeaconFilterInfo(pMac, psessionEntry) != eSIR_SUCCESS) |
| { |
| pmmLog(pMac, LOGE, FL("Fail to send Beacon Filter Info ")); |
| } |
| } |
| #endif |
| |
| #ifdef FEATURE_WLAN_DIAG_SUPPORT |
| limDiagEventReport(pMac, WLAN_PE_DIAG_ENTER_BMPS_REQ_EVENT, psessionEntry, 0, 0); |
| #endif //FEATURE_WLAN_DIAG_SUPPORT |
| |
| if ( ((pMac->pmm.gPmmState != ePMM_STATE_READY) && |
| (pMac->pmm.gPmmState != ePMM_STATE_BMPS_WAKEUP)) || |
| limIsSystemInScanState(pMac) || |
| limIsChanSwitchRunning(pMac) || |
| limIsInQuietDuration(pMac) ) |
| { |
| PELOGE(pmmLog(pMac, LOGE, |
| FL("pmmBmps: BMPS Request received in invalid state PMM=%d, SME=%d, rejecting the initpwrsave request"), |
| pMac->pmm.gPmmState, pMac->lim.gLimSmeState);) |
| |
| respStatus = eSIR_SME_INVALID_PMM_STATE; |
| pmmBmpsUpdateInvalidStateCnt(pMac); |
| goto failure; |
| } |
| |
| //If we are in a missed beacon scenario, we should not be attempting to enter BMPS as heartbeat probe is going on |
| if(pMac->pmm.inMissedBeaconScenario) |
| { |
| if (pMac->lim.gLimTimersCreated && pMac->lim.limTimers.gLimHeartBeatTimer.pMac) |
| { |
| if(VOS_TRUE != tx_timer_running(&pMac->lim.limTimers.gLimHeartBeatTimer)) |
| { |
| PELOGE(pmmLog(pMac, LOGE, FL("Unexpected heartbeat timer not running"));) |
| limReactivateHeartBeatTimer(pMac, psessionEntry); |
| } |
| } |
| respStatus = eSIR_SME_BMPS_REQ_REJECT; |
| goto failure; |
| } |
| |
| /* At this point, device is associated and PMM is not in BMPS_SLEEP state. |
| * Heartbeat timer not running is an indication that PE have detected a |
| * loss of link. In this case, reject BMPS request. |
| */ |
| |
| //If the following function returns SUCCESS, then PMM will wait for an explicit |
| //response message from softmac. |
| |
| //changing PMM state before posting message to HAL, as this is a synchronous call to HAL |
| pMac->pmm.gPmmState = ePMM_STATE_BMPS_WT_INIT_RSP; |
| if((retStatus = pmmSendInitPowerSaveMsg(pMac,psessionEntry)) != eSIR_SUCCESS) |
| { |
| PELOGE(pmmLog(pMac, LOGE, |
| FL("pmmBmps: Init Power Save Request Failed: Sending Response: %d"), |
| retStatus);) |
| |
| respStatus = eSIR_SME_BMPS_REQ_REJECT; |
| pmmBmpsUpdateHalReqFailureCnt(pMac); |
| goto failure; |
| } |
| //Update the powerSave sessionId |
| pMac->pmm.sessionId = psessionEntry->peSessionId; |
| return; |
| |
| failure: |
| |
| // Change the state back to original state |
| pMac->pmm.gPmmState =origState; |
| limSendSmeRsp(pMac, eWNI_PMC_ENTER_BMPS_RSP, respStatus, 0, 0); |
| return; |
| } |
| |
| |
| /** |
| * pmmSendChangePowerSaveMsg() |
| * |
| *FUNCTION: |
| * This function is called to send SIR_HAL_EXIT_BMPS_REQ to HAL. |
| * This message will trigger HAL to program HW to wake up. |
| * |
| *LOGIC: |
| * |
| *ASSUMPTIONS: |
| * NA |
| * |
| *NOTE: |
| * NA |
| * |
| * @param pMac pointer to Global Mac structure. |
| * @return success if message send is ok, else false. |
| */ |
| tSirRetStatus pmmSendChangePowerSaveMsg(tpAniSirGlobal pMac) |
| { |
| tSirRetStatus retStatus = eSIR_SUCCESS; |
| tpExitBmpsParams pExitBmpsParams; |
| tSirMsgQ msgQ; |
| tpPESession psessionEntry; |
| tANI_U8 currentOperatingChannel = limGetCurrentOperatingChannel(pMac); |
| |
| pExitBmpsParams = vos_mem_malloc(sizeof(*pExitBmpsParams)); |
| if ( NULL == pExitBmpsParams ) |
| { |
| pmmLog(pMac, LOGW, FL("Failed to allocate memory")); |
| retStatus = eSIR_MEM_ALLOC_FAILED; |
| return retStatus; |
| } |
| |
| if((psessionEntry = peGetValidPowerSaveSession(pMac)) == NULL ) |
| { |
| retStatus = eSIR_FAILURE; |
| vos_mem_free(pExitBmpsParams); |
| return retStatus; |
| } |
| |
| vos_mem_zero(pExitBmpsParams, sizeof(*pExitBmpsParams)); |
| msgQ.type = WDA_EXIT_BMPS_REQ; |
| msgQ.reserved = 0; |
| msgQ.bodyptr = pExitBmpsParams; |
| msgQ.bodyval = 0; |
| |
| /* If reason for full power is disconnecting (ie. link is |
| * disconnected) or because of channel switch or full power requested |
| * because of beacon miss and connected on DFS channel |
| * then we should not send data null. |
| * For all other reason code, send data null. |
| */ |
| if ( !(SIR_IS_FULL_POWER_REASON_DISCONNECTED(pMac->pmm.gPmmExitBmpsReasonCode) || |
| ( (eSME_MISSED_BEACON_IND_RCVD == pMac->pmm.gPmmExitBmpsReasonCode) && |
| limIsconnectedOnDFSChannel(currentOperatingChannel)))) |
| pExitBmpsParams->sendDataNull = 1; |
| |
| pExitBmpsParams->bssIdx = psessionEntry->bssIdx; |
| |
| /* we need to defer any incoming messages until we |
| * get a WDA_EXIT_BMPS_RSP from HAL. |
| */ |
| SET_LIM_PROCESS_DEFD_MESGS(pMac, false); |
| MTRACE(macTraceMsgTx(pMac, NO_SESSION, msgQ.type)); |
| retStatus = wdaPostCtrlMsg( pMac, &msgQ); |
| if( eSIR_SUCCESS != retStatus ) |
| { |
| PELOGE(pmmLog( pMac, LOGE, FL("Sending WDA_EXIT_BMPS_REQ failed, reason=%X "), retStatus );) |
| vos_mem_free(pExitBmpsParams); |
| return retStatus; |
| } |
| |
| PELOG1(pmmLog(pMac, LOG1, FL("WDA_EXIT_BMPS_REQ has been successfully sent to HAL"));) |
| return retStatus; |
| } |
| |
| |
| /** |
| * pmmSendInitPowerSaveMsg() |
| * |
| *FUNCTION: |
| * This function is called to send ENTER_BMPS_REQ message to HAL. |
| * This message is sent to initialize the process of bringing the |
| * station into power save state. |
| * |
| *LOGIC: |
| * |
| *ASSUMPTIONS: |
| * NA |
| * |
| *NOTE: |
| * NA |
| * |
| * @param pMac pointer to Global Mac structure. |
| * @param mode The Power Save or Active State |
| * |
| * @return success if message send is ok, else false. |
| */ |
| |
| tSirRetStatus pmmSendInitPowerSaveMsg(tpAniSirGlobal pMac,tpPESession psessionEntry) |
| { |
| tSirRetStatus retCode = eSIR_SUCCESS; |
| tSirMsgQ msgQ; |
| tpEnterBmpsParams pBmpsParams = NULL; |
| tANI_U32 rssiFilterPeriod = 5; |
| tANI_U32 numBeaconPerRssiAverage = 20; |
| tANI_U32 bRssiFilterEnable = FALSE; |
| |
| if(psessionEntry->currentBssBeaconCnt == 0 ) |
| { |
| PELOGE(pmmLog( pMac, LOGE, FL("Beacon count is zero, can not retrieve the TSF, failing the Enter Bmps Request"));) |
| return eSIR_FAILURE; |
| } |
| |
| pBmpsParams = vos_mem_malloc(sizeof(*pBmpsParams)); |
| if ( NULL == pBmpsParams ) |
| { |
| pmmLog(pMac, LOGP, "PMM: Not able to allocate memory for Enter Bmps"); |
| return eSIR_FAILURE; |
| } |
| |
| vos_mem_zero(pBmpsParams, sizeof(*pBmpsParams)); |
| |
| pMac->pmm.inMissedBeaconScenario = FALSE; |
| pBmpsParams->respReqd = TRUE; |
| |
| pBmpsParams->tbtt = psessionEntry->lastBeaconTimeStamp; |
| pBmpsParams->dtimCount = psessionEntry->lastBeaconDtimCount; |
| pBmpsParams->dtimPeriod = psessionEntry->lastBeaconDtimPeriod; |
| pBmpsParams->bssIdx = psessionEntry->bssIdx; |
| |
| /* TODO: Config parameters (Rssi filter period, FW RSSI Monitoring |
| and Number of beacons per RSSI average) values sent down to FW during |
| initial exchange (driver load) is same as ENTER_BMPS_REQ. |
| Sending these values again in ENTER_BMPS_REQ is not required |
| (can be removed). This is kept as-is for now to support |
| backward compatibility with the older host running on new FW. */ |
| |
| if(wlan_cfgGetInt(pMac, WNI_CFG_RSSI_FILTER_PERIOD, &rssiFilterPeriod) != eSIR_SUCCESS) |
| pmmLog(pMac, LOGP, FL("pmmCfg: cfgGet failed for Rssi filter period")); |
| pBmpsParams->rssiFilterPeriod = (tANI_U8)rssiFilterPeriod; |
| |
| if(wlan_cfgGetInt(pMac, WNI_CFG_PS_ENABLE_RSSI_MONITOR, &bRssiFilterEnable) != eSIR_SUCCESS) |
| pmmLog(pMac, LOGP, FL("pmmCfg: cfgGet failed for Rssi monitor enable flag")); |
| pBmpsParams->bRssiFilterEnable = bRssiFilterEnable; |
| |
| /* The numBeaconPerRssiAverage should be less than |
| the max allowed (default set to 20 in CFG) */ |
| if(wlan_cfgGetInt(pMac, WNI_CFG_NUM_BEACON_PER_RSSI_AVERAGE, &numBeaconPerRssiAverage) != eSIR_SUCCESS) |
| pmmLog(pMac, LOGP, FL("pmmCfg: cfgGet failed for num beacon per rssi")); |
| |
| pBmpsParams->numBeaconPerRssiAverage = |
| (tANI_U8)GET_MIN_VALUE((tANI_U8) numBeaconPerRssiAverage, WNI_CFG_NUM_BEACON_PER_RSSI_AVERAGE_STAMAX); |
| |
| pmmLog (pMac, LOG1, |
| "%s: RssiFilterInfo..%d %x %x", __func__, (int)pBmpsParams->bRssiFilterEnable, |
| (unsigned int)pBmpsParams->rssiFilterPeriod, (unsigned int)pBmpsParams->numBeaconPerRssiAverage); |
| |
| msgQ.type = WDA_ENTER_BMPS_REQ; |
| msgQ.reserved = 0; |
| msgQ.bodyptr = pBmpsParams; |
| msgQ.bodyval = 0; |
| |
| PELOG2(pmmLog( pMac, LOG2, |
| FL( "pmmBmps: Sending WDA_ENTER_BMPS_REQ" ));) |
| |
| /* we need to defer any incoming messages until we get a |
| * WDA_ENTER_BMPS_RSP from HAL. |
| */ |
| SET_LIM_PROCESS_DEFD_MESGS(pMac, false); |
| |
| MTRACE(macTraceMsgTx(pMac, psessionEntry->peSessionId, msgQ.type)); |
| if( eSIR_SUCCESS != (retCode = wdaPostCtrlMsg( pMac, &msgQ ))) |
| { |
| vos_mem_free(pBmpsParams); |
| PELOGE(pmmLog( pMac, LOGE, |
| FL("Posting WDA_ENTER_BMPS_REQ to HAL failed, reason=%X"), |
| retCode );) |
| } |
| |
| return retCode; |
| } |
| |
| /** |
| * pmmSendPowerSaveCfg() |
| * |
| *FUNCTION: |
| * This function is called to send power save configuration. |
| * |
| *NOTE: |
| * |
| * @param pMac pointer to Global Mac structure. |
| * @param mode The Power Save or Active State |
| * |
| * @return success if message send is ok, else false. |
| */ |
| tSirRetStatus pmmSendPowerSaveCfg(tpAniSirGlobal pMac, tpSirPowerSaveCfg pUpdatedPwrSaveCfg) |
| { |
| tSirRetStatus retCode = eSIR_SUCCESS; |
| tSirMsgQ msgQ; |
| tANI_U32 listenInterval; |
| tANI_U32 HeartBeatCount = 1; |
| tANI_U32 maxPsPoll; |
| tANI_U32 numBeaconPerRssiAverage; |
| tANI_U32 minRssiThreshold; |
| tANI_U32 nthBeaconFilter; |
| tANI_U32 broadcastFrameFilter; |
| tANI_U32 rssiFilterPeriod; |
| tANI_U32 ignoreDtim; |
| |
| if (NULL == pUpdatedPwrSaveCfg) |
| goto returnFailure; |
| |
| if(pMac->lim.gLimSmeState != eLIM_SME_IDLE_STATE ) |
| { |
| pmmLog(pMac, LOGE, |
| FL("pmmCfg: Power Save Configuration received in invalid global sme state %d"), |
| pMac->lim.gLimSmeState); |
| retCode = eSIR_SME_INVALID_STATE; |
| goto returnFailure; |
| } |
| |
| // Get power save configuration CFG values |
| if(wlan_cfgGetInt(pMac, WNI_CFG_LISTEN_INTERVAL, &listenInterval) != eSIR_SUCCESS) |
| pmmLog(pMac, LOGP, FL("pmmCfg: cfgGet failed for listen interval")); |
| pUpdatedPwrSaveCfg->listenInterval = (tANI_U16)listenInterval; |
| |
| if(wlan_cfgGetInt(pMac, WNI_CFG_HEART_BEAT_THRESHOLD, &HeartBeatCount) != eSIR_SUCCESS) |
| pmmLog(pMac, LOGP, FL("pmmCfg: cfgGet failed for heart beat thresh")); |
| |
| pMac->lim.gLimHeartBeatCount = HeartBeatCount; |
| pUpdatedPwrSaveCfg->HeartBeatCount = HeartBeatCount; |
| |
| if(wlan_cfgGetInt(pMac, WNI_CFG_NTH_BEACON_FILTER, &nthBeaconFilter) != eSIR_SUCCESS) |
| pmmLog(pMac, LOGP, FL("pmmCfg: cfgGet failed for Nth beacon filter")); |
| pUpdatedPwrSaveCfg->nthBeaconFilter = nthBeaconFilter; |
| |
| if(wlan_cfgGetInt(pMac, WNI_CFG_MAX_PS_POLL, &maxPsPoll) != eSIR_SUCCESS) |
| pmmLog(pMac, LOGP, FL("pmmCfg: cfgGet failed for max poll")); |
| pUpdatedPwrSaveCfg->maxPsPoll = maxPsPoll; |
| |
| if(wlan_cfgGetInt(pMac, WNI_CFG_MIN_RSSI_THRESHOLD, &minRssiThreshold) != eSIR_SUCCESS) |
| pmmLog(pMac, LOGP, FL("pmmCfg: cfgGet failed for min RSSI Threshold")); |
| pUpdatedPwrSaveCfg->minRssiThreshold = minRssiThreshold; |
| |
| if(wlan_cfgGetInt(pMac, WNI_CFG_NUM_BEACON_PER_RSSI_AVERAGE, &numBeaconPerRssiAverage) != eSIR_SUCCESS) |
| pmmLog(pMac, LOGP, FL("pmmCfg: cfgGet failed for num beacon per rssi")); |
| pUpdatedPwrSaveCfg->numBeaconPerRssiAverage = (tANI_U8) numBeaconPerRssiAverage; |
| |
| if(wlan_cfgGetInt(pMac, WNI_CFG_RSSI_FILTER_PERIOD, &rssiFilterPeriod) != eSIR_SUCCESS) |
| pmmLog(pMac, LOGP, FL("pmmCfg: cfgGet failed for Rssi filter period")); |
| pUpdatedPwrSaveCfg->rssiFilterPeriod = (tANI_U8) rssiFilterPeriod; |
| |
| if(wlan_cfgGetInt(pMac, WNI_CFG_BROADCAST_FRAME_FILTER_ENABLE, &broadcastFrameFilter) != eSIR_SUCCESS) |
| pmmLog(pMac, LOGP, FL("pmmCfg: cfgGet failed for Nth beacon filter")); |
| pUpdatedPwrSaveCfg->broadcastFrameFilter = (tANI_U8) broadcastFrameFilter; |
| |
| if(wlan_cfgGetInt(pMac, WNI_CFG_IGNORE_DTIM, &ignoreDtim) != eSIR_SUCCESS) |
| pmmLog(pMac, LOGP, FL("pmmCfg: cfgGet failed for ignoreDtim")); |
| pUpdatedPwrSaveCfg->ignoreDtim = (tANI_U8) ignoreDtim; |
| |
| //Save a copy of the CFG in global pmm context. |
| vos_mem_copy( (tANI_U8 *) &pMac->pmm.gPmmCfg, pUpdatedPwrSaveCfg, sizeof(tSirPowerSaveCfg)); |
| |
| |
| msgQ.type = WDA_PWR_SAVE_CFG; |
| msgQ.reserved = 0; |
| msgQ.bodyptr = pUpdatedPwrSaveCfg; |
| msgQ.bodyval = 0; |
| |
| PELOG1(pmmLog( pMac, LOG1, FL( "pmmBmps: Sending WDA_PWR_SAVE_CFG to HAL"));) |
| MTRACE(macTraceMsgTx(pMac, NO_SESSION, msgQ.type)); |
| if( eSIR_SUCCESS != (retCode = wdaPostCtrlMsg( pMac, &msgQ ))) |
| { |
| pmmLog( pMac, LOGP, |
| FL("Posting WDA_PWR_SAVE_CFG to HAL failed, reason=%X"), |
| retCode ); |
| goto returnFailure; |
| } |
| return retCode; |
| |
| returnFailure: |
| |
| /* In case of failure, we need to free the memory */ |
| if (NULL != pUpdatedPwrSaveCfg) |
| { |
| vos_mem_free(pUpdatedPwrSaveCfg); |
| } |
| return retCode; |
| } |
| |
| /** |
| * pmmExitBmpsResponseHandler |
| * |
| *FUNCTION: |
| * This function processes the Wakeup Rsp from HAL and if successful, |
| * sends a response back to PMC layer. |
| *LOGIC: |
| * |
| *ASSUMPTIONS: |
| * NA |
| * |
| *NOTE: |
| * NA |
| * |
| * @param pMac pointer to Global Mac structure. |
| * @param rspStatus Status of the response, Success or an error code. |
| * |
| * @return none. |
| */ |
| void pmmExitBmpsResponseHandler(tpAniSirGlobal pMac, tpSirMsgQ limMsg) |
| { |
| tpExitBmpsParams pExitBmpsRsp; |
| eHalStatus rspStatus; |
| tANI_U8 PowersavesessionId; |
| tpPESession psessionEntry; |
| tSirResultCodes retStatus = eSIR_SME_SUCCESS; |
| |
| /* Copy the power save sessionId to the local variable */ |
| PowersavesessionId = pMac->pmm.sessionId; |
| |
| /* we need to process all the deferred messages enqueued since |
| * the initiating the SIR_HAL_EXIT_BMPS_REQ. |
| */ |
| |
| SET_LIM_PROCESS_DEFD_MESGS(pMac, true); |
| |
| if((psessionEntry = peFindSessionBySessionId(pMac,PowersavesessionId))==NULL) |
| { |
| pmmLog(pMac, LOGP,FL("Session Does not exist for given sessionID")); |
| return; |
| } |
| |
| if (NULL == limMsg->bodyptr) |
| { |
| pmmLog(pMac, LOGE, FL("Received SIR_HAL_EXIT_BMPS_RSP with NULL ")); |
| return; |
| } |
| pExitBmpsRsp = (tpExitBmpsParams)(limMsg->bodyptr); |
| rspStatus = pExitBmpsRsp->status; |
| |
| if(pMac->pmm.gPmmState != ePMM_STATE_BMPS_WT_WAKEUP_RSP) |
| { |
| PELOGE(pmmLog(pMac, LOGE, |
| FL("Received SIR_HAL_EXIT_BMPS_RSP while in incorrect state: %d"), |
| pMac->pmm.gPmmState);) |
| |
| retStatus = eSIR_SME_INVALID_PMM_STATE; |
| pmmBmpsUpdateInvalidStateCnt(pMac); |
| } |
| else |
| { |
| PELOGW(pmmLog(pMac, LOGW, FL("Received SIR_HAL_EXIT_BMPS_RSP in correct state. "));) |
| } |
| |
| /* PE is going to wakeup irrespective of whether |
| * SIR_HAL_EXIT_BMPS_REQ was successful or not |
| */ |
| switch (rspStatus) |
| { |
| case eHAL_STATUS_SUCCESS: |
| pMac->pmm.gPmmState = ePMM_STATE_BMPS_WAKEUP; |
| retStatus = eSIR_SME_SUCCESS; |
| break; |
| |
| default: |
| { |
| /* PE is going to be awake irrespective of whether EXIT_BMPS_REQ |
| * failed or not. This is mainly to eliminate the dead-lock condition |
| * But, PMC will be informed about the error. |
| */ |
| retStatus = eSIR_SME_BMPS_REQ_FAILED; |
| pMac->pmm.gPmmState = ePMM_STATE_BMPS_SLEEP; |
| } |
| break; |
| |
| } |
| |
| // turn on background scan |
| pMac->sys.gSysEnableScanMode = true; |
| |
| // send response to PMC |
| if(IS_FEATURE_SUPPORTED_BY_FW(SLM_SESSIONIZATION) ) |
| { |
| limSendSmeRsp(pMac, eWNI_PMC_EXIT_BMPS_RSP, retStatus, |
| psessionEntry->smeSessionId, psessionEntry->transactionId); |
| } |
| else |
| { |
| limSendSmeRsp(pMac, eWNI_PMC_EXIT_BMPS_RSP, retStatus, 0, 0); |
| } |
| |
| if ( pMac->pmm.gPmmExitBmpsReasonCode == eSME_MISSED_BEACON_IND_RCVD) |
| { |
| PELOGW(pmmLog(pMac, LOGW, FL("Rcvd SIR_HAL_EXIT_BMPS_RSP with MISSED_BEACON"));) |
| pmmMissedBeaconHandler(pMac); |
| } |
| else if(pMac->pmm.inMissedBeaconScenario) |
| { |
| PELOGW(pmmLog(pMac, LOGW, FL("Rcvd SIR_HAL_EXIT_BMPS_RSP in missed beacon scenario but reason code not correct"));) |
| pmmMissedBeaconHandler(pMac); |
| } |
| else |
| { |
| // Enable heartbeat timer |
| limReactivateHeartBeatTimer(pMac, psessionEntry); |
| } |
| return; |
| } |
| |
| |
| /** |
| * pmmMissedBeaconHandler() |
| * |
| *FUNCTION: |
| * This function is called when PMM receives an eWNI_PMC_EXIT_BMPS_REQ |
| * with reason code being eSME_MISSED_BEACON_IND_RCVD. |
| * |
| *NOTE: |
| * @param pMac pointer to Global Mac structure. |
| * @return none |
| */ |
| void pmmMissedBeaconHandler(tpAniSirGlobal pMac) |
| { |
| tANI_U8 pwrSaveSessionId; |
| tANI_U32 beaconInterval = 0; |
| tANI_U32 heartBeatInterval = pMac->lim.gLimHeartBeatCount; |
| tpPESession psessionEntry; |
| |
| /* Copy the power save sessionId to the local variable */ |
| pwrSaveSessionId = pMac->pmm.sessionId; |
| |
| if((psessionEntry = peFindSessionBySessionId(pMac,pwrSaveSessionId))==NULL) |
| { |
| pmmLog(pMac, LOGE,FL("Session Does not exist for given sessionID")); |
| return; |
| } |
| |
| |
| PELOGE(pmmLog(pMac, LOG1, FL("The device woke up due to MISSED BEACON "));) |
| |
| /* Proceed only if HeartBeat timer is created */ |
| if((pMac->lim.limTimers.gLimHeartBeatTimer.pMac) && |
| (pMac->lim.gLimTimersCreated)) |
| { |
| if (wlan_cfgGetInt(pMac, WNI_CFG_BEACON_INTERVAL, &beaconInterval) != eSIR_SUCCESS) |
| PELOG1(pmmLog(pMac, LOG1, FL("Fail to get BEACON_INTERVAL value"));) |
| |
| /* Change timer to reactivate it in future */ |
| heartBeatInterval= SYS_MS_TO_TICKS(beaconInterval * heartBeatInterval); |
| |
| if( tx_timer_change(&pMac->lim.limTimers.gLimHeartBeatTimer, |
| (tANI_U32)heartBeatInterval, 0) != TX_SUCCESS) |
| { |
| PELOG1(pmmLog(pMac, LOG1, FL("Fail to change HeartBeat timer"));) |
| } |
| |
| /* update some statistics */ |
| if(LIM_IS_CONNECTION_ACTIVE(psessionEntry)) |
| { |
| if(psessionEntry->LimRxedBeaconCntDuringHB < MAX_NO_BEACONS_PER_HEART_BEAT_INTERVAL) |
| pMac->lim.gLimHeartBeatBeaconStats[psessionEntry->LimRxedBeaconCntDuringHB]++; |
| else |
| pMac->lim.gLimHeartBeatBeaconStats[0]++; |
| } |
| |
| /* To handle the missed beacon failure, message is being posted to self as if the |
| * actual timer has expired. This is done to make sure that there exists one |
| * common entry and exit points |
| */ |
| limResetHBPktCount(psessionEntry); // 090805: This is what it SHOULD be. If we even need it. |
| pmmSendMessageToLim(pMac, SIR_LIM_HEART_BEAT_TIMEOUT); |
| } |
| else |
| { |
| PELOGE(pmmLog(pMac, LOGE, FL("HeartBeat Timer is not created, cannot re-activate"));) |
| } |
| |
| return; |
| } |
| |
| |
| /** |
| * pmmExitBmpsIndicationHandler |
| * |
| *FUNCTION: |
| * This function sends a Power Save Indication. back to PMC layer. |
| * This indication is originated from softmac and will occur in the following two |
| * scenarios: |
| * 1) When softmac is in sleep state and wakes up to parse TIM and finds that |
| * AP has the data pending for this STA, then it sends this indication to let PMC know |
| * that it is going to be awake and pass the control over to PMC |
| * 2) When softmac is in sleep state and wakes up to parse TIM and determines that |
| * current TIM is DTIM and AP has buffered broadcast/multicast frames. |
| * In this scenario, softmac needs to remain awake for broadcast/multicast frames and it |
| * sends an indication to PMC that it is awake and passes the control over to PMC. |
| * 3) If station is awake and 'fEnablePwrSaveImmediately' flag is set, then softmac will transmit all |
| * frames in its queues and go to sleep. Before going to sleep it sends the notification to PMC that |
| * it is going to sleep. |
| *LOGIC: |
| * |
| *ASSUMPTIONS: |
| * NA |
| * |
| *NOTE: |
| * NA |
| * |
| * @param pMac pointer to Global Mac structure. |
| * @param rspStatus Status of the response, Success or an error code. |
| * |
| * @return none. |
| */ |
| |
| void pmmExitBmpsIndicationHandler(tpAniSirGlobal pMac, tANI_U8 mode, eHalStatus rspStatus) |
| { |
| |
| tANI_U32 beaconInterval = 0; |
| tANI_U32 heartBeatInterval = pMac->lim.gLimHeartBeatCount; |
| tANI_U8 powersavesessionId; |
| tpPESession psessionEntry; |
| |
| /* Copy the power save sessionId to the local variable */ |
| powersavesessionId = pMac->pmm.sessionId; |
| |
| psessionEntry = peFindSessionBySessionId(pMac,powersavesessionId); |
| |
| if(psessionEntry == NULL) |
| { |
| PELOGE(pmmLog(pMac, LOGE, |
| FL("Session does Not exist with given sessionId :%d "),powersavesessionId);) |
| return; |
| } |
| |
| /* Since, the hardware is already woken up, PE also wakes up and informs |
| * the upper layers that the system is waking up. Hence always Success is |
| * sent in the reason code for the message sent to PMC |
| */ |
| |
| PELOGW(pmmLog(pMac, LOGW, |
| FL("pmmBmps: Received SIR_HAL_EXIT_BMPS_IND from HAL, Exiting BMPS sleep mode")); ) |
| |
| pMac->pmm.gPmmState = ePMM_STATE_BMPS_WAKEUP; |
| |
| /* turn on background scan */ |
| pMac->sys.gSysEnableScanMode = true; |
| |
| pmmBmpsUpdateWakeupIndCnt(pMac); |
| |
| /* Inform SME about the system awake state */ |
| limSendSmeRsp(pMac, |
| eWNI_PMC_EXIT_BMPS_IND, |
| eSIR_SME_SUCCESS, 0, 0); |
| |
| switch(rspStatus) |
| { |
| |
| /* The SoftMAC sends wakeup indication even when Heart-Beat timer expired |
| * The PE should start taking action against this as soon as it identifies |
| * that the SoftMAC has identified heart-beat miss |
| */ |
| case eHAL_STATUS_HEARTBEAT_TMOUT: |
| { |
| PELOG1(pmmLog(pMac, LOG1, |
| FL("pmmBmps: The device woke up due to HeartBeat Timeout"));) |
| |
| /* Proceed only if HeartBeat timer is created */ |
| if((pMac->lim.limTimers.gLimHeartBeatTimer.pMac) && |
| (pMac->lim.gLimTimersCreated)) |
| { |
| |
| /* Read the beacon interval from sessionTable */ |
| beaconInterval = psessionEntry->beaconParams.beaconInterval; |
| |
| /* Change timer to reactivate it in future */ |
| heartBeatInterval= SYS_MS_TO_TICKS(beaconInterval * heartBeatInterval); |
| |
| if(tx_timer_change(&pMac->lim.limTimers.gLimHeartBeatTimer, |
| (tANI_U32)heartBeatInterval, 0) != TX_SUCCESS) |
| { |
| PELOG1(pmmLog(pMac, LOG1, |
| FL("pmmBmps: Unable to change HeartBeat timer"));) |
| } |
| |
| /* update some statistics */ |
| if(LIM_IS_CONNECTION_ACTIVE(psessionEntry)) |
| { |
| if(psessionEntry->LimRxedBeaconCntDuringHB < MAX_NO_BEACONS_PER_HEART_BEAT_INTERVAL) |
| pMac->lim.gLimHeartBeatBeaconStats[psessionEntry->LimRxedBeaconCntDuringHB]++; |
| else |
| pMac->lim.gLimHeartBeatBeaconStats[0]++; |
| } |
| |
| /* To handle the heartbeat failure, message is being posted to self as if the |
| * actual timer has expired. This is done to make sure that there exists one |
| * common entry and exit points |
| */ |
| pmmSendMessageToLim(pMac, SIR_LIM_HEART_BEAT_TIMEOUT); |
| |
| } |
| else |
| { |
| |
| PELOGE(pmmLog(pMac, LOGE, |
| FL("pmmBmps: HeartBeat Timer is not created, cannot re-activate"));) |
| } |
| } |
| break; |
| |
| case eHAL_STATUS_NTH_BEACON_DELIVERY: |
| break; |
| |
| default: |
| break; |
| |
| } |
| |
| return; |
| |
| } |
| |
| |
| // -------------------------------------------------------------------- |
| /** |
| * pmmProcessMessage |
| * |
| * FUNCTION: Processes the next received Power Management message |
| * |
| * LOGIC: |
| * |
| * ASSUMPTIONS: |
| * |
| * NOTE: |
| * |
| * @param None |
| * @return None |
| */ |
| |
| void pmmProcessMessage(tpAniSirGlobal pMac, tpSirMsgQ pMsg) |
| { |
| switch (pMsg->type) |
| { |
| case eWNI_PMC_PWR_SAVE_CFG: |
| { |
| tpSirPowerSaveCfg pPSCfg; |
| tSirMbMsg *pMbMsg = (tSirMbMsg *)pMsg->bodyptr; |
| |
| pPSCfg = vos_mem_malloc(sizeof(*pPSCfg)); |
| if ( NULL == pPSCfg ) |
| { |
| pmmLog(pMac, LOGP, "PMM: Not able to allocate memory for PMC Config"); |
| } |
| vos_mem_copy(pPSCfg, pMbMsg->data, sizeof(*pPSCfg)); |
| pmmSendPowerSaveCfg(pMac, pPSCfg); |
| } |
| break; |
| |
| case eWNI_PMC_ENTER_BMPS_REQ: |
| pmmInitBmpsPwrSave(pMac); |
| break; |
| |
| case WDA_ENTER_BMPS_RSP: |
| pmmInitBmpsResponseHandler(pMac, pMsg); |
| break; |
| |
| case eWNI_PMC_EXIT_BMPS_REQ: |
| { |
| tpExitBmpsInfo pExitBmpsInfo; |
| tSirMbMsg *pMbMsg = (tSirMbMsg *)pMsg->bodyptr; |
| |
| pExitBmpsInfo = vos_mem_malloc(sizeof(*pExitBmpsInfo)); |
| if ( NULL == pExitBmpsInfo ) |
| { |
| pmmLog(pMac, LOGP, "PMM: Failed to allocate memory for Exit BMPS Info "); |
| } |
| vos_mem_copy(pExitBmpsInfo, pMbMsg->data, sizeof(*pExitBmpsInfo)); |
| pmmExitBmpsRequestHandler(pMac, pExitBmpsInfo); |
| } |
| break; |
| |
| case WDA_EXIT_BMPS_RSP: |
| pmmExitBmpsResponseHandler(pMac, pMsg); |
| break; |
| |
| case WDA_EXIT_BMPS_IND: |
| pmmExitBmpsIndicationHandler(pMac, SIR_PM_ACTIVE_MODE, (eHalStatus)pMsg->bodyval); |
| break; |
| |
| case eWNI_PMC_ENTER_IMPS_REQ: |
| pmmEnterImpsRequestHandler(pMac); |
| break; |
| |
| case WDA_ENTER_IMPS_RSP: |
| pmmEnterImpsResponseHandler(pMac, (eHalStatus)pMsg->bodyval); |
| break; |
| |
| case eWNI_PMC_EXIT_IMPS_REQ: |
| pmmExitImpsRequestHandler(pMac); |
| break; |
| |
| case WDA_EXIT_IMPS_RSP: |
| pmmExitImpsResponseHandler(pMac, (eHalStatus)pMsg->bodyval); |
| break; |
| |
| case eWNI_PMC_ENTER_UAPSD_REQ: |
| pmmEnterUapsdRequestHandler(pMac); |
| break; |
| |
| case WDA_ENTER_UAPSD_RSP: |
| pmmEnterUapsdResponseHandler(pMac, pMsg); |
| break; |
| |
| case eWNI_PMC_EXIT_UAPSD_REQ: |
| pmmExitUapsdRequestHandler(pMac); |
| break; |
| |
| case WDA_EXIT_UAPSD_RSP: |
| pmmExitUapsdResponseHandler(pMac, pMsg); |
| break; |
| |
| case eWNI_PMC_WOWL_ADD_BCAST_PTRN: |
| pmmSendWowlAddBcastPtrn(pMac, pMsg); |
| break; |
| |
| case eWNI_PMC_WOWL_DEL_BCAST_PTRN: |
| pmmSendWowlDelBcastPtrn(pMac, pMsg); |
| break; |
| |
| case eWNI_PMC_ENTER_WOWL_REQ: |
| pmmEnterWowlRequestHandler(pMac, pMsg); |
| break; |
| |
| case WDA_WOWL_ENTER_RSP: |
| pmmEnterWowlanResponseHandler(pMac, pMsg); |
| break; |
| |
| case eWNI_PMC_EXIT_WOWL_REQ: |
| pmmExitWowlanRequestHandler(pMac, pMsg); |
| break; |
| |
| case WDA_WOWL_EXIT_RSP: |
| pmmExitWowlanResponseHandler(pMac, pMsg); |
| break; |
| #ifdef WLAN_FEATURE_PACKET_FILTERING |
| case WDA_PACKET_COALESCING_FILTER_MATCH_COUNT_RSP: |
| pmmFilterMatchCountResponseHandler(pMac, pMsg); |
| break; |
| #endif // WLAN_FEATURE_PACKET_FILTERING |
| |
| |
| #ifdef WLAN_FEATURE_GTK_OFFLOAD |
| case WDA_GTK_OFFLOAD_GETINFO_RSP: |
| pmmGTKOffloadGetInfoResponseHandler(pMac, pMsg); |
| break; |
| #endif // WLAN_FEATURE_GTK_OFFLOAD |
| |
| default: |
| PELOGW(pmmLog(pMac, LOGW, |
| FL("PMM: Unknown message in pmmMsgQ type %d, potential memory leak!!"), |
| pMsg->type);) |
| } |
| |
| if (NULL != pMsg->bodyptr) |
| { |
| vos_mem_free(pMsg->bodyptr); |
| pMsg->bodyptr = NULL; |
| } |
| } |
| |
| |
| |
| |
| |
| |
| // -------------------------------------------------------------------- |
| /** |
| * pmmPostMessage |
| * |
| * FUNCTION: |
| * Post a message to the pmm message queue |
| * |
| * LOGIC: |
| * |
| * ASSUMPTIONS: |
| * |
| * NOTE: |
| * |
| * @param pMsg pointer to message |
| * @return None |
| */ |
| |
| tSirRetStatus |
| pmmPostMessage(tpAniSirGlobal pMac, tpSirMsgQ pMsg) |
| { |
| VOS_STATUS vosStatus; |
| vosStatus = vos_mq_post_message(VOS_MQ_ID_PE, (vos_msg_t *) pMsg); |
| if(!VOS_IS_STATUS_SUCCESS(vosStatus)) |
| { |
| pmmLog(pMac, LOGP, FL("vos_mq_post_message failed with status code %d"), vosStatus); |
| return eSIR_FAILURE; |
| } |
| |
| return eSIR_SUCCESS; |
| } |
| |
| // -------------------------------------------------------------------- |
| /** |
| * pmmEnterImpsRequestHandler |
| * |
| * FUNCTION: |
| * This function sends the idle mode power save request from host device |
| * drive to HAL. This function is called from pmmProcessMsg() |
| * |
| * LOGIC: |
| * |
| * ASSUMPTIONS: |
| * None |
| * |
| * NOTE: |
| * |
| * @param Global handle to MAC |
| * @return None |
| */ |
| void pmmEnterImpsRequestHandler (tpAniSirGlobal pMac) |
| { |
| tSirResultCodes resultCode = eSIR_SME_SUCCESS; |
| tSirRetStatus retStatus = eSIR_SUCCESS; |
| tPmmState origState = pMac->pmm.gPmmState; |
| |
| #ifdef FEATURE_WLAN_DIAG_SUPPORT |
| limDiagEventReport(pMac, WLAN_PE_DIAG_ENTER_IMPS_REQ_EVENT, peGetValidPowerSaveSession(pMac), 0, 0); |
| #endif //FEATURE_WLAN_DIAG_SUPPORT |
| |
| /*Returns True even single active session present */ |
| if(peIsAnySessionActive(pMac)) |
| { |
| /* Print active pesession and tracedump once in every 16 |
| * continuous error. |
| */ |
| if (!(pMac->pmc.ImpsReqFailCnt & 0xF)) |
| { |
| pePrintActiveSession(pMac); |
| } |
| resultCode = eSIR_SME_INVALID_STATE; |
| pmmLog(pMac, LOGE, FL("Session is active go to failure resultCode = " |
| "eSIR_SME_INVALID_STATE (%d)"),resultCode); |
| goto failure; |
| } |
| |
| if ( ((pMac->pmm.gPmmState != ePMM_STATE_READY) && |
| (pMac->pmm.gPmmState != ePMM_STATE_IMPS_WAKEUP)) || |
| ((pMac->lim.gLimSmeState != eLIM_SME_IDLE_STATE) && |
| (pMac->lim.gLimSmeState != eLIM_SME_JOIN_FAILURE_STATE)) || |
| (pMac->lim.gLimMlmState != eLIM_MLM_IDLE_STATE) || |
| limIsChanSwitchRunning (pMac) || |
| limIsInQuietDuration (pMac) ) |
| { |
| PELOGE(pmmLog(pMac, LOGE, |
| FL("pmmImps: PMM State = %d, Global MLM State = %d, Global SME State = %d, rejecting the sleep mode request"), |
| pMac->pmm.gPmmState, pMac->lim.gLimMlmState, pMac->lim.gLimSmeState);) |
| |
| resultCode = eSIR_SME_INVALID_PMM_STATE; |
| pmmImpsUpdateErrStateStats(pMac); |
| goto failure; |
| } |
| |
| // change PE state and send the request to HAL |
| pMac->pmm.gPmmState = ePMM_STATE_IMPS_WT_SLEEP_RSP; |
| if( (retStatus = pmmImpsSendChangePwrSaveMsg(pMac, SIR_PM_SLEEP_MODE)) != eSIR_SUCCESS) |
| { |
| PELOGE(pmmLog(pMac, LOGE, |
| FL("pmmImps: IMPS Sleep Request failed: sending response: %x"), retStatus);) |
| |
| resultCode = eSIR_SME_IMPS_REQ_FAILED; |
| goto failure; |
| } |
| else |
| { |
| PELOG1(pmmLog(pMac, LOG1, |
| FL("pmmImps: Waiting for SoftMac response for IMPS request"));) |
| } |
| return; |
| |
| failure: |
| pMac->pmm.gPmmState = origState; |
| pmmImpsUpdateSleepErrStats(pMac, retStatus); |
| |
| limSendSmeRsp(pMac, |
| eWNI_PMC_ENTER_IMPS_RSP, |
| resultCode, 0, 0); |
| |
| } |
| |
| // -------------------------------------------------------------------- |
| /** |
| * pmmEnterImpsResponseHandler |
| * |
| * FUNCTION: |
| * This function receives the response from HAL layer for the idle mode |
| * power save request sent. The function is also responsible for checking |
| * the correctness of the system state before configuring the new state |
| * on success. This function is called by pmmProcessMsg() |
| * |
| * LOGIC: |
| * |
| * ASSUMPTIONS: |
| * None |
| * |
| * NOTE: |
| * |
| * @param Global handle to MAC, Status code |
| * @return None |
| */ |
| void pmmEnterImpsResponseHandler (tpAniSirGlobal pMac, eHalStatus rspStatus) |
| { |
| tPmmState nextState = pMac->pmm.gPmmState; |
| tSirResultCodes resultCode = eSIR_SME_SUCCESS; |
| |
| /* we need to process all the deferred messages enqueued since |
| * the initiating the WDA_ENTER_IMPS_REQ. |
| */ |
| SET_LIM_PROCESS_DEFD_MESGS(pMac, true); |
| |
| if(pMac->pmm.gPmmState != ePMM_STATE_IMPS_WT_SLEEP_RSP) |
| { |
| PELOGE(pmmLog(pMac, LOGE, |
| FL("pmmImps: Receives IMPS sleep rsp in invalid state: %d"), |
| pMac->pmm.gPmmState);) |
| |
| resultCode = eSIR_SME_INVALID_PMM_STATE; |
| pmmImpsUpdateErrStateStats(pMac); |
| |
| goto failure; |
| } |
| |
| if(eHAL_STATUS_SUCCESS == rspStatus) |
| { |
| //if success, change the state to IMPS sleep mode |
| pMac->pmm.gPmmState = ePMM_STATE_IMPS_SLEEP; |
| |
| PELOG2(pmmLog(pMac, LOG2, |
| FL("pmmImps: Received successful WDA_ENTER_IMPS_RSP from HAL"));) |
| |
| //update power save statistics |
| pmmImpsUpdatePwrSaveStats(pMac); |
| |
| limSendSmeRsp(pMac, |
| eWNI_PMC_ENTER_IMPS_RSP, |
| resultCode, 0, 0); |
| } |
| else |
| { |
| // go back to previous state if request failed |
| nextState = ePMM_STATE_READY; |
| resultCode = eSIR_SME_CANNOT_ENTER_IMPS; |
| goto failure; |
| } |
| return; |
| |
| failure: |
| PELOGE(pmmLog(pMac, LOGE, |
| FL("pmmImpsSleepRsp failed, Ret Code: %d, next state will be: %d"), |
| rspStatus, |
| pMac->pmm.gPmmState);) |
| |
| pMac->pmm.gPmmState = nextState; |
| |
| limSendSmeRsp(pMac, |
| eWNI_PMC_ENTER_IMPS_RSP, |
| resultCode, 0, 0); |
| } |
| |
| |
| // -------------------------------------------------------------------- |
| /** |
| * pmmExitImpsRequestHandler |
| * |
| * FUNCTION: |
| * This function is called by pmmProcessMsg(). The function sends a request |
| * to HAL to wakeup the device from idle mode power save mode. |
| * |
| * LOGIC: |
| * |
| * ASSUMPTIONS: |
| * None |
| * |
| * NOTE: |
| * |
| * @param Global handle to MAC |
| * @return None |
| */ |
| void pmmExitImpsRequestHandler (tpAniSirGlobal pMac) |
| { |
| tSirRetStatus retStatus = eSIR_SUCCESS; |
| tSirResultCodes resultCode = eSIR_SME_SUCCESS; |
| |
| tPmmState origState = pMac->pmm.gPmmState; |
| |
| #ifdef FEATURE_WLAN_DIAG_SUPPORT |
| limDiagEventReport(pMac, WLAN_PE_DIAG_EXIT_IMPS_REQ_EVENT, peGetValidPowerSaveSession(pMac), 0, 0); |
| #endif //FEATURE_WLAN_DIAG_SUPPORT |
| |
| if (ePMM_STATE_IMPS_SLEEP == pMac->pmm.gPmmState) |
| { |
| pMac->pmm.gPmmState = ePMM_STATE_IMPS_WT_WAKEUP_RSP; |
| if( (retStatus = pmmImpsSendChangePwrSaveMsg(pMac, SIR_PM_ACTIVE_MODE)) != |
| eSIR_SUCCESS) |
| { |
| PELOGE(pmmLog(pMac, LOGE, |
| FL("pmmImps: Wakeup request message sent to SoftMac failed"));) |
| resultCode = eSIR_SME_IMPS_REQ_FAILED; |
| goto failure; |
| } |
| } |
| else |
| { |
| // PE in invalid state |
| PELOGE(pmmLog(pMac, LOGE, |
| FL("pmmImps: Wakeup Req received in invalid state: %x"), |
| pMac->pmm.gPmmState);) |
| |
| resultCode = eSIR_SME_INVALID_PMM_STATE; |
| pmmImpsUpdateErrStateStats(pMac); |
| |
| goto failure; |
| } |
| return; |
| |
| failure: |
| PELOGE(pmmLog (pMac, LOGE, |
| FL("pmmImps: Changing to IMPS wakeup mode failed, Ret Code: %d, Next State: %d"), |
| retStatus, pMac->pmm.gPmmState);) |
| |
| pMac->pmm.gPmmState = origState; |
| pmmImpsUpdateWakeupErrStats(pMac, retStatus); |
| |
| limSendSmeRsp(pMac, |
| eWNI_PMC_EXIT_IMPS_RSP, |
| resultCode, 0, 0); |
| } |
| |
| |
| // -------------------------------------------------------------------- |
| /** |
| * pmmExitImpsResponseHandler |
| * |
| * FUNCTION: |
| * This function receives the response from HAL layer for the idle mode |
| * power save request sent. The function is also responsible for checking |
| * the correctness of the system state before configuring the new state |
| * on success. This function is called by pmmProcessMsg() |
| * |
| * LOGIC: |
| * |
| * ASSUMPTIONS: |
| * None |
| * |
| * NOTE: |
| * |
| * @param Global handle to MAC |
| * @return None |
| */ |
| void pmmExitImpsResponseHandler(tpAniSirGlobal pMac, eHalStatus rspStatus) |
| { |
| tSirResultCodes resultCode = eSIR_SME_SUCCESS; |
| |
| /* we need to process all the deferred messages enqueued since |
| * the initiating the WDA_EXIT_IMPS_REQ. |
| */ |
| SET_LIM_PROCESS_DEFD_MESGS(pMac, true); |
| |
| if (pMac->pmm.gPmmState != ePMM_STATE_IMPS_WT_WAKEUP_RSP) |
| { |
| PELOGE(pmmLog(pMac, LOGE, |
| FL("pmmImps: Received 'Wakeup' response in invalid state: %d"), |
| pMac->pmm.gPmmState);) |
| |
| resultCode = eSIR_SME_INVALID_PMM_STATE; |
| pmmImpsUpdateErrStateStats(pMac); |
| } |
| |
| switch(rspStatus) |
| { |
| case eHAL_STATUS_SUCCESS: |
| { |
| resultCode = eSIR_SME_SUCCESS; |
| pMac->pmm.gPmmState = ePMM_STATE_IMPS_WAKEUP; |
| PELOG2(pmmLog(pMac, LOG2, |
| FL("pmmImps: Received WDA_EXIT_IMPS_RSP with Successful response from HAL"));) |
| } |
| break; |
| |
| default: |
| { |
| resultCode = eSIR_SME_IMPS_REQ_FAILED; |
| /* Set the status back to IMPS SLEEP as we failed |
| * to come out of sleep |
| */ |
| pMac->pmm.gPmmState = ePMM_STATE_IMPS_SLEEP; |
| PELOGW(pmmLog(pMac, LOGW, |
| FL("pmmImps: Received WDA_EXIT_IMPS_RSP with Failure Status from HAL"));) |
| } |
| break; |
| } |
| |
| //update power save statistics |
| pmmImpsUpdateWakeupStats(pMac); |
| |
| limSendSmeRsp(pMac, |
| eWNI_PMC_EXIT_IMPS_RSP, |
| resultCode, 0, 0); |
| return; |
| |
| } |
| |
| // -------------------------------------------------------------------- |
| /** |
| * pmmEnterUapsdRequestHandler |
| * |
| * FUNCTION: |
| * This function process the eWNI_PMC_ENTER_UAPSD_REQ from PMC, |
| * checks the correctness of the system state before configuring |
| * PMM to the new ePMM_STATE_UAPSD_WT_SLEEP_RSP state, and invokes |
| * invokes pmmUapsdSendChangePwrSaveMsg() to send |
| * WDA_ENTER_UAPSD_REQ to HAL. |
| * |
| * NOTE: |
| * |
| * @param Global handle to MAC |
| * @return None |
| */ |
| void pmmEnterUapsdRequestHandler (tpAniSirGlobal pMac) |
| { |
| tSirResultCodes resultCode = eSIR_SME_SUCCESS; |
| tSirRetStatus retStatus = eSIR_SUCCESS; |
| |
| tPmmState origState = pMac->pmm.gPmmState; |
| |
| #ifdef FEATURE_WLAN_DIAG_SUPPORT |
| limDiagEventReport(pMac, WLAN_PE_DIAG_ENTER_UAPSD_REQ_EVENT, peGetValidPowerSaveSession(pMac), 0, 0); |
| #endif //FEATURE_WLAN_DIAG_SUPPORT |
| |
| if ( (pMac->pmm.gPmmState != ePMM_STATE_BMPS_SLEEP) || |
| limIsSystemInScanState(pMac) ) |
| { |
| PELOGE(pmmLog(pMac, LOGE, |
| FL("pmmUapsd: PMM State = %d, Global MLM State = %d, Global SME State = %d, rejecting the sleep mode request"), |
| pMac->pmm.gPmmState, pMac->lim.gLimMlmState, pMac->lim.gLimSmeState);) |
| |
| resultCode = eSIR_SME_INVALID_PMM_STATE; |
| goto failure; |
| } |
| |
| pMac->pmm.gPmmState = ePMM_STATE_UAPSD_WT_SLEEP_RSP; |
| |
| if( (retStatus = pmmUapsdSendChangePwrSaveMsg(pMac, SIR_PM_SLEEP_MODE)) != eSIR_SUCCESS) |
| { |
| PELOGE(pmmLog(pMac, LOGE, |
| FL("pmmUapsd: HAL_ENTER_UAPSD_REQ failed with response: %x"), retStatus);) |
| resultCode = eSIR_SME_UAPSD_REQ_FAILED; |
| goto failure; |
| } |
| |
| PELOG1(pmmLog(pMac, LOG1, FL("pmmUapsd: Waiting for WDA_ENTER_UAPSD_RSP "));) |
| return; |
| |
| failure: |
| pMac->pmm.gPmmState = origState; |
| limSendSmeRsp(pMac, eWNI_PMC_ENTER_UAPSD_RSP, resultCode, 0, 0); |
| return; |
| } |
| |
| |
| // -------------------------------------------------------------------- |
| /** |
| * pmmEnterUapsdResponseHandler |
| * |
| * FUNCTION: |
| * This function processes the SIR_HAL_ENTER_UAPSD_RSP from HAL. |
| * If the response is successful, it puts PMM into ePMM_STATE_UAPSD_SLEEP |
| * state and sends back success response to PMC. |
| * |
| * NOTE: |
| * |
| * @param limMsg |
| * @return None |
| */ |
| void pmmEnterUapsdResponseHandler(tpAniSirGlobal pMac, tpSirMsgQ limMsg) |
| { |
| tpUapsdParams pUapsdRspMsg; |
| tSirResultCodes retStatus = eSIR_SME_SUCCESS; |
| |
| tANI_U8 PowersavesessionId; |
| tpPESession psessionEntry; |
| |
| /* we need to process all the deferred messages enqueued since |
| * the initiating the SIR_HAL_ENTER_UAPSD_REQ. |
| */ |
| SET_LIM_PROCESS_DEFD_MESGS(pMac, true); |
| |
| /* Copy the power save sessionId to the local variable */ |
| PowersavesessionId = pMac->pmm.sessionId; |
| |
| if (NULL == limMsg->bodyptr) |
| { |
| PELOGE(pmmLog(pMac, LOGE, FL("pmmUapsd: Received SIR_HAL_ENTER_UAPSD_RSP with NULL "));) |
| return; |
| } |
| |
| pUapsdRspMsg = (tpUapsdParams)(limMsg->bodyptr); |
| |
| if((psessionEntry = peFindSessionBySessionId(pMac,PowersavesessionId))==NULL) |
| { |
| pmmLog(pMac, LOGP,FL("Session Does not exist for given sessionID")); |
| return; |
| } |
| |
| if(pMac->pmm.gPmmState != ePMM_STATE_UAPSD_WT_SLEEP_RSP) |
| { |
| PELOGE(pmmLog(pMac, LOGE, |
| FL("pmmUapsd: Received SIR_HAL_ENTER_UAPSD_RSP while in incorrect state: %d"), |
| pMac->pmm.gPmmState);) |
| limSendSmeRsp(pMac, eWNI_PMC_ENTER_UAPSD_RSP, eSIR_SME_INVALID_PMM_STATE, 0, 0); |
| return; |
| } |
| |
| if(pUapsdRspMsg->status == eHAL_STATUS_SUCCESS) |
| { |
| PELOGW(pmmLog(pMac, LOGW, |
| FL("pmmUapsd: Received successful response from HAL to enter UAPSD mode "));) |
| pMac->pmm.gPmmState = ePMM_STATE_UAPSD_SLEEP; |
| } |
| else |
| { |
| PELOGE(pmmLog(pMac, LOGE, |
| FL("pmmUapsd: SIR_HAL_ENTER_UAPSD_RSP failed, informing SME"));) |
| pMac->pmm.gPmmState = ePMM_STATE_BMPS_SLEEP; |
| retStatus = eSIR_SME_UAPSD_REQ_FAILED; |
| } |
| |
| if(IS_FEATURE_SUPPORTED_BY_FW(SLM_SESSIONIZATION)) |
| { |
| limSendSmeRsp(pMac, eWNI_PMC_ENTER_UAPSD_RSP, retStatus, |
| psessionEntry->smeSessionId, psessionEntry->transactionId); |
| } |
| else |
| { |
| limSendSmeRsp(pMac, eWNI_PMC_ENTER_UAPSD_RSP, retStatus, 0, 0); |
| } |
| |
| return; |
| } |
| |
| |
| // -------------------------------------------------------------------- |
| /** |
| * pmmExitUapsdRequestHandler |
| * |
| * FUNCTION: |
| * This function process the eWNI_PMC_EXIT_UAPSD_REQ from PMC, |
| * checks the correctness of the system state before configuring |
| * PMM to the new ePMM_STATE_UAPSD_WT_WAKEUP_RSP state, and |
| * invokes pmmUapsdSendChangePwrSaveMsg() to send |
| * SIR_HAL_EXIT_UAPSD_REQ to HAL. |
| * |
| * NOTE: |
| * |
| * @param Global handle to MAC |
| * @return None |
| */ |
| void pmmExitUapsdRequestHandler(tpAniSirGlobal pMac) |
| { |
| tSirRetStatus retStatus = eSIR_SUCCESS; |
| tSirResultCodes resultCode = eSIR_SME_SUCCESS; |
| |
| tPmmState origState = pMac->pmm.gPmmState; |
| |
| #ifdef FEATURE_WLAN_DIAG_SUPPORT |
| limDiagEventReport(pMac, WLAN_PE_DIAG_EXIT_UAPSD_REQ_EVENT, peGetValidPowerSaveSession(pMac), 0, 0); |
| #endif //FEATURE_WLAN_DIAG_SUPPORT |
| |
| if (ePMM_STATE_UAPSD_SLEEP == pMac->pmm.gPmmState) |
| { |
| pMac->pmm.gPmmState = ePMM_STATE_UAPSD_WT_WAKEUP_RSP; |
| if( (retStatus = pmmUapsdSendChangePwrSaveMsg(pMac, SIR_PM_ACTIVE_MODE)) != |
| eSIR_SUCCESS) |
| { |
| PELOGE(pmmLog(pMac, LOGE, |
| FL("pmmUapsd: sending EXIT_UAPSD to HAL failed "));) |
| resultCode = eSIR_SME_UAPSD_REQ_FAILED; |
| goto failure; |
| } |
| } |
| else |
| { |
| PELOGE(pmmLog(pMac, LOGE, |
| FL("pmmUapsd: Rcv EXIT_UAPSD from PMC in invalid state: %x"), |
| pMac->pmm.gPmmState);) |
| |
| resultCode = eSIR_SME_INVALID_PMM_STATE; |
| goto failure; |
| } |
| return; |
| |
| failure: |
| pMac->pmm.gPmmState = origState; |
| PELOGE(pmmLog(pMac, LOGE, |
| FL("pmmUapsd: Waking up from UAPSD mode failed, Ret Code: %d, Next State: %d"), |
| retStatus, pMac->pmm.gPmmState);) |
| limSendSmeRsp(pMac, eWNI_PMC_EXIT_UAPSD_RSP, resultCode, 0, 0); |
| } |
| |
| |
| // -------------------------------------------------------------------- |
| /** |
| * pmmExitUapsdResponseHandler |
| * |
| * FUNCTION: |
| * This function receives the SIR_HAL_EXIT_UAPSD_RSP from HAL and is |
| * responsible for checking the correctness of the system state |
| * before configuring PMM to the new ePMM_STATE_BMPS_SLEEP state |
| * and send eWNI_PMC_EXIT_UAPSD_RSP to PMC. |
| * |
| * NOTE: |
| * |
| * @param Global handle to MAC |
| * @return None |
| */ |
| void pmmExitUapsdResponseHandler(tpAniSirGlobal pMac, tpSirMsgQ limMsg) |
| { |
| tSirResultCodes resultCode = eSIR_SME_SUCCESS; |
| tANI_U8 PowersavesessionId; |
| tpPESession psessionEntry; |
| tUapsdParams *pUapsdExitRspParams; |
| |
| /* we need to process all the deferred messages enqueued since |
| * the initiating the SIR_HAL_EXIT_UAPSD_REQ. |
| */ |
| SET_LIM_PROCESS_DEFD_MESGS(pMac, true); |
| |
| if (pMac->pmm.gPmmState != ePMM_STATE_UAPSD_WT_WAKEUP_RSP) |
| { |
| PELOGE(pmmLog(pMac, LOGE, |
| FL("Received HAL_EXIT_UAPSD_RSP in invalid state: %d"), |
| pMac->pmm.gPmmState);) |
| limSendSmeRsp(pMac, eWNI_PMC_EXIT_UAPSD_RSP, eSIR_SME_INVALID_PMM_STATE, 0, 0); |
| return; |
| } |
| pUapsdExitRspParams = (tUapsdParams *)(limMsg->bodyptr); |
| |
| PowersavesessionId = pMac->pmm.sessionId; |
| if((psessionEntry = peFindSessionBySessionId(pMac,PowersavesessionId))==NULL) |
| { |
| pmmLog(pMac, LOGP,FL("Session Does not exist for given sessionID")); |
| return; |
| } |
| |
| if(NULL == pUapsdExitRspParams ) |
| { |
| PELOGE(pmmLog(pMac, LOGE, |
| FL("Received HAL_EXIT_UAPSD_RSP message with zero parameters:"));) |
| limSendSmeRsp(pMac, eWNI_PMC_EXIT_UAPSD_RSP, eSIR_SME_UAPSD_REQ_FAILED, 0, 0); |
| return; |
| } |
| switch(pUapsdExitRspParams->status) |
| { |
| case eHAL_STATUS_SUCCESS: |
| resultCode = eSIR_SME_SUCCESS; |
| PELOGW(pmmLog(pMac, LOGW, |
| FL("Received SIR_HAL_EXIT_UAPSD_RSP with Successful response "));) |
| break; |
| default: |
| resultCode = eSIR_SME_UAPSD_REQ_FAILED; |
| PELOGE(pmmLog(pMac, LOGW, |
| FL("Received SIR_HAL_EXIT_UAPSD_RSP with Failure Status"));) |
| break; |
| } |
| |
| pMac->pmm.gPmmState = ePMM_STATE_BMPS_SLEEP; |
| |
| if(IS_FEATURE_SUPPORTED_BY_FW(SLM_SESSIONIZATION)) |
| { |
| limSendSmeRsp(pMac, eWNI_PMC_EXIT_UAPSD_RSP, resultCode, psessionEntry->smeSessionId, |
| psessionEntry->transactionId); |
| } |
| else |
| { |
| limSendSmeRsp(pMac, eWNI_PMC_EXIT_UAPSD_RSP, resultCode, 0, 0); |
| } |
| return; |
| } |
| |
| /** ------------------------------------------------------------ |
| \fn pmmSendWowlAddBcastPtrn |
| \brief This function sends a SIR_HAL_WOWL_ADD_BCAST_PTRN |
| \ message to HAL. |
| \param tpAniSirGlobal pMac |
| \param tpSirMsgQ pMsg |
| \return None |
| --------------------------------------------------------------*/ |
| void pmmSendWowlAddBcastPtrn(tpAniSirGlobal pMac, tpSirMsgQ pMsg) |
| { |
| tpSirWowlAddBcastPtrn pBcastPtrn; |
| tSirMbMsg *pMbMsg = (tSirMbMsg *)pMsg->bodyptr; |
| tSirRetStatus retCode = eSIR_SUCCESS; |
| tSirMsgQ msgQ; |
| |
| pBcastPtrn = vos_mem_malloc(sizeof(*pBcastPtrn)); |
| if ( NULL == pBcastPtrn ) |
| { |
| pmmLog(pMac, LOGP, FL("Fail to allocate memory for WoWLAN Add Bcast Pattern ")); |
| return; |
| } |
| vos_mem_copy(pBcastPtrn, pMbMsg->data, sizeof(*pBcastPtrn)); |
| |
| msgQ.type = WDA_WOWL_ADD_BCAST_PTRN; |
| msgQ.reserved = 0; |
| msgQ.bodyptr = pBcastPtrn; |
| msgQ.bodyval = 0; |
| |
| pmmLog(pMac, LOG1, FL( "Sending WDA_WOWL_ADD_BCAST_PTRN to HAL")); |
| #ifdef FEATURE_WLAN_DIAG_SUPPORT |
| limDiagEventReport(pMac, WLAN_PE_DIAG_WOWL_ADD_BCAST_PTRN_EVENT, NULL, 0, 0); |
| #endif //FEATURE_WLAN_DIAG_SUPPORT |
| |
| if( eSIR_SUCCESS != (retCode = wdaPostCtrlMsg( pMac, &msgQ ))) |
| { |
| if (pBcastPtrn != NULL) |
| vos_mem_free(pBcastPtrn); |
| pmmLog( pMac, LOGP, FL("Posting WDA_WOWL_ADD_BCAST_PTRN failed, reason=%X"), retCode ); |
| } |
| return; |
| } |
| |
| /** ------------------------------------------------------------ |
| \fn pmmSendWowlDelBcastPtrn |
| \brief This function sends a SIR_HAL_WOWL_DEL_BCAST_PTRN |
| \ message to HAL. |
| \param tpAniSirGlobal pMac |
| \param tpSirMsgQ pMsg |
| \return None |
| --------------------------------------------------------------*/ |
| void pmmSendWowlDelBcastPtrn(tpAniSirGlobal pMac, tpSirMsgQ pMsg) |
| { |
| tpSirWowlDelBcastPtrn pDeletePtrn; |
| tSirMbMsg *pMbMsg = (tSirMbMsg *)pMsg->bodyptr; |
| tSirRetStatus retCode = eSIR_SUCCESS; |
| tSirMsgQ msgQ; |
| |
| pDeletePtrn = vos_mem_malloc(sizeof(*pDeletePtrn)); |
| if ( NULL == pDeletePtrn ) |
| { |
| pmmLog(pMac, LOGP, FL("Fail to allocate memory for WoWLAN Delete Bcast Pattern ")); |
| return; |
| } |
| vos_mem_copy(pDeletePtrn, pMbMsg->data, sizeof(*pDeletePtrn)); |
| |
| if (NULL == pDeletePtrn) |
| { |
| pmmLog(pMac, LOGE, FL("Delete broadcast pattern message is NULL ")); |
| return; |
| } |
| |
| msgQ.type = WDA_WOWL_DEL_BCAST_PTRN; |
| msgQ.reserved = 0; |
| msgQ.bodyptr = pDeletePtrn; |
| msgQ.bodyval = 0; |
| |
| pmmLog(pMac, LOG1, FL( "Sending WDA_WOWL_DEL_BCAST_PTRN")); |
| #ifdef FEATURE_WLAN_DIAG_SUPPORT |
| limDiagEventReport(pMac, WLAN_PE_DIAG_WOWL_DEL_BCAST_PTRN_EVENT, NULL, 0, 0); |
| #endif //FEATURE_WLAN_DIAG_SUPPORT |
| |
| if( eSIR_SUCCESS != (retCode = wdaPostCtrlMsg( pMac, &msgQ ))) |
| { |
| if (NULL != pDeletePtrn) |
| vos_mem_free(pDeletePtrn); |
| pmmLog( pMac, LOGP, FL("Posting WDA_WOWL_DEL_BCAST_PTRN failed, reason=%X"), retCode ); |
| } |
| return; |
| } |
| |
| /** --------------------------------------------------------- |
| \fn pmmEnterWowlRequestHandler |
| \brief LIM process the eWNI_PMC_ENTER_WOWL_REQ message, and |
| \ invokes pmmSendWowlEnterRequest() to send |
| \ WDA_WOWL_ENTER_REQ message to HAL. |
| \param tpAniSirGlobal pMac |
| \param tpSirMsgQ pMsg |
| \return None |
| ------------------------------------------------------------*/ |
| void pmmEnterWowlRequestHandler(tpAniSirGlobal pMac, tpSirMsgQ pMsg) |
| { |
| tpSirSmeWowlEnterParams pSmeWowlParams = NULL; |
| tpSirHalWowlEnterParams pHalWowlParams = NULL; |
| tSirRetStatus retCode = eSIR_SUCCESS; |
| tANI_U32 cfgValue = 0; |
| tSirMbMsg *pMbMsg = (tSirMbMsg *)pMsg->bodyptr; |
| tpPESession pSessionEntry = NULL; |
| tANI_U8 peSessionId = 0; |
| |
| #ifdef FEATURE_WLAN_DIAG_SUPPORT |
| limDiagEventReport(pMac, WLAN_PE_DIAG_ENTER_WOWL_REQ_EVENT, NULL, 0, 0); |
| #endif //FEATURE_WLAN_DIAG_SUPPORT |
| |
| pSmeWowlParams = (tpSirSmeWowlEnterParams)(pMbMsg->data); |
| if (NULL == pSmeWowlParams) |
| { |
| pmmLog(pMac, LOGE, |
| FL("NULL message received")); |
| return; |
| } |
| |
| if (pMac->psOffloadEnabled) |
| goto skip_pmm_state_check; |
| |
| pSessionEntry = peFindSessionByBssid(pMac, pSmeWowlParams->bssId, |
| &peSessionId); |
| if (NULL == pSessionEntry) |
| { |
| pmmLog(pMac, LOGE, |
| FL("session does not exist for given BSSId")); |
| goto end; |
| } |
| pMac->pmm.sessionId = peSessionId; |
| |
| if ((pMac->pmm.gPmmState != ePMM_STATE_BMPS_SLEEP) && (pMac->pmm.gPmmState != ePMM_STATE_WOWLAN)) |
| { |
| pmmLog(pMac, LOGE, FL("Rcvd PMC_ENTER_WOWL_REQ in invalid Power Save state ")); |
| limSendSmeRsp(pMac, eWNI_PMC_ENTER_WOWL_RSP, eSIR_SME_INVALID_PMM_STATE, 0, 0); |
| goto end; |
| } |
| |
| skip_pmm_state_check: |
| |
| pHalWowlParams = vos_mem_malloc(sizeof(*pHalWowlParams)); |
| if ( NULL == pHalWowlParams ) |
| { |
| pmmLog(pMac, LOGP, FL("Fail to allocate memory for Enter Wowl Request ")); |
| goto end; |
| } |
| vos_mem_zero(pHalWowlParams, sizeof(*pHalWowlParams)); |
| |
| // fill in the message field |
| pHalWowlParams->ucMagicPktEnable = pSmeWowlParams->ucMagicPktEnable; |
| pHalWowlParams->ucPatternFilteringEnable = pSmeWowlParams->ucPatternFilteringEnable; |
| vos_mem_copy(pHalWowlParams->magicPtrn, |
| pSmeWowlParams->magicPtrn, sizeof(tSirMacAddr)); |
| |
| #ifdef WLAN_WAKEUP_EVENTS |
| pHalWowlParams->ucWoWEAPIDRequestEnable = pSmeWowlParams->ucWoWEAPIDRequestEnable; |
| pHalWowlParams->ucWoWEAPOL4WayEnable = pSmeWowlParams->ucWoWEAPOL4WayEnable; |
| pHalWowlParams->ucWowNetScanOffloadMatch = pSmeWowlParams->ucWowNetScanOffloadMatch; |
| pHalWowlParams->ucWowGTKRekeyError = pSmeWowlParams->ucWowGTKRekeyError; |
| pHalWowlParams->ucWoWBSSConnLoss = pSmeWowlParams->ucWoWBSSConnLoss; |
| #endif // WLAN_WAKEUP_EVENTS |
| |
| if (!pMac->psOffloadEnabled) |
| pHalWowlParams->bssIdx = pSessionEntry->bssIdx; |
| |
| if(wlan_cfgGetInt(pMac, WNI_CFG_WOWLAN_UCAST_PATTERN_FILTER_ENABLE, &cfgValue) != eSIR_SUCCESS) |
| { |
| pmmLog(pMac, LOGP, FL("cfgGet failed for WNI_CFG_WOWLAN_UCAST_PATTERN_FILTER_ENABLE")); |
| goto end; |
| } |
| pHalWowlParams->ucUcastPatternFilteringEnable = (tANI_U8)cfgValue; |
| |
| if(wlan_cfgGetInt(pMac, WNI_CFG_WOWLAN_CHANNEL_SWITCH_ENABLE, &cfgValue) != eSIR_SUCCESS) |
| { |
| pmmLog(pMac, LOGP, FL("cfgGet failed for WNI_CFG_WOWLAN_CHANNEL_SWITCH_ENABLE")); |
| goto end; |
| } |
| pHalWowlParams->ucWowChnlSwitchRcv = (tANI_U8)cfgValue; |
| |
| if(wlan_cfgGetInt(pMac, WNI_CFG_WOWLAN_DEAUTH_ENABLE, &cfgValue) != eSIR_SUCCESS) |
| { |
| pmmLog(pMac, LOGP, FL("cfgGet failed for WNI_CFG_WOWLAN_DEAUTH_ENABLE ")); |
| goto end; |
| } |
| pHalWowlParams->ucWowDeauthRcv = (tANI_U8)cfgValue; |
| |
| if(wlan_cfgGetInt(pMac, WNI_CFG_WOWLAN_DISASSOC_ENABLE, &cfgValue) != eSIR_SUCCESS) |
| { |
| pmmLog(pMac, LOGP, FL("cfgGet failed for WNI_CFG_WOWLAN_DEAUTH_ENABLE ")); |
| goto end; |
| } |
| pHalWowlParams->ucWowDisassocRcv = (tANI_U8)cfgValue; |
| |
| if(wlan_cfgGetInt(pMac, WNI_CFG_WOWLAN_MAX_MISSED_BEACON, &cfgValue) != eSIR_SUCCESS) |
| { |
| pmmLog(pMac, LOGP, FL("cfgGet failed for WNI_CFG_WOWLAN_MAX_MISSED_BEACON ")); |
| goto end; |
| } |
| pHalWowlParams->ucWowMaxMissedBeacons = (tANI_U8)cfgValue; |
| |
| if(wlan_cfgGetInt(pMac, WNI_CFG_WOWLAN_MAX_SLEEP_PERIOD, &cfgValue) != eSIR_SUCCESS) |
| { |
| pmmLog(pMac, LOGP, FL("cfgGet failed for WNI_CFG_WOWLAN_MAX_SLEEP_PERIOD ")); |
| goto end; |
| } |
| pHalWowlParams->ucWowMaxSleepUsec = (tANI_U8)cfgValue; |
| |
| pHalWowlParams->sessionId = pSmeWowlParams->sessionId; |
| //Send message to HAL |
| if( eSIR_SUCCESS != (retCode = pmmSendWowlEnterRequest( pMac, pHalWowlParams))) |
| { |
| pmmLog(pMac, LOGE, FL("Send ENTER_WOWL_REQ to HAL failed, reasonCode %d "), retCode); |
| limSendSmeRsp(pMac, eWNI_PMC_ENTER_WOWL_RSP, eSIR_SME_WOWL_ENTER_REQ_FAILED, 0, 0); |
| goto end; |
| } |
| return; |
| |
| end: |
| if (pHalWowlParams != NULL) |
| vos_mem_free(pHalWowlParams); |
| return; |
| } |
| |
| |
| /** ------------------------------------------------------------ |
| \fn pmmSendWowlEnterRequest |
| \brief LIM sends a WDA_WOWL_ENTER_REQ message to HAL with |
| \ the message structure pHalWowlParams. HAL shall later |
| \ send a WDA_WOWL_ENTER_RSP with the same pointer |
| \ to the message structure back to PMM. |
| \param tpAniSirGlobal pMac |
| \param tpSirHalWowlEnterParams pHalWowlParams |
| \return tSirRetStatus |
| --------------------------------------------------------------*/ |
| tSirRetStatus pmmSendWowlEnterRequest(tpAniSirGlobal pMac, tpSirHalWowlEnterParams pHalWowlParams) |
| { |
| tSirRetStatus retCode = eSIR_SUCCESS; |
| tSirMsgQ msgQ; |
| |
| if (NULL == pHalWowlParams) |
| return eSIR_FAILURE; |
| |
| msgQ.type = WDA_WOWL_ENTER_REQ; |
| msgQ.reserved = 0; |
| msgQ.bodyptr = pHalWowlParams; |
| msgQ.bodyval = 0; |
| |
| if (!pMac->psOffloadEnabled) |
| { |
| /* Defer any incoming message until we get |
| * a WDA_WOWL_ENTER_RSP from HAL |
| */ |
| SET_LIM_PROCESS_DEFD_MESGS(pMac, false); |
| } |
| |
| retCode = wdaPostCtrlMsg(pMac, &msgQ); |
| if( eSIR_SUCCESS != retCode ) |
| { |
| pmmLog( pMac, LOGE, FL("Posting WDA_WOWL_ENTER_REQ failed, reason=%X"), retCode ); |
| return retCode; |
| } |
| return retCode; |
| } |
| |
| /** --------------------------------------------------------- |
| \fn pmmEnterWowlanResponseHandler |
| \brief LIM process the WDA_WOWL_ENTER_RSP message. |
| \ and sends eWNI_PMC_ENTER_WOWL_RSP to SME. |
| \param tpAniSirGlobal pMac |
| \param tpSirMsgQ limMsg |
| \return None |
| ------------------------------------------------------------*/ |
| void pmmEnterWowlanResponseHandler(tpAniSirGlobal pMac, tpSirMsgQ limMsg) |
| { |
| tpSirHalWowlEnterParams pWowlEnterParams; |
| eHalStatus rspStatus; |
| tSirResultCodes smeRspCode = eSIR_SME_SUCCESS; |
| |
| /* we need to process all the deferred messages enqueued |
| * since the initiating the WDA_WOWL_ENTER_REQ. |
| */ |
| SET_LIM_PROCESS_DEFD_MESGS(pMac, true); |
| |
| pWowlEnterParams = (tpSirHalWowlEnterParams)(limMsg->bodyptr); |
| if (NULL == pWowlEnterParams) |
| { |
| pmmLog(pMac, LOGE, FL("Recvd WDA_WOWL_ENTER_RSP with NULL msg ")); |
| smeRspCode = eSIR_SME_WOWL_ENTER_REQ_FAILED; |
| } |
| else |
| { |
| rspStatus = pWowlEnterParams->status; |
| |
| if(rspStatus == eHAL_STATUS_SUCCESS) |
| { |
| pmmLog(pMac, LOGW, FL("Rcv successful response from HAL to enter WOWLAN ")); |
| pMac->pmm.gPmmState = ePMM_STATE_WOWLAN; |
| } |
| else |
| { |
| pmmLog(pMac, LOGE, FL("HAL enter WOWLAN failed, informing SME")); |
| smeRspCode = eSIR_SME_WOWL_ENTER_REQ_FAILED; |
| } |
| } |
| |
| limSendSmeRsp(pMac, eWNI_PMC_ENTER_WOWL_RSP, smeRspCode, 0, 0); |
| return; |
| } |
| |
| /** --------------------------------------------------------- |
| \fn pmmExitWowlanRequestHandler |
| \brief PE process the eWNI_PMC_EXIT_WOWL_REQ message. |
| \ and sends WDA_WOWL_EXIT_REQ to HAL. |
| \param tpAniSirGlobal pMac |
| \return None |
| ------------------------------------------------------------*/ |
| void pmmExitWowlanRequestHandler(tpAniSirGlobal pMac, tpSirMsgQ pMsg) |
| { |
| tpSirSmeWowlExitParams pSmeWowlParams = NULL; |
| tSirMbMsg *pMbMsg = (tSirMbMsg *)pMsg->bodyptr; |
| tSirRetStatus retStatus = eSIR_SUCCESS; |
| tSirResultCodes smeRspCode = eSIR_SME_SUCCESS; |
| tpPESession pSessionEntry = NULL; |
| tpSirHalWowlExitParams pHalWowlMsg = NULL; |
| tANI_U8 PowersavesessionId = 0; |
| |
| pSmeWowlParams = (tpSirSmeWowlExitParams)(pMbMsg->data); |
| if (NULL == pSmeWowlParams) |
| { |
| limLog(pMac, LOGE, |
| FL("NULL message received")); |
| return; |
| } |
| |
| if (pMac->psOffloadEnabled) |
| goto skip_pe_session_lookup; |
| |
| PowersavesessionId = pMac->pmm.sessionId; |
| |
| if((pSessionEntry = peFindSessionBySessionId(pMac,PowersavesessionId)) == NULL ) |
| { |
| PELOGW(pmmLog(pMac, LOGE, FL("pmmWowl : failed to allocate memory"));) |
| smeRspCode = eSIR_SME_WOWL_EXIT_REQ_FAILED; |
| goto failure; |
| } |
| |
| skip_pe_session_lookup: |
| |
| pHalWowlMsg = vos_mem_malloc(sizeof(*pHalWowlMsg)); |
| if ( NULL == pHalWowlMsg ) |
| { |
| pmmLog(pMac, LOGP, FL("Fail to allocate memory for WoWLAN Add Bcast Pattern ")); |
| smeRspCode = eSIR_SME_WOWL_EXIT_REQ_FAILED; |
| goto failure; |
| } |
| |
| #ifdef FEATURE_WLAN_DIAG_SUPPORT |
| limDiagEventReport(pMac, WLAN_PE_DIAG_EXIT_WOWL_REQ_EVENT, NULL, 0, 0); |
| #endif //FEATURE_WLAN_DIAG_SUPPORT |
| |
| if ( !pMac->psOffloadEnabled && pMac->pmm.gPmmState != ePMM_STATE_WOWLAN ) |
| { |
| pmmLog(pMac, LOGE, |
| FL("Exit WOWLAN Request received in invalid state PMM=%d "), |
| pMac->pmm.gPmmState); |
| smeRspCode = eSIR_SME_INVALID_PMM_STATE; |
| goto failure; |
| } |
| |
| vos_mem_zero(pHalWowlMsg, sizeof(*pHalWowlMsg)); |
| |
| if (!pMac->psOffloadEnabled) |
| pHalWowlMsg->bssIdx = pSessionEntry->bssIdx; |
| |
| pHalWowlMsg->sessionId = pSmeWowlParams->sessionId; |
| if((retStatus = pmmSendExitWowlReq(pMac, pHalWowlMsg)) != eSIR_SUCCESS) |
| { |
| pmmLog(pMac, LOGE, |
| FL("Fail to send WDA_WOWL_EXIT_REQ, reason code %d"), |
| retStatus); |
| smeRspCode = eSIR_SME_WOWL_EXIT_REQ_FAILED; |
| goto failure; |
| } |
| return; |
| |
| failure: |
| if (pHalWowlMsg != NULL) |
| vos_mem_free(pHalWowlMsg); |
| limSendSmeRsp(pMac, eWNI_PMC_EXIT_WOWL_RSP, smeRspCode, 0, 0); |
| return; |
| } |
| |
| /** --------------------------------------------------------- |
| \fn pmmSendExitWowlReq |
| \brief This function sends the WDA_WOWL_EXIT_REQ |
| \ message to HAL. |
| \param tpAniSirGlobal pMac |
| \return None |
| ------------------------------------------------------------*/ |
| tSirRetStatus pmmSendExitWowlReq(tpAniSirGlobal pMac, tpSirHalWowlExitParams pHalWowlParams) |
| { |
| tSirRetStatus retCode = eSIR_SUCCESS; |
| tSirMsgQ msgQ; |
| |
| if (NULL == pHalWowlParams) |
| return eSIR_FAILURE; |
| |
| msgQ.type = WDA_WOWL_EXIT_REQ; |
| msgQ.reserved = 0; |
| msgQ.bodyptr = pHalWowlParams; |
| msgQ.bodyval = 0; |
| |
| pmmLog(pMac, LOGW, FL("Sending WDA_WOWL_EXIT_REQ")); |
| |
| if (!pMac->psOffloadEnabled) |
| { |
| /* we need to defer any incoming messages until |
| * we get a WDA_WOWL_EXIT_RSP from HAL. |
| */ |
| SET_LIM_PROCESS_DEFD_MESGS(pMac, false); |
| } |
| |
| if( eSIR_SUCCESS != (retCode = wdaPostCtrlMsg( pMac, &msgQ ))) |
| pmmLog( pMac, LOGE, |
| FL("Posting WDA_WOWL_EXIT_REQ failed, reason=%X"), |
| retCode ); |
| |
| return retCode; |
| } |
| |
| /** --------------------------------------------------------- |
| \fn pmmExitWowlanResponseHandler |
| \brief This function process the WDA_WOWL_EXIT_RSP message. |
| \ and sends back eWNI_PMC_EXIT_WOWL_RSP to SME. |
| \param tpAniSirGlobal pMac |
| \return None |
| ------------------------------------------------------------*/ |
| void pmmExitWowlanResponseHandler(tpAniSirGlobal pMac, tpSirMsgQ limMsg) |
| { |
| |
| tpSirHalWowlExitParams pHalWowlRspMsg; |
| eHalStatus rspStatus = eHAL_STATUS_FAILURE; |
| |
| /* we need to process all the deferred messages enqueued |
| * since the initiating the WDA_WOWL_EXIT_REQ. |
| */ |
| SET_LIM_PROCESS_DEFD_MESGS(pMac, true); |
| |
| pHalWowlRspMsg = (tpSirHalWowlExitParams)(limMsg->bodyptr); |
| if (NULL == pHalWowlRspMsg) |
| { |
| pmmLog(pMac, LOGE, FL("Recvd WDA_WOWL_ENTER_RSP with NULL msg ")); |
| } |
| else |
| { |
| // restore PMM state to BMPS mode |
| pMac->pmm.gPmmState = ePMM_STATE_BMPS_SLEEP; |
| rspStatus = pHalWowlRspMsg->status; |
| } |
| |
| if( rspStatus == eHAL_STATUS_SUCCESS) |
| { |
| pmmLog(pMac, LOGW, FL("Rcvd successful rsp from HAL to exit WOWLAN ")); |
| limSendSmeRsp(pMac, eWNI_PMC_EXIT_WOWL_RSP, eSIR_SME_SUCCESS, 0, 0); |
| } |
| else |
| { |
| pmmLog(pMac, LOGE, FL("Rcvd failure rsp from HAL to exit WOWLAN ")); |
| limSendSmeRsp(pMac, eWNI_PMC_EXIT_WOWL_RSP, eSIR_SME_WOWL_EXIT_REQ_FAILED, 0, 0); |
| } |
| return; |
| } |
| |
| |
| // -------------------------------------------------------------------- |
| /** |
| * pmmImpsSendChangePwrSaveMsg |
| * |
| * FUNCTION: |
| * This function is called to toggle the Idle mode power save mode |
| * |
| * LOGIC: |
| * |
| * ASSUMPTIONS: |
| * None |
| * |
| * NOTE: |
| * |
| * @param Global handle to MAC |
| * @param mode to be configured |
| * @return None |
| */ |
| |
| tSirRetStatus pmmImpsSendChangePwrSaveMsg(tpAniSirGlobal pMac, tANI_U8 mode) |
| { |
| tSirRetStatus retStatus = eSIR_SUCCESS; |
| tSirMsgQ msgQ; |
| |
| if (SIR_PM_SLEEP_MODE == mode) |
| { |
| msgQ.type = WDA_ENTER_IMPS_REQ; |
| PELOG2(pmmLog (pMac, LOG2, FL("Sending WDA_ENTER_IMPS_REQ to HAL"));) |
| } |
| else |
| { |
| msgQ.type = WDA_EXIT_IMPS_REQ; |
| PELOG2(pmmLog (pMac, LOG2, FL("Sending WDA_EXIT_IMPS_REQ to HAL"));) |
| } |
| |
| msgQ.reserved = 0; |
| msgQ.bodyptr = NULL; |
| msgQ.bodyval = 0; |
| |
| /* we need to defer any incoming messages until we get a |
| * WDA_ENTER_IMPS_REQ or WDA_EXIT_IMPS_RSP from HAL. |
| */ |
| SET_LIM_PROCESS_DEFD_MESGS(pMac, false); |
| MTRACE(macTraceMsgTx(pMac, NO_SESSION, msgQ.type)); |
| retStatus = wdaPostCtrlMsg(pMac, &msgQ); |
| if ( eSIR_SUCCESS != retStatus ) |
| { |
| PELOGE(pmmLog(pMac, LOGE, |
| FL("WDA_ENTER/EXIT_IMPS_REQ to HAL failed, reason=%X"), retStatus);) |
| } |
| |
| return retStatus; |
| } |
| |
| // -------------------------------------------------------------------- |
| /** |
| * pmmUapsdSendChangePwrSaveMsg |
| * |
| * FUNCTION: |
| * This function is called to send either WDA_ENTER_UAPSD_REQ |
| * or WDA_EXIT_UAPSD_REQ to HAL. |
| * |
| * NOTE: |
| * |
| * @param pMac Global handle to MAC |
| * @param mode mode to be configured |
| * @return tSirRetStatus |
| */ |
| tSirRetStatus pmmUapsdSendChangePwrSaveMsg (tpAniSirGlobal pMac, tANI_U8 mode) |
| { |
| tSirRetStatus retStatus = eSIR_SUCCESS; |
| tpUapsdParams pUapsdParams = NULL; |
| tSirMsgQ msgQ; |
| tpPESession pSessionEntry; |
| tpExitUapsdParams pExitUapsdParams = NULL; |
| |
| if((pSessionEntry = peGetValidPowerSaveSession(pMac)) == NULL ) |
| { |
| PELOGW(pmmLog(pMac, LOGW, FL("pmmUapsd : failed to allocate memory"));) |
| retStatus = eSIR_FAILURE; |
| return retStatus; |
| } |
| |
| if (SIR_PM_SLEEP_MODE == mode) |
| { |
| pUapsdParams = vos_mem_malloc(sizeof(*pUapsdParams)); |
| if ( NULL == pUapsdParams ) |
| { |
| PELOGW(pmmLog(pMac, LOGW, FL("pmmUapsd : failed to allocate memory"));) |
| retStatus = eSIR_MEM_ALLOC_FAILED; |
| return retStatus; |
| } |
| |
| vos_mem_zero(pUapsdParams, sizeof(*pUapsdParams)); |
| msgQ.type = WDA_ENTER_UAPSD_REQ; |
| msgQ.bodyptr = pUapsdParams; |
| |
| /* |
| * An AC is delivery enabled AC if the bit for that AC is set into the |
| * gAcAdmitMask[SIR_MAC_DIRECTION_DLINK],it is not set then we will take Static values. |
| */ |
| |
| if ( pMac->lim.gAcAdmitMask[SIR_MAC_DIRECTION_DNLINK] & LIM_ADMIT_MASK_FLAG_ACBE) |
| { |
| pUapsdParams->beDeliveryEnabled = LIM_UAPSD_GET(ACBE, pMac->lim.gUapsdPerAcDeliveryEnableMask); |
| } |
| else |
| { |
| pUapsdParams->beDeliveryEnabled = LIM_UAPSD_GET(ACBE, pMac->lim.gUapsdPerAcBitmask); |
| } |
| if ( pMac->lim.gAcAdmitMask[SIR_MAC_DIRECTION_DNLINK] & LIM_ADMIT_MASK_FLAG_ACBK) |
| { |
| pUapsdParams->bkDeliveryEnabled = LIM_UAPSD_GET(ACBK, pMac->lim.gUapsdPerAcDeliveryEnableMask); |
| } |
| else |
| { |
| pUapsdParams->bkDeliveryEnabled = LIM_UAPSD_GET(ACBK, pMac->lim.gUapsdPerAcBitmask); |
| } |
| if ( pMac->lim.gAcAdmitMask[SIR_MAC_DIRECTION_DNLINK] & LIM_ADMIT_MASK_FLAG_ACVI) |
| { |
| pUapsdParams->viDeliveryEnabled = LIM_UAPSD_GET(ACVI, pMac->lim.gUapsdPerAcDeliveryEnableMask); |
| } |
| else |
| { |
| pUapsdParams->viDeliveryEnabled = LIM_UAPSD_GET(ACVI, pMac->lim.gUapsdPerAcBitmask); |
| } |
| |
| if ( pMac->lim.gAcAdmitMask[SIR_MAC_DIRECTION_DNLINK] & LIM_ADMIT_MASK_FLAG_ACVO) |
| { |
| pUapsdParams->voDeliveryEnabled = LIM_UAPSD_GET(ACVO, pMac->lim.gUapsdPerAcDeliveryEnableMask); |
| } |
| else |
| { |
| pUapsdParams->voDeliveryEnabled = LIM_UAPSD_GET(ACVO, pMac->lim.gUapsdPerAcBitmask); |
| } |
| |
| /* |
| * An AC is trigger enabled AC if the bit for that AC is set into the |
| * gAcAdmitMask[SIR_MAC_DIRECTION_UPLINK],it is not set then we will take Static values. |
| */ |
| |
| if ( pMac->lim.gAcAdmitMask[SIR_MAC_DIRECTION_UPLINK] & LIM_ADMIT_MASK_FLAG_ACBE) |
| { |
| pUapsdParams->beTriggerEnabled = LIM_UAPSD_GET(ACBE, pMac->lim.gUapsdPerAcTriggerEnableMask); |
| } |
| else |
| { |
| pUapsdParams->beTriggerEnabled = LIM_UAPSD_GET(ACBE, pMac->lim.gUapsdPerAcBitmask); |
| } |
| if ( pMac->lim.gAcAdmitMask[SIR_MAC_DIRECTION_UPLINK] & LIM_ADMIT_MASK_FLAG_ACBK) |
| { |
| pUapsdParams->bkTriggerEnabled = LIM_UAPSD_GET(ACBK, pMac->lim.gUapsdPerAcTriggerEnableMask); |
| } |
| else |
| { |
| pUapsdParams->bkTriggerEnabled = LIM_UAPSD_GET(ACBK, pMac->lim.gUapsdPerAcBitmask); |
| } |
| if ( pMac->lim.gAcAdmitMask[SIR_MAC_DIRECTION_UPLINK] & LIM_ADMIT_MASK_FLAG_ACVI) |
| { |
| pUapsdParams->viTriggerEnabled = LIM_UAPSD_GET(ACVI, pMac->lim.gUapsdPerAcTriggerEnableMask); |
| } |
| else |
| { |
| pUapsdParams->viTriggerEnabled = LIM_UAPSD_GET(ACVI, pMac->lim.gUapsdPerAcBitmask); |
| } |
| |
| if ( pMac->lim.gAcAdmitMask[SIR_MAC_DIRECTION_UPLINK] & LIM_ADMIT_MASK_FLAG_ACVO) |
| { |
| pUapsdParams->voTriggerEnabled = LIM_UAPSD_GET(ACVO, pMac->lim.gUapsdPerAcTriggerEnableMask); |
| } |
| else |
| { |
| pUapsdParams->voTriggerEnabled = LIM_UAPSD_GET(ACVO, pMac->lim.gUapsdPerAcBitmask); |
| } |
| |
| pUapsdParams->bssIdx = pSessionEntry->bssIdx; |
| |
| PELOGW(pmmLog(pMac, LOGW, |
| FL("UAPSD Mask: static = 0x%x, DeliveryEnabled = 0x%x, TriggerEnabled = 0x%x "), |
| pMac->lim.gUapsdPerAcBitmask, |
| pMac->lim.gUapsdPerAcDeliveryEnableMask, |
| pMac->lim.gUapsdPerAcTriggerEnableMask);) |
| |
| PELOGW(pmmLog(pMac, LOGW, FL("Delivery Enabled: BK=%d, BE=%d, Vi=%d, Vo=%d "), |
| pUapsdParams->bkDeliveryEnabled, |
| pUapsdParams->beDeliveryEnabled, |
| pUapsdParams->viDeliveryEnabled, |
| pUapsdParams->voDeliveryEnabled);) |
| |
| PELOGW(pmmLog(pMac, LOGW, FL("Trigger Enabled: BK=%d, BE=%d, Vi=%d, Vo=%d "), |
| pUapsdParams->bkTriggerEnabled, |
| pUapsdParams->beTriggerEnabled, |
| pUapsdParams->viTriggerEnabled, |
| pUapsdParams->voTriggerEnabled);) |
| |
| PELOGW(pmmLog (pMac, LOGW, FL("pmmUapsd: Sending WDA_ENTER_UAPSD_REQ to HAL"));) |
| } |
| else |
| { |
| pExitUapsdParams = vos_mem_malloc(sizeof(*pExitUapsdParams)); |
| if ( NULL == pExitUapsdParams ) |
| { |
| PELOGW(pmmLog(pMac, LOGW, FL("pmmUapsd : failed to allocate memory"));) |
| retStatus = eSIR_MEM_ALLOC_FAILED; |
| return retStatus; |
| } |
| |
| vos_mem_zero(pExitUapsdParams, sizeof(*pExitUapsdParams)); |
| msgQ.type = WDA_EXIT_UAPSD_REQ; |
| msgQ.bodyptr = pExitUapsdParams; |
| pExitUapsdParams->bssIdx = pSessionEntry->bssIdx; |
| PELOGW(pmmLog (pMac, LOGW, FL("pmmUapsd: Sending WDA_EXIT_UAPSD_REQ to HAL"));) |
| } |
| |
| /* we need to defer any incoming messages until we get a |
| * WDA_ENTER/EXIT_UAPSD_RSP from HAL. |
| */ |
| SET_LIM_PROCESS_DEFD_MESGS(pMac, false); |
| |
| msgQ.reserved = 0; |
| msgQ.bodyval = 0; |
| MTRACE(macTraceMsgTx(pMac, NO_SESSION, msgQ.type)); |
| retStatus = wdaPostCtrlMsg(pMac, &msgQ); |
| if ( eSIR_SUCCESS != retStatus ) |
| { |
| PELOGE(pmmLog(pMac, LOGE, |
| FL("pmmUapsd: WDA_ENTER/EXIT_UAPSD_REQ to HAL failed, reason=%X"), |
| retStatus);) |
| if (SIR_PM_SLEEP_MODE == mode) |
| vos_mem_free(pUapsdParams); |
| else |
| vos_mem_free(pExitUapsdParams); |
| } |
| |
| return retStatus; |
| } |
| |
| |
| // -------------------------------------------------------------------- |
| /** |
| * pmmUpdateImpsPwrSaveStats |
| * |
| * FUNCTION: |
| * This function is called to update the power save statistics in MAC |
| * for Idle mode power save |
| * |
| * LOGIC: |
| * |
| * ASSUMPTIONS: |
| * None |
| * |
| * NOTE: |
| * |
| * @param Global handle to MAC |
| * @return None |
| */ |
| |
| void pmmImpsUpdatePwrSaveStats(tpAniSirGlobal pMac) |
| { |
| } |
| |
| |
| // -------------------------------------------------------------------- |
| /** |
| * pmmImpsUpdateWakeupStats |
| * |
| * FUNCTION: |
| * This function is called to update the Wake up statistics in MAC |
| * for Idle mode power save |
| * |
| * LOGIC: |
| * |
| * ASSUMPTIONS: |
| * None |
| * |
| * NOTE: |
| * |
| * @param Global handle to MAC |
| * @return None |
| */ |
| |
| void pmmImpsUpdateWakeupStats (tpAniSirGlobal pMac) |
| { |
| } |
| |
| // Collects number of times error occurred while going to sleep mode |
| void pmmImpsUpdateSleepErrStats(tpAniSirGlobal pMac, |
| tSirRetStatus retStatus) |
| { |
| pMac->pmm.ImpsSleepErrCnt++; |
| pMac->pmm.ImpsLastErr = retStatus; |
| return; |
| } |
| |
| // Collects number of times error occurred while waking up from sleep mode |
| void pmmImpsUpdateWakeupErrStats(tpAniSirGlobal pMac, |
| tSirRetStatus retStatus) |
| { |
| pMac->pmm.ImpsWakeupErrCnt++; |
| pMac->pmm.ImpsLastErr = retStatus; |
| return; |
| } |
| |
| |
| // Collects number of times the system has received request or |
| // response in an invalid state |
| void pmmImpsUpdateErrStateStats(tpAniSirGlobal pMac) |
| { |
| pMac->pmm.ImpsInvalidStateCnt++; |
| return; |
| } |
| |
| // Collects number of packets dropped while in IMPS mode |
| void pmmImpsUpdatePktDropStats(tpAniSirGlobal pMac) |
| { |
| |
| pMac->pmm.ImpsPktDrpInSleepMode++; |
| return; |
| } |
| |
| // Collects number of packets dropped while in BMPS mode |
| void pmmBmpsUpdatePktDropStats(tpAniSirGlobal pMac) |
| { |
| |
| pMac->pmm.BmpsPktDrpInSleepMode++; |
| return; |
| } |
| |
| // Collects statistics for number of times BMPS init failed |
| void pmmBmpsUpdateInitFailureCnt(tpAniSirGlobal pMac) |
| { |
| |
| pMac->pmm.BmpsInitFailCnt++; |
| return; |
| } |
| |
| // Collects statistics for number of times sleep request failed |
| void pmmBmpsUpdateSleepReqFailureCnt(tpAniSirGlobal pMac) |
| { |
| |
| pMac->pmm.BmpsSleeReqFailCnt++; |
| return; |
| } |
| |
| // Collects statistics for number of times Wakeup request failed |
| void pmmBmpsUpdateWakeupReqFailureCnt(tpAniSirGlobal pMac) |
| { |
| |
| pMac->pmm.BmpsWakeupReqFailCnt++; |
| return; |
| } |
| |
| // Collects statistics for number of times request / response received in invalid state |
| void pmmBmpsUpdateInvalidStateCnt(tpAniSirGlobal pMac) |
| { |
| |
| pMac->pmm.BmpsInvStateCnt++; |
| return; |
| } |
| |
| // Collects statistics for number of times wakeup indications received |
| void pmmBmpsUpdateWakeupIndCnt(tpAniSirGlobal pMac) |
| { |
| pMac->pmm.BmpsWakeupIndCnt++; |
| return; |
| } |
| |
| // Collects statistics for number of times wakeup indications received |
| void pmmBmpsUpdateHalReqFailureCnt(tpAniSirGlobal pMac) |
| { |
| pMac->pmm.BmpsHalReqFailCnt++; |
| return; |
| } |
| |
| // Collects statistics for number of times requests received from HDD in |
| // invalid device role |
| void pmmBmpsUpdateReqInInvalidRoleCnt(tpAniSirGlobal pMac) |
| { |
| pMac->pmm.BmpsReqInInvalidRoleCnt++; |
| return; |
| } |
| |
| // Resets PMM state ePMM_STATE_READY |
| void pmmResetPmmState(tpAniSirGlobal pMac) |
| { |
| pMac->pmm.gPmmState = ePMM_STATE_READY; |
| |
| pMac->pmm.inMissedBeaconScenario = FALSE; |
| return; |
| } |
| |
| /* Sends Background scan message back to Lim */ |
| void pmmSendMessageToLim(tpAniSirGlobal pMac, |
| tANI_U32 msgId) |
| { |
| tSirMsgQ limMsg; |
| tANI_U32 statusCode; |
| |
| limMsg.type = (tANI_U16) msgId; |
| limMsg.bodyptr = NULL; |
| limMsg.bodyval = 0; |
| |
| if ((statusCode = limPostMsgApi(pMac, &limMsg)) != eSIR_SUCCESS) |
| { |
| PELOGW(pmmLog(pMac, LOGW, |
| FL("posting message %X to LIM failed, reason=%d"), |
| limMsg.type, statusCode);) |
| } |
| } |
| |
| #ifdef WLAN_FEATURE_PACKET_FILTERING |
| void pmmFilterMatchCountResponseHandler(tpAniSirGlobal pMac, tpSirMsgQ limMsg) |
| { |
| tpSirRcvFltPktMatchRsp pRcvFltPktMatchCntRsp; |
| eHalStatus rspStatus; |
| tSirResultCodes smeRspCode = eSIR_SME_SUCCESS; |
| |
| /* we need to process all the deferred messages enqueued |
| * since the initiating the WDA_PACKET_COALESCING_FILTER_MATCH_COUNT_REQ. |
| */ |
| SET_LIM_PROCESS_DEFD_MESGS(pMac, true); |
| |
| pRcvFltPktMatchCntRsp = (tpSirRcvFltPktMatchRsp)(limMsg->bodyptr); |
| if (NULL == pRcvFltPktMatchCntRsp) |
| { |
| pmmLog(pMac, LOGE, FL("Received " |
| "WDA_PACKET_COALESCING_FILTER_MATCH_COUNT_RSP with NULL msg ")); |
| smeRspCode = eSIR_SME_PC_FILTER_MATCH_COUNT_REQ_FAILED; |
| } |
| else |
| { |
| rspStatus = pRcvFltPktMatchCntRsp->status; |
| if (eHAL_STATUS_SUCCESS == rspStatus) |
| { |
| pmmLog(pMac, LOGE, FL("Rcv successful response from HAL to get " |
| "Packet Coalescing Filter Match Count")); |
| } |
| else |
| { |
| pmmLog(pMac, LOGE, FL("HAL failed to get Packet Coalescing " |
| "Filter Match Count, informing SME")); |
| smeRspCode = eSIR_SME_PC_FILTER_MATCH_COUNT_REQ_FAILED; |
| } |
| } |
| |
| limSendSmeRsp(pMac, eWNI_PMC_PACKET_COALESCING_FILTER_MATCH_COUNT_RSP, |
| smeRspCode, 0, 0); |
| return; |
| } |
| #endif // WLAN_FEATURE_PACKET_FILTERING |
| |
| #ifdef WLAN_FEATURE_GTK_OFFLOAD |
| void pmmGTKOffloadGetInfoResponseHandler(tpAniSirGlobal pMac, tpSirMsgQ limMsg) |
| { |
| tpSirGtkOffloadGetInfoRspParams pGtkOffloadGetInfoRspParams; |
| eHalStatus rspStatus; |
| tSirResultCodes smeRspCode = eSIR_SME_SUCCESS; |
| |
| /* we need to process all the deferred messages enqueued |
| * since the initiating the WDA_GTK_OFFLOAD_GETINFO_REQ. |
| */ |
| SET_LIM_PROCESS_DEFD_MESGS(pMac, true); |
| |
| pGtkOffloadGetInfoRspParams = (tpSirGtkOffloadGetInfoRspParams)(limMsg->bodyptr); |
| if (NULL == pGtkOffloadGetInfoRspParams) |
| { |
| pmmLog(pMac, LOGE, FL("Received WDA_GTK_OFFLOAD_GETINFO_RSP with NULL msg ")); |
| smeRspCode = eSIR_SME_GTK_OFFLOAD_GETINFO_REQ_FAILED; |
| } |
| else |
| { |
| rspStatus = pGtkOffloadGetInfoRspParams->ulStatus; |
| if(rspStatus == eHAL_STATUS_SUCCESS) |
| { |
| pmmLog(pMac, LOGW, FL("Rcv successful response from HAL to get GTK Offload Information")); |
| } |
| else |
| { |
| pmmLog(pMac, LOGE, FL("HAL failed to get GTK Offload Information, informing SME")); |
| smeRspCode = eSIR_SME_GTK_OFFLOAD_GETINFO_REQ_FAILED; |
| } |
| } |
| |
| limSendSmeRsp(pMac, eWNI_PMC_GTK_OFFLOAD_GETINFO_RSP, smeRspCode, 0, 0); |
| return; |
| } |
| #endif // WLAN_FEATURE_GTK_OFFLOAD |
| |
| /* Power save Offload Implementation */ |
| eHalStatus pmmPsOffloadOpen(tpAniSirGlobal pMac,tpPESession psessionEntry) |
| { |
| if(psessionEntry->valid) |
| { |
| psessionEntry->pmmOffloadInfo.psstate = PMM_FULL_POWER; |
| psessionEntry->pmmOffloadInfo.bcnmiss = FALSE; |
| |
| pmmLog(pMac, LOG1, |
| FL("ps offload open success for pe session %x"), |
| psessionEntry->peSessionId); |
| |
| return eHAL_STATUS_SUCCESS; |
| } |
| else |
| { |
| pmmLog(pMac, LOGE, |
| FL("ps offload open failed:invalid pe session")); |
| return eHAL_STATUS_FAILURE; |
| } |
| } |
| |
| eHalStatus pmmPsOffloadClose(tpAniSirGlobal pMac, tpPESession psessionEntry) |
| { |
| if(psessionEntry->valid) |
| { |
| psessionEntry->pmmOffloadInfo.psstate = PMM_FULL_POWER; |
| psessionEntry->pmmOffloadInfo.bcnmiss = FALSE; |
| pmmLog(pMac, LOG1, |
| FL("ps offload close success for pe session %x"), |
| psessionEntry->peSessionId); |
| return eHAL_STATUS_SUCCESS; |
| } |
| else |
| { |
| pmmLog(pMac, LOGW, |
| FL("ps offload close failed:invalid pe session")); |
| return eHAL_STATUS_FAILURE; |
| } |
| } |
| |
| tANI_U8 pmmPsOffloadIsActive(tpAniSirGlobal pMac, tpPESession psessionEntry) |
| { |
| if(psessionEntry->valid && |
| psessionEntry->pmmOffloadInfo.psstate == PMM_FULL_POWER) |
| { |
| /* Session is in Active State */ |
| return TRUE; |
| } |
| else |
| { |
| /* Session is in Power Save State */ |
| return FALSE; |
| } |
| } |
| |
| tSirRetStatus pmmOffloadEnterBmpsRespHandler(tpAniSirGlobal pMac, |
| void *pRespData) |
| { |
| tANI_U8 sessionId; |
| tpPESession psessionEntry; |
| tpEnablePsParams psRespData = (tpEnablePsParams)pRespData; |
| |
| /* |
| * we need to process all the deferred messages enqueued since |
| * initiating SIR_HAL_ENTER_BMPS_REQ. |
| */ |
| SET_LIM_PROCESS_DEFD_MESGS(pMac, true); |
| |
| if(!pRespData) |
| { |
| pmmLog(pMac, LOGE, " No Ps Resp Data: Invalid Enter Bmps Resp"); |
| return eSIR_FAILURE; |
| } |
| |
| pmmLog(pMac, LOG1, |
| "pmmOffloadEnterBmpsRespHandler Status %x", psRespData->status); |
| |
| /* Get the PE Session Corresponding to BSSID */ |
| psessionEntry = peFindSessionByBssid(pMac, psRespData->bssid, &sessionId); |
| |
| if(!psessionEntry) |
| { |
| pmmLog(pMac, LOGE, |
| " No PE Session for given BSSID : Invalid Enter Bmps Request"); |
| limSendSmeRsp(pMac, eWNI_PMC_ENTER_BMPS_RSP, eSIR_SME_INVALID_STATE, |
| psRespData->sessionid, 0); |
| return eSIR_FAILURE; |
| } |
| |
| if(eHAL_STATUS_SUCCESS == psRespData->status) |
| { |
| psessionEntry->pmmOffloadInfo.psstate = PMM_POWER_SAVE; |
| pmmLog(pMac, LOG1, |
| "EnterBmpsResp Success PeSessionId %x SmeSessionId %x", |
| psessionEntry->peSessionId, psessionEntry->smeSessionId); |
| |
| limSendSmeRsp(pMac, eWNI_PMC_ENTER_BMPS_RSP, eSIR_SUCCESS, |
| psessionEntry->smeSessionId, |
| psessionEntry->transactionId); |
| } |
| else |
| { |
| pmmLog(pMac, LOGE, |
| "EnterBmpsResp Failed PeSessionId %x SmeSessionId %x", |
| psessionEntry->peSessionId, psessionEntry->smeSessionId); |
| |
| limSendSmeRsp(pMac, eWNI_PMC_ENTER_BMPS_RSP, eSIR_FAILURE, |
| psessionEntry->smeSessionId, |
| psessionEntry->transactionId); |
| } |
| return eSIR_SUCCESS; |
| } |
| |
| eHalStatus pmmOffloadFillUapsdParams(tpPESession psessionEntry, |
| tpUapsd_Params pUapsdParams) |
| { |
| /* |
| * If gAcAdmitMask[SIR_MAC_DIRECTION_DLINK] is set,DeliveryEnabled bits are filled |
| * based on PSB from addts dynamically. If it is not set, DeliveryEnabled bits are |
| * filled from static values as per UapsdMask in ini file. |
| */ |
| |
| if ( psessionEntry->gAcAdmitMask[SIR_MAC_DIRECTION_DNLINK] & LIM_ADMIT_MASK_FLAG_ACBE) |
| { |
| pUapsdParams->beDeliveryEnabled = LIM_UAPSD_GET(ACBE, psessionEntry->gUapsdPerAcDeliveryEnableMask); |
| } |
| else |
| { |
| pUapsdParams->beDeliveryEnabled = LIM_UAPSD_GET(ACBE, psessionEntry->gUapsdPerAcBitmask); |
| } |
| if ( psessionEntry->gAcAdmitMask[SIR_MAC_DIRECTION_DNLINK] & LIM_ADMIT_MASK_FLAG_ACBK) |
| { |
| pUapsdParams->bkDeliveryEnabled = LIM_UAPSD_GET(ACBK, psessionEntry->gUapsdPerAcDeliveryEnableMask); |
| } |
| else |
| { |
| pUapsdParams->bkDeliveryEnabled = LIM_UAPSD_GET(ACBK, psessionEntry->gUapsdPerAcBitmask); |
| } |
| if ( psessionEntry->gAcAdmitMask[SIR_MAC_DIRECTION_DNLINK] & LIM_ADMIT_MASK_FLAG_ACVI) |
| { |
| pUapsdParams->viDeliveryEnabled = LIM_UAPSD_GET(ACVI, psessionEntry->gUapsdPerAcDeliveryEnableMask); |
| } |
| else |
| { |
| pUapsdParams->viDeliveryEnabled = LIM_UAPSD_GET(ACVI, psessionEntry->gUapsdPerAcBitmask); |
| } |
| |
| if ( psessionEntry->gAcAdmitMask[SIR_MAC_DIRECTION_DNLINK] & LIM_ADMIT_MASK_FLAG_ACVO) |
| { |
| pUapsdParams->voDeliveryEnabled = LIM_UAPSD_GET(ACVO, psessionEntry->gUapsdPerAcDeliveryEnableMask); |
| } |
| else |
| { |
| pUapsdParams->voDeliveryEnabled = LIM_UAPSD_GET(ACVO, psessionEntry->gUapsdPerAcBitmask); |
| } |
| |
| /* |
| * If gAcAdmitMask[SIR_MAC_DIRECTION_UPLINK] is set,TriggerEnabled bits are filled |
| * based on PSB from addts dynamically. If it is not set, TriggerEnabled bits are |
| * filled from static values as per UapsdMask in ini file. |
| */ |
| |
| if ( psessionEntry->gAcAdmitMask[SIR_MAC_DIRECTION_UPLINK] & LIM_ADMIT_MASK_FLAG_ACBE) |
| { |
| pUapsdParams->beTriggerEnabled = LIM_UAPSD_GET(ACBE, psessionEntry->gUapsdPerAcTriggerEnableMask); |
| } |
| else |
| { |
| pUapsdParams->beTriggerEnabled = LIM_UAPSD_GET(ACBE, psessionEntry->gUapsdPerAcBitmask); |
| } |
| if ( psessionEntry->gAcAdmitMask[SIR_MAC_DIRECTION_UPLINK] & LIM_ADMIT_MASK_FLAG_ACBK) |
| { |
| pUapsdParams->bkTriggerEnabled = LIM_UAPSD_GET(ACBK, psessionEntry->gUapsdPerAcTriggerEnableMask); |
| } |
| else |
| { |
| pUapsdParams->bkTriggerEnabled = LIM_UAPSD_GET(ACBK, psessionEntry->gUapsdPerAcBitmask); |
| } |
| if ( psessionEntry->gAcAdmitMask[SIR_MAC_DIRECTION_UPLINK] & LIM_ADMIT_MASK_FLAG_ACVI) |
| { |
| pUapsdParams->viTriggerEnabled = LIM_UAPSD_GET(ACVI, psessionEntry->gUapsdPerAcTriggerEnableMask); |
| } |
| else |
| { |
| pUapsdParams->viTriggerEnabled = LIM_UAPSD_GET(ACVI, psessionEntry->gUapsdPerAcBitmask); |
| } |
| |
| if ( psessionEntry->gAcAdmitMask[SIR_MAC_DIRECTION_UPLINK] & LIM_ADMIT_MASK_FLAG_ACVO) |
| { |
| pUapsdParams->voTriggerEnabled = LIM_UAPSD_GET(ACVO, psessionEntry->gUapsdPerAcTriggerEnableMask); |
| } |
| else |
| { |
| pUapsdParams->voTriggerEnabled = LIM_UAPSD_GET(ACVO, psessionEntry->gUapsdPerAcBitmask); |
| } |
| |
| return eHAL_STATUS_SUCCESS; |
| } |
| |
| tSirRetStatus pmmOffloadEnterBmpsReqHandler(tpAniSirGlobal pMac, |
| void *pReqData) |
| { |
| tANI_U8 sessionId; |
| tpPESession psessionEntry; |
| tpEnablePsParams pEnablePsReqParams; |
| tSirMsgQ msgQ; |
| tpSirPsReqData psReqData = (tpSirPsReqData)pReqData; |
| |
| if(!psReqData) |
| { |
| pmmLog(pMac, LOGE, " No Ps Req Data: Invalid Enter Bmps Request"); |
| return eSIR_FAILURE; |
| } |
| |
| /* Get the PE Session Corresponding to BSSID */ |
| psessionEntry = peFindSessionByBssid(pMac, psReqData->bssId, &sessionId); |
| |
| if(NULL == psessionEntry) |
| { |
| pmmLog(pMac, LOGE, |
| " No PE Session for given BSSID : Invalid Enter Bmps Request"); |
| limSendSmeRsp(pMac, eWNI_PMC_ENTER_BMPS_RSP, eSIR_FAILURE, 0, 0); |
| return eSIR_FAILURE; |
| } |
| |
| /* Missed Beacon Scenario. Don't allow Power Save */ |
| if(TRUE == psessionEntry->pmmOffloadInfo.bcnmiss) |
| { |
| pmmLog(pMac, LOGE, "Enter Bmps Request in Missed Beacon Scenario"); |
| limSendSmeRsp(pMac, eWNI_PMC_ENTER_BMPS_RSP, eSIR_FAILURE, |
| psessionEntry->smeSessionId, |
| psessionEntry->transactionId); |
| return eSIR_SUCCESS; |
| } |
| |
| pEnablePsReqParams = vos_mem_malloc(sizeof(*pEnablePsReqParams)); |
| if (NULL == pEnablePsReqParams) |
| { |
| pmmLog(pMac, LOGE, |
| FL("Memory allocation failed for pEnablePsReqParams")); |
| limSendSmeRsp(pMac, eWNI_PMC_ENTER_BMPS_RSP, eSIR_FAILURE, |
| psessionEntry->smeSessionId, |
| psessionEntry->transactionId); |
| return eSIR_MEM_ALLOC_FAILED; |
| } |
| |
| vos_mem_zero(pEnablePsReqParams, sizeof(*pEnablePsReqParams)); |
| /* Fill the BSSID corresponding to PS Req */ |
| vos_mem_copy(pEnablePsReqParams->bssid, psReqData->bssId, |
| sizeof(tSirMacAddr)); |
| |
| /* Fill the Sme Session Id */ |
| pEnablePsReqParams->sessionid = psessionEntry->smeSessionId; |
| |
| /* Fill the Last Beacon DTIM Period */ |
| pEnablePsReqParams->bcnDtimPeriod = psessionEntry->lastBeaconDtimPeriod; |
| |
| /* Fill the additional power save setting */ |
| pEnablePsReqParams->psSetting = psReqData->addOnReq; |
| |
| if(eSIR_ADDON_ENABLE_UAPSD == pEnablePsReqParams->psSetting) |
| { |
| pmmOffloadFillUapsdParams(psessionEntry, |
| &pEnablePsReqParams->uapsdParams); |
| } |
| |
| msgQ.type = WDA_ENTER_BMPS_REQ; |
| msgQ.reserved = 0; |
| msgQ.bodyptr = pEnablePsReqParams; |
| msgQ.bodyval = 0; |
| |
| if(eSIR_SUCCESS != wdaPostCtrlMsg(pMac, &msgQ)) |
| { |
| pmmLog(pMac, LOGE, FL("Posting WDA_ENTER_BMPS_REQ failed")); |
| vos_mem_free(pEnablePsReqParams); |
| limSendSmeRsp(pMac, eWNI_PMC_ENTER_BMPS_RSP, eSIR_FAILURE, |
| psessionEntry->smeSessionId, |
| psessionEntry->transactionId); |
| return eSIR_FAILURE; |
| } |
| /* |
| * we need to defer any incoming messages until we |
| * get a WDA_EXIT_BMPS_RSP from HAL. |
| */ |
| SET_LIM_PROCESS_DEFD_MESGS(pMac, false); |
| pmmLog(pMac, LOG1, FL("WDA_ENTER_BMPS_REQ Successfully sent to WDA")); |
| |
| return eSIR_SUCCESS; |
| } |
| |
| tSirRetStatus pmmOffloadExitBmpsRespHandler(tpAniSirGlobal pMac, |
| void *pRespData) |
| { |
| tANI_U8 sessionId; |
| tpPESession psessionEntry; |
| tpDisablePsParams psRespData = (tpDisablePsParams)pRespData; |
| |
| /* |
| * we need to process all the deferred messages enqueued since |
| * initiating SIR_HAL_EXIT_BMPS_REQ. |
| */ |
| SET_LIM_PROCESS_DEFD_MESGS(pMac, true); |
| |
| if(!pRespData) |
| { |
| pmmLog(pMac, LOGE, " No Ps Resp Data: Invalid Enter Bmps Resp"); |
| return eSIR_FAILURE; |
| } |
| |
| pmmLog(pMac, LOG1, |
| "pmmOffloadExitBmpsRespHandler Status %x", psRespData->status); |
| |
| /* Get the PE Session Corresponding to BSSID */ |
| psessionEntry = peFindSessionByBssid(pMac, psRespData->bssid, &sessionId); |
| |
| if(!psessionEntry) |
| { |
| pmmLog(pMac, LOGE, |
| " No PE Session for given BSSID : Invalid Exit Bmps Request"); |
| limSendSmeRsp(pMac, eWNI_PMC_EXIT_BMPS_RSP, eSIR_SME_INVALID_STATE, |
| psRespData->sessionid, 0); |
| return eSIR_FAILURE; |
| } |
| |
| if(eHAL_STATUS_SUCCESS == psRespData->status) |
| { |
| psessionEntry->pmmOffloadInfo.psstate = PMM_FULL_POWER; |
| pmmLog(pMac, LOG1, |
| "ExitBmpsResp Success PeSessionId %x SmeSessionId %x", |
| psessionEntry->peSessionId, psessionEntry->smeSessionId); |
| |
| limSendSmeRsp(pMac, eWNI_PMC_EXIT_BMPS_RSP, eSIR_SUCCESS, |
| psessionEntry->smeSessionId, |
| psessionEntry->transactionId); |
| } |
| else |
| { |
| pmmLog(pMac, LOGE, |
| "ExitBmpsResp Failed PeSessionId %x SmeSessionId %x", |
| psessionEntry->peSessionId, psessionEntry->smeSessionId); |
| |
| limSendSmeRsp(pMac, eWNI_PMC_EXIT_BMPS_RSP, eSIR_FAILURE, |
| psessionEntry->smeSessionId, |
| psessionEntry->transactionId); |
| } |
| |
| if(TRUE == psessionEntry->pmmOffloadInfo.bcnmiss) |
| { |
| pmmLog(pMac, LOGE, |
| "Exit BMPS:- Missed Bcn Scenario PeSessionId %x SmeSessionId %x", |
| psessionEntry->peSessionId, psessionEntry->smeSessionId); |
| |
| /* Missed Beacon Scenario */ |
| limSendHeartBeatTimeoutInd(pMac, psessionEntry); |
| } |
| return eSIR_SUCCESS; |
| } |
| |
| tSirRetStatus pmmOffloadExitBmpsReqHandler(tpAniSirGlobal pMac, |
| void *pReqData) |
| { |
| tANI_U8 sessionId; |
| tpPESession psessionEntry; |
| tpDisablePsParams pDisablePsReqParams; |
| tSirMsgQ msgQ; |
| tpSirPsReqData psReqData = (tpSirPsReqData)pReqData; |
| |
| if(!psReqData) |
| { |
| pmmLog(pMac, LOGE, " No Ps Req Data: Invalid Exit Bmps Request"); |
| return eSIR_FAILURE; |
| } |
| |
| /* Get the PE Session Corresponding to BSSID */ |
| psessionEntry = peFindSessionByBssid(pMac, psReqData->bssId, &sessionId); |
| |
| if(NULL == psessionEntry) |
| { |
| pmmLog(pMac, LOGE, |
| " No PE Session for given BSSID : Invalid Enter Bmps Request"); |
| limSendSmeRsp(pMac, eWNI_PMC_EXIT_BMPS_RSP, eSIR_FAILURE, 0, 0); |
| return eSIR_FAILURE; |
| } |
| |
| pDisablePsReqParams = vos_mem_malloc(sizeof(*pDisablePsReqParams)); |
| if (NULL == pDisablePsReqParams) |
| { |
| pmmLog(pMac, LOGE, FL("Memory allocation failed for tDisablePsParams")); |
| limSendSmeRsp(pMac, eWNI_PMC_EXIT_BMPS_RSP, eSIR_FAILURE, |
| psessionEntry->smeSessionId, |
| psessionEntry->transactionId); |
| return eSIR_MEM_ALLOC_FAILED; |
| } |
| |
| vos_mem_zero(pDisablePsReqParams, sizeof(*pDisablePsReqParams)); |
| /* Fill the BSSID corresponding to PS Req */ |
| vos_mem_copy(pDisablePsReqParams->bssid, psReqData->bssId, |
| sizeof(tSirMacAddr)); |
| |
| /* Fill the Sme Session Id */ |
| pDisablePsReqParams->sessionid = psessionEntry->smeSessionId; |
| |
| msgQ.type = WDA_EXIT_BMPS_REQ; |
| msgQ.reserved = 0; |
| msgQ.bodyptr = pDisablePsReqParams; |
| msgQ.bodyval = 0; |
| |
| if(eSIR_SUCCESS != wdaPostCtrlMsg(pMac, &msgQ)) |
| { |
| pmmLog(pMac, LOGE, FL("Posting WDA_EXIT_BMPS_REQ failed")); |
| vos_mem_free(pDisablePsReqParams); |
| limSendSmeRsp(pMac, eWNI_PMC_EXIT_BMPS_RSP, eSIR_FAILURE, |
| psessionEntry->smeSessionId, |
| psessionEntry->transactionId); |
| return eSIR_FAILURE; |
| } |
| /* |
| * we need to defer any incoming messages until we |
| * get a WDA_EXIT_BMPS_RSP from HAL. |
| */ |
| SET_LIM_PROCESS_DEFD_MESGS(pMac, false); |
| |
| pmmLog(pMac, LOG1, FL("WDA_EXIT_BMPS_REQ Successfully sent to WDA")); |
| |
| return eSIR_SUCCESS; |
| } |
| |
| tSirRetStatus pmmOffloadEnterUapsdRespHandler(tpAniSirGlobal pMac, |
| void *pRespData) |
| { |
| tANI_U8 sessionId; |
| tpPESession psessionEntry; |
| tpEnableUapsdParams psRespData = (tpEnableUapsdParams)pRespData; |
| |
| /* |
| * we need to process all the deferred messages enqueued since |
| * initiating SIR_HAL_ENTER_UAPSD_REQ. |
| */ |
| SET_LIM_PROCESS_DEFD_MESGS(pMac, true); |
| |
| if(!pRespData) |
| { |
| pmmLog(pMac, LOGE, " No Ps Resp Data: Invalid Enter Uapsd Resp"); |
| return eSIR_FAILURE; |
| } |
| |
| pmmLog(pMac, LOG1, |
| "pmmOffloadEnterUapsdRespHandler Status %x", psRespData->status); |
| |
| /* Get the PE Session Corresponding to BSSID */ |
| psessionEntry = peFindSessionByBssid(pMac, psRespData->bssid, &sessionId); |
| |
| if(!psessionEntry) |
| { |
| pmmLog(pMac, LOGE, |
| " No PE Session for given BSSID : Invalid Enter Uapsd Request"); |
| limSendSmeRsp(pMac, eWNI_PMC_ENTER_UAPSD_RSP, eSIR_SME_INVALID_STATE, |
| psRespData->sessionid, 0); |
| return eSIR_FAILURE; |
| } |
| |
| if(eHAL_STATUS_SUCCESS == psRespData->status) |
| { |
| pmmLog(pMac, LOG1, |
| "EnterUapsdResp Success PeSessionId %x SmeSessionId %x", |
| psessionEntry->peSessionId, psessionEntry->smeSessionId); |
| |
| limSendSmeRsp(pMac, eWNI_PMC_ENTER_UAPSD_RSP, eSIR_SUCCESS, |
| psessionEntry->smeSessionId, |
| psessionEntry->transactionId); |
| } |
| else |
| { |
| pmmLog(pMac, LOGE, |
| "EnterUapsdResp Failed PeSessionId %x SmeSessionId %x", |
| psessionEntry->peSessionId, psessionEntry->smeSessionId); |
| |
| limSendSmeRsp(pMac, eWNI_PMC_ENTER_UAPSD_RSP, eSIR_FAILURE, |
| psessionEntry->smeSessionId, |
| psessionEntry->transactionId); |
| } |
| return eSIR_SUCCESS; |
| } |
| |
| |
| tSirRetStatus pmmOffloadEnterUapsdReqHandler(tpAniSirGlobal pMac, |
| void *pReqData) |
| { |
| tANI_U8 sessionId; |
| tpPESession psessionEntry; |
| tpEnableUapsdParams pEnableUapsdReqParams; |
| tSirMsgQ msgQ; |
| tpSirPsReqData psReqData = (tpSirPsReqData)pReqData; |
| tANI_U8 uapsdDeliveryMask = 0; |
| tANI_U8 uapsdTriggerMask = 0; |
| |
| if(!psReqData) |
| { |
| pmmLog(pMac, LOGE, " No Ps Req Data: Invalid Enter Uapsd Request"); |
| return eSIR_FAILURE; |
| } |
| |
| /* Get the PE Session Corresponding to BSSID */ |
| psessionEntry = peFindSessionByBssid(pMac, psReqData->bssId, &sessionId); |
| |
| if(NULL == psessionEntry) |
| { |
| pmmLog(pMac, LOGE, |
| " No PE Session for given BSSID : Invalid Enter Uapsd Request"); |
| return eSIR_FAILURE; |
| } |
| |
| pEnableUapsdReqParams = vos_mem_malloc(sizeof(*pEnableUapsdReqParams)); |
| if (NULL == pEnableUapsdReqParams) |
| { |
| pmmLog(pMac, LOGE, |
| FL("Memory allocation failed for pEnableUapsdReqParams")); |
| return eSIR_MEM_ALLOC_FAILED; |
| } |
| |
| vos_mem_zero(pEnableUapsdReqParams, sizeof(*pEnableUapsdReqParams)); |
| uapsdDeliveryMask = (psessionEntry->gUapsdPerAcBitmask | |
| psessionEntry->gUapsdPerAcDeliveryEnableMask); |
| |
| uapsdTriggerMask = (psessionEntry->gUapsdPerAcBitmask | |
| psessionEntry->gUapsdPerAcTriggerEnableMask); |
| |
| pEnableUapsdReqParams->uapsdParams.bkDeliveryEnabled = |
| LIM_UAPSD_GET(ACBK, uapsdDeliveryMask); |
| |
| pEnableUapsdReqParams->uapsdParams.beDeliveryEnabled = |
| LIM_UAPSD_GET(ACBE, uapsdDeliveryMask); |
| |
| pEnableUapsdReqParams->uapsdParams.viDeliveryEnabled = |
| LIM_UAPSD_GET(ACVI, uapsdDeliveryMask); |
| |
| pEnableUapsdReqParams->uapsdParams.voDeliveryEnabled = |
| LIM_UAPSD_GET(ACVO, uapsdDeliveryMask); |
| |
| pEnableUapsdReqParams->uapsdParams.bkTriggerEnabled = |
| LIM_UAPSD_GET(ACBK, uapsdTriggerMask); |
| |
| pEnableUapsdReqParams->uapsdParams.beTriggerEnabled = |
| LIM_UAPSD_GET(ACBE, uapsdTriggerMask); |
| |
| pEnableUapsdReqParams->uapsdParams.viTriggerEnabled = |
| LIM_UAPSD_GET(ACVI, uapsdTriggerMask); |
| |
| pEnableUapsdReqParams->uapsdParams.voTriggerEnabled = |
| LIM_UAPSD_GET(ACVO, uapsdTriggerMask); |
| |
| /* Fill the BSSID corresponding to PS Req */ |
| vos_mem_copy(pEnableUapsdReqParams->bssid, psReqData->bssId, |
| sizeof(tSirMacAddr)); |
| |
| /* Fill the Sme Session Id */ |
| pEnableUapsdReqParams->sessionid = psessionEntry->smeSessionId; |
| |
| msgQ.type = WDA_ENTER_UAPSD_REQ; |
| msgQ.reserved = 0; |
| msgQ.bodyptr = pEnableUapsdReqParams; |
| msgQ.bodyval = 0; |
| |
| if(eSIR_SUCCESS != wdaPostCtrlMsg(pMac, &msgQ)) |
| { |
| pmmLog(pMac, LOGE, FL("Posting WDA_ENTER_UAPSD_REQ failed")); |
| vos_mem_free(pEnableUapsdReqParams); |
| return eSIR_FAILURE; |
| } |
| |
| /* |
| * we need to defer any incoming messages until we |
| * get a WDA_EXIT_UAPSD_RSP from HAL. |
| */ |
| SET_LIM_PROCESS_DEFD_MESGS(pMac, false); |
| pmmLog(pMac, LOG1, FL("WDA_ENTER_UAPSD_REQ Successfully sent to WDA")); |
| return eSIR_SUCCESS; |
| } |
| |
| tSirRetStatus pmmOffloadExitUapsdRespHandler(tpAniSirGlobal pMac, |
| void *pRespData) |
| { |
| tANI_U8 sessionId; |
| tpPESession psessionEntry; |
| tpDisableUapsdParams psRespData = (tpDisableUapsdParams)pRespData; |
| |
| /* |
| * we need to process all the deferred messages enqueued since |
| * initiating SIR_HAL_EXIT_UAPSD_REQ. |
| */ |
| SET_LIM_PROCESS_DEFD_MESGS(pMac, true); |
| |
| if(!pRespData) |
| { |
| pmmLog(pMac, LOGE, " No Ps Resp Data: Invalid Exit Uapsd Resp"); |
| return eSIR_FAILURE; |
| } |
| |
| pmmLog(pMac, LOG1, |
| "pmmOffloadExitUapsdRespHandler Status %x", psRespData->status); |
| |
| /* Get the PE Session Corresponding to BSSID */ |
| psessionEntry = peFindSessionByBssid(pMac, psRespData->bssid, &sessionId); |
| |
| if(!psessionEntry) |
| { |
| pmmLog(pMac, LOGE, |
| " No PE Session for given BSSID : Invalid Exit Uapsd Request"); |
| limSendSmeRsp(pMac, eWNI_PMC_EXIT_UAPSD_RSP, eSIR_SME_INVALID_STATE, |
| psRespData->sessionid, 0); |
| return eSIR_FAILURE; |
| } |
| |
| if(eHAL_STATUS_SUCCESS == psRespData->status) |
| { |
| pmmLog(pMac, LOG1, |
| "ExitUapsdResp Success PeSessionId %x SmeSessionId %x", |
| psessionEntry->peSessionId, psessionEntry->smeSessionId); |
| |
| limSendSmeRsp(pMac, eWNI_PMC_EXIT_UAPSD_RSP, eSIR_SUCCESS, |
| psessionEntry->smeSessionId, |
| psessionEntry->transactionId); |
| } |
| else |
| { |
| pmmLog(pMac, LOGE, |
| "ExitUapsdResp Failed PeSessionId %x SmeSessionId %x", |
| psessionEntry->peSessionId, psessionEntry->smeSessionId); |
| |
| limSendSmeRsp(pMac, eWNI_PMC_EXIT_UAPSD_RSP, eSIR_FAILURE, |
| psessionEntry->smeSessionId, |
| psessionEntry->transactionId); |
| } |
| return eSIR_SUCCESS; |
| } |
| |
| tSirRetStatus pmmOffloadExitUapsdReqHandler(tpAniSirGlobal pMac, |
| void *pReqData) |
| { |
| tANI_U8 sessionId; |
| tpPESession psessionEntry; |
| tpDisableUapsdParams pDisableUapsdReqParams; |
| tSirMsgQ msgQ; |
| tpSirPsReqData psReqData = (tpSirPsReqData)pReqData; |
| |
| if(!psReqData) |
| { |
| pmmLog(pMac, LOGE, " No Ps Req Data: Invalid Exit Uapsd Request"); |
| return eSIR_FAILURE; |
| } |
| |
| /* Get the PE Session Corresponding to BSSID */ |
| psessionEntry = peFindSessionByBssid(pMac, psReqData->bssId, &sessionId); |
| |
| if(NULL == psessionEntry) |
| { |
| pmmLog(pMac, LOGE, |
| " No PE Session for given BSSID : Invalid Enter Uapsd Request"); |
| return eSIR_FAILURE; |
| } |
| |
| pDisableUapsdReqParams = vos_mem_malloc(sizeof(*pDisableUapsdReqParams)); |
| if (NULL == pDisableUapsdReqParams) |
| { |
| pmmLog(pMac, LOGE, |
| FL("Memory allocation failed for pDisableUapsdReqParams")); |
| return eSIR_MEM_ALLOC_FAILED; |
| } |
| |
| vos_mem_zero(pDisableUapsdReqParams, sizeof(*pDisableUapsdReqParams)); |
| /* Fill the BSSID corresponding to PS Req */ |
| vos_mem_copy(pDisableUapsdReqParams->bssid, psReqData->bssId, |
| sizeof(tSirMacAddr)); |
| |
| /* Fill the Sme Session Id */ |
| pDisableUapsdReqParams->sessionid = psessionEntry->smeSessionId; |
| |
| msgQ.type = WDA_EXIT_UAPSD_REQ; |
| msgQ.reserved = 0; |
| msgQ.bodyptr = pDisableUapsdReqParams; |
| msgQ.bodyval = 0; |
| |
| if(eSIR_SUCCESS != wdaPostCtrlMsg(pMac, &msgQ)) |
| { |
| pmmLog(pMac, LOGE, FL("Posting WDA_EXIT_UAPSD_REQ failed")); |
| vos_mem_free(pDisableUapsdReqParams); |
| return eSIR_FAILURE; |
| } |
| |
| /* |
| * we need to defer any incoming messages until we |
| * get a WDA_EXIT_UAPSD_RSP from HAL. |
| */ |
| SET_LIM_PROCESS_DEFD_MESGS(pMac, false); |
| pmmLog(pMac, LOG1, FL("WDA_EXIT_UAPSD_REQ Successfully sent to WDA")); |
| return eSIR_SUCCESS; |
| } |
| |
| void pmmOffloadProcessMessage(tpAniSirGlobal pMac, tpSirMsgQ pMsg) |
| { |
| switch (pMsg->type) |
| { |
| case eWNI_PMC_ENTER_BMPS_REQ: |
| { |
| tSirMbMsg *pMbMsg = (tSirMbMsg *)pMsg->bodyptr; |
| |
| if(eSIR_SUCCESS != |
| pmmOffloadEnterBmpsReqHandler(pMac, pMbMsg->data)) |
| { |
| pmmLog(pMac, LOGE, |
| "PMM: Failed to Process eWNI_PMC_ENTER_BMPS_REQ"); |
| } |
| } |
| break; |
| |
| case WDA_ENTER_BMPS_RSP: |
| if(eSIR_SUCCESS != |
| pmmOffloadEnterBmpsRespHandler(pMac, pMsg->bodyptr)) |
| { |
| pmmLog(pMac, LOGE, |
| "PMM: Failed to Process WDA_ENTER_BMPS_RSP"); |
| } |
| break; |
| |
| case eWNI_PMC_EXIT_BMPS_REQ: |
| { |
| tSirMbMsg *pMbMsg = (tSirMbMsg *)pMsg->bodyptr; |
| |
| if(eSIR_SUCCESS != |
| pmmOffloadExitBmpsReqHandler(pMac, pMbMsg->data)) |
| { |
| pmmLog(pMac, LOGE, |
| "PMM: Failed to Process eWNI_PMC_EXIT_BMPS_REQ"); |
| } |
| } |
| break; |
| |
| case WDA_EXIT_BMPS_RSP: |
| if(eSIR_SUCCESS != |
| pmmOffloadExitBmpsRespHandler(pMac, pMsg->bodyptr)) |
| { |
| pmmLog(pMac, LOGE, |
| "PMM: Failed to Process WDA_EXIT_BMPS_RSP"); |
| } |
| break; |
| |
| case eWNI_PMC_ENTER_UAPSD_REQ: |
| { |
| tSirMbMsg *pMbMsg = (tSirMbMsg *)pMsg->bodyptr; |
| if(eSIR_SUCCESS != |
| pmmOffloadEnterUapsdReqHandler(pMac, pMbMsg->data)) |
| { |
| pmmLog(pMac, LOGE, |
| "PMM: Failed to Process eWNI_PMC_ENTER_UAPSD_REQ"); |
| } |
| } |
| break; |
| |
| case WDA_ENTER_UAPSD_RSP: |
| if(eSIR_SUCCESS != |
| pmmOffloadEnterUapsdRespHandler(pMac, pMsg->bodyptr)) |
| { |
| pmmLog(pMac, LOGE, |
| "PMM: Failed to Process WDA_ENTER_UAPSD_RSP"); |
| } |
| break; |
| |
| case eWNI_PMC_EXIT_UAPSD_REQ: |
| { |
| tSirMbMsg *pMbMsg = (tSirMbMsg *)pMsg->bodyptr; |
| if(eSIR_SUCCESS != |
| pmmOffloadExitUapsdReqHandler(pMac, pMbMsg->data)) |
| { |
| pmmLog(pMac, LOGE, |
| "PMM: Failed to Process eWNI_PMC_EXIT_UAPSD_REQ"); |
| } |
| } |
| break; |
| |
| case WDA_EXIT_UAPSD_RSP: |
| if(eSIR_SUCCESS != |
| pmmOffloadExitUapsdRespHandler(pMac, pMsg->bodyptr)) |
| { |
| pmmLog(pMac, LOGE, |
| "PMM: Failed to Process WDA_EXIT_UAPSD_RSP"); |
| } |
| break; |
| |
| case eWNI_PMC_WOWL_ADD_BCAST_PTRN: |
| pmmSendWowlAddBcastPtrn(pMac, pMsg); |
| break; |
| |
| case eWNI_PMC_WOWL_DEL_BCAST_PTRN: |
| pmmSendWowlDelBcastPtrn(pMac, pMsg); |
| break; |
| |
| case eWNI_PMC_ENTER_WOWL_REQ: |
| pmmEnterWowlRequestHandler(pMac, pMsg); |
| break; |
| |
| case WDA_WOWL_ENTER_RSP: |
| pmmLog(pMac, LOGE, |
| "PMM: WDA_WOWL_ENTER_RSP not supported yet"); |
| break; |
| |
| case eWNI_PMC_EXIT_WOWL_REQ: |
| pmmExitWowlanRequestHandler(pMac, pMsg); |
| break; |
| |
| case WDA_WOWL_EXIT_RSP: |
| pmmLog(pMac, LOGE, |
| "PMM: WDA_WOWL_EXIT_RSP not supported yet"); |
| break; |
| |
| default: |
| PELOGW(pmmLog(pMac, LOGW, |
| FL("PMM: Unknown message in pmmMsgQ type %d, potential memory leak!!"), |
| pMsg->type);) |
| } |
| |
| if (NULL != pMsg->bodyptr) |
| { |
| vos_mem_free(pMsg->bodyptr); |
| pMsg->bodyptr = NULL; |
| } |
| } |