| /* |
| * Copyright (c) 2016 The Linux Foundation. All rights reserved. |
| * |
| * Previously licensed under the ISC license by Qualcomm Atheros, Inc. |
| * |
| * Permission to use, copy, modify, and/or distribute this software for |
| * any purpose with or without fee is hereby granted, provided that the |
| * above copyright notice and this permission notice appear in all |
| * copies. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL |
| * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED |
| * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE |
| * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL |
| * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR |
| * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER |
| * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR |
| * PERFORMANCE OF THIS SOFTWARE. |
| */ |
| |
| /** |
| * DOC: lim_process_mlm_host_roam.c |
| * |
| * Host based roaming MLM implementation |
| */ |
| #include "cds_api.h" |
| #include "wni_cfg.h" |
| #include "ani_global.h" |
| #include "sir_api.h" |
| #include "sir_params.h" |
| #include "cfg_api.h" |
| |
| #include "sch_api.h" |
| #include "utils_api.h" |
| #include "lim_utils.h" |
| #include "lim_assoc_utils.h" |
| #include "lim_prop_exts_utils.h" |
| #include "lim_security_utils.h" |
| #include "lim_send_messages.h" |
| #include "lim_send_messages.h" |
| #include "lim_session_utils.h" |
| #include <lim_ft.h> |
| #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM |
| #include "host_diag_core_log.h" |
| #endif |
| #include "wma_if.h" |
| #include "rrm_api.h" |
| static void lim_handle_sme_reaasoc_result(tpAniSirGlobal, tSirResultCodes, |
| uint16_t, tpPESession); |
| /** |
| * lim_process_mlm_reassoc_req() - process mlm reassoc request. |
| * |
| * @mac_ctx: pointer to Global MAC structure |
| * @msg: pointer to the MLM message buffer |
| * |
| * This function is called to process MLM_REASSOC_REQ message |
| * from SME |
| * |
| * Return: None |
| */ |
| void lim_process_mlm_reassoc_req(tpAniSirGlobal mac_ctx, uint32_t *msg) |
| { |
| uint8_t channel, sec_ch_offset; |
| struct tLimPreAuthNode *auth_node; |
| tLimMlmReassocReq *reassoc_req; |
| tLimMlmReassocCnf reassoc_cnf; |
| tpPESession session; |
| |
| if (msg == NULL) { |
| lim_log(mac_ctx, LOGE, FL("Buffer is Pointing to NULL")); |
| return; |
| } |
| |
| reassoc_req = (tLimMlmReassocReq *) msg; |
| session = pe_find_session_by_session_id(mac_ctx, |
| reassoc_req->sessionId); |
| if (NULL == session) { |
| lim_log(mac_ctx, LOGE, |
| FL("Session Does not exist for given sessionId %d"), |
| reassoc_req->sessionId); |
| qdf_mem_free(reassoc_req); |
| return; |
| } |
| |
| lim_log(mac_ctx, LOG1, |
| FL("ReAssoc Req on session %d role %d mlm %d " MAC_ADDRESS_STR), |
| reassoc_req->sessionId, GET_LIM_SYSTEM_ROLE(session), |
| session->limMlmState, MAC_ADDR_ARRAY(reassoc_req->peerMacAddr)); |
| |
| if (LIM_IS_AP_ROLE(session) || |
| (session->limMlmState != |
| eLIM_MLM_LINK_ESTABLISHED_STATE)) { |
| /* |
| * Received Reassoc request in invalid state or |
| * in AP role.Return Reassoc confirm with Invalid |
| * parameters code. |
| */ |
| |
| lim_log(mac_ctx, LOGW, |
| FL("unexpect msg,state %Xrole %d,MAC" MAC_ADDRESS_STR), |
| session->limMlmState, GET_LIM_SYSTEM_ROLE(session), |
| MAC_ADDR_ARRAY(reassoc_req->peerMacAddr)); |
| lim_print_mlm_state(mac_ctx, LOGW, session->limMlmState); |
| reassoc_cnf.resultCode = eSIR_SME_INVALID_PARAMETERS; |
| reassoc_cnf.protStatusCode = eSIR_MAC_UNSPEC_FAILURE_STATUS; |
| goto end; |
| } |
| |
| if (session->pLimMlmReassocReq) |
| qdf_mem_free(session->pLimMlmReassocReq); |
| |
| /* |
| * Hold Re-Assoc request as part of Session, knock-out mac_ctx |
| * Hold onto Reassoc request parameters |
| */ |
| session->pLimMlmReassocReq = reassoc_req; |
| |
| /* See if we have pre-auth context with new AP */ |
| auth_node = lim_search_pre_auth_list(mac_ctx, session->limReAssocbssId); |
| |
| if (!auth_node && (qdf_mem_cmp(reassoc_req->peerMacAddr, |
| session->bssId, |
| sizeof(tSirMacAddr)))) { |
| /* |
| * Either pre-auth context does not exist AND |
| * we are not reassociating with currently |
| * associated AP. |
| * Return Reassoc confirm with not authenticated |
| */ |
| reassoc_cnf.resultCode = eSIR_SME_STA_NOT_AUTHENTICATED; |
| reassoc_cnf.protStatusCode = eSIR_MAC_UNSPEC_FAILURE_STATUS; |
| |
| goto end; |
| } |
| /* assign the sessionId to the timer object */ |
| mac_ctx->lim.limTimers.gLimReassocFailureTimer.sessionId = |
| reassoc_req->sessionId; |
| session->limPrevMlmState = session->limMlmState; |
| session->limMlmState = eLIM_MLM_WT_REASSOC_RSP_STATE; |
| MTRACE(mac_trace(mac_ctx, TRACE_CODE_MLM_STATE, session->peSessionId, |
| session->limMlmState)); |
| |
| /* Derive channel from BSS description and store it at CFG. */ |
| channel = session->limReassocChannelId; |
| sec_ch_offset = session->reAssocHtSecondaryChannelOffset; |
| |
| /* Apply previously set configuration at HW */ |
| lim_apply_configuration(mac_ctx, session); |
| |
| /* store the channel switch sessionEntry in the lim global var */ |
| session->channelChangeReasonCode = |
| LIM_SWITCH_CHANNEL_REASSOC; |
| |
| /* Switch channel to the new Operating channel for Reassoc */ |
| lim_set_channel(mac_ctx, channel, |
| session->ch_center_freq_seg0, |
| session->ch_center_freq_seg1, |
| session->ch_width, |
| session->maxTxPower, |
| session->peSessionId); |
| |
| return; |
| end: |
| reassoc_cnf.protStatusCode = eSIR_MAC_UNSPEC_FAILURE_STATUS; |
| /* Update PE sessio Id */ |
| reassoc_cnf.sessionId = reassoc_req->sessionId; |
| /* Free up buffer allocated for reassocReq */ |
| qdf_mem_free(reassoc_req); |
| session->pLimReAssocReq = NULL; |
| lim_post_sme_message(mac_ctx, LIM_MLM_REASSOC_CNF, |
| (uint32_t *) &reassoc_cnf); |
| } |
| |
| /** |
| * lim_handle_sme_reaasoc_result() - Handle the reassoc result |
| * @pMac: Global MAC Context |
| * @resultCode: Result code |
| * @protStatusCode: Protocol Status Code |
| * @psessionEntry: PE Session |
| * |
| * This function is called to process reassoc failures |
| * upon receiving REASSOC_CNF with a failure code or |
| * MLM_REASSOC_CNF with a success code in case of STA role |
| * |
| * Return: None |
| */ |
| static void lim_handle_sme_reaasoc_result(tpAniSirGlobal pMac, |
| tSirResultCodes resultCode, uint16_t protStatusCode, |
| tpPESession psessionEntry) |
| { |
| tpDphHashNode pStaDs = NULL; |
| uint8_t smesessionId; |
| uint16_t smetransactionId; |
| |
| if (psessionEntry == NULL) { |
| PELOGE(lim_log(pMac, LOGE, FL("psessionEntry is NULL "));) |
| return; |
| } |
| smesessionId = psessionEntry->smeSessionId; |
| smetransactionId = psessionEntry->transactionId; |
| if (resultCode != eSIR_SME_SUCCESS) { |
| pStaDs = |
| dph_get_hash_entry(pMac, DPH_STA_HASH_INDEX_PEER, |
| &psessionEntry->dph.dphHashTable); |
| if (pStaDs != NULL) { |
| pStaDs->mlmStaContext.disassocReason = |
| eSIR_MAC_UNSPEC_FAILURE_REASON; |
| pStaDs->mlmStaContext.cleanupTrigger = |
| eLIM_JOIN_FAILURE; |
| pStaDs->mlmStaContext.resultCode = resultCode; |
| pStaDs->mlmStaContext.protStatusCode = protStatusCode; |
| lim_cleanup_rx_path(pMac, pStaDs, psessionEntry); |
| /* Cleanup if add bss failed */ |
| if (psessionEntry->add_bss_failed) { |
| dph_delete_hash_entry(pMac, |
| pStaDs->staAddr, pStaDs->assocId, |
| &psessionEntry->dph.dphHashTable); |
| goto error; |
| } |
| return; |
| } |
| } |
| error: |
| /* Delete teh session if REASSOC failure occurred. */ |
| if (resultCode != eSIR_SME_SUCCESS) { |
| if (NULL != psessionEntry) { |
| pe_delete_session(pMac, psessionEntry); |
| psessionEntry = NULL; |
| } |
| } |
| lim_send_sme_join_reassoc_rsp(pMac, eWNI_SME_REASSOC_RSP, resultCode, |
| protStatusCode, psessionEntry, smesessionId, smetransactionId); |
| } |
| |
| /** |
| * lim_process_mlm_reassoc_cnf() - process mlm reassoc cnf msg |
| * |
| * @mac_ctx: Pointer to Global MAC structure |
| * @msg_buf: A pointer to the MLM message buffer |
| * |
| * This function is called to process MLM_REASSOC_CNF message from MLM State |
| * machine. |
| * |
| * @Return: void |
| */ |
| void lim_process_mlm_reassoc_cnf(tpAniSirGlobal mac_ctx, uint32_t *msg_buf) |
| { |
| tpPESession session; |
| tLimMlmReassocCnf *lim_mlm_reassoc_cnf; |
| |
| if (msg_buf == NULL) { |
| lim_log(mac_ctx, LOGE, FL("Buffer is Pointing to NULL")); |
| return; |
| } |
| lim_mlm_reassoc_cnf = (tLimMlmReassocCnf *) msg_buf; |
| session = pe_find_session_by_session_id(mac_ctx, |
| lim_mlm_reassoc_cnf->sessionId); |
| if (session == NULL) { |
| lim_log(mac_ctx, LOGE, |
| FL("session Does not exist for given session Id")); |
| return; |
| } |
| if ((session->limSmeState != eLIM_SME_WT_REASSOC_STATE) || |
| LIM_IS_AP_ROLE(session)) { |
| /* |
| * Should not have received Reassocication confirm |
| * from MLM in other states OR on AP. |
| */ |
| lim_log(mac_ctx, LOGE, |
| FL("Rcv unexpected MLM_REASSOC_CNF role %d, sme 0x%X"), |
| GET_LIM_SYSTEM_ROLE(session), session->limSmeState); |
| return; |
| } |
| if (session->pLimReAssocReq) { |
| qdf_mem_free(session->pLimReAssocReq); |
| session->pLimReAssocReq = NULL; |
| } |
| |
| /* |
| * Upon Reassoc success or failure, freeup the cached preauth request, |
| * to ensure that channel switch is now allowed following any change in |
| * HT params. |
| */ |
| if (session->ftPEContext.pFTPreAuthReq) { |
| lim_log(mac_ctx, LOG1, FL("Freeing pFTPreAuthReq= %p"), |
| session->ftPEContext.pFTPreAuthReq); |
| if (session->ftPEContext.pFTPreAuthReq->pbssDescription) { |
| qdf_mem_free( |
| session->ftPEContext.pFTPreAuthReq->pbssDescription); |
| session->ftPEContext.pFTPreAuthReq->pbssDescription = |
| NULL; |
| } |
| qdf_mem_free(session->ftPEContext.pFTPreAuthReq); |
| session->ftPEContext.pFTPreAuthReq = NULL; |
| session->ftPEContext.ftPreAuthSession = false; |
| } |
| |
| #ifdef WLAN_FEATURE_ROAM_OFFLOAD |
| if (session->bRoamSynchInProgress) { |
| QDF_TRACE(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_DEBUG, |
| FL("LFR3:Re-set the LIM Ctxt Roam Synch In Progress")); |
| session->bRoamSynchInProgress = false; |
| } |
| #endif |
| |
| lim_log(mac_ctx, LOG1, FL("Rcv MLM_REASSOC_CNF with result code %d"), |
| lim_mlm_reassoc_cnf->resultCode); |
| if (lim_mlm_reassoc_cnf->resultCode == eSIR_SME_SUCCESS) { |
| /* Successful Reassociation */ |
| QDF_TRACE(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_DEBUG, |
| FL("*** Reassociated with new BSS ***")); |
| |
| session->limSmeState = eLIM_SME_LINK_EST_STATE; |
| MTRACE(mac_trace(mac_ctx, TRACE_CODE_SME_STATE, |
| session->peSessionId, session->limSmeState)); |
| |
| /* Need to send Reassoc rsp with Reassoc success to Host. */ |
| lim_send_sme_join_reassoc_rsp(mac_ctx, eWNI_SME_REASSOC_RSP, |
| lim_mlm_reassoc_cnf->resultCode, |
| lim_mlm_reassoc_cnf->protStatusCode, |
| session, session->smeSessionId, |
| session->transactionId); |
| } else if (lim_mlm_reassoc_cnf->resultCode |
| == eSIR_SME_REASSOC_REFUSED) { |
| /* |
| * Reassociation failure With the New AP but we still have the |
| * link with the Older AP |
| */ |
| session->limSmeState = eLIM_SME_LINK_EST_STATE; |
| MTRACE(mac_trace(mac_ctx, TRACE_CODE_SME_STATE, |
| session->peSessionId, session->limSmeState)); |
| |
| /* Need to send Reassoc rsp with Assoc failure to Host. */ |
| lim_send_sme_join_reassoc_rsp(mac_ctx, eWNI_SME_REASSOC_RSP, |
| lim_mlm_reassoc_cnf->resultCode, |
| lim_mlm_reassoc_cnf->protStatusCode, |
| session, session->smeSessionId, |
| session->transactionId); |
| } else { |
| /* Reassociation failure */ |
| session->limSmeState = eLIM_SME_JOIN_FAILURE_STATE; |
| MTRACE(mac_trace(mac_ctx, TRACE_CODE_SME_STATE, |
| session->peSessionId, session->limSmeState)); |
| /* Need to send Reassoc rsp with Assoc failure to Host. */ |
| lim_handle_sme_reaasoc_result(mac_ctx, |
| lim_mlm_reassoc_cnf->resultCode, |
| lim_mlm_reassoc_cnf->protStatusCode, |
| session); |
| } |
| } |
| |
| /** |
| * lim_process_sta_mlm_add_bss_rsp_ft() - Handle the ADD BSS response |
| * @pMac: Global MAC context |
| * @limMsgQ: ADD BSS Parameters |
| * @psessionEntry: PE Session |
| * |
| * Function to handle WMA_ADD_BSS_RSP, in FT reassoc state. |
| * Send ReAssociation Request. |
| * |
| *Return: None |
| */ |
| void lim_process_sta_mlm_add_bss_rsp_ft(tpAniSirGlobal pMac, |
| tpSirMsgQ limMsgQ, tpPESession psessionEntry) |
| { |
| tLimMlmReassocCnf mlmReassocCnf; /* keep sme */ |
| tpDphHashNode pStaDs = NULL; |
| tpAddStaParams pAddStaParams = NULL; |
| uint32_t listenInterval = WNI_CFG_LISTEN_INTERVAL_STADEF; |
| tpAddBssParams pAddBssParams = (tpAddBssParams) limMsgQ->bodyptr; |
| uint32_t selfStaDot11Mode = 0; |
| |
| /* Sanity Checks */ |
| |
| if (pAddBssParams == NULL) { |
| PELOGE(lim_log(pMac, LOGE, FL("Invalid parameters"));) |
| goto end; |
| } |
| if (eLIM_MLM_WT_ADD_BSS_RSP_FT_REASSOC_STATE != |
| psessionEntry->limMlmState) { |
| goto end; |
| } |
| |
| pStaDs = dph_add_hash_entry(pMac, pAddBssParams->bssId, |
| DPH_STA_HASH_INDEX_PEER, |
| &psessionEntry->dph.dphHashTable); |
| if (pStaDs == NULL) { |
| /* Could not add hash table entry */ |
| lim_log(pMac, LOGE, FL("could not add hash entry at DPH for")); |
| lim_print_mac_addr(pMac, pAddBssParams->staContext.staMac, |
| LOGE); |
| goto end; |
| } |
| /* Prepare and send Reassociation request frame */ |
| /* start reassoc timer. */ |
| #ifdef WLAN_FEATURE_ROAM_OFFLOAD |
| if (psessionEntry->bRoamSynchInProgress != true) { |
| #endif |
| pMac->lim.limTimers.gLimReassocFailureTimer.sessionId = |
| psessionEntry->peSessionId; |
| /* / Start reassociation failure timer */ |
| MTRACE(mac_trace |
| (pMac, TRACE_CODE_TIMER_ACTIVATE, |
| psessionEntry->peSessionId, eLIM_REASSOC_FAIL_TIMER)); |
| if (tx_timer_activate |
| (&pMac->lim.limTimers.gLimReassocFailureTimer) |
| != TX_SUCCESS) { |
| /* / Could not start reassoc failure timer. */ |
| /* Log error */ |
| lim_log(pMac, LOGP, |
| FL("could not start Reassoc failure timer")); |
| /* Return Reassoc confirm with */ |
| /* Resources Unavailable */ |
| mlmReassocCnf.resultCode = |
| eSIR_SME_RESOURCES_UNAVAILABLE; |
| mlmReassocCnf.protStatusCode = |
| eSIR_MAC_UNSPEC_FAILURE_STATUS; |
| goto end; |
| } |
| pMac->lim.pSessionEntry = psessionEntry; |
| if (NULL == pMac->lim.pSessionEntry->pLimMlmReassocRetryReq) { |
| /* Take a copy of reassoc request for retrying */ |
| pMac->lim.pSessionEntry->pLimMlmReassocRetryReq = |
| qdf_mem_malloc(sizeof(tLimMlmReassocReq)); |
| if (NULL == |
| pMac->lim.pSessionEntry->pLimMlmReassocRetryReq) |
| goto end; |
| qdf_mem_set(pMac->lim.pSessionEntry-> |
| pLimMlmReassocRetryReq, |
| sizeof(tLimMlmReassocReq), 0); |
| qdf_mem_copy(pMac->lim.pSessionEntry-> |
| pLimMlmReassocRetryReq, |
| psessionEntry->pLimMlmReassocReq, |
| sizeof(tLimMlmReassocReq)); |
| } |
| pMac->lim.reAssocRetryAttempt = 0; |
| lim_send_reassoc_req_with_ft_ies_mgmt_frame(pMac, |
| psessionEntry-> |
| pLimMlmReassocReq, |
| psessionEntry); |
| #ifdef WLAN_FEATURE_ROAM_OFFLOAD |
| } else { |
| QDF_TRACE(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_DEBUG, |
| "LFR3:Do not activate timer and dont send the reassoc"); |
| } |
| #endif |
| psessionEntry->limPrevMlmState = psessionEntry->limMlmState; |
| psessionEntry->limMlmState = eLIM_MLM_WT_FT_REASSOC_RSP_STATE; |
| MTRACE(mac_trace |
| (pMac, TRACE_CODE_MLM_STATE, psessionEntry->peSessionId, |
| eLIM_MLM_WT_FT_REASSOC_RSP_STATE)); |
| PELOGE(lim_log |
| (pMac, LOG1, FL("Set the mlm state to %d session=%d"), |
| psessionEntry->limMlmState, psessionEntry->peSessionId); |
| ) |
| |
| psessionEntry->bssIdx = (uint8_t) pAddBssParams->bssIdx; |
| |
| /* Success, handle below */ |
| pStaDs->bssId = pAddBssParams->bssIdx; |
| /* STA Index(genr by HAL) for the BSS entry is stored here */ |
| pStaDs->staIndex = pAddBssParams->staContext.staIdx; |
| pStaDs->ucUcastSig = pAddBssParams->staContext.ucUcastSig; |
| pStaDs->ucBcastSig = pAddBssParams->staContext.ucBcastSig; |
| |
| rrm_cache_mgmt_tx_power(pMac, pAddBssParams->txMgmtPower, |
| psessionEntry); |
| |
| pAddStaParams = qdf_mem_malloc(sizeof(tAddStaParams)); |
| if (NULL == pAddStaParams) { |
| lim_log(pMac, LOGP, |
| FL("Unable to allocate memory during ADD_STA")); |
| goto end; |
| } |
| qdf_mem_set((uint8_t *) pAddStaParams, sizeof(tAddStaParams), 0); |
| |
| /* / Add STA context at MAC HW (BMU, RHP & TFP) */ |
| qdf_mem_copy((uint8_t *) pAddStaParams->staMac, |
| (uint8_t *) psessionEntry->selfMacAddr, |
| sizeof(tSirMacAddr)); |
| |
| qdf_mem_copy((uint8_t *) pAddStaParams->bssId, |
| psessionEntry->bssId, sizeof(tSirMacAddr)); |
| |
| pAddStaParams->staType = STA_ENTRY_SELF; |
| pAddStaParams->status = QDF_STATUS_SUCCESS; |
| pAddStaParams->respReqd = 1; |
| |
| /* Update PE session ID */ |
| pAddStaParams->sessionId = psessionEntry->peSessionId; |
| pAddStaParams->smesessionId = psessionEntry->smeSessionId; |
| |
| /* This will indicate HAL to "allocate" a new STA index */ |
| #ifdef WLAN_FEATURE_ROAM_OFFLOAD |
| if (psessionEntry->bRoamSynchInProgress != true) |
| #endif |
| pAddStaParams->staIdx = STA_INVALID_IDX; |
| pAddStaParams->updateSta = false; |
| |
| pAddStaParams->shortPreambleSupported = |
| (uint8_t) psessionEntry->beaconParams.fShortPreamble; |
| lim_populate_peer_rate_set(pMac, &pAddStaParams->supportedRates, NULL, |
| false, psessionEntry, NULL); |
| |
| if (psessionEntry->htCapability) { |
| pAddStaParams->htCapable = psessionEntry->htCapability; |
| pAddStaParams->vhtCapable = psessionEntry->vhtCapability; |
| pAddStaParams->ch_width = psessionEntry->ch_width; |
| pAddStaParams->greenFieldCapable = |
| lim_get_ht_capability(pMac, eHT_GREENFIELD, |
| psessionEntry); |
| pAddStaParams->mimoPS = |
| lim_get_ht_capability(pMac, eHT_MIMO_POWER_SAVE, |
| psessionEntry); |
| pAddStaParams->rifsMode = |
| lim_get_ht_capability(pMac, eHT_RIFS_MODE, |
| psessionEntry); |
| pAddStaParams->lsigTxopProtection = |
| lim_get_ht_capability(pMac, eHT_LSIG_TXOP_PROTECTION, |
| psessionEntry); |
| pAddStaParams->maxAmpduDensity = |
| lim_get_ht_capability(pMac, eHT_MPDU_DENSITY, |
| psessionEntry); |
| pAddStaParams->maxAmpduSize = |
| lim_get_ht_capability(pMac, eHT_MAX_RX_AMPDU_FACTOR, |
| psessionEntry); |
| pAddStaParams->maxAmsduSize = |
| lim_get_ht_capability(pMac, eHT_MAX_AMSDU_LENGTH, |
| psessionEntry); |
| pAddStaParams->fDsssCckMode40Mhz = |
| lim_get_ht_capability(pMac, eHT_DSSS_CCK_MODE_40MHZ, |
| psessionEntry); |
| pAddStaParams->fShortGI20Mhz = |
| lim_get_ht_capability(pMac, eHT_SHORT_GI_20MHZ, |
| psessionEntry); |
| pAddStaParams->fShortGI40Mhz = |
| lim_get_ht_capability(pMac, eHT_SHORT_GI_40MHZ, |
| psessionEntry); |
| } |
| |
| if (wlan_cfg_get_int(pMac, WNI_CFG_LISTEN_INTERVAL, &listenInterval) != |
| eSIR_SUCCESS) |
| lim_log(pMac, LOGP, FL("Couldn't get LISTEN_INTERVAL")); |
| pAddStaParams->listenInterval = (uint16_t) listenInterval; |
| |
| wlan_cfg_get_int(pMac, WNI_CFG_DOT11_MODE, &selfStaDot11Mode); |
| pAddStaParams->encryptType = psessionEntry->encryptType; |
| pAddStaParams->maxTxPower = psessionEntry->maxTxPower; |
| |
| /* Lets save this for when we receive the Reassoc Rsp */ |
| psessionEntry->ftPEContext.pAddStaReq = pAddStaParams; |
| |
| if (pAddBssParams != NULL) { |
| qdf_mem_free(pAddBssParams); |
| pAddBssParams = NULL; |
| limMsgQ->bodyptr = NULL; |
| } |
| #ifdef WLAN_FEATURE_ROAM_OFFLOAD |
| if (psessionEntry->bRoamSynchInProgress) { |
| QDF_TRACE(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_DEBUG, |
| "LFR3:Prep and save AddStaReq for post-assoc-rsp"); |
| lim_process_assoc_rsp_frame(pMac, pMac->roam.pReassocResp, |
| LIM_REASSOC, psessionEntry); |
| } |
| #endif |
| return; |
| |
| end: |
| /* Free up buffer allocated for reassocReq */ |
| if (psessionEntry != NULL) |
| if (psessionEntry->pLimMlmReassocReq != NULL) { |
| qdf_mem_free(psessionEntry->pLimMlmReassocReq); |
| psessionEntry->pLimMlmReassocReq = NULL; |
| } |
| |
| if (pAddBssParams != NULL) { |
| qdf_mem_free(pAddBssParams); |
| pAddBssParams = NULL; |
| limMsgQ->bodyptr = NULL; |
| } |
| |
| mlmReassocCnf.resultCode = eSIR_SME_FT_REASSOC_FAILURE; |
| mlmReassocCnf.protStatusCode = eSIR_MAC_UNSPEC_FAILURE_STATUS; |
| /* Update PE session Id */ |
| if (psessionEntry != NULL) |
| mlmReassocCnf.sessionId = psessionEntry->peSessionId; |
| else |
| mlmReassocCnf.sessionId = 0; |
| |
| lim_post_sme_message(pMac, LIM_MLM_REASSOC_CNF, |
| (uint32_t *) &mlmReassocCnf); |
| } |
| |
| /** |
| * lim_process_mlm_ft_reassoc_req() - Handle the Reassoc request |
| * @pMac: Global MAC context |
| * @pMsgBuf: Buffer which holds the data |
| * @psessionEntry: PE Session |
| * |
| * This function handles the Reassoc Req from SME |
| * |
| * Return: None |
| */ |
| void lim_process_mlm_ft_reassoc_req(tpAniSirGlobal pMac, uint32_t *pMsgBuf, |
| tpPESession psessionEntry) |
| { |
| uint8_t smeSessionId = 0; |
| uint16_t transactionId = 0; |
| uint8_t chanNum = 0; |
| tLimMlmReassocReq *pMlmReassocReq; |
| uint16_t caps; |
| uint32_t val; |
| tSirMsgQ msgQ; |
| tSirRetStatus retCode; |
| uint32_t teleBcnEn = 0; |
| |
| chanNum = psessionEntry->currentOperChannel; |
| lim_get_session_info(pMac, (uint8_t *) pMsgBuf, &smeSessionId, |
| &transactionId); |
| psessionEntry->smeSessionId = smeSessionId; |
| psessionEntry->transactionId = transactionId; |
| |
| #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */ |
| lim_diag_event_report(pMac, WLAN_PE_DIAG_REASSOCIATING, |
| psessionEntry, 0, 0); |
| #endif |
| |
| /* Nothing to be done if the session is not in STA mode */ |
| if (!LIM_IS_STA_ROLE(psessionEntry)) { |
| lim_log(pMac, LOGE, FL("psessionEntry is not in STA mode")); |
| return; |
| } |
| |
| if (NULL == psessionEntry->ftPEContext.pAddBssReq) { |
| lim_log(pMac, LOGE, FL("pAddBssReq is NULL")); |
| return; |
| } |
| pMlmReassocReq = qdf_mem_malloc(sizeof(tLimMlmReassocReq)); |
| if (NULL == pMlmReassocReq) { |
| lim_log(pMac, LOGE, |
| FL("call to AllocateMemory failed for mlmReassocReq")); |
| return; |
| } |
| |
| qdf_mem_copy(pMlmReassocReq->peerMacAddr, |
| psessionEntry->bssId, sizeof(tSirMacAddr)); |
| |
| if (wlan_cfg_get_int(pMac, WNI_CFG_REASSOCIATION_FAILURE_TIMEOUT, |
| (uint32_t *) &pMlmReassocReq->reassocFailureTimeout) |
| != eSIR_SUCCESS) { |
| /** |
| * Could not get ReassocFailureTimeout value |
| * from CFG. Log error. |
| */ |
| lim_log(pMac, LOGE, |
| FL("could not retrieve ReassocFailureTimeout value")); |
| qdf_mem_free(pMlmReassocReq); |
| return; |
| } |
| |
| if (cfg_get_capability_info(pMac, &caps, psessionEntry) != |
| eSIR_SUCCESS) { |
| /** |
| * Could not get Capabilities value |
| * from CFG. Log error. |
| */ |
| lim_log(pMac, LOGE, FL("could not get Capabilities value")); |
| qdf_mem_free(pMlmReassocReq); |
| return; |
| } |
| |
| lim_update_caps_info_for_bss(pMac, &caps, |
| psessionEntry->pLimReAssocReq->bssDescription.capabilityInfo); |
| lim_log(pMac, LOG1, FL("Capabilities info FT Reassoc: 0x%X"), caps); |
| |
| pMlmReassocReq->capabilityInfo = caps; |
| |
| /* Update PE sessionId */ |
| pMlmReassocReq->sessionId = psessionEntry->peSessionId; |
| |
| /* If telescopic beaconing is enabled, set listen interval |
| to WNI_CFG_TELE_BCN_MAX_LI |
| */ |
| if (wlan_cfg_get_int(pMac, WNI_CFG_TELE_BCN_WAKEUP_EN, &teleBcnEn) != |
| eSIR_SUCCESS) { |
| lim_log(pMac, LOGP, |
| FL("Couldn't get WNI_CFG_TELE_BCN_WAKEUP_EN")); |
| qdf_mem_free(pMlmReassocReq); |
| return; |
| } |
| |
| if (teleBcnEn) { |
| if (wlan_cfg_get_int(pMac, WNI_CFG_TELE_BCN_MAX_LI, &val) != |
| eSIR_SUCCESS) { |
| /** |
| * Could not get ListenInterval value |
| * from CFG. Log error. |
| */ |
| lim_log(pMac, LOGE, |
| FL("could not retrieve ListenInterval")); |
| qdf_mem_free(pMlmReassocReq); |
| return; |
| } |
| } else { |
| if (wlan_cfg_get_int(pMac, WNI_CFG_LISTEN_INTERVAL, &val) != |
| eSIR_SUCCESS) { |
| /** |
| * Could not get ListenInterval value |
| * from CFG. Log error. |
| */ |
| lim_log(pMac, LOGE, |
| FL("could not retrieve ListenInterval")); |
| qdf_mem_free(pMlmReassocReq); |
| return; |
| } |
| } |
| if (lim_set_link_state |
| (pMac, eSIR_LINK_PREASSOC_STATE, psessionEntry->bssId, |
| psessionEntry->selfMacAddr, NULL, NULL) != eSIR_SUCCESS) { |
| qdf_mem_free(pMlmReassocReq); |
| return; |
| } |
| |
| pMlmReassocReq->listenInterval = (uint16_t) val; |
| psessionEntry->pLimMlmReassocReq = pMlmReassocReq; |
| |
| /* we need to defer the message until we get response back from HAL */ |
| SET_LIM_PROCESS_DEFD_MESGS(pMac, false); |
| |
| msgQ.type = SIR_HAL_ADD_BSS_REQ; |
| msgQ.reserved = 0; |
| msgQ.bodyptr = psessionEntry->ftPEContext.pAddBssReq; |
| msgQ.bodyval = 0; |
| |
| lim_log(pMac, LOG1, FL("Sending SIR_HAL_ADD_BSS_REQ...")); |
| MTRACE(mac_trace_msg_tx(pMac, psessionEntry->peSessionId, msgQ.type)); |
| retCode = wma_post_ctrl_msg(pMac, &msgQ); |
| if (eSIR_SUCCESS != retCode) { |
| qdf_mem_free(psessionEntry->ftPEContext.pAddBssReq); |
| lim_log(pMac, LOGE, |
| FL("Posting ADD_BSS_REQ to HAL failed, reason=%X"), |
| retCode); |
| } |
| |
| psessionEntry->ftPEContext.pAddBssReq = NULL; |
| return; |
| } |
| |