blob: 091e425bd879ab0da385b7867d68ae89c1577d93 [file] [log] [blame]
/*
* Copyright (c) 2011-2018 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
* above copyright notice and this permission notice appear in all
* copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
/*
* This file was originally distributed by Qualcomm Atheros, Inc.
* under proprietary terms before Copyright ownership was assigned
* to the Linux Foundation.
*/
/*
* This file 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_P2P_NOA_START_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;
}
/**
* 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) */
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;
uint8_t p2p_go_exists = 0;
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;
case SIR_HAL_P2P_NOA_START_IND:
session_entry = &mac_ctx->lim.gpSession[0];
pe_debug("LIM received NOA start %x", msg->type);
/* Since insert NOA is done and NOA start msg received,
* we should deactivate the Insert NOA timer
*/
lim_deactivate_and_change_timer(mac_ctx,
eLIM_INSERT_SINGLESHOT_NOA_TIMER);
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 NOA start attribute for Go persona*/
p2p_go_exists = 1;
qdf_mem_copy(&session_entry->p2pGoPsNoaStartInd,
msg->bodyptr, sizeof(tSirP2PNoaStart));
qdf_status =
session_entry->p2pGoPsNoaStartInd.status;
if (qdf_status != QDF_STATUS_SUCCESS)
QDF_TRACE(QDF_MODULE_ID_PE, LOGW,
FL(
"GO NOA start status %d by FW"),
qdf_status);
break;
}
}
if (p2p_go_exists == 0)
QDF_TRACE(QDF_MODULE_ID_PE, LOGW,
FL(
"GO is removed by the time NOA start recvd"));
/* We received the NOA start indication. Now we can send down
* the SME request which requires off-channel operation */
lim_process_regd_defd_sme_req_after_noa_start(mac_ctx);
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_INSERT_SINGLESHOT_NOA_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
}