| /* |
| * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved. |
| * |
| * Previously licensed under the ISC license by Qualcomm Atheros, Inc. |
| * |
| * |
| * Permission to use, copy, modify, and/or distribute this software for |
| * any purpose with or without fee is hereby granted, provided that the |
| * above copyright notice and this permission notice appear in all |
| * copies. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL |
| * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED |
| * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE |
| * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL |
| * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR |
| * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER |
| * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR |
| * PERFORMANCE OF THIS SOFTWARE. |
| */ |
| |
| /* |
| * This file was originally distributed by Qualcomm Atheros, Inc. |
| * under proprietary terms before Copyright ownership was assigned |
| * to the Linux Foundation. |
| */ |
| |
| |
| /* |
| * This file limProcessSmeReqMessages.cc contains the code |
| * for processing SME request messages. |
| * Author: Chandra Modumudi |
| * Date: 02/11/02 |
| * History:- |
| * Date Modified by Modification Information |
| * -------------------------------------------------------------------- |
| * |
| */ |
| |
| #include "palTypes.h" |
| #include "wniApi.h" |
| #include "wni_cfg.h" |
| #include "cfgApi.h" |
| #include "sirApi.h" |
| #include "schApi.h" |
| #include "utilsApi.h" |
| #include "limTypes.h" |
| #include "limUtils.h" |
| #include "limAssocUtils.h" |
| #include "limSecurityUtils.h" |
| #include "limSerDesUtils.h" |
| #include "limSmeReqUtils.h" |
| #include "limIbssPeerMgmt.h" |
| #include "limAdmitControl.h" |
| #include "dphHashTable.h" |
| #include "limSendMessages.h" |
| #include "limApi.h" |
| #include "wmmApsd.h" |
| #include "sirMacProtDef.h" |
| #include "regdomain_common.h" |
| #include "rrmApi.h" |
| #include "nan_datapath.h" |
| #include "wma.h" |
| #include "sapApi.h" |
| #include "lim_process_fils.h" |
| #if defined(FEATURE_WLAN_ESE) && !defined(FEATURE_WLAN_ESE_UPLOAD) |
| #include "eseApi.h" |
| #endif |
| |
| #if defined WLAN_FEATURE_VOWIFI_11R |
| #include <limFT.h> |
| #endif |
| |
| /* This overhead is time for sending NOA start to host in case of GO/sending NULL data & receiving ACK |
| * in case of P2P Client and starting actual scanning with init scan req/rsp plus in case of concurrency, |
| * taking care of sending null data and receiving ACK to/from AP/Also SetChannel with calibration is taking |
| * around 7ms . |
| */ |
| #define SCAN_MESSAGING_OVERHEAD 20 // in msecs |
| #define JOIN_NOA_DURATION 2000 // in msecs |
| #define OEM_DATA_NOA_DURATION 60 // in msecs |
| #define DEFAULT_PASSIVE_MAX_CHANNEL_TIME 110 // in msecs |
| |
| #define CONV_MS_TO_US 1024 //conversion factor from ms to us |
| |
| #define BEACON_INTERVAL_THRESHOLD 50 /* in msecs */ |
| #define STA_BURST_SCAN_DURATION 120 /* in msecs */ |
| |
| // SME REQ processing function templates |
| static void __limProcessSmeStartReq(tpAniSirGlobal, tANI_U32 *); |
| static tANI_BOOLEAN __limProcessSmeSysReadyInd(tpAniSirGlobal, tANI_U32 *); |
| static tANI_BOOLEAN __limProcessSmeStartBssReq(tpAniSirGlobal, tpSirMsgQ pMsg); |
| static void __limProcessSmeScanReq(tpAniSirGlobal, tANI_U32 *); |
| static void __limProcessSmeJoinReq(tpAniSirGlobal, tANI_U32 *); |
| static void __limProcessSmeReassocReq(tpAniSirGlobal, tANI_U32 *); |
| static void __limProcessSmeDisassocReq(tpAniSirGlobal, tANI_U32 *); |
| static void __limProcessSmeDisassocCnf(tpAniSirGlobal, tANI_U32 *); |
| static void __limProcessSmeDeauthReq(tpAniSirGlobal, tANI_U32 *); |
| static void __limProcessSmeSetContextReq(tpAniSirGlobal, tANI_U32 *); |
| static tANI_BOOLEAN __limProcessSmeStopBssReq(tpAniSirGlobal, tpSirMsgQ pMsg); |
| static void limProcessSmeChannelChangeRequest(tpAniSirGlobal pMac, |
| tANI_U32 *pMsg); |
| static void limProcessSmeStartBeaconReq(tpAniSirGlobal pMac, |
| tANI_U32 *pMsg); |
| static void limProcessSmeDfsCsaIeRequest(tpAniSirGlobal pMac, tANI_U32 *pMsg); |
| |
| static void limStartBssUpdateAddIEBuffer(tpAniSirGlobal pMac, |
| tANI_U8 **pDstData_buff, |
| tANI_U16 *pDstDataLen, |
| tANI_U8 *pSrcData_buff, |
| tANI_U16 srcDataLen); |
| |
| static void limUpdateAddIEBuffer(tpAniSirGlobal pMac, |
| tANI_U8 **pDstData_buff, |
| tANI_U16 *pDstDataLen, |
| tANI_U8 *pSrcData_buff, |
| tANI_U16 srcDataLen); |
| static tANI_BOOLEAN limUpdateIBssPropAddIEs(tpAniSirGlobal pMac, |
| tANI_U8 **pDstData_buff, |
| tANI_U16 *pDstDataLen, |
| tSirModifyIE *pModifyIE); |
| static void limProcessModifyAddIEs(tpAniSirGlobal pMac, tANI_U32 *pMsg); |
| |
| static void limProcessUpdateAddIEs(tpAniSirGlobal pMac, tANI_U32 *pMsg); |
| |
| static void lim_process_ext_change_channel(tpAniSirGlobal mac_ctx, |
| uint32_t *msg); |
| |
| void __limProcessSmeAssocCnfNew(tpAniSirGlobal, tANI_U32, tANI_U32 *); |
| |
| extern void peRegisterTLHandle(tpAniSirGlobal pMac); |
| |
| static void lim_process_set_pdev_IEs(tpAniSirGlobal pMac, tANI_U32 *msg_buf); |
| static void lim_set_pdev_ht_ie(tpAniSirGlobal mac_ctx, tANI_U8 pdev_id, |
| tANI_U8 nss); |
| static void lim_set_pdev_vht_ie(tpAniSirGlobal mac_ctx, tANI_U8 pdev_id, |
| tANI_U8 nss); |
| static void __lim_process_send_disassoc_frame(tpAniSirGlobal mac_ctx, |
| uint32_t *msg_buf); |
| |
| #ifdef BACKGROUND_SCAN_ENABLED |
| |
| // start the background scan timers if it hasn't already started |
| static void |
| __limBackgroundScanInitiate(tpAniSirGlobal pMac) |
| { |
| if (pMac->lim.gLimBackgroundScanStarted) |
| return; |
| |
| //make sure timer is created first |
| if (TX_TIMER_VALID(pMac->lim.limTimers.gLimBackgroundScanTimer)) |
| { |
| limDeactivateAndChangeTimer(pMac, eLIM_BACKGROUND_SCAN_TIMER); |
| MTRACE(macTrace(pMac, TRACE_CODE_TIMER_ACTIVATE, NO_SESSION, eLIM_BACKGROUND_SCAN_TIMER)); |
| if (tx_timer_activate(&pMac->lim.limTimers.gLimBackgroundScanTimer) != TX_SUCCESS) |
| limLog(pMac, LOGP, FL("could not activate background scan timer")); |
| pMac->lim.gLimBackgroundScanStarted = true; |
| pMac->lim.gLimBackgroundScanChannelId = 0; |
| } |
| } |
| |
| #endif // BACKGROUND_SCAN_ENABLED |
| |
| /** |
| * __limFreshScanReqd() - determine if fresh scan request must be issued or not |
| * @mac_ctx - mac global context |
| * @return_fresh_results - fresh scan requested |
| * |
| * PE will do fresh scan, if all of the active sessions are in good state |
| * (Link Est or BSS Started). If one of the sessions is not in one of the these |
| * states, then PE does not do fresh scan. If no session exists (scanning very |
| * first time), then PE will always do fresh scan if SME asks it to do that. |
| */ |
| static uint8_t __limFreshScanReqd(tpAniSirGlobal mac_ctx, |
| uint8_t return_fresh_results) |
| { |
| int i; |
| uint8_t valid_state = true; |
| |
| limLog(mac_ctx, LOG1, FL("gLimSmeState: %d, return_fresh_results 0x%x"), |
| mac_ctx->lim.gLimSmeState, return_fresh_results); |
| |
| if (mac_ctx->lim.gLimSmeState != eLIM_SME_IDLE_STATE) { |
| limLog(mac_ctx, LOG1, FL("return false, global_sme_state: %d"), |
| mac_ctx->lim.gLimSmeState); |
| return false; |
| } |
| |
| for (i = 0; i < mac_ctx->lim.maxBssId; i++) { |
| if (mac_ctx->lim.gpSession[i].valid == false) |
| continue; |
| |
| limLog(mac_ctx, LOG1, |
| FL("session %d, bsstype %d, limSystemRole %d, limSmeState %d"), |
| i, mac_ctx->lim.gpSession[i].bssType, |
| mac_ctx->lim.gpSession[i].limSystemRole, |
| mac_ctx->lim.gpSession[i].limSmeState); |
| |
| if (mac_ctx->lim.gpSession[i].bssType == eSIR_NDI_MODE) |
| continue; |
| |
| if (mac_ctx->lim.gpSession[i].bssType == |
| eSIR_INFRASTRUCTURE_MODE |
| && mac_ctx->lim.gpSession[i].limSmeState == |
| eLIM_SME_LINK_EST_STATE) |
| continue; |
| |
| if (mac_ctx->lim.gpSession[i].limSystemRole == |
| eLIM_BT_AMP_STA_ROLE |
| && mac_ctx->lim.gpSession[i].limSmeState == |
| eLIM_SME_LINK_EST_STATE) |
| continue; |
| |
| if (mac_ctx->lim.gpSession[i].bssType == eSIR_IBSS_MODE |
| && mac_ctx->lim.gpSession[i].limSmeState == |
| eLIM_SME_NORMAL_STATE) |
| continue; |
| |
| if (mac_ctx->lim.gpSession[i].limSystemRole == |
| eLIM_BT_AMP_AP_ROLE |
| && mac_ctx->lim.gpSession[i].limSmeState == |
| eLIM_SME_NORMAL_STATE) |
| continue; |
| |
| if (mac_ctx->lim.gpSession[i].limSystemRole == |
| eLIM_BT_AMP_STA_ROLE |
| && mac_ctx->lim.gpSession[i].limSmeState == |
| eLIM_SME_NORMAL_STATE) |
| continue; |
| |
| if (mac_ctx->lim.gpSession[i].bssType == eSIR_INFRA_AP_MODE |
| && mac_ctx->lim.gpSession[i].pePersona == |
| VOS_P2P_GO_MODE |
| && mac_ctx->lim.gpSession[i].limSmeState == |
| eLIM_SME_NORMAL_STATE) |
| continue; |
| |
| if (mac_ctx->lim.gpSession[i].limSystemRole == eLIM_AP_ROLE |
| && mac_ctx->lim.gpSession[i].limSmeState == |
| eLIM_SME_NORMAL_STATE) |
| continue; |
| |
| valid_state = false; |
| break; |
| } |
| |
| if (valid_state && (return_fresh_results |
| & SIR_BG_SCAN_RETURN_FRESH_RESULTS)) { |
| limLog(mac_ctx, LOG1, FL("valid_state: %d, return true"), |
| valid_state); |
| return true; |
| } else { |
| limLog(mac_ctx, LOG1, FL("valid_state: %d, return false"), |
| valid_state); |
| return false; |
| } |
| } |
| |
| /** |
| * __limIsSmeAssocCnfValid() |
| * |
| *FUNCTION: |
| * This function is called by limProcessLmmMessages() upon |
| * receiving SME_ASSOC_CNF. |
| * |
| *LOGIC: |
| * Message validity checks are performed in this function |
| * |
| *ASSUMPTIONS: |
| * |
| *NOTE: |
| * |
| * @param pMeasReq Pointer to Received ASSOC_CNF message |
| * @return true When received SME_ASSOC_CNF is formatted |
| * correctly |
| * false otherwise |
| */ |
| |
| inline static tANI_U8 |
| __limIsSmeAssocCnfValid(tpSirSmeAssocCnf pAssocCnf) |
| { |
| if (limIsGroupAddr(pAssocCnf->peerMacAddr)) |
| return false; |
| else |
| return true; |
| } /*** end __limIsSmeAssocCnfValid() ***/ |
| |
| |
| /** |
| * __limGetSmeJoinReqSizeForAlloc() |
| * |
| *FUNCTION: |
| * This function is called in various places to get IE length |
| * from tSirBssDescription structure |
| * number being scanned. |
| * |
| *PARAMS: |
| * |
| *LOGIC: |
| * |
| *ASSUMPTIONS: |
| * NA |
| * |
| *NOTE: |
| * NA |
| * |
| * @param pBssDescr |
| * @return Total IE length |
| */ |
| |
| static tANI_U16 |
| __limGetSmeJoinReqSizeForAlloc(tANI_U8 *pBuf) |
| { |
| tANI_U16 len = 0; |
| |
| if (!pBuf) |
| return len; |
| |
| pBuf += sizeof(tANI_U16); |
| len = limGetU16( pBuf ); |
| return (len + sizeof( tANI_U16 )); |
| } /*** end __limGetSmeJoinReqSizeForAlloc() ***/ |
| |
| |
| /**---------------------------------------------------------------- |
| \fn __limIsDeferedMsgForLearn |
| |
| \brief Has role only if 11h is enabled. Not used on STA side. |
| Defers the message if SME is in learn state and brings |
| the LIM back to normal mode. |
| |
| \param pMac |
| \param pMsg - Pointer to message posted from SME to LIM. |
| \return TRUE - If defered |
| FALSE - Otherwise |
| ------------------------------------------------------------------*/ |
| static tANI_BOOLEAN |
| __limIsDeferedMsgForLearn(tpAniSirGlobal pMac, tpSirMsgQ pMsg) |
| { |
| if (limIsSystemInScanState(pMac)) |
| { |
| if (limDeferMsg(pMac, pMsg) != TX_SUCCESS) |
| { |
| PELOGE(limLog(pMac, LOGE, FL("Could not defer Msg = %d"), pMsg->type);) |
| return eANI_BOOLEAN_FALSE; |
| } |
| PELOG1(limLog(pMac, LOG1, FL("Defer the message, in learn mode type = %d"), |
| pMsg->type);) |
| |
| /** Send finish scan req to HAL only if LIM is not waiting for any response |
| * from HAL like init scan rsp, start scan rsp etc. |
| */ |
| if (GET_LIM_PROCESS_DEFD_MESGS(pMac)) |
| { |
| //Set the resume channel to Any valid channel (invalid). |
| //This will instruct HAL to set it to any previous valid channel. |
| peSetResumeChannel(pMac, 0, 0); |
| limSendHalFinishScanReq(pMac, eLIM_HAL_FINISH_LEARN_WAIT_STATE); |
| } |
| |
| return eANI_BOOLEAN_TRUE; |
| } |
| return eANI_BOOLEAN_FALSE; |
| } |
| |
| /**---------------------------------------------------------------- |
| \fn __limIsDeferedMsgForRadar |
| |
| \brief Has role only if 11h is enabled. Not used on STA side. |
| Defers the message if radar is detected. |
| |
| \param pMac |
| \param pMsg - Pointer to message posted from SME to LIM. |
| \return TRUE - If defered |
| FALSE - Otherwise |
| ------------------------------------------------------------------*/ |
| static tANI_BOOLEAN |
| __limIsDeferedMsgForRadar(tpAniSirGlobal pMac, tpSirMsgQ pMsg) |
| { |
| /** fRadarDetCurOperChan will be set only if we detect radar in current |
| * operating channel and System Role == AP ROLE */ |
| //TODO: Need to take care radar detection. |
| //if (LIM_IS_RADAR_DETECTED(pMac)) |
| if( 0 ) |
| { |
| if (limDeferMsg(pMac, pMsg) != TX_SUCCESS) |
| { |
| PELOGE(limLog(pMac, LOGE, FL("Could not defer Msg = %d"), pMsg->type);) |
| return eANI_BOOLEAN_FALSE; |
| } |
| PELOG1(limLog(pMac, LOG1, FL("Defer the message, in learn mode type = %d"), |
| pMsg->type);) |
| return eANI_BOOLEAN_TRUE; |
| } |
| return eANI_BOOLEAN_FALSE; |
| } |
| |
| |
| /** |
| * __limProcessSmeStartReq() |
| * |
| *FUNCTION: |
| * This function is called to process SME_START_REQ message |
| * from HDD or upper layer application. |
| * |
| *LOGIC: |
| * |
| *ASSUMPTIONS: |
| * |
| *NOTE: |
| * |
| * @param pMac Pointer to Global MAC structure |
| * @param *pMsgBuf A pointer to the SME message buffer |
| * @return None |
| */ |
| |
| static void |
| __limProcessSmeStartReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) |
| { |
| tSirResultCodes retCode = eSIR_SME_SUCCESS; |
| tANI_U8 smesessionId; |
| tANI_U16 smetransactionId; |
| |
| |
| PELOG1(limLog(pMac, LOG1, FL("Received START_REQ"));) |
| |
| limGetSessionInfo(pMac,(tANI_U8 *)pMsgBuf,&smesessionId,&smetransactionId); |
| |
| if (pMac->lim.gLimSmeState == eLIM_SME_OFFLINE_STATE) |
| { |
| pMac->lim.gLimSmeState = eLIM_SME_IDLE_STATE; |
| |
| MTRACE(macTrace(pMac, TRACE_CODE_SME_STATE, NO_SESSION, pMac->lim.gLimSmeState)); |
| |
| /// By default do not return after first scan match |
| pMac->lim.gLimReturnAfterFirstMatch = 0; |
| |
| /// By default return unique scan results |
| pMac->lim.gLimReturnUniqueResults = true; |
| pMac->lim.gLimSmeScanResultLength = 0; |
| #ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD |
| pMac->lim.gLimSmeLfrScanResultLength = 0; |
| #endif |
| |
| if (((tSirSmeStartReq *) pMsgBuf)->sendNewBssInd) |
| { |
| /* |
| * Need to indicate new BSSs found during background scanning to |
| * host. Update this parameter at CFG |
| */ |
| if (cfgSetInt(pMac, WNI_CFG_NEW_BSS_FOUND_IND, ((tSirSmeStartReq *) pMsgBuf)->sendNewBssInd) |
| != eSIR_SUCCESS) |
| { |
| limLog(pMac, LOGP, FL("could not set NEIGHBOR_BSS_IND at CFG")); |
| retCode = eSIR_SME_UNEXPECTED_REQ_RESULT_CODE; |
| } |
| } |
| } |
| else |
| { |
| /** |
| * Should not have received eWNI_SME_START_REQ in states |
| * other than OFFLINE. Return response to host and |
| * log error |
| */ |
| limLog(pMac, LOGE, FL("Invalid SME_START_REQ received in SME state %X"),pMac->lim.gLimSmeState ); |
| retCode = eSIR_SME_UNEXPECTED_REQ_RESULT_CODE; |
| } |
| limSendSmeRsp(pMac, eWNI_SME_START_RSP, retCode,smesessionId,smetransactionId); |
| } /*** end __limProcessSmeStartReq() ***/ |
| |
| |
| /** ------------------------------------------------------------- |
| \fn __limProcessSmeSysReadyInd |
| \brief handles the notification from HDD. PE just forwards this message to HAL. |
| \param tpAniSirGlobal pMac |
| \param tANI_U32* pMsgBuf |
| \return TRUE-Posting to HAL failed, so PE will consume the buffer. |
| \ FALSE-Posting to HAL successful, so HAL will consume the buffer. |
| -------------------------------------------------------------*/ |
| static tANI_BOOLEAN |
| __limProcessSmeSysReadyInd(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) |
| { |
| tSirMsgQ msg; |
| |
| msg.type = WDA_SYS_READY_IND; |
| msg.reserved = 0; |
| msg.bodyptr = pMsgBuf; |
| msg.bodyval = 0; |
| |
| if (ANI_DRIVER_TYPE(pMac) != eDRIVER_TYPE_MFG) { |
| peRegisterTLHandle(pMac); |
| } |
| PELOGW(limLog(pMac, LOGW, FL("sending WDA_SYS_READY_IND msg to HAL"));) |
| MTRACE(macTraceMsgTx(pMac, NO_SESSION, msg.type)); |
| |
| if (eSIR_SUCCESS != wdaPostCtrlMsg(pMac, &msg)) |
| { |
| limLog(pMac, LOGP, FL("wdaPostCtrlMsg failed")); |
| return eANI_BOOLEAN_TRUE; |
| } |
| return eANI_BOOLEAN_FALSE; |
| } |
| |
| #ifdef WLAN_FEATURE_11AC |
| |
| tANI_U32 limGetCenterChannel(tpAniSirGlobal pMac,tANI_U8 primarychanNum,ePhyChanBondState secondaryChanOffset, tANI_U8 chanWidth) |
| { |
| if (chanWidth == WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ) |
| { |
| switch(secondaryChanOffset) |
| { |
| case PHY_QUADRUPLE_CHANNEL_20MHZ_CENTERED_40MHZ_CENTERED: |
| return primarychanNum; |
| case PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_CENTERED: |
| return primarychanNum + 2; |
| case PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_CENTERED: |
| return primarychanNum - 2; |
| case PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW: |
| return primarychanNum + 6; |
| case PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW: |
| return primarychanNum + 2; |
| case PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH: |
| return primarychanNum - 2; |
| case PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH: |
| return primarychanNum - 6; |
| default : |
| return eSIR_CFG_INVALID_ID; |
| } |
| } |
| else if (chanWidth == WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ) |
| { |
| switch(secondaryChanOffset) |
| { |
| case PHY_DOUBLE_CHANNEL_LOW_PRIMARY: |
| return primarychanNum + 2; |
| case PHY_DOUBLE_CHANNEL_HIGH_PRIMARY: |
| return primarychanNum - 2; |
| case PHY_QUADRUPLE_CHANNEL_20MHZ_CENTERED_40MHZ_CENTERED: |
| return primarychanNum; |
| case PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_CENTERED: |
| return primarychanNum + 2; |
| case PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_CENTERED: |
| return primarychanNum - 2; |
| case PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW: |
| return primarychanNum + 2; |
| case PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW: |
| return primarychanNum - 2; |
| case PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH: |
| return primarychanNum + 2; |
| case PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH: |
| return primarychanNum - 2; |
| default : |
| return eSIR_CFG_INVALID_ID; |
| } |
| } |
| return primarychanNum; |
| } |
| |
| #endif |
| /** |
| * __limHandleSmeStartBssRequest() |
| * |
| *FUNCTION: |
| * This function is called to process SME_START_BSS_REQ message |
| * from HDD or upper layer application. |
| * |
| *LOGIC: |
| * |
| *ASSUMPTIONS: |
| * |
| *NOTE: |
| * |
| * @param pMac Pointer to Global MAC structure |
| * @param *pMsgBuf A pointer to the SME message buffer |
| * @return None |
| */ |
| |
| static void |
| __limHandleSmeStartBssRequest(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) |
| { |
| tANI_U16 size; |
| tANI_U32 val = 0; |
| tSirRetStatus retStatus; |
| tSirMacChanNum channelNumber; |
| tLimMlmStartReq *pMlmStartReq = NULL; |
| tpSirSmeStartBssReq pSmeStartBssReq = NULL; |
| tSirResultCodes retCode = eSIR_SME_SUCCESS; |
| tANI_U32 autoGenBssId = FALSE; //Flag Used in case of IBSS to Auto generate BSSID. |
| tANI_U8 sessionId; |
| tpPESession psessionEntry = NULL; |
| tANI_U8 smesessionId; |
| tANI_U16 smetransactionId; |
| struct vdev_type_nss *vdev_type_nss; |
| |
| #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM //FEATURE_WLAN_DIAG_SUPPORT |
| //Since the session is not created yet, sending NULL. The response should have the correct state. |
| limDiagEventReport(pMac, WLAN_PE_DIAG_START_BSS_REQ_EVENT, NULL, 0, 0); |
| #endif //FEATURE_WLAN_DIAG_SUPPORT |
| |
| PELOG1(limLog(pMac, LOG1, FL("Received START_BSS_REQ"));) |
| |
| /* Global Sme state and mlm states are not defined yet, for BT-AMP Suppoprt . TO BE DONE */ |
| if ( (pMac->lim.gLimSmeState == eLIM_SME_OFFLINE_STATE) || |
| (pMac->lim.gLimSmeState == eLIM_SME_IDLE_STATE)) |
| { |
| size = sizeof(tSirSmeStartBssReq) + SIR_MAC_MAX_IE_LENGTH; |
| |
| pSmeStartBssReq = vos_mem_malloc(size); |
| if ( NULL == pSmeStartBssReq ) |
| { |
| PELOGE(limLog(pMac, LOGE, FL("AllocateMemory failed for pMac->lim.gpLimStartBssReq"));) |
| /// Send failure response to host |
| retCode = eSIR_SME_RESOURCES_UNAVAILABLE; |
| goto end; |
| } |
| |
| vos_mem_set((void *)pSmeStartBssReq, size, 0); |
| |
| if ((limStartBssReqSerDes(pMac, pSmeStartBssReq, (tANI_U8 *) pMsgBuf) == eSIR_FAILURE) || |
| (!limIsSmeStartBssReqValid(pMac, pSmeStartBssReq))) |
| { |
| PELOGW(limLog(pMac, LOGW, FL("Received invalid eWNI_SME_START_BSS_REQ"));) |
| retCode = eSIR_SME_INVALID_PARAMETERS; |
| goto free; |
| } |
| |
| /* This is the place where PE is going to create a session. |
| * If session is not existed, then create a new session */ |
| if((psessionEntry = peFindSessionByBssid(pMac,pSmeStartBssReq->bssId,&sessionId)) != NULL) |
| { |
| limLog(pMac, LOGW, FL("Session Already exists for given BSSID")); |
| retCode = eSIR_SME_BSS_ALREADY_STARTED_OR_JOINED; |
| psessionEntry = NULL; |
| goto free; |
| } |
| else |
| { |
| if((psessionEntry = peCreateSession(pMac, |
| pSmeStartBssReq->bssId, |
| &sessionId, |
| pMac->lim.maxStation, |
| pSmeStartBssReq->bssType)) == NULL) |
| { |
| limLog(pMac, LOGW, FL("Session Can not be created ")); |
| retCode = eSIR_SME_RESOURCES_UNAVAILABLE; |
| goto free; |
| } |
| } |
| |
| if (VOS_NDI_MODE != pSmeStartBssReq->bssPersona) { |
| /* Probe resp add ie */ |
| limStartBssUpdateAddIEBuffer(pMac, |
| &psessionEntry->addIeParams.probeRespData_buff, |
| &psessionEntry->addIeParams.probeRespDataLen, |
| pSmeStartBssReq->addIeParams.probeRespData_buff, |
| pSmeStartBssReq->addIeParams.probeRespDataLen); |
| |
| /* Probe Beacon add ie */ |
| limStartBssUpdateAddIEBuffer(pMac, |
| &psessionEntry->addIeParams.probeRespBCNData_buff, |
| &psessionEntry->addIeParams.probeRespBCNDataLen, |
| pSmeStartBssReq->addIeParams.probeRespBCNData_buff, |
| pSmeStartBssReq->addIeParams.probeRespBCNDataLen); |
| |
| /* Assoc resp IE */ |
| limStartBssUpdateAddIEBuffer(pMac, |
| &psessionEntry->addIeParams.assocRespData_buff, |
| &psessionEntry->addIeParams.assocRespDataLen, |
| pSmeStartBssReq->addIeParams.assocRespData_buff, |
| pSmeStartBssReq->addIeParams.assocRespDataLen); |
| } |
| |
| /* Store the session related parameters in newly created session */ |
| psessionEntry->pLimStartBssReq = pSmeStartBssReq; |
| |
| /* Store PE sessionId in session Table */ |
| psessionEntry->peSessionId = sessionId; |
| |
| /* Store SME session Id in sessionTable */ |
| psessionEntry->smeSessionId = pSmeStartBssReq->sessionId; |
| |
| psessionEntry->transactionId = pSmeStartBssReq->transactionId; |
| |
| vos_mem_copy(&(psessionEntry->htConfig), &(pSmeStartBssReq->htConfig), |
| sizeof(psessionEntry->htConfig)); |
| |
| sirCopyMacAddr(psessionEntry->selfMacAddr,pSmeStartBssReq->selfMacAddr); |
| |
| /* Copy SSID to session table */ |
| vos_mem_copy( (tANI_U8 *)&psessionEntry->ssId, |
| (tANI_U8 *)&pSmeStartBssReq->ssId, |
| (pSmeStartBssReq->ssId.length + 1)); |
| |
| psessionEntry->bssType = pSmeStartBssReq->bssType; |
| |
| psessionEntry->nwType = pSmeStartBssReq->nwType; |
| |
| psessionEntry->beaconParams.beaconInterval = pSmeStartBssReq->beaconInterval; |
| |
| /* Store the channel number in session Table */ |
| psessionEntry->currentOperChannel = pSmeStartBssReq->channelId; |
| |
| /*Store Persona */ |
| psessionEntry->pePersona = pSmeStartBssReq->bssPersona; |
| VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,FL("PE PERSONA=%d"), |
| psessionEntry->pePersona); |
| |
| /*Update the phymode*/ |
| psessionEntry->gLimPhyMode = pSmeStartBssReq->nwType; |
| |
| psessionEntry->maxTxPower = cfgGetRegulatoryMaxTransmitPower( pMac, |
| psessionEntry->currentOperChannel ); |
| /* Store the dot 11 mode in to the session Table*/ |
| psessionEntry->dot11mode = pSmeStartBssReq->dot11mode; |
| #ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH |
| psessionEntry->cc_switch_mode = pSmeStartBssReq->cc_switch_mode; |
| #endif |
| psessionEntry->htCapability = IS_DOT11_MODE_HT(psessionEntry->dot11mode); |
| #ifdef WLAN_FEATURE_11AC |
| psessionEntry->vhtCapability = IS_DOT11_MODE_VHT(psessionEntry->dot11mode); |
| VOS_TRACE(VOS_MODULE_ID_PE,VOS_TRACE_LEVEL_INFO, |
| FL("*****psessionEntry->vhtCapability = %d"),psessionEntry->vhtCapability); |
| #endif |
| |
| psessionEntry->txLdpcIniFeatureEnabled = |
| pSmeStartBssReq->txLdpcIniFeatureEnabled; |
| |
| #ifdef WLAN_FEATURE_11W |
| psessionEntry->limRmfEnabled = pSmeStartBssReq->pmfCapable ? 1 : 0; |
| limLog(pMac, LOG1, FL("Session RMF enabled: %d"), psessionEntry->limRmfEnabled); |
| #endif |
| |
| /* Update sub 20MHz channel width */ |
| psessionEntry->sub20_channelwidth = pSmeStartBssReq->sub20_channelwidth; |
| psessionEntry->lim_sub20_channel_switch_bandwidth = |
| pSmeStartBssReq->sub20_channelwidth; |
| |
| vos_mem_copy((void*)&psessionEntry->rateSet, |
| (void*)&pSmeStartBssReq->operationalRateSet, |
| sizeof(tSirMacRateSet)); |
| vos_mem_copy((void*)&psessionEntry->extRateSet, |
| (void*)&pSmeStartBssReq->extendedRateSet, |
| sizeof(tSirMacRateSet)); |
| |
| if (IS_5G_CH(psessionEntry->currentOperChannel)) |
| vdev_type_nss = &pMac->vdev_type_nss_5g; |
| else |
| vdev_type_nss = &pMac->vdev_type_nss_2g; |
| switch(pSmeStartBssReq->bssType) |
| { |
| case eSIR_INFRA_AP_MODE: |
| psessionEntry->limSystemRole = eLIM_AP_ROLE; |
| psessionEntry->privacy = pSmeStartBssReq->privacy; |
| psessionEntry->fwdWPSPBCProbeReq = pSmeStartBssReq->fwdWPSPBCProbeReq; |
| psessionEntry->authType = pSmeStartBssReq->authType; |
| /* Store the DTIM period */ |
| psessionEntry->dtimPeriod = (tANI_U8)pSmeStartBssReq->dtimPeriod; |
| /*Enable/disable UAPSD*/ |
| psessionEntry->apUapsdEnable = pSmeStartBssReq->apUapsdEnable; |
| if (psessionEntry->pePersona == VOS_P2P_GO_MODE) |
| { |
| psessionEntry->proxyProbeRspEn = 0; |
| psessionEntry->vdev_nss = vdev_type_nss->p2p_go; |
| } |
| else |
| { |
| /* To detect PBC overlap in SAP WPS mode, Host handles |
| * Probe Requests. |
| */ |
| if(SAP_WPS_DISABLED == pSmeStartBssReq->wps_state) |
| { |
| psessionEntry->proxyProbeRspEn = 1; |
| } |
| else |
| { |
| psessionEntry->proxyProbeRspEn = 0; |
| } |
| psessionEntry->vdev_nss = vdev_type_nss->sap; |
| } |
| psessionEntry->ssidHidden = pSmeStartBssReq->ssidHidden; |
| psessionEntry->wps_state = pSmeStartBssReq->wps_state; |
| psessionEntry->sap_dot11mc = pSmeStartBssReq->sap_dot11mc; |
| psessionEntry->vendor_vht_for_24ghz_sap = |
| pSmeStartBssReq->vendor_vht_for_24ghz_sap; |
| limGetShortSlotFromPhyMode(pMac, psessionEntry, |
| psessionEntry->gLimPhyMode, |
| &psessionEntry->shortSlotTimeSupported); |
| psessionEntry->isCoalesingInIBSSAllowed = |
| pSmeStartBssReq->isCoalesingInIBSSAllowed; |
| psessionEntry->beacon_tx_rate = |
| pSmeStartBssReq->beacon_tx_rate; |
| break; |
| case eSIR_IBSS_MODE: |
| psessionEntry->limSystemRole = eLIM_STA_IN_IBSS_ROLE; |
| limGetShortSlotFromPhyMode(pMac, psessionEntry, |
| psessionEntry->gLimPhyMode, |
| &psessionEntry->shortSlotTimeSupported); |
| |
| // initialize to "OPEN". will be updated upon key installation |
| psessionEntry->encryptType = eSIR_ED_NONE; |
| psessionEntry->vdev_nss = vdev_type_nss->ibss; |
| break; |
| |
| case eSIR_BTAMP_AP_MODE: |
| psessionEntry->limSystemRole = eLIM_BT_AMP_AP_ROLE; |
| break; |
| |
| case eSIR_BTAMP_STA_MODE: |
| psessionEntry->limSystemRole = eLIM_BT_AMP_STA_ROLE; |
| break; |
| |
| case eSIR_NDI_MODE: |
| psessionEntry->limSystemRole = eLIM_NDI_ROLE; |
| break; |
| |
| case eSIR_AUTO_MODE: |
| default: |
| //not used anywhere...used in scan function |
| break; |
| } |
| limLog(pMac, LOG1, FL("persona - %d, nss - %d"), |
| psessionEntry->pePersona, psessionEntry->vdev_nss); |
| // BT-AMP: Allocate memory for the array of parsed (Re)Assoc request structure |
| if ( (pSmeStartBssReq->bssType == eSIR_BTAMP_AP_MODE) |
| || (pSmeStartBssReq->bssType == eSIR_INFRA_AP_MODE) |
| ) |
| { |
| psessionEntry->parsedAssocReq = vos_mem_malloc( |
| psessionEntry->dph.dphHashTable.size * sizeof(tpSirAssocReq)); |
| if ( NULL == psessionEntry->parsedAssocReq ) |
| { |
| limLog(pMac, LOGW, FL("AllocateMemory() failed")); |
| retCode = eSIR_SME_RESOURCES_UNAVAILABLE; |
| goto free; |
| } |
| vos_mem_set(psessionEntry->parsedAssocReq, |
| (psessionEntry->dph.dphHashTable.size * sizeof(tpSirAssocReq)), |
| 0 ); |
| } |
| |
| /* |
| * Channel Bonding is not addressd yet for BT-AMP Support. |
| * It will be addressed later. |
| * Channel number is ignored in NDI start request. Hence allow the |
| * session configuration for NDI mode even if channelId is 0. |
| */ |
| channelNumber = pSmeStartBssReq->channelId; |
| if (pSmeStartBssReq->channelId) |
| { |
| #ifdef QCA_HT_2040_COEX |
| if (pSmeStartBssReq->obssEnabled) |
| psessionEntry->htSupportedChannelWidthSet = |
| IS_DOT11_MODE_HT(psessionEntry->dot11mode) ? 1 : 0; |
| else |
| #endif |
| psessionEntry->htSupportedChannelWidthSet = |
| (pSmeStartBssReq->cbMode > 0)?1:0; |
| psessionEntry->htSecondaryChannelOffset = pSmeStartBssReq->cbMode; |
| psessionEntry->htRecommendedTxWidthSet = |
| (psessionEntry->htSecondaryChannelOffset)? 1:0; |
| VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, |
| FL("cbMode %u"), pSmeStartBssReq->cbMode); |
| #ifdef WLAN_FEATURE_11AC |
| if(psessionEntry->vhtCapability) |
| { |
| tANI_U32 centerChan; |
| tANI_U32 chanWidth; |
| |
| chanWidth = pSmeStartBssReq->vht_channel_width; |
| |
| VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, |
| FL("vht_channel_width %u"), |
| pSmeStartBssReq->vht_channel_width); |
| |
| if(channelNumber <= RF_CHAN_14 && |
| chanWidth != eHT_CHANNEL_WIDTH_20MHZ) |
| { |
| chanWidth = eHT_CHANNEL_WIDTH_20MHZ; |
| limLog(pMac, LOG1, FL("Setting chanWidth to 20Mhz for" |
| " channel %d"),channelNumber); |
| } |
| |
| /* |
| * For Sta+p2p-Go concurrency |
| * vhtTxChannelWidthSet is used for storing p2p-GO channel width |
| * apChanWidth is used for storing the AP channel width that |
| * the Sta is going to associate. |
| * Initialize the apChanWidth same as p2p-GO channel width this |
| * gets over written once the station joins the AP |
| */ |
| if(chanWidth == eHT_CHANNEL_WIDTH_20MHZ || |
| chanWidth == eHT_CHANNEL_WIDTH_40MHZ) |
| { |
| psessionEntry->vhtTxChannelWidthSet = |
| WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ; |
| psessionEntry->apChanWidth = |
| WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ; |
| } |
| if (chanWidth == eHT_CHANNEL_WIDTH_80MHZ) |
| { |
| psessionEntry->vhtTxChannelWidthSet = |
| WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ; |
| psessionEntry->apChanWidth = |
| WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ; |
| |
| centerChan = limGetCenterChannel( pMac, channelNumber, |
| pSmeStartBssReq->cbMode, |
| WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ); |
| if(centerChan != eSIR_CFG_INVALID_ID) |
| { |
| limLog(pMac, LOGW, FL("***Center Channel for " |
| "80MHZ channel width = %d"),centerChan); |
| psessionEntry->apCenterChan = centerChan; |
| if (cfgSetInt(pMac, |
| WNI_CFG_VHT_CHANNEL_CENTER_FREQ_SEGMENT1, |
| centerChan) != eSIR_SUCCESS) |
| { |
| limLog(pMac, LOGP, FL("could not set " |
| "WNI_CFG_CHANNEL_BONDING_MODE at CFG")); |
| retCode = eSIR_LOGP_EXCEPTION; |
| goto free; |
| } |
| } |
| } |
| |
| } |
| psessionEntry->htSecondaryChannelOffset = limGetHTCBState(pSmeStartBssReq->cbMode); |
| #endif |
| } |
| else if(pSmeStartBssReq->bssType != eSIR_NDI_MODE) { |
| limLog(pMac, LOGW, FL("Received invalid eWNI_SME_START_BSS_REQ")); |
| retCode = eSIR_SME_INVALID_PARAMETERS; |
| goto free; |
| } |
| |
| // Delete pre-auth list if any |
| limDeletePreAuthList(pMac); |
| |
| psessionEntry->htCapability = IS_DOT11_MODE_HT(pSmeStartBssReq->dot11mode); |
| |
| /* |
| * keep the RSN/WPA IE information in PE Session Entry |
| * later will be using this to check when received (Re)Assoc req |
| */ |
| limSetRSNieWPAiefromSmeStartBSSReqMessage(pMac,&pSmeStartBssReq->rsnIE,psessionEntry); |
| |
| if (LIM_IS_AP_ROLE(psessionEntry) || |
| LIM_IS_IBSS_ROLE(psessionEntry) || |
| LIM_IS_NDI_ROLE(psessionEntry)) { |
| psessionEntry->gLimProtectionControl = pSmeStartBssReq->protEnabled; |
| /* |
| * each byte will have the following info |
| * bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 |
| * reserved reserved RIFS Lsig n-GF ht20 11g 11b |
| */ |
| vos_mem_copy( (void *) &psessionEntry->cfgProtection, |
| (void *) &pSmeStartBssReq->ht_capab, |
| sizeof( tANI_U16 )); |
| /* Initialize WPS PBC session link list */ |
| psessionEntry->pAPWPSPBCSession = NULL; |
| } |
| |
| /* Prepare and Issue LIM_MLM_START_REQ to MLM */ |
| pMlmStartReq = vos_mem_malloc(sizeof(tLimMlmStartReq)); |
| if (NULL == pMlmStartReq) { |
| limLog(pMac, LOGP, |
| FL("call to AllocateMemory failed for mlmStartReq")); |
| retCode = eSIR_SME_RESOURCES_UNAVAILABLE; |
| goto free; |
| } |
| |
| vos_mem_set((void *) pMlmStartReq, sizeof(tLimMlmStartReq), 0); |
| |
| /* Copy SSID to the MLM start structure */ |
| vos_mem_copy( (tANI_U8 *) &pMlmStartReq->ssId, |
| (tANI_U8 *) &pSmeStartBssReq->ssId, |
| pSmeStartBssReq->ssId.length + 1); |
| pMlmStartReq->ssidHidden = pSmeStartBssReq->ssidHidden; |
| pMlmStartReq->obssProtEnabled = pSmeStartBssReq->obssProtEnabled; |
| |
| |
| pMlmStartReq->bssType = psessionEntry->bssType; |
| |
| /* Fill PE session Id from the session Table */ |
| pMlmStartReq->sessionId = psessionEntry->peSessionId; |
| |
| if ((pMlmStartReq->bssType == eSIR_BTAMP_STA_MODE) || |
| (pMlmStartReq->bssType == eSIR_BTAMP_AP_MODE) || |
| (pMlmStartReq->bssType == eSIR_INFRA_AP_MODE) || |
| (pMlmStartReq->bssType == eSIR_NDI_MODE)) { |
| /* Copy the BSSId from sessionTable to mlmStartReq struct */ |
| sirCopyMacAddr(pMlmStartReq->bssId,psessionEntry->bssId); |
| } else { |
| /* ibss mode */ |
| pMac->lim.gLimIbssCoalescingHappened = false; |
| |
| retStatus = wlan_cfgGetInt(pMac, WNI_CFG_IBSS_AUTO_BSSID, |
| &autoGenBssId); |
| if (retStatus != eSIR_SUCCESS) { |
| limLog(pMac, LOGP, |
| FL("Could not retrieve Auto Gen BSSID, retStatus=%d"), |
| retStatus); |
| retCode = eSIR_LOGP_EXCEPTION; |
| goto free; |
| } |
| |
| if (!autoGenBssId) { |
| /* BSSID is not auto generated. Get it from session entry */ |
| sirCopyMacAddr(pMlmStartReq->bssId,psessionEntry->bssId); |
| |
| if (pMlmStartReq->bssId[0] & 0x01) { |
| limLog(pMac, LOGE, |
| FL("Autogenerating BSSID for IBSS with group BSSID")); |
| autoGenBssId = TRUE; |
| } |
| } |
| |
| if (autoGenBssId) { |
| /* |
| * if BSSID is not any uc id |
| * then use locally generated BSSID. |
| * Autogenerate the BSSID using a random value. |
| */ |
| |
| limGetRandomBssid( pMac, pMlmStartReq->bssId); |
| pMlmStartReq->bssId[0]= 0x02; |
| |
| /* Copy randomly generated BSSID to the session Table */ |
| sirCopyMacAddr(psessionEntry->bssId,pMlmStartReq->bssId); |
| } |
| } |
| /* store the channel num in mlmstart req structure */ |
| pMlmStartReq->channelNumber = psessionEntry->currentOperChannel; |
| pMlmStartReq->cbMode = pSmeStartBssReq->cbMode; |
| pMlmStartReq->beaconPeriod = psessionEntry->beaconParams.beaconInterval; |
| |
| if (LIM_IS_AP_ROLE(psessionEntry)) { |
| pMlmStartReq->dtimPeriod = psessionEntry->dtimPeriod; |
| pMlmStartReq->wps_state = psessionEntry->wps_state; |
| } else { |
| if (wlan_cfgGetInt(pMac, WNI_CFG_DTIM_PERIOD, &val) != eSIR_SUCCESS) |
| limLog(pMac, LOGP, FL("could not retrieve DTIM Period")); |
| pMlmStartReq->dtimPeriod = (tANI_U8)val; |
| } |
| |
| if (wlan_cfgGetInt(pMac, WNI_CFG_CFP_PERIOD, &val) != eSIR_SUCCESS) |
| limLog(pMac, LOGP, FL("could not retrieve Beacon interval")); |
| pMlmStartReq->cfParamSet.cfpPeriod = (tANI_U8)val; |
| |
| if (wlan_cfgGetInt(pMac, WNI_CFG_CFP_MAX_DURATION, &val) != eSIR_SUCCESS) |
| limLog(pMac, LOGP, FL("could not retrieve CFPMaxDuration")); |
| pMlmStartReq->cfParamSet.cfpMaxDuration = (tANI_U16) val; |
| |
| //this may not be needed anymore now, as rateSet is now included in the session entry and MLM has session context. |
| vos_mem_copy((void*)&pMlmStartReq->rateSet, (void*)&psessionEntry->rateSet, |
| sizeof(tSirMacRateSet)); |
| |
| // Now populate the 11n related parameters |
| pMlmStartReq->nwType = psessionEntry->nwType; |
| pMlmStartReq->htCapable = psessionEntry->htCapability; |
| // |
| // FIXME_GEN4 - Determine the appropriate defaults... |
| // |
| pMlmStartReq->htOperMode = pMac->lim.gHTOperMode; |
| pMlmStartReq->dualCTSProtection = pMac->lim.gHTDualCTSProtection; // Unused |
| pMlmStartReq->txChannelWidthSet = psessionEntry->htRecommendedTxWidthSet; |
| |
| psessionEntry->limRFBand = limGetRFBand(channelNumber); |
| |
| // Initialize 11h Enable Flag |
| psessionEntry->lim11hEnable = 0; |
| if (pMlmStartReq->bssType != eSIR_IBSS_MODE) { |
| if (CHAN_HOP_ALL_BANDS_ENABLE || |
| SIR_BAND_5_GHZ == psessionEntry->limRFBand) { |
| if (wlan_cfgGetInt(pMac, WNI_CFG_11H_ENABLED, &val) != |
| eSIR_SUCCESS) |
| limLog(pMac, LOGP, |
| FL("Fail to get WNI_CFG_11H_ENABLED ")); |
| psessionEntry->lim11hEnable = val; |
| |
| if (psessionEntry->lim11hEnable && |
| (eSIR_INFRA_AP_MODE == pMlmStartReq->bssType)) { |
| if (wlan_cfgGetInt(pMac, WNI_CFG_DFS_MASTER_ENABLED, |
| &val) != eSIR_SUCCESS) |
| limLog(pMac, LOGE, |
| FL("Fail to get WNI_CFG_DFS_MASTER_ENABLED")); |
| psessionEntry->lim11hEnable = val; |
| } |
| } |
| } |
| |
| if (!psessionEntry->lim11hEnable) |
| { |
| if (cfgSetInt(pMac, WNI_CFG_LOCAL_POWER_CONSTRAINT, 0) != eSIR_SUCCESS) |
| limLog(pMac, LOGE, FL |
| ("Fail to set value for WNI_CFG_LOCAL_POWER_CONSTRAINT")); |
| } |
| |
| pMlmStartReq->beacon_tx_rate = psessionEntry->beacon_tx_rate; |
| |
| psessionEntry ->limPrevSmeState = psessionEntry->limSmeState; |
| psessionEntry ->limSmeState = eLIM_SME_WT_START_BSS_STATE; |
| MTRACE(macTrace(pMac, TRACE_CODE_SME_STATE, psessionEntry->peSessionId, psessionEntry ->limSmeState)); |
| |
| limPostMlmMessage(pMac, LIM_MLM_START_REQ, (tANI_U32 *) pMlmStartReq); |
| return; |
| } |
| else |
| { |
| |
| limLog(pMac, LOGE, FL("Received unexpected START_BSS_REQ, in state %X"),pMac->lim.gLimSmeState); |
| retCode = eSIR_SME_BSS_ALREADY_STARTED_OR_JOINED; |
| goto end; |
| } // if (pMac->lim.gLimSmeState == eLIM_SME_OFFLINE_STATE) |
| |
| free: |
| if ((psessionEntry != NULL) && |
| (psessionEntry->pLimStartBssReq == pSmeStartBssReq)) |
| { |
| psessionEntry->pLimStartBssReq = NULL; |
| } |
| vos_mem_free( pSmeStartBssReq); |
| vos_mem_free( pMlmStartReq); |
| |
| end: |
| |
| /* This routine should return the sme sessionId and SME transaction Id */ |
| limGetSessionInfo(pMac,(tANI_U8*)pMsgBuf,&smesessionId,&smetransactionId); |
| |
| if(NULL != psessionEntry) |
| { |
| peDeleteSession(pMac,psessionEntry); |
| psessionEntry = NULL; |
| } |
| limSendSmeStartBssRsp(pMac, eWNI_SME_START_BSS_RSP, retCode,psessionEntry,smesessionId,smetransactionId); |
| } /*** end __limHandleSmeStartBssRequest() ***/ |
| |
| |
| /**-------------------------------------------------------------- |
| \fn __limProcessSmeStartBssReq |
| |
| \brief Wrapper for the function __limHandleSmeStartBssRequest |
| This message will be defered until softmac come out of |
| scan mode or if we have detected radar on the current |
| operating channel. |
| \param pMac |
| \param pMsg |
| |
| \return TRUE - If we consumed the buffer |
| FALSE - If have defered the message. |
| ---------------------------------------------------------------*/ |
| static tANI_BOOLEAN |
| __limProcessSmeStartBssReq(tpAniSirGlobal pMac, tpSirMsgQ pMsg) |
| { |
| if (__limIsDeferedMsgForLearn(pMac, pMsg) || |
| __limIsDeferedMsgForRadar(pMac, pMsg)) |
| { |
| /** |
| * If message defered, buffer is not consumed yet. |
| * So return false |
| */ |
| return eANI_BOOLEAN_FALSE; |
| } |
| |
| __limHandleSmeStartBssRequest(pMac, (tANI_U32 *) pMsg->bodyptr); |
| return eANI_BOOLEAN_TRUE; |
| } |
| |
| |
| /** |
| * limGetRandomBssid() |
| * |
| * FUNCTION:This function is called to process generate the random number for bssid |
| * This function is called to process SME_SCAN_REQ message |
| * from HDD or upper layer application. |
| * |
| * LOGIC: |
| * |
| * ASSUMPTIONS: |
| * |
| * NOTE: |
| * 1. geneartes the unique random number for bssid in ibss |
| * |
| * @param pMac Pointer to Global MAC structure |
| * @param *data Pointer to bssid buffer |
| * @return None |
| */ |
| void limGetRandomBssid(tpAniSirGlobal pMac, tANI_U8 *data) |
| { |
| tANI_U32 random[2] ; |
| random[0] = tx_time_get(); |
| random[0] |= (random[0] << 15) ; |
| random[1] = random[0] >> 1; |
| vos_mem_copy( data, (tANI_U8*)random, sizeof(tSirMacAddr)); |
| } |
| |
| static eHalStatus limSendHalStartScanOffloadReq(tpAniSirGlobal pMac, |
| tpSirSmeScanReq pScanReq) |
| { |
| tSirScanOffloadReq *pScanOffloadReq; |
| tANI_U8 *p; |
| tANI_U8 *ht_cap_ie; |
| tSirMsgQ msg; |
| tANI_U16 i, len; |
| tANI_U16 ht_cap_len = 0, addn_ie_len = 0; |
| #ifdef WLAN_FEATURE_11AC |
| tANI_U8 *vht_cap_ie; |
| tANI_U16 vht_cap_len = 0; |
| #endif /* WLAN_FEATURE_11AC */ |
| uint8_t *vendor_tpc_ie; |
| tSirRetStatus status, rc = eSIR_SUCCESS; |
| tDot11fIEExtCap extracted_extcap = {0}; |
| bool extcap_present = true; |
| uint32_t lim_11h_enable = WNI_CFG_11H_ENABLED_STADEF; |
| |
| wlan_cfgGetInt(pMac, WNI_CFG_11H_ENABLED, &lim_11h_enable); |
| |
| |
| pMac->lim.fOffloadScanPending = 0; |
| pMac->lim.fOffloadScanP2PSearch = 0; |
| |
| if (pScanReq->uIEFieldLen) { |
| status = lim_strip_extcap_update_struct(pMac, |
| (uint8_t *) pScanReq + pScanReq->uIEFieldOffset, |
| &pScanReq->uIEFieldLen, &extracted_extcap); |
| |
| if (eSIR_SUCCESS != status) { |
| extcap_present = false; |
| limLog(pMac, LOG1, FL("Unable to Strip ExtCap IE from Scan Req")); |
| } |
| |
| if (extcap_present) { |
| limLog(pMac, LOG1, FL("Extcap was part of SCAN IE - Updating FW")); |
| lim_send_ext_cap_ie(pMac, pScanReq->sessionId, |
| &extracted_extcap, true); |
| } |
| } else { |
| limLog(pMac, LOG1, FL("No IEs in the scan request from supplicant")); |
| } |
| |
| /* The tSirScanOffloadReq will reserve the space for first channel, |
| so allocate the memory for (numChannels - 1) and uIEFieldLen */ |
| len = sizeof(tSirScanOffloadReq) + (pScanReq->channelList.numChannels - 1) + |
| pScanReq->uIEFieldLen + pScanReq->oui_field_len; |
| |
| if (!pMac->per_band_chainmask_supp) { |
| if (IS_DOT11_MODE_HT(pScanReq->dot11mode)) { |
| limLog(pMac, LOG1, |
| FL("Adding HT Caps IE since dot11mode=%d"), |
| pScanReq->dot11mode); |
| ht_cap_len = 2 + sizeof(tHtCaps); /* 2 bytes for EID and Length */ |
| len += ht_cap_len; |
| addn_ie_len += ht_cap_len; |
| } |
| |
| #ifdef WLAN_FEATURE_11AC |
| if (IS_DOT11_MODE_VHT(pScanReq->dot11mode)) { |
| limLog(pMac, LOG1, |
| FL("Adding VHT Caps IE since dot11mode=%d"), |
| pScanReq->dot11mode); |
| /* 2 bytes for EID and Length */ |
| vht_cap_len = 2 + sizeof(tSirMacVHTCapabilityInfo) + |
| sizeof(tSirVhtMcsInfo); |
| len += vht_cap_len; |
| addn_ie_len += vht_cap_len; |
| } |
| #endif /* WLAN_FEATURE_11AC */ |
| } |
| |
| if (lim_11h_enable) { |
| addn_ie_len += DOT11F_IE_WFATPC_MAX_LEN + 2; |
| len += DOT11F_IE_WFATPC_MAX_LEN + 2; |
| } |
| |
| pScanOffloadReq = vos_mem_malloc(len); |
| if ( NULL == pScanOffloadReq ) |
| { |
| limLog(pMac, LOGE, |
| FL("AllocateMemory failed for pScanOffloadReq")); |
| return eHAL_STATUS_FAILURE; |
| } |
| |
| vos_mem_set( (tANI_U8 *) pScanOffloadReq, len, 0); |
| |
| msg.type = WDA_START_SCAN_OFFLOAD_REQ; |
| msg.bodyptr = pScanOffloadReq; |
| msg.bodyval = 0; |
| |
| vos_mem_copy((tANI_U8 *) pScanOffloadReq->bssId, |
| (tANI_U8*) pScanReq->bssId, |
| sizeof(tSirMacAddr)); |
| |
| if (pScanReq->numSsid > SIR_SCAN_MAX_NUM_SSID) |
| { |
| limLog(pMac, LOGE, |
| FL("Invalid value (%d) for numSsid"), SIR_SCAN_MAX_NUM_SSID); |
| vos_mem_free (pScanOffloadReq); |
| return eHAL_STATUS_FAILURE; |
| } |
| |
| pScanOffloadReq->numSsid = pScanReq->numSsid; |
| for (i = 0; i < pScanOffloadReq->numSsid; i++) |
| { |
| pScanOffloadReq->ssId[i].length = pScanReq->ssId[i].length; |
| vos_mem_copy((tANI_U8 *) pScanOffloadReq->ssId[i].ssId, |
| (tANI_U8 *) pScanReq->ssId[i].ssId, |
| pScanOffloadReq->ssId[i].length); |
| } |
| |
| pScanOffloadReq->hiddenSsid = pScanReq->hiddenSsid; |
| vos_mem_copy((tANI_U8 *) pScanOffloadReq->selfMacAddr, |
| (tANI_U8 *) pScanReq->selfMacAddr, |
| sizeof(tSirMacAddr)); |
| pScanOffloadReq->bssType = pScanReq->bssType; |
| pScanOffloadReq->dot11mode = pScanReq->dot11mode; |
| pScanOffloadReq->scanType = pScanReq->scanType; |
| pScanOffloadReq->minChannelTime = pScanReq->minChannelTime; |
| pScanOffloadReq->maxChannelTime = pScanReq->maxChannelTime; |
| pScanOffloadReq->restTime= pScanReq->restTime; |
| pScanOffloadReq->min_rest_time= pScanReq->min_rest_time; |
| pScanOffloadReq->idle_time= pScanReq->idle_time; |
| |
| for (i = 0; i < pMac->lim.maxBssId; i++) { |
| tpPESession session_entry = peFindSessionBySessionId(pMac,i); |
| if (session_entry && |
| (eLIM_MLM_LINK_ESTABLISHED_STATE == session_entry->limMlmState) && |
| (session_entry->beaconParams.beaconInterval |
| < BEACON_INTERVAL_THRESHOLD)) { |
| pScanOffloadReq->burst_scan_duration = STA_BURST_SCAN_DURATION; |
| break; |
| } |
| } |
| /* for normal scan, the value for p2pScanType should be 0 |
| always */ |
| if (pScanReq->p2pSearch) |
| pScanOffloadReq->p2pScanType = P2P_SCAN_TYPE_SEARCH; |
| |
| pScanOffloadReq->sessionId = pScanReq->sessionId; |
| |
| if (pScanOffloadReq->sessionId >= pMac->lim.maxBssId) |
| limLog(pMac, LOGE, FL("Invalid pe sessionID : %d"), |
| pScanOffloadReq->sessionId); |
| |
| pScanOffloadReq->channelList.numChannels = |
| pScanReq->channelList.numChannels; |
| p = &(pScanOffloadReq->channelList.channelNumber[0]); |
| for (i = 0; i < pScanOffloadReq->channelList.numChannels; i++) |
| p[i] = pScanReq->channelList.channelNumber[i]; |
| |
| pScanOffloadReq->uIEFieldLen = pScanReq->uIEFieldLen; |
| pScanOffloadReq->uIEFieldOffset = len - addn_ie_len - |
| pScanOffloadReq->uIEFieldLen - |
| pScanReq->oui_field_len; |
| vos_mem_copy( |
| (tANI_U8 *) pScanOffloadReq + pScanOffloadReq->uIEFieldOffset, |
| (tANI_U8 *) pScanReq + pScanReq->uIEFieldOffset, |
| pScanReq->uIEFieldLen); |
| |
| if (!pMac->per_band_chainmask_supp) { |
| /* Copy HT Capability info if dot11mode is HT */ |
| if (IS_DOT11_MODE_HT(pScanReq->dot11mode)) { |
| /* Populate EID and Length field here */ |
| ht_cap_ie = (tANI_U8 *) pScanOffloadReq + |
| pScanOffloadReq->uIEFieldOffset + |
| pScanOffloadReq->uIEFieldLen; |
| vos_mem_set(ht_cap_ie, ht_cap_len, 0); |
| *ht_cap_ie = SIR_MAC_HT_CAPABILITIES_EID; |
| *(ht_cap_ie + 1) = ht_cap_len - 2; |
| lim_set_ht_caps(pMac, NULL, ht_cap_ie, ht_cap_len); |
| pScanOffloadReq->uIEFieldLen += ht_cap_len; |
| } |
| |
| #ifdef WLAN_FEATURE_11AC |
| /* Copy VHT Capability info if dot11mode is VHT Capable */ |
| if (IS_DOT11_MODE_VHT(pScanReq->dot11mode)) { |
| /* Populate EID and Length field here */ |
| vht_cap_ie = (tANI_U8 *) pScanOffloadReq + |
| pScanOffloadReq->uIEFieldOffset + |
| pScanOffloadReq->uIEFieldLen; |
| vos_mem_set(vht_cap_ie, vht_cap_len, 0); |
| *vht_cap_ie = SIR_MAC_VHT_CAPABILITIES_EID; |
| *(vht_cap_ie + 1) = vht_cap_len - 2; |
| lim_set_vht_caps(pMac, NULL, vht_cap_ie, vht_cap_len); |
| pScanOffloadReq->uIEFieldLen += vht_cap_len; |
| } |
| #endif /* WLAN_FEATURE_11AC */ |
| } |
| |
| if (lim_11h_enable) { |
| tDot11fIEWFATPC wfa_tpc; |
| vendor_tpc_ie = (uint8_t *) pScanOffloadReq + |
| pScanOffloadReq->uIEFieldOffset + |
| pScanOffloadReq->uIEFieldLen; |
| PopulateDot11fWFATPC(pMac, &wfa_tpc, |
| rrmGetMgmtTxPower(pMac, NULL), 0); |
| vendor_tpc_ie[0] = DOT11F_EID_WFATPC; |
| vendor_tpc_ie[1] = DOT11F_IE_WFATPC_MAX_LEN; |
| vos_mem_copy(&vendor_tpc_ie[2], SIR_MAC_WFA_TPC_OUI, |
| SIR_MAC_WFA_TPC_OUI_SIZE); |
| vos_mem_copy(&vendor_tpc_ie[SIR_MAC_WFA_TPC_OUI_SIZE + 2], |
| ((uint8_t *)&wfa_tpc) + 1, |
| DOT11F_IE_WFATPC_MAX_LEN |
| - SIR_MAC_WFA_TPC_OUI_SIZE); |
| pScanOffloadReq->uIEFieldLen += DOT11F_IE_WFATPC_MAX_LEN + 2; |
| } |
| |
| pScanOffloadReq->enable_scan_randomization = |
| pScanReq->enable_scan_randomization; |
| if (pScanOffloadReq->enable_scan_randomization) { |
| vos_mem_copy(pScanOffloadReq->mac_addr, pScanReq->mac_addr, |
| VOS_MAC_ADDR_SIZE); |
| vos_mem_copy(pScanOffloadReq->mac_addr_mask, pScanReq->mac_addr_mask, |
| VOS_MAC_ADDR_SIZE); |
| } |
| |
| pScanOffloadReq->oui_field_len = pScanReq->oui_field_len; |
| pScanOffloadReq->num_vendor_oui = pScanReq->num_vendor_oui; |
| pScanOffloadReq->ie_whitelist = pScanReq->ie_whitelist; |
| if (pScanOffloadReq->ie_whitelist) |
| vos_mem_copy(pScanOffloadReq->probe_req_ie_bitmap, |
| pScanReq->probe_req_ie_bitmap, |
| PROBE_REQ_BITMAP_LEN * sizeof(uint32_t)); |
| pScanOffloadReq->oui_field_offset = sizeof(tSirScanOffloadReq) + |
| (pScanOffloadReq->channelList.numChannels - 1) + |
| pScanOffloadReq->uIEFieldLen; |
| if (pScanOffloadReq->num_vendor_oui != 0) { |
| vos_mem_copy( |
| (tANI_U8 *) pScanOffloadReq + pScanOffloadReq->oui_field_offset, |
| (uint8_t *) pScanReq + pScanReq->oui_field_offset, |
| pScanReq->oui_field_len); |
| } |
| |
| rc = wdaPostCtrlMsg(pMac, &msg); |
| if (rc != eSIR_SUCCESS) |
| { |
| limLog(pMac, LOGE, FL("wdaPostCtrlMsg() return failure")); |
| vos_mem_free(pScanOffloadReq); |
| return eHAL_STATUS_FAILURE; |
| } |
| |
| pMac->lim.fOffloadScanPending = 1; |
| if (pScanReq->p2pSearch) |
| pMac->lim.fOffloadScanP2PSearch = 1; |
| return eHAL_STATUS_SUCCESS; |
| } |
| |
| /** |
| * __limProcessSmeScanReq() |
| * |
| *FUNCTION: |
| * This function is called to process SME_SCAN_REQ message |
| * from HDD or upper layer application. |
| * |
| *LOGIC: |
| * |
| *ASSUMPTIONS: |
| * |
| *NOTE: |
| * 1. Periodic scanning should be requesting to return unique |
| * scan results. |
| * |
| * @param pMac Pointer to Global MAC structure |
| * @param *pMsgBuf A pointer to the SME message buffer |
| * @return None |
| */ |
| |
| static void |
| __limProcessSmeScanReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) |
| { |
| tANI_U32 len; |
| tLimMlmScanReq *pMlmScanReq; |
| tpSirSmeScanReq pScanReq; |
| tANI_U8 i = 0; |
| |
| #ifdef FEATURE_WLAN_DIAG_SUPPORT |
| limDiagEventReport(pMac, WLAN_PE_DIAG_SCAN_REQ_EVENT, NULL, |
| eSIR_SUCCESS, eSIR_SUCCESS); |
| #endif |
| |
| pScanReq = (tpSirSmeScanReq) pMsgBuf; |
| limLog(pMac, LOG1,FL("SME SCAN REQ numChan %d min %d max %d IELen %d" |
| "first %d fresh %d unique %d type %s (%d)" |
| " mode %s (%d)rsp %d"), |
| pScanReq->channelList.numChannels, |
| pScanReq->minChannelTime, |
| pScanReq->maxChannelTime, |
| pScanReq->uIEFieldLen, |
| pScanReq->returnAfterFirstMatch, |
| pScanReq->returnFreshResults, |
| pScanReq->returnUniqueResults, |
| lim_ScanTypetoString(pScanReq->scanType), |
| pScanReq->scanType, |
| lim_BackgroundScanModetoString(pScanReq->backgroundScanMode), |
| pScanReq->backgroundScanMode, pMac->lim.gLimRspReqd ? 1 : 0); |
| |
| |
| /* Since scan req always requires a response, we will overwrite response required here. |
| * This is added esp to take care of the condition where in p2p go case, we hold the scan req and |
| * insert single NOA. We send the held scan request to FW later on getting start NOA ind from FW so |
| * we lose state of the gLimRspReqd flag for the scan req if any other request comes by then. |
| * e.g. While unit testing, we found when insert single NOA is done, we see a get stats request which turns the flag |
| * gLimRspReqd to FALSE; now when we actually start the saved scan req for init scan after getting |
| * NOA started, the gLimRspReqd being a global flag is showing FALSE instead of TRUE value for |
| * this saved scan req. Since all scan reqs coming to lim require a response, there is no harm in setting |
| * the global flag gLimRspReqd to TRUE here. |
| */ |
| pMac->lim.gLimRspReqd = TRUE; |
| |
| /*copy the Self MAC address from SmeReq to the globalplace, used for sending probe req*/ |
| sirCopyMacAddr(pMac->lim.gSelfMacAddr, pScanReq->selfMacAddr); |
| |
| /* This routine should return the sme sessionId and SME transaction Id */ |
| |
| if (!limIsSmeScanReqValid(pMac, pScanReq)) |
| { |
| limLog(pMac, LOGE, FL("Received SME_SCAN_REQ with invalid parameters")); |
| |
| if (pMac->lim.gLimRspReqd) |
| { |
| pMac->lim.gLimRspReqd = false; |
| |
| limSendSmeScanRsp(pMac, sizeof(tSirSmeScanRsp), eSIR_SME_INVALID_PARAMETERS, pScanReq->sessionId, pScanReq->transactionId); |
| |
| } // if (pMac->lim.gLimRspReqd) |
| |
| return; |
| } |
| |
| /* |
| * if scan is disabled then return as invalid scan request. |
| * if scan in power save is disabled, and system is in power save mode, |
| * then ignore scan request. |
| */ |
| if((pMac->lim.fScanDisabled) || |
| (!pMac->psOffloadEnabled && |
| !pMac->lim.gScanInPowersave && |
| !limIsSystemInActiveState(pMac))) |
| { |
| limLog(pMac, LOGE, FL("SCAN is disabled or SCAN in power save" |
| " is disabled and system is in power save.")); |
| |
| limSendSmeScanRsp(pMac, offsetof(tSirSmeScanRsp,bssDescription[0]), eSIR_SME_INVALID_PARAMETERS, pScanReq->sessionId, pScanReq->transactionId); |
| return; |
| } |
| |
| /* Clear P2P scan entries before starting any scan */ |
| if (pMac->fScanOffload) |
| limFlushp2pScanResults(pMac); |
| |
| /** |
| * If scan request is received in idle, joinFailed |
| * states or in link established state (in STA role) |
| * or in normal state (in STA-in-IBSS/AP role) with |
| * 'return fresh scan results' request from HDD or |
| * it is periodic background scanning request, |
| * trigger fresh scan request to MLM |
| */ |
| if (__limFreshScanReqd(pMac, pScanReq->returnFreshResults)) |
| { |
| limLog(pMac, LOG1, FL("Fresh scan is required")); |
| |
| if (pScanReq->returnFreshResults & SIR_BG_SCAN_PURGE_RESUTLS) |
| { |
| // Discard previously cached scan results |
| limReInitScanResults(pMac); |
| } |
| |
| pMac->lim.gLim24Band11dScanDone = 0; |
| pMac->lim.gLim50Band11dScanDone = 0; |
| pMac->lim.gLimReturnAfterFirstMatch = |
| pScanReq->returnAfterFirstMatch; |
| pMac->lim.gLimBackgroundScanMode = |
| pScanReq->backgroundScanMode; |
| |
| pMac->lim.gLimReturnUniqueResults = |
| ((pScanReq->returnUniqueResults) > 0 ? true : false); |
| |
| if (pMac->psOffloadEnabled) |
| { |
| if ((pMac->lim.gLimBackgroundScanMode != eSIR_ROAMING_SCAN) && |
| (!IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE)) |
| { |
| for (i=0;i<pMac->lim.maxBssId;i++) |
| { |
| tpPESession psessionEntry = peFindSessionBySessionId(pMac,i); |
| if (psessionEntry && psessionEntry->valid && |
| (eLIM_MLM_LINK_ESTABLISHED_STATE == |
| psessionEntry->limMlmState) && |
| (psessionEntry->pmmOffloadInfo.psstate == PMM_FULL_POWER)) |
| { |
| limHeartBeatDeactivateAndChangeTimer(pMac, psessionEntry); |
| } |
| } |
| } |
| } |
| /* De-activate Heartbeat timers for connected sessions while |
| * scan is in progress if the system is in Active mode * |
| * AND it is not a ROAMING ("background") scan */ |
| else if (((ePMM_STATE_BMPS_WAKEUP == pMac->pmm.gPmmState) || |
| (ePMM_STATE_READY == pMac->pmm.gPmmState)) && |
| (pScanReq->backgroundScanMode != eSIR_ROAMING_SCAN ) && |
| (!IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE)) |
| { |
| for(i=0;i<pMac->lim.maxBssId;i++) |
| { |
| if((peFindSessionBySessionId(pMac,i) != NULL) && |
| (pMac->lim.gpSession[i].valid == TRUE) && |
| (eLIM_MLM_LINK_ESTABLISHED_STATE == pMac->lim.gpSession[i].limMlmState)) |
| { |
| limHeartBeatDeactivateAndChangeTimer(pMac, peFindSessionBySessionId(pMac,i)); |
| } |
| } |
| } |
| |
| if (pMac->fScanOffload) |
| { |
| if (eHAL_STATUS_SUCCESS != |
| limSendHalStartScanOffloadReq(pMac, pScanReq)) |
| { |
| limLog(pMac, LOGE, FL("Couldn't send Offload scan request")); |
| limSendSmeScanRsp(pMac, |
| offsetof(tSirSmeScanRsp, bssDescription[0]), |
| eSIR_SME_INVALID_PARAMETERS, |
| pScanReq->sessionId, |
| pScanReq->transactionId); |
| return; |
| } |
| } |
| else |
| { |
| |
| /*Change Global SME state */ |
| /* Store the previous SME state */ |
| limLog(pMac, LOG1, FL("Non Offload SCAN request ")); |
| pMac->lim.gLimPrevSmeState = pMac->lim.gLimSmeState; |
| pMac->lim.gLimSmeState = eLIM_SME_WT_SCAN_STATE; |
| MTRACE(macTrace(pMac, TRACE_CODE_SME_STATE, pScanReq->sessionId, pMac->lim.gLimSmeState)); |
| |
| if (pScanReq->channelList.numChannels == 0) |
| { |
| tANI_U32 cfg_len; |
| |
| limLog(pMac, LOG1, |
| FL("Scan all channels as Number of channels is 0")); |
| |
| // Scan all channels |
| len = sizeof(tLimMlmScanReq) + |
| (sizeof( pScanReq->channelList.channelNumber ) * (WNI_CFG_VALID_CHANNEL_LIST_LEN - 1)) + |
| pScanReq->uIEFieldLen; |
| pMlmScanReq = vos_mem_malloc(len); |
| if ( NULL == pMlmScanReq ) |
| { |
| // Log error |
| limLog(pMac, LOGP, |
| FL("call to AllocateMemory failed for mlmScanReq (%d)"), len); |
| |
| return; |
| } |
| |
| // Initialize this buffer |
| vos_mem_set( (tANI_U8 *) pMlmScanReq, len, 0 ); |
| |
| cfg_len = WNI_CFG_VALID_CHANNEL_LIST_LEN; |
| if (wlan_cfgGetStr(pMac, WNI_CFG_VALID_CHANNEL_LIST, |
| pMlmScanReq->channelList.channelNumber, |
| &cfg_len) != eSIR_SUCCESS) |
| { |
| /** |
| * Could not get Valid channel list from CFG. |
| * Log error. |
| */ |
| limLog(pMac, LOGP, |
| FL("could not retrieve Valid channel list")); |
| } |
| pMlmScanReq->channelList.numChannels = (tANI_U8) cfg_len; |
| } |
| else |
| { |
| len = sizeof( tLimMlmScanReq ) - sizeof( pScanReq->channelList.channelNumber ) + |
| (sizeof( pScanReq->channelList.channelNumber ) * pScanReq->channelList.numChannels ) + |
| pScanReq->uIEFieldLen; |
| |
| pMlmScanReq = vos_mem_malloc(len); |
| if ( NULL == pMlmScanReq ) |
| { |
| // Log error |
| limLog(pMac, LOGP, |
| FL("call to AllocateMemory failed for mlmScanReq(%d)"), len); |
| |
| return; |
| } |
| |
| // Initialize this buffer |
| vos_mem_set( (tANI_U8 *) pMlmScanReq, len, 0); |
| if (pScanReq->channelList.numChannels <= SIR_ESE_MAX_MEAS_IE_REQS) |
| { |
| pMlmScanReq->channelList.numChannels = |
| pScanReq->channelList.numChannels; |
| } |
| else |
| { |
| limLog(pMac, LOGE, |
| FL("numChannels is more than the size(%d)"), |
| pScanReq->channelList.numChannels); |
| pMlmScanReq->channelList.numChannels = |
| SIR_ESE_MAX_MEAS_IE_REQS; |
| } |
| |
| vos_mem_copy( pMlmScanReq->channelList.channelNumber, |
| pScanReq->channelList.channelNumber, |
| pMlmScanReq->channelList.numChannels); |
| } |
| |
| pMlmScanReq->uIEFieldLen = pScanReq->uIEFieldLen; |
| pMlmScanReq->uIEFieldOffset = len - pScanReq->uIEFieldLen; |
| if(pScanReq->uIEFieldLen) |
| { |
| vos_mem_copy( (tANI_U8 *)pMlmScanReq+ pMlmScanReq->uIEFieldOffset, |
| (tANI_U8 *)pScanReq+(pScanReq->uIEFieldOffset), |
| pScanReq->uIEFieldLen); |
| } |
| |
| pMlmScanReq->bssType = pScanReq->bssType; |
| vos_mem_copy( pMlmScanReq->bssId, |
| pScanReq->bssId, |
| sizeof(tSirMacAddr)); |
| pMlmScanReq->numSsid = pScanReq->numSsid; |
| pMlmScanReq->sessionId = pScanReq->sessionId; |
| |
| i = 0; |
| while (i < pMlmScanReq->numSsid) |
| { |
| vos_mem_copy( (tANI_U8 *) &pMlmScanReq->ssId[i], |
| (tANI_U8 *) &pScanReq->ssId[i], |
| pScanReq->ssId[i].length + 1); |
| |
| i++; |
| } |
| |
| |
| pMlmScanReq->scanType = pScanReq->scanType; |
| pMlmScanReq->backgroundScanMode = pScanReq->backgroundScanMode; |
| pMlmScanReq->minChannelTime = pScanReq->minChannelTime; |
| pMlmScanReq->maxChannelTime = pScanReq->maxChannelTime; |
| pMlmScanReq->minChannelTimeBtc = pScanReq->minChannelTimeBtc; |
| pMlmScanReq->maxChannelTimeBtc = pScanReq->maxChannelTimeBtc; |
| pMlmScanReq->dot11mode = pScanReq->dot11mode; |
| pMlmScanReq->p2pSearch = pScanReq->p2pSearch; |
| |
| //Store the smeSessionID and transaction ID for later use. |
| pMac->lim.gSmeSessionId = pScanReq->sessionId; |
| pMac->lim.gTransactionId = pScanReq->transactionId; |
| |
| // Issue LIM_MLM_SCAN_REQ to MLM |
| limLog(pMac, LOG1, FL("Issue Scan request command to MLM ")); |
| limPostMlmMessage(pMac, LIM_MLM_SCAN_REQ, (tANI_U32 *) pMlmScanReq); |
| } |
| } // if ((pMac->lim.gLimSmeState == eLIM_SME_IDLE_STATE) || ... |
| |
| else |
| { |
| /// In all other cases return 'cached' scan results |
| if ((pMac->lim.gLimRspReqd) || pMac->lim.gLimReportBackgroundScanResults) |
| { |
| tANI_U16 scanRspLen = sizeof(tSirSmeScanRsp); |
| |
| pMac->lim.gLimRspReqd = false; |
| #ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD |
| if (pScanReq->returnFreshResults & SIR_BG_SCAN_RETURN_LFR_CACHED_RESULTS) |
| { |
| pMac->lim.gLimSmeLfrScanResultLength = pMac->lim.gLimMlmLfrScanResultLength; |
| limLog(pMac, LOG1, |
| FL("Returned scan results from LFR cache, length = %d"), |
| pMac->lim.gLimSmeLfrScanResultLength); |
| |
| if (pMac->lim.gLimSmeLfrScanResultLength == 0) |
| { |
| limSendSmeLfrScanRsp(pMac, scanRspLen, |
| eSIR_SME_SUCCESS, |
| pScanReq->sessionId, |
| pScanReq->transactionId); |
| } |
| else |
| { |
| scanRspLen = sizeof(tSirSmeScanRsp) + |
| pMac->lim.gLimSmeLfrScanResultLength - |
| sizeof(tSirBssDescription); |
| limSendSmeLfrScanRsp(pMac, scanRspLen, eSIR_SME_SUCCESS, |
| pScanReq->sessionId, pScanReq->transactionId); |
| } |
| } |
| else |
| { |
| #endif |
| limLog(pMac, LOG1, |
| FL("Returned scan results from normal cache, length = %d"), |
| pMac->lim.gLimSmeScanResultLength); |
| if (pMac->lim.gLimSmeScanResultLength == 0) |
| { |
| limSendSmeScanRsp(pMac, scanRspLen, eSIR_SME_SUCCESS, |
| pScanReq->sessionId, pScanReq->transactionId); |
| } |
| else |
| { |
| scanRspLen = sizeof(tSirSmeScanRsp) + |
| pMac->lim.gLimSmeScanResultLength - |
| sizeof(tSirBssDescription); |
| limSendSmeScanRsp(pMac, scanRspLen, eSIR_SME_SUCCESS, |
| pScanReq->sessionId, pScanReq->transactionId); |
| } |
| #ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD |
| } |
| #endif |
| limLog(pMac, LOG1, FL("Cached scan results are returned ")); |
| |
| if (pScanReq->returnFreshResults & SIR_BG_SCAN_PURGE_RESUTLS) |
| { |
| // Discard previously cached scan results |
| limReInitScanResults(pMac); |
| } |
| #ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD |
| if (pScanReq->returnFreshResults & SIR_BG_SCAN_PURGE_LFR_RESULTS) |
| { |
| // Discard previously cached scan results |
| limReInitLfrScanResults(pMac); |
| } |
| #endif |
| |
| } // if (pMac->lim.gLimRspReqd) |
| } // else ((pMac->lim.gLimSmeState == eLIM_SME_IDLE_STATE) || ... |
| |
| #ifdef BACKGROUND_SCAN_ENABLED |
| // start background scans if needed |
| // There is a bug opened against softmac. Need to enable when the bug is fixed. |
| __limBackgroundScanInitiate(pMac); |
| #endif |
| |
| } /*** end __limProcessSmeScanReq() ***/ |
| |
| #ifdef FEATURE_OEM_DATA_SUPPORT |
| |
| static void __limProcessSmeOemDataReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) |
| { |
| tpSirOemDataReq pOemDataReq; |
| tLimMlmOemDataReq* pMlmOemDataReq; |
| |
| pOemDataReq = (tpSirOemDataReq) pMsgBuf; |
| |
| //post the lim mlm message now |
| pMlmOemDataReq = vos_mem_malloc(sizeof(*pMlmOemDataReq)); |
| if ( NULL == pMlmOemDataReq ) |
| { |
| limLog(pMac, LOGP, FL("AllocateMemory failed for mlmOemDataReq")); |
| return; |
| } |
| |
| pMlmOemDataReq->data = vos_mem_malloc(pOemDataReq->data_len); |
| if (!pMlmOemDataReq->data) { |
| limLog(pMac, LOGP, FL("memory allocation failed")); |
| vos_mem_free(pMlmOemDataReq); |
| /* buffer from SME copied, free it now */ |
| vos_mem_free(pOemDataReq->data); |
| return; |
| } |
| |
| vos_mem_copy( pMlmOemDataReq->selfMacAddr, pOemDataReq->selfMacAddr, |
| sizeof(tSirMacAddr)); |
| |
| pMlmOemDataReq->data_len = pOemDataReq->data_len; |
| vos_mem_copy(pMlmOemDataReq->data, pOemDataReq->data, |
| pOemDataReq->data_len); |
| /* buffer from SME copied, free it now */ |
| vos_mem_free(pOemDataReq->data); |
| |
| //Issue LIM_MLM_OEM_DATA_REQ to MLM |
| limPostMlmMessage(pMac, LIM_MLM_OEM_DATA_REQ, (tANI_U32*)pMlmOemDataReq); |
| |
| return; |
| |
| } /*** end __limProcessSmeOemDataReq() ***/ |
| |
| #endif //FEATURE_OEM_DATA_SUPPORT |
| |
| /** |
| * __limProcessClearDfsChannelList() |
| * |
| *FUNCTION: |
| *Clear DFS channel list when country is changed/aquired. |
| .*This message is sent from SME. |
| * |
| *LOGIC: |
| * |
| *ASSUMPTIONS: |
| * |
| *NOTE: |
| * |
| * @param pMac Pointer to Global MAC structure |
| * @param *pMsgBuf A pointer to the SME message buffer |
| * @return None |
| */ |
| static void __limProcessClearDfsChannelList(tpAniSirGlobal pMac, |
| tpSirMsgQ pMsg) |
| { |
| vos_mem_set( &pMac->lim.dfschannelList, |
| sizeof(tSirDFSChannelList), 0); |
| } |
| |
| /** |
| * __limProcessSmeJoinReq() |
| * |
| *FUNCTION: |
| * This function is called to process SME_JOIN_REQ message |
| * from HDD or upper layer application. |
| * |
| *LOGIC: |
| * |
| *ASSUMPTIONS: |
| * |
| *NOTE: |
| * |
| * @param pMac Pointer to Global MAC structure |
| * @param *pMsgBuf A pointer to the SME message buffer |
| * @return None |
| */ |
| static void |
| __limProcessSmeJoinReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) |
| { |
| // tANI_U8 *pBuf; |
| //tANI_U32 len; |
| // tSirMacAddr currentBssId; |
| tpSirSmeJoinReq pSmeJoinReq = NULL; |
| tLimMlmJoinReq *pMlmJoinReq; |
| tSirResultCodes retCode = eSIR_SME_SUCCESS; |
| tANI_U32 val = 0; |
| tANI_U16 nSize; |
| tANI_U8 sessionId; |
| tpPESession psessionEntry = NULL; |
| tANI_U8 smesessionId = 0; |
| tANI_U16 smetransactionId = 0; |
| tPowerdBm localPowerConstraint = 0, regMax = 0; |
| tANI_U16 ieLen; |
| v_U8_t *vendorIE; |
| struct vdev_type_nss *vdev_type_nss; |
| |
| #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM //FEATURE_WLAN_DIAG_SUPPORT |
| //Not sending any session, since it is not created yet. The response whould have correct state. |
| limDiagEventReport(pMac, WLAN_PE_DIAG_JOIN_REQ_EVENT, NULL, 0, 0); |
| #endif //FEATURE_WLAN_DIAG_SUPPORT |
| |
| /** |
| * Expect Join request in idle state. |
| * Reassociate request is expected in link established state. |
| */ |
| |
| /* Global SME and LIM states are not defined yet for BT-AMP Support */ |
| if(pMac->lim.gLimSmeState == eLIM_SME_IDLE_STATE) |
| { |
| nSize = __limGetSmeJoinReqSizeForAlloc((tANI_U8*) pMsgBuf); |
| |
| pSmeJoinReq = vos_mem_malloc(nSize); |
| if ( NULL == pSmeJoinReq ) |
| { |
| limLog(pMac, LOGP, FL("call to AllocateMemory failed for " |
| "pSmeJoinReq")); |
| retCode = eSIR_SME_RESOURCES_UNAVAILABLE; |
| goto end; |
| } |
| (void) vos_mem_set((void *) pSmeJoinReq, nSize, 0); |
| |
| if ((limJoinReqSerDes(pMac, pSmeJoinReq, (tANI_U8 *)pMsgBuf) == eSIR_FAILURE) || |
| (!limIsSmeJoinReqValid(pMac, pSmeJoinReq))) |
| { |
| /// Received invalid eWNI_SME_JOIN_REQ |
| // Log the event |
| limLog(pMac, LOGW, FL("SessionId:%d Received SME_JOIN_REQ with invalid data"), |
| pSmeJoinReq->sessionId); |
| retCode = eSIR_SME_INVALID_PARAMETERS; |
| goto end; |
| } |
| |
| /* |
| * Update the capability here itself as this is used in |
| * limExtractAPCapability() below. If not updated issues like not |
| * honoring power constraint on 1st association after driver loading |
| * might occur. |
| */ |
| lim_update_rrm_capability(pMac, pSmeJoinReq); |
| |
| if (pe_find_session_by_sme_session_id(pMac, pSmeJoinReq->sessionId)) { |
| limLog(pMac, LOGE, |
| FL("A session already exist for the SME session %d"), |
| pSmeJoinReq->sessionId); |
| vos_flush_logs(WLAN_LOG_TYPE_FATAL, |
| WLAN_LOG_INDICATOR_HOST_DRIVER, |
| WLAN_LOG_REASON_STALE_SESSION_FOUND, |
| DUMP_VOS_TRACE); |
| retCode = eSIR_SME_REFUSED; |
| goto end; |
| } |
| |
| /* check for the existence of start BSS session */ |
| if((psessionEntry = peFindSessionByBssid(pMac,pSmeJoinReq->bssDescription.bssId,&sessionId)) != NULL) |
| { |
| limLog(pMac, LOGE, FL("Session(%d) Already exists for BSSID: " |
| MAC_ADDRESS_STR" in limSmeState = %X"),sessionId, |
| MAC_ADDR_ARRAY(pSmeJoinReq->bssDescription.bssId), |
| psessionEntry->limSmeState); |
| |
| if(psessionEntry->limSmeState == eLIM_SME_LINK_EST_STATE && |
| psessionEntry->smeSessionId == pSmeJoinReq->sessionId) |
| { |
| // Received eWNI_SME_JOIN_REQ for same |
| // BSS as currently associated. |
| // Log the event and send success |
| PELOGW(limLog(pMac, LOGW, FL("SessionId:%d Received SME_JOIN_REQ for currently joined BSS"), |
| sessionId);) |
| /// Send Join success response to host |
| retCode = eSIR_SME_ALREADY_JOINED_A_BSS; |
| psessionEntry = NULL; |
| goto end; |
| } |
| else |
| { |
| PELOGE(limLog(pMac, LOGE, FL("SME_JOIN_REQ not for" |
| "currently joined BSS"));) |
| retCode = eSIR_SME_REFUSED; |
| psessionEntry = NULL; |
| goto end; |
| } |
| } |
| else /* Session Entry does not exist for given BSSId */ |
| { |
| /* Try to Create a new session */ |
| if((psessionEntry = peCreateSession(pMac, |
| pSmeJoinReq->bssDescription.bssId, |
| &sessionId, |
| pMac->lim.maxStation, |
| eSIR_INFRASTRUCTURE_MODE )) == NULL) |
| { |
| limLog(pMac, LOGE, FL("Session Can not be created ")); |
| retCode = eSIR_SME_RESOURCES_UNAVAILABLE; |
| goto end; |
| } |
| else |
| limLog(pMac,LOG2,FL("SessionId:%d New session created"), |
| sessionId); |
| } |
| psessionEntry->max_amsdu_num = pSmeJoinReq->max_amsdu_num; |
| |
| /* Store Session related parameters */ |
| /* Store PE session Id in session Table */ |
| psessionEntry->peSessionId = sessionId; |
| |
| /* store the smejoin req handle in session table */ |
| psessionEntry->pLimJoinReq = pSmeJoinReq; |
| |
| /* Store SME session Id in sessionTable */ |
| psessionEntry->smeSessionId = pSmeJoinReq->sessionId; |
| |
| /* Store SME transaction Id in session Table */ |
| psessionEntry->transactionId = pSmeJoinReq->transactionId; |
| |
| /* Store beaconInterval */ |
| psessionEntry->beaconParams.beaconInterval = pSmeJoinReq->bssDescription.beaconInterval; |
| |
| vos_mem_copy(&(psessionEntry->htConfig), &(pSmeJoinReq->htConfig), |
| sizeof(psessionEntry->htConfig)); |
| |
| /* Copying of bssId is already done, while creating session */ |
| sirCopyMacAddr(psessionEntry->selfMacAddr,pSmeJoinReq->selfMacAddr); |
| psessionEntry->bssType = pSmeJoinReq->bsstype; |
| |
| psessionEntry->statypeForBss = STA_ENTRY_PEER; |
| psessionEntry->limWmeEnabled = pSmeJoinReq->isWMEenabled; |
| psessionEntry->limQosEnabled = pSmeJoinReq->isQosEnabled; |
| psessionEntry->osen_association = pSmeJoinReq->osen_association; |
| psessionEntry->wps_registration = pSmeJoinReq->wps_registration; |
| |
| |
| /* Store vendor specfic IE for CISCO AP */ |
| ieLen = GET_IE_LEN_IN_BSS(pSmeJoinReq->bssDescription.length); |
| |
| vendorIE = cfg_get_vendor_ie_ptr_from_oui(pMac, SIR_MAC_CISCO_OUI, |
| SIR_MAC_CISCO_OUI_SIZE, |
| ((tANI_U8 *)&pSmeJoinReq->bssDescription.ieFields) , ieLen); |
| |
| if (NULL != vendorIE) { |
| limLog(pMac, LOG1, FL("Cisco vendor OUI present")); |
| psessionEntry->isCiscoVendorAP = TRUE; |
| } else { |
| psessionEntry->isCiscoVendorAP = FALSE; |
| } |
| |
| /* Copy the dot 11 mode in to the session table */ |
| |
| psessionEntry->dot11mode = pSmeJoinReq->dot11mode; |
| #ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH |
| psessionEntry->cc_switch_mode = pSmeJoinReq->cc_switch_mode; |
| #endif |
| psessionEntry->nwType = pSmeJoinReq->bssDescription.nwType; |
| psessionEntry->enableAmpduPs = pSmeJoinReq->enableAmpduPs; |
| psessionEntry->enableHtSmps = pSmeJoinReq->enableHtSmps; |
| psessionEntry->htSmpsvalue = pSmeJoinReq->htSmps; |
| /* |
| * By default supported NSS 1x1 is set to true |
| * and later on updated while determining session |
| * supported rates which is the intersection of |
| * self and peer rates |
| */ |
| psessionEntry->supported_nss_1x1 = true; |
| |
| /*Store Persona */ |
| psessionEntry->pePersona = pSmeJoinReq->staPersona; |
| /* Copy The channel Id to the session Table */ |
| psessionEntry->currentOperChannel = |
| pSmeJoinReq->bssDescription.channelId; |
| if (IS_5G_CH(psessionEntry->currentOperChannel)) |
| vdev_type_nss = &pMac->vdev_type_nss_5g; |
| else |
| vdev_type_nss = &pMac->vdev_type_nss_2g; |
| if (psessionEntry->pePersona == VOS_P2P_CLIENT_MODE) |
| psessionEntry->vdev_nss = vdev_type_nss->p2p_cli; |
| else |
| psessionEntry->vdev_nss = vdev_type_nss->sta; |
| |
| limLog(pMac, LOG1, |
| FL("persona: %d, nss: %d cbMode: %d enableHtSmps: %d htSmps: %d supported NSS 1x1: %d force_24ghz_in_ht20 %d"), |
| psessionEntry->pePersona, |
| psessionEntry->vdev_nss, |
| pSmeJoinReq->cbMode, |
| psessionEntry->enableHtSmps, |
| psessionEntry->htSmpsvalue, |
| psessionEntry->supported_nss_1x1, |
| pSmeJoinReq->force_24ghz_in_ht20); |
| |
| #ifdef WLAN_FEATURE_11AC |
| psessionEntry->vhtCapability = IS_DOT11_MODE_VHT(psessionEntry->dot11mode); |
| if (psessionEntry->vhtCapability ) |
| { |
| if (psessionEntry->pePersona == VOS_STA_MODE) |
| { |
| psessionEntry->txBFIniFeatureEnabled = pSmeJoinReq->txBFIniFeatureEnabled; |
| } |
| else |
| { |
| psessionEntry->txBFIniFeatureEnabled = 0; |
| } |
| psessionEntry->txMuBformee = pSmeJoinReq->txMuBformee; |
| psessionEntry->enableVhtpAid = pSmeJoinReq->enableVhtpAid; |
| psessionEntry->enableVhtGid = pSmeJoinReq->enableVhtGid; |
| if (cfgSetInt(pMac, WNI_CFG_VHT_SU_BEAMFORMEE_CAP, |
| psessionEntry->txBFIniFeatureEnabled)) { |
| limLog(pMac, LOGE, FL("Could not set WNI_CFG_VHT_SU_BEAMFORMEE_CAP at CFG")); |
| retCode = eSIR_LOGP_EXCEPTION; |
| goto end; |
| } |
| |
| if (psessionEntry->txBFIniFeatureEnabled) { |
| if (cfgSetInt(pMac, WNI_CFG_VHT_CSN_BEAMFORMEE_ANT_SUPPORTED, |
| pSmeJoinReq->txBFCsnValue) |
| != eSIR_SUCCESS) |
| { |
| limLog(pMac, LOGE, FL("could not set " |
| "WNI_CFG_VHT_CSN_BEAMFORMEE_ANT_SUPPORTED at CFG")); |
| retCode = eSIR_LOGP_EXCEPTION; |
| goto end; |
| } |
| } |
| } |
| limLog(pMac, LOG1, |
| FL("vhtCapability: %d txBFIniFeatureEnabled: %d txBFCsnValue: %d txMuBformee: %d"), |
| psessionEntry->vhtCapability, |
| psessionEntry->txBFIniFeatureEnabled, |
| pSmeJoinReq->txBFCsnValue, |
| psessionEntry->txMuBformee); |
| #endif |
| |
| /*Phy mode*/ |
| psessionEntry->gLimPhyMode = pSmeJoinReq->bssDescription.nwType; |
| handleHTCapabilityandHTInfo(pMac, psessionEntry); |
| psessionEntry->htSupportedChannelWidthSet = (pSmeJoinReq->cbMode > 0)?1:0; // This is already merged value of peer and self - done by csr in csrGetCBModeFromIes |
| psessionEntry->force_24ghz_in_ht20 = pSmeJoinReq->force_24ghz_in_ht20; |
| psessionEntry->htRecommendedTxWidthSet = psessionEntry->htSupportedChannelWidthSet; |
| psessionEntry->htSecondaryChannelOffset = pSmeJoinReq->cbMode; |
| |
| /* Record if management frames need to be protected */ |
| #ifdef WLAN_FEATURE_11W |
| if(eSIR_ED_AES_128_CMAC == pSmeJoinReq->MgmtEncryptionType) |
| { |
| VOS_STATUS vosStatus; |
| psessionEntry->limRmfEnabled = 1; |
| /* |
| * For STA profile only: |
| * init pmf comeback timer and info struct only if PMF connection |
| */ |
| psessionEntry->pmfComebackTimerInfo.pMac = pMac; |
| psessionEntry->pmfComebackTimerInfo.sessionID = sessionId; |
| vosStatus = vos_timer_init(&psessionEntry->pmfComebackTimer, |
| VOS_TIMER_TYPE_SW, |
| limPmfComebackTimerCallback, |
| (void*)&psessionEntry->pmfComebackTimerInfo); |
| if (VOS_STATUS_SUCCESS != vosStatus) { |
| limLog(pMac, LOGP, |
| FL("cannot init pmf comeback timer.")); |
| retCode = eSIR_LOGP_EXCEPTION; |
| goto end; |
| } |
| } |
| else |
| { |
| psessionEntry->limRmfEnabled = 0; |
| } |
| #endif |
| |
| #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM |
| psessionEntry->rssi = pSmeJoinReq->bssDescription.rssi; |
| #endif |
| |
| |
| /* Copy the SSID from smejoinreq to session entry */ |
| psessionEntry->ssId.length = pSmeJoinReq->ssId.length; |
| vos_mem_copy( psessionEntry->ssId.ssId, |
| pSmeJoinReq->ssId.ssId, psessionEntry->ssId.length); |
| |
| // Determin 11r or ESE connection based on input from SME |
| // which inturn is dependent on the profile the user wants to connect |
| // to, So input is coming from supplicant |
| #ifdef WLAN_FEATURE_VOWIFI_11R |
| psessionEntry->is11Rconnection = pSmeJoinReq->is11Rconnection; |
| #endif |
| #ifdef FEATURE_WLAN_ESE |
| psessionEntry->isESEconnection = pSmeJoinReq->isESEconnection; |
| #endif |
| #if defined WLAN_FEATURE_VOWIFI_11R || defined FEATURE_WLAN_ESE || defined(FEATURE_WLAN_LFR) |
| psessionEntry->isFastTransitionEnabled = pSmeJoinReq->isFastTransitionEnabled; |
| #endif |
| |
| #ifdef FEATURE_WLAN_LFR |
| psessionEntry->isFastRoamIniFeatureEnabled = pSmeJoinReq->isFastRoamIniFeatureEnabled; |
| #endif |
| psessionEntry->txLdpcIniFeatureEnabled = pSmeJoinReq->txLdpcIniFeatureEnabled; |
| lim_update_fils_config(psessionEntry, pSmeJoinReq); |
| if (psessionEntry->bssType == eSIR_INFRASTRUCTURE_MODE) |
| { |
| psessionEntry->limSystemRole = eLIM_STA_ROLE; |
| } |
| else if (psessionEntry->bssType == eSIR_BTAMP_AP_MODE) |
| { |
| psessionEntry->limSystemRole = eLIM_BT_AMP_STA_ROLE; |
| } |
| else |
| { |
| /* Throw an error and return and make sure to delete the session.*/ |
| limLog(pMac, LOGE, FL("received SME_JOIN_REQ with invalid" |
| " bss type %d"), psessionEntry->bssType); |
| retCode = eSIR_SME_INVALID_PARAMETERS; |
| goto end; |
| } |
| |
| if (pSmeJoinReq->addIEScan.length) |
| { |
| vos_mem_copy( &psessionEntry->pLimJoinReq->addIEScan, |
| &pSmeJoinReq->addIEScan, sizeof(tSirAddie)); |
| } |
| |
| if (pSmeJoinReq->addIEAssoc.length) |
| { |
| vos_mem_copy( &psessionEntry->pLimJoinReq->addIEAssoc, |
| &pSmeJoinReq->addIEAssoc, sizeof(tSirAddie)); |
| } |
| |
| val = sizeof(tLimMlmJoinReq) + psessionEntry->pLimJoinReq->bssDescription.length + 2; |
| pMlmJoinReq = vos_mem_malloc(val); |
| if ( NULL == pMlmJoinReq ) |
| { |
| limLog(pMac, LOGP, FL("call to AllocateMemory " |
| "failed for mlmJoinReq")); |
| retCode = eSIR_SME_RESOURCES_UNAVAILABLE; |
| goto end; |
| } |
| (void) vos_mem_set((void *) pMlmJoinReq, val, 0); |
| |
| /* PE SessionId is stored as a part of JoinReq*/ |
| pMlmJoinReq->sessionId = psessionEntry->peSessionId; |
| |
| if (wlan_cfgGetInt(pMac, WNI_CFG_JOIN_FAILURE_TIMEOUT, (tANI_U32 *) &pMlmJoinReq->joinFailureTimeout) |
| != eSIR_SUCCESS) |
| { |
| limLog(pMac, LOGP, FL("could not retrieve JoinFailureTimer value" |
| " setting to default value")); |
| pMlmJoinReq->joinFailureTimeout = |
| WNI_CFG_JOIN_FAILURE_TIMEOUT_STADEF; |
| } |
| /* copy operational rate from psessionEntry*/ |
| vos_mem_copy((void*)&psessionEntry->rateSet, (void*)&pSmeJoinReq->operationalRateSet, |
| sizeof(tSirMacRateSet)); |
| vos_mem_copy((void*)&psessionEntry->extRateSet, (void*)&pSmeJoinReq->extendedRateSet, |
| sizeof(tSirMacRateSet)); |
| //this may not be needed anymore now, as rateSet is now included in the session entry and MLM has session context. |
| vos_mem_copy((void*)&pMlmJoinReq->operationalRateSet, (void*)&psessionEntry->rateSet, |
| sizeof(tSirMacRateSet)); |
| |
| psessionEntry->encryptType = pSmeJoinReq->UCEncryptionType; |
| |
| pMlmJoinReq->bssDescription.length = psessionEntry->pLimJoinReq->bssDescription.length; |
| |
| vos_mem_copy((tANI_U8 *) &pMlmJoinReq->bssDescription.bssId, |
| (tANI_U8 *) &psessionEntry->pLimJoinReq->bssDescription.bssId, |
| psessionEntry->pLimJoinReq->bssDescription.length + 2); |
| |
| psessionEntry->limCurrentBssCaps = |
| psessionEntry->pLimJoinReq->bssDescription.capabilityInfo; |
| |
| regMax = cfgGetRegulatoryMaxTransmitPower( pMac, psessionEntry->currentOperChannel ); |
| |
| localPowerConstraint = regMax; |
| |
| if(!pMac->psOffloadEnabled) |
| { |
| limExtractApCapability( pMac, |
| (tANI_U8 *) psessionEntry->pLimJoinReq->bssDescription.ieFields, |
| GET_IE_LEN_IN_BSS( |
| psessionEntry->pLimJoinReq->bssDescription.length), |
| &psessionEntry->limCurrentBssQosCaps, |
| &psessionEntry->limCurrentBssPropCap, |
| &pMac->lim.gLimCurrentBssUapsd |
| , &localPowerConstraint, |
| psessionEntry |
| ); |
| } |
| else |
| { |
| limExtractApCapability( pMac, |
| (tANI_U8 *) psessionEntry->pLimJoinReq->bssDescription.ieFields, |
| GET_IE_LEN_IN_BSS( |
| psessionEntry->pLimJoinReq->bssDescription.length), |
| &psessionEntry->limCurrentBssQosCaps, |
| &psessionEntry->limCurrentBssPropCap, |
| &psessionEntry->gLimCurrentBssUapsd, |
| &localPowerConstraint, |
| psessionEntry |
| ); |
| } |
| |
| psessionEntry->maxTxPower = limGetMaxTxPower(regMax, |
| localPowerConstraint, pMac->roam.configParam.nTxPowerCap); |
| |
| limLog(pMac, LOG1, |
| FL("regMax = %d, localPowerConstraint = %d," |
| "max tx pwr = %d, UAPSD flag for all AC - 0x%2x"), |
| regMax, localPowerConstraint, |
| psessionEntry->maxTxPower, |
| psessionEntry->gUapsdPerAcBitmask); |
| |
| if (pSmeJoinReq->powerCap.maxTxPower > psessionEntry->maxTxPower) |
| { |
| pSmeJoinReq->powerCap.maxTxPower = psessionEntry->maxTxPower; |
| VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, |
| "Update MaxTxPower in join Req to %d", |
| pSmeJoinReq->powerCap.maxTxPower); |
| } |
| if(!pMac->psOffloadEnabled) |
| { |
| if (pMac->lim.gLimCurrentBssUapsd) |
| { |
| pMac->lim.gUapsdPerAcBitmask = |
| psessionEntry->pLimJoinReq->uapsdPerAcBitmask; |
| // resetting the dynamic uapsd mask |
| pMac->lim.gUapsdPerAcDeliveryEnableMask = 0; |
| pMac->lim.gUapsdPerAcTriggerEnableMask = 0; |
| } |
| } |
| else |
| { |
| if (psessionEntry->gLimCurrentBssUapsd) |
| { |
| psessionEntry->gUapsdPerAcBitmask = |
| psessionEntry->pLimJoinReq->uapsdPerAcBitmask; |
| /* resetting the dynamic uapsd mask */ |
| psessionEntry->gUapsdPerAcDeliveryEnableMask = 0; |
| psessionEntry->gUapsdPerAcTriggerEnableMask = 0; |
| } |
| } |
| |
| psessionEntry->limRFBand = limGetRFBand(psessionEntry->currentOperChannel); |
| |
| // Initialize 11h Enable Flag |
| if(SIR_BAND_5_GHZ == psessionEntry->limRFBand) |
| { |
| if (wlan_cfgGetInt(pMac, WNI_CFG_11H_ENABLED, &val) != eSIR_SUCCESS) |
| { |
| limLog(pMac, LOGP, FL("Fail to get WNI_CFG_11H_ENABLED ")); |
| psessionEntry->lim11hEnable = WNI_CFG_11H_ENABLED_STADEF; |
| } |
| else { |
| psessionEntry->lim11hEnable = val; |
| } |
| } |
| else |
| psessionEntry->lim11hEnable = 0; |
| |
| //To care of the scenario when STA transitions from IBSS to Infrastructure mode. |
| pMac->lim.gLimIbssCoalescingHappened = false; |
| |
| psessionEntry->limPrevSmeState = psessionEntry->limSmeState; |
| psessionEntry->limSmeState = eLIM_SME_WT_JOIN_STATE; |
| MTRACE(macTrace(pMac, TRACE_CODE_SME_STATE, psessionEntry->peSessionId, psessionEntry->limSmeState)); |
| |
| /* Indicate whether spectrum management is enabled*/ |
| psessionEntry->spectrumMgtEnabled = |
| pSmeJoinReq->spectrumMgtIndicator; |
| |
| /* Enable the spectrum management if this is a DFS channel */ |
| if (psessionEntry->countryInfoPresent && |
| limIsconnectedOnDFSChannel(psessionEntry->currentOperChannel)) |
| psessionEntry->spectrumMgtEnabled = TRUE; |
| |
| psessionEntry->isOSENConnection = |
| pSmeJoinReq->isOSENConnection; |
| |
| psessionEntry->sub20_channelwidth = pSmeJoinReq->sub20_channelwidth; |
| |
| /* Issue LIM_MLM_JOIN_REQ to MLM */ |
| limPostMlmMessage(pMac, LIM_MLM_JOIN_REQ, (tANI_U32 *) pMlmJoinReq); |
| return; |
| |
| } |
| else |
| { |
| /* Received eWNI_SME_JOIN_REQ un expected state */ |
| limLog(pMac, LOGE, FL("received unexpected SME_JOIN_REQ " |
| "in state %X"), pMac->lim.gLimSmeState); |
| retCode = eSIR_SME_UNEXPECTED_REQ_RESULT_CODE; |
| psessionEntry = NULL; |
| goto end; |
| |
| } |
| |
| end: |
| limGetSessionInfo(pMac,(tANI_U8*)pMsgBuf,&smesessionId,&smetransactionId); |
| |
| if(pSmeJoinReq) |
| { |
| vos_mem_free(pSmeJoinReq); |
| pSmeJoinReq = NULL; |
| if (NULL != psessionEntry) |
| { |
| psessionEntry->pLimJoinReq = NULL; |
| } |
| } |
| |
| if(retCode != eSIR_SME_SUCCESS) |
| { |
| if(NULL != psessionEntry) |
| { |
| peDeleteSession(pMac,psessionEntry); |
| psessionEntry = NULL; |
| } |
| } |
| limLog(pMac, LOG1, FL("Sending failure status limSendSmeJoinReassocRsp" |
| "on sessionid: %d with retCode = %d"),smesessionId, retCode); |
| limSendSmeJoinReassocRsp(pMac, eWNI_SME_JOIN_RSP, retCode, eSIR_MAC_UNSPEC_FAILURE_STATUS,psessionEntry,smesessionId,smetransactionId); |
| } /*** end __limProcessSmeJoinReq() ***/ |
| |
| |
| #if defined FEATURE_WLAN_ESE || defined WLAN_FEATURE_VOWIFI |
| tANI_U8 limGetMaxTxPower(tPowerdBm regMax, tPowerdBm apTxPower, tANI_U8 iniTxPower) |
| { |
| tANI_U8 maxTxPower = 0; |
| tANI_U8 txPower = VOS_MIN( regMax, (apTxPower) ); |
| txPower = VOS_MIN(txPower, iniTxPower); |
| if((txPower >= MIN_TX_PWR_CAP) && (txPower <= MAX_TX_PWR_CAP)) |
| maxTxPower = txPower; |
| else if (txPower < MIN_TX_PWR_CAP) |
| maxTxPower = MIN_TX_PWR_CAP; |
| else |
| maxTxPower = MAX_TX_PWR_CAP; |
| |
| return (maxTxPower); |
| } |
| #endif |
| |
| /** |
| * __limProcessSmeReassocReq() |
| * |
| *FUNCTION: |
| * This function is called to process SME_REASSOC_REQ message |
| * from HDD or upper layer application. |
| * |
| *LOGIC: |
| * |
| *ASSUMPTIONS: |
| * |
| *NOTE: |
| * |
| * @param pMac Pointer to Global MAC structure |
| * @param *pMsgBuf A pointer to the SME message buffer |
| * @return None |
| */ |
| |
| static void |
| __limProcessSmeReassocReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) |
| { |
| tANI_U16 caps; |
| tANI_U32 val; |
| tpSirSmeJoinReq pReassocReq = NULL; |
| tLimMlmReassocReq *pMlmReassocReq; |
| tSirResultCodes retCode = eSIR_SME_SUCCESS; |
| tpPESession psessionEntry = NULL; |
| tANI_U8 sessionId; |
| tANI_U8 smeSessionId; |
| uint8_t no_of_sessions; |
| tANI_U16 transactionId; |
| tPowerdBm localPowerConstraint = 0, regMax = 0; |
| tANI_U32 teleBcnEn = 0; |
| tANI_U16 nSize; |
| |
| |
| PELOG3(limLog(pMac, LOG3, FL("Received REASSOC_REQ"));) |
| |
| nSize = __limGetSmeJoinReqSizeForAlloc((tANI_U8 *) pMsgBuf); |
| pReassocReq = vos_mem_malloc(nSize); |
| if ( NULL == pReassocReq ) |
| { |
| // Log error |
| limLog(pMac, LOGP, |
| FL("call to AllocateMemory failed for pReassocReq")); |
| |
| retCode = eSIR_SME_RESOURCES_UNAVAILABLE; |
| goto end; |
| } |
| (void) vos_mem_set((void *) pReassocReq, nSize, 0); |
| if ((limJoinReqSerDes(pMac, (tpSirSmeJoinReq) pReassocReq, |
| (tANI_U8 *) pMsgBuf) == eSIR_FAILURE) || |
| (!limIsSmeJoinReqValid(pMac, |
| (tpSirSmeJoinReq) pReassocReq))) |
| { |
| /// Received invalid eWNI_SME_REASSOC_REQ |
| // Log the event |
| limLog(pMac, LOGW, |
| FL("received SME_REASSOC_REQ with invalid data")); |
| |
| retCode = eSIR_SME_INVALID_PARAMETERS; |
| goto end; |
| } |
| |
| no_of_sessions = |
| pe_count_session_with_sme_session_id(pMac, pReassocReq->sessionId); |
| if (no_of_sessions > 1) { |
| limLog(pMac, LOGE, |
| FL("%d sessions exist for the SME session %d"), |
| no_of_sessions, pReassocReq->sessionId); |
| vos_flush_logs(WLAN_LOG_TYPE_FATAL, |
| WLAN_LOG_INDICATOR_HOST_DRIVER, |
| WLAN_LOG_REASON_STALE_SESSION_FOUND, |
| DUMP_VOS_TRACE); |
| retCode = eSIR_SME_REFUSED; |
| goto end; |
| } |
| |
| if((psessionEntry = peFindSessionByBssid(pMac,pReassocReq->bssDescription.bssId,&sessionId))==NULL) |
| { |
| limLog(pMac, LOGE, FL("Session does not exist for given bssId")); |
| limPrintMacAddr(pMac, pReassocReq->bssDescription.bssId, LOGE); |
| retCode = eSIR_SME_INVALID_PARAMETERS; |
| |
| limGetSessionInfo(pMac,(tANI_U8*)pMsgBuf, &smeSessionId, &transactionId); |
| psessionEntry = pe_find_session_by_sme_session_id(pMac, smeSessionId); |
| |
| if (psessionEntry != NULL) |
| limHandleSmeJoinResult(pMac, eSIR_SME_INVALID_PARAMETERS, |
| eSIR_MAC_UNSPEC_FAILURE_STATUS, psessionEntry); |
| goto end; |
| } |
| |
| #ifdef FEATURE_WLAN_DIAG_SUPPORT |
| limDiagEventReport(pMac, WLAN_PE_DIAG_REASSOC_REQ_EVENT, psessionEntry, |
| eSIR_SUCCESS, eSIR_SUCCESS); |
| #endif |
| //pMac->lim.gpLimReassocReq = pReassocReq;//TO SUPPORT BT-AMP |
| |
| /* Store the reassoc handle in the session Table.. 23rd sep review */ |
| psessionEntry->pLimReAssocReq = pReassocReq; |
| |
| psessionEntry->dot11mode = pReassocReq->dot11mode; |
| psessionEntry->vhtCapability = IS_DOT11_MODE_VHT(pReassocReq->dot11mode); |
| |
| #ifdef WLAN_FEATURE_11AC |
| if (psessionEntry->vhtCapability) { |
| if (psessionEntry->pePersona == VOS_STA_MODE) |
| psessionEntry->txBFIniFeatureEnabled = |
| pReassocReq->txBFIniFeatureEnabled; |
| else |
| psessionEntry->txBFIniFeatureEnabled = 0; |
| |
| psessionEntry->txMuBformee = pReassocReq->txMuBformee; |
| psessionEntry->enableVhtpAid = pReassocReq->enableVhtpAid; |
| psessionEntry->enableVhtGid = pReassocReq->enableVhtGid; |
| if (psessionEntry->txBFIniFeatureEnabled) { |
| if (cfgSetInt(pMac, WNI_CFG_VHT_SU_BEAMFORMEE_CAP, |
| psessionEntry->txBFIniFeatureEnabled) |
| != eSIR_SUCCESS) { |
| limLog(pMac, LOGE, FL("could not set " |
| "WNI_CFG_VHT_SU_BEAMFORMEE_CAP at CFG")); |
| retCode = eSIR_LOGP_EXCEPTION; |
| goto end; |
| } |
| if (cfgSetInt(pMac, WNI_CFG_VHT_CSN_BEAMFORMEE_ANT_SUPPORTED, |
| pReassocReq->txBFCsnValue) |
| != eSIR_SUCCESS) { |
| limLog(pMac, LOGE, FL("could not set " |
| "WNI_CFG_VHT_CSN_BEAMFORMEE_ANT_SUPPORTED at CFG")); |
| retCode = eSIR_LOGP_EXCEPTION; |
| goto end; |
| } |
| } |
| } |
| limLog(pMac, LOG1, |
| FL("vhtCapability: %d txBFIniFeatureEnabled: %d" |
| "txBFCsnValue: %d txMuBformee: %d"), |
| psessionEntry->vhtCapability, |
| psessionEntry->txBFIniFeatureEnabled, |
| pReassocReq->txBFCsnValue, |
| psessionEntry->txMuBformee); |
| #endif |
| |
| psessionEntry->enableHtSmps = pReassocReq->enableHtSmps; |
| psessionEntry->htSmpsvalue = pReassocReq->htSmps; |
| limLog(pMac, LOG1, FL("enableHtSmps: %d htSmps: %d supported nss 1x1: %d"), |
| psessionEntry->enableHtSmps, |
| psessionEntry->htSmpsvalue, |
| psessionEntry->supported_nss_1x1); |
| |
| /** |
| * Reassociate request is expected |
| * in link established state only. |
| */ |
| |
| if (psessionEntry->limSmeState != eLIM_SME_LINK_EST_STATE) |
| { |
| #if defined(WLAN_FEATURE_VOWIFI_11R) || defined(FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR) |
| if (psessionEntry->limSmeState == eLIM_SME_WT_REASSOC_STATE) |
| { |
| // May be from 11r FT pre-auth. So lets check it before we bail out |
| limLog(pMac, LOG1, FL("Session in reassoc state is %d"), |
| psessionEntry->peSessionId); |
| |
| // Make sure its our preauth bssid |
| if (!vos_mem_compare( pReassocReq->bssDescription.bssId, |
| psessionEntry->limReAssocbssId, 6)) |
| { |
| limPrintMacAddr(pMac, pReassocReq->bssDescription.bssId, LOGE); |
| limLog(pMac, LOGP, FL("Unknown bssId in reassoc state")); |
| retCode = eSIR_SME_INVALID_PARAMETERS; |
| goto end; |
| } |
| |
| limProcessMlmFTReassocReq(pMac, pMsgBuf, psessionEntry); |
| return; |
| } |
| #endif |
| /// Should not have received eWNI_SME_REASSOC_REQ |
| // Log the event |
| limLog(pMac, LOGE, |
| FL("received unexpected SME_REASSOC_REQ in state %X"), |
| psessionEntry->limSmeState); |
| |
| retCode = eSIR_SME_UNEXPECTED_REQ_RESULT_CODE; |
| goto end; |
| } |
| |
| vos_mem_copy( psessionEntry->limReAssocbssId, |
| psessionEntry->pLimReAssocReq->bssDescription.bssId, |
| sizeof(tSirMacAddr)); |
| |
| psessionEntry->limReassocChannelId = |
| psessionEntry->pLimReAssocReq->bssDescription.channelId; |
| |
| psessionEntry->reAssocHtSupportedChannelWidthSet = |
| (psessionEntry->pLimReAssocReq->cbMode)?1:0; |
| psessionEntry->reAssocHtRecommendedTxWidthSet = |
| psessionEntry->reAssocHtSupportedChannelWidthSet; |
| psessionEntry->reAssocHtSecondaryChannelOffset = |
| psessionEntry->pLimReAssocReq->cbMode; |
| |
| psessionEntry->limReassocBssCaps = |
| psessionEntry->pLimReAssocReq->bssDescription.capabilityInfo; |
| regMax = cfgGetRegulatoryMaxTransmitPower( pMac, psessionEntry->currentOperChannel ); |
| localPowerConstraint = regMax; |
| |
| if(!pMac->psOffloadEnabled) |
| { |
| limExtractApCapability( pMac, |
| (tANI_U8 *) psessionEntry->pLimReAssocReq->bssDescription.ieFields, |
| GET_IE_LEN_IN_BSS( |
| psessionEntry->pLimReAssocReq->bssDescription.length), |
| &psessionEntry->limReassocBssQosCaps, |
| &psessionEntry->limReassocBssPropCap, |
| &pMac->lim.gLimCurrentBssUapsd |
| , &localPowerConstraint, |
| psessionEntry |
| ); |
| } |
| else |
| { |
| limExtractApCapability(pMac, |
| (tANI_U8 *) psessionEntry->pLimReAssocReq->bssDescription.ieFields, |
| GET_IE_LEN_IN_BSS( |
| psessionEntry->pLimReAssocReq->bssDescription.length), |
| &psessionEntry->limReassocBssQosCaps, |
| &psessionEntry->limReassocBssPropCap, |
| &psessionEntry->gLimCurrentBssUapsd, |
| &localPowerConstraint, |
| psessionEntry); |
| } |
| |
| psessionEntry->maxTxPower = VOS_MIN( regMax, (localPowerConstraint) ); |
| #if defined WLAN_VOWIFI_DEBUG |
| limLog( pMac, LOGE, "Regulatory max = %d, local power constraint " |
| "= %d, max tx = %d", regMax, localPowerConstraint, |
| psessionEntry->maxTxPower ); |
| #endif |
| { |
| |
| /* Copy the SSID from session entry to local variable */ |
| psessionEntry->limReassocSSID.length = pReassocReq->ssId.length; |
| vos_mem_copy(psessionEntry->limReassocSSID.ssId, |
| pReassocReq->ssId.ssId, psessionEntry->limReassocSSID.length); |
| |
| } |
| |
| if(!pMac->psOffloadEnabled) |
| { |
| if (pMac->lim.gLimCurrentBssUapsd) |
| { |
| pMac->lim.gUapsdPerAcBitmask = |
| psessionEntry->pLimReAssocReq->uapsdPerAcBitmask; |
| limLog( pMac, LOG1, |
| FL("UAPSD flag for all AC - 0x%2x"), |
| pMac->lim.gUapsdPerAcBitmask); |
| } |
| } |
| else |
| { |
| if(psessionEntry->gLimCurrentBssUapsd) |
| { |
| psessionEntry->gUapsdPerAcBitmask = |
| psessionEntry->pLimReAssocReq->uapsdPerAcBitmask; |
| limLog( pMac, LOG1, |
| FL("UAPSD flag for all AC - 0x%2x"), |
| psessionEntry->gUapsdPerAcBitmask); |
| } |
| } |
| |
| pMlmReassocReq = vos_mem_malloc(sizeof(tLimMlmReassocReq)); |
| if ( NULL == pMlmReassocReq ) |
| { |
| // Log error |
| limLog(pMac, LOGP, |
| FL("call to AllocateMemory failed for mlmReassocReq")); |
| |
| retCode = eSIR_SME_RESOURCES_UNAVAILABLE; |
| goto end; |
| } |
| |
| vos_mem_copy( pMlmReassocReq->peerMacAddr, |
| psessionEntry->limReAssocbssId, |
| sizeof(tSirMacAddr)); |
| |
| if (wlan_cfgGetInt(pMac, WNI_CFG_REASSOCIATION_FAILURE_TIMEOUT, |
| (tANI_U32 *) &pMlmReassocReq->reassocFailureTimeout) |
| != eSIR_SUCCESS) |
| { |
| /** |
| * Could not get ReassocFailureTimeout value |
| * from CFG. Log error. |
| */ |
| limLog(pMac, LOGP, |
| FL("could not retrieve ReassocFailureTimeout value")); |
| } |
| |
| if (cfgGetCapabilityInfo(pMac, &caps,psessionEntry) != eSIR_SUCCESS) |
| { |
| /** |
| * Could not get Capabilities value |
| * from CFG. Log error. |
| */ |
| limLog(pMac, LOGP, |
| FL("could not retrieve Capabilities value")); |
| } |
| |
| lim_update_caps_info_for_bss(pMac, &caps, |
| pReassocReq->bssDescription.capabilityInfo); |
| |
| limLog(pMac, LOG1, FL("Capabilities info Reassoc: 0x%X"), caps); |
| |
| pMlmReassocReq->capabilityInfo = caps; |
| |
| /* Update PE sessionId*/ |
| pMlmReassocReq->sessionId = sessionId; |
| |
| /* If telescopic beaconing is enabled, set listen interval to |
| WNI_CFG_TELE_BCN_MAX_LI */ |
| if(wlan_cfgGetInt(pMac, WNI_CFG_TELE_BCN_WAKEUP_EN, &teleBcnEn) != |
| eSIR_SUCCESS) |
| limLog(pMac, LOGP, FL("Couldn't get WNI_CFG_TELE_BCN_WAKEUP_EN")); |
| |
| val = WNI_CFG_LISTEN_INTERVAL_STADEF; |
| |
| if(teleBcnEn) |
| { |
| if(wlan_cfgGetInt(pMac, WNI_CFG_TELE_BCN_MAX_LI, &val) != |
| eSIR_SUCCESS) |
| { |
| /** |
| * Could not get ListenInterval value |
| * from CFG. Log error. |
| */ |
| limLog(pMac, LOGP, FL("could not retrieve ListenInterval")); |
| } |
| } |
| else |
| { |
| if (wlan_cfgGetInt(pMac, WNI_CFG_LISTEN_INTERVAL, &val) != eSIR_SUCCESS) |
| { |
| /** |
| * Could not get ListenInterval value |
| * from CFG. Log error. |
| */ |
| limLog(pMac, LOGP, FL("could not retrieve ListenInterval")); |
| } |
| } |
| |
| pMlmReassocReq->listenInterval = (tANI_U16) val; |
| |
| /* Indicate whether spectrum management is enabled*/ |
| psessionEntry->spectrumMgtEnabled = pReassocReq->spectrumMgtIndicator; |
| |
| /* Enable the spectrum management if this is a DFS channel */ |
| if (psessionEntry->countryInfoPresent && |
| limIsconnectedOnDFSChannel(psessionEntry->currentOperChannel)) |
| psessionEntry->spectrumMgtEnabled = TRUE; |
| |
| psessionEntry->limPrevSmeState = psessionEntry->limSmeState; |
| psessionEntry->limSmeState = eLIM_SME_WT_REASSOC_STATE; |
| |
| MTRACE(macTrace(pMac, TRACE_CODE_SME_STATE, psessionEntry->peSessionId, psessionEntry->limSmeState)); |
| |
| limPostMlmMessage(pMac, |
| LIM_MLM_REASSOC_REQ, |
| (tANI_U32 *) pMlmReassocReq); |
| return; |
| |
| end: |
| if (pReassocReq) { |
| vos_mem_free( pReassocReq); |
| if (psessionEntry) |
| psessionEntry->pLimReAssocReq = NULL; |
| } |
| |
| if (psessionEntry) |
| { |
| // error occurred after we determined the session so extract |
| // session and transaction info from there |
| smeSessionId = psessionEntry->smeSessionId; |
| transactionId = psessionEntry->transactionId; |
| } |
| else |
| { |
| // error occurred before or during the time we determined the session |
| // so extract the session and transaction info from the message |
| limGetSessionInfo(pMac,(tANI_U8*)pMsgBuf, &smeSessionId, &transactionId); |
| } |
| |
| /// Send Reassoc failure response to host |
| /// (note psessionEntry may be NULL, but that's OK) |
| limSendSmeJoinReassocRsp(pMac, eWNI_SME_REASSOC_RSP, |
| retCode, eSIR_MAC_UNSPEC_FAILURE_STATUS, |
| psessionEntry, smeSessionId, transactionId); |
| |
| } /*** end __limProcessSmeReassocReq() ***/ |
| |
| |
| tANI_BOOLEAN sendDisassocFrame = 1; |
| /** |
| * __limProcessSmeDisassocReq() |
| * |
| *FUNCTION: |
| * This function is called to process SME_DISASSOC_REQ message |
| * from HDD or upper layer application. |
| * |
| *LOGIC: |
| * |
| *ASSUMPTIONS: |
| * |
| *NOTE: |
| * |
| * @param pMac Pointer to Global MAC structure |
| * @param *pMsgBuf A pointer to the SME message buffer |
| * @return None |
| */ |
| |
| static void |
| __limProcessSmeDisassocReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) |
| { |
| tANI_U16 disassocTrigger, reasonCode; |
| tLimMlmDisassocReq *pMlmDisassocReq; |
| tSirResultCodes retCode = eSIR_SME_SUCCESS; |
| tSirRetStatus status; |
| tSirSmeDisassocReq smeDisassocReq; |
| tpPESession psessionEntry = NULL; |
| tANI_U8 sessionId; |
| tANI_U8 smesessionId; |
| tANI_U16 smetransactionId; |
| |
| if (pMsgBuf == NULL) |
| { |
| limLog(pMac, LOGE, FL("Buffer is Pointing to NULL")); |
| return; |
| } |
| |
| limGetSessionInfo(pMac, (tANI_U8 *)pMsgBuf,&smesessionId, &smetransactionId); |
| |
| status = limDisassocReqSerDes(pMac, &smeDisassocReq, (tANI_U8 *) pMsgBuf); |
| |
| if ( (eSIR_FAILURE == status) || |
| (!limIsSmeDisassocReqValid(pMac, &smeDisassocReq, psessionEntry)) ) |
| { |
| PELOGE(limLog(pMac, LOGE, |
| FL("received invalid SME_DISASSOC_REQ message"));) |
| |
| if (pMac->lim.gLimRspReqd) |
| { |
| pMac->lim.gLimRspReqd = false; |
| |
| retCode = eSIR_SME_INVALID_PARAMETERS; |
| disassocTrigger = eLIM_HOST_DISASSOC; |
| goto sendDisassoc; |
| } |
| |
| return; |
| } |
| |
| if((psessionEntry = peFindSessionByBssid(pMac,smeDisassocReq.bssId,&sessionId))== NULL) |
| { |
| limLog(pMac, LOGE,FL("session does not exist for given bssId "MAC_ADDRESS_STR), |
| MAC_ADDR_ARRAY(smeDisassocReq.bssId)); |
| retCode = eSIR_SME_INVALID_PARAMETERS; |
| disassocTrigger = eLIM_HOST_DISASSOC; |
| goto sendDisassoc; |
| |
| } |
| limLog(pMac, LOG1, FL("received DISASSOC_REQ message on sessionid %d " |
| "Systemrole %d Reason: %u SmeState: %d from: "MAC_ADDRESS_STR), |
| smesessionId, GET_LIM_SYSTEM_ROLE(psessionEntry), |
| smeDisassocReq.reasonCode, pMac->lim.gLimSmeState, |
| MAC_ADDR_ARRAY(smeDisassocReq.peerMacAddr)); |
| |
| #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM //FEATURE_WLAN_DIAG_SUPPORT |
| limDiagEventReport(pMac, WLAN_PE_DIAG_DISASSOC_REQ_EVENT, psessionEntry, 0, smeDisassocReq.reasonCode); |
| #endif //FEATURE_WLAN_DIAG_SUPPORT |
| |
| /* Update SME session Id and SME transaction ID*/ |
| |
| psessionEntry->smeSessionId = smesessionId; |
| psessionEntry->transactionId = smetransactionId; |
| |
| switch (GET_LIM_SYSTEM_ROLE(psessionEntry)) |
| { |
| case eLIM_STA_ROLE: |
| case eLIM_BT_AMP_STA_ROLE: |
| switch (psessionEntry->limSmeState) |
| { |
| case eLIM_SME_ASSOCIATED_STATE: |
| case eLIM_SME_LINK_EST_STATE: |
| limLog(pMac, LOG1, FL("Rcvd SME_DISASSOC_REQ in limSmeState: %d"), |
| psessionEntry->limSmeState); |
| psessionEntry->limPrevSmeState = psessionEntry->limSmeState; |
| psessionEntry->limSmeState= eLIM_SME_WT_DISASSOC_STATE; |
| #ifdef FEATURE_WLAN_TDLS |
| /* Delete all TDLS peers connected before leaving BSS*/ |
| limDeleteTDLSPeers(pMac, psessionEntry); |
| #endif |
| MTRACE(macTrace(pMac, TRACE_CODE_SME_STATE, psessionEntry->peSessionId, psessionEntry->limSmeState)); |
| break; |
| |
| case eLIM_SME_WT_DEAUTH_STATE: |
| /* PE shall still process the DISASSOC_REQ and proceed with |
| * link tear down even if it had already sent a DEAUTH_IND to |
| * to SME. pMac->lim.gLimPrevSmeState shall remain the same as |
| * its been set when PE entered WT_DEAUTH_STATE. |
| */ |
| psessionEntry->limSmeState= eLIM_SME_WT_DISASSOC_STATE; |
| MTRACE(macTrace(pMac, TRACE_CODE_SME_STATE, psessionEntry->peSessionId, psessionEntry->limSmeState)); |
| limLog(pMac, LOG1, FL("Rcvd SME_DISASSOC_REQ while in " |
| "SME_WT_DEAUTH_STATE. ")); |
| break; |
| |
| case eLIM_SME_WT_DISASSOC_STATE: |
| /* PE Recieved a Disassoc frame. Normally it gets DISASSOC_CNF but it |
| * received DISASSOC_REQ. Which means host is also trying to disconnect. |
| * PE can continue processing DISASSOC_REQ and send the response instead |
| * of failing the request. SME will anyway ignore DEAUTH_IND that was sent |
| * for disassoc frame. |
| * |
| * It will send a disassoc, which is ok. However, we can use the global flag |
| * sendDisassoc to not send disassoc frame. |
| */ |
| limLog(pMac, LOG1, FL("Rcvd SME_DISASSOC_REQ while in " |
| "SME_WT_DISASSOC_STATE. ")); |
| break; |
| |
| case eLIM_SME_JOIN_FAILURE_STATE: { |
| /** Return Success as we are already in Disconnected State*/ |
| limLog(pMac, LOG1, FL("Rcvd SME_DISASSOC_REQ while in " |
| "eLIM_SME_JOIN_FAILURE_STATE. ")); |
| if (pMac->lim.gLimRspReqd) { |
| retCode = eSIR_SME_SUCCESS; |
| disassocTrigger = eLIM_HOST_DISASSOC; |
| goto sendDisassoc; |
| } |
| }break; |
| default: |
| /** |
| * STA is not currently associated. |
| * Log error and send response to host |
| */ |
| limLog(pMac, LOGE, |
| FL("received unexpected SME_DISASSOC_REQ in state %X"), |
| psessionEntry->limSmeState); |
| |
| if (pMac->lim.gLimRspReqd) |
| { |
| if (psessionEntry->limSmeState != |
| eLIM_SME_WT_ASSOC_STATE) |
| pMac->lim.gLimRspReqd = false; |
| |
| retCode = eSIR_SME_UNEXPECTED_REQ_RESULT_CODE; |
| disassocTrigger = eLIM_HOST_DISASSOC; |
| goto sendDisassoc; |
| } |
| |
| return; |
| } |
| |
| break; |
| |
| case eLIM_AP_ROLE: |
| case eLIM_BT_AMP_AP_ROLE: |
| // Fall through |
| break; |
| |
| case eLIM_STA_IN_IBSS_ROLE: |
| default: // eLIM_UNKNOWN_ROLE |
| limLog(pMac, LOGE, |
| FL("received unexpected SME_DISASSOC_REQ for role %d"), |
| GET_LIM_SYSTEM_ROLE(psessionEntry)); |
| |
| retCode = eSIR_SME_UNEXPECTED_REQ_RESULT_CODE; |
| disassocTrigger = eLIM_HOST_DISASSOC; |
| goto sendDisassoc; |
| } // end switch (pMac->lim.gLimSystemRole) |
| |
| disassocTrigger = eLIM_HOST_DISASSOC; |
| reasonCode = smeDisassocReq.reasonCode; |
| |
| if (smeDisassocReq.doNotSendOverTheAir) |
| { |
| limLog(pMac, LOG1, FL("do not send dissoc over the air")); |
| sendDisassocFrame = 0; |
| } |
| // Trigger Disassociation frame to peer MAC entity |
| limLog(pMac, LOG1, FL("Sending Disasscoc with disassoc Trigger" |
| " : %d, reasonCode : %d"), |
| disassocTrigger, reasonCode); |
| |
| pMlmDisassocReq = vos_mem_malloc(sizeof(tLimMlmDisassocReq)); |
| if ( NULL == pMlmDisassocReq ) |
| { |
| // Log error |
| limLog(pMac, LOGP, |
| FL("call to AllocateMemory failed for mlmDisassocReq")); |
| |
| return; |
| } |
| |
| vos_mem_copy( (tANI_U8 *) &pMlmDisassocReq->peerMacAddr, |
| (tANI_U8 *) &smeDisassocReq.peerMacAddr, |
| sizeof(tSirMacAddr)); |
| |
| pMlmDisassocReq->reasonCode = reasonCode; |
| pMlmDisassocReq->disassocTrigger = disassocTrigger; |
| |
| /* Update PE session ID*/ |
| pMlmDisassocReq->sessionId = sessionId; |
| |
| limPostMlmMessage(pMac, |
| LIM_MLM_DISASSOC_REQ, |
| (tANI_U32 *) pMlmDisassocReq); |
| return; |
| |
| sendDisassoc: |
| if (psessionEntry) |
| limSendSmeDisassocNtf(pMac, smeDisassocReq.peerMacAddr, |
| retCode, |
| disassocTrigger, |
| 1,smesessionId,smetransactionId,psessionEntry); |
| else |
| limSendSmeDisassocNtf(pMac, smeDisassocReq.peerMacAddr, |
| retCode, |
| disassocTrigger, |
| 1, smesessionId, smetransactionId, NULL); |
| |
| |
| } /*** end __limProcessSmeDisassocReq() ***/ |
| |
| |
| /** ----------------------------------------------------------------- |
| \brief __limProcessSmeDisassocCnf() - Process SME_DISASSOC_CNF |
| |
| This function is called to process SME_DISASSOC_CNF message |
| from HDD or upper layer application. |
| |
| \param pMac - global mac structure |
| \param pStaDs - station dph hash node |
| \return none |
| \sa |
| ----------------------------------------------------------------- */ |
| static void |
| __limProcessSmeDisassocCnf(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) |
| { |
| tSirSmeDisassocCnf smeDisassocCnf; |
| tANI_U16 aid; |
| tpDphHashNode pStaDs; |
| tSirRetStatus status = eSIR_SUCCESS; |
| tpPESession psessionEntry; |
| tANI_U8 sessionId; |
| |
| |
| PELOG1(limLog(pMac, LOG1, FL("received DISASSOC_CNF message"));) |
| |
| status = limDisassocCnfSerDes(pMac, &smeDisassocCnf,(tANI_U8 *) pMsgBuf); |
| |
| if (status == eSIR_FAILURE) |
| { |
| PELOGE(limLog(pMac, LOGE, FL("invalid SME_DISASSOC_CNF message"));) |
| return; |
| } |
| |
| if((psessionEntry = peFindSessionByBssid(pMac, smeDisassocCnf.bssId, &sessionId))== NULL) |
| { |
| limLog(pMac, LOGE,FL("session does not exist for given bssId")); |
| return; |
| } |
| |
| if (!limIsSmeDisassocCnfValid(pMac, &smeDisassocCnf, psessionEntry)) |
| { |
| limLog(pMac, LOGE, FL("received invalid SME_DISASSOC_CNF message")); |
| return; |
| } |
| |
| #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM //FEATURE_WLAN_DIAG_SUPPORT |
| if (smeDisassocCnf.messageType == eWNI_SME_DISASSOC_CNF) |
| limDiagEventReport(pMac, WLAN_PE_DIAG_DISASSOC_CNF_EVENT, psessionEntry, (tANI_U16)smeDisassocCnf.statusCode, 0); |
| else if (smeDisassocCnf.messageType == eWNI_SME_DEAUTH_CNF) |
| limDiagEventReport(pMac, WLAN_PE_DIAG_DEAUTH_CNF_EVENT, psessionEntry, (tANI_U16)smeDisassocCnf.statusCode, 0); |
| #endif //FEATURE_WLAN_DIAG_SUPPORT |
| |
| switch (GET_LIM_SYSTEM_ROLE(psessionEntry)) |
| { |
| case eLIM_STA_ROLE: |
| case eLIM_BT_AMP_STA_ROLE: //To test reconn |
| if ((psessionEntry->limSmeState != eLIM_SME_IDLE_STATE) && |
| (psessionEntry->limSmeState != eLIM_SME_WT_DISASSOC_STATE) && |
| (psessionEntry->limSmeState != eLIM_SME_WT_DEAUTH_STATE)) |
| { |
| limLog(pMac, LOGE, |
| FL("received unexp SME_DISASSOC_CNF in state %X"), |
| psessionEntry->limSmeState); |
| return; |
| } |
| break; |
| |
| case eLIM_AP_ROLE: |
| // Fall through |
| break; |
| |
| case eLIM_STA_IN_IBSS_ROLE: |
| default: // eLIM_UNKNOWN_ROLE |
| limLog(pMac, LOGE, |
| FL("received unexpected SME_DISASSOC_CNF role %d"), |
| GET_LIM_SYSTEM_ROLE(psessionEntry)); |
| |
| return; |
| } |
| |
| if ((psessionEntry->limSmeState == eLIM_SME_WT_DISASSOC_STATE) || |
| (psessionEntry->limSmeState == eLIM_SME_WT_DEAUTH_STATE) || |
| LIM_IS_AP_ROLE(psessionEntry)) { |
| pStaDs = dphLookupHashEntry(pMac, smeDisassocCnf.peerMacAddr, &aid, &psessionEntry->dph.dphHashTable); |
| if (pStaDs == NULL) |
| { |
| PELOGE(limLog(pMac, LOGE, FL("received DISASSOC_CNF for a STA that " |
| "does not have context, addr= "MAC_ADDRESS_STR), |
| MAC_ADDR_ARRAY(smeDisassocCnf.peerMacAddr));) |
| return; |
| } |
| |
| /* |
| * If MlM state is either of del_sta or del_bss state, then no need to |
| * go ahead and clean up further as there must be some cleanup in |
| * progress from upper layer disassoc/deauth request. |
| */ |
| if((pStaDs->mlmStaContext.mlmState == eLIM_MLM_WT_DEL_STA_RSP_STATE) || |
| (pStaDs->mlmStaContext.mlmState == eLIM_MLM_WT_DEL_BSS_RSP_STATE)) { |
| limLog(pMac, LOGE, FL("No need to cleanup for addr:"MAC_ADDRESS_STR |
| "as Mlm state is %d"), |
| MAC_ADDR_ARRAY(smeDisassocCnf.peerMacAddr), |
| pStaDs->mlmStaContext.mlmState); |
| return; |
| } |
| |
| #if defined WLAN_FEATURE_VOWIFI_11R |
| /* Delete FT session if there exists one */ |
| limFTCleanupPreAuthInfo(pMac, psessionEntry); |
| #endif |
| limCleanupRxPath(pMac, pStaDs, psessionEntry); |
| |
| limCleanUpDisassocDeauthReq(pMac, (char*)&smeDisassocCnf.peerMacAddr, 0); |
| } |
| |
| return; |
| } |
| |
| |
| /** |
| * __limProcessSmeDeauthReq() |
| * |
| *FUNCTION: |
| * This function is called to process SME_DEAUTH_REQ message |
| * from HDD or upper layer application. |
| * |
| *LOGIC: |
| * |
| *ASSUMPTIONS: |
| * |
| *NOTE: |
| * |
| * @param pMac Pointer to Global MAC structure |
| * @param *pMsgBuf A pointer to the SME message buffer |
| * @return None |
| */ |
| |
| static void |
| __limProcessSmeDeauthReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) |
| { |
| tANI_U16 deauthTrigger, reasonCode; |
| tLimMlmDeauthReq *pMlmDeauthReq; |
| tSirSmeDeauthReq smeDeauthReq; |
| tSirResultCodes retCode = eSIR_SME_SUCCESS; |
| tSirRetStatus status = eSIR_SUCCESS; |
| tpPESession psessionEntry; |
| tANI_U8 sessionId; //PE sessionId |
| tANI_U8 smesessionId; |
| tANI_U16 smetransactionId; |
| |
| PELOG1(limLog(pMac, LOG1,FL("received DEAUTH_REQ message"));) |
| |
| status = limDeauthReqSerDes(pMac, &smeDeauthReq,(tANI_U8 *) pMsgBuf); |
| |
| limGetSessionInfo(pMac,(tANI_U8 *)pMsgBuf,&smesessionId,&smetransactionId); |
| |
| //We need to get a session first but we don't even know if the message is correct. |
| if((psessionEntry = peFindSessionByBssid(pMac, smeDeauthReq.bssId, &sessionId)) == NULL) |
| { |
| limLog(pMac, LOGE,FL("session does not exist for given bssId")); |
| retCode = eSIR_SME_INVALID_PARAMETERS; |
| deauthTrigger = eLIM_HOST_DEAUTH; |
| goto sendDeauth; |
| |
| } |
| |
| if ((status == eSIR_FAILURE) || (!limIsSmeDeauthReqValid(pMac, &smeDeauthReq, psessionEntry))) |
| { |
| PELOGE(limLog(pMac, LOGE,FL |
| ("received invalid SME_DEAUTH_REQ message"));) |
| pMac->lim.gLimRspReqd = false; |
| |
| retCode = eSIR_SME_INVALID_PARAMETERS; |
| deauthTrigger = eLIM_HOST_DEAUTH; |
| goto sendDeauth; |
| } |
| limLog(pMac, LOG1,FL("received DEAUTH_REQ message on sessionid %d " |
| "Systemrole %d with reasoncode %u in limSmestate %d from " |
| MAC_ADDRESS_STR), smesessionId, GET_LIM_SYSTEM_ROLE(psessionEntry), |
| smeDeauthReq.reasonCode, psessionEntry->limSmeState, |
| MAC_ADDR_ARRAY(smeDeauthReq.peerMacAddr)); |
| #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM //FEATURE_WLAN_DIAG_SUPPORT |
| limDiagEventReport(pMac, WLAN_PE_DIAG_DEAUTH_REQ_EVENT, psessionEntry, 0, smeDeauthReq.reasonCode); |
| #endif //FEATURE_WLAN_DIAG_SUPPORT |
| |
| /* Update SME session ID and Transaction ID */ |
| psessionEntry->smeSessionId = smesessionId; |
| psessionEntry->transactionId = smetransactionId; |
| |
| |
| switch (GET_LIM_SYSTEM_ROLE(psessionEntry)) |
| { |
| case eLIM_STA_ROLE: |
| case eLIM_BT_AMP_STA_ROLE: |
| |
| switch (psessionEntry->limSmeState) |
| { |
| case eLIM_SME_ASSOCIATED_STATE: |
| case eLIM_SME_LINK_EST_STATE: |
| case eLIM_SME_WT_ASSOC_STATE: |
| case eLIM_SME_JOIN_FAILURE_STATE: |
| case eLIM_SME_IDLE_STATE: |
| psessionEntry->limPrevSmeState = psessionEntry->limSmeState; |
| psessionEntry->limSmeState = eLIM_SME_WT_DEAUTH_STATE; |
| MTRACE(macTrace(pMac, TRACE_CODE_SME_STATE, psessionEntry->peSessionId, psessionEntry->limSmeState)); |
| |
| // Send Deauthentication request to MLM below |
| |
| break; |
| case eLIM_SME_WT_DEAUTH_STATE: |
| case eLIM_SME_WT_DISASSOC_STATE: |
| /* |
| * PE Recieved a Deauth/Disassoc frame. Normally it gets |
| * DEAUTH_CNF/DISASSOC_CNF but it received DEAUTH_REQ. Which |
| * means host is also trying to disconnect. |
| * PE can continue processing DEAUTH_REQ and send |
| * the response instead of failing the request. |
| * SME will anyway ignore DEAUTH_IND/DISASSOC_IND that |
| * was sent for deauth/disassoc frame. |
| */ |
| psessionEntry->limSmeState = eLIM_SME_WT_DEAUTH_STATE; |
| limLog(pMac, LOG1, FL("Rcvd SME_DEAUTH_REQ while in " |
| "SME_WT_DEAUTH_STATE. ")); |
| break; |
| default: |
| /** |
| * STA is not in a state to deauthenticate with |
| * peer. Log error and send response to host. |
| */ |
| limLog(pMac, LOGE, |
| FL("received unexp SME_DEAUTH_REQ in state %X"), |
| psessionEntry->limSmeState); |
| |
| if (pMac->lim.gLimRspReqd) |
| { |
| pMac->lim.gLimRspReqd = false; |
| |
| retCode = eSIR_SME_STA_NOT_AUTHENTICATED; |
| deauthTrigger = eLIM_HOST_DEAUTH; |
| |
| /* |
| here we received deauth request from AP so sme state is |
| eLIM_SME_WT_DEAUTH_STATE.if we have ISSUED delSta then |
| mlm state should be eLIM_MLM_WT_DEL_STA_RSP_STATE and if |
| we got delBSS rsp then mlm state should be eLIM_MLM_IDLE_STATE |
| so the below condition captures the state where delSta |
| not done and firmware still in connected state. |
| */ |
| |
| if (psessionEntry->limSmeState == eLIM_SME_WT_DEAUTH_STATE && |
| psessionEntry->limMlmState != eLIM_MLM_IDLE_STATE && |
| psessionEntry->limMlmState != eLIM_MLM_WT_DEL_STA_RSP_STATE) |
| { |
| retCode = eSIR_SME_DEAUTH_STATUS; |
| } |
| goto sendDeauth; |
| } |
| |
| return; |
| } |
| |
| break; |
| |
| case eLIM_STA_IN_IBSS_ROLE: |
| limLog(pMac, LOGE,FL("Deauth not allowed in IBSS")); |
| if (pMac->lim.gLimRspReqd) |
| { |
| pMac->lim.gLimRspReqd = false; |
| retCode = eSIR_SME_INVALID_PARAMETERS; |
| deauthTrigger = eLIM_HOST_DEAUTH; |
| goto sendDeauth; |
| } |
| return; |
| |
| case eLIM_AP_ROLE: |
| // Fall through |
| |
| break; |
| |
| default: |
| limLog(pMac, LOGE, |
| FL("received unexpected SME_DEAUTH_REQ for role %X"), |
| GET_LIM_SYSTEM_ROLE(psessionEntry)); |
| if (pMac->lim.gLimRspReqd) |
| { |
| pMac->lim.gLimRspReqd = false; |
| retCode = eSIR_SME_INVALID_PARAMETERS; |
| deauthTrigger = eLIM_HOST_DEAUTH; |
| goto sendDeauth; |
| } |
| return; |
| } // end switch (pMac->lim.gLimSystemRole) |
| |
| if (smeDeauthReq.reasonCode == eLIM_LINK_MONITORING_DEAUTH) |
| { |
| /// Deauthentication is triggered by Link Monitoring |
| PELOG1(limLog(pMac, LOG1, FL("**** Lost link with AP ****"));) |
| deauthTrigger = eLIM_LINK_MONITORING_DEAUTH; |
| reasonCode = eSIR_MAC_UNSPEC_FAILURE_REASON; |
| } |
| else |
| { |
| deauthTrigger = eLIM_HOST_DEAUTH; |
| reasonCode = smeDeauthReq.reasonCode; |
| } |
| |
| // Trigger Deauthentication frame to peer MAC entity |
| pMlmDeauthReq = vos_mem_malloc(sizeof(tLimMlmDeauthReq)); |
| if ( NULL == pMlmDeauthReq ) |
| { |
| // Log error |
| limLog(pMac, LOGE, |
| FL("call to AllocateMemory failed for mlmDeauthReq")); |
| if (pMac->lim.gLimRspReqd) |
| { |
| pMac->lim.gLimRspReqd = false; |
| retCode = eSIR_SME_RESOURCES_UNAVAILABLE; |
| deauthTrigger = eLIM_HOST_DEAUTH; |
| goto sendDeauth; |
| } |
| return; |
| } |
| |
| vos_mem_copy( (tANI_U8 *) &pMlmDeauthReq->peerMacAddr, |
| (tANI_U8 *) &smeDeauthReq.peerMacAddr, |
| sizeof(tSirMacAddr)); |
| |
| pMlmDeauthReq->reasonCode = reasonCode; |
| pMlmDeauthReq->deauthTrigger = deauthTrigger; |
| |
| /* Update PE session Id*/ |
| pMlmDeauthReq->sessionId = sessionId; |
| |
| limPostMlmMessage(pMac, |
| LIM_MLM_DEAUTH_REQ, |
| (tANI_U32 *) pMlmDeauthReq); |
| return; |
| |
| sendDeauth: |
| limSendSmeDeauthNtf(pMac, smeDeauthReq.peerMacAddr, |
| retCode, |
| deauthTrigger, |
| 1, |
| smesessionId, smetransactionId); |
| } /*** end __limProcessSmeDeauthReq() ***/ |
| |
| |
| |
| /** |
| * __limProcessSmeSetContextReq() |
| * |
| *FUNCTION: |
| * This function is called to process SME_SETCONTEXT_REQ message |
| * from HDD or upper layer application. |
| * |
| *LOGIC: |
| * |
| *ASSUMPTIONS: |
| * |
| *NOTE: |
| * |
| * @param pMac Pointer to Global MAC structure |
| * @param *pMsgBuf A pointer to the SME message buffer |
| * @return None |
| */ |
| |
| static void |
| __limProcessSmeSetContextReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) |
| { |
| tpSirSmeSetContextReq pSetContextReq; |
| tLimMlmSetKeysReq *pMlmSetKeysReq; |
| tpPESession psessionEntry; |
| tANI_U8 sessionId; //PE sessionID |
| tANI_U8 smesessionId; |
| tANI_U16 smetransactionId; |
| |
| |
| PELOG1(limLog(pMac, LOG1, |
| FL("received SETCONTEXT_REQ message"));); |
| |
| |
| if(pMsgBuf == NULL) |
| { |
| limLog(pMac, LOGE,FL("Buffer is Pointing to NULL")); |
| return; |
| } |
| |
| limGetSessionInfo(pMac,(tANI_U8 *)pMsgBuf,&smesessionId,&smetransactionId); |
| |
| pSetContextReq = vos_mem_malloc(sizeof(tSirKeys) * SIR_MAC_MAX_NUM_OF_DEFAULT_KEYS); |
| if ( NULL == pSetContextReq ) |
| { |
| limLog(pMac, LOGP, FL("call to AllocateMemory failed for pSetContextReq")); |
| return; |
| } |
| |
| if ((limSetContextReqSerDes(pMac, pSetContextReq, (tANI_U8 *) pMsgBuf) == eSIR_FAILURE) || |
| (!limIsSmeSetContextReqValid(pMac, pSetContextReq))) |
| { |
| limLog(pMac, LOGW, FL("received invalid SME_SETCONTEXT_REQ message")); |
| goto end; |
| } |
| |
| if(pSetContextReq->keyMaterial.numKeys > SIR_MAC_MAX_NUM_OF_DEFAULT_KEYS) |
| { |
| PELOGE(limLog(pMac, LOGE, FL("numKeys:%d is more than SIR_MAC_MAX_NUM_OF_DEFAULT_KEYS"), pSetContextReq->keyMaterial.numKeys);) |
| limSendSmeSetContextRsp(pMac, |
| pSetContextReq->peerMacAddr, |
| 1, |
| eSIR_SME_INVALID_PARAMETERS,NULL, |
| smesessionId,smetransactionId); |
| |
| goto end; |
| } |
| |
| |
| if((psessionEntry = peFindSessionByBssid(pMac, pSetContextReq->bssId, &sessionId)) == NULL) |
| { |
| limLog(pMac, LOGW, FL("Session does not exist for given BSSID")); |
| limSendSmeSetContextRsp(pMac, |
| pSetContextReq->peerMacAddr, |
| 1, |
| eSIR_SME_INVALID_PARAMETERS,NULL, |
| smesessionId,smetransactionId); |
| |
| goto end; |
| } |
| |
| #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM //FEATURE_WLAN_DIAG_SUPPORT |
| limDiagEventReport(pMac, WLAN_PE_DIAG_SETCONTEXT_REQ_EVENT, psessionEntry, 0, 0); |
| #endif //FEATURE_WLAN_DIAG_SUPPORT |
| |
| |
| if (((LIM_IS_STA_ROLE(psessionEntry) || |
| LIM_IS_BT_AMP_STA_ROLE(psessionEntry)) && |
| (psessionEntry->limSmeState == eLIM_SME_LINK_EST_STATE)) || |
| ((LIM_IS_IBSS_ROLE(psessionEntry) || |
| LIM_IS_AP_ROLE(psessionEntry) || |
| LIM_IS_BT_AMP_AP_ROLE(psessionEntry)) && |
| (psessionEntry->limSmeState == eLIM_SME_NORMAL_STATE))) { |
| // Trigger MLM_SETKEYS_REQ |
| pMlmSetKeysReq = vos_mem_malloc(sizeof(tLimMlmSetKeysReq)); |
| if ( NULL == pMlmSetKeysReq ) |
| { |
| // Log error |
| limLog(pMac, LOGP, FL("call to AllocateMemory failed for mlmSetKeysReq")); |
| goto end; |
| } |
| |
| pMlmSetKeysReq->edType = pSetContextReq->keyMaterial.edType; |
| pMlmSetKeysReq->numKeys = pSetContextReq->keyMaterial.numKeys; |
| if(pMlmSetKeysReq->numKeys > SIR_MAC_MAX_NUM_OF_DEFAULT_KEYS) |
| { |
| limLog(pMac, LOGP, FL("Num of keys exceeded max num of default keys limit")); |
| goto end; |
| } |
| vos_mem_copy( (tANI_U8 *) &pMlmSetKeysReq->peerMacAddr, |
| (tANI_U8 *) &pSetContextReq->peerMacAddr, |
| sizeof(tSirMacAddr)); |
| |
| |
| vos_mem_copy( (tANI_U8 *) &pMlmSetKeysReq->key, |
| (tANI_U8 *) &pSetContextReq->keyMaterial.key, |
| sizeof(tSirKeys) * (pMlmSetKeysReq->numKeys ? pMlmSetKeysReq->numKeys : 1)); |
| |
| pMlmSetKeysReq->sessionId = sessionId; |
| pMlmSetKeysReq->smesessionId = smesessionId; |
| #ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG |
| PELOG1(limLog(pMac, LOG1, |
| FL("received SETCONTEXT_REQ message sessionId=%d"), pMlmSetKeysReq->sessionId);); |
| #endif |
| |
| if (((pSetContextReq->keyMaterial.edType == eSIR_ED_WEP40) || |
| (pSetContextReq->keyMaterial.edType == eSIR_ED_WEP104)) && |
| LIM_IS_AP_ROLE(psessionEntry)) { |
| if(pSetContextReq->keyMaterial.key[0].keyLength) |
| { |
| tANI_U8 keyId; |
| keyId = pSetContextReq->keyMaterial.key[0].keyId; |
| vos_mem_copy( (tANI_U8 *)&psessionEntry->WEPKeyMaterial[keyId], |
| (tANI_U8 *) &pSetContextReq->keyMaterial, sizeof(tSirKeyMaterial)); |
| } |
| else { |
| tANI_U32 i; |
| for( i = 0; i < SIR_MAC_MAX_NUM_OF_DEFAULT_KEYS; i++) |
| { |
| vos_mem_copy( (tANI_U8 *) &pMlmSetKeysReq->key[i], |
| (tANI_U8 *)psessionEntry->WEPKeyMaterial[i].key, sizeof(tSirKeys)); |
| } |
| } |
| } |
| |
| limPostMlmMessage(pMac, LIM_MLM_SETKEYS_REQ, (tANI_U32 *) pMlmSetKeysReq); |
| } |
| else |
| { |
| limLog(pMac, LOGE, |
| FL("received unexpected SME_SETCONTEXT_REQ for role %d, state=%X"), |
| GET_LIM_SYSTEM_ROLE(psessionEntry), |
| psessionEntry->limSmeState); |
| |
| limSendSmeSetContextRsp(pMac, pSetContextReq->peerMacAddr, |
| 1, |
| eSIR_SME_UNEXPECTED_REQ_RESULT_CODE,psessionEntry, |
| smesessionId, |
| smetransactionId); |
| } |
| |
| end: |
| vos_mem_free( pSetContextReq); |
| return; |
| } /*** end __limProcessSmeSetContextReq() ***/ |
| |
| /** |
| * __limProcessSmeRemoveKeyReq() |
| * |
| *FUNCTION: |
| * This function is called to process SME_REMOVEKEY_REQ message |
| * from HDD or upper layer application. |
| * |
| *LOGIC: |
| * |
| *ASSUMPTIONS: |
| * |
| *NOTE: |
| * |
| * @param pMac Pointer to Global MAC structure |
| * @param *pMsgBuf A pointer to the SME message buffer |
| * @return None |
| */ |
| |
| static void |
| __limProcessSmeRemoveKeyReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) |
| { |
| tpSirSmeRemoveKeyReq pRemoveKeyReq; |
| tLimMlmRemoveKeyReq *pMlmRemoveKeyReq; |
| tpPESession psessionEntry; |
| tANI_U8 sessionId; //PE sessionID |
| tANI_U8 smesessionId; |
| tANI_U16 smetransactionId; |
| |
| PELOG1(limLog(pMac, LOG1, |
| FL("received REMOVEKEY_REQ message"));) |
| |
| if(pMsgBuf == NULL) |
| { |
| limLog(pMac, LOGE,FL("Buffer is Pointing to NULL")); |
| return; |
| } |
| |
| |
| limGetSessionInfo(pMac,(tANI_U8 *)pMsgBuf,&smesessionId,&smetransactionId); |
| |
| pRemoveKeyReq = vos_mem_malloc(sizeof(*pRemoveKeyReq)); |
| if ( NULL == pRemoveKeyReq ) |
| { |
| //Log error |
| limLog(pMac, LOGP, |
| FL("call to AllocateMemory failed for pRemoveKeyReq")); |
| |
| return; |
| } |
| |
| if ((limRemoveKeyReqSerDes(pMac, |
| pRemoveKeyReq, |
| (tANI_U8 *) pMsgBuf) == eSIR_FAILURE)) |
| { |
| limLog(pMac, LOGW, |
| FL("received invalid SME_REMOVECONTEXT_REQ message")); |
| |
| /* extra look up is needed since, session entry to be passed il limsendremovekey response */ |
| |
| if((psessionEntry = peFindSessionByBssid(pMac,pRemoveKeyReq->bssId,&sessionId))== NULL) |
| { |
| limLog(pMac, LOGE,FL("session does not exist for given bssId")); |
| //goto end; |
| } |
| |
| limSendSmeRemoveKeyRsp(pMac, |
| pRemoveKeyReq->peerMacAddr, |
| eSIR_SME_INVALID_PARAMETERS,psessionEntry, |
| smesessionId,smetransactionId); |
| |
| goto end; |
| } |
| |
| if((psessionEntry = peFindSessionByBssid(pMac,pRemoveKeyReq->bssId, &sessionId))== NULL) |
| { |
| limLog(pMac, LOGE, |
| FL("session does not exist for given bssId")); |
| limSendSmeRemoveKeyRsp(pMac, |
| pRemoveKeyReq->peerMacAddr, |
| eSIR_SME_UNEXPECTED_REQ_RESULT_CODE, NULL, |
| smesessionId, smetransactionId); |
| goto end; |
| } |
| |
| |
| if (((LIM_IS_STA_ROLE(psessionEntry) || |
| LIM_IS_BT_AMP_STA_ROLE(psessionEntry)) && |
| (psessionEntry->limSmeState == eLIM_SME_LINK_EST_STATE)) || |
| ((LIM_IS_IBSS_ROLE(psessionEntry) || |
| LIM_IS_AP_ROLE(psessionEntry) || |
| LIM_IS_BT_AMP_AP_ROLE(psessionEntry)) && |
| (psessionEntry->limSmeState == eLIM_SME_NORMAL_STATE))) { |
| // Trigger MLM_REMOVEKEYS_REQ |
| pMlmRemoveKeyReq = vos_mem_malloc(sizeof(tLimMlmRemoveKeyReq)); |
| if ( NULL == pMlmRemoveKeyReq ) |
| { |
| // Log error |
| limLog(pMac, LOGP, |
| FL("call to AllocateMemory failed for mlmRemoveKeysReq")); |
| |
| goto end; |
| } |
| |
| pMlmRemoveKeyReq->edType = (tAniEdType)pRemoveKeyReq->edType; |
| pMlmRemoveKeyReq->keyId = pRemoveKeyReq->keyId; |
| pMlmRemoveKeyReq->wepType = pRemoveKeyReq->wepType; |
| pMlmRemoveKeyReq->unicast = pRemoveKeyReq->unicast; |
| |
| /* Update PE session Id */ |
| pMlmRemoveKeyReq->sessionId = sessionId; |
| |
| vos_mem_copy( (tANI_U8 *) &pMlmRemoveKeyReq->peerMacAddr, |
| (tANI_U8 *) &pRemoveKeyReq->peerMacAddr, |
| sizeof(tSirMacAddr)); |
| |
| |
| limPostMlmMessage(pMac, |
| LIM_MLM_REMOVEKEY_REQ, |
| (tANI_U32 *) pMlmRemoveKeyReq); |
| } |
| else |
| { |
| limLog(pMac, LOGE, |
| FL("received unexpected SME_REMOVEKEY_REQ for role %d, state=%X"), |
| GET_LIM_SYSTEM_ROLE(psessionEntry), |
| psessionEntry->limSmeState); |
| |
| limSendSmeRemoveKeyRsp(pMac, |
| pRemoveKeyReq->peerMacAddr, |
| eSIR_SME_UNEXPECTED_REQ_RESULT_CODE,psessionEntry, |
| smesessionId,smetransactionId); |
| } |
| |
| end: |
| vos_mem_free( pRemoveKeyReq); |
| } /*** end __limProcessSmeRemoveKeyReq() ***/ |
| |
| void limProcessSmeGetScanChannelInfo(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) |
| { |
| tSirMsgQ mmhMsg; |
| tpSmeGetScanChnRsp pSirSmeRsp; |
| tANI_U16 len = 0; |
| tANI_U8 sessionId; |
| tANI_U16 transactionId; |
| |
| if(pMac->lim.scanChnInfo.numChnInfo > SIR_MAX_SUPPORTED_CHANNEL_LIST) |
| { |
| limLog(pMac, LOGW, FL("numChn is out of bounds %d"), |
| pMac->lim.scanChnInfo.numChnInfo); |
| pMac->lim.scanChnInfo.numChnInfo = SIR_MAX_SUPPORTED_CHANNEL_LIST; |
| } |
| |
| len = sizeof(tSmeGetScanChnRsp) + (pMac->lim.scanChnInfo.numChnInfo - 1) * sizeof(tLimScanChn); |
| pSirSmeRsp = vos_mem_malloc(len); |
| if ( NULL == pSirSmeRsp ) |
| { |
| /// Buffer not available. Log error |
| limLog(pMac, LOGP, |
| FL("call to AllocateMemory failed for JOIN/REASSOC_RSP")); |
| |
| return; |
| } |
| vos_mem_set(pSirSmeRsp, len, 0); |
| |
| pSirSmeRsp->mesgType = eWNI_SME_GET_SCANNED_CHANNEL_RSP; |
| pSirSmeRsp->mesgLen = len; |
| |
| if (pMac->fScanOffload) |
| { |
| limGetSessionInfo(pMac,(tANI_U8 *)pMsgBuf,&sessionId,&transactionId); |
| pSirSmeRsp->sessionId = sessionId; |
| } |
| else |
| pSirSmeRsp->sessionId = 0; |
| |
| if(pMac->lim.scanChnInfo.numChnInfo) |
| { |
| pSirSmeRsp->numChn = pMac->lim.scanChnInfo.numChnInfo; |
| vos_mem_copy( pSirSmeRsp->scanChn, pMac->lim.scanChnInfo.scanChn, |
| sizeof(tLimScanChn) * pSirSmeRsp->numChn); |
| } |
| //Clear the list |
| limRessetScanChannelInfo(pMac); |
| |
| mmhMsg.type = eWNI_SME_GET_SCANNED_CHANNEL_RSP; |
| mmhMsg.bodyptr = pSirSmeRsp; |
| mmhMsg.bodyval = 0; |
| |
| pMac->lim.gLimRspReqd = false; |
| MTRACE(macTrace(pMac, TRACE_CODE_TX_SME_MSG, NO_SESSION, mmhMsg.type)); |
| limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT); |
| } |
| |
| |
| void limProcessSmeGetAssocSTAsInfo(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) |
| { |
| tSirSmeGetAssocSTAsReq getAssocSTAsReq; |
| tpDphHashNode pStaDs = NULL; |
| tpPESession psessionEntry = NULL; |
| tSap_Event sapEvent; |
| tpWLAN_SAPEventCB pSapEventCallback = NULL; |
| tpSap_AssocMacAddr pAssocStasTemp = NULL;// #include "sapApi.h" |
| tANI_U8 sessionId = CSR_SESSION_ID_INVALID; |
| tANI_U8 assocId = 0; |
| tANI_U8 staCount = 0; |
| |
| vos_mem_zero(&getAssocSTAsReq, sizeof(getAssocSTAsReq)); |
| |
| if (!limIsSmeGetAssocSTAsReqValid(pMac, &getAssocSTAsReq, (tANI_U8 *) pMsgBuf)) |
| { |
| limLog(pMac, LOGE, |
| FL("received invalid eWNI_SME_GET_ASSOC_STAS_REQ message")); |
| return; |
| } |
| |
| switch (getAssocSTAsReq.modId) |
| { |
| case VOS_MODULE_ID_PE: |
| default: |
| break; |
| } |
| |
| // Get Associated stations from PE |
| // Find PE session Entry |
| if ((psessionEntry = peFindSessionByBssid(pMac, getAssocSTAsReq.bssId, &sessionId)) == NULL) |
| { |
| limLog(pMac, LOGE, |
| FL("session does not exist for given bssId")); |
| goto limAssocStaEnd; |
| } |
| |
| if (!LIM_IS_AP_ROLE(psessionEntry)) { |
| limLog(pMac, LOGE, |
| FL("Received unexpected message in state %X, in role %X"), |
| psessionEntry->limSmeState, GET_LIM_SYSTEM_ROLE(psessionEntry)); |
| goto limAssocStaEnd; |
| } |
| |
| // Retrieve values obtained in the request message |
| pSapEventCallback = (tpWLAN_SAPEventCB)getAssocSTAsReq.pSapEventCallback; |
| pAssocStasTemp = (tpSap_AssocMacAddr)getAssocSTAsReq.pAssocStasArray; |
| |
| if (NULL == pAssocStasTemp) |
| goto limAssocStaEnd; |
| |
| for (assocId = 0; assocId < psessionEntry->dph.dphHashTable.size; assocId++)// Softap dphHashTable.size = 8 |
| { |
| pStaDs = dphGetHashEntry(pMac, assocId, &psessionEntry->dph.dphHashTable); |
| |
| if (NULL == pStaDs) |
| continue; |
| |
| if (pStaDs->valid) |
| { |
| vos_mem_copy((tANI_U8 *)&pAssocStasTemp->staMac, |
| (tANI_U8 *)&pStaDs->staAddr, |
| sizeof(v_MACADDR_t)); // Mac address |
| pAssocStasTemp->assocId = (v_U8_t)pStaDs->assocId; // Association Id |
| pAssocStasTemp->staId = (v_U8_t)pStaDs->staIndex; // Station Id |
| |
| vos_mem_copy((tANI_U8 *)&pAssocStasTemp->supportedRates, |
| (tANI_U8 *)&pStaDs->supportedRates, |
| sizeof(tSirSupportedRates)); |
| pAssocStasTemp->ShortGI40Mhz = pStaDs->htShortGI40Mhz; |
| pAssocStasTemp->ShortGI20Mhz = pStaDs->htShortGI20Mhz; |
| pAssocStasTemp->Support40Mhz = pStaDs->htDsssCckRate40MHzSupport; |
| |
| limLog(pMac, LOG1, FL("dph Station Number = %d"), staCount+1); |
| limLog(pMac, LOG1, FL("MAC = " MAC_ADDRESS_STR), |
| MAC_ADDR_ARRAY(pStaDs->staAddr)); |
| limLog(pMac, LOG1, FL("Association Id = %d"),pStaDs->assocId); |
| limLog(pMac, LOG1, FL("Station Index = %d"),pStaDs->staIndex); |
| |
| pAssocStasTemp++; |
| staCount++; |
| } |
| } |
| |
| limAssocStaEnd: |
| // Call hdd callback with sap event to send the list of associated stations from PE |
| if (pSapEventCallback != NULL) |
| { |
| sapEvent.sapHddEventCode = eSAP_ASSOC_STA_CALLBACK_EVENT; |
| sapEvent.sapevt.sapAssocStaListEvent.module = VOS_MODULE_ID_PE; |
| sapEvent.sapevt.sapAssocStaListEvent.noOfAssocSta = staCount; |
| sapEvent.sapevt.sapAssocStaListEvent.pAssocStas = (tpSap_AssocMacAddr)getAssocSTAsReq.pAssocStasArray; |
| pSapEventCallback(&sapEvent, getAssocSTAsReq.pUsrContext); |
| } |
| } |
| |
| |
| /** |
| * limProcessSmeGetWPSPBCSessions |
| * |
| *FUNCTION: |
| * This function is called when query the WPS PBC overlap message is received |
| * |
| *LOGIC: |
| * This function parses get WPS PBC overlap information message and call callback to pass |
| * WPS PBC overlap information back to hdd. |
| *ASSUMPTIONS: |
| * |
| * |
| *NOTE: |
| * |
| * @param pMac Pointer to Global MAC structure |
| * @param pMsgBuf A pointer to WPS PBC overlap query message |
| * |
| * @return None |
| */ |
| void limProcessSmeGetWPSPBCSessions(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) |
| { |
| tSirSmeGetWPSPBCSessionsReq GetWPSPBCSessionsReq; |
| tpPESession psessionEntry = NULL; |
| tSap_Event sapEvent; |
| tpWLAN_SAPEventCB pSapEventCallback = NULL; |
| tANI_U8 sessionId = CSR_SESSION_ID_INVALID; |
| tSirMacAddr zeroMac = {0,0,0,0,0,0}; |
| |
| sapEvent.sapevt.sapGetWPSPBCSessionEvent.status = VOS_STATUS_E_FAULT; |
| |
| if (limIsSmeGetWPSPBCSessionsReqValid(pMac, &GetWPSPBCSessionsReq, (tANI_U8 *) pMsgBuf) != eSIR_SUCCESS) |
| { |
| limLog(pMac, LOGE, |
| FL("received invalid eWNI_SME_GET_ASSOC_STAS_REQ message")); |
| return; |
| } |
| |
| // Get Associated stations from PE |
| // Find PE session Entry |
| if ((psessionEntry = peFindSessionByBssid(pMac, GetWPSPBCSessionsReq.bssId, &sessionId)) == NULL) |
| { |
| limLog(pMac, LOGE, |
| FL("session does not exist for given bssId")); |
| goto limGetWPSPBCSessionsEnd; |
| } |
| |
| if (!LIM_IS_AP_ROLE(psessionEntry)) { |
| limLog(pMac, LOGE, |
| FL("Received unexpected message in role %X"), |
| GET_LIM_SYSTEM_ROLE(psessionEntry)); |
| goto limGetWPSPBCSessionsEnd; |
| } |
| |
| // Call hdd callback with sap event to send the WPS PBC overlap information |
| sapEvent.sapHddEventCode = eSAP_GET_WPSPBC_SESSION_EVENT; |
| sapEvent.sapevt.sapGetWPSPBCSessionEvent.module = VOS_MODULE_ID_PE; |
| |
| if (vos_mem_compare( zeroMac, GetWPSPBCSessionsReq.pRemoveMac, sizeof(tSirMacAddr))) |
| { //This is GetWpsSession call |
| |
| limGetWPSPBCSessions(pMac, |
| sapEvent.sapevt.sapGetWPSPBCSessionEvent.addr.bytes, sapEvent.sapevt.sapGetWPSPBCSessionEvent.UUID_E, |
| &sapEvent.sapevt.sapGetWPSPBCSessionEvent.wpsPBCOverlap, psessionEntry); |
| } |
| else |
| { |
| limRemovePBCSessions(pMac, GetWPSPBCSessionsReq.pRemoveMac,psessionEntry); |
| /* don't have to inform the HDD/Host */ |
| return; |
| } |
| |
| PELOG4(limLog(pMac, LOGE, FL("wpsPBCOverlap %d"), sapEvent.sapevt.sapGetWPSPBCSessionEvent.wpsPBCOverlap);) |
| PELOG4(limPrintMacAddr(pMac, sapEvent.sapevt.sapGetWPSPBCSessionEvent.addr.bytes, LOG4);) |
| |
| sapEvent.sapevt.sapGetWPSPBCSessionEvent.status = VOS_STATUS_SUCCESS; |
| |
| limGetWPSPBCSessionsEnd: |
| pSapEventCallback = (tpWLAN_SAPEventCB)GetWPSPBCSessionsReq.pSapEventCallback; |
| if (NULL != pSapEventCallback) |
| pSapEventCallback(&sapEvent, GetWPSPBCSessionsReq.pUsrContext); |
| } |
| |
| |
| |
| /** |
| * __limCounterMeasures() |
| * |
| * FUNCTION: |
| * This function is called to "implement" MIC counter measure |
| * and is *temporary* only |
| * |
| * LOGIC: on AP, disassoc all STA associated thru TKIP, |
| * we don't do the proper STA disassoc sequence since the |
| * BSS will be stoped anyway |
| * |
| *ASSUMPTIONS: |
| * |
| *NOTE: |
| * |
| * @param pMac Pointer to Global MAC structure |
| * @return None |
| */ |
| |
| static void |
| __limCounterMeasures(tpAniSirGlobal pMac, tpPESession psessionEntry) |
| { |
| tSirMacAddr mac = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; |
| if (LIM_IS_AP_ROLE(psessionEntry) || LIM_IS_BT_AMP_AP_ROLE(psessionEntry) || |
| LIM_IS_BT_AMP_STA_ROLE(psessionEntry)) |
| limSendDisassocMgmtFrame(pMac, eSIR_MAC_MIC_FAILURE_REASON, mac, psessionEntry, FALSE); |
| } |
| |
| |
| void |
| limProcessTkipCounterMeasures(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) |
| { |
| tSirSmeTkipCntrMeasReq tkipCntrMeasReq; |
| tpPESession psessionEntry; |
| tANI_U8 sessionId; //PE sessionId |
| |
| if ( limTkipCntrMeasReqSerDes( pMac, &tkipCntrMeasReq, (tANI_U8 *) pMsgBuf ) != eSIR_SUCCESS ) |
| { |
| limLog(pMac, LOGE, |
| FL("received invalid eWNI_SME_TKIP_CNTR_MEAS_REQ message")); |
| return; |
| } |
| |
| if ( NULL == (psessionEntry = peFindSessionByBssid( pMac, tkipCntrMeasReq.bssId, &sessionId )) ) |
| { |
| limLog(pMac, LOGE, FL("session does not exist for given BSSID ")); |
| return; |
| } |
| |
| if ( tkipCntrMeasReq.bEnable ) |
| { |
| __limCounterMeasures( pMac, psessionEntry ); |
| } |
| |
| psessionEntry->bTkipCntrMeasActive = tkipCntrMeasReq.bEnable; |
| } |
| |
| |
| static void |
| __limHandleSmeStopBssRequest(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) |
| { |
| tSirSmeStopBssReq stopBssReq; |
| tSirRetStatus status; |
| tLimSmeStates prevState; |
| tANI_U8 sessionId; //PE sessionId |
| tpPESession psessionEntry; |
| tANI_U8 smesessionId; |
| tANI_U16 smetransactionId; |
| tANI_U8 i = 0; |
| tpDphHashNode pStaDs = NULL; |
| limGetSessionInfo(pMac,(tANI_U8 *)pMsgBuf,&smesessionId,&smetransactionId); |
| |
| |
| |
| if ((limStopBssReqSerDes(pMac, &stopBssReq, (tANI_U8 *) pMsgBuf) != eSIR_SUCCESS) || |
| !limIsSmeStopBssReqValid(pMsgBuf)) |
| { |
| PELOGW(limLog(pMac, LOGW, FL("received invalid SME_STOP_BSS_REQ message"));) |
| /// Send Stop BSS response to host |
| limSendSmeRsp(pMac, eWNI_SME_STOP_BSS_RSP, eSIR_SME_INVALID_PARAMETERS,smesessionId,smetransactionId); |
| return; |
| } |
| |
| |
| if((psessionEntry = peFindSessionByBssid(pMac,stopBssReq.bssId,&sessionId)) == NULL) |
| { |
| limLog(pMac, LOGW, FL("session does not exist for given BSSID ")); |
| limSendSmeRsp(pMac, eWNI_SME_STOP_BSS_RSP, eSIR_SME_INVALID_PARAMETERS,smesessionId,smetransactionId); |
| return; |
| } |
| |
| #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM //FEATURE_WLAN_DIAG_SUPPORT |
| limDiagEventReport(pMac, WLAN_PE_DIAG_STOP_BSS_REQ_EVENT, psessionEntry, 0, 0); |
| #endif //FEATURE_WLAN_DIAG_SUPPORT |
| |
| |
| if ((psessionEntry->limSmeState != eLIM_SME_NORMAL_STATE) || /* Added For BT -AMP Support */ |
| LIM_IS_STA_ROLE(psessionEntry)) { |
| /** |
| * Should not have received STOP_BSS_REQ in states |
| * other than 'normal' state or on STA in Infrastructure |
| * mode. Log error and return response to host. |
| */ |
| limLog(pMac, LOGE, |
| FL("received unexpected SME_STOP_BSS_REQ in state %X, for role %d"), |
| psessionEntry->limSmeState, GET_LIM_SYSTEM_ROLE(psessionEntry)); |
| /// Send Stop BSS response to host |
| limSendSmeRsp(pMac, eWNI_SME_STOP_BSS_RSP, eSIR_SME_UNEXPECTED_REQ_RESULT_CODE,smesessionId,smetransactionId); |
| return; |
| } |
| |
| if (LIM_IS_AP_ROLE(psessionEntry)) { |
| limWPSPBCClose(pMac, psessionEntry); |
| } |
| PELOGW(limLog(pMac, LOGW, FL("RECEIVED STOP_BSS_REQ with reason code=%d"), stopBssReq.reasonCode);) |
| |
| prevState = psessionEntry->limSmeState; |
| |
| psessionEntry->limSmeState = eLIM_SME_IDLE_STATE; |
| MTRACE(macTrace(pMac, TRACE_CODE_SME_STATE, psessionEntry->peSessionId, psessionEntry->limSmeState)); |
| |
| /* Update SME session Id and Transaction Id */ |
| psessionEntry->smeSessionId = smesessionId; |
| psessionEntry->transactionId = smetransactionId; |
| |
| /* BTAMP_STA, STA_IN_IBSS and NDI should NOT send Disassoc frame */ |
| if (!LIM_IS_IBSS_ROLE(psessionEntry) && |
| !LIM_IS_BT_AMP_STA_ROLE(psessionEntry) && |
| !LIM_IS_NDI_ROLE(psessionEntry)) { |
| tSirMacAddr bcAddr = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; |
| if ((stopBssReq.reasonCode == eSIR_SME_MIC_COUNTER_MEASURES)) |
| // Send disassoc all stations associated thru TKIP |
| __limCounterMeasures(pMac,psessionEntry); |
| else |
| limSendDisassocMgmtFrame(pMac, |
| eSIR_MAC_DEAUTH_LEAVING_BSS_REASON, |
| bcAddr, psessionEntry, FALSE); |
| } |
| |
| if (!LIM_IS_NDI_ROLE(psessionEntry)) { |
| /* Free the buffer allocated in START_BSS_REQ */ |
| vos_mem_free(psessionEntry->addIeParams.probeRespData_buff); |
| psessionEntry->addIeParams.probeRespDataLen = 0; |
| psessionEntry->addIeParams.probeRespData_buff = NULL; |
| |
| vos_mem_free(psessionEntry->addIeParams.assocRespData_buff); |
| psessionEntry->addIeParams.assocRespDataLen = 0; |
| psessionEntry->addIeParams.assocRespData_buff = NULL; |
| |
| vos_mem_free(psessionEntry->addIeParams.probeRespBCNData_buff); |
| psessionEntry->addIeParams.probeRespBCNDataLen = 0; |
| psessionEntry->addIeParams.probeRespBCNData_buff = NULL; |
| |
| /* |
| * limDelBss is also called as part of coalescing, |
| * when we send DEL BSS followed by Add Bss msg. |
| */ |
| pMac->lim.gLimIbssCoalescingHappened = false; |
| } |
| for(i = 1 ; i < pMac->lim.gLimAssocStaLimit ; i++) |
| { |
| pStaDs = dphGetHashEntry(pMac, i, &psessionEntry->dph.dphHashTable); |
| if (NULL == pStaDs) |
| continue; |
| status = limDelSta(pMac, pStaDs, false, psessionEntry) ; |
| if(eSIR_SUCCESS == status) |
| { |
| limDeleteDphHashEntry(pMac, pStaDs->staAddr, pStaDs->assocId, psessionEntry) ; |
| limReleasePeerIdx(pMac, pStaDs->assocId, psessionEntry) ; |
| } |
| else |
| { |
| limLog(pMac, LOGE, FL("limDelSta failed with Status : %d"), status); |
| VOS_ASSERT(0) ; |
| } |
| } |
| /* send a delBss to HAL and wait for a response */ |
| status = limDelBss(pMac, NULL,psessionEntry->bssIdx,psessionEntry); |
| |
| if (status != eSIR_SUCCESS) |
| { |
| PELOGE(limLog(pMac, LOGE, FL("delBss failed for bss %d"), psessionEntry->bssIdx);) |
| psessionEntry->limSmeState= prevState; |
| |
| MTRACE(macTrace(pMac, TRACE_CODE_SME_STATE, psessionEntry->peSessionId, psessionEntry->limSmeState)); |
| |
| limSendSmeRsp(pMac, eWNI_SME_STOP_BSS_RSP, eSIR_SME_STOP_BSS_FAILURE,smesessionId,smetransactionId); |
| } |
| } |
| |
| |
| /**-------------------------------------------------------------- |
| \fn __limProcessSmeStopBssReq |
| |
| \brief Wrapper for the function __limHandleSmeStopBssRequest |
| This message will be defered until softmac come out of |
| scan mode. Message should be handled even if we have |
| detected radar in the current operating channel. |
| \param pMac |
| \param pMsg |
| |
| \return TRUE - If we consumed the buffer |
| FALSE - If have defered the message. |
| ---------------------------------------------------------------*/ |
| static tANI_BOOLEAN |
| __limProcessSmeStopBssReq(tpAniSirGlobal pMac, tpSirMsgQ pMsg) |
| { |
| if (__limIsDeferedMsgForLearn(pMac, pMsg)) |
| { |
| /** |
| * If message defered, buffer is not consumed yet. |
| * So return false |
| */ |
| return eANI_BOOLEAN_FALSE; |
| } |
| __limHandleSmeStopBssRequest(pMac, (tANI_U32 *) pMsg->bodyptr); |
| return eANI_BOOLEAN_TRUE; |
| } /*** end __limProcessSmeStopBssReq() ***/ |
| |
| |
| void limProcessSmeDelBssRsp( |
| tpAniSirGlobal pMac, |
| tANI_U32 body,tpPESession psessionEntry) |
| { |
| |
| (void) body; |
| SET_LIM_PROCESS_DEFD_MESGS(pMac, true); |
| limIbssDelete(pMac,psessionEntry); |
| dphHashTableClassInit(pMac, &psessionEntry->dph.dphHashTable); |
| limDeletePreAuthList(pMac); |
| limSendSmeRsp(pMac, eWNI_SME_STOP_BSS_RSP, eSIR_SME_SUCCESS,psessionEntry->smeSessionId,psessionEntry->transactionId); |
| return; |
| } |
| |
| |
| /**--------------------------------------------------------------- |
| \fn __limProcessSmeAssocCnfNew |
| \brief This function handles SME_ASSOC_CNF/SME_REASSOC_CNF |
| \ in BTAMP AP. |
| \ |
| \param pMac |
| \param msgType - message type |
| \param pMsgBuf - a pointer to the SME message buffer |
| \return None |
| ------------------------------------------------------------------*/ |
| |
| void |
| __limProcessSmeAssocCnfNew(tpAniSirGlobal pMac, tANI_U32 msgType, tANI_U32 *pMsgBuf) |
| { |
| tSirSmeAssocCnf assocCnf; |
| tpDphHashNode pStaDs = NULL; |
| tpPESession psessionEntry= NULL; |
| tANI_U8 sessionId; |
| |
| |
| if(pMsgBuf == NULL) |
| { |
| limLog(pMac, LOGE, FL("pMsgBuf is NULL ")); |
| goto end; |
| } |
| |
| if ((limAssocCnfSerDes(pMac, &assocCnf, (tANI_U8 *) pMsgBuf) == eSIR_FAILURE) || |
| !__limIsSmeAssocCnfValid(&assocCnf)) |
| { |
| limLog(pMac, LOGE, FL("Received invalid SME_RE(ASSOC)_CNF message ")); |
| goto end; |
| } |
| |
| if((psessionEntry = peFindSessionByBssid(pMac, assocCnf.bssId, &sessionId))== NULL) |
| { |
| limLog(pMac, LOGE, FL("session does not exist for given bssId")); |
| goto end; |
| } |
| |
| if ((!LIM_IS_AP_ROLE(psessionEntry) && |
| !LIM_IS_BT_AMP_AP_ROLE(psessionEntry)) || |
| ((psessionEntry->limSmeState != eLIM_SME_NORMAL_STATE) && |
| (psessionEntry->limSmeState != eLIM_SME_NORMAL_CHANNEL_SCAN_STATE))) { |
| limLog(pMac, LOGE, |
| FL("Received unexpected message %X in state %X, in role %X"), |
| msgType, psessionEntry->limSmeState, |
| GET_LIM_SYSTEM_ROLE(psessionEntry)); |
| goto end; |
| } |
| |
| pStaDs = dphGetHashEntry(pMac, assocCnf.aid, &psessionEntry->dph.dphHashTable); |
| |
| if (pStaDs == NULL) |
| { |
| limLog(pMac, LOGE, |
| FL("Received invalid message %X due to no STA context" |
| "for aid %d, peer "), |
| msgType, assocCnf.aid); |
| limPrintMacAddr(pMac, assocCnf.peerMacAddr, LOG1); |
| |
| /* |
| ** send a DISASSOC_IND message to WSM to make sure |
| ** the state in WSM and LIM is the same |
| **/ |
| limSendSmeDisassocNtf( pMac, assocCnf.peerMacAddr, eSIR_SME_STA_NOT_ASSOCIATED, |
| eLIM_PEER_ENTITY_DISASSOC, assocCnf.aid,psessionEntry->smeSessionId,psessionEntry->transactionId,psessionEntry); |
| goto end; |
| } |
| if ((pStaDs && |
| (( !vos_mem_compare( (tANI_U8 *) pStaDs->staAddr, |
| (tANI_U8 *) assocCnf.peerMacAddr, |
| sizeof(tSirMacAddr)) ) || |
| (pStaDs->mlmStaContext.mlmState != eLIM_MLM_WT_ASSOC_CNF_STATE) || |
| ((pStaDs->mlmStaContext.subType == LIM_ASSOC) && |
| (msgType != eWNI_SME_ASSOC_CNF)) || |
| ((pStaDs->mlmStaContext.subType == LIM_REASSOC) && |
| (msgType != eWNI_SME_ASSOC_CNF))))) // since softap is passing this as ASSOC_CNF and subtype differs |
| { |
| limLog(pMac, LOG1, |
| FL("Received invalid message %X due to peerMacAddr mismatched" |
| "or not in eLIM_MLM_WT_ASSOC_CNF_STATE state, for aid %d, peer " |
| "StaD mlmState : %d"), |
| msgType, assocCnf.aid, pStaDs->mlmStaContext.mlmState); |
| limPrintMacAddr(pMac, assocCnf.peerMacAddr, LOG1); |
| goto end; |
| } |
| |
| /* |
| ** Deactivate/delet CNF_WAIT timer since ASSOC_CNF |
| ** has been received |
| **/ |
| limLog(pMac, LOG1, FL("Received SME_ASSOC_CNF. Delete Timer")); |
| limDeactivateAndChangePerStaIdTimer(pMac, eLIM_CNF_WAIT_TIMER, pStaDs->assocId); |
| |
| if (assocCnf.statusCode == eSIR_SME_SUCCESS) |
| { |
| /* In BTAMP-AP, PE already finished the WDA_ADD_STA sequence |
| * when it had received Assoc Request frame. Now, PE just needs to send |
| * Association Response frame to the requesting BTAMP-STA. |
| */ |
| pStaDs->mlmStaContext.mlmState = eLIM_MLM_LINK_ESTABLISHED_STATE; |
| limLog(pMac, LOG1, FL("sending Assoc Rsp frame to STA (assoc id=%d) "), pStaDs->assocId); |
| limSendAssocRspMgmtFrame( pMac, eSIR_SUCCESS, pStaDs->assocId, pStaDs->staAddr, |
| pStaDs->mlmStaContext.subType, pStaDs, psessionEntry); |
| goto end; |
| } // (assocCnf.statusCode == eSIR_SME_SUCCESS) |
| else |
| { |
| // SME_ASSOC_CNF status is non-success, so STA is not allowed to be associated |
| /*Since the HAL sta entry is created for denied STA we need to remove this HAL entry.So to do that set updateContext to 1*/ |
| if(!pStaDs->mlmStaContext.updateContext) |
| pStaDs->mlmStaContext.updateContext = 1; |
| limLog(pMac, LOG1, FL("Receive Assoc Cnf with status Code : %d(assoc id=%d) "), |
| assocCnf.statusCode, pStaDs->assocId); |
| limRejectAssociation(pMac, pStaDs->staAddr, |
| pStaDs->mlmStaContext.subType, |
| true, pStaDs->mlmStaContext.authType, |
| pStaDs->assocId, true, |
| eSIR_MAC_UNSPEC_FAILURE_STATUS, psessionEntry); |
| } |
| |
| end: |
| if((psessionEntry != NULL) && (pStaDs != NULL)) |
| { |
| if ( psessionEntry->parsedAssocReq[pStaDs->assocId] != NULL ) |
| { |
| if ( ((tpSirAssocReq)(psessionEntry->parsedAssocReq[pStaDs->assocId]))->assocReqFrame) |
| { |
| vos_mem_free(((tpSirAssocReq) |
| (psessionEntry->parsedAssocReq[pStaDs->assocId]))->assocReqFrame); |
| ((tpSirAssocReq)(psessionEntry->parsedAssocReq[pStaDs->assocId]))->assocReqFrame = NULL; |
| } |
| |
| vos_mem_free(psessionEntry->parsedAssocReq[pStaDs->assocId]); |
| psessionEntry->parsedAssocReq[pStaDs->assocId] = NULL; |
| } |
| } |
| |
| } /*** end __limProcessSmeAssocCnfNew() ***/ |
| |
| #ifdef SAP_AUTH_OFFLOAD |
| /** |
| * __lim_process_sme_assoc_offload_cnf() station connect confirm |
| * @pMac: SirGlobal handler |
| * @msgType: message type |
| * @pMsgBuf: message body |
| * |
| * This function handles the station connect confirm of |
| * Software AP authentication offload feature |
| * |
| * Return: None |
| */ |
| static void |
| __lim_process_sme_assoc_offload_cnf(tpAniSirGlobal pmac, |
| tANI_U32 msg_type, |
| tANI_U32 *pmsg_buf) |
| { |
| tSirSmeAssocCnf assoc_cnf; |
| tpDphHashNode sta_ds = NULL; |
| tpPESession psession_entry= NULL; |
| tANI_U8 session_id; |
| tANI_U16 aid=0; |
| |
| if(pmsg_buf == NULL) { |
| limLog(pmac, LOGE, FL("pmsg_buf is NULL ")); |
| goto end; |
| } |
| |
| if ((limAssocCnfSerDes(pmac, &assoc_cnf, (tANI_U8 *) pmsg_buf) == |
| eSIR_FAILURE) || !__limIsSmeAssocCnfValid(&assoc_cnf)) { |
| limLog(pmac, LOGE, FL("Received invalid SME_RE(ASSOC)_CNF message ")); |
| goto end; |
| } |
| |
| if((psession_entry = |
| peFindSessionByBssid(pmac, assoc_cnf.bssId, &session_id))== NULL) { |
| limLog(pmac, LOGE, FL("session does not exist for given bssId")); |
| goto end; |
| } |
| |
| if ((!LIM_IS_AP_ROLE(psession_entry) && |
| !LIM_IS_BT_AMP_AP_ROLE(psession_entry)) || |
| ((psession_entry->limSmeState != eLIM_SME_NORMAL_STATE) && |
| (psession_entry->limSmeState != eLIM_SME_NORMAL_CHANNEL_SCAN_STATE))) { |
| limLog(pmac, LOGE, |
| FL("Received unexpected message %X in state %X, in role %X"), |
| msg_type, psession_entry->limSmeState, |
| GET_LIM_SYSTEM_ROLE(psession_entry)); |
| goto end; |
| } |
| |
| sta_ds = dphGetHashEntry(pmac, |
| assoc_cnf.aid, |
| &psession_entry->dph.dphHashTable); |
| if (sta_ds != NULL) { |
| aid = sta_ds->assocId; |
| limDeactivateAndChangePerStaIdTimer(pmac, |
| eLIM_CNF_WAIT_TIMER, |
| aid); |
| } |
| |
| end: |
| if((psession_entry != NULL) && (sta_ds != NULL)) { |
| if ( psession_entry->parsedAssocReq[aid] != NULL ) { |
| if ( ((tpSirAssocReq) |
| (psession_entry->parsedAssocReq[aid]))->assocReqFrame) { |
| vos_mem_free(((tpSirAssocReq) |
| (psession_entry->parsedAssocReq[aid]))->assocReqFrame); |
| ((tpSirAssocReq) |
| (psession_entry->parsedAssocReq[aid]))->assocReqFrame = |
| NULL; |
| } |
| vos_mem_free(psession_entry->parsedAssocReq[aid]); |
| psession_entry->parsedAssocReq[aid] = NULL; |
| } |
| } |
| |
| } /*** end __lim_process_sme_assoc_offload_cnf() ***/ |
| #endif /* SAP_AUTH_OFFLOAD */ |
| |
| static void |
| __limProcessSmeAddtsReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) |
| { |
| tpDphHashNode pStaDs; |
| tSirMacAddr peerMac; |
| tpSirAddtsReq pSirAddts; |
| tANI_U32 timeout; |
| tpPESession psessionEntry; |
| tANI_U8 sessionId; //PE sessionId |
| tANI_U8 smesessionId; |
| tANI_U16 smetransactionId; |
| |
| |
| if(pMsgBuf == NULL) |
| { |
| limLog(pMac, LOGE,FL("Buffer is Pointing to NULL")); |
| return; |
| } |
| |
| limGetSessionInfo(pMac,(tANI_U8 *)pMsgBuf,&smesessionId,&smetransactionId); |
| |
| pSirAddts = (tpSirAddtsReq) pMsgBuf; |
| |
| if((psessionEntry = peFindSessionByBssid(pMac, pSirAddts->bssId,&sessionId))== NULL) |
| { |
| limLog(pMac, LOGE, "Session Does not exist for given bssId"); |
| return; |
| } |
| #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM //FEATURE_WLAN_DIAG_SUPPORT |
| limDiagEventReport(pMac, WLAN_PE_DIAG_ADDTS_REQ_EVENT, psessionEntry, 0, 0); |
| #endif //FEATURE_WLAN_DIAG_SUPPORT |
| |
| |
| |
| /* if sta |
| * - verify assoc state |
| * - send addts request to ap |
| * - wait for addts response from ap |
| * if ap, just ignore with error log |
| */ |
| PELOG1(limLog(pMac, LOG1, |
| FL("Received SME_ADDTS_REQ (TSid %d, UP %d)"), |
| pSirAddts->req.tspec.tsinfo.traffic.tsid, |
| pSirAddts->req.tspec.tsinfo.traffic.userPrio);) |
| |
| if (!LIM_IS_STA_ROLE(psessionEntry) && |
| !LIM_IS_BT_AMP_STA_ROLE(psessionEntry)) { |
| PELOGE(limLog(pMac, LOGE, "AddTs received on AP - ignoring");) |
| limSendSmeAddtsRsp(pMac, pSirAddts->rspReqd, eSIR_FAILURE, psessionEntry, pSirAddts->req.tspec, |
| smesessionId,smetransactionId); |
| return; |
| } |
| |
| pStaDs = dphGetHashEntry(pMac, DPH_STA_HASH_INDEX_PEER, &psessionEntry->dph.dphHashTable); |
| |
| if(pStaDs == NULL) |
| { |
| PELOGE(limLog(pMac, LOGE, "Cannot find AP context for addts req");) |
| limSendSmeAddtsRsp(pMac, pSirAddts->rspReqd, eSIR_FAILURE, psessionEntry, pSirAddts->req.tspec, |
| smesessionId,smetransactionId); |
| return; |
| } |
| |
| if ((! pStaDs->valid) || |
| (pStaDs->mlmStaContext.mlmState != eLIM_MLM_LINK_ESTABLISHED_STATE)) |
| { |
| PELOGE(limLog(pMac, LOGE, "AddTs received in invalid MLM state");) |
| limSendSmeAddtsRsp(pMac, pSirAddts->rspReqd, eSIR_FAILURE, psessionEntry, pSirAddts->req.tspec, |
| smesessionId,smetransactionId); |
| return; |
| } |
| |
| pSirAddts->req.wsmTspecPresent = 0; |
| pSirAddts->req.wmeTspecPresent = 0; |
| pSirAddts->req.lleTspecPresent = 0; |
| |
| if ((pStaDs->wsmEnabled) && |
| (pSirAddts->req.tspec.tsinfo.traffic.accessPolicy != SIR_MAC_ACCESSPOLICY_EDCA)) |
| pSirAddts->req.wsmTspecPresent = 1; |
| else if (pStaDs->wmeEnabled) |
| pSirAddts->req.wmeTspecPresent = 1; |
| else if (pStaDs->lleEnabled) |
| pSirAddts->req.lleTspecPresent = 1; |
| else |
| { |
| PELOGW(limLog(pMac, LOGW, FL("ADDTS_REQ ignore - qos is disabled"));) |
| limSendSmeAddtsRsp(pMac, pSirAddts->rspReqd, eSIR_FAILURE, psessionEntry, pSirAddts->req.tspec, |
| smesessionId,smetransactionId); |
| return; |
| } |
| |
| if ((psessionEntry->limSmeState != eLIM_SME_ASSOCIATED_STATE) && |
| (psessionEntry->limSmeState != eLIM_SME_LINK_EST_STATE)) |
| { |
| limLog(pMac, LOGE, "AddTs received in invalid LIMsme state (%d)", |
| psessionEntry->limSmeState); |
| limSendSmeAddtsRsp(pMac, pSirAddts->rspReqd, eSIR_FAILURE, psessionEntry, pSirAddts->req.tspec, |
| smesessionId,smetransactionId); |
| return; |
| } |
| |
| if (pMac->lim.gLimAddtsSent) |
| { |
| limLog(pMac, LOGE, "Addts (token %d, tsid %d, up %d) is still pending", |
| pMac->lim.gLimAddtsReq.req.dialogToken, |
| pMac->lim.gLimAddtsReq.req.tspec.tsinfo.traffic.tsid, |
| pMac->lim.gLimAddtsReq.req.tspec.tsinfo.traffic.userPrio); |
| limSendSmeAddtsRsp(pMac, pSirAddts->rspReqd, eSIR_FAILURE, psessionEntry, pSirAddts->req.tspec, |
| smesessionId,smetransactionId); |
| return; |
| } |
| |
| sirCopyMacAddr(peerMac,psessionEntry->bssId); |
| |
| // save the addts request |
| pMac->lim.gLimAddtsSent = true; |
| vos_mem_copy( (tANI_U8 *) &pMac->lim.gLimAddtsReq, (tANI_U8 *) pSirAddts, sizeof(tSirAddtsReq)); |
| |
| // ship out the message now |
| limSendAddtsReqActionFrame(pMac, peerMac, &pSirAddts->req, |
| psessionEntry); |
| PELOG1(limLog(pMac, LOG1, "Sent ADDTS request");) |
| |
| // start a timer to wait for the response |
| if (pSirAddts->timeout) |
| timeout = pSirAddts->timeout; |
| else if (wlan_cfgGetInt(pMac, WNI_CFG_ADDTS_RSP_TIMEOUT, &timeout) != eSIR_SUCCESS) |
| { |
| limLog(pMac, LOGP, FL("Unable to get Cfg param %d (Addts Rsp Timeout)"), |
| WNI_CFG_ADDTS_RSP_TIMEOUT); |
| return; |
| } |
| |
| timeout = SYS_MS_TO_TICKS(timeout); |
| if (tx_timer_change(&pMac->lim.limTimers.gLimAddtsRspTimer, timeout, 0) != TX_SUCCESS) |
| { |
| limLog(pMac, LOGP, FL("AddtsRsp timer change failed!")); |
| return; |
| } |
| pMac->lim.gLimAddtsRspTimerCount++; |
| if (tx_timer_change_context(&pMac->lim.limTimers.gLimAddtsRspTimer, |
| pMac->lim.gLimAddtsRspTimerCount) != TX_SUCCESS) |
| { |
| limLog(pMac, LOGP, FL("AddtsRsp timer change failed!")); |
| return; |
| } |
| MTRACE(macTrace(pMac, TRACE_CODE_TIMER_ACTIVATE, psessionEntry->peSessionId, eLIM_ADDTS_RSP_TIMER)); |
| |
| //add the sessionId to the timer object |
| pMac->lim.limTimers.gLimAddtsRspTimer.sessionId = sessionId; |
| if (tx_timer_activate(&pMac->lim.limTimers.gLimAddtsRspTimer) != TX_SUCCESS) |
| { |
| limLog(pMac, LOGP, FL("AddtsRsp timer activation failed!")); |
| return; |
| } |
| return; |
| } |
| |
| |
| static void |
| __limProcessSmeDeltsReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) |
| { |
| tSirMacAddr peerMacAddr; |
| tANI_U8 ac; |
| tSirMacTSInfo *pTsinfo; |
| tpSirDeltsReq pDeltsReq = (tpSirDeltsReq) pMsgBuf; |
| tpDphHashNode pStaDs = NULL; |
| tpPESession psessionEntry; |
| tANI_U8 sessionId; |
| tANI_U32 status = eSIR_SUCCESS; |
| tANI_U8 smesessionId; |
| tANI_U16 smetransactionId; |
| |
| limGetSessionInfo(pMac,(tANI_U8 *)pMsgBuf,&smesessionId,&smetransactionId); |
| |
| if((psessionEntry = peFindSessionByBssid(pMac, pDeltsReq->bssId, &sessionId))== NULL) |
| { |
| limLog(pMac, LOGE, "Session Does not exist for given bssId"); |
| status = eSIR_FAILURE; |
| goto end; |
| } |
| #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM //FEATURE_WLAN_DIAG_SUPPORT |
| limDiagEventReport(pMac, WLAN_PE_DIAG_DELTS_REQ_EVENT, psessionEntry, 0, 0); |
| #endif //FEATURE_WLAN_DIAG_SUPPORT |
| |
| |
| if (eSIR_SUCCESS != limValidateDeltsReq(pMac, pDeltsReq, peerMacAddr,psessionEntry)) |
| { |
| PELOGE(limLog(pMac, LOGE, FL("limValidateDeltsReq failed"));) |
| status = eSIR_FAILURE; |
| limSendSmeDeltsRsp(pMac, pDeltsReq, eSIR_FAILURE,psessionEntry,smesessionId,smetransactionId); |
| return; |
| } |
| |
| PELOG1(limLog(pMac, LOG1, FL("Sent DELTS request to station with " |
| "assocId = %d MacAddr = "MAC_ADDRESS_STR), |
| pDeltsReq->aid, MAC_ADDR_ARRAY(peerMacAddr));) |
| |
| limSendDeltsReqActionFrame(pMac, peerMacAddr, pDeltsReq->req.wmeTspecPresent, &pDeltsReq->req.tsinfo, &pDeltsReq->req.tspec, |
| psessionEntry); |
| |
| pTsinfo = pDeltsReq->req.wmeTspecPresent ? &pDeltsReq->req.tspec.tsinfo : &pDeltsReq->req.tsinfo; |
| |
| /* We've successfully send DELTS frame to AP. Update the |
| * dynamic UAPSD mask. The AC for this TSPEC to be deleted |
| * is no longer trigger enabled or delivery enabled |
| */ |
| if(!pMac->psOffloadEnabled) |
| { |
| limSetTspecUapsdMask(pMac, pTsinfo, CLEAR_UAPSD_MASK); |
| |
| /* We're deleting the TSPEC, so this particular AC is no longer |
| * admitted. PE needs to downgrade the EDCA |
| * parameters(for the AC for which TS is being deleted) to the |
| * next best AC for which ACM is not enabled, and send the |
| * updated values to HAL. |
| */ |
| ac = upToAc(pTsinfo->traffic.userPrio); |
| |
| if(pTsinfo->traffic.direction == SIR_MAC_DIRECTION_UPLINK) |
| { |
| pMac->lim.gAcAdmitMask[SIR_MAC_DIRECTION_UPLINK] &= ~(1 << ac); |
| } |
| else if(pTsinfo->traffic.direction == SIR_MAC_DIRECTION_DNLINK) |
| { |
| pMac->lim.gAcAdmitMask[SIR_MAC_DIRECTION_DNLINK] &= ~(1 << ac); |
| } |
| else if(pTsinfo->traffic.direction == SIR_MAC_DIRECTION_BIDIR) |
| { |
| pMac->lim.gAcAdmitMask[SIR_MAC_DIRECTION_UPLINK] &= ~(1 << ac); |
| pMac->lim.gAcAdmitMask[SIR_MAC_DIRECTION_DNLINK] &= ~(1 << ac); |
| } |
| } |
| else |
| { |
| limSetTspecUapsdMaskPerSession(pMac, psessionEntry, |
| pTsinfo, CLEAR_UAPSD_MASK); |
| |
| /* We're deleting the TSPEC, so this particular AC is no longer |
| * admitted. PE needs to downgrade the EDCA |
| * parameters(for the AC for which TS is being deleted) to the |
| * next best AC for which ACM is not enabled, and send the |
| * updated values to HAL. |
| */ |
| ac = upToAc(pTsinfo->traffic.userPrio); |
| |
| if(pTsinfo->traffic.direction == SIR_MAC_DIRECTION_UPLINK) |
| { |
| psessionEntry->gAcAdmitMask[SIR_MAC_DIRECTION_UPLINK] &= ~(1 << ac); |
| } |
| else if(pTsinfo->traffic.direction == SIR_MAC_DIRECTION_DNLINK) |
| { |
| psessionEntry->gAcAdmitMask[SIR_MAC_DIRECTION_DNLINK] &= ~(1 << ac); |
| } |
| else if(pTsinfo->traffic.direction == SIR_MAC_DIRECTION_BIDIR) |
| { |
| psessionEntry->gAcAdmitMask[SIR_MAC_DIRECTION_UPLINK] &= ~(1 << ac); |
| psessionEntry->gAcAdmitMask[SIR_MAC_DIRECTION_DNLINK] &= ~(1 << ac); |
| } |
| } |
| |
| limSetActiveEdcaParams(pMac, psessionEntry->gLimEdcaParams, psessionEntry); |
| |
| pStaDs = dphGetHashEntry(pMac, DPH_STA_HASH_INDEX_PEER, &psessionEntry->dph.dphHashTable); |
| if (pStaDs != NULL) |
| { |
| limSendEdcaParams(pMac, psessionEntry->gLimEdcaParamsActive, |
| pStaDs->bssId); |
| status = eSIR_SUCCESS; |
| } |
| else |
| { |
| limLog(pMac, LOGE, FL("Self entry missing in Hash Table ")); |
| status = eSIR_FAILURE; |
| } |
| #ifdef FEATURE_WLAN_ESE |
| #ifdef FEATURE_WLAN_ESE_UPLOAD |
| limSendSmeTsmIEInd(pMac, psessionEntry, 0, 0, 0); |
| #else |
| limDeactivateAndChangeTimer(pMac,eLIM_TSM_TIMER); |
| #endif /* FEATURE_WLAN_ESE_UPLOAD */ |
| #endif |
| |
| // send an sme response back |
| end: |
| limSendSmeDeltsRsp(pMac, pDeltsReq, eSIR_SUCCESS,psessionEntry,smesessionId,smetransactionId); |
| } |
| |
| |
| void |
| limProcessSmeAddtsRspTimeout(tpAniSirGlobal pMac, tANI_U32 param) |
| { |
| //fetch the sessionEntry based on the sessionId |
| tpPESession psessionEntry; |
| if((psessionEntry = peFindSessionBySessionId(pMac, pMac->lim.limTimers.gLimAddtsRspTimer.sessionId))== NULL) |
| { |
| limLog(pMac, LOGP,FL("Session Does not exist for given sessionID")); |
| return; |
| } |
| |
| if (!LIM_IS_STA_ROLE(psessionEntry) && |
| !LIM_IS_BT_AMP_STA_ROLE(psessionEntry)) { |
| limLog(pMac, LOGW, "AddtsRspTimeout in non-Sta role (%d)", |
| GET_LIM_SYSTEM_ROLE(psessionEntry)); |
| pMac->lim.gLimAddtsSent = false; |
| return; |
| } |
| |
| if (! pMac->lim.gLimAddtsSent) |
| { |
| PELOGW(limLog(pMac, LOGW, "AddtsRspTimeout but no AddtsSent");) |
| return; |
| } |
| |
| if (param != pMac->lim.gLimAddtsRspTimerCount) |
| { |
| limLog(pMac, LOGE, FL("Invalid AddtsRsp Timer count %d (exp %d)"), |
| param, pMac->lim.gLimAddtsRspTimerCount); |
| return; |
| } |
| |
| // this a real response timeout |
| pMac->lim.gLimAddtsSent = false; |
| pMac->lim.gLimAddtsRspTimerCount++; |
| |
| limSendSmeAddtsRsp(pMac, true, eSIR_SME_ADDTS_RSP_TIMEOUT, psessionEntry, pMac->lim.gLimAddtsReq.req.tspec, |
| psessionEntry->smeSessionId, psessionEntry->transactionId); |
| } |
| |
| |
| /** |
| * __limProcessSmeStatsRequest() |
| * |
| *FUNCTION: |
| * |
| * |
| *NOTE: |
| * |
| * @param pMac Pointer to Global MAC structure |
| * @param *pMsgBuf A pointer to the SME message buffer |
| * @return None |
| */ |
| static void |
| __limProcessSmeStatsRequest(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) |
| { |
| tpAniGetStatsReq pStatsReq; |
| tSirMsgQ msgQ; |
| tpPESession psessionEntry; |
| tANI_U8 sessionId; |
| |
| |
| if(pMsgBuf == NULL) |
| { |
| limLog(pMac, LOGE,FL("Buffer is Pointing to NULL")); |
| return; |
| } |
| |
| pStatsReq = (tpAniGetStatsReq) pMsgBuf; |
| |
| if((psessionEntry = peFindSessionByBssid(pMac,pStatsReq->bssId,&sessionId))== NULL) |
| { |
| limLog(pMac, LOGE, FL("session does not exist for given bssId")); |
| vos_mem_free( pMsgBuf ); |
| pMsgBuf = NULL; |
| return; |
| } |
| |
| |
| |
| switch(pStatsReq->msgType) |
| { |
| //Add Lim stats here. and send reqsponse. |
| |
| //HAL maintained Stats. |
| case eWNI_SME_STA_STAT_REQ: |
| msgQ.type = WDA_STA_STAT_REQ; |
| break; |
| case eWNI_SME_AGGR_STAT_REQ: |
| msgQ.type = WDA_AGGR_STAT_REQ; |
| break; |
| case eWNI_SME_GLOBAL_STAT_REQ: |
| msgQ.type = WDA_GLOBAL_STAT_REQ; |
| break; |
| case eWNI_SME_STAT_SUMM_REQ: |
| msgQ.type = WDA_STAT_SUMM_REQ; |
| break; |
| default: //Unknown request. |
| PELOGE(limLog(pMac, LOGE, "Unknown Statistics request");) |
| vos_mem_free( pMsgBuf ); |
| pMsgBuf = NULL; |
| return; |
| } |
| |
| msgQ.reserved = 0; |
| msgQ.bodyptr = pMsgBuf; |
| msgQ.bodyval = 0; |
| if(NULL == psessionEntry) |
| { |
| MTRACE(macTraceMsgTx(pMac, NO_SESSION, msgQ.type)); |
| } |
| else |
| { |
| MTRACE(macTraceMsgTx(pMac, psessionEntry->peSessionId, msgQ.type)); |
| } |
| if( eSIR_SUCCESS != (wdaPostCtrlMsg( pMac, &msgQ ))){ |
| limLog(pMac, LOGP, "Unable to forward request"); |
| vos_mem_free( pMsgBuf ); |
| pMsgBuf = NULL; |
| return; |
| } |
| |
| return; |
| } |
| |
| |
| /** |
| * __limProcessSmeGetStatisticsRequest() |
| * |
| *FUNCTION: |
| * |
| * |
| *NOTE: |
| * |
| * @param pMac Pointer to Global MAC structure |
| * @param *pMsgBuf A pointer to the SME message buffer |
| * @return None |
| */ |
| static void |
| __limProcessSmeGetStatisticsRequest(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) |
| { |
| tpAniGetPEStatsReq pPEStatsReq; |
| tSirMsgQ msgQ; |
| |
| pPEStatsReq = (tpAniGetPEStatsReq) pMsgBuf; |
| |
| msgQ.type = WDA_GET_STATISTICS_REQ; |
| |
| msgQ.reserved = 0; |
| msgQ.bodyptr = pMsgBuf; |
| msgQ.bodyval = 0; |
| MTRACE(macTraceMsgTx(pMac, NO_SESSION, msgQ.type)); |
| |
| if( eSIR_SUCCESS != (wdaPostCtrlMsg( pMac, &msgQ ))){ |
| vos_mem_free( pMsgBuf ); |
| pMsgBuf = NULL; |
| limLog(pMac, LOGP, "Unable to forward request"); |
| return; |
| } |
| |
| return; |
| } |
| |
| #if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) |
| /** |
| *FUNCTION: __limProcessSmeGetTsmStatsRequest() |
| * |
| *NOTE: |
| * |
| * @param pMac Pointer to Global MAC structure |
| * @param *pMsgBuf A pointer to the SME message buffer |
| * @return None |
| */ |
| static void |
| __limProcessSmeGetTsmStatsRequest(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) |
| { |
| tSirMsgQ msgQ; |
| |
| msgQ.type = WDA_TSM_STATS_REQ; |
| msgQ.reserved = 0; |
| msgQ.bodyptr = pMsgBuf; |
| msgQ.bodyval = 0; |
| MTRACE(macTraceMsgTx(pMac, NO_SESSION, msgQ.type)); |
| |
| if( eSIR_SUCCESS != (wdaPostCtrlMsg( pMac, &msgQ ))){ |
| vos_mem_free( pMsgBuf ); |
| pMsgBuf = NULL; |
| limLog(pMac, LOGP, "Unable to forward request"); |
| return; |
| } |
| } |
| #endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */ |
| |
| static void |
| __limProcessSmeUpdateAPWPSIEs(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) |
| { |
| tpSirUpdateAPWPSIEsReq pUpdateAPWPSIEsReq; |
| tpPESession psessionEntry; |
| tANI_U8 sessionId; //PE sessionID |
| |
| PELOG1(limLog(pMac, LOG1, |
| FL("received UPDATE_APWPSIEs_REQ message"));); |
| |
| if(pMsgBuf == NULL) |
| { |
| limLog(pMac, LOGE,FL("Buffer is Pointing to NULL")); |
| return; |
| } |
| |
| pUpdateAPWPSIEsReq = vos_mem_malloc(sizeof(tSirUpdateAPWPSIEsReq)); |
| if ( NULL == pUpdateAPWPSIEsReq ) |
| { |
| limLog(pMac, LOGP, FL("call to AllocateMemory failed for pUpdateAPWPSIEsReq")); |
| return; |
| } |
| |
| if ((limUpdateAPWPSIEsReqSerDes(pMac, pUpdateAPWPSIEsReq, (tANI_U8 *) pMsgBuf) == eSIR_FAILURE)) |
| { |
| limLog(pMac, LOGW, FL("received invalid SME_SETCONTEXT_REQ message")); |
| goto end; |
| } |
| |
| if((psessionEntry = peFindSessionByBssid(pMac, pUpdateAPWPSIEsReq->bssId, &sessionId)) == NULL) |
| { |
| limLog(pMac, LOGW, FL("Session does not exist for given BSSID")); |
| goto end; |
| } |
| |
| vos_mem_copy( &psessionEntry->APWPSIEs, &pUpdateAPWPSIEsReq->APWPSIEs, sizeof(tSirAPWPSIEs)); |
| |
| schSetFixedBeaconFields(pMac, psessionEntry); |
| limSendBeaconInd(pMac, psessionEntry); |
| |
| end: |
| vos_mem_free( pUpdateAPWPSIEsReq); |
| return; |
| } /*** end __limProcessSmeUpdateAPWPSIEs(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) ***/ |
| |
| void |
| limSendVdevRestart(tpAniSirGlobal pMac, |
| tpPESession psessionEntry, |
| tANI_U8 sessionId) |
| { |
| tpHalHiddenSsidVdevRestart pHalHiddenSsidVdevRestart = NULL; |
| tSirMsgQ msgQ; |
| tSirRetStatus retCode = eSIR_SUCCESS; |
| |
| if ( psessionEntry == NULL ) |
| { |
| PELOGE(limLog(pMac, LOGE, "%s:%d: Invalid parameters", __func__, __LINE__ );) |
| return; |
| } |
| |
| pHalHiddenSsidVdevRestart = vos_mem_malloc(sizeof(tHalHiddenSsidVdevRestart)); |
| if (NULL == pHalHiddenSsidVdevRestart) |
| { |
| PELOGE(limLog(pMac, LOGE, "%s:%d: Unable to allocate memory", __func__, __LINE__ );) |
| return; |
| } |
| |
| pHalHiddenSsidVdevRestart->ssidHidden = psessionEntry->ssidHidden; |
| pHalHiddenSsidVdevRestart->sessionId = sessionId; |
| |
| msgQ.type = WDA_HIDDEN_SSID_VDEV_RESTART; |
| msgQ.bodyptr = pHalHiddenSsidVdevRestart; |
| msgQ.bodyval = 0; |
| |
| retCode = wdaPostCtrlMsg(pMac, &msgQ); |
| if (eSIR_SUCCESS != retCode) |
| { |
| PELOGE(limLog(pMac, LOGE, "%s:%d: wdaPostCtrlMsg() failed", __func__, __LINE__ );) |
| vos_mem_free(pHalHiddenSsidVdevRestart); |
| } |
| } |
| static void __lim_process_roam_scan_offload_req(tpAniSirGlobal mac_ctx, |
| tANI_U32 *msg_buf) |
| { |
| tpPESession pe_session; |
| tSirMsgQ wma_msg; |
| tSirRetStatus status; |
| tSirRoamOffloadScanReq *msg, *req_buffer; |
| |
| msg = (tSirRoamOffloadScanReq *)msg_buf; |
| pe_session = pe_find_session_by_sme_session_id(mac_ctx, |
| msg->sessionId); |
| |
| /* Set roaming_in_progress flag according to the command */ |
| if ( pe_session && (msg->Command == ROAM_SCAN_OFFLOAD_START || |
| msg->Command == ROAM_SCAN_OFFLOAD_RESTART || |
| msg->Command == ROAM_SCAN_OFFLOAD_STOP)) |
| pe_session->roaming_in_progress = false; |
| |
| req_buffer = vos_mem_malloc(sizeof(tSirRoamOffloadScanReq)); |
| if (NULL == req_buffer) { |
| limLog(mac_ctx, LOGE, |
| FL("Mem Alloc failed for req buffer")); |
| return; |
| } |
| |
| *req_buffer = *msg; |
| |
| vos_mem_zero(&wma_msg, sizeof(tSirMsgQ)); |
| wma_msg.type = WDA_ROAM_SCAN_OFFLOAD_REQ; |
| wma_msg.bodyptr = req_buffer; |
| |
| status = wdaPostCtrlMsg(mac_ctx, &wma_msg); |
| if (eSIR_SUCCESS != status) |
| { |
| limLog(mac_ctx, LOGE, |
| FL("Posting WDA_ROAM_SCAN_OFFLOAD_REQ failed")); |
| vos_mem_free(req_buffer); |
| } |
| } |
| static void |
| __limProcessSmeHideSSID(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) |
| { |
| tpSirUpdateParams pUpdateParams; |
| tpPESession psessionEntry; |
| |
| PELOG1(limLog(pMac, LOG1, |
| FL("received HIDE_SSID message"));); |
| |
| if(pMsgBuf == NULL) |
| { |
| limLog(pMac, LOGE,FL("Buffer is Pointing to NULL")); |
| return; |
| } |
| |
| pUpdateParams = (tpSirUpdateParams)pMsgBuf; |
| |
| psessionEntry = pe_find_session_by_sme_session_id(pMac, |
| pUpdateParams->sessionId); |
| if(NULL == psessionEntry) { |
| limLog(pMac, LOGE, "Session does not exist for given sme sessionId %d", |
| pUpdateParams->sessionId); |
| return; |
| } |
| |
| if (psessionEntry->ssidHidden != pUpdateParams->ssidHidden) { |
| /* Update the session entry */ |
| psessionEntry->ssidHidden = pUpdateParams->ssidHidden; |
| } else { |
| PELOG1(limLog(pMac, LOG1, |
| FL("Same config already present!"))); |
| return; |
| } |
| |
| /* Send vdev restart */ |
| limSendVdevRestart(pMac, psessionEntry, pUpdateParams->sessionId); |
| |
| /* Update beacon */ |
| schSetFixedBeaconFields(pMac, psessionEntry); |
| limSendBeaconInd(pMac, psessionEntry); |
| |
| return; |
| } /*** end __limProcessSmeHideSSID(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) ***/ |
| |
| static void |
| __limProcessSmeSetWPARSNIEs(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) |
| { |
| tpSirUpdateAPWPARSNIEsReq pUpdateAPWPARSNIEsReq; |
| tpPESession psessionEntry; |
| tANI_U8 sessionId; //PE sessionID |
| |
| if(pMsgBuf == NULL) |
| { |
| limLog(pMac, LOGE,FL("Buffer is Pointing to NULL")); |
| return; |
| } |
| |
| pUpdateAPWPARSNIEsReq = vos_mem_malloc(sizeof(tSirUpdateAPWPSIEsReq)); |
| if ( NULL == pUpdateAPWPARSNIEsReq ) |
| { |
| limLog(pMac, LOGP, FL("call to AllocateMemory failed for pUpdateAPWPARSNIEsReq")); |
| return; |
| } |
| |
| if ((limUpdateAPWPARSNIEsReqSerDes(pMac, pUpdateAPWPARSNIEsReq, (tANI_U8 *) pMsgBuf) == eSIR_FAILURE)) |
| { |
| limLog(pMac, LOGW, FL("received invalid SME_SETCONTEXT_REQ message")); |
| goto end; |
| } |
| |
| if((psessionEntry = peFindSessionByBssid(pMac, pUpdateAPWPARSNIEsReq->bssId, &sessionId)) == NULL) |
| { |
| limLog(pMac, LOGW, FL("Session does not exist for given BSSID")); |
| goto end; |
| } |
| |
| vos_mem_copy(&psessionEntry->pLimStartBssReq->rsnIE, |
| &pUpdateAPWPARSNIEsReq->APWPARSNIEs, sizeof(tSirRSNie)); |
| |
| limSetRSNieWPAiefromSmeStartBSSReqMessage(pMac, &psessionEntry->pLimStartBssReq->rsnIE, psessionEntry); |
| |
| psessionEntry->pLimStartBssReq->privacy = 1; |
| psessionEntry->privacy = 1; |
| |
| schSetFixedBeaconFields(pMac, psessionEntry); |
| limSendBeaconInd(pMac, psessionEntry); |
| |
| end: |
| vos_mem_free(pUpdateAPWPARSNIEsReq); |
| return; |
| } /*** end __limProcessSmeSetWPARSNIEs(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) ***/ |
| |
| /* |
| Update the beacon Interval dynamically if beaconInterval is different in MCC |
| */ |
| static void |
| __limProcessSmeChangeBI(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) |
| { |
| tpSirChangeBIParams pChangeBIParams; |
| tpPESession psessionEntry; |
| tANI_U8 sessionId = 0; |
| tUpdateBeaconParams beaconParams; |
| |
| PELOG1(limLog(pMac, LOG1, |
| FL("received Update Beacon Interval message"));); |
| |
| if(pMsgBuf == NULL) |
| { |
| limLog(pMac, LOGE,FL("Buffer is Pointing to NULL")); |
| return; |
| } |
| |
| vos_mem_zero(&beaconParams, sizeof(tUpdateBeaconParams)); |
| pChangeBIParams = (tpSirChangeBIParams)pMsgBuf; |
| |
| if((psessionEntry = peFindSessionByBssid(pMac, pChangeBIParams->bssId, &sessionId)) == NULL) |
| { |
| limLog(pMac, LOGE, FL("Session does not exist for given BSSID")); |
| return; |
| } |
| |
| /*Update sessionEntry Beacon Interval*/ |
| if(psessionEntry->beaconParams.beaconInterval != |
| pChangeBIParams->beaconInterval ) |
| { |
| psessionEntry->beaconParams.beaconInterval = pChangeBIParams->beaconInterval; |
| } |
| |
| /*Update sch beaconInterval*/ |
| if(pMac->sch.schObject.gSchBeaconInterval != |
| pChangeBIParams->beaconInterval ) |
| { |
| pMac->sch.schObject.gSchBeaconInterval = pChangeBIParams->beaconInterval; |
| |
| PELOG1(limLog(pMac, LOG1, |
| FL("LIM send update BeaconInterval Indication : %d"),pChangeBIParams->beaconInterval);); |
| |
| if (VOS_FALSE == pMac->sap.SapDfsInfo.is_dfs_cac_timer_running) |
| { |
| /* Update beacon */ |
| schSetFixedBeaconFields(pMac, psessionEntry); |
| |
| beaconParams.bssIdx = psessionEntry->bssIdx; |
| //Set change in beacon Interval |
| beaconParams.beaconInterval = pChangeBIParams->beaconInterval; |
| beaconParams.paramChangeBitmap = PARAM_BCN_INTERVAL_CHANGED; |
| limSendBeaconParams(pMac, &beaconParams, psessionEntry); |
| } |
| } |
| |
| return; |
| } /*** end __limProcessSmeChangeBI(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) ***/ |
| |
| #ifdef QCA_HT_2040_COEX |
| static void __limProcessSmeSetHT2040Mode(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) |
| { |
| tpSirSetHT2040Mode pSetHT2040Mode; |
| tpPESession psessionEntry; |
| tANI_U8 sessionId = 0; |
| vos_msg_t msg; |
| tUpdateVHTOpMode *pHtOpMode = NULL; |
| tANI_U16 staId = 0; |
| tpDphHashNode pStaDs = NULL; |
| |
| PELOG1(limLog(pMac, LOG1, |
| FL("received Set HT 20/40 mode message"));); |
| if(pMsgBuf == NULL) |
| { |
| limLog(pMac, LOGE,FL("Buffer is Pointing to NULL")); |
| return; |
| } |
| |
| pSetHT2040Mode = (tpSirSetHT2040Mode)pMsgBuf; |
| |
| if((psessionEntry = peFindSessionByBssid(pMac, pSetHT2040Mode->bssId, |
| &sessionId)) == NULL) |
| { |
| limLog(pMac, LOG1, FL("Session does not exist for given BSSID ")); |
| limPrintMacAddr(pMac, pSetHT2040Mode->bssId, LOG1); |
| return; |
| } |
| |
| limLog(pMac, LOG1, FL("Update session entry for cbMod=%d"), |
| pSetHT2040Mode->cbMode); |
| /*Update sessionEntry HT related fields*/ |
| switch(pSetHT2040Mode->cbMode) |
| { |
| case PHY_SINGLE_CHANNEL_CENTERED: |
| psessionEntry->htSecondaryChannelOffset = PHY_SINGLE_CHANNEL_CENTERED; |
| psessionEntry->htRecommendedTxWidthSet = 0; |
| if (pSetHT2040Mode->obssEnabled) |
| psessionEntry->htSupportedChannelWidthSet = eHT_CHANNEL_WIDTH_40MHZ; |
| else |
| psessionEntry->htSupportedChannelWidthSet = eHT_CHANNEL_WIDTH_20MHZ; |
| break; |
| case PHY_DOUBLE_CHANNEL_LOW_PRIMARY: |
| psessionEntry->htSecondaryChannelOffset = PHY_DOUBLE_CHANNEL_LOW_PRIMARY; |
| psessionEntry->htRecommendedTxWidthSet = 1; |
| break; |
| case PHY_DOUBLE_CHANNEL_HIGH_PRIMARY: |
| psessionEntry->htSecondaryChannelOffset = PHY_DOUBLE_CHANNEL_HIGH_PRIMARY; |
| psessionEntry->htRecommendedTxWidthSet = 1; |
| break; |
| default: |
| limLog(pMac, LOGE,FL("Invalid cbMode")); |
| return; |
| } |
| |
| /* Update beacon */ |
| schSetFixedBeaconFields(pMac, psessionEntry); |
| limSendBeaconInd(pMac, psessionEntry); |
| |
| /* update OP Mode for each associated peer */ |
| for (staId = 0; staId < psessionEntry->dph.dphHashTable.size; staId++) |
| { |
| pStaDs = dphGetHashEntry(pMac, staId, &psessionEntry->dph.dphHashTable); |
| if (NULL == pStaDs) |
| continue; |
| |
| if (pStaDs->valid && pStaDs->htSupportedChannelWidthSet) |
| { |
| pHtOpMode = vos_mem_malloc(sizeof(tUpdateVHTOpMode)); |
| if ( NULL == pHtOpMode ) |
| { |
| limLog(pMac, LOGE, |
| FL("%s: Not able to allocate memory for setting OP mode"), |
| __func__); |
| return; |
| } |
| pHtOpMode->opMode = (psessionEntry->htSecondaryChannelOffset == |
| PHY_SINGLE_CHANNEL_CENTERED)? |
| eHT_CHANNEL_WIDTH_20MHZ:eHT_CHANNEL_WIDTH_40MHZ; |
| pHtOpMode->staId = staId; |
| vos_mem_copy(pHtOpMode->peer_mac, &pStaDs->staAddr, |
| sizeof(tSirMacAddr)); |
| pHtOpMode->smesessionId = sessionId; |
| pHtOpMode->chanMode = wma_chan_to_mode( |
| psessionEntry->currentOperChannel, |
| psessionEntry->htSecondaryChannelOffset, |
| psessionEntry->vhtCapability, |
| psessionEntry->dot11mode); |
| |
| msg.type = WDA_UPDATE_OP_MODE; |
| msg.reserved = 0; |
| msg.bodyptr = pHtOpMode; |
| if (!VOS_IS_STATUS_SUCCESS( |
| vos_mq_post_message(VOS_MODULE_ID_WDA, &msg))) |
| { |
| limLog(pMac, LOGE, |
| FL("%s: Not able to post WDA_UPDATE_OP_MODE message to WDA"), |
| __func__); |
| vos_mem_free(pHtOpMode); |
| return; |
| } |
| limLog(pMac, LOG1, |
| FL("%s: Notifed FW about OP mode: %d for staId=%d"), |
| __func__, pHtOpMode->opMode, staId); |
| |
| } |
| else |
| limLog(pMac, LOG1, FL("%s: station %d does not support HT40\n"), |
| __func__, staId); |
| } |
| |
| return; |
| } |
| #endif |
| |
| // -------------------------------------------------------------------- |
| /** |
| * __limProcessReportMessage |
| * |
| * FUNCTION: Processes the next received Radio Resource Management message |
| * |
| * LOGIC: |
| * |
| * ASSUMPTIONS: |
| * |
| * NOTE: |
| * |
| * @param None |
| * @return None |
| */ |
| |
| void __limProcessReportMessage(tpAniSirGlobal pMac, tpSirMsgQ pMsg) |
| { |
| #ifdef WLAN_FEATURE_VOWIFI |
| switch (pMsg->type) |
| { |
| case eWNI_SME_NEIGHBOR_REPORT_REQ_IND: |
| rrmProcessNeighborReportReq( pMac, pMsg->bodyptr ); |
| break; |
| case eWNI_SME_BEACON_REPORT_RESP_XMIT_IND: |
| { |
| #if defined(FEATURE_WLAN_ESE) && !defined(FEATURE_WLAN_ESE_UPLOAD) |
| tpSirBeaconReportXmitInd pBcnReport=NULL; |
| tpPESession psessionEntry=NULL; |
| tANI_U8 sessionId; |
| tpEsePEContext pEseContext = NULL; |
| |
| if(pMsg->bodyptr == NULL) |
| { |
| limLog(pMac, LOGE,FL("Buffer is Pointing to NULL")); |
| return; |
| } |
| pBcnReport = (tpSirBeaconReportXmitInd )pMsg->bodyptr; |
| if((psessionEntry = peFindSessionByBssid(pMac, pBcnReport->bssId,&sessionId))== NULL) |
| { |
| limLog(pMac, LOGE, "Session Does not exist for given bssId"); |
| return; |
| } |
| |
| pEseContext = &psessionEntry->eseContext; |
| |
| if (psessionEntry->isESEconnection && pEseContext->curMeasReq.isValid) |
| eseProcessBeaconReportXmit( pMac, pMsg->bodyptr); |
| else |
| #endif |
| rrmProcessBeaconReportXmit( pMac, pMsg->bodyptr ); |
| } |
| break; |
| default: |
| limLog(pMac, LOGE, FL("Invalid msg type:%d"), pMsg->type); |
| } |
| #endif |
| } |
| |
| #if defined(FEATURE_WLAN_ESE) || defined(WLAN_FEATURE_VOWIFI) |
| // -------------------------------------------------------------------- |
| /** |
| * limSendSetMaxTxPowerReq |
| * |
| * FUNCTION: Send SIR_HAL_SET_MAX_TX_POWER_REQ message to change the max tx power. |
| * |
| * LOGIC: |
| * |
| * ASSUMPTIONS: |
| * |
| * NOTE: |
| * |
| * @param txPower txPower to be set. |
| * @param pSessionEntry session entry. |
| * @return None |
| */ |
| tSirRetStatus |
| limSendSetMaxTxPowerReq ( tpAniSirGlobal pMac, tPowerdBm txPower, tpPESession pSessionEntry ) |
| { |
| tpMaxTxPowerParams pMaxTxParams = NULL; |
| tSirRetStatus retCode = eSIR_SUCCESS; |
| tSirMsgQ msgQ; |
| |
| if( pSessionEntry == NULL ) |
| { |
| PELOGE(limLog(pMac, LOGE, "%s:%d: Inavalid parameters", __func__, __LINE__ );) |
| return eSIR_FAILURE; |
| } |
| |
| pMaxTxParams = vos_mem_malloc(sizeof(tMaxTxPowerParams)); |
| if ( NULL == pMaxTxParams ) |
| { |
| limLog( pMac, LOGP, "%s:%d:Unable to allocate memory for pMaxTxParams ", __func__, __LINE__); |
| return eSIR_MEM_ALLOC_FAILED; |
| |
| } |
| #if defined(WLAN_VOWIFI_DEBUG) || defined(FEATURE_WLAN_ESE) |
| PELOG1(limLog( pMac, LOG1, "%s:%d: Allocated memory for pMaxTxParams...will be freed in other module", __func__, __LINE__ );) |
| #endif |
| if( pMaxTxParams == NULL ) |
| { |
| limLog( pMac, LOGE, "%s:%d: pMaxTxParams is NULL", __func__, __LINE__); |
| return eSIR_FAILURE; |
| } |
| pMaxTxParams->power = txPower; |
| vos_mem_copy( pMaxTxParams->bssId, pSessionEntry->bssId, sizeof(tSirMacAddr) ); |
| vos_mem_copy( pMaxTxParams->selfStaMacAddr, pSessionEntry->selfMacAddr, sizeof(tSirMacAddr) ); |
| |
| msgQ.type = WDA_SET_MAX_TX_POWER_REQ; |
| msgQ.bodyptr = pMaxTxParams; |
| msgQ.bodyval = 0; |
| PELOG1(limLog(pMac, LOG1, FL("Posting WDA_SET_MAX_TX_POWER_REQ to WDA"));) |
| MTRACE(macTraceMsgTx(pMac, pSessionEntry->peSessionId, msgQ.type)); |
| retCode = wdaPostCtrlMsg(pMac, &msgQ); |
| if (eSIR_SUCCESS != retCode) |
| { |
| PELOGE(limLog(pMac, LOGE, FL("wdaPostCtrlMsg() failed"));) |
| vos_mem_free(pMaxTxParams); |
| } |
| return retCode; |
| } |
| #endif |
| |
| /** |
| * __limProcessSmeAddStaSelfReq() |
| * |
| *FUNCTION: |
| * This function is called to process SME_ADD_STA_SELF_REQ message |
| * from SME. It sends a SIR_HAL_ADD_STA_SELF_REQ message to HAL. |
| * |
| *LOGIC: |
| * |
| *ASSUMPTIONS: |
| * |
| *NOTE: |
| * |
| * @param pMac Pointer to Global MAC structure |
| * @param *pMsgBuf A pointer to the SME message buffer |
| * @return None |
| */ |
| |
| static void |
| __limProcessSmeAddStaSelfReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) |
| { |
| tSirMsgQ msg; |
| tpAddStaSelfParams pAddStaSelfParams; |
| tpSirSmeAddStaSelfReq pSmeReq = (tpSirSmeAddStaSelfReq) pMsgBuf; |
| |
| pAddStaSelfParams = vos_mem_malloc(sizeof(tAddStaSelfParams)); |
| if ( NULL == pAddStaSelfParams ) |
| { |
| limLog( pMac, LOGP, FL("Unable to allocate memory for tAddSelfStaParams") ); |
| return; |
| } |
| |
| vos_mem_copy( pAddStaSelfParams->selfMacAddr, pSmeReq->selfMacAddr, sizeof(tSirMacAddr) ); |
| pAddStaSelfParams->currDeviceMode = pSmeReq->currDeviceMode; |
| pAddStaSelfParams->sessionId = pSmeReq->sessionId; |
| pAddStaSelfParams->type = pSmeReq->type; |
| pAddStaSelfParams->subType = pSmeReq->subType; |
| pAddStaSelfParams->pkt_err_disconn_th = pSmeReq->pkt_err_disconn_th; |
| pAddStaSelfParams->nss_2g = pSmeReq->nss_2g; |
| pAddStaSelfParams->nss_5g = pSmeReq->nss_5g; |
| pAddStaSelfParams->tx_aggregation_size = pSmeReq->tx_aggregation_size; |
| pAddStaSelfParams->rx_aggregation_size = pSmeReq->rx_aggregation_size; |
| |
| msg.type = SIR_HAL_ADD_STA_SELF_REQ; |
| msg.reserved = 0; |
| msg.bodyptr = pAddStaSelfParams; |
| msg.bodyval = 0; |
| |
| PELOGW(limLog(pMac, LOG1, FL("sending SIR_HAL_ADD_STA_SELF_REQ msg to HAL"));) |
| MTRACE(macTraceMsgTx(pMac, NO_SESSION, msg.type)); |
| |
| if(eSIR_SUCCESS != wdaPostCtrlMsg(pMac, &msg)) |
| { |
| limLog(pMac, LOGP, FL("wdaPostCtrlMsg failed")); |
| } |
| return; |
| } /*** end __limProcessAddStaSelfReq() ***/ |
| |
| |
| /** |
| * __limProcessSmeDelStaSelfReq() |
| * |
| *FUNCTION: |
| * This function is called to process SME_DEL_STA_SELF_REQ message |
| * from SME. It sends a SIR_HAL_DEL_STA_SELF_REQ message to HAL. |
| * |
| *LOGIC: |
| * |
| *ASSUMPTIONS: |
| * |
| *NOTE: |
| * |
| * @param pMac Pointer to Global MAC structure |
| * @param *pMsgBuf A pointer to the SME message buffer |
| * @return None |
| */ |
| |
| static void |
| __limProcessSmeDelStaSelfReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) |
| { |
| tSirMsgQ msg; |
| tpDelStaSelfParams pDelStaSelfParams; |
| tpSirSmeDelStaSelfReq pSmeReq = (tpSirSmeDelStaSelfReq) pMsgBuf; |
| |
| pDelStaSelfParams = vos_mem_malloc(sizeof( tDelStaSelfParams)); |
| if ( NULL == pDelStaSelfParams ) |
| { |
| limLog( pMac, LOGP, FL("Unable to allocate memory for tDelStaSelfParams") ); |
| return; |
| } |
| |
| vos_mem_copy( pDelStaSelfParams->selfMacAddr, pSmeReq->selfMacAddr, sizeof(tSirMacAddr) ); |
| |
| pDelStaSelfParams->sessionId = pSmeReq->sessionId; |
| msg.type = SIR_HAL_DEL_STA_SELF_REQ; |
| msg.reserved = 0; |
| msg.bodyptr = pDelStaSelfParams; |
| msg.bodyval = 0; |
| |
| PELOGW(limLog(pMac, LOG1, |
| FL("sending SIR_HAL_DEL_STA_SELF_REQ msg to HAL"));) |
| MTRACE(macTraceMsgTx(pMac, NO_SESSION, msg.type)); |
| |
| if(eSIR_SUCCESS != wdaPostCtrlMsg(pMac, &msg)) |
| { |
| limLog(pMac, LOGP, FL("wdaPostCtrlMsg failed")); |
| vos_mem_free(pDelStaSelfParams); |
| } |
| return; |
| } /*** end __limProcessSmeDelStaSelfReq() ***/ |
| |
| |
| /** |
| * __limProcessSmeRegisterMgmtFrameReq() |
| * |
| *FUNCTION: |
| * This function is called to process eWNI_SME_REGISTER_MGMT_FRAME_REQ message |
| * from SME. It Register this information within PE. |
| * |
| *LOGIC: |
| * |
| *ASSUMPTIONS: |
| * |
| *NOTE: |
| * |
| * @param pMac Pointer to Global MAC structure |
| * @param *pMsgBuf A pointer to the SME message buffer |
| * @return None |
| */ |
| static void |
| __limProcessSmeRegisterMgmtFrameReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) |
| { |
| VOS_STATUS vosStatus; |
| tpSirRegisterMgmtFrame pSmeReq = (tpSirRegisterMgmtFrame)pMsgBuf; |
| tpLimMgmtFrameRegistration pLimMgmtRegistration = NULL, pNext = NULL; |
| tANI_BOOLEAN match = VOS_FALSE; |
| PELOG1(limLog(pMac, LOG1, |
| FL("registerFrame %d, frameType %d, matchLen %d"), |
| pSmeReq->registerFrame, pSmeReq->frameType, pSmeReq->matchLen);) |
| |
| /* First check whether entry exists already*/ |
| |
| vos_list_peek_front(&pMac->lim.gLimMgmtFrameRegistratinQueue, |
| (vos_list_node_t**)&pLimMgmtRegistration); |
| |
| while(pLimMgmtRegistration != NULL) |
| { |
| if (pLimMgmtRegistration->frameType == pSmeReq->frameType) |
| { |
| if(pSmeReq->matchLen) |
| { |
| if (pLimMgmtRegistration->matchLen == pSmeReq->matchLen) |
| { |
| if (vos_mem_compare( pLimMgmtRegistration->matchData, |
| pSmeReq->matchData, pLimMgmtRegistration->matchLen)) |
| { |
| /* found match! */ |
| match = VOS_TRUE; |
| break; |
| } |
| } |
| } |
| else |
| { |
| /* found match! */ |
| match = VOS_TRUE; |
| break; |
| } |
| } |
| vosStatus = vos_list_peek_next ( |
| &pMac->lim.gLimMgmtFrameRegistratinQueue, |
| (vos_list_node_t*) pLimMgmtRegistration, |
| (vos_list_node_t**) &pNext ); |
| |
| pLimMgmtRegistration = pNext; |
| pNext = NULL; |
| |
| } |
| |
| if (match) |
| { |
| vos_list_remove_node(&pMac->lim.gLimMgmtFrameRegistratinQueue, |
| (vos_list_node_t*)pLimMgmtRegistration); |
| vos_mem_free(pLimMgmtRegistration); |
| } |
| |
| if(pSmeReq->registerFrame) |
| { |
| pLimMgmtRegistration = vos_mem_malloc(sizeof(tLimMgmtFrameRegistration) + pSmeReq->matchLen); |
| if ( pLimMgmtRegistration != NULL) |
| { |
| vos_mem_set((void*)pLimMgmtRegistration, |
| sizeof(tLimMgmtFrameRegistration) + pSmeReq->matchLen, 0 ); |
| pLimMgmtRegistration->frameType = pSmeReq->frameType; |
| pLimMgmtRegistration->matchLen = pSmeReq->matchLen; |
| pLimMgmtRegistration->sessionId = pSmeReq->sessionId; |
| if(pSmeReq->matchLen) |
| { |
| vos_mem_copy(pLimMgmtRegistration->matchData, |
| pSmeReq->matchData, pSmeReq->matchLen); |
| } |
| vos_list_insert_front(&pMac->lim.gLimMgmtFrameRegistratinQueue, |
| &pLimMgmtRegistration->node); |
| } |
| } |
| |
| return; |
| } /*** end __limProcessSmeRegisterMgmtFrameReq() ***/ |
| |
| static tANI_BOOLEAN |
| __limInsertSingleShotNOAForScan(tpAniSirGlobal pMac, tANI_U32 noaDuration) |
| { |
| tpP2pPsParams pMsgNoA; |
| tSirMsgQ msg; |
| |
| pMsgNoA = vos_mem_malloc(sizeof( tP2pPsConfig )); |
| if ( NULL == pMsgNoA ) |
| { |
| limLog( pMac, LOGP, |
| FL( "Unable to allocate memory during NoA Update" )); |
| goto error; |
| } |
| |
| vos_mem_set((tANI_U8 *)pMsgNoA, sizeof(tP2pPsConfig), 0); |
| /* Below params used for opp PS/periodic NOA and are don't care in this case - so initialized to 0 */ |
| pMsgNoA->opp_ps = 0; |
| pMsgNoA->ctWindow = 0; |
| pMsgNoA->duration = 0; |
| pMsgNoA->interval = 0; |
| pMsgNoA->count = 0; |
| |
| /* Below params used for Single Shot NOA - so assign proper values */ |
| pMsgNoA->psSelection = P2P_SINGLE_NOA; |
| pMsgNoA->single_noa_duration = noaDuration; |
| |
| /* Start Insert NOA timer |
| * If insert NOA req fails or NOA rsp fails or start NOA indication doesn't come from FW due to GO session deletion |
| * or any other failure or reason, we still need to process the deferred SME req. The insert NOA |
| * timer of 500 ms will ensure the stored SME req always gets processed |
| */ |
| if (tx_timer_activate(&pMac->lim.limTimers.gLimP2pSingleShotNoaInsertTimer) |
| == TX_TIMER_ERROR) |
| { |
| /// Could not activate Insert NOA timer. |
| // Log error |
| limLog(pMac, LOGP, FL("could not activate Insert Single Shot NOA during scan timer")); |
| |
| // send the scan response back with status failure and do not even call insert NOA |
| limSendSmeScanRsp(pMac, sizeof(tSirSmeScanRsp), eSIR_SME_SCAN_FAILED, pMac->lim.gSmeSessionId, pMac->lim.gTransactionId); |
| vos_mem_free(pMsgNoA); |
| goto error; |
| } |
| |
| MTRACE(macTrace(pMac, TRACE_CODE_TIMER_ACTIVATE, NO_SESSION, eLIM_INSERT_SINGLESHOT_NOA_TIMER)); |
| |
| msg.type = WDA_SET_P2P_GO_NOA_REQ; |
| msg.reserved = 0; |
| msg.bodyptr = pMsgNoA; |
| msg.bodyval = 0; |
| |
| if(eSIR_SUCCESS != wdaPostCtrlMsg(pMac, &msg)) |
| { |
| /* In this failure case, timer is already started, so its expiration will take care of sending scan response */ |
| limLog(pMac, LOGP, FL("wdaPost Msg failed")); |
| /* Deactivate the NOA timer in failure case */ |
| limDeactivateAndChangeTimer(pMac, eLIM_INSERT_SINGLESHOT_NOA_TIMER); |
| goto error; |
| } |
| return FALSE; |
| |
| error: |
| /* In any of the failure cases, just go ahead with the processing of registered deferred SME request without |
| * worrying about the NOA |
| */ |
| limProcessRegdDefdSmeReqAfterNOAStart(pMac); |
| // msg buffer is consumed and freed in above function so return FALSE |
| return FALSE; |
| |
| } |
| |
| static void __limRegisterDeferredSmeReqForNOAStart(tpAniSirGlobal pMac, tANI_U16 msgType, tANI_U32 *pMsgBuf) |
| { |
| limLog(pMac, LOG1, FL("Reg msgType %d"), msgType) ; |
| pMac->lim.gDeferMsgTypeForNOA = msgType; |
| pMac->lim.gpDefdSmeMsgForNOA = pMsgBuf; |
| } |
| |
| static void __limDeregisterDeferredSmeReqAfterNOAStart(tpAniSirGlobal pMac) |
| { |
| limLog(pMac, LOG1, FL("Dereg msgType %d"), pMac->lim.gDeferMsgTypeForNOA) ; |
| pMac->lim.gDeferMsgTypeForNOA = 0; |
| if (pMac->lim.gpDefdSmeMsgForNOA != NULL) |
| { |
| /* __limProcessSmeScanReq consumed the buffer. We can free it. */ |
| vos_mem_free(pMac->lim.gpDefdSmeMsgForNOA); |
| pMac->lim.gpDefdSmeMsgForNOA = NULL; |
| } |
| } |
| |
| static |
| tANI_U32 limCalculateNOADuration(tpAniSirGlobal pMac, tANI_U16 msgType, tANI_U32 *pMsgBuf) |
| { |
| tANI_U32 noaDuration = 0; |
| |
| switch (msgType) |
| { |
| case eWNI_SME_SCAN_REQ: |
| { |
| tANI_U32 val; |
| tANI_U8 i; |
| tpSirSmeScanReq pScanReq = (tpSirSmeScanReq) pMsgBuf; |
| if (wlan_cfgGetInt(pMac, WNI_CFG_PASSIVE_MAXIMUM_CHANNEL_TIME, &val) != eSIR_SUCCESS) |
| { |
| /* |
| * Could not get max channel value |
| * from CFG. Log error. |
| */ |
| limLog(pMac, LOGP, FL("could not retrieve passive max channel value")); |
| |
| /* use a default value of 110ms */ |
| val = DEFAULT_PASSIVE_MAX_CHANNEL_TIME; |
| } |
| |
| for (i = 0; i < pScanReq->channelList.numChannels; i++) { |
| tANI_U8 channelNum = pScanReq->channelList.channelNumber[i]; |
| |
| if (limActiveScanAllowed(pMac, channelNum)) { |
| /* Use min + max channel time to calculate the total duration of scan */ |
| noaDuration += pScanReq->minChannelTime + pScanReq->maxChannelTime; |
| } else { |
| /* using the value from WNI_CFG_PASSIVE_MINIMUM_CHANNEL_TIME as is done in |
| * void limContinuePostChannelScan(tpAniSirGlobal pMac) |
| */ |
| noaDuration += val; |
| } |
| } |
| |
| /* Adding an overhead of 20ms to account for the scan messaging delays */ |
| noaDuration += SCAN_MESSAGING_OVERHEAD; |
| noaDuration *= CONV_MS_TO_US; |
| |
| break; |
| } |
| |
| #ifdef FEATURE_OEM_DATA_SUPPORT |
| case eWNI_SME_OEM_DATA_REQ: |
| noaDuration = OEM_DATA_NOA_DURATION*CONV_MS_TO_US; // use 60 msec as default |
| break; |
| #endif |
| |
| case eWNI_SME_REMAIN_ON_CHANNEL_REQ: |
| { |
| tSirRemainOnChnReq *pRemainOnChnReq = (tSirRemainOnChnReq *) pMsgBuf; |
| noaDuration = (pRemainOnChnReq->duration)*CONV_MS_TO_US; |
| break; |
| } |
| |
| case eWNI_SME_JOIN_REQ: |
| noaDuration = JOIN_NOA_DURATION*CONV_MS_TO_US; |
| break; |
| |
| default: |
| noaDuration = 0; |
| break; |
| |
| } |
| limLog(pMac, LOGW, FL("msgType %d noa %d"), msgType, noaDuration); |
| return noaDuration; |
| } |
| |
| void limProcessRegdDefdSmeReqAfterNOAStart(tpAniSirGlobal pMac) |
| { |
| tANI_BOOLEAN bufConsumed = TRUE; |
| |
| limLog(pMac, LOG1, FL("Process defd sme req %d"), pMac->lim.gDeferMsgTypeForNOA); |
| if ( (pMac->lim.gDeferMsgTypeForNOA != 0) && |
| (pMac->lim.gpDefdSmeMsgForNOA != NULL) ) |
| { |
| switch (pMac->lim.gDeferMsgTypeForNOA) |
| { |
| case eWNI_SME_SCAN_REQ: |
| __limProcessSmeScanReq(pMac, pMac->lim.gpDefdSmeMsgForNOA); |
| break; |
| #ifdef FEATURE_OEM_DATA_SUPPORT |
| case eWNI_SME_OEM_DATA_REQ: |
| __limProcessSmeOemDataReq(pMac, pMac->lim.gpDefdSmeMsgForNOA); |
| break; |
| #endif |
| case eWNI_SME_REMAIN_ON_CHANNEL_REQ: |
| bufConsumed = limProcessRemainOnChnlReq(pMac, pMac->lim.gpDefdSmeMsgForNOA); |
| /* limProcessRemainOnChnlReq doesnt want us to free the buffer since |
| * it is freed in limRemainOnChnRsp. this change is to avoid "double free" |
| */ |
| if (FALSE == bufConsumed) |
| { |
| pMac->lim.gpDefdSmeMsgForNOA = NULL; |
| } |
| break; |
| case eWNI_SME_JOIN_REQ: |
| __limProcessSmeJoinReq(pMac, pMac->lim.gpDefdSmeMsgForNOA); |
| break; |
| default: |
| limLog(pMac, LOGE, FL("Unknown deferred msg type %d"), pMac->lim.gDeferMsgTypeForNOA); |
| break; |
| } |
| __limDeregisterDeferredSmeReqAfterNOAStart(pMac); |
| } |
| else |
| { |
| limLog( pMac, LOGW, FL("start received from FW when no sme deferred msg pending. Do nothing." |
| "It might happen sometime when NOA start ind and timeout happen at the same time")); |
| } |
| } |
| |
| |
| static void |
| __limProcessSmeResetApCapsChange(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) |
| { |
| tpSirResetAPCapsChange pResetCapsChange; |
| tpPESession psessionEntry; |
| tANI_U8 sessionId = 0; |
| if (pMsgBuf == NULL) |
| { |
| limLog(pMac, LOGE,FL("Buffer is Pointing to NULL")); |
| return; |
| } |
| |
| pResetCapsChange = (tpSirResetAPCapsChange)pMsgBuf; |
| psessionEntry = peFindSessionByBssid(pMac, pResetCapsChange->bssId, &sessionId); |
| if (psessionEntry == NULL) |
| { |
| limLog(pMac, LOGE, FL("Session does not exist for given BSSID")); |
| return; |
| } |
| |
| psessionEntry->limSentCapsChangeNtf = false; |
| return; |
| } |
| |
| /** |
| * lim_register_p2p_ack_ind_cb() - Save the p2p ack indication callback. |
| * @mac_ctx: Mac pointer |
| * @msg_buf: Msg pointer containing the callback |
| * |
| * This function is used to save the p2p ack indication callback in PE. |
| * |
| * Return: None |
| */ |
| static void lim_register_p2p_ack_ind_cb(tpAniSirGlobal mac_ctx, |
| uint32_t *msg_buf) |
| { |
| struct sir_sme_p2p_ack_ind_cb_req *sme_req = |
| (struct sir_sme_p2p_ack_ind_cb_req *)msg_buf; |
| |
| if (NULL == msg_buf) { |
| limLog(mac_ctx, LOGE, FL("msg_buf is null")); |
| return; |
| } |
| if (sme_req->callback) |
| mac_ctx->p2p_ack_ind_cb = |
| sme_req->callback; |
| else |
| limLog(mac_ctx, LOGE, FL("sme_req->callback is null")); |
| } |
| |
| /** |
| * lim_register_mgmt_frame_ind_cb() - Save the Management frame |
| * indication callback in PE. |
| * @mac_ctx: Mac pointer |
| * @msg_buf: Msg pointer containing the callback |
| * |
| * This function is used save the Management frame |
| * indication callback in PE. |
| * |
| * Return: None |
| */ |
| static void lim_register_mgmt_frame_ind_cb(tpAniSirGlobal mac_ctx, |
| uint32_t *msg_buf) |
| { |
| struct sir_sme_mgmt_frame_cb_req *sme_req = |
| (struct sir_sme_mgmt_frame_cb_req *)msg_buf; |
| |
| if (NULL == msg_buf) { |
| limLog(mac_ctx, LOGE, FL("msg_buf is null")); |
| return; |
| } |
| if (sme_req->callback) |
| mac_ctx->mgmt_frame_ind_cb = |
| sme_req->callback; |
| else |
| limLog(mac_ctx, LOGE, FL("sme_req->callback is null")); |
| } |
| |
| /** |
| *__lim_process_send_disassoc_frame: function processes disassoc frame |
| * @mac_ctx: pointer to mac context |
| * @msg_buf: message buffer |
| * |
| * function processes disassoc request received from SME |
| * |
| * return: none |
| */ |
| static void __lim_process_send_disassoc_frame(tpAniSirGlobal mac_ctx, |
| uint32_t *msg_buf) |
| { |
| struct sme_send_disassoc_frm_req sme_send_disassoc_frame_req; |
| tSirRetStatus status; |
| tpPESession session_entry = NULL; |
| uint8_t sme_session_id; |
| uint16_t sme_trans_id; |
| |
| if(msg_buf == NULL) { |
| limLog(mac_ctx, LOGE, FL("Buffer is Pointing to NULL")); |
| return; |
| } |
| |
| limGetSessionInfo(mac_ctx, (uint8_t *)msg_buf, &sme_session_id, |
| &sme_trans_id); |
| |
| status = lim_send_disassoc_frm_req_ser_des(mac_ctx, |
| &sme_send_disassoc_frame_req, |
| (uint8_t *)msg_buf); |
| |
| if((eSIR_FAILURE == status) || |
| (limIsGroupAddr(sme_send_disassoc_frame_req.peer_mac) && |
| !limIsAddrBC(sme_send_disassoc_frame_req.peer_mac))) { |
| PELOGE(limLog(mac_ctx, LOGE, |
| FL("received invalid SME_DISASSOC_REQ message"));) |
| return; |
| } |
| |
| if((session_entry = pe_find_session_by_sme_session_id( |
| mac_ctx, sme_session_id)) == NULL) { |
| limLog(mac_ctx, LOGE, |
| FL("session does not exist for given bssId "MAC_ADDRESS_STR), |
| MAC_ADDR_ARRAY(sme_send_disassoc_frame_req.peer_mac)); |
| return; |
| } |
| |
| limLog(mac_ctx, LOG1, |
| FL("msg_type->%d len->%d sess_id->%d trans_id->%d mac->"MAC_ADDRESS_STR" reason->%d wait_for_ack->%d"), |
| sme_send_disassoc_frame_req.msg_type, |
| sme_send_disassoc_frame_req.length, |
| sme_send_disassoc_frame_req.session_id, |
| sme_send_disassoc_frame_req.trans_id, |
| MAC_ADDR_ARRAY(sme_send_disassoc_frame_req.peer_mac), |
| sme_send_disassoc_frame_req.reason, |
| sme_send_disassoc_frame_req.wait_for_ack); |
| |
| limSendDisassocMgmtFrame(mac_ctx, |
| sme_send_disassoc_frame_req.reason, |
| sme_send_disassoc_frame_req.peer_mac, |
| session_entry, sme_send_disassoc_frame_req.wait_for_ack); |
| } |
| |
| /** |
| * lim_process_sme_update_access_policy_vendor_ie: function updates vendor IE |
| * access policy |
| * @mac_ctx: pointer to mac context |
| * @msg: message buffer |
| * |
| * function processes vendor IE and access policy from SME and updates PE |
| * session entry |
| * |
| * return: none |
| */ |
| static void lim_process_sme_update_access_policy_vendor_ie( |
| tpAniSirGlobal mac_ctx, |
| uint32_t *msg) |
| { |
| struct sme_update_access_policy_vendor_ie *update_vendor_ie; |
| struct sPESession *pe_session_entry; |
| uint8_t num_bytes; |
| |
| if (!msg) { |
| limLog(mac_ctx, LOGE,FL("Buffer is Pointing to NULL")); |
| return; |
| } |
| |
| update_vendor_ie = (struct sme_update_access_policy_vendor_ie*) msg; |
| |
| pe_session_entry = pe_find_session_by_sme_session_id(mac_ctx, |
| update_vendor_ie->sme_session_id); |
| if (!pe_session_entry) { |
| limLog(mac_ctx, LOGE, |
| FL("Session does not exist for given sme session id(%hu)"), |
| update_vendor_ie->sme_session_id); |
| return; |
| } |
| |
| if (pe_session_entry->access_policy_vendor_ie) |
| vos_mem_free(pe_session_entry->access_policy_vendor_ie); |
| |
| num_bytes = update_vendor_ie->ie[1] + 2; |
| pe_session_entry->access_policy_vendor_ie = vos_mem_malloc(num_bytes); |
| |
| if (!pe_session_entry->access_policy_vendor_ie) { |
| limLog(mac_ctx, LOGE, |
| FL("Failed to allocate memory for vendor ie")); |
| return; |
| } |
| |
| vos_mem_copy(pe_session_entry->access_policy_vendor_ie, |
| &update_vendor_ie->ie[0], num_bytes); |
| pe_session_entry->access_policy = update_vendor_ie->access_policy; |
| |
| return; |
| } |
| |
| #ifdef FEATURE_WLAN_SUB_20_MHZ |
| /** |
| * lim_process_sme_set_sub20_channelwidth() - update sub 20MHz channel width |
| * @mac_ptr: Mac pointer |
| * @msgbuf_ptr: Msg pointer containing the callback |
| * |
| * This function is used to save sub 20MHz channel width |
| * |
| * Return: None |
| */ |
| static void lim_process_sme_set_sub20_channelwidth( |
| tpAniSirGlobal mac_ptr, uint32_t *msgbuf_ptr) |
| { |
| struct sme_sub20_chan_width *msg; |
| tpPESession session_entry_ptr; |
| |
| if (msgbuf_ptr == NULL) { |
| limLog(mac_ptr, LOGE, FL("Buffer is Pointing to NULL")); |
| return; |
| } |
| |
| msg = (struct sme_sub20_chan_width *)msgbuf_ptr; |
| session_entry_ptr = |
| pe_find_session_by_sme_session_id(mac_ptr, msg->session_id); |
| if (session_entry_ptr == NULL) { |
| limLog(mac_ptr, LOGE, FL("Session not exist")); |
| return; |
| } |
| |
| session_entry_ptr->sub20_channelwidth = msg->channelwidth; |
| limLog(mac_ptr, LOGE, "Set sub20 channel width %d\n", |
| session_entry_ptr->sub20_channelwidth); |
| return; |
| } |
| #else |
| static void lim_process_sme_set_sub20_channelwidth( |
| tpAniSirGlobal mac_ptr, uint32_t *msgbuf_ptr) |
| { |
| limLog(mac_ptr, LOGE, FL("invalid event")); |
| return; |
| } |
| #endif |
| |
| /** |
| * limProcessSmeReqMessages() |
| * |
| *FUNCTION: |
| * This function is called by limProcessMessageQueue(). This |
| * function processes SME request messages from HDD or upper layer |
| * application. |
| * |
| *LOGIC: |
| * |
| *ASSUMPTIONS: |
| * |
| *NOTE: |
| * |
| * @param pMac Pointer to Global MAC structure |
| * @param msgType Indicates the SME message type |
| * @param *pMsgBuf A pointer to the SME message buffer |
| * @return Boolean - TRUE - if pMsgBuf is consumed and can be freed. |
| * FALSE - if pMsgBuf is not to be freed. |
| */ |
| |
| tANI_BOOLEAN |
| limProcessSmeReqMessages(tpAniSirGlobal pMac, tpSirMsgQ pMsg) |
| { |
| tANI_BOOLEAN bufConsumed = TRUE; //Set this flag to false within case block of any following message, that doesnt want pMsgBuf to be freed. |
| tANI_U32 *pMsgBuf = pMsg->bodyptr; |
| tpSirSmeScanReq pScanReq; |
| PELOG1(limLog(pMac, LOG1, FL("LIM Received Global LimMlmState: %s(%d)"), |
| limMlmStateStr(pMac->lim.gLimMlmState), pMac->lim.gLimMlmState );) |
| |
| pScanReq = (tpSirSmeScanReq) pMsgBuf; |
| /* Special handling of some SME Req msgs where we have an existing GO session and |
| * want to insert NOA before processing those msgs. These msgs will be processed later when |
| * start event happens |
| */ |
| switch (pMsg->type) |
| { |
| case eWNI_SME_SCAN_REQ: |
| case eWNI_SME_REMAIN_ON_CHANNEL_REQ: |
| |
| /* If scan is disabled return from here |
| */ |
| if (pMac->lim.fScanDisabled) |
| { |
| if (pMsg->type == eWNI_SME_SCAN_REQ) |
| { |
| limSendSmeScanRsp(pMac, |
| offsetof(tSirSmeScanRsp,bssDescription[0]), |
| eSIR_SME_INVALID_PARAMETERS, |
| pScanReq->sessionId, |
| pScanReq->transactionId); |
| |
| bufConsumed = TRUE; |
| } |
| else if (pMsg->type == eWNI_SME_REMAIN_ON_CHANNEL_REQ) |
| { |
| pMac->lim.gpDefdSmeMsgForNOA = NULL; |
| pMac->lim.gpLimRemainOnChanReq = (tpSirRemainOnChnReq )pMsgBuf; |
| limRemainOnChnRsp(pMac,eHAL_STATUS_FAILURE, NULL); |
| |
| /* |
| * limRemainOnChnRsp will free the buffer this change is to |
| * avoid "double free" |
| */ |
| bufConsumed = FALSE; |
| } |
| |
| limLog(pMac, LOGE, |
| FL("Error: Scan Disabled." |
| " Return with error status for SME Message type(%d)"), |
| pMsg->type); |
| |
| return bufConsumed; |
| } |
| /* |
| * Do not add BREAK here |
| */ |
| #ifdef FEATURE_OEM_DATA_SUPPORT |
| case eWNI_SME_OEM_DATA_REQ: |
| #endif |
| case eWNI_SME_JOIN_REQ: |
| /* If we have an existing P2P GO session we need to insert NOA before actually process this SME Req */ |
| if (!pMac->fScanOffload && (limIsNOAInsertReqd(pMac) == TRUE) && |
| IS_FEATURE_SUPPORTED_BY_FW(P2P_GO_NOA_DECOUPLE_INIT_SCAN)) |
| { |
| tANI_U32 noaDuration; |
| __limRegisterDeferredSmeReqForNOAStart(pMac, pMsg->type, pMsgBuf); |
| noaDuration = limCalculateNOADuration(pMac, pMsg->type, pMsgBuf); |
| bufConsumed = __limInsertSingleShotNOAForScan(pMac, noaDuration); |
| return bufConsumed; |
| } |
| } |
| /* If no insert NOA required then execute the code below */ |
| |
| switch (pMsg->type) |
| { |
| case eWNI_SME_START_REQ: |
| __limProcessSmeStartReq(pMac, pMsgBuf); |
| break; |
| |
| case eWNI_SME_SYS_READY_IND: |
| bufConsumed = __limProcessSmeSysReadyInd(pMac, pMsgBuf); |
| break; |
| |
| case eWNI_SME_START_BSS_REQ: |
| bufConsumed = __limProcessSmeStartBssReq(pMac, pMsg); |
| break; |
| |
| case eWNI_SME_SCAN_REQ: |
| __limProcessSmeScanReq(pMac, pMsgBuf); |
| break; |
| |
| #ifdef FEATURE_OEM_DATA_SUPPORT |
| case eWNI_SME_OEM_DATA_REQ: |
| __limProcessSmeOemDataReq(pMac, pMsgBuf); |
| break; |
| #endif |
| case eWNI_SME_REMAIN_ON_CHANNEL_REQ: |
| bufConsumed = limProcessRemainOnChnlReq(pMac, pMsgBuf); |
| break; |
| |
| case eWNI_SME_UPDATE_NOA: |
| __limProcessSmeNoAUpdate(pMac, pMsgBuf); |
| break; |
| case eWNI_SME_CLEAR_DFS_CHANNEL_LIST: |
| __limProcessClearDfsChannelList(pMac, pMsg); |
| break; |
| case eWNI_SME_CLEAR_LIM_SCAN_CACHE: |
| limReInitScanResults(pMac); |
| break; |
| case eWNI_SME_JOIN_REQ: |
| __limProcessSmeJoinReq(pMac, pMsgBuf); |
| break; |
| |
| case eWNI_SME_REASSOC_REQ: |
| __limProcessSmeReassocReq(pMac, pMsgBuf); |
| break; |
| |
| case eWNI_SME_DISASSOC_REQ: |
| __limProcessSmeDisassocReq(pMac, pMsgBuf); |
| break; |
| |
| case eWNI_SME_DISASSOC_CNF: |
| case eWNI_SME_DEAUTH_CNF: |
| __limProcessSmeDisassocCnf(pMac, pMsgBuf); |
| break; |
| |
| case eWNI_SME_DEAUTH_REQ: |
| __limProcessSmeDeauthReq(pMac, pMsgBuf); |
| break; |
| |
| case eWNI_SME_SEND_DISASSOC_FRAME: |
| __lim_process_send_disassoc_frame(pMac, pMsgBuf); |
| break; |
| |
| case eWNI_SME_SETCONTEXT_REQ: |
| __limProcessSmeSetContextReq(pMac, pMsgBuf); |
| break; |
| |
| case eWNI_SME_REMOVEKEY_REQ: |
| __limProcessSmeRemoveKeyReq(pMac, pMsgBuf); |
| break; |
| |
| case eWNI_SME_STOP_BSS_REQ: |
| bufConsumed = __limProcessSmeStopBssReq(pMac, pMsg); |
| break; |
| |
| case eWNI_SME_ASSOC_CNF: |
| case eWNI_SME_REASSOC_CNF: |
| if (pMsg->type == eWNI_SME_ASSOC_CNF) |
| PELOG1(limLog(pMac, LOG1, FL("Received ASSOC_CNF message"));) |
| else |
| PELOG1(limLog(pMac, LOG1, FL("Received REASSOC_CNF message"));) |
| |
| #ifdef SAP_AUTH_OFFLOAD |
| if (pMac->sap_auth_offload) { |
| __lim_process_sme_assoc_offload_cnf(pMac, pMsg->type, pMsgBuf); |
| } else { |
| __limProcessSmeAssocCnfNew(pMac, pMsg->type, pMsgBuf); |
| } |
| #else |
| __limProcessSmeAssocCnfNew(pMac, pMsg->type, pMsgBuf); |
| #endif /* SAP_AUTH_OFFLOAD */ |
| break; |
| |
| case eWNI_SME_ADDTS_REQ: |
| PELOG1(limLog(pMac, LOG1, FL("Received ADDTS_REQ message"));) |
| __limProcessSmeAddtsReq(pMac, pMsgBuf); |
| break; |
| |
| case eWNI_SME_DELTS_REQ: |
| PELOG1(limLog(pMac, LOG1, FL("Received DELTS_REQ message"));) |
| __limProcessSmeDeltsReq(pMac, pMsgBuf); |
| break; |
| |
| case SIR_LIM_ADDTS_RSP_TIMEOUT: |
| PELOG1(limLog(pMac, LOG1, FL("Received SIR_LIM_ADDTS_RSP_TIMEOUT message "));) |
| limProcessSmeAddtsRspTimeout(pMac, pMsg->bodyval); |
| break; |
| |
| case eWNI_SME_STA_STAT_REQ: |
| case eWNI_SME_AGGR_STAT_REQ: |
| case eWNI_SME_GLOBAL_STAT_REQ: |
| case eWNI_SME_STAT_SUMM_REQ: |
| __limProcessSmeStatsRequest( pMac, pMsgBuf); |
| //HAL consumes pMsgBuf. It will be freed there. Set bufConsumed to false. |
| bufConsumed = FALSE; |
| break; |
| case eWNI_SME_GET_STATISTICS_REQ: |
| __limProcessSmeGetStatisticsRequest( pMac, pMsgBuf); |
| //HAL consumes pMsgBuf. It will be freed there. Set bufConsumed to false. |
| bufConsumed = FALSE; |
| break; |
| #if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD) |
| case eWNI_SME_GET_TSM_STATS_REQ: |
| __limProcessSmeGetTsmStatsRequest( pMac, pMsgBuf); |
| bufConsumed = FALSE; |
| break; |
| #endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */ |
| case eWNI_SME_GET_SCANNED_CHANNEL_REQ: |
| limProcessSmeGetScanChannelInfo(pMac, pMsgBuf); |
| break; |
| case eWNI_SME_GET_ASSOC_STAS_REQ: |
| limProcessSmeGetAssocSTAsInfo(pMac, pMsgBuf); |
| break; |
| case eWNI_SME_TKIP_CNTR_MEAS_REQ: |
| limProcessTkipCounterMeasures(pMac, pMsgBuf); |
| break; |
| case eWNI_SME_EXT_CHANGE_CHANNEL: |
| lim_process_ext_change_channel(pMac, pMsgBuf); |
| break; |
| case eWNI_SME_HIDE_SSID_REQ: |
| __limProcessSmeHideSSID(pMac, pMsgBuf); |
| break; |
| case eWNI_SME_ROAM_SCAN_OFFLOAD_REQ: |
| __lim_process_roam_scan_offload_req(pMac, pMsgBuf); |
| break; |
| case eWNI_SME_UPDATE_APWPSIE_REQ: |
| __limProcessSmeUpdateAPWPSIEs(pMac, pMsgBuf); |
| break; |
| case eWNI_SME_GET_WPSPBC_SESSION_REQ: |
| limProcessSmeGetWPSPBCSessions(pMac, pMsgBuf); |
| break; |
| |
| case eWNI_SME_SET_APWPARSNIEs_REQ: |
| __limProcessSmeSetWPARSNIEs(pMac, pMsgBuf); |
| break; |
| |
| case eWNI_SME_CHNG_MCC_BEACON_INTERVAL: |
| //Update the beaconInterval |
| __limProcessSmeChangeBI(pMac, pMsgBuf ); |
| break; |
| |
| #ifdef QCA_HT_2040_COEX |
| case eWNI_SME_SET_HT_2040_MODE: |
| __limProcessSmeSetHT2040Mode(pMac, pMsgBuf); |
| break; |
| #endif |
| |
| #if defined WLAN_FEATURE_VOWIFI |
| case eWNI_SME_NEIGHBOR_REPORT_REQ_IND: |
| case eWNI_SME_BEACON_REPORT_RESP_XMIT_IND: |
| __limProcessReportMessage(pMac, pMsg); |
| break; |
| #endif |
| |
| #if defined WLAN_FEATURE_VOWIFI_11R |
| case eWNI_SME_FT_PRE_AUTH_REQ: |
| bufConsumed = (tANI_BOOLEAN)limProcessFTPreAuthReq(pMac, pMsg); |
| break; |
| case eWNI_SME_FT_UPDATE_KEY: |
| limProcessFTUpdateKey(pMac, pMsgBuf); |
| break; |
| |
| case eWNI_SME_FT_AGGR_QOS_REQ: |
| limProcessFTAggrQosReq(pMac, pMsgBuf); |
| break; |
| #endif |
| |
| #if defined(FEATURE_WLAN_ESE) && !defined(FEATURE_WLAN_ESE_UPLOAD) |
| case eWNI_SME_ESE_ADJACENT_AP_REPORT: |
| limProcessAdjacentAPRepMsg ( pMac, pMsgBuf ); |
| break; |
| #endif |
| case eWNI_SME_ADD_STA_SELF_REQ: |
| __limProcessSmeAddStaSelfReq( pMac, pMsgBuf ); |
| break; |
| case eWNI_SME_DEL_STA_SELF_REQ: |
| __limProcessSmeDelStaSelfReq( pMac, pMsgBuf ); |
| break; |
| |
| case eWNI_SME_REGISTER_MGMT_FRAME_REQ: |
| __limProcessSmeRegisterMgmtFrameReq( pMac, pMsgBuf ); |
| break; |
| #ifdef FEATURE_WLAN_TDLS |
| case eWNI_SME_TDLS_SEND_MGMT_REQ: |
| limProcessSmeTdlsMgmtSendReq(pMac, pMsgBuf); |
| break; |
| case eWNI_SME_TDLS_ADD_STA_REQ: |
| limProcessSmeTdlsAddStaReq(pMac, pMsgBuf); |
| break; |
| case eWNI_SME_TDLS_DEL_STA_REQ: |
| limProcessSmeTdlsDelStaReq(pMac, pMsgBuf); |
| break; |
| case eWNI_SME_TDLS_LINK_ESTABLISH_REQ: |
| limProcesSmeTdlsLinkEstablishReq(pMac, pMsgBuf); |
| break; |
| #endif |
| case eWNI_SME_RESET_AP_CAPS_CHANGED: |
| __limProcessSmeResetApCapsChange(pMac, pMsgBuf); |
| break; |
| |
| case eWNI_SME_SET_TX_POWER_REQ: |
| limSendSetTxPowerReq(pMac, pMsgBuf); |
| break ; |
| |
| case eWNI_SME_CHANNEL_CHANGE_REQ: |
| limProcessSmeChannelChangeRequest(pMac, pMsgBuf); |
| break; |
| |
| case eWNI_SME_START_BEACON_REQ: |
| limProcessSmeStartBeaconReq(pMac, pMsgBuf); |
| break; |
| |
| case eWNI_SME_DFS_BEACON_CHAN_SW_IE_REQ: |
| limProcessSmeDfsCsaIeRequest(pMac, pMsgBuf); |
| break; |
| |
| case eWNI_SME_UPDATE_ADDITIONAL_IES: |
| limProcessUpdateAddIEs(pMac, pMsgBuf); |
| break; |
| |
| case eWNI_SME_MODIFY_ADDITIONAL_IES: |
| limProcessModifyAddIEs(pMac, pMsgBuf); |
| break; |
| |
| case eWNI_SME_PDEV_SET_HT_VHT_IE: |
| lim_process_set_pdev_IEs(pMac, pMsgBuf); |
| break; |
| case eWNI_SME_REGISTER_MGMT_FRAME_CB: |
| lim_register_mgmt_frame_ind_cb(pMac, pMsgBuf); |
| break; |
| case eWNI_SME_NDP_INITIATOR_REQ: |
| case eWNI_SME_NDP_RESPONDER_REQ: |
| case eWNI_SME_NDP_END_REQ: |
| lim_handle_ndp_request_message(pMac, pMsg); |
| break; |
| case eWNI_SME_REGISTER_P2P_ACK_CB: |
| lim_register_p2p_ack_ind_cb(pMac, pMsgBuf); |
| break; |
| case eWNI_SME_UPDATE_ACCESS_POLICY_VENDOR_IE: |
| lim_process_sme_update_access_policy_vendor_ie(pMac, pMsgBuf); |
| break; |
| case eWNI_SME_SET_SUB20_CH_WIDTH: |
| lim_process_sme_set_sub20_channelwidth(pMac, pMsgBuf); |
| break; |
| default: |
| vos_mem_free((v_VOID_t*)pMsg->bodyptr); |
| pMsg->bodyptr = NULL; |
| break; |
| } // switch (msgType) |
| |
| return bufConsumed; |
| } /*** end limProcessSmeReqMessages() ***/ |
| |
| /** |
| * limProcessSmeStartBeaconReq() |
| * |
| *FUNCTION: |
| * This function is called by limProcessMessageQueue(). This |
| * function processes SME request messages from HDD or upper layer |
| * application. |
| * |
| *LOGIC: |
| * |
| *ASSUMPTIONS: |
| * |
| *NOTE: |
| * |
| * @param pMac Pointer to Global MAC structure |
| * @param msgType Indicates the SME message type |
| * @param *pMsgBuf A pointer to the SME message buffer |
| * @return Boolean - TRUE - if pMsgBuf is consumed and can be freed. |
| * FALSE - if pMsgBuf is not to be freed. |
| */ |
| static void |
| limProcessSmeStartBeaconReq(tpAniSirGlobal pMac, tANI_U32 * pMsg) |
| { |
| tpSirStartBeaconIndication pBeaconStartInd; |
| tpPESession psessionEntry; |
| tANI_U8 sessionId; //PE sessionID |
| |
| if( pMsg == NULL ) |
| { |
| limLog(pMac, LOGE,FL("Buffer is Pointing to NULL")); |
| return; |
| } |
| |
| pBeaconStartInd = (tpSirStartBeaconIndication)pMsg; |
| if((psessionEntry = |
| peFindSessionByBssid(pMac, pBeaconStartInd->bssid, &sessionId)) |
| == NULL) |
| { |
| limPrintMacAddr(pMac, pBeaconStartInd->bssid, LOGE); |
| PELOGE(limLog(pMac, LOGE, |
| "%s[%d]: Session does not exist for given bssId", |
| __func__, __LINE__ );) |
| return; |
| } |
| |
| if (pBeaconStartInd->beaconStartStatus == VOS_TRUE) |
| { |
| /* |
| * Currently this Indication comes from SAP |
| * to start Beacon Tx on a DFS channel |
| * since beaconing has to be done on DFS |
| * channel only after CAC WAIT is completed. |
| * On a DFS Channel LIM does not start beacon |
| * Tx right after the WDA_ADD_BSS_RSP. |
| */ |
| limApplyConfiguration(pMac,psessionEntry); |
| VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, |
| FL("Start Beacon with ssid %s Ch %d"), |
| psessionEntry->ssId.ssId, |
| psessionEntry->currentOperChannel); |
| limSendBeaconInd(pMac, psessionEntry); |
| } |
| else |
| { |
| limLog(pMac, LOGE,FL("Invalid Beacon Start Indication")); |
| return; |
| } |
| } |
| |
| static void |
| limProcessSmeChannelChangeRequest(tpAniSirGlobal pMac, tANI_U32 *pMsg) |
| { |
| tpSirChanChangeRequest pChannelChangeReq; |
| tpPESession psessionEntry; |
| tANI_U8 sessionId; //PE sessionID |
| tPowerdBm maxTxPwr; |
| u_int32_t val = 0; |
| #ifdef WLAN_FEATURE_11AC |
| tANI_U32 centerChan; |
| tANI_U32 chanWidth; |
| #endif |
| if( pMsg == NULL ) |
| { |
| limLog(pMac, LOGE,FL("pMsg is NULL")); |
| return; |
| } |
| pChannelChangeReq = (tpSirChanChangeRequest)pMsg; |
| |
| if((psessionEntry = |
| peFindSessionByBssid(pMac, pChannelChangeReq->bssid, &sessionId)) |
| == NULL) |
| { |
| limPrintMacAddr(pMac, pChannelChangeReq->bssid, LOGE); |
| PELOGE(limLog(pMac, LOGE, |
| "%s[%d]: Session does not exist for given bssId", |
| __func__, __LINE__ );) |
| return; |
| } |
| |
| if (LIM_IS_AP_ROLE(psessionEntry)) |
| psessionEntry->channelChangeReasonCode = LIM_SWITCH_CHANNEL_SAP_DFS; |
| else |
| psessionEntry->channelChangeReasonCode = LIM_SWITCH_CHANNEL_OPERATION; |
| |
| maxTxPwr = cfgGetRegulatoryMaxTransmitPower( pMac, |
| pChannelChangeReq->targetChannel ); |
| |
| if (pChannelChangeReq->messageType == eWNI_SME_CHANNEL_CHANGE_REQ |
| && |
| maxTxPwr != WDA_MAX_TXPOWER_INVALID) |
| { |
| |
| /* Store the New Channel Params in psessionEntry */ |
| if (psessionEntry->currentOperChannel != |
| pChannelChangeReq->targetChannel || |
| psessionEntry->sub20_channelwidth != |
| pChannelChangeReq->sub20_channelwidth || |
| ((VOS_MONITOR_MODE == vos_get_conparam()) && |
| (pChannelChangeReq->vht_channel_width != |
| psessionEntry->vht_channel_width))) { |
| limLog(pMac, LOGE, |
| FL("switch old chn %d --> new chn %d CH width - %d"), |
| psessionEntry->currentOperChannel, |
| pChannelChangeReq->targetChannel, |
| pChannelChangeReq->vht_channel_width); |
| |
| |
| #ifdef WLAN_FEATURE_11AC |
| if(psessionEntry->vhtCapability) |
| { |
| |
| chanWidth = pChannelChangeReq->vht_channel_width; |
| |
| if(chanWidth == eHT_CHANNEL_WIDTH_20MHZ || chanWidth == eHT_CHANNEL_WIDTH_40MHZ) |
| { |
| psessionEntry->vhtTxChannelWidthSet = |
| WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ; |
| psessionEntry->apChanWidth = |
| WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ; |
| /* |
| * In case of DFS operation, If AP falls back to lower |
| * bandwidth [< 80Mhz] then there is no need of |
| * Center freq segment. So reset it to zero. |
| */ |
| if (cfgSetInt(pMac, |
| WNI_CFG_VHT_CHANNEL_CENTER_FREQ_SEGMENT1, |
| 0) |
| != eSIR_SUCCESS) |
| { |
| limLog(pMac, LOGP, |
| FL("couldn't reset center freq seg 0 in beacon")); |
| } |
| psessionEntry->apCenterChan = 0; |
| } |
| if (chanWidth == eHT_CHANNEL_WIDTH_80MHZ) |
| { |
| psessionEntry->vhtTxChannelWidthSet = |
| WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ; |
| psessionEntry->apChanWidth = |
| WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ; |
| |
| centerChan = limGetCenterChannel(pMac, pChannelChangeReq->targetChannel, |
| pChannelChangeReq->cbMode,WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ); |
| if(centerChan != eSIR_CFG_INVALID_ID) |
| { |
| limLog(pMac, LOGW, FL("***Center Channel for 80MHZ channel width = %d"),centerChan); |
| psessionEntry->apCenterChan = centerChan; |
| if (cfgSetInt(pMac, WNI_CFG_VHT_CHANNEL_CENTER_FREQ_SEGMENT1, centerChan) |
| != eSIR_SUCCESS) |
| { |
| limLog(pMac, LOGP, FL("could not set WNI_CFG_CHANNEL_BONDING_MODE at CFG")); |
| } |
| } |
| } |
| |
| } |
| psessionEntry->htSecondaryChannelOffset = limGetHTCBState(pChannelChangeReq->cbMode); |
| psessionEntry->htSupportedChannelWidthSet = (pChannelChangeReq->cbMode ? 1 : 0); |
| |
| psessionEntry->htRecommendedTxWidthSet = |
| psessionEntry->htSupportedChannelWidthSet; |
| psessionEntry->currentOperChannel = |
| pChannelChangeReq->targetChannel; |
| psessionEntry->limRFBand = |
| limGetRFBand(psessionEntry->currentOperChannel); |
| |
| /* Update sub 20MHz channel width */ |
| psessionEntry->sub20_channelwidth = |
| pChannelChangeReq->sub20_channelwidth; |
| psessionEntry->vht_channel_width = |
| pChannelChangeReq->vht_channel_width; |
| // Initialize 11h Enable Flag |
| if (CHAN_HOP_ALL_BANDS_ENABLE || |
| SIR_BAND_5_GHZ == psessionEntry->limRFBand) { |
| if (wlan_cfgGetInt(pMac, WNI_CFG_11H_ENABLED, &val) != |
| eSIR_SUCCESS) |
| limLog(pMac, LOGP, |
| FL("Fail to get WNI_CFG_11H_ENABLED ")); |
| } |
| |
| psessionEntry->lim11hEnable = val; |
| psessionEntry->dot11mode = pChannelChangeReq->dot11mode; |
| |
| vos_mem_copy((void*)&psessionEntry->rateSet, |
| (void*)&pChannelChangeReq->operational_rateset, |
| sizeof(tSirMacRateSet)); |
| vos_mem_copy((void*)&psessionEntry->extRateSet, |
| (void*)&pChannelChangeReq->extended_rateset, |
| sizeof(tSirMacRateSet)); |
| |
| limSetChannel(pMac, pChannelChangeReq->targetChannel, |
| psessionEntry->htSecondaryChannelOffset, |
| maxTxPwr, |
| psessionEntry->peSessionId); |
| #endif |
| } |
| |
| } |
| else |
| { |
| limLog(pMac, LOGE,FL("Invalid Request/maxTxPwr")); |
| } |
| } |
| |
| /****************************************************************************** |
| * limStartBssUpdateAddIEBuffer() |
| * |
| *FUNCTION: |
| * This function checks the src buffer and its length and then malloc for |
| * dst buffer update the same |
| * |
| *LOGIC: |
| * |
| *ASSUMPTIONS: |
| * |
| *NOTE: |
| * |
| * @param pMac Pointer to Global MAC structure |
| * @param **pDstData_buff A pointer to pointer of tANI_U8 dst buffer |
| * @param *pDstDataLen A pointer to pointer of tANI_U16 dst buffer length |
| * @param *pSrcData_buff A pointer of tANI_U8 src buffer |
| * @param srcDataLen src buffer length |
| ******************************************************************************/ |
| |
| static void |
| limStartBssUpdateAddIEBuffer(tpAniSirGlobal pMac, |
| tANI_U8 **pDstData_buff, |
| tANI_U16 *pDstDataLen, |
| tANI_U8 *pSrcData_buff, |
| tANI_U16 srcDataLen) |
| { |
| |
| if (srcDataLen > 0 && pSrcData_buff != NULL) |
| { |
| *pDstDataLen = srcDataLen; |
| |
| *pDstData_buff = vos_mem_malloc(*pDstDataLen); |
| |
| if (NULL == *pDstData_buff) |
| { |
| PELOGE(limLog(pMac, LOGE, FL("AllocateMemory failed for " |
| "pDstData_buff"));) |
| return; |
| } |
| vos_mem_copy(*pDstData_buff, pSrcData_buff, *pDstDataLen); |
| } |
| else |
| { |
| *pDstData_buff = NULL; |
| *pDstDataLen = 0; |
| } |
| } |
| /****************************************************************************** |
| * limUpdateAddIEBuffer() |
| * |
| *FUNCTION: |
| * This function checks the src buffer and length if src buffer length more |
| * than dst buffer length then free the dst buffer and malloc for the new src |
| * length, and update the dst buffer and length. But if dst buffer is bigger |
| * than src buffer length then it just update the dst buffer and length |
| * |
| *LOGIC: |
| * |
| *ASSUMPTIONS: |
| * |
| *NOTE: |
| * |
| * @param pMac Pointer to Global MAC structure |
| * @param **pDstData_buff A pointer to pointer of tANI_U8 dst buffer |
| * @param *pDstDataLen A pointer to pointer of tANI_U16 dst buffer length |
| * @param *pSrcData_buff A pointer of tANI_U8 src buffer |
| * @param srcDataLen src buffer length |
| ******************************************************************************/ |
| |
| static void |
| limUpdateAddIEBuffer(tpAniSirGlobal pMac, |
| tANI_U8 **pDstData_buff, |
| tANI_U16 *pDstDataLen, |
| tANI_U8 *pSrcData_buff, |
| tANI_U16 srcDataLen) |
| { |
| |
| if (NULL == pSrcData_buff) |
| { |
| limLog(pMac, LOGE, FL("src buffer is null.")); |
| return; |
| } |
| |
| if (srcDataLen > *pDstDataLen) |
| { |
| *pDstDataLen = srcDataLen; |
| /* free old buffer */ |
| vos_mem_free(*pDstData_buff); |
| /* allocate a new */ |
| *pDstData_buff = vos_mem_malloc(*pDstDataLen); |
| |
| if (NULL == *pDstData_buff) |
| { |
| limLog(pMac, LOGE, FL("Memory allocation failed.")); |
| *pDstDataLen = 0; |
| return; |
| } |
| } |
| |
| /* copy the content of buffer into dst buffer |
| */ |
| *pDstDataLen = srcDataLen; |
| vos_mem_copy(*pDstData_buff, pSrcData_buff, *pDstDataLen); |
| |
| } |
| |
| /** |
| * limUpdateIBssPropAddIEs() - update IBSS prop IE |
| * @pMac : Pointer to Global MAC structure |
| * @pDstData_buff : A pointer to pointer of tANI_U8 dst buffer |
| * @pDstDataLen : A pointer to pointer of tANI_U16 dst buffer length |
| * @pModifyIE : A pointer to tSirModifyIE |
| * |
| * This function replaces previous ibss prop_ie with new ibss prop_ie. |
| * |
| * Return: |
| * True or false depending upon whether IE is updated or not |
| */ |
| static tANI_BOOLEAN |
| limUpdateIBssPropAddIEs(tpAniSirGlobal pMac, tANI_U8 **pDstData_buff, |
| tANI_U16 *pDstDataLen, tSirModifyIE *pModifyIE) |
| { |
| int32_t oui_length; |
| uint8_t *ibss_ie = NULL; |
| uint8_t *vendor_ie; |
| #define MAC_VENDOR_OUI "\x00\x16\x32" |
| #define MAC_VENDOR_SIZE 3 |
| |
| ibss_ie = pModifyIE->pIEBuffer; |
| oui_length = pModifyIE->oui_length; |
| |
| if ((0 == oui_length) || (NULL == ibss_ie)) { |
| VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, |
| FL("Invalid set IBSS vendor IE comamnd length %d ibss_ie %pK"), |
| oui_length, ibss_ie); |
| return FALSE; |
| } |
| /* |
| * Why replace only beacon OUI data here: |
| * 1. other ie (such as wpa) shall not be overwritten here. |
| * 2. per spec, beacon oui ie might be set twice and original one |
| * shall be updated. |
| */ |
| vendor_ie = cfg_get_vendor_ie_ptr_from_oui(pMac, MAC_VENDOR_OUI, |
| MAC_VENDOR_SIZE, *pDstData_buff, *pDstDataLen); |
| |
| if (vendor_ie) { |
| VOS_ASSERT((vendor_ie[1] + 2) == pModifyIE->ieBufferlength); |
| vos_mem_copy(vendor_ie, pModifyIE->pIEBuffer, |
| pModifyIE->ieBufferlength); |
| } else { |
| uint8_t *new_ptr; |
| uint16_t new_length; |
| |
| if (USHRT_MAX - pModifyIE->ieBufferlength < *pDstDataLen) { |
| limLog(pMac,LOGE,FL("U16 overflow due to %d + %d"), |
| pModifyIE->ieBufferlength, *pDstDataLen); |
| return false; |
| } |
| |
| new_length = pModifyIE->ieBufferlength + *pDstDataLen; |
| new_ptr = vos_mem_malloc(new_length); |
| |
| if (NULL == new_ptr) { |
| limLog(pMac, LOGE, FL("Memory allocation failed.")); |
| return FALSE; |
| } |
| vos_mem_copy(new_ptr, *pDstData_buff, *pDstDataLen); |
| vos_mem_copy(&new_ptr[*pDstDataLen], pModifyIE->pIEBuffer, |
| pModifyIE->ieBufferlength); |
| vos_mem_free(*pDstData_buff); |
| *pDstDataLen = new_length; |
| *pDstData_buff = new_ptr; |
| } |
| return TRUE; |
| } |
| |
| /****************************************************************************** |
| * limProcessModifyAddIEs() |
| * |
| *FUNCTION: |
| * This function is called by limProcessMessageQueue(). This |
| * function update the PE buffers for additional IEs. |
| * |
| *LOGIC: |
| * |
| *ASSUMPTIONS: |
| * |
| *NOTE: |
| * |
| * @param pMac Pointer to Global MAC structure |
| * @param *pMsgBuf A pointer to the SME message buffer |
| ******************************************************************************/ |
| static void |
| limProcessModifyAddIEs(tpAniSirGlobal pMac, tANI_U32 *pMsg) |
| { |
| tpSirModifyIEsInd pModifyAddIEs = (tpSirModifyIEsInd)pMsg; |
| tANI_U8 sessionId; |
| tANI_BOOLEAN ret = FALSE; |
| |
| /* Incoming message has smeSession, use BSSID to find PE session*/ |
| tpPESession psessionEntry = peFindSessionByBssid(pMac, |
| pModifyAddIEs->modifyIE.bssid, |
| &sessionId); |
| |
| if (NULL != psessionEntry) |
| { |
| if ((0 != pModifyAddIEs->modifyIE.ieBufferlength) && |
| (0 != pModifyAddIEs->modifyIE.ieIDLen) && |
| (NULL != pModifyAddIEs->modifyIE.pIEBuffer)) |
| { |
| |
| switch (pModifyAddIEs->updateType) |
| { |
| case eUPDATE_IE_PROBE_RESP: |
| { |
| /* Probe resp */ |
| if (LIM_IS_IBSS_ROLE(psessionEntry)) { |
| limUpdateIBssPropAddIEs(pMac, |
| &psessionEntry->addIeParams.probeRespData_buff, |
| &psessionEntry->addIeParams.probeRespDataLen, |
| &pModifyAddIEs->modifyIE); |
| } |
| break; |
| } |
| case eUPDATE_IE_ASSOC_RESP: |
| /* assoc resp IE */ |
| if (psessionEntry->addIeParams.assocRespDataLen == 0) |
| { |
| VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, |
| FL("assoc resp add ie not present %d"), |
| psessionEntry->addIeParams.assocRespDataLen); |
| } |
| /* search through the buffer and modify the IE */ |
| break; |
| case eUPDATE_IE_PROBE_BCN: |
| { |
| /*probe beacon IE*/ |
| if (LIM_IS_IBSS_ROLE(psessionEntry)) { |
| ret = limUpdateIBssPropAddIEs(pMac, |
| &psessionEntry->addIeParams.probeRespBCNData_buff, |
| &psessionEntry->addIeParams.probeRespBCNDataLen, |
| &pModifyAddIEs->modifyIE); |
| } |
| if (ret == TRUE && pModifyAddIEs->modifyIE.notify) |
| { |
| limHandleParamUpdate(pMac, pModifyAddIEs->updateType); |
| } |
| break; |
| } |
| default: |
| limLog(pMac, LOGE, FL("unhandled buffer type %d."), |
| pModifyAddIEs->updateType); |
| break; |
| } |
| } |
| else |
| { |
| limLog(pMac, LOGE, FL("Invalid request pIEBuffer %pK ieBufferlength" |
| " %d ieIDLen %d ieID %d. update Type %d"), |
| pModifyAddIEs->modifyIE.pIEBuffer, |
| pModifyAddIEs->modifyIE.ieBufferlength, |
| pModifyAddIEs->modifyIE.ieID, |
| pModifyAddIEs->modifyIE.ieIDLen, |
| pModifyAddIEs->updateType); |
| } |
| } |
| else |
| { |
| limLog(pMac, LOGE, FL("Session not found for given bssid. " |
| MAC_ADDRESS_STR), MAC_ADDR_ARRAY(pModifyAddIEs->modifyIE.bssid)); |
| } |
| vos_mem_free(pModifyAddIEs->modifyIE.pIEBuffer); |
| pModifyAddIEs->modifyIE.pIEBuffer = NULL; |
| |
| } |
| |
| /** |
| * lim_process_set_pdev_IEs() - process the set pdev IE req |
| * |
| * @mac_ctx: Pointer to Global MAC structure |
| * @msg_buf: Pointer to the SME message buffer |
| * |
| * This function is called by limProcessMessageQueue(). This |
| * function sets the PDEV IEs to the FW. |
| * |
| * Return: None |
| */ |
| static void lim_process_set_pdev_IEs(tpAniSirGlobal mac_ctx, tANI_U32 *msg_buf) |
| { |
| struct sir_set_ht_vht_cfg *ht_vht_cfg; |
| |
| ht_vht_cfg = (struct sir_set_ht_vht_cfg*)msg_buf; |
| |
| if (NULL == ht_vht_cfg) { |
| limLog(mac_ctx, LOGE, FL("NULL ht_vht_cfg")); |
| return; |
| } |
| |
| limLog(mac_ctx, LOG1, FL("rcvd set pdev ht vht ie req with nss = %d"), |
| ht_vht_cfg->nss); |
| lim_set_pdev_ht_ie(mac_ctx, ht_vht_cfg->pdev_id, ht_vht_cfg->nss); |
| |
| if (IS_DOT11_MODE_VHT(ht_vht_cfg->dot11mode)) |
| lim_set_pdev_vht_ie(mac_ctx, ht_vht_cfg->pdev_id, |
| ht_vht_cfg->nss); |
| } |
| |
| /** |
| * lim_set_pdev_ht_ie() - sends the set HT IE req to FW |
| * |
| * @mac_ctx: Pointer to Global MAC structure |
| * @pdev_id: pdev id to set the IE. |
| * @nss: Nss values to prepare the HT IE. |
| * |
| * Prepares the HT IE with self capabilities for different |
| * Nss values and sends the set HT IE req to FW. |
| * |
| * Return: None |
| */ |
| static void lim_set_pdev_ht_ie(tpAniSirGlobal mac_ctx, tANI_U8 pdev_id, |
| tANI_U8 nss) |
| { |
| struct set_ie_param *ie_params; |
| tSirMsgQ msg; |
| tSirRetStatus rc = eSIR_SUCCESS; |
| v_U8_t *p_ie = NULL; |
| tHtCaps *p_ht_cap; |
| int i; |
| |
| for (i = nss; i > 0; i--) { |
| ie_params = vos_mem_malloc(sizeof(*ie_params)); |
| if (NULL == ie_params) { |
| limLog(mac_ctx, LOGE, FL("mem alloc failed")); |
| return; |
| } |
| ie_params->nss = i; |
| ie_params->pdev_id = pdev_id; |
| ie_params->ie_type = DOT11_HT_IE; |
| /* 2 for IE len and EID */ |
| ie_params->ie_len = 2 + sizeof(tHtCaps); |
| ie_params->ie_ptr = vos_mem_malloc(ie_params->ie_len); |
| if (NULL == ie_params->ie_ptr) { |
| vos_mem_free(ie_params); |
| limLog(mac_ctx, LOGE, FL("mem alloc failed")); |
| return; |
| } |
| *ie_params->ie_ptr = SIR_MAC_HT_CAPABILITIES_EID; |
| *(ie_params->ie_ptr + 1) = ie_params->ie_len - 2; |
| lim_set_ht_caps(mac_ctx, NULL, ie_params->ie_ptr, |
| ie_params->ie_len); |
| |
| if (1 == i) { |
| p_ie = limGetIEPtr(mac_ctx, ie_params->ie_ptr, |
| ie_params->ie_len, |
| DOT11F_EID_HTCAPS, ONE_BYTE); |
| if (NULL == p_ie) { |
| vos_mem_free(ie_params->ie_ptr); |
| vos_mem_free(ie_params); |
| limLog(mac_ctx, LOGE, FL( |
| "failed to get IE ptr")); |
| return; |
| } |
| p_ht_cap = (tHtCaps *)&p_ie[2]; |
| p_ht_cap->supportedMCSSet[1] = 0; |
| p_ht_cap->txSTBC = 0; |
| } |
| |
| msg.type = WDA_SET_PDEV_IE_REQ; |
| msg.bodyptr = ie_params; |
| msg.bodyval = 0; |
| |
| rc = wdaPostCtrlMsg(mac_ctx, &msg); |
| if (rc != eSIR_SUCCESS) { |
| limLog(mac_ctx, LOGE, FL( |
| "wdaPostCtrlMsg() return failure")); |
| vos_mem_free(ie_params->ie_ptr); |
| vos_mem_free(ie_params); |
| return; |
| } |
| } |
| } |
| |
| /** |
| * lim_set_pdev_vht_ie() - sends the set VHT IE to req FW |
| * |
| * @mac_ctx: Pointer to Global MAC structure |
| * @pdev_id: pdev id to set the IE. |
| * @nss: Nss values to prepare the VHT IE. |
| * |
| * Prepares the VHT IE with self capabilities for different |
| * Nss values and sends the set VHT IE req to FW. |
| * |
| * Return: None |
| */ |
| static void lim_set_pdev_vht_ie(tpAniSirGlobal mac_ctx, tANI_U8 pdev_id, |
| tANI_U8 nss) |
| { |
| struct set_ie_param *ie_params; |
| tSirMsgQ msg; |
| tSirRetStatus rc = eSIR_SUCCESS; |
| v_U8_t *p_ie = NULL; |
| tSirMacVHTCapabilityInfo *vht_cap; |
| int i; |
| tSirVhtMcsInfo *vht_mcs; |
| |
| for (i = nss; i > 0; i--) { |
| ie_params = vos_mem_malloc(sizeof(*ie_params)); |
| if (NULL == ie_params) { |
| limLog(mac_ctx, LOGE, FL("mem alloc failed")); |
| return; |
| } |
| ie_params->nss = i; |
| ie_params->pdev_id = pdev_id; |
| ie_params->ie_type = DOT11_VHT_IE; |
| /* 2 for IE len and EID */ |
| ie_params->ie_len = 2 + sizeof(tSirMacVHTCapabilityInfo) + |
| sizeof(tSirVhtMcsInfo); |
| ie_params->ie_ptr = vos_mem_malloc(ie_params->ie_len); |
| if (NULL == ie_params->ie_ptr) { |
| vos_mem_free(ie_params); |
| limLog(mac_ctx, LOGE, FL("mem alloc failed")); |
| return; |
| } |
| *ie_params->ie_ptr = SIR_MAC_VHT_CAPABILITIES_EID; |
| *(ie_params->ie_ptr + 1) = ie_params->ie_len - 2; |
| lim_set_vht_caps(mac_ctx, NULL, ie_params->ie_ptr, |
| ie_params->ie_len); |
| |
| if (1 == i) { |
| p_ie = limGetIEPtr(mac_ctx, ie_params->ie_ptr, |
| ie_params->ie_len, |
| DOT11F_EID_VHTCAPS, ONE_BYTE); |
| if (NULL == p_ie) { |
| vos_mem_free(ie_params->ie_ptr); |
| vos_mem_free(ie_params); |
| limLog(mac_ctx, LOGE, FL( |
| "failed to get IE ptr")); |
| return; |
| } |
| vht_cap = (tSirMacVHTCapabilityInfo *)&p_ie[2]; |
| vht_cap->txSTBC = 0; |
| vht_mcs = |
| (tSirVhtMcsInfo *)&p_ie[2 + |
| sizeof(tSirMacVHTCapabilityInfo)]; |
| vht_mcs->rxMcsMap |= DISABLE_NSS2_MCS; |
| vht_mcs->rxHighest = |
| VHT_RX_HIGHEST_SUPPORTED_DATA_RATE_1_1; |
| vht_mcs->txMcsMap |= DISABLE_NSS2_MCS; |
| vht_mcs->txHighest = |
| VHT_TX_HIGHEST_SUPPORTED_DATA_RATE_1_1; |
| } |
| msg.type = WDA_SET_PDEV_IE_REQ; |
| msg.bodyptr = ie_params; |
| msg.bodyval = 0; |
| |
| rc = wdaPostCtrlMsg(mac_ctx, &msg); |
| if (rc != eSIR_SUCCESS) { |
| limLog(mac_ctx, LOGE, FL( |
| "wdaPostCtrlMsg() return failure")); |
| vos_mem_free(ie_params->ie_ptr); |
| vos_mem_free(ie_params); |
| return; |
| } |
| } |
| } |
| /****************************************************************************** |
| * limProcessUpdateAddIEs() |
| * |
| *FUNCTION: |
| * This function is called by limProcessMessageQueue(). This |
| * function update the PE buffers for additional IEs. |
| * |
| *LOGIC: |
| * |
| *ASSUMPTIONS: |
| * |
| *NOTE: |
| * |
| * @param pMac Pointer to Global MAC structure |
| * @param *pMsgBuf A pointer to the SME message buffer |
| ******************************************************************************/ |
| static void |
| limProcessUpdateAddIEs(tpAniSirGlobal pMac, tANI_U32 *pMsg) |
| { |
| tpSirUpdateIEsInd pUpdateAddIEs = (tpSirUpdateIEsInd)pMsg; |
| tANI_U8 sessionId; |
| /* incoming message has smeSession, use BSSID to find PE session*/ |
| tpPESession psessionEntry = peFindSessionByBssid(pMac, |
| pUpdateAddIEs->updateIE.bssid, |
| &sessionId); |
| |
| if (NULL != psessionEntry) |
| { |
| /* if len is 0, upper layer requested freeing of buffer */ |
| if (0 == pUpdateAddIEs->updateIE.ieBufferlength) |
| { |
| switch (pUpdateAddIEs->updateType) |
| { |
| case eUPDATE_IE_PROBE_RESP: |
| vos_mem_free(psessionEntry->addIeParams.probeRespData_buff); |
| psessionEntry->addIeParams.probeRespData_buff = NULL; |
| psessionEntry->addIeParams.probeRespDataLen = 0; |
| break; |
| case eUPDATE_IE_ASSOC_RESP: |
| vos_mem_free(psessionEntry->addIeParams.assocRespData_buff); |
| psessionEntry->addIeParams.assocRespData_buff = NULL; |
| psessionEntry->addIeParams.assocRespDataLen = 0; |
| break; |
| case eUPDATE_IE_PROBE_BCN: |
| vos_mem_free(psessionEntry->addIeParams.probeRespBCNData_buff); |
| psessionEntry->addIeParams.probeRespBCNData_buff = NULL; |
| psessionEntry->addIeParams.probeRespBCNDataLen = 0; |
| |
| if (pUpdateAddIEs->updateIE.notify) |
| { |
| limHandleParamUpdate(pMac, pUpdateAddIEs->updateType); |
| } |
| break; |
| default: |
| break; |
| } |
| return; |
| } |
| |
| switch (pUpdateAddIEs->updateType) |
| { |
| case eUPDATE_IE_PROBE_RESP: |
| { |
| if (pUpdateAddIEs->updateIE.append) |
| { |
| /* In case of append, allocate new memory with combined length */ |
| tANI_U16 new_length = pUpdateAddIEs->updateIE.ieBufferlength + |
| psessionEntry->addIeParams.probeRespDataLen; |
| tANI_U8 *new_ptr = vos_mem_malloc(new_length); |
| /* Multiple back to back append commands |
| * can lead to a huge length.So, check |
| * for the validity of the length. |
| */ |
| if (psessionEntry->addIeParams.probeRespDataLen > |
| (USHRT_MAX - pUpdateAddIEs->updateIE.ieBufferlength)) |
| { |
| limLog(pMac, LOGE, |
| FL("IE Length overflow, curr:%d, new:%d."), |
| psessionEntry->addIeParams.probeRespDataLen, |
| pUpdateAddIEs->updateIE.ieBufferlength); |
| vos_mem_free(pUpdateAddIEs->updateIE.pAdditionIEBuffer); |
| pUpdateAddIEs->updateIE.pAdditionIEBuffer = NULL; |
| return; |
| } |
| if (NULL == new_ptr) |
| { |
| limLog(pMac, LOGE, FL("Memory allocation failed.")); |
| /* free incoming buffer in message */ |
| vos_mem_free(pUpdateAddIEs->updateIE.pAdditionIEBuffer); |
| return; |
| } |
| /* append buffer to end of local buffers */ |
| vos_mem_copy(new_ptr, |
| psessionEntry->addIeParams.probeRespData_buff, |
| psessionEntry->addIeParams.probeRespDataLen); |
| vos_mem_copy(&new_ptr[psessionEntry->addIeParams.probeRespDataLen], |
| pUpdateAddIEs->updateIE.pAdditionIEBuffer, |
| pUpdateAddIEs->updateIE.ieBufferlength); |
| /* free old memory*/ |
| vos_mem_free(psessionEntry->addIeParams.probeRespData_buff); |
| /* adjust length accordingly */ |
| psessionEntry->addIeParams.probeRespDataLen = new_length; |
| /* save refernece of local buffer in PE session */ |
| psessionEntry->addIeParams.probeRespData_buff = new_ptr; |
| /* free incoming buffer in message */ |
| vos_mem_free(pUpdateAddIEs->updateIE.pAdditionIEBuffer); |
| return; |
| } |
| limUpdateAddIEBuffer(pMac, |
| &psessionEntry->addIeParams.probeRespData_buff, |
| &psessionEntry->addIeParams.probeRespDataLen, |
| pUpdateAddIEs->updateIE.pAdditionIEBuffer, |
| pUpdateAddIEs->updateIE.ieBufferlength); |
| break; |
| } |
| case eUPDATE_IE_ASSOC_RESP: |
| /*assoc resp IE*/ |
| limUpdateAddIEBuffer(pMac, |
| &psessionEntry->addIeParams.assocRespData_buff, |
| &psessionEntry->addIeParams.assocRespDataLen, |
| pUpdateAddIEs->updateIE.pAdditionIEBuffer, |
| pUpdateAddIEs->updateIE.ieBufferlength); |
| break; |
| case eUPDATE_IE_PROBE_BCN: |
| /*probe resp Bcn IE*/ |
| limUpdateAddIEBuffer(pMac, |
| &psessionEntry->addIeParams.probeRespBCNData_buff, |
| &psessionEntry->addIeParams.probeRespBCNDataLen, |
| pUpdateAddIEs->updateIE.pAdditionIEBuffer, |
| pUpdateAddIEs->updateIE.ieBufferlength); |
| if (pUpdateAddIEs->updateIE.notify) |
| { |
| limHandleParamUpdate(pMac, pUpdateAddIEs->updateType); |
| } |
| break; |
| default: |
| limLog(pMac, LOGE, FL("unhandled buffer type %d."), |
| pUpdateAddIEs->updateType); |
| break; |
| } |
| } |
| else |
| { |
| limLog(pMac, LOGE, FL("Session not found for given bssid. " |
| MAC_ADDRESS_STR), MAC_ADDR_ARRAY(pUpdateAddIEs->updateIE.bssid)); |
| } |
| vos_mem_free(pUpdateAddIEs->updateIE.pAdditionIEBuffer); |
| pUpdateAddIEs->updateIE.pAdditionIEBuffer = NULL; |
| |
| } |
| |
| /** |
| * send_extended_chan_switch_action_frame()- function to send ECSA |
| * action frame for each sta connected to SAP/GO and AP in case of |
| * STA . |
| * @mac_ctx: pointer to global mac structure |
| * @new_channel: new channel to switch to. |
| * @ch_bandwidth: BW of channel to calculate op_class |
| * @session_entry: pe session |
| * |
| * This function is called to send ECSA frame for STA/CLI and SAP/GO. |
| * |
| * Return: void |
| */ |
| |
| static void send_extended_chan_switch_action_frame(tpAniSirGlobal mac_ctx, |
| uint16_t new_channel, uint8_t ch_bandwidth, |
| tpPESession session_entry) |
| { |
| uint16_t op_class; |
| uint8_t switch_mode = 0, i; |
| tpDphHashNode psta; |
| uint8_t switch_count; |
| |
| |
| op_class = regdm_get_opclass_from_channel( |
| mac_ctx->scan.countryCodeCurrent, |
| new_channel, |
| ch_bandwidth); |
| |
| if (LIM_IS_AP_ROLE(session_entry) && |
| (mac_ctx->sap.SapDfsInfo.disable_dfs_ch_switch == VOS_FALSE)) |
| switch_mode = session_entry->gLimChannelSwitch.switchMode; |
| |
| switch_count = session_entry->gLimChannelSwitch.switchCount; |
| |
| if (LIM_IS_AP_ROLE(session_entry)) { |
| /* first node in hash table not used */ |
| for (i = 0; i < (mac_ctx->lim.maxStation + 1); i++) { |
| psta = |
| session_entry->dph.dphHashTable.pDphNodeArray + i; |
| if (psta && psta->added) { |
| lim_send_extended_chan_switch_action_frame( |
| mac_ctx, |
| psta->staAddr, |
| switch_mode, op_class, new_channel, |
| switch_count, session_entry); |
| } |
| } |
| } else if (LIM_IS_STA_ROLE(session_entry)) { |
| lim_send_extended_chan_switch_action_frame(mac_ctx, |
| session_entry->bssId, |
| switch_mode, op_class, new_channel, |
| switch_count, session_entry); |
| } |
| |
| } |
| |
| /** |
| * lim_send_chan_switch_action_frame()- Send an action frame |
| * containing CSA IE or ECSA IE depending on the connected |
| * sta capability. |
| * |
| * @mac_ctx: pointer to global mac structure |
| * @new_channel: new channel to switch to. |
| * @ch_bandwidth: BW of channel to calculate op_class |
| * @session_entry: pe session |
| * |
| * Return: void |
| */ |
| void lim_send_chan_switch_action_frame(tpAniSirGlobal mac_ctx, |
| uint16_t new_channel, |
| uint8_t ch_bandwidth, |
| tpPESession session_entry) |
| { |
| uint16_t op_class; |
| uint8_t switch_mode = 0, i; |
| uint8_t switch_count; |
| tpDphHashNode psta; |
| tpDphHashNode dph_node_array_ptr; |
| |
| dph_node_array_ptr = session_entry->dph.dphHashTable.pDphNodeArray; |
| |
| op_class = regdm_get_opclass_from_channel( |
| mac_ctx->scan.countryCodeCurrent, |
| new_channel, ch_bandwidth); |
| |
| if (LIM_IS_AP_ROLE(session_entry) && |
| mac_ctx->sap.SapDfsInfo.disable_dfs_ch_switch == VOS_FALSE) |
| switch_mode = session_entry->gLimChannelSwitch.switchMode; |
| |
| switch_count = session_entry->gLimChannelSwitch.switchCount; |
| |
| if (LIM_IS_AP_ROLE(session_entry)) { |
| for (i = 0; i < mac_ctx->lim.maxStation; i++) { |
| psta = dph_node_array_ptr + i; |
| if (!(psta && psta->added)) |
| continue; |
| if (session_entry->lim_non_ecsa_cap_num == 0) |
| lim_send_extended_chan_switch_action_frame |
| (mac_ctx, psta->staAddr, switch_mode, |
| op_class, new_channel, switch_count, |
| session_entry); |
| else |
| limSendChannelSwitchMgmtFrame |
| (mac_ctx, psta->staAddr, switch_mode, |
| new_channel, switch_count, |
| session_entry); |
| } |
| } else if (LIM_IS_STA_ROLE(session_entry)) { |
| lim_send_extended_chan_switch_action_frame |
| (mac_ctx, session_entry->bssId, switch_mode, op_class, |
| new_channel, switch_count, session_entry); |
| } |
| } |
| |
| /** |
| * limProcessSmeDfsCsaIeRequest() |
| * |
| *FUNCTION: |
| * This function is called by limProcessMessageQueue(). This |
| * function processes SME request messages from HDD or upper layer |
| * application. |
| * |
| *LOGIC: |
| * |
| *ASSUMPTIONS: |
| * |
| *NOTE: |
| * |
| * @param pMac Pointer to Global MAC structure |
| * @param *pMsgBuf A pointer to the SME message buffer |
| */ |
| static void |
| limProcessSmeDfsCsaIeRequest(tpAniSirGlobal pMac, tANI_U32 *pMsg) |
| { |
| |
| tpSirDfsCsaIeRequest pDfsCsaIeRequest = (tSirDfsCsaIeRequest *)pMsg; |
| tpPESession psessionEntry = NULL; |
| tANI_U32 chanWidth = 0; |
| tANI_U8 sessionId; |
| uint8_t target_channel; |
| |
| if ( pMsg == NULL ) |
| { |
| limLog(pMac, LOGE,FL("Buffer is Pointing to NULL")); |
| return; |
| } |
| |
| if ((psessionEntry = |
| peFindSessionByBssid(pMac, |
| pDfsCsaIeRequest->bssid, |
| &sessionId)) == NULL) |
| { |
| limLog(pMac, LOGE, |
| FL("Session not found for given BSSID" MAC_ADDRESS_STR), |
| MAC_ADDR_ARRAY(pDfsCsaIeRequest->bssid)); |
| return; |
| } |
| |
| if (psessionEntry->valid && !LIM_IS_AP_ROLE(psessionEntry)) { |
| limLog(pMac, LOGE, FL("Invalid SystemRole %d"), |
| GET_LIM_SYSTEM_ROLE(psessionEntry)); |
| return; |
| } |
| |
| target_channel = pDfsCsaIeRequest->targetChannel; |
| |
| if ( psessionEntry ) |
| { |
| /* target channel */ |
| psessionEntry->gLimChannelSwitch.primaryChannel = target_channel; |
| |
| /* Channel switch announcement needs to be included in beacon */ |
| psessionEntry->dfsIncludeChanSwIe = VOS_TRUE; |
| |
| psessionEntry->gLimChannelSwitch.switchCount = |
| pDfsCsaIeRequest->ch_switch_beacon_cnt; |
| |
| |
| if (pDfsCsaIeRequest->dfs_ch_switch_disable == VOS_FALSE) |
| psessionEntry->gLimChannelSwitch.switchMode = |
| pDfsCsaIeRequest->ch_switch_mode; |
| |
| |
| psessionEntry->gLimChannelSwitch.secondarySubBand = |
| pDfsCsaIeRequest->ch_bandwidth; |
| |
| /* Sub 20MHz channel width changing request */ |
| psessionEntry->lim_sub20_channel_switch_bandwidth = |
| pDfsCsaIeRequest->sub20_channelwidth; |
| |
| /* Validate if SAP is operating HT or VHT |
| * mode and set the Channel Switch Wrapper |
| * element with the Wide Band Switch |
| * subelement.. |
| */ |
| #ifdef WLAN_FEATURE_11AC |
| if (VOS_TRUE == psessionEntry->vhtCapability) |
| { |
| if (WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ == |
| psessionEntry->vhtTxChannelWidthSet) |
| { |
| chanWidth = eHT_CHANNEL_WIDTH_80MHZ; |
| } |
| else if (WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ == |
| psessionEntry->vhtTxChannelWidthSet) |
| { |
| chanWidth = psessionEntry->htSupportedChannelWidthSet; |
| } |
| |
| /* |
| * Now encode the Wider Channel BW element |
| * depending on the chanWidth. |
| */ |
| switch(chanWidth) |
| { |
| case eHT_CHANNEL_WIDTH_20MHZ: |
| /* |
| * Wide channel BW sublement in channel |
| * wrapper element is not required in case |
| * of 20 Mhz operation. Currently It is set |
| * only set in case of 40/80 Mhz Operation. |
| */ |
| psessionEntry->dfsIncludeChanWrapperIe = VOS_FALSE; |
| psessionEntry->gLimWiderBWChannelSwitch.newChanWidth = |
| WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ; |
| break; |
| case eHT_CHANNEL_WIDTH_40MHZ: |
| psessionEntry->dfsIncludeChanWrapperIe = VOS_TRUE; |
| psessionEntry->gLimWiderBWChannelSwitch.newChanWidth = |
| WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ; |
| break; |
| case eHT_CHANNEL_WIDTH_80MHZ: |
| psessionEntry->dfsIncludeChanWrapperIe = VOS_TRUE; |
| psessionEntry->gLimWiderBWChannelSwitch.newChanWidth = |
| WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ; |
| break; |
| case eHT_CHANNEL_WIDTH_160MHZ: |
| psessionEntry->dfsIncludeChanWrapperIe = VOS_TRUE; |
| psessionEntry->gLimWiderBWChannelSwitch.newChanWidth = |
| WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ; |
| break; |
| default: |
| psessionEntry->dfsIncludeChanWrapperIe = VOS_FALSE; |
| /* Need to handle 80+80 Mhz Scenario |
| * When 80+80 is supported set the |
| * gLimWiderBWChannelSwitch.newChanWidth |
| * to 3 |
| */ |
| PELOGE(limLog(pMac, LOGE, FL("Invalid Channel Width"));) |
| break; |
| } |
| /* |
| * Fetch the center channel based on the channel width |
| */ |
| psessionEntry->gLimWiderBWChannelSwitch.newCenterChanFreq0 = |
| limGetCenterChannel( |
| pMac, target_channel, |
| psessionEntry->htSecondaryChannelOffset, |
| psessionEntry->gLimWiderBWChannelSwitch.newChanWidth); |
| /* |
| * This is not applicable for 20/40/80 Mhz. |
| * Only used when we support 80+80 Mhz |
| * operation. In case of 80+80 Mhz, this |
| * parameter indicates center channel |
| * frequency index of 80 Mhz channel |
| * of frequency segment 1. |
| */ |
| psessionEntry->gLimWiderBWChannelSwitch.newCenterChanFreq1 = 0; |
| } |
| #endif |
| /* Send CSA IE request from here */ |
| if (schSetFixedBeaconFields(pMac, psessionEntry) != eSIR_SUCCESS) |
| { |
| PELOGE(limLog(pMac, LOGE, FL("Unable to set CSA IE in beacon"));) |
| return; |
| } |
| |
| /* First beacon update request is sent here, the remaining updates are |
| * done when the FW responds back after sending the first beacon after |
| * the template update |
| */ |
| limSendBeaconInd(pMac, psessionEntry); |
| limLog(pMac, LOG1, |
| FL(" Updated CSA IE, IE COUNT = %d"), |
| psessionEntry->gLimChannelSwitch.switchCount ); |
| /** |
| * Send Action frame after updating the beacon |
| * Action frame is not required if sub20 enabled |
| */ |
| if (pDfsCsaIeRequest->sub20_switch_mode == 0) { |
| if (CHAN_HOP_ALL_BANDS_ENABLE) |
| lim_send_chan_switch_action_frame |
| (pMac, psessionEntry->gLimChannelSwitch.primaryChannel, |
| psessionEntry->gLimChannelSwitch.secondarySubBand, |
| psessionEntry); |
| else |
| send_extended_chan_switch_action_frame |
| (pMac, psessionEntry->gLimChannelSwitch.primaryChannel, |
| psessionEntry->gLimChannelSwitch.secondarySubBand, |
| psessionEntry); |
| } |
| |
| psessionEntry->gLimChannelSwitch.switchCount--; |
| } |
| return; |
| } |
| |
| /** |
| * lim_process_ext_change_channel()- function to send ECSA |
| * action frame for STA/CLI . |
| * @mac_ctx: pointer to global mac structure |
| * @msg: params from sme for new channel. |
| * |
| * This function is called to send ECSA frame for STA/CLI. |
| * |
| * Return: void |
| */ |
| |
| static void lim_process_ext_change_channel(tpAniSirGlobal mac_ctx, |
| uint32_t *msg) |
| { |
| struct sir_sme_ext_cng_chan_req *ext_chng_channel = |
| (struct sir_sme_ext_cng_chan_req *) msg; |
| tpPESession session_entry = NULL; |
| |
| if (NULL == msg) { |
| limLog(mac_ctx, LOGE, FL("Buffer is Pointing to NULL")); |
| return; |
| } |
| session_entry = |
| pe_find_session_by_sme_session_id(mac_ctx, |
| ext_chng_channel->session_id); |
| if (NULL == session_entry) { |
| limLog(mac_ctx, LOGE, |
| FL("Session not found for given session %d"), |
| ext_chng_channel->session_id); |
| return; |
| } |
| if (LIM_IS_AP_ROLE(session_entry)) { |
| limLog(mac_ctx, LOGE, |
| FL("not an STA/CLI session")); |
| return; |
| } |
| send_extended_chan_switch_action_frame(mac_ctx, |
| ext_chng_channel->new_channel, |
| 0, session_entry); |
| } |