| /* |
| * Copyright (c) 2011-2018 The Linux Foundation. All rights reserved. |
| * |
| * Previously licensed under the ISC license by Qualcomm Atheros, Inc. |
| * |
| * |
| * Permission to use, copy, modify, and/or distribute this software for |
| * any purpose with or without fee is hereby granted, provided that the |
| * above copyright notice and this permission notice appear in all |
| * copies. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL |
| * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED |
| * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE |
| * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL |
| * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR |
| * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER |
| * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR |
| * PERFORMANCE OF THIS SOFTWARE. |
| */ |
| |
| /* |
| * This file was originally distributed by Qualcomm Atheros, Inc. |
| * under proprietary terms before Copyright ownership was assigned |
| * to the Linux Foundation. |
| */ |
| |
| /* |
| * This file lim ProcessMessageQueue.cc contains the code |
| * for processing LIM message Queue. |
| * Author: Chandra Modumudi |
| * Date: 02/11/02 |
| * History:- |
| * Date Modified by Modification Information |
| * -------------------------------------------------------------------- |
| * |
| */ |
| #include "cds_api.h" |
| #include "wni_api.h" |
| #include "wma_types.h" |
| |
| #include "wni_cfg.h" |
| #include "cfg_api.h" |
| #include "sir_common.h" |
| #include "utils_api.h" |
| #include "lim_types.h" |
| #include "lim_utils.h" |
| #include "lim_assoc_utils.h" |
| #include "lim_prop_exts_utils.h" |
| |
| #include "lim_admit_control.h" |
| #include "lim_ibss_peer_mgmt.h" |
| #include "sch_api.h" |
| #include "lim_ft_defs.h" |
| #include "lim_session.h" |
| #include "lim_send_messages.h" |
| |
| #include "rrm_api.h" |
| |
| #include "lim_ft.h" |
| |
| #include "qdf_types.h" |
| #include "cds_packet.h" |
| #include "qdf_mem.h" |
| #include "wlan_policy_mgr_api.h" |
| #include "nan_datapath.h" |
| #include "wlan_reg_services_api.h" |
| #include "lim_security_utils.h" |
| #include "cds_ieee80211_common.h" |
| #include <wlan_scan_ucfg_api.h> |
| |
| |
| void lim_log_session_states(tpAniSirGlobal pMac); |
| static void lim_process_normal_hdd_msg(tpAniSirGlobal mac_ctx, |
| struct scheduler_msg *msg, uint8_t rsp_reqd); |
| |
| #ifdef WLAN_FEATURE_SAE |
| /** |
| * lim_process_sae_msg() - Process SAE message |
| * @mac: Global MAC pointer |
| * @body: Buffer pointer |
| * |
| * Return: None |
| */ |
| static void lim_process_sae_msg(tpAniSirGlobal mac, struct sir_sae_msg *body) |
| { |
| struct sir_sae_msg *sae_msg = body; |
| tpPESession session; |
| |
| if (!sae_msg) { |
| pe_err("SAE msg is NULL"); |
| return; |
| } |
| |
| session = pe_find_session_by_sme_session_id(mac, |
| sae_msg->session_id); |
| if (session == NULL) { |
| pe_err("SAE:Unable to find session"); |
| return; |
| } |
| |
| if (session->pePersona != QDF_STA_MODE) { |
| pe_err("SAE:Not supported in this mode %d", |
| session->pePersona); |
| return; |
| } |
| |
| pe_debug("SAE:status %d limMlmState %d pePersona %d", |
| sae_msg->sae_status, session->limMlmState, |
| session->pePersona); |
| switch (session->limMlmState) { |
| case eLIM_MLM_WT_SAE_AUTH_STATE: |
| /* SAE authentication is completed. Restore from auth state */ |
| if (tx_timer_running(&mac->lim.limTimers.sae_auth_timer)) |
| lim_deactivate_and_change_timer(mac, |
| eLIM_AUTH_SAE_TIMER); |
| /* success */ |
| if (sae_msg->sae_status == IEEE80211_STATUS_SUCCESS) |
| lim_restore_from_auth_state(mac, |
| eSIR_SME_SUCCESS, |
| eSIR_MAC_SUCCESS_STATUS, |
| session); |
| else |
| lim_restore_from_auth_state(mac, |
| eSIR_SME_AUTH_REFUSED, |
| eSIR_MAC_UNSPEC_FAILURE_STATUS, |
| session); |
| break; |
| default: |
| /* SAE msg is received in unexpected state */ |
| pe_err("received SAE msg in state %X", |
| session->limMlmState); |
| lim_print_mlm_state(mac, LOGE, session->limMlmState); |
| break; |
| } |
| } |
| #else |
| static inline void lim_process_sae_msg(tpAniSirGlobal mac, void *body) |
| {} |
| #endif |
| |
| /** |
| * lim_process_dual_mac_cfg_resp() - Process set dual mac config response |
| * @mac: Global MAC pointer |
| * @body: Set dual mac config response in sir_dual_mac_config_resp format |
| * |
| * Process the set dual mac config response and post the message |
| * to SME to process this further and release the active |
| * command list |
| * |
| * Return: None |
| */ |
| static void lim_process_dual_mac_cfg_resp(tpAniSirGlobal mac, void *body) |
| { |
| struct sir_dual_mac_config_resp *resp, *param; |
| uint32_t len, fail_resp = 0; |
| struct scheduler_msg msg = {0}; |
| |
| resp = (struct sir_dual_mac_config_resp *)body; |
| if (!resp) { |
| pe_err("Set dual mac cfg param is NULL"); |
| fail_resp = 1; |
| /* Not returning here. If possible, let us proceed |
| * and send fail response to SME |
| */ |
| } |
| |
| len = sizeof(*param); |
| |
| param = qdf_mem_malloc(len); |
| if (!param) { |
| pe_err("Fail to allocate memory"); |
| /* Memory allocation for param failed. |
| * Cannot send fail status back to SME |
| */ |
| return; |
| } |
| |
| if (fail_resp) { |
| pe_err("Send fail status to SME"); |
| param->status = SET_HW_MODE_STATUS_ECANCELED; |
| } else { |
| param->status = resp->status; |
| /* |
| * TODO: Update this HW mode info in any UMAC params, if needed |
| */ |
| } |
| |
| msg.type = eWNI_SME_SET_DUAL_MAC_CFG_RESP; |
| msg.bodyptr = param; |
| msg.bodyval = 0; |
| pe_debug("Send eWNI_SME_SET_DUAL_MAC_CFG_RESP to SME"); |
| lim_sys_process_mmh_msg_api(mac, &msg, ePROT); |
| return; |
| } |
| |
| /** |
| * lim_process_set_hw_mode_resp() - Process set HW mode response |
| * @mac: Global MAC pointer |
| * @body: Set HW mode response in sir_set_hw_mode_resp format |
| * |
| * Process the set HW mode response and post the message |
| * to SME to process this further and release the active |
| * command list |
| * |
| * Return: None |
| */ |
| static void lim_process_set_hw_mode_resp(tpAniSirGlobal mac, void *body) |
| { |
| struct sir_set_hw_mode_resp *resp, *param; |
| uint32_t len, i, fail_resp = 0; |
| struct scheduler_msg msg = {0}; |
| |
| resp = (struct sir_set_hw_mode_resp *)body; |
| if (!resp) { |
| pe_err("Set HW mode param is NULL"); |
| fail_resp = 1; |
| /* Not returning here. If possible, let us proceed |
| * and send fail response to SME */ |
| } |
| |
| len = sizeof(*param); |
| |
| param = qdf_mem_malloc(len); |
| if (!param) { |
| pe_err("Fail to allocate memory"); |
| /* Memory allocation for param failed. |
| * Cannot send fail status back to SME |
| */ |
| return; |
| } |
| |
| if (fail_resp) { |
| pe_err("Send fail status to SME"); |
| param->status = SET_HW_MODE_STATUS_ECANCELED; |
| param->cfgd_hw_mode_index = 0; |
| param->num_vdev_mac_entries = 0; |
| } else { |
| param->status = resp->status; |
| param->cfgd_hw_mode_index = resp->cfgd_hw_mode_index; |
| param->num_vdev_mac_entries = resp->num_vdev_mac_entries; |
| |
| for (i = 0; i < resp->num_vdev_mac_entries; i++) { |
| param->vdev_mac_map[i].vdev_id = |
| resp->vdev_mac_map[i].vdev_id; |
| param->vdev_mac_map[i].mac_id = |
| resp->vdev_mac_map[i].mac_id; |
| } |
| /* |
| * TODO: Update this HW mode info in any UMAC params, if needed |
| */ |
| } |
| |
| msg.type = eWNI_SME_SET_HW_MODE_RESP; |
| msg.bodyptr = param; |
| msg.bodyval = 0; |
| pe_err("Send eWNI_SME_SET_HW_MODE_RESP to SME"); |
| lim_sys_process_mmh_msg_api(mac, &msg, ePROT); |
| return; |
| } |
| |
| /** |
| * lim_process_antenna_mode_resp() - Process set antenna mode |
| * response |
| * @mac: Global MAC pointer |
| * @body: Set antenna mode response in sir_antenna_mode_resp |
| * format |
| * |
| * Process the set antenna mode response and post the message |
| * to SME to process this further and release the active |
| * command list |
| * |
| * Return: None |
| */ |
| static void lim_process_set_antenna_resp(tpAniSirGlobal mac, void *body) |
| { |
| struct sir_antenna_mode_resp *resp, *param; |
| bool fail_resp = false; |
| struct scheduler_msg msg = {0}; |
| |
| resp = (struct sir_antenna_mode_resp *)body; |
| if (!resp) { |
| pe_err("Set antenna mode resp is NULL"); |
| fail_resp = true; |
| /* Not returning here. If possible, let us proceed |
| * and send fail response to SME |
| */ |
| } |
| |
| param = qdf_mem_malloc(sizeof(*param)); |
| if (!param) { |
| pe_err("Fail to allocate memory"); |
| /* Memory allocation for param failed. |
| * Cannot send fail status back to SME |
| */ |
| return; |
| } |
| |
| if (fail_resp) { |
| pe_err("Send fail status to SME"); |
| param->status = SET_ANTENNA_MODE_STATUS_ECANCELED; |
| } else { |
| param->status = resp->status; |
| } |
| |
| msg.type = eWNI_SME_SET_ANTENNA_MODE_RESP; |
| msg.bodyptr = param; |
| msg.bodyval = 0; |
| pe_debug("Send eWNI_SME_SET_ANTENNA_MODE_RESP to SME"); |
| lim_sys_process_mmh_msg_api(mac, &msg, ePROT); |
| return; |
| } |
| |
| /** |
| * lim_process_set_default_scan_ie_request() - Process the Set default |
| * Scan IE request from HDD. |
| * @mac_ctx: Pointer to Global MAC structure |
| * @msg_buf: Pointer to incoming data |
| * |
| * This function receives the default scan IEs and updates the ext cap IE |
| * (if present) with FTM capabilities and pass the Scan IEs to WMA. |
| * |
| * Return: None |
| */ |
| static void lim_process_set_default_scan_ie_request(tpAniSirGlobal mac_ctx, |
| uint32_t *msg_buf) |
| { |
| struct hdd_default_scan_ie *set_ie_params; |
| struct vdev_ie_info *wma_ie_params; |
| uint8_t *local_ie_buf; |
| uint16_t local_ie_len; |
| struct scheduler_msg msg_q = {0}; |
| tSirRetStatus ret_code; |
| |
| if (!msg_buf) { |
| pe_err("msg_buf is NULL"); |
| return; |
| } |
| |
| set_ie_params = (struct hdd_default_scan_ie *) msg_buf; |
| local_ie_len = set_ie_params->ie_len; |
| |
| local_ie_buf = qdf_mem_malloc(MAX_DEFAULT_SCAN_IE_LEN); |
| if (!local_ie_buf) { |
| pe_err("Scan IE Update fails due to malloc failure"); |
| return; |
| } |
| |
| if (lim_update_ext_cap_ie(mac_ctx, |
| (uint8_t *)set_ie_params->ie_data, |
| local_ie_buf, &local_ie_len)) { |
| pe_err("Update ext cap IEs fails"); |
| goto scan_ie_send_fail; |
| } |
| |
| wma_ie_params = qdf_mem_malloc(sizeof(*wma_ie_params) + local_ie_len); |
| if (!wma_ie_params) { |
| pe_err("fail to alloc wma_ie_params"); |
| goto scan_ie_send_fail; |
| } |
| wma_ie_params->vdev_id = set_ie_params->session_id; |
| wma_ie_params->ie_id = DEFAULT_SCAN_IE_ID; |
| wma_ie_params->length = local_ie_len; |
| wma_ie_params->data = (uint8_t *)(wma_ie_params) |
| + sizeof(*wma_ie_params); |
| qdf_mem_copy(wma_ie_params->data, local_ie_buf, local_ie_len); |
| |
| msg_q.type = WMA_SET_IE_INFO; |
| msg_q.bodyptr = wma_ie_params; |
| msg_q.bodyval = 0; |
| ret_code = wma_post_ctrl_msg(mac_ctx, &msg_q); |
| if (eSIR_SUCCESS != ret_code) { |
| pe_err("fail to send WMA_SET_IE_INFO"); |
| qdf_mem_free(wma_ie_params); |
| } |
| scan_ie_send_fail: |
| qdf_mem_free(local_ie_buf); |
| } |
| |
| /** |
| * lim_process_hw_mode_trans_ind() - Process set HW mode transition indication |
| * @mac: Global MAC pointer |
| * @body: Set HW mode response in sir_hw_mode_trans_ind format |
| * |
| * Process the set HW mode transition indication and post the message |
| * to SME to invoke the HDD callback |
| * command list |
| * |
| * Return: None |
| */ |
| static void lim_process_hw_mode_trans_ind(tpAniSirGlobal mac, void *body) |
| { |
| struct sir_hw_mode_trans_ind *ind, *param; |
| uint32_t len, i; |
| struct scheduler_msg msg = {0}; |
| |
| ind = (struct sir_hw_mode_trans_ind *)body; |
| if (!ind) { |
| pe_err("Set HW mode trans ind param is NULL"); |
| return; |
| } |
| |
| len = sizeof(*param); |
| |
| param = qdf_mem_malloc(len); |
| if (!param) { |
| pe_err("Fail to allocate memory"); |
| return; |
| } |
| |
| param->old_hw_mode_index = ind->old_hw_mode_index; |
| param->new_hw_mode_index = ind->new_hw_mode_index; |
| param->num_vdev_mac_entries = ind->num_vdev_mac_entries; |
| |
| for (i = 0; i < ind->num_vdev_mac_entries; i++) { |
| param->vdev_mac_map[i].vdev_id = |
| ind->vdev_mac_map[i].vdev_id; |
| param->vdev_mac_map[i].mac_id = |
| ind->vdev_mac_map[i].mac_id; |
| } |
| |
| /* TODO: Update this HW mode info in any UMAC params, if needed */ |
| |
| msg.type = eWNI_SME_HW_MODE_TRANS_IND; |
| msg.bodyptr = param; |
| msg.bodyval = 0; |
| pe_err("Send eWNI_SME_HW_MODE_TRANS_IND to SME"); |
| lim_sys_process_mmh_msg_api(mac, &msg, ePROT); |
| return; |
| } |
| |
| /** ------------------------------------------------------------- |
| \fn def_msg_decision |
| \brief The function decides whether to defer a message or not in limProcessMessage function |
| \param tpAniSirGlobal pMac |
| \param struct scheduler_msg limMsg |
| \param tSirMacTspecIE *ppInfo |
| \return none |
| -------------------------------------------------------------*/ |
| |
| uint8_t static def_msg_decision(tpAniSirGlobal pMac, struct scheduler_msg *limMsg) |
| { |
| uint8_t type, subtype; |
| QDF_STATUS status; |
| bool mgmt_pkt_defer = true; |
| |
| /* this function should not changed */ |
| if (pMac->lim.gLimSmeState == eLIM_SME_OFFLINE_STATE) { |
| /* Defer processsing this message */ |
| if (lim_defer_msg(pMac, limMsg) != TX_SUCCESS) { |
| QDF_TRACE(QDF_MODULE_ID_PE, LOGE, |
| FL("Unable to Defer Msg")); |
| lim_log_session_states(pMac); |
| lim_handle_defer_msg_error(pMac, limMsg); |
| } |
| return true; |
| } |
| /* When defer is requested then defer all the messages except HAL responses. */ |
| if ((!lim_is_system_in_scan_state(pMac)) |
| && (true != GET_LIM_PROCESS_DEFD_MESGS(pMac)) |
| && !pMac->lim.gLimSystemInScanLearnMode) { |
| |
| if (limMsg->type == SIR_BB_XPORT_MGMT_MSG) { |
| /* |
| * Dont defer beacon and probe response |
| * because it will fill the differ queue quickly |
| */ |
| status = lim_util_get_type_subtype(limMsg->bodyptr, |
| &type, &subtype); |
| if (QDF_IS_STATUS_SUCCESS(status) && |
| (type == SIR_MAC_MGMT_FRAME) && |
| ((subtype == SIR_MAC_MGMT_BEACON) || |
| (subtype == SIR_MAC_MGMT_PROBE_RSP))) |
| mgmt_pkt_defer = false; |
| } |
| |
| if ((limMsg->type != WMA_ADD_BSS_RSP) |
| && (limMsg->type != WMA_DELETE_BSS_RSP) |
| && (limMsg->type != WMA_DELETE_BSS_HO_FAIL_RSP) |
| && (limMsg->type != WMA_ADD_STA_RSP) |
| && (limMsg->type != WMA_DELETE_STA_RSP) |
| && (limMsg->type != WMA_SET_BSSKEY_RSP) |
| && (limMsg->type != WMA_SET_STAKEY_RSP) |
| && (limMsg->type != WMA_SET_STA_BCASTKEY_RSP) |
| && (limMsg->type != WMA_AGGR_QOS_RSP) |
| && (limMsg->type != WMA_SET_MIMOPS_RSP) |
| && (limMsg->type != WMA_SWITCH_CHANNEL_RSP) |
| && (limMsg->type != WMA_P2P_NOA_ATTR_IND) |
| && (limMsg->type != WMA_ADD_TS_RSP) && |
| /* |
| * LIM won't process any defer queue commands if gLimAddtsSent is |
| * set to TRUE. gLimAddtsSent will be set TRUE to while sending |
| * ADDTS REQ. Say, when deferring is enabled, if |
| * SIR_LIM_ADDTS_RSP_TIMEOUT is posted (because of not receiving ADDTS |
| * RSP) then this command will be added to defer queue and as |
| * gLimAddtsSent is set TRUE LIM will never process any commands from |
| * defer queue, including SIR_LIM_ADDTS_RSP_TIMEOUT. Hence allowing |
| * SIR_LIM_ADDTS_RSP_TIMEOUT command to be processed with deferring |
| * enabled, so that this will be processed immediately and sets |
| * gLimAddtsSent to FALSE. |
| */ |
| (limMsg->type != SIR_LIM_ADDTS_RSP_TIMEOUT) && |
| /* Allow processing of RX frames while awaiting reception |
| * of ADD TS response over the air. This logic particularly |
| * handles the case when host sends ADD BA request to FW |
| * after ADD TS request is sent over the air and |
| * ADD TS response received over the air */ |
| !(limMsg->type == SIR_BB_XPORT_MGMT_MSG && |
| pMac->lim.gLimAddtsSent) && |
| (mgmt_pkt_defer)) { |
| pe_debug("Defer the current message %s , gLimProcessDefdMsgs is false and system is not in scan/learn mode", |
| lim_msg_str(limMsg->type)); |
| /* Defer processsing this message */ |
| if (lim_defer_msg(pMac, limMsg) != TX_SUCCESS) { |
| QDF_TRACE(QDF_MODULE_ID_PE, LOGE, |
| FL("Unable to Defer Msg")); |
| lim_log_session_states(pMac); |
| lim_handle_defer_msg_error(pMac, limMsg); |
| |
| } |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| #ifdef FEATURE_WLAN_EXTSCAN |
| static void |
| __lim_pno_match_fwd_bcn_probepsp(tpAniSirGlobal pmac, uint8_t *rx_pkt_info, |
| tSirProbeRespBeacon *frame, uint32_t ie_len, |
| uint32_t msg_type) |
| { |
| struct pno_match_found *result; |
| uint8_t *body; |
| struct scheduler_msg mmh_msg = {0}; |
| tpSirMacMgmtHdr hdr; |
| uint32_t num_results = 1, len, i; |
| |
| /* Upon receiving every matched beacon, bss info is forwarded to the |
| * the upper layer, hence num_results is set to 1 */ |
| len = sizeof(*result) + (num_results * sizeof(tSirWifiScanResult)) + |
| ie_len; |
| |
| result = qdf_mem_malloc(len); |
| if (NULL == result) { |
| pe_err("Memory allocation failed"); |
| return; |
| } |
| hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info); |
| body = WMA_GET_RX_MPDU_DATA(rx_pkt_info); |
| |
| /* Received frame does not have request id, hence set 0 */ |
| result->request_id = 0; |
| result->more_data = 0; |
| result->num_results = num_results; |
| |
| for (i = 0; i < result->num_results; i++) { |
| result->ap[i].ts = qdf_mc_timer_get_system_time(); |
| result->ap[i].beaconPeriod = frame->beaconInterval; |
| result->ap[i].capability = |
| lim_get_u16((uint8_t *) &frame->capabilityInfo); |
| result->ap[i].channel = WMA_GET_RX_CH(rx_pkt_info); |
| result->ap[i].rssi = WMA_GET_RX_RSSI_NORMALIZED(rx_pkt_info); |
| result->ap[i].rtt = 0; |
| result->ap[i].rtt_sd = 0; |
| result->ap[i].ieLength = ie_len; |
| qdf_mem_copy((uint8_t *) &result->ap[i].ssid[0], |
| (uint8_t *) frame->ssId.ssId, frame->ssId.length); |
| result->ap[i].ssid[frame->ssId.length] = '\0'; |
| qdf_mem_copy((uint8_t *) &result->ap[i].bssid, |
| (uint8_t *) hdr->bssId, |
| sizeof(tSirMacAddr)); |
| /* Copy IE fields */ |
| qdf_mem_copy((uint8_t *) &result->ap[i].ieData, |
| body + SIR_MAC_B_PR_SSID_OFFSET, ie_len); |
| } |
| |
| mmh_msg.type = msg_type; |
| mmh_msg.bodyptr = result; |
| mmh_msg.bodyval = 0; |
| lim_sys_process_mmh_msg_api(pmac, &mmh_msg, ePROT); |
| } |
| |
| |
| static void |
| __lim_ext_scan_forward_bcn_probe_rsp(tpAniSirGlobal pmac, uint8_t *rx_pkt_info, |
| tSirProbeRespBeacon *frame, |
| uint32_t ie_len, |
| uint32_t msg_type) |
| { |
| tpSirWifiFullScanResultEvent result; |
| uint8_t *body; |
| struct scheduler_msg mmh_msg = {0}; |
| tpSirMacMgmtHdr hdr; |
| uint32_t frame_len; |
| tSirBssDescription *bssdescr; |
| |
| result = qdf_mem_malloc(sizeof(*result) + ie_len); |
| if (NULL == result) { |
| pe_err("Memory allocation failed"); |
| return; |
| } |
| hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info); |
| body = WMA_GET_RX_MPDU_DATA(rx_pkt_info); |
| |
| /* Received frame does not have request id, hence set 0 */ |
| result->requestId = 0; |
| |
| result->moreData = 0; |
| result->ap.ts = qdf_mc_timer_get_system_time(); |
| result->ap.beaconPeriod = frame->beaconInterval; |
| result->ap.capability = |
| lim_get_u16((uint8_t *) &frame->capabilityInfo); |
| result->ap.channel = WMA_GET_RX_CH(rx_pkt_info); |
| result->ap.rssi = WMA_GET_RX_RSSI_NORMALIZED(rx_pkt_info); |
| result->ap.rtt = 0; |
| result->ap.rtt_sd = 0; |
| result->ap.ieLength = ie_len; |
| |
| qdf_mem_copy((uint8_t *) &result->ap.ssid[0], |
| (uint8_t *) frame->ssId.ssId, frame->ssId.length); |
| result->ap.ssid[frame->ssId.length] = '\0'; |
| qdf_mem_copy((uint8_t *) &result->ap.bssid.bytes, |
| (uint8_t *) hdr->bssId, |
| QDF_MAC_ADDR_SIZE); |
| /* Copy IE fields */ |
| qdf_mem_copy((uint8_t *) &result->ap.ieData, |
| body + SIR_MAC_B_PR_SSID_OFFSET, ie_len); |
| |
| frame_len = sizeof(*bssdescr) + ie_len - sizeof(bssdescr->ieFields[1]); |
| bssdescr = (tSirBssDescription *) qdf_mem_malloc(frame_len); |
| |
| if (NULL == bssdescr) { |
| pe_err("qdf_mem_malloc(length=%d) failed", frame_len); |
| return; |
| } |
| |
| qdf_mem_zero(bssdescr, frame_len); |
| |
| lim_collect_bss_description(pmac, bssdescr, frame, rx_pkt_info, false); |
| |
| qdf_mem_free(bssdescr); |
| |
| mmh_msg.type = msg_type; |
| mmh_msg.bodyptr = result; |
| mmh_msg.bodyval = 0; |
| lim_sys_process_mmh_msg_api(pmac, &mmh_msg, ePROT); |
| } |
| |
| static void |
| __lim_process_ext_scan_beacon_probe_rsp(tpAniSirGlobal pmac, |
| uint8_t *rx_pkt_info, |
| uint8_t sub_type) |
| { |
| tSirProbeRespBeacon *frame; |
| uint8_t *body; |
| uint32_t frm_len; |
| tSirRetStatus status; |
| |
| frm_len = WMA_GET_RX_PAYLOAD_LEN(rx_pkt_info); |
| if (frm_len <= SIR_MAC_B_PR_SSID_OFFSET) { |
| pe_err("RX packet has invalid length %d", frm_len); |
| return; |
| } |
| |
| frame = qdf_mem_malloc(sizeof(*frame)); |
| if (NULL == frame) { |
| pe_err("Memory allocation failed"); |
| return; |
| } |
| |
| if (sub_type == SIR_MAC_MGMT_BEACON) { |
| pe_debug("Beacon due to ExtScan/epno"); |
| status = sir_convert_beacon_frame2_struct(pmac, |
| (uint8_t *)rx_pkt_info, |
| frame); |
| } else if (sub_type == SIR_MAC_MGMT_PROBE_RSP) { |
| pe_debug("Probe Rsp due to ExtScan/epno"); |
| body = WMA_GET_RX_MPDU_DATA(rx_pkt_info); |
| status = sir_convert_probe_frame2_struct(pmac, body, |
| frm_len, frame); |
| } else { |
| qdf_mem_free(frame); |
| return; |
| } |
| |
| if (status != eSIR_SUCCESS) { |
| pe_err("Frame parsing failed"); |
| qdf_mem_free(frame); |
| return; |
| } |
| |
| if (WMA_IS_EXTSCAN_SCAN_SRC(rx_pkt_info)) |
| __lim_ext_scan_forward_bcn_probe_rsp(pmac, rx_pkt_info, frame, |
| (frm_len - SIR_MAC_B_PR_SSID_OFFSET), |
| eWNI_SME_EXTSCAN_FULL_SCAN_RESULT_IND); |
| |
| if (WMA_IS_EPNO_SCAN_SRC(rx_pkt_info)) |
| __lim_pno_match_fwd_bcn_probepsp(pmac, rx_pkt_info, frame, |
| (frm_len - SIR_MAC_B_PR_SSID_OFFSET), |
| eWNI_SME_EPNO_NETWORK_FOUND_IND); |
| |
| qdf_mem_free(frame); |
| } |
| #endif |
| |
| /* |
| * Beacon Handling Cases: |
| * during scanning, when no session is active: |
| * handled by lim_handle_frames_in_scan_state before __lim_handle_beacon call is invoked. |
| * during scanning, when any session is active, but beacon/Pr does not belong to that session, psessionEntry will be null. |
| * handled by lim_handle_frames_in_scan_state before __lim_handle_beacon call is invoked. |
| * during scanning, when any session is active, and beacon/Pr belongs to one of the session, psessionEntry will not be null. |
| * handled by lim_handle_frames_in_scan_state before __lim_handle_beacon call is invoked. |
| * Not scanning, no session: |
| * there should not be any beacon coming, if coming, should be dropped. |
| * Not Scanning, |
| */ |
| static void |
| __lim_handle_beacon(tpAniSirGlobal pMac, struct scheduler_msg *pMsg, |
| tpPESession psessionEntry) |
| { |
| uint8_t *pRxPacketInfo; |
| |
| lim_get_b_dfrom_rx_packet(pMac, pMsg->bodyptr, |
| (uint32_t **) &pRxPacketInfo); |
| |
| /* This function should not be called if beacon is received in scan state. */ |
| /* So not doing any checks for the global state. */ |
| |
| if (psessionEntry == NULL) { |
| sch_beacon_process(pMac, pRxPacketInfo, NULL); |
| } else if ((psessionEntry->limSmeState == eLIM_SME_LINK_EST_STATE) || |
| (psessionEntry->limSmeState == eLIM_SME_NORMAL_STATE)) { |
| sch_beacon_process(pMac, pRxPacketInfo, psessionEntry); |
| } else |
| lim_process_beacon_frame(pMac, pRxPacketInfo, psessionEntry); |
| |
| return; |
| } |
| |
| /** |
| * lim_defer_msg() |
| * |
| ***FUNCTION: |
| * This function is called to defer the messages received |
| * during Learn mode |
| * |
| ***LOGIC: |
| * NA |
| * |
| ***ASSUMPTIONS: |
| * NA |
| * |
| ***NOTE: |
| * NA |
| * |
| * @param pMac - Pointer to Global MAC structure |
| * @param pMsg of type struct scheduler_msg - Pointer to the message structure |
| * @return None |
| */ |
| |
| uint32_t lim_defer_msg(tpAniSirGlobal pMac, struct scheduler_msg *pMsg) |
| { |
| uint32_t retCode = TX_SUCCESS; |
| |
| retCode = lim_write_deferred_msg_q(pMac, pMsg); |
| |
| if (retCode == TX_SUCCESS) { |
| MTRACE(mac_trace_msg_rx |
| (pMac, NO_SESSION, |
| LIM_TRACE_MAKE_RXMSG(pMsg->type, LIM_MSG_DEFERRED))); |
| } else { |
| pe_err("Dropped lim message (0x%X) Message %s", pMsg->type, lim_msg_str(pMsg->type)); |
| MTRACE(mac_trace_msg_rx |
| (pMac, NO_SESSION, |
| LIM_TRACE_MAKE_RXMSG(pMsg->type, LIM_MSG_DROPPED))); |
| } |
| |
| return retCode; |
| } /*** end lim_defer_msg() ***/ |
| |
| /** |
| * lim_handle_unknown_a2_index_frames() - This function handles Unknown Unicast |
| * (A2 Index) packets |
| * @mac_ctx: Pointer to the Global Mac Context. |
| * @rx_pkt_buffer: Pointer to the packet Buffer descriptor. |
| * @session_entry: Pointer to the PE Session Entry. |
| * |
| * This routine will handle public action frames. |
| * |
| * Return: None. |
| */ |
| static void lim_handle_unknown_a2_index_frames(tpAniSirGlobal mac_ctx, |
| void *rx_pkt_buffer, tpPESession session_entry) |
| { |
| #ifdef FEATURE_WLAN_TDLS |
| tpSirMacDataHdr3a mac_hdr; |
| #endif |
| if (LIM_IS_P2P_DEVICE_ROLE(session_entry)) |
| lim_process_action_frame_no_session(mac_ctx, |
| (uint8_t *) rx_pkt_buffer); |
| #ifdef FEATURE_WLAN_TDLS |
| mac_hdr = WMA_GET_RX_MPDUHEADER3A(rx_pkt_buffer); |
| |
| if (lim_is_group_addr(mac_hdr->addr2)) { |
| QDF_TRACE(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_DEBUG, |
| FL("Ignoring A2 Invalid Packet received for MC/BC:")); |
| lim_print_mac_addr(mac_ctx, mac_hdr->addr2, LOGD); |
| return; |
| } |
| QDF_TRACE(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_DEBUG, |
| FL("type=0x%x, subtype=0x%x"), |
| mac_hdr->fc.type, mac_hdr->fc.subType); |
| /* Currently only following type and subtype are handled. |
| * If there are more combinations, then add switch-case |
| * statements. |
| */ |
| if (LIM_IS_STA_ROLE(session_entry) && |
| (mac_hdr->fc.type == SIR_MAC_MGMT_FRAME) && |
| (mac_hdr->fc.subType == SIR_MAC_MGMT_ACTION)) |
| lim_process_action_frame(mac_ctx, rx_pkt_buffer, session_entry); |
| #endif |
| return; |
| } |
| |
| /** |
| * lim_check_mgmt_registered_frames() - This function handles registered |
| * management frames. |
| * |
| * @mac_ctx: Pointer to the Global Mac Context. |
| * @buff_desc: Pointer to the packet Buffer descriptor. |
| * @session_entry: Pointer to the PE Session Entry. |
| * |
| * This function is called to process to check if received frame match with |
| * any of the registered frame from HDD. If yes pass this frame to SME. |
| * |
| * Return: True or False for Match or Mismatch respectively. |
| */ |
| static bool |
| lim_check_mgmt_registered_frames(tpAniSirGlobal mac_ctx, uint8_t *buff_desc, |
| tpPESession session_entry) |
| { |
| tSirMacFrameCtl fc; |
| tpSirMacMgmtHdr hdr; |
| uint8_t *body; |
| struct mgmt_frm_reg_info *mgmt_frame = NULL; |
| struct mgmt_frm_reg_info *next_frm = NULL; |
| uint16_t frm_type; |
| uint16_t frm_len; |
| uint8_t type, sub_type; |
| bool match = false; |
| QDF_STATUS qdf_status; |
| |
| hdr = WMA_GET_RX_MAC_HEADER(buff_desc); |
| fc = hdr->fc; |
| frm_type = (fc.type << 2) | (fc.subType << 4); |
| body = WMA_GET_RX_MPDU_DATA(buff_desc); |
| frm_len = WMA_GET_RX_PAYLOAD_LEN(buff_desc); |
| |
| qdf_mutex_acquire(&mac_ctx->lim.lim_frame_register_lock); |
| qdf_list_peek_front(&mac_ctx->lim.gLimMgmtFrameRegistratinQueue, |
| (qdf_list_node_t **) &mgmt_frame); |
| qdf_mutex_release(&mac_ctx->lim.lim_frame_register_lock); |
| |
| while (mgmt_frame != NULL) { |
| type = (mgmt_frame->frameType >> 2) & 0x03; |
| sub_type = (mgmt_frame->frameType >> 4) & 0x0f; |
| if ((type == SIR_MAC_MGMT_FRAME) |
| && (fc.type == SIR_MAC_MGMT_FRAME) |
| && (sub_type == SIR_MAC_MGMT_RESERVED15)) { |
| QDF_TRACE(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_DEBUG, |
| FL |
| ("rcvd frm match for SIR_MAC_MGMT_RESERVED15")); |
| match = true; |
| break; |
| } |
| if (mgmt_frame->frameType == frm_type) { |
| if (mgmt_frame->matchLen <= 0) { |
| match = true; |
| break; |
| } |
| if (mgmt_frame->matchLen <= frm_len && |
| (!qdf_mem_cmp(mgmt_frame->matchData, body, |
| mgmt_frame->matchLen))) { |
| /* found match! */ |
| match = true; |
| break; |
| } |
| } |
| |
| qdf_mutex_acquire(&mac_ctx->lim.lim_frame_register_lock); |
| qdf_status = |
| qdf_list_peek_next( |
| &mac_ctx->lim.gLimMgmtFrameRegistratinQueue, |
| (qdf_list_node_t *) mgmt_frame, |
| (qdf_list_node_t **) &next_frm); |
| qdf_mutex_release(&mac_ctx->lim.lim_frame_register_lock); |
| mgmt_frame = next_frm; |
| next_frm = NULL; |
| } |
| |
| if (match) { |
| QDF_TRACE(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_DEBUG, |
| FL("rcvd frame match with registered frame params")); |
| /* Indicate this to SME */ |
| lim_send_sme_mgmt_frame_ind(mac_ctx, hdr->fc.subType, |
| (uint8_t *) hdr, |
| WMA_GET_RX_PAYLOAD_LEN(buff_desc) + |
| sizeof(tSirMacMgmtHdr), mgmt_frame->sessionId, |
| WMA_GET_RX_CH(buff_desc), session_entry, |
| WMA_GET_RX_RSSI_NORMALIZED(buff_desc)); |
| |
| if ((type == SIR_MAC_MGMT_FRAME) |
| && (fc.type == SIR_MAC_MGMT_FRAME) |
| && (sub_type == SIR_MAC_MGMT_RESERVED15)) |
| /* These packets needs to be processed by PE/SME |
| * as well as HDD.If it returns true here, |
| * the packet is forwarded to HDD only. |
| */ |
| match = false; |
| } |
| |
| return match; |
| } |
| |
| #ifdef FEATURE_WLAN_DIAG_SUPPORT |
| /** |
| * lim_is_mgmt_frame_loggable() - to log non-excessive mgmt frames |
| * @type: type of frames i.e. mgmt, control, data |
| * @subtype: subtype of frames i.e. beacon, probe rsp, probe req and etc |
| * |
| * This API tells if given mgmt frame is expected to come excessive in |
| * amount or not. |
| * |
| * Return: true if mgmt is expected to come not that often, so makes it |
| * loggable. false if mgmt is expected to come too often, so makes |
| * it not loggable |
| */ |
| static bool |
| lim_is_mgmt_frame_loggable(uint8_t type, uint8_t subtype) |
| { |
| if (type != SIR_MAC_MGMT_FRAME) |
| return false; |
| |
| switch (subtype) { |
| case SIR_MAC_MGMT_BEACON: |
| case SIR_MAC_MGMT_PROBE_REQ: |
| case SIR_MAC_MGMT_PROBE_RSP: |
| return false; |
| default: |
| return true; |
| } |
| } |
| #else |
| static bool |
| lim_is_mgmt_frame_loggable(uint8_t type, uint8_t subtype) |
| { |
| return false; |
| } |
| #endif |
| |
| /** |
| * lim_handle80211_frames() |
| * |
| ***FUNCTION: |
| * This function is called to process 802.11 frames |
| * received by LIM. |
| * |
| ***LOGIC: |
| * NA |
| * |
| ***ASSUMPTIONS: |
| * NA |
| * |
| ***NOTE: |
| * NA |
| * |
| * @param pMac - Pointer to Global MAC structure |
| * @param pMsg of type struct scheduler_msg - Pointer to the message structure |
| * @return None |
| */ |
| |
| static void |
| lim_handle80211_frames(tpAniSirGlobal pMac, struct scheduler_msg *limMsg, |
| uint8_t *pDeferMsg) |
| { |
| uint8_t *pRxPacketInfo = NULL; |
| tSirMacFrameCtl fc; |
| tpSirMacMgmtHdr pHdr = NULL; |
| tpPESession psessionEntry = NULL; |
| uint8_t sessionId; |
| bool isFrmFt = false; |
| uint8_t channel; |
| bool is_hw_sbs_capable = false; |
| |
| *pDeferMsg = false; |
| lim_get_b_dfrom_rx_packet(pMac, limMsg->bodyptr, |
| (uint32_t **) &pRxPacketInfo); |
| |
| pHdr = WMA_GET_RX_MAC_HEADER(pRxPacketInfo); |
| isFrmFt = WMA_GET_RX_FT_DONE(pRxPacketInfo); |
| channel = WMA_GET_RX_CH(pRxPacketInfo); |
| fc = pHdr->fc; |
| |
| is_hw_sbs_capable = |
| policy_mgr_is_hw_sbs_capable(pMac->psoc); |
| if (IS_5G_CH(channel) && |
| (!is_hw_sbs_capable || |
| (is_hw_sbs_capable && wlan_reg_is_dfs_ch(pMac->pdev, channel))) && |
| pMac->sap.SapDfsInfo.is_dfs_cac_timer_running) { |
| psessionEntry = pe_find_session_by_bssid(pMac, |
| pHdr->bssId, &sessionId); |
| if (psessionEntry && |
| (QDF_SAP_MODE == psessionEntry->pePersona)) { |
| pe_debug("CAC timer running - drop the frame"); |
| goto end; |
| } |
| } |
| |
| #ifdef WLAN_DUMP_MGMTFRAMES |
| pe_debug("ProtVersion %d, Type %d, Subtype %d rateIndex=%d", |
| fc.protVer, fc.type, fc.subType, |
| WMA_GET_RX_MAC_RATE_IDX(pRxPacketInfo)); |
| QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_ERROR, pHdr, |
| WMA_GET_RX_MPDU_HEADER_LEN(pRxPacketInfo)); |
| #endif |
| if (pMac->fEnableDebugLog & 0x1) { |
| if ((fc.type == SIR_MAC_MGMT_FRAME) && |
| (fc.subType != SIR_MAC_MGMT_PROBE_REQ) && |
| (fc.subType != SIR_MAC_MGMT_PROBE_RSP) && |
| (fc.subType != SIR_MAC_MGMT_BEACON)) { |
| pe_debug("RX MGMT - Type %hu, SubType %hu, seq num[%d]", |
| fc.type, |
| fc.subType, |
| ((pHdr->seqControl.seqNumHi << |
| HIGH_SEQ_NUM_OFFSET) | |
| pHdr->seqControl.seqNumLo)); |
| } |
| } |
| #ifdef FEATURE_WLAN_EXTSCAN |
| if (WMA_IS_EXTSCAN_SCAN_SRC(pRxPacketInfo) || |
| WMA_IS_EPNO_SCAN_SRC(pRxPacketInfo)) { |
| if (fc.subType == SIR_MAC_MGMT_BEACON || |
| fc.subType == SIR_MAC_MGMT_PROBE_RSP) { |
| __lim_process_ext_scan_beacon_probe_rsp(pMac, |
| pRxPacketInfo, |
| fc.subType); |
| } else { |
| pe_err("Wrong frameType %d, Subtype %d for %d", |
| fc.type, fc.subType, |
| WMA_GET_SCAN_SRC(pRxPacketInfo)); |
| } |
| goto end; |
| } |
| #endif |
| /* Added For BT-AMP Support */ |
| psessionEntry = pe_find_session_by_bssid(pMac, pHdr->bssId, |
| &sessionId); |
| if (psessionEntry == NULL) { |
| if (fc.subType == SIR_MAC_MGMT_AUTH) { |
| pe_debug("ProtVersion %d, Type %d, Subtype %d rateIndex=%d", |
| fc.protVer, fc.type, fc.subType, |
| WMA_GET_RX_MAC_RATE_IDX(pRxPacketInfo)); |
| lim_print_mac_addr(pMac, pHdr->bssId, LOGD); |
| if (lim_process_auth_frame_no_session |
| (pMac, pRxPacketInfo, |
| limMsg->bodyptr) == eSIR_SUCCESS) { |
| goto end; |
| } |
| } |
| /* Public action frame can be received from non-assoc stations*/ |
| if ((fc.subType != SIR_MAC_MGMT_PROBE_RSP) && |
| (fc.subType != SIR_MAC_MGMT_BEACON) && |
| (fc.subType != SIR_MAC_MGMT_PROBE_REQ) |
| && (fc.subType != SIR_MAC_MGMT_ACTION)) { |
| |
| psessionEntry = pe_find_session_by_peer_sta(pMac, |
| pHdr->sa, &sessionId); |
| if (psessionEntry == NULL) { |
| pe_debug("session does not exist for bssId"); |
| lim_print_mac_addr(pMac, pHdr->sa, LOGD); |
| goto end; |
| } else { |
| pe_debug("SessionId:%d exists for given Bssid", |
| psessionEntry->peSessionId); |
| } |
| } |
| /* For p2p resp frames search for valid session with DA as */ |
| /* BSSID will be SA and session will be present with DA only */ |
| if (fc.subType == SIR_MAC_MGMT_ACTION) { |
| psessionEntry = |
| pe_find_session_by_bssid(pMac, pHdr->da, &sessionId); |
| } |
| } |
| |
| /* Check if frame is registered by HDD */ |
| if (lim_check_mgmt_registered_frames(pMac, pRxPacketInfo, psessionEntry)) { |
| pe_debug("Received frame is passed to SME"); |
| goto end; |
| } |
| |
| if (fc.protVer != SIR_MAC_PROTOCOL_VERSION) { /* Received Frame with non-zero Protocol Version */ |
| pe_err("Unexpected frame with protVersion %d received", |
| fc.protVer); |
| lim_pkt_free(pMac, TXRX_FRM_802_11_MGMT, pRxPacketInfo, |
| (void *)limMsg->bodyptr); |
| #ifdef WLAN_DEBUG |
| pMac->lim.numProtErr++; |
| #endif |
| goto end; |
| } |
| |
| /* Chance of crashing : to be done BT-AMP ........happens when broadcast probe req is received */ |
| |
| #ifdef WLAN_DEBUG |
| pMac->lim.numMAC[fc.type][fc.subType]++; |
| #endif |
| |
| switch (fc.type) { |
| case SIR_MAC_MGMT_FRAME: |
| { |
| /* Received Management frame */ |
| switch (fc.subType) { |
| case SIR_MAC_MGMT_ASSOC_REQ: |
| /* Make sure the role supports Association */ |
| if (LIM_IS_AP_ROLE(psessionEntry)) |
| lim_process_assoc_req_frame(pMac, |
| pRxPacketInfo, |
| LIM_ASSOC, |
| psessionEntry); |
| else { |
| pe_err("unexpected message received %X", |
| limMsg->type); |
| lim_print_msg_name(pMac, LOGE, |
| limMsg->type); |
| } |
| break; |
| |
| case SIR_MAC_MGMT_ASSOC_RSP: |
| lim_process_assoc_rsp_frame(pMac, pRxPacketInfo, |
| LIM_ASSOC, |
| psessionEntry); |
| break; |
| |
| case SIR_MAC_MGMT_REASSOC_REQ: |
| /* Make sure the role supports Reassociation */ |
| if (LIM_IS_AP_ROLE(psessionEntry)) { |
| lim_process_assoc_req_frame(pMac, |
| pRxPacketInfo, |
| LIM_REASSOC, |
| psessionEntry); |
| } else { |
| pe_err("unexpected message received %X", |
| limMsg->type); |
| lim_print_msg_name(pMac, LOGE, |
| limMsg->type); |
| } |
| break; |
| |
| case SIR_MAC_MGMT_REASSOC_RSP: |
| lim_process_assoc_rsp_frame(pMac, pRxPacketInfo, |
| LIM_REASSOC, |
| psessionEntry); |
| break; |
| |
| case SIR_MAC_MGMT_PROBE_REQ: |
| lim_process_probe_req_frame_multiple_bss(pMac, |
| pRxPacketInfo, |
| psessionEntry); |
| break; |
| |
| case SIR_MAC_MGMT_PROBE_RSP: |
| if (psessionEntry) |
| lim_process_probe_rsp_frame(pMac, |
| pRxPacketInfo, |
| psessionEntry); |
| break; |
| |
| case SIR_MAC_MGMT_BEACON: |
| __lim_handle_beacon(pMac, limMsg, psessionEntry); |
| break; |
| |
| case SIR_MAC_MGMT_DISASSOC: |
| lim_process_disassoc_frame(pMac, pRxPacketInfo, |
| psessionEntry); |
| break; |
| |
| case SIR_MAC_MGMT_AUTH: |
| lim_process_auth_frame(pMac, pRxPacketInfo, |
| psessionEntry); |
| break; |
| |
| case SIR_MAC_MGMT_DEAUTH: |
| lim_process_deauth_frame(pMac, pRxPacketInfo, |
| psessionEntry); |
| break; |
| |
| case SIR_MAC_MGMT_ACTION: |
| if (psessionEntry == NULL) |
| lim_process_action_frame_no_session(pMac, |
| pRxPacketInfo); |
| else { |
| if (WMA_GET_RX_UNKNOWN_UCAST |
| (pRxPacketInfo)) |
| lim_handle_unknown_a2_index_frames |
| (pMac, pRxPacketInfo, |
| psessionEntry); |
| else |
| lim_process_action_frame(pMac, |
| pRxPacketInfo, |
| psessionEntry); |
| } |
| break; |
| default: |
| /* Received Management frame of 'reserved' subtype */ |
| break; |
| } /* switch (fc.subType) */ |
| |
| } |
| break; |
| case SIR_MAC_DATA_FRAME: |
| { |
| } |
| break; |
| default: |
| /* Received frame of type 'reserved' */ |
| break; |
| |
| } /* switch (fc.type) */ |
| if (lim_is_mgmt_frame_loggable(fc.type, fc.subType)) |
| lim_diag_mgmt_rx_event_report(pMac, pHdr, |
| psessionEntry, |
| eSIR_SUCCESS, eSIR_SUCCESS); |
| end: |
| lim_pkt_free(pMac, TXRX_FRM_802_11_MGMT, pRxPacketInfo, |
| (void *)limMsg->bodyptr); |
| return; |
| } /*** end lim_handle80211_frames() ***/ |
| |
| void lim_process_abort_scan_ind(tpAniSirGlobal mac_ctx, |
| uint8_t vdev_id, uint32_t scan_id, uint32_t scan_requestor_id) |
| { |
| QDF_STATUS status; |
| struct scan_cancel_request *req; |
| struct wlan_objmgr_vdev *vdev; |
| |
| pe_debug("scan_id %d, scan_requestor_id 0x%x", |
| scan_id, scan_requestor_id); |
| |
| vdev = wlan_objmgr_get_vdev_by_id_from_psoc( |
| mac_ctx->psoc, vdev_id, |
| WLAN_LEGACY_MAC_ID); |
| if (!vdev) { |
| pe_debug("vdev is NULL"); |
| return; |
| } |
| |
| req = qdf_mem_malloc(sizeof(*req)); |
| if (!req) { |
| pe_debug("failed to alloc scan cancel request"); |
| goto fail; |
| } |
| |
| req->vdev = vdev; |
| req->cancel_req.requester = scan_requestor_id; |
| req->cancel_req.scan_id = scan_id; |
| req->cancel_req.vdev_id = vdev_id; |
| req->cancel_req.req_type = WLAN_SCAN_CANCEL_SINGLE; |
| |
| status = ucfg_scan_cancel(req); |
| if (QDF_IS_STATUS_ERROR(status)) |
| pe_err("Cancel scan request failed"); |
| |
| fail: |
| wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_MAC_ID); |
| } |
| |
| static void lim_process_sme_obss_scan_ind(tpAniSirGlobal mac_ctx, |
| struct scheduler_msg *msg) |
| { |
| struct sPESession *session; |
| uint8_t session_id; |
| struct sme_obss_ht40_scanind_msg *ht40_scanind; |
| |
| ht40_scanind = (struct sme_obss_ht40_scanind_msg *)msg->bodyptr; |
| session = pe_find_session_by_bssid(mac_ctx, |
| ht40_scanind->mac_addr.bytes, &session_id); |
| if (session == NULL) { |
| QDF_TRACE(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_DEBUG, |
| "OBSS Scan not started: session id is NULL"); |
| return; |
| } |
| if (session->htSupportedChannelWidthSet == |
| WNI_CFG_CHANNEL_BONDING_MODE_ENABLE) { |
| QDF_TRACE(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_DEBUG, |
| "OBSS Scan Start Req: session id %d" |
| "htSupportedChannelWidthSet %d", |
| session->peSessionId, |
| session->htSupportedChannelWidthSet); |
| lim_send_ht40_obss_scanind(mac_ctx, session); |
| } else { |
| QDF_TRACE(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_DEBUG, |
| "OBSS Scan not started: channel width - %d session %d", |
| session->htSupportedChannelWidthSet, |
| session->peSessionId); |
| } |
| return; |
| } |
| |
| /** |
| * lim_process_messages() - Process messages from upper layers. |
| * |
| * @mac_ctx: Pointer to the Global Mac Context. |
| * @msg: Received message. |
| * |
| * Return: None. |
| */ |
| static void lim_process_messages(tpAniSirGlobal mac_ctx, |
| struct scheduler_msg *msg) |
| { |
| #ifdef FEATURE_AP_MCC_CH_AVOIDANCE |
| uint8_t vdev_id = 0; |
| tUpdateBeaconParams beacon_params; |
| #endif /* FEATURE_AP_MCC_CH_AVOIDANCE */ |
| uint8_t i; |
| tpPESession session_entry = NULL; |
| uint8_t defer_msg = false; |
| tLinkStateParams *link_state_param; |
| uint16_t pkt_len = 0; |
| cds_pkt_t *body_ptr = NULL; |
| QDF_STATUS qdf_status; |
| struct scheduler_msg new_msg = {0}; |
| uint8_t session_id; |
| |
| #ifdef FEATURE_WLAN_TDLS |
| tSirTdlsInd *tdls_ind = NULL; |
| tpDphHashNode sta_ds = NULL; |
| #endif |
| if (ANI_DRIVER_TYPE(mac_ctx) == QDF_DRIVER_TYPE_MFG) { |
| qdf_mem_free(msg->bodyptr); |
| msg->bodyptr = NULL; |
| return; |
| } |
| if (msg == NULL) { |
| pe_err("Message pointer is Null"); |
| QDF_ASSERT(0); |
| return; |
| } |
| #ifdef WLAN_DEBUG |
| mac_ctx->lim.numTot++; |
| #endif |
| /* |
| * MTRACE logs not captured for events received from SME |
| * SME enums (eWNI_SME_START_REQ) starts with 0x16xx. |
| * Compare received SME events with SIR_SME_MODULE_ID |
| */ |
| if ((SIR_SME_MODULE_ID == |
| (uint8_t)MAC_TRACE_GET_MODULE_ID(msg->type)) && |
| (msg->type != eWNI_SME_REGISTER_MGMT_FRAME_REQ)) { |
| MTRACE(mac_trace(mac_ctx, TRACE_CODE_RX_SME_MSG, |
| NO_SESSION, msg->type)); |
| } else { |
| /* |
| * Omitting below message types as these are too frequent |
| * and when crash happens we loose critical trace logs |
| * if these are also logged |
| */ |
| if (msg->type != SIR_CFG_PARAM_UPDATE_IND && |
| msg->type != SIR_BB_XPORT_MGMT_MSG && |
| msg->type != WMA_RX_SCAN_EVENT) |
| MTRACE(mac_trace_msg_rx(mac_ctx, NO_SESSION, |
| LIM_TRACE_MAKE_RXMSG(msg->type, |
| LIM_MSG_PROCESSED))); |
| } |
| |
| switch (msg->type) { |
| |
| case SIR_LIM_UPDATE_BEACON: |
| lim_update_beacon(mac_ctx); |
| break; |
| case SIR_CFG_PARAM_UPDATE_IND: |
| if (!lim_is_system_in_scan_state(mac_ctx)) { |
| lim_handle_cf_gparam_update(mac_ctx, msg->bodyval); |
| break; |
| } |
| /* System is in DFS (Learn) mode. |
| * Defer processsing this message |
| */ |
| if (lim_defer_msg(mac_ctx, msg) != TX_SUCCESS) { |
| if (!(mac_ctx->lim.deferredMsgCnt & 0xF)) |
| QDF_TRACE(QDF_MODULE_ID_PE, LOGE, |
| FL("Unable to Defer Msg")); |
| lim_log_session_states(mac_ctx); |
| lim_print_msg_name(mac_ctx, LOGE, msg->type); |
| } |
| break; |
| case WMA_SWITCH_CHANNEL_RSP: |
| lim_process_switch_channel_rsp(mac_ctx, msg->bodyptr); |
| msg->bodyptr = NULL; |
| break; |
| #ifdef ANI_SIR_IBSS_PEER_CACHING |
| case WMA_IBSS_STA_ADD: |
| lim_ibss_sta_add(mac_ctx, msg->bodyptr); |
| break; |
| #endif |
| case SIR_BB_XPORT_MGMT_MSG: |
| /* These messages are from Peer MAC entity. */ |
| #ifdef WLAN_DEBUG |
| mac_ctx->lim.numBbt++; |
| #endif |
| /* The original msg which we were deferring have the |
| * bodyPointer point to 'BD' instead of 'cds pkt'. If we |
| * don't make a copy of msg, then overwrite the |
| * msg->bodyPointer and next time when we try to |
| * process the msg, we will try to use 'BD' as |
| * 'cds Pkt' which will cause a crash |
| */ |
| if (msg->bodyptr == NULL) { |
| pe_err("Message bodyptr is Null"); |
| QDF_ASSERT(0); |
| break; |
| } |
| qdf_mem_copy((uint8_t *) &new_msg, |
| (uint8_t *) msg, sizeof(struct scheduler_msg)); |
| body_ptr = (cds_pkt_t *) new_msg.bodyptr; |
| cds_pkt_get_packet_length(body_ptr, &pkt_len); |
| |
| qdf_status = wma_ds_peek_rx_packet_info(body_ptr, |
| (void **) &new_msg.bodyptr, false); |
| |
| if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { |
| lim_decrement_pending_mgmt_count(mac_ctx); |
| cds_pkt_return_packet(body_ptr); |
| break; |
| } |
| if (WMA_GET_ROAMCANDIDATEIND(new_msg.bodyptr)) |
| pe_debug("roamCandidateInd: %d", |
| WMA_GET_ROAMCANDIDATEIND(new_msg.bodyptr)); |
| if (WMA_GET_OFFLOADSCANLEARN(new_msg.bodyptr)) |
| pe_debug("offloadScanLearn: %d", |
| WMA_GET_OFFLOADSCANLEARN(new_msg.bodyptr)); |
| |
| lim_handle80211_frames(mac_ctx, &new_msg, &defer_msg); |
| |
| if (defer_msg == true) { |
| QDF_TRACE(QDF_MODULE_ID_PE, LOGD, |
| FL("Defer Msg type=%x"), msg->type); |
| if (lim_defer_msg(mac_ctx, msg) != TX_SUCCESS) { |
| QDF_TRACE(QDF_MODULE_ID_PE, LOGE, |
| FL("Unable to Defer Msg")); |
| lim_log_session_states(mac_ctx); |
| lim_decrement_pending_mgmt_count(mac_ctx); |
| cds_pkt_return_packet(body_ptr); |
| } |
| } else { |
| /* PE is not deferring this 802.11 frame so we need to |
| * call cds_pkt_return. Asumption here is when Rx mgmt |
| * frame processing is done, cds packet could be |
| * freed here. |
| */ |
| lim_decrement_pending_mgmt_count(mac_ctx); |
| cds_pkt_return_packet(body_ptr); |
| } |
| break; |
| case eWNI_SME_DISASSOC_REQ: |
| case eWNI_SME_DEAUTH_REQ: |
| #ifdef FEATURE_WLAN_TDLS |
| case eWNI_SME_TDLS_SEND_MGMT_REQ: |
| case eWNI_SME_TDLS_ADD_STA_REQ: |
| case eWNI_SME_TDLS_DEL_STA_REQ: |
| case eWNI_SME_TDLS_LINK_ESTABLISH_REQ: |
| #endif |
| case eWNI_SME_RESET_AP_CAPS_CHANGED: |
| case eWNI_SME_SET_HW_MODE_REQ: |
| case eWNI_SME_SET_DUAL_MAC_CFG_REQ: |
| case eWNI_SME_SET_ANTENNA_MODE_REQ: |
| case eWNI_SME_UPDATE_ACCESS_POLICY_VENDOR_IE: |
| case eWNI_SME_UPDATE_CONFIG: |
| /* These messages are from HDD. Need to respond to HDD */ |
| lim_process_normal_hdd_msg(mac_ctx, msg, true); |
| break; |
| case eWNI_SME_SEND_DISASSOC_FRAME: |
| /* Need to response to hdd */ |
| lim_process_normal_hdd_msg(mac_ctx, msg, true); |
| break; |
| case eWNI_SME_PDEV_SET_HT_VHT_IE: |
| case eWNI_SME_SET_VDEV_IES_PER_BAND: |
| case eWNI_SME_SYS_READY_IND: |
| case eWNI_SME_JOIN_REQ: |
| case eWNI_SME_REASSOC_REQ: |
| case eWNI_SME_START_BSS_REQ: |
| case eWNI_SME_STOP_BSS_REQ: |
| case eWNI_SME_SWITCH_CHL_IND: |
| case eWNI_SME_SETCONTEXT_REQ: |
| case eWNI_SME_DISASSOC_CNF: |
| case eWNI_SME_DEAUTH_CNF: |
| case eWNI_SME_ASSOC_CNF: |
| case eWNI_SME_ADDTS_REQ: |
| case eWNI_SME_DELTS_REQ: |
| case eWNI_SME_GET_ASSOC_STAS_REQ: |
| case eWNI_SME_SESSION_UPDATE_PARAM: |
| case eWNI_SME_CHNG_MCC_BEACON_INTERVAL: |
| case eWNI_SME_NEIGHBOR_REPORT_REQ_IND: |
| case eWNI_SME_BEACON_REPORT_RESP_XMIT_IND: |
| #if defined FEATURE_WLAN_ESE |
| case eWNI_SME_ESE_ADJACENT_AP_REPORT: |
| #endif |
| case eWNI_SME_FT_UPDATE_KEY: |
| case eWNI_SME_FT_PRE_AUTH_REQ: |
| case eWNI_SME_FT_AGGR_QOS_REQ: |
| case eWNI_SME_REGISTER_MGMT_FRAME_REQ: |
| case eWNI_SME_CLEAR_DFS_CHANNEL_LIST: |
| case eWNI_SME_GET_STATISTICS_REQ: |
| #ifdef FEATURE_WLAN_ESE |
| case eWNI_SME_GET_TSM_STATS_REQ: |
| #endif /* FEATURE_WLAN_ESE */ |
| case eWNI_SME_REGISTER_MGMT_FRAME_CB: |
| case eWNI_SME_EXT_CHANGE_CHANNEL: |
| case eWNI_SME_ROAM_SCAN_OFFLOAD_REQ: |
| case eWNI_SME_SET_ADDBA_ACCEPT: |
| case eWNI_SME_UPDATE_EDCA_PROFILE: |
| /* These messages are from HDD.No need to respond to HDD */ |
| lim_process_normal_hdd_msg(mac_ctx, msg, false); |
| break; |
| case eWNI_SME_SEND_MGMT_FRAME_TX: |
| lim_send_mgmt_frame_tx(mac_ctx, msg); |
| qdf_mem_free(msg->bodyptr); |
| msg->bodyptr = NULL; |
| break; |
| case eWNI_SME_MON_INIT_SESSION: |
| lim_mon_init_session(mac_ctx, msg->bodyptr); |
| qdf_mem_free(msg->bodyptr); |
| msg->bodyptr = NULL; |
| break; |
| #ifdef FEATURE_WLAN_TDLS |
| case SIR_HAL_TDLS_IND: |
| tdls_ind = (tpSirTdlsInd) msg->bodyptr; |
| session_entry = pe_find_session_by_sta_id(mac_ctx, |
| tdls_ind->staIdx, &session_id); |
| if (session_entry == NULL) { |
| pe_debug("No session exist for given bssId"); |
| qdf_mem_free(msg->bodyptr); |
| msg->bodyptr = NULL; |
| return; |
| } |
| sta_ds = dph_get_hash_entry(mac_ctx, tdls_ind->assocId, |
| &session_entry->dph.dphHashTable); |
| if (sta_ds == NULL) { |
| pe_debug("No sta_ds exist for given staId"); |
| qdf_mem_free(msg->bodyptr); |
| msg->bodyptr = NULL; |
| return; |
| } |
| |
| if (STA_ENTRY_TDLS_PEER == sta_ds->staType) { |
| pe_err("rcvd TDLS IND from FW with RC %d", |
| tdls_ind->reasonCode); |
| lim_send_sme_tdls_del_sta_ind(mac_ctx, sta_ds, |
| session_entry, tdls_ind->reasonCode); |
| } |
| qdf_mem_free(msg->bodyptr); |
| msg->bodyptr = NULL; |
| break; |
| #endif |
| case SIR_HAL_P2P_NOA_ATTR_IND: |
| session_entry = &mac_ctx->lim.gpSession[0]; |
| pe_debug("Received message Noa_ATTR %x", |
| msg->type); |
| for (i = 0; i < mac_ctx->lim.maxBssId; i++) { |
| session_entry = &mac_ctx->lim.gpSession[i]; |
| if ((session_entry != NULL) && (session_entry->valid) |
| && (session_entry->pePersona == |
| QDF_P2P_GO_MODE)) { /* Save P2P attr for Go */ |
| qdf_mem_copy( |
| &session_entry->p2pGoPsUpdate, |
| msg->bodyptr, |
| sizeof(tSirP2PNoaAttr)); |
| pe_debug("bssId" |
| MAC_ADDRESS_STR |
| " ctWin=%d oppPsFlag=%d", |
| MAC_ADDR_ARRAY( |
| session_entry->bssId), |
| session_entry->p2pGoPsUpdate.ctWin, |
| session_entry->p2pGoPsUpdate.oppPsFlag); |
| pe_debug("uNoa1IntervalCnt=%d uNoa1Duration=%d uNoa1Interval=%d uNoa1StartTime=%d", |
| session_entry->p2pGoPsUpdate.uNoa1IntervalCnt, |
| session_entry->p2pGoPsUpdate.uNoa1Duration, |
| session_entry->p2pGoPsUpdate.uNoa1Interval, |
| session_entry->p2pGoPsUpdate.uNoa1StartTime); |
| break; |
| } |
| } |
| qdf_mem_free(msg->bodyptr); |
| msg->bodyptr = NULL; |
| break; |
| case WMA_MISSED_BEACON_IND: |
| lim_ps_offload_handle_missed_beacon_ind(mac_ctx, msg); |
| qdf_mem_free(msg->bodyptr); |
| msg->bodyptr = NULL; |
| break; |
| case SIR_LIM_ADDTS_RSP_TIMEOUT: |
| lim_process_sme_req_messages(mac_ctx, msg); |
| break; |
| #ifdef FEATURE_WLAN_ESE |
| case WMA_TSM_STATS_RSP: |
| lim_send_sme_pe_ese_tsm_rsp(mac_ctx, |
| (tAniGetTsmStatsRsp *) msg->bodyptr); |
| break; |
| #endif |
| case WMA_ADD_TS_RSP: |
| lim_process_hal_add_ts_rsp(mac_ctx, msg); |
| break; |
| case SIR_LIM_DEL_TS_IND: |
| lim_process_del_ts_ind(mac_ctx, msg); |
| break; |
| case SIR_LIM_BEACON_GEN_IND: |
| if (mac_ctx->lim.gLimSystemRole != eLIM_AP_ROLE) |
| sch_process_pre_beacon_ind(mac_ctx, msg); |
| break; |
| case SIR_LIM_DELETE_STA_CONTEXT_IND: |
| lim_delete_sta_context(mac_ctx, msg); |
| break; |
| case SIR_LIM_JOIN_FAIL_TIMEOUT: |
| case SIR_LIM_PERIODIC_JOIN_PROBE_REQ_TIMEOUT: |
| case SIR_LIM_AUTH_FAIL_TIMEOUT: |
| case SIR_LIM_AUTH_RSP_TIMEOUT: |
| case SIR_LIM_ASSOC_FAIL_TIMEOUT: |
| case SIR_LIM_REASSOC_FAIL_TIMEOUT: |
| case SIR_LIM_FT_PREAUTH_RSP_TIMEOUT: |
| case SIR_LIM_DISASSOC_ACK_TIMEOUT: |
| case SIR_LIM_DEAUTH_ACK_TIMEOUT: |
| case SIR_LIM_CONVERT_ACTIVE_CHANNEL_TO_PASSIVE: |
| case SIR_LIM_AUTH_RETRY_TIMEOUT: |
| case SIR_LIM_AUTH_SAE_TIMEOUT: |
| /* These timeout messages are handled by MLM sub module */ |
| lim_process_mlm_req_messages(mac_ctx, msg); |
| break; |
| case SIR_LIM_HEART_BEAT_TIMEOUT: |
| /** check if heart beat failed, even if one Beacon |
| * is rcvd within the Heart Beat interval continue |
| * normal processing |
| */ |
| if (NULL == msg->bodyptr) |
| pe_err("Can't Process HB TO - bodyptr is Null"); |
| else { |
| session_entry = (tpPESession) msg->bodyptr; |
| pe_err("SIR_LIM_HEART_BEAT_TIMEOUT, Session %d", |
| ((tpPESession) msg->bodyptr)->peSessionId); |
| limResetHBPktCount(session_entry); |
| lim_handle_heart_beat_timeout_for_session(mac_ctx, |
| session_entry); |
| } |
| break; |
| case SIR_LIM_PROBE_HB_FAILURE_TIMEOUT: |
| lim_handle_heart_beat_failure_timeout(mac_ctx); |
| break; |
| case SIR_LIM_CNF_WAIT_TIMEOUT: |
| /* Does not receive CNF or dummy packet */ |
| lim_handle_cnf_wait_timeout(mac_ctx, (uint16_t) msg->bodyval); |
| break; |
| case SIR_LIM_RETRY_INTERRUPT_MSG: |
| /* Message from ISR upon TFP's max retry limit interrupt */ |
| break; |
| case SIR_LIM_INV_KEY_INTERRUPT_MSG: |
| /* Message from ISR upon SP's Invalid session key interrupt */ |
| break; |
| case SIR_LIM_KEY_ID_INTERRUPT_MSG: |
| /* Message from ISR upon SP's Invalid key ID interrupt */ |
| break; |
| case SIR_LIM_REPLAY_THRES_INTERRUPT_MSG: |
| /* Message from ISR upon SP's Replay threshold interrupt */ |
| break; |
| case SIR_LIM_CHANNEL_SWITCH_TIMEOUT: |
| lim_process_channel_switch_timeout(mac_ctx); |
| break; |
| case SIR_LIM_QUIET_TIMEOUT: |
| lim_process_quiet_timeout(mac_ctx); |
| break; |
| case SIR_LIM_QUIET_BSS_TIMEOUT: |
| lim_process_quiet_bss_timeout(mac_ctx); |
| break; |
| case SIR_LIM_UPDATE_OLBC_CACHEL_TIMEOUT: |
| lim_handle_update_olbc_cache(mac_ctx); |
| break; |
| case WMA_ADD_BSS_RSP: |
| lim_process_mlm_add_bss_rsp(mac_ctx, msg); |
| break; |
| case WMA_HIDDEN_SSID_RESTART_RSP: |
| lim_process_mlm_update_hidden_ssid_rsp(mac_ctx, msg); |
| break; |
| case WMA_ADD_STA_RSP: |
| lim_process_add_sta_rsp(mac_ctx, msg); |
| break; |
| case WMA_DELETE_STA_RSP: |
| lim_process_mlm_del_sta_rsp(mac_ctx, msg); |
| break; |
| case WMA_DELETE_BSS_RSP: |
| case WMA_DELETE_BSS_HO_FAIL_RSP: |
| lim_handle_delete_bss_rsp(mac_ctx, msg); |
| break; |
| case WMA_CSA_OFFLOAD_EVENT: |
| lim_handle_csa_offload_msg(mac_ctx, msg); |
| break; |
| case WMA_SET_BSSKEY_RSP: |
| case WMA_SET_STA_BCASTKEY_RSP: |
| lim_process_mlm_set_bss_key_rsp(mac_ctx, msg); |
| break; |
| case WMA_SET_STAKEY_RSP: |
| lim_process_mlm_set_sta_key_rsp(mac_ctx, msg); |
| break; |
| case WMA_GET_STATISTICS_RSP: |
| lim_send_sme_pe_statistics_rsp(mac_ctx, msg->type, |
| (void *)msg->bodyptr); |
| break; |
| case WMA_SET_MIMOPS_RSP: |
| case WMA_SET_TX_POWER_RSP: |
| qdf_mem_free((void *)msg->bodyptr); |
| msg->bodyptr = NULL; |
| break; |
| case WMA_SET_MAX_TX_POWER_RSP: |
| rrm_set_max_tx_power_rsp(mac_ctx, msg); |
| if (msg->bodyptr != NULL) { |
| qdf_mem_free((void *)msg->bodyptr); |
| msg->bodyptr = NULL; |
| } |
| break; |
| case SIR_LIM_ADDR2_MISS_IND: |
| pe_err( |
| FL("Addr2 mismatch interrupt received %X"), msg->type); |
| /* message from HAL indicating addr2 mismatch interrupt occurred |
| * msg->bodyptr contains only pointer to 48-bit addr2 field |
| */ |
| qdf_mem_free((void *)(msg->bodyptr)); |
| msg->bodyptr = NULL; |
| break; |
| case WMA_AGGR_QOS_RSP: |
| lim_process_ft_aggr_qo_s_rsp(mac_ctx, msg); |
| break; |
| case WMA_SET_LINK_STATE_RSP: |
| link_state_param = (tLinkStateParams *) msg->bodyptr; |
| session_entry = link_state_param->session; |
| if (link_state_param->ft |
| #if defined WLAN_FEATURE_ROAM_OFFLOAD |
| && !session_entry->bRoamSynchInProgress |
| #endif |
| ) |
| lim_send_reassoc_req_with_ft_ies_mgmt_frame(mac_ctx, |
| session_entry->pLimMlmReassocReq, |
| session_entry); |
| if (link_state_param->callback) |
| link_state_param->callback(mac_ctx, |
| link_state_param->callbackArg, |
| link_state_param->status); |
| qdf_mem_free((void *)(msg->bodyptr)); |
| msg->bodyptr = NULL; |
| break; |
| case WMA_RX_CHN_STATUS_EVENT: |
| lim_process_rx_channel_status_event(mac_ctx, msg->bodyptr); |
| break; |
| case WMA_IBSS_PEER_INACTIVITY_IND: |
| lim_process_ibss_peer_inactivity(mac_ctx, msg->bodyptr); |
| qdf_mem_free((void *)(msg->bodyptr)); |
| msg->bodyptr = NULL; |
| break; |
| case WMA_DFS_BEACON_TX_SUCCESS_IND: |
| lim_process_beacon_tx_success_ind(mac_ctx, msg->type, |
| (void *)msg->bodyptr); |
| qdf_mem_free((void *)msg->bodyptr); |
| msg->bodyptr = NULL; |
| break; |
| case WMA_DISASSOC_TX_COMP: |
| lim_disassoc_tx_complete_cnf(mac_ctx, msg->bodyval, |
| msg->bodyptr); |
| break; |
| case WMA_DEAUTH_TX_COMP: |
| lim_deauth_tx_complete_cnf(mac_ctx, msg->bodyval, |
| msg->bodyptr); |
| break; |
| #ifdef FEATURE_AP_MCC_CH_AVOIDANCE |
| case WMA_UPDATE_Q2Q_IE_IND: |
| qdf_mem_zero(&beacon_params, sizeof(tUpdateBeaconParams)); |
| beacon_params.paramChangeBitmap = 0; |
| for (i = 0; i < mac_ctx->lim.maxBssId; i++) { |
| vdev_id = ((uint8_t *)msg->bodyptr)[i]; |
| session_entry = pe_find_session_by_sme_session_id( |
| mac_ctx, vdev_id); |
| if (session_entry == NULL) |
| continue; |
| session_entry->sap_advertise_avoid_ch_ie = |
| (uint8_t)msg->bodyval; |
| /* |
| * if message comes for DFS channel, no need to update: |
| * 1) We wont have MCC with DFS channels. so no need to |
| * add Q2Q IE |
| * 2) We cannot end up in DFS channel SCC by channel |
| * switch from non DFS MCC scenario, so no need to |
| * remove Q2Q IE |
| * 3) There is however a case where device start MCC and |
| * then user modifies hostapd.conf and does SAP |
| * restart, in such a case, beacon params will be |
| * reset and thus will not contain Q2Q IE, by default |
| */ |
| if (wlan_reg_get_channel_state(mac_ctx->pdev, |
| session_entry->currentOperChannel) |
| != CHANNEL_STATE_DFS) { |
| beacon_params.bssIdx = session_entry->bssIdx; |
| beacon_params.beaconInterval = |
| session_entry->beaconParams.beaconInterval; |
| beacon_params.paramChangeBitmap |= |
| PARAM_BCN_INTERVAL_CHANGED; |
| sch_set_fixed_beacon_fields(mac_ctx, |
| session_entry); |
| lim_send_beacon_params(mac_ctx, &beacon_params, |
| session_entry); |
| } |
| } |
| qdf_mem_free(msg->bodyptr); |
| msg->bodyptr = NULL; |
| break; |
| #endif /* FEATURE_AP_MCC_CH_AVOIDANCE */ |
| case eWNI_SME_NSS_UPDATE_REQ: |
| case eWNI_SME_DFS_BEACON_CHAN_SW_IE_REQ: |
| lim_process_sme_req_messages(mac_ctx, msg); |
| qdf_mem_free((void *)msg->bodyptr); |
| msg->bodyptr = NULL; |
| break; |
| case eWNI_SME_CHANNEL_CHANGE_REQ: |
| lim_process_sme_req_messages(mac_ctx, msg); |
| qdf_mem_free((void *)msg->bodyptr); |
| msg->bodyptr = NULL; |
| break; |
| case eWNI_SME_START_BEACON_REQ: |
| lim_process_sme_req_messages(mac_ctx, msg); |
| qdf_mem_free((void *)msg->bodyptr); |
| msg->bodyptr = NULL; |
| break; |
| case eWNI_SME_UPDATE_ADDITIONAL_IES: |
| lim_process_sme_req_messages(mac_ctx, msg); |
| qdf_mem_free((void *)msg->bodyptr); |
| msg->bodyptr = NULL; |
| break; |
| case eWNI_SME_MODIFY_ADDITIONAL_IES: |
| lim_process_sme_req_messages(mac_ctx, msg); |
| qdf_mem_free((void *)msg->bodyptr); |
| msg->bodyptr = NULL; |
| break; |
| #ifdef QCA_HT_2040_COEX |
| case eWNI_SME_SET_HT_2040_MODE: |
| lim_process_sme_req_messages(mac_ctx, msg); |
| qdf_mem_free((void *)msg->bodyptr); |
| msg->bodyptr = NULL; |
| break; |
| #endif |
| case SIR_HAL_PDEV_SET_HW_MODE_RESP: |
| lim_process_set_hw_mode_resp(mac_ctx, msg->bodyptr); |
| qdf_mem_free((void *)msg->bodyptr); |
| msg->bodyptr = NULL; |
| break; |
| case SIR_HAL_PDEV_HW_MODE_TRANS_IND: |
| lim_process_hw_mode_trans_ind(mac_ctx, msg->bodyptr); |
| qdf_mem_free((void *)msg->bodyptr); |
| msg->bodyptr = NULL; |
| break; |
| case SIR_HAL_PDEV_MAC_CFG_RESP: |
| lim_process_dual_mac_cfg_resp(mac_ctx, msg->bodyptr); |
| qdf_mem_free((void *)msg->bodyptr); |
| msg->bodyptr = NULL; |
| break; |
| case eWNI_SME_SET_IE_REQ: |
| lim_process_sme_req_messages(mac_ctx, msg); |
| qdf_mem_free((void *)msg->bodyptr); |
| msg->bodyptr = NULL; |
| break; |
| case eWNI_SME_HT40_OBSS_SCAN_IND: |
| lim_process_sme_obss_scan_ind(mac_ctx, msg); |
| qdf_mem_free(msg->bodyptr); |
| break; |
| case SIR_HAL_SOC_ANTENNA_MODE_RESP: |
| lim_process_set_antenna_resp(mac_ctx, msg->bodyptr); |
| qdf_mem_free((void *)msg->bodyptr); |
| msg->bodyptr = NULL; |
| break; |
| case eWNI_SME_DEFAULT_SCAN_IE: |
| lim_process_set_default_scan_ie_request(mac_ctx, msg->bodyptr); |
| qdf_mem_free((void *)msg->bodyptr); |
| msg->bodyptr = NULL; |
| break; |
| case eWNI_SME_SET_HE_BSS_COLOR: |
| lim_process_set_he_bss_color(mac_ctx, msg->bodyptr); |
| qdf_mem_free((void *)msg->bodyptr); |
| msg->bodyptr = NULL; |
| break; |
| case eWNI_SME_DEL_ALL_TDLS_PEERS: |
| lim_process_sme_del_all_tdls_peers(mac_ctx, msg->bodyptr); |
| qdf_mem_free((void *)msg->bodyptr); |
| msg->bodyptr = NULL; |
| break; |
| case WMA_OBSS_DETECTION_INFO: |
| lim_process_obss_detection_ind(mac_ctx, msg->bodyptr); |
| qdf_mem_free(msg->bodyptr); |
| msg->bodyptr = NULL; |
| break; |
| case eWNI_SME_SEND_SAE_MSG: |
| lim_process_sae_msg(mac_ctx, msg->bodyptr); |
| qdf_mem_free((void *)msg->bodyptr); |
| msg->bodyptr = NULL; |
| break; |
| case WMA_OBSS_COLOR_COLLISION_INFO: |
| lim_process_obss_color_collision_info(mac_ctx, msg->bodyptr); |
| qdf_mem_free((void *)msg->bodyptr); |
| msg->bodyptr = NULL; |
| break; |
| default: |
| qdf_mem_free((void *)msg->bodyptr); |
| msg->bodyptr = NULL; |
| pe_debug("Discarding unexpected message received %X", |
| msg->type); |
| lim_print_msg_name(mac_ctx, LOGE, msg->type); |
| break; |
| |
| } /* switch (msg->type) */ |
| } /*** end lim_process_messages() ***/ |
| |
| /** |
| * lim_process_deferred_message_queue() |
| * |
| * This function is called by LIM while exiting from Learn |
| * mode. This function fetches messages posted to the LIM |
| * deferred message queue limDeferredMsgQ. |
| * |
| * @pMac: Pointer to Global MAC structure |
| * @return None |
| */ |
| |
| static void lim_process_deferred_message_queue(tpAniSirGlobal pMac) |
| { |
| struct scheduler_msg limMsg = {0}; |
| struct scheduler_msg *readMsg; |
| uint16_t size; |
| |
| /* |
| ** check any deferred messages need to be processed |
| **/ |
| size = pMac->lim.gLimDeferredMsgQ.size; |
| if (size > 0) { |
| while ((readMsg = lim_read_deferred_msg_q(pMac)) != NULL) { |
| qdf_mem_copy((uint8_t *) &limMsg, |
| (uint8_t *) readMsg, |
| sizeof(struct scheduler_msg)); |
| size--; |
| lim_process_messages(pMac, &limMsg); |
| |
| if ((lim_is_system_in_scan_state(pMac)) |
| || (true != GET_LIM_PROCESS_DEFD_MESGS(pMac)) |
| || (pMac->lim.gLimSystemInScanLearnMode) |
| || pMac->lim.gLimAddtsSent) |
| break; |
| } |
| } |
| } /*** end lim_process_deferred_message_queue() ***/ |
| |
| /** |
| * lim_message_processor() - Process messages from LIM. |
| * @mac_ctx: Pointer to the Global Mac Context. |
| * @msg: Received LIM message. |
| * |
| * Wrapper function for lim_process_messages when handling messages received by |
| * LIM. Could either defer messages or process them. |
| * |
| * Return: None. |
| */ |
| void lim_message_processor(tpAniSirGlobal mac_ctx, struct scheduler_msg *msg) |
| { |
| if (eLIM_MLM_OFFLINE_STATE == mac_ctx->lim.gLimMlmState) { |
| pe_free_msg(mac_ctx, msg); |
| return; |
| } |
| |
| if (!def_msg_decision(mac_ctx, msg)) { |
| lim_process_messages(mac_ctx, msg); |
| /* process deferred message queue if allowed */ |
| if ((!(mac_ctx->lim.gLimAddtsSent)) && |
| (!(lim_is_system_in_scan_state(mac_ctx))) && |
| (true == GET_LIM_PROCESS_DEFD_MESGS(mac_ctx))) |
| lim_process_deferred_message_queue(mac_ctx); |
| } |
| } |
| |
| /** |
| * lim_process_normal_hdd_msg() - Process the message and defer if needed |
| * @mac_ctx : Pointer to Global MAC structure |
| * @msg : The message need to be processed |
| * @rsp_reqd: whether return result to hdd |
| * |
| * This function checks the current lim state and decide whether the message |
| * passed will be deferred or not. |
| * |
| * Return: None |
| */ |
| static void lim_process_normal_hdd_msg(tpAniSirGlobal mac_ctx, |
| struct scheduler_msg *msg, |
| uint8_t rsp_reqd) |
| { |
| bool defer_msg = true; |
| |
| /* Added For BT-AMP Support */ |
| if ((mac_ctx->lim.gLimSystemRole == eLIM_AP_ROLE) |
| || (mac_ctx->lim.gLimSystemRole == eLIM_UNKNOWN_ROLE)) { |
| /* |
| * This check is required only for the AP and in 2 cases. |
| * 1. If we are in learn mode and we receive any of these |
| * messages, you have to come out of scan and process the |
| * message, hence dont defer the message here. In handler, |
| * these message could be defered till we actually come out of |
| * scan mode. |
| * 2. If radar is detected, you might have to defer all of |
| * these messages except Stop BSS request/ Switch channel |
| * request. This decision is also made inside its handler. |
| * |
| * Please be careful while using the flag defer_msg. Possibly |
| * you might end up in an infinite loop. |
| */ |
| if ((msg->type == eWNI_SME_START_BSS_REQ) || |
| (msg->type == eWNI_SME_STOP_BSS_REQ) || |
| (msg->type == eWNI_SME_SWITCH_CHL_IND)) |
| defer_msg = false; |
| } |
| |
| if (((mac_ctx->lim.gLimAddtsSent) || |
| (lim_is_system_in_scan_state(mac_ctx))) && defer_msg) { |
| /* |
| * System is in DFS (Learn) mode or awaiting addts response or |
| * if radar is detected, Defer processsing this message |
| */ |
| if (lim_defer_msg(mac_ctx, msg) != TX_SUCCESS) { |
| #ifdef WLAN_DEBUG |
| mac_ctx->lim.numSme++; |
| #endif |
| lim_log_session_states(mac_ctx); |
| /* Release body */ |
| qdf_mem_free(msg->bodyptr); |
| msg->bodyptr = NULL; |
| } |
| } else { |
| /* |
| * These messages are from HDD.Since these requests may also be |
| * generated internally within LIM module, need to distinquish |
| * and send response to host |
| */ |
| if (rsp_reqd) |
| mac_ctx->lim.gLimRspReqd = true; |
| #ifdef WLAN_DEBUG |
| mac_ctx->lim.numSme++; |
| #endif |
| if (lim_process_sme_req_messages(mac_ctx, msg)) { |
| /* |
| * Release body. limProcessSmeReqMessage consumed the |
| * buffer. We can free it. |
| */ |
| qdf_mem_free(msg->bodyptr); |
| msg->bodyptr = NULL; |
| } |
| } |
| } |
| |
| void |
| handle_ht_capabilityand_ht_info(struct sAniSirGlobal *pMac, |
| tpPESession psessionEntry) |
| { |
| tSirMacHTCapabilityInfo macHTCapabilityInfo; |
| tSirMacHTParametersInfo macHTParametersInfo; |
| tSirMacHTInfoField1 macHTInfoField1; |
| tSirMacHTInfoField2 macHTInfoField2; |
| tSirMacHTInfoField3 macHTInfoField3; |
| uint32_t cfgValue; |
| uint8_t *ptr; |
| |
| if (wlan_cfg_get_int(pMac, WNI_CFG_HT_CAP_INFO, &cfgValue) != |
| eSIR_SUCCESS) { |
| pe_err("Fail to retrieve WNI_CFG_HT_CAP_INFO value"); |
| return; |
| } |
| ptr = (uint8_t *) &macHTCapabilityInfo; |
| *((uint16_t *) ptr) = (uint16_t) (cfgValue & 0xffff); |
| pMac->lim.gHTLsigTXOPProtection = |
| (uint8_t) macHTCapabilityInfo.lsigTXOPProtection; |
| pMac->lim.gHTMIMOPSState = |
| (tSirMacHTMIMOPowerSaveState) macHTCapabilityInfo.mimoPowerSave; |
| pMac->lim.gHTGreenfield = (uint8_t) macHTCapabilityInfo.greenField; |
| pMac->lim.gHTMaxAmsduLength = |
| (uint8_t) macHTCapabilityInfo.maximalAMSDUsize; |
| pMac->lim.gHTShortGI20Mhz = (uint8_t) macHTCapabilityInfo.shortGI20MHz; |
| pMac->lim.gHTShortGI40Mhz = (uint8_t) macHTCapabilityInfo.shortGI40MHz; |
| pMac->lim.gHTPSMPSupport = (uint8_t) macHTCapabilityInfo.psmp; |
| pMac->lim.gHTDsssCckRate40MHzSupport = |
| (uint8_t) macHTCapabilityInfo.dsssCckMode40MHz; |
| |
| if (wlan_cfg_get_int(pMac, WNI_CFG_HT_AMPDU_PARAMS, &cfgValue) != |
| eSIR_SUCCESS) { |
| pe_err("Fail to retrieve WNI_CFG_HT_PARAM_INFO value"); |
| return; |
| } |
| ptr = (uint8_t *) &macHTParametersInfo; |
| *ptr = (uint8_t) (cfgValue & 0xff); |
| pMac->lim.gHTAMpduDensity = (uint8_t) macHTParametersInfo.mpduDensity; |
| pMac->lim.gHTMaxRxAMpduFactor = |
| (uint8_t) macHTParametersInfo.maxRxAMPDUFactor; |
| |
| /* Get HT IE Info */ |
| if (wlan_cfg_get_int(pMac, WNI_CFG_HT_INFO_FIELD1, &cfgValue) != |
| eSIR_SUCCESS) { |
| pe_err("Fail to retrieve WNI_CFG_HT_INFO_FIELD1 value"); |
| return; |
| } |
| ptr = (uint8_t *) &macHTInfoField1; |
| *((uint8_t *) ptr) = (uint8_t) (cfgValue & 0xff); |
| pMac->lim.gHTServiceIntervalGranularity = |
| (uint8_t) macHTInfoField1.serviceIntervalGranularity; |
| pMac->lim.gHTControlledAccessOnly = |
| (uint8_t) macHTInfoField1.controlledAccessOnly; |
| pMac->lim.gHTRifsMode = (uint8_t) macHTInfoField1.rifsMode; |
| |
| if (wlan_cfg_get_int(pMac, WNI_CFG_HT_INFO_FIELD2, &cfgValue) != |
| eSIR_SUCCESS) { |
| pe_err("Fail to retrieve WNI_CFG_HT_INFO_FIELD2 value"); |
| return; |
| } |
| ptr = (uint8_t *) &macHTInfoField2; |
| *((uint16_t *) ptr) = (uint16_t) (cfgValue & 0xffff); |
| pMac->lim.gHTOperMode = (tSirMacHTOperatingMode) macHTInfoField2.opMode; |
| |
| if (wlan_cfg_get_int(pMac, WNI_CFG_HT_INFO_FIELD3, &cfgValue) != |
| eSIR_SUCCESS) { |
| pe_err("Fail to retrieve WNI_CFG_HT_INFO_FIELD3 value"); |
| return; |
| } |
| ptr = (uint8_t *) &macHTInfoField3; |
| *((uint16_t *) ptr) = (uint16_t) (cfgValue & 0xffff); |
| pMac->lim.gHTPCOActive = (uint8_t) macHTInfoField3.pcoActive; |
| pMac->lim.gHTPCOPhase = (uint8_t) macHTInfoField3.pcoPhase; |
| pMac->lim.gHTSecondaryBeacon = |
| (uint8_t) macHTInfoField3.secondaryBeacon; |
| pMac->lim.gHTDualCTSProtection = |
| (uint8_t) macHTInfoField3.dualCTSProtection; |
| pMac->lim.gHTSTBCBasicMCS = (uint8_t) macHTInfoField3.basicSTBCMCS; |
| |
| /* The lim globals for channelwidth and secondary chnl have been removed and should not be used during no session; |
| * instead direct cfg is read and used when no session for transmission of mgmt frames (same as old); |
| * For now, we might come here during init and join with sessionEntry = NULL; in that case just fill the globals which exist |
| * Sessionized entries values will be filled in join or add bss req. The ones which are missed in join are filled below |
| */ |
| if (psessionEntry != NULL) { |
| psessionEntry->htCapability = |
| IS_DOT11_MODE_HT(psessionEntry->dot11mode); |
| psessionEntry->beaconParams.fLsigTXOPProtectionFullSupport = |
| (uint8_t) macHTInfoField3.lsigTXOPProtectionFullSupport; |
| lim_init_obss_params(pMac, psessionEntry); |
| } |
| } |
| |
| void lim_log_session_states(tpAniSirGlobal mac_ctx) |
| { |
| #ifdef WLAN_DEBUG |
| int i; |
| |
| for (i = 0; i < mac_ctx->lim.maxBssId; i++) { |
| if (mac_ctx->lim.gpSession[i].valid) { |
| QDF_TRACE(QDF_MODULE_ID_PE, LOGD, |
| FL("sysRole(%d) Session (%d)"), |
| mac_ctx->lim.gLimSystemRole, i); |
| QDF_TRACE(QDF_MODULE_ID_PE, LOGD, |
| FL("SME: Curr %s,Prev %s,MLM: Curr %s,Prev %s"), |
| lim_sme_state_str( |
| mac_ctx->lim.gpSession[i].limSmeState), |
| lim_sme_state_str( |
| mac_ctx->lim.gpSession[i].limPrevSmeState), |
| lim_mlm_state_str( |
| mac_ctx->lim.gpSession[i].limMlmState), |
| lim_mlm_state_str( |
| mac_ctx->lim.gpSession[i].limPrevMlmState)); |
| } |
| } |
| #endif |
| } |