qcacld-3.0: Initial snapshot of ihelium wlan driver
qcacld-3.0: Initial snapshot of ihelium wlan driver
to match code-scanned SU Release 5.0.0.139. This is
open-source version of wlan for next Android release.
Change-Id: Icf598ca97da74f84bea607e4e902d1889806f507
diff --git a/core/mac/src/pe/include/lim_admit_control.h b/core/mac/src/pe/include/lim_admit_control.h
new file mode 100644
index 0000000..90eae86
--- /dev/null
+++ b/core/mac/src/pe/include/lim_admit_control.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2011-2012, 2014-2015 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.
+ */
+
+/*
+ *
+ * Author: Dinesh Upadhyay
+ * Date: 10/24/06
+ * History:-
+ * Date Modified by Modification Information
+ * --------------------------------------------------------------------
+ *
+ */
+
+#ifndef __LIM_ADMIT_CONTROL_H__
+#define __LIM_ADMIT_CONTROL_H__
+
+#include "sir_common.h"
+#include "sir_mac_prot_def.h"
+
+#include "ani_global.h"
+
+tSirRetStatus
+lim_tspec_find_by_assoc_id(tpAniSirGlobal, uint16_t, tSirMacTspecIE *,
+ tpLimTspecInfo, tpLimTspecInfo *);
+
+/* Add TSPEC in lim local table */
+tSirRetStatus lim_tspec_add(tpAniSirGlobal pMac,
+ uint8_t *pAddr,
+ uint16_t assocId,
+ tSirMacTspecIE *pTspec,
+ uint32_t interval, tpLimTspecInfo *ppInfo);
+
+/* admit control interface */
+extern tSirRetStatus lim_admit_control_add_ts(tpAniSirGlobal pMac,
+ uint8_t *pAddr, tSirAddtsReqInfo *addts,
+ tSirMacQosCapabilityStaIE *qos,
+ uint16_t assocId, uint8_t alloc,
+ tSirMacScheduleIE *pSch,
+ /* index to the lim tspec table. */
+ uint8_t *pTspecIdx,
+ tpPESession psessionEntry);
+
+static inline tSirRetStatus
+lim_admit_control_add_sta(tpAniSirGlobal pMac, uint8_t *staAddr, uint8_t alloc)
+{
+ return eSIR_SUCCESS;
+}
+
+extern tSirRetStatus
+lim_admit_control_delete_sta(tpAniSirGlobal pMac, uint16_t assocId);
+
+extern tSirRetStatus
+lim_admit_control_delete_ts(tpAniSirGlobal pMac,
+ uint16_t assocId,
+ tSirMacTSInfo *tsinfo,
+ uint8_t *tsStatus, uint8_t *tspecIdx);
+
+extern tSirRetStatus lim_update_admit_policy(tpAniSirGlobal pMac);
+
+tSirRetStatus lim_admit_control_init(tpAniSirGlobal pMac);
+#ifdef FEATURE_WLAN_ESE
+tSirRetStatus lim_send_hal_msg_add_ts(tpAniSirGlobal pMac,
+ uint16_t staIdx,
+ uint8_t tspecIdx,
+ tSirMacTspecIE tspecIE,
+ uint8_t sessionId, uint16_t tsm_interval);
+#else
+tSirRetStatus lim_send_hal_msg_add_ts(tpAniSirGlobal pMac,
+ uint16_t staIdx,
+ uint8_t tspecIdx,
+ tSirMacTspecIE tspecIE,
+ uint8_t sessionId);
+#endif
+
+tSirRetStatus lim_send_hal_msg_del_ts(tpAniSirGlobal pMac,
+ uint16_t staIdx,
+ uint8_t tspecIdx,
+ tSirDeltsReqInfo delts,
+ uint8_t sessionId, uint8_t *bssId);
+void lim_process_hal_add_ts_rsp(tpAniSirGlobal pMac, tpSirMsgQ limMsg);
+
+#endif
diff --git a/core/mac/src/pe/include/lim_api.h b/core/mac/src/pe/include/lim_api.h
new file mode 100644
index 0000000..99e2fc7
--- /dev/null
+++ b/core/mac/src/pe/include/lim_api.h
@@ -0,0 +1,251 @@
+/*
+ * Copyright (c) 2011-2015 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_api.h contains the definitions exported by
+ * LIM module.
+ * Author: Chandra Modumudi
+ * Date: 02/11/02
+ * History:-
+ * Date Modified by Modification Information
+ * --------------------------------------------------------------------
+ *
+ */
+#ifndef __LIM_API_H
+#define __LIM_API_H
+#include "wni_api.h"
+#include "sir_api.h"
+#include "ani_global.h"
+#include "sir_mac_prot_def.h"
+#include "sir_common.h"
+#include "sir_debug.h"
+#include "sch_global.h"
+#include "utils_api.h"
+#include "lim_global.h"
+#include "wma_if.h"
+#include "wma_types.h"
+
+/* Macro to count heartbeat */
+#define limResetHBPktCount(psessionEntry) (psessionEntry->LimRxedBeaconCntDuringHB = 0)
+
+/* Useful macros for fetching various states in pMac->lim */
+/* gLimSystemRole */
+#define GET_LIM_SYSTEM_ROLE(psessionEntry) (psessionEntry->limSystemRole)
+#define LIM_IS_AP_ROLE(psessionEntry) (GET_LIM_SYSTEM_ROLE(psessionEntry) == eLIM_AP_ROLE)
+#define LIM_IS_STA_ROLE(psessionEntry) (GET_LIM_SYSTEM_ROLE(psessionEntry) == eLIM_STA_ROLE)
+#define LIM_IS_IBSS_ROLE(psessionEntry) (GET_LIM_SYSTEM_ROLE(psessionEntry) == eLIM_STA_IN_IBSS_ROLE)
+#define LIM_IS_UNKNOWN_ROLE(psessionEntry) (GET_LIM_SYSTEM_ROLE(psessionEntry) == eLIM_UNKNOWN_ROLE)
+#define LIM_IS_BT_AMP_AP_ROLE(psessionEntry) (GET_LIM_SYSTEM_ROLE(psessionEntry) == eLIM_BT_AMP_AP_ROLE)
+#define LIM_IS_BT_AMP_STA_ROLE(psessionEntry) (GET_LIM_SYSTEM_ROLE(psessionEntry) == eLIM_BT_AMP_STA_ROLE)
+#define LIM_IS_P2P_DEVICE_ROLE(psessionEntry) (GET_LIM_SYSTEM_ROLE(psessionEntry) == eLIM_P2P_DEVICE_ROLE)
+#define LIM_IS_P2P_DEVICE_GO(psessionEntry) (GET_LIM_SYSTEM_ROLE(psessionEntry) == eLIM_P2P_DEVICE_GO)
+/* gLimSmeState */
+#define GET_LIM_SME_STATE(pMac) (pMac->lim.gLimSmeState)
+#define SET_LIM_SME_STATE(pMac, state) (pMac->lim.gLimSmeState = state)
+/* gLimMlmState */
+#define GET_LIM_MLM_STATE(pMac) (pMac->lim.gLimMlmState)
+#define SET_LIM_MLM_STATE(pMac, state) (pMac->lim.gLimMlmState = state)
+/*tpdphHashNode mlmStaContext*/
+#define GET_LIM_STA_CONTEXT_MLM_STATE(pStaDs) (pStaDs->mlmStaContext.mlmState)
+#define SET_LIM_STA_CONTEXT_MLM_STATE(pStaDs, state) (pStaDs->mlmStaContext.mlmState = state)
+/* gLimQuietState */
+#define GET_LIM_QUIET_STATE(pMac) (pMac->lim.gLimSpecMgmt.quietState)
+#define SET_LIM_QUIET_STATE(pMac, state) (pMac->lim.gLimSpecMgmt.quietState = state)
+#define LIM_IS_CONNECTION_ACTIVE(psessionEntry) (psessionEntry->LimRxedBeaconCntDuringHB)
+/*pMac->lim.gLimProcessDefdMsgs*/
+#define GET_LIM_PROCESS_DEFD_MESGS(pMac) (pMac->lim.gLimProcessDefdMsgs)
+#define SET_LIM_PROCESS_DEFD_MESGS(pMac, val) (pMac->lim.gLimProcessDefdMsgs = val)
+/* LIM exported function templates */
+#define LIM_IS_RADAR_DETECTED(pMac) (pMac->lim.gLimSpecMgmt.fRadarDetCurOperChan)
+#define LIM_SET_RADAR_DETECTED(pMac, val) (pMac->lim.gLimSpecMgmt.fRadarDetCurOperChan = val)
+#define LIM_MIN_BCN_PR_LENGTH 12
+#define LIM_BCN_PR_CAPABILITY_OFFSET 10
+typedef enum eMgmtFrmDropReason {
+ eMGMT_DROP_NO_DROP,
+ eMGMT_DROP_NOT_LAST_IBSS_BCN,
+ eMGMT_DROP_INFRA_BCN_IN_IBSS,
+ eMGMT_DROP_SCAN_MODE_FRAME,
+ eMGMT_DROP_NON_SCAN_MODE_FRAME,
+ eMGMT_DROP_INVALID_SIZE,
+ eMGMT_DROP_SPURIOUS_FRAME,
+} tMgmtFrmDropReason;
+
+/**
+ * Function to initialize LIM state machines.
+ * This called upon LIM thread creation.
+ */
+extern tSirRetStatus lim_initialize(tpAniSirGlobal);
+tSirRetStatus pe_open(tpAniSirGlobal pMac, tMacOpenParameters *pMacOpenParam);
+tSirRetStatus pe_close(tpAniSirGlobal pMac);
+void pe_register_tl_handle(tpAniSirGlobal pMac);
+tSirRetStatus lim_start(tpAniSirGlobal pMac);
+tSirRetStatus pe_start(tpAniSirGlobal pMac);
+void pe_stop(tpAniSirGlobal pMac);
+tSirRetStatus pe_post_msg_api(tpAniSirGlobal pMac, tSirMsgQ *pMsg);
+tSirRetStatus peProcessMsg(tpAniSirGlobal pMac, tSirMsgQ *limMsg);
+/**
+ * Function to cleanup LIM state.
+ * This called upon reset/persona change etc
+ */
+extern void lim_cleanup(tpAniSirGlobal);
+/* / Function to post messages to LIM thread */
+extern uint32_t lim_post_msg_api(tpAniSirGlobal, tSirMsgQ *);
+/**
+ * Function to process messages posted to LIM thread
+ * and dispatch to various sub modules within LIM module.
+ */
+extern void lim_message_processor(tpAniSirGlobal, tpSirMsgQ);
+extern void lim_process_messages(tpAniSirGlobal, tpSirMsgQ); /* DT test alt deferred 2 */
+/**
+ * Function to check the LIM state if system is in Scan/Learn state.
+ */
+extern uint8_t lim_is_system_in_scan_state(tpAniSirGlobal);
+/**
+ * Function to handle IBSS coalescing.
+ * Beacon Processing module to call this.
+ */
+extern tSirRetStatus lim_handle_ibss_coalescing(tpAniSirGlobal,
+ tpSchBeaconStruct,
+ uint8_t *, tpPESession);
+/* / Function used by other Sirius modules to read global SME state */
+static inline tLimSmeStates lim_get_sme_state(tpAniSirGlobal pMac)
+{
+ return pMac->lim.gLimSmeState;
+}
+
+extern void lim_received_hb_handler(tpAniSirGlobal, uint8_t, tpPESession);
+extern void limCheckAndQuietBSS(tpAniSirGlobal);
+/* / Function that triggers STA context deletion */
+extern void lim_trigger_sta_deletion(tpAniSirGlobal pMac, tpDphHashNode pStaDs,
+ tpPESession psessionEntry);
+
+#ifdef FEATURE_WLAN_TDLS
+/* Function that sends TDLS Del Sta indication to SME */
+extern void lim_send_sme_tdls_del_sta_ind(tpAniSirGlobal pMac, tpDphHashNode pStaDs,
+ tpPESession psessionEntry,
+ uint16_t reasonCode);
+#endif
+
+/* / Function that checks for change in AP's capabilties on STA */
+extern void lim_detect_change_in_ap_capabilities(tpAniSirGlobal,
+ tpSirProbeRespBeacon, tpPESession);
+tSirRetStatus lim_update_short_slot(tpAniSirGlobal pMac,
+ tpSirProbeRespBeacon pBeacon,
+ tpUpdateBeaconParams pBeaconParams,
+ tpPESession);
+
+void lim_ps_offload_handle_missed_beacon_ind(tpAniSirGlobal pMac, tpSirMsgQ pMsg);
+void lim_send_heart_beat_timeout_ind(tpAniSirGlobal pMac, tpPESession psessionEntry);
+tMgmtFrmDropReason lim_is_pkt_candidate_for_drop(tpAniSirGlobal pMac,
+ uint8_t *pRxPacketInfo,
+ uint32_t subType);
+bool lim_is_deauth_diassoc_for_drop(tpAniSirGlobal mac, uint8_t *rx_pkt_info);
+#ifdef WLAN_FEATURE_11W
+bool lim_is_assoc_req_for_drop(tpAniSirGlobal mac, uint8_t *rx_pkt_info);
+#endif
+#ifdef WLAN_FEATURE_ROAM_OFFLOAD
+void lim_roam_offload_synch_ind(tpAniSirGlobal pMac, tpSirMsgQ pMsg);
+#endif
+#define limGetQosMode(psessionEntry, pVal) (*(pVal) = (psessionEntry)->limQosEnabled)
+#define limGetWmeMode(psessionEntry, pVal) (*(pVal) = (psessionEntry)->limWmeEnabled)
+#define limGetWsmMode(psessionEntry, pVal) (*(pVal) = (psessionEntry)->limWsmEnabled)
+#define limGet11dMode(psessionEntry, pVal) (*(pVal) = (psessionEntry)->lim11dEnabled)
+#define limGetAckPolicy(pMac, pVal) (*(pVal) = pMac->lim.ackPolicy)
+/* ----------------------------------------------------------------------- */
+static inline void lim_get_phy_mode(tpAniSirGlobal pMac, uint32_t *phyMode,
+ tpPESession psessionEntry)
+{
+ *phyMode =
+ psessionEntry ? psessionEntry->gLimPhyMode : pMac->lim.gLimPhyMode;
+}
+
+/* ----------------------------------------------------------------------- */
+static inline void lim_get_rf_band_new(tpAniSirGlobal pMac, tSirRFBand *band,
+ tpPESession psessionEntry)
+{
+ *band = psessionEntry ? psessionEntry->limRFBand : SIR_BAND_UNKNOWN;
+}
+
+/*--------------------------------------------------------------------------
+
+ \brief pe_process_messages() - Message Processor for PE
+
+ Voss calls this function to dispatch the message to PE
+
+ \param pMac - Pointer to Global MAC structure
+ \param pMsg - Pointer to the message structure
+
+ \return uint32_t - TX_SUCCESS for success.
+
+ --------------------------------------------------------------------------*/
+tSirRetStatus pe_process_messages(tpAniSirGlobal pMac, tSirMsgQ *pMsg);
+/** -------------------------------------------------------------
+ \fn pe_free_msg
+ \brief Called by CDS scheduler (function cds_sched_flush_mc_mqs)
+ \ to free a given PE message on the TX and MC thread.
+ \ This happens when there are messages pending in the PE
+ \ queue when system is being stopped and reset.
+ \param tpAniSirGlobal pMac
+ \param tSirMsgQ pMsg
+ \return none
+ -----------------------------------------------------------------*/
+void pe_free_msg(tpAniSirGlobal pMac, tSirMsgQ *pMsg);
+
+/*--------------------------------------------------------------------------
+
+ \brief lim_remain_on_chn_rsp() - API for sending remain on channel response.
+
+ LIM calls this api to send the remain on channel response to SME.
+
+ \param pMac - Pointer to Global MAC structure
+ \param status - status of the response
+ \param data - pointer to msg
+
+ \return void
+
+ --------------------------------------------------------------------------*/
+void lim_remain_on_chn_rsp(tpAniSirGlobal pMac, CDF_STATUS status, uint32_t *data);
+
+/*--------------------------------------------------------------------------
+
+ \brief lim_process_abort_scan_ind() - function for sending abort scan indication.
+
+ LIM calls this function for sending abort scan indication.
+
+ \param pMac - Pointer to Global MAC structure
+
+ \return void
+
+ --------------------------------------------------------------------------*/
+void lim_process_abort_scan_ind(tpAniSirGlobal pMac, uint8_t sessionId,
+ uint32_t scan_id);
+
+void __lim_process_sme_assoc_cnf_new(tpAniSirGlobal, uint32_t, uint32_t *);
+
+/************************************************************/
+#endif /* __LIM_API_H */
diff --git a/core/mac/src/pe/include/lim_ft.h b/core/mac/src/pe/include/lim_ft.h
new file mode 100644
index 0000000..a0be848
--- /dev/null
+++ b/core/mac/src/pe/include/lim_ft.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2011-2014 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.
+ */
+
+#if defined WLAN_FEATURE_VOWIFI_11R
+/**=========================================================================
+
+ Macros and Function prototypes FT and 802.11R purposes
+
+ ========================================================================*/
+
+#ifndef __LIMFT_H__
+#define __LIMFT_H__
+
+#include <cds_api.h>
+#include <lim_global.h>
+#include <ani_global.h>
+#include <lim_debug.h>
+#include <lim_ser_des_utils.h>
+
+/*-------------------------------------------------------------------------
+ Function declarations and documenation
+ ------------------------------------------------------------------------*/
+void lim_ft_open(tpAniSirGlobal pMac, tpPESession psessionEntry);
+void lim_ft_cleanup(tpAniSirGlobal pMac, tpPESession psessionEntry);
+void lim_ft_cleanup_pre_auth_info(tpAniSirGlobal pMac, tpPESession psessionEntry);
+int lim_process_ft_pre_auth_req(tpAniSirGlobal pMac, tpSirMsgQ pMsg);
+void lim_perform_ft_pre_auth(tpAniSirGlobal pMac, CDF_STATUS status,
+ uint32_t *data, tpPESession psessionEntry);
+void limPerformPostFTPreAuth(tpAniSirGlobal pMac, CDF_STATUS status,
+ uint32_t *data, tpPESession psessionEntry);
+void limFTResumeLinkCb(tpAniSirGlobal pMac, CDF_STATUS status, uint32_t *data);
+void lim_post_ft_pre_auth_rsp(tpAniSirGlobal pMac, tSirRetStatus status,
+ uint8_t *auth_rsp, uint16_t auth_rsp_length,
+ tpPESession psessionEntry);
+void lim_handle_ft_pre_auth_rsp(tpAniSirGlobal pMac, tSirRetStatus status,
+ uint8_t *auth_rsp, uint16_t auth_rsp_len,
+ tpPESession psessionEntry);
+void lim_process_mlm_ft_reassoc_req(tpAniSirGlobal pMac, uint32_t *pMsgBuf,
+ tpPESession psessionEntry);
+void lim_process_ft_preauth_rsp_timeout(tpAniSirGlobal pMac);
+
+bool lim_process_ft_update_key(tpAniSirGlobal pMac, uint32_t *pMsgBuf);
+tSirRetStatus lim_process_ft_aggr_qos_req(tpAniSirGlobal pMac, uint32_t *pMsgBuf);
+void lim_process_ft_aggr_qo_s_rsp(tpAniSirGlobal pMac, tpSirMsgQ limMsg);
+void lim_ft_cleanup_all_ft_sessions(tpAniSirGlobal pMac);
+void lim_fill_ft_session(tpAniSirGlobal pMac,
+ tpSirBssDescription pbssDescription,
+ tpPESession pftSessionEntry,
+ tpPESession psessionEntry);
+tSirRetStatus lim_ft_prepare_add_bss_req(tpAniSirGlobal pMac,
+ uint8_t updateEntry,
+ tpPESession pftSessionEntry,
+ tpSirBssDescription bssDescription);
+#endif /* __LIMFT_H__ */
+
+#endif /* WLAN_FEATURE_VOWIFI_11R */
diff --git a/core/mac/src/pe/include/lim_ft_defs.h b/core/mac/src/pe/include/lim_ft_defs.h
new file mode 100644
index 0000000..da4f11f
--- /dev/null
+++ b/core/mac/src/pe/include/lim_ft_defs.h
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2013-2015 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.
+ */
+
+#if defined WLAN_FEATURE_VOWIFI_11R
+/**=========================================================================
+
+ Macros and Function prototypes FT and 802.11R purposes
+
+ ========================================================================*/
+
+#ifndef __LIMFTDEFS_H__
+#define __LIMFTDEFS_H__
+
+#include <cds_api.h>
+#include "wma_if.h"
+
+/*--------------------------------------------------------------------------
+ Preprocessor definitions and constants
+ ------------------------------------------------------------------------*/
+#define SIR_MDIE_SIZE 3 /* MD ID(2 bytes), Capability(1 byte) */
+#define MAX_FTIE_SIZE 384 /* Max size limited to 384, on acct. of IW custom events */
+
+/*--------------------------------------------------------------------------
+ Type declarations
+ ------------------------------------------------------------------------*/
+/*--------------------------------------------------------------------------
+ FT Pre Auth Req SME<->PE
+ ------------------------------------------------------------------------*/
+typedef struct sSirFTPreAuthReq {
+ uint16_t messageType; /* eWNI_SME_FT_PRE_AUTH_REQ */
+ uint16_t length;
+ /*
+ * Track if response is processed for this request
+ * We expect only one response per request.
+ */
+ bool bPreAuthRspProcessed;
+ uint8_t preAuthchannelNum;
+ /* BSSID currently associated to suspend the link */
+ tSirMacAddr currbssId;
+ tSirMacAddr preAuthbssId; /* BSSID to preauth to */
+ uint16_t ft_ies_length;
+ uint8_t ft_ies[MAX_FTIE_SIZE];
+ tpSirBssDescription pbssDescription;
+} tSirFTPreAuthReq, *tpSirFTPreAuthReq;
+
+/*-------------------------------------------------------------------------
+ FT Pre Auth Rsp PE<->SME
+ ------------------------------------------------------------------------*/
+typedef struct sSirFTPreAuthRsp {
+ uint16_t messageType; /* eWNI_SME_FT_PRE_AUTH_RSP */
+ uint16_t length;
+ uint8_t smeSessionId;
+ tSirMacAddr preAuthbssId; /* BSSID to preauth to */
+ tSirRetStatus status;
+ uint16_t ft_ies_length;
+ uint8_t ft_ies[MAX_FTIE_SIZE];
+ uint16_t ric_ies_length;
+ uint8_t ric_ies[MAX_FTIE_SIZE];
+} tSirFTPreAuthRsp, *tpSirFTPreAuthRsp;
+
+/*--------------------------------------------------------------------------
+ FT Pre Auth Rsp Key SME<->PE
+ ------------------------------------------------------------------------*/
+typedef struct sSirFTUpdateKeyInfo {
+ uint16_t messageType;
+ uint16_t length;
+ uint32_t smeSessionId;
+ tSirMacAddr bssId;
+ tSirKeyMaterial keyMaterial;
+} tSirFTUpdateKeyInfo, *tpSirFTUpdateKeyInfo;
+
+/*--------------------------------------------------------------------------
+ FT Pre Auth Rsp Key SME<->PE
+ ------------------------------------------------------------------------*/
+typedef struct sSirFTPreAuthKeyInfo {
+ uint8_t extSetStaKeyParamValid; /* Ext Bss Config Msg if set */
+ /* SetStaKeyParams for ext bss msg */
+ tLimMlmSetKeysReq extSetStaKeyParam;
+} tSirFTPreAuthKeyInfo, *tpSirFTPreAuthKeyInfo;
+
+/*-------------------------------------------------------------------------
+ Global FT Information
+ ------------------------------------------------------------------------*/
+typedef struct sFTPEContext {
+ tpSirFTPreAuthReq pFTPreAuthReq; /* Saved FT Pre Auth Req */
+ tSirRetStatus ftPreAuthStatus;
+ uint16_t saved_auth_rsp_length;
+ uint8_t saved_auth_rsp[MAX_FTIE_SIZE];
+ tSirFTPreAuthKeyInfo PreAuthKeyInfo;
+ /* Items created for the new FT, session */
+ void *pAddBssReq; /* Save add bss req */
+ void *pAddStaReq; /*Save add sta req */
+ uint32_t peSessionId;
+ uint32_t smeSessionId;
+
+ /* This flag is required to indicate on which session the preauth
+ * has taken place, since the auth reponse for preauth will come
+ * for a new BSSID for which there is no session yet. This flag
+ * will be used to extract the session from the session preauth
+ * has been initiated
+ */
+ bool ftPreAuthSession;
+} tftPEContext, *tpftPEContext;
+
+#endif /* __LIMFTDEFS_H__ */
+
+#endif /* WLAN_FEATURE_VOWIFI_11R */
diff --git a/core/mac/src/pe/include/lim_global.h b/core/mac/src/pe/include/lim_global.h
new file mode 100644
index 0000000..5ddb01c
--- /dev/null
+++ b/core/mac/src/pe/include/lim_global.h
@@ -0,0 +1,670 @@
+/*
+ * Copyright (c) 2011-2015 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_global.h contains the definitions exported by
+ * LIM module.
+ * Author: Chandra Modumudi
+ * Date: 02/11/02
+ * History:-
+ * Date Modified by Modification Information
+ * --------------------------------------------------------------------
+ *
+ */
+#ifndef __LIM_GLOBAL_H
+#define __LIM_GLOBAL_H
+
+#include "wni_api.h"
+#include "sir_api.h"
+#include "sir_mac_prot_def.h"
+#include "sir_mac_prop_exts.h"
+#include "sir_common.h"
+#include "sir_debug.h"
+#include "wni_cfg.h"
+#include "csr_api.h"
+#include "sap_api.h"
+#include "dot11f.h"
+#include "wma_if.h"
+
+/* / Maximum number of scan hash table entries */
+#define LIM_MAX_NUM_OF_SCAN_RESULTS 256
+
+/* Sending Disassociate frames threshold */
+#define LIM_SEND_DISASSOC_FRAME_THRESHOLD 2
+#define LIM_HASH_MISS_TIMER_MS 10000
+
+/* Deferred Message Queue Length */
+#define MAX_DEFERRED_QUEUE_LEN 80
+
+/* Maximum number of PS - TIM's to be sent with out wakeup from STA */
+#define LIM_TIM_WAIT_COUNT_FACTOR 5
+
+/*
+ * Use this count if (LIM_TIM_WAIT_FACTOR * ListenInterval)
+ * is less than LIM_MIN_TIM_WAIT_CNT
+ */
+#define LIM_MIN_TIM_WAIT_COUNT 50
+
+#define GET_TIM_WAIT_COUNT(LIntrvl) \
+ ((LIntrvl * LIM_TIM_WAIT_COUNT_FACTOR) > LIM_MIN_TIM_WAIT_COUNT ? \
+ (LIntrvl * LIM_TIM_WAIT_COUNT_FACTOR) : LIM_MIN_TIM_WAIT_COUNT)
+
+#define IS_5G_BAND(__rfBand) ((__rfBand & 0x3) == 0x2)
+#define IS_24G_BAND(__rfBand) ((__rfBand & 0x3) == 0x1)
+
+#define LIM_MAX_CSA_IE_UPDATES (5)
+
+/* enums exported by LIM are as follows */
+
+/*System role definition */
+typedef enum eLimSystemRole {
+ eLIM_UNKNOWN_ROLE,
+ eLIM_AP_ROLE,
+ eLIM_STA_IN_IBSS_ROLE,
+ eLIM_STA_ROLE,
+ eLIM_BT_AMP_STA_ROLE,
+ eLIM_BT_AMP_AP_ROLE,
+ eLIM_P2P_DEVICE_ROLE,
+ eLIM_P2P_DEVICE_GO,
+ eLIM_P2P_DEVICE_CLIENT
+} tLimSystemRole;
+
+/*
+ * SME state definition accessible across all Sirius modules.
+ * AP only states are LIM_SME_CHANNEL_SCAN_STATE &
+ * LIM_SME_NORMAL_CHANNEL_SCAN_STATE.
+ * Note that these states may also be present in STA
+ * side too when DFS support is present for a STA in IBSS mode.
+ */
+typedef enum eLimSmeStates {
+ eLIM_SME_OFFLINE_STATE,
+ eLIM_SME_IDLE_STATE,
+ eLIM_SME_SUSPEND_STATE,
+ eLIM_SME_WT_SCAN_STATE,
+ eLIM_SME_WT_JOIN_STATE,
+ eLIM_SME_WT_AUTH_STATE,
+ eLIM_SME_WT_ASSOC_STATE,
+ eLIM_SME_WT_REASSOC_STATE,
+ eLIM_SME_WT_REASSOC_LINK_FAIL_STATE,
+ eLIM_SME_JOIN_FAILURE_STATE,
+ eLIM_SME_ASSOCIATED_STATE,
+ eLIM_SME_REASSOCIATED_STATE,
+ eLIM_SME_LINK_EST_STATE,
+ eLIM_SME_LINK_EST_WT_SCAN_STATE,
+ eLIM_SME_WT_PRE_AUTH_STATE,
+ eLIM_SME_WT_DISASSOC_STATE,
+ eLIM_SME_WT_DEAUTH_STATE,
+ eLIM_SME_WT_START_BSS_STATE,
+ eLIM_SME_WT_STOP_BSS_STATE,
+ eLIM_SME_NORMAL_STATE,
+ eLIM_SME_CHANNEL_SCAN_STATE,
+ eLIM_SME_NORMAL_CHANNEL_SCAN_STATE
+} tLimSmeStates;
+
+/*
+ * MLM state definition.
+ * While these states are present on AP too when it is
+ * STA mode, per-STA MLM state exclusive to AP is:
+ * eLIM_MLM_WT_AUTH_FRAME3.
+ */
+typedef enum eLimMlmStates {
+ eLIM_MLM_OFFLINE_STATE,
+ eLIM_MLM_IDLE_STATE,
+ eLIM_MLM_WT_PROBE_RESP_STATE,
+ eLIM_MLM_PASSIVE_SCAN_STATE,
+ eLIM_MLM_WT_JOIN_BEACON_STATE,
+ eLIM_MLM_JOINED_STATE,
+ eLIM_MLM_BSS_STARTED_STATE,
+ eLIM_MLM_WT_AUTH_FRAME2_STATE,
+ eLIM_MLM_WT_AUTH_FRAME3_STATE,
+ eLIM_MLM_WT_AUTH_FRAME4_STATE,
+ eLIM_MLM_AUTH_RSP_TIMEOUT_STATE,
+ eLIM_MLM_AUTHENTICATED_STATE,
+ eLIM_MLM_WT_ASSOC_RSP_STATE,
+ eLIM_MLM_WT_REASSOC_RSP_STATE,
+ eLIM_MLM_ASSOCIATED_STATE,
+ eLIM_MLM_REASSOCIATED_STATE,
+ eLIM_MLM_LINK_ESTABLISHED_STATE,
+ eLIM_MLM_WT_ASSOC_CNF_STATE,
+ eLIM_MLM_LEARN_STATE,
+ eLIM_MLM_WT_ADD_BSS_RSP_STATE,
+ eLIM_MLM_WT_DEL_BSS_RSP_STATE,
+ eLIM_MLM_WT_ADD_BSS_RSP_ASSOC_STATE,
+ eLIM_MLM_WT_ADD_BSS_RSP_REASSOC_STATE,
+ eLIM_MLM_WT_ADD_BSS_RSP_PREASSOC_STATE,
+ eLIM_MLM_WT_ADD_STA_RSP_STATE,
+ eLIM_MLM_WT_DEL_STA_RSP_STATE,
+ /*
+ * MLM goes to this state when LIM initiates DELETE_STA
+ * as processing of Assoc req because the entry already exists.
+ * LIM comes out of this state when DELETE_STA response from
+ * HAL is received. LIM needs to maintain this state so that ADD_STA
+ * can be issued while processing DELETE_STA response from HAL.
+ */
+ eLIM_MLM_WT_ASSOC_DEL_STA_RSP_STATE,
+ eLIM_MLM_WT_SET_BSS_KEY_STATE,
+ eLIM_MLM_WT_SET_STA_KEY_STATE,
+ eLIM_MLM_WT_SET_STA_BCASTKEY_STATE,
+ eLIM_MLM_WT_SET_MIMOPS_STATE,
+#if defined WLAN_FEATURE_VOWIFI_11R
+ eLIM_MLM_WT_ADD_BSS_RSP_FT_REASSOC_STATE,
+ eLIM_MLM_WT_FT_REASSOC_RSP_STATE,
+#endif
+ eLIM_MLM_P2P_LISTEN_STATE,
+} tLimMlmStates;
+
+/* 11h channel quiet states */
+
+/*
+ * This enum indicates in which state the device is in
+ * when it receives quiet element in beacon or probe-response.
+ * The default quiet state of the device is always INIT
+ * eLIM_QUIET_BEGIN - When Quiet period is started
+ * eLIM_QUIET_CHANGED - When Quiet period is updated
+ * eLIM_QUIET_RUNNING - Between two successive Quiet updates
+ * eLIM_QUIET_END - When quiet period ends
+ */
+typedef enum eLimQuietStates {
+ eLIM_QUIET_INIT,
+ eLIM_QUIET_BEGIN,
+ eLIM_QUIET_CHANGED,
+ eLIM_QUIET_RUNNING,
+ eLIM_QUIET_END
+} tLimQuietStates;
+
+/* 11h channel switch states */
+
+/*
+ * This enum indicates in which state the channel-swith
+ * is presently operating.
+ * eLIM_11H_CHANSW_INIT - Default state
+ * eLIM_11H_CHANSW_RUNNING - When channel switch is running
+ * eLIM_11H_CHANSW_END - After channel switch is complete
+ */
+typedef enum eLimDot11hChanSwStates {
+ eLIM_11H_CHANSW_INIT,
+ eLIM_11H_CHANSW_RUNNING,
+ eLIM_11H_CHANSW_END
+} tLimDot11hChanSwStates;
+
+
+/* WLAN_SUSPEND_LINK Related */
+typedef void (*SUSPEND_RESUME_LINK_CALLBACK)(tpAniSirGlobal pMac,
+ CDF_STATUS status,
+ uint32_t *data);
+
+/* LIM to HAL SCAN Management Message Interface states */
+typedef enum eLimHalScanState {
+ eLIM_HAL_IDLE_SCAN_STATE,
+ eLIM_HAL_INIT_SCAN_WAIT_STATE,
+ eLIM_HAL_START_SCAN_WAIT_STATE,
+ eLIM_HAL_END_SCAN_WAIT_STATE,
+ eLIM_HAL_FINISH_SCAN_WAIT_STATE,
+ eLIM_HAL_INIT_LEARN_WAIT_STATE,
+ eLIM_HAL_START_LEARN_WAIT_STATE,
+ eLIM_HAL_END_LEARN_WAIT_STATE,
+ eLIM_HAL_FINISH_LEARN_WAIT_STATE,
+ eLIM_HAL_SCANNING_STATE,
+/* WLAN_SUSPEND_LINK Related */
+ eLIM_HAL_SUSPEND_LINK_WAIT_STATE,
+ eLIM_HAL_SUSPEND_LINK_STATE,
+ eLIM_HAL_RESUME_LINK_WAIT_STATE,
+/* end WLAN_SUSPEND_LINK Related */
+} tLimLimHalScanState;
+
+/* MLM Req/Cnf structure definitions */
+typedef struct sLimMlmAuthReq {
+ tSirMacAddr peerMacAddr;
+ tAniAuthType authType;
+ uint32_t authFailureTimeout;
+ uint8_t sessionId;
+} tLimMlmAuthReq, *tpLimMlmAuthReq;
+
+typedef struct sLimMlmJoinReq {
+ uint32_t joinFailureTimeout;
+ tSirMacRateSet operationalRateSet;
+ uint8_t sessionId;
+ tSirBssDescription bssDescription;
+} tLimMlmJoinReq, *tpLimMlmJoinReq;
+
+typedef struct sLimMlmScanReq {
+ tSirBssType bssType;
+ tSirMacAddr bssId;
+ tSirMacSSid ssId[SIR_SCAN_MAX_NUM_SSID];
+ tSirScanType scanType;
+ uint32_t minChannelTime;
+ uint32_t maxChannelTime;
+ uint32_t dot11mode;
+ /* Number of SSIDs to scan(send Probe request) */
+ uint8_t numSsid;
+
+ bool p2pSearch;
+ uint16_t uIEFieldLen;
+ uint16_t uIEFieldOffset;
+
+ uint8_t sessionId;
+ /* channelList MUST be the last field of this structure */
+ tSirChannelList channelList;
+ /*-----------------------------
+ tLimMlmScanReq....
+ -----------------------------
+ uIEFiledLen
+ -----------------------------
+ uIEFiledOffset ----+
+ ----------------------------- |
+ channelList.numChannels |
+ ----------------------------- |
+ ... variable size up to |
+ channelNumber[numChannels-1] |
+ This can be zero, if |
+ numChannel is zero. |
+ ----------------------------- <--+
+ ... variable size uIEFiled
+ up to uIEFieldLen (can be 0)
+ -----------------------------*/
+} tLimMlmScanReq, *tpLimMlmScanReq;
+
+typedef struct tLimScanResultNode tLimScanResultNode;
+struct tLimScanResultNode {
+ tLimScanResultNode *next;
+ tSirBssDescription bssDescription;
+};
+
+#ifdef FEATURE_OEM_DATA_SUPPORT
+
+#ifndef OEM_DATA_REQ_SIZE
+#define OEM_DATA_REQ_SIZE 280
+#endif
+#ifndef OEM_DATA_RSP_SIZE
+#define OEM_DATA_RSP_SIZE 1724
+#endif
+
+/* OEM Data related structure definitions */
+typedef struct sLimMlmOemDataReq {
+ tSirMacAddr selfMacAddr;
+ uint8_t oemDataReq[OEM_DATA_REQ_SIZE];
+} tLimMlmOemDataReq, *tpLimMlmOemDataReq;
+
+typedef struct sLimMlmOemDataRsp {
+ uint8_t oemDataRsp[OEM_DATA_RSP_SIZE];
+} tLimMlmOemDataRsp, *tpLimMlmOemDataRsp;
+#endif
+
+/* Pre-authentication structure definition */
+typedef struct tLimPreAuthNode {
+ struct tLimPreAuthNode *next;
+ tSirMacAddr peerMacAddr;
+ tAniAuthType authType;
+ tLimMlmStates mlmState;
+ uint8_t authNodeIdx;
+ uint8_t challengeText[SIR_MAC_AUTH_CHALLENGE_LENGTH];
+ uint8_t fTimerStarted:1;
+ uint8_t fSeen:1;
+ uint8_t fFree:1;
+ uint8_t rsvd:5;
+ TX_TIMER timer;
+ uint16_t seq_num;
+ v_TIME_t timestamp;
+} tLimPreAuthNode, *tpLimPreAuthNode;
+
+/* Pre-authentication table definition */
+typedef struct tLimPreAuthTable {
+ uint32_t numEntry;
+ tpLimPreAuthNode pTable;
+} tLimPreAuthTable, *tpLimPreAuthTable;
+
+/* / Per STA context structure definition */
+typedef struct sLimMlmStaContext {
+ tLimMlmStates mlmState;
+ tAniAuthType authType;
+ uint16_t listenInterval;
+ tSirMacCapabilityInfo capabilityInfo;
+ tSirMacPropRateSet propRateSet;
+ tSirMacReasonCodes disassocReason;
+ uint16_t cleanupTrigger;
+
+ tSirResultCodes resultCode;
+ uint16_t protStatusCode;
+
+ uint8_t subType:1; /* Indicates ASSOC (0) or REASSOC (1) */
+ uint8_t updateContext:1;
+ uint8_t schClean:1;
+ /* 802.11n HT Capability in Station: Enabled 1 or DIsabled 0 */
+ uint8_t htCapability:1;
+#ifdef WLAN_FEATURE_11AC
+ uint8_t vhtCapability:1;
+#endif
+} tLimMlmStaContext, *tpLimMlmStaContext;
+
+/* Structure definition to hold deferred messages queue parameters */
+typedef struct sLimDeferredMsgQParams {
+ tSirMsgQ deferredQueue[MAX_DEFERRED_QUEUE_LEN];
+ uint16_t size;
+ uint16_t read;
+ uint16_t write;
+} tLimDeferredMsgQParams, *tpLimDeferredMsgQParams;
+
+typedef struct sCfgProtection {
+ uint32_t overlapFromlla:1;
+ uint32_t overlapFromllb:1;
+ uint32_t overlapFromllg:1;
+ uint32_t overlapHt20:1;
+ uint32_t overlapNonGf:1;
+ uint32_t overlapLsigTxop:1;
+ uint32_t overlapRifs:1;
+ uint32_t overlapOBSS:1; /* added for obss */
+ uint32_t fromlla:1;
+ uint32_t fromllb:1;
+ uint32_t fromllg:1;
+ uint32_t ht20:1;
+ uint32_t nonGf:1;
+ uint32_t lsigTxop:1;
+ uint32_t rifs:1;
+ uint32_t obss:1; /* added for Obss */
+} tCfgProtection, *tpCfgProtection;
+
+typedef enum eLimProtStaCacheType {
+ eLIM_PROT_STA_CACHE_TYPE_INVALID,
+ eLIM_PROT_STA_CACHE_TYPE_llB,
+ eLIM_PROT_STA_CACHE_TYPE_llG,
+ eLIM_PROT_STA_CACHE_TYPE_HT20
+} tLimProtStaCacheType;
+
+typedef struct sCacheParams {
+ uint8_t active;
+ tSirMacAddr addr;
+ tLimProtStaCacheType protStaCacheType;
+
+} tCacheParams, *tpCacheParams;
+
+#define LIM_PROT_STA_OVERLAP_CACHE_SIZE HAL_NUM_ASSOC_STA
+#define LIM_PROT_STA_CACHE_SIZE HAL_NUM_ASSOC_STA
+
+typedef struct sLimProtStaParams {
+ uint8_t numSta;
+ uint8_t protectionEnabled;
+} tLimProtStaParams, *tpLimProtStaParams;
+
+typedef struct sLimNoShortParams {
+ uint8_t numNonShortPreambleSta;
+ tCacheParams staNoShortCache[LIM_PROT_STA_CACHE_SIZE];
+} tLimNoShortParams, *tpLimNoShortParams;
+
+typedef struct sLimNoShortSlotParams {
+ uint8_t numNonShortSlotSta;
+ tCacheParams staNoShortSlotCache[LIM_PROT_STA_CACHE_SIZE];
+} tLimNoShortSlotParams, *tpLimNoShortSlotParams;
+
+typedef struct tLimIbssPeerNode tLimIbssPeerNode;
+struct tLimIbssPeerNode {
+ tLimIbssPeerNode *next;
+ tSirMacAddr peerMacAddr;
+ uint8_t extendedRatesPresent:1;
+ uint8_t edcaPresent:1;
+ uint8_t wmeEdcaPresent:1;
+ uint8_t wmeInfoPresent:1;
+ uint8_t htCapable:1;
+ uint8_t vhtCapable:1;
+ uint8_t rsvd:2;
+ uint8_t htSecondaryChannelOffset;
+ tSirMacCapabilityInfo capabilityInfo;
+ tSirMacRateSet supportedRates;
+ tSirMacRateSet extendedRates;
+ uint8_t supportedMCSSet[SIZE_OF_SUPPORTED_MCS_SET];
+ tSirMacEdcaParamSetIE edcaParams;
+ uint8_t erpIePresent;
+
+ /* HT Capabilities of IBSS Peer */
+ uint8_t htGreenfield;
+ uint8_t htShortGI40Mhz;
+ uint8_t htShortGI20Mhz;
+
+ /* DSSS/CCK at 40 MHz: Enabled 1 or Disabled */
+ uint8_t htDsssCckRate40MHzSupport;
+
+ /* MIMO Power Save */
+ tSirMacHTMIMOPowerSaveState htMIMOPSState;
+
+ /* */
+ /* A-MPDU Density */
+ /* 000 - No restriction */
+ /* 001 - 1/8 usec */
+ /* 010 - 1/4 usec */
+ /* 011 - 1/2 usec */
+ /* 100 - 1 usec */
+ /* 101 - 2 usec */
+ /* 110 - 4 usec */
+ /* 111 - 8 usec */
+ /* */
+ uint8_t htAMpduDensity;
+
+ /* Maximum Rx A-MPDU factor */
+ uint8_t htMaxRxAMpduFactor;
+
+ /* Set to 0 for 3839 octets */
+ /* Set to 1 for 7935 octets */
+ uint8_t htMaxAmsduLength;
+
+ /* */
+ /* Recommended Tx Width Set */
+ /* 0 - use 20 MHz channel (control channel) */
+ /* 1 - use 40 Mhz channel */
+ /* */
+ uint8_t htSupportedChannelWidthSet;
+
+ uint8_t htLdpcCapable;
+
+ uint8_t beaconHBCount;
+ uint8_t heartbeatFailure;
+
+ uint8_t *beacon; /* Hold beacon to be sent to HDD/CSR */
+ uint16_t beaconLen;
+
+#ifdef WLAN_FEATURE_11AC
+ tDot11fIEVHTCaps VHTCaps;
+ uint8_t vhtSupportedChannelWidthSet;
+ uint8_t vhtBeamFormerCapable;
+#endif
+ /*
+ * Peer Atim Info
+ */
+ uint8_t atimIePresent;
+ uint32_t peerAtimWindowLength;
+};
+
+/* Enums used for channel switching. */
+typedef enum eLimChannelSwitchState {
+ eLIM_CHANNEL_SWITCH_IDLE,
+ eLIM_CHANNEL_SWITCH_PRIMARY_ONLY,
+ eLIM_CHANNEL_SWITCH_PRIMARY_AND_SECONDARY
+} tLimChannelSwitchState;
+
+/* Channel Switch Info */
+typedef struct sLimChannelSwitchInfo {
+ tLimChannelSwitchState state;
+ uint8_t primaryChannel;
+ uint8_t ch_center_freq_seg0;
+ uint8_t ch_center_freq_seg1;
+ phy_ch_width ch_width;
+ int8_t switchCount;
+ uint32_t switchTimeoutValue;
+ uint8_t switchMode;
+} tLimChannelSwitchInfo, *tpLimChannelSwitchInfo;
+
+#ifdef WLAN_FEATURE_11AC
+typedef struct sLimOperatingModeInfo {
+ uint8_t present;
+ uint8_t chanWidth:2;
+ uint8_t reserved:2;
+ uint8_t rxNSS:3;
+ uint8_t rxNSSType:1;
+} tLimOperatingModeInfo, *tpLimOperatingModeInfo;
+#endif
+
+typedef struct sLimWiderBWChannelSwitch {
+ uint8_t newChanWidth;
+ uint8_t newCenterChanFreq0;
+ uint8_t newCenterChanFreq1;
+} tLimWiderBWChannelSwitchInfo, *tpLimWiderBWChannelSwitchInfo;
+
+/* Enums used when stopping the Tx. */
+typedef enum eLimQuietTxMode {
+ /* Stop/resume transmission of all stations,Uses the global flag */
+ eLIM_TX_ALL = 0,
+ /*
+ * Stops/resumes the transmission of specific stations identified
+ * by staId.
+ */
+ eLIM_TX_STA,
+ /* Stops/resumes the transmission of all the packets in BSS */
+ eLIM_TX_BSS,
+ /*
+ * Stops/resumes the transmission of all packets except beacons in BSS
+ * This is used when radar is detected in the current operating channel.
+ * Beacon has to be sent to notify the stations associated about the
+ * scheduled channel switch
+ */
+ eLIM_TX_BSS_BUT_BEACON
+} tLimQuietTxMode;
+
+typedef enum eLimControlTx {
+ eLIM_RESUME_TX = 0,
+ eLIM_STOP_TX
+} tLimControlTx;
+
+/* -------------------------------------------------------------------- */
+
+typedef struct sLimTspecInfo {
+ /* 0==free, else used */
+ uint8_t inuse;
+ /* index in list */
+ uint8_t idx;
+ tSirMacAddr staAddr;
+ uint16_t assocId;
+ tSirMacTspecIE tspec;
+ /* number of Tclas elements */
+ uint8_t numTclas;
+ tSirTclasInfo tclasInfo[SIR_MAC_TCLASIE_MAXNUM];
+ uint8_t tclasProc;
+ /* tclassProc is valid only if this is set to 1. */
+ uint8_t tclasProcPresent:1;
+} cdf_packed tLimTspecInfo, *tpLimTspecInfo;
+
+typedef struct sLimAdmitPolicyInfo {
+ /* admit control policy type */
+ uint8_t type;
+ /* oversubscription factor : 0 means nothing is allowed */
+ uint8_t bw_factor;
+ /* valid only when 'type' is set BW_FACTOR */
+} tLimAdmitPolicyInfo, *tpLimAdmitPolicyInfo;
+
+typedef enum eLimWscEnrollState {
+ eLIM_WSC_ENROLL_NOOP,
+ eLIM_WSC_ENROLL_BEGIN,
+ eLIM_WSC_ENROLL_IN_PROGRESS,
+ eLIM_WSC_ENROLL_END
+} tLimWscEnrollState;
+
+#define WSC_PASSWD_ID_PUSH_BUTTON (0x0004)
+
+typedef struct sLimWscIeInfo {
+ bool apSetupLocked;
+ bool selectedRegistrar;
+ uint16_t selectedRegistrarConfigMethods;
+ tLimWscEnrollState wscEnrollmentState;
+ tLimWscEnrollState probeRespWscEnrollmentState;
+ uint8_t reqType;
+ uint8_t respType;
+} tLimWscIeInfo, *tpLimWscIeInfo;
+
+/* maximum number of tspec's supported */
+#define LIM_NUM_TSPEC_MAX 15
+
+/* structure to hold all 11h specific data */
+typedef struct sLimSpecMgmtInfo {
+ tLimQuietStates quietState;
+ uint32_t quietCount;
+ /* This is in units of system TICKS */
+ uint32_t quietDuration;
+ /* This is in units of TU, for over the air transmission */
+ uint32_t quietDuration_TU;
+ /* After this timeout, actual quiet starts */
+ uint32_t quietTimeoutValue;
+ /* Used on AP, if quiet is enabled during learning */
+ bool fQuietEnabled;
+ tLimDot11hChanSwStates dot11hChanSwState;
+ /* Radar detected in cur oper chan on AP */
+ bool fRadarDetCurOperChan;
+ /* Whether radar interrupt has been configured */
+ bool fRadarIntrConfigured;
+} tLimSpecMgmtInfo, *tpLimSpecMgmtInfo;
+
+#ifdef FEATURE_WLAN_TDLS
+/*
+ * Peer info needed for TDLS setup..
+ */
+typedef struct tLimTDLSPeerSta {
+ struct tLimTDLSPeerSta *next;
+ uint8_t dialog;
+ tSirMacAddr peerMac;
+ tSirMacCapabilityInfo capabilityInfo;
+ tSirMacRateSet supportedRates;
+ tSirMacRateSet extendedRates;
+ tSirMacQosCapabilityStaIE qosCaps;
+ tSirMacEdcaParamSetIE edcaParams;
+ uint8_t mcsSet[SIZE_OF_SUPPORTED_MCS_SET];
+ uint8_t tdls_bIsResponder;
+ /* HT Capabilties */
+ tDot11fIEHTCaps tdlsPeerHTCaps;
+ tDot11fIEExtCap tdlsPeerExtCaps;
+ uint8_t tdls_flags;
+ uint8_t tdls_link_state;
+ uint8_t tdls_prev_link_state;
+ uint8_t tdls_sessionId;
+ uint8_t ExtRatesPresent;
+ TX_TIMER gLimTdlsLinkSetupRspTimeoutTimer;
+ TX_TIMER gLimTdlsLinkSetupCnfTimeoutTimer;
+} tLimTdlsLinkSetupPeer, *tpLimTdlsLinkSetupPeer;
+
+typedef struct tLimTdlsLinkSetupInfo {
+ tLimTdlsLinkSetupPeer *tdlsLinkSetupList;
+ uint8_t num_tdls_peers;
+ uint8_t tdls_flags;
+ uint8_t tdls_state;
+ uint8_t tdls_prev_state;
+} tLimTdlsLinkSetupInfo, *tpLimTdlsLinkSetupInfo;
+
+typedef enum tdlsLinkMode {
+ TDLS_LINK_MODE_BG,
+ TDLS_LINK_MODE_N,
+ TDLS_LINK_MODE_AC,
+ TDLS_LINK_MODE_NONE
+} eLimTdlsLinkMode;
+#endif /* FEATURE_WLAN_TDLS */
+
+#endif
diff --git a/core/mac/src/pe/include/lim_session.h b/core/mac/src/pe/include/lim_session.h
new file mode 100644
index 0000000..f027fa0
--- /dev/null
+++ b/core/mac/src/pe/include/lim_session.h
@@ -0,0 +1,612 @@
+/*
+ * Copyright (c) 2012-2015 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.
+ */
+
+#if !defined(__LIM_SESSION_H)
+#define __LIM_SESSION_H
+
+/**=========================================================================
+
+ \file lim_session.h
+
+ \brief prototype for lim Session related APIs
+
+ \author Sunit Bhatia
+
+ ========================================================================*/
+
+/* Powersave Offload Implementation */
+typedef enum ePowersaveState {
+ PMM_FULL_POWER,
+ PMM_POWER_SAVE
+} tPowersaveState;
+
+/* Master Structure: This will be part of PE Session Entry */
+typedef struct sPowersaveoffloadInfo {
+ tPowersaveState psstate;
+ uint8_t bcnmiss;
+} tPowersaveoffloadInfo, tpPowersaveoffloadInfo;
+
+#ifdef WLAN_FEATURE_11W
+typedef struct tagComebackTimerInfo {
+ tpAniSirGlobal pMac;
+ uint8_t sessionID;
+ tLimMlmStates limPrevMlmState; /* Previous MLM State */
+ tLimSmeStates limMlmState; /* MLM State */
+} tComebackTimerInfo;
+#endif /* WLAN_FEATURE_11W */
+/*--------------------------------------------------------------------------
+ Include Files
+ ------------------------------------------------------------------------*/
+
+/*--------------------------------------------------------------------------
+ Preprocessor definitions and constants
+ ------------------------------------------------------------------------*/
+#define NUM_WEP_KEYS 4
+
+/* Maximum allowable size of a beacon frame */
+#define SCH_MAX_BEACON_SIZE 512
+
+#define SCH_MAX_PROBE_RESP_SIZE 512
+#define SCH_PROTECTION_RESET_TIME 4000
+
+/*--------------------------------------------------------------------------
+ Type declarations
+ ------------------------------------------------------------------------*/
+typedef struct {
+ tSirMacBeaconInterval beaconInterval;
+ uint8_t fShortPreamble;
+ uint8_t llaCoexist;
+ uint8_t llbCoexist;
+ uint8_t llgCoexist;
+ uint8_t ht20Coexist;
+ uint8_t llnNonGFCoexist;
+ uint8_t fRIFSMode;
+ uint8_t fLsigTXOPProtectionFullSupport;
+ uint8_t gHTObssMode;
+} tBeaconParams, *tpBeaconParams;
+
+typedef struct sPESession /* Added to Support BT-AMP */
+{
+ /* To check session table is in use or free */
+ uint8_t available;
+ uint16_t peSessionId;
+ uint8_t smeSessionId;
+ uint16_t transactionId;
+
+ /* In AP role: BSSID and selfMacAddr will be the same. */
+ /* In STA role: they will be different */
+ tSirMacAddr bssId;
+ tSirMacAddr selfMacAddr;
+ tSirMacSSid ssId;
+ uint8_t bssIdx;
+ uint8_t valid;
+ tLimMlmStates limMlmState; /* MLM State */
+ tLimMlmStates limPrevMlmState; /* Previous MLM State */
+ tLimSmeStates limSmeState; /* SME State */
+ tLimSmeStates limPrevSmeState; /* Previous SME State */
+ tLimSystemRole limSystemRole;
+ tSirBssType bssType;
+ uint8_t operMode; /* AP - 0; STA - 1 ; */
+ tSirNwType nwType;
+ tpSirSmeStartBssReq pLimStartBssReq; /* handle to smestart bss req */
+ tpSirSmeJoinReq pLimJoinReq; /* handle to sme join req */
+ tpSirSmeJoinReq pLimReAssocReq; /* handle to sme reassoc req */
+ tpLimMlmJoinReq pLimMlmJoinReq; /* handle to MLM join Req */
+#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
+ void *pLimMlmReassocRetryReq; /* keep reasoc req for retry */
+#endif
+ void *pLimMlmReassocReq; /* handle to MLM reassoc Req */
+ uint16_t channelChangeReasonCode;
+ uint8_t dot11mode;
+ uint8_t htCapability;
+ /* Supported Channel Width Set: 0-20MHz 1 - 40MHz */
+ uint8_t htSupportedChannelWidthSet;
+ /* Recommended Tx Width Set
+ * 0 - use 20 MHz channel (control channel)
+ * 1 - use channel width enabled under Supported Channel Width Set
+ */
+ uint8_t htRecommendedTxWidthSet;
+ /* Identifies the 40 MHz extension channel */
+ ePhyChanBondState htSecondaryChannelOffset;
+ tSirRFBand limRFBand;
+ uint8_t limIbssActive; /* TO SUPPORT CONCURRENCY */
+
+ /* These global varibales moved to session Table to support BT-AMP : Oct 9th review */
+ tAniAuthType limCurrentAuthType;
+ uint16_t limCurrentBssCaps;
+ uint8_t limCurrentBssQosCaps;
+ uint16_t limCurrentBssPropCap;
+ uint8_t limSentCapsChangeNtf;
+ uint16_t limAID;
+
+ /* Parameters For Reassociation */
+ tSirMacAddr limReAssocbssId;
+ tSirMacChanNum limReassocChannelId;
+ /* CB paramaters required/duplicated for Reassoc since re-assoc mantains its own params in lim */
+ uint8_t reAssocHtSupportedChannelWidthSet;
+ uint8_t reAssocHtRecommendedTxWidthSet;
+ ePhyChanBondState reAssocHtSecondaryChannelOffset;
+ tSirMacSSid limReassocSSID;
+ uint16_t limReassocBssCaps;
+ uint8_t limReassocBssQosCaps;
+ uint16_t limReassocBssPropCap;
+
+ /* Assoc or ReAssoc Response Data/Frame */
+ void *limAssocResponseData;
+
+ /** BSS Table parameters **/
+
+ /*
+ * staId: Start BSS: this is the Sta Id for the BSS.
+ * Join: this is the selfStaId
+ * In both cases above, the peer STA ID wll be stored in dph hash table.
+ */
+ uint16_t staId;
+ uint16_t statypeForBss; /* to know session is for PEER or SELF */
+ uint8_t shortSlotTimeSupported;
+ uint8_t dtimPeriod;
+ tSirMacRateSet rateSet;
+ tSirMacRateSet extRateSet;
+ tSirMacHTOperatingMode htOperMode;
+ uint8_t currentOperChannel;
+ uint8_t currentReqChannel;
+ uint8_t LimRxedBeaconCntDuringHB;
+
+ /* Time stamp of the last beacon received from the BSS to which STA is connected. */
+ uint64_t lastBeaconTimeStamp;
+ /* RX Beacon count for the current BSS to which STA is connected. */
+ uint32_t currentBssBeaconCnt;
+ uint8_t lastBeaconDtimCount;
+ uint8_t lastBeaconDtimPeriod;
+
+ uint32_t bcnLen;
+ uint8_t *beacon; /* Used to store last beacon / probe response before assoc. */
+
+ uint32_t assocReqLen;
+ uint8_t *assocReq; /* Used to store association request frame sent out while associating. */
+
+ uint32_t assocRspLen;
+ uint8_t *assocRsp; /* Used to store association response received while associating */
+ tAniSirDph dph;
+ void **parsedAssocReq; /* Used to store parsed assoc req from various requesting station */
+#ifdef WLAN_FEATURE_VOWIFI_11R
+ uint32_t RICDataLen; /* Used to store the Ric data received in the assoc response */
+ uint8_t *ricData;
+#endif
+#ifdef FEATURE_WLAN_ESE
+ uint32_t tspecLen; /* Used to store the TSPEC IEs received in the assoc response */
+ uint8_t *tspecIes;
+#endif
+ uint32_t encryptType;
+
+ bool bTkipCntrMeasActive; /* Used to keep record of TKIP counter measures start/stop */
+
+ uint8_t gLimProtectionControl; /* used for 11n protection */
+
+ uint8_t gHTNonGFDevicesPresent;
+
+ /* protection related config cache */
+ tCfgProtection cfgProtection;
+
+ /* Number of legacy STAs associated */
+ tLimProtStaParams gLim11bParams;
+
+ /* Number of 11A STAs associated */
+ tLimProtStaParams gLim11aParams;
+
+ /* Number of non-ht non-legacy STAs associated */
+ tLimProtStaParams gLim11gParams;
+
+ /* Number of nonGf STA associated */
+ tLimProtStaParams gLimNonGfParams;
+
+ /* Number of HT 20 STAs associated */
+ tLimProtStaParams gLimHt20Params;
+
+ /* Number of Lsig Txop not supported STAs associated */
+ tLimProtStaParams gLimLsigTxopParams;
+
+ /* Number of STAs that do not support short preamble */
+ tLimNoShortParams gLimNoShortParams;
+
+ /* Number of STAs that do not support short slot time */
+ tLimNoShortSlotParams gLimNoShortSlotParams;
+
+ /* OLBC parameters */
+ tLimProtStaParams gLimOlbcParams;
+
+ /* OLBC parameters */
+ tLimProtStaParams gLimOverlap11gParams;
+
+ tLimProtStaParams gLimOverlap11aParams;
+ tLimProtStaParams gLimOverlapHt20Params;
+ tLimProtStaParams gLimOverlapNonGfParams;
+
+ /* cache for each overlap */
+ tCacheParams protStaCache[LIM_PROT_STA_CACHE_SIZE];
+
+ uint8_t privacy;
+ tAniAuthType authType;
+ tSirKeyMaterial WEPKeyMaterial[NUM_WEP_KEYS];
+
+ tDot11fIERSN gStartBssRSNIe;
+ tDot11fIEWPA gStartBssWPAIe;
+ tSirAPWPSIEs APWPSIEs;
+ uint8_t apUapsdEnable;
+ tSirWPSPBCSession *pAPWPSPBCSession;
+ uint32_t DefProbeRspIeBitmap[8];
+ uint32_t proxyProbeRspEn;
+ tDot11fProbeResponse probeRespFrame;
+ uint8_t ssidHidden;
+ bool fwdWPSPBCProbeReq;
+ uint8_t wps_state;
+
+ uint8_t limQosEnabled:1; /* 11E */
+ uint8_t limWmeEnabled:1; /* WME */
+ uint8_t limWsmEnabled:1; /* WSM */
+ uint8_t limHcfEnabled:1;
+ uint8_t lim11dEnabled:1;
+#ifdef WLAN_FEATURE_11W
+ uint8_t limRmfEnabled:1; /* 11W */
+#endif
+ uint32_t lim11hEnable;
+
+ tPowerdBm maxTxPower; /* MIN (Regulatory and local power constraint) */
+ tCDF_CON_MODE pePersona;
+#if defined WLAN_FEATURE_VOWIFI
+ tPowerdBm txMgmtPower;
+#endif
+
+#ifdef WLAN_FEATURE_VOWIFI_11R
+ tAniBool is11Rconnection;
+#endif
+
+#ifdef FEATURE_WLAN_ESE
+ tAniBool isESEconnection;
+ tEsePEContext eseContext;
+#endif
+#if defined WLAN_FEATURE_VOWIFI_11R || defined FEATURE_WLAN_ESE || defined(FEATURE_WLAN_LFR)
+ tAniBool isFastTransitionEnabled;
+#endif
+#ifdef FEATURE_WLAN_LFR
+ tAniBool isFastRoamIniFeatureEnabled;
+#endif
+ tSirNoAParam p2pNoA;
+ tSirP2PNoaAttr p2pGoPsUpdate;
+ uint32_t defaultAuthFailureTimeout;
+ tSirP2PNoaStart p2pGoPsNoaStartInd;
+
+ /* EDCA QoS parameters
+ * gLimEdcaParams - These EDCA parameters are used locally on AP or STA.
+ * If STA, then these are values taken from the Assoc Rsp when associating,
+ * or Beacons/Probe Response after association. If AP, then these are
+ * values originally set locally on AP.
+ *
+ * gLimEdcaParamsBC - These EDCA parameters are use by AP to broadcast
+ * to other STATIONs in the BSS.
+ *
+ * gLimEdcaParamsActive: These EDCA parameters are what's actively being
+ * used on station. Specific AC values may be downgraded depending on
+ * admission control for that particular AC.
+ */
+ tSirMacEdcaParamRecord gLimEdcaParams[MAX_NUM_AC]; /* used locally */
+ tSirMacEdcaParamRecord gLimEdcaParamsBC[MAX_NUM_AC]; /* used for broadcast */
+ tSirMacEdcaParamRecord gLimEdcaParamsActive[MAX_NUM_AC];
+
+ uint8_t gLimEdcaParamSetCount;
+
+ tBeaconParams beaconParams;
+ uint8_t vhtCapability;
+ uint8_t vhtTxChannelWidthSet;
+ tLimOperatingModeInfo gLimOperatingMode;
+ uint8_t vhtCapabilityPresentInBeacon;
+ uint8_t ch_center_freq_seg0;
+ phy_ch_width ch_width;
+ uint8_t ch_center_freq_seg1;
+ uint8_t txBFIniFeatureEnabled;
+ uint8_t txMuBformee;
+ uint8_t enableVhtpAid;
+ uint8_t enableVhtGid;
+ uint8_t enable_su_tx_bformer;
+ tLimWiderBWChannelSwitchInfo gLimWiderBWChannelSwitch;
+ uint8_t enableAmpduPs;
+ uint8_t enableHtSmps;
+ uint8_t htSmpsvalue;
+ uint8_t spectrumMgtEnabled;
+ /* *********************11H related**************************** */
+ tLimSpecMgmtInfo gLimSpecMgmt;
+ /* CB Primary/Secondary Channel Switch Info */
+ tLimChannelSwitchInfo gLimChannelSwitch;
+ /* *********************End 11H related**************************** */
+
+ /*Flag to Track Status/Indicate HBFailure on this session */
+ bool LimHBFailureStatus;
+ uint32_t gLimPhyMode;
+ uint8_t amsduSupportedInBA;
+ uint8_t txLdpcIniFeatureEnabled;
+ /**
+ * Following is the place holder for free peer index pool.
+ * A non-zero value indicates that peer index is available
+ * for assignment.
+ */
+ uint8_t *gpLimPeerIdxpool;
+ uint8_t freePeerIdxHead;
+ uint8_t freePeerIdxTail;
+ uint16_t gLimNumOfCurrentSTAs;
+#ifdef FEATURE_WLAN_TDLS
+ uint32_t peerAIDBitmap[2];
+ bool tdls_prohibited;
+ bool tdls_chan_swit_prohibited;
+#endif
+ bool fWaitForProbeRsp;
+ bool fIgnoreCapsChange;
+ bool fDeauthReceived;
+#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM
+ int8_t rssi;
+#endif
+ uint8_t isAmsduSupportInAMPDU;
+ uint8_t isCoalesingInIBSSAllowed;
+
+ tSirHTConfig htConfig;
+
+ /*
+ * Place holder for StartBssReq message
+ * received by SME state machine
+ */
+ uint8_t gLimCurrentBssUapsd;
+
+ /* Used on STA, this is a static UAPSD mask setting
+ * derived from SME_JOIN_REQ and SME_REASSOC_REQ. If a
+ * particular AC bit is set, it means the AC is both
+ * trigger enabled and delivery enabled.
+ */
+ uint8_t gUapsdPerAcBitmask;
+
+ /* Used on STA, this is a dynamic UPASD mask setting
+ * derived from AddTS Rsp and DelTS frame. If a
+ * particular AC bit is set, it means AC is trigger
+ * enabled.
+ */
+ uint8_t gUapsdPerAcTriggerEnableMask;
+
+ /* Used on STA, dynamic UPASD mask setting
+ * derived from AddTS Rsp and DelTs frame. If
+ * a particular AC bit is set, it means AC is
+ * delivery enabled.
+ */
+ uint8_t gUapsdPerAcDeliveryEnableMask;
+
+ /* Flag to skip CSA IE processing when CSA
+ * offload is enabled.
+ */
+ uint8_t csaOffloadEnable;
+
+ /* Used on STA for AC downgrade. This is a dynamic mask
+ * setting which keep tracks of ACs being admitted.
+ * If bit is set to 0: That partiular AC is not admitted
+ * If bit is set to 1: That particular AC is admitted
+ */
+ uint8_t gAcAdmitMask[SIR_MAC_DIRECTION_DIRECT];
+
+ /* Power Save Off load Parameters */
+ tPowersaveoffloadInfo pmmOffloadInfo;
+ /* SMPS mode */
+ uint8_t smpsMode;
+
+ uint8_t chainMask;
+
+ /* Flag to indicate Chan Sw announcement is required */
+ uint8_t dfsIncludeChanSwIe;
+
+ /* Flag to indicate Chan Wrapper Element is required */
+ uint8_t dfsIncludeChanWrapperIe;
+
+#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH
+ uint8_t cc_switch_mode;
+#endif
+
+ bool isCiscoVendorAP;
+
+ tSirAddIeParams addIeParams;
+
+ uint8_t *pSchProbeRspTemplate;
+ /* Beginning portion of the beacon frame to be written to TFP */
+ uint8_t *pSchBeaconFrameBegin;
+ /* Trailing portion of the beacon frame to be written to TFP */
+ uint8_t *pSchBeaconFrameEnd;
+ /* Size of the beginning portion */
+ uint16_t schBeaconOffsetBegin;
+ /* Size of the trailing portion */
+ uint16_t schBeaconOffsetEnd;
+ bool isOSENConnection;
+ /* DSCP to UP mapping for HS 2.0 */
+ tSirQosMapSet QosMapSet;
+
+#ifdef WLAN_FEATURE_ROAM_OFFLOAD
+ bool bRoamSynchInProgress;
+#endif
+
+#if defined WLAN_FEATURE_VOWIFI_11R
+ /* Fast Transition (FT) */
+ tftPEContext ftPEContext;
+#endif
+ bool isNonRoamReassoc;
+#ifdef WLAN_FEATURE_11W
+ cdf_mc_timer_t pmfComebackTimer;
+ tComebackTimerInfo pmfComebackTimerInfo;
+#endif /* WLAN_FEATURE_11W */
+ uint8_t is_key_installed;
+ /* timer for reseting protection fileds at regular intervals */
+ cdf_mc_timer_t protection_fields_reset_timer;
+ void *mac_ctx;
+ /*
+ * variable to store state of various protection struct like
+ * gLimOlbcParams, gLimOverlap11gParams, gLimOverlapHt20Params etc
+ */
+ uint16_t old_protection_state;
+ tSirMacAddr prev_ap_bssid;
+#ifdef FEATURE_AP_MCC_CH_AVOIDANCE
+ /* tells if Q2Q IE, from another MDM device in AP MCC mode was recvd */
+ bool sap_advertise_avoid_ch_ie;
+#endif /* FEATURE_AP_MCC_CH_AVOIDANCE */
+#ifdef FEATURE_WLAN_ESE
+ uint8_t is_ese_version_ie_present;
+#endif
+ uint8_t sap_dot11mc;
+ bool is_vendor_specific_vhtcaps;
+ uint8_t vendor_specific_vht_ie_type;
+ uint8_t vendor_specific_vht_ie_sub_type;
+ /* flag to indicate country code in beacon */
+ uint8_t country_info_present;
+ uint8_t nss;
+} tPESession, *tpPESession;
+
+/*-------------------------------------------------------------------------
+ Function declarations and documenation
+ ------------------------------------------------------------------------*/
+
+/**
+ * pe_create_session() - creates a new PE session given the BSSID
+ *
+ * @pMac: pointer to global adapter context
+ * @bssid: BSSID of the new session
+ * @sessionId: session ID is returned here, if session is created.
+ * @numSta: number of stations
+ * @bssType: bss type of new session to do conditional memory allocation.
+ *
+ * This function returns the session context and the session ID if the session
+ * corresponding to the passed BSSID is found in the PE session table.
+ *
+ * Return: ptr to the session context or NULL if session can not be created.
+ */
+tpPESession pe_create_session(tpAniSirGlobal pMac,
+ uint8_t *bssid,
+ uint8_t *sessionId,
+ uint16_t numSta, tSirBssType bssType);
+
+/**
+ * pe_find_session_by_bssid() - looks up the PE session given the BSSID.
+ *
+ * @pMac: pointer to global adapter context
+ * @bssid: BSSID of the new session
+ * @sessionId: session ID is returned here, if session is created.
+ *
+ * This function returns the session context and the session ID if the session
+ * corresponding to the given BSSID is found in the PE session table.
+ *
+ * Return: pointer to the session context or NULL if session is not found.
+ */
+tpPESession pe_find_session_by_bssid(tpAniSirGlobal pMac, uint8_t *bssid,
+ uint8_t *sessionId);
+
+/**
+ * pe_find_session_by_bss_idx() - looks up the PE session given the bssIdx.
+ *
+ * @pMac: pointer to global adapter context
+ * @bssIdx: bss index of the session
+ *
+ * This function returns the session context if the session
+ * corresponding to the given bssIdx is found in the PE session table.
+ *
+ * Return: pointer to the session context or NULL if session is not found.
+ */
+tpPESession pe_find_session_by_bss_idx(tpAniSirGlobal pMac, uint8_t bssIdx);
+
+/**
+ * pe_find_session_by_peer_sta() - looks up the PE session given the Peer
+ * Station Address.
+ *
+ * @pMac: pointer to global adapter context
+ * @sa: Peer STA Address of the session
+ * @sessionId: session ID is returned here, if session is found.
+ *
+ * This function returns the session context and the session ID if the session
+ * corresponding to the given destination address is found in the PE session
+ * table.
+ *
+ * Return: pointer to the session context or NULL if session is not found.
+ */
+tpPESession pe_find_session_by_peer_sta(tpAniSirGlobal pMac, uint8_t *sa,
+ uint8_t *sessionId);
+
+/**
+ * pe_find_session_by_session_id() - looks up the PE session given the session
+ * ID.
+ *
+ * @pMac: pointer to global adapter context
+ * @sessionId: session ID for which session context needs to be looked up.
+ *
+ * This function returns the session context if the session corresponding to
+ * the given session ID is found in the PE session table.
+ *
+ * Return: pointer to the session context or NULL if session is not found.
+ */
+tpPESession pe_find_session_by_session_id(tpAniSirGlobal pMac,
+ uint8_t sessionId);
+
+/**
+ * pe_find_session_by_bssid() - looks up the PE session given staid.
+ *
+ * @pMac: pointer to global adapter context
+ * @staid: StaId of the session
+ * @sessionId: session ID is returned here, if session is found.
+ *
+ * This function returns the session context and the session ID if the session
+ * corresponding to the given StaId is found in the PE session table.
+ *
+ * Return: pointer to the session context or NULL if session is not found.
+ */
+tpPESession pe_find_session_by_sta_id(tpAniSirGlobal pMac, uint8_t staid,
+ uint8_t *sessionId);
+
+/**
+ * pe_delete_session() - deletes the PE session given the session ID.
+ *
+ * @pMac: pointer to global adapter context
+ * @sessionId: session ID to delete.
+ *
+ * Return: void
+ */
+void pe_delete_session(tpAniSirGlobal pMac, tpPESession psessionEntry);
+
+
+#ifdef FEATURE_AP_MCC_CH_AVOIDANCE
+/**
+ * pe_find_session_by_sme_session_id() - looks up the PE session for given sme
+ * session id
+ * @mac_ctx: pointer to global adapter context
+ * @sme_session_id: sme session id
+ *
+ * looks up the PE session for given sme session id
+ *
+ * Return: pe session entry for given sme session if found else NULL
+ */
+tpPESession pe_find_session_by_sme_session_id(tpAniSirGlobal mac_ctx,
+ uint8_t sme_session_id);
+#endif /* FEATURE_AP_MCC_CH_AVOIDANCE */
+uint8_t pe_get_active_session_count(tpAniSirGlobal mac_ctx);
+#endif /* #if !defined( __LIM_SESSION_H ) */
diff --git a/core/mac/src/pe/include/lim_trace.h b/core/mac/src/pe/include/lim_trace.h
new file mode 100644
index 0000000..494edc8
--- /dev/null
+++ b/core/mac/src/pe/include/lim_trace.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2013-2015 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.
+ */
+
+/**=========================================================================
+
+ * \file lim_trace.h
+
+ * \brief definition for trace related APIs
+
+ * \author Sunit Bhatia
+
+ ========================================================================*/
+
+#ifndef __LIM_TRACE_H
+#define __LIM_TRACE_H
+
+#include "lim_global.h"
+#include "mac_trace.h"
+#include "cdf_trace.h"
+#ifdef LIM_TRACE_RECORD
+
+#define LIM_TRACE_GET_SSN(data) (((data) >> 16) & 0xff)
+#define LIM_TRACE_GET_SUBTYPE(data) (data & 0xff)
+#define LIM_TRACE_GET_DEFERRED(data) (data & 0x80000000)
+#define LIM_TRACE_GET_DEFRD_OR_DROPPED(data) (data & 0xc0000000)
+
+#define LIM_MSG_PROCESSED 0
+#define LIM_MSG_DEFERRED 1
+#define LIM_MSG_DROPPED 2
+
+#define LIM_TRACE_MAKE_RXMGMT(type, ssn) \
+ ((ssn << 16) | (type))
+#define LIM_TRACE_MAKE_RXMSG(msg, action) \
+ ((msg) | (action << 30))
+
+enum {
+ TRACE_CODE_MLM_STATE,
+ TRACE_CODE_SME_STATE,
+ TRACE_CODE_TX_MGMT,
+ TRACE_CODE_RX_MGMT,
+ TRACE_CODE_RX_MGMT_TSF,
+ TRACE_CODE_TX_COMPLETE,
+ TRACE_CODE_TX_SME_MSG,
+ TRACE_CODE_RX_SME_MSG,
+ TRACE_CODE_TX_WMA_MSG,
+ TRACE_CODE_RX_WMA_MSG,
+ TRACE_CODE_TX_LIM_MSG,
+ TRACE_CODE_RX_LIM_MSG,
+ TRACE_CODE_TX_CFG_MSG,
+ TRACE_CODE_RX_CFG_MSG,
+ TRACE_CODE_RX_MGMT_DROP,
+
+ TRACE_CODE_TIMER_ACTIVATE,
+ TRACE_CODE_TIMER_DEACTIVATE,
+ TRACE_CODE_INFO_LOG
+};
+
+void lim_trace_init(tpAniSirGlobal pMac);
+void limTraceReset(tpAniSirGlobal pMac);
+void limTraceUpdateMgmtStat(tpAniSirGlobal pMac, uint8_t subtype);
+void lim_trace_dumpMgmtStat(tpAniSirGlobal pMac, uint8_t subtype);
+uint8_t *lim_trace_get_mlm_state_string(uint32_t mlmState);
+uint8_t *lim_trace_get_sme_state_string(uint32_t smeState);
+void lim_trace_dump(tpAniSirGlobal pMac, tp_cdf_trace_record pRecord,
+ uint16_t recIndex);
+void mac_trace_msg_tx(tpAniSirGlobal pMac, uint8_t session, uint32_t data);
+void mac_trace_msg_rx(tpAniSirGlobal pMac, uint8_t session, uint32_t data);
+
+void mac_trace_msg_rx_new(tpAniSirGlobal pMac, uint8_t module, uint8_t session,
+ uint32_t data);
+void mac_trace_msg_tx_new(tpAniSirGlobal pMac, uint8_t module, uint8_t session,
+ uint32_t data);
+#endif /* endof LIM_TRACE_RECORD MACRO */
+
+#endif
diff --git a/core/mac/src/pe/include/rrm_api.h b/core/mac/src/pe/include/rrm_api.h
new file mode 100644
index 0000000..05466c0
--- /dev/null
+++ b/core/mac/src/pe/include/rrm_api.h
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2011-2012, 2014 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.
+ */
+
+/**=========================================================================
+
+ \file rrm_api.h
+
+ \brief RRM APIs
+
+ ========================================================================*/
+
+/* $Header$ */
+
+#ifndef __RRM_API_H__
+#define __RRM_API_H__
+
+#define RRM_MIN_TX_PWR_CAP 13
+#define RRM_MAX_TX_PWR_CAP 19
+
+#define RRM_BCN_RPT_NO_BSS_INFO 0
+#define RRM_BCN_RPT_MIN_RPT 1
+
+uint8_t rrm_get_min_of_max_tx_power(tpAniSirGlobal pMac, tPowerdBm regMax,
+ tPowerdBm apTxPower);
+
+extern tSirRetStatus rrm_initialize(tpAniSirGlobal pMac);
+
+extern tSirRetStatus rrm_cleanup(tpAniSirGlobal pMac);
+
+extern tSirRetStatus rrm_process_link_measurement_request(tpAniSirGlobal pMac,
+ uint8_t *pRxPacketInfo,
+ tDot11fLinkMeasurementRequest
+ *pLinkReq,
+ tpPESession
+ pSessionEntry);
+
+extern tSirRetStatus rrm_process_radio_measurement_request(tpAniSirGlobal pMac,
+ tSirMacAddr peer,
+ tDot11fRadioMeasurementRequest
+ *pRRMReq,
+ tpPESession
+ pSessionEntry);
+
+extern tSirRetStatus rrm_process_neighbor_report_response(tpAniSirGlobal pMac,
+ tDot11fNeighborReportResponse
+ *pNeighborRep,
+ tpPESession
+ pSessionEntry);
+
+extern void rrm_process_message(tpAniSirGlobal pMac, tpSirMsgQ pMsg);
+
+extern tSirRetStatus rrm_send_set_max_tx_power_req(tpAniSirGlobal pMac,
+ tPowerdBm txPower,
+ tpPESession pSessionEntry);
+
+extern tPowerdBm rrm_get_mgmt_tx_power(tpAniSirGlobal pMac,
+ tpPESession pSessionEntry);
+
+extern void rrm_cache_mgmt_tx_power(tpAniSirGlobal pMac,
+ tPowerdBm txPower, tpPESession pSessionEntry);
+
+extern tpRRMCaps rrm_get_capabilities(tpAniSirGlobal pMac,
+ tpPESession pSessionEntry);
+
+extern void rrm_update_config(tpAniSirGlobal pMac, tpPESession pSessionEntry);
+
+extern void rrm_get_start_tsf(tpAniSirGlobal pMac, uint32_t *pStartTSF);
+
+extern void rrm_update_start_tsf(tpAniSirGlobal pMac, uint32_t startTSF[2]);
+
+extern tSirRetStatus rrm_set_max_tx_power_rsp(tpAniSirGlobal pMac,
+ tpSirMsgQ limMsgQ);
+
+extern tSirRetStatus
+rrm_process_neighbor_report_req(tpAniSirGlobal pMac,
+ tpSirNeighborReportReqInd pNeighborReq);
+extern tSirRetStatus
+rrm_process_beacon_report_xmit(tpAniSirGlobal pMac,
+ tpSirBeaconReportXmitInd pBcnReport);
+#endif
diff --git a/core/mac/src/pe/include/rrm_global.h b/core/mac/src/pe/include/rrm_global.h
new file mode 100644
index 0000000..053848d
--- /dev/null
+++ b/core/mac/src/pe/include/rrm_global.h
@@ -0,0 +1,228 @@
+/*
+ * Copyright (c) 2011-2012, 2014-2015 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.
+ */
+
+#if !defined(__RRMGLOBAL_H)
+#define __RRMGLOBAL_H
+
+/**=========================================================================
+
+ \file rrm_global.h
+
+ \brief Definitions for SME APIs
+
+ ========================================================================*/
+
+typedef enum eRrmRetStatus {
+ eRRM_SUCCESS,
+ eRRM_INCAPABLE,
+ eRRM_REFUSED,
+ eRRM_FAILURE
+} tRrmRetStatus;
+
+typedef enum eRrmMsgReqSource {
+ eRRM_MSG_SOURCE_LEGACY_ESE = 1, /* legacy ese */
+ eRRM_MSG_SOURCE_11K = 2, /* 11k */
+ eRRM_MSG_SOURCE_ESE_UPLOAD = 3, /* ese upload approach */
+} tRrmMsgReqSource;
+
+typedef struct sSirChannelInfo {
+ uint8_t regulatoryClass;
+ uint8_t channelNum;
+} tSirChannelInfo, *tpSirChannelInfo;
+
+typedef struct sSirBeaconReportReqInd {
+ uint16_t messageType; /* eWNI_SME_BEACON_REPORT_REQ_IND */
+ uint16_t length;
+ tSirMacAddr bssId;
+ uint16_t measurementDuration[SIR_ESE_MAX_MEAS_IE_REQS]; /* ms */
+ uint16_t randomizationInterval; /* ms */
+ tSirChannelInfo channelInfo;
+ /* 0: wildcard */
+ tSirMacAddr macaddrBssid;
+ /* 0:Passive, 1: Active, 2: table mode */
+ uint8_t fMeasurementtype[SIR_ESE_MAX_MEAS_IE_REQS];
+ tAniSSID ssId; /* May be wilcard. */
+ uint16_t uDialogToken;
+ tSirChannelList channelList; /* From AP channel report. */
+ tRrmMsgReqSource msgSource;
+} tSirBeaconReportReqInd, *tpSirBeaconReportReqInd;
+
+typedef struct sSirBeaconReportXmitInd {
+ uint16_t messageType; /* eWNI_SME_BEACON_REPORT_RESP_XMIT_IND */
+ uint16_t length;
+ tSirMacAddr bssId;
+ uint16_t uDialogToken;
+ uint8_t fMeasureDone;
+ uint16_t duration;
+ uint8_t regClass;
+ uint8_t numBssDesc;
+ tpSirBssDescription pBssDescription[SIR_BCN_REPORT_MAX_BSS_DESC];
+} tSirBeaconReportXmitInd, *tpSirBeaconReportXmitInd;
+
+typedef struct sSirNeighborReportReqInd {
+ /* eWNI_SME_NEIGHBOR_REPORT_REQ_IND */
+ uint16_t messageType;
+ uint16_t length;
+ /* For the session. */
+ tSirMacAddr bssId;
+ /* true - dont include SSID in the request. */
+ uint16_t noSSID;
+ /* false include the SSID. It may be null (wildcard) */
+ tSirMacSSid ucSSID;
+} tSirNeighborReportReqInd, *tpSirNeighborReportReqInd;
+
+typedef struct sSirNeighborBssDescription {
+ uint16_t length;
+ tSirMacAddr bssId;
+ uint8_t regClass;
+ uint8_t channel;
+ uint8_t phyType;
+ union sSirNeighborBssidInfo {
+ struct _rrmInfo {
+ /* see IEEE 802.11k Table 7-43a */
+ uint32_t fApPreauthReachable:2;
+ uint32_t fSameSecurityMode:1;
+ uint32_t fSameAuthenticator:1;
+ /* see IEEE 802.11k Table 7-95d */
+ uint32_t fCapSpectrumMeasurement:1;
+ uint32_t fCapQos:1;
+ uint32_t fCapApsd:1;
+ uint32_t fCapRadioMeasurement:1;
+ uint32_t fCapDelayedBlockAck:1;
+ uint32_t fCapImmediateBlockAck:1;
+ uint32_t fMobilityDomain:1;
+ uint32_t reserved:21;
+ } rrmInfo;
+ struct _eseInfo {
+ uint32_t channelBand:8;
+ uint32_t minRecvSigPower:8;
+ uint32_t apTxPower:8;
+ uint32_t roamHysteresis:8;
+ uint32_t adaptScanThres:8;
+
+ uint32_t transitionTime:8;
+ uint32_t tsfOffset:16;
+
+ uint32_t beaconInterval:16;
+ uint32_t reserved:16;
+ } eseInfo;
+ } bssidInfo;
+
+ /* Optional sub IEs....ignoring for now. */
+} tSirNeighborBssDescription, *tpSirNeighborBssDescripton;
+
+typedef struct sSirNeighborReportInd {
+ uint16_t messageType; /* eWNI_SME_NEIGHBOR_REPORT_IND */
+ uint16_t length;
+ uint8_t sessionId;
+ uint16_t numNeighborReports;
+ tSirMacAddr bssId; /* For the session. */
+ tSirNeighborBssDescription sNeighborBssDescription[1];
+} tSirNeighborReportInd, *tpSirNeighborReportInd;
+
+typedef struct sRRMBeaconReportRequestedIes {
+ uint8_t num;
+ uint8_t *pElementIds;
+} tRRMBeaconReportRequestedIes, *tpRRMBeaconReportRequestedIes;
+
+/* Reporting detail defines. */
+/* Reference - IEEE Std 802.11k-2008 section 7.3.2.21.6 Table 7-29h */
+#define BEACON_REPORTING_DETAIL_NO_FF_IE 0
+#define BEACON_REPORTING_DETAIL_ALL_FF_REQ_IE 1
+#define BEACON_REPORTING_DETAIL_ALL_FF_IE 2
+
+typedef struct sRRMReq {
+ uint8_t dialog_token; /* In action frame; */
+ uint8_t token; /* Within individual request; */
+ uint8_t type;
+ union {
+ struct {
+ uint8_t reportingDetail;
+ tRRMBeaconReportRequestedIes reqIes;
+ } Beacon;
+ } request;
+ uint8_t sendEmptyBcnRpt;
+} tRRMReq, *tpRRMReq;
+
+typedef struct sRRMCaps {
+ uint8_t LinkMeasurement:1;
+ uint8_t NeighborRpt:1;
+ uint8_t parallel:1;
+ uint8_t repeated:1;
+ uint8_t BeaconPassive:1;
+ uint8_t BeaconActive:1;
+ uint8_t BeaconTable:1;
+ uint8_t BeaconRepCond:1;
+ uint8_t FrameMeasurement:1;
+ uint8_t ChannelLoad:1;
+ uint8_t NoiseHistogram:1;
+ uint8_t statistics:1;
+ uint8_t LCIMeasurement:1;
+ uint8_t LCIAzimuth:1;
+ uint8_t TCMCapability:1;
+ uint8_t triggeredTCM:1;
+ uint8_t APChanReport:1;
+ uint8_t RRMMIBEnabled:1;
+ uint8_t operatingChanMax:3;
+ uint8_t nonOperatingChanMax:3;
+ uint8_t MeasurementPilot:3;
+ uint8_t MeasurementPilotEnabled:1;
+ uint8_t NeighborTSFOffset:1;
+ uint8_t RCPIMeasurement:1;
+ uint8_t RSNIMeasurement:1;
+ uint8_t BssAvgAccessDelay:1;
+ uint8_t BSSAvailAdmission:1;
+ uint8_t AntennaInformation:1;
+ uint8_t fine_time_meas_rpt:1;
+ uint8_t lci_capability:1;
+ uint8_t reserved:4;
+} tRRMCaps, *tpRRMCaps;
+
+typedef struct sRrmPEContext {
+ uint8_t rrmEnable;
+ /*
+ * Used during scan/measurement to store the start TSF.
+ * this is not used directly in beacon reports.
+ */
+ uint32_t startTSF[2];
+ /*
+ * This value is stored into bssdescription and beacon report
+ * gets it from bss decsription.
+ */
+ tRRMCaps rrmEnabledCaps;
+ tPowerdBm txMgmtPower;
+ /* Dialog token for the request initiated from station. */
+ uint8_t DialogToken;
+ tpRRMReq pCurrentReq;
+} tRrmPEContext, *tpRrmPEContext;
+
+/* 2008 11k spec reference: 18.4.8.5 RCPI Measurement */
+#define RCPI_LOW_RSSI_VALUE (-110)
+#define RCPI_MAX_VALUE (220)
+#define CALCULATE_RCPI(rssi) (((rssi) + 110) * 2)
+
+#endif /* #if defined __RRMGLOBAL_H */
diff --git a/core/mac/src/pe/include/sch_api.h b/core/mac/src/pe/include/sch_api.h
new file mode 100644
index 0000000..04db805
--- /dev/null
+++ b/core/mac/src/pe/include/sch_api.h
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2011-2015 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.
+ */
+
+/*
+ *
+ * Author: Sandesh Goel
+ * Date: 02/25/02
+ * History:-
+ * Date Modified by Modification Information
+ * --------------------------------------------------------------------
+ *
+ */
+
+#ifndef __SCH_API_H__
+#define __SCH_API_H__
+
+#include "sir_common.h"
+#include "sir_mac_prot_def.h"
+
+#include "ani_global.h"
+
+/* / Send start scan response message */
+extern void sch_send_start_scan_rsp(tpAniSirGlobal pMac);
+
+/* update only the broadcast qos params */
+extern void sch_qos_update_broadcast(tpAniSirGlobal pMac,
+ tpPESession psessionEntry);
+
+/* fill in the default local edca parameter into gLimEdcaParams[] */
+extern void sch_set_default_edca_params(tpAniSirGlobal pMac, tpPESession psessionE);
+
+/* update only local qos params */
+extern void sch_qos_update_local(tpAniSirGlobal pMac, tpPESession psessionEntry);
+
+/* update the edca profile parameters */
+extern void sch_edca_profile_update(tpAniSirGlobal pMac,
+ tpPESession psessionEntry);
+
+/* / Set the fixed fields in a beacon frame */
+extern tSirRetStatus sch_set_fixed_beacon_fields(tpAniSirGlobal pMac,
+ tpPESession psessionEntry);
+
+/* / Initialize globals */
+extern void sch_init_globals(tpAniSirGlobal pMac);
+
+/* / Initialize CF Poll template */
+extern void sch_initializeCfPollTemplate(tpAniSirGlobal pMac);
+
+/* / Initialize CF End template */
+extern void sch_initializeCfEndTemplate(tpAniSirGlobal pMac);
+
+/* / Process the scheduler messages */
+extern void sch_process_message(tpAniSirGlobal pMac, tpSirMsgQ pSchMsg);
+
+/* / The beacon Indication handler function */
+extern void sch_process_pre_beacon_ind(tpAniSirGlobal pMac, tpSirMsgQ limMsg);
+
+/* / Post a message to the scheduler message queue */
+extern tSirRetStatus sch_post_message(tpAniSirGlobal pMac, tpSirMsgQ pMsg);
+
+extern void sch_beacon_process(tpAniSirGlobal pMac, uint8_t *pRxPacketInfo,
+ tpPESession psessionEntry);
+extern tSirRetStatus sch_beacon_edca_process(tpAniSirGlobal pMac,
+ tSirMacEdcaParamSetIE *edca,
+ tpPESession psessionEntry);
+
+void sch_generate_tim(tpAniSirGlobal, uint8_t **, uint16_t *, uint8_t);
+#define SCH_RR_TIMEOUT (SCH_RR_TIMEOUT_MS / SYS_TICK_DUR_MS)
+
+void sch_set_beacon_interval(tpAniSirGlobal pMac, tpPESession psessionEntry);
+
+tSirRetStatus sch_send_beacon_req(tpAniSirGlobal, uint8_t *, uint16_t,
+ tpPESession psessionEntry);
+
+tSirRetStatus lim_update_probe_rsp_template_ie_bitmap_beacon1(tpAniSirGlobal,
+ tDot11fBeacon1 *,
+ tpPESession
+ psessionEntry);
+void lim_update_probe_rsp_template_ie_bitmap_beacon2(tpAniSirGlobal, tDot11fBeacon2 *,
+ uint32_t *,
+ tDot11fProbeResponse *);
+void set_probe_rsp_ie_bitmap(uint32_t *, uint32_t);
+uint32_t lim_send_probe_rsp_template_to_hal(tpAniSirGlobal, tpPESession, uint32_t *);
+
+int sch_gen_timing_advert_frame(tpAniSirGlobal pMac, tSirMacAddr self_addr,
+ uint8_t **buf, uint32_t *timestamp_offset, uint32_t *time_value_offset);
+
+#endif
diff --git a/core/mac/src/pe/include/sch_global.h b/core/mac/src/pe/include/sch_global.h
new file mode 100644
index 0000000..baebe98
--- /dev/null
+++ b/core/mac/src/pe/include/sch_global.h
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 2013-2014 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.
+ */
+
+/*
+ *
+ *
+ * Author: Sandesh Goel
+ * Date: 02/25/02
+ * History:-
+ * Date Modified by Modification Information
+ * --------------------------------------------------------------------
+ *
+ */
+
+#ifndef __SCH_GLOBAL_H__
+#define __SCH_GLOBAL_H__
+
+#include "sir_mac_prop_exts.h"
+#include "lim_global.h"
+
+#include "parser_api.h"
+
+#ifdef WLAN_SOFTAP_VSTA_FEATURE
+#define TIM_IE_SIZE 0xB
+#else
+#define TIM_IE_SIZE 0x7
+#endif
+
+/* ----------------------- Beacon processing ------------------------ */
+
+/* / Beacon structure */
+#define tSchBeaconStruct tSirProbeRespBeacon
+#define tpSchBeaconStruct struct sSirProbeRespBeacon *
+
+/* ------------------------------------------------------------------- */
+
+/* ****************** MISC defs ********************************* */
+
+struct schMisc {
+ uint16_t gSchBeaconInterval;
+
+ /* / Current CFP count */
+ uint8_t gSchCFPCount;
+
+ /* / CFP Duration remaining */
+ uint8_t gSchCFPDurRemaining;
+
+ /* / CFP Maximum Duration */
+ uint8_t gSchCFPMaxDuration;
+
+ /* / Current DTIM count */
+ uint8_t gSchDTIMCount;
+
+ /* / Whether we have initiated a CFP or not */
+ uint8_t gSchCFPInitiated;
+
+ /* / Whether we have initiated a CFB or not */
+ uint8_t gSchCFBInitiated;
+
+ /* / CFP is enabled and AP is configured as HCF */
+ uint8_t gSchCFPEnabled;
+
+ /* / CFB is enabled and AP is configured as HCF */
+ uint8_t gSchCFBEnabled;
+
+ /* --------- STA ONLY state ----------- */
+
+ /* / Indicates whether RR timer is running or not */
+ uint8_t rrTimer[8];
+
+ /* / Indicates the remaining RR timeout value if the RR timer is running */
+ uint16_t rrTimeout[8];
+
+ /* / Number of RRs transmitted */
+ uint16_t numRR[8];
+ uint16_t numRRtimeouts[8];
+
+ /* / flag to indicate that beacon template has been updated */
+ uint8_t fBeaconChanged;
+
+ uint16_t p2pIeOffset;
+
+};
+
+/* ****************** MISC defs ********************************* */
+
+typedef struct schStaWaitList {
+ uint16_t staId;
+ uint16_t count;
+} tStaWaitList, *tpStaWaitList;
+
+/* / Global SCH structure */
+typedef struct sAniSirSch {
+ /* / The scheduler object */
+ struct schMisc schObject;
+
+ /* schQoSClass unsolicited; */
+
+ /* / Whether HCF is enabled or not */
+ uint8_t gSchHcfEnabled;
+
+ /* / Whether scan is requested by LIM or not */
+ uint8_t gSchScanRequested;
+
+ /* / Whether scan request is received by SCH or not */
+ uint8_t gSchScanReqRcvd;
+
+ /* / Debug flag to disable beacon generation */
+ uint32_t gSchGenBeacon;
+
+#define SCH_MAX_ARR 100
+ uint32_t gSchBeaconsWritten;
+ uint32_t gSchBeaconsSent;
+ uint32_t gSchBBXportRcvCnt;
+ uint32_t gSchRRRcvCnt, qosNullCnt;
+ uint32_t gSchBcnRcvCnt;
+ uint32_t gSchUnknownRcvCnt;
+
+ uint32_t gSchBcnParseErrorCnt;
+ uint32_t gSchBcnIgnored;
+
+ uint32_t numPoll, numData, numCorrupt;
+ uint32_t numBogusInt, numTxAct0;
+
+#define SCH_MAX_NUM_SCH 21
+ uint32_t lastBeaconLength;
+ uint16_t rrTimeout;
+ uint32_t pollPeriod;
+ uint32_t multipleSched;
+ uint32_t pollFeedbackHist[8];
+ uint32_t dataFeedbackHist[8];
+ uint32_t maxPollTimeouts;
+ uint32_t checkCfbFlagStuck;
+
+ /* / Sta Wait list */
+ tpStaWaitList pStaWaitList;
+
+ /* / Pointer to next available entry in sta wait list */
+ uint16_t staWaitListIn;
+ /* / Pointer to first waiting sta in sta wait list */
+ uint16_t staWaitListOut;
+ /* / Total number of waiting STAs in sta wait list */
+ uint16_t staWaitListCount;
+ /* / Total number of schedules to be waited */
+ uint16_t staWaitListTotalWait;
+
+ /* / Number of entries in DPH activity queue that were ignored */
+ uint32_t ignoreDph;
+
+} tAniSirSch, *tpAniSirSch;
+
+#endif
diff --git a/core/mac/src/pe/include/wmm_apsd.h b/core/mac/src/pe/include/wmm_apsd.h
new file mode 100644
index 0000000..9b5d5d4
--- /dev/null
+++ b/core/mac/src/pe/include/wmm_apsd.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2013-2014 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.
+ */
+
+#ifndef __WMMAPSD_H__
+#define __WMMAPSD_H__
+
+#include "ani_global.h"
+
+/* UAPSD Flag for each AC (WMM spec 2.2.1) */
+#define LIM_UAPSD_BITOFFSET_ACVO 0
+#define LIM_UAPSD_BITOFFSET_ACVI 1
+#define LIM_UAPSD_BITOFFSET_ACBK 2
+#define LIM_UAPSD_BITOFFSET_ACBE 3
+
+#define LIM_UAPSD_FLAG_ACVO (1 << LIM_UAPSD_BITOFFSET_ACVO)
+#define LIM_UAPSD_FLAG_ACVI (1 << LIM_UAPSD_BITOFFSET_ACVI)
+#define LIM_UAPSD_FLAG_ACBK (1 << LIM_UAPSD_BITOFFSET_ACBK)
+#define LIM_UAPSD_FLAG_ACBE (1 << LIM_UAPSD_BITOFFSET_ACBE)
+
+#define LIM_UAPSD_GET(ac, mask) (((mask) & (LIM_UAPSD_FLAG_ ## ac)) >> LIM_UAPSD_BITOFFSET_ ## ac)
+
+/* Definition for setting/clearing Uapsd Mask */
+#define SET_UAPSD_MASK 1
+#define CLEAR_UAPSD_MASK 0
+
+#endif /* __WMMAPSD_H__ */
diff --git a/core/mac/src/pe/lim/lim_admit_control.c b/core/mac/src/pe/lim/lim_admit_control.c
new file mode 100644
index 0000000..b217c40
--- /dev/null
+++ b/core/mac/src/pe/lim/lim_admit_control.c
@@ -0,0 +1,1140 @@
+/*
+ * Copyright (c) 2011-2014 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 contains TSPEC and STA admit control related functions
+ * NOTE: applies only to AP builds
+ *
+ * Author: Sandesh Goel
+ * Date: 02/25/02
+ * History:-
+ * Date Modified by Modification Information
+ * --------------------------------------------------------------------
+ *
+ */
+#include "lim_debug.h"
+#include "sys_def.h"
+#include "lim_api.h"
+#include "cfg_api.h" /* wlan_cfg_get_int() */
+#include "lim_trace.h"
+#include "lim_send_sme_rsp_messages.h"
+#include "lim_types.h"
+
+#define ADMIT_CONTROL_LOGLEVEL LOG1
+#define ADMIT_CONTROL_POLICY_LOGLEVEL LOG1
+
+/* total available bandwidth in bps in each phy mode
+ * these should be defined in hal or dph - replace these later
+ */
+#define LIM_TOTAL_BW_11A 54000000
+#define LIM_MIN_BW_11A 6000000
+#define LIM_TOTAL_BW_11B 11000000
+#define LIM_MIN_BW_11B 1000000
+#define LIM_TOTAL_BW_11G LIM_TOTAL_BW_11A
+#define LIM_MIN_BW_11G LIM_MIN_BW_11B
+
+/* conversion factors */
+#define LIM_CONVERT_SIZE_BITS(numBytes) ((numBytes) * 8)
+#define LIM_CONVERT_RATE_MBPS(rate) ((rate)/1000000)
+
+/* ------------------------------------------------------------------------------ */
+/* local protos */
+
+static tSirRetStatus
+lim_calculate_svc_int(tpAniSirGlobal, tSirMacTspecIE *, uint32_t *);
+static tSirRetStatus
+lim_validate_tspec_edca(tpAniSirGlobal, tSirMacTspecIE *, tpPESession);
+static tSirRetStatus
+lim_validate_tspec(tpAniSirGlobal, tSirMacTspecIE *, tpPESession);
+static void
+lim_compute_mean_bw_used(tpAniSirGlobal, uint32_t *, uint32_t, tpLimTspecInfo,
+ tpPESession);
+static void lim_get_available_bw(tpAniSirGlobal, uint32_t *, uint32_t *, uint32_t,
+ uint32_t);
+static tSirRetStatus lim_admit_policy_oversubscription(tpAniSirGlobal,
+ tSirMacTspecIE *,
+ tpLimAdmitPolicyInfo,
+ tpLimTspecInfo,
+ tpPESession);
+static tSirRetStatus lim_tspec_find_by_sta_addr(tpAniSirGlobal, uint8_t *,
+ tSirMacTspecIE *, tpLimTspecInfo,
+ tpLimTspecInfo *);
+static tSirRetStatus lim_validate_access_policy(tpAniSirGlobal, uint8_t, uint16_t,
+ tpPESession);
+
+/** -------------------------------------------------------------
+ \fn lim_calculate_svc_int
+ \brief TSPEC validation and servcie interval determination
+ \param tpAniSirGlobal pMac
+ \param tSirMacTspecIE *pTspec
+ \param uint32_t *pSvcInt
+ \return eSirRetStatus - status of the comparison
+ -------------------------------------------------------------*/
+
+static tSirRetStatus
+lim_calculate_svc_int(tpAniSirGlobal pMac,
+ tSirMacTspecIE *pTspec, uint32_t *pSvcInt)
+{
+ uint32_t msduSz, dataRate;
+ *pSvcInt = 0;
+
+ /* if a service interval is already specified, we are done */
+ if ((pTspec->minSvcInterval != 0) || (pTspec->maxSvcInterval != 0)) {
+ *pSvcInt = (pTspec->maxSvcInterval != 0)
+ ? pTspec->maxSvcInterval : pTspec->minSvcInterval;
+ return eSIR_SUCCESS;
+ }
+
+ /* Masking off the fixed bits according to definition of MSDU size
+ * in IEEE 802.11-2007 spec (section 7.3.2.30). Nominal MSDU size
+ * is defined as: Bit[0:14]=Size, Bit[15]=Fixed
+ */
+ if (pTspec->nomMsduSz != 0)
+ msduSz = (pTspec->nomMsduSz & 0x7fff);
+ else if (pTspec->maxMsduSz != 0)
+ msduSz = pTspec->maxMsduSz;
+ else {
+ PELOGE(lim_log(pMac, LOGE, FL("MsduSize not specified"));)
+ return eSIR_FAILURE;
+ }
+
+ /* need to calculate a reasonable service interval
+ * this is simply the msduSz/meanDataRate
+ */
+ if (pTspec->meanDataRate != 0)
+ dataRate = pTspec->meanDataRate;
+ else if (pTspec->peakDataRate != 0)
+ dataRate = pTspec->peakDataRate;
+ else if (pTspec->minDataRate != 0)
+ dataRate = pTspec->minDataRate;
+ else {
+ PELOGE(lim_log(pMac, LOGE, FL("DataRate not specified"));)
+ return eSIR_FAILURE;
+ }
+
+ *pSvcInt =
+ LIM_CONVERT_SIZE_BITS(msduSz) / LIM_CONVERT_RATE_MBPS(dataRate);
+ return eSIR_FAILURE;
+}
+
+/**
+ * lim_validate_tspec_edca() - Validate the parameters
+ * @mac_ctx: Global MAC context
+ * @tspec: Pointer to the TSPEC
+ * @session_entry: Session Entry
+ *
+ * validate the parameters in the edca tspec
+ * mandatory fields are derived from 11e Annex I (Table I.1)
+ *
+ * Return: Status
+ **/
+static tSirRetStatus
+lim_validate_tspec_edca(tpAniSirGlobal mac_ctx,
+ tSirMacTspecIE *tspec, tpPESession session_entry)
+{
+ uint32_t max_phy_rate, min_phy_rate;
+ uint32_t phy_mode;
+ tSirRetStatus retval = eSIR_SUCCESS;
+
+ lim_get_phy_mode(mac_ctx, &phy_mode, session_entry);
+
+ lim_get_available_bw(mac_ctx, &max_phy_rate, &min_phy_rate, phy_mode,
+ 1 /* bandwidth mult factor */);
+ /* mandatory fields are derived from 11e Annex I (Table I.1) */
+ if ((tspec->nomMsduSz == 0) ||
+ (tspec->meanDataRate == 0) ||
+ (tspec->surplusBw == 0) ||
+ (tspec->minPhyRate == 0) ||
+ (tspec->minPhyRate > max_phy_rate)) {
+ lim_log(mac_ctx, LOGW,
+ FL
+ ("Invalid EDCA Tspec: NomMsdu %d, meanDataRate %d, surplusBw %d, min_phy_rate %d"),
+ tspec->nomMsduSz, tspec->meanDataRate,
+ tspec->surplusBw, tspec->minPhyRate);
+ retval = eSIR_FAILURE;
+ }
+
+ lim_log(mac_ctx, ADMIT_CONTROL_LOGLEVEL,
+ FL("return status %d"), retval);
+ return retval;
+}
+
+/** -------------------------------------------------------------
+ \fn lim_validate_tspec
+ \brief validate the offered tspec
+ \param tpAniSirGlobal pMac
+ \param tSirMacTspecIE *pTspec
+ \return eSirRetStatus - status
+ -------------------------------------------------------------*/
+
+static tSirRetStatus
+lim_validate_tspec(tpAniSirGlobal pMac,
+ tSirMacTspecIE *pTspec, tpPESession psessionEntry)
+{
+ tSirRetStatus retval = eSIR_SUCCESS;
+ switch (pTspec->tsinfo.traffic.accessPolicy) {
+ case SIR_MAC_ACCESSPOLICY_EDCA:
+ retval = lim_validate_tspec_edca(pMac, pTspec, psessionEntry);
+ if (retval != eSIR_SUCCESS)
+ PELOGW(lim_log(pMac, LOGW, FL("EDCA tspec invalid"));)
+ break;
+
+ case SIR_MAC_ACCESSPOLICY_HCCA:
+ case SIR_MAC_ACCESSPOLICY_BOTH:
+ /* TBD: should we support hybrid tspec as well?? for now, just fall through */
+ default:
+ lim_log(pMac, LOGW, FL("AccessType %d not supported"),
+ pTspec->tsinfo.traffic.accessPolicy);
+ retval = eSIR_FAILURE;
+ break;
+ }
+ return retval;
+}
+
+/* ----------------------------------------------------------------------------- */
+/* Admit Control Policy */
+
+/** -------------------------------------------------------------
+ \fn lim_compute_mean_bw_used
+ \brief determime the used/allocated bandwidth
+ \param tpAniSirGlobal pMac
+ \param uint32_t *pBw
+ \param uint32_t phyMode
+ \param tpLimTspecInfo pTspecInfo
+ \return eSirRetStatus - status
+ -------------------------------------------------------------*/
+
+static void
+lim_compute_mean_bw_used(tpAniSirGlobal pMac,
+ uint32_t *pBw,
+ uint32_t phyMode,
+ tpLimTspecInfo pTspecInfo, tpPESession psessionEntry)
+{
+ uint32_t ctspec;
+ *pBw = 0;
+ for (ctspec = 0; ctspec < LIM_NUM_TSPEC_MAX; ctspec++, pTspecInfo++) {
+ if (pTspecInfo->inuse) {
+ tpDphHashNode pSta =
+ dph_get_hash_entry(pMac, pTspecInfo->assocId,
+ &psessionEntry->dph.dphHashTable);
+ if (pSta == NULL) {
+ /* maybe we should delete the tspec?? */
+ lim_log(pMac, LOGE,
+ FL
+ ("Tspec %d (assocId %d): dphNode not found"),
+ ctspec, pTspecInfo->assocId);
+ continue;
+ }
+ *pBw += pTspecInfo->tspec.meanDataRate;
+ }
+ }
+}
+
+/** -------------------------------------------------------------
+ \fn lim_get_available_bw
+ \brief based on the phy mode and the bw_factor, determine the total bandwidth that
+ can be supported
+ \param tpAniSirGlobal pMac
+ \param uint32_t *pMaxBw
+ \param uint32_t *pMinBw
+ \param uint32_t phyMode
+ \param uint32_t bw_factor
+ \return eSirRetStatus - status
+ -------------------------------------------------------------*/
+
+static void
+lim_get_available_bw(tpAniSirGlobal pMac,
+ uint32_t *pMaxBw,
+ uint32_t *pMinBw, uint32_t phyMode, uint32_t bw_factor)
+{
+ switch (phyMode) {
+ case WNI_CFG_PHY_MODE_11B:
+ *pMaxBw = LIM_TOTAL_BW_11B;
+ *pMinBw = LIM_MIN_BW_11B;
+ break;
+
+ case WNI_CFG_PHY_MODE_11A:
+ *pMaxBw = LIM_TOTAL_BW_11A;
+ *pMinBw = LIM_MIN_BW_11A;
+ break;
+
+ case WNI_CFG_PHY_MODE_11G:
+ case WNI_CFG_PHY_MODE_NONE:
+ default:
+ *pMaxBw = LIM_TOTAL_BW_11G;
+ *pMinBw = LIM_MIN_BW_11G;
+ break;
+ }
+ *pMaxBw *= bw_factor;
+}
+
+/**
+ * lim_admit_policy_oversubscription() - Admission control policy
+ * @mac_ctx: Global MAC Context
+ * @tspec: Pointer to the tspec
+ * @admit_policy: Admission policy
+ * @tspec_info: TSPEC information
+ * @session_entry: Session Entry
+ *
+ * simple admission control policy based on oversubscription
+ * if the total bandwidth of all admitted tspec's exceeds (factor * phy-bw) then
+ * reject the tspec, else admit it. The phy-bw is the peak available bw in the
+ * current phy mode. The 'factor' is the configured oversubscription factor.
+ *
+ * Return: Status
+ **/
+static tSirRetStatus
+lim_admit_policy_oversubscription(tpAniSirGlobal mac_ctx,
+ tSirMacTspecIE *tspec,
+ tpLimAdmitPolicyInfo admit_policy,
+ tpLimTspecInfo tspec_info,
+ tpPESession session_entry)
+{
+ uint32_t totalbw, minbw, usedbw;
+ uint32_t phy_mode;
+
+ /* determine total bandwidth used so far */
+ lim_get_phy_mode(mac_ctx, &phy_mode, session_entry);
+
+ lim_compute_mean_bw_used(mac_ctx, &usedbw, phy_mode,
+ tspec_info, session_entry);
+
+ /* determine how much bw is available based on the current phy mode */
+ lim_get_available_bw(mac_ctx, &totalbw, &minbw, phy_mode,
+ admit_policy->bw_factor);
+
+ if (usedbw > totalbw) /* this can't possibly happen */
+ return eSIR_FAILURE;
+
+ if ((totalbw - usedbw) < tspec->meanDataRate) {
+ lim_log(mac_ctx, ADMIT_CONTROL_POLICY_LOGLEVEL,
+ FL
+ ("Total BW %d, Used %d, Tspec request %d not possible"),
+ totalbw, usedbw, tspec->meanDataRate);
+ return eSIR_FAILURE;
+ }
+ return eSIR_SUCCESS;
+}
+
+/** -------------------------------------------------------------
+ \fn lim_admit_policy
+ \brief determine the current admit control policy and apply it for the offered tspec
+ \param tpAniSirGlobal pMac
+ \param tSirMacTspecIE *pTspec
+ \return eSirRetStatus - status
+ -------------------------------------------------------------*/
+
+tSirRetStatus lim_admit_policy(tpAniSirGlobal pMac,
+ tSirMacTspecIE *pTspec, tpPESession psessionEntry)
+{
+ tSirRetStatus retval = eSIR_FAILURE;
+ tpLimAdmitPolicyInfo pAdmitPolicy = &pMac->lim.admitPolicyInfo;
+
+ switch (pAdmitPolicy->type) {
+ case WNI_CFG_ADMIT_POLICY_ADMIT_ALL:
+ retval = eSIR_SUCCESS;
+ break;
+
+ case WNI_CFG_ADMIT_POLICY_BW_FACTOR:
+ retval = lim_admit_policy_oversubscription(pMac, pTspec,
+ &pMac->lim.
+ admitPolicyInfo,
+ &pMac->lim.tspecInfo[0],
+ psessionEntry);
+ if (retval != eSIR_SUCCESS)
+ PELOGE(lim_log
+ (pMac, LOGE, FL("rejected by BWFactor policy"));
+ )
+ break;
+
+ case WNI_CFG_ADMIT_POLICY_REJECT_ALL:
+ retval = eSIR_FAILURE;
+ break;
+
+ default:
+ retval = eSIR_SUCCESS;
+ lim_log(pMac, LOGE,
+ FL("Admit Policy %d unknown, admitting all traffic"),
+ pAdmitPolicy->type);
+ break;
+ }
+ return retval;
+}
+
+/** -------------------------------------------------------------
+ \fn lim_tspec_delete
+ \brief delete the specified tspec
+ \param tpAniSirGlobal pMac
+ \param tpLimTspecInfo pInfo
+ \return eSirRetStatus - status
+ -------------------------------------------------------------*/
+
+/* ----------------------------------------------------------------------------- */
+/* delete the specified tspec */
+void lim_tspec_delete(tpAniSirGlobal pMac, tpLimTspecInfo pInfo)
+{
+ if (pInfo == NULL)
+ return;
+ /* pierre */
+ lim_log(pMac, ADMIT_CONTROL_LOGLEVEL, FL("tspec entry = %d"),
+ pInfo->idx);
+ lim_log(pMac, ADMIT_CONTROL_LOGLEVEL, FL("delete tspec %p"), pInfo);
+ pInfo->inuse = 0;
+
+ return;
+}
+
+/** -------------------------------------------------------------
+ \fn lim_tspec_find_by_sta_addr
+ \brief Send halMsg_AddTs to HAL
+ \param tpAniSirGlobal pMac
+ \param \param uint8_t *pAddr
+ \param tSirMacTspecIE *pTspecIE
+ \param tpLimTspecInfo pTspecList
+ \param tpLimTspecInfo *ppInfo
+ \return eSirRetStatus - status
+ -------------------------------------------------------------*/
+
+/* find the specified tspec in the list */
+static tSirRetStatus
+lim_tspec_find_by_sta_addr(tpAniSirGlobal pMac,
+ uint8_t *pAddr,
+ tSirMacTspecIE *pTspecIE,
+ tpLimTspecInfo pTspecList, tpLimTspecInfo *ppInfo)
+{
+ int ctspec;
+
+ *ppInfo = NULL;
+
+ for (ctspec = 0; ctspec < LIM_NUM_TSPEC_MAX; ctspec++, pTspecList++) {
+ if ((pTspecList->inuse)
+ &&
+ (cdf_mem_compare
+ (pAddr, pTspecList->staAddr, sizeof(pTspecList->staAddr)))
+ &&
+ (cdf_mem_compare
+ ((uint8_t *) pTspecIE, (uint8_t *) &pTspecList->tspec,
+ sizeof(tSirMacTspecIE)))) {
+ *ppInfo = pTspecList;
+ return eSIR_SUCCESS;
+ }
+ }
+ return eSIR_FAILURE;
+}
+
+/** -------------------------------------------------------------
+ \fn lim_tspec_find_by_assoc_id
+ \brief find tspec with matchin staid and Tspec
+ \param tpAniSirGlobal pMac
+ \param uint32_t staid
+ \param tSirMacTspecIE *pTspecIE
+ \param tpLimTspecInfo pTspecList
+ \param tpLimTspecInfo *ppInfo
+ \return eSirRetStatus - status
+ -------------------------------------------------------------*/
+
+tSirRetStatus
+lim_tspec_find_by_assoc_id(tpAniSirGlobal pMac,
+ uint16_t assocId,
+ tSirMacTspecIE *pTspecIE,
+ tpLimTspecInfo pTspecList, tpLimTspecInfo *ppInfo)
+{
+ int ctspec;
+
+ *ppInfo = NULL;
+
+ lim_log(pMac, ADMIT_CONTROL_LOGLEVEL,
+ FL("Trying to find tspec entry for assocId = %d"), assocId);
+ lim_log(pMac, ADMIT_CONTROL_LOGLEVEL,
+ FL
+ ("pTsInfo->traffic.direction = %d, pTsInfo->traffic.tsid = %d"),
+ pTspecIE->tsinfo.traffic.direction,
+ pTspecIE->tsinfo.traffic.tsid);
+
+ for (ctspec = 0; ctspec < LIM_NUM_TSPEC_MAX; ctspec++, pTspecList++) {
+ if ((pTspecList->inuse)
+ && (assocId == pTspecList->assocId)
+ &&
+ (cdf_mem_compare
+ ((uint8_t *) pTspecIE, (uint8_t *) &pTspecList->tspec,
+ sizeof(tSirMacTspecIE)))) {
+ *ppInfo = pTspecList;
+ return eSIR_SUCCESS;
+ }
+ }
+ return eSIR_FAILURE;
+}
+
+/** -------------------------------------------------------------
+ \fn lim_find_tspec
+ \brief finding a TSPEC entry with assocId, tsinfo.direction and tsinfo.tsid
+ \param uint16_t assocId
+ \param tpAniSirGlobal pMac
+ \param tSirMacTSInfo *pTsInfo
+ \param tpLimTspecInfo pTspecList
+ \param tpLimTspecInfo *ppInfo
+ \return eSirRetStatus - status of the comparison
+ -------------------------------------------------------------*/
+
+tSirRetStatus
+lim_find_tspec(tpAniSirGlobal pMac,
+ uint16_t assocId,
+ tSirMacTSInfo *pTsInfo,
+ tpLimTspecInfo pTspecList, tpLimTspecInfo *ppInfo)
+{
+ int ctspec;
+
+ *ppInfo = NULL;
+
+ lim_log(pMac, ADMIT_CONTROL_LOGLEVEL,
+ FL("Trying to find tspec entry for assocId = %d"), assocId);
+ lim_log(pMac, ADMIT_CONTROL_LOGLEVEL,
+ FL
+ ("pTsInfo->traffic.direction = %d, pTsInfo->traffic.tsid = %d"),
+ pTsInfo->traffic.direction, pTsInfo->traffic.tsid);
+
+ for (ctspec = 0; ctspec < LIM_NUM_TSPEC_MAX; ctspec++, pTspecList++) {
+ if ((pTspecList->inuse)
+ && (assocId == pTspecList->assocId)
+ && (pTsInfo->traffic.direction ==
+ pTspecList->tspec.tsinfo.traffic.direction)
+ && (pTsInfo->traffic.tsid ==
+ pTspecList->tspec.tsinfo.traffic.tsid)) {
+ *ppInfo = pTspecList;
+ return eSIR_SUCCESS;
+ }
+ }
+ return eSIR_FAILURE;
+}
+
+/** -------------------------------------------------------------
+ \fn lim_tspec_add
+ \brief add or update the specified tspec to the tspec list
+ \param tpAniSirGlobal pMac
+ \param uint8_t *pAddr
+ \param uint16_t assocId
+ \param tSirMacTspecIE *pTspec
+ \param uint32_t interval
+ \param tpLimTspecInfo *ppInfo
+
+ \return eSirRetStatus - status of the comparison
+ -------------------------------------------------------------*/
+
+tSirRetStatus lim_tspec_add(tpAniSirGlobal pMac,
+ uint8_t *pAddr,
+ uint16_t assocId,
+ tSirMacTspecIE *pTspec,
+ uint32_t interval, tpLimTspecInfo *ppInfo)
+{
+ tpLimTspecInfo pTspecList = &pMac->lim.tspecInfo[0];
+ *ppInfo = NULL;
+
+ /* validate the assocId */
+ if (assocId >= pMac->lim.maxStation) {
+ PELOGE(lim_log(pMac, LOGE, FL("Invalid assocId 0x%x"), assocId);)
+ return eSIR_FAILURE;
+ }
+ /* decide whether to add/update */
+ {
+ *ppInfo = NULL;
+
+ if (eSIR_SUCCESS ==
+ lim_find_tspec(pMac, assocId, &pTspec->tsinfo, pTspecList,
+ ppInfo)) {
+ /* update this entry. */
+ lim_log(pMac, ADMIT_CONTROL_LOGLEVEL,
+ FL("updating TSPEC table entry = %d"),
+ (*ppInfo)->idx);
+ } else {
+ /* We didn't find one to update. So find a free slot in the
+ * LIM TSPEC list and add this new entry
+ */
+ uint8_t ctspec = 0;
+ for (ctspec = 0, pTspecList = &pMac->lim.tspecInfo[0];
+ ctspec < LIM_NUM_TSPEC_MAX;
+ ctspec++, pTspecList++) {
+ if (!pTspecList->inuse) {
+ lim_log(pMac, LOG1,
+ FL
+ ("Found free slot in TSPEC list. Add to TSPEC table entry %d"),
+ ctspec);
+ break;
+ }
+ }
+
+ if (ctspec >= LIM_NUM_TSPEC_MAX)
+ return eSIR_FAILURE;
+
+ /* Record the new index entry */
+ pTspecList->idx = ctspec;
+ }
+ }
+
+ /* update the tspec info */
+ pTspecList->tspec = *pTspec;
+ pTspecList->assocId = assocId;
+ cdf_mem_copy(pTspecList->staAddr, pAddr, sizeof(pTspecList->staAddr));
+
+ /* for edca tspec's, we are all done */
+ if (pTspec->tsinfo.traffic.accessPolicy == SIR_MAC_ACCESSPOLICY_EDCA) {
+ pTspecList->inuse = 1;
+ *ppInfo = pTspecList;
+ lim_log(pMac, ADMIT_CONTROL_LOGLEVEL,
+ FL("added entry for EDCA AccessPolicy"));
+ return eSIR_SUCCESS;
+ }
+
+ /*
+ * for hcca tspec's, must set the parameterized bit in the queues
+ * the 'ts' bit in the queue data structure indicates that the queue is
+ * parameterized (hcca). When the schedule is written this bit is used
+ * in the tsid field (bit 3) and the other three bits (0-2) are simply
+ * filled in as the user priority (or qid). This applies only to uplink
+ * polls where the qos control field must contain the tsid specified in the
+ * tspec.
+ */
+ pTspecList->inuse = 1;
+ *ppInfo = pTspecList;
+ lim_log(pMac, ADMIT_CONTROL_LOGLEVEL,
+ FL("added entry for HCCA AccessPolicy"));
+ return eSIR_SUCCESS;
+}
+
+/** -------------------------------------------------------------
+ \fn lim_validate_access_policy
+ \brief Validates Access policy
+ \param tpAniSirGlobal pMac
+ \param uint8_t accessPolicy
+ \param uint16_t assocId
+ \return eSirRetStatus - status
+ -------------------------------------------------------------*/
+
+static tSirRetStatus
+lim_validate_access_policy(tpAniSirGlobal pMac,
+ uint8_t accessPolicy,
+ uint16_t assocId, tpPESession psessionEntry)
+{
+ tSirRetStatus retval = eSIR_FAILURE;
+ tpDphHashNode pSta =
+ dph_get_hash_entry(pMac, assocId, &psessionEntry->dph.dphHashTable);
+
+ if ((pSta == NULL) || (!pSta->valid)) {
+ PELOGE(lim_log(pMac, LOGE, FL("invalid station address passed"));)
+ return eSIR_FAILURE;
+ }
+
+ switch (accessPolicy) {
+ case SIR_MAC_ACCESSPOLICY_EDCA:
+ if (pSta->wmeEnabled || pSta->lleEnabled)
+ retval = eSIR_SUCCESS;
+ break;
+
+ case SIR_MAC_ACCESSPOLICY_HCCA:
+ case SIR_MAC_ACCESSPOLICY_BOTH:
+ default:
+ PELOGE(lim_log
+ (pMac, LOGE, FL("Invalid accessPolicy %d"),
+ accessPolicy);
+ )
+ break;
+ }
+
+ if (retval != eSIR_SUCCESS)
+ lim_log(pMac, LOGW,
+ FL
+ ("failed (accPol %d, staId %d, lle %d, wme %d, wsm %d)"),
+ accessPolicy, pSta->staIndex, pSta->lleEnabled,
+ pSta->wmeEnabled, pSta->wsmEnabled);
+
+ return retval;
+}
+
+/**
+ * lim_admit_control_add_ts() - Check if STA can be admitted
+ * @pMac: Global MAC context
+ * @pAddr: Address
+ * @pAddts: ADD TS
+ * @pQos: QOS fields
+ * @assocId: Association ID
+ * @alloc: Allocate bandwidth for this tspec
+ * @pSch: Schedule IE
+ * @pTspecIdx: TSPEC index
+ * @psessionEntry: PE Session Entry
+ *
+ * Determine if STA with the specified TSPEC can be admitted. If it can,
+ * a schedule element is provided
+ *
+ * Return: status
+ **/
+tSirRetStatus lim_admit_control_add_ts(tpAniSirGlobal pMac, uint8_t *pAddr,
+ tSirAddtsReqInfo *pAddts, tSirMacQosCapabilityStaIE *pQos,
+ uint16_t assocId, uint8_t alloc, tSirMacScheduleIE *pSch,
+ uint8_t *pTspecIdx, tpPESession psessionEntry)
+{
+ tpLimTspecInfo pTspecInfo;
+ tSirRetStatus retval;
+ uint32_t svcInterval;
+ (void)pQos;
+
+ /* TBD: modify tspec as needed */
+ /* EDCA: need to fill in the medium time and the minimum phy rate */
+ /* to be consistent with the desired traffic parameters. */
+
+ lim_log(pMac, ADMIT_CONTROL_LOGLEVEL,
+ FL
+ ("tsid %d, directn %d, start %d, intvl %d, accPolicy %d, up %d"),
+ pAddts->tspec.tsinfo.traffic.tsid,
+ pAddts->tspec.tsinfo.traffic.direction,
+ pAddts->tspec.svcStartTime, pAddts->tspec.minSvcInterval,
+ pAddts->tspec.tsinfo.traffic.accessPolicy,
+ pAddts->tspec.tsinfo.traffic.userPrio);
+
+ /* check for duplicate tspec */
+ retval = (alloc)
+ ? lim_tspec_find_by_assoc_id(pMac, assocId, &pAddts->tspec,
+ &pMac->lim.tspecInfo[0], &pTspecInfo)
+ : lim_tspec_find_by_sta_addr(pMac, pAddr, &pAddts->tspec,
+ &pMac->lim.tspecInfo[0], &pTspecInfo);
+
+ if (retval == eSIR_SUCCESS) {
+ lim_log(pMac, ADMIT_CONTROL_LOGLEVEL,
+ FL("duplicate tspec (index %d)!"), pTspecInfo->idx);
+ return eSIR_FAILURE;
+ }
+ /* check that the tspec's are well formed and acceptable */
+ if (lim_validate_tspec(pMac, &pAddts->tspec, psessionEntry) !=
+ eSIR_SUCCESS) {
+ PELOGW(lim_log(pMac, LOGW, FL("tspec validation failed"));)
+ return eSIR_FAILURE;
+ }
+ /* determine a service interval for the tspec */
+ if (lim_calculate_svc_int(pMac, &pAddts->tspec, &svcInterval) !=
+ eSIR_SUCCESS) {
+ PELOGW(lim_log(pMac, LOGW, FL("SvcInt calculate failed"));)
+ return eSIR_FAILURE;
+ }
+ /* determine if the tspec can be admitted or not based on current policy */
+ if (lim_admit_policy(pMac, &pAddts->tspec, psessionEntry) != eSIR_SUCCESS) {
+ PELOGW(lim_log
+ (pMac, LOGW,
+ FL("tspec rejected by admit control policy"));
+ )
+ return eSIR_FAILURE;
+ }
+ /* fill in a schedule if requested */
+ if (pSch != NULL) {
+ cdf_mem_set((uint8_t *) pSch, sizeof(*pSch), 0);
+ pSch->svcStartTime = pAddts->tspec.svcStartTime;
+ pSch->svcInterval = svcInterval;
+ pSch->maxSvcDuration = (uint16_t) pSch->svcInterval; /* use SP = SI */
+ pSch->specInterval = 0x1000; /* fixed for now: TBD */
+
+ pSch->info.direction = pAddts->tspec.tsinfo.traffic.direction;
+ pSch->info.tsid = pAddts->tspec.tsinfo.traffic.tsid;
+ pSch->info.aggregation = 0; /* no support for aggregation for now: TBD */
+ }
+ /* if no allocation is requested, done */
+ if (!alloc)
+ return eSIR_SUCCESS;
+
+ /* check that we are in the proper mode to deal with the tspec type */
+ if (lim_validate_access_policy
+ (pMac, (uint8_t) pAddts->tspec.tsinfo.traffic.accessPolicy, assocId,
+ psessionEntry) != eSIR_SUCCESS) {
+ lim_log(pMac, LOGW,
+ FL("AccessPolicy %d is not valid in current mode"),
+ pAddts->tspec.tsinfo.traffic.accessPolicy);
+ return eSIR_FAILURE;
+ }
+ /* add tspec to list */
+ if (lim_tspec_add
+ (pMac, pAddr, assocId, &pAddts->tspec, svcInterval, &pTspecInfo)
+ != eSIR_SUCCESS) {
+ PELOGE(lim_log(pMac, LOGE, FL("no space in tspec list"));)
+ return eSIR_FAILURE;
+ }
+ /* passing lim tspec table index to the caller */
+ *pTspecIdx = pTspecInfo->idx;
+
+ return eSIR_SUCCESS;
+}
+
+/** -------------------------------------------------------------
+ \fn lim_admit_control_delete_ts
+ \brief Delete the specified Tspec for the specified STA
+ \param tpAniSirGlobal pMac
+ \param uint16_t assocId
+ \param tSirMacTSInfo *pTsInfo
+ \param uint8_t *pTsStatus
+ \param uint8_t *ptspecIdx
+ \return eSirRetStatus - status
+ -------------------------------------------------------------*/
+
+tSirRetStatus
+lim_admit_control_delete_ts(tpAniSirGlobal pMac,
+ uint16_t assocId,
+ tSirMacTSInfo *pTsInfo,
+ uint8_t *pTsStatus, uint8_t *ptspecIdx)
+{
+ tpLimTspecInfo pTspecInfo = NULL;
+
+ if (pTsStatus != NULL)
+ *pTsStatus = 0;
+
+ if (lim_find_tspec
+ (pMac, assocId, pTsInfo, &pMac->lim.tspecInfo[0],
+ &pTspecInfo) == eSIR_SUCCESS) {
+ if (pTspecInfo != NULL) {
+ lim_log(pMac, ADMIT_CONTROL_LOGLEVEL,
+ FL("Tspec entry %d found"), pTspecInfo->idx);
+
+ *ptspecIdx = pTspecInfo->idx;
+ lim_tspec_delete(pMac, pTspecInfo);
+ return eSIR_SUCCESS;
+ }
+ }
+ return eSIR_FAILURE;
+}
+
+/** -------------------------------------------------------------
+ \fn lim_admit_control_delete_sta
+ \brief Delete all TSPEC for the specified STA
+ \param tpAniSirGlobal pMac
+ \param uint16_t assocId
+ \return eSirRetStatus - status
+ -------------------------------------------------------------*/
+
+tSirRetStatus lim_admit_control_delete_sta(tpAniSirGlobal pMac, uint16_t assocId)
+{
+ tpLimTspecInfo pTspecInfo = &pMac->lim.tspecInfo[0];
+ int ctspec;
+
+ for (ctspec = 0; ctspec < LIM_NUM_TSPEC_MAX; ctspec++, pTspecInfo++) {
+ if (assocId == pTspecInfo->assocId) {
+ lim_tspec_delete(pMac, pTspecInfo);
+ lim_log(pMac, ADMIT_CONTROL_LOGLEVEL,
+ FL("Deleting TSPEC %d for assocId %d"), ctspec,
+ assocId);
+ }
+ }
+ lim_log(pMac, ADMIT_CONTROL_LOGLEVEL, FL("assocId %d done"), assocId);
+
+ return eSIR_SUCCESS;
+}
+
+/** -------------------------------------------------------------
+ \fn lim_admit_control_init
+ \brief init tspec table
+ \param tpAniSirGlobal pMac
+ \return eSirRetStatus - status
+ -------------------------------------------------------------*/
+tSirRetStatus lim_admit_control_init(tpAniSirGlobal pMac)
+{
+ cdf_mem_set(pMac->lim.tspecInfo,
+ LIM_NUM_TSPEC_MAX * sizeof(tLimTspecInfo), 0);
+ return eSIR_SUCCESS;
+}
+
+/** -------------------------------------------------------------
+ \fn lim_update_admit_policy
+ \brief Set the admit control policy based on CFG parameters
+ \param tpAniSirGlobal pMac
+ \return eSirRetStatus - status
+ -------------------------------------------------------------*/
+
+tSirRetStatus lim_update_admit_policy(tpAniSirGlobal pMac)
+{
+ uint32_t val;
+ if (wlan_cfg_get_int(pMac, WNI_CFG_ADMIT_POLICY, &val) != eSIR_SUCCESS) {
+ lim_log(pMac, LOGP, FL("Unable to get CFG_ADMIT_POLICY"));
+ return eSIR_FAILURE;
+ }
+ pMac->lim.admitPolicyInfo.type = (uint8_t) val;
+ if (wlan_cfg_get_int(pMac, WNI_CFG_ADMIT_BWFACTOR, &val) != eSIR_SUCCESS) {
+ lim_log(pMac, LOGP, FL("Unable to get CFG_ADMIT_BWFACTOR"));
+ return eSIR_FAILURE;
+ }
+ pMac->lim.admitPolicyInfo.bw_factor = (uint8_t) val;
+
+ PELOG1(lim_log(pMac, LOG1, FL("LIM: AdmitPolicy %d, bw_factor %d"),
+ pMac->lim.admitPolicyInfo.type,
+ pMac->lim.admitPolicyInfo.bw_factor);
+ )
+
+ return eSIR_SUCCESS;
+}
+
+/** -------------------------------------------------------------
+ \fn lim_send_hal_msg_add_ts
+ \brief Send halMsg_AddTs to HAL
+ \param tpAniSirGlobal pMac
+ \param uint16_t staIdx
+ \param uint8_t tspecIdx
+ \param tSirMacTspecIE tspecIE
+ \param tSirTclasInfo *tclasInfo
+ \param uint8_t tclasProc
+ \param uint16_t tsm_interval
+ \return eSirRetStatus - status
+ -------------------------------------------------------------*/
+#ifdef FEATURE_WLAN_ESE
+tSirRetStatus
+lim_send_hal_msg_add_ts(tpAniSirGlobal pMac,
+ uint16_t staIdx,
+ uint8_t tspecIdx,
+ tSirMacTspecIE tspecIE,
+ uint8_t sessionId, uint16_t tsm_interval)
+#else
+tSirRetStatus
+lim_send_hal_msg_add_ts(tpAniSirGlobal pMac,
+ uint16_t staIdx,
+ uint8_t tspecIdx, tSirMacTspecIE tspecIE, uint8_t sessionId)
+#endif
+{
+ tSirMsgQ msg;
+ tpAddTsParams pAddTsParam;
+
+#ifdef WLAN_FEATURE_ROAM_OFFLOAD
+ tpPESession psessionEntry = pe_find_session_by_session_id(pMac, sessionId);
+ if (psessionEntry == NULL) {
+ lim_log(pMac, LOGP,
+ FL("Unable to get Session for session Id %d"),
+ sessionId);
+ return eSIR_FAILURE;
+ }
+#endif
+ pAddTsParam = cdf_mem_malloc(sizeof(tAddTsParams));
+ if (NULL == pAddTsParam) {
+ PELOGW(lim_log(pMac, LOGW, FL("AllocateMemory() failed"));)
+ return eSIR_MEM_ALLOC_FAILED;
+ }
+
+ cdf_mem_set((uint8_t *) pAddTsParam, sizeof(tAddTsParams), 0);
+ pAddTsParam->staIdx = staIdx;
+ pAddTsParam->tspecIdx = tspecIdx;
+ cdf_mem_copy(&pAddTsParam->tspec, &tspecIE, sizeof(tSirMacTspecIE));
+ pAddTsParam->sessionId = sessionId;
+ pAddTsParam->sme_session_id = psessionEntry->smeSessionId;
+
+#ifdef FEATURE_WLAN_ESE
+ pAddTsParam->tsm_interval = tsm_interval;
+#endif
+#ifdef WLAN_FEATURE_ROAM_OFFLOAD
+ if (pMac->roam.configParam.isRoamOffloadEnabled &&
+ psessionEntry->is11Rconnection)
+ pAddTsParam->setRICparams = 1;
+#endif
+
+ msg.type = WMA_ADD_TS_REQ;
+ msg.bodyptr = pAddTsParam;
+ msg.bodyval = 0;
+
+ /* We need to defer any incoming messages until we get a
+ * WMA_ADD_TS_RSP from HAL.
+ */
+ SET_LIM_PROCESS_DEFD_MESGS(pMac, false);
+ MTRACE(mac_trace_msg_tx(pMac, sessionId, msg.type));
+
+ if (eSIR_SUCCESS != wma_post_ctrl_msg(pMac, &msg)) {
+ lim_log(pMac, LOGW, FL("wma_post_ctrl_msg() failed"));
+ SET_LIM_PROCESS_DEFD_MESGS(pMac, true);
+ cdf_mem_free(pAddTsParam);
+ return eSIR_FAILURE;
+ }
+ return eSIR_SUCCESS;
+}
+
+/** -------------------------------------------------------------
+ \fn lim_send_hal_msg_del_ts
+ \brief Send halMsg_AddTs to HAL
+ \param tpAniSirGlobal pMac
+ \param uint16_t staIdx
+ \param uint8_t tspecIdx
+ \param tSirAddtsReqInfo addts
+ \return eSirRetStatus - status
+ -------------------------------------------------------------*/
+
+tSirRetStatus
+lim_send_hal_msg_del_ts(tpAniSirGlobal pMac,
+ uint16_t staIdx,
+ uint8_t tspecIdx,
+ tSirDeltsReqInfo delts, uint8_t sessionId, uint8_t *bssId)
+{
+ tSirMsgQ msg;
+ tpDelTsParams pDelTsParam;
+ tpPESession psessionEntry = NULL;
+
+ pDelTsParam = cdf_mem_malloc(sizeof(tDelTsParams));
+ if (NULL == pDelTsParam) {
+ lim_log(pMac, LOGP, FL("AllocateMemory() failed"));
+ return eSIR_MEM_ALLOC_FAILED;
+ }
+
+ msg.type = WMA_DEL_TS_REQ;
+ msg.bodyptr = pDelTsParam;
+ msg.bodyval = 0;
+ cdf_mem_set((uint8_t *) pDelTsParam, sizeof(tDelTsParams), 0);
+
+ /* filling message parameters. */
+ pDelTsParam->staIdx = staIdx;
+ pDelTsParam->tspecIdx = tspecIdx;
+ cdf_mem_copy(&pDelTsParam->bssId, bssId, sizeof(tSirMacAddr));
+
+ psessionEntry = pe_find_session_by_session_id(pMac, sessionId);
+ if (psessionEntry == NULL) {
+ PELOGE(lim_log(pMac, LOGE,
+ FL
+ ("Session does Not exist with given sessionId :%d "),
+ sessionId);
+ )
+ goto err;
+ }
+ pDelTsParam->sessionId = psessionEntry->smeSessionId;
+ pDelTsParam->userPrio = delts.wmeTspecPresent ?
+ delts.tspec.tsinfo.traffic.userPrio :
+ delts.tsinfo.traffic.userPrio;
+
+#ifdef WLAN_FEATURE_ROAM_OFFLOAD
+ if (pMac->roam.configParam.isRoamOffloadEnabled &&
+ psessionEntry->is11Rconnection) {
+ cdf_mem_copy(&pDelTsParam->delTsInfo, &delts,
+ sizeof(tSirDeltsReqInfo));
+ pDelTsParam->setRICparams = 1;
+ }
+#endif
+
+ lim_log(pMac, LOGW, FL("calling wma_post_ctrl_msg()"));
+ MTRACE(mac_trace_msg_tx(pMac, sessionId, msg.type));
+
+ if (eSIR_SUCCESS != wma_post_ctrl_msg(pMac, &msg)) {
+ lim_log(pMac, LOGW, FL("wma_post_ctrl_msg() failed"));
+ goto err;
+ }
+ return eSIR_SUCCESS;
+
+err:
+ cdf_mem_free(pDelTsParam);
+ return eSIR_FAILURE;
+}
+
+/** -------------------------------------------------------------
+ \fn lim_process_hal_add_ts_rsp
+ \brief This function process the WMA_ADD_TS_RSP from HAL.
+ \ If response is successful, then send back SME_ADDTS_RSP.
+ \ Otherwise, send DELTS action frame to peer and then
+ \ then send back SME_ADDTS_RSP.
+ \
+ \param tpAniSirGlobal pMac
+ \param tpSirMsgQ limMsg
+ -------------------------------------------------------------*/
+void lim_process_hal_add_ts_rsp(tpAniSirGlobal pMac, tpSirMsgQ limMsg)
+{
+ tpAddTsParams pAddTsRspMsg = NULL;
+ tpDphHashNode pSta = NULL;
+ uint16_t assocId = 0;
+ tSirMacAddr peerMacAddr;
+ uint8_t rspReqd = 1;
+ tpPESession psessionEntry = NULL;
+
+ /* Need to process all the deferred messages enqueued
+ * since sending the WMA_ADD_TS_REQ.
+ */
+ SET_LIM_PROCESS_DEFD_MESGS(pMac, true);
+
+ if (NULL == limMsg->bodyptr) {
+ lim_log(pMac, LOGP, FL("Received WMA_ADD_TS_RSP with NULL "));
+ goto end;
+ }
+
+ pAddTsRspMsg = (tpAddTsParams) (limMsg->bodyptr);
+
+ /* 090803: Use pe_find_session_by_session_id() to obtain the PE session context */
+ /* from the sessionId in the Rsp Msg from HAL */
+ psessionEntry = pe_find_session_by_session_id(pMac, pAddTsRspMsg->sessionId);
+
+ if (psessionEntry == NULL) {
+ PELOGE(lim_log
+ (pMac, LOGE,
+ FL("Session does Not exist with given sessionId :%d "),
+ pAddTsRspMsg->sessionId);
+ )
+ lim_send_sme_addts_rsp(pMac, rspReqd, eSIR_SME_ADDTS_RSP_FAILED,
+ psessionEntry, pAddTsRspMsg->tspec,
+ pMac->lim.gLimAddtsReq.sessionId,
+ pMac->lim.gLimAddtsReq.transactionId);
+ goto end;
+ }
+
+ if (pAddTsRspMsg->status == CDF_STATUS_SUCCESS) {
+ PELOG1(lim_log
+ (pMac, LOG1,
+ FL("Received successful ADDTS response from HAL "));
+ )
+ /* Use the smesessionId and smetransactionId from the PE session context */
+ lim_send_sme_addts_rsp(pMac, rspReqd, eSIR_SME_SUCCESS,
+ psessionEntry, pAddTsRspMsg->tspec,
+ psessionEntry->smeSessionId,
+ psessionEntry->transactionId);
+ goto end;
+ } else {
+ PELOG1(lim_log
+ (pMac, LOG1,
+ FL("Received failure ADDTS response from HAL "));
+ )
+ /* Send DELTS action frame to AP */
+ /* 090803: Get peer MAC addr from session */
+ sir_copy_mac_addr(peerMacAddr, psessionEntry->bssId);
+
+ /* 090803: Add the SME Session ID */
+ lim_send_delts_req_action_frame(pMac, peerMacAddr, rspReqd,
+ &pAddTsRspMsg->tspec.tsinfo,
+ &pAddTsRspMsg->tspec, psessionEntry);
+
+ /* Delete TSPEC */
+ /* 090803: Pull the hash table from the session */
+ pSta = dph_lookup_assoc_id(pMac, pAddTsRspMsg->staIdx, &assocId,
+ &psessionEntry->dph.dphHashTable);
+ if (pSta != NULL)
+ lim_admit_control_delete_ts(pMac, assocId,
+ &pAddTsRspMsg->tspec.tsinfo,
+ NULL,
+ (uint8_t *) &pAddTsRspMsg->
+ tspecIdx);
+
+ /* Send SME_ADDTS_RSP */
+ /* 090803: Use the smesessionId and smetransactionId from the PE session context */
+ lim_send_sme_addts_rsp(pMac, rspReqd, eSIR_SME_ADDTS_RSP_FAILED,
+ psessionEntry, pAddTsRspMsg->tspec,
+ psessionEntry->smeSessionId,
+ psessionEntry->transactionId);
+ goto end;
+ }
+
+end:
+ if (pAddTsRspMsg != NULL)
+ cdf_mem_free(pAddTsRspMsg);
+ return;
+}
diff --git a/core/mac/src/pe/lim/lim_aid_mgmt.c b/core/mac/src/pe/lim/lim_aid_mgmt.c
new file mode 100644
index 0000000..253543d
--- /dev/null
+++ b/core/mac/src/pe/lim/lim_aid_mgmt.c
@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) 2011-2015 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_aid_mgmt.c contains the functions related to
+ * AID pool management like initialization, assignment etc.
+ * Author: Chandra Modumudi
+ * Date: 03/20/02
+ * History:-
+ * Date Modified by Modification Information
+ * --------------------------------------------------------------------
+ */
+
+#include "cds_api.h"
+#include "wni_cfg.h"
+#include "ani_global.h"
+#include "cfg_api.h"
+#include "sir_params.h"
+#include "lim_utils.h"
+#include "lim_timer_utils.h"
+#ifdef WLAN_FEATURE_VOWIFI_11R
+#include "lim_ft_defs.h"
+#endif
+#include "lim_session.h"
+#include "lim_session_utils.h"
+
+#define LIM_START_PEER_IDX 1
+
+/**
+ * lim_init_peer_idxpool()
+ *
+ ***FUNCTION:
+ * This function is called while starting a BSS at AP
+ * to initialize AID pool. This may also be called while
+ * starting/joining an IBSS if 'Association' is allowed
+ * in IBSS.
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ * NA
+ *
+ ***NOTE:
+ * NA
+ *
+ * @param pMac - Pointer to Global MAC structure
+ * @return None
+ */
+
+void lim_init_peer_idxpool(tpAniSirGlobal pMac, tpPESession pSessionEntry)
+{
+ uint8_t i;
+ uint8_t maxAssocSta = pMac->lim.gLimAssocStaLimit;
+
+ pSessionEntry->gpLimPeerIdxpool[0] = 0;
+
+#ifdef FEATURE_WLAN_TDLS
+ /* In station role, DPH_STA_HASH_INDEX_PEER (index 1) is reserved for peer */
+ /* station index corresponding to AP. Avoid choosing that index and get index */
+ /* starting from (DPH_STA_HASH_INDEX_PEER + 1) (index 2) for TDLS stations; */
+ if (LIM_IS_STA_ROLE(pSessionEntry)) {
+ pSessionEntry->freePeerIdxHead = DPH_STA_HASH_INDEX_PEER + 1;
+ } else
+#endif
+#ifdef QCA_IBSS_SUPPORT
+ if (LIM_IS_IBSS_ROLE(pSessionEntry)) {
+ pSessionEntry->freePeerIdxHead = LIM_START_PEER_IDX;
+ maxAssocSta = pMac->lim.gLimIbssStaLimit;
+ } else
+#endif
+ {
+ pSessionEntry->freePeerIdxHead = LIM_START_PEER_IDX;
+ }
+
+ for (i = pSessionEntry->freePeerIdxHead; i < maxAssocSta; i++) {
+ pSessionEntry->gpLimPeerIdxpool[i] = i + 1;
+ }
+ pSessionEntry->gpLimPeerIdxpool[i] = 0;
+
+ pSessionEntry->freePeerIdxTail = i;
+
+}
+
+/**
+ * lim_assign_peer_idx()
+ *
+ ***FUNCTION:
+ * This function is called to get a peer station index. This index is
+ * used during Association/Reassociation
+ * frame handling to assign association ID (aid) to a STA.
+ * In case of TDLS, this is used to assign a index into the Dph hash entry.
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ * NA
+ *
+ ***NOTE:
+ *
+ * @param pMac - Pointer to Global MAC structure
+ * @return peerIdx - assigned peer Station IDx for STA
+ */
+
+uint16_t lim_assign_peer_idx(tpAniSirGlobal pMac, tpPESession pSessionEntry)
+{
+ uint16_t peerId;
+
+ /* make sure we haven't exceeded the configurable limit on associations */
+ /* This count is global to ensure that it doesnt exceed the hardware limits. */
+ if (pe_get_current_stas_count(pMac) >= pMac->lim.gLimAssocStaLimit) {
+ /* too many associations already active */
+ return 0;
+ }
+
+ /* return head of free list */
+
+ if (pSessionEntry->freePeerIdxHead) {
+ peerId = pSessionEntry->freePeerIdxHead;
+ pSessionEntry->freePeerIdxHead =
+ pSessionEntry->gpLimPeerIdxpool[pSessionEntry->
+ freePeerIdxHead];
+ if (pSessionEntry->freePeerIdxHead == 0)
+ pSessionEntry->freePeerIdxTail = 0;
+ pSessionEntry->gLimNumOfCurrentSTAs++;
+ return peerId;
+ }
+
+ return 0; /* no more free peer index */
+}
+
+/**
+ * lim_release_peer_idx()
+ *
+ ***FUNCTION:
+ * This function is called when a STA context is removed
+ * at AP (or at a STA in IBSS mode or TDLS) to return peer Index
+ * to free pool.
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ * NA
+ *
+ ***NOTE:
+ *
+ * @param pMac - Pointer to Global MAC structure
+ * @param peerIdx - peer station index that need to return to free pool
+ *
+ * @return None
+ */
+
+void
+lim_release_peer_idx(tpAniSirGlobal pMac, uint16_t peerIdx,
+ tpPESession pSessionEntry)
+{
+ pSessionEntry->gLimNumOfCurrentSTAs--;
+
+ /* insert at tail of free list */
+ if (pSessionEntry->freePeerIdxTail) {
+ pSessionEntry->gpLimPeerIdxpool[pSessionEntry->
+ freePeerIdxTail] =
+ (uint8_t) peerIdx;
+ pSessionEntry->freePeerIdxTail = (uint8_t) peerIdx;
+ } else {
+ pSessionEntry->freePeerIdxTail =
+ pSessionEntry->freePeerIdxHead = (uint8_t) peerIdx;
+ }
+ pSessionEntry->gpLimPeerIdxpool[(uint8_t) peerIdx] = 0;
+}
diff --git a/core/mac/src/pe/lim/lim_api.c b/core/mac/src/pe/lim/lim_api.c
new file mode 100644
index 0000000..1d0dc07
--- /dev/null
+++ b/core/mac/src/pe/lim/lim_api.c
@@ -0,0 +1,2202 @@
+/*
+ * Copyright (c) 2011-2015 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_api.cc contains the functions that are
+ * exported by LIM to other modules.
+ *
+ * Author: Chandra Modumudi
+ * Date: 02/11/02
+ * History:-
+ * Date Modified by Modification Information
+ * --------------------------------------------------------------------
+ *
+ */
+#include "cds_api.h"
+#include "wni_cfg.h"
+#include "wni_api.h"
+#include "sir_common.h"
+#include "sir_debug.h"
+#include "cfg_api.h"
+
+#include "sch_api.h"
+#include "utils_api.h"
+#include "lim_api.h"
+#include "lim_global.h"
+#include "lim_types.h"
+#include "lim_utils.h"
+#include "lim_assoc_utils.h"
+#include "lim_prop_exts_utils.h"
+#include "lim_ser_des_utils.h"
+#include "lim_ibss_peer_mgmt.h"
+#include "lim_admit_control.h"
+#include "lim_send_sme_rsp_messages.h"
+#include "wmm_apsd.h"
+#include "lim_trace.h"
+#ifdef WLAN_FEATURE_VOWIFI_11R
+#include "lim_ft_defs.h"
+#endif
+#include "lim_session.h"
+#include "wma_types.h"
+
+#if defined WLAN_FEATURE_VOWIFI
+#include "rrm_api.h"
+#endif
+
+#include <lim_ft.h>
+#include "cdf_types.h"
+#include "cds_packet.h"
+#include "cds_utils.h"
+#include "sys_startup.h"
+
+static void __lim_init_scan_vars(tpAniSirGlobal pMac)
+{
+ pMac->lim.gLimUseScanModeForLearnMode = 1;
+
+ pMac->lim.gLimSystemInScanLearnMode = 0;
+
+ /* Scan related globals on STA */
+ pMac->lim.gLimReturnAfterFirstMatch = 0;
+ pMac->lim.gLim24Band11dScanDone = 0;
+ pMac->lim.gLim50Band11dScanDone = 0;
+ pMac->lim.gLimReturnUniqueResults = 0;
+
+ pMac->lim.gLimCurrentScanChannelId = 0;
+ pMac->lim.gpLimMlmScanReq = NULL;
+ pMac->lim.gDeferMsgTypeForNOA = 0;
+ pMac->lim.gpDefdSmeMsgForNOA = NULL;
+
+ pMac->lim.gLimRestoreCBNumScanInterval =
+ LIM_RESTORE_CB_NUM_SCAN_INTERVAL_DEFAULT;
+ pMac->lim.gLimRestoreCBCount = 0;
+ cdf_mem_set(pMac->lim.gLimLegacyBssidList,
+ sizeof(pMac->lim.gLimLegacyBssidList), 0);
+
+ /* Fill in default values */
+
+ /* abort scan is used to abort an on-going scan */
+ pMac->lim.abortScan = 0;
+ cdf_mem_set(&pMac->lim.scanChnInfo, sizeof(tLimScanChnInfo), 0);
+ cdf_mem_set(&pMac->lim.dfschannelList, sizeof(tSirDFSChannelList), 0);
+
+/* WLAN_SUSPEND_LINK Related */
+ pMac->lim.gpLimSuspendCallback = NULL;
+ pMac->lim.gpLimResumeCallback = NULL;
+/* end WLAN_SUSPEND_LINK Related */
+}
+
+static void __lim_init_bss_vars(tpAniSirGlobal pMac)
+{
+ cdf_mem_set((void *)pMac->lim.gpSession,
+ sizeof(*pMac->lim.gpSession) * pMac->lim.maxBssId, 0);
+
+ /* This is for testing purposes only, be default should always be off */
+ pMac->lim.gLimForceNoPropIE = 0;
+ pMac->lim.gpLimMlmSetKeysReq = NULL;
+}
+
+static void __lim_init_stats_vars(tpAniSirGlobal pMac)
+{
+ pMac->lim.gLimNumBeaconsRcvd = 0;
+ pMac->lim.gLimNumBeaconsIgnored = 0;
+
+ pMac->lim.gLimNumDeferredMsgs = 0;
+
+ /* / Variable to keep track of number of currently associated STAs */
+ pMac->lim.gLimNumOfAniSTAs = 0; /* count of ANI peers */
+
+ /* Heart-Beat interval value */
+ pMac->lim.gLimHeartBeatCount = 0;
+
+ cdf_mem_zero(pMac->lim.gLimHeartBeatApMac[0],
+ sizeof(tSirMacAddr));
+ cdf_mem_zero(pMac->lim.gLimHeartBeatApMac[1],
+ sizeof(tSirMacAddr));
+ pMac->lim.gLimHeartBeatApMacIndex = 0;
+
+ /* Statistics to keep track of no. beacons rcvd in heart beat interval */
+ cdf_mem_set(pMac->lim.gLimHeartBeatBeaconStats,
+ sizeof(pMac->lim.gLimHeartBeatBeaconStats), 0);
+
+#ifdef WLAN_DEBUG
+ /* Debug counters */
+ pMac->lim.numTot = 0;
+ pMac->lim.numBbt = 0;
+ pMac->lim.numProtErr = 0;
+ pMac->lim.numLearn = 0;
+ pMac->lim.numLearnIgnore = 0;
+ pMac->lim.numSme = 0;
+ cdf_mem_set(pMac->lim.numMAC, sizeof(pMac->lim.numMAC), 0);
+ pMac->lim.gLimNumAssocReqDropInvldState = 0;
+ pMac->lim.gLimNumAssocReqDropACRejectTS = 0;
+ pMac->lim.gLimNumAssocReqDropACRejectSta = 0;
+ pMac->lim.gLimNumReassocReqDropInvldState = 0;
+ pMac->lim.gLimNumHashMissIgnored = 0;
+ pMac->lim.gLimUnexpBcnCnt = 0;
+ pMac->lim.gLimBcnSSIDMismatchCnt = 0;
+ pMac->lim.gLimNumLinkEsts = 0;
+ pMac->lim.gLimNumRxCleanup = 0;
+ pMac->lim.gLim11bStaAssocRejectCount = 0;
+#endif
+}
+
+static void __lim_init_states(tpAniSirGlobal pMac)
+{
+ /* Counts Heartbeat failures */
+ pMac->lim.gLimHBfailureCntInLinkEstState = 0;
+ pMac->lim.gLimProbeFailureAfterHBfailedCnt = 0;
+ pMac->lim.gLimHBfailureCntInOtherStates = 0;
+ pMac->lim.gLimRspReqd = 0;
+ pMac->lim.gLimPrevSmeState = eLIM_SME_OFFLINE_STATE;
+
+ /* / MLM State visible across all Sirius modules */
+ MTRACE(mac_trace
+ (pMac, TRACE_CODE_MLM_STATE, NO_SESSION, eLIM_MLM_IDLE_STATE));
+ pMac->lim.gLimMlmState = eLIM_MLM_IDLE_STATE;
+
+ /* / Previous MLM State */
+ pMac->lim.gLimPrevMlmState = eLIM_MLM_OFFLINE_STATE;
+
+ /* LIM to HAL SCAN Management Message Interface states */
+ pMac->lim.gLimHalScanState = eLIM_HAL_IDLE_SCAN_STATE;
+
+ /**
+ * Initialize state to eLIM_SME_OFFLINE_STATE
+ */
+ pMac->lim.gLimSmeState = eLIM_SME_OFFLINE_STATE;
+
+ /**
+ * By default assume 'unknown' role. This will be updated
+ * when SME_START_BSS_REQ is received.
+ */
+
+ cdf_mem_set(&pMac->lim.gLimOverlap11gParams, sizeof(tLimProtStaParams),
+ 0);
+ cdf_mem_set(&pMac->lim.gLimOverlap11aParams, sizeof(tLimProtStaParams),
+ 0);
+ cdf_mem_set(&pMac->lim.gLimOverlapHt20Params, sizeof(tLimProtStaParams),
+ 0);
+ cdf_mem_set(&pMac->lim.gLimOverlapNonGfParams,
+ sizeof(tLimProtStaParams), 0);
+ cdf_mem_set(&pMac->lim.gLimNoShortParams, sizeof(tLimNoShortParams), 0);
+ cdf_mem_set(&pMac->lim.gLimNoShortSlotParams,
+ sizeof(tLimNoShortSlotParams), 0);
+
+ pMac->lim.gLimPhyMode = 0;
+ pMac->lim.scanStartTime = 0; /* used to measure scan time */
+
+ cdf_mem_set(pMac->lim.gLimMyMacAddr, sizeof(pMac->lim.gLimMyMacAddr),
+ 0);
+ pMac->lim.ackPolicy = 0;
+
+ pMac->lim.gLimProbeRespDisableFlag = 0; /* control over probe resp */
+}
+
+static void __lim_init_vars(tpAniSirGlobal pMac)
+{
+ /* Place holder for Measurement Req/Rsp/Ind related info */
+
+
+ /* Deferred Queue Paramters */
+ cdf_mem_set(&pMac->lim.gLimDeferredMsgQ, sizeof(tSirAddtsReq), 0);
+
+ /* addts request if any - only one can be outstanding at any time */
+ cdf_mem_set(&pMac->lim.gLimAddtsReq, sizeof(tSirAddtsReq), 0);
+ pMac->lim.gLimAddtsSent = 0;
+ pMac->lim.gLimAddtsRspTimerCount = 0;
+
+ /* protection related config cache */
+ cdf_mem_set(&pMac->lim.cfgProtection, sizeof(tCfgProtection), 0);
+ pMac->lim.gLimProtectionControl = 0;
+ SET_LIM_PROCESS_DEFD_MESGS(pMac, true);
+
+ /* WMM Related Flag */
+ pMac->lim.gUapsdEnable = 0;
+ pMac->lim.gUapsdPerAcBitmask = 0;
+
+ /* QoS-AC Downgrade: Initially, no AC is admitted */
+ pMac->lim.gAcAdmitMask[SIR_MAC_DIRECTION_UPLINK] = 0;
+ pMac->lim.gAcAdmitMask[SIR_MAC_DIRECTION_DNLINK] = 0;
+
+ /* dialogue token List head/tail for Action frames request sent. */
+ pMac->lim.pDialogueTokenHead = NULL;
+ pMac->lim.pDialogueTokenTail = NULL;
+
+ cdf_mem_set(&pMac->lim.tspecInfo,
+ sizeof(tLimTspecInfo) * LIM_NUM_TSPEC_MAX, 0);
+
+ /* admission control policy information */
+ cdf_mem_set(&pMac->lim.admitPolicyInfo, sizeof(tLimAdmitPolicyInfo), 0);
+
+ pMac->lim.gLastBeaconDtimCount = 0;
+ pMac->lim.gLastBeaconDtimPeriod = 0;
+
+ /* Scan in Power Save Flag */
+ pMac->lim.gScanInPowersave = 0;
+ pMac->lim.probeCounter = 0;
+ pMac->lim.maxProbe = 0;
+}
+
+static void __lim_init_assoc_vars(tpAniSirGlobal pMac)
+{
+ uint32_t val;
+ if (wlan_cfg_get_int(pMac, WNI_CFG_ASSOC_STA_LIMIT, &val)
+ != eSIR_SUCCESS)
+ lim_log(pMac, LOGP, FL("cfg get assoc sta limit failed"));
+ pMac->lim.gLimAssocStaLimit = val;
+ pMac->lim.gLimIbssStaLimit = val;
+ /* Place holder for current authentication request */
+ /* being handled */
+ pMac->lim.gpLimMlmAuthReq = NULL;
+
+ /* / MAC level Pre-authentication related globals */
+ pMac->lim.gLimPreAuthChannelNumber = 0;
+ pMac->lim.gLimPreAuthType = eSIR_OPEN_SYSTEM;
+ cdf_mem_set(&pMac->lim.gLimPreAuthPeerAddr, sizeof(tSirMacAddr), 0);
+ pMac->lim.gLimNumPreAuthContexts = 0;
+ cdf_mem_set(&pMac->lim.gLimPreAuthTimerTable, sizeof(tLimPreAuthTable),
+ 0);
+
+ /* Placed holder to deauth reason */
+ pMac->lim.gLimDeauthReasonCode = 0;
+
+ /* Place holder for Pre-authentication node list */
+ pMac->lim.pLimPreAuthList = NULL;
+
+ /* Send Disassociate frame threshold parameters */
+ pMac->lim.gLimDisassocFrameThreshold =
+ LIM_SEND_DISASSOC_FRAME_THRESHOLD;
+ pMac->lim.gLimDisassocFrameCredit = 0;
+
+ /* One cache for each overlap and associated case. */
+ cdf_mem_set(pMac->lim.protStaOverlapCache,
+ sizeof(tCacheParams) * LIM_PROT_STA_OVERLAP_CACHE_SIZE, 0);
+ cdf_mem_set(pMac->lim.protStaCache,
+ sizeof(tCacheParams) * LIM_PROT_STA_CACHE_SIZE, 0);
+
+#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
+ pMac->lim.pSessionEntry = NULL;
+ pMac->lim.reAssocRetryAttempt = 0;
+#endif
+
+}
+
+static void __lim_init_ht_vars(tpAniSirGlobal pMac)
+{
+ pMac->lim.htCapabilityPresentInBeacon = 0;
+ pMac->lim.gHTGreenfield = 0;
+ pMac->lim.gHTShortGI40Mhz = 0;
+ pMac->lim.gHTShortGI20Mhz = 0;
+ pMac->lim.gHTMaxAmsduLength = 0;
+ pMac->lim.gHTDsssCckRate40MHzSupport = 0;
+ pMac->lim.gHTPSMPSupport = 0;
+ pMac->lim.gHTLsigTXOPProtection = 0;
+ pMac->lim.gHTMIMOPSState = eSIR_HT_MIMO_PS_STATIC;
+ pMac->lim.gHTAMpduDensity = 0;
+
+ pMac->lim.gMaxAmsduSizeEnabled = false;
+ pMac->lim.gHTMaxRxAMpduFactor = 0;
+ pMac->lim.gHTServiceIntervalGranularity = 0;
+ pMac->lim.gHTControlledAccessOnly = 0;
+ pMac->lim.gHTOperMode = eSIR_HT_OP_MODE_PURE;
+ pMac->lim.gHTPCOActive = 0;
+
+ pMac->lim.gHTPCOPhase = 0;
+ pMac->lim.gHTSecondaryBeacon = 0;
+ pMac->lim.gHTDualCTSProtection = 0;
+ pMac->lim.gHTSTBCBasicMCS = 0;
+}
+
+static tSirRetStatus __lim_init_config(tpAniSirGlobal pMac)
+{
+ uint32_t val1, val2, val3;
+ uint16_t val16;
+ uint8_t val8;
+ tSirMacHTCapabilityInfo *pHTCapabilityInfo;
+ tSirMacHTInfoField1 *pHTInfoField1;
+ tSirMacHTParametersInfo *pAmpduParamInfo;
+
+ /* Read all the CFGs here that were updated before pe_start is called */
+ /* All these CFG READS/WRITES are only allowed in init, at start when there is no session
+ * and they will be used throughout when there is no session
+ */
+
+ if (wlan_cfg_get_int(pMac, WNI_CFG_HT_CAP_INFO, &val1) != eSIR_SUCCESS) {
+ PELOGE(lim_log(pMac, LOGE, FL("could not retrieve HT Cap CFG"));)
+ return eSIR_FAILURE;
+ }
+
+ if (wlan_cfg_get_int(pMac, WNI_CFG_CHANNEL_BONDING_MODE, &val2) !=
+ eSIR_SUCCESS) {
+ PELOGE(lim_log
+ (pMac, LOGE,
+ FL("could not retrieve Channel Bonding CFG"));
+ )
+ return eSIR_FAILURE;
+ }
+ val16 = (uint16_t) val1;
+ pHTCapabilityInfo = (tSirMacHTCapabilityInfo *) &val16;
+
+ /* channel bonding mode could be set to anything from 0 to 4(Titan had these */
+ /* modes But for Taurus we have only two modes: enable(>0) or disable(=0) */
+ pHTCapabilityInfo->supportedChannelWidthSet = val2 ?
+ WNI_CFG_CHANNEL_BONDING_MODE_ENABLE :
+ WNI_CFG_CHANNEL_BONDING_MODE_DISABLE;
+ if (cfg_set_int
+ (pMac, WNI_CFG_HT_CAP_INFO, *(uint16_t *) pHTCapabilityInfo)
+ != eSIR_SUCCESS) {
+ PELOGE(lim_log
+ (pMac, LOGE, FL("could not update HT Cap Info CFG"));
+ )
+ return eSIR_FAILURE;
+ }
+
+ if (wlan_cfg_get_int(pMac, WNI_CFG_HT_INFO_FIELD1, &val1) != eSIR_SUCCESS) {
+ PELOGE(lim_log
+ (pMac, LOGE,
+ FL("could not retrieve HT INFO Field1 CFG"));
+ )
+ return eSIR_FAILURE;
+ }
+
+ val8 = (uint8_t) val1;
+ pHTInfoField1 = (tSirMacHTInfoField1 *) &val8;
+ pHTInfoField1->recommendedTxWidthSet =
+ (uint8_t) pHTCapabilityInfo->supportedChannelWidthSet;
+ if (cfg_set_int(pMac, WNI_CFG_HT_INFO_FIELD1, *(uint8_t *) pHTInfoField1)
+ != eSIR_SUCCESS) {
+ PELOGE(lim_log(pMac, LOGE, FL("could not update HT Info Field"));)
+ return eSIR_FAILURE;
+ }
+
+ /* WNI_CFG_HEART_BEAT_THRESHOLD */
+
+ if (wlan_cfg_get_int(pMac, WNI_CFG_HEART_BEAT_THRESHOLD, &val1) !=
+ eSIR_SUCCESS) {
+ PELOGE(lim_log
+ (pMac, LOGE,
+ FL
+ ("could not retrieve WNI_CFG_HEART_BEAT_THRESHOLD CFG"));
+ )
+ return eSIR_FAILURE;
+ }
+ if (!val1) {
+ pMac->sys.gSysEnableLinkMonitorMode = 0;
+ } else {
+ /* No need to activate the timer during init time. */
+ pMac->sys.gSysEnableLinkMonitorMode = 1;
+ }
+
+ /* WNI_CFG_SHORT_GI_20MHZ */
+
+ if (wlan_cfg_get_int(pMac, WNI_CFG_HT_CAP_INFO, &val1) != eSIR_SUCCESS) {
+ PELOGE(lim_log(pMac, LOGE, FL("could not retrieve HT Cap CFG"));)
+ return eSIR_FAILURE;
+ }
+ if (wlan_cfg_get_int(pMac, WNI_CFG_SHORT_GI_20MHZ, &val2) != eSIR_SUCCESS) {
+ PELOGE(lim_log
+ (pMac, LOGE, FL("could not retrieve shortGI 20Mhz CFG"));
+ )
+ return eSIR_FAILURE;
+ }
+ if (wlan_cfg_get_int(pMac, WNI_CFG_SHORT_GI_40MHZ, &val3) != eSIR_SUCCESS) {
+ PELOGE(lim_log
+ (pMac, LOGE, FL("could not retrieve shortGI 40Mhz CFG"));
+ )
+ return eSIR_FAILURE;
+ }
+
+ val16 = (uint16_t) val1;
+ pHTCapabilityInfo = (tSirMacHTCapabilityInfo *) &val16;
+ pHTCapabilityInfo->shortGI20MHz = (uint16_t) val2;
+ pHTCapabilityInfo->shortGI40MHz = (uint16_t) val3;
+
+ if (cfg_set_int
+ (pMac, WNI_CFG_HT_CAP_INFO,
+ *(uint16_t *) pHTCapabilityInfo) != eSIR_SUCCESS) {
+ PELOGE(lim_log
+ (pMac, LOGE, FL("could not update HT Cap Info CFG"));
+ )
+ return eSIR_FAILURE;
+ }
+
+ /* WNI_CFG_MAX_RX_AMPDU_FACTOR */
+
+ if (wlan_cfg_get_int(pMac, WNI_CFG_HT_AMPDU_PARAMS, &val1) !=
+ eSIR_SUCCESS) {
+ PELOGE(lim_log
+ (pMac, LOGE,
+ FL("could not retrieve HT AMPDU Param CFG"));
+ )
+ return eSIR_FAILURE;
+ }
+ if (wlan_cfg_get_int(pMac, WNI_CFG_MAX_RX_AMPDU_FACTOR, &val2) !=
+ eSIR_SUCCESS) {
+ PELOGE(lim_log
+ (pMac, LOGE, FL("could not retrieve AMPDU Factor CFG"));
+ )
+ return eSIR_FAILURE;
+ }
+ val16 = (uint16_t) val1;
+ pAmpduParamInfo = (tSirMacHTParametersInfo *) &val16;
+ pAmpduParamInfo->maxRxAMPDUFactor = (uint8_t) val2;
+ if (cfg_set_int
+ (pMac, WNI_CFG_HT_AMPDU_PARAMS,
+ *(uint8_t *) pAmpduParamInfo) != eSIR_SUCCESS) {
+ lim_log(pMac, LOGE, FL("cfg get short preamble failed"));
+ return eSIR_FAILURE;
+ }
+
+ /* WNI_CFG_SHORT_PREAMBLE - this one is not updated in
+ lim_handle_cf_gparam_update do we want to update this? */
+ if (wlan_cfg_get_int(pMac, WNI_CFG_SHORT_PREAMBLE, &val1) != eSIR_SUCCESS) {
+ lim_log(pMac, LOGP, FL("cfg get short preamble failed"));
+ return eSIR_FAILURE;
+ }
+
+ /* WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA - not needed */
+
+ /* This was initially done after resume notification from HAL. Now, DAL is
+ started before PE so this can be done here */
+ handle_ht_capabilityand_ht_info(pMac, NULL);
+ if (eSIR_SUCCESS !=
+ wlan_cfg_get_int(pMac, WNI_CFG_DISABLE_LDPC_WITH_TXBF_AP,
+ (uint32_t *) &pMac->lim.disableLDPCWithTxbfAP)) {
+ lim_log(pMac, LOGP, FL("cfg get disableLDPCWithTxbfAP failed"));
+ return eSIR_FAILURE;
+ }
+#ifdef FEATURE_WLAN_TDLS
+ if (eSIR_SUCCESS != wlan_cfg_get_int(pMac, WNI_CFG_TDLS_BUF_STA_ENABLED,
+ (uint32_t *) &pMac->lim.
+ gLimTDLSBufStaEnabled)) {
+ lim_log(pMac, LOGP, FL("cfg get LimTDLSBufStaEnabled failed"));
+ return eSIR_FAILURE;
+ }
+ if (eSIR_SUCCESS !=
+ wlan_cfg_get_int(pMac, WNI_CFG_TDLS_QOS_WMM_UAPSD_MASK,
+ (uint32_t *) &pMac->lim.gLimTDLSUapsdMask)) {
+ lim_log(pMac, LOGP, FL("cfg get LimTDLSUapsdMask failed"));
+ return eSIR_FAILURE;
+ }
+ if (eSIR_SUCCESS !=
+ wlan_cfg_get_int(pMac, WNI_CFG_TDLS_OFF_CHANNEL_ENABLED,
+ (uint32_t *) &pMac->lim.
+ gLimTDLSOffChannelEnabled)) {
+ lim_log(pMac, LOGP, FL("cfg get LimTDLSUapsdMask failed"));
+ return eSIR_FAILURE;
+ }
+
+ if (eSIR_SUCCESS != wlan_cfg_get_int(pMac, WNI_CFG_TDLS_WMM_MODE_ENABLED,
+ (uint32_t *) &pMac->lim.
+ gLimTDLSWmmMode)) {
+ lim_log(pMac, LOGP, FL("cfg get LimTDLSWmmMode failed"));
+ return eSIR_FAILURE;
+ }
+#endif
+ return eSIR_SUCCESS;
+}
+
+/*
+ lim_start
+ This function is to replace the __lim_process_sme_start_req since there is no
+ eWNI_SME_START_REQ post to PE.
+ */
+tSirRetStatus lim_start(tpAniSirGlobal pMac)
+{
+ tSirResultCodes retCode = eSIR_SUCCESS;
+
+ PELOG1(lim_log(pMac, LOG1, FL(" enter"));)
+
+ if (pMac->lim.gLimSmeState == eLIM_SME_OFFLINE_STATE) {
+ pMac->lim.gLimSmeState = eLIM_SME_IDLE_STATE;
+
+ MTRACE(mac_trace
+ (pMac, TRACE_CODE_SME_STATE, NO_SESSION,
+ pMac->lim.gLimSmeState));
+
+ /* By default do not return after first scan match */
+ pMac->lim.gLimReturnAfterFirstMatch = 0;
+
+ /* Initialize MLM state machine */
+ lim_init_mlm(pMac);
+
+ /* By default return unique scan results */
+ pMac->lim.gLimReturnUniqueResults = true;
+ } else {
+ /**
+ * Should not have received eWNI_SME_START_REQ in states
+ * other than OFFLINE. Return response to host and
+ * log error
+ */
+ lim_log(pMac, LOGE, FL("Invalid SME state %X"),
+ pMac->lim.gLimSmeState);
+ retCode = eSIR_FAILURE;
+ }
+
+ return retCode;
+}
+
+/**
+ * lim_initialize()
+ *
+ ***FUNCTION:
+ * This function is called from LIM thread entry function.
+ * LIM related global data structures are initialized in this function.
+ *
+ ***LOGIC:
+ * NA
+ *
+ ***ASSUMPTIONS:
+ * NA
+ *
+ ***NOTE:
+ * NA
+ *
+ * @param pMac - Pointer to global MAC structure
+ * @return None
+ */
+
+tSirRetStatus lim_initialize(tpAniSirGlobal pMac)
+{
+ tSirRetStatus status = eSIR_SUCCESS;
+
+ __lim_init_assoc_vars(pMac);
+ __lim_init_vars(pMac);
+ __lim_init_states(pMac);
+ __lim_init_stats_vars(pMac);
+ __lim_init_bss_vars(pMac);
+ __lim_init_scan_vars(pMac);
+ __lim_init_ht_vars(pMac);
+
+ status = lim_start(pMac);
+ if (eSIR_SUCCESS != status) {
+ return status;
+ }
+ /* Initializations for maintaining peers in IBSS */
+ lim_ibss_init(pMac);
+
+#if defined WLAN_FEATURE_VOWIFI
+ rrm_initialize(pMac);
+#endif
+
+ cdf_mutex_init(&pMac->lim.lim_frame_register_lock);
+ cdf_list_init(&pMac->lim.gLimMgmtFrameRegistratinQueue, 0);
+
+ /* Initialize the configurations needed by PE */
+ if (eSIR_FAILURE == __lim_init_config(pMac)) {
+ /* We need to undo everything in lim_start */
+ lim_cleanup_mlm(pMac);
+ return eSIR_FAILURE;
+ }
+ /* initialize the TSPEC admission control table. */
+ /* Note that this was initially done after resume notification from HAL. */
+ /* Now, DAL is started before PE so this can be done here */
+ lim_admit_control_init(pMac);
+ lim_register_hal_ind_call_back(pMac);
+
+ return status;
+
+} /*** end lim_initialize() ***/
+
+/**
+ * lim_cleanup()
+ *
+ ***FUNCTION:
+ * This function is called upon reset or persona change
+ * to cleanup LIM state
+ *
+ ***LOGIC:
+ * NA
+ *
+ ***ASSUMPTIONS:
+ * NA
+ *
+ ***NOTE:
+ * NA
+ *
+ * @param pMac - Pointer to Global MAC structure
+ * @return None
+ */
+
+void lim_cleanup(tpAniSirGlobal pMac)
+{
+ void *p_cds_gctx;
+ CDF_STATUS retStatus;
+
+ /*Before destroying the list making sure all the nodes have been deleted
+ *Which should be the normal case, but a memory leak has been reported
+ */
+
+ struct mgmt_frm_reg_info *pLimMgmtRegistration = NULL;
+
+ if (CDF_FTM_MODE != cds_get_conparam()) {
+ cdf_mutex_acquire(&pMac->lim.lim_frame_register_lock);
+ while (cdf_list_remove_front(
+ &pMac->lim.gLimMgmtFrameRegistratinQueue,
+ (cdf_list_node_t **) &pLimMgmtRegistration) ==
+ CDF_STATUS_SUCCESS) {
+ CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_INFO,
+ FL("Fixing leak! Deallocating pLimMgmtRegistration node"));
+ cdf_mem_free(pLimMgmtRegistration);
+ }
+ cdf_mutex_release(&pMac->lim.lim_frame_register_lock);
+ cdf_list_destroy(&pMac->lim.gLimMgmtFrameRegistratinQueue);
+ }
+
+ lim_cleanup_mlm(pMac);
+ lim_cleanup_lmm(pMac);
+
+ /* free up preAuth table */
+ if (pMac->lim.gLimPreAuthTimerTable.pTable != NULL) {
+ cdf_mem_free(pMac->lim.gLimPreAuthTimerTable.pTable);
+ pMac->lim.gLimPreAuthTimerTable.pTable = NULL;
+ pMac->lim.gLimPreAuthTimerTable.numEntry = 0;
+ }
+
+ if (NULL != pMac->lim.pDialogueTokenHead) {
+ lim_delete_dialogue_token_list(pMac);
+ }
+
+ if (NULL != pMac->lim.pDialogueTokenTail) {
+ cdf_mem_free(pMac->lim.pDialogueTokenTail);
+ pMac->lim.pDialogueTokenTail = NULL;
+ }
+
+ if (pMac->lim.gpLimMlmSetKeysReq != NULL) {
+ cdf_mem_free(pMac->lim.gpLimMlmSetKeysReq);
+ pMac->lim.gpLimMlmSetKeysReq = NULL;
+ }
+
+ if (pMac->lim.gpLimMlmAuthReq != NULL) {
+ cdf_mem_free(pMac->lim.gpLimMlmAuthReq);
+ pMac->lim.gpLimMlmAuthReq = NULL;
+ }
+
+ if (pMac->lim.gpDefdSmeMsgForNOA != NULL) {
+ cdf_mem_free(pMac->lim.gpDefdSmeMsgForNOA);
+ pMac->lim.gpDefdSmeMsgForNOA = NULL;
+ }
+
+ if (pMac->lim.gpLimMlmScanReq != NULL) {
+ cdf_mem_free(pMac->lim.gpLimMlmScanReq);
+ pMac->lim.gpLimMlmScanReq = NULL;
+ }
+ /* Now, finally reset the deferred message queue pointers */
+ lim_reset_deferred_msg_q(pMac);
+
+ p_cds_gctx = cds_get_global_context();
+ retStatus = wma_de_register_mgmt_frm_client(p_cds_gctx);
+
+ if (retStatus != CDF_STATUS_SUCCESS)
+ PELOGE(lim_log
+ (pMac, LOGE,
+ FL
+ ("DeRegistering the PE Handle with wma has failed bailing out..."));
+ )
+#if defined WLAN_FEATURE_VOWIFI
+ rrm_cleanup(pMac);
+#endif
+
+#if defined WLAN_FEATURE_VOWIFI_11R
+ lim_ft_cleanup_all_ft_sessions(pMac);
+#endif
+
+} /*** end lim_cleanup() ***/
+
+/** -------------------------------------------------------------
+ \fn pe_open
+ \brief will be called in Open sequence from mac_open
+ \param tpAniSirGlobal pMac
+ \param tHalOpenParameters *pHalOpenParam
+ \return tSirRetStatus
+ -------------------------------------------------------------*/
+
+tSirRetStatus pe_open(tpAniSirGlobal pMac, tMacOpenParameters *pMacOpenParam)
+{
+ tSirRetStatus status = eSIR_SUCCESS;
+
+ if (eDRIVER_TYPE_MFG == pMacOpenParam->driverType)
+ return eSIR_SUCCESS;
+
+ pMac->lim.maxBssId = pMacOpenParam->maxBssId;
+ pMac->lim.maxStation = pMacOpenParam->maxStation;
+
+ if ((pMac->lim.maxBssId == 0) || (pMac->lim.maxStation == 0)) {
+ PELOGE(lim_log(pMac, LOGE,
+ FL("max number of Bssid or Stations cannot be zero!"));)
+ return eSIR_FAILURE;
+ }
+
+ pMac->lim.limTimers.gpLimCnfWaitTimer =
+ cdf_mem_malloc(sizeof(TX_TIMER) * (pMac->lim.maxStation + 1));
+ if (NULL == pMac->lim.limTimers.gpLimCnfWaitTimer) {
+ PELOGE(lim_log(pMac, LOGE,
+ FL("gpLimCnfWaitTimer memory allocate failed!"));)
+ return eSIR_MEM_ALLOC_FAILED;
+ }
+
+ pMac->lim.gpSession =
+ cdf_mem_malloc(sizeof(tPESession) * pMac->lim.maxBssId);
+ if (NULL == pMac->lim.gpSession) {
+ lim_log(pMac, LOGE,
+ FL("gpSession memory allocate failed!"));
+ status = eSIR_MEM_ALLOC_FAILED;
+ goto pe_open_psession_fail;
+ }
+
+ cdf_mem_set(pMac->lim.gpSession,
+ sizeof(tPESession) * pMac->lim.maxBssId, 0);
+
+ pMac->lim.mgmtFrameSessionId = 0xff;
+ pMac->lim.deferredMsgCnt = 0;
+
+ if (!CDF_IS_STATUS_SUCCESS(cdf_mutex_init(&pMac->lim.lkPeGlobalLock))) {
+ PELOGE(lim_log(pMac, LOGE, FL("pe lock init failed!"));)
+ status = eSIR_FAILURE;
+ goto pe_open_lock_fail;
+ }
+ pMac->lim.deauthMsgCnt = 0;
+ pMac->lim.retry_packet_cnt = 0;
+ pMac->lim.ibss_retry_cnt = 0;
+
+ /*
+ * pe_open is successful by now, so it is right time to initialize
+ * MTRACE for PE module. if LIM_TRACE_RECORD is not defined in build
+ * file then nothing will be logged for PE module.
+ */
+#ifdef LIM_TRACE_RECORD
+ MTRACE(lim_trace_init(pMac));
+#endif
+ return status; /* status here will be eSIR_SUCCESS */
+
+pe_open_lock_fail:
+ cdf_mem_free(pMac->lim.gpSession);
+ pMac->lim.gpSession = NULL;
+pe_open_psession_fail:
+ cdf_mem_free(pMac->lim.limTimers.gpLimCnfWaitTimer);
+ pMac->lim.limTimers.gpLimCnfWaitTimer = NULL;
+
+ return status;
+}
+
+/** -------------------------------------------------------------
+ \fn pe_close
+ \brief will be called in close sequence from mac_close
+ \param tpAniSirGlobal pMac
+ \return tSirRetStatus
+ -------------------------------------------------------------*/
+
+tSirRetStatus pe_close(tpAniSirGlobal pMac)
+{
+ uint8_t i;
+
+ if (ANI_DRIVER_TYPE(pMac) == eDRIVER_TYPE_MFG)
+ return eSIR_SUCCESS;
+
+ for (i = 0; i < pMac->lim.maxBssId; i++) {
+ if (pMac->lim.gpSession[i].valid == true) {
+ pe_delete_session(pMac, &pMac->lim.gpSession[i]);
+ }
+ }
+ cdf_mem_free(pMac->lim.limTimers.gpLimCnfWaitTimer);
+ pMac->lim.limTimers.gpLimCnfWaitTimer = NULL;
+
+ if (pMac->lim.gpLimMlmOemDataReq) {
+ cdf_mem_free(pMac->lim.gpLimMlmOemDataReq);
+ pMac->lim.gpLimMlmOemDataReq = NULL;
+ }
+
+ cdf_mem_free(pMac->lim.gpSession);
+ pMac->lim.gpSession = NULL;
+ if (!CDF_IS_STATUS_SUCCESS
+ (cdf_mutex_destroy(&pMac->lim.lkPeGlobalLock))) {
+ return eSIR_FAILURE;
+ }
+ return eSIR_SUCCESS;
+}
+
+/** -------------------------------------------------------------
+ \fn pe_start
+ \brief will be called in start sequence from mac_start
+ \param tpAniSirGlobal pMac
+ \return none
+ -------------------------------------------------------------*/
+
+tSirRetStatus pe_start(tpAniSirGlobal pMac)
+{
+ tSirRetStatus status = eSIR_SUCCESS;
+
+ status = lim_initialize(pMac);
+ return status;
+}
+
+/** -------------------------------------------------------------
+ \fn pe_stop
+ \brief will be called in stop sequence from mac_stop
+ \param tpAniSirGlobal pMac
+ \return none
+ -------------------------------------------------------------*/
+
+void pe_stop(tpAniSirGlobal pMac)
+{
+ lim_cleanup(pMac);
+ SET_LIM_MLM_STATE(pMac, eLIM_MLM_OFFLINE_STATE);
+ return;
+}
+
+/** -------------------------------------------------------------
+ \fn pe_free_msg
+ \brief Called by CDS scheduler (function cds_sched_flush_mc_mqs)
+ \ to free a given PE message on the TX and MC thread.
+ \ This happens when there are messages pending in the PE
+ \ queue when system is being stopped and reset.
+ \param tpAniSirGlobal pMac
+ \param tSirMsgQ pMsg
+ \return none
+ -----------------------------------------------------------------*/
+void pe_free_msg(tpAniSirGlobal pMac, tSirMsgQ *pMsg)
+{
+ if (pMsg != NULL) {
+ if (NULL != pMsg->bodyptr) {
+ if (SIR_BB_XPORT_MGMT_MSG == pMsg->type) {
+ cds_pkt_return_packet((cds_pkt_t *) pMsg->
+ bodyptr);
+ } else {
+ cdf_mem_free((void *)pMsg->bodyptr);
+ }
+ }
+ pMsg->bodyptr = 0;
+ pMsg->bodyval = 0;
+ pMsg->type = 0;
+ }
+ return;
+}
+
+/**
+ * lim_post_msg_api()
+ *
+ ***FUNCTION:
+ * This function is called from other thread while posting a
+ * message to LIM message Queue gSirLimMsgQ.
+ *
+ ***LOGIC:
+ * NA
+ *
+ ***ASSUMPTIONS:
+ * NA
+ *
+ ***NOTE:
+ * NA
+ *
+ * @param pMac - Pointer to Global MAC structure
+ * @param pMsg - Pointer to the message structure
+ * @return None
+ */
+
+uint32_t lim_post_msg_api(tpAniSirGlobal pMac, tSirMsgQ *pMsg)
+{
+ return cds_mq_post_message(CDS_MQ_ID_PE, (cds_msg_t *) pMsg);
+
+} /*** end lim_post_msg_api() ***/
+
+/*--------------------------------------------------------------------------
+
+ \brief pe_post_msg_api() - A wrapper function to post message to Voss msg queues
+
+ This function can be called by legacy code to post message to cds queues OR
+ legacy code may keep on invoking 'lim_post_msg_api' to post the message to cds queue
+ for dispatching it later.
+
+ \param pMac - Pointer to Global MAC structure
+ \param pMsg - Pointer to the message structure
+
+ \return uint32_t - TX_SUCCESS for success.
+
+ --------------------------------------------------------------------------*/
+
+tSirRetStatus pe_post_msg_api(tpAniSirGlobal pMac, tSirMsgQ *pMsg)
+{
+ return (tSirRetStatus) lim_post_msg_api(pMac, pMsg);
+}
+
+/*--------------------------------------------------------------------------
+
+ \brief pe_process_messages() - Message Processor for PE
+
+ Voss calls this function to dispatch the message to PE
+
+ \param pMac - Pointer to Global MAC structure
+ \param pMsg - Pointer to the message structure
+
+ \return uint32_t - TX_SUCCESS for success.
+
+ --------------------------------------------------------------------------*/
+
+tSirRetStatus pe_process_messages(tpAniSirGlobal pMac, tSirMsgQ *pMsg)
+{
+ if (ANI_DRIVER_TYPE(pMac) == eDRIVER_TYPE_MFG) {
+ return eSIR_SUCCESS;
+ }
+ /**
+ * If the Message to be handled is for CFG Module call the CFG Msg
+ * Handler and for all the other cases post it to LIM
+ */
+ if (SIR_CFG_PARAM_UPDATE_IND != pMsg->type && IS_CFG_MSG(pMsg->type))
+ cfg_process_mb_msg(pMac, (tSirMbMsg *) pMsg->bodyptr);
+ else
+ lim_message_processor(pMac, pMsg);
+ return eSIR_SUCCESS;
+}
+
+/* --------------------------------------------------------------------------- */
+/**
+ * pe_handle_mgmt_frame
+ *
+ * FUNCTION:
+ * Process the Management frames from TL
+ *
+ * LOGIC:
+ *
+ * ASSUMPTIONS: TL sends the packet along with the CDS GlobalContext
+ *
+ * NOTE:
+ *
+ * @param p_cds_gctx Global Vos Context
+ * @param cds_buff Packet
+ * @return None
+ */
+
+CDF_STATUS pe_handle_mgmt_frame(void *p_cds_gctx, void *cds_buff)
+{
+ tpAniSirGlobal pMac;
+ tpSirMacMgmtHdr mHdr;
+ tSirMsgQ msg;
+ cds_pkt_t *pVosPkt;
+ CDF_STATUS cdf_status;
+ uint8_t *pRxPacketInfo;
+
+ pVosPkt = (cds_pkt_t *) cds_buff;
+ if (NULL == pVosPkt) {
+ return CDF_STATUS_E_FAILURE;
+ }
+
+ pMac = cds_get_context(CDF_MODULE_ID_PE);
+ if (NULL == pMac) {
+ /* cannot log a failure without a valid pMac */
+ cds_pkt_return_packet(pVosPkt);
+ pVosPkt = NULL;
+ return CDF_STATUS_E_FAILURE;
+ }
+
+ cdf_status =
+ wma_ds_peek_rx_packet_info(pVosPkt, (void *)&pRxPacketInfo, false);
+
+ if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
+ cds_pkt_return_packet(pVosPkt);
+ pVosPkt = NULL;
+ return CDF_STATUS_E_FAILURE;
+ }
+
+ /*
+ * The MPDU header is now present at a certain "offset" in
+ * the BD and is specified in the BD itself
+ */
+
+ mHdr = WMA_GET_RX_MAC_HEADER(pRxPacketInfo);
+ if (mHdr->fc.type == SIR_MAC_MGMT_FRAME) {
+ lim_log(pMac, LOG1, FL
+ ("RxBd=%p mHdr=%p Type: %d Subtype: %d Sizes:FC%zu Mgmt%zu"),
+ pRxPacketInfo, mHdr, mHdr->fc.type, mHdr->fc.subType,
+ sizeof(tSirMacFrameCtl), sizeof(tSirMacMgmtHdr));
+
+ lim_log(pMac, LOG1, FL("mpdu_len:%d hdr_len:%d data_len:%d"),
+ WMA_GET_RX_MPDU_LEN(pRxPacketInfo),
+ WMA_GET_RX_MPDU_HEADER_LEN(pRxPacketInfo),
+ WMA_GET_RX_PAYLOAD_LEN(pRxPacketInfo));
+
+ MTRACE(mac_trace(pMac, TRACE_CODE_RX_MGMT,
+ WMA_GET_RX_PAYLOAD_LEN(pRxPacketInfo),
+ LIM_TRACE_MAKE_RXMGMT(mHdr->fc.subType,
+ (uint16_t) (((uint16_t)
+ (mHdr->seqControl.seqNumHi << 4)) |
+ mHdr->seqControl.seqNumLo)));)
+
+ if (WMA_GET_ROAMCANDIDATEIND(pRxPacketInfo))
+ lim_log(pMac, LOG1, FL("roamCandidateInd %d"),
+ WMA_GET_ROAMCANDIDATEIND(pRxPacketInfo));
+
+ if (WMA_GET_OFFLOADSCANLEARN(pRxPacketInfo))
+ lim_log(pMac, LOG1, FL("offloadScanLearn %d"),
+ WMA_GET_OFFLOADSCANLEARN(pRxPacketInfo));
+ }
+
+ /* Forward to MAC via mesg = SIR_BB_XPORT_MGMT_MSG */
+ msg.type = SIR_BB_XPORT_MGMT_MSG;
+ msg.bodyptr = cds_buff;
+ msg.bodyval = 0;
+
+ if (eSIR_SUCCESS != sys_bbt_process_message_core(pMac,
+ &msg,
+ mHdr->fc.type,
+ mHdr->fc.subType)) {
+ cds_pkt_return_packet(pVosPkt);
+ pVosPkt = NULL;
+ lim_log(pMac, LOGW,
+ FL
+ ("sys_bbt_process_message_core failed to process SIR_BB_XPORT_MGMT_MSG"));
+ return CDF_STATUS_E_FAILURE;
+ }
+
+ return CDF_STATUS_SUCCESS;
+}
+
+/**
+ * pe_register_wma_handle() - register management frame handler to WMA
+ * @pMac: mac global ctx
+ *
+ * Return: None
+ */
+void pe_register_wma_handle(tpAniSirGlobal pMac)
+{
+ void *p_cds_gctx;
+ CDF_STATUS retStatus;
+
+ p_cds_gctx = cds_get_global_context();
+
+ retStatus = wma_register_mgmt_frm_client(p_cds_gctx,
+ pe_handle_mgmt_frame);
+ if (retStatus != CDF_STATUS_SUCCESS)
+ lim_log(pMac, LOGP,
+ FL("Registering the PE Handle with WMA has failed"));
+
+}
+
+/**
+ * lim_is_system_in_scan_state()
+ *
+ ***FUNCTION:
+ * This function is called by various MAC software modules to
+ * determine if System is in Scan/Learn state
+ *
+ ***LOGIC:
+ * NA
+ *
+ ***ASSUMPTIONS:
+ * NA
+ *
+ ***NOTE:
+ *
+ * @param pMac - Pointer to Global MAC structure
+ * @return true - System is in Scan/Learn state
+ * false - System is NOT in Scan/Learn state
+ */
+
+uint8_t lim_is_system_in_scan_state(tpAniSirGlobal pMac)
+{
+ switch (pMac->lim.gLimSmeState) {
+ case eLIM_SME_CHANNEL_SCAN_STATE:
+ case eLIM_SME_NORMAL_CHANNEL_SCAN_STATE:
+ case eLIM_SME_LINK_EST_WT_SCAN_STATE:
+ case eLIM_SME_WT_SCAN_STATE:
+ /* System is in Learn mode */
+ return true;
+
+ default:
+ /* System is NOT in Learn mode */
+ return false;
+ }
+} /*** end lim_is_system_in_scan_state() ***/
+
+#ifdef WLAN_FEATURE_11W
+/**
+ * lim_is_assoc_req_for_drop()- function to decides to drop assoc\reassoc
+ * frames.
+ * @mac: pointer to global mac structure
+ * @rx_pkt_info: rx packet meta information
+ *
+ * This function is called before enqueuing the frame to PE queue to
+ * drop flooded assoc/reassoc frames getting into PE Queue.
+ *
+ * Return: true for dropping the frame otherwise false
+ */
+
+bool lim_is_assoc_req_for_drop(tpAniSirGlobal mac, uint8_t *rx_pkt_info)
+{
+ uint8_t session_id;
+ uint16_t aid;
+ tpPESession session_entry;
+ tpSirMacMgmtHdr mac_hdr;
+ tpDphHashNode sta_ds;
+
+ mac_hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info);
+ session_entry = pe_find_session_by_bssid(mac, mac_hdr->bssId,
+ &session_id);
+ if (!session_entry) {
+ PELOG1(limLog(pMac, LOG1,
+ FL("session does not exist for given STA [%pM]"),
+ mac_hdr->sa););
+ return false;
+ }
+
+ sta_ds = dph_lookup_hash_entry(mac, mac_hdr->sa, &aid,
+ &session_entry->dph.dphHashTable);
+ if (!sta_ds) {
+ PELOG1(limLog(pMac, LOG1, FL("pStaDs is NULL")););
+ return false;
+ }
+
+ if (!sta_ds->rmfEnabled)
+ return false;
+
+ if (sta_ds->pmfSaQueryState == DPH_SA_QUERY_IN_PROGRESS)
+ return true;
+
+ if (sta_ds->last_assoc_received_time &&
+ ((cdf_mc_timer_get_system_ticks() -
+ sta_ds->last_assoc_received_time) < 1000))
+ return true;
+
+ sta_ds->last_assoc_received_time = cdf_mc_timer_get_system_ticks();
+ return false;
+}
+#endif
+
+/**
+ * lim_is_deauth_diassoc_for_drop()- function to decides to drop deauth\diassoc
+ * frames.
+ * @mac: pointer to global mac structure
+ * @rx_pkt_info: rx packet meta information
+ *
+ * This function is called before enqueuing the frame to PE queue to
+ * drop flooded deauth/diassoc frames getting into PE Queue.
+ *
+ * Return: true for dropping the frame otherwise false
+ */
+
+bool lim_is_deauth_diassoc_for_drop(tpAniSirGlobal mac, uint8_t *rx_pkt_info)
+{
+ uint8_t session_id;
+ uint16_t aid;
+ tpPESession session_entry;
+ tpSirMacMgmtHdr mac_hdr;
+ tpDphHashNode sta_ds;
+
+ mac_hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info);
+ session_entry = pe_find_session_by_bssid(mac, mac_hdr->bssId,
+ &session_id);
+ if (!session_entry) {
+ PELOG1(limLog(mac, LOG1,
+ FL("session does not exist for given STA [%pM]"),
+ mac_hdr->sa););
+ return true;
+ }
+
+ sta_ds = dph_lookup_hash_entry(mac, mac_hdr->sa, &aid,
+ &session_entry->dph.dphHashTable);
+ if (!sta_ds) {
+ PELOG1(limLog(mac, LOG1, FL("pStaDs is NULL")););
+ return true;
+ }
+
+#ifdef WLAN_FEATURE_11W
+ if (session_entry->limRmfEnabled) {
+ if ((WMA_GET_RX_DPU_FEEDBACK(rx_pkt_info) &
+ DPU_FEEDBACK_UNPROTECTED_ERROR)) {
+ /* It may be possible that deauth/diassoc frames from a
+ * spoofy AP is received. So if all further
+ * deauth/diassoc frmaes are dropped, then it may
+ * result in lossing deauth/diassoc frames from genuine
+ * AP. So process all deauth/diassoc frames with
+ * a time difference of 1 sec.
+ */
+ if ((cdf_mc_timer_get_system_ticks() -
+ sta_ds->last_unprot_deauth_disassoc) < 1000)
+ return true;
+
+ sta_ds->last_unprot_deauth_disassoc =
+ cdf_mc_timer_get_system_ticks();
+ } else {
+ /* PMF enabed, Management frames are protected */
+ if (sta_ds->proct_deauh_disassoc_cnt)
+ return true;
+ else
+ sta_ds->proct_deauh_disassoc_cnt++;
+ }
+ } else
+#endif
+ /* PMF disabled */
+ {
+ if (sta_ds->is_disassoc_deauth_in_progress)
+ return true;
+ else
+ sta_ds->is_disassoc_deauth_in_progress++;
+ }
+
+ return false;
+}
+
+/**
+ *\brief lim_received_hb_handler()
+ *
+ * This function is called by sch_beacon_process() upon
+ * receiving a Beacon on STA. This also gets called upon
+ * receiving Probe Response after heat beat failure is
+ * detected.
+ *
+ * param pMac - global mac structure
+ * param channel - channel number indicated in Beacon, Probe Response
+ * return - none
+ */
+
+void
+lim_received_hb_handler(tpAniSirGlobal pMac, uint8_t channelId,
+ tpPESession psessionEntry)
+{
+ if ((channelId == 0)
+ || (channelId == psessionEntry->currentOperChannel))
+ psessionEntry->LimRxedBeaconCntDuringHB++;
+
+ psessionEntry->pmmOffloadInfo.bcnmiss = false;
+} /*** lim_init_wds_info_params() ***/
+
+/** -------------------------------------------------------------
+ \fn lim_update_overlap_sta_param
+ \brief Updates overlap cache and param data structure
+ \param tpAniSirGlobal pMac
+ \param tSirMacAddr bssId
+ \param tpLimProtStaParams pStaParams
+ \return None
+ -------------------------------------------------------------*/
+void
+lim_update_overlap_sta_param(tpAniSirGlobal pMac, tSirMacAddr bssId,
+ tpLimProtStaParams pStaParams)
+{
+ int i;
+ if (!pStaParams->numSta) {
+ cdf_mem_copy(pMac->lim.protStaOverlapCache[0].addr,
+ bssId, sizeof(tSirMacAddr));
+ pMac->lim.protStaOverlapCache[0].active = true;
+
+ pStaParams->numSta = 1;
+
+ return;
+ }
+
+ for (i = 0; i < LIM_PROT_STA_OVERLAP_CACHE_SIZE; i++) {
+ if (pMac->lim.protStaOverlapCache[i].active) {
+ if (cdf_mem_compare
+ (pMac->lim.protStaOverlapCache[i].addr, bssId,
+ sizeof(tSirMacAddr))) {
+ return;
+ }
+ } else
+ break;
+ }
+
+ if (i == LIM_PROT_STA_OVERLAP_CACHE_SIZE) {
+ PELOG1(lim_log(pMac, LOGW, FL("Overlap cache is full"));)
+ } else {
+ cdf_mem_copy(pMac->lim.protStaOverlapCache[i].addr,
+ bssId, sizeof(tSirMacAddr));
+ pMac->lim.protStaOverlapCache[i].active = true;
+
+ pStaParams->numSta++;
+ }
+}
+
+/**
+ * lim_ibss_enc_type_matched
+ *
+ ***FUNCTION:
+ * This function compares the encryption type of the peer with self
+ * while operating in IBSS mode and detects mismatch.
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ *
+ ***NOTE:
+ *
+ * @param pBeacon - Parsed Beacon Frame structure
+ * @param pSession - Pointer to the PE session
+ *
+ * @return eSIR_TRUE if encryption type is matched; eSIR_FALSE otherwise
+ */
+static tAniBool lim_ibss_enc_type_matched(tpSchBeaconStruct pBeacon,
+ tpPESession pSession)
+{
+ if (!pBeacon || !pSession)
+ return eSIR_FALSE;
+
+ /* Open case */
+ if (pBeacon->capabilityInfo.privacy == 0
+ && pSession->encryptType == eSIR_ED_NONE)
+ return eSIR_TRUE;
+
+ /* WEP case */
+ if (pBeacon->capabilityInfo.privacy == 1 && pBeacon->wpaPresent == 0
+ && pBeacon->rsnPresent == 0
+ && (pSession->encryptType == eSIR_ED_WEP40
+ || pSession->encryptType == eSIR_ED_WEP104))
+ return eSIR_TRUE;
+
+ /* WPA-None case */
+ if (pBeacon->capabilityInfo.privacy == 1 && pBeacon->wpaPresent == 1
+ && pBeacon->rsnPresent == 0
+ && ((pSession->encryptType == eSIR_ED_CCMP) ||
+ (pSession->encryptType == eSIR_ED_TKIP)))
+ return eSIR_TRUE;
+
+ return eSIR_FALSE;
+}
+
+/**
+ * lim_handle_ibs_scoalescing()
+ *
+ ***FUNCTION:
+ * This function is called upon receiving Beacon/Probe Response
+ * while operating in IBSS mode.
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ *
+ ***NOTE:
+ *
+ * @param pMac - Pointer to Global MAC structure
+ * @param pBeacon - Parsed Beacon Frame structure
+ * @param pRxPacketInfo - Pointer to RX packet info structure
+ *
+ * @return Status whether to process or ignore received Beacon Frame
+ */
+
+tSirRetStatus
+lim_handle_ibss_coalescing(tpAniSirGlobal pMac,
+ tpSchBeaconStruct pBeacon,
+ uint8_t *pRxPacketInfo, tpPESession psessionEntry)
+{
+ tpSirMacMgmtHdr pHdr;
+ tSirRetStatus retCode;
+
+ pHdr = WMA_GET_RX_MAC_HEADER(pRxPacketInfo);
+
+ /* Ignore the beacon when any of the conditions below is met:
+ 1. The beacon claims no IBSS network
+ 2. SSID in the beacon does not match SSID of self station
+ 3. Operational channel in the beacon does not match self station
+ 4. Encyption type in the beacon does not match with self station
+ */
+ if ((!pBeacon->capabilityInfo.ibss) ||
+ (lim_cmp_s_sid(pMac, &pBeacon->ssId, psessionEntry) != true) ||
+ (psessionEntry->currentOperChannel != pBeacon->channelNumber))
+ retCode = eSIR_LIM_IGNORE_BEACON;
+ else if (lim_ibss_enc_type_matched(pBeacon, psessionEntry) != eSIR_TRUE) {
+ PELOG3(lim_log(pMac, LOG3,
+ FL
+ ("peer privacy %d peer wpa %d peer rsn %d self encType %d"),
+ pBeacon->capabilityInfo.privacy,
+ pBeacon->wpaPresent, pBeacon->rsnPresent,
+ psessionEntry->encryptType);
+ )
+ retCode = eSIR_LIM_IGNORE_BEACON;
+ } else {
+ uint32_t ieLen;
+ uint16_t tsfLater;
+ uint8_t *pIEs;
+ ieLen = WMA_GET_RX_PAYLOAD_LEN(pRxPacketInfo);
+ tsfLater = WMA_GET_RX_TSF_LATER(pRxPacketInfo);
+ pIEs = WMA_GET_RX_MPDU_DATA(pRxPacketInfo);
+ PELOG3(lim_log
+ (pMac, LOG3, FL("BEFORE Coalescing tsfLater val :%d"),
+ tsfLater);
+ )
+ retCode =
+ lim_ibss_coalesce(pMac, pHdr, pBeacon, pIEs, ieLen, tsfLater,
+ psessionEntry);
+ }
+ return retCode;
+} /*** end lim_handle_ibs_scoalescing() ***/
+
+/**
+ * lim_enc_type_matched() - matches security type of incoming beracon with
+ * current
+ * @mac_ctx Pointer to Global MAC structure
+ * @bcn Pointer to parsed Beacon structure
+ * @session PE session entry
+ *
+ * This function matches security type of incoming beracon with current
+ *
+ * @return true if matched, false otherwise
+ */
+static bool
+lim_enc_type_matched(tpAniSirGlobal mac_ctx,
+ tpSchBeaconStruct bcn,
+ tpPESession session)
+{
+ if (!bcn || !session)
+ return false;
+
+ lim_log(mac_ctx, LOG1,
+ FL("Beacon/Probe:: Privacy :%d WPA Present:%d RSN Present: %d"),
+ bcn->capabilityInfo.privacy, bcn->wpaPresent, bcn->rsnPresent);
+ lim_log(mac_ctx, LOG1,
+ FL("session:: Privacy :%d EncyptionType: %d"),
+ SIR_MAC_GET_PRIVACY(session->limCurrentBssCaps),
+ session->encryptType);
+
+ /*
+ * This is handled by sending probe req due to IOT issues so
+ * return TRUE
+ */
+ if ((bcn->capabilityInfo.privacy) !=
+ SIR_MAC_GET_PRIVACY(session->limCurrentBssCaps)) {
+ lim_log(mac_ctx, LOGW, FL("Privacy bit miss match\n"));
+ return true;
+ }
+
+ /* Open */
+ if ((bcn->capabilityInfo.privacy == 0) &&
+ (session->encryptType == eSIR_ED_NONE))
+ return true;
+
+ /* WEP */
+ if ((bcn->capabilityInfo.privacy == 1) &&
+ (bcn->wpaPresent == 0) && (bcn->rsnPresent == 0) &&
+ ((session->encryptType == eSIR_ED_WEP40) ||
+ (session->encryptType == eSIR_ED_WEP104)
+#ifdef FEATURE_WLAN_WAPI
+ || (session->encryptType == eSIR_ED_WPI)
+#endif
+ ))
+ return true;
+
+ /* WPA OR RSN*/
+ if ((bcn->capabilityInfo.privacy == 1) &&
+ ((bcn->wpaPresent == 1) || (bcn->rsnPresent == 1)) &&
+ ((session->encryptType == eSIR_ED_TKIP) ||
+ (session->encryptType == eSIR_ED_CCMP) ||
+ (session->encryptType == eSIR_ED_AES_128_CMAC)))
+ return true;
+
+ return false;
+}
+
+/**
+ * lim_detect_change_in_ap_capabilities()
+ *
+ ***FUNCTION:
+ * This function is called while SCH is processing
+ * received Beacon from AP on STA to detect any
+ * change in AP's capabilities. If there any change
+ * is detected, Roaming is informed of such change
+ * so that it can trigger reassociation.
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ *
+ ***NOTE:
+ * Notification is enabled for STA product only since
+ * it is not a requirement on BP side.
+ *
+ * @param pMac Pointer to Global MAC structure
+ * @param pBeacon Pointer to parsed Beacon structure
+ * @return None
+ */
+
+void
+lim_detect_change_in_ap_capabilities(tpAniSirGlobal pMac,
+ tpSirProbeRespBeacon pBeacon,
+ tpPESession psessionEntry)
+{
+ uint8_t len;
+ tSirSmeApNewCaps apNewCaps;
+ uint8_t newChannel;
+ tSirRetStatus status = eSIR_SUCCESS;
+ bool security_caps_matched = true;
+
+ apNewCaps.capabilityInfo =
+ lim_get_u16((uint8_t *) &pBeacon->capabilityInfo);
+ newChannel = (uint8_t) pBeacon->channelNumber;
+
+ security_caps_matched = lim_enc_type_matched(pMac, pBeacon,
+ psessionEntry);
+ if ((false == psessionEntry->limSentCapsChangeNtf) &&
+ (((!lim_is_null_ssid(&pBeacon->ssId)) &&
+ (false == lim_cmp_s_sid(pMac, &pBeacon->ssId, psessionEntry))) ||
+ ((SIR_MAC_GET_ESS(apNewCaps.capabilityInfo) !=
+ SIR_MAC_GET_ESS(psessionEntry->limCurrentBssCaps)) ||
+ (SIR_MAC_GET_PRIVACY(apNewCaps.capabilityInfo) !=
+ SIR_MAC_GET_PRIVACY(psessionEntry->limCurrentBssCaps)) ||
+ (SIR_MAC_GET_SHORT_PREAMBLE(apNewCaps.capabilityInfo) !=
+ SIR_MAC_GET_SHORT_PREAMBLE(psessionEntry->limCurrentBssCaps)) ||
+ (SIR_MAC_GET_QOS(apNewCaps.capabilityInfo) !=
+ SIR_MAC_GET_QOS(psessionEntry->limCurrentBssCaps)) ||
+ ((newChannel != psessionEntry->currentOperChannel) &&
+ (newChannel != 0)) ||
+ (false == security_caps_matched)
+ ))) {
+ if (false == psessionEntry->fWaitForProbeRsp) {
+ /* If Beacon capabilities is not matching with the current capability,
+ * then send unicast probe request to AP and take decision after
+ * receiving probe response */
+ if (true == psessionEntry->fIgnoreCapsChange) {
+ lim_log(pMac, LOGW,
+ FL
+ ("Ignoring the Capability change as it is false alarm"));
+ return;
+ }
+ psessionEntry->fWaitForProbeRsp = true;
+ lim_log(pMac, LOGW,
+ FL("AP capabilities are not matching,"
+ "sending directed probe request.. "));
+ status =
+ lim_send_probe_req_mgmt_frame(pMac, &psessionEntry->ssId,
+ psessionEntry->bssId,
+ psessionEntry->
+ currentOperChannel,
+ psessionEntry->selfMacAddr,
+ psessionEntry->dot11mode,
+ 0, NULL);
+
+ if (eSIR_SUCCESS != status) {
+ lim_log(pMac, LOGE, FL("send ProbeReq failed"));
+ psessionEntry->fWaitForProbeRsp = false;
+ }
+ return;
+ }
+ /**
+ * BSS capabilities have changed.
+ * Inform Roaming.
+ */
+ len = sizeof(tSirMacCapabilityInfo) + sizeof(tSirMacAddr) + sizeof(uint8_t) + 3 * sizeof(uint8_t) + /* reserved fields */
+ pBeacon->ssId.length + 1;
+
+ cdf_mem_copy(apNewCaps.bssId,
+ psessionEntry->bssId, sizeof(tSirMacAddr));
+ if (newChannel != psessionEntry->currentOperChannel) {
+ PELOGE(lim_log
+ (pMac, LOGE,
+ FL("Channel Change from %d --> %d - "
+ "Ignoring beacon!"),
+ psessionEntry->currentOperChannel, newChannel);
+ )
+ return;
+ }
+
+ /**
+ * When Cisco 1262 Enterprise APs are configured with WPA2-PSK with
+ * AES+TKIP Pairwise ciphers and WEP-40 Group cipher, they do not set
+ * the privacy bit in Beacons (wpa/rsnie is still present in beacons),
+ * the privacy bit is set in Probe and association responses.
+ * Due to this anomaly, we detect a change in
+ * AP capabilities when we receive a beacon after association and
+ * disconnect from the AP. The following check makes sure that we can
+ * connect to such APs
+ */
+ else if ((SIR_MAC_GET_PRIVACY(apNewCaps.capabilityInfo) == 0) &&
+ (pBeacon->rsnPresent || pBeacon->wpaPresent)) {
+ PELOGE(lim_log
+ (pMac, LOGE,
+ FL("BSS Caps (Privacy) bit 0 in beacon,"
+ " but WPA or RSN IE present, Ignore Beacon!"));
+ )
+ return;
+ } else
+ apNewCaps.channelId = psessionEntry->currentOperChannel;
+ cdf_mem_copy((uint8_t *) &apNewCaps.ssId,
+ (uint8_t *) &pBeacon->ssId,
+ pBeacon->ssId.length + 1);
+
+ psessionEntry->fIgnoreCapsChange = false;
+ psessionEntry->fWaitForProbeRsp = false;
+ psessionEntry->limSentCapsChangeNtf = true;
+ lim_send_sme_wm_status_change_ntf(pMac, eSIR_SME_AP_CAPS_CHANGED,
+ (uint32_t *) &apNewCaps,
+ len, psessionEntry->smeSessionId);
+ } else if (true == psessionEntry->fWaitForProbeRsp) {
+ /* Only for probe response frames and matching capabilities the control
+ * will come here. If beacon is with broadcast ssid then fWaitForProbeRsp
+ * will be false, the control will not come here*/
+
+ lim_log(pMac, LOG1, FL("capabilities in probe response are"
+ "matching with the current setting,"
+ "Ignoring subsequent capability"
+ "mismatch"));
+ psessionEntry->fIgnoreCapsChange = true;
+ psessionEntry->fWaitForProbeRsp = false;
+ }
+
+} /*** lim_detect_change_in_ap_capabilities() ***/
+
+/* --------------------------------------------------------------------- */
+/**
+ * lim_update_short_slot
+ *
+ * FUNCTION:
+ * Enable/Disable short slot
+ *
+ * LOGIC:
+ *
+ * ASSUMPTIONS:
+ *
+ * NOTE:
+ *
+ * @param enable Flag to enable/disable short slot
+ * @return None
+ */
+
+tSirRetStatus lim_update_short_slot(tpAniSirGlobal pMac,
+ tpSirProbeRespBeacon pBeacon,
+ tpUpdateBeaconParams pBeaconParams,
+ tpPESession psessionEntry)
+{
+
+ tSirSmeApNewCaps apNewCaps;
+ uint32_t nShortSlot;
+ uint32_t val = 0;
+ uint32_t phyMode;
+
+ /* Check Admin mode first. If it is disabled just return */
+ if (wlan_cfg_get_int(pMac, WNI_CFG_11G_SHORT_SLOT_TIME_ENABLED, &val)
+ != eSIR_SUCCESS) {
+ lim_log(pMac, LOGP,
+ FL("cfg get WNI_CFG_11G_SHORT_SLOT_TIME failed"));
+ return eSIR_FAILURE;
+ }
+ if (val == false)
+ return eSIR_SUCCESS;
+
+ /* Check for 11a mode or 11b mode. In both cases return since slot time is constant and cannot/should not change in beacon */
+ lim_get_phy_mode(pMac, &phyMode, psessionEntry);
+ if ((phyMode == WNI_CFG_PHY_MODE_11A)
+ || (phyMode == WNI_CFG_PHY_MODE_11B))
+ return eSIR_SUCCESS;
+
+ apNewCaps.capabilityInfo =
+ lim_get_u16((uint8_t *) &pBeacon->capabilityInfo);
+
+ /* Earlier implementation: determine the appropriate short slot mode based on AP advertised modes */
+ /* when erp is present, apply short slot always unless, prot=on && shortSlot=off */
+ /* if no erp present, use short slot based on current ap caps */
+
+ /* Issue with earlier implementation : Cisco 1231 BG has shortSlot = 0, erpIEPresent and useProtection = 0 (Case4); */
+
+ /* Resolution : always use the shortSlot setting the capability info to decide slot time. */
+ /* The difference between the earlier implementation and the new one is only Case4. */
+ /*
+ ERP IE Present | useProtection | shortSlot = QC STA Short Slot
+ Case1 1 1 1 1 //AP should not advertise this combination.
+ Case2 1 1 0 0
+ Case3 1 0 1 1
+ Case4 1 0 0 0
+ Case5 0 1 1 1
+ Case6 0 1 0 0
+ Case7 0 0 1 1
+ Case8 0 0 0 0
+ */
+ nShortSlot = SIR_MAC_GET_SHORT_SLOT_TIME(apNewCaps.capabilityInfo);
+
+ if (nShortSlot != psessionEntry->shortSlotTimeSupported) {
+ /* Short slot time capability of AP has changed. Adopt to it. */
+ PELOG1(lim_log
+ (pMac, LOG1,
+ FL("Shortslot capability of AP changed: %d"),
+ nShortSlot);
+ )
+ ((tpSirMacCapabilityInfo) & psessionEntry->
+ limCurrentBssCaps)->shortSlotTime = (uint16_t) nShortSlot;
+ psessionEntry->shortSlotTimeSupported = nShortSlot;
+ pBeaconParams->fShortSlotTime = (uint8_t) nShortSlot;
+ pBeaconParams->paramChangeBitmap |=
+ PARAM_SHORT_SLOT_TIME_CHANGED;
+ }
+ return eSIR_SUCCESS;
+}
+
+
+void lim_send_heart_beat_timeout_ind(tpAniSirGlobal pMac, tpPESession psessionEntry)
+{
+ uint32_t statusCode;
+ tSirMsgQ msg;
+
+ /* Prepare and post message to LIM Message Queue */
+ msg.type = (uint16_t) SIR_LIM_HEART_BEAT_TIMEOUT;
+ msg.bodyptr = psessionEntry;
+ msg.bodyval = 0;
+ lim_log(pMac, LOGE, FL("Heartbeat failure from Fw"));
+
+ statusCode = lim_post_msg_api(pMac, &msg);
+
+ if (statusCode != eSIR_SUCCESS) {
+ lim_log(pMac, LOGE,
+ FL("posting message %X to LIM failed, reason=%d"),
+ msg.type, statusCode);
+ }
+}
+
+/**
+ * lim_ps_offload_handle_missed_beacon_ind(): handles missed beacon indication
+ * @pMac : global mac context
+ * @pMsg: message
+ *
+ * This function process the SIR_HAL_MISSED_BEACON_IND
+ * message from HAL, to do active AP probing.
+ *
+ * Return: void
+ */
+void lim_ps_offload_handle_missed_beacon_ind(tpAniSirGlobal pMac, tpSirMsgQ pMsg)
+{
+ tpSirSmeMissedBeaconInd pSirMissedBeaconInd =
+ (tpSirSmeMissedBeaconInd) pMsg->bodyptr;
+ tpPESession psessionEntry =
+ pe_find_session_by_bss_idx(pMac, pSirMissedBeaconInd->bssIdx);
+
+ if (!psessionEntry) {
+ lim_log(pMac, LOGE,
+ FL("session does not exist for given BSSId"));
+ return;
+ }
+
+ /* Set Beacon Miss in Powersave Offload */
+ psessionEntry->pmmOffloadInfo.bcnmiss = true;
+ PELOGE(lim_log(pMac, LOGE,
+ FL("Received Heart Beat Failure"));)
+
+ /* Do AP probing immediately */
+ lim_send_heart_beat_timeout_ind(pMac, psessionEntry);
+ return;
+}
+
+#ifdef WLAN_FEATURE_ROAM_OFFLOAD
+CDF_STATUS lim_roam_fill_bss_descr(tpAniSirGlobal pMac,
+ roam_offload_synch_ind *roam_offload_synch_ind_ptr)
+{
+ uint32_t ie_len = 0;
+ tpSirProbeRespBeacon parsed_frm_ptr;
+ tpSirMacMgmtHdr mac_hdr;
+ uint8_t *bcn_proberesp_ptr;
+ tSirBssDescription *bss_desc_ptr = NULL;
+
+ bcn_proberesp_ptr = (uint8_t *)roam_offload_synch_ind_ptr +
+ roam_offload_synch_ind_ptr->beaconProbeRespOffset;
+ mac_hdr = (tpSirMacMgmtHdr)bcn_proberesp_ptr;
+ parsed_frm_ptr =
+ (tpSirProbeRespBeacon) cdf_mem_malloc(sizeof(tSirProbeRespBeacon));
+ if (NULL == parsed_frm_ptr) {
+ lim_log(pMac, LOGE, "fail to allocate memory for frame");
+ return CDF_STATUS_E_NOMEM;
+ }
+
+ if (roam_offload_synch_ind_ptr->beaconProbeRespLength <=
+ SIR_MAC_HDR_LEN_3A) {
+ CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_ERROR, "%s: very"
+ "few bytes in synchInd beacon / probe resp frame! length=%d",
+ __func__, roam_offload_synch_ind_ptr->beaconProbeRespLength);
+ cdf_mem_free(parsed_frm_ptr);
+ return CDF_STATUS_E_FAILURE;
+ }
+
+ CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_INFO,
+ "LFR3: Beacon/Prb Rsp:");
+ CDF_TRACE_HEX_DUMP(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_INFO,
+ bcn_proberesp_ptr, roam_offload_synch_ind_ptr->beaconProbeRespLength);
+ if (roam_offload_synch_ind_ptr->isBeacon) {
+ if (sir_parse_beacon_ie(pMac, parsed_frm_ptr,
+ &bcn_proberesp_ptr[SIR_MAC_HDR_LEN_3A +
+ SIR_MAC_B_PR_SSID_OFFSET],
+ roam_offload_synch_ind_ptr->beaconProbeRespLength -
+ SIR_MAC_HDR_LEN_3A) != eSIR_SUCCESS ||
+ !parsed_frm_ptr->ssidPresent) {
+ CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_ERROR,
+ "Parse error Beacon, length=%d",
+ roam_offload_synch_ind_ptr->beaconProbeRespLength);
+ cdf_mem_free(parsed_frm_ptr);
+ return CDF_STATUS_E_FAILURE;
+ }
+ } else {
+ if (sir_convert_probe_frame2_struct(pMac,
+ &bcn_proberesp_ptr[SIR_MAC_HDR_LEN_3A],
+ roam_offload_synch_ind_ptr->beaconProbeRespLength -
+ SIR_MAC_HDR_LEN_3A, parsed_frm_ptr) != eSIR_SUCCESS ||
+ !parsed_frm_ptr->ssidPresent) {
+ CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_ERROR,
+ "Parse error ProbeResponse, length=%d",
+ roam_offload_synch_ind_ptr->beaconProbeRespLength);
+ cdf_mem_free(parsed_frm_ptr);
+ return CDF_STATUS_E_FAILURE;
+ }
+ }
+ /* 24 byte MAC header and 12 byte to ssid IE */
+ if (roam_offload_synch_ind_ptr->beaconProbeRespLength >
+ (SIR_MAC_HDR_LEN_3A + SIR_MAC_B_PR_SSID_OFFSET)) {
+ ie_len = roam_offload_synch_ind_ptr->beaconProbeRespLength -
+ (SIR_MAC_HDR_LEN_3A + SIR_MAC_B_PR_SSID_OFFSET);
+ }
+ /*
+ * Memory allocated below is freed up in csrProcessRoamOffloadSynchInd
+ */
+ roam_offload_synch_ind_ptr->bss_desc_ptr =
+ cdf_mem_malloc(sizeof (tSirBssDescription) + ie_len);
+ bss_desc_ptr = roam_offload_synch_ind_ptr->bss_desc_ptr;
+ if (NULL == bss_desc_ptr) {
+ CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_ERROR,
+ "LFR3:Failed to allocate memory");
+ CDF_ASSERT(bss_desc_ptr != NULL);
+ return CDF_STATUS_E_NOMEM;
+ }
+ cdf_mem_zero(bss_desc_ptr, sizeof(tSirBssDescription));
+
+ /*
+ * Length of BSS desription is without length of
+ * length itself and length of pointer
+ * that holds ieFields
+ *
+ * tSirBssDescription
+ * +--------+---------------------------------+---------------+
+ * | length | other fields | pointer to IEs|
+ * +--------+---------------------------------+---------------+
+ * ^
+ * ieFields
+ */
+ bss_desc_ptr->length = (uint16_t) (offsetof(tSirBssDescription,
+ ieFields[0]) -
+ sizeof(bss_desc_ptr->length) + ie_len);
+
+ if (parsed_frm_ptr->dsParamsPresent) {
+ bss_desc_ptr->channelId = parsed_frm_ptr->channelNumber;
+ } else if (parsed_frm_ptr->HTInfo.present) {
+ bss_desc_ptr->channelId = parsed_frm_ptr->HTInfo.primaryChannel;
+ } else {
+ /*
+ * If DS Params or HTIE is not present in the probe resp or
+ * beacon, then use the channel frequency provided by firmware
+ * to fill the channel in the BSS descriptor.*/
+ bss_desc_ptr->channelId =
+ cds_freq_to_chan(roam_offload_synch_ind_ptr->chan_freq);
+ }
+ bss_desc_ptr->channelIdSelf = bss_desc_ptr->channelId;
+
+ if ((bss_desc_ptr->channelId > 0) && (bss_desc_ptr->channelId < 15)) {
+ int i;
+ /* *
+ * 11b or 11g packet
+ * 11g if extended Rate IE is present or
+ * if there is an A rate in suppRate IE
+ * */
+ for (i = 0; i < parsed_frm_ptr->supportedRates.numRates; i++) {
+ if (sirIsArate(parsed_frm_ptr->supportedRates.rate[i] &
+ 0x7f)) {
+ bss_desc_ptr->nwType = eSIR_11G_NW_TYPE;
+ break;
+ }
+ }
+ if (parsed_frm_ptr->extendedRatesPresent) {
+ bss_desc_ptr->nwType = eSIR_11G_NW_TYPE;
+ }
+ } else {
+ /* 11a packet */
+ bss_desc_ptr->nwType = eSIR_11A_NW_TYPE;
+ }
+
+ bss_desc_ptr->sinr = 0;
+ bss_desc_ptr->beaconInterval = parsed_frm_ptr->beaconInterval;
+ bss_desc_ptr->timeStamp[0] = parsed_frm_ptr->timeStamp[0];
+ bss_desc_ptr->timeStamp[1] = parsed_frm_ptr->timeStamp[1];
+ cdf_mem_copy(&bss_desc_ptr->capabilityInfo,
+ &bcn_proberesp_ptr[SIR_MAC_HDR_LEN_3A + SIR_MAC_B_PR_CAPAB_OFFSET], 2);
+ cdf_mem_copy((uint8_t *) &bss_desc_ptr->bssId,
+ (uint8_t *) mac_hdr->bssId,
+ sizeof(tSirMacAddr));
+ bss_desc_ptr->nReceivedTime =
+ (uint32_t)cdf_mc_timer_get_system_ticks();
+ if (parsed_frm_ptr->mdiePresent) {
+ bss_desc_ptr->mdiePresent = parsed_frm_ptr->mdiePresent;
+ cdf_mem_copy((uint8_t *)bss_desc_ptr->mdie,
+ (uint8_t *)parsed_frm_ptr->mdie,
+ SIR_MDIE_SIZE);
+ }
+ CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_DEBUG,
+ "LFR3:%s:BssDescr Info:", __func__);
+ CDF_TRACE_HEX_DUMP(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_DEBUG,
+ bss_desc_ptr->bssId, sizeof(tSirMacAddr));
+ CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_DEBUG,
+ "chan=%d, rssi=%d", bss_desc_ptr->channelId,
+ bss_desc_ptr->rssi);
+ if (ie_len) {
+ cdf_mem_copy(&bss_desc_ptr->ieFields,
+ bcn_proberesp_ptr +
+ (SIR_MAC_HDR_LEN_3A + SIR_MAC_B_PR_SSID_OFFSET),
+ ie_len);
+ }
+ cdf_mem_free(parsed_frm_ptr);
+ return CDF_STATUS_SUCCESS;
+}
+
+/**-----------------------------------------------------------------
+ * brief lim_roam_offload_synch_ind() - Handles Roam Synch Indication
+ * param pMac - global mac structure
+ * return - none
+ *-----------------------------------------------------------------
+ **/
+void lim_roam_offload_synch_ind(tpAniSirGlobal pMac, tpSirMsgQ pMsg)
+{
+ tpPESession session_ptr;
+ tpPESession ft_session_ptr;
+ uint8_t session_id;
+ tSirMsgQ mmh_msg;
+ tSirBssDescription *bss_desc_ptr = NULL;
+ roam_offload_synch_ind *roam_sync_ind_ptr =
+ (roam_offload_synch_ind *)pMsg->bodyptr;
+
+ if (!roam_sync_ind_ptr) {
+ CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_ERROR,
+ "LFR3:%s:roam_sync_ind_ptr is NULL", __func__);
+ return;
+ }
+ CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_ERROR,
+ "LFR3: Received WMA_ROAM_OFFLOAD_SYNCH_IND");
+ CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_DEBUG,
+ "LFR3:%s:authStatus=%d, vdevId=%d", __func__,
+ roam_sync_ind_ptr->authStatus,
+ roam_sync_ind_ptr->roamedVdevId);
+ CDF_TRACE_HEX_DUMP(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_DEBUG,
+ roam_sync_ind_ptr->bssId, 6);
+ session_ptr = pe_find_session_by_bss_idx(pMac,
+ roam_sync_ind_ptr->roamedVdevId);
+ if (session_ptr == NULL) {
+ CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_ERROR,
+ "%s: LFR3:Unable to find session", __func__);
+ return;
+ }
+ /* Nothing to be done if the session is not in STA mode */
+ if (!LIM_IS_STA_ROLE(session_ptr)) {
+ CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_ERROR,
+ "session is not in STA mode");
+ return;
+ }
+ if (!CDF_IS_STATUS_SUCCESS(lim_roam_fill_bss_descr(pMac,
+ roam_sync_ind_ptr))) {
+ CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_ERROR,
+ "LFR3:%s:Failed to fill Bss Descr", __func__);
+ return;
+ }
+ bss_desc_ptr = roam_sync_ind_ptr->bss_desc_ptr;
+ ft_session_ptr = pe_create_session(pMac, bss_desc_ptr->bssId,
+ &session_id, pMac->lim.maxStation,
+ eSIR_INFRASTRUCTURE_MODE);
+ if (ft_session_ptr == NULL) {
+ CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_ERROR,
+ "LFR3: Session Can't be created for new AP during Roam Synch");
+ lim_print_mac_addr(pMac, bss_desc_ptr->bssId, LOGE);
+ return;
+ }
+ ft_session_ptr->peSessionId = session_id;
+ sir_copy_mac_addr(ft_session_ptr->selfMacAddr, session_ptr->selfMacAddr);
+ sir_copy_mac_addr(ft_session_ptr->limReAssocbssId, bss_desc_ptr->bssId);
+ ft_session_ptr->bssType = eSIR_INFRASTRUCTURE_MODE;
+ /**
+ * Set bRoamSynchInProgress here since this session is
+ *specific to roam synch indication. This flag will
+ *later be used to differentiate LFR3 with LFR2 in LIM
+ **/
+ ft_session_ptr->bRoamSynchInProgress = true;
+
+ if (ft_session_ptr->bssType == eSIR_INFRASTRUCTURE_MODE) {
+ ft_session_ptr->limSystemRole = eLIM_STA_ROLE;
+ } else {
+ CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_ERROR,
+ "LFR3:Invalid bss type");
+ return;
+ }
+ ft_session_ptr->limPrevSmeState = ft_session_ptr->limSmeState;
+ ft_session_ptr->limSmeState = eLIM_SME_WT_REASSOC_STATE;
+ CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_DEBUG,
+ "LFR3:%s:created session (%p) with id = %d",
+ __func__, ft_session_ptr, ft_session_ptr->peSessionId);
+ /* Update the ReAssoc BSSID of the current session */
+ sir_copy_mac_addr(session_ptr->limReAssocbssId, bss_desc_ptr->bssId);
+ lim_print_mac_addr(pMac, session_ptr->limReAssocbssId, LOG2);
+
+ /* Prepare the session right now with as much as possible */
+ lim_fill_ft_session(pMac, bss_desc_ptr, ft_session_ptr, session_ptr);
+ lim_ft_prepare_add_bss_req(pMac, false, ft_session_ptr, bss_desc_ptr);
+ mmh_msg.type =
+ roam_sync_ind_ptr->messageType;
+ /* eWNI_SME_ROAM_OFFLOAD_SYNCH_IND */
+ mmh_msg.bodyptr = roam_sync_ind_ptr;
+ mmh_msg.bodyval = 0;
+
+ CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_DEBUG,
+ "LFR3:%s:sending eWNI_SME_ROAM_OFFLOAD_SYNCH_IND", __func__);
+ lim_sys_process_mmh_msg_api(pMac, &mmh_msg, ePROT);
+}
+#endif
+
+uint8_t lim_is_beacon_miss_scenario(tpAniSirGlobal pMac, uint8_t *pRxPacketInfo)
+{
+ tpSirMacMgmtHdr pHdr = WMA_GET_RX_MAC_HEADER(pRxPacketInfo);
+ uint8_t sessionId;
+ tpPESession psessionEntry =
+ pe_find_session_by_bssid(pMac, pHdr->bssId, &sessionId);
+
+ if (psessionEntry && psessionEntry->pmmOffloadInfo.bcnmiss)
+ return true;
+ return false;
+}
+
+/** -----------------------------------------------------------------
+ \brief lim_is_pkt_candidate_for_drop() - decides whether to drop the frame or not
+
+ This function is called before enqueuing the frame to PE queue for further processing.
+ This prevents unnecessary frames getting into PE Queue and drops them right away.
+ Frames will be droped in the following scenarios:
+
+ - In Scan State, drop the frames which are not marked as scan frames
+ - In non-Scan state, drop the frames which are marked as scan frames.
+ - Drop INFRA Beacons and Probe Responses in IBSS Mode
+ - Drop the Probe Request in IBSS mode, if STA did not send out the last beacon
+
+ \param pMac - global mac structure
+ \return - none
+ \sa
+ ----------------------------------------------------------------- */
+
+tMgmtFrmDropReason lim_is_pkt_candidate_for_drop(tpAniSirGlobal pMac,
+ uint8_t *pRxPacketInfo,
+ uint32_t subType)
+{
+ uint32_t framelen;
+ uint8_t *pBody;
+ tSirMacCapabilityInfo capabilityInfo;
+ tpSirMacMgmtHdr pHdr = NULL;
+ tpPESession psessionEntry = NULL;
+ uint8_t sessionId;
+
+ /*
+ *
+ * In scan mode, drop only Beacon/Probe Response which are NOT marked as scan-frames.
+ * In non-scan mode, drop only Beacon/Probe Response which are marked as scan frames.
+ * Allow other mgmt frames, they must be from our own AP, as we don't allow
+ * other than beacons or probe responses in scan state.
+ */
+ if ((subType == SIR_MAC_MGMT_BEACON) ||
+ (subType == SIR_MAC_MGMT_PROBE_RSP)) {
+ if (lim_is_beacon_miss_scenario(pMac, pRxPacketInfo)) {
+ MTRACE(mac_trace
+ (pMac, TRACE_CODE_INFO_LOG, 0,
+ eLOG_NODROP_MISSED_BEACON_SCENARIO));
+ return eMGMT_DROP_NO_DROP;
+ }
+ if (lim_is_system_in_scan_state(pMac)) {
+ return eMGMT_DROP_NO_DROP;
+ } else if (WMA_IS_RX_IN_SCAN(pRxPacketInfo)) {
+ return eMGMT_DROP_SCAN_MODE_FRAME;
+ } else {
+ /* Beacons and probe responses can come in any time
+ * because of parallel scans. Don't drop them.
+ */
+ return eMGMT_DROP_NO_DROP;
+ }
+ }
+
+ if ((subType == SIR_MAC_MGMT_DEAUTH ||
+ subType == SIR_MAC_MGMT_DISASSOC) &&
+ lim_is_deauth_diassoc_for_drop(pMac, pRxPacketInfo))
+ return eMGMT_DROP_SPURIOUS_FRAME;
+
+#ifdef WLAN_FEATURE_11W
+ if ((subType == SIR_MAC_MGMT_ASSOC_REQ ||
+ subType == SIR_MAC_MGMT_REASSOC_REQ) &&
+ lim_is_assoc_req_for_drop(pMac, pRxPacketInfo))
+ return eMGMT_DROP_SPURIOUS_FRAME;
+#endif
+
+ framelen = WMA_GET_RX_PAYLOAD_LEN(pRxPacketInfo);
+ pBody = WMA_GET_RX_MPDU_DATA(pRxPacketInfo);
+
+ /* Drop INFRA Beacons and Probe Responses in IBSS Mode */
+ if ((subType == SIR_MAC_MGMT_BEACON) ||
+ (subType == SIR_MAC_MGMT_PROBE_RSP)) {
+ /* drop the frame if length is less than 12 */
+ if (framelen < LIM_MIN_BCN_PR_LENGTH)
+ return eMGMT_DROP_INVALID_SIZE;
+
+ *((uint16_t *) &capabilityInfo) =
+ sir_read_u16(pBody + LIM_BCN_PR_CAPABILITY_OFFSET);
+
+ /* Note sure if this is sufficient, basically this condition allows all probe responses and
+ * beacons from an infrastructure network
+ */
+ if (!capabilityInfo.ibss)
+ return eMGMT_DROP_NO_DROP;
+
+ /* This can be enhanced to even check the SSID before deciding to enque the frame. */
+ if (capabilityInfo.ess)
+ return eMGMT_DROP_INFRA_BCN_IN_IBSS;
+ } else if ((subType == SIR_MAC_MGMT_PROBE_REQ) &&
+ (!WMA_GET_RX_BEACON_SENT(pRxPacketInfo))) {
+ pHdr = WMA_GET_RX_MAC_HEADER(pRxPacketInfo);
+ psessionEntry =
+ pe_find_session_by_bssid(pMac, pHdr->bssId, &sessionId);
+ if ((psessionEntry && !LIM_IS_IBSS_ROLE(psessionEntry)) ||
+ (!psessionEntry))
+ return eMGMT_DROP_NO_DROP;
+
+ /* Drop the Probe Request in IBSS mode, if STA did not send out the last beacon */
+ /* In IBSS, the node which sends out the beacon, is supposed to respond to ProbeReq */
+ return eMGMT_DROP_NOT_LAST_IBSS_BCN;
+ }
+
+ return eMGMT_DROP_NO_DROP;
+}
+
+CDF_STATUS pe_acquire_global_lock(tAniSirLim *psPe)
+{
+ CDF_STATUS status = CDF_STATUS_E_INVAL;
+
+ if (psPe) {
+ if (CDF_IS_STATUS_SUCCESS
+ (cdf_mutex_acquire(&psPe->lkPeGlobalLock))) {
+ status = CDF_STATUS_SUCCESS;
+ }
+ }
+ return status;
+}
+
+CDF_STATUS pe_release_global_lock(tAniSirLim *psPe)
+{
+ CDF_STATUS status = CDF_STATUS_E_INVAL;
+ if (psPe) {
+ if (CDF_IS_STATUS_SUCCESS
+ (cdf_mutex_release(&psPe->lkPeGlobalLock))) {
+ status = CDF_STATUS_SUCCESS;
+ }
+ }
+ return status;
+}
+
diff --git a/core/mac/src/pe/lim/lim_assoc_utils.c b/core/mac/src/pe/lim/lim_assoc_utils.c
new file mode 100644
index 0000000..a1680d6
--- /dev/null
+++ b/core/mac/src/pe/lim/lim_assoc_utils.c
@@ -0,0 +1,5132 @@
+/*
+ * Copyright (c) 2011-2015 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_assoc_utils.cc contains the utility functions
+ * LIM uses while processing (Re) Association messages.
+ * Author: Chandra Modumudi
+ * Date: 02/13/02
+ * History:-
+ * Date Modified by Modification Information
+ * --------------------------------------------------------------------
+ * 05/26/10 js WPA handling in (Re)Assoc frames
+ *
+ */
+
+#include "cds_api.h"
+#include "ani_global.h"
+#include "wni_api.h"
+#include "sir_common.h"
+
+#include "wni_cfg.h"
+#include "cfg_api.h"
+
+#include "sch_api.h"
+#include "utils_api.h"
+#include "lim_utils.h"
+#include "lim_assoc_utils.h"
+#include "lim_security_utils.h"
+#include "lim_ser_des_utils.h"
+#include "lim_sta_hash_api.h"
+#include "lim_admit_control.h"
+#include "lim_send_messages.h"
+#include "lim_ibss_peer_mgmt.h"
+#ifdef WLAN_FEATURE_VOWIFI_11R
+#include "lim_ft_defs.h"
+#endif
+#include "lim_session.h"
+
+#include "cdf_types.h"
+#include "wma_types.h"
+#include "lim_types.h"
+
+/*
+ * fill up the rate info properly based on what is actually supported by the peer
+ * TBD TBD TBD
+ */
+void
+lim_fill_supported_rates_info(tpAniSirGlobal pMac,
+ tpDphHashNode pSta,
+ tpSirSupportedRates pRates, tpPESession psessionEntry)
+{
+ /* pSta will be NULL for self entry, so get the opRateMode based on the self mode. */
+ /* For the peer entry get it from the peer Capabilities present in hash table */
+ if (pSta == NULL)
+ pRates->opRateMode =
+ lim_get_sta_rate_mode((uint8_t) psessionEntry->dot11mode);
+ else
+ pRates->opRateMode =
+ lim_get_sta_peer_type(pMac, pSta, psessionEntry);
+
+}
+
+/**
+ * lim_cmp_s_sid()
+ *
+ ***FUNCTION:
+ * This function is called in various places within LIM code
+ * to determine whether received SSid is same as SSID in use.
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ * NA
+ *
+ ***NOTE:
+ * NA
+ *
+ * @param *prxSSid - pointer to SSID structure
+ *
+ * @return status - true for SSID match else false.
+ */
+
+uint8_t
+lim_cmp_s_sid(tpAniSirGlobal pMac, tSirMacSSid *prxSSid,
+ tpPESession psessionEntry)
+{
+
+ if (cdf_mem_compare
+ ((uint8_t *) prxSSid, (uint8_t *) &psessionEntry->ssId,
+ (uint8_t) (psessionEntry->ssId.length + 1)))
+ return true;
+ else
+ return false;
+
+} /****** end lim_cmp_s_sid() ******/
+
+/**
+ * lim_compare_capabilities()
+ *
+ ***FUNCTION:
+ * This function is called during Association/Reassociation
+ * frame handling to determine whether received capabilities
+ * match with local capabilities or not.
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ * NA
+ *
+ ***NOTE:
+ * NA
+ *
+ * @param pMac - Pointer to Global MAC structure
+ * @param pAssocReq - Pointer to received Assoc Req frame
+ * @param pLocalCapabs - Pointer to local capabilities
+ *
+ * @return status - true for Capabilitity match else false.
+ */
+
+uint8_t
+lim_compare_capabilities(tpAniSirGlobal pMac,
+ tSirAssocReq *pAssocReq,
+ tSirMacCapabilityInfo *pLocalCapabs,
+ tpPESession psessionEntry)
+{
+ uint32_t val;
+
+ if ((LIM_IS_AP_ROLE(psessionEntry) ||
+ LIM_IS_BT_AMP_AP_ROLE(psessionEntry)) &&
+ (pAssocReq->capabilityInfo.ibss)) {
+ /* Requesting STA asserting IBSS capability. */
+ lim_log(pMac, LOG1,
+ FL("Requesting STA asserting IBSS capability"));
+ return false;
+ }
+ /* Compare CF capabilities */
+ if (pAssocReq->capabilityInfo.cfPollable ||
+ pAssocReq->capabilityInfo.cfPollReq) {
+ /* AP does not support PCF functionality */
+ lim_log(pMac, LOG1,
+ FL(" AP does not support PCF functionality"));
+ return false;
+ }
+ /* Compare short preamble capability */
+ if (pAssocReq->capabilityInfo.shortPreamble &&
+ (pAssocReq->capabilityInfo.shortPreamble !=
+ pLocalCapabs->shortPreamble)) {
+ /* Allowing a STA requesting short preamble while */
+ /* AP does not support it */
+ }
+
+ lim_log(pMac, LOG1, "QoS in AssocReq: %d, local capabs qos: %d",
+ pAssocReq->capabilityInfo.qos, pLocalCapabs->qos);
+
+ /* Compare QoS capability */
+ if (pAssocReq->capabilityInfo.qos &&
+ (pAssocReq->capabilityInfo.qos != pLocalCapabs->qos)) {
+ /*Temporary hack for UPF to skip 11e capability check in order to interop with
+ CSR - proper fix needs to be put in place */
+ lim_log(pMac, LOG1,
+ FL
+ ("Received unmatched QOS but cfg to suppress - continuing"));
+ }
+
+ /*
+ * If AP supports shortSlot and if apple user has
+ * enforced association only from shortSlot station,
+ * then AP must reject any station that does not support
+ * shortSlot
+ */
+ if ((LIM_IS_AP_ROLE(psessionEntry) ||
+ LIM_IS_BT_AMP_AP_ROLE(psessionEntry)) &&
+ (pLocalCapabs->shortSlotTime == 1)) {
+ if (wlan_cfg_get_int
+ (pMac, WNI_CFG_ACCEPT_SHORT_SLOT_ASSOC_ONLY,
+ &val) != eSIR_SUCCESS) {
+ lim_log(pMac, LOGP,
+ FL
+ ("error getting WNI_CFG_FORCE_SHORT_SLOT_ASSOC_ONLY "));
+ return false;
+ }
+ if (val) {
+ if (pAssocReq->capabilityInfo.shortSlotTime !=
+ pLocalCapabs->shortSlotTime) {
+ lim_log(pMac, LOGE,
+ FL
+ ("AP rejects association as station doesnt support shortslot time"));
+ return false;
+ }
+ return false;
+ }
+ }
+
+ return true;
+} /****** end lim_compare_capabilities() ******/
+
+/**
+ * lim_check_rx_basic_rates()
+ *
+ ***FUNCTION:
+ * This function is called during Association/Reassociation
+ * frame handling to determine whether received rates in
+ * Assoc/Reassoc request frames include all BSS basic rates
+ * or not.
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ * NA
+ *
+ ***NOTE:
+ * NA
+ *
+ * @param rxRateSet - pointer to SSID structure
+ *
+ * @return status - true if ALL BSS basic rates are present in the
+ * received rateset else false.
+ */
+
+uint8_t
+lim_check_rx_basic_rates(tpAniSirGlobal pMac, tSirMacRateSet rxRateSet,
+ tpPESession psessionEntry)
+{
+ tSirMacRateSet *pRateSet, basicRate;
+ uint8_t i, j, k, match;
+
+ pRateSet = cdf_mem_malloc(sizeof(tSirMacRateSet));
+ if (NULL == pRateSet) {
+ lim_log(pMac, LOGP,
+ FL("call to AllocateMemory failed for RATESET"));
+
+ return false;
+ }
+
+ /* Copy operational rate set from session Entry */
+ cdf_mem_copy(pRateSet->rate, (psessionEntry->rateSet.rate),
+ psessionEntry->rateSet.numRates);
+
+ pRateSet->numRates = psessionEntry->rateSet.numRates;
+
+ /* Extract BSS basic rateset from operational rateset */
+ for (i = 0, j = 0;
+ ((i < pRateSet->numRates) && (i < SIR_MAC_RATESET_EID_MAX)); i++) {
+ if ((pRateSet->rate[i] & 0x80) == 0x80) {
+ /* msb is set, so this is a basic rate */
+ basicRate.rate[j++] = pRateSet->rate[i];
+ }
+ }
+
+ /*
+ * For each BSS basic rate, find if it is present in the
+ * received rateset.
+ */
+ for (k = 0; k < j; k++) {
+ match = 0;
+ for (i = 0;
+ ((i < rxRateSet.numRates)
+ && (i < SIR_MAC_RATESET_EID_MAX)); i++) {
+ if ((rxRateSet.rate[i] | 0x80) == basicRate.rate[k])
+ match = 1;
+ }
+
+ if (!match) {
+ /* Free up memory allocated for rateset */
+ cdf_mem_free((uint8_t *) pRateSet);
+
+ return false;
+ }
+ }
+
+ /* Free up memory allocated for rateset */
+ cdf_mem_free((uint8_t *) pRateSet);
+
+ return true;
+} /****** end lim_check_rx_basic_rates() ******/
+
+/**
+ * lim_check_mcs_set()
+ *
+ ***FUNCTION:
+ * This function is called during Association/Reassociation
+ * frame handling to determine whether received MCS rates in
+ * Assoc/Reassoc request frames includes all Basic MCS Rate Set or not.
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ * NA
+ *
+ ***NOTE:
+ * NA
+ *
+ * @param supportedMCSSet - pointer to Supported MCS Rate Set
+ *
+ * @return status - true if ALL MCS Basic Rate Set rates are present in the
+ * received rateset else false.
+ */
+
+uint8_t lim_check_mcs_set(tpAniSirGlobal pMac, uint8_t *supportedMCSSet)
+{
+ uint8_t basicMCSSet[SIZE_OF_BASIC_MCS_SET] = { 0 };
+ uint32_t cfgLen = 0;
+ uint8_t i;
+ uint8_t validBytes;
+ uint8_t lastByteMCSMask = 0x1f;
+
+ cfgLen = WNI_CFG_BASIC_MCS_SET_LEN;
+ if (wlan_cfg_get_str(pMac, WNI_CFG_BASIC_MCS_SET,
+ (uint8_t *) basicMCSSet,
+ (uint32_t *) &cfgLen) != eSIR_SUCCESS) {
+ /* / Could not get Basic MCS rateset from CFG. Log error. */
+ lim_log(pMac, LOGP, FL("could not retrieve Basic MCS rateset"));
+ return false;
+ }
+
+ validBytes = VALID_MCS_SIZE / 8;
+
+ /* check if all the Basic MCS Bits are set in supported MCS bitmap */
+ for (i = 0; i < validBytes; i++) {
+ if ((basicMCSSet[i] & supportedMCSSet[i]) != basicMCSSet[i]) {
+ /* Log is avaiable in calling function in file lim_process_assoc_req_frame.c */
+ lim_log(pMac, LOGW,
+ FL
+ ("One of Basic MCS Set Rates is not supported by the Station."));
+ return false;
+ }
+ }
+
+ /* check the last 5 bits of the valid MCS bitmap */
+ if (((basicMCSSet[i] & lastByteMCSMask) &
+ (supportedMCSSet[i] & lastByteMCSMask)) !=
+ (basicMCSSet[i] & lastByteMCSMask)) {
+ lim_log(pMac, LOGW,
+ FL
+ ("One of Basic MCS Set Rates is not supported by the Station."));
+ return false;
+ }
+
+ return true;
+}
+
+#define SECURITY_SUITE_TYPE_MASK 0xFF
+#define SECURITY_SUITE_TYPE_WEP40 0x1
+#define SECURITY_SUITE_TYPE_TKIP 0x2
+#define SECURITY_SUITE_TYPE_CCMP 0x4
+#define SECURITY_SUITE_TYPE_WEP104 0x4
+
+/**
+ * lim_check_rx_rsn_ie_match()- validate received rsn ie with supported cipher
+ * suites.
+ * @mac_ctx: pointer to global mac structure
+ * @rx_rsn_ie: received rsn IE
+ * @session_entry: pe session entry
+ * @sta_is_ht: peer station HT capability
+ * @pmf_connection: set to true if this is pmf connection
+ *
+ * This function is called during Association/Reassociation
+ * frame handling to determine whether received RSN in
+ * Assoc/Reassoc request frames include supported cipher suites or not.
+ *
+ * Return: eSIR_SUCCESS if ALL BSS basic rates are present in the
+ * received rateset else failure status.
+ */
+
+uint8_t
+lim_check_rx_rsn_ie_match(tpAniSirGlobal mac_ctx, tDot11fIERSN rx_rsn_ie,
+ tpPESession session_entry, uint8_t sta_is_ht,
+ bool *pmf_connection)
+{
+ tDot11fIERSN *rsn_ie;
+ uint8_t i, j, match, only_non_ht_cipher = 1;
+#ifdef WLAN_FEATURE_11W
+ bool we_are_pmf_capable;
+ bool we_require_pmf;
+ bool they_are_pmf_capable;
+ bool they_require_pmf;
+#endif
+
+ /* RSN IE should be received from PE */
+ rsn_ie = &session_entry->gStartBssRSNIe;
+
+ /* Check groupwise cipher suite */
+ for (i = 0; i < sizeof(rx_rsn_ie.gp_cipher_suite); i++)
+ if (rsn_ie->gp_cipher_suite[i] !=
+ rx_rsn_ie.gp_cipher_suite[i]) {
+ lim_log(mac_ctx, LOG3,
+ FL("Invalid groupwise cipher suite"));
+ return eSIR_MAC_INVALID_GROUP_CIPHER_STATUS;
+ }
+
+ /*
+ * For each Pairwise cipher suite check whether we support
+ * received pairwise
+ */
+ match = 0;
+ for (i = 0; i < rx_rsn_ie.pwise_cipher_suite_count; i++) {
+ for (j = 0; j < rsn_ie->pwise_cipher_suite_count; j++) {
+ if (cdf_mem_compare(&rx_rsn_ie.pwise_cipher_suites[i],
+ &rsn_ie->pwise_cipher_suites[j],
+ sizeof(rsn_ie->pwise_cipher_suites[j]))) {
+ match = 1;
+ break;
+ }
+ }
+
+ if ((sta_is_ht)
+#ifdef ANI_LITTLE_BYTE_ENDIAN
+ &&
+ ((rx_rsn_ie.pwise_cipher_suites[i][3] &
+ SECURITY_SUITE_TYPE_MASK) ==
+ SECURITY_SUITE_TYPE_CCMP))
+#else
+ &&
+ ((rx_rsn_ie.pwise_cipher_suites[i][0] &
+ SECURITY_SUITE_TYPE_MASK) ==
+ SECURITY_SUITE_TYPE_CCMP))
+#endif
+ only_non_ht_cipher = 0;
+
+ }
+
+ if ((!match) || ((sta_is_ht) && only_non_ht_cipher)) {
+ lim_log(mac_ctx, LOG1, FL("Invalid pairwise cipher suite"));
+ return eSIR_MAC_INVALID_PAIRWISE_CIPHER_STATUS;
+ }
+ /*
+ * Check RSN capabilities
+ * Bit 0 of First Byte - PreAuthentication Capability
+ */
+ if (((rx_rsn_ie.RSN_Cap[0] >> 0) & 0x1) == true) {
+ /* this is supported by AP only */
+ lim_log(mac_ctx, LOG1,
+ FL("Invalid RSN information element capabilities"));
+ return eSIR_MAC_INVALID_RSN_IE_CAPABILITIES_STATUS;
+ }
+
+ *pmf_connection = false;
+
+#ifdef WLAN_FEATURE_11W
+ we_are_pmf_capable = session_entry->pLimStartBssReq->pmfCapable;
+ we_require_pmf = session_entry->pLimStartBssReq->pmfRequired;
+ they_are_pmf_capable = (rx_rsn_ie.RSN_Cap[0] >> 7) & 0x1;
+ they_require_pmf = (rx_rsn_ie.RSN_Cap[0] >> 6) & 0x1;
+
+ if ((they_require_pmf && they_are_pmf_capable && !we_are_pmf_capable) ||
+ (we_require_pmf && !they_are_pmf_capable)) {
+ lim_log(mac_ctx, LOG1,
+ FL("Association fail, robust management frames policy"
+ " violation they_require_pmf =%d"
+ " theyArePMFCapable %d weArePMFCapable %d"
+ " weRequirePMF %d theyArePMFCapable %d"),
+ they_require_pmf, they_are_pmf_capable,
+ we_are_pmf_capable, we_require_pmf,
+ they_are_pmf_capable);
+ return eSIR_MAC_ROBUST_MGMT_FRAMES_POLICY_VIOLATION;
+ }
+
+ if (they_are_pmf_capable && we_are_pmf_capable)
+ *pmf_connection = true;
+
+ lim_log(mac_ctx, LOG1,
+ FL("weAreCapable %d, weRequire %d, theyAreCapable %d,"
+ " theyRequire %d, PMFconnection %d"),
+ we_are_pmf_capable, we_require_pmf, they_are_pmf_capable,
+ they_require_pmf, *pmf_connection);
+#endif
+
+ return eSIR_SUCCESS;
+}
+
+/**
+ * lim_check_rx_wpa_ie_match() - to check supported cipher suites
+ *
+ * @mac: pointer to global mac structure
+ * @rx_wpaie: Received WPA IE in (Re)Assco req
+ * @session_entry: pointer to PE session
+ * @sta_is_ht: peer station is HT
+ *
+ * This function is called during Association/Reassociation
+ * frame handling to determine whether received RSN in
+ * Assoc/Reassoc request frames include supported cipher suites or not.
+ *
+ * Return: Success if ALL BSS basic rates are present in the
+ * received rateset else failure status.
+ */
+
+uint8_t
+lim_check_rx_wpa_ie_match(tpAniSirGlobal mac, tDot11fIEWPA rx_wpaie,
+ tpPESession session_entry, uint8_t sta_is_ht)
+{
+ tDot11fIEWPA *wpa_ie;
+ uint8_t i, j, match, only_non_ht_cipher = 1;
+
+ /* WPA IE should be received from PE */
+ wpa_ie = &session_entry->gStartBssWPAIe;
+
+ /* Check groupwise cipher suite */
+ for (i = 0; i < 4; i++) {
+ if (wpa_ie->multicast_cipher[i] != rx_wpaie.multicast_cipher[i]) {
+ lim_log(mac, LOG1,
+ FL("Invalid groupwise cipher suite"));
+ return eSIR_MAC_INVALID_GROUP_CIPHER_STATUS;
+ }
+ }
+
+ /*
+ * For each Pairwise cipher suite check whether we support
+ * received pairwise
+ */
+ match = 0;
+ for (i = 0; i < rx_wpaie.unicast_cipher_count; i++) {
+ for (j = 0; j < wpa_ie->unicast_cipher_count; j++) {
+ if (cdf_mem_compare(rx_wpaie.unicast_ciphers[i],
+ wpa_ie->unicast_ciphers[j], 4)) {
+ match = 1;
+ break;
+ }
+ }
+
+ if ((sta_is_ht)
+#ifdef ANI_LITTLE_BYTE_ENDIAN
+ &&
+ ((rx_wpaie.
+ unicast_ciphers[i][3] & SECURITY_SUITE_TYPE_MASK) ==
+ SECURITY_SUITE_TYPE_CCMP))
+#else
+ &&
+ ((rx_wpaie.
+ unicast_ciphers[i][0] & SECURITY_SUITE_TYPE_MASK) ==
+ SECURITY_SUITE_TYPE_CCMP))
+#endif
+ {
+ only_non_ht_cipher = 0;
+ }
+
+ }
+
+ if ((!match) || ((sta_is_ht) && only_non_ht_cipher)) {
+ lim_log(mac, LOG1, FL("Invalid pairwise cipher suite"));
+ return eSIR_MAC_CIPHER_SUITE_REJECTED_STATUS;
+ }
+
+ return eSIR_SUCCESS;
+}
+
+/**
+ * lim_cleanup_rx_path()
+ *
+ ***FUNCTION:
+ * This function is called to cleanup STA state at SP & RFP.
+ *
+ ***LOGIC:
+ * To circumvent RFP's handling of dummy packet when it does not
+ * have an incomplete packet for the STA to be deleted, a packet
+ * with 'more framgents' bit set will be queued to RFP's WQ before
+ * queuing 'dummy packet'.
+ * A 'dummy' BD is pushed into RFP's WQ with type=00, subtype=1010
+ * (Disassociation frame) and routing flags in BD set to eCPU's
+ * Low Priority WQ.
+ * RFP cleans up its local context for the STA id mentioned in the
+ * BD and then pushes BD to eCPU's low priority WQ.
+ *
+ ***ASSUMPTIONS:
+ * NA
+ *
+ ***NOTE:
+ * NA
+ *
+ * @param pMac Pointer to Global MAC structure
+ * @param pStaDs Pointer to the per STA data structure
+ * initialized by LIM and maintained at DPH
+ *
+ * @return None
+ */
+
+tSirRetStatus
+lim_cleanup_rx_path(tpAniSirGlobal pMac, tpDphHashNode pStaDs,
+ tpPESession psessionEntry)
+{
+ tSirRetStatus retCode = eSIR_SUCCESS;
+
+ lim_log(pMac, LOG1, FL("Cleanup Rx Path for AID : %d"
+ "psessionEntry->limSmeState : %d, mlmState : %d"),
+ pStaDs->assocId, psessionEntry->limSmeState,
+ pStaDs->mlmStaContext.mlmState);
+
+ psessionEntry->isCiscoVendorAP = false;
+
+ if (pMac->lim.gLimAddtsSent) {
+ MTRACE(mac_trace
+ (pMac, TRACE_CODE_TIMER_DEACTIVATE,
+ psessionEntry->peSessionId, eLIM_ADDTS_RSP_TIMER));
+ tx_timer_deactivate(&pMac->lim.limTimers.gLimAddtsRspTimer);
+ }
+
+ if (pStaDs->mlmStaContext.mlmState == eLIM_MLM_WT_ASSOC_CNF_STATE) {
+ lim_deactivate_and_change_per_sta_id_timer(pMac, eLIM_CNF_WAIT_TIMER,
+ pStaDs->assocId);
+
+ if (!pStaDs->mlmStaContext.updateContext) {
+ /**
+ * There is no context at Polaris to delete.
+ * Release our assigned AID back to the free pool
+ */
+ if (LIM_IS_AP_ROLE(psessionEntry) ||
+ LIM_IS_BT_AMP_AP_ROLE(psessionEntry)) {
+ lim_release_peer_idx(pMac, pStaDs->assocId,
+ psessionEntry);
+ }
+ lim_delete_dph_hash_entry(pMac, pStaDs->staAddr,
+ pStaDs->assocId, psessionEntry);
+
+ return retCode;
+ }
+ }
+ /* delete all tspecs associated with this sta. */
+ lim_admit_control_delete_sta(pMac, pStaDs->assocId);
+
+ /**
+ * Make STA hash entry invalid at eCPU so that DPH
+ * does not process any more data packets and
+ * releases those BDs
+ */
+ pStaDs->valid = 0;
+ pStaDs->mlmStaContext.mlmState = eLIM_MLM_WT_DEL_STA_RSP_STATE;
+
+ if (LIM_IS_STA_ROLE(psessionEntry) ||
+ LIM_IS_BT_AMP_STA_ROLE(psessionEntry)) {
+ MTRACE(mac_trace
+ (pMac, TRACE_CODE_MLM_STATE, psessionEntry->peSessionId,
+ eLIM_MLM_WT_DEL_STA_RSP_STATE));
+ psessionEntry->limMlmState = eLIM_MLM_WT_DEL_STA_RSP_STATE;
+ /* Deactivating probe after heart beat timer */
+ lim_deactivate_and_change_timer(pMac, eLIM_PROBE_AFTER_HB_TIMER);
+ lim_deactivate_and_change_timer(pMac, eLIM_JOIN_FAIL_TIMER);
+ pMac->lim.gLastBeaconDtimCount = 0;
+ pMac->lim.gLastBeaconDtimPeriod = 0;
+
+#ifdef FEATURE_WLAN_ESE
+#ifdef FEATURE_WLAN_ESE_UPLOAD
+ lim_send_sme_tsm_ie_ind(pMac, psessionEntry, 0, 0, 0);
+#else
+ lim_deactivate_and_change_timer(pMac, eLIM_TSM_TIMER);
+#endif /* FEATURE_WLAN_ESE_UPLOAD */
+#endif
+
+ }
+#ifdef WLAN_DEBUG
+ /* increment a debug count */
+ pMac->lim.gLimNumRxCleanup++;
+#endif
+
+ if (psessionEntry->limSmeState == eLIM_SME_JOIN_FAILURE_STATE) {
+ retCode =
+ lim_del_bss(pMac, pStaDs, psessionEntry->bssIdx,
+ psessionEntry);
+ } else
+ retCode = lim_del_sta(pMac, pStaDs, true, psessionEntry);
+
+ return retCode;
+
+} /*** end lim_cleanup_rx_path() ***/
+
+/**
+ * lim_send_del_sta_cnf()
+ *
+ ***FUNCTION:
+ * This function is called to send appropriate CNF message to SME
+ *
+ ***LOGIC:
+ *
+ *
+ ***ASSUMPTIONS:
+ * NA
+ *
+ ***NOTE:
+ * NA
+ *
+ * @param pMac Pointer to Global MAC structure
+ * @param tpAniSirGlobal pMac,
+ * @param tSirMacAddr staDsAddr,
+ * @param uint16_t staDsAssocId,
+ * @param tLimMlmStaContext mlmStaContext,
+ * @param tSirResultCodes statusCode
+ *
+ * @return None
+ */
+
+void
+lim_send_del_sta_cnf(tpAniSirGlobal pMac, tSirMacAddr staDsAddr,
+ uint16_t staDsAssocId, tLimMlmStaContext mlmStaContext,
+ tSirResultCodes statusCode, tpPESession psessionEntry)
+{
+
+ tLimMlmDisassocCnf mlmDisassocCnf;
+ tLimMlmDeauthCnf mlmDeauthCnf;
+ tLimMlmPurgeStaInd mlmPurgeStaInd;
+
+ lim_log(pMac, LOG1, FL("Sessionid: %d staDsAssocId: %d Trigger: %d"
+ "statusCode: %d staDsAddr: " MAC_ADDRESS_STR),
+ psessionEntry->peSessionId, staDsAssocId,
+ mlmStaContext.cleanupTrigger, statusCode,
+ MAC_ADDR_ARRAY(staDsAddr));
+
+ if (LIM_IS_STA_ROLE(psessionEntry) ||
+ LIM_IS_BT_AMP_STA_ROLE(psessionEntry)) {
+ /* Set BSSID at CFG to null */
+ tSirMacAddr nullAddr = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+ sir_copy_mac_addr(nullAddr, psessionEntry->bssId);
+
+ /* Free up buffer allocated for JoinReq held by */
+ /* MLM state machine */
+ if (psessionEntry->pLimMlmJoinReq) {
+ cdf_mem_free(psessionEntry->pLimMlmJoinReq);
+ psessionEntry->pLimMlmJoinReq = NULL;
+ }
+
+ psessionEntry->limAID = 0;
+
+ }
+
+ if ((mlmStaContext.cleanupTrigger ==
+ eLIM_HOST_DISASSOC) ||
+ (mlmStaContext.cleanupTrigger ==
+ eLIM_LINK_MONITORING_DISASSOC) ||
+ (mlmStaContext.cleanupTrigger == eLIM_PROMISCUOUS_MODE_DISASSOC)) {
+ /**
+ * Host or LMM driven Disassociation.
+ * Issue Disassoc Confirm to SME.
+ */
+ lim_log(pMac, LOGW,
+ FL("Lim Posting DISASSOC_CNF to Sme. Trigger: %d"),
+ mlmStaContext.cleanupTrigger);
+
+ cdf_mem_copy((uint8_t *) &mlmDisassocCnf.peerMacAddr,
+ (uint8_t *) staDsAddr, sizeof(tSirMacAddr));
+ mlmDisassocCnf.resultCode = statusCode;
+ mlmDisassocCnf.disassocTrigger = mlmStaContext.cleanupTrigger;
+ /* Update PE session Id */
+ mlmDisassocCnf.sessionId = psessionEntry->peSessionId;
+
+ lim_post_sme_message(pMac,
+ LIM_MLM_DISASSOC_CNF,
+ (uint32_t *) &mlmDisassocCnf);
+ } else if ((mlmStaContext.cleanupTrigger ==
+ eLIM_HOST_DEAUTH) ||
+ (mlmStaContext.cleanupTrigger ==
+ eLIM_LINK_MONITORING_DEAUTH)) {
+ /**
+ * Host or LMM driven Deauthentication.
+ * Issue Deauth Confirm to SME.
+ */
+ lim_log(pMac, LOGW,
+ FL("Lim Posting DEAUTH_CNF to Sme. Trigger: %d"),
+ mlmStaContext.cleanupTrigger);
+ cdf_mem_copy((uint8_t *) &mlmDeauthCnf.peerMacAddr,
+ (uint8_t *) staDsAddr, sizeof(tSirMacAddr));
+ mlmDeauthCnf.resultCode = statusCode;
+ mlmDeauthCnf.deauthTrigger = mlmStaContext.cleanupTrigger;
+ /* PE session Id */
+ mlmDeauthCnf.sessionId = psessionEntry->peSessionId;
+
+ lim_post_sme_message(pMac,
+ LIM_MLM_DEAUTH_CNF,
+ (uint32_t *) &mlmDeauthCnf);
+ } else if ((mlmStaContext.cleanupTrigger ==
+ eLIM_PEER_ENTITY_DISASSOC) ||
+ (mlmStaContext.cleanupTrigger == eLIM_PEER_ENTITY_DEAUTH)) {
+ /**
+ * Received Disassociation/Deauthentication from peer.
+ * Issue Purge Ind to SME.
+ */
+ lim_log(pMac, LOGW,
+ FL("Lim Posting PURGE_STA_IND to Sme. Trigger: %d"),
+ mlmStaContext.cleanupTrigger);
+ cdf_mem_copy((uint8_t *) &mlmPurgeStaInd.peerMacAddr,
+ (uint8_t *) staDsAddr, sizeof(tSirMacAddr));
+ mlmPurgeStaInd.reasonCode =
+ (uint8_t) mlmStaContext.disassocReason;
+ mlmPurgeStaInd.aid = staDsAssocId;
+ mlmPurgeStaInd.purgeTrigger = mlmStaContext.cleanupTrigger;
+ mlmPurgeStaInd.sessionId = psessionEntry->peSessionId;
+
+ lim_post_sme_message(pMac,
+ LIM_MLM_PURGE_STA_IND,
+ (uint32_t *) &mlmPurgeStaInd);
+ } else if (mlmStaContext.cleanupTrigger == eLIM_JOIN_FAILURE) {
+ /* PE setup the peer entry in HW upfront, right after join is completed. */
+ /* If there is a failure during rest of the assoc sequence, this context needs to be cleaned up. */
+ uint8_t smesessionId;
+ uint16_t smetransactionId;
+
+ smesessionId = psessionEntry->smeSessionId;
+ smetransactionId = psessionEntry->transactionId;
+
+ psessionEntry->limSmeState = eLIM_SME_JOIN_FAILURE_STATE;
+ MTRACE(mac_trace
+ (pMac, TRACE_CODE_SME_STATE, psessionEntry->peSessionId,
+ psessionEntry->limSmeState));
+
+ /* if it is a reassoc failure to join new AP */
+ if ((mlmStaContext.resultCode ==
+ eSIR_SME_FT_REASSOC_TIMEOUT_FAILURE)
+ || (mlmStaContext.resultCode == eSIR_SME_FT_REASSOC_FAILURE)
+ || (mlmStaContext.resultCode ==
+ eSIR_SME_REASSOC_TIMEOUT_RESULT_CODE)) {
+ lim_log(pMac, LOG1,
+ FL("Lim Posting eWNI_SME_REASSOC_RSP to SME"
+ "resultCode: %d, statusCode: %d,"
+ "sessionId: %d"),
+ mlmStaContext.resultCode,
+ mlmStaContext.protStatusCode,
+ psessionEntry->peSessionId);
+
+ if (mlmStaContext.resultCode != eSIR_SME_SUCCESS) {
+ pe_delete_session(pMac, psessionEntry);
+ psessionEntry = NULL;
+ }
+
+ lim_send_sme_join_reassoc_rsp(pMac, eWNI_SME_REASSOC_RSP,
+ mlmStaContext.resultCode,
+ mlmStaContext.protStatusCode,
+ psessionEntry, smesessionId,
+ smetransactionId);
+ } else {
+ cdf_mem_free(psessionEntry->pLimJoinReq);
+ psessionEntry->pLimJoinReq = NULL;
+
+ lim_log(pMac, LOG1,
+ FL("Lim Posting eWNI_SME_JOIN_RSP to SME."
+ "resultCode: %d,statusCode: %d,"
+ "sessionId: %d"),
+ mlmStaContext.resultCode,
+ mlmStaContext.protStatusCode,
+ psessionEntry->peSessionId);
+
+ if (mlmStaContext.resultCode != eSIR_SME_SUCCESS) {
+ pe_delete_session(pMac, psessionEntry);
+ psessionEntry = NULL;
+ }
+
+ lim_send_sme_join_reassoc_rsp(pMac, eWNI_SME_JOIN_RSP,
+ mlmStaContext.resultCode,
+ mlmStaContext.protStatusCode,
+ psessionEntry, smesessionId,
+ smetransactionId);
+ }
+
+ }
+
+ if (NULL != psessionEntry && !LIM_IS_AP_ROLE(psessionEntry)) {
+ pe_delete_session(pMac, psessionEntry);
+ psessionEntry = NULL;
+ }
+}
+
+/**
+ * lim_reject_association() - function to reject Re/Association Request
+ *
+ * @mac_ctx: pointer to global mac structure
+ * @peer_addr: mac address of the peer
+ * @sub_type: Indicates whether it is Association Request (=0) or
+ * Reassociation Request (=1) frame
+ * @add_pre_auth_context:Indicates whether pre-auth context
+ * to be added for this STA
+ * @auth_type: Indicates auth type to be added
+ * @sta_id: Indicates staId of the STA being rejected
+ * association
+ * @delete_sta: Indicates whether to delete STA context
+ * at Polaris
+ * @result_code: Indicates what reasonCode to be sent in
+ * Re/Assoc response to STA
+ * @session_entry: pointer to PE session
+ *
+ * This function is called whenever Re/Association Request need
+ * to be rejected due to failure in assigning an AID or failure
+ * in adding STA context at Polaris or reject by applications.
+ * Resources allocated if any are freedup and (Re) Association
+ * Response frame is sent to requesting STA. Pre-Auth context
+ * will be added for this STA if it does not exist already
+ *
+ * Return: none
+ */
+
+void
+lim_reject_association(tpAniSirGlobal mac_ctx, tSirMacAddr peer_addr,
+ uint8_t sub_type, uint8_t add_pre_auth_context,
+ tAniAuthType auth_type, uint16_t sta_id,
+ uint8_t delete_sta, tSirResultCodes result_code,
+ tpPESession session_entry)
+{
+ tpDphHashNode sta_ds;
+
+ lim_log(mac_ctx, LOG1,
+ FL("Sessionid: %d auth_type: %d sub_type: %d add_pre_auth_context: %d sta_id: %d delete_sta: %d result_code : %d peer_addr: " MAC_ADDRESS_STR),
+ session_entry->peSessionId, auth_type, sub_type,
+ add_pre_auth_context, sta_id, delete_sta, result_code,
+ MAC_ADDR_ARRAY(peer_addr));
+
+ if (add_pre_auth_context) {
+ /* Create entry for this STA in pre-auth list */
+ struct tLimPreAuthNode *auth_node;
+
+ auth_node = lim_acquire_free_pre_auth_node(mac_ctx,
+ &mac_ctx->lim.gLimPreAuthTimerTable);
+
+ if (auth_node) {
+ cdf_mem_copy((uint8_t *) auth_node->peerMacAddr,
+ peer_addr, sizeof(tSirMacAddr));
+ auth_node->fTimerStarted = 0;
+ auth_node->mlmState = eLIM_MLM_AUTHENTICATED_STATE;
+ auth_node->authType = (tAniAuthType) auth_type;
+ auth_node->timestamp = cdf_mc_timer_get_system_ticks();
+ lim_add_pre_auth_node(mac_ctx, auth_node);
+ }
+ }
+
+ if (delete_sta == false) {
+ lim_send_assoc_rsp_mgmt_frame(mac_ctx,
+ eSIR_MAC_MAX_ASSOC_STA_REACHED_STATUS,
+ 1, peer_addr, sub_type, 0, session_entry);
+ /* Log error */
+ lim_log(mac_ctx, LOGW,
+ FL("received Re/Assoc req when max associated STAs reached from "));
+ lim_print_mac_addr(mac_ctx, peer_addr, LOGW);
+ lim_send_sme_max_assoc_exceeded_ntf(mac_ctx, peer_addr,
+ session_entry->smeSessionId);
+ return;
+ }
+
+ sta_ds = dph_get_hash_entry(mac_ctx, sta_id,
+ &session_entry->dph.dphHashTable);
+
+ if (sta_ds == NULL) {
+ lim_log(mac_ctx, LOGW,
+ FL("No STA context, yet rejecting Association"));
+ return;
+ }
+
+ /*
+ * Polaris has state for this STA.
+ * Trigger cleanup.
+ */
+ sta_ds->mlmStaContext.cleanupTrigger = eLIM_REASSOC_REJECT;
+
+ /* Receive path cleanup */
+ lim_cleanup_rx_path(mac_ctx, sta_ds, session_entry);
+
+ /*
+ * Send Re/Association Response with
+ * status code to requesting STA.
+ */
+ lim_send_assoc_rsp_mgmt_frame(mac_ctx, result_code, 0, peer_addr,
+ sub_type, 0, session_entry);
+
+ if (session_entry->parsedAssocReq[sta_ds->assocId] != NULL) {
+ uint8_t *assoc_req_frame;
+
+ assoc_req_frame = (uint8_t *)((tpSirAssocReq) (session_entry->
+ parsedAssocReq[sta_ds->assocId]))->assocReqFrame;
+ /*
+ *Assoction confirmation is complete,
+ *free the copy of association request frame.
+ */
+ if (assoc_req_frame) {
+ cdf_mem_free(assoc_req_frame);
+ assoc_req_frame = NULL;
+ }
+
+ cdf_mem_free(session_entry->parsedAssocReq[sta_ds->assocId]);
+ session_entry->parsedAssocReq[sta_ds->assocId] = NULL;
+ }
+}
+
+/**
+ * lim_decide_ap_protection_on_ht20_delete() - function to update protection
+ * parameters.
+ * @mac_ctx: pointer to global mac structure
+ * @sta_ds: station node
+ * @beacon_params: ap beacon parameters
+ * @session_entry: pe session entry
+ *
+ * protection related function while HT20 station is getting deleted.
+ *
+ * Return: none
+ */
+static void
+lim_decide_ap_protection_on_ht20_delete(tpAniSirGlobal mac_ctx,
+ tpDphHashNode sta_ds,
+ tpUpdateBeaconParams beacon_params,
+ tpPESession session_entry)
+{
+ uint32_t i = 0;
+
+ lim_log(mac_ctx, LOG1,
+ FL("(%d) A HT 20 STA is disassociated. Addr is %pM"),
+ session_entry->gLimHt20Params.numSta, sta_ds->staAddr);
+
+ if (session_entry->gLimHt20Params.numSta > 0) {
+ for (i = 0; i < LIM_PROT_STA_CACHE_SIZE; i++) {
+ if (!session_entry->protStaCache[i].active)
+ continue;
+
+ if (cdf_mem_compare(session_entry->protStaCache[i].addr,
+ sta_ds->staAddr, sizeof(tSirMacAddr))) {
+ session_entry->gLimHt20Params.numSta--;
+ session_entry->protStaCache[i].active =
+ false;
+ break;
+ }
+ }
+ }
+
+ if (session_entry->gLimHt20Params.numSta == 0) {
+ /* disable protection */
+ lim_log(mac_ctx, LOG1, FL("No 11B STA exists, PESessionID %d"),
+ session_entry->peSessionId);
+ lim_enable_ht20_protection(mac_ctx, false, false, beacon_params,
+ session_entry);
+ }
+}
+
+/**
+ * lim_decide_ap_protection_on_delete() - update SAP protection on station
+ * deletion.
+ * @mac_ctx: pointer to global mac structure
+ * @sta_ds: station node
+ * @beacon_params: ap beacon parameters
+ * @session_entry: pe session entry
+ *
+ * Decides about protection related settings when a station is getting deleted.
+ *
+ * Return: none
+ */
+void
+lim_decide_ap_protection_on_delete(tpAniSirGlobal mac_ctx,
+ tpDphHashNode sta_ds,
+ tpUpdateBeaconParams beacon_params,
+ tpPESession session_entry)
+{
+ uint32_t phy_mode;
+ tHalBitVal erp_enabled = eHAL_CLEAR;
+ tSirRFBand rf_band = SIR_BAND_UNKNOWN;
+ uint32_t i;
+
+ if (NULL == sta_ds)
+ return;
+
+ lim_get_rf_band_new(mac_ctx, &rf_band, session_entry);
+ lim_get_phy_mode(mac_ctx, &phy_mode, session_entry);
+ erp_enabled = sta_ds->erpEnabled;
+
+ if ((SIR_BAND_5_GHZ == rf_band) &&
+ (true == session_entry->htCapability) &&
+ (session_entry->beaconParams.llaCoexist) &&
+ (false == sta_ds->mlmStaContext.htCapability)) {
+ /*
+ * we are HT. if we are 11A, then protection is not required or
+ * we are HT and 11A station is leaving.
+ * protection consideration required.
+ * HT station leaving ==> this case is commonly handled
+ * between both the bands below.
+ */
+ lim_log(mac_ctx, LOG1,
+ FL("(%d) A 11A STA is disassociated. Addr is %pM"),
+ session_entry->gLim11aParams.numSta, sta_ds->staAddr);
+ for (i = 0; i < LIM_PROT_STA_CACHE_SIZE; i++) {
+ if (session_entry->protStaCache[i].active &&
+ cdf_mem_compare(
+ session_entry->protStaCache[i].addr,
+ sta_ds->staAddr,
+ sizeof(tSirMacAddr))) {
+ session_entry->protStaCache[i].active = false;
+ break;
+ }
+ }
+
+ if (session_entry->gLim11aParams.numSta == 0) {
+ /* disable protection */
+ lim_update_11a_protection(mac_ctx, false, false,
+ beacon_params, session_entry);
+ }
+ }
+
+ /* we are HT or 11G and 11B station is getting deleted */
+ if ((SIR_BAND_2_4_GHZ == rf_band) &&
+ (phy_mode == WNI_CFG_PHY_MODE_11G ||
+ session_entry->htCapability) &&
+ (erp_enabled == eHAL_CLEAR)) {
+ lim_log(mac_ctx, LOG1,
+ FL("(%d) A legacy STA is disassociated. Addr is %pM"),
+ session_entry->gLim11bParams.numSta, sta_ds->staAddr);
+ for (i = 0; i < LIM_PROT_STA_CACHE_SIZE; i++) {
+ if (session_entry->protStaCache[i].active &&
+ cdf_mem_compare(
+ session_entry->protStaCache[i].addr,
+ sta_ds->staAddr,
+ sizeof(tSirMacAddr))) {
+ session_entry->gLim11bParams.numSta--;
+ session_entry->protStaCache[i].active =
+ false;
+ break;
+ }
+ }
+
+ if (session_entry->gLim11bParams.numSta == 0) {
+ /* disable protection */
+ lim_enable11g_protection(mac_ctx, false, false,
+ beacon_params, session_entry);
+ }
+ }
+
+ /*
+ * we are HT AP and non-11B station is leaving.
+ * 11g station is leaving
+ */
+ if ((SIR_BAND_2_4_GHZ == rf_band) &&
+ session_entry->htCapability &&
+ !sta_ds->mlmStaContext.htCapability) {
+ lim_log(mac_ctx, LOG1,
+ FL("(%d) A 11g STA is disassociated. Addr is %pM"),
+ session_entry->gLim11bParams.numSta, sta_ds->staAddr);
+ for (i = 0; i < LIM_PROT_STA_CACHE_SIZE; i++) {
+ if (session_entry->protStaCache[i].active &&
+ cdf_mem_compare(
+ session_entry->protStaCache[i].addr,
+ sta_ds->staAddr,
+ sizeof(tSirMacAddr))) {
+ session_entry->gLim11gParams.numSta--;
+ session_entry->protStaCache[i].active = false;
+ break;
+ }
+ }
+
+ if (session_entry->gLim11gParams.numSta == 0) {
+ /* disable protection */
+ lim_enable_ht_protection_from11g(mac_ctx, false, false,
+ beacon_params,
+ session_entry);
+ }
+ }
+
+ if (!((true == session_entry->htCapability) &&
+ (true == sta_ds->mlmStaContext.htCapability)))
+ return;
+
+ /*
+ * Applies to 2.4 as well as 5 GHZ.
+ * HT non-GF leaving
+ */
+ if (!sta_ds->htGreenfield) {
+ lim_log(mac_ctx, LOG1,
+ FL("(%d) A non-GF STA is disassociated. Addr is %pM"),
+ session_entry->gLimNonGfParams.numSta, sta_ds->staAddr);
+ for (i = 0; i < LIM_PROT_STA_CACHE_SIZE; i++) {
+ if (session_entry->protStaCache[i].active &&
+ cdf_mem_compare(
+ session_entry->protStaCache[i].addr,
+ sta_ds->staAddr,
+ sizeof(tSirMacAddr))) {
+ session_entry->protStaCache[i].active = false;
+ break;
+ }
+ }
+
+ if (session_entry->gLimNonGfParams.numSta == 0) {
+ /* disable protection */
+ lim_enable_ht_non_gf_protection(mac_ctx, false, false,
+ beacon_params, session_entry);
+ }
+ }
+
+ /*
+ * Applies to 2.4 as well as 5 GHZ.
+ * HT 20Mhz station leaving
+ */
+ if (session_entry->beaconParams.ht20Coexist &&
+ (eHT_CHANNEL_WIDTH_20MHZ ==
+ sta_ds->htSupportedChannelWidthSet)) {
+ lim_decide_ap_protection_on_ht20_delete(mac_ctx, sta_ds,
+ beacon_params, session_entry);
+ }
+
+ /*
+ * Applies to 2.4 as well as 5 GHZ.
+ * LSIG TXOP not supporting staiton leaving
+ */
+ if ((false == session_entry->beaconParams.
+ fLsigTXOPProtectionFullSupport) &&
+ (false == sta_ds->htLsigTXOPProtection)) {
+ lim_log(mac_ctx, LOG1,
+ FL("(%d) A HT LSIG not supporting STA is disassociated. Addr is %pM"),
+ session_entry->gLimLsigTxopParams.numSta,
+ sta_ds->staAddr);
+ for (i = 0; i < LIM_PROT_STA_CACHE_SIZE; i++) {
+ if (session_entry->protStaCache[i].active &&
+ cdf_mem_compare(
+ session_entry->protStaCache[i].addr,
+ sta_ds->staAddr,
+ sizeof(tSirMacAddr))) {
+ session_entry->protStaCache[i].active = false;
+ break;
+ }
+ }
+
+ if (session_entry->gLimLsigTxopParams.numSta == 0) {
+ /* disable protection */
+ lim_enable_ht_lsig_txop_protection(mac_ctx, true,
+ false, beacon_params, session_entry);
+ }
+ }
+}
+
+/**
+ * lim_decide_short_preamble() - update short preamble parameters
+ * @mac_ctx: pointer to global mac structure
+ * @sta_ds: station node
+ * @beacon_params: ap beacon parameters
+ * @session_entry: pe session entry
+ *
+ * Decides about any short preamble related change because of new station
+ * joining.
+ *
+ * Return: None
+ */
+void lim_decide_short_preamble(tpAniSirGlobal mac_ctx,
+ tpDphHashNode sta_ds,
+ tpUpdateBeaconParams beacon_params,
+ tpPESession session_entry)
+{
+ uint32_t i;
+
+ if (sta_ds->shortPreambleEnabled == eHAL_CLEAR) {
+ lim_log(mac_ctx, LOG1,
+ FL("(%d) A non-short preamble STA is disassociated. Addr is %pM"),
+ session_entry->gLimNoShortParams.numNonShortPreambleSta,
+ sta_ds->staAddr);
+ for (i = 0; i < LIM_PROT_STA_CACHE_SIZE; i++) {
+ if (session_entry->gLimNoShortParams.
+ staNoShortCache[i].active &&
+ cdf_mem_compare(session_entry->
+ gLimNoShortParams.
+ staNoShortCache[i].addr,
+ sta_ds->staAddr,
+ sizeof(tSirMacAddr))) {
+ session_entry->gLimNoShortParams.
+ numNonShortPreambleSta--;
+ session_entry->gLimNoShortParams.
+ staNoShortCache[i].active = false;
+ break;
+ }
+ }
+
+ if (session_entry->gLimNoShortParams.numNonShortPreambleSta)
+ return;
+
+ /*
+ * enable short preamble
+ * reset the cache
+ */
+ cdf_mem_set((uint8_t *) &session_entry->gLimNoShortParams,
+ sizeof(tLimNoShortParams), 0);
+ if (lim_enable_short_preamble(mac_ctx, true,
+ beacon_params, session_entry) != eSIR_SUCCESS) {
+ lim_log(mac_ctx, LOGE,
+ FL("Cannot enable short preamble"));
+ }
+ }
+}
+
+/**
+ * lim_decide_short_slot() - update short slot time related parameters
+ * @mac_ctx: pointer to global mac structure
+ * @sta_ds: station node
+ * @beacon_params: ap beacon parameters
+ * @session_entry: pe session entry
+ *
+ * Decides about any short slot time related change because of station leaving
+ * the BSS.
+ * Return: None
+ */
+void
+lim_decide_short_slot(tpAniSirGlobal mac_ctx, tpDphHashNode sta_ds,
+ tpUpdateBeaconParams beacon_params,
+ tpPESession session_entry)
+{
+ uint32_t i, val, non_short_slot_sta_count;
+
+ if (sta_ds->shortSlotTimeEnabled != eHAL_CLEAR)
+ return;
+
+ lim_log(mac_ctx, LOG1,
+ FL("(%d) A non-short slottime STA is disassociated. Addr is %pM"),
+ mac_ctx->lim.gLimNoShortSlotParams.numNonShortSlotSta,
+ sta_ds->staAddr);
+
+ wlan_cfg_get_int(mac_ctx, WNI_CFG_11G_SHORT_SLOT_TIME_ENABLED,
+ &val);
+
+ if (LIM_IS_AP_ROLE(session_entry)) {
+ non_short_slot_sta_count =
+ session_entry->gLimNoShortSlotParams.numNonShortSlotSta;
+ for (i = 0; i < LIM_PROT_STA_CACHE_SIZE; i++) {
+ if (session_entry->gLimNoShortSlotParams.
+ staNoShortSlotCache[i].active &&
+ cdf_mem_compare(session_entry->
+ gLimNoShortSlotParams.
+ staNoShortSlotCache[i].addr,
+ sta_ds->staAddr,
+ sizeof(tSirMacAddr))) {
+ non_short_slot_sta_count--;
+ session_entry->gLimNoShortSlotParams.
+ staNoShortSlotCache[i].active = false;
+ break;
+ }
+ }
+
+ if (non_short_slot_sta_count == 0 && val) {
+ /*
+ * enable short slot time
+ * reset the cache
+ */
+ cdf_mem_set((uint8_t *) &session_entry->
+ gLimNoShortSlotParams,
+ sizeof(tLimNoShortSlotParams), 0);
+ beacon_params->fShortSlotTime = true;
+ beacon_params->paramChangeBitmap |=
+ PARAM_SHORT_SLOT_TIME_CHANGED;
+ session_entry->shortSlotTimeSupported = true;
+ }
+ session_entry->gLimNoShortSlotParams.numNonShortSlotSta =
+ non_short_slot_sta_count;
+ } else {
+ non_short_slot_sta_count =
+ mac_ctx->lim.gLimNoShortSlotParams.numNonShortSlotSta;
+ for (i = 0; i < LIM_PROT_STA_CACHE_SIZE; i++) {
+ if (mac_ctx->lim.gLimNoShortSlotParams.
+ staNoShortSlotCache[i].active &&
+ cdf_mem_compare(
+ mac_ctx->lim.gLimNoShortSlotParams.
+ staNoShortSlotCache[i].addr,
+ sta_ds->staAddr,
+ sizeof(tSirMacAddr))) {
+ non_short_slot_sta_count--;
+ mac_ctx->lim.gLimNoShortSlotParams.
+ staNoShortSlotCache[i].active = false;
+ break;
+ }
+ }
+
+ if (val && !non_short_slot_sta_count) {
+ /*
+ * enable short slot time
+ * reset the cache
+ */
+ cdf_mem_set(
+ (uint8_t *) &mac_ctx->lim.gLimNoShortSlotParams,
+ sizeof(tLimNoShortSlotParams), 0);
+ /*in case of AP set SHORT_SLOT_TIME to enable*/
+ if (LIM_IS_AP_ROLE(session_entry)) {
+ beacon_params->fShortSlotTime = true;
+ beacon_params->paramChangeBitmap |=
+ PARAM_SHORT_SLOT_TIME_CHANGED;
+ session_entry->shortSlotTimeSupported = true;
+ }
+ }
+ mac_ctx->lim.gLimNoShortSlotParams.numNonShortSlotSta =
+ non_short_slot_sta_count;
+ }
+}
+
+void
+lim_post_reassoc_failure(tpAniSirGlobal pMac,
+ tSirResultCodes resultCode,
+ uint16_t protStatusCode, tpPESession psessionEntry)
+{
+ tLimMlmReassocCnf mlmReassocCnf;
+
+ psessionEntry->limMlmState = eLIM_MLM_LINK_ESTABLISHED_STATE;
+ MTRACE(mac_trace
+ (pMac, TRACE_CODE_MLM_STATE, psessionEntry->peSessionId,
+ eLIM_MLM_LINK_ESTABLISHED_STATE));
+
+ /* 'Change' timer for future activations */
+ lim_deactivate_and_change_timer(pMac, eLIM_REASSOC_FAIL_TIMER);
+
+ mlmReassocCnf.resultCode = resultCode;
+ mlmReassocCnf.protStatusCode = protStatusCode;
+ /* Update PE session Id */
+ mlmReassocCnf.sessionId = psessionEntry->peSessionId;
+ lim_post_sme_message(pMac,
+ LIM_MLM_REASSOC_CNF, (uint32_t *) &mlmReassocCnf);
+} /*** end lim_post_reassoc_failure() ***/
+
+/**
+ * lim_restore_pre_reassoc_state()
+ *
+ ***FUNCTION:
+ * This function is called on STA role whenever Reasociation
+ * Response with a reject code is received from AP.
+ *
+ ***LOGIC:
+ * Reassociation failure timer is stopped, Old (or current) AP's
+ * context is restored both at Polaris & software
+ *
+ ***ASSUMPTIONS:
+ *
+ ***NOTE:
+ *
+ * @param pMac - Pointer to Global MAC structure
+ * @param resultCode - Result code that specifies why Reassociation
+ * attemp failed
+ *
+ * @return None
+ */
+
+void
+lim_restore_pre_reassoc_state(tpAniSirGlobal pMac,
+ tSirResultCodes resultCode,
+ uint16_t protStatusCode, tpPESession psessionEntry)
+{
+ tLimMlmReassocCnf mlmReassocCnf;
+
+ lim_log(pMac, LOG1,
+ FL("sessionid: %d protStatusCode: %d resultCode: %d"),
+ psessionEntry->smeSessionId, protStatusCode, resultCode);
+
+ psessionEntry->limMlmState = eLIM_MLM_LINK_ESTABLISHED_STATE;
+ MTRACE(mac_trace
+ (pMac, TRACE_CODE_MLM_STATE, psessionEntry->peSessionId,
+ eLIM_MLM_LINK_ESTABLISHED_STATE));
+
+ /* 'Change' timer for future activations */
+ lim_deactivate_and_change_timer(pMac, eLIM_REASSOC_FAIL_TIMER);
+
+ lim_set_channel(pMac, psessionEntry->currentOperChannel,
+ psessionEntry->ch_center_freq_seg0,
+ psessionEntry->ch_center_freq_seg1,
+ psessionEntry->ch_width,
+ psessionEntry->maxTxPower,
+ psessionEntry->peSessionId);
+
+ /** @ToDo : Need to Integrate the STOP the DataTransfer to the AP from 11H code */
+
+ mlmReassocCnf.resultCode = resultCode;
+ mlmReassocCnf.protStatusCode = protStatusCode;
+ /* Update PE session Id */
+ mlmReassocCnf.sessionId = psessionEntry->peSessionId;
+ lim_post_sme_message(pMac,
+ LIM_MLM_REASSOC_CNF, (uint32_t *) &mlmReassocCnf);
+} /*** end lim_restore_pre_reassoc_state() ***/
+
+/**
+ * lim_is_reassoc_in_progress()
+ *
+ ***FUNCTION:
+ * This function is called to see if STA is in wt-reassoc-rsp state.
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ *
+ ***NOTE:
+ *
+ * @param pMac - Pointer to Global MAC structure
+ *
+ * @return true When STA is waiting for Reassoc response from AP \n
+ * else false
+ */
+
+bool lim_is_reassoc_in_progress(tpAniSirGlobal pMac, tpPESession psessionEntry)
+{
+ if (psessionEntry == NULL) {
+ return false;
+ }
+ if ((LIM_IS_STA_ROLE(psessionEntry) ||
+ LIM_IS_BT_AMP_STA_ROLE(psessionEntry)) &&
+ ((psessionEntry->limSmeState == eLIM_SME_WT_REASSOC_STATE) ||
+ (psessionEntry->limSmeState ==
+ eLIM_SME_WT_REASSOC_LINK_FAIL_STATE)))
+ return true;
+
+ return false;
+} /*** end lim_is_reassoc_in_progress() ***/
+
+#ifdef WLAN_FEATURE_11AC
+/**
+ * lim_populate_vht_mcs_set - function to populate vht mcs rate set
+ * @mac_ctx: pointer to global mac structure
+ * @rates: pointer to supported rate set
+ * @peer_vht_caps: pointer to peer vht capabilities
+ * @session_entry: pe session entry
+ *
+ * Populates vht mcs rate set based on peer and self capabilities
+ *
+ * Return: eSIR_SUCCESS on success else eSIR_FAILURE
+ */
+tSirRetStatus lim_populate_vht_mcs_set(tpAniSirGlobal mac_ctx,
+ tpSirSupportedRates rates,
+ tDot11fIEVHTCaps *peer_vht_caps,
+ tpPESession session_entry)
+{
+ uint32_t val;
+ uint32_t self_sta_dot11mode = 0;
+ uint16_t mcs_map_mask = MCSMAPMASK1x1;
+ uint16_t mcs_map_mask2x2 = 0;
+
+ wlan_cfg_get_int(mac_ctx, WNI_CFG_DOT11_MODE, &self_sta_dot11mode);
+
+ if (!IS_DOT11_MODE_VHT(self_sta_dot11mode))
+ return eSIR_SUCCESS;
+
+ if (wlan_cfg_get_int(mac_ctx, WNI_CFG_VHT_RX_MCS_MAP, &val) !=
+ eSIR_SUCCESS) {
+ lim_log(mac_ctx, LOGE, FL("could not retrieve VHT RX MCS MAP"));
+ goto error;
+ }
+ rates->vhtRxMCSMap = (uint16_t) val;
+
+ if (wlan_cfg_get_int(mac_ctx, WNI_CFG_VHT_TX_MCS_MAP, &val) !=
+ eSIR_SUCCESS) {
+ lim_log(mac_ctx, LOGE, FL("could not retrieve VHT TX MCS MAP"));
+ goto error;
+ }
+ rates->vhtTxMCSMap = (uint16_t) val;
+
+ if (wlan_cfg_get_int(mac_ctx,
+ WNI_CFG_VHT_RX_HIGHEST_SUPPORTED_DATA_RATE,
+ &val) != eSIR_SUCCESS) {
+ lim_log(mac_ctx, LOGE,
+ FL("couldn't retrieve VHT RX Supported data rate MAP"));
+ goto error;
+ }
+ rates->vhtRxHighestDataRate = (uint16_t) val;
+
+ if (wlan_cfg_get_int(mac_ctx,
+ WNI_CFG_VHT_TX_HIGHEST_SUPPORTED_DATA_RATE,
+ &val) != eSIR_SUCCESS) {
+ lim_log(mac_ctx, LOGE,
+ FL("couldn't retrieve VHT RX Supported data rate MAP"));
+ goto error;
+ }
+ rates->vhtTxHighestDataRate = (uint16_t) val;
+
+ if (peer_vht_caps == NULL)
+ return eSIR_SUCCESS;
+
+ rates->vhtTxHighestDataRate =
+ CDF_MIN(rates->vhtTxHighestDataRate,
+ peer_vht_caps->txSupDataRate);
+ rates->vhtRxHighestDataRate =
+ CDF_MIN(rates->vhtRxHighestDataRate,
+ peer_vht_caps->rxHighSupDataRate);
+
+ if (mac_ctx->roam.configParam.enable2x2) {
+ if (session_entry && mac_ctx->lteCoexAntShare &&
+ IS_24G_CH(session_entry->currentOperChannel)) {
+ if (IS_2X2_CHAIN(session_entry->chainMask))
+ mcs_map_mask2x2 = MCSMAPMASK2x2;
+ else
+ lim_log(mac_ctx, LOGE, FL("2x2 not enabled %d"),
+ session_entry->chainMask);
+ } else {
+ mcs_map_mask2x2 = MCSMAPMASK2x2;
+ }
+ }
+
+ if ((peer_vht_caps->txMCSMap & mcs_map_mask) <
+ (rates->vhtRxMCSMap & mcs_map_mask)) {
+ rates->vhtRxMCSMap &= ~(mcs_map_mask);
+ rates->vhtRxMCSMap |=
+ (peer_vht_caps->txMCSMap & mcs_map_mask);
+ }
+ if ((peer_vht_caps->rxMCSMap & mcs_map_mask) <
+ (rates->vhtTxMCSMap & mcs_map_mask)) {
+ rates->vhtTxMCSMap &= ~(mcs_map_mask);
+ rates->vhtTxMCSMap |=
+ (peer_vht_caps->rxMCSMap & mcs_map_mask);
+ }
+
+ if (mcs_map_mask2x2) {
+
+ uint16_t peer_mcs_map, self_mcs_map;
+
+ peer_mcs_map =
+ peer_vht_caps->txMCSMap & mcs_map_mask2x2;
+ self_mcs_map =
+ rates->vhtRxMCSMap & mcs_map_mask2x2;
+
+ if ((self_mcs_map != mcs_map_mask2x2) &&
+ ((peer_mcs_map == mcs_map_mask2x2) ||
+ (peer_mcs_map < self_mcs_map))) {
+ rates->vhtRxMCSMap &= ~mcs_map_mask2x2;
+ rates->vhtRxMCSMap |= peer_mcs_map;
+ }
+
+ peer_mcs_map =
+ (peer_vht_caps->rxMCSMap & mcs_map_mask2x2);
+ self_mcs_map =
+ (rates->vhtTxMCSMap & mcs_map_mask2x2);
+
+ if ((self_mcs_map != mcs_map_mask2x2) &&
+ ((peer_mcs_map == mcs_map_mask2x2) ||
+ (peer_mcs_map < self_mcs_map))) {
+ rates->vhtTxMCSMap &= ~mcs_map_mask2x2;
+ rates->vhtTxMCSMap |= peer_mcs_map;
+ }
+ }
+
+ lim_log(mac_ctx, LOG1,
+ FL("enable2x2 - %d vhtRxMCSMap - %x vhtTxMCSMap - %x\n"),
+ mac_ctx->roam.configParam.enable2x2,
+ rates->vhtRxMCSMap, rates->vhtTxMCSMap);
+
+ return eSIR_SUCCESS;
+error:
+
+ return eSIR_FAILURE;
+}
+#endif
+
+/**
+ * lim_populate_own_rate_set() - comprises the basic and extended rates read
+ * from CFG
+ * @mac_ctx: pointer to global mac structure
+ * @rates: pointer to supported rates
+ * @supported_mcs_set: pointer to supported mcs rates
+ * @basic_only: update only basic rates if set true
+ * @session_entry: pe session entry
+ * @vht_caps: pointer to vht capability
+ *
+ * This function is called by limProcessAssocRsp() or
+ * lim_add_staInIBSS()
+ * - It creates a combined rate set of 12 rates max which
+ * comprises the basic and extended rates read from CFG
+ * - It sorts the combined rate Set and copy it in the
+ * rate array of the pSTA descriptor
+ * - It sets the erpEnabled bit of the STA descriptor
+ * ERP bit is set iff the dph PHY mode is 11G and there is at least
+ * an A rate in the supported or extended rate sets
+ *
+ * Return: eSIR_SUCCESS or eSIR_FAILURE.
+ */
+#ifdef WLAN_FEATURE_11AC
+tSirRetStatus
+lim_populate_own_rate_set(tpAniSirGlobal mac_ctx,
+ tpSirSupportedRates rates, uint8_t *supported_mcs_set,
+ uint8_t basic_only, tpPESession session_entry,
+ tDot11fIEVHTCaps *vht_caps)
+#else
+tSirRetStatus
+lim_populate_own_rate_set(tpAniSirGlobal mac_ctx,
+ tpSirSupportedRates rates,
+ uint8_t *supported_mcs_set,
+ uint8_t basic_only, tpPESession session_entry)
+#endif
+{
+ tSirMacRateSet temp_rate_set;
+ tSirMacRateSet temp_rate_set2;
+ uint32_t i, j, val, min, is_arate;
+ uint32_t phy_mode = 0;
+ uint32_t self_sta_dot11mode = 0;
+ uint8_t a_rate_index = 0;
+ uint8_t b_rate_index = 0;
+
+
+ is_arate = 0;
+
+ wlan_cfg_get_int(mac_ctx, WNI_CFG_DOT11_MODE, &self_sta_dot11mode);
+ lim_get_phy_mode(mac_ctx, &phy_mode, session_entry);
+
+ /*
+ * Include 11b rates only when the device configured in
+ * auto, 11a/b/g or 11b_only
+ */
+ if ((self_sta_dot11mode == WNI_CFG_DOT11_MODE_ALL) ||
+ (self_sta_dot11mode == WNI_CFG_DOT11_MODE_11A) ||
+ (self_sta_dot11mode == WNI_CFG_DOT11_MODE_11AC) ||
+ (self_sta_dot11mode == WNI_CFG_DOT11_MODE_11N) ||
+ (self_sta_dot11mode == WNI_CFG_DOT11_MODE_11G) ||
+ (self_sta_dot11mode == WNI_CFG_DOT11_MODE_11B)) {
+ val = WNI_CFG_SUPPORTED_RATES_11B_LEN;
+ wlan_cfg_get_str(mac_ctx, WNI_CFG_SUPPORTED_RATES_11B,
+ (uint8_t *) &temp_rate_set.rate, &val);
+ temp_rate_set.numRates = (uint8_t) val;
+ } else {
+ temp_rate_set.numRates = 0;
+ }
+
+ /* Include 11a rates when the device configured in non-11b mode */
+ if (!IS_DOT11_MODE_11B(self_sta_dot11mode)) {
+ val = WNI_CFG_SUPPORTED_RATES_11A_LEN;
+ wlan_cfg_get_str(mac_ctx, WNI_CFG_SUPPORTED_RATES_11A,
+ (uint8_t *) &temp_rate_set2.rate, &val);
+ temp_rate_set2.numRates = (uint8_t) val;
+ } else {
+ temp_rate_set2.numRates = 0;
+ }
+
+ if ((temp_rate_set.numRates + temp_rate_set2.numRates) > 12) {
+ /* we are in big trouble */
+ lim_log(mac_ctx, LOGP, FL("more than 12 rates in CFG"));
+ /* panic */
+ goto error;
+ }
+ /* copy all rates in temp_rate_set, there are 12 rates max */
+ for (i = 0; i < temp_rate_set2.numRates; i++)
+ temp_rate_set.rate[i + temp_rate_set.numRates] =
+ temp_rate_set2.rate[i];
+
+ temp_rate_set.numRates += temp_rate_set2.numRates;
+
+ /**
+ * Sort rates in temp_rate_set (they are likely to be already sorted)
+ * put the result in pSupportedRates
+ */
+
+ cdf_mem_set((uint8_t *) rates, sizeof(tSirSupportedRates), 0);
+ for (i = 0; i < temp_rate_set.numRates; i++) {
+ min = 0;
+ val = 0xff;
+ is_arate = 0;
+
+ for (j = 0; (j < temp_rate_set.numRates) &&
+ (j < SIR_MAC_RATESET_EID_MAX); j++) {
+ if ((uint32_t) (temp_rate_set.rate[j] & 0x7f) <
+ val) {
+ val = temp_rate_set.rate[j] & 0x7f;
+ min = j;
+ }
+ }
+
+ if (sirIsArate(temp_rate_set.rate[min] & 0x7f))
+ is_arate = 1;
+
+ /*
+ * HAL needs to know whether the rate is basic rate or
+ * not, as it needs to update the response rate table
+ * accordingly. e.g. if one of the 11a rates is
+ * basic rate, then that rate can be used for sending
+ * control frames.
+ * HAL updates the response rate table whenever basic
+ * rate set is changed.
+ */
+ if (basic_only && temp_rate_set.rate[min] & 0x80) {
+ if (is_arate)
+ rates->llaRates[a_rate_index++] =
+ temp_rate_set.rate[min];
+ else
+ rates->llbRates[b_rate_index++] =
+ temp_rate_set.rate[min];
+ } else {
+ if (is_arate)
+ rates->llaRates[a_rate_index++] =
+ temp_rate_set.rate[min];
+ else
+ rates->llbRates[b_rate_index++] =
+ temp_rate_set.rate[min];
+ }
+ temp_rate_set.rate[min] = 0xff;
+ }
+
+ if (IS_DOT11_MODE_HT(self_sta_dot11mode)) {
+ val = SIZE_OF_SUPPORTED_MCS_SET;
+ if (wlan_cfg_get_str(mac_ctx, WNI_CFG_SUPPORTED_MCS_SET,
+ rates->supportedMCSSet,
+ &val) != eSIR_SUCCESS) {
+ /* Could not get rateset from CFG. Log error. */
+ lim_log(mac_ctx, LOGE,
+ FL("could not retrieve supportedMCSSet"));
+ goto error;
+ }
+
+ /*
+ * if supported MCS Set of the peer is passed in,
+ * then do the intersection
+ * else use the MCS set from local CFG.
+ */
+
+ if (supported_mcs_set != NULL) {
+ for (i = 0; i < SIR_MAC_MAX_SUPPORTED_MCS_SET; i++)
+ rates->supportedMCSSet[i] &=
+ supported_mcs_set[i];
+ }
+
+ lim_log(mac_ctx, LOG2, FL("MCS Rate Set Bitmap: "));
+ for (i = 0; i < SIR_MAC_MAX_SUPPORTED_MCS_SET; i++)
+ PELOG2(lim_log(mac_ctx, LOG2, FL("%x "),
+ rates->supportedMCSSet[i]);)
+ }
+#ifdef WLAN_FEATURE_11AC
+ lim_populate_vht_mcs_set(mac_ctx, rates, vht_caps, session_entry);
+#endif
+
+ return eSIR_SUCCESS;
+error:
+ return eSIR_FAILURE;
+}
+
+#ifdef WLAN_FEATURE_11AC
+tSirRetStatus
+lim_populate_peer_rate_set(tpAniSirGlobal pMac,
+ tpSirSupportedRates pRates,
+ uint8_t *pSupportedMCSSet,
+ uint8_t basicOnly,
+ tpPESession psessionEntry, tDot11fIEVHTCaps *pVHTCaps)
+#else
+tSirRetStatus
+lim_populate_peer_rate_set(tpAniSirGlobal pMac,
+ tpSirSupportedRates pRates,
+ uint8_t *pSupportedMCSSet,
+ uint8_t basicOnly, tpPESession psessionEntry)
+#endif
+{
+ tSirMacRateSet tempRateSet;
+ tSirMacRateSet tempRateSet2;
+ uint32_t i, j, val, min, isArate;
+ isArate = 0;
+
+ /* copy operational rate set from psessionEntry */
+ if (psessionEntry->rateSet.numRates <= SIR_MAC_RATESET_EID_MAX) {
+ cdf_mem_copy((uint8_t *) tempRateSet.rate,
+ (uint8_t *) (psessionEntry->rateSet.rate),
+ psessionEntry->rateSet.numRates);
+ tempRateSet.numRates = psessionEntry->rateSet.numRates;
+ } else {
+ lim_log(pMac, LOGE,
+ FL("more than SIR_MAC_RATESET_EID_MAX rates\n"));
+ goto error;
+ }
+ if ((psessionEntry->dot11mode == WNI_CFG_DOT11_MODE_11G) ||
+ (psessionEntry->dot11mode == WNI_CFG_DOT11_MODE_11A) ||
+ (psessionEntry->dot11mode == WNI_CFG_DOT11_MODE_11AC) ||
+ (psessionEntry->dot11mode == WNI_CFG_DOT11_MODE_11N)) {
+ if (psessionEntry->extRateSet.numRates <=
+ SIR_MAC_RATESET_EID_MAX) {
+ cdf_mem_copy((uint8_t *) tempRateSet2.rate,
+ (uint8_t *) (psessionEntry->extRateSet.
+ rate),
+ psessionEntry->extRateSet.numRates);
+ tempRateSet2.numRates =
+ psessionEntry->extRateSet.numRates;
+ } else {
+ lim_log(pMac, LOGE,
+ FL
+ ("psessionEntry->extRateSet.numRates more than SIR_MAC_RATESET_EID_MAX rates\n"));
+ goto error;
+ }
+ } else
+ tempRateSet2.numRates = 0;
+ if ((tempRateSet.numRates + tempRateSet2.numRates) >
+ SIR_MAC_RATESET_EID_MAX) {
+ /* we are in big trouble */
+ lim_log(pMac, LOGP, FL("more than 12 rates in CFG"));
+ goto error;
+ }
+
+ /* copy all rates in tempRateSet, there are 12 rates max */
+ for (i = 0; i < tempRateSet2.numRates; i++)
+ tempRateSet.rate[i + tempRateSet.numRates] =
+ tempRateSet2.rate[i];
+ tempRateSet.numRates += tempRateSet2.numRates;
+ /**
+ * Sort rates in tempRateSet (they are likely to be already sorted)
+ * put the result in pSupportedRates
+ */
+ {
+ uint8_t aRateIndex = 0;
+ uint8_t bRateIndex = 0;
+ cdf_mem_set((uint8_t *) pRates, sizeof(tSirSupportedRates), 0);
+ for (i = 0; i < tempRateSet.numRates; i++) {
+ min = 0;
+ val = 0xff;
+ isArate = 0;
+ for (j = 0;
+ (j < tempRateSet.numRates)
+ && (j < SIR_MAC_RATESET_EID_MAX); j++) {
+ if ((uint32_t) (tempRateSet.rate[j] & 0x7f) <
+ val) {
+ val = tempRateSet.rate[j] & 0x7f;
+ min = j;
+ }
+ }
+ if (sirIsArate(tempRateSet.rate[min] & 0x7f))
+ isArate = 1;
+ /*
+ * HAL needs to know whether the rate is basic rate or not, as it needs to
+ * update the response rate table accordingly. e.g. if one of the 11a rates is
+ * basic rate, then that rate can be used for sending control frames.
+ * HAL updates the response rate table whenever basic rate set is changed.
+ */
+ if (basicOnly) {
+ if (tempRateSet.rate[min] & 0x80) {
+ if (isArate)
+ pRates->llaRates[aRateIndex++] =
+ tempRateSet.rate[min];
+ else
+ pRates->llbRates[bRateIndex++] =
+ tempRateSet.rate[min];
+ }
+ } else {
+ if (isArate)
+ pRates->llaRates[aRateIndex++] =
+ tempRateSet.rate[min];
+ else
+ pRates->llbRates[bRateIndex++] =
+ tempRateSet.rate[min];
+ }
+ tempRateSet.rate[min] = 0xff;
+ }
+ }
+
+ if (IS_DOT11_MODE_HT(psessionEntry->dot11mode)) {
+ val = SIZE_OF_SUPPORTED_MCS_SET;
+ if (wlan_cfg_get_str(pMac, WNI_CFG_SUPPORTED_MCS_SET,
+ pRates->supportedMCSSet,
+ &val) != eSIR_SUCCESS) {
+ /* / Could not get rateset from CFG. Log error. */
+ PELOGE(lim_log
+ (pMac, LOGE,
+ FL("could not retrieve supportedMCSSet"));
+ )
+ goto error;
+ }
+ /* if supported MCS Set of the peer is passed in, then do the intersection */
+ /* else use the MCS set from local CFG. */
+ if (pSupportedMCSSet != NULL) {
+ for (i = 0; i < SIR_MAC_MAX_SUPPORTED_MCS_SET; i++)
+ pRates->supportedMCSSet[i] &=
+ pSupportedMCSSet[i];
+ }
+ PELOG2(lim_log(pMac, LOG2, FL("MCS Rate Set Bitmap: "));)
+ for (i = 0; i < SIR_MAC_MAX_SUPPORTED_MCS_SET; i++)
+ PELOG2(lim_log
+ (pMac, LOG2, FL("%x "),
+ pRates->supportedMCSSet[i]);
+ )
+ }
+#ifdef WLAN_FEATURE_11AC
+ lim_populate_vht_mcs_set(pMac, pRates, pVHTCaps, psessionEntry);
+#endif
+ return eSIR_SUCCESS;
+error:
+ return eSIR_FAILURE;
+} /*** lim_populate_peer_rate_set() ***/
+
+/**
+ * lim_populate_matching_rate_set() -process the CFG rate sets and
+ * the rate sets received in the Assoc request on AP.
+ * @mac_ctx: pointer to global mac structure
+ * @sta_ds: station node
+ * @oper_rate_set: pointer to operating rate set
+ * @ext_rate_set: pointer to extended rate set
+ * @supported_mcs_set: pointer to supported rate set
+ * @session_entry: pointer to pe session entry
+ * @vht_caps: pointer to vht capabilities
+ *
+ * This is called at the time of Association Request
+ * processing on AP and while adding peer's context
+ * in IBSS role to process the CFG rate sets and
+ * the rate sets received in the Assoc request on AP
+ * or Beacon/Probe Response from peer in IBSS.
+ *
+ * 1. It makes the intersection between our own rate Sat
+ * and extemcded rate set and the ones received in the
+ * association request.
+ * 2. It creates a combined rate set of 12 rates max which
+ * comprised the basic and extended rates
+ * 3. It sorts the combined rate Set and copy it in the
+ * rate array of the pSTA descriptor
+ *
+ * The parser has already ensured unicity of the rates in the
+ * association request structure
+ *
+ * Return: eSIR_SUCCESS on success else eSIR_FAILURE
+ */
+#ifdef WLAN_FEATURE_11AC
+tSirRetStatus
+lim_populate_matching_rate_set(tpAniSirGlobal mac_ctx, tpDphHashNode sta_ds,
+ tSirMacRateSet *oper_rate_set, tSirMacRateSet *ext_rate_set,
+ uint8_t *supported_mcs_set, tpPESession session_entry,
+ tDot11fIEVHTCaps * vht_caps)
+#else
+tSirRetStatus
+lim_populate_matching_rate_set(tpAniSirGlobal mac_ctx, tpDphHashNode sta_ds,
+ tSirMacRateSet *oper_rate_set, tSirMacRateSet *ext_rate_set,
+ uint8_t *supported_mcs_set, tpPESession session_entry)
+#endif
+{
+ tSirMacRateSet temp_rate_set;
+ tSirMacRateSet temp_rate_set2;
+ uint32_t i, j, val, min, is_arate;
+ uint32_t phy_mode;
+ uint8_t mcs_set[SIZE_OF_SUPPORTED_MCS_SET];
+ tpSirSupportedRates rates;
+ uint8_t a_rate_index = 0;
+ uint8_t b_rate_index = 0;
+
+ is_arate = 0;
+
+ lim_get_phy_mode(mac_ctx, &phy_mode, session_entry);
+
+ /* copy operational rate set from session_entry */
+ cdf_mem_copy((temp_rate_set.rate), (session_entry->rateSet.rate),
+ session_entry->rateSet.numRates);
+ temp_rate_set.numRates = (uint8_t) session_entry->rateSet.numRates;
+
+ if (phy_mode == WNI_CFG_PHY_MODE_11G) {
+ cdf_mem_copy((temp_rate_set2.rate),
+ (session_entry->extRateSet.rate),
+ session_entry->extRateSet.numRates);
+ temp_rate_set2.numRates =
+ (uint8_t) session_entry->extRateSet.numRates;
+ } else {
+ temp_rate_set2.numRates = 0;
+ }
+
+ if ((temp_rate_set.numRates + temp_rate_set2.numRates) > 12) {
+ lim_log(mac_ctx, LOGE, FL("more than 12 rates in CFG"));
+ goto error;
+ }
+
+ /*
+ * Handling of the rate set IEs is the following:
+ * - keep only rates that we support and that the station supports
+ * - sort and the rates into the pSta->rate array
+ */
+
+ /* Copy all rates in temp_rate_set, there are 12 rates max */
+ for (i = 0; i < temp_rate_set2.numRates; i++)
+ temp_rate_set.rate[i + temp_rate_set.numRates] =
+ temp_rate_set2.rate[i];
+
+ temp_rate_set.numRates += temp_rate_set2.numRates;
+
+ /*
+ * Sort rates in temp_rate_set (they are likely to be already sorted)
+ * put the result in temp_rate_set2
+ */
+ temp_rate_set2.numRates = 0;
+
+ for (i = 0; i < temp_rate_set.numRates; i++) {
+ min = 0;
+ val = 0xff;
+
+ for (j = 0; j < temp_rate_set.numRates; j++)
+ if ((uint32_t) (temp_rate_set.rate[j] & 0x7f) < val) {
+ val = temp_rate_set.rate[j] & 0x7f;
+ min = j;
+ }
+
+ temp_rate_set2.rate[temp_rate_set2.numRates++] =
+ temp_rate_set.rate[min];
+ temp_rate_set.rate[min] = 0xff;
+ }
+
+ /*
+ * Copy received rates in temp_rate_set, the parser has ensured
+ * unicity of the rates so there cannot be more than 12
+ */
+ for (i = 0; (i < oper_rate_set->numRates &&
+ i < SIR_MAC_RATESET_EID_MAX); i++)
+ temp_rate_set.rate[i] = oper_rate_set->rate[i];
+
+ temp_rate_set.numRates = oper_rate_set->numRates;
+
+ lim_log(mac_ctx, LOG2,
+ "Sum of SUPPORTED and EXTENDED Rate Set (%1d)",
+ temp_rate_set.numRates + ext_rate_set->numRates);
+
+ if (ext_rate_set->numRates &&
+ ((temp_rate_set.numRates + ext_rate_set->numRates) > 12) &&
+ temp_rate_set.numRates < 12) {
+ int found = 0;
+ int tail = temp_rate_set.numRates;
+
+ for (i = 0; (i < ext_rate_set->numRates &&
+ i < SIR_MAC_RATESET_EID_MAX); i++) {
+ found = 0;
+ for (j = 0; j < (uint32_t) tail; j++) {
+ if ((temp_rate_set.rate[j] & 0x7F) ==
+ (ext_rate_set->rate[i] & 0x7F)) {
+ found = 1;
+ break;
+ }
+ }
+
+ if (!found) {
+ temp_rate_set.rate[temp_rate_set.numRates++] =
+ ext_rate_set->rate[i];
+ if (temp_rate_set.numRates >= 12)
+ break;
+ }
+ }
+ } else if (ext_rate_set->numRates &&
+ ((temp_rate_set.numRates + ext_rate_set->numRates) <= 12)) {
+ for (j = 0; ((j < ext_rate_set->numRates) &&
+ (j < SIR_MAC_RATESET_EID_MAX) &&
+ ((i + j) < SIR_MAC_RATESET_EID_MAX)); j++)
+ temp_rate_set.rate[i + j] = ext_rate_set->rate[j];
+
+ temp_rate_set.numRates += ext_rate_set->numRates;
+ } else if (ext_rate_set->numRates) {
+ lim_log(mac_ctx, LOG2,
+ "Relying only on the SUPPORTED Rate Set IE...");
+ }
+
+
+ rates = &sta_ds->supportedRates;
+ cdf_mem_set((uint8_t *) rates, sizeof(tSirSupportedRates), 0);
+ for (i = 0; (i < temp_rate_set2.numRates &&
+ i < SIR_MAC_RATESET_EID_MAX); i++) {
+ for (j = 0; (j < temp_rate_set.numRates &&
+ j < SIR_MAC_RATESET_EID_MAX); j++) {
+ if ((temp_rate_set2.rate[i] & 0x7F) !=
+ (temp_rate_set.rate[j] & 0x7F))
+ continue;
+
+ if (sirIsArate(temp_rate_set2.rate[i] & 0x7f) &&
+ a_rate_index < SIR_NUM_11A_RATES) {
+ is_arate = 1;
+ rates->llaRates[a_rate_index++] =
+ temp_rate_set2.rate[i];
+ } else if ((b_rate_index < SIR_NUM_11B_RATES) &&
+ !(sirIsArate(temp_rate_set2.rate[i] & 0x7f))) {
+ rates->llbRates[b_rate_index++] =
+ temp_rate_set2.rate[i];
+ }
+ break;
+ }
+ }
+
+ /*
+ * Now add the Polaris rates only when Proprietary rates are enabled.
+ * compute the matching MCS rate set, if peer is 11n capable and self
+ * mode is 11n
+ */
+#ifdef FEATURE_WLAN_TDLS
+ if (sta_ds->mlmStaContext.htCapability)
+#else
+ if (IS_DOT11_MODE_HT(session_entry->dot11mode) &&
+ (sta_ds->mlmStaContext.htCapability))
+#endif
+ {
+ val = SIZE_OF_SUPPORTED_MCS_SET;
+ if (wlan_cfg_get_str(mac_ctx, WNI_CFG_SUPPORTED_MCS_SET,
+ mcs_set, &val) != eSIR_SUCCESS) {
+ /* Could not get rateset from CFG. Log error. */
+ lim_log(mac_ctx, LOGP,
+ FL("could not retrieve supportedMCSet"));
+ goto error;
+ }
+
+ for (i = 0; i < val; i++)
+ sta_ds->supportedRates.supportedMCSSet[i] =
+ mcs_set[i] & supported_mcs_set[i];
+
+ lim_log(mac_ctx, LOG2,
+ FL("lim_populate_matching_rate_set: MCS Rate Set Bitmap"
+ " from CFG and DPH : "));
+ for (i = 0; i < SIR_MAC_MAX_SUPPORTED_MCS_SET; i++) {
+ lim_log(mac_ctx, LOG2, FL("%x %x "), mcs_set[i],
+ sta_ds->supportedRates.supportedMCSSet[i]);
+ }
+ }
+#ifdef WLAN_FEATURE_11AC
+ lim_populate_vht_mcs_set(mac_ctx, &sta_ds->supportedRates, vht_caps,
+ session_entry);
+#endif
+ /*
+ * Set the erpEnabled bit if the phy is in G mode and at least
+ * one A rate is supported
+ */
+ if ((phy_mode == WNI_CFG_PHY_MODE_11G) && is_arate)
+ sta_ds->erpEnabled = eHAL_SET;
+
+ return eSIR_SUCCESS;
+
+error:
+
+ return eSIR_FAILURE;
+}
+
+/**
+ * lim_populate_vht_caps() - populates vht capabilities based on input
+ * capabilities
+ * @input_caps: input capabilities based on which we format the vht
+ * capabilities
+ *
+ * function to populate the supported vht capabilities.
+ *
+ * Return: vht capabilities derived based on input parameters.
+ */
+static uint32_t lim_populate_vht_caps(tDot11fIEVHTCaps input_caps)
+{
+ uint32_t vht_caps;
+
+ vht_caps = ((input_caps.maxMPDULen << SIR_MAC_VHT_CAP_MAX_MPDU_LEN) |
+ (input_caps.supportedChannelWidthSet <<
+ SIR_MAC_VHT_CAP_SUPP_CH_WIDTH_SET) |
+ (input_caps.ldpcCodingCap <<
+ SIR_MAC_VHT_CAP_LDPC_CODING_CAP) |
+ (input_caps.shortGI80MHz <<
+ SIR_MAC_VHT_CAP_SHORTGI_80MHZ) |
+ (input_caps.shortGI160and80plus80MHz <<
+ SIR_MAC_VHT_CAP_SHORTGI_160_80_80MHZ) |
+ (input_caps.txSTBC << SIR_MAC_VHT_CAP_TXSTBC) |
+ (input_caps.rxSTBC << SIR_MAC_VHT_CAP_RXSTBC) |
+ (input_caps.suBeamFormerCap <<
+ SIR_MAC_VHT_CAP_SU_BEAMFORMER_CAP) |
+ (input_caps.suBeamformeeCap <<
+ SIR_MAC_VHT_CAP_SU_BEAMFORMEE_CAP) |
+ (input_caps.csnofBeamformerAntSup <<
+ SIR_MAC_VHT_CAP_CSN_BEAMORMER_ANT_SUP) |
+ (input_caps.numSoundingDim <<
+ SIR_MAC_VHT_CAP_NUM_SOUNDING_DIM) |
+ (input_caps.muBeamformerCap <<
+ SIR_MAC_VHT_CAP_NUM_BEAM_FORMER_CAP) |
+ (input_caps.muBeamformeeCap <<
+ SIR_MAC_VHT_CAP_NUM_BEAM_FORMEE_CAP) |
+ (input_caps.vhtTXOPPS <<
+ SIR_MAC_VHT_CAP_TXOPPS) |
+ (input_caps.htcVHTCap <<
+ SIR_MAC_VHT_CAP_HTC_CAP) |
+ (input_caps.maxAMPDULenExp <<
+ SIR_MAC_VHT_CAP_MAX_AMDU_LEN_EXPO) |
+ (input_caps.vhtLinkAdaptCap <<
+ SIR_MAC_VHT_CAP_LINK_ADAPT_CAP) |
+ (input_caps.rxAntPattern <<
+ SIR_MAC_VHT_CAP_RX_ANTENNA_PATTERN) |
+ (input_caps.txAntPattern <<
+ SIR_MAC_VHT_CAP_TX_ANTENNA_PATTERN) |
+ (input_caps.reserved1 <<
+ SIR_MAC_VHT_CAP_RESERVED2));
+
+ return vht_caps;
+}
+/**
+ * lim_add_sta()- called to add an STA context at hardware
+ * @mac_ctx: pointer to global mac structure
+ * @sta_ds: station node
+ * @update_entry: set to true for updating the entry
+ * @session_entry: pe session entry
+ *
+ * This function is called to add an STA context at hardware
+ * whenever a STA is (Re) Associated.
+ *
+ * Return: eSIR_SUCCESS on success else eSirRetStatus failure codes
+ */
+
+tSirRetStatus
+lim_add_sta(tpAniSirGlobal mac_ctx,
+ tpDphHashNode sta_ds, uint8_t update_entry, tpPESession session_entry)
+{
+ tpAddStaParams add_sta_params = NULL;
+ tSirMsgQ msg_q;
+ tSirRetStatus ret_code = eSIR_SUCCESS;
+ tSirMacAddr sta_mac, *sta_Addr;
+ uint8_t i, nw_type_11b = 0;
+ tpSirAssocReq assoc_req;
+ tLimIbssPeerNode *peer_node; /* for IBSS mode */
+ uint8_t *p2p_ie = NULL;
+
+ sir_copy_mac_addr(sta_mac, session_entry->selfMacAddr);
+
+ lim_log(mac_ctx, LOG1,
+ FL("sessionid: %d update_entry = %d limsystemrole = %d "),
+ session_entry->smeSessionId, update_entry,
+ GET_LIM_SYSTEM_ROLE(session_entry));
+
+ add_sta_params = cdf_mem_malloc(sizeof(tAddStaParams));
+ if (NULL == add_sta_params) {
+ lim_log(mac_ctx, LOGP,
+ FL("Unable to allocate memory during ADD_STA"));
+ return eSIR_MEM_ALLOC_FAILED;
+ }
+ cdf_mem_set((uint8_t *) add_sta_params, sizeof(tAddStaParams), 0);
+
+ if (LIM_IS_AP_ROLE(session_entry) || LIM_IS_IBSS_ROLE(session_entry) ||
+ LIM_IS_BT_AMP_AP_ROLE(session_entry))
+ sta_Addr = &sta_ds->staAddr;
+#ifdef FEATURE_WLAN_TDLS
+ /* SystemRole shouldn't be matter if staType is TDLS peer */
+ else if (STA_ENTRY_TDLS_PEER == sta_ds->staType)
+ sta_Addr = &sta_ds->staAddr;
+#endif
+ else
+ sta_Addr = &sta_mac;
+
+ lim_log(mac_ctx, LOG1,
+ FL(MAC_ADDRESS_STR ": Subtype(Assoc/Reassoc): %d"),
+ MAC_ADDR_ARRAY(*sta_Addr), sta_ds->mlmStaContext.subType);
+
+ cdf_mem_copy((uint8_t *) add_sta_params->staMac,
+ (uint8_t *) *sta_Addr, sizeof(tSirMacAddr));
+ cdf_mem_copy((uint8_t *) add_sta_params->bssId,
+ session_entry->bssId, sizeof(tSirMacAddr));
+ cdf_mem_copy(&add_sta_params->capab_info,
+ &sta_ds->mlmStaContext.capabilityInfo,
+ sizeof(add_sta_params->capab_info));
+
+ lim_fill_supported_rates_info(mac_ctx, sta_ds, &sta_ds->supportedRates,
+ session_entry);
+
+ /* Copy legacy rates */
+ cdf_mem_copy((uint8_t *) &add_sta_params->supportedRates,
+ (uint8_t *) &sta_ds->supportedRates,
+ sizeof(tSirSupportedRates));
+
+ add_sta_params->assocId = sta_ds->assocId;
+
+ add_sta_params->wmmEnabled = sta_ds->qosMode;
+ add_sta_params->listenInterval = sta_ds->mlmStaContext.listenInterval;
+ add_sta_params->shortPreambleSupported = sta_ds->shortPreambleEnabled;
+ if (LIM_IS_AP_ROLE(session_entry) &&
+ (sta_ds->mlmStaContext.subType == LIM_REASSOC)) {
+ /*
+ * TBD - need to remove this REASSOC check
+ * after fixinf rmmod issue
+ */
+ add_sta_params->updateSta = sta_ds->mlmStaContext.updateContext;
+ }
+ sta_ds->valid = 0;
+ sta_ds->mlmStaContext.mlmState = eLIM_MLM_WT_ADD_STA_RSP_STATE;
+
+ lim_log(mac_ctx, LOG2,
+ FL(" Assoc ID: %d wmmEnabled = %d listenInterval = %d"
+ " shortPreambleSupported: %d "), add_sta_params->assocId,
+ add_sta_params->wmmEnabled, add_sta_params->listenInterval,
+ add_sta_params->shortPreambleSupported);
+ /* This will indicate HAL to "allocate" a new STA index */
+#ifdef FEATURE_WLAN_TDLS
+ /*
+ * As there is corner case in-between add_sta and change_sta,if del_sta
+ * for other staIdx happened, firmware return wrong staIdx
+ * (recently removed staIdx). Until we get a confirmation from the
+ * firmware team it is now return correct staIdx for same sta_mac_addr
+ * for update case, we want to get around it by passing valid staIdx
+ * given by add_sta time.
+ */
+ if ((STA_ENTRY_TDLS_PEER == sta_ds->staType) && (true == update_entry))
+ add_sta_params->staIdx = sta_ds->staIndex;
+ else
+#endif
+ add_sta_params->staIdx = STA_INVALID_IDX;
+ add_sta_params->staType = sta_ds->staType;
+
+ add_sta_params->updateSta = update_entry;
+
+ add_sta_params->status = CDF_STATUS_SUCCESS;
+ add_sta_params->respReqd = 1;
+ /* Update HT Capability */
+
+ if (LIM_IS_AP_ROLE(session_entry) ||
+ LIM_IS_BT_AMP_AP_ROLE(session_entry) ||
+ LIM_IS_IBSS_ROLE(session_entry)) {
+ add_sta_params->htCapable = sta_ds->mlmStaContext.htCapability;
+#ifdef WLAN_FEATURE_11AC
+ add_sta_params->vhtCapable =
+ sta_ds->mlmStaContext.vhtCapability;
+#endif
+ }
+#ifdef FEATURE_WLAN_TDLS
+ /* SystemRole shouldn't be matter if staType is TDLS peer */
+ else if (STA_ENTRY_TDLS_PEER == sta_ds->staType) {
+ add_sta_params->htCapable = sta_ds->mlmStaContext.htCapability;
+#ifdef WLAN_FEATURE_11AC
+ add_sta_params->vhtCapable =
+ sta_ds->mlmStaContext.vhtCapability;
+#endif
+ }
+#endif
+ else {
+ add_sta_params->htCapable = session_entry->htCapability;
+#ifdef WLAN_FEATURE_11AC
+ add_sta_params->vhtCapable = session_entry->vhtCapability;
+#endif
+
+ }
+#ifdef WLAN_FEATURE_11AC
+ lim_log(mac_ctx, LOG2, FL("vhtCapable: %d "),
+ add_sta_params->vhtCapable);
+#endif
+ lim_log(mac_ctx, LOG2, FL(" StaIdx: %d updateSta = %d htcapable = %d "),
+ add_sta_params->staIdx, add_sta_params->updateSta,
+ add_sta_params->htCapable);
+
+ add_sta_params->greenFieldCapable = sta_ds->htGreenfield;
+ add_sta_params->maxAmpduDensity = sta_ds->htAMpduDensity;
+ add_sta_params->maxAmpduSize = sta_ds->htMaxRxAMpduFactor;
+ add_sta_params->fDsssCckMode40Mhz = sta_ds->htDsssCckRate40MHzSupport;
+ add_sta_params->fShortGI20Mhz = sta_ds->htShortGI20Mhz;
+ add_sta_params->fShortGI40Mhz = sta_ds->htShortGI40Mhz;
+ add_sta_params->lsigTxopProtection = sta_ds->htLsigTXOPProtection;
+ add_sta_params->maxAmsduSize = sta_ds->htMaxAmsduLength;
+ add_sta_params->ch_width = sta_ds->htSupportedChannelWidthSet;
+ add_sta_params->mimoPS = sta_ds->htMIMOPSState;
+
+ lim_log(mac_ctx, LOG2,
+ FL("greenFieldCapable: %d maxAmpduDensity = %d maxAmpduDensity = %d"),
+ add_sta_params->greenFieldCapable,
+ add_sta_params->maxAmpduDensity, add_sta_params->maxAmpduSize);
+
+ lim_log(mac_ctx, LOG2,
+ FL("fDsssCckMode40Mhz: %d fShortGI20Mhz: %d fShortGI40Mhz: %d"),
+ add_sta_params->fDsssCckMode40Mhz,
+ add_sta_params->fShortGI20Mhz, add_sta_params->fShortGI40Mhz);
+
+ lim_log(mac_ctx, LOG2,
+ FL("lsigTxopProtection: %d maxAmsduSize: %d txChannelWidth: %d mimoPS: %d "),
+ add_sta_params->lsigTxopProtection,
+ add_sta_params->maxAmsduSize, add_sta_params->ch_width,
+ add_sta_params->mimoPS);
+
+ if (add_sta_params->vhtCapable) {
+ if (sta_ds->vhtSupportedChannelWidthSet)
+ add_sta_params->ch_width =
+ sta_ds->vhtSupportedChannelWidthSet + 1;
+
+ add_sta_params->vhtSupportedRxNss = sta_ds->vhtSupportedRxNss;
+ add_sta_params->vhtTxBFCapable =
+#ifdef FEATURE_WLAN_TDLS
+ ((STA_ENTRY_PEER == sta_ds->staType)
+ || (STA_ENTRY_TDLS_PEER == sta_ds->staType)) ?
+ sta_ds->vhtBeamFormerCapable :
+ session_entry->txBFIniFeatureEnabled;
+#else
+ (STA_ENTRY_PEER == sta_ds->staType) ?
+ sta_ds->vhtBeamFormerCapable :
+ session_entry->txBFIniFeatureEnabled;
+#endif
+ add_sta_params->enable_su_tx_bformer =
+ sta_ds->vht_su_bfee_capable;
+ }
+
+ lim_log(mac_ctx, LOGE, FL("TxChWidth %d vhtTxBFCap %d, su_bfer %d"),
+ add_sta_params->ch_width, add_sta_params->vhtTxBFCapable,
+ add_sta_params->enable_su_tx_bformer);
+#ifdef FEATURE_WLAN_TDLS
+ if ((STA_ENTRY_PEER == sta_ds->staType) ||
+ (STA_ENTRY_TDLS_PEER == sta_ds->staType))
+#else
+ if (STA_ENTRY_PEER == sta_ds->staType)
+#endif
+ {
+ /*
+ * peer STA get the LDPC capability from sta_ds,
+ * which populated from
+ * HT/VHT capability
+ */
+ if (add_sta_params->vhtTxBFCapable
+ && mac_ctx->lim.disableLDPCWithTxbfAP) {
+ add_sta_params->htLdpcCapable = 0;
+ add_sta_params->vhtLdpcCapable = 0;
+ } else {
+ add_sta_params->htLdpcCapable = sta_ds->htLdpcCapable;
+ add_sta_params->vhtLdpcCapable = sta_ds->vhtLdpcCapable;
+ }
+ } else if (STA_ENTRY_SELF == sta_ds->staType) {
+ /* For Self STA get the LDPC capability from config.ini */
+ add_sta_params->htLdpcCapable =
+ (session_entry->txLdpcIniFeatureEnabled & 0x01);
+ add_sta_params->vhtLdpcCapable =
+ ((session_entry->txLdpcIniFeatureEnabled >> 1) & 0x01);
+ }
+
+ /* Update PE session ID */
+ add_sta_params->sessionId = session_entry->peSessionId;
+
+ /* Update SME session ID */
+ add_sta_params->smesessionId = session_entry->smeSessionId;
+
+ add_sta_params->maxTxPower = session_entry->maxTxPower;
+
+ if (session_entry->parsedAssocReq != NULL) {
+ uint16_t aid = sta_ds->assocId;
+ /* Get a copy of the already parsed Assoc Request */
+ assoc_req =
+ (tpSirAssocReq) session_entry->parsedAssocReq[aid];
+ if (assoc_req && assoc_req->addIEPresent
+ && assoc_req->addIE.length) {
+ p2p_ie = limGetP2pIEPtr(mac_ctx,
+ assoc_req->addIE.addIEdata,
+ assoc_req->addIE.length);
+ }
+
+ add_sta_params->p2pCapableSta = (p2p_ie != NULL);
+ if (assoc_req && add_sta_params->htCapable) {
+ cdf_mem_copy(&add_sta_params->ht_caps,
+ ((uint8_t *) &assoc_req->HTCaps) + 1,
+ sizeof(add_sta_params->ht_caps));
+ }
+
+ if (assoc_req && add_sta_params->vhtCapable)
+ add_sta_params->vht_caps =
+ lim_populate_vht_caps(assoc_req->VHTCaps);
+ } else if (LIM_IS_IBSS_ROLE(session_entry)) {
+
+ /*
+ * in IBSS mode, use peer node as the source of ht_caps
+ * and vht_caps
+ */
+ peer_node = lim_ibss_peer_find(mac_ctx, *sta_Addr);
+ if (!peer_node) {
+ lim_log(mac_ctx, LOGP,
+ FL("Can't find IBSS peer node for ADD_STA"));
+ return eSIR_HAL_STA_DOES_NOT_EXIST;
+ }
+
+ if (peer_node->atimIePresent) {
+ add_sta_params->atimIePresent =
+ peer_node->atimIePresent;
+ add_sta_params->peerAtimWindowLength =
+ peer_node->peerAtimWindowLength;
+ }
+
+ add_sta_params->ht_caps =
+ (peer_node->htSupportedChannelWidthSet <<
+ SIR_MAC_HT_CAP_CHWIDTH40_S) |
+ (peer_node->htGreenfield <<
+ SIR_MAC_HT_CAP_GREENFIELD_S) |
+ (peer_node->htShortGI20Mhz <<
+ SIR_MAC_HT_CAP_SHORTGI20MHZ_S) |
+ (peer_node->htShortGI40Mhz <<
+ SIR_MAC_HT_CAP_SHORTGI40MHZ_S) |
+ (SIR_MAC_TXSTBC <<
+ SIR_MAC_HT_CAP_TXSTBC_S) |
+ (SIR_MAC_RXSTBC <<
+ SIR_MAC_HT_CAP_RXSTBC_S) |
+ (peer_node->htMaxAmsduLength <<
+ SIR_MAC_HT_CAP_MAXAMSDUSIZE_S) |
+ (peer_node->htDsssCckRate40MHzSupport <<
+ SIR_MAC_HT_CAP_DSSSCCK40_S);
+
+ add_sta_params->vht_caps =
+ lim_populate_vht_caps(peer_node->VHTCaps);
+ }
+#ifdef FEATURE_WLAN_TDLS
+ if (STA_ENTRY_TDLS_PEER == sta_ds->staType) {
+ add_sta_params->ht_caps = sta_ds->ht_caps;
+ add_sta_params->vht_caps = sta_ds->vht_caps;
+
+ lim_log(mac_ctx, LOG1,
+ FL("Sta type is TDLS_PEER, ht_caps: 0x%x, vht_caps: 0x%x"),
+ add_sta_params->ht_caps,
+ add_sta_params->vht_caps);
+ }
+#endif
+
+#ifdef FEATURE_WLAN_TDLS
+ if (sta_ds->wmeEnabled &&
+ (LIM_IS_AP_ROLE(session_entry) ||
+ (STA_ENTRY_TDLS_PEER == sta_ds->staType)))
+#else
+ if (sta_ds->wmeEnabled && LIM_IS_AP_ROLE(session_entry))
+#endif
+ {
+ add_sta_params->uAPSD = 0;
+ /*
+ * update UAPSD and send it to LIM to add STA
+ * bitmap MSB <- LSB MSB 4 bits are for
+ * trigger enabled AC setting and LSB 4 bits
+ * are for delivery enabled AC setting
+ * 7 6 5 4 3 2 1 0
+ * BE BK VI VO BE BK VI VO
+ */
+ add_sta_params->uAPSD |=
+ sta_ds->qos.capability.qosInfo.acvo_uapsd;
+ add_sta_params->uAPSD |=
+ (sta_ds->qos.capability.qosInfo.acvi_uapsd << 1);
+ add_sta_params->uAPSD |=
+ (sta_ds->qos.capability.qosInfo.acbk_uapsd << 2);
+ add_sta_params->uAPSD |=
+ (sta_ds->qos.capability.qosInfo.acbe_uapsd << 3);
+ /*
+ * making delivery enabled and
+ * trigger enabled setting the same.
+ */
+ add_sta_params->uAPSD |= add_sta_params->uAPSD << 4;
+
+ add_sta_params->maxSPLen =
+ sta_ds->qos.capability.qosInfo.maxSpLen;
+ lim_log(mac_ctx, LOG1, FL("uAPSD = 0x%x, maxSpLen = %d"),
+ add_sta_params->uAPSD, add_sta_params->maxSPLen);
+ }
+#ifdef WLAN_FEATURE_11W
+ add_sta_params->rmfEnabled = sta_ds->rmfEnabled;
+ lim_log(mac_ctx, LOG1, FL("PMF enabled %d"),
+ add_sta_params->rmfEnabled);
+#endif
+
+ lim_log(mac_ctx, LOG2, FL("htLdpcCapable: %d vhtLdpcCapable: %d "
+ "p2pCapableSta: %d"),
+ add_sta_params->htLdpcCapable, add_sta_params->vhtLdpcCapable,
+ add_sta_params->p2pCapableSta);
+
+ /*
+ * we need to defer the message until we get the
+ * response back from HAL.
+ */
+ if (add_sta_params->respReqd)
+ SET_LIM_PROCESS_DEFD_MESGS(mac_ctx, false);
+
+ for (i = 0; i < SIR_NUM_11A_RATES; i++) {
+ if (sirIsArate(sta_ds->supportedRates.llaRates[i] & 0x7F)) {
+ nw_type_11b = 0;
+ break;
+ } else {
+ nw_type_11b = 1;
+ }
+ }
+ if (nw_type_11b)
+ add_sta_params->nwType = eSIR_11B_NW_TYPE;
+ else
+ add_sta_params->nwType = session_entry->nwType;
+
+ msg_q.type = WMA_ADD_STA_REQ;
+
+ msg_q.reserved = 0;
+ msg_q.bodyptr = add_sta_params;
+ msg_q.bodyval = 0;
+
+ lim_log(mac_ctx, LOG1, FL("Sending WMA_ADD_STA_REQ for assocId %d"),
+ sta_ds->assocId);
+ MTRACE(mac_trace_msg_tx(mac_ctx, session_entry->peSessionId,
+ msg_q.type));
+
+ ret_code = wma_post_ctrl_msg(mac_ctx, &msg_q);
+ if (eSIR_SUCCESS != ret_code) {
+ if (add_sta_params->respReqd)
+ SET_LIM_PROCESS_DEFD_MESGS(mac_ctx, true);
+ lim_log(mac_ctx, LOGE,
+ FL("ADD_STA_REQ for aId %d failed (reason %X)"),
+ sta_ds->assocId, ret_code);
+ cdf_mem_free(add_sta_params);
+ }
+
+ return ret_code;
+}
+
+/**
+ * lim_del_sta()
+ *
+ ***FUNCTION:
+ * This function is called to delete an STA context at hardware
+ * whenever a STA is disassociated
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ * NA
+ *
+ ***NOTE:
+ * NA
+ *
+ * @param pMac - Pointer to Global MAC structure
+ * @param pStaDs - Pointer to the STA datastructure created by
+ * LIM and maintained by DPH
+ * @param fRespReqd - flag to indicate whether the delete is synchronous (true)
+ * or not (false)
+ * @return retCode - Indicates success or failure return code
+ */
+
+tSirRetStatus
+lim_del_sta(tpAniSirGlobal pMac,
+ tpDphHashNode pStaDs, bool fRespReqd, tpPESession psessionEntry)
+{
+ tpDeleteStaParams pDelStaParams = NULL;
+ tSirMsgQ msgQ;
+ tSirRetStatus retCode = eSIR_SUCCESS;
+
+ pDelStaParams = cdf_mem_malloc(sizeof(tDeleteStaParams));
+ if (NULL == pDelStaParams) {
+ lim_log(pMac, LOGP,
+ FL("Unable to allocate memory during ADD_STA"));
+ return eSIR_MEM_ALLOC_FAILED;
+ }
+
+ cdf_mem_set((uint8_t *) pDelStaParams, sizeof(tDeleteStaParams), 0);
+
+ /* */
+ /* DPH contains the STA index only for "peer" STA entries. */
+ /* LIM global contains "self" STA index */
+ /* Thus, */
+ /* if( STA role ) */
+ /* get STA index from LIM global */
+ /* else */
+ /* get STA index from DPH */
+ /* */
+
+#ifdef FEATURE_WLAN_TDLS
+ if ((LIM_IS_STA_ROLE(psessionEntry) &&
+ (pStaDs->staType != STA_ENTRY_TDLS_PEER)) ||
+ LIM_IS_BT_AMP_STA_ROLE(psessionEntry))
+#else
+ if (LIM_IS_STA_ROLE(psessionEntry) ||
+ LIM_IS_BT_AMP_STA_ROLE(psessionEntry))
+#endif
+ pDelStaParams->staIdx = psessionEntry->staId;
+
+ else
+ pDelStaParams->staIdx = pStaDs->staIndex;
+
+ pDelStaParams->assocId = pStaDs->assocId;
+ pStaDs->valid = 0;
+
+ if (!fRespReqd)
+ pDelStaParams->respReqd = 0;
+ else {
+ /* when lim_del_sta is called from processSmeAssocCnf then mlmState is already set properly. */
+ if (eLIM_MLM_WT_ASSOC_DEL_STA_RSP_STATE !=
+ GET_LIM_STA_CONTEXT_MLM_STATE(pStaDs)) {
+ MTRACE(mac_trace
+ (pMac, TRACE_CODE_MLM_STATE,
+ psessionEntry->peSessionId,
+ eLIM_MLM_WT_DEL_STA_RSP_STATE));
+ SET_LIM_STA_CONTEXT_MLM_STATE(pStaDs,
+ eLIM_MLM_WT_DEL_STA_RSP_STATE);
+ }
+ if (LIM_IS_STA_ROLE(psessionEntry) ||
+ LIM_IS_BT_AMP_STA_ROLE(psessionEntry)) {
+ MTRACE(mac_trace
+ (pMac, TRACE_CODE_MLM_STATE,
+ psessionEntry->peSessionId,
+ eLIM_MLM_WT_DEL_STA_RSP_STATE));
+
+ psessionEntry->limMlmState =
+ eLIM_MLM_WT_DEL_STA_RSP_STATE;
+
+ }
+ pDelStaParams->respReqd = 1;
+ /* we need to defer the message until we get the response back from HAL. */
+ SET_LIM_PROCESS_DEFD_MESGS(pMac, false);
+ }
+
+ /* Update PE session ID */
+ pDelStaParams->sessionId = psessionEntry->peSessionId;
+ pDelStaParams->smesessionId = psessionEntry->smeSessionId;
+
+ pDelStaParams->staType = pStaDs->staType;
+ cdf_mem_copy((uint8_t *) pDelStaParams->staMac,
+ (uint8_t *) pStaDs->staAddr, sizeof(tSirMacAddr));
+
+ pDelStaParams->status = CDF_STATUS_SUCCESS;
+ msgQ.type = WMA_DELETE_STA_REQ;
+ msgQ.reserved = 0;
+ msgQ.bodyptr = pDelStaParams;
+ msgQ.bodyval = 0;
+
+ lim_log(pMac, LOG1, FL("Sessionid %d :Sending SIR_HAL_DELETE_STA_REQ "
+ "for STAID: %X and AssocID: %d MAC : "
+ MAC_ADDRESS_STR), pDelStaParams->sessionId,
+ pDelStaParams->staIdx, pDelStaParams->assocId,
+ MAC_ADDR_ARRAY(pStaDs->staAddr));
+
+ MTRACE(mac_trace_msg_tx(pMac, psessionEntry->peSessionId, msgQ.type));
+ retCode = wma_post_ctrl_msg(pMac, &msgQ);
+ if (eSIR_SUCCESS != retCode) {
+ if (fRespReqd)
+ SET_LIM_PROCESS_DEFD_MESGS(pMac, true);
+ lim_log(pMac, LOGE,
+ FL("Posting DELETE_STA_REQ to HAL failed, reason=%X"),
+ retCode);
+ cdf_mem_free(pDelStaParams);
+ }
+
+ return retCode;
+}
+
+#if defined WLAN_FEATURE_VOWIFI_11R
+/**
+ * lim_add_ft_sta_self()- function to add STA once we have connected with a
+ * new AP
+ * @mac_ctx: pointer to global mac structure
+ * @assoc_id: association id for the station connection
+ * @session_entry: pe session entr
+ *
+ * This function is called to add a STA once we have connected with a new
+ * AP, that we have performed an FT to.
+ *
+ * The Add STA Response is created and now after the ADD Bss Is Successful
+ * we add the self sta. We update with the association id from the reassoc
+ * response from the AP.
+ *
+ * Return: eSIR_SUCCESS on success else eSirRetStatus failure codes
+ */
+tSirRetStatus lim_add_ft_sta_self(tpAniSirGlobal mac_ctx, uint16_t assoc_id,
+ tpPESession session_entry)
+{
+ tpAddStaParams add_sta_params = NULL;
+ tSirRetStatus ret_code = eSIR_SUCCESS;
+ tSirMsgQ msg_q;
+
+ add_sta_params = session_entry->ftPEContext.pAddStaReq;
+ add_sta_params->assocId = assoc_id;
+ add_sta_params->smesessionId = session_entry->smeSessionId;
+
+ msg_q.type = WMA_ADD_STA_REQ;
+ msg_q.reserved = 0;
+ msg_q.bodyptr = add_sta_params;
+ msg_q.bodyval = 0;
+
+#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG
+ CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_DEBUG,
+ "Sending WMA_ADD_STA_REQ (aid %d)",
+ add_sta_params->assocId);
+#endif
+ MTRACE(mac_trace_msg_tx(mac_ctx, session_entry->peSessionId,
+ msg_q.type));
+
+ session_entry->limPrevMlmState = session_entry->limMlmState;
+ MTRACE(mac_trace(mac_ctx, TRACE_CODE_MLM_STATE,
+ session_entry->peSessionId, eLIM_MLM_WT_ADD_STA_RSP_STATE));
+ session_entry->limMlmState = eLIM_MLM_WT_ADD_STA_RSP_STATE;
+ ret_code = wma_post_ctrl_msg(mac_ctx, &msg_q);
+ if (eSIR_SUCCESS != ret_code) {
+ lim_log(mac_ctx, LOGE,
+ FL("Posting WMA_ADD_STA_REQ to HAL failed, reason=%X"),
+ ret_code);
+ cdf_mem_free(add_sta_params);
+ }
+
+ session_entry->ftPEContext.pAddStaReq = NULL;
+ return ret_code;
+}
+#endif /* WLAN_FEATURE_VOWIFI_11R */
+
+/**
+ * lim_add_sta_self()
+ *
+ ***FUNCTION:
+ * This function is called to add an STA context at hardware
+ * whenever a STA is (Re) Associated.
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ * NA
+ *
+ ***NOTE:
+ * NA
+ *
+ * @param pMac - Pointer to Global MAC structure
+ * @param pStaDs - Pointer to the STA datastructure created by
+ * LIM and maintained by DPH
+ * @return retCode - Indicates success or failure return code
+ */
+
+tSirRetStatus
+lim_add_sta_self(tpAniSirGlobal pMac, uint16_t staIdx, uint8_t updateSta,
+ tpPESession psessionEntry)
+{
+ tpAddStaParams pAddStaParams = NULL;
+ tSirMsgQ msgQ;
+ tSirRetStatus retCode = eSIR_SUCCESS;
+ tSirMacAddr staMac;
+ uint32_t listenInterval = WNI_CFG_LISTEN_INTERVAL_STADEF;
+ uint32_t shortGi20MhzSupport;
+ uint32_t shortGi40MhzSupport;
+ uint32_t ampduLenExponent = 0;
+ /*This self Sta dot 11 mode comes from the cfg and the expectation here is
+ * that cfg carries the systemwide capability that device under
+ * consideration can support. This capability gets plumbed into the cfg
+ * cache at system initialization time via the .dat and .ini file override
+ * mechanisms and will not change. If it does change, it is the
+ * responsibility of SME to evict the selfSta and reissue a new AddStaSelf
+ * command.*/
+ uint32_t selfStaDot11Mode = 0, selfTxWidth = 0;
+ uint32_t val;
+ wlan_cfg_get_int(pMac, WNI_CFG_DOT11_MODE, &selfStaDot11Mode);
+ lim_log(pMac, LOG1, FL("cfgDot11Mode %d"), (int)selfStaDot11Mode);
+ wlan_cfg_get_int(pMac, WNI_CFG_HT_CAP_INFO_SUPPORTED_CHAN_WIDTH_SET,
+ &selfTxWidth);
+ lim_log(pMac, LOG1, FL("SGI 20 %d"), (int)selfTxWidth);
+ lim_log(pMac, LOG1, FL("Roam Channel Bonding Mode %d"),
+ (int)pMac->roam.configParam.uCfgDot11Mode);
+
+ sir_copy_mac_addr(staMac, psessionEntry->selfMacAddr);
+ lim_log(pMac, LOG1, FL(MAC_ADDRESS_STR ": "), MAC_ADDR_ARRAY(staMac));
+ pAddStaParams = cdf_mem_malloc(sizeof(tAddStaParams));
+ if (NULL == pAddStaParams) {
+ lim_log(pMac, LOGP,
+ FL("Unable to allocate memory during ADD_STA"));
+ return eSIR_MEM_ALLOC_FAILED;
+ }
+ cdf_mem_set((uint8_t *) pAddStaParams, sizeof(tAddStaParams), 0);
+
+ /* / Add STA context at MAC HW (BMU, RHP & TFP) */
+ cdf_mem_copy((uint8_t *) pAddStaParams->staMac,
+ (uint8_t *) staMac, sizeof(tSirMacAddr));
+
+ cdf_mem_copy((uint8_t *) pAddStaParams->bssId,
+ psessionEntry->bssId, sizeof(tSirMacAddr));
+
+ pAddStaParams->assocId = psessionEntry->limAID;
+ pAddStaParams->staType = STA_ENTRY_SELF;
+ pAddStaParams->status = CDF_STATUS_SUCCESS;
+ pAddStaParams->respReqd = 1;
+
+ /* Update PE session ID */
+ pAddStaParams->sessionId = psessionEntry->peSessionId;
+
+ /* Update SME session ID */
+ pAddStaParams->smesessionId = psessionEntry->smeSessionId;
+
+ pAddStaParams->maxTxPower = psessionEntry->maxTxPower;
+
+ /* This will indicate HAL to "allocate" a new STA index */
+ pAddStaParams->staIdx = staIdx;
+ pAddStaParams->updateSta = updateSta;
+
+ if (wlan_cfg_get_int(pMac, WNI_CFG_SHORT_PREAMBLE, &val) !=
+ eSIR_SUCCESS) {
+ lim_log(pMac, LOGE, FL(
+ "Couldn't get SHORT_PREAMBLE, set default"));
+ pAddStaParams->shortPreambleSupported = 1;
+ } else {
+ pAddStaParams->shortPreambleSupported = val;
+ }
+
+#ifdef WLAN_FEATURE_11AC
+ lim_populate_own_rate_set(pMac, &pAddStaParams->supportedRates, NULL, false,
+ psessionEntry, NULL);
+#else
+ lim_populate_own_rate_set(pMac, &pAddStaParams->supportedRates, NULL, false,
+ psessionEntry);
+#endif
+ if (IS_DOT11_MODE_HT(selfStaDot11Mode)) {
+ pAddStaParams->htCapable = true;
+#ifdef DISABLE_GF_FOR_INTEROP
+ if ((psessionEntry->pLimJoinReq != NULL)
+ && (!psessionEntry->pLimJoinReq->bssDescription.
+ aniIndicator)) {
+ lim_log(pMac, LOGE,
+ FL
+ (" Turning off Greenfield, when adding self entry"));
+ pAddStaParams->greenFieldCapable =
+ WNI_CFG_GREENFIELD_CAPABILITY_DISABLE;
+ } else
+#endif
+ {
+ pAddStaParams->greenFieldCapable =
+ lim_get_ht_capability(pMac, eHT_GREENFIELD,
+ psessionEntry);
+ pAddStaParams->ch_width =
+ pMac->roam.configParam.channelBondingMode5GHz;
+ pAddStaParams->mimoPS =
+ lim_get_ht_capability(pMac, eHT_MIMO_POWER_SAVE,
+ psessionEntry);
+ pAddStaParams->rifsMode =
+ lim_get_ht_capability(pMac, eHT_RIFS_MODE,
+ psessionEntry);
+ pAddStaParams->lsigTxopProtection =
+ lim_get_ht_capability(pMac, eHT_LSIG_TXOP_PROTECTION,
+ psessionEntry);
+ pAddStaParams->maxAmpduDensity =
+ lim_get_ht_capability(pMac, eHT_MPDU_DENSITY,
+ psessionEntry);
+ pAddStaParams->maxAmpduSize =
+ lim_get_ht_capability(pMac, eHT_MAX_RX_AMPDU_FACTOR,
+ psessionEntry);
+ pAddStaParams->maxAmsduSize =
+ lim_get_ht_capability(pMac, eHT_MAX_AMSDU_LENGTH,
+ psessionEntry);
+ pAddStaParams->fDsssCckMode40Mhz =
+ lim_get_ht_capability(pMac, eHT_DSSS_CCK_MODE_40MHZ,
+ psessionEntry);
+ /*
+ * We will read the gShortGI20Mhz from ini file, and if it is set
+ * to 1 then we will tell Peer that we support 40Mhz short GI
+ */
+ if (IS_SIR_STATUS_SUCCESS(wlan_cfg_get_int
+ (pMac, WNI_CFG_SHORT_GI_20MHZ,
+ &shortGi20MhzSupport))) {
+ if (true == shortGi20MhzSupport) {
+ pAddStaParams->fShortGI20Mhz =
+ WNI_CFG_SHORT_GI_20MHZ_STAMAX;
+ } else {
+ pAddStaParams->fShortGI20Mhz = false;
+ }
+ } else {
+ PELOGE(lim_log
+ (pMac, LOGE,
+ FL("could not retrieve shortGI 20Mhz"
+ "CFG,setting value to default"));
+ )
+ pAddStaParams->fShortGI20Mhz =
+ WNI_CFG_SHORT_GI_20MHZ_STADEF;
+ }
+
+ /*
+ * We will read the gShortGI40Mhz from ini file, and if it is set
+ * to 1 then we will tell Peer that we support 40Mhz short GI
+ */
+ if (IS_SIR_STATUS_SUCCESS(wlan_cfg_get_int
+ (pMac, WNI_CFG_SHORT_GI_40MHZ,
+ &shortGi40MhzSupport))) {
+ if (true == shortGi40MhzSupport) {
+ pAddStaParams->fShortGI40Mhz =
+ WNI_CFG_SHORT_GI_40MHZ_STAMAX;
+ } else {
+ pAddStaParams->fShortGI40Mhz = false;
+ }
+ } else {
+ PELOGE(lim_log
+ (pMac, LOGE,
+ FL("could not retrieve shortGI 40Mhz"
+ "CFG,setting value to default"));
+ )
+ pAddStaParams->fShortGI40Mhz =
+ WNI_CFG_SHORT_GI_40MHZ_STADEF;
+ }
+ lim_log(pMac, LOG2,
+ FL(" greenFieldCapable: %d maxAmpduDensity = %d "
+ "maxAmpduSize = %d"),
+ pAddStaParams->greenFieldCapable,
+ pAddStaParams->maxAmpduDensity,
+ pAddStaParams->maxAmpduSize);
+
+ lim_log(pMac, LOG2,
+ FL("fDsssCckMode40Mhz: %d fShortGI20Mhz: %d "
+ "fShortGI40Mhz: %d lsigTxopProtection: %d"),
+ pAddStaParams->fDsssCckMode40Mhz,
+ pAddStaParams->fShortGI20Mhz,
+ pAddStaParams->fShortGI40Mhz,
+ pAddStaParams->lsigTxopProtection);
+
+ lim_log(pMac, LOG2,
+ FL("maxAmsduSize: %d txChannelWidth: %d mimoPS: %d rifsMode %d"),
+ pAddStaParams->maxAmsduSize,
+ pAddStaParams->ch_width,
+ pAddStaParams->mimoPS, pAddStaParams->rifsMode);
+ }
+ }
+#ifdef WLAN_FEATURE_11AC
+ pAddStaParams->vhtCapable = IS_DOT11_MODE_VHT(selfStaDot11Mode);
+ if (pAddStaParams->vhtCapable) {
+ pAddStaParams->ch_width =
+ psessionEntry->ch_width;
+ lim_log(pMac, LOG1, FL("VHT WIDTH SET %d"),
+ pAddStaParams->ch_width);
+ }
+ pAddStaParams->vhtTxBFCapable = psessionEntry->txBFIniFeatureEnabled;
+ pAddStaParams->enable_su_tx_bformer =
+ psessionEntry->enable_su_tx_bformer;
+ lim_log(pMac, LOG2, FL("vhtCapable: %d vhtTxBFCapable %d, su_bfer %d"),
+ pAddStaParams->vhtCapable, pAddStaParams->vhtTxBFCapable,
+ pAddStaParams->enable_su_tx_bformer);
+
+ /* In 11ac mode, the hardware is capable of supporting 128K AMPDU size */
+ if (IS_DOT11_MODE_VHT(selfStaDot11Mode)) {
+ if (wlan_cfg_get_int
+ (pMac, WNI_CFG_VHT_AMPDU_LEN_EXPONENT, &duLenExponent)
+ != eSIR_SUCCESS) {
+ lim_log(pMac, LOGP,
+ FL
+ ("Couldn't get WNI_CFG_VHT_AMPDU_LEN_EXPONENT"));
+ }
+ pAddStaParams->maxAmpduSize = (uint8_t) ampduLenExponent;
+ }
+ pAddStaParams->vhtTxMUBformeeCapable = psessionEntry->txMuBformee;
+ pAddStaParams->enableVhtpAid = psessionEntry->enableVhtpAid;
+#endif
+ pAddStaParams->enableAmpduPs = psessionEntry->enableAmpduPs;
+ pAddStaParams->enableHtSmps = psessionEntry->enableHtSmps;
+ pAddStaParams->htSmpsconfig = psessionEntry->htSmpsvalue;
+
+ /* For Self STA get the LDPC capability from session i.e config.ini */
+ pAddStaParams->htLdpcCapable =
+ (psessionEntry->txLdpcIniFeatureEnabled & 0x01);
+ pAddStaParams->vhtLdpcCapable =
+ ((psessionEntry->txLdpcIniFeatureEnabled >> 1) & 0x01);
+
+ if (wlan_cfg_get_int(pMac, WNI_CFG_LISTEN_INTERVAL, &listenInterval) !=
+ eSIR_SUCCESS)
+ lim_log(pMac, LOGP, FL("Couldn't get LISTEN_INTERVAL"));
+ pAddStaParams->listenInterval = (uint16_t) listenInterval;
+
+ if (CDF_P2P_CLIENT_MODE == psessionEntry->pePersona) {
+ pAddStaParams->p2pCapableSta = 1;
+ }
+
+ pAddStaParams->supportedRates.opRateMode =
+ lim_get_sta_rate_mode((uint8_t) selfStaDot11Mode);
+
+ lim_log(pMac, LOG2, FL(" StaIdx: %d updateSta = %d htcapable = %d "),
+ pAddStaParams->staIdx, pAddStaParams->updateSta,
+ pAddStaParams->htCapable);
+
+ lim_log(pMac, LOG2, FL("htLdpcCapable: %d vhtLdpcCapable: %d "
+ "p2pCapableSta: %d"),
+ pAddStaParams->htLdpcCapable, pAddStaParams->vhtLdpcCapable,
+ pAddStaParams->p2pCapableSta);
+
+ if (psessionEntry->isNonRoamReassoc) {
+ pAddStaParams->nonRoamReassoc = 1;
+ psessionEntry->isNonRoamReassoc = 0;
+ }
+ lim_log(pMac, LOG2, FL("sessionid: %d Assoc ID: %d listenInterval = %d "
+ "shortPreambleSupported: %d"),
+ psessionEntry->smeSessionId, pAddStaParams->assocId,
+ pAddStaParams->listenInterval,
+ pAddStaParams->shortPreambleSupported);
+
+ msgQ.type = WMA_ADD_STA_REQ;
+ msgQ.reserved = 0;
+ msgQ.bodyptr = pAddStaParams;
+ msgQ.bodyval = 0;
+
+ lim_log(pMac, LOG1, FL(MAC_ADDRESS_STR ":Sessionid %d : "
+ "Sending WMA_ADD_STA_REQ. (aid %d)"),
+ MAC_ADDR_ARRAY(pAddStaParams->staMac),
+ pAddStaParams->sessionId, pAddStaParams->assocId);
+ MTRACE(mac_trace_msg_tx(pMac, psessionEntry->peSessionId, msgQ.type));
+
+ retCode = wma_post_ctrl_msg(pMac, &msgQ);
+ if (eSIR_SUCCESS != retCode) {
+ lim_log(pMac, LOGE,
+ FL("Posting WMA_ADD_STA_REQ to HAL failed, reason=%X"),
+ retCode);
+ cdf_mem_free(pAddStaParams);
+ }
+ return retCode;
+}
+
+/**
+ * limTeardownInfraBSS()
+ *
+ ***FUNCTION:
+ * This function is called by various LIM functions to teardown
+ * an established Infrastructure BSS
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ *
+ ***NOTE:
+ *
+ * @param pMac - Pointer to Global MAC structure
+ * @return None
+ */
+
+void lim_teardown_infra_bss(tpAniSirGlobal pMac, tpPESession psessionEntry)
+{
+ tSirMacAddr bcAddr = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
+
+ /**
+ * Send Broadcast Disassociate frame with
+ * 'leaving BSS' reason.
+ */
+ lim_send_disassoc_mgmt_frame(pMac,
+ eSIR_MAC_DISASSOC_LEAVING_BSS_REASON,
+ bcAddr, psessionEntry, false);
+} /*** end lim_teardown_infra_bss() ***/
+
+/**
+ * lim_handle_cnf_wait_timeout()
+ *
+ ***FUNCTION:
+ * This function is called by limProcessMessageQueue to handle
+ * various confirmation failure cases.
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ *
+ ***NOTE:
+ *
+ * @param pMac - Pointer to Global MAC structure
+ * @param pStaDs - Pointer to a sta descriptor
+ * @return None
+ */
+
+void lim_handle_cnf_wait_timeout(tpAniSirGlobal pMac, uint16_t staId)
+{
+ tpDphHashNode pStaDs;
+ tpPESession psessionEntry = NULL;
+
+ psessionEntry = pe_find_session_by_session_id(pMac,
+ pMac->lim.limTimers.gpLimCnfWaitTimer[staId].sessionId);
+ if (psessionEntry == NULL) {
+ lim_log(pMac, LOGP,
+ FL("Session Does not exist for given sessionID"));
+ return;
+ }
+ pStaDs = dph_get_hash_entry(pMac, staId, &psessionEntry->dph.dphHashTable);
+
+ if (pStaDs == NULL) {
+ PELOGW(lim_log
+ (pMac, LOGW,
+ FL("No STA context in SIR_LIM_CNF_WAIT_TIMEOUT."));
+ )
+ return;
+ }
+
+ switch (pStaDs->mlmStaContext.mlmState) {
+ case eLIM_MLM_WT_ASSOC_CNF_STATE:
+ PELOGW(lim_log
+ (pMac, LOGW,
+ FL
+ ("Did not receive Assoc Cnf in eLIM_MLM_WT_ASSOC_CNF_STATE sta Assoc id %d"),
+ pStaDs->assocId);
+ )
+ lim_print_mac_addr(pMac, pStaDs->staAddr, LOGW);
+
+ if (LIM_IS_AP_ROLE(psessionEntry) ||
+ LIM_IS_BT_AMP_AP_ROLE(psessionEntry)) {
+ lim_reject_association(pMac, pStaDs->staAddr,
+ pStaDs->mlmStaContext.subType,
+ true,
+ pStaDs->mlmStaContext.authType,
+ pStaDs->assocId, true,
+ (tSirResultCodes)
+ eSIR_MAC_UNSPEC_FAILURE_STATUS,
+ psessionEntry);
+ }
+ break;
+
+ default:
+ lim_log(pMac, LOGW, FL("Received CNF_WAIT_TIMEOUT in state %d"),
+ pStaDs->mlmStaContext.mlmState);
+ }
+}
+
+/**
+ * lim_delete_dph_hash_entry()- function to delete dph hash entry
+ * @mac_ctx: pointer to global mac structure
+ * @sta_addr: peer station address
+ * @sta_id: id assigned to peer station
+ * @session_entry: pe session entry
+ *
+ * This function is called whenever we need to delete
+ * the dph hash entry
+ *
+ * Return: none
+ */
+
+void
+lim_delete_dph_hash_entry(tpAniSirGlobal mac_ctx, tSirMacAddr sta_addr,
+ uint16_t sta_id, tpPESession session_entry)
+{
+ uint16_t aid;
+ tpDphHashNode sta_ds;
+ tUpdateBeaconParams beacon_params;
+
+ cdf_mem_zero(&beacon_params, sizeof(tUpdateBeaconParams));
+ beacon_params.paramChangeBitmap = 0;
+ lim_deactivate_and_change_per_sta_id_timer(mac_ctx, eLIM_CNF_WAIT_TIMER,
+ sta_id);
+ if (NULL == session_entry) {
+ lim_log(mac_ctx, LOGE, FL("NULL session_entry"));
+ return;
+ }
+
+ beacon_params.bssIdx = session_entry->bssIdx;
+ sta_ds = dph_lookup_hash_entry(mac_ctx, sta_addr, &aid,
+ &session_entry->dph.dphHashTable);
+
+ if (sta_ds == NULL) {
+ lim_log(mac_ctx, LOGE, FL("sta_ds is NULL"));
+ return;
+ }
+
+ lim_log(mac_ctx, LOGW, FL("Deleting DPH Hash entry for STAID: %X"),
+ sta_id);
+ /*
+ * update the station count and perform associated actions
+ * do this before deleting the dph hash entry
+ */
+ lim_util_count_sta_del(mac_ctx, sta_ds, session_entry);
+
+ if (LIM_IS_AP_ROLE(session_entry) || LIM_IS_IBSS_ROLE(session_entry)) {
+ if (LIM_IS_AP_ROLE(session_entry)) {
+ if (session_entry->gLimProtectionControl !=
+ WNI_CFG_FORCE_POLICY_PROTECTION_DISABLE)
+ lim_decide_ap_protection_on_delete(mac_ctx,
+ sta_ds, &beacon_params, session_entry);
+ }
+
+ if (LIM_IS_IBSS_ROLE(session_entry))
+ lim_ibss_decide_protection_on_delete(mac_ctx, sta_ds,
+ &beacon_params, session_entry);
+
+ lim_decide_short_preamble(mac_ctx, sta_ds, &beacon_params,
+ session_entry);
+ lim_decide_short_slot(mac_ctx, sta_ds, &beacon_params,
+ session_entry);
+
+ /* Send message to HAL about beacon parameter change. */
+ lim_log(mac_ctx, LOGW, FL("param bitmap = %d "),
+ beacon_params.paramChangeBitmap);
+ if (beacon_params.paramChangeBitmap &&
+ (false ==
+ mac_ctx->sap.SapDfsInfo.is_dfs_cac_timer_running)) {
+ sch_set_fixed_beacon_fields(mac_ctx, session_entry);
+ lim_send_beacon_params(mac_ctx, &beacon_params,
+ session_entry);
+ }
+#ifdef WLAN_FEATURE_11W
+ tx_timer_delete(&sta_ds->pmfSaQueryTimer);
+#endif
+ }
+
+ if (dph_delete_hash_entry(mac_ctx, sta_addr, sta_id,
+ &session_entry->dph.dphHashTable) != eSIR_SUCCESS)
+ lim_log(mac_ctx, LOGP, FL("error deleting hash entry"));
+}
+
+/**
+ * lim_check_and_announce_join_success()- function to check if the received
+ * Beacon/Probe Response is from the BSS that we're attempting to join.
+ * @mac: pointer to global mac structure
+ * @beacon_probe_rsp: pointer to reveived beacon/probe response frame
+ * @header: pointer to received management frame header
+ * @session_entry: pe session entry
+ *
+ * This function is called upon receiving Beacon/Probe Response
+ * frame in WT_JOIN_BEACON_STATE to check if the received
+ * Beacon/Probe Response is from the BSS that we're attempting
+ * to join.
+ * If the Beacon/Probe Response is indeed from the BSS we're
+ * attempting to join, join success is sent to SME.
+ *
+ * Return: none
+ */
+
+void
+lim_check_and_announce_join_success(tpAniSirGlobal mac_ctx,
+ tSirProbeRespBeacon *beacon_probe_rsp, tpSirMacMgmtHdr header,
+ tpPESession session_entry)
+{
+ tSirMacSSid current_ssid;
+ tLimMlmJoinCnf mlm_join_cnf;
+ uint32_t val = 0;
+ uint32_t *noa_duration_from_beacon = NULL;
+ uint32_t *noa2_duration_from_beacon = NULL;
+ uint32_t noa;
+ uint32_t total_num_noa_desc = 0;
+
+ cdf_mem_copy(current_ssid.ssId,
+ session_entry->ssId.ssId, session_entry->ssId.length);
+
+ current_ssid.length = (uint8_t) session_entry->ssId.length;
+
+ /*
+ * Check for SSID only in probe response. Beacons may not carry
+ * SSID information in hidden SSID case
+ */
+ if (((SIR_MAC_MGMT_FRAME == header->fc.type) &&
+ (SIR_MAC_MGMT_PROBE_RSP == header->fc.subType)) &&
+ current_ssid.length &&
+ (!cdf_mem_compare((uint8_t *) &beacon_probe_rsp->ssId,
+ (uint8_t *) ¤t_ssid,
+ (uint8_t) (1 + current_ssid.length)))) {
+ /*
+ * Received SSID does not match with the one we've.
+ * Ignore received Beacon frame
+ */
+ lim_log(mac_ctx, LOG1,
+ FL("SSID received in Beacon does not match"));
+#ifdef WLAN_DEBUG
+ mac_ctx->lim.gLimBcnSSIDMismatchCnt++;
+#endif
+ return;
+ }
+
+ if (!(LIM_IS_BT_AMP_STA_ROLE(session_entry) ||
+ LIM_IS_STA_ROLE(session_entry)))
+ return;
+
+ lim_log(mac_ctx, LOG1,
+ FL("Received Beacon/PR with matching BSSID:%pM PESessionID %d"),
+ session_entry->bssId, session_entry->peSessionId);
+
+ /* Deactivate Join Failure timer */
+ lim_deactivate_and_change_timer(mac_ctx, eLIM_JOIN_FAIL_TIMER);
+ /* Deactivate Periodic Join timer */
+ lim_deactivate_and_change_timer(mac_ctx,
+ eLIM_PERIODIC_JOIN_PROBE_REQ_TIMER);
+
+ if (CDF_P2P_CLIENT_MODE == session_entry->pePersona &&
+ beacon_probe_rsp->P2PProbeRes.NoticeOfAbsence.present) {
+
+ noa_duration_from_beacon = (uint32_t *)
+ (beacon_probe_rsp->P2PProbeRes.NoticeOfAbsence.NoADesc + 1);
+
+ if (beacon_probe_rsp->P2PProbeRes.NoticeOfAbsence.num_NoADesc)
+ total_num_noa_desc =
+ beacon_probe_rsp->P2PProbeRes.NoticeOfAbsence.
+ num_NoADesc / SIZE_OF_NOA_DESCRIPTOR;
+
+ noa = *noa_duration_from_beacon;
+
+ if (total_num_noa_desc > 1) {
+ noa2_duration_from_beacon = (uint32_t *)
+ (beacon_probe_rsp->P2PProbeRes.NoticeOfAbsence.NoADesc +
+ SIZE_OF_NOA_DESCRIPTOR + 1);
+ noa += *noa2_duration_from_beacon;
+ }
+
+ /*
+ * If MAX Noa exceeds 3 secs we will consider only 3 secs to
+ * avoid arbitary values in noa duration field
+ */
+ noa = noa > MAX_NOA_PERIOD_IN_MICROSECS ?
+ MAX_NOA_PERIOD_IN_MICROSECS : noa;
+ noa = noa / 1000; /* Convert to ms */
+
+ if (wlan_cfg_get_int(mac_ctx,
+ WNI_CFG_AUTHENTICATE_FAILURE_TIMEOUT, &val) ==
+ eSIR_SUCCESS) {
+ session_entry->defaultAuthFailureTimeout = val;
+ cfg_set_int(mac_ctx,
+ WNI_CFG_AUTHENTICATE_FAILURE_TIMEOUT,
+ val + noa);
+ }
+ } else {
+ session_entry->defaultAuthFailureTimeout = 0;
+ }
+
+ /* Update Beacon Interval at CFG database */
+
+ if (beacon_probe_rsp->HTCaps.present)
+ lim_update_sta_run_time_ht_capability(mac_ctx,
+ &beacon_probe_rsp->HTCaps);
+ if (beacon_probe_rsp->HTInfo.present)
+ lim_update_sta_run_time_ht_info(mac_ctx,
+ &beacon_probe_rsp->HTInfo, session_entry);
+ session_entry->limMlmState = eLIM_MLM_JOINED_STATE;
+ MTRACE(mac_trace(mac_ctx, TRACE_CODE_MLM_STATE,
+ session_entry->peSessionId, eLIM_MLM_JOINED_STATE));
+
+ /*
+ * update the capability info based on recently received beacon/probe
+ * response frame
+ */
+ session_entry->limCurrentBssCaps =
+ lim_get_u16((uint8_t *)&beacon_probe_rsp->capabilityInfo);
+
+ /*
+ * Announce join success by sending
+ * Join confirm to SME.
+ */
+ mlm_join_cnf.resultCode = eSIR_SME_SUCCESS;
+ mlm_join_cnf.protStatusCode = eSIR_MAC_SUCCESS_STATUS;
+ /* Update PE sessionId */
+ mlm_join_cnf.sessionId = session_entry->peSessionId;
+ lim_post_sme_message(mac_ctx, LIM_MLM_JOIN_CNF,
+ (uint32_t *) &mlm_join_cnf);
+
+ if (beacon_probe_rsp->vendor2_ie.VHTCaps.present) {
+ session_entry->is_vendor_specific_vhtcaps = true;
+ session_entry->vendor_specific_vht_ie_type =
+ beacon_probe_rsp->vendor2_ie.type;
+ session_entry->vendor_specific_vht_ie_sub_type =
+ beacon_probe_rsp->vendor2_ie.sub_type;
+ lim_log(mac_ctx, LOG1, FL(
+ "VHT caps are present in vendor specific IE"));
+ }
+}
+
+/**
+ * lim_extract_ap_capabilities()
+ *
+ ***FUNCTION:
+ * This function is called to extract all of the AP's capabilities
+ * from the IEs received from it in Beacon/Probe Response frames
+ *
+ ***LOGIC:
+ * This routine mimics the lim_extract_ap_capability() API. The difference here
+ * is that this API returns the entire tSirProbeRespBeacon info as is. It is
+ * left to the caller of this API to use this info as required
+ *
+ ***ASSUMPTIONS:
+ * NA
+ *
+ ***NOTE:
+ *
+ * @param pMac Pointer to Global MAC structure
+ * @param pIE Pointer to starting IE in Beacon/Probe Response
+ * @param ieLen Length of all IEs combined
+ * @param beaconStruct A pointer to tSirProbeRespBeacon that needs to be
+ * populated
+ * @return status A status reporting eSIR_SUCCESS or eSIR_FAILURE
+ */
+tSirRetStatus lim_extract_ap_capabilities(tpAniSirGlobal pMac,
+ uint8_t *pIE,
+ uint16_t ieLen,
+ tpSirProbeRespBeacon beaconStruct)
+{
+ cdf_mem_set((uint8_t *) beaconStruct, sizeof(tSirProbeRespBeacon), 0);
+
+ PELOG3(lim_log(pMac, LOG3,
+ FL
+ ("In lim_extract_ap_capabilities: The IE's being received are:"));
+ sir_dump_buf(pMac, SIR_LIM_MODULE_ID, LOG3, pIE, ieLen);
+ )
+ /* Parse the Beacon IE's, Don't try to parse if we dont have anything in IE */
+ if (ieLen > 0) {
+ if (eSIR_SUCCESS !=
+ sir_parse_beacon_ie(pMac, beaconStruct, pIE,
+ (uint32_t) ieLen)) {
+ lim_log(pMac, LOGE,
+ FL("APCapExtract: Beacon parsing error!"));
+ return eSIR_FAILURE;
+ }
+ }
+
+ return eSIR_SUCCESS;
+}
+
+/**
+ * lim_del_bss()
+ *
+ ***FUNCTION:
+ * This function is called to delete BSS context at hardware
+ * whenever a STA is disassociated
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ * NA
+ *
+ ***NOTE:
+ * NA
+ *
+ * @param pMac - Pointer to Global MAC structure
+ * @param pStaDs - Pointer to the STA datastructure created by
+ * LIM and maintained by DPH
+ * @return retCode - Indicates success or failure return code
+ */
+
+tSirRetStatus
+lim_del_bss(tpAniSirGlobal pMac, tpDphHashNode pStaDs, uint16_t bssIdx,
+ tpPESession psessionEntry)
+{
+ tpDeleteBssParams pDelBssParams = NULL;
+ tSirMsgQ msgQ;
+ tSirRetStatus retCode = eSIR_SUCCESS;
+
+ pDelBssParams = cdf_mem_malloc(sizeof(tDeleteBssParams));
+ if (NULL == pDelBssParams) {
+ lim_log(pMac, LOGP,
+ FL("Unable to allocate memory during ADD_BSS"));
+ return eSIR_MEM_ALLOC_FAILED;
+ }
+ cdf_mem_set((uint8_t *) pDelBssParams, sizeof(tDeleteBssParams), 0);
+
+ pDelBssParams->sessionId = psessionEntry->peSessionId; /* update PE session Id */
+
+ /* DPH was storing the AssocID in staID field, */
+ /* staID is actually assigned by HAL when AddSTA message is sent. */
+ if (pStaDs != NULL) {
+ pDelBssParams->bssIdx = pStaDs->bssId;
+ pStaDs->valid = 0;
+ pStaDs->mlmStaContext.mlmState = eLIM_MLM_WT_DEL_BSS_RSP_STATE;
+ } else
+ pDelBssParams->bssIdx = bssIdx;
+ psessionEntry->limMlmState = eLIM_MLM_WT_DEL_BSS_RSP_STATE;
+ MTRACE(mac_trace
+ (pMac, TRACE_CODE_MLM_STATE, psessionEntry->peSessionId,
+ eLIM_MLM_WT_DEL_BSS_RSP_STATE));
+
+ if ((psessionEntry->peSessionId ==
+ pMac->lim.limTimers.gLimJoinFailureTimer.sessionId)
+ && (true ==
+ tx_timer_running(&pMac->lim.limTimers.gLimJoinFailureTimer))) {
+ lim_deactivate_and_change_timer(pMac, eLIM_JOIN_FAIL_TIMER);
+ }
+
+ pDelBssParams->status = CDF_STATUS_SUCCESS;
+ pDelBssParams->respReqd = 1;
+ cdf_mem_copy(pDelBssParams->bssid, psessionEntry->bssId,
+ sizeof(tSirMacAddr));
+ pDelBssParams->smesessionId = psessionEntry->smeSessionId;
+ PELOGW(lim_log
+ (pMac, LOGW,
+ FL("Sessionid %d : Sending HAL_DELETE_BSS_REQ "
+ "for bss idx: %X BSSID:" MAC_ADDRESS_STR),
+ pDelBssParams->sessionId, pDelBssParams->bssIdx,
+ MAC_ADDR_ARRAY(psessionEntry->bssId));
+ )
+ /* we need to defer the message until we get the response back from HAL. */
+ SET_LIM_PROCESS_DEFD_MESGS(pMac, false);
+
+ msgQ.type = WMA_DELETE_BSS_REQ;
+ msgQ.reserved = 0;
+ msgQ.bodyptr = pDelBssParams;
+ msgQ.bodyval = 0;
+
+ MTRACE(mac_trace_msg_tx(pMac, psessionEntry->peSessionId, msgQ.type));
+
+ retCode = wma_post_ctrl_msg(pMac, &msgQ);
+ if (eSIR_SUCCESS != retCode) {
+ SET_LIM_PROCESS_DEFD_MESGS(pMac, true);
+ lim_log(pMac, LOGE,
+ FL("Posting DELETE_BSS_REQ to HAL failed, reason=%X"),
+ retCode);
+ cdf_mem_free(pDelBssParams);
+ }
+
+ return retCode;
+}
+
+/**
+ * lim_update_vhtcaps_assoc_resp : Update VHT caps in assoc response.
+ * @mac_ctx Pointer to Global MAC structure
+ * @pAddBssParams: parameters required for add bss params.
+ * @vht_caps: VHT capabilities.
+ * @psessionEntry : session entry.
+ *
+ * Return : void
+ */
+void lim_update_vhtcaps_assoc_resp(tpAniSirGlobal mac_ctx,
+ tpAddBssParams pAddBssParams,
+ tDot11fIEVHTCaps *vht_caps, tpPESession psessionEntry)
+{
+ pAddBssParams->staContext.vht_caps =
+ ((vht_caps->maxMPDULen <<
+ SIR_MAC_VHT_CAP_MAX_MPDU_LEN) |
+ (vht_caps->supportedChannelWidthSet <<
+ SIR_MAC_VHT_CAP_SUPP_CH_WIDTH_SET) |
+ (vht_caps->ldpcCodingCap <<
+ SIR_MAC_VHT_CAP_LDPC_CODING_CAP) |
+ (vht_caps->shortGI80MHz <<
+ SIR_MAC_VHT_CAP_SHORTGI_80MHZ) |
+ (vht_caps->shortGI160and80plus80MHz <<
+ SIR_MAC_VHT_CAP_SHORTGI_160_80_80MHZ) |
+ (vht_caps->txSTBC <<
+ SIR_MAC_VHT_CAP_TXSTBC) |
+ (vht_caps->rxSTBC <<
+ SIR_MAC_VHT_CAP_RXSTBC) |
+ (vht_caps->suBeamFormerCap <<
+ SIR_MAC_VHT_CAP_SU_BEAMFORMER_CAP) |
+ (vht_caps->suBeamformeeCap <<
+ SIR_MAC_VHT_CAP_SU_BEAMFORMEE_CAP) |
+ (vht_caps->csnofBeamformerAntSup <<
+ SIR_MAC_VHT_CAP_CSN_BEAMORMER_ANT_SUP) |
+ (vht_caps->numSoundingDim <<
+ SIR_MAC_VHT_CAP_NUM_SOUNDING_DIM) |
+ (vht_caps->muBeamformerCap <<
+ SIR_MAC_VHT_CAP_NUM_BEAM_FORMER_CAP) |
+ (vht_caps->muBeamformeeCap <<
+ SIR_MAC_VHT_CAP_NUM_BEAM_FORMEE_CAP) |
+ (vht_caps->vhtTXOPPS <<
+ SIR_MAC_VHT_CAP_TXOPPS) |
+ (vht_caps->htcVHTCap <<
+ SIR_MAC_VHT_CAP_HTC_CAP) |
+ (vht_caps->maxAMPDULenExp <<
+ SIR_MAC_VHT_CAP_MAX_AMDU_LEN_EXPO) |
+ (vht_caps->vhtLinkAdaptCap <<
+ SIR_MAC_VHT_CAP_LINK_ADAPT_CAP) |
+ (vht_caps->rxAntPattern <<
+ SIR_MAC_VHT_CAP_RX_ANTENNA_PATTERN) |
+ (vht_caps->txAntPattern <<
+ SIR_MAC_VHT_CAP_TX_ANTENNA_PATTERN) |
+ (vht_caps->reserved1 <<
+ SIR_MAC_VHT_CAP_RESERVED2));
+
+ pAddBssParams->staContext.maxAmpduSize =
+ SIR_MAC_GET_VHT_MAX_AMPDU_EXPO(
+ pAddBssParams->staContext.vht_caps);
+
+ lim_log(mac_ctx, LOG1,
+ FL("Updating VHT caps in assoc Response"));
+}
+
+/**
+ * lim_update_vht_oper_assoc_resp : Update VHT Operations in assoc response.
+ * @mac_ctx Pointer to Global MAC structure
+ * @pAddBssParams: parameters required for add bss params.
+ * @vht_oper: VHT Operations to update.
+ * @psessionEntry : session entry.
+ *
+ * Return : void
+ */
+void lim_update_vht_oper_assoc_resp(tpAniSirGlobal mac_ctx,
+ tpAddBssParams pAddBssParams,
+ tDot11fIEVHTOperation *vht_oper, tpPESession psessionEntry)
+{
+ if (vht_oper->chanWidth &&
+ psessionEntry->ch_width) {
+ pAddBssParams->ch_width = vht_oper->chanWidth + 1;
+
+ pAddBssParams->ch_center_freq_seg0 =
+ vht_oper->chanCenterFreqSeg1;
+
+ pAddBssParams->ch_center_freq_seg1 =
+ vht_oper->chanCenterFreqSeg2;
+ }
+ lim_log(mac_ctx, LOG1,
+ FL("Updating VHT Operation in assoc Response"));
+}
+
+
+/**
+ * limSendAddBss()
+ *
+ ***FUNCTION:
+ *
+ ***LOGIC:
+ * 1) LIM receives eWNI_SME_JOIN_REQ
+ * 2) For a valid eWNI_SME_JOIN_REQ, LIM sends
+ * SIR_HAL_ADD_BSS_REQ to HAL
+ *
+ ***ASSUMPTIONS:
+ * JOIN REQ parameters are saved in pMac->lim.gLimMlmJoinReq
+ * ADD BSS parameters can be obtained from two sources:
+ * 1) pMac->lim.gLimMlmJoinReq
+ * 2) beaconStruct, passed as paramter
+ * So, if a reqd parameter is found in bssDescriptions
+ * then it is given preference over beaconStruct
+ *
+ ***NOTE:
+ *
+ * @param pMac Pointer to Global MAC structure
+ * pAssocRsp contains the structured assoc/reassoc Response got from AP
+ * beaconstruct Has the ProbeRsp/Beacon structured details
+ * bssDescription bssDescription passed to PE from the SME
+ * @return None
+ */
+
+tSirRetStatus lim_sta_send_add_bss(tpAniSirGlobal pMac, tpSirAssocRsp pAssocRsp,
+ tpSchBeaconStruct pBeaconStruct,
+ tpSirBssDescription bssDescription,
+ uint8_t updateEntry, tpPESession psessionEntry)
+{
+ tSirMsgQ msgQ;
+ tpAddBssParams pAddBssParams = NULL;
+ uint32_t retCode;
+ tpDphHashNode pStaDs = NULL;
+ uint8_t chanWidthSupp = 0;
+ uint32_t shortGi20MhzSupport;
+ uint32_t shortGi40MhzSupport;
+ uint32_t enableTxBF20MHz;
+ tDot11fIEVHTCaps *vht_caps = NULL;
+ tDot11fIEVHTOperation *vht_oper = NULL;
+ tAddStaParams *sta_context;
+
+ /* Package SIR_HAL_ADD_BSS_REQ message parameters */
+ pAddBssParams = cdf_mem_malloc(sizeof(tAddBssParams));
+ if (NULL == pAddBssParams) {
+ lim_log(pMac, LOGP,
+ FL("Unable to allocate memory during ADD_BSS"));
+ retCode = eSIR_MEM_ALLOC_FAILED;
+ goto returnFailure;
+ } else
+ cdf_mem_set((uint8_t *) pAddBssParams, sizeof(tAddBssParams),
+ 0);
+
+ cdf_mem_copy(pAddBssParams->bssId, bssDescription->bssId,
+ sizeof(tSirMacAddr));
+ /* Fill in tAddBssParams selfMacAddr */
+ cdf_mem_copy(pAddBssParams->selfMacAddr,
+ psessionEntry->selfMacAddr, sizeof(tSirMacAddr));
+
+ lim_log(pMac, LOG1,
+ FL("sessionid: %d updateEntry = %d limsystemrole = %d "),
+ psessionEntry->smeSessionId, updateEntry,
+ GET_LIM_SYSTEM_ROLE(psessionEntry));
+
+ lim_log(pMac, LOG1, FL("BSSID: " MAC_ADDRESS_STR),
+ MAC_ADDR_ARRAY(pAddBssParams->bssId));
+
+ if (psessionEntry->bssType == eSIR_BTAMP_AP_MODE) {
+ pAddBssParams->bssType = eSIR_BTAMP_AP_MODE;
+ } else {
+ pAddBssParams->bssType = eSIR_INFRASTRUCTURE_MODE;
+ }
+
+ pAddBssParams->operMode = BSS_OPERATIONAL_MODE_STA;
+
+ /* Update PE session ID */
+ pAddBssParams->sessionId = psessionEntry->peSessionId;
+
+ pAddBssParams->beaconInterval = bssDescription->beaconInterval;
+
+ pAddBssParams->dtimPeriod = pBeaconStruct->tim.dtimPeriod;
+ pAddBssParams->updateBss = updateEntry;
+
+ pAddBssParams->cfParamSet.cfpCount = pBeaconStruct->cfParamSet.cfpCount;
+ pAddBssParams->cfParamSet.cfpPeriod =
+ pBeaconStruct->cfParamSet.cfpPeriod;
+ pAddBssParams->cfParamSet.cfpMaxDuration =
+ pBeaconStruct->cfParamSet.cfpMaxDuration;
+ pAddBssParams->cfParamSet.cfpDurRemaining =
+ pBeaconStruct->cfParamSet.cfpDurRemaining;
+
+ pAddBssParams->rateSet.numRates = pAssocRsp->supportedRates.numRates;
+ cdf_mem_copy(pAddBssParams->rateSet.rate,
+ pAssocRsp->supportedRates.rate,
+ pAssocRsp->supportedRates.numRates);
+
+ if (IS_DOT11_MODE_11B(psessionEntry->dot11mode) &&
+ bssDescription->nwType != eSIR_11B_NW_TYPE) {
+ pAddBssParams->nwType = eSIR_11B_NW_TYPE;
+ } else {
+ pAddBssParams->nwType = bssDescription->nwType;
+ }
+
+ pAddBssParams->shortSlotTimeSupported =
+ (uint8_t) pAssocRsp->capabilityInfo.shortSlotTime;
+ pAddBssParams->llaCoexist =
+ (uint8_t) psessionEntry->beaconParams.llaCoexist;
+ pAddBssParams->llbCoexist =
+ (uint8_t) psessionEntry->beaconParams.llbCoexist;
+ pAddBssParams->llgCoexist =
+ (uint8_t) psessionEntry->beaconParams.llgCoexist;
+ pAddBssParams->ht20Coexist =
+ (uint8_t) psessionEntry->beaconParams.ht20Coexist;
+
+ lim_log(pMac, LOG2, FL(" BSS Type %d Beacon Interval: %d dtimPeriod: %d "
+ "cfpCount: %d"), pAddBssParams->bssType,
+ pAddBssParams->beaconInterval, pAddBssParams->dtimPeriod,
+ pAddBssParams->cfParamSet.cfpCount);
+
+ lim_log(pMac, LOG2,
+ FL(" cfpPeriod: %d cfpMaxDuration: %d cfpDurRemaining:"
+ " %d numRates: %d "), pAddBssParams->cfParamSet.cfpPeriod,
+ pAddBssParams->cfParamSet.cfpMaxDuration,
+ pAddBssParams->cfParamSet.cfpDurRemaining,
+ pAddBssParams->rateSet.numRates);
+
+ lim_log(pMac, LOG2, FL("nwType:%d shortSlotTimeSupported: %d"
+ "llaCoexist: %d llbCoexist: %d llgCoexist: %d ht20Coexist: %d"),
+ pAddBssParams->nwType, pAddBssParams->shortSlotTimeSupported,
+ pAddBssParams->llaCoexist, pAddBssParams->llbCoexist,
+ pAddBssParams->llgCoexist, pAddBssParams->ht20Coexist);
+
+ pAddBssParams->dot11_mode = psessionEntry->dot11mode;
+ lim_log(pMac, LOG2, FL("dot11_mode:%d"), pAddBssParams->dot11_mode);
+
+ /* Use the advertised capabilities from the received beacon/PR */
+
+ if (IS_DOT11_MODE_HT(psessionEntry->dot11mode)
+ && (pAssocRsp->HTCaps.present)) {
+ pAddBssParams->htCapable = pAssocRsp->HTCaps.present;
+ lim_log(pMac, LOG2, FL("htCapable: %d"),
+ pAddBssParams->htCapable);
+ if (pBeaconStruct->HTInfo.present) {
+ pAddBssParams->htOperMode =
+ (tSirMacHTOperatingMode) pAssocRsp->HTInfo.opMode;
+ pAddBssParams->dualCTSProtection =
+ (uint8_t) pAssocRsp->HTInfo.dualCTSProtection;
+ chanWidthSupp =
+ lim_get_ht_capability(pMac,
+ eHT_SUPPORTED_CHANNEL_WIDTH_SET,
+ psessionEntry);
+ if ((pAssocRsp->HTCaps.supportedChannelWidthSet)
+ && (chanWidthSupp)) {
+ pAddBssParams->ch_width = (uint8_t)
+ pAssocRsp->HTInfo.recommendedTxWidthSet;
+ if (pAssocRsp->HTInfo.secondaryChannelOffset ==
+ PHY_DOUBLE_CHANNEL_LOW_PRIMARY)
+ pAddBssParams->ch_center_freq_seg0 =
+ bssDescription->channelId + 2;
+ else if (pAssocRsp->HTInfo.secondaryChannelOffset ==
+ PHY_DOUBLE_CHANNEL_HIGH_PRIMARY)
+ pAddBssParams->ch_center_freq_seg0 =
+ bssDescription->channelId - 2;
+ } else {
+ pAddBssParams->ch_width = CH_WIDTH_20MHZ;
+ pAddBssParams->ch_center_freq_seg0 = 0;
+ }
+ pAddBssParams->llnNonGFCoexist =
+ (uint8_t) pAssocRsp->HTInfo.nonGFDevicesPresent;
+ pAddBssParams->fLsigTXOPProtectionFullSupport =
+ (uint8_t) pAssocRsp->HTInfo.
+ lsigTXOPProtectionFullSupport;
+ pAddBssParams->fRIFSMode = pAssocRsp->HTInfo.rifsMode;
+
+ lim_log(pMac, LOGE,
+ FL("htOperMode: %d dualCTSProtection: %d txChannelWidth: %d center_freq_0: %d "),
+ pAddBssParams->htOperMode,
+ pAddBssParams->dualCTSProtection,
+ pAddBssParams->ch_width,
+ pAddBssParams->ch_center_freq_seg0);
+
+ lim_log(pMac, LOG2, FL("llnNonGFCoexist: %d "
+ "fLsigTXOPProtectionFullSupport: %d fRIFSMode %d"),
+ pAddBssParams->llnNonGFCoexist,
+ pAddBssParams->fLsigTXOPProtectionFullSupport,
+ pAddBssParams->fRIFSMode);
+ }
+ }
+
+ pAddBssParams->currentOperChannel = bssDescription->channelId;
+ lim_log(pMac, LOGE, FL("currentOperChannel %d"),
+ pAddBssParams->currentOperChannel);
+ if (psessionEntry->vhtCapability && (pAssocRsp->VHTCaps.present)) {
+ pAddBssParams->vhtCapable = pAssocRsp->VHTCaps.present;
+ vht_caps = &pAssocRsp->VHTCaps;
+ vht_oper = &pAssocRsp->VHTOperation;
+ } else if (psessionEntry->vhtCapability &&
+ pAssocRsp->vendor2_ie.VHTCaps.present){
+ pAddBssParams->vhtCapable =
+ pAssocRsp->vendor2_ie.VHTCaps.present;
+ lim_log(pMac, LOG1,
+ FL("VHT Caps and Operation are present in vendor Specfic IE"));
+ vht_caps = &pAssocRsp->vendor2_ie.VHTCaps;
+ vht_oper = &pAssocRsp->vendor2_ie.VHTOperation;
+ } else {
+ pAddBssParams->vhtCapable = 0;
+ }
+ if (pAddBssParams->vhtCapable) {
+ if (vht_oper != NULL)
+ lim_update_vht_oper_assoc_resp(pMac, pAddBssParams,
+ vht_oper, psessionEntry);
+ if (vht_caps != NULL)
+ lim_update_vhtcaps_assoc_resp(pMac, pAddBssParams,
+ vht_caps, psessionEntry);
+ }
+
+ lim_log(pMac, LOGE, FL("vhtCapable %d TxChannelWidth %d center_freq_0 %d center_freq_1 %d"),
+ pAddBssParams->vhtCapable, pAddBssParams->ch_width,
+ pAddBssParams->ch_center_freq_seg0,
+ pAddBssParams->ch_center_freq_seg1);
+
+ /*
+ * Populate the STA-related parameters here
+ * Note that the STA here refers to the AP
+ * staType = PEER
+ */
+ sta_context = &pAddBssParams->staContext;
+ /* Identifying AP as an STA */
+ pAddBssParams->staContext.staType = STA_ENTRY_OTHER;
+
+ cdf_mem_copy(pAddBssParams->staContext.bssId,
+ bssDescription->bssId, sizeof(tSirMacAddr));
+ pAddBssParams->staContext.listenInterval =
+ bssDescription->beaconInterval;
+
+ /* Fill Assoc id from the dph table */
+ pStaDs = dph_lookup_hash_entry(pMac, pAddBssParams->staContext.bssId,
+ &pAddBssParams->staContext.assocId,
+ &psessionEntry->dph.dphHashTable);
+ if (pStaDs == NULL) {
+ lim_log(pMac, LOGE, FL(
+ "Couldn't get assoc id for " "MAC ADDR: "
+ MAC_ADDRESS_STR),
+ MAC_ADDR_ARRAY(
+ pAddBssParams->staContext.staMac));
+ return eSIR_FAILURE;
+ }
+
+ pAddBssParams->staContext.uAPSD =
+ psessionEntry->gUapsdPerAcBitmask;
+
+ pAddBssParams->staContext.maxSPLen = 0;
+ pAddBssParams->staContext.shortPreambleSupported =
+ (uint8_t) pAssocRsp->capabilityInfo.shortPreamble;
+ pAddBssParams->staContext.updateSta = updateEntry;
+
+ lim_log(pMac, LOG2, FL("StaContext: " MAC_ADDRESS_STR
+ " shortPreambleSupported: %d"),
+ MAC_ADDR_ARRAY(pAddBssParams->staContext.staMac),
+ pAddBssParams->staContext.shortPreambleSupported);
+
+ if (IS_DOT11_MODE_HT(psessionEntry->dot11mode)
+ && pBeaconStruct->HTCaps.present) {
+ pAddBssParams->staContext.us32MaxAmpduDuration = 0;
+ pAddBssParams->staContext.htCapable = 1;
+ pAddBssParams->staContext.greenFieldCapable =
+ (uint8_t) pAssocRsp->HTCaps.greenField;
+ pAddBssParams->staContext.lsigTxopProtection =
+ (uint8_t) pAssocRsp->HTCaps.lsigTXOPProtection;
+ lim_log(pMac, LOG2, FL(
+ "StaCtx: htCap %d GFcap %d lsigTxopProtn %d"),
+ pAddBssParams->staContext.htCapable,
+ pAddBssParams->staContext.greenFieldCapable,
+ pAddBssParams->staContext.lsigTxopProtection);
+ if (psessionEntry->vhtCapability &&
+ (IS_BSS_VHT_CAPABLE(pBeaconStruct->VHTCaps) ||
+ IS_BSS_VHT_CAPABLE(
+ pBeaconStruct->vendor2_ie.VHTCaps))) {
+ pAddBssParams->staContext.vhtCapable = 1;
+ pAddBssParams->staContext.vhtSupportedRxNss =
+ pStaDs->vhtSupportedRxNss;
+ if (pAssocRsp->VHTCaps.present)
+ vht_caps = &pAssocRsp->VHTCaps;
+ else if (pAssocRsp->vendor2_ie.VHTCaps.present) {
+ vht_caps = &pAssocRsp->vendor2_ie.VHTCaps;
+ lim_log(pMac, LOG1, FL(
+ "VHT Caps are in vendor Specfic IE"));
+ }
+
+ if ((vht_caps != NULL) && (vht_caps->suBeamFormerCap ||
+ vht_caps->muBeamformerCap) &&
+ psessionEntry->txBFIniFeatureEnabled)
+ sta_context->vhtTxBFCapable = 1;
+
+ if ((vht_caps != NULL) && vht_caps->muBeamformerCap &&
+ psessionEntry->txMuBformee)
+ sta_context->vhtTxMUBformeeCapable = 1;
+ if ((vht_caps != NULL) && vht_caps->suBeamformeeCap &&
+ psessionEntry->enable_su_tx_bformer)
+ sta_context->enable_su_tx_bformer = 1;
+ }
+
+ if ((pAssocRsp->HTCaps.supportedChannelWidthSet) &&
+ (chanWidthSupp)) {
+ pAddBssParams->staContext.ch_width = (uint8_t)
+ pAssocRsp->HTInfo.recommendedTxWidthSet;
+ if (pAssocRsp->VHTCaps.present)
+ vht_oper = &pAssocRsp->VHTOperation;
+ else if (pAssocRsp->vendor2_ie.VHTCaps.present) {
+ vht_oper = &pAssocRsp->vendor2_ie.VHTOperation;
+ lim_log(pMac, LOG1, FL(
+ "VHT Op IE is in vendor Specfic IE"));
+ }
+ if ((vht_oper != NULL) &&
+ pAddBssParams->staContext.vhtCapable &&
+ vht_oper->chanWidth)
+ pAddBssParams->staContext.ch_width =
+ vht_oper->chanWidth + 1;
+
+ lim_log(pMac, LOGE, FL(
+ "StaCtx: vhtCap %d ChBW %d TxBF %d"),
+ pAddBssParams->staContext.vhtCapable,
+ pAddBssParams->staContext.ch_width,
+ sta_context->vhtTxBFCapable);
+ lim_log(pMac, LOGE, FL("StaContext su_tx_bfer %d"),
+ sta_context->enable_su_tx_bformer);
+ } else {
+ sta_context->ch_width = CH_WIDTH_20MHZ;
+ if ((IS_SIR_STATUS_SUCCESS(
+ wlan_cfg_get_int(pMac,
+ WNI_CFG_VHT_ENABLE_TXBF_20MHZ,
+ &enableTxBF20MHz))) &&
+ (false == enableTxBF20MHz))
+ sta_context->vhtTxBFCapable = 0;
+ }
+ pAddBssParams->staContext.mimoPS =
+ (tSirMacHTMIMOPowerSaveState)
+ pAssocRsp->HTCaps.mimoPowerSave;
+ pAddBssParams->staContext.maxAmsduSize =
+ (uint8_t) pAssocRsp->HTCaps.maximalAMSDUsize;
+ pAddBssParams->staContext.maxAmpduDensity =
+ pAssocRsp->HTCaps.mpduDensity;
+ pAddBssParams->staContext.fDsssCckMode40Mhz =
+ (uint8_t) pAssocRsp->HTCaps.dsssCckMode40MHz;
+ /*
+ * We will check gShortGI20Mhz and gShortGI40Mhz from
+ * ini file. if they are set then we will use what ever
+ * Assoc response coming from AP supports. If these
+ * values are set as 0 in ini file then we will
+ * hardcode this values to 0.
+ */
+ if (IS_SIR_STATUS_SUCCESS(wlan_cfg_get_int
+ (pMac, WNI_CFG_SHORT_GI_20MHZ,
+ &shortGi20MhzSupport))) {
+ if (true == shortGi20MhzSupport) {
+ pAddBssParams->staContext.
+ fShortGI20Mhz =
+ (uint8_t) pAssocRsp->HTCaps.
+ shortGI20MHz;
+ } else {
+ pAddBssParams->staContext.
+ fShortGI20Mhz = false;
+ }
+ } else {
+ lim_log(pMac, LOGE, FL(
+ "failed to get shortGI 20Mhz, set default"));
+ pAddBssParams->staContext.fShortGI20Mhz =
+ WNI_CFG_SHORT_GI_20MHZ_STADEF;
+ }
+
+ if (IS_SIR_STATUS_SUCCESS(wlan_cfg_get_int
+ (pMac, WNI_CFG_SHORT_GI_40MHZ,
+ &shortGi40MhzSupport))) {
+ if (true == shortGi40MhzSupport) {
+ pAddBssParams->staContext.
+ fShortGI40Mhz =
+ (uint8_t) pAssocRsp->HTCaps.
+ shortGI40MHz;
+ } else {
+ pAddBssParams->staContext.
+ fShortGI40Mhz = false;
+ }
+ } else {
+ lim_log(pMac, LOGE, FL(
+ "failed to get shortGI 40Mhz, set default"));
+ pAddBssParams->staContext.fShortGI40Mhz =
+ WNI_CFG_SHORT_GI_40MHZ_STADEF;
+ }
+
+ if (!pAddBssParams->staContext.vhtCapable)
+ /* Use max ampd factor advertised in
+ * HTCAP for non-vht connection */
+ {
+ pAddBssParams->staContext.maxAmpduSize =
+ pAssocRsp->HTCaps.maxRxAMPDUFactor;
+ } else if (pAddBssParams->staContext.maxAmpduSize <
+ pAssocRsp->HTCaps.maxRxAMPDUFactor) {
+ pAddBssParams->staContext.maxAmpduSize =
+ pAssocRsp->HTCaps.maxRxAMPDUFactor;
+ }
+ if (pAddBssParams->staContext.vhtTxBFCapable
+ && pMac->lim.disableLDPCWithTxbfAP) {
+ pAddBssParams->staContext.htLdpcCapable = 0;
+ pAddBssParams->staContext.vhtLdpcCapable = 0;
+ } else {
+ pAddBssParams->staContext.htLdpcCapable =
+ (uint8_t) pAssocRsp->HTCaps.advCodingCap;
+ if (pAssocRsp->VHTCaps.present)
+ vht_caps = &pAssocRsp->VHTCaps;
+ else if (pAssocRsp->vendor2_ie.VHTCaps.present) {
+ vht_caps = &pAssocRsp->vendor2_ie.VHTCaps;
+ lim_log(pMac, LOG1, FL(
+ "VHT Caps is in vendor Specfic IE"));
+ }
+ if (vht_caps != NULL)
+ pAddBssParams->staContext.vhtLdpcCapable =
+ (uint8_t) vht_caps->ldpcCodingCap;
+ }
+
+ if (pBeaconStruct->HTInfo.present)
+ pAddBssParams->staContext.rifsMode =
+ pAssocRsp->HTInfo.rifsMode;
+
+ lim_log(pMac, LOGE, FL(
+ "StaCtx: ChBW %d mimoPS %d maxAmsduSize %d"),
+ pAddBssParams->staContext.ch_width,
+ pAddBssParams->staContext.mimoPS,
+ pAddBssParams->staContext.maxAmsduSize);
+
+ lim_log(pMac, LOG2, FL(
+ "maxAmpduDens %d CckMode40Mhz %d SGI20Mhz %d"),
+ pAddBssParams->staContext.maxAmpduDensity,
+ pAddBssParams->staContext.fDsssCckMode40Mhz,
+ pAddBssParams->staContext.fShortGI20Mhz);
+
+ lim_log(pMac, LOG2, FL(
+ "SGI40M %d maxAmpdu %d htLdpc %d vhtLdpc %d"),
+ pAddBssParams->staContext.fShortGI40Mhz,
+ pAddBssParams->staContext.maxAmpduSize,
+ pAddBssParams->staContext.htLdpcCapable,
+ pAddBssParams->staContext.vhtLdpcCapable);
+ }
+ pAddBssParams->staContext.smesessionId =
+ psessionEntry->smeSessionId;
+ pAddBssParams->staContext.wpa_rsn = pBeaconStruct->rsnPresent;
+ pAddBssParams->staContext.wpa_rsn |=
+ (pBeaconStruct->wpaPresent << 1);
+ /* For OSEN Connection AP does not advertise RSN or WPA IE
+ * so from the IEs we get from supplicant we get this info
+ * so for FW to transmit EAPOL message 4 we shall set
+ * wpa_rsn
+ */
+ if ((!pAddBssParams->staContext.wpa_rsn)
+ && (psessionEntry->isOSENConnection))
+ pAddBssParams->staContext.wpa_rsn = 1;
+ cdf_mem_copy(&pAddBssParams->staContext.capab_info,
+ &pAssocRsp->capabilityInfo,
+ sizeof(pAddBssParams->staContext.capab_info));
+ cdf_mem_copy(&pAddBssParams->staContext.ht_caps,
+ (uint8_t *) &pAssocRsp->HTCaps + sizeof(uint8_t),
+ sizeof(pAddBssParams->staContext.ht_caps));
+
+ /* If WMM IE or 802.11E IE is present then enable WMM */
+ if ((psessionEntry->limWmeEnabled && pAssocRsp->wmeEdcaPresent) ||
+ (psessionEntry->limQosEnabled && pAssocRsp->edcaPresent))
+ pAddBssParams->staContext.wmmEnabled = 1;
+ else
+ pAddBssParams->staContext.wmmEnabled = 0;
+
+ /* Update the rates */
+ pStaDs = dph_get_hash_entry(pMac, DPH_STA_HASH_INDEX_PEER,
+ &psessionEntry->dph.dphHashTable);
+ if (pStaDs != NULL) {
+ lim_fill_supported_rates_info(pMac, pStaDs,
+ &pStaDs->supportedRates,
+ psessionEntry);
+ cdf_mem_copy((uint8_t *) &pAddBssParams->staContext.
+ supportedRates,
+ (uint8_t *) &pStaDs->supportedRates,
+ sizeof(tSirSupportedRates));
+ } else
+ lim_log(pMac, LOGE, FL(
+ "could not Update the supported rates"));
+ pAddBssParams->staContext.encryptType = psessionEntry->encryptType;
+
+#if defined WLAN_FEATURE_VOWIFI
+ pAddBssParams->maxTxPower = psessionEntry->maxTxPower;
+ lim_log(pMac, LOG2, FL("maxTxPower: %d"), pAddBssParams->maxTxPower);
+#endif
+ /* FIXME_GEN4 - Any other value that can be used for initialization? */
+ pAddBssParams->status = CDF_STATUS_SUCCESS;
+ pAddBssParams->respReqd = true;
+ /* update persona */
+ pAddBssParams->halPersona = (uint8_t) psessionEntry->pePersona;
+
+ if (CDF_P2P_CLIENT_MODE == psessionEntry->pePersona)
+ pAddBssParams->staContext.p2pCapableSta = 1;
+
+ pAddBssParams->bSpectrumMgtEnabled = psessionEntry->spectrumMgtEnabled;
+
+#if defined WLAN_FEATURE_VOWIFI_11R
+ pAddBssParams->extSetStaKeyParamValid = 0;
+ lim_log(pMac, LOG2, FL("extSetStaKeyParamValid: %d"),
+ pAddBssParams->extSetStaKeyParamValid);
+#endif
+
+#ifdef WLAN_FEATURE_11W
+ if (psessionEntry->limRmfEnabled) {
+ pAddBssParams->rmfEnabled = 1;
+ pAddBssParams->staContext.rmfEnabled = 1;
+ }
+#endif
+
+ /* Set a new state for MLME */
+ if (eLIM_MLM_WT_ASSOC_RSP_STATE == psessionEntry->limMlmState)
+ psessionEntry->limMlmState =
+ eLIM_MLM_WT_ADD_BSS_RSP_ASSOC_STATE;
+ else
+ psessionEntry->limMlmState =
+ eLIM_MLM_WT_ADD_BSS_RSP_REASSOC_STATE;
+ MTRACE(mac_trace
+ (pMac, TRACE_CODE_MLM_STATE, psessionEntry->peSessionId,
+ psessionEntry->limMlmState));
+
+ lim_log(pMac, LOG2, FL("staContext wmmEnabled: %d encryptType: %d "
+ "p2pCapableSta: %d"),
+ pAddBssParams->staContext.wmmEnabled,
+ pAddBssParams->staContext.encryptType,
+ pAddBssParams->staContext.p2pCapableSta);
+
+ lim_log(pMac, LOG2, FL("bSpectrumMgtEnabled: %d halPersona: %d setting "
+ "LimMlm state to %d"),
+ pAddBssParams->bSpectrumMgtEnabled, pAddBssParams->halPersona,
+ psessionEntry->limMlmState);
+ if (psessionEntry->isNonRoamReassoc)
+ pAddBssParams->nonRoamReassoc = 1;
+ pAddBssParams->nss = psessionEntry->nss;
+ lim_log(pMac, LOG2, FL("nss value: %d"), pAddBssParams->nss);
+
+ /* we need to defer the message until we get the response back from HAL. */
+ SET_LIM_PROCESS_DEFD_MESGS(pMac, false);
+
+ msgQ.type = WMA_ADD_BSS_REQ;
+ /** @ToDo : Update the Global counter to keeptrack of the PE <--> HAL messages*/
+ msgQ.reserved = 0;
+ msgQ.bodyptr = pAddBssParams;
+ msgQ.bodyval = 0;
+
+ lim_log(pMac, LOG1, FL("SessionId:%d Sending WMA_ADD_BSS_REQ"),
+ psessionEntry->peSessionId);
+ MTRACE(mac_trace_msg_tx(pMac, psessionEntry->peSessionId, msgQ.type));
+
+ retCode = wma_post_ctrl_msg(pMac, &msgQ);
+ if (eSIR_SUCCESS != retCode) {
+ SET_LIM_PROCESS_DEFD_MESGS(pMac, true);
+ cdf_mem_free(pAddBssParams);
+ lim_log(pMac, LOGE,
+ FL("Posting ADD_BSS_REQ to HAL failed, reason=%X"),
+ retCode);
+ goto returnFailure;
+
+ } else
+ return retCode;
+
+returnFailure:
+ /* Clean-up will be done by the caller... */
+ return retCode;
+}
+
+tSirRetStatus lim_sta_send_add_bss_pre_assoc(tpAniSirGlobal pMac, uint8_t updateEntry,
+ tpPESession psessionEntry)
+{
+ tSirMsgQ msgQ;
+ tpAddBssParams pAddBssParams = NULL;
+ uint32_t retCode;
+ tSchBeaconStruct *pBeaconStruct;
+ uint8_t chanWidthSupp = 0;
+ uint32_t shortGi20MhzSupport;
+ uint32_t shortGi40MhzSupport;
+ tDot11fIEVHTOperation *vht_oper = NULL;
+ tDot11fIEVHTCaps *vht_caps = NULL;
+
+ tpSirBssDescription bssDescription =
+ &psessionEntry->pLimJoinReq->bssDescription;
+
+ pBeaconStruct = cdf_mem_malloc(sizeof(tSchBeaconStruct));
+ if (NULL == pBeaconStruct) {
+ lim_log(pMac, LOGE,
+ FL("Unable to allocate memory during ADD_BSS"));
+ return eSIR_MEM_ALLOC_FAILED;
+ }
+
+ /* Package SIR_HAL_ADD_BSS_REQ message parameters */
+ pAddBssParams = cdf_mem_malloc(sizeof(tAddBssParams));
+ if (NULL == pAddBssParams) {
+ lim_log(pMac, LOGP,
+ FL("Unable to allocate memory during ADD_BSS"));
+ retCode = eSIR_MEM_ALLOC_FAILED;
+ goto returnFailure;
+ }
+
+ cdf_mem_set((uint8_t *) pAddBssParams, sizeof(tAddBssParams), 0);
+
+ lim_extract_ap_capabilities(pMac, (uint8_t *) bssDescription->ieFields,
+ lim_get_ielen_from_bss_description(bssDescription),
+ pBeaconStruct);
+
+ if (pMac->lim.gLimProtectionControl !=
+ WNI_CFG_FORCE_POLICY_PROTECTION_DISABLE)
+ lim_decide_sta_protection_on_assoc(pMac, pBeaconStruct,
+ psessionEntry);
+ cdf_mem_copy(pAddBssParams->bssId, bssDescription->bssId,
+ sizeof(tSirMacAddr));
+
+ /* Fill in tAddBssParams selfMacAddr */
+ cdf_mem_copy(pAddBssParams->selfMacAddr,
+ psessionEntry->selfMacAddr, sizeof(tSirMacAddr));
+ lim_log(pMac, LOG1,
+ FL("sessionid: %d updateEntry = %d limsystemrole = %d "),
+ psessionEntry->smeSessionId, updateEntry,
+ GET_LIM_SYSTEM_ROLE(psessionEntry));
+
+ lim_log(pMac, LOG1, FL("BSSID: " MAC_ADDRESS_STR),
+ MAC_ADDR_ARRAY(pAddBssParams->bssId));
+ /* Incorrect BSS Type which caused UMA Descriptor to be overwritten on
+ * top of an already established Infra link. This lead to issues in
+ * concurrent data transfer.
+ */
+
+ pAddBssParams->bssType = psessionEntry->bssType; /* eSIR_INFRASTRUCTURE_MODE; */
+ pAddBssParams->operMode = BSS_OPERATIONAL_MODE_STA;
+
+ pAddBssParams->beaconInterval = bssDescription->beaconInterval;
+
+ pAddBssParams->dtimPeriod = pBeaconStruct->tim.dtimPeriod;
+ pAddBssParams->updateBss = updateEntry;
+
+ pAddBssParams->cfParamSet.cfpCount = pBeaconStruct->cfParamSet.cfpCount;
+ pAddBssParams->cfParamSet.cfpPeriod =
+ pBeaconStruct->cfParamSet.cfpPeriod;
+ pAddBssParams->cfParamSet.cfpMaxDuration =
+ pBeaconStruct->cfParamSet.cfpMaxDuration;
+ pAddBssParams->cfParamSet.cfpDurRemaining =
+ pBeaconStruct->cfParamSet.cfpDurRemaining;
+
+ pAddBssParams->rateSet.numRates =
+ pBeaconStruct->supportedRates.numRates;
+ cdf_mem_copy(pAddBssParams->rateSet.rate,
+ pBeaconStruct->supportedRates.rate,
+ pBeaconStruct->supportedRates.numRates);
+
+ pAddBssParams->nwType = bssDescription->nwType;
+
+ pAddBssParams->shortSlotTimeSupported =
+ (uint8_t) pBeaconStruct->capabilityInfo.shortSlotTime;
+ pAddBssParams->llaCoexist =
+ (uint8_t) psessionEntry->beaconParams.llaCoexist;
+ pAddBssParams->llbCoexist =
+ (uint8_t) psessionEntry->beaconParams.llbCoexist;
+ pAddBssParams->llgCoexist =
+ (uint8_t) psessionEntry->beaconParams.llgCoexist;
+ pAddBssParams->ht20Coexist =
+ (uint8_t) psessionEntry->beaconParams.ht20Coexist;
+
+ lim_log(pMac, LOG2, FL(" BSS Type %d Beacon Interval: %d dtimPeriod: %d "
+ "cfpCount: %d"), pAddBssParams->bssType,
+ pAddBssParams->beaconInterval, pAddBssParams->dtimPeriod,
+ pAddBssParams->cfParamSet.cfpCount);
+
+ lim_log(pMac, LOG2,
+ FL(" cfpPeriod: %d cfpMaxDuration: %d cfpDurRemaining:"
+ " %d numRates: %d "), pAddBssParams->cfParamSet.cfpPeriod,
+ pAddBssParams->cfParamSet.cfpMaxDuration,
+ pAddBssParams->cfParamSet.cfpDurRemaining,
+ pAddBssParams->rateSet.numRates);
+
+ lim_log(pMac, LOG2, FL("nwType:%d shortSlotTimeSupported: %d"
+ "llaCoexist: %d llbCoexist: %d llgCoexist: %d ht20Coexist: %d"),
+ pAddBssParams->nwType, pAddBssParams->shortSlotTimeSupported,
+ pAddBssParams->llaCoexist, pAddBssParams->llbCoexist,
+ pAddBssParams->llgCoexist, pAddBssParams->ht20Coexist);
+ /* Use the advertised capabilities from the received beacon/PR */
+ if (IS_DOT11_MODE_HT(psessionEntry->dot11mode)
+ && (pBeaconStruct->HTCaps.present)) {
+ pAddBssParams->htCapable = pBeaconStruct->HTCaps.present;
+ lim_log(pMac, LOG2, FL("htCapable: %d"),
+ pAddBssParams->htCapable);
+ if (pBeaconStruct->HTInfo.present) {
+ pAddBssParams->htOperMode =
+ (tSirMacHTOperatingMode) pBeaconStruct->HTInfo.
+ opMode;
+ pAddBssParams->dualCTSProtection =
+ (uint8_t) pBeaconStruct->HTInfo.dualCTSProtection;
+
+ chanWidthSupp =
+ lim_get_ht_capability(pMac,
+ eHT_SUPPORTED_CHANNEL_WIDTH_SET,
+ psessionEntry);
+ if ((pBeaconStruct->HTCaps.supportedChannelWidthSet)
+ && (chanWidthSupp)) {
+ pAddBssParams->ch_width =
+ (uint8_t) pBeaconStruct->HTInfo.
+ recommendedTxWidthSet;
+ if (pBeaconStruct->HTInfo.secondaryChannelOffset ==
+ PHY_DOUBLE_CHANNEL_LOW_PRIMARY)
+ pAddBssParams->ch_center_freq_seg0 =
+ bssDescription->channelId + 2;
+
+ if (pBeaconStruct->HTInfo.secondaryChannelOffset ==
+ PHY_DOUBLE_CHANNEL_HIGH_PRIMARY)
+ pAddBssParams->ch_center_freq_seg0 =
+ bssDescription->channelId - 2;
+ } else {
+ pAddBssParams->ch_width = CH_WIDTH_20MHZ;
+ pAddBssParams->ch_center_freq_seg0 = 0;
+ }
+ pAddBssParams->llnNonGFCoexist =
+ (uint8_t) pBeaconStruct->HTInfo.nonGFDevicesPresent;
+ pAddBssParams->fLsigTXOPProtectionFullSupport =
+ (uint8_t) pBeaconStruct->HTInfo.
+ lsigTXOPProtectionFullSupport;
+ pAddBssParams->fRIFSMode =
+ pBeaconStruct->HTInfo.rifsMode;
+
+ lim_log(pMac, LOG2,
+ FL("htOperMode: %d dualCTSProtection: %d txChannelWidthSet: %d center_freq_seg0: %d "),
+ pAddBssParams->htOperMode,
+ pAddBssParams->dualCTSProtection,
+ pAddBssParams->txChannelWidthSet,
+ pAddBssParams->ch_center_freq_seg0);
+
+ lim_log(pMac, LOG2, FL("llnNonGFCoexist: %d "
+ "fLsigTXOPProtectionFullSupport: %d fRIFSMode %d"),
+ pAddBssParams->llnNonGFCoexist,
+ pAddBssParams->fLsigTXOPProtectionFullSupport,
+ pAddBssParams->fRIFSMode);
+ }
+ }
+
+ pAddBssParams->currentOperChannel = bssDescription->channelId;
+ lim_log(pMac, LOG2, FL("currentOperChannel %d"),
+ pAddBssParams->currentOperChannel);
+#ifdef WLAN_FEATURE_11AC
+ if (psessionEntry->vhtCapability &&
+ (IS_BSS_VHT_CAPABLE(pBeaconStruct->VHTCaps) ||
+ IS_BSS_VHT_CAPABLE(pBeaconStruct->vendor2_ie.VHTCaps))) {
+
+ pAddBssParams->vhtCapable = 1;
+ if (pBeaconStruct->VHTOperation.present)
+ vht_oper = &pBeaconStruct->VHTOperation;
+ else if (pBeaconStruct->vendor2_ie.VHTOperation.present) {
+ vht_oper = &pBeaconStruct->vendor2_ie.VHTOperation;
+ lim_log(pMac, LOG1,
+ FL("VHT Operation is present in vendor Specfic IE"));
+ }
+
+
+ if ((vht_oper != NULL) &&
+ vht_oper->chanWidth &&
+ chanWidthSupp) {
+ pAddBssParams->ch_width =
+ vht_oper->chanWidth + 1;
+ pAddBssParams->ch_center_freq_seg0 =
+ vht_oper->chanCenterFreqSeg1;
+ pAddBssParams->ch_center_freq_seg1 =
+ vht_oper->chanCenterFreqSeg2;
+ }
+ pAddBssParams->staContext.maxAmpduSize =
+ SIR_MAC_GET_VHT_MAX_AMPDU_EXPO(
+ pAddBssParams->staContext.vht_caps);
+ } else {
+ pAddBssParams->vhtCapable = 0;
+ }
+ lim_log(pMac, LOGE, FL("vhtCapable %d vhtTxChannelWidthSet %d center_freq_seg0 - %d, center_freq_seg1 - %d"),
+ pAddBssParams->vhtCapable, pAddBssParams->ch_width,
+ pAddBssParams->ch_center_freq_seg0,
+ pAddBssParams->ch_center_freq_seg1);
+#endif
+
+ /*
+ * Populate the STA-related parameters here
+ * Note that the STA here refers to the AP
+ */
+ /* Identifying AP as an STA */
+ pAddBssParams->staContext.staType = STA_ENTRY_OTHER;
+
+ cdf_mem_copy(pAddBssParams->staContext.bssId,
+ bssDescription->bssId, sizeof(tSirMacAddr));
+ pAddBssParams->staContext.listenInterval =
+ bssDescription->beaconInterval;
+
+ pAddBssParams->staContext.assocId = 0;
+ pAddBssParams->staContext.uAPSD = 0;
+ pAddBssParams->staContext.maxSPLen = 0;
+ pAddBssParams->staContext.shortPreambleSupported =
+ (uint8_t) pBeaconStruct->capabilityInfo.shortPreamble;
+ pAddBssParams->staContext.updateSta = updateEntry;
+
+ lim_log(pMac, LOG2, FL(
+ "StaCtx: " MAC_ADDRESS_STR " shortPreamble: %d"),
+ MAC_ADDR_ARRAY(pAddBssParams->staContext.staMac),
+ pAddBssParams->staContext.shortPreambleSupported);
+
+ pAddBssParams->dot11_mode = psessionEntry->dot11mode;
+ lim_log(pMac, LOG2, FL("dot11_mode:%d"),
+ pAddBssParams->dot11_mode);
+
+ if (IS_DOT11_MODE_HT(psessionEntry->dot11mode)
+ && (pBeaconStruct->HTCaps.present)) {
+ pAddBssParams->staContext.us32MaxAmpduDuration = 0;
+ pAddBssParams->staContext.htCapable = 1;
+ pAddBssParams->staContext.greenFieldCapable =
+ (uint8_t) pBeaconStruct->HTCaps.greenField;
+ pAddBssParams->staContext.lsigTxopProtection =
+ (uint8_t) pBeaconStruct->HTCaps.lsigTXOPProtection;
+ lim_log(pMac, LOG2, FL(
+ "StaCtx: htCap %d GFCap %d lsigTxopProtn %d"),
+ pAddBssParams->staContext.htCapable,
+ pAddBssParams->staContext.greenFieldCapable,
+ pAddBssParams->staContext.lsigTxopProtection);
+ if (psessionEntry->vhtCapability &&
+ (IS_BSS_VHT_CAPABLE(pBeaconStruct->VHTCaps) ||
+ IS_BSS_VHT_CAPABLE(
+ pBeaconStruct->vendor2_ie.VHTCaps))) {
+ pAddBssParams->staContext.vhtCapable = 1;
+ if (pBeaconStruct->VHTCaps.present)
+ vht_caps = &pBeaconStruct->VHTCaps;
+ else if (pBeaconStruct->vendor2_ie.VHTCaps.present)
+ vht_caps = &pBeaconStruct->vendor2_ie.VHTCaps;
+
+ if ((vht_caps != NULL) && (vht_caps->suBeamFormerCap ||
+ vht_caps->muBeamformerCap) &&
+ psessionEntry->txBFIniFeatureEnabled)
+ pAddBssParams->staContext.vhtTxBFCapable = 1;
+
+ if ((vht_caps != NULL) && vht_caps->muBeamformerCap &&
+ psessionEntry->txMuBformee)
+ pAddBssParams->staContext.vhtTxMUBformeeCapable
+ = 1;
+ if ((vht_caps != NULL) && vht_caps->suBeamformeeCap &&
+ psessionEntry->enable_su_tx_bformer)
+ pAddBssParams->staContext.enable_su_tx_bformer
+ = 1;
+ lim_log(pMac, LOG2, FL("StaContext: su_tx_bfer %d"),
+ pAddBssParams->staContext.enable_su_tx_bformer);
+ }
+ if ((pBeaconStruct->HTCaps.supportedChannelWidthSet) &&
+ (chanWidthSupp)) {
+ pAddBssParams->staContext.ch_width =
+ (uint8_t) pBeaconStruct->HTInfo.
+ recommendedTxWidthSet;
+ if ((vht_oper != NULL) &&
+ pAddBssParams->staContext.vhtCapable &&
+ vht_oper->chanWidth)
+ pAddBssParams->staContext.ch_width =
+ vht_oper->chanWidth + 1;
+ lim_log(pMac, LOG2, FL(
+ "StaCtx: vhtCap %d ch_bw %d TxBF %d"),
+ pAddBssParams->staContext.vhtCapable,
+ pAddBssParams->staContext.ch_width,
+ pAddBssParams->staContext.
+ vhtTxBFCapable);
+ } else {
+ pAddBssParams->staContext.ch_width =
+ CH_WIDTH_20MHZ;
+ }
+ pAddBssParams->staContext.mimoPS =
+ (tSirMacHTMIMOPowerSaveState) pBeaconStruct->HTCaps.
+ mimoPowerSave;
+ pAddBssParams->staContext.maxAmsduSize =
+ (uint8_t) pBeaconStruct->HTCaps.maximalAMSDUsize;
+ pAddBssParams->staContext.maxAmpduDensity =
+ pBeaconStruct->HTCaps.mpduDensity;
+ pAddBssParams->staContext.fDsssCckMode40Mhz =
+ (uint8_t) pBeaconStruct->HTCaps.dsssCckMode40MHz;
+ /*
+ * We will check gShortGI20Mhz and gShortGI40Mhz from ini file.
+ * if they are set then we will use what ever Beacon coming
+ * from AP supports. If these values are set as 0 in ini file
+ * then we will hardcode this values to 0.
+ */
+ if (IS_SIR_STATUS_SUCCESS(wlan_cfg_get_int
+ (pMac, WNI_CFG_SHORT_GI_20MHZ,
+ &shortGi20MhzSupport))) {
+ if (true == shortGi20MhzSupport)
+ pAddBssParams->staContext.fShortGI20Mhz =
+ (uint8_t)pBeaconStruct->HTCaps.shortGI20MHz;
+ else
+ pAddBssParams->staContext.fShortGI20Mhz =
+ false;
+ } else {
+ lim_log(pMac, LOGE, FL(
+ "get shortGI 20Mhz failed, set default"));
+ pAddBssParams->staContext.fShortGI20Mhz =
+ WNI_CFG_SHORT_GI_20MHZ_STADEF;
+ }
+
+ if (IS_SIR_STATUS_SUCCESS(wlan_cfg_get_int
+ (pMac, WNI_CFG_SHORT_GI_40MHZ,
+ &shortGi40MhzSupport))) {
+ if (true == shortGi40MhzSupport) {
+ pAddBssParams->staContext.
+ fShortGI40Mhz =
+ (uint8_t) pBeaconStruct->HTCaps.
+ shortGI40MHz;
+ } else {
+ pAddBssParams->staContext.
+ fShortGI40Mhz = false;
+ }
+ } else {
+ lim_log(pMac, LOGE, FL(
+ "get shortGI 40Mhz failed, set default"));
+ pAddBssParams->staContext.fShortGI40Mhz =
+ WNI_CFG_SHORT_GI_40MHZ_STADEF;
+ }
+
+ pAddBssParams->staContext.maxAmpduSize =
+ pBeaconStruct->HTCaps.maxRxAMPDUFactor;
+ if (pAddBssParams->staContext.vhtTxBFCapable
+ && pMac->lim.disableLDPCWithTxbfAP) {
+ pAddBssParams->staContext.htLdpcCapable = 0;
+ pAddBssParams->staContext.vhtLdpcCapable = 0;
+ } else {
+ pAddBssParams->staContext.htLdpcCapable =
+ (uint8_t) pBeaconStruct->HTCaps.
+ advCodingCap;
+ if (pBeaconStruct->VHTCaps.present)
+ vht_caps = &pBeaconStruct->VHTCaps;
+ else if (pBeaconStruct->vendor2_ie.VHTCaps.present) {
+ vht_caps =
+ &pBeaconStruct->vendor2_ie.VHTCaps;
+ lim_log(pMac, LOG1, FL(
+ "VHT Caps are in vendor Specfic IE"));
+ }
+ if (vht_caps != NULL)
+ pAddBssParams->staContext.vhtLdpcCapable =
+ (uint8_t) vht_caps->ldpcCodingCap;
+ }
+
+ if (pBeaconStruct->HTInfo.present)
+ pAddBssParams->staContext.rifsMode =
+ pBeaconStruct->HTInfo.rifsMode;
+ lim_log(pMac, LOG2,
+ FL("StaContext ChannelWidth: %d mimoPS: %d maxAmsduSize: %d"),
+ pAddBssParams->staContext.ch_width,
+ pAddBssParams->staContext.mimoPS,
+ pAddBssParams->staContext.maxAmsduSize);
+
+ lim_log(pMac, LOG2, FL(
+ "maxAmpduDensity %d Cck40Mhz %d SGI20Mhz %d"),
+ pAddBssParams->staContext.maxAmpduDensity,
+ pAddBssParams->staContext.fDsssCckMode40Mhz,
+ pAddBssParams->staContext.fShortGI20Mhz);
+
+ lim_log(pMac, LOG2, FL(
+ "SGI40M %d maxAmpdu %d htLdpc %d vhtLdpc %d"),
+ pAddBssParams->staContext.fShortGI40Mhz,
+ pAddBssParams->staContext.maxAmpduSize,
+ pAddBssParams->staContext.htLdpcCapable,
+ pAddBssParams->staContext.vhtLdpcCapable);
+ }
+ /*
+ * If WMM IE or 802.11E IE is not present
+ * and AP is HT AP then enable WMM
+ */
+ if ((psessionEntry->limWmeEnabled && (pBeaconStruct->wmeEdcaPresent ||
+ pAddBssParams->staContext.htCapable)) ||
+ (psessionEntry->limQosEnabled &&
+ (pBeaconStruct->edcaPresent ||
+ pAddBssParams->staContext.htCapable)))
+ pAddBssParams->staContext.wmmEnabled = 1;
+ else
+ pAddBssParams->staContext.wmmEnabled = 0;
+
+ /* Update the rates */
+#ifdef WLAN_FEATURE_11AC
+ lim_populate_peer_rate_set(pMac,
+ &pAddBssParams->staContext.
+ supportedRates,
+ pBeaconStruct->HTCaps.supportedMCSSet,
+ false, psessionEntry,
+ &pBeaconStruct->VHTCaps);
+#else
+ lim_populate_peer_rate_set(pMac,
+ &pAddBssParams->staContext.
+ supportedRates,
+ pBeaconStruct->HTCaps.supportedMCSSet,
+ false, psessionEntry);
+#endif
+ lim_fill_supported_rates_info(pMac, NULL,
+ &pAddBssParams->staContext.
+ supportedRates, psessionEntry);
+
+
+ pAddBssParams->staContext.encryptType = psessionEntry->encryptType;
+
+#if defined WLAN_FEATURE_VOWIFI
+ pAddBssParams->maxTxPower = psessionEntry->maxTxPower;
+ lim_log(pMac, LOG2, FL("maxTxPower: %d"), pAddBssParams->maxTxPower);
+#endif
+
+ pAddBssParams->status = CDF_STATUS_SUCCESS;
+ pAddBssParams->respReqd = true;
+
+ pAddBssParams->staContext.smesessionId = psessionEntry->smeSessionId;
+ pAddBssParams->staContext.sessionId = psessionEntry->peSessionId;
+ pAddBssParams->sessionId = psessionEntry->peSessionId;
+
+ pAddBssParams->halPersona = (uint8_t) psessionEntry->pePersona; /* update persona */
+
+ pAddBssParams->bSpectrumMgtEnabled = psessionEntry->spectrumMgtEnabled;
+
+#if defined WLAN_FEATURE_VOWIFI_11R
+ pAddBssParams->extSetStaKeyParamValid = 0;
+ lim_log(pMac, LOG2, FL("extSetStaKeyParamValid: %d"),
+ pAddBssParams->extSetStaKeyParamValid);
+#endif
+
+#ifdef WLAN_FEATURE_11W
+ if (psessionEntry->limRmfEnabled) {
+ pAddBssParams->rmfEnabled = 1;
+ pAddBssParams->staContext.rmfEnabled = 1;
+ }
+#endif
+
+ pAddBssParams->nss = psessionEntry->nss;
+ lim_log(pMac, LOG2, FL("nss value: %d"), pAddBssParams->nss);
+
+ /* Set a new state for MLME */
+ psessionEntry->limMlmState = eLIM_MLM_WT_ADD_BSS_RSP_PREASSOC_STATE;
+
+ MTRACE(mac_trace
+ (pMac, TRACE_CODE_MLM_STATE, psessionEntry->peSessionId,
+ psessionEntry->limMlmState));
+
+ lim_log(pMac, LOG2, FL("staContext wmmEnabled: %d encryptType: %d "
+ "p2pCapableSta: %d"),
+ pAddBssParams->staContext.wmmEnabled,
+ pAddBssParams->staContext.encryptType,
+ pAddBssParams->staContext.p2pCapableSta);
+
+ lim_log(pMac, LOG2, FL("bSpectrumMgtEnabled: %d halPersona: %d setting "
+ "LimMlm state to %d"),
+ pAddBssParams->bSpectrumMgtEnabled, pAddBssParams->halPersona,
+ psessionEntry->limMlmState);
+
+ /* we need to defer the message until we get the response back from HAL. */
+ SET_LIM_PROCESS_DEFD_MESGS(pMac, false);
+
+ msgQ.type = WMA_ADD_BSS_REQ;
+ /** @ToDo : Update the Global counter to keeptrack of the PE <--> HAL messages*/
+ msgQ.reserved = 0;
+ msgQ.bodyptr = pAddBssParams;
+ msgQ.bodyval = 0;
+
+ lim_log(pMac, LOG1, FL("SessionId:%d Sending WMA_ADD_BSS_REQ"),
+ psessionEntry->peSessionId);
+ MTRACE(mac_trace_msg_tx(pMac, psessionEntry->peSessionId, msgQ.type));
+
+ retCode = wma_post_ctrl_msg(pMac, &msgQ);
+ if (eSIR_SUCCESS != retCode) {
+ SET_LIM_PROCESS_DEFD_MESGS(pMac, true);
+ cdf_mem_free(pAddBssParams);
+ lim_log(pMac, LOGE,
+ FL("Posting ADD_BSS_REQ to HAL failed, reason=%X"),
+ retCode);
+ goto returnFailure;
+
+ } else {
+ cdf_mem_free(pBeaconStruct);
+ return retCode;
+ }
+
+returnFailure:
+ /* Clean-up will be done by the caller... */
+ cdf_mem_free(pBeaconStruct);
+ return retCode;
+}
+
+/**
+ * lim_prepare_and_send_del_sta_cnf() - prepares and send del sta cnf
+ *
+ * @pMac: mac global context
+ * @pStaDs: sta dph node
+ * @statusCode: status code
+ * @psessionEntry: session context
+ *
+ * deletes DPH entry, changes the MLM mode for station, calls
+ * lim_send_del_sta_cnf
+ *
+ * Return: void
+ */
+void
+lim_prepare_and_send_del_sta_cnf(tpAniSirGlobal pMac, tpDphHashNode pStaDs,
+ tSirResultCodes statusCode,
+ tpPESession psessionEntry)
+{
+ uint16_t staDsAssocId = 0;
+ tSirMacAddr staDsAddr;
+ tLimMlmStaContext mlmStaContext;
+
+ if (pStaDs == NULL) {
+ PELOGW(lim_log(pMac, LOGW, FL("pStaDs is NULL"));)
+ return;
+ }
+ staDsAssocId = pStaDs->assocId;
+ cdf_mem_copy((uint8_t *) staDsAddr,
+ pStaDs->staAddr, sizeof(tSirMacAddr));
+
+ mlmStaContext = pStaDs->mlmStaContext;
+ if (LIM_IS_AP_ROLE(psessionEntry) ||
+ LIM_IS_BT_AMP_AP_ROLE(psessionEntry)) {
+ lim_release_peer_idx(pMac, pStaDs->assocId, psessionEntry);
+ }
+ lim_delete_dph_hash_entry(pMac, pStaDs->staAddr, pStaDs->assocId,
+ psessionEntry);
+
+ if (LIM_IS_STA_ROLE(psessionEntry) ||
+ LIM_IS_BT_AMP_STA_ROLE(psessionEntry)) {
+ psessionEntry->limMlmState = eLIM_MLM_IDLE_STATE;
+ MTRACE(mac_trace(pMac, TRACE_CODE_MLM_STATE,
+ psessionEntry->peSessionId,
+ psessionEntry->limMlmState));
+ }
+ lim_send_del_sta_cnf(pMac, staDsAddr, staDsAssocId, mlmStaContext,
+ statusCode, psessionEntry);
+}
+
+/** -------------------------------------------------------------
+ \fn lim_get_sta_rate_mode
+ \brief Gets the Station Rate Mode.
+ \param uint8_t dot11Mode
+ \return none
+ -------------------------------------------------------------*/
+tStaRateMode lim_get_sta_rate_mode(uint8_t dot11Mode)
+{
+ switch (dot11Mode) {
+ case WNI_CFG_DOT11_MODE_11A:
+ return eSTA_11a;
+ case WNI_CFG_DOT11_MODE_11B:
+ return eSTA_11b;
+ case WNI_CFG_DOT11_MODE_11G:
+ return eSTA_11bg;
+ case WNI_CFG_DOT11_MODE_11N:
+ return eSTA_11n;
+#ifdef WLAN_FEATURE_11AC
+ case WNI_CFG_DOT11_MODE_11AC:
+ return eSTA_11ac;
+#endif
+ case WNI_CFG_DOT11_MODE_ALL:
+ default:
+ return eSTA_11n;
+
+ }
+}
+
+/** -------------------------------------------------------------
+ \fn lim_init_pre_auth_timer_table
+ \brief Initialize the Pre Auth Tanle and creates the timer for
+ each node for the timeout value got from cfg.
+ \param tpAniSirGlobal pMac
+ \param tpLimPreAuthTable pPreAuthTimerTable
+ \return none
+ -------------------------------------------------------------*/
+void lim_init_pre_auth_timer_table(tpAniSirGlobal pMac,
+ tpLimPreAuthTable pPreAuthTimerTable)
+{
+ uint32_t cfgValue;
+ uint32_t authNodeIdx;
+ tpLimPreAuthNode pAuthNode = pPreAuthTimerTable->pTable;
+
+ /* Get AUTH_RSP Timers value */
+
+ if (wlan_cfg_get_int(pMac, WNI_CFG_AUTHENTICATE_RSP_TIMEOUT,
+ &cfgValue) != eSIR_SUCCESS) {
+ /*
+ ** Could not get AUTH_RSP timeout value
+ ** from CFG. Log error.
+ **/
+ lim_log(pMac, LOGP,
+ FL("could not retrieve AUTH_RSP timeout value"));
+ return;
+ }
+
+ cfgValue = SYS_MS_TO_TICKS(cfgValue);
+ for (authNodeIdx = 0; authNodeIdx < pPreAuthTimerTable->numEntry;
+ authNodeIdx++, pAuthNode++) {
+ if (tx_timer_create
+ (&pAuthNode->timer, "AUTH RESPONSE TIMEOUT",
+ lim_auth_response_timer_handler, authNodeIdx, cfgValue, 0,
+ TX_NO_ACTIVATE) != TX_SUCCESS) {
+ /* Cannot create timer. Log error. */
+ lim_log(pMac, LOGP,
+ FL("Cannot create Auth Rsp timer of Index :%d."),
+ authNodeIdx);
+ return;
+ }
+ pAuthNode->authNodeIdx = (uint8_t) authNodeIdx;
+ pAuthNode->fFree = 1;
+ }
+
+}
+
+/** -------------------------------------------------------------
+ \fn lim_acquire_free_pre_auth_node
+ \brief Retrives a free Pre Auth node from Pre Auth Table.
+ \param tpAniSirGlobal pMac
+ \param tpLimPreAuthTable pPreAuthTimerTable
+ \return none
+ -------------------------------------------------------------*/
+tLimPreAuthNode *lim_acquire_free_pre_auth_node(tpAniSirGlobal pMac,
+ tpLimPreAuthTable pPreAuthTimerTable)
+{
+ uint32_t i;
+ tLimPreAuthNode *pTempNode = pPreAuthTimerTable->pTable;
+ for (i = 0; i < pPreAuthTimerTable->numEntry; i++, pTempNode++) {
+ if (pTempNode->fFree == 1) {
+ pTempNode->fFree = 0;
+ return pTempNode;
+ }
+ }
+
+ return NULL;
+}
+
+/** -------------------------------------------------------------
+ \fn lim_get_pre_auth_node_from_index
+ \brief Depending on the Index this retrives the pre auth node.
+ \param tpAniSirGlobal pMac
+ \param tpLimPreAuthTable pAuthTable
+ \param uint32_t authNodeIdx
+ \return none
+ -------------------------------------------------------------*/
+tLimPreAuthNode *lim_get_pre_auth_node_from_index(tpAniSirGlobal pMac,
+ tpLimPreAuthTable pAuthTable,
+ uint32_t authNodeIdx)
+{
+ if ((authNodeIdx >= pAuthTable->numEntry)
+ || (pAuthTable->pTable == NULL)) {
+ lim_log(pMac, LOGE,
+ FL("Invalid Auth Timer Index : %d NumEntry : %d"),
+ authNodeIdx, pAuthTable->numEntry);
+ return NULL;
+ }
+
+ return pAuthTable->pTable + authNodeIdx;
+}
+
+/* Util API to check if the channels supported by STA is within range */
+tSirRetStatus lim_is_dot11h_supported_channels_valid(tpAniSirGlobal pMac,
+ tSirAssocReq *assoc)
+{
+ /*
+ * Allow all the stations to join with us.
+ * 802.11h-2003 11.6.1 => An AP may use the supported channels list for associated STAs
+ * as an input into an algorithm used to select a new channel for the BSS.
+ * The specification of the algorithm is beyond the scope of this amendment.
+ */
+
+ return eSIR_SUCCESS;
+}
+
+/* Util API to check if the txpower supported by STA is within range */
+tSirRetStatus lim_is_dot11h_power_capabilities_in_range(tpAniSirGlobal pMac,
+ tSirAssocReq *assoc,
+ tpPESession psessionEntry)
+{
+ tPowerdBm localMaxTxPower;
+ uint32_t localPwrConstraint;
+
+ localMaxTxPower =
+ cfg_get_regulatory_max_transmit_power(pMac,
+ psessionEntry->currentOperChannel);
+
+ if (wlan_cfg_get_int
+ (pMac, WNI_CFG_LOCAL_POWER_CONSTRAINT,
+ &localPwrConstraint) != eSIR_SUCCESS) {
+ lim_log(pMac, LOGP,
+ FL("Unable to get Local Power Constraint from cfg"));
+ return eSIR_FAILURE;
+ }
+ localMaxTxPower -= (tPowerdBm) localPwrConstraint;
+
+ /**
+ * The min Tx Power of the associating station should not be greater than (regulatory
+ * max tx power - local power constraint configured on AP).
+ */
+ if (assoc->powerCapability.minTxPower > localMaxTxPower) {
+ lim_log(pMac, LOGW,
+ FL("minTxPower (STA) = %d, localMaxTxPower (AP) = %d"),
+ assoc->powerCapability.minTxPower, localMaxTxPower);
+ return eSIR_FAILURE;
+ }
+
+ return eSIR_SUCCESS;
+}
+
+/** -------------------------------------------------------------
+ \fn lim_fill_rx_highest_supported_rate
+ \brief Fills in the Rx Highest Supported Data Rate field from
+ \ the 'supported MCS set' field in HT capability element.
+ \param tpAniSirGlobal pMac
+ \param tpSirSupportedRates pRates
+ \param uint8_t* pSupportedMCSSet
+ \return none
+ -------------------------------------------------------------*/
+void lim_fill_rx_highest_supported_rate(tpAniSirGlobal pMac,
+ uint16_t *rxHighestRate,
+ uint8_t *pSupportedMCSSet)
+{
+ tSirMacRxHighestSupportRate *pRxHighestRate;
+ uint8_t *pBuf;
+ uint16_t rate = 0;
+
+ pBuf = pSupportedMCSSet + MCS_RX_HIGHEST_SUPPORTED_RATE_BYTE_OFFSET;
+ rate = lim_get_u16(pBuf);
+
+ pRxHighestRate = (tSirMacRxHighestSupportRate *) &rate;
+ *rxHighestRate = pRxHighestRate->rate;
+
+ return;
+}
+
+#ifdef WLAN_FEATURE_11W
+/** -------------------------------------------------------------
+ \fn lim_send_sme_unprotected_mgmt_frame_ind
+ \brief Forwards the unprotected management frame to SME.
+ \param tpAniSirGlobal pMac
+ \param frameType - 802.11 frame type
+ \param frame - frame buffer
+ \param sessionId - id for the current session
+ \param psessionEntry - PE session context
+ \return none
+ -------------------------------------------------------------*/
+void lim_send_sme_unprotected_mgmt_frame_ind(tpAniSirGlobal pMac, uint8_t frameType,
+ uint8_t *frame, uint32_t frameLen,
+ uint16_t sessionId,
+ tpPESession psessionEntry)
+{
+ tSirMsgQ mmhMsg;
+ tSirSmeUnprotMgmtFrameInd *pSirSmeMgmtFrame = NULL;
+ uint16_t length;
+
+ length = sizeof(tSirSmeUnprotMgmtFrameInd) + frameLen;
+
+ pSirSmeMgmtFrame = cdf_mem_malloc(length);
+ if (NULL == pSirSmeMgmtFrame) {
+ lim_log(pMac, LOGP,
+ FL
+ ("AllocateMemory failed for tSirSmeUnprotectedMgmtFrameInd"));
+ return;
+ }
+ cdf_mem_set((void *)pSirSmeMgmtFrame, length, 0);
+
+ pSirSmeMgmtFrame->sessionId = sessionId;
+ pSirSmeMgmtFrame->frameType = frameType;
+
+ cdf_mem_copy(pSirSmeMgmtFrame->frameBuf, frame, frameLen);
+ pSirSmeMgmtFrame->frameLen = frameLen;
+
+ mmhMsg.type = eWNI_SME_UNPROT_MGMT_FRM_IND;
+ mmhMsg.bodyptr = pSirSmeMgmtFrame;
+ mmhMsg.bodyval = 0;
+
+ lim_sys_process_mmh_msg_api(pMac, &mmhMsg, ePROT);
+ return;
+}
+#endif
+
+#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
+/** -------------------------------------------------------------
+ \fn lim_send_sme_tsm_ie_ind
+ \brief Forwards the TSM IE information to SME.
+ \param tpAniSirGlobal pMac
+ \param psessionEntry - PE session context
+ \param tid - traffic id
+ \param state - tsm state (enabled/disabled)
+ \param measurementInterval - measurement interval
+ \return none
+ -------------------------------------------------------------*/
+void lim_send_sme_tsm_ie_ind(tpAniSirGlobal pMac, tpPESession psessionEntry,
+ uint8_t tid, uint8_t state, uint16_t measInterval)
+{
+ tSirMsgQ mmhMsg;
+ tpSirSmeTsmIEInd pSirSmeTsmIeInd = NULL;
+
+ if (!pMac || !psessionEntry)
+ return;
+
+ pSirSmeTsmIeInd = cdf_mem_malloc(sizeof(tSirSmeTsmIEInd));
+ if (NULL == pSirSmeTsmIeInd) {
+ lim_log(pMac, LOGP,
+ FL("AllocateMemory failed for tSirSmeTsmIEInd"));
+ return;
+ }
+ cdf_mem_set((void *)pSirSmeTsmIeInd, sizeof(tSirSmeTsmIEInd), 0);
+
+ pSirSmeTsmIeInd->sessionId = psessionEntry->smeSessionId;
+ pSirSmeTsmIeInd->tsmIe.tsid = tid;
+ pSirSmeTsmIeInd->tsmIe.state = state;
+ pSirSmeTsmIeInd->tsmIe.msmt_interval = measInterval;
+
+ mmhMsg.type = eWNI_SME_TSM_IE_IND;
+ mmhMsg.bodyptr = pSirSmeTsmIeInd;
+ mmhMsg.bodyval = 0;
+
+ lim_sys_process_mmh_msg_api(pMac, &mmhMsg, ePROT);
+ return;
+}
+#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
diff --git a/core/mac/src/pe/lim/lim_assoc_utils.h b/core/mac/src/pe/lim/lim_assoc_utils.h
new file mode 100644
index 0000000..b9efbff
--- /dev/null
+++ b/core/mac/src/pe/lim/lim_assoc_utils.h
@@ -0,0 +1,212 @@
+/*
+ * Copyright (c) 2011-2015 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_assoc_utils.h contains the utility definitions
+ * LIM uses while processing Re/Association messages.
+ * Author: Chandra Modumudi
+ * Date: 02/13/02
+ * History:-
+ * Date Modified by Modification Information
+ * --------------------------------------------------------------------
+ * 05/26/10 js WPA handling in (Re)Assoc frames
+ *
+ */
+#ifndef __LIM_ASSOC_UTILS_H
+#define __LIM_ASSOC_UTILS_H
+
+#include "sir_api.h"
+#include "sir_debug.h"
+#include "cfg_api.h"
+
+#include "lim_types.h"
+
+uint8_t lim_cmp_s_sid(tpAniSirGlobal, tSirMacSSid *, tpPESession);
+uint8_t lim_compare_capabilities(tpAniSirGlobal,
+ tSirAssocReq *,
+ tSirMacCapabilityInfo *, tpPESession);
+uint8_t lim_check_rx_basic_rates(tpAniSirGlobal, tSirMacRateSet, tpPESession);
+uint8_t lim_check_rx_rsn_ie_match(tpAniSirGlobal, tDot11fIERSN, tpPESession, uint8_t,
+ bool *);
+uint8_t lim_check_rx_wpa_ie_match(tpAniSirGlobal, tDot11fIEWPA, tpPESession,
+ uint8_t);
+uint8_t lim_check_mcs_set(tpAniSirGlobal pMac, uint8_t *supportedMCSSet);
+void limPostDummyToTmRing(tpAniSirGlobal, tpDphHashNode);
+void limPostPacketToTdRing(tpAniSirGlobal, tpDphHashNode, uint8_t);
+tSirRetStatus lim_cleanup_rx_path(tpAniSirGlobal, tpDphHashNode, tpPESession);
+void lim_reject_association(tpAniSirGlobal, tSirMacAddr, uint8_t,
+ uint8_t, tAniAuthType,
+ uint16_t, uint8_t, tSirResultCodes, tpPESession);
+
+#ifdef WLAN_FEATURE_11AC
+tSirRetStatus lim_populate_peer_rate_set(tpAniSirGlobal pMac,
+ tpSirSupportedRates pRates,
+ uint8_t *pSupportedMCSSet,
+ uint8_t basicOnly,
+ tpPESession psessionEntry,
+ tDot11fIEVHTCaps *pVHTCaps);
+#else
+tSirRetStatus lim_populate_peer_rate_set(tpAniSirGlobal pMac,
+ tpSirSupportedRates pRates,
+ uint8_t *pSupportedMCSSet,
+ uint8_t basicOnly,
+ tpPESession psessionEntry);
+#endif
+
+#ifdef WLAN_FEATURE_11AC
+tSirRetStatus lim_populate_own_rate_set(tpAniSirGlobal pMac,
+ tpSirSupportedRates pRates,
+ uint8_t *pSupportedMCSSet,
+ uint8_t basicOnly,
+ tpPESession psessionEntry,
+ tDot11fIEVHTCaps *pVHTCaps);
+
+#else
+tSirRetStatus lim_populate_own_rate_set(tpAniSirGlobal pMac,
+ tpSirSupportedRates pRates,
+ uint8_t *pSupportedMCSSet,
+ uint8_t basicOnly,
+ tpPESession psessionEntry);
+#endif
+
+#ifdef WLAN_FEATURE_11AC
+tSirRetStatus
+lim_populate_matching_rate_set(tpAniSirGlobal pMac,
+ tpDphHashNode pStaDs,
+ tSirMacRateSet *pOperRateSet,
+ tSirMacRateSet *pExtRateSet,
+ uint8_t *pSupportedMCSSet,
+ tpPESession psessionEntry,
+ tDot11fIEVHTCaps *pVHTCaps);
+#else
+tSirRetStatus lim_populate_matching_rate_set(tpAniSirGlobal,
+ tpDphHashNode,
+ tSirMacRateSet *,
+ tSirMacRateSet *,
+ uint8_t *pSupportedMCSSet,
+ tpPESession);
+
+#endif
+
+#ifdef WLAN_FEATURE_11AC
+#define MCSMAPMASK1x1 0x3
+#define MCSMAPMASK2x2 0xC
+#endif
+
+tSirRetStatus lim_add_sta(tpAniSirGlobal, tpDphHashNode, uint8_t, tpPESession);
+tSirRetStatus lim_del_bss(tpAniSirGlobal, tpDphHashNode, uint16_t, tpPESession);
+tSirRetStatus lim_del_sta(tpAniSirGlobal, tpDphHashNode, bool, tpPESession);
+#ifdef WLAN_FEATURE_VOWIFI_11R
+tSirRetStatus lim_add_ft_sta_self(tpAniSirGlobal pMac, uint16_t assocId,
+ tpPESession psessionEntry);
+#endif /* WLAN_FEATURE_VOWIFI_11R */
+tSirRetStatus lim_add_sta_self(tpAniSirGlobal, uint16_t, uint8_t, tpPESession);
+tStaRateMode lim_get_sta_rate_mode(uint8_t dot11Mode);
+
+void lim_teardown_infra_bss(tpAniSirGlobal, tpPESession);
+void lim_restore_pre_reassoc_state(tpAniSirGlobal,
+ tSirResultCodes, uint16_t, tpPESession);
+void lim_post_reassoc_failure(tpAniSirGlobal,
+ tSirResultCodes, uint16_t, tpPESession);
+bool lim_is_reassoc_in_progress(tpAniSirGlobal, tpPESession);
+void
+lim_send_del_sta_cnf(tpAniSirGlobal pMac, tSirMacAddr staDsAddr,
+ uint16_t staDsAssocId, tLimMlmStaContext mlmStaContext,
+ tSirResultCodes statusCode, tpPESession psessionEntry);
+
+void lim_handle_cnf_wait_timeout(tpAniSirGlobal pMac, uint16_t staId);
+void lim_delete_dph_hash_entry(tpAniSirGlobal, tSirMacAddr, uint16_t, tpPESession);
+void lim_check_and_announce_join_success(tpAniSirGlobal,
+ tSirProbeRespBeacon *,
+ tpSirMacMgmtHdr, tpPESession);
+void lim_update_re_assoc_globals(tpAniSirGlobal pMac,
+ tpSirAssocRsp pAssocRsp,
+ tpPESession psessionEntry);
+
+void lim_update_assoc_sta_datas(tpAniSirGlobal pMac,
+ tpDphHashNode pStaDs, tpSirAssocRsp pAssocRsp,
+ tpPESession psessionEntry);
+void lim_fill_supported_rates_info(tpAniSirGlobal pMac, tpDphHashNode pSta,
+ tpSirSupportedRates pRates,
+ tpPESession psessionEntry);
+
+tSirRetStatus lim_sta_send_add_bss(tpAniSirGlobal pMac, tpSirAssocRsp pAssocRsp,
+ tpSchBeaconStruct pBeaconStruct,
+ tpSirBssDescription bssDescription,
+ uint8_t updateEntry, tpPESession psessionEntry);
+tSirRetStatus lim_sta_send_add_bss_pre_assoc(tpAniSirGlobal pMac, uint8_t updateEntry,
+ tpPESession psessionEntry);
+
+void lim_prepare_and_send_del_sta_cnf(tpAniSirGlobal pMac, tpDphHashNode pStaDs,
+ tSirResultCodes statusCode, tpPESession);
+tSirRetStatus lim_extract_ap_capabilities(tpAniSirGlobal pMac, uint8_t *pIE,
+ uint16_t ieLen,
+ tpSirProbeRespBeacon beaconStruct);
+void lim_init_pre_auth_timer_table(tpAniSirGlobal pMac,
+ tpLimPreAuthTable pPreAuthTimerTable);
+tpLimPreAuthNode lim_acquire_free_pre_auth_node(tpAniSirGlobal pMac,
+ tpLimPreAuthTable
+ pPreAuthTimerTable);
+tpLimPreAuthNode lim_get_pre_auth_node_from_index(tpAniSirGlobal pMac,
+ tpLimPreAuthTable pAuthTable,
+ uint32_t authNodeIdx);
+
+/* Util API to check if the channels supported by STA is within range */
+tSirRetStatus lim_is_dot11h_supported_channels_valid(tpAniSirGlobal pMac,
+ tSirAssocReq *assoc);
+
+/* Util API to check if the txpower supported by STA is within range */
+tSirRetStatus lim_is_dot11h_power_capabilities_in_range(tpAniSirGlobal pMac,
+ tSirAssocReq *assoc,
+ tpPESession);
+
+/* API to re-add the same BSS during re-association */
+void lim_handle_add_bss_in_re_assoc_context(tpAniSirGlobal pMac, tpDphHashNode pStaDs,
+ tpPESession psessionEntry);
+
+/* API to fill in RX Highest Supported data Rate */
+void lim_fill_rx_highest_supported_rate(tpAniSirGlobal pMac,
+ uint16_t *rxHighestRate,
+ uint8_t *pSupportedMCSSet);
+#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
+void lim_send_retry_reassoc_req_frame(tpAniSirGlobal pMac,
+ tLimMlmReassocReq *pMlmReassocReq,
+ tpPESession psessionEntry);
+#endif
+#ifdef WLAN_FEATURE_11W
+void lim_send_sme_unprotected_mgmt_frame_ind(tpAniSirGlobal pMac, uint8_t frameType,
+ uint8_t *frame, uint32_t frameLen,
+ uint16_t sessionId,
+ tpPESession psessionEntry);
+#endif
+
+#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
+void lim_send_sme_tsm_ie_ind(tpAniSirGlobal pMac, tpPESession psessionEntry,
+ uint8_t tid, uint8_t state, uint16_t measInterval);
+#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
+
+#endif /* __LIM_ASSOC_UTILS_H */
diff --git a/core/mac/src/pe/lim/lim_debug.c b/core/mac/src/pe/lim/lim_debug.c
new file mode 100644
index 0000000..51620d7
--- /dev/null
+++ b/core/mac/src/pe/lim/lim_debug.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2014 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.
+ */
+
+/**=========================================================================
+
+ \file lim_debug.c
+
+ \brief implementation for log Debug related APIs
+
+ \author Sunit Bhatia
+
+ ========================================================================*/
+
+#include "lim_debug.h"
+
+void lim_log(tpAniSirGlobal pMac, uint32_t loglevel, const char *pString, ...)
+{
+#ifdef WLAN_DEBUG
+ /* Verify against current log level */
+ if (loglevel >
+ pMac->utils.gLogDbgLevel[LOG_INDEX_FOR_MODULE(SIR_LIM_MODULE_ID)])
+ return;
+ else {
+ va_list marker;
+
+ va_start(marker, pString); /* Initialize variable arguments. */
+
+ log_debug(pMac, SIR_LIM_MODULE_ID, loglevel, pString, marker);
+
+ va_end(marker); /* Reset variable arguments. */
+ }
+#endif
+}
diff --git a/core/mac/src/pe/lim/lim_debug.h b/core/mac/src/pe/lim/lim_debug.h
new file mode 100644
index 0000000..e0ab7f6
--- /dev/null
+++ b/core/mac/src/pe/lim/lim_debug.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2011-2012, 2014-2015 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_debug.h contains log function called by LIM module.
+ *
+ * Author: Chandra Modumudi
+ * Date: 02/11/02
+ * History:-
+ * Date Modified by Modification Information
+ * --------------------------------------------------------------------
+ *
+ */
+
+#ifndef __LIM_DEBUG_H__
+#define __LIM_DEBUG_H__
+
+#include "utils_api.h"
+#include "sir_debug.h"
+
+#if !defined(__printf)
+#define __printf(a, b)
+#endif
+
+void __printf(3, 4) lim_log(tpAniSirGlobal pMac, uint32_t loglevel,
+ const char *pString, ...);
+
+/* define this to show more message in the LIM during TDLS development */
+#define LIM_DEBUG_TDLS
+
+#ifdef LIM_DEBUG_TDLS
+#define LIM_LOG_TDLS(x0) x0
+#else
+#define LIM_LOG_TDLS(x0)
+#endif
+
+#endif
diff --git a/core/mac/src/pe/lim/lim_ft.c b/core/mac/src/pe/lim/lim_ft.c
new file mode 100644
index 0000000..c96327c
--- /dev/null
+++ b/core/mac/src/pe/lim/lim_ft.c
@@ -0,0 +1,2027 @@
+/*
+ * Copyright (c) 2012-2015 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.
+ */
+
+#ifdef WLAN_FEATURE_VOWIFI_11R
+/**=========================================================================
+
+ \brief implementation for PE 11r VoWiFi FT Protocol
+
+ ========================================================================*/
+
+/* $Header$ */
+
+/*--------------------------------------------------------------------------
+ Include Files
+ ------------------------------------------------------------------------*/
+#include <lim_send_messages.h>
+#include <lim_types.h>
+#include <lim_ft.h>
+#include <lim_ft_defs.h>
+#include <lim_utils.h>
+#include <lim_prop_exts_utils.h>
+#include <lim_assoc_utils.h>
+#include <lim_session.h>
+#include <lim_admit_control.h>
+#include "wmm_apsd.h"
+
+extern void lim_send_set_sta_key_req(tpAniSirGlobal pMac,
+ tLimMlmSetKeysReq *pMlmSetKeysReq,
+ uint16_t staIdx,
+ uint8_t defWEPIdx,
+ tpPESession sessionEntry, bool sendRsp);
+
+/*--------------------------------------------------------------------------
+ Initialize the FT variables.
+ ------------------------------------------------------------------------*/
+void lim_ft_open(tpAniSirGlobal pMac, tpPESession psessionEntry)
+{
+ if (psessionEntry)
+ cdf_mem_set(&psessionEntry->ftPEContext, sizeof(tftPEContext),
+ 0);
+}
+
+/*--------------------------------------------------------------------------
+ Cleanup FT variables.
+ ------------------------------------------------------------------------*/
+void lim_ft_cleanup_pre_auth_info(tpAniSirGlobal pMac, tpPESession psessionEntry)
+{
+ tpPESession pReAssocSessionEntry = NULL;
+ uint8_t sessionId = 0;
+
+ if (!psessionEntry) {
+#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG
+ PELOGE(lim_log
+ (pMac, LOGE, "%s: psessionEntry is NULL", __func__);
+ )
+#endif
+ return;
+ }
+
+ /* Nothing to be done if the session is not in STA mode */
+ if (!LIM_IS_STA_ROLE(psessionEntry)) {
+#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG
+ PELOGE(lim_log
+ (pMac, LOGE, FL("psessionEntry is not in STA mode"));
+ )
+#endif
+ return;
+ }
+
+ if (psessionEntry->ftPEContext.pFTPreAuthReq) {
+ pReAssocSessionEntry =
+ pe_find_session_by_bssid(pMac,
+ psessionEntry->ftPEContext.
+ pFTPreAuthReq->preAuthbssId,
+ &sessionId);
+
+#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG
+ PELOG1(lim_log(pMac, LOG1, FL("Freeing pFTPreAuthReq= %p"),
+ psessionEntry->ftPEContext.pFTPreAuthReq);
+ )
+#endif
+ if (psessionEntry->ftPEContext.pFTPreAuthReq->
+ pbssDescription) {
+ cdf_mem_free(psessionEntry->ftPEContext.pFTPreAuthReq->
+ pbssDescription);
+ psessionEntry->ftPEContext.pFTPreAuthReq->
+ pbssDescription = NULL;
+ }
+ cdf_mem_free(psessionEntry->ftPEContext.pFTPreAuthReq);
+ psessionEntry->ftPEContext.pFTPreAuthReq = NULL;
+ }
+
+ if (psessionEntry->ftPEContext.pAddBssReq) {
+ cdf_mem_free(psessionEntry->ftPEContext.pAddBssReq);
+ psessionEntry->ftPEContext.pAddBssReq = NULL;
+ }
+
+ if (psessionEntry->ftPEContext.pAddStaReq) {
+ cdf_mem_free(psessionEntry->ftPEContext.pAddStaReq);
+ psessionEntry->ftPEContext.pAddStaReq = NULL;
+ }
+
+ /* The session is being deleted, cleanup the contents */
+ cdf_mem_set(&psessionEntry->ftPEContext, sizeof(tftPEContext), 0);
+
+ /* Delete the session created while handling pre-auth response */
+ if (pReAssocSessionEntry) {
+ /* If we have successful pre-auth response, then we would have
+ * created a session on which reassoc request will be sent
+ */
+ if (pReAssocSessionEntry->valid &&
+ pReAssocSessionEntry->limSmeState ==
+ eLIM_SME_WT_REASSOC_STATE) {
+ CDF_TRACE(CDF_MODULE_ID_PE,
+ CDF_TRACE_LEVEL_DEBUG,
+ FL("Deleting Preauth session(%d)"),
+ pReAssocSessionEntry->peSessionId);
+ pe_delete_session(pMac, pReAssocSessionEntry);
+ }
+ }
+}
+
+void lim_ft_cleanup_all_ft_sessions(tpAniSirGlobal pMac)
+{
+ /* Wrapper function to cleanup all FT sessions */
+ int i;
+
+ for (i = 0; i < pMac->lim.maxBssId; i++) {
+ if (true == pMac->lim.gpSession[i].valid) {
+ /* The session is valid, may have FT data */
+ lim_ft_cleanup(pMac, &pMac->lim.gpSession[i]);
+ }
+ }
+}
+
+void lim_ft_cleanup(tpAniSirGlobal pMac, tpPESession psessionEntry)
+{
+ if (NULL == psessionEntry) {
+#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG
+ PELOGE(lim_log(pMac, LOGE, FL("psessionEntry is NULL"));)
+#endif
+ return;
+ }
+
+ /* Nothing to be done if the session is not in STA mode */
+ if (!LIM_IS_STA_ROLE(psessionEntry)) {
+#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG
+ PELOGE(lim_log
+ (pMac, LOGE, FL("psessionEntry is not in STA mode"));
+ )
+#endif
+ return;
+ }
+
+ if (NULL != psessionEntry->ftPEContext.pFTPreAuthReq) {
+#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG
+ PELOG1(lim_log(pMac, LOG1, FL("Freeing pFTPreAuthReq= %p"),
+ psessionEntry->ftPEContext.pFTPreAuthReq);
+ )
+#endif
+ if (NULL !=
+ psessionEntry->ftPEContext.pFTPreAuthReq->
+ pbssDescription) {
+ cdf_mem_free(psessionEntry->ftPEContext.pFTPreAuthReq->
+ pbssDescription);
+ psessionEntry->ftPEContext.pFTPreAuthReq->
+ pbssDescription = NULL;
+ }
+ cdf_mem_free(psessionEntry->ftPEContext.pFTPreAuthReq);
+ psessionEntry->ftPEContext.pFTPreAuthReq = NULL;
+ }
+
+ if (psessionEntry->ftPEContext.pAddBssReq) {
+ cdf_mem_free(psessionEntry->ftPEContext.pAddBssReq);
+ psessionEntry->ftPEContext.pAddBssReq = NULL;
+ }
+
+ if (psessionEntry->ftPEContext.pAddStaReq) {
+ cdf_mem_free(psessionEntry->ftPEContext.pAddStaReq);
+ psessionEntry->ftPEContext.pAddStaReq = NULL;
+ }
+
+ /* The session is being deleted, cleanup the contents */
+ cdf_mem_set(&psessionEntry->ftPEContext, sizeof(tftPEContext), 0);
+}
+
+/*------------------------------------------------------------------
+ *
+ * This is the handler after suspending the link.
+ * We suspend the link and then now proceed to switch channel.
+ *
+ *------------------------------------------------------------------*/
+void static
+lim_ft_pre_auth_suspend_link_handler(tpAniSirGlobal pMac, CDF_STATUS status,
+ uint32_t *data)
+{
+ tpPESession psessionEntry = (tpPESession) data;
+
+ /* The link is suspended of not */
+ if (NULL == psessionEntry ||
+ NULL == psessionEntry->ftPEContext.pFTPreAuthReq ||
+ status != CDF_STATUS_SUCCESS) {
+ PELOGE(lim_log(pMac, LOGE,
+ FL("preAuth error, status = %d"), status);
+ )
+ lim_post_ft_pre_auth_rsp(pMac, eSIR_FAILURE, NULL, 0,
+ psessionEntry);
+ return;
+ }
+
+ /* Suspended, now move to a different channel.
+ * Perform some sanity check before proceeding
+ */
+ if (psessionEntry->ftPEContext.pFTPreAuthReq) {
+ lim_change_channel_with_callback(pMac,
+ psessionEntry->ftPEContext.
+ pFTPreAuthReq->preAuthchannelNum,
+ lim_perform_ft_pre_auth, NULL,
+ psessionEntry);
+ return;
+ }
+}
+
+/*
+ * lim_process_ft_pre_auth_req() - process ft pre auth req
+ *
+ * @mac_ctx: global mac ctx
+ * @msg: pointer to message
+ *
+ * In this function, we process the FT Pre Auth Req:
+ * We receive Pre-Auth, suspend link, register a call back. In the call back,
+ * we will need to accept frames from the new bssid. Send out the auth req to
+ * new AP. Start timer and when the timer is done or if we receive the Auth
+ * response. We change channel. Resume link
+ *
+ * Return: value to indicate if buffer was consumed
+ */
+int lim_process_ft_pre_auth_req(tpAniSirGlobal mac_ctx, tpSirMsgQ msg)
+{
+ int buf_consumed = false;
+ tpPESession session;
+ uint8_t session_id;
+ tpSirFTPreAuthReq ft_pre_auth_req = (tSirFTPreAuthReq *) msg->bodyptr;
+
+ if (NULL == ft_pre_auth_req) {
+#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG
+ PELOGE(lim_log(mac_ctx, LOGE, FL("tSirFTPreAuthReq is NULL"));)
+#endif
+ return buf_consumed;
+ }
+
+ /* Get the current session entry */
+ session = pe_find_session_by_bssid(mac_ctx,
+ ft_pre_auth_req->currbssId,
+ &session_id);
+ if (session == NULL) {
+ lim_log(mac_ctx, LOGE,
+ FL("Unable to find session for the bssid"
+ MAC_ADDRESS_STR),
+ MAC_ADDR_ARRAY(ft_pre_auth_req->currbssId));
+ /* Post the FT Pre Auth Response to SME */
+ lim_post_ft_pre_auth_rsp(mac_ctx, eSIR_FAILURE, NULL, 0,
+ session);
+ /*
+ * return FALSE, since the Pre-Auth Req will be freed in
+ * limPostFTPreAuthRsp on failure
+ */
+ return buf_consumed;
+ }
+
+ /* Nothing to be done if the session is not in STA mode */
+ if (!LIM_IS_STA_ROLE(session)) {
+#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG
+ lim_log(mac_ctx, LOGE, FL("session is not in STA mode"));
+#endif
+ buf_consumed = true;
+ return buf_consumed;
+ }
+
+ /* Can set it only after sending auth */
+ session->ftPEContext.ftPreAuthStatus = eSIR_FAILURE;
+ session->ftPEContext.ftPreAuthSession = true;
+
+ /* Indicate that this is the session on which preauth is being done */
+ if (session->ftPEContext.pFTPreAuthReq) {
+ if (session->ftPEContext.pFTPreAuthReq->pbssDescription) {
+ cdf_mem_free(
+ session->ftPEContext.pFTPreAuthReq->pbssDescription);
+ session->ftPEContext.pFTPreAuthReq->pbssDescription =
+ NULL;
+ }
+ cdf_mem_free(session->ftPEContext.pFTPreAuthReq);
+ session->ftPEContext.pFTPreAuthReq = NULL;
+ }
+
+ /* We need information from the Pre-Auth Req. Lets save that */
+ session->ftPEContext.pFTPreAuthReq = ft_pre_auth_req;
+
+#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG
+ lim_log(mac_ctx, LOG1, FL("PRE Auth ft_ies_length=%02x%02x%02x"),
+ session->ftPEContext.pFTPreAuthReq->ft_ies[0],
+ session->ftPEContext.pFTPreAuthReq->ft_ies[1],
+ session->ftPEContext.pFTPreAuthReq->ft_ies[2]);
+#endif
+#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */
+ lim_diag_event_report(mac_ctx, WLAN_PE_DIAG_PRE_AUTH_REQ_EVENT,
+ session, 0, 0);
+#endif
+
+ /* Dont need to suspend if APs are in same channel */
+ if (session->currentOperChannel !=
+ session->ftPEContext.pFTPreAuthReq->preAuthchannelNum) {
+ /* Need to suspend link only if the channels are different */
+ lim_log(mac_ctx, LOG2,
+ FL("Performing pre-auth on diff channel(session %p)"),
+ session);
+ lim_ft_pre_auth_suspend_link_handler(mac_ctx, CDF_STATUS_SUCCESS,
+ (uint32_t *)session);
+ } else {
+ lim_log(mac_ctx, LOG2,
+ FL("Performing pre-auth on same channel (session %p)"),
+ session);
+ /* We are in the same channel. Perform pre-auth */
+ lim_perform_ft_pre_auth(mac_ctx, CDF_STATUS_SUCCESS, NULL,
+ session);
+ }
+
+ return buf_consumed;
+}
+
+/*------------------------------------------------------------------
+ * Send the Auth1
+ * Receive back Auth2
+ *------------------------------------------------------------------*/
+void lim_perform_ft_pre_auth(tpAniSirGlobal pMac, CDF_STATUS status,
+ uint32_t *data, tpPESession psessionEntry)
+{
+ tSirMacAuthFrameBody authFrame;
+
+ if (NULL == psessionEntry) {
+ PELOGE(lim_log(pMac, LOGE, FL("psessionEntry is NULL"));)
+ return;
+ }
+
+ if (psessionEntry->is11Rconnection &&
+ psessionEntry->ftPEContext.pFTPreAuthReq) {
+ /* Only 11r assoc has FT IEs */
+ if (psessionEntry->ftPEContext.pFTPreAuthReq->ft_ies == NULL) {
+ PELOGE(lim_log(pMac, LOGE,
+ "%s: FTIEs for Auth Req Seq 1 is absent",
+ __func__);
+ )
+ goto preauth_fail;
+ }
+ }
+
+ if (status != CDF_STATUS_SUCCESS) {
+ PELOGE(lim_log(pMac, LOGE,
+ "%s: Change channel not successful for FT pre-auth",
+ __func__);
+ )
+ goto preauth_fail;
+ }
+
+ /* Nothing to be done if the session is not in STA mode */
+ if (!LIM_IS_STA_ROLE(psessionEntry)) {
+#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG
+ PELOGE(lim_log
+ (pMac, LOGE, FL("psessionEntry is not in STA mode"));
+ )
+#endif
+ return;
+ }
+#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG
+ PELOG2(lim_log(pMac, LOG2, "Entered wait auth2 state for FT"
+ " (old session %p)", psessionEntry);
+ )
+#endif
+ if (psessionEntry->is11Rconnection) {
+ /* Now we are on the right channel and need to send out Auth1 and
+ * receive Auth2
+ */
+ authFrame.authAlgoNumber = eSIR_FT_AUTH;
+ }
+#if defined FEATURE_WLAN_ESE || defined FEATURE_WLAN_LFR
+ else {
+ /* Will need to make isESEconnection a enum may be for further
+ * improvements to this to match this algorithm number
+ */
+ authFrame.authAlgoNumber = eSIR_OPEN_SYSTEM;
+ }
+#endif
+ authFrame.authTransactionSeqNumber = SIR_MAC_AUTH_FRAME_1;
+ authFrame.authStatusCode = 0;
+
+ /* Start timer here to come back to operating channel */
+ pMac->lim.limTimers.gLimFTPreAuthRspTimer.sessionId =
+ psessionEntry->peSessionId;
+ if (TX_SUCCESS !=
+ tx_timer_activate(&pMac->lim.limTimers.gLimFTPreAuthRspTimer)) {
+#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG
+ PELOGE(lim_log(pMac, LOGE, FL("FT Auth Rsp Timer Start Failed"));)
+#endif
+ }
+ MTRACE(mac_trace
+ (pMac, TRACE_CODE_TIMER_ACTIVATE, psessionEntry->peSessionId,
+ eLIM_FT_PREAUTH_RSP_TIMER));
+
+#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG
+ PELOG1(lim_log(pMac, LOG1, FL("FT Auth Rsp Timer Started"));)
+#endif
+#ifdef FEATURE_WLAN_DIAG_SUPPORT
+ lim_diag_event_report(pMac, WLAN_PE_DIAG_ROAM_AUTH_START_EVENT,
+ pMac->lim.pSessionEntry, eSIR_SUCCESS, eSIR_SUCCESS);
+#endif
+
+ lim_send_auth_mgmt_frame(pMac, &authFrame,
+ psessionEntry->ftPEContext.pFTPreAuthReq->
+ preAuthbssId, LIM_NO_WEP_IN_FC, psessionEntry);
+
+ return;
+
+preauth_fail:
+ lim_handle_ft_pre_auth_rsp(pMac, eSIR_FAILURE, NULL, 0, psessionEntry);
+ return;
+}
+
+/*------------------------------------------------------------------
+ *
+ * Create the new Add Bss Req to the new AP.
+ * This will be used when we are ready to FT to the new AP.
+ * The newly created ft Session entry is passed to this function
+ *
+ *------------------------------------------------------------------*/
+tSirRetStatus lim_ft_prepare_add_bss_req(tpAniSirGlobal pMac,
+ uint8_t updateEntry,
+ tpPESession pftSessionEntry,
+ tpSirBssDescription bssDescription)
+{
+ tpAddBssParams pAddBssParams = NULL;
+ tAddStaParams *sta_ctx;
+ uint8_t chanWidthSupp = 0;
+ tSchBeaconStruct *pBeaconStruct;
+
+ /* Nothing to be done if the session is not in STA mode */
+ if (!LIM_IS_STA_ROLE(pftSessionEntry)) {
+#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG
+ PELOGE(lim_log
+ (pMac, LOGE, FL("psessionEntry is not in STA mode"));
+ )
+#endif
+ return eSIR_FAILURE;
+ }
+
+ pBeaconStruct = cdf_mem_malloc(sizeof(tSchBeaconStruct));
+ if (NULL == pBeaconStruct) {
+ lim_log(pMac, LOGE,
+ FL("Unable to allocate memory for creating ADD_BSS"));
+ return eSIR_MEM_ALLOC_FAILED;
+ }
+ /* Package SIR_HAL_ADD_BSS_REQ message parameters */
+ pAddBssParams = cdf_mem_malloc(sizeof(tAddBssParams));
+ if (NULL == pAddBssParams) {
+ cdf_mem_free(pBeaconStruct);
+ lim_log(pMac, LOGP,
+ FL("Unable to allocate memory for creating ADD_BSS"));
+ return (eSIR_MEM_ALLOC_FAILED);
+ }
+
+ cdf_mem_set((uint8_t *) pAddBssParams, sizeof(tAddBssParams), 0);
+
+ lim_extract_ap_capabilities(pMac, (uint8_t *) bssDescription->ieFields,
+ lim_get_ielen_from_bss_description(bssDescription),
+ pBeaconStruct);
+
+ if (pMac->lim.gLimProtectionControl !=
+ WNI_CFG_FORCE_POLICY_PROTECTION_DISABLE)
+ lim_decide_sta_protection_on_assoc(pMac, pBeaconStruct,
+ pftSessionEntry);
+
+ cdf_mem_copy(pAddBssParams->bssId, bssDescription->bssId,
+ sizeof(tSirMacAddr));
+
+ /* Fill in tAddBssParams selfMacAddr */
+ cdf_mem_copy(pAddBssParams->selfMacAddr, pftSessionEntry->selfMacAddr,
+ sizeof(tSirMacAddr));
+
+ pAddBssParams->bssType = pftSessionEntry->bssType;
+ pAddBssParams->operMode = BSS_OPERATIONAL_MODE_STA;
+
+ pAddBssParams->beaconInterval = bssDescription->beaconInterval;
+
+ pAddBssParams->dtimPeriod = pBeaconStruct->tim.dtimPeriod;
+ pAddBssParams->updateBss = updateEntry;
+
+ pAddBssParams->reassocReq = true;
+
+ pAddBssParams->cfParamSet.cfpCount = pBeaconStruct->cfParamSet.cfpCount;
+ pAddBssParams->cfParamSet.cfpPeriod =
+ pBeaconStruct->cfParamSet.cfpPeriod;
+ pAddBssParams->cfParamSet.cfpMaxDuration =
+ pBeaconStruct->cfParamSet.cfpMaxDuration;
+ pAddBssParams->cfParamSet.cfpDurRemaining =
+ pBeaconStruct->cfParamSet.cfpDurRemaining;
+
+ pAddBssParams->rateSet.numRates =
+ pBeaconStruct->supportedRates.numRates;
+ cdf_mem_copy(pAddBssParams->rateSet.rate,
+ pBeaconStruct->supportedRates.rate,
+ pBeaconStruct->supportedRates.numRates);
+
+ pAddBssParams->nwType = bssDescription->nwType;
+
+ pAddBssParams->shortSlotTimeSupported =
+ (uint8_t) pBeaconStruct->capabilityInfo.shortSlotTime;
+ pAddBssParams->llaCoexist =
+ (uint8_t) pftSessionEntry->beaconParams.llaCoexist;
+ pAddBssParams->llbCoexist =
+ (uint8_t) pftSessionEntry->beaconParams.llbCoexist;
+ pAddBssParams->llgCoexist =
+ (uint8_t) pftSessionEntry->beaconParams.llgCoexist;
+ pAddBssParams->ht20Coexist =
+ (uint8_t) pftSessionEntry->beaconParams.ht20Coexist;
+#ifdef WLAN_FEATURE_11W
+ pAddBssParams->rmfEnabled = pftSessionEntry->limRmfEnabled;
+#endif
+
+ /* Use the advertised capabilities from the received beacon/PR */
+ if (IS_DOT11_MODE_HT(pftSessionEntry->dot11mode) &&
+ (pBeaconStruct->HTCaps.present)) {
+ pAddBssParams->htCapable = pBeaconStruct->HTCaps.present;
+ cdf_mem_copy(&pAddBssParams->staContext.capab_info,
+ &pBeaconStruct->capabilityInfo,
+ sizeof(pAddBssParams->staContext.capab_info));
+ cdf_mem_copy(&pAddBssParams->staContext.ht_caps,
+ (uint8_t *) &pBeaconStruct->HTCaps +
+ sizeof(uint8_t),
+ sizeof(pAddBssParams->staContext.ht_caps));
+
+ if (pBeaconStruct->HTInfo.present) {
+ pAddBssParams->htOperMode =
+ (tSirMacHTOperatingMode) pBeaconStruct->HTInfo.
+ opMode;
+ pAddBssParams->dualCTSProtection =
+ (uint8_t) pBeaconStruct->HTInfo.dualCTSProtection;
+
+ chanWidthSupp = lim_get_ht_capability(pMac,
+ eHT_SUPPORTED_CHANNEL_WIDTH_SET,
+ pftSessionEntry);
+ if ((pBeaconStruct->HTCaps.supportedChannelWidthSet) &&
+ (chanWidthSupp)) {
+ pAddBssParams->ch_width = (uint8_t)
+ pBeaconStruct->HTInfo.recommendedTxWidthSet;
+ if (pBeaconStruct->HTInfo.secondaryChannelOffset ==
+ PHY_DOUBLE_CHANNEL_LOW_PRIMARY)
+ pAddBssParams->ch_center_freq_seg0 =
+ bssDescription->channelId + 2;
+ else if (pBeaconStruct->HTInfo.secondaryChannelOffset ==
+ PHY_DOUBLE_CHANNEL_HIGH_PRIMARY)
+ pAddBssParams->ch_center_freq_seg0 =
+ bssDescription->channelId - 2;
+ } else {
+ pAddBssParams->ch_width = CH_WIDTH_20MHZ;
+ pAddBssParams->ch_center_freq_seg0 = 0;
+ }
+ pAddBssParams->llnNonGFCoexist =
+ (uint8_t) pBeaconStruct->HTInfo.nonGFDevicesPresent;
+ pAddBssParams->fLsigTXOPProtectionFullSupport =
+ (uint8_t) pBeaconStruct->HTInfo.
+ lsigTXOPProtectionFullSupport;
+ pAddBssParams->fRIFSMode =
+ pBeaconStruct->HTInfo.rifsMode;
+ }
+ }
+
+ pAddBssParams->currentOperChannel = bssDescription->channelId;
+ pftSessionEntry->htSecondaryChannelOffset =
+ pBeaconStruct->HTInfo.secondaryChannelOffset;
+ sta_ctx = &pAddBssParams->staContext;
+
+#ifdef WLAN_FEATURE_11AC
+ if (pftSessionEntry->vhtCapability &&
+ pftSessionEntry->vhtCapabilityPresentInBeacon) {
+ pAddBssParams->vhtCapable = pBeaconStruct->VHTCaps.present;
+ if (pBeaconStruct->VHTOperation.chanWidth && chanWidthSupp) {
+ pAddBssParams->ch_width =
+ pBeaconStruct->VHTOperation.chanWidth + 1;
+ pAddBssParams->ch_center_freq_seg0 =
+ pBeaconStruct->VHTOperation.chanCenterFreqSeg1;
+ pAddBssParams->ch_center_freq_seg1 =
+ pBeaconStruct->VHTOperation.chanCenterFreqSeg2;
+ }
+ pAddBssParams->staContext.vht_caps =
+ ((pBeaconStruct->VHTCaps.maxMPDULen <<
+ SIR_MAC_VHT_CAP_MAX_MPDU_LEN) |
+ (pBeaconStruct->VHTCaps.supportedChannelWidthSet <<
+ SIR_MAC_VHT_CAP_SUPP_CH_WIDTH_SET) |
+ (pBeaconStruct->VHTCaps.ldpcCodingCap <<
+ SIR_MAC_VHT_CAP_LDPC_CODING_CAP) |
+ (pBeaconStruct->VHTCaps.shortGI80MHz <<
+ SIR_MAC_VHT_CAP_SHORTGI_80MHZ) |
+ (pBeaconStruct->VHTCaps.shortGI160and80plus80MHz <<
+ SIR_MAC_VHT_CAP_SHORTGI_160_80_80MHZ) |
+ (pBeaconStruct->VHTCaps.txSTBC <<
+ SIR_MAC_VHT_CAP_TXSTBC) |
+ (pBeaconStruct->VHTCaps.rxSTBC <<
+ SIR_MAC_VHT_CAP_RXSTBC) |
+ (pBeaconStruct->VHTCaps.suBeamFormerCap <<
+ SIR_MAC_VHT_CAP_SU_BEAMFORMER_CAP) |
+ (pBeaconStruct->VHTCaps.suBeamformeeCap <<
+ SIR_MAC_VHT_CAP_SU_BEAMFORMEE_CAP) |
+ (pBeaconStruct->VHTCaps.csnofBeamformerAntSup <<
+ SIR_MAC_VHT_CAP_CSN_BEAMORMER_ANT_SUP) |
+ (pBeaconStruct->VHTCaps.numSoundingDim <<
+ SIR_MAC_VHT_CAP_NUM_SOUNDING_DIM) |
+ (pBeaconStruct->VHTCaps.muBeamformerCap <<
+ SIR_MAC_VHT_CAP_NUM_BEAM_FORMER_CAP) |
+ (pBeaconStruct->VHTCaps.muBeamformeeCap <<
+ SIR_MAC_VHT_CAP_NUM_BEAM_FORMEE_CAP) |
+ (pBeaconStruct->VHTCaps.vhtTXOPPS <<
+ SIR_MAC_VHT_CAP_TXOPPS) |
+ (pBeaconStruct->VHTCaps.htcVHTCap <<
+ SIR_MAC_VHT_CAP_HTC_CAP) |
+ (pBeaconStruct->VHTCaps.maxAMPDULenExp <<
+ SIR_MAC_VHT_CAP_MAX_AMDU_LEN_EXPO) |
+ (pBeaconStruct->VHTCaps.vhtLinkAdaptCap <<
+ SIR_MAC_VHT_CAP_LINK_ADAPT_CAP) |
+ (pBeaconStruct->VHTCaps.rxAntPattern <<
+ SIR_MAC_VHT_CAP_RX_ANTENNA_PATTERN) |
+ (pBeaconStruct->VHTCaps.txAntPattern <<
+ SIR_MAC_VHT_CAP_TX_ANTENNA_PATTERN) |
+ (pBeaconStruct->VHTCaps.reserved1 <<
+ SIR_MAC_VHT_CAP_RESERVED2));
+ } else {
+ pAddBssParams->vhtCapable = 0;
+ }
+#endif
+
+#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG
+ lim_log(pMac, LOG1, FL("SIR_HAL_ADD_BSS_REQ with channel = %d..."),
+ pAddBssParams->currentOperChannel);
+#endif
+
+ /* Populate the STA-related parameters here */
+ /* Note that the STA here refers to the AP */
+ {
+ pAddBssParams->staContext.staType = STA_ENTRY_OTHER;
+
+ cdf_mem_copy(pAddBssParams->staContext.bssId,
+ bssDescription->bssId, sizeof(tSirMacAddr));
+ pAddBssParams->staContext.listenInterval =
+ bssDescription->beaconInterval;
+
+ pAddBssParams->staContext.assocId = 0;
+ pAddBssParams->staContext.uAPSD = 0;
+ pAddBssParams->staContext.maxSPLen = 0;
+ pAddBssParams->staContext.shortPreambleSupported =
+ (uint8_t) pBeaconStruct->capabilityInfo.shortPreamble;
+ pAddBssParams->staContext.updateSta = updateEntry;
+ pAddBssParams->staContext.encryptType =
+ pftSessionEntry->encryptType;
+#ifdef WLAN_FEATURE_11W
+ pAddBssParams->staContext.rmfEnabled =
+ pftSessionEntry->limRmfEnabled;
+#endif
+
+ if (IS_DOT11_MODE_HT(pftSessionEntry->dot11mode) &&
+ (pBeaconStruct->HTCaps.present)) {
+ pAddBssParams->staContext.us32MaxAmpduDuration = 0;
+ pAddBssParams->staContext.htCapable = 1;
+ pAddBssParams->staContext.greenFieldCapable =
+ (uint8_t) pBeaconStruct->HTCaps.greenField;
+ pAddBssParams->staContext.lsigTxopProtection =
+ (uint8_t) pBeaconStruct->HTCaps.lsigTXOPProtection;
+ if ((pBeaconStruct->HTCaps.supportedChannelWidthSet) &&
+ (chanWidthSupp)) {
+ pAddBssParams->staContext.ch_width = (uint8_t)
+ pBeaconStruct->HTInfo.recommendedTxWidthSet;
+ } else {
+ pAddBssParams->staContext.ch_width =
+ CH_WIDTH_20MHZ;
+ }
+ if (pftSessionEntry->vhtCapability &&
+ IS_BSS_VHT_CAPABLE(pBeaconStruct->VHTCaps)) {
+ pAddBssParams->staContext.vhtCapable = 1;
+ if ((pBeaconStruct->VHTCaps.suBeamFormerCap ||
+ pBeaconStruct->VHTCaps.muBeamformerCap) &&
+ pftSessionEntry->txBFIniFeatureEnabled)
+ sta_ctx->vhtTxBFCapable
+ = 1;
+ if (pBeaconStruct->VHTCaps.suBeamformeeCap &&
+ pftSessionEntry->enable_su_tx_bformer)
+ sta_ctx->enable_su_tx_bformer = 1;
+ }
+ if ((pBeaconStruct->HTCaps.supportedChannelWidthSet) &&
+ (chanWidthSupp)) {
+ sta_ctx->ch_width = (uint8_t)
+ pBeaconStruct->HTInfo.recommendedTxWidthSet;
+ if (pAddBssParams->staContext.vhtCapable &&
+ pBeaconStruct->VHTOperation.chanWidth)
+ sta_ctx->ch_width =
+ pBeaconStruct->VHTOperation.chanWidth
+ + 1;
+ } else {
+ pAddBssParams->staContext.ch_width =
+ CH_WIDTH_20MHZ;
+ }
+ pAddBssParams->staContext.mimoPS =
+ (tSirMacHTMIMOPowerSaveState) pBeaconStruct->HTCaps.
+ mimoPowerSave;
+ pAddBssParams->staContext.maxAmsduSize =
+ (uint8_t) pBeaconStruct->HTCaps.maximalAMSDUsize;
+ pAddBssParams->staContext.maxAmpduDensity =
+ pBeaconStruct->HTCaps.mpduDensity;
+ pAddBssParams->staContext.fDsssCckMode40Mhz =
+ (uint8_t) pBeaconStruct->HTCaps.dsssCckMode40MHz;
+ pAddBssParams->staContext.fShortGI20Mhz =
+ (uint8_t) pBeaconStruct->HTCaps.shortGI20MHz;
+ pAddBssParams->staContext.fShortGI40Mhz =
+ (uint8_t) pBeaconStruct->HTCaps.shortGI40MHz;
+ pAddBssParams->staContext.maxAmpduSize =
+ pBeaconStruct->HTCaps.maxRxAMPDUFactor;
+
+ if (pBeaconStruct->HTInfo.present)
+ pAddBssParams->staContext.rifsMode =
+ pBeaconStruct->HTInfo.rifsMode;
+ }
+
+ if ((pftSessionEntry->limWmeEnabled
+ && pBeaconStruct->wmeEdcaPresent)
+ || (pftSessionEntry->limQosEnabled
+ && pBeaconStruct->edcaPresent))
+ pAddBssParams->staContext.wmmEnabled = 1;
+ else
+ pAddBssParams->staContext.wmmEnabled = 0;
+
+ pAddBssParams->staContext.wpa_rsn = pBeaconStruct->rsnPresent;
+ /* For OSEN Connection AP does not advertise RSN or WPA IE
+ * so from the IEs we get from supplicant we get this info
+ * so for FW to transmit EAPOL message 4 we shall set
+ * wpa_rsn
+ */
+ pAddBssParams->staContext.wpa_rsn |=
+ (pBeaconStruct->wpaPresent << 1);
+ if ((!pAddBssParams->staContext.wpa_rsn)
+ && (pftSessionEntry->isOSENConnection))
+ pAddBssParams->staContext.wpa_rsn = 1;
+ /* Update the rates */
+#ifdef WLAN_FEATURE_11AC
+ lim_populate_peer_rate_set(pMac,
+ &pAddBssParams->staContext.
+ supportedRates,
+ pBeaconStruct->HTCaps.supportedMCSSet,
+ false, pftSessionEntry,
+ &pBeaconStruct->VHTCaps);
+#else
+ lim_populate_peer_rate_set(pMac,
+ &pAddBssParams->staContext.
+ supportedRates,
+ beaconStruct.HTCaps.supportedMCSSet,
+ false, pftSessionEntry);
+#endif
+ if (pftSessionEntry->htCapability) {
+ pAddBssParams->staContext.supportedRates.opRateMode =
+ eSTA_11n;
+ if (pftSessionEntry->vhtCapability)
+ pAddBssParams->staContext.supportedRates.
+ opRateMode = eSTA_11ac;
+ } else {
+ if (pftSessionEntry->limRFBand == SIR_BAND_5_GHZ) {
+ pAddBssParams->staContext.supportedRates.
+ opRateMode = eSTA_11a;
+ } else {
+ pAddBssParams->staContext.supportedRates.
+ opRateMode = eSTA_11bg;
+ }
+ }
+ }
+
+#if defined WLAN_FEATURE_VOWIFI
+ pAddBssParams->maxTxPower = pftSessionEntry->maxTxPower;
+#endif
+
+#ifdef WLAN_FEATURE_11W
+ if (pftSessionEntry->limRmfEnabled) {
+ pAddBssParams->rmfEnabled = 1;
+ pAddBssParams->staContext.rmfEnabled = 1;
+ }
+#endif
+
+ pAddBssParams->status = CDF_STATUS_SUCCESS;
+ pAddBssParams->respReqd = true;
+
+ pAddBssParams->staContext.sessionId = pftSessionEntry->peSessionId;
+ pAddBssParams->staContext.smesessionId = pftSessionEntry->smeSessionId;
+ pAddBssParams->sessionId = pftSessionEntry->peSessionId;
+
+ /* Set a new state for MLME */
+
+ pftSessionEntry->limMlmState = eLIM_MLM_WT_ADD_BSS_RSP_FT_REASSOC_STATE;
+ MTRACE(mac_trace
+ (pMac, TRACE_CODE_MLM_STATE, pftSessionEntry->peSessionId,
+ eLIM_MLM_WT_ADD_BSS_RSP_FT_REASSOC_STATE));
+ pAddBssParams->halPersona = (uint8_t) pftSessionEntry->pePersona;
+
+ pftSessionEntry->ftPEContext.pAddBssReq = pAddBssParams;
+
+#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG
+ lim_log(pMac, LOG1, FL("Saving SIR_HAL_ADD_BSS_REQ for pre-auth ap..."));
+#endif
+
+ cdf_mem_free(pBeaconStruct);
+ return 0;
+}
+
+/*------------------------------------------------------------------
+ *
+ * Setup the new session for the pre-auth AP.
+ * Return the newly created session entry.
+ *
+ *------------------------------------------------------------------*/
+void lim_fill_ft_session(tpAniSirGlobal pMac,
+ tpSirBssDescription pbssDescription,
+ tpPESession pftSessionEntry, tpPESession psessionEntry)
+{
+ uint8_t currentBssUapsd;
+ tPowerdBm localPowerConstraint;
+ tPowerdBm regMax;
+ tSchBeaconStruct *pBeaconStruct;
+ uint32_t selfDot11Mode;
+ ePhyChanBondState cbEnabledMode;
+
+ pBeaconStruct = cdf_mem_malloc(sizeof(tSchBeaconStruct));
+ if (NULL == pBeaconStruct) {
+#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG
+ lim_log(pMac, LOGE,
+ FL
+ ("Unable to allocate memory for creating lim_fill_ft_session"));
+#endif
+ return;
+ }
+
+ /* Retrieve the session that has already been created and update the entry */
+#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG || defined FEATURE_WLAN_ESE || defined(FEATURE_WLAN_LFR)
+ lim_print_mac_addr(pMac, pbssDescription->bssId, LOG1);
+#endif
+ pftSessionEntry->limWmeEnabled = psessionEntry->limWmeEnabled;
+ pftSessionEntry->limQosEnabled = psessionEntry->limQosEnabled;
+ pftSessionEntry->limWsmEnabled = psessionEntry->limWsmEnabled;
+ pftSessionEntry->lim11hEnable = psessionEntry->lim11hEnable;
+ pftSessionEntry->isOSENConnection = psessionEntry->isOSENConnection;
+
+ /* Fields to be filled later */
+ pftSessionEntry->pLimJoinReq = NULL;
+ pftSessionEntry->smeSessionId = psessionEntry->smeSessionId;
+ pftSessionEntry->transactionId = 0;
+
+ lim_extract_ap_capabilities(pMac, (uint8_t *) pbssDescription->ieFields,
+ lim_get_ielen_from_bss_description(pbssDescription),
+ pBeaconStruct);
+
+ pftSessionEntry->rateSet.numRates =
+ pBeaconStruct->supportedRates.numRates;
+ cdf_mem_copy(pftSessionEntry->rateSet.rate,
+ pBeaconStruct->supportedRates.rate,
+ pBeaconStruct->supportedRates.numRates);
+
+ pftSessionEntry->extRateSet.numRates =
+ pBeaconStruct->extendedRates.numRates;
+ cdf_mem_copy(pftSessionEntry->extRateSet.rate,
+ pBeaconStruct->extendedRates.rate,
+ pftSessionEntry->extRateSet.numRates);
+
+ pftSessionEntry->ssId.length = pBeaconStruct->ssId.length;
+ cdf_mem_copy(pftSessionEntry->ssId.ssId, pBeaconStruct->ssId.ssId,
+ pftSessionEntry->ssId.length);
+
+ wlan_cfg_get_int(pMac, WNI_CFG_DOT11_MODE, &selfDot11Mode);
+ lim_log(pMac, LOG1, FL("selfDot11Mode %d"), selfDot11Mode);
+ pftSessionEntry->dot11mode = selfDot11Mode;
+ pftSessionEntry->vhtCapability =
+ (IS_DOT11_MODE_VHT(pftSessionEntry->dot11mode)
+ && IS_BSS_VHT_CAPABLE(pBeaconStruct->VHTCaps));
+ pftSessionEntry->htCapability =
+ (IS_DOT11_MODE_HT(pftSessionEntry->dot11mode)
+ && pBeaconStruct->HTCaps.present);
+
+ /* Copy The channel Id to the session Table */
+ pftSessionEntry->limReassocChannelId = pbssDescription->channelId;
+ pftSessionEntry->currentOperChannel = pbssDescription->channelId;
+
+ pftSessionEntry->limRFBand = lim_get_rf_band(
+ pftSessionEntry->currentOperChannel);
+
+ if (pftSessionEntry->limRFBand == SIR_BAND_2_4_GHZ) {
+ cbEnabledMode = pMac->roam.configParam.channelBondingMode24GHz;
+ } else {
+ cbEnabledMode = pMac->roam.configParam.channelBondingMode5GHz;
+ }
+ pftSessionEntry->htSupportedChannelWidthSet =
+ (pBeaconStruct->HTInfo.present) ?
+ (cbEnabledMode && pBeaconStruct->HTInfo.recommendedTxWidthSet) : 0;
+ pftSessionEntry->htRecommendedTxWidthSet =
+ pftSessionEntry->htSupportedChannelWidthSet;
+
+
+#ifdef WLAN_FEATURE_11AC
+ if (IS_BSS_VHT_CAPABLE(pBeaconStruct->VHTCaps) &&
+ pBeaconStruct->VHTOperation.present &&
+ pftSessionEntry->vhtCapability) {
+ pftSessionEntry->vhtCapabilityPresentInBeacon = 1;
+ } else {
+ pftSessionEntry->vhtCapabilityPresentInBeacon = 0;
+ }
+#endif
+ if (pftSessionEntry->htRecommendedTxWidthSet) {
+ pftSessionEntry->ch_width = CH_WIDTH_40MHZ;
+ if (pftSessionEntry->vhtCapabilityPresentInBeacon &&
+ pBeaconStruct->VHTOperation.chanWidth) {
+ pftSessionEntry->ch_width =
+ pBeaconStruct->VHTOperation.chanWidth + 1;
+ pftSessionEntry->ch_center_freq_seg0 =
+ pBeaconStruct->VHTOperation.chanCenterFreqSeg1;
+ pftSessionEntry->ch_center_freq_seg1 =
+ pBeaconStruct->VHTOperation.chanCenterFreqSeg2;
+ } else {
+ if (pBeaconStruct->HTInfo.secondaryChannelOffset ==
+ PHY_DOUBLE_CHANNEL_LOW_PRIMARY)
+ pftSessionEntry->ch_center_freq_seg0 =
+ pbssDescription->channelId + 2;
+ else if (pBeaconStruct->HTInfo.secondaryChannelOffset ==
+ PHY_DOUBLE_CHANNEL_HIGH_PRIMARY)
+ pftSessionEntry->ch_center_freq_seg0 =
+ pbssDescription->channelId - 2;
+ else
+ lim_log(pMac, LOGE, FL("Invalid sec ch offset"));
+ }
+ } else {
+ pftSessionEntry->ch_width = CH_WIDTH_20MHZ;
+ pftSessionEntry->ch_center_freq_seg0 = 0;
+ pftSessionEntry->ch_center_freq_seg1 = 0;
+ }
+
+ sir_copy_mac_addr(pftSessionEntry->selfMacAddr,
+ psessionEntry->selfMacAddr);
+ sir_copy_mac_addr(pftSessionEntry->limReAssocbssId,
+ pbssDescription->bssId);
+ sir_copy_mac_addr(pftSessionEntry->prev_ap_bssid, psessionEntry->bssId);
+#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG || defined FEATURE_WLAN_ESE || defined(FEATURE_WLAN_LFR)
+ lim_print_mac_addr(pMac, pftSessionEntry->limReAssocbssId, LOG1);
+#endif
+
+ /* Store beaconInterval */
+ pftSessionEntry->beaconParams.beaconInterval =
+ pbssDescription->beaconInterval;
+ pftSessionEntry->bssType = psessionEntry->bssType;
+
+ pftSessionEntry->statypeForBss = STA_ENTRY_PEER;
+ pftSessionEntry->nwType = pbssDescription->nwType;
+
+
+ if (pftSessionEntry->bssType == eSIR_INFRASTRUCTURE_MODE) {
+ pftSessionEntry->limSystemRole = eLIM_STA_ROLE;
+ } else if (pftSessionEntry->bssType == eSIR_BTAMP_AP_MODE) {
+ pftSessionEntry->limSystemRole = eLIM_BT_AMP_STA_ROLE;
+ } else {
+ /* Throw an error and return and make sure to delete the session. */
+ lim_log(pMac, LOGE, FL("Invalid bss type"));
+ }
+
+ pftSessionEntry->limCurrentBssCaps = pbssDescription->capabilityInfo;
+ pftSessionEntry->limReassocBssCaps = pbssDescription->capabilityInfo;
+ if (pMac->roam.configParam.shortSlotTime &&
+ SIR_MAC_GET_SHORT_SLOT_TIME(pftSessionEntry->limReassocBssCaps)) {
+ pftSessionEntry->shortSlotTimeSupported = true;
+ }
+
+ regMax = cfg_get_regulatory_max_transmit_power(pMac,
+ pftSessionEntry->
+ currentOperChannel);
+ localPowerConstraint = regMax;
+ lim_extract_ap_capability(pMac, (uint8_t *) pbssDescription->ieFields,
+ lim_get_ielen_from_bss_description(pbssDescription),
+ &pftSessionEntry->limCurrentBssQosCaps,
+ &pftSessionEntry->limCurrentBssPropCap, ¤tBssUapsd,
+ &localPowerConstraint, pftSessionEntry);
+
+ pftSessionEntry->limReassocBssQosCaps =
+ pftSessionEntry->limCurrentBssQosCaps;
+ pftSessionEntry->limReassocBssPropCap =
+ pftSessionEntry->limCurrentBssPropCap;
+
+#ifdef WLAN_FEATURE_VOWIFI_11R
+ pftSessionEntry->is11Rconnection = psessionEntry->is11Rconnection;
+#endif
+#ifdef FEATURE_WLAN_ESE
+ pftSessionEntry->isESEconnection = psessionEntry->isESEconnection;
+ pftSessionEntry->is_ese_version_ie_present =
+ pBeaconStruct->is_ese_ver_ie_present;
+#endif
+#if defined WLAN_FEATURE_VOWIFI_11R || defined FEATURE_WLAN_ESE || defined(FEATURE_WLAN_LFR)
+ pftSessionEntry->isFastTransitionEnabled =
+ psessionEntry->isFastTransitionEnabled;
+#endif
+
+#ifdef FEATURE_WLAN_LFR
+ pftSessionEntry->isFastRoamIniFeatureEnabled =
+ psessionEntry->isFastRoamIniFeatureEnabled;
+#endif
+
+#ifdef FEATURE_WLAN_ESE
+ pftSessionEntry->maxTxPower =
+ lim_get_max_tx_power(regMax, localPowerConstraint,
+ pMac->roam.configParam.nTxPowerCap);
+#else
+ pftSessionEntry->maxTxPower = CDF_MIN(regMax, (localPowerConstraint));
+#endif
+
+#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG
+ lim_log(pMac, LOG1,
+ FL
+ ("Reg max = %d, local power = %d, ini tx power = %d, max tx = %d"),
+ regMax, localPowerConstraint, pMac->roam.configParam.nTxPowerCap,
+ pftSessionEntry->maxTxPower);
+#endif
+
+ pftSessionEntry->limPrevSmeState = pftSessionEntry->limSmeState;
+ pftSessionEntry->limSmeState = eLIM_SME_WT_REASSOC_STATE;
+ MTRACE(mac_trace
+ (pMac, TRACE_CODE_SME_STATE, pftSessionEntry->peSessionId,
+ pftSessionEntry->limSmeState));
+
+ pftSessionEntry->encryptType = psessionEntry->encryptType;
+#ifdef WLAN_FEATURE_11W
+ pftSessionEntry->limRmfEnabled = psessionEntry->limRmfEnabled;
+#endif
+
+ cdf_mem_free(pBeaconStruct);
+}
+
+/*------------------------------------------------------------------
+ *
+ * Setup the session and the add bss req for the pre-auth AP.
+ *
+ *------------------------------------------------------------------*/
+tSirRetStatus lim_ft_setup_auth_session(tpAniSirGlobal pMac,
+ tpPESession psessionEntry)
+{
+ tpPESession pftSessionEntry = NULL;
+ uint8_t sessionId = 0;
+
+ pftSessionEntry =
+ pe_find_session_by_bssid(pMac, psessionEntry->limReAssocbssId,
+ &sessionId);
+ if (pftSessionEntry == NULL) {
+ PELOGE(lim_log(pMac, LOGE,
+ FL
+ ("Unable to find session for the following bssid"));
+ )
+ lim_print_mac_addr(pMac, psessionEntry->limReAssocbssId, LOGE);
+ return eSIR_FAILURE;
+ }
+
+ /* Nothing to be done if the session is not in STA mode */
+ if (!LIM_IS_STA_ROLE(psessionEntry)) {
+#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG
+ PELOGE(lim_log
+ (pMac, LOGE, FL("psessionEntry is not in STA mode"));
+ )
+#endif
+ return eSIR_FAILURE;
+ }
+
+ if (psessionEntry->ftPEContext.pFTPreAuthReq &&
+ psessionEntry->ftPEContext.pFTPreAuthReq->pbssDescription) {
+ lim_fill_ft_session(pMac,
+ psessionEntry->ftPEContext.pFTPreAuthReq->
+ pbssDescription, pftSessionEntry,
+ psessionEntry);
+
+ lim_ft_prepare_add_bss_req(pMac, false, pftSessionEntry,
+ psessionEntry->ftPEContext.pFTPreAuthReq->
+ pbssDescription);
+ }
+
+ return eSIR_SUCCESS;
+}
+
+/*------------------------------------------------------------------
+ * Resume Link Call Back
+ *------------------------------------------------------------------*/
+void lim_ft_process_pre_auth_result(tpAniSirGlobal pMac, CDF_STATUS status,
+ uint32_t *data)
+{
+ tpPESession psessionEntry = (tpPESession) data;
+
+ if (NULL == psessionEntry ||
+ NULL == psessionEntry->ftPEContext.pFTPreAuthReq)
+ return;
+
+ /* Nothing to be done if the session is not in STA mode */
+ if (!LIM_IS_STA_ROLE(psessionEntry)) {
+#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG
+ PELOGE(lim_log
+ (pMac, LOGE, FL("psessionEntry is not in STA mode"));
+ )
+#endif
+ return;
+ }
+
+ if (psessionEntry->ftPEContext.ftPreAuthStatus == eSIR_SUCCESS) {
+ psessionEntry->ftPEContext.ftPreAuthStatus =
+ lim_ft_setup_auth_session(pMac, psessionEntry);
+ }
+ /* Post the FT Pre Auth Response to SME */
+ lim_post_ft_pre_auth_rsp(pMac, psessionEntry->ftPEContext.ftPreAuthStatus,
+ psessionEntry->ftPEContext.saved_auth_rsp,
+ psessionEntry->ftPEContext.saved_auth_rsp_length,
+ psessionEntry);
+}
+
+/*------------------------------------------------------------------
+ * Resume Link Call Back
+ *------------------------------------------------------------------*/
+void lim_perform_post_ft_pre_auth_and_channel_change(tpAniSirGlobal pMac,
+ CDF_STATUS status,
+ uint32_t *data,
+ tpPESession psessionEntry)
+{
+ /* Set the resume channel to Any valid channel (invalid)
+ * This will instruct HAL to set it to any previous valid channel.
+ */
+ pe_set_resume_channel(pMac, 0, 0);
+ lim_ft_process_pre_auth_result(pMac, CDF_STATUS_SUCCESS,
+ (uint32_t *) psessionEntry);
+}
+
+/*
+ * lim_post_ft_pre_auth_rsp() - post ft pre auth response to SME.
+ *
+ * @mac_ctx: global mac ctx
+ * @status: status code to post in auth rsp
+ * @auth_rsp: pointer to auth rsp FT ie
+ * @auth_rsp_length: len of the IE field
+ * @session: pe session
+ *
+ * post pre auth response to SME.
+ *
+ * Return: void
+ */
+void lim_post_ft_pre_auth_rsp(tpAniSirGlobal mac_ctx,
+ tSirRetStatus status,
+ uint8_t *auth_rsp,
+ uint16_t auth_rsp_length,
+ tpPESession session)
+{
+ tpSirFTPreAuthRsp ft_pre_auth_rsp;
+ tSirMsgQ mmh_msg;
+ uint16_t rsp_len = sizeof(tSirFTPreAuthRsp);
+
+ ft_pre_auth_rsp = (tpSirFTPreAuthRsp) cdf_mem_malloc(rsp_len);
+ if (NULL == ft_pre_auth_rsp) {
+ lim_log(mac_ctx, LOGE, "Failed to allocate memory");
+ CDF_ASSERT(ft_pre_auth_rsp != NULL);
+ return;
+ }
+ cdf_mem_zero(ft_pre_auth_rsp, rsp_len);
+
+#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG
+ lim_log(mac_ctx, LOG1, FL("Auth Rsp = %p"), ft_pre_auth_rsp);
+#endif
+ if (session) {
+ /* Nothing to be done if the session is not in STA mode */
+ if (!LIM_IS_STA_ROLE(session)) {
+#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG
+ lim_log(mac_ctx, LOGE,
+ FL("session is not in STA mode"));
+#endif
+ cdf_mem_free(ft_pre_auth_rsp);
+ return;
+ }
+ ft_pre_auth_rsp->smeSessionId = session->smeSessionId;
+ /* The bssid of the AP we are sending Auth1 to. */
+ if (session->ftPEContext.pFTPreAuthReq)
+ sir_copy_mac_addr(ft_pre_auth_rsp->preAuthbssId,
+ session->ftPEContext.pFTPreAuthReq->preAuthbssId);
+ }
+
+ ft_pre_auth_rsp->messageType = eWNI_SME_FT_PRE_AUTH_RSP;
+ ft_pre_auth_rsp->length = (uint16_t) rsp_len;
+ ft_pre_auth_rsp->status = status;
+
+ /* Attach the auth response now back to SME */
+ ft_pre_auth_rsp->ft_ies_length = 0;
+ if ((auth_rsp != NULL) && (auth_rsp_length < MAX_FTIE_SIZE)) {
+ /* Only 11r assoc has FT IEs */
+ cdf_mem_copy(ft_pre_auth_rsp->ft_ies,
+ auth_rsp, auth_rsp_length);
+ ft_pre_auth_rsp->ft_ies_length = auth_rsp_length;
+ }
+
+ if (status != eSIR_SUCCESS) {
+ /*
+ * Ensure that on Pre-Auth failure the cached Pre-Auth Req and
+ * other allocated memory is freed up before returning.
+ */
+ lim_log(mac_ctx, LOG1, "Pre-Auth Failed, Cleanup!");
+ lim_ft_cleanup(mac_ctx, session);
+ }
+
+ mmh_msg.type = ft_pre_auth_rsp->messageType;
+ mmh_msg.bodyptr = ft_pre_auth_rsp;
+ mmh_msg.bodyval = 0;
+
+#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG
+ lim_log(mac_ctx, LOG1, FL("Posted Auth Rsp to SME with status of 0x%x"),
+ status);
+#endif
+#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */
+ if (status == eSIR_SUCCESS)
+ lim_diag_event_report(mac_ctx, WLAN_PE_DIAG_PREAUTH_DONE,
+ session, status, 0);
+#endif
+ lim_sys_process_mmh_msg_api(mac_ctx, &mmh_msg, ePROT);
+}
+
+/*------------------------------------------------------------------
+ *
+ * Send the FT Pre Auth Response to SME whenever we have a status
+ * ready to be sent to SME
+ *
+ * SME will be the one to send it up to the supplicant to receive
+ * FTIEs which will be required for Reassoc Req.
+ *
+ *------------------------------------------------------------------*/
+void lim_handle_ft_pre_auth_rsp(tpAniSirGlobal pMac, tSirRetStatus status,
+ uint8_t *auth_rsp, uint16_t auth_rsp_length,
+ tpPESession psessionEntry)
+{
+ tpPESession pftSessionEntry = NULL;
+ uint8_t sessionId = 0;
+ tpSirBssDescription pbssDescription = NULL;
+#ifdef FEATURE_WLAN_DIAG_SUPPORT
+ lim_diag_event_report(pMac, WLAN_PE_DIAG_PRE_AUTH_RSP_EVENT,
+ psessionEntry, (uint16_t) status, 0);
+#endif
+
+ /* Nothing to be done if the session is not in STA mode */
+ if (!LIM_IS_STA_ROLE(psessionEntry)) {
+#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG
+ PELOGE(lim_log
+ (pMac, LOGE, FL("psessionEntry is not in STA mode"));
+ )
+#endif
+ return;
+ }
+
+ /* Save the status of pre-auth */
+ psessionEntry->ftPEContext.ftPreAuthStatus = status;
+
+ /* Save the auth rsp, so we can send it to
+ * SME once we resume link
+ */
+ psessionEntry->ftPEContext.saved_auth_rsp_length = 0;
+ if ((auth_rsp != NULL) && (auth_rsp_length < MAX_FTIE_SIZE)) {
+ cdf_mem_copy(psessionEntry->ftPEContext.saved_auth_rsp,
+ auth_rsp, auth_rsp_length);
+ psessionEntry->ftPEContext.saved_auth_rsp_length =
+ auth_rsp_length;
+ }
+
+ if (!psessionEntry->ftPEContext.pFTPreAuthReq ||
+ !psessionEntry->ftPEContext.pFTPreAuthReq->pbssDescription) {
+ lim_log(pMac, LOGE,
+ FL("pFTPreAuthReq or pbssDescription is NULL"));
+ return;
+ }
+
+ /* Create FT session for the re-association at this point */
+ if (psessionEntry->ftPEContext.ftPreAuthStatus == eSIR_SUCCESS) {
+ pbssDescription =
+ psessionEntry->ftPEContext.pFTPreAuthReq->pbssDescription;
+ lim_print_mac_addr(pMac, pbssDescription->bssId, LOG1);
+ if ((pftSessionEntry =
+ pe_create_session(pMac, pbssDescription->bssId,
+ &sessionId, pMac->lim.maxStation,
+ psessionEntry->bssType)) == NULL) {
+ lim_log(pMac, LOGE, FL(
+ "Session not created for pre-auth 11R AP"));
+ status = eSIR_FAILURE;
+ psessionEntry->ftPEContext.ftPreAuthStatus = status;
+ goto send_rsp;
+ }
+ pftSessionEntry->peSessionId = sessionId;
+ pftSessionEntry->smeSessionId = psessionEntry->smeSessionId;
+ sir_copy_mac_addr(pftSessionEntry->selfMacAddr,
+ psessionEntry->selfMacAddr);
+ sir_copy_mac_addr(pftSessionEntry->limReAssocbssId,
+ pbssDescription->bssId);
+ pftSessionEntry->bssType = psessionEntry->bssType;
+
+ if (pftSessionEntry->bssType == eSIR_INFRASTRUCTURE_MODE) {
+ pftSessionEntry->limSystemRole = eLIM_STA_ROLE;
+ } else if (pftSessionEntry->bssType == eSIR_BTAMP_AP_MODE) {
+ pftSessionEntry->limSystemRole = eLIM_BT_AMP_STA_ROLE;
+ } else {
+ lim_log(pMac, LOGE, FL("Invalid bss type"));
+ }
+ pftSessionEntry->limPrevSmeState = pftSessionEntry->limSmeState;
+ cdf_mem_copy(&(pftSessionEntry->htConfig),
+ &(psessionEntry->htConfig),
+ sizeof(psessionEntry->htConfig));
+ pftSessionEntry->limSmeState = eLIM_SME_WT_REASSOC_STATE;
+
+ PELOGE(lim_log
+ (pMac, LOG1, "%s:created session (%p) with id = %d",
+ __func__, pftSessionEntry,
+ pftSessionEntry->peSessionId);
+ )
+
+ /* Update the ReAssoc BSSID of the current session */
+ sir_copy_mac_addr(psessionEntry->limReAssocbssId,
+ pbssDescription->bssId);
+ lim_print_mac_addr(pMac, psessionEntry->limReAssocbssId, LOG1);
+ }
+send_rsp:
+ if (psessionEntry->currentOperChannel !=
+ psessionEntry->ftPEContext.pFTPreAuthReq->preAuthchannelNum) {
+ /* Need to move to the original AP channel */
+ lim_change_channel_with_callback(pMac,
+ psessionEntry->currentOperChannel,
+ lim_perform_post_ft_pre_auth_and_channel_change,
+ NULL, psessionEntry);
+ } else {
+#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG
+ PELOGE(lim_log(pMac, LOG1,
+ "Pre auth on same channel as connected AP channel %d",
+ psessionEntry->ftPEContext.pFTPreAuthReq->
+ preAuthchannelNum);
+ )
+#endif
+ lim_ft_process_pre_auth_result(pMac, status,
+ (uint32_t *) psessionEntry);
+ }
+}
+
+/*------------------------------------------------------------------
+ *
+ * This function handles the 11R Reassoc Req from SME
+ *
+ *------------------------------------------------------------------*/
+void lim_process_mlm_ft_reassoc_req(tpAniSirGlobal pMac, uint32_t *pMsgBuf,
+ tpPESession psessionEntry)
+{
+ uint8_t smeSessionId = 0;
+ uint16_t transactionId = 0;
+ uint8_t chanNum = 0;
+ tLimMlmReassocReq *pMlmReassocReq;
+ uint16_t caps;
+ uint32_t val;
+ tSirMsgQ msgQ;
+ tSirRetStatus retCode;
+ uint32_t teleBcnEn = 0;
+
+ chanNum = psessionEntry->currentOperChannel;
+ lim_get_session_info(pMac, (uint8_t *) pMsgBuf, &smeSessionId,
+ &transactionId);
+ psessionEntry->smeSessionId = smeSessionId;
+ psessionEntry->transactionId = transactionId;
+
+#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */
+ lim_diag_event_report(pMac, WLAN_PE_DIAG_REASSOCIATING, psessionEntry, 0,
+ 0);
+#endif
+
+ /* Nothing to be done if the session is not in STA mode */
+ if (!LIM_IS_STA_ROLE(psessionEntry)) {
+#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG
+ PELOGE(lim_log
+ (pMac, LOGE, FL("psessionEntry is not in STA mode"));
+ )
+#endif
+ return;
+ }
+
+ if (NULL == psessionEntry->ftPEContext.pAddBssReq) {
+ lim_log(pMac, LOGE, FL("pAddBssReq is NULL"));
+ return;
+ }
+ pMlmReassocReq = cdf_mem_malloc(sizeof(tLimMlmReassocReq));
+ if (NULL == pMlmReassocReq) {
+ lim_log(pMac, LOGE,
+ FL("call to AllocateMemory failed for mlmReassocReq"));
+ return;
+ }
+
+ cdf_mem_copy(pMlmReassocReq->peerMacAddr,
+ psessionEntry->bssId, sizeof(tSirMacAddr));
+
+ if (wlan_cfg_get_int(pMac, WNI_CFG_REASSOCIATION_FAILURE_TIMEOUT,
+ (uint32_t *) &pMlmReassocReq->reassocFailureTimeout)
+ != eSIR_SUCCESS) {
+ /**
+ * Could not get ReassocFailureTimeout value
+ * from CFG. Log error.
+ */
+ lim_log(pMac, LOGE,
+ FL("could not retrieve ReassocFailureTimeout value"));
+ cdf_mem_free(pMlmReassocReq);
+ return;
+ }
+
+ if (cfg_get_capability_info(pMac, &caps, psessionEntry) != eSIR_SUCCESS) {
+ /**
+ * Could not get Capabilities value
+ * from CFG. Log error.
+ */
+ lim_log(pMac, LOGE, FL("could not retrieve Capabilities value"));
+ cdf_mem_free(pMlmReassocReq);
+ return;
+ }
+ pMlmReassocReq->capabilityInfo = caps;
+
+ /* Update PE sessionId */
+ pMlmReassocReq->sessionId = psessionEntry->peSessionId;
+
+ /* If telescopic beaconing is enabled, set listen interval
+ to WNI_CFG_TELE_BCN_MAX_LI
+ */
+ if (wlan_cfg_get_int(pMac, WNI_CFG_TELE_BCN_WAKEUP_EN, &teleBcnEn) !=
+ eSIR_SUCCESS) {
+ lim_log(pMac, LOGP,
+ FL("Couldn't get WNI_CFG_TELE_BCN_WAKEUP_EN"));
+ cdf_mem_free(pMlmReassocReq);
+ return;
+ }
+
+ if (teleBcnEn) {
+ if (wlan_cfg_get_int(pMac, WNI_CFG_TELE_BCN_MAX_LI, &val) !=
+ eSIR_SUCCESS) {
+ /**
+ * Could not get ListenInterval value
+ * from CFG. Log error.
+ */
+ lim_log(pMac, LOGE,
+ FL("could not retrieve ListenInterval"));
+ cdf_mem_free(pMlmReassocReq);
+ return;
+ }
+ } else {
+ if (wlan_cfg_get_int(pMac, WNI_CFG_LISTEN_INTERVAL, &val) !=
+ eSIR_SUCCESS) {
+ /**
+ * Could not get ListenInterval value
+ * from CFG. Log error.
+ */
+ lim_log(pMac, LOGE,
+ FL("could not retrieve ListenInterval"));
+ cdf_mem_free(pMlmReassocReq);
+ return;
+ }
+ }
+ if (lim_set_link_state
+ (pMac, eSIR_LINK_PREASSOC_STATE, psessionEntry->bssId,
+ psessionEntry->selfMacAddr, NULL, NULL) != eSIR_SUCCESS) {
+ cdf_mem_free(pMlmReassocReq);
+ return;
+ }
+
+ pMlmReassocReq->listenInterval = (uint16_t) val;
+ psessionEntry->pLimMlmReassocReq = pMlmReassocReq;
+
+ /* we need to defer the message until we get the response back from HAL */
+ SET_LIM_PROCESS_DEFD_MESGS(pMac, false);
+
+ msgQ.type = SIR_HAL_ADD_BSS_REQ;
+ msgQ.reserved = 0;
+ msgQ.bodyptr = psessionEntry->ftPEContext.pAddBssReq;
+ msgQ.bodyval = 0;
+
+#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG
+ lim_log(pMac, LOG1, FL("Sending SIR_HAL_ADD_BSS_REQ..."));
+#endif
+ MTRACE(mac_trace_msg_tx(pMac, psessionEntry->peSessionId, msgQ.type));
+ retCode = wma_post_ctrl_msg(pMac, &msgQ);
+ if (eSIR_SUCCESS != retCode) {
+ cdf_mem_free(psessionEntry->ftPEContext.pAddBssReq);
+ lim_log(pMac, LOGE,
+ FL("Posting ADD_BSS_REQ to HAL failed, reason=%X"),
+ retCode);
+ }
+
+ psessionEntry->ftPEContext.pAddBssReq = NULL;
+ return;
+}
+
+/*
+ * lim_process_ft_preauth_rsp_timeout() - process ft preauth rsp timeout
+ *
+ * @mac_ctx: global mac ctx
+ *
+ * This function is called if preauth response is not received from the AP
+ * within this timeout while FT in progress
+ *
+ * Return: void
+ */
+void lim_process_ft_preauth_rsp_timeout(tpAniSirGlobal mac_ctx)
+{
+ tpPESession session;
+
+ /*
+ * We have failed pre auth. We need to resume link and get back on
+ * home channel
+ */
+ lim_log(mac_ctx, LOGE, FL("FT Pre-Auth Time Out!!!!"));
+ session = pe_find_session_by_session_id(mac_ctx,
+ mac_ctx->lim.limTimers.gLimFTPreAuthRspTimer.sessionId);
+ if (NULL == session) {
+ lim_log(mac_ctx, LOGE,
+ FL("Session Does not exist for given sessionID"));
+ return;
+ }
+
+ /* Nothing to be done if the session is not in STA mode */
+ if (!LIM_IS_STA_ROLE(session)) {
+#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG
+ lim_log(mac_ctx, LOGE, FL("session is not in STA mode"));
+#endif
+ return;
+ }
+
+ /* Reset the flag to indicate preauth request session */
+ session->ftPEContext.ftPreAuthSession = false;
+
+ if (NULL == session->ftPEContext.pFTPreAuthReq) {
+ lim_log(mac_ctx, LOGE,
+ FL("pFTPreAuthReq is NULL. Auth Rsp might already be posted to SME and ftcleanup done! sessionId:%d"),
+ mac_ctx->lim.limTimers.gLimFTPreAuthRspTimer.sessionId);
+ return;
+ }
+
+ /*
+ * To handle the race condition where we recieve preauth rsp after
+ * timer has expired.
+ */
+ if (true ==
+ session->ftPEContext.pFTPreAuthReq->bPreAuthRspProcessed) {
+ lim_log(mac_ctx, LOGE,
+ FL("Auth rsp already posted to SME (session %p)"),
+ session);
+ return;
+ } else {
+ /*
+ * Here we are sending preauth rsp with failure state
+ * and which is forwarded to SME. Now, if we receive an preauth
+ * resp from AP with success it would create a FT pesession, but
+ * will be dropped in SME leaving behind the pesession. Mark
+ * Preauth rsp processed so that any rsp from AP is dropped in
+ * lim_process_auth_frame_no_session.
+ */
+ lim_log(mac_ctx, LOG1,
+ FL("Auth rsp not yet posted to SME (session %p)"),
+ session);
+ session->ftPEContext.pFTPreAuthReq->bPreAuthRspProcessed = true;
+ }
+
+ /*
+ * Attempted at Pre-Auth and failed. If we are off channel. We need
+ * to get back to home channel
+ */
+ lim_handle_ft_pre_auth_rsp(mac_ctx, eSIR_FAILURE, NULL, 0, session);
+}
+
+/*------------------------------------------------------------------
+ *
+ * This function is called to process the update key request from SME
+ *
+ *------------------------------------------------------------------*/
+bool lim_process_ft_update_key(tpAniSirGlobal pMac, uint32_t *pMsgBuf)
+{
+ tAddBssParams *pAddBssParams;
+ tSirFTUpdateKeyInfo *pKeyInfo;
+ uint32_t val = 0;
+ tpPESession psessionEntry;
+ uint8_t sessionId;
+
+ /* Sanity Check */
+ if (pMac == NULL || pMsgBuf == NULL) {
+ return false;
+ }
+
+ pKeyInfo = (tSirFTUpdateKeyInfo *) pMsgBuf;
+
+ psessionEntry = pe_find_session_by_bssid(pMac, pKeyInfo->bssId, &sessionId);
+ if (NULL == psessionEntry) {
+ PELOGE(lim_log(pMac, LOGE,
+ "%s: Unable to find session for the following bssid",
+ __func__);
+ )
+ lim_print_mac_addr(pMac, pKeyInfo->bssId, LOGE);
+ return false;
+ }
+
+ /* Nothing to be done if the session is not in STA mode */
+ if (!LIM_IS_STA_ROLE(psessionEntry)) {
+#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG
+ PELOGE(lim_log
+ (pMac, LOGE, FL("psessionEntry is not in STA mode"));
+ )
+#endif
+ return false;
+ }
+
+ if (NULL == psessionEntry->ftPEContext.pAddBssReq) {
+ /* AddBss Req is NULL, save the keys to configure them later. */
+ tpLimMlmSetKeysReq pMlmSetKeysReq =
+ &psessionEntry->ftPEContext.PreAuthKeyInfo.
+ extSetStaKeyParam;
+
+ cdf_mem_zero(pMlmSetKeysReq, sizeof(tLimMlmSetKeysReq));
+ cdf_mem_copy(pMlmSetKeysReq->peerMacAddr, pKeyInfo->bssId,
+ sizeof(tSirMacAddr));
+ pMlmSetKeysReq->sessionId = psessionEntry->peSessionId;
+ pMlmSetKeysReq->smesessionId = psessionEntry->smeSessionId;
+ pMlmSetKeysReq->edType = pKeyInfo->keyMaterial.edType;
+ pMlmSetKeysReq->numKeys = pKeyInfo->keyMaterial.numKeys;
+ cdf_mem_copy((uint8_t *) &pMlmSetKeysReq->key,
+ (uint8_t *) &pKeyInfo->keyMaterial.key,
+ sizeof(tSirKeys));
+
+ psessionEntry->ftPEContext.PreAuthKeyInfo.
+ extSetStaKeyParamValid = true;
+
+ lim_log(pMac, LOGE, FL("pAddBssReq is NULL"));
+
+ if (psessionEntry->ftPEContext.pAddStaReq == NULL) {
+ lim_log(pMac, LOGE, FL("pAddStaReq is NULL"));
+ lim_send_set_sta_key_req(pMac, pMlmSetKeysReq, 0, 0,
+ psessionEntry, false);
+ psessionEntry->ftPEContext.PreAuthKeyInfo.
+ extSetStaKeyParamValid = false;
+ }
+ } else {
+ pAddBssParams = psessionEntry->ftPEContext.pAddBssReq;
+
+ /* Store the key information in the ADD BSS parameters */
+ pAddBssParams->extSetStaKeyParamValid = 1;
+ pAddBssParams->extSetStaKeyParam.encType =
+ pKeyInfo->keyMaterial.edType;
+ cdf_mem_copy((uint8_t *) &pAddBssParams->extSetStaKeyParam.key,
+ (uint8_t *) &pKeyInfo->keyMaterial.key,
+ sizeof(tSirKeys));
+ if (eSIR_SUCCESS !=
+ wlan_cfg_get_int(pMac, WNI_CFG_SINGLE_TID_RC, &val)) {
+ lim_log(pMac, LOGP,
+ FL("Unable to read WNI_CFG_SINGLE_TID_RC"));
+ }
+
+ pAddBssParams->extSetStaKeyParam.singleTidRc = val;
+ PELOG1(lim_log(pMac, LOG1, FL("Key valid %d"),
+ pAddBssParams->extSetStaKeyParamValid,
+ pAddBssParams->extSetStaKeyParam.key[0].
+ keyLength);
+ )
+
+ pAddBssParams->extSetStaKeyParam.staIdx = 0;
+
+ PELOG1(lim_log(pMac, LOG1,
+ FL("BSSID = " MAC_ADDRESS_STR),
+ MAC_ADDR_ARRAY(pKeyInfo->bssId));
+ )
+
+ sir_copy_mac_addr(pAddBssParams->extSetStaKeyParam.peerMacAddr,
+ pKeyInfo->bssId);
+
+ pAddBssParams->extSetStaKeyParam.sendRsp = false;
+
+ if (pAddBssParams->extSetStaKeyParam.key[0].keyLength == 16) {
+ PELOG1(lim_log(pMac, LOG1,
+ FL
+ ("BSS key = %02X-%02X-%02X-%02X-%02X-%02X-%02X- "
+ "%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X"),
+ pAddBssParams->extSetStaKeyParam.key[0].
+ key[0],
+ pAddBssParams->extSetStaKeyParam.key[0].
+ key[1],
+ pAddBssParams->extSetStaKeyParam.key[0].
+ key[2],
+ pAddBssParams->extSetStaKeyParam.key[0].
+ key[3],
+ pAddBssParams->extSetStaKeyParam.key[0].
+ key[4],
+ pAddBssParams->extSetStaKeyParam.key[0].
+ key[5],
+ pAddBssParams->extSetStaKeyParam.key[0].
+ key[6],
+ pAddBssParams->extSetStaKeyParam.key[0].
+ key[7],
+ pAddBssParams->extSetStaKeyParam.key[0].
+ key[8],
+ pAddBssParams->extSetStaKeyParam.key[0].
+ key[9],
+ pAddBssParams->extSetStaKeyParam.key[0].
+ key[10],
+ pAddBssParams->extSetStaKeyParam.key[0].
+ key[11],
+ pAddBssParams->extSetStaKeyParam.key[0].
+ key[12],
+ pAddBssParams->extSetStaKeyParam.key[0].
+ key[13],
+ pAddBssParams->extSetStaKeyParam.key[0].
+ key[14],
+ pAddBssParams->extSetStaKeyParam.key[0].
+ key[15]);
+ )
+ }
+ }
+ return true;
+}
+
+void
+lim_ft_send_aggr_qos_rsp(tpAniSirGlobal pMac, uint8_t rspReqd,
+ tpAggrAddTsParams aggrQosRsp, uint8_t smesessionId)
+{
+ tpSirAggrQosRsp rsp;
+ int i = 0;
+ if (!rspReqd) {
+ return;
+ }
+ rsp = cdf_mem_malloc(sizeof(tSirAggrQosRsp));
+ if (NULL == rsp) {
+ lim_log(pMac, LOGP,
+ FL("AllocateMemory failed for tSirAggrQosRsp"));
+ return;
+ }
+ cdf_mem_set((uint8_t *) rsp, sizeof(*rsp), 0);
+ rsp->messageType = eWNI_SME_FT_AGGR_QOS_RSP;
+ rsp->sessionId = smesessionId;
+ rsp->length = sizeof(*rsp);
+ rsp->aggrInfo.tspecIdx = aggrQosRsp->tspecIdx;
+ for (i = 0; i < SIR_QOS_NUM_AC_MAX; i++) {
+ if ((1 << i) & aggrQosRsp->tspecIdx) {
+ rsp->aggrInfo.aggrRsp[i].status = aggrQosRsp->status[i];
+ rsp->aggrInfo.aggrRsp[i].tspec = aggrQosRsp->tspec[i];
+ }
+ }
+ lim_send_sme_aggr_qos_rsp(pMac, rsp, smesessionId);
+ return;
+}
+void lim_process_ft_aggr_qo_s_rsp(tpAniSirGlobal pMac, tpSirMsgQ limMsg)
+{
+ tpAggrAddTsParams pAggrQosRspMsg = NULL;
+ tAddTsParams addTsParam = { 0 };
+ tpDphHashNode pSta = NULL;
+ uint16_t assocId = 0;
+ tSirMacAddr peerMacAddr;
+ uint8_t rspReqd = 1;
+ tpPESession psessionEntry = NULL;
+ int i = 0;
+ PELOG1(lim_log(pMac, LOG1, FL(" Received AGGR_QOS_RSP from HAL"));)
+ SET_LIM_PROCESS_DEFD_MESGS(pMac, true);
+ pAggrQosRspMsg = (tpAggrAddTsParams) (limMsg->bodyptr);
+ if (NULL == pAggrQosRspMsg) {
+ PELOGE(lim_log(pMac, LOGE, FL("NULL pAggrQosRspMsg"));)
+ return;
+ }
+ psessionEntry =
+ pe_find_session_by_session_id(pMac, pAggrQosRspMsg->sessionId);
+ if (NULL == psessionEntry) {
+ PELOGE(lim_log(pMac, LOGE,
+ FL("Cant find session entry for %s"), __func__);
+ )
+ if (pAggrQosRspMsg != NULL) {
+ cdf_mem_free(pAggrQosRspMsg);
+ }
+ return;
+ }
+ if (!LIM_IS_STA_ROLE(psessionEntry)) {
+#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG
+ PELOGE(lim_log
+ (pMac, LOGE, FL("psessionEntry is not in STA mode"));
+ )
+#endif
+ return;
+ }
+ for (i = 0; i < HAL_QOS_NUM_AC_MAX; i++) {
+ if ((((1 << i) & pAggrQosRspMsg->tspecIdx)) &&
+ (pAggrQosRspMsg->status[i] != CDF_STATUS_SUCCESS)) {
+ sir_copy_mac_addr(peerMacAddr, psessionEntry->bssId);
+ addTsParam.staIdx = pAggrQosRspMsg->staIdx;
+ addTsParam.sessionId = pAggrQosRspMsg->sessionId;
+ addTsParam.tspec = pAggrQosRspMsg->tspec[i];
+ addTsParam.tspecIdx = pAggrQosRspMsg->tspecIdx;
+ lim_send_delts_req_action_frame(pMac, peerMacAddr, rspReqd,
+ &addTsParam.tspec.tsinfo,
+ &addTsParam.tspec,
+ psessionEntry);
+ pSta =
+ dph_lookup_assoc_id(pMac, addTsParam.staIdx, &assocId,
+ &psessionEntry->dph.dphHashTable);
+ if (pSta != NULL) {
+ lim_admit_control_delete_ts(pMac, assocId,
+ &addTsParam.tspec.
+ tsinfo, NULL,
+ (uint8_t *) &
+ addTsParam.tspecIdx);
+ }
+ }
+ }
+ lim_ft_send_aggr_qos_rsp(pMac, rspReqd, pAggrQosRspMsg,
+ psessionEntry->smeSessionId);
+ if (pAggrQosRspMsg != NULL) {
+ cdf_mem_free(pAggrQosRspMsg);
+ }
+ return;
+}
+tSirRetStatus lim_process_ft_aggr_qos_req(tpAniSirGlobal pMac, uint32_t *pMsgBuf)
+{
+ tSirMsgQ msg;
+ tSirAggrQosReq *aggrQosReq = (tSirAggrQosReq *) pMsgBuf;
+ tpAggrAddTsParams pAggrAddTsParam;
+ tpPESession psessionEntry = NULL;
+ tpLimTspecInfo tspecInfo;
+ uint8_t ac;
+ tpDphHashNode pSta;
+ uint16_t aid;
+ uint8_t sessionId;
+ int i;
+
+ pAggrAddTsParam = cdf_mem_malloc(sizeof(tAggrAddTsParams));
+ if (NULL == pAggrAddTsParam) {
+ PELOGE(lim_log(pMac, LOGE, FL("AllocateMemory() failed"));)
+ return eSIR_MEM_ALLOC_FAILED;
+ }
+
+ psessionEntry =
+ pe_find_session_by_bssid(pMac, aggrQosReq->bssId, &sessionId);
+
+ if (psessionEntry == NULL) {
+ PELOGE(lim_log
+ (pMac, LOGE,
+ FL("psession Entry Null for sessionId = %d"),
+ aggrQosReq->sessionId);
+ )
+ cdf_mem_free(pAggrAddTsParam);
+ return eSIR_FAILURE;
+ }
+
+ /* Nothing to be done if the session is not in STA mode */
+ if (!LIM_IS_STA_ROLE(psessionEntry)) {
+#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG
+ PELOGE(lim_log
+ (pMac, LOGE, FL("psessionEntry is not in STA mode"));
+ )
+#endif
+ cdf_mem_free(pAggrAddTsParam);
+ return eSIR_FAILURE;
+ }
+
+ pSta = dph_lookup_hash_entry(pMac, aggrQosReq->bssId, &aid,
+ &psessionEntry->dph.dphHashTable);
+ if (pSta == NULL) {
+ PELOGE(lim_log(pMac, LOGE,
+ FL
+ ("Station context not found - ignoring AddTsRsp"));
+ )
+ cdf_mem_free(pAggrAddTsParam);
+ return eSIR_FAILURE;
+ }
+
+ cdf_mem_set((uint8_t *) pAggrAddTsParam, sizeof(tAggrAddTsParams), 0);
+ pAggrAddTsParam->staIdx = psessionEntry->staId;
+ /* Fill in the sessionId specific to PE */
+ pAggrAddTsParam->sessionId = sessionId;
+ pAggrAddTsParam->tspecIdx = aggrQosReq->aggrInfo.tspecIdx;
+
+ for (i = 0; i < HAL_QOS_NUM_AC_MAX; i++) {
+ if (aggrQosReq->aggrInfo.tspecIdx & (1 << i)) {
+ tSirMacTspecIE *pTspec =
+ &aggrQosReq->aggrInfo.aggrAddTsInfo[i].tspec;
+ /* Since AddTS response was successful, check for the PSB flag
+ * and directional flag inside the TS Info field.
+ * An AC is trigger enabled AC if the PSB subfield is set to 1
+ * in the uplink direction.
+ * An AC is delivery enabled AC if the PSB subfield is set to 1
+ * in the downlink direction.
+ * An AC is trigger and delivery enabled AC if the PSB subfield
+ * is set to 1 in the bi-direction field.
+ */
+ if (pTspec->tsinfo.traffic.psb == 1) {
+ lim_set_tspec_uapsd_mask_per_session(pMac,
+ psessionEntry,
+ &pTspec->
+ tsinfo,
+ SET_UAPSD_MASK);
+ } else {
+ lim_set_tspec_uapsd_mask_per_session(pMac,
+ psessionEntry,
+ &pTspec->
+ tsinfo,
+ CLEAR_UAPSD_MASK);
+ }
+ /*
+ * ADDTS success, so AC is now admitted.
+ * We shall now use the default
+ * EDCA parameters as advertised by AP and
+ * send the updated EDCA params
+ * to HAL.
+ */
+ ac = upToAc(pTspec->tsinfo.traffic.userPrio);
+ if (pTspec->tsinfo.traffic.direction ==
+ SIR_MAC_DIRECTION_UPLINK) {
+ psessionEntry->
+ gAcAdmitMask
+ [SIR_MAC_DIRECTION_UPLINK] |=
+ (1 << ac);
+ } else if (pTspec->tsinfo.traffic.direction ==
+ SIR_MAC_DIRECTION_DNLINK) {
+ psessionEntry->
+ gAcAdmitMask
+ [SIR_MAC_DIRECTION_DNLINK] |=
+ (1 << ac);
+ } else if (pTspec->tsinfo.traffic.direction ==
+ SIR_MAC_DIRECTION_BIDIR) {
+ psessionEntry->
+ gAcAdmitMask
+ [SIR_MAC_DIRECTION_UPLINK] |=
+ (1 << ac);
+ psessionEntry->
+ gAcAdmitMask
+ [SIR_MAC_DIRECTION_DNLINK] |=
+ (1 << ac);
+ }
+ lim_set_active_edca_params(pMac,
+ psessionEntry->gLimEdcaParams,
+ psessionEntry);
+
+ lim_send_edca_params(pMac,
+ psessionEntry->gLimEdcaParamsActive,
+ pSta->bssId);
+
+ if (eSIR_SUCCESS !=
+ lim_tspec_add(pMac, pSta->staAddr, pSta->assocId,
+ pTspec, 0, &tspecInfo)) {
+ PELOGE(lim_log
+ (pMac, LOGE,
+ FL
+ ("Adding entry in lim Tspec Table failed "));
+ )
+ pMac->lim.gLimAddtsSent = false;
+ cdf_mem_free(pAggrAddTsParam);
+ return eSIR_FAILURE;
+ }
+
+ pAggrAddTsParam->tspec[i] =
+ aggrQosReq->aggrInfo.aggrAddTsInfo[i].tspec;
+ }
+ }
+
+#ifdef WLAN_FEATURE_ROAM_OFFLOAD
+ if (!pMac->roam.configParam.isRoamOffloadEnabled ||
+ (pMac->roam.configParam.isRoamOffloadEnabled &&
+ !psessionEntry->is11Rconnection))
+#endif
+ {
+ msg.type = WMA_AGGR_QOS_REQ;
+ msg.bodyptr = pAggrAddTsParam;
+ msg.bodyval = 0;
+
+ /* We need to defer any incoming messages until we get a
+ * WMA_AGGR_QOS_RSP from HAL.
+ */
+ SET_LIM_PROCESS_DEFD_MESGS(pMac, false);
+ MTRACE(mac_trace_msg_tx(pMac, psessionEntry->peSessionId, msg.type));
+
+ if (eSIR_SUCCESS != wma_post_ctrl_msg(pMac, &msg)) {
+ PELOGW(lim_log
+ (pMac, LOGW, FL("wma_post_ctrl_msg() failed"));
+ )
+ SET_LIM_PROCESS_DEFD_MESGS(pMac, true);
+ cdf_mem_free(pAggrAddTsParam);
+ return eSIR_FAILURE;
+ }
+ }
+#ifdef WLAN_FEATURE_ROAM_OFFLOAD
+ else {
+ /* Implies it is a LFR3.0 based 11r connection
+ * so donot send add ts request to fimware since it
+ * already has the RIC IEs */
+
+ /* Send the Aggr QoS response to SME */
+ lim_ft_send_aggr_qos_rsp(pMac, true, pAggrAddTsParam,
+ psessionEntry->smeSessionId);
+ if (pAggrAddTsParam != NULL) {
+ cdf_mem_free(pAggrAddTsParam);
+ }
+ }
+#endif
+
+ return eSIR_SUCCESS;
+}
+
+#endif /* WLAN_FEATURE_VOWIFI_11R */
diff --git a/core/mac/src/pe/lim/lim_ibss_peer_mgmt.c b/core/mac/src/pe/lim/lim_ibss_peer_mgmt.c
new file mode 100644
index 0000000..c2c3dba
--- /dev/null
+++ b/core/mac/src/pe/lim/lim_ibss_peer_mgmt.c
@@ -0,0 +1,1833 @@
+/*
+ * Copyright (c) 2012-2015 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.
+ */
+
+#include "cds_api.h"
+#include "ani_global.h"
+#include "sir_common.h"
+#include "wni_cfg.h"
+#include "lim_utils.h"
+#include "lim_assoc_utils.h"
+#include "lim_sta_hash_api.h"
+#include "sch_api.h" /* sch_set_fixed_beacon_fields for IBSS coalesce */
+#include "lim_security_utils.h"
+#include "lim_send_messages.h"
+#ifdef WLAN_FEATURE_VOWIFI_11R
+#include "lim_ft_defs.h"
+#endif
+#include "lim_session.h"
+#include "lim_ibss_peer_mgmt.h"
+#include "lim_types.h"
+
+/**
+ * ibss_peer_find
+ *
+ ***FUNCTION:
+ * This function is called while adding a context at
+ * DPH & Polaris for a peer in IBSS.
+ * If peer is found in the list, capabilities from the
+ * returned BSS description are used at DPH node & Polaris.
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ *
+ ***NOTE:
+ *
+ * @param macAddr - MAC address of the peer
+ *
+ * @return Pointer to peer node if found, else NULL
+ */
+
+static tLimIbssPeerNode *ibss_peer_find(tpAniSirGlobal pMac,
+ tSirMacAddr macAddr)
+{
+ tLimIbssPeerNode *pTempNode = pMac->lim.gLimIbssPeerList;
+
+ while (pTempNode != NULL) {
+ if (cdf_mem_compare((uint8_t *) macAddr,
+ (uint8_t *) &pTempNode->peerMacAddr,
+ sizeof(tSirMacAddr)))
+ break;
+ pTempNode = pTempNode->next;
+ }
+ return pTempNode;
+} /*** end ibss_peer_find() ***/
+
+/**
+ * ibss_peer_add
+ *
+ ***FUNCTION:
+ * This is called on a STA in IBSS upon receiving Beacon/
+ * Probe Response from a peer.
+ *
+ ***LOGIC:
+ * Node is always added to the front of the list
+ *
+ ***ASSUMPTIONS:
+ *
+ ***NOTE:
+ *
+ * @param pMac - Pointer to Global MAC structure
+ * @param pPeerNode - Pointer to peer node to be added to the list.
+ *
+ * @return None
+ */
+
+static tSirRetStatus
+ibss_peer_add(tpAniSirGlobal pMac, tLimIbssPeerNode *pPeerNode)
+{
+#ifdef ANI_SIR_IBSS_PEER_CACHING
+ uint32_t numIbssPeers = (2 * pMac->lim.maxStation);
+
+ if (pMac->lim.gLimNumIbssPeers >= numIbssPeers) {
+ /**
+ * Reached max number of peers to be maintained.
+ * Delete last entry & add new entry at the beginning.
+ */
+ tLimIbssPeerNode *pTemp, *pPrev;
+ pTemp = pPrev = pMac->lim.gLimIbssPeerList;
+ while (pTemp->next != NULL) {
+ pPrev = pTemp;
+ pTemp = pTemp->next;
+ }
+ if (pTemp->beacon) {
+ cdf_mem_free(pTemp->beacon);
+ }
+
+ cdf_mem_free(pTemp);
+ pPrev->next = NULL;
+ } else
+#endif
+ pMac->lim.gLimNumIbssPeers++;
+
+ pPeerNode->next = pMac->lim.gLimIbssPeerList;
+ pMac->lim.gLimIbssPeerList = pPeerNode;
+
+ return eSIR_SUCCESS;
+
+} /*** end limAddIbssPeerToList() ***/
+
+/**
+ * ibss_peer_collect
+ *
+ ***FUNCTION:
+ * This is called to collect IBSS peer information
+ * from received Beacon/Probe Response frame from it.
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ *
+ ***NOTE:
+ *
+ * @param pMac - Pointer to Global MAC structure
+ * @param pBeacon - Parsed Beacon Frame structure
+ * @param pBD - Pointer to received BD
+ * @param pPeer - Pointer to IBSS peer node
+ *
+ * @return None
+ */
+
+static void
+ibss_peer_collect(tpAniSirGlobal pMac,
+ tpSchBeaconStruct pBeacon,
+ tpSirMacMgmtHdr pHdr,
+ tLimIbssPeerNode *pPeer, tpPESession psessionEntry)
+{
+ cdf_mem_copy(pPeer->peerMacAddr, pHdr->sa, sizeof(tSirMacAddr));
+
+ pPeer->capabilityInfo = pBeacon->capabilityInfo;
+ pPeer->extendedRatesPresent = pBeacon->extendedRatesPresent;
+ pPeer->edcaPresent = pBeacon->edcaPresent;
+ pPeer->wmeEdcaPresent = pBeacon->wmeEdcaPresent;
+ pPeer->wmeInfoPresent = pBeacon->wmeInfoPresent;
+
+ if (pBeacon->IBSSParams.present) {
+ pPeer->atimIePresent = pBeacon->IBSSParams.present;
+ pPeer->peerAtimWindowLength = pBeacon->IBSSParams.atim;
+ }
+
+ if (IS_DOT11_MODE_HT(psessionEntry->dot11mode) &&
+ (pBeacon->HTCaps.present)) {
+ pPeer->htCapable = pBeacon->HTCaps.present;
+ cdf_mem_copy((uint8_t *) pPeer->supportedMCSSet,
+ (uint8_t *) pBeacon->HTCaps.supportedMCSSet,
+ sizeof(pPeer->supportedMCSSet));
+ pPeer->htGreenfield = (uint8_t) pBeacon->HTCaps.greenField;
+ pPeer->htSupportedChannelWidthSet =
+ (uint8_t) pBeacon->HTCaps.supportedChannelWidthSet;
+ pPeer->htMIMOPSState =
+ (tSirMacHTMIMOPowerSaveState) pBeacon->HTCaps.mimoPowerSave;
+ pPeer->htMaxAmsduLength =
+ (uint8_t) pBeacon->HTCaps.maximalAMSDUsize;
+ pPeer->htAMpduDensity = pBeacon->HTCaps.mpduDensity;
+ pPeer->htDsssCckRate40MHzSupport =
+ (uint8_t) pBeacon->HTCaps.dsssCckMode40MHz;
+ pPeer->htShortGI20Mhz = (uint8_t) pBeacon->HTCaps.shortGI20MHz;
+ pPeer->htShortGI40Mhz = (uint8_t) pBeacon->HTCaps.shortGI40MHz;
+ pPeer->htMaxRxAMpduFactor = pBeacon->HTCaps.maxRxAMPDUFactor;
+ pPeer->htSecondaryChannelOffset =
+ pBeacon->HTInfo.secondaryChannelOffset;
+ pPeer->htLdpcCapable = (uint8_t) pBeacon->HTCaps.advCodingCap;
+ }
+
+ /* Collect peer VHT capabilities based on the received beacon from the peer */
+#ifdef WLAN_FEATURE_11AC
+ if (pBeacon->VHTCaps.present) {
+ pPeer->vhtSupportedChannelWidthSet =
+ pBeacon->VHTOperation.chanWidth;
+ pPeer->vhtCapable = pBeacon->VHTCaps.present;
+
+ /* Collect VHT capabilities from beacon */
+ cdf_mem_copy((uint8_t *) &pPeer->VHTCaps,
+ (uint8_t *) &pBeacon->VHTCaps,
+ sizeof(tDot11fIEVHTCaps));
+ }
+#endif
+ pPeer->erpIePresent = pBeacon->erpPresent;
+
+ cdf_mem_copy((uint8_t *) &pPeer->supportedRates,
+ (uint8_t *) &pBeacon->supportedRates,
+ pBeacon->supportedRates.numRates + 1);
+ if (pPeer->extendedRatesPresent)
+ cdf_mem_copy((uint8_t *) &pPeer->extendedRates,
+ (uint8_t *) &pBeacon->extendedRates,
+ pBeacon->extendedRates.numRates + 1);
+ else
+ pPeer->extendedRates.numRates = 0;
+
+ pPeer->next = NULL;
+} /*** end ibss_peer_collect() ***/
+
+/* handle change in peer qos/wme capabilities */
+static void
+ibss_sta_caps_update(tpAniSirGlobal pMac,
+ tLimIbssPeerNode *pPeerNode, tpPESession psessionEntry)
+{
+ uint16_t peerIdx;
+ tpDphHashNode pStaDs;
+
+ pPeerNode->beaconHBCount++; /* Update beacon count. */
+
+ /* if the peer node exists, update its qos capabilities */
+ pStaDs = dph_lookup_hash_entry(pMac, pPeerNode->peerMacAddr, &peerIdx,
+ &psessionEntry->dph.dphHashTable);
+ if (pStaDs == NULL)
+ return;
+
+ /* Update HT Capabilities */
+ if (IS_DOT11_MODE_HT(psessionEntry->dot11mode)) {
+ pStaDs->mlmStaContext.htCapability = pPeerNode->htCapable;
+ if (pPeerNode->htCapable) {
+ pStaDs->htGreenfield = pPeerNode->htGreenfield;
+ pStaDs->htSupportedChannelWidthSet =
+ pPeerNode->htSupportedChannelWidthSet;
+ pStaDs->htMIMOPSState = pPeerNode->htMIMOPSState;
+ pStaDs->htMaxAmsduLength = pPeerNode->htMaxAmsduLength;
+ pStaDs->htAMpduDensity = pPeerNode->htAMpduDensity;
+ pStaDs->htDsssCckRate40MHzSupport =
+ pPeerNode->htDsssCckRate40MHzSupport;
+ pStaDs->htShortGI20Mhz = pPeerNode->htShortGI20Mhz;
+ pStaDs->htShortGI40Mhz = pPeerNode->htShortGI40Mhz;
+ pStaDs->htMaxRxAMpduFactor =
+ pPeerNode->htMaxRxAMpduFactor;
+ /* In the future, may need to check for "delayedBA" */
+ /* For now, it is IMMEDIATE BA only on ALL TID's */
+ pStaDs->baPolicyFlag = 0xFF;
+ pStaDs->htLdpcCapable = pPeerNode->htLdpcCapable;
+ }
+ }
+#ifdef WLAN_FEATURE_11AC
+ if (IS_DOT11_MODE_VHT(psessionEntry->dot11mode)) {
+ pStaDs->mlmStaContext.vhtCapability = pPeerNode->vhtCapable;
+ if (pPeerNode->vhtCapable) {
+ pStaDs->vhtSupportedChannelWidthSet =
+ pPeerNode->vhtSupportedChannelWidthSet;
+
+ /* If in 11AC mode and if session requires 11AC mode, consider peer's */
+ /* max AMPDU length factor */
+ pStaDs->htMaxRxAMpduFactor =
+ pPeerNode->VHTCaps.maxAMPDULenExp;
+ pStaDs->vhtLdpcCapable =
+ (uint8_t) pPeerNode->VHTCaps.ldpcCodingCap;
+ }
+ }
+#endif
+ /* peer is 11e capable but is not 11e enabled yet */
+ /* some STA's when joining Airgo IBSS, assert qos capability even when */
+ /* they don't suport qos. however, they do not include the edca parameter */
+ /* set. so let's check for edcaParam in addition to the qos capability */
+ if (pPeerNode->capabilityInfo.qos && (psessionEntry->limQosEnabled)
+ && pPeerNode->edcaPresent) {
+ pStaDs->qosMode = 1;
+ pStaDs->wmeEnabled = 0;
+ if (!pStaDs->lleEnabled) {
+ pStaDs->lleEnabled = 1;
+ /* dphSetACM(pMac, pStaDs); */
+ }
+ return;
+ }
+ /* peer is not 11e capable now but was 11e enabled earlier */
+ else if (pStaDs->lleEnabled) {
+ pStaDs->qosMode = 0;
+ pStaDs->lleEnabled = 0;
+ }
+ /* peer is wme capable but is not wme enabled yet */
+ if (pPeerNode->wmeInfoPresent && psessionEntry->limWmeEnabled) {
+ pStaDs->qosMode = 1;
+ pStaDs->lleEnabled = 0;
+ if (!pStaDs->wmeEnabled) {
+ pStaDs->wmeEnabled = 1;
+ }
+ return;
+ }
+ /* When the peer device supports EDCA parameters, then we were not
+ considering. Added this code when we saw that one of the Peer Device
+ was advertising WMM param where we were not honouring that. CR# 210756
+ */
+ if (pPeerNode->wmeEdcaPresent && psessionEntry->limWmeEnabled) {
+ pStaDs->qosMode = 1;
+ pStaDs->lleEnabled = 0;
+ if (!pStaDs->wmeEnabled) {
+ pStaDs->wmeEnabled = 1;
+ }
+ return;
+ }
+ /* peer is not wme capable now but was wme enabled earlier */
+ else if (pStaDs->wmeEnabled) {
+ pStaDs->qosMode = 0;
+ pStaDs->wmeEnabled = 0;
+ }
+
+}
+
+static void
+ibss_sta_rates_update(tpAniSirGlobal pMac,
+ tpDphHashNode pStaDs,
+ tLimIbssPeerNode *pPeer, tpPESession psessionEntry)
+{
+#ifdef WLAN_FEATURE_11AC
+ lim_populate_matching_rate_set(pMac, pStaDs, &pPeer->supportedRates,
+ &pPeer->extendedRates,
+ pPeer->supportedMCSSet, psessionEntry,
+ &pPeer->VHTCaps);
+#else
+ /* Populate supported rateset */
+ lim_populate_matching_rate_set(pMac, pStaDs, &pPeer->supportedRates,
+ &pPeer->extendedRates,
+ pPeer->supportedMCSSet, psessionEntry);
+#endif
+
+ pStaDs->mlmStaContext.capabilityInfo = pPeer->capabilityInfo;
+} /*** end ibss_sta_info_update() ***/
+
+/**
+ * ibss_sta_info_update
+ *
+ ***FUNCTION:
+ * This is called to program both SW & Polaris context
+ * for peer in IBSS.
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ *
+ ***NOTE:
+ *
+ * @param pMac - Pointer to Global MAC structure
+ * @param pStaDs - Pointer to DPH node
+ * @param pPeer - Pointer to IBSS peer node
+ *
+ * @return None
+ */
+
+static void
+ibss_sta_info_update(tpAniSirGlobal pMac,
+ tpDphHashNode pStaDs,
+ tLimIbssPeerNode *pPeer, tpPESession psessionEntry)
+{
+ pStaDs->staType = STA_ENTRY_PEER;
+ ibss_sta_caps_update(pMac, pPeer, psessionEntry);
+ ibss_sta_rates_update(pMac, pStaDs, pPeer, psessionEntry);
+} /*** end ibss_sta_info_update() ***/
+
+static void ibss_coalesce_free(tpAniSirGlobal pMac)
+{
+ if (pMac->lim.ibssInfo.pHdr != NULL)
+ cdf_mem_free(pMac->lim.ibssInfo.pHdr);
+ if (pMac->lim.ibssInfo.pBeacon != NULL)
+ cdf_mem_free(pMac->lim.ibssInfo.pBeacon);
+
+ pMac->lim.ibssInfo.pHdr = NULL;
+ pMac->lim.ibssInfo.pBeacon = NULL;
+}
+
+/*
+ * save the beacon params for use when adding the bss
+ */
+static void
+ibss_coalesce_save(tpAniSirGlobal pMac,
+ tpSirMacMgmtHdr pHdr, tpSchBeaconStruct pBeacon)
+{
+ /* get rid of any saved info */
+ ibss_coalesce_free(pMac);
+
+ pMac->lim.ibssInfo.pHdr = cdf_mem_malloc(sizeof(*pHdr));
+ if (NULL == pMac->lim.ibssInfo.pHdr) {
+ PELOGE(lim_log(pMac, LOGE, FL("ibbs-save: Failed malloc pHdr"));)
+ return;
+ }
+ pMac->lim.ibssInfo.pBeacon = cdf_mem_malloc(sizeof(*pBeacon));
+ if (NULL == pMac->lim.ibssInfo.pBeacon) {
+ PELOGE(lim_log
+ (pMac, LOGE, FL("ibbs-save: Failed malloc pBeacon"));
+ )
+ ibss_coalesce_free(pMac);
+ return;
+ }
+
+ cdf_mem_copy(pMac->lim.ibssInfo.pHdr, pHdr, sizeof(*pHdr));
+ cdf_mem_copy(pMac->lim.ibssInfo.pBeacon, pBeacon, sizeof(*pBeacon));
+}
+
+/*
+ * tries to add a new entry to dph hash node
+ * if necessary, an existing entry is eliminated
+ */
+static tSirRetStatus
+ibss_dph_entry_add(tpAniSirGlobal pMac,
+ tSirMacAddr peerAddr,
+ tpDphHashNode *ppSta, tpPESession psessionEntry)
+{
+ uint16_t peerIdx;
+ tpDphHashNode pStaDs;
+
+ *ppSta = NULL;
+
+ pStaDs =
+ dph_lookup_hash_entry(pMac, peerAddr, &peerIdx,
+ &psessionEntry->dph.dphHashTable);
+ if (pStaDs != NULL) {
+ /* Trying to add context for already existing STA in IBSS */
+ PELOGE(lim_log(pMac, LOGE, FL("STA exists already "));)
+ lim_print_mac_addr(pMac, peerAddr, LOGE);
+ return eSIR_FAILURE;
+ }
+
+ /**
+ * Assign an AID, delete context existing with that
+ * AID and then add an entry to hash table maintained
+ * by DPH module.
+ */
+ peerIdx = lim_assign_peer_idx(pMac, psessionEntry);
+
+ pStaDs =
+ dph_get_hash_entry(pMac, peerIdx, &psessionEntry->dph.dphHashTable);
+ if (pStaDs) {
+ (void)lim_del_sta(pMac, pStaDs, false /*asynchronous */,
+ psessionEntry);
+ lim_delete_dph_hash_entry(pMac, pStaDs->staAddr, peerIdx,
+ psessionEntry);
+ }
+
+ pStaDs =
+ dph_add_hash_entry(pMac, peerAddr, peerIdx,
+ &psessionEntry->dph.dphHashTable);
+ if (pStaDs == NULL) {
+ /* Could not add hash table entry */
+ PELOGE(lim_log
+ (pMac, LOGE,
+ FL
+ ("could not add hash entry at DPH for peerIdx/aid=%d MACaddr:"),
+ peerIdx);
+ )
+ lim_print_mac_addr(pMac, peerAddr, LOGE);
+ return eSIR_FAILURE;
+ }
+
+ *ppSta = pStaDs;
+ return eSIR_SUCCESS;
+}
+
+/* send a status change notification */
+static void
+ibss_status_chg_notify(tpAniSirGlobal pMac,
+ tSirMacAddr peerAddr,
+ uint16_t staIndex,
+ uint8_t ucastSig,
+ uint8_t bcastSig, uint16_t status, uint8_t sessionId)
+{
+
+ tLimIbssPeerNode *peerNode;
+ uint8_t *beacon = NULL;
+ uint16_t bcnLen = 0;
+
+ peerNode = ibss_peer_find(pMac, peerAddr);
+ if (peerNode != NULL) {
+ if (peerNode->beacon == NULL)
+ peerNode->beaconLen = 0;
+ beacon = peerNode->beacon;
+ bcnLen = peerNode->beaconLen;
+ peerNode->beacon = NULL;
+ peerNode->beaconLen = 0;
+ }
+
+ lim_send_sme_ibss_peer_ind(pMac, peerAddr, staIndex, ucastSig, bcastSig,
+ beacon, bcnLen, status, sessionId);
+
+ if (beacon != NULL) {
+ cdf_mem_free(beacon);
+ }
+}
+
+static void ibss_bss_add(tpAniSirGlobal pMac, tpPESession psessionEntry)
+{
+ tLimMlmStartReq mlmStartReq;
+ uint32_t cfg;
+ tpSirMacMgmtHdr pHdr = (tpSirMacMgmtHdr) pMac->lim.ibssInfo.pHdr;
+ tpSchBeaconStruct pBeacon =
+ (tpSchBeaconStruct) pMac->lim.ibssInfo.pBeacon;
+ uint8_t numExtRates = 0;
+
+ if ((pHdr == NULL) || (pBeacon == NULL)) {
+ PELOGE(lim_log
+ (pMac, LOGE,
+ FL("Unable to add BSS (no cached BSS info)"));
+ )
+ return;
+ }
+
+ cdf_mem_copy(psessionEntry->bssId, pHdr->bssId, sizeof(tSirMacAddr));
+
+ sir_copy_mac_addr(pHdr->bssId, psessionEntry->bssId);
+
+ /* Copy beacon interval from sessionTable */
+ cfg = psessionEntry->beaconParams.beaconInterval;
+ if (cfg != pBeacon->beaconInterval)
+ psessionEntry->beaconParams.beaconInterval =
+ pBeacon->beaconInterval;
+
+ /* This function ibss_bss_add (and hence the below code) is only called during ibss coalescing. We need to
+ * adapt to peer's capability with respect to short slot time. Changes have been made to lim_apply_configuration()
+ * so that the IBSS doesnt blindly start with short slot = 1. If IBSS start is part of coalescing then it will adapt
+ * to peer's short slot using code below.
+ */
+ /* If cfg is already set to current peer's capability then no need to set it again */
+ if (psessionEntry->shortSlotTimeSupported !=
+ pBeacon->capabilityInfo.shortSlotTime) {
+ psessionEntry->shortSlotTimeSupported =
+ pBeacon->capabilityInfo.shortSlotTime;
+ }
+ cdf_mem_copy((uint8_t *) &psessionEntry->pLimStartBssReq->
+ operationalRateSet, (uint8_t *) &pBeacon->supportedRates,
+ pBeacon->supportedRates.numRates);
+
+ /**
+ * WNI_CFG_EXTENDED_OPERATIONAL_RATE_SET CFG needs to be reset, when
+ * there is no extended rate IE present in beacon. This is especially important when
+ * supportedRateSet IE contains all the extended rates as well and STA decides to coalesce.
+ * In this IBSS coalescing scenario LIM will tear down the BSS and Add a new one. So LIM needs to
+ * reset this CFG, just in case CSR originally had set this CFG when IBSS was started from the local profile.
+ * If IBSS was started by CSR from the BssDescription, then it would reset this CFG before StartBss is issued.
+ * The idea is that the count of OpRateSet and ExtendedOpRateSet rates should not be more than 12.
+ */
+
+ if (pBeacon->extendedRatesPresent)
+ numExtRates = pBeacon->extendedRates.numRates;
+ if (cfg_set_str(pMac, WNI_CFG_EXTENDED_OPERATIONAL_RATE_SET,
+ (uint8_t *) &pBeacon->extendedRates.rate,
+ numExtRates) != eSIR_SUCCESS) {
+ lim_log(pMac, LOGP,
+ FL("could not update ExtendedOperRateset at CFG"));
+ return;
+ }
+
+ /*
+ * Each IBSS node will advertise its own HT Capabilities instead of adapting to the Peer's capabilities
+ * If we don't do this then IBSS may not go back to full capabilities when the STA with lower capabilities
+ * leaves the IBSS. e.g. when non-CB STA joins an IBSS and then leaves, the IBSS will be stuck at non-CB mode
+ * even though all the nodes are capable of doing CB.
+ * so it is decided to leave the self HT capabilties intact. This may change if some issues are found in interop.
+ */
+ cdf_mem_set((void *)&mlmStartReq, sizeof(mlmStartReq), 0);
+
+ cdf_mem_copy(mlmStartReq.bssId, pHdr->bssId, sizeof(tSirMacAddr));
+ mlmStartReq.rateSet.numRates =
+ psessionEntry->pLimStartBssReq->operationalRateSet.numRates;
+ cdf_mem_copy(&mlmStartReq.rateSet.rate[0],
+ &psessionEntry->pLimStartBssReq->operationalRateSet.
+ rate[0], mlmStartReq.rateSet.numRates);
+ mlmStartReq.bssType = eSIR_IBSS_MODE;
+ mlmStartReq.beaconPeriod = pBeacon->beaconInterval;
+ mlmStartReq.nwType = psessionEntry->pLimStartBssReq->nwType; /* psessionEntry->nwType is also OK???? */
+ mlmStartReq.htCapable = psessionEntry->htCapability;
+ mlmStartReq.htOperMode = pMac->lim.gHTOperMode;
+ mlmStartReq.dualCTSProtection = pMac->lim.gHTDualCTSProtection;
+ mlmStartReq.txChannelWidthSet = psessionEntry->htRecommendedTxWidthSet;
+
+ /* reading the channel num from session Table */
+ mlmStartReq.channelNumber = psessionEntry->currentOperChannel;
+
+ mlmStartReq.cbMode = psessionEntry->pLimStartBssReq->cbMode;
+
+ /* Copy the SSID for RxP filtering based on SSID. */
+ cdf_mem_copy((uint8_t *) &mlmStartReq.ssId,
+ (uint8_t *) &psessionEntry->pLimStartBssReq->ssId,
+ psessionEntry->pLimStartBssReq->ssId.length + 1);
+
+ PELOG1(lim_log
+ (pMac, LOG1, FL("invoking ADD_BSS as part of coalescing!"));
+ )
+ if (lim_mlm_add_bss(pMac, &mlmStartReq, psessionEntry) !=
+ eSIR_SME_SUCCESS) {
+ PELOGE(lim_log(pMac, LOGE, FL("AddBss failure"));)
+ return;
+ }
+ /* Update fields in Beacon */
+ if (sch_set_fixed_beacon_fields(pMac, psessionEntry) != eSIR_SUCCESS) {
+ PELOGE(lim_log
+ (pMac, LOGE,
+ FL("*** Unable to set fixed Beacon fields ***"));
+ )
+ return;
+ }
+
+}
+
+/* delete the current BSS */
+static void ibss_bss_delete(tpAniSirGlobal pMac, tpPESession psessionEntry)
+{
+ tSirRetStatus status;
+ PELOGW(lim_log(pMac, LOGW, FL("Initiating IBSS Delete BSS"));)
+ if (psessionEntry->limMlmState != eLIM_MLM_BSS_STARTED_STATE) {
+ lim_log(pMac, LOGW,
+ FL("Incorrect LIM MLM state for delBss (%d)"),
+ psessionEntry->limMlmState);
+ return;
+ }
+ status = lim_del_bss(pMac, NULL, psessionEntry->bssIdx, psessionEntry);
+ if (status != eSIR_SUCCESS)
+ PELOGE(lim_log
+ (pMac, LOGE, FL("delBss failed for bss %d"),
+ psessionEntry->bssIdx);
+ )
+}
+
+/**
+ * lim_ibss_init
+ *
+ ***FUNCTION:
+ * This function is called while starting an IBSS
+ * to initialize list used to maintain IBSS peers.
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ *
+ ***NOTE:
+ *
+ * @param pMac - Pointer to Global MAC structure
+ * @return None
+ */
+
+void lim_ibss_init(tpAniSirGlobal pMac)
+{
+ pMac->lim.gLimIbssCoalescingHappened = 0;
+ pMac->lim.gLimIbssPeerList = NULL;
+ pMac->lim.gLimNumIbssPeers = 0;
+
+ /* ibss info - params for which ibss to join while coalescing */
+ cdf_mem_set(&pMac->lim.ibssInfo, sizeof(tAniSirLimIbss), 0);
+} /*** end lim_ibss_init() ***/
+
+/**
+ * lim_ibss_delete_all_peers
+ *
+ ***FUNCTION:
+ * This function is called to delete all peers.
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ *
+ ***NOTE:
+ *
+ * @param pMac - Pointer to Global MAC structure
+ * @return None
+ */
+
+void lim_ibss_delete_all_peers(tpAniSirGlobal pMac, tpPESession psessionEntry)
+{
+ tLimIbssPeerNode *pCurrNode, *pTempNode;
+ tpDphHashNode pStaDs;
+ uint16_t peerIdx;
+
+ pCurrNode = pTempNode = pMac->lim.gLimIbssPeerList;
+
+ while (pCurrNode != NULL) {
+ if (!pMac->lim.gLimNumIbssPeers) {
+ lim_log(pMac, LOGP,
+ FL
+ ("Number of peers in the list is zero and node present"));
+ return;
+ }
+ /* Delete the dph entry for the station
+ * Since it is called to remove all peers, just delete from dph,
+ * no need to do any beacon related params i.e., dont call lim_delete_dph_hash_entry
+ */
+ pStaDs =
+ dph_lookup_hash_entry(pMac, pCurrNode->peerMacAddr, &peerIdx,
+ &psessionEntry->dph.dphHashTable);
+ if (pStaDs) {
+
+ ibss_status_chg_notify(pMac, pCurrNode->peerMacAddr,
+ pStaDs->staIndex,
+ pStaDs->ucUcastSig,
+ pStaDs->ucBcastSig,
+ eWNI_SME_IBSS_PEER_DEPARTED_IND,
+ psessionEntry->smeSessionId);
+ lim_release_peer_idx(pMac, peerIdx, psessionEntry);
+ dph_delete_hash_entry(pMac, pStaDs->staAddr, peerIdx,
+ &psessionEntry->dph.dphHashTable);
+ }
+
+ pTempNode = pCurrNode->next;
+
+ /* TODO :Sessionize this code */
+ /* Fix CR 227642: PeerList should point to the next node since the current node is being
+ * freed in the next line. In ibss_peerfind in ibss_status_chg_notify above, we use this
+ * peer list to find the next peer. So this list needs to be updated with the no of peers left
+ * after each iteration in this while loop since one by one peers are deleted (freed) in this
+ * loop causing the lim.gLimIbssPeerList to point to some freed memory.
+ */
+ pMac->lim.gLimIbssPeerList = pTempNode;
+
+ if (pCurrNode->beacon) {
+ cdf_mem_free(pCurrNode->beacon);
+ }
+ cdf_mem_free(pCurrNode);
+ if (pMac->lim.gLimNumIbssPeers > 0) /* be paranoid */
+ pMac->lim.gLimNumIbssPeers--;
+ pCurrNode = pTempNode;
+ }
+
+ if (pMac->lim.gLimNumIbssPeers)
+ lim_log(pMac, LOGP,
+ FL("Number of peers[%d] in the list is non-zero"),
+ pMac->lim.gLimNumIbssPeers);
+
+ pMac->lim.gLimNumIbssPeers = 0;
+ pMac->lim.gLimIbssPeerList = NULL;
+
+}
+
+/**
+ * lim_ibss_delete() - This function is called while tearing down an IBSS
+ *
+ * @pMac: Pointer to Global MAC structure
+ * @psessionEntry: Pointer to session entry
+ *
+ * Return: none
+ */
+
+void lim_ibss_delete(tpAniSirGlobal pMac, tpPESession psessionEntry)
+{
+ lim_ibss_delete_all_peers(pMac, psessionEntry);
+ ibss_coalesce_free(pMac);
+}
+
+/** -------------------------------------------------------------
+ \fn lim_ibss_set_protection
+ \brief Decides all the protection related information.
+ \
+ \param tpAniSirGlobal pMac
+ \param tSirMacAddr peerMacAddr
+ \param tpUpdateBeaconParams pBeaconParams
+ \return None
+ -------------------------------------------------------------*/
+static void
+lim_ibss_set_protection(tpAniSirGlobal pMac, uint8_t enable,
+ tpUpdateBeaconParams pBeaconParams,
+ tpPESession psessionEntry)
+{
+
+ if (!pMac->lim.cfgProtection.fromllb) {
+ PELOG1(lim_log
+ (pMac, LOG1, FL("protection from 11b is disabled"));
+ )
+ return;
+ }
+
+ if (enable) {
+ psessionEntry->gLim11bParams.protectionEnabled = true;
+ if (false ==
+ psessionEntry->beaconParams.
+ llbCoexist /*pMac->lim.llbCoexist */) {
+ PELOGE(lim_log
+ (pMac, LOGE, FL("=> IBSS: Enable Protection "));
+ )
+ pBeaconParams->llbCoexist =
+ psessionEntry->beaconParams.llbCoexist = true;
+ pBeaconParams->paramChangeBitmap |=
+ PARAM_llBCOEXIST_CHANGED;
+ }
+ } else if (true ==
+ psessionEntry->beaconParams.
+ llbCoexist /*pMac->lim.llbCoexist */) {
+ psessionEntry->gLim11bParams.protectionEnabled = false;
+ PELOGE(lim_log(pMac, LOGE, FL("===> IBSS: Disable protection "));)
+ pBeaconParams->llbCoexist =
+ psessionEntry->beaconParams.llbCoexist = false;
+ pBeaconParams->paramChangeBitmap |= PARAM_llBCOEXIST_CHANGED;
+ }
+ return;
+}
+
+/** -------------------------------------------------------------
+ \fn lim_ibss_update_protection_params
+ \brief Decides all the protection related information.
+ \
+ \param tpAniSirGlobal pMac
+ \param tSirMacAddr peerMacAddr
+ \param tpUpdateBeaconParams pBeaconParams
+ \return None
+ -------------------------------------------------------------*/
+static void
+lim_ibss_update_protection_params(tpAniSirGlobal pMac,
+ tSirMacAddr peerMacAddr,
+ tLimProtStaCacheType protStaCacheType,
+ tpPESession psessionEntry)
+{
+ uint32_t i;
+
+ PELOG1(lim_log(pMac, LOG1, FL("A STA is associated:"));
+ lim_log(pMac, LOG1, FL("Addr : "));
+ lim_print_mac_addr(pMac, peerMacAddr, LOG1);
+ )
+
+ for (i = 0; i < LIM_PROT_STA_CACHE_SIZE; i++) {
+ if (pMac->lim.protStaCache[i].active) {
+ PELOG1(lim_log(pMac, LOG1, FL("Addr: "));)
+ PELOG1(lim_print_mac_addr
+ (pMac, pMac->lim.protStaCache[i].addr, LOG1);
+ )
+
+ if (cdf_mem_compare(pMac->lim.protStaCache[i].addr,
+ peerMacAddr,
+ sizeof(tSirMacAddr))) {
+ PELOG1(lim_log
+ (pMac, LOG1,
+ FL
+ ("matching cache entry at %d already active."),
+ i);
+ )
+ return;
+ }
+ }
+ }
+
+ for (i = 0; i < LIM_PROT_STA_CACHE_SIZE; i++) {
+ if (!pMac->lim.protStaCache[i].active)
+ break;
+ }
+
+ if (i >= LIM_PROT_STA_CACHE_SIZE) {
+ PELOGE(lim_log(pMac, LOGE, FL("No space in ProtStaCache"));)
+ return;
+ }
+
+ cdf_mem_copy(pMac->lim.protStaCache[i].addr,
+ peerMacAddr, sizeof(tSirMacAddr));
+
+ pMac->lim.protStaCache[i].protStaCacheType = protStaCacheType;
+ pMac->lim.protStaCache[i].active = true;
+ if (eLIM_PROT_STA_CACHE_TYPE_llB == protStaCacheType) {
+ psessionEntry->gLim11bParams.numSta++;
+ } else if (eLIM_PROT_STA_CACHE_TYPE_llG == protStaCacheType) {
+ psessionEntry->gLim11gParams.numSta++;
+ }
+}
+
+/** -------------------------------------------------------------
+ \fn lim_ibss_decide_protection
+ \brief Decides all the protection related information.
+ \
+ \param tpAniSirGlobal pMac
+ \param tSirMacAddr peerMacAddr
+ \param tpUpdateBeaconParams pBeaconParams
+ \return None
+ -------------------------------------------------------------*/
+static void
+lim_ibss_decide_protection(tpAniSirGlobal pMac, tpDphHashNode pStaDs,
+ tpUpdateBeaconParams pBeaconParams,
+ tpPESession psessionEntry)
+{
+ tSirRFBand rfBand = SIR_BAND_UNKNOWN;
+ uint32_t phyMode;
+ tLimProtStaCacheType protStaCacheType =
+ eLIM_PROT_STA_CACHE_TYPE_INVALID;
+
+ pBeaconParams->paramChangeBitmap = 0;
+
+ if (NULL == pStaDs) {
+ PELOGE(lim_log(pMac, LOGE, FL("pStaDs is NULL"));)
+ return;
+ }
+
+ lim_get_rf_band_new(pMac, &rfBand, psessionEntry);
+ if (SIR_BAND_2_4_GHZ == rfBand) {
+ lim_get_phy_mode(pMac, &phyMode, psessionEntry);
+
+ /* We are 11G or 11n. Check if we need protection from 11b Stations. */
+ if ((phyMode == WNI_CFG_PHY_MODE_11G)
+ || (psessionEntry->htCapability)) {
+ /* As we found in the past, it is possible that a 11n STA sends
+ * Beacon with HT IE but not ERP IE. So the absense of ERP IE
+ * in the Beacon is not enough to conclude that STA is 11b.
+ */
+ if ((pStaDs->erpEnabled == eHAL_CLEAR) &&
+ (!pStaDs->mlmStaContext.htCapability)) {
+ protStaCacheType = eLIM_PROT_STA_CACHE_TYPE_llB;
+ PELOGE(lim_log
+ (pMac, LOGE,
+ FL("Enable protection from 11B"));
+ )
+ lim_ibss_set_protection(pMac, true,
+ pBeaconParams,
+ psessionEntry);
+ }
+ }
+ }
+ lim_ibss_update_protection_params(pMac, pStaDs->staAddr, protStaCacheType,
+ psessionEntry);
+ return;
+}
+
+/**
+ * lim_ibss_peer_find()
+ *
+ ***FUNCTION:
+ * This function is called while adding a context at
+ * DPH & Polaris for a peer in IBSS.
+ * If peer is found in the list, capabilities from the
+ * returned BSS description are used at DPH node & Polaris.
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ *
+ ***NOTE:
+ *
+ * @param macAddr - MAC address of the peer
+ *
+ * @return Pointer to peer node if found, else NULL
+ */
+tLimIbssPeerNode *lim_ibss_peer_find(tpAniSirGlobal pMac, tSirMacAddr macAddr)
+{
+ return ibss_peer_find(pMac, macAddr);
+}
+
+/**
+ * lim_ibss_sta_add()
+ *
+ ***FUNCTION:
+ * This function is called to add an STA context in IBSS role
+ * whenever a data frame is received from/for a STA that failed
+ * hash lookup at DPH.
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ * NA
+ *
+ ***NOTE:
+ * NA
+ *
+ * @param pMac Pointer to Global MAC structure
+ * @param peerAdddr MAC address of the peer being added
+ * @return retCode Indicates success or failure return code
+ * @return
+ */
+
+tSirRetStatus
+lim_ibss_sta_add(tpAniSirGlobal pMac, void *pBody, tpPESession psessionEntry)
+{
+ tSirRetStatus retCode = eSIR_SUCCESS;
+ tpDphHashNode pStaDs;
+ tLimIbssPeerNode *pPeerNode;
+ tLimMlmStates prevState;
+ tSirMacAddr *pPeerAddr = (tSirMacAddr *) pBody;
+ tUpdateBeaconParams beaconParams;
+
+ cdf_mem_set((uint8_t *) &beaconParams, sizeof(tUpdateBeaconParams), 0);
+
+ if (pBody == 0) {
+ PELOGE(lim_log(pMac, LOGE, FL("Invalid IBSS AddSta"));)
+ return eSIR_FAILURE;
+ }
+
+ PELOGE(lim_log(pMac, LOGE, FL("Rx Add-Ibss-Sta for MAC:"));)
+ lim_print_mac_addr(pMac, *pPeerAddr, LOGE);
+
+ pPeerNode = ibss_peer_find(pMac, *pPeerAddr);
+ if (NULL != pPeerNode) {
+ retCode =
+ ibss_dph_entry_add(pMac, *pPeerAddr, &pStaDs,
+ psessionEntry);
+ if (eSIR_SUCCESS == retCode) {
+ prevState = pStaDs->mlmStaContext.mlmState;
+ pStaDs->erpEnabled = pPeerNode->erpIePresent;
+
+ ibss_sta_info_update(pMac, pStaDs, pPeerNode,
+ psessionEntry);
+ PELOGW(lim_log
+ (pMac, LOGW,
+ FL("initiating ADD STA for the IBSS peer."));
+ )
+ retCode =
+ lim_add_sta(pMac, pStaDs, false, psessionEntry);
+ if (retCode != eSIR_SUCCESS) {
+ PELOGE(lim_log
+ (pMac, LOGE,
+ FL("ibss-sta-add failed (reason %x)"),
+ retCode);
+ )
+ lim_print_mac_addr(pMac, *pPeerAddr, LOGE);
+ pStaDs->mlmStaContext.mlmState = prevState;
+ dph_delete_hash_entry(pMac, pStaDs->staAddr,
+ pStaDs->assocId,
+ &psessionEntry->dph.
+ dphHashTable);
+ } else {
+ if (pMac->lim.gLimProtectionControl !=
+ WNI_CFG_FORCE_POLICY_PROTECTION_DISABLE)
+ lim_ibss_decide_protection(pMac, pStaDs,
+ &beaconParams,
+ psessionEntry);
+
+ if (beaconParams.paramChangeBitmap) {
+ PELOGE(lim_log
+ (pMac, LOGE,
+ FL
+ ("---> Update Beacon Params "));
+ )
+ sch_set_fixed_beacon_fields(pMac,
+ psessionEntry);
+ beaconParams.bssIdx =
+ psessionEntry->bssIdx;
+ lim_send_beacon_params(pMac, &beaconParams,
+ psessionEntry);
+ }
+ }
+ } else {
+ PELOGE(lim_log
+ (pMac, LOGE, FL("hashTblAdd failed (reason %x)"),
+ retCode);
+ )
+ lim_print_mac_addr(pMac, *pPeerAddr, LOGE);
+ }
+ } else {
+ retCode = eSIR_FAILURE;
+ }
+
+ return retCode;
+}
+
+/* handle the response from HAL for an ADD STA request */
+tSirRetStatus
+lim_ibss_add_sta_rsp(tpAniSirGlobal pMac, void *msg, tpPESession psessionEntry)
+{
+ tpDphHashNode pStaDs;
+ uint16_t peerIdx;
+ tpAddStaParams pAddStaParams = (tpAddStaParams) msg;
+
+ SET_LIM_PROCESS_DEFD_MESGS(pMac, true);
+ if (pAddStaParams == NULL) {
+ PELOGE(lim_log
+ (pMac, LOGE, FL("IBSS: ADD_STA_RSP with no body!"));
+ )
+ return eSIR_FAILURE;
+ }
+
+ pStaDs =
+ dph_lookup_hash_entry(pMac, pAddStaParams->staMac, &peerIdx,
+ &psessionEntry->dph.dphHashTable);
+ if (pStaDs == NULL) {
+ PELOGE(lim_log
+ (pMac, LOGE,
+ FL("IBSS: ADD_STA_RSP for unknown MAC addr "));
+ )
+ lim_print_mac_addr(pMac, pAddStaParams->staMac, LOGE);
+ cdf_mem_free(pAddStaParams);
+ return eSIR_FAILURE;
+ }
+
+ if (pAddStaParams->status != CDF_STATUS_SUCCESS) {
+ PELOGE(lim_log
+ (pMac, LOGE, FL("IBSS: ADD_STA_RSP error (%x) "),
+ pAddStaParams->status);
+ )
+ lim_print_mac_addr(pMac, pAddStaParams->staMac, LOGE);
+ cdf_mem_free(pAddStaParams);
+ return eSIR_FAILURE;
+ }
+
+ pStaDs->bssId = pAddStaParams->bssIdx;
+ pStaDs->staIndex = pAddStaParams->staIdx;
+ pStaDs->ucUcastSig = pAddStaParams->ucUcastSig;
+ pStaDs->ucBcastSig = pAddStaParams->ucBcastSig;
+ pStaDs->valid = 1;
+ pStaDs->mlmStaContext.mlmState = eLIM_MLM_LINK_ESTABLISHED_STATE;
+
+ PELOGW(lim_log
+ (pMac, LOGW, FL("IBSS: sending IBSS_NEW_PEER msg to SME!"));
+ )
+
+ ibss_status_chg_notify(pMac, pAddStaParams->staMac,
+ pStaDs->staIndex, pStaDs->ucUcastSig,
+ pStaDs->ucBcastSig,
+ eWNI_SME_IBSS_NEW_PEER_IND,
+ psessionEntry->smeSessionId);
+
+ cdf_mem_free(pAddStaParams);
+
+ return eSIR_SUCCESS;
+}
+
+void lim_ibss_del_bss_rsp_when_coalescing(tpAniSirGlobal pMac, void *msg,
+ tpPESession psessionEntry)
+{
+ tpDeleteBssParams pDelBss = (tpDeleteBssParams) msg;
+
+ PELOGW(lim_log
+ (pMac, LOGW, FL("IBSS: DEL_BSS_RSP Rcvd during coalescing!"));
+ )
+
+ if (pDelBss == NULL) {
+ PELOGE(lim_log
+ (pMac, LOGE,
+ FL("IBSS: DEL_BSS_RSP(coalesce) with no body!"));
+ )
+ goto end;
+ }
+
+ if (pDelBss->status != CDF_STATUS_SUCCESS) {
+ lim_log(pMac, LOGE,
+ FL("IBSS: DEL_BSS_RSP(coalesce) error (%x) Bss %d "),
+ pDelBss->status, pDelBss->bssIdx);
+ goto end;
+ }
+ /* Delete peer entries. */
+ lim_ibss_delete_all_peers(pMac, psessionEntry);
+
+ /* add the new bss */
+ ibss_bss_add(pMac, psessionEntry);
+
+end:
+ if (pDelBss != NULL)
+ cdf_mem_free(pDelBss);
+}
+
+void lim_ibss_add_bss_rsp_when_coalescing(tpAniSirGlobal pMac, void *msg,
+ tpPESession pSessionEntry)
+{
+ uint8_t infoLen;
+ tSirSmeNewBssInfo newBssInfo;
+
+ tpAddBssParams pAddBss = (tpAddBssParams) msg;
+
+ tpSirMacMgmtHdr pHdr = (tpSirMacMgmtHdr) pMac->lim.ibssInfo.pHdr;
+ tpSchBeaconStruct pBeacon =
+ (tpSchBeaconStruct) pMac->lim.ibssInfo.pBeacon;
+
+ if ((pHdr == NULL) || (pBeacon == NULL)) {
+ PELOGE(lim_log
+ (pMac, LOGE,
+ FL
+ ("Unable to handle AddBssRspWhenCoalescing (no cached BSS info)"));
+ )
+ goto end;
+ }
+ /* Inform Host of IBSS coalescing */
+ infoLen = sizeof(tSirMacAddr) + sizeof(tSirMacChanNum) +
+ sizeof(uint8_t) + pBeacon->ssId.length + 1;
+
+ cdf_mem_set((void *)&newBssInfo, sizeof(newBssInfo), 0);
+ cdf_mem_copy(newBssInfo.bssId, pHdr->bssId, sizeof(tSirMacAddr));
+ newBssInfo.channelNumber = (tSirMacChanNum) pAddBss->currentOperChannel;
+ cdf_mem_copy((uint8_t *) &newBssInfo.ssId,
+ (uint8_t *) &pBeacon->ssId, pBeacon->ssId.length + 1);
+
+ PELOGW(lim_log
+ (pMac, LOGW, FL("Sending JOINED_NEW_BSS notification to SME."));
+ )
+
+ lim_send_sme_wm_status_change_ntf(pMac, eSIR_SME_JOINED_NEW_BSS,
+ (uint32_t *) &newBssInfo,
+ infoLen, pSessionEntry->smeSessionId);
+ {
+ /* Configure beacon and send beacons to HAL */
+ lim_send_beacon_ind(pMac, pSessionEntry);
+ }
+
+end:
+ ibss_coalesce_free(pMac);
+}
+
+void lim_ibss_del_bss_rsp(tpAniSirGlobal pMac, void *msg, tpPESession psessionEntry)
+{
+ tSirResultCodes rc = eSIR_SME_SUCCESS;
+ tpDeleteBssParams pDelBss = (tpDeleteBssParams) msg;
+ tSirMacAddr nullBssid = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+ SET_LIM_PROCESS_DEFD_MESGS(pMac, true);
+ if (pDelBss == NULL) {
+ PELOGE(lim_log
+ (pMac, LOGE, FL("IBSS: DEL_BSS_RSP with no body!"));
+ )
+ rc = eSIR_SME_REFUSED;
+ goto end;
+ }
+
+ psessionEntry = pe_find_session_by_session_id(pMac, pDelBss->sessionId);
+ if (psessionEntry == NULL) {
+ lim_log(pMac, LOGP,
+ FL("Session Does not exist for given sessionID"));
+ goto end;
+ }
+
+ /*
+ * If delBss was issued as part of IBSS Coalescing, gLimIbssCoalescingHappened flag will be true.
+ * BSS has to be added again in this scenario, so this case needs to be handled separately.
+ * If delBss was issued as a result of trigger from SME_STOP_BSS Request, then limSme state changes to
+ * 'IDLE' and gLimIbssCoalescingHappened flag will be false. In this case STOP BSS RSP has to be sent to SME.
+ */
+ if (true == pMac->lim.gLimIbssCoalescingHappened) {
+
+ lim_ibss_del_bss_rsp_when_coalescing(pMac, msg, psessionEntry);
+ return;
+ }
+
+ if (pDelBss->status != CDF_STATUS_SUCCESS) {
+ PELOGE(lim_log
+ (pMac, LOGE, FL("IBSS: DEL_BSS_RSP error (%x) Bss %d "),
+ pDelBss->status, pDelBss->bssIdx);
+ )
+ rc = eSIR_SME_STOP_BSS_FAILURE;
+ goto end;
+ }
+
+ if (lim_set_link_state(pMac, eSIR_LINK_IDLE_STATE, nullBssid,
+ psessionEntry->selfMacAddr, NULL,
+ NULL) != eSIR_SUCCESS) {
+ PELOGE(lim_log
+ (pMac, LOGE,
+ FL("IBSS: DEL_BSS_RSP setLinkState failed"));
+ )
+ rc = eSIR_SME_REFUSED;
+ goto end;
+ }
+
+ lim_ibss_delete(pMac, psessionEntry);
+
+ dph_hash_table_class_init(pMac, &psessionEntry->dph.dphHashTable);
+ lim_delete_pre_auth_list(pMac);
+
+ psessionEntry->limMlmState = eLIM_MLM_IDLE_STATE;
+
+ MTRACE(mac_trace
+ (pMac, TRACE_CODE_MLM_STATE, psessionEntry->peSessionId,
+ psessionEntry->limMlmState));
+
+ psessionEntry->limSystemRole = eLIM_STA_ROLE;
+
+ /* Change the short slot operating mode to Default (which is 1 for now) so that when IBSS starts next time with Libra
+ * as originator, it picks up the default. This enables us to remove hard coding of short slot = 1 from lim_apply_configuration
+ */
+ psessionEntry->shortSlotTimeSupported = WNI_CFG_SHORT_SLOT_TIME_STADEF;
+
+end:
+ if (pDelBss != NULL)
+ cdf_mem_free(pDelBss);
+ /* Delete PE session once BSS is deleted */
+ if (NULL != psessionEntry) {
+ lim_send_sme_rsp(pMac, eWNI_SME_STOP_BSS_RSP, rc,
+ psessionEntry->smeSessionId,
+ psessionEntry->transactionId);
+ pe_delete_session(pMac, psessionEntry);
+ psessionEntry = NULL;
+ }
+}
+
+static void
+__lim_ibss_search_and_delete_peer(tpAniSirGlobal pMac,
+ tpPESession psessionEntry, tSirMacAddr macAddr)
+{
+ tLimIbssPeerNode *pTempNode, *pPrevNode;
+ tLimIbssPeerNode *pTempNextNode = NULL;
+ tpDphHashNode pStaDs = NULL;
+ uint16_t peerIdx = 0;
+ uint16_t staIndex = 0;
+ uint8_t ucUcastSig;
+ uint8_t ucBcastSig;
+
+ pPrevNode = pTempNode = pMac->lim.gLimIbssPeerList;
+
+ lim_log(pMac, LOG1, FL(" PEER ADDR :" MAC_ADDRESS_STR),
+ MAC_ADDR_ARRAY(macAddr));
+
+ /** Compare Peer */
+ while (NULL != pTempNode) {
+ pTempNextNode = pTempNode->next;
+
+ /* Delete the STA with MAC address */
+ if (cdf_mem_compare((uint8_t *) macAddr,
+ (uint8_t *) &pTempNode->peerMacAddr,
+ sizeof(tSirMacAddr))) {
+ pStaDs = dph_lookup_hash_entry(pMac, macAddr,
+ &peerIdx,
+ &psessionEntry->dph.
+ dphHashTable);
+ if (pStaDs) {
+ staIndex = pStaDs->staIndex;
+ ucUcastSig = pStaDs->ucUcastSig;
+ ucBcastSig = pStaDs->ucBcastSig;
+
+ (void)lim_del_sta(pMac, pStaDs,
+ false /*asynchronous */,
+ psessionEntry);
+ lim_delete_dph_hash_entry(pMac, pStaDs->staAddr,
+ peerIdx, psessionEntry);
+ lim_release_peer_idx(pMac, peerIdx, psessionEntry);
+
+ /* Send indication to upper layers */
+ ibss_status_chg_notify(pMac, macAddr, staIndex,
+ ucUcastSig, ucBcastSig,
+ eWNI_SME_IBSS_PEER_DEPARTED_IND,
+ psessionEntry->
+ smeSessionId);
+ if (pTempNode == pMac->lim.gLimIbssPeerList) {
+ pMac->lim.gLimIbssPeerList =
+ pTempNode->next;
+ pPrevNode = pMac->lim.gLimIbssPeerList;
+ } else
+ pPrevNode->next = pTempNode->next;
+
+ cdf_mem_free(pTempNode);
+ pMac->lim.gLimNumIbssPeers--;
+
+ pTempNode = pTempNextNode;
+ break;
+ }
+ }
+ pPrevNode = pTempNode;
+ pTempNode = pTempNextNode;
+ }
+ /*
+ * if it is the last peer walking out, we better
+ * we set IBSS state to inactive.
+ */
+ if (0 == pMac->lim.gLimNumIbssPeers) {
+ CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_INFO,
+ "Last STA from IBSS walked out");
+ psessionEntry->limIbssActive = false;
+ }
+}
+
+/**
+ * lim_ibss_coalesce()
+ *
+ ***FUNCTION:
+ * This function is called upon receiving Beacon/Probe Response
+ * while operating in IBSS mode.
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ *
+ ***NOTE:
+ *
+ * @param pMac - Pointer to Global MAC structure
+ * @param pBeacon - Parsed Beacon Frame structure
+ * @param pBD - Pointer to received BD
+ *
+ * @return Status whether to process or ignore received Beacon Frame
+ */
+
+tSirRetStatus
+lim_ibss_coalesce(tpAniSirGlobal pMac,
+ tpSirMacMgmtHdr pHdr,
+ tpSchBeaconStruct pBeacon,
+ uint8_t *pIEs,
+ uint32_t ieLen, uint16_t fTsfLater, tpPESession psessionEntry)
+{
+ uint16_t peerIdx;
+ tSirMacAddr currentBssId;
+ tLimIbssPeerNode *pPeerNode;
+ tpDphHashNode pStaDs;
+ tUpdateBeaconParams beaconParams;
+
+ cdf_mem_set((uint8_t *) &beaconParams, sizeof(tUpdateBeaconParams), 0);
+
+ sir_copy_mac_addr(currentBssId, psessionEntry->bssId);
+
+ lim_log(pMac, LOG1,
+ FL("Current BSSID :" MAC_ADDRESS_STR " Received BSSID :"
+ MAC_ADDRESS_STR), MAC_ADDR_ARRAY(currentBssId),
+ MAC_ADDR_ARRAY(pHdr->bssId));
+
+ /* Check for IBSS Coalescing only if Beacon is from different BSS */
+ if (!cdf_mem_compare(currentBssId, pHdr->bssId, sizeof(tSirMacAddr))
+ && psessionEntry->isCoalesingInIBSSAllowed) {
+ /*
+ * If STA entry is already available in the LIM hash table, then it is
+ * possible that the peer may have left and rejoined within the heartbeat
+ * timeout. In the offloaded case with 32 peers, the HB timeout is whopping
+ * 128 seconds. In that case, the FW will not let any frames come in until
+ * atleast the last sequence number is received before the peer is left
+ * Hence, if the coalescing peer is already there in the peer list and if
+ * the BSSID matches then, invoke delSta() to cleanup the entries. We will
+ * let the peer coalesce when we receive next beacon from the peer
+ */
+ pPeerNode = ibss_peer_find(pMac, pHdr->sa);
+ if (NULL != pPeerNode) {
+ __lim_ibss_search_and_delete_peer(pMac, psessionEntry,
+ pHdr->sa);
+ PELOGW(lim_log
+ (pMac, LOGW,
+ FL
+ ("** Peer attempting to reconnect before HB timeout, deleted **"));
+ )
+ return eSIR_LIM_IGNORE_BEACON;
+ }
+
+ if (!fTsfLater) { /* No Coalescing happened. */
+ PELOGW(lim_log(pMac, LOGW, FL("No Coalescing happened"));)
+ return eSIR_LIM_IGNORE_BEACON;
+ }
+ /*
+ * IBSS Coalescing happened.
+ * save the received beacon, and delete the current BSS. The rest of the
+ * processing will be done in the delBss response processing
+ */
+ pMac->lim.gLimIbssCoalescingHappened = true;
+ PELOGW(lim_log(pMac, LOGW, FL("IBSS Coalescing happened"));)
+ ibss_coalesce_save(pMac, pHdr, pBeacon);
+ lim_log(pMac, LOGW, FL("Delete BSSID :" MAC_ADDRESS_STR),
+ MAC_ADDR_ARRAY(currentBssId));
+ ibss_bss_delete(pMac, psessionEntry);
+ return eSIR_SUCCESS;
+ } else {
+ if (!cdf_mem_compare
+ (currentBssId, pHdr->bssId, sizeof(tSirMacAddr)))
+ return eSIR_LIM_IGNORE_BEACON;
+ }
+
+ /* STA in IBSS mode and SSID matches with ours */
+ pPeerNode = ibss_peer_find(pMac, pHdr->sa);
+ if (pPeerNode == NULL) {
+ /* Peer not in the list - Collect BSS description & add to the list */
+ uint32_t frameLen;
+ tSirRetStatus retCode;
+
+ /*
+ * Limit the Max number of IBSS Peers allowed as the max
+ * number of STA's allowed
+ * pMac->lim.gLimNumIbssPeers will be increamented after exiting
+ * this function. so we will add additional 1 to compare against
+ * pMac->lim.gLimIbssStaLimit
+ */
+ if ((pMac->lim.gLimNumIbssPeers + 1) >=
+ pMac->lim.gLimIbssStaLimit) {
+ /*Print every 100th time */
+ if (pMac->lim.ibss_retry_cnt % 100 == 0) {
+ PELOGE(lim_log(pMac, LOG1,
+ FL("**** MAX STA LIMIT HAS REACHED ****"));)
+ }
+ pMac->lim.ibss_retry_cnt++;
+ return eSIR_LIM_MAX_STA_REACHED_ERROR;
+ }
+ PELOGW(lim_log
+ (pMac, LOGW,
+ FL("IBSS Peer node does not exist, adding it***"));
+ )
+ frameLen =
+ sizeof(tLimIbssPeerNode) + ieLen - sizeof(uint32_t);
+
+ pPeerNode = cdf_mem_malloc((uint16_t) frameLen);
+ if (NULL == pPeerNode) {
+ lim_log(pMac, LOGP,
+ FL
+ ("alloc fail (%d bytes) storing IBSS peer info"),
+ frameLen);
+ return eSIR_MEM_ALLOC_FAILED;
+ }
+
+ pPeerNode->beacon = NULL;
+ pPeerNode->beaconLen = 0;
+
+ ibss_peer_collect(pMac, pBeacon, pHdr, pPeerNode,
+ psessionEntry);
+ pPeerNode->beacon = cdf_mem_malloc(ieLen);
+ if (NULL == pPeerNode->beacon) {
+ PELOGE(lim_log
+ (pMac, LOGE,
+ FL
+ ("Unable to allocate memory to store beacon"));
+ )
+ } else {
+ cdf_mem_copy(pPeerNode->beacon, pIEs, ieLen);
+ pPeerNode->beaconLen = (uint16_t) ieLen;
+ }
+ ibss_peer_add(pMac, pPeerNode);
+
+ pStaDs =
+ dph_lookup_hash_entry(pMac, pPeerNode->peerMacAddr, &peerIdx,
+ &psessionEntry->dph.dphHashTable);
+ if (pStaDs != NULL) {
+ /* / DPH node already exists for the peer */
+ PELOGW(lim_log
+ (pMac, LOGW,
+ FL("DPH Node present for just learned peer"));
+ )
+ PELOG1(lim_print_mac_addr
+ (pMac, pPeerNode->peerMacAddr, LOG1);
+ )
+ ibss_sta_info_update(pMac, pStaDs, pPeerNode,
+ psessionEntry);
+ return eSIR_SUCCESS;
+ }
+ retCode =
+ lim_ibss_sta_add(pMac, pPeerNode->peerMacAddr, psessionEntry);
+ if (retCode != eSIR_SUCCESS) {
+ PELOGE(lim_log
+ (pMac, LOGE,
+ FL("lim-ibss-sta-add failed (reason %x)"),
+ retCode);
+ )
+ lim_print_mac_addr(pMac, pPeerNode->peerMacAddr, LOGE);
+ return retCode;
+ }
+ /* Decide protection mode */
+ pStaDs =
+ dph_lookup_hash_entry(pMac, pPeerNode->peerMacAddr, &peerIdx,
+ &psessionEntry->dph.dphHashTable);
+ if (pMac->lim.gLimProtectionControl !=
+ WNI_CFG_FORCE_POLICY_PROTECTION_DISABLE)
+ lim_ibss_decide_protection(pMac, pStaDs, &beaconParams,
+ psessionEntry);
+
+ if (beaconParams.paramChangeBitmap) {
+ PELOGE(lim_log
+ (pMac, LOGE,
+ FL
+ ("beaconParams.paramChangeBitmap=1 ---> Update Beacon Params "));
+ )
+ sch_set_fixed_beacon_fields(pMac, psessionEntry);
+ beaconParams.bssIdx = psessionEntry->bssIdx;
+ lim_send_beacon_params(pMac, &beaconParams, psessionEntry);
+ }
+ } else
+ ibss_sta_caps_update(pMac, pPeerNode, psessionEntry);
+
+ if (psessionEntry->limSmeState != eLIM_SME_NORMAL_STATE)
+ return eSIR_SUCCESS;
+
+ /* Received Beacon from same IBSS we're */
+ /* currently part of. Inform Roaming algorithm */
+ /* if not already that IBSS is active. */
+ if (psessionEntry->limIbssActive == false) {
+ limResetHBPktCount(psessionEntry);
+ PELOGW(lim_log
+ (pMac, LOGW,
+ FL
+ ("Partner joined our IBSS, Sending IBSS_ACTIVE Notification to SME"));
+ )
+ psessionEntry->limIbssActive = true;
+ lim_send_sme_wm_status_change_ntf(pMac, eSIR_SME_IBSS_ACTIVE, NULL, 0,
+ psessionEntry->smeSessionId);
+ }
+
+ return eSIR_SUCCESS;
+} /*** end lim_handle_ibs_scoalescing() ***/
+
+/**
+ * lim_ibss_heart_beat_handle() - handle IBSS hearbeat failure
+ *
+ * @mac_ctx: global mac context
+ * @session: PE session entry
+ *
+ * Hanlde IBSS hearbeat failure.
+ *
+ * Return: None.
+ */
+void lim_ibss_heart_beat_handle(tpAniSirGlobal mac_ctx, tpPESession session)
+{
+ tLimIbssPeerNode *tempnode, *prevnode;
+ tLimIbssPeerNode *temp_next = NULL;
+ uint16_t peer_idx = 0;
+ tpDphHashNode stads = 0;
+ uint32_t threshold = 0;
+ uint16_t sta_idx = 0;
+ uint8_t ucast_sig = 0;
+ uint8_t bcast_sig = 0;
+
+ /*
+ * MLM BSS is started and if PE in scanmode then MLM state will be
+ * waiting for probe resp. If Heart beat timeout triggers during this
+ * corner case then we need to reactivate HeartBeat timer.
+ */
+ if (session->limMlmState != eLIM_MLM_BSS_STARTED_STATE)
+ return;
+
+ /* If LinkMonitor is Disabled */
+ if (!mac_ctx->sys.gSysEnableLinkMonitorMode)
+ return;
+
+ prevnode = tempnode = mac_ctx->lim.gLimIbssPeerList;
+ threshold = (mac_ctx->lim.gLimNumIbssPeers / 4) + 1;
+
+ /* Monitor the HeartBeat with the Individual PEERS in the IBSS */
+ while (tempnode != NULL) {
+ temp_next = tempnode->next;
+ if (tempnode->beaconHBCount) {
+ /* There was a beacon for this peer during heart beat */
+ tempnode->beaconHBCount = 0;
+ tempnode->heartbeatFailure = 0;
+ prevnode = tempnode;
+ tempnode = temp_next;
+ continue;
+ }
+
+ /* There wasnt any beacon received during heartbeat timer. */
+ tempnode->heartbeatFailure++;
+ lim_log(mac_ctx, LOGE, FL("Heartbeat fail = %d thres = %d"),
+ tempnode->heartbeatFailure, mac_ctx->lim.gLimNumIbssPeers);
+ if (tempnode->heartbeatFailure >= threshold) {
+ /* Remove this entry from the list. */
+ stads = dph_lookup_hash_entry(mac_ctx,
+ tempnode->peerMacAddr, &peer_idx,
+ &session->dph.dphHashTable);
+ if (stads) {
+ sta_idx = stads->staIndex;
+ ucast_sig = stads->ucUcastSig;
+ bcast_sig = stads->ucBcastSig;
+
+ (void)lim_del_sta(mac_ctx, stads, false,
+ session);
+ lim_delete_dph_hash_entry(mac_ctx,
+ stads->staAddr, peer_idx, session);
+ lim_release_peer_idx(mac_ctx, peer_idx,
+ session);
+ /* Send indication. */
+ ibss_status_chg_notify(mac_ctx,
+ tempnode->peerMacAddr, sta_idx,
+ ucast_sig, bcast_sig,
+ eWNI_SME_IBSS_PEER_DEPARTED_IND,
+ session->smeSessionId);
+ }
+ if (tempnode == mac_ctx->lim.gLimIbssPeerList) {
+ mac_ctx->lim.gLimIbssPeerList = tempnode->next;
+ prevnode = mac_ctx->lim.gLimIbssPeerList;
+ } else {
+ prevnode->next = tempnode->next;
+ }
+
+ cdf_mem_free(tempnode);
+ mac_ctx->lim.gLimNumIbssPeers--;
+
+ /* we deleted current node, so prevNode remains same. */
+ tempnode = temp_next;
+ continue;
+ }
+ prevnode = tempnode;
+ tempnode = temp_next;
+ }
+
+ /*
+ * General IBSS Activity Monitor,
+ * check if in IBSS Mode we are received any Beacons
+ */
+ if (mac_ctx->lim.gLimNumIbssPeers) {
+ if (session->LimRxedBeaconCntDuringHB <
+ MAX_NO_BEACONS_PER_HEART_BEAT_INTERVAL)
+ mac_ctx->lim.gLimHeartBeatBeaconStats[
+ session->LimRxedBeaconCntDuringHB]++;
+ else
+ mac_ctx->lim.gLimHeartBeatBeaconStats[0]++;
+
+ /* Reset number of beacons received */
+ limResetHBPktCount(session);
+ return;
+ } else {
+ lim_log(mac_ctx, LOGW, FL("Heartbeat Failure"));
+ mac_ctx->lim.gLimHBfailureCntInLinkEstState++;
+
+ if (session->limIbssActive == true) {
+ /*
+ * We don't receive Beacon frames from any
+ * other STA in IBSS. Announce IBSS inactive
+ * to Roaming algorithm
+ */
+ lim_log(mac_ctx, LOGW, FL("Alone in IBSS"));
+ session->limIbssActive = false;
+
+ lim_send_sme_wm_status_change_ntf(mac_ctx,
+ eSIR_SME_IBSS_INACTIVE, NULL, 0,
+ session->smeSessionId);
+ }
+ }
+}
+
+/**
+ * lim_ibss_decide_protection_on_delete() - decides protection related info.
+ *
+ * @mac_ctx: global mac context
+ * @stads: station hash node
+ * @bcn_param: beacon parameters
+ * @session: PE session entry
+ *
+ * Decides all the protection related information.
+ *
+ * Return: None
+ */
+void lim_ibss_decide_protection_on_delete(tpAniSirGlobal mac_ctx,
+ tpDphHashNode stads,
+ tpUpdateBeaconParams bcn_param,
+ tpPESession session)
+{
+ uint32_t phymode;
+ tHalBitVal erpenabled = eHAL_CLEAR;
+ tSirRFBand rfband = SIR_BAND_UNKNOWN;
+ uint32_t i;
+
+ if (NULL == stads)
+ return;
+
+ lim_get_rf_band_new(mac_ctx, &rfband, session);
+ if (SIR_BAND_2_4_GHZ != rfband)
+ return;
+
+ lim_get_phy_mode(mac_ctx, &phymode, session);
+ erpenabled = stads->erpEnabled;
+ /* we are HT or 11G and 11B station is getting deleted. */
+ if (((phymode == WNI_CFG_PHY_MODE_11G) ||
+ session->htCapability) && (erpenabled == eHAL_CLEAR)) {
+ lim_log(mac_ctx, LOGE,
+ FL("(%d) A legacy STA is disassociated. Addr is "),
+ session->gLim11bParams.numSta);
+ lim_print_mac_addr(mac_ctx, stads->staAddr, LOGE);
+ if (session->gLim11bParams.numSta == 0) {
+ lim_log(mac_ctx, LOGE,
+ FL("No 11B STA exists. Disable protection."));
+ lim_ibss_set_protection(mac_ctx, false,
+ bcn_param, session);
+ }
+
+ for (i = 0; i < LIM_PROT_STA_CACHE_SIZE; i++) {
+ if (!mac_ctx->lim.protStaCache[i].active)
+ continue;
+ if (cdf_mem_compare(mac_ctx->lim.protStaCache[i].addr,
+ stads->staAddr, sizeof(tSirMacAddr))) {
+ session->gLim11bParams.numSta--;
+ mac_ctx->lim.protStaCache[i].active = false;
+ break;
+ }
+ }
+
+ }
+}
+
+/** -----------------------------------------------------------------
+ \fn __lim_ibss_peer_inactivity_handler
+ \brief Internal function. Deletes FW indicated peer which is inactive
+ \
+ \param tpAniSirGlobal pMac
+ \param tpPESession psessionEntry
+ \param tpSirIbssPeerInactivityInd peerInactivityInd
+ \return None
+ -----------------------------------------------------------------*/
+static void
+__lim_ibss_peer_inactivity_handler(tpAniSirGlobal pMac,
+ tpPESession psessionEntry,
+ tpSirIbssPeerInactivityInd peerInactivityInd)
+{
+ if (psessionEntry->limMlmState != eLIM_MLM_BSS_STARTED_STATE) {
+ return;
+ }
+
+ /* delete the peer for which heartbeat is observed */
+ __lim_ibss_search_and_delete_peer(pMac, psessionEntry,
+ peerInactivityInd->peerAddr);
+
+}
+
+/** -------------------------------------------------------------
+ \fn lim_process_ibss_peer_inactivity
+ \brief Peer inactivity message handler
+ \
+ \param tpAniSirGlobal pMac
+ \param void* buf
+ \return None
+ -------------------------------------------------------------*/
+void lim_process_ibss_peer_inactivity(tpAniSirGlobal pMac, void *buf)
+{
+ /*
+ * --------------- HEARTBEAT OFFLOAD CASE ------------------
+ * This message handler is executed when the firmware identifies
+ * inactivity from one or more peer devices. We will come here
+ * for every inactive peer device
+ */
+ uint8_t i;
+
+ tSirIbssPeerInactivityInd *peerInactivityInd =
+ (tSirIbssPeerInactivityInd *) buf;
+
+ /*
+ * If IBSS is not started or heartbeat offload is not enabled
+ * we should not handle this request
+ */
+ if (eLIM_STA_IN_IBSS_ROLE != pMac->lim.gLimSystemRole &&
+ !IS_IBSS_HEARTBEAT_OFFLOAD_FEATURE_ENABLE) {
+ return;
+ }
+
+ /** If LinkMonitor is Disabled */
+ if (!pMac->sys.gSysEnableLinkMonitorMode) {
+ return;
+ }
+
+ for (i = 0; i < pMac->lim.maxBssId; i++) {
+ if (true == pMac->lim.gpSession[i].valid &&
+ eSIR_IBSS_MODE == pMac->lim.gpSession[i].bssType) {
+ __lim_ibss_peer_inactivity_handler(pMac,
+ &pMac->lim.gpSession[i],
+ peerInactivityInd);
+ break;
+ }
+ }
+}
diff --git a/core/mac/src/pe/lim/lim_ibss_peer_mgmt.h b/core/mac/src/pe/lim/lim_ibss_peer_mgmt.h
new file mode 100644
index 0000000..0c97919
--- /dev/null
+++ b/core/mac/src/pe/lim/lim_ibss_peer_mgmt.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2011-2012, 2014 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_ibss_peer_mgmt.h contains prototypes for
+ * the utility functions LIM uses to maintain peers in IBSS.
+ * Author: Chandra Modumudi
+ * Date: 03/12/04
+ * History:-
+ * Date Modified by Modification Information
+ * --------------------------------------------------------------------
+ */
+
+#include "sir_common.h"
+#include "lim_utils.h"
+
+#define IBSS_STATIONS_USED_DURING_INIT 4 /* (broadcast + self + p2p + softap) */
+
+void lim_ibss_init(tpAniSirGlobal);
+void lim_ibss_delete(tpAniSirGlobal, tpPESession psessionEntry);
+tSirRetStatus lim_ibss_coalesce(tpAniSirGlobal, tpSirMacMgmtHdr,
+ tpSchBeaconStruct, uint8_t *, uint32_t, uint16_t,
+ tpPESession);
+tSirRetStatus lim_ibss_sta_add(tpAniSirGlobal, void *, tpPESession);
+tSirRetStatus lim_ibss_add_sta_rsp(tpAniSirGlobal, void *, tpPESession);
+tLimIbssPeerNode *lim_ibss_peer_find(tpAniSirGlobal pMac, tSirMacAddr macAddr);
+void lim_ibss_del_bss_rsp(tpAniSirGlobal, void *, tpPESession);
+void lim_ibss_del_bss_rsp_when_coalescing(tpAniSirGlobal, void *, tpPESession);
+void lim_ibss_add_bss_rsp_when_coalescing(tpAniSirGlobal pMac, void *msg,
+ tpPESession pSessionEntry);
+void lim_ibss_decide_protection_on_delete(tpAniSirGlobal pMac, tpDphHashNode pStaDs,
+ tpUpdateBeaconParams pBeaconParams,
+ tpPESession pSessionEntry);
+void lim_ibss_heart_beat_handle(tpAniSirGlobal pMac, tpPESession psessionEntry);
+void lim_process_ibss_peer_inactivity(tpAniSirGlobal pMac, void *buf);
diff --git a/core/mac/src/pe/lim/lim_link_monitoring_algo.c b/core/mac/src/pe/lim/lim_link_monitoring_algo.c
new file mode 100644
index 0000000..2ce55b0
--- /dev/null
+++ b/core/mac/src/pe/lim/lim_link_monitoring_algo.c
@@ -0,0 +1,561 @@
+/*
+ * Copyright (c) 2012-2015 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_link_monitoring_algo.cc contains the code for
+ * Link monitoring algorithm on AP and heart beat failure
+ * handling on STA.
+ * Author: Chandra Modumudi
+ * Date: 03/01/02
+ * History:-
+ * Date Modified by Modification Information
+ * --------------------------------------------------------------------
+ *
+ */
+
+#include "ani_global.h"
+#include "wni_cfg.h"
+#include "cfg_api.h"
+
+#include "sch_api.h"
+#include "utils_api.h"
+#include "lim_assoc_utils.h"
+#include "lim_types.h"
+#include "lim_utils.h"
+#include "lim_prop_exts_utils.h"
+
+#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */
+#include "host_diag_core_log.h"
+#endif /* FEATURE_WLAN_DIAG_SUPPORT */
+#ifdef WLAN_FEATURE_VOWIFI_11R
+#include "lim_ft_defs.h"
+#endif
+#include "lim_session.h"
+#include "lim_ser_des_utils.h"
+
+/**
+ * lim_delete_sta_util - utility function for deleting station context
+ *
+ * @mac_ctx: global MAC context
+ * @msg: pointer to delte station context
+ * @session_entry: PE session entry
+ *
+ * utility function called to clear up station context.
+ *
+ * Return: None.
+ */
+static void lim_delete_sta_util(tpAniSirGlobal mac_ctx, tpDeleteStaContext msg,
+ tpPESession session_entry)
+{
+ tpDphHashNode stads;
+
+ lim_log(mac_ctx, LOGE,
+ FL("Deleting station: staId = %d, reasonCode = %d"),
+ msg->staId, msg->reasonCode);
+
+ if (LIM_IS_IBSS_ROLE(session_entry)) {
+ cdf_mem_free(msg);
+ return;
+ }
+
+ stads = dph_lookup_assoc_id(mac_ctx, msg->staId, &msg->assocId,
+ &session_entry->dph.dphHashTable);
+
+ if (!stads) {
+ lim_log(mac_ctx, LOGE,
+ FL("Invalid STA limSystemRole=%d"),
+ GET_LIM_SYSTEM_ROLE(session_entry));
+ cdf_mem_free(msg);
+ return;
+ }
+
+ /* check and see if same staId. This is to avoid the scenario
+ * where we're trying to delete a staId we just added.
+ */
+ if (stads->staIndex != msg->staId) {
+ lim_log(mac_ctx, LOGE, FL("staid mismatch: %d vs %d "),
+ stads->staIndex, msg->staId);
+ cdf_mem_free(msg);
+ return;
+ }
+
+ if (LIM_IS_BT_AMP_AP_ROLE(session_entry) ||
+ LIM_IS_AP_ROLE(session_entry)) {
+ lim_log(mac_ctx, LOG1,
+ FL("Delete Station staId: %d, assocId: %d"),
+ msg->staId, msg->assocId);
+ /*
+ * Check if Deauth/Disassoc is triggered from Host.
+ * If mlmState is in some transient state then
+ * don't trigger STA deletion to avoid the race
+ * condition.
+ */
+ if ((stads &&
+ ((stads->mlmStaContext.mlmState !=
+ eLIM_MLM_LINK_ESTABLISHED_STATE) &&
+ (stads->mlmStaContext.mlmState !=
+ eLIM_MLM_WT_ASSOC_CNF_STATE) &&
+ (stads->mlmStaContext.mlmState !=
+ eLIM_MLM_ASSOCIATED_STATE)))) {
+ lim_log(mac_ctx, LOGE,
+ FL("Inv Del STA staId:%d, assocId:%d"),
+ msg->staId, msg->assocId);
+ cdf_mem_free(msg);
+ return;
+ } else {
+ lim_trigger_sta_deletion(mac_ctx, stads, session_entry);
+ }
+ } else {
+#ifdef FEATURE_WLAN_TDLS
+ if (LIM_IS_STA_ROLE(session_entry) &&
+ STA_ENTRY_TDLS_PEER == stads->staType) {
+ /*
+ * TeardownLink with PEER reason code
+ * HAL_DEL_STA_REASON_CODE_KEEP_ALIVE means
+ * eSIR_MAC_TDLS_TEARDOWN_PEER_UNREACHABLE
+ */
+ lim_send_sme_tdls_del_sta_ind(mac_ctx, stads,
+ session_entry,
+ eSIR_MAC_TDLS_TEARDOWN_PEER_UNREACHABLE);
+ } else {
+#endif
+ /* TearDownLink with AP */
+ tLimMlmDeauthInd mlm_deauth_ind;
+ lim_log(mac_ctx, LOGW,
+ FL("Delete Station (staId: %d, assocId: %d) "),
+ msg->staId, msg->assocId);
+
+ if ((stads &&
+ ((stads->mlmStaContext.mlmState !=
+ eLIM_MLM_LINK_ESTABLISHED_STATE) &&
+ (stads->mlmStaContext.mlmState !=
+ eLIM_MLM_WT_ASSOC_CNF_STATE) &&
+ (stads->mlmStaContext.mlmState !=
+ eLIM_MLM_ASSOCIATED_STATE)))) {
+
+ /*
+ * Received SIR_LIM_DELETE_STA_CONTEXT_IND for STA that
+ * does not have context or in some transit state.
+ * Log error
+ */
+ lim_log(mac_ctx, LOGE,
+ FL("Received SIR_LIM_DELETE_STA_CONTEXT_IND for "
+ "STA that either has no context or "
+ "in some transit state, Addr = "
+ MAC_ADDRESS_STR),
+ MAC_ADDR_ARRAY(msg->bssId));
+ cdf_mem_free(msg);
+ return;
+ }
+
+ stads->mlmStaContext.disassocReason =
+ eSIR_MAC_DISASSOC_DUE_TO_INACTIVITY_REASON;
+ stads->mlmStaContext.cleanupTrigger =
+ eLIM_LINK_MONITORING_DEAUTH;
+
+ /* Issue Deauth Indication to SME. */
+ cdf_mem_copy((uint8_t *) &mlm_deauth_ind.peerMacAddr,
+ stads->staAddr, sizeof(tSirMacAddr));
+ mlm_deauth_ind.reasonCode =
+ (uint8_t) stads->mlmStaContext.disassocReason;
+ mlm_deauth_ind.deauthTrigger =
+ stads->mlmStaContext.cleanupTrigger;
+
+#ifdef FEATURE_WLAN_TDLS
+ /* Delete all TDLS peers connected before leaving BSS */
+ lim_delete_tdls_peers(mac_ctx, session_entry);
+#endif
+ lim_post_sme_message(mac_ctx, LIM_MLM_DEAUTH_IND,
+ (uint32_t *) &mlm_deauth_ind);
+
+ lim_send_sme_deauth_ind(mac_ctx, stads, session_entry);
+#ifdef FEATURE_WLAN_TDLS
+ }
+#endif
+ }
+}
+
+/**
+ * lim_delete_sta_context() - delete sta context.
+ *
+ * @mac_ctx: global mac_ctx context
+ * @lim_msg: lim message.
+ *
+ * This function handles the message from HAL: WMA_DELETE_STA_CONTEXT_IND.
+ * This function validates that the given station id exist, and if so,
+ * deletes the station by calling lim_trigger_sta_deletion.
+ *
+ * Return: none
+ */
+void lim_delete_sta_context(tpAniSirGlobal mac_ctx, tpSirMsgQ lim_msg)
+{
+ tpDeleteStaContext msg = (tpDeleteStaContext) lim_msg->bodyptr;
+ tpPESession session_entry;
+ uint8_t session_id;
+
+ if (NULL == msg) {
+ lim_log(mac_ctx, LOGE, FL("Invalid body pointer in message"));
+ return;
+ }
+ session_entry = pe_find_session_by_bssid(mac_ctx, msg->bssId,
+ &session_id);
+ if (NULL == session_entry) {
+ lim_log(mac_ctx, LOGE, FL("session does not exist"));
+ cdf_mem_free(msg);
+ return;
+ }
+
+ switch (msg->reasonCode) {
+ case HAL_DEL_STA_REASON_CODE_KEEP_ALIVE:
+ case HAL_DEL_STA_REASON_CODE_TIM_BASED:
+ lim_delete_sta_util(mac_ctx, msg, session_entry);
+ break;
+
+ case HAL_DEL_STA_REASON_CODE_UNKNOWN_A2:
+ lim_log(mac_ctx, LOGE, FL("Deleting Unknown station "));
+ lim_print_mac_addr(mac_ctx, msg->addr2, LOGE);
+ lim_send_deauth_mgmt_frame(mac_ctx,
+ eSIR_MAC_CLASS3_FRAME_FROM_NON_ASSOC_STA_REASON,
+ msg->addr2, session_entry, false);
+ break;
+
+ default:
+ lim_log(mac_ctx, LOGE, FL(" Unknown reason code "));
+ break;
+ }
+ cdf_mem_free(msg);
+ return;
+}
+
+/**
+ * lim_trigger_sta_deletion()
+ *
+ ***FUNCTION:
+ * This function is called to trigger STA context deletion
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ *
+ ***NOTE:
+ * NA
+ *
+ * @param pMac - Pointer to global MAC structure
+ * @param pStaDs - Pointer to internal STA Datastructure
+ * @return None
+ */
+void
+lim_trigger_sta_deletion(tpAniSirGlobal pMac, tpDphHashNode pStaDs,
+ tpPESession psessionEntry)
+{
+ tSirSmeDeauthReq *pSmeDeauthReq;
+ uint8_t *pBuf;
+ uint8_t *pLen;
+ uint16_t msgLength = 0;
+
+ if (!pStaDs) {
+ PELOGW(lim_log
+ (pMac, LOGW, FL("Skip STA deletion (invalid STA)"));
+ )
+ return;
+ }
+ /**
+ * MAC based Authentication was used. Trigger
+ * Deauthentication frame to peer since it will
+ * take care of disassociation as well.
+ */
+
+ pSmeDeauthReq = cdf_mem_malloc(sizeof(tSirSmeDeauthReq));
+ if (NULL == pSmeDeauthReq) {
+ lim_log(pMac, LOGP,
+ FL("AllocateMemory failed for eWNI_SME_DEAUTH_REQ "));
+ return;
+ }
+
+ pBuf = (uint8_t *) &pSmeDeauthReq->messageType;
+
+ /* messageType */
+ lim_copy_u16((uint8_t *) pBuf, eWNI_SME_DISASSOC_REQ);
+ pBuf += sizeof(uint16_t);
+ msgLength += sizeof(uint16_t);
+
+ /* length */
+ pLen = pBuf;
+ pBuf += sizeof(uint16_t);
+ msgLength += sizeof(uint16_t);
+
+ /* sessionId */
+ *pBuf = psessionEntry->smeSessionId;
+ pBuf++;
+ msgLength++;
+
+ /* transactionId */
+ lim_copy_u16((uint8_t *) pBuf, psessionEntry->transactionId);
+ pBuf += sizeof(uint16_t);
+ msgLength += sizeof(uint16_t);
+
+ /* bssId */
+ cdf_mem_copy(pBuf, psessionEntry->bssId, sizeof(tSirMacAddr));
+ pBuf += sizeof(tSirMacAddr);
+ msgLength += sizeof(tSirMacAddr);
+
+ /* peerMacAddr */
+ cdf_mem_copy(pBuf, pStaDs->staAddr, sizeof(tSirMacAddr));
+ pBuf += sizeof(tSirMacAddr);
+ msgLength += sizeof(tSirMacAddr);
+
+ /* reasonCode */
+ lim_copy_u16((uint8_t *) pBuf, (uint16_t) eLIM_LINK_MONITORING_DISASSOC);
+ pBuf += sizeof(uint16_t);
+ msgLength += sizeof(uint16_t);
+
+ /* Do not send disassoc OTA */
+ /* pBuf[0] = 1 means do not send the disassoc frame over the air */
+ /* pBuf[0] = 0 means send the disassoc frame over the air */
+ pBuf[0] = 0;
+ pBuf += sizeof(uint8_t);
+ msgLength += sizeof(uint8_t);
+
+ /* Fill in length */
+ lim_copy_u16((uint8_t *) pLen, msgLength);
+
+ lim_post_sme_message(pMac, eWNI_SME_DISASSOC_REQ,
+ (uint32_t *) pSmeDeauthReq);
+ cdf_mem_free(pSmeDeauthReq);
+
+} /*** end lim_trigger_st_adeletion() ***/
+
+/**
+ * lim_tear_down_link_with_ap()
+ *
+ ***FUNCTION:
+ * This function is called when heartbeat (beacon reception)
+ * fails on STA
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ *
+ ***NOTE:
+ *
+ * @param pMac - Pointer to Global MAC structure
+ * @return None
+ */
+
+void
+lim_tear_down_link_with_ap(tpAniSirGlobal pMac, uint8_t sessionId,
+ tSirMacReasonCodes reasonCode)
+{
+ tpDphHashNode pStaDs = NULL;
+
+ /* tear down the following sessionEntry */
+ tpPESession psessionEntry;
+
+ if ((psessionEntry = pe_find_session_by_session_id(pMac, sessionId)) == NULL) {
+ lim_log(pMac, LOGP,
+ FL("Session Does not exist for given sessionID"));
+ return;
+ }
+ /**
+ * Heart beat failed for upto threshold value
+ * and AP did not respond for Probe request.
+ * Trigger link tear down.
+ */
+ psessionEntry->pmmOffloadInfo.bcnmiss = false;
+
+ lim_log(pMac, LOGW,
+ FL("No ProbeRsp from AP after HB failure. Tearing down link"));
+
+ /* Announce loss of link to Roaming algorithm */
+ /* and cleanup by sending SME_DISASSOC_REQ to SME */
+
+ pStaDs =
+ dph_get_hash_entry(pMac, DPH_STA_HASH_INDEX_PEER,
+ &psessionEntry->dph.dphHashTable);
+
+ if (pStaDs != NULL) {
+ tLimMlmDeauthInd mlmDeauthInd;
+
+#ifdef FEATURE_WLAN_TDLS
+ /* Delete all TDLS peers connected before leaving BSS */
+ lim_delete_tdls_peers(pMac, psessionEntry);
+#endif
+
+ pStaDs->mlmStaContext.disassocReason = reasonCode;
+ pStaDs->mlmStaContext.cleanupTrigger =
+ eLIM_LINK_MONITORING_DEAUTH;
+
+ /*
+ * Set state to mlm State to eLIM_MLM_WT_DEL_STA_RSP_STATE
+ * This is to address the issue of race condition between
+ * disconnect request from the HDD and deauth from
+ * Tx inactivity timer by FWR. This will make sure that we
+ * will not process disassoc if deauth is in progress for
+ * the station and thus mlmStaContext.cleanupTrigger will
+ * not be overwritten.
+ */
+
+ pStaDs->mlmStaContext.mlmState =
+ eLIM_MLM_WT_DEL_STA_RSP_STATE;
+
+ /* / Issue Deauth Indication to SME. */
+ cdf_mem_copy((uint8_t *) &mlmDeauthInd.peerMacAddr,
+ pStaDs->staAddr, sizeof(tSirMacAddr));
+
+ /*
+ * if sendDeauthBeforeCon is enabled and reasoncode is
+ * Beacon Missed Store the MAC of AP in the flip flop
+ * buffer. This MAC will be used to send Deauth before
+ * connection, if we connect to same AP after HB failure.
+ */
+ if (pMac->roam.configParam.sendDeauthBeforeCon &&
+ eSIR_BEACON_MISSED == reasonCode) {
+ int apCount = pMac->lim.gLimHeartBeatApMacIndex;
+
+ if (pMac->lim.gLimHeartBeatApMacIndex)
+ pMac->lim.gLimHeartBeatApMacIndex = 0;
+ else
+ pMac->lim.gLimHeartBeatApMacIndex = 1;
+
+ lim_log(pMac, LOGE, FL("HB Failure on MAC "
+ MAC_ADDRESS_STR" Store it on Index %d"),
+ MAC_ADDR_ARRAY(pStaDs->staAddr),apCount);
+
+ sir_copy_mac_addr(pMac->lim.gLimHeartBeatApMac[apCount],
+ pStaDs->staAddr);
+ }
+
+ mlmDeauthInd.reasonCode =
+ (uint8_t) pStaDs->mlmStaContext.disassocReason;
+ mlmDeauthInd.deauthTrigger =
+ pStaDs->mlmStaContext.cleanupTrigger;
+
+ lim_post_sme_message(pMac, LIM_MLM_DEAUTH_IND,
+ (uint32_t *) &mlmDeauthInd);
+
+ lim_send_sme_deauth_ind(pMac, pStaDs, psessionEntry);
+ }
+} /*** lim_tear_down_link_with_ap() ***/
+
+/**
+ * lim_handle_heart_beat_failure() - handle hear beat failure in STA
+ *
+ * @mac_ctx: global MAC context
+ * @session: PE session entry
+ *
+ * This function is called when heartbeat (beacon reception)
+ * fails on STA
+ *
+ * Return: None
+ */
+
+void lim_handle_heart_beat_failure(tpAniSirGlobal mac_ctx,
+ tpPESession session)
+{
+ uint8_t curr_chan;
+
+#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */
+ host_log_beacon_update_pkt_type *log_ptr = NULL;
+#endif /* FEATURE_WLAN_DIAG_SUPPORT */
+
+#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */
+ WLAN_HOST_DIAG_LOG_ALLOC(log_ptr, host_log_beacon_update_pkt_type,
+ LOG_WLAN_BEACON_UPDATE_C);
+ if (log_ptr)
+ log_ptr->bcn_rx_cnt = session->LimRxedBeaconCntDuringHB;
+ WLAN_HOST_DIAG_LOG_REPORT(log_ptr);
+#endif /* FEATURE_WLAN_DIAG_SUPPORT */
+
+ /* Ensure HB Status for the session has been reseted */
+ session->LimHBFailureStatus = false;
+
+ if ((LIM_IS_STA_ROLE(session) ||
+ LIM_IS_BT_AMP_STA_ROLE(session)) &&
+ (session->limMlmState == eLIM_MLM_LINK_ESTABLISHED_STATE) &&
+ (session->limSmeState != eLIM_SME_WT_DISASSOC_STATE) &&
+ (session->limSmeState != eLIM_SME_WT_DEAUTH_STATE)) {
+ if (!mac_ctx->sys.gSysEnableLinkMonitorMode)
+ return;
+
+ /* Beacon frame not received within heartbeat timeout. */
+ lim_log(mac_ctx, LOGW, FL("Heartbeat Failure"));
+ mac_ctx->lim.gLimHBfailureCntInLinkEstState++;
+
+ /*
+ * Check if connected on the DFS channel, if not connected on
+ * DFS channel then only send the probe request otherwise tear
+ * down the link
+ */
+ curr_chan = session->currentOperChannel;
+ if (!lim_isconnected_on_dfs_channel(curr_chan)) {
+ /* Detected continuous Beacon Misses */
+ session->LimHBFailureStatus = true;
+
+ /*Reset the HB packet count before sending probe*/
+ limResetHBPktCount(session);
+ /**
+ * Send Probe Request frame to AP to see if
+ * it is still around. Wait until certain
+ * timeout for Probe Response from AP.
+ */
+ lim_log(mac_ctx, LOGW,
+ FL("HB missed from AP. Sending Probe Req"));
+ /* for searching AP, we don't include any more IE */
+ lim_send_probe_req_mgmt_frame(mac_ctx, &session->ssId,
+ session->bssId, curr_chan, session->selfMacAddr,
+ session->dot11mode, 0, NULL);
+ } else {
+ lim_log(mac_ctx, LOGW,
+ FL("HB missed from AP on DFS chanel moving to passive"));
+ if (curr_chan < SIR_MAX_24G_5G_CHANNEL_RANGE) {
+ lim_covert_channel_scan_type(mac_ctx, curr_chan,
+ false);
+ mac_ctx->lim.dfschannelList.timeStamp[curr_chan]
+ = 0;
+ }
+ /*
+ * Connected on DFS channel so should not send the
+ * probe request tear down the link directly
+ */
+ lim_tear_down_link_with_ap(mac_ctx,
+ session->peSessionId,
+ eSIR_BEACON_MISSED);
+ }
+ } else {
+ /**
+ * Heartbeat timer may have timed out
+ * while we're doing background scanning/learning
+ * or in states other than link-established state.
+ * Log error.
+ */
+ lim_log(mac_ctx, LOG1,
+ FL("received heartbeat timeout in state %X"),
+ session->limMlmState);
+ lim_print_mlm_state(mac_ctx, LOG1, session->limMlmState);
+ mac_ctx->lim.gLimHBfailureCntInOtherStates++;
+ }
+}
diff --git a/core/mac/src/pe/lim/lim_p2p.c b/core/mac/src/pe/lim/lim_p2p.c
new file mode 100644
index 0000000..7f29157
--- /dev/null
+++ b/core/mac/src/pe/lim/lim_p2p.c
@@ -0,0 +1,794 @@
+/*
+ * Copyright (c) 2012-2014 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.
+ */
+
+/*===========================================================================
+ L I M _ P 2 P . C
+
+ OVERVIEW:
+
+ This software unit holds the implementation of the WLAN Protocol Engine for
+ P2P.
+ ===========================================================================*/
+
+/*===========================================================================
+
+ EDIT HISTORY FOR FILE
+
+ This section contains comments describing changes made to the module.
+ Notice that changes are listed in reverse chronological order.
+
+ $Header$$DateTime$$Author$
+
+ when who what, where, why
+ ---------- --- --------------------------------------------------------
+ 2011-05-02 djindal Corrected file indentation and changed remain on channel
+ handling for concurrency.
+ ===========================================================================*/
+
+#include "lim_utils.h"
+#include "lim_session_utils.h"
+#include "wma_types.h"
+#include "lim_types.h"
+
+#define PROBE_RSP_IE_OFFSET 36
+#define BSSID_OFFSET 16
+#define ADDR2_OFFSET 10
+#define ACTION_OFFSET 24
+
+/* A DFS channel can be ACTIVE for max 9000 msec, from the last
+ received Beacon/Prpbe Resp. */
+#define MAX_TIME_TO_BE_ACTIVE_CHANNEL 9000
+
+void lim_exit_remain_on_channel(tpAniSirGlobal pMac, CDF_STATUS status,
+ uint32_t *data, tpPESession psessionEntry);
+extern tSirRetStatus lim_set_link_state(tpAniSirGlobal pMac, tSirLinkState state,
+ tSirMacAddr bssId, tSirMacAddr selfMacAddr,
+ tpSetLinkStateCallback callback,
+ void *callbackArg);
+
+CDF_STATUS lim_p2p_action_cnf(tpAniSirGlobal pMac, uint32_t txCompleteSuccess);
+
+/*------------------------------------------------------------------
+ *
+ * Below function is called if hdd requests a remain on channel.
+ *
+ *------------------------------------------------------------------*/
+static CDF_STATUS lim_send_hal_req_remain_on_chan_offload(tpAniSirGlobal pMac,
+ tSirRemainOnChnReq *
+ pRemOnChnReq)
+{
+ tSirScanOffloadReq *pScanOffloadReq;
+ tSirMsgQ msg;
+ tSirRetStatus rc = eSIR_SUCCESS;
+ uint8_t bssid[CDF_MAC_ADDR_SIZE] =
+ { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+
+ pScanOffloadReq = cdf_mem_malloc(sizeof(tSirScanOffloadReq));
+ if (NULL == pScanOffloadReq) {
+ lim_log(pMac, LOGE,
+ FL("Memory allocation failed for pScanOffloadReq"));
+ return CDF_STATUS_E_NOMEM;
+ }
+
+ cdf_mem_zero(pScanOffloadReq, sizeof(tSirScanOffloadReq));
+
+ msg.type = WMA_START_SCAN_OFFLOAD_REQ;
+ msg.bodyptr = pScanOffloadReq;
+ msg.bodyval = 0;
+
+ cdf_mem_copy((uint8_t *) pScanOffloadReq->selfMacAddr,
+ (uint8_t *) pRemOnChnReq->selfMacAddr,
+ sizeof(tSirMacAddr));
+
+ cdf_mem_copy((uint8_t *) pScanOffloadReq->bssId,
+ (uint8_t *) bssid, sizeof(tSirMacAddr));
+ pScanOffloadReq->scanType = eSIR_PASSIVE_SCAN;
+ pScanOffloadReq->p2pScanType = P2P_SCAN_TYPE_LISTEN;
+ pScanOffloadReq->minChannelTime = pRemOnChnReq->duration;
+ pScanOffloadReq->maxChannelTime = pRemOnChnReq->duration;
+ pScanOffloadReq->sessionId = pRemOnChnReq->sessionId;
+ pScanOffloadReq->channelList.numChannels = 1;
+ pScanOffloadReq->channelList.channelNumber[0] = pRemOnChnReq->chnNum;
+ pScanOffloadReq->scan_id = pRemOnChnReq->scan_id;
+
+ lim_log(pMac, LOG1,
+ FL("Req-rem-on-channel: duration %u, session %hu, chan %hu"),
+ pRemOnChnReq->duration, pRemOnChnReq->sessionId,
+ pRemOnChnReq->chnNum);
+
+ rc = wma_post_ctrl_msg(pMac, &msg);
+ if (rc != eSIR_SUCCESS) {
+ lim_log(pMac, LOGE, FL("wma_post_ctrl_msg() return failure %u"),
+ rc);
+ cdf_mem_free(pScanOffloadReq);
+ return CDF_STATUS_E_FAILURE;
+ }
+
+ return CDF_STATUS_SUCCESS;
+}
+
+/*------------------------------------------------------------------
+ *
+ * Remain on channel req handler. Initiate the INIT_SCAN, CHN_CHANGE
+ * and SET_LINK Request from SME, chnNum and duration to remain on channel.
+ *
+ *------------------------------------------------------------------*/
+int lim_process_remain_on_chnl_req(tpAniSirGlobal pMac, uint32_t *pMsg)
+{
+ tSirRemainOnChnReq *msgbuff = (tSirRemainOnChnReq *) pMsg;
+ CDF_STATUS status;
+
+ pMac->lim.gpLimRemainOnChanReq = msgbuff;
+ status = lim_send_hal_req_remain_on_chan_offload(pMac, msgbuff);
+ if (status != CDF_STATUS_SUCCESS) {
+ /* Post the meessage to Sme */
+ lim_send_sme_rsp(pMac, eWNI_SME_REMAIN_ON_CHN_RSP,
+ status, msgbuff->sessionId, msgbuff->scan_id);
+ cdf_mem_free(pMac->lim.gpLimRemainOnChanReq);
+ pMac->lim.gpLimRemainOnChanReq = NULL;
+ }
+ return false;
+}
+
+/*------------------------------------------------------------------
+ *
+ * lim Insert NOA timer timeout callback - when timer fires, deactivate it and send
+ * scan rsp to csr/hdd
+ *
+ *------------------------------------------------------------------*/
+void lim_process_insert_single_shot_noa_timeout(tpAniSirGlobal pMac)
+{
+ /* timeout means start NOA did not arrive; we need to deactivate and change the timer for
+ * future activations
+ */
+ lim_deactivate_and_change_timer(pMac, eLIM_INSERT_SINGLESHOT_NOA_TIMER);
+
+ /* Even if insert NOA timedout, go ahead and process/send stored SME request */
+ lim_process_regd_defd_sme_req_after_noa_start(pMac);
+
+ return;
+}
+
+/*-----------------------------------------------------------------
+ * lim Insert Timer callback function to check active DFS channels
+ * and convert them to passive channels if there was no
+ * beacon/proberesp for MAX_TIME_TO_BE_ACTIVE_CHANNEL time
+ *------------------------------------------------------------------*/
+void lim_convert_active_channel_to_passive_channel(tpAniSirGlobal pMac)
+{
+ uint32_t currentTime;
+ uint32_t lastTime = 0;
+ uint32_t timeDiff;
+ uint8_t i;
+ currentTime = cdf_mc_timer_get_system_time();
+ for (i = 1; i < SIR_MAX_24G_5G_CHANNEL_RANGE; i++) {
+ if ((pMac->lim.dfschannelList.timeStamp[i]) != 0) {
+ lastTime = pMac->lim.dfschannelList.timeStamp[i];
+ if (currentTime >= lastTime) {
+ timeDiff = (currentTime - lastTime);
+ } else {
+ timeDiff =
+ (0xFFFFFFFF - lastTime) + currentTime;
+ }
+
+ if (timeDiff >= MAX_TIME_TO_BE_ACTIVE_CHANNEL) {
+ lim_covert_channel_scan_type(pMac, i, false);
+ pMac->lim.dfschannelList.timeStamp[i] = 0;
+ }
+ }
+ }
+ /* lastTime is zero if there is no DFS active channels in the list.
+ * If this is non zero then we have active DFS channels so restart the timer.
+ */
+ if (lastTime != 0) {
+ if (tx_timer_activate
+ (&pMac->lim.limTimers.gLimActiveToPassiveChannelTimer)
+ != TX_SUCCESS) {
+ lim_log(pMac, LOGE,
+ FL
+ ("Could not activate Active to Passive Channel timer"));
+ }
+ }
+
+ return;
+
+}
+
+/**
+ * lim_process_remain_on_chn_timeout() - ROC timeout handler
+ *
+ * @mac_ctx: MAC context
+ *
+ * limchannelchange callback, on success channel change, set the
+ * link_state to LISTEN
+ *
+ * Return: NULL
+ */
+void lim_process_remain_on_chn_timeout(tpAniSirGlobal mac_ctx)
+{
+ tpPESession session;
+ tSirMacAddr null_bssid = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+ TX_TIMER *roc_timer;
+
+ roc_timer = &mac_ctx->lim.limTimers.gLimRemainOnChannelTimer;
+ /*
+ * Timer might get extended while Sending Action Frame
+ * In that case don't process Channel Timeout
+ */
+ if (tx_timer_running(roc_timer)) {
+ lim_log(mac_ctx, LOGE,
+ FL("already timer is running and not processing "));
+ return;
+ }
+
+ lim_deactivate_and_change_timer(mac_ctx, eLIM_REMAIN_CHN_TIMER);
+ if (NULL == mac_ctx->lim.gpLimRemainOnChanReq) {
+ lim_log(mac_ctx, LOGE, FL("No Remain on channel pending"));
+ return;
+ }
+
+ /* get the previous valid LINK state */
+ if (lim_set_link_state(mac_ctx, eSIR_LINK_IDLE_STATE, null_bssid,
+ mac_ctx->lim.gSelfMacAddr, NULL, NULL) != eSIR_SUCCESS)
+ {
+ lim_log(mac_ctx, LOGE, FL("Unable to change link state"));
+ return;
+ }
+
+ if (mac_ctx->lim.gLimMlmState != eLIM_MLM_P2P_LISTEN_STATE) {
+ lim_remain_on_chn_rsp(mac_ctx, CDF_STATUS_SUCCESS, NULL);
+ } else {
+ session = pe_find_session_by_session_id(mac_ctx,
+ roc_timer->sessionId);
+ /* get the session */
+ if (session == NULL) {
+ lim_log(mac_ctx, LOGE,
+ FL("Session Does not exist sessionID %d"),
+ roc_timer->sessionId);
+ goto error;
+ }
+
+ lim_exit_remain_on_channel(mac_ctx, CDF_STATUS_SUCCESS, NULL,
+ session);
+ return;
+error:
+ lim_remain_on_chn_rsp(mac_ctx, CDF_STATUS_E_FAILURE, NULL);
+ }
+ return;
+}
+
+/*------------------------------------------------------------------
+ *
+ * limchannelchange callback, on success channel change, set the link_state
+ * to LISTEN
+ *
+ *------------------------------------------------------------------*/
+
+void lim_exit_remain_on_channel(tpAniSirGlobal pMac, CDF_STATUS status,
+ uint32_t *data, tpPESession psessionEntry)
+{
+
+ if (status != CDF_STATUS_SUCCESS) {
+ PELOGE(lim_log(pMac, LOGE, "Remain on Channel Failed");)
+ goto error;
+ }
+ /* Set the resume channel to Any valid channel (invalid). */
+ /* This will instruct HAL to set it to any previous valid channel. */
+ pe_set_resume_channel(pMac, 0, 0);
+ lim_remain_on_chn_rsp(pMac, CDF_STATUS_SUCCESS, NULL);
+ return;
+error:
+ lim_remain_on_chn_rsp(pMac, CDF_STATUS_E_FAILURE, NULL);
+ return;
+}
+
+/*------------------------------------------------------------------
+ *
+ * Send remain on channel respone: Success/ Failure
+ *
+ *------------------------------------------------------------------*/
+void lim_remain_on_chn_rsp(tpAniSirGlobal pMac, CDF_STATUS status, uint32_t *data)
+{
+ tpPESession psessionEntry;
+ uint8_t sessionId;
+ tSirRemainOnChnReq *MsgRemainonChannel = pMac->lim.gpLimRemainOnChanReq;
+ tSirMacAddr nullBssid = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+ if (NULL == MsgRemainonChannel) {
+ PELOGE(lim_log(pMac, LOGP,
+ "%s: No Pointer for Remain on Channel Req",
+ __func__);
+ )
+ return;
+ }
+ /* Incase of the Remain on Channel Failure Case */
+ /* Cleanup Everything */
+ if (CDF_STATUS_E_FAILURE == status) {
+ /* Deactivate Remain on Channel Timer */
+ lim_deactivate_and_change_timer(pMac, eLIM_REMAIN_CHN_TIMER);
+
+ /* Set the Link State to Idle */
+ /* get the previous valid LINK state */
+ if (lim_set_link_state(pMac, eSIR_LINK_IDLE_STATE, nullBssid,
+ pMac->lim.gSelfMacAddr, NULL,
+ NULL) != eSIR_SUCCESS) {
+ lim_log(pMac, LOGE, "Unable to change link state");
+ }
+
+ pMac->lim.gLimSystemInScanLearnMode = 0;
+ pMac->lim.gLimHalScanState = eLIM_HAL_IDLE_SCAN_STATE;
+ SET_LIM_PROCESS_DEFD_MESGS(pMac, true);
+ }
+
+ /* delete the session */
+ if ((psessionEntry = pe_find_session_by_bssid(pMac,
+ MsgRemainonChannel->
+ selfMacAddr,
+ &sessionId)) != NULL) {
+ if (LIM_IS_P2P_DEVICE_ROLE(psessionEntry)) {
+ pe_delete_session(pMac, psessionEntry);
+ }
+ }
+
+ /* Post the meessage to Sme */
+ lim_send_sme_rsp(pMac, eWNI_SME_REMAIN_ON_CHN_RSP,
+ status,
+ MsgRemainonChannel->sessionId, 0);
+
+ cdf_mem_free(pMac->lim.gpLimRemainOnChanReq);
+ pMac->lim.gpLimRemainOnChanReq = NULL;
+
+ pMac->lim.gLimMlmState = pMac->lim.gLimPrevMlmState;
+
+ /* If remain on channel timer expired and action frame is pending then
+ * indicaiton confirmation with status failure */
+ if (pMac->lim.mgmtFrameSessionId != 0xff) {
+ lim_p2p_action_cnf(pMac, 0);
+ }
+
+ return;
+}
+
+/*------------------------------------------------------------------
+ *
+ * Indicate the Mgmt Frame received to SME to HDD callback
+ * handle Probe_req/Action frame currently
+ *
+ *------------------------------------------------------------------*/
+void lim_send_sme_mgmt_frame_ind(tpAniSirGlobal pMac, uint8_t frameType,
+ uint8_t *frame, uint32_t frameLen,
+ uint16_t sessionId, uint32_t rxChannel,
+ tpPESession psessionEntry, int8_t rxRssi)
+{
+ tSirMsgQ mmhMsg;
+ tpSirSmeMgmtFrameInd pSirSmeMgmtFrame = NULL;
+ uint16_t length;
+
+ length = sizeof(tSirSmeMgmtFrameInd) + frameLen;
+
+ pSirSmeMgmtFrame = cdf_mem_malloc(length);
+ if (NULL == pSirSmeMgmtFrame) {
+ lim_log(pMac, LOGP,
+ FL("AllocateMemory failed for eWNI_SME_LISTEN_RSP"));
+ return;
+ }
+ cdf_mem_set((void *)pSirSmeMgmtFrame, length, 0);
+
+ pSirSmeMgmtFrame->mesgType = eWNI_SME_MGMT_FRM_IND;
+ pSirSmeMgmtFrame->mesgLen = length;
+ pSirSmeMgmtFrame->sessionId = sessionId;
+ pSirSmeMgmtFrame->frameType = frameType;
+ pSirSmeMgmtFrame->rxRssi = rxRssi;
+ pSirSmeMgmtFrame->rxChan = rxChannel;
+
+ cdf_mem_zero(pSirSmeMgmtFrame->frameBuf, frameLen);
+ cdf_mem_copy(pSirSmeMgmtFrame->frameBuf, frame, frameLen);
+
+ mmhMsg.type = eWNI_SME_MGMT_FRM_IND;
+ mmhMsg.bodyptr = pSirSmeMgmtFrame;
+ mmhMsg.bodyval = 0;
+
+ lim_sys_process_mmh_msg_api(pMac, &mmhMsg, ePROT);
+ return;
+}
+
+CDF_STATUS lim_p2p_action_cnf(tpAniSirGlobal pMac, uint32_t txCompleteSuccess)
+{
+ if (pMac->lim.mgmtFrameSessionId != 0xff) {
+ /* The session entry might be invalid(0xff) action confirmation received after
+ * remain on channel timer expired */
+ lim_send_sme_rsp(pMac, eWNI_SME_ACTION_FRAME_SEND_CNF,
+ (txCompleteSuccess ? eSIR_SME_SUCCESS :
+ eSIR_SME_SEND_ACTION_FAIL),
+ pMac->lim.mgmtFrameSessionId, 0);
+ pMac->lim.mgmtFrameSessionId = 0xff;
+ }
+
+ return CDF_STATUS_SUCCESS;
+}
+
+/**
+ * lim_tx_action_frame() - Handles action frame transmission request
+ * @mac_ctx: Pointer to mac context
+ * @mb_msg: message sent from SME
+ * @msg_len: Message length
+ * @packet: network buffer for TX
+ * @frame: frame buffer
+ *
+ * This function processes the action frame transmission request and
+ * posts message to WMA.
+ *
+ * Return: NULL
+ */
+static void lim_tx_action_frame(tpAniSirGlobal mac_ctx,
+ tSirMbMsgP2p *mb_msg, uint32_t msg_len, void *packet, uint8_t *frame)
+{
+ uint8_t tx_flag = 0;
+ tpSirMacFrameCtl fc = (tpSirMacFrameCtl) mb_msg->data;
+ CDF_STATUS cdf_status;
+ uint8_t sme_session_id = 0;
+ uint16_t channel_freq;
+
+ sme_session_id = mb_msg->sessionId;
+ channel_freq = mb_msg->channel_freq;
+ /*
+ * Use BD rate 2 for all P2P related frames. As these frames
+ * need to go at OFDM rates. And BD rate2 we configured at 6Mbps.
+ */
+ tx_flag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME;
+
+ if ((SIR_MAC_MGMT_PROBE_RSP == fc->subType) ||
+ (mb_msg->noack)) {
+ cdf_status = wma_tx_frame(mac_ctx, packet, (uint16_t) msg_len,
+ TXRX_FRM_802_11_MGMT,
+ ANI_TXDIR_TODS, 7, lim_tx_complete,
+ frame, tx_flag, sme_session_id,
+ channel_freq);
+
+ if (!mb_msg->noack)
+ lim_send_sme_rsp(mac_ctx,
+ eWNI_SME_ACTION_FRAME_SEND_CNF,
+ cdf_status, mb_msg->sessionId, 0);
+ mac_ctx->lim.mgmtFrameSessionId = 0xff;
+ } else {
+ mac_ctx->lim.mgmtFrameSessionId = mb_msg->sessionId;
+ cdf_status =
+ wma_tx_frameWithTxComplete(mac_ctx, packet,
+ (uint16_t) msg_len,
+ TXRX_FRM_802_11_MGMT,
+ ANI_TXDIR_TODS, 7, lim_tx_complete,
+ frame, lim_p2p_action_cnf, tx_flag,
+ sme_session_id, false,
+ channel_freq);
+
+ if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
+ lim_log(mac_ctx, LOGE,
+ FL("couldn't send action frame"));
+ lim_send_sme_rsp(mac_ctx,
+ eWNI_SME_ACTION_FRAME_SEND_CNF,
+ cdf_status, mb_msg->sessionId, 0);
+ mac_ctx->lim.mgmtFrameSessionId = 0xff;
+ } else {
+ mac_ctx->lim.mgmtFrameSessionId = mb_msg->sessionId;
+ lim_log(mac_ctx, LOG2,
+ FL("lim.actionFrameSessionId = %u"),
+ mac_ctx->lim.mgmtFrameSessionId);
+ }
+ }
+
+ return;
+}
+
+/**
+ * lim_send_p2p_action_frame() - Process action frame request
+ * @mac_ctx: Pointer to mac context
+ * @msg: message sent from SME
+ *
+ * This function processes the action frame request sent from the
+ * SME and generates the ACTION frame.
+ *
+ * Return: NULL
+ */
+void lim_send_p2p_action_frame(tpAniSirGlobal mac_ctx,
+ tpSirMsgQ msg)
+{
+ tSirMbMsgP2p *mb_msg = (tSirMbMsgP2p *) msg->bodyptr;
+ uint32_t msg_len;
+ uint8_t *frame;
+ void *packet;
+ CDF_STATUS cdf_status;
+ tpSirMacFrameCtl fc = (tpSirMacFrameCtl) mb_msg->data;
+ uint8_t noa_len = 0;
+ uint8_t noa_stream[SIR_MAX_NOA_ATTR_LEN + (2 * SIR_P2P_IE_HEADER_LEN)];
+ uint8_t orig_len = 0;
+ uint8_t session_id = 0;
+ uint8_t *p2p_ie = NULL;
+ tpPESession session_entry = NULL;
+ uint8_t *presence_noa_attr = NULL;
+ uint8_t *tmp_p2p_ie = NULL;
+ uint16_t remain_len = 0;
+ uint8_t sme_session_id = 0;
+#ifdef WLAN_FEATURE_11W
+ tpSirMacMgmtHdr mac_hdr;
+ tpSirMacActionFrameHdr action_hdr;
+#endif
+
+ msg_len = mb_msg->msgLen - sizeof(tSirMbMsgP2p);
+ lim_log(mac_ctx, LOG1, FL("sending fc->type=%d fc->subType=%d"),
+ fc->type, fc->subType);
+
+ if ((!mac_ctx->lim.gpLimRemainOnChanReq) && (0 != mb_msg->wait)) {
+ lim_log(mac_ctx, LOGE,
+ FL("RemainOnChannel is not running\n"));
+ lim_send_sme_rsp(mac_ctx, eWNI_SME_ACTION_FRAME_SEND_CNF,
+ CDF_STATUS_E_FAILURE, mb_msg->sessionId, 0);
+ return;
+ }
+ sme_session_id = mb_msg->sessionId;
+
+ if ((SIR_MAC_MGMT_FRAME == fc->type) &&
+ (SIR_MAC_MGMT_PROBE_RSP == fc->subType)) {
+ /* get proper offset for Probe RSP */
+ p2p_ie = limGetP2pIEPtr(mac_ctx,
+ (uint8_t *) mb_msg->data +
+ PROBE_RSP_IE_OFFSET,
+ msg_len - PROBE_RSP_IE_OFFSET);
+ while ((NULL != p2p_ie)
+ && (SIR_MAC_MAX_IE_LENGTH == p2p_ie[1])) {
+ remain_len =
+ msg_len - (p2p_ie -
+ (uint8_t *) mb_msg->data);
+ if (remain_len > 2) {
+ tmp_p2p_ie = limGetP2pIEPtr(mac_ctx,
+ p2p_ie + SIR_MAC_MAX_IE_LENGTH + 2,
+ remain_len);
+ }
+ if (tmp_p2p_ie) {
+ p2p_ie = tmp_p2p_ie;
+ tmp_p2p_ie = NULL;
+ } else {
+ break;
+ }
+ } /* end of while */
+ } else if ((SIR_MAC_MGMT_FRAME == fc->type) &&
+ (SIR_MAC_MGMT_ACTION == fc->subType) &&
+ (SIR_MAC_ACTION_VENDOR_SPECIFIC_CATEGORY ==
+ *((uint8_t *) mb_msg->data + ACTION_OFFSET))) {
+ tpSirMacP2PActionFrameHdr action_hdr =
+ (tpSirMacP2PActionFrameHdr) ((uint8_t *)
+ mb_msg->data + ACTION_OFFSET);
+ if (cdf_mem_compare(action_hdr->Oui, SIR_MAC_P2P_OUI,
+ SIR_MAC_P2P_OUI_SIZE) &&
+ (SIR_MAC_ACTION_P2P_SUBTYPE_PRESENCE_RSP ==
+ action_hdr->OuiSubType)) {
+
+ /* In case of Presence RSP response */
+ p2p_ie = limGetP2pIEPtr(mac_ctx,
+ (uint8_t *)mb_msg->data +
+ ACTION_OFFSET +
+ sizeof(tSirMacP2PActionFrameHdr),
+ (msg_len - ACTION_OFFSET
+ - sizeof(tSirMacP2PActionFrameHdr)));
+ if (NULL != p2p_ie) {
+ /* extract the presence of NoA attribute inside
+ * P2P IE */
+ presence_noa_attr = lim_get_ie_ptr_new(mac_ctx,
+ p2p_ie + SIR_P2P_IE_HEADER_LEN,
+ p2p_ie[1], SIR_P2P_NOA_ATTR, TWO_BYTE);
+ }
+ }
+ }
+
+ if ((SIR_MAC_MGMT_FRAME == fc->type) &&
+ (SIR_MAC_MGMT_PROBE_RSP == fc->subType ||
+ SIR_MAC_MGMT_ACTION == fc->subType) && p2p_ie != NULL) {
+ /* get NoA attribute stream P2P IE */
+ noa_len =
+ lim_get_noa_attr_stream(mac_ctx, noa_stream,
+ session_entry);
+ /* need to append NoA attribute in P2P IE */
+ if (noa_len > 0) {
+ orig_len = p2p_ie[1];
+ /* if Presence Rsp has NoAttr */
+ if (presence_noa_attr) {
+ uint16_t noa_len =
+ presence_noa_attr[1] |
+ (presence_noa_attr[2] << 8);
+ /*One byte for attribute, 2bytes for length */
+ orig_len -= (noa_len + 1 + 2);
+ /* remove those bytes to copy */
+ msg_len -= (noa_len + 1 + 2);
+ /* remove NoA from original Len */
+ p2p_ie[1] = orig_len;
+ }
+ if ((p2p_ie[1] + (uint16_t) noa_len) >
+ SIR_MAC_MAX_IE_LENGTH) {
+ /*
+ * Form the new NoA Byte array in multiple
+ * P2P IEs
+ */
+ noa_len =
+ lim_get_noa_attr_stream_in_mult_p2p_ies
+ (mac_ctx, noa_stream, noa_len,
+ ((p2p_ie[1] + (uint16_t)noa_len)
+ - SIR_MAC_MAX_IE_LENGTH));
+ p2p_ie[1] = SIR_MAC_MAX_IE_LENGTH;
+ } else {
+ /* increment the length of P2P IE */
+ p2p_ie[1] += noa_len;
+ }
+ msg_len += noa_len;
+ lim_log(mac_ctx, LOGE,
+ FL("noa_len=%d orig_len=%d p2p_ie=%p"
+ " msg_len=%d nBytesToCopy=%zu "),
+ noa_len, orig_len, p2p_ie, msg_len,
+ ((p2p_ie + orig_len + 2) -
+ (uint8_t *) mb_msg->data));
+ }
+ }
+
+ if ((SIR_MAC_MGMT_PROBE_RSP == fc->subType ||
+ SIR_MAC_MGMT_ACTION == fc->subType))
+ lim_set_ht_caps(mac_ctx, session_entry,
+ (uint8_t *) mb_msg->data + PROBE_RSP_IE_OFFSET,
+ msg_len - PROBE_RSP_IE_OFFSET);
+
+ /* Ok-- try to allocate some memory: */
+ cdf_status = cds_packet_alloc((uint16_t) msg_len, (void **)&frame,
+ (void **)&packet);
+ if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
+ lim_log(mac_ctx, LOGE,
+ FL("Failed to allocate %d bytes for a Probe Request."),
+ msg_len);
+ return;
+ }
+ /* Paranoia: */
+ cdf_mem_set(frame, msg_len, 0);
+
+ /*
+ * Add sequence number to action frames
+ * Frames are handed over in .11 format by supplicant already
+ */
+ lim_populate_p2p_mac_header(mac_ctx, (uint8_t *) mb_msg->data);
+
+ if ((noa_len > 0)
+ && (noa_len < (SIR_MAX_NOA_ATTR_LEN + SIR_P2P_IE_HEADER_LEN))) {
+ /* Add 2 bytes for length and Arribute field */
+ uint32_t nBytesToCopy = ((p2p_ie + orig_len + 2) -
+ (uint8_t *) mb_msg->data);
+ cdf_mem_copy(frame, mb_msg->data, nBytesToCopy);
+ cdf_mem_copy((frame + nBytesToCopy), noa_stream, noa_len);
+ cdf_mem_copy((frame + nBytesToCopy + noa_len),
+ mb_msg->data + nBytesToCopy,
+ msg_len - nBytesToCopy - noa_len);
+
+ } else {
+ cdf_mem_copy(frame, mb_msg->data, msg_len);
+ }
+
+#ifdef WLAN_FEATURE_11W
+ action_hdr = (tpSirMacActionFrameHdr) (frame + sizeof(tSirMacMgmtHdr));
+
+ /*
+ * Setting Protected bit for SA_QUERY Action Frame
+ * This has to be based on the current Connection with the
+ * station lim_set_protected_bit API will set the protected bit
+ * if PMF
+ */
+ if ((SIR_MAC_MGMT_ACTION == fc->subType) &&
+ (SIR_MAC_ACTION_SA_QUERY == action_hdr->category)) {
+ mac_hdr = (tpSirMacMgmtHdr) frame;
+ session_entry = pe_find_session_by_bssid(mac_ctx,
+ (uint8_t *) mb_msg->data + BSSID_OFFSET,
+ &session_id);
+
+ /*
+ * Check for session corresponding to ADDR2 ss supplicant
+ * is filling ADDR2 with BSSID
+ */
+ if (NULL == session_entry) {
+ session_entry = pe_find_session_by_bssid(mac_ctx,
+ (uint8_t *) mb_msg->data + ADDR2_OFFSET,
+ &session_id);
+ }
+
+ if (NULL != session_entry) {
+ lim_set_protected_bit(mac_ctx, session_entry,
+ mac_hdr->da, mac_hdr);
+ } else {
+ lim_log(mac_ctx, LOGE,
+ FL("Dropping SA Query - PE Session not found"));
+ lim_send_sme_rsp(mac_ctx,
+ eWNI_SME_ACTION_FRAME_SEND_CNF,
+ CDF_STATUS_E_FAILURE, mb_msg->sessionId, 0);
+ cds_packet_free((void *)packet);
+ return;
+ }
+
+ /*
+ * If wep bit is not set in MAC header then we are trying to
+ * send SA Query via non PMF connection. Drop the packet.
+ */
+ if (0 == mac_hdr->fc.wep) {
+ lim_log(mac_ctx, LOGE,
+ FL("Dropping SA Query due to non PMF conne."));
+ lim_send_sme_rsp(mac_ctx,
+ eWNI_SME_ACTION_FRAME_SEND_CNF,
+ CDF_STATUS_E_FAILURE, mb_msg->sessionId, 0);
+ cds_packet_free((void *)packet);
+ return;
+ }
+ }
+#endif
+ lim_tx_action_frame(mac_ctx, mb_msg, msg_len, packet, frame);
+ return;
+}
+
+void lim_abort_remain_on_chan(tpAniSirGlobal pMac, uint8_t sessionId,
+ uint32_t scan_id)
+{
+ lim_process_abort_scan_ind(pMac, sessionId, scan_id);
+}
+
+/* Power Save Related Functions */
+tSirRetStatus __lim_process_sme_no_a_update(tpAniSirGlobal pMac, uint32_t *pMsgBuf)
+{
+ tpP2pPsConfig pNoA;
+ tpP2pPsParams pMsgNoA;
+ tSirMsgQ msg;
+
+ pNoA = (tpP2pPsConfig) pMsgBuf;
+
+ pMsgNoA = cdf_mem_malloc(sizeof(tP2pPsConfig));
+ if (NULL == pMsgNoA) {
+ lim_log(pMac, LOGE,
+ FL("Unable to allocate memory during NoA Update"));
+ return eSIR_MEM_ALLOC_FAILED;
+ }
+
+ cdf_mem_set((uint8_t *) pMsgNoA, sizeof(tP2pPsConfig), 0);
+ pMsgNoA->opp_ps = pNoA->opp_ps;
+ pMsgNoA->ctWindow = pNoA->ctWindow;
+ pMsgNoA->duration = pNoA->duration;
+ pMsgNoA->interval = pNoA->interval;
+ pMsgNoA->count = pNoA->count;
+ pMsgNoA->single_noa_duration = pNoA->single_noa_duration;
+ pMsgNoA->psSelection = pNoA->psSelection;
+ pMsgNoA->sessionId = pNoA->sessionid;
+
+ msg.type = WMA_SET_P2P_GO_NOA_REQ;
+ msg.reserved = 0;
+ msg.bodyptr = pMsgNoA;
+ msg.bodyval = 0;
+
+ if (eSIR_SUCCESS != wma_post_ctrl_msg(pMac, &msg)) {
+ lim_log(pMac, LOGE, FL("halPostMsgApi failed"));
+ return eSIR_FAILURE;
+ }
+
+ return eSIR_SUCCESS;
+} /*** end __limProcessSmeGoNegReq() ***/
diff --git a/core/mac/src/pe/lim/lim_process_action_frame.c b/core/mac/src/pe/lim/lim_process_action_frame.c
new file mode 100644
index 0000000..c77ae53
--- /dev/null
+++ b/core/mac/src/pe/lim/lim_process_action_frame.c
@@ -0,0 +1,2093 @@
+/*
+ * Copyright (c) 2012-2015 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_process_action_frame.cc contains the code
+ * for processing Action Frame.
+ * Author: Michael Lui
+ * Date: 05/23/03
+ * History:-
+ * Date Modified by Modification Information
+ * --------------------------------------------------------------------
+ *
+ */
+#include "cds_api.h"
+#include "wni_api.h"
+#include "sir_api.h"
+#include "ani_global.h"
+#include "wni_cfg.h"
+#include "sch_api.h"
+#include "utils_api.h"
+#include "lim_types.h"
+#include "lim_utils.h"
+#include "lim_assoc_utils.h"
+#include "lim_security_utils.h"
+#include "lim_ser_des_utils.h"
+#include "lim_send_sme_rsp_messages.h"
+#include "parser_api.h"
+#include "lim_admit_control.h"
+#include "wmm_apsd.h"
+#include "lim_send_messages.h"
+#if defined WLAN_FEATURE_VOWIFI
+#include "rrm_api.h"
+#endif
+#include "lim_session_utils.h"
+
+#include "wma_types.h"
+
+
+#define BA_DEFAULT_TX_BUFFER_SIZE 64
+
+/* Note: The test passes if the STAUT stops sending any frames, and no further
+ frames are transmitted on this channel by the station when the AP has sent
+ the last 6 beacons, with the channel switch information elements as seen
+ with the sniffer.*/
+#define SIR_CHANSW_TX_STOP_MAX_COUNT 6
+/**-----------------------------------------------------------------
+ \fn lim_stop_tx_and_switch_channel
+ \brief Stops the transmission if channel switch mode is silent and
+ starts the channel switch timer.
+
+ \param pMac
+ \return NONE
+ -----------------------------------------------------------------*/
+void lim_stop_tx_and_switch_channel(tpAniSirGlobal pMac, uint8_t sessionId)
+{
+ tpPESession psessionEntry;
+
+ psessionEntry = pe_find_session_by_session_id(pMac, sessionId);
+
+ if (NULL == psessionEntry) {
+ lim_log(pMac, LOGE, FL("Session %d not active"), sessionId);
+ return;
+ }
+
+ PELOG1(lim_log(pMac, LOG1, FL("Channel switch Mode == %d"),
+ psessionEntry->gLimChannelSwitch.switchMode);
+ )
+
+ if (psessionEntry->gLimChannelSwitch.switchMode ==
+ eSIR_CHANSW_MODE_SILENT
+ || psessionEntry->gLimChannelSwitch.switchCount <=
+ SIR_CHANSW_TX_STOP_MAX_COUNT) {
+ /* Freeze the transmission */
+ lim_frame_transmission_control(pMac, eLIM_TX_ALL, eLIM_STOP_TX);
+
+ } else {
+ /* Resume the transmission */
+ lim_frame_transmission_control(pMac, eLIM_TX_ALL, eLIM_RESUME_TX);
+ }
+
+ pMac->lim.limTimers.gLimChannelSwitchTimer.sessionId = sessionId;
+ /* change the channel immediatly only if
+ * the channel switch count is 0
+ */
+ if (psessionEntry->gLimChannelSwitch.switchCount == 0) {
+ lim_process_channel_switch_timeout(pMac);
+ return;
+ }
+ MTRACE(mac_trace
+ (pMac, TRACE_CODE_TIMER_ACTIVATE, sessionId,
+ eLIM_CHANNEL_SWITCH_TIMER));
+
+ if (tx_timer_activate(&pMac->lim.limTimers.gLimChannelSwitchTimer) !=
+ TX_SUCCESS) {
+ lim_log(pMac, LOGP, FL("tx_timer_activate failed"));
+ }
+ return;
+}
+
+/**------------------------------------------------------------
+ \fn lim_start_channel_switch
+ \brief Switches the channel if switch count == 0, otherwise
+ starts the timer for channel switch and stops BG scan
+ and heartbeat timer tempororily.
+
+ \param pMac
+ \param psessionEntry
+ \return NONE
+ ------------------------------------------------------------*/
+tSirRetStatus lim_start_channel_switch(tpAniSirGlobal pMac,
+ tpPESession psessionEntry)
+{
+ PELOG1(lim_log(pMac, LOG1, FL("Starting the channel switch"));)
+
+ /*If channel switch is already running and it is on a different session, just return */
+ /*This need to be removed for MCC */
+ if ((lim_is_chan_switch_running(pMac) &&
+ psessionEntry->gLimSpecMgmt.dot11hChanSwState !=
+ eLIM_11H_CHANSW_RUNNING) || psessionEntry->csaOffloadEnable) {
+ lim_log(pMac, LOGW, FL("Ignoring channel switch on session %d"),
+ psessionEntry->peSessionId);
+ return eSIR_SUCCESS;
+ }
+
+ /* Deactivate and change reconfigure the timeout value */
+ /* lim_deactivate_and_change_timer(pMac, eLIM_CHANNEL_SWITCH_TIMER); */
+ MTRACE(mac_trace
+ (pMac, TRACE_CODE_TIMER_DEACTIVATE, psessionEntry->peSessionId,
+ eLIM_CHANNEL_SWITCH_TIMER));
+ if (tx_timer_deactivate(&pMac->lim.limTimers.gLimChannelSwitchTimer) !=
+ eSIR_SUCCESS) {
+ lim_log(pMac, LOGP, FL("tx_timer_deactivate failed!"));
+ return eSIR_FAILURE;
+ }
+
+ if (tx_timer_change(&pMac->lim.limTimers.gLimChannelSwitchTimer,
+ psessionEntry->gLimChannelSwitch.switchTimeoutValue,
+ 0) != TX_SUCCESS) {
+ lim_log(pMac, LOGP, FL("tx_timer_change failed "));
+ return eSIR_FAILURE;
+ }
+
+ /* Follow the channel switch, forget about the previous quiet. */
+ /* If quiet is running, chance is there to resume tx on its timeout. */
+ /* so stop timer for a safer side. */
+ if (psessionEntry->gLimSpecMgmt.quietState == eLIM_QUIET_BEGIN) {
+ MTRACE(mac_trace
+ (pMac, TRACE_CODE_TIMER_DEACTIVATE,
+ psessionEntry->peSessionId, eLIM_QUIET_TIMER));
+ if (tx_timer_deactivate(&pMac->lim.limTimers.gLimQuietTimer) !=
+ TX_SUCCESS) {
+ lim_log(pMac, LOGP, FL("tx_timer_deactivate failed"));
+ return eSIR_FAILURE;
+ }
+ } else if (psessionEntry->gLimSpecMgmt.quietState == eLIM_QUIET_RUNNING) {
+ MTRACE(mac_trace
+ (pMac, TRACE_CODE_TIMER_DEACTIVATE,
+ psessionEntry->peSessionId, eLIM_QUIET_BSS_TIMER));
+ if (tx_timer_deactivate(&pMac->lim.limTimers.gLimQuietBssTimer)
+ != TX_SUCCESS) {
+ lim_log(pMac, LOGP, FL("tx_timer_deactivate failed"));
+ return eSIR_FAILURE;
+ }
+ }
+ psessionEntry->gLimSpecMgmt.quietState = eLIM_QUIET_INIT;
+
+ /* Prepare for 11h channel switch */
+ lim_prepare_for11h_channel_switch(pMac, psessionEntry);
+
+ /** Dont add any more statements here as we posted finish scan request
+ * to HAL, wait till we get the response
+ */
+ return eSIR_SUCCESS;
+}
+
+/**
+ * __lim_process_channel_switch_action_frame() - to process channel switch
+ * @mac_ctx: Pointer to Global MAC structure
+ * @rx_pkt_info: A pointer to packet info structure
+ *
+ * This routine will be called to process channel switch action frame
+ *
+ * Return: None
+ */
+
+static void __lim_process_channel_switch_action_frame(tpAniSirGlobal mac_ctx,
+ uint8_t *rx_pkt_info, tpPESession session)
+{
+ tpSirMacMgmtHdr mac_hdr;
+ uint8_t *body_ptr;
+ tDot11fChannelSwitch *chnl_switch_frame;
+ uint16_t bcn_period;
+ uint32_t val, frame_len, status;
+ tLimChannelSwitchInfo *ch_switch_params;
+ struct sDot11fIEWiderBWChanSwitchAnn *wbw_chnlswitch_ie = NULL;
+ struct sLimWiderBWChannelSwitch *lim_wbw_chnlswitch_info = NULL;
+ struct sDot11fIEsec_chan_offset_ele *sec_chnl_offset = NULL;
+
+ mac_hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info);
+ body_ptr = WMA_GET_RX_MPDU_DATA(rx_pkt_info);
+ frame_len = WMA_GET_RX_PAYLOAD_LEN(rx_pkt_info);
+
+ PELOG3(lim_log(mac_ctx, LOG3,
+ FL("Received Channel switch action frame"));)
+ if (!session->lim11hEnable)
+ return;
+
+ chnl_switch_frame = cdf_mem_malloc(sizeof(*chnl_switch_frame));
+ if (NULL == chnl_switch_frame) {
+ lim_log(mac_ctx, LOGE, FL("AllocateMemory failed"));
+ return;
+ }
+
+ /* Unpack channel switch frame */
+ status = dot11f_unpack_channel_switch(mac_ctx, body_ptr, frame_len,
+ chnl_switch_frame);
+
+ if (DOT11F_FAILED(status)) {
+ lim_log(mac_ctx, LOGE,
+ FL("Failed to unpack and parse (0x%08x, %d bytes)"),
+ status, frame_len);
+ cdf_mem_free(chnl_switch_frame);
+ return;
+ } else if (DOT11F_WARNED(status)) {
+ lim_log(mac_ctx, LOGW,
+ FL("warning: unpack 11h-CHANSW Req(0x%08x, %d bytes)"),
+ status, frame_len);
+ }
+
+ if (!(cdf_mem_compare((uint8_t *) &session->bssId,
+ (uint8_t *) &mac_hdr->sa, sizeof(tSirMacAddr)))) {
+ lim_log(mac_ctx, LOG1,
+ FL("Rcvd action frame not from our BSS, dropping..."));
+ cdf_mem_free(chnl_switch_frame);
+ return;
+ }
+ /* copy the beacon interval from session */
+ val = session->beaconParams.beaconInterval;
+ ch_switch_params = &session->gLimChannelSwitch;
+ bcn_period = (uint16_t)val;
+ ch_switch_params->primaryChannel =
+ chnl_switch_frame->ChanSwitchAnn.newChannel;
+ ch_switch_params->switchCount =
+ chnl_switch_frame->ChanSwitchAnn.switchCount;
+ ch_switch_params->switchTimeoutValue =
+ SYS_MS_TO_TICKS(bcn_period) *
+ session->gLimChannelSwitch.switchCount;
+ ch_switch_params->switchMode =
+ chnl_switch_frame->ChanSwitchAnn.switchMode;
+
+ /* Only primary channel switch element is present */
+ ch_switch_params->state = eLIM_CHANNEL_SWITCH_PRIMARY_ONLY;
+ ch_switch_params->ch_width = CH_WIDTH_20MHZ;
+
+ if (chnl_switch_frame->WiderBWChanSwitchAnn.present
+ && session->vhtCapability) {
+ wbw_chnlswitch_ie = &chnl_switch_frame->WiderBWChanSwitchAnn;
+ session->gLimWiderBWChannelSwitch.newChanWidth =
+ wbw_chnlswitch_ie->newChanWidth;
+ session->gLimWiderBWChannelSwitch.newCenterChanFreq0 =
+ wbw_chnlswitch_ie->newCenterChanFreq0;
+ session->gLimWiderBWChannelSwitch.newCenterChanFreq1 =
+ wbw_chnlswitch_ie->newCenterChanFreq1;
+ }
+ lim_log(mac_ctx, LOG3,
+ FL("Rcv Chnl Swtch Frame: Timeout in %d ticks"),
+ session->gLimChannelSwitch.switchTimeoutValue);
+ if (session->htSupportedChannelWidthSet) {
+ sec_chnl_offset = &chnl_switch_frame->sec_chan_offset_ele;
+ if (sec_chnl_offset->secondaryChannelOffset ==
+ PHY_DOUBLE_CHANNEL_LOW_PRIMARY) {
+ ch_switch_params->state =
+ eLIM_CHANNEL_SWITCH_PRIMARY_AND_SECONDARY;
+ ch_switch_params->ch_width = CH_WIDTH_40MHZ;
+ ch_switch_params->ch_center_freq_seg0 =
+ ch_switch_params->primaryChannel + 2;
+ } else if (sec_chnl_offset->secondaryChannelOffset ==
+ PHY_DOUBLE_CHANNEL_HIGH_PRIMARY) {
+ ch_switch_params->state =
+ eLIM_CHANNEL_SWITCH_PRIMARY_AND_SECONDARY;
+ ch_switch_params->ch_width = CH_WIDTH_40MHZ;
+ ch_switch_params->ch_center_freq_seg0 =
+ ch_switch_params->primaryChannel - 2;
+
+ }
+ if (session->vhtCapability &&
+ chnl_switch_frame->WiderBWChanSwitchAnn.present) {
+ wbw_chnlswitch_ie =
+ &chnl_switch_frame->WiderBWChanSwitchAnn;
+ ch_switch_params->ch_width =
+ wbw_chnlswitch_ie->newChanWidth + 1;
+ lim_wbw_chnlswitch_info =
+ &session->gLimWiderBWChannelSwitch;
+ ch_switch_params->ch_center_freq_seg0 =
+ lim_wbw_chnlswitch_info->newCenterChanFreq0;
+ ch_switch_params->ch_center_freq_seg1 =
+ lim_wbw_chnlswitch_info->newCenterChanFreq1;
+
+ }
+ }
+
+ if (CH_WIDTH_20MHZ == ch_switch_params->ch_width) {
+ session->htSupportedChannelWidthSet =
+ WNI_CFG_CHANNEL_BONDING_MODE_DISABLE;
+ session->htRecommendedTxWidthSet =
+ session->htSupportedChannelWidthSet;
+ }
+
+ if (eSIR_SUCCESS != lim_start_channel_switch(mac_ctx, session))
+ lim_log(mac_ctx, LOG1,
+ FL("Could not start channel switch"));
+
+ cdf_mem_free(chnl_switch_frame);
+ return;
+}
+
+#ifdef WLAN_FEATURE_11AC
+/**
+ * __lim_process_operating_mode_action_frame() - To process op mode frames
+ * @mac_ctx: pointer to mac context
+ * @rx_pkt_info: pointer to received packet info
+ * @session: pointer to session
+ *
+ * This routine is called to process operating mode action frames
+ *
+ * Return: None
+ */
+static void __lim_process_operating_mode_action_frame(tpAniSirGlobal mac_ctx,
+ uint8_t *rx_pkt_info, tpPESession session)
+{
+
+ tpSirMacMgmtHdr mac_hdr;
+ uint8_t *body_ptr;
+ tDot11fOperatingMode *operating_mode_frm;
+ uint32_t frame_len;
+ uint32_t status;
+ tpDphHashNode sta_ptr;
+ uint16_t aid;
+ uint8_t oper_mode;
+ uint8_t cb_mode;
+
+ mac_hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info);
+ body_ptr = WMA_GET_RX_MPDU_DATA(rx_pkt_info);
+ frame_len = WMA_GET_RX_PAYLOAD_LEN(rx_pkt_info);
+
+ lim_log(mac_ctx, LOG1,
+ FL("Received Operating Mode action frame"));
+ if (RF_CHAN_14 >= session->currentOperChannel)
+ cb_mode = mac_ctx->roam.configParam.channelBondingMode24GHz;
+ else
+ cb_mode = mac_ctx->roam.configParam.channelBondingMode5GHz;
+ /* Do not update the channel bonding mode if channel bonding
+ * mode is disabled in INI.
+ */
+ if (WNI_CFG_CHANNEL_BONDING_MODE_DISABLE == cb_mode) {
+ lim_log(mac_ctx, LOGW, FL("channel bonding disabled"));
+ return;
+ }
+ operating_mode_frm = cdf_mem_malloc(sizeof(*operating_mode_frm));
+ if (NULL == operating_mode_frm) {
+ lim_log(mac_ctx, LOGE, FL("AllocateMemory failed"));
+ return;
+ }
+ /* Unpack channel switch frame */
+ status = dot11f_unpack_operating_mode(mac_ctx, body_ptr, frame_len,
+ operating_mode_frm);
+ if (DOT11F_FAILED(status)) {
+ lim_log(mac_ctx, LOGE,
+ FL("Failed to unpack and parse (0x%08x, %d bytes)"),
+ status, frame_len);
+ cdf_mem_free(operating_mode_frm);
+ return;
+ } else if (DOT11F_WARNED(status)) {
+ lim_log(mac_ctx, LOGW,
+ FL("warnings while unpacking (0x%08x, %d bytes):"),
+ status, frame_len);
+ }
+ sta_ptr = dph_lookup_hash_entry(mac_ctx, mac_hdr->sa, &aid,
+ &session->dph.dphHashTable);
+ if (sta_ptr->htSupportedChannelWidthSet) {
+ if (WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ <
+ sta_ptr->vhtSupportedChannelWidthSet)
+ oper_mode = eHT_CHANNEL_WIDTH_160MHZ;
+ else
+ oper_mode = sta_ptr->vhtSupportedChannelWidthSet + 1;
+ } else {
+ oper_mode = eHT_CHANNEL_WIDTH_20MHZ;
+ }
+ if (oper_mode != operating_mode_frm->OperatingMode.chanWidth) {
+ lim_log(mac_ctx, LOGE,
+ FL(" received Chanwidth %d, staIdx = %d"),
+ (operating_mode_frm->OperatingMode.chanWidth),
+ sta_ptr->staIndex);
+
+ lim_log(mac_ctx, LOGE,
+ FL(" MAC - %0x:%0x:%0x:%0x:%0x:%0x"),
+ mac_hdr->sa[0], mac_hdr->sa[1], mac_hdr->sa[2],
+ mac_hdr->sa[3], mac_hdr->sa[4], mac_hdr->sa[5]);
+
+ if (operating_mode_frm->OperatingMode.chanWidth ==
+ eHT_CHANNEL_WIDTH_160MHZ) {
+ sta_ptr->vhtSupportedChannelWidthSet =
+ WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ;
+ sta_ptr->htSupportedChannelWidthSet =
+ eHT_CHANNEL_WIDTH_40MHZ;
+ } else if (operating_mode_frm->OperatingMode.chanWidth ==
+ eHT_CHANNEL_WIDTH_80MHZ) {
+ sta_ptr->vhtSupportedChannelWidthSet =
+ WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ;
+ sta_ptr->htSupportedChannelWidthSet =
+ eHT_CHANNEL_WIDTH_40MHZ;
+ } else if (operating_mode_frm->OperatingMode.chanWidth ==
+ eHT_CHANNEL_WIDTH_40MHZ) {
+ sta_ptr->vhtSupportedChannelWidthSet =
+ WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ;
+ sta_ptr->htSupportedChannelWidthSet =
+ eHT_CHANNEL_WIDTH_40MHZ;
+ } else if (operating_mode_frm->OperatingMode.chanWidth ==
+ eHT_CHANNEL_WIDTH_20MHZ) {
+ sta_ptr->vhtSupportedChannelWidthSet =
+ WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ;
+ sta_ptr->htSupportedChannelWidthSet =
+ eHT_CHANNEL_WIDTH_20MHZ;
+ }
+ lim_check_vht_op_mode_change(mac_ctx, session,
+ operating_mode_frm->OperatingMode.chanWidth,
+ sta_ptr->staIndex, mac_hdr->sa);
+ }
+
+ if (sta_ptr->vhtSupportedRxNss !=
+ (operating_mode_frm->OperatingMode.rxNSS + 1)) {
+ sta_ptr->vhtSupportedRxNss =
+ operating_mode_frm->OperatingMode.rxNSS + 1;
+ lim_set_nss_change(mac_ctx, session, sta_ptr->vhtSupportedRxNss,
+ sta_ptr->staIndex, mac_hdr->sa);
+ }
+ cdf_mem_free(operating_mode_frm);
+ return;
+}
+
+/**
+ * __lim_process_gid_management_action_frame() - To process group-id mgmt frames
+ * @mac_ctx: Pointer to mac context
+ * @rx_pkt_info: Rx packet info
+ * @session: pointer to session
+ *
+ * This routine will be called to process group id management frames
+ *
+ * Return: none
+ */
+static void __lim_process_gid_management_action_frame(tpAniSirGlobal mac_ctx,
+ uint8_t *rx_pkt_info, tpPESession session)
+{
+
+ uint8_t *body_ptr;
+ uint16_t aid;
+ uint32_t frame_len, status, membership = 0, usr_position = 0;
+ uint32_t *mem_lower, *mem_upper, *mem_cur;
+ tpSirMacMgmtHdr mac_hdr;
+ tDot11fVHTGidManagementActionFrame *gid_mgmt_frame;
+ tpDphHashNode sta_ptr;
+ struct sDot11fFfVhtMembershipStatusArray *vht_member_status = NULL;
+ struct sDot11fFfVhtUserPositionArray *vht_user_position = NULL;
+
+ mac_hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info);
+ body_ptr = WMA_GET_RX_MPDU_DATA(rx_pkt_info);
+ frame_len = WMA_GET_RX_PAYLOAD_LEN(rx_pkt_info);
+
+ lim_log(mac_ctx, LOG3, FL("Received GID Management action frame"));
+ gid_mgmt_frame = cdf_mem_malloc(sizeof(*gid_mgmt_frame));
+ if (NULL == gid_mgmt_frame) {
+ lim_log(mac_ctx, LOGE, FL("AllocateMemory failed"));
+ return;
+ }
+
+ /* Unpack Gid Mangement Action frame */
+ status = dot11f_unpack_vht_gid_management_action_frame(mac_ctx,
+ body_ptr, frame_len, gid_mgmt_frame);
+ if (DOT11F_FAILED(status)) {
+ lim_log(mac_ctx, LOGE,
+ FL("Fail to parse an Grp id frame (0x%08x, %d bytes):"),
+ status, frame_len);
+ cdf_mem_free(gid_mgmt_frame);
+ return;
+ } else if (DOT11F_WARNED(status)) {
+ lim_log(mac_ctx, LOGW,
+ FL("warnings while unpacking Grp id frm (0x%08x, %d bytes):"),
+ status, frame_len);
+ }
+ sta_ptr = dph_lookup_hash_entry(mac_ctx, mac_hdr->sa, &aid,
+ &session->dph.dphHashTable);
+ lim_log(mac_ctx, LOGE,
+ FL("received Gid Management Action Frame , staIdx = %d"),
+ sta_ptr->staIndex);
+
+ lim_log(mac_ctx, LOGE,
+ FL(" MAC - %0x:%0x:%0x:%0x:%0x:%0x"),
+ mac_hdr->sa[0], mac_hdr->sa[1], mac_hdr->sa[2],
+ mac_hdr->sa[3], mac_hdr->sa[4], mac_hdr->sa[5]);
+ vht_member_status = &gid_mgmt_frame->VhtMembershipStatusArray;
+ mem_lower = (uint32_t *) vht_member_status->membershipStatusArray;
+ mem_upper = (uint32_t *) &vht_member_status->membershipStatusArray[4];
+
+ if (*mem_lower && *mem_upper) {
+ lim_log(mac_ctx, LOGE,
+ FL("rcved frame with mult group ID set, staIdx = %d"),
+ sta_ptr->staIndex);
+ goto out;
+ }
+ if (*mem_lower) {
+ mem_cur = mem_lower;
+ } else if (*mem_upper) {
+ mem_cur = mem_upper;
+ membership += sizeof(uint32_t);
+ } else {
+ lim_log(mac_ctx, LOGE,
+ FL("rcved Gid frame with no group ID set, staIdx = %d"),
+ sta_ptr->staIndex);
+ goto out;
+ }
+ while (!(*mem_cur & 1)) {
+ *mem_cur >>= 1;
+ ++membership;
+ }
+ if (*mem_cur) {
+ lim_log(mac_ctx, LOGE,
+ FL("rcved frame with mult group ID set, staIdx = %d"),
+ sta_ptr->staIndex);
+ goto out;
+ }
+
+ /*Just read the last two bits */
+ vht_user_position = &gid_mgmt_frame->VhtUserPositionArray;
+ usr_position = vht_user_position->userPositionArray[membership] & 0x3;
+ lim_check_membership_user_position(mac_ctx, session, membership,
+ usr_position, sta_ptr->staIndex);
+out:
+ cdf_mem_free(gid_mgmt_frame);
+ return;
+}
+
+#endif
+
+static void
+__lim_process_add_ts_req(tpAniSirGlobal pMac, uint8_t *pRxPacketInfo,
+ tpPESession psessionEntry)
+{
+}
+
+/**
+ * __lim_process_add_ts_rsp() - To process add ts response frame
+ * @mac_ctx: pointer to mac context
+ * @rx_pkt_info: Received packet info
+ * @session: pointer to session
+ *
+ * This routine is to handle add ts response frame
+ *
+ * Return: none
+ */
+static void __lim_process_add_ts_rsp(tpAniSirGlobal mac_ctx,
+ uint8_t *rx_pkt_info, tpPESession session)
+{
+ tSirAddtsRspInfo addts;
+ tSirRetStatus retval;
+ tpSirMacMgmtHdr mac_hdr;
+ tpDphHashNode sta_ptr;
+ uint16_t aid;
+ uint32_t frameLen;
+ uint8_t *body_ptr;
+ tpLimTspecInfo tspec_info;
+ uint8_t ac;
+ tpDphHashNode sta_ds_ptr = NULL;
+ uint8_t rsp_reqd = 1;
+ uint32_t cfg_len;
+ tSirMacAddr peer_macaddr;
+
+ mac_hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info);
+ body_ptr = WMA_GET_RX_MPDU_DATA(rx_pkt_info);
+ frameLen = WMA_GET_RX_PAYLOAD_LEN(rx_pkt_info);
+
+ lim_log(mac_ctx, LOGW, "Recv AddTs Response");
+ if (LIM_IS_AP_ROLE(session) ||
+ LIM_IS_BT_AMP_AP_ROLE(session)) {
+ lim_log(mac_ctx, LOGW,
+ FL("AddTsRsp recvd at AP: ignoring"));
+ return;
+ }
+
+ sta_ptr = dph_lookup_hash_entry(mac_ctx, mac_hdr->sa, &aid,
+ &session->dph.dphHashTable);
+ if (sta_ptr == NULL) {
+ lim_log(mac_ctx, LOGE,
+ FL("Station context not found - ignoring AddTsRsp"));
+ return;
+ }
+
+ retval = sir_convert_addts_rsp2_struct(mac_ctx, body_ptr,
+ frameLen, &addts);
+ if (retval != eSIR_SUCCESS) {
+ lim_log(mac_ctx, LOGW,
+ FL("AddTsRsp parsing failed (error %d)"), retval);
+ return;
+ }
+ /*
+ * don't have to check for qos/wme capabilities since we wouldn't have
+ * this flag set otherwise
+ */
+ if (!mac_ctx->lim.gLimAddtsSent) {
+ /* we never sent an addts request! */
+ lim_log(mac_ctx, LOGW,
+ FL("rx AddTsRsp but no req was ever sent-ignoring"));
+ return;
+ }
+
+ if (mac_ctx->lim.gLimAddtsReq.req.dialogToken != addts.dialogToken) {
+ lim_log(mac_ctx, LOGW,
+ FL("token mismatch (got %d, exp %d) - ignoring"),
+ addts.dialogToken,
+ mac_ctx->lim.gLimAddtsReq.req.dialogToken);
+ return;
+ }
+
+ /*
+ * for successful addts reponse, try to add the classifier.
+ * if this fails for any reason, we should send a delts request to the
+ * ap for now, its ok not to send a delts since we are going to add
+ * support for multiple tclas soon and until then we won't send any
+ * addts requests with multiple tclas elements anyway.
+ * In case of addClassifier failure, we just let the addts timer run out
+ */
+ if (((addts.tspec.tsinfo.traffic.accessPolicy ==
+ SIR_MAC_ACCESSPOLICY_HCCA) ||
+ (addts.tspec.tsinfo.traffic.accessPolicy ==
+ SIR_MAC_ACCESSPOLICY_BOTH)) &&
+ (addts.status == eSIR_MAC_SUCCESS_STATUS)) {
+ /* add the classifier - this should always succeed */
+ if (addts.numTclas > 1) {
+ /* currently no support for multiple tclas elements */
+ lim_log(mac_ctx, LOGE,
+ FL("Sta %d: Too many Tclas (%d), 1 supported"),
+ aid, addts.numTclas);
+ return;
+ } else if (addts.numTclas == 1) {
+ lim_log(mac_ctx, LOGW,
+ FL("Response from STA %d: tsid %d, UP %d, OK!"),
+ aid, addts.tspec.tsinfo.traffic.tsid,
+ addts.tspec.tsinfo.traffic.userPrio);
+ }
+ }
+ lim_log(mac_ctx, LOGW, FL("Recv AddTsRsp: tsid %d, UP %d, status %d "),
+ addts.tspec.tsinfo.traffic.tsid,
+ addts.tspec.tsinfo.traffic.userPrio, addts.status);
+
+ /* deactivate the response timer */
+ lim_deactivate_and_change_timer(mac_ctx, eLIM_ADDTS_RSP_TIMER);
+
+ if (addts.status != eSIR_MAC_SUCCESS_STATUS) {
+ lim_log(mac_ctx, LOGW,
+ FL("Recv AddTsRsp: tsid %d, UP %d, status %d "),
+ addts.tspec.tsinfo.traffic.tsid,
+ addts.tspec.tsinfo.traffic.userPrio, addts.status);
+ lim_send_sme_addts_rsp(mac_ctx, true, addts.status, session,
+ addts.tspec, session->smeSessionId,
+ session->transactionId);
+
+ /* clear the addts flag */
+ mac_ctx->lim.gLimAddtsSent = false;
+
+ return;
+ }
+#ifdef FEATURE_WLAN_ESE
+ if (addts.tsmPresent) {
+ lim_log(mac_ctx, LOGW, "TSM IE Present");
+ session->eseContext.tsm.tid =
+ addts.tspec.tsinfo.traffic.userPrio;
+ cdf_mem_copy(&session->eseContext.tsm.tsmInfo,
+ &addts.tsmIE, sizeof(tSirMacESETSMIE));
+#ifdef FEATURE_WLAN_ESE_UPLOAD
+ lim_send_sme_tsm_ie_ind(mac_ctx, session, addts.tsmIE.tsid,
+ addts.tsmIE.state,
+ addts.tsmIE.msmt_interval);
+#else
+ limActivateTSMStatsTimer(mac_ctx, session);
+#endif /* FEATURE_WLAN_ESE_UPLOAD */
+ }
+#endif
+ /*
+ * Since AddTS response was successful, check for the PSB flag
+ * and directional flag inside the TS Info field.
+ * An AC is trigger enabled AC if the PSB subfield is set to 1
+ * in the uplink direction.
+ * An AC is delivery enabled AC if the PSB subfield is set to 1
+ * in the downlink direction.
+ * An AC is trigger and delivery enabled AC if the PSB subfield
+ * is set to 1 in the bi-direction field.
+ */
+ if (addts.tspec.tsinfo.traffic.psb == 1)
+ lim_set_tspec_uapsd_mask_per_session(mac_ctx, session,
+ &addts.tspec.tsinfo,
+ SET_UAPSD_MASK);
+ else
+ lim_set_tspec_uapsd_mask_per_session(mac_ctx, session,
+ &addts.tspec.tsinfo,
+ CLEAR_UAPSD_MASK);
+
+ /*
+ * ADDTS success, so AC is now admitted. We shall now use the default
+ * EDCA parameters as advertised by AP and send the updated EDCA params
+ * to HAL.
+ */
+ ac = upToAc(addts.tspec.tsinfo.traffic.userPrio);
+ if (addts.tspec.tsinfo.traffic.direction ==
+ SIR_MAC_DIRECTION_UPLINK) {
+ session->gAcAdmitMask[SIR_MAC_DIRECTION_UPLINK] |=
+ (1 << ac);
+ } else if (addts.tspec.tsinfo.traffic.direction ==
+ SIR_MAC_DIRECTION_DNLINK) {
+ session->gAcAdmitMask[SIR_MAC_DIRECTION_DNLINK] |=
+ (1 << ac);
+ } else if (addts.tspec.tsinfo.traffic.direction ==
+ SIR_MAC_DIRECTION_BIDIR) {
+ session->gAcAdmitMask[SIR_MAC_DIRECTION_UPLINK] |=
+ (1 << ac);
+ session->gAcAdmitMask[SIR_MAC_DIRECTION_DNLINK] |=
+ (1 << ac);
+ }
+ lim_set_active_edca_params(mac_ctx, session->gLimEdcaParams,
+ session);
+ sta_ds_ptr = dph_get_hash_entry(mac_ctx, DPH_STA_HASH_INDEX_PEER,
+ &session->dph.dphHashTable);
+ if (sta_ds_ptr != NULL)
+ lim_send_edca_params(mac_ctx, session->gLimEdcaParamsActive,
+ sta_ds_ptr->bssId);
+ else
+ lim_log(mac_ctx, LOGE, FL("Self entry missing in Hash Table "));
+ sir_copy_mac_addr(peer_macaddr, session->bssId);
+ /* if schedule is not present then add TSPEC with svcInterval as 0. */
+ if (!addts.schedulePresent)
+ addts.schedule.svcInterval = 0;
+ if (eSIR_SUCCESS !=
+ lim_tspec_add(mac_ctx, sta_ptr->staAddr, sta_ptr->assocId,
+ &addts.tspec, addts.schedule.svcInterval, &tspec_info)) {
+ lim_log(mac_ctx, LOGE,
+ FL("Adding entry in lim Tspec Table failed "));
+ lim_send_delts_req_action_frame(mac_ctx, peer_macaddr, rsp_reqd,
+ &addts.tspec.tsinfo,
+ &addts.tspec, session);
+ mac_ctx->lim.gLimAddtsSent = false;
+ return;
+ /*
+ * Error handling. send the response with error status.
+ * need to send DelTS to tear down the TSPEC status.
+ */
+ }
+ if ((addts.tspec.tsinfo.traffic.accessPolicy !=
+ SIR_MAC_ACCESSPOLICY_EDCA) ||
+ ((upToAc(addts.tspec.tsinfo.traffic.userPrio) < MAX_NUM_AC))) {
+#ifdef FEATURE_WLAN_ESE
+ retval = lim_send_hal_msg_add_ts(mac_ctx,
+ sta_ptr->staIndex, tspec_info->idx,
+ addts.tspec, session->peSessionId,
+ addts.tsmIE.msmt_interval);
+#else
+ retval = lim_send_hal_msg_add_ts(mac_ctx,
+ sta_ptr->staIndex, tspec_info->idx,
+ addts.tspec, session->peSessionId);
+#endif
+ if (eSIR_SUCCESS != retval) {
+ lim_admit_control_delete_ts(mac_ctx, sta_ptr->assocId,
+ &addts.tspec.tsinfo, NULL, &tspec_info->idx);
+
+ /* Send DELTS action frame to AP */
+ cfg_len = sizeof(tSirMacAddr);
+ lim_send_delts_req_action_frame(mac_ctx, peer_macaddr,
+ rsp_reqd, &addts.tspec.tsinfo,
+ &addts.tspec, session);
+ lim_send_sme_addts_rsp(mac_ctx, true, retval,
+ session, addts.tspec,
+ session->smeSessionId,
+ session->transactionId);
+ mac_ctx->lim.gLimAddtsSent = false;
+ return;
+ }
+ lim_log(mac_ctx, LOGW,
+ FL("AddTsRsp received successfully(UP %d, TSID %d)"),
+ addts.tspec.tsinfo.traffic.userPrio,
+ addts.tspec.tsinfo.traffic.tsid);
+ } else {
+ lim_log(mac_ctx, LOGW,
+ FL("AddTsRsp received successfully(UP %d, TSID %d)"),
+ addts.tspec.tsinfo.traffic.userPrio,
+ addts.tspec.tsinfo.traffic.tsid);
+ lim_log(mac_ctx, LOGW,
+ FL("no ACM: Bypass sending WMA_ADD_TS_REQ to HAL "));
+ /*
+ * Use the smesessionId and smetransactionId from the PE
+ * session context
+ */
+ lim_send_sme_addts_rsp(mac_ctx, true, eSIR_SME_SUCCESS,
+ session, addts.tspec, session->smeSessionId,
+ session->transactionId);
+ }
+ /* clear the addts flag */
+ mac_ctx->lim.gLimAddtsSent = false;
+ return;
+}
+
+/**
+ * __lim_process_del_ts_req() - To process del ts response frame
+ * @mac_ctx: pointer to mac context
+ * @rx_pkt_info: Received packet info
+ * @session: pointer to session
+ *
+ * This routine is to handle del ts request frame
+ *
+ * Return: none
+ */
+static void __lim_process_del_ts_req(tpAniSirGlobal mac_ctx,
+ uint8_t *rx_pkt_info, tpPESession session)
+{
+ tSirRetStatus retval;
+ tSirDeltsReqInfo delts;
+ tpSirMacMgmtHdr mac_hdr;
+ tpDphHashNode sta_ptr;
+ uint32_t frame_len;
+ uint16_t aid;
+ uint8_t *body_ptr;
+ uint8_t ts_status;
+ tSirMacTSInfo *tsinfo;
+ uint8_t tspec_idx;
+ uint8_t ac;
+ tpDphHashNode sta_ds_ptr = NULL;
+
+ mac_hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info);
+ body_ptr = WMA_GET_RX_MPDU_DATA(rx_pkt_info);
+ frame_len = WMA_GET_RX_PAYLOAD_LEN(rx_pkt_info);
+
+ sta_ptr = dph_lookup_hash_entry(mac_ctx, mac_hdr->sa, &aid,
+ &session->dph.dphHashTable);
+ if (sta_ptr == NULL) {
+ lim_log(mac_ctx, LOGE,
+ FL("Station context not found - ignoring DelTs"));
+ return;
+ }
+ /* parse the delts request */
+ retval = sir_convert_delts_req2_struct(mac_ctx, body_ptr,
+ frame_len, &delts);
+ if (retval != eSIR_SUCCESS) {
+ lim_log(mac_ctx, LOGW,
+ FL("DelTs parsing failed (error %d)"), retval);
+ return;
+ }
+
+ if (delts.wmeTspecPresent) {
+ if ((!session->limWmeEnabled) || (!sta_ptr->wmeEnabled)) {
+ lim_log(mac_ctx, LOGW,
+ FL("Ignore delts req: wme not enabled"));
+ return;
+ }
+ lim_log(mac_ctx, LOG2, FL("WME Delts received"));
+ } else if ((session->limQosEnabled) && sta_ptr->lleEnabled) {
+ lim_log(mac_ctx, LOG2, FL("11e QoS Delts received"));
+ } else if ((session->limWsmEnabled) && sta_ptr->wsmEnabled) {
+ lim_log(mac_ctx, LOG2, FL("WSM Delts received"));
+ } else {
+ lim_log(mac_ctx, LOGW,
+ FL("Ignoring delts request: qos not enabled/capable"));
+ return;
+ }
+
+ tsinfo = delts.wmeTspecPresent ? &delts.tspec.tsinfo : &delts.tsinfo;
+
+ /* if no Admit Control, ignore the request */
+ if ((tsinfo->traffic.accessPolicy == SIR_MAC_ACCESSPOLICY_EDCA)) {
+
+ if (upToAc(tsinfo->traffic.userPrio) >= MAX_NUM_AC) {
+ lim_log(mac_ctx, LOGW,
+ FL("DelTs with UP %d has no AC - ignoring req"),
+ tsinfo->traffic.userPrio);
+ return;
+ }
+ }
+
+ if (!LIM_IS_AP_ROLE(session) &&
+ !LIM_IS_BT_AMP_AP_ROLE(session))
+ lim_send_sme_delts_ind(mac_ctx, &delts, aid, session);
+
+ /* try to delete the TS */
+ if (eSIR_SUCCESS !=
+ lim_admit_control_delete_ts(mac_ctx, sta_ptr->assocId, tsinfo,
+ &ts_status, &tspec_idx)) {
+ lim_log(mac_ctx, LOGW, FL("Unable to Delete TS"));
+ return;
+ } else if (!((tsinfo->traffic.accessPolicy == SIR_MAC_ACCESSPOLICY_HCCA)
+ || (tsinfo->traffic.accessPolicy ==
+ SIR_MAC_ACCESSPOLICY_BOTH))){
+ /* send message to HAL to delete TS */
+ if (eSIR_SUCCESS != lim_send_hal_msg_del_ts(mac_ctx,
+ sta_ptr->staIndex, tspec_idx,
+ delts, session->peSessionId,
+ session->bssId)) {
+ lim_log(mac_ctx, LOGW,
+ FL("DelTs with UP %d failed ignoring request"),
+ tsinfo->traffic.userPrio);
+ return;
+ }
+ }
+ /*
+ * We successfully deleted the TSPEC. Update the dynamic UAPSD Mask.
+ * The AC for this TSPEC is no longer trigger enabled if this Tspec
+ * was set-up in uplink direction only.
+ * The AC for this TSPEC is no longer delivery enabled if this Tspec
+ * was set-up in downlink direction only.
+ * The AC for this TSPEC is no longer triiger enabled and delivery
+ * enabled if this Tspec was a bidirectional TSPEC.
+ */
+ lim_set_tspec_uapsd_mask_per_session(mac_ctx, session,
+ tsinfo, CLEAR_UAPSD_MASK);
+ /*
+ * We're deleting the TSPEC.
+ * The AC for this TSPEC is no longer admitted in uplink/downlink
+ * direction if this TSPEC was set-up in uplink/downlink direction only.
+ * The AC for this TSPEC is no longer admitted in both uplink and
+ * downlink directions if this TSPEC was a bi-directional TSPEC.
+ * If ACM is set for this AC and this AC is admitted only in downlink
+ * direction, PE needs to downgrade the EDCA parameter
+ * (for the AC for which TS is being deleted) to the
+ * next best AC for which ACM is not enabled, and send the
+ * updated values to HAL.
+ */
+ ac = upToAc(tsinfo->traffic.userPrio);
+ if (tsinfo->traffic.direction == SIR_MAC_DIRECTION_UPLINK) {
+ session->gAcAdmitMask[SIR_MAC_DIRECTION_UPLINK] &=
+ ~(1 << ac);
+ } else if (tsinfo->traffic.direction ==
+ SIR_MAC_DIRECTION_DNLINK) {
+ session->gAcAdmitMask[SIR_MAC_DIRECTION_DNLINK] &=
+ ~(1 << ac);
+ } else if (tsinfo->traffic.direction == SIR_MAC_DIRECTION_BIDIR) {
+ session->gAcAdmitMask[SIR_MAC_DIRECTION_UPLINK] &=
+ ~(1 << ac);
+ session->gAcAdmitMask[SIR_MAC_DIRECTION_DNLINK] &=
+ ~(1 << ac);
+ }
+ lim_set_active_edca_params(mac_ctx, session->gLimEdcaParams,
+ session);
+ sta_ds_ptr = dph_get_hash_entry(mac_ctx, DPH_STA_HASH_INDEX_PEER,
+ &session->dph.dphHashTable);
+ if (sta_ds_ptr != NULL)
+ lim_send_edca_params(mac_ctx, session->gLimEdcaParamsActive,
+ sta_ds_ptr->bssId);
+ else
+ lim_log(mac_ctx, LOGE, FL("Self entry missing in Hash Table "));
+
+ lim_log(mac_ctx, LOG1, FL("DeleteTS succeeded"));
+#ifdef FEATURE_WLAN_ESE
+#ifdef FEATURE_WLAN_ESE_UPLOAD
+ lim_send_sme_tsm_ie_ind(mac_ctx, session, 0, 0, 0);
+#else
+ lim_deactivate_and_change_timer(mac_ctx, eLIM_TSM_TIMER);
+#endif /* FEATURE_WLAN_ESE_UPLOAD */
+#endif
+}
+
+/**
+ * __lim_process_qos_map_configure_frame() - to process QoS map configure frame
+ * @mac_ctx: pointer to mac context
+ * @rx_pkt_info: pointer to received packet info
+ * @session: pointer to session
+ *
+ * This routine will called to process qos map configure frame
+ *
+ * Return: none
+ */
+static void __lim_process_qos_map_configure_frame(tpAniSirGlobal mac_ctx,
+ uint8_t *rx_pkt_info, tpPESession session)
+{
+ tpSirMacMgmtHdr mac_hdr;
+ uint32_t frame_len;
+ uint8_t *body_ptr;
+ tSirRetStatus retval;
+ mac_hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info);
+ body_ptr = WMA_GET_RX_MPDU_DATA(rx_pkt_info);
+ frame_len = WMA_GET_RX_PAYLOAD_LEN(rx_pkt_info);
+ retval = sir_convert_qos_map_configure_frame2_struct(mac_ctx,
+ body_ptr, frame_len, &session->QosMapSet);
+ if (retval != eSIR_SUCCESS) {
+ lim_log(mac_ctx, LOGE,
+ FL("QosMapConfigure frame parsing fail(error %d)"),
+ retval);
+ return;
+ }
+ lim_send_sme_mgmt_frame_ind(mac_ctx, mac_hdr->fc.subType,
+ (uint8_t *) mac_hdr,
+ frame_len + sizeof(tSirMacMgmtHdr), 0,
+ WMA_GET_RX_CH(rx_pkt_info), session, 0);
+}
+
+#ifdef ANI_SUPPORT_11H
+static void
+__lim_process_basic_meas_req(tpAniSirGlobal pMac,
+ tpSirMacMeasReqActionFrame pMeasReqFrame,
+ tSirMacAddr peerMacAddr, tpPESession psessionEntry)
+{
+ if (lim_send_meas_report_frame(pMac,
+ pMeasReqFrame,
+ peerMacAddr, psessionEntry) != eSIR_SUCCESS)
+ {
+ PELOGE(lim_log
+ (pMac, LOGE, FL("fail to send Basic Meas report "));
+ )
+ return;
+ }
+}
+static void
+__lim_process_cca_meas_req(tpAniSirGlobal pMac,
+ tpSirMacMeasReqActionFrame pMeasReqFrame,
+ tSirMacAddr peerMacAddr, tpPESession psessionEntry)
+{
+ if (lim_send_meas_report_frame(pMac,
+ pMeasReqFrame,
+ peerMacAddr, psessionEntry) != eSIR_SUCCESS)
+ {
+ PELOGE(lim_log(pMac, LOGE, FL("fail to send CCA Meas report "));)
+ return;
+ }
+}
+static void
+__lim_process_rpi_meas_req(tpAniSirGlobal pMac,
+ tpSirMacMeasReqActionFrame pMeasReqFrame,
+ tSirMacAddr peerMacAddr, tpPESession psessionEntry)
+{
+ if (lim_send_meas_report_frame(pMac,
+ pMeasReqFrame,
+ peerMacAddr, psessionEntry) != eSIR_SUCCESS)
+ {
+ PELOGE(lim_log(pMac, LOGE, FL("fail to send RPI Meas report "));)
+ return;
+ }
+}
+static void
+__lim_process_measurement_request_frame(tpAniSirGlobal pMac,
+ uint8_t *pRxPacketInfo,
+ tpPESession psessionEntry)
+{
+ tpSirMacMgmtHdr pHdr;
+ uint8_t *pBody;
+ tpSirMacMeasReqActionFrame pMeasReqFrame;
+ uint32_t frameLen;
+
+ pHdr = WMA_GET_RX_MAC_HEADER(pRxPacketInfo);
+ pBody = WMA_GET_RX_MPDU_DATA(pRxPacketInfo);
+ frameLen = WMA_GET_RX_PAYLOAD_LEN(pRxPacketInfo);
+
+ pMeasReqFrame = cdf_mem_malloc(sizeof(tSirMacMeasReqActionFrame));
+ if (NULL == pMeasReqFrame) {
+ lim_log(pMac, LOGE,
+ FL
+ ("limProcessMeasurementRequestFrame: AllocateMemory failed "));
+ return;
+ }
+
+ if (sir_convert_meas_req_frame2_struct(pMac, pBody, pMeasReqFrame, frameLen)
+ != eSIR_SUCCESS) {
+ PELOGW(lim_log
+ (pMac, LOGW,
+ FL("Rcv invalid Measurement Request Action Frame "));
+ )
+ return;
+ }
+ switch (pMeasReqFrame->measReqIE.measType) {
+ case SIR_MAC_BASIC_MEASUREMENT_TYPE:
+ __lim_process_basic_meas_req(pMac, pMeasReqFrame, pHdr->sa,
+ psessionEntry);
+ break;
+ case SIR_MAC_CCA_MEASUREMENT_TYPE:
+ __lim_process_cca_meas_req(pMac, pMeasReqFrame, pHdr->sa,
+ psessionEntry);
+ break;
+ case SIR_MAC_RPI_MEASUREMENT_TYPE:
+ __lim_process_rpi_meas_req(pMac, pMeasReqFrame, pHdr->sa,
+ psessionEntry);
+ break;
+ default:
+ PELOG1(lim_log(pMac, LOG1, FL("Unknown Measurement Type %d "),
+ pMeasReqFrame->measReqIE.measType);
+ )
+ break;
+ }
+} /*** end limProcessMeasurementRequestFrame ***/
+static void
+__lim_process_tpc_request_frame(tpAniSirGlobal pMac, uint8_t *pRxPacketInfo,
+ tpPESession psessionEntry)
+{
+ tpSirMacMgmtHdr pHdr;
+ uint8_t *pBody;
+ tpSirMacTpcReqActionFrame pTpcReqFrame;
+ uint32_t frameLen;
+ pHdr = WMA_GET_RX_MAC_HEADER(pRxPacketInfo);
+ pBody = WMA_GET_RX_MPDU_DATA(pRxPacketInfo);
+ frameLen = WMA_GET_RX_PAYLOAD_LEN(pRxPacketInfo);
+ PELOG1(lim_log
+ (pMac, LOG1,
+ FL("****LIM: Processing TPC Request from peer ****"));
+ )
+ pTpcReqFrame = cdf_mem_malloc(sizeof(tSirMacTpcReqActionFrame));
+ if (NULL == pTpcReqFrame) {
+ PELOGE(lim_log(pMac, LOGE, FL("AllocateMemory failed "));)
+ return;
+ }
+ if (sir_convert_tpc_req_frame2_struct(pMac, pBody, pTpcReqFrame, frameLen) !=
+ eSIR_SUCCESS) {
+ PELOGW(lim_log
+ (pMac, LOGW, FL("Rcv invalid TPC Req Action Frame "));
+ )
+ return;
+ }
+ if (lim_send_tpc_report_frame(pMac,
+ pTpcReqFrame,
+ pHdr->sa, psessionEntry) != eSIR_SUCCESS) {
+ PELOGE(lim_log
+ (pMac, LOGE, FL("fail to send TPC Report Frame. "));
+ )
+ return;
+ }
+}
+#endif
+
+static void
+__lim_process_sm_power_save_update(tpAniSirGlobal pMac, uint8_t *pRxPacketInfo,
+ tpPESession psessionEntry)
+{
+
+ tpSirMacMgmtHdr pHdr;
+ tDot11fSMPowerSave frmSMPower;
+ tSirMacHTMIMOPowerSaveState state;
+ tpDphHashNode pSta;
+ uint16_t aid;
+ uint32_t frameLen, nStatus;
+ uint8_t *pBody;
+
+ pHdr = WMA_GET_RX_MAC_HEADER(pRxPacketInfo);
+ pBody = WMA_GET_RX_MPDU_DATA(pRxPacketInfo);
+ frameLen = WMA_GET_RX_PAYLOAD_LEN(pRxPacketInfo);
+
+ pSta =
+ dph_lookup_hash_entry(pMac, pHdr->sa, &aid,
+ &psessionEntry->dph.dphHashTable);
+ if (pSta == NULL) {
+ lim_log(pMac, LOGE,
+ FL
+ ("STA context not found - ignoring UpdateSM PSave Mode from "));
+ lim_print_mac_addr(pMac, pHdr->sa, LOGW);
+ return;
+ }
+
+ /**Unpack the received frame */
+ nStatus = dot11f_unpack_sm_power_save(pMac, pBody, frameLen, &frmSMPower);
+
+ if (DOT11F_FAILED(nStatus)) {
+ lim_log(pMac, LOGE,
+ FL
+ ("Failed to unpack and parse a Update SM Power (0x%08x, %d bytes):"),
+ nStatus, frameLen);
+ PELOG2(sir_dump_buf
+ (pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frameLen);
+ )
+ return;
+ } else if (DOT11F_WARNED(nStatus)) {
+ lim_log(pMac, LOGW,
+ FL
+ ("There were warnings while unpacking a SMPower Save update (0x%08x, %d bytes):"),
+ nStatus, frameLen);
+ PELOG2(sir_dump_buf
+ (pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frameLen);
+ )
+ }
+
+ lim_log(pMac, LOGW,
+ FL("Received SM Power save Mode update Frame with PS_Enable:%d"
+ "PS Mode: %d"), frmSMPower.SMPowerModeSet.PowerSave_En,
+ frmSMPower.SMPowerModeSet.Mode);
+
+ /** Update in the DPH Table about the Update in the SM Power Save mode*/
+ if (frmSMPower.SMPowerModeSet.PowerSave_En
+ && frmSMPower.SMPowerModeSet.Mode)
+ state = eSIR_HT_MIMO_PS_DYNAMIC;
+ else if ((frmSMPower.SMPowerModeSet.PowerSave_En)
+ && (frmSMPower.SMPowerModeSet.Mode == 0))
+ state = eSIR_HT_MIMO_PS_STATIC;
+ else if ((frmSMPower.SMPowerModeSet.PowerSave_En == 0)
+ && (frmSMPower.SMPowerModeSet.Mode == 0))
+ state = eSIR_HT_MIMO_PS_NO_LIMIT;
+ else {
+ PELOGW(lim_log
+ (pMac, LOGW,
+ FL
+ ("Received SM Power save Mode update Frame with invalid mode"));
+ )
+ return;
+ }
+
+ if (state == pSta->htMIMOPSState) {
+ PELOGE(lim_log
+ (pMac, LOGE,
+ FL("The PEER is already set in the same mode"));
+ )
+ return;
+ }
+
+ /** Update in the HAL Station Table for the Update of the Protection Mode */
+ pSta->htMIMOPSState = state;
+ lim_post_sm_state_update(pMac, pSta->staIndex, pSta->htMIMOPSState,
+ pSta->staAddr, psessionEntry->smeSessionId);
+}
+
+#if defined WLAN_FEATURE_VOWIFI
+
+static void
+__lim_process_radio_measure_request(tpAniSirGlobal pMac, uint8_t *pRxPacketInfo,
+ tpPESession psessionEntry)
+{
+ tpSirMacMgmtHdr pHdr;
+ tDot11fRadioMeasurementRequest frm;
+ uint32_t frameLen, nStatus;
+ uint8_t *pBody;
+
+ pHdr = WMA_GET_RX_MAC_HEADER(pRxPacketInfo);
+ pBody = WMA_GET_RX_MPDU_DATA(pRxPacketInfo);
+ frameLen = WMA_GET_RX_PAYLOAD_LEN(pRxPacketInfo);
+
+ if (psessionEntry == NULL) {
+ return;
+ }
+
+ lim_send_sme_mgmt_frame_ind(pMac, pHdr->fc.subType, (uint8_t *)pHdr,
+ frameLen + sizeof(tSirMacMgmtHdr), 0,
+ WMA_GET_RX_CH(pRxPacketInfo), psessionEntry, 0);
+
+ /**Unpack the received frame */
+ nStatus =
+ dot11f_unpack_radio_measurement_request(pMac, pBody, frameLen, &frm);
+
+ if (DOT11F_FAILED(nStatus)) {
+ lim_log(pMac, LOGE,
+ FL
+ ("Failed to unpack and parse a Radio Measure request (0x%08x, %d bytes):"),
+ nStatus, frameLen);
+ PELOG2(sir_dump_buf
+ (pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frameLen);
+ )
+ return;
+ } else if (DOT11F_WARNED(nStatus)) {
+ lim_log(pMac, LOGW,
+ FL
+ ("There were warnings while unpacking a Radio Measure request (0x%08x, %d bytes):"),
+ nStatus, frameLen);
+ PELOG2(sir_dump_buf
+ (pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frameLen);
+ )
+ }
+ /* Call rrm function to handle the request. */
+
+ rrm_process_radio_measurement_request(pMac, pHdr->sa, &frm, psessionEntry);
+}
+
+static void
+__lim_process_link_measurement_req(tpAniSirGlobal pMac, uint8_t *pRxPacketInfo,
+ tpPESession psessionEntry)
+{
+ tpSirMacMgmtHdr pHdr;
+ tDot11fLinkMeasurementRequest frm;
+ uint32_t frameLen, nStatus;
+ uint8_t *pBody;
+
+ pHdr = WMA_GET_RX_MAC_HEADER(pRxPacketInfo);
+ pBody = WMA_GET_RX_MPDU_DATA(pRxPacketInfo);
+ frameLen = WMA_GET_RX_PAYLOAD_LEN(pRxPacketInfo);
+
+ if (psessionEntry == NULL) {
+ return;
+ }
+
+ /**Unpack the received frame */
+ nStatus =
+ dot11f_unpack_link_measurement_request(pMac, pBody, frameLen, &frm);
+
+ if (DOT11F_FAILED(nStatus)) {
+ lim_log(pMac, LOGE,
+ FL
+ ("Failed to unpack and parse a Link Measure request (0x%08x, %d bytes):"),
+ nStatus, frameLen);
+ PELOG2(sir_dump_buf
+ (pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frameLen);
+ )
+ return;
+ } else if (DOT11F_WARNED(nStatus)) {
+ lim_log(pMac, LOGW,
+ FL
+ ("There were warnings while unpacking a Link Measure request (0x%08x, %d bytes):"),
+ nStatus, frameLen);
+ PELOG2(sir_dump_buf
+ (pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frameLen);
+ )
+ }
+ /* Call rrm function to handle the request. */
+
+ rrm_process_link_measurement_request(pMac, pRxPacketInfo, &frm,
+ psessionEntry);
+
+}
+
+static void
+__lim_process_neighbor_report(tpAniSirGlobal pMac, uint8_t *pRxPacketInfo,
+ tpPESession psessionEntry)
+{
+ tpSirMacMgmtHdr pHdr;
+ tDot11fNeighborReportResponse *pFrm;
+ uint32_t frameLen, nStatus;
+ uint8_t *pBody;
+
+ pHdr = WMA_GET_RX_MAC_HEADER(pRxPacketInfo);
+ pBody = WMA_GET_RX_MPDU_DATA(pRxPacketInfo);
+ frameLen = WMA_GET_RX_PAYLOAD_LEN(pRxPacketInfo);
+
+ pFrm = cdf_mem_malloc(sizeof(tDot11fNeighborReportResponse));
+ if (NULL == pFrm) {
+ lim_log(pMac, LOGE,
+ FL
+ ("Unable to allocate memory in __lim_process_neighbor_report"));
+ return;
+ }
+
+ if (psessionEntry == NULL) {
+ cdf_mem_free(pFrm);
+ return;
+ }
+
+ /**Unpack the received frame */
+ nStatus =
+ dot11f_unpack_neighbor_report_response(pMac, pBody, frameLen, pFrm);
+
+ if (DOT11F_FAILED(nStatus)) {
+ lim_log(pMac, LOGE,
+ FL
+ ("Failed to unpack and parse a Neighbor report response (0x%08x, %d bytes):"),
+ nStatus, frameLen);
+ PELOG2(sir_dump_buf
+ (pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frameLen);
+ )
+ cdf_mem_free(pFrm);
+ return;
+ } else if (DOT11F_WARNED(nStatus)) {
+ lim_log(pMac, LOGW,
+ FL
+ ("There were warnings while unpacking a Neighbor report response (0x%08x, %d bytes):"),
+ nStatus, frameLen);
+ PELOG2(sir_dump_buf
+ (pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frameLen);
+ )
+ }
+ /* Call rrm function to handle the request. */
+ rrm_process_neighbor_report_response(pMac, pFrm, psessionEntry);
+
+ cdf_mem_free(pFrm);
+}
+
+#endif
+
+#ifdef WLAN_FEATURE_11W
+/**
+ * limProcessSAQueryRequestActionFrame
+ *
+ ***FUNCTION:
+ * This function is called by lim_process_action_frame() upon
+ * SA query request Action frame reception.
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ *
+ ***NOTE:
+ *
+ * @param pMac - Pointer to Global MAC structure
+ * @param *pRxPacketInfo - Handle to the Rx packet info
+ * @param psessionEntry - PE session entry
+ *
+ * @return None
+ */
+static void __lim_process_sa_query_request_action_frame(tpAniSirGlobal pMac,
+ uint8_t *pRxPacketInfo,
+ tpPESession psessionEntry)
+{
+ tpSirMacMgmtHdr pHdr;
+ uint8_t *pBody;
+ uint8_t transId[2];
+
+ /* Prima --- Below Macro not available in prima
+ pHdr = SIR_MAC_BD_TO_MPDUHEADER(pBd);
+ pBody = SIR_MAC_BD_TO_MPDUDATA(pBd); */
+
+ pHdr = WMA_GET_RX_MAC_HEADER(pRxPacketInfo);
+ pBody = WMA_GET_RX_MPDU_DATA(pRxPacketInfo);
+
+ /* If this is an unprotected SA Query Request, then ignore it. */
+ if (pHdr->fc.wep == 0)
+ return;
+
+ /*Extract 11w trsansId from SA query request action frame
+ In SA query response action frame we will send same transId
+ In SA query request action frame:
+ Category : 1 byte
+ Action : 1 byte
+ Transaction ID : 2 bytes */
+ cdf_mem_copy(&transId[0], &pBody[2], 2);
+
+ /* Send 11w SA query response action frame */
+ if (lim_send_sa_query_response_frame(pMac,
+ transId,
+ pHdr->sa,
+ psessionEntry) != eSIR_SUCCESS) {
+ PELOGE(lim_log
+ (pMac, LOGE,
+ FL("fail to send SA query response action frame."));
+ )
+ return;
+ }
+}
+
+/**
+ * __lim_process_sa_query_response_action_frame
+ *
+ ***FUNCTION:
+ * This function is called by lim_process_action_frame() upon
+ * SA query response Action frame reception.
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ *
+ ***NOTE:
+ *
+ * @param pMac - Pointer to Global MAC structure
+ * @param *pRxPacketInfo - Handle to the Rx packet info
+ * @param psessionEntry - PE session entry
+ * @return None
+ */
+static void __lim_process_sa_query_response_action_frame(tpAniSirGlobal pMac,
+ uint8_t *pRxPacketInfo,
+ tpPESession psessionEntry)
+{
+ tpSirMacMgmtHdr pHdr;
+ uint32_t frameLen;
+ uint8_t *pBody;
+ tpDphHashNode pSta;
+ uint16_t aid;
+ uint16_t transId;
+ uint8_t retryNum;
+
+ pHdr = WMA_GET_RX_MAC_HEADER(pRxPacketInfo);
+ frameLen = WMA_GET_RX_PAYLOAD_LEN(pRxPacketInfo);
+ pBody = WMA_GET_RX_MPDU_DATA(pRxPacketInfo);
+ CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_INFO,
+ ("SA Query Response received..."));
+
+ /* When a station, supplicant handles SA Query Response.
+ * Forward to SME to HDD to wpa_supplicant.
+ */
+ if (LIM_IS_STA_ROLE(psessionEntry)) {
+ lim_send_sme_mgmt_frame_ind(pMac, pHdr->fc.subType, (uint8_t *) pHdr,
+ frameLen + sizeof(tSirMacMgmtHdr), 0,
+ WMA_GET_RX_CH(pRxPacketInfo),
+ psessionEntry, 0);
+ return;
+ }
+
+ /* If this is an unprotected SA Query Response, then ignore it. */
+ if (pHdr->fc.wep == 0)
+ return;
+
+ pSta =
+ dph_lookup_hash_entry(pMac, pHdr->sa, &aid,
+ &psessionEntry->dph.dphHashTable);
+ if (NULL == pSta)
+ return;
+
+ lim_log(pMac, LOG1,
+ FL("SA Query Response source addr - %0x:%0x:%0x:%0x:%0x:%0x"),
+ pHdr->sa[0], pHdr->sa[1], pHdr->sa[2], pHdr->sa[3],
+ pHdr->sa[4], pHdr->sa[5]);
+ lim_log(pMac, LOG1,
+ FL("SA Query state for station - %d"), pSta->pmfSaQueryState);
+
+ if (DPH_SA_QUERY_IN_PROGRESS != pSta->pmfSaQueryState)
+ return;
+
+ /* Extract 11w trsansId from SA query reponse action frame
+ In SA query response action frame:
+ Category : 1 byte
+ Action : 1 byte
+ Transaction ID : 2 bytes */
+ cdf_mem_copy(&transId, &pBody[2], 2);
+
+ /* If SA Query is in progress with the station and the station
+ responds then the association request that triggered the SA
+ query is from a rogue station, just go back to initial state. */
+ for (retryNum = 0; retryNum <= pSta->pmfSaQueryRetryCount; retryNum++)
+ if (transId == pSta->pmfSaQueryStartTransId + retryNum) {
+ lim_log(pMac, LOG1,
+ FL
+ ("Found matching SA Query Request - transaction ID %d"),
+ transId);
+ tx_timer_deactivate(&pSta->pmfSaQueryTimer);
+ pSta->pmfSaQueryState = DPH_SA_QUERY_NOT_IN_PROGRESS;
+ break;
+ }
+}
+#endif
+
+#ifdef WLAN_FEATURE_11W
+/**
+ * lim_drop_unprotected_action_frame
+ *
+ ***FUNCTION:
+ * This function checks if an Action frame should be dropped since it is
+ * a Robust Managment Frame, it is unprotected, and it is received on a
+ * connection where PMF is enabled.
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ *
+ ***NOTE:
+ *
+ * @param pMac - Global MAC structure
+ * @param psessionEntry - PE session entry
+ * @param pHdr - Frame header
+ * @param category - Action frame category
+ * @return true if frame should be dropped
+ */
+
+static bool
+lim_drop_unprotected_action_frame(tpAniSirGlobal pMac, tpPESession psessionEntry,
+ tpSirMacMgmtHdr pHdr, uint8_t category)
+{
+ uint16_t aid;
+ tpDphHashNode pStaDs;
+ bool rmfConnection = false;
+
+ if (LIM_IS_AP_ROLE(psessionEntry) ||
+ LIM_IS_BT_AMP_AP_ROLE(psessionEntry)) {
+ pStaDs =
+ dph_lookup_hash_entry(pMac, pHdr->sa, &aid,
+ &psessionEntry->dph.dphHashTable);
+ if (pStaDs != NULL)
+ if (pStaDs->rmfEnabled)
+ rmfConnection = true;
+ } else if (psessionEntry->limRmfEnabled)
+ rmfConnection = true;
+
+ if (rmfConnection && (pHdr->fc.wep == 0)) {
+ PELOGE(lim_log
+ (pMac, LOGE,
+ FL("Dropping unprotected Action category %d frame "
+ "since RMF is enabled."), category);
+ )
+ return true;
+ } else
+ return false;
+}
+#endif
+
+/**
+ * lim_process_action_frame() - to process action frames
+ * @mac_ctx: Pointer to Global MAC structure
+ * @rx_pkt_info: A pointer to packet info structure
+ *
+ * This function is called by limProcessMessageQueue() upon
+ * Action frame reception.
+ *
+ * Return: none
+ */
+
+void lim_process_action_frame(tpAniSirGlobal mac_ctx,
+ uint8_t *rx_pkt_info, tpPESession session)
+{
+ uint8_t *body_ptr = WMA_GET_RX_MPDU_DATA(rx_pkt_info);
+ tpSirMacActionFrameHdr action_hdr = (tpSirMacActionFrameHdr) body_ptr;
+#ifdef WLAN_FEATURE_11W
+ tpSirMacMgmtHdr mac_hdr_11w = WMA_GET_RX_MAC_HEADER(rx_pkt_info);
+#endif
+ tpSirMacMgmtHdr mac_hdr = NULL;
+ int8_t rssi;
+ uint32_t frame_len;
+ tpSirMacVendorSpecificFrameHdr vendor_specific;
+ uint8_t oui[] = { 0x00, 0x00, 0xf0 };
+ tpSirMacVendorSpecificPublicActionFrameHdr pub_action;
+ uint8_t p2p_oui[] = { 0x50, 0x6F, 0x9A, 0x09 };
+
+ frame_len = WMA_GET_RX_PAYLOAD_LEN(rx_pkt_info);
+
+ switch (action_hdr->category) {
+ case SIR_MAC_ACTION_QOS_MGMT:
+#ifdef WLAN_FEATURE_11W
+ if (lim_drop_unprotected_action_frame(mac_ctx, session,
+ mac_hdr_11w, action_hdr->category))
+ break;
+#endif
+ if ((session->limQosEnabled) ||
+ (action_hdr->actionID == SIR_MAC_QOS_MAP_CONFIGURE)) {
+ switch (action_hdr->actionID) {
+ case SIR_MAC_QOS_ADD_TS_REQ:
+ __lim_process_add_ts_req(mac_ctx,
+ (uint8_t *) rx_pkt_info,
+ session);
+ break;
+
+ case SIR_MAC_QOS_ADD_TS_RSP:
+ __lim_process_add_ts_rsp(mac_ctx,
+ (uint8_t *) rx_pkt_info,
+ session);
+ break;
+
+ case SIR_MAC_QOS_DEL_TS_REQ:
+ __lim_process_del_ts_req(mac_ctx,
+ (uint8_t *) rx_pkt_info,
+ session);
+ break;
+
+ case SIR_MAC_QOS_MAP_CONFIGURE:
+ __lim_process_qos_map_configure_frame(mac_ctx,
+ (uint8_t *)rx_pkt_info,
+ session);
+ break;
+ default:
+ lim_log(mac_ctx, LOGE,
+ FL("Qos action %d not handled"),
+ action_hdr->actionID);
+ break;
+ }
+ break;
+ }
+ break;
+
+ case SIR_MAC_ACTION_SPECTRUM_MGMT:
+#ifdef WLAN_FEATURE_11W
+ if (lim_drop_unprotected_action_frame(mac_ctx, session,
+ mac_hdr_11w, action_hdr->category))
+ break;
+#endif
+ switch (action_hdr->actionID) {
+#ifdef ANI_SUPPORT_11H
+ case SIR_MAC_ACTION_MEASURE_REQUEST_ID:
+ if (session->lim11hEnable)
+ __lim_process_measurement_request_frame(mac_ctx,
+ rx_pkt_info,
+ session);
+ break;
+ case SIR_MAC_ACTION_TPC_REQUEST_ID:
+ if ((LIM_IS_STA_ROLE(session) ||
+ LIM_IS_AP_ROLE(session)) &&
+ session->lim11hEnable)
+ __lim_process_tpc_request_frame(mac_ctx,
+ rx_pkt_info, session);
+ break;
+#endif
+ case SIR_MAC_ACTION_CHANNEL_SWITCH_ID:
+ if (LIM_IS_STA_ROLE(session))
+ __lim_process_channel_switch_action_frame(
+ mac_ctx, rx_pkt_info, session);
+ break;
+ default:
+ lim_log(mac_ctx, LOGE,
+ FL("Spectrum mgmt action id %d not handled"),
+ action_hdr->actionID);
+ break;
+ }
+ break;
+
+ case SIR_MAC_ACTION_WME:
+ if (!session->limWmeEnabled) {
+ lim_log(mac_ctx, LOGW,
+ FL("WME mode disabled - dropping frame %d"),
+ action_hdr->actionID);
+ break;
+ }
+ switch (action_hdr->actionID) {
+ case SIR_MAC_QOS_ADD_TS_REQ:
+ __lim_process_add_ts_req(mac_ctx,
+ (uint8_t *) rx_pkt_info, session);
+ break;
+
+ case SIR_MAC_QOS_ADD_TS_RSP:
+ __lim_process_add_ts_rsp(mac_ctx,
+ (uint8_t *) rx_pkt_info, session);
+ break;
+
+ case SIR_MAC_QOS_DEL_TS_REQ:
+ __lim_process_del_ts_req(mac_ctx,
+ (uint8_t *) rx_pkt_info, session);
+ break;
+
+ case SIR_MAC_QOS_MAP_CONFIGURE:
+ __lim_process_qos_map_configure_frame(mac_ctx,
+ (uint8_t *)rx_pkt_info, session);
+ break;
+
+ default:
+ lim_log(mac_ctx, LOGE,
+ FL("WME action %d not handled"),
+ action_hdr->actionID);
+ break;
+ }
+ break;
+
+ case SIR_MAC_ACTION_HT:
+ /** Type of HT Action to be performed*/
+ switch (action_hdr->actionID) {
+ case SIR_MAC_SM_POWER_SAVE:
+ if (LIM_IS_AP_ROLE(session))
+ __lim_process_sm_power_save_update(mac_ctx,
+ (uint8_t *)rx_pkt_info,
+ session);
+ break;
+ default:
+ lim_log(mac_ctx, LOGE,
+ FL("Action ID %d not handled in HT category"),
+ action_hdr->actionID);
+ break;
+ }
+ break;
+
+ case SIR_MAC_ACTION_WNM:
+#ifdef WLAN_FEATURE_11W
+ if ((session->limRmfEnabled) && (mac_hdr_11w->fc.wep == 0)) {
+ lim_log(mac_ctx, LOGE,
+ FL("Dropping unprot action %d frm (PMF on)"),
+ action_hdr->category);
+ break;
+ }
+#endif
+ lim_log(mac_ctx, LOG1,
+ FL("WNM Action category %d action %d."),
+ action_hdr->category, action_hdr->actionID);
+ switch (action_hdr->actionID) {
+ case SIR_MAC_WNM_BSS_TM_QUERY:
+ case SIR_MAC_WNM_BSS_TM_REQUEST:
+ case SIR_MAC_WNM_BSS_TM_RESPONSE:
+ case SIR_MAC_WNM_NOTIF_REQUEST:
+ case SIR_MAC_WNM_NOTIF_RESPONSE:
+ rssi = WMA_GET_RX_RSSI_DB(rx_pkt_info);
+ mac_hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info);
+ /* Forward to the SME to HDD to wpa_supplicant */
+ lim_send_sme_mgmt_frame_ind(mac_ctx,
+ mac_hdr->fc.subType,
+ (uint8_t *) mac_hdr,
+ frame_len + sizeof(tSirMacMgmtHdr),
+ session->smeSessionId,
+ WMA_GET_RX_CH(rx_pkt_info),
+ session, rssi);
+ break;
+ default:
+ lim_log(mac_ctx, LOGE,
+ FL("Action ID %d not handled in WNM category"),
+ action_hdr->actionID);
+ break;
+ }
+ break;
+
+#if defined WLAN_FEATURE_VOWIFI
+ case SIR_MAC_ACTION_RRM:
+#ifdef WLAN_FEATURE_11W
+ if (lim_drop_unprotected_action_frame(mac_ctx, session,
+ mac_hdr_11w, action_hdr->category))
+ break;
+#endif
+ if (mac_ctx->rrm.rrmPEContext.rrmEnable) {
+ switch (action_hdr->actionID) {
+ case SIR_MAC_RRM_RADIO_MEASURE_REQ:
+ __lim_process_radio_measure_request(mac_ctx,
+ (uint8_t *)rx_pkt_info,
+ session);
+ break;
+ case SIR_MAC_RRM_LINK_MEASUREMENT_REQ:
+ __lim_process_link_measurement_req(mac_ctx,
+ (uint8_t *)rx_pkt_info,
+ session);
+ break;
+ case SIR_MAC_RRM_NEIGHBOR_RPT:
+ __lim_process_neighbor_report(mac_ctx,
+ (uint8_t *)rx_pkt_info,
+ session);
+ break;
+ default:
+ lim_log(mac_ctx, LOGE,
+ FL("Action ID %d not handled in RRM"),
+ action_hdr->actionID);
+ break;
+
+ }
+ } else {
+ /* Else we will just ignore the RRM messages. */
+ lim_log(mac_ctx, LOGE,
+ FL("RRM frm ignored, it is disabled in cfg"));
+ }
+ break;
+#endif
+#if defined(WLAN_FEATURE_VOWIFI_11R) || defined(FEATURE_WLAN_ESE) || \
+ defined(FEATURE_WLAN_LFR)
+ case SIR_MAC_ACTION_VENDOR_SPECIFIC_CATEGORY:
+ vendor_specific = (tpSirMacVendorSpecificFrameHdr) action_hdr;
+ mac_hdr = NULL;
+ frame_len = 0;
+
+ mac_hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info);
+ frame_len = WMA_GET_RX_PAYLOAD_LEN(rx_pkt_info);
+
+ /* Check if it is a vendor specific action frame. */
+ if (LIM_IS_STA_ROLE(session) &&
+ (true == cdf_mem_compare(session->selfMacAddr,
+ &mac_hdr->da[0], sizeof(tSirMacAddr)))
+ && IS_WES_MODE_ENABLED(mac_ctx)
+ && cdf_mem_compare(vendor_specific->Oui, oui, 3)) {
+ lim_log(mac_ctx, LOGW,
+ FL("Rcvd Vendor specific frame, OUI %x %x %x"),
+ vendor_specific->Oui[0],
+ vendor_specific->Oui[1],
+ vendor_specific->Oui[2]);
+ /*
+ * Forward to the SME to HDD to wpa_supplicant
+ * type is ACTION
+ */
+ lim_send_sme_mgmt_frame_ind(mac_ctx,
+ mac_hdr->fc.subType,
+ (uint8_t *) mac_hdr,
+ frame_len +
+ sizeof(tSirMacMgmtHdr),
+ session->smeSessionId,
+ WMA_GET_RX_CH(rx_pkt_info),
+ session, 0);
+ } else {
+ lim_log(mac_ctx, LOGE,
+ FL("Dropping the vendor specific action frame"
+ "beacause of (WES Mode not enabled "
+ "(WESMODE = %d) or OUI mismatch "
+ "(%02x %02x %02x) or not received with"
+ "SelfSta address) system role = %d"),
+ IS_WES_MODE_ENABLED(mac_ctx),
+ vendor_specific->Oui[0],
+ vendor_specific->Oui[1],
+ vendor_specific->Oui[2],
+ GET_LIM_SYSTEM_ROLE(session));
+ }
+ break;
+#endif /* WLAN_FEATURE_VOWIFI_11R || FEATURE_WLAN_ESE ||
+ FEATURE_WLAN_LFR */
+ case SIR_MAC_ACTION_PUBLIC_USAGE:
+ switch (action_hdr->actionID) {
+ case SIR_MAC_ACTION_VENDOR_SPECIFIC:
+ pub_action =
+ (tpSirMacVendorSpecificPublicActionFrameHdr)
+ action_hdr;
+ mac_hdr = NULL;
+ frame_len = 0;
+
+ mac_hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info);
+ frame_len = WMA_GET_RX_PAYLOAD_LEN(rx_pkt_info);
+ /* Check if it is a P2P public action frame. */
+ if (cdf_mem_compare(pub_action->Oui, p2p_oui, 4)) {
+ /*
+ * Forward to the SME to HDD to wpa_supplicant
+ * type is ACTION
+ */
+ lim_send_sme_mgmt_frame_ind(mac_ctx,
+ mac_hdr->fc.subType,
+ (uint8_t *) mac_hdr,
+ frame_len +
+ sizeof(tSirMacMgmtHdr),
+ session->smeSessionId,
+ WMA_GET_RX_CH(rx_pkt_info),
+ session, 0);
+ } else {
+ lim_log(mac_ctx, LOGE,
+ FL("Unhandled public action frame (Vendor specific). OUI %x %x %x %x"),
+ pub_action->Oui[0], pub_action->Oui[1],
+ pub_action->Oui[2], pub_action->Oui[3]);
+ }
+ break;
+
+ case SIR_MAC_ACTION_2040_BSS_COEXISTENCE:
+ mac_hdr = NULL;
+ frame_len = 0;
+
+ mac_hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info);
+ frame_len = WMA_GET_RX_PAYLOAD_LEN(rx_pkt_info);
+
+ lim_send_sme_mgmt_frame_ind(mac_ctx,
+ mac_hdr->fc.subType,
+ (uint8_t *) mac_hdr,
+ frame_len + sizeof(tSirMacMgmtHdr),
+ session->smeSessionId,
+ WMA_GET_RX_CH(rx_pkt_info), session, 0);
+ break;
+#ifdef FEATURE_WLAN_TDLS
+ case SIR_MAC_TDLS_DIS_RSP:
+ mac_hdr = NULL;
+ frame_len = 0;
+ rssi = 0;
+
+ mac_hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info);
+ frame_len = WMA_GET_RX_PAYLOAD_LEN(rx_pkt_info);
+ rssi = WMA_GET_RX_RSSI_DB(rx_pkt_info);
+ CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_INFO,
+ ("Public Action TDLS Discovery RSP .."));
+ lim_send_sme_mgmt_frame_ind(mac_ctx,
+ mac_hdr->fc.subType, (uint8_t *) mac_hdr,
+ frame_len + sizeof(tSirMacMgmtHdr),
+ session->smeSessionId,
+ WMA_GET_RX_CH(rx_pkt_info), session, rssi);
+ break;
+#endif
+
+ default:
+ lim_log(mac_ctx, LOGE,
+ FL("Unhandled public action frame -- %x "),
+ action_hdr->actionID);
+ break;
+ }
+ break;
+
+#ifdef WLAN_FEATURE_11W
+ case SIR_MAC_ACTION_SA_QUERY:
+ lim_log(mac_ctx, LOG1,
+ FL("SA Query Action category %d action %d."),
+ action_hdr->category, action_hdr->actionID);
+ if (lim_drop_unprotected_action_frame(mac_ctx, session,
+ mac_hdr_11w, action_hdr->category))
+ break;
+ switch (action_hdr->actionID) {
+ case SIR_MAC_SA_QUERY_REQ:
+ /**11w SA query request action frame received**/
+ /* Respond directly to the incoming request in LIM */
+ __lim_process_sa_query_request_action_frame(mac_ctx,
+ (uint8_t *)rx_pkt_info,
+ session);
+ break;
+ case SIR_MAC_SA_QUERY_RSP:
+ /**11w SA query response action frame received**/
+ /* Handle based on the current SA Query state */
+ __lim_process_sa_query_response_action_frame(mac_ctx,
+ (uint8_t *)rx_pkt_info,
+ session);
+ break;
+ default:
+ break;
+ }
+ break;
+#endif
+#ifdef WLAN_FEATURE_11AC
+ case SIR_MAC_ACTION_VHT:
+ if (!session->vhtCapability)
+ break;
+ switch (action_hdr->actionID) {
+ case SIR_MAC_VHT_OPMODE_NOTIFICATION:
+ __lim_process_operating_mode_action_frame(mac_ctx,
+ rx_pkt_info, session);
+ break;
+ case SIR_MAC_VHT_GID_NOTIFICATION:
+ /* Only if ini supports it */
+ if (session->enableVhtGid)
+ __lim_process_gid_management_action_frame(
+ mac_ctx, rx_pkt_info, session);
+ break;
+ default:
+ break;
+ }
+ break;
+#endif
+ default:
+ lim_log(mac_ctx, LOGE,
+ FL("Action category %d not handled"),
+ action_hdr->category);
+ break;
+ }
+}
+
+/**
+ * lim_process_action_frame_no_session
+ *
+ ***FUNCTION:
+ * This function is called by limProcessMessageQueue() upon
+ * Action frame reception and no session.
+ * Currently only public action frames can be received from
+ * a non-associated station.
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ *
+ ***NOTE:
+ *
+ * @param pMac - Pointer to Global MAC structure
+ * @param *pBd - A pointer to Buffer descriptor + associated PDUs
+ * @return None
+ */
+
+void lim_process_action_frame_no_session(tpAniSirGlobal pMac, uint8_t *pBd)
+{
+ uint8_t *pBody = WMA_GET_RX_MPDU_DATA(pBd);
+ tpSirMacVendorSpecificPublicActionFrameHdr pActionHdr =
+ (tpSirMacVendorSpecificPublicActionFrameHdr) pBody;
+
+ lim_log(pMac, LOG1, "Received a Action frame -- no session");
+
+ switch (pActionHdr->category) {
+ case SIR_MAC_ACTION_PUBLIC_USAGE:
+ switch (pActionHdr->actionID) {
+ case SIR_MAC_ACTION_VENDOR_SPECIFIC:
+ {
+ tpSirMacMgmtHdr pHdr;
+ uint32_t frameLen;
+ uint8_t P2POui[] = { 0x50, 0x6F, 0x9A, 0x09 };
+
+ pHdr = WMA_GET_RX_MAC_HEADER(pBd);
+ frameLen = WMA_GET_RX_PAYLOAD_LEN(pBd);
+
+ /* Check if it is a P2P public action frame. */
+ if (cdf_mem_compare(pActionHdr->Oui, P2POui, 4)) {
+ /* Forward to the SME to HDD to wpa_supplicant */
+ /* type is ACTION */
+ lim_send_sme_mgmt_frame_ind(pMac,
+ pHdr->fc.subType,
+ (uint8_t *) pHdr,
+ frameLen +
+ sizeof
+ (tSirMacMgmtHdr),
+ 0,
+ WMA_GET_RX_CH
+ (pBd), NULL, 0);
+ } else {
+ lim_log(pMac, LOGE,
+ FL
+ ("Unhandled public action frame (Vendor specific). OUI %x %x %x %x"),
+ pActionHdr->Oui[0],
+ pActionHdr->Oui[1],
+ pActionHdr->Oui[2],
+ pActionHdr->Oui[3]);
+ }
+ }
+ break;
+ default:
+ PELOGE(lim_log
+ (pMac, LOGE,
+ FL("Unhandled public action frame -- %x "),
+ pActionHdr->actionID);
+ )
+ break;
+ }
+ break;
+ default:
+ PELOGE(lim_log
+ (pMac, LOG1,
+ FL("Unhandled action frame without session -- %x "),
+ pActionHdr->category);
+ )
+ break;
+
+ }
+}
diff --git a/core/mac/src/pe/lim/lim_process_assoc_req_frame.c b/core/mac/src/pe/lim/lim_process_assoc_req_frame.c
new file mode 100644
index 0000000..1972461
--- /dev/null
+++ b/core/mac/src/pe/lim/lim_process_assoc_req_frame.c
@@ -0,0 +1,1921 @@
+/*
+ * Copyright (c) 2012-2015 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_process_assoc_req_frame.cc contains the code
+ * for processing Re/Association Request Frame.
+ * Author: Chandra Modumudi
+ * Date: 03/18/02
+ * History:-
+ * Date Modified by Modification Information
+ * --------------------------------------------------------------------
+ * 05/26/10 js WPA handling in (Re)Assoc frames
+ *
+ */
+#include "cds_api.h"
+#include "ani_global.h"
+#include "wni_cfg.h"
+#include "sir_api.h"
+#include "cfg_api.h"
+
+#include "sch_api.h"
+#include "utils_api.h"
+#include "lim_types.h"
+#include "lim_utils.h"
+#include "lim_assoc_utils.h"
+#include "lim_security_utils.h"
+#include "lim_ser_des_utils.h"
+#include "lim_sta_hash_api.h"
+#include "lim_admit_control.h"
+#include "cds_packet.h"
+#include "lim_session_utils.h"
+
+#include "cdf_types.h"
+#include "cds_utils.h"
+
+/**
+ * lim_convert_supported_channels - Parses channel support IE
+ *
+ * @mac_ctx - A pointer to Global MAC structure
+ * @assoc_ind - A pointer to SME ASSOC/REASSOC IND
+ * @assoc_req - A pointer to ASSOC/REASSOC Request frame
+ *
+ * This function is called by lim_process_assoc_req_frame() to
+ * parse the channel support IE in the Assoc/Reassoc Request
+ * frame, and send relevant information in the SME_ASSOC_IND
+ *
+ * return None
+ */
+static void
+lim_convert_supported_channels(tpAniSirGlobal mac_ctx,
+ tpLimMlmAssocInd assoc_ind, tSirAssocReq *assoc_req)
+{
+ uint16_t i, j, index = 0;
+ uint8_t first_chn_no;
+ uint8_t chn_count;
+ uint8_t next_chn_no;
+ uint8_t channel_offset = 0;
+
+ if (assoc_req->supportedChannels.length >=
+ SIR_MAX_SUPPORTED_CHANNEL_LIST) {
+ lim_log(mac_ctx, LOG1,
+ FL("Number of supported channels:%d is more than MAX"),
+ assoc_req->supportedChannels.length);
+ assoc_ind->supportedChannels.numChnl = 0;
+ return;
+ }
+
+ for (i = 0; i < (assoc_req->supportedChannels.length); i++) {
+ /* Get First Channel Number */
+ first_chn_no =
+ assoc_req->supportedChannels.supportedChannels[i];
+ assoc_ind->supportedChannels.channelList[index] =
+ first_chn_no;
+ i++;
+ index++;
+
+ /* Get Number of Channels in a Subband */
+ chn_count =
+ assoc_req->supportedChannels.supportedChannels[i];
+ PELOG2(lim_log(mac_ctx, LOG2,
+ FL("Rcv assoc_req: chnl=%d, numOfChnl=%d "),
+ first_chn_no, chn_count);)
+ if (index >= SIR_MAX_SUPPORTED_CHANNEL_LIST) {
+ PELOG2(lim_log(mac_ctx, LOGW,
+ FL("Channel count is more than max supported =%d "),
+ chn_count);)
+ assoc_ind->supportedChannels.numChnl = 0;
+ return;
+ }
+ if (chn_count <= 1)
+ continue;
+ next_chn_no = first_chn_no;
+ if (SIR_BAND_5_GHZ == lim_get_rf_band(first_chn_no))
+ channel_offset = SIR_11A_FREQUENCY_OFFSET;
+ else if (SIR_BAND_2_4_GHZ == lim_get_rf_band(first_chn_no))
+ channel_offset = SIR_11B_FREQUENCY_OFFSET;
+ else
+ continue;
+
+ for (j = 1; j < chn_count; j++) {
+ next_chn_no += channel_offset;
+ assoc_ind->supportedChannels.channelList[index]
+ = next_chn_no;
+ index++;
+ if (index >= SIR_MAX_SUPPORTED_CHANNEL_LIST) {
+ PELOG2(lim_log(mac_ctx, LOGW,
+ FL("Channel count is more than supported =%d "),
+ chn_count);)
+ assoc_ind->supportedChannels.numChnl = 0;
+ return;
+ }
+ }
+ }
+
+ assoc_ind->supportedChannels.numChnl = (uint8_t) index;
+ PELOG2(lim_log(mac_ctx, LOG2,
+ FL("Send AssocInd to WSM: minPwr %d, maxPwr %d, numChnl %d"),
+ assoc_ind->powerCap.minTxPower,
+ assoc_ind->powerCap.maxTxPower,
+ assoc_ind->supportedChannels.numChnl);)
+}
+
+/**---------------------------------------------------------------
+ \fn lim_check_sta_in_pe_entries
+ \brief This function is called by lim_process_assoc_req_frame()
+ \ to check if STA entry already exists in any of the
+ \ PE entries of the AP. If it exists, deauth will be
+ \ sent on that session and the STA deletion will
+ \ happen. After this, the ASSOC request will be
+ \ processed
+ \
+ \param pMac - A pointer to Global MAC structure
+ \param pHdr - A pointer to the MAC header
+ \return None
+ ------------------------------------------------------------------*/
+void lim_check_sta_in_pe_entries(tpAniSirGlobal pMac, tpSirMacMgmtHdr pHdr)
+{
+ uint8_t i;
+ uint16_t assocId = 0;
+ tpDphHashNode pStaDs = NULL;
+ tpPESession psessionEntry = NULL;
+
+ for (i = 0; i < pMac->lim.maxBssId; i++) {
+ if ((&pMac->lim.gpSession[i] != NULL) &&
+ (pMac->lim.gpSession[i].valid) &&
+ (pMac->lim.gpSession[i].pePersona == CDF_SAP_MODE)) {
+
+ psessionEntry = &pMac->lim.gpSession[i];
+ pStaDs = dph_lookup_hash_entry(pMac, pHdr->sa, &assocId,
+ &psessionEntry->dph.
+ dphHashTable);
+ if (pStaDs
+#ifdef WLAN_FEATURE_11W
+ && !pStaDs->rmfEnabled
+#endif
+ ) {
+ lim_log(pMac, LOGE,
+ FL
+ ("Sending Deauth and Deleting existing STA entry: "
+ MAC_ADDRESS_STR),
+ MAC_ADDR_ARRAY(psessionEntry->
+ selfMacAddr));
+ lim_send_deauth_mgmt_frame(pMac,
+ eSIR_MAC_UNSPEC_FAILURE_REASON,
+ (uint8_t *) pHdr->sa,
+ psessionEntry, false);
+ lim_trigger_sta_deletion(pMac, pStaDs,
+ psessionEntry);
+ break;
+ }
+ }
+ }
+}
+
+/**---------------------------------------------------------------
+ \fn lim_process_assoc_req_frame
+ \brief This function is called by limProcessMessageQueue()
+ \ upon Re/Association Request frame reception in
+ \ BTAMP AP or Soft AP role.
+ \
+ \param pMac
+ \param *pRxPacketInfo - A pointer to Buffer descriptor + associated PDUs
+ \param subType - Indicates whether it is Association Request(=0)
+ \ or Reassociation Request(=1) frame
+ \return None
+ ------------------------------------------------------------------*/
+void
+lim_process_assoc_req_frame(tpAniSirGlobal pMac, uint8_t *pRxPacketInfo,
+ uint8_t subType, tpPESession psessionEntry)
+{
+ uint8_t updateContext;
+ uint8_t *pBody;
+ uint16_t peerIdx, temp;
+ uint32_t val;
+ int32_t framelen;
+ tSirRetStatus status;
+ tpSirMacMgmtHdr pHdr;
+ struct tLimPreAuthNode *pStaPreAuthContext;
+ tAniAuthType authType;
+ tSirMacCapabilityInfo localCapabilities;
+ tpDphHashNode pStaDs = NULL;
+ tpSirAssocReq pAssocReq, pTempAssocReq;
+ tLimMlmStates mlmPrevState;
+ tDot11fIERSN Dot11fIERSN;
+ tDot11fIEWPA Dot11fIEWPA;
+ uint32_t phyMode;
+ tHalBitVal qosMode;
+ tHalBitVal wsmMode, wmeMode;
+ uint8_t *wpsIe = NULL;
+ uint8_t *ht_cap_ie = NULL;
+ tSirMacRateSet basicRates;
+ uint8_t i = 0, j = 0;
+ bool pmfConnection = false;
+#ifdef WLAN_FEATURE_11W
+ tPmfSaQueryTimerId timerId;
+ uint32_t retryInterval;
+#endif
+ uint16_t assoc_id = 0;
+ bool assoc_req_copied = false;
+
+ lim_get_phy_mode(pMac, &phyMode, psessionEntry);
+
+ limGetQosMode(psessionEntry, &qosMode);
+
+ pHdr = WMA_GET_RX_MAC_HEADER(pRxPacketInfo);
+ framelen = WMA_GET_RX_PAYLOAD_LEN(pRxPacketInfo);
+
+ lim_log(pMac, LOG1,
+ FL("Received %s Req Frame on sessionid: %d systemrole %d"
+ " limMlmState %d from: " MAC_ADDRESS_STR),
+ (LIM_ASSOC == subType) ? "Assoc" : "ReAssoc",
+ psessionEntry->peSessionId, GET_LIM_SYSTEM_ROLE(psessionEntry),
+ psessionEntry->limMlmState, MAC_ADDR_ARRAY(pHdr->sa));
+
+ if (LIM_IS_STA_ROLE(psessionEntry) ||
+ LIM_IS_BT_AMP_STA_ROLE(psessionEntry)) {
+ lim_log(pMac, LOGE,
+ FL("received unexpected ASSOC REQ on sessionid: %d "
+ "sys subType=%d for role=%d from: " MAC_ADDRESS_STR),
+ psessionEntry->peSessionId, subType,
+ GET_LIM_SYSTEM_ROLE(psessionEntry),
+ MAC_ADDR_ARRAY(pHdr->sa));
+ sir_dump_buf(pMac, SIR_LIM_MODULE_ID, LOG3,
+ WMA_GET_RX_MPDU_DATA(pRxPacketInfo), framelen);
+ return;
+ }
+
+ /*
+ * If a STA is already present in DPH and it
+ * is initiating a Assoc re-transmit, do not
+ * process it. This can happen when first Assoc Req frame
+ * is received but ACK lost at STA side. The ACK for this
+ * dropped Assoc Req frame should be sent by HW. Host simply
+ * does not process it once the entry for the STA is already
+ * present in DPH.
+ */
+ pStaDs = dph_lookup_hash_entry(pMac, pHdr->sa, &assoc_id,
+ &psessionEntry->dph.dphHashTable);
+ if ((NULL != pStaDs) && (pHdr->fc.retry > 0)) {
+ lim_log(pMac, LOGE,
+ FL("STA is initiating Assoc Req after ACK lost. Do not process"
+ " sessionid: %d sys subType=%d for role=%d from: "
+ MAC_ADDRESS_STR), psessionEntry->peSessionId,
+ subType, GET_LIM_SYSTEM_ROLE(psessionEntry),
+ MAC_ADDR_ARRAY(pHdr->sa));
+ return;
+ }
+
+ lim_check_sta_in_pe_entries(pMac, pHdr);
+
+ /* Get pointer to Re/Association Request frame body */
+ pBody = WMA_GET_RX_MPDU_DATA(pRxPacketInfo);
+
+ if (lim_is_group_addr(pHdr->sa)) {
+ /* Received Re/Assoc Req frame from a BC/MC address */
+ /* Log error and ignore it */
+ lim_log(pMac, LOGE,
+ FL("Received %s Req on sessionid: %d frame from a "
+ "BC/MC address" MAC_ADDRESS_STR),
+ (LIM_ASSOC == subType) ? "Assoc" : "ReAssoc",
+ psessionEntry->peSessionId, MAC_ADDR_ARRAY(pHdr->sa));
+ return;
+ }
+
+ sir_dump_buf(pMac, SIR_LIM_MODULE_ID, LOG2, (uint8_t *) pBody, framelen);
+
+ if (cdf_mem_compare((uint8_t *) pHdr->sa, (uint8_t *) pHdr->da,
+ (uint8_t) (sizeof(tSirMacAddr)))) {
+ lim_log(pMac, LOGE,
+ FL("Rejected Assoc Req frame Since same mac as"
+ " SAP/GO"));
+ lim_send_assoc_rsp_mgmt_frame(pMac, eSIR_MAC_UNSPEC_FAILURE_STATUS,
+ 1, pHdr->sa, subType, 0,
+ psessionEntry);
+ return;
+ }
+ /* If TKIP counter measures active send Assoc Rsp frame to station with eSIR_MAC_MIC_FAILURE_REASON */
+ if (psessionEntry->bTkipCntrMeasActive &&
+ LIM_IS_AP_ROLE(psessionEntry)) {
+ lim_log(pMac, LOGE, FL("TKIP counter measure is active"));
+ lim_send_assoc_rsp_mgmt_frame(pMac,
+ eSIR_MAC_MIC_FAILURE_REASON,
+ 1, pHdr->sa, subType,
+ 0, psessionEntry);
+ return;
+ }
+ /* Allocate memory for the Assoc Request frame */
+ pAssocReq = cdf_mem_malloc(sizeof(*pAssocReq));
+ if (NULL == pAssocReq) {
+ lim_log(pMac, LOGP, FL("Allocate Memory failed in assoc_req"));
+ return;
+ }
+ cdf_mem_set((void *)pAssocReq, sizeof(*pAssocReq), 0);
+
+ /* Parse Assoc Request frame */
+ if (subType == LIM_ASSOC)
+ status =
+ sir_convert_assoc_req_frame2_struct(pMac, pBody, framelen,
+ pAssocReq);
+ else
+ status =
+ sir_convert_reassoc_req_frame2_struct(pMac, pBody, framelen,
+ pAssocReq);
+
+ if (status != eSIR_SUCCESS) {
+ lim_log(pMac, LOGE,
+ FL("Parse error AssocRequest, length=%d from "
+ MAC_ADDRESS_STR), framelen, MAC_ADDR_ARRAY(pHdr->sa));
+ lim_send_assoc_rsp_mgmt_frame(pMac, eSIR_MAC_UNSPEC_FAILURE_STATUS,
+ 1, pHdr->sa, subType, 0,
+ psessionEntry);
+ goto error;
+ }
+
+ pAssocReq->assocReqFrame = cdf_mem_malloc(framelen);
+ if (NULL == pAssocReq->assocReqFrame) {
+ lim_log(pMac, LOGE,
+ FL("Unable to allocate memory for the assoc req, "
+ "length=%d from "), framelen);
+ goto error;
+ }
+
+ cdf_mem_copy((uint8_t *) pAssocReq->assocReqFrame,
+ (uint8_t *) pBody, framelen);
+ pAssocReq->assocReqFrameLength = framelen;
+
+ if (cfg_get_capability_info(pMac, &temp, psessionEntry) != eSIR_SUCCESS) {
+ lim_log(pMac, LOGP, FL("could not retrieve Capabilities"));
+ goto error;
+ }
+ lim_copy_u16((uint8_t *) &localCapabilities, temp);
+
+ if (lim_compare_capabilities(pMac,
+ pAssocReq,
+ &localCapabilities, psessionEntry) == false)
+ {
+ lim_log(pMac, LOGE, FL("local caps mismatch received caps"));
+ lim_log(pMac, LOGE, FL("Received %s Req with unsupported "
+ "capabilities from" MAC_ADDRESS_STR),
+ (LIM_ASSOC == subType) ? "Assoc" : "ReAssoc",
+ MAC_ADDR_ARRAY(pHdr->sa));
+ /**
+ * Capabilities of requesting STA does not match with
+ * local capabilities. Respond with 'unsupported capabilities'
+ * status code.
+ */
+ lim_send_assoc_rsp_mgmt_frame(pMac,
+ eSIR_MAC_CAPABILITIES_NOT_SUPPORTED_STATUS,
+ 1,
+ pHdr->sa, subType, 0, psessionEntry);
+
+ goto error;
+ }
+
+ updateContext = false;
+
+ if (lim_cmp_s_sid(pMac, &pAssocReq->ssId, psessionEntry) == false) {
+ lim_log(pMac, LOGE,
+ FL("Received %s Req with unmatched ssid ( Received"
+ " SSID: %.*s current SSID: %.*s ) from "
+ MAC_ADDRESS_STR),
+ (LIM_ASSOC == subType) ? "Assoc" : "ReAssoc",
+ pAssocReq->ssId.length, pAssocReq->ssId.ssId,
+ psessionEntry->ssId.length, psessionEntry->ssId.ssId,
+ MAC_ADDR_ARRAY(pHdr->sa));
+
+ /**
+ * Received Re/Association Request with either
+ * Broadcast SSID OR with SSID that does not
+ * match with local one.
+ * Respond with unspecified status code.
+ */
+ lim_send_assoc_rsp_mgmt_frame(pMac,
+ eSIR_MAC_UNSPEC_FAILURE_STATUS,
+ 1,
+ pHdr->sa, subType, 0, psessionEntry);
+
+ goto error;
+ }
+
+ /***************************************************************
+ ** Verify if the requested rates are available in supported rate
+ ** set or Extended rate set. Some APs are adding basic rates in
+ ** Extended rateset IE
+ ***************************************************************/
+ basicRates.numRates = 0;
+
+ for (i = 0;
+ i < pAssocReq->supportedRates.numRates
+ && (i < SIR_MAC_RATESET_EID_MAX); i++) {
+ basicRates.rate[i] = pAssocReq->supportedRates.rate[i];
+ basicRates.numRates++;
+ }
+
+ for (j = 0;
+ (j < pAssocReq->extendedRates.numRates)
+ && (i < SIR_MAC_RATESET_EID_MAX); i++, j++) {
+ basicRates.rate[i] = pAssocReq->extendedRates.rate[j];
+ basicRates.numRates++;
+ }
+ if (lim_check_rx_basic_rates(pMac, basicRates, psessionEntry) == false) {
+ lim_log(pMac, LOGE, FL("Received %s Req with unsupported "
+ "rates from" MAC_ADDRESS_STR),
+ (LIM_ASSOC == subType) ? "Assoc" : "ReAssoc",
+ MAC_ADDR_ARRAY(pHdr->sa));
+ /**
+ * Requesting STA does not support ALL BSS basic
+ * rates. Respond with 'basic rates not supported'
+ * status code.
+ */
+ lim_send_assoc_rsp_mgmt_frame(pMac,
+ eSIR_MAC_BASIC_RATES_NOT_SUPPORTED_STATUS,
+ 1,
+ pHdr->sa, subType, 0, psessionEntry);
+
+ goto error;
+ }
+
+ if (LIM_IS_AP_ROLE(psessionEntry) &&
+ (psessionEntry->dot11mode == WNI_CFG_DOT11_MODE_11G_ONLY) &&
+ (pAssocReq->HTCaps.present))
+ {
+ lim_log(pMac, LOGE,
+ FL("SOFTAP was in 11G only mode, rejecting legacy "
+ "STA : " MAC_ADDRESS_STR), MAC_ADDR_ARRAY(pHdr->sa));
+ lim_send_assoc_rsp_mgmt_frame(pMac,
+ eSIR_MAC_CAPABILITIES_NOT_SUPPORTED_STATUS,
+ 1, pHdr->sa, subType, 0,
+ psessionEntry);
+ goto error;
+
+ } /* end if phyMode == 11G_only */
+
+ if (LIM_IS_AP_ROLE(psessionEntry) &&
+ (psessionEntry->dot11mode == WNI_CFG_DOT11_MODE_11N_ONLY) &&
+ (!pAssocReq->HTCaps.present)) {
+ lim_log(pMac, LOGE,
+ FL("SOFTAP was in 11N only mode, rejecting legacy "
+ "STA : " MAC_ADDRESS_STR), MAC_ADDR_ARRAY(pHdr->sa));
+ lim_send_assoc_rsp_mgmt_frame(pMac,
+ eSIR_MAC_CAPABILITIES_NOT_SUPPORTED_STATUS,
+ 1, pHdr->sa, subType, 0,
+ psessionEntry);
+ goto error;
+ } /* end if PhyMode == 11N_only */
+
+ if (LIM_IS_AP_ROLE(psessionEntry) &&
+ (psessionEntry->dot11mode == WNI_CFG_DOT11_MODE_11AC_ONLY) &&
+ (!pAssocReq->VHTCaps.present)) {
+ lim_send_assoc_rsp_mgmt_frame(pMac,
+ eSIR_MAC_CAPABILITIES_NOT_SUPPORTED_STATUS,
+ 1, pHdr->sa, subType, 0,
+ psessionEntry);
+ lim_log(pMac, LOGE, FL("SOFTAP was in 11AC only mode, reject"));
+ goto error;
+ } /* end if PhyMode == 11AC_only */
+
+ /* Spectrum Management (11h) specific checks */
+ if (localCapabilities.spectrumMgt) {
+ tSirRetStatus status = eSIR_SUCCESS;
+
+ /* If station is 11h capable, then it SHOULD send all mandatory
+ * IEs in assoc request frame. Let us verify that
+ */
+ if (pAssocReq->capabilityInfo.spectrumMgt) {
+ if (!
+ ((pAssocReq->powerCapabilityPresent)
+ && (pAssocReq->supportedChannelsPresent))) {
+ /* One or more required information elements are missing, log the peers error */
+ if (!pAssocReq->powerCapabilityPresent) {
+ lim_log(pMac, LOG1,
+ FL
+ ("LIM Info: Missing Power capability "
+ "IE in %s Req from "
+ MAC_ADDRESS_STR),
+ (LIM_ASSOC ==
+ subType) ? "Assoc" : "ReAssoc",
+ MAC_ADDR_ARRAY(pHdr->sa));
+ }
+ if (!pAssocReq->supportedChannelsPresent) {
+ lim_log(pMac, LOGW,
+ FL
+ ("LIM Info: Missing Supported channel "
+ "IE in %s Req from "
+ MAC_ADDRESS_STR),
+ (LIM_ASSOC ==
+ subType) ? "Assoc" : "ReAssoc",
+ MAC_ADDR_ARRAY(pHdr->sa));
+
+ }
+ } else {
+ /* Assoc request has mandatory fields */
+ status =
+ lim_is_dot11h_power_capabilities_in_range(pMac,
+ pAssocReq,
+ psessionEntry);
+ if (eSIR_SUCCESS != status) {
+ lim_log(pMac, LOGW,
+ FL("LIM Info: MinTxPower(STA) > "
+ "MaxTxPower(AP) in %s Req from "
+ MAC_ADDRESS_STR),
+ (LIM_ASSOC ==
+ subType) ? "Assoc" : "ReAssoc",
+ MAC_ADDR_ARRAY(pHdr->sa));
+
+ }
+ status =
+ lim_is_dot11h_supported_channels_valid(pMac,
+ pAssocReq);
+ if (eSIR_SUCCESS != status) {
+ lim_log(pMac, LOGW,
+ FL("LIM Info: wrong supported "
+ "channels (STA) in %s Req from "
+ MAC_ADDRESS_STR),
+ (LIM_ASSOC ==
+ subType) ? "Assoc" : "ReAssoc",
+ MAC_ADDR_ARRAY(pHdr->sa));
+
+ }
+ /* IEs are valid, use them if needed */
+ }
+ } /* if(assoc.capabilityInfo.spectrumMgt) */
+ else {
+ /* As per the capabiities, the spectrum management is not enabled on the station
+ * The AP may allow the associations to happen even if spectrum management is not
+ * allowed, if the transmit power of station is below the regulatory maximum
+ */
+
+ /* TODO: presently, this is not handled. In the current implemetation, the AP would
+ * allow the station to associate even if it doesn't support spectrum management.
+ */
+ }
+ } /* end of spectrum management related processing */
+
+ if ((pAssocReq->HTCaps.present)
+ && (lim_check_mcs_set(pMac, pAssocReq->HTCaps.supportedMCSSet) ==
+ false)) {
+ lim_log(pMac, LOGE,
+ FL("received %s req with unsupported"
+ "MCS Rate Set from " MAC_ADDRESS_STR),
+ (LIM_ASSOC == subType) ? "Assoc" : "ReAssoc",
+ MAC_ADDR_ARRAY(pHdr->sa));
+
+ /**
+ * Requesting STA does not support ALL BSS MCS basic Rate set rates.
+ * Spec does not define any status code for this scenario.
+ */
+ lim_send_assoc_rsp_mgmt_frame(pMac,
+ eSIR_MAC_OUTSIDE_SCOPE_OF_SPEC_STATUS,
+ 1,
+ pHdr->sa, subType, 0, psessionEntry);
+
+ goto error;
+ }
+
+ if (phyMode == WNI_CFG_PHY_MODE_11G) {
+
+ if (wlan_cfg_get_int(pMac, WNI_CFG_11G_ONLY_POLICY, &val) !=
+ eSIR_SUCCESS) {
+ lim_log(pMac, LOGP,
+ FL("could not retrieve 11g-only flag"));
+ goto error;
+ }
+
+ if (!pAssocReq->extendedRatesPresent && val) {
+ /**
+ * Received Re/Association Request from
+ * 11b STA when 11g only policy option
+ * is set.
+ * Reject with unspecified status code.
+ */
+ lim_send_assoc_rsp_mgmt_frame(pMac,
+ eSIR_MAC_BASIC_RATES_NOT_SUPPORTED_STATUS,
+ 1,
+ pHdr->sa,
+ subType, 0, psessionEntry);
+
+ lim_log(pMac, LOGE,
+ FL("Rejecting Re/Assoc req from 11b STA: "));
+ lim_print_mac_addr(pMac, pHdr->sa, LOGW);
+
+#ifdef WLAN_DEBUG
+ pMac->lim.gLim11bStaAssocRejectCount++;
+#endif
+ goto error;
+ }
+ }
+
+ /* Check for 802.11n HT caps compatibility; are HT Capabilities */
+ /* turned on in lim? */
+ if (psessionEntry->htCapability) {
+ /* There are; are they turned on in the STA? */
+ if (pAssocReq->HTCaps.present) {
+ /* The station *does* support 802.11n HT capability... */
+
+ lim_log(pMac, LOG1, FL("AdvCodingCap:%d ChaWidthSet:%d "
+ "PowerSave:%d greenField:%d "
+ "shortGI20:%d shortGI40:%d"
+ "txSTBC:%d rxSTBC:%d delayBA:%d"
+ "maxAMSDUsize:%d DSSS/CCK:%d "
+ "PSMP:%d stbcCntl:%d lsigTXProt:%d"),
+ pAssocReq->HTCaps.advCodingCap,
+ pAssocReq->HTCaps.supportedChannelWidthSet,
+ pAssocReq->HTCaps.mimoPowerSave,
+ pAssocReq->HTCaps.greenField,
+ pAssocReq->HTCaps.shortGI20MHz,
+ pAssocReq->HTCaps.shortGI40MHz,
+ pAssocReq->HTCaps.txSTBC,
+ pAssocReq->HTCaps.rxSTBC,
+ pAssocReq->HTCaps.delayedBA,
+ pAssocReq->HTCaps.maximalAMSDUsize,
+ pAssocReq->HTCaps.dsssCckMode40MHz,
+ pAssocReq->HTCaps.psmp,
+ pAssocReq->HTCaps.stbcControlFrame,
+ pAssocReq->HTCaps.lsigTXOPProtection);
+
+ /* Make sure the STA's caps are compatible with our own: */
+ /* 11.15.2 Support of DSSS/CCK in 40 MHz */
+ /* the AP shall refuse association requests from an HT STA that has the DSSS/CCK */
+ /* Mode in 40 MHz subfield set to 1; */
+ }
+ } /* End if on HT caps turned on in lim. */
+
+ /* Clear the buffers so that frame parser knows that there isn't a previously decoded IE in these buffers */
+ cdf_mem_set((uint8_t *) &Dot11fIERSN, sizeof(Dot11fIERSN), 0);
+ cdf_mem_set((uint8_t *) &Dot11fIEWPA, sizeof(Dot11fIEWPA), 0);
+
+ /* if additional IE is present, check if it has WscIE */
+ if (pAssocReq->addIEPresent && pAssocReq->addIE.length)
+ wpsIe =
+ limGetWscIEPtr(pMac, pAssocReq->addIE.addIEdata,
+ pAssocReq->addIE.length);
+ else {
+ lim_log(pMac, LOG1, FL("Assoc req addIEPresent = %d "
+ "addIE length = %d"),
+ pAssocReq->addIEPresent, pAssocReq->addIE.length);
+ }
+ /* when wpsIe is present, RSN/WPA IE is ignored */
+ if (wpsIe == NULL) {
+ /** check whether as RSN IE is present */
+ if (LIM_IS_AP_ROLE(psessionEntry) &&
+ psessionEntry->pLimStartBssReq->privacy &&
+ psessionEntry->pLimStartBssReq->rsnIE.length) {
+ lim_log(pMac, LOG1,
+ FL("RSN enabled auth, Re/Assoc req from STA: "
+ MAC_ADDRESS_STR), MAC_ADDR_ARRAY(pHdr->sa));
+ if (pAssocReq->rsnPresent) {
+ if (pAssocReq->rsn.length) {
+ /* Unpack the RSN IE */
+ dot11f_unpack_ie_rsn(pMac,
+ &pAssocReq->rsn.
+ info[0],
+ pAssocReq->rsn.length,
+ &Dot11fIERSN);
+
+ /* Check RSN version is supported or not */
+ if (SIR_MAC_OUI_VERSION_1 ==
+ Dot11fIERSN.version) {
+ /* check the groupwise and pairwise cipher suites */
+ if (eSIR_SUCCESS !=
+ (status =
+ lim_check_rx_rsn_ie_match(pMac,
+ Dot11fIERSN,
+ psessionEntry,
+ pAssocReq->
+ HTCaps.
+ present,
+ &pmfConnection)))
+ {
+ lim_log(pMac, LOGE,
+ FL("RSN Mismatch."
+ "Rejecting Re/Assoc req from "
+ "STA: "
+ MAC_ADDRESS_STR),
+ MAC_ADDR_ARRAY
+ (pHdr->sa));
+
+ /* some IE is not properly sent */
+ /* received Association req frame with RSN IE but length is 0 */
+ lim_send_assoc_rsp_mgmt_frame
+ (pMac, status, 1,
+ pHdr->sa, subType,
+ 0, psessionEntry);
+
+ goto error;
+
+ }
+ } else {
+ lim_log(pMac, LOGE,
+ FL("RSN length not correct."
+ "Rejecting Re/Assoc req from "
+ "STA: "
+ MAC_ADDRESS_STR),
+ MAC_ADDR_ARRAY(pHdr->
+ sa));
+
+ /* received Association req frame with RSN IE version wrong */
+ lim_send_assoc_rsp_mgmt_frame(pMac,
+ eSIR_MAC_UNSUPPORTED_RSN_IE_VERSION_STATUS,
+ 1,
+ pHdr->
+ sa,
+ subType,
+ 0,
+ psessionEntry);
+ goto error;
+
+ }
+ } else {
+ lim_log(pMac, LOGW,
+ FL
+ ("Rejecting Re/Assoc req from STA:"
+ MAC_ADDRESS_STR),
+ MAC_ADDR_ARRAY(pHdr->sa));
+ /* received Association req frame with RSN IE but length is 0 */
+ lim_send_assoc_rsp_mgmt_frame(pMac,
+ eSIR_MAC_INVALID_INFORMATION_ELEMENT_STATUS,
+ 1,
+ pHdr->sa,
+ subType, 0,
+ psessionEntry);
+
+ goto error;
+
+ }
+ } /* end - if(pAssocReq->rsnPresent) */
+ if ((!pAssocReq->rsnPresent) && pAssocReq->wpaPresent) {
+ /* Unpack the WPA IE */
+ if (pAssocReq->wpa.length) {
+ dot11f_unpack_ie_wpa(pMac, &pAssocReq->wpa.info[4], /* OUI is not taken care */
+ pAssocReq->wpa.length,
+ &Dot11fIEWPA);
+ /* check the groupwise and pairwise cipher suites */
+ if (eSIR_SUCCESS !=
+ (status =
+ lim_check_rx_wpa_ie_match(pMac,
+ Dot11fIEWPA,
+ psessionEntry,
+ pAssocReq->
+ HTCaps.
+ present))) {
+ lim_log(pMac, LOGW,
+ FL("WPA IE mismatch"
+ "Rejecting Re/Assoc req from "
+ "STA: "
+ MAC_ADDRESS_STR),
+ MAC_ADDR_ARRAY(pHdr->
+ sa));
+ /* received Association req frame with WPA IE but mismatch */
+ lim_send_assoc_rsp_mgmt_frame(pMac,
+ status,
+ 1,
+ pHdr->
+ sa,
+ subType,
+ 0,
+ psessionEntry);
+ goto error;
+
+ }
+ } else {
+ lim_log(pMac, LOGW,
+ FL("WPA len incorrect."
+ "Rejecting Re/Assoc req from"
+ "STA: "MAC_ADDRESS_STR),
+ MAC_ADDR_ARRAY(pHdr->sa));
+ /* received Association req frame with invalid WPA IE */
+ lim_send_assoc_rsp_mgmt_frame(pMac,
+ eSIR_MAC_INVALID_INFORMATION_ELEMENT_STATUS,
+ 1,
+ pHdr->sa,
+ subType, 0,
+ psessionEntry);
+
+ goto error;
+ } /* end - if(pAssocReq->wpa.length) */
+ } /* end - if(pAssocReq->wpaPresent) */
+ }
+ /* end of if(psessionEntry->pLimStartBssReq->privacy
+ && psessionEntry->pLimStartBssReq->rsnIE->length) */
+ } /* end of if( ! pAssocReq->wscInfo.present ) */
+ else {
+ lim_log(pMac, LOG1, FL("Assoc req WSE IE is present"));
+ }
+
+ /**
+ * Extract 'associated' context for STA, if any.
+ * This is maintained by DPH and created by LIM.
+ */
+ pStaDs =
+ dph_lookup_hash_entry(pMac, pHdr->sa, &peerIdx,
+ &psessionEntry->dph.dphHashTable);
+
+ /* / Extract pre-auth context for the STA, if any. */
+ pStaPreAuthContext = lim_search_pre_auth_list(pMac, pHdr->sa);
+
+ if (pStaDs == NULL) {
+ /* / Requesting STA is not currently associated */
+ if (pe_get_current_stas_count(pMac) ==
+ pMac->lim.gLimAssocStaLimit) {
+ /**
+ * Maximum number of STAs that AP can handle reached.
+ * Send Association response to peer MAC entity
+ */
+ lim_log(pMac, LOGE, FL("Max Sta count reached : %d"),
+ pMac->lim.maxStation);
+ lim_reject_association(pMac, pHdr->sa,
+ subType, false,
+ (tAniAuthType) 0, 0,
+ false,
+ (tSirResultCodes)
+ eSIR_MAC_UNSPEC_FAILURE_STATUS,
+ psessionEntry);
+
+ goto error;
+ }
+ /* / Check if STA is pre-authenticated. */
+ if ((pStaPreAuthContext == NULL) ||
+ (pStaPreAuthContext &&
+ (pStaPreAuthContext->mlmState !=
+ eLIM_MLM_AUTHENTICATED_STATE))) {
+ /**
+ * STA is not pre-authenticated yet requesting
+ * Re/Association before Authentication.
+ * OR STA is in the process of getting authenticated
+ * and sent Re/Association request.
+ * Send Deauthentication frame with 'prior
+ * authentication required' reason code.
+ */
+ lim_send_deauth_mgmt_frame(pMac, eSIR_MAC_STA_NOT_PRE_AUTHENTICATED_REASON, /* =9 */
+ pHdr->sa, psessionEntry, false);
+
+ lim_log(pMac, LOGE,
+ FL("received %s req on sessionid: %d from STA "
+ "that does not have pre-auth context"
+ MAC_ADDRESS_STR),
+ (LIM_ASSOC == subType) ? "Assoc" : "ReAssoc",
+ psessionEntry->peSessionId,
+ MAC_ADDR_ARRAY(pHdr->sa));
+ goto error;
+ }
+ /* / Delete 'pre-auth' context of STA */
+ authType = pStaPreAuthContext->authType;
+ lim_delete_pre_auth_node(pMac, pHdr->sa);
+
+ /* All is well. Assign AID (after else part) */
+
+ } /* if (pStaDs == NULL) */
+ else {
+ /* STA context does exist for this STA */
+
+ if (pStaDs->mlmStaContext.mlmState !=
+ eLIM_MLM_LINK_ESTABLISHED_STATE) {
+ /**
+ * Requesting STA is in some 'transient' state?
+ * Ignore the Re/Assoc Req frame by incrementing
+ * debug counter & logging error.
+ */
+ if (subType == LIM_ASSOC) {
+
+#ifdef WLAN_DEBUG
+ pMac->lim.gLimNumAssocReqDropInvldState++;
+#endif
+ lim_log(pMac, LOGE,
+ FL("received Assoc req in state "
+ "%X from "),
+ pStaDs->mlmStaContext.mlmState);
+ } else {
+#ifdef WLAN_DEBUG
+ pMac->lim.gLimNumReassocReqDropInvldState++;
+#endif
+ lim_log(pMac, LOGE,
+ FL("received ReAssoc req in state %X"
+ " from "),
+ pStaDs->mlmStaContext.mlmState);
+ }
+ lim_print_mac_addr(pMac, pHdr->sa, LOG1);
+ lim_print_mlm_state(pMac, LOG1,
+ (tLimMlmStates) pStaDs->mlmStaContext.
+ mlmState);
+
+ goto error;
+ } /* if (pStaDs->mlmStaContext.mlmState != eLIM_MLM_LINK_ESTABLISHED_STATE) */
+
+ /* STA sent association Request frame while already in
+ * 'associated' state */
+
+#ifdef WLAN_FEATURE_11W
+ lim_log(pMac, LOG1,
+ FL
+ ("Re/Assoc request from station that is already associated"));
+ lim_log(pMac, LOG1, FL("PMF enabled %d, SA Query state %d"),
+ pStaDs->rmfEnabled, pStaDs->pmfSaQueryState);
+ if (pStaDs->rmfEnabled) {
+ switch (pStaDs->pmfSaQueryState) {
+
+ /* start SA Query procedure, respond to Association Request */
+ /* with try again later */
+ case DPH_SA_QUERY_NOT_IN_PROGRESS:
+ /*
+ * We should reset the retry counter before we start
+ * the SA query procedure, otherwise in next set of SA query
+ * procedure we will end up using the stale value.
+ */
+ pStaDs->pmfSaQueryRetryCount = 0;
+ lim_send_assoc_rsp_mgmt_frame(pMac,
+ eSIR_MAC_TRY_AGAIN_LATER,
+ 1, pHdr->sa, subType,
+ pStaDs, psessionEntry);
+ lim_send_sa_query_request_frame(pMac,
+ (uint8_t *) &
+ (pStaDs->
+ pmfSaQueryCurrentTransId),
+ pHdr->sa,
+ psessionEntry);
+ pStaDs->pmfSaQueryStartTransId =
+ pStaDs->pmfSaQueryCurrentTransId;
+ pStaDs->pmfSaQueryCurrentTransId++;
+
+ /* start timer for SA Query retry */
+ if (tx_timer_activate(&pStaDs->pmfSaQueryTimer)
+ != TX_SUCCESS) {
+ lim_log(pMac, LOGE,
+ FL
+ ("PMF SA Query timer activation failed!"));
+ goto error;
+ }
+
+ pStaDs->pmfSaQueryState =
+ DPH_SA_QUERY_IN_PROGRESS;
+ goto error;
+
+ /* SA Query procedure still going, respond to Association */
+ /* Request with try again later */
+ case DPH_SA_QUERY_IN_PROGRESS:
+ lim_send_assoc_rsp_mgmt_frame(pMac,
+ eSIR_MAC_TRY_AGAIN_LATER,
+ 1, pHdr->sa, subType,
+ 0, psessionEntry);
+ goto error;
+
+ /* SA Query procedure timed out, accept Association Request */
+ /* normally */
+ case DPH_SA_QUERY_TIMED_OUT:
+ pStaDs->pmfSaQueryState =
+ DPH_SA_QUERY_NOT_IN_PROGRESS;
+ break;
+ }
+ }
+#endif
+
+ /* no change in the capability so drop the frame */
+ if ((true ==
+ cdf_mem_compare(&pStaDs->mlmStaContext.capabilityInfo,
+ &pAssocReq->capabilityInfo,
+ sizeof(tSirMacCapabilityInfo)))
+ && (subType == LIM_ASSOC)) {
+ lim_log(pMac, LOGE,
+ FL(" Received Assoc req in state %X STAid=%d"),
+ pStaDs->mlmStaContext.mlmState, peerIdx);
+ goto error;
+ } else {
+ /**
+ * STA sent Re/association Request frame while already in
+ * 'associated' state. Update STA capabilities and
+ * send Association response frame with same AID
+ */
+ lim_log(pMac, LOG1,
+ FL("Recved Assoc req from STA already connected"
+ " UpdateConext"));
+ pStaDs->mlmStaContext.capabilityInfo =
+ pAssocReq->capabilityInfo;
+ if (pStaPreAuthContext
+ && (pStaPreAuthContext->mlmState ==
+ eLIM_MLM_AUTHENTICATED_STATE)) {
+ /* / STA has triggered pre-auth again */
+ authType = pStaPreAuthContext->authType;
+ lim_delete_pre_auth_node(pMac, pHdr->sa);
+ } else
+ authType = pStaDs->mlmStaContext.authType;
+
+ updateContext = true;
+ if (dph_init_sta_state
+ (pMac, pHdr->sa, peerIdx, true,
+ &psessionEntry->dph.dphHashTable)
+ == NULL) {
+ lim_log(pMac, LOGE,
+ FL("could not Init STAid=%d"), peerIdx);
+ goto error;
+ }
+ }
+ goto sendIndToSme;
+ } /* end if (lookup for STA in perStaDs fails) */
+
+ /* check if sta is allowed per QoS AC rules */
+ limGetWmeMode(psessionEntry, &wmeMode);
+ if ((qosMode == eHAL_SET) || (wmeMode == eHAL_SET)) {
+ /* for a qsta, check if the requested Traffic spec */
+ /* is admissible */
+ /* for a non-qsta check if the sta can be admitted */
+ if (pAssocReq->addtsPresent) {
+ uint8_t tspecIdx = 0; /* index in the sch tspec table. */
+ if (lim_admit_control_add_ts
+ (pMac, pHdr->sa, &(pAssocReq->addtsReq),
+ &(pAssocReq->qosCapability), 0, false, NULL,
+ &tspecIdx, psessionEntry) != eSIR_SUCCESS) {
+ lim_log(pMac, LOGE,
+ FL("AdmitControl: TSPEC rejected"));
+ lim_send_assoc_rsp_mgmt_frame(pMac,
+ eSIR_MAC_QAP_NO_BANDWIDTH_REASON,
+ 1, pHdr->sa, subType,
+ 0, psessionEntry);
+#ifdef WLAN_DEBUG
+ pMac->lim.gLimNumAssocReqDropACRejectTS++;
+#endif
+ goto error;
+ }
+ } else if (lim_admit_control_add_sta(pMac, pHdr->sa, false)
+ != eSIR_SUCCESS) {
+ lim_log(pMac, LOGE, FL("AdmitControl: Sta rejected"));
+ lim_send_assoc_rsp_mgmt_frame(pMac,
+ eSIR_MAC_QAP_NO_BANDWIDTH_REASON,
+ 1,
+ pHdr->sa,
+ subType, 0, psessionEntry);
+#ifdef WLAN_DEBUG
+ pMac->lim.gLimNumAssocReqDropACRejectSta++;
+#endif
+ goto error;
+ }
+ /* else all ok */
+ lim_log(pMac, LOG1, FL("AdmitControl: Sta OK!"));
+ }
+
+ /**
+ * STA is Associated !
+ */
+ lim_log(pMac, LOGE,
+ FL("Received %s Req successful from " MAC_ADDRESS_STR),
+ (LIM_ASSOC == subType) ? "Assoc" : "ReAssoc",
+ MAC_ADDR_ARRAY(pHdr->sa));
+
+ /**
+ * AID for this association will be same as the peer Index used in DPH table.
+ * Assign unused/least recently used peer Index from perStaDs.
+ * NOTE: lim_assign_peer_idx() assigns AID values ranging
+ * between 1 - cfg_item(WNI_CFG_ASSOC_STA_LIMIT)
+ */
+
+ peerIdx = lim_assign_peer_idx(pMac, psessionEntry);
+
+ if (!peerIdx) {
+ /* Could not assign AID */
+ /* Reject association */
+ lim_log(pMac, LOGE,
+ FL("PeerIdx not avaialble. Reject associaton"));
+ lim_reject_association(pMac, pHdr->sa,
+ subType, true, authType,
+ peerIdx, false,
+ (tSirResultCodes)
+ eSIR_MAC_UNSPEC_FAILURE_STATUS,
+ psessionEntry);
+
+ goto error;
+ }
+
+ /**
+ * Add an entry to hash table maintained by DPH module
+ */
+
+ pStaDs =
+ dph_add_hash_entry(pMac, pHdr->sa, peerIdx,
+ &psessionEntry->dph.dphHashTable);
+
+ if (pStaDs == NULL) {
+ /* Could not add hash table entry at DPH */
+ lim_log(pMac, LOGE,
+ FL("could not add hash entry at DPH for aid=%d, MacAddr:"
+ MAC_ADDRESS_STR), peerIdx, MAC_ADDR_ARRAY(pHdr->sa));
+
+ /* Release AID */
+ lim_release_peer_idx(pMac, peerIdx, psessionEntry);
+
+ lim_reject_association(pMac, pHdr->sa,
+ subType, true, authType, peerIdx, false,
+ (tSirResultCodes)
+ eSIR_MAC_UNSPEC_FAILURE_STATUS,
+ psessionEntry);
+
+ goto error;
+ }
+
+sendIndToSme:
+ /*
+ * check here if the parsedAssocReq already
+ * pointing to the assoc_req and free it before
+ * assigning this new pAssocReq
+ */
+ if (psessionEntry->parsedAssocReq != NULL) {
+ pTempAssocReq = psessionEntry->parsedAssocReq[pStaDs->assocId];
+ if (pTempAssocReq != NULL) {
+ if (pTempAssocReq->assocReqFrame) {
+ cdf_mem_free(pTempAssocReq->assocReqFrame);
+ pTempAssocReq->assocReqFrame = NULL;
+ pTempAssocReq->assocReqFrameLength = 0;
+ }
+ cdf_mem_free(pTempAssocReq);
+ pTempAssocReq = NULL;
+ }
+
+ psessionEntry->parsedAssocReq[pStaDs->assocId] = pAssocReq;
+ assoc_req_copied = true;
+ }
+
+ pStaDs->mlmStaContext.htCapability = pAssocReq->HTCaps.present;
+#ifdef WLAN_FEATURE_11AC
+ pStaDs->mlmStaContext.vhtCapability = pAssocReq->VHTCaps.present;
+#endif
+ pStaDs->qos.addtsPresent =
+ (pAssocReq->addtsPresent == 0) ? false : true;
+ pStaDs->qos.addts = pAssocReq->addtsReq;
+ pStaDs->qos.capability = pAssocReq->qosCapability;
+ pStaDs->versionPresent = 0;
+ /* short slot and short preamble should be updated before doing limaddsta */
+ pStaDs->shortPreambleEnabled =
+ (uint8_t) pAssocReq->capabilityInfo.shortPreamble;
+ pStaDs->shortSlotTimeEnabled =
+ (uint8_t) pAssocReq->capabilityInfo.shortSlotTime;
+
+ pStaDs->valid = 0;
+ pStaDs->mlmStaContext.authType = authType;
+ pStaDs->staType = STA_ENTRY_PEER;
+
+ /* TODO: If listen interval is more than certain limit, reject the association. */
+ /* Need to check customer requirements and then implement. */
+ pStaDs->mlmStaContext.listenInterval = pAssocReq->listenInterval;
+ pStaDs->mlmStaContext.capabilityInfo = pAssocReq->capabilityInfo;
+
+ /* The following count will be used to knock-off the station if it doesn't
+ * come back to receive the buffered data. The AP will wait for numTimSent number
+ * of beacons after sending TIM information for the station, before assuming that
+ * the station is no more associated and disassociates it
+ */
+
+ /** timWaitCount is used by PMM for monitoring the STA's in PS for LINK*/
+ pStaDs->timWaitCount =
+ (uint8_t) GET_TIM_WAIT_COUNT(pAssocReq->listenInterval);
+
+ /** Initialise the Current successful MPDU's tranfered to this STA count as 0 */
+ pStaDs->curTxMpduCnt = 0;
+
+ if (IS_DOT11_MODE_HT(psessionEntry->dot11mode) &&
+ pAssocReq->HTCaps.present && pAssocReq->wmeInfoPresent) {
+ pStaDs->htGreenfield = (uint8_t) pAssocReq->HTCaps.greenField;
+ pStaDs->htAMpduDensity = pAssocReq->HTCaps.mpduDensity;
+ pStaDs->htDsssCckRate40MHzSupport =
+ (uint8_t) pAssocReq->HTCaps.dsssCckMode40MHz;
+ pStaDs->htLsigTXOPProtection =
+ (uint8_t) pAssocReq->HTCaps.lsigTXOPProtection;
+ pStaDs->htMaxAmsduLength =
+ (uint8_t) pAssocReq->HTCaps.maximalAMSDUsize;
+ pStaDs->htMaxRxAMpduFactor = pAssocReq->HTCaps.maxRxAMPDUFactor;
+ pStaDs->htMIMOPSState = pAssocReq->HTCaps.mimoPowerSave;
+
+ /* pAssocReq will be copied to psessionEntry->parsedAssocReq
+ * later
+ */
+ ht_cap_ie = ((uint8_t *) &pAssocReq->HTCaps) + 1;
+
+ /* check whether AP is enabled with shortGI */
+ if (wlan_cfg_get_int(pMac, WNI_CFG_SHORT_GI_20MHZ, &val) !=
+ eSIR_SUCCESS) {
+ PELOGE(lim_log(pMac, LOGE,
+ FL("could not retrieve shortGI 20Mhz CFG"));)
+ goto error;
+ }
+ if (val) {
+ pStaDs->htShortGI20Mhz =
+ (uint8_t)pAssocReq->HTCaps.shortGI20MHz;
+ } else {
+ /* Unset htShortGI20Mhz in ht_caps*/
+ *ht_cap_ie &= ~(1 << SIR_MAC_HT_CAP_SHORTGI20MHZ_S);
+ pStaDs->htShortGI20Mhz = 0;
+ }
+
+ if (wlan_cfg_get_int(pMac, WNI_CFG_SHORT_GI_40MHZ, &val) !=
+ eSIR_SUCCESS) {
+ PELOGE(lim_log(pMac, LOGE,
+ FL("could not retrieve shortGI 40Mhz CFG"));)
+ goto error;
+ }
+ if (val) {
+ pStaDs->htShortGI40Mhz =
+ (uint8_t)pAssocReq->HTCaps.shortGI40MHz;
+ } else {
+ /* Unset htShortGI40Mhz in ht_caps */
+ *ht_cap_ie &= ~(1 << SIR_MAC_HT_CAP_SHORTGI40MHZ_S);
+ pStaDs->htShortGI40Mhz = 0;
+ }
+
+ pStaDs->htSupportedChannelWidthSet =
+ (uint8_t) pAssocReq->HTCaps.supportedChannelWidthSet;
+ /*
+ * peer just follows AP; so when we are softAP/GO,
+ * we just store our session entry's secondary channel offset
+ * here in peer INFRA STA. However, if peer's 40MHz channel
+ * width support is disabled then secondary channel will be zero
+ */
+ pStaDs->htSecondaryChannelOffset =
+ (pStaDs->htSupportedChannelWidthSet) ? psessionEntry->
+ htSecondaryChannelOffset : 0;
+#ifdef WLAN_FEATURE_11AC
+ if (pAssocReq->operMode.present) {
+ pStaDs->vhtSupportedChannelWidthSet =
+ (uint8_t) ((pAssocReq->operMode.chanWidth ==
+ eHT_CHANNEL_WIDTH_80MHZ) ?
+ WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ :
+ WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ);
+ pStaDs->htSupportedChannelWidthSet =
+ (uint8_t) (pAssocReq->operMode.
+ chanWidth ? eHT_CHANNEL_WIDTH_40MHZ :
+ eHT_CHANNEL_WIDTH_20MHZ);
+ } else if (pAssocReq->VHTCaps.present) {
+ /* Check if STA has enabled it's channel bonding mode. */
+ /* If channel bonding mode is enabled, we decide based on SAP's current configuration. */
+ /* else, we set it to VHT20. */
+ pStaDs->vhtSupportedChannelWidthSet =
+ (uint8_t) ((pStaDs->htSupportedChannelWidthSet ==
+ eHT_CHANNEL_WIDTH_20MHZ) ?
+ WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ :
+ psessionEntry->ch_width - 1);
+ pStaDs->htMaxRxAMpduFactor =
+ pAssocReq->VHTCaps.maxAMPDULenExp;
+ }
+ /* Lesser among the AP and STA bandwidth of operation. */
+ pStaDs->htSupportedChannelWidthSet =
+ (pStaDs->htSupportedChannelWidthSet <
+ psessionEntry->htSupportedChannelWidthSet) ?
+ pStaDs->htSupportedChannelWidthSet :
+ psessionEntry->htSupportedChannelWidthSet;
+
+#endif
+ pStaDs->baPolicyFlag = 0xFF;
+ pStaDs->htLdpcCapable =
+ (uint8_t) pAssocReq->HTCaps.advCodingCap;
+ }
+
+ if (pAssocReq->VHTCaps.present && pAssocReq->wmeInfoPresent) {
+ pStaDs->vhtLdpcCapable =
+ (uint8_t) pAssocReq->VHTCaps.ldpcCodingCap;
+ }
+
+ if (!pAssocReq->wmeInfoPresent) {
+ pStaDs->mlmStaContext.htCapability = 0;
+ pStaDs->mlmStaContext.vhtCapability = 0;
+ }
+ if (pStaDs->mlmStaContext.vhtCapability) {
+ if (psessionEntry->txBFIniFeatureEnabled &&
+ pAssocReq->VHTCaps.suBeamFormerCap)
+ pStaDs->vhtBeamFormerCapable = 1;
+ else
+ pStaDs->vhtBeamFormerCapable = 0;
+ if (psessionEntry->enable_su_tx_bformer &&
+ pAssocReq->VHTCaps.suBeamformeeCap)
+ pStaDs->vht_su_bfee_capable = 1;
+ else
+ pStaDs->vht_su_bfee_capable = 0;
+ }
+#ifdef WLAN_FEATURE_11AC
+ if (lim_populate_matching_rate_set(pMac,
+ pStaDs,
+ &(pAssocReq->supportedRates),
+ &(pAssocReq->extendedRates),
+ pAssocReq->HTCaps.supportedMCSSet,
+ psessionEntry, &pAssocReq->VHTCaps)
+ != eSIR_SUCCESS)
+#else
+
+ if (lim_populate_matching_rate_set(pMac,
+ pStaDs,
+ &(pAssocReq->supportedRates),
+ &(pAssocReq->extendedRates),
+ pAssocReq->HTCaps.supportedMCSSet,
+ psessionEntry) != eSIR_SUCCESS)
+#endif
+ {
+ /* Could not update hash table entry at DPH with rateset */
+ lim_log(pMac, LOGE,
+ FL
+ ("could not update hash entry at DPH for aid=%d, MacAddr: "
+ MAC_ADDRESS_STR), peerIdx, MAC_ADDR_ARRAY(pHdr->sa));
+
+ /* Release AID */
+ lim_release_peer_idx(pMac, peerIdx, psessionEntry);
+
+ lim_reject_association(pMac, pHdr->sa,
+ subType, true, authType, peerIdx, true,
+ (tSirResultCodes)
+ eSIR_MAC_UNSPEC_FAILURE_STATUS,
+ psessionEntry);
+
+ if (psessionEntry->parsedAssocReq)
+ pAssocReq =
+ psessionEntry->parsedAssocReq[pStaDs->assocId];
+ goto error;
+ }
+#ifdef WLAN_FEATURE_11AC
+ if (pAssocReq->operMode.present) {
+ pStaDs->vhtSupportedRxNss = pAssocReq->operMode.rxNSS + 1;
+ } else {
+ pStaDs->vhtSupportedRxNss =
+ ((pStaDs->supportedRates.vhtRxMCSMap & MCSMAPMASK2x2)
+ == MCSMAPMASK2x2) ? 1 : 2;
+ }
+#endif
+
+ /* / Add STA context at MAC HW (BMU, RHP & TFP) */
+
+ pStaDs->qosMode = false;
+ pStaDs->lleEnabled = false;
+ if (pAssocReq->capabilityInfo.qos && (qosMode == eHAL_SET)) {
+ pStaDs->lleEnabled = true;
+ pStaDs->qosMode = true;
+ }
+
+ pStaDs->wmeEnabled = false;
+ pStaDs->wsmEnabled = false;
+ limGetWmeMode(psessionEntry, &wmeMode);
+ if ((!pStaDs->lleEnabled) && pAssocReq->wmeInfoPresent
+ && (wmeMode == eHAL_SET)) {
+ pStaDs->wmeEnabled = true;
+ pStaDs->qosMode = true;
+ limGetWsmMode(psessionEntry, &wsmMode);
+ /* WMM_APSD - WMM_SA related processing should be separate; WMM_SA and WMM_APSD
+ can coexist */
+ if (pAssocReq->WMMInfoStation.present) {
+ /* check whether AP supports or not */
+ if (LIM_IS_AP_ROLE(psessionEntry) &&
+ (psessionEntry->apUapsdEnable == 0) &&
+ (pAssocReq->WMMInfoStation.acbe_uapsd ||
+ pAssocReq->WMMInfoStation.acbk_uapsd ||
+ pAssocReq->WMMInfoStation.acvo_uapsd ||
+ pAssocReq->WMMInfoStation.acvi_uapsd)) {
+
+ /**
+ * Received Re/Association Request from
+ * STA when UPASD is not supported.
+ */
+ lim_log(pMac, LOGE,
+ FL("AP do not support UAPSD so reply "
+ "to STA accordingly"));
+ /* update UAPSD and send it to LIM to add STA */
+ pStaDs->qos.capability.qosInfo.acbe_uapsd = 0;
+ pStaDs->qos.capability.qosInfo.acbk_uapsd = 0;
+ pStaDs->qos.capability.qosInfo.acvo_uapsd = 0;
+ pStaDs->qos.capability.qosInfo.acvi_uapsd = 0;
+ pStaDs->qos.capability.qosInfo.maxSpLen = 0;
+
+ } else {
+ /* update UAPSD and send it to LIM to add STA */
+ pStaDs->qos.capability.qosInfo.acbe_uapsd =
+ pAssocReq->WMMInfoStation.acbe_uapsd;
+ pStaDs->qos.capability.qosInfo.acbk_uapsd =
+ pAssocReq->WMMInfoStation.acbk_uapsd;
+ pStaDs->qos.capability.qosInfo.acvo_uapsd =
+ pAssocReq->WMMInfoStation.acvo_uapsd;
+ pStaDs->qos.capability.qosInfo.acvi_uapsd =
+ pAssocReq->WMMInfoStation.acvi_uapsd;
+ pStaDs->qos.capability.qosInfo.maxSpLen =
+ pAssocReq->WMMInfoStation.max_sp_length;
+ }
+ }
+ if (pAssocReq->wsmCapablePresent && (wsmMode == eHAL_SET))
+ pStaDs->wsmEnabled = true;
+
+ }
+ /* Re/Assoc Response frame to requesting STA */
+ pStaDs->mlmStaContext.subType = subType;
+
+#ifdef WLAN_FEATURE_11W
+ pStaDs->rmfEnabled = (pmfConnection) ? 1 : 0;
+ pStaDs->pmfSaQueryState = DPH_SA_QUERY_NOT_IN_PROGRESS;
+ timerId.fields.sessionId = psessionEntry->peSessionId;
+ timerId.fields.peerIdx = peerIdx;
+ if (wlan_cfg_get_int(pMac, WNI_CFG_PMF_SA_QUERY_RETRY_INTERVAL,
+ &retryInterval) != eSIR_SUCCESS) {
+ lim_log(pMac, LOGE,
+ FL
+ ("Could not retrieve PMF SA Query retry interval value"));
+ lim_reject_association(pMac, pHdr->sa, subType, true, authType,
+ peerIdx, false,
+ (tSirResultCodes)
+ eSIR_MAC_UNSPEC_FAILURE_STATUS,
+ psessionEntry);
+ goto error;
+ }
+ if (WNI_CFG_PMF_SA_QUERY_RETRY_INTERVAL_STAMIN > retryInterval) {
+ retryInterval = WNI_CFG_PMF_SA_QUERY_RETRY_INTERVAL_STADEF;
+ }
+ if (tx_timer_create(&pStaDs->pmfSaQueryTimer, "PMF SA Query timer",
+ lim_pmf_sa_query_timer_handler, timerId.value,
+ SYS_MS_TO_TICKS((retryInterval * 1024) / 1000),
+ 0, TX_NO_ACTIVATE) != TX_SUCCESS) {
+ lim_log(pMac, LOGE, FL("could not create PMF SA Query timer"));
+ lim_reject_association(pMac, pHdr->sa,
+ subType, true, authType,
+ peerIdx, false,
+ (tSirResultCodes)
+ eSIR_MAC_UNSPEC_FAILURE_STATUS,
+ psessionEntry);
+ goto error;
+ }
+#endif
+
+ if (pAssocReq->ExtCap.present) {
+ lim_set_stads_rtt_cap(pStaDs,
+ (struct s_ext_cap *) pAssocReq->ExtCap.bytes, pMac);
+ } else {
+ pStaDs->timingMeasCap = 0;
+ PELOG1(lim_log(pMac, LOG1, FL("ExtCap not present"));)
+ }
+
+ /* BTAMP: Storing the parsed assoc request in the psessionEntry array */
+ if (psessionEntry->parsedAssocReq)
+ psessionEntry->parsedAssocReq[pStaDs->assocId] = pAssocReq;
+ assoc_req_copied = true;
+
+ /* BTAMP: If STA context already exist (ie. updateContext = 1)
+ * for this STA, then we should delete the old one, and add
+ * the new STA. This is taken care of in the lim_del_sta() routine.
+ *
+ * Prior to BTAMP, we were setting this flag so that when
+ * PE receives SME_ASSOC_CNF, and if this flag is set, then
+ * PE shall delete the old station and then add. But now in
+ * BTAMP, we're directly adding station before waiting for
+ * SME_ASSOC_CNF, so we can do this now.
+ */
+ if (!updateContext) {
+ pStaDs->mlmStaContext.updateContext = 0;
+
+ /* BTAMP: Add STA context at HW - issue WMA_ADD_STA_REQ to HAL */
+ if (lim_add_sta(pMac, pStaDs, false, psessionEntry) !=
+ eSIR_SUCCESS) {
+ lim_log(pMac, LOGE,
+ FL("could not Add STA with assocId=%d"),
+ pStaDs->assocId);
+ lim_reject_association(pMac, pStaDs->staAddr,
+ pStaDs->mlmStaContext.subType,
+ true,
+ pStaDs->mlmStaContext.authType,
+ pStaDs->assocId, true,
+ (tSirResultCodes)
+ eSIR_MAC_UNSPEC_FAILURE_STATUS,
+ psessionEntry);
+
+ if (psessionEntry->parsedAssocReq)
+ pAssocReq = psessionEntry->parsedAssocReq[
+ pStaDs->assocId];
+ goto error;
+ }
+ } else {
+ pStaDs->mlmStaContext.updateContext = 1;
+
+ mlmPrevState = pStaDs->mlmStaContext.mlmState;
+
+ /* As per the HAL/FW needs the reassoc req need not be calling lim_del_sta */
+ if (subType != LIM_REASSOC) {
+ /* we need to set the mlmState here in order differentiate in lim_del_sta. */
+ pStaDs->mlmStaContext.mlmState =
+ eLIM_MLM_WT_ASSOC_DEL_STA_RSP_STATE;
+ if (lim_del_sta(pMac, pStaDs, true, psessionEntry) !=
+ eSIR_SUCCESS) {
+ lim_log(pMac, LOGE,
+ FL
+ ("could not DEL STA with assocId=%d staId %d"),
+ pStaDs->assocId, pStaDs->staIndex);
+ lim_reject_association(pMac, pStaDs->staAddr,
+ pStaDs->mlmStaContext.
+ subType, true,
+ pStaDs->mlmStaContext.
+ authType, pStaDs->assocId,
+ true,
+ (tSirResultCodes)
+ eSIR_MAC_UNSPEC_FAILURE_STATUS,
+ psessionEntry);
+
+ /* Restoring the state back. */
+ pStaDs->mlmStaContext.mlmState = mlmPrevState;
+ if (psessionEntry->parsedAssocReq)
+ pAssocReq =
+ psessionEntry->parsedAssocReq[
+ pStaDs->assocId];
+ goto error;
+ }
+ } else {
+ /* mlmState is changed in lim_add_sta context */
+ /* use the same AID, already allocated */
+ if (lim_add_sta(pMac, pStaDs, false, psessionEntry) !=
+ eSIR_SUCCESS) {
+ lim_log(pMac, LOGE,
+ FL("Could not AddSta with assocId= %d"
+ "staId %d"),
+ pStaDs->assocId, pStaDs->staIndex);
+ lim_reject_association(pMac, pStaDs->staAddr,
+ pStaDs->mlmStaContext.
+ subType, true,
+ pStaDs->mlmStaContext.
+ authType, pStaDs->assocId,
+ true,
+ (tSirResultCodes)
+ eSIR_MAC_WME_REFUSED_STATUS,
+ psessionEntry);
+
+ /* Restoring the state back. */
+ pStaDs->mlmStaContext.mlmState = mlmPrevState;
+ if (psessionEntry->parsedAssocReq)
+ pAssocReq =
+ psessionEntry->parsedAssocReq[
+ pStaDs->assocId];
+ goto error;
+ }
+
+ }
+
+ }
+
+ /* AddSta is sucess here */
+ if (LIM_IS_AP_ROLE(psessionEntry) &&
+ IS_DOT11_MODE_HT(psessionEntry->dot11mode) &&
+ pAssocReq->HTCaps.present && pAssocReq->wmeInfoPresent) {
+ /** Update in the HAL Station Table for the Update of the Protection Mode */
+ lim_post_sm_state_update(pMac, pStaDs->staIndex,
+ pStaDs->htMIMOPSState,
+ pStaDs->staAddr,
+ psessionEntry->smeSessionId);
+ }
+
+ return;
+
+error:
+ if (pAssocReq != NULL) {
+ if (pAssocReq->assocReqFrame) {
+ cdf_mem_free(pAssocReq->assocReqFrame);
+ pAssocReq->assocReqFrame = NULL;
+ pAssocReq->assocReqFrameLength = 0;
+ }
+
+ cdf_mem_free(pAssocReq);
+ /* to avoid double free */
+ if (assoc_req_copied && psessionEntry->parsedAssocReq)
+ psessionEntry->parsedAssocReq[pStaDs->assocId] = NULL;
+ }
+
+ /* If it is not duplicate Assoc request then only make to Null */
+ if ((pStaDs != NULL) &&
+ (pStaDs->mlmStaContext.mlmState != eLIM_MLM_WT_ADD_STA_RSP_STATE)) {
+ if (psessionEntry->parsedAssocReq != NULL) {
+ pTempAssocReq =
+ psessionEntry->parsedAssocReq[pStaDs->assocId];
+ if (pTempAssocReq != NULL) {
+ if (pTempAssocReq->assocReqFrame) {
+ cdf_mem_free(pTempAssocReq->
+ assocReqFrame);
+ pTempAssocReq->assocReqFrame = NULL;
+ pTempAssocReq->assocReqFrameLength = 0;
+ }
+ cdf_mem_free(pTempAssocReq);
+ psessionEntry->
+ parsedAssocReq[pStaDs->assocId] = NULL;
+ }
+ }
+ }
+
+ return;
+
+} /*** end lim_process_assoc_req_frame() ***/
+
+#ifdef FEATURE_WLAN_WAPI
+/**
+ * lim_fill_assoc_ind_wapi_info()- Updates WAPI data in assoc indication
+ * @mac_ctx: Global Mac context
+ * @assoc_req: pointer to association request
+ * @assoc_ind: Pointer to association indication
+ * @wpsie: WPS IE
+ *
+ * This function updates WAPI meta data in association indication message
+ * sent to SME.
+ *
+ * Return: None
+ */
+static void lim_fill_assoc_ind_wapi_info(tpAniSirGlobal mac_ctx,
+ tpSirAssocReq assoc_req, tpLimMlmAssocInd assoc_ind,
+ uint8_t *wpsie)
+{
+ if (assoc_req->wapiPresent && (NULL == wpsie)) {
+ lim_log(mac_ctx, LOG2,
+ FL("Received WAPI IE length in Assoc Req is %d"),
+ assoc_req->wapi.length);
+ assoc_ind->wapiIE.wapiIEdata[0] = SIR_MAC_WAPI_EID;
+ assoc_ind->wapiIE.wapiIEdata[1] = assoc_req->wapi.length;
+ cdf_mem_copy(&assoc_ind->wapiIE.wapiIEdata[2],
+ assoc_req->wapi.info, assoc_req->wapi.length);
+ assoc_ind->wapiIE.length =
+ 2 + assoc_req->wapi.length;
+ }
+ return;
+}
+#endif
+
+/**
+ * lim_fill_assoc_ind_vht_info() - Updates VHT information in assoc indication
+ * @mac_ctx: Global Mac context
+ * @assoc_req: pointer to association request
+ * @session_entry: PE session entry
+ * @assoc_ind: Pointer to association indication
+ *
+ * This function updates VHT information in association indication message
+ * sent to SME.
+ *
+ * Return: None
+ */
+static void lim_fill_assoc_ind_vht_info(tpAniSirGlobal mac_ctx,
+ tpPESession session_entry, tpSirAssocReq assoc_req,
+ tpLimMlmAssocInd assoc_ind)
+{
+ uint8_t chan;
+
+ if (session_entry->limRFBand == SIR_BAND_2_4_GHZ) {
+ if (session_entry->vhtCapability
+ && assoc_req->VHTCaps.present)
+ assoc_ind->chan_info.info = MODE_11AC_VHT20;
+ else if (session_entry->htCapability
+ && assoc_req->HTCaps.present)
+ assoc_ind->chan_info.info = MODE_11NG_HT20;
+ else
+ assoc_ind->chan_info.info = MODE_11G;
+ } else {
+ if (session_entry->vhtCapability
+ && assoc_req->VHTCaps.present) {
+ if ((session_entry->ch_width > CH_WIDTH_40MHZ)
+ && assoc_req->HTCaps.supportedChannelWidthSet) {
+ chan = session_entry->ch_center_freq_seg0;
+ assoc_ind->chan_info.band_center_freq1 =
+ cds_chan_to_freq(chan);
+ assoc_ind->chan_info.info = MODE_11AC_VHT80;
+ } else if ((session_entry->ch_width == CH_WIDTH_40MHZ)
+ && assoc_req->HTCaps.supportedChannelWidthSet) {
+ assoc_ind->chan_info.info = MODE_11AC_VHT40;
+ if (session_entry->htSecondaryChannelOffset ==
+ PHY_DOUBLE_CHANNEL_LOW_PRIMARY)
+ assoc_ind->chan_info.band_center_freq1
+ += 10;
+ else
+ assoc_ind->chan_info.band_center_freq1
+ -= 10;
+ } else {
+ assoc_ind->chan_info.info = MODE_11AC_VHT20;
+ }
+ } else if (session_entry->htCapability
+ && assoc_req->HTCaps.present) {
+ if ((session_entry->ch_width == CH_WIDTH_40MHZ)
+ && assoc_req->HTCaps.supportedChannelWidthSet) {
+ assoc_ind->chan_info.info = MODE_11NA_HT40;
+ if (session_entry->htSecondaryChannelOffset ==
+ PHY_DOUBLE_CHANNEL_LOW_PRIMARY)
+ assoc_ind->chan_info.band_center_freq1
+ += 10;
+ else
+ assoc_ind->chan_info.band_center_freq1
+ -= 10;
+ } else {
+ assoc_ind->chan_info.info = MODE_11NA_HT20;
+ }
+ } else {
+ assoc_ind->chan_info.info = MODE_11A;
+ }
+ }
+ return;
+}
+
+/**
+ * lim_send_mlm_assoc_ind() - Sends assoc indication to SME
+ * @mac_ctx: Global Mac context
+ * @sta_ds: Station DPH hash entry
+ * @session_entry: PE session entry
+ *
+ * This function sends either LIM_MLM_ASSOC_IND
+ * or LIM_MLM_REASSOC_IND to SME.
+ *
+ * Return: None
+ */
+void lim_send_mlm_assoc_ind(tpAniSirGlobal mac_ctx,
+ tpDphHashNode sta_ds, tpPESession session_entry)
+{
+ tpLimMlmAssocInd assoc_ind = NULL;
+ tpSirAssocReq assoc_req;
+ uint16_t temp, rsn_len;
+ uint32_t phy_mode;
+ uint8_t sub_type;
+ uint8_t *wpsie = NULL;
+ uint32_t tmp;
+
+ /* Get a copy of the already parsed Assoc Request */
+ assoc_req =
+ (tpSirAssocReq) session_entry->parsedAssocReq[sta_ds->assocId];
+
+ /* Get the phy_mode */
+ lim_get_phy_mode(mac_ctx, &phy_mode, session_entry);
+
+ /* Determine if its Assoc or ReAssoc Request */
+ if (assoc_req->reassocRequest == 1)
+ sub_type = LIM_REASSOC;
+ else
+ sub_type = LIM_ASSOC;
+
+ lim_log(mac_ctx, LOG1,
+ FL("Sessionid %d ssid %s sub_type %d Associd %d staAddr "
+ MAC_ADDRESS_STR), session_entry->peSessionId,
+ assoc_req->ssId.ssId, sub_type, sta_ds->assocId,
+ MAC_ADDR_ARRAY(sta_ds->staAddr));
+
+ if (sub_type == LIM_ASSOC || sub_type == LIM_REASSOC) {
+ temp = sizeof(tLimMlmAssocInd);
+
+ assoc_ind = cdf_mem_malloc(temp);
+ if (NULL == assoc_ind) {
+ lim_release_peer_idx(mac_ctx, sta_ds->assocId,
+ session_entry);
+ lim_log(mac_ctx, LOGP,
+ FL("AllocateMemory failed for assoc_ind"));
+ return;
+ }
+ cdf_mem_set(assoc_ind, temp, 0);
+ cdf_mem_copy((uint8_t *) assoc_ind->peerMacAddr,
+ (uint8_t *) sta_ds->staAddr, sizeof(tSirMacAddr));
+ assoc_ind->aid = sta_ds->assocId;
+ cdf_mem_copy((uint8_t *) &assoc_ind->ssId,
+ (uint8_t *) &(assoc_req->ssId),
+ assoc_req->ssId.length + 1);
+ assoc_ind->sessionId = session_entry->peSessionId;
+ assoc_ind->authType = sta_ds->mlmStaContext.authType;
+ assoc_ind->capabilityInfo = assoc_req->capabilityInfo;
+
+ /* Fill in RSN IE information */
+ assoc_ind->rsnIE.length = 0;
+ /* if WPS IE is present, ignore RSN IE */
+ if (assoc_req->addIEPresent && assoc_req->addIE.length) {
+ wpsie = limGetWscIEPtr(mac_ctx,
+ assoc_req->addIE.addIEdata,
+ assoc_req->addIE.length);
+ }
+ if (assoc_req->rsnPresent && (NULL == wpsie)) {
+ lim_log(mac_ctx, LOG2, FL("Assoc Req RSN IE len = %d"),
+ assoc_req->rsn.length);
+ assoc_ind->rsnIE.length = 2 + assoc_req->rsn.length;
+ assoc_ind->rsnIE.rsnIEdata[0] = SIR_MAC_RSN_EID;
+ assoc_ind->rsnIE.rsnIEdata[1] =
+ assoc_req->rsn.length;
+ cdf_mem_copy(&assoc_ind->rsnIE.rsnIEdata[2],
+ assoc_req->rsn.info,
+ assoc_req->rsn.length);
+ }
+ /* Fill in 802.11h related info */
+ if (assoc_req->powerCapabilityPresent
+ && assoc_req->supportedChannelsPresent) {
+ assoc_ind->spectrumMgtIndicator = eSIR_TRUE;
+ assoc_ind->powerCap.minTxPower =
+ assoc_req->powerCapability.minTxPower;
+ assoc_ind->powerCap.maxTxPower =
+ assoc_req->powerCapability.maxTxPower;
+ lim_convert_supported_channels(mac_ctx, assoc_ind,
+ assoc_req);
+ } else {
+ assoc_ind->spectrumMgtIndicator = eSIR_FALSE;
+ }
+
+ /* This check is to avoid extra Sec IEs present incase of WPS */
+ if (assoc_req->wpaPresent && (NULL == wpsie)) {
+ rsn_len = assoc_ind->rsnIE.length;
+ if ((rsn_len + assoc_req->wpa.length)
+ >= SIR_MAC_MAX_IE_LENGTH) {
+ lim_log(mac_ctx, LOGE,
+ FL("rsnIEdata index out of bounds %d"),
+ rsn_len);
+ cdf_mem_free(assoc_ind);
+ return;
+ }
+ assoc_ind->rsnIE.rsnIEdata[rsn_len] =
+ SIR_MAC_WPA_EID;
+ assoc_ind->rsnIE.rsnIEdata[rsn_len + 1]
+ = assoc_req->wpa.length;
+ cdf_mem_copy(
+ &assoc_ind->rsnIE.rsnIEdata[rsn_len + 2],
+ assoc_req->wpa.info, assoc_req->wpa.length);
+ assoc_ind->rsnIE.length += 2 + assoc_req->wpa.length;
+ }
+#ifdef FEATURE_WLAN_WAPI
+ lim_fill_assoc_ind_wapi_info(mac_ctx, assoc_req, assoc_ind,
+ wpsie);
+#endif
+
+ assoc_ind->addIE.length = 0;
+ if (assoc_req->addIEPresent) {
+ cdf_mem_copy(&assoc_ind->addIE.addIEdata,
+ assoc_req->addIE.addIEdata,
+ assoc_req->addIE.length);
+ assoc_ind->addIE.length = assoc_req->addIE.length;
+ }
+ /*
+ * Add HT Capabilities into addIE for OBSS
+ * processing in hostapd
+ */
+ if (assoc_req->HTCaps.present) {
+ rsn_len = assoc_ind->addIE.length;
+ if (assoc_ind->addIE.length + DOT11F_IE_HTCAPS_MIN_LEN
+ + 2 < SIR_MAC_MAX_IE_LENGTH) {
+ assoc_ind->addIE.addIEdata[rsn_len] =
+ SIR_MAC_HT_CAPABILITIES_EID;
+ assoc_ind->addIE.addIEdata[rsn_len + 1] =
+ DOT11F_IE_HTCAPS_MIN_LEN;
+ cdf_mem_copy(
+ &assoc_ind->addIE.addIEdata[rsn_len+2],
+ ((uint8_t *)&assoc_req->HTCaps) + 1,
+ DOT11F_IE_HTCAPS_MIN_LEN);
+ assoc_ind->addIE.length +=
+ 2 + DOT11F_IE_HTCAPS_MIN_LEN;
+ } else {
+ lim_log(mac_ctx, LOGP,
+ FL("Fail:HT capabilities IE to addIE"));
+ }
+ }
+
+ if (assoc_req->wmeInfoPresent) {
+ if (wlan_cfg_get_int (mac_ctx,
+ (uint16_t) WNI_CFG_WME_ENABLED, &tmp)
+ != eSIR_SUCCESS)
+ lim_log(mac_ctx, LOGP,
+ FL("wlan_cfg_get_int failed for id %d"),
+ WNI_CFG_WME_ENABLED);
+
+ /* check whether AP is enabled with WMM */
+ if (tmp)
+ assoc_ind->WmmStaInfoPresent = 1;
+ else
+ assoc_ind->WmmStaInfoPresent = 0;
+ /*
+ * Note: we are not rejecting association here
+ * because IOT will fail
+ */
+ }
+ /* Required for indicating the frames to upper layer */
+ assoc_ind->assocReqLength = assoc_req->assocReqFrameLength;
+ assoc_ind->assocReqPtr = assoc_req->assocReqFrame;
+
+ assoc_ind->beaconPtr = session_entry->beacon;
+ assoc_ind->beaconLength = session_entry->bcnLen;
+
+ assoc_ind->chan_info.chan_id =
+ session_entry->currentOperChannel;
+ assoc_ind->chan_info.mhz =
+ cds_chan_to_freq(session_entry->currentOperChannel);
+ assoc_ind->chan_info.band_center_freq1 =
+ cds_chan_to_freq(session_entry->currentOperChannel);
+ assoc_ind->chan_info.band_center_freq2 = 0;
+ assoc_ind->chan_info.reg_info_1 =
+ (session_entry->maxTxPower << 16);
+ assoc_ind->chan_info.reg_info_2 =
+ (session_entry->maxTxPower << 8);
+ /* updates VHT information in assoc indication */
+ lim_fill_assoc_ind_vht_info(mac_ctx, session_entry, assoc_req,
+ assoc_ind);
+ lim_post_sme_message(mac_ctx, LIM_MLM_ASSOC_IND,
+ (uint32_t *) assoc_ind);
+ cdf_mem_free(assoc_ind);
+ }
+ return;
+}
diff --git a/core/mac/src/pe/lim/lim_process_assoc_rsp_frame.c b/core/mac/src/pe/lim/lim_process_assoc_rsp_frame.c
new file mode 100644
index 0000000..e4c672b
--- /dev/null
+++ b/core/mac/src/pe/lim/lim_process_assoc_rsp_frame.c
@@ -0,0 +1,1109 @@
+/*
+ * Copyright (c) 2011-2015 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_process_assoc_rsp_frame.cc contains the code
+ * for processing Re/Association Response Frame.
+ * Author: Chandra Modumudi
+ * Date: 03/18/02
+ * History:-
+ * Date Modified by Modification Information
+ * --------------------------------------------------------------------
+ *
+ */
+
+#include "wni_api.h"
+#include "wni_cfg.h"
+#include "ani_global.h"
+#include "cfg_api.h"
+#include "sch_api.h"
+
+#include "utils_api.h"
+#include "lim_types.h"
+#include "lim_utils.h"
+#include "lim_assoc_utils.h"
+#include "lim_security_utils.h"
+#include "lim_ser_des_utils.h"
+#include "lim_sta_hash_api.h"
+#include "lim_send_messages.h"
+
+
+extern tSirRetStatus sch_beacon_edca_process(tpAniSirGlobal pMac,
+ tSirMacEdcaParamSetIE *edca, tpPESession psessionEntry);
+
+/**
+ * lim_update_stads_htcap() - Updates station Descriptor HT capability
+ * @mac_ctx: Pointer to Global MAC structure
+ * @sta_ds: Station Descriptor in DPH
+ * @assoc_rsp: Pointer to Association Response Structure
+ *
+ * This function is called to Update the HT capabilities in
+ * Station Descriptor (dph) Details from
+ * Association / ReAssociation Response Frame
+ *
+ * Return: None
+ */
+static void lim_update_stads_htcap(tpAniSirGlobal mac_ctx,
+ tpDphHashNode sta_ds, tpSirAssocRsp assoc_rsp)
+{
+ uint16_t highest_rxrate = 0;
+ tDot11fIEHTCaps *ht_caps;
+
+ ht_caps = &assoc_rsp->HTCaps;
+ sta_ds->mlmStaContext.htCapability = assoc_rsp->HTCaps.present;
+ if (assoc_rsp->HTCaps.present) {
+ sta_ds->htGreenfield =
+ (uint8_t) ht_caps->greenField;
+ sta_ds->htSupportedChannelWidthSet =
+ (uint8_t) (ht_caps->supportedChannelWidthSet ?
+ assoc_rsp->HTInfo.recommendedTxWidthSet :
+ ht_caps->supportedChannelWidthSet);
+ sta_ds->htLsigTXOPProtection =
+ (uint8_t) ht_caps->lsigTXOPProtection;
+ sta_ds->htMIMOPSState =
+ (tSirMacHTMIMOPowerSaveState)ht_caps->mimoPowerSave;
+ sta_ds->htMaxAmsduLength =
+ (uint8_t) ht_caps->maximalAMSDUsize;
+ sta_ds->htAMpduDensity = ht_caps->mpduDensity;
+ sta_ds->htDsssCckRate40MHzSupport =
+ (uint8_t) ht_caps->dsssCckMode40MHz;
+ sta_ds->htShortGI20Mhz =
+ (uint8_t) ht_caps->shortGI20MHz;
+ sta_ds->htShortGI40Mhz =
+ (uint8_t) ht_caps->shortGI40MHz;
+ sta_ds->htMaxRxAMpduFactor =
+ ht_caps->maxRxAMPDUFactor;
+ lim_fill_rx_highest_supported_rate(mac_ctx, &highest_rxrate,
+ ht_caps->supportedMCSSet);
+ sta_ds->supportedRates.rxHighestDataRate =
+ highest_rxrate;
+ /*
+ * This is for AP as peer STA and we are INFRA STA
+ *.We will put APs offset in dph node which is peer STA
+ */
+ sta_ds->htSecondaryChannelOffset =
+ (uint8_t) assoc_rsp->HTInfo.secondaryChannelOffset;
+ /*
+ * FIXME_AMPDU
+ * In the future, may need to check for
+ * "assoc.HTCaps.delayedBA"
+ * For now, it is IMMEDIATE BA only on ALL TID's
+ */
+ sta_ds->baPolicyFlag = 0xFF;
+ }
+}
+
+/**
+ * lim_update_assoc_sta_datas() - Updates station Descriptor
+ * mac_ctx: Pointer to Global MAC structure
+ * sta_ds: Station Descriptor in DPH
+ * assoc_rsp: Pointer to Association Response Structure
+ * session_entry : PE session Entry
+ *
+ * This function is called to Update the Station Descriptor (dph) Details from
+ * Association / ReAssociation Response Frame
+ *
+ * Return: None
+ */
+void lim_update_assoc_sta_datas(tpAniSirGlobal mac_ctx,
+ tpDphHashNode sta_ds, tpSirAssocRsp assoc_rsp,
+ tpPESession session_entry)
+{
+ uint32_t phy_mode;
+ bool qos_mode;
+ tDot11fIEVHTCaps *vht_caps = NULL;
+
+ lim_get_phy_mode(mac_ctx, &phy_mode, session_entry);
+ sta_ds->staType = STA_ENTRY_SELF;
+ limGetQosMode(session_entry, &qos_mode);
+ sta_ds->mlmStaContext.authType = session_entry->limCurrentAuthType;
+
+ /* Add capabilities information, rates and AID */
+ sta_ds->mlmStaContext.capabilityInfo = assoc_rsp->capabilityInfo;
+ sta_ds->shortPreambleEnabled =
+ (uint8_t) assoc_rsp->capabilityInfo.shortPreamble;
+
+ /* Update HT Capabilites only when the self mode supports HT */
+ if (IS_DOT11_MODE_HT(session_entry->dot11mode))
+ lim_update_stads_htcap(mac_ctx, sta_ds, assoc_rsp);
+
+#ifdef WLAN_FEATURE_11AC
+ if (assoc_rsp->VHTCaps.present)
+ vht_caps = &assoc_rsp->VHTCaps;
+ else if (assoc_rsp->vendor2_ie.VHTCaps.present)
+ vht_caps = &assoc_rsp->vendor2_ie.VHTCaps;
+
+ if (IS_DOT11_MODE_VHT(session_entry->dot11mode)) {
+ if ((vht_caps != NULL) && vht_caps->present) {
+ sta_ds->mlmStaContext.vhtCapability =
+ vht_caps->present;
+ /*
+ * If 11ac is supported and if the peer is
+ * sending VHT capabilities,
+ * then htMaxRxAMpduFactor should be
+ * overloaded with VHT maxAMPDULenExp
+ */
+ sta_ds->htMaxRxAMpduFactor = vht_caps->maxAMPDULenExp;
+ if (session_entry->htSupportedChannelWidthSet) {
+ if (assoc_rsp->VHTOperation.present)
+ sta_ds->vhtSupportedChannelWidthSet =
+ assoc_rsp->VHTOperation.chanWidth;
+ else
+ sta_ds->vhtSupportedChannelWidthSet =
+ eHT_CHANNEL_WIDTH_40MHZ;
+ }
+ }
+ }
+ if (lim_populate_peer_rate_set(mac_ctx, &sta_ds->supportedRates,
+ assoc_rsp->HTCaps.supportedMCSSet,
+ false, session_entry,
+ vht_caps) != eSIR_SUCCESS) {
+ lim_log(mac_ctx, LOGP,
+ FL("could not get rateset and extended rate set"));
+ return;
+ }
+#else
+ if (lim_populate_peer_rate_set(mac_ctx, &sta_ds->supportedRates,
+ assoc_rsp->HTCaps.supportedMCSSet,
+ false, session_entry) != eSIR_SUCCESS) {
+ lim_log(mac_ctx, LOGP,
+ FL("could not get rateset and extended rate set"));
+ return;
+ }
+#endif
+#ifdef WLAN_FEATURE_11AC
+ sta_ds->vhtSupportedRxNss =
+ ((sta_ds->supportedRates.vhtRxMCSMap & MCSMAPMASK2x2)
+ == MCSMAPMASK2x2) ? 1 : 2;
+#endif
+ /* If one of the rates is 11g rates, set the ERP mode. */
+ if ((phy_mode == WNI_CFG_PHY_MODE_11G) &&
+ sirIsArate(sta_ds->supportedRates.llaRates[0] & 0x7f))
+ sta_ds->erpEnabled = eHAL_SET;
+
+ /* Could not get prop rateset from CFG. Log error. */
+ sta_ds->qosMode = 0;
+ sta_ds->lleEnabled = 0;
+
+ /* update TSID to UP mapping */
+ if (qos_mode) {
+ if (assoc_rsp->edcaPresent) {
+ tSirRetStatus status;
+ status =
+ sch_beacon_edca_process(mac_ctx,
+ &assoc_rsp->edca, session_entry);
+ lim_log(mac_ctx, LOG2,
+ "Edca set update based on AssocRsp: status %d",
+ status);
+ if (status != eSIR_SUCCESS) {
+ lim_log(mac_ctx, LOGE,
+ FL("Edca error in AssocResp "));
+ } else {
+ /* update default tidmap based on ACM */
+ sta_ds->qosMode = 1;
+ sta_ds->lleEnabled = 1;
+ }
+ }
+ }
+
+ sta_ds->wmeEnabled = 0;
+ sta_ds->wsmEnabled = 0;
+ if (session_entry->limWmeEnabled && assoc_rsp->wmeEdcaPresent) {
+ tSirRetStatus status;
+ status = sch_beacon_edca_process(mac_ctx, &assoc_rsp->edca,
+ session_entry);
+ lim_log(mac_ctx, LOGW,
+ "WME Edca set update based on AssocRsp: status %d",
+ status);
+
+ if (status != eSIR_SUCCESS)
+ lim_log(mac_ctx, LOGE,
+ FL("WME Edca error in AssocResp - ignoring"));
+
+ else {
+ /* update default tidmap based on HashACM */
+ sta_ds->qosMode = 1;
+ sta_ds->wmeEnabled = 1;
+ }
+ } else {
+ /*
+ * We received assoc rsp from a legacy AP.
+ * So fill in the default local EDCA params.
+ * This is needed (refer to bug #14989) as we'll
+ * be passing the gLimEdcaParams to HAL in
+ * lim_process_sta_mlm_add_bss_rsp().
+ */
+ sch_set_default_edca_params(mac_ctx, session_entry);
+ }
+
+ if (qos_mode && (!sta_ds->qosMode) &&
+ sta_ds->mlmStaContext.htCapability) {
+ /*
+ * Enable QOS for all HT AP's even though WMM
+ * or 802.11E IE is not present
+ */
+ sta_ds->qosMode = 1;
+ sta_ds->wmeEnabled = 1;
+ }
+#ifdef WLAN_FEATURE_11W
+ if (session_entry->limRmfEnabled)
+ sta_ds->rmfEnabled = 1;
+#endif
+}
+
+/**
+ * @function : lim_update_re_assoc_globals
+ *
+ * @brief : This function is called to Update the Globals (LIM) during ReAssoc.
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ *
+ ***NOTE:
+ *
+ * @param pMac - Pointer to Global MAC structure
+ * @param pAssocRsp - Pointer to Association Response Structure
+ *
+ * @return None
+ */
+
+void lim_update_re_assoc_globals(tpAniSirGlobal pMac, tpSirAssocRsp pAssocRsp,
+ tpPESession psessionEntry)
+{
+ /* Update the current Bss Information */
+ cdf_mem_copy(psessionEntry->bssId,
+ psessionEntry->limReAssocbssId, sizeof(tSirMacAddr));
+ psessionEntry->currentOperChannel = psessionEntry->limReassocChannelId;
+ psessionEntry->htSecondaryChannelOffset =
+ psessionEntry->reAssocHtSupportedChannelWidthSet;
+ psessionEntry->htRecommendedTxWidthSet =
+ psessionEntry->reAssocHtRecommendedTxWidthSet;
+ psessionEntry->htSecondaryChannelOffset =
+ psessionEntry->reAssocHtSecondaryChannelOffset;
+ psessionEntry->limCurrentBssCaps = psessionEntry->limReassocBssCaps;
+ psessionEntry->limCurrentBssQosCaps =
+ psessionEntry->limReassocBssQosCaps;
+ psessionEntry->limCurrentBssPropCap =
+ psessionEntry->limReassocBssPropCap;
+
+ cdf_mem_copy((uint8_t *) &psessionEntry->ssId,
+ (uint8_t *) &psessionEntry->limReassocSSID,
+ psessionEntry->limReassocSSID.length + 1);
+
+ /* Store assigned AID for TIM processing */
+ psessionEntry->limAID = pAssocRsp->aid & 0x3FFF;
+ /** Set the State Back to ReAssoc Rsp*/
+ psessionEntry->limMlmState = eLIM_MLM_WT_REASSOC_RSP_STATE;
+ MTRACE(mac_trace
+ (pMac, TRACE_CODE_MLM_STATE, psessionEntry->peSessionId,
+ psessionEntry->limMlmState));
+
+}
+#ifdef WLAN_FEATURE_VOWIFI_11R
+/**
+ * lim_update_ric_data() - update session with ric data
+ * @mac_ctx: Pointer to Global MAC structure
+ * @session_entry: PE session handle
+ * @assoc_rsp: pointer to assoc response
+ *
+ * This function is called by lim_process_assoc_rsp_frame() to
+ * update PE session context with RIC data.
+ *
+ * Return: None
+ */
+static void lim_update_ric_data(tpAniSirGlobal mac_ctx,
+ tpPESession session_entry, tpSirAssocRsp assoc_rsp)
+{
+ if (session_entry->ricData != NULL) {
+ cdf_mem_free(session_entry->ricData);
+ session_entry->ricData = NULL;
+ }
+ if (assoc_rsp->ricPresent) {
+ session_entry->RICDataLen =
+ assoc_rsp->num_RICData * sizeof(tDot11fIERICDataDesc);
+ session_entry->ricData =
+ cdf_mem_malloc(session_entry->RICDataLen);
+ if (NULL == session_entry->ricData) {
+ lim_log(mac_ctx, LOGE,
+ FL("Assoc res/RIC: Unable to allocate memory"));
+ session_entry->RICDataLen = 0;
+ } else {
+ cdf_mem_copy(session_entry->ricData,
+ &assoc_rsp->RICData[0],
+ session_entry->RICDataLen);
+ }
+ } else {
+ lim_log(mac_ctx, LOG1,
+ FL("Ric is not present,Set RICDataLen & RicData to 0"));
+ session_entry->RICDataLen = 0;
+ session_entry->ricData = NULL;
+ }
+ return;
+}
+#endif
+
+#ifdef FEATURE_WLAN_ESE
+
+/**
+ * lim_update_ese_tspec() - update session with Tspec info.
+ * @mac_ctx: Pointer to Global MAC structure
+ * @session_entry: PE session handle
+ * @assoc_rsp: pointer to assoc response
+ *
+ * This function is called by lim_process_assoc_rsp_frame() to
+ * update PE session context with Tspec data.
+ *
+ * Return: None
+ */
+static void lim_update_ese_tspec(tpAniSirGlobal mac_ctx,
+ tpPESession session_entry, tpSirAssocRsp assoc_rsp)
+{
+ if (session_entry->tspecIes != NULL) {
+ cdf_mem_free(session_entry->tspecIes);
+ session_entry->tspecIes = NULL;
+ }
+ if (assoc_rsp->tspecPresent) {
+ session_entry->tspecLen =
+ assoc_rsp->num_tspecs * sizeof(tDot11fIEWMMTSPEC);
+ session_entry->tspecIes =
+ cdf_mem_malloc(session_entry->tspecLen);
+ if (NULL == session_entry->tspecIes) {
+ lim_log(mac_ctx, LOGE,
+ FL("Assoc Rsp/Tspec:Fail to allocate memory"));
+ session_entry->tspecLen = 0;
+ } else {
+ cdf_mem_copy(session_entry->tspecIes,
+ &assoc_rsp->TSPECInfo[0],
+ session_entry->tspecLen);
+ }
+ lim_log(mac_ctx, LOG1, FL(" Tspec EID present in assoc rsp "));
+ } else {
+ session_entry->tspecLen = 0;
+ session_entry->tspecIes = NULL;
+ lim_log(mac_ctx, LOG1,
+ FL(" Tspec EID *NOT* present in assoc rsp "));
+ }
+ return;
+}
+
+/**
+ * lim_update_ese_tsm() - update session with TSM info.
+ * @mac_ctx: Pointer to Global MAC structure
+ * @session_entry: PE session handle
+ * @assoc_rsp: pointer to assoc response
+ *
+ * This function is called by lim_process_assoc_rsp_frame() to
+ * update PE session context with TSM IE data and send
+ * eWNI_TSM_IE_IND to SME.
+ *
+ * Return: None
+ */
+static void lim_update_ese_tsm(tpAniSirGlobal mac_ctx,
+ tpPESession session_entry, tpSirAssocRsp assoc_rsp)
+{
+ uint8_t cnt = 0;
+ tpEseTSMContext tsm_ctx;
+
+ lim_log(mac_ctx, LOG1,
+ FL("TSM IE Present in Reassoc Rsp"));
+ /*
+ * Start the TSM timer only if the TSPEC
+ * Ie is present in the reassoc rsp
+ */
+ if (!assoc_rsp->tspecPresent) {
+ lim_log(mac_ctx, LOGE,
+ FL("TSM present but TSPEC IE not present"));
+ return;
+ }
+ tsm_ctx = &session_entry->eseContext.tsm;
+ /* Find the TSPEC IE with VO user priority */
+ for (cnt = 0; cnt < assoc_rsp->num_tspecs; cnt++) {
+ if (upToAc(assoc_rsp->TSPECInfo[cnt].user_priority) ==
+ EDCA_AC_VO) {
+ tsm_ctx->tid =
+ assoc_rsp->TSPECInfo[cnt].user_priority;
+ cdf_mem_copy(&tsm_ctx->tsmInfo,
+ &assoc_rsp->tsmIE, sizeof(tSirMacESETSMIE));
+#ifdef FEATURE_WLAN_ESE_UPLOAD
+ lim_send_sme_tsm_ie_ind(mac_ctx,
+ session_entry, assoc_rsp->tsmIE.tsid,
+ assoc_rsp->tsmIE.state,
+ assoc_rsp->tsmIE.msmt_interval);
+#else
+ limActivateTSMStatsTimer(mac_ctx, session_entry);
+#endif
+ if (tsm_ctx->tsmInfo.state)
+ tsm_ctx->tsmMetrics.RoamingCount++;
+ break;
+ }
+ }
+}
+#endif
+
+/**
+ * lim_update_stads_ext_cap() - update sta ds with ext cap
+ * @mac_ctx: Pointer to Global MAC structure
+ * @session_entry: PE session handle
+ * @assoc_rsp: pointer to assoc response
+ *
+ * This function is called by lim_process_assoc_rsp_frame() to
+ * update STA DS with ext capablities.
+ *
+ * Return: None
+ */
+static void lim_update_stads_ext_cap(tpAniSirGlobal mac_ctx,
+ tpPESession session_entry, tpSirAssocRsp assoc_rsp,
+ tpDphHashNode sta_ds)
+{
+ struct s_ext_cap *ext_cap;
+ if (!assoc_rsp->ExtCap.present) {
+ sta_ds->timingMeasCap = 0;
+#ifdef FEATURE_WLAN_TDLS
+ session_entry->tdls_prohibited = false;
+ session_entry->tdls_chan_swit_prohibited = false;
+#endif
+ lim_log(mac_ctx, LOG1, FL("ExtCap not present"));
+ return;
+ }
+
+ ext_cap = (struct s_ext_cap *)assoc_rsp->ExtCap.bytes;
+ lim_set_stads_rtt_cap(sta_ds, ext_cap, mac_ctx);
+#ifdef FEATURE_WLAN_TDLS
+ session_entry->tdls_prohibited = ext_cap->tdls_prohibited;
+ session_entry->tdls_chan_swit_prohibited =
+ ext_cap->tdls_chan_swit_prohibited;
+ lim_log(mac_ctx, LOG1,
+ FL("ExtCap: tdls_prohibited:%d, tdls_chan_swit_prohibited: %d"),
+ ext_cap->tdls_prohibited,
+ ext_cap->tdls_chan_swit_prohibited);
+#endif
+}
+
+/**
+ * lim_process_assoc_rsp_frame() - Processes assoc response
+ * @mac_ctx: Pointer to Global MAC structure
+ * @rx_packet_info - A pointer to Rx packet info structure
+ * @sub_type - Indicates whether it is Association Response (=0) or
+ * Reassociation Response (=1) frame
+ *
+ * This function is called by limProcessMessageQueue() upon
+ * Re/Association Response frame reception.
+ *
+ * Return: None
+ */
+
+void
+lim_process_assoc_rsp_frame(tpAniSirGlobal mac_ctx,
+ uint8_t *rx_pkt_info, uint8_t subtype, tpPESession session_entry)
+{
+ uint8_t *body;
+ uint16_t caps, ie_len;
+ uint32_t frame_len;
+ tSirMacAddr current_bssid;
+ tpSirMacMgmtHdr hdr = NULL;
+ tSirMacCapabilityInfo mac_capab;
+ tpDphHashNode sta_ds;
+ tpSirAssocRsp assoc_rsp;
+ tLimMlmAssocCnf assoc_cnf;
+ tSchBeaconStruct *beacon;
+#ifdef WLAN_FEATURE_ROAM_OFFLOAD
+ uint8_t sme_sessionid = 0;
+#endif
+ tCsrRoamSession *roam_session;
+
+ /* Initialize status code to success. */
+#ifdef WLAN_FEATURE_ROAM_OFFLOAD
+ if (session_entry->bRoamSynchInProgress)
+ hdr = (tpSirMacMgmtHdr) mac_ctx->roam.pReassocResp;
+ else
+#endif
+ hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info);
+#ifdef WLAN_FEATURE_ROAM_OFFLOAD
+ sme_sessionid = session_entry->smeSessionId;
+#endif
+ assoc_cnf.resultCode = eSIR_SME_SUCCESS;
+ /* Update PE session Id */
+ assoc_cnf.sessionId = session_entry->peSessionId;
+ if (hdr == NULL) {
+ lim_log(mac_ctx, LOGE,
+ FL("LFR3: Reassoc response packet header is NULL"));
+ return;
+ } else if (hdr->sa == NULL) {
+ lim_log(mac_ctx, LOGE,
+ FL("LFR3: Reassoc resp packet source address is NULL"));
+ return;
+ }
+
+ lim_log(mac_ctx, LOG1,
+ FL("received Re/Assoc(%d) resp on sessionid: %d systemrole: %d"
+ "and mlmstate: %d RSSI %d from " MAC_ADDRESS_STR), subtype,
+ session_entry->peSessionId, GET_LIM_SYSTEM_ROLE(session_entry),
+ session_entry->limMlmState,
+ (uint) abs((int8_t) WMA_GET_RX_RSSI_DB(rx_pkt_info)),
+ MAC_ADDR_ARRAY(hdr->sa));
+
+ beacon = cdf_mem_malloc(sizeof(tSchBeaconStruct));
+ if (NULL == beacon) {
+ lim_log(mac_ctx, LOGE, FL("Unable to allocate memory"));
+ return;
+ }
+
+ if (LIM_IS_AP_ROLE(session_entry) ||
+ LIM_IS_BT_AMP_AP_ROLE(session_entry)) {
+ /*
+ * Should not have received Re/Association
+ * Response frame on AP. Log error
+ */
+ lim_log(mac_ctx, LOGE,
+ FL("Should not recieved Re/Assoc Response in role %d "),
+ GET_LIM_SYSTEM_ROLE(session_entry));
+ cdf_mem_free(beacon);
+ return;
+ }
+#ifdef WLAN_FEATURE_ROAM_OFFLOAD
+ if (session_entry->bRoamSynchInProgress) {
+ hdr = (tpSirMacMgmtHdr) mac_ctx->roam.pReassocResp;
+ frame_len = mac_ctx->roam.reassocRespLen - SIR_MAC_HDR_LEN_3A;
+ } else {
+#endif
+ hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info);
+ frame_len = WMA_GET_RX_PAYLOAD_LEN(rx_pkt_info);
+#ifdef WLAN_FEATURE_ROAM_OFFLOAD
+}
+#endif
+ if (((subtype == LIM_ASSOC) &&
+ (session_entry->limMlmState != eLIM_MLM_WT_ASSOC_RSP_STATE)) ||
+ ((subtype == LIM_REASSOC) &&
+ ((session_entry->limMlmState != eLIM_MLM_WT_REASSOC_RSP_STATE)
+#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
+ && (session_entry->limMlmState !=
+ eLIM_MLM_WT_FT_REASSOC_RSP_STATE)
+#endif
+ ))) {
+ /* Received unexpected Re/Association Response frame */
+
+#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG
+ lim_log(mac_ctx, LOG1,
+ FL("Recieved Re/Assoc rsp in unexpected "
+ "state %d on session=%d"),
+ session_entry->limMlmState, session_entry->peSessionId);
+#endif
+ if (!hdr->fc.retry) {
+ if (!(mac_ctx->lim.retry_packet_cnt & 0xf)) {
+ lim_log(mac_ctx, LOGE,
+ FL("recvd Re/Assoc rsp:not a retry frame"));
+ lim_print_mlm_state(mac_ctx, LOGE,
+ session_entry->limMlmState);
+ } else {
+ mac_ctx->lim.retry_packet_cnt++;
+ }
+ }
+ cdf_mem_free(beacon);
+ return;
+ }
+ sir_copy_mac_addr(current_bssid, session_entry->bssId);
+ if (subtype == LIM_ASSOC) {
+ if (!cdf_mem_compare
+ (hdr->sa, current_bssid, sizeof(tSirMacAddr))) {
+ /*
+ * Received Association Response frame from an entity
+ * other than one to which request was initiated.
+ * Ignore this and wait until Assoc Failure Timeout
+ */
+ lim_log(mac_ctx, LOGW,
+ FL("received AssocRsp from unexpected peer "
+ MAC_ADDRESS_STR),
+ MAC_ADDR_ARRAY(hdr->sa));
+ cdf_mem_free(beacon);
+ return;
+ }
+ } else {
+ if (!cdf_mem_compare
+ (hdr->sa, session_entry->limReAssocbssId,
+ sizeof(tSirMacAddr))) {
+ /*
+ * Received Reassociation Response frame from an entity
+ * other than one to which request was initiated.
+ * Ignore this and wait until Reassoc Failure Timeout.
+ */
+ lim_log(mac_ctx, LOGW,
+ FL("received ReassocRsp from unexpected peer "
+ MAC_ADDRESS_STR),
+ MAC_ADDR_ARRAY(hdr->sa));
+ cdf_mem_free(beacon);
+ return;
+ }
+ }
+
+ assoc_rsp = cdf_mem_malloc(sizeof(*assoc_rsp));
+ if (NULL == assoc_rsp) {
+ lim_log(mac_ctx, LOGP,
+ FL("Allocate Memory failed in AssocRsp"));
+ cdf_mem_free(beacon);
+ return;
+ }
+ /* Get pointer to Re/Association Response frame body */
+#ifdef WLAN_FEATURE_ROAM_OFFLOAD
+ if (session_entry->bRoamSynchInProgress)
+ body = mac_ctx->roam.pReassocResp + SIR_MAC_HDR_LEN_3A;
+ else
+#endif
+ body = WMA_GET_RX_MPDU_DATA(rx_pkt_info);
+ /* parse Re/Association Response frame. */
+ if (sir_convert_assoc_resp_frame2_struct(mac_ctx, body,
+ frame_len, assoc_rsp) == eSIR_FAILURE) {
+ cdf_mem_free(assoc_rsp);
+ lim_log(mac_ctx, LOGE,
+ FL("Parse error Assoc resp subtype %d," "length=%d"),
+ frame_len, subtype);
+ cdf_mem_free(beacon);
+ return;
+ }
+
+ if (!assoc_rsp->suppRatesPresent) {
+ lim_log(mac_ctx, LOGE,
+ FL("assoc response does not have supported rate set"));
+ cdf_mem_copy(&assoc_rsp->supportedRates,
+ &session_entry->rateSet,
+ sizeof(tSirMacRateSet));
+ }
+
+ assoc_cnf.protStatusCode = assoc_rsp->statusCode;
+ if (session_entry->assocRsp != NULL) {
+ lim_log(mac_ctx, LOGW,
+ FL("session_entry->assocRsp is not NULL freeing it "
+ "and setting NULL"));
+ cdf_mem_free(session_entry->assocRsp);
+ session_entry->assocRsp = NULL;
+ }
+
+ session_entry->assocRsp = cdf_mem_malloc(frame_len);
+ if (NULL == session_entry->assocRsp) {
+ lim_log(mac_ctx, LOGE,
+ FL("Unable to allocate memory for assoc res,len=%d"),
+ frame_len);
+ } else {
+ /*
+ * Store the Assoc response. This is sent
+ * to csr/hdd in join cnf response.
+ */
+ cdf_mem_copy(session_entry->assocRsp, body, frame_len);
+ session_entry->assocRspLen = frame_len;
+ }
+
+#ifdef WLAN_FEATURE_VOWIFI_11R
+ lim_update_ric_data(mac_ctx, session_entry, assoc_rsp);
+#endif
+
+#ifdef WLAN_FEATURE_ROAM_OFFLOAD
+ roam_session =
+ &mac_ctx->roam.roamSession[sme_sessionid];
+ if (assoc_rsp->FTInfo.R0KH_ID.present) {
+ roam_session->ftSmeContext.r0kh_id_len =
+ assoc_rsp->FTInfo.R0KH_ID.num_PMK_R0_ID;
+ cdf_mem_copy(roam_session->ftSmeContext.r0kh_id,
+ assoc_rsp->FTInfo.R0KH_ID.PMK_R0_ID,
+ roam_session->ftSmeContext.r0kh_id_len);
+ } else {
+ roam_session->ftSmeContext.r0kh_id_len = 0;
+ cdf_mem_zero(roam_session->ftSmeContext.r0kh_id,
+ SIR_ROAM_R0KH_ID_MAX_LEN);
+ }
+#endif
+
+#ifdef FEATURE_WLAN_ESE
+ lim_update_ese_tspec(mac_ctx, session_entry, assoc_rsp);
+#endif
+
+ if (assoc_rsp->capabilityInfo.ibss) {
+ /*
+ * Received Re/Association Response from peer
+ * with IBSS capability set.
+ * Ignore the frame and wait until Re/assoc
+ * failure timeout.
+ */
+ lim_log(mac_ctx, LOGE,
+ FL("received Re/AssocRsp frame with IBSS capability"));
+ cdf_mem_free(assoc_rsp);
+ cdf_mem_free(beacon);
+ return;
+ }
+
+ if (cfg_get_capability_info(mac_ctx, &caps, session_entry)
+ != eSIR_SUCCESS) {
+ cdf_mem_free(assoc_rsp);
+ cdf_mem_free(beacon);
+ lim_log(mac_ctx, LOGP, FL("could not retrieve Capabilities "));
+ return;
+ }
+ lim_copy_u16((uint8_t *) &mac_capab, caps);
+
+ /* Stop Association failure timer */
+ if (subtype == LIM_ASSOC)
+ lim_deactivate_and_change_timer(mac_ctx, eLIM_ASSOC_FAIL_TIMER);
+ else
+ {
+ /* Stop Reassociation failure timer */
+#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
+ mac_ctx->lim.reAssocRetryAttempt = 0;
+ if ((NULL != mac_ctx->lim.pSessionEntry)
+ && (NULL !=
+ mac_ctx->lim.pSessionEntry->pLimMlmReassocRetryReq)) {
+ cdf_mem_free(
+ mac_ctx->lim.pSessionEntry->pLimMlmReassocRetryReq);
+ mac_ctx->lim.pSessionEntry->pLimMlmReassocRetryReq =
+ NULL;
+ }
+#endif
+ lim_deactivate_and_change_timer(mac_ctx,
+ eLIM_REASSOC_FAIL_TIMER);
+ }
+
+ if (assoc_rsp->statusCode != eSIR_MAC_SUCCESS_STATUS
+#ifdef WLAN_FEATURE_11W
+ && assoc_rsp->statusCode != eSIR_MAC_TRY_AGAIN_LATER
+#endif
+ ) {
+ /*
+ *Re/Association response was received
+ * either with failure code.
+ */
+ lim_log(mac_ctx, LOGE,
+ FL("received Re/AssocRsp frame failure code %d"),
+ assoc_rsp->statusCode);
+ /*
+ * Need to update 'association failure' error counter
+ * along with STATUS CODE
+ * Return Assoc confirm to SME with received failure code
+ */
+ assoc_cnf.resultCode = eSIR_SME_ASSOC_REFUSED;
+ /* Delete Pre-auth context for the associated BSS */
+ if (lim_search_pre_auth_list(mac_ctx, hdr->sa))
+ lim_delete_pre_auth_node(mac_ctx, hdr->sa);
+ goto assocReject;
+ } else if ((assoc_rsp->aid & 0x3FFF) > 2007) {
+ /*
+ * Re/Association response was received
+ * with invalid AID value
+ */
+ lim_log(mac_ctx, LOGE, FL("received Re/AssocRsp frame with"
+ "invalid aid %X"), assoc_rsp->aid);
+ assoc_cnf.resultCode = eSIR_SME_INVALID_ASSOC_RSP_RXED;
+ assoc_cnf.protStatusCode = eSIR_MAC_UNSPEC_FAILURE_STATUS;
+ /* Send advisory Disassociation frame to AP */
+ lim_send_disassoc_mgmt_frame(mac_ctx,
+ eSIR_MAC_UNSPEC_FAILURE_REASON,
+ hdr->sa, session_entry, false);
+ goto assocReject;
+ }
+ /*
+ * Association Response received with success code
+ * Set the link state to POSTASSOC now that we have received
+ * assoc/reassoc response
+ * NOTE: for BTAMP case, it is being handled in
+ * lim_process_mlm_assoc_req
+ */
+#ifdef WLAN_FEATURE_11W
+ if (assoc_rsp->statusCode == eSIR_MAC_TRY_AGAIN_LATER) {
+ if (assoc_rsp->TimeoutInterval.present &&
+ (assoc_rsp->TimeoutInterval.timeoutType ==
+ SIR_MAC_TI_TYPE_ASSOC_COMEBACK)) {
+ uint16_t timeout_value =
+ assoc_rsp->TimeoutInterval.timeoutValue;
+ if (timeout_value < 10) {
+ /*
+ * if this value is less than 10 then our timer
+ * will fail to start and due to this we will
+ * never re-attempt. Better modify the timer
+ * value here.
+ */
+ timeout_value = 10;
+ }
+ lim_log(mac_ctx, LOG1,
+ FL("ASSOC res with eSIR_MAC_TRY_AGAIN_LATER "
+ " recvd.Starting timer to wait timeout=%d."),
+ timeout_value);
+ if (CDF_STATUS_SUCCESS !=
+ cdf_mc_timer_start(
+ &session_entry->pmfComebackTimer,
+ timeout_value)) {
+ lim_log(mac_ctx, LOGE,
+ FL("Failed to start comeback timer."));
+ }
+ } else {
+ lim_log(mac_ctx, LOGW,
+ FL("ASSOC resp with try again event recvd. "
+ "But try again time interval IE is wrong."));
+ }
+ cdf_mem_free(beacon);
+ cdf_mem_free(assoc_rsp);
+ return;
+ }
+#endif
+ if (!((session_entry->bssType == eSIR_BTAMP_STA_MODE) ||
+ ((session_entry->bssType == eSIR_BTAMP_AP_MODE) &&
+ LIM_IS_BT_AMP_STA_ROLE(session_entry)))) {
+ if (lim_set_link_state
+ (mac_ctx, eSIR_LINK_POSTASSOC_STATE,
+ session_entry->bssId,
+ session_entry->selfMacAddr, NULL,
+ NULL) != eSIR_SUCCESS) {
+ lim_log(mac_ctx, LOGE,
+ FL("Set link state to POSTASSOC failed"));
+ cdf_mem_free(beacon);
+ cdf_mem_free(assoc_rsp);
+ return;
+ }
+ }
+ if (subtype == LIM_REASSOC) {
+ lim_log
+ (mac_ctx, LOG1, FL("Successfully Reassociated with BSS"));
+#ifdef FEATURE_WLAN_DIAG_SUPPORT
+ lim_diag_event_report(mac_ctx, WLAN_PE_DIAG_ROAM_ASSOC_COMP_EVENT,
+ session_entry, eSIR_SUCCESS, eSIR_SUCCESS);
+#endif
+#ifdef FEATURE_WLAN_ESE
+ if (assoc_rsp->tsmPresent)
+ lim_update_ese_tsm(mac_ctx, session_entry, assoc_rsp);
+#endif
+ if (session_entry->pLimMlmJoinReq) {
+ cdf_mem_free(session_entry->pLimMlmJoinReq);
+ session_entry->pLimMlmJoinReq = NULL;
+ }
+
+ session_entry->limAssocResponseData = (void *)assoc_rsp;
+ /*
+ * Store the ReAssocRsp Frame in DphTable
+ * to be used during processing DelSta and
+ * DelBss to send AddBss again
+ */
+ sta_ds =
+ dph_get_hash_entry(mac_ctx, DPH_STA_HASH_INDEX_PEER,
+ &session_entry->dph.dphHashTable);
+
+ if (!sta_ds) {
+ lim_log(mac_ctx, LOGE,
+ FL("could not get hash entry at DPH for"));
+ lim_print_mac_addr(mac_ctx, hdr->sa, LOGE);
+ assoc_cnf.resultCode =
+ eSIR_SME_INVALID_ASSOC_RSP_RXED;
+ assoc_cnf.protStatusCode =
+ eSIR_MAC_UNSPEC_FAILURE_STATUS;
+
+ /* Send advisory Disassociation frame to AP */
+ lim_send_disassoc_mgmt_frame(mac_ctx,
+ eSIR_MAC_UNSPEC_FAILURE_REASON, hdr->sa,
+ session_entry, false);
+ goto assocReject;
+ }
+#if defined(WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
+ if (session_entry->limMlmState ==
+ eLIM_MLM_WT_FT_REASSOC_RSP_STATE) {
+#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG
+ lim_log(mac_ctx, LOG1, FL("Sending self sta"));
+#endif
+ lim_update_assoc_sta_datas(mac_ctx, sta_ds, assoc_rsp,
+ session_entry);
+ /* Store assigned AID for TIM processing */
+ session_entry->limAID = assoc_rsp->aid & 0x3FFF;
+ /* Downgrade the EDCA parameters if needed */
+ lim_set_active_edca_params(mac_ctx,
+ session_entry->gLimEdcaParams,
+ session_entry);
+ /* Send the active EDCA parameters to HAL */
+#ifdef WLAN_FEATURE_ROAM_OFFLOAD
+ if (!session_entry->bRoamSynchInProgress) {
+#endif
+ lim_send_edca_params(mac_ctx,
+ session_entry->gLimEdcaParamsActive,
+ sta_ds->bssId);
+#ifdef WLAN_FEATURE_ROAM_OFFLOAD
+ }
+#endif
+ lim_add_ft_sta_self(mac_ctx, (assoc_rsp->aid & 0x3FFF),
+ session_entry);
+ cdf_mem_free(beacon);
+ return;
+ }
+#endif /* WLAN_FEATURE_VOWIFI_11R */
+
+ /*
+ * If we're re-associating to the same BSS,
+ * we don't want to invoke delete STA, delete
+ * BSS, as that would remove the already
+ * established TSPEC. Just go ahead and re-add
+ * the BSS, STA with new capability information.
+ * However, if we're re-associating to a different
+ * BSS, then follow thru with del STA, del BSS,
+ * add BSS, add STA.
+ */
+ if (sir_compare_mac_addr(session_entry->bssId,
+ session_entry->limReAssocbssId))
+ lim_handle_add_bss_in_re_assoc_context(mac_ctx, sta_ds,
+ session_entry);
+ else {
+ /*
+ * reset the uapsd mask settings since
+ * we're re-associating to new AP
+ */
+ session_entry->gUapsdPerAcDeliveryEnableMask = 0;
+ session_entry->gUapsdPerAcTriggerEnableMask = 0;
+
+ if (lim_cleanup_rx_path(mac_ctx, sta_ds, session_entry)
+ != eSIR_SUCCESS) {
+ lim_log(mac_ctx, LOGE,
+ FL("Could not cleanup the rx path"));
+ goto assocReject;
+ }
+ }
+ cdf_mem_free(beacon);
+ return;
+ }
+ lim_log(mac_ctx, LOG1,
+ FL("Successfully Associated with BSS " MAC_ADDRESS_STR),
+ MAC_ADDR_ARRAY(hdr->sa));
+#ifdef FEATURE_WLAN_ESE
+ if (session_entry->eseContext.tsm.tsmInfo.state)
+ session_entry->eseContext.tsm.tsmMetrics.RoamingCount = 0;
+#endif
+ /* Store assigned AID for TIM processing */
+ session_entry->limAID = assoc_rsp->aid & 0x3FFF;
+
+ /* STA entry was created during pre-assoc state. */
+ sta_ds = dph_get_hash_entry(mac_ctx, DPH_STA_HASH_INDEX_PEER,
+ &session_entry->dph.dphHashTable);
+ if (sta_ds == NULL) {
+ /* Could not add hash table entry */
+ lim_log(mac_ctx, LOGE, FL("could not get hash entry at DPH "));
+ lim_print_mac_addr(mac_ctx, hdr->sa, LOGE);
+ assoc_cnf.resultCode = eSIR_SME_RESOURCES_UNAVAILABLE;
+ assoc_cnf.protStatusCode = eSIR_SME_SUCCESS;
+ lim_post_sme_message(mac_ctx, LIM_MLM_ASSOC_CNF,
+ (uint32_t *) &assoc_cnf);
+ cdf_mem_free(assoc_rsp);
+ cdf_mem_free(beacon);
+ return;
+ }
+ /* Delete Pre-auth context for the associated BSS */
+ if (lim_search_pre_auth_list(mac_ctx, hdr->sa))
+ lim_delete_pre_auth_node(mac_ctx, hdr->sa);
+
+ lim_update_assoc_sta_datas(mac_ctx, sta_ds, assoc_rsp, session_entry);
+ /*
+ * Extract the AP capabilities from the beacon that
+ * was received earlier
+ */
+ ie_len = lim_get_ielen_from_bss_description(
+ &session_entry->pLimJoinReq->bssDescription);
+ lim_extract_ap_capabilities(mac_ctx,
+ (uint8_t *) session_entry->pLimJoinReq->bssDescription.ieFields,
+ ie_len,
+ beacon);
+
+ if (mac_ctx->lim.gLimProtectionControl !=
+ WNI_CFG_FORCE_POLICY_PROTECTION_DISABLE)
+ lim_decide_sta_protection_on_assoc(mac_ctx, beacon,
+ session_entry);
+
+ if (beacon->erpPresent) {
+ if (beacon->erpIEInfo.barkerPreambleMode)
+ session_entry->beaconParams.fShortPreamble = false;
+ else
+ session_entry->beaconParams.fShortPreamble = true;
+ }
+
+#ifdef FEATURE_WLAN_DIAG_SUPPORT
+ lim_diag_event_report(mac_ctx, WLAN_PE_DIAG_CONNECTED, session_entry,
+ eSIR_SUCCESS, eSIR_SUCCESS);
+#endif
+ if (assoc_rsp->QosMapSet.present)
+ cdf_mem_copy(&session_entry->QosMapSet,
+ &assoc_rsp->QosMapSet, sizeof(tSirQosMapSet));
+ else
+ cdf_mem_zero(&session_entry->QosMapSet, sizeof(tSirQosMapSet));
+
+ lim_update_stads_ext_cap(mac_ctx, session_entry, assoc_rsp, sta_ds);
+ /* Update the BSS Entry, this entry was added during preassoc. */
+ if (eSIR_SUCCESS == lim_sta_send_add_bss(mac_ctx, assoc_rsp,
+ beacon,
+ &session_entry->pLimJoinReq->bssDescription, true,
+ session_entry)) {
+ cdf_mem_free(assoc_rsp);
+ cdf_mem_free(beacon);
+ return;
+ } else {
+ lim_log(mac_ctx, LOGE, FL("could not update the bss entry"));
+ assoc_cnf.resultCode = eSIR_SME_RESOURCES_UNAVAILABLE;
+ assoc_cnf.protStatusCode = eSIR_MAC_UNSPEC_FAILURE_STATUS;
+ }
+
+assocReject:
+ if ((subtype == LIM_ASSOC)
+#ifdef WLAN_FEATURE_VOWIFI_11R
+ || ((subtype == LIM_REASSOC)
+ && (session_entry->limMlmState ==
+ eLIM_MLM_WT_FT_REASSOC_RSP_STATE))
+#endif
+ ) {
+ lim_log(mac_ctx, LOGE, FL("Assoc Rejected by the peer. "
+ "mlmestate: %d sessionid %d Reason: %d MACADDR:"
+ MAC_ADDRESS_STR),
+ session_entry->limMlmState,
+ session_entry->peSessionId,
+ assoc_cnf.resultCode, MAC_ADDR_ARRAY(hdr->sa));
+ session_entry->limMlmState = eLIM_MLM_IDLE_STATE;
+ MTRACE(mac_trace(mac_ctx, TRACE_CODE_MLM_STATE,
+ session_entry->peSessionId,
+ session_entry->limMlmState));
+ if (session_entry->pLimMlmJoinReq) {
+ cdf_mem_free(session_entry->pLimMlmJoinReq);
+ session_entry->pLimMlmJoinReq = NULL;
+ }
+ if (subtype == LIM_ASSOC) {
+ lim_post_sme_message(mac_ctx, LIM_MLM_ASSOC_CNF,
+ (uint32_t *) &assoc_cnf);
+ }
+#ifdef WLAN_FEATURE_VOWIFI_11R
+ else {
+ assoc_cnf.resultCode = eSIR_SME_FT_REASSOC_FAILURE;
+ lim_post_sme_message(mac_ctx, LIM_MLM_REASSOC_CNF,
+ (uint32_t *)&assoc_cnf);
+ }
+#endif
+ } else {
+ lim_restore_pre_reassoc_state(mac_ctx,
+ eSIR_SME_REASSOC_REFUSED,
+ assoc_cnf.protStatusCode,
+ session_entry);
+ }
+
+ cdf_mem_free(beacon);
+ cdf_mem_free(assoc_rsp);
+ return;
+}
diff --git a/core/mac/src/pe/lim/lim_process_auth_frame.c b/core/mac/src/pe/lim/lim_process_auth_frame.c
new file mode 100644
index 0000000..9871cff
--- /dev/null
+++ b/core/mac/src/pe/lim/lim_process_auth_frame.c
@@ -0,0 +1,1929 @@
+/*
+ * Copyright (c) 2011-2015 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_process_auth_frame.cc contains the code
+ * for processing received Authentication Frame.
+ * Author: Chandra Modumudi
+ * Date: 03/11/02
+ * History:-
+ * Date Modified by Modification Information
+ * --------------------------------------------------------------------
+ * 05/12/2010 js To support Shared key authentication at AP side
+ *
+ */
+
+#include "wni_api.h"
+#include "wni_cfg.h"
+#include "ani_global.h"
+#include "cfg_api.h"
+
+#include "utils_api.h"
+#include "lim_utils.h"
+#include "lim_assoc_utils.h"
+#include "lim_security_utils.h"
+#include "lim_ser_des_utils.h"
+#ifdef WLAN_FEATURE_VOWIFI_11R
+#include "lim_ft.h"
+#endif
+#include "cds_utils.h"
+
+/**
+ * is_auth_valid
+ *
+ ***FUNCTION:
+ * This function is called by lim_process_auth_frame() upon Authentication
+ * frame reception.
+ *
+ ***LOGIC:
+ * This function is used to test validity of auth frame:
+ * - AUTH1 and AUTH3 must be received in AP mode
+ * - AUTH2 and AUTH4 must be received in STA mode
+ * - AUTH3 and AUTH4 must have challenge text IE, that is,'type' field has been set to
+ * SIR_MAC_CHALLENGE_TEXT_EID by parser
+ * -
+ *
+ ***ASSUMPTIONS:
+ *
+ ***NOTE:
+ *
+ * @param *auth - Pointer to extracted auth frame body
+ *
+ * @return 0 or 1 (Valid)
+ */
+
+static inline unsigned int is_auth_valid(tpAniSirGlobal pMac,
+ tpSirMacAuthFrameBody auth,
+ tpPESession sessionEntry)
+{
+ unsigned int valid = 1;
+
+ if (((auth->authTransactionSeqNumber == SIR_MAC_AUTH_FRAME_1) ||
+ (auth->authTransactionSeqNumber == SIR_MAC_AUTH_FRAME_3)) &&
+ (LIM_IS_STA_ROLE(sessionEntry) ||
+ LIM_IS_BT_AMP_STA_ROLE(sessionEntry)))
+ valid = 0;
+
+ if (((auth->authTransactionSeqNumber == SIR_MAC_AUTH_FRAME_2) ||
+ (auth->authTransactionSeqNumber == SIR_MAC_AUTH_FRAME_4)) &&
+ (LIM_IS_AP_ROLE(sessionEntry) ||
+ LIM_IS_BT_AMP_AP_ROLE(sessionEntry)))
+ valid = 0;
+
+ if (((auth->authTransactionSeqNumber == SIR_MAC_AUTH_FRAME_3) ||
+ (auth->authTransactionSeqNumber == SIR_MAC_AUTH_FRAME_4)) &&
+ (auth->type != SIR_MAC_CHALLENGE_TEXT_EID) &&
+ (auth->authAlgoNumber != eSIR_SHARED_KEY))
+ valid = 0;
+
+ return valid;
+}
+
+/**
+ * lim_process_auth_frame
+ *
+ ***FUNCTION:
+ * This function is called by limProcessMessageQueue() upon Authentication
+ * frame reception.
+ *
+ ***LOGIC:
+ * This function processes received Authentication frame and responds
+ * with either next Authentication frame in sequence to peer MAC entity
+ * or LIM_MLM_AUTH_IND on AP or LIM_MLM_AUTH_CNF on STA.
+ *
+ ***ASSUMPTIONS:
+ *
+ ***NOTE:
+ * 1. Authentication failures are reported to SME with same status code
+ * received from the peer MAC entity.
+ * 2. Authentication frame2/4 received with alogirthm number other than
+ * one requested in frame1/3 are logged with an error and auth confirm
+ * will be sent to SME only after auth failure timeout.
+ * 3. Inconsistency in the spec:
+ * On receiving Auth frame2, specs says that if WEP key mapping key
+ * or default key is NULL, Auth frame3 with a status code 15 (challenge
+ * failure to be returned to peer entity. However, section 7.2.3.10,
+ * table 14 says that status code field is 'reserved' for frame3 !
+ * In the current implementation, Auth frame3 is returned with status
+ * code 15 overriding section 7.2.3.10.
+ * 4. If number pre-authentications reach configrable max limit,
+ * Authentication frame with 'unspecified failure' status code is
+ * returned to requesting entity.
+ *
+ * @param pMac - Pointer to Global MAC structure
+ * @param *pRxPacketInfo - A pointer to Rx packet info structure
+ * @return None
+ */
+
+void
+lim_process_auth_frame(tpAniSirGlobal pMac, uint8_t *pRxPacketInfo,
+ tpPESession psessionEntry)
+{
+ uint8_t *pBody, keyId, cfgPrivacyOptImp,
+ defaultKey[SIR_MAC_KEY_LENGTH],
+ encrAuthFrame[LIM_ENCR_AUTH_BODY_LEN], plainBody[256];
+ uint16_t frameLen;
+ uint32_t maxNumPreAuth, val;
+ tSirMacAuthFrameBody *pRxAuthFrameBody, rxAuthFrame, authFrame;
+ tpSirMacMgmtHdr pHdr;
+ struct tLimPreAuthNode *pAuthNode;
+ uint8_t decryptResult;
+ uint8_t *pChallenge;
+ uint32_t key_length = 8;
+ uint8_t challengeTextArray[SIR_MAC_AUTH_CHALLENGE_LENGTH];
+ tpDphHashNode pStaDs = NULL;
+ uint16_t assocId = 0;
+ uint16_t curr_seq_num = 0;
+
+ /* Get pointer to Authentication frame header and body */
+ pHdr = WMA_GET_RX_MAC_HEADER(pRxPacketInfo);
+ frameLen = WMA_GET_RX_PAYLOAD_LEN(pRxPacketInfo);
+
+ if (!frameLen) {
+ /* Log error */
+ lim_log(pMac, LOGE,
+ FL("received Authentication frame with no body from "));
+ lim_print_mac_addr(pMac, pHdr->sa, LOGE);
+
+ return;
+ }
+
+ if (lim_is_group_addr(pHdr->sa)) {
+ /* Received Auth frame from a BC/MC address */
+ /* Log error and ignore it */
+ lim_log(pMac, LOGE, FL (
+ "received Auth frame from a BC/MC addr - "));
+ PELOGE(lim_print_mac_addr(pMac, pHdr->sa, LOGE);)
+
+ return;
+ }
+ curr_seq_num = (pHdr->seqControl.seqNumHi << 4) |
+ (pHdr->seqControl.seqNumLo);
+
+ lim_log(pMac, LOG1,
+ FL("Sessionid: %d System role : %d limMlmState: %d :Auth "
+ "Frame Received: BSSID: " MAC_ADDRESS_STR " (RSSI %d)"),
+ psessionEntry->peSessionId, GET_LIM_SYSTEM_ROLE(psessionEntry),
+ psessionEntry->limMlmState, MAC_ADDR_ARRAY(pHdr->bssId),
+ (uint) abs((int8_t) WMA_GET_RX_RSSI_DB(pRxPacketInfo)));
+
+ pBody = WMA_GET_RX_MPDU_DATA(pRxPacketInfo);
+
+ /* Restore default failure timeout */
+ if (CDF_P2P_CLIENT_MODE == psessionEntry->pePersona
+ && psessionEntry->defaultAuthFailureTimeout) {
+ lim_log(pMac, LOG1, FL("Restore default failure timeout"));
+ cfg_set_int(pMac, WNI_CFG_AUTHENTICATE_FAILURE_TIMEOUT,
+ psessionEntry->defaultAuthFailureTimeout);
+ }
+ /* / Determine if WEP bit is set in the FC or received MAC header */
+ if (pHdr->fc.wep) {
+ /**
+ * WEP bit is set in FC of MAC header.
+ */
+
+ /* If TKIP counter measures enabled issue Deauth frame to station */
+ if (psessionEntry->bTkipCntrMeasActive &&
+ LIM_IS_AP_ROLE(psessionEntry)) {
+ PELOGE(lim_log
+ (pMac, LOGE,
+ FL
+ ("Tkip counter measures Enabled, sending Deauth frame to"));
+ )
+ lim_print_mac_addr(pMac, pHdr->sa, LOGE);
+
+ lim_send_deauth_mgmt_frame(pMac,
+ eSIR_MAC_MIC_FAILURE_REASON,
+ pHdr->sa, psessionEntry, false);
+ return;
+ }
+ /* Extract key ID from IV (most 2 bits of 4th byte of IV) */
+
+ keyId = (*(pBody + 3)) >> 6;
+
+ /**
+ * On STA in infrastructure BSS, Authentication frames received
+ * with WEP bit set in the FC must be rejected with challenge
+ * failure status code (wierd thing in the spec - this should have
+ * been rejected with unspecified failure or unexpected assertion
+ * of wep bit (this status code does not exist though) or
+ * Out-of-sequence-Authentication-Frame status code.
+ */
+
+ if (LIM_IS_STA_ROLE(psessionEntry) ||
+ LIM_IS_BT_AMP_STA_ROLE(psessionEntry)) {
+ authFrame.authAlgoNumber = eSIR_SHARED_KEY;
+ authFrame.authTransactionSeqNumber =
+ SIR_MAC_AUTH_FRAME_4;
+ authFrame.authStatusCode =
+ eSIR_MAC_CHALLENGE_FAILURE_STATUS;
+ /* Log error */
+ PELOGE(lim_log(pMac, LOGE,
+ FL
+ ("received Authentication frame with wep bit set on role=%d "
+ MAC_ADDRESS_STR),
+ GET_LIM_SYSTEM_ROLE(psessionEntry),
+ MAC_ADDR_ARRAY(pHdr->sa));
+ )
+
+ lim_send_auth_mgmt_frame(pMac, &authFrame,
+ pHdr->sa,
+ LIM_NO_WEP_IN_FC,
+ psessionEntry);
+ return;
+ }
+
+ if (frameLen < LIM_ENCR_AUTH_BODY_LEN) {
+ /* Log error */
+ lim_log(pMac, LOGE,
+ FL
+ ("Not enough size [%d] to decrypt received Auth frame"),
+ frameLen);
+ lim_print_mac_addr(pMac, pHdr->sa, LOGE);
+
+ return;
+ }
+ if (LIM_IS_AP_ROLE(psessionEntry)) {
+ val = psessionEntry->privacy;
+ } else
+ /* Accept Authentication frame only if Privacy is implemented */
+ if (wlan_cfg_get_int(pMac, WNI_CFG_PRIVACY_ENABLED,
+ &val) != eSIR_SUCCESS) {
+ /**
+ * Could not get Privacy option
+ * from CFG. Log error.
+ */
+ lim_log(pMac, LOGP,
+ FL("could not retrieve Privacy option"));
+ }
+
+ cfgPrivacyOptImp = (uint8_t) val;
+ if (cfgPrivacyOptImp) {
+ /**
+ * Privacy option is implemented.
+ * Check if the received frame is Authentication
+ * frame3 and there is a context for requesting STA.
+ * If not, reject with unspecified failure status code
+ */
+ pAuthNode = lim_search_pre_auth_list(pMac, pHdr->sa);
+
+ if (pAuthNode == NULL) {
+ /* Log error */
+ PELOGE(lim_log(pMac, LOGE,
+ FL
+ ("received Authentication frame from peer that has no preauth context with WEP bit set "
+ MAC_ADDRESS_STR),
+ MAC_ADDR_ARRAY(pHdr->sa));
+ )
+
+ /**
+ * No 'pre-auth' context exists for this STA that sent
+ * an Authentication frame with FC bit set.
+ * Send Auth frame4 with 'out of sequence' status code.
+ */
+ authFrame.authAlgoNumber = eSIR_SHARED_KEY;
+ authFrame.authTransactionSeqNumber =
+ SIR_MAC_AUTH_FRAME_4;
+ authFrame.authStatusCode =
+ eSIR_MAC_AUTH_FRAME_OUT_OF_SEQ_STATUS;
+
+ lim_send_auth_mgmt_frame(pMac, &authFrame,
+ pHdr->sa,
+ LIM_NO_WEP_IN_FC,
+ psessionEntry);
+ return;
+ } else {
+ /* / Change the auth-response timeout */
+ lim_deactivate_and_change_per_sta_id_timer(pMac,
+ eLIM_AUTH_RSP_TIMER,
+ pAuthNode->
+ authNodeIdx);
+
+ /* / 'Pre-auth' status exists for STA */
+ if ((pAuthNode->mlmState !=
+ eLIM_MLM_WT_AUTH_FRAME3_STATE) &&
+ (pAuthNode->mlmState !=
+ eLIM_MLM_AUTH_RSP_TIMEOUT_STATE)) {
+ /* Log error */
+ PELOGE(lim_log(pMac, LOGE,
+ FL
+ ("received Authentication frame from peer that is in state %d "
+ MAC_ADDRESS_STR),
+ pAuthNode->mlmState,
+ MAC_ADDR_ARRAY(pHdr->sa));)
+ /**
+ * Should not have received Authentication frame
+ * with WEP bit set in FC in other states.
+ * Reject by sending Authenticaton frame with
+ * out of sequence Auth frame status code.
+ */
+ authFrame.authAlgoNumber =
+ eSIR_SHARED_KEY;
+ authFrame.authTransactionSeqNumber =
+ SIR_MAC_AUTH_FRAME_4;
+ authFrame.authStatusCode =
+ eSIR_MAC_AUTH_FRAME_OUT_OF_SEQ_STATUS;
+
+ lim_send_auth_mgmt_frame(pMac, &authFrame,
+ pHdr->sa,
+ LIM_NO_WEP_IN_FC,
+ psessionEntry);
+ return;
+ }
+ }
+
+ val = SIR_MAC_KEY_LENGTH;
+
+ if (LIM_IS_AP_ROLE(psessionEntry)) {
+ tpSirKeys pKey;
+ pKey =
+ &psessionEntry->
+ WEPKeyMaterial[keyId].key[0];
+ cdf_mem_copy(defaultKey, pKey->key,
+ pKey->keyLength);
+ val = pKey->keyLength;
+ } else if (wlan_cfg_get_str(pMac,
+ (uint16_t) (WNI_CFG_WEP_DEFAULT_KEY_1 +
+ keyId), defaultKey,
+ &val) != eSIR_SUCCESS) {
+ /* / Could not get Default key from CFG. */
+ /* Log error. */
+ lim_log(pMac, LOGP,
+ FL
+ ("could not retrieve Default key"));
+
+ /**
+ * Send Authentication frame
+ * with challenge failure status code
+ */
+
+ authFrame.authAlgoNumber =
+ eSIR_SHARED_KEY;
+ authFrame.authTransactionSeqNumber =
+ SIR_MAC_AUTH_FRAME_4;
+ authFrame.authStatusCode =
+ eSIR_MAC_CHALLENGE_FAILURE_STATUS;
+
+ lim_send_auth_mgmt_frame(pMac, &authFrame,
+ pHdr->sa,
+ LIM_NO_WEP_IN_FC,
+ psessionEntry);
+
+ return;
+ }
+
+ key_length = val;
+
+ decryptResult = lim_decrypt_auth_frame(pMac, defaultKey,
+ pBody, plainBody, key_length,
+ (uint16_t) (frameLen -
+ SIR_MAC_WEP_IV_LENGTH));
+ if (decryptResult == LIM_DECRYPT_ICV_FAIL) {
+ /* Log error */
+ PELOGE(lim_log(pMac, LOGE,
+ FL
+ ("received Authentication frame from peer that failed decryption: "
+ MAC_ADDRESS_STR),
+ MAC_ADDR_ARRAY(pHdr->sa));
+ )
+ /* / ICV failure */
+ lim_delete_pre_auth_node(pMac,
+ pHdr->sa);
+ authFrame.authAlgoNumber =
+ eSIR_SHARED_KEY;
+ authFrame.authTransactionSeqNumber =
+ SIR_MAC_AUTH_FRAME_4;
+ authFrame.authStatusCode =
+ eSIR_MAC_CHALLENGE_FAILURE_STATUS;
+
+ lim_send_auth_mgmt_frame(pMac, &authFrame,
+ pHdr->sa,
+ LIM_NO_WEP_IN_FC,
+ psessionEntry);
+ return;
+ }
+ if ((sir_convert_auth_frame2_struct
+ (pMac, plainBody, frameLen - 8,
+ &rxAuthFrame) != eSIR_SUCCESS) ||
+ (!is_auth_valid
+ (pMac, &rxAuthFrame, psessionEntry))) {
+ lim_log(pMac, LOGE,
+ FL
+ ("failed to convert Auth Frame to structure or Auth is not valid "));
+ return;
+ }
+ } else {
+ /* Log error */
+ PELOGE(lim_log(pMac, LOGE,
+ FL
+ ("received Authentication frame3 from peer that while privacy option is turned OFF "
+ MAC_ADDRESS_STR),
+ MAC_ADDR_ARRAY(pHdr->sa));
+ )
+ /**
+ * Privacy option is not implemented.
+ * So reject Authentication frame received with
+ * WEP bit set by sending Authentication frame
+ * with 'challenge failure' status code. This is
+ * another strange thing in the spec. Status code
+ * should have been 'unsupported algorithm' status code.
+ */
+ authFrame.authAlgoNumber = eSIR_SHARED_KEY;
+ authFrame.authTransactionSeqNumber =
+ SIR_MAC_AUTH_FRAME_4;
+ authFrame.authStatusCode =
+ eSIR_MAC_CHALLENGE_FAILURE_STATUS;
+
+ lim_send_auth_mgmt_frame(pMac, &authFrame,
+ pHdr->sa,
+ LIM_NO_WEP_IN_FC, psessionEntry);
+ return;
+ } /* else if (wlan_cfg_get_int(CFG_PRIVACY_OPTION_IMPLEMENTED)) */
+ } /* if (fc.wep) */
+ else {
+ if ((sir_convert_auth_frame2_struct(pMac, pBody,
+ frameLen,
+ &rxAuthFrame) != eSIR_SUCCESS)
+ || (!is_auth_valid(pMac, &rxAuthFrame, psessionEntry))) {
+ PELOGE(lim_log
+ (pMac, LOGE,
+ FL
+ ("failed to convert Auth Frame to structure or Auth is not valid "));
+ )
+ return;
+ }
+ }
+
+ pRxAuthFrameBody = &rxAuthFrame;
+
+ PELOGW(lim_log(pMac, LOGW,
+ FL
+ ("Received Auth frame with type=%d seqnum=%d, status=%d (%d)"),
+ (uint32_t) pRxAuthFrameBody->authAlgoNumber,
+ (uint32_t) pRxAuthFrameBody->authTransactionSeqNumber,
+ (uint32_t) pRxAuthFrameBody->authStatusCode,
+ (uint32_t) pMac->lim.gLimNumPreAuthContexts);
+ )
+
+ switch (pRxAuthFrameBody->authTransactionSeqNumber) {
+ case SIR_MAC_AUTH_FRAME_1:
+ /* AuthFrame 1 */
+
+ pStaDs = dph_lookup_hash_entry(pMac, pHdr->sa,
+ &assocId,
+ &psessionEntry->dph.dphHashTable);
+ if (pStaDs) {
+ tLimMlmDisassocReq *pMlmDisassocReq = NULL;
+ tLimMlmDeauthReq *pMlmDeauthReq = NULL;
+ tAniBool isConnected = eSIR_TRUE;
+
+ pMlmDisassocReq =
+ pMac->lim.limDisassocDeauthCnfReq.pMlmDisassocReq;
+ if (pMlmDisassocReq
+ &&
+ (cdf_mem_compare
+ ((uint8_t *) pHdr->sa,
+ (uint8_t *) &pMlmDisassocReq->peerMacAddr,
+ sizeof(tSirMacAddr)))) {
+ PELOGE(lim_log
+ (pMac, LOGE,
+ FL("TODO:Ack for disassoc "
+ "frame is pending Issue delsta for "
+ MAC_ADDRESS_STR),
+ MAC_ADDR_ARRAY(pMlmDisassocReq->
+ peerMacAddr));
+ )
+ lim_process_disassoc_ack_timeout(pMac);
+ isConnected = eSIR_FALSE;
+ }
+ pMlmDeauthReq =
+ pMac->lim.limDisassocDeauthCnfReq.pMlmDeauthReq;
+ if (pMlmDeauthReq
+ &&
+ (cdf_mem_compare
+ ((uint8_t *) pHdr->sa,
+ (uint8_t *) &pMlmDeauthReq->peerMacAddr,
+ sizeof(tSirMacAddr)))) {
+ PELOGE(lim_log
+ (pMac, LOGE,
+ FL("TODO:Ack for deauth frame "
+ "is pending Issue delsta for "
+ MAC_ADDRESS_STR),
+ MAC_ADDR_ARRAY(pMlmDeauthReq->
+ peerMacAddr));
+ )
+ lim_process_deauth_ack_timeout(pMac);
+ isConnected = eSIR_FALSE;
+ }
+
+ /* pStaDS != NULL and isConnected = 1 means the STA is already
+ * connected, But SAP received the Auth from that station.
+ * For non PMF connection send Deauth frame as STA will retry
+ * to connect back.
+ *
+ * For PMF connection the AP should not tear down or otherwise
+ * modify the state of the existing association until the
+ * SA-Query procedure determines that the original SA is
+ * invalid.
+ */
+ if (isConnected
+#ifdef WLAN_FEATURE_11W
+ && !pStaDs->rmfEnabled
+#endif
+ ) {
+ lim_log(pMac, LOGE,
+ FL
+ ("STA is already connected but received auth frame"
+ "Send the Deauth and lim Delete Station Context"
+ "(staId: %d, assocId: %d) "),
+ pStaDs->staIndex, assocId);
+ lim_send_deauth_mgmt_frame(pMac,
+ eSIR_MAC_UNSPEC_FAILURE_REASON,
+ (uint8_t *) pHdr->sa,
+ psessionEntry, false);
+ lim_trigger_sta_deletion(pMac, pStaDs,
+ psessionEntry);
+ return;
+ }
+ }
+ /* / Check if there exists pre-auth context for this STA */
+ pAuthNode = lim_search_pre_auth_list(pMac, pHdr->sa);
+ if (pAuthNode) {
+ /* / Pre-auth context exists for the STA */
+ if (pHdr->fc.retry == 0 ||
+ pAuthNode->seq_num != curr_seq_num) {
+ /**
+ * STA is initiating brand-new Authentication
+ * sequence after local Auth Response timeout.
+ * Or STA retrying to transmit First Auth frame due to packet drop OTA
+ * Delete Pre-auth node and fall through.
+ */
+ if (pAuthNode->fTimerStarted) {
+ lim_deactivate_and_change_per_sta_id_timer
+ (pMac, eLIM_AUTH_RSP_TIMER,
+ pAuthNode->authNodeIdx);
+ }
+ PELOGE(lim_log
+ (pMac, LOGE,
+ FL
+ ("STA is initiating brand-new Authentication ..."));
+ )
+ lim_delete_pre_auth_node(pMac, pHdr->sa);
+ /**
+ * SAP Mode:Disassociate the station and
+ * delete its entry if we have its entry
+ * already and received "auth" from the
+ * same station.
+ */
+
+ for (assocId = 0; assocId < psessionEntry->dph.dphHashTable.size; assocId++) /* Softap dphHashTable.size = 8 */
+ {
+ pStaDs =
+ dph_get_hash_entry(pMac, assocId,
+ &psessionEntry->dph.
+ dphHashTable);
+
+ if (NULL == pStaDs)
+ continue;
+
+ if (pStaDs->valid) {
+ if (cdf_mem_compare
+ ((uint8_t *) &pStaDs->
+ staAddr,
+ (uint8_t *) &(pHdr->sa),
+ (uint8_t) (sizeof
+ (tSirMacAddr))))
+ break;
+ }
+
+ pStaDs = NULL;
+ }
+
+ if (NULL != pStaDs
+#ifdef WLAN_FEATURE_11W
+ && !pStaDs->rmfEnabled
+#endif
+ ) {
+ PELOGE(lim_log(pMac, LOGE,
+ FL
+ ("lim Delete Station Context (staId: %d, assocId: %d) "),
+ pStaDs->staIndex,
+ assocId);
+ )
+ lim_send_deauth_mgmt_frame(pMac,
+ eSIR_MAC_UNSPEC_FAILURE_REASON,
+ (uint8_t *)
+ pAuthNode->
+ peerMacAddr,
+ psessionEntry,
+ false);
+ lim_trigger_sta_deletion(pMac, pStaDs,
+ psessionEntry);
+ return;
+ }
+ } else {
+ /*
+ * This can happen when first authentication frame is received
+ * but ACK lost at STA side, in this case 2nd auth frame is already
+ * in transmission queue
+ * */
+ PELOGE(lim_log
+ (pMac, LOGE,
+ FL
+ ("STA is initiating Authentication after ACK lost..."));
+ )
+ return;
+ }
+ }
+ if (wlan_cfg_get_int(pMac, WNI_CFG_MAX_NUM_PRE_AUTH,
+ (uint32_t *) &maxNumPreAuth) !=
+ eSIR_SUCCESS) {
+ /**
+ * Could not get MaxNumPreAuth
+ * from CFG. Log error.
+ */
+ lim_log(pMac, LOGP,
+ FL("could not retrieve MaxNumPreAuth"));
+ }
+ if (pMac->lim.gLimNumPreAuthContexts == maxNumPreAuth &&
+ !lim_delete_open_auth_pre_auth_node(pMac)) {
+ PELOGE(lim_log
+ (pMac, LOGE,
+ FL("Max number of preauth context reached"));
+ )
+ /**
+ * Maximum number of pre-auth contexts
+ * reached. Send Authentication frame
+ * with unspecified failure
+ */
+ authFrame.authAlgoNumber =
+ pRxAuthFrameBody->authAlgoNumber;
+ authFrame.authTransactionSeqNumber =
+ pRxAuthFrameBody->authTransactionSeqNumber + 1;
+ authFrame.authStatusCode =
+ eSIR_MAC_UNSPEC_FAILURE_STATUS;
+
+ lim_send_auth_mgmt_frame(pMac, &authFrame,
+ pHdr->sa,
+ LIM_NO_WEP_IN_FC, psessionEntry);
+
+ return;
+ }
+ /* / No Pre-auth context exists for the STA. */
+ if (lim_is_auth_algo_supported(pMac, (tAniAuthType)
+ pRxAuthFrameBody->authAlgoNumber,
+ psessionEntry)) {
+ switch (pRxAuthFrameBody->authAlgoNumber) {
+ case eSIR_OPEN_SYSTEM:
+ PELOGW(lim_log
+ (pMac, LOGW,
+ FL("=======> eSIR_OPEN_SYSTEM ..."));
+ )
+ /* / Create entry for this STA in pre-auth list */
+ pAuthNode =
+ lim_acquire_free_pre_auth_node(pMac,
+ &pMac->lim.
+ gLimPreAuthTimerTable);
+ if (pAuthNode == NULL) {
+ /* Log error */
+ lim_log(pMac, LOGW,
+ FL
+ ("Max pre-auth nodes reached "));
+ lim_print_mac_addr(pMac, pHdr->sa, LOGW);
+
+ return;
+ }
+
+ PELOG1(lim_log
+ (pMac, LOG1,
+ FL("Alloc new data: %x peer "),
+ pAuthNode);
+ lim_print_mac_addr(pMac, pHdr->sa, LOG1);
+ )
+
+ cdf_mem_copy((uint8_t *) pAuthNode->
+ peerMacAddr, pHdr->sa,
+ sizeof(tSirMacAddr));
+
+ pAuthNode->mlmState =
+ eLIM_MLM_AUTHENTICATED_STATE;
+ pAuthNode->authType = (tAniAuthType)
+ pRxAuthFrameBody->authAlgoNumber;
+ pAuthNode->fSeen = 0;
+ pAuthNode->fTimerStarted = 0;
+ pAuthNode->seq_num =
+ ((pHdr->seqControl.seqNumHi << 4) |
+ (pHdr->seqControl.seqNumLo));
+ pAuthNode->timestamp =
+ cdf_mc_timer_get_system_ticks();
+ lim_add_pre_auth_node(pMac, pAuthNode);
+
+ /**
+ * Send Authenticaton frame with Success
+ * status code.
+ */
+
+ authFrame.authAlgoNumber =
+ pRxAuthFrameBody->authAlgoNumber;
+ authFrame.authTransactionSeqNumber =
+ pRxAuthFrameBody->authTransactionSeqNumber +
+ 1;
+ authFrame.authStatusCode =
+ eSIR_MAC_SUCCESS_STATUS;
+ lim_send_auth_mgmt_frame(pMac, &authFrame, pHdr->sa,
+ LIM_NO_WEP_IN_FC,
+ psessionEntry);
+ break;
+
+ case eSIR_SHARED_KEY:
+ PELOGW(lim_log
+ (pMac, LOGW,
+ FL("=======> eSIR_SHARED_KEY ..."));
+ )
+ if (LIM_IS_AP_ROLE(psessionEntry)) {
+ val = psessionEntry->privacy;
+ } else
+ if (wlan_cfg_get_int
+ (pMac, WNI_CFG_PRIVACY_ENABLED,
+ &val) != eSIR_SUCCESS) {
+ /**
+ * Could not get Privacy option
+ * from CFG. Log error.
+ */
+ lim_log(pMac, LOGP,
+ FL
+ ("could not retrieve Privacy option"));
+ }
+ cfgPrivacyOptImp = (uint8_t) val;
+ if (!cfgPrivacyOptImp) {
+ /* Log error */
+ PELOGE(lim_log(pMac, LOGE,
+ FL
+ ("received Auth frame for unsupported auth algorithm %d "
+ MAC_ADDRESS_STR),
+ pRxAuthFrameBody->
+ authAlgoNumber,
+ MAC_ADDR_ARRAY(pHdr->sa));
+ )
+
+ /**
+ * Authenticator does not have WEP
+ * implemented.
+ * Reject by sending Authentication frame
+ * with Auth algorithm not supported status
+ * code.
+ */
+ authFrame.authAlgoNumber =
+ pRxAuthFrameBody->authAlgoNumber;
+ authFrame.authTransactionSeqNumber =
+ pRxAuthFrameBody->
+ authTransactionSeqNumber + 1;
+ authFrame.authStatusCode =
+ eSIR_MAC_AUTH_ALGO_NOT_SUPPORTED_STATUS;
+
+ lim_send_auth_mgmt_frame(pMac, &authFrame,
+ pHdr->sa,
+ LIM_NO_WEP_IN_FC,
+ psessionEntry);
+ return;
+ } else {
+ /* Create entry for this STA */
+ /* in pre-auth list */
+ pAuthNode =
+ lim_acquire_free_pre_auth_node(pMac,
+ &pMac->
+ lim.
+ gLimPreAuthTimerTable);
+ if (pAuthNode == NULL) {
+ /* Log error */
+ lim_log(pMac, LOGW,
+ FL
+ ("Max pre-auth nodes reached "));
+ lim_print_mac_addr(pMac, pHdr->sa,
+ LOGW);
+
+ return;
+ }
+
+ cdf_mem_copy((uint8_t *) pAuthNode->
+ peerMacAddr, pHdr->sa,
+ sizeof(tSirMacAddr));
+
+ pAuthNode->mlmState =
+ eLIM_MLM_WT_AUTH_FRAME3_STATE;
+ pAuthNode->authType = (tAniAuthType)
+ pRxAuthFrameBody->authAlgoNumber;
+ pAuthNode->fSeen = 0;
+ pAuthNode->fTimerStarted = 0;
+ pAuthNode->seq_num =
+ ((pHdr->seqControl.seqNumHi <<
+ 4) |
+ (pHdr->seqControl.seqNumLo));
+ pAuthNode->timestamp =
+ cdf_mc_timer_get_system_ticks();
+ lim_add_pre_auth_node(pMac, pAuthNode);
+
+ PELOG1(lim_log
+ (pMac, LOG1,
+ FL
+ ("Alloc new data: %x id %d peer "),
+ pAuthNode,
+ pAuthNode->authNodeIdx);
+ )
+ PELOG1(lim_print_mac_addr
+ (pMac, pHdr->sa, LOG1);
+ )
+ /* / Create and activate Auth Response timer */
+ if (tx_timer_change_context
+ (&pAuthNode->timer,
+ pAuthNode->authNodeIdx) !=
+ TX_SUCCESS) {
+ /* / Could not start Auth response timer. */
+ /* Log error */
+ lim_log(pMac, LOGP,
+ FL
+ ("Unable to chg context auth response timer for peer "));
+ lim_print_mac_addr(pMac, pHdr->sa,
+ LOGP);
+
+ /**
+ * Send Authenticaton frame with
+ * unspecified failure status code.
+ */
+
+ authFrame.authAlgoNumber =
+ pRxAuthFrameBody->
+ authAlgoNumber;
+ authFrame.
+ authTransactionSeqNumber =
+ pRxAuthFrameBody->
+ authTransactionSeqNumber +
+ 1;
+ authFrame.authStatusCode =
+ eSIR_MAC_UNSPEC_FAILURE_STATUS;
+
+ lim_send_auth_mgmt_frame(pMac,
+ &authFrame,
+ pHdr->sa,
+ LIM_NO_WEP_IN_FC,
+ psessionEntry);
+
+ lim_delete_pre_auth_node(pMac,
+ pHdr->sa);
+ return;
+ }
+
+ lim_activate_auth_rsp_timer(pMac,
+ pAuthNode);
+
+ pAuthNode->fTimerStarted = 1;
+
+ /* get random bytes and use as */
+ /* challenge text. If it fails we already have random stack bytes. */
+ if (!CDF_IS_STATUS_SUCCESS
+ (cds_rand_get_bytes
+ (0, (uint8_t *) challengeTextArray,
+ SIR_MAC_AUTH_CHALLENGE_LENGTH))) {
+ lim_log(pMac, LOGE,
+ FL
+ ("Challenge text preparation failed in lim_process_auth_frame"));
+ }
+
+ pChallenge = pAuthNode->challengeText;
+
+ cdf_mem_copy(pChallenge,
+ (uint8_t *)
+ challengeTextArray,
+ sizeof
+ (challengeTextArray));
+
+ /**
+ * Sending Authenticaton frame with challenge.
+ */
+
+ authFrame.authAlgoNumber =
+ pRxAuthFrameBody->authAlgoNumber;
+ authFrame.authTransactionSeqNumber =
+ pRxAuthFrameBody->
+ authTransactionSeqNumber + 1;
+ authFrame.authStatusCode =
+ eSIR_MAC_SUCCESS_STATUS;
+ authFrame.type =
+ SIR_MAC_CHALLENGE_TEXT_EID;
+ authFrame.length =
+ SIR_MAC_AUTH_CHALLENGE_LENGTH;
+ cdf_mem_copy(authFrame.challengeText,
+ pAuthNode->challengeText,
+ SIR_MAC_AUTH_CHALLENGE_LENGTH);
+
+ lim_send_auth_mgmt_frame(pMac, &authFrame,
+ pHdr->sa,
+ LIM_NO_WEP_IN_FC,
+ psessionEntry);
+ } /* if (wlan_cfg_get_int(CFG_PRIVACY_OPTION_IMPLEMENTED)) */
+
+ break;
+
+ default:
+ /* Log error */
+ PELOGE(lim_log(pMac, LOGE,
+ FL
+ ("received Auth frame for unsupported auth algorithm %d "
+ MAC_ADDRESS_STR),
+ pRxAuthFrameBody->authAlgoNumber,
+ MAC_ADDR_ARRAY(pHdr->sa));
+ )
+
+ /**
+ * Responding party does not support the
+ * authentication algorithm requested by
+ * sending party.
+ * Reject by sending Authentication frame
+ * with auth algorithm not supported status code
+ */
+ authFrame.authAlgoNumber =
+ pRxAuthFrameBody->authAlgoNumber;
+ authFrame.authTransactionSeqNumber =
+ pRxAuthFrameBody->authTransactionSeqNumber +
+ 1;
+ authFrame.authStatusCode =
+ eSIR_MAC_AUTH_ALGO_NOT_SUPPORTED_STATUS;
+
+ lim_send_auth_mgmt_frame(pMac, &authFrame,
+ pHdr->sa,
+ LIM_NO_WEP_IN_FC,
+ psessionEntry);
+ return;
+ } /* end switch(pRxAuthFrameBody->authAlgoNumber) */
+ } /* if (lim_is_auth_algo_supported(pRxAuthFrameBody->authAlgoNumber)) */
+ else {
+ /* Log error */
+ PELOGE(lim_log(pMac, LOGE,
+ FL
+ ("received Authentication frame for unsupported auth algorithm %d "
+ MAC_ADDRESS_STR),
+ pRxAuthFrameBody->authAlgoNumber,
+ MAC_ADDR_ARRAY(pHdr->sa));
+ )
+
+ /**
+ * Responding party does not support the
+ * authentication algorithm requested by sending party.
+ * Reject Authentication with StatusCode=13.
+ */
+ authFrame.authAlgoNumber =
+ pRxAuthFrameBody->authAlgoNumber;
+ authFrame.authTransactionSeqNumber =
+ pRxAuthFrameBody->authTransactionSeqNumber + 1;
+ authFrame.authStatusCode =
+ eSIR_MAC_AUTH_ALGO_NOT_SUPPORTED_STATUS;
+
+ lim_send_auth_mgmt_frame(pMac, &authFrame,
+ pHdr->sa,
+ LIM_NO_WEP_IN_FC, psessionEntry);
+ return;
+ } /* end if (lim_is_auth_algo_supported(pRxAuthFrameBody->authAlgoNumber)) */
+ break;
+
+ case SIR_MAC_AUTH_FRAME_2:
+ /* AuthFrame 2 */
+
+ if (psessionEntry->limMlmState != eLIM_MLM_WT_AUTH_FRAME2_STATE) {
+#ifdef WLAN_FEATURE_VOWIFI_11R
+ /**
+ * Check if a Reassociation is in progress and this is a
+ * Pre-Auth frame
+ */
+ if ((LIM_IS_STA_ROLE(psessionEntry) ||
+ LIM_IS_BT_AMP_STA_ROLE(psessionEntry))
+ && (psessionEntry->limSmeState ==
+ eLIM_SME_WT_REASSOC_STATE)
+ && (pRxAuthFrameBody->authStatusCode ==
+ eSIR_MAC_SUCCESS_STATUS)
+ && (psessionEntry->ftPEContext.pFTPreAuthReq !=
+ NULL)
+ &&
+ (cdf_mem_compare
+ (psessionEntry->ftPEContext.pFTPreAuthReq->
+ preAuthbssId, pHdr->sa, sizeof(tSirMacAddr)))) {
+ /* Update the FTIEs in the saved auth response */
+ PELOGW(lim_log
+ (pMac, LOGW,
+ FL("received another PreAuth frame2"
+ " from peer " MAC_ADDRESS_STR
+ " in Smestate %d"),
+ MAC_ADDR_ARRAY(pHdr->sa),
+ psessionEntry->limSmeState);
+ )
+
+ psessionEntry->ftPEContext.
+ saved_auth_rsp_length = 0;
+ if ((pBody != NULL)
+ && (frameLen < MAX_FTIE_SIZE)) {
+ cdf_mem_copy(psessionEntry->ftPEContext.
+ saved_auth_rsp, pBody,
+ frameLen);
+ psessionEntry->ftPEContext.
+ saved_auth_rsp_length = frameLen;
+ }
+ } else
+#endif
+ {
+ /**
+ * Received Authentication frame2 in an unexpected state.
+ * Log error and ignore the frame.
+ */
+
+ /* Log error */
+ PELOG1(lim_log(pMac, LOG1,
+ FL
+ ("received Auth frame2 from peer in state %d, addr "),
+ psessionEntry->limMlmState);
+ )
+ PELOG1(lim_print_mac_addr
+ (pMac, pHdr->sa, LOG1);
+ )
+ }
+
+ return;
+
+ }
+
+ if (!cdf_mem_compare((uint8_t *) pHdr->sa,
+ (uint8_t *) &pMac->lim.gpLimMlmAuthReq->
+ peerMacAddr, sizeof(tSirMacAddr))) {
+ /**
+ * Received Authentication frame from an entity
+ * other than one request was initiated.
+ * Wait until Authentication Failure Timeout.
+ */
+
+ /* Log error */
+ PELOGW(lim_log(pMac, LOGW,
+ FL
+ ("received Auth frame2 from unexpected peer "
+ MAC_ADDRESS_STR),
+ MAC_ADDR_ARRAY(pHdr->sa));
+ )
+
+ break;
+ }
+
+ if (pRxAuthFrameBody->authStatusCode ==
+ eSIR_MAC_AUTH_ALGO_NOT_SUPPORTED_STATUS) {
+ /**
+ * Interoperability workaround: Linksys WAP4400N is returning
+ * wrong authType in OpenAuth response in case of
+ * SharedKey AP configuration. Pretend we don't see that,
+ * so upper layer can fallback to SharedKey authType,
+ * and successfully connect to the AP.
+ */
+ if (pRxAuthFrameBody->authAlgoNumber !=
+ pMac->lim.gpLimMlmAuthReq->authType) {
+ pRxAuthFrameBody->authAlgoNumber =
+ pMac->lim.gpLimMlmAuthReq->authType;
+ }
+ }
+
+ if (pRxAuthFrameBody->authAlgoNumber !=
+ pMac->lim.gpLimMlmAuthReq->authType) {
+ /**
+ * Received Authentication frame with an auth
+ * algorithm other than one requested.
+ * Wait until Authentication Failure Timeout.
+ */
+
+ /* Log error */
+ PELOGW(lim_log(pMac, LOGW,
+ FL
+ ("received Auth frame2 for unexpected auth algo number %d "
+ MAC_ADDRESS_STR),
+ pRxAuthFrameBody->authAlgoNumber,
+ MAC_ADDR_ARRAY(pHdr->sa));
+ )
+
+ break;
+ }
+
+ if (pRxAuthFrameBody->authStatusCode == eSIR_MAC_SUCCESS_STATUS) {
+ if (pRxAuthFrameBody->authAlgoNumber ==
+ eSIR_OPEN_SYSTEM) {
+ psessionEntry->limCurrentAuthType =
+ eSIR_OPEN_SYSTEM;
+
+ pAuthNode =
+ lim_acquire_free_pre_auth_node(pMac,
+ &pMac->lim.
+ gLimPreAuthTimerTable);
+
+ if (pAuthNode == NULL) {
+ /* Log error */
+ lim_log(pMac, LOGW,
+ FL
+ ("Max pre-auth nodes reached "));
+ lim_print_mac_addr(pMac, pHdr->sa, LOGW);
+
+ return;
+ }
+
+ PELOG1(lim_log
+ (pMac, LOG1,
+ FL("Alloc new data: %x peer "),
+ pAuthNode);
+ )
+ PELOG1(lim_print_mac_addr
+ (pMac, pHdr->sa, LOG1);
+ )
+
+ cdf_mem_copy((uint8_t *) pAuthNode->
+ peerMacAddr,
+ pMac->lim.gpLimMlmAuthReq->
+ peerMacAddr,
+ sizeof(tSirMacAddr));
+ pAuthNode->fTimerStarted = 0;
+ pAuthNode->authType =
+ pMac->lim.gpLimMlmAuthReq->authType;
+ pAuthNode->seq_num =
+ ((pHdr->seqControl.seqNumHi << 4) |
+ (pHdr->seqControl.seqNumLo));
+ pAuthNode->timestamp =
+ cdf_mc_timer_get_system_ticks();
+ lim_add_pre_auth_node(pMac, pAuthNode);
+
+ lim_restore_from_auth_state(pMac, eSIR_SME_SUCCESS,
+ pRxAuthFrameBody->
+ authStatusCode,
+ psessionEntry);
+ } /* if (pRxAuthFrameBody->authAlgoNumber == eSIR_OPEN_SYSTEM) */
+ else {
+ /* Shared key authentication */
+
+ if (LIM_IS_AP_ROLE(psessionEntry)) {
+ val = psessionEntry->privacy;
+ } else
+ if (wlan_cfg_get_int
+ (pMac, WNI_CFG_PRIVACY_ENABLED,
+ &val) != eSIR_SUCCESS) {
+ /**
+ * Could not get Privacy option
+ * from CFG. Log error.
+ */
+ lim_log(pMac, LOGP,
+ FL
+ ("could not retrieve Privacy option"));
+ }
+ cfgPrivacyOptImp = (uint8_t) val;
+ if (!cfgPrivacyOptImp) {
+ /**
+ * Requesting STA does not have WEP implemented.
+ * Reject with unsupported authentication algorithm
+ * Status code and wait until auth failure timeout
+ */
+
+ /* Log error */
+ PELOGE(lim_log(pMac, LOGE,
+ FL
+ ("received Auth frame from peer for unsupported auth algo %d "
+ MAC_ADDRESS_STR),
+ pRxAuthFrameBody->
+ authAlgoNumber,
+ MAC_ADDR_ARRAY(pHdr->sa));
+ )
+
+ authFrame.authAlgoNumber =
+ pRxAuthFrameBody->authAlgoNumber;
+ authFrame.authTransactionSeqNumber =
+ pRxAuthFrameBody->
+ authTransactionSeqNumber + 1;
+ authFrame.authStatusCode =
+ eSIR_MAC_AUTH_ALGO_NOT_SUPPORTED_STATUS;
+
+ lim_send_auth_mgmt_frame(pMac, &authFrame,
+ pHdr->sa,
+ LIM_NO_WEP_IN_FC,
+ psessionEntry);
+ return;
+ } else {
+
+ if (pRxAuthFrameBody->type !=
+ SIR_MAC_CHALLENGE_TEXT_EID) {
+ /* Log error */
+ PELOGE(lim_log(pMac, LOGE,
+ FL
+ ("received Auth frame with invalid challenge text IE"));
+ )
+
+ return;
+ }
+
+ if (wlan_cfg_get_int
+ (pMac,
+ WNI_CFG_WEP_DEFAULT_KEYID,
+ &val) != eSIR_SUCCESS) {
+ /**
+ * Could not get Default keyId
+ * from CFG. Log error.
+ */
+ lim_log(pMac, LOGP,
+ FL
+ ("could not retrieve Default keyId"));
+ }
+ keyId = (uint8_t) val;
+
+ val = SIR_MAC_KEY_LENGTH;
+
+ if (LIM_IS_AP_ROLE(psessionEntry)) {
+ tpSirKeys pKey;
+ pKey =
+ &psessionEntry->
+ WEPKeyMaterial
+ [keyId].key[0];
+ cdf_mem_copy(defaultKey,
+ pKey->key,
+ pKey->
+ keyLength);
+ } else
+ if (wlan_cfg_get_str
+ (pMac,
+ (uint16_t)
+ (WNI_CFG_WEP_DEFAULT_KEY_1
+ + keyId), defaultKey,
+ &val)
+ != eSIR_SUCCESS) {
+ /* / Could not get Default key from CFG. */
+ /* Log error. */
+ lim_log(pMac, LOGP,
+ FL
+ ("could not retrieve Default key"));
+
+ authFrame.authAlgoNumber =
+ pRxAuthFrameBody->
+ authAlgoNumber;
+ authFrame.
+ authTransactionSeqNumber =
+ pRxAuthFrameBody->
+ authTransactionSeqNumber
+ + 1;
+ authFrame.authStatusCode =
+ eSIR_MAC_CHALLENGE_FAILURE_STATUS;
+
+ lim_send_auth_mgmt_frame
+ (pMac, &authFrame,
+ pHdr->sa,
+ LIM_NO_WEP_IN_FC,
+ psessionEntry);
+
+ lim_restore_from_auth_state
+ (pMac,
+ eSIR_SME_INVALID_WEP_DEFAULT_KEY,
+ eSIR_MAC_UNSPEC_FAILURE_REASON,
+ psessionEntry);
+
+ break;
+ }
+ key_length = val;
+ ((tpSirMacAuthFrameBody)
+ plainBody)->authAlgoNumber =
+ sir_swap_u16if_needed(pRxAuthFrameBody->
+ authAlgoNumber);
+ ((tpSirMacAuthFrameBody)
+ plainBody)->
+ authTransactionSeqNumber =
+ sir_swap_u16if_needed((uint16_t)
+ (pRxAuthFrameBody->
+ authTransactionSeqNumber + 1));
+ ((tpSirMacAuthFrameBody)
+ plainBody)->authStatusCode =
+ eSIR_MAC_SUCCESS_STATUS;
+ ((tpSirMacAuthFrameBody)
+ plainBody)->type =
+ SIR_MAC_CHALLENGE_TEXT_EID;
+ ((tpSirMacAuthFrameBody)
+ plainBody)->length =
+ SIR_MAC_AUTH_CHALLENGE_LENGTH;
+ cdf_mem_copy((uint8_t*) ((tpSirMacAuthFrameBody) plainBody)->challengeText,
+ pRxAuthFrameBody->challengeText,
+ SIR_MAC_AUTH_CHALLENGE_LENGTH);
+
+ lim_encrypt_auth_frame(pMac, keyId,
+ defaultKey,
+ plainBody,
+ encrAuthFrame,
+ key_length);
+
+ psessionEntry->limMlmState =
+ eLIM_MLM_WT_AUTH_FRAME4_STATE;
+ MTRACE(mac_trace
+ (pMac,
+ TRACE_CODE_MLM_STATE,
+ psessionEntry->
+ peSessionId,
+ psessionEntry->
+ limMlmState));
+
+ lim_send_auth_mgmt_frame(pMac,
+ (tpSirMacAuthFrameBody)
+ encrAuthFrame,
+ pHdr->sa,
+ LIM_WEP_IN_FC,
+ psessionEntry);
+
+ break;
+ } /* end if (!wlan_cfg_get_int(CFG_PRIVACY_OPTION_IMPLEMENTED)) */
+ } /* end if (pRxAuthFrameBody->authAlgoNumber == eSIR_OPEN_SYSTEM) */
+ } /* if (pRxAuthFrameBody->authStatusCode == eSIR_MAC_SUCCESS_STATUS) */
+ else {
+ /**
+ * Authentication failure.
+ * Return Auth confirm with received failure code to SME
+ */
+
+ /* Log error */
+ PELOGE(lim_log(pMac, LOGE,
+ FL
+ ("received Auth frame from peer with failure code %d "
+ MAC_ADDRESS_STR),
+ pRxAuthFrameBody->authStatusCode,
+ MAC_ADDR_ARRAY(pHdr->sa));
+ )
+
+ lim_restore_from_auth_state(pMac, eSIR_SME_AUTH_REFUSED,
+ pRxAuthFrameBody->
+ authStatusCode,
+ psessionEntry);
+ } /* end if (pRxAuthFrameBody->authStatusCode == eSIR_MAC_SUCCESS_STATUS) */
+
+ break;
+
+ case SIR_MAC_AUTH_FRAME_3:
+ /* AuthFrame 3 */
+
+ if (pRxAuthFrameBody->authAlgoNumber != eSIR_SHARED_KEY) {
+ /* Log error */
+ PELOGE(lim_log(pMac, LOGE,
+ FL
+ ("received Auth frame3 from peer with auth algo number %d "
+ MAC_ADDRESS_STR),
+ pRxAuthFrameBody->authAlgoNumber,
+ MAC_ADDR_ARRAY(pHdr->sa));
+ )
+
+ /**
+ * Received Authentication frame3 with algorithm other than
+ * Shared Key authentication type. Reject with Auth frame4
+ * with 'out of sequence' status code.
+ */
+ authFrame.authAlgoNumber = eSIR_SHARED_KEY;
+ authFrame.authTransactionSeqNumber =
+ SIR_MAC_AUTH_FRAME_4;
+ authFrame.authStatusCode =
+ eSIR_MAC_AUTH_FRAME_OUT_OF_SEQ_STATUS;
+
+ lim_send_auth_mgmt_frame(pMac, &authFrame,
+ pHdr->sa,
+ LIM_NO_WEP_IN_FC, psessionEntry);
+ return;
+ }
+
+ if (LIM_IS_AP_ROLE(psessionEntry) ||
+ LIM_IS_BT_AMP_AP_ROLE(psessionEntry) ||
+ LIM_IS_IBSS_ROLE(psessionEntry)) {
+ /**
+ * Check if wep bit was set in FC. If not set,
+ * reject with Authentication frame4 with
+ * 'challenge failure' status code.
+ */
+ if (!pHdr->fc.wep) {
+ /* Log error */
+ PELOGE(lim_log(pMac, LOGE,
+ FL
+ ("received Auth frame3 from peer with no WEP bit set "
+ MAC_ADDRESS_STR),
+ MAC_ADDR_ARRAY(pHdr->sa));
+ )
+ /* / WEP bit is not set in FC of Auth Frame3 */
+ authFrame.authAlgoNumber = eSIR_SHARED_KEY;
+ authFrame.authTransactionSeqNumber =
+ SIR_MAC_AUTH_FRAME_4;
+ authFrame.authStatusCode =
+ eSIR_MAC_CHALLENGE_FAILURE_STATUS;
+
+ lim_send_auth_mgmt_frame(pMac, &authFrame,
+ pHdr->sa,
+ LIM_NO_WEP_IN_FC,
+ psessionEntry);
+ return;
+ }
+
+ pAuthNode = lim_search_pre_auth_list(pMac, pHdr->sa);
+ if (pAuthNode == NULL) {
+ /* Log error */
+ PELOGE(lim_log(pMac, LOGW,
+ FL
+ ("received AuthFrame3 from peer that has no preauth context "
+ MAC_ADDRESS_STR),
+ MAC_ADDR_ARRAY(pHdr->sa));
+ )
+ /**
+ * No 'pre-auth' context exists for
+ * this STA that sent an Authentication
+ * frame3.
+ * Send Auth frame4 with 'out of sequence'
+ * status code.
+ */
+ authFrame.authAlgoNumber = eSIR_SHARED_KEY;
+ authFrame.authTransactionSeqNumber =
+ SIR_MAC_AUTH_FRAME_4;
+ authFrame.authStatusCode =
+ eSIR_MAC_AUTH_FRAME_OUT_OF_SEQ_STATUS;
+
+ lim_send_auth_mgmt_frame(pMac, &authFrame,
+ pHdr->sa,
+ LIM_NO_WEP_IN_FC,
+ psessionEntry);
+ return;
+ }
+
+ if (pAuthNode->mlmState ==
+ eLIM_MLM_AUTH_RSP_TIMEOUT_STATE) {
+ /* Log error */
+ lim_log(pMac, LOGW,
+ FL
+ ("auth response timer timedout for peer "
+ MAC_ADDRESS_STR),
+ MAC_ADDR_ARRAY(pHdr->sa));
+
+ /**
+ * Received Auth Frame3 after Auth Response timeout.
+ * Reject by sending Auth Frame4 with
+ * Auth respone timeout Status Code.
+ */
+ authFrame.authAlgoNumber = eSIR_SHARED_KEY;
+ authFrame.authTransactionSeqNumber =
+ SIR_MAC_AUTH_FRAME_4;
+ authFrame.authStatusCode =
+ eSIR_MAC_AUTH_RSP_TIMEOUT_STATUS;
+
+ lim_send_auth_mgmt_frame(pMac, &authFrame,
+ pHdr->sa,
+ LIM_NO_WEP_IN_FC,
+ psessionEntry);
+
+ /* / Delete pre-auth context of STA */
+ lim_delete_pre_auth_node(pMac, pHdr->sa);
+
+ return;
+ } /* end switch (pAuthNode->mlmState) */
+
+ if (pRxAuthFrameBody->authStatusCode !=
+ eSIR_MAC_SUCCESS_STATUS) {
+ /**
+ * Received Authenetication Frame 3 with status code
+ * other than success. Wait until Auth response timeout
+ * to delete STA context.
+ */
+
+ /* Log error */
+ PELOGE(lim_log(pMac, LOGE,
+ FL
+ ("received Auth frame3 from peer with status code %d "
+ MAC_ADDRESS_STR),
+ pRxAuthFrameBody->authStatusCode,
+ MAC_ADDR_ARRAY(pHdr->sa));
+ )
+
+ return;
+ }
+
+ /**
+ * Check if received challenge text is same as one sent in
+ * Authentication frame3
+ */
+
+ if (cdf_mem_compare(pRxAuthFrameBody->challengeText,
+ pAuthNode->challengeText,
+ SIR_MAC_AUTH_CHALLENGE_LENGTH)) {
+ /* / Challenge match. STA is autheticated ! */
+
+ /* / Delete Authentication response timer if running */
+ lim_deactivate_and_change_per_sta_id_timer(pMac,
+ eLIM_AUTH_RSP_TIMER,
+ pAuthNode->
+ authNodeIdx);
+
+ pAuthNode->fTimerStarted = 0;
+ pAuthNode->mlmState =
+ eLIM_MLM_AUTHENTICATED_STATE;
+
+ /**
+ * Send Authentication Frame4 with 'success' Status Code.
+ */
+ authFrame.authAlgoNumber = eSIR_SHARED_KEY;
+ authFrame.authTransactionSeqNumber =
+ SIR_MAC_AUTH_FRAME_4;
+ authFrame.authStatusCode =
+ eSIR_MAC_SUCCESS_STATUS;
+
+ lim_send_auth_mgmt_frame(pMac, &authFrame,
+ pHdr->sa,
+ LIM_NO_WEP_IN_FC,
+ psessionEntry);
+ break;
+ } else {
+ /* Log error */
+ PELOGE(lim_log(pMac, LOGW,
+ FL("Challenge failure for peer "
+ MAC_ADDRESS_STR),
+ MAC_ADDR_ARRAY(pHdr->sa));
+ )
+ /**
+ * Challenge Failure.
+ * Send Authentication frame4 with 'challenge failure'
+ * status code and wait until Auth response timeout to
+ * delete STA context.
+ */
+ authFrame.authAlgoNumber =
+ pRxAuthFrameBody->authAlgoNumber;
+ authFrame.authTransactionSeqNumber =
+ SIR_MAC_AUTH_FRAME_4;
+ authFrame.authStatusCode =
+ eSIR_MAC_CHALLENGE_FAILURE_STATUS;
+
+ lim_send_auth_mgmt_frame(pMac, &authFrame,
+ pHdr->sa,
+ LIM_NO_WEP_IN_FC,
+ psessionEntry);
+ return;
+ }
+ } /* if (pMac->lim.gLimSystemRole == eLIM_AP_ROLE || ... */
+
+ break;
+
+ case SIR_MAC_AUTH_FRAME_4:
+ /* AuthFrame 4 */
+ if (psessionEntry->limMlmState != eLIM_MLM_WT_AUTH_FRAME4_STATE) {
+ /**
+ * Received Authentication frame4 in an unexpected state.
+ * Log error and ignore the frame.
+ */
+
+ /* Log error */
+ PELOG1(lim_log(pMac, LOG1,
+ FL
+ ("received unexpected Auth frame4 from peer in state %d, addr "
+ MAC_ADDRESS_STR),
+ psessionEntry->limMlmState,
+ MAC_ADDR_ARRAY(pHdr->sa));
+ )
+
+ return;
+ }
+
+ if (pRxAuthFrameBody->authAlgoNumber != eSIR_SHARED_KEY) {
+ /**
+ * Received Authentication frame4 with algorithm other than
+ * Shared Key authentication type.
+ * Wait until Auth failure timeout to report authentication
+ * failure to SME.
+ */
+
+ /* Log error */
+ PELOGE(lim_log(pMac, LOGE,
+ FL
+ ("received Auth frame4 from peer with invalid auth algo %d "
+ MAC_ADDRESS_STR),
+ pRxAuthFrameBody->authAlgoNumber,
+ MAC_ADDR_ARRAY(pHdr->sa));
+ )
+
+ return;
+ }
+
+ if (!cdf_mem_compare((uint8_t *) pHdr->sa,
+ (uint8_t *) &pMac->lim.gpLimMlmAuthReq->
+ peerMacAddr, sizeof(tSirMacAddr))) {
+ /**
+ * Received Authentication frame from an entity
+ * other than one to which request was initiated.
+ * Wait until Authentication Failure Timeout.
+ */
+
+ /* Log error */
+ PELOGE(lim_log(pMac, LOGW,
+ FL
+ ("received Auth frame4 from unexpected peer "
+ MAC_ADDRESS_STR),
+ MAC_ADDR_ARRAY(pHdr->sa));
+ )
+
+ break;
+ }
+
+ if (pRxAuthFrameBody->authAlgoNumber !=
+ pMac->lim.gpLimMlmAuthReq->authType) {
+ /**
+ * Received Authentication frame with an auth algorithm
+ * other than one requested.
+ * Wait until Authentication Failure Timeout.
+ */
+
+ PELOGE(lim_log(pMac, LOGE,
+ FL
+ ("received Authentication frame from peer with invalid auth seq number %d "
+ MAC_ADDRESS_STR),
+ pRxAuthFrameBody->
+ authTransactionSeqNumber,
+ MAC_ADDR_ARRAY(pHdr->sa));
+ )
+
+ break;
+ }
+
+ if (pRxAuthFrameBody->authStatusCode == eSIR_MAC_SUCCESS_STATUS) {
+ /**
+ * Authentication Success !
+ * Inform SME of same.
+ */
+ psessionEntry->limCurrentAuthType = eSIR_SHARED_KEY;
+
+ pAuthNode =
+ lim_acquire_free_pre_auth_node(pMac,
+ &pMac->lim.
+ gLimPreAuthTimerTable);
+ if (pAuthNode == NULL) {
+ /* Log error */
+ lim_log(pMac, LOGW,
+ FL("Max pre-auth nodes reached "));
+ lim_print_mac_addr(pMac, pHdr->sa, LOGW);
+
+ return;
+ }
+ PELOG1(lim_log
+ (pMac, LOG1, FL("Alloc new data: %x peer "),
+ pAuthNode);
+ lim_print_mac_addr(pMac, pHdr->sa, LOG1);
+ )
+
+ cdf_mem_copy((uint8_t *) pAuthNode->peerMacAddr,
+ pMac->lim.gpLimMlmAuthReq->peerMacAddr,
+ sizeof(tSirMacAddr));
+ pAuthNode->fTimerStarted = 0;
+ pAuthNode->authType =
+ pMac->lim.gpLimMlmAuthReq->authType;
+ pAuthNode->seq_num =
+ ((pHdr->seqControl.seqNumHi << 4) |
+ (pHdr->seqControl.seqNumLo));
+ pAuthNode->timestamp = cdf_mc_timer_get_system_ticks();
+ lim_add_pre_auth_node(pMac, pAuthNode);
+
+ lim_restore_from_auth_state(pMac, eSIR_SME_SUCCESS,
+ pRxAuthFrameBody->
+ authStatusCode, psessionEntry);
+
+ } /* if (pRxAuthFrameBody->authStatusCode == eSIR_MAC_SUCCESS_STATUS) */
+ else {
+ /**
+ * Authentication failure.
+ * Return Auth confirm with received failure code to SME
+ */
+
+ /* Log error */
+ PELOGE(lim_log
+ (pMac, LOGE,
+ FL("Authentication failure from peer "
+ MAC_ADDRESS_STR), MAC_ADDR_ARRAY(pHdr->sa));
+ )
+
+ lim_restore_from_auth_state(pMac, eSIR_SME_AUTH_REFUSED,
+ pRxAuthFrameBody->
+ authStatusCode,
+ psessionEntry);
+ } /* end if (pRxAuthFrameBody->Status == 0) */
+
+ break;
+
+ default:
+ /* / Invalid Authentication Frame received. Ignore it. */
+
+ /* Log error */
+ PELOGE(lim_log(pMac, LOGE,
+ FL
+ ("received Auth frame from peer with invalid auth seq "
+ "number %d " MAC_ADDRESS_STR),
+ pRxAuthFrameBody->authTransactionSeqNumber,
+ MAC_ADDR_ARRAY(pHdr->sa));
+ )
+
+ break;
+ } /* end switch (pRxAuthFrameBody->authTransactionSeqNumber) */
+} /*** end lim_process_auth_frame() ***/
+
+#ifdef WLAN_FEATURE_VOWIFI_11R
+
+/*----------------------------------------------------------------------
+ *
+ * Pass the received Auth frame. This is possibly the pre-auth from the
+ * neighbor AP, in the same mobility domain.
+ * This will be used in case of 11r FT.
+ *
+ * !!!! This is going to be renoved for the next checkin. We will be creating
+ * the session before sending out the Auth. Thus when auth response
+ * is received we will have a session in progress. !!!!!
+ ***----------------------------------------------------------------------
+ */
+tSirRetStatus lim_process_auth_frame_no_session(tpAniSirGlobal pMac, uint8_t *pBd,
+ void *body)
+{
+ tpSirMacMgmtHdr pHdr;
+ tpPESession psessionEntry = NULL;
+ uint8_t *pBody;
+ uint16_t frameLen;
+ tSirMacAuthFrameBody rxAuthFrame;
+ tSirMacAuthFrameBody *pRxAuthFrameBody = NULL;
+ tSirRetStatus ret_status = eSIR_FAILURE;
+ int i;
+
+ pHdr = WMA_GET_RX_MAC_HEADER(pBd);
+ pBody = WMA_GET_RX_MPDU_DATA(pBd);
+ frameLen = WMA_GET_RX_PAYLOAD_LEN(pBd);
+
+ lim_log(pMac, LOG1,
+ FL("Auth Frame Received: BSSID " MAC_ADDRESS_STR " (RSSI %d)"),
+ MAC_ADDR_ARRAY(pHdr->bssId),
+ (uint) abs((int8_t) WMA_GET_RX_RSSI_DB(pBd)));
+
+ /* Auth frame has come on a new BSS, however, we need to find the session
+ * from where the auth-req was sent to the new AP
+ */
+ for (i = 0; i < pMac->lim.maxBssId; i++) {
+ /* Find first free room in session table */
+ if (pMac->lim.gpSession[i].valid == true &&
+ pMac->lim.gpSession[i].ftPEContext.ftPreAuthSession ==
+ true) {
+ /* Found the session */
+ psessionEntry = &pMac->lim.gpSession[i];
+ pMac->lim.gpSession[i].ftPEContext.ftPreAuthSession =
+ false;
+ }
+ }
+
+ if (psessionEntry == NULL) {
+ lim_log(pMac, LOGE,
+ FL
+ ("Error: Unable to find session id while in pre-auth phase for FT"));
+ return eSIR_FAILURE;
+ }
+
+ if (psessionEntry->ftPEContext.pFTPreAuthReq == NULL) {
+ lim_log(pMac, LOGE, FL("Error: No FT"));
+ /* No FT in progress. */
+ return eSIR_FAILURE;
+ }
+
+ if (frameLen == 0) {
+ lim_log(pMac, LOGE, FL("Error: Frame len = 0"));
+ return eSIR_FAILURE;
+ }
+#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG
+ lim_print_mac_addr(pMac, pHdr->bssId, LOG2);
+ lim_print_mac_addr(pMac,
+ psessionEntry->ftPEContext.pFTPreAuthReq->preAuthbssId,
+ LOG2);
+ lim_log(pMac, LOG2, FL("seqControl 0x%X"),
+ ((pHdr->seqControl.seqNumHi << 8) | (pHdr->seqControl.
+ seqNumLo << 4) | (pHdr->
+ seqControl.
+ fragNum)));
+#endif
+
+ /* Check that its the same bssId we have for preAuth */
+ if (!cdf_mem_compare
+ (psessionEntry->ftPEContext.pFTPreAuthReq->preAuthbssId,
+ pHdr->bssId, sizeof(tSirMacAddr))) {
+ lim_log(pMac, LOGE, FL("Error: Same bssid as preauth BSSID"));
+ /* In this case SME if indeed has triggered a */
+ /* pre auth it will time out. */
+ return eSIR_FAILURE;
+ }
+
+ if (true ==
+ psessionEntry->ftPEContext.pFTPreAuthReq->bPreAuthRspProcessed) {
+ /*
+ * This is likely a duplicate for the same pre-auth request.
+ * PE/LIM already posted a response to SME. Hence, drop it.
+ * TBD:
+ * 1) How did we even receive multiple auth responses?
+ * 2) Do we need to delete pre-auth session? Suppose we
+ * previously received an auth resp with failure which
+ * would not have created the session and forwarded to SME.
+ * And, we subsequently received an auth resp with success
+ * which would have created the session. This will now be
+ * dropped without being forwarded to SME! However, it is
+ * very unlikely to receive auth responses from the same
+ * AP with different reason codes.
+ * NOTE: return eSIR_SUCCESS so that the packet is dropped
+ * as this was indeed a response from the BSSID we tried to
+ * pre-auth.
+ */
+ PELOGE(lim_log(pMac, LOG1, "Auth rsp already posted to SME"
+ " (session %p, FT session %p)", psessionEntry,
+ psessionEntry);
+ );
+ return eSIR_SUCCESS;
+ } else {
+ PELOGE(lim_log(pMac, LOGW, "Auth rsp not yet posted to SME"
+ " (session %p, FT session %p)", psessionEntry,
+ psessionEntry);
+ );
+ psessionEntry->ftPEContext.pFTPreAuthReq->bPreAuthRspProcessed =
+ true;
+ }
+
+#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG
+ lim_log(pMac, LOG1, FL("Pre-Auth response received from neighbor"));
+ lim_log(pMac, LOG1, FL("Pre-Auth done state"));
+#endif
+ /* Stopping timer now, that we have our unicast from the AP */
+ /* of our choice. */
+ lim_deactivate_and_change_timer(pMac, eLIM_FT_PREAUTH_RSP_TIMER);
+
+ /* Save off the auth resp. */
+ if ((sir_convert_auth_frame2_struct(pMac, pBody, frameLen, &rxAuthFrame) !=
+ eSIR_SUCCESS)) {
+ lim_log(pMac, LOGE,
+ FL("failed to convert Auth frame to struct"));
+ lim_handle_ft_pre_auth_rsp(pMac, eSIR_FAILURE, NULL, 0,
+ psessionEntry);
+ return eSIR_FAILURE;
+ }
+ pRxAuthFrameBody = &rxAuthFrame;
+
+#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG
+ PELOGE(lim_log(pMac, LOG1,
+ FL
+ ("Received Auth frame with type=%d seqnum=%d, status=%d (%d)"),
+ (uint32_t) pRxAuthFrameBody->authAlgoNumber,
+ (uint32_t) pRxAuthFrameBody->authTransactionSeqNumber,
+ (uint32_t) pRxAuthFrameBody->authStatusCode,
+ (uint32_t) pMac->lim.gLimNumPreAuthContexts);
+ )
+#endif
+ switch (pRxAuthFrameBody->authTransactionSeqNumber) {
+ case SIR_MAC_AUTH_FRAME_2:
+ if (pRxAuthFrameBody->authStatusCode != eSIR_MAC_SUCCESS_STATUS) {
+#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG
+ PELOGE(lim_log
+ (pMac, LOGE, "Auth status code received is %d",
+ (uint32_t) pRxAuthFrameBody->authStatusCode);
+ );
+#endif
+ if (eSIR_MAC_MAX_ASSOC_STA_REACHED_STATUS ==
+ pRxAuthFrameBody->authStatusCode)
+ ret_status = eSIR_LIM_MAX_STA_REACHED_ERROR;
+ } else {
+ ret_status = eSIR_SUCCESS;
+ }
+ break;
+
+ default:
+#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG
+ PELOGE(lim_log
+ (pMac, LOGE, "Seq. no incorrect expected 2 received %d",
+ (uint32_t) pRxAuthFrameBody->authTransactionSeqNumber);
+ )
+#endif
+ break;
+ }
+
+ /* Send the Auth response to SME */
+ lim_handle_ft_pre_auth_rsp(pMac, ret_status, pBody, frameLen, psessionEntry);
+
+ return ret_status;
+}
+
+#endif /* WLAN_FEATURE_VOWIFI_11R */
diff --git a/core/mac/src/pe/lim/lim_process_beacon_frame.c b/core/mac/src/pe/lim/lim_process_beacon_frame.c
new file mode 100644
index 0000000..3a72a69
--- /dev/null
+++ b/core/mac/src/pe/lim/lim_process_beacon_frame.c
@@ -0,0 +1,250 @@
+/*
+ * Copyright (c) 2011-2015 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_process_beacon_frame.cc contains the code
+ * for processing Received Beacon Frame.
+ * Author: Chandra Modumudi
+ * Date: 03/01/02
+ * History:-
+ * Date Modified by Modification Information
+ * --------------------------------------------------------------------
+ *
+ */
+
+#include "wni_cfg.h"
+#include "ani_global.h"
+#include "cfg_api.h"
+#include "sch_api.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_ser_des_utils.h"
+
+/**
+ * lim_process_beacon_frame() - to process beacon frames
+ * @mac_ctx: Pointer to Global MAC structure
+ * @rx_pkt_info: A pointer to RX packet info structure
+ * @session: A pointer to session
+ *
+ * This function is called by limProcessMessageQueue() upon Beacon
+ * frame reception.
+ * Note:
+ * 1. Beacons received in 'normal' state in IBSS are handled by
+ * Beacon Processing module.
+ *
+ * Return: none
+ */
+
+void
+lim_process_beacon_frame(tpAniSirGlobal mac_ctx, uint8_t *rx_pkt_info,
+ tpPESession session)
+{
+ tpSirMacMgmtHdr mac_hdr;
+ tSchBeaconStruct *bcn_ptr;
+
+ mac_ctx->lim.gLimNumBeaconsRcvd++;
+
+ /*
+ * here is it required to increment session specific heartBeat
+ * beacon counter
+ */
+ mac_hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info);
+ lim_log(mac_ctx, LOG2,
+ FL("Received Beacon frame with length=%d from "),
+ WMA_GET_RX_MPDU_LEN(rx_pkt_info));
+ lim_print_mac_addr(mac_ctx, mac_hdr->sa, LOG2);
+
+ /* Expect Beacon in any state as Scan is independent of LIM state */
+ bcn_ptr = cdf_mem_malloc(sizeof(*bcn_ptr));
+ if (NULL == bcn_ptr) {
+ lim_log(mac_ctx, LOGE,
+ FL("Unable to allocate memory"));
+ return;
+ }
+ /* Parse received Beacon */
+ if (sir_convert_beacon_frame2_struct(mac_ctx,
+ rx_pkt_info, bcn_ptr) !=
+ eSIR_SUCCESS) {
+ /*
+ * Received wrongly formatted/invalid Beacon.
+ * Ignore it and move on.
+ */
+ lim_log(mac_ctx, LOGW,
+ FL("Received invalid Beacon in state %X"),
+ session->limMlmState);
+ lim_print_mlm_state(mac_ctx, LOGW,
+ session->limMlmState);
+ cdf_mem_free(bcn_ptr);
+ return;
+ }
+ /*
+ * during scanning, when any session is active, and
+ * beacon/Pr belongs to one of the session, fill up the
+ * following, TBD - HB couter
+ */
+ if ((!session->lastBeaconDtimPeriod) &&
+ (sir_compare_mac_addr(session->bssId,
+ bcn_ptr->bssid))) {
+ cdf_mem_copy((uint8_t *)&session->lastBeaconTimeStamp,
+ (uint8_t *) bcn_ptr->timeStamp,
+ sizeof(uint64_t));
+ session->lastBeaconDtimCount =
+ bcn_ptr->tim.dtimCount;
+ session->lastBeaconDtimPeriod =
+ bcn_ptr->tim.dtimPeriod;
+ session->currentBssBeaconCnt++;
+ }
+ MTRACE(mac_trace(mac_ctx,
+ TRACE_CODE_RX_MGMT_TSF, 0, bcn_ptr->timeStamp[0]);)
+ MTRACE(mac_trace(mac_ctx, TRACE_CODE_RX_MGMT_TSF, 0,
+ bcn_ptr->timeStamp[1]);)
+ lim_check_and_add_bss_description(mac_ctx, bcn_ptr,
+ rx_pkt_info, false, true);
+
+ if ((mac_ctx->lim.gLimMlmState ==
+ eLIM_MLM_WT_PROBE_RESP_STATE) ||
+ (mac_ctx->lim.gLimMlmState ==
+ eLIM_MLM_PASSIVE_SCAN_STATE)) {
+ lim_check_and_add_bss_description(mac_ctx, bcn_ptr,
+ rx_pkt_info,
+ ((mac_ctx->lim.gLimHalScanState ==
+ eLIM_HAL_SCANNING_STATE) ? true : false),
+ false);
+ /*
+ * Calling dfsChannelList which will convert DFS channel
+ * to active channel for x secs if this channel is DFS
+ */
+ lim_set_dfs_channel_list(mac_ctx,
+ bcn_ptr->channelNumber,
+ &mac_ctx->lim.dfschannelList);
+ } else if (session->limMlmState ==
+ eLIM_MLM_WT_JOIN_BEACON_STATE) {
+ if (session->beacon != NULL) {
+ cdf_mem_free(session->beacon);
+ session->beacon = NULL;
+ }
+ session->bcnLen = WMA_GET_RX_PAYLOAD_LEN(rx_pkt_info);
+ session->beacon = cdf_mem_malloc(session->bcnLen);
+ if (NULL == session->beacon) {
+ lim_log(mac_ctx, LOGE,
+ FL("fail to alloc mem to store bcn"));
+ } else {
+ /*
+ * Store the Beacon/ProbeRsp. This is sent to
+ * csr/hdd in join cnf response.
+ */
+ cdf_mem_copy(session->beacon,
+ WMA_GET_RX_MPDU_DATA(rx_pkt_info),
+ session->bcnLen);
+ }
+ lim_check_and_announce_join_success(mac_ctx, bcn_ptr,
+ mac_hdr, session);
+ }
+ cdf_mem_free(bcn_ptr);
+ return;
+}
+
+/**---------------------------------------------------------------
+ \fn lim_process_beacon_frame_no_session
+ \brief This function is called by limProcessMessageQueue()
+ \ upon Beacon reception.
+ \
+ \param pMac
+ \param *pRxPacketInfo - A pointer to Rx packet info structure
+ \return None
+ ------------------------------------------------------------------*/
+void
+lim_process_beacon_frame_no_session(tpAniSirGlobal pMac, uint8_t *pRxPacketInfo)
+{
+ tpSirMacMgmtHdr pHdr;
+ tSchBeaconStruct *pBeacon;
+
+ pMac->lim.gLimNumBeaconsRcvd++;
+ pHdr = WMA_GET_RX_MAC_HEADER(pRxPacketInfo);
+
+ lim_log(pMac, LOG2, FL("Received Beacon frame with length=%d from "),
+ WMA_GET_RX_MPDU_LEN(pRxPacketInfo));
+ lim_print_mac_addr(pMac, pHdr->sa, LOG2);
+
+
+ /**
+ * No session has been established. Expect Beacon only when
+ * 1. STA is in Scan mode waiting for Beacon/Probe response or
+ * 2. STA/AP is in Learn mode
+ */
+ if ((pMac->lim.gLimMlmState == eLIM_MLM_WT_PROBE_RESP_STATE) ||
+ (pMac->lim.gLimMlmState == eLIM_MLM_PASSIVE_SCAN_STATE) ||
+ (pMac->lim.gLimMlmState == eLIM_MLM_LEARN_STATE)) {
+ pBeacon = cdf_mem_malloc(sizeof(tSchBeaconStruct));
+ if (NULL == pBeacon) {
+ lim_log(pMac, LOGE,
+ FL
+ ("Unable to allocate memory in lim_process_beacon_frame_no_session"));
+ return;
+ }
+
+ if (sir_convert_beacon_frame2_struct
+ (pMac, (uint8_t *) pRxPacketInfo,
+ pBeacon) != eSIR_SUCCESS) {
+ /* Received wrongly formatted/invalid Beacon. Ignore and move on. */
+ lim_log(pMac, LOGW,
+ FL
+ ("Received invalid Beacon in global MLM state %X"),
+ pMac->lim.gLimMlmState);
+ lim_print_mlm_state(pMac, LOGW, pMac->lim.gLimMlmState);
+ cdf_mem_free(pBeacon);
+ return;
+ }
+
+ if ((pMac->lim.gLimMlmState == eLIM_MLM_WT_PROBE_RESP_STATE) ||
+ (pMac->lim.gLimMlmState == eLIM_MLM_PASSIVE_SCAN_STATE)) {
+ lim_check_and_add_bss_description(pMac, pBeacon,
+ pRxPacketInfo, true,
+ false);
+ /* Calling dfsChannelList which will convert DFS channel
+ * to Active channel for x secs if this channel is DFS channel */
+ lim_set_dfs_channel_list(pMac, pBeacon->channelNumber,
+ &pMac->lim.dfschannelList);
+ } else if (pMac->lim.gLimMlmState == eLIM_MLM_LEARN_STATE) {
+ } /* end of eLIM_MLM_LEARN_STATE) */
+ cdf_mem_free(pBeacon);
+ } /* end of (eLIM_MLM_WT_PROBE_RESP_STATE) || (eLIM_MLM_PASSIVE_SCAN_STATE) */
+ else {
+ lim_log(pMac, LOG1, FL("Rcvd Beacon in unexpected MLM state %d"),
+ pMac->lim.gLimMlmState);
+ lim_print_mlm_state(pMac, LOG1, pMac->lim.gLimMlmState);
+#ifdef WLAN_DEBUG
+ pMac->lim.gLimUnexpBcnCnt++;
+#endif
+ }
+
+ return;
+} /*** end lim_process_beacon_frame_no_session() ***/
diff --git a/core/mac/src/pe/lim/lim_process_cfg_updates.c b/core/mac/src/pe/lim/lim_process_cfg_updates.c
new file mode 100644
index 0000000..e1a645e
--- /dev/null
+++ b/core/mac/src/pe/lim/lim_process_cfg_updates.c
@@ -0,0 +1,648 @@
+/*
+ * Copyright (c) 2012-2015 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_process_cfg_updates.cc contains the utility functions
+ * to handle various CFG parameter update events
+ * Author: Chandra Modumudi
+ * Date: 01/20/03
+ * History:-
+ * Date Modified by Modification Information
+ * --------------------------------------------------------------------
+ */
+
+#include "ani_global.h"
+
+#include "wni_cfg.h"
+#include "sir_mac_prot_def.h"
+#include "cfg_api.h"
+#include "lim_types.h"
+#include "lim_utils.h"
+#include "lim_prop_exts_utils.h"
+#include "sch_api.h"
+#if defined WLAN_FEATURE_VOWIFI
+#include "rrm_api.h"
+#endif
+
+static void lim_update_config(tpAniSirGlobal pMac, tpPESession psessionEntry);
+
+static void lim_set_default_key_id_and_keys(tpAniSirGlobal pMac)
+{
+#ifdef FIXME_GEN6
+ uint32_t val;
+ uint32_t dkCfgId;
+ PELOG1(lim_log(pMac, LOG1, FL("Setting default keys at SP"));)
+ if (wlan_cfg_get_int(pMac, WNI_CFG_WEP_DEFAULT_KEYID,
+ &val) != eSIR_SUCCESS) {
+ lim_log(pMac, LOGP,
+ FL("Unable to retrieve defaultKeyId from CFG"));
+ }
+ dkCfgId = limGetCfgIdOfDefaultKeyid(val);
+#endif
+
+} /*** end lim_set_default_key_id_and_keys() ***/
+/** -------------------------------------------------------------
+ \fn lim_set_cfg_protection
+ \brief sets lim global cfg cache from the config.
+ \param tpAniSirGlobal pMac
+ \return None
+ -------------------------------------------------------------*/
+void lim_set_cfg_protection(tpAniSirGlobal pMac, tpPESession pesessionEntry)
+{
+ uint32_t val = 0;
+
+ if (pesessionEntry != NULL && LIM_IS_AP_ROLE(pesessionEntry)) {
+ if (pesessionEntry->gLimProtectionControl ==
+ WNI_CFG_FORCE_POLICY_PROTECTION_DISABLE)
+ cdf_mem_set((void *)&pesessionEntry->cfgProtection,
+ sizeof(tCfgProtection), 0);
+ else {
+ lim_log(pMac, LOG1,
+ FL(" frm11a = %d, from11b = %d, frm11g = %d, "
+ "ht20 = %d, nongf = %d, lsigTxop = %d, "
+ "rifs = %d, obss = %d"),
+ pesessionEntry->cfgProtection.fromlla,
+ pesessionEntry->cfgProtection.fromllb,
+ pesessionEntry->cfgProtection.fromllg,
+ pesessionEntry->cfgProtection.ht20,
+ pesessionEntry->cfgProtection.nonGf,
+ pesessionEntry->cfgProtection.lsigTxop,
+ pesessionEntry->cfgProtection.rifs,
+ pesessionEntry->cfgProtection.obss);
+ }
+ } else {
+ if (wlan_cfg_get_int(pMac, WNI_CFG_FORCE_POLICY_PROTECTION, &val)
+ != eSIR_SUCCESS) {
+ lim_log(pMac, LOGP,
+ FL
+ ("reading WNI_CFG_FORCE_POLICY_PROTECTION cfg failed"));
+ return;
+ } else
+ pMac->lim.gLimProtectionControl = (uint8_t) val;
+
+ if (wlan_cfg_get_int(pMac, WNI_CFG_PROTECTION_ENABLED, &val) !=
+ eSIR_SUCCESS) {
+ lim_log(pMac, LOGP, FL("reading protection cfg failed"));
+ return;
+ }
+
+ if (pMac->lim.gLimProtectionControl ==
+ WNI_CFG_FORCE_POLICY_PROTECTION_DISABLE)
+ cdf_mem_set((void *)&pMac->lim.cfgProtection,
+ sizeof(tCfgProtection), 0);
+ else {
+ pMac->lim.cfgProtection.fromlla =
+ (val >> WNI_CFG_PROTECTION_ENABLED_FROM_llA) & 1;
+ pMac->lim.cfgProtection.fromllb =
+ (val >> WNI_CFG_PROTECTION_ENABLED_FROM_llB) & 1;
+ pMac->lim.cfgProtection.fromllg =
+ (val >> WNI_CFG_PROTECTION_ENABLED_FROM_llG) & 1;
+ pMac->lim.cfgProtection.ht20 =
+ (val >> WNI_CFG_PROTECTION_ENABLED_HT_20) & 1;
+ pMac->lim.cfgProtection.nonGf =
+ (val >> WNI_CFG_PROTECTION_ENABLED_NON_GF) & 1;
+ pMac->lim.cfgProtection.lsigTxop =
+ (val >> WNI_CFG_PROTECTION_ENABLED_LSIG_TXOP) & 1;
+ pMac->lim.cfgProtection.rifs =
+ (val >> WNI_CFG_PROTECTION_ENABLED_RIFS) & 1;
+ pMac->lim.cfgProtection.obss =
+ (val >> WNI_CFG_PROTECTION_ENABLED_OBSS) & 1;
+
+ }
+ }
+}
+
+/**
+ * lim_handle_param_update()
+ *
+ ***FUNCTION:
+ * This function is use to post a message whenever need indicate
+ * there is update of config parameter.
+ *
+ ***PARAMS:
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ * NA
+ *
+ ***NOTE:
+ *
+ * @param pMac - Pointer to Global MAC structure
+ * @param cfgId - ID of CFG parameter that got updated
+ * @return None
+ */
+void lim_handle_param_update(tpAniSirGlobal pMac, eUpdateIEsType cfgId)
+{
+ tSirMsgQ msg = { 0 };
+ uint32_t status;
+
+ PELOG3(lim_log
+ (pMac, LOG3, FL("Handling CFG parameter id %X update"), cfgId);
+ )
+ switch (cfgId) {
+ case eUPDATE_IE_PROBE_BCN:
+ {
+ msg.type = SIR_LIM_UPDATE_BEACON;
+ status = lim_post_msg_api(pMac, &msg);
+
+ if (status != TX_SUCCESS)
+ PELOGE(lim_log
+ (pMac, LOGE,
+ FL("Failed lim_post_msg_api %u"), status);
+ )
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+/**
+ * lim_handle_cf_gparam_update()
+ *
+ ***FUNCTION:
+ * This function is called by lim_process_messages() to
+ * whenever SIR_CFG_PARAM_UPDATE_IND message is posted
+ * to LIM (due to a set operation on a CFG parameter).
+ *
+ ***PARAMS:
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ * NA
+ *
+ ***NOTE:
+ *
+ * @param pMac - Pointer to Global MAC structure
+ * @param cfgId - ID of CFG parameter that got updated
+ * @return None
+ */
+
+void lim_handle_cf_gparam_update(tpAniSirGlobal pMac, uint32_t cfgId)
+{
+ uint32_t val1, val2;
+ uint16_t val16;
+ tSirMacHTCapabilityInfo *pHTCapabilityInfo;
+ tSirMacHTParametersInfo *pAmpduParamInfo;
+
+ PELOG3(lim_log
+ (pMac, LOG3, FL("Handling CFG parameter id %X update"), cfgId);
+ )
+ switch (cfgId) {
+ case WNI_CFG_WEP_DEFAULT_KEYID:
+
+ /* !!LAC - when the default KeyID is changed, force all of the */
+ /* keys and the keyID to be reprogrammed. this allows the */
+ /* keys to change after the initial setting of the keys when the CFG was */
+ /* applied at association time through CFG changes of the keys. */
+ lim_set_default_key_id_and_keys(pMac);
+
+ break;
+
+ case WNI_CFG_EXCLUDE_UNENCRYPTED:
+ if (wlan_cfg_get_int(pMac, WNI_CFG_EXCLUDE_UNENCRYPTED,
+ &val1) != eSIR_SUCCESS) {
+ lim_log(pMac, LOGP,
+ FL("Unable to retrieve excludeUnencr from CFG"));
+ }
+ lim_log(pMac, LOGE,
+ FL("Unsupported CFG: WNI_CFG_EXCLUDE_UNENCRYPTED"));
+
+ break;
+
+ case WNI_CFG_ASSOCIATION_FAILURE_TIMEOUT:
+ if (pMac->lim.gLimMlmState != eLIM_MLM_WT_ASSOC_RSP_STATE) {
+ /* 'Change' timer for future activations */
+ lim_deactivate_and_change_timer(pMac,
+ eLIM_ASSOC_FAIL_TIMER);
+ }
+
+ break;
+
+ case WNI_CFG_PROTECTION_ENABLED:
+ lim_set_cfg_protection(pMac, NULL);
+ break;
+ case WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG:
+ {
+ tSirMsgQ msg = { 0 };
+ uint32_t status;
+
+ msg.type = SIR_LIM_UPDATE_BEACON;
+
+ status = lim_post_msg_api(pMac, &msg);
+
+ if (status != TX_SUCCESS)
+ PELOGE(lim_log
+ (pMac, LOGE,
+ FL("Failed lim_post_msg_api %u"), status);
+ )
+ break;
+ }
+ case WNI_CFG_GREENFIELD_CAPABILITY:
+ if (wlan_cfg_get_int(pMac, WNI_CFG_HT_CAP_INFO, &val1) !=
+ eSIR_SUCCESS) {
+ PELOGE(lim_log
+ (pMac, LOGE,
+ FL("could not retrieve HT Cap Info CFG"));
+ )
+ break;
+ }
+ if (wlan_cfg_get_int(pMac, WNI_CFG_GREENFIELD_CAPABILITY, &val2)
+ != eSIR_SUCCESS) {
+ PELOGE(lim_log
+ (pMac, LOGE,
+ FL("could not retrieve GreenField CFG"));
+ )
+ break;
+ }
+ val16 = (uint16_t) val1;
+ pHTCapabilityInfo = (tSirMacHTCapabilityInfo *) &val16;
+ pHTCapabilityInfo->greenField = (uint16_t) val2;
+ if (cfg_set_int
+ (pMac, WNI_CFG_HT_CAP_INFO,
+ *(uint16_t *) pHTCapabilityInfo) != eSIR_SUCCESS)
+ PELOGE(lim_log
+ (pMac, LOGE,
+ FL("could not update HT Cap Info CFG"));
+ )
+ break;
+
+ case WNI_CFG_HT_RX_STBC:
+ if (wlan_cfg_get_int(pMac, WNI_CFG_HT_CAP_INFO, &val1) !=
+ eSIR_SUCCESS) {
+ PELOGE(lim_log
+ (pMac, LOGE,
+ FL("could not retrieve WNI_CFG_HT_CAP_INFO "));
+ )
+ break;
+ }
+ if (wlan_cfg_get_int(pMac, WNI_CFG_HT_RX_STBC, &val2) !=
+ eSIR_SUCCESS) {
+ PELOGE(lim_log
+ (pMac, LOGE,
+ FL("could not retrieve WNI_CFG_HT_RX_STBC"));
+ )
+ break;
+ }
+ val16 = (uint16_t) val1;
+ pHTCapabilityInfo = (tSirMacHTCapabilityInfo *) &val16;
+ pHTCapabilityInfo->rxSTBC = (uint16_t) val2;
+ if (cfg_set_int
+ (pMac, WNI_CFG_HT_CAP_INFO,
+ *(uint16_t *) pHTCapabilityInfo) != eSIR_SUCCESS)
+ PELOGE(lim_log
+ (pMac, LOGE,
+ FL("could not update HT Cap Info CFG"));
+ )
+ break;
+
+ case WNI_CFG_MAX_AMSDU_LENGTH:
+ if (wlan_cfg_get_int(pMac, WNI_CFG_HT_CAP_INFO, &val1) !=
+ eSIR_SUCCESS) {
+ PELOGE(lim_log
+ (pMac, LOGE,
+ FL("could not retrieve HT Cap Info CFG"));
+ )
+ break;
+ }
+ if (wlan_cfg_get_int(pMac, WNI_CFG_MAX_AMSDU_LENGTH, &val2) !=
+ eSIR_SUCCESS) {
+ PELOGE(lim_log
+ (pMac, LOGE,
+ FL("could not retrieve Max AMSDU Length CFG"));
+ )
+ break;
+ }
+ val16 = (uint16_t) val1;
+ pHTCapabilityInfo = (tSirMacHTCapabilityInfo *) &val16;
+ pHTCapabilityInfo->maximalAMSDUsize = (uint16_t) val2;
+ if (cfg_set_int
+ (pMac, WNI_CFG_HT_CAP_INFO,
+ *(uint16_t *) pHTCapabilityInfo) != eSIR_SUCCESS)
+ PELOGE(lim_log
+ (pMac, LOGE,
+ FL("could not update HT Cap Info CFG"));
+ )
+ break;
+
+ case WNI_CFG_SHORT_GI_20MHZ:
+ if (wlan_cfg_get_int(pMac, WNI_CFG_HT_CAP_INFO, &val1) !=
+ eSIR_SUCCESS) {
+ PELOGE(lim_log
+ (pMac, LOGE,
+ FL("could not retrieve HT Cap CFG"));
+ )
+ break;
+ }
+ if (wlan_cfg_get_int(pMac, WNI_CFG_SHORT_GI_20MHZ, &val2) !=
+ eSIR_SUCCESS) {
+ PELOGE(lim_log
+ (pMac, LOGE,
+ FL("could not retrieve shortGI 20Mhz CFG"));
+ )
+ break;
+ }
+ val16 = (uint16_t) val1;
+ pHTCapabilityInfo = (tSirMacHTCapabilityInfo *) &val16;
+ pHTCapabilityInfo->shortGI20MHz = (uint16_t) val2;
+ if (cfg_set_int
+ (pMac, WNI_CFG_HT_CAP_INFO,
+ *(uint16_t *) pHTCapabilityInfo) != eSIR_SUCCESS)
+ PELOGE(lim_log
+ (pMac, LOGE,
+ FL("could not update HT Cap Info CFG"));
+ )
+ break;
+ case WNI_CFG_SHORT_GI_40MHZ:
+ if (wlan_cfg_get_int(pMac, WNI_CFG_HT_CAP_INFO, &val1) !=
+ eSIR_SUCCESS) {
+ PELOGE(lim_log
+ (pMac, LOGE,
+ FL("could not retrieve HT Cap CFG"));
+ )
+ break;
+ }
+ if (wlan_cfg_get_int(pMac, WNI_CFG_SHORT_GI_40MHZ, &val2) !=
+ eSIR_SUCCESS) {
+ PELOGE(lim_log
+ (pMac, LOGE,
+ FL("could not retrieve shortGI 40Mhz CFG"));
+ )
+ break;
+ }
+ val16 = (uint16_t) val1;
+ pHTCapabilityInfo = (tSirMacHTCapabilityInfo *) &val16;
+ pHTCapabilityInfo->shortGI40MHz = (uint16_t) val2;
+ if (cfg_set_int
+ (pMac, WNI_CFG_HT_CAP_INFO,
+ *(uint16_t *) pHTCapabilityInfo) != eSIR_SUCCESS)
+ PELOGE(lim_log
+ (pMac, LOGE,
+ FL("could not update HT Cap Info CFG"));
+ )
+ break;
+ case WNI_CFG_MPDU_DENSITY:
+ if (wlan_cfg_get_int(pMac, WNI_CFG_HT_AMPDU_PARAMS, &val1) !=
+ eSIR_SUCCESS) {
+ PELOGE(lim_log
+ (pMac, LOGE,
+ FL("could not retrieve HT AMPDU Param CFG"));
+ )
+ break;
+ }
+ if (wlan_cfg_get_int(pMac, WNI_CFG_MPDU_DENSITY, &val2) !=
+ eSIR_SUCCESS) {
+ PELOGE(lim_log
+ (pMac, LOGE,
+ FL("could not retrieve MPDU Density CFG"));
+ )
+ break;
+ }
+ val16 = (uint16_t) val1;
+ pAmpduParamInfo = (tSirMacHTParametersInfo *) &val16;
+ pAmpduParamInfo->mpduDensity = (uint8_t) val2;
+ if (cfg_set_int
+ (pMac, WNI_CFG_HT_AMPDU_PARAMS,
+ *(uint8_t *) pAmpduParamInfo) != eSIR_SUCCESS)
+ PELOGE(lim_log
+ (pMac, LOGE,
+ FL("could not update HT AMPDU Param CFG"));
+ )
+
+ break;
+ case WNI_CFG_MAX_RX_AMPDU_FACTOR:
+ if (wlan_cfg_get_int(pMac, WNI_CFG_HT_AMPDU_PARAMS, &val1) !=
+ eSIR_SUCCESS) {
+ PELOGE(lim_log
+ (pMac, LOGE,
+ FL("could not retrieve HT AMPDU Param CFG"));
+ )
+ break;
+ }
+ if (wlan_cfg_get_int(pMac, WNI_CFG_MAX_RX_AMPDU_FACTOR, &val2) !=
+ eSIR_SUCCESS) {
+ PELOGE(lim_log
+ (pMac, LOGE,
+ FL("could not retrieve AMPDU Factor CFG"));
+ )
+ break;
+ }
+ val16 = (uint16_t) val1;
+ pAmpduParamInfo = (tSirMacHTParametersInfo *) &val16;
+ pAmpduParamInfo->maxRxAMPDUFactor = (uint8_t) val2;
+ if (cfg_set_int
+ (pMac, WNI_CFG_HT_AMPDU_PARAMS,
+ *(uint8_t *) pAmpduParamInfo) != eSIR_SUCCESS)
+ PELOGE(lim_log
+ (pMac, LOGE,
+ FL("could not update HT AMPDU Param CFG"));
+ )
+ break;
+
+ case WNI_CFG_DOT11_MODE:
+ if (wlan_cfg_get_int(pMac, WNI_CFG_DOT11_MODE, &val1) !=
+ eSIR_SUCCESS) {
+ PELOGE(lim_log
+ (pMac, LOGE,
+ FL("could not retrieve Dot11 Mode CFG"));
+ )
+ break;
+ }
+ break;
+
+ case WNI_CFG_SCAN_IN_POWERSAVE:
+ if (wlan_cfg_get_int(pMac, WNI_CFG_SCAN_IN_POWERSAVE, &val1) !=
+ eSIR_SUCCESS) {
+ lim_log(pMac, LOGE,
+ FL("Unable to get WNI_CFG_SCAN_IN_POWERSAVE "));
+ break;
+ }
+ pMac->lim.gScanInPowersave = (uint8_t) val1;
+ break;
+
+ case WNI_CFG_ASSOC_STA_LIMIT:
+ if (wlan_cfg_get_int(pMac, WNI_CFG_ASSOC_STA_LIMIT, &val1) !=
+ eSIR_SUCCESS) {
+ lim_log(pMac, LOGE,
+ FL("Unable to get WNI_CFG_ASSOC_STA_LIMIT"));
+ break;
+ }
+ pMac->lim.gLimAssocStaLimit = (uint16_t) val1;
+ break;
+ default:
+ break;
+ }
+} /*** end lim_handle_cf_gparam_update() ***/
+
+/**
+ * lim_apply_configuration()
+ *
+ ***FUNCTION:
+ * This function is called to apply the configured parameters
+ * before joining or reassociating with a BSS or starting a BSS.
+ *
+ ***PARAMS:
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ * NA
+ *
+ ***NOTE:
+ *
+ * @param pMac - Pointer to Global MAC structure
+ * @return None
+ */
+
+void lim_apply_configuration(tpAniSirGlobal pMac, tpPESession psessionEntry)
+{
+ uint32_t val = 0, phyMode;
+
+ PELOG2(lim_log(pMac, LOG2, FL("Applying config"));)
+
+ psessionEntry->limSentCapsChangeNtf = false;
+
+ lim_get_phy_mode(pMac, &phyMode, psessionEntry);
+
+ /* Set default keyId and keys */
+ lim_set_default_key_id_and_keys(pMac);
+
+ lim_update_config(pMac, psessionEntry);
+
+ lim_get_short_slot_from_phy_mode(pMac, psessionEntry, phyMode,
+ &psessionEntry->shortSlotTimeSupported);
+
+ lim_set_cfg_protection(pMac, psessionEntry);
+
+ /* Added for BT - AMP Support */
+ if (LIM_IS_AP_ROLE(psessionEntry) ||
+ LIM_IS_BT_AMP_AP_ROLE(psessionEntry) ||
+ LIM_IS_IBSS_ROLE(psessionEntry) ||
+ LIM_IS_BT_AMP_STA_ROLE(psessionEntry)) {
+ /* This check is required to ensure the beacon generation is not done
+ as a part of join request for a BT-AMP station */
+
+ if (psessionEntry->statypeForBss == STA_ENTRY_SELF) {
+ PELOG1(lim_log
+ (pMac, LOG1,
+ FL("Initializing BT-AMP beacon generation"));
+ )
+ sch_set_beacon_interval(pMac, psessionEntry);
+ sch_set_fixed_beacon_fields(pMac, psessionEntry);
+ }
+ }
+
+ if (wlan_cfg_get_int(pMac, WNI_CFG_SCAN_IN_POWERSAVE, &val) !=
+ eSIR_SUCCESS) {
+ lim_log(pMac, LOGP,
+ FL("could not retrieve WNI_CFG_SCAN_IN_POWERSAVE"));
+ return;
+ }
+
+ PELOG1(lim_log(pMac, LOG1, FL("pMac->lim.gScanInPowersave = %hu"),
+ pMac->lim.gScanInPowersave);
+ )
+ pMac->lim.gScanInPowersave = (uint8_t) val;
+
+} /*** end lim_apply_configuration() ***/
+
+/**
+ * lim_update_config
+ *
+ * FUNCTION:
+ * Update the local state from CFG database
+ * (This used to be dphUpdateConfig)
+ *
+ * LOGIC:
+ *
+ * ASSUMPTIONS:
+ *
+ * NOTE:
+ *
+ * @param None
+ * @return None
+ */
+
+static void lim_update_config(tpAniSirGlobal pMac, tpPESession psessionEntry)
+{
+ uint32_t val;
+
+ sir_copy_mac_addr(pMac->lim.gLimMyMacAddr, psessionEntry->selfMacAddr);
+
+ if (wlan_cfg_get_int(pMac, WNI_CFG_SHORT_PREAMBLE, &val) != eSIR_SUCCESS)
+ lim_log(pMac, LOGP, FL("cfg get short preamble failed"));
+ psessionEntry->beaconParams.fShortPreamble = (val) ? 1 : 0;
+
+ /* In STA case this parameter is filled during the join request */
+ if (LIM_IS_AP_ROLE(psessionEntry) ||
+ LIM_IS_IBSS_ROLE(psessionEntry)) {
+ if (wlan_cfg_get_int(pMac, WNI_CFG_WME_ENABLED, &val) !=
+ eSIR_SUCCESS)
+ lim_log(pMac, LOGP, FL("cfg get wme enabled failed"));
+ psessionEntry->limWmeEnabled = (val) ? 1 : 0;
+ }
+
+ if (wlan_cfg_get_int(pMac, WNI_CFG_WSM_ENABLED, &val) != eSIR_SUCCESS)
+ lim_log(pMac, LOGP, FL("cfg get wsm enabled failed"));
+ psessionEntry->limWsmEnabled = (val) ? 1 : 0;
+
+ if ((!psessionEntry->limWmeEnabled) && (psessionEntry->limWsmEnabled)) {
+ PELOGE(lim_log(pMac, LOGE, FL("Can't enable WSM without WME"));)
+ psessionEntry->limWsmEnabled = 0;
+ }
+ /* In STA , this parameter is filled during the join request */
+ if (LIM_IS_AP_ROLE(psessionEntry) || LIM_IS_IBSS_ROLE(psessionEntry)) {
+ if (wlan_cfg_get_int(pMac, WNI_CFG_QOS_ENABLED, &val) !=
+ eSIR_SUCCESS)
+ lim_log(pMac, LOGP, FL("cfg get qos enabled failed"));
+ psessionEntry->limQosEnabled = (val) ? 1 : 0;
+ }
+ if (wlan_cfg_get_int(pMac, WNI_CFG_HCF_ENABLED, &val) != eSIR_SUCCESS)
+ lim_log(pMac, LOGP, FL("cfg get hcf enabled failed"));
+ psessionEntry->limHcfEnabled = (val) ? 1 : 0;
+
+ /* AP: WSM should enable HCF as well, for STA enable WSM only after */
+ /* association response is received */
+ if (psessionEntry->limWsmEnabled && LIM_IS_AP_ROLE(psessionEntry))
+ psessionEntry->limHcfEnabled = 1;
+
+ if (wlan_cfg_get_int(pMac, WNI_CFG_11D_ENABLED, &val) != eSIR_SUCCESS)
+ lim_log(pMac, LOGP, FL("cfg get 11d enabled failed"));
+ psessionEntry->lim11dEnabled = (val) ? 1 : 0;
+
+ if (wlan_cfg_get_int(pMac, WNI_CFG_ASSOC_STA_LIMIT, &val) != eSIR_SUCCESS) {
+ lim_log(pMac, LOGP, FL("cfg get assoc sta limit failed"));
+ }
+ pMac->lim.gLimAssocStaLimit = (uint16_t) val;
+
+#if defined WLAN_FEATURE_VOWIFI
+ rrm_update_config(pMac, psessionEntry);
+#endif
+ PELOG1(lim_log(pMac, LOG1, FL("Updated Lim shadow state based on CFG"));)
+}
diff --git a/core/mac/src/pe/lim/lim_process_deauth_frame.c b/core/mac/src/pe/lim/lim_process_deauth_frame.c
new file mode 100644
index 0000000..e64058d
--- /dev/null
+++ b/core/mac/src/pe/lim/lim_process_deauth_frame.c
@@ -0,0 +1,596 @@
+/*
+ * Copyright (c) 2011-2014 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_process_deauth_frame.cc contains the code
+ * for processing Deauthentication Frame.
+ * Author: Chandra Modumudi
+ * Date: 03/24/02
+ * History:-
+ * Date Modified by Modification Information
+ * --------------------------------------------------------------------
+ *
+ */
+#include "cds_api.h"
+#include "ani_global.h"
+
+#include "utils_api.h"
+#include "lim_types.h"
+#include "lim_utils.h"
+#include "lim_assoc_utils.h"
+#include "lim_security_utils.h"
+#include "lim_ser_des_utils.h"
+#include "sch_api.h"
+#include "lim_send_messages.h"
+
+/**
+ * lim_process_deauth_frame
+ *
+ ***FUNCTION:
+ * This function is called by limProcessMessageQueue() upon
+ * Deauthentication frame reception.
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ *
+ ***NOTE:
+ *
+ * @param pMac - Pointer to Global MAC structure
+ * @param *pRxPacketInfo - A pointer to Buffer descriptor + associated PDUs
+ * @return None
+ */
+
+void
+lim_process_deauth_frame(tpAniSirGlobal pMac, uint8_t *pRxPacketInfo,
+ tpPESession psessionEntry)
+{
+ uint8_t *pBody;
+ uint16_t aid, reasonCode;
+ tpSirMacMgmtHdr pHdr;
+ tLimMlmAssocCnf mlmAssocCnf;
+ tLimMlmDeauthInd mlmDeauthInd;
+ tpDphHashNode pStaDs;
+ tpPESession pRoamSessionEntry = NULL;
+ uint8_t roamSessionId;
+#ifdef WLAN_FEATURE_11W
+ uint32_t frameLen;
+#endif
+
+ pHdr = WMA_GET_RX_MAC_HEADER(pRxPacketInfo);
+
+ pBody = WMA_GET_RX_MPDU_DATA(pRxPacketInfo);
+
+ if (LIM_IS_STA_ROLE(psessionEntry) &&
+ ((eLIM_SME_WT_DISASSOC_STATE == psessionEntry->limSmeState) ||
+ (eLIM_SME_WT_DEAUTH_STATE == psessionEntry->limSmeState))) {
+ /*Every 15th deauth frame will be logged in kmsg */
+ if (!(pMac->lim.deauthMsgCnt & 0xF)) {
+ PELOGE(lim_log(pMac, LOGE,
+ FL
+ ("received Deauth frame in DEAUTH_WT_STATE"
+ "(already processing previously received DEAUTH frame).."
+ "Dropping this.. Deauth Failed %d"),
+ ++pMac->lim.deauthMsgCnt);
+ )
+ } else {
+ pMac->lim.deauthMsgCnt++;
+ }
+ return;
+ }
+
+ if (lim_is_group_addr(pHdr->sa)) {
+ /* Received Deauth frame from a BC/MC address */
+ /* Log error and ignore it */
+ PELOGE(lim_log(pMac, LOGE,
+ FL("received Deauth frame from a BC/MC address"));
+ )
+
+ return;
+ }
+
+ if (lim_is_group_addr(pHdr->da) && !lim_is_addr_bc(pHdr->da)) {
+ /* Received Deauth frame for a MC address */
+ /* Log error and ignore it */
+ PELOGE(lim_log(pMac, LOGE,
+ FL("received Deauth frame for a MC address"));
+ )
+
+ return;
+ }
+ if (!lim_validate_received_frame_a1_addr(pMac,
+ pHdr->da, psessionEntry)) {
+ lim_log(pMac, LOGE,
+ FL("rx frame doesn't have valid a1 address, drop it"));
+ return;
+ }
+#ifdef WLAN_FEATURE_11W
+ /* PMF: If this session is a PMF session, then ensure that this frame was protected */
+ if (psessionEntry->limRmfEnabled
+ && (WMA_GET_RX_DPU_FEEDBACK(pRxPacketInfo) &
+ DPU_FEEDBACK_UNPROTECTED_ERROR)) {
+ PELOGE(lim_log
+ (pMac, LOGE,
+ FL("received an unprotected deauth from AP"));
+ )
+ /* If the frame received is unprotected, forward it to the supplicant to initiate */
+ /* an SA query */
+ frameLen = WMA_GET_RX_PAYLOAD_LEN(pRxPacketInfo);
+
+ /* send the unprotected frame indication to SME */
+ lim_send_sme_unprotected_mgmt_frame_ind(pMac, pHdr->fc.subType,
+ (uint8_t *) pHdr,
+ (frameLen +
+ sizeof(tSirMacMgmtHdr)),
+ psessionEntry->smeSessionId,
+ psessionEntry);
+ return;
+ }
+#endif
+
+ /* Get reasonCode from Deauthentication frame body */
+ reasonCode = sir_read_u16(pBody);
+
+ PELOGE(lim_log(pMac, LOGE,
+ FL("Received Deauth frame for Addr: " MAC_ADDRESS_STR
+ " (mlm state = %s,"
+ " sme state = %d systemrole = %d) with reason code %d [%s] from "
+ MAC_ADDRESS_STR), MAC_ADDR_ARRAY(pHdr->da),
+ lim_mlm_state_str(psessionEntry->limMlmState),
+ psessionEntry->limSmeState,
+ GET_LIM_SYSTEM_ROLE(psessionEntry),
+ reasonCode, lim_dot11_reason_str(reasonCode),
+ MAC_ADDR_ARRAY(pHdr->sa));
+ )
+
+ if (lim_check_disassoc_deauth_ack_pending(pMac, (uint8_t *) pHdr->sa)) {
+ PELOGE(lim_log(pMac, LOGE,
+ FL
+ ("Ignore the Deauth received, while waiting for ack of "
+ "disassoc/deauth"));
+ )
+ lim_clean_up_disassoc_deauth_req(pMac, (uint8_t *) pHdr->sa, 1);
+ return;
+ }
+
+ if (LIM_IS_AP_ROLE(psessionEntry) ||
+ LIM_IS_BT_AMP_AP_ROLE(psessionEntry)) {
+ switch (reasonCode) {
+ case eSIR_MAC_UNSPEC_FAILURE_REASON:
+ case eSIR_MAC_DEAUTH_LEAVING_BSS_REASON:
+ /* Valid reasonCode in received Deauthentication frame */
+ break;
+
+ default:
+ /* Invalid reasonCode in received Deauthentication frame */
+ /* Log error and ignore the frame */
+ PELOGE(lim_log(pMac, LOGE,
+ FL
+ ("received Deauth frame with invalid reasonCode %d from "
+ MAC_ADDRESS_STR), reasonCode,
+ MAC_ADDR_ARRAY(pHdr->sa));
+ )
+
+ break;
+ }
+ } else if (LIM_IS_STA_ROLE(psessionEntry) ||
+ LIM_IS_BT_AMP_STA_ROLE(psessionEntry)) {
+ switch (reasonCode) {
+ case eSIR_MAC_UNSPEC_FAILURE_REASON:
+ case eSIR_MAC_PREV_AUTH_NOT_VALID_REASON:
+ case eSIR_MAC_DEAUTH_LEAVING_BSS_REASON:
+ case eSIR_MAC_CLASS2_FRAME_FROM_NON_AUTH_STA_REASON:
+ case eSIR_MAC_CLASS3_FRAME_FROM_NON_ASSOC_STA_REASON:
+ case eSIR_MAC_STA_NOT_PRE_AUTHENTICATED_REASON:
+ /* Valid reasonCode in received Deauth frame */
+ break;
+
+ default:
+ /* Invalid reasonCode in received Deauth frame */
+ /* Log error and ignore the frame */
+ PELOGE(lim_log(pMac, LOGE,
+ FL
+ ("received Deauth frame with invalid reasonCode %d from "
+ MAC_ADDRESS_STR), reasonCode,
+ MAC_ADDR_ARRAY(pHdr->sa));
+ )
+
+ break;
+ }
+ } else {
+ /* Received Deauth frame in either IBSS */
+ /* or un-known role. Log and ignore it */
+ lim_log(pMac, LOGE,
+ FL
+ ("received Deauth frame with reasonCode %d in role %d from "
+ MAC_ADDRESS_STR), reasonCode,
+ GET_LIM_SYSTEM_ROLE(psessionEntry),
+ MAC_ADDR_ARRAY(pHdr->sa));
+
+ return;
+ }
+
+ /** If we are in the middle of ReAssoc, a few things could happen:
+ * - STA is reassociating to current AP, and receives deauth from:
+ * a) current AP
+ * b) other AP
+ * - STA is reassociating to a new AP, and receives deauth from:
+ * c) current AP
+ * d) reassoc AP
+ * e) other AP
+ *
+ * The logic is:
+ * 1) If rcv deauth from an AP other than the one we're trying to
+ * reassociate with, then drop the deauth frame (case b, c, e)
+ * 2) If rcv deauth from the "new" reassoc AP (case d), then restore
+ * context with previous AP and send SME_REASSOC_RSP failure.
+ * 3) If rcv deauth from the reassoc AP, which is also the same
+ * AP we're currently associated with (case a), then proceed
+ * with normal deauth processing.
+ */
+ if (psessionEntry->limReAssocbssId != NULL) {
+ pRoamSessionEntry =
+ pe_find_session_by_bssid(pMac, psessionEntry->limReAssocbssId,
+ &roamSessionId);
+ }
+ if (lim_is_reassoc_in_progress(pMac, psessionEntry)
+ || lim_is_reassoc_in_progress(pMac, pRoamSessionEntry)) {
+ if (!IS_REASSOC_BSSID(pMac, pHdr->sa, psessionEntry)) {
+ PELOGE(lim_log
+ (pMac, LOGE,
+ FL("Rcv Deauth from unknown/different "
+ "AP while ReAssoc. Ignore " MAC_ADDRESS_STR),
+ MAC_ADDR_ARRAY(pHdr->sa));
+ )
+ PELOGE(lim_log
+ (pMac, LOGE,
+ FL(" limReAssocbssId : " MAC_ADDRESS_STR),
+ MAC_ADDR_ARRAY(psessionEntry->
+ limReAssocbssId));
+ )
+ return;
+ }
+
+ /** Received deauth from the new AP to which we tried to ReAssociate.
+ * Drop ReAssoc and Restore the Previous context( current connected AP).
+ */
+ if (!IS_CURRENT_BSSID(pMac, pHdr->sa, psessionEntry)) {
+ PELOGE(lim_log
+ (pMac, LOGE,
+ FL("received DeAuth from the New AP to "
+ "which ReAssoc is sent " MAC_ADDRESS_STR),
+ MAC_ADDR_ARRAY(pHdr->sa));
+ )
+ PELOGE(lim_log
+ (pMac, LOGE,
+ FL(" psessionEntry->bssId: "
+ MAC_ADDRESS_STR),
+ MAC_ADDR_ARRAY(psessionEntry->bssId));
+ )
+ lim_restore_pre_reassoc_state(pMac,
+ eSIR_SME_REASSOC_REFUSED,
+ reasonCode,
+ psessionEntry);
+ return;
+ }
+ }
+
+ /* If received DeAuth from AP other than the one we're trying to join with
+ * nor associated with, then ignore deauth and delete Pre-auth entry.
+ */
+ if (!LIM_IS_AP_ROLE(psessionEntry)) {
+ if (!IS_CURRENT_BSSID(pMac, pHdr->bssId, psessionEntry)) {
+ PELOGE(lim_log
+ (pMac, LOGE,
+ FL("received DeAuth from an AP other "
+ "than we're trying to join. Ignore. "
+ MAC_ADDRESS_STR), MAC_ADDR_ARRAY(pHdr->sa));
+ )
+ if (lim_search_pre_auth_list(pMac, pHdr->sa)) {
+ PELOG1(lim_log
+ (pMac, LOG1,
+ FL("Preauth entry exist. "
+ "Deleting... "));
+ )
+ lim_delete_pre_auth_node(pMac, pHdr->sa);
+ }
+ return;
+ }
+ }
+
+ pStaDs =
+ dph_lookup_hash_entry(pMac, pHdr->sa, &aid,
+ &psessionEntry->dph.dphHashTable);
+
+ /* Check for pre-assoc states */
+ switch (GET_LIM_SYSTEM_ROLE(psessionEntry)) {
+ case eLIM_STA_ROLE:
+ case eLIM_BT_AMP_STA_ROLE:
+ switch (psessionEntry->limMlmState) {
+ case eLIM_MLM_WT_AUTH_FRAME2_STATE:
+ /**
+ * AP sent Deauth frame while waiting
+ * for Auth frame2. Report Auth failure
+ * to SME.
+ */
+
+ /* Log error */
+ PELOG1(lim_log(pMac, LOG1,
+ FL
+ ("received Deauth frame state %X with failure "
+ "code %d from " MAC_ADDRESS_STR),
+ psessionEntry->limMlmState, reasonCode,
+ MAC_ADDR_ARRAY(pHdr->sa));
+ )
+
+ lim_restore_from_auth_state(pMac,
+ eSIR_SME_DEAUTH_WHILE_JOIN,
+ reasonCode, psessionEntry);
+
+ return;
+
+ case eLIM_MLM_AUTHENTICATED_STATE:
+ lim_log(pMac, LOG1,
+ FL("received Deauth frame state %X with "
+ "reasonCode=%d from " MAC_ADDRESS_STR),
+ psessionEntry->limMlmState, reasonCode,
+ MAC_ADDR_ARRAY(pHdr->sa));
+ /* / Issue Deauth Indication to SME. */
+ cdf_mem_copy((uint8_t *) &mlmDeauthInd.peerMacAddr,
+ pHdr->sa, sizeof(tSirMacAddr));
+ mlmDeauthInd.reasonCode = reasonCode;
+
+ psessionEntry->limMlmState = eLIM_MLM_IDLE_STATE;
+ MTRACE(mac_trace
+ (pMac, TRACE_CODE_MLM_STATE,
+ psessionEntry->peSessionId,
+ psessionEntry->limMlmState));
+
+ lim_post_sme_message(pMac,
+ LIM_MLM_DEAUTH_IND,
+ (uint32_t *) &mlmDeauthInd);
+ return;
+
+ case eLIM_MLM_WT_ASSOC_RSP_STATE:
+ /**
+ * AP may have 'aged-out' our Pre-auth
+ * context. Delete local pre-auth context
+ * if any and issue ASSOC_CNF to SME.
+ */
+ lim_log(pMac, LOG1,
+ FL("received Deauth frame state %X with "
+ "reasonCode=%d from " MAC_ADDRESS_STR),
+ psessionEntry->limMlmState, reasonCode,
+ MAC_ADDR_ARRAY(pHdr->sa));
+ if (lim_search_pre_auth_list(pMac, pHdr->sa))
+ lim_delete_pre_auth_node(pMac, pHdr->sa);
+
+ if (psessionEntry->pLimMlmJoinReq) {
+ cdf_mem_free(psessionEntry->pLimMlmJoinReq);
+ psessionEntry->pLimMlmJoinReq = NULL;
+ }
+
+ mlmAssocCnf.resultCode = eSIR_SME_DEAUTH_WHILE_JOIN;
+ mlmAssocCnf.protStatusCode = reasonCode;
+
+ /* PE session Id */
+ mlmAssocCnf.sessionId = psessionEntry->peSessionId;
+
+ psessionEntry->limMlmState =
+ psessionEntry->limPrevMlmState;
+ MTRACE(mac_trace
+ (pMac, TRACE_CODE_MLM_STATE,
+ psessionEntry->peSessionId,
+ psessionEntry->limMlmState));
+
+ /* Deactive Association response timeout */
+ lim_deactivate_and_change_timer(pMac,
+ eLIM_ASSOC_FAIL_TIMER);
+
+ lim_post_sme_message(pMac,
+ LIM_MLM_ASSOC_CNF,
+ (uint32_t *) &mlmAssocCnf);
+
+ return;
+
+ case eLIM_MLM_WT_ADD_STA_RSP_STATE:
+ psessionEntry->fDeauthReceived = true;
+ PELOGW(lim_log(pMac, LOGW,
+ FL
+ ("Received Deauth frame in state %X with Reason "
+ "Code %d from Peer" MAC_ADDRESS_STR),
+ psessionEntry->limMlmState, reasonCode,
+ MAC_ADDR_ARRAY(pHdr->sa));
+ )
+ return;
+
+ case eLIM_MLM_IDLE_STATE:
+ case eLIM_MLM_LINK_ESTABLISHED_STATE:
+#ifdef FEATURE_WLAN_TDLS
+ if ((NULL != pStaDs)
+ && (STA_ENTRY_TDLS_PEER == pStaDs->staType)) {
+ PELOGE(lim_log
+ (pMac, LOGE,
+ FL
+ ("received Deauth frame in state %X with "
+ "reason code %d from Tdls peer"
+ MAC_ADDRESS_STR),
+ psessionEntry->limMlmState, reasonCode,
+ MAC_ADDR_ARRAY(pHdr->sa));
+ )
+ lim_send_sme_tdls_del_sta_ind(pMac, pStaDs,
+ psessionEntry,
+ reasonCode);
+ return;
+ } else {
+
+ /*
+ * Delete all the TDLS peers only if Deauth
+ * is received from the AP
+ */
+ if (IS_CURRENT_BSSID(pMac, pHdr->sa, psessionEntry))
+ lim_delete_tdls_peers(pMac, psessionEntry);
+#endif
+ /**
+ * This could be Deauthentication frame from
+ * a BSS with which pre-authentication was
+ * performed. Delete Pre-auth entry if found.
+ */
+ if (lim_search_pre_auth_list(pMac, pHdr->sa))
+ lim_delete_pre_auth_node(pMac, pHdr->sa);
+#ifdef FEATURE_WLAN_TDLS
+ }
+#endif
+ break;
+
+ case eLIM_MLM_WT_REASSOC_RSP_STATE:
+ lim_log(pMac, LOGE,
+ FL("received Deauth frame state %X with "
+ "reasonCode=%d from " MAC_ADDRESS_STR),
+ psessionEntry->limMlmState, reasonCode,
+ MAC_ADDR_ARRAY(pHdr->sa));
+ break;
+
+ case eLIM_MLM_WT_FT_REASSOC_RSP_STATE:
+ PELOGE(lim_log(pMac, LOGE,
+ FL
+ ("received Deauth frame in FT state %X with "
+ "reasonCode=%d from " MAC_ADDRESS_STR),
+ psessionEntry->limMlmState, reasonCode,
+ MAC_ADDR_ARRAY(pHdr->sa));
+ )
+ break;
+
+ default:
+ PELOGE(lim_log(pMac, LOGE,
+ FL
+ ("received Deauth frame in state %X with "
+ "reasonCode=%d from " MAC_ADDRESS_STR),
+ psessionEntry->limMlmState, reasonCode,
+ MAC_ADDR_ARRAY(pHdr->sa));
+ )
+ return;
+ }
+ break;
+
+ case eLIM_STA_IN_IBSS_ROLE:
+ break;
+
+ case eLIM_AP_ROLE:
+ break;
+
+ default: /* eLIM_AP_ROLE or eLIM_BT_AMP_AP_ROLE */
+
+ return;
+ } /* end switch (pMac->lim.gLimSystemRole) */
+
+ /**
+ * Extract 'associated' context for STA, if any.
+ * This is maintained by DPH and created by LIM.
+ */
+ if (NULL == pStaDs) {
+ lim_log(pMac, LOGE, FL("pStaDs is NULL"));
+ return;
+ }
+
+ if ((pStaDs->mlmStaContext.mlmState == eLIM_MLM_WT_DEL_STA_RSP_STATE) ||
+ (pStaDs->mlmStaContext.mlmState == eLIM_MLM_WT_DEL_BSS_RSP_STATE)) {
+ /**
+ * Already in the process of deleting context for the peer
+ * and received Deauthentication frame. Log and Ignore.
+ */
+ PELOGE(lim_log(pMac, LOGE,
+ FL
+ ("received Deauth frame from peer that is in state %X, addr "
+ MAC_ADDRESS_STR), pStaDs->mlmStaContext.mlmState,
+ MAC_ADDR_ARRAY(pHdr->sa));
+ )
+ return;
+ }
+ pStaDs->mlmStaContext.disassocReason = (tSirMacReasonCodes) reasonCode;
+ pStaDs->mlmStaContext.cleanupTrigger = eLIM_PEER_ENTITY_DEAUTH;
+
+ /* / Issue Deauth Indication to SME. */
+ cdf_mem_copy((uint8_t *) &mlmDeauthInd.peerMacAddr,
+ pStaDs->staAddr, sizeof(tSirMacAddr));
+ mlmDeauthInd.reasonCode =
+ (uint8_t) pStaDs->mlmStaContext.disassocReason;
+ mlmDeauthInd.deauthTrigger = eLIM_PEER_ENTITY_DEAUTH;
+
+ /*
+ * If we're in the middle of ReAssoc and received deauth from
+ * the ReAssoc AP, then notify SME by sending REASSOC_RSP with
+ * failure result code. SME will post the disconnect to the
+ * supplicant and the latter would start a fresh assoc.
+ */
+ if (lim_is_reassoc_in_progress(pMac, psessionEntry)) {
+ /**
+ * AP may have 'aged-out' our Pre-auth
+ * context. Delete local pre-auth context
+ * if any and issue REASSOC_CNF to SME.
+ */
+ if (lim_search_pre_auth_list(pMac, pHdr->sa))
+ lim_delete_pre_auth_node(pMac, pHdr->sa);
+
+ if (psessionEntry->limAssocResponseData) {
+ cdf_mem_free(psessionEntry->limAssocResponseData);
+ psessionEntry->limAssocResponseData = NULL;
+ }
+
+ PELOGE(lim_log(pMac, LOGE, FL("Rcv Deauth from ReAssoc AP. "
+ "Issue REASSOC_CNF. "));
+ )
+ /*
+ * TODO: Instead of overloading eSIR_SME_FT_REASSOC_TIMEOUT_FAILURE
+ * it would have been good to define/use a different failure type.
+ * Using eSIR_SME_FT_REASSOC_FAILURE does not seem to clean-up
+ * properly and we end up seeing "transmit queue timeout".
+ */
+ lim_post_reassoc_failure(pMac,
+ eSIR_SME_FT_REASSOC_TIMEOUT_FAILURE,
+ eSIR_MAC_UNSPEC_FAILURE_STATUS,
+ psessionEntry);
+ return;
+ }
+ /* reset the deauthMsgCnt here since we are able to Process
+ * the deauth frame and sending up the indication as well */
+ if (pMac->lim.deauthMsgCnt != 0) {
+ pMac->lim.deauthMsgCnt = 0;
+ }
+ if (LIM_IS_STA_ROLE(psessionEntry))
+ wma_tx_abort(psessionEntry->smeSessionId);
+
+ /* / Deauthentication from peer MAC entity */
+ lim_post_sme_message(pMac, LIM_MLM_DEAUTH_IND,
+ (uint32_t *) &mlmDeauthInd);
+
+ /* send eWNI_SME_DEAUTH_IND to SME */
+ lim_send_sme_deauth_ind(pMac, pStaDs, psessionEntry);
+ return;
+
+} /*** end lim_process_deauth_frame() ***/
diff --git a/core/mac/src/pe/lim/lim_process_disassoc_frame.c b/core/mac/src/pe/lim/lim_process_disassoc_frame.c
new file mode 100644
index 0000000..33a1c08
--- /dev/null
+++ b/core/mac/src/pe/lim/lim_process_disassoc_frame.c
@@ -0,0 +1,390 @@
+/*
+ * Copyright (c) 2011-2015 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_process_disassoc_frame.cc contains the code
+ * for processing Disassocation Frame.
+ * Author: Chandra Modumudi
+ * Date: 03/24/02
+ * History:-
+ * Date Modified by Modification Information
+ * --------------------------------------------------------------------
+ *
+ */
+#include "cds_api.h"
+#include "wni_api.h"
+#include "sir_api.h"
+#include "ani_global.h"
+#include "wni_cfg.h"
+
+#include "utils_api.h"
+#include "lim_types.h"
+#include "lim_utils.h"
+#include "lim_assoc_utils.h"
+#include "lim_security_utils.h"
+#include "lim_ser_des_utils.h"
+#include "lim_send_messages.h"
+#include "sch_api.h"
+
+/**
+ * lim_process_disassoc_frame
+ *
+ ***FUNCTION:
+ * This function is called by limProcessMessageQueue() upon
+ * Disassociation frame reception.
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ * DPH drops packets for STA with 'valid' bit in pStaDs set to '0'.
+ *
+ ***NOTE:
+ *
+ * @param pMac - Pointer to Global MAC structure
+ * @param *pRxPacketInfo - A pointer to Rx packet info structure
+ * @return None
+ */
+void
+lim_process_disassoc_frame(tpAniSirGlobal pMac, uint8_t *pRxPacketInfo,
+ tpPESession psessionEntry)
+{
+ uint8_t *pBody;
+ uint16_t aid, reasonCode;
+ tpSirMacMgmtHdr pHdr;
+ tpDphHashNode pStaDs;
+ tLimMlmDisassocInd mlmDisassocInd;
+#ifdef WLAN_FEATURE_11W
+ uint32_t frameLen;
+#endif
+
+ pHdr = WMA_GET_RX_MAC_HEADER(pRxPacketInfo);
+ pBody = WMA_GET_RX_MPDU_DATA(pRxPacketInfo);
+
+ if (lim_is_group_addr(pHdr->sa)) {
+ /* Received Disassoc frame from a BC/MC address */
+ /* Log error and ignore it */
+ PELOGE(lim_log(pMac, LOGE,
+ FL
+ ("received Disassoc frame from a BC/MC address"));
+ )
+
+ return;
+ }
+
+ if (lim_is_group_addr(pHdr->da) && !lim_is_addr_bc(pHdr->da)) {
+ /* Received Disassoc frame for a MC address */
+ /* Log error and ignore it */
+ PELOGE(lim_log(pMac, LOGE,
+ FL("received Disassoc frame for a MC address"));
+ )
+
+ return;
+ }
+ if (!lim_validate_received_frame_a1_addr(pMac,
+ pHdr->da, psessionEntry)) {
+ lim_log(pMac, LOGE,
+ FL("rx frame doesn't have valid a1 address, drop it"));
+ return;
+ }
+
+ if (LIM_IS_STA_ROLE(psessionEntry) &&
+ (eLIM_SME_WT_DISASSOC_STATE == psessionEntry->limSmeState)) {
+ if (pHdr->fc.retry > 0) {
+ /*
+ * This can happen when first disassoc frame is received
+ * but ACK from this STA is lost, in this case 2nd
+ * disassoc frame is already in transmission queue
+ */
+ lim_log(pMac, LOGE,
+ FL("AP is sending disassoc after ACK lost..."));
+ return;
+ }
+ }
+#ifdef WLAN_FEATURE_11W
+ /* PMF: If this session is a PMF session, then ensure that this frame was protected */
+ if (psessionEntry->limRmfEnabled
+ && (WMA_GET_RX_DPU_FEEDBACK(pRxPacketInfo) &
+ DPU_FEEDBACK_UNPROTECTED_ERROR)) {
+ PELOGE(lim_log
+ (pMac, LOGE,
+ FL("received an unprotected disassoc from AP"));
+ )
+ /* If the frame received is unprotected, forward it to the supplicant to initiate */
+ /* an SA query */
+ frameLen = WMA_GET_RX_PAYLOAD_LEN(pRxPacketInfo);
+ /* send the unprotected frame indication to SME */
+ lim_send_sme_unprotected_mgmt_frame_ind(pMac, pHdr->fc.subType,
+ (uint8_t *) pHdr,
+ (frameLen +
+ sizeof(tSirMacMgmtHdr)),
+ psessionEntry->smeSessionId,
+ psessionEntry);
+ return;
+ }
+#endif
+
+ /* Get reasonCode from Disassociation frame body */
+ reasonCode = sir_read_u16(pBody);
+
+ PELOG2(lim_log(pMac, LOGE,
+ FL("Received Disassoc frame for Addr: " MAC_ADDRESS_STR
+ "(mlm state=%s, sme state=%d),"
+ "with reason code %d [%s] from " MAC_ADDRESS_STR),
+ MAC_ADDR_ARRAY(pHdr->da),
+ lim_mlm_state_str(psessionEntry->limMlmState),
+ psessionEntry->limSmeState, reasonCode,
+ lim_dot11_reason_str(reasonCode), MAC_ADDR_ARRAY(pHdr->sa));
+ )
+
+ /**
+ * Extract 'associated' context for STA, if any.
+ * This is maintained by DPH and created by LIM.
+ */
+ pStaDs =
+ dph_lookup_hash_entry(pMac, pHdr->sa, &aid,
+ &psessionEntry->dph.dphHashTable);
+
+ if (pStaDs == NULL) {
+ /**
+ * Disassociating STA is not associated.
+ * Log error.
+ */
+ PELOGE(lim_log(pMac, LOGE,
+ FL
+ ("received Disassoc frame from STA that does not have context "
+ "reasonCode=%d, addr " MAC_ADDRESS_STR),
+ reasonCode, MAC_ADDR_ARRAY(pHdr->sa));
+ )
+
+ return;
+ }
+
+ if (lim_check_disassoc_deauth_ack_pending(pMac, (uint8_t *) pHdr->sa)) {
+ PELOGE(lim_log(pMac, LOGE,
+ FL("Ignore the DisAssoc received, while waiting "
+ "for ack of disassoc/deauth"));
+ )
+ lim_clean_up_disassoc_deauth_req(pMac, (uint8_t *) pHdr->sa, 1);
+ return;
+ }
+
+ /** If we are in the Wait for ReAssoc Rsp state */
+ if (lim_is_reassoc_in_progress(pMac, psessionEntry)) {
+ /** If we had received the DisAssoc from,
+ * a. the Current AP during ReAssociate to different AP in same ESS
+ * b. Unknown AP
+ * drop/ignore the DisAssoc received
+ */
+ if (!IS_REASSOC_BSSID(pMac, pHdr->sa, psessionEntry)) {
+ PELOGE(lim_log
+ (pMac, LOGE,
+ FL("Ignore the DisAssoc received, while "
+ "Processing ReAssoc with different/unknown AP"));
+ )
+ return;
+ }
+ /** If the Disassoc is received from the new AP to which we tried to ReAssociate
+ * Drop ReAssoc and Restore the Previous context( current connected AP).
+ */
+ if (!IS_CURRENT_BSSID(pMac, pHdr->sa, psessionEntry)) {
+ PELOGW(lim_log
+ (pMac, LOGW,
+ FL
+ ("received Disassoc from the New AP to which ReAssoc is sent "));
+ )
+ lim_restore_pre_reassoc_state(pMac,
+ eSIR_SME_REASSOC_REFUSED,
+ reasonCode,
+ psessionEntry);
+ return;
+ }
+ }
+
+ if (LIM_IS_AP_ROLE(psessionEntry) ||
+ LIM_IS_BT_AMP_AP_ROLE(psessionEntry)) {
+ switch (reasonCode) {
+ case eSIR_MAC_UNSPEC_FAILURE_REASON:
+ case eSIR_MAC_DISASSOC_DUE_TO_INACTIVITY_REASON:
+ case eSIR_MAC_DISASSOC_LEAVING_BSS_REASON:
+ case eSIR_MAC_MIC_FAILURE_REASON:
+ case eSIR_MAC_4WAY_HANDSHAKE_TIMEOUT_REASON:
+ case eSIR_MAC_GR_KEY_UPDATE_TIMEOUT_REASON:
+ case eSIR_MAC_RSN_IE_MISMATCH_REASON:
+ case eSIR_MAC_1X_AUTH_FAILURE_REASON:
+ /* Valid reasonCode in received Disassociation frame */
+ break;
+
+ default:
+ /* Invalid reasonCode in received Disassociation frame */
+ PELOGE(lim_log(pMac, LOGE,
+ FL
+ ("received Disassoc frame with invalid reasonCode "
+ "%d from " MAC_ADDRESS_STR), reasonCode,
+ MAC_ADDR_ARRAY(pHdr->sa));
+ )
+ break;
+ }
+ } else if ((LIM_IS_STA_ROLE(psessionEntry) ||
+ LIM_IS_BT_AMP_STA_ROLE(psessionEntry)) &&
+ ((psessionEntry->limSmeState != eLIM_SME_WT_JOIN_STATE) &&
+ (psessionEntry->limSmeState != eLIM_SME_WT_AUTH_STATE) &&
+ (psessionEntry->limSmeState != eLIM_SME_WT_ASSOC_STATE) &&
+ (psessionEntry->limSmeState != eLIM_SME_WT_REASSOC_STATE))) {
+ switch (reasonCode) {
+ case eSIR_MAC_UNSPEC_FAILURE_REASON:
+ case eSIR_MAC_DISASSOC_DUE_TO_INACTIVITY_REASON:
+ case eSIR_MAC_DISASSOC_DUE_TO_DISABILITY_REASON:
+ case eSIR_MAC_CLASS2_FRAME_FROM_NON_AUTH_STA_REASON:
+ case eSIR_MAC_CLASS3_FRAME_FROM_NON_ASSOC_STA_REASON:
+ case eSIR_MAC_MIC_FAILURE_REASON:
+ case eSIR_MAC_4WAY_HANDSHAKE_TIMEOUT_REASON:
+ case eSIR_MAC_GR_KEY_UPDATE_TIMEOUT_REASON:
+ case eSIR_MAC_RSN_IE_MISMATCH_REASON:
+ case eSIR_MAC_1X_AUTH_FAILURE_REASON:
+ case eSIR_MAC_PREV_AUTH_NOT_VALID_REASON:
+ /* Valid reasonCode in received Disassociation frame */
+ break;
+
+ case eSIR_MAC_DEAUTH_LEAVING_BSS_REASON:
+ case eSIR_MAC_DISASSOC_LEAVING_BSS_REASON:
+ /* Valid reasonCode in received Disassociation frame */
+ /* as long as we're not about to channel switch */
+ if (psessionEntry->gLimChannelSwitch.state !=
+ eLIM_CHANNEL_SWITCH_IDLE) {
+ lim_log(pMac, LOGE,
+ FL
+ ("Ignoring disassoc frame due to upcoming "
+ "channel switch, from "
+ MAC_ADDRESS_STR),
+ MAC_ADDR_ARRAY(pHdr->sa));
+ return;
+ }
+ break;
+
+ default:
+ /* Invalid reasonCode in received Disassociation frame */
+ /* Log error and ignore the frame */
+ PELOGE(lim_log(pMac, LOGE,
+ FL
+ ("received Disassoc frame with invalid reasonCode "
+ "%d from " MAC_ADDRESS_STR), reasonCode,
+ MAC_ADDR_ARRAY(pHdr->sa));
+ )
+ return;
+ }
+ } else {
+ /* Received Disassociation frame in either IBSS */
+ /* or un-known role. Log and ignore it */
+ lim_log(pMac, LOGE,
+ FL
+ ("received Disassoc frame with invalid reasonCode %d in role "
+ "%d in sme state %d from " MAC_ADDRESS_STR), reasonCode,
+ GET_LIM_SYSTEM_ROLE(psessionEntry), psessionEntry->limSmeState,
+ MAC_ADDR_ARRAY(pHdr->sa));
+
+ return;
+ }
+
+ if ((pStaDs->mlmStaContext.mlmState == eLIM_MLM_WT_DEL_STA_RSP_STATE) ||
+ (pStaDs->mlmStaContext.mlmState == eLIM_MLM_WT_DEL_BSS_RSP_STATE)) {
+ /**
+ * Already in the process of deleting context for the peer
+ * and received Disassociation frame. Log and Ignore.
+ */
+ PELOGE(lim_log(pMac, LOGE,
+ FL("received Disassoc frame in state %d from "
+ MAC_ADDRESS_STR),
+ pStaDs->mlmStaContext.mlmState,
+ MAC_ADDR_ARRAY(pHdr->sa));
+ )
+
+ return;
+ }
+
+ if (pStaDs->mlmStaContext.mlmState != eLIM_MLM_LINK_ESTABLISHED_STATE) {
+ /**
+ * Requesting STA is in some 'transient' state?
+ * Log error.
+ */
+ if (pStaDs->mlmStaContext.mlmState ==
+ eLIM_MLM_WT_ASSOC_CNF_STATE)
+ pStaDs->mlmStaContext.updateContext = 1;
+
+ PELOGE(lim_log(pMac, LOGE,
+ FL
+ ("received Disassoc frame from peer that is in state %X, addr "
+ MAC_ADDRESS_STR), pStaDs->mlmStaContext.mlmState,
+ MAC_ADDR_ARRAY(pHdr->sa));
+ )
+
+ } /* if (pStaDs->mlmStaContext.mlmState != eLIM_MLM_LINK_ESTABLISHED_STATE) */
+
+ pStaDs->mlmStaContext.cleanupTrigger = eLIM_PEER_ENTITY_DISASSOC;
+ pStaDs->mlmStaContext.disassocReason = (tSirMacReasonCodes) reasonCode;
+
+ /* Issue Disassoc Indication to SME. */
+ cdf_mem_copy((uint8_t *) &mlmDisassocInd.peerMacAddr,
+ (uint8_t *) pStaDs->staAddr, sizeof(tSirMacAddr));
+ mlmDisassocInd.reasonCode =
+ (uint8_t) pStaDs->mlmStaContext.disassocReason;
+ mlmDisassocInd.disassocTrigger = eLIM_PEER_ENTITY_DISASSOC;
+
+ /* Update PE session Id */
+ mlmDisassocInd.sessionId = psessionEntry->peSessionId;
+
+ if (lim_is_reassoc_in_progress(pMac, psessionEntry)) {
+
+ /* If we're in the middle of ReAssoc and received disassoc from
+ * the ReAssoc AP, then notify SME by sending REASSOC_RSP with
+ * failure result code. By design, SME will then issue "Disassoc"
+ * and cleanup will happen at that time.
+ */
+ PELOGE(lim_log
+ (pMac, LOGE,
+ FL("received Disassoc from AP while waiting "
+ "for Reassoc Rsp"));
+ )
+
+ if (psessionEntry->limAssocResponseData) {
+ cdf_mem_free(psessionEntry->limAssocResponseData);
+ psessionEntry->limAssocResponseData = NULL;
+ }
+
+ lim_restore_pre_reassoc_state(pMac, eSIR_SME_REASSOC_REFUSED,
+ reasonCode, psessionEntry);
+ return;
+ }
+
+ lim_post_sme_message(pMac, LIM_MLM_DISASSOC_IND,
+ (uint32_t *) &mlmDisassocInd);
+
+ /* send eWNI_SME_DISASSOC_IND to SME */
+ lim_send_sme_disassoc_ind(pMac, pStaDs, psessionEntry);
+
+ return;
+} /*** end lim_process_disassoc_frame() ***/
diff --git a/core/mac/src/pe/lim/lim_process_message_queue.c b/core/mac/src/pe/lim/lim_process_message_queue.c
new file mode 100644
index 0000000..25e7ed1
--- /dev/null
+++ b/core/mac/src/pe/lim/lim_process_message_queue.c
@@ -0,0 +1,2098 @@
+/*
+ * Copyright (c) 2011-2015 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"
+#ifdef WLAN_FEATURE_VOWIFI_11R
+#include "lim_ft_defs.h"
+#endif
+#include "lim_session.h"
+#include "lim_send_messages.h"
+
+#if defined WLAN_FEATURE_VOWIFI
+#include "rrm_api.h"
+#endif
+
+#if defined WLAN_FEATURE_VOWIFI_11R
+#include "lim_ft.h"
+#endif
+
+#include "cdf_types.h"
+#include "cds_packet.h"
+#include "cdf_memory.h"
+
+void lim_log_session_states(tpAniSirGlobal pMac);
+static void lim_process_normal_hdd_msg(tpAniSirGlobal mac_ctx,
+ struct sSirMsgQ *msg, uint8_t rsp_reqd);
+
+/**
+ * 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;
+ tSirMsgQ msg;
+
+ resp = (struct sir_dual_mac_config_resp *)body;
+ if (!resp) {
+ lim_log(mac, LOGE, FL("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 = cdf_mem_malloc(len);
+ if (!param) {
+ lim_log(mac, LOGE, FL("Fail to allocate memory"));
+ /* Memory allocation for param failed.
+ * Cannot send fail status back to SME
+ */
+ return;
+ }
+
+ if (fail_resp) {
+ lim_log(mac, LOGE, FL("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;
+ lim_log(mac, LOG1, FL("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;
+ tSirMsgQ msg;
+
+ resp = (struct sir_set_hw_mode_resp *)body;
+ if (!resp) {
+ lim_log(mac, LOGE, FL("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 = cdf_mem_malloc(len);
+ if (!param) {
+ lim_log(mac, LOGE, FL("Fail to allocate memory"));
+ /* Memory allocation for param failed.
+ * Cannot send fail status back to SME
+ */
+ return;
+ }
+
+ if (fail_resp) {
+ lim_log(mac, LOGE, FL("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;
+ lim_log(mac, LOGE, FL("Send eWNI_SME_SET_HW_MODE_RESP to SME"));
+ lim_sys_process_mmh_msg_api(mac, &msg, ePROT);
+ return;
+}
+
+/**
+ * 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;
+ tSirMsgQ msg;
+
+ ind = (struct sir_hw_mode_trans_ind *)body;
+ if (!ind) {
+ lim_log(mac, LOGE, FL("Set HW mode trans ind param is NULL"));
+ return;
+ }
+
+ len = sizeof(*param);
+
+ param = cdf_mem_malloc(len);
+ if (!param) {
+ lim_log(mac, LOGE, FL("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;
+ lim_log(mac, LOGE, FL("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 tSirMsgQ limMsg
+ \param tSirMacTspecIE *ppInfo
+ \return none
+ -------------------------------------------------------------*/
+
+uint8_t static def_msg_decision(tpAniSirGlobal pMac, tpSirMsgQ limMsg)
+{
+
+/* 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) {
+ CDF_TRACE(CDF_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 != WMA_ADD_BSS_RSP)
+ && (limMsg->type != WMA_DELETE_BSS_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) &&
+#ifdef FEATURE_OEM_DATA_SUPPORT
+ (limMsg->type != WMA_START_OEM_DATA_RSP) &&
+#endif
+ (limMsg->type != WMA_ADD_TS_RSP)) {
+ PELOG1(lim_log
+ (pMac, LOG1,
+ FL
+ ("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) {
+ CDF_TRACE(CDF_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;
+ tSirMsgQ mmh_msg;
+ 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 = cdf_mem_malloc(len);
+ if (NULL == result) {
+ lim_log(pmac, LOGE, FL("Memory allocation failed"));
+ return;
+ }
+ hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info);
+ body = WMA_GET_RX_MPDU_DATA(rx_pkt_info);
+ cdf_mem_zero(result, sizeof(*result) + ie_len);
+
+ /* 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 = cdf_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_DB(rx_pkt_info);
+ result->ap[i].rtt = 0;
+ result->ap[i].rtt_sd = 0;
+ result->ap[i].ieLength = ie_len;
+ cdf_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';
+ cdf_mem_copy((uint8_t *) &result->ap[i].bssid,
+ (uint8_t *) hdr->bssId,
+ sizeof(tSirMacAddr));
+ /* Copy IE fields */
+ cdf_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;
+ tSirMsgQ mmh_msg;
+ tpSirMacMgmtHdr hdr;
+
+ result = cdf_mem_malloc(sizeof(*result) + ie_len);
+ if (NULL == result) {
+ lim_log(pmac, LOGE, FL("Memory allocation failed"));
+ return;
+ }
+ hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info);
+ body = WMA_GET_RX_MPDU_DATA(rx_pkt_info);
+ cdf_mem_zero(result, sizeof(*result) + ie_len);
+
+ /* Received frame does not have request id, hence set 0 */
+ result->requestId = 0;
+
+ result->moreData = 0;
+ result->ap.ts = cdf_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_DB(rx_pkt_info);
+ result->ap.rtt = 0;
+ result->ap.rtt_sd = 0;
+ result->ap.ieLength = ie_len;
+
+ cdf_mem_copy((uint8_t *) &result->ap.ssid[0],
+ (uint8_t *) frame->ssId.ssId, frame->ssId.length);
+ result->ap.ssid[frame->ssId.length] = '\0';
+ cdf_mem_copy((uint8_t *) &result->ap.bssid.bytes,
+ (uint8_t *) hdr->bssId,
+ CDF_MAC_ADDR_SIZE);
+ /* Copy IE fields */
+ cdf_mem_copy((uint8_t *) &result->ap.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_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) {
+ lim_log(pmac, LOGP,
+ FL("RX packet has invalid length %d"), frm_len);
+ return;
+ }
+
+ frame = cdf_mem_malloc(sizeof(*frame));
+ if (NULL == frame) {
+ lim_log(pmac, LOGE, FL("Memory allocation failed"));
+ return;
+ }
+
+ if (sub_type == SIR_MAC_MGMT_BEACON) {
+ lim_log(pmac, LOG2, FL("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) {
+ lim_log(pmac, LOG2, FL("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 {
+ cdf_mem_free(frame);
+ return;
+ }
+
+ if (status != eSIR_SUCCESS) {
+ lim_log(pmac, LOGE, FL("Frame parsing failed"));
+ cdf_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);
+
+ cdf_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, tpSirMsgQ pMsg,
+ tpPESession psessionEntry)
+{
+ /* checking for global SME state... */
+ 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 tSirMsgQ - Pointer to the message structure
+ * @return None
+ */
+
+uint32_t lim_defer_msg(tpAniSirGlobal pMac, tSirMsgQ *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 {
+ lim_log(pMac, LOGE, FL("Dropped lim message (0x%X)"),
+ 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)) {
+ CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_INFO_HIGH,
+ FL("Ignoring A2 Invalid Packet received for MC/BC:"));
+ lim_print_mac_addr(mac_ctx, mac_hdr->addr2, LOG2);
+ return;
+ }
+ CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_INFO,
+ 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;
+ CDF_STATUS cdf_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);
+
+ cdf_mutex_acquire(&mac_ctx->lim.lim_frame_register_lock);
+ cdf_list_peek_front(&mac_ctx->lim.gLimMgmtFrameRegistratinQueue,
+ (cdf_list_node_t **) &mgmt_frame);
+ cdf_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)) {
+ CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_INFO_HIGH,
+ 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 &&
+ cdf_mem_compare(mgmt_frame->matchData, body,
+ mgmt_frame->matchLen)) {
+ /* found match! */
+ match = true;
+ break;
+ }
+ }
+
+ cdf_mutex_acquire(&mac_ctx->lim.lim_frame_register_lock);
+ cdf_status =
+ cdf_list_peek_next(
+ &mac_ctx->lim.gLimMgmtFrameRegistratinQueue,
+ (cdf_list_node_t *) mgmt_frame,
+ (cdf_list_node_t **) &next_frm);
+ cdf_mutex_release(&mac_ctx->lim.lim_frame_register_lock);
+ mgmt_frame = next_frm;
+ next_frm = NULL;
+ }
+
+ if (match) {
+ CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_INFO,
+ 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, 0);
+
+ 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 tSirMsgQ - Pointer to the message structure
+ * @return None
+ */
+
+static void
+lim_handle80211_frames(tpAniSirGlobal pMac, tpSirMsgQ limMsg, uint8_t *pDeferMsg)
+{
+ uint8_t *pRxPacketInfo = NULL;
+ tSirMacFrameCtl fc;
+ tpSirMacMgmtHdr pHdr = NULL;
+ tpPESession psessionEntry = NULL;
+ uint8_t sessionId;
+ tAniBool isFrmFt = 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);
+ fc = pHdr->fc;
+
+#ifdef WLAN_DUMP_MGMTFRAMES
+ lim_log(pMac, LOGE,
+ FL("ProtVersion %d, Type %d, Subtype %d rateIndex=%d"),
+ fc.protVer, fc.type, fc.subType,
+ WMA_GET_RX_MAC_RATE_IDX(pRxPacketInfo));
+ CDF_TRACE_HEX_DUMP(CDF_MODULE_ID_PE, CDF_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)) {
+ lim_log(pMac, LOGE,
+ FL("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 {
+ lim_log(pMac, LOGE,
+ FL("Wrong frameType %d, Subtype %d for %d"),
+ fc.type, fc.subType,
+ WMA_GET_SCAN_SRC(pRxPacketInfo));
+ }
+ goto end;
+ }
+#endif
+ if (WMA_GET_OFFLOADSCANLEARN(pRxPacketInfo)) {
+ if (fc.subType == SIR_MAC_MGMT_BEACON) {
+ lim_log(pMac, LOG2, FL("Learning scan beacon"));
+ __lim_handle_beacon(pMac, limMsg, NULL);
+ } else if (fc.subType == SIR_MAC_MGMT_PROBE_RSP) {
+ lim_log(pMac, LOG2, FL("Learning scan probe rsp"));
+ lim_process_probe_rsp_frame_no_session(pMac, pRxPacketInfo);
+ } else {
+ lim_log(pMac, LOGE,
+ FL("Wrong frame Type %d, Subtype %d for LFR"),
+ fc.type, fc.subType);
+ }
+ goto end;
+ }
+ /* Added For BT-AMP Support */
+ if ((psessionEntry =
+ pe_find_session_by_bssid(pMac, pHdr->bssId,
+ &sessionId)) == NULL) {
+#ifdef WLAN_FEATURE_VOWIFI_11R
+ if (fc.subType == SIR_MAC_MGMT_AUTH) {
+#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG
+ lim_log(pMac, LOG1,
+ FL
+ ("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, LOG1);
+#endif
+ if (lim_process_auth_frame_no_session
+ (pMac, pRxPacketInfo,
+ limMsg->bodyptr) == eSIR_SUCCESS) {
+ lim_pkt_free(pMac, TXRX_FRM_802_11_MGMT,
+ pRxPacketInfo, limMsg->bodyptr);
+ return;
+ }
+ }
+#endif
+ 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) /* Public action frame can be received from non-associated stations. */
+ ) {
+
+ if ((psessionEntry =
+ pe_find_session_by_peer_sta(pMac, pHdr->sa,
+ &sessionId)) == NULL) {
+ lim_log(pMac, LOG1,
+ FL
+ ("session does not exist for given bssId"));
+ lim_pkt_free(pMac, TXRX_FRM_802_11_MGMT,
+ pRxPacketInfo, limMsg->bodyptr);
+ return;
+ } else
+ lim_log(pMac, LOG1,
+ "SessionId:%d Session Exist 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)) {
+ lim_log(pMac, LOG1, FL("Received frame is passed to SME"));
+ lim_pkt_free(pMac, TXRX_FRM_802_11_MGMT, pRxPacketInfo,
+ limMsg->bodyptr);
+ return;
+ }
+
+ if (fc.protVer != SIR_MAC_PROTOCOL_VERSION) { /* Received Frame with non-zero Protocol Version */
+ lim_log(pMac, LOGE,
+ FL("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
+ return;
+ }
+
+/* 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_BT_AMP_AP_ROLE(psessionEntry) ||
+ LIM_IS_AP_ROLE(psessionEntry))
+ lim_process_assoc_req_frame(pMac,
+ pRxPacketInfo,
+ LIM_ASSOC,
+ psessionEntry);
+ else {
+ /* Unwanted messages - Log error */
+ lim_log(pMac, LOGE,
+ FL
+ ("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_BT_AMP_AP_ROLE(psessionEntry) ||
+ LIM_IS_AP_ROLE(psessionEntry)) {
+ lim_process_assoc_req_frame(pMac,
+ pRxPacketInfo,
+ LIM_REASSOC,
+ psessionEntry);
+ } else {
+ /* Unwanted messages - Log error */
+ lim_log(pMac, LOGE,
+ FL
+ ("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 == NULL)
+ lim_process_probe_rsp_frame_no_session(pMac,
+ pRxPacketInfo);
+ else
+ 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() ***/
+
+/**
+ * lim_send_stop_scan_offload_req()
+ *
+ ***FUNCTION:
+ * This function will be called to abort the ongoing offloaded scan
+ * request.
+ *
+ *
+ ***NOTE:
+ *
+ * @param pMac Pointer to Global MAC structure
+ * @return CDF_STATUS_SUCCESS or CDF_STATUS_E_FAILURE
+ */
+CDF_STATUS lim_send_stop_scan_offload_req(tpAniSirGlobal pMac,
+ uint8_t SessionId, uint32_t scan_id)
+{
+ tSirMsgQ msg;
+ tSirRetStatus rc = eSIR_SUCCESS;
+ tAbortScanParams *pAbortScanParams;
+
+ pAbortScanParams = cdf_mem_malloc(sizeof(tAbortScanParams));
+ if (NULL == pAbortScanParams) {
+ lim_log(pMac, LOGP,
+ FL("Memory allocation failed for AbortScanParams"));
+ return CDF_STATUS_E_NOMEM;
+ }
+
+ pAbortScanParams->SessionId = SessionId;
+ pAbortScanParams->scan_id = scan_id;
+ msg.type = WMA_STOP_SCAN_OFFLOAD_REQ;
+ msg.bodyptr = pAbortScanParams;
+ msg.bodyval = 0;
+
+ rc = wma_post_ctrl_msg(pMac, &msg);
+ if (rc != eSIR_SUCCESS) {
+ lim_log(pMac, LOGE, FL("wma_post_ctrl_msg() return failure"));
+ cdf_mem_free(pAbortScanParams);
+ return CDF_STATUS_E_FAILURE;
+ }
+
+ lim_log(pMac, LOG1, FL("Abort ongoing offload scan."));
+ return CDF_STATUS_SUCCESS;
+
+}
+
+/**
+ * lim_process_abort_scan_ind()
+ *
+ ***FUNCTION:
+ * This function is called from HDD to abort the scan which is presently being run
+ *
+ *
+ ***NOTE:
+ *
+ * @param pMac Pointer to Global MAC structure
+ * @param *pMsgBuf A pointer to the SME message buffer
+ * @return None
+ */
+void lim_process_abort_scan_ind(tpAniSirGlobal mac_ctx,
+ uint8_t session_id, uint32_t scan_id)
+{
+#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM
+ lim_diag_event_report(mac_ctx, WLAN_PE_DIAG_SCAN_ABORT_IND_EVENT, NULL, 0, 0);
+#endif
+
+ lim_log(mac_ctx, LOG2, FL("Processing AbortScan Ind scan_id %d"),
+ scan_id);
+
+ /* send stop scan cmd to fw if scan offload is enabled. */
+ lim_send_stop_scan_offload_req(mac_ctx, session_id, scan_id);
+ return;
+}
+
+/**
+ * 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, tpSirMsgQ 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);
+ }
+}
+
+#ifdef FEATURE_OEM_DATA_SUPPORT
+
+void lim_oem_data_rsp_handle_resume_link_rsp(tpAniSirGlobal pMac, CDF_STATUS status,
+ uint32_t *mlmOemDataRsp)
+{
+ if (status != CDF_STATUS_SUCCESS) {
+ lim_log(pMac, LOGE,
+ FL
+ ("OEM Data Rsp failed to get the response for resume link"));
+ }
+
+ if (NULL != pMac->lim.gpLimMlmOemDataReq) {
+ cdf_mem_free(pMac->lim.gpLimMlmOemDataReq);
+ pMac->lim.gpLimMlmOemDataReq = NULL;
+ }
+ /* "Failure" status doesn't mean that Oem Data Rsp did not happen */
+ /* and hence we need to respond to upper layers. Only Resume link is failed, but */
+ /* we got the oem data response already. */
+ /* Post the meessage to MLM */
+ lim_post_sme_message(pMac, LIM_MLM_OEM_DATA_CNF,
+ (uint32_t *) (mlmOemDataRsp));
+
+ return;
+}
+
+void lim_process_oem_data_rsp(tpAniSirGlobal pMac, uint32_t *body)
+{
+ tpLimMlmOemDataRsp mlmOemDataRsp = NULL;
+
+ /* Process all the messages for the lim queue */
+ SET_LIM_PROCESS_DEFD_MESGS(pMac, true);
+
+ mlmOemDataRsp = (tpLimMlmOemDataRsp) body;
+
+ PELOG1(lim_log
+ (pMac, LOG1, FL("%s: sending oem data response msg to sme"),
+ __func__);
+ )
+ lim_post_sme_message(pMac, LIM_MLM_OEM_DATA_CNF,
+ (uint32_t *) (mlmOemDataRsp));
+
+ return;
+}
+
+#endif
+
+/**
+ * lim_process_messages() - Process messages from upper layers.
+ *
+ * @mac_ctx: Pointer to the Global Mac Context.
+ * @msg: Received message.
+ *
+ * Return: None.
+ */
+void lim_process_messages(tpAniSirGlobal mac_ctx, tpSirMsgQ 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;
+ CDF_STATUS cdf_status;
+ tSirMsgQ new_msg;
+ tSirSmeScanAbortReq *req_msg = NULL;
+ uint8_t session_id;
+ uint32_t scan_id;
+
+#ifdef FEATURE_WLAN_TDLS
+ tSirTdlsInd *tdls_ind = NULL;
+ tpDphHashNode sta_ds = NULL;
+ tTdlsLinkEstablishParams *tdls_link_params = NULL;
+#endif
+ tSirMbMsgP2p *p2p_msg = NULL;
+ if (ANI_DRIVER_TYPE(mac_ctx) == eDRIVER_TYPE_MFG) {
+ cdf_mem_free(msg->bodyptr);
+ msg->bodyptr = NULL;
+ return;
+ }
+ if (msg == NULL) {
+ lim_log(mac_ctx, LOGE, FL("Message pointer is Null"));
+ CDF_ASSERT(0);
+ return;
+ }
+#ifdef WLAN_DEBUG
+ mac_ctx->lim.numTot++;
+#endif
+ 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))
+ CDF_TRACE(CDF_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;
+#ifdef FEATURE_OEM_DATA_SUPPORT
+ case WMA_START_OEM_DATA_RSP:
+ lim_process_oem_data_rsp(mac_ctx, msg->bodyptr);
+ msg->bodyptr = NULL;
+ break;
+#endif
+ 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) {
+ lim_log(mac_ctx, LOGE, FL("Message bodyptr is Null"));
+ CDF_ASSERT(0);
+ break;
+ }
+ cdf_mem_copy((uint8_t *) &new_msg,
+ (uint8_t *) msg, sizeof(tSirMsgQ));
+ body_ptr = (cds_pkt_t *) new_msg.bodyptr;
+ cds_pkt_get_packet_length(body_ptr, &pkt_len);
+
+ cdf_status = wma_ds_peek_rx_packet_info(body_ptr,
+ (void **) &new_msg.bodyptr, false);
+
+ if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
+ cds_pkt_return_packet(body_ptr);
+ break;
+ }
+
+ if (WMA_GET_ROAMCANDIDATEIND(new_msg.bodyptr))
+ lim_log(mac_ctx, LOG1, FL("roamCandidateInd %d"),
+ WMA_GET_ROAMCANDIDATEIND(new_msg.bodyptr));
+
+ if (WMA_GET_OFFLOADSCANLEARN(new_msg.bodyptr))
+ lim_log(mac_ctx, LOG1, FL("offloadScanLearn %d"),
+ WMA_GET_OFFLOADSCANLEARN(new_msg.bodyptr));
+
+ lim_handle80211_frames(mac_ctx, &new_msg, &defer_msg);
+
+ if (defer_msg == true) {
+ CDF_TRACE(CDF_MODULE_ID_PE, LOG1,
+ FL("Defer Msg type=%x"), msg->type);
+ if (lim_defer_msg(mac_ctx, msg) != TX_SUCCESS) {
+ CDF_TRACE(CDF_MODULE_ID_PE, LOGE,
+ FL("Unable to Defer Msg"));
+ lim_log_session_states(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.
+ */
+ cds_pkt_return_packet(body_ptr);
+ break;
+ case eWNI_SME_SCAN_REQ:
+ case eWNI_SME_REMAIN_ON_CHANNEL_REQ:
+ case eWNI_SME_DISASSOC_REQ:
+ case eWNI_SME_DEAUTH_REQ:
+#ifdef FEATURE_OEM_DATA_SUPPORT
+ case eWNI_SME_OEM_DATA_REQ:
+#endif
+#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:
+ /* These messages are from HDD. Need to respond to HDD */
+ lim_process_normal_hdd_msg(mac_ctx, msg, true);
+ break;
+
+ case eWNI_SME_SCAN_ABORT_IND:
+ req_msg = msg->bodyptr;
+ if (req_msg) {
+ session_id = req_msg->sessionId;
+ scan_id = req_msg->scan_id;
+ lim_process_abort_scan_ind(mac_ctx, session_id,
+ scan_id);
+ cdf_mem_free((void *)msg->bodyptr);
+ msg->bodyptr = NULL;
+ }
+ break;
+ 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_TKIP_CNTR_MEAS_REQ:
+ case eWNI_SME_UPDATE_APWPSIE_REQ:
+ case eWNI_SME_HIDE_SSID_REQ:
+ case eWNI_SME_GET_WPSPBC_SESSION_REQ:
+ case eWNI_SME_SET_APWPARSNIEs_REQ:
+ case eWNI_SME_CHNG_MCC_BEACON_INTERVAL:
+#if defined WLAN_FEATURE_VOWIFI
+ case eWNI_SME_NEIGHBOR_REPORT_REQ_IND:
+ case eWNI_SME_BEACON_REPORT_RESP_XMIT_IND:
+#endif
+#if defined FEATURE_WLAN_ESE
+ case eWNI_SME_ESE_ADJACENT_AP_REPORT:
+#endif
+#ifdef WLAN_FEATURE_VOWIFI_11R
+ case eWNI_SME_FT_UPDATE_KEY:
+ case eWNI_SME_FT_PRE_AUTH_REQ:
+ case eWNI_SME_FT_AGGR_QOS_REQ:
+#endif
+ case eWNI_SME_REGISTER_MGMT_FRAME_REQ:
+ case eWNI_SME_UPDATE_NOA:
+ case eWNI_SME_CLEAR_DFS_CHANNEL_LIST:
+ case eWNI_SME_GET_STATISTICS_REQ:
+#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
+ case eWNI_SME_GET_TSM_STATS_REQ:
+#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
+ /* These messages are from HDD.No need to respond to HDD */
+ lim_process_normal_hdd_msg(mac_ctx, msg, false);
+ break;
+
+ case eWNI_PMC_SMPS_STATE_IND:
+ if (msg->bodyptr) {
+ cdf_mem_free(msg->bodyptr);
+ msg->bodyptr = NULL;
+ }
+ break;
+ case eWNI_SME_SEND_ACTION_FRAME_IND:
+ lim_send_p2p_action_frame(mac_ctx, msg);
+ cdf_mem_free(msg->bodyptr);
+ msg->bodyptr = NULL;
+ break;
+ case eWNI_SME_ABORT_REMAIN_ON_CHAN_IND:
+ p2p_msg = (tSirMbMsgP2p *) msg->bodyptr;
+ lim_abort_remain_on_chan(mac_ctx, p2p_msg->sessionId,
+ p2p_msg->scan_id);
+ cdf_mem_free(msg->bodyptr);
+ msg->bodyptr = NULL;
+ break;
+ case SIR_HAL_P2P_NOA_START_IND:
+ session_entry = &mac_ctx->lim.gpSession[0];
+ lim_log(mac_ctx, LOG1, "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 == CDF_P2P_GO_MODE)) {
+ /* Save P2P NOA start attribute for Go persona*/
+ p2p_go_exists = 1;
+ cdf_mem_copy(&session_entry->p2pGoPsNoaStartInd,
+ msg->bodyptr, sizeof(tSirP2PNoaStart));
+ cdf_status =
+ session_entry->p2pGoPsNoaStartInd.status;
+ if (cdf_status != CDF_STATUS_SUCCESS)
+ CDF_TRACE(CDF_MODULE_ID_PE, LOGW,
+ FL(
+ "GO NOA start status %d by FW"),
+ cdf_status);
+ break;
+ }
+ }
+
+ if (p2p_go_exists == 0)
+ CDF_TRACE(CDF_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);
+ cdf_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) {
+ lim_log(mac_ctx, LOG1,
+ FL("No session exist for given bssId"));
+ cdf_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) {
+ lim_log(mac_ctx, LOG1,
+ FL("No sta_ds exist for given staId"));
+ cdf_mem_free(msg->bodyptr);
+ msg->bodyptr = NULL;
+ return;
+ }
+
+ if (STA_ENTRY_TDLS_PEER == sta_ds->staType) {
+ lim_log(mac_ctx, LOGE,
+ FL("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);
+ }
+ cdf_mem_free(msg->bodyptr);
+ msg->bodyptr = NULL;
+ break;
+#endif
+ case SIR_HAL_P2P_NOA_ATTR_IND:
+ session_entry = &mac_ctx->lim.gpSession[0];
+ lim_log(mac_ctx, LOG1, FL("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 ==
+ CDF_P2P_GO_MODE)) { /* Save P2P attr for Go */
+ cdf_mem_copy(
+ &session_entry->p2pGoPsUpdate,
+ msg->bodyptr,
+ sizeof(tSirP2PNoaAttr));
+ lim_log(mac_ctx, LOG2,
+ FL("bssId"
+ MAC_ADDRESS_STR
+ " ctWin=%d oppPsFlag=%d"),
+ MAC_ADDR_ARRAY(
+ session_entry->bssId),
+ session_entry->p2pGoPsUpdate.ctWin,
+ session_entry->p2pGoPsUpdate.oppPsFlag);
+ lim_log(mac_ctx, LOG2,
+ FL
+ (" 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;
+ }
+ }
+ cdf_mem_free(msg->bodyptr);
+ msg->bodyptr = NULL;
+ break;
+ case WMA_MISSED_BEACON_IND:
+ lim_ps_offload_handle_missed_beacon_ind(mac_ctx, msg);
+ cdf_mem_free(msg->bodyptr);
+ msg->bodyptr = NULL;
+ break;
+#ifdef WLAN_FEATURE_ROAM_OFFLOAD
+ case WMA_ROAM_OFFLOAD_SYNCH_IND:
+ lim_roam_offload_synch_ind(mac_ctx, msg);
+ /* bodyPtr is freed after handling
+ * eWNI_SME_ROAM_OFFLOAD_SYNCH_IND in sme_ProcessMsg */
+ break;
+#endif
+ case SIR_LIM_ADDTS_RSP_TIMEOUT:
+ lim_process_sme_req_messages(mac_ctx, msg);
+ break;
+#ifdef FEATURE_WLAN_ESE
+ case SIR_LIM_ESE_TSM_TIMEOUT:
+#ifndef FEATURE_WLAN_ESE_UPLOAD
+ limProcessTsmTimeoutHandler(mac_ctx, msg);
+#endif /* FEATURE_WLAN_ESE_UPLOAD */
+ break;
+ case WMA_TSM_STATS_RSP:
+#ifdef FEATURE_WLAN_ESE_UPLOAD
+ lim_send_sme_pe_ese_tsm_rsp(mac_ctx,
+ (tAniGetTsmStatsRsp *) msg->bodyptr);
+#else
+ limProcessHalEseTsmRsp(mac_ctx, msg);
+#endif /* FEATURE_WLAN_ESE_UPLOAD */
+ 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_PERIODIC_PROBE_REQ_TIMEOUT:
+ 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:
+#ifdef WLAN_FEATURE_VOWIFI_11R
+ case SIR_LIM_FT_PREAUTH_RSP_TIMEOUT:
+#endif
+ case SIR_LIM_REMAIN_CHN_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:
+ /* 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)
+ lim_log(mac_ctx, LOGE,
+ FL("Can't Process HB TO - bodyptr is Null"));
+ else {
+ session_entry = (tpPESession) msg->bodyptr;
+ lim_log(mac_ctx, LOGE,
+ FL
+ ("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_HASH_MISS_THRES_TIMEOUT:
+ mac_ctx->lim.gLimDisassocFrameCredit = 0;
+ 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;
+#ifdef FEATURE_WLAN_TDLS
+ case SIR_HAL_TDLS_SHOULD_DISCOVER:
+ case SIR_HAL_TDLS_SHOULD_TEARDOWN:
+ case SIR_HAL_TDLS_PEER_DISCONNECTED:
+ CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_INFO,
+ ("%s received tdls event: 0x%x"), __func__, msg->type);
+ lim_send_sme_tdls_event_notify(mac_ctx, msg->type,
+ (void *)msg->bodyptr);
+ break;
+#endif
+ case WMA_ADD_BSS_RSP:
+ lim_process_mlm_add_bss_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:
+ 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:
+ cdf_mem_free((void *)msg->bodyptr);
+ msg->bodyptr = NULL;
+ break;
+ case WMA_SET_MAX_TX_POWER_RSP:
+#if defined WLAN_FEATURE_VOWIFI
+ rrm_set_max_tx_power_rsp(mac_ctx, msg);
+#endif
+ if (msg->bodyptr != NULL) {
+ cdf_mem_free((void *)msg->bodyptr);
+ msg->bodyptr = NULL;
+ }
+ break;
+ case SIR_LIM_ADDR2_MISS_IND:
+ lim_log(mac_ctx, LOGE,
+ 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
+ */
+ cdf_mem_free((void *)(msg->bodyptr));
+ msg->bodyptr = NULL;
+ break;
+#ifdef WLAN_FEATURE_VOWIFI_11R
+ case WMA_AGGR_QOS_RSP:
+ lim_process_ft_aggr_qo_s_rsp(mac_ctx, msg);
+ break;
+#endif
+ case WMA_SET_LINK_STATE_RSP:
+ link_state_param = (tLinkStateParams *) msg->bodyptr;
+#if defined WLAN_FEATURE_VOWIFI_11R
+ 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);
+#endif
+ if (link_state_param->callback)
+ link_state_param->callback(mac_ctx,
+ link_state_param->callbackArg,
+ link_state_param->status);
+ cdf_mem_free((void *)(msg->bodyptr));
+ msg->bodyptr = NULL;
+ break;
+ case eWNI_SME_SET_BCN_FILTER_REQ:
+ session_id = (uint8_t) msg->bodyval;
+ session_entry = &mac_ctx->lim.gpSession[session_id];
+ if ((session_entry != NULL) &&
+ (lim_send_beacon_filter_info(mac_ctx, session_entry) !=
+ eSIR_SUCCESS))
+ lim_log(mac_ctx, LOGE,
+ FL("Failied to send Beacon Filter Info "));
+ cdf_mem_free((void *)(msg->bodyptr));
+ msg->bodyptr = NULL;
+ break;
+#ifdef FEATURE_WLAN_TDLS
+ case WMA_SET_TDLS_LINK_ESTABLISH_REQ_RSP:
+ tdls_link_params = (tTdlsLinkEstablishParams *) msg->bodyptr;
+ session_entry = pe_find_session_by_sta_id(mac_ctx,
+ tdls_link_params->staIdx, &session_id);
+ if (session_entry == NULL) {
+ lim_log(mac_ctx, LOGE,
+ FL("session %u does not exist"), session_id);
+ /* Still send the eWNI_SME_TDLS_LINK_ESTABLISH_RSP
+ * message to SME with session id as zero and status
+ * as FAILURE so, that message queued in SME queue
+ * can be freed to prevent the SME cmd buffer leak
+ */
+ lim_send_sme_tdls_link_establish_req_rsp(mac_ctx, 0,
+ NULL, NULL, eSIR_FAILURE);
+ } else {
+ lim_send_sme_tdls_link_establish_req_rsp(mac_ctx,
+ session_entry->smeSessionId, NULL, NULL,
+ tdls_link_params->status);
+ }
+ cdf_mem_free((void *)(msg->bodyptr));
+ msg->bodyptr = NULL;
+ break;
+#endif
+ case WMA_RX_SCAN_EVENT:
+ lim_process_rx_scan_event(mac_ctx, msg->bodyptr);
+ break;
+ case WMA_IBSS_PEER_INACTIVITY_IND:
+ lim_process_ibss_peer_inactivity(mac_ctx, msg->bodyptr);
+ cdf_mem_free((void *)(msg->bodyptr));
+ msg->bodyptr = NULL;
+ break;
+ case WMA_DFS_RADAR_IND:
+ lim_send_sme_dfs_event_notify(mac_ctx, msg->type,
+ (void *)msg->bodyptr);
+ /* msg->bodyptr will be freed up by SME/CSR */
+ break;
+ case WMA_DFS_BEACON_TX_SUCCESS_IND:
+ lim_process_beacon_tx_success_ind(mac_ctx, msg->type,
+ (void *)msg->bodyptr);
+ cdf_mem_free((void *)msg->bodyptr);
+ msg->bodyptr = NULL;
+ break;
+ case WMA_DISASSOC_TX_COMP:
+ lim_disassoc_tx_complete_cnf(mac_ctx, msg->bodyval);
+ break;
+ case WMA_DEAUTH_TX_COMP:
+ lim_deauth_tx_complete_cnf(mac_ctx, msg->bodyval);
+ break;
+#ifdef FEATURE_AP_MCC_CH_AVOIDANCE
+ case WMA_UPDATE_Q2Q_IE_IND:
+ cdf_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 (cds_get_channel_state(
+ 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);
+ }
+ }
+ cdf_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);
+ cdf_mem_free((void *)msg->bodyptr);
+ msg->bodyptr = NULL;
+ break;
+ case eWNI_SME_CHANNEL_CHANGE_REQ:
+ lim_process_sme_req_messages(mac_ctx, msg);
+ cdf_mem_free((void *)msg->bodyptr);
+ msg->bodyptr = NULL;
+ break;
+ case eWNI_SME_START_BEACON_REQ:
+ lim_process_sme_req_messages(mac_ctx, msg);
+ cdf_mem_free((void *)msg->bodyptr);
+ msg->bodyptr = NULL;
+ break;
+ case eWNI_SME_UPDATE_ADDITIONAL_IES:
+ lim_process_sme_req_messages(mac_ctx, msg);
+ cdf_mem_free((void *)msg->bodyptr);
+ msg->bodyptr = NULL;
+ break;
+ case eWNI_SME_MODIFY_ADDITIONAL_IES:
+ lim_process_sme_req_messages(mac_ctx, msg);
+ cdf_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);
+ cdf_mem_free((void *)msg->bodyptr);
+ msg->bodyptr = NULL;
+ break;
+#endif
+ case SIR_HAL_SOC_SET_HW_MODE_RESP:
+ lim_process_set_hw_mode_resp(mac_ctx, msg->bodyptr);
+ cdf_mem_free((void *)msg->bodyptr);
+ msg->bodyptr = NULL;
+ break;
+ case SIR_HAL_SOC_HW_MODE_TRANS_IND:
+ lim_process_hw_mode_trans_ind(mac_ctx, msg->bodyptr);
+ cdf_mem_free((void *)msg->bodyptr);
+ msg->bodyptr = NULL;
+ break;
+ case SIR_HAL_SOC_DUAL_MAC_CFG_RESP:
+ lim_process_dual_mac_cfg_resp(mac_ctx, msg->bodyptr);
+ cdf_mem_free((void *)msg->bodyptr);
+ msg->bodyptr = NULL;
+ break;
+ case eWNI_SME_SET_IE_REQ:
+ lim_process_sme_req_messages(mac_ctx, msg);
+ cdf_mem_free((void *)msg->bodyptr);
+ msg->bodyptr = NULL;
+ break;
+ default:
+ cdf_mem_free((void *)msg->bodyptr);
+ msg->bodyptr = NULL;
+ /* Unwanted messages */
+ /* Log error */
+ lim_log(mac_ctx, LOGE,
+ FL("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
+ *
+ ***FUNCTION:
+ * This function is called by LIM while exiting from Learn
+ * mode. This function fetches messages posted to the LIM
+ * deferred message queue limDeferredMsgQ.
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ * NA
+ *
+ ***NOTE:
+ * NA
+ *
+ * @param pMac - Pointer to Global MAC structure
+ * @return None
+ */
+
+void lim_process_deferred_message_queue(tpAniSirGlobal pMac)
+{
+ tSirMsgQ limMsg = { 0, 0, 0 };
+
+ tSirMsgQ *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) {
+ cdf_mem_copy((uint8_t *) &limMsg,
+ (uint8_t *) readMsg, sizeof(tSirMsgQ));
+ size--;
+ lim_process_messages(pMac, &limMsg);
+
+ if ((lim_is_system_in_scan_state(pMac))
+ || (true != GET_LIM_PROCESS_DEFD_MESGS(pMac))
+ || (pMac->lim.gLimSystemInScanLearnMode))
+ break;
+ }
+ }
+} /*** end lim_process_deferred_message_queue() ***/
+
+/**
+ * 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, tSirMsgQ *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_BT_AMP_AP_ROLE)
+ || (mac_ctx->lim.gLimSystemRole == eLIM_BT_AMP_STA_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 */
+ cdf_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.
+ */
+ cdf_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) {
+ lim_log(pMac, LOGP,
+ FL("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) {
+ lim_log(pMac, LOGP,
+ FL("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) {
+ lim_log(pMac, LOGP,
+ FL("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) {
+ lim_log(pMac, LOGP,
+ FL("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) {
+ lim_log(pMac, LOGP,
+ FL("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;
+ }
+}
+
+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) {
+ CDF_TRACE(CDF_MODULE_ID_PE, LOG1,
+ FL("sysRole(%d) Session (%d)"),
+ mac_ctx->lim.gLimSystemRole, i);
+ CDF_TRACE(CDF_MODULE_ID_PE, LOG1,
+ 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
+}
diff --git a/core/mac/src/pe/lim/lim_process_mlm_req_messages.c b/core/mac/src/pe/lim/lim_process_mlm_req_messages.c
new file mode 100644
index 0000000..73f4bf0
--- /dev/null
+++ b/core/mac/src/pe/lim/lim_process_mlm_req_messages.c
@@ -0,0 +1,2868 @@
+/*
+ * Copyright (c) 2011-2015 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.
+ */
+
+#include "cds_api.h"
+#include "wni_cfg.h"
+#include "ani_global.h"
+#include "sir_api.h"
+#include "sir_params.h"
+#include "cfg_api.h"
+
+#include "sch_api.h"
+#include "utils_api.h"
+#include "lim_utils.h"
+#include "lim_assoc_utils.h"
+#include "lim_prop_exts_utils.h"
+#include "lim_security_utils.h"
+#include "lim_send_messages.h"
+#include "lim_send_messages.h"
+#include "lim_session_utils.h"
+#ifdef WLAN_FEATURE_VOWIFI_11R
+#include <lim_ft.h>
+#endif
+#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM
+#include "host_diag_core_log.h"
+#endif
+#include "wma_if.h"
+
+static void lim_process_mlm_start_req(tpAniSirGlobal, uint32_t *);
+#ifdef FEATURE_OEM_DATA_SUPPORT
+static void lim_process_mlm_oem_data_req(tpAniSirGlobal, uint32_t *);
+#endif
+static void lim_process_mlm_join_req(tpAniSirGlobal, uint32_t *);
+static void lim_process_mlm_auth_req(tpAniSirGlobal, uint32_t *);
+static void lim_process_mlm_assoc_req(tpAniSirGlobal, uint32_t *);
+static void lim_process_mlm_reassoc_req(tpAniSirGlobal, uint32_t *);
+static void lim_process_mlm_disassoc_req(tpAniSirGlobal, uint32_t *);
+static void lim_process_mlm_deauth_req(tpAniSirGlobal, uint32_t *);
+static void lim_process_mlm_set_keys_req(tpAniSirGlobal, uint32_t *);
+
+/* MLM Timeout event handler templates */
+static void lim_process_periodic_probe_req_timer(tpAniSirGlobal mac_ctx);
+static void lim_process_join_failure_timeout(tpAniSirGlobal);
+static void lim_process_auth_failure_timeout(tpAniSirGlobal);
+static void lim_process_auth_rsp_timeout(tpAniSirGlobal, uint32_t);
+static void lim_process_assoc_failure_timeout(tpAniSirGlobal, uint32_t);
+static void lim_process_periodic_join_probe_req_timer(tpAniSirGlobal);
+
+/**
+ * lim_process_mlm_req_messages() - process mlm request messages
+ * @mac_ctx: global MAC context
+ * @msg: mlm request message
+ *
+ * This function is called by lim_post_mlm_message(). This
+ * function handles MLM primitives invoked by SME.
+ * Depending on the message type, corresponding function will be
+ * called.
+ * ASSUMPTIONS:
+ * 1. Upon receiving Beacon in WT_JOIN_STATE, MLM module invokes
+ * APIs exposed by Beacon Processing module for setting parameters
+ * at MAC hardware.
+ * 2. If attempt to Reassociate with an AP fails, link with current
+ * AP is restored back.
+ *
+ * Return: None
+ */
+void lim_process_mlm_req_messages(tpAniSirGlobal mac_ctx, tpSirMsgQ msg)
+{
+ MTRACE(mac_trace_msg_rx(mac_ctx, NO_SESSION, msg->type));
+ switch (msg->type) {
+ case LIM_MLM_START_REQ:
+ lim_process_mlm_start_req(mac_ctx, msg->bodyptr);
+ break;
+#ifdef FEATURE_OEM_DATA_SUPPORT
+ case LIM_MLM_OEM_DATA_REQ:
+ lim_process_mlm_oem_data_req(mac_ctx, msg->bodyptr);
+ break;
+#endif
+ case LIM_MLM_JOIN_REQ:
+ lim_process_mlm_join_req(mac_ctx, msg->bodyptr);
+ break;
+ case LIM_MLM_AUTH_REQ:
+ lim_process_mlm_auth_req(mac_ctx, msg->bodyptr);
+ break;
+ case LIM_MLM_ASSOC_REQ:
+ lim_process_mlm_assoc_req(mac_ctx, msg->bodyptr);
+ break;
+ case LIM_MLM_REASSOC_REQ:
+ lim_process_mlm_reassoc_req(mac_ctx, msg->bodyptr);
+ break;
+ case LIM_MLM_DISASSOC_REQ:
+ lim_process_mlm_disassoc_req(mac_ctx, msg->bodyptr);
+ break;
+ case LIM_MLM_DEAUTH_REQ:
+ lim_process_mlm_deauth_req(mac_ctx, msg->bodyptr);
+ break;
+ case LIM_MLM_SETKEYS_REQ:
+ lim_process_mlm_set_keys_req(mac_ctx, msg->bodyptr);
+ break;
+ case SIR_LIM_PERIODIC_PROBE_REQ_TIMEOUT:
+ lim_process_periodic_probe_req_timer(mac_ctx);
+ break;
+ case SIR_LIM_JOIN_FAIL_TIMEOUT:
+ lim_process_join_failure_timeout(mac_ctx);
+ break;
+ case SIR_LIM_PERIODIC_JOIN_PROBE_REQ_TIMEOUT:
+ lim_process_periodic_join_probe_req_timer(mac_ctx);
+ break;
+ case SIR_LIM_AUTH_FAIL_TIMEOUT:
+ lim_process_auth_failure_timeout(mac_ctx);
+ break;
+ case SIR_LIM_AUTH_RSP_TIMEOUT:
+ lim_process_auth_rsp_timeout(mac_ctx, msg->bodyval);
+ break;
+ case SIR_LIM_ASSOC_FAIL_TIMEOUT:
+ lim_process_assoc_failure_timeout(mac_ctx, msg->bodyval);
+ break;
+#ifdef WLAN_FEATURE_VOWIFI_11R
+ case SIR_LIM_FT_PREAUTH_RSP_TIMEOUT:
+ lim_process_ft_preauth_rsp_timeout(mac_ctx);
+ break;
+#endif
+ case SIR_LIM_REMAIN_CHN_TIMEOUT:
+ lim_process_remain_on_chn_timeout(mac_ctx);
+ break;
+ case SIR_LIM_INSERT_SINGLESHOT_NOA_TIMEOUT:
+ lim_process_insert_single_shot_noa_timeout(mac_ctx);
+ break;
+ case SIR_LIM_CONVERT_ACTIVE_CHANNEL_TO_PASSIVE:
+ lim_convert_active_channel_to_passive_channel(mac_ctx);
+ break;
+ case SIR_LIM_DISASSOC_ACK_TIMEOUT:
+ lim_process_disassoc_ack_timeout(mac_ctx);
+ break;
+ case SIR_LIM_DEAUTH_ACK_TIMEOUT:
+ lim_process_deauth_ack_timeout(mac_ctx);
+ break;
+ case LIM_MLM_TSPEC_REQ:
+ default:
+ break;
+ } /* switch (msg->type) */
+}
+
+/* WLAN_SUSPEND_LINK Related */
+
+/**
+ * lim_is_link_suspended()- check if link is suspended
+ * @mac_ctx: global MAC context
+ *
+ * This function returns is link is suspended or not.
+ * Since Suspend link uses init scan, it just returns
+ * gLimSystemInScanLearnMode flag.
+ *
+ * Return: uint8_t(gLimSystemInScanLearnMode flag)
+ */
+uint8_t lim_is_link_suspended(tpAniSirGlobal mac_ctx)
+{
+ return mac_ctx->lim.gLimSystemInScanLearnMode;
+}
+
+/**
+ * lim_change_channel_with_callback() - change channel and register callback
+ * @mac_ctx: global MAC context
+ * @new_chan: new channel to switch
+ * @callback: Callback function
+ * @cbdata: callback data
+ * @session_entry: PE session pointer
+ *
+ * This function is called to change channel and perform off channel operation
+ * if required. The caller registers a callback to be called at the end of the
+ * channel change.
+ *
+ * Return: None
+ */
+void
+lim_change_channel_with_callback(tpAniSirGlobal mac_ctx, uint8_t new_chan,
+ CHANGE_CHANNEL_CALLBACK callback,
+ uint32_t *cbdata, tpPESession session_entry)
+{
+ /* Sanity checks for the current and new channel */
+#if defined WLAN_VOWIFI_DEBUG
+ lim_log(mac_ctx, LOGE, FL("Switching channel to %d"), new_chan);
+#endif
+ session_entry->channelChangeReasonCode =
+ LIM_SWITCH_CHANNEL_OPERATION;
+
+ mac_ctx->lim.gpchangeChannelCallback = callback;
+ mac_ctx->lim.gpchangeChannelData = cbdata;
+
+ lim_send_switch_chnl_params(mac_ctx, new_chan, 0, 0,
+ CH_WIDTH_20MHZ, session_entry->maxTxPower,
+ session_entry->peSessionId, false);
+
+ return;
+}
+
+/**
+ * lim_covert_channel_scan_type() - switch between ACTIVE and PASSIVE scan type
+ * @mac_ctx: global MAC context
+ * @chan_num: channel number to change the scan type
+ * @passive_to_active: flag to indicate if switch allowed
+ *
+ * This function is called to get the list,
+ * change the channel type and set again.
+ * NOTE: If a channel is ACTIVE, this function will make it as PASSIVE
+ * If a channel is PASSIVE, this fucntion will make it as ACTIVE
+ *
+ * Return: None
+ */
+
+void lim_covert_channel_scan_type(tpAniSirGlobal mac_ctx, uint8_t chan_num,
+ bool passive_to_active)
+{
+
+ uint32_t i;
+ uint8_t chan_pair[WNI_CFG_SCAN_CONTROL_LIST_LEN];
+ uint32_t len = WNI_CFG_SCAN_CONTROL_LIST_LEN;
+ tSirRetStatus status;
+
+ status = wlan_cfg_get_str(mac_ctx, WNI_CFG_SCAN_CONTROL_LIST,
+ chan_pair, &len);
+ if (eSIR_SUCCESS != status) {
+ lim_log(mac_ctx, LOGE, FL("Unable to get scan control list"));
+ return;
+ }
+ if (len > WNI_CFG_SCAN_CONTROL_LIST_LEN) {
+ lim_log(mac_ctx, LOGE,
+ FL("Invalid scan control list length:%d"), len);
+ return;
+ }
+ for (i = 0; (i + 1) < len; i += 2) {
+ if (chan_pair[i] != chan_num) /* skip this channel */
+ continue;
+ if ((eSIR_PASSIVE_SCAN == chan_pair[i + 1]) &&
+ true == passive_to_active) {
+ lim_log(mac_ctx, LOG1, FL
+ ("Channel %d changed from Passive to Active"),
+ chan_num);
+ chan_pair[i + 1] = eSIR_ACTIVE_SCAN;
+ break;
+ }
+ if ((eSIR_ACTIVE_SCAN == chan_pair[i + 1]) &&
+ false == passive_to_active) {
+ lim_log(mac_ctx, LOG1, FL
+ ("Channel %d changed from Active to Passive"),
+ chan_num);
+ chan_pair[i + 1] = eSIR_PASSIVE_SCAN;
+ break;
+ }
+ }
+
+ cfg_set_str_notify(mac_ctx, WNI_CFG_SCAN_CONTROL_LIST,
+ (uint8_t *) chan_pair, len, false);
+ return;
+}
+
+/**
+ * lim_set_dfs_channel_list() - convert dfs channel list to active channel list
+ * @mac_ctx: global MAC context.
+ * @chan_num: channel number
+ * @dfs_ch_list: list of DFS channels
+ *
+ * This function is called to convert DFS channel list to active channel list
+ * when any beacon is present on that channel. This function store time for
+ * passive channels which help to know that for how much time channel has been
+ * passive.
+ *
+ * NOTE: If a channel is ACTIVE, it won't store any time
+ * If a channel is PAssive, it will store time as timestamp
+ *
+ * Return: None
+ */
+void lim_set_dfs_channel_list(tpAniSirGlobal mac_ctx, uint8_t chan_num,
+ tSirDFSChannelList *dfs_ch_list)
+{
+ bool pass_to_active = true;
+
+ if (!((1 <= chan_num) && (165 >= chan_num))) {
+ lim_log(mac_ctx, LOGE, FL("Invalid Channel: %d"), chan_num);
+ return;
+ }
+
+ if (true == lim_isconnected_on_dfs_channel(chan_num)) {
+ if (dfs_ch_list->timeStamp[chan_num] == 0) {
+ /*
+ * Received first beacon;
+ * Convert DFS channel to Active channel.
+ */
+ lim_log(mac_ctx, LOG1,
+ FL("Received first beacon on DFS channel: %d"),
+ chan_num);
+ lim_covert_channel_scan_type(mac_ctx, chan_num,
+ pass_to_active);
+ }
+ dfs_ch_list->timeStamp[chan_num] =
+ cdf_mc_timer_get_system_time();
+ } else {
+ lim_log(mac_ctx, LOG1, FL("Channel %d is Active"), chan_num);
+ return;
+ }
+
+ if (!tx_timer_running
+ (&mac_ctx->lim.limTimers.gLimActiveToPassiveChannelTimer)) {
+ tx_timer_activate(
+ &mac_ctx->lim.limTimers.gLimActiveToPassiveChannelTimer);
+ }
+
+ return;
+}
+
+/**
+ * lim_restore_pre_scan_state() - restore HW state prior to scan
+ *
+ * @mac_ctx: global MAC context
+ *
+ * This function is called by lim_continue_channel_scan()
+ * to restore HW state prior to entering 'scan state'
+ *
+ * Return: None
+ */
+void lim_restore_pre_scan_state(tpAniSirGlobal mac_ctx)
+{
+ /* Deactivate MIN/MAX channel timers if running */
+ lim_deactivate_and_change_timer(mac_ctx, eLIM_MIN_CHANNEL_TIMER);
+ lim_deactivate_and_change_timer(mac_ctx, eLIM_MAX_CHANNEL_TIMER);
+
+ mac_ctx->lim.gLimSystemInScanLearnMode = 0;
+ lim_log(mac_ctx, LOG1, FL("Scan ended, took %llu tu"),
+ (tx_time_get() - mac_ctx->lim.scanStartTime));
+}
+
+#ifdef FEATURE_OEM_DATA_SUPPORT
+/**
+ * lim_send_hal_oem_data_req() - send oem data request
+ * @mac_ctx: global MAC context
+ *
+ * This function is used to send OEM data request to HAL.
+ *
+ * Return: None
+ */
+void lim_send_hal_oem_data_req(tpAniSirGlobal mac_ctx)
+{
+ tSirMsgQ msg;
+ tpStartOemDataReq start_oem_data_req = NULL;
+ tSirRetStatus rc = eSIR_SUCCESS;
+ tpLimMlmOemDataRsp mlm_oem_data_rsp;
+ uint32_t reqlen = 0;
+
+ if (NULL == mac_ctx->lim.gpLimMlmOemDataReq) {
+ lim_log(mac_ctx, LOGE, FL("Null pointer"));
+ goto error;
+ }
+
+ reqlen = sizeof(tStartOemDataReq);
+
+ start_oem_data_req = cdf_mem_malloc(reqlen);
+ if (NULL == start_oem_data_req) {
+ lim_log(mac_ctx, LOGE, FL
+ ("Could not allocate memory for start_oem_data_req"));
+ goto error;
+ }
+
+ cdf_mem_set((uint8_t *) (start_oem_data_req), reqlen, 0);
+
+ /* Now copy over the information to the OEM DATA REQ to HAL */
+ cdf_mem_copy(start_oem_data_req->selfMacAddr,
+ mac_ctx->lim.gpLimMlmOemDataReq->selfMacAddr,
+ sizeof(tSirMacAddr));
+
+ cdf_mem_copy(start_oem_data_req->oemDataReq,
+ mac_ctx->lim.gpLimMlmOemDataReq->oemDataReq,
+ OEM_DATA_REQ_SIZE);
+
+ /* Create the message to be passed to HAL */
+ msg.type = WMA_START_OEM_DATA_REQ;
+ msg.bodyptr = start_oem_data_req;
+ msg.bodyval = 0;
+
+ SET_LIM_PROCESS_DEFD_MESGS(mac_ctx, false);
+ MTRACE(mac_trace_msg_tx(mac_ctx, NO_SESSION, msg.type));
+
+ rc = wma_post_ctrl_msg(mac_ctx, &msg);
+ if (rc == eSIR_SUCCESS)
+ return;
+
+ SET_LIM_PROCESS_DEFD_MESGS(mac_ctx, true);
+ cdf_mem_free(start_oem_data_req);
+ lim_log(mac_ctx, LOGE,
+ FL("OEM_DATA: posting WMA_START_OEM_DATA_REQ to HAL failed"));
+
+error:
+ mac_ctx->lim.gLimMlmState = mac_ctx->lim.gLimPrevMlmState;
+ MTRACE(mac_trace(mac_ctx, TRACE_CODE_MLM_STATE, NO_SESSION,
+ mac_ctx->lim.gLimMlmState));
+
+ mlm_oem_data_rsp = cdf_mem_malloc(sizeof(tLimMlmOemDataRsp));
+ if (NULL == mlm_oem_data_rsp) {
+ lim_log(mac_ctx->hHdd, LOGP, FL
+ ("memory allocation for mlm_oem_data_rsp"));
+ return;
+ }
+
+ if (NULL != mac_ctx->lim.gpLimMlmOemDataReq) {
+ cdf_mem_free(mac_ctx->lim.gpLimMlmOemDataReq);
+ mac_ctx->lim.gpLimMlmOemDataReq = NULL;
+ }
+
+ lim_post_sme_message(mac_ctx, LIM_MLM_OEM_DATA_CNF,
+ (uint32_t *) mlm_oem_data_rsp);
+
+ return;
+}
+#endif /* FEATURE_OEM_DATA_SUPPORT */
+
+/**
+ * mlm_add_sta() - MLM add sta
+ * @mac_ctx: global MAC context
+ * @sta_param: Add sta params
+ * @bssid: BSSID
+ * @ht_capable: HT capability
+ * @session_entry: PE session entry
+ *
+ * This function is called to update station parameters
+ *
+ * Return: None
+ */
+static void mlm_add_sta(tpAniSirGlobal mac_ctx, tpAddStaParams sta_param,
+ uint8_t *bssid, uint8_t ht_capable, tpPESession session_entry)
+{
+ uint32_t val;
+ uint32_t self_dot11mode = 0;
+
+ wlan_cfg_get_int(mac_ctx, WNI_CFG_DOT11_MODE, &self_dot11mode);
+ sta_param->staType = STA_ENTRY_SELF; /* Identifying self */
+
+ cdf_mem_copy(sta_param->bssId, bssid, sizeof(tSirMacAddr));
+ cdf_mem_copy(sta_param->staMac, session_entry->selfMacAddr,
+ sizeof(tSirMacAddr));
+
+ /* Configuration related parameters to be changed to support BT-AMP */
+
+ if (eSIR_SUCCESS != wlan_cfg_get_int(mac_ctx, WNI_CFG_LISTEN_INTERVAL,
+ &val))
+ lim_log(mac_ctx, LOGP, FL("Couldn't get LISTEN_INTERVAL"));
+ sta_param->listenInterval = (uint16_t) val;
+
+ if (eSIR_SUCCESS != wlan_cfg_get_int(mac_ctx, WNI_CFG_SHORT_PREAMBLE,
+ &val))
+ lim_log(mac_ctx, LOGP, FL("Couldn't get SHORT_PREAMBLE"));
+ sta_param->shortPreambleSupported = (uint8_t) val;
+
+ sta_param->assocId = 0; /* Is SMAC OK with this? */
+ sta_param->wmmEnabled = 0;
+ sta_param->uAPSD = 0;
+ sta_param->maxSPLen = 0;
+ sta_param->us32MaxAmpduDuration = 0;
+ sta_param->maxAmpduSize = 0; /* 0: 8k, 1: 16k,2: 32k,3: 64k, 4:128k */
+
+ /* For Self STA get the LDPC capability from config.ini */
+ sta_param->htLdpcCapable =
+ (session_entry->txLdpcIniFeatureEnabled & 0x01);
+ sta_param->vhtLdpcCapable =
+ ((session_entry->txLdpcIniFeatureEnabled >> 1) & 0x01);
+
+ if (IS_DOT11_MODE_HT(session_entry->dot11mode)) {
+ sta_param->htCapable = ht_capable;
+ sta_param->greenFieldCapable =
+ lim_get_ht_capability(mac_ctx, eHT_GREENFIELD,
+ session_entry);
+ sta_param->ch_width =
+ lim_get_ht_capability(mac_ctx,
+ eHT_SUPPORTED_CHANNEL_WIDTH_SET, session_entry);
+ sta_param->mimoPS =
+ (tSirMacHTMIMOPowerSaveState)lim_get_ht_capability(
+ mac_ctx, eHT_MIMO_POWER_SAVE, session_entry);
+ sta_param->rifsMode =
+ lim_get_ht_capability(mac_ctx, eHT_RIFS_MODE,
+ session_entry);
+ sta_param->lsigTxopProtection =
+ lim_get_ht_capability(mac_ctx, eHT_LSIG_TXOP_PROTECTION,
+ session_entry);
+ sta_param->maxAmpduDensity =
+ lim_get_ht_capability(mac_ctx, eHT_MPDU_DENSITY,
+ session_entry);
+ sta_param->maxAmsduSize =
+ lim_get_ht_capability(mac_ctx, eHT_MAX_AMSDU_LENGTH,
+ session_entry);
+ sta_param->fDsssCckMode40Mhz =
+ lim_get_ht_capability(mac_ctx, eHT_DSSS_CCK_MODE_40MHZ,
+ session_entry);
+ sta_param->fShortGI20Mhz =
+ lim_get_ht_capability(mac_ctx, eHT_SHORT_GI_20MHZ,
+ session_entry);
+ sta_param->fShortGI40Mhz =
+ lim_get_ht_capability(mac_ctx, eHT_SHORT_GI_40MHZ,
+ session_entry);
+ }
+ if (session_entry->vhtCapability) {
+ sta_param->vhtCapable = true;
+ sta_param->vhtTxBFCapable =
+ session_entry->txBFIniFeatureEnabled;
+ sta_param->vhtTxMUBformeeCapable = session_entry->txMuBformee;
+ sta_param->enable_su_tx_bformer =
+ session_entry->enable_su_tx_bformer;
+ }
+ /*
+ * Since this is Self-STA, need to populate Self MAX_AMPDU_SIZE
+ * capabilities
+ */
+ if (IS_DOT11_MODE_VHT(self_dot11mode)) {
+ val = 0; /* Default 8K AMPDU size */
+ if (eSIR_SUCCESS != wlan_cfg_get_int(mac_ctx,
+ WNI_CFG_VHT_AMPDU_LEN_EXPONENT, &val))
+ lim_log(mac_ctx, LOGE, FL
+ ("Couldn't get WNI_CFG_VHT_AMPDU_LEN_EXPONENT"));
+ sta_param->maxAmpduSize = (uint8_t) val;
+ }
+ sta_param->enableVhtpAid = session_entry->enableVhtpAid;
+ sta_param->enableAmpduPs = session_entry->enableAmpduPs;
+ sta_param->enableHtSmps = session_entry->enableHtSmps;
+ sta_param->htSmpsconfig = session_entry->htSmpsvalue;
+
+#ifdef WLAN_FEATURE_11AC
+ lim_populate_own_rate_set(mac_ctx, &sta_param->supportedRates, NULL,
+ false, session_entry, NULL);
+#else
+ lim_populate_own_rate_set(mac_ctx, &sta_param->supportedRates, NULL,
+ false, session_entry);
+#endif
+ lim_fill_supported_rates_info(mac_ctx, NULL, &sta_param->supportedRates,
+ session_entry);
+
+ lim_log(mac_ctx, LOGE, FL(
+ "GF: %d, ChnlWidth: %d, MimoPS: %d, lsigTXOP: %d, dsssCCK: %d,"
+ " SGI20: %d, SGI40%d"), sta_param->greenFieldCapable,
+ sta_param->ch_width, sta_param->mimoPS,
+ sta_param->lsigTxopProtection, sta_param->fDsssCckMode40Mhz,
+ sta_param->fShortGI20Mhz, sta_param->fShortGI40Mhz);
+
+ if (CDF_P2P_GO_MODE == session_entry->pePersona)
+ sta_param->p2pCapableSta = 1;
+}
+
+/**
+ * lim_mlm_add_bss() - HAL interface for WMA_ADD_BSS_REQ
+ * @mac_ctx: global MAC context
+ * @mlm_start_req: MLM start request
+ * @session: PE session entry
+ *
+ * Package WMA_ADD_BSS_REQ to HAL, in order to start a BSS
+ *
+ * Return: eSIR_SME_SUCCESS on success, other error codes otherwise
+ */
+tSirResultCodes
+lim_mlm_add_bss(tpAniSirGlobal mac_ctx,
+ tLimMlmStartReq *mlm_start_req, tpPESession session)
+{
+ tSirMsgQ msg_buf;
+ tpAddBssParams addbss_param = NULL;
+ uint32_t retcode;
+
+ /* Package WMA_ADD_BSS_REQ message parameters */
+ addbss_param = cdf_mem_malloc(sizeof(tAddBssParams));
+ if (NULL == addbss_param) {
+ lim_log(mac_ctx, LOGE,
+ FL("Unable to allocate memory during ADD_BSS"));
+ /* Respond to SME with LIM_MLM_START_CNF */
+ return eSIR_MEM_ALLOC_FAILED;
+ }
+
+ cdf_mem_set(addbss_param, sizeof(tAddBssParams), 0);
+ /* Fill in tAddBssParams members */
+ cdf_mem_copy(addbss_param->bssId, mlm_start_req->bssId,
+ sizeof(tSirMacAddr));
+
+ /* Fill in tAddBssParams selfMacAddr */
+ cdf_mem_copy(addbss_param->selfMacAddr,
+ session->selfMacAddr, sizeof(tSirMacAddr));
+
+ addbss_param->bssType = mlm_start_req->bssType;
+ if ((mlm_start_req->bssType == eSIR_IBSS_MODE) ||
+ (mlm_start_req->bssType == eSIR_BTAMP_AP_MODE) ||
+ (mlm_start_req->bssType == eSIR_BTAMP_STA_MODE)) {
+ addbss_param->operMode = BSS_OPERATIONAL_MODE_STA;
+ } else if (mlm_start_req->bssType == eSIR_INFRA_AP_MODE) {
+ addbss_param->operMode = BSS_OPERATIONAL_MODE_AP;
+ }
+
+ addbss_param->shortSlotTimeSupported = session->shortSlotTimeSupported;
+ addbss_param->beaconInterval = mlm_start_req->beaconPeriod;
+ addbss_param->dtimPeriod = mlm_start_req->dtimPeriod;
+ addbss_param->wps_state = mlm_start_req->wps_state;
+ addbss_param->cfParamSet.cfpCount = mlm_start_req->cfParamSet.cfpCount;
+ addbss_param->cfParamSet.cfpPeriod =
+ mlm_start_req->cfParamSet.cfpPeriod;
+ addbss_param->cfParamSet.cfpMaxDuration =
+ mlm_start_req->cfParamSet.cfpMaxDuration;
+ addbss_param->cfParamSet.cfpDurRemaining =
+ mlm_start_req->cfParamSet.cfpDurRemaining;
+
+ addbss_param->rateSet.numRates = mlm_start_req->rateSet.numRates;
+ cdf_mem_copy(addbss_param->rateSet.rate, mlm_start_req->rateSet.rate,
+ mlm_start_req->rateSet.numRates);
+
+ addbss_param->nwType = mlm_start_req->nwType;
+ addbss_param->htCapable = mlm_start_req->htCapable;
+ addbss_param->vhtCapable = session->vhtCapability;
+ addbss_param->ch_width = session->ch_width;
+ addbss_param->ch_center_freq_seg0 =
+ session->ch_center_freq_seg0;
+ addbss_param->ch_center_freq_seg1 =
+ session->ch_center_freq_seg1;
+ addbss_param->htOperMode = mlm_start_req->htOperMode;
+ addbss_param->dualCTSProtection = mlm_start_req->dualCTSProtection;
+ addbss_param->txChannelWidthSet = mlm_start_req->txChannelWidthSet;
+
+ addbss_param->currentOperChannel = mlm_start_req->channelNumber;
+#ifdef WLAN_FEATURE_11W
+ addbss_param->rmfEnabled = session->limRmfEnabled;
+#endif
+
+ /* Update PE sessionId */
+ addbss_param->sessionId = mlm_start_req->sessionId;
+
+ /* Send the SSID to HAL to enable SSID matching for IBSS */
+ cdf_mem_copy(&(addbss_param->ssId.ssId),
+ mlm_start_req->ssId.ssId, mlm_start_req->ssId.length);
+ addbss_param->ssId.length = mlm_start_req->ssId.length;
+ addbss_param->bHiddenSSIDEn = mlm_start_req->ssidHidden;
+ lim_log(mac_ctx, LOGE, FL("TRYING TO HIDE SSID %d"),
+ addbss_param->bHiddenSSIDEn);
+ /* CR309183. Disable Proxy Probe Rsp. Host handles Probe Requests. Until FW fixed. */
+ addbss_param->bProxyProbeRespEn = 0;
+ addbss_param->obssProtEnabled = mlm_start_req->obssProtEnabled;
+
+#if defined WLAN_FEATURE_VOWIFI
+ addbss_param->maxTxPower = session->maxTxPower;
+#endif
+ mlm_add_sta(mac_ctx, &addbss_param->staContext,
+ addbss_param->bssId, addbss_param->htCapable,
+ session);
+
+ addbss_param->status = CDF_STATUS_SUCCESS;
+ addbss_param->respReqd = 1;
+
+ /* Set a new state for MLME */
+ session->limMlmState = eLIM_MLM_WT_ADD_BSS_RSP_STATE;
+ MTRACE(mac_trace(mac_ctx, TRACE_CODE_MLM_STATE, session->peSessionId,
+ session->limMlmState));
+
+ /* pass on the session persona to hal */
+ addbss_param->halPersona = session->pePersona;
+
+ addbss_param->bSpectrumMgtEnabled = session->spectrumMgtEnabled ||
+ lim_isconnected_on_dfs_channel(mlm_start_req->channelNumber);
+#if defined WLAN_FEATURE_VOWIFI_11R
+ addbss_param->extSetStaKeyParamValid = 0;
+#endif
+
+ addbss_param->dot11_mode = session->dot11mode;
+ addbss_param->nss = session->nss;
+ lim_log(mac_ctx, LOG2, FL("dot11_mode:%d nss value:%d"),
+ addbss_param->dot11_mode, addbss_param->nss);
+
+ msg_buf.type = WMA_ADD_BSS_REQ;
+ msg_buf.reserved = 0;
+ msg_buf.bodyptr = addbss_param;
+ msg_buf.bodyval = 0;
+ MTRACE(mac_trace_msg_tx(mac_ctx, session->peSessionId, msg_buf.type));
+
+ lim_log(mac_ctx, LOGW, FL("Sending WMA_ADD_BSS_REQ..."));
+ retcode = wma_post_ctrl_msg(mac_ctx, &msg_buf);
+ if (eSIR_SUCCESS != retcode) {
+ lim_log(mac_ctx, LOGE,
+ FL("Posting ADD_BSS_REQ to HAL failed, reason=%X"),
+ retcode);
+ cdf_mem_free(addbss_param);
+ return eSIR_SME_HAL_SEND_MESSAGE_FAIL;
+ }
+
+ return eSIR_SME_SUCCESS;
+}
+
+/**
+ * lim_process_mlm_start_req() - process MLM_START_REQ message
+ *
+ * @mac_ctx: global MAC context
+ * @msg_buf: Pointer to MLM message buffer
+ *
+ * This function is called to process MLM_START_REQ message
+ * from SME
+ * 1) MLME receives LIM_MLM_START_REQ from LIM
+ * 2) MLME sends WMA_ADD_BSS_REQ to HAL
+ * 3) MLME changes state to eLIM_MLM_WT_ADD_BSS_RSP_STATE
+ * MLME now waits for HAL to send WMA_ADD_BSS_RSP
+ *
+ * Return: None
+ */
+static void lim_process_mlm_start_req(tpAniSirGlobal mac_ctx, uint32_t *msg_buf)
+{
+ tLimMlmStartReq *mlm_start_req;
+ tLimMlmStartCnf mlm_start_cnf;
+ tpPESession session = NULL;
+
+ if (msg_buf == NULL) {
+ lim_log(mac_ctx, LOGE, FL("Buffer is Pointing to NULL"));
+ return;
+ }
+
+ mlm_start_req = (tLimMlmStartReq *) msg_buf;
+ session = pe_find_session_by_session_id(mac_ctx,
+ mlm_start_req->sessionId);
+ if (NULL == session) {
+ lim_log(mac_ctx, LOGP,
+ FL("Session Does not exist for given sessionID"));
+ mlm_start_cnf.resultCode = eSIR_SME_REFUSED;
+ goto end;
+ }
+
+ if (session->limMlmState != eLIM_MLM_IDLE_STATE) {
+ /*
+ * Should not have received Start req in states other than idle.
+ * Return Start confirm with failure code.
+ */
+ lim_log(mac_ctx, LOGE,
+ FL("received unexpected MLM_START_REQ in state %X"),
+ session->limMlmState);
+ lim_print_mlm_state(mac_ctx, LOGE, session->limMlmState);
+ mlm_start_cnf.resultCode =
+ eSIR_SME_BSS_ALREADY_STARTED_OR_JOINED;
+ goto end;
+ }
+
+ mlm_start_cnf.resultCode =
+ lim_mlm_add_bss(mac_ctx, mlm_start_req, session);
+
+end:
+ /* Update PE session Id */
+ mlm_start_cnf.sessionId = mlm_start_req->sessionId;
+
+ /* Free up buffer allocated for LimMlmScanReq */
+ cdf_mem_free(msg_buf);
+
+ /*
+ * Respond immediately to LIM, only if MLME has not been
+ * successfully able to send WMA_ADD_BSS_REQ to HAL.
+ * Else, LIM_MLM_START_CNF will be sent after receiving
+ * WMA_ADD_BSS_RSP from HAL
+ */
+ if (eSIR_SME_SUCCESS != mlm_start_cnf.resultCode)
+ lim_post_sme_message(mac_ctx, LIM_MLM_START_CNF,
+ (uint32_t *) &mlm_start_cnf);
+}
+
+#ifdef FEATURE_OEM_DATA_SUPPORT
+/**
+ * lim_process_mlm_oem_data_req() - process MLM OEM_DATA_REQ message
+ * @mac_ctx: global MAC context
+ * @msg_buf: MLM message buffer
+ *
+ * This function process MLM OEM_DATA_REQ message.
+ *
+ * Return: None
+ */
+static void lim_process_mlm_oem_data_req(tpAniSirGlobal mac_ctx,
+ uint32_t *msg_buf)
+{
+ tLimMlmOemDataRsp *mlm_oem_data_rsp;
+
+ if (((mac_ctx->lim.gLimMlmState == eLIM_MLM_IDLE_STATE) ||
+ (mac_ctx->lim.gLimMlmState == eLIM_MLM_JOINED_STATE) ||
+ (mac_ctx->lim.gLimMlmState == eLIM_MLM_AUTHENTICATED_STATE) ||
+ (mac_ctx->lim.gLimMlmState == eLIM_MLM_BSS_STARTED_STATE) ||
+ (mac_ctx->lim.gLimMlmState == eLIM_MLM_LINK_ESTABLISHED_STATE))) {
+ /*
+ * Hold onto the oem data request criteria
+ * Free gpLimMlmOemDataReq to avoid memory leak due to
+ * second OEM data request
+ */
+ if (mac_ctx->lim.gpLimMlmOemDataReq) {
+ cdf_mem_free(mac_ctx->lim.gpLimMlmOemDataReq);
+ mac_ctx->lim.gpLimMlmOemDataReq = NULL;
+ }
+
+ mac_ctx->lim.gpLimMlmOemDataReq = (tLimMlmOemDataReq *) msg_buf;
+ mac_ctx->lim.gLimPrevMlmState = mac_ctx->lim.gLimMlmState;
+
+ lim_log(mac_ctx, LOG2, FL("Calling lim_send_hal_oem_data_req"));
+ lim_send_hal_oem_data_req(mac_ctx);
+ } else {
+ /* Should not have received oem data req in other states */
+ lim_log(mac_ctx, LOGW, FL
+ ("unexpected LIM_MLM_OEM_DATA_REQ in invalid state %X"),
+ mac_ctx->lim.gLimMlmState);
+ lim_print_mlm_state(mac_ctx, LOGW, mac_ctx->lim.gLimMlmState);
+
+ /* Free up buffer allocated */
+ cdf_mem_free(msg_buf);
+
+ /* Return Meas confirm with INVALID_PARAMETERS */
+ mlm_oem_data_rsp = cdf_mem_malloc(sizeof(tLimMlmOemDataRsp));
+ if (mlm_oem_data_rsp != NULL) {
+ lim_post_sme_message(mac_ctx, LIM_MLM_OEM_DATA_CNF,
+ (uint32_t *) mlm_oem_data_rsp);
+ cdf_mem_free(mlm_oem_data_rsp);
+ } else {
+ lim_log(mac_ctx, LOGP, FL
+ ("Could not allocate memory for mlm_oem_data_rsp"));
+ return;
+ }
+ }
+
+ return;
+}
+#endif /* FEATURE_OEM_DATA_SUPPORT */
+/**
+ * lim_post_join_set_link_state_callback()- registered callback to perform post
+ * peer creation operations
+ *
+ * @mac: pointer to global mac structure
+ * @callback_arg: registered callback argument
+ * @status: peer creation status
+ *
+ * this is registered callback function during association to perform
+ * post peer creation operation based on the peer creation status
+ *
+ * Return: none
+ */
+void lim_post_join_set_link_state_callback(tpAniSirGlobal mac,
+ void *callback_arg, bool status)
+{
+ uint8_t chan_num, sec_chan_offset;
+ tpPESession session_entry = (tpPESession) callback_arg;
+ tLimMlmJoinCnf mlm_join_cnf;
+
+ lim_log(mac, LOG1, FL("Sessionid %d set link state(%d) cb status:%d"),
+ session_entry->peSessionId, session_entry->limMlmState,
+ status);
+
+ if (!status) {
+ lim_log(mac, LOGE,
+ FL("failed to find pe session for session id:%d"),
+ session_entry->peSessionId);
+ goto failure;
+ }
+
+ chan_num = session_entry->currentOperChannel;
+ sec_chan_offset = session_entry->htSecondaryChannelOffset;
+ /*
+ * store the channel switch session_entry in the lim
+ * global variable
+ */
+ session_entry->channelChangeReasonCode =
+ LIM_SWITCH_CHANNEL_JOIN;
+#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || \
+ defined(FEATURE_WLAN_LFR)
+ session_entry->pLimMlmReassocRetryReq = NULL;
+#endif
+ lim_log(mac, LOGE,
+ FL("[lim_process_mlm_join_req]: suspend link success(%d) "
+ "on sessionid: %d setting channel to: %d with ch_width :%d "
+ "and maxtxPower: %d"), status, session_entry->peSessionId,
+ session_entry->currentOperChannel,
+ session_entry->ch_width,
+ session_entry->maxTxPower);
+ lim_set_channel(mac, session_entry->currentOperChannel,
+ session_entry->ch_center_freq_seg0,
+ session_entry->ch_center_freq_seg1,
+ session_entry->ch_width,
+ session_entry->maxTxPower,
+ session_entry->peSessionId);
+ return;
+
+failure:
+ MTRACE(mac_trace(mac, TRACE_CODE_MLM_STATE, session_entry->peSessionId,
+ session_entry->limMlmState));
+ session_entry->limMlmState = eLIM_MLM_IDLE_STATE;
+ mlm_join_cnf.resultCode = eSIR_SME_RESOURCES_UNAVAILABLE;
+ mlm_join_cnf.sessionId = session_entry->peSessionId;
+ mlm_join_cnf.protStatusCode = eSIR_MAC_UNSPEC_FAILURE_STATUS;
+ lim_post_sme_message(mac, LIM_MLM_JOIN_CNF, (uint32_t *) &mlm_join_cnf);
+}
+
+/**
+ * lim_process_mlm_post_join_suspend_link() - This function is called after the
+ * suspend link while joining off channel.
+ *
+ * @mac_ctx: Pointer to Global MAC structure
+ * @status: status of suspend link.
+ * @ctx: passed while calling suspend link(session)
+ *
+ * This function does following:
+ * Check for suspend state.
+ * If success, proceed with setting link state to recieve the
+ * probe response/beacon from intended AP.
+ * Switch to the APs channel.
+ * On an error case, send the MLM_JOIN_CNF with error status.
+ *
+ * @Return None
+ */
+static void
+lim_process_mlm_post_join_suspend_link(tpAniSirGlobal mac_ctx,
+ CDF_STATUS status,
+ uint32_t *ctx)
+{
+ tLimMlmJoinCnf mlm_join_cnf;
+ tpPESession session = (tpPESession) ctx;
+ tSirLinkState lnk_state;
+
+ if (CDF_STATUS_SUCCESS != status) {
+ lim_log(mac_ctx, LOGE,
+ FL("Sessionid %d Suspend link(NOTIFY_BSS) failed. Still proceeding with join"),
+ session->peSessionId);
+ }
+ lim_deactivate_and_change_timer(mac_ctx, eLIM_JOIN_FAIL_TIMER);
+
+ /* assign appropriate sessionId to the timer object */
+ mac_ctx->lim.limTimers.gLimJoinFailureTimer.sessionId =
+ session->peSessionId;
+
+ lnk_state = (LIM_IS_BT_AMP_STA_ROLE(session) ?
+ eSIR_LINK_BTAMP_PREASSOC_STATE : eSIR_LINK_PREASSOC_STATE);
+ lim_log(mac_ctx, LOG1, FL("[lim_process_mlm_join_req]: lnk_state:%d"),
+ lnk_state);
+
+ if (lim_set_link_state(mac_ctx, lnk_state,
+ session->pLimMlmJoinReq->bssDescription.bssId,
+ session->selfMacAddr,
+ lim_post_join_set_link_state_callback,
+ session) != eSIR_SUCCESS) {
+ lim_log(mac_ctx, LOGE,
+ FL("SessionId:%d lim_set_link_state to eSIR_LINK_PREASSOC_STATE Failed!!"),
+ session->peSessionId);
+ lim_print_mac_addr(mac_ctx,
+ session->pLimMlmJoinReq->bssDescription.bssId, LOGE);
+ mlm_join_cnf.resultCode = eSIR_SME_RESOURCES_UNAVAILABLE;
+ session->limMlmState = eLIM_MLM_IDLE_STATE;
+ MTRACE(mac_trace(mac_ctx, TRACE_CODE_MLM_STATE,
+ session->peSessionId, session->limMlmState));
+ goto error;
+ }
+
+ return;
+error:
+ mlm_join_cnf.resultCode = eSIR_SME_RESOURCES_UNAVAILABLE;
+ mlm_join_cnf.sessionId = session->peSessionId;
+ mlm_join_cnf.protStatusCode = eSIR_MAC_UNSPEC_FAILURE_STATUS;
+ lim_post_sme_message(mac_ctx, LIM_MLM_JOIN_CNF,
+ (uint32_t *) &mlm_join_cnf);
+}
+
+/**
+ * lim_process_mlm_join_req() - process mlm join request.
+ *
+ * @mac_ctx: Pointer to Global MAC structure
+ * @msg: Pointer to the MLM message buffer
+ *
+ * This function is called to process MLM_JOIN_REQ message
+ * from SME. It does following:
+ * 1) Initialize LIM, HAL, DPH
+ * 2) Configure the BSS for which the JOIN REQ was received
+ * a) Send WMA_ADD_BSS_REQ to HAL -
+ * This will identify the BSS that we are interested in
+ * --AND--
+ * Add a STA entry for the AP (in a STA context)
+ * b) Wait for WMA_ADD_BSS_RSP
+ * c) Send WMA_ADD_STA_REQ to HAL
+ * This will add the "local STA" entry to the STA table
+ * 3) Continue as before, i.e,
+ * a) Send a PROBE REQ
+ * b) Wait for PROBE RSP/BEACON containing the SSID that
+ * we are interested in
+ * c) Then start an AUTH seq
+ * d) Followed by the ASSOC seq
+ *
+ * @Return: None
+ */
+static void lim_process_mlm_join_req(tpAniSirGlobal mac_ctx, uint32_t *msg)
+{
+ tLimMlmJoinCnf mlmjoin_cnf;
+ uint8_t sessionid;
+ tpPESession session;
+
+ sessionid = ((tpLimMlmJoinReq) msg)->sessionId;
+
+ session = pe_find_session_by_session_id(mac_ctx, sessionid);
+ if (NULL == session) {
+ lim_log(mac_ctx, LOGE, FL("SessionId:%d does not exist"),
+ sessionid);
+ goto error;
+ }
+
+ if ((!LIM_IS_AP_ROLE(session) &&
+ !LIM_IS_BT_AMP_AP_ROLE(session)) &&
+ ((session->limMlmState == eLIM_MLM_IDLE_STATE) ||
+ (session->limMlmState == eLIM_MLM_JOINED_STATE)) &&
+ (SIR_MAC_GET_ESS
+ (((tpLimMlmJoinReq) msg)->bssDescription.capabilityInfo) !=
+ SIR_MAC_GET_IBSS(((tpLimMlmJoinReq) msg)->bssDescription.
+ capabilityInfo))) {
+ /* Hold onto Join request parameters */
+
+ session->pLimMlmJoinReq = (tpLimMlmJoinReq) msg;
+ if (is_lim_session_off_channel(mac_ctx, sessionid)) {
+ lim_log(mac_ctx, LOG1,
+ "SessionId:%d LimSession is on OffChannel",
+ sessionid);
+ /* suspend link */
+ lim_log(mac_ctx, LOG1,
+ FL("Suspend link, sessionid %d is off channel"),
+ sessionid);
+ if (lim_is_link_suspended(mac_ctx)) {
+ lim_log(mac_ctx, LOGE, FL(
+ "link is already suspended, session %d"
+ ), sessionid);
+ goto error;
+ }
+ lim_process_mlm_post_join_suspend_link(mac_ctx,
+ CDF_STATUS_SUCCESS, (uint32_t *)session);
+ } else {
+ lim_log(mac_ctx, LOG1, FL("No need to Suspend link"));
+ /*
+ * No need to Suspend link as LimSession is not
+ * off channel, calling
+ * lim_process_mlm_post_join_suspend_link with
+ * status as SUCCESS.
+ */
+ lim_log(mac_ctx, LOG1,
+ FL("SessionId:%d Join req on current chan"),
+ sessionid);
+ lim_process_mlm_post_join_suspend_link(mac_ctx,
+ CDF_STATUS_SUCCESS, (uint32_t *)session);
+ }
+ return;
+ } else {
+ /**
+ * Should not have received JOIN req in states other than
+ * Idle state or on AP.
+ * Return join confirm with invalid parameters code.
+ */
+ lim_log(mac_ctx, LOGE,
+ FL("Session:%d Unexpected Join req, role %d state %X"),
+ session->peSessionId, GET_LIM_SYSTEM_ROLE(session),
+ session->limMlmState);
+ lim_print_mlm_state(mac_ctx, LOGE, session->limMlmState);
+ }
+
+error:
+ cdf_mem_free(msg);
+ if (session != NULL)
+ session->pLimMlmJoinReq = NULL;
+ mlmjoin_cnf.resultCode = eSIR_SME_RESOURCES_UNAVAILABLE;
+ mlmjoin_cnf.sessionId = sessionid;
+ mlmjoin_cnf.protStatusCode = eSIR_MAC_UNSPEC_FAILURE_STATUS;
+ lim_post_sme_message(mac_ctx, LIM_MLM_JOIN_CNF,
+ (uint32_t *)&mlmjoin_cnf);
+
+}
+
+/**
+ * lim_is_auth_req_expected() - check if auth request is expected
+ *
+ * @mac_ctx: global MAC context
+ * @session: PE session entry
+ *
+ * This function is called by lim_process_mlm_auth_req to check
+ * if auth request is expected.
+ *
+ * Return: true if expected and false otherwise
+ */
+static bool lim_is_auth_req_expected(tpAniSirGlobal mac_ctx,
+ tpPESession session)
+{
+ bool flag = false;
+
+ /*
+ * Expect Auth request only when:
+ * 1. STA joined/associated with a BSS or
+ * 2. STA is in IBSS mode
+ * and STA is going to authenticate with a unicast
+ * address and requested authentication algorithm is
+ * supported.
+ */
+
+ flag = ((((LIM_IS_STA_ROLE(session) ||
+ LIM_IS_BT_AMP_STA_ROLE(session)) &&
+ ((session->limMlmState == eLIM_MLM_JOINED_STATE) ||
+ (session->limMlmState ==
+ eLIM_MLM_LINK_ESTABLISHED_STATE))) ||
+ (LIM_IS_IBSS_ROLE(session) &&
+ (session->limMlmState ==
+ eLIM_MLM_BSS_STARTED_STATE))) &&
+ (!lim_is_group_addr(mac_ctx->lim.gpLimMlmAuthReq->peerMacAddr))
+ && lim_is_auth_algo_supported(mac_ctx,
+ mac_ctx->lim.gpLimMlmAuthReq->authType, session));
+
+ return flag;
+}
+
+/**
+ * lim_is_preauth_ctx_exisits() - check if preauth context exists
+ *
+ * @mac_ctx: global MAC context
+ * @session: PE session entry
+ * @preauth_node_ptr: pointer to preauth node pointer
+ *
+ * This function is called by lim_process_mlm_auth_req to check
+ * if preauth context already exists
+ *
+ * Return: true if exists and false otherwise
+ */
+static bool lim_is_preauth_ctx_exists(tpAniSirGlobal mac_ctx,
+ tpPESession session,
+ struct tLimPreAuthNode **preauth_node_ptr)
+{
+ bool fl = false;
+ struct tLimPreAuthNode *preauth_node;
+ tpDphHashNode stads;
+ tSirMacAddr curr_bssid;
+
+ preauth_node = *preauth_node_ptr;
+ sir_copy_mac_addr(curr_bssid, session->bssId);
+ stads = dph_get_hash_entry(mac_ctx, DPH_STA_HASH_INDEX_PEER,
+ &session->dph.dphHashTable);
+ preauth_node = lim_search_pre_auth_list(mac_ctx,
+ mac_ctx->lim.gpLimMlmAuthReq->peerMacAddr);
+
+ fl = (((LIM_IS_STA_ROLE(session) || LIM_IS_BT_AMP_STA_ROLE(session)) &&
+ (session->limMlmState == eLIM_MLM_LINK_ESTABLISHED_STATE) &&
+ ((stads != NULL) &&
+ (mac_ctx->lim.gpLimMlmAuthReq->authType ==
+ stads->mlmStaContext.authType)) &&
+ (cdf_mem_compare(mac_ctx->lim.gpLimMlmAuthReq->peerMacAddr,
+ curr_bssid, sizeof(tSirMacAddr)))) ||
+ ((preauth_node != NULL) &&
+ (preauth_node->authType ==
+ mac_ctx->lim.gpLimMlmAuthReq->authType)));
+
+ return fl;
+}
+
+/**
+ * lim_process_mlm_auth_req() - process lim auth request
+ *
+ * @mac_ctx: global MAC context
+ * @msg: MLM auth request message
+ *
+ * This function is called to process MLM_AUTH_REQ message from SME
+ *
+ * @Return: None
+ */
+static void lim_process_mlm_auth_req(tpAniSirGlobal mac_ctx, uint32_t *msg)
+{
+ uint32_t num_preauth_ctx;
+ tSirMacAddr curr_bssid;
+ tSirMacAuthFrameBody auth_frame_body;
+ tLimMlmAuthCnf mlm_auth_cnf;
+ struct tLimPreAuthNode *preauth_node = NULL;
+ uint8_t session_id;
+ tpPESession session;
+
+ if (msg == NULL) {
+ lim_log(mac_ctx, LOGE, FL("Buffer is Pointing to NULL"));
+ return;
+ }
+
+ mac_ctx->lim.gpLimMlmAuthReq = (tLimMlmAuthReq *) msg;
+ session_id = mac_ctx->lim.gpLimMlmAuthReq->sessionId;
+ session = pe_find_session_by_session_id(mac_ctx, session_id);
+ if (NULL == session) {
+ lim_log(mac_ctx, LOGP, FL("SessionId:%d does not exist"),
+ session_id);
+ return;
+ }
+
+ lim_log(mac_ctx, LOG1, FL("Process Auth Req sessionID %d Systemrole %d"
+ "mlmstate %d from: " MAC_ADDRESS_STR
+ " with authtype %d"), session_id,
+ GET_LIM_SYSTEM_ROLE(session), session->limMlmState,
+ MAC_ADDR_ARRAY(mac_ctx->lim.gpLimMlmAuthReq->peerMacAddr),
+ mac_ctx->lim.gpLimMlmAuthReq->authType);
+
+ sir_copy_mac_addr(curr_bssid, session->bssId);
+
+ if (!lim_is_auth_req_expected(mac_ctx, session)) {
+ /*
+ * Unexpected auth request.
+ * Return Auth confirm with Invalid parameters code.
+ */
+ mlm_auth_cnf.resultCode = eSIR_SME_INVALID_PARAMETERS;
+ goto end;
+ }
+
+ /*
+ * This is a request for pre-authentication. Check if there exists
+ * context already for the requested peer OR
+ * if this request is for the AP we're currently associated with.
+ * If yes, return auth confirm immediately when
+ * requested auth type is same as the one used before.
+ */
+ if (lim_is_preauth_ctx_exists(mac_ctx, session, &preauth_node)) {
+ lim_log(mac_ctx, LOG2,
+ FL("Already have pre-auth context with peer: "
+ MAC_ADDRESS_STR),
+ MAC_ADDR_ARRAY(mac_ctx->lim.gpLimMlmAuthReq->peerMacAddr));
+ mlm_auth_cnf.resultCode = (tSirResultCodes)
+ eSIR_MAC_SUCCESS_STATUS;
+ goto end;
+ } else {
+ if (wlan_cfg_get_int(mac_ctx, WNI_CFG_MAX_NUM_PRE_AUTH,
+ (uint32_t *) &num_preauth_ctx) != eSIR_SUCCESS)
+ lim_log(mac_ctx, LOGP,
+ FL("Could not retrieve NumPreAuthLimit from CFG"));
+
+ if (mac_ctx->lim.gLimNumPreAuthContexts == num_preauth_ctx) {
+ lim_log(mac_ctx, LOGW,
+ FL("Number of pre-auth reached max limit"));
+ /* Return Auth confirm with reject code */
+ mlm_auth_cnf.resultCode =
+ eSIR_SME_MAX_NUM_OF_PRE_AUTH_REACHED;
+ goto end;
+ }
+ }
+
+ /* Delete pre-auth node if exists */
+ if (preauth_node)
+ lim_delete_pre_auth_node(mac_ctx,
+ mac_ctx->lim.gpLimMlmAuthReq->peerMacAddr);
+
+ session->limPrevMlmState = session->limMlmState;
+ session->limMlmState = eLIM_MLM_WT_AUTH_FRAME2_STATE;
+ MTRACE(mac_trace(mac_ctx, TRACE_CODE_MLM_STATE, session->peSessionId,
+ session->limMlmState));
+
+ /* Prepare & send Authentication frame */
+ auth_frame_body.authAlgoNumber =
+ (uint8_t) mac_ctx->lim.gpLimMlmAuthReq->authType;
+ auth_frame_body.authTransactionSeqNumber = SIR_MAC_AUTH_FRAME_1;
+ auth_frame_body.authStatusCode = 0;
+#ifdef FEATURE_WLAN_DIAG_SUPPORT
+ lim_diag_event_report(mac_ctx, WLAN_PE_DIAG_AUTH_START_EVENT, session,
+ eSIR_SUCCESS, auth_frame_body.authStatusCode);
+#endif
+
+ lim_send_auth_mgmt_frame(mac_ctx,
+ &auth_frame_body, mac_ctx->lim.gpLimMlmAuthReq->peerMacAddr,
+ LIM_NO_WEP_IN_FC, session);
+
+ /* assign appropriate session_id to the timer object */
+ mac_ctx->lim.limTimers.gLimAuthFailureTimer.sessionId = session_id;
+
+ /* Activate Auth failure timer */
+ MTRACE(mac_trace(mac_ctx, TRACE_CODE_TIMER_ACTIVATE,
+ session->peSessionId, eLIM_AUTH_FAIL_TIMER));
+ if (tx_timer_activate(&mac_ctx->lim.limTimers.gLimAuthFailureTimer)
+ != TX_SUCCESS) {
+ /* Could not start Auth failure timer. */
+ lim_log(mac_ctx, LOGP,
+ FL("could not start Auth failure timer"));
+ /* Cleanup as if auth timer expired */
+ lim_process_auth_failure_timeout(mac_ctx);
+ }
+ return;
+end:
+ cdf_mem_copy((uint8_t *) &mlm_auth_cnf.peerMacAddr,
+ (uint8_t *) &mac_ctx->lim.gpLimMlmAuthReq->peerMacAddr,
+ sizeof(tSirMacAddr));
+
+ mlm_auth_cnf.authType = mac_ctx->lim.gpLimMlmAuthReq->authType;
+ mlm_auth_cnf.sessionId = session_id;
+
+ cdf_mem_free(mac_ctx->lim.gpLimMlmAuthReq);
+ mac_ctx->lim.gpLimMlmAuthReq = NULL;
+ lim_log(mac_ctx, LOG1, "SessionId:%d LimPostSme LIM_MLM_AUTH_CNF ",
+ session_id);
+ lim_post_sme_message(mac_ctx, LIM_MLM_AUTH_CNF,
+ (uint32_t *) &mlm_auth_cnf);
+}
+
+/**
+ * lim_process_mlm_assoc_req() - This function is called to process
+ * MLM_ASSOC_REQ message from SME
+ *
+ * @mac_ctx: Pointer to Global MAC structure
+ * @msg_buf: A pointer to the MLM message buffer
+ *
+ * This function is called to process MLM_ASSOC_REQ message from SME
+ *
+ * @Return None
+ */
+
+static void lim_process_mlm_assoc_req(tpAniSirGlobal mac_ctx, uint32_t *msg_buf)
+{
+ tSirMacAddr curr_bssId;
+ tLimMlmAssocReq *mlm_assoc_req;
+ tLimMlmAssocCnf mlm_assoc_cnf;
+ tpPESession session_entry;
+
+ if (msg_buf == NULL) {
+ lim_log(mac_ctx, LOGE, FL("Buffer is Pointing to NULL"));
+ return;
+ }
+
+ mlm_assoc_req = (tLimMlmAssocReq *) msg_buf;
+ session_entry = pe_find_session_by_session_id(mac_ctx,
+ mlm_assoc_req->sessionId);
+ if (session_entry == NULL) {
+ lim_log(mac_ctx, LOGP,
+ FL("SessionId:%d Session Does not exist"),
+ mlm_assoc_req->sessionId);
+ cdf_mem_free(mlm_assoc_req);
+ return;
+ }
+
+ sir_copy_mac_addr(curr_bssId, session_entry->bssId);
+
+ if (!((!LIM_IS_AP_ROLE(session_entry) &&
+ !LIM_IS_BT_AMP_AP_ROLE(session_entry)) &&
+ (session_entry->limMlmState == eLIM_MLM_AUTHENTICATED_STATE ||
+ session_entry->limMlmState == eLIM_MLM_JOINED_STATE) &&
+ (cdf_mem_compare(mlm_assoc_req->peerMacAddr,
+ curr_bssId, sizeof(tSirMacAddr))))) {
+ /*
+ * Received Association request either in invalid state
+ * or to a peer MAC entity whose address is different
+ * from one that STA is currently joined with or on AP.
+ * Return Assoc confirm with Invalid parameters code.
+ */
+ lim_log(mac_ctx, LOGW,
+ FL("received unexpected MLM_ASSOC_CNF in state %X for role=%d, MAC addr= "
+ MAC_ADDRESS_STR), session_entry->limMlmState,
+ GET_LIM_SYSTEM_ROLE(session_entry),
+ MAC_ADDR_ARRAY(mlm_assoc_req->peerMacAddr));
+ lim_print_mlm_state(mac_ctx, LOGW, session_entry->limMlmState);
+ mlm_assoc_cnf.resultCode = eSIR_SME_INVALID_PARAMETERS;
+ mlm_assoc_cnf.protStatusCode = eSIR_MAC_UNSPEC_FAILURE_STATUS;
+ goto end;
+ }
+
+ /* map the session entry pointer to the AssocFailureTimer */
+ mac_ctx->lim.limTimers.gLimAssocFailureTimer.sessionId =
+ mlm_assoc_req->sessionId;
+#ifdef WLAN_FEATURE_11W
+ /*
+ * Store current MLM state in case ASSOC response returns with
+ * TRY_AGAIN_LATER return code.
+ */
+ if (session_entry->limRmfEnabled) {
+ session_entry->pmfComebackTimerInfo.limPrevMlmState =
+ session_entry->limPrevMlmState;
+ session_entry->pmfComebackTimerInfo.limMlmState =
+ session_entry->limMlmState;
+ }
+#endif /* WLAN_FEATURE_11W */
+
+ session_entry->limPrevMlmState = session_entry->limMlmState;
+ session_entry->limMlmState = eLIM_MLM_WT_ASSOC_RSP_STATE;
+ MTRACE(mac_trace(mac_ctx, TRACE_CODE_MLM_STATE,
+ session_entry->peSessionId,
+ session_entry->limMlmState));
+ lim_log(mac_ctx, LOG1, FL("SessionId:%d Sending Assoc_Req Frame"),
+ session_entry->peSessionId);
+
+ /* Prepare and send Association request frame */
+ lim_send_assoc_req_mgmt_frame(mac_ctx, mlm_assoc_req, session_entry);
+
+ /*
+ * Set the link state to postAssoc, so HW can start receiving frames
+ * from AP.
+ */
+ if ((session_entry->bssType == eSIR_BTAMP_STA_MODE) ||
+ ((session_entry->bssType == eSIR_BTAMP_AP_MODE)
+ && LIM_IS_BT_AMP_STA_ROLE(session_entry))) {
+ if (lim_set_link_state(mac_ctx, eSIR_LINK_BTAMP_POSTASSOC_STATE,
+ curr_bssId, session_entry->selfMacAddr,
+ NULL, NULL) != eSIR_SUCCESS)
+ lim_log(mac_ctx, LOGE,
+ FL("Failed to set the LinkState"));
+ }
+ /* Start association failure timer */
+ MTRACE(mac_trace(mac_ctx, TRACE_CODE_TIMER_ACTIVATE,
+ session_entry->peSessionId, eLIM_ASSOC_FAIL_TIMER));
+ if (tx_timer_activate(&mac_ctx->lim.limTimers.gLimAssocFailureTimer)
+ != TX_SUCCESS) {
+ lim_log(mac_ctx, LOGP,
+ FL("SessionId:%d couldn't start Assoc failure timer"),
+ session_entry->peSessionId);
+ /* Cleanup as if assoc timer expired */
+ lim_process_assoc_failure_timeout(mac_ctx, LIM_ASSOC);
+ }
+
+ return;
+end:
+ /* Update PE session Id */
+ mlm_assoc_cnf.sessionId = mlm_assoc_req->sessionId;
+ /* Free up buffer allocated for assocReq */
+ cdf_mem_free(mlm_assoc_req);
+ lim_post_sme_message(mac_ctx, LIM_MLM_ASSOC_CNF,
+ (uint32_t *) &mlm_assoc_cnf);
+}
+
+/**
+ * lim_process_mlm_reassoc_req() - process mlm reassoc request.
+ *
+ * @mac_ctx: pointer to Global MAC structure
+ * @msg: pointer to the MLM message buffer
+ *
+ * This function is called to process MLM_REASSOC_REQ message
+ * from SME
+ *
+ * Return: None
+ */
+static void lim_process_mlm_reassoc_req(tpAniSirGlobal mac_ctx, uint32_t *msg)
+{
+ uint8_t channel, sec_ch_offset;
+ struct tLimPreAuthNode *auth_node;
+ tLimMlmReassocReq *reassoc_req;
+ tLimMlmReassocCnf reassoc_cnf;
+ tpPESession session;
+
+ if (msg == NULL) {
+ lim_log(mac_ctx, LOGE, FL("Buffer is Pointing to NULL"));
+ return;
+ }
+
+ reassoc_req = (tLimMlmReassocReq *) msg;
+ session = pe_find_session_by_session_id(mac_ctx,
+ reassoc_req->sessionId);
+ if (NULL == session) {
+ lim_log(mac_ctx, LOGE,
+ FL("Session Does not exist for given sessionId %d"),
+ reassoc_req->sessionId);
+ cdf_mem_free(reassoc_req);
+ return;
+ }
+
+ lim_log(mac_ctx, LOG1,
+ FL("Process ReAssoc Req on sessionID %d Systemrole %d mlmstate %d from: " MAC_ADDRESS_STR),
+ reassoc_req->sessionId, GET_LIM_SYSTEM_ROLE(session),
+ session->limMlmState, MAC_ADDR_ARRAY(reassoc_req->peerMacAddr));
+
+ if ((LIM_IS_AP_ROLE(session) ||
+ LIM_IS_BT_AMP_AP_ROLE(session)) ||
+ (session->limMlmState !=
+ eLIM_MLM_LINK_ESTABLISHED_STATE)) {
+ /*
+ * Received Reassoc request in invalid state or
+ * in AP role.Return Reassoc confirm with Invalid
+ * parameters code.
+ */
+
+ lim_log(mac_ctx, LOGW,
+ FL("received unexpected MLM_REASSOC_CNF in state %X for role=%d, MAC addr= " MAC_ADDRESS_STR),
+ session->limMlmState, GET_LIM_SYSTEM_ROLE(session),
+ MAC_ADDR_ARRAY(reassoc_req->peerMacAddr));
+ lim_print_mlm_state(mac_ctx, LOGW, session->limMlmState);
+ reassoc_cnf.resultCode = eSIR_SME_INVALID_PARAMETERS;
+ reassoc_cnf.protStatusCode = eSIR_MAC_UNSPEC_FAILURE_STATUS;
+ goto end;
+ }
+
+ if (session->pLimMlmReassocReq)
+ cdf_mem_free(session->pLimMlmReassocReq);
+
+ /*
+ * Hold Re-Assoc request as part of Session, knock-out mac_ctx
+ * Hold onto Reassoc request parameters
+ */
+ session->pLimMlmReassocReq = reassoc_req;
+
+ /* See if we have pre-auth context with new AP */
+ auth_node = lim_search_pre_auth_list(mac_ctx, session->limReAssocbssId);
+
+ if (!auth_node && (!cdf_mem_compare(reassoc_req->peerMacAddr,
+ session->bssId,
+ sizeof(tSirMacAddr)))) {
+ /*
+ * Either pre-auth context does not exist AND
+ * we are not reassociating with currently
+ * associated AP.
+ * Return Reassoc confirm with not authenticated
+ */
+ reassoc_cnf.resultCode = eSIR_SME_STA_NOT_AUTHENTICATED;
+ reassoc_cnf.protStatusCode = eSIR_MAC_UNSPEC_FAILURE_STATUS;
+
+ goto end;
+ }
+ /* assign the sessionId to the timer object */
+ mac_ctx->lim.limTimers.gLimReassocFailureTimer.sessionId =
+ reassoc_req->sessionId;
+ session->limPrevMlmState = session->limMlmState;
+ session->limMlmState = eLIM_MLM_WT_REASSOC_RSP_STATE;
+ MTRACE(mac_trace(mac_ctx, TRACE_CODE_MLM_STATE, session->peSessionId,
+ session->limMlmState));
+
+ /* Derive channel from BSS description and store it at CFG. */
+ channel = session->limReassocChannelId;
+ sec_ch_offset = session->reAssocHtSecondaryChannelOffset;
+
+ /* Apply previously set configuration at HW */
+ lim_apply_configuration(mac_ctx, session);
+
+ /* store the channel switch sessionEntry in the lim global var */
+ session->channelChangeReasonCode =
+ LIM_SWITCH_CHANNEL_REASSOC;
+
+ /* Switch channel to the new Operating channel for Reassoc */
+ lim_set_channel(mac_ctx, channel,
+ session->ch_center_freq_seg0,
+ session->ch_center_freq_seg1,
+ session->ch_width,
+ session->maxTxPower,
+ session->peSessionId);
+
+ return;
+end:
+ reassoc_cnf.protStatusCode = eSIR_MAC_UNSPEC_FAILURE_STATUS;
+ /* Update PE sessio Id */
+ reassoc_cnf.sessionId = reassoc_req->sessionId;
+ /* Free up buffer allocated for reassocReq */
+ cdf_mem_free(reassoc_req);
+ session->pLimReAssocReq = NULL;
+ lim_post_sme_message(mac_ctx, LIM_MLM_REASSOC_CNF,
+ (uint32_t *) &reassoc_cnf);
+}
+
+/**
+ * lim_process_mlm_disassoc_req_ntf() - process disassoc request notification
+ *
+ * @mac_ctx: global MAC context
+ * @suspend_status: suspend status
+ * @msg: mlm message buffer
+ *
+ * This function is used to process MLM disassoc notification
+ *
+ * Return: None
+ */
+static void
+lim_process_mlm_disassoc_req_ntf(tpAniSirGlobal mac_ctx,
+ CDF_STATUS suspend_status, uint32_t *msg)
+{
+ uint16_t aid;
+ tSirMacAddr curr_bssid;
+ tpDphHashNode stads;
+ tLimMlmDisassocReq *mlm_disassocreq;
+ tLimMlmDisassocCnf mlm_disassoccnf;
+ tpPESession session;
+ extern bool send_disassoc_frame;
+ tLimMlmStates mlm_state;
+
+ if (CDF_STATUS_SUCCESS != suspend_status)
+ lim_log(mac_ctx, LOGE, FL("Suspend Status is not success %X"),
+ suspend_status);
+
+ mlm_disassocreq = (tLimMlmDisassocReq *) msg;
+
+ session = pe_find_session_by_session_id(mac_ctx,
+ mlm_disassocreq->sessionId);
+ if (NULL == session) {
+ lim_log(mac_ctx, LOGE,
+ FL("session does not exist for given sessionId %d"),
+ mlm_disassocreq->sessionId);
+ mlm_disassoccnf.resultCode = eSIR_SME_INVALID_PARAMETERS;
+ goto end;
+ }
+
+ lim_log(mac_ctx, LOG1,
+ FL("Process DisAssoc Req on sessionID %d Systemrole %d"
+ "mlmstate %d from: " MAC_ADDRESS_STR),
+ mlm_disassocreq->sessionId, GET_LIM_SYSTEM_ROLE(session),
+ session->limMlmState,
+ MAC_ADDR_ARRAY(mlm_disassocreq->peerMacAddr));
+
+ sir_copy_mac_addr(curr_bssid, session->bssId);
+
+ switch (GET_LIM_SYSTEM_ROLE(session)) {
+ case eLIM_STA_ROLE:
+ case eLIM_BT_AMP_STA_ROLE:
+ if (!cdf_mem_compare(mlm_disassocreq->peerMacAddr,
+ curr_bssid, sizeof(tSirMacAddr))) {
+ lim_log(mac_ctx, LOGW,
+ FL("received MLM_DISASSOC_REQ with invalid BSS id"));
+ lim_print_mac_addr(mac_ctx,
+ mlm_disassocreq->peerMacAddr, LOGW);
+
+ /* Prepare and Send LIM_MLM_DISASSOC_CNF */
+ mlm_disassoccnf.resultCode =
+ eSIR_SME_INVALID_PARAMETERS;
+ goto end;
+ }
+ break;
+ case eLIM_STA_IN_IBSS_ROLE:
+ break;
+ case eLIM_AP_ROLE:
+ case eLIM_P2P_DEVICE_GO:
+ if (true ==
+ mac_ctx->sap.SapDfsInfo.is_dfs_cac_timer_running) {
+ lim_log(mac_ctx, LOGE,
+ FL("CAC timer is running, drop disassoc from going out"));
+ mlm_disassoccnf.resultCode = eSIR_SME_SUCCESS;
+ goto end;
+ }
+ break;
+ default:
+ break;
+ } /* end switch (GET_LIM_SYSTEM_ROLE(session)) */
+
+ /*
+ * Check if there exists a context for the peer entity
+ * to be disassociated with.
+ */
+ stads = dph_lookup_hash_entry(mac_ctx, mlm_disassocreq->peerMacAddr,
+ &aid, &session->dph.dphHashTable);
+ if (stads)
+ mlm_state = stads->mlmStaContext.mlmState;
+
+ if ((stads == NULL) ||
+ (stads &&
+ ((mlm_state != eLIM_MLM_LINK_ESTABLISHED_STATE) &&
+ (mlm_state != eLIM_MLM_WT_ASSOC_CNF_STATE) &&
+ (mlm_state != eLIM_MLM_ASSOCIATED_STATE)))) {
+ /*
+ * Received LIM_MLM_DISASSOC_REQ for STA that does not
+ * have context or in some transit state.
+ */
+ lim_log(mac_ctx, LOGW,
+ FL("Invalid MLM_DISASSOC_REQ, Addr= " MAC_ADDRESS_STR),
+ MAC_ADDR_ARRAY(mlm_disassocreq->peerMacAddr));
+ if (stads != NULL)
+ lim_log(mac_ctx, LOGE, FL("Sta MlmState : %d"),
+ stads->mlmStaContext.mlmState);
+
+ /* Prepare and Send LIM_MLM_DISASSOC_CNF */
+ mlm_disassoccnf.resultCode = eSIR_SME_INVALID_PARAMETERS;
+ goto end;
+ }
+
+ stads->mlmStaContext.disassocReason = (tSirMacReasonCodes)
+ mlm_disassocreq->reasonCode;
+ stads->mlmStaContext.cleanupTrigger = mlm_disassocreq->disassocTrigger;
+
+ /*
+ * Set state to mlm State to eLIM_MLM_WT_DEL_STA_RSP_STATE
+ * This is to address the issue of race condition between
+ * disconnect request from the HDD and deauth from AP
+ */
+
+ stads->mlmStaContext.mlmState = eLIM_MLM_WT_DEL_STA_RSP_STATE;
+
+ /* Send Disassociate frame to peer entity */
+ if (send_disassoc_frame && (mlm_disassocreq->reasonCode !=
+ eSIR_MAC_DISASSOC_DUE_TO_FTHANDOFF_REASON)) {
+ mac_ctx->lim.limDisassocDeauthCnfReq.pMlmDisassocReq =
+ mlm_disassocreq;
+ /*
+ * Set state to mlm State to eLIM_MLM_WT_DEL_STA_RSP_STATE
+ * This is to address the issue of race condition between
+ * disconnect request from the HDD and deauth from AP
+ */
+ stads->mlmStaContext.mlmState = eLIM_MLM_WT_DEL_STA_RSP_STATE;
+
+ /*
+ * If the reason for disassociation is inactivity of STA, then
+ * dont wait for acknowledgement
+ */
+ if ((mlm_disassocreq->reasonCode ==
+ eSIR_MAC_DISASSOC_DUE_TO_INACTIVITY_REASON) &&
+ LIM_IS_AP_ROLE(session)) {
+ lim_send_disassoc_mgmt_frame(mac_ctx,
+ mlm_disassocreq->reasonCode,
+ mlm_disassocreq->peerMacAddr, session, false);
+
+ /* Send Disassoc CNF and receive path cleanup */
+ lim_send_disassoc_cnf(mac_ctx);
+ } else {
+ lim_send_disassoc_mgmt_frame(mac_ctx,
+ mlm_disassocreq->reasonCode,
+ mlm_disassocreq->peerMacAddr, session, true);
+ /*
+ * Abort Tx so that data frames won't be sent to the AP
+ * after sending Disassoc.
+ */
+ if (LIM_IS_STA_ROLE(session))
+ wma_tx_abort(session->smeSessionId);
+ }
+ } else {
+ /* Disassoc frame is not sent OTA */
+ send_disassoc_frame = 1;
+ /* Receive path cleanup with dummy packet */
+ if (eSIR_SUCCESS !=
+ lim_cleanup_rx_path(mac_ctx, stads, session)) {
+ mlm_disassoccnf.resultCode =
+ eSIR_SME_RESOURCES_UNAVAILABLE;
+ goto end;
+ }
+ /* Free up buffer allocated for mlmDisassocReq */
+ cdf_mem_free(mlm_disassocreq);
+ }
+
+ return;
+
+end:
+ cdf_mem_copy((uint8_t *) &mlm_disassoccnf.peerMacAddr,
+ (uint8_t *) mlm_disassocreq->peerMacAddr,
+ sizeof(tSirMacAddr));
+ mlm_disassoccnf.aid = mlm_disassocreq->aid;
+ mlm_disassoccnf.disassocTrigger = mlm_disassocreq->disassocTrigger;
+
+ /* Update PE session ID */
+ mlm_disassoccnf.sessionId = mlm_disassocreq->sessionId;
+
+ /* Free up buffer allocated for mlmDisassocReq */
+ cdf_mem_free(mlm_disassocreq);
+
+ lim_post_sme_message(mac_ctx, LIM_MLM_DISASSOC_CNF,
+ (uint32_t *) &mlm_disassoccnf);
+}
+
+/**
+ * lim_check_disassoc_deauth_ack_pending() - check if deauth is pending
+ *
+ * @mac_ctx - global MAC context
+ * @sta_mac - station MAC
+ *
+ * This function checks if diassociation or deauthentication is pending for
+ * given station MAC address.
+ *
+ * Return: true if pending and false otherwise.
+ */
+bool lim_check_disassoc_deauth_ack_pending(tpAniSirGlobal mac_ctx,
+ uint8_t *sta_mac)
+{
+ tLimMlmDisassocReq *disassoc_req;
+ tLimMlmDeauthReq *deauth_req;
+
+ disassoc_req = mac_ctx->lim.limDisassocDeauthCnfReq.pMlmDisassocReq;
+ deauth_req = mac_ctx->lim.limDisassocDeauthCnfReq.pMlmDeauthReq;
+ if ((disassoc_req && (cdf_mem_compare((uint8_t *) sta_mac,
+ (uint8_t *) &disassoc_req->peerMacAddr,
+ sizeof(tSirMacAddr)))) ||
+ (deauth_req && (cdf_mem_compare((uint8_t *) sta_mac,
+ (uint8_t *) &deauth_req->peerMacAddr,
+ sizeof(tSirMacAddr))))) {
+ PELOG1(lim_log(mac_ctx, LOG1,
+ FL("Disassoc/Deauth ack pending"));)
+ return true;
+ } else {
+ PELOG1(lim_log(mac_ctx, LOG1,
+ FL("Disassoc/Deauth Ack not pending"));)
+ return false;
+ }
+}
+
+/*
+ * lim_clean_up_disassoc_deauth_req() - cleans up pending disassoc or deauth req
+ *
+ * @mac_ctx: mac_ctx
+ * @sta_mac: sta mac address
+ * @clean_rx_path: flag to indicate whether to cleanup rx path or not
+ *
+ * This function cleans up pending disassoc or deauth req
+ *
+ * Return: void
+ */
+void lim_clean_up_disassoc_deauth_req(tpAniSirGlobal mac_ctx,
+ uint8_t *sta_mac, bool clean_rx_path)
+{
+ tLimMlmDisassocReq *mlm_disassoc_req;
+ tLimMlmDeauthReq *mlm_deauth_req;
+ mlm_disassoc_req = mac_ctx->lim.limDisassocDeauthCnfReq.pMlmDisassocReq;
+ if (mlm_disassoc_req &&
+ (cdf_mem_compare((uint8_t *) sta_mac,
+ (uint8_t *) &mlm_disassoc_req->peerMacAddr,
+ sizeof(tSirMacAddr)))) {
+ if (clean_rx_path) {
+ lim_process_disassoc_ack_timeout(mac_ctx);
+ } else {
+ if (tx_timer_running(
+ &mac_ctx->lim.limTimers.gLimDisassocAckTimer)) {
+ lim_deactivate_and_change_timer(mac_ctx,
+ eLIM_DISASSOC_ACK_TIMER);
+ }
+ cdf_mem_free(mlm_disassoc_req);
+ mac_ctx->lim.limDisassocDeauthCnfReq.pMlmDisassocReq =
+ NULL;
+ }
+ }
+
+ mlm_deauth_req = mac_ctx->lim.limDisassocDeauthCnfReq.pMlmDeauthReq;
+ if (mlm_deauth_req &&
+ (cdf_mem_compare((uint8_t *) sta_mac,
+ (uint8_t *) &mlm_deauth_req->peerMacAddr,
+ sizeof(tSirMacAddr)))) {
+ if (clean_rx_path) {
+ lim_process_deauth_ack_timeout(mac_ctx);
+ } else {
+ if (tx_timer_running(
+ &mac_ctx->lim.limTimers.gLimDeauthAckTimer)) {
+ lim_deactivate_and_change_timer(mac_ctx,
+ eLIM_DEAUTH_ACK_TIMER);
+ }
+ cdf_mem_free(mlm_deauth_req);
+ mac_ctx->lim.limDisassocDeauthCnfReq.pMlmDeauthReq =
+ NULL;
+ }
+ }
+}
+
+/*
+ * lim_process_disassoc_ack_timeout() - wrapper function around
+ * lim_send_disassoc_cnf
+ *
+ * @mac_ctx: mac_ctx
+ *
+ * wrapper function around lim_send_disassoc_cnf
+ *
+ * Return: void
+ */
+void lim_process_disassoc_ack_timeout(tpAniSirGlobal mac_ctx)
+{
+ lim_log(mac_ctx, LOG1, FL(""));
+ lim_send_disassoc_cnf(mac_ctx);
+}
+
+/**
+ * lim_process_mlm_disassoc_req() - This function is called to process
+ * MLM_DISASSOC_REQ message from SME
+ *
+ * @mac_ctx: Pointer to Global MAC structure
+ * @msg_buf: A pointer to the MLM message buffer
+ *
+ * This function is called to process MLM_DISASSOC_REQ message from SME
+ *
+ * @Return: None
+ */
+static void
+lim_process_mlm_disassoc_req(tpAniSirGlobal mac_ctx, uint32_t *msg_buf)
+{
+ tLimMlmDisassocReq *mlm_disassoc_req;
+ tpPESession session;
+
+ if (msg_buf == NULL) {
+ lim_log(mac_ctx, LOGE,
+ FL("Buffer is Pointing to NULL"));
+ return;
+ }
+
+ mlm_disassoc_req = (tLimMlmDisassocReq *) msg_buf;
+ lim_log(mac_ctx, LOG1,
+ FL("Process disassoc req, sessionID %d from: "MAC_ADDRESS_STR),
+ mlm_disassoc_req->sessionId,
+ MAC_ADDR_ARRAY(mlm_disassoc_req->peerMacAddr));
+
+ session = pe_find_session_by_session_id(mac_ctx,
+ mlm_disassoc_req->sessionId);
+ if (NULL == session) {
+ lim_log(mac_ctx, LOGE,
+ FL("session does not exist for given sessionId %d"),
+ mlm_disassoc_req->sessionId);
+ return;
+ }
+
+ lim_process_mlm_disassoc_req_ntf(mac_ctx, CDF_STATUS_SUCCESS,
+ (uint32_t *) msg_buf);
+}
+
+/**
+ * lim_process_mlm_deauth_req_ntf() - This function is process mlm deauth req
+ * notification
+ *
+ * @mac_ctx: Pointer to Global MAC structure
+ * @suspend_status: suspend status
+ * @msg_buf: A pointer to the MLM message buffer
+ *
+ * This function is process mlm deauth req notification
+ *
+ * @Return: None
+ */
+static void
+lim_process_mlm_deauth_req_ntf(tpAniSirGlobal mac_ctx,
+ CDF_STATUS suspend_status, uint32_t *msg_buf)
+{
+ uint16_t aid;
+ tSirMacAddr curr_bssId;
+ tpDphHashNode sta_ds;
+ struct tLimPreAuthNode *auth_node;
+ tLimMlmDeauthReq *mlm_deauth_req;
+ tLimMlmDeauthCnf mlm_deauth_cnf;
+ tpPESession session;
+
+ if (CDF_STATUS_SUCCESS != suspend_status)
+ lim_log(mac_ctx, LOGE, FL("Suspend Status is not success %X"),
+ suspend_status);
+
+ mlm_deauth_req = (tLimMlmDeauthReq *) msg_buf;
+ session = pe_find_session_by_session_id(mac_ctx,
+ mlm_deauth_req->sessionId);
+ if (NULL == session) {
+ lim_log(mac_ctx, LOGE,
+ FL("session does not exist for given sessionId %d"),
+ mlm_deauth_req->sessionId);
+ cdf_mem_free(mlm_deauth_req);
+ return;
+ }
+ lim_log(mac_ctx, LOG1, FL("Process Deauth Req on sessionID %d Systemrole %d"
+ "mlmstate %d from: " MAC_ADDRESS_STR),
+ mlm_deauth_req->sessionId,
+ GET_LIM_SYSTEM_ROLE(session),
+ session->limMlmState,
+ MAC_ADDR_ARRAY(mlm_deauth_req->peerMacAddr));
+ sir_copy_mac_addr(curr_bssId, session->bssId);
+
+ switch (GET_LIM_SYSTEM_ROLE(session)) {
+ case eLIM_STA_ROLE:
+ case eLIM_BT_AMP_STA_ROLE:
+ switch (session->limMlmState) {
+ case eLIM_MLM_IDLE_STATE:
+ /*
+ * Attempting to Deauthenticate with a pre-authenticated
+ * peer. Deauthetiate with peer if there exists a
+ * pre-auth context below.
+ */
+ break;
+ case eLIM_MLM_AUTHENTICATED_STATE:
+ case eLIM_MLM_WT_ASSOC_RSP_STATE:
+ case eLIM_MLM_LINK_ESTABLISHED_STATE:
+ if (!cdf_mem_compare(mlm_deauth_req->peerMacAddr,
+ curr_bssId, sizeof(tSirMacAddr))) {
+ lim_log(mac_ctx, LOGE,
+ FL("received MLM_DEAUTH_REQ with invalid BSS id "
+ "Peer MAC: "MAC_ADDRESS_STR
+ " CFG BSSID Addr : "MAC_ADDRESS_STR),
+ MAC_ADDR_ARRAY(
+ mlm_deauth_req->peerMacAddr),
+ MAC_ADDR_ARRAY(curr_bssId));
+ /* Prepare and Send LIM_MLM_DEAUTH_CNF */
+ mlm_deauth_cnf.resultCode =
+ eSIR_SME_INVALID_PARAMETERS;
+ goto end;
+ }
+
+ if ((session->limMlmState ==
+ eLIM_MLM_AUTHENTICATED_STATE) ||
+ (session->limMlmState ==
+ eLIM_MLM_WT_ASSOC_RSP_STATE)) {
+ /* Send deauth frame to peer entity */
+ lim_send_deauth_mgmt_frame(mac_ctx,
+ mlm_deauth_req->reasonCode,
+ mlm_deauth_req->peerMacAddr,
+ session, false);
+ /* Prepare and Send LIM_MLM_DEAUTH_CNF */
+ mlm_deauth_cnf.resultCode = eSIR_SME_SUCCESS;
+ session->limMlmState = eLIM_MLM_IDLE_STATE;
+ MTRACE(mac_trace(mac_ctx, TRACE_CODE_MLM_STATE,
+ session->peSessionId,
+ session->limMlmState));
+ goto end;
+ }
+ break;
+ default:
+ lim_log(mac_ctx, LOGW,
+ FL("received MLM_DEAUTH_REQ with in state %d for peer "
+ MAC_ADDRESS_STR),
+ session->limMlmState,
+ MAC_ADDR_ARRAY(mlm_deauth_req->peerMacAddr));
+ lim_print_mlm_state(mac_ctx, LOGW,
+ session->limMlmState);
+ /* Prepare and Send LIM_MLM_DEAUTH_CNF */
+ mlm_deauth_cnf.resultCode =
+ eSIR_SME_STA_NOT_AUTHENTICATED;
+
+ goto end;
+ }
+ break;
+ case eLIM_STA_IN_IBSS_ROLE:
+ lim_log(mac_ctx, LOGE, FL("received MLM_DEAUTH_REQ IBSS Mode"));
+ mlm_deauth_cnf.resultCode = eSIR_SME_INVALID_PARAMETERS;
+ goto end;
+ case eLIM_AP_ROLE:
+ case eLIM_P2P_DEVICE_GO:
+ if (true ==
+ mac_ctx->sap.SapDfsInfo.is_dfs_cac_timer_running) {
+ lim_log(mac_ctx, LOGE,
+ FL("CAC timer is running, drop disassoc from going out"));
+ mlm_deauth_cnf.resultCode = eSIR_SME_SUCCESS;
+ goto end;
+ }
+ break;
+
+ default:
+ break;
+ } /* end switch (GET_LIM_SYSTEM_ROLE(session)) */
+
+ /*
+ * Check if there exists a context for the peer entity
+ * to be deauthenticated with.
+ */
+ sta_ds = dph_lookup_hash_entry(mac_ctx, mlm_deauth_req->peerMacAddr,
+ &aid, &session->dph.dphHashTable);
+
+ if (sta_ds == NULL) {
+ /* Check if there exists pre-auth context for this STA */
+ auth_node = lim_search_pre_auth_list(mac_ctx,
+ mlm_deauth_req->peerMacAddr);
+ if (auth_node == NULL) {
+ /*
+ * Received DEAUTH REQ for a STA that is neither
+ * Associated nor Pre-authenticated. Log error,
+ * Prepare and Send LIM_MLM_DEAUTH_CNF
+ */
+ lim_log(mac_ctx, LOGW,
+ FL("received MLM_DEAUTH_REQ in mlme state %d for STA that "
+ "does not have context, Addr="
+ MAC_ADDRESS_STR),
+ session->limMlmState,
+ MAC_ADDR_ARRAY(mlm_deauth_req->peerMacAddr));
+ mlm_deauth_cnf.resultCode =
+ eSIR_SME_STA_NOT_AUTHENTICATED;
+ } else {
+ mlm_deauth_cnf.resultCode = eSIR_SME_SUCCESS;
+ /* Delete STA from pre-auth STA list */
+ lim_delete_pre_auth_node(mac_ctx,
+ mlm_deauth_req->peerMacAddr);
+ /* Send Deauthentication frame to peer entity */
+ lim_send_deauth_mgmt_frame(mac_ctx,
+ mlm_deauth_req->reasonCode,
+ mlm_deauth_req->peerMacAddr,
+ session, false);
+ }
+ goto end;
+ } else if ((sta_ds->mlmStaContext.mlmState !=
+ eLIM_MLM_LINK_ESTABLISHED_STATE) &&
+ (sta_ds->mlmStaContext.mlmState !=
+ eLIM_MLM_WT_ASSOC_CNF_STATE)) {
+ /*
+ * received MLM_DEAUTH_REQ for STA that either has no context or
+ * in some transit state
+ */
+ lim_log(mac_ctx, LOGW,
+ FL("Invalid MLM_DEAUTH_REQ, Addr="MAC_ADDRESS_STR),
+ MAC_ADDR_ARRAY(mlm_deauth_req->peerMacAddr));
+ /* Prepare and Send LIM_MLM_DEAUTH_CNF */
+ mlm_deauth_cnf.resultCode = eSIR_SME_INVALID_PARAMETERS;
+ goto end;
+ }
+ /* sta_ds->mlmStaContext.rxPurgeReq = 1; */
+ sta_ds->mlmStaContext.disassocReason = (tSirMacReasonCodes)
+ mlm_deauth_req->reasonCode;
+ sta_ds->mlmStaContext.cleanupTrigger = mlm_deauth_req->deauthTrigger;
+ mac_ctx->lim.limDisassocDeauthCnfReq.pMlmDeauthReq = mlm_deauth_req;
+ /*
+ * Set state to mlm State to eLIM_MLM_WT_DEL_STA_RSP_STATE
+ * This is to address the issue of race condition between
+ * disconnect request from the HDD and disassoc from
+ * inactivity timer. This will make sure that we will not
+ * process disassoc if deauth is in progress for the station
+ * and thus mlmStaContext.cleanupTrigger will not be overwritten.
+ */
+ sta_ds->mlmStaContext.mlmState = eLIM_MLM_WT_DEL_STA_RSP_STATE;
+ /* Send Deauthentication frame to peer entity */
+ lim_send_deauth_mgmt_frame(mac_ctx, mlm_deauth_req->reasonCode,
+ mlm_deauth_req->peerMacAddr, session, true);
+ return;
+end:
+ cdf_mem_copy((uint8_t *) &mlm_deauth_cnf.peerMacAddr,
+ (uint8_t *) mlm_deauth_req->peerMacAddr,
+ sizeof(tSirMacAddr));
+ mlm_deauth_cnf.deauthTrigger = mlm_deauth_req->deauthTrigger;
+ mlm_deauth_cnf.aid = mlm_deauth_req->aid;
+ mlm_deauth_cnf.sessionId = mlm_deauth_req->sessionId;
+
+ /* Free up buffer allocated for mlmDeauthReq */
+ cdf_mem_free(mlm_deauth_req);
+ lim_post_sme_message(mac_ctx,
+ LIM_MLM_DEAUTH_CNF, (uint32_t *) &mlm_deauth_cnf);
+}
+
+/*
+ * lim_process_deauth_ack_timeout() - wrapper function around
+ * lim_send_deauth_cnf
+ *
+ * @mac_ctx: mac_ctx
+ *
+ * wrapper function around lim_send_deauth_cnf
+ *
+ * Return: void
+ */
+void lim_process_deauth_ack_timeout(tpAniSirGlobal mac_ctx)
+{
+ lim_log(mac_ctx, LOG1, FL(""));
+ lim_send_deauth_cnf(mac_ctx);
+}
+
+/*
+ * lim_process_mlm_deauth_req() - This function is called to process
+ * MLM_DEAUTH_REQ message from SME
+ *
+ * @mac_ctx: Pointer to Global MAC structure
+ * @msg_buf: A pointer to the MLM message buffer
+ *
+ * This function is called to process MLM_DEAUTH_REQ message from SME
+ *
+ * @Return: None
+ */
+static void
+lim_process_mlm_deauth_req(tpAniSirGlobal mac_ctx, uint32_t *msg_buf)
+{
+ tLimMlmDeauthReq *mlm_deauth_req;
+ tpPESession session;
+
+ if (msg_buf == NULL) {
+ PELOGE(lim_log(mac_ctx, LOGE, FL("Buffer is Pointing to NULL"));)
+ return;
+ }
+
+ mlm_deauth_req = (tLimMlmDeauthReq *) msg_buf;
+ lim_log(mac_ctx, LOG1,
+ FL("Process Deauth Req on sessionID %d from: "
+ MAC_ADDRESS_STR),
+ mlm_deauth_req->sessionId,
+ MAC_ADDR_ARRAY(mlm_deauth_req->peerMacAddr));
+
+ session = pe_find_session_by_session_id(mac_ctx,
+ mlm_deauth_req->sessionId);
+ if (NULL == session) {
+ lim_log(mac_ctx, LOGE,
+ FL("session does not exist for given sessionId %d"),
+ mlm_deauth_req->sessionId);
+ return;
+ }
+ lim_process_mlm_deauth_req_ntf(mac_ctx, CDF_STATUS_SUCCESS,
+ (uint32_t *) msg_buf);
+}
+
+/**
+ * lim_process_mlm_set_keys_req() - This function is called to process
+ * MLM_SETKEYS_REQ message from SME
+ *
+ * @mac_ctx: Pointer to Global MAC structure
+ * @msg_buf: A pointer to the MLM message buffer
+ *
+ * This function is called to process MLM_SETKEYS_REQ message from SME
+ *
+ * @Return: None
+ */
+static void
+lim_process_mlm_set_keys_req(tpAniSirGlobal mac_ctx, uint32_t *msg_buf)
+{
+ uint16_t aid;
+ uint16_t sta_idx = 0;
+ uint32_t default_key_id = 0;
+ tSirMacAddr curr_bssid;
+ tpDphHashNode sta_ds;
+ tLimMlmSetKeysReq *mlm_set_keys_req;
+ tLimMlmSetKeysCnf mlm_set_keys_cnf;
+ tpPESession session;
+
+ if (msg_buf == NULL) {
+ lim_log(mac_ctx, LOGE, FL("Buffer is Pointing to NULL"));
+ return;
+ }
+
+ mlm_set_keys_req = (tLimMlmSetKeysReq *) msg_buf;
+ /* Hold onto the SetKeys request parameters */
+ mac_ctx->lim.gpLimMlmSetKeysReq = (void *)mlm_set_keys_req;
+ session = pe_find_session_by_session_id(mac_ctx,
+ mlm_set_keys_req->sessionId);
+ if (NULL == session) {
+ lim_log(mac_ctx, LOGE,
+ FL("session does not exist for given sessionId"));
+ return;
+ }
+
+ lim_log(mac_ctx, LOGW,
+ FL("Received MLM_SETKEYS_REQ with parameters:"
+ "AID [%d], ED Type [%d], # Keys [%d] & Peer MAC Addr - "),
+ mlm_set_keys_req->aid, mlm_set_keys_req->edType,
+ mlm_set_keys_req->numKeys);
+ lim_print_mac_addr(mac_ctx, mlm_set_keys_req->peerMacAddr, LOGW);
+ sir_copy_mac_addr(curr_bssid, session->bssId);
+
+ switch (GET_LIM_SYSTEM_ROLE(session)) {
+ case eLIM_STA_ROLE:
+ case eLIM_BT_AMP_STA_ROLE:
+ /*
+ * In case of TDLS, peerMac address need not be BssId. Skip this
+ * check if TDLS is enabled.
+ */
+#ifndef FEATURE_WLAN_TDLS
+ if ((!lim_is_addr_bc(mlm_set_keys_req->peerMacAddr)) &&
+ (!cdf_mem_compare(mlm_set_keys_req->peerMacAddr,
+ curr_bssid, sizeof(tSirMacAddr)))) {
+ lim_log(mac_ctx, LOGW,
+ FL("Received MLM_SETKEYS_REQ with invalid BSSID"
+ MAC_ADDRESS_STR),
+ MAC_ADDR_ARRAY(mlm_set_keys_req->peerMacAddr));
+ /*
+ * Prepare and Send LIM_MLM_SETKEYS_CNF with error code
+ */
+ mlm_set_keys_cnf.resultCode =
+ eSIR_SME_INVALID_PARAMETERS;
+ goto end;
+ }
+#endif
+ break;
+ case eLIM_STA_IN_IBSS_ROLE:
+ /*
+ * update the IBSS PE session encrption type based on the
+ * key type
+ */
+ session->encryptType = mlm_set_keys_req->edType;
+ break;
+ default:
+ break;
+ }
+
+ /*
+ * Use the "unicast" parameter to determine if the "Group Keys"
+ * are being set.
+ * mlm_set_keys_req->key.unicast = 0 -> Multicast/broadcast
+ * mlm_set_keys_req->key.unicast - 1 -> Unicast keys are being set
+ */
+ if (lim_is_addr_bc(mlm_set_keys_req->peerMacAddr)) {
+ lim_log(mac_ctx, LOG1, FL("Trying to set Group Keys...%d "),
+ mlm_set_keys_req->sessionId);
+ /*
+ * When trying to set Group Keys for any security mode other
+ * than WEP, use the STA Index corresponding to the AP...
+ */
+ switch (mlm_set_keys_req->edType) {
+ case eSIR_ED_CCMP:
+#ifdef WLAN_FEATURE_11W
+ case eSIR_ED_AES_128_CMAC:
+#endif
+ sta_idx = session->staId;
+ break;
+ default:
+ break;
+ }
+ } else {
+ lim_log(mac_ctx, LOG1, FL("Trying to set Unicast Keys..."));
+ /*
+ * Check if there exists a context for the
+ * peer entity for which keys need to be set.
+ */
+ sta_ds = dph_lookup_hash_entry(mac_ctx,
+ mlm_set_keys_req->peerMacAddr, &aid,
+ &session->dph.dphHashTable);
+ if ((sta_ds == NULL) ||
+ ((sta_ds->mlmStaContext.mlmState !=
+ eLIM_MLM_LINK_ESTABLISHED_STATE) &&
+ !LIM_IS_AP_ROLE(session))) {
+ /*
+ * Received LIM_MLM_SETKEYS_REQ for STA that does not
+ * have context or in some transit state.
+ */
+ lim_log(mac_ctx, LOG1,
+ FL("Invalid MLM_SETKEYS_REQ, Addr = "
+ MAC_ADDRESS_STR),
+ MAC_ADDR_ARRAY(mlm_set_keys_req->peerMacAddr));
+ /* Prepare and Send LIM_MLM_SETKEYS_CNF */
+ mlm_set_keys_cnf.resultCode =
+ eSIR_SME_INVALID_PARAMETERS;
+ goto end;
+ } else {
+ sta_idx = sta_ds->staIndex;
+ }
+ }
+
+ if ((mlm_set_keys_req->numKeys == 0)
+ && (mlm_set_keys_req->edType != eSIR_ED_NONE)) {
+ /*
+ * Broadcast/Multicast Keys (for WEP!!) are NOT sent
+ * via this interface!! This indicates to HAL that the WEP Keys
+ * need to be extracted from the CFG and applied to hardware
+ */
+ default_key_id = 0xff;
+ } else if (mlm_set_keys_req->key[0].keyId &&
+ ((mlm_set_keys_req->edType == eSIR_ED_WEP40) ||
+ (mlm_set_keys_req->edType == eSIR_ED_WEP104))) {
+ /*
+ * If the Key Id is non zero and encryption mode is WEP,
+ * the key index is coming from the upper layers so that key
+ * only need to be used as the default tx key, This is being
+ * used only in case of WEP mode in HAL
+ */
+ default_key_id = mlm_set_keys_req->key[0].keyId;
+ } else {
+ default_key_id = 0;
+ }
+ lim_log(mac_ctx, LOG1,
+ FL("Trying to set keys for STA Index [%d], using default_key_id [%d]"),
+ sta_idx, default_key_id);
+
+ if (lim_is_addr_bc(mlm_set_keys_req->peerMacAddr)) {
+ session->limPrevMlmState = session->limMlmState;
+ session->limMlmState = eLIM_MLM_WT_SET_BSS_KEY_STATE;
+ MTRACE(mac_trace(mac_ctx, TRACE_CODE_MLM_STATE,
+ session->peSessionId, session->limMlmState));
+ lim_log(mac_ctx, LOG1, FL("Trying to set Group Keys...%d "),
+ session->peSessionId);
+ /* Package WMA_SET_BSSKEY_REQ message parameters */
+ lim_send_set_bss_key_req(mac_ctx, mlm_set_keys_req, session);
+ return;
+ } else {
+ /*
+ * Package WMA_SET_STAKEY_REQ / WMA_SET_STA_BCASTKEY_REQ message
+ * parameters
+ */
+ lim_send_set_sta_key_req(mac_ctx, mlm_set_keys_req, sta_idx,
+ (uint8_t) default_key_id, session,
+ true);
+ return;
+ }
+end:
+ mlm_set_keys_cnf.sessionId = mlm_set_keys_req->sessionId;
+ lim_post_sme_set_keys_cnf(mac_ctx, mlm_set_keys_req, &mlm_set_keys_cnf);
+}
+
+/**
+ * lim_process_periodic_probe_req_timer() - This function is called to process
+ * periodic probe request to send during scan.
+ *
+ * @mac_ctx: Pointer to Global MAC structure
+ *
+ * This function is called to process periodic probe request to send during scan
+ *
+ * @Return None
+ */
+static void lim_process_periodic_probe_req_timer(tpAniSirGlobal mac_ctx)
+{
+ uint8_t channel_num;
+ uint8_t i = 0;
+ tLimMlmScanReq *mlm_scan_req;
+ tSirRetStatus status = eSIR_SUCCESS;
+ TX_TIMER *probe_req_timer =
+ &mac_ctx->lim.limTimers.gLimPeriodicProbeReqTimer;
+
+ if (cdf_mc_timer_get_current_state(&probe_req_timer->cdf_timer)
+ != CDF_TIMER_STATE_STOPPED) {
+ lim_log(mac_ctx, LOG1, FL("Invalid state of timer"));
+ return;
+ }
+
+ if (!((mac_ctx->lim.gLimMlmState == eLIM_MLM_WT_PROBE_RESP_STATE)
+ && (probe_req_timer->sessionId != 0xff)
+ && (mac_ctx->lim.probeCounter < mac_ctx->lim.maxProbe))) {
+ lim_log(mac_ctx, LOG1,
+ FL("received unexpected Periodic scan timeout in state %X"),
+ mac_ctx->lim.gLimMlmState);
+ return;
+ }
+
+ mlm_scan_req = mac_ctx->lim.gpLimMlmScanReq;
+ lim_log(mac_ctx, LOG1, FL("Scanning : Periodic scanning"));
+ mac_ctx->lim.probeCounter++;
+ /* Periodic channel timer timed out to send probe request. */
+ channel_num = lim_get_current_scan_channel(mac_ctx);
+ do {
+ /*
+ * Prepare and send Probe Request frame for all the SSIDs
+ * present in the saved MLM
+ */
+ status = lim_send_probe_req_mgmt_frame(mac_ctx,
+ &mlm_scan_req->ssId[i], mlm_scan_req->bssId,
+ channel_num, mac_ctx->lim.gSelfMacAddr,
+ mlm_scan_req->dot11mode,
+ mlm_scan_req->uIEFieldLen,
+ (uint8_t *) (mlm_scan_req) +
+ mlm_scan_req->uIEFieldOffset);
+ if (status != eSIR_SUCCESS) {
+ lim_log(mac_ctx, LOGE,
+ FL("send ProbeReq failed for SSID %s on channel: %d"),
+ mlm_scan_req->ssId[i].ssId, channel_num);
+ return;
+ }
+ i++;
+ } while (i < mlm_scan_req->numSsid);
+ /* Activate timer again */
+ MTRACE(mac_trace(mac_ctx, TRACE_CODE_TIMER_ACTIVATE,
+ probe_req_timer->sessionId,
+ eLIM_PERIODIC_PROBE_REQ_TIMER));
+ if (tx_timer_activate(probe_req_timer) != TX_SUCCESS) {
+ lim_log(mac_ctx, LOGP,
+ FL("could not start periodic probe req timer"));
+ return;
+ }
+}
+
+/**
+ * lim_process_join_failure_timeout() - This function is called to process
+ * JoinFailureTimeout
+ *
+ * @mac_ctx: Pointer to Global MAC structure
+ *
+ * This function is called to process JoinFailureTimeout
+ *
+ * @Return None
+ */
+static void lim_process_join_failure_timeout(tpAniSirGlobal mac_ctx)
+{
+ tLimMlmJoinCnf mlm_join_cnf;
+ uint32_t len;
+#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM
+ host_log_rssi_pkt_type *rssi_log = NULL;
+#endif
+ tpPESession session;
+
+ session = pe_find_session_by_session_id(mac_ctx,
+ mac_ctx->lim.limTimers.gLimJoinFailureTimer.sessionId);
+ if (NULL == session) {
+ lim_log(mac_ctx, LOGE,
+ FL("Session Does not exist for given sessionID"));
+ return;
+ }
+#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM
+ WLAN_HOST_DIAG_LOG_ALLOC(rssi_log,
+ host_log_rssi_pkt_type, LOG_WLAN_RSSI_UPDATE_C);
+ if (rssi_log)
+ rssi_log->rssi = session->rssi;
+ WLAN_HOST_DIAG_LOG_REPORT(rssi_log);
+#endif
+
+ if (session->limMlmState == eLIM_MLM_WT_JOIN_BEACON_STATE) {
+ len = sizeof(tSirMacAddr);
+ /* Change timer for future activations */
+ lim_deactivate_and_change_timer(mac_ctx, eLIM_JOIN_FAIL_TIMER);
+ /* Change Periodic probe req timer for future activation */
+ lim_deactivate_and_change_timer(mac_ctx,
+ eLIM_PERIODIC_JOIN_PROBE_REQ_TIMER);
+ /* Issue MLM join confirm with timeout reason code */
+ lim_log(mac_ctx, LOGE,
+ FL("In state eLIM_MLM_WT_JOIN_BEACON_STATE."));
+ lim_log(mac_ctx, LOGE,
+ FL("Join Failure Timeout occurred for session %d with BSS "
+ MAC_ADDRESS_STR),
+ session->peSessionId, MAC_ADDR_ARRAY(session->bssId));
+
+ mlm_join_cnf.resultCode = eSIR_SME_JOIN_TIMEOUT_RESULT_CODE;
+ mlm_join_cnf.protStatusCode = eSIR_MAC_UNSPEC_FAILURE_STATUS;
+ session->limMlmState = eLIM_MLM_IDLE_STATE;
+ MTRACE(mac_trace(mac_ctx, TRACE_CODE_MLM_STATE,
+ session->peSessionId, session->limMlmState));
+ if (lim_set_link_state(mac_ctx, eSIR_LINK_IDLE_STATE,
+ session->bssId, session->selfMacAddr,
+ NULL, NULL) != eSIR_SUCCESS)
+ lim_log(mac_ctx, LOGE,
+ ("Failed to set the LinkState"));
+ /* Update PE session Id */
+ mlm_join_cnf.sessionId = session->peSessionId;
+ /* Freeup buffer allocated to join request */
+ if (session->pLimMlmJoinReq) {
+ cdf_mem_free(session->pLimMlmJoinReq);
+ session->pLimMlmJoinReq = NULL;
+ }
+ lim_post_sme_message(mac_ctx, LIM_MLM_JOIN_CNF,
+ (uint32_t *) &mlm_join_cnf);
+ return;
+ } else {
+ lim_log(mac_ctx, LOGW,
+ FL("received unexpected JOIN failure timeout in state %X"),
+ session->limMlmState);
+ lim_print_mlm_state(mac_ctx, LOGW, session->limMlmState);
+ }
+}
+
+/**
+ * lim_process_periodic_join_probe_req_timer() - This function is called to
+ * process periodic probe request send during joining process.
+ *
+ * @mac_ctx: Pointer to Global MAC structure
+ *
+ * This function is called to process periodic probe request send during
+ * joining process.
+ *
+ * @Return None
+ */
+static void lim_process_periodic_join_probe_req_timer(tpAniSirGlobal mac_ctx)
+{
+ tpPESession session;
+ tSirMacSSid ssid;
+
+ session = pe_find_session_by_session_id(mac_ctx,
+ mac_ctx->lim.limTimers.gLimPeriodicJoinProbeReqTimer.sessionId);
+ if (NULL == session) {
+ lim_log(mac_ctx, LOGE,
+ FL("session does not exist for given SessionId : %d"),
+ mac_ctx->lim.limTimers.gLimPeriodicJoinProbeReqTimer.
+ sessionId);
+ return;
+ }
+
+ if ((true ==
+ tx_timer_running(&mac_ctx->lim.limTimers.gLimJoinFailureTimer))
+ && (session->limMlmState == eLIM_MLM_WT_JOIN_BEACON_STATE)) {
+ cdf_mem_copy(ssid.ssId, session->ssId.ssId,
+ session->ssId.length);
+ ssid.length = session->ssId.length;
+ lim_send_probe_req_mgmt_frame(mac_ctx, &ssid,
+ session->pLimMlmJoinReq->bssDescription.bssId,
+ session->currentOperChannel /*chanNum */,
+ session->selfMacAddr, session->dot11mode,
+ session->pLimJoinReq->addIEScan.length,
+ session->pLimJoinReq->addIEScan.addIEdata);
+ lim_deactivate_and_change_timer(mac_ctx,
+ eLIM_PERIODIC_JOIN_PROBE_REQ_TIMER);
+ /* Activate Join Periodic Probe Req timer */
+ if (tx_timer_activate(
+ &mac_ctx->lim.limTimers.gLimPeriodicJoinProbeReqTimer) !=
+ TX_SUCCESS) {
+ lim_log(mac_ctx, LOGP,
+ FL("could not activate Periodic Join req failure timer"));
+ return;
+ }
+ }
+}
+
+/**
+ * lim_process_auth_failure_timeout() - This function is called to process Min
+ * Channel Timeout during channel scan.
+ *
+ * @mac_ctx: Pointer to Global MAC structure
+ *
+ * This function is called to process Min Channel Timeout during channel scan.
+ *
+ * @Return: None
+ */
+static void lim_process_auth_failure_timeout(tpAniSirGlobal mac_ctx)
+{
+ /* fetch the sessionEntry based on the sessionId */
+ tpPESession session;
+#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM
+ host_log_rssi_pkt_type *rssi_log = NULL;
+#endif
+
+ session = pe_find_session_by_session_id(mac_ctx,
+ mac_ctx->lim.limTimers.gLimAuthFailureTimer.sessionId);
+ if (NULL == session) {
+ lim_log(mac_ctx, LOGP,
+ FL("Session Does not exist for given sessionID"));
+ return;
+ }
+
+ lim_log(mac_ctx, LOGE,
+ FL("received AUTH failure timeout in sessionid %d "
+ "limMlmstate %X limSmeState %X"),
+ session->peSessionId, session->limMlmState,
+ session->limSmeState);
+#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM
+ WLAN_HOST_DIAG_LOG_ALLOC(rssi_log, host_log_rssi_pkt_type,
+ LOG_WLAN_RSSI_UPDATE_C);
+ if (rssi_log)
+ rssi_log->rssi = session->rssi;
+ WLAN_HOST_DIAG_LOG_REPORT(rssi_log);
+#endif
+
+ switch (session->limMlmState) {
+ case eLIM_MLM_WT_AUTH_FRAME2_STATE:
+ case eLIM_MLM_WT_AUTH_FRAME4_STATE:
+ /*
+ * Requesting STA did not receive next auth frame before Auth
+ * Failure timeout. Issue MLM auth confirm with timeout reason
+ * code. Restore default failure timeout
+ */
+ if (CDF_P2P_CLIENT_MODE == session->pePersona
+ && session->defaultAuthFailureTimeout)
+ cfg_set_int(mac_ctx,
+ WNI_CFG_AUTHENTICATE_FAILURE_TIMEOUT,
+ session->defaultAuthFailureTimeout);
+ lim_restore_from_auth_state(mac_ctx,
+ eSIR_SME_AUTH_TIMEOUT_RESULT_CODE,
+ eSIR_MAC_UNSPEC_FAILURE_REASON, session);
+ break;
+ default:
+ /*
+ * Auth failure timer should not have timed out
+ * in states other than wt_auth_frame2/4
+ */
+ lim_log(mac_ctx, LOGE,
+ FL("received unexpected AUTH failure timeout in state %X"),
+ session->limMlmState);
+ lim_print_mlm_state(mac_ctx, LOGE, session->limMlmState);
+ break;
+ }
+}
+
+/**
+ * lim_process_auth_rsp_timeout() - This function is called to process Min
+ * Channel Timeout during channel scan.
+ *
+ * @mac_ctx: Pointer to Global MAC structure
+ *
+ * This function is called to process Min Channel Timeout during channel scan.
+ *
+ * @Return: None
+ */
+static void
+lim_process_auth_rsp_timeout(tpAniSirGlobal mac_ctx, uint32_t auth_idx)
+{
+ struct tLimPreAuthNode *auth_node;
+ tpPESession session;
+ uint8_t session_id;
+
+ auth_node = lim_get_pre_auth_node_from_index(mac_ctx,
+ &mac_ctx->lim.gLimPreAuthTimerTable, auth_idx);
+ if (NULL == auth_node) {
+ lim_log(mac_ctx, LOGW, FL("Invalid auth node"));
+ return;
+ }
+
+ session = pe_find_session_by_bssid(mac_ctx, auth_node->peerMacAddr,
+ &session_id);
+ if (NULL == session) {
+ lim_log(mac_ctx, LOGW,
+ FL("session does not exist for given BSSID "));
+ return;
+ }
+
+ if (LIM_IS_AP_ROLE(session) || LIM_IS_IBSS_ROLE(session)) {
+ if (auth_node->mlmState != eLIM_MLM_WT_AUTH_FRAME3_STATE) {
+ lim_log(mac_ctx, LOGE,
+ FL("received AUTH rsp timeout in unexpected "
+ "state for MAC address: " MAC_ADDRESS_STR),
+ MAC_ADDR_ARRAY(auth_node->peerMacAddr));
+ } else {
+ auth_node->mlmState = eLIM_MLM_AUTH_RSP_TIMEOUT_STATE;
+ auth_node->fTimerStarted = 0;
+ lim_log(mac_ctx, LOG1,
+ FL("AUTH rsp timedout for MAC address "
+ MAC_ADDRESS_STR),
+ MAC_ADDR_ARRAY(auth_node->peerMacAddr));
+ /* Change timer to reactivate it in future */
+ lim_deactivate_and_change_per_sta_id_timer(mac_ctx,
+ eLIM_AUTH_RSP_TIMER, auth_node->authNodeIdx);
+ lim_delete_pre_auth_node(mac_ctx,
+ auth_node->peerMacAddr);
+ }
+ }
+}
+
+/**
+ * lim_process_assoc_failure_timeout() - This function is called to process Min
+ * Channel Timeout during channel scan.
+ *
+ * @mac_ctx Pointer to Global MAC structure
+ *
+ * This function is called to process Min Channel Timeout during channel scan.
+ *
+ * @Return: None
+ */
+static void
+lim_process_assoc_failure_timeout(tpAniSirGlobal mac_ctx, uint32_t msg_type)
+{
+
+ tLimMlmAssocCnf mlm_assoc_cnf;
+ tpPESession session;
+#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM
+ host_log_rssi_pkt_type *rssi_log = NULL;
+#endif
+ /*
+ * to fetch the lim/mlm state based on the session_id, use the
+ * below sessionEntry
+ */
+ uint8_t session_id;
+
+ if (msg_type == LIM_ASSOC)
+ session_id =
+ mac_ctx->lim.limTimers.gLimAssocFailureTimer.sessionId;
+ else
+ session_id =
+ mac_ctx->lim.limTimers.gLimReassocFailureTimer.sessionId;
+
+ session = pe_find_session_by_session_id(mac_ctx, session_id);
+ if (NULL == session) {
+ lim_log(mac_ctx, LOGP,
+ FL("Session Does not exist for given sessionID"));
+ return;
+ }
+#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM
+ WLAN_HOST_DIAG_LOG_ALLOC(rssi_log,
+ host_log_rssi_pkt_type,
+ LOG_WLAN_RSSI_UPDATE_C);
+ if (rssi_log)
+ rssi_log->rssi = session->rssi;
+ WLAN_HOST_DIAG_LOG_REPORT(rssi_log);
+#endif
+
+ lim_log(mac_ctx, LOG1,
+ FL("Re/Association Response not received before timeout "));
+
+ if ((LIM_IS_AP_ROLE(session) || LIM_IS_BT_AMP_AP_ROLE(session)) ||
+ ((session->limMlmState != eLIM_MLM_WT_ASSOC_RSP_STATE) &&
+ (session->limMlmState != eLIM_MLM_WT_REASSOC_RSP_STATE) &&
+ (session->limMlmState != eLIM_MLM_WT_FT_REASSOC_RSP_STATE))) {
+ /*
+ * Re/Assoc failure timer should not have timedout on AP
+ * or in a state other than wt_re/assoc_response.
+ */
+ lim_log(mac_ctx, LOGW,
+ FL("received unexpected REASSOC failure timeout in state %X for role %d"),
+ session->limMlmState,
+ GET_LIM_SYSTEM_ROLE(session));
+ lim_print_mlm_state(mac_ctx, LOGW, session->limMlmState);
+ return;
+ }
+
+ if ((msg_type == LIM_ASSOC) || ((msg_type == LIM_REASSOC)
+ && (session->limMlmState == eLIM_MLM_WT_FT_REASSOC_RSP_STATE))) {
+ lim_log(mac_ctx, LOGE,
+ FL("(Re)Assoc Failure Timeout occurred."));
+ session->limMlmState = eLIM_MLM_IDLE_STATE;
+ MTRACE(mac_trace(mac_ctx, TRACE_CODE_MLM_STATE,
+ session->peSessionId, session->limMlmState));
+ /* Change timer for future activations */
+ lim_deactivate_and_change_timer(mac_ctx, eLIM_ASSOC_FAIL_TIMER);
+ /*
+ * Free up buffer allocated for JoinReq held by
+ * MLM state machine
+ */
+ if (session->pLimMlmJoinReq) {
+ cdf_mem_free(session->pLimMlmJoinReq);
+ session->pLimMlmJoinReq = NULL;
+ }
+ /* To remove the preauth node in case of fail to associate */
+ if (lim_search_pre_auth_list(mac_ctx, session->bssId)) {
+ lim_log(mac_ctx, LOG1,
+ FL(" delete pre auth node for "MAC_ADDRESS_STR),
+ MAC_ADDR_ARRAY(session->bssId));
+ lim_delete_pre_auth_node(mac_ctx,
+ session->bssId);
+ }
+
+ mlm_assoc_cnf.resultCode = eSIR_SME_ASSOC_TIMEOUT_RESULT_CODE;
+ mlm_assoc_cnf.protStatusCode = eSIR_MAC_UNSPEC_FAILURE_STATUS;
+ /* Update PE session Id */
+ mlm_assoc_cnf.sessionId = session->peSessionId;
+ if (msg_type == LIM_ASSOC) {
+ lim_post_sme_message(mac_ctx, LIM_MLM_ASSOC_CNF,
+ (uint32_t *) &mlm_assoc_cnf);
+ } else {
+ /*
+ * Will come here only in case of 11r, Ese FT
+ * when reassoc rsp is not received and we
+ * receive a reassoc - timesout
+ */
+ mlm_assoc_cnf.resultCode =
+ eSIR_SME_FT_REASSOC_TIMEOUT_FAILURE;
+ lim_post_sme_message(mac_ctx, LIM_MLM_REASSOC_CNF,
+ (uint32_t *) &mlm_assoc_cnf);
+ }
+ } else {
+ /*
+ * Restore pre-reassoc req state.
+ * Set BSSID to currently associated AP address.
+ */
+ session->limMlmState = session->limPrevMlmState;
+ MTRACE(mac_trace(mac_ctx, TRACE_CODE_MLM_STATE,
+ session->peSessionId, session->limMlmState));
+ lim_restore_pre_reassoc_state(mac_ctx,
+ eSIR_SME_REASSOC_TIMEOUT_RESULT_CODE,
+ eSIR_MAC_UNSPEC_FAILURE_STATUS, session);
+ }
+}
+
+/**
+ * lim_complete_mlm_scan() - This function is called to send MLM_SCAN_CNF
+ * message to SME state machine.
+ *
+ * @mac_ctx: Pointer to Global MAC structure
+ * @ret_code: Result code to be sent
+ *
+ * This function is called to send MLM_SCAN_CNF message to SME state machine.
+ *
+ * @Return: None
+ */
+
+void lim_complete_mlm_scan(tpAniSirGlobal mac_ctx, tSirResultCodes ret_code)
+{
+ tLimMlmScanCnf mlm_scan_cnf;
+
+ /* Restore previous MLM state */
+ mac_ctx->lim.gLimMlmState = mac_ctx->lim.gLimPrevMlmState;
+ MTRACE(mac_trace(mac_ctx, TRACE_CODE_MLM_STATE, NO_SESSION,
+ mac_ctx->lim.gLimMlmState));
+ lim_restore_pre_scan_state(mac_ctx);
+ /* Free up mac_ctx->lim.gLimMlmScanReq */
+ if (NULL != mac_ctx->lim.gpLimMlmScanReq) {
+ cdf_mem_free(mac_ctx->lim.gpLimMlmScanReq);
+ mac_ctx->lim.gpLimMlmScanReq = NULL;
+ }
+
+ mlm_scan_cnf.resultCode = ret_code;
+ lim_post_sme_message(mac_ctx, LIM_MLM_SCAN_CNF,
+ (uint32_t *) &mlm_scan_cnf);
+}
+
+/**
+ * lim_set_channel() - set channel api for lim
+ *
+ * @mac_ctx: Pointer to Global MAC structure
+ * @channel: power save state
+ * @ch_center_freq_seg0: center freq seq 0
+ * @ch_center_freq_seg1: center freq seq 1
+ * @ch_width: channel width
+ * @max_tx_power: max tx power
+ * @pe_session_id: pe session id
+ *
+ * set channel api for lim
+ *
+ * @Return: None
+ */
+void lim_set_channel(tpAniSirGlobal mac_ctx, uint8_t channel,
+ uint8_t ch_center_freq_seg0, uint8_t ch_center_freq_seg1,
+ phy_ch_width ch_width, tPowerdBm max_tx_power,
+ uint8_t pe_session_id)
+{
+#if !defined WLAN_FEATURE_VOWIFI
+ uint32_t localPwrConstraint;
+#endif
+ tpPESession pe_session;
+ pe_session = pe_find_session_by_session_id(mac_ctx, pe_session_id);
+
+ if (NULL == pe_session) {
+ lim_log(mac_ctx, LOGP, FL("Invalid PE session = %d"),
+ pe_session_id);
+ return;
+ }
+#if defined WLAN_FEATURE_VOWIFI
+ lim_send_switch_chnl_params(mac_ctx, channel, ch_center_freq_seg0,
+ ch_center_freq_seg1, ch_width,
+ max_tx_power, pe_session_id, false);
+#else
+ if (wlan_cfg_get_int(mac_ctx, WNI_CFG_LOCAL_POWER_CONSTRAINT,
+ &localPwrConstraint) != eSIR_SUCCESS) {
+ lim_log(mac_ctx, LOGP,
+ FL("couldn't read CFG_LOCAL_POWER_CONSTRAINT"));
+ return;
+ }
+ /* Send WMA_CHNL_SWITCH_IND to HAL */
+ lim_send_switch_chnl_params(mac_ctx, channel, ch_center_freq_seg0,
+ ch_center_freq_seg1, ch_width,
+ (tPowerdBm) localPwrConstraint,
+ pe_session_id, false);
+#endif
+}
diff --git a/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c b/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c
new file mode 100644
index 0000000..4450acd
--- /dev/null
+++ b/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c
@@ -0,0 +1,4200 @@
+/*
+ * Copyright (c) 2012-2015 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.
+ */
+
+#include "wni_api.h"
+#include "wni_cfg.h"
+#include "cfg_api.h"
+#include "sir_api.h"
+#include "sch_api.h"
+#include "utils_api.h"
+#include "lim_utils.h"
+#include "lim_assoc_utils.h"
+#include "lim_security_utils.h"
+#include "lim_ser_des_utils.h"
+#include "lim_timer_utils.h"
+#include "lim_send_messages.h"
+#include "lim_admit_control.h"
+#include "lim_send_messages.h"
+#include "lim_ibss_peer_mgmt.h"
+#ifdef WLAN_FEATURE_VOWIFI_11R
+#include "lim_ft.h"
+#include "lim_ft_defs.h"
+#endif
+#include "lim_session.h"
+#include "lim_session_utils.h"
+#if defined WLAN_FEATURE_VOWIFI
+#include "rrm_api.h"
+#endif
+#include "wma_types.h"
+#include "cds_utils.h"
+#include "lim_types.h"
+
+#define MAX_SUPPORTED_PEERS_WEP 16
+
+static void lim_handle_sme_join_result(tpAniSirGlobal, tSirResultCodes, uint16_t,
+ tpPESession);
+static void lim_handle_sme_reaasoc_result(tpAniSirGlobal, tSirResultCodes, uint16_t,
+ tpPESession);
+
+#ifdef FEATURE_OEM_DATA_SUPPORT
+void lim_process_mlm_oem_data_req_cnf(tpAniSirGlobal, uint32_t *);
+#endif
+void lim_process_mlm_join_cnf(tpAniSirGlobal, uint32_t *);
+void lim_process_mlm_auth_cnf(tpAniSirGlobal, uint32_t *);
+void lim_process_mlm_start_cnf(tpAniSirGlobal, uint32_t *);
+void lim_process_mlm_assoc_ind(tpAniSirGlobal, uint32_t *);
+void lim_process_mlm_assoc_cnf(tpAniSirGlobal, uint32_t *);
+void lim_process_mlm_reassoc_cnf(tpAniSirGlobal, uint32_t *);
+void lim_process_mlm_reassoc_ind(tpAniSirGlobal, uint32_t *);
+void lim_process_mlm_set_keys_cnf(tpAniSirGlobal, uint32_t *);
+void lim_process_mlm_disassoc_ind(tpAniSirGlobal, uint32_t *);
+void lim_process_mlm_disassoc_cnf(tpAniSirGlobal, uint32_t *);
+void lim_process_mlm_deauth_ind(tpAniSirGlobal, uint32_t *);
+void lim_process_mlm_deauth_cnf(tpAniSirGlobal, uint32_t *);
+void lim_process_mlm_purge_sta_ind(tpAniSirGlobal, uint32_t *);
+static void lim_handle_del_bss_in_re_assoc_context(tpAniSirGlobal pMac,
+ tpDphHashNode pStaDs,
+ tpPESession psessionEntry);
+void lim_get_session_info(tpAniSirGlobal pMac, uint8_t *, uint8_t *, uint16_t *);
+static void
+lim_process_btamp_add_bss_rsp(tpAniSirGlobal pMac, tpSirMsgQ limMsgQ,
+ tpPESession psessionEntry);
+/**
+ * lim_process_mlm_rsp_messages()
+ *
+ ***FUNCTION:
+ * This function is called to processes various MLM response (CNF/IND
+ * messages from MLM State machine.
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ *
+ ***NOTE:
+ *
+ * @param pMac Pointer to Global MAC structure
+ * @param msgType Indicates the MLM message type
+ * @param *pMsgBuf A pointer to the MLM message buffer
+ *
+ * @return None
+ */
+void
+lim_process_mlm_rsp_messages(tpAniSirGlobal pMac, uint32_t msgType,
+ uint32_t *pMsgBuf)
+{
+
+ if (pMsgBuf == NULL) {
+ PELOGE(lim_log(pMac, LOGE, FL("Buffer is Pointing to NULL"));)
+ return;
+ }
+ MTRACE(mac_trace(pMac, TRACE_CODE_TX_LIM_MSG, 0, msgType));
+ switch (msgType) {
+
+#ifdef FEATURE_OEM_DATA_SUPPORT
+ case LIM_MLM_OEM_DATA_CNF:
+ lim_process_mlm_oem_data_req_cnf(pMac, pMsgBuf);
+ pMsgBuf = NULL;
+ break;
+#endif
+
+ case LIM_MLM_AUTH_CNF:
+ lim_process_mlm_auth_cnf(pMac, pMsgBuf);
+ break;
+ case LIM_MLM_ASSOC_CNF:
+ lim_process_mlm_assoc_cnf(pMac, pMsgBuf);
+ break;
+ case LIM_MLM_START_CNF:
+ lim_process_mlm_start_cnf(pMac, pMsgBuf);
+ break;
+ case LIM_MLM_JOIN_CNF:
+ lim_process_mlm_join_cnf(pMac, pMsgBuf);
+ break;
+ case LIM_MLM_ASSOC_IND:
+ lim_process_mlm_assoc_ind(pMac, pMsgBuf);
+ break;
+ case LIM_MLM_REASSOC_CNF:
+ lim_process_mlm_reassoc_cnf(pMac, pMsgBuf);
+ break;
+ case LIM_MLM_DISASSOC_CNF:
+ lim_process_mlm_disassoc_cnf(pMac, pMsgBuf);
+ break;
+ case LIM_MLM_DISASSOC_IND:
+ lim_process_mlm_disassoc_ind(pMac, pMsgBuf);
+ break;
+ case LIM_MLM_PURGE_STA_IND:
+ lim_process_mlm_purge_sta_ind(pMac, pMsgBuf);
+ break;
+ case LIM_MLM_DEAUTH_CNF:
+ lim_process_mlm_deauth_cnf(pMac, pMsgBuf);
+ break;
+ case LIM_MLM_DEAUTH_IND:
+ lim_process_mlm_deauth_ind(pMac, pMsgBuf);
+ break;
+ case LIM_MLM_SETKEYS_CNF:
+ lim_process_mlm_set_keys_cnf(pMac, pMsgBuf);
+ break;
+ case LIM_MLM_TSPEC_CNF:
+ break;
+ default:
+ break;
+ } /* switch (msgType) */
+ return;
+} /*** end lim_process_mlm_rsp_messages() ***/
+
+#ifdef FEATURE_OEM_DATA_SUPPORT
+
+/**
+ * lim_process_mlm_oem_data_req_cnf()
+ *
+ ***FUNCTION:
+ * This function is called to processes LIM_MLM_OEM_DATA_REQ_CNF
+ * message from MLM State machine.
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ *
+ ***NOTE:
+ *
+ * @param pMac Pointer to Global MAC structure
+ * @param pMsgBuf A pointer to the MLM message buffer
+ *
+ * @return None
+ */
+
+void lim_process_mlm_oem_data_req_cnf(tpAniSirGlobal pMac, uint32_t *pMsgBuf)
+{
+ tLimMlmOemDataRsp *measRsp;
+
+ tSirResultCodes resultCode = eSIR_SME_SUCCESS;
+
+ measRsp = (tLimMlmOemDataRsp *) (pMsgBuf);
+
+ /* Now send the meas confirm message to the sme */
+ lim_send_sme_oem_data_rsp(pMac, (uint32_t *) measRsp, resultCode);
+
+ /* Dont free the memory here. It will be freed up by the callee */
+
+ return;
+}
+#endif
+
+/**
+ * lim_process_mlm_start_cnf()
+ *
+ ***FUNCTION:
+ * This function is called to processes MLM_START_CNF
+ * message from MLM State machine.
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ *
+ ***NOTE:
+ *
+ * @param pMac Pointer to Global MAC structure
+ * @param pMsgBuf A pointer to the MLM message buffer
+ *
+ * @return None
+ */
+void lim_process_mlm_start_cnf(tpAniSirGlobal pMac, uint32_t *pMsgBuf)
+{
+ tpPESession psessionEntry = NULL;
+ tLimMlmStartCnf *pLimMlmStartCnf;
+ uint8_t smesessionId;
+ uint16_t smetransactionId;
+ uint8_t channelId;
+
+ if (pMsgBuf == NULL) {
+ PELOGE(lim_log(pMac, LOGE, FL("Buffer is Pointing to NULL"));)
+ return;
+ }
+ pLimMlmStartCnf = (tLimMlmStartCnf *) pMsgBuf;
+ psessionEntry = pe_find_session_by_session_id(pMac,
+ pLimMlmStartCnf->sessionId);
+ if (psessionEntry == NULL) {
+ PELOGE(lim_log(pMac, LOGE, FL(
+ "Session does Not exist with given sessionId "));)
+ return;
+ }
+ smesessionId = psessionEntry->smeSessionId;
+ smetransactionId = psessionEntry->transactionId;
+
+ if (psessionEntry->limSmeState != eLIM_SME_WT_START_BSS_STATE) {
+ /*
+ * Should not have received Start confirm from MLM
+ * in other states. Log error.
+ */
+ PELOGE(lim_log(pMac, LOGE, FL
+ ("received unexpected MLM_START_CNF in state %X"),
+ psessionEntry->limSmeState);)
+ return;
+ }
+ if (((tLimMlmStartCnf *) pMsgBuf)->resultCode == eSIR_SME_SUCCESS) {
+
+ /*
+ * Update global SME state so that Beacon Generation
+ * module starts writing Beacon frames into TFP's
+ * Beacon file register.
+ */
+ psessionEntry->limSmeState = eLIM_SME_NORMAL_STATE;
+ MTRACE(mac_trace
+ (pMac, TRACE_CODE_SME_STATE, psessionEntry->peSessionId,
+ psessionEntry->limSmeState));
+ if (psessionEntry->bssType == eSIR_BTAMP_STA_MODE) {
+ lim_log(pMac, LOG1,
+ FL("*** Started BSS in BT_AMP STA SIDE***"));
+ } else if (psessionEntry->bssType == eSIR_BTAMP_AP_MODE) {
+ lim_log(pMac, LOG1,
+ FL("*** Started BSS in BT_AMP AP SIDE***"));
+ } else if (psessionEntry->bssType == eSIR_INFRA_AP_MODE) {
+ lim_log(pMac, LOG1,
+ FL("*** Started BSS in INFRA AP SIDE***"));
+ } else
+ PELOG1(lim_log(pMac, LOG1, FL("*** Started BSS ***"));)
+ } else {
+ /* Start BSS is a failure */
+ pe_delete_session(pMac, psessionEntry);
+ psessionEntry = NULL;
+ PELOGE(lim_log(pMac, LOGE, FL("Start BSS Failed "));)
+ }
+ /* Send response to Host */
+ lim_send_sme_start_bss_rsp(pMac, eWNI_SME_START_BSS_RSP,
+ ((tLimMlmStartCnf *)pMsgBuf)->resultCode,
+ psessionEntry, smesessionId, smetransactionId);
+ if ((psessionEntry != NULL) &&
+ (((tLimMlmStartCnf *) pMsgBuf)->resultCode ==
+ eSIR_SME_SUCCESS)) {
+ channelId = psessionEntry->pLimStartBssReq->channelId;
+
+ /* We should start beacon transmission only if the channel
+ * on which we are operating is non-DFS until the channel
+ * availability check is done. The PE will receive an explicit
+ * request from upper layers to start the beacon transmission
+ */
+
+ if (LIM_IS_IBSS_ROLE(psessionEntry) ||
+ (LIM_IS_AP_ROLE(psessionEntry) &&
+ (cds_get_channel_state(channelId) !=
+ CHANNEL_STATE_DFS))) {
+ /* Configure beacon and send beacons to HAL */
+ CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_INFO,
+ FL("Start Beacon with ssid %s Ch %d"),
+ psessionEntry->ssId.ssId,
+ psessionEntry->currentOperChannel);
+ lim_send_beacon_ind(pMac, psessionEntry);
+ }
+ }
+}
+
+/*** end lim_process_mlm_start_cnf() ***/
+
+/**
+ * lim_process_mlm_join_cnf() - Processes join confirmation
+ * @mac_ctx: Pointer to Global MAC structure
+ * @msg: A pointer to the MLM message buffer
+ *
+ * This Function handles the join confirmation message
+ * LIM_MLM_JOIN_CNF.
+ *
+ * Return: None
+ */
+void lim_process_mlm_join_cnf(tpAniSirGlobal mac_ctx,
+ uint32_t *msg)
+{
+ tSirResultCodes result_code;
+ tLimMlmJoinCnf *join_cnf;
+ tpPESession session_entry;
+
+ join_cnf = (tLimMlmJoinCnf *) msg;
+ session_entry = pe_find_session_by_session_id(mac_ctx,
+ join_cnf->sessionId);
+ if (session_entry == NULL) {
+ lim_log(mac_ctx, LOGE, FL("SessionId:%d does not exist"),
+ join_cnf->sessionId);
+ return;
+ }
+
+ if (session_entry->limSmeState != eLIM_SME_WT_JOIN_STATE) {
+ lim_log(mac_ctx, LOGE,
+ FL("received unexpected MLM_JOIN_CNF in state %X"),
+ session_entry->limSmeState);
+ return;
+ }
+
+ result_code = ((tLimMlmJoinCnf *) msg)->resultCode;
+ /* Process Join confirm from MLM */
+ if (result_code == eSIR_SME_SUCCESS) {
+ lim_log(mac_ctx, LOG1, FL("***SessionId:%d Joined ESS ***"),
+ join_cnf->sessionId);
+ /* Setup hardware upfront */
+ if (lim_sta_send_add_bss_pre_assoc(mac_ctx, false,
+ session_entry) == eSIR_SUCCESS)
+ return;
+ else
+ result_code = eSIR_SME_REFUSED;
+ }
+
+ /* Join failure */
+ session_entry->limSmeState = eLIM_SME_JOIN_FAILURE_STATE;
+ MTRACE(mac_trace(mac_ctx, TRACE_CODE_SME_STATE,
+ session_entry->peSessionId,
+ session_entry->limSmeState));
+ /* Send Join response to Host */
+ lim_handle_sme_join_result(mac_ctx, result_code,
+ ((tLimMlmJoinCnf *) msg)->protStatusCode, session_entry);
+ return;
+}
+
+/**
+ * lim_send_mlm_assoc_req() - Association request will be processed
+ * mac_ctx: Pointer to Global MAC structure
+ * session_entry: Pointer to session etnry
+ *
+ * This function is sends ASSOC request MLM message to MLM State machine.
+ * ASSOC request packet would be by picking parameters from psessionEntry
+ * automatically based on the current state of MLM state machine.
+ * ASSUMPTIONS:
+ * this function is called in middle of connection state machine and is
+ * expected to be called after auth cnf has been received or after ASSOC rsp
+ * with TRY_AGAIN_LATER was received and required time has elapsed after that.
+ *
+ * Return: None
+ */
+
+void lim_send_mlm_assoc_req(tpAniSirGlobal mac_ctx,
+ tpPESession session_entry)
+{
+ tLimMlmAssocReq *assoc_req;
+ uint32_t val;
+ uint16_t caps;
+ uint32_t tele_bcn = 0;
+ tpSirMacCapabilityInfo cap_info;
+
+ /* Successful MAC based authentication. Trigger Association with BSS */
+ lim_log(mac_ctx, LOG1, FL("SessionId:%d Authenticated with BSS"),
+ session_entry->peSessionId);
+
+ if (NULL == session_entry->pLimJoinReq) {
+ lim_log(mac_ctx, LOGE, FL("Join Request is NULL."));
+ /* No need to Assert. JOIN timeout will handle this error */
+ return;
+ }
+
+ assoc_req = cdf_mem_malloc(sizeof(tLimMlmAssocReq));
+ if (NULL == assoc_req) {
+ lim_log(mac_ctx, LOGP,
+ FL("call to AllocateMemory failed for mlmAssocReq"));
+ return;
+ }
+ val = sizeof(tSirMacAddr);
+ sir_copy_mac_addr(assoc_req->peerMacAddr, session_entry->bssId);
+ if (wlan_cfg_get_int(mac_ctx, WNI_CFG_ASSOCIATION_FAILURE_TIMEOUT,
+ (uint32_t *) &assoc_req->assocFailureTimeout)
+ != eSIR_SUCCESS) {
+ /* Could not get AssocFailureTimeout value from CFG.*/
+ lim_log(mac_ctx, LOGP,
+ FL("could not retrieve AssocFailureTimeout value"));
+ }
+
+ if (cfg_get_capability_info(mac_ctx, &caps, session_entry)
+ != eSIR_SUCCESS)
+ /* Could not get Capabilities value from CFG.*/
+ lim_log(mac_ctx, LOGP,
+ FL("could not retrieve Capabilities value"));
+
+ /* Clear spectrum management bit if AP doesn't support it */
+ if (!(session_entry->pLimJoinReq->bssDescription.capabilityInfo &
+ LIM_SPECTRUM_MANAGEMENT_BIT_MASK))
+ /*
+ * AP doesn't support spectrum management
+ * clear spectrum management bit
+ */
+ caps &= (~LIM_SPECTRUM_MANAGEMENT_BIT_MASK);
+
+ /* Clear rrm bit if AP doesn't support it */
+ if (!(session_entry->pLimJoinReq->bssDescription.capabilityInfo
+ & LIM_RRM_BIT_MASK))
+ caps &= (~LIM_RRM_BIT_MASK);
+
+ /* Clear short preamble bit if AP does not support it */
+ if (!(session_entry->pLimJoinReq->bssDescription.capabilityInfo &
+ (LIM_SHORT_PREAMBLE_BIT_MASK))) {
+ caps &= (~LIM_SHORT_PREAMBLE_BIT_MASK);
+ lim_log(mac_ctx, LOG1,
+ FL("Clearing short preamble:no AP support"));
+ }
+
+ /* Clear immediate block ack bit if AP does not support it */
+ if (!(session_entry->pLimJoinReq->bssDescription.capabilityInfo &
+ (LIM_IMMEDIATE_BLOCK_ACK_MASK))) {
+ caps &= (~LIM_IMMEDIATE_BLOCK_ACK_MASK);
+ lim_log(mac_ctx, LOG1,
+ FL("Clearing Immed Blk Ack:no AP support"));
+ }
+
+ assoc_req->capabilityInfo = caps;
+ cap_info = ((tpSirMacCapabilityInfo) &assoc_req->capabilityInfo);
+ lim_log(mac_ctx, LOG3, FL("Capabilities to be used in AssocReq=0x%X,"
+ "privacy bit=%x shortSlotTime %x"), caps,
+ cap_info->privacy,
+ cap_info->shortSlotTime);
+
+ /*
+ * If telescopic beaconing is enabled, set listen interval to
+ * WNI_CFG_TELE_BCN_MAX_LI
+ */
+ if (wlan_cfg_get_int(mac_ctx, WNI_CFG_TELE_BCN_WAKEUP_EN, &tele_bcn)
+ != eSIR_SUCCESS)
+ lim_log(mac_ctx, LOGP,
+ FL("Couldn't get WNI_CFG_TELE_BCN_WAKEUP_EN"));
+
+ val = WNI_CFG_LISTEN_INTERVAL_STADEF;
+ if (tele_bcn) {
+ if (wlan_cfg_get_int(mac_ctx, WNI_CFG_TELE_BCN_MAX_LI, &val) !=
+ eSIR_SUCCESS)
+ /*
+ * Could not get ListenInterval value
+ * from CFG. Log error.
+ */
+ lim_log(mac_ctx, LOGP,
+ FL("could not retrieve ListenInterval"));
+ } else {
+ if (wlan_cfg_get_int(mac_ctx, WNI_CFG_LISTEN_INTERVAL,
+ &val) != eSIR_SUCCESS)
+ /*
+ * Could not get ListenInterval value
+ * from CFG. Log error.
+ */
+ lim_log(mac_ctx, LOGP,
+ FL("could not retrieve ListenInterval"));
+ }
+#ifdef FEATURE_WLAN_DIAG_SUPPORT
+ lim_diag_event_report(mac_ctx, WLAN_PE_DIAG_ASSOC_REQ_EVENT,
+ session_entry, eSIR_SUCCESS, eSIR_SUCCESS);
+#endif
+ assoc_req->listenInterval = (uint16_t) val;
+ /* Update PE session ID */
+ assoc_req->sessionId = session_entry->peSessionId;
+ session_entry->limPrevSmeState = session_entry->limSmeState;
+ session_entry->limSmeState = eLIM_SME_WT_ASSOC_STATE;
+ MTRACE(mac_trace(mac_ctx, TRACE_CODE_SME_STATE,
+ session_entry->peSessionId, session_entry->limSmeState));
+ lim_post_mlm_message(mac_ctx, LIM_MLM_ASSOC_REQ,
+ (uint32_t *) assoc_req);
+}
+
+#ifdef WLAN_FEATURE_11W
+/**
+ * lim_pmf_comeback_timer_callback() -PMF callback handler
+ * @context: Timer context
+ *
+ * This function is called to processes the PMF comeback
+ * callback
+ *
+ * Return: None
+ */
+void lim_pmf_comeback_timer_callback(void *context)
+{
+ tComebackTimerInfo *info = (tComebackTimerInfo *) context;
+ tpAniSirGlobal mac_ctx = info->pMac;
+ tpPESession psessionEntry = &mac_ctx->lim.gpSession[info->sessionID];
+
+ lim_log(mac_ctx, LOGE,
+ FL("comeback later timer expired. sending MLM ASSOC req"));
+ /* set MLM state such that ASSOC REQ packet will be sent out */
+ psessionEntry->limPrevMlmState = info->limPrevMlmState;
+ psessionEntry->limMlmState = info->limMlmState;
+ lim_send_mlm_assoc_req(mac_ctx, psessionEntry);
+}
+#endif /* WLAN_FEATURE_11W */
+
+/**
+ * lim_process_mlm_auth_cnf()-Process Auth confirmation
+ * @mac_ctx: Pointer to Global MAC structure
+ * @msg: A pointer to the MLM message buffer
+ *
+ * This function is called to processes MLM_AUTH_CNF
+ * message from MLM State machine.
+ *
+ * Return: None
+ */
+void lim_process_mlm_auth_cnf(tpAniSirGlobal mac_ctx, uint32_t *msg)
+{
+ tAniAuthType auth_type, auth_mode;
+ tLimMlmAuthReq *auth_req;
+ tLimMlmAuthCnf *auth_cnf;
+ tpPESession session_entry;
+
+ if (msg == NULL) {
+ lim_log(mac_ctx, LOGE, FL("Buffer is Pointing to NULL"));
+ return;
+ }
+ auth_cnf = (tLimMlmAuthCnf *) msg;
+ session_entry = pe_find_session_by_session_id(mac_ctx,
+ auth_cnf->sessionId);
+ if (session_entry == NULL) {
+ lim_log(mac_ctx, LOGE, FL("SessionId:%d session doesn't exist"),
+ auth_cnf->sessionId);
+ return;
+ }
+
+ if ((session_entry->limSmeState != eLIM_SME_WT_AUTH_STATE &&
+ session_entry->limSmeState != eLIM_SME_WT_PRE_AUTH_STATE) ||
+ LIM_IS_AP_ROLE(session_entry) ||
+ LIM_IS_BT_AMP_AP_ROLE(session_entry)) {
+ /**
+ * Should not have received AUTH confirm
+ * from MLM in other states or on AP.
+ * Log error
+ */
+ lim_log(mac_ctx, LOGE,
+ FL("SessionId:%d received MLM_AUTH_CNF in state %X"),
+ session_entry->peSessionId, session_entry->limSmeState);
+ return;
+ }
+
+ if (((tLimMlmAuthCnf *) msg)->resultCode == eSIR_SME_SUCCESS) {
+ if (session_entry->limSmeState == eLIM_SME_WT_AUTH_STATE) {
+ lim_send_mlm_assoc_req(mac_ctx, session_entry);
+ } else {
+ /*
+ * Successful Pre-authentication. Send
+ * Pre-auth response to host
+ */
+ session_entry->limSmeState =
+ session_entry->limPrevSmeState;
+ MTRACE(mac_trace
+ (mac_ctx, TRACE_CODE_SME_STATE,
+ session_entry->peSessionId,
+ session_entry->limSmeState));
+ }
+ /* Return for success case */
+ return;
+ }
+ /*
+ * Failure case handle:
+ * Process AUTH confirm from MLM
+ */
+ if (session_entry->limSmeState == eLIM_SME_WT_AUTH_STATE) {
+ if (wlan_cfg_get_int(mac_ctx, WNI_CFG_AUTHENTICATION_TYPE,
+ (uint32_t *) &auth_type) != eSIR_SUCCESS) {
+ /*
+ * Could not get AuthType value from CFG.
+ * Log error.
+ */
+ lim_log(mac_ctx, LOGP,
+ FL("Fail to retrieve AuthType value"));
+ }
+ } else {
+ auth_type = mac_ctx->lim.gLimPreAuthType;
+ }
+
+ if ((auth_type == eSIR_AUTO_SWITCH) &&
+ (((tLimMlmAuthCnf *) msg)->authType == eSIR_OPEN_SYSTEM)
+ && (eSIR_MAC_AUTH_ALGO_NOT_SUPPORTED_STATUS ==
+ ((tLimMlmAuthCnf *) msg)->protStatusCode)) {
+ /*
+ * When Open authentication fails with reason
+ * code "13" and authType set to 'auto switch',
+ * Try with Shared Authentication
+ */
+ auth_mode = eSIR_SHARED_KEY;
+ /* Trigger MAC based Authentication */
+ auth_req = cdf_mem_malloc(sizeof(tLimMlmAuthReq));
+ if (NULL == auth_req) {
+ /* Log error */
+ lim_log(mac_ctx, LOGP,
+ FL("mlmAuthReq :Memory alloc failed "));
+ return;
+ }
+ cdf_mem_set((uint8_t *) auth_req,
+ sizeof(tLimMlmAuthReq), 0);
+ if (session_entry->limSmeState ==
+ eLIM_SME_WT_AUTH_STATE) {
+ sir_copy_mac_addr(auth_req->peerMacAddr,
+ session_entry->bssId);
+ } else {
+ cdf_mem_copy((uint8_t *)&auth_req->peerMacAddr,
+ (uint8_t *)&mac_ctx->lim.gLimPreAuthPeerAddr,
+ sizeof(tSirMacAddr));
+ }
+ auth_req->authType = auth_mode;
+ /* Update PE session Id */
+ auth_req->sessionId = auth_cnf->sessionId;
+ if (wlan_cfg_get_int(mac_ctx,
+ WNI_CFG_AUTHENTICATE_FAILURE_TIMEOUT,
+ (uint32_t *) &auth_req->authFailureTimeout)
+ != eSIR_SUCCESS) {
+ /*
+ * Could not get AuthFailureTimeout value from CFG.
+ * Log error.
+ */
+ lim_log(mac_ctx, LOGP,
+ FL("Fail:retrieve AuthFailureTimeout "));
+ }
+ lim_post_mlm_message(mac_ctx, LIM_MLM_AUTH_REQ,
+ (uint32_t *) auth_req);
+ return;
+ } else {
+ /* MAC based authentication failure */
+ if (session_entry->limSmeState ==
+ eLIM_SME_WT_AUTH_STATE) {
+ lim_log(mac_ctx, LOGE,
+ FL("Auth Failure occurred."));
+ session_entry->limSmeState =
+ eLIM_SME_JOIN_FAILURE_STATE;
+ MTRACE(mac_trace(mac_ctx, TRACE_CODE_SME_STATE,
+ session_entry->peSessionId,
+ session_entry->limSmeState));
+ session_entry->limMlmState =
+ eLIM_MLM_IDLE_STATE;
+ MTRACE(mac_trace(mac_ctx, TRACE_CODE_MLM_STATE,
+ session_entry->peSessionId,
+ session_entry->limMlmState));
+ /*
+ * Need to send Join response with
+ * auth failure to Host.
+ */
+ lim_handle_sme_join_result(mac_ctx,
+ ((tLimMlmAuthCnf *)msg)->resultCode,
+ ((tLimMlmAuthCnf *)msg)->protStatusCode,
+ session_entry);
+ } else {
+ /*
+ * Pre-authentication failure.
+ * Send Pre-auth failure response to host
+ */
+ session_entry->limSmeState =
+ session_entry->limPrevSmeState;
+ MTRACE(mac_trace(mac_ctx, TRACE_CODE_SME_STATE,
+ session_entry->peSessionId,
+ session_entry->limSmeState));
+ }
+ }
+}
+
+/**
+ * lim_process_mlm_assoc_cnf() - Process association confirmation
+ * @mac_ctx: Pointer to Global MAC structure
+ * @msg: A pointer to the MLM message buffer
+ *
+ * This function is called to processes MLM_ASSOC_CNF
+ * message from MLM State machine.
+ *
+ * Return: None
+ */
+void lim_process_mlm_assoc_cnf(tpAniSirGlobal mac_ctx,
+ uint32_t *msg)
+{
+ tpPESession session_entry;
+ tLimMlmAssocCnf *assoc_cnf;
+
+ if (msg == NULL) {
+ lim_log(mac_ctx, LOGE, FL("Buffer is Pointing to NULL"));
+ return;
+ }
+ assoc_cnf = (tLimMlmAssocCnf *) msg;
+ session_entry = pe_find_session_by_session_id(mac_ctx,
+ assoc_cnf->sessionId);
+ if (session_entry == NULL) {
+ lim_log(mac_ctx, LOGE,
+ FL("SessionId:%d Session does not exist"),
+ assoc_cnf->sessionId);
+ return;
+ }
+ if (session_entry->limSmeState != eLIM_SME_WT_ASSOC_STATE ||
+ LIM_IS_AP_ROLE(session_entry) ||
+ LIM_IS_BT_AMP_AP_ROLE(session_entry)) {
+ /*
+ * Should not have received Assocication confirm
+ * from MLM in other states OR on AP.
+ * Log error
+ */
+ lim_log(mac_ctx, LOGE,
+ FL("SessionId:%d Received MLM_ASSOC_CNF in state %X"),
+ session_entry->peSessionId, session_entry->limSmeState);
+ return;
+ }
+ if (((tLimMlmAssocCnf *) msg)->resultCode != eSIR_SME_SUCCESS) {
+ /* Association failure */
+ lim_log(mac_ctx, LOG1, FL("SessionId:%d Association failure"),
+ session_entry->peSessionId);
+ session_entry->limSmeState = eLIM_SME_JOIN_FAILURE_STATE;
+ MTRACE(mac_trace(mac_ctx, TRACE_CODE_SME_STATE,
+ session_entry->peSessionId, mac_ctx->lim.gLimSmeState));
+ /*
+ * Need to send Join response with
+ * Association failure to Host.
+ */
+ lim_handle_sme_join_result(mac_ctx,
+ ((tLimMlmAssocCnf *) msg)->resultCode,
+ ((tLimMlmAssocCnf *) msg)->protStatusCode,
+ session_entry);
+ } else {
+ /* Successful Association */
+ lim_log(mac_ctx, LOG1, FL("SessionId:%d Associated with BSS"),
+ session_entry->peSessionId);
+ session_entry->limSmeState = eLIM_SME_LINK_EST_STATE;
+ MTRACE(mac_trace(mac_ctx, TRACE_CODE_SME_STATE,
+ session_entry->peSessionId,
+ session_entry->limSmeState));
+ /**
+ * Need to send Join response with
+ * Association success to Host.
+ */
+ lim_handle_sme_join_result(mac_ctx,
+ ((tLimMlmAssocCnf *) msg)->resultCode,
+ ((tLimMlmAssocCnf *) msg)->protStatusCode,
+ session_entry);
+ }
+}
+
+/**
+ * lim_process_mlm_reassoc_cnf() - process mlm reassoc cnf msg
+ *
+ * @mac_ctx: Pointer to Global MAC structure
+ * @msg_buf: A pointer to the MLM message buffer
+ *
+ * This function is called to process MLM_REASSOC_CNF message from MLM State
+ * machine.
+ *
+ * @Return: void
+ */
+void lim_process_mlm_reassoc_cnf(tpAniSirGlobal mac_ctx, uint32_t *msg_buf)
+{
+ tpPESession session;
+ tLimMlmReassocCnf *lim_mlm_reassoc_cnf;
+
+ if (msg_buf == NULL) {
+ lim_log(mac_ctx, LOGE, FL("Buffer is Pointing to NULL"));
+ return;
+ }
+ lim_mlm_reassoc_cnf = (tLimMlmReassocCnf *) msg_buf;
+ session = pe_find_session_by_session_id(mac_ctx,
+ lim_mlm_reassoc_cnf->sessionId);
+ if (session == NULL) {
+ lim_log(mac_ctx, LOGE,
+ FL("session Does not exist for given session Id"));
+ return;
+ }
+ if ((session->limSmeState != eLIM_SME_WT_REASSOC_STATE) ||
+ LIM_IS_AP_ROLE(session) || LIM_IS_BT_AMP_AP_ROLE(session)) {
+ /*
+ * Should not have received Reassocication confirm
+ * from MLM in other states OR on AP.
+ */
+ lim_log(mac_ctx, LOGE,
+ FL("Rcv unexpected MLM_REASSOC_CNF in role %d, sme state 0x%X"),
+ GET_LIM_SYSTEM_ROLE(session), session->limSmeState);
+ return;
+ }
+ if (session->pLimReAssocReq) {
+ cdf_mem_free(session->pLimReAssocReq);
+ session->pLimReAssocReq = NULL;
+ }
+
+ /*
+ * Upon Reassoc success or failure, freeup the cached preauth request,
+ * to ensure that channel switch is now allowed following any change in
+ * HT params.
+ */
+ if (session->ftPEContext.pFTPreAuthReq) {
+ lim_log(mac_ctx, LOG1, FL("Freeing pFTPreAuthReq= %p"),
+ session->ftPEContext.pFTPreAuthReq);
+ if (session->ftPEContext.pFTPreAuthReq->pbssDescription) {
+ cdf_mem_free(
+ session->ftPEContext.pFTPreAuthReq->pbssDescription);
+ session->ftPEContext.pFTPreAuthReq->pbssDescription =
+ NULL;
+ }
+ cdf_mem_free(session->ftPEContext.pFTPreAuthReq);
+ session->ftPEContext.pFTPreAuthReq = NULL;
+ session->ftPEContext.ftPreAuthSession = false;
+ }
+
+#ifdef WLAN_FEATURE_ROAM_OFFLOAD
+ if (session->bRoamSynchInProgress) {
+ CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_DEBUG,
+ FL("LFR3:Re-set the LIM Ctxt Roam Synch In Progress"));
+ session->bRoamSynchInProgress = false;
+ }
+#endif
+
+ lim_log(mac_ctx, LOG1, FL("Rcv MLM_REASSOC_CNF with result code %d"),
+ lim_mlm_reassoc_cnf->resultCode);
+ if (lim_mlm_reassoc_cnf->resultCode == eSIR_SME_SUCCESS) {
+ /* Successful Reassociation */
+ CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_DEBUG,
+ FL("*** Reassociated with new BSS ***"));
+
+ session->limSmeState = eLIM_SME_LINK_EST_STATE;
+ MTRACE(mac_trace(mac_ctx, TRACE_CODE_SME_STATE,
+ session->peSessionId, session->limSmeState));
+
+ /* Need to send Reassoc rsp with Reassoc success to Host. */
+ lim_send_sme_join_reassoc_rsp(mac_ctx, eWNI_SME_REASSOC_RSP,
+ lim_mlm_reassoc_cnf->resultCode,
+ lim_mlm_reassoc_cnf->protStatusCode,
+ session, session->smeSessionId,
+ session->transactionId);
+ } else if (lim_mlm_reassoc_cnf->resultCode
+ == eSIR_SME_REASSOC_REFUSED) {
+ /*
+ * Reassociation failure With the New AP but we still have the
+ * link with the Older AP
+ */
+ session->limSmeState = eLIM_SME_LINK_EST_STATE;
+ MTRACE(mac_trace(mac_ctx, TRACE_CODE_SME_STATE,
+ session->peSessionId, session->limSmeState));
+
+ /* Need to send Reassoc rsp with Assoc failure to Host. */
+ lim_send_sme_join_reassoc_rsp(mac_ctx, eWNI_SME_REASSOC_RSP,
+ lim_mlm_reassoc_cnf->resultCode,
+ lim_mlm_reassoc_cnf->protStatusCode,
+ session, session->smeSessionId,
+ session->transactionId);
+ } else {
+ /* Reassociation failure */
+ session->limSmeState = eLIM_SME_JOIN_FAILURE_STATE;
+ MTRACE(mac_trace(mac_ctx, TRACE_CODE_SME_STATE,
+ session->peSessionId, session->limSmeState));
+ /* Need to send Reassoc rsp with Assoc failure to Host. */
+ lim_handle_sme_reaasoc_result(mac_ctx,
+ lim_mlm_reassoc_cnf->resultCode,
+ lim_mlm_reassoc_cnf->protStatusCode,
+ session);
+ }
+}
+
+/**
+ * lim_fill_assoc_ind_params() - Initialize association indication
+ * mac_ctx: Pointer to Global MAC structure
+ * assoc_ind: PE association indication structure
+ * sme_assoc_ind: SME association indication
+ * session_entry: PE session entry
+ *
+ * This function is called to initialzie the association
+ * indication strucutre to process association indication.
+ *
+ * Return: None
+ */
+
+void
+lim_fill_assoc_ind_params(tpAniSirGlobal mac_ctx,
+ tpLimMlmAssocInd assoc_ind, tSirSmeAssocInd *sme_assoc_ind,
+ tpPESession session_entry)
+{
+ sme_assoc_ind->length = sizeof(tSirSmeAssocInd);
+ sme_assoc_ind->sessionId = session_entry->smeSessionId;
+
+ /* Required for indicating the frames to upper layer */
+ sme_assoc_ind->assocReqLength = assoc_ind->assocReqLength;
+ sme_assoc_ind->assocReqPtr = assoc_ind->assocReqPtr;
+
+ sme_assoc_ind->beaconPtr = session_entry->beacon;
+ sme_assoc_ind->beaconLength = session_entry->bcnLen;
+
+ /* Fill in peerMacAddr */
+ cdf_mem_copy(sme_assoc_ind->peerMacAddr, assoc_ind->peerMacAddr,
+ sizeof(tSirMacAddr));
+
+ /* Fill in aid */
+ sme_assoc_ind->aid = assoc_ind->aid;
+ /* Fill in bssId */
+ cdf_mem_copy(sme_assoc_ind->bssId, session_entry->bssId,
+ sizeof(tSirMacAddr));
+ /* Fill in authType */
+ sme_assoc_ind->authType = assoc_ind->authType;
+ /* Fill in ssId */
+ cdf_mem_copy((uint8_t *) &sme_assoc_ind->ssId,
+ (uint8_t *) &(assoc_ind->ssId), assoc_ind->ssId.length + 1);
+ sme_assoc_ind->rsnIE.length = assoc_ind->rsnIE.length;
+ cdf_mem_copy((uint8_t *) &sme_assoc_ind->rsnIE.rsnIEdata,
+ (uint8_t *) &(assoc_ind->rsnIE.rsnIEdata),
+ assoc_ind->rsnIE.length);
+
+#ifdef FEATURE_WLAN_WAPI
+ sme_assoc_ind->wapiIE.length = assoc_ind->wapiIE.length;
+ cdf_mem_copy((uint8_t *) &sme_assoc_ind->wapiIE.wapiIEdata,
+ (uint8_t *) &(assoc_ind->wapiIE.wapiIEdata),
+ assoc_ind->wapiIE.length);
+#endif
+ sme_assoc_ind->addIE.length = assoc_ind->addIE.length;
+ cdf_mem_copy((uint8_t *) &sme_assoc_ind->addIE.addIEdata,
+ (uint8_t *) &(assoc_ind->addIE.addIEdata),
+ assoc_ind->addIE.length);
+
+ /* Copy the new TITAN capabilities */
+ sme_assoc_ind->spectrumMgtIndicator = assoc_ind->spectrumMgtIndicator;
+ if (assoc_ind->spectrumMgtIndicator == eSIR_TRUE) {
+ sme_assoc_ind->powerCap.minTxPower =
+ assoc_ind->powerCap.minTxPower;
+ sme_assoc_ind->powerCap.maxTxPower =
+ assoc_ind->powerCap.maxTxPower;
+ sme_assoc_ind->supportedChannels.numChnl =
+ assoc_ind->supportedChannels.numChnl;
+ cdf_mem_copy((uint8_t *) &sme_assoc_ind->supportedChannels.
+ channelList,
+ (uint8_t *) &(assoc_ind->supportedChannels.channelList),
+ assoc_ind->supportedChannels.numChnl);
+ }
+ cdf_mem_copy(&sme_assoc_ind->chan_info, &assoc_ind->chan_info,
+ sizeof(tSirSmeChanInfo));
+ /* Fill in WmmInfo */
+ sme_assoc_ind->wmmEnabledSta = assoc_ind->WmmStaInfoPresent;
+}
+
+/**
+ * lim_process_mlm_assoc_ind()
+ *
+ ***FUNCTION:
+ * This function is called to processes MLM_ASSOC_IND
+ * message from MLM State machine.
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ *
+ ***NOTE:
+ *
+ * @param pMac Pointer to Global MAC structure
+ * @param pMsgBuf A pointer to the MLM message buffer
+ *
+ * @return None
+ */
+void lim_process_mlm_assoc_ind(tpAniSirGlobal pMac, uint32_t *pMsgBuf)
+{
+ uint32_t len;
+ tSirMsgQ msgQ;
+ tSirSmeAssocInd *pSirSmeAssocInd;
+ tpDphHashNode pStaDs = 0;
+ tpPESession psessionEntry;
+ if (pMsgBuf == NULL) {
+ PELOGE(lim_log(pMac, LOGE, FL("Buffer is Pointing to NULL"));)
+ return;
+ }
+ psessionEntry = pe_find_session_by_session_id(pMac,
+ ((tpLimMlmAssocInd) pMsgBuf)->
+ sessionId);
+ if (psessionEntry == NULL) {
+ lim_log(pMac, LOGE,
+ FL("Session Does not exist for given sessionId"));
+ return;
+ }
+ /* / Inform Host of STA association */
+ len = sizeof(tSirSmeAssocInd);
+ pSirSmeAssocInd = cdf_mem_malloc(len);
+ if (NULL == pSirSmeAssocInd) {
+ /* Log error */
+ lim_log(pMac, LOGP,
+ FL
+ ("call to AllocateMemory failed for eWNI_SME_ASSOC_IND"));
+ return;
+ }
+
+ pSirSmeAssocInd->messageType = eWNI_SME_ASSOC_IND;
+ lim_fill_assoc_ind_params(pMac, (tpLimMlmAssocInd) pMsgBuf, pSirSmeAssocInd,
+ psessionEntry);
+ msgQ.type = eWNI_SME_ASSOC_IND;
+ msgQ.bodyptr = pSirSmeAssocInd;
+ msgQ.bodyval = 0;
+ pStaDs = dph_get_hash_entry(pMac,
+ ((tpLimMlmAssocInd) pMsgBuf)->aid,
+ &psessionEntry->dph.dphHashTable);
+ if (!pStaDs) { /* good time to panic... */
+ lim_log(pMac, LOGE,
+ FL
+ ("MLM AssocInd: Station context no longer valid (aid %d)"),
+ ((tpLimMlmAssocInd) pMsgBuf)->aid);
+ cdf_mem_free(pSirSmeAssocInd);
+
+ return;
+ }
+ pSirSmeAssocInd->staId = pStaDs->staIndex;
+ pSirSmeAssocInd->reassocReq = pStaDs->mlmStaContext.subType;
+ pSirSmeAssocInd->timingMeasCap = pStaDs->timingMeasCap;
+ MTRACE(mac_trace_msg_tx(pMac, psessionEntry->peSessionId, msgQ.type));
+#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */
+ lim_diag_event_report(pMac, WLAN_PE_DIAG_ASSOC_IND_EVENT, psessionEntry, 0,
+ 0);
+#endif /* FEATURE_WLAN_DIAG_SUPPORT */
+ lim_sys_process_mmh_msg_api(pMac, &msgQ, ePROT);
+
+ PELOG1(lim_log(pMac, LOG1,
+ FL
+ ("Create CNF_WAIT_TIMER after received LIM_MLM_ASSOC_IND"));
+ )
+ /*
+ ** turn on a timer to detect the loss of ASSOC CNF
+ **/
+ lim_activate_cnf_timer(pMac,
+ (uint16_t) ((tpLimMlmAssocInd) pMsgBuf)->aid,
+ psessionEntry);
+
+} /*** end lim_process_mlm_assoc_ind() ***/
+
+/**
+ * lim_process_mlm_disassoc_ind()
+ *
+ ***FUNCTION:
+ * This function is called to processes MLM_DISASSOC_IND
+ * message from MLM State machine.
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ *
+ ***NOTE:
+ *
+ * @param pMac Pointer to Global MAC structure
+ * @param pMsgBuf A pointer to the MLM message buffer
+ *
+ * @return None
+ */
+void lim_process_mlm_disassoc_ind(tpAniSirGlobal pMac, uint32_t *pMsgBuf)
+{
+ tLimMlmDisassocInd *pMlmDisassocInd;
+ tpPESession psessionEntry;
+ pMlmDisassocInd = (tLimMlmDisassocInd *) pMsgBuf;
+ psessionEntry = pe_find_session_by_session_id(pMac,
+ pMlmDisassocInd->sessionId);
+ if (psessionEntry == NULL) {
+ lim_log(pMac, LOGP,
+ FL("Session Does not exist for given sessionID"));
+ return;
+ }
+ switch (GET_LIM_SYSTEM_ROLE(psessionEntry)) {
+ case eLIM_STA_IN_IBSS_ROLE:
+ break;
+ case eLIM_STA_ROLE:
+ case eLIM_BT_AMP_STA_ROLE:
+ psessionEntry->limSmeState = eLIM_SME_WT_DISASSOC_STATE;
+ MTRACE(mac_trace
+ (pMac, TRACE_CODE_SME_STATE, psessionEntry->peSessionId,
+ psessionEntry->limSmeState));
+ break;
+ default: /* eLIM_AP_ROLE //eLIM_BT_AMP_AP_ROLE */
+ PELOG1(lim_log(pMac, LOG1,
+ FL("*** Peer staId=%d Disassociated ***"),
+ pMlmDisassocInd->aid);
+ )
+ /* Send SME_DISASOC_IND after Polaris cleanup */
+ /* (after receiving LIM_MLM_PURGE_STA_IND) */
+ break;
+ } /* end switch (GET_LIM_SYSTEM_ROLE(psessionEntry)) */
+} /*** end lim_process_mlm_disassoc_ind() ***/
+
+/**
+ * lim_process_mlm_disassoc_cnf() - Processes disassociation
+ * @mac_ctx: Pointer to Global MAC structure
+ * @msg: A pointer to the MLM message buffer
+ *
+ * This function is called to processes MLM_DISASSOC_CNF
+ * message from MLM State machine.
+ *
+ * Return: None
+ */
+void lim_process_mlm_disassoc_cnf(tpAniSirGlobal mac_ctx,
+ uint32_t *msg)
+{
+ tSirResultCodes result_code;
+ tLimMlmDisassocCnf *disassoc_cnf;
+ tpPESession session_entry;
+ disassoc_cnf = (tLimMlmDisassocCnf *) msg;
+
+ session_entry =
+ pe_find_session_by_session_id(mac_ctx, disassoc_cnf->sessionId);
+ if (session_entry == NULL) {
+ lim_log(mac_ctx, LOGE,
+ FL("session Does not exist for given session Id"));
+ return;
+ }
+ result_code = (tSirResultCodes)(disassoc_cnf->disassocTrigger ==
+ eLIM_LINK_MONITORING_DISASSOC) ?
+ eSIR_SME_LOST_LINK_WITH_PEER_RESULT_CODE :
+ disassoc_cnf->resultCode;
+ if (LIM_IS_STA_ROLE(session_entry) ||
+ LIM_IS_BT_AMP_STA_ROLE(session_entry)) {
+ /* Disassociate Confirm from MLM */
+ if ((session_entry->limSmeState != eLIM_SME_WT_DISASSOC_STATE)
+ && (session_entry->limSmeState !=
+ eLIM_SME_WT_DEAUTH_STATE)) {
+ /*
+ * Should not have received
+ * Disassocate confirm
+ * from MLM in other states.Log error
+ */
+ lim_log(mac_ctx, LOGE,
+ FL("received MLM_DISASSOC_CNF in state %X"),
+ session_entry->limSmeState);
+ return;
+ }
+ if (mac_ctx->lim.gLimRspReqd)
+ mac_ctx->lim.gLimRspReqd = false;
+ if (disassoc_cnf->disassocTrigger ==
+ eLIM_PROMISCUOUS_MODE_DISASSOC) {
+ if (disassoc_cnf->resultCode != eSIR_SME_SUCCESS)
+ session_entry->limSmeState =
+ session_entry->limPrevSmeState;
+ else
+ session_entry->limSmeState =
+ eLIM_SME_OFFLINE_STATE;
+ MTRACE(mac_trace
+ (mac_ctx, TRACE_CODE_SME_STATE,
+ session_entry->peSessionId,
+ session_entry->limSmeState));
+ } else {
+ if (disassoc_cnf->resultCode != eSIR_SME_SUCCESS)
+ session_entry->limSmeState =
+ session_entry->limPrevSmeState;
+ else
+ session_entry->limSmeState =
+ eLIM_SME_IDLE_STATE;
+ MTRACE(mac_trace(mac_ctx, TRACE_CODE_SME_STATE,
+ session_entry->peSessionId,
+ session_entry->limSmeState));
+ lim_send_sme_disassoc_ntf(mac_ctx,
+ disassoc_cnf->peerMacAddr, result_code,
+ disassoc_cnf->disassocTrigger,
+ disassoc_cnf->aid, session_entry->smeSessionId,
+ session_entry->transactionId, session_entry);
+ }
+ } else if (LIM_IS_AP_ROLE(session_entry) ||
+ LIM_IS_BT_AMP_AP_ROLE(session_entry)) {
+ lim_send_sme_disassoc_ntf(mac_ctx, disassoc_cnf->peerMacAddr,
+ result_code, disassoc_cnf->disassocTrigger,
+ disassoc_cnf->aid, session_entry->smeSessionId,
+ session_entry->transactionId, session_entry);
+ }
+}
+
+/**
+ * lim_process_mlm_deauth_ind()
+ *
+ ***FUNCTION:
+ * This function is called to processes MLM_DEAUTH_IND
+ * message from MLM State machine.
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ *
+ ***NOTE:
+ *
+ * @param pMac Pointer to Global MAC structure
+ * @param pMsgBuf A pointer to the MLM message buffer
+ *
+ * @return None
+ */
+void lim_process_mlm_deauth_ind(tpAniSirGlobal pMac, uint32_t *pMsgBuf)
+{
+ tLimMlmDeauthInd *pMlmDeauthInd;
+ tpPESession psessionEntry;
+ uint8_t sessionId;
+ pMlmDeauthInd = (tLimMlmDeauthInd *) pMsgBuf;
+ psessionEntry = pe_find_session_by_bssid(pMac,
+ pMlmDeauthInd->peerMacAddr, &sessionId);
+ if (psessionEntry == NULL) {
+ lim_log(pMac, LOGE,
+ FL("session does not exist for Addr:" MAC_ADDRESS_STR),
+ MAC_ADDR_ARRAY(pMlmDeauthInd->peerMacAddr));
+ return;
+ }
+ switch (GET_LIM_SYSTEM_ROLE(psessionEntry)) {
+ case eLIM_STA_IN_IBSS_ROLE:
+ break;
+ case eLIM_STA_ROLE:
+ case eLIM_BT_AMP_STA_ROLE:
+ psessionEntry->limSmeState = eLIM_SME_WT_DEAUTH_STATE;
+ MTRACE(mac_trace
+ (pMac, TRACE_CODE_SME_STATE, psessionEntry->peSessionId,
+ psessionEntry->limSmeState));
+
+ default: /* eLIM_AP_ROLE */
+ {
+ PELOG1(lim_log(pMac, LOG1,
+ FL
+ ("*** Received Deauthentication from staId=%d ***"),
+ pMlmDeauthInd->aid);
+ )
+ }
+ /* Send SME_DEAUTH_IND after Polaris cleanup */
+ /* (after receiving LIM_MLM_PURGE_STA_IND) */
+ break;
+ } /* end switch (GET_LIM_SYSTEM_ROLE(psessionEntry)) */
+} /*** end lim_process_mlm_deauth_ind() ***/
+
+/**
+ * lim_process_mlm_deauth_cnf()
+ *
+ ***FUNCTION:
+ * This function is called to processes MLM_DEAUTH_CNF
+ * message from MLM State machine.
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ *
+ ***NOTE:
+ *
+ * @param pMac Pointer to Global MAC structure
+ * @param pMsgBuf A pointer to the MLM message buffer
+ *
+ * @return None
+ */
+void lim_process_mlm_deauth_cnf(tpAniSirGlobal pMac, uint32_t *pMsgBuf)
+{
+ uint16_t aid;
+ tSirResultCodes resultCode;
+ tLimMlmDeauthCnf *pMlmDeauthCnf;
+ tpPESession psessionEntry;
+
+ if (pMsgBuf == NULL) {
+ PELOGE(lim_log(pMac, LOGE, FL("Buffer is Pointing to NULL"));)
+ return;
+ }
+ pMlmDeauthCnf = (tLimMlmDeauthCnf *) pMsgBuf;
+ psessionEntry = pe_find_session_by_session_id(pMac,
+ pMlmDeauthCnf->sessionId);
+ if (psessionEntry == NULL) {
+ PELOGE(lim_log
+ (pMac, LOGE,
+ FL("session does not exist for given session Id "));
+ )
+ return;
+ }
+
+ resultCode = (tSirResultCodes)
+ (pMlmDeauthCnf->deauthTrigger ==
+ eLIM_LINK_MONITORING_DEAUTH) ?
+ eSIR_SME_LOST_LINK_WITH_PEER_RESULT_CODE :
+ pMlmDeauthCnf->resultCode;
+ aid = LIM_IS_AP_ROLE(psessionEntry) ? pMlmDeauthCnf->aid : 1;
+ if (LIM_IS_STA_ROLE(psessionEntry) ||
+ LIM_IS_BT_AMP_STA_ROLE(psessionEntry)) {
+ /* Deauth Confirm from MLM */
+ if (psessionEntry->limSmeState != eLIM_SME_WT_DEAUTH_STATE) {
+ /**
+ * Should not have received Deauth confirm
+ * from MLM in other states.
+ * Log error
+ */
+ PELOGE(lim_log(pMac, LOGE,
+ FL
+ ("received unexpected MLM_DEAUTH_CNF in state %X"),
+ psessionEntry->limSmeState);)
+ return;
+ }
+ if (pMlmDeauthCnf->resultCode == eSIR_SME_SUCCESS) {
+ psessionEntry->limSmeState = eLIM_SME_IDLE_STATE;
+ PELOG1(lim_log(pMac, LOG1,
+ FL("*** Deauthenticated with BSS ***"));)
+ } else
+ psessionEntry->limSmeState =
+ psessionEntry->limPrevSmeState;
+ MTRACE(mac_trace
+ (pMac, TRACE_CODE_SME_STATE, psessionEntry->peSessionId,
+ psessionEntry->limSmeState));
+
+ if (pMac->lim.gLimRspReqd)
+ pMac->lim.gLimRspReqd = false;
+ }
+ /* On STA or on BASIC AP, send SME_DEAUTH_RSP to host */
+ lim_send_sme_deauth_ntf(pMac, pMlmDeauthCnf->peerMacAddr,
+ resultCode,
+ pMlmDeauthCnf->deauthTrigger,
+ aid, psessionEntry->smeSessionId,
+ psessionEntry->transactionId);
+} /*** end lim_process_mlm_deauth_cnf() ***/
+
+/**
+ * lim_process_mlm_purge_sta_ind()
+ *
+ ***FUNCTION:
+ * This function is called to processes MLM_PURGE_STA_IND
+ * message from MLM State machine.
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ *
+ ***NOTE:
+ *
+ * @param pMac Pointer to Global MAC structure
+ * @param pMsgBuf A pointer to the MLM message buffer
+ *
+ * @return None
+ */
+void lim_process_mlm_purge_sta_ind(tpAniSirGlobal pMac, uint32_t *pMsgBuf)
+{
+ tSirResultCodes resultCode;
+ tpLimMlmPurgeStaInd pMlmPurgeStaInd;
+ tpPESession psessionEntry;
+ if (pMsgBuf == NULL) {
+ PELOGE(lim_log(pMac, LOGE, FL("Buffer is Pointing to NULL"));)
+ return;
+ }
+ pMlmPurgeStaInd = (tpLimMlmPurgeStaInd) pMsgBuf;
+ psessionEntry = pe_find_session_by_session_id(pMac,
+ pMlmPurgeStaInd->sessionId);
+ if (psessionEntry == NULL) {
+ PELOGE(lim_log
+ (pMac, LOGE,
+ FL("session does not exist for given bssId"));
+ )
+ return;
+ }
+ /* Purge STA indication from MLM */
+ resultCode = (tSirResultCodes) pMlmPurgeStaInd->reasonCode;
+ switch (GET_LIM_SYSTEM_ROLE(psessionEntry)) {
+ case eLIM_STA_IN_IBSS_ROLE:
+ break;
+ case eLIM_STA_ROLE:
+ case eLIM_BT_AMP_STA_ROLE:
+ default: /* eLIM_AP_ROLE */
+ if (LIM_IS_STA_ROLE(psessionEntry) &&
+ (psessionEntry->limSmeState !=
+ eLIM_SME_WT_DISASSOC_STATE) &&
+ (psessionEntry->limSmeState != eLIM_SME_WT_DEAUTH_STATE)) {
+ /**
+ * Should not have received
+ * Purge STA indication
+ * from MLM in other states.
+ * Log error
+ */
+ PELOGE(lim_log(pMac, LOGE,
+ FL
+ ("received unexpected MLM_PURGE_STA_IND in state %X"),
+ psessionEntry->limSmeState);
+ )
+ break;
+ }
+ PELOG1(lim_log(pMac, LOG1,
+ FL("*** Cleanup completed for staId=%d ***"),
+ pMlmPurgeStaInd->aid);
+ )
+ if (LIM_IS_STA_ROLE(psessionEntry) ||
+ LIM_IS_BT_AMP_STA_ROLE(psessionEntry)) {
+ psessionEntry->limSmeState = eLIM_SME_IDLE_STATE;
+ MTRACE(mac_trace
+ (pMac, TRACE_CODE_SME_STATE,
+ psessionEntry->peSessionId,
+ psessionEntry->limSmeState));
+
+ }
+ if (pMlmPurgeStaInd->purgeTrigger == eLIM_PEER_ENTITY_DEAUTH) {
+ lim_send_sme_deauth_ntf(pMac,
+ pMlmPurgeStaInd->peerMacAddr,
+ resultCode,
+ pMlmPurgeStaInd->purgeTrigger,
+ pMlmPurgeStaInd->aid,
+ psessionEntry->smeSessionId,
+ psessionEntry->transactionId);
+ } else
+ lim_send_sme_disassoc_ntf(pMac,
+ pMlmPurgeStaInd->peerMacAddr,
+ resultCode,
+ pMlmPurgeStaInd->purgeTrigger,
+ pMlmPurgeStaInd->aid,
+ psessionEntry->smeSessionId,
+ psessionEntry->transactionId,
+ psessionEntry);
+ } /* end switch (GET_LIM_SYSTEM_ROLE(psessionEntry)) */
+} /*** end lim_process_mlm_purge_sta_ind() ***/
+
+/**
+ * lim_process_mlm_set_keys_cnf()
+ *
+ ***FUNCTION:
+ * This function is called to processes MLM_SETKEYS_CNF
+ * message from MLM State machine.
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ *
+ ***NOTE:
+ *
+ * @param pMac Pointer to Global MAC structure
+ * @param pMsgBuf A pointer to the MLM message buffer
+ *
+ * @return None
+ */
+void lim_process_mlm_set_keys_cnf(tpAniSirGlobal pMac, uint32_t *pMsgBuf)
+{
+ /* Prepare and send SME_SETCONTEXT_RSP message */
+ tLimMlmSetKeysCnf *pMlmSetKeysCnf;
+ tpPESession psessionEntry;
+ uint16_t aid;
+ tpDphHashNode sta_ds;
+
+ if (pMsgBuf == NULL) {
+ PELOGE(lim_log(pMac, LOGE, FL("Buffer is Pointing to NULL"));)
+ return;
+ }
+ pMlmSetKeysCnf = (tLimMlmSetKeysCnf *) pMsgBuf;
+ psessionEntry = pe_find_session_by_session_id(pMac,
+ pMlmSetKeysCnf->sessionId);
+ if (psessionEntry == NULL) {
+ PELOGE(lim_log
+ (pMac, LOGE,
+ FL("session does not exist for given sessionId "));
+ )
+ return;
+ }
+ psessionEntry->is_key_installed = 0;
+ lim_log(pMac, LOG1,
+ FL("Received MLM_SETKEYS_CNF with resultCode = %d"),
+ pMlmSetKeysCnf->resultCode);
+ /* if the status is success keys are installed in the
+ * Firmware so we can set the protection bit
+ */
+ if (eSIR_SME_SUCCESS == pMlmSetKeysCnf->resultCode) {
+ psessionEntry->is_key_installed = 1;
+ if (LIM_IS_AP_ROLE(psessionEntry) ||
+ LIM_IS_BT_AMP_AP_ROLE(psessionEntry)) {
+ sta_ds = dph_lookup_hash_entry(pMac,
+ pMlmSetKeysCnf->peerMacAddr,
+ &aid, &psessionEntry->dph.dphHashTable);
+ if (sta_ds != NULL)
+ sta_ds->is_key_installed = 1;
+ }
+ }
+ lim_send_sme_set_context_rsp(pMac,
+ pMlmSetKeysCnf->peerMacAddr,
+ 1,
+ (tSirResultCodes) pMlmSetKeysCnf->resultCode,
+ psessionEntry, psessionEntry->smeSessionId,
+ psessionEntry->transactionId);
+} /*** end lim_process_mlm_set_keys_cnf() ***/
+
+/**
+ * lim_handle_sme_join_result() - Handles sme join result
+ * @mac_ctx: Pointer to Global MAC structure
+ * @result_code: Failure code to be sent
+ * @prot_status_code : Protocol status code
+ * @session_entry: PE session handle
+ *
+ * This function is called to process join/auth/assoc failures
+ * upon receiving MLM_JOIN/AUTH/ASSOC_CNF with a failure code or
+ * MLM_ASSOC_CNF with a success code in case of STA role and
+ * MLM_JOIN_CNF with success in case of STA in IBSS role.
+ *
+ * Return: None
+ */
+static void
+lim_handle_sme_join_result(tpAniSirGlobal mac_ctx,
+ tSirResultCodes result_code, uint16_t prot_status_code,
+ tpPESession session_entry)
+{
+ tpDphHashNode sta_ds = NULL;
+ uint8_t sme_session_id;
+ uint16_t sme_trans_id;
+
+ if (session_entry == NULL) {
+ lim_log(mac_ctx, LOGE, FL("psessionEntry is NULL "));
+ return;
+ }
+ sme_session_id = session_entry->smeSessionId;
+ sme_trans_id = session_entry->transactionId;
+ /*
+ * When associations is failed , delete the session created
+ * and pass NULL to limsendsmeJoinReassocRsp()
+ */
+ if (result_code != eSIR_SME_SUCCESS) {
+ sta_ds =
+ dph_get_hash_entry(mac_ctx, DPH_STA_HASH_INDEX_PEER,
+ &session_entry->dph.dphHashTable);
+ if (sta_ds != NULL) {
+ sta_ds->mlmStaContext.disassocReason =
+ eSIR_MAC_UNSPEC_FAILURE_REASON;
+ sta_ds->mlmStaContext.cleanupTrigger =
+ eLIM_JOIN_FAILURE;
+ sta_ds->mlmStaContext.resultCode = result_code;
+ sta_ds->mlmStaContext.protStatusCode = prot_status_code;
+ /*
+ * FIX_ME: at the end of lim_cleanup_rx_path,
+ * make sure PE is sending eWNI_SME_JOIN_RSP
+ * to SME
+ */
+ lim_cleanup_rx_path(mac_ctx, sta_ds, session_entry);
+ cdf_mem_free(session_entry->pLimJoinReq);
+ session_entry->pLimJoinReq = NULL;
+ return;
+ }
+ }
+
+ cdf_mem_free(session_entry->pLimJoinReq);
+ session_entry->pLimJoinReq = NULL;
+ /* Delete teh session if JOIN failure occurred. */
+ if (result_code != eSIR_SME_SUCCESS) {
+ if (lim_set_link_state(mac_ctx, eSIR_LINK_DOWN_STATE,
+ session_entry->bssId,
+ session_entry->selfMacAddr, NULL, NULL)
+ != eSIR_SUCCESS)
+ lim_log(mac_ctx, LOGE,
+ FL("Failed to set the DownState."));
+ if (lim_set_link_state
+ (mac_ctx, eSIR_LINK_IDLE_STATE,
+ session_entry->bssId,
+ session_entry->selfMacAddr, NULL,
+ NULL) != eSIR_SUCCESS)
+ lim_log(mac_ctx, LOGE,
+ FL("Failed to set the LinkState."));
+ pe_delete_session(mac_ctx, session_entry);
+ session_entry = NULL;
+ }
+
+ lim_send_sme_join_reassoc_rsp(mac_ctx, eWNI_SME_JOIN_RSP, result_code,
+ prot_status_code, session_entry, sme_session_id, sme_trans_id);
+}
+
+/**
+ * lim_handle_sme_reaasoc_result()
+ *
+ ***FUNCTION:
+ * This function is called to process reassoc failures
+ * upon receiving REASSOC_CNF with a failure code or
+ * MLM_REASSOC_CNF with a success code in case of STA role
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ *
+ ***NOTE:
+ *
+ * @param pMac Pointer to Global MAC structure
+ * @param resultCode Failure code to be sent
+ *
+ *
+ * @return None
+ */
+static void
+lim_handle_sme_reaasoc_result(tpAniSirGlobal pMac, tSirResultCodes resultCode,
+ uint16_t protStatusCode, tpPESession psessionEntry)
+{
+ tpDphHashNode pStaDs = NULL;
+ uint8_t smesessionId;
+ uint16_t smetransactionId;
+
+ if (psessionEntry == NULL) {
+ PELOGE(lim_log(pMac, LOGE, FL("psessionEntry is NULL "));)
+ return;
+ }
+ smesessionId = psessionEntry->smeSessionId;
+ smetransactionId = psessionEntry->transactionId;
+ /* When associations is failed , delete the session created and pass NULL to limsendsmeJoinReassocRsp() */
+ if (resultCode != eSIR_SME_SUCCESS) {
+ pStaDs =
+ dph_get_hash_entry(pMac, DPH_STA_HASH_INDEX_PEER,
+ &psessionEntry->dph.dphHashTable);
+ if (pStaDs != NULL) {
+ pStaDs->mlmStaContext.disassocReason =
+ eSIR_MAC_UNSPEC_FAILURE_REASON;
+ pStaDs->mlmStaContext.cleanupTrigger =
+ eLIM_JOIN_FAILURE;
+ pStaDs->mlmStaContext.resultCode = resultCode;
+ pStaDs->mlmStaContext.protStatusCode = protStatusCode;
+ lim_cleanup_rx_path(pMac, pStaDs, psessionEntry);
+ return;
+ }
+ }
+ /* Delete teh session if REASSOC failure occurred. */
+ if (resultCode != eSIR_SME_SUCCESS) {
+ if (NULL != psessionEntry) {
+ pe_delete_session(pMac, psessionEntry);
+ psessionEntry = NULL;
+ }
+ }
+ lim_send_sme_join_reassoc_rsp(pMac, eWNI_SME_REASSOC_RSP, resultCode,
+ protStatusCode, psessionEntry, smesessionId,
+ smetransactionId);
+} /*** end limHandleSmeReassocResult() ***/
+
+/**
+ * lim_process_mlm_add_sta_rsp()
+ *
+ ***FUNCTION:
+ * This function is called to process a WMA_ADD_STA_RSP from HAL.
+ * Upon receipt of this message from HAL, MLME -
+ * > Determines the "state" in which this message was received
+ * > Forwards it to the appropriate callback
+ *
+ ***ASSUMPTIONS:
+ *
+ ***NOTE:
+ *
+ * @param pMac Pointer to Global MAC structure
+ * @param tSirMsgQ The MsgQ header, which contains the response buffer
+ *
+ * @return None
+ */
+void lim_process_mlm_add_sta_rsp(tpAniSirGlobal pMac, tpSirMsgQ limMsgQ,
+ tpPESession psessionEntry)
+{
+ /* we need to process the deferred message since the initiating req. there might be nested request. */
+ /* in the case of nested request the new request initiated from the response will take care of resetting */
+ /* the deffered flag. */
+ SET_LIM_PROCESS_DEFD_MESGS(pMac, true);
+ if (LIM_IS_BT_AMP_AP_ROLE(psessionEntry) ||
+ LIM_IS_AP_ROLE(psessionEntry)) {
+ lim_process_ap_mlm_add_sta_rsp(pMac, limMsgQ, psessionEntry);
+ return;
+ }
+ lim_process_sta_mlm_add_sta_rsp(pMac, limMsgQ, psessionEntry);
+}
+
+/**
+ * lim_process_sta_mlm_add_sta_rsp () - Process add sta response
+ * @mac_ctx: Pointer to mac context
+ * @msg: tpSirMsgQan Message structure
+ * @session_entry: PE session entry
+ *
+ * Process ADD STA response sent from WMA and posts results
+ * to SME.
+ *
+ * Return: Null
+ */
+
+void lim_process_sta_mlm_add_sta_rsp(tpAniSirGlobal mac_ctx,
+ tpSirMsgQ msg, tpPESession session_entry)
+{
+ tLimMlmAssocCnf mlm_assoc_cnf;
+ tpDphHashNode sta_ds;
+ uint32_t msg_type = LIM_MLM_ASSOC_CNF;
+ tpAddStaParams add_sta_params = (tpAddStaParams) msg->bodyptr;
+ tpPESession ft_session = NULL;
+ uint8_t ft_session_id;
+
+ if (NULL == add_sta_params) {
+ lim_log(mac_ctx, LOGE, FL("Encountered NULL Pointer"));
+ return;
+ }
+
+ if (session_entry->limSmeState == eLIM_SME_WT_REASSOC_STATE)
+ msg_type = LIM_MLM_REASSOC_CNF;
+
+ if (true == session_entry->fDeauthReceived) {
+ lim_log(mac_ctx, LOGE,
+ FL("Received Deauth frame in ADD_STA_RESP state"));
+ if (CDF_STATUS_SUCCESS == add_sta_params->status) {
+ lim_log(mac_ctx, LOGE,
+ FL("ADD_STA success, send update result code with eSIR_SME_JOIN_DEAUTH_FROM_AP_DURING_ADD_STA staIdx: %d limMlmState: %d"),
+ add_sta_params->staIdx,
+ session_entry->limMlmState);
+
+ if (session_entry->limSmeState ==
+ eLIM_SME_WT_REASSOC_STATE)
+ msg_type = LIM_MLM_REASSOC_CNF;
+ /*
+ * We are sending result code
+ * eSIR_SME_JOIN_DEAUTH_FROM_AP_DURING_ADD_STA which
+ * will trigger proper cleanup (DEL_STA/DEL_BSS both
+ * required) in either assoc cnf or reassoc cnf handler.
+ */
+ mlm_assoc_cnf.resultCode =
+ eSIR_SME_JOIN_DEAUTH_FROM_AP_DURING_ADD_STA;
+ session_entry->staId = add_sta_params->staIdx;
+ goto end;
+ }
+ }
+
+ if (CDF_STATUS_SUCCESS == add_sta_params->status) {
+ if (eLIM_MLM_WT_ADD_STA_RSP_STATE !=
+ session_entry->limMlmState) {
+ lim_log(mac_ctx, LOGE,
+ FL("Received WMA_ADD_STA_RSP in state %X"),
+ session_entry->limMlmState);
+ mlm_assoc_cnf.resultCode =
+ (tSirResultCodes) eSIR_SME_REFUSED;
+ goto end;
+ }
+ if (session_entry->limSmeState == eLIM_SME_WT_REASSOC_STATE) {
+#ifdef WLAN_FEATURE_VOWIFI_11R
+ /* check if we have keys(PTK)to install in case of 11r */
+ tpftPEContext ft_ctx = &session_entry->ftPEContext;
+ ft_session = pe_find_session_by_bssid(mac_ctx,
+ session_entry->limReAssocbssId, &ft_session_id);
+ if (ft_session != NULL &&
+ ft_ctx->PreAuthKeyInfo.extSetStaKeyParamValid
+ == true) {
+ tpLimMlmSetKeysReq pMlmStaKeys =
+ &ft_ctx->PreAuthKeyInfo.extSetStaKeyParam;
+ lim_send_set_sta_key_req(mac_ctx, pMlmStaKeys,
+ 0, 0, ft_session, false);
+ ft_ctx->PreAuthKeyInfo.extSetStaKeyParamValid =
+ false;
+ }
+#endif
+ }
+ /*
+ * Update the DPH Hash Entry for this STA
+ * with proper state info
+ */
+ sta_ds =
+ dph_get_hash_entry(mac_ctx, DPH_STA_HASH_INDEX_PEER,
+ &session_entry->dph.dphHashTable);
+ if (NULL != sta_ds)
+ sta_ds->mlmStaContext.mlmState =
+ eLIM_MLM_LINK_ESTABLISHED_STATE;
+ else
+ lim_log(mac_ctx, LOGW,
+ FL("Fail to get DPH Hash Entry for AID - %d"),
+ DPH_STA_HASH_INDEX_PEER);
+ session_entry->limMlmState = eLIM_MLM_LINK_ESTABLISHED_STATE;
+ MTRACE(mac_trace(mac_ctx, TRACE_CODE_MLM_STATE,
+ session_entry->peSessionId,
+ session_entry->limMlmState));
+ /*
+ * Storing the self StaIndex(Generated by HAL) in
+ * session context, instead of storing it in DPH Hash
+ * entry for Self STA.
+ * DPH entry for the self STA stores the sta index for
+ * the BSS entry to which the STA is associated
+ */
+ session_entry->staId = add_sta_params->staIdx;
+
+#ifdef WLAN_DEBUG
+ mac_ctx->lim.gLimNumLinkEsts++;
+#endif
+#ifdef FEATURE_WLAN_TDLS
+ /* initialize TDLS peer related data */
+ lim_init_tdls_data(mac_ctx, session_entry);
+#endif
+ /*
+ * Return Assoc confirm to SME with success
+ * FIXME - Need the correct ASSOC RSP code to
+ * be passed in here
+ */
+ mlm_assoc_cnf.resultCode = (tSirResultCodes) eSIR_SME_SUCCESS;
+ } else {
+ lim_log(mac_ctx, LOGE, FL("ADD_STA failed!"));
+ if (session_entry->limSmeState == eLIM_SME_WT_REASSOC_STATE)
+ mlm_assoc_cnf.resultCode =
+ (tSirResultCodes) eSIR_SME_FT_REASSOC_FAILURE;
+ else
+ mlm_assoc_cnf.resultCode =
+ (tSirResultCodes) eSIR_SME_REFUSED;
+ }
+end:
+ if (NULL != msg->bodyptr) {
+ cdf_mem_free(add_sta_params);
+ msg->bodyptr = NULL;
+ }
+ /* Updating PE session Id */
+ mlm_assoc_cnf.sessionId = session_entry->peSessionId;
+ lim_post_sme_message(mac_ctx, msg_type, (uint32_t *) &mlm_assoc_cnf);
+ if (true == session_entry->fDeauthReceived)
+ session_entry->fDeauthReceived = false;
+ return;
+}
+
+void lim_process_mlm_del_bss_rsp(tpAniSirGlobal pMac, tpSirMsgQ limMsgQ,
+ tpPESession psessionEntry)
+{
+ /* we need to process the deferred message since the initiating req. there might be nested request. */
+ /* in the case of nested request the new request initiated from the response will take care of resetting */
+ /* the deffered flag. */
+ SET_LIM_PROCESS_DEFD_MESGS(pMac, true);
+ pMac->sys.gSysFrameCount[SIR_MAC_MGMT_FRAME][SIR_MAC_MGMT_DEAUTH] = 0;
+
+ if ((LIM_IS_BT_AMP_AP_ROLE(psessionEntry) ||
+ LIM_IS_BT_AMP_STA_ROLE(psessionEntry) ||
+ LIM_IS_AP_ROLE(psessionEntry)) &&
+ (psessionEntry->statypeForBss == STA_ENTRY_SELF)) {
+ lim_process_bt_amp_ap_mlm_del_bss_rsp(pMac, limMsgQ, psessionEntry);
+ return;
+ }
+ lim_process_sta_mlm_del_bss_rsp(pMac, limMsgQ, psessionEntry);
+
+#ifdef WLAN_FEATURE_11W
+ if (psessionEntry->limRmfEnabled) {
+ if (eSIR_SUCCESS !=
+ lim_send_exclude_unencrypt_ind(pMac, true, psessionEntry)) {
+ lim_log(pMac, LOGE,
+ FL
+ ("Could not send down Exclude Unencrypted Indication!"));
+ }
+ }
+#endif
+}
+
+void lim_process_sta_mlm_del_bss_rsp(tpAniSirGlobal pMac, tpSirMsgQ limMsgQ,
+ tpPESession psessionEntry)
+{
+ tpDeleteBssParams pDelBssParams = (tpDeleteBssParams) limMsgQ->bodyptr;
+ tpDphHashNode pStaDs =
+ dph_get_hash_entry(pMac, DPH_STA_HASH_INDEX_PEER,
+ &psessionEntry->dph.dphHashTable);
+ tSirResultCodes statusCode = eSIR_SME_SUCCESS;
+
+ if (NULL == pDelBssParams) {
+ lim_log(pMac, LOGE, FL("Invalid body pointer in message"));
+ goto end;
+ }
+ if (CDF_STATUS_SUCCESS == pDelBssParams->status) {
+ PELOGW(lim_log(pMac, LOGW,
+ FL("STA received the DEL_BSS_RSP for BSSID: %X."),
+ pDelBssParams->bssIdx);
+ )
+ if (lim_set_link_state
+ (pMac, eSIR_LINK_IDLE_STATE, psessionEntry->bssId,
+ psessionEntry->selfMacAddr, NULL,
+ NULL) != eSIR_SUCCESS) {
+ PELOGE(lim_log
+ (pMac, LOGE,
+ FL("Failure in setting link state to IDLE"));
+ )
+ statusCode = eSIR_SME_REFUSED;
+ goto end;
+ }
+ if (pStaDs == NULL) {
+ lim_log(pMac, LOGE, FL("DPH Entry for STA 1 missing."));
+ statusCode = eSIR_SME_REFUSED;
+ goto end;
+ }
+ if (eLIM_MLM_WT_DEL_BSS_RSP_STATE !=
+ pStaDs->mlmStaContext.mlmState) {
+ PELOGE(lim_log
+ (pMac, LOGE,
+ FL
+ ("Received unexpected WMA_DEL_BSS_RSP in state %X"),
+ pStaDs->mlmStaContext.mlmState);
+ )
+ statusCode = eSIR_SME_REFUSED;
+ goto end;
+ }
+ PELOG1(lim_log
+ (pMac, LOG1, FL("STA AssocID %d MAC "), pStaDs->assocId);
+ lim_print_mac_addr(pMac, pStaDs->staAddr, LOG1);
+ )
+ } else {
+ lim_log(pMac, LOGE, FL("DEL BSS failed!"));
+ statusCode = eSIR_SME_STOP_BSS_FAILURE;
+ }
+end:
+ if (0 != limMsgQ->bodyptr) {
+ cdf_mem_free(pDelBssParams);
+ limMsgQ->bodyptr = NULL;
+ }
+ if (pStaDs == NULL)
+ return;
+ if ((LIM_IS_STA_ROLE(psessionEntry) ||
+ LIM_IS_BT_AMP_STA_ROLE(psessionEntry)) &&
+ (psessionEntry->limSmeState !=
+ eLIM_SME_WT_DISASSOC_STATE &&
+ psessionEntry->limSmeState !=
+ eLIM_SME_WT_DEAUTH_STATE) &&
+ pStaDs->mlmStaContext.cleanupTrigger !=
+ eLIM_JOIN_FAILURE) {
+ /** The Case where the DelBss is invoked from
+ * context of other than normal DisAssoc / Deauth OR
+ * as part of Join Failure.
+ */
+ lim_handle_del_bss_in_re_assoc_context(pMac, pStaDs, psessionEntry);
+ return;
+ }
+ lim_prepare_and_send_del_sta_cnf(pMac, pStaDs, statusCode, psessionEntry);
+ return;
+}
+
+void lim_process_bt_amp_ap_mlm_del_bss_rsp(tpAniSirGlobal pMac, tpSirMsgQ limMsgQ,
+ tpPESession psessionEntry)
+{
+ tSirResultCodes rc = eSIR_SME_SUCCESS;
+ tSirRetStatus status;
+ tpDeleteBssParams pDelBss = (tpDeleteBssParams) limMsgQ->bodyptr;
+ tSirMacAddr nullBssid = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+ if (psessionEntry == NULL) {
+ lim_log(pMac, LOGE, FL("Session entry passed is NULL"));
+ if (pDelBss != NULL) {
+ cdf_mem_free(pDelBss);
+ limMsgQ->bodyptr = NULL;
+ }
+ return;
+ }
+
+ if (pDelBss == NULL) {
+ PELOGE(lim_log(pMac, LOGE, FL("BSS: DEL_BSS_RSP with no body!"));)
+ rc = eSIR_SME_REFUSED;
+ goto end;
+ }
+ pMac->lim.gLimMlmState = eLIM_MLM_IDLE_STATE;
+ MTRACE(mac_trace
+ (pMac, TRACE_CODE_MLM_STATE, NO_SESSION,
+ pMac->lim.gLimMlmState));
+
+ if (eLIM_MLM_WT_DEL_BSS_RSP_STATE != psessionEntry->limMlmState) {
+ lim_log(pMac, LOGE,
+ FL("Received unexpected WMA_DEL_BSS_RSP in state %X"),
+ psessionEntry->limMlmState);
+ rc = eSIR_SME_REFUSED;
+ goto end;
+ }
+ if (pDelBss->status != CDF_STATUS_SUCCESS) {
+ lim_log(pMac, LOGE, FL("BSS: DEL_BSS_RSP error (%x) Bss %d "),
+ pDelBss->status, pDelBss->bssIdx);
+ rc = eSIR_SME_STOP_BSS_FAILURE;
+ goto end;
+ }
+ status = lim_set_link_state(pMac, eSIR_LINK_IDLE_STATE, nullBssid,
+ psessionEntry->selfMacAddr, NULL, NULL);
+ if (status != eSIR_SUCCESS) {
+ rc = eSIR_SME_REFUSED;
+ goto end;
+ }
+ /** Softmac may send all the buffered packets right after resuming the transmission hence
+ * to occupy the medium during non channel occupancy period. So resume the transmission after
+ * HAL gives back the response.
+ */
+ dph_hash_table_class_init(pMac, &psessionEntry->dph.dphHashTable);
+ lim_delete_pre_auth_list(pMac);
+ /* Initialize number of associated stations during cleanup */
+ psessionEntry->gLimNumOfCurrentSTAs = 0;
+end:
+ lim_send_sme_rsp(pMac, eWNI_SME_STOP_BSS_RSP, rc,
+ psessionEntry->smeSessionId,
+ psessionEntry->transactionId);
+ pe_delete_session(pMac, psessionEntry);
+
+ if (pDelBss != NULL) {
+ cdf_mem_free(pDelBss);
+ limMsgQ->bodyptr = NULL;
+ }
+}
+
+/**
+ * lim_process_mlm_del_sta_rsp() - Process DEL STA response
+ * @mac_ctx: Pointer to Global MAC structure
+ * @msg: The MsgQ header, which contains the response buffer
+ *
+ * This function is called to process a WMA_DEL_STA_RSP from
+ * WMA Upon receipt of this message from FW.
+ *
+ * Return: None
+ */
+void lim_process_mlm_del_sta_rsp(tpAniSirGlobal mac_ctx,
+ tpSirMsgQ msg)
+{
+ /*
+ * we need to process the deferred message since the
+ * initiating req. there might be nested request
+ * in the case of nested request the new request
+ * initiated from the response will take care of resetting
+ * the deffered flag.
+ */
+ tpPESession session_entry;
+ tpDeleteStaParams del_sta_params;
+ del_sta_params = (tpDeleteStaParams) msg->bodyptr;
+ if (NULL == del_sta_params) {
+ lim_log(mac_ctx, LOGE,
+ FL("null pointer del_sta_params msg"));
+ return;
+ }
+ SET_LIM_PROCESS_DEFD_MESGS(mac_ctx, true);
+
+ session_entry = pe_find_session_by_session_id(mac_ctx,
+ del_sta_params->sessionId);
+ if (NULL == session_entry) {
+ lim_log(mac_ctx, LOGP,
+ FL("Session Doesn't exist"));
+ cdf_mem_free(del_sta_params);
+ msg->bodyptr = NULL;
+ return;
+ }
+
+ if (LIM_IS_BT_AMP_AP_ROLE(session_entry) ||
+ LIM_IS_AP_ROLE(session_entry)) {
+ lim_process_bt_amp_ap_mlm_del_sta_rsp(mac_ctx, msg,
+ session_entry);
+ return;
+ }
+ lim_process_sta_mlm_del_sta_rsp(mac_ctx, msg, session_entry);
+}
+
+void lim_process_bt_amp_ap_mlm_del_sta_rsp(tpAniSirGlobal pMac, tpSirMsgQ limMsgQ,
+ tpPESession psessionEntry)
+{
+ tpDeleteStaParams pDelStaParams = (tpDeleteStaParams) limMsgQ->bodyptr;
+ tpDphHashNode pStaDs;
+ tSirResultCodes statusCode = eSIR_SME_SUCCESS;
+ if (limMsgQ->bodyptr == NULL) {
+ lim_log(pMac, LOGE, FL("limMsgQ->bodyptry NULL"));
+ return;
+ }
+
+ pStaDs =
+ dph_get_hash_entry(pMac, pDelStaParams->assocId,
+ &psessionEntry->dph.dphHashTable);
+ if (pStaDs == NULL) {
+ lim_log(pMac, LOGE,
+ FL("DPH Entry for STA %X missing."),
+ pDelStaParams->assocId);
+ statusCode = eSIR_SME_REFUSED;
+ cdf_mem_free(pDelStaParams);
+ limMsgQ->bodyptr = NULL;
+
+ return;
+ }
+ lim_log(pMac, LOG1, FL("Received del Sta Rsp in StaD MlmState : %d"),
+ pStaDs->mlmStaContext.mlmState);
+ if (CDF_STATUS_SUCCESS == pDelStaParams->status) {
+ lim_log(pMac, LOGW,
+ FL("AP received the DEL_STA_RSP for assocID: %X."),
+ pDelStaParams->assocId);
+
+ if ((eLIM_MLM_WT_DEL_STA_RSP_STATE !=
+ pStaDs->mlmStaContext.mlmState)
+ && (eLIM_MLM_WT_ASSOC_DEL_STA_RSP_STATE !=
+ pStaDs->mlmStaContext.mlmState)) {
+ lim_log(pMac, LOGE,
+ FL
+ ("Received unexpected WMA_DEL_STA_RSP in state %s for staId %d assocId %d "),
+ lim_mlm_state_str(pStaDs->mlmStaContext.mlmState),
+ pStaDs->staIndex, pStaDs->assocId);
+ statusCode = eSIR_SME_REFUSED;
+ goto end;
+ }
+
+ lim_log(pMac, LOG1,
+ FL("Deleted STA AssocID %d staId %d MAC "),
+ pStaDs->assocId, pStaDs->staIndex);
+ lim_print_mac_addr(pMac, pStaDs->staAddr, LOG1);
+ if (eLIM_MLM_WT_ASSOC_DEL_STA_RSP_STATE ==
+ pStaDs->mlmStaContext.mlmState) {
+ cdf_mem_free(pDelStaParams);
+ limMsgQ->bodyptr = NULL;
+ if (lim_add_sta(pMac, pStaDs, false, psessionEntry) !=
+ eSIR_SUCCESS) {
+ PELOGE(lim_log
+ (pMac, LOGE,
+ FL("could not Add STA with assocId=%d"),
+ pStaDs->assocId);
+ )
+ /* delete the TS if it has already been added. */
+ /* send the response with error status. */
+ if (pStaDs->qos.addtsPresent) {
+ tpLimTspecInfo pTspecInfo;
+ if (eSIR_SUCCESS ==
+ lim_tspec_find_by_assoc_id(pMac,
+ pStaDs->assocId,
+ &pStaDs->qos.addts.tspec,
+ &pMac->lim.tspecInfo[0],
+ &pTspecInfo)) {
+ lim_admit_control_delete_ts(pMac,
+ pStaDs->
+ assocId,
+ &pStaDs->
+ qos.
+ addts.
+ tspec.
+ tsinfo,
+ NULL,
+ &pTspecInfo->
+ idx);
+ }
+ }
+ lim_reject_association(pMac,
+ pStaDs->staAddr,
+ pStaDs->mlmStaContext.
+ subType, true,
+ pStaDs->mlmStaContext.
+ authType, pStaDs->assocId,
+ true,
+ (tSirResultCodes)
+ eSIR_MAC_UNSPEC_FAILURE_STATUS,
+ psessionEntry);
+ }
+ return;
+ }
+ } else {
+ lim_log(pMac, LOGW, FL("DEL STA failed!"));
+ statusCode = eSIR_SME_REFUSED;
+ }
+end:
+ cdf_mem_free(pDelStaParams);
+ limMsgQ->bodyptr = NULL;
+ if (eLIM_MLM_WT_ASSOC_DEL_STA_RSP_STATE !=
+ pStaDs->mlmStaContext.mlmState) {
+ lim_prepare_and_send_del_sta_cnf(pMac, pStaDs, statusCode,
+ psessionEntry);
+ }
+ return;
+}
+
+void lim_process_sta_mlm_del_sta_rsp(tpAniSirGlobal pMac, tpSirMsgQ limMsgQ,
+ tpPESession psessionEntry)
+{
+ tSirResultCodes statusCode = eSIR_SME_SUCCESS;
+ tpDeleteStaParams pDelStaParams = (tpDeleteStaParams) limMsgQ->bodyptr;
+ tpDphHashNode pStaDs = NULL;
+ if (NULL == pDelStaParams) {
+ lim_log(pMac, LOGE, FL("Encountered NULL Pointer"));
+ goto end;
+ }
+ if (CDF_STATUS_SUCCESS == pDelStaParams->status) {
+ pStaDs =
+ dph_get_hash_entry(pMac, DPH_STA_HASH_INDEX_PEER,
+ &psessionEntry->dph.dphHashTable);
+ if (pStaDs == NULL) {
+ /* TODO: any response to be sent out here ? */
+ lim_log(pMac, LOGE, FL("DPH Entry for STA %X missing."),
+ pDelStaParams->assocId);
+ statusCode = eSIR_SME_REFUSED;
+ goto end;
+ }
+ if (eLIM_MLM_WT_DEL_STA_RSP_STATE != psessionEntry->limMlmState) {
+ /* TODO: any response to be sent out here ? */
+ lim_log(pMac, LOGE,
+ FL
+ ("Received unexpected WMA_DELETE_STA_RSP in state %s"),
+ lim_mlm_state_str(psessionEntry->limMlmState));
+ statusCode = eSIR_SME_REFUSED;
+ goto end;
+ }
+ PELOG1(lim_log
+ (pMac, LOG1, FL("STA AssocID %d MAC "), pStaDs->assocId);
+ lim_print_mac_addr(pMac, pStaDs->staAddr, LOG1);
+ )
+ lim_log(pMac, LOGW,
+ FL("DEL_STA_RSP received for assocID: %X"),
+ pDelStaParams->assocId);
+ /* we must complete all cleanup related to delSta before calling limDelBSS. */
+ if (0 != limMsgQ->bodyptr) {
+ cdf_mem_free(pDelStaParams);
+ limMsgQ->bodyptr = NULL;
+ }
+ statusCode =
+ (tSirResultCodes) lim_del_bss(pMac, pStaDs, 0, psessionEntry);
+ return;
+ } else {
+ lim_log(pMac, LOGE, FL("DEL_STA failed for sta Id %d"),
+ pDelStaParams->staIdx);
+ statusCode = eSIR_SME_REFUSED;
+ }
+end:
+ if (0 != limMsgQ->bodyptr) {
+ cdf_mem_free(pDelStaParams);
+ limMsgQ->bodyptr = NULL;
+ }
+ return;
+}
+
+void lim_process_ap_mlm_add_sta_rsp(tpAniSirGlobal pMac, tpSirMsgQ limMsgQ,
+ tpPESession psessionEntry)
+{
+ tpAddStaParams pAddStaParams = (tpAddStaParams) limMsgQ->bodyptr;
+ tpDphHashNode pStaDs = NULL;
+
+ if (NULL == pAddStaParams) {
+ lim_log(pMac, LOGE, FL("Invalid body pointer in message"));
+ goto end;
+ }
+
+ pStaDs =
+ dph_get_hash_entry(pMac, pAddStaParams->assocId,
+ &psessionEntry->dph.dphHashTable);
+ if (pStaDs == NULL) {
+ /* TODO: any response to be sent out here ? */
+ lim_log(pMac, LOGE, FL("DPH Entry for STA %X missing."),
+ pAddStaParams->assocId);
+ goto end;
+ }
+ /* */
+ /* TODO & FIXME_GEN4 */
+ /* Need to inspect tSirMsgQ.reserved for a valid Dialog token! */
+ /* */
+ /* TODO: any check for pMac->lim.gLimMlmState ? */
+ if (eLIM_MLM_WT_ADD_STA_RSP_STATE != pStaDs->mlmStaContext.mlmState) {
+ /* TODO: any response to be sent out here ? */
+ lim_log(pMac, LOGE,
+ FL("Received unexpected WMA_ADD_STA_RSP in state %X"),
+ pStaDs->mlmStaContext.mlmState);
+ goto end;
+ }
+ if (CDF_STATUS_SUCCESS != pAddStaParams->status) {
+ PELOGE(lim_log
+ (pMac, LOGE,
+ FL("Error! rcvd delSta rsp from HAL with status %d"),
+ pAddStaParams->status);
+ )
+ lim_reject_association(pMac, pStaDs->staAddr,
+ pStaDs->mlmStaContext.subType,
+ true, pStaDs->mlmStaContext.authType,
+ pStaDs->assocId, true,
+ (tSirResultCodes)
+ eSIR_MAC_UNSPEC_FAILURE_STATUS,
+ psessionEntry);
+ goto end;
+ }
+ pStaDs->bssId = pAddStaParams->bssIdx;
+ pStaDs->staIndex = pAddStaParams->staIdx;
+ /* if the AssocRsp frame is not acknowledged, then keep alive timer will take care of the state */
+ pStaDs->valid = 1;
+ pStaDs->mlmStaContext.mlmState = eLIM_MLM_WT_ASSOC_CNF_STATE;
+ lim_log(pMac, LOG1,
+ FL("AddStaRsp Success.STA AssocID %d staId %d MAC "),
+ pStaDs->assocId, pStaDs->staIndex);
+ lim_print_mac_addr(pMac, pStaDs->staAddr, LOG1);
+
+ /* For BTAMP-AP, the flow sequence shall be:
+ * 1) PE sends eWNI_SME_ASSOC_IND to SME
+ * 2) PE receives eWNI_SME_ASSOC_CNF from SME
+ * 3) BTAMP-AP sends Re/Association Response to BTAMP-STA
+ */
+ lim_send_mlm_assoc_ind(pMac, pStaDs, psessionEntry);
+ /* fall though to reclaim the original Add STA Response message */
+end:
+ if (0 != limMsgQ->bodyptr) {
+ cdf_mem_free(pAddStaParams);
+ limMsgQ->bodyptr = NULL;
+ }
+ return;
+}
+
+/**
+ * lim_process_ap_mlm_add_bss_rsp()
+ *
+ ***FUNCTION:
+ * This function is called to process a WMA_ADD_BSS_RSP from HAL.
+ * Upon receipt of this message from HAL, MLME -
+ * > Validates the result of WMA_ADD_BSS_REQ
+ * > Init other remaining LIM variables
+ * > Init the AID pool, for that BSSID
+ * > Init the Pre-AUTH list, for that BSSID
+ * > Create LIM timers, specific to that BSSID
+ * > Init DPH related parameters that are specific to that BSSID
+ * > TODO - When do we do the actual change channel?
+ *
+ ***LOGIC:
+ * SME sends eWNI_SME_START_BSS_REQ to LIM
+ * LIM sends LIM_MLM_START_REQ to MLME
+ * MLME sends WMA_ADD_BSS_REQ to HAL
+ * HAL responds with WMA_ADD_BSS_RSP to MLME
+ * MLME responds with LIM_MLM_START_CNF to LIM
+ * LIM responds with eWNI_SME_START_BSS_RSP to SME
+ *
+ ***ASSUMPTIONS:
+ * tSirMsgQ.body is allocated by MLME during lim_process_mlm_start_req
+ * tSirMsgQ.body will now be freed by this routine
+ *
+ ***NOTE:
+ *
+ * @param pMac Pointer to Global MAC structure
+ * @param tSirMsgQ The MsgQ header, which contains the response buffer
+ *
+ * @return None
+ */
+static void lim_process_ap_mlm_add_bss_rsp(tpAniSirGlobal pMac, tpSirMsgQ limMsgQ)
+{
+ tLimMlmStartCnf mlmStartCnf;
+ tpPESession psessionEntry;
+ uint8_t isWepEnabled = false;
+ tpAddBssParams pAddBssParams = (tpAddBssParams) limMsgQ->bodyptr;
+ if (NULL == pAddBssParams) {
+ lim_log(pMac, LOGE, FL("Encountered NULL Pointer"));
+ goto end;
+ }
+ /* TBD: free the memory before returning, do it for all places where lookup fails. */
+ psessionEntry = pe_find_session_by_session_id(pMac,
+ pAddBssParams->sessionId);
+ if (psessionEntry == NULL) {
+ PELOGE(lim_log
+ (pMac, LOGE,
+ FL("session does not exist for given sessionId"));
+ )
+ if (NULL != pAddBssParams) {
+ cdf_mem_free(pAddBssParams);
+ limMsgQ->bodyptr = NULL;
+ }
+ return;
+ }
+ /* Update PE session Id */
+ mlmStartCnf.sessionId = pAddBssParams->sessionId;
+ if (CDF_STATUS_SUCCESS == pAddBssParams->status) {
+ PELOG2(lim_log
+ (pMac, LOG2,
+ FL("WMA_ADD_BSS_RSP returned with CDF_STATUS_SUCCESS"));
+ )
+ if (lim_set_link_state
+ (pMac, eSIR_LINK_AP_STATE, psessionEntry->bssId,
+ psessionEntry->selfMacAddr, NULL,
+ NULL) != eSIR_SUCCESS)
+ goto end;
+ /* Set MLME state */
+ psessionEntry->limMlmState = eLIM_MLM_BSS_STARTED_STATE;
+ psessionEntry->chainMask = pAddBssParams->chainMask;
+ psessionEntry->smpsMode = pAddBssParams->smpsMode;
+ MTRACE(mac_trace
+ (pMac, TRACE_CODE_MLM_STATE, psessionEntry->peSessionId,
+ psessionEntry->limMlmState));
+ if (eSIR_IBSS_MODE == pAddBssParams->bssType) {
+ /** IBSS is 'active' when we receive
+ * Beacon frames from other STAs that are part of same IBSS.
+ * Mark internal state as inactive until then.
+ */
+ psessionEntry->limIbssActive = false;
+ psessionEntry->statypeForBss = STA_ENTRY_PEER; /* to know session created for self/peer */
+ limResetHBPktCount(psessionEntry);
+ }
+ psessionEntry->bssIdx = (uint8_t) pAddBssParams->bssIdx;
+
+ psessionEntry->limSystemRole = eLIM_STA_IN_IBSS_ROLE;
+
+ if (eSIR_INFRA_AP_MODE == pAddBssParams->bssType)
+ psessionEntry->limSystemRole = eLIM_AP_ROLE;
+ else
+ psessionEntry->limSystemRole = eLIM_STA_IN_IBSS_ROLE;
+ sch_edca_profile_update(pMac, psessionEntry);
+ lim_init_pre_auth_list(pMac);
+ /* Check the SAP security configuration.If configured to
+ * WEP then max clients supported is 16
+ */
+ if (psessionEntry->privacy) {
+ if ((psessionEntry->gStartBssRSNIe.present)
+ || (psessionEntry->gStartBssWPAIe.present))
+ lim_log(pMac, LOG1,
+ FL("WPA/WPA2 SAP configuration\n"));
+ else {
+ if (pMac->lim.gLimAssocStaLimit >
+ MAX_SUPPORTED_PEERS_WEP) {
+ lim_log(pMac, LOG1,
+ FL("WEP SAP Configuration\n"));
+ pMac->lim.gLimAssocStaLimit =
+ MAX_SUPPORTED_PEERS_WEP;
+ isWepEnabled = true;
+ }
+ }
+ }
+ lim_init_peer_idxpool(pMac, psessionEntry);
+
+ /* Start OLBC timer */
+ if (tx_timer_activate
+ (&pMac->lim.limTimers.gLimUpdateOlbcCacheTimer) !=
+ TX_SUCCESS) {
+ lim_log(pMac, LOGE, FL("tx_timer_activate failed"));
+ }
+
+ /* Apply previously set configuration at HW */
+ lim_apply_configuration(pMac, psessionEntry);
+
+ /* In lim_apply_configuration gLimAssocStaLimit is assigned from cfg.
+ * So update the value to 16 in case SoftAP is configured in WEP.
+ */
+ if ((pMac->lim.gLimAssocStaLimit > MAX_SUPPORTED_PEERS_WEP)
+ && (isWepEnabled))
+ pMac->lim.gLimAssocStaLimit = MAX_SUPPORTED_PEERS_WEP;
+ psessionEntry->staId = pAddBssParams->staContext.staIdx;
+ mlmStartCnf.resultCode = eSIR_SME_SUCCESS;
+ } else {
+ lim_log(pMac, LOGE, FL("WMA_ADD_BSS_REQ failed with status %d"),
+ pAddBssParams->status);
+ mlmStartCnf.resultCode = eSIR_SME_HAL_SEND_MESSAGE_FAIL;
+ }
+ lim_post_sme_message(pMac, LIM_MLM_START_CNF, (uint32_t *) &mlmStartCnf);
+end:
+ if (0 != limMsgQ->bodyptr) {
+ cdf_mem_free(pAddBssParams);
+ limMsgQ->bodyptr = NULL;
+ }
+}
+
+/**
+ * lim_process_ibss_mlm_add_bss_rsp()
+ *
+ ***FUNCTION:
+ * This function is called to process a WMA_ADD_BSS_RSP from HAL.
+ * Upon receipt of this message from HAL, MLME -
+ * > Validates the result of WMA_ADD_BSS_REQ
+ * > Init other remaining LIM variables
+ * > Init the AID pool, for that BSSID
+ * > Init the Pre-AUTH list, for that BSSID
+ * > Create LIM timers, specific to that BSSID
+ * > Init DPH related parameters that are specific to that BSSID
+ * > TODO - When do we do the actual change channel?
+ *
+ ***LOGIC:
+ * SME sends eWNI_SME_START_BSS_REQ to LIM
+ * LIM sends LIM_MLM_START_REQ to MLME
+ * MLME sends WMA_ADD_BSS_REQ to HAL
+ * HAL responds with WMA_ADD_BSS_RSP to MLME
+ * MLME responds with LIM_MLM_START_CNF to LIM
+ * LIM responds with eWNI_SME_START_BSS_RSP to SME
+ *
+ ***ASSUMPTIONS:
+ * tSirMsgQ.body is allocated by MLME during lim_process_mlm_start_req
+ * tSirMsgQ.body will now be freed by this routine
+ *
+ ***NOTE:
+ *
+ * @param pMac Pointer to Global MAC structure
+ * @param tSirMsgQ The MsgQ header, which contains the response buffer
+ *
+ * @return None
+ */
+static void
+lim_process_ibss_mlm_add_bss_rsp(tpAniSirGlobal pMac, tpSirMsgQ limMsgQ,
+ tpPESession psessionEntry)
+{
+ tLimMlmStartCnf mlmStartCnf;
+ tpAddBssParams pAddBssParams = (tpAddBssParams) limMsgQ->bodyptr;
+
+ if (NULL == pAddBssParams) {
+ lim_log(pMac, LOGE, FL("Invalid body pointer in message"));
+ goto end;
+ }
+ if (CDF_STATUS_SUCCESS == pAddBssParams->status) {
+ PELOG1(lim_log
+ (pMac, LOG1,
+ FL("WMA_ADD_BSS_RSP returned with CDF_STATUS_SUCCESS"));
+ )
+ if (lim_set_link_state
+ (pMac, eSIR_LINK_IBSS_STATE, psessionEntry->bssId,
+ psessionEntry->selfMacAddr, NULL,
+ NULL) != eSIR_SUCCESS)
+ goto end;
+ /* Set MLME state */
+ psessionEntry->limMlmState = eLIM_MLM_BSS_STARTED_STATE;
+ MTRACE(mac_trace
+ (pMac, TRACE_CODE_MLM_STATE, psessionEntry->peSessionId,
+ psessionEntry->limMlmState));
+ /** IBSS is 'active' when we receive
+ * Beacon frames from other STAs that are part of same IBSS.
+ * Mark internal state as inactive until then.
+ */
+ psessionEntry->limIbssActive = false;
+ limResetHBPktCount(psessionEntry);
+ psessionEntry->bssIdx = (uint8_t) pAddBssParams->bssIdx;
+ psessionEntry->limSystemRole = eLIM_STA_IN_IBSS_ROLE;
+ psessionEntry->statypeForBss = STA_ENTRY_SELF;
+ sch_edca_profile_update(pMac, psessionEntry);
+ if (0 == psessionEntry->freePeerIdxHead)
+ lim_init_peer_idxpool(pMac, psessionEntry);
+
+ /* Apply previously set configuration at HW */
+ lim_apply_configuration(pMac, psessionEntry);
+ psessionEntry->staId = pAddBssParams->staContext.staIdx;
+ mlmStartCnf.resultCode = eSIR_SME_SUCCESS;
+ /* If ADD BSS was issued as part of IBSS coalescing, don't send the message to SME, as that is internal to LIM */
+ if (true == pMac->lim.gLimIbssCoalescingHappened) {
+ lim_ibss_add_bss_rsp_when_coalescing(pMac, limMsgQ->bodyptr,
+ psessionEntry);
+ goto end;
+ }
+ } else {
+ lim_log(pMac, LOGE, FL("WMA_ADD_BSS_REQ failed with status %d"),
+ pAddBssParams->status);
+ mlmStartCnf.resultCode = eSIR_SME_HAL_SEND_MESSAGE_FAIL;
+ }
+ /* Send this message to SME, when ADD_BSS is initiated by SME */
+ /* If ADD_BSS is done as part of coalescing, this won't happen. */
+ /* Update PE session Id */
+ mlmStartCnf.sessionId = psessionEntry->peSessionId;
+ lim_post_sme_message(pMac, LIM_MLM_START_CNF, (uint32_t *) &mlmStartCnf);
+end:
+ if (0 != limMsgQ->bodyptr) {
+ cdf_mem_free(pAddBssParams);
+ limMsgQ->bodyptr = NULL;
+ }
+}
+
+/**
+ * csr_neighbor_roam_handoff_req_hdlr - Processes handoff request
+ * @mac_ctx: Pointer to mac context
+ * @msg: message sent to HDD
+ * @session_entry: PE session handle
+ *
+ * This function is called to process a WMA_ADD_BSS_RSP from HAL.
+ * Upon receipt of this message from HAL if the state is pre assoc.
+ *
+ * Return: Null
+ */
+static void
+lim_process_sta_add_bss_rsp_pre_assoc(tpAniSirGlobal mac_ctx,
+ tpSirMsgQ msg, tpPESession session_entry)
+{
+ tpAddBssParams pAddBssParams = (tpAddBssParams) msg->bodyptr;
+ tAniAuthType cfgAuthType, authMode;
+ tLimMlmAuthReq *pMlmAuthReq;
+ tpDphHashNode pStaDs = NULL;
+
+ if (NULL == pAddBssParams) {
+ lim_log(mac_ctx, LOGE, FL("Invalid body pointer in message"));
+ goto joinFailure;
+ }
+ if (CDF_STATUS_SUCCESS == pAddBssParams->status) {
+ pStaDs = dph_add_hash_entry(mac_ctx,
+ pAddBssParams->staContext.staMac,
+ DPH_STA_HASH_INDEX_PEER,
+ &session_entry->dph.dphHashTable);
+ if (pStaDs == NULL) {
+ /* Could not add hash table entry */
+ lim_log(mac_ctx, LOGE,
+ FL("could not add hash entry at DPH for "));
+ lim_print_mac_addr(mac_ctx,
+ pAddBssParams->staContext.staMac, LOGE);
+ goto joinFailure;
+ }
+ session_entry->bssIdx = (uint8_t) pAddBssParams->bssIdx;
+ /* Success, handle below */
+ pStaDs->bssId = pAddBssParams->bssIdx;
+ /* STA Index(genr by HAL) for the BSS entry is stored here */
+ pStaDs->staIndex = pAddBssParams->staContext.staIdx;
+ /* Trigger Authentication with AP */
+ if (wlan_cfg_get_int(mac_ctx, WNI_CFG_AUTHENTICATION_TYPE,
+ (uint32_t *) &cfgAuthType) != eSIR_SUCCESS) {
+ /*
+ * Could not get AuthType from CFG.
+ * Log error.
+ */
+ lim_log(mac_ctx, LOGP,
+ FL("could not retrieve AuthType"));
+ }
+ /* Try Open Authentication first */
+ if (cfgAuthType == eSIR_AUTO_SWITCH)
+ authMode = eSIR_OPEN_SYSTEM;
+ else
+ authMode = cfgAuthType;
+
+ /* Trigger MAC based Authentication */
+ pMlmAuthReq = cdf_mem_malloc(sizeof(tLimMlmAuthReq));
+ if (NULL == pMlmAuthReq) {
+ lim_log(mac_ctx, LOGP,
+ FL("Allocate Memory failed for mlmAuthReq"));
+ return;
+ }
+ sir_copy_mac_addr(pMlmAuthReq->peerMacAddr,
+ session_entry->bssId);
+
+ pMlmAuthReq->authType = authMode;
+ if (wlan_cfg_get_int(mac_ctx,
+ WNI_CFG_AUTHENTICATE_FAILURE_TIMEOUT,
+ (uint32_t *) &pMlmAuthReq->authFailureTimeout)
+ != eSIR_SUCCESS) {
+ /*
+ * Could not get AuthFailureTimeout
+ * value from CFG. Log error.
+ */
+ lim_log(mac_ctx, LOGP,
+ FL("Fail: retrieve AuthFailureTimeout value"));
+ }
+ session_entry->limMlmState = eLIM_MLM_JOINED_STATE;
+ MTRACE(mac_trace(mac_ctx, TRACE_CODE_MLM_STATE,
+ session_entry->peSessionId, eLIM_MLM_JOINED_STATE));
+ pMlmAuthReq->sessionId = session_entry->peSessionId;
+ session_entry->limPrevSmeState = session_entry->limSmeState;
+ session_entry->limSmeState = eLIM_SME_WT_AUTH_STATE;
+ /* remember staId in case of assoc timeout/failure handling */
+ session_entry->staId = pAddBssParams->staContext.staIdx;
+
+ MTRACE(mac_trace(mac_ctx, TRACE_CODE_SME_STATE,
+ session_entry->peSessionId,
+ session_entry->limSmeState));
+ lim_log(mac_ctx, LOG1,
+ FL("SessionId:%d lim_post_mlm_message "
+ "LIM_MLM_AUTH_REQ with limSmeState:%d"),
+ session_entry->peSessionId, session_entry->limSmeState);
+ lim_post_mlm_message(mac_ctx, LIM_MLM_AUTH_REQ,
+ (uint32_t *) pMlmAuthReq);
+ return;
+ }
+
+joinFailure:
+ {
+ session_entry->limSmeState = eLIM_SME_JOIN_FAILURE_STATE;
+ MTRACE(mac_trace(mac_ctx, TRACE_CODE_SME_STATE,
+ session_entry->peSessionId,
+ session_entry->limSmeState));
+
+ /* Send Join response to Host */
+ lim_handle_sme_join_result(mac_ctx, eSIR_SME_REFUSED,
+ eSIR_MAC_UNSPEC_FAILURE_STATUS, session_entry);
+ }
+
+}
+
+#ifdef WLAN_FEATURE_VOWIFI_11R
+/*------------------------------------------------------------------------------------------
+ *
+ * Function to handle WMA_ADD_BSS_RSP, in FT reassoc state.
+ * Function to Send ReAssociation Request.
+ *
+ *
+ ***------------------------------------------------------------------------------------------
+ */
+static inline void
+lim_process_sta_mlm_add_bss_rsp_ft(tpAniSirGlobal pMac, tpSirMsgQ limMsgQ,
+ tpPESession psessionEntry)
+{
+ tLimMlmReassocCnf mlmReassocCnf; /* keep sme */
+ tpDphHashNode pStaDs = NULL;
+ tpAddStaParams pAddStaParams = NULL;
+ uint32_t listenInterval = WNI_CFG_LISTEN_INTERVAL_STADEF;
+ tpAddBssParams pAddBssParams = (tpAddBssParams) limMsgQ->bodyptr;
+ uint32_t selfStaDot11Mode = 0;
+
+ /* Sanity Checks */
+
+ if (pAddBssParams == NULL) {
+ PELOGE(lim_log(pMac, LOGE, FL("Invalid parameters"));)
+ goto end;
+ }
+ if (eLIM_MLM_WT_ADD_BSS_RSP_FT_REASSOC_STATE !=
+ psessionEntry->limMlmState) {
+ goto end;
+ }
+
+ pStaDs = dph_add_hash_entry(pMac, pAddBssParams->bssId,
+ DPH_STA_HASH_INDEX_PEER,
+ &psessionEntry->dph.dphHashTable);
+ if (pStaDs == NULL) {
+ /* Could not add hash table entry */
+ PELOGE(lim_log
+ (pMac, LOGE, FL("could not add hash entry at DPH for "));
+ )
+ lim_print_mac_addr(pMac, pAddBssParams->staContext.staMac,
+ LOGE);
+ goto end;
+ }
+ /* Prepare and send Reassociation request frame */
+ /* start reassoc timer. */
+#ifdef WLAN_FEATURE_ROAM_OFFLOAD
+ if (psessionEntry->bRoamSynchInProgress != true) {
+#endif
+ pMac->lim.limTimers.gLimReassocFailureTimer.sessionId =
+ psessionEntry->peSessionId;
+ /* / Start reassociation failure timer */
+ MTRACE(mac_trace
+ (pMac, TRACE_CODE_TIMER_ACTIVATE,
+ psessionEntry->peSessionId, eLIM_REASSOC_FAIL_TIMER));
+ if (tx_timer_activate
+ (&pMac->lim.limTimers.gLimReassocFailureTimer)
+ != TX_SUCCESS) {
+ /* / Could not start reassoc failure timer. */
+ /* Log error */
+ lim_log(pMac, LOGP,
+ FL
+ ("could not start Reassociation failure timer"));
+ /* Return Reassoc confirm with */
+ /* Resources Unavailable */
+ mlmReassocCnf.resultCode =
+ eSIR_SME_RESOURCES_UNAVAILABLE;
+ mlmReassocCnf.protStatusCode =
+ eSIR_MAC_UNSPEC_FAILURE_STATUS;
+ goto end;
+ }
+#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
+ pMac->lim.pSessionEntry = psessionEntry;
+ if (NULL == pMac->lim.pSessionEntry->pLimMlmReassocRetryReq) {
+ /* Take a copy of reassoc request for retrying */
+ pMac->lim.pSessionEntry->pLimMlmReassocRetryReq =
+ cdf_mem_malloc(sizeof(tLimMlmReassocReq));
+ if (NULL ==
+ pMac->lim.pSessionEntry->pLimMlmReassocRetryReq)
+ goto end;
+ cdf_mem_set(pMac->lim.pSessionEntry->
+ pLimMlmReassocRetryReq,
+ sizeof(tLimMlmReassocReq), 0);
+ cdf_mem_copy(pMac->lim.pSessionEntry->
+ pLimMlmReassocRetryReq,
+ psessionEntry->pLimMlmReassocReq,
+ sizeof(tLimMlmReassocReq));
+ }
+ pMac->lim.reAssocRetryAttempt = 0;
+#endif
+ lim_send_reassoc_req_with_ft_ies_mgmt_frame(pMac,
+ psessionEntry->
+ pLimMlmReassocReq,
+ psessionEntry);
+#ifdef WLAN_FEATURE_ROAM_OFFLOAD
+} else {
+ CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_DEBUG,
+ "LFR3:Do not activate timer and dont send the reassoc req");
+}
+#endif
+ psessionEntry->limPrevMlmState = psessionEntry->limMlmState;
+ psessionEntry->limMlmState = eLIM_MLM_WT_FT_REASSOC_RSP_STATE;
+ MTRACE(mac_trace
+ (pMac, TRACE_CODE_MLM_STATE, psessionEntry->peSessionId,
+ eLIM_MLM_WT_FT_REASSOC_RSP_STATE));
+ PELOGE(lim_log
+ (pMac, LOG1, FL("Set the mlm state to %d session=%d"),
+ psessionEntry->limMlmState, psessionEntry->peSessionId);
+ )
+
+ psessionEntry->bssIdx = (uint8_t) pAddBssParams->bssIdx;
+
+ /* Success, handle below */
+ pStaDs->bssId = pAddBssParams->bssIdx;
+ /* STA Index(genr by HAL) for the BSS entry is stored here */
+ pStaDs->staIndex = pAddBssParams->staContext.staIdx;
+ pStaDs->ucUcastSig = pAddBssParams->staContext.ucUcastSig;
+ pStaDs->ucBcastSig = pAddBssParams->staContext.ucBcastSig;
+
+#if defined WLAN_FEATURE_VOWIFI
+ rrm_cache_mgmt_tx_power(pMac, pAddBssParams->txMgmtPower, psessionEntry);
+#endif
+
+ pAddStaParams = cdf_mem_malloc(sizeof(tAddStaParams));
+ if (NULL == pAddStaParams) {
+ lim_log(pMac, LOGP,
+ FL("Unable to allocate memory during ADD_STA"));
+ goto end;
+ }
+ cdf_mem_set((uint8_t *) pAddStaParams, sizeof(tAddStaParams), 0);
+
+ /* / Add STA context at MAC HW (BMU, RHP & TFP) */
+ cdf_mem_copy((uint8_t *) pAddStaParams->staMac,
+ (uint8_t *) psessionEntry->selfMacAddr,
+ sizeof(tSirMacAddr));
+
+ cdf_mem_copy((uint8_t *) pAddStaParams->bssId,
+ psessionEntry->bssId, sizeof(tSirMacAddr));
+
+ pAddStaParams->staType = STA_ENTRY_SELF;
+ pAddStaParams->status = CDF_STATUS_SUCCESS;
+ pAddStaParams->respReqd = 1;
+
+ /* Update PE session ID */
+ pAddStaParams->sessionId = psessionEntry->peSessionId;
+ pAddStaParams->smesessionId = psessionEntry->smeSessionId;
+
+ /* This will indicate HAL to "allocate" a new STA index */
+#ifdef WLAN_FEATURE_ROAM_OFFLOAD
+ if (psessionEntry->bRoamSynchInProgress != true)
+#endif
+ pAddStaParams->staIdx = STA_INVALID_IDX;
+ pAddStaParams->updateSta = false;
+
+ pAddStaParams->shortPreambleSupported =
+ (uint8_t) psessionEntry->beaconParams.fShortPreamble;
+#ifdef WLAN_FEATURE_11AC
+ lim_populate_peer_rate_set(pMac, &pAddStaParams->supportedRates, NULL,
+ false, psessionEntry, NULL);
+#else
+ lim_populate_peer_rate_set(pMac, &pAddStaParams->supportedRates, NULL,
+ false, psessionEntry);
+#endif
+
+ if (psessionEntry->htCapability) {
+ pAddStaParams->htCapable = psessionEntry->htCapability;
+#ifdef WLAN_FEATURE_11AC
+ pAddStaParams->vhtCapable = psessionEntry->vhtCapability;
+ pAddStaParams->ch_width = psessionEntry->ch_width;
+#endif
+
+ pAddStaParams->greenFieldCapable =
+ lim_get_ht_capability(pMac, eHT_GREENFIELD,
+ psessionEntry);
+ pAddStaParams->mimoPS =
+ lim_get_ht_capability(pMac, eHT_MIMO_POWER_SAVE,
+ psessionEntry);
+ pAddStaParams->rifsMode =
+ lim_get_ht_capability(pMac, eHT_RIFS_MODE, psessionEntry);
+ pAddStaParams->lsigTxopProtection =
+ lim_get_ht_capability(pMac, eHT_LSIG_TXOP_PROTECTION,
+ psessionEntry);
+ pAddStaParams->maxAmpduDensity =
+ lim_get_ht_capability(pMac, eHT_MPDU_DENSITY, psessionEntry);
+ pAddStaParams->maxAmpduSize =
+ lim_get_ht_capability(pMac, eHT_MAX_RX_AMPDU_FACTOR,
+ psessionEntry);
+ pAddStaParams->maxAmsduSize =
+ lim_get_ht_capability(pMac, eHT_MAX_AMSDU_LENGTH,
+ psessionEntry);
+ pAddStaParams->fDsssCckMode40Mhz =
+ lim_get_ht_capability(pMac, eHT_DSSS_CCK_MODE_40MHZ,
+ psessionEntry);
+ pAddStaParams->fShortGI20Mhz =
+ lim_get_ht_capability(pMac, eHT_SHORT_GI_20MHZ, psessionEntry);
+ pAddStaParams->fShortGI40Mhz =
+ lim_get_ht_capability(pMac, eHT_SHORT_GI_40MHZ, psessionEntry);
+ }
+
+ if (wlan_cfg_get_int(pMac, WNI_CFG_LISTEN_INTERVAL, &listenInterval) !=
+ eSIR_SUCCESS)
+ lim_log(pMac, LOGP, FL("Couldn't get LISTEN_INTERVAL"));
+ pAddStaParams->listenInterval = (uint16_t) listenInterval;
+
+ wlan_cfg_get_int(pMac, WNI_CFG_DOT11_MODE, &selfStaDot11Mode);
+ pAddStaParams->supportedRates.opRateMode =
+ lim_get_sta_rate_mode((uint8_t) selfStaDot11Mode);
+ pAddStaParams->encryptType = psessionEntry->encryptType;
+ pAddStaParams->maxTxPower = psessionEntry->maxTxPower;
+
+ /* Lets save this for when we receive the Reassoc Rsp */
+ psessionEntry->ftPEContext.pAddStaReq = pAddStaParams;
+
+ if (pAddBssParams != NULL) {
+ cdf_mem_free(pAddBssParams);
+ pAddBssParams = NULL;
+ limMsgQ->bodyptr = NULL;
+ }
+#ifdef WLAN_FEATURE_ROAM_OFFLOAD
+ if (psessionEntry->bRoamSynchInProgress) {
+ CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_DEBUG,
+ "LFR3:Prepare and save pAddStaReq in pMac for post-assoc-rsp");
+ lim_process_assoc_rsp_frame(pMac, pMac->roam.pReassocResp,
+ LIM_REASSOC, psessionEntry);
+ }
+#endif
+ return;
+
+end:
+ /* Free up buffer allocated for reassocReq */
+ if (psessionEntry != NULL)
+ if (psessionEntry->pLimMlmReassocReq != NULL) {
+ cdf_mem_free(psessionEntry->pLimMlmReassocReq);
+ psessionEntry->pLimMlmReassocReq = NULL;
+ }
+
+ if (pAddBssParams != NULL) {
+ cdf_mem_free(pAddBssParams);
+ pAddBssParams = NULL;
+ limMsgQ->bodyptr = NULL;
+ }
+
+ mlmReassocCnf.resultCode = eSIR_SME_FT_REASSOC_FAILURE;
+ mlmReassocCnf.protStatusCode = eSIR_MAC_UNSPEC_FAILURE_STATUS;
+ /* Update PE session Id */
+ if (psessionEntry != NULL)
+ mlmReassocCnf.sessionId = psessionEntry->peSessionId;
+ else
+ mlmReassocCnf.sessionId = 0;
+
+ lim_post_sme_message(pMac, LIM_MLM_REASSOC_CNF,
+ (uint32_t *) &mlmReassocCnf);
+}
+#endif /* WLAN_FEATURE_VOWIFI_11R */
+/**
+ * lim_process_sta_mlm_add_bss_rsp() - Process ADD BSS response
+ * @mac_ctx: Pointer to Global MAC structure
+ * @msg: The MsgQ header, which contains the response buffer
+ *
+ * This function is called to process a WMA_ADD_BSS_RSP from HAL.
+ * Upon receipt of this message from HAL, MLME -
+ * > Validates the result of WMA_ADD_BSS_REQ
+ * > Now, send an ADD_STA to HAL and ADD the "local" STA itself
+ *
+ * MLME had sent WMA_ADD_BSS_REQ to HAL
+ * HAL responded with WMA_ADD_BSS_RSP to MLME
+ * MLME now sends WMA_ADD_STA_REQ to HAL
+ * ASSUMPTIONS:
+ * tSirMsgQ.body is allocated by MLME during lim_process_mlm_join_req
+ * tSirMsgQ.body will now be freed by this routine
+ *
+ * Return: None
+ */
+static void
+lim_process_sta_mlm_add_bss_rsp(tpAniSirGlobal mac_ctx,
+ tpSirMsgQ msg, tpPESession session_entry)
+{
+ tpAddBssParams add_bss_params = (tpAddBssParams) msg->bodyptr;
+ tLimMlmAssocCnf mlm_assoc_cnf;
+ uint32_t msg_type = LIM_MLM_ASSOC_CNF;
+ uint32_t sub_type = LIM_ASSOC;
+ tpDphHashNode sta_ds = NULL;
+ uint16_t sta_idx = STA_INVALID_IDX;
+ uint8_t update_sta = false;
+ mlm_assoc_cnf.resultCode = eSIR_SME_SUCCESS;
+
+ if (eLIM_MLM_WT_ADD_BSS_RSP_PREASSOC_STATE ==
+ session_entry->limMlmState) {
+ lim_log(mac_ctx, LOG1,
+ "SessionId:%d lim_process_sta_add_bss_rsp_pre_assoc",
+ session_entry->peSessionId);
+ lim_process_sta_add_bss_rsp_pre_assoc(mac_ctx, msg,
+ session_entry);
+ goto end;
+ }
+ if (eLIM_MLM_WT_ADD_BSS_RSP_REASSOC_STATE == session_entry->limMlmState
+#if defined(WLAN_FEATURE_VOWIFI_11R) || defined(FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
+ || (eLIM_MLM_WT_ADD_BSS_RSP_FT_REASSOC_STATE ==
+ session_entry->limMlmState)
+#endif
+ ) {
+ msg_type = LIM_MLM_REASSOC_CNF;
+ sub_type = LIM_REASSOC;
+ /*
+ * If Reassoc is happening for the same BSS, then
+ * use the existing StaId and indicate to HAL to update
+ * the existing STA entry.
+ * If Reassoc is happening for the new BSS, then
+ * old BSS and STA entry would have been already deleted
+ * before PE tries to add BSS for the new BSS, so set the
+ * updateSta to false and pass INVALID STA Index.
+ */
+ if (sir_compare_mac_addr(session_entry->bssId,
+ session_entry->limReAssocbssId)) {
+ sta_idx = session_entry->staId;
+ update_sta = true;
+ }
+ }
+
+ if (add_bss_params == 0)
+ goto end;
+#ifdef WLAN_FEATURE_ROAM_OFFLOAD
+ if (session_entry->bRoamSynchInProgress)
+ CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_DEBUG,
+ "LFR3:lim_process_sta_mlm_add_bss_rsp");
+#endif
+
+ if (CDF_STATUS_SUCCESS == add_bss_params->status) {
+#if defined(WLAN_FEATURE_VOWIFI_11R) || defined(FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
+ if (eLIM_MLM_WT_ADD_BSS_RSP_FT_REASSOC_STATE ==
+ session_entry->limMlmState) {
+#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG
+ lim_log(mac_ctx, LOG1, FL("Mlm=%d %d"),
+ session_entry->limMlmState,
+ eLIM_MLM_WT_ADD_BSS_RSP_REASSOC_STATE);
+#endif
+ lim_process_sta_mlm_add_bss_rsp_ft(mac_ctx, msg,
+ session_entry);
+ goto end;
+ }
+#endif /* WLAN_FEATURE_VOWIFI_11R */
+
+ /* Set MLME state */
+ session_entry->limMlmState = eLIM_MLM_WT_ADD_STA_RSP_STATE;
+ MTRACE(mac_trace(mac_ctx, TRACE_CODE_MLM_STATE,
+ session_entry->peSessionId,
+ session_entry->limMlmState));
+ /* to know the session started for self or for peer */
+ session_entry->statypeForBss = STA_ENTRY_PEER;
+ /* Now, send WMA_ADD_STA_REQ */
+ lim_log(mac_ctx, LOGW,
+ FL("SessionId:%d On STA: ADD_BSS was successful"),
+ session_entry->peSessionId);
+ sta_ds =
+ dph_get_hash_entry(mac_ctx, DPH_STA_HASH_INDEX_PEER,
+ &session_entry->dph.dphHashTable);
+ if (sta_ds == NULL) {
+ lim_log(mac_ctx, LOGE,
+ FL("Session:%d Fail to add Self Entry for STA"),
+ session_entry->peSessionId);
+ mlm_assoc_cnf.resultCode =
+ (tSirResultCodes) eSIR_SME_REFUSED;
+ } else {
+ session_entry->bssIdx =
+ (uint8_t) add_bss_params->bssIdx;
+ /* Success, handle below */
+ sta_ds->bssId = add_bss_params->bssIdx;
+ /*
+ * STA Index(genr by HAL) for the BSS
+ * entry is stored here
+ */
+ sta_ds->staIndex = add_bss_params->staContext.staIdx;
+ sta_ds->ucUcastSig =
+ add_bss_params->staContext.ucUcastSig;
+ sta_ds->ucBcastSig =
+ add_bss_params->staContext.ucBcastSig;
+ /* Downgrade the EDCA parameters if needed */
+ lim_set_active_edca_params(mac_ctx,
+ session_entry->gLimEdcaParams, session_entry);
+ lim_send_edca_params(mac_ctx,
+ session_entry->gLimEdcaParamsActive,
+ sta_ds->bssId);
+#if defined WLAN_FEATURE_VOWIFI
+ rrm_cache_mgmt_tx_power(mac_ctx,
+ add_bss_params->txMgmtPower, session_entry);
+#endif
+ if (lim_add_sta_self(mac_ctx, sta_idx, update_sta,
+ session_entry) != eSIR_SUCCESS) {
+ /* Add STA context at HW */
+ lim_log(mac_ctx, LOGE,
+ FL("Session:%d could not Add Self"
+ "Entry for the station"),
+ session_entry->peSessionId);
+ mlm_assoc_cnf.resultCode =
+ (tSirResultCodes) eSIR_SME_REFUSED;
+ }
+ }
+ } else {
+ lim_log(mac_ctx, LOGP, FL("SessionId:%d ADD_BSS failed!"),
+ session_entry->peSessionId);
+ /* Return Assoc confirm to SME with failure */
+ if (eLIM_MLM_WT_ADD_BSS_RSP_FT_REASSOC_STATE ==
+ session_entry->limMlmState)
+ mlm_assoc_cnf.resultCode =
+ (tSirResultCodes) eSIR_SME_FT_REASSOC_FAILURE;
+ else
+ mlm_assoc_cnf.resultCode =
+ (tSirResultCodes) eSIR_SME_REFUSED;
+ }
+
+ if (mlm_assoc_cnf.resultCode != eSIR_SME_SUCCESS) {
+ session_entry->limMlmState = eLIM_MLM_IDLE_STATE;
+ if (lim_set_link_state(mac_ctx, eSIR_LINK_IDLE_STATE,
+ session_entry->bssId,
+ session_entry->selfMacAddr,
+ NULL, NULL) != eSIR_SUCCESS)
+ lim_log(mac_ctx, LOGE, FL("Failed to set the LinkState"));
+ /* Update PE session Id */
+ mlm_assoc_cnf.sessionId = session_entry->peSessionId;
+ lim_post_sme_message(mac_ctx, msg_type,
+ (uint32_t *) &mlm_assoc_cnf);
+ }
+end:
+ if (0 != msg->bodyptr) {
+ cdf_mem_free(add_bss_params);
+ msg->bodyptr = NULL;
+ }
+}
+
+/**
+ * lim_process_mlm_add_bss_rsp() - Processes ADD BSS Response
+ *
+ * @mac_ctx - Pointer to Global MAC structure
+ * @msg - The MsgQ header, which contains the response buffer
+ *
+ * This function is called to process a WMA_ADD_BSS_RSP from HAL.
+ * Upon receipt of this message from HAL, MLME -
+ * Determines the "state" in which this message was received
+ * Forwards it to the appropriate callback
+ *
+ *LOGIC:
+ * WMA_ADD_BSS_RSP can be received by MLME while the LIM is
+ * in the following two states:
+ * 1) As AP, LIM state = eLIM_SME_WT_START_BSS_STATE
+ * 2) As STA, LIM state = eLIM_SME_WT_JOIN_STATE
+ * Based on these two states, this API will determine where to
+ * route the message to
+ *
+ * Return None
+ */
+void lim_process_mlm_add_bss_rsp(tpAniSirGlobal mac_ctx,
+ tpSirMsgQ msg)
+{
+ tLimMlmStartCnf mlm_start_cnf;
+ tpPESession session_entry;
+ tpAddBssParams add_bss_param = (tpAddBssParams) (msg->bodyptr);
+ tSirBssType bss_type;
+
+ if (NULL == add_bss_param) {
+ lim_log(mac_ctx, LOGE, FL("Encountered NULL Pointer"));
+ return;
+ }
+
+ /*
+ * we need to process the deferred message since the
+ * initiating req.there might be nested request.
+ * in the case of nested request the new request initiated
+ * from the response will take care of resetting the deffered
+ * flag.
+ */
+ SET_LIM_PROCESS_DEFD_MESGS(mac_ctx, true);
+ /* Validate SME/LIM/MLME state */
+ session_entry = pe_find_session_by_session_id(mac_ctx,
+ add_bss_param->sessionId);
+ if (session_entry == NULL) {
+ lim_log(mac_ctx, LOGE, FL("SessionId:%d Session Doesn't exist"),
+ add_bss_param->sessionId);
+ if (NULL != add_bss_param) {
+ cdf_mem_free(add_bss_param);
+ msg->bodyptr = NULL;
+ }
+ return;
+ }
+
+ session_entry->nss = add_bss_param->nss;
+ bss_type = session_entry->bssType;
+ /* update PE session Id */
+ mlm_start_cnf.sessionId = session_entry->peSessionId;
+ if (eSIR_IBSS_MODE == bss_type) {
+ lim_process_ibss_mlm_add_bss_rsp(mac_ctx, msg, session_entry);
+ } else {
+ if (eLIM_SME_WT_START_BSS_STATE == session_entry->limSmeState) {
+ if (eLIM_MLM_WT_ADD_BSS_RSP_STATE !=
+ session_entry->limMlmState) {
+ /* Mesg received from HAL in Invalid state! */
+ lim_log(mac_ctx, LOGE,
+ FL("SessionId:%d Received "
+ " WMA_ADD_BSS_RSP in state %X"),
+ session_entry->peSessionId,
+ session_entry->limMlmState);
+ mlm_start_cnf.resultCode =
+ eSIR_SME_BSS_ALREADY_STARTED_OR_JOINED;
+ if (0 != msg->bodyptr) {
+ cdf_mem_free(add_bss_param);
+ msg->bodyptr = NULL;
+ }
+ lim_post_sme_message(mac_ctx, LIM_MLM_START_CNF,
+ (uint32_t *) &mlm_start_cnf);
+ } else if ((bss_type == eSIR_BTAMP_AP_MODE) ||
+ (bss_type == eSIR_BTAMP_STA_MODE)) {
+ lim_process_btamp_add_bss_rsp(mac_ctx, msg,
+ session_entry);
+ } else
+ lim_process_ap_mlm_add_bss_rsp(mac_ctx, msg);
+ } else {
+ /* Called while processing assoc response */
+ lim_process_sta_mlm_add_bss_rsp(mac_ctx, msg,
+ session_entry);
+ }
+ }
+
+#ifdef WLAN_FEATURE_11W
+ if (session_entry->limRmfEnabled) {
+ if (eSIR_SUCCESS !=
+ lim_send_exclude_unencrypt_ind(mac_ctx, false,
+ session_entry)) {
+ lim_log(mac_ctx, LOGE,
+ FL("Failed to send Exclude Unencrypted Ind."));
+ }
+ }
+#endif
+}
+
+/**
+ * lim_process_mlm_set_sta_key_rsp() - Process STA key response
+ *
+ * @mac_ctx: Pointer to Global MAC structure
+ * @msg: The MsgQ header, which contains the response buffer
+ *
+ * This function is called to process the following two
+ * messages from HAL:
+ * 1) WMA_SET_BSSKEY_RSP
+ * 2) WMA_SET_STAKEY_RSP
+ * 3) WMA_SET_STA_BCASTKEY_RSP
+ * Upon receipt of this message from HAL,
+ * MLME -
+ * > Determines the "state" in which this message was received
+ * > Forwards it to the appropriate callback
+ * LOGIC:
+ * WMA_SET_BSSKEY_RSP/WMA_SET_STAKEY_RSP can be
+ * received by MLME while in the following state:
+ * MLME state = eLIM_MLM_WT_SET_BSS_KEY_STATE --OR--
+ * MLME state = eLIM_MLM_WT_SET_STA_KEY_STATE --OR--
+ * MLME state = eLIM_MLM_WT_SET_STA_BCASTKEY_STATE
+ * Based on this state, this API will determine where to
+ * route the message to
+ * Assumption:
+ * ONLY the MLME state is being taken into account for now.
+ * This is because, it appears that the handling of the
+ * SETKEYS REQ is handled symmetrically on both the AP & STA
+ *
+ * Return: None
+ */
+void lim_process_mlm_set_sta_key_rsp(tpAniSirGlobal mac_ctx,
+ tpSirMsgQ msg)
+{
+ uint8_t resp_reqd = 1;
+ tLimMlmSetKeysCnf mlm_set_key_cnf;
+ uint8_t session_id = 0;
+ tpPESession session_entry;
+
+ SET_LIM_PROCESS_DEFD_MESGS(mac_ctx, true);
+ cdf_mem_set((void *)&mlm_set_key_cnf, sizeof(tLimMlmSetKeysCnf), 0);
+ if (NULL == msg->bodyptr) {
+ PELOGE(lim_log(mac_ctx, LOGE, FL("msg bodyptr is NULL"));)
+ return;
+ }
+ session_id = ((tpSetStaKeyParams) msg->bodyptr)->sessionId;
+ session_entry = pe_find_session_by_session_id(mac_ctx, session_id);
+ if (session_entry == NULL) {
+ PELOGE(lim_log(mac_ctx, LOGE,
+ FL("session does not exist for given session_id"));)
+ cdf_mem_free(msg->bodyptr);
+ msg->bodyptr = NULL;
+ return;
+ }
+ if (eLIM_MLM_WT_SET_STA_KEY_STATE != session_entry->limMlmState) {
+ /* Mesg received from HAL in Invalid state! */
+ lim_log(mac_ctx, LOGE,
+ FL("Received unexpected [Mesg Id - %d] in state %X"),
+ msg->type, session_entry->limMlmState);
+ /* There's not much that MLME can do at this stage... */
+ resp_reqd = 0;
+ } else {
+ mlm_set_key_cnf.resultCode =
+ (uint16_t)(((tpSetStaKeyParams) msg->bodyptr)->status);
+ }
+
+ cdf_mem_free(msg->bodyptr);
+ msg->bodyptr = NULL;
+ /* Restore MLME state */
+ session_entry->limMlmState = session_entry->limPrevMlmState;
+ MTRACE(mac_trace(mac_ctx, TRACE_CODE_MLM_STATE,
+ session_entry->peSessionId, session_entry->limMlmState));
+ if (resp_reqd) {
+ tpLimMlmSetKeysReq lpLimMlmSetKeysReq =
+ (tpLimMlmSetKeysReq) mac_ctx->lim.gpLimMlmSetKeysReq;
+ /* Prepare and Send LIM_MLM_SETKEYS_CNF */
+ if (NULL != lpLimMlmSetKeysReq) {
+ cdf_mem_copy((uint8_t *) &mlm_set_key_cnf.peerMacAddr,
+ (uint8_t *) lpLimMlmSetKeysReq->peerMacAddr,
+ sizeof(tSirMacAddr));
+ /*
+ * Free the buffer cached for the global
+ * mac_ctx->lim.gpLimMlmSetKeysReq
+ */
+ cdf_mem_free(mac_ctx->lim.gpLimMlmSetKeysReq);
+ mac_ctx->lim.gpLimMlmSetKeysReq = NULL;
+ }
+ mlm_set_key_cnf.sessionId = session_id;
+ lim_post_sme_message(mac_ctx, LIM_MLM_SETKEYS_CNF,
+ (uint32_t *) &mlm_set_key_cnf);
+ }
+}
+
+/**
+ * lim_process_mlm_set_bss_key_rsp() - handles BSS key
+ *
+ * @mac_ctx: A pointer to Global MAC structure
+ * @msg: Message from SME
+ *
+ * This function processes BSS key response and updates
+ * PE status accordingly.
+ *
+ * Return: NULL
+ */
+void lim_process_mlm_set_bss_key_rsp(tpAniSirGlobal mac_ctx,
+ tpSirMsgQ msg)
+{
+ tLimMlmSetKeysCnf set_key_cnf;
+ uint16_t result_status;
+ uint8_t session_id = 0;
+ tpPESession session_entry;
+ tpLimMlmSetKeysReq set_key_req;
+
+ SET_LIM_PROCESS_DEFD_MESGS(mac_ctx, true);
+ cdf_mem_set((void *)&set_key_cnf, sizeof(tLimMlmSetKeysCnf), 0);
+ if (NULL == msg->bodyptr) {
+ PELOGE(lim_log(mac_ctx, LOGE, FL("msg bodyptr is null"));)
+ return;
+ }
+ session_id = ((tpSetBssKeyParams) msg->bodyptr)->sessionId;
+ session_entry = pe_find_session_by_session_id(mac_ctx, session_id);
+ if (session_entry == NULL) {
+ PELOGE(lim_log(mac_ctx, LOGE,
+ FL("session does not exist for given sessionId [%d]"),
+ session_id);)
+ cdf_mem_free(msg->bodyptr);
+ msg->bodyptr = NULL;
+ return;
+ }
+ if (eLIM_MLM_WT_SET_BSS_KEY_STATE == session_entry->limMlmState)
+ result_status =
+ (uint16_t)(((tpSetBssKeyParams)msg->bodyptr)->status);
+ else
+ /*
+ * BCAST key also uses tpSetStaKeyParams.
+ * Done this way for readabilty.
+ */
+ result_status =
+ (uint16_t)(((tpSetStaKeyParams)msg->bodyptr)->status);
+
+ /* Validate MLME state */
+ if (eLIM_MLM_WT_SET_BSS_KEY_STATE != session_entry->limMlmState &&
+ eLIM_MLM_WT_SET_STA_BCASTKEY_STATE !=
+ session_entry->limMlmState) {
+ /* Msg received from HAL in Invalid state! */
+ lim_log(mac_ctx, LOGE,
+ FL("Received unexpected [Mesg Id - %d] in state %X"),
+ msg->type, session_entry->limMlmState);
+ } else {
+ set_key_cnf.resultCode = result_status;
+ }
+
+ cdf_mem_free(msg->bodyptr);
+ msg->bodyptr = NULL;
+ /* Restore MLME state */
+ session_entry->limMlmState = session_entry->limPrevMlmState;
+
+ MTRACE(mac_trace
+ (mac_ctx, TRACE_CODE_MLM_STATE, session_entry->peSessionId,
+ session_entry->limMlmState));
+ set_key_req =
+ (tpLimMlmSetKeysReq) mac_ctx->lim.gpLimMlmSetKeysReq;
+ set_key_cnf.sessionId = session_id;
+
+ /* Prepare and Send LIM_MLM_SETKEYS_CNF */
+ if (NULL != set_key_req) {
+ cdf_mem_copy((uint8_t *) &set_key_cnf.peerMacAddr,
+ (uint8_t *) set_key_req->peerMacAddr,
+ sizeof(tSirMacAddr));
+ /*
+ * Free the buffer cached for the
+ * global mac_ctx->lim.gpLimMlmSetKeysReq
+ */
+ cdf_mem_free(mac_ctx->lim.gpLimMlmSetKeysReq);
+ mac_ctx->lim.gpLimMlmSetKeysReq = NULL;
+ }
+ lim_post_sme_message(mac_ctx, LIM_MLM_SETKEYS_CNF,
+ (uint32_t *) &set_key_cnf);
+}
+
+/**
+ * lim_process_switch_channel_re_assoc_req()
+ *
+ ***FUNCTION:
+ * This function is called to send the reassoc req mgmt frame after the
+ * switchChannelRsp message is received from HAL.
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ * NA
+ *
+ ***NOTE:
+ * NA
+ *
+ * @param pMac - Pointer to Global MAC structure.
+ * @param psessionEntry - session related information.
+ * @param status - channel switch success/failure.
+ *
+ * @return None
+ */
+static void lim_process_switch_channel_re_assoc_req(tpAniSirGlobal pMac,
+ tpPESession psessionEntry,
+ CDF_STATUS status)
+{
+ tLimMlmReassocCnf mlmReassocCnf;
+ tLimMlmReassocReq *pMlmReassocReq;
+ pMlmReassocReq =
+ (tLimMlmReassocReq *) (psessionEntry->pLimMlmReassocReq);
+ if (pMlmReassocReq == NULL) {
+ lim_log(pMac, LOGP,
+ FL
+ ("pLimMlmReassocReq does not exist for given switchChanSession"));
+ mlmReassocCnf.resultCode = eSIR_SME_RESOURCES_UNAVAILABLE;
+ goto end;
+ }
+
+ if (status != CDF_STATUS_SUCCESS) {
+ PELOGE(lim_log(pMac, LOGE, FL("Change channel failed!!"));)
+ mlmReassocCnf.resultCode = eSIR_SME_CHANNEL_SWITCH_FAIL;
+ goto end;
+ }
+ /* / Start reassociation failure timer */
+ MTRACE(mac_trace
+ (pMac, TRACE_CODE_TIMER_ACTIVATE, psessionEntry->peSessionId,
+ eLIM_REASSOC_FAIL_TIMER));
+ if (tx_timer_activate(&pMac->lim.limTimers.gLimReassocFailureTimer)
+ != TX_SUCCESS) {
+ /* / Could not start reassoc failure timer. */
+ /* Log error */
+ lim_log(pMac, LOGP,
+ FL("could not start Reassociation failure timer"));
+ /* Return Reassoc confirm with */
+ /* Resources Unavailable */
+ mlmReassocCnf.resultCode = eSIR_SME_RESOURCES_UNAVAILABLE;
+ goto end;
+ }
+ /* / Prepare and send Reassociation request frame */
+ lim_send_reassoc_req_mgmt_frame(pMac, pMlmReassocReq, psessionEntry);
+ return;
+end:
+ /* Free up buffer allocated for reassocReq */
+ if (pMlmReassocReq != NULL) {
+ /* Update PE session Id */
+ mlmReassocCnf.sessionId = pMlmReassocReq->sessionId;
+ cdf_mem_free(pMlmReassocReq);
+ psessionEntry->pLimMlmReassocReq = NULL;
+ } else {
+ mlmReassocCnf.sessionId = 0;
+ }
+
+ mlmReassocCnf.protStatusCode = eSIR_MAC_UNSPEC_FAILURE_STATUS;
+ /* Update PE sessio Id */
+ mlmReassocCnf.sessionId = psessionEntry->peSessionId;
+
+ lim_post_sme_message(pMac, LIM_MLM_REASSOC_CNF,
+ (uint32_t *) &mlmReassocCnf);
+}
+
+
+/**
+ * lim_process_switch_channel_join_req() -Initiates probe request
+ *
+ * @mac_ctx - A pointer to Global MAC structure
+ * @sessionEntry - session related information.
+ * @status - channel switch success/failure
+ *
+ * This function is called to send the probe req mgmt frame
+ * after the switchChannelRsp message is received from HAL.
+ *
+ * Return None
+ */
+static void lim_process_switch_channel_join_req(
+ tpAniSirGlobal mac_ctx, tpPESession session_entry,
+ CDF_STATUS status)
+{
+ tSirMacSSid ssId;
+ tLimMlmJoinCnf join_cnf;
+ if (status != CDF_STATUS_SUCCESS) {
+ PELOGE(lim_log(mac_ctx, LOGE, FL("Change channel failed!!"));)
+ goto error;
+ }
+
+ if ((NULL == session_entry) || (NULL == session_entry->pLimMlmJoinReq)
+ || (NULL == session_entry->pLimJoinReq)) {
+ PELOGE(lim_log(mac_ctx, LOGE, FL("invalid pointer!!"));)
+ goto error;
+ }
+
+ /*
+ * eSIR_BTAMP_AP_MODE stroed as bss type in session
+ * Table when join req is received, is to be veified
+ */
+ if (session_entry->bssType == eSIR_BTAMP_AP_MODE) {
+ if (lim_set_link_state
+ (mac_ctx, eSIR_LINK_BTAMP_PREASSOC_STATE,
+ session_entry->bssId, session_entry->selfMacAddr,
+ NULL, NULL) != eSIR_SUCCESS) {
+ PELOGE(lim_log
+ (mac_ctx, LOGE,
+ FL("Sessionid: %d Set link state "
+ "failed!! BSSID:" MAC_ADDRESS_STR),
+ session_entry->peSessionId,
+ MAC_ADDR_ARRAY(session_entry->bssId));)
+ goto error;
+ }
+ }
+
+ session_entry->limPrevMlmState = session_entry->limMlmState;
+ session_entry->limMlmState = eLIM_MLM_WT_JOIN_BEACON_STATE;
+ lim_log(mac_ctx, LOG1,
+ FL("Sessionid %d prev lim state %d new lim state %d "
+ "systemrole = %d"), session_entry->peSessionId,
+ session_entry->limPrevMlmState,
+ session_entry->limMlmState, GET_LIM_SYSTEM_ROLE(session_entry));
+
+ /* Apply previously set configuration at HW */
+ lim_apply_configuration(mac_ctx, session_entry);
+
+ /*
+ * If sendDeauthBeforeCon is enabled, Send Deauth first to AP if last
+ * disconnection was caused by HB failure.
+ */
+ if(mac_ctx->roam.configParam.sendDeauthBeforeCon) {
+ int apCount;
+
+ for(apCount = 0; apCount < 2; apCount++) {
+
+ if (cdf_mem_compare(session_entry->pLimMlmJoinReq->bssDescription.bssId,
+ mac_ctx->lim.gLimHeartBeatApMac[apCount], sizeof(tSirMacAddr))) {
+
+ lim_log(mac_ctx, LOGE, FL("Index %d Sessionid: %d Send deauth on "
+ "channel %d to BSSID: "MAC_ADDRESS_STR ), apCount,
+ session_entry->peSessionId, session_entry->currentOperChannel,
+ MAC_ADDR_ARRAY(session_entry->pLimMlmJoinReq->bssDescription.
+ bssId));
+
+ lim_send_deauth_mgmt_frame(mac_ctx, eSIR_MAC_UNSPEC_FAILURE_REASON,
+ session_entry->pLimMlmJoinReq->bssDescription.bssId,
+ session_entry, false );
+
+ cdf_mem_zero(mac_ctx->lim.gLimHeartBeatApMac[apCount],
+ sizeof(tSirMacAddr));
+ break;
+ }
+ }
+ }
+
+ /* Wait for Beacon to announce join success */
+ cdf_mem_copy(ssId.ssId,
+ session_entry->ssId.ssId, session_entry->ssId.length);
+ ssId.length = session_entry->ssId.length;
+
+ lim_deactivate_and_change_timer(mac_ctx,
+ eLIM_PERIODIC_JOIN_PROBE_REQ_TIMER);
+
+ /* assign appropriate sessionId to the timer object */
+ mac_ctx->lim.limTimers.gLimPeriodicJoinProbeReqTimer.sessionId =
+ session_entry->peSessionId;
+ lim_log(mac_ctx, LOG1,
+ FL("Sessionid: %d Send Probe req on channel %d ssid:%.*s "
+ "BSSID: " MAC_ADDRESS_STR), session_entry->peSessionId,
+ session_entry->currentOperChannel, ssId.length, ssId.ssId,
+ MAC_ADDR_ARRAY(
+ session_entry->pLimMlmJoinReq->bssDescription.bssId));
+
+ /*
+ * We need to wait for probe response, so start join
+ * timeout timer.This timer will be deactivated once
+ * we receive probe response.
+ */
+ MTRACE(mac_trace(mac_ctx, TRACE_CODE_TIMER_ACTIVATE,
+ session_entry->peSessionId, eLIM_JOIN_FAIL_TIMER));
+ if (tx_timer_activate(&mac_ctx->lim.limTimers.gLimJoinFailureTimer) !=
+ TX_SUCCESS) {
+ lim_log(mac_ctx, LOGP,
+ FL("couldn't activate Join failure timer"));
+ session_entry->limMlmState = session_entry->limPrevMlmState;
+ MTRACE(mac_trace(mac_ctx, TRACE_CODE_MLM_STATE,
+ session_entry->peSessionId,
+ mac_ctx->lim.gLimMlmState));
+ session_entry->pLimMlmJoinReq = NULL;
+ goto error;
+ }
+ /* include additional IE if there is */
+ lim_send_probe_req_mgmt_frame(mac_ctx, &ssId,
+ session_entry->pLimMlmJoinReq->bssDescription.bssId,
+ session_entry->currentOperChannel, session_entry->selfMacAddr,
+ session_entry->dot11mode,
+ session_entry->pLimJoinReq->addIEScan.length,
+ session_entry->pLimJoinReq->addIEScan.addIEdata);
+
+ if (session_entry->pePersona == CDF_P2P_CLIENT_MODE) {
+ /* Activate Join Periodic Probe Req timer */
+ if (tx_timer_activate
+ (&mac_ctx->lim.limTimers.gLimPeriodicJoinProbeReqTimer)
+ != TX_SUCCESS) {
+ lim_log(mac_ctx, LOGP,
+ FL("Periodic JoinReq timer activate failed"));
+ goto error;
+ }
+ }
+ return;
+error:
+ if (NULL != session_entry) {
+ if (session_entry->pLimMlmJoinReq) {
+ cdf_mem_free(session_entry->pLimMlmJoinReq);
+ session_entry->pLimMlmJoinReq = NULL;
+ }
+ if (session_entry->pLimJoinReq) {
+ cdf_mem_free(session_entry->pLimJoinReq);
+ session_entry->pLimJoinReq = NULL;
+ }
+ join_cnf.sessionId = session_entry->peSessionId;
+ } else {
+ join_cnf.sessionId = 0;
+ }
+ join_cnf.resultCode = eSIR_SME_RESOURCES_UNAVAILABLE;
+ join_cnf.protStatusCode = eSIR_MAC_UNSPEC_FAILURE_STATUS;
+ lim_post_sme_message(mac_ctx, LIM_MLM_JOIN_CNF, (uint32_t *)&join_cnf);
+}
+
+/**
+ * lim_process_switch_channel_rsp()
+ *
+ ***FUNCTION:
+ * This function is called to process switchChannelRsp message from HAL.
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ * NA
+ *
+ ***NOTE:
+ * NA
+ *
+ * @param pMac - Pointer to Global MAC structure
+ * @param body - message body.
+ *
+ * @return None
+ */
+void lim_process_switch_channel_rsp(tpAniSirGlobal pMac, void *body)
+{
+ tpSwitchChannelParams pChnlParams = NULL;
+ CDF_STATUS status;
+ uint16_t channelChangeReasonCode;
+ uint8_t peSessionId;
+ tpPESession psessionEntry;
+ /* we need to process the deferred message since the initiating req. there might be nested request. */
+ /* in the case of nested request the new request initiated from the response will take care of resetting */
+ /* the deffered flag. */
+ SET_LIM_PROCESS_DEFD_MESGS(pMac, true);
+ pChnlParams = (tpSwitchChannelParams) body;
+ status = pChnlParams->status;
+ peSessionId = pChnlParams->peSessionId;
+
+ psessionEntry = pe_find_session_by_session_id(pMac, peSessionId);
+ if (psessionEntry == NULL) {
+ lim_log(pMac, LOGP,
+ FL("session does not exist for given sessionId"));
+ return;
+ }
+#if defined WLAN_FEATURE_VOWIFI
+ /* HAL fills in the tx power used for mgmt frames in this field. */
+ /* Store this value to use in TPC report IE. */
+ rrm_cache_mgmt_tx_power(pMac, pChnlParams->txMgmtPower, psessionEntry);
+#endif
+ channelChangeReasonCode = psessionEntry->channelChangeReasonCode;
+ /* initialize it back to invalid id */
+ psessionEntry->chainMask = pChnlParams->chainMask;
+ psessionEntry->nss = pChnlParams->nss;
+ psessionEntry->smpsMode = pChnlParams->smpsMode;
+ psessionEntry->channelChangeReasonCode = 0xBAD;
+ lim_log(pMac, LOG1, FL("channelChangeReasonCode %d"),
+ channelChangeReasonCode);
+ switch (channelChangeReasonCode) {
+ case LIM_SWITCH_CHANNEL_REASSOC:
+ lim_process_switch_channel_re_assoc_req(pMac, psessionEntry, status);
+ break;
+ case LIM_SWITCH_CHANNEL_JOIN:
+ lim_process_switch_channel_join_req(pMac, psessionEntry, status);
+ break;
+
+ case LIM_SWITCH_CHANNEL_OPERATION:
+ /*
+ * The above code should also use the callback.
+ * mechanism below, there is scope for cleanup here.
+ * THat way all this response handler does is call the call back
+ * We can get rid of the reason code here.
+ */
+ if (pMac->lim.gpchangeChannelCallback) {
+ PELOG1(lim_log
+ (pMac, LOG1,
+ "Channel changed hence invoke registered call back");
+ )
+ pMac->lim.gpchangeChannelCallback(pMac, status,
+ pMac->lim.
+ gpchangeChannelData,
+ psessionEntry);
+ }
+ break;
+ case LIM_SWITCH_CHANNEL_SAP_DFS:
+ {
+ /* Note: This event code specific to SAP mode
+ * When SAP session issues channel change as performing
+ * DFS, we will come here. Other sessions, for e.g. P2P
+ * will have to define their own event code and channel
+ * switch handler. This is required since the SME may
+ * require completely different information for P2P unlike
+ * SAP.
+ */
+ lim_send_sme_ap_channel_switch_resp(pMac, psessionEntry,
+ pChnlParams);
+ }
+ break;
+ default:
+ break;
+ }
+ cdf_mem_free(body);
+}
+
+/**
+ * @function : lim_handle_del_bss_in_re_assoc_context
+ * @brief : While Processing the ReAssociation Response Frame in STA,
+ * a. immediately after receiving the Reassoc Response the RxCleanUp is
+ * being issued and the end of DelBSS the new BSS is being added.
+ *
+ * b .If an AP rejects the ReAssociation (Disassoc / Deauth) with some context
+ * change, We need to update CSR with ReAssocCNF Response with the
+ * ReAssoc Fail and the reason Code, that is also being handled in the DELBSS
+ * context only
+ *
+ * @param : pMac - tpAniSirGlobal
+ * pStaDs - Station Descriptor
+ *
+ * @return : none
+ */
+static void
+lim_handle_del_bss_in_re_assoc_context(tpAniSirGlobal pMac, tpDphHashNode pStaDs,
+ tpPESession psessionEntry)
+{
+ tLimMlmReassocCnf mlmReassocCnf;
+ /*
+ * Skipped the DeleteDPH Hash Entry as we need it for the new BSS
+ * Set the MlmState to IDLE
+ */
+ psessionEntry->limMlmState = eLIM_MLM_IDLE_STATE;
+ /* Update PE session Id */
+ mlmReassocCnf.sessionId = psessionEntry->peSessionId;
+ switch (psessionEntry->limSmeState) {
+ case eLIM_SME_WT_REASSOC_STATE:
+ {
+ tpSirAssocRsp assocRsp;
+ tpDphHashNode pStaDs;
+ tSirRetStatus retStatus = eSIR_SUCCESS;
+ tpSchBeaconStruct beacon_struct;
+ beacon_struct = cdf_mem_malloc(sizeof(tSchBeaconStruct));
+ if (NULL == beacon_struct) {
+ lim_log(pMac, LOGE, FL("beaconStruct alloc failed"));
+ mlmReassocCnf.resultCode =
+ eSIR_SME_RESOURCES_UNAVAILABLE;
+ mlmReassocCnf.protStatusCode =
+ eSIR_MAC_UNSPEC_FAILURE_STATUS;
+ lim_delete_dph_hash_entry(pMac, psessionEntry->bssId,
+ DPH_STA_HASH_INDEX_PEER, psessionEntry);
+ goto error;
+ }
+ /* Delete the older STA Table entry */
+ lim_delete_dph_hash_entry(pMac, psessionEntry->bssId,
+ DPH_STA_HASH_INDEX_PEER, psessionEntry);
+ /*
+ * Add an entry for AP to hash table
+ * maintained by DPH module
+ */
+ pStaDs = dph_add_hash_entry(pMac,
+ psessionEntry->limReAssocbssId,
+ DPH_STA_HASH_INDEX_PEER,
+ &psessionEntry->dph.dphHashTable);
+ if (pStaDs == NULL) {
+ /* Could not add hash table entry */
+ lim_log(pMac, LOGE,
+ FL("could not add hash entry at DPH for "));
+ lim_print_mac_addr(pMac,
+ psessionEntry->limReAssocbssId, LOGE);
+ mlmReassocCnf.resultCode =
+ eSIR_SME_RESOURCES_UNAVAILABLE;
+ mlmReassocCnf.protStatusCode = eSIR_SME_SUCCESS;
+ goto error;
+ }
+ /*
+ * While Processing the ReAssoc Response Frame the ReAssocRsp Frame
+ * is being stored to be used here for sending ADDBSS
+ */
+ assocRsp =
+ (tpSirAssocRsp) psessionEntry->limAssocResponseData;
+ lim_update_assoc_sta_datas(pMac, pStaDs, assocRsp,
+ psessionEntry);
+ lim_update_re_assoc_globals(pMac, assocRsp, psessionEntry);
+ lim_extract_ap_capabilities(pMac,
+ (uint8_t *) psessionEntry->pLimReAssocReq->bssDescription.ieFields,
+ lim_get_ielen_from_bss_description(
+ &psessionEntry->pLimReAssocReq->bssDescription),
+ beacon_struct);
+ if (pMac->lim.gLimProtectionControl !=
+ WNI_CFG_FORCE_POLICY_PROTECTION_DISABLE)
+ lim_decide_sta_protection_on_assoc(pMac,
+ beacon_struct,
+ psessionEntry);
+ if (beacon_struct->erpPresent) {
+ if (beacon_struct->erpIEInfo.barkerPreambleMode)
+ psessionEntry->beaconParams.fShortPreamble = 0;
+ else
+ psessionEntry->beaconParams.fShortPreamble = 1;
+ }
+ /*
+ * updateBss flag is false, as in this case, PE is first
+ * deleting the existing BSS and then adding a new one
+ */
+ if (eSIR_SUCCESS !=
+ lim_sta_send_add_bss(pMac, assocRsp, beacon_struct,
+ &psessionEntry->pLimReAssocReq->bssDescription,
+ false, psessionEntry)) {
+ lim_log(pMac, LOGE,
+ FL("Posting ADDBSS in the ReAssocCtx has Failed "));
+ retStatus = eSIR_FAILURE;
+ }
+ if (retStatus != eSIR_SUCCESS) {
+ mlmReassocCnf.resultCode =
+ eSIR_SME_RESOURCES_UNAVAILABLE;
+ mlmReassocCnf.protStatusCode =
+ eSIR_MAC_UNSPEC_FAILURE_STATUS;
+ cdf_mem_free(assocRsp);
+ pMac->lim.gLimAssocResponseData = NULL;
+ cdf_mem_free(beacon_struct);
+ goto error;
+ }
+ cdf_mem_free(assocRsp);
+ cdf_mem_free(beacon_struct);
+ psessionEntry->limAssocResponseData = NULL;
+ }
+ break;
+ case eLIM_SME_WT_REASSOC_LINK_FAIL_STATE:
+ {
+ /** Case wherein the DisAssoc / Deauth
+ * being sent as response to ReAssoc Req*/
+ /** Send the Reason code as the same received in Disassoc / Deauth Frame*/
+ mlmReassocCnf.resultCode =
+ pStaDs->mlmStaContext.disassocReason;
+ mlmReassocCnf.protStatusCode =
+ pStaDs->mlmStaContext.cleanupTrigger;
+ /** Set the SME State back to WT_Reassoc State*/
+ psessionEntry->limSmeState = eLIM_SME_WT_REASSOC_STATE;
+ lim_delete_dph_hash_entry(pMac, pStaDs->staAddr,
+ pStaDs->assocId, psessionEntry);
+ if (LIM_IS_STA_ROLE(psessionEntry) ||
+ LIM_IS_BT_AMP_STA_ROLE(psessionEntry)) {
+ psessionEntry->limMlmState =
+ eLIM_MLM_IDLE_STATE;
+ }
+ lim_post_sme_message(pMac, LIM_MLM_REASSOC_CNF,
+ (uint32_t *) &mlmReassocCnf);
+ }
+ break;
+ default:
+ lim_log(pMac, LOGE,
+ FL("DelBss is being invoked in the wrong system Role /unhandled SME State"));
+
+ mlmReassocCnf.resultCode = eSIR_SME_REFUSED;
+ mlmReassocCnf.protStatusCode =
+ eSIR_SME_UNEXPECTED_REQ_RESULT_CODE;
+ goto error;
+ }
+ return;
+error:
+ lim_post_sme_message(pMac, LIM_MLM_REASSOC_CNF,
+ (uint32_t *) &mlmReassocCnf);
+}
+
+/* Added For BT -AMP Support */
+static void
+lim_process_btamp_add_bss_rsp(tpAniSirGlobal pMac, tpSirMsgQ limMsgQ,
+ tpPESession psessionEntry)
+{
+ tLimMlmStartCnf mlmStartCnf;
+ tpAddBssParams pAddBssParams = (tpAddBssParams) limMsgQ->bodyptr;
+
+ if (NULL == pAddBssParams) {
+ lim_log(pMac, LOGE, FL("Invalid body pointer in message"));
+ goto end;
+ }
+ if (CDF_STATUS_SUCCESS == pAddBssParams->status) {
+ lim_log(pMac, LOG2,
+ FL("WMA_ADD_BSS_RSP returned with CDF_STATUS_SUCCESS"));
+ if (psessionEntry->bssType == eSIR_BTAMP_AP_MODE) {
+ if (lim_set_link_state
+ (pMac, eSIR_LINK_BTAMP_AP_STATE,
+ psessionEntry->bssId, psessionEntry->selfMacAddr,
+ NULL, NULL) != eSIR_SUCCESS)
+ goto end;
+ } else if (psessionEntry->bssType == eSIR_BTAMP_STA_MODE) {
+ if (lim_set_link_state
+ (pMac, eSIR_LINK_SCAN_STATE, psessionEntry->bssId,
+ psessionEntry->selfMacAddr, NULL,
+ NULL) != eSIR_SUCCESS)
+ goto end;
+ }
+ /* Set MLME state */
+ psessionEntry->limMlmState = eLIM_MLM_BSS_STARTED_STATE;
+ psessionEntry->statypeForBss = STA_ENTRY_SELF; /* to know session started for peer or for self */
+ psessionEntry->bssIdx = (uint8_t) pAddBssParams->bssIdx;
+ sch_edca_profile_update(pMac, psessionEntry);
+ lim_init_peer_idxpool(pMac, psessionEntry);
+
+ /* Apply previously set configuration at HW */
+ lim_apply_configuration(pMac, psessionEntry);
+ psessionEntry->staId = pAddBssParams->staContext.staIdx;
+ mlmStartCnf.resultCode = eSIR_SME_SUCCESS;
+ } else {
+ lim_log(pMac, LOGE, FL("WMA_ADD_BSS_REQ failed with status %d"),
+ pAddBssParams->status);
+ mlmStartCnf.resultCode = eSIR_SME_HAL_SEND_MESSAGE_FAIL;
+ }
+ mlmStartCnf.sessionId = psessionEntry->peSessionId;
+ lim_post_sme_message(pMac, LIM_MLM_START_CNF, (uint32_t *) &mlmStartCnf);
+end:
+ if (0 != limMsgQ->bodyptr) {
+ cdf_mem_free(pAddBssParams);
+ limMsgQ->bodyptr = NULL;
+ }
+}
+
+/**
+ * @function : lim_handle_add_bss_in_re_assoc_context
+ * @brief : While Processing the ReAssociation Response Frame in STA,
+ * a. immediately after receiving the Reassoc Response the RxCleanUp is
+ * being issued and the end of DelBSS the new BSS is being added.
+ *
+ * b .If an AP rejects the ReAssociation (Disassoc / Deauth) with some context
+ * change, We need to update CSR with ReAssocCNF Response with the
+ * ReAssoc Fail and the reason Code, that is also being handled in the DELBSS
+ * context only
+ *
+ * @param : pMac - tpAniSirGlobal
+ * pStaDs - Station Descriptor
+ *
+ * @return : none
+ */
+void
+lim_handle_add_bss_in_re_assoc_context(tpAniSirGlobal pMac, tpDphHashNode pStaDs,
+ tpPESession psessionEntry)
+{
+ tLimMlmReassocCnf mlmReassocCnf;
+ /** Skipped the DeleteDPH Hash Entry as we need it for the new BSS*/
+ /** Set the MlmState to IDLE*/
+ psessionEntry->limMlmState = eLIM_MLM_IDLE_STATE;
+ MTRACE(mac_trace
+ (pMac, TRACE_CODE_MLM_STATE, psessionEntry->peSessionId,
+ psessionEntry->limMlmState));
+ switch (psessionEntry->limSmeState) {
+ case eLIM_SME_WT_REASSOC_STATE: {
+ tpSirAssocRsp assocRsp;
+ tpDphHashNode pStaDs;
+ tSirRetStatus retStatus = eSIR_SUCCESS;
+ tSchBeaconStruct *pBeaconStruct;
+ pBeaconStruct =
+ cdf_mem_malloc(sizeof(tSchBeaconStruct));
+ if (NULL == pBeaconStruct) {
+ lim_log(pMac, LOGE,
+ FL
+ ("Unable to allocate memory in lim_handle_add_bss_in_re_assoc_context"));
+ mlmReassocCnf.resultCode =
+ eSIR_SME_RESOURCES_UNAVAILABLE;
+ mlmReassocCnf.protStatusCode =
+ eSIR_SME_RESOURCES_UNAVAILABLE;
+ goto Error;
+ }
+ /* Get the AP entry from DPH hash table */
+ pStaDs =
+ dph_get_hash_entry(pMac, DPH_STA_HASH_INDEX_PEER,
+ &psessionEntry->dph.dphHashTable);
+ if (pStaDs == NULL) {
+ PELOGE(lim_log
+ (pMac, LOGE,
+ FL
+ ("Fail to get STA PEER entry from hash"));
+ )
+ mlmReassocCnf.resultCode =
+ eSIR_SME_RESOURCES_UNAVAILABLE;
+ mlmReassocCnf.protStatusCode = eSIR_SME_SUCCESS;
+ cdf_mem_free(pBeaconStruct);
+ goto Error;
+ }
+ /** While Processing the ReAssoc Response Frame the ReAssocRsp Frame
+ * is being stored to be used here for sending ADDBSS
+ */
+ assocRsp =
+ (tpSirAssocRsp) psessionEntry->limAssocResponseData;
+ lim_update_assoc_sta_datas(pMac, pStaDs, assocRsp,
+ psessionEntry);
+ lim_update_re_assoc_globals(pMac, assocRsp, psessionEntry);
+ lim_extract_ap_capabilities(pMac,
+ (uint8_t *) psessionEntry->
+ pLimReAssocReq->bssDescription.
+ ieFields,
+ lim_get_ielen_from_bss_description
+ (&psessionEntry->
+ pLimReAssocReq->
+ bssDescription),
+ pBeaconStruct);
+ if (pMac->lim.gLimProtectionControl !=
+ WNI_CFG_FORCE_POLICY_PROTECTION_DISABLE)
+ lim_decide_sta_protection_on_assoc(pMac,
+ pBeaconStruct,
+ psessionEntry);
+
+ if (pBeaconStruct->erpPresent) {
+ if (pBeaconStruct->erpIEInfo.barkerPreambleMode)
+ psessionEntry->beaconParams.
+ fShortPreamble = 0;
+ else
+ psessionEntry->beaconParams.
+ fShortPreamble = 1;
+ }
+
+ psessionEntry->isNonRoamReassoc = 1;
+ if (eSIR_SUCCESS !=
+ lim_sta_send_add_bss(pMac, assocRsp, pBeaconStruct,
+ &psessionEntry->pLimReAssocReq->
+ bssDescription, true,
+ psessionEntry)) {
+ lim_log(pMac, LOGE,
+ FL
+ ("Posting ADDBSS in the ReAssocContext has Failed "));
+ retStatus = eSIR_FAILURE;
+ }
+ if (retStatus != eSIR_SUCCESS) {
+ mlmReassocCnf.resultCode =
+ eSIR_SME_RESOURCES_UNAVAILABLE;
+ mlmReassocCnf.protStatusCode =
+ eSIR_MAC_UNSPEC_FAILURE_STATUS;
+ cdf_mem_free(assocRsp);
+ pMac->lim.gLimAssocResponseData = NULL;
+ cdf_mem_free(pBeaconStruct);
+ goto Error;
+ }
+ cdf_mem_free(assocRsp);
+ psessionEntry->limAssocResponseData = NULL;
+ cdf_mem_free(pBeaconStruct);
+ }
+ break;
+ case eLIM_SME_WT_REASSOC_LINK_FAIL_STATE: {
+ /* Case wherein the DisAssoc / Deauth
+ * being sent as response to ReAssoc Req
+ * Send the Reason code as the same received
+ * in Disassoc / Deauth Frame
+ */
+ mlmReassocCnf.resultCode =
+ pStaDs->mlmStaContext.disassocReason;
+ mlmReassocCnf.protStatusCode =
+ pStaDs->mlmStaContext.cleanupTrigger;
+ /** Set the SME State back to WT_Reassoc State*/
+ psessionEntry->limSmeState = eLIM_SME_WT_REASSOC_STATE;
+ lim_delete_dph_hash_entry(pMac, pStaDs->staAddr,
+ pStaDs->assocId, psessionEntry);
+ if (LIM_IS_STA_ROLE(psessionEntry)) {
+ psessionEntry->limMlmState =
+ eLIM_MLM_IDLE_STATE;
+ MTRACE(mac_trace
+ (pMac, TRACE_CODE_MLM_STATE,
+ psessionEntry->peSessionId,
+ psessionEntry->limMlmState));
+ }
+
+ lim_post_sme_message(pMac, LIM_MLM_REASSOC_CNF,
+ (uint32_t *) &mlmReassocCnf);
+ }
+ break;
+ default:
+ PELOGE(lim_log
+ (pMac, LOGE,
+ FL
+ ("DelBss is being invoked in the wrong system Role /unhandled SME State"));
+ )
+ mlmReassocCnf.resultCode = eSIR_SME_REFUSED;
+ mlmReassocCnf.protStatusCode =
+ eSIR_SME_UNEXPECTED_REQ_RESULT_CODE;
+ goto Error;
+ }
+ return;
+Error:
+ lim_post_sme_message(pMac, LIM_MLM_REASSOC_CNF,
+ (uint32_t *) &mlmReassocCnf);
+}
+
+void lim_send_beacon_ind(tpAniSirGlobal pMac, tpPESession psessionEntry)
+{
+ tBeaconGenParams *pBeaconGenParams = NULL;
+ tSirMsgQ limMsg;
+ /** Allocate the Memory for Beacon Pre Message and for Stations in PoweSave*/
+ if (psessionEntry == NULL) {
+ PELOGE(lim_log(pMac, LOGE,
+ FL("Error:Unable to get the PESessionEntry"));
+ )
+ return;
+ }
+ pBeaconGenParams = cdf_mem_malloc(sizeof(*pBeaconGenParams));
+ if (NULL == pBeaconGenParams) {
+ PELOGE(lim_log(pMac, LOGP,
+ FL
+ ("Unable to allocate memory during sending beaconPreMessage"));
+ )
+ return;
+ }
+ cdf_mem_set(pBeaconGenParams, sizeof(*pBeaconGenParams), 0);
+ cdf_mem_copy((void *)pBeaconGenParams->bssId,
+ (void *)psessionEntry->bssId, CDF_MAC_ADDR_SIZE);
+ limMsg.bodyptr = pBeaconGenParams;
+ sch_process_pre_beacon_ind(pMac, &limMsg);
+ return;
+}
+
+#ifdef FEATURE_WLAN_SCAN_PNO
+/**
+ * lim_send_sme_scan_cache_updated_ind()
+ *
+ ***FUNCTION:
+ * This function is used to post WMA_SME_SCAN_CACHE_UPDATED message to WMA.
+ * This message is the indication to WMA that all scan cache results
+ * are updated from LIM to SME. Mainly used only in PNO offload case.
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ * This function should be called after posting scan cache results to SME.
+ *
+ ***NOTE:
+ * NA
+ *
+ * @return None
+ */
+void lim_send_sme_scan_cache_updated_ind(uint8_t sessionId)
+{
+ cds_msg_t msg;
+
+ msg.type = WMA_SME_SCAN_CACHE_UPDATED;
+ msg.reserved = 0;
+ msg.bodyptr = NULL;
+ msg.bodyval = sessionId;
+
+ if (!CDF_IS_STATUS_SUCCESS
+ (cds_mq_post_message(CDF_MODULE_ID_WMA, &msg)))
+ CDF_TRACE(CDF_MODULE_ID_SME, CDF_TRACE_LEVEL_ERROR,
+ "%s: Not able to post WMA_SME_SCAN_CACHE_UPDATED message to WMA",
+ __func__);
+}
+#endif
+
+void lim_send_scan_offload_complete(tpAniSirGlobal pMac,
+ tSirScanOffloadEvent *pScanEvent)
+{
+
+ pMac->lim.gLimRspReqd = false;
+ lim_send_sme_scan_rsp(pMac, pScanEvent->reasonCode,
+ pScanEvent->sessionId, 0, pScanEvent->scanId);
+#ifdef FEATURE_WLAN_SCAN_PNO
+ lim_send_sme_scan_cache_updated_ind(pScanEvent->sessionId);
+#endif
+}
+
+void lim_process_rx_scan_event(tpAniSirGlobal pMac, void *buf)
+{
+ tSirScanOffloadEvent *pScanEvent = (tSirScanOffloadEvent *) buf;
+
+ CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_INFO,
+ "scan_id = %u", pScanEvent->scanId);
+ switch (pScanEvent->event) {
+ case SCAN_EVENT_STARTED:
+ break;
+ case SCAN_EVENT_START_FAILED:
+ case SCAN_EVENT_COMPLETED:
+ if (P2P_SCAN_TYPE_LISTEN == pScanEvent->p2pScanType) {
+ lim_send_sme_roc_rsp(pMac, eWNI_SME_REMAIN_ON_CHN_RSP,
+ CDF_STATUS_SUCCESS,
+ pScanEvent->sessionId,
+ pScanEvent->scanId);
+ cdf_mem_free(pMac->lim.gpLimRemainOnChanReq);
+ pMac->lim.gpLimRemainOnChanReq = NULL;
+ /*
+ * If remain on channel timer expired and action frame
+ * is pending then indicate confirmation with status
+ * failure.
+ */
+ if (pMac->lim.mgmtFrameSessionId != 0xff) {
+ lim_send_sme_rsp(pMac,
+ eWNI_SME_ACTION_FRAME_SEND_CNF,
+ eSIR_SME_SEND_ACTION_FAIL,
+ pMac->lim.mgmtFrameSessionId, 0);
+ pMac->lim.mgmtFrameSessionId = 0xff;
+ }
+ } else {
+ lim_send_scan_offload_complete(pMac, pScanEvent);
+ }
+ break;
+ case SCAN_EVENT_FOREIGN_CHANNEL:
+ if (P2P_SCAN_TYPE_LISTEN == pScanEvent->p2pScanType) {
+ /*Send Ready on channel indication to SME */
+ if (pMac->lim.gpLimRemainOnChanReq) {
+ lim_send_sme_roc_rsp(pMac,
+ eWNI_SME_REMAIN_ON_CHN_RDY_IND,
+ CDF_STATUS_SUCCESS,
+ pScanEvent->sessionId,
+ pScanEvent->scanId);
+ } else {
+ lim_log(pMac, LOGE,
+ FL("gpLimRemainOnChanReq is NULL"));
+ }
+ }
+ break;
+ case SCAN_EVENT_BSS_CHANNEL:
+ case SCAN_EVENT_DEQUEUED:
+ case SCAN_EVENT_PREEMPTED:
+ default:
+ CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_DEBUG,
+ "Received unhandled scan event %u",
+ pScanEvent->event);
+ }
+ cdf_mem_free(buf);
+}
diff --git a/core/mac/src/pe/lim/lim_process_probe_req_frame.c b/core/mac/src/pe/lim/lim_process_probe_req_frame.c
new file mode 100644
index 0000000..ccc8712
--- /dev/null
+++ b/core/mac/src/pe/lim/lim_process_probe_req_frame.c
@@ -0,0 +1,693 @@
+/*
+ * Copyright (c) 2012-2015 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_process_probe_req_frame.cc contains the code
+ * for processing Probe Request Frame.
+ * Author: Chandra Modumudi
+ * Date: 02/28/02
+ * History:-
+ * Date Modified by Modification Information
+ * --------------------------------------------------------------------
+ *
+ */
+
+#include "wni_cfg.h"
+#include "ani_global.h"
+#include "cfg_api.h"
+
+#include "utils_api.h"
+#include "lim_types.h"
+#include "lim_utils.h"
+#include "lim_assoc_utils.h"
+#include "lim_ser_des_utils.h"
+#include "parser_api.h"
+#ifdef WLAN_FEATURE_VOWIFI_11R
+#include "lim_ft_defs.h"
+#endif
+#include "lim_session.h"
+
+void
+
+lim_send_sme_probe_req_ind(tpAniSirGlobal pMac,
+ tSirMacAddr peerMacAddr,
+ uint8_t *pProbeReqIE,
+ uint32_t ProbeReqIELen, tpPESession psessionEntry);
+
+/**
+ * lim_get_wpspbc_sessions() - to get wps pbs sessions
+ * @mac_ctx: Pointer to Global MAC structure
+ * @addr: A pointer to probe request source MAC addresss
+ * @uuid_e: A pointer to UUIDE element of WPS IE in WPS PBC probe request
+ * @session: A pointer to station PE session
+ *
+ * This function is called to query the WPS PBC overlap. This function
+ * check WPS PBC probe request link list for PBC overlap
+ *
+ * @return None
+ */
+
+void lim_get_wpspbc_sessions(tpAniSirGlobal mac_ctx, uint8_t *addr,
+ uint8_t *uuid_e, eWPSPBCOverlap *overlap,
+ tpPESession session)
+{
+ int count = 0;
+ tSirWPSPBCSession *pbc;
+ uint32_t cur_time;
+
+ cur_time = (uint32_t) (cdf_mc_timer_get_system_ticks() /
+ CDF_TICKS_PER_SECOND);
+ cdf_mem_set((uint8_t *) addr, sizeof(tSirMacAddr), 0);
+ cdf_mem_set((uint8_t *) uuid_e, SIR_WPS_UUID_LEN, 0);
+ for (pbc = session->pAPWPSPBCSession; pbc; pbc = pbc->next) {
+ if (cur_time > pbc->timestamp + SIR_WPS_PBC_WALK_TIME)
+ break;
+ count++;
+ if (count > 1)
+ break;
+ cdf_mem_copy((uint8_t *) addr, (uint8_t *) pbc->addr,
+ sizeof(tSirMacAddr));
+ cdf_mem_copy((uint8_t *) uuid_e, (uint8_t *) pbc->uuid_e,
+ SIR_WPS_UUID_LEN);
+ }
+ if (count > 1)
+ /* Overlap */
+ *overlap = eSAP_WPSPBC_OVERLAP_IN120S;
+ else if (count == 0)
+ /* no WPS probe request in 120 second */
+ *overlap = eSAP_WPSPBC_NO_WPSPBC_PROBE_REQ_IN120S;
+ else
+ /* One WPS probe request in 120 second */
+ *overlap = eSAP_WPSPBC_ONE_WPSPBC_PROBE_REQ_IN120S;
+
+ lim_log(mac_ctx, LOGE, FL("overlap = %d"), *overlap);
+ sir_dump_buf(mac_ctx, SIR_LIM_MODULE_ID, LOGE, addr,
+ sizeof(tSirMacAddr));
+ sir_dump_buf(mac_ctx, SIR_LIM_MODULE_ID, LOGE, uuid_e,
+ SIR_WPS_UUID_LEN);
+ return;
+}
+
+/**
+ * lim_remove_timeout_pb_csessions
+ *
+ ***FUNCTION:
+ * This function is called to remove the WPS PBC probe request entires from specific entry to end.
+ *
+ ***LOGIC:
+ *
+ *
+ ***ASSUMPTIONS:
+ *
+ *
+ ***NOTE:
+ *
+ * @param pMac Pointer to Global MAC structure
+ * @param pbc The beginning entry in WPS PBC probe request link list
+ *
+ * @return None
+ */
+static void lim_remove_timeout_pb_csessions(tpAniSirGlobal pMac,
+ tSirWPSPBCSession *pbc)
+{
+ tSirWPSPBCSession *prev;
+
+ while (pbc) {
+ prev = pbc;
+ pbc = pbc->next;
+
+ PELOG4(lim_log(pMac, LOG4, FL("WPS PBC sessions remove"));)
+ PELOG4(sir_dump_buf
+ (pMac, SIR_LIM_MODULE_ID, LOG4, prev->addr,
+ sizeof(tSirMacAddr));
+ )
+ PELOG4(sir_dump_buf
+ (pMac, SIR_LIM_MODULE_ID, LOG4, prev->uuid_e,
+ SIR_WPS_UUID_LEN);
+ )
+
+ cdf_mem_free(prev);
+ }
+}
+
+void lim_remove_pbc_sessions(tpAniSirGlobal pMac, tSirMacAddr pRemoveMac,
+ tpPESession psessionEntry)
+{
+ tSirWPSPBCSession *pbc, *prev = NULL;
+ prev = pbc = psessionEntry->pAPWPSPBCSession;
+
+ while (pbc) {
+ if (cdf_mem_compare((uint8_t *) pbc->addr,
+ (uint8_t *) pRemoveMac,
+ sizeof(tSirMacAddr))) {
+ prev->next = pbc->next;
+ if (pbc == psessionEntry->pAPWPSPBCSession)
+ psessionEntry->pAPWPSPBCSession = pbc->next;
+ cdf_mem_free(pbc);
+ return;
+ }
+ prev = pbc;
+ pbc = pbc->next;
+ }
+
+}
+
+/**
+ * lim_update_pbc_session_entry
+ *
+ ***FUNCTION:
+ * This function is called when probe request with WPS PBC IE is received
+ *
+ ***LOGIC:
+ * This function add the WPS PBC probe request in the WPS PBC probe request link list
+ * The link list is in decreased time order of probe request that is received.
+ * The entry that is more than 120 second is removed.
+ *
+ ***ASSUMPTIONS:
+ *
+ *
+ ***NOTE:
+ *
+ * @param pMac Pointer to Global MAC structure
+ * @param addr A pointer to probe request source MAC addresss
+ * @param uuid_e A pointer to UUIDE element of WPS IE
+ * @param psessionEntry A pointer to station PE session
+ *
+ * @return None
+ */
+
+static void lim_update_pbc_session_entry(tpAniSirGlobal pMac,
+ uint8_t *addr, uint8_t *uuid_e,
+ tpPESession psessionEntry)
+{
+ tSirWPSPBCSession *pbc, *prev = NULL;
+
+ uint32_t curTime;
+
+ curTime =
+ (uint32_t) (cdf_mc_timer_get_system_ticks() /
+ CDF_TICKS_PER_SECOND);
+
+ PELOG4(lim_log
+ (pMac, LOG4, FL("Receive WPS probe reques curTime=%d"), curTime);
+ )
+ PELOG4(sir_dump_buf
+ (pMac, SIR_LIM_MODULE_ID, LOG4, addr, sizeof(tSirMacAddr));
+ )
+ PELOG4(sir_dump_buf
+ (pMac, SIR_LIM_MODULE_ID, LOG4, uuid_e, SIR_WPS_UUID_LEN);
+ )
+
+ pbc = psessionEntry->pAPWPSPBCSession;
+
+ while (pbc) {
+ if (cdf_mem_compare
+ ((uint8_t *) pbc->addr, (uint8_t *) addr,
+ sizeof(tSirMacAddr))
+ && cdf_mem_compare((uint8_t *) pbc->uuid_e,
+ (uint8_t *) uuid_e, SIR_WPS_UUID_LEN)) {
+ if (prev)
+ prev->next = pbc->next;
+ else
+ psessionEntry->pAPWPSPBCSession = pbc->next;
+ break;
+ }
+ prev = pbc;
+ pbc = pbc->next;
+ }
+
+ if (!pbc) {
+ pbc = cdf_mem_malloc(sizeof(tSirWPSPBCSession));
+ if (NULL == pbc) {
+ PELOGE(lim_log
+ (pMac, LOGE, FL("memory allocate failed!"));
+ )
+ return;
+ }
+ cdf_mem_copy((uint8_t *) pbc->addr, (uint8_t *) addr,
+ sizeof(tSirMacAddr));
+
+ if (uuid_e)
+ cdf_mem_copy((uint8_t *) pbc->uuid_e,
+ (uint8_t *) uuid_e, SIR_WPS_UUID_LEN);
+ }
+
+ pbc->next = psessionEntry->pAPWPSPBCSession;
+ psessionEntry->pAPWPSPBCSession = pbc;
+ pbc->timestamp = curTime;
+
+ /* remove entries that have timed out */
+ prev = pbc;
+ pbc = pbc->next;
+
+ while (pbc) {
+ if (curTime > pbc->timestamp + SIR_WPS_PBC_WALK_TIME) {
+ prev->next = NULL;
+ lim_remove_timeout_pb_csessions(pMac, pbc);
+ break;
+ }
+ prev = pbc;
+ pbc = pbc->next;
+ }
+}
+
+/**
+ * lim_wpspbc_close
+ *
+ ***FUNCTION:
+ * This function is called when BSS is closed
+ *
+ ***LOGIC:
+ * This function remove all the WPS PBC entries
+ *
+ ***ASSUMPTIONS:
+ *
+ *
+ ***NOTE:
+ *
+ * @param pMac Pointer to Global MAC structure
+ * @param psessionEntry A pointer to station PE session
+ *
+ * @return None
+ */
+
+void lim_wpspbc_close(tpAniSirGlobal pMac, tpPESession psessionEntry)
+{
+
+ lim_remove_timeout_pb_csessions(pMac, psessionEntry->pAPWPSPBCSession);
+
+}
+
+/**
+ * lim_check11b_rates
+ *
+ ***FUNCTION:
+ * This function is called by lim_process_probe_req_frame() upon
+ * Probe Request frame reception.
+ *
+ ***LOGIC:
+ * This function check 11b rates in supportedRates and extendedRates rates
+ *
+ ***NOTE:
+ *
+ * @param rate
+ *
+ * @return BOOLEAN
+ */
+
+bool lim_check11b_rates(uint8_t rate)
+{
+ if ((0x02 == (rate))
+ || (0x04 == (rate))
+ || (0x0b == (rate))
+ || (0x16 == (rate))
+ ) {
+ return true;
+ }
+ return false;
+}
+
+/**
+ * lim_process_probe_req_frame: to process probe req frame
+ * @mac_ctx: Pointer to Global MAC structure
+ * @rx_pkt_info: A pointer to Buffer descriptor + associated PDUs
+ * @session: a ponter to session entry
+ *
+ * This function is called by limProcessMessageQueue() upon
+ * Probe Request frame reception. This function processes received
+ * Probe Request frame and responds with Probe Response.
+ * Only AP or STA in IBSS mode that sent last Beacon will respond to
+ * Probe Request.
+ * ASSUMPTIONS:
+ * 1. AP or STA in IBSS mode that sent last Beacon will always respond
+ * to Probe Request received with broadcast SSID.
+ * NOTE:
+ * 1. Dunno what to do with Rates received in Probe Request frame
+ * 2. Frames with out-of-order fields/IEs are dropped.
+ *
+ *
+ * Return: none
+ */
+
+void
+lim_process_probe_req_frame(tpAniSirGlobal mac_ctx, uint8_t *rx_pkt_info,
+ tpPESession session)
+{
+ uint8_t *body_ptr;
+ tpSirMacMgmtHdr mac_hdr;
+ uint32_t frame_len;
+ tSirProbeReq probe_req;
+ tAniSSID ssid;
+
+ /* Don't send probe responses if disabled */
+ if (mac_ctx->lim.gLimProbeRespDisableFlag)
+ return;
+
+ /*
+ * Don't send probe response if P2P go is scanning till scan
+ * come to idle state.
+ */
+ if ((session->pePersona == CDF_P2P_GO_MODE) &&
+ ((mac_ctx->lim.gpLimRemainOnChanReq) ||
+ (mac_ctx->lim.gLimHalScanState != eLIM_HAL_IDLE_SCAN_STATE))) {
+ lim_log(mac_ctx, LOG3,
+ FL("GO is scanning, don't send probersp on diff chnl"));
+ return;
+ }
+ mac_hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info);
+ if (LIM_IS_AP_ROLE(session) ||
+ LIM_IS_BT_AMP_AP_ROLE(session) ||
+ LIM_IS_BT_AMP_STA_ROLE(session) ||
+ (LIM_IS_IBSS_ROLE(session) &&
+ (WMA_GET_RX_BEACON_SENT(rx_pkt_info)))) {
+ frame_len = WMA_GET_RX_PAYLOAD_LEN(rx_pkt_info);
+
+ lim_log(mac_ctx, LOG3,
+ FL("Received Probe Request %d bytes from "),
+ frame_len);
+ lim_print_mac_addr(mac_ctx, mac_hdr->sa, LOG3);
+ /* Get pointer to Probe Request frame body */
+ body_ptr = WMA_GET_RX_MPDU_DATA(rx_pkt_info);
+
+ /* Parse Probe Request frame */
+ if (sir_convert_probe_req_frame2_struct(mac_ctx, body_ptr,
+ frame_len, &probe_req) == eSIR_FAILURE) {
+ lim_log(mac_ctx, LOGE,
+ FL("Parse error ProbeReq, length=%d, SA is: "
+ MAC_ADDRESS_STR), frame_len,
+ MAC_ADDR_ARRAY(mac_hdr->sa));
+ mac_ctx->sys.probeError++;
+ return;
+ }
+ if (session->pePersona == CDF_P2P_GO_MODE) {
+ uint8_t i = 0, rate_11b = 0, other_rates = 0;
+ /* Check 11b rates in supported rates */
+ for (i = 0; i < probe_req.supportedRates.numRates;
+ i++) {
+ if (lim_check11b_rates(
+ probe_req.supportedRates.rate[i] &
+ 0x7f))
+ rate_11b++;
+ else
+ other_rates++;
+ }
+
+ /* Check 11b rates in extended rates */
+ for (i = 0; i < probe_req.extendedRates.numRates; i++) {
+ if (lim_check11b_rates(
+ probe_req.extendedRates.rate[i] & 0x7f))
+ rate_11b++;
+ else
+ other_rates++;
+ }
+
+ if ((rate_11b > 0) && (other_rates == 0)) {
+ lim_log(mac_ctx, LOG3,
+ FL("Received a probe req frame with only 11b rates, SA is: "));
+ lim_print_mac_addr(mac_ctx,
+ mac_hdr->sa, LOG3);
+ return;
+ }
+ }
+ if (LIM_IS_AP_ROLE(session) &&
+ ((session->APWPSIEs.SirWPSProbeRspIE.FieldPresent
+ & SIR_WPS_PROBRSP_VER_PRESENT)
+ && (probe_req.wscIePresent == 1)
+ && (probe_req.probeReqWscIeInfo.DevicePasswordID.id ==
+ WSC_PASSWD_ID_PUSH_BUTTON)
+ && (probe_req.probeReqWscIeInfo.UUID_E.present == 1))) {
+ if (session->fwdWPSPBCProbeReq) {
+ sir_dump_buf(mac_ctx, SIR_LIM_MODULE_ID,
+ LOG4, mac_hdr->sa, sizeof(tSirMacAddr));
+ sir_dump_buf(mac_ctx, SIR_LIM_MODULE_ID,
+ LOG4, body_ptr, frame_len);
+ lim_send_sme_probe_req_ind(mac_ctx, mac_hdr->sa,
+ body_ptr, frame_len, session);
+ } else {
+ lim_update_pbc_session_entry(mac_ctx,
+ mac_hdr->sa,
+ probe_req.probeReqWscIeInfo.UUID_E.uuid,
+ session);
+ }
+ }
+ ssid.length = session->ssId.length;
+ /* Copy the SSID from sessio entry to local variable */
+ cdf_mem_copy(ssid.ssId, session->ssId.ssId,
+ session->ssId.length);
+
+ /*
+ * Compare received SSID with current SSID. If they match,
+ * reply with Probe Response
+ */
+ if (probe_req.ssId.length) {
+ if (!ssid.length)
+ goto multipleSSIDcheck;
+
+ if (cdf_mem_compare((uint8_t *) &ssid,
+ (uint8_t *) &(probe_req.ssId),
+ (uint8_t) (ssid.length + 1))) {
+ lim_send_probe_rsp_mgmt_frame(mac_ctx,
+ mac_hdr->sa, &ssid,
+ DPH_USE_MGMT_STAID,
+ DPH_NON_KEEPALIVE_FRAME,
+ session,
+ probe_req.p2pIePresent);
+ return;
+ } else if (session->pePersona ==
+ CDF_P2P_GO_MODE) {
+ uint8_t direct_ssid[7] = "DIRECT-";
+ uint8_t direct_ssid_len = 7;
+ if (cdf_mem_compare((uint8_t *) &direct_ssid,
+ (uint8_t *) &(probe_req.ssId.ssId),
+ (uint8_t) (direct_ssid_len))) {
+ lim_send_probe_rsp_mgmt_frame(mac_ctx,
+ mac_hdr->sa,
+ &ssid,
+ DPH_USE_MGMT_STAID,
+ DPH_NON_KEEPALIVE_FRAME,
+ session,
+ probe_req.p2pIePresent);
+ return;
+ }
+ } else {
+ lim_log(mac_ctx, LOG3,
+ FL("Ignore ProbeReq frm with unmatch SSID received from "));
+ lim_print_mac_addr(mac_ctx, mac_hdr->sa,
+ LOG3);
+ mac_ctx->sys.probeBadSsid++;
+ }
+ } else {
+ /*
+ * Broadcast SSID in the Probe Request.
+ * Reply with SSID we're configured with.
+ * Turn off the SSID length to 0 if hidden SSID feature
+ * is present
+ */
+ if (session->ssidHidden)
+ /*
+ * We are returning from here as probe request
+ * contains the broadcast SSID. So no need to
+ * send the probe resp
+ */
+ return;
+ lim_send_probe_rsp_mgmt_frame(mac_ctx, mac_hdr->sa,
+ &ssid,
+ DPH_USE_MGMT_STAID,
+ DPH_NON_KEEPALIVE_FRAME,
+ session,
+ probe_req.p2pIePresent);
+ return;
+ }
+multipleSSIDcheck:
+ lim_log(mac_ctx, LOG3,
+ FL("Ignore ProbeReq frm with unmatch SSID rcved from"));
+ lim_print_mac_addr(mac_ctx, mac_hdr->sa, LOG3);
+ mac_ctx->sys.probeBadSsid++;
+ } else {
+ /* Ignore received Probe Request frame */
+ lim_log(mac_ctx, LOG3,
+ FL("Ignoring Probe Request frame received from "));
+ lim_print_mac_addr(mac_ctx, mac_hdr->sa, LOG3);
+ mac_ctx->sys.probeIgnore++;
+ }
+ return;
+}
+
+/**
+ * lim_indicate_probe_req_to_hdd
+ *
+ ***FUNCTION:
+ * This function is called by lim_process_probe_req_frame_multiple_bss() upon
+ * Probe Request frame reception.
+ *
+ ***LOGIC:
+ * This function processes received Probe Request frame and Pass
+ * Probe Request Frame to HDD.
+ *
+ * @param pMac Pointer to Global MAC structure
+ * @param *pBd A pointer to Buffer descriptor + associated PDUs
+ * @param psessionEntry A pointer to PE session
+ *
+ * @return None
+ */
+
+static void
+lim_indicate_probe_req_to_hdd(tpAniSirGlobal pMac, uint8_t *pBd,
+ tpPESession psessionEntry)
+{
+ tpSirMacMgmtHdr pHdr;
+ uint32_t frameLen;
+
+ lim_log(pMac, LOG1, "Received a probe request frame");
+
+ pHdr = WMA_GET_RX_MAC_HEADER(pBd);
+ frameLen = WMA_GET_RX_PAYLOAD_LEN(pBd);
+
+ /* send the probe req to SME. */
+ lim_send_sme_mgmt_frame_ind(pMac, pHdr->fc.subType,
+ (uint8_t *) pHdr,
+ (frameLen + sizeof(tSirMacMgmtHdr)),
+ psessionEntry->smeSessionId, WMA_GET_RX_CH(pBd),
+ psessionEntry, 0);
+} /*** end lim_indicate_probe_req_to_hdd() ***/
+
+/**
+ * lim_process_probe_req_frame_multiple_bss() - to process probe req
+ * @mac_ctx: Pointer to Global MAC structure
+ * @buf_descr: A pointer to Buffer descriptor + associated PDUs
+ * @session: A pointer to PE session
+ *
+ * This function is called by limProcessMessageQueue() upon
+ * Probe Request frame reception. This function call
+ * lim_indicate_probe_req_to_hdd function to indicate
+ * Probe Request frame to HDD. It also call lim_process_probe_req_frame
+ * function which process received Probe Request frame and responds
+ * with Probe Response.
+ *
+ * @return None
+ */
+void
+lim_process_probe_req_frame_multiple_bss(tpAniSirGlobal mac_ctx,
+ uint8_t *buf_descr, tpPESession session)
+{
+ uint8_t i;
+
+ if (session != NULL) {
+ if (LIM_IS_AP_ROLE(session)) {
+ lim_indicate_probe_req_to_hdd(mac_ctx,
+ buf_descr, session);
+ }
+ lim_process_probe_req_frame(mac_ctx, buf_descr, session);
+ return;
+ }
+
+ for (i = 0; i < mac_ctx->lim.maxBssId; i++) {
+ session = pe_find_session_by_session_id(mac_ctx, i);
+ if (session == NULL)
+ continue;
+ if (LIM_IS_AP_ROLE(session))
+ lim_indicate_probe_req_to_hdd(mac_ctx,
+ buf_descr, session);
+ if (LIM_IS_AP_ROLE(session) ||
+ LIM_IS_IBSS_ROLE(session) ||
+ LIM_IS_BT_AMP_AP_ROLE(session) ||
+ LIM_IS_BT_AMP_STA_ROLE(session))
+ lim_process_probe_req_frame(mac_ctx,
+ buf_descr, session);
+ }
+}
+
+/**
+ * lim_send_sme_probe_req_ind()
+ *
+ ***FUNCTION:
+ * This function is to send
+ * eWNI_SME_WPS_PBC_PROBE_REQ_IND message to host
+ *
+ ***PARAMS:
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ * NA
+ *
+ ***NOTE:
+ * This function is used for sending eWNI_SME_WPS_PBC_PROBE_REQ_IND
+ * to host.
+ *
+ * @param peerMacAddr Indicates the peer MAC addr that the probe request
+ * is generated.
+ * @param pProbeReqIE pointer to RAW probe request IE
+ * @param ProbeReqIELen The length of probe request IE.
+ * @param psessionEntry A pointer to PE session
+ *
+ * @return None
+ */
+void
+lim_send_sme_probe_req_ind(tpAniSirGlobal pMac,
+ tSirMacAddr peerMacAddr,
+ uint8_t *pProbeReqIE,
+ uint32_t ProbeReqIELen, tpPESession psessionEntry)
+{
+ tSirSmeProbeReqInd *pSirSmeProbeReqInd;
+ tSirMsgQ msgQ;
+
+ pSirSmeProbeReqInd = cdf_mem_malloc(sizeof(tSirSmeProbeReqInd));
+ if (NULL == pSirSmeProbeReqInd) {
+ /* Log error */
+ lim_log(pMac, LOGP,
+ FL
+ ("call to AllocateMemory failed for eWNI_SME_PROBE_REQ_IND"));
+ return;
+ }
+
+ msgQ.type = eWNI_SME_WPS_PBC_PROBE_REQ_IND;
+ msgQ.bodyval = 0;
+ msgQ.bodyptr = pSirSmeProbeReqInd;
+
+ pSirSmeProbeReqInd->messageType = eWNI_SME_WPS_PBC_PROBE_REQ_IND;
+ pSirSmeProbeReqInd->length = sizeof(tSirSmeProbeReq);
+ pSirSmeProbeReqInd->sessionId = psessionEntry->smeSessionId;
+
+ cdf_mem_copy(pSirSmeProbeReqInd->bssId, psessionEntry->bssId,
+ sizeof(tSirMacAddr));
+ cdf_mem_copy(pSirSmeProbeReqInd->WPSPBCProbeReq.peerMacAddr,
+ peerMacAddr, sizeof(tSirMacAddr));
+
+ MTRACE(mac_trace_msg_tx(pMac, psessionEntry->peSessionId, msgQ.type));
+ pSirSmeProbeReqInd->WPSPBCProbeReq.probeReqIELen =
+ (uint16_t) ProbeReqIELen;
+ cdf_mem_copy(pSirSmeProbeReqInd->WPSPBCProbeReq.probeReqIE, pProbeReqIE,
+ ProbeReqIELen);
+
+ if (lim_sys_process_mmh_msg_api(pMac, &msgQ, ePROT) != eSIR_SUCCESS) {
+ PELOGE(lim_log
+ (pMac, LOGE, FL("couldnt send the probe req to hdd"));
+ )
+ }
+
+} /*** end lim_send_sme_probe_req_ind() ***/
diff --git a/core/mac/src/pe/lim/lim_process_probe_rsp_frame.c b/core/mac/src/pe/lim/lim_process_probe_rsp_frame.c
new file mode 100644
index 0000000..d3df1d3
--- /dev/null
+++ b/core/mac/src/pe/lim/lim_process_probe_rsp_frame.c
@@ -0,0 +1,362 @@
+/*
+ * Copyright (c) 2011-2015 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_process_probe_rsp_frame.cc contains the code
+ * for processing Probe Response Frame.
+ * Author: Chandra Modumudi
+ * Date: 03/01/02
+ * History:-
+ * Date Modified by Modification Information
+ * --------------------------------------------------------------------
+ *
+ */
+
+#include "wni_api.h"
+#include "wni_cfg.h"
+#include "ani_global.h"
+#include "sch_api.h"
+#include "utils_api.h"
+#include "lim_api.h"
+#include "lim_types.h"
+#include "lim_utils.h"
+#include "lim_assoc_utils.h"
+#include "lim_prop_exts_utils.h"
+#include "lim_ser_des_utils.h"
+#include "lim_send_messages.h"
+
+#include "parser_api.h"
+
+tSirRetStatus lim_validate_ie_information_in_probe_rsp_frame(uint8_t *pRxPacketInfo)
+{
+ tSirRetStatus status = eSIR_SUCCESS;
+
+ if (WMA_GET_RX_PAYLOAD_LEN(pRxPacketInfo) <
+ (SIR_MAC_B_PR_SSID_OFFSET + SIR_MAC_MIN_IE_LEN)) {
+ status = eSIR_FAILURE;
+ }
+
+ return status;
+}
+
+/**
+ * lim_process_probe_rsp_frame() - processes received Probe Response frame
+ * @mac_ctx: Pointer to Global MAC structure
+ * @rx_Packet_info: A pointer to Buffer descriptor + associated PDUs
+ * @session_entry: Handle to the session.
+ *
+ * This function processes received Probe Response frame.
+ * Frames with out-of-order IEs are dropped.
+ * In case of IBSS, join 'success' makes MLM state machine
+ * transition into 'BSS started' state. This may have to change
+ * depending on supporting what kinda Authentication in IBSS.
+ *
+ * Return: None
+ */
+void
+lim_process_probe_rsp_frame(tpAniSirGlobal mac_ctx, uint8_t *rx_Packet_info,
+ tpPESession session_entry)
+{
+ uint8_t *body;
+ uint32_t frame_len = 0;
+ tSirMacAddr current_bssid;
+ tpSirMacMgmtHdr header;
+ tSirProbeRespBeacon *probe_rsp;
+ uint8_t qos_enabled = false;
+ uint8_t wme_enabled = false;
+
+ if (!session_entry) {
+ lim_log(mac_ctx, LOGE, FL("session_entry is NULL"));
+ return;
+ }
+ lim_log(mac_ctx, LOG1, "SessionId:%d ProbeRsp Frame is received",
+ session_entry->peSessionId);
+
+ probe_rsp = cdf_mem_malloc(sizeof(tSirProbeRespBeacon));
+ if (NULL == probe_rsp) {
+ lim_log(mac_ctx, LOGE,
+ FL
+ ("Unable to allocate memory "));
+ return;
+ }
+
+ probe_rsp->ssId.length = 0;
+ probe_rsp->wpa.length = 0;
+
+ header = WMA_GET_RX_MAC_HEADER(rx_Packet_info);
+
+ lim_log(mac_ctx, LOG2,
+ FL("Rx Probe Response with length = %d from "MAC_ADDRESS_STR),
+ WMA_GET_RX_MPDU_LEN(rx_Packet_info),
+ MAC_ADDR_ARRAY(header->sa));
+
+ /* Validate IE information before processing Probe Response Frame */
+ if (lim_validate_ie_information_in_probe_rsp_frame(rx_Packet_info) !=
+ eSIR_SUCCESS) {
+ lim_log(mac_ctx, LOG1,
+ FL("Parse error ProbeResponse, length=%d"), frame_len);
+ cdf_mem_free(probe_rsp);
+ return;
+ }
+
+ frame_len = WMA_GET_RX_PAYLOAD_LEN(rx_Packet_info);
+ CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_INFO,
+ FL("Probe Resp Frame Received: BSSID "
+ MAC_ADDRESS_STR " (RSSI %d)"),
+ MAC_ADDR_ARRAY(header->bssId),
+ (uint) abs((int8_t)WMA_GET_RX_RSSI_DB(rx_Packet_info)));
+ /* Get pointer to Probe Response frame body */
+ body = WMA_GET_RX_MPDU_DATA(rx_Packet_info);
+ /* Enforce Mandatory IEs */
+ if ((sir_convert_probe_frame2_struct(mac_ctx,
+ body, frame_len, probe_rsp) == eSIR_FAILURE) ||
+ !probe_rsp->ssidPresent) {
+ lim_log(mac_ctx, LOG1,
+ FL("Parse error ProbeResponse, length=%d"), frame_len);
+ cdf_mem_free(probe_rsp);
+ return;
+ }
+ lim_check_and_add_bss_description(mac_ctx, probe_rsp,
+ rx_Packet_info, false, true);
+ /* To Support BT-AMP */
+ if ((mac_ctx->lim.gLimMlmState ==
+ eLIM_MLM_WT_PROBE_RESP_STATE) ||
+ (mac_ctx->lim.gLimMlmState ==
+ eLIM_MLM_PASSIVE_SCAN_STATE)) {
+ lim_check_and_add_bss_description(mac_ctx, probe_rsp,
+ rx_Packet_info, ((mac_ctx->lim.
+ gLimHalScanState == eLIM_HAL_SCANNING_STATE)
+ ? true : false), true);
+ } else if (session_entry->limMlmState ==
+ eLIM_MLM_WT_JOIN_BEACON_STATE) {
+ /*
+ * Either Beacon/probe response is required.
+ * Hence store it in same buffer.
+ */
+ if (session_entry->beacon != NULL) {
+ cdf_mem_free(session_entry->beacon);
+ session_entry->beacon = NULL;
+ }
+ session_entry->bcnLen =
+ WMA_GET_RX_PAYLOAD_LEN(rx_Packet_info);
+ session_entry->beacon =
+ cdf_mem_malloc(session_entry->bcnLen);
+ if (NULL == session_entry->beacon) {
+ lim_log(mac_ctx, LOGE,
+ FL("No Memory to store beacon"));
+ } else {
+ /*
+ * Store the Beacon/ProbeRsp.
+ * This is sent to csr/hdd in join cnf response.
+ */
+ cdf_mem_copy(session_entry->beacon,
+ WMA_GET_RX_MPDU_DATA
+ (rx_Packet_info),
+ session_entry->bcnLen);
+ }
+ /* STA in WT_JOIN_BEACON_STATE */
+ lim_check_and_announce_join_success(mac_ctx, probe_rsp,
+ header,
+ session_entry);
+ } else if (session_entry->limMlmState ==
+ eLIM_MLM_LINK_ESTABLISHED_STATE) {
+ tpDphHashNode sta_ds = NULL;
+ /*
+ * Check if this Probe Response is for
+ * our Probe Request sent upon reaching
+ * heart beat threshold
+ */
+ sir_copy_mac_addr(current_bssid, session_entry->bssId);
+ if (!cdf_mem_compare(current_bssid, header->bssId,
+ sizeof(tSirMacAddr))) {
+ cdf_mem_free(probe_rsp);
+ return;
+ }
+ if (!LIM_IS_CONNECTION_ACTIVE(session_entry)) {
+ lim_log(mac_ctx, LOGW,
+ FL("Recved Probe Resp from AP,AP-alive"));
+ if (probe_rsp->HTInfo.present)
+ lim_received_hb_handler(mac_ctx,
+ probe_rsp->HTInfo.primaryChannel,
+ session_entry);
+ else
+ lim_received_hb_handler(mac_ctx,
+ (uint8_t)probe_rsp->channelNumber,
+ session_entry);
+ }
+ if (LIM_IS_STA_ROLE(session_entry)) {
+ if (probe_rsp->channelSwitchPresent) {
+ lim_update_channel_switch(mac_ctx,
+ probe_rsp,
+ session_entry);
+ } else if (session_entry->gLimSpecMgmt.dot11hChanSwState
+ == eLIM_11H_CHANSW_RUNNING) {
+ lim_cancel_dot11h_channel_switch(
+ mac_ctx, session_entry);
+ }
+ }
+ /*
+ * Now Process EDCA Parameters, if EDCAParamSet
+ * count is different.
+ * -- While processing beacons in link established
+ * state if it is determined that
+ * QoS Info IE has a different count for EDCA Params,
+ * and EDCA IE is not present in beacon,
+ * then probe req is sent out to get the EDCA params.
+ */
+ sta_ds = dph_get_hash_entry(mac_ctx,
+ DPH_STA_HASH_INDEX_PEER,
+ &session_entry->dph.dphHashTable);
+ limGetQosMode(session_entry, &qos_enabled);
+ limGetWmeMode(session_entry, &wme_enabled);
+ lim_log(mac_ctx, LOG2,
+ FL("wmeEdcaPresent: %d wme_enabled: %d"),
+ probe_rsp->wmeEdcaPresent, wme_enabled);
+ lim_log(mac_ctx, LOG2,
+ FL("edcaPresent: %d, qos_enabled: %d"),
+ probe_rsp->edcaPresent, qos_enabled);
+ lim_log(mac_ctx, LOG2,
+ FL("edcaParams.qosInfo.count: %d"),
+ probe_rsp->edcaParams.qosInfo.count);
+ lim_log(mac_ctx, LOG2,
+ FL("schObject.gLimEdcaParamSetCount: %d"),
+ session_entry->gLimEdcaParamSetCount);
+ if (((probe_rsp->wmeEdcaPresent && wme_enabled) ||
+ (probe_rsp->edcaPresent && qos_enabled)) &&
+ (probe_rsp->edcaParams.qosInfo.count !=
+ session_entry->gLimEdcaParamSetCount)) {
+ if (sch_beacon_edca_process(mac_ctx,
+ &probe_rsp->edcaParams,
+ session_entry) != eSIR_SUCCESS) {
+ lim_log(mac_ctx, LOGE,
+ FL("EDCA param process error"));
+ } else if (sta_ds != NULL) {
+ /*
+ * If needed, downgrade the
+ * EDCA parameters
+ */
+ lim_set_active_edca_params(mac_ctx,
+ session_entry->
+ gLimEdcaParams,
+ session_entry);
+ lim_send_edca_params(mac_ctx,
+ session_entry->
+ gLimEdcaParamsActive,
+ sta_ds->bssId);
+ } else {
+ lim_log(mac_ctx, LOGE,
+ FL("SelfEntry missing in Hash"));
+ }
+ }
+ if (session_entry->fWaitForProbeRsp == true) {
+ lim_log(mac_ctx, LOGW,
+ FL("Check probe resp for caps change"));
+ lim_detect_change_in_ap_capabilities(
+ mac_ctx, probe_rsp, session_entry);
+ }
+ } else {
+ if (LIM_IS_IBSS_ROLE(session_entry) &&
+ (session_entry->limMlmState ==
+ eLIM_MLM_BSS_STARTED_STATE))
+ lim_handle_ibss_coalescing(mac_ctx, probe_rsp,
+ rx_Packet_info, session_entry);
+ }
+ cdf_mem_free(probe_rsp);
+
+ /* Ignore Probe Response frame in all other states */
+ return;
+}
+
+/**
+ * lim_process_probe_rsp_frame_no_session() - process Probe Response frame
+ * @mac_ctx: Pointer to Global MAC structure
+ * @rx_packet_info: A pointer to Buffer descriptor + associated PDUs
+ *
+ * This function processes received Probe Response frame with no session.
+ *
+ * Return: None
+ */
+void
+lim_process_probe_rsp_frame_no_session(tpAniSirGlobal mac_ctx,
+ uint8_t *rx_packet_info)
+{
+ uint8_t *body;
+ uint32_t frame_len = 0;
+ tpSirMacMgmtHdr header;
+ tSirProbeRespBeacon *probe_rsp;
+
+ probe_rsp = cdf_mem_malloc(sizeof(tSirProbeRespBeacon));
+ if (NULL == probe_rsp) {
+ lim_log(mac_ctx, LOGE,
+ FL("Unable to allocate memory"));
+ return;
+ }
+
+ probe_rsp->ssId.length = 0;
+ probe_rsp->wpa.length = 0;
+
+ header = WMA_GET_RX_MAC_HEADER(rx_packet_info);
+
+ lim_log(mac_ctx, LOG2,
+ FL("Received Probe Response frame with length=%d from "),
+ WMA_GET_RX_MPDU_LEN(rx_packet_info));
+ lim_print_mac_addr(mac_ctx, header->sa, LOG2);
+
+ /* Validate IE information before processing Probe Response Frame */
+ if (lim_validate_ie_information_in_probe_rsp_frame(rx_packet_info) !=
+ eSIR_SUCCESS) {
+ lim_log(mac_ctx, LOG1,
+ FL("Parse error ProbeResponse, length=%d"), frame_len);
+ cdf_mem_free(probe_rsp);
+ return;
+ }
+
+ frame_len = WMA_GET_RX_PAYLOAD_LEN(rx_packet_info);
+ CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_INFO,
+ FL("Probe Resp Frame Received: BSSID "
+ MAC_ADDRESS_STR " (RSSI %d)"),
+ MAC_ADDR_ARRAY(header->bssId),
+ (uint) abs((int8_t)WMA_GET_RX_RSSI_DB(rx_packet_info)));
+ /*
+ * Get pointer to Probe Response frame body
+ */
+ body = WMA_GET_RX_MPDU_DATA(rx_packet_info);
+ if (sir_convert_probe_frame2_struct(mac_ctx, body, frame_len,
+ probe_rsp) == eSIR_FAILURE) {
+ lim_log(mac_ctx, LOG1,
+ FL("Parse error ProbeResponse, length=%d\n"),
+ frame_len);
+ cdf_mem_free(probe_rsp);
+ return;
+ }
+ lim_log(mac_ctx, LOG2, FL("Save this probe rsp in LFR cache"));
+ lim_check_and_add_bss_description(mac_ctx, probe_rsp,
+ rx_packet_info, false, true);
+ cdf_mem_free(probe_rsp);
+ return;
+}
diff --git a/core/mac/src/pe/lim/lim_process_sme_req_messages.c b/core/mac/src/pe/lim/lim_process_sme_req_messages.c
new file mode 100644
index 0000000..0db6d07
--- /dev/null
+++ b/core/mac/src/pe/lim/lim_process_sme_req_messages.c
@@ -0,0 +1,5690 @@
+/*
+ * Copyright (c) 2012-2015 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_process_sme_req_messages.cc contains the code
+ * for processing SME request messages.
+ * Author: Chandra Modumudi
+ * Date: 02/11/02
+ * History:-
+ * Date Modified by Modification Information
+ * --------------------------------------------------------------------
+ *
+ */
+
+#include "cds_api.h"
+#include "wni_api.h"
+#include "wni_cfg.h"
+#include "cfg_api.h"
+#include "sir_api.h"
+#include "sch_api.h"
+#include "utils_api.h"
+#include "lim_types.h"
+#include "lim_utils.h"
+#include "lim_assoc_utils.h"
+#include "lim_security_utils.h"
+#include "lim_ser_des_utils.h"
+#include "lim_sme_req_utils.h"
+#include "lim_ibss_peer_mgmt.h"
+#include "lim_admit_control.h"
+#include "dph_hash_table.h"
+#include "lim_send_messages.h"
+#include "lim_api.h"
+#include "wmm_apsd.h"
+#include "sir_mac_prot_def.h"
+
+#include "sap_api.h"
+
+#if defined WLAN_FEATURE_VOWIFI
+#include "rrm_api.h"
+#endif
+
+#if defined WLAN_FEATURE_VOWIFI_11R
+#include <lim_ft.h>
+#endif
+
+/*
+ * This overhead is time for sending NOA start to host in case of GO/sending
+ * NULL data & receiving ACK in case of P2P Client and starting actual scanning
+ * with init scan req/rsp plus in case of concurrency, taking care of sending
+ * null data and receiving ACK to/from AP/Also SetChannel with calibration
+ * is taking around 7ms .
+ */
+#define SCAN_MESSAGING_OVERHEAD 20 /* in msecs */
+#define JOIN_NOA_DURATION 2000 /* in msecs */
+#define OEM_DATA_NOA_DURATION 60 /* in msecs */
+#define DEFAULT_PASSIVE_MAX_CHANNEL_TIME 110 /* in msecs */
+
+#define CONV_MS_TO_US 1024 /* conversion factor from ms to us */
+
+/* SME REQ processing function templates */
+static bool __lim_process_sme_sys_ready_ind(tpAniSirGlobal, uint32_t *);
+static bool __lim_process_sme_start_bss_req(tpAniSirGlobal, tpSirMsgQ pMsg);
+static void __lim_process_sme_scan_req(tpAniSirGlobal, uint32_t *);
+static void __lim_process_sme_join_req(tpAniSirGlobal, uint32_t *);
+static void __lim_process_sme_reassoc_req(tpAniSirGlobal, uint32_t *);
+static void __lim_process_sme_disassoc_req(tpAniSirGlobal, uint32_t *);
+static void __lim_process_sme_disassoc_cnf(tpAniSirGlobal, uint32_t *);
+static void __lim_process_sme_deauth_req(tpAniSirGlobal, uint32_t *);
+static void __lim_process_sme_set_context_req(tpAniSirGlobal, uint32_t *);
+static bool __lim_process_sme_stop_bss_req(tpAniSirGlobal, tpSirMsgQ pMsg);
+static void lim_process_sme_channel_change_request(tpAniSirGlobal pMac,
+ uint32_t *pMsg);
+static void lim_process_sme_start_beacon_req(tpAniSirGlobal pMac, uint32_t *pMsg);
+static void lim_process_sme_dfs_csa_ie_request(tpAniSirGlobal pMac, uint32_t *pMsg);
+static void lim_process_nss_update_request(tpAniSirGlobal pMac, uint32_t *pMsg);
+static void lim_process_set_ie_req(tpAniSirGlobal pMac, uint32_t *pMsg);
+
+static void lim_start_bss_update_add_ie_buffer(tpAniSirGlobal pMac,
+ uint8_t **pDstData_buff,
+ uint16_t *pDstDataLen,
+ uint8_t *pSrcData_buff,
+ uint16_t srcDataLen);
+
+static void lim_update_add_ie_buffer(tpAniSirGlobal pMac,
+ uint8_t **pDstData_buff,
+ uint16_t *pDstDataLen,
+ uint8_t *pSrcData_buff, uint16_t srcDataLen);
+
+static void lim_process_modify_add_ies(tpAniSirGlobal pMac, uint32_t *pMsg);
+
+static void lim_process_update_add_ies(tpAniSirGlobal pMac, uint32_t *pMsg);
+
+extern void pe_register_wma_handle(tpAniSirGlobal pMac);
+
+/**
+ * lim_process_set_hw_mode() - Send set HW mode command to WMA
+ * @mac: Globacl MAC pointer
+ * @msg: Message containing the hw mode index
+ *
+ * Send the set HW mode command to WMA
+ *
+ * Return: CDF_STATUS_SUCCESS if message posting is successful
+ */
+static CDF_STATUS lim_process_set_hw_mode(tpAniSirGlobal mac, uint32_t *msg)
+{
+ CDF_STATUS status = CDF_STATUS_SUCCESS;
+ cds_msg_t cds_message;
+ struct sir_hw_mode *req_msg;
+ uint32_t len;
+ struct s_sir_set_hw_mode *buf;
+ tSirMsgQ resp_msg;
+ struct sir_set_hw_mode_resp *param;
+
+ buf = (struct s_sir_set_hw_mode *) msg;
+ if (!buf) {
+ lim_log(mac, LOGE, FL("Set HW mode param is NULL"));
+ /* To free the active command list */
+ goto fail;
+ }
+
+ len = sizeof(*req_msg);
+
+ req_msg = cdf_mem_malloc(len);
+ if (!req_msg) {
+ lim_log(mac, LOGE, FL("cdf_mem_malloc failed"));
+ /* Free the active command list
+ * Probably the malloc is going to fail there as well?!
+ */
+ return CDF_STATUS_E_NOMEM;
+ }
+
+ cdf_mem_zero(req_msg, len);
+
+ req_msg->hw_mode_index = buf->set_hw.hw_mode_index;
+ /* Other parameters are not needed for WMA */
+
+ cds_message.bodyptr = req_msg;
+ cds_message.type = SIR_HAL_SOC_SET_HW_MODE;
+
+ lim_log(mac, LOG1, FL("Posting SIR_HAL_SOC_SET_HW_MOD to WMA"));
+ status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_message);
+ if (!CDF_IS_STATUS_SUCCESS(status)) {
+ lim_log(mac, LOGE,
+ FL("vos_mq_post_message failed!(err=%d)"),
+ status);
+ cdf_mem_free(req_msg);
+ goto fail;
+ }
+ return status;
+fail:
+ param = cdf_mem_malloc(sizeof(*param));
+ if (!param) {
+ lim_log(mac, LOGE, FL("HW mode resp failed"));
+ return CDF_STATUS_E_FAILURE;
+ }
+ param->status = SET_HW_MODE_STATUS_ECANCELED;
+ param->cfgd_hw_mode_index = 0;
+ param->num_vdev_mac_entries = 0;
+ resp_msg.type = eWNI_SME_SET_HW_MODE_RESP;
+ resp_msg.bodyptr = param;
+ resp_msg.bodyval = 0;
+ lim_sys_process_mmh_msg_api(mac, &resp_msg, ePROT);
+ return CDF_STATUS_SUCCESS;
+}
+
+/**
+ * lim_process_set_dual_mac_cfg_req() - Set dual mac config command to WMA
+ * @mac: Global MAC pointer
+ * @msg: Message containing the dual mac config parameter
+ *
+ * Send the set dual mac config command to WMA
+ *
+ * Return: CDF_STATUS_SUCCESS if message posting is successful
+ */
+static CDF_STATUS lim_process_set_dual_mac_cfg_req(tpAniSirGlobal mac,
+ uint32_t *msg)
+{
+ CDF_STATUS status = CDF_STATUS_SUCCESS;
+ cds_msg_t cds_message;
+ struct sir_dual_mac_config *req_msg;
+ uint32_t len;
+ struct sir_set_dual_mac_cfg *buf;
+ tSirMsgQ resp_msg;
+ struct sir_dual_mac_config_resp *param;
+
+ buf = (struct sir_set_dual_mac_cfg *) msg;
+ if (!buf) {
+ lim_log(mac, LOGE, FL("Set Dual mac config is NULL"));
+ /* To free the active command list */
+ goto fail;
+ }
+
+ len = sizeof(*req_msg);
+
+ req_msg = cdf_mem_malloc(len);
+ if (!req_msg) {
+ lim_log(mac, LOGE, FL("vos_mem_malloc failed"));
+ /* Free the active command list
+ * Probably the malloc is going to fail there as well?!
+ */
+ return CDF_STATUS_E_NOMEM;
+ }
+
+ cdf_mem_zero(req_msg, len);
+
+ req_msg->scan_config = buf->set_dual_mac.scan_config;
+ req_msg->fw_mode_config = buf->set_dual_mac.fw_mode_config;
+ /* Other parameters are not needed for WMA */
+
+ cds_message.bodyptr = req_msg;
+ cds_message.type = SIR_HAL_SOC_DUAL_MAC_CFG_REQ;
+
+ lim_log(mac, LOG1,
+ FL("Post SIR_HAL_SOC_DUAL_MAC_CFG_REQ to WMA: %x %x"),
+ req_msg->scan_config, req_msg->fw_mode_config);
+ status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_message);
+ if (!CDF_IS_STATUS_SUCCESS(status)) {
+ lim_log(mac, LOGE,
+ FL("vos_mq_post_message failed!(err=%d)"),
+ status);
+ cdf_mem_free(req_msg);
+ goto fail;
+ }
+ return status;
+fail:
+ param = cdf_mem_malloc(sizeof(*param));
+ if (!param) {
+ lim_log(mac, LOGE, FL("Dual mac config resp failed"));
+ return CDF_STATUS_E_FAILURE;
+ }
+ param->status = SET_HW_MODE_STATUS_ECANCELED;
+ resp_msg.type = eWNI_SME_SET_DUAL_MAC_CFG_RESP;
+ resp_msg.bodyptr = param;
+ resp_msg.bodyval = 0;
+ lim_sys_process_mmh_msg_api(mac, &resp_msg, ePROT);
+ return CDF_STATUS_SUCCESS;
+}
+
+/**
+ * __lim_fresh_scan_reqd() - determine if a fresh scan request must be issued.
+ * @mac_ctx: Pointer to Global MAC structure
+ * @return_fresh_results: Trigger fresh scan.
+ *
+ * PE will do fresh scan, if all of the active sessions are in
+ * good state (Link Est or BSS Started). If one of the sessions
+ * is not in one of the above states, then PE does not do fresh
+ * scan. If no session exists (scanning very first time),
+ * then PE will always do fresh scan if SME asks it to do that.
+ *
+ * Return: true for fresh scan results, false if in invalid state.
+ */
+static uint8_t
+__lim_fresh_scan_reqd(tpAniSirGlobal mac_ctx, uint8_t return_fresh_results)
+{
+ uint8_t valid_state = true;
+ int i;
+
+ lim_log(mac_ctx, LOG1, FL("gLimSmeState: %d, returnFreshResults 0x%x"),
+ mac_ctx->lim.gLimSmeState, return_fresh_results);
+
+ if (mac_ctx->lim.gLimSmeState != eLIM_SME_IDLE_STATE) {
+ lim_log(mac_ctx, LOG1, FL("return FALSE"));
+ return false;
+ }
+
+ for (i = 0; i < mac_ctx->lim.maxBssId; i++) {
+ lim_log(mac_ctx, LOG1,
+ FL("session %d, bsstype %d, limSystemRole %d, limSmeState %d"),
+ i, mac_ctx->lim.gpSession[i].bssType,
+ mac_ctx->lim.gpSession[i].limSystemRole,
+ mac_ctx->lim.gpSession[i].limSmeState);
+ if (mac_ctx->lim.gpSession[i].valid == true) {
+ if (!((((mac_ctx->lim.gpSession[i].bssType ==
+ eSIR_INFRASTRUCTURE_MODE) ||
+ (mac_ctx->lim.gpSession[i].limSystemRole ==
+ eLIM_BT_AMP_STA_ROLE)) &&
+ (mac_ctx->lim.gpSession[i].limSmeState ==
+ eLIM_SME_LINK_EST_STATE)) ||
+ (((mac_ctx->lim.gpSession[i].bssType ==
+ eSIR_IBSS_MODE) ||
+ (mac_ctx->lim.gpSession[i].limSystemRole ==
+ eLIM_BT_AMP_AP_ROLE) ||
+ (mac_ctx->lim.gpSession[i].limSystemRole ==
+ eLIM_BT_AMP_STA_ROLE)) &&
+ (mac_ctx->lim.gpSession[i].limSmeState ==
+ eLIM_SME_NORMAL_STATE)) ||
+ ((((mac_ctx->lim.gpSession[i].bssType ==
+ eSIR_INFRA_AP_MODE) &&
+ (mac_ctx->lim.gpSession[i].pePersona ==
+ CDF_P2P_GO_MODE)) ||
+ (mac_ctx->lim.gpSession[i].limSystemRole ==
+ eLIM_AP_ROLE)) &&
+ (mac_ctx->lim.gpSession[i].limSmeState ==
+ eLIM_SME_NORMAL_STATE)))) {
+ valid_state = false;
+ break;
+ }
+ }
+ }
+
+ lim_log(mac_ctx, LOG1, FL("valid_state: %d"), valid_state);
+
+ if ((valid_state) &&
+ (return_fresh_results & SIR_BG_SCAN_RETURN_FRESH_RESULTS))
+ return true;
+ else
+ return false;
+}
+
+/**
+ * __lim_is_sme_assoc_cnf_valid()
+ *
+ ***FUNCTION:
+ * This function is called by __lim_process_sme_assoc_cnf_new() upon
+ * receiving SME_ASSOC_CNF.
+ *
+ ***LOGIC:
+ * Message validity checks are performed in this function
+ *
+ ***ASSUMPTIONS:
+ *
+ ***NOTE:
+ *
+ * @param pMeasReq Pointer to Received ASSOC_CNF message
+ * @return true When received SME_ASSOC_CNF is formatted
+ * correctly
+ * false otherwise
+ */
+
+static inline uint8_t __lim_is_sme_assoc_cnf_valid(tpSirSmeAssocCnf pAssocCnf)
+{
+ if (lim_is_group_addr(pAssocCnf->peerMacAddr))
+ return false;
+ else
+ return true;
+} /*** end __lim_is_sme_assoc_cnf_valid() ***/
+
+/**
+ * __lim_get_sme_join_req_size_for_alloc()
+ *
+ ***FUNCTION:
+ * This function is called in various places to get IE length
+ * from tSirBssDescription structure
+ * number being scanned.
+ *
+ ***PARAMS:
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ * NA
+ *
+ ***NOTE:
+ * NA
+ *
+ * @param pBssDescr
+ * @return Total IE length
+ */
+
+static uint16_t __lim_get_sme_join_req_size_for_alloc(uint8_t *pBuf)
+{
+ uint16_t len = 0;
+
+ if (!pBuf)
+ return len;
+
+ pBuf += sizeof(uint16_t);
+ len = lim_get_u16(pBuf);
+ return len + sizeof(uint16_t);
+}
+
+/**
+ * __lim_is_defered_msg_for_learn() - message handling in SME learn state
+ * @pMac: Global MAC context
+ * @pMsg: Pointer to message posted from SME to LIM.
+ *
+ * Has role only if 11h is enabled. Not used on STA side.
+ * Defers the message if SME is in learn state and brings
+ * the LIM back to normal mode.
+ *
+ * Return: true - If defered false - Otherwise
+ */
+
+static bool __lim_is_defered_msg_for_learn(tpAniSirGlobal pMac, tpSirMsgQ pMsg)
+{
+ if (lim_is_system_in_scan_state(pMac)) {
+ if (lim_defer_msg(pMac, pMsg) != TX_SUCCESS) {
+ lim_log(pMac, LOGE, FL("Could not defer Msg = %d"),
+ pMsg->type);
+ return false;
+ }
+ lim_log(pMac, LOG1,
+ FL("Defer the message, in learn mode type = %d"),
+ pMsg->type);
+ return true;
+ }
+ return false;
+}
+
+/**
+ * __lim_is_defered_msg_for_radar() - Defers the message if radar is detected
+ * @mac_ctx: Pointer to Global MAC structure
+ * @message: Pointer to message posted from SME to LIM.
+ *
+ * Has role only if 11h is enabled. Not used on STA side.
+ * Defers the message if radar is detected.
+ *
+ * Return: true, if defered otherwise return false.
+ */
+static bool
+__lim_is_defered_msg_for_radar(tpAniSirGlobal mac_ctx, tpSirMsgQ message)
+{
+ /*
+ * fRadarDetCurOperChan will be set only if we
+ * detect radar in current operating channel and
+ * System Role == AP ROLE
+ *
+ * TODO: Need to take care radar detection.
+ *
+ * if (LIM_IS_RADAR_DETECTED(mac_ctx))
+ */
+ if (0) {
+ if (lim_defer_msg(mac_ctx, message) != TX_SUCCESS) {
+ lim_log(mac_ctx, LOGE, FL("Could not defer Msg = %d"),
+ message->type);
+ return false;
+ }
+ lim_log(mac_ctx, LOG1,
+ FL("Defer the message, in learn mode type = %d"),
+ message->type);
+ return true;
+ }
+ return false;
+}
+
+/**
+ * __lim_process_sme_sys_ready_ind () - Process ready indication from WMA
+ * @pMac: Global MAC context
+ * @pMsgBuf: Message from WMA
+ *
+ * handles the notification from HDD. PE just forwards this message to HAL.
+ *
+ * Return: true-Posting to HAL failed, so PE will consume the buffer.
+ * false-Posting to HAL successful, so HAL will consume the buffer.
+ */
+
+static bool __lim_process_sme_sys_ready_ind(tpAniSirGlobal pMac, uint32_t *pMsgBuf)
+{
+ tSirMsgQ msg;
+ tSirSmeReadyReq *ready_req = (tSirSmeReadyReq *) pMsgBuf;
+
+ msg.type = WMA_SYS_READY_IND;
+ msg.reserved = 0;
+ msg.bodyptr = pMsgBuf;
+ msg.bodyval = 0;
+
+ if (ANI_DRIVER_TYPE(pMac) != eDRIVER_TYPE_MFG) {
+ pe_register_wma_handle(pMac);
+ pMac->lim.add_bssdescr_callback = ready_req->add_bssdescr_cb;
+ }
+ PELOGW(lim_log(pMac, LOGW, FL("sending WMA_SYS_READY_IND msg to HAL"));)
+ MTRACE(mac_trace_msg_tx(pMac, NO_SESSION, msg.type));
+
+ if (eSIR_SUCCESS != wma_post_ctrl_msg(pMac, &msg)) {
+ lim_log(pMac, LOGP, FL("wma_post_ctrl_msg failed"));
+ return true;
+ }
+ return false;
+}
+
+#ifdef WLAN_FEATURE_11AC
+
+uint32_t lim_get_center_channel(tpAniSirGlobal pMac, uint8_t primarychanNum,
+ ePhyChanBondState secondaryChanOffset,
+ uint8_t chanWidth)
+{
+ if (chanWidth == WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ) {
+ switch (secondaryChanOffset) {
+ case PHY_QUADRUPLE_CHANNEL_20MHZ_CENTERED_40MHZ_CENTERED:
+ return primarychanNum;
+ case PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_CENTERED:
+ return primarychanNum + 2;
+ case PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_CENTERED:
+ return primarychanNum - 2;
+ case PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW:
+ return primarychanNum + 6;
+ case PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW:
+ return primarychanNum + 2;
+ case PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH:
+ return primarychanNum - 2;
+ case PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH:
+ return primarychanNum - 6;
+ default:
+ return eSIR_CFG_INVALID_ID;
+ }
+ } else if (chanWidth == WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ) {
+ switch (secondaryChanOffset) {
+ case PHY_DOUBLE_CHANNEL_LOW_PRIMARY:
+ return primarychanNum + 2;
+ case PHY_DOUBLE_CHANNEL_HIGH_PRIMARY:
+ return primarychanNum - 2;
+ case PHY_QUADRUPLE_CHANNEL_20MHZ_CENTERED_40MHZ_CENTERED:
+ return primarychanNum;
+ case PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_CENTERED:
+ return primarychanNum + 2;
+ case PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_CENTERED:
+ return primarychanNum - 2;
+ case PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW:
+ return primarychanNum + 2;
+ case PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW:
+ return primarychanNum - 2;
+ case PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH:
+ return primarychanNum + 2;
+ case PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH:
+ return primarychanNum - 2;
+ default:
+ return eSIR_CFG_INVALID_ID;
+ }
+ }
+ return primarychanNum;
+}
+
+#endif
+
+/**
+ *lim_configure_ap_start_bss_session() - Configure the AP Start BSS in session.
+ *@mac_ctx: Pointer to Global MAC structure
+ *@session: A pointer to session entry
+ *@sme_start_bss_req: Start BSS Request from upper layers.
+ *
+ * This function is used to configure the start bss parameters
+ * in to the session.
+ *
+ * Return: None.
+ */
+static void
+lim_configure_ap_start_bss_session(tpAniSirGlobal mac_ctx, tpPESession session,
+ tpSirSmeStartBssReq sme_start_bss_req)
+{
+ session->limSystemRole = eLIM_AP_ROLE;
+ session->privacy = sme_start_bss_req->privacy;
+ session->fwdWPSPBCProbeReq = sme_start_bss_req->fwdWPSPBCProbeReq;
+ session->authType = sme_start_bss_req->authType;
+ /* Store the DTIM period */
+ session->dtimPeriod = (uint8_t) sme_start_bss_req->dtimPeriod;
+ /* Enable/disable UAPSD */
+ session->apUapsdEnable = sme_start_bss_req->apUapsdEnable;
+ if (session->pePersona == CDF_P2P_GO_MODE) {
+ session->proxyProbeRspEn = 0;
+ } else {
+ /*
+ * To detect PBC overlap in SAP WPS mode,
+ * Host handles Probe Requests.
+ */
+ if (SAP_WPS_DISABLED == sme_start_bss_req->wps_state)
+ session->proxyProbeRspEn = 1;
+ else
+ session->proxyProbeRspEn = 0;
+ }
+ session->ssidHidden = sme_start_bss_req->ssidHidden;
+ session->wps_state = sme_start_bss_req->wps_state;
+ session->sap_dot11mc = sme_start_bss_req->sap_dot11mc;
+ lim_get_short_slot_from_phy_mode(mac_ctx, session, session->gLimPhyMode,
+ &session->shortSlotTimeSupported);
+ session->isCoalesingInIBSSAllowed =
+ sme_start_bss_req->isCoalesingInIBSSAllowed;
+
+}
+
+/**
+ * __lim_handle_sme_start_bss_request() - process SME_START_BSS_REQ message
+ *@mac_ctx: Pointer to Global MAC structure
+ *@msg_buf: A pointer to the SME message buffer
+ *
+ * This function is called to process SME_START_BSS_REQ message
+ * from HDD or upper layer application.
+ *
+ * Return: None
+ */
+static void
+__lim_handle_sme_start_bss_request(tpAniSirGlobal mac_ctx, uint32_t *msg_buf)
+{
+ uint16_t size;
+ uint32_t val = 0;
+ tSirRetStatus ret_status;
+ tSirMacChanNum channel_number;
+ tLimMlmStartReq *mlm_start_req = NULL;
+ tpSirSmeStartBssReq sme_start_bss_req = NULL;
+ tSirResultCodes ret_code = eSIR_SME_SUCCESS;
+ /* Flag Used in case of IBSS to Auto generate BSSID. */
+ uint32_t auto_gen_bssid = false;
+ uint8_t session_id;
+ tpPESession session = NULL;
+ uint8_t sme_session_id = 0;
+ uint16_t sme_transaction_id = 0;
+ uint32_t chanwidth;
+ tSirRetStatus cfg_get_wmi_dfs_master_param = eSIR_SUCCESS;
+
+/* FEATURE_WLAN_DIAG_SUPPORT */
+#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM
+ /*
+ * Since the session is not created yet, sending NULL.
+ * The response should have the correct state.
+ */
+ lim_diag_event_report(mac_ctx, WLAN_PE_DIAG_START_BSS_REQ_EVENT,
+ NULL, 0, 0);
+#endif /* FEATURE_WLAN_DIAG_SUPPORT */
+
+ lim_log(mac_ctx, LOG1, FL("Received START_BSS_REQ"));
+
+ /*
+ * Global Sme state and mlm states are not defined yet,
+ * for BT-AMP Suppoprt . TO BE DONE
+ */
+ if ((mac_ctx->lim.gLimSmeState == eLIM_SME_OFFLINE_STATE) ||
+ (mac_ctx->lim.gLimSmeState == eLIM_SME_IDLE_STATE)) {
+ size = sizeof(tSirSmeStartBssReq);
+
+ sme_start_bss_req = cdf_mem_malloc(size);
+ if (NULL == sme_start_bss_req) {
+ lim_log(mac_ctx, LOGE,
+ FL("Allocate Memory fail for LimStartBssReq"));
+ /* Send failure response to host */
+ ret_code = eSIR_SME_RESOURCES_UNAVAILABLE;
+ goto end;
+ }
+
+ cdf_mem_set((void *)sme_start_bss_req, size, 0);
+ cdf_mem_copy(sme_start_bss_req, msg_buf,
+ sizeof(tSirSmeStartBssReq));
+ if (!lim_is_sme_start_bss_req_valid(mac_ctx,
+ sme_start_bss_req)) {
+ lim_log(mac_ctx, LOGW,
+ FL("Received invalid eWNI_SME_START_BSS_REQ"));
+ ret_code = eSIR_SME_INVALID_PARAMETERS;
+ goto free;
+ }
+
+ /*
+ * This is the place where PE is going to create a session.
+ * If session is not existed, then create a new session
+ */
+ session = pe_find_session_by_bssid(mac_ctx,
+ sme_start_bss_req->bssId, &session_id);
+ if (session != NULL) {
+ lim_log(mac_ctx, LOGW,
+ FL("Session Already exists for given BSSID"));
+ ret_code = eSIR_SME_BSS_ALREADY_STARTED_OR_JOINED;
+ session = NULL;
+ goto free;
+ } else {
+ session = pe_create_session(mac_ctx,
+ sme_start_bss_req->bssId,
+ &session_id, mac_ctx->lim.maxStation,
+ sme_start_bss_req->bssType);
+ if (session == NULL) {
+ lim_log(mac_ctx, LOGW,
+ FL("Session Can not be created "));
+ ret_code = eSIR_SME_RESOURCES_UNAVAILABLE;
+ goto free;
+ }
+ }
+
+ /* Probe resp add ie */
+ lim_start_bss_update_add_ie_buffer(mac_ctx,
+ &session->addIeParams.probeRespData_buff,
+ &session->addIeParams.probeRespDataLen,
+ sme_start_bss_req->addIeParams.probeRespData_buff,
+ sme_start_bss_req->addIeParams.probeRespDataLen);
+
+ /* Probe Beacon add ie */
+ lim_start_bss_update_add_ie_buffer(mac_ctx,
+ &session->addIeParams.probeRespBCNData_buff,
+ &session->addIeParams.probeRespBCNDataLen,
+ sme_start_bss_req->addIeParams.probeRespBCNData_buff,
+ sme_start_bss_req->addIeParams.probeRespBCNDataLen);
+
+ /* Assoc resp IE */
+ lim_start_bss_update_add_ie_buffer(mac_ctx,
+ &session->addIeParams.assocRespData_buff,
+ &session->addIeParams.assocRespDataLen,
+ sme_start_bss_req->addIeParams.assocRespData_buff,
+ sme_start_bss_req->addIeParams.assocRespDataLen);
+
+ /* Store the session related params in newly created session */
+ session->pLimStartBssReq = sme_start_bss_req;
+
+ /* Store PE session_id in session Table */
+ session->peSessionId = session_id;
+
+ /* Store SME session Id in sessionTable */
+ session->smeSessionId = sme_start_bss_req->sessionId;
+
+ session->transactionId = sme_start_bss_req->transactionId;
+
+ cdf_mem_copy(&(session->htConfig),
+ &(sme_start_bss_req->htConfig),
+ sizeof(session->htConfig));
+
+ sir_copy_mac_addr(session->selfMacAddr,
+ sme_start_bss_req->selfMacAddr);
+
+ /* Copy SSID to session table */
+ cdf_mem_copy((uint8_t *) &session->ssId,
+ (uint8_t *) &sme_start_bss_req->ssId,
+ (sme_start_bss_req->ssId.length + 1));
+
+ session->bssType = sme_start_bss_req->bssType;
+
+ session->nwType = sme_start_bss_req->nwType;
+
+ session->beaconParams.beaconInterval =
+ sme_start_bss_req->beaconInterval;
+
+ /* Store the channel number in session Table */
+ session->currentOperChannel =
+ sme_start_bss_req->channelId;
+
+ /* Store Persona */
+ session->pePersona = sme_start_bss_req->bssPersona;
+ CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_INFO,
+ FL("PE PERSONA=%d"), session->pePersona);
+
+ /* Update the phymode */
+ session->gLimPhyMode = sme_start_bss_req->nwType;
+
+ session->maxTxPower =
+ cfg_get_regulatory_max_transmit_power(mac_ctx,
+ session->currentOperChannel);
+ /* Store the dot 11 mode in to the session Table */
+ session->dot11mode = sme_start_bss_req->dot11mode;
+#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH
+ session->cc_switch_mode =
+ sme_start_bss_req->cc_switch_mode;
+#endif
+ session->htCapability =
+ IS_DOT11_MODE_HT(session->dot11mode);
+ session->vhtCapability =
+ IS_DOT11_MODE_VHT(session->dot11mode);
+ CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_INFO,
+ FL("*****session->vhtCapability = %d"),
+ session->vhtCapability);
+ session->txLdpcIniFeatureEnabled =
+ sme_start_bss_req->txLdpcIniFeatureEnabled;
+
+ if (mac_ctx->roam.configParam.enable2x2)
+ session->nss = 2;
+ else
+ session->nss = 1;
+#ifdef WLAN_FEATURE_11W
+ session->limRmfEnabled =
+ sme_start_bss_req->pmfCapable ? 1 : 0;
+ lim_log(mac_ctx, LOG1, FL("Session RMF enabled: %d"),
+ session->limRmfEnabled);
+#endif
+
+ cdf_mem_copy((void *)&session->rateSet,
+ (void *)&sme_start_bss_req->operationalRateSet,
+ sizeof(tSirMacRateSet));
+ cdf_mem_copy((void *)&session->extRateSet,
+ (void *)&sme_start_bss_req->extendedRateSet,
+ sizeof(tSirMacRateSet));
+
+ switch (sme_start_bss_req->bssType) {
+ case eSIR_INFRA_AP_MODE:
+ lim_configure_ap_start_bss_session(mac_ctx, session,
+ sme_start_bss_req);
+ break;
+ case eSIR_IBSS_MODE:
+ session->limSystemRole = eLIM_STA_IN_IBSS_ROLE;
+ lim_get_short_slot_from_phy_mode(mac_ctx, session,
+ session->gLimPhyMode,
+ &session->shortSlotTimeSupported);
+
+ /*
+ * initialize to "OPEN".
+ * will be updated upon key installation
+ */
+ session->encryptType = eSIR_ED_NONE;
+
+ break;
+
+ case eSIR_BTAMP_AP_MODE:
+ session->limSystemRole = eLIM_BT_AMP_AP_ROLE;
+ break;
+
+ case eSIR_BTAMP_STA_MODE:
+ session->limSystemRole = eLIM_BT_AMP_STA_ROLE;
+ break;
+
+ /*
+ * There is one more mode called auto mode.
+ * which is used no where
+ */
+
+ /* FORBUILD -TEMPFIX.. HOW TO use AUTO MODE????? */
+
+ default:
+ /* not used anywhere...used in scan function */
+ break;
+ }
+
+ /*
+ * BT-AMP: Allocate memory for the array of
+ * parsed (Re)Assoc request structure
+ */
+ if ((sme_start_bss_req->bssType == eSIR_BTAMP_AP_MODE) ||
+ (sme_start_bss_req->bssType == eSIR_INFRA_AP_MODE)) {
+ session->parsedAssocReq =
+ cdf_mem_malloc(session->dph.dphHashTable.
+ size * sizeof(tpSirAssocReq));
+ if (NULL == session->parsedAssocReq) {
+ lim_log(mac_ctx, LOGW,
+ FL("AllocateMemory() failed"));
+ ret_code = eSIR_SME_RESOURCES_UNAVAILABLE;
+ goto free;
+ }
+ cdf_mem_set(session->parsedAssocReq,
+ (session->dph.dphHashTable.size *
+ sizeof(tpSirAssocReq)), 0);
+ }
+
+ if (!sme_start_bss_req->channelId) {
+ lim_log(mac_ctx, LOGE,
+ FL("Received invalid eWNI_SME_START_BSS_REQ"));
+ ret_code = eSIR_SME_INVALID_PARAMETERS;
+ goto free;
+ }
+ channel_number = sme_start_bss_req->channelId;
+#ifdef QCA_HT_2040_COEX
+ if (sme_start_bss_req->obssEnabled)
+ session->htSupportedChannelWidthSet =
+ session->htCapability;
+ else
+#endif
+ session->htSupportedChannelWidthSet =
+ (sme_start_bss_req->sec_ch_offset) ? 1 : 0;
+ session->htSecondaryChannelOffset =
+ sme_start_bss_req->sec_ch_offset;
+ session->htRecommendedTxWidthSet =
+ (session->htSecondaryChannelOffset) ? 1 : 0;
+ CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_INFO,
+ FL("cbMode %u"), sme_start_bss_req->cbMode);
+ if (session->vhtCapability || session->htCapability) {
+ chanwidth = sme_start_bss_req->vht_channel_width;
+ lim_log(mac_ctx, LOG1, FL("vht_channel_width %u"),
+ sme_start_bss_req->vht_channel_width);
+ if (channel_number <= RF_CHAN_14 &&
+ chanwidth != eHT_CHANNEL_WIDTH_20MHZ) {
+ chanwidth = CH_WIDTH_20MHZ;
+ session->htSupportedChannelWidthSet = 0;
+ lim_log(mac_ctx, LOG1,
+ FL("Set chanwidth to 20Mhz, chan %d"),
+ channel_number);
+ }
+ session->ch_width = chanwidth;
+ if (session->htSupportedChannelWidthSet) {
+ session->ch_center_freq_seg0 =
+ sme_start_bss_req->center_freq_seg0;
+ session->ch_center_freq_seg1 =
+ sme_start_bss_req->center_freq_seg1;
+ } else {
+ session->ch_center_freq_seg0 = 0;
+ session->ch_center_freq_seg1 = 0;
+ }
+ }
+
+ if (session->vhtCapability &&
+ (CH_WIDTH_160MHZ > session->ch_width)) {
+ if (wlan_cfg_get_int(mac_ctx,
+ WNI_CFG_VHT_SU_BEAMFORMER_CAP, &val) !=
+ eSIR_SUCCESS)
+ lim_log(mac_ctx, LOGE, FL(
+ "cfg get vht su bformer failed"));
+
+ session->enable_su_tx_bformer = val;
+ } else {
+ session->nss = 1;
+ }
+ lim_log(mac_ctx, LOG1, FL("vht su tx bformer %d"), val);
+
+ /* Delete pre-auth list if any */
+ lim_delete_pre_auth_list(mac_ctx);
+
+ /*
+ * keep the RSN/WPA IE information in PE Session Entry
+ * later will be using this to check when received (Re)Assoc req
+ */
+ lim_set_rs_nie_wp_aiefrom_sme_start_bss_req_message(mac_ctx,
+ &sme_start_bss_req->rsnIE, session);
+
+ if (LIM_IS_AP_ROLE(session) || LIM_IS_IBSS_ROLE(session)) {
+ session->gLimProtectionControl =
+ sme_start_bss_req->protEnabled;
+ /*
+ * each byte will have the following info
+ * bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0
+ * reserved reserved RIFS Lsig n-GF ht20 11g 11b
+ */
+ cdf_mem_copy((void *)&session->cfgProtection,
+ (void *)&sme_start_bss_req->ht_capab,
+ sizeof(uint16_t));
+ /* Initialize WPS PBC session link list */
+ session->pAPWPSPBCSession = NULL;
+ }
+ /* Prepare and Issue LIM_MLM_START_REQ to MLM */
+ mlm_start_req = cdf_mem_malloc(sizeof(tLimMlmStartReq));
+ if (NULL == mlm_start_req) {
+ lim_log(mac_ctx, LOGP,
+ FL("Allocate Memory failed for mlmStartReq"));
+ ret_code = eSIR_SME_RESOURCES_UNAVAILABLE;
+ goto free;
+ }
+
+ cdf_mem_set((void *)mlm_start_req, sizeof(tLimMlmStartReq), 0);
+
+ /* Copy SSID to the MLM start structure */
+ cdf_mem_copy((uint8_t *) &mlm_start_req->ssId,
+ (uint8_t *) &sme_start_bss_req->ssId,
+ sme_start_bss_req->ssId.length + 1);
+ mlm_start_req->ssidHidden = sme_start_bss_req->ssidHidden;
+ mlm_start_req->obssProtEnabled =
+ sme_start_bss_req->obssProtEnabled;
+
+ mlm_start_req->bssType = session->bssType;
+
+ /* Fill PE session Id from the session Table */
+ mlm_start_req->sessionId = session->peSessionId;
+
+ if ((mlm_start_req->bssType == eSIR_BTAMP_STA_MODE) ||
+ (mlm_start_req->bssType == eSIR_BTAMP_AP_MODE) ||
+ (mlm_start_req->bssType == eSIR_INFRA_AP_MODE)) {
+ /*
+ * Copy the BSSId from sessionTable to
+ * mlmStartReq struct
+ */
+ sir_copy_mac_addr(mlm_start_req->bssId, session->bssId);
+ } else {
+ /* ibss mode */
+ mac_ctx->lim.gLimIbssCoalescingHappened = false;
+
+ ret_status = wlan_cfg_get_int(mac_ctx,
+ WNI_CFG_IBSS_AUTO_BSSID,
+ &auto_gen_bssid);
+ if (ret_status != eSIR_SUCCESS) {
+ lim_log(mac_ctx, LOGP,
+ FL("Get Auto Gen BSSID fail,Status=%d"),
+ ret_status);
+ ret_code = eSIR_LOGP_EXCEPTION;
+ goto free;
+ }
+
+ if (!auto_gen_bssid) {
+ /*
+ * We're not auto generating BSSID.
+ * Instead, get it from session entry
+ */
+ sir_copy_mac_addr(mlm_start_req->bssId,
+ session->bssId);
+ /*
+ * Start IBSS group BSSID
+ * Auto Generating BSSID.
+ */
+ auto_gen_bssid = ((mlm_start_req->bssId[0] &
+ 0x01) ? true : false);
+ }
+
+ if (auto_gen_bssid) {
+ /*
+ * if BSSID is not any uc id.
+ * then use locally generated BSSID.
+ * Autogenerate the BSSID
+ */
+ lim_get_random_bssid(mac_ctx,
+ mlm_start_req->bssId);
+ mlm_start_req->bssId[0] = 0x02;
+
+ /*
+ * Copy randomly generated BSSID
+ * to the session Table
+ */
+ sir_copy_mac_addr(session->bssId,
+ mlm_start_req->bssId);
+ }
+ }
+ /* store the channel num in mlmstart req structure */
+ mlm_start_req->channelNumber = session->currentOperChannel;
+ mlm_start_req->cbMode = sme_start_bss_req->cbMode;
+ mlm_start_req->beaconPeriod =
+ session->beaconParams.beaconInterval;
+
+ if (LIM_IS_AP_ROLE(session)) {
+ mlm_start_req->dtimPeriod = session->dtimPeriod;
+ mlm_start_req->wps_state = session->wps_state;
+
+ } else {
+ if (wlan_cfg_get_int(mac_ctx,
+ WNI_CFG_DTIM_PERIOD, &val) != eSIR_SUCCESS)
+ lim_log(mac_ctx, LOGP,
+ FL("could not retrieve DTIM Period"));
+ mlm_start_req->dtimPeriod = (uint8_t) val;
+ }
+
+ if (wlan_cfg_get_int(mac_ctx, WNI_CFG_CFP_PERIOD, &val) !=
+ eSIR_SUCCESS)
+ lim_log(mac_ctx, LOGP,
+ FL("could not retrieve Beacon interval"));
+ mlm_start_req->cfParamSet.cfpPeriod = (uint8_t) val;
+
+ if (wlan_cfg_get_int(mac_ctx, WNI_CFG_CFP_MAX_DURATION, &val) !=
+ eSIR_SUCCESS)
+ lim_log(mac_ctx, LOGP,
+ FL("could not retrieve CFPMaxDuration"));
+ mlm_start_req->cfParamSet.cfpMaxDuration = (uint16_t) val;
+
+ /*
+ * this may not be needed anymore now,
+ * as rateSet is now included in the
+ * session entry and MLM has session context.
+ */
+ cdf_mem_copy((void *)&mlm_start_req->rateSet,
+ (void *)&session->rateSet,
+ sizeof(tSirMacRateSet));
+
+ /* Now populate the 11n related parameters */
+ mlm_start_req->nwType = session->nwType;
+ mlm_start_req->htCapable = session->htCapability;
+
+ mlm_start_req->htOperMode = mac_ctx->lim.gHTOperMode;
+ /* Unused */
+ mlm_start_req->dualCTSProtection =
+ mac_ctx->lim.gHTDualCTSProtection;
+ mlm_start_req->txChannelWidthSet =
+ session->htRecommendedTxWidthSet;
+
+ session->limRFBand = lim_get_rf_band(channel_number);
+
+ /* Initialize 11h Enable Flag */
+ session->lim11hEnable = 0;
+ if ((mlm_start_req->bssType != eSIR_IBSS_MODE) &&
+ (SIR_BAND_5_GHZ == session->limRFBand)) {
+ if (wlan_cfg_get_int(mac_ctx,
+ WNI_CFG_11H_ENABLED, &val) != eSIR_SUCCESS)
+ lim_log(mac_ctx, LOGP,
+ FL("Fail to get WNI_CFG_11H_ENABLED "));
+ else
+ session->lim11hEnable = val;
+
+ if (session->lim11hEnable &&
+ (eSIR_INFRA_AP_MODE ==
+ mlm_start_req->bssType)) {
+ cfg_get_wmi_dfs_master_param =
+ wlan_cfg_get_int(mac_ctx,
+ WNI_CFG_DFS_MASTER_ENABLED,
+ &val);
+ session->lim11hEnable = val;
+ }
+ if (cfg_get_wmi_dfs_master_param != eSIR_SUCCESS)
+ /* Failed get CFG WNI_CFG_DFS_MASTER_ENABLED */
+ lim_log(mac_ctx, LOGE,
+ FL("Get Fail, CFG DFS ENABLE"));
+ }
+
+ if (!session->lim11hEnable) {
+ if (cfg_set_int(mac_ctx,
+ WNI_CFG_LOCAL_POWER_CONSTRAINT, 0) !=
+ eSIR_SUCCESS)
+ /*
+ * Failed to set the CFG param
+ * WNI_CFG_LOCAL_POWER_CONSTRAINT
+ */
+ lim_log(mac_ctx, LOGE,
+ FL("Set LOCAL_POWER_CONSTRAINT failed"));
+ }
+
+ session->limPrevSmeState = session->limSmeState;
+ session->limSmeState = eLIM_SME_WT_START_BSS_STATE;
+ MTRACE(mac_trace
+ (mac_ctx, TRACE_CODE_SME_STATE,
+ session->peSessionId,
+ session->limSmeState));
+
+ lim_post_mlm_message(mac_ctx, LIM_MLM_START_REQ,
+ (uint32_t *) mlm_start_req);
+ return;
+ } else {
+
+ lim_log(mac_ctx, LOGE,
+ FL("Received unexpected START_BSS_REQ, in state %X"),
+ mac_ctx->lim.gLimSmeState);
+ ret_code = eSIR_SME_BSS_ALREADY_STARTED_OR_JOINED;
+ goto end;
+ } /* if (mac_ctx->lim.gLimSmeState == eLIM_SME_OFFLINE_STATE) */
+
+free:
+ if ((session != NULL) &&
+ (session->pLimStartBssReq == sme_start_bss_req)) {
+ session->pLimStartBssReq = NULL;
+ }
+ cdf_mem_free(sme_start_bss_req);
+ cdf_mem_free(mlm_start_req);
+
+end:
+ if (sme_start_bss_req != NULL) {
+ sme_session_id = sme_start_bss_req->sessionId;
+ sme_transaction_id = sme_start_bss_req->transactionId;
+ }
+ if (NULL != session) {
+ pe_delete_session(mac_ctx, session);
+ session = NULL;
+ }
+ lim_send_sme_start_bss_rsp(mac_ctx, eWNI_SME_START_BSS_RSP, ret_code,
+ session, sme_session_id, sme_transaction_id);
+}
+
+/**
+ * __lim_process_sme_start_bss_req() - Call handler to start BSS
+ *
+ * @pMac: Global MAC context
+ * @pMsg: Message pointer
+ *
+ * Wrapper for the function __lim_handle_sme_start_bss_request
+ * This message will be defered until softmac come out of
+ * scan mode or if we have detected radar on the current
+ * operating channel.
+ *
+ * return true - If we consumed the buffer
+ * false - If have defered the message.
+ */
+static bool __lim_process_sme_start_bss_req(tpAniSirGlobal pMac, tpSirMsgQ pMsg)
+{
+ if (__lim_is_defered_msg_for_learn(pMac, pMsg) ||
+ __lim_is_defered_msg_for_radar(pMac, pMsg)) {
+ /**
+ * If message defered, buffer is not consumed yet.
+ * So return false
+ */
+ return false;
+ }
+
+ __lim_handle_sme_start_bss_request(pMac, (uint32_t *) pMsg->bodyptr);
+ return true;
+}
+
+/**
+ * lim_get_random_bssid()
+ *
+ * FUNCTION:This function is called to process generate the random number for bssid
+ * This function is called to process SME_SCAN_REQ message
+ * from HDD or upper layer application.
+ *
+ * LOGIC:
+ *
+ * ASSUMPTIONS:
+ *
+ * NOTE:
+ * 1. geneartes the unique random number for bssid in ibss
+ *
+ * @param pMac Pointer to Global MAC structure
+ * @param *data Pointer to bssid buffer
+ * @return None
+ */
+void lim_get_random_bssid(tpAniSirGlobal pMac, uint8_t *data)
+{
+ uint32_t random[2];
+ random[0] = tx_time_get();
+ random[0] |= (random[0] << 15);
+ random[1] = random[0] >> 1;
+ cdf_mem_copy(data, (uint8_t *) random, sizeof(tSirMacAddr));
+}
+
+static CDF_STATUS lim_send_hal_start_scan_offload_req(tpAniSirGlobal pMac,
+ tpSirSmeScanReq pScanReq)
+{
+ tSirScanOffloadReq *pScanOffloadReq;
+ uint8_t *p;
+ uint8_t *ht_cap_ie;
+ tSirMsgQ msg;
+ uint16_t i, len;
+ uint16_t ht_cap_len = 0, addn_ie_len = 0;
+#ifdef WLAN_FEATURE_11AC
+ uint8_t *vht_cap_ie;
+ uint16_t vht_cap_len = 0;
+#endif /* WLAN_FEATURE_11AC */
+ tSirRetStatus status, rc = eSIR_SUCCESS;
+ tDot11fIEExtCap extracted_extcap = {0};
+ bool extcap_present = true;
+
+ if (pScanReq->uIEFieldLen) {
+ status = lim_strip_extcap_update_struct(pMac,
+ (uint8_t *) pScanReq + pScanReq->uIEFieldOffset,
+ &pScanReq->uIEFieldLen, &extracted_extcap);
+
+ if (eSIR_SUCCESS != status) {
+ extcap_present = false;
+ lim_log(pMac, LOG1,
+ FL("Unable to Strip ExtCap IE from Scan Req"));
+ }
+
+ if (extcap_present) {
+ lim_log(pMac, LOG1,
+ FL("Extcap was part of SCAN IE - Updating FW"));
+ lim_send_ext_cap_ie(pMac, pScanReq->sessionId,
+ &extracted_extcap, true);
+ }
+ } else {
+ lim_log(pMac, LOG1,
+ FL("No IEs in the scan request from supplicant"));
+ }
+
+ /**
+ * The tSirScanOffloadReq will reserve the space for first channel,
+ * so allocate the memory for (numChannels - 1) and uIEFieldLen
+ */
+ len = sizeof(tSirScanOffloadReq) +
+ (pScanReq->channelList.numChannels - 1) + pScanReq->uIEFieldLen;
+
+ if (IS_DOT11_MODE_HT(pScanReq->dot11mode)) {
+ lim_log(pMac, LOG1,
+ FL("Adding HT Caps IE since dot11mode=%d"),
+ pScanReq->dot11mode);
+ /* 2 bytes for EID and Length */
+ ht_cap_len = 2 + sizeof(tHtCaps);
+ len += ht_cap_len;
+ addn_ie_len += ht_cap_len;
+ }
+
+#ifdef WLAN_FEATURE_11AC
+ if (IS_DOT11_MODE_VHT(pScanReq->dot11mode)) {
+ lim_log(pMac, LOG1,
+ FL("Adding VHT Caps IE since dot11mode=%d"),
+ pScanReq->dot11mode);
+ /* 2 bytes for EID and Length */
+ vht_cap_len = 2 + sizeof(tSirMacVHTCapabilityInfo) +
+ sizeof(tSirVhtMcsInfo);
+ len += vht_cap_len;
+ addn_ie_len += vht_cap_len;
+ }
+#endif /* WLAN_FEATURE_11AC */
+
+ pScanOffloadReq = cdf_mem_malloc(len);
+ if (NULL == pScanOffloadReq) {
+ lim_log(pMac, LOGE,
+ FL("AllocateMemory failed for pScanOffloadReq"));
+ return CDF_STATUS_E_NOMEM;
+ }
+
+ cdf_mem_set((uint8_t *) pScanOffloadReq, len, 0);
+
+ msg.type = WMA_START_SCAN_OFFLOAD_REQ;
+ msg.bodyptr = pScanOffloadReq;
+ msg.bodyval = 0;
+
+ cdf_mem_copy((uint8_t *) pScanOffloadReq->bssId,
+ (uint8_t *) pScanReq->bssId, sizeof(tSirMacAddr));
+
+ if (pScanReq->numSsid > SIR_SCAN_MAX_NUM_SSID) {
+ lim_log(pMac, LOGE,
+ FL("Invalid value (%d) for numSsid"),
+ SIR_SCAN_MAX_NUM_SSID);
+ cdf_mem_free(pScanOffloadReq);
+ return CDF_STATUS_E_FAILURE;
+ }
+
+ pScanOffloadReq->numSsid = pScanReq->numSsid;
+ for (i = 0; i < pScanOffloadReq->numSsid; i++) {
+ pScanOffloadReq->ssId[i].length = pScanReq->ssId[i].length;
+ cdf_mem_copy((uint8_t *) pScanOffloadReq->ssId[i].ssId,
+ (uint8_t *) pScanReq->ssId[i].ssId,
+ pScanOffloadReq->ssId[i].length);
+ }
+
+ pScanOffloadReq->hiddenSsid = pScanReq->hiddenSsid;
+ cdf_mem_copy((uint8_t *) pScanOffloadReq->selfMacAddr,
+ (uint8_t *) pScanReq->selfMacAddr, sizeof(tSirMacAddr));
+ pScanOffloadReq->bssType = pScanReq->bssType;
+ pScanOffloadReq->dot11mode = pScanReq->dot11mode;
+ pScanOffloadReq->scanType = pScanReq->scanType;
+ pScanOffloadReq->minChannelTime = pScanReq->minChannelTime;
+ pScanOffloadReq->maxChannelTime = pScanReq->maxChannelTime;
+ pScanOffloadReq->restTime = pScanReq->restTime;
+
+ /* for normal scan, the value for p2pScanType should be 0
+ always */
+ if (pScanReq->p2pSearch)
+ pScanOffloadReq->p2pScanType = P2P_SCAN_TYPE_SEARCH;
+
+ pScanOffloadReq->sessionId = pScanReq->sessionId;
+ pScanOffloadReq->scan_id = pScanReq->scan_id;
+
+ if (pScanOffloadReq->sessionId >= pMac->lim.maxBssId)
+ lim_log(pMac, LOGE, FL("Invalid pe sessionID : %d"),
+ pScanOffloadReq->sessionId);
+
+ pScanOffloadReq->channelList.numChannels =
+ pScanReq->channelList.numChannels;
+ p = &(pScanOffloadReq->channelList.channelNumber[0]);
+ for (i = 0; i < pScanOffloadReq->channelList.numChannels; i++)
+ p[i] = pScanReq->channelList.channelNumber[i];
+
+ pScanOffloadReq->uIEFieldLen = pScanReq->uIEFieldLen;
+ pScanOffloadReq->uIEFieldOffset = len - addn_ie_len -
+ pScanOffloadReq->uIEFieldLen;
+ cdf_mem_copy((uint8_t *) pScanOffloadReq +
+ pScanOffloadReq->uIEFieldOffset,
+ (uint8_t *) pScanReq + pScanReq->uIEFieldOffset,
+ pScanReq->uIEFieldLen);
+
+ /* Copy HT Capability info if dot11mode is HT */
+ if (IS_DOT11_MODE_HT(pScanReq->dot11mode)) {
+ /* Populate EID and Length field here */
+ ht_cap_ie = (uint8_t *) pScanOffloadReq +
+ pScanOffloadReq->uIEFieldOffset +
+ pScanOffloadReq->uIEFieldLen;
+ cdf_mem_set(ht_cap_ie, ht_cap_len, 0);
+ *ht_cap_ie = SIR_MAC_HT_CAPABILITIES_EID;
+ *(ht_cap_ie + 1) = ht_cap_len - 2;
+ lim_set_ht_caps(pMac, NULL, ht_cap_ie, ht_cap_len);
+ pScanOffloadReq->uIEFieldLen += ht_cap_len;
+ }
+
+#ifdef WLAN_FEATURE_11AC
+ /* Copy VHT Capability info if dot11mode is VHT Capable */
+ if (IS_DOT11_MODE_VHT(pScanReq->dot11mode)) {
+ /* Populate EID and Length field here */
+ vht_cap_ie = (uint8_t *) pScanOffloadReq +
+ pScanOffloadReq->uIEFieldOffset +
+ pScanOffloadReq->uIEFieldLen;
+ cdf_mem_set(vht_cap_ie, vht_cap_len, 0);
+ *vht_cap_ie = SIR_MAC_VHT_CAPABILITIES_EID;
+ *(vht_cap_ie + 1) = vht_cap_len - 2;
+ lim_set_vht_caps(pMac, NULL, vht_cap_ie, vht_cap_len);
+ pScanOffloadReq->uIEFieldLen += vht_cap_len;
+ }
+#endif /* WLAN_FEATURE_11AC */
+
+ rc = wma_post_ctrl_msg(pMac, &msg);
+ if (rc != eSIR_SUCCESS) {
+ lim_log(pMac, LOGE, FL("wma_post_ctrl_msg() return failure"));
+ cdf_mem_free(pScanOffloadReq);
+ return CDF_STATUS_E_FAILURE;
+ }
+
+ lim_log(pMac, LOG1, FL("Processed Offload Scan Request Successfully"));
+
+ return CDF_STATUS_SUCCESS;
+}
+
+/**
+ * __lim_process_sme_scan_req() - Process the SME Scan Request
+ * @mac_ctx: Global MAC Context
+ * @msg_buf: Buffer which contains the request and pertinent parameters
+ *
+ * This function is called to process SME_SCAN_REQ message
+ * from HDD or upper layer application.
+ *
+ * Return: None
+ */
+
+static void __lim_process_sme_scan_req(tpAniSirGlobal mac_ctx,
+ uint32_t *msg_buf)
+{
+ tpSirSmeScanReq scan_req;
+ uint8_t valid_req = 0;
+
+#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */
+ lim_diag_event_report(mac_ctx, WLAN_PE_DIAG_SCAN_REQ_EVENT, NULL,
+ eSIR_SUCCESS, eSIR_SUCCESS);
+#endif
+
+ scan_req = (tpSirSmeScanReq) msg_buf;
+ lim_log(mac_ctx, LOG1,
+ FL("SME SCAN REQ id %d numChan %d min %d max %d IELen %d first %d fresh %d unique %d type %d rsp %d"),
+ scan_req->scan_id, scan_req->channelList.numChannels,
+ scan_req->minChannelTime, scan_req->maxChannelTime,
+ scan_req->uIEFieldLen, scan_req->returnAfterFirstMatch,
+ scan_req->returnFreshResults, scan_req->returnUniqueResults,
+ scan_req->scanType, mac_ctx->lim.gLimRspReqd ? 1 : 0);
+ /*
+ * Since scan req always requires a response, we will overwrite response
+ * required here. This is added esp to take care of the condition where
+ * in p2p go case, we hold the scan req and insert single NOA. We send
+ * the held scan request to FW later on getting start NOA ind from FW so
+ * we lose state of the gLimRspReqd flag for the scan req if any other
+ * request comes by then. e.g. While unit testing, we found when insert
+ * single NOA is done, we see a get stats request which turns the flag
+ * gLimRspReqd to false; now when we actually start the saved scan req
+ * for init scan after getting NOA started, the gLimRspReqd being a
+ * global flag is showing false instead of true value for this saved
+ * scan req. Since all scan reqs coming to lim require a response,
+ * there is no harm in setting the global flag gLimRspReqd to true here.
+ */
+ mac_ctx->lim.gLimRspReqd = true;
+
+ /*
+ * copy the Self MAC address from SmeReq to the globalplace,
+ * used for sending probe req
+ */
+ sir_copy_mac_addr(mac_ctx->lim.gSelfMacAddr, scan_req->selfMacAddr);
+ valid_req = lim_is_sme_scan_req_valid(mac_ctx, scan_req);
+
+ if (!valid_req || mac_ctx->lim.scan_disabled) {
+ lim_log(mac_ctx, LOGE,
+ FL("Scan disabled %d, Valid Scan Req %d"),
+ mac_ctx->lim.scan_disabled, valid_req);
+
+ if (mac_ctx->lim.gLimRspReqd) {
+ mac_ctx->lim.gLimRspReqd = false;
+
+ lim_send_sme_scan_rsp(mac_ctx,
+ eSIR_SME_INVALID_PARAMETERS,
+ scan_req->sessionId,
+ scan_req->transactionId,
+ scan_req->scan_id);
+ }
+ return;
+ }
+
+ /*
+ * If scan request is received in idle, joinFailed
+ * states or in link established state (in STA role)
+ * or in normal state (in STA-in-IBSS/AP role) with
+ * 'return fresh scan results' request from HDD or
+ * it is periodic background scanning request,
+ * trigger fresh scan request to MLM
+ */
+ if (__lim_fresh_scan_reqd(mac_ctx, scan_req->returnFreshResults)) {
+
+ mac_ctx->lim.gLim24Band11dScanDone = 0;
+ mac_ctx->lim.gLim50Band11dScanDone = 0;
+ mac_ctx->lim.gLimReturnAfterFirstMatch =
+ scan_req->returnAfterFirstMatch;
+ mac_ctx->lim.gLimReturnUniqueResults =
+ ((scan_req->returnUniqueResults) > 0 ? true : false);
+
+ if (CDF_STATUS_SUCCESS !=
+ lim_send_hal_start_scan_offload_req(mac_ctx,
+ scan_req)) {
+ lim_log(mac_ctx, LOGE, FL(
+ "Couldn't send Offload scan request"));
+ lim_send_sme_scan_rsp(mac_ctx,
+ eSIR_SME_INVALID_PARAMETERS,
+ scan_req->sessionId,
+ scan_req->transactionId,
+ scan_req->scan_id);
+ return;
+ }
+ }
+ else {
+ /* In all other cases return 'cached' scan results */
+ if (mac_ctx->lim.gLimRspReqd) {
+ mac_ctx->lim.gLimRspReqd = false;
+ lim_send_sme_scan_rsp(mac_ctx, eSIR_SME_SUCCESS,
+ scan_req->sessionId,
+ scan_req->transactionId, scan_req->scan_id);
+ }
+ }
+}
+
+#ifdef FEATURE_OEM_DATA_SUPPORT
+
+static void __lim_process_sme_oem_data_req(tpAniSirGlobal pMac, uint32_t *pMsgBuf)
+{
+ tpSirOemDataReq pOemDataReq;
+ tLimMlmOemDataReq *pMlmOemDataReq;
+
+ pOemDataReq = (tpSirOemDataReq) pMsgBuf;
+
+ /* post the lim mlm message now */
+ pMlmOemDataReq = cdf_mem_malloc(sizeof(tLimMlmOemDataReq));
+ if (NULL == pMlmOemDataReq) {
+ lim_log(pMac, LOGP,
+ FL("AllocateMemory failed for mlmOemDataReq"));
+ return;
+ }
+ /* Initialize this buffer */
+ cdf_mem_set(pMlmOemDataReq, (sizeof(tLimMlmOemDataReq)), 0);
+
+ cdf_mem_copy(pMlmOemDataReq->selfMacAddr, pOemDataReq->selfMacAddr,
+ sizeof(tSirMacAddr));
+ cdf_mem_copy(pMlmOemDataReq->oemDataReq, pOemDataReq->oemDataReq,
+ OEM_DATA_REQ_SIZE);
+
+ /* Issue LIM_MLM_OEM_DATA_REQ to MLM */
+ lim_post_mlm_message(pMac, LIM_MLM_OEM_DATA_REQ,
+ (uint32_t *) pMlmOemDataReq);
+
+ return;
+
+} /*** end __lim_process_sme_oem_data_req() ***/
+
+#endif /* FEATURE_OEM_DATA_SUPPORT */
+
+/**
+ * __lim_process_clear_dfs_channel_list()
+ *
+ ***FUNCTION:
+ ***Clear DFS channel list when country is changed/aquired.
+ .*This message is sent from SME.
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ *
+ ***NOTE:
+ *
+ * @param pMac Pointer to Global MAC structure
+ * @param *pMsgBuf A pointer to the SME message buffer
+ * @return None
+ */
+static void __lim_process_clear_dfs_channel_list(tpAniSirGlobal pMac, tpSirMsgQ pMsg)
+{
+ cdf_mem_set(&pMac->lim.dfschannelList, sizeof(tSirDFSChannelList), 0);
+}
+
+/**
+ * __lim_process_sme_join_req() - process SME_JOIN_REQ message
+ * @mac_ctx: Pointer to Global MAC structure
+ * @msg_buf: A pointer to the SME message buffer
+ *
+ * This function is called to process SME_JOIN_REQ message
+ * from HDD or upper layer application.
+ *
+ * Return: None
+ */
+static void
+__lim_process_sme_join_req(tpAniSirGlobal mac_ctx, uint32_t *msg_buf)
+{
+ tpSirSmeJoinReq sme_join_req = NULL;
+ tLimMlmJoinReq *mlm_join_req;
+ tSirResultCodes ret_code = eSIR_SME_SUCCESS;
+ uint32_t val = 0;
+ uint16_t n_size;
+ uint8_t session_id;
+ tpPESession session = NULL;
+ uint8_t sme_session_id;
+ uint16_t sme_transaction_id;
+ tPowerdBm local_power_constraint = 0, reg_max = 0;
+ uint16_t ie_len;
+ uint8_t *vendor_ie;
+ tSirBssDescription bss_desc;
+
+/* FEATURE_WLAN_DIAG_SUPPORT */
+#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM
+ /*
+ * Not sending any session, since it is not created yet.
+ * The response whould have correct state.
+ */
+ lim_diag_event_report(mac_ctx, WLAN_PE_DIAG_JOIN_REQ_EVENT, NULL, 0, 0);
+#endif /* FEATURE_WLAN_DIAG_SUPPORT */
+
+ lim_log(mac_ctx, LOG1, FL("Received SME_JOIN_REQ"));
+#ifdef WLAN_FEATURE_VOWIFI
+ /*
+ * Need to read the CFG here itself as this is
+ * used in limExtractAPCapability() below.
+ * This CFG is actually read in rrm_update_config()
+ * which is called later. Because this is not
+ * read, RRM related path before calling rrm_update_config()
+ * is not getting executed causing issues
+ * like not honoring power constraint on 1st association
+ * after driver loading.
+ */
+ if (wlan_cfg_get_int(mac_ctx, WNI_CFG_RRM_ENABLED, &val) !=
+ eSIR_SUCCESS)
+ lim_log(mac_ctx, LOGP, FL("cfg get rrm enabled failed"));
+ mac_ctx->rrm.rrmPEContext.rrmEnable = (val) ? 1 : 0;
+ val = 0;
+#endif /* WLAN_FEATURE_VOWIFI */
+
+ /*
+ * Expect Join request in idle state.
+ * Reassociate request is expected in link established state.
+ */
+
+ /* Global SME and LIM states are not defined yet for BT-AMP Support */
+ if (mac_ctx->lim.gLimSmeState == eLIM_SME_IDLE_STATE) {
+ n_size = __lim_get_sme_join_req_size_for_alloc((uint8_t *)
+ msg_buf);
+
+ sme_join_req = cdf_mem_malloc(n_size);
+ if (NULL == sme_join_req) {
+ lim_log(mac_ctx, LOGP,
+ FL("AllocateMemory failed for sme_join_req"));
+ ret_code = eSIR_SME_RESOURCES_UNAVAILABLE;
+ return;
+ }
+ (void)cdf_mem_set((void *)sme_join_req, n_size, 0);
+ (void)cdf_mem_copy((void *)sme_join_req, (void *)msg_buf,
+ n_size);
+
+ if (!lim_is_sme_join_req_valid(mac_ctx, sme_join_req)) {
+ /* Received invalid eWNI_SME_JOIN_REQ */
+ /* Log the event */
+ lim_log(mac_ctx, LOGW,
+ FL("SessionId:%d JOIN REQ with invalid data"),
+ sme_join_req->sessionId);
+ ret_code = eSIR_SME_INVALID_PARAMETERS;
+ goto end;
+ }
+
+ bss_desc = sme_join_req->bssDescription;
+ /* check for the existence of start BSS session */
+
+ session = pe_find_session_by_bssid(mac_ctx, bss_desc.bssId,
+ &session_id);
+
+ if (session != NULL) {
+ lim_log(mac_ctx, LOGE,
+ FL("Session(%d) Already exists for BSSID: "
+ MAC_ADDRESS_STR " in limSmeState = %X"),
+ session_id,
+ MAC_ADDR_ARRAY(bss_desc.bssId),
+ session->limSmeState);
+
+ if (session->limSmeState == eLIM_SME_LINK_EST_STATE &&
+ session->smeSessionId == sme_join_req->sessionId) {
+ /*
+ * Received eWNI_SME_JOIN_REQ for same
+ * BSS as currently associated.
+ * Log the event and send success
+ */
+ lim_log(mac_ctx, LOGW,
+ FL("SessionId: %d"), session_id);
+ lim_log(mac_ctx, LOGW,
+ FL("JOIN_REQ for current joined BSS"));
+ /* Send Join success response to host */
+ ret_code = eSIR_SME_ALREADY_JOINED_A_BSS;
+ session = NULL;
+ goto end;
+ } else {
+ lim_log(mac_ctx, LOGE,
+ FL("JOIN_REQ not for current joined BSS"));
+ ret_code = eSIR_SME_REFUSED;
+ session = NULL;
+ goto end;
+ }
+ } else {
+ /*
+ * Session Entry does not exist for given BSSId
+ * Try to Create a new session
+ */
+ session = pe_create_session(mac_ctx, bss_desc.bssId,
+ &session_id, mac_ctx->lim.maxStation,
+ eSIR_INFRASTRUCTURE_MODE);
+ if (session == NULL) {
+ lim_log(mac_ctx, LOGE,
+ FL("Session Can not be created "));
+ ret_code = eSIR_SME_RESOURCES_UNAVAILABLE;
+ goto end;
+ } else
+ lim_log(mac_ctx, LOG1,
+ FL("SessionId:%d New session created"),
+ session_id);
+ }
+ session->isAmsduSupportInAMPDU =
+ sme_join_req->isAmsduSupportInAMPDU;
+
+ /*
+ * Store Session related parameters
+ * Store PE session Id in session Table
+ */
+ session->peSessionId = session_id;
+
+ /* store the smejoin req handle in session table */
+ session->pLimJoinReq = sme_join_req;
+
+ /* Store SME session Id in sessionTable */
+ session->smeSessionId = sme_join_req->sessionId;
+
+ /* Store SME transaction Id in session Table */
+ session->transactionId = sme_join_req->transactionId;
+
+ /* Store beaconInterval */
+ session->beaconParams.beaconInterval =
+ bss_desc.beaconInterval;
+
+ cdf_mem_copy(&(session->htConfig), &(sme_join_req->htConfig),
+ sizeof(session->htConfig));
+
+ /* Copying of bssId is already done, while creating session */
+ sir_copy_mac_addr(session->selfMacAddr,
+ sme_join_req->selfMacAddr);
+ session->bssType = sme_join_req->bsstype;
+
+ session->statypeForBss = STA_ENTRY_PEER;
+ session->limWmeEnabled = sme_join_req->isWMEenabled;
+ session->limQosEnabled = sme_join_req->isQosEnabled;
+
+ /* Store vendor specfic IE for CISCO AP */
+ ie_len = (bss_desc.length + sizeof(bss_desc.length) -
+ GET_FIELD_OFFSET(tSirBssDescription, ieFields));
+
+ vendor_ie = cfg_get_vendor_ie_ptr_from_oui(mac_ctx,
+ SIR_MAC_CISCO_OUI, SIR_MAC_CISCO_OUI_SIZE,
+ ((uint8_t *)&bss_desc.ieFields), ie_len);
+
+ if (NULL != vendor_ie) {
+ lim_log(mac_ctx, LOGE,
+ FL("DUT is trying to connect to Cisco AP"));
+ session->isCiscoVendorAP = true;
+ } else {
+ session->isCiscoVendorAP = false;
+ }
+
+ /* Copy the dot 11 mode in to the session table */
+
+ session->dot11mode = sme_join_req->dot11mode;
+#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH
+ session->cc_switch_mode = sme_join_req->cc_switch_mode;
+#endif
+ session->nwType = bss_desc.nwType;
+ session->enableAmpduPs = sme_join_req->enableAmpduPs;
+ session->enableHtSmps = sme_join_req->enableHtSmps;
+ session->htSmpsvalue = sme_join_req->htSmps;
+
+ /*Store Persona */
+ session->pePersona = sme_join_req->staPersona;
+ CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_INFO,
+ FL("PE PERSONA=%d cbMode %u"),
+ session->pePersona, sme_join_req->cbMode);
+ if (mac_ctx->roam.configParam.enable2x2)
+ session->nss = 2;
+ else
+ session->nss = 1;
+#ifdef WLAN_FEATURE_11AC
+ session->vhtCapability =
+ IS_DOT11_MODE_VHT(session->dot11mode);
+ CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_INFO_MED,
+ "***__lim_process_sme_join_req: vhtCapability=%d****",
+ session->vhtCapability);
+ if (session->vhtCapability) {
+ if (session->pePersona == CDF_STA_MODE) {
+ session->txBFIniFeatureEnabled =
+ sme_join_req->txBFIniFeatureEnabled;
+ } else {
+ session->txBFIniFeatureEnabled = 0;
+ }
+ session->txMuBformee = sme_join_req->txMuBformee;
+ session->enableVhtpAid =
+ sme_join_req->enableVhtpAid;
+ session->enableVhtGid =
+ sme_join_req->enableVhtGid;
+
+ CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_INFO_MED,
+ FL("***txBFIniFeatureEnabled=%d***"),
+ session->txBFIniFeatureEnabled);
+ if (wlan_cfg_get_int(mac_ctx,
+ WNI_CFG_VHT_SU_BEAMFORMER_CAP, &val) !=
+ eSIR_SUCCESS)
+ lim_log(mac_ctx, LOGE, FL(
+ "cfg get vht su bformer failed"));
+
+ session->enable_su_tx_bformer = val;
+ lim_log(mac_ctx, LOGE, FL("vht su tx bformer %d"), val);
+ }
+ if (session->vhtCapability && session->txBFIniFeatureEnabled) {
+ if (cfg_set_int(mac_ctx, WNI_CFG_VHT_SU_BEAMFORMEE_CAP,
+ session->txBFIniFeatureEnabled) !=
+ eSIR_SUCCESS) {
+ /*
+ * Set failed for
+ * CFG_VHT_SU_BEAMFORMEE_CAP
+ */
+ lim_log(mac_ctx, LOGP,
+ FL("Failed CFG_VHT_SU_BEAMFORMEE_CAP"));
+ ret_code = eSIR_LOGP_EXCEPTION;
+ goto end;
+ }
+ CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_INFO_MED,
+ "%s: txBFCsnValue=%d", __func__,
+ sme_join_req->txBFCsnValue);
+ if (cfg_set_int(mac_ctx,
+ WNI_CFG_VHT_CSN_BEAMFORMEE_ANT_SUPPORTED,
+ sme_join_req->txBFCsnValue) != eSIR_SUCCESS) {
+ /*
+ * Set Failed for CFG
+ * CFG_VHT_CSN_BEAMFORMEE_ANT_SUPPORTED
+ */
+ lim_log(mac_ctx, LOGP, FL("Set Fail CFG"));
+ ret_code = eSIR_LOGP_EXCEPTION;
+ goto end;
+ }
+ }
+#endif
+
+ /*Phy mode */
+ session->gLimPhyMode = bss_desc.nwType;
+ handle_ht_capabilityand_ht_info(mac_ctx, session);
+ /* Copy The channel Id to the session Table */
+ session->currentOperChannel = bss_desc.channelId;
+ /* cbMode is already merged value of peer and self -
+ * done by csr in csr_get_cb_mode_from_ies */
+ session->htSupportedChannelWidthSet =
+ (sme_join_req->cbMode) ? 1 : 0;
+ session->htRecommendedTxWidthSet =
+ session->htSupportedChannelWidthSet;
+ session->htSecondaryChannelOffset = sme_join_req->cbMode;
+
+ if (PHY_DOUBLE_CHANNEL_HIGH_PRIMARY == sme_join_req->cbMode) {
+ session->ch_center_freq_seg0 =
+ session->currentOperChannel - 2;
+ session->ch_width = CH_WIDTH_40MHZ;
+ } else if (PHY_DOUBLE_CHANNEL_LOW_PRIMARY ==
+ sme_join_req->cbMode) {
+ session->ch_center_freq_seg0 =
+ session->currentOperChannel + 2;
+ session->ch_width = CH_WIDTH_40MHZ;
+ } else {
+ session->ch_center_freq_seg0 = 0;
+ session->ch_width = CH_WIDTH_20MHZ;
+ }
+
+ /* Record if management frames need to be protected */
+#ifdef WLAN_FEATURE_11W
+ if (eSIR_ED_AES_128_CMAC == sme_join_req->MgmtEncryptionType) {
+ CDF_STATUS cdf_status;
+ session->limRmfEnabled = 1;
+ session->pmfComebackTimerInfo.pMac = mac_ctx;
+ session->pmfComebackTimerInfo.sessionID =
+ session_id;
+ cdf_status = cdf_mc_timer_init(
+ &session->pmfComebackTimer,
+ CDF_TIMER_TYPE_SW,
+ lim_pmf_comeback_timer_callback,
+ (void *)&session->pmfComebackTimerInfo);
+ if (CDF_STATUS_SUCCESS != cdf_status) {
+ lim_log(mac_ctx, LOGP,
+ FL("cannot init pmf comeback timer."));
+ ret_code = eSIR_LOGP_EXCEPTION;
+ goto end;
+ }
+ } else {
+ session->limRmfEnabled = 0;
+ }
+#endif
+
+#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM
+ session->rssi = bss_desc.rssi;
+#endif
+
+ /* Copy the SSID from smejoinreq to session entry */
+ session->ssId.length = sme_join_req->ssId.length;
+ cdf_mem_copy(session->ssId.ssId, sme_join_req->ssId.ssId,
+ session->ssId.length);
+
+ /*
+ * Determin 11r or ESE connection based on input from SME
+ * which inturn is dependent on the profile the user wants
+ * to connect to, So input is coming from supplicant
+ */
+#ifdef WLAN_FEATURE_VOWIFI_11R
+ session->is11Rconnection = sme_join_req->is11Rconnection;
+#endif
+#ifdef FEATURE_WLAN_ESE
+ session->isESEconnection = sme_join_req->isESEconnection;
+#endif
+#if defined WLAN_FEATURE_VOWIFI_11R || defined FEATURE_WLAN_ESE || defined(FEATURE_WLAN_LFR)
+ session->isFastTransitionEnabled =
+ sme_join_req->isFastTransitionEnabled;
+#endif
+
+#ifdef FEATURE_WLAN_LFR
+ session->isFastRoamIniFeatureEnabled =
+ sme_join_req->isFastRoamIniFeatureEnabled;
+#endif
+ session->txLdpcIniFeatureEnabled =
+ sme_join_req->txLdpcIniFeatureEnabled;
+
+ if (session->bssType == eSIR_INFRASTRUCTURE_MODE) {
+ session->limSystemRole = eLIM_STA_ROLE;
+ } else if (session->bssType == eSIR_BTAMP_AP_MODE) {
+ session->limSystemRole = eLIM_BT_AMP_STA_ROLE;
+ } else {
+ /*
+ * Throw an error and return and make
+ * sure to delete the session.
+ */
+ lim_log(mac_ctx, LOGE,
+ FL("recvd JOIN_REQ with invalid bss type %d"),
+ session->bssType);
+ ret_code = eSIR_SME_INVALID_PARAMETERS;
+ goto end;
+ }
+
+ if (sme_join_req->addIEScan.length)
+ cdf_mem_copy(&session->pLimJoinReq->addIEScan,
+ &sme_join_req->addIEScan, sizeof(tSirAddie));
+
+ if (sme_join_req->addIEAssoc.length)
+ cdf_mem_copy(&session->pLimJoinReq->addIEAssoc,
+ &sme_join_req->addIEAssoc, sizeof(tSirAddie));
+
+ val = sizeof(tLimMlmJoinReq) +
+ session->pLimJoinReq->bssDescription.length + 2;
+ mlm_join_req = cdf_mem_malloc(val);
+ if (NULL == mlm_join_req) {
+ lim_log(mac_ctx, LOGP,
+ FL("AllocateMemory failed for mlmJoinReq"));
+ return;
+ }
+ (void)cdf_mem_set((void *)mlm_join_req, val, 0);
+
+ /* PE SessionId is stored as a part of JoinReq */
+ mlm_join_req->sessionId = session->peSessionId;
+
+ if (wlan_cfg_get_int(mac_ctx, WNI_CFG_JOIN_FAILURE_TIMEOUT,
+ (uint32_t *) &mlm_join_req->joinFailureTimeout) !=
+ eSIR_SUCCESS) {
+ lim_log(mac_ctx, LOGP,
+ FL("couldn't retrieve JoinFailureTimer value"
+ " setting to default value"));
+ mlm_join_req->joinFailureTimeout =
+ WNI_CFG_JOIN_FAILURE_TIMEOUT_STADEF;
+ }
+
+ /* copy operational rate from session */
+ cdf_mem_copy((void *)&session->rateSet,
+ (void *)&sme_join_req->operationalRateSet,
+ sizeof(tSirMacRateSet));
+ cdf_mem_copy((void *)&session->extRateSet,
+ (void *)&sme_join_req->extendedRateSet,
+ sizeof(tSirMacRateSet));
+ /*
+ * this may not be needed anymore now, as rateSet is now
+ * included in the session entry and MLM has session context.
+ */
+ cdf_mem_copy((void *)&mlm_join_req->operationalRateSet,
+ (void *)&session->rateSet,
+ sizeof(tSirMacRateSet));
+
+ session->encryptType = sme_join_req->UCEncryptionType;
+
+ mlm_join_req->bssDescription.length =
+ session->pLimJoinReq->bssDescription.length;
+
+ cdf_mem_copy((uint8_t *) &mlm_join_req->bssDescription.bssId,
+ (uint8_t *)
+ &session->pLimJoinReq->bssDescription.bssId,
+ session->pLimJoinReq->bssDescription.length + 2);
+
+ session->limCurrentBssCaps =
+ session->pLimJoinReq->bssDescription.capabilityInfo;
+
+ reg_max = cfg_get_regulatory_max_transmit_power(mac_ctx,
+ session->currentOperChannel);
+ local_power_constraint = reg_max;
+
+ lim_extract_ap_capability(mac_ctx,
+ (uint8_t *)
+ session->pLimJoinReq->bssDescription.ieFields,
+ lim_get_ielen_from_bss_description(
+ &session->pLimJoinReq->bssDescription),
+ &session->limCurrentBssQosCaps,
+ &session->limCurrentBssPropCap,
+ &session->gLimCurrentBssUapsd,
+ &local_power_constraint, session);
+
+#ifdef FEATURE_WLAN_ESE
+ session->maxTxPower = lim_get_max_tx_power(reg_max,
+ local_power_constraint,
+ mac_ctx->roam.configParam.nTxPowerCap);
+#else
+ session->maxTxPower =
+ CDF_MIN(reg_max, (local_power_constraint));
+#endif
+#if defined WLAN_VOWIFI_DEBUG
+ lim_log(mac_ctx, LOGE,
+ "Regulatory max = %d, local power constraint = %d"
+ reg_max, local_power_constraint);
+ lim_log(mac_ctx, LOGE, FL(" max tx = %d"),
+ session->maxTxPower);
+#endif
+
+ if (session->gLimCurrentBssUapsd) {
+ session->gUapsdPerAcBitmask =
+ session->pLimJoinReq->uapsdPerAcBitmask;
+ lim_log(mac_ctx, LOG1,
+ FL("UAPSD flag for all AC - 0x%2x"),
+ session->gUapsdPerAcBitmask);
+
+ /* resetting the dynamic uapsd mask */
+ session->gUapsdPerAcDeliveryEnableMask = 0;
+ session->gUapsdPerAcTriggerEnableMask = 0;
+ }
+
+ session->limRFBand =
+ lim_get_rf_band(session->currentOperChannel);
+
+ /* Initialize 11h Enable Flag */
+ if (SIR_BAND_5_GHZ == session->limRFBand) {
+ if (wlan_cfg_get_int(mac_ctx, WNI_CFG_11H_ENABLED,
+ &val) != eSIR_SUCCESS) {
+ lim_log(mac_ctx, LOGP,
+ FL("Fail to get WNI_CFG_11H_ENABLED "));
+ session->lim11hEnable =
+ WNI_CFG_11H_ENABLED_STADEF;
+ } else {
+ session->lim11hEnable = val;
+ }
+ } else {
+ session->lim11hEnable = 0;
+ }
+
+ /*
+ * To care of the scenario when STA transitions from
+ * IBSS to Infrastructure mode.
+ */
+ mac_ctx->lim.gLimIbssCoalescingHappened = false;
+
+ session->limPrevSmeState = session->limSmeState;
+ session->limSmeState = eLIM_SME_WT_JOIN_STATE;
+ MTRACE(mac_trace(mac_ctx, TRACE_CODE_SME_STATE,
+ session->peSessionId,
+ session->limSmeState));
+
+ lim_log(mac_ctx, LOG1,
+ FL("SME JoinReq:Sessionid %d SSID len %d SSID : %s Channel %d, BSSID " MAC_ADDRESS_STR),
+ mlm_join_req->sessionId, session->ssId.length,
+ session->ssId.ssId, session->currentOperChannel,
+ MAC_ADDR_ARRAY(session->bssId));
+
+ /* Indicate whether spectrum management is enabled */
+ session->spectrumMgtEnabled =
+ sme_join_req->spectrumMgtIndicator;
+
+ /* Enable the spectrum management if this is a DFS channel */
+ if (session->country_info_present &&
+ lim_isconnected_on_dfs_channel(
+ session->currentOperChannel))
+ session->spectrumMgtEnabled = true;
+
+ session->isOSENConnection = sme_join_req->isOSENConnection;
+
+ lim_log(mac_ctx, LOG1,
+ FL("SessionId:%d MLM_JOIN_REQ is posted to MLM SM"),
+ mlm_join_req->sessionId);
+ /* Issue LIM_MLM_JOIN_REQ to MLM */
+ lim_post_mlm_message(mac_ctx, LIM_MLM_JOIN_REQ,
+ (uint32_t *) mlm_join_req);
+ return;
+
+ } else {
+ /* Received eWNI_SME_JOIN_REQ un expected state */
+ lim_log(mac_ctx, LOGE,
+ FL("received unexpected SME_JOIN_REQ in state %X"),
+ mac_ctx->lim.gLimSmeState);
+ lim_print_sme_state(mac_ctx, LOGE, mac_ctx->lim.gLimSmeState);
+ ret_code = eSIR_SME_UNEXPECTED_REQ_RESULT_CODE;
+ session = NULL;
+ goto end;
+ }
+
+end:
+ sme_session_id = sme_join_req->sessionId;
+ sme_transaction_id = sme_join_req->transactionId;
+
+ if (sme_join_req) {
+ cdf_mem_free(sme_join_req);
+ sme_join_req = NULL;
+ if (NULL != session)
+ session->pLimJoinReq = NULL;
+ }
+ if (ret_code != eSIR_SME_SUCCESS) {
+ if (NULL != session) {
+ pe_delete_session(mac_ctx, session);
+ session = NULL;
+ }
+ }
+ lim_log(mac_ctx, LOG1,
+ FL("Send failure status on sessionid: %d with ret_code = %d"),
+ sme_session_id, ret_code);
+ lim_send_sme_join_reassoc_rsp(mac_ctx, eWNI_SME_JOIN_RSP, ret_code,
+ eSIR_MAC_UNSPEC_FAILURE_STATUS, session, sme_session_id,
+ sme_transaction_id);
+}
+
+#if defined FEATURE_WLAN_ESE || defined WLAN_FEATURE_VOWIFI
+uint8_t lim_get_max_tx_power(tPowerdBm regMax, tPowerdBm apTxPower,
+ uint8_t iniTxPower)
+{
+ uint8_t maxTxPower = 0;
+ uint8_t txPower = CDF_MIN(regMax, (apTxPower));
+ txPower = CDF_MIN(txPower, iniTxPower);
+ if ((txPower >= MIN_TX_PWR_CAP) && (txPower <= MAX_TX_PWR_CAP))
+ maxTxPower = txPower;
+ else if (txPower < MIN_TX_PWR_CAP)
+ maxTxPower = MIN_TX_PWR_CAP;
+ else
+ maxTxPower = MAX_TX_PWR_CAP;
+
+ return maxTxPower;
+}
+#endif
+
+/**
+ * __lim_process_sme_reassoc_req() - process reassoc req
+ *
+ * @mac_ctx: Pointer to Global MAC structure
+ * @msg_buf: pointer to the SME message buffer
+ *
+ * This function is called to process SME_REASSOC_REQ message
+ * from HDD or upper layer application.
+ *
+ * Return: None
+ */
+
+static void __lim_process_sme_reassoc_req(tpAniSirGlobal mac_ctx,
+ uint32_t *msg_buf)
+{
+ uint16_t caps;
+ uint32_t val;
+ tpSirSmeJoinReq reassoc_req = NULL;
+ tLimMlmReassocReq *mlm_reassoc_req;
+ tSirResultCodes ret_code = eSIR_SME_SUCCESS;
+ tpPESession session_entry = NULL;
+ uint8_t session_id;
+ uint8_t sme_session_id;
+ uint16_t transaction_id;
+ tPowerdBm local_pwr_constraint = 0, reg_max = 0;
+ uint32_t tele_bcn_en = 0;
+ uint16_t size;
+
+ lim_log(mac_ctx, LOG3, FL("Received REASSOC_REQ"));
+
+ size = __lim_get_sme_join_req_size_for_alloc((uint8_t *)msg_buf);
+ reassoc_req = cdf_mem_malloc(size);
+ if (NULL == reassoc_req) {
+ lim_log(mac_ctx, LOGP,
+ FL("call to AllocateMemory failed for reassoc_req"));
+
+ ret_code = eSIR_SME_RESOURCES_UNAVAILABLE;
+ goto end;
+ }
+ (void)cdf_mem_set((void *)reassoc_req, size, 0);
+ (void)cdf_mem_copy((void *)reassoc_req, (void *)msg_buf, size);
+
+ if (!lim_is_sme_join_req_valid(mac_ctx,
+ (tpSirSmeJoinReq)reassoc_req)) {
+ /*
+ * Received invalid eWNI_SME_REASSOC_REQ
+ */
+ lim_log(mac_ctx, LOGW,
+ FL("received SME_REASSOC_REQ with invalid data"));
+
+ ret_code = eSIR_SME_INVALID_PARAMETERS;
+ goto end;
+ }
+
+ session_entry = pe_find_session_by_bssid(mac_ctx,
+ reassoc_req->bssDescription.bssId,
+ &session_id);
+ if (session_entry == NULL) {
+ lim_print_mac_addr(mac_ctx, reassoc_req->bssDescription.bssId,
+ LOGE);
+ lim_log(mac_ctx, LOGE,
+ FL("Session does not exist for given bssId"));
+ ret_code = eSIR_SME_INVALID_PARAMETERS;
+ goto end;
+ }
+#ifdef FEATURE_WLAN_DIAG_SUPPORT /* FEATURE_WLAN_DIAG_SUPPORT */
+ lim_diag_event_report(mac_ctx, WLAN_PE_DIAG_REASSOC_REQ_EVENT,
+ session_entry, eSIR_SUCCESS, eSIR_SUCCESS);
+#endif /* FEATURE_WLAN_DIAG_SUPPORT */
+ /* mac_ctx->lim.gpLimReassocReq = reassoc_req;//TO SUPPORT BT-AMP */
+
+ /* Store the reassoc handle in the session Table */
+ session_entry->pLimReAssocReq = reassoc_req;
+
+ session_entry->dot11mode = reassoc_req->dot11mode;
+ session_entry->vhtCapability =
+ IS_DOT11_MODE_VHT(reassoc_req->dot11mode);
+ /*
+ * Reassociate request is expected
+ * in link established state only.
+ */
+
+ if (session_entry->limSmeState != eLIM_SME_LINK_EST_STATE) {
+#if defined(WLAN_FEATURE_VOWIFI_11R) || defined(FEATURE_WLAN_ESE) || \
+ defined(FEATURE_WLAN_LFR)
+ if (session_entry->limSmeState == eLIM_SME_WT_REASSOC_STATE) {
+ /*
+ * May be from 11r FT pre-auth. So lets check it
+ * before we bail out
+ */
+ lim_log(mac_ctx, LOG1, FL(
+ "Session in reassoc state is %d"),
+ session_entry->peSessionId);
+
+ /* Make sure its our preauth bssid */
+ if (!cdf_mem_compare(reassoc_req->bssDescription.bssId,
+ session_entry->limReAssocbssId,
+ 6)) {
+ lim_print_mac_addr(mac_ctx,
+ reassoc_req->bssDescription.
+ bssId, LOGE);
+ lim_log(mac_ctx, LOGP,
+ FL("Unknown bssId in reassoc state"));
+ ret_code = eSIR_SME_INVALID_PARAMETERS;
+ goto end;
+ }
+
+ lim_process_mlm_ft_reassoc_req(mac_ctx, msg_buf,
+ session_entry);
+ return;
+ }
+#endif
+ /*
+ * Should not have received eWNI_SME_REASSOC_REQ
+ */
+ lim_log(mac_ctx, LOGE,
+ FL("received unexpected SME_REASSOC_REQ in state %X"),
+ session_entry->limSmeState);
+ lim_print_sme_state(mac_ctx, LOGE, session_entry->limSmeState);
+
+ ret_code = eSIR_SME_UNEXPECTED_REQ_RESULT_CODE;
+ goto end;
+ }
+
+ cdf_mem_copy(session_entry->limReAssocbssId,
+ session_entry->pLimReAssocReq->bssDescription.bssId,
+ sizeof(tSirMacAddr));
+
+ session_entry->limReassocChannelId =
+ session_entry->pLimReAssocReq->bssDescription.channelId;
+
+ session_entry->reAssocHtSupportedChannelWidthSet =
+ (session_entry->pLimReAssocReq->cbMode) ? 1 : 0;
+ session_entry->reAssocHtRecommendedTxWidthSet =
+ session_entry->reAssocHtSupportedChannelWidthSet;
+ session_entry->reAssocHtSecondaryChannelOffset =
+ session_entry->pLimReAssocReq->cbMode;
+
+ session_entry->limReassocBssCaps =
+ session_entry->pLimReAssocReq->bssDescription.capabilityInfo;
+ reg_max = cfg_get_regulatory_max_transmit_power(mac_ctx,
+ session_entry->currentOperChannel);
+ local_pwr_constraint = reg_max;
+
+ lim_extract_ap_capability(mac_ctx,
+ (uint8_t *)session_entry->pLimReAssocReq->bssDescription.ieFields,
+ lim_get_ielen_from_bss_description(
+ &session_entry->pLimReAssocReq->bssDescription),
+ &session_entry->limReassocBssQosCaps,
+ &session_entry->limReassocBssPropCap,
+ &session_entry->gLimCurrentBssUapsd,
+ &local_pwr_constraint, session_entry);
+ session_entry->maxTxPower = CDF_MIN(reg_max, (local_pwr_constraint));
+#if defined WLAN_VOWIFI_DEBUG
+ lim_log(mac_ctx, LOGE,
+ "Regulatory max = %d, local pwr constraint = %d, max tx = %d",
+ reg_max, local_pwr_constraint,
+ session_entry->maxTxPower);
+#endif
+ /* Copy the SSID from session entry to local variable */
+ session_entry->limReassocSSID.length = reassoc_req->ssId.length;
+ cdf_mem_copy(session_entry->limReassocSSID.ssId,
+ reassoc_req->ssId.ssId,
+ session_entry->limReassocSSID.length);
+ if (session_entry->gLimCurrentBssUapsd) {
+ session_entry->gUapsdPerAcBitmask =
+ session_entry->pLimReAssocReq->uapsdPerAcBitmask;
+ lim_log(mac_ctx, LOG1,
+ FL("UAPSD flag for all AC - 0x%2x"),
+ session_entry->gUapsdPerAcBitmask);
+ }
+
+ mlm_reassoc_req = cdf_mem_malloc(sizeof(tLimMlmReassocReq));
+ if (NULL == mlm_reassoc_req) {
+ lim_log(mac_ctx, LOGP,
+ FL("call to AllocateMemory failed for mlmReassocReq"));
+
+ ret_code = eSIR_SME_RESOURCES_UNAVAILABLE;
+ goto end;
+ }
+
+ cdf_mem_copy(mlm_reassoc_req->peerMacAddr,
+ session_entry->limReAssocbssId, sizeof(tSirMacAddr));
+
+ if (wlan_cfg_get_int(mac_ctx, WNI_CFG_REASSOCIATION_FAILURE_TIMEOUT,
+ (uint32_t *)&mlm_reassoc_req->reassocFailureTimeout) !=
+ eSIR_SUCCESS) {
+ /*
+ * Could not get ReassocFailureTimeout value
+ * from CFG. Log error.
+ */
+ lim_log(mac_ctx, LOGP,
+ FL("could not retrieve ReassocFailureTimeout value"));
+ }
+
+ if (cfg_get_capability_info(mac_ctx, &caps, session_entry) !=
+ eSIR_SUCCESS) {
+ /*
+ * Could not get Capabilities value
+ * from CFG. Log error.
+ */
+ lim_log(mac_ctx, LOGP, FL(
+ "could not retrieve Capabilities value"));
+ }
+ mlm_reassoc_req->capabilityInfo = caps;
+
+ /* Update PE session_id */
+ mlm_reassoc_req->sessionId = session_id;
+
+ /*
+ * If telescopic beaconing is enabled, set listen interval to
+ * WNI_CFG_TELE_BCN_MAX_LI
+ */
+ if (wlan_cfg_get_int(mac_ctx, WNI_CFG_TELE_BCN_WAKEUP_EN,
+ &tele_bcn_en) != eSIR_SUCCESS)
+ lim_log(mac_ctx, LOGP,
+ FL("Couldn't get WNI_CFG_TELE_BCN_WAKEUP_EN"));
+
+ val = WNI_CFG_LISTEN_INTERVAL_STADEF;
+
+ if (tele_bcn_en) {
+ if (wlan_cfg_get_int(mac_ctx, WNI_CFG_TELE_BCN_MAX_LI, &val) !=
+ eSIR_SUCCESS)
+ /*
+ * Could not get ListenInterval value
+ * from CFG. Log error.
+ */
+ lim_log(mac_ctx, LOGP,
+ FL("could not retrieve ListenInterval"));
+ } else {
+ if (wlan_cfg_get_int(mac_ctx, WNI_CFG_LISTEN_INTERVAL, &val) !=
+ eSIR_SUCCESS)
+ /*
+ * Could not get ListenInterval value
+ * from CFG. Log error.
+ */
+ lim_log(mac_ctx, LOGP,
+ FL("could not retrieve ListenInterval"));
+ }
+
+ mlm_reassoc_req->listenInterval = (uint16_t) val;
+
+ /* Indicate whether spectrum management is enabled */
+ session_entry->spectrumMgtEnabled = reassoc_req->spectrumMgtIndicator;
+
+ /* Enable the spectrum management if this is a DFS channel */
+ if (session_entry->country_info_present &&
+ lim_isconnected_on_dfs_channel(
+ session_entry->currentOperChannel))
+ session_entry->spectrumMgtEnabled = true;
+
+ session_entry->limPrevSmeState = session_entry->limSmeState;
+ session_entry->limSmeState = eLIM_SME_WT_REASSOC_STATE;
+
+ MTRACE(mac_trace(mac_ctx, TRACE_CODE_SME_STATE,
+ session_entry->peSessionId,
+ session_entry->limSmeState));
+
+ lim_post_mlm_message(mac_ctx,
+ LIM_MLM_REASSOC_REQ, (uint32_t *)mlm_reassoc_req);
+ return;
+end:
+ if (reassoc_req) {
+ cdf_mem_free(reassoc_req);
+ if (session_entry)
+ session_entry->pLimReAssocReq = NULL;
+ }
+
+ if (session_entry) {
+ /*
+ * error occurred after we determined the session so extract
+ * session and transaction info from there
+ */
+ sme_session_id = session_entry->smeSessionId;
+ transaction_id = session_entry->transactionId;
+ } else
+ /*
+ * error occurred before or during the time we determined
+ * the session so extract the session and transaction info
+ * from the message
+ */
+ lim_get_session_info(mac_ctx, (uint8_t *) msg_buf,
+ &sme_session_id, &transaction_id);
+
+ /*
+ * Send Reassoc failure response to host
+ * (note session_entry may be NULL, but that's OK)
+ */
+ lim_send_sme_join_reassoc_rsp(mac_ctx, eWNI_SME_REASSOC_RSP,
+ ret_code, eSIR_MAC_UNSPEC_FAILURE_STATUS,
+ session_entry, sme_session_id,
+ transaction_id);
+}
+
+bool send_disassoc_frame = 1;
+/**
+ * __lim_process_sme_disassoc_req()
+ *
+ ***FUNCTION:
+ * This function is called to process SME_DISASSOC_REQ message
+ * from HDD or upper layer application.
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ *
+ ***NOTE:
+ *
+ * @param pMac Pointer to Global MAC structure
+ * @param *pMsgBuf A pointer to the SME message buffer
+ * @return None
+ */
+
+static void __lim_process_sme_disassoc_req(tpAniSirGlobal pMac, uint32_t *pMsgBuf)
+{
+ uint16_t disassocTrigger, reasonCode;
+ tLimMlmDisassocReq *pMlmDisassocReq;
+ tSirResultCodes retCode = eSIR_SME_SUCCESS;
+ tSirSmeDisassocReq smeDisassocReq;
+ tpPESession psessionEntry = NULL;
+ uint8_t sessionId;
+ uint8_t smesessionId;
+ uint16_t smetransactionId;
+
+ if (pMsgBuf == NULL) {
+ lim_log(pMac, LOGE, FL("Buffer is Pointing to NULL"));
+ return;
+ }
+
+ cdf_mem_copy(&smeDisassocReq, pMsgBuf, sizeof(tSirSmeDisassocReq));
+ smesessionId = smeDisassocReq.sessionId;
+ smetransactionId = smeDisassocReq.transactionId;
+ if (!lim_is_sme_disassoc_req_valid(pMac,
+ &smeDisassocReq,
+ psessionEntry)) {
+ PELOGE(lim_log(pMac, LOGE,
+ FL("received invalid SME_DISASSOC_REQ message"));)
+ if (pMac->lim.gLimRspReqd) {
+ pMac->lim.gLimRspReqd = false;
+
+ retCode = eSIR_SME_INVALID_PARAMETERS;
+ disassocTrigger = eLIM_HOST_DISASSOC;
+ goto sendDisassoc;
+ }
+
+ return;
+ }
+
+ psessionEntry = pe_find_session_by_bssid(pMac,
+ smeDisassocReq.bssId,
+ &sessionId);
+ if (psessionEntry == NULL) {
+ lim_log(pMac, LOGE,
+ FL("session does not exist for given bssId "
+ MAC_ADDRESS_STR),
+ MAC_ADDR_ARRAY(smeDisassocReq.bssId));
+ retCode = eSIR_SME_INVALID_PARAMETERS;
+ disassocTrigger = eLIM_HOST_DISASSOC;
+ goto sendDisassoc;
+ }
+ lim_log(pMac, LOG1,
+ FL("received DISASSOC_REQ message on sessionid %d Systemrole %d Reason: %u SmeState: %d from: "
+ MAC_ADDRESS_STR), smesessionId,
+ GET_LIM_SYSTEM_ROLE(psessionEntry), smeDisassocReq.reasonCode,
+ pMac->lim.gLimSmeState,
+ MAC_ADDR_ARRAY(smeDisassocReq.peerMacAddr));
+
+#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */
+ lim_diag_event_report(pMac, WLAN_PE_DIAG_DISASSOC_REQ_EVENT, psessionEntry,
+ 0, smeDisassocReq.reasonCode);
+#endif /* FEATURE_WLAN_DIAG_SUPPORT */
+
+ /* Update SME session Id and SME transaction ID */
+
+ psessionEntry->smeSessionId = smesessionId;
+ psessionEntry->transactionId = smetransactionId;
+
+ switch (GET_LIM_SYSTEM_ROLE(psessionEntry)) {
+ case eLIM_STA_ROLE:
+ case eLIM_BT_AMP_STA_ROLE:
+ switch (psessionEntry->limSmeState) {
+ case eLIM_SME_ASSOCIATED_STATE:
+ case eLIM_SME_LINK_EST_STATE:
+ psessionEntry->limPrevSmeState =
+ psessionEntry->limSmeState;
+ psessionEntry->limSmeState = eLIM_SME_WT_DISASSOC_STATE;
+#ifdef FEATURE_WLAN_TDLS
+ /* Delete all TDLS peers connected before leaving BSS */
+ lim_delete_tdls_peers(pMac, psessionEntry);
+#endif
+ MTRACE(mac_trace
+ (pMac, TRACE_CODE_SME_STATE,
+ psessionEntry->peSessionId,
+ psessionEntry->limSmeState));
+ lim_log(pMac, LOG1,
+ FL("Rcvd SME_DISASSOC_REQ while in limSmeState: %d "),
+ psessionEntry->limSmeState);
+ break;
+
+ case eLIM_SME_WT_DEAUTH_STATE:
+ /* PE shall still process the DISASSOC_REQ and proceed with
+ * link tear down even if it had already sent a DEAUTH_IND to
+ * to SME. pMac->lim.gLimPrevSmeState shall remain the same as
+ * its been set when PE entered WT_DEAUTH_STATE.
+ */
+ psessionEntry->limSmeState = eLIM_SME_WT_DISASSOC_STATE;
+ MTRACE(mac_trace
+ (pMac, TRACE_CODE_SME_STATE,
+ psessionEntry->peSessionId,
+ psessionEntry->limSmeState));
+ lim_log(pMac, LOG1,
+ FL("Rcvd SME_DISASSOC_REQ while in SME_WT_DEAUTH_STATE. "));
+ break;
+
+ case eLIM_SME_WT_DISASSOC_STATE:
+ /* PE Recieved a Disassoc frame. Normally it gets DISASSOC_CNF but it
+ * received DISASSOC_REQ. Which means host is also trying to disconnect.
+ * PE can continue processing DISASSOC_REQ and send the response instead
+ * of failing the request. SME will anyway ignore DEAUTH_IND that was sent
+ * for disassoc frame.
+ *
+ * It will send a disassoc, which is ok. However, we can use the global flag
+ * sendDisassoc to not send disassoc frame.
+ */
+ lim_log(pMac, LOG1,
+ FL("Rcvd SME_DISASSOC_REQ while in SME_WT_DISASSOC_STATE. "));
+ break;
+
+ case eLIM_SME_JOIN_FAILURE_STATE: {
+ /* Already in Disconnected State, return success */
+ lim_log(pMac, LOG1,
+ FL("Rcvd SME_DISASSOC_REQ while in eLIM_SME_JOIN_FAILURE_STATE. "));
+ if (pMac->lim.gLimRspReqd) {
+ retCode = eSIR_SME_SUCCESS;
+ disassocTrigger = eLIM_HOST_DISASSOC;
+ goto sendDisassoc;
+ }
+ }
+ break;
+ default:
+ /**
+ * STA is not currently associated.
+ * Log error and send response to host
+ */
+ lim_log(pMac, LOGE,
+ FL("received unexpected SME_DISASSOC_REQ in state %X"),
+ psessionEntry->limSmeState);
+ lim_print_sme_state(pMac, LOGE,
+ psessionEntry->limSmeState);
+
+ if (pMac->lim.gLimRspReqd) {
+ if (psessionEntry->limSmeState !=
+ eLIM_SME_WT_ASSOC_STATE)
+ pMac->lim.gLimRspReqd = false;
+
+ retCode = eSIR_SME_UNEXPECTED_REQ_RESULT_CODE;
+ disassocTrigger = eLIM_HOST_DISASSOC;
+ goto sendDisassoc;
+ }
+
+ return;
+ }
+
+ break;
+
+ case eLIM_AP_ROLE:
+ case eLIM_BT_AMP_AP_ROLE:
+ /* Fall through */
+ break;
+
+ case eLIM_STA_IN_IBSS_ROLE:
+ default:
+ /* eLIM_UNKNOWN_ROLE */
+ lim_log(pMac, LOGE,
+ FL("received unexpected SME_DISASSOC_REQ for role %d"),
+ GET_LIM_SYSTEM_ROLE(psessionEntry));
+
+ retCode = eSIR_SME_UNEXPECTED_REQ_RESULT_CODE;
+ disassocTrigger = eLIM_HOST_DISASSOC;
+ goto sendDisassoc;
+ } /* end switch (pMac->lim.gLimSystemRole) */
+
+ if (smeDisassocReq.reasonCode == eLIM_LINK_MONITORING_DISASSOC) {
+ /* / Disassociation is triggered by Link Monitoring */
+ lim_log(pMac, LOG1,
+ FL("Sending Disasscoc with reason Link Monitoring"));
+ disassocTrigger = eLIM_LINK_MONITORING_DISASSOC;
+ reasonCode = eSIR_MAC_DISASSOC_DUE_TO_INACTIVITY_REASON;
+ } else {
+ disassocTrigger = eLIM_HOST_DISASSOC;
+ reasonCode = smeDisassocReq.reasonCode;
+ }
+
+ if (smeDisassocReq.doNotSendOverTheAir) {
+ lim_log(pMac, LOG1, FL("do not send dissoc over the air"));
+ send_disassoc_frame = 0;
+ }
+ /* Trigger Disassociation frame to peer MAC entity */
+ lim_log(pMac, LOG1, FL("Sending Disasscoc with disassoc Trigger"
+ " : %d, reasonCode : %d"),
+ disassocTrigger, reasonCode);
+
+ pMlmDisassocReq = cdf_mem_malloc(sizeof(tLimMlmDisassocReq));
+ if (NULL == pMlmDisassocReq) {
+ /* Log error */
+ lim_log(pMac, LOGP,
+ FL("call to AllocateMemory failed for mlmDisassocReq"));
+
+ return;
+ }
+
+ cdf_mem_copy((uint8_t *) &pMlmDisassocReq->peerMacAddr,
+ (uint8_t *) &smeDisassocReq.peerMacAddr,
+ sizeof(tSirMacAddr));
+
+ pMlmDisassocReq->reasonCode = reasonCode;
+ pMlmDisassocReq->disassocTrigger = disassocTrigger;
+
+ /* Update PE session ID */
+ pMlmDisassocReq->sessionId = sessionId;
+
+ lim_post_mlm_message(pMac,
+ LIM_MLM_DISASSOC_REQ, (uint32_t *) pMlmDisassocReq);
+ return;
+
+sendDisassoc:
+ if (psessionEntry)
+ lim_send_sme_disassoc_ntf(pMac, smeDisassocReq.peerMacAddr,
+ retCode,
+ disassocTrigger,
+ 1, smesessionId, smetransactionId,
+ psessionEntry);
+ else
+ lim_send_sme_disassoc_ntf(pMac, smeDisassocReq.peerMacAddr,
+ retCode,
+ disassocTrigger,
+ 1, smesessionId, smetransactionId, NULL);
+
+} /*** end __lim_process_sme_disassoc_req() ***/
+
+/** -----------------------------------------------------------------
+ \brief __lim_process_sme_disassoc_cnf() - Process SME_DISASSOC_CNF
+
+ This function is called to process SME_DISASSOC_CNF message
+ from HDD or upper layer application.
+
+ \param pMac - global mac structure
+ \param pStaDs - station dph hash node
+ \return none
+ \sa
+ ----------------------------------------------------------------- */
+static void __lim_process_sme_disassoc_cnf(tpAniSirGlobal pMac, uint32_t *pMsgBuf)
+{
+ tSirSmeDisassocCnf smeDisassocCnf;
+ uint16_t aid;
+ tpDphHashNode pStaDs;
+ tpPESession psessionEntry;
+ uint8_t sessionId;
+
+ PELOG1(lim_log(pMac, LOG1, FL("received DISASSOC_CNF message"));)
+
+ cdf_mem_copy(&smeDisassocCnf, pMsgBuf,
+ sizeof(struct sSirSmeDisassocCnf));
+
+ psessionEntry = pe_find_session_by_bssid(pMac,
+ smeDisassocCnf.bssId,
+ &sessionId);
+ if (psessionEntry == NULL) {
+ lim_log(pMac, LOGE,
+ FL("session does not exist for given bssId"));
+ return;
+ }
+
+ if (!lim_is_sme_disassoc_cnf_valid(pMac, &smeDisassocCnf, psessionEntry)) {
+ lim_log(pMac, LOGE,
+ FL("received invalid SME_DISASSOC_CNF message"));
+ return;
+ }
+#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */
+ if (smeDisassocCnf.messageType == eWNI_SME_DISASSOC_CNF)
+ lim_diag_event_report(pMac, WLAN_PE_DIAG_DISASSOC_CNF_EVENT,
+ psessionEntry,
+ (uint16_t) smeDisassocCnf.statusCode, 0);
+ else if (smeDisassocCnf.messageType == eWNI_SME_DEAUTH_CNF)
+ lim_diag_event_report(pMac, WLAN_PE_DIAG_DEAUTH_CNF_EVENT,
+ psessionEntry,
+ (uint16_t) smeDisassocCnf.statusCode, 0);
+#endif /* FEATURE_WLAN_DIAG_SUPPORT */
+
+ switch (GET_LIM_SYSTEM_ROLE(psessionEntry)) {
+ case eLIM_STA_ROLE:
+ case eLIM_BT_AMP_STA_ROLE: /* To test reconn */
+ if ((psessionEntry->limSmeState != eLIM_SME_IDLE_STATE) &&
+ (psessionEntry->limSmeState != eLIM_SME_WT_DISASSOC_STATE)
+ && (psessionEntry->limSmeState !=
+ eLIM_SME_WT_DEAUTH_STATE)) {
+ lim_log(pMac, LOGE,
+ FL
+ ("received unexp SME_DISASSOC_CNF in state %X"),
+ psessionEntry->limSmeState);
+ lim_print_sme_state(pMac, LOGE,
+ psessionEntry->limSmeState);
+ return;
+ }
+ break;
+
+ case eLIM_AP_ROLE:
+ /* Fall through */
+ break;
+
+ case eLIM_STA_IN_IBSS_ROLE:
+ default: /* eLIM_UNKNOWN_ROLE */
+ lim_log(pMac, LOGE,
+ FL("received unexpected SME_DISASSOC_CNF role %d"),
+ GET_LIM_SYSTEM_ROLE(psessionEntry));
+
+ return;
+ }
+
+ if ((psessionEntry->limSmeState == eLIM_SME_WT_DISASSOC_STATE) ||
+ (psessionEntry->limSmeState == eLIM_SME_WT_DEAUTH_STATE) ||
+ LIM_IS_AP_ROLE(psessionEntry)) {
+ pStaDs = dph_lookup_hash_entry(pMac,
+ smeDisassocCnf.peerMacAddr, &aid,
+ &psessionEntry->dph.dphHashTable);
+ if (pStaDs == NULL) {
+ lim_log(pMac, LOGE,
+ FL("DISASSOC_CNF for a STA with no context, addr= "
+ MAC_ADDRESS_STR),
+ MAC_ADDR_ARRAY(smeDisassocCnf.peerMacAddr));
+ return;
+ }
+#if defined WLAN_FEATURE_VOWIFI_11R
+ /* Delete FT session if there exists one */
+ lim_ft_cleanup_pre_auth_info(pMac, psessionEntry);
+#endif
+ lim_cleanup_rx_path(pMac, pStaDs, psessionEntry);
+
+ lim_clean_up_disassoc_deauth_req(pMac,
+ (char *)&smeDisassocCnf.peerMacAddr,
+ 0);
+ }
+
+ return;
+}
+
+/**
+ * __lim_process_sme_deauth_req() - process sme deauth req
+ * @mac_ctx: Pointer to Global MAC structure
+ * @msg_buf: pointer to the SME message buffer
+ *
+ * This function is called to process SME_DEAUTH_REQ message
+ * from HDD or upper layer application.
+ *
+ * Return: None
+ */
+
+static void __lim_process_sme_deauth_req(tpAniSirGlobal mac_ctx,
+ uint32_t *msg_buf)
+{
+ uint16_t deauth_trigger, reason_code;
+ tLimMlmDeauthReq *mlm_deauth_req;
+ tSirSmeDeauthReq sme_deauth_req;
+ tSirResultCodes ret_code = eSIR_SME_SUCCESS;
+ tpPESession session_entry;
+ uint8_t session_id; /* PE sessionId */
+ uint8_t sme_session_id;
+ uint16_t sme_transaction_id;
+
+ lim_log(mac_ctx, LOG1, FL("received DEAUTH_REQ message"));
+
+ cdf_mem_copy(&sme_deauth_req, msg_buf, sizeof(tSirSmeDeauthReq));
+ sme_session_id = sme_deauth_req.sessionId;
+ sme_transaction_id = sme_deauth_req.transactionId;
+
+ /*
+ * We need to get a session first but we don't even know
+ * if the message is correct.
+ */
+ session_entry = pe_find_session_by_bssid(mac_ctx, sme_deauth_req.bssId,
+ &session_id);
+ if (session_entry == NULL) {
+ lim_log(mac_ctx, LOGE,
+ FL("session does not exist for given bssId"));
+ ret_code = eSIR_SME_INVALID_PARAMETERS;
+ deauth_trigger = eLIM_HOST_DEAUTH;
+ goto send_deauth;
+ }
+
+ if (!lim_is_sme_deauth_req_valid(mac_ctx, &sme_deauth_req,
+ session_entry)) {
+ lim_log(mac_ctx, LOGE,
+ FL("received invalid SME_DEAUTH_REQ message"));
+ mac_ctx->lim.gLimRspReqd = false;
+
+ ret_code = eSIR_SME_INVALID_PARAMETERS;
+ deauth_trigger = eLIM_HOST_DEAUTH;
+ goto send_deauth;
+ }
+ lim_log(mac_ctx, LOG1,
+ FL("received DEAUTH_REQ sessionid %d Systemrole %d reasoncode %u limSmestate %d from "
+ MAC_ADDRESS_STR), sme_session_id,
+ GET_LIM_SYSTEM_ROLE(session_entry), sme_deauth_req.reasonCode,
+ session_entry->limSmeState,
+ MAC_ADDR_ARRAY(sme_deauth_req.peerMacAddr));
+#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */
+ lim_diag_event_report(mac_ctx, WLAN_PE_DIAG_DEAUTH_REQ_EVENT,
+ session_entry, 0, sme_deauth_req.reasonCode);
+#endif /* FEATURE_WLAN_DIAG_SUPPORT */
+
+ /* Update SME session ID and Transaction ID */
+ session_entry->smeSessionId = sme_session_id;
+ session_entry->transactionId = sme_transaction_id;
+
+ switch (GET_LIM_SYSTEM_ROLE(session_entry)) {
+ case eLIM_STA_ROLE:
+ case eLIM_BT_AMP_STA_ROLE:
+
+ switch (session_entry->limSmeState) {
+ case eLIM_SME_ASSOCIATED_STATE:
+ case eLIM_SME_LINK_EST_STATE:
+ case eLIM_SME_WT_ASSOC_STATE:
+ case eLIM_SME_JOIN_FAILURE_STATE:
+ case eLIM_SME_IDLE_STATE:
+ session_entry->limPrevSmeState =
+ session_entry->limSmeState;
+ session_entry->limSmeState = eLIM_SME_WT_DEAUTH_STATE;
+ MTRACE(mac_trace(mac_ctx, TRACE_CODE_SME_STATE,
+ session_entry->peSessionId,
+ session_entry->limSmeState));
+ /* Send Deauthentication request to MLM below */
+ break;
+ case eLIM_SME_WT_DEAUTH_STATE:
+ case eLIM_SME_WT_DISASSOC_STATE:
+ /*
+ * PE Recieved a Deauth/Disassoc frame. Normally it get
+ * DEAUTH_CNF/DISASSOC_CNF but it received DEAUTH_REQ.
+ * Which means host is also trying to disconnect.
+ * PE can continue processing DEAUTH_REQ and send
+ * the response instead of failing the request.
+ * SME will anyway ignore DEAUTH_IND/DISASSOC_IND that
+ * was sent for deauth/disassoc frame.
+ */
+ session_entry->limSmeState = eLIM_SME_WT_DEAUTH_STATE;
+ lim_log(mac_ctx, LOG1, FL(
+ "Rcvd SME_DEAUTH_REQ while in SME_WT_DEAUTH_STATE"));
+ break;
+ default:
+ /*
+ * STA is not in a state to deauthenticate with
+ * peer. Log error and send response to host.
+ */
+ lim_log(mac_ctx, LOGE, FL(
+ "received unexp SME_DEAUTH_REQ in state %X"),
+ session_entry->limSmeState);
+ lim_print_sme_state(mac_ctx, LOGE,
+ session_entry->limSmeState);
+
+ if (mac_ctx->lim.gLimRspReqd) {
+ mac_ctx->lim.gLimRspReqd = false;
+
+ ret_code = eSIR_SME_STA_NOT_AUTHENTICATED;
+ deauth_trigger = eLIM_HOST_DEAUTH;
+
+ /*
+ * here we received deauth request from AP so sme state
+ * is eLIM_SME_WT_DEAUTH_STATE.if we have ISSUED
+ * delSta then mlm state should be
+ * eLIM_MLM_WT_DEL_STA_RSP_STATE and ifwe got delBSS
+ * rsp then mlm state should be eLIM_MLM_IDLE_STATE
+ * so the below condition captures the state where
+ * delSta not done and firmware still in
+ * connected state.
+ */
+ if (session_entry->limSmeState ==
+ eLIM_SME_WT_DEAUTH_STATE &&
+ session_entry->limMlmState !=
+ eLIM_MLM_IDLE_STATE &&
+ session_entry->limMlmState !=
+ eLIM_MLM_WT_DEL_STA_RSP_STATE)
+ ret_code = eSIR_SME_DEAUTH_STATUS;
+ goto send_deauth;
+ }
+ return;
+ }
+ break;
+
+ case eLIM_STA_IN_IBSS_ROLE:
+ lim_log(mac_ctx, LOGE, FL("Deauth not allowed in IBSS"));
+ if (mac_ctx->lim.gLimRspReqd) {
+ mac_ctx->lim.gLimRspReqd = false;
+ ret_code = eSIR_SME_INVALID_PARAMETERS;
+ deauth_trigger = eLIM_HOST_DEAUTH;
+ goto send_deauth;
+ }
+ return;
+ case eLIM_AP_ROLE:
+ break;
+ default:
+ lim_log(mac_ctx, LOGE,
+ FL("received unexpected SME_DEAUTH_REQ for role %X"),
+ GET_LIM_SYSTEM_ROLE(session_entry));
+ if (mac_ctx->lim.gLimRspReqd) {
+ mac_ctx->lim.gLimRspReqd = false;
+ ret_code = eSIR_SME_INVALID_PARAMETERS;
+ deauth_trigger = eLIM_HOST_DEAUTH;
+ goto send_deauth;
+ }
+ return;
+ } /* end switch (mac_ctx->lim.gLimSystemRole) */
+
+ if (sme_deauth_req.reasonCode == eLIM_LINK_MONITORING_DEAUTH) {
+ /* Deauthentication is triggered by Link Monitoring */
+ lim_log(mac_ctx, LOG1, FL("** Lost link with AP **"));
+ deauth_trigger = eLIM_LINK_MONITORING_DEAUTH;
+ reason_code = eSIR_MAC_UNSPEC_FAILURE_REASON;
+ } else {
+ deauth_trigger = eLIM_HOST_DEAUTH;
+ reason_code = sme_deauth_req.reasonCode;
+ }
+
+ /* Trigger Deauthentication frame to peer MAC entity */
+ mlm_deauth_req = cdf_mem_malloc(sizeof(tLimMlmDeauthReq));
+ if (NULL == mlm_deauth_req) {
+ lim_log(mac_ctx, LOGP,
+ FL("call to AllocateMemory failed for mlmDeauthReq"));
+ if (mac_ctx->lim.gLimRspReqd) {
+ mac_ctx->lim.gLimRspReqd = false;
+ ret_code = eSIR_SME_RESOURCES_UNAVAILABLE;
+ deauth_trigger = eLIM_HOST_DEAUTH;
+ goto send_deauth;
+ }
+ return;
+ }
+
+ cdf_mem_copy((uint8_t *) &mlm_deauth_req->peerMacAddr,
+ (uint8_t *) &sme_deauth_req.peerMacAddr,
+ sizeof(tSirMacAddr));
+
+ mlm_deauth_req->reasonCode = reason_code;
+ mlm_deauth_req->deauthTrigger = deauth_trigger;
+
+ /* Update PE session Id */
+ mlm_deauth_req->sessionId = session_id;
+
+ lim_post_mlm_message(mac_ctx, LIM_MLM_DEAUTH_REQ,
+ (uint32_t *)mlm_deauth_req);
+ return;
+
+send_deauth:
+ lim_send_sme_deauth_ntf(mac_ctx, sme_deauth_req.peerMacAddr, ret_code,
+ deauth_trigger, 1, sme_session_id, sme_transaction_id);
+}
+
+/**
+ * __lim_process_sme_set_context_req()
+ *
+ * @mac_ctx: Pointer to Global MAC structure
+ * @msg_buf: pointer to the SME message buffer
+ *
+ * This function is called to process SME_SETCONTEXT_REQ message
+ * from HDD or upper layer application.
+ *
+ * Return: None
+ */
+
+static void
+__lim_process_sme_set_context_req(tpAniSirGlobal mac_ctx, uint32_t *msg_buf)
+{
+ tpSirSmeSetContextReq set_context_req;
+ tLimMlmSetKeysReq *mlm_set_key_req;
+ tpPESession session_entry;
+ uint8_t session_id; /* PE sessionID */
+ uint8_t sme_session_id;
+ uint16_t sme_transaction_id;
+
+ lim_log(mac_ctx, LOG1, FL("received SETCONTEXT_REQ message"));
+
+ if (msg_buf == NULL) {
+ lim_log(mac_ctx, LOGE, FL("Buffer is Pointing to NULL"));
+ return;
+ }
+
+ set_context_req = cdf_mem_malloc(sizeof(struct sSirSmeSetContextReq));
+ if (NULL == set_context_req) {
+ lim_log(mac_ctx, LOGP, FL(
+ "call to AllocateMemory failed for set_context_req"));
+ return;
+ }
+ cdf_mem_copy(set_context_req, msg_buf,
+ sizeof(struct sSirSmeSetContextReq));
+ sme_session_id = set_context_req->sessionId;
+ sme_transaction_id = set_context_req->transactionId;
+
+ if ((!lim_is_sme_set_context_req_valid(mac_ctx, set_context_req))) {
+ lim_log(mac_ctx, LOGW,
+ FL("received invalid SME_SETCONTEXT_REQ message"));
+ goto end;
+ }
+
+ if (set_context_req->keyMaterial.numKeys >
+ SIR_MAC_MAX_NUM_OF_DEFAULT_KEYS) {
+ lim_log(mac_ctx, LOGE, FL(
+ "numKeys:%d is more than SIR_MAC_MAX_NUM_OF_DEFAULT_KEYS"),
+ set_context_req->keyMaterial.numKeys);
+ lim_send_sme_set_context_rsp(mac_ctx,
+ set_context_req->peerMacAddr, 1,
+ eSIR_SME_INVALID_PARAMETERS, NULL,
+ sme_session_id, sme_transaction_id);
+ goto end;
+ }
+
+ session_entry = pe_find_session_by_bssid(mac_ctx,
+ set_context_req->bssId, &session_id);
+ if (session_entry == NULL) {
+ lim_log(mac_ctx, LOGW,
+ FL("Session does not exist for given BSSID"));
+ lim_send_sme_set_context_rsp(mac_ctx,
+ set_context_req->peerMacAddr, 1,
+ eSIR_SME_INVALID_PARAMETERS, NULL,
+ sme_session_id, sme_transaction_id);
+ goto end;
+ }
+#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */
+ lim_diag_event_report(mac_ctx, WLAN_PE_DIAG_SETCONTEXT_REQ_EVENT,
+ session_entry, 0, 0);
+#endif /* FEATURE_WLAN_DIAG_SUPPORT */
+
+ if (((LIM_IS_STA_ROLE(session_entry) ||
+ LIM_IS_BT_AMP_STA_ROLE(session_entry)) &&
+ (session_entry->limSmeState == eLIM_SME_LINK_EST_STATE)) ||
+ ((LIM_IS_IBSS_ROLE(session_entry) ||
+ LIM_IS_AP_ROLE(session_entry) ||
+ LIM_IS_BT_AMP_AP_ROLE(session_entry)) &&
+ (session_entry->limSmeState == eLIM_SME_NORMAL_STATE))) {
+ /* Trigger MLM_SETKEYS_REQ */
+ mlm_set_key_req = cdf_mem_malloc(sizeof(tLimMlmSetKeysReq));
+ if (NULL == mlm_set_key_req) {
+ lim_log(mac_ctx, LOGP, FL(
+ "mem alloc failed for mlmSetKeysReq"));
+ goto end;
+ }
+ mlm_set_key_req->edType = set_context_req->keyMaterial.edType;
+ mlm_set_key_req->numKeys =
+ set_context_req->keyMaterial.numKeys;
+ if (mlm_set_key_req->numKeys >
+ SIR_MAC_MAX_NUM_OF_DEFAULT_KEYS) {
+ lim_log(mac_ctx, LOGP, FL(
+ "no.of keys exceeded max num of default keys limit"));
+ goto end;
+ }
+ cdf_mem_copy((uint8_t *) &mlm_set_key_req->peerMacAddr,
+ (uint8_t *) &set_context_req->peerMacAddr,
+ sizeof(tSirMacAddr));
+
+ cdf_mem_copy((uint8_t *) &mlm_set_key_req->key,
+ (uint8_t *) &set_context_req->keyMaterial.key,
+ sizeof(tSirKeys) *
+ (mlm_set_key_req->numKeys ? mlm_set_key_req->
+ numKeys : 1));
+
+ mlm_set_key_req->sessionId = session_id;
+ mlm_set_key_req->smesessionId = sme_session_id;
+#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG
+ lim_log(mac_ctx, LOG1, FL(
+ "received SETCONTEXT_REQ message sessionId=%d"),
+ mlm_set_key_req->sessionId);
+#endif
+
+ if (((set_context_req->keyMaterial.edType == eSIR_ED_WEP40) ||
+ (set_context_req->keyMaterial.edType == eSIR_ED_WEP104)) &&
+ LIM_IS_AP_ROLE(session_entry)) {
+ if (set_context_req->keyMaterial.key[0].keyLength) {
+ uint8_t key_id;
+ key_id =
+ set_context_req->keyMaterial.key[0].keyId;
+ cdf_mem_copy((uint8_t *)
+ &session_entry->WEPKeyMaterial[key_id],
+ (uint8_t *) &set_context_req->keyMaterial,
+ sizeof(tSirKeyMaterial));
+ } else {
+ uint32_t i;
+ for (i = 0; i < SIR_MAC_MAX_NUM_OF_DEFAULT_KEYS;
+ i++) {
+ cdf_mem_copy((uint8_t *)
+ &mlm_set_key_req->key[i],
+ (uint8_t *)session_entry->WEPKeyMaterial[i].key,
+ sizeof(tSirKeys));
+ }
+ }
+ }
+ lim_post_mlm_message(mac_ctx, LIM_MLM_SETKEYS_REQ,
+ (uint32_t *) mlm_set_key_req);
+ } else {
+ lim_log(mac_ctx, LOGE, FL(
+ "rcvd unexpected SME_SETCONTEXT_REQ for role %d, state=%X"),
+ GET_LIM_SYSTEM_ROLE(session_entry),
+ session_entry->limSmeState);
+ lim_print_sme_state(mac_ctx, LOGE, session_entry->limSmeState);
+
+ lim_send_sme_set_context_rsp(mac_ctx,
+ set_context_req->peerMacAddr, 1,
+ eSIR_SME_UNEXPECTED_REQ_RESULT_CODE,
+ session_entry, sme_session_id,
+ sme_transaction_id);
+ }
+end:
+ cdf_mem_free(set_context_req);
+ return;
+}
+
+/**
+ * lim_process_sme_get_assoc_sta_info() - process sme assoc sta req
+ *
+ * @mac_ctx: Pointer to Global MAC structure
+ * @msg_buf: pointer to the SME message buffer
+ *
+ * This function is called to process SME_GET_ASSOC_STAS_REQ message
+ * from HDD or upper layer application.
+ *
+ * Return: None
+ */
+
+void lim_process_sme_get_assoc_sta_info(tpAniSirGlobal mac_ctx,
+ uint32_t *msg_buf)
+{
+ tSirSmeGetAssocSTAsReq get_assoc_stas_req;
+ tpDphHashNode sta_ds = NULL;
+ tpPESession session_entry = NULL;
+ tSap_Event sap_event;
+ tpWLAN_SAPEventCB sap_event_cb = NULL;
+ tpSap_AssocMacAddr assoc_sta_tmp = NULL;
+ uint8_t session_id = CSR_SESSION_ID_INVALID;
+ uint8_t assoc_id = 0;
+ uint8_t sta_cnt = 0;
+
+ if (msg_buf == NULL) {
+ lim_log(mac_ctx, LOGE, FL("Buffer is Pointing to NULL"));
+ return;
+ }
+
+ cdf_mem_copy(&get_assoc_stas_req, msg_buf,
+ sizeof(struct sSirSmeGetAssocSTAsReq));
+ /*
+ * Get Associated stations from PE.
+ * Find PE session Entry
+ */
+ session_entry = pe_find_session_by_bssid(mac_ctx,
+ get_assoc_stas_req.bssId,
+ &session_id);
+ if (session_entry == NULL) {
+ lim_log(mac_ctx, LOGE,
+ FL("session does not exist for given bssId"));
+ goto lim_assoc_sta_end;
+ }
+
+ if (!LIM_IS_AP_ROLE(session_entry)) {
+ lim_log(mac_ctx, LOGE, FL(
+ "Received unexpected message in state %X, in role %X"),
+ session_entry->limSmeState,
+ GET_LIM_SYSTEM_ROLE(session_entry));
+ goto lim_assoc_sta_end;
+ }
+ /* Retrieve values obtained in the request message */
+ sap_event_cb = (tpWLAN_SAPEventCB)get_assoc_stas_req.pSapEventCallback;
+ assoc_sta_tmp = (tpSap_AssocMacAddr)get_assoc_stas_req.pAssocStasArray;
+
+ if (NULL == assoc_sta_tmp)
+ goto lim_assoc_sta_end;
+ for (assoc_id = 0; assoc_id < session_entry->dph.dphHashTable.size;
+ assoc_id++) {
+ sta_ds = dph_get_hash_entry(mac_ctx, assoc_id,
+ &session_entry->dph.dphHashTable);
+ if (NULL == sta_ds)
+ continue;
+ if (sta_ds->valid) {
+ cdf_mem_copy((uint8_t *) &assoc_sta_tmp->staMac,
+ (uint8_t *) &sta_ds->staAddr,
+ CDF_MAC_ADDR_SIZE);
+ assoc_sta_tmp->assocId = (uint8_t) sta_ds->assocId;
+ assoc_sta_tmp->staId = (uint8_t) sta_ds->staIndex;
+
+ cdf_mem_copy((uint8_t *)&assoc_sta_tmp->supportedRates,
+ (uint8_t *)&sta_ds->supportedRates,
+ sizeof(tSirSupportedRates));
+ assoc_sta_tmp->ShortGI40Mhz = sta_ds->htShortGI40Mhz;
+ assoc_sta_tmp->ShortGI20Mhz = sta_ds->htShortGI20Mhz;
+ assoc_sta_tmp->Support40Mhz =
+ sta_ds->htDsssCckRate40MHzSupport;
+
+ lim_log(mac_ctx, LOG1, FL("dph Station Number = %d"),
+ sta_cnt + 1);
+ lim_log(mac_ctx, LOG1, FL("MAC = " MAC_ADDRESS_STR),
+ MAC_ADDR_ARRAY(sta_ds->staAddr));
+ lim_log(mac_ctx, LOG1, FL("Association Id = %d"),
+ sta_ds->assocId);
+ lim_log(mac_ctx, LOG1, FL("Station Index = %d"),
+ sta_ds->staIndex);
+ assoc_sta_tmp++;
+ sta_cnt++;
+ }
+ }
+lim_assoc_sta_end:
+ /*
+ * Call hdd callback with sap event to send the list of
+ * associated stations from PE
+ */
+ if (sap_event_cb != NULL) {
+ sap_event.sapHddEventCode = eSAP_ASSOC_STA_CALLBACK_EVENT;
+ sap_event.sapevt.sapAssocStaListEvent.module =
+ CDF_MODULE_ID_PE;
+ sap_event.sapevt.sapAssocStaListEvent.noOfAssocSta = sta_cnt;
+ sap_event.sapevt.sapAssocStaListEvent.pAssocStas =
+ (tpSap_AssocMacAddr)get_assoc_stas_req.pAssocStasArray;
+ sap_event_cb(&sap_event, get_assoc_stas_req.pUsrContext);
+ }
+}
+
+/**
+ * lim_process_sme_get_wpspbc_sessions - process sme get wpspbc req
+ *
+ * @mac_ctx: Pointer to Global MAC structure
+ * @msg_buf: pointer to WPS PBC overlap query message
+ *
+ * This function parses get WPS PBC overlap information
+ * message and call callback to pass WPS PBC overlap
+ * information back to hdd.
+ *
+ * Return: None
+ */
+void lim_process_sme_get_wpspbc_sessions(tpAniSirGlobal mac_ctx,
+ uint32_t *msg_buf)
+{
+ tSirSmeGetWPSPBCSessionsReq get_wps_pbc_sessions_req;
+ tpPESession session_entry = NULL;
+ tSap_Event sap_event;
+ tpWLAN_SAPEventCB sap_event_cb = NULL;
+ uint8_t session_id = CSR_SESSION_ID_INVALID;
+ tSirMacAddr zero_mac = { 0, 0, 0, 0, 0, 0 };
+ tSap_GetWPSPBCSessionEvent *sap_get_wpspbc_event;
+
+ if (msg_buf == NULL) {
+ lim_log(mac_ctx, LOGE, FL("Buffer is Pointing to NULL"));
+ return;
+ }
+
+ sap_get_wpspbc_event = &sap_event.sapevt.sapGetWPSPBCSessionEvent;
+ sap_get_wpspbc_event->status = CDF_STATUS_E_FAULT;
+
+ cdf_mem_copy(&get_wps_pbc_sessions_req, msg_buf,
+ sizeof(struct sSirSmeGetWPSPBCSessionsReq));
+ /*
+ * Get Associated stations from PE
+ * Find PE session Entry
+ */
+ session_entry = pe_find_session_by_bssid(mac_ctx,
+ get_wps_pbc_sessions_req.bssId, &session_id);
+ if (session_entry == NULL) {
+ lim_log(mac_ctx, LOGE,
+ FL("session does not exist for given bssId"));
+ goto lim_get_wpspbc_sessions_end;
+ }
+
+ if (!LIM_IS_AP_ROLE(session_entry)) {
+ lim_log(mac_ctx, LOGE,
+ FL("Received unexpected message in role %X"),
+ GET_LIM_SYSTEM_ROLE(session_entry));
+ goto lim_get_wpspbc_sessions_end;
+ }
+ /*
+ * Call hdd callback with sap event to send the
+ * WPS PBC overlap information
+ */
+ sap_event.sapHddEventCode = eSAP_GET_WPSPBC_SESSION_EVENT;
+ sap_get_wpspbc_event->module = CDF_MODULE_ID_PE;
+
+ if (cdf_mem_compare(zero_mac, get_wps_pbc_sessions_req.pRemoveMac,
+ sizeof(tSirMacAddr))) {
+ lim_get_wpspbc_sessions(mac_ctx,
+ sap_get_wpspbc_event->addr.bytes,
+ sap_get_wpspbc_event->UUID_E,
+ &sap_get_wpspbc_event->wpsPBCOverlap,
+ session_entry);
+ } else {
+ lim_remove_pbc_sessions(mac_ctx,
+ get_wps_pbc_sessions_req.pRemoveMac,
+ session_entry);
+ /* don't have to inform the HDD/Host */
+ return;
+ }
+
+ lim_log(mac_ctx, LOGE, FL("wpsPBCOverlap %d"),
+ sap_get_wpspbc_event->wpsPBCOverlap);
+ lim_print_mac_addr(mac_ctx,
+ sap_get_wpspbc_event->addr.bytes, LOG4);
+
+ sap_get_wpspbc_event->status = CDF_STATUS_SUCCESS;
+
+lim_get_wpspbc_sessions_end:
+ sap_event_cb =
+ (tpWLAN_SAPEventCB)get_wps_pbc_sessions_req.pSapEventCallback;
+ if (NULL != sap_event_cb)
+ sap_event_cb(&sap_event, get_wps_pbc_sessions_req.pUsrContext);
+}
+
+/**
+ * __lim_counter_measures()
+ *
+ * FUNCTION:
+ * This function is called to "implement" MIC counter measure
+ * and is *temporary* only
+ *
+ * LOGIC: on AP, disassoc all STA associated thru TKIP,
+ * we don't do the proper STA disassoc sequence since the
+ * BSS will be stoped anyway
+ *
+ ***ASSUMPTIONS:
+ *
+ ***NOTE:
+ *
+ * @param pMac Pointer to Global MAC structure
+ * @return None
+ */
+
+static void __lim_counter_measures(tpAniSirGlobal pMac, tpPESession psessionEntry)
+{
+ tSirMacAddr mac = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
+ if (LIM_IS_AP_ROLE(psessionEntry) ||
+ LIM_IS_BT_AMP_AP_ROLE(psessionEntry) ||
+ LIM_IS_BT_AMP_STA_ROLE(psessionEntry))
+ lim_send_disassoc_mgmt_frame(pMac, eSIR_MAC_MIC_FAILURE_REASON,
+ mac, psessionEntry, false);
+};
+
+void lim_process_tkip_counter_measures(tpAniSirGlobal pMac, uint32_t *pMsgBuf)
+{
+ tSirSmeTkipCntrMeasReq tkipCntrMeasReq;
+ tpPESession psessionEntry;
+ uint8_t sessionId; /* PE sessionId */
+
+ cdf_mem_copy(&tkipCntrMeasReq, pMsgBuf,
+ sizeof(struct sSirSmeTkipCntrMeasReq));
+
+ psessionEntry = pe_find_session_by_bssid(pMac,
+ tkipCntrMeasReq.bssId,
+ &sessionId);
+ if (NULL == psessionEntry) {
+ lim_log(pMac, LOGE,
+ FL("session does not exist for given BSSID "));
+ return;
+ }
+
+ if (tkipCntrMeasReq.bEnable)
+ __lim_counter_measures(pMac, psessionEntry);
+
+ psessionEntry->bTkipCntrMeasActive = tkipCntrMeasReq.bEnable;
+}
+
+static void
+__lim_handle_sme_stop_bss_request(tpAniSirGlobal pMac, uint32_t *pMsgBuf)
+{
+ tSirSmeStopBssReq stopBssReq;
+ tSirRetStatus status;
+ tLimSmeStates prevState;
+ tpPESession psessionEntry;
+ uint8_t smesessionId;
+ uint8_t sessionId;
+ uint16_t smetransactionId;
+ uint8_t i = 0;
+ tpDphHashNode pStaDs = NULL;
+
+ cdf_mem_copy(&stopBssReq, pMsgBuf, sizeof(tSirSmeStopBssReq));
+ smesessionId = stopBssReq.sessionId;
+ smetransactionId = stopBssReq.transactionId;
+
+ if (!lim_is_sme_stop_bss_req_valid(pMsgBuf)) {
+ PELOGW(lim_log(pMac, LOGW,
+ FL("received invalid SME_STOP_BSS_REQ message"));)
+ /* Send Stop BSS response to host */
+ lim_send_sme_rsp(pMac, eWNI_SME_STOP_BSS_RSP,
+ eSIR_SME_INVALID_PARAMETERS, smesessionId,
+ smetransactionId);
+ return;
+ }
+
+ psessionEntry = pe_find_session_by_bssid(pMac,
+ stopBssReq.bssId,
+ &sessionId);
+ if (psessionEntry == NULL) {
+ lim_log(pMac, LOGW,
+ FL("session does not exist for given BSSID "));
+ lim_send_sme_rsp(pMac, eWNI_SME_STOP_BSS_RSP,
+ eSIR_SME_INVALID_PARAMETERS, smesessionId,
+ smetransactionId);
+ return;
+ }
+#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */
+ lim_diag_event_report(pMac, WLAN_PE_DIAG_STOP_BSS_REQ_EVENT, psessionEntry,
+ 0, 0);
+#endif /* FEATURE_WLAN_DIAG_SUPPORT */
+
+ if (psessionEntry->limSmeState != eLIM_SME_NORMAL_STATE || /* Added For BT -AMP Support */
+ LIM_IS_STA_ROLE(psessionEntry)) {
+ /**
+ * Should not have received STOP_BSS_REQ in states
+ * other than 'normal' state or on STA in Infrastructure
+ * mode. Log error and return response to host.
+ */
+ lim_log(pMac, LOGE,
+ FL
+ ("received unexpected SME_STOP_BSS_REQ in state %X, for role %d"),
+ psessionEntry->limSmeState,
+ GET_LIM_SYSTEM_ROLE(psessionEntry));
+ lim_print_sme_state(pMac, LOGE, psessionEntry->limSmeState);
+ /* / Send Stop BSS response to host */
+ lim_send_sme_rsp(pMac, eWNI_SME_STOP_BSS_RSP,
+ eSIR_SME_UNEXPECTED_REQ_RESULT_CODE, smesessionId,
+ smetransactionId);
+ return;
+ }
+
+ if (LIM_IS_AP_ROLE(psessionEntry))
+ lim_wpspbc_close(pMac, psessionEntry);
+
+ lim_log(pMac, LOGW,
+ FL("RECEIVED STOP_BSS_REQ with reason code=%d"),
+ stopBssReq.reasonCode);
+
+ prevState = psessionEntry->limSmeState;
+
+ psessionEntry->limSmeState = eLIM_SME_IDLE_STATE;
+ MTRACE(mac_trace
+ (pMac, TRACE_CODE_SME_STATE, psessionEntry->peSessionId,
+ psessionEntry->limSmeState));
+
+ /* Update SME session Id and Transaction Id */
+ psessionEntry->smeSessionId = smesessionId;
+ psessionEntry->transactionId = smetransactionId;
+
+ /* BTAMP_STA and STA_IN_IBSS should NOT send Disassoc frame */
+ if (!LIM_IS_IBSS_ROLE(psessionEntry) &&
+ !LIM_IS_BT_AMP_STA_ROLE(psessionEntry)) {
+ tSirMacAddr bcAddr = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
+ if (stopBssReq.reasonCode == eSIR_SME_MIC_COUNTER_MEASURES)
+ /* Send disassoc all stations associated thru TKIP */
+ __lim_counter_measures(pMac, psessionEntry);
+ else
+ lim_send_disassoc_mgmt_frame(pMac,
+ eSIR_MAC_DEAUTH_LEAVING_BSS_REASON,
+ bcAddr, psessionEntry, false);
+ }
+
+ /* Free the buffer allocated in START_BSS_REQ */
+ cdf_mem_free(psessionEntry->addIeParams.probeRespData_buff);
+ psessionEntry->addIeParams.probeRespDataLen = 0;
+ psessionEntry->addIeParams.probeRespData_buff = NULL;
+
+ cdf_mem_free(psessionEntry->addIeParams.assocRespData_buff);
+ psessionEntry->addIeParams.assocRespDataLen = 0;
+ psessionEntry->addIeParams.assocRespData_buff = NULL;
+
+ cdf_mem_free(psessionEntry->addIeParams.probeRespBCNData_buff);
+ psessionEntry->addIeParams.probeRespBCNDataLen = 0;
+ psessionEntry->addIeParams.probeRespBCNData_buff = NULL;
+
+ /* lim_del_bss is also called as part of coalescing, when we send DEL BSS followed by Add Bss msg. */
+ pMac->lim.gLimIbssCoalescingHappened = false;
+
+ for (i = 1; i < pMac->lim.gLimAssocStaLimit; i++) {
+ pStaDs =
+ dph_get_hash_entry(pMac, i, &psessionEntry->dph.dphHashTable);
+ if (NULL == pStaDs)
+ continue;
+ status = lim_del_sta(pMac, pStaDs, false, psessionEntry);
+ if (eSIR_SUCCESS == status) {
+ lim_delete_dph_hash_entry(pMac, pStaDs->staAddr,
+ pStaDs->assocId, psessionEntry);
+ lim_release_peer_idx(pMac, pStaDs->assocId, psessionEntry);
+ } else {
+ lim_log(pMac, LOGE,
+ FL("lim_del_sta failed with Status : %d"), status);
+ CDF_ASSERT(0);
+ }
+ }
+ /* send a delBss to HAL and wait for a response */
+ status = lim_del_bss(pMac, NULL, psessionEntry->bssIdx, psessionEntry);
+
+ if (status != eSIR_SUCCESS) {
+ PELOGE(lim_log
+ (pMac, LOGE, FL("delBss failed for bss %d"),
+ psessionEntry->bssIdx);
+ )
+ psessionEntry->limSmeState = prevState;
+
+ MTRACE(mac_trace
+ (pMac, TRACE_CODE_SME_STATE, psessionEntry->peSessionId,
+ psessionEntry->limSmeState));
+
+ lim_send_sme_rsp(pMac, eWNI_SME_STOP_BSS_RSP,
+ eSIR_SME_STOP_BSS_FAILURE, smesessionId,
+ smetransactionId);
+ }
+}
+
+/**
+ * __lim_process_sme_stop_bss_req() - Process STOP_BSS from SME
+ * @pMac: Global MAC context
+ * @pMsg: Message from SME
+ *
+ * Wrapper for the function __lim_handle_sme_stop_bss_request
+ * This message will be defered until softmac come out of
+ * scan mode. Message should be handled even if we have
+ * detected radar in the current operating channel.
+ *
+ * Return: true - If we consumed the buffer
+ * false - If have defered the message.
+ */
+
+static bool __lim_process_sme_stop_bss_req(tpAniSirGlobal pMac, tpSirMsgQ pMsg)
+{
+ if (__lim_is_defered_msg_for_learn(pMac, pMsg)) {
+ /**
+ * If message defered, buffer is not consumed yet.
+ * So return false
+ */
+ return false;
+ }
+ __lim_handle_sme_stop_bss_request(pMac, (uint32_t *) pMsg->bodyptr);
+ return true;
+} /*** end __lim_process_sme_stop_bss_req() ***/
+
+void lim_process_sme_del_bss_rsp(tpAniSirGlobal pMac,
+ uint32_t body, tpPESession psessionEntry)
+{
+
+ (void)body;
+ SET_LIM_PROCESS_DEFD_MESGS(pMac, true);
+ lim_ibss_delete(pMac, psessionEntry);
+ dph_hash_table_class_init(pMac, &psessionEntry->dph.dphHashTable);
+ lim_delete_pre_auth_list(pMac);
+ lim_send_sme_rsp(pMac, eWNI_SME_STOP_BSS_RSP, eSIR_SME_SUCCESS,
+ psessionEntry->smeSessionId,
+ psessionEntry->transactionId);
+ return;
+}
+
+/**
+ * __lim_process_sme_assoc_cnf_new() - process sme assoc/reassoc cnf
+ *
+ * @mac_ctx: pointer to mac context
+ * @msg_type: message type
+ * @msg_buf: pointer to the SME message buffer
+ *
+ * This function handles SME_ASSOC_CNF/SME_REASSOC_CNF
+ * in BTAMP AP.
+ *
+ * Return: None
+ */
+
+void __lim_process_sme_assoc_cnf_new(tpAniSirGlobal mac_ctx, uint32_t msg_type,
+ uint32_t *msg_buf)
+{
+ tSirSmeAssocCnf assoc_cnf;
+ tpDphHashNode sta_ds = NULL;
+ tpPESession session_entry = NULL;
+ uint8_t session_id;
+ tpSirAssocReq assoc_req;
+
+ if (msg_buf == NULL) {
+ lim_log(mac_ctx, LOGE, FL("msg_buf is NULL "));
+ goto end;
+ }
+
+ cdf_mem_copy(&assoc_cnf, msg_buf, sizeof(struct sSirSmeAssocCnf));
+ if (!__lim_is_sme_assoc_cnf_valid(&assoc_cnf)) {
+ lim_log(mac_ctx, LOGE,
+ FL("Received invalid SME_RE(ASSOC)_CNF message "));
+ goto end;
+ }
+
+ session_entry = pe_find_session_by_bssid(mac_ctx, assoc_cnf.bssId,
+ &session_id);
+ if (session_entry == NULL) {
+ lim_log(mac_ctx, LOGE,
+ FL("session does not exist for given bssId"));
+ goto end;
+ }
+
+ if ((!LIM_IS_AP_ROLE(session_entry) &&
+ !LIM_IS_BT_AMP_AP_ROLE(session_entry)) ||
+ ((session_entry->limSmeState != eLIM_SME_NORMAL_STATE) &&
+ (session_entry->limSmeState !=
+ eLIM_SME_NORMAL_CHANNEL_SCAN_STATE))) {
+ lim_log(mac_ctx, LOGE, FL(
+ "Rcvd unexpected msg %X in state %X, in role %X"),
+ msg_type, session_entry->limSmeState,
+ GET_LIM_SYSTEM_ROLE(session_entry));
+ goto end;
+ }
+ sta_ds = dph_get_hash_entry(mac_ctx, assoc_cnf.aid,
+ &session_entry->dph.dphHashTable);
+ if (sta_ds == NULL) {
+ lim_log(mac_ctx, LOGE, FL(
+ "Rcvd invalid msg %X due to no STA ctx, aid %d, peer "),
+ msg_type, assoc_cnf.aid);
+ lim_print_mac_addr(mac_ctx, assoc_cnf.peerMacAddr, LOG1);
+
+ /*
+ * send a DISASSOC_IND message to WSM to make sure
+ * the state in WSM and LIM is the same
+ */
+ lim_send_sme_disassoc_ntf(mac_ctx, assoc_cnf.peerMacAddr,
+ eSIR_SME_STA_NOT_ASSOCIATED,
+ eLIM_PEER_ENTITY_DISASSOC, assoc_cnf.aid,
+ session_entry->smeSessionId,
+ session_entry->transactionId,
+ session_entry);
+ goto end;
+ }
+ if (!cdf_mem_compare((uint8_t *)sta_ds->staAddr,
+ (uint8_t *) assoc_cnf.peerMacAddr,
+ sizeof(tSirMacAddr))) {
+ lim_log(mac_ctx, LOG1, FL(
+ "peerMacAddr mismatched for aid %d, peer "),
+ assoc_cnf.aid);
+ lim_print_mac_addr(mac_ctx, assoc_cnf.peerMacAddr, LOG1);
+ goto end;
+ }
+
+ if ((sta_ds->mlmStaContext.mlmState != eLIM_MLM_WT_ASSOC_CNF_STATE) ||
+ ((sta_ds->mlmStaContext.subType == LIM_ASSOC) &&
+ (msg_type != eWNI_SME_ASSOC_CNF)) ||
+ ((sta_ds->mlmStaContext.subType == LIM_REASSOC) &&
+ (msg_type != eWNI_SME_ASSOC_CNF))) {
+ lim_log(mac_ctx, LOG1, FL(
+ "not in MLM_WT_ASSOC_CNF_STATE, for aid %d, peer"
+ "StaD mlmState : %d"),
+ assoc_cnf.aid, sta_ds->mlmStaContext.mlmState);
+ lim_print_mac_addr(mac_ctx, assoc_cnf.peerMacAddr, LOG1);
+ goto end;
+ }
+ /*
+ * Deactivate/delet CNF_WAIT timer since ASSOC_CNF
+ * has been received
+ */
+ lim_log(mac_ctx, LOG1, FL("Received SME_ASSOC_CNF. Delete Timer"));
+ lim_deactivate_and_change_per_sta_id_timer(mac_ctx,
+ eLIM_CNF_WAIT_TIMER, sta_ds->assocId);
+
+ if (assoc_cnf.statusCode == eSIR_SME_SUCCESS) {
+ /*
+ * In BTAMP-AP, PE already finished the WMA_ADD_STA sequence
+ * when it had received Assoc Request frame. Now, PE just needs
+ * to send association rsp frame to the requesting BTAMP-STA.
+ */
+ sta_ds->mlmStaContext.mlmState =
+ eLIM_MLM_LINK_ESTABLISHED_STATE;
+ lim_log(mac_ctx, LOG1,
+ FL("sending Assoc Rsp frame to STA (assoc id=%d) "),
+ sta_ds->assocId);
+ lim_send_assoc_rsp_mgmt_frame(mac_ctx, eSIR_SUCCESS,
+ sta_ds->assocId, sta_ds->staAddr,
+ sta_ds->mlmStaContext.subType, sta_ds,
+ session_entry);
+ goto end;
+ } else {
+ /*
+ * SME_ASSOC_CNF status is non-success, so STA is not allowed
+ * to be associated since the HAL sta entry is created for
+ * denied STA we need to remove this HAL entry.
+ * So to do that set updateContext to 1
+ */
+ if (!sta_ds->mlmStaContext.updateContext)
+ sta_ds->mlmStaContext.updateContext = 1;
+ lim_log(mac_ctx, LOG1,
+ FL("Recv Assoc Cnf, status Code : %d(assoc id=%d) "),
+ assoc_cnf.statusCode, sta_ds->assocId);
+ lim_reject_association(mac_ctx, sta_ds->staAddr,
+ sta_ds->mlmStaContext.subType,
+ true, sta_ds->mlmStaContext.authType,
+ sta_ds->assocId, true,
+ eSIR_MAC_UNSPEC_FAILURE_STATUS,
+ session_entry);
+ }
+end:
+ if (((session_entry != NULL) && (sta_ds != NULL)) &&
+ (session_entry->parsedAssocReq[sta_ds->assocId] != NULL)) {
+ assoc_req = (tpSirAssocReq)
+ session_entry->parsedAssocReq[sta_ds->assocId];
+ if (assoc_req->assocReqFrame) {
+ cdf_mem_free(assoc_req->assocReqFrame);
+ assoc_req->assocReqFrame = NULL;
+ }
+ cdf_mem_free(session_entry->parsedAssocReq[sta_ds->assocId]);
+ session_entry->parsedAssocReq[sta_ds->assocId] = NULL;
+ }
+}
+
+static void __lim_process_sme_addts_req(tpAniSirGlobal pMac, uint32_t *pMsgBuf)
+{
+ tpDphHashNode pStaDs;
+ tSirMacAddr peerMac;
+ tpSirAddtsReq pSirAddts;
+ uint32_t timeout;
+ tpPESession psessionEntry;
+ uint8_t sessionId; /* PE sessionId */
+ uint8_t smesessionId;
+ uint16_t smetransactionId;
+
+ if (pMsgBuf == NULL) {
+ lim_log(pMac, LOGE, FL("Buffer is Pointing to NULL"));
+ return;
+ }
+
+ lim_get_session_info(pMac, (uint8_t *) pMsgBuf, &smesessionId,
+ &smetransactionId);
+
+ pSirAddts = (tpSirAddtsReq) pMsgBuf;
+
+ psessionEntry = pe_find_session_by_bssid(pMac,
+ pSirAddts->bssId,
+ &sessionId);
+ if (psessionEntry == NULL) {
+ lim_log(pMac, LOGE, "Session Does not exist for given bssId");
+ return;
+ }
+#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */
+ lim_diag_event_report(pMac, WLAN_PE_DIAG_ADDTS_REQ_EVENT, psessionEntry, 0,
+ 0);
+#endif /* FEATURE_WLAN_DIAG_SUPPORT */
+
+ /* if sta
+ * - verify assoc state
+ * - send addts request to ap
+ * - wait for addts response from ap
+ * if ap, just ignore with error log
+ */
+ PELOG1(lim_log(pMac, LOG1,
+ FL("Received SME_ADDTS_REQ (TSid %d, UP %d)"),
+ pSirAddts->req.tspec.tsinfo.traffic.tsid,
+ pSirAddts->req.tspec.tsinfo.traffic.userPrio);
+ )
+
+ if (!LIM_IS_STA_ROLE(psessionEntry) &&
+ !LIM_IS_BT_AMP_STA_ROLE(psessionEntry)) {
+ PELOGE(lim_log(pMac, LOGE, "AddTs received on AP - ignoring");)
+ lim_send_sme_addts_rsp(pMac, pSirAddts->rspReqd, eSIR_FAILURE,
+ psessionEntry, pSirAddts->req.tspec,
+ smesessionId, smetransactionId);
+ return;
+ }
+ /* Ignore the request if STA is in 11B mode. */
+ if (psessionEntry->dot11mode == WNI_CFG_DOT11_MODE_11B) {
+ PELOGE(lim_log
+ (pMac, LOGE,
+ "AddTS received while Dot11Mode is 11B - ignoring");
+ )
+ lim_send_sme_addts_rsp(pMac, pSirAddts->rspReqd, eSIR_FAILURE,
+ psessionEntry, pSirAddts->req.tspec,
+ smesessionId, smetransactionId);
+ return;
+ }
+
+ pStaDs =
+ dph_get_hash_entry(pMac, DPH_STA_HASH_INDEX_PEER,
+ &psessionEntry->dph.dphHashTable);
+
+ if (pStaDs == NULL) {
+ PELOGE(lim_log
+ (pMac, LOGE, "Cannot find AP context for addts req");
+ )
+ lim_send_sme_addts_rsp(pMac, pSirAddts->rspReqd, eSIR_FAILURE,
+ psessionEntry, pSirAddts->req.tspec,
+ smesessionId, smetransactionId);
+ return;
+ }
+
+ if ((!pStaDs->valid) || (pStaDs->mlmStaContext.mlmState !=
+ eLIM_MLM_LINK_ESTABLISHED_STATE)) {
+ lim_log(pMac, LOGE, "AddTs received in invalid MLM state");
+ lim_send_sme_addts_rsp(pMac, pSirAddts->rspReqd, eSIR_FAILURE,
+ psessionEntry, pSirAddts->req.tspec,
+ smesessionId, smetransactionId);
+ return;
+ }
+
+ pSirAddts->req.wsmTspecPresent = 0;
+ pSirAddts->req.wmeTspecPresent = 0;
+ pSirAddts->req.lleTspecPresent = 0;
+
+ if ((pStaDs->wsmEnabled) &&
+ (pSirAddts->req.tspec.tsinfo.traffic.accessPolicy !=
+ SIR_MAC_ACCESSPOLICY_EDCA))
+ pSirAddts->req.wsmTspecPresent = 1;
+ else if (pStaDs->wmeEnabled)
+ pSirAddts->req.wmeTspecPresent = 1;
+ else if (pStaDs->lleEnabled)
+ pSirAddts->req.lleTspecPresent = 1;
+ else {
+ PELOGW(lim_log
+ (pMac, LOGW, FL("ADDTS_REQ ignore - qos is disabled"));
+ )
+ lim_send_sme_addts_rsp(pMac, pSirAddts->rspReqd, eSIR_FAILURE,
+ psessionEntry, pSirAddts->req.tspec,
+ smesessionId, smetransactionId);
+ return;
+ }
+
+ if ((psessionEntry->limSmeState != eLIM_SME_ASSOCIATED_STATE) &&
+ (psessionEntry->limSmeState != eLIM_SME_LINK_EST_STATE)) {
+ lim_log(pMac, LOGE,
+ "AddTs received in invalid LIMsme state (%d)",
+ psessionEntry->limSmeState);
+ lim_send_sme_addts_rsp(pMac, pSirAddts->rspReqd, eSIR_FAILURE,
+ psessionEntry, pSirAddts->req.tspec,
+ smesessionId, smetransactionId);
+ return;
+ }
+
+ if (pMac->lim.gLimAddtsSent) {
+ lim_log(pMac, LOGE,
+ "Addts (token %d, tsid %d, up %d) is still pending",
+ pMac->lim.gLimAddtsReq.req.dialogToken,
+ pMac->lim.gLimAddtsReq.req.tspec.tsinfo.traffic.tsid,
+ pMac->lim.gLimAddtsReq.req.tspec.tsinfo.traffic.
+ userPrio);
+ lim_send_sme_addts_rsp(pMac, pSirAddts->rspReqd, eSIR_FAILURE,
+ psessionEntry, pSirAddts->req.tspec,
+ smesessionId, smetransactionId);
+ return;
+ }
+
+ sir_copy_mac_addr(peerMac, psessionEntry->bssId);
+
+ /* save the addts request */
+ pMac->lim.gLimAddtsSent = true;
+ cdf_mem_copy((uint8_t *) &pMac->lim.gLimAddtsReq,
+ (uint8_t *) pSirAddts, sizeof(tSirAddtsReq));
+
+ /* ship out the message now */
+ lim_send_addts_req_action_frame(pMac, peerMac, &pSirAddts->req,
+ psessionEntry);
+ PELOG1(lim_log(pMac, LOG1, "Sent ADDTS request");)
+ /* start a timer to wait for the response */
+ if (pSirAddts->timeout)
+ timeout = pSirAddts->timeout;
+ else if (wlan_cfg_get_int(pMac, WNI_CFG_ADDTS_RSP_TIMEOUT, &timeout) !=
+ eSIR_SUCCESS) {
+ lim_log(pMac, LOGP,
+ FL("Unable to get Cfg param %d (Addts Rsp Timeout)"),
+ WNI_CFG_ADDTS_RSP_TIMEOUT);
+ return;
+ }
+
+ timeout = SYS_MS_TO_TICKS(timeout);
+ if (tx_timer_change(&pMac->lim.limTimers.gLimAddtsRspTimer, timeout, 0)
+ != TX_SUCCESS) {
+ lim_log(pMac, LOGP, FL("AddtsRsp timer change failed!"));
+ return;
+ }
+ pMac->lim.gLimAddtsRspTimerCount++;
+ if (tx_timer_change_context(&pMac->lim.limTimers.gLimAddtsRspTimer,
+ pMac->lim.gLimAddtsRspTimerCount) !=
+ TX_SUCCESS) {
+ lim_log(pMac, LOGP, FL("AddtsRsp timer change failed!"));
+ return;
+ }
+ MTRACE(mac_trace
+ (pMac, TRACE_CODE_TIMER_ACTIVATE, psessionEntry->peSessionId,
+ eLIM_ADDTS_RSP_TIMER));
+
+ /* add the sessionId to the timer object */
+ pMac->lim.limTimers.gLimAddtsRspTimer.sessionId = sessionId;
+ if (tx_timer_activate(&pMac->lim.limTimers.gLimAddtsRspTimer) !=
+ TX_SUCCESS) {
+ lim_log(pMac, LOGP, FL("AddtsRsp timer activation failed!"));
+ return;
+ }
+ return;
+}
+
+static void __lim_process_sme_delts_req(tpAniSirGlobal pMac, uint32_t *pMsgBuf)
+{
+ tSirMacAddr peerMacAddr;
+ uint8_t ac;
+ tSirMacTSInfo *pTsinfo;
+ tpSirDeltsReq pDeltsReq = (tpSirDeltsReq) pMsgBuf;
+ tpDphHashNode pStaDs = NULL;
+ tpPESession psessionEntry;
+ uint8_t sessionId;
+ uint32_t status = eSIR_SUCCESS;
+ uint8_t smesessionId;
+ uint16_t smetransactionId;
+
+ lim_get_session_info(pMac, (uint8_t *) pMsgBuf, &smesessionId,
+ &smetransactionId);
+
+ psessionEntry = pe_find_session_by_bssid(pMac,
+ pDeltsReq->bssId,
+ &sessionId);
+ if (psessionEntry == NULL) {
+ lim_log(pMac, LOGE, "Session Does not exist for given bssId");
+ status = eSIR_FAILURE;
+ goto end;
+ }
+#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */
+ lim_diag_event_report(pMac, WLAN_PE_DIAG_DELTS_REQ_EVENT, psessionEntry, 0,
+ 0);
+#endif /* FEATURE_WLAN_DIAG_SUPPORT */
+
+ if (eSIR_SUCCESS !=
+ lim_validate_delts_req(pMac, pDeltsReq, peerMacAddr, psessionEntry)) {
+ PELOGE(lim_log(pMac, LOGE, FL("lim_validate_delts_req failed"));)
+ status = eSIR_FAILURE;
+ lim_send_sme_delts_rsp(pMac, pDeltsReq, eSIR_FAILURE, psessionEntry,
+ smesessionId, smetransactionId);
+ return;
+ }
+
+ lim_log(pMac, LOG1,
+ FL("Sent DELTS request to station with assocId = %d MacAddr = "
+ MAC_ADDRESS_STR),
+ pDeltsReq->aid, MAC_ADDR_ARRAY(peerMacAddr));
+
+ lim_send_delts_req_action_frame(pMac, peerMacAddr,
+ pDeltsReq->req.wmeTspecPresent,
+ &pDeltsReq->req.tsinfo,
+ &pDeltsReq->req.tspec, psessionEntry);
+
+ pTsinfo =
+ pDeltsReq->req.wmeTspecPresent ? &pDeltsReq->req.tspec.
+ tsinfo : &pDeltsReq->req.tsinfo;
+
+ /* We've successfully send DELTS frame to AP. Update the
+ * dynamic UAPSD mask. The AC for this TSPEC to be deleted
+ * is no longer trigger enabled or delivery enabled
+ */
+ lim_set_tspec_uapsd_mask_per_session(pMac, psessionEntry,
+ pTsinfo, CLEAR_UAPSD_MASK);
+
+ /* We're deleting the TSPEC, so this particular AC is no longer
+ * admitted. PE needs to downgrade the EDCA
+ * parameters(for the AC for which TS is being deleted) to the
+ * next best AC for which ACM is not enabled, and send the
+ * updated values to HAL.
+ */
+ ac = upToAc(pTsinfo->traffic.userPrio);
+
+ if (pTsinfo->traffic.direction == SIR_MAC_DIRECTION_UPLINK) {
+ psessionEntry->gAcAdmitMask[SIR_MAC_DIRECTION_UPLINK] &=
+ ~(1 << ac);
+ } else if (pTsinfo->traffic.direction ==
+ SIR_MAC_DIRECTION_DNLINK) {
+ psessionEntry->gAcAdmitMask[SIR_MAC_DIRECTION_DNLINK] &=
+ ~(1 << ac);
+ } else if (pTsinfo->traffic.direction ==
+ SIR_MAC_DIRECTION_BIDIR) {
+ psessionEntry->gAcAdmitMask[SIR_MAC_DIRECTION_UPLINK] &=
+ ~(1 << ac);
+ psessionEntry->gAcAdmitMask[SIR_MAC_DIRECTION_DNLINK] &=
+ ~(1 << ac);
+ }
+
+ lim_set_active_edca_params(pMac, psessionEntry->gLimEdcaParams,
+ psessionEntry);
+
+ pStaDs =
+ dph_get_hash_entry(pMac, DPH_STA_HASH_INDEX_PEER,
+ &psessionEntry->dph.dphHashTable);
+ if (pStaDs != NULL) {
+ lim_send_edca_params(pMac, psessionEntry->gLimEdcaParamsActive,
+ pStaDs->bssId);
+ status = eSIR_SUCCESS;
+ } else {
+ lim_log(pMac, LOGE, FL("Self entry missing in Hash Table "));
+ status = eSIR_FAILURE;
+ }
+#ifdef FEATURE_WLAN_ESE
+#ifdef FEATURE_WLAN_ESE_UPLOAD
+ lim_send_sme_tsm_ie_ind(pMac, psessionEntry, 0, 0, 0);
+#else
+ lim_deactivate_and_change_timer(pMac, eLIM_TSM_TIMER);
+#endif /* FEATURE_WLAN_ESE_UPLOAD */
+#endif
+
+ /* send an sme response back */
+end:
+ lim_send_sme_delts_rsp(pMac, pDeltsReq, eSIR_SUCCESS, psessionEntry,
+ smesessionId, smetransactionId);
+}
+
+void lim_process_sme_addts_rsp_timeout(tpAniSirGlobal pMac, uint32_t param)
+{
+ /* fetch the sessionEntry based on the sessionId */
+ tpPESession psessionEntry;
+ psessionEntry = pe_find_session_by_session_id(pMac,
+ pMac->lim.limTimers.gLimAddtsRspTimer.
+ sessionId);
+ if (psessionEntry == NULL) {
+ lim_log(pMac, LOGP,
+ FL("Session Does not exist for given sessionID"));
+ return;
+ }
+
+ if (!LIM_IS_STA_ROLE(psessionEntry) &&
+ !LIM_IS_BT_AMP_STA_ROLE(psessionEntry)) {
+ lim_log(pMac, LOGW, "AddtsRspTimeout in non-Sta role (%d)",
+ GET_LIM_SYSTEM_ROLE(psessionEntry));
+ pMac->lim.gLimAddtsSent = false;
+ return;
+ }
+
+ if (!pMac->lim.gLimAddtsSent) {
+ lim_log(pMac, LOGW, "AddtsRspTimeout but no AddtsSent");
+ return;
+ }
+
+ if (param != pMac->lim.gLimAddtsRspTimerCount) {
+ lim_log(pMac, LOGE,
+ FL("Invalid AddtsRsp Timer count %d (exp %d)"), param,
+ pMac->lim.gLimAddtsRspTimerCount);
+ return;
+ }
+ /* this a real response timeout */
+ pMac->lim.gLimAddtsSent = false;
+ pMac->lim.gLimAddtsRspTimerCount++;
+
+ lim_send_sme_addts_rsp(pMac, true, eSIR_SME_ADDTS_RSP_TIMEOUT,
+ psessionEntry, pMac->lim.gLimAddtsReq.req.tspec,
+ psessionEntry->smeSessionId,
+ psessionEntry->transactionId);
+}
+
+/**
+ * __lim_process_sme_get_statistics_request()
+ *
+ ***FUNCTION:
+ *
+ *
+ ***NOTE:
+ *
+ * @param pMac Pointer to Global MAC structure
+ * @param *pMsgBuf A pointer to the SME message buffer
+ * @return None
+ */
+static void
+__lim_process_sme_get_statistics_request(tpAniSirGlobal pMac, uint32_t *pMsgBuf)
+{
+ tpAniGetPEStatsReq pPEStatsReq;
+ tSirMsgQ msgQ;
+
+ pPEStatsReq = (tpAniGetPEStatsReq) pMsgBuf;
+
+ msgQ.type = WMA_GET_STATISTICS_REQ;
+
+ msgQ.reserved = 0;
+ msgQ.bodyptr = pMsgBuf;
+ msgQ.bodyval = 0;
+ MTRACE(mac_trace_msg_tx(pMac, NO_SESSION, msgQ.type));
+
+ if (eSIR_SUCCESS != (wma_post_ctrl_msg(pMac, &msgQ))) {
+ cdf_mem_free(pMsgBuf);
+ pMsgBuf = NULL;
+ lim_log(pMac, LOGP, "Unable to forward request");
+ return;
+ }
+
+ return;
+}
+
+#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
+/**
+ *FUNCTION: __lim_process_sme_get_tsm_stats_request()
+ *
+ ***NOTE:
+ *
+ * @param pMac Pointer to Global MAC structure
+ * @param *pMsgBuf A pointer to the SME message buffer
+ * @return None
+ */
+static void
+__lim_process_sme_get_tsm_stats_request(tpAniSirGlobal pMac, uint32_t *pMsgBuf)
+{
+ tSirMsgQ msgQ;
+
+ msgQ.type = WMA_TSM_STATS_REQ;
+ msgQ.reserved = 0;
+ msgQ.bodyptr = pMsgBuf;
+ msgQ.bodyval = 0;
+ MTRACE(mac_trace_msg_tx(pMac, NO_SESSION, msgQ.type));
+
+ if (eSIR_SUCCESS != (wma_post_ctrl_msg(pMac, &msgQ))) {
+ cdf_mem_free(pMsgBuf);
+ pMsgBuf = NULL;
+ lim_log(pMac, LOGP, "Unable to forward request");
+ return;
+ }
+}
+#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
+
+static void
+__lim_process_sme_update_apwpsi_es(tpAniSirGlobal pMac, uint32_t *pMsgBuf)
+{
+ tpSirUpdateAPWPSIEsReq pUpdateAPWPSIEsReq;
+ tpPESession psessionEntry;
+ uint8_t sessionId; /* PE sessionID */
+
+ PELOG1(lim_log(pMac, LOG1, FL("received UPDATE_APWPSIEs_REQ message")););
+
+ if (pMsgBuf == NULL) {
+ lim_log(pMac, LOGE, FL("Buffer is Pointing to NULL"));
+ return;
+ }
+
+ pUpdateAPWPSIEsReq = cdf_mem_malloc(sizeof(tSirUpdateAPWPSIEsReq));
+ if (NULL == pUpdateAPWPSIEsReq) {
+ lim_log(pMac, LOGP,
+ FL
+ ("call to AllocateMemory failed for pUpdateAPWPSIEsReq"));
+ return;
+ }
+ cdf_mem_copy(pUpdateAPWPSIEsReq, pMsgBuf,
+ sizeof(struct sSirUpdateAPWPSIEsReq));
+
+ psessionEntry = pe_find_session_by_bssid(pMac,
+ pUpdateAPWPSIEsReq->bssId,
+ &sessionId);
+ if (psessionEntry == NULL) {
+ lim_log(pMac, LOGW,
+ FL("Session does not exist for given BSSID"));
+ goto end;
+ }
+
+ cdf_mem_copy(&psessionEntry->APWPSIEs, &pUpdateAPWPSIEsReq->APWPSIEs,
+ sizeof(tSirAPWPSIEs));
+
+ sch_set_fixed_beacon_fields(pMac, psessionEntry);
+ lim_send_beacon_ind(pMac, psessionEntry);
+
+end:
+ cdf_mem_free(pUpdateAPWPSIEsReq);
+ return;
+}
+
+void
+lim_send_vdev_restart(tpAniSirGlobal pMac,
+ tpPESession psessionEntry, uint8_t sessionId)
+{
+ tpHalHiddenSsidVdevRestart pHalHiddenSsidVdevRestart = NULL;
+ tSirMsgQ msgQ;
+ tSirRetStatus retCode = eSIR_SUCCESS;
+
+ if (psessionEntry == NULL) {
+ PELOGE(lim_log
+ (pMac, LOGE, "%s:%d: Invalid parameters", __func__,
+ __LINE__);
+ )
+ return;
+ }
+
+ pHalHiddenSsidVdevRestart =
+ cdf_mem_malloc(sizeof(tHalHiddenSsidVdevRestart));
+ if (NULL == pHalHiddenSsidVdevRestart) {
+ PELOGE(lim_log
+ (pMac, LOGE, "%s:%d: Unable to allocate memory",
+ __func__, __LINE__);
+ )
+ return;
+ }
+
+ pHalHiddenSsidVdevRestart->ssidHidden = psessionEntry->ssidHidden;
+ pHalHiddenSsidVdevRestart->sessionId = sessionId;
+
+ msgQ.type = WMA_HIDDEN_SSID_VDEV_RESTART;
+ msgQ.bodyptr = pHalHiddenSsidVdevRestart;
+ msgQ.bodyval = 0;
+
+ retCode = wma_post_ctrl_msg(pMac, &msgQ);
+ if (eSIR_SUCCESS != retCode) {
+ PELOGE(lim_log
+ (pMac, LOGE, "%s:%d: wma_post_ctrl_msg() failed", __func__,
+ __LINE__);
+ )
+ cdf_mem_free(pHalHiddenSsidVdevRestart);
+ }
+}
+
+static void __lim_process_sme_hide_ssid(tpAniSirGlobal pMac, uint32_t *pMsgBuf)
+{
+ tpSirUpdateParams pUpdateParams;
+ tpPESession psessionEntry;
+
+ PELOG1(lim_log(pMac, LOG1, FL("received HIDE_SSID message")););
+
+ if (pMsgBuf == NULL) {
+ lim_log(pMac, LOGE, FL("Buffer is Pointing to NULL"));
+ return;
+ }
+
+ pUpdateParams = (tpSirUpdateParams) pMsgBuf;
+
+ psessionEntry = pe_find_session_by_session_id(pMac,
+ pUpdateParams->sessionId);
+ if (psessionEntry == NULL) {
+ lim_log(pMac, LOGW,
+ "Session does not exist for given sessionId %d",
+ pUpdateParams->sessionId);
+ return;
+ }
+
+ /* Update the session entry */
+ psessionEntry->ssidHidden = pUpdateParams->ssidHidden;
+
+ /* Send vdev restart */
+ lim_send_vdev_restart(pMac, psessionEntry, pUpdateParams->sessionId);
+
+ /* Update beacon */
+ sch_set_fixed_beacon_fields(pMac, psessionEntry);
+ lim_send_beacon_ind(pMac, psessionEntry);
+
+ return;
+} /*** end __lim_process_sme_hide_ssid(tpAniSirGlobal pMac, uint32_t *pMsgBuf) ***/
+
+static void __lim_process_sme_set_wparsni_es(tpAniSirGlobal pMac, uint32_t *pMsgBuf)
+{
+ tpSirUpdateAPWPARSNIEsReq pUpdateAPWPARSNIEsReq;
+ tpPESession psessionEntry;
+ uint8_t sessionId; /* PE sessionID */
+
+ if (pMsgBuf == NULL) {
+ lim_log(pMac, LOGE, FL("Buffer is Pointing to NULL"));
+ return;
+ }
+
+ pUpdateAPWPARSNIEsReq = cdf_mem_malloc(sizeof(tSirUpdateAPWPSIEsReq));
+ if (NULL == pUpdateAPWPARSNIEsReq) {
+ lim_log(pMac, LOGP,
+ FL
+ ("call to AllocateMemory failed for pUpdateAPWPARSNIEsReq"));
+ return;
+ }
+ cdf_mem_copy(pUpdateAPWPARSNIEsReq, pMsgBuf,
+ sizeof(struct sSirUpdateAPWPARSNIEsReq));
+
+ psessionEntry = pe_find_session_by_bssid(pMac,
+ pUpdateAPWPARSNIEsReq->bssId,
+ &sessionId);
+ if (psessionEntry == NULL) {
+ lim_log(pMac, LOGW,
+ FL("Session does not exist for given BSSID"));
+ goto end;
+ }
+
+ cdf_mem_copy(&psessionEntry->pLimStartBssReq->rsnIE,
+ &pUpdateAPWPARSNIEsReq->APWPARSNIEs, sizeof(tSirRSNie));
+
+ lim_set_rs_nie_wp_aiefrom_sme_start_bss_req_message(pMac,
+ &psessionEntry->
+ pLimStartBssReq->rsnIE,
+ psessionEntry);
+
+ psessionEntry->pLimStartBssReq->privacy = 1;
+ psessionEntry->privacy = 1;
+
+ sch_set_fixed_beacon_fields(pMac, psessionEntry);
+ lim_send_beacon_ind(pMac, psessionEntry);
+
+end:
+ cdf_mem_free(pUpdateAPWPARSNIEsReq);
+ return;
+} /*** end __lim_process_sme_set_wparsni_es(tpAniSirGlobal pMac, uint32_t *pMsgBuf) ***/
+
+/*
+ Update the beacon Interval dynamically if beaconInterval is different in MCC
+ */
+static void __lim_process_sme_change_bi(tpAniSirGlobal pMac, uint32_t *pMsgBuf)
+{
+ tpSirChangeBIParams pChangeBIParams;
+ tpPESession psessionEntry;
+ uint8_t sessionId = 0;
+ tUpdateBeaconParams beaconParams;
+
+ PELOG1(lim_log(pMac, LOG1,
+ FL("received Update Beacon Interval message"));
+ );
+
+ if (pMsgBuf == NULL) {
+ lim_log(pMac, LOGE, FL("Buffer is Pointing to NULL"));
+ return;
+ }
+
+ cdf_mem_zero(&beaconParams, sizeof(tUpdateBeaconParams));
+ pChangeBIParams = (tpSirChangeBIParams) pMsgBuf;
+
+ psessionEntry = pe_find_session_by_bssid(pMac,
+ pChangeBIParams->bssId,
+ &sessionId);
+ if (psessionEntry == NULL) {
+ lim_log(pMac, LOGE,
+ FL("Session does not exist for given BSSID"));
+ return;
+ }
+
+ /*Update sessionEntry Beacon Interval */
+ if (psessionEntry->beaconParams.beaconInterval !=
+ pChangeBIParams->beaconInterval) {
+ psessionEntry->beaconParams.beaconInterval =
+ pChangeBIParams->beaconInterval;
+ }
+
+ /*Update sch beaconInterval */
+ if (pMac->sch.schObject.gSchBeaconInterval !=
+ pChangeBIParams->beaconInterval) {
+ pMac->sch.schObject.gSchBeaconInterval =
+ pChangeBIParams->beaconInterval;
+
+ PELOG1(lim_log(pMac, LOG1,
+ FL
+ ("LIM send update BeaconInterval Indication : %d"),
+ pChangeBIParams->beaconInterval);
+ );
+
+ if (false == pMac->sap.SapDfsInfo.is_dfs_cac_timer_running) {
+ /* Update beacon */
+ sch_set_fixed_beacon_fields(pMac, psessionEntry);
+
+ beaconParams.bssIdx = psessionEntry->bssIdx;
+ /* Set change in beacon Interval */
+ beaconParams.beaconInterval =
+ pChangeBIParams->beaconInterval;
+ beaconParams.paramChangeBitmap =
+ PARAM_BCN_INTERVAL_CHANGED;
+ lim_send_beacon_params(pMac, &beaconParams, psessionEntry);
+ }
+ }
+
+ return;
+} /*** end __lim_process_sme_change_bi(tpAniSirGlobal pMac, uint32_t *pMsgBuf) ***/
+
+#ifdef QCA_HT_2040_COEX
+static void __lim_process_sme_set_ht2040_mode(tpAniSirGlobal pMac,
+ uint32_t *pMsgBuf)
+{
+ tpSirSetHT2040Mode pSetHT2040Mode;
+ tpPESession psessionEntry;
+ uint8_t sessionId = 0;
+ cds_msg_t msg;
+ tUpdateVHTOpMode *pHtOpMode = NULL;
+ uint16_t staId = 0;
+ tpDphHashNode pStaDs = NULL;
+
+ PELOG1(lim_log(pMac, LOG1, FL("received Set HT 20/40 mode message")););
+ if (pMsgBuf == NULL) {
+ lim_log(pMac, LOGE, FL("Buffer is Pointing to NULL"));
+ return;
+ }
+
+ pSetHT2040Mode = (tpSirSetHT2040Mode) pMsgBuf;
+
+ psessionEntry = pe_find_session_by_bssid(pMac,
+ pSetHT2040Mode->bssId,
+ &sessionId);
+ if (psessionEntry == NULL) {
+ lim_log(pMac, LOG1,
+ FL("Session does not exist for given BSSID "));
+ lim_print_mac_addr(pMac, pSetHT2040Mode->bssId, LOG1);
+ return;
+ }
+
+ lim_log(pMac, LOG1, FL("Update session entry for cbMod=%d"),
+ pSetHT2040Mode->cbMode);
+ /*Update sessionEntry HT related fields */
+ switch (pSetHT2040Mode->cbMode) {
+ case PHY_SINGLE_CHANNEL_CENTERED:
+ psessionEntry->htSecondaryChannelOffset =
+ PHY_SINGLE_CHANNEL_CENTERED;
+ psessionEntry->htRecommendedTxWidthSet = 0;
+ if (pSetHT2040Mode->obssEnabled)
+ psessionEntry->htSupportedChannelWidthSet
+ = eHT_CHANNEL_WIDTH_40MHZ;
+ else
+ psessionEntry->htSupportedChannelWidthSet
+ = eHT_CHANNEL_WIDTH_20MHZ;
+ break;
+ case PHY_DOUBLE_CHANNEL_LOW_PRIMARY:
+ psessionEntry->htSecondaryChannelOffset =
+ PHY_DOUBLE_CHANNEL_LOW_PRIMARY;
+ psessionEntry->htRecommendedTxWidthSet = 1;
+ break;
+ case PHY_DOUBLE_CHANNEL_HIGH_PRIMARY:
+ psessionEntry->htSecondaryChannelOffset =
+ PHY_DOUBLE_CHANNEL_HIGH_PRIMARY;
+ psessionEntry->htRecommendedTxWidthSet = 1;
+ break;
+ default:
+ lim_log(pMac, LOGE, FL("Invalid cbMode"));
+ return;
+ }
+
+ /* Update beacon */
+ sch_set_fixed_beacon_fields(pMac, psessionEntry);
+ lim_send_beacon_ind(pMac, psessionEntry);
+
+ /* update OP Mode for each associated peer */
+ for (staId = 0; staId < psessionEntry->dph.dphHashTable.size; staId++) {
+ pStaDs = dph_get_hash_entry(pMac, staId,
+ &psessionEntry->dph.dphHashTable);
+ if (NULL == pStaDs)
+ continue;
+
+ if (pStaDs->valid && pStaDs->htSupportedChannelWidthSet) {
+ pHtOpMode = cdf_mem_malloc(sizeof(tUpdateVHTOpMode));
+ if (NULL == pHtOpMode) {
+ lim_log(pMac, LOGE,
+ FL
+ ("%s: Not able to allocate memory for setting OP mode"),
+ __func__);
+ return;
+ }
+ pHtOpMode->opMode =
+ (psessionEntry->htSecondaryChannelOffset ==
+ PHY_SINGLE_CHANNEL_CENTERED) ?
+ eHT_CHANNEL_WIDTH_20MHZ : eHT_CHANNEL_WIDTH_40MHZ;
+ pHtOpMode->staId = staId;
+ cdf_mem_copy(pHtOpMode->peer_mac, &pStaDs->staAddr,
+ sizeof(tSirMacAddr));
+ pHtOpMode->smesessionId = sessionId;
+
+ msg.type = WMA_UPDATE_OP_MODE;
+ msg.reserved = 0;
+ msg.bodyptr = pHtOpMode;
+ if (!CDF_IS_STATUS_SUCCESS
+ (cds_mq_post_message(CDF_MODULE_ID_WMA, &msg))) {
+ lim_log(pMac, LOGE,
+ FL
+ ("%s: Not able to post WMA_UPDATE_OP_MODE message to WMA"),
+ __func__);
+ cdf_mem_free(pHtOpMode);
+ return;
+ }
+ lim_log(pMac, LOG1,
+ FL
+ ("%s: Notifed FW about OP mode: %d for staId=%d"),
+ __func__, pHtOpMode->opMode, staId);
+
+ } else
+ lim_log(pMac, LOG1,
+ FL("%s: station %d does not support HT40\n"),
+ __func__, staId);
+ }
+
+ return;
+}
+#endif
+
+/* -------------------------------------------------------------------- */
+/**
+ * __lim_process_report_message
+ *
+ * FUNCTION: Processes the next received Radio Resource Management message
+ *
+ * LOGIC:
+ *
+ * ASSUMPTIONS:
+ *
+ * NOTE:
+ *
+ * @param None
+ * @return None
+ */
+
+void __lim_process_report_message(tpAniSirGlobal pMac, tpSirMsgQ pMsg)
+{
+#ifdef WLAN_FEATURE_VOWIFI
+ switch (pMsg->type) {
+ case eWNI_SME_NEIGHBOR_REPORT_REQ_IND:
+ rrm_process_neighbor_report_req(pMac, pMsg->bodyptr);
+ break;
+ case eWNI_SME_BEACON_REPORT_RESP_XMIT_IND:
+ {
+ rrm_process_beacon_report_xmit(pMac, pMsg->bodyptr);
+ }
+ break;
+ }
+#endif
+}
+
+#if defined(FEATURE_WLAN_ESE) || defined(WLAN_FEATURE_VOWIFI)
+/* -------------------------------------------------------------------- */
+/**
+ * lim_send_set_max_tx_power_req
+ *
+ * FUNCTION: Send SIR_HAL_SET_MAX_TX_POWER_REQ message to change the max tx power.
+ *
+ * LOGIC:
+ *
+ * ASSUMPTIONS:
+ *
+ * NOTE:
+ *
+ * @param txPower txPower to be set.
+ * @param pSessionEntry session entry.
+ * @return None
+ */
+tSirRetStatus
+lim_send_set_max_tx_power_req(tpAniSirGlobal pMac, tPowerdBm txPower,
+ tpPESession pSessionEntry)
+{
+ tpMaxTxPowerParams pMaxTxParams = NULL;
+ tSirRetStatus retCode = eSIR_SUCCESS;
+ tSirMsgQ msgQ;
+
+ if (pSessionEntry == NULL) {
+ PELOGE(lim_log
+ (pMac, LOGE, "%s:%d: Inavalid parameters", __func__,
+ __LINE__);
+ )
+ return eSIR_FAILURE;
+ }
+
+ pMaxTxParams = cdf_mem_malloc(sizeof(tMaxTxPowerParams));
+ if (NULL == pMaxTxParams) {
+ lim_log(pMac, LOGP,
+ FL("Unable to allocate memory for pMaxTxParams "));
+ return eSIR_MEM_ALLOC_FAILED;
+
+ }
+#if defined(WLAN_VOWIFI_DEBUG) || defined(FEATURE_WLAN_ESE)
+ lim_log(pMac, LOG1,
+ FL("pMaxTxParams allocated...will be freed in other module"));
+#endif
+ if (pMaxTxParams == NULL) {
+ lim_log(pMac, LOGE, FL("pMaxTxParams is NULL"));
+ return eSIR_FAILURE;
+ }
+ pMaxTxParams->power = txPower;
+ cdf_mem_copy(pMaxTxParams->bssId, pSessionEntry->bssId,
+ sizeof(tSirMacAddr));
+ cdf_mem_copy(pMaxTxParams->selfStaMacAddr, pSessionEntry->selfMacAddr,
+ sizeof(tSirMacAddr));
+
+ msgQ.type = WMA_SET_MAX_TX_POWER_REQ;
+ msgQ.bodyptr = pMaxTxParams;
+ msgQ.bodyval = 0;
+ PELOG1(lim_log
+ (pMac, LOG1, FL("Posting WMA_SET_MAX_TX_POWER_REQ to WMA"));
+ )
+ MTRACE(mac_trace_msg_tx(pMac, pSessionEntry->peSessionId, msgQ.type));
+ retCode = wma_post_ctrl_msg(pMac, &msgQ);
+ if (eSIR_SUCCESS != retCode) {
+ lim_log(pMac, LOGE, FL("wma_post_ctrl_msg() failed"));
+ cdf_mem_free(pMaxTxParams);
+ }
+ return retCode;
+}
+#endif
+
+/**
+ * __lim_process_sme_register_mgmt_frame_req() - process sme reg mgmt frame req
+ *
+ * @mac_ctx: Pointer to Global MAC structure
+ * @msg_buf: pointer to the SME message buffer
+ *
+ * This function is called to process eWNI_SME_REGISTER_MGMT_FRAME_REQ message
+ * from SME. It Register this information within PE.
+ *
+ * Return: None
+ */
+static void __lim_process_sme_register_mgmt_frame_req(tpAniSirGlobal mac_ctx,
+ uint32_t *msg_buf)
+{
+ CDF_STATUS cdf_status;
+ tpSirRegisterMgmtFrame sme_req = (tpSirRegisterMgmtFrame)msg_buf;
+ struct mgmt_frm_reg_info *lim_mgmt_regn = NULL;
+ struct mgmt_frm_reg_info *next = NULL;
+ bool match = false;
+
+ lim_log(mac_ctx, LOG1, FL(
+ "registerFrame %d, frameType %d, matchLen %d"),
+ sme_req->registerFrame, sme_req->frameType,
+ sme_req->matchLen);
+ /* First check whether entry exists already */
+ cdf_mutex_acquire(&mac_ctx->lim.lim_frame_register_lock);
+ cdf_list_peek_front(&mac_ctx->lim.gLimMgmtFrameRegistratinQueue,
+ (cdf_list_node_t **) &lim_mgmt_regn);
+ cdf_mutex_release(&mac_ctx->lim.lim_frame_register_lock);
+
+ while (lim_mgmt_regn != NULL) {
+ if (lim_mgmt_regn->frameType != sme_req->frameType)
+ goto skip_match;
+ if (sme_req->matchLen) {
+ if ((lim_mgmt_regn->matchLen == sme_req->matchLen) &&
+ (cdf_mem_compare(lim_mgmt_regn->matchData,
+ sme_req->matchData,
+ lim_mgmt_regn->matchLen))) {
+ /* found match! */
+ match = true;
+ break;
+ }
+ } else {
+ /* found match! */
+ match = true;
+ break;
+ }
+skip_match:
+ cdf_mutex_acquire(&mac_ctx->lim.lim_frame_register_lock);
+ cdf_status = cdf_list_peek_next(
+ &mac_ctx->lim.gLimMgmtFrameRegistratinQueue,
+ (cdf_list_node_t *)lim_mgmt_regn,
+ (cdf_list_node_t **)&next);
+ cdf_mutex_release(&mac_ctx->lim.lim_frame_register_lock);
+ lim_mgmt_regn = next;
+ next = NULL;
+ }
+ if (match) {
+ cdf_mutex_acquire(&mac_ctx->lim.lim_frame_register_lock);
+ cdf_list_remove_node(
+ &mac_ctx->lim.gLimMgmtFrameRegistratinQueue,
+ (cdf_list_node_t *)lim_mgmt_regn);
+ cdf_mutex_release(&mac_ctx->lim.lim_frame_register_lock);
+ cdf_mem_free(lim_mgmt_regn);
+ }
+
+ if (sme_req->registerFrame) {
+ lim_mgmt_regn =
+ cdf_mem_malloc(sizeof(struct mgmt_frm_reg_info) +
+ sme_req->matchLen);
+ if (lim_mgmt_regn != NULL) {
+ cdf_mem_set((void *)lim_mgmt_regn,
+ sizeof(struct mgmt_frm_reg_info) +
+ sme_req->matchLen, 0);
+ lim_mgmt_regn->frameType = sme_req->frameType;
+ lim_mgmt_regn->matchLen = sme_req->matchLen;
+ lim_mgmt_regn->sessionId = sme_req->sessionId;
+ if (sme_req->matchLen) {
+ cdf_mem_copy(lim_mgmt_regn->matchData,
+ sme_req->matchData,
+ sme_req->matchLen);
+ }
+ cdf_mutex_acquire(
+ &mac_ctx->lim.lim_frame_register_lock);
+ cdf_list_insert_front(&mac_ctx->lim.
+ gLimMgmtFrameRegistratinQueue,
+ &lim_mgmt_regn->node);
+ cdf_mutex_release(
+ &mac_ctx->lim.lim_frame_register_lock);
+ }
+ }
+ return;
+}
+
+static void __lim_deregister_deferred_sme_req_after_noa_start(tpAniSirGlobal pMac)
+{
+ lim_log(pMac, LOG1, FL("Dereg msgType %d"),
+ pMac->lim.gDeferMsgTypeForNOA);
+ pMac->lim.gDeferMsgTypeForNOA = 0;
+ if (pMac->lim.gpDefdSmeMsgForNOA != NULL) {
+ /* __lim_process_sme_scan_req consumed the buffer. We can free it. */
+ cdf_mem_free(pMac->lim.gpDefdSmeMsgForNOA);
+ pMac->lim.gpDefdSmeMsgForNOA = NULL;
+ }
+}
+
+/**
+ * lim_process_regd_defd_sme_req_after_noa_start()
+ *
+ * mac_ctx: Pointer to Global MAC structure
+ *
+ * This function is called to process deferred sme req message
+ * after noa start.
+ *
+ * Return: None
+ */
+void lim_process_regd_defd_sme_req_after_noa_start(tpAniSirGlobal mac_ctx)
+{
+ bool buf_consumed = true;
+
+ lim_log(mac_ctx, LOG1, FL("Process defd sme req %d"),
+ mac_ctx->lim.gDeferMsgTypeForNOA);
+
+ if ((mac_ctx->lim.gDeferMsgTypeForNOA == 0) ||
+ (mac_ctx->lim.gpDefdSmeMsgForNOA == NULL)) {
+ lim_log(mac_ctx, LOGW,
+ FL("start rcvd from FW when no sme deferred msg pending. Do nothing. "));
+ lim_log(mac_ctx, LOGW,
+ FL("It may happen when NOA start ind and timeout happen at the same time"));
+ return;
+ }
+ switch (mac_ctx->lim.gDeferMsgTypeForNOA) {
+ case eWNI_SME_SCAN_REQ:
+ __lim_process_sme_scan_req(mac_ctx,
+ mac_ctx->lim.gpDefdSmeMsgForNOA);
+ break;
+#ifdef FEATURE_OEM_DATA_SUPPORT
+ case eWNI_SME_OEM_DATA_REQ:
+ __lim_process_sme_oem_data_req(mac_ctx,
+ mac_ctx->lim.gpDefdSmeMsgForNOA);
+ break;
+#endif
+ case eWNI_SME_REMAIN_ON_CHANNEL_REQ:
+ buf_consumed = lim_process_remain_on_chnl_req(mac_ctx,
+ mac_ctx->lim.gpDefdSmeMsgForNOA);
+ /*
+ * lim_process_remain_on_chnl_req doesnt want us to free
+ * the buffer since it is freed in lim_remain_on_chn_rsp.
+ * this change is to avoid "double free"
+ */
+ if (false == buf_consumed)
+ mac_ctx->lim.gpDefdSmeMsgForNOA = NULL;
+ break;
+ case eWNI_SME_JOIN_REQ:
+ __lim_process_sme_join_req(mac_ctx,
+ mac_ctx->lim.gpDefdSmeMsgForNOA);
+ break;
+ default:
+ lim_log(mac_ctx, LOGE, FL("Unknown deferred msg type %d"),
+ mac_ctx->lim.gDeferMsgTypeForNOA);
+ break;
+ }
+ __lim_deregister_deferred_sme_req_after_noa_start(mac_ctx);
+}
+
+static void
+__lim_process_sme_reset_ap_caps_change(tpAniSirGlobal pMac, uint32_t *pMsgBuf)
+{
+ tpSirResetAPCapsChange pResetCapsChange;
+ tpPESession psessionEntry;
+ uint8_t sessionId = 0;
+ if (pMsgBuf == NULL) {
+ lim_log(pMac, LOGE, FL("Buffer is Pointing to NULL"));
+ return;
+ }
+
+ pResetCapsChange = (tpSirResetAPCapsChange) pMsgBuf;
+ psessionEntry =
+ pe_find_session_by_bssid(pMac, pResetCapsChange->bssId, &sessionId);
+ if (psessionEntry == NULL) {
+ lim_log(pMac, LOGE,
+ FL("Session does not exist for given BSSID"));
+ return;
+ }
+
+ psessionEntry->limSentCapsChangeNtf = false;
+ return;
+}
+
+/**
+ * lim_process_sme_req_messages()
+ *
+ ***FUNCTION:
+ * This function is called by limProcessMessageQueue(). This
+ * function processes SME request messages from HDD or upper layer
+ * application.
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ *
+ ***NOTE:
+ *
+ * @param pMac Pointer to Global MAC structure
+ * @param msgType Indicates the SME message type
+ * @param *pMsgBuf A pointer to the SME message buffer
+ * @return Boolean - true - if pMsgBuf is consumed and can be freed.
+ * false - if pMsgBuf is not to be freed.
+ */
+
+bool lim_process_sme_req_messages(tpAniSirGlobal pMac, tpSirMsgQ pMsg)
+{
+ bool bufConsumed = true; /* Set this flag to false within case block of any following message, that doesnt want pMsgBuf to be freed. */
+ uint32_t *pMsgBuf = pMsg->bodyptr;
+ tpSirSmeScanReq pScanReq;
+ PELOG1(lim_log
+ (pMac, LOG1,
+ FL
+ ("LIM Received SME Message %s(%d) Global LimSmeState:%s(%d) Global LimMlmState: %s(%d)"),
+ lim_msg_str(pMsg->type), pMsg->type,
+ lim_sme_state_str(pMac->lim.gLimSmeState), pMac->lim.gLimSmeState,
+ lim_mlm_state_str(pMac->lim.gLimMlmState), pMac->lim.gLimMlmState);
+ )
+
+ pScanReq = (tpSirSmeScanReq) pMsgBuf;
+ /* If no insert NOA required then execute the code below */
+
+ switch (pMsg->type) {
+ case eWNI_SME_SYS_READY_IND:
+ bufConsumed = __lim_process_sme_sys_ready_ind(pMac, pMsgBuf);
+ break;
+
+ case eWNI_SME_START_BSS_REQ:
+ bufConsumed = __lim_process_sme_start_bss_req(pMac, pMsg);
+ break;
+
+ case eWNI_SME_SCAN_REQ:
+ __lim_process_sme_scan_req(pMac, pMsgBuf);
+ break;
+
+#ifdef FEATURE_OEM_DATA_SUPPORT
+ case eWNI_SME_OEM_DATA_REQ:
+ __lim_process_sme_oem_data_req(pMac, pMsgBuf);
+ break;
+#endif
+ case eWNI_SME_REMAIN_ON_CHANNEL_REQ:
+ bufConsumed = lim_process_remain_on_chnl_req(pMac, pMsgBuf);
+ break;
+
+ case eWNI_SME_UPDATE_NOA:
+ __lim_process_sme_no_a_update(pMac, pMsgBuf);
+ break;
+ case eWNI_SME_CLEAR_DFS_CHANNEL_LIST:
+ __lim_process_clear_dfs_channel_list(pMac, pMsg);
+ break;
+ case eWNI_SME_JOIN_REQ:
+ __lim_process_sme_join_req(pMac, pMsgBuf);
+ break;
+
+ case eWNI_SME_REASSOC_REQ:
+ __lim_process_sme_reassoc_req(pMac, pMsgBuf);
+ break;
+
+ case eWNI_SME_DISASSOC_REQ:
+ __lim_process_sme_disassoc_req(pMac, pMsgBuf);
+ break;
+
+ case eWNI_SME_DISASSOC_CNF:
+ case eWNI_SME_DEAUTH_CNF:
+ __lim_process_sme_disassoc_cnf(pMac, pMsgBuf);
+ break;
+
+ case eWNI_SME_DEAUTH_REQ:
+ __lim_process_sme_deauth_req(pMac, pMsgBuf);
+ break;
+
+ case eWNI_SME_SETCONTEXT_REQ:
+ __lim_process_sme_set_context_req(pMac, pMsgBuf);
+ break;
+
+ case eWNI_SME_STOP_BSS_REQ:
+ bufConsumed = __lim_process_sme_stop_bss_req(pMac, pMsg);
+ break;
+
+ case eWNI_SME_ASSOC_CNF:
+ if (pMsg->type == eWNI_SME_ASSOC_CNF)
+ PELOG1(lim_log(pMac,
+ LOG1, FL("Received ASSOC_CNF message"));)
+ __lim_process_sme_assoc_cnf_new(pMac, pMsg->type,
+ pMsgBuf);
+ break;
+
+ case eWNI_SME_ADDTS_REQ:
+ PELOG1(lim_log(pMac, LOG1, FL("Received ADDTS_REQ message"));)
+ __lim_process_sme_addts_req(pMac, pMsgBuf);
+ break;
+
+ case eWNI_SME_DELTS_REQ:
+ PELOG1(lim_log(pMac, LOG1, FL("Received DELTS_REQ message"));)
+ __lim_process_sme_delts_req(pMac, pMsgBuf);
+ break;
+
+ case SIR_LIM_ADDTS_RSP_TIMEOUT:
+ PELOG1(lim_log
+ (pMac, LOG1,
+ FL("Received SIR_LIM_ADDTS_RSP_TIMEOUT message "));
+ )
+ lim_process_sme_addts_rsp_timeout(pMac, pMsg->bodyval);
+ break;
+
+ case eWNI_SME_GET_STATISTICS_REQ:
+ __lim_process_sme_get_statistics_request(pMac, pMsgBuf);
+ /* HAL consumes pMsgBuf. It will be freed there. Set bufConsumed to false. */
+ bufConsumed = false;
+ break;
+#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
+ case eWNI_SME_GET_TSM_STATS_REQ:
+ __lim_process_sme_get_tsm_stats_request(pMac, pMsgBuf);
+ bufConsumed = false;
+ break;
+#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
+ case eWNI_SME_GET_ASSOC_STAS_REQ:
+ lim_process_sme_get_assoc_sta_info(pMac, pMsgBuf);
+ break;
+ case eWNI_SME_TKIP_CNTR_MEAS_REQ:
+ lim_process_tkip_counter_measures(pMac, pMsgBuf);
+ break;
+
+ case eWNI_SME_HIDE_SSID_REQ:
+ __lim_process_sme_hide_ssid(pMac, pMsgBuf);
+ break;
+ case eWNI_SME_UPDATE_APWPSIE_REQ:
+ __lim_process_sme_update_apwpsi_es(pMac, pMsgBuf);
+ break;
+ case eWNI_SME_GET_WPSPBC_SESSION_REQ:
+ lim_process_sme_get_wpspbc_sessions(pMac, pMsgBuf);
+ break;
+
+ case eWNI_SME_SET_APWPARSNIEs_REQ:
+ __lim_process_sme_set_wparsni_es(pMac, pMsgBuf);
+ break;
+
+ case eWNI_SME_CHNG_MCC_BEACON_INTERVAL:
+ /* Update the beaconInterval */
+ __lim_process_sme_change_bi(pMac, pMsgBuf);
+ break;
+
+#ifdef QCA_HT_2040_COEX
+ case eWNI_SME_SET_HT_2040_MODE:
+ __lim_process_sme_set_ht2040_mode(pMac, pMsgBuf);
+ break;
+#endif
+
+#if defined WLAN_FEATURE_VOWIFI
+ case eWNI_SME_NEIGHBOR_REPORT_REQ_IND:
+ case eWNI_SME_BEACON_REPORT_RESP_XMIT_IND:
+ __lim_process_report_message(pMac, pMsg);
+ break;
+#endif
+
+#if defined WLAN_FEATURE_VOWIFI_11R
+ case eWNI_SME_FT_PRE_AUTH_REQ:
+ bufConsumed = (bool) lim_process_ft_pre_auth_req(pMac, pMsg);
+ break;
+ case eWNI_SME_FT_UPDATE_KEY:
+ lim_process_ft_update_key(pMac, pMsgBuf);
+ break;
+
+ case eWNI_SME_FT_AGGR_QOS_REQ:
+ lim_process_ft_aggr_qos_req(pMac, pMsgBuf);
+ break;
+#endif
+
+ case eWNI_SME_REGISTER_MGMT_FRAME_REQ:
+ __lim_process_sme_register_mgmt_frame_req(pMac, pMsgBuf);
+ break;
+#ifdef FEATURE_WLAN_TDLS
+ case eWNI_SME_TDLS_SEND_MGMT_REQ:
+ lim_process_sme_tdls_mgmt_send_req(pMac, pMsgBuf);
+ break;
+ case eWNI_SME_TDLS_ADD_STA_REQ:
+ lim_process_sme_tdls_add_sta_req(pMac, pMsgBuf);
+ break;
+ case eWNI_SME_TDLS_DEL_STA_REQ:
+ lim_process_sme_tdls_del_sta_req(pMac, pMsgBuf);
+ break;
+ case eWNI_SME_TDLS_LINK_ESTABLISH_REQ:
+ lim_process_sme_tdls_link_establish_req(pMac, pMsgBuf);
+ break;
+#endif
+ case eWNI_SME_RESET_AP_CAPS_CHANGED:
+ __lim_process_sme_reset_ap_caps_change(pMac, pMsgBuf);
+ break;
+
+ case eWNI_SME_CHANNEL_CHANGE_REQ:
+ lim_process_sme_channel_change_request(pMac, pMsgBuf);
+ break;
+
+ case eWNI_SME_START_BEACON_REQ:
+ lim_process_sme_start_beacon_req(pMac, pMsgBuf);
+ break;
+
+ case eWNI_SME_DFS_BEACON_CHAN_SW_IE_REQ:
+ lim_process_sme_dfs_csa_ie_request(pMac, pMsgBuf);
+ break;
+
+ case eWNI_SME_UPDATE_ADDITIONAL_IES:
+ lim_process_update_add_ies(pMac, pMsgBuf);
+ break;
+
+ case eWNI_SME_MODIFY_ADDITIONAL_IES:
+ lim_process_modify_add_ies(pMac, pMsgBuf);
+ break;
+ case eWNI_SME_SET_HW_MODE_REQ:
+ lim_process_set_hw_mode(pMac, pMsgBuf);
+ break;
+ case eWNI_SME_NSS_UPDATE_REQ:
+ lim_process_nss_update_request(pMac, pMsgBuf);
+ break;
+ case eWNI_SME_SET_DUAL_MAC_CFG_REQ:
+ lim_process_set_dual_mac_cfg_req(pMac, pMsgBuf);
+ break;
+ case eWNI_SME_SET_IE_REQ:
+ lim_process_set_ie_req(pMac, pMsgBuf);
+ break;
+ default:
+ cdf_mem_free((void *)pMsg->bodyptr);
+ pMsg->bodyptr = NULL;
+ break;
+ } /* switch (msgType) */
+
+ return bufConsumed;
+} /*** end lim_process_sme_req_messages() ***/
+
+/**
+ * lim_process_sme_start_beacon_req()
+ *
+ ***FUNCTION:
+ * This function is called by limProcessMessageQueue(). This
+ * function processes SME request messages from HDD or upper layer
+ * application.
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ *
+ ***NOTE:
+ *
+ * @param pMac Pointer to Global MAC structure
+ * @param msgType Indicates the SME message type
+ * @param *pMsgBuf A pointer to the SME message buffer
+ * @return Boolean - true - if pMsgBuf is consumed and can be freed.
+ * false - if pMsgBuf is not to be freed.
+ */
+static void lim_process_sme_start_beacon_req(tpAniSirGlobal pMac, uint32_t *pMsg)
+{
+ tpSirStartBeaconIndication pBeaconStartInd;
+ tpPESession psessionEntry;
+ uint8_t sessionId; /* PE sessionID */
+
+ if (pMsg == NULL) {
+ lim_log(pMac, LOGE, FL("Buffer is Pointing to NULL"));
+ return;
+ }
+
+ pBeaconStartInd = (tpSirStartBeaconIndication) pMsg;
+ psessionEntry = pe_find_session_by_bssid(pMac,
+ pBeaconStartInd->bssid,
+ &sessionId);
+ if (psessionEntry == NULL) {
+ lim_print_mac_addr(pMac, pBeaconStartInd->bssid, LOGE);
+ lim_log(pMac, LOGE,
+ FL("Session does not exist for given bssId"));
+ return;
+ }
+
+ if (pBeaconStartInd->beaconStartStatus == true) {
+ /*
+ * Currently this Indication comes from SAP
+ * to start Beacon Tx on a DFS channel
+ * since beaconing has to be done on DFS
+ * channel only after CAC WAIT is completed.
+ * On a DFS Channel LIM does not start beacon
+ * Tx right after the WMA_ADD_BSS_RSP.
+ */
+ lim_apply_configuration(pMac, psessionEntry);
+ CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_INFO,
+ FL("Start Beacon with ssid %s Ch %d"),
+ psessionEntry->ssId.ssId,
+ psessionEntry->currentOperChannel);
+ lim_send_beacon_ind(pMac, psessionEntry);
+ } else {
+ lim_log(pMac, LOGE, FL("Invalid Beacon Start Indication"));
+ return;
+ }
+}
+
+/**
+ * lim_process_sme_channel_change_request() - process sme ch change req
+ *
+ * @mac_ctx: Pointer to Global MAC structure
+ * @msg_buf: pointer to the SME message buffer
+ *
+ * This function is called to process SME_CHANNEL_CHANGE_REQ message
+ *
+ * Return: None
+ */
+static void lim_process_sme_channel_change_request(tpAniSirGlobal mac_ctx,
+ uint32_t *msg_buf)
+{
+ tpSirChanChangeRequest ch_change_req;
+ tpPESession session_entry;
+ uint8_t session_id; /* PE session_id */
+ tPowerdBm max_tx_pwr;
+ uint32_t val = 0;
+
+ if (msg_buf == NULL) {
+ lim_log(mac_ctx, LOGE, FL("msg_buf is NULL"));
+ return;
+ }
+ ch_change_req = (tpSirChanChangeRequest)msg_buf;
+
+ max_tx_pwr = cfg_get_regulatory_max_transmit_power(mac_ctx,
+ ch_change_req->targetChannel);
+
+ if ((ch_change_req->messageType != eWNI_SME_CHANNEL_CHANGE_REQ) ||
+ (max_tx_pwr == WMA_MAX_TXPOWER_INVALID)) {
+ lim_log(mac_ctx, LOGE, FL("Invalid Request/max_tx_pwr"));
+ return;
+ }
+
+ session_entry = pe_find_session_by_bssid(mac_ctx,
+ ch_change_req->bssid, &session_id);
+ if (session_entry == NULL) {
+ lim_print_mac_addr(mac_ctx, ch_change_req->bssid, LOGE);
+ lim_log(mac_ctx, LOGE, FL(
+ "Session does not exist for given bssId"));
+ return;
+ }
+
+ if (session_entry->currentOperChannel ==
+ ch_change_req->targetChannel) {
+ lim_log(mac_ctx, LOGE, FL("target CH is same as current CH"));
+ return;
+ }
+
+ if (LIM_IS_AP_ROLE(session_entry))
+ session_entry->channelChangeReasonCode =
+ LIM_SWITCH_CHANNEL_SAP_DFS;
+ else
+ session_entry->channelChangeReasonCode =
+ LIM_SWITCH_CHANNEL_OPERATION;
+
+ lim_log(mac_ctx, LOGW, FL(
+ "switch old chnl %d to new chnl %d, ch_bw %d"),
+ session_entry->currentOperChannel,
+ ch_change_req->targetChannel,
+ ch_change_req->channel_width);
+
+ /* Store the New Channel Params in session_entry */
+ session_entry->ch_width = ch_change_req->channel_width;
+ session_entry->ch_center_freq_seg0 =
+ ch_change_req->center_freq_seg_0;
+ session_entry->ch_center_freq_seg1 =
+ ch_change_req->center_freq_seg_1;
+ session_entry->htSecondaryChannelOffset = ch_change_req->cbMode;
+ session_entry->htSupportedChannelWidthSet =
+ (ch_change_req->channel_width ? 1 : 0);
+ session_entry->htRecommendedTxWidthSet =
+ session_entry->htSupportedChannelWidthSet;
+ session_entry->currentOperChannel =
+ ch_change_req->targetChannel;
+ session_entry->limRFBand =
+ lim_get_rf_band(session_entry->currentOperChannel);
+ /* Initialize 11h Enable Flag */
+ if (SIR_BAND_5_GHZ == session_entry->limRFBand) {
+ if (wlan_cfg_get_int(mac_ctx, WNI_CFG_11H_ENABLED, &val) !=
+ eSIR_SUCCESS)
+ lim_log(mac_ctx, LOGP,
+ FL("Fail to get WNI_CFG_11H_ENABLED"));
+ }
+
+ session_entry->lim11hEnable = val;
+ session_entry->dot11mode = ch_change_req->dot11mode;
+ cdf_mem_copy(&session_entry->rateSet,
+ &ch_change_req->operational_rateset,
+ sizeof(session_entry->rateSet));
+ cdf_mem_copy(&session_entry->extRateSet,
+ &ch_change_req->extended_rateset,
+ sizeof(session_entry->extRateSet));
+ lim_set_channel(mac_ctx, ch_change_req->targetChannel,
+ session_entry->ch_center_freq_seg0,
+ session_entry->ch_center_freq_seg1,
+ session_entry->ch_width,
+ max_tx_pwr, session_entry->peSessionId);
+}
+
+/******************************************************************************
+* lim_start_bss_update_add_ie_buffer()
+*
+***FUNCTION:
+* This function checks the src buffer and its length and then malloc for
+* dst buffer update the same
+*
+***LOGIC:
+*
+***ASSUMPTIONS:
+*
+***NOTE:
+*
+* @param pMac Pointer to Global MAC structure
+* @param **pDstData_buff A pointer to pointer of uint8_t dst buffer
+* @param *pDstDataLen A pointer to pointer of uint16_t dst buffer length
+* @param *pSrcData_buff A pointer of uint8_t src buffer
+* @param srcDataLen src buffer length
+******************************************************************************/
+
+static void
+lim_start_bss_update_add_ie_buffer(tpAniSirGlobal pMac,
+ uint8_t **pDstData_buff,
+ uint16_t *pDstDataLen,
+ uint8_t *pSrcData_buff, uint16_t srcDataLen)
+{
+
+ if (srcDataLen > 0 && pSrcData_buff != NULL) {
+ *pDstDataLen = srcDataLen;
+
+ *pDstData_buff = cdf_mem_malloc(*pDstDataLen);
+
+ if (NULL == *pDstData_buff) {
+ lim_log(pMac, LOGE,
+ FL("AllocateMemory failed for pDstData_buff"));
+ return;
+ }
+ cdf_mem_copy(*pDstData_buff, pSrcData_buff, *pDstDataLen);
+ } else {
+ *pDstData_buff = NULL;
+ *pDstDataLen = 0;
+ }
+}
+
+/******************************************************************************
+* lim_update_add_ie_buffer()
+*
+***FUNCTION:
+* This function checks the src buffer and length if src buffer length more
+* than dst buffer length then free the dst buffer and malloc for the new src
+* length, and update the dst buffer and length. But if dst buffer is bigger
+* than src buffer length then it just update the dst buffer and length
+*
+***LOGIC:
+*
+***ASSUMPTIONS:
+*
+***NOTE:
+*
+* @param pMac Pointer to Global MAC structure
+* @param **pDstData_buff A pointer to pointer of uint8_t dst buffer
+* @param *pDstDataLen A pointer to pointer of uint16_t dst buffer length
+* @param *pSrcData_buff A pointer of uint8_t src buffer
+* @param srcDataLen src buffer length
+******************************************************************************/
+
+static void
+lim_update_add_ie_buffer(tpAniSirGlobal pMac,
+ uint8_t **pDstData_buff,
+ uint16_t *pDstDataLen,
+ uint8_t *pSrcData_buff, uint16_t srcDataLen)
+{
+
+ if (NULL == pSrcData_buff) {
+ lim_log(pMac, LOGE, FL("src buffer is null."));
+ return;
+ }
+
+ if (srcDataLen > *pDstDataLen) {
+ *pDstDataLen = srcDataLen;
+ /* free old buffer */
+ cdf_mem_free(*pDstData_buff);
+ /* allocate a new */
+ *pDstData_buff = cdf_mem_malloc(*pDstDataLen);
+
+ if (NULL == *pDstData_buff) {
+ lim_log(pMac, LOGE, FL("Memory allocation failed."));
+ *pDstDataLen = 0;
+ return;
+ }
+ }
+
+ /* copy the content of buffer into dst buffer
+ */
+ *pDstDataLen = srcDataLen;
+ cdf_mem_copy(*pDstData_buff, pSrcData_buff, *pDstDataLen);
+
+}
+
+/*
+* lim_process_modify_add_ies() - process modify additional IE req.
+*
+* @mac_ctx: Pointer to Global MAC structure
+* @msg_buf: pointer to the SME message buffer
+*
+* This function update the PE buffers for additional IEs.
+*
+* Return: None
+*/
+static void lim_process_modify_add_ies(tpAniSirGlobal mac_ctx,
+ uint32_t *msg_buf)
+{
+ tpSirModifyIEsInd modify_add_ies;
+ tpPESession session_entry;
+ uint8_t session_id;
+ bool ret = false;
+ tSirAddIeParams *add_ie_params;
+
+ if (msg_buf == NULL) {
+ lim_log(mac_ctx, LOGE, FL("msg_buf is NULL"));
+ return;
+ }
+
+ modify_add_ies = (tpSirModifyIEsInd)msg_buf;
+ /* Incoming message has smeSession, use BSSID to find PE session */
+ session_entry = pe_find_session_by_bssid(mac_ctx,
+ modify_add_ies->modifyIE.bssid, &session_id);
+
+ if (NULL == session_entry) {
+ lim_log(mac_ctx, LOGE, FL("Session not found for given bssid. "
+ MAC_ADDRESS_STR),
+ MAC_ADDR_ARRAY(modify_add_ies->modifyIE.bssid));
+ goto end;
+ }
+ if ((0 == modify_add_ies->modifyIE.ieBufferlength) ||
+ (0 == modify_add_ies->modifyIE.ieIDLen) ||
+ (NULL == modify_add_ies->modifyIE.pIEBuffer)) {
+ lim_log(mac_ctx, LOGE,
+ FL("Invalid request pIEBuffer %p ieBufferlength %d ieIDLen %d ieID %d. update Type %d"),
+ modify_add_ies->modifyIE.pIEBuffer,
+ modify_add_ies->modifyIE.ieBufferlength,
+ modify_add_ies->modifyIE.ieID,
+ modify_add_ies->modifyIE.ieIDLen,
+ modify_add_ies->updateType);
+ goto end;
+ }
+ add_ie_params = &session_entry->addIeParams;
+ switch (modify_add_ies->updateType) {
+ case eUPDATE_IE_PROBE_RESP:
+ /* Probe resp */
+ break;
+ case eUPDATE_IE_ASSOC_RESP:
+ /* assoc resp IE */
+ if (add_ie_params->assocRespDataLen == 0) {
+ CDF_TRACE(CDF_MODULE_ID_PE,
+ CDF_TRACE_LEVEL_ERROR, FL(
+ "assoc resp add ie not present %d"),
+ add_ie_params->assocRespDataLen);
+ }
+ /* search through the buffer and modify the IE */
+ break;
+ case eUPDATE_IE_PROBE_BCN:
+ /*probe beacon IE */
+ if (ret == true && modify_add_ies->modifyIE.notify) {
+ lim_handle_param_update(mac_ctx,
+ modify_add_ies->updateType);
+ }
+ break;
+ default:
+ lim_log(mac_ctx, LOGE, FL("unhandled buffer type %d"),
+ modify_add_ies->updateType);
+ break;
+ }
+end:
+ cdf_mem_free(modify_add_ies->modifyIE.pIEBuffer);
+ modify_add_ies->modifyIE.pIEBuffer = NULL;
+}
+
+/*
+* lim_process_update_add_ies() - process additional IE update req
+*
+* @mac_ctx: Pointer to Global MAC structure
+* @msg_buf: pointer to the SME message buffer
+*
+* This function update the PE buffers for additional IEs.
+*
+* Return: None
+*/
+static void lim_process_update_add_ies(tpAniSirGlobal mac_ctx,
+ uint32_t *msg_buf)
+{
+ tpSirUpdateIEsInd update_add_ies = (tpSirUpdateIEsInd)msg_buf;
+ uint8_t session_id;
+ tpPESession session_entry;
+ tSirAddIeParams *addn_ie;
+ uint16_t new_length = 0;
+ uint8_t *new_ptr = NULL;
+ tSirUpdateIE *update_ie;
+
+ if (msg_buf == NULL) {
+ lim_log(mac_ctx, LOGE, FL("msg_buf is NULL"));
+ return;
+ }
+ update_ie = &update_add_ies->updateIE;
+ /* incoming message has smeSession, use BSSID to find PE session */
+ session_entry = pe_find_session_by_bssid(mac_ctx,
+ update_ie->bssid, &session_id);
+
+ if (NULL == session_entry) {
+ lim_log(mac_ctx, LOGE, FL("Session not found for given bssid. "
+ MAC_ADDRESS_STR),
+ MAC_ADDR_ARRAY(update_ie->bssid));
+ goto end;
+ }
+ addn_ie = &session_entry->addIeParams;
+ /* if len is 0, upper layer requested freeing of buffer */
+ if (0 == update_ie->ieBufferlength) {
+ switch (update_add_ies->updateType) {
+ case eUPDATE_IE_PROBE_RESP:
+ cdf_mem_free(addn_ie->probeRespData_buff);
+ addn_ie->probeRespData_buff = NULL;
+ addn_ie->probeRespDataLen = 0;
+ break;
+ case eUPDATE_IE_ASSOC_RESP:
+ cdf_mem_free(addn_ie->assocRespData_buff);
+ addn_ie->assocRespData_buff = NULL;
+ addn_ie->assocRespDataLen = 0;
+ break;
+ case eUPDATE_IE_PROBE_BCN:
+ cdf_mem_free(addn_ie->probeRespBCNData_buff);
+ addn_ie->probeRespBCNData_buff = NULL;
+ addn_ie->probeRespBCNDataLen = 0;
+
+ if (update_ie->notify)
+ lim_handle_param_update(mac_ctx,
+ update_add_ies->updateType);
+ break;
+ default:
+ break;
+ }
+ return;
+ }
+ switch (update_add_ies->updateType) {
+ case eUPDATE_IE_PROBE_RESP:
+ if (update_ie->append) {
+ /*
+ * In case of append, allocate new memory
+ * with combined length
+ */
+ new_length = update_ie->ieBufferlength +
+ addn_ie->probeRespDataLen;
+ new_ptr = cdf_mem_malloc(new_length);
+ if (NULL == new_ptr) {
+ lim_log(mac_ctx, LOGE, FL(
+ "Memory allocation failed."));
+ goto end;
+ }
+ /* append buffer to end of local buffers */
+ cdf_mem_copy(new_ptr, addn_ie->probeRespData_buff,
+ addn_ie->probeRespDataLen);
+ cdf_mem_copy(&new_ptr[addn_ie->probeRespDataLen],
+ update_ie->pAdditionIEBuffer,
+ update_ie->ieBufferlength);
+ /* free old memory */
+ cdf_mem_free(addn_ie->probeRespData_buff);
+ /* adjust length accordingly */
+ addn_ie->probeRespDataLen = new_length;
+ /* save refernece of local buffer in PE session */
+ addn_ie->probeRespData_buff = new_ptr;
+ goto end;
+ }
+ lim_update_add_ie_buffer(mac_ctx, &addn_ie->probeRespData_buff,
+ &addn_ie->probeRespDataLen,
+ update_ie->pAdditionIEBuffer,
+ update_ie->ieBufferlength);
+ break;
+ case eUPDATE_IE_ASSOC_RESP:
+ /* assoc resp IE */
+ lim_update_add_ie_buffer(mac_ctx, &addn_ie->assocRespData_buff,
+ &addn_ie->assocRespDataLen,
+ update_ie->pAdditionIEBuffer,
+ update_ie->ieBufferlength);
+ break;
+ case eUPDATE_IE_PROBE_BCN:
+ /* probe resp Bcn IE */
+ lim_update_add_ie_buffer(mac_ctx,
+ &addn_ie->probeRespBCNData_buff,
+ &addn_ie->probeRespBCNDataLen,
+ update_ie->pAdditionIEBuffer,
+ update_ie->ieBufferlength);
+ if (update_ie->notify)
+ lim_handle_param_update(mac_ctx,
+ update_add_ies->updateType);
+ break;
+ default:
+ lim_log(mac_ctx, LOGE, FL("unhandled buffer type %d."),
+ update_add_ies->updateType);
+ break;
+ }
+end:
+ cdf_mem_free(update_ie->pAdditionIEBuffer);
+ update_ie->pAdditionIEBuffer = NULL;
+}
+
+/**
+ * lim_process_sme_dfs_csa_ie_request() - process sme dfs csa ie req
+ *
+ * @mac_ctx: Pointer to Global MAC structure
+ * @msg_buf: pointer to the SME message buffer
+ *
+ * This function processes SME request messages from HDD or upper layer
+ * application.
+ *
+ * Return: None
+ */
+static void lim_process_sme_dfs_csa_ie_request(tpAniSirGlobal mac_ctx,
+ uint32_t *msg_buf)
+{
+ tpSirDfsCsaIeRequest dfs_csa_ie_req;
+ tpPESession session_entry = NULL;
+ uint32_t ch_width = 0;
+ uint8_t session_id;
+ tLimWiderBWChannelSwitchInfo *wider_bw_ch_switch;
+
+ if (msg_buf == NULL) {
+ lim_log(mac_ctx, LOGE, FL("Buffer is Pointing to NULL"));
+ return;
+ }
+
+ dfs_csa_ie_req = (tSirDfsCsaIeRequest *)msg_buf;
+ session_entry = pe_find_session_by_bssid(mac_ctx,
+ dfs_csa_ie_req->bssid, &session_id);
+ if (session_entry == NULL) {
+ lim_log(mac_ctx, LOGE, FL(
+ "Session not found for given BSSID" MAC_ADDRESS_STR),
+ MAC_ADDR_ARRAY(dfs_csa_ie_req->bssid));
+ return;
+ }
+
+ if (session_entry->valid && !LIM_IS_AP_ROLE(session_entry)) {
+ lim_log(mac_ctx, LOGE, FL("Invalid SystemRole %d"),
+ GET_LIM_SYSTEM_ROLE(session_entry));
+ return;
+ }
+
+ /* target channel */
+ session_entry->gLimChannelSwitch.primaryChannel =
+ dfs_csa_ie_req->targetChannel;
+
+ /* Channel switch announcement needs to be included in beacon */
+ session_entry->dfsIncludeChanSwIe = true;
+ session_entry->gLimChannelSwitch.switchCount = LIM_MAX_CSA_IE_UPDATES;
+ session_entry->gLimChannelSwitch.ch_width =
+ dfs_csa_ie_req->ch_bandwidth;
+ if (mac_ctx->sap.SapDfsInfo.disable_dfs_ch_switch == false)
+ session_entry->gLimChannelSwitch.switchMode = 1;
+
+ /*
+ * Validate if SAP is operating HT or VHT mode and set the Channel
+ * Switch Wrapper element with the Wide Band Switch subelement.
+ */
+ if (true != session_entry->vhtCapability)
+ goto skip_vht;
+
+ if (WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ ==
+ session_entry->vhtTxChannelWidthSet)
+ ch_width = eHT_CHANNEL_WIDTH_80MHZ;
+ else if (WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ ==
+ session_entry->vhtTxChannelWidthSet)
+ ch_width = session_entry->htSupportedChannelWidthSet;
+ /* Now encode the Wider Ch BW element depending on the ch width */
+ wider_bw_ch_switch = &session_entry->gLimWiderBWChannelSwitch;
+ switch (ch_width) {
+ case eHT_CHANNEL_WIDTH_20MHZ:
+ /*
+ * Wide channel BW sublement in channel wrapper element is not
+ * required in case of 20 Mhz operation. Currently It is set
+ * only set in case of 40/80 Mhz Operation.
+ */
+ session_entry->dfsIncludeChanWrapperIe = false;
+ wider_bw_ch_switch->newChanWidth =
+ WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ;
+ break;
+ case eHT_CHANNEL_WIDTH_40MHZ:
+ session_entry->dfsIncludeChanWrapperIe = true;
+ wider_bw_ch_switch->newChanWidth =
+ WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ;
+ break;
+ case eHT_CHANNEL_WIDTH_80MHZ:
+ session_entry->dfsIncludeChanWrapperIe = true;
+ wider_bw_ch_switch->newChanWidth =
+ WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ;
+ break;
+ case eHT_CHANNEL_WIDTH_160MHZ:
+ session_entry->dfsIncludeChanWrapperIe = true;
+ wider_bw_ch_switch->newChanWidth =
+ WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ;
+ break;
+ default:
+ session_entry->dfsIncludeChanWrapperIe = false;
+ /*
+ * Need to handle 80+80 Mhz Scenario. When 80+80 is supported
+ * set the gLimWiderBWChannelSwitch.newChanWidth to 3
+ */
+ lim_log(mac_ctx, LOGE, FL("Invalid Channel Width"));
+ break;
+ }
+ /* Fetch the center channel based on the channel width */
+ wider_bw_ch_switch->newCenterChanFreq0 =
+ lim_get_center_channel(mac_ctx, dfs_csa_ie_req->targetChannel,
+ session_entry->htSecondaryChannelOffset,
+ wider_bw_ch_switch->newChanWidth);
+ /*
+ * This is not applicable for 20/40/80 Mhz.Only used when we support
+ * 80+80 Mhz operation. In case of 80+80 Mhz, this parameter indicates
+ * center channel frequency index of 80 Mhz channel of
+ * frequency segment 1.
+ */
+ wider_bw_ch_switch->newCenterChanFreq1 = 0;
+skip_vht:
+ /* Send CSA IE request from here */
+ if (sch_set_fixed_beacon_fields(mac_ctx, session_entry) !=
+ eSIR_SUCCESS) {
+ lim_log(mac_ctx, LOGE, FL("Unable to set CSA IE in beacon"));
+ return;
+ }
+
+ /*
+ * First beacon update request is sent here, the remaining updates are
+ * done when the FW responds back after sending the first beacon after
+ * the template update
+ */
+ lim_send_beacon_ind(mac_ctx, session_entry);
+ lim_log(mac_ctx, LOG1, FL("Updated CSA IE, IE COUNT = %d"),
+ session_entry->gLimChannelSwitch.switchCount);
+ session_entry->gLimChannelSwitch.switchCount--;
+}
+
+/**
+ * lim_process_nss_update_request() - process sme nss update req
+ *
+ * @mac_ctx: Pointer to Global MAC structure
+ * @msg_buf: pointer to the SME message buffer
+ *
+ * This function processes SME request messages from HDD or upper layer
+ * application.
+ *
+ * Return: None
+ */
+static void lim_process_nss_update_request(tpAniSirGlobal mac_ctx,
+ uint32_t *msg_buf)
+{
+ struct sir_nss_update_request *nss_update_req_ptr;
+ tpPESession session_entry = NULL;
+
+ if (msg_buf == NULL) {
+ lim_log(mac_ctx, LOGE, FL("Buffer is Pointing to NULL"));
+ return;
+ }
+
+ nss_update_req_ptr = (struct sir_nss_update_request *)msg_buf;
+ session_entry = pe_find_session_by_session_id(mac_ctx,
+ nss_update_req_ptr->vdev_id);
+ if (session_entry == NULL) {
+ lim_log(mac_ctx, LOGE, FL(
+ "Session not found for given session_id %d"),
+ nss_update_req_ptr->vdev_id);
+ return;
+ }
+
+ if (session_entry->valid && !LIM_IS_AP_ROLE(session_entry)) {
+ lim_log(mac_ctx, LOGE, FL("Invalid SystemRole %d"),
+ GET_LIM_SYSTEM_ROLE(session_entry));
+ return;
+ }
+
+ /* populate nss field in the beacon */
+ session_entry->gLimOperatingMode.present = 1;
+ session_entry->gLimOperatingMode.rxNSS = nss_update_req_ptr->new_nss;
+ /* Send nss update request from here */
+ if (sch_set_fixed_beacon_fields(mac_ctx, session_entry) !=
+ eSIR_SUCCESS) {
+ lim_log(mac_ctx, LOGE,
+ FL("Unable to set op mode IE in beacon"));
+ return;
+ }
+
+ lim_send_beacon_ind(mac_ctx, session_entry);
+}
+
+/**
+ * lim_process_set_ie_req() - process sme set IE request
+ *
+ * @mac_ctx: Pointer to Global MAC structure
+ * @msg_buf: pointer to the SME message buffer
+ *
+ * This function processes SME request messages from HDD or upper layer
+ * application.
+ *
+ * Return: None
+ */
+static void lim_process_set_ie_req(tpAniSirGlobal mac_ctx, uint32_t *msg_buf)
+{
+ struct send_extcap_ie *msg;
+ CDF_STATUS status;
+
+ if (msg_buf == NULL) {
+ lim_log(mac_ctx, LOGE, FL("Buffer is Pointing to NULL"));
+ return;
+ }
+
+ msg = (struct send_extcap_ie *)msg_buf;
+ status = lim_send_ext_cap_ie(mac_ctx, msg->session_id, NULL, false);
+ if (CDF_STATUS_SUCCESS != status)
+ lim_log(mac_ctx, LOGE, FL("Unable to send ExtCap to FW"));
+
+}
diff --git a/core/mac/src/pe/lim/lim_process_tdls.c b/core/mac/src/pe/lim/lim_process_tdls.c
new file mode 100644
index 0000000..fa5a0ab
--- /dev/null
+++ b/core/mac/src/pe/lim/lim_process_tdls.c
@@ -0,0 +1,3267 @@
+/*
+ * Copyright (c) 2012-2015 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.
+ */
+
+/*===========================================================================
+ * lim_process_tdls.c
+ * OVERVIEW:
+ *
+ * DEPENDENCIES:
+ *
+ * Are listed for each API below.
+ * ===========================================================================*/
+
+/*===========================================================================
+
+ * EDIT HISTORY FOR FILE
+
+ * This section contains comments describing changes made to the module.
+ * Notice that changes are listed in reverse chronological order.
+
+ * $Header$$DateTime$$Author$
+
+ * when who what, where, why
+ * ---------- --- ------------------------------------------------------
+ * 05/05/2010 Ashwani Initial Creation, added TDLS action frame
+ * functionality,TDLS message exchange with SME..etc..
+
+ ===========================================================================*/
+
+/**
+ * \file lim_process_tdls.c
+ *
+ * \brief Code for preparing,processing and sending 802.11z action frames
+ *
+ */
+
+#ifdef FEATURE_WLAN_TDLS
+
+#include "sir_api.h"
+#include "ani_global.h"
+#include "sir_mac_prot_def.h"
+#include "cfg_api.h"
+#include "utils_api.h"
+#include "lim_types.h"
+#include "lim_utils.h"
+#include "lim_security_utils.h"
+#include "dot11f.h"
+#include "lim_sta_hash_api.h"
+#include "sch_api.h"
+#include "lim_send_messages.h"
+#include "utils_parser.h"
+#include "lim_assoc_utils.h"
+#include "dph_hash_table.h"
+#include "wma_types.h"
+#include "cds_regdomain_common.h"
+
+/* define NO_PAD_TDLS_MIN_8023_SIZE to NOT padding: See CR#447630
+ There was IOT issue with cisco 1252 open mode, where it pads
+ discovery req/teardown frame with some junk value up to min size.
+ To avoid this issue, we pad QCOM_VENDOR_IE.
+ If there is other IOT issue because of this bandage, define NO_PAD...
+ */
+#ifndef NO_PAD_TDLS_MIN_8023_SIZE
+#define MIN_IEEE_8023_SIZE 46
+#define MIN_VENDOR_SPECIFIC_IE_SIZE 5
+#endif
+
+static tSirRetStatus lim_tdls_setup_add_sta(tpAniSirGlobal pMac,
+ tSirTdlsAddStaReq * pAddStaReq, tpPESession psessionEntry);
+void populate_dot11f_link_iden(tpAniSirGlobal pMac, tpPESession psessionEntry,
+ tDot11fIELinkIdentifier *linkIden,
+ tSirMacAddr peerMac, uint8_t reqType);
+void populate_dot11f_tdls_ext_capability(tpAniSirGlobal pMac,
+ tpPESession psessionEntry,
+ tDot11fIEExtCap *extCapability);
+
+void populate_dot11f_tdls_offchannel_params(tpAniSirGlobal pMac,
+ tpPESession psessionEntry,
+ tDot11fIESuppChannels *suppChannels,
+ tDot11fIESuppOperatingClasses *
+ suppOperClasses);
+void lim_log_vht_cap(tpAniSirGlobal pMac, tDot11fIEVHTCaps *pDot11f);
+tSirRetStatus lim_populate_vht_mcs_set(tpAniSirGlobal pMac,
+ tpSirSupportedRates pRates,
+ tDot11fIEVHTCaps *pPeerVHTCaps,
+ tpPESession psessionEntry);
+ePhyChanBondState lim_get_htcb_state(ePhyChanBondState aniCBMode);
+
+/*
+ * TDLS data frames will go out/come in as non-qos data.
+ * so, eth_890d_header will be aligned access..
+ */
+static const uint8_t eth_890d_header[] = {
+ 0xaa, 0xaa, 0x03, 0x00,
+ 0x00, 0x00, 0x89, 0x0d,
+};
+
+/*
+ * type of links used in TDLS
+ */
+enum tdlsLinks {
+ TDLS_LINK_AP,
+ TDLS_LINK_DIRECT
+} e_tdls_link;
+
+/*
+ * node status in node searching
+ */
+enum tdlsLinkNodeStatus {
+ TDLS_NODE_NOT_FOUND,
+ TDLS_NODE_FOUND
+} e_tdls_link_node_status;
+
+enum tdlsReqType {
+ TDLS_INITIATOR,
+ TDLS_RESPONDER
+} e_tdls_req_type;
+
+typedef enum tdlsLinkSetupStatus {
+ TDLS_SETUP_STATUS_SUCCESS = 0,
+ TDLS_SETUP_STATUS_FAILURE = 37
+} etdlsLinkSetupStatus;
+
+/* These maps to Kernel TDLS peer capability
+ * flags and should get changed as and when necessary
+ */
+enum tdls_peer_capability {
+ TDLS_PEER_HT_CAP = 0,
+ TDLS_PEER_VHT_CAP = 1,
+ TDLS_PEER_WMM_CAP = 2
+} e_tdls_peer_capability;
+
+/* some local defines */
+#define LINK_IDEN_ADDR_OFFSET(x) (&x.LinkIdentifier)
+#define PTI_LINK_IDEN_OFFSET (5)
+#define PTI_BUF_STATUS_OFFSET (25)
+
+/* TODO, Move this parameters to configuration */
+#define PEER_PSM_SUPPORT (0)
+#define TDLS_SUPPORT (1)
+#define TDLS_PROHIBITED (0)
+#define TDLS_CH_SWITCH_PROHIBITED (1)
+/** @brief Set bit manipulation macro */
+#define SET_BIT(value, mask) ((value) |= (1 << (mask)))
+/** @brief Clear bit manipulation macro */
+#define CLEAR_BIT(value, mask) ((value) &= ~(1 << (mask)))
+/** @brief Check bit manipulation macro */
+#define CHECK_BIT(value, mask) ((value) & (1 << (mask)))
+
+#define SET_PEER_AID_BITMAP(peer_bitmap, aid) \
+ do { \
+ if ((aid) < (sizeof(uint32_t) << 3)) \
+ SET_BIT(peer_bitmap[0], (aid)); \
+ else if ((aid) < (sizeof(uint32_t) << 4)) \
+ SET_BIT(peer_bitmap[1], ((aid) - (sizeof(uint32_t) << 3)));\
+ } while (0);
+
+#define CLEAR_PEER_AID_BITMAP(peer_bitmap, aid) \
+ do { \
+ if ((aid) < (sizeof(uint32_t) << 3)) \
+ CLEAR_BIT(peer_bitmap[0], (aid)); \
+ else if ((aid) < (sizeof(uint32_t) << 4)) \
+ CLEAR_BIT(peer_bitmap[1], ((aid) - (sizeof(uint32_t) << 3)));\
+ } while (0);
+
+#ifdef LIM_DEBUG_TDLS
+
+#ifdef FEATURE_WLAN_TDLS
+#define WNI_CFG_TDLS_LINK_SETUP_RSP_TIMEOUT (800)
+#define WNI_CFG_TDLS_LINK_SETUP_CNF_TIMEOUT (200)
+#endif
+
+#define IS_QOS_ENABLED(psessionEntry) ((((psessionEntry)->limQosEnabled) && \
+ SIR_MAC_GET_QOS((psessionEntry)->limCurrentBssCaps)) || \
+ (((psessionEntry)->limWmeEnabled) && \
+ LIM_BSS_CAPS_GET(WME, (psessionEntry)->limCurrentBssQosCaps)))
+
+#define TID_AC_VI 4
+#define TID_AC_BK 1
+
+const uint8_t *lim_trace_tdls_action_string(uint8_t tdlsActionCode)
+{
+ switch (tdlsActionCode) {
+ CASE_RETURN_STRING(SIR_MAC_TDLS_SETUP_REQ);
+ CASE_RETURN_STRING(SIR_MAC_TDLS_SETUP_RSP);
+ CASE_RETURN_STRING(SIR_MAC_TDLS_SETUP_CNF);
+ CASE_RETURN_STRING(SIR_MAC_TDLS_TEARDOWN);
+ CASE_RETURN_STRING(SIR_MAC_TDLS_PEER_TRAFFIC_IND);
+ CASE_RETURN_STRING(SIR_MAC_TDLS_CH_SWITCH_REQ);
+ CASE_RETURN_STRING(SIR_MAC_TDLS_CH_SWITCH_RSP);
+ CASE_RETURN_STRING(SIR_MAC_TDLS_PEER_TRAFFIC_RSP);
+ CASE_RETURN_STRING(SIR_MAC_TDLS_DIS_REQ);
+ CASE_RETURN_STRING(SIR_MAC_TDLS_DIS_RSP);
+ }
+ return (const uint8_t *)"UNKNOWN";
+}
+#endif
+/*
+ * initialize TDLS setup list and related data structures.
+ */
+void lim_init_tdls_data(tpAniSirGlobal pMac, tpPESession pSessionEntry)
+{
+ lim_init_peer_idxpool(pMac, pSessionEntry);
+
+ return;
+}
+
+/*
+ * prepare TDLS frame header, it includes
+ * | | | |
+ * |802.11 header|RFC1042 header|TDLS_PYLOAD_TYPE|PAYLOAD
+ * | | | |
+ */
+static uint32_t lim_prepare_tdls_frame_header(tpAniSirGlobal pMac, uint8_t *pFrame,
+ tDot11fIELinkIdentifier *link_iden,
+ uint8_t tdlsLinkType, uint8_t reqType,
+ uint8_t tid,
+ tpPESession psessionEntry)
+{
+ tpSirMacDataHdr3a pMacHdr;
+ uint32_t header_offset = 0;
+ uint8_t *addr1 = NULL;
+ uint8_t *addr3 = NULL;
+ uint8_t toDs = (tdlsLinkType == TDLS_LINK_AP)
+ ? ANI_TXDIR_TODS : ANI_TXDIR_IBSS;
+ uint8_t *peerMac = (reqType == TDLS_INITIATOR)
+ ? link_iden->RespStaAddr : link_iden->InitStaAddr;
+ uint8_t *staMac = (reqType == TDLS_INITIATOR)
+ ? link_iden->InitStaAddr : link_iden->RespStaAddr;
+
+ pMacHdr = (tpSirMacDataHdr3a) (pFrame);
+
+ /*
+ * if TDLS frame goes through the AP link, it follows normal address
+ * pattern, if TDLS frame goes thorugh the direct link, then
+ * A1--> Peer STA addr, A2-->Self STA address, A3--> BSSID
+ */
+ (tdlsLinkType == TDLS_LINK_AP) ? ((addr1 = (link_iden->bssid)),
+ (addr3 = (peerMac)))
+ : ((addr1 = (peerMac)), (addr3 = (link_iden->bssid)));
+ /*
+ * prepare 802.11 header
+ */
+ pMacHdr->fc.protVer = SIR_MAC_PROTOCOL_VERSION;
+ pMacHdr->fc.type = SIR_MAC_DATA_FRAME;
+ pMacHdr->fc.subType =
+ IS_QOS_ENABLED(psessionEntry) ? SIR_MAC_DATA_QOS_DATA :
+ SIR_MAC_DATA_DATA;
+
+ /*
+ * TL is not setting up below fields, so we are doing it here
+ */
+ pMacHdr->fc.toDS = toDs;
+ pMacHdr->fc.powerMgmt = 0;
+ pMacHdr->fc.wep = (psessionEntry->encryptType == eSIR_ED_NONE) ? 0 : 1;
+
+ cdf_mem_copy((uint8_t *) pMacHdr->addr1,
+ (uint8_t *) addr1, sizeof(tSirMacAddr));
+ cdf_mem_copy((uint8_t *) pMacHdr->addr2,
+ (uint8_t *) staMac, sizeof(tSirMacAddr));
+
+ cdf_mem_copy((uint8_t *) pMacHdr->addr3,
+ (uint8_t *) (addr3), sizeof(tSirMacAddr));
+
+ lim_log(pMac, LOG1,
+ FL(
+ "Preparing TDLS frame header to %s A1:"
+ MAC_ADDRESS_STR", A2:"MAC_ADDRESS_STR", A3:"
+ MAC_ADDRESS_STR
+ ),
+ (tdlsLinkType == TDLS_LINK_AP) ? "AP" : "DIRECT",
+ MAC_ADDR_ARRAY(pMacHdr->addr1),
+ MAC_ADDR_ARRAY(pMacHdr->addr2),
+ MAC_ADDR_ARRAY(pMacHdr->addr3));
+
+ if (IS_QOS_ENABLED(psessionEntry)) {
+ pMacHdr->qosControl.tid = tid;
+ header_offset += sizeof(tSirMacDataHdr3a);
+ } else
+ header_offset += sizeof(tSirMacMgmtHdr);
+
+ /*
+ * Now form RFC1042 header
+ */
+ cdf_mem_copy((uint8_t *) (pFrame + header_offset),
+ (uint8_t *) eth_890d_header, sizeof(eth_890d_header));
+
+ header_offset += sizeof(eth_890d_header);
+
+ /* add payload type as TDLS */
+ *(pFrame + header_offset) = PAYLOAD_TYPE_TDLS;
+ header_offset += PAYLOAD_TYPE_TDLS_SIZE;
+ return header_offset;
+}
+
+/*
+ * TX Complete for Management frames
+ */
+CDF_STATUS lim_mgmt_tx_complete(tpAniSirGlobal pMac, uint32_t txCompleteSuccess)
+{
+ tpPESession psessionEntry = NULL;
+
+ if (0xff != pMac->lim.mgmtFrameSessionId) {
+ psessionEntry =
+ pe_find_session_by_session_id(pMac,
+ pMac->lim.mgmtFrameSessionId);
+ if (NULL == psessionEntry) {
+ lim_log(pMac, LOGE, FL("sessionID %d is not found"),
+ pMac->lim.mgmtFrameSessionId);
+ return CDF_STATUS_E_FAILURE;
+ }
+ lim_send_sme_mgmt_tx_completion(pMac, psessionEntry,
+ txCompleteSuccess);
+ pMac->lim.mgmtFrameSessionId = 0xff;
+ }
+ return CDF_STATUS_SUCCESS;
+}
+
+/*
+ * This function can be used for bacst or unicast discovery request
+ * We are not differentiating it here, it will all depnds on peer MAC address,
+ */
+tSirRetStatus lim_send_tdls_dis_req_frame(tpAniSirGlobal pMac, tSirMacAddr peer_mac,
+ uint8_t dialog, tpPESession psessionEntry)
+{
+ tDot11fTDLSDisReq tdlsDisReq;
+ uint32_t status = 0;
+ uint32_t nPayload = 0;
+ uint32_t size = 0;
+ uint32_t nBytes = 0;
+ uint32_t header_offset = 0;
+ uint8_t *pFrame;
+ void *pPacket;
+ CDF_STATUS cdf_status;
+#ifndef NO_PAD_TDLS_MIN_8023_SIZE
+ uint32_t padLen = 0;
+#endif
+ uint8_t smeSessionId = 0;
+
+ if (NULL == psessionEntry) {
+ lim_log(pMac, LOGE, FL("psessionEntry is NULL"));
+ return eSIR_FAILURE;
+ }
+ smeSessionId = psessionEntry->smeSessionId;
+ /*
+ * The scheme here is to fill out a 'tDot11fProbeRequest' structure
+ * and then hand it off to 'dot11f_pack_probe_request' (for
+ * serialization). We start by zero-initializing the structure:
+ */
+ cdf_mem_set((uint8_t *) &tdlsDisReq, sizeof(tDot11fTDLSDisReq), 0);
+
+ /*
+ * setup Fixed fields,
+ */
+ tdlsDisReq.Category.category = SIR_MAC_ACTION_TDLS;
+ tdlsDisReq.Action.action = SIR_MAC_TDLS_DIS_REQ;
+ tdlsDisReq.DialogToken.token = dialog;
+
+ size = sizeof(tSirMacAddr);
+
+ populate_dot11f_link_iden(pMac, psessionEntry, &tdlsDisReq.LinkIdentifier,
+ peer_mac, TDLS_INITIATOR);
+
+ /*
+ * now we pack it. First, how much space are we going to need?
+ */
+ status = dot11f_get_packed_tdls_dis_req_size(pMac, &tdlsDisReq, &nPayload);
+ if (DOT11F_FAILED(status)) {
+ lim_log(pMac, LOGP,
+ FL(
+ "Failed to calculate the packed size for a discovery Request (0x%08x)."
+ ),
+ status);
+ /* We'll fall back on the worst case scenario: */
+ nPayload = sizeof(tDot11fTDLSDisReq);
+ } else if (DOT11F_WARNED(status)) {
+ lim_log(pMac, LOGW,
+ FL(
+ "There were warnings while calculating the packed size for a discovery Request (0x%08x)."
+ ),
+ status);
+ }
+
+ /*
+ * This frame is going out from PE as data frames with special ethertype
+ * 89-0d.
+ * 8 bytes of RFC 1042 header
+ */
+
+ nBytes = nPayload + ((IS_QOS_ENABLED(psessionEntry))
+ ? sizeof(tSirMacDataHdr3a) :
+ sizeof(tSirMacMgmtHdr))
+ + sizeof(eth_890d_header)
+ + PAYLOAD_TYPE_TDLS_SIZE;
+
+#ifndef NO_PAD_TDLS_MIN_8023_SIZE
+ /* IOT issue with some AP : some AP doesn't like the data packet size < minimum 802.3 frame length (64)
+ Hence AP itself padding some bytes, which caused teardown packet is dropped at
+ receiver side. To avoid such IOT issue, we added some extra bytes to meet data frame size >= 64
+ */
+ if (nPayload + PAYLOAD_TYPE_TDLS_SIZE < MIN_IEEE_8023_SIZE) {
+ padLen =
+ MIN_IEEE_8023_SIZE - (nPayload + PAYLOAD_TYPE_TDLS_SIZE);
+
+ /* if padLen is less than minimum vendorSpecific (5), pad up to 5 */
+ if (padLen < MIN_VENDOR_SPECIFIC_IE_SIZE)
+ padLen = MIN_VENDOR_SPECIFIC_IE_SIZE;
+
+ nBytes += padLen;
+ }
+#endif
+
+ /* Ok-- try to allocate memory from MGMT PKT pool */
+
+ cdf_status = cds_packet_alloc((uint16_t) nBytes, (void **)&pFrame,
+ (void **)&pPacket);
+ if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
+ lim_log(pMac, LOGP,
+ FL(
+ "Failed to allocate %d bytes for a TDLS Discovery Request."
+ ),
+ nBytes);
+ return eSIR_MEM_ALLOC_FAILED;
+ }
+
+ /* zero out the memory */
+ cdf_mem_set(pFrame, nBytes, 0);
+
+ /*
+ * IE formation, memory allocation is completed, Now form TDLS discovery
+ * request frame
+ */
+
+ /* fill out the buffer descriptor */
+
+ header_offset = lim_prepare_tdls_frame_header(pMac, pFrame,
+ LINK_IDEN_ADDR_OFFSET
+ (tdlsDisReq), TDLS_LINK_AP,
+ TDLS_INITIATOR, TID_AC_VI,
+ psessionEntry);
+
+ status = dot11f_pack_tdls_dis_req(pMac, &tdlsDisReq, pFrame
+ + header_offset, nPayload, &nPayload);
+
+ if (DOT11F_FAILED(status)) {
+ lim_log(pMac, LOGE,
+ FL("Failed to pack a TDLS discovery req (0x%08x)."),
+ status);
+ cds_packet_free((void *)pPacket);
+ return eSIR_FAILURE;
+ } else if (DOT11F_WARNED(status)) {
+ lim_log(pMac, LOGW,
+ FL(
+ "There were warnings while packing TDLS Discovery Request (0x%08x)."
+ ),
+ status);
+ }
+#ifndef NO_PAD_TDLS_MIN_8023_SIZE
+ if (padLen != 0) {
+ /* QCOM VENDOR OUI = { 0x00, 0xA0, 0xC6, type = 0x0000 }; */
+ uint8_t *padVendorSpecific = pFrame + header_offset + nPayload;
+ /* make QCOM_VENDOR_OUI, and type = 0x0000, and all the payload to be zero */
+ padVendorSpecific[0] = 221;
+ padVendorSpecific[1] = padLen - 2;
+ padVendorSpecific[2] = 0x00;
+ padVendorSpecific[3] = 0xA0;
+ padVendorSpecific[4] = 0xC6;
+
+ lim_log(pMac, LOGW,
+ FL("Padding Vendor Specific Ie Len = %d"), padLen);
+
+ /* padding zero if more than 5 bytes are required */
+ if (padLen > MIN_VENDOR_SPECIFIC_IE_SIZE)
+ cdf_mem_set(pFrame + header_offset + nPayload +
+ MIN_VENDOR_SPECIFIC_IE_SIZE,
+ padLen - MIN_VENDOR_SPECIFIC_IE_SIZE, 0);
+ }
+#endif
+
+ lim_log(pMac, LOG1,
+ FL("[TDLS] action %d (%s) -AP-> OTA peer="MAC_ADDRESS_STR),
+ SIR_MAC_TDLS_DIS_REQ,
+ lim_trace_tdls_action_string(SIR_MAC_TDLS_DIS_REQ),
+ MAC_ADDR_ARRAY(peer_mac));
+
+ pMac->lim.mgmtFrameSessionId = psessionEntry->peSessionId;
+ cdf_status = wma_tx_frameWithTxComplete(pMac, pPacket, (uint16_t) nBytes,
+ TXRX_FRM_802_11_DATA,
+ ANI_TXDIR_TODS,
+ TID_AC_VI,
+ lim_tx_complete, pFrame,
+ lim_mgmt_tx_complete,
+ HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME,
+ smeSessionId, false, 0);
+ if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
+ pMac->lim.mgmtFrameSessionId = 0xff;
+ lim_log(pMac, LOGE,
+ FL("could not send TDLS Discovery Request frame"));
+ return eSIR_FAILURE;
+ }
+
+ return eSIR_SUCCESS;
+
+}
+
+/*
+ * This static function is consistent with any kind of TDLS management
+ * frames we are sending. Currently it is being used by lim_send_tdls_dis_rsp_frame,
+ * lim_send_tdls_link_setup_req_frame and lim_send_tdls_setup_rsp_frame
+ */
+static void populate_dot11f_tdls_ht_vht_cap(tpAniSirGlobal pMac,
+ uint32_t selfDot11Mode,
+ tDot11fIEHTCaps *htCap,
+ tDot11fIEVHTCaps *vhtCap,
+ tpPESession psessionEntry)
+{
+ if (IS_DOT11_MODE_HT(selfDot11Mode)) {
+ /* Include HT Capability IE */
+ populate_dot11f_ht_caps(pMac, NULL, htCap);
+ /*
+ * Advertise ht capability and max supported channel bandwidth
+ * when populating HT IE in TDLS Setup Request/Setup Response/
+ * Setup Confirmation frames.
+ * 11.21.6.2 Setting up a 40 MHz direct link: A 40 MHz
+ * off-channel direct link may be started if both TDLS peer STAs
+ * indicated 40 MHz support in the Supported Channel Width Set
+ * field of the HT Capabilities element (which is included in
+ * the TDLS Setup Request frame and the TDLS Setup Response
+ * frame). Switching to a 40 MHz off-channel direct link is
+ * achieved by including the following information in the TDLS
+ * Channel Switch Request
+ * 11.21.1 General: The channel width of the TDLS direct link on
+ * the base channel shall not exceed the channel width of the
+ * BSS to which the TDLS peer STAs are associated.
+ */
+ htCap->supportedChannelWidthSet = 1;
+ } else {
+ htCap->present = 0;
+ }
+ lim_log(pMac, LOG1, FL("HT present = %hu, Chan Width = %hu"),
+ htCap->present, htCap->supportedChannelWidthSet);
+#ifdef WLAN_FEATURE_11AC
+ if (((psessionEntry->currentOperChannel <= SIR_11B_CHANNEL_END) &&
+ pMac->roam.configParam.enableVhtFor24GHz) ||
+ (psessionEntry->currentOperChannel >= SIR_11B_CHANNEL_END)) {
+ if (IS_DOT11_MODE_VHT(selfDot11Mode) &&
+ IS_FEATURE_SUPPORTED_BY_FW(DOT11AC)) {
+ /* Include VHT Capability IE */
+ populate_dot11f_vht_caps(pMac, psessionEntry, vhtCap);
+ vhtCap->suBeamformeeCap = 0;
+ vhtCap->suBeamFormerCap = 0;
+ vhtCap->muBeamformeeCap = 0;
+ vhtCap->muBeamformerCap = 0;
+ } else {
+ vhtCap->present = 0;
+ }
+ } else {
+ /* Vht Disable from ini in 2.4 GHz */
+ vhtCap->present = 0;
+ }
+ lim_log(pMac, LOG1, FL("VHT present = %hu, Chan Width = %hu"),
+ vhtCap->present, vhtCap->supportedChannelWidthSet);
+#endif
+}
+
+/*
+ * Send TDLS discovery response frame on direct link.
+ */
+
+static tSirRetStatus lim_send_tdls_dis_rsp_frame(tpAniSirGlobal pMac,
+ tSirMacAddr peerMac, uint8_t dialog,
+ tpPESession psessionEntry,
+ uint8_t *addIe, uint16_t addIeLen)
+{
+ tDot11fTDLSDisRsp tdlsDisRsp;
+ uint16_t caps = 0;
+ uint32_t status = 0;
+ uint32_t nPayload = 0;
+ uint32_t nBytes = 0;
+ uint8_t *pFrame;
+ void *pPacket;
+ CDF_STATUS cdf_status;
+ uint32_t selfDot11Mode;
+/* Placeholder to support different channel bonding mode of TDLS than AP. */
+/* Today, WNI_CFG_CHANNEL_BONDING_MODE will be overwritten when connecting to AP */
+/* To support this feature, we need to introduce WNI_CFG_TDLS_CHANNEL_BONDING_MODE */
+/* As of now, we hardcoded to max channel bonding of dot11Mode (i.e HT80 for 11ac/HT40 for 11n) */
+/* uint32_t tdlsChannelBondingMode; */
+ uint8_t smeSessionId = 0;
+
+ if (NULL == psessionEntry) {
+ lim_log(pMac, LOGE, FL("psessionEntry is NULL"));
+ return eSIR_FAILURE;
+ }
+ smeSessionId = psessionEntry->smeSessionId;
+
+ /*
+ * The scheme here is to fill out a 'tDot11fProbeRequest' structure
+ * and then hand it off to 'dot11f_pack_probe_request' (for
+ * serialization). We start by zero-initializing the structure:
+ */
+ cdf_mem_set((uint8_t *) &tdlsDisRsp, sizeof(tDot11fTDLSDisRsp), 0);
+
+ /*
+ * setup Fixed fields,
+ */
+ tdlsDisRsp.Category.category = SIR_MAC_ACTION_PUBLIC_USAGE;
+ tdlsDisRsp.Action.action = SIR_MAC_TDLS_DIS_RSP;
+ tdlsDisRsp.DialogToken.token = dialog;
+
+ populate_dot11f_link_iden(pMac, psessionEntry,
+ &tdlsDisRsp.LinkIdentifier,
+ peerMac, TDLS_RESPONDER);
+
+ if (cfg_get_capability_info(pMac, &caps, psessionEntry)
+ != eSIR_SUCCESS) {
+ /*
+ * Could not get Capabilities value
+ * from CFG. Log error.
+ */
+ lim_log(pMac, LOGE,
+ FL("could not retrieve Capabilities value"));
+ }
+ swap_bit_field16(caps, (uint16_t *) &tdlsDisRsp.Capabilities);
+
+ /* populate supported rate and ext supported rate IE */
+ if (eSIR_FAILURE == populate_dot11f_rates_tdls(pMac,
+ &tdlsDisRsp.SuppRates,
+ &tdlsDisRsp.ExtSuppRates))
+ lim_log(pMac, LOGE,
+ FL("could not populate supported data rates"));
+
+ /* populate extended capability IE */
+ populate_dot11f_tdls_ext_capability(pMac,
+ psessionEntry,
+ &tdlsDisRsp.ExtCap);
+
+ wlan_cfg_get_int(pMac, WNI_CFG_DOT11_MODE, &selfDot11Mode);
+
+ /* Populate HT/VHT Capabilities */
+ populate_dot11f_tdls_ht_vht_cap(pMac, selfDot11Mode, &tdlsDisRsp.HTCaps,
+ &tdlsDisRsp.VHTCaps, psessionEntry);
+
+ /* Populate TDLS offchannel param only if offchannel is enabled
+ * and TDLS Channel Switching is not prohibited by AP in ExtCap
+ * IE in assoc/re-assoc response.
+ */
+ if ((1 == pMac->lim.gLimTDLSOffChannelEnabled) &&
+ (!psessionEntry->tdls_chan_swit_prohibited)) {
+ populate_dot11f_tdls_offchannel_params(pMac, psessionEntry,
+ &tdlsDisRsp.SuppChannels,
+ &tdlsDisRsp.
+ SuppOperatingClasses);
+ if (pMac->roam.configParam.bandCapability != eCSR_BAND_24) {
+ tdlsDisRsp.ht2040_bss_coexistence.present = 1;
+ tdlsDisRsp.ht2040_bss_coexistence.info_request = 1;
+ }
+ } else {
+ lim_log(pMac, LOG1,
+ FL("TDLS offchan not enabled, or channel switch prohibited by AP, gLimTDLSOffChannelEnabled (%d), tdls_chan_swit_prohibited (%d)"),
+ pMac->lim.gLimTDLSOffChannelEnabled,
+ psessionEntry->tdls_chan_swit_prohibited);
+ }
+ /*
+ * now we pack it. First, how much space are we going to need?
+ */
+ status = dot11f_get_packed_tdls_dis_rsp_size(pMac, &tdlsDisRsp, &nPayload);
+ if (DOT11F_FAILED(status)) {
+ lim_log(pMac, LOGE,
+ FL(
+ "Failed to calculate the packed size for a Discovery Response (0x%08x)."
+ ),
+ status);
+ /* We'll fall back on the worst case scenario: */
+ nPayload = sizeof(tDot11fProbeRequest);
+ } else if (DOT11F_WARNED(status)) {
+ lim_log(pMac, LOGW,
+ FL(
+ "There were warnings while calculating the packed size for a Discovery Response (0x%08x)."
+ ),
+ status);
+ }
+
+ /*
+ * This frame is going out from PE as data frames with special ethertype
+ * 89-0d.
+ * 8 bytes of RFC 1042 header
+ */
+
+ nBytes = nPayload + sizeof(tSirMacMgmtHdr) + addIeLen;
+
+ /* Ok-- try to allocate memory from MGMT PKT pool */
+ cdf_status = cds_packet_alloc((uint16_t) nBytes, (void **)&pFrame,
+ (void **)&pPacket);
+ if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
+ lim_log(pMac, LOGE,
+ FL(
+ "Failed to allocate %d bytes for a TDLS Discovery Request."
+ ),
+ nBytes);
+ return eSIR_MEM_ALLOC_FAILED;
+ }
+
+ /* zero out the memory */
+ cdf_mem_set(pFrame, nBytes, 0);
+
+ /*
+ * IE formation, memory allocation is completed, Now form TDLS discovery
+ * response frame
+ */
+
+ /* Make public Action Frame */
+
+ lim_populate_mac_header(pMac, pFrame, SIR_MAC_MGMT_FRAME,
+ SIR_MAC_MGMT_ACTION, peerMac,
+ psessionEntry->selfMacAddr);
+
+ {
+ tpSirMacMgmtHdr pMacHdr;
+ pMacHdr = (tpSirMacMgmtHdr) pFrame;
+ pMacHdr->fc.toDS = ANI_TXDIR_IBSS;
+ pMacHdr->fc.powerMgmt = 0;
+ sir_copy_mac_addr(pMacHdr->bssId, psessionEntry->bssId);
+ }
+
+ status = dot11f_pack_tdls_dis_rsp(pMac, &tdlsDisRsp, pFrame +
+ sizeof(tSirMacMgmtHdr),
+ nPayload, &nPayload);
+
+ if (DOT11F_FAILED(status)) {
+ lim_log(pMac, LOGE,
+ FL(
+ "Failed to pack a TDLS discovery response (0x%08x)."
+ ),
+ status);
+ cds_packet_free((void *)pPacket);
+ return eSIR_FAILURE;
+ } else if (DOT11F_WARNED(status)) {
+ lim_log(pMac, LOGW,
+ FL(
+ "There were warnings while packing TDLS Discovery Response (0x%08x)."
+ ),
+ status);
+ }
+ if (0 != addIeLen) {
+ lim_log(pMac, LOG1,
+ FL("Copy Additional Ie Len = %d"), addIeLen);
+ cdf_mem_copy(pFrame + sizeof(tSirMacMgmtHdr) + nPayload, addIe,
+ addIeLen);
+ }
+ lim_log(pMac, LOG1,
+ FL("[TDLS] action %d (%s) -DIRECT-> OTA peer="MAC_ADDRESS_STR),
+ SIR_MAC_TDLS_DIS_RSP,
+ lim_trace_tdls_action_string(SIR_MAC_TDLS_DIS_RSP),
+ MAC_ADDR_ARRAY(peerMac));
+
+ pMac->lim.mgmtFrameSessionId = psessionEntry->peSessionId;
+ /*
+ * Transmit Discovery response and watch if this is delivered to
+ * peer STA.
+ */
+ /* In CLD 2.0, pass Discovery Response as mgmt frame so that
+ * wma does not do header conversion to 802.3 before calling tx/rx
+ * routine and subsequenly target also sends frame as is OTA
+ */
+ cdf_status = wma_tx_frameWithTxComplete(pMac, pPacket, (uint16_t) nBytes,
+ TXRX_FRM_802_11_MGMT,
+ ANI_TXDIR_IBSS,
+ 0,
+ lim_tx_complete, pFrame,
+ lim_mgmt_tx_complete,
+ HAL_USE_SELF_STA_REQUESTED_MASK,
+ smeSessionId, false, 0);
+ if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
+ pMac->lim.mgmtFrameSessionId = 0xff;
+ lim_log(pMac, LOGE,
+ FL("could not send TDLS Discovery Response frame!"));
+ return eSIR_FAILURE;
+ }
+
+ return eSIR_SUCCESS;
+
+}
+
+/*
+ * This static function is currently used by lim_send_tdls_link_setup_req_frame and
+ * lim_send_tdls_setup_rsp_frame to populate the AID if device is 11ac capable.
+ */
+static void populate_dotf_tdls_vht_aid(tpAniSirGlobal pMac, uint32_t selfDot11Mode,
+ tSirMacAddr peerMac, tDot11fIEAID *Aid,
+ tpPESession psessionEntry)
+{
+ if (((psessionEntry->currentOperChannel <= SIR_11B_CHANNEL_END) &&
+ pMac->roam.configParam.enableVhtFor24GHz) ||
+ (psessionEntry->currentOperChannel >= SIR_11B_CHANNEL_END)) {
+ if (IS_DOT11_MODE_VHT(selfDot11Mode) &&
+ IS_FEATURE_SUPPORTED_BY_FW(DOT11AC)) {
+
+ uint16_t aid;
+ tpDphHashNode pStaDs;
+
+ pStaDs =
+ dph_lookup_hash_entry(pMac, peerMac, &aid,
+ &psessionEntry->dph.
+ dphHashTable);
+ if (NULL != pStaDs) {
+ Aid->present = 1;
+ Aid->assocId = aid | LIM_AID_MASK; /* set bit 14 and 15 1's */
+ } else {
+ Aid->present = 0;
+ lim_log(pMac, LOGE,
+ FL("pStaDs is NULL for "
+ MAC_ADDRESS_STR),
+ MAC_ADDR_ARRAY(peerMac));
+ }
+ }
+ } else {
+ Aid->present = 0;
+ lim_log(pMac, LOGW, FL("Vht not enable from ini for 2.4GHz."));
+ }
+}
+
+/*
+ * TDLS setup Request frame on AP link
+ */
+
+tSirRetStatus lim_send_tdls_link_setup_req_frame(tpAniSirGlobal pMac,
+ tSirMacAddr peerMac, uint8_t dialog,
+ tpPESession psessionEntry,
+ uint8_t *addIe, uint16_t addIeLen)
+{
+ tDot11fTDLSSetupReq tdlsSetupReq;
+ uint16_t caps = 0;
+ uint32_t status = 0;
+ uint32_t nPayload = 0;
+ uint32_t nBytes = 0;
+ uint32_t header_offset = 0;
+ uint8_t *pFrame;
+ void *pPacket;
+ CDF_STATUS cdf_status;
+ uint32_t selfDot11Mode;
+ uint8_t smeSessionId = 0;
+/* Placeholder to support different channel bonding mode of TDLS than AP. */
+/* Today, WNI_CFG_CHANNEL_BONDING_MODE will be overwritten when connecting to AP */
+/* To support this feature, we need to introduce WNI_CFG_TDLS_CHANNEL_BONDING_MODE */
+/* As of now, we hardcoded to max channel bonding of dot11Mode (i.e HT80 for 11ac/HT40 for 11n) */
+/* uint32_t tdlsChannelBondingMode; */
+
+ /*
+ * The scheme here is to fill out a 'tDot11fProbeRequest' structure
+ * and then hand it off to 'dot11f_pack_probe_request' (for
+ * serialization). We start by zero-initializing the structure:
+ */
+ smeSessionId = psessionEntry->smeSessionId;
+
+ cdf_mem_set((uint8_t *) &tdlsSetupReq, sizeof(tDot11fTDLSSetupReq), 0);
+ tdlsSetupReq.Category.category = SIR_MAC_ACTION_TDLS;
+ tdlsSetupReq.Action.action = SIR_MAC_TDLS_SETUP_REQ;
+ tdlsSetupReq.DialogToken.token = dialog;
+
+ populate_dot11f_link_iden(pMac, psessionEntry,
+ &tdlsSetupReq.LinkIdentifier, peerMac,
+ TDLS_INITIATOR);
+
+ if (cfg_get_capability_info(pMac, &caps, psessionEntry) != eSIR_SUCCESS) {
+ /*
+ * Could not get Capabilities value
+ * from CFG. Log error.
+ */
+ lim_log(pMac, LOGE,
+ FL("could not retrieve Capabilities value"));
+ }
+ swap_bit_field16(caps, (uint16_t *) &tdlsSetupReq.Capabilities);
+
+ /* populate supported rate and ext supported rate IE */
+ if (eSIR_FAILURE == populate_dot11f_rates_tdls(pMac,
+ &tdlsSetupReq.SuppRates,
+ &tdlsSetupReq.ExtSuppRates))
+ lim_log(pMac, LOGE,
+ FL("could not populate supported data rates"));
+
+ /* Populate extended capability IE */
+ populate_dot11f_tdls_ext_capability(pMac,
+ psessionEntry,
+ &tdlsSetupReq.ExtCap);
+
+ if (1 == pMac->lim.gLimTDLSWmmMode) {
+ uint32_t val = 0;
+
+ lim_log(pMac, LOG1,
+ FL("populate WMM IE in Setup Request Frame"));
+ /* include WMM IE */
+ tdlsSetupReq.WMMInfoStation.version = SIR_MAC_OUI_VERSION_1;
+ tdlsSetupReq.WMMInfoStation.acvo_uapsd =
+ (pMac->lim.gLimTDLSUapsdMask & 0x01);
+ tdlsSetupReq.WMMInfoStation.acvi_uapsd =
+ ((pMac->lim.gLimTDLSUapsdMask & 0x02) >> 1);
+ tdlsSetupReq.WMMInfoStation.acbk_uapsd =
+ ((pMac->lim.gLimTDLSUapsdMask & 0x04) >> 2);
+ tdlsSetupReq.WMMInfoStation.acbe_uapsd =
+ ((pMac->lim.gLimTDLSUapsdMask & 0x08) >> 3);
+
+ if (wlan_cfg_get_int(pMac, WNI_CFG_MAX_SP_LENGTH, &val) !=
+ eSIR_SUCCESS)
+ lim_log(pMac, LOGE,
+ FL("could not retrieve Max SP Length"));
+
+ tdlsSetupReq.WMMInfoStation.max_sp_length = (uint8_t) val;
+ tdlsSetupReq.WMMInfoStation.present = 1;
+ } else {
+ /*
+ * TODO: we need to see if we have to support conditions where
+ * we have EDCA parameter info element is needed a) if we need
+ * different QOS parameters for off channel operations or QOS
+ * is not supported on AP link and we wanted to QOS on direct
+ * link.
+ */
+
+ /* Populate QOS info, needed for Peer U-APSD session */
+
+ /*
+ * TODO: Now hardcoded, since populate_dot11f_qos_caps_station()
+ * depends on AP's capability, and TDLS doesn't want to depend
+ * on AP's capability
+ */
+
+ lim_log(pMac, LOG1,
+ FL("populate QOS IE in Setup Request Frame"));
+ tdlsSetupReq.QOSCapsStation.present = 1;
+ tdlsSetupReq.QOSCapsStation.max_sp_length = 0;
+ tdlsSetupReq.QOSCapsStation.qack = 0;
+ tdlsSetupReq.QOSCapsStation.acbe_uapsd =
+ ((pMac->lim.gLimTDLSUapsdMask & 0x08) >> 3);
+ tdlsSetupReq.QOSCapsStation.acbk_uapsd =
+ ((pMac->lim.gLimTDLSUapsdMask & 0x04) >> 2);
+ tdlsSetupReq.QOSCapsStation.acvi_uapsd =
+ ((pMac->lim.gLimTDLSUapsdMask & 0x02) >> 1);
+ tdlsSetupReq.QOSCapsStation.acvo_uapsd =
+ (pMac->lim.gLimTDLSUapsdMask & 0x01);
+ }
+
+ /*
+ * we will always try to init TDLS link with 11n capabilities
+ * let TDLS setup response to come, and we will set our caps based
+ * of peer caps
+ */
+
+ wlan_cfg_get_int(pMac, WNI_CFG_DOT11_MODE, &selfDot11Mode);
+
+ /* Populate HT/VHT Capabilities */
+ populate_dot11f_tdls_ht_vht_cap(pMac, selfDot11Mode, &tdlsSetupReq.HTCaps,
+ &tdlsSetupReq.VHTCaps, psessionEntry);
+
+ /* Populate AID */
+ populate_dotf_tdls_vht_aid(pMac, selfDot11Mode, peerMac,
+ &tdlsSetupReq.AID, psessionEntry);
+
+ /* Populate TDLS offchannel param only if offchannel is enabled
+ * and TDLS Channel Switching is not prohibited by AP in ExtCap
+ * IE in assoc/re-assoc response.
+ */
+ if ((1 == pMac->lim.gLimTDLSOffChannelEnabled) &&
+ (!psessionEntry->tdls_chan_swit_prohibited)) {
+ populate_dot11f_tdls_offchannel_params(pMac, psessionEntry,
+ &tdlsSetupReq.SuppChannels,
+ &tdlsSetupReq.
+ SuppOperatingClasses);
+ if (pMac->roam.configParam.bandCapability != eCSR_BAND_24) {
+ tdlsSetupReq.ht2040_bss_coexistence.present = 1;
+ tdlsSetupReq.ht2040_bss_coexistence.info_request = 1;
+ }
+ } else {
+ lim_log(pMac, LOG1,
+ FL("TDLS offchan not enabled, or channel switch prohibited by AP, gLimTDLSOffChannelEnabled (%d), tdls_chan_swit_prohibited (%d)"),
+ pMac->lim.gLimTDLSOffChannelEnabled,
+ psessionEntry->tdls_chan_swit_prohibited);
+ }
+ /*
+ * now we pack it. First, how much space are we going to need?
+ */
+ status = dot11f_get_packed_tdls_setup_req_size(pMac, &tdlsSetupReq,
+ &nPayload);
+ if (DOT11F_FAILED(status)) {
+ lim_log(pMac, LOGE,
+ FL(
+ "Failed to calculate the packed size for a Setup Request (0x%08x)."
+ ),
+ status);
+ /* We'll fall back on the worst case scenario: */
+ nPayload = sizeof(tDot11fProbeRequest);
+ } else if (DOT11F_WARNED(status)) {
+ lim_log(pMac, LOGW,
+ FL(
+ "There were warnings while calculating the packed size for a Setup Request (0x%08x)."
+ ),
+ status);
+ }
+
+ /*
+ * This frame is going out from PE as data frames with special ethertype
+ * 89-0d.
+ * 8 bytes of RFC 1042 header
+ */
+
+ nBytes = nPayload + ((IS_QOS_ENABLED(psessionEntry))
+ ? sizeof(tSirMacDataHdr3a) :
+ sizeof(tSirMacMgmtHdr))
+ + sizeof(eth_890d_header)
+ + PAYLOAD_TYPE_TDLS_SIZE + addIeLen;
+
+ /* Ok-- try to allocate memory from MGMT PKT pool */
+ cdf_status = cds_packet_alloc((uint16_t) nBytes, (void **)&pFrame,
+ (void **)&pPacket);
+ if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
+ lim_log(pMac, LOGE,
+ FL(
+ "Failed to allocate %d bytes for a TDLS Setup Request."
+ ),
+ nBytes);
+ return eSIR_MEM_ALLOC_FAILED;
+ }
+
+ /* zero out the memory */
+ cdf_mem_set(pFrame, nBytes, 0);
+
+ /*
+ * IE formation, memory allocation is completed, Now form TDLS discovery
+ * request frame
+ */
+
+ /* fill out the buffer descriptor */
+
+ header_offset = lim_prepare_tdls_frame_header(pMac, pFrame,
+ LINK_IDEN_ADDR_OFFSET
+ (tdlsSetupReq), TDLS_LINK_AP,
+ TDLS_INITIATOR, TID_AC_BK,
+ psessionEntry);
+
+ lim_log(pMac, LOGW,
+ FL(
+ "SupportedChnlWidth %x rxMCSMap %x rxMCSMap %x txSupDataRate %x"
+ ),
+ tdlsSetupReq.VHTCaps.supportedChannelWidthSet,
+ tdlsSetupReq.VHTCaps.rxMCSMap,
+ tdlsSetupReq.VHTCaps.txMCSMap,
+ tdlsSetupReq.VHTCaps.txSupDataRate);
+
+ status = dot11f_pack_tdls_setup_req(pMac, &tdlsSetupReq, pFrame
+ + header_offset, nPayload, &nPayload);
+
+ if (DOT11F_FAILED(status)) {
+ lim_log(pMac, LOGE,
+ FL("Failed to pack a TDLS Setup request (0x%08x)."),
+ status);
+ cds_packet_free((void *)pPacket);
+ return eSIR_FAILURE;
+ } else if (DOT11F_WARNED(status)) {
+ lim_log(pMac, LOGW,
+ FL(
+ "There were warnings while packing TDLS Setup Request (0x%08x)."
+ ),
+ status);
+ }
+ /* Copy the additional IE. */
+ /* TODO : addIe is added at the end of the frame. This means it doesnt */
+ /* follow the order. This should be ok, but we should consider changing this */
+ /* if there is any IOT issue. */
+ if (addIeLen != 0) {
+ lim_log(pMac, LOG1, FL("Copy Additional Ie Len = %d"),
+ addIeLen);
+ cdf_mem_copy(pFrame + header_offset + nPayload, addIe,
+ addIeLen);
+ }
+
+ lim_log(pMac, LOG1,
+ FL("[TDLS] action %d (%s) -AP-> OTA peer="MAC_ADDRESS_STR),
+ SIR_MAC_TDLS_SETUP_REQ,
+ lim_trace_tdls_action_string(SIR_MAC_TDLS_SETUP_REQ),
+ MAC_ADDR_ARRAY(peerMac));
+
+ pMac->lim.mgmtFrameSessionId = psessionEntry->peSessionId;
+
+ cdf_status = wma_tx_frameWithTxComplete(pMac, pPacket, (uint16_t) nBytes,
+ TXRX_FRM_802_11_DATA,
+ ANI_TXDIR_TODS,
+ TID_AC_BK,
+ lim_tx_complete, pFrame,
+ lim_mgmt_tx_complete,
+ HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME,
+ smeSessionId, false, 0);
+
+ if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
+ pMac->lim.mgmtFrameSessionId = 0xff;
+ lim_log(pMac, LOGE,
+ FL("could not send TDLS Setup Request frame!"));
+ return eSIR_FAILURE;
+ }
+
+ return eSIR_SUCCESS;
+
+}
+
+/*
+ * Send TDLS Teardown frame on Direct link or AP link, depends on reason code.
+ */
+
+tSirRetStatus lim_send_tdls_teardown_frame(tpAniSirGlobal pMac,
+ tSirMacAddr peerMac, uint16_t reason,
+ uint8_t responder,
+ tpPESession psessionEntry,
+ uint8_t *addIe, uint16_t addIeLen)
+{
+ tDot11fTDLSTeardown teardown;
+ uint32_t status = 0;
+ uint32_t nPayload = 0;
+ uint32_t nBytes = 0;
+ uint32_t header_offset = 0;
+ uint8_t *pFrame;
+ void *pPacket;
+ CDF_STATUS cdf_status;
+#ifndef NO_PAD_TDLS_MIN_8023_SIZE
+ uint32_t padLen = 0;
+#endif
+ uint8_t smeSessionId = 0;
+
+ if (NULL == psessionEntry) {
+ lim_log(pMac, LOGE, FL("psessionEntry is NULL"));
+ return eSIR_FAILURE;
+ }
+ smeSessionId = psessionEntry->smeSessionId;
+ /*
+ * The scheme here is to fill out a 'tDot11fProbeRequest' structure
+ * and then hand it off to 'dot11f_pack_probe_request' (for
+ * serialization). We start by zero-initializing the structure:
+ */
+ cdf_mem_set((uint8_t *) &teardown, sizeof(tDot11fTDLSTeardown), 0);
+ teardown.Category.category = SIR_MAC_ACTION_TDLS;
+ teardown.Action.action = SIR_MAC_TDLS_TEARDOWN;
+ teardown.Reason.code = reason;
+
+ populate_dot11f_link_iden(pMac, psessionEntry, &teardown.LinkIdentifier,
+ peerMac,
+ (responder ==
+ true) ? TDLS_RESPONDER : TDLS_INITIATOR);
+
+ /*
+ * now we pack it. First, how much space are we going to need?
+ */
+ status = dot11f_get_packed_tdls_teardown_size(pMac, &teardown, &nPayload);
+ if (DOT11F_FAILED(status)) {
+ lim_log(pMac, LOGE,
+ FL(
+ "Failed to calculate the packed size for a discovery Request (0x%08x)."
+ ),
+ status);
+ /* We'll fall back on the worst case scenario: */
+ nPayload = sizeof(tDot11fProbeRequest);
+ } else if (DOT11F_WARNED(status)) {
+ lim_log(pMac, LOGW,
+ FL(
+ "There were warnings while calculating the packed size for a discovery Request (0x%08x)."
+ ),
+ status);
+ }
+
+ /*
+ * This frame is going out from PE as data frames with special ethertype
+ * 89-0d.
+ * 8 bytes of RFC 1042 header
+ */
+
+ nBytes = nPayload + ((IS_QOS_ENABLED(psessionEntry))
+ ? sizeof(tSirMacDataHdr3a) :
+ sizeof(tSirMacMgmtHdr))
+ + sizeof(eth_890d_header)
+ + PAYLOAD_TYPE_TDLS_SIZE + addIeLen;
+
+#ifndef NO_PAD_TDLS_MIN_8023_SIZE
+ /* IOT issue with some AP : some AP doesn't like the data packet size < minimum 802.3 frame length (64)
+ Hence AP itself padding some bytes, which caused teardown packet is dropped at
+ receiver side. To avoid such IOT issue, we added some extra bytes to meet data frame size >= 64
+ */
+ if (nPayload + PAYLOAD_TYPE_TDLS_SIZE < MIN_IEEE_8023_SIZE) {
+ padLen =
+ MIN_IEEE_8023_SIZE - (nPayload + PAYLOAD_TYPE_TDLS_SIZE);
+
+ /* if padLen is less than minimum vendorSpecific (5), pad up to 5 */
+ if (padLen < MIN_VENDOR_SPECIFIC_IE_SIZE)
+ padLen = MIN_VENDOR_SPECIFIC_IE_SIZE;
+
+ nBytes += padLen;
+ }
+#endif
+
+ /* Ok-- try to allocate memory from MGMT PKT pool */
+ cdf_status = cds_packet_alloc((uint16_t) nBytes, (void **)&pFrame,
+ (void **)&pPacket);
+ if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
+ lim_log(pMac, LOGE,
+ FL(
+ "Failed to allocate %d bytes for a TDLS Teardown Frame."
+ ),
+ nBytes);
+ return eSIR_MEM_ALLOC_FAILED;
+ }
+
+ /* zero out the memory */
+ cdf_mem_set(pFrame, nBytes, 0);
+
+ /*
+ * IE formation, memory allocation is completed, Now form TDLS discovery
+ * request frame
+ */
+
+ /* fill out the buffer descriptor */
+ lim_log(pMac, LOGE, FL("Reason of TDLS Teardown: %d"), reason);
+ header_offset = lim_prepare_tdls_frame_header(pMac, pFrame,
+ LINK_IDEN_ADDR_OFFSET
+ (teardown),
+ (reason ==
+ eSIR_MAC_TDLS_TEARDOWN_PEER_UNREACHABLE)
+ ? TDLS_LINK_AP :
+ TDLS_LINK_DIRECT,
+ (responder ==
+ true) ? TDLS_RESPONDER :
+ TDLS_INITIATOR, TID_AC_VI,
+ psessionEntry);
+
+ status = dot11f_pack_tdls_teardown(pMac, &teardown, pFrame
+ + header_offset, nPayload, &nPayload);
+
+ if (DOT11F_FAILED(status)) {
+ lim_log(pMac, LOGE,
+ FL("Failed to pack a TDLS Teardown frame (0x%08x)."),
+ status);
+ cds_packet_free((void *)pPacket);
+ return eSIR_FAILURE;
+ } else if (DOT11F_WARNED(status)) {
+ lim_log(pMac, LOGW,
+ FL(
+ "There were warnings while packing TDLS Teardown frame (0x%08x)."
+ ),
+ status);
+ }
+
+ if (addIeLen != 0) {
+ lim_log(pMac, LOGW,
+ FL("Copy Additional Ie Len = %d"), addIeLen);
+ cdf_mem_copy(pFrame + header_offset + nPayload, addIe,
+ addIeLen);
+ }
+#ifndef NO_PAD_TDLS_MIN_8023_SIZE
+ if (padLen != 0) {
+ /* QCOM VENDOR OUI = { 0x00, 0xA0, 0xC6, type = 0x0000 }; */
+ uint8_t *padVendorSpecific =
+ pFrame + header_offset + nPayload + addIeLen;
+ /* make QCOM_VENDOR_OUI, and type = 0x0000, and all the payload to be zero */
+ padVendorSpecific[0] = 221;
+ padVendorSpecific[1] = padLen - 2;
+ padVendorSpecific[2] = 0x00;
+ padVendorSpecific[3] = 0xA0;
+ padVendorSpecific[4] = 0xC6;
+
+ lim_log(pMac, LOG1, FL("Padding Vendor Specific Ie Len = %d"),
+ padLen);
+
+ /* padding zero if more than 5 bytes are required */
+ if (padLen > MIN_VENDOR_SPECIFIC_IE_SIZE)
+ cdf_mem_set(pFrame + header_offset + nPayload +
+ addIeLen + MIN_VENDOR_SPECIFIC_IE_SIZE,
+ padLen - MIN_VENDOR_SPECIFIC_IE_SIZE, 0);
+ }
+#endif
+ lim_log(pMac, LOG1,
+ FL("[TDLS] action %d (%s) -%s-> OTA peer="MAC_ADDRESS_STR),
+ SIR_MAC_TDLS_TEARDOWN,
+ lim_trace_tdls_action_string(SIR_MAC_TDLS_TEARDOWN),
+ ((reason == eSIR_MAC_TDLS_TEARDOWN_PEER_UNREACHABLE) ? "AP" :
+ "DIRECT"),
+ MAC_ADDR_ARRAY(peerMac));
+
+ pMac->lim.mgmtFrameSessionId = psessionEntry->peSessionId;
+
+ cdf_status = wma_tx_frameWithTxComplete(pMac, pPacket, (uint16_t) nBytes,
+ TXRX_FRM_802_11_DATA,
+ ANI_TXDIR_TODS,
+ TID_AC_VI,
+ lim_tx_complete, pFrame,
+ lim_mgmt_tx_complete,
+ HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME,
+ smeSessionId, false, 0);
+
+ if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
+ pMac->lim.mgmtFrameSessionId = 0xff;
+ lim_log(pMac, LOGE,
+ FL("could not send TDLS Teardown frame"));
+ return eSIR_FAILURE;
+
+ }
+ return eSIR_SUCCESS;
+
+}
+
+/*
+ * Send Setup RSP frame on AP link.
+ */
+static tSirRetStatus lim_send_tdls_setup_rsp_frame(tpAniSirGlobal pMac,
+ tSirMacAddr peerMac,
+ uint8_t dialog,
+ tpPESession psessionEntry,
+ etdlsLinkSetupStatus setupStatus,
+ uint8_t *addIe,
+ uint16_t addIeLen)
+{
+ tDot11fTDLSSetupRsp tdlsSetupRsp;
+ uint32_t status = 0;
+ uint16_t caps = 0;
+ uint32_t nPayload = 0;
+ uint32_t header_offset = 0;
+ uint32_t nBytes = 0;
+ uint8_t *pFrame;
+ void *pPacket;
+ CDF_STATUS cdf_status;
+ uint32_t selfDot11Mode;
+/* Placeholder to support different channel bonding mode of TDLS than AP. */
+/* Today, WNI_CFG_CHANNEL_BONDING_MODE will be overwritten when connecting to AP */
+/* To support this feature, we need to introduce WNI_CFG_TDLS_CHANNEL_BONDING_MODE */
+/* As of now, we hardcoded to max channel bonding of dot11Mode (i.e HT80 for 11ac/HT40 for 11n) */
+/* uint32_t tdlsChannelBondingMode; */
+ uint8_t smeSessionId = 0;
+
+ if (NULL == psessionEntry) {
+ lim_log(pMac, LOGE, FL("psessionEntry is NULL"));
+ return eSIR_FAILURE;
+ }
+ smeSessionId = psessionEntry->smeSessionId;
+
+ /*
+ * The scheme here is to fill out a 'tDot11fProbeRequest' structure
+ * and then hand it off to 'dot11f_pack_probe_request' (for
+ * serialization). We start by zero-initializing the structure:
+ */
+ cdf_mem_set((uint8_t *) &tdlsSetupRsp, sizeof(tDot11fTDLSSetupRsp), 0);
+
+ /*
+ * setup Fixed fields,
+ */
+ tdlsSetupRsp.Category.category = SIR_MAC_ACTION_TDLS;
+ tdlsSetupRsp.Action.action = SIR_MAC_TDLS_SETUP_RSP;
+ tdlsSetupRsp.DialogToken.token = dialog;
+
+ populate_dot11f_link_iden(pMac, psessionEntry,
+ &tdlsSetupRsp.LinkIdentifier, peerMac,
+ TDLS_RESPONDER);
+
+ if (cfg_get_capability_info(pMac, &caps, psessionEntry) != eSIR_SUCCESS) {
+ /*
+ * Could not get Capabilities value
+ * from CFG. Log error.
+ */
+ lim_log(pMac, LOGE,
+ FL("could not retrieve Capabilities value"));
+ }
+ swap_bit_field16(caps, (uint16_t *) &tdlsSetupRsp.Capabilities);
+
+ /* populate supported rate and ext supported rate IE */
+ if (eSIR_FAILURE == populate_dot11f_rates_tdls(pMac,
+ &tdlsSetupRsp.SuppRates,
+ &tdlsSetupRsp.ExtSuppRates))
+ lim_log(pMac, LOGE,
+ FL("could not populate supported data rates"));
+
+ /* Populate extended capability IE */
+ populate_dot11f_tdls_ext_capability(pMac,
+ psessionEntry,
+ &tdlsSetupRsp.ExtCap);
+
+ if (1 == pMac->lim.gLimTDLSWmmMode) {
+ uint32_t val = 0;
+
+ lim_log(pMac, LOG1,
+ FL("populate WMM IE in Setup Response frame"));
+ /* include WMM IE */
+ tdlsSetupRsp.WMMInfoStation.version = SIR_MAC_OUI_VERSION_1;
+ tdlsSetupRsp.WMMInfoStation.acvo_uapsd =
+ (pMac->lim.gLimTDLSUapsdMask & 0x01);
+ tdlsSetupRsp.WMMInfoStation.acvi_uapsd =
+ ((pMac->lim.gLimTDLSUapsdMask & 0x02) >> 1);
+ tdlsSetupRsp.WMMInfoStation.acbk_uapsd =
+ ((pMac->lim.gLimTDLSUapsdMask & 0x04) >> 2);
+ tdlsSetupRsp.WMMInfoStation.acbe_uapsd =
+ ((pMac->lim.gLimTDLSUapsdMask & 0x08) >> 3);
+ if (wlan_cfg_get_int(pMac, WNI_CFG_MAX_SP_LENGTH, &val) !=
+ eSIR_SUCCESS)
+ lim_log(pMac, LOGE,
+ FL("could not retrieve Max SP Length"));
+ tdlsSetupRsp.WMMInfoStation.max_sp_length = (uint8_t) val;
+ tdlsSetupRsp.WMMInfoStation.present = 1;
+ } else {
+ /*
+ * TODO: we need to see if we have to support conditions where
+ * we have EDCA parameter info element is needed a) if we need
+ * different QOS parameters for off channel operations or QOS
+ * is not supported on AP link and we wanted to QOS on direct
+ * link.
+ */
+ /* Populate QOS info, needed for Peer U-APSD session */
+ /*
+ * TODO: Now hardcoded, because
+ * populate_dot11f_qos_caps_station() depends on AP's
+ * capability, and TDLS doesn't want to depend on AP's
+ * capability
+ */
+ lim_log(pMac, LOG1,
+ FL("populate QOS IE in Setup Response frame"));
+ tdlsSetupRsp.QOSCapsStation.present = 1;
+ tdlsSetupRsp.QOSCapsStation.max_sp_length = 0;
+ tdlsSetupRsp.QOSCapsStation.qack = 0;
+ tdlsSetupRsp.QOSCapsStation.acbe_uapsd =
+ ((pMac->lim.gLimTDLSUapsdMask & 0x08) >> 3);
+ tdlsSetupRsp.QOSCapsStation.acbk_uapsd =
+ ((pMac->lim.gLimTDLSUapsdMask & 0x04) >> 2);
+ tdlsSetupRsp.QOSCapsStation.acvi_uapsd =
+ ((pMac->lim.gLimTDLSUapsdMask & 0x02) >> 1);
+ tdlsSetupRsp.QOSCapsStation.acvo_uapsd =
+ (pMac->lim.gLimTDLSUapsdMask & 0x01);
+ }
+
+ wlan_cfg_get_int(pMac, WNI_CFG_DOT11_MODE, &selfDot11Mode);
+
+ /* Populate HT/VHT Capabilities */
+ populate_dot11f_tdls_ht_vht_cap(pMac, selfDot11Mode, &tdlsSetupRsp.HTCaps,
+ &tdlsSetupRsp.VHTCaps, psessionEntry);
+
+ /* Populate AID */
+ populate_dotf_tdls_vht_aid(pMac, selfDot11Mode, peerMac,
+ &tdlsSetupRsp.AID, psessionEntry);
+
+ /* Populate TDLS offchannel param only if offchannel is enabled
+ * and TDLS Channel Switching is not prohibited by AP in ExtCap
+ * IE in assoc/re-assoc response.
+ */
+ if ((1 == pMac->lim.gLimTDLSOffChannelEnabled) &&
+ (!psessionEntry->tdls_chan_swit_prohibited)) {
+ populate_dot11f_tdls_offchannel_params(pMac, psessionEntry,
+ &tdlsSetupRsp.SuppChannels,
+ &tdlsSetupRsp.
+ SuppOperatingClasses);
+ if (pMac->roam.configParam.bandCapability != eCSR_BAND_24) {
+ tdlsSetupRsp.ht2040_bss_coexistence.present = 1;
+ tdlsSetupRsp.ht2040_bss_coexistence.info_request = 1;
+ }
+ } else {
+ lim_log(pMac, LOG1,
+ FL("TDLS offchan not enabled, or channel switch prohibited by AP, gLimTDLSOffChannelEnabled (%d), tdls_chan_swit_prohibited (%d)"),
+ pMac->lim.gLimTDLSOffChannelEnabled,
+ psessionEntry->tdls_chan_swit_prohibited);
+ }
+ tdlsSetupRsp.Status.status = setupStatus;
+ /*
+ * now we pack it. First, how much space are we going to need?
+ */
+ status = dot11f_get_packed_tdls_setup_rsp_size(pMac, &tdlsSetupRsp,
+ &nPayload);
+ if (DOT11F_FAILED(status)) {
+ lim_log(pMac, LOGE,
+ FL(
+ "Failed to calculate the packed size for a Setup Response (0x%08x)."
+ ),
+ status);
+ /* We'll fall back on the worst case scenario: */
+ nPayload = sizeof(tDot11fProbeRequest);
+ } else if (DOT11F_WARNED(status)) {
+ lim_log(pMac, LOGW,
+ FL(
+ "There were warnings while calculating the packed size for Setup Response (0x%08x)."
+ ),
+ status);
+ }
+
+ /*
+ * This frame is going out from PE as data frames with special ethertype
+ * 89-0d.
+ * 8 bytes of RFC 1042 header
+ */
+
+ nBytes = nPayload + ((IS_QOS_ENABLED(psessionEntry))
+ ? sizeof(tSirMacDataHdr3a) :
+ sizeof(tSirMacMgmtHdr))
+ + sizeof(eth_890d_header)
+ + PAYLOAD_TYPE_TDLS_SIZE + addIeLen;
+
+ /* Ok-- try to allocate memory from MGMT PKT pool */
+ cdf_status = cds_packet_alloc((uint16_t) nBytes, (void **)&pFrame,
+ (void **)&pPacket);
+ if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
+ lim_log(pMac, LOGE,
+ FL(
+ "Failed to allocate %d bytes for a TDLS Setup Response."
+ ),
+ nBytes);
+ return eSIR_MEM_ALLOC_FAILED;
+ }
+
+ /* zero out the memory */
+ cdf_mem_set(pFrame, nBytes, 0);
+
+ /*
+ * IE formation, memory allocation is completed, Now form TDLS discovery
+ * request frame
+ */
+
+ /* fill out the buffer descriptor */
+
+ header_offset = lim_prepare_tdls_frame_header(pMac, pFrame,
+ LINK_IDEN_ADDR_OFFSET
+ (tdlsSetupRsp), TDLS_LINK_AP,
+ TDLS_RESPONDER, TID_AC_BK,
+ psessionEntry);
+
+ lim_log(pMac, LOG1,
+ FL(
+ "SupportedChnlWidth %x rxMCSMap %x rxMCSMap %x txSupDataRate %x"
+ ),
+ tdlsSetupRsp.VHTCaps.supportedChannelWidthSet,
+ tdlsSetupRsp.VHTCaps.rxMCSMap,
+ tdlsSetupRsp.VHTCaps.txMCSMap,
+ tdlsSetupRsp.VHTCaps.txSupDataRate);
+ status = dot11f_pack_tdls_setup_rsp(pMac, &tdlsSetupRsp,
+ pFrame + header_offset,
+ nPayload, &nPayload);
+
+ if (DOT11F_FAILED(status)) {
+ lim_log(pMac, LOGE,
+ FL("Failed to pack a TDLS Setup Response (0x%08x)."),
+ status);
+ cds_packet_free((void *)pPacket);
+ return eSIR_FAILURE;
+ } else if (DOT11F_WARNED(status)) {
+ lim_log(pMac, LOGW,
+ FL(
+ "There were warnings while packing TDLS Setup Response (0x%08x)."
+ ),
+ status);
+ }
+ /* Copy the additional IE. */
+ /* TODO : addIe is added at the end of the frame. This means it doesnt */
+ /* follow the order. This should be ok, but we should consider changing this */
+ /* if there is any IOT issue. */
+ if (addIeLen != 0) {
+ cdf_mem_copy(pFrame + header_offset + nPayload, addIe,
+ addIeLen);
+ }
+
+ lim_log(pMac, LOG1,
+ FL("[TDLS] action %d (%s) -AP-> OTA peer="MAC_ADDRESS_STR),
+ SIR_MAC_TDLS_SETUP_RSP,
+ lim_trace_tdls_action_string(SIR_MAC_TDLS_SETUP_RSP),
+ MAC_ADDR_ARRAY(peerMac));
+
+ pMac->lim.mgmtFrameSessionId = psessionEntry->peSessionId;
+
+ cdf_status = wma_tx_frameWithTxComplete(pMac, pPacket, (uint16_t) nBytes,
+ TXRX_FRM_802_11_DATA,
+ ANI_TXDIR_TODS,
+ TID_AC_BK,
+ lim_tx_complete, pFrame,
+ lim_mgmt_tx_complete,
+ HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME,
+ smeSessionId, false, 0);
+
+ if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
+ pMac->lim.mgmtFrameSessionId = 0xff;
+ lim_log(pMac, LOGE,
+ FL("could not send TDLS Dis Request frame!"));
+ return eSIR_FAILURE;
+ }
+
+ return eSIR_SUCCESS;
+
+}
+
+/*
+ * Send TDLS setup CNF frame on AP link
+ */
+
+tSirRetStatus lim_send_tdls_link_setup_cnf_frame(tpAniSirGlobal pMac,
+ tSirMacAddr peerMac,
+ uint8_t dialog,
+ uint32_t peerCapability,
+ tpPESession psessionEntry,
+ uint8_t *addIe, uint16_t addIeLen)
+{
+ tDot11fTDLSSetupCnf tdlsSetupCnf;
+ uint32_t status = 0;
+ uint32_t nPayload = 0;
+ uint32_t nBytes = 0;
+ uint32_t header_offset = 0;
+ uint8_t *pFrame;
+ void *pPacket;
+ CDF_STATUS cdf_status;
+#ifndef NO_PAD_TDLS_MIN_8023_SIZE
+ uint32_t padLen = 0;
+#endif
+ uint8_t smeSessionId = 0;
+
+ /*
+ * The scheme here is to fill out a 'tDot11fProbeRequest' structure
+ * and then hand it off to 'dot11f_pack_probe_request' (for
+ * serialization). We start by zero-initializing the structure:
+ */
+ smeSessionId = psessionEntry->smeSessionId;
+
+ cdf_mem_set((uint8_t *) &tdlsSetupCnf, sizeof(tDot11fTDLSSetupCnf), 0);
+
+ /*
+ * setup Fixed fields,
+ */
+ tdlsSetupCnf.Category.category = SIR_MAC_ACTION_TDLS;
+ tdlsSetupCnf.Action.action = SIR_MAC_TDLS_SETUP_CNF;
+ tdlsSetupCnf.DialogToken.token = dialog;
+
+ populate_dot11f_link_iden(pMac, psessionEntry,
+ &tdlsSetupCnf.LinkIdentifier, peerMac,
+ TDLS_INITIATOR);
+ /*
+ * TODO: we need to see if we have to support conditions where we have
+ * EDCA parameter info element is needed a) if we need different QOS
+ * parameters for off channel operations or QOS is not supported on
+ * AP link and we wanted to QOS on direct link.
+ */
+
+ /* Check self and peer WMM capable */
+ if ((1 == pMac->lim.gLimTDLSWmmMode) &&
+ (CHECK_BIT(peerCapability, TDLS_PEER_WMM_CAP))) {
+ lim_log(pMac, LOG1, FL("populate WMM praram in Setup Confirm"));
+ populate_dot11f_wmm_params(pMac, &tdlsSetupCnf.WMMParams,
+ psessionEntry);
+ }
+
+ /* Check peer is VHT capable */
+ if (CHECK_BIT(peerCapability, TDLS_PEER_VHT_CAP)) {
+ populate_dot11f_vht_operation(pMac,
+ psessionEntry,
+ &tdlsSetupCnf.VHTOperation);
+ populate_dot11f_ht_info(pMac, &tdlsSetupCnf.HTInfo, psessionEntry);
+ } else if (CHECK_BIT(peerCapability, TDLS_PEER_HT_CAP)) { /* Check peer is HT capable */
+ populate_dot11f_ht_info(pMac, &tdlsSetupCnf.HTInfo, psessionEntry);
+ }
+
+ /*
+ * now we pack it. First, how much space are we going to need?
+ */
+ status = dot11f_get_packed_tdls_setup_cnf_size(pMac, &tdlsSetupCnf,
+ &nPayload);
+ if (DOT11F_FAILED(status)) {
+ lim_log(pMac, LOGE,
+ FL(
+ "Failed to calculate the packed size for a Setup Confirm (0x%08x)."
+ ),
+ status);
+ /* We'll fall back on the worst case scenario: */
+ nPayload = sizeof(tDot11fProbeRequest);
+ } else if (DOT11F_WARNED(status)) {
+ lim_log(pMac, LOGW,
+ FL(
+ "There were warnings while calculating the packed size for Setup Confirm (0x%08x)."
+ ),
+ status);
+ }
+
+ /*
+ * This frame is going out from PE as data frames with special ethertype
+ * 89-0d.
+ * 8 bytes of RFC 1042 header
+ */
+
+ nBytes = nPayload + ((IS_QOS_ENABLED(psessionEntry))
+ ? sizeof(tSirMacDataHdr3a) :
+ sizeof(tSirMacMgmtHdr))
+ + sizeof(eth_890d_header)
+ + PAYLOAD_TYPE_TDLS_SIZE + addIeLen;
+
+#ifndef NO_PAD_TDLS_MIN_8023_SIZE
+ /* IOT issue with some AP : some AP doesn't like the data packet size < minimum 802.3 frame length (64)
+ Hence AP itself padding some bytes, which caused teardown packet is dropped at
+ receiver side. To avoid such IOT issue, we added some extra bytes to meet data frame size >= 64
+ */
+ if (nPayload + PAYLOAD_TYPE_TDLS_SIZE < MIN_IEEE_8023_SIZE) {
+ padLen =
+ MIN_IEEE_8023_SIZE - (nPayload + PAYLOAD_TYPE_TDLS_SIZE);
+
+ /* if padLen is less than minimum vendorSpecific (5), pad up to 5 */
+ if (padLen < MIN_VENDOR_SPECIFIC_IE_SIZE)
+ padLen = MIN_VENDOR_SPECIFIC_IE_SIZE;
+
+ nBytes += padLen;
+ }
+#endif
+
+ /* Ok-- try to allocate memory from MGMT PKT pool */
+ cdf_status = cds_packet_alloc((uint16_t) nBytes, (void **)&pFrame,
+ (void **)&pPacket);
+ if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
+ lim_log(pMac, LOGE,
+ FL(
+ "Failed to allocate %d bytes for a TDLS Setup Confirm."
+ ),
+ nBytes);
+ return eSIR_MEM_ALLOC_FAILED;
+ }
+
+ /* zero out the memory */
+ cdf_mem_set(pFrame, nBytes, 0);
+
+ /*
+ * IE formation, memory allocation is completed, Now form TDLS discovery
+ * request frame
+ */
+
+ /* fill out the buffer descriptor */
+
+ header_offset = lim_prepare_tdls_frame_header(pMac, pFrame,
+ LINK_IDEN_ADDR_OFFSET
+ (tdlsSetupCnf), TDLS_LINK_AP,
+ TDLS_INITIATOR, TID_AC_VI,
+ psessionEntry);
+
+ status = dot11f_pack_tdls_setup_cnf(pMac, &tdlsSetupCnf, pFrame
+ + header_offset, nPayload, &nPayload);
+
+ if (DOT11F_FAILED(status)) {
+ lim_log(pMac, LOGE,
+ FL("Failed to pack a TDLS discovery req (0x%08x)."),
+ status);
+ cds_packet_free((void *)pPacket);
+ return eSIR_FAILURE;
+ } else if (DOT11F_WARNED(status)) {
+ lim_log(pMac, LOGW,
+ FL(
+ "There were warnings while packing TDLS Discovery Request (0x%08x)."
+ ),
+ status);
+ }
+ /* Copy the additional IE. */
+ /* TODO : addIe is added at the end of the frame. This means it doesnt */
+ /* follow the order. This should be ok, but we should consider changing this */
+ /* if there is any IOT issue. */
+ if (addIeLen != 0) {
+ cdf_mem_copy(pFrame + header_offset + nPayload, addIe,
+ addIeLen);
+ }
+#ifndef NO_PAD_TDLS_MIN_8023_SIZE
+ if (padLen != 0) {
+ /* QCOM VENDOR OUI = { 0x00, 0xA0, 0xC6, type = 0x0000 }; */
+ uint8_t *padVendorSpecific =
+ pFrame + header_offset + nPayload + addIeLen;
+ /* make QCOM_VENDOR_OUI, and type = 0x0000, and all the payload to be zero */
+ padVendorSpecific[0] = 221;
+ padVendorSpecific[1] = padLen - 2;
+ padVendorSpecific[2] = 0x00;
+ padVendorSpecific[3] = 0xA0;
+ padVendorSpecific[4] = 0xC6;
+
+ lim_log(pMac, LOG1, FL("Padding Vendor Specific Ie Len = %d"),
+ padLen);
+
+ /* padding zero if more than 5 bytes are required */
+ if (padLen > MIN_VENDOR_SPECIFIC_IE_SIZE)
+ cdf_mem_set(pFrame + header_offset + nPayload +
+ addIeLen + MIN_VENDOR_SPECIFIC_IE_SIZE,
+ padLen - MIN_VENDOR_SPECIFIC_IE_SIZE, 0);
+ }
+#endif
+
+ lim_log(pMac, LOG1,
+ FL("[TDLS] action %d (%s) -AP-> OTA peer="MAC_ADDRESS_STR),
+ SIR_MAC_TDLS_SETUP_CNF,
+ lim_trace_tdls_action_string(SIR_MAC_TDLS_SETUP_CNF),
+ MAC_ADDR_ARRAY(peerMac));
+
+ pMac->lim.mgmtFrameSessionId = psessionEntry->peSessionId;
+
+ cdf_status = wma_tx_frameWithTxComplete(pMac, pPacket, (uint16_t) nBytes,
+ TXRX_FRM_802_11_DATA,
+ ANI_TXDIR_TODS,
+ TID_AC_VI,
+ lim_tx_complete, pFrame,
+ lim_mgmt_tx_complete,
+ HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME,
+ smeSessionId, false, 0);
+
+ if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
+ pMac->lim.mgmtFrameSessionId = 0xff;
+ lim_log(pMac, LOGE,
+ FL("could not send TDLS Setup Confirm frame"));
+ return eSIR_FAILURE;
+
+ }
+
+ return eSIR_SUCCESS;
+}
+
+/* This Function is similar to populate_dot11f_ht_caps, except that the HT Capabilities
+ * are considered from the AddStaReq rather from the cfg.dat as in populate_dot11f_ht_caps
+ */
+static tSirRetStatus lim_tdls_populate_dot11f_ht_caps(tpAniSirGlobal pMac,
+ tpPESession psessionEntry,
+ tSirTdlsAddStaReq *
+ pTdlsAddStaReq,
+ tDot11fIEHTCaps *pDot11f)
+{
+ uint32_t nCfgValue;
+ uint8_t nCfgValue8;
+ tSirMacHTParametersInfo *pHTParametersInfo;
+ union {
+ uint16_t nCfgValue16;
+ tSirMacHTCapabilityInfo htCapInfo;
+ tSirMacExtendedHTCapabilityInfo extHtCapInfo;
+ } uHTCapabilityInfo;
+
+ tSirMacTxBFCapabilityInfo *pTxBFCapabilityInfo;
+ tSirMacASCapabilityInfo *pASCapabilityInfo;
+
+ nCfgValue = pTdlsAddStaReq->htCap.capInfo;
+
+ uHTCapabilityInfo.nCfgValue16 = nCfgValue & 0xFFFF;
+
+ pDot11f->advCodingCap = uHTCapabilityInfo.htCapInfo.advCodingCap;
+ pDot11f->mimoPowerSave = uHTCapabilityInfo.htCapInfo.mimoPowerSave;
+ pDot11f->greenField = uHTCapabilityInfo.htCapInfo.greenField;
+ pDot11f->shortGI20MHz = uHTCapabilityInfo.htCapInfo.shortGI20MHz;
+ pDot11f->shortGI40MHz = uHTCapabilityInfo.htCapInfo.shortGI40MHz;
+ pDot11f->txSTBC = uHTCapabilityInfo.htCapInfo.txSTBC;
+ pDot11f->rxSTBC = uHTCapabilityInfo.htCapInfo.rxSTBC;
+ pDot11f->delayedBA = uHTCapabilityInfo.htCapInfo.delayedBA;
+ pDot11f->maximalAMSDUsize =
+ uHTCapabilityInfo.htCapInfo.maximalAMSDUsize;
+ pDot11f->dsssCckMode40MHz =
+ uHTCapabilityInfo.htCapInfo.dsssCckMode40MHz;
+ pDot11f->psmp = uHTCapabilityInfo.htCapInfo.psmp;
+ pDot11f->stbcControlFrame =
+ uHTCapabilityInfo.htCapInfo.stbcControlFrame;
+ pDot11f->lsigTXOPProtection =
+ uHTCapabilityInfo.htCapInfo.lsigTXOPProtection;
+
+ /*
+ * All sessionized entries will need the check below
+ * Only in case of NO session
+ */
+ if (psessionEntry == NULL) {
+ pDot11f->supportedChannelWidthSet =
+ uHTCapabilityInfo.htCapInfo.supportedChannelWidthSet;
+ } else {
+ pDot11f->supportedChannelWidthSet =
+ psessionEntry->htSupportedChannelWidthSet;
+ }
+
+ /* Ensure that shortGI40MHz is Disabled if supportedChannelWidthSet is
+ eHT_CHANNEL_WIDTH_20MHZ */
+ if (pDot11f->supportedChannelWidthSet == eHT_CHANNEL_WIDTH_20MHZ) {
+ pDot11f->shortGI40MHz = 0;
+ }
+
+ lim_log(pMac, LOG1,
+ FL(
+ "SupportedChnlWidth: %d, mimoPS: %d, GF: %d, shortGI20:%d, shortGI40: %d, dsssCck: %d"
+ ),
+ pDot11f->supportedChannelWidthSet,
+ pDot11f->mimoPowerSave,
+ pDot11f->greenField,
+ pDot11f->shortGI20MHz,
+ pDot11f->shortGI40MHz,
+ pDot11f->dsssCckMode40MHz);
+
+ nCfgValue = pTdlsAddStaReq->htCap.ampduParamsInfo;
+
+ nCfgValue8 = (uint8_t) nCfgValue;
+ pHTParametersInfo = (tSirMacHTParametersInfo *) &nCfgValue8;
+
+ pDot11f->maxRxAMPDUFactor = pHTParametersInfo->maxRxAMPDUFactor;
+ pDot11f->mpduDensity = pHTParametersInfo->mpduDensity;
+ pDot11f->reserved1 = pHTParametersInfo->reserved;
+
+ lim_log(pMac, LOG1, FL("AMPDU Param: %x"), nCfgValue);
+
+ cdf_mem_copy(pDot11f->supportedMCSSet, pTdlsAddStaReq->htCap.suppMcsSet,
+ SIZE_OF_SUPPORTED_MCS_SET);
+
+ nCfgValue = pTdlsAddStaReq->htCap.extendedHtCapInfo;
+
+ uHTCapabilityInfo.nCfgValue16 = nCfgValue & 0xFFFF;
+
+ pDot11f->pco = uHTCapabilityInfo.extHtCapInfo.pco;
+ pDot11f->transitionTime = uHTCapabilityInfo.extHtCapInfo.transitionTime;
+ pDot11f->mcsFeedback = uHTCapabilityInfo.extHtCapInfo.mcsFeedback;
+
+ nCfgValue = pTdlsAddStaReq->htCap.txBFCapInfo;
+
+ pTxBFCapabilityInfo = (tSirMacTxBFCapabilityInfo *) &nCfgValue;
+ pDot11f->txBF = pTxBFCapabilityInfo->txBF;
+ pDot11f->rxStaggeredSounding = pTxBFCapabilityInfo->rxStaggeredSounding;
+ pDot11f->txStaggeredSounding = pTxBFCapabilityInfo->txStaggeredSounding;
+ pDot11f->rxZLF = pTxBFCapabilityInfo->rxZLF;
+ pDot11f->txZLF = pTxBFCapabilityInfo->txZLF;
+ pDot11f->implicitTxBF = pTxBFCapabilityInfo->implicitTxBF;
+ pDot11f->calibration = pTxBFCapabilityInfo->calibration;
+ pDot11f->explicitCSITxBF = pTxBFCapabilityInfo->explicitCSITxBF;
+ pDot11f->explicitUncompressedSteeringMatrix =
+ pTxBFCapabilityInfo->explicitUncompressedSteeringMatrix;
+ pDot11f->explicitBFCSIFeedback =
+ pTxBFCapabilityInfo->explicitBFCSIFeedback;
+ pDot11f->explicitUncompressedSteeringMatrixFeedback =
+ pTxBFCapabilityInfo->explicitUncompressedSteeringMatrixFeedback;
+ pDot11f->explicitCompressedSteeringMatrixFeedback =
+ pTxBFCapabilityInfo->explicitCompressedSteeringMatrixFeedback;
+ pDot11f->csiNumBFAntennae = pTxBFCapabilityInfo->csiNumBFAntennae;
+ pDot11f->uncompressedSteeringMatrixBFAntennae =
+ pTxBFCapabilityInfo->uncompressedSteeringMatrixBFAntennae;
+ pDot11f->compressedSteeringMatrixBFAntennae =
+ pTxBFCapabilityInfo->compressedSteeringMatrixBFAntennae;
+
+ nCfgValue = pTdlsAddStaReq->htCap.antennaSelectionInfo;
+
+ nCfgValue8 = (uint8_t) nCfgValue;
+
+ pASCapabilityInfo = (tSirMacASCapabilityInfo *) &nCfgValue8;
+ pDot11f->antennaSelection = pASCapabilityInfo->antennaSelection;
+ pDot11f->explicitCSIFeedbackTx =
+ pASCapabilityInfo->explicitCSIFeedbackTx;
+ pDot11f->antennaIndicesFeedbackTx =
+ pASCapabilityInfo->antennaIndicesFeedbackTx;
+ pDot11f->explicitCSIFeedback = pASCapabilityInfo->explicitCSIFeedback;
+ pDot11f->antennaIndicesFeedback =
+ pASCapabilityInfo->antennaIndicesFeedback;
+ pDot11f->rxAS = pASCapabilityInfo->rxAS;
+ pDot11f->txSoundingPPDUs = pASCapabilityInfo->txSoundingPPDUs;
+
+ pDot11f->present = pTdlsAddStaReq->htcap_present;
+
+ return eSIR_SUCCESS;
+
+}
+
+tSirRetStatus
+lim_tdls_populate_dot11f_vht_caps(tpAniSirGlobal pMac,
+ tSirTdlsAddStaReq *pTdlsAddStaReq,
+ tDot11fIEVHTCaps *pDot11f)
+{
+ uint32_t nCfgValue = 0;
+ union {
+ uint32_t nCfgValue32;
+ tSirMacVHTCapabilityInfo vhtCapInfo;
+ } uVHTCapabilityInfo;
+ union {
+ uint16_t nCfgValue16;
+ tSirMacVHTTxSupDataRateInfo vhtTxSupDataRateInfo;
+ tSirMacVHTRxSupDataRateInfo vhtRxsupDataRateInfo;
+ } uVHTSupDataRateInfo;
+
+ pDot11f->present = pTdlsAddStaReq->vhtcap_present;
+
+ nCfgValue = pTdlsAddStaReq->vhtCap.vhtCapInfo;
+ uVHTCapabilityInfo.nCfgValue32 = nCfgValue;
+
+ pDot11f->maxMPDULen = uVHTCapabilityInfo.vhtCapInfo.maxMPDULen;
+ pDot11f->supportedChannelWidthSet =
+ uVHTCapabilityInfo.vhtCapInfo.supportedChannelWidthSet;
+ pDot11f->ldpcCodingCap = uVHTCapabilityInfo.vhtCapInfo.ldpcCodingCap;
+ pDot11f->shortGI80MHz = uVHTCapabilityInfo.vhtCapInfo.shortGI80MHz;
+ pDot11f->shortGI160and80plus80MHz =
+ uVHTCapabilityInfo.vhtCapInfo.shortGI160and80plus80MHz;
+ pDot11f->txSTBC = uVHTCapabilityInfo.vhtCapInfo.txSTBC;
+ pDot11f->rxSTBC = uVHTCapabilityInfo.vhtCapInfo.rxSTBC;
+ pDot11f->suBeamFormerCap = 0;
+ pDot11f->suBeamformeeCap = 0;
+ pDot11f->csnofBeamformerAntSup =
+ uVHTCapabilityInfo.vhtCapInfo.csnofBeamformerAntSup;
+ pDot11f->numSoundingDim = uVHTCapabilityInfo.vhtCapInfo.numSoundingDim;
+ pDot11f->muBeamformerCap = 0;
+ pDot11f->muBeamformeeCap = 0;
+ pDot11f->vhtTXOPPS = uVHTCapabilityInfo.vhtCapInfo.vhtTXOPPS;
+ pDot11f->htcVHTCap = uVHTCapabilityInfo.vhtCapInfo.htcVHTCap;
+ pDot11f->maxAMPDULenExp = uVHTCapabilityInfo.vhtCapInfo.maxAMPDULenExp;
+ pDot11f->vhtLinkAdaptCap =
+ uVHTCapabilityInfo.vhtCapInfo.vhtLinkAdaptCap;
+ pDot11f->rxAntPattern = uVHTCapabilityInfo.vhtCapInfo.rxAntPattern;
+ pDot11f->txAntPattern = uVHTCapabilityInfo.vhtCapInfo.txAntPattern;
+ pDot11f->reserved1 = uVHTCapabilityInfo.vhtCapInfo.reserved1;
+
+ pDot11f->rxMCSMap = pTdlsAddStaReq->vhtCap.suppMcs.rxMcsMap;
+
+ nCfgValue = pTdlsAddStaReq->vhtCap.suppMcs.rxHighest;
+ uVHTSupDataRateInfo.nCfgValue16 = nCfgValue & 0xffff;
+ pDot11f->rxHighSupDataRate =
+ uVHTSupDataRateInfo.vhtRxsupDataRateInfo.rxSupDataRate;
+
+ pDot11f->txMCSMap = pTdlsAddStaReq->vhtCap.suppMcs.txMcsMap;
+
+ nCfgValue = pTdlsAddStaReq->vhtCap.suppMcs.txHighest;
+ uVHTSupDataRateInfo.nCfgValue16 = nCfgValue & 0xffff;
+ pDot11f->txSupDataRate =
+ uVHTSupDataRateInfo.vhtTxSupDataRateInfo.txSupDataRate;
+
+ pDot11f->reserved3 = uVHTSupDataRateInfo.vhtTxSupDataRateInfo.reserved;
+
+ lim_log_vht_cap(pMac, pDot11f);
+
+ return eSIR_SUCCESS;
+
+}
+
+/**
+ * lim_tdls_populate_matching_rate_set() - populate matching rate set
+ *
+ * @mac_ctx - global MAC context
+ * @stads - station hash entry
+ * @supp_rate_set - pointer to supported rate set
+ * @supp_rates_len - length of the supported rates
+ * @supp_mcs_set - pointer to supported MSC set
+ * @session_entry - pointer to PE session entry
+ * @vht_caps - pointer to VHT capability
+ *
+ *
+ * This function gets set of available rates from the config and compare them
+ * against the set of received supported rates. After the comparison station
+ * entry's rates is populated with 11A rates and 11B rates.
+ *
+ * Return: eSIR_SUCCESS on success, eSIR_FAILURE on failure.
+ */
+static tSirRetStatus
+lim_tdls_populate_matching_rate_set(tpAniSirGlobal mac_ctx, tpDphHashNode stads,
+ uint8_t *supp_rate_set,
+ uint8_t supp_rates_len,
+ uint8_t *supp_mcs_set,
+ tpPESession session_entry,
+ tDot11fIEVHTCaps *vht_caps)
+{
+ tSirMacRateSet temp_rate_set;
+ uint32_t i, j, val, min, is_a_rate;
+ tSirMacRateSet temp_rate_set2;
+ uint32_t phymode;
+ uint8_t mcsSet[SIZE_OF_SUPPORTED_MCS_SET];
+ tpSirSupportedRates rates;
+ uint8_t a_rateindex = 0;
+ uint8_t b_rateindex = 0;
+ is_a_rate = 0;
+ temp_rate_set2.numRates = 0;
+
+ lim_get_phy_mode(mac_ctx, &phymode, NULL);
+
+ /* get own rate set */
+ val = WNI_CFG_OPERATIONAL_RATE_SET_LEN;
+ if (wlan_cfg_get_str(mac_ctx, WNI_CFG_OPERATIONAL_RATE_SET,
+ (uint8_t *) &temp_rate_set.rate,
+ &val) != eSIR_SUCCESS) {
+ /* Could not get rateset from CFG. Log error. */
+ lim_log(mac_ctx, LOGE, FL("could not retrieve rateset"));
+ val = 0;
+ }
+ temp_rate_set.numRates = val;
+
+ if (phymode == WNI_CFG_PHY_MODE_11G) {
+ /* get own extended rate set */
+ val = WNI_CFG_EXTENDED_OPERATIONAL_RATE_SET_LEN;
+ if (wlan_cfg_get_str(mac_ctx,
+ WNI_CFG_EXTENDED_OPERATIONAL_RATE_SET,
+ (uint8_t *) &temp_rate_set2.rate,
+ &val) != eSIR_SUCCESS)
+ temp_rate_set2.numRates = val;
+ }
+
+ if ((temp_rate_set.numRates + temp_rate_set2.numRates) > 12) {
+ lim_log(mac_ctx, LOGE, FL("more than 12 rates in CFG"));
+ goto error;
+ }
+
+ /**
+ * Handling of the rate set IEs is the following:
+ * - keep only rates that we support and that the station supports
+ * - sort and the rates into the pSta->rate array
+ */
+
+ /* Copy all rates in temp_rate_set, there are 12 rates max */
+ for (i = 0; i < temp_rate_set2.numRates; i++)
+ temp_rate_set.rate[i + temp_rate_set.numRates] =
+ temp_rate_set2.rate[i];
+
+ temp_rate_set.numRates += temp_rate_set2.numRates;
+
+ /**
+ * Sort rates in temp_rate_set (they are likely to be already sorted)
+ * put the result in temp_rate_set2
+ */
+ temp_rate_set2.numRates = 0;
+
+ for (i = 0; i < temp_rate_set.numRates; i++) {
+ min = 0;
+ val = 0xff;
+
+ for (j = 0; j < temp_rate_set.numRates; j++)
+ if ((uint32_t) (temp_rate_set.rate[j] & 0x7f) < val) {
+ val = temp_rate_set.rate[j] & 0x7f;
+ min = j;
+ }
+
+ temp_rate_set2.rate[temp_rate_set2.numRates++] =
+ temp_rate_set.rate[min];
+ temp_rate_set.rate[min] = 0xff;
+ }
+
+ /**
+ * Copy received rates in temp_rate_set, the parser has ensured
+ * unicity of the rates so there cannot be more than 12 .
+ */
+ if (supp_rates_len > SIR_MAC_RATESET_EID_MAX) {
+ lim_log(mac_ctx, LOGW,
+ FL(
+ "Supported rates length %d more than the Max limit, reset to Max"
+ ),
+ supp_rates_len);
+ supp_rates_len = SIR_MAC_RATESET_EID_MAX;
+ }
+
+ for (i = 0; i < supp_rates_len; i++)
+ temp_rate_set.rate[i] = supp_rate_set[i];
+
+ temp_rate_set.numRates = supp_rates_len;
+
+ rates = &stads->supportedRates;
+ cdf_mem_set((uint8_t *) rates, sizeof(tSirSupportedRates), 0);
+
+ for (i = 0; i < temp_rate_set2.numRates; i++) {
+ for (j = 0; j < temp_rate_set.numRates; j++) {
+ if ((temp_rate_set2.rate[i] & 0x7F) !=
+ (temp_rate_set.rate[j] & 0x7F))
+ continue;
+
+#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
+ if ((b_rateindex > HAL_NUM_11B_RATES) ||
+ (a_rateindex > HAL_NUM_11A_RATES)) {
+ lim_log(mac_ctx, LOGE,
+ FL("Invalid number of rates (11b->%d, 11a->%d)"),
+ b_rateindex, a_rateindex);
+ return eSIR_FAILURE;
+ }
+#endif
+ if (sirIsArate(temp_rate_set2.rate[i] & 0x7f)) {
+ is_a_rate = 1;
+ if (a_rateindex < SIR_NUM_11A_RATES)
+ rates->llaRates[a_rateindex++] = temp_rate_set2.rate[i];
+ } else {
+ if (b_rateindex < SIR_NUM_11B_RATES)
+ rates->llbRates[b_rateindex++] = temp_rate_set2.rate[i];
+ }
+ break;
+ }
+ }
+
+ /* compute the matching MCS rate set, if peer is 11n capable and self mode is 11n */
+#ifdef FEATURE_WLAN_TDLS
+ if (stads->mlmStaContext.htCapability)
+#else
+ if (IS_DOT11_MODE_HT(session_entry->dot11mode) &&
+ (stads->mlmStaContext.htCapability))
+#endif
+ {
+ val = SIZE_OF_SUPPORTED_MCS_SET;
+ if (wlan_cfg_get_str(mac_ctx, WNI_CFG_SUPPORTED_MCS_SET,
+ mcsSet, &val) != eSIR_SUCCESS) {
+ /* Could not get rateset from CFG. Log error. */
+ lim_log(mac_ctx, LOGP,
+ FL("could not retrieve supportedMCSSet"));
+ goto error;
+ }
+
+ for (i = 0; i < val; i++)
+ stads->supportedRates.supportedMCSSet[i] =
+ mcsSet[i] & supp_mcs_set[i];
+
+ lim_log(mac_ctx, LOG1,
+ FL("MCS Rate Set Bitmap from CFG and DPH"));
+ for (i = 0; i < SIR_MAC_MAX_SUPPORTED_MCS_SET; i++) {
+ lim_log(mac_ctx, LOG1, FL("%x %x"), mcsSet[i],
+ stads->supportedRates.supportedMCSSet[i]);
+ }
+ }
+#ifdef WLAN_FEATURE_11AC
+ lim_populate_vht_mcs_set(mac_ctx, &stads->supportedRates, vht_caps,
+ session_entry);
+#endif
+ /**
+ * Set the erpEnabled bit if the phy is in G mode and at least
+ * one A rate is supported
+ */
+ if ((phymode == WNI_CFG_PHY_MODE_11G) && is_a_rate)
+ stads->erpEnabled = eHAL_SET;
+
+ return eSIR_SUCCESS;
+
+error:
+ return eSIR_FAILURE;
+}
+
+/*
+ * update HASH node entry info
+ */
+static void lim_tdls_update_hash_node_info(tpAniSirGlobal pMac,
+ tDphHashNode *pStaDs,
+ tSirTdlsAddStaReq *pTdlsAddStaReq,
+ tpPESession psessionEntry)
+{
+ tDot11fIEHTCaps htCap = {0,};
+ tDot11fIEHTCaps *htCaps;
+ tDot11fIEVHTCaps *pVhtCaps = NULL;
+ tDot11fIEVHTCaps *pVhtCaps_txbf = NULL;
+#ifdef WLAN_FEATURE_11AC
+ tDot11fIEVHTCaps vhtCap;
+ uint8_t cbMode;
+#endif
+ tpDphHashNode pSessStaDs = NULL;
+ uint16_t aid;
+
+ if (pTdlsAddStaReq->tdlsAddOper == TDLS_OPER_ADD) {
+ populate_dot11f_ht_caps(pMac, psessionEntry, &htCap);
+ } else if (pTdlsAddStaReq->tdlsAddOper == TDLS_OPER_UPDATE) {
+ lim_tdls_populate_dot11f_ht_caps(pMac, NULL, pTdlsAddStaReq, &htCap);
+ }
+ htCaps = &htCap;
+ if (htCaps->present) {
+ pStaDs->mlmStaContext.htCapability = 1;
+ pStaDs->htGreenfield = htCaps->greenField;
+ pStaDs->htSupportedChannelWidthSet =
+ htCaps->supportedChannelWidthSet;
+ pStaDs->htMIMOPSState = htCaps->mimoPowerSave;
+ pStaDs->htMaxAmsduLength = htCaps->maximalAMSDUsize;
+ pStaDs->htAMpduDensity = htCaps->mpduDensity;
+ pStaDs->htDsssCckRate40MHzSupport = htCaps->dsssCckMode40MHz;
+ pStaDs->htShortGI20Mhz = htCaps->shortGI20MHz;
+ pStaDs->htShortGI40Mhz = htCaps->shortGI40MHz;
+ pStaDs->htMaxRxAMpduFactor = htCaps->maxRxAMPDUFactor;
+ lim_fill_rx_highest_supported_rate(pMac,
+ &pStaDs->supportedRates.
+ rxHighestDataRate,
+ htCaps->supportedMCSSet);
+ pStaDs->baPolicyFlag = 0xFF;
+ pMac->lim.gLimTdlsLinkMode = TDLS_LINK_MODE_N;
+ pStaDs->ht_caps = pTdlsAddStaReq->htCap.capInfo;
+ } else {
+ pStaDs->mlmStaContext.htCapability = 0;
+ pMac->lim.gLimTdlsLinkMode = TDLS_LINK_MODE_BG;
+ }
+#ifdef WLAN_FEATURE_11AC
+ lim_tdls_populate_dot11f_vht_caps(pMac, pTdlsAddStaReq, &vhtCap);
+ pVhtCaps = &vhtCap;
+ if (pVhtCaps->present) {
+ pStaDs->mlmStaContext.vhtCapability = 1;
+
+ if (psessionEntry->currentOperChannel <= SIR_11B_CHANNEL_END) {
+ /*
+ * if the channel is 2G then update the min channel
+ * widthset in pStaDs. These values are used when
+ * sending a AddSta request to firmware
+ * 11.21.1 General: The channel width of the TDLS direct
+ * link on the base channel shall not exceed the channel
+ * width of the BSS to which the TDLS peer STAs are
+ * associated.
+ */
+ pStaDs->vhtSupportedChannelWidthSet =
+ WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ;
+ pStaDs->htSupportedChannelWidthSet =
+ eHT_CHANNEL_WIDTH_20MHZ;
+ lim_log(pMac, LOG1, FL("vhtSupportedChannelWidthSet = %hu, htSupportedChannelWidthSet %hu"),
+ pStaDs->htSupportedChannelWidthSet,
+ pStaDs->htSupportedChannelWidthSet);
+ } else {
+ pStaDs->vhtSupportedChannelWidthSet =
+ WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ;
+ pStaDs->htSupportedChannelWidthSet =
+ eHT_CHANNEL_WIDTH_40MHZ;
+ }
+
+ pStaDs->vhtLdpcCapable = pVhtCaps->ldpcCodingCap;
+ pStaDs->vhtBeamFormerCapable = 0;
+ pMac->lim.gLimTdlsLinkMode = TDLS_LINK_MODE_AC;
+ pVhtCaps_txbf = (tDot11fIEVHTCaps *) (&pTdlsAddStaReq->vhtCap);
+ pVhtCaps_txbf->suBeamformeeCap = 0;
+ pVhtCaps_txbf->suBeamFormerCap = 0;
+ pVhtCaps_txbf->muBeamformerCap = 0;
+ pVhtCaps_txbf->muBeamformeeCap = 0;
+ pStaDs->vht_caps = pTdlsAddStaReq->vhtCap.vhtCapInfo;
+ } else {
+ pStaDs->mlmStaContext.vhtCapability = 0;
+ pStaDs->vhtSupportedChannelWidthSet =
+ WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ;
+ }
+#endif
+ /*Calculate the Secondary Coannel Offset */
+ cbMode = lim_select_cb_mode(pStaDs, psessionEntry,
+ psessionEntry->currentOperChannel,
+ pStaDs->vhtSupportedChannelWidthSet);
+
+ pStaDs->htSecondaryChannelOffset = cbMode;
+
+#ifdef WLAN_FEATURE_11AC
+ if (pStaDs->mlmStaContext.vhtCapability) {
+ pStaDs->htSecondaryChannelOffset = lim_get_htcb_state(cbMode);
+ }
+#endif
+
+ pSessStaDs = dph_lookup_hash_entry(pMac, psessionEntry->bssId, &aid,
+ &psessionEntry->dph.dphHashTable);
+
+ /* Lets enable QOS parameter */
+ pStaDs->qosMode = 1;
+ pStaDs->wmeEnabled = 1;
+ pStaDs->lleEnabled = 0;
+ /* TDLS Dummy AddSTA does not have qosInfo , is it OK ??
+ */
+ pStaDs->qos.capability.qosInfo =
+ (*(tSirMacQosInfoStation *) &pTdlsAddStaReq->uapsd_queues);
+
+ /* populate matching rate set */
+
+ /* TDLS Dummy AddSTA does not have HTCap,VHTCap,Rates info , is it OK ??
+ */
+ lim_tdls_populate_matching_rate_set(pMac, pStaDs,
+ pTdlsAddStaReq->supported_rates,
+ pTdlsAddStaReq->supported_rates_length,
+ (uint8_t *) pTdlsAddStaReq->htCap.
+ suppMcsSet, psessionEntry, pVhtCaps);
+
+ /* TDLS Dummy AddSTA does not have right capability , is it OK ??
+ */
+ pStaDs->mlmStaContext.capabilityInfo =
+ (*(tSirMacCapabilityInfo *) &pTdlsAddStaReq->capability);
+
+ return;
+}
+
+/*
+ * Add STA for TDLS setup procedure
+ */
+static tSirRetStatus lim_tdls_setup_add_sta(tpAniSirGlobal pMac,
+ tSirTdlsAddStaReq *pAddStaReq,
+ tpPESession psessionEntry)
+{
+ tpDphHashNode pStaDs = NULL;
+ tSirRetStatus status = eSIR_SUCCESS;
+ uint16_t aid = 0;
+
+ pStaDs = dph_lookup_hash_entry(pMac, pAddStaReq->peerMac, &aid,
+ &psessionEntry->dph.dphHashTable);
+ if (NULL == pStaDs) {
+ aid = lim_assign_peer_idx(pMac, psessionEntry);
+
+ if (!aid) {
+ lim_log(pMac, LOGE,
+ FL("No more free AID for peer "
+ MAC_ADDRESS_STR),
+ MAC_ADDR_ARRAY(pAddStaReq->peerMac));
+ return eSIR_FAILURE;
+ }
+
+ /* Set the aid in peerAIDBitmap as it has been assigned to TDLS peer */
+ SET_PEER_AID_BITMAP(psessionEntry->peerAIDBitmap, aid);
+
+ lim_log(pMac, LOG1, FL("Aid = %d, for peer =" MAC_ADDRESS_STR),
+ aid, MAC_ADDR_ARRAY(pAddStaReq->peerMac));
+ pStaDs =
+ dph_get_hash_entry(pMac, aid,
+ &psessionEntry->dph.dphHashTable);
+
+ if (pStaDs) {
+ (void)lim_del_sta(pMac, pStaDs, false /*asynchronous */,
+ psessionEntry);
+ lim_delete_dph_hash_entry(pMac, pStaDs->staAddr, aid,
+ psessionEntry);
+ }
+
+ pStaDs = dph_add_hash_entry(pMac, pAddStaReq->peerMac, aid,
+ &psessionEntry->dph.dphHashTable);
+
+ if (NULL == pStaDs) {
+ lim_log(pMac, LOGE, FL("add hash entry failed"));
+ CDF_ASSERT(0);
+ return eSIR_FAILURE;
+ }
+ }
+
+ lim_tdls_update_hash_node_info(pMac, pStaDs, pAddStaReq, psessionEntry);
+
+ pStaDs->staType = STA_ENTRY_TDLS_PEER;
+
+ status =
+ lim_add_sta(pMac, pStaDs,
+ (pAddStaReq->tdlsAddOper ==
+ TDLS_OPER_UPDATE) ? true : false, psessionEntry);
+
+ if (eSIR_SUCCESS != status) {
+ /* should not fail */
+ CDF_ASSERT(0);
+ }
+ return status;
+}
+
+/*
+ * Del STA, after Link is teardown or discovery response sent on direct link
+ */
+static tpDphHashNode lim_tdls_del_sta(tpAniSirGlobal pMac, tSirMacAddr peerMac,
+ tpPESession psessionEntry)
+{
+ tSirRetStatus status = eSIR_SUCCESS;
+ uint16_t peerIdx = 0;
+ tpDphHashNode pStaDs = NULL;
+
+ pStaDs = dph_lookup_hash_entry(pMac, peerMac, &peerIdx,
+ &psessionEntry->dph.dphHashTable);
+
+ if (pStaDs) {
+
+ lim_log(pMac, LOG1, FL("DEL STA peer MAC: "MAC_ADDRESS_STR),
+ MAC_ADDR_ARRAY(pStaDs->staAddr));
+
+ lim_log(pMac, LOG1, FL("STA type = %x, sta idx = %x"),
+ pStaDs->staType,
+ pStaDs->staIndex);
+
+ status = lim_del_sta(pMac, pStaDs, false, psessionEntry);
+ }
+
+ return pStaDs;
+}
+
+/*
+ * Once Link is setup with PEER, send Add STA ind to SME
+ */
+static CDF_STATUS lim_send_sme_tdls_add_sta_rsp(tpAniSirGlobal pMac,
+ uint8_t sessionId,
+ tSirMacAddr peerMac,
+ uint8_t updateSta,
+ tDphHashNode *pStaDs, uint8_t status)
+{
+ tSirMsgQ mmhMsg = { 0 };
+ tSirTdlsAddStaRsp *addStaRsp = NULL;
+ mmhMsg.type = eWNI_SME_TDLS_ADD_STA_RSP;
+
+ addStaRsp = cdf_mem_malloc(sizeof(tSirTdlsAddStaRsp));
+ if (NULL == addStaRsp) {
+ lim_log(pMac, LOGE, FL("Failed to allocate memory"));
+ return CDF_STATUS_E_NOMEM;
+ }
+
+ addStaRsp->sessionId = sessionId;
+ addStaRsp->statusCode = status;
+ if (pStaDs) {
+ addStaRsp->staId = pStaDs->staIndex;
+ addStaRsp->ucastSig = pStaDs->ucUcastSig;
+ addStaRsp->bcastSig = pStaDs->ucBcastSig;
+ }
+ if (peerMac) {
+ cdf_mem_copy(addStaRsp->peerMac,
+ (uint8_t *) peerMac, sizeof(tSirMacAddr));
+ }
+ if (updateSta)
+ addStaRsp->tdlsAddOper = TDLS_OPER_UPDATE;
+ else
+ addStaRsp->tdlsAddOper = TDLS_OPER_ADD;
+
+ addStaRsp->length = sizeof(tSirTdlsAddStaRsp);
+ addStaRsp->messageType = eWNI_SME_TDLS_ADD_STA_RSP;
+
+ mmhMsg.bodyptr = addStaRsp;
+ mmhMsg.bodyval = 0;
+ lim_sys_process_mmh_msg_api(pMac, &mmhMsg, ePROT);
+
+ return CDF_STATUS_SUCCESS;
+
+}
+
+/*
+ * STA RSP received from HAL
+ */
+CDF_STATUS lim_process_tdls_add_sta_rsp(tpAniSirGlobal pMac, void *msg,
+ tpPESession psessionEntry)
+{
+ tAddStaParams *pAddStaParams = (tAddStaParams *) msg;
+ uint8_t status = eSIR_SUCCESS;
+ tDphHashNode *pStaDs = NULL;
+ uint16_t aid = 0;
+
+ SET_LIM_PROCESS_DEFD_MESGS(pMac, true);
+ lim_log(pMac, LOG1, FL("staIdx=%d, staMac="MAC_ADDRESS_STR),
+ pAddStaParams->staIdx,
+ MAC_ADDR_ARRAY(pAddStaParams->staMac));
+
+ if (pAddStaParams->status != CDF_STATUS_SUCCESS) {
+ CDF_ASSERT(0);
+ lim_log(pMac, LOGE, FL("Add sta failed "));
+ status = eSIR_FAILURE;
+ goto add_sta_error;
+ }
+
+ pStaDs = dph_lookup_hash_entry(pMac, pAddStaParams->staMac, &aid,
+ &psessionEntry->dph.dphHashTable);
+ if (NULL == pStaDs) {
+ lim_log(pMac, LOGE, FL("pStaDs is NULL "));
+ status = eSIR_FAILURE;
+ goto add_sta_error;
+ }
+
+ pStaDs->bssId = pAddStaParams->bssIdx;
+ pStaDs->staIndex = pAddStaParams->staIdx;
+ pStaDs->ucUcastSig = pAddStaParams->ucUcastSig;
+ pStaDs->ucBcastSig = pAddStaParams->ucBcastSig;
+ pStaDs->mlmStaContext.mlmState = eLIM_MLM_LINK_ESTABLISHED_STATE;
+ pStaDs->valid = 1;
+add_sta_error:
+ status = lim_send_sme_tdls_add_sta_rsp(pMac, psessionEntry->smeSessionId,
+ pAddStaParams->staMac,
+ pAddStaParams->updateSta, pStaDs,
+ status);
+ cdf_mem_free(pAddStaParams);
+ return status;
+}
+
+void populate_dot11f_tdls_offchannel_params(tpAniSirGlobal pMac,
+ tpPESession psessionEntry,
+ tDot11fIESuppChannels *suppChannels,
+ tDot11fIESuppOperatingClasses *
+ suppOperClasses)
+{
+ uint32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
+ uint8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
+ uint8_t i;
+ uint8_t valid_count = 0;
+ uint8_t chanOffset;
+ uint8_t op_class;
+ uint8_t numClasses;
+ uint8_t classes[SIR_MAC_MAX_SUPP_OPER_CLASSES];
+ if (wlan_cfg_get_str(pMac, WNI_CFG_VALID_CHANNEL_LIST,
+ validChan, &numChans) != eSIR_SUCCESS) {
+ /**
+ * Could not get Valid channel list from CFG.
+ * Log error.
+ */
+ lim_log(pMac, LOGE,
+ FL("could not retrieve Valid channel list"));
+ return;
+ }
+
+ /* validating the channel list for DFS channels */
+ for (i = 0U; i < numChans; i++) {
+ if (CHANNEL_STATE_DFS ==
+ cds_get_channel_state(validChan[i])) {
+ lim_log(pMac, LOG1,
+ FL(
+ "skipping DFS channel %d from the valid channel list"
+ ),
+ validChan[i]);
+ continue;
+ }
+
+ if (valid_count >= ARRAY_SIZE(suppChannels->bands))
+ break;
+ suppChannels->bands[valid_count][0] = validChan[i];
+ suppChannels->bands[valid_count][1] = 1;
+ valid_count++;
+ }
+
+ suppChannels->num_bands = valid_count;
+ suppChannels->present = 1;
+
+ /* find channel offset and get op class for current operating channel */
+ switch (psessionEntry->htSecondaryChannelOffset) {
+ case PHY_SINGLE_CHANNEL_CENTERED:
+ chanOffset = BW20;
+ break;
+
+ case PHY_DOUBLE_CHANNEL_LOW_PRIMARY:
+ chanOffset = BW40_LOW_PRIMARY;
+ break;
+
+ case PHY_DOUBLE_CHANNEL_HIGH_PRIMARY:
+ chanOffset = BW40_HIGH_PRIMARY;
+ break;
+
+ default:
+ chanOffset = BWALL;
+ break;
+
+ }
+
+ op_class = cds_regdm_get_opclass_from_channel(
+ pMac->scan.countryCodeCurrent,
+ psessionEntry->currentOperChannel,
+ chanOffset);
+
+ if (op_class == 0) {
+ lim_log(pMac, LOGE,
+ FL(
+ "Present Operating class is wrong, countryCodeCurrent: %s, currentOperChannel: %d, htSecondaryChannelOffset: %d, chanOffset: %d"
+ ),
+ pMac->scan.countryCodeCurrent,
+ psessionEntry->currentOperChannel,
+ psessionEntry->htSecondaryChannelOffset,
+ chanOffset);
+ } else {
+ lim_log(pMac, LOG1,
+ FL(
+ "Present Operating channel: %d chanOffset: %d, op class=%d"
+ ),
+ psessionEntry->currentOperChannel, chanOffset,
+ op_class);
+ }
+ suppOperClasses->present = 1;
+ suppOperClasses->classes[0] = op_class;
+
+ cds_regdm_get_curr_opclasses(&numClasses, &classes[0]);
+
+ for (i = 0; i < numClasses; i++) {
+ suppOperClasses->classes[i + 1] = classes[i];
+ }
+ /* add one for present operating class, added in the beginning */
+ suppOperClasses->num_classes = numClasses + 1;
+
+ return;
+}
+
+/*
+ * FUNCTION: Populate Link Identifier element IE
+ *
+ */
+
+void populate_dot11f_link_iden(tpAniSirGlobal pMac, tpPESession psessionEntry,
+ tDot11fIELinkIdentifier *linkIden,
+ tSirMacAddr peerMac, uint8_t reqType)
+{
+ uint8_t *initStaAddr = NULL;
+ uint8_t *respStaAddr = NULL;
+
+ (reqType == TDLS_INITIATOR) ? ((initStaAddr = linkIden->InitStaAddr),
+ (respStaAddr = linkIden->RespStaAddr))
+ : ((respStaAddr = linkIden->InitStaAddr),
+ (initStaAddr = linkIden->RespStaAddr));
+ cdf_mem_copy((uint8_t *) linkIden->bssid,
+ (uint8_t *) psessionEntry->bssId, sizeof(tSirMacAddr));
+
+ cdf_mem_copy((uint8_t *) initStaAddr,
+ psessionEntry->selfMacAddr, sizeof(tSirMacAddr));
+
+ cdf_mem_copy((uint8_t *) respStaAddr, (uint8_t *) peerMac,
+ sizeof(tSirMacAddr));
+
+ linkIden->present = 1;
+ return;
+
+}
+
+void populate_dot11f_tdls_ext_capability(tpAniSirGlobal pMac,
+ tpPESession psessionEntry,
+ tDot11fIEExtCap *extCapability)
+{
+ struct s_ext_cap *p_ext_cap = (struct s_ext_cap *)extCapability->bytes;
+
+ p_ext_cap->tdls_peer_psm_supp = PEER_PSM_SUPPORT;
+ p_ext_cap->tdls_peer_uapsd_buffer_sta = pMac->lim.gLimTDLSBufStaEnabled;
+
+ /*
+ * Set TDLS channel switching bits only if offchannel is enabled
+ * and TDLS Channel Switching is not prohibited by AP in ExtCap
+ * IE in assoc/re-assoc response.
+ */
+ if ((1 == pMac->lim.gLimTDLSOffChannelEnabled) &&
+ (!psessionEntry->tdls_chan_swit_prohibited)) {
+ p_ext_cap->tdls_channel_switching = 1;
+ p_ext_cap->tdls_chan_swit_prohibited = 0;
+ } else {
+ p_ext_cap->tdls_channel_switching = 0;
+ p_ext_cap->tdls_chan_swit_prohibited = TDLS_CH_SWITCH_PROHIBITED;
+ }
+ p_ext_cap->tdls_support = TDLS_SUPPORT;
+ p_ext_cap->tdls_prohibited = TDLS_PROHIBITED;
+
+ extCapability->present = 1;
+ /* For STA cases we alwasy support 11mc - Allow MAX length */
+ extCapability->num_bytes = DOT11F_IE_EXTCAP_MAX_LEN;
+
+ return;
+}
+
+/**
+ * lim_process_sme_tdls_mgmt_send_req() - send out tdls management frames
+ *
+ * @mac_ctx - global mac context
+ * @msg - message buffer received from SME.
+ *
+ * Process Send Mgmt Request from SME and transmit to AP.
+ *
+ * Return: eSIR_SUCCESS on success, error code otherwise
+ */
+tSirRetStatus lim_process_sme_tdls_mgmt_send_req(tpAniSirGlobal mac_ctx,
+ uint32_t *msg)
+{
+ /* get all discovery request parameters */
+ tSirTdlsSendMgmtReq *send_req = (tSirTdlsSendMgmtReq *) msg;
+ tpPESession session_entry;
+ uint8_t session_id;
+ tSirResultCodes result_code = eSIR_SME_INVALID_PARAMETERS;
+
+ lim_log(mac_ctx, LOG1, FL("Send Mgmt Recieved"));
+ session_entry = pe_find_session_by_bssid(mac_ctx,
+ send_req->bssid, &session_id);
+ if (NULL == session_entry) {
+ lim_log(mac_ctx, LOGE,
+ FL("PE Session does not exist for given sme session_id %d"),
+ send_req->sessionId);
+ goto lim_tdls_send_mgmt_error;
+ }
+
+ /* check if we are in proper state to work as TDLS client */
+ if (!LIM_IS_STA_ROLE(session_entry)) {
+ CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_ERROR,
+ FL("send mgmt received in wrong system Role %d"),
+ GET_LIM_SYSTEM_ROLE(session_entry));
+ goto lim_tdls_send_mgmt_error;
+ }
+
+ /*
+ * if we are still good, go ahead and check if we are in proper state to
+ * do TDLS discovery req/rsp/....frames.
+ */
+ if ((session_entry->limSmeState != eLIM_SME_ASSOCIATED_STATE) &&
+ (session_entry->limSmeState != eLIM_SME_LINK_EST_STATE)) {
+ lim_log(mac_ctx, LOGE,
+ FL("send mgmt received in invalid LIMsme state (%d)"),
+ session_entry->limSmeState);
+ goto lim_tdls_send_mgmt_error;
+ }
+
+ switch (send_req->reqType) {
+ case SIR_MAC_TDLS_DIS_REQ:
+ lim_log(mac_ctx, LOG1, FL("Transmit Discovery Request Frame"));
+ /* format TDLS discovery request frame and transmit it */
+ lim_send_tdls_dis_req_frame(mac_ctx, send_req->peerMac,
+ send_req->dialog, session_entry);
+ result_code = eSIR_SME_SUCCESS;
+ break;
+ case SIR_MAC_TDLS_DIS_RSP:
+ lim_log(mac_ctx, LOG1, FL("Transmit Discovery Response Frame"));
+ /* Send a response mgmt action frame */
+ lim_send_tdls_dis_rsp_frame(mac_ctx, send_req->peerMac,
+ send_req->dialog, session_entry, &send_req->addIe[0],
+ (send_req->length - sizeof(tSirTdlsSendMgmtReq)));
+ result_code = eSIR_SME_SUCCESS;
+ break;
+ case SIR_MAC_TDLS_SETUP_REQ:
+ lim_log(mac_ctx, LOG1, FL("Transmit Setup Request Frame"));
+ lim_send_tdls_link_setup_req_frame(mac_ctx,
+ send_req->peerMac, send_req->dialog, session_entry,
+ &send_req->addIe[0],
+ (send_req->length - sizeof(tSirTdlsSendMgmtReq)));
+ result_code = eSIR_SME_SUCCESS;
+ break;
+ case SIR_MAC_TDLS_SETUP_RSP:
+ lim_log(mac_ctx, LOG1, FL("Transmit Setup Response Frame"));
+ lim_send_tdls_setup_rsp_frame(mac_ctx,
+ send_req->peerMac, send_req->dialog, session_entry,
+ send_req->statusCode, &send_req->addIe[0],
+ (send_req->length - sizeof(tSirTdlsSendMgmtReq)));
+ result_code = eSIR_SME_SUCCESS;
+ break;
+ case SIR_MAC_TDLS_SETUP_CNF:
+ lim_log(mac_ctx, LOG1, FL("Transmit Setup Confirm Frame"));
+ lim_send_tdls_link_setup_cnf_frame(mac_ctx,
+ send_req->peerMac, send_req->dialog,
+ send_req->peerCapability, session_entry,
+ &send_req->addIe[0],
+ (send_req->length - sizeof(tSirTdlsSendMgmtReq)));
+ result_code = eSIR_SME_SUCCESS;
+ break;
+ case SIR_MAC_TDLS_TEARDOWN:
+ lim_log(mac_ctx, LOG1, FL("Transmit Teardown Frame"));
+ lim_send_tdls_teardown_frame(mac_ctx,
+ send_req->peerMac, send_req->statusCode,
+ send_req->responder, session_entry,
+ &send_req->addIe[0],
+ (send_req->length - sizeof(tSirTdlsSendMgmtReq)));
+ result_code = eSIR_SME_SUCCESS;
+ break;
+ case SIR_MAC_TDLS_PEER_TRAFFIC_IND:
+ break;
+ case SIR_MAC_TDLS_CH_SWITCH_REQ:
+ break;
+ case SIR_MAC_TDLS_CH_SWITCH_RSP:
+ break;
+ case SIR_MAC_TDLS_PEER_TRAFFIC_RSP:
+ break;
+ default:
+ break;
+ }
+
+lim_tdls_send_mgmt_error:
+ lim_send_sme_rsp(mac_ctx, eWNI_SME_TDLS_SEND_MGMT_RSP,
+ result_code, send_req->sessionId,
+ send_req->transactionId);
+
+ return eSIR_SUCCESS;
+}
+
+/*
+ * Send Response to Link Establish Request to SME
+ */
+void lim_send_sme_tdls_link_establish_req_rsp(tpAniSirGlobal pMac,
+ uint8_t sessionId, tSirMacAddr peerMac,
+ tDphHashNode *pStaDs, uint8_t status)
+{
+ tSirMsgQ mmhMsg = { 0 };
+
+ tSirTdlsLinkEstablishReqRsp *pTdlsLinkEstablishReqRsp = NULL;
+
+ pTdlsLinkEstablishReqRsp =
+ cdf_mem_malloc(sizeof(tSirTdlsLinkEstablishReqRsp));
+ if (NULL == pTdlsLinkEstablishReqRsp) {
+ lim_log(pMac, LOGE, FL("Failed to allocate memory"));
+ return;
+ }
+ pTdlsLinkEstablishReqRsp->statusCode = status;
+ if (peerMac) {
+ cdf_mem_copy(pTdlsLinkEstablishReqRsp->peerMac, peerMac,
+ sizeof(tSirMacAddr));
+ }
+ pTdlsLinkEstablishReqRsp->sessionId = sessionId;
+ mmhMsg.type = eWNI_SME_TDLS_LINK_ESTABLISH_RSP;
+ mmhMsg.bodyptr = pTdlsLinkEstablishReqRsp;
+ mmhMsg.bodyval = 0;
+ lim_sys_process_mmh_msg_api(pMac, &mmhMsg, ePROT);
+ return;
+
+}
+
+/*
+ * Once link is teardown, send Del Peer Ind to SME
+ */
+static CDF_STATUS lim_send_sme_tdls_del_sta_rsp(tpAniSirGlobal pMac,
+ uint8_t sessionId,
+ tSirMacAddr peerMac,
+ tDphHashNode *pStaDs, uint8_t status)
+{
+ tSirMsgQ mmhMsg = { 0 };
+ tSirTdlsDelStaRsp *pDelSta = NULL;
+ mmhMsg.type = eWNI_SME_TDLS_DEL_STA_RSP;
+
+ pDelSta = cdf_mem_malloc(sizeof(tSirTdlsDelStaRsp));
+ if (NULL == pDelSta) {
+ lim_log(pMac, LOGE, FL("Failed to allocate memory"));
+ return CDF_STATUS_E_NOMEM;
+ }
+
+ pDelSta->sessionId = sessionId;
+ pDelSta->statusCode = status;
+ if (pStaDs) {
+ pDelSta->staId = pStaDs->staIndex;
+ } else
+ pDelSta->staId = STA_INVALID_IDX;
+
+ if (peerMac) {
+ cdf_mem_copy(pDelSta->peerMac, peerMac, sizeof(tSirMacAddr));
+ }
+
+ pDelSta->length = sizeof(tSirTdlsDelStaRsp);
+ pDelSta->messageType = eWNI_SME_TDLS_DEL_STA_RSP;
+
+ mmhMsg.bodyptr = pDelSta;
+
+ mmhMsg.bodyval = 0;
+ lim_sys_process_mmh_msg_api(pMac, &mmhMsg, ePROT);
+ return CDF_STATUS_SUCCESS;
+
+}
+
+/*
+ * Process Send Mgmt Request from SME and transmit to AP.
+ */
+tSirRetStatus lim_process_sme_tdls_add_sta_req(tpAniSirGlobal pMac,
+ uint32_t *pMsgBuf)
+{
+ /* get all discovery request parameters */
+ tSirTdlsAddStaReq *pAddStaReq = (tSirTdlsAddStaReq *) pMsgBuf;
+ tpPESession psessionEntry;
+ uint8_t sessionId;
+
+ lim_log(pMac, LOG1, FL("TDLS Add STA Request Recieved"));
+ psessionEntry =
+ pe_find_session_by_bssid(pMac, pAddStaReq->bssid, &sessionId);
+ if (psessionEntry == NULL) {
+ lim_log(pMac, LOGE,
+ FL(
+ "PE Session does not exist for given sme sessionId %d"
+ ),
+ pAddStaReq->sessionId);
+ goto lim_tdls_add_sta_error;
+ }
+
+ /* check if we are in proper state to work as TDLS client */
+ if (!LIM_IS_STA_ROLE(psessionEntry)) {
+ CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_ERROR,
+ "send mgmt received in wrong system Role %d",
+ GET_LIM_SYSTEM_ROLE(psessionEntry));
+ goto lim_tdls_add_sta_error;
+ }
+
+ /*
+ * if we are still good, go ahead and check if we are in proper state to
+ * do TDLS discovery req/rsp/....frames.
+ */
+ if ((psessionEntry->limSmeState != eLIM_SME_ASSOCIATED_STATE) &&
+ (psessionEntry->limSmeState != eLIM_SME_LINK_EST_STATE)) {
+
+ lim_log(pMac, LOGE,
+ FL("send mgmt received in invalid LIMsme state (%d)"),
+ psessionEntry->limSmeState);
+ goto lim_tdls_add_sta_error;
+ }
+
+ pMac->lim.gLimAddStaTdls = true;
+
+ /* To start with, send add STA request to HAL */
+ if (eSIR_FAILURE == lim_tdls_setup_add_sta(pMac, pAddStaReq, psessionEntry)) {
+ lim_log(pMac, LOGE,
+ FL("Add TDLS Station request failed"));
+ goto lim_tdls_add_sta_error;
+ }
+ return eSIR_SUCCESS;
+lim_tdls_add_sta_error:
+ lim_send_sme_tdls_add_sta_rsp(pMac,
+ pAddStaReq->sessionId, pAddStaReq->peerMac,
+ (pAddStaReq->tdlsAddOper == TDLS_OPER_UPDATE),
+ NULL, eSIR_FAILURE);
+
+ return eSIR_SUCCESS;
+}
+
+/*
+ * Process Del Sta Request from SME .
+ */
+tSirRetStatus lim_process_sme_tdls_del_sta_req(tpAniSirGlobal pMac,
+ uint32_t *pMsgBuf)
+{
+ /* get all discovery request parameters */
+ tSirTdlsDelStaReq *pDelStaReq = (tSirTdlsDelStaReq *) pMsgBuf;
+ tpPESession psessionEntry;
+ uint8_t sessionId;
+ tpDphHashNode pStaDs = NULL;
+
+ lim_log(pMac, LOG1, FL("TDLS Delete STA Request Recieved"));
+ psessionEntry =
+ pe_find_session_by_bssid(pMac, pDelStaReq->bssid, &sessionId);
+ if (psessionEntry == NULL) {
+ lim_log(pMac, LOGE,
+ FL(
+ "PE Session does not exist for given sme sessionId %d"
+ ),
+ pDelStaReq->sessionId);
+ lim_send_sme_tdls_del_sta_rsp(pMac, pDelStaReq->sessionId,
+ pDelStaReq->peerMac, NULL,
+ eSIR_FAILURE);
+ return eSIR_FAILURE;
+ }
+
+ /* check if we are in proper state to work as TDLS client */
+ if (!LIM_IS_STA_ROLE(psessionEntry)) {
+ CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_ERROR,
+ "Del sta received in wrong system Role %d",
+ GET_LIM_SYSTEM_ROLE(psessionEntry));
+ goto lim_tdls_del_sta_error;
+ }
+
+ /*
+ * if we are still good, go ahead and check if we are in proper state to
+ * do TDLS discovery req/rsp/....frames.
+ */
+ if ((psessionEntry->limSmeState != eLIM_SME_ASSOCIATED_STATE) &&
+ (psessionEntry->limSmeState != eLIM_SME_LINK_EST_STATE)) {
+
+ lim_log(pMac, LOGE,
+ FL("Del Sta received in invalid LIMsme state (%d)"),
+ psessionEntry->limSmeState);
+ goto lim_tdls_del_sta_error;
+ }
+
+ pStaDs = lim_tdls_del_sta(pMac, pDelStaReq->peerMac, psessionEntry);
+
+ /* now send indication to SME-->HDD->TL to remove STA from TL */
+
+ if (pStaDs) {
+ lim_send_sme_tdls_del_sta_rsp(pMac, psessionEntry->smeSessionId,
+ pDelStaReq->peerMac, pStaDs,
+ eSIR_SUCCESS);
+ lim_release_peer_idx(pMac, pStaDs->assocId, psessionEntry);
+
+ /* Clear the aid in peerAIDBitmap as this aid is now in freepool */
+ CLEAR_PEER_AID_BITMAP(psessionEntry->peerAIDBitmap,
+ pStaDs->assocId);
+ lim_delete_dph_hash_entry(pMac, pStaDs->staAddr, pStaDs->assocId,
+ psessionEntry);
+
+ return eSIR_SUCCESS;
+
+ }
+
+lim_tdls_del_sta_error:
+ lim_send_sme_tdls_del_sta_rsp(pMac, psessionEntry->smeSessionId,
+ pDelStaReq->peerMac, NULL, eSIR_FAILURE);
+
+ return eSIR_SUCCESS;
+}
+
+/* Intersects the two input arrays and outputs an array */
+/* For now the array length of uint8_t suffices */
+static void lim_tdls_get_intersection(uint8_t *input_array1,
+ uint8_t input1_length,
+ uint8_t *input_array2,
+ uint8_t input2_length,
+ uint8_t *output_array,
+ uint8_t *output_length)
+{
+ uint8_t i, j, k = 0, flag = 0;
+ for (i = 0; i < input1_length; i++) {
+ flag = 0;
+ for (j = 0; j < input2_length; j++) {
+ if (input_array1[i] == input_array2[j]) {
+ flag = 1;
+ break;
+ }
+ }
+ if (flag == 1) {
+ output_array[k] = input_array1[i];
+ k++;
+ }
+ }
+ *output_length = k;
+}
+
+/**
+ * lim_process_sme_tdls_link_establish_req() - process tdls link establishment
+ * request
+ *
+ * @mac_ctx - global MAC context
+ * @msg_buf - message buffer from SME
+ *
+ * Process Link Establishment Request from SME
+ *
+ * Return: eSIR_SUCCESS on success, failure code otherwise.
+ */
+tSirRetStatus lim_process_sme_tdls_link_establish_req(tpAniSirGlobal mac_ctx,
+ uint32_t *msg_buf)
+{
+ /* get all discovery request parameters */
+ tSirTdlsLinkEstablishReq *tdls_req =
+ (tSirTdlsLinkEstablishReq *) msg_buf;
+ tpPESession session_entry;
+ uint8_t session_id;
+ tpTdlsLinkEstablishParams tdls_req_params;
+ tSirMsgQ msg;
+ uint16_t peer_idx = 0;
+ tpDphHashNode stads = NULL;
+ uint32_t self_num_chan = WNI_CFG_VALID_CHANNEL_LIST_LEN;
+ uint8_t self_supp_chan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
+
+ CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_INFO,
+ FL("Send Mgmt Recieved"));
+
+ session_entry = pe_find_session_by_bssid(mac_ctx, tdls_req->bssid,
+ &session_id);
+ if (NULL == session_entry) {
+ CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_ERROR,
+ FL("PE Session does not exist for sme session_id %d"),
+ tdls_req->sessionId);
+ lim_send_sme_tdls_link_establish_req_rsp(mac_ctx,
+ tdls_req->sessionId, tdls_req->peerMac, NULL,
+ eSIR_FAILURE);
+ return eSIR_FAILURE;
+ }
+
+ /* check if we are in proper state to work as TDLS client */
+ if (!LIM_IS_STA_ROLE(session_entry)) {
+ CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_ERROR,
+ FL("TDLS Link Establish Request received in wrong system Role %d"),
+ GET_LIM_SYSTEM_ROLE(session_entry));
+ goto lim_tdls_link_establish_error;
+ }
+
+ /*
+ * if we are still good, go ahead and check if we are in proper state to
+ * do TDLS discovery req/rsp/....frames.
+ */
+ if ((session_entry->limSmeState != eLIM_SME_ASSOCIATED_STATE) &&
+ (session_entry->limSmeState != eLIM_SME_LINK_EST_STATE)) {
+ lim_log(mac_ctx, LOGE,
+ FL("TDLS Link Establish Request received in invalid LIMsme state (%d)"),
+ session_entry->limSmeState);
+ goto lim_tdls_link_establish_error;
+ }
+
+ stads = dph_lookup_hash_entry(mac_ctx, tdls_req->peerMac, &peer_idx,
+ &session_entry->dph.dphHashTable);
+ if (NULL == stads) {
+ lim_log(mac_ctx, LOGE, FL("stads is NULL"));
+ goto lim_tdls_link_establish_error;
+ }
+ tdls_req_params = cdf_mem_malloc(sizeof(tTdlsLinkEstablishParams));
+ if (NULL == tdls_req_params) {
+ lim_log(mac_ctx, LOGE,
+ FL("Unable to allocate memory TDLS Link Establish Request"));
+ return eSIR_MEM_ALLOC_FAILED;
+ }
+
+ cdf_mem_set((uint8_t *) tdls_req_params,
+ sizeof(tTdlsLinkEstablishParams), 0);
+
+ tdls_req_params->staIdx = stads->staIndex;
+ tdls_req_params->isResponder = tdls_req->isResponder;
+ tdls_req_params->uapsdQueues = tdls_req->uapsdQueues;
+ tdls_req_params->maxSp = tdls_req->maxSp;
+ tdls_req_params->isBufsta = tdls_req->isBufSta;
+ tdls_req_params->isOffChannelSupported =
+ tdls_req->isOffChannelSupported;
+
+ if (0 == tdls_req->supportedChannelsLen)
+ goto send_tdls_establish_request;
+
+ if (wlan_cfg_get_str(mac_ctx, WNI_CFG_VALID_CHANNEL_LIST,
+ self_supp_chan,
+ &self_num_chan) != eSIR_SUCCESS) {
+ /**
+ * Could not get Valid channel list from CFG.
+ * Log error.
+ */
+ lim_log(mac_ctx, LOGE,
+ FL("could not retrieve Valid channel list"));
+ }
+
+ if (self_num_chan > WNI_CFG_VALID_CHANNEL_LIST_LEN) {
+ lim_log(mac_ctx, LOGE,
+ FL("Channel List more than Valid Channel list"));
+ self_num_chan = WNI_CFG_VALID_CHANNEL_LIST_LEN;
+ }
+
+ if (tdls_req->supportedChannelsLen > SIR_MAC_MAX_SUPP_CHANNELS) {
+ lim_log(mac_ctx, LOGE,
+ FL("Channel List is more than the supported Channel list"));
+ tdls_req->supportedChannelsLen = SIR_MAC_MAX_SUPP_CHANNELS;
+ }
+
+ lim_tdls_get_intersection(self_supp_chan, self_num_chan,
+ tdls_req->supportedChannels, tdls_req->supportedChannelsLen,
+ tdls_req_params->validChannels,
+ &tdls_req_params->validChannelsLen);
+
+send_tdls_establish_request:
+ cdf_mem_copy(tdls_req_params->validOperClasses,
+ tdls_req->supportedOperClasses,
+ tdls_req->supportedOperClassesLen);
+ tdls_req_params->validOperClassesLen =
+ tdls_req->supportedOperClassesLen;
+
+ msg.type = WMA_SET_TDLS_LINK_ESTABLISH_REQ;
+ msg.reserved = 0;
+ msg.bodyptr = tdls_req_params;
+ msg.bodyval = 0;
+ if (eSIR_SUCCESS != wma_post_ctrl_msg(mac_ctx, &msg)) {
+ lim_log(mac_ctx, LOGE, FL("halPostMsgApi failed"));
+ goto lim_tdls_link_establish_error;
+ }
+ return eSIR_SUCCESS;
+
+lim_tdls_link_establish_error:
+ lim_send_sme_tdls_link_establish_req_rsp(mac_ctx,
+ session_entry->smeSessionId, tdls_req->peerMac, NULL,
+ eSIR_FAILURE);
+
+ return eSIR_SUCCESS;
+}
+
+/**
+ * lim_delete_tdls_peers() - delete tdls peers
+ *
+ * @mac_ctx - global MAC context
+ * @session_entry - PE session entry
+ *
+ * Delete all the TDLS peer connected before leaving the BSS
+ *
+ * Return: eSIR_SUCCESS on success, error code otherwise
+ */
+tSirRetStatus lim_delete_tdls_peers(tpAniSirGlobal mac_ctx,
+ tpPESession session_entry)
+{
+ tpDphHashNode stads = NULL;
+ int i, aid;
+ size_t aid_bitmap_size = sizeof(session_entry->peerAIDBitmap);
+
+ if (NULL == session_entry) {
+ lim_log(mac_ctx, LOGE, FL("NULL session_entry"));
+ return eSIR_FAILURE;
+ }
+
+ /*
+ * Check all the set bit in peerAIDBitmap and delete the peer
+ * (with that aid) entry from the hash table and add the aid
+ * in free pool
+ */
+ for (i = 0; i < aid_bitmap_size / sizeof(uint32_t); i++) {
+ for (aid = 0; aid < (sizeof(uint32_t) << 3); aid++) {
+ if (!CHECK_BIT(session_entry->peerAIDBitmap[i], aid))
+ continue;
+ stads = dph_get_hash_entry(mac_ctx,
+ (aid + i * (sizeof(uint32_t) << 3)),
+ &session_entry->dph.dphHashTable);
+
+ if (NULL != stads) {
+ lim_log(mac_ctx, LOGE,
+ FL("Deleting "MAC_ADDRESS_STR),
+ MAC_ADDR_ARRAY(stads->staAddr));
+
+ lim_send_deauth_mgmt_frame(mac_ctx,
+ eSIR_MAC_DEAUTH_LEAVING_BSS_REASON,
+ stads->staAddr, session_entry, false);
+ dph_delete_hash_entry(mac_ctx,
+ stads->staAddr, stads->assocId,
+ &session_entry->dph.dphHashTable);
+ }
+ lim_release_peer_idx(mac_ctx,
+ (aid + i * (sizeof(uint32_t) << 3)),
+ session_entry);
+ CLEAR_BIT(session_entry->peerAIDBitmap[i], aid);
+ }
+ }
+ lim_send_sme_tdls_delete_all_peer_ind(mac_ctx, session_entry);
+
+ return eSIR_SUCCESS;
+}
+
+#endif
diff --git a/core/mac/src/pe/lim/lim_prop_exts_utils.c b/core/mac/src/pe/lim/lim_prop_exts_utils.c
new file mode 100644
index 0000000..d534905
--- /dev/null
+++ b/core/mac/src/pe/lim/lim_prop_exts_utils.c
@@ -0,0 +1,296 @@
+/*
+ * Copyright (c) 2011-2015 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_prop_exts_utils.cc contains the utility functions
+ * to populate, parse proprietary extensions required to
+ * support ANI feature set.
+ *
+ * Author: Chandra Modumudi
+ * Date: 11/27/02
+ * History:-
+ * Date Modified by Modification Information
+ * --------------------------------------------------------------------
+ *
+ */
+#include "ani_global.h"
+#include "wni_cfg.h"
+#include "sir_common.h"
+#include "sir_debug.h"
+#include "utils_api.h"
+#include "cfg_api.h"
+#include "lim_api.h"
+#include "lim_types.h"
+#include "lim_utils.h"
+#include "lim_assoc_utils.h"
+#include "lim_prop_exts_utils.h"
+#include "lim_ser_des_utils.h"
+#include "lim_trace.h"
+#ifdef WLAN_FEATURE_VOWIFI_11R
+#include "lim_ft_defs.h"
+#endif
+#include "lim_session.h"
+#define LIM_GET_NOISE_MAX_TRY 5
+/**
+ * lim_extract_ap_capability() - extract AP's HCF/WME/WSM capability
+ * @mac_ctx: Pointer to Global MAC structure
+ * @p_ie: Pointer to starting IE in Beacon/Probe Response
+ * @ie_len: Length of all IEs combined
+ * @qos_cap: Bits are set according to capabilities
+ * @prop_cap: Pointer to prop info IE.
+ * @uapsd: pointer to uapsd
+ * @local_constraint: Pointer to local power constraint.
+ * @session: A pointer to session entry.
+ *
+ * This function is called to extract AP's HCF/WME/WSM capability
+ * from the IEs received from it in Beacon/Probe Response frames
+ *
+ * Return: None
+ */
+void
+lim_extract_ap_capability(tpAniSirGlobal mac_ctx, uint8_t *p_ie,
+ uint16_t ie_len, uint8_t *qos_cap, uint16_t *prop_cap, uint8_t *uapsd,
+ tPowerdBm *local_constraint, tpPESession session)
+{
+ tSirProbeRespBeacon *beacon_struct;
+#if !defined WLAN_FEATURE_VOWIFI
+ uint32_t local_power_constraints = 0;
+#endif
+ uint32_t enable_txbf_20mhz;
+ tSirRetStatus cfg_set_status = eSIR_FAILURE;
+ tSirRetStatus cfg_get_status = eSIR_FAILURE;
+
+ beacon_struct = cdf_mem_malloc(sizeof(tSirProbeRespBeacon));
+ if (NULL == beacon_struct) {
+ lim_log(mac_ctx, LOGE, FL("Unable to allocate memory"));
+ return;
+ }
+
+ cdf_mem_set((uint8_t *) beacon_struct, sizeof(tSirProbeRespBeacon), 0);
+ *qos_cap = 0;
+ *prop_cap = 0;
+ *uapsd = 0;
+ lim_log(mac_ctx, LOG3,
+ FL("In lim_extract_ap_capability: The IE's being received:"));
+ sir_dump_buf(mac_ctx, SIR_LIM_MODULE_ID, LOG3, p_ie, ie_len);
+ if (sir_parse_beacon_ie(mac_ctx, beacon_struct, p_ie,
+ (uint32_t) ie_len) == eSIR_SUCCESS) {
+ if (beacon_struct->wmeInfoPresent
+ || beacon_struct->wmeEdcaPresent)
+ LIM_BSS_CAPS_SET(WME, *qos_cap);
+ if (LIM_BSS_CAPS_GET(WME, *qos_cap)
+ && beacon_struct->wsmCapablePresent)
+ LIM_BSS_CAPS_SET(WSM, *qos_cap);
+ if (beacon_struct->propIEinfo.capabilityPresent)
+ *prop_cap = beacon_struct->propIEinfo.capability;
+ if (beacon_struct->HTCaps.present)
+ mac_ctx->lim.htCapabilityPresentInBeacon = 1;
+ else
+ mac_ctx->lim.htCapabilityPresentInBeacon = 0;
+
+#ifdef WLAN_FEATURE_11AC
+ CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_INFO_MED,
+ "beacon.VHTCaps.present = %d BSS_VHT_Capable:%d",
+ beacon_struct->VHTCaps.present,
+ IS_BSS_VHT_CAPABLE(beacon_struct->VHTCaps));
+ CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_INFO_MED,
+ "***beacon.SU Beamformer Capable*****=%d",
+ beacon_struct->VHTCaps.suBeamFormerCap);
+
+ if (IS_BSS_VHT_CAPABLE(beacon_struct->VHTCaps) &&
+ beacon_struct->VHTOperation.present &&
+ session->vhtCapability) {
+ session->vhtCapabilityPresentInBeacon = 1;
+ if (((beacon_struct->Vendor1IEPresent &&
+ beacon_struct->vendor2_ie.present &&
+ beacon_struct->Vendor3IEPresent)) &&
+ (((beacon_struct->VHTCaps.txMCSMap &
+ VHT_MCS_3x3_MASK) == VHT_MCS_3x3_MASK) &&
+ ((beacon_struct->VHTCaps.txMCSMap &
+ VHT_MCS_2x2_MASK) != VHT_MCS_2x2_MASK))) {
+ session->txBFIniFeatureEnabled = 0;
+ }
+ } else {
+ session->vhtCapabilityPresentInBeacon = 0;
+ }
+ if (session->vhtCapabilityPresentInBeacon == 1 &&
+ session->txBFIniFeatureEnabled == 0) {
+ cfg_set_status = cfg_set_int(mac_ctx,
+ WNI_CFG_VHT_SU_BEAMFORMEE_CAP,
+ 0);
+ if (cfg_set_status != eSIR_SUCCESS)
+ lim_log(mac_ctx, LOGP,
+ FL("Set VHT_SU_BEAMFORMEE_CAP Fail"));
+ }
+ if (session->vhtCapabilityPresentInBeacon == 1 &&
+ !session->htSupportedChannelWidthSet) {
+ cfg_get_status = wlan_cfg_get_int(mac_ctx,
+ WNI_CFG_VHT_ENABLE_TXBF_20MHZ,
+ &enable_txbf_20mhz);
+ if ((IS_SIR_STATUS_SUCCESS(cfg_get_status)) &&
+ (false == enable_txbf_20mhz))
+ session->txBFIniFeatureEnabled = 0;
+ } else if (session->vhtCapabilityPresentInBeacon == 1 &&
+ beacon_struct->VHTOperation.chanWidth) {
+ session->ch_center_freq_seg0 =
+ beacon_struct->VHTOperation.chanCenterFreqSeg1;
+ session->ch_center_freq_seg1 =
+ beacon_struct->VHTOperation.chanCenterFreqSeg2;
+ session->ch_width =
+ beacon_struct->VHTOperation.chanWidth + 1;
+ if (CH_WIDTH_80MHZ < session->ch_width) {
+ session->enable_su_tx_bformer = 0;
+ session->nss = 1;
+ }
+ }
+ if (session->vhtCapabilityPresentInBeacon == 1 &&
+ !session->htSupportedChannelWidthSet &&
+ session->txBFIniFeatureEnabled == 0) {
+ cfg_set_status = cfg_set_int(mac_ctx,
+ WNI_CFG_VHT_SU_BEAMFORMEE_CAP,
+ 0);
+ if (cfg_set_status != eSIR_SUCCESS)
+ lim_log(mac_ctx, LOGP,
+ FL("Set VHT_SU_BEAMFORMEE_CAP Fail"));
+ }
+#endif
+ /* Extract the UAPSD flag from WMM Parameter element */
+ if (beacon_struct->wmeEdcaPresent)
+ *uapsd = beacon_struct->edcaParams.qosInfo.uapsd;
+#if defined FEATURE_WLAN_ESE
+ /* If there is Power Constraint Element specifically,
+ * adapt to it. Hence there is else condition check
+ * for this if statement.
+ */
+ if (beacon_struct->eseTxPwr.present)
+ *local_constraint = beacon_struct->eseTxPwr.power_limit;
+ session->is_ese_version_ie_present =
+ beacon_struct->is_ese_ver_ie_present;
+#endif
+ if (beacon_struct->powerConstraintPresent) {
+#if defined WLAN_FEATURE_VOWIFI
+ *local_constraint -=
+ beacon_struct->localPowerConstraint.
+ localPowerConstraints;
+#else
+ local_power_constraints =
+ (uint32_t) beacon_struct->localPowerConstraint.
+ localPowerConstraints;
+#endif
+ }
+#if !defined WLAN_FEATURE_VOWIFI
+ if (cfg_set_int
+ (mac_ctx, WNI_CFG_LOCAL_POWER_CONSTRAINT,
+ local_power_constraints) != eSIR_SUCCESS) {
+ lim_log(mac_ctx, LOGP,
+ FL
+ ("Could not update local power constraint to cfg."));
+ }
+#endif
+ session->country_info_present = false;
+ /* Initializing before first use */
+ if (beacon_struct->countryInfoPresent)
+ session->country_info_present = true;
+ }
+ cdf_mem_free(beacon_struct);
+ return;
+} /****** end lim_extract_ap_capability() ******/
+
+/**
+ * lim_get_htcb_state
+ *
+ ***FUNCTION:
+ * This routing provides the translation of Airgo Enum to HT enum for determining
+ * secondary channel offset.
+ * Airgo Enum is required for backward compatibility purposes.
+ *
+ *
+ ***NOTE:
+ *
+ * @param pMac - Pointer to Global MAC structure
+ * @return The corresponding HT enumeration
+ */
+ePhyChanBondState lim_get_htcb_state(ePhyChanBondState aniCBMode)
+{
+ switch (aniCBMode) {
+#ifdef WLAN_FEATURE_11AC
+ case PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW:
+ case PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_CENTERED:
+ case PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH:
+#endif
+ case PHY_DOUBLE_CHANNEL_HIGH_PRIMARY:
+ return PHY_DOUBLE_CHANNEL_HIGH_PRIMARY;
+#ifdef WLAN_FEATURE_11AC
+ case PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW:
+ case PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_CENTERED:
+ case PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH:
+#endif
+ case PHY_DOUBLE_CHANNEL_LOW_PRIMARY:
+ return PHY_DOUBLE_CHANNEL_LOW_PRIMARY;
+#ifdef WLAN_FEATURE_11AC
+ case PHY_QUADRUPLE_CHANNEL_20MHZ_CENTERED_40MHZ_CENTERED:
+ return PHY_SINGLE_CHANNEL_CENTERED;
+#endif
+ default:
+ return PHY_SINGLE_CHANNEL_CENTERED;
+ }
+}
+
+/*
+ * lim_get_sta_peer_type
+ *
+ ***FUNCTION:
+ * This API returns STA peer type
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ *
+ ***NOTE:
+ *
+ * @param pMac - Pointer to Global MAC structure
+ * @param pStaDs - Pointer to the tpDphHashNode of the STA
+ * under consideration
+ * @return tStaRateMode
+ */
+tStaRateMode lim_get_sta_peer_type(tpAniSirGlobal pMac,
+ tpDphHashNode pStaDs, tpPESession psessionEntry)
+{
+ tStaRateMode staPeerType = eSTA_11b;
+#ifdef WLAN_FEATURE_11AC
+ if (pStaDs->mlmStaContext.vhtCapability)
+ staPeerType = eSTA_11ac;
+#endif
+ else if (pStaDs->mlmStaContext.htCapability)
+ staPeerType = eSTA_11n;
+ else if (pStaDs->erpEnabled)
+ staPeerType = eSTA_11bg;
+ else if (psessionEntry->limRFBand == SIR_BAND_5_GHZ)
+ staPeerType = eSTA_11a;
+ return staPeerType;
+}
diff --git a/core/mac/src/pe/lim/lim_prop_exts_utils.h b/core/mac/src/pe/lim/lim_prop_exts_utils.h
new file mode 100644
index 0000000..a648a78
--- /dev/null
+++ b/core/mac/src/pe/lim/lim_prop_exts_utils.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2011-2014 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_prop_exts_utils.h contains the definitions
+ * used by all LIM modules to support proprietary features.
+ * Author: Chandra Modumudi
+ * Date: 12/11/02
+ * History:-
+ * Date Modified by Modification Information
+ * --------------------------------------------------------------------
+ *
+ */
+
+#ifndef __LIM_PROP_EXTS_UTILS_H
+#define __LIM_PROP_EXTS_UTILS_H
+
+/* Function templates */
+void limQuietBss(tpAniSirGlobal, uint32_t);
+void lim_cleanupMeasData(tpAniSirGlobal);
+void limDeleteMeasTimers(tpAniSirGlobal);
+void limStopMeasTimers(tpAniSirGlobal pMac);
+void lim_cleanupMeasResources(tpAniSirGlobal);
+void limRestorePreLearnState(tpAniSirGlobal);
+void limCollectMeasurementData(tpAniSirGlobal, uint32_t *, tpSchBeaconStruct);
+void limCollectRSSI(tpAniSirGlobal);
+void limDeleteCurrentBssWdsNode(tpAniSirGlobal);
+uint32_t limComputeAvg(tpAniSirGlobal, uint32_t, uint32_t);
+
+/* / Function to extract AP's HCF capability from IE fields */
+void lim_extract_ap_capability(tpAniSirGlobal, uint8_t *, uint16_t, uint8_t *,
+ uint16_t *, uint8_t *, tPowerdBm *, tpPESession);
+
+tStaRateMode lim_get_sta_peer_type(tpAniSirGlobal, tpDphHashNode, tpPESession);
+#ifdef WLAN_FEATURE_11AC
+ePhyChanBondState lim_get_htcb_state(ePhyChanBondState aniCBMode);
+#endif
+
+#endif /* __LIM_PROP_EXTS_UTILS_H */
diff --git a/core/mac/src/pe/lim/lim_scan_result_utils.c b/core/mac/src/pe/lim/lim_scan_result_utils.c
new file mode 100644
index 0000000..387152e
--- /dev/null
+++ b/core/mac/src/pe/lim/lim_scan_result_utils.c
@@ -0,0 +1,421 @@
+/*
+ * Copyright (c) 2011-2015 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_scan_result_utils.cc contains the utility functions
+ * LIM uses for maintaining and accessing scan results on STA.
+ * Author: Chandra Modumudi
+ * Date: 02/13/02
+ * History:-
+ * Date Modified by Modification Information
+ * --------------------------------------------------------------------
+ */
+
+#include "lim_types.h"
+#include "lim_utils.h"
+#include "lim_ser_des_utils.h"
+#include "lim_api.h"
+#ifdef WLAN_FEATURE_VOWIFI_11R
+#include "lim_ft_defs.h"
+#endif
+#include "lim_session.h"
+#if defined WLAN_FEATURE_VOWIFI
+#include "rrm_api.h"
+#endif
+#include "cds_utils.h"
+
+
+/**
+ * lim_collect_bss_description()
+ *
+ ***FUNCTION:
+ * This function is called during scan upon receiving
+ * Beacon/Probe Response frame to check if the received
+ * frame matches scan criteria, collect BSS description
+ * and add it to cached scan results.
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ * NA
+ *
+ ***NOTE:
+ * NA
+ *
+ * @param pMac - Pointer to Global MAC structure
+ * @param pBPR - Pointer to parsed Beacon/Probe Response structure
+ * @param pRxPacketInfo - Pointer to Received frame's BD
+ * ---------if defined WLAN_FEATURE_VOWIFI------
+ * @param fScanning - flag to indicate if it is during scan.
+ * ---------------------------------------------
+ *
+ * @return None
+ */
+#if defined WLAN_FEATURE_VOWIFI
+CDF_STATUS
+lim_collect_bss_description(tpAniSirGlobal pMac,
+ tSirBssDescription *pBssDescr,
+ tpSirProbeRespBeacon pBPR,
+ uint8_t *pRxPacketInfo, uint8_t fScanning)
+#else
+CDF_STATUS
+lim_collect_bss_description(tpAniSirGlobal pMac,
+ tSirBssDescription *pBssDescr,
+ tpSirProbeRespBeacon pBPR, uint8_t *pRxPacketInfo)
+#endif
+{
+ uint8_t *pBody;
+ uint32_t ieLen = 0;
+ tpSirMacMgmtHdr pHdr;
+ uint8_t channelNum;
+ uint8_t rxChannel;
+ uint8_t rfBand = 0;
+
+ pHdr = WMA_GET_RX_MAC_HEADER(pRxPacketInfo);
+
+ if (SIR_MAC_B_PR_SSID_OFFSET > WMA_GET_RX_PAYLOAD_LEN(pRxPacketInfo)) {
+ CDF_ASSERT(WMA_GET_RX_PAYLOAD_LEN(pRxPacketInfo) >=
+ SIR_MAC_B_PR_SSID_OFFSET);
+ return CDF_STATUS_E_FAILURE;
+ }
+ ieLen =
+ WMA_GET_RX_PAYLOAD_LEN(pRxPacketInfo) - SIR_MAC_B_PR_SSID_OFFSET;
+ rxChannel = WMA_GET_RX_CH(pRxPacketInfo);
+ pBody = WMA_GET_RX_MPDU_DATA(pRxPacketInfo);
+ rfBand = WMA_GET_RX_RFBAND(pRxPacketInfo);
+
+ /**
+ * Length of BSS desription is without length of
+ * length itself and length of pointer that holds ieFields.
+ *
+ * tSirBssDescription
+ * +--------+---------------------------------+---------------+
+ * | length | other fields | pointer to IEs|
+ * +--------+---------------------------------+---------------+
+ * ^
+ * ieFields
+ */
+ pBssDescr->length = (uint16_t)(offsetof(tSirBssDescription, ieFields[0])
+ - sizeof(pBssDescr->length) + ieLen);
+
+ /* Copy BSS Id */
+ cdf_mem_copy((uint8_t *) &pBssDescr->bssId,
+ (uint8_t *) pHdr->bssId, sizeof(tSirMacAddr));
+
+ /* Copy Timestamp, Beacon Interval and Capability Info */
+ pBssDescr->scanSysTimeMsec = cdf_mc_timer_get_system_time();
+
+ pBssDescr->timeStamp[0] = pBPR->timeStamp[0];
+ pBssDescr->timeStamp[1] = pBPR->timeStamp[1];
+ pBssDescr->beaconInterval = pBPR->beaconInterval;
+ pBssDescr->capabilityInfo =
+ lim_get_u16((uint8_t *) &pBPR->capabilityInfo);
+
+ if (!pBssDescr->beaconInterval) {
+ lim_log(pMac, LOGW,
+ FL("Beacon Interval is ZERO, making it to default 100 "
+ MAC_ADDRESS_STR), MAC_ADDR_ARRAY(pHdr->bssId));
+ pBssDescr->beaconInterval = 100;
+ }
+ /*
+ * There is a narrow window after Channel Switch msg is sent to HAL and before the AGC is shut
+ * down and beacons/Probe Rsps can trickle in and we may report the incorrect channel in 5Ghz
+ * band, so not relying on the 'last Scanned Channel' stored in LIM.
+ * Instead use the value returned by RXP in BD. This the the same value which HAL programs into
+ * RXP before every channel switch.
+ * Right now there is a problem in 5Ghz, where we are receiving beacons from a channel different from
+ * the currently scanned channel. so incorrect channel is reported to CSR and association does not happen.
+ * So for now we keep on looking for the channel info in the beacon (DSParamSet IE OR HT Info IE), and only if it
+ * is not present in the beacon, we go for the channel info present in RXP.
+ * This fix will work for 5Ghz 11n devices, but for 11a devices, we have to rely on RXP routing flag to get the correct channel.
+ * So The problem of incorrect channel reporting in 5Ghz will still remain for 11a devices.
+ */
+ pBssDescr->channelId = lim_get_channel_from_beacon(pMac, pBPR);
+
+ if (pBssDescr->channelId == 0) {
+ /* If the channel Id is not retrieved from Beacon, extract the channel from BD */
+ if (!rxChannel) {
+ rxChannel = pMac->lim.gLimCurrentScanChannelId;
+ }
+ pBssDescr->channelId = rxChannel;
+ }
+
+ pBssDescr->channelIdSelf = pBssDescr->channelId;
+ /* set the network type in bss description */
+ channelNum = pBssDescr->channelId;
+ pBssDescr->nwType =
+ lim_get_nw_type(pMac, channelNum, SIR_MAC_MGMT_FRAME, pBPR);
+
+ /* Copy RSSI & SINR from BD */
+
+ lim_log(pMac, LOG4, "*********BSS Description for BSSID:********* ");
+ sir_dump_buf(pMac, SIR_LIM_MODULE_ID, LOG4, pBssDescr->bssId, 6);
+ sir_dump_buf(pMac, SIR_LIM_MODULE_ID, LOG4,
+ (uint8_t *) pRxPacketInfo, 36);
+
+ pBssDescr->rssi = (int8_t) WMA_GET_RX_RSSI_DB(pRxPacketInfo);
+
+ /* SINR no longer reported by HW */
+ pBssDescr->sinr = 0;
+
+ pBssDescr->nReceivedTime = (uint32_t) cdf_mc_timer_get_system_ticks();
+ pBssDescr->tsf_delta = WMA_GET_RX_TSF_DELTA(pRxPacketInfo);
+
+ lim_log(pMac, LOG1, FL("BSSID: "MAC_ADDRESS_STR " tsf_delta = %u"),
+ MAC_ADDR_ARRAY(pHdr->bssId), pBssDescr->tsf_delta);
+
+#if defined WLAN_FEATURE_VOWIFI
+ if (fScanning) {
+ rrm_get_start_tsf(pMac, pBssDescr->startTSF);
+ pBssDescr->parentTSF = WMA_GET_RX_TIMESTAMP(pRxPacketInfo);
+ }
+#endif
+
+#ifdef WLAN_FEATURE_VOWIFI_11R
+ /* MobilityDomain */
+ pBssDescr->mdie[0] = 0;
+ pBssDescr->mdie[1] = 0;
+ pBssDescr->mdie[2] = 0;
+ pBssDescr->mdiePresent = false;
+ /* If mdie is present in the probe resp we */
+ /* fill it in the bss description */
+ if (pBPR->mdiePresent) {
+ pBssDescr->mdiePresent = true;
+ pBssDescr->mdie[0] = pBPR->mdie[0];
+ pBssDescr->mdie[1] = pBPR->mdie[1];
+ pBssDescr->mdie[2] = pBPR->mdie[2];
+ }
+#endif
+
+#ifdef FEATURE_WLAN_ESE
+ pBssDescr->QBSSLoad_present = false;
+ pBssDescr->QBSSLoad_avail = 0;
+ if (pBPR->QBSSLoad.present) {
+ pBssDescr->QBSSLoad_present = true;
+ pBssDescr->QBSSLoad_avail = pBPR->QBSSLoad.avail;
+ }
+#endif
+ /* Copy IE fields */
+ cdf_mem_copy((uint8_t *) &pBssDescr->ieFields,
+ pBody + SIR_MAC_B_PR_SSID_OFFSET, ieLen);
+
+ /*set channel number in beacon in case it is not present */
+ pBPR->channelNumber = pBssDescr->channelId;
+
+ lim_log(pMac, LOG3,
+ FL("Collected BSS Description for Channel(%1d), length(%u), IE Fields(%u)"),
+ pBssDescr->channelId, pBssDescr->length, ieLen);
+
+ return CDF_STATUS_SUCCESS;
+} /*** end lim_collect_bss_description() ***/
+
+/**
+ * lim_is_scan_requested_ssid()
+ *
+ ***FUNCTION:
+ * This function is called during scan upon receiving
+ * Beacon/Probe Response frame to check if the received
+ * SSID is present in the list of requested SSIDs in scan
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ * NA
+ *
+ ***NOTE:
+ * NA
+ *
+ * @param pMac - Pointer to Global MAC structure
+ * @param ssId - SSID Received in beacons/Probe responses that is compared against the
+ requeusted SSID in scan list
+ * ---------------------------------------------
+ *
+ * @return bool - true if SSID is present in requested list, false otherwise
+ */
+
+bool lim_is_scan_requested_ssid(tpAniSirGlobal pMac, tSirMacSSid *ssId)
+{
+ uint8_t i = 0;
+
+ for (i = 0; i < pMac->lim.gpLimMlmScanReq->numSsid; i++) {
+ if (true == cdf_mem_compare((uint8_t *) ssId,
+ (uint8_t *) &pMac->lim.
+ gpLimMlmScanReq->ssId[i],
+ (uint8_t) (pMac->lim.
+ gpLimMlmScanReq->ssId[i].
+ length + 1))) {
+ return true;
+ }
+ }
+ return false;
+}
+
+/**
+ * lim_check_and_add_bss_description()
+ * @mac_ctx: Pointer to Global MAC structure
+ * @bpr: Pointer to parsed Beacon/Probe Response structure
+ * @rx_packet_info: Pointer to Received frame's BD
+ * @scanning: bool to indicate whether the BSS is from current scan
+ * or just happens to receive a beacon
+ *
+ * FUNCTION:
+ * This function is called during scan upon receiving
+ * Beacon/Probe Response frame to check if the received
+ * frame matches scan criteria, collect BSS description
+ * and add it to cached scan results.
+ *
+ * Return: None
+ */
+
+void
+lim_check_and_add_bss_description(tpAniSirGlobal mac_ctx,
+ tpSirProbeRespBeacon bpr, uint8_t *rx_packet_info,
+ bool scanning, uint8_t fProbeRsp)
+{
+ tSirBssDescription *bssdescr = NULL;
+ uint32_t frame_len, ie_len = 0;
+ uint8_t rx_chan_in_beacon = 0;
+ CDF_STATUS status;
+ uint8_t dont_update_all = 0;
+ uint8_t rf_band = 0;
+ uint8_t rx_chan_bd = 0;
+
+ tSirMacAddr bssid_zero = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
+ tpSirMacDataHdr3a hdr;
+
+ hdr = WMA_GET_RX_MPDUHEADER3A((uint8_t *) rx_packet_info);
+
+ /* Check For Null BSSID and Skip in case of P2P */
+ if (cdf_mem_compare(bssid_zero, &hdr->addr3, 6))
+ return;
+
+ /*
+ * SSID/BSSID policy:
+ * Accept beacons/probe responses with any SSID or BSSID because
+ * multiple scan requests may be running at the same time and
+ * firmware may forward results to CLD from scans requested through a
+ * different path.
+ *
+ * CSA Policy:
+ * There is no point in caching & reporting the scan results for APs
+ * which are in the process of switching the channel. So, we are not
+ * caching the scan results for APs which are adverzing the
+ * channel-switch element in their beacons and probe responses.
+ */
+ if (bpr->channelSwitchPresent)
+ return;
+
+ /*
+ * If beacon/probe resp DS param channel does not match with
+ * RX BD channel then don't save the results. It might be a beacon
+ * from another channel heard as noise on the current scanning channel
+ */
+
+ if ((bpr->dsParamsPresent) || (bpr->HTInfo.present)) {
+ /* This means that we are in 2.4GHz mode or 5GHz 11n mode */
+ rx_chan_in_beacon = lim_get_channel_from_beacon(mac_ctx, bpr);
+ rf_band = WMA_GET_RX_RFBAND(rx_packet_info);
+ rx_chan_bd = WMA_GET_RX_CH(rx_packet_info);
+
+ if (rx_chan_bd != rx_chan_in_beacon) {
+ /* BCAST Frame, if CH do not match, Drop */
+ if (WMA_IS_RX_BCAST(rx_packet_info)) {
+ lim_log(mac_ctx, LOG3,
+ FL("Beacon/Probe Rsp dropped. Channel in BD %d. Channel in beacon %d"),
+ WMA_GET_RX_CH(rx_packet_info),
+ lim_get_channel_from_beacon(mac_ctx,
+ bpr));
+ return;
+ }
+ /* Unit cast frame, Probe RSP, do not drop */
+ else {
+ dont_update_all = 1;
+ lim_log(mac_ctx, LOG3,
+ FL("SSID %s, CH in ProbeRsp %d, CH in BD %d, mismatch, Do Not Drop"),
+ bpr->ssId.ssId, rx_chan_in_beacon,
+ WMA_GET_RX_CH(rx_packet_info));
+ WMA_GET_RX_CH(rx_packet_info) =
+ rx_chan_in_beacon;
+ }
+ }
+ }
+
+ /*
+ * Allocate buffer to hold BSS description from
+ * received Beacon frame.
+ * Include size of fixed fields and IEs length
+ */
+
+ ie_len = WMA_GET_RX_PAYLOAD_LEN(rx_packet_info);
+ if (ie_len <= SIR_MAC_B_PR_SSID_OFFSET) {
+ lim_log(mac_ctx, LOGP,
+ FL("RX packet has invalid length %d"), ie_len);
+ return;
+ }
+
+ ie_len -= SIR_MAC_B_PR_SSID_OFFSET;
+
+ /* IEs will be overlap ieFields field. Adjust the length accordingly */
+ frame_len = sizeof(*bssdescr) + ie_len - sizeof(bssdescr->ieFields[1]);
+ bssdescr = (tSirBssDescription *) cdf_mem_malloc(frame_len);
+
+ if (NULL == bssdescr) {
+ /* Log error */
+ lim_log(mac_ctx, LOGE,
+ FL("cdf_mem_malloc(length=%d) failed"), frame_len);
+ return;
+ }
+ /* In scan state, store scan result. */
+#if defined WLAN_FEATURE_VOWIFI
+ status = lim_collect_bss_description(mac_ctx, bssdescr,
+ bpr, rx_packet_info, scanning);
+ if (CDF_STATUS_SUCCESS != status)
+ goto last;
+#else
+ status = lim_collect_bss_description(mac_ctx, bssdescr,
+ bpr, rx_packet_info);
+ if (CDF_STATUS_SUCCESS != status)
+ goto last;
+#endif
+ bssdescr->fProbeRsp = fProbeRsp;
+
+ /*
+ * Send the beacon to CSR with registered callback routine.
+ * scan_id and flags parameters are currently unused and set to 0.
+ */
+ if (mac_ctx->lim.add_bssdescr_callback) {
+ (mac_ctx->lim.add_bssdescr_callback) (mac_ctx, bssdescr, 0, 0);
+ } else {
+ lim_log(mac_ctx, LOGE,
+ FL("No CSR callback routine to send beacons"));
+ status = CDF_STATUS_E_INVAL;
+ }
+last:
+ cdf_mem_free(bssdescr);
+ return;
+}
+
diff --git a/core/mac/src/pe/lim/lim_scan_result_utils.h b/core/mac/src/pe/lim/lim_scan_result_utils.h
new file mode 100644
index 0000000..c622dc2
--- /dev/null
+++ b/core/mac/src/pe/lim/lim_scan_result_utils.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2012, 2014 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_scan_result_utils.h contains the utility definitions
+ * LIM uses for maintaining and accessing scan results on STA.
+ * Author: Chandra Modumudi
+ * Date: 02/13/02
+ * History:-
+ * Date Modified by Modification Information
+ * --------------------------------------------------------------------
+ */
+#ifndef __LIM_SCAN_UTILS_H
+#define __LIM_SCAN_UTILS_H
+
+#include "parser_api.h"
+#include "lim_types.h"
+
+/* Scan result hash related functions */
+uint8_t lim_scan_hash_function(tSirMacAddr);
+void lim_restore_pre_scan_state(tpAniSirGlobal);
+void lim_copy_scan_result(tpAniSirGlobal, uint8_t *);
+void lim_check_and_add_bss_description(tpAniSirGlobal, tpSirProbeRespBeacon,
+ uint8_t *, bool, uint8_t);
+#if defined WLAN_FEATURE_VOWIFI
+CDF_STATUS lim_collect_bss_description(tpAniSirGlobal,
+ tSirBssDescription *,
+ tpSirProbeRespBeacon, uint8_t *, uint8_t);
+#else
+CDF_STATUS lim_collect_bss_description(tpAniSirGlobal,
+ tSirBssDescription *,
+ tpSirProbeRespBeacon, uint8_t *);
+#endif
+
+#endif /* __LIM_SCAN_UTILS_H */
diff --git a/core/mac/src/pe/lim/lim_security_utils.c b/core/mac/src/pe/lim/lim_security_utils.c
new file mode 100644
index 0000000..ae0a422
--- /dev/null
+++ b/core/mac/src/pe/lim/lim_security_utils.c
@@ -0,0 +1,1075 @@
+/*
+ * Copyright (c) 2013-2015 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_utils.cc contains the utility functions
+ * LIM uses.
+ * Author: Chandra Modumudi
+ * Date: 02/13/02
+ * History:-
+ * Date Modified by Modification Information
+ * --------------------------------------------------------------------
+ */
+
+#include "ani_global.h"
+#include "wni_api.h"
+
+#include "sir_common.h"
+#include "wni_cfg.h"
+#include "cfg_api.h"
+
+#include "utils_api.h"
+#include "lim_utils.h"
+#include "lim_security_utils.h"
+#ifdef WLAN_FEATURE_VOWIFI_11R
+#include "lim_ft_defs.h"
+#endif
+#include "lim_session.h"
+
+#define LIM_SEED_LENGTH 16
+/*
+ * preauth node timeout value in interval of 10msec
+ */
+#define LIM_OPENAUTH_TIMEOUT 500
+
+/**
+ * lim_is_auth_algo_supported()
+ *
+ ***FUNCTION:
+ * This function is called in various places within LIM code
+ * to determine whether passed authentication algorithm is enabled
+ * or not
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ * NA
+ *
+ ***NOTE:
+ * NA
+ *
+ * @param authType Indicates MAC based authentication type
+ * (eSIR_OPEN_SYSTEM or eSIR_SHARED_KEY)
+ * If Shared Key authentication to be used,
+ * 'Privacy Option Implemented' flag is also
+ * checked.
+ *
+ * @return true if passed authType is enabled else false
+ */
+uint8_t
+lim_is_auth_algo_supported(tpAniSirGlobal pMac, tAniAuthType authType,
+ tpPESession psessionEntry)
+{
+ uint32_t algoEnable, privacyOptImp;
+
+ if (authType == eSIR_OPEN_SYSTEM) {
+
+ if (LIM_IS_AP_ROLE(psessionEntry)) {
+ if ((psessionEntry->authType == eSIR_OPEN_SYSTEM)
+ || (psessionEntry->authType == eSIR_AUTO_SWITCH))
+ return true;
+ else
+ return false;
+ }
+
+ if (wlan_cfg_get_int(pMac, WNI_CFG_OPEN_SYSTEM_AUTH_ENABLE,
+ &algoEnable) != eSIR_SUCCESS) {
+ /**
+ * Could not get AuthAlgo1 Enable value
+ * from CFG. Log error.
+ */
+ lim_log(pMac, LOGE,
+ FL("could not retrieve AuthAlgo1 Enable value"));
+
+ return false;
+ } else
+ return ((algoEnable > 0 ? true : false));
+ } else {
+
+ if (LIM_IS_AP_ROLE(psessionEntry)) {
+ if ((psessionEntry->authType == eSIR_SHARED_KEY)
+ || (psessionEntry->authType == eSIR_AUTO_SWITCH))
+ algoEnable = true;
+ else
+ algoEnable = false;
+
+ } else
+
+ if (wlan_cfg_get_int
+ (pMac, WNI_CFG_SHARED_KEY_AUTH_ENABLE,
+ &algoEnable) != eSIR_SUCCESS) {
+ /**
+ * Could not get AuthAlgo2 Enable value
+ * from CFG. Log error.
+ */
+ lim_log(pMac, LOGE,
+ FL("could not retrieve AuthAlgo2 Enable value"));
+
+ return false;
+ }
+
+ if (LIM_IS_AP_ROLE(psessionEntry)) {
+ privacyOptImp = psessionEntry->privacy;
+ } else
+
+ if (wlan_cfg_get_int(pMac, WNI_CFG_PRIVACY_ENABLED,
+ &privacyOptImp) != eSIR_SUCCESS)
+ {
+ /**
+ * Could not get PrivacyOptionImplemented value
+ * from CFG. Log error.
+ */
+ lim_log(pMac, LOGE,
+ FL
+ ("could not retrieve PrivacyOptImplemented value"));
+
+ return false;
+ }
+ return (algoEnable && privacyOptImp);
+ }
+} /****** end lim_is_auth_algo_supported() ******/
+
+/**
+ * lim_init_pre_auth_list
+ *
+ ***FUNCTION:
+ * This function is called while starting a BSS at AP
+ * to initialize MAC authenticated STA list. This may also be called
+ * while joining/starting an IBSS if MAC authentication is allowed
+ * in IBSS mode.
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ *
+ ***NOTE:
+ *
+ * @param pMac - Pointer to Global MAC structure
+ * @return None
+ */
+
+void lim_init_pre_auth_list(tpAniSirGlobal pMac)
+{
+ pMac->lim.pLimPreAuthList = NULL;
+
+} /*** end lim_init_pre_auth_list() ***/
+
+/**
+ * lim_delete_pre_auth_list
+ *
+ ***FUNCTION:
+ * This function is called cleanup Pre-auth list either on
+ * AP or on STA when moving from one persona to other.
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ *
+ ***NOTE:
+ *
+ * @param pMac - Pointer to Global MAC structure
+ * @return None
+ */
+
+void lim_delete_pre_auth_list(tpAniSirGlobal pMac)
+{
+ struct tLimPreAuthNode *pCurrNode, *pTempNode;
+
+ pCurrNode = pTempNode = pMac->lim.pLimPreAuthList;
+ while (pCurrNode != NULL) {
+ pTempNode = pCurrNode->next;
+
+ PELOG1(lim_log(pMac, LOG1, FL("=====> lim_delete_pre_auth_list "));)
+ lim_release_pre_auth_node(pMac, pCurrNode);
+
+ pCurrNode = pTempNode;
+ }
+ pMac->lim.pLimPreAuthList = NULL;
+} /*** end lim_delete_pre_auth_list() ***/
+
+/**
+ * lim_search_pre_auth_list
+ *
+ ***FUNCTION:
+ * This function is called when Authentication frame is received
+ * by AP (or at a STA in IBSS supporting MAC based authentication)
+ * to search if a STA is in the middle of MAC Authentication
+ * transaction sequence.
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ *
+ ***NOTE:
+ *
+ * @param macAddr - MAC address of the STA that sent
+ * Authentication frame.
+ *
+ * @return Pointer to pre-auth node if found, else NULL
+ */
+
+struct tLimPreAuthNode *lim_search_pre_auth_list(tpAniSirGlobal pMac,
+ tSirMacAddr macAddr)
+{
+ struct tLimPreAuthNode *pTempNode = pMac->lim.pLimPreAuthList;
+
+ while (pTempNode != NULL) {
+ if (cdf_mem_compare((uint8_t *) macAddr,
+ (uint8_t *) &pTempNode->peerMacAddr,
+ sizeof(tSirMacAddr)))
+ break;
+
+ pTempNode = pTempNode->next;
+ }
+
+ return pTempNode;
+} /*** end lim_search_pre_auth_list() ***/
+
+/**
+ * lim_delete_open_auth_pre_auth_node() - delete any stale preauth nodes
+ * @mac_ctx: Pointer to Global MAC structure
+ *
+ * This function is called to delete any stale preauth nodes on
+ * receiving authentication frame and existing preauth nodes
+ * reached the maximum allowed limit.
+ *
+ * Return: return true if any preauthnode deleted else false
+ */
+uint8_t
+lim_delete_open_auth_pre_auth_node(tpAniSirGlobal mac_ctx)
+{
+ struct tLimPreAuthNode *prev_node, *temp_node, *found_node;
+ uint8_t auth_node_freed = false;
+
+ temp_node = prev_node = mac_ctx->lim.pLimPreAuthList;
+
+ if (temp_node == NULL)
+ return auth_node_freed;
+
+ while (temp_node != NULL) {
+ if (temp_node->mlmState == eLIM_MLM_AUTHENTICATED_STATE &&
+ temp_node->authType == eSIR_OPEN_SYSTEM &&
+ (cdf_mc_timer_get_system_ticks() >
+ (LIM_OPENAUTH_TIMEOUT + temp_node->timestamp) ||
+ cdf_mc_timer_get_system_ticks() < temp_node->timestamp)) {
+ /* Found node to be deleted */
+ auth_node_freed = true;
+ found_node = temp_node;
+ if (mac_ctx->lim.pLimPreAuthList == temp_node) {
+ prev_node = mac_ctx->lim.pLimPreAuthList =
+ temp_node = found_node->next;
+ } else {
+ prev_node->next = temp_node->next;
+ temp_node = prev_node->next;
+ }
+
+ lim_release_pre_auth_node(mac_ctx, found_node);
+ } else {
+ prev_node = temp_node;
+ temp_node = prev_node->next;
+ }
+ }
+
+ return auth_node_freed;
+}
+
+/**
+ * lim_add_pre_auth_node
+ *
+ ***FUNCTION:
+ * This function is called at AP while sending Authentication
+ * frame2.
+ * This may also be called on a STA in IBSS if MAC authentication is
+ * allowed in IBSS mode.
+ *
+ ***LOGIC:
+ * Node is always added to the front of the list
+ *
+ ***ASSUMPTIONS:
+ *
+ ***NOTE:
+ *
+ * @param pMac - Pointer to Global MAC structure
+ * @param pAuthNode - Pointer to pre-auth node to be added to the list.
+ *
+ * @return None
+ */
+
+void lim_add_pre_auth_node(tpAniSirGlobal pMac, struct tLimPreAuthNode *pAuthNode)
+{
+ pMac->lim.gLimNumPreAuthContexts++;
+
+ pAuthNode->next = pMac->lim.pLimPreAuthList;
+
+ pMac->lim.pLimPreAuthList = pAuthNode;
+} /*** end lim_add_pre_auth_node() ***/
+
+/**
+ * lim_release_pre_auth_node
+ *
+ ***FUNCTION:
+ * This function is called to realease the accquired
+ * pre auth node from list.
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ *
+ ***NOTE:
+ *
+ * @param pMac - Pointer to Global MAC structure
+ * @param pAuthNode - Pointer to Pre Auth node to be released
+ * @return None
+ */
+
+void lim_release_pre_auth_node(tpAniSirGlobal pMac, tpLimPreAuthNode pAuthNode)
+{
+ pAuthNode->fFree = 1;
+ MTRACE(mac_trace
+ (pMac, TRACE_CODE_TIMER_DEACTIVATE, NO_SESSION,
+ eLIM_PRE_AUTH_CLEANUP_TIMER));
+ tx_timer_deactivate(&pAuthNode->timer);
+ pMac->lim.gLimNumPreAuthContexts--;
+} /*** end lim_release_pre_auth_node() ***/
+
+/**
+ * lim_delete_pre_auth_node
+ *
+ ***FUNCTION:
+ * This function is called at AP when a pre-authenticated STA is
+ * Associated/Reassociated or when AuthFrame4 is received after
+ * Auth Response timeout.
+ * This may also be called on a STA in IBSS if MAC authentication and
+ * Association/Reassociation is allowed in IBSS mode.
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ *
+ ***NOTE:
+ *
+ * @param pMac - Pointer to Global MAC structure
+ * @param peerMacAddr - MAC address of the STA that need to be deleted
+ * from pre-auth node list.
+ *
+ * @return None
+ */
+
+void lim_delete_pre_auth_node(tpAniSirGlobal pMac, tSirMacAddr macAddr)
+{
+ struct tLimPreAuthNode *pPrevNode, *pTempNode;
+
+ pTempNode = pPrevNode = pMac->lim.pLimPreAuthList;
+
+ if (pTempNode == NULL)
+ return;
+
+ if (cdf_mem_compare((uint8_t *) macAddr,
+ (uint8_t *) &pTempNode->peerMacAddr,
+ sizeof(tSirMacAddr))) {
+ /* First node to be deleted */
+
+ pMac->lim.pLimPreAuthList = pTempNode->next;
+
+ PELOG1(lim_log
+ (pMac, LOG1,
+ FL
+ ("=====> lim_delete_pre_auth_node : first node to delete"));
+ )
+ PELOG1(lim_log
+ (pMac, LOG1,
+ FL("Release data entry: %x id %d peer "), pTempNode,
+ pTempNode->authNodeIdx);
+ lim_print_mac_addr(pMac, macAddr, LOG1);
+ )
+ lim_release_pre_auth_node(pMac, pTempNode);
+
+ return;
+ }
+
+ pTempNode = pTempNode->next;
+
+ while (pTempNode != NULL) {
+ if (cdf_mem_compare((uint8_t *) macAddr,
+ (uint8_t *) &pTempNode->peerMacAddr,
+ sizeof(tSirMacAddr))) {
+ /* Found node to be deleted */
+
+ pPrevNode->next = pTempNode->next;
+
+ PELOG1(lim_log
+ (pMac, LOG1,
+ FL
+ ("=====> lim_delete_pre_auth_node : subsequent node to delete"));
+ lim_log(pMac, LOG1,
+ FL("Release data entry: %x id %d peer "),
+ pTempNode, pTempNode->authNodeIdx);
+ lim_print_mac_addr(pMac, macAddr, LOG1);
+ )
+ lim_release_pre_auth_node(pMac, pTempNode);
+
+ return;
+ }
+
+ pPrevNode = pTempNode;
+ pTempNode = pTempNode->next;
+ }
+
+ /* Should not be here */
+ /* Log error */
+ lim_log(pMac, LOGP, FL("peer not found in pre-auth list, addr= "));
+ lim_print_mac_addr(pMac, macAddr, LOGP);
+
+} /*** end lim_delete_pre_auth_node() ***/
+
+/**
+ * limRestoreFromPreAuthState
+ *
+ ***FUNCTION:
+ * This function is called on STA whenever an Authentication
+ * sequence is complete and state prior to auth need to be
+ * restored.
+ *
+ ***LOGIC:
+ * MLM_AUTH_CNF is prepared and sent to SME state machine.
+ * In case of restoring from pre-auth:
+ * - Channel Id is programmed at LO/RF synthesizer
+ * - BSSID is programmed at RHP
+ *
+ ***ASSUMPTIONS:
+ *
+ ***NOTE:
+ *
+ * @param pMac - Pointer to Global MAC structure
+ * @param resultCode - result of authentication attempt
+ * @return None
+ */
+
+void
+lim_restore_from_auth_state(tpAniSirGlobal pMac, tSirResultCodes resultCode,
+ uint16_t protStatusCode, tpPESession sessionEntry)
+{
+ tSirMacAddr currentBssId;
+ tLimMlmAuthCnf mlmAuthCnf;
+
+#ifdef FEATURE_WLAN_DIAG_SUPPORT
+ lim_diag_event_report(pMac, WLAN_PE_DIAG_AUTH_COMP_EVENT, sessionEntry,
+ resultCode, protStatusCode);
+#endif
+
+ cdf_mem_copy((uint8_t *) &mlmAuthCnf.peerMacAddr,
+ (uint8_t *) &pMac->lim.gpLimMlmAuthReq->peerMacAddr,
+ sizeof(tSirMacAddr));
+ mlmAuthCnf.authType = pMac->lim.gpLimMlmAuthReq->authType;
+ mlmAuthCnf.resultCode = resultCode;
+ mlmAuthCnf.protStatusCode = protStatusCode;
+
+ /* Update PE session ID */
+ mlmAuthCnf.sessionId = sessionEntry->peSessionId;
+
+ /* / Free up buffer allocated */
+ /* / for pMac->lim.gLimMlmAuthReq */
+ cdf_mem_free(pMac->lim.gpLimMlmAuthReq);
+ pMac->lim.gpLimMlmAuthReq = NULL;
+
+ sessionEntry->limMlmState = sessionEntry->limPrevMlmState;
+
+ MTRACE(mac_trace
+ (pMac, TRACE_CODE_MLM_STATE, sessionEntry->peSessionId,
+ sessionEntry->limMlmState));
+
+ /* 'Change' timer for future activations */
+ lim_deactivate_and_change_timer(pMac, eLIM_AUTH_FAIL_TIMER);
+
+ sir_copy_mac_addr(currentBssId, sessionEntry->bssId);
+
+ if (sessionEntry->limSmeState == eLIM_SME_WT_PRE_AUTH_STATE) {
+ pMac->lim.gLimPreAuthChannelNumber = 0;
+ }
+
+ lim_post_sme_message(pMac, LIM_MLM_AUTH_CNF, (uint32_t *) &mlmAuthCnf);
+} /*** end lim_restore_from_auth_state() ***/
+
+/**
+ * lim_encrypt_auth_frame()
+ *
+ ***FUNCTION:
+ * This function is called in lim_process_auth_frame() function
+ * to encrypt Authentication frame3 body.
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ * NA
+ *
+ ***NOTE:
+ * NA
+ *
+ * @param pMac Pointer to Global MAC structure
+ * @param keyId key id to used
+ * @param pKey Pointer to the key to be used for encryption
+ * @param pPlainText Pointer to the body to be encrypted
+ * @param pEncrBody Pointer to the encrypted auth frame body
+ * @param keyLength 8 (WEP40) or 16 (WEP104)
+ * @return None
+ */
+
+void
+lim_encrypt_auth_frame(tpAniSirGlobal pMac, uint8_t keyId, uint8_t *pKey,
+ uint8_t *pPlainText, uint8_t *pEncrBody,
+ uint32_t keyLength)
+{
+ uint8_t seed[LIM_SEED_LENGTH], icv[SIR_MAC_WEP_ICV_LENGTH];
+
+ keyLength += 3;
+
+ /* Bytes 3-7 of seed is key */
+ cdf_mem_copy((uint8_t *) &seed[3], pKey, keyLength - 3);
+
+ /* Compute CRC-32 and place them in last 4 bytes of plain text */
+ lim_compute_crc32(icv, pPlainText, sizeof(tSirMacAuthFrameBody));
+
+ cdf_mem_copy(pPlainText + sizeof(tSirMacAuthFrameBody),
+ icv, SIR_MAC_WEP_ICV_LENGTH);
+
+ /* Run RC4 on plain text with the seed */
+ lim_rc4(pEncrBody + SIR_MAC_WEP_IV_LENGTH,
+ (uint8_t *) pPlainText, seed, keyLength,
+ LIM_ENCR_AUTH_BODY_LEN - SIR_MAC_WEP_IV_LENGTH);
+
+ /* Prepare IV */
+ pEncrBody[0] = seed[0];
+ pEncrBody[1] = seed[1];
+ pEncrBody[2] = seed[2];
+ pEncrBody[3] = keyId << 6;
+} /****** end lim_encrypt_auth_frame() ******/
+
+/**
+ * lim_compute_crc32()
+ *
+ ***FUNCTION:
+ * This function is called to compute CRC-32 on a given source.
+ * Used while encrypting/decrypting Authentication frame 3.
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ * NA
+ *
+ ***NOTE:
+ * NA
+ *
+ * @param pDest Destination location for computed CRC
+ * @param pSrc Source location to be CRC computed
+ * @param len Length over which CRC to be computed
+ * @return None
+ */
+
+void lim_compute_crc32(uint8_t *pDest, uint8_t *pSrc, uint8_t len)
+{
+ uint32_t crc;
+ int i;
+
+ crc = 0;
+ crc = ~crc;
+
+ while (len-- > 0)
+ crc = lim_crc_update(crc, *pSrc++);
+
+ crc = ~crc;
+
+ for (i = 0; i < SIR_MAC_WEP_IV_LENGTH; i++) {
+ pDest[i] = (uint8_t) crc;
+ crc >>= 8;
+ }
+} /****** end lim_compute_crc32() ******/
+
+/**
+ * lim_rc4()
+ *
+ ***FUNCTION:
+ * This function is called to run RC4 algorithm. Called while
+ * encrypting/decrypting Authentication frame 3.
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ * NA
+ *
+ ***NOTE:
+ * NA
+ *
+ * @param pDest Destination location for encrypted text
+ * @param pSrc Source location to be encrypted
+ * @param seed Contains seed (IV + key) for PRNG
+ * @param keyLength 8 (WEP40) or 16 (WEP104)
+ * @param frameLen Length of the frame
+ *
+ * @return None
+ */
+
+void
+lim_rc4(uint8_t *pDest, uint8_t *pSrc, uint8_t *seed, uint32_t keyLength,
+ uint16_t frameLen)
+{
+ typedef struct {
+ uint8_t i, j;
+ uint8_t sbox[256];
+ } tRC4Context;
+
+ tRC4Context ctx;
+
+ {
+ uint16_t i, j, k;
+
+ /* */
+ /* Initialize sbox using seed */
+ /* */
+
+ ctx.i = ctx.j = 0;
+ for (i = 0; i < 256; i++)
+ ctx.sbox[i] = (uint8_t) i;
+
+ j = 0;
+ k = 0;
+ for (i = 0; i < 256; i++) {
+ uint8_t temp;
+ if (k < LIM_SEED_LENGTH)
+ j = (uint8_t) (j + ctx.sbox[i] + seed[k]);
+ temp = ctx.sbox[i];
+ ctx.sbox[i] = ctx.sbox[j];
+ ctx.sbox[j] = temp;
+
+ if (++k >= keyLength)
+ k = 0;
+ }
+ }
+
+ {
+ uint8_t i = ctx.i;
+ uint8_t j = ctx.j;
+ uint8_t len = (uint8_t) frameLen;
+
+ while (len-- > 0) {
+ uint8_t temp1, temp2;
+
+ i = (uint8_t) (i + 1);
+ temp1 = ctx.sbox[i];
+ j = (uint8_t) (j + temp1);
+
+ ctx.sbox[i] = temp2 = ctx.sbox[j];
+ ctx.sbox[j] = temp1;
+
+ temp1 = (uint8_t) (temp1 + temp2);
+ temp1 = ctx.sbox[temp1];
+ temp2 = (uint8_t) (pSrc ? *pSrc++ : 0);
+
+ *pDest++ = (uint8_t) (temp1 ^ temp2);
+ }
+
+ ctx.i = i;
+ ctx.j = j;
+ }
+} /****** end lim_rc4() ******/
+
+/**
+ * lim_decrypt_auth_frame()
+ *
+ ***FUNCTION:
+ * This function is called in lim_process_auth_frame() function
+ * to decrypt received Authentication frame3 body.
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ * NA
+ *
+ ***NOTE:
+ * NA
+ *
+ * @param pMac Pointer to Global MAC structure
+ * @param pKey Pointer to the key to be used for decryption
+ * @param pEncrBody Pointer to the body to be decrypted
+ * @param pPlainBody Pointer to the decrypted body
+ * @param keyLength 8 (WEP40) or 16 (WEP104)
+ *
+ * @return Decrypt result - eSIR_SUCCESS for success and
+ * LIM_DECRYPT_ICV_FAIL for ICV mismatch.
+ * If decryption is a success, pBody will
+ * have decrypted auth frame body.
+ */
+
+uint8_t
+lim_decrypt_auth_frame(tpAniSirGlobal pMac, uint8_t *pKey, uint8_t *pEncrBody,
+ uint8_t *pPlainBody, uint32_t keyLength, uint16_t frameLen)
+{
+ uint8_t seed[LIM_SEED_LENGTH], icv[SIR_MAC_WEP_ICV_LENGTH];
+ int i;
+ keyLength += 3;
+
+ /* Bytes 0-2 of seed is received IV */
+ cdf_mem_copy((uint8_t *) seed, pEncrBody, SIR_MAC_WEP_IV_LENGTH - 1);
+
+ /* Bytes 3-7 of seed is key */
+ cdf_mem_copy((uint8_t *) &seed[3], pKey, keyLength - 3);
+
+ /* Run RC4 on encrypted text with the seed */
+ lim_rc4(pPlainBody,
+ pEncrBody + SIR_MAC_WEP_IV_LENGTH, seed, keyLength, frameLen);
+
+ PELOG4(lim_log(pMac, LOG4, FL("plainbody is "));
+ sir_dump_buf(pMac, SIR_LIM_MODULE_ID, LOG4, pPlainBody, frameLen);
+ )
+ /* Compute CRC-32 and place them in last 4 bytes of encrypted body */
+ lim_compute_crc32(icv,
+ (uint8_t *) pPlainBody,
+ (uint8_t) (frameLen - SIR_MAC_WEP_ICV_LENGTH));
+
+ /* Compare RX_ICV with computed ICV */
+ for (i = 0; i < SIR_MAC_WEP_ICV_LENGTH; i++) {
+ PELOG4(lim_log
+ (pMac, LOG4, FL(" computed ICV%d[%x], rxed ICV%d[%x]"),
+ i, icv[i], i,
+ pPlainBody[frameLen - SIR_MAC_WEP_ICV_LENGTH + i]);
+ )
+ if (icv[i] !=
+ pPlainBody[frameLen - SIR_MAC_WEP_ICV_LENGTH + i])
+ return LIM_DECRYPT_ICV_FAIL;
+ }
+
+ return eSIR_SUCCESS;
+} /****** end lim_decrypt_auth_frame() ******/
+
+/**
+ * lim_post_sme_set_keys_cnf
+ *
+ * A utility API to send MLM_SETKEYS_CNF to SME
+ */
+void lim_post_sme_set_keys_cnf(tpAniSirGlobal pMac,
+ tLimMlmSetKeysReq *pMlmSetKeysReq,
+ tLimMlmSetKeysCnf *mlmSetKeysCnf)
+{
+ /* Prepare and Send LIM_MLM_SETKEYS_CNF */
+ cdf_mem_copy((uint8_t *) &mlmSetKeysCnf->peerMacAddr,
+ (uint8_t *) pMlmSetKeysReq->peerMacAddr,
+ sizeof(tSirMacAddr));
+
+ cdf_mem_copy((uint8_t *) &mlmSetKeysCnf->peerMacAddr,
+ (uint8_t *) pMlmSetKeysReq->peerMacAddr,
+ sizeof(tSirMacAddr));
+
+ /* / Free up buffer allocated for mlmSetKeysReq */
+ cdf_mem_free(pMlmSetKeysReq);
+ pMac->lim.gpLimMlmSetKeysReq = NULL;
+
+ lim_post_sme_message(pMac,
+ LIM_MLM_SETKEYS_CNF, (uint32_t *) mlmSetKeysCnf);
+}
+
+/**
+ * lim_send_set_bss_key_req()
+ *
+ ***FUNCTION:
+ * This function is called from lim_process_mlm_set_keys_req(),
+ * when PE is trying to setup the Group Keys related
+ * to a specified encryption type
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ * NA
+ *
+ ***NOTE:
+ * NA
+ *
+ * @param pMac Pointer to Global MAC structure
+ * @param pMlmSetKeysReq Pointer to MLM_SETKEYS_REQ buffer
+ * @return none
+ */
+void lim_send_set_bss_key_req(tpAniSirGlobal pMac,
+ tLimMlmSetKeysReq *pMlmSetKeysReq,
+ tpPESession psessionEntry)
+{
+ tSirMsgQ msgQ;
+ tpSetBssKeyParams pSetBssKeyParams = NULL;
+ tLimMlmSetKeysCnf mlmSetKeysCnf;
+ tSirRetStatus retCode;
+ uint32_t val = 0;
+
+ if (pMlmSetKeysReq->numKeys > SIR_MAC_MAX_NUM_OF_DEFAULT_KEYS) {
+ lim_log(pMac, LOG1,
+ FL
+ ("numKeys = %d is more than SIR_MAC_MAX_NUM_OF_DEFAULT_KEYS"),
+ pMlmSetKeysReq->numKeys);
+
+ /* Respond to SME with error code */
+ mlmSetKeysCnf.resultCode = eSIR_SME_INVALID_PARAMETERS;
+ goto end;
+ }
+ /* Package WMA_SET_BSSKEY_REQ message parameters */
+
+ pSetBssKeyParams = cdf_mem_malloc(sizeof(tSetBssKeyParams));
+ if (NULL == pSetBssKeyParams) {
+ lim_log(pMac, LOGE,
+ FL("Unable to allocate memory during SET_BSSKEY"));
+
+ /* Respond to SME with error code */
+ mlmSetKeysCnf.resultCode = eSIR_SME_RESOURCES_UNAVAILABLE;
+ goto end;
+ } else
+ cdf_mem_set((void *)pSetBssKeyParams,
+ sizeof(tSetBssKeyParams), 0);
+
+ /* Update the WMA_SET_BSSKEY_REQ parameters */
+ pSetBssKeyParams->bssIdx = psessionEntry->bssIdx;
+ pSetBssKeyParams->encType = pMlmSetKeysReq->edType;
+
+ if (eSIR_SUCCESS != wlan_cfg_get_int(pMac, WNI_CFG_SINGLE_TID_RC, &val)) {
+ lim_log(pMac, LOGP, FL("Unable to read WNI_CFG_SINGLE_TID_RC"));
+ }
+
+ pSetBssKeyParams->singleTidRc = (uint8_t) val;
+
+ /* Update PE session Id */
+ pSetBssKeyParams->sessionId = psessionEntry->peSessionId;
+
+ pSetBssKeyParams->smesessionId = pMlmSetKeysReq->smesessionId;
+
+ if (pMlmSetKeysReq->key[0].keyId &&
+ ((pMlmSetKeysReq->edType == eSIR_ED_WEP40) ||
+ (pMlmSetKeysReq->edType == eSIR_ED_WEP104))
+ ) {
+ /* IF the key id is non-zero and encryption type is WEP, Send all the 4
+ * keys to HAL with filling the key at right index in pSetBssKeyParams->key. */
+ pSetBssKeyParams->numKeys = SIR_MAC_MAX_NUM_OF_DEFAULT_KEYS;
+ cdf_mem_copy((uint8_t *) &pSetBssKeyParams->
+ key[pMlmSetKeysReq->key[0].keyId],
+ (uint8_t *) &pMlmSetKeysReq->key[0],
+ sizeof(pMlmSetKeysReq->key[0]));
+
+ } else {
+ pSetBssKeyParams->numKeys = pMlmSetKeysReq->numKeys;
+ cdf_mem_copy((uint8_t *) &pSetBssKeyParams->key,
+ (uint8_t *) &pMlmSetKeysReq->key,
+ sizeof(tSirKeys) * pMlmSetKeysReq->numKeys);
+ }
+
+ SET_LIM_PROCESS_DEFD_MESGS(pMac, false);
+ msgQ.type = WMA_SET_BSSKEY_REQ;
+ msgQ.reserved = 0;
+ msgQ.bodyptr = pSetBssKeyParams;
+ msgQ.bodyval = 0;
+
+ lim_log(pMac, LOGW, FL("Sending WMA_SET_BSSKEY_REQ..."));
+ MTRACE(mac_trace_msg_tx(pMac, psessionEntry->peSessionId, msgQ.type));
+ if (eSIR_SUCCESS != (retCode = wma_post_ctrl_msg(pMac, &msgQ))) {
+ lim_log(pMac, LOGE,
+ FL("Posting SET_BSSKEY to HAL failed, reason=%X"),
+ retCode);
+
+ /* Respond to SME with LIM_MLM_SETKEYS_CNF */
+ mlmSetKeysCnf.resultCode = eSIR_SME_HAL_SEND_MESSAGE_FAIL;
+ } else
+ return; /* Continue after WMA_SET_BSSKEY_RSP... */
+
+end:
+ lim_post_sme_set_keys_cnf(pMac, pMlmSetKeysReq, &mlmSetKeysCnf);
+
+}
+
+/**
+ * @function : lim_send_set_sta_key_req()
+ *
+ * @brief : This function is called from lim_process_mlm_set_keys_req(),
+ * when PE is trying to setup the Unicast Keys related
+ * to a specified STA with specified encryption type
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ * NA
+ *
+ ***NOTE:
+ * NA
+ *
+ * @param pMac Pointer to Global MAC structure
+ * @param pMlmSetKeysReq Pointer to MLM_SETKEYS_REQ buffer
+ * @param staIdx STA index for which the keys are being set
+ * @param defWEPIdx The default WEP key index [0..3]
+ * @return none
+ */
+void lim_send_set_sta_key_req(tpAniSirGlobal pMac,
+ tLimMlmSetKeysReq *pMlmSetKeysReq,
+ uint16_t staIdx,
+ uint8_t defWEPIdx,
+ tpPESession sessionEntry, bool sendRsp)
+{
+ tSirMsgQ msgQ;
+ tpSetStaKeyParams pSetStaKeyParams = NULL;
+ tLimMlmSetKeysCnf mlmSetKeysCnf;
+ tSirRetStatus retCode;
+ uint32_t val = 0;
+
+ /* Package WMA_SET_STAKEY_REQ message parameters */
+ pSetStaKeyParams = cdf_mem_malloc(sizeof(tSetStaKeyParams));
+ if (NULL == pSetStaKeyParams) {
+ lim_log(pMac, LOGP,
+ FL("Unable to allocate memory during SET_BSSKEY"));
+ return;
+ } else
+ cdf_mem_set((void *)pSetStaKeyParams, sizeof(tSetStaKeyParams),
+ 0);
+
+ /* Update the WMA_SET_STAKEY_REQ parameters */
+ pSetStaKeyParams->staIdx = staIdx;
+ pSetStaKeyParams->encType = pMlmSetKeysReq->edType;
+
+ if (eSIR_SUCCESS != wlan_cfg_get_int(pMac, WNI_CFG_SINGLE_TID_RC, &val)) {
+ lim_log(pMac, LOGP, FL("Unable to read WNI_CFG_SINGLE_TID_RC"));
+ }
+
+ pSetStaKeyParams->singleTidRc = (uint8_t) val;
+
+ /* Update PE session ID */
+ pSetStaKeyParams->sessionId = sessionEntry->peSessionId;
+
+ /**
+ * For WEP - defWEPIdx indicates the default WEP
+ * Key to be used for TX
+ * For all others, there's just one key that can
+ * be used and hence it is assumed that
+ * defWEPIdx = 0 (from the caller)
+ */
+
+ pSetStaKeyParams->defWEPIdx = defWEPIdx;
+
+ pSetStaKeyParams->smesessionId = pMlmSetKeysReq->smesessionId;
+ cdf_mem_copy(pSetStaKeyParams->peerMacAddr,
+ pMlmSetKeysReq->peerMacAddr, sizeof(tSirMacAddr));
+
+ if (sendRsp == true) {
+ /** Store the Previous MlmState*/
+ sessionEntry->limPrevMlmState = sessionEntry->limMlmState;
+ SET_LIM_PROCESS_DEFD_MESGS(pMac, false);
+ }
+
+ if (LIM_IS_IBSS_ROLE(sessionEntry)
+ && !pMlmSetKeysReq->key[0].unicast) {
+ if (sendRsp == true)
+ sessionEntry->limMlmState =
+ eLIM_MLM_WT_SET_STA_BCASTKEY_STATE;
+ msgQ.type = WMA_SET_STA_BCASTKEY_REQ;
+ } else {
+ if (sendRsp == true)
+ sessionEntry->limMlmState =
+ eLIM_MLM_WT_SET_STA_KEY_STATE;
+ msgQ.type = WMA_SET_STAKEY_REQ;
+ }
+ MTRACE(mac_trace
+ (pMac, TRACE_CODE_MLM_STATE, sessionEntry->peSessionId,
+ sessionEntry->limMlmState));
+
+ /**
+ * In the Case of WEP_DYNAMIC, ED_TKIP and ED_CCMP
+ * the Key[0] contains the KEY, so just copy that alone,
+ * for the case of WEP_STATIC the hal gets the key from cfg
+ */
+ switch (pMlmSetKeysReq->edType) {
+ case eSIR_ED_WEP40:
+ case eSIR_ED_WEP104:
+ /* FIXME! Is this OK? */
+ if (0 == pMlmSetKeysReq->numKeys) {
+ uint32_t i;
+
+ for (i = 0; i < SIR_MAC_MAX_NUM_OF_DEFAULT_KEYS; i++) {
+ cdf_mem_copy((uint8_t *) &pSetStaKeyParams->
+ key[i],
+ (uint8_t *) &pMlmSetKeysReq->
+ key[i], sizeof(tSirKeys));
+ }
+ pSetStaKeyParams->wepType = eSIR_WEP_STATIC;
+ sessionEntry->limMlmState =
+ eLIM_MLM_WT_SET_STA_KEY_STATE;
+ MTRACE(mac_trace
+ (pMac, TRACE_CODE_MLM_STATE,
+ sessionEntry->peSessionId,
+ sessionEntry->limMlmState));
+ } else {
+ /*This case the keys are coming from upper layer so need to fill the
+ * key at the default wep key index and send to the HAL */
+ if (defWEPIdx < SIR_MAC_MAX_NUM_OF_DEFAULT_KEYS) {
+ cdf_mem_copy((uint8_t *) &pSetStaKeyParams->
+ key[defWEPIdx],
+ (uint8_t *) &pMlmSetKeysReq->
+ key[0],
+ sizeof(pMlmSetKeysReq->key[0]));
+ pMlmSetKeysReq->numKeys =
+ SIR_MAC_MAX_NUM_OF_DEFAULT_KEYS;
+ } else {
+ lim_log(pMac, LOGE, FL("Wrong Key Index %d"),
+ defWEPIdx);
+ cdf_mem_free(pSetStaKeyParams);
+ return;
+ }
+ }
+ break;
+ case eSIR_ED_TKIP:
+ case eSIR_ED_CCMP:
+#ifdef FEATURE_WLAN_WAPI
+ case eSIR_ED_WPI:
+#endif
+ {
+ cdf_mem_copy((uint8_t *) &pSetStaKeyParams->key,
+ (uint8_t *) &pMlmSetKeysReq->key[0],
+ sizeof(tSirKeys));
+ }
+ break;
+ default:
+ break;
+ }
+
+ pSetStaKeyParams->sendRsp = sendRsp;
+
+ msgQ.reserved = 0;
+ msgQ.bodyptr = pSetStaKeyParams;
+ msgQ.bodyval = 0;
+
+ lim_log(pMac, LOG1, FL("Sending WMA_SET_STAKEY_REQ..."));
+ MTRACE(mac_trace_msg_tx(pMac, sessionEntry->peSessionId, msgQ.type));
+ if (eSIR_SUCCESS != (retCode = wma_post_ctrl_msg(pMac, &msgQ))) {
+ lim_log(pMac, LOGE,
+ FL("Posting SET_STAKEY to HAL failed, reason=%X"),
+ retCode);
+ /* Respond to SME with LIM_MLM_SETKEYS_CNF */
+ mlmSetKeysCnf.resultCode = eSIR_SME_HAL_SEND_MESSAGE_FAIL;
+ } else
+ return; /* Continue after WMA_SET_STAKEY_RSP... */
+
+ if (sendRsp == true)
+ lim_post_sme_set_keys_cnf(pMac, pMlmSetKeysReq, &mlmSetKeysCnf);
+}
diff --git a/core/mac/src/pe/lim/lim_security_utils.h b/core/mac/src/pe/lim/lim_security_utils.h
new file mode 100644
index 0000000..c5b30ba
--- /dev/null
+++ b/core/mac/src/pe/lim/lim_security_utils.h
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2011-2015 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_security_utils.h contains the utility definitions
+ * related to WEP encryption/decryption etc.
+ * Author: Chandra Modumudi
+ * Date: 02/13/02
+ * History:-
+ * Date Modified by Modification Information
+ * --------------------------------------------------------------------
+ */
+#ifndef __LIM_SECURITY_UTILS_H
+#define __LIM_SECURITY_UTILS_H
+#include "sir_mac_prot_def.h" /* for tSirMacAuthFrameBody */
+
+#define LIM_ENCR_AUTH_BODY_LEN (sizeof(tSirMacAuthFrameBody) + \
+ SIR_MAC_WEP_IV_LENGTH + \
+ SIR_MAC_WEP_ICV_LENGTH)
+struct tLimPreAuthNode;
+
+uint8_t lim_is_auth_algo_supported(tpAniSirGlobal, tAniAuthType, tpPESession);
+
+/* MAC based authentication related functions */
+void lim_init_pre_auth_list(tpAniSirGlobal);
+void lim_delete_pre_auth_list(tpAniSirGlobal);
+struct tLimPreAuthNode *lim_search_pre_auth_list(tpAniSirGlobal, tSirMacAddr);
+void lim_add_pre_auth_node(tpAniSirGlobal, struct tLimPreAuthNode *);
+void lim_delete_pre_auth_node(tpAniSirGlobal, tSirMacAddr);
+void lim_release_pre_auth_node(tpAniSirGlobal pMac, tpLimPreAuthNode pAuthNode);
+void lim_restore_from_auth_state(tpAniSirGlobal,
+ tSirResultCodes, uint16_t, tpPESession);
+uint8_t lim_delete_open_auth_pre_auth_node(tpAniSirGlobal mac_ctx);
+
+/* Encryption/Decryption related functions */
+void lim_compute_crc32(uint8_t *, uint8_t *, uint8_t);
+void lim_rc4(uint8_t *, uint8_t *, uint8_t *, uint32_t, uint16_t);
+void lim_encrypt_auth_frame(tpAniSirGlobal, uint8_t, uint8_t *, uint8_t *,
+ uint8_t *, uint32_t);
+uint8_t lim_decrypt_auth_frame(tpAniSirGlobal, uint8_t *, uint8_t *, uint8_t *,
+ uint32_t, uint16_t);
+
+void lim_send_set_bss_key_req(tpAniSirGlobal, tLimMlmSetKeysReq *, tpPESession);
+void lim_send_set_sta_key_req(tpAniSirGlobal, tLimMlmSetKeysReq *, uint16_t, uint8_t,
+ tpPESession, bool sendRsp);
+void lim_post_sme_set_keys_cnf(tpAniSirGlobal, tLimMlmSetKeysReq *,
+ tLimMlmSetKeysCnf *);
+
+#define PTAPS 0xedb88320
+
+static inline uint32_t lim_crc_update(uint32_t crc, uint8_t x)
+{
+
+ /* Update CRC computation for 8 bits contained in x */
+ /* */
+ uint32_t z;
+ uint32_t fb;
+ int i;
+
+ z = crc ^ x;
+ for (i = 0; i < 8; i++) {
+ fb = z & 1;
+ z >>= 1;
+ if (fb)
+ z ^= PTAPS;
+ }
+ return z;
+}
+
+#endif /* __LIM_SECURITY_UTILS_H */
diff --git a/core/mac/src/pe/lim/lim_send_management_frames.c b/core/mac/src/pe/lim/lim_send_management_frames.c
new file mode 100644
index 0000000..c7f4220
--- /dev/null
+++ b/core/mac/src/pe/lim/lim_send_management_frames.c
@@ -0,0 +1,5130 @@
+/*
+ * Copyright (c) 2011-2015 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.
+ */
+
+/**
+ * \file lim_send_management_frames.c
+ *
+ * \brief Code for preparing and sending 802.11 Management frames
+ *
+ *
+ */
+
+#include "sir_api.h"
+#include "ani_global.h"
+#include "sir_mac_prot_def.h"
+#include "cfg_api.h"
+#include "utils_api.h"
+#include "lim_types.h"
+#include "lim_utils.h"
+#include "lim_security_utils.h"
+#include "lim_prop_exts_utils.h"
+#include "dot11f.h"
+#include "lim_sta_hash_api.h"
+#include "sch_api.h"
+#include "lim_send_messages.h"
+#include "lim_assoc_utils.h"
+#include "lim_ft.h"
+#ifdef WLAN_FEATURE_11W
+#include "wni_cfg.h"
+#endif
+
+#ifdef WLAN_FEATURE_VOWIFI_11R
+#include "lim_ft_defs.h"
+#endif
+#include "lim_session.h"
+#include "cdf_types.h"
+#include "cdf_trace.h"
+#include "cds_utils.h"
+#include "sme_trace.h"
+#if defined WLAN_FEATURE_VOWIFI
+#include "rrm_api.h"
+#endif
+
+#include "wma_types.h"
+
+/**
+ *
+ * \brief This function is called to add the sequence number to the
+ * management frames
+ *
+ * \param pMac Pointer to Global MAC structure
+ *
+ * \param pMacHdr Pointer to MAC management header
+ *
+ * The pMacHdr argument points to the MAC management header. The
+ * sequence number stored in the pMac structure will be incremented
+ * and updated to the MAC management header. The start sequence
+ * number is WLAN_HOST_SEQ_NUM_MIN and the end value is
+ * WLAN_HOST_SEQ_NUM_MAX. After reaching the MAX value, the sequence
+ * number will roll over.
+ *
+ */
+void lim_add_mgmt_seq_num(tpAniSirGlobal pMac, tpSirMacMgmtHdr pMacHdr)
+{
+ if (pMac->mgmtSeqNum >= WLAN_HOST_SEQ_NUM_MAX) {
+ pMac->mgmtSeqNum = WLAN_HOST_SEQ_NUM_MIN - 1;
+ }
+
+ pMac->mgmtSeqNum++;
+
+ pMacHdr->seqControl.seqNumLo = (pMac->mgmtSeqNum & LOW_SEQ_NUM_MASK);
+ pMacHdr->seqControl.seqNumHi =
+ ((pMac->mgmtSeqNum & HIGH_SEQ_NUM_MASK) >> HIGH_SEQ_NUM_OFFSET);
+}
+
+/**
+ *
+ * \brief This function is called before sending a p2p action frame
+ * inorder to add sequence numbers to action packets
+ *
+ * \param pMac Pointer to Global MAC structure
+ *
+ * \param pBD Pointer to the frame buffer that needs to be populate
+ *
+ * The pMacHdr argument points to the MAC management header. The
+ * sequence number stored in the pMac structure will be incremented
+ * and updated to the MAC management header. The start sequence
+ * number is WLAN_HOST_SEQ_NUM_MIN and the end value is
+ * WLAN_HOST_SEQ_NUM_MAX. After reaching the MAX value, the sequence
+ * number will roll over.
+ *
+ */
+void lim_populate_p2p_mac_header(tpAniSirGlobal pMac, uint8_t *pBD)
+{
+ tpSirMacMgmtHdr pMacHdr;
+
+ /* / Prepare MAC management header */
+ pMacHdr = (tpSirMacMgmtHdr) (pBD);
+
+ /* Prepare sequence number */
+ lim_add_mgmt_seq_num(pMac, pMacHdr);
+ lim_log(pMac, LOG1, "seqNumLo=%d, seqNumHi=%d, mgmtSeqNum=%d",
+ pMacHdr->seqControl.seqNumLo,
+ pMacHdr->seqControl.seqNumHi, pMac->mgmtSeqNum);
+}
+
+/**
+ * lim_populate_mac_header() - Fill in 802.11 header of frame
+ *
+ * @mac_ctx: Pointer to Global MAC structure
+ * @buf: Pointer to the frame buffer that needs to be populate
+ * @type: 802.11 Type of the frame
+ * @sub_type: 802.11 Subtype of the frame
+ * @peer_addr: dst address
+ * @self_mac_addr: local mac address
+ *
+ * This function is called by various LIM modules to prepare the
+ * 802.11 frame MAC header
+ *
+ * The buf argument points to the beginning of the frame buffer to
+ * which - a) The 802.11 MAC header is set b) Following this MAC header
+ * will be the MGMT frame payload The payload itself is populated by the
+ * caller API
+ *
+ * Return: None
+ */
+
+void lim_populate_mac_header(tpAniSirGlobal mac_ctx, uint8_t *buf,
+ uint8_t type, uint8_t sub_type, tSirMacAddr peer_addr,
+ tSirMacAddr self_mac_addr)
+{
+ tpSirMacMgmtHdr mac_hdr;
+
+ /* Prepare MAC management header */
+ mac_hdr = (tpSirMacMgmtHdr) (buf);
+
+ /* Prepare FC */
+ mac_hdr->fc.protVer = SIR_MAC_PROTOCOL_VERSION;
+ mac_hdr->fc.type = type;
+ mac_hdr->fc.subType = sub_type;
+
+ /* Prepare Address 1 */
+ cdf_mem_copy((uint8_t *) mac_hdr->da,
+ (uint8_t *) peer_addr, sizeof(tSirMacAddr));
+
+ /* Prepare Address 2 */
+ sir_copy_mac_addr(mac_hdr->sa, self_mac_addr);
+
+ /* Prepare Address 3 */
+ cdf_mem_copy((uint8_t *) mac_hdr->bssId,
+ (uint8_t *) peer_addr, sizeof(tSirMacAddr));
+
+ /* Prepare sequence number */
+ lim_add_mgmt_seq_num(mac_ctx, mac_hdr);
+ lim_log(mac_ctx, LOG1, "seqNumLo=%d, seqNumHi=%d, mgmtSeqNum=%d",
+ mac_hdr->seqControl.seqNumLo,
+ mac_hdr->seqControl.seqNumHi, mac_ctx->mgmtSeqNum);
+}
+
+/**
+ * lim_send_probe_req_mgmt_frame() - send probe request management frame
+ * @mac_ctx: Pointer to Global MAC structure
+ * @ssid: SSID to be sent in Probe Request frame
+ * @bssid: BSSID to be sent in Probe Request frame
+ * @channel: Channel # on which the Probe Request is going out
+ * @self_macaddr: self MAC address
+ * @dot11mode: self dotllmode
+ * @additional_ielen: if non-zero, include additional_ie in the Probe Request
+ * frame
+ * @additional_ie: if additional_ielen is non zero, include this field in the
+ * Probe Request frame
+ *
+ * This function is called by various LIM modules to send Probe Request frame
+ * during active scan/learn phase.
+ * Probe request is sent out in the following scenarios:
+ * --heartbeat failure: session needed
+ * --join req: session needed
+ * --foreground scan: no session
+ * --background scan: no session
+ * --sch_beacon_processing: to get EDCA parameters: session needed
+ *
+ * Return: tSirRetStatus (eSIR_SUCCESS on success and error codes otherwise)
+ */
+tSirRetStatus
+lim_send_probe_req_mgmt_frame(tpAniSirGlobal mac_ctx,
+ tSirMacSSid *ssid,
+ tSirMacAddr bssid,
+ uint8_t channel,
+ tSirMacAddr self_macaddr,
+ uint32_t dot11mode,
+ uint32_t additional_ielen, uint8_t *additional_ie)
+{
+ tDot11fProbeRequest pr;
+ uint32_t status, bytes, payload;
+ uint8_t *frame;
+ void *packet;
+ CDF_STATUS cdf_status, extcap_status;
+ tpPESession pesession;
+ uint8_t sessionid;
+ uint8_t *p2pie = NULL;
+ uint8_t txflag = 0;
+ uint8_t sme_sessionid = 0;
+ bool is_vht_enabled = false;
+ uint8_t txPower;
+ uint16_t addn_ielen = additional_ielen;
+
+ /* The probe req should not send 11ac capabilieties if band is 2.4GHz,
+ * unless enableVhtFor24GHz is enabled in INI. So if enableVhtFor24GHz
+ * is false and dot11mode is 11ac set it to 11n.
+ */
+ if (channel <= SIR_11B_CHANNEL_END &&
+ (false == mac_ctx->roam.configParam.enableVhtFor24GHz) &&
+ (WNI_CFG_DOT11_MODE_11AC == dot11mode ||
+ WNI_CFG_DOT11_MODE_11AC_ONLY == dot11mode))
+ dot11mode = WNI_CFG_DOT11_MODE_11N;
+ /*
+ * session context may or may not be present, when probe request needs
+ * to be sent out. Following cases exist:
+ * --heartbeat failure: session needed
+ * --join req: session needed
+ * --foreground scan: no session
+ * --background scan: no session
+ * --sch_beacon_processing: to get EDCA parameters: session needed
+ * If session context does not exist, some IEs will be populated from
+ * CFGs, e.g. Supported and Extended rate set IEs
+ */
+ pesession = pe_find_session_by_bssid(mac_ctx, bssid, &sessionid);
+
+ if (pesession != NULL)
+ sme_sessionid = pesession->smeSessionId;
+
+ /* The scheme here is to fill out a 'tDot11fProbeRequest' structure */
+ /* and then hand it off to 'dot11f_pack_probe_request' (for */
+ /* serialization). We start by zero-initializing the structure: */
+ cdf_mem_set((uint8_t *) &pr, sizeof(pr), 0);
+
+ /* & delegating to assorted helpers: */
+ populate_dot11f_ssid(mac_ctx, ssid, &pr.SSID);
+
+ if (addn_ielen && additional_ie)
+ p2pie = limGetP2pIEPtr(mac_ctx, additional_ie, addn_ielen);
+
+ /*
+ * Don't include 11b rate if it is a P2P serach or probe request is
+ * sent by P2P Client
+ */
+ if ((WNI_CFG_DOT11_MODE_11B != dot11mode) && (p2pie != NULL) &&
+ (((mac_ctx->lim.gpLimMlmScanReq != NULL) &&
+ mac_ctx->lim.gpLimMlmScanReq->p2pSearch) ||
+ ((pesession != NULL) &&
+ (CDF_P2P_CLIENT_MODE == pesession->pePersona))
+ )
+ ) {
+ /*
+ * In the below API pass channel number > 14, do that it fills
+ * only 11a rates in supported rates
+ */
+ populate_dot11f_supp_rates(mac_ctx, 15, &pr.SuppRates,
+ pesession);
+ } else {
+ populate_dot11f_supp_rates(mac_ctx, channel,
+ &pr.SuppRates, pesession);
+
+ if (WNI_CFG_DOT11_MODE_11B != dot11mode) {
+ populate_dot11f_ext_supp_rates1(mac_ctx, channel,
+ &pr.ExtSuppRates);
+ }
+ }
+
+#if defined WLAN_FEATURE_VOWIFI
+ /*
+ * Table 7-14 in IEEE Std. 802.11k-2008 says
+ * DS params "can" be present in RRM is disabled and "is" present if
+ * RRM is enabled. It should be ok even if we add it into probe req when
+ * RRM is not enabled.
+ */
+ populate_dot11f_ds_params(mac_ctx, &pr.DSParams, channel);
+ /* Call RRM module to get the tx power for management used. */
+ txPower = (uint8_t) rrm_get_mgmt_tx_power(mac_ctx, pesession);
+ populate_dot11f_wfatpc(mac_ctx, &pr.WFATPC, txPower, 0);
+
+#endif
+
+ if (pesession != NULL) {
+ pesession->htCapability = IS_DOT11_MODE_HT(dot11mode);
+ /* Include HT Capability IE */
+ if (pesession->htCapability)
+ populate_dot11f_ht_caps(mac_ctx, pesession, &pr.HTCaps);
+ } else { /* pesession == NULL */
+ if (IS_DOT11_MODE_HT(dot11mode))
+ populate_dot11f_ht_caps(mac_ctx, NULL, &pr.HTCaps);
+ }
+
+ /*
+ * Set channelbonding information as "disabled" when tunned to a
+ * 2.4 GHz channel
+ */
+ if (channel <= SIR_11B_CHANNEL_END) {
+ if (mac_ctx->roam.configParam.channelBondingMode24GHz
+ == PHY_SINGLE_CHANNEL_CENTERED) {
+ pr.HTCaps.supportedChannelWidthSet =
+ eHT_CHANNEL_WIDTH_20MHZ;
+ pr.HTCaps.shortGI40MHz = 0;
+ } else {
+ pr.HTCaps.supportedChannelWidthSet =
+ eHT_CHANNEL_WIDTH_40MHZ;
+ }
+ }
+#ifdef WLAN_FEATURE_11AC
+ if (pesession != NULL) {
+ pesession->vhtCapability = IS_DOT11_MODE_VHT(dot11mode);
+ /* Include VHT Capability IE */
+ if (pesession->vhtCapability) {
+ populate_dot11f_vht_caps(mac_ctx, pesession,
+ &pr.VHTCaps);
+ is_vht_enabled = true;
+ }
+ } else {
+ if (IS_DOT11_MODE_VHT(dot11mode)) {
+ populate_dot11f_vht_caps(mac_ctx, pesession,
+ &pr.VHTCaps);
+ is_vht_enabled = true;
+ }
+ }
+#endif
+ if (pesession != NULL)
+ populate_dot11f_ext_cap(mac_ctx, is_vht_enabled, &pr.ExtCap,
+ pesession);
+
+ /* That's it-- now we pack it. First, how much space are we going to */
+ status = dot11f_get_packed_probe_request_size(mac_ctx, &pr, &payload);
+ if (DOT11F_FAILED(status)) {
+ lim_log(mac_ctx, LOGP, FL("Failed to calculate the packed size for a Probe Request (0x%08x)."), status);
+ /* We'll fall back on the worst case scenario: */
+ payload = sizeof(tDot11fProbeRequest);
+ } else if (DOT11F_WARNED(status)) {
+ lim_log(mac_ctx, LOGW,
+ FL("There were warnings while calculating the packed size for a Probe Request (0x%08x)."), status);
+ }
+
+ /* Strip extended capability IE (if present). FW will add that IE */
+ if (addn_ielen) {
+ extcap_status = lim_strip_extcap_ie(mac_ctx, additional_ie,
+ &addn_ielen, NULL);
+ if (CDF_STATUS_SUCCESS != extcap_status)
+ lim_log(mac_ctx, LOGE,
+ FL("Error:%d stripping extcap IE"), extcap_status);
+ }
+
+ bytes = payload + sizeof(tSirMacMgmtHdr) + addn_ielen;
+
+ /* Ok-- try to allocate some memory: */
+ cdf_status = cds_packet_alloc((uint16_t) bytes, (void **)&frame,
+ (void **)&packet);
+ if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
+ lim_log(mac_ctx, LOGP, FL("Failed to allocate %d bytes for a Probe Request."), bytes);
+ return eSIR_MEM_ALLOC_FAILED;
+ }
+ /* Paranoia: */
+ cdf_mem_set(frame, bytes, 0);
+
+ /* Next, we fill out the buffer descriptor: */
+ lim_populate_mac_header(mac_ctx, frame, SIR_MAC_MGMT_FRAME,
+ SIR_MAC_MGMT_PROBE_REQ, bssid, self_macaddr);
+
+ /* That done, pack the Probe Request: */
+ status = dot11f_pack_probe_request(mac_ctx, &pr, frame +
+ sizeof(tSirMacMgmtHdr),
+ payload, &payload);
+ if (DOT11F_FAILED(status)) {
+ lim_log(mac_ctx, LOGE,
+ FL("Failed to pack a Probe Request (0x%08x)."), status);
+ cds_packet_free((void *)packet);
+ return eSIR_FAILURE; /* allocated! */
+ } else if (DOT11F_WARNED(status)) {
+ lim_log(mac_ctx, LOGW, FL("There were warnings while packing a Probe Request (0x%08x)."), status);
+ }
+ /* Append any AddIE if present. */
+ if (addn_ielen) {
+ cdf_mem_copy(frame + sizeof(tSirMacMgmtHdr) + payload,
+ additional_ie, addn_ielen);
+ payload += addn_ielen;
+ }
+
+ /* If this probe request is sent during P2P Search State, then we need
+ * to send it at OFDM rate.
+ */
+ if ((SIR_BAND_5_GHZ == lim_get_rf_band(channel))
+ || ((mac_ctx->lim.gpLimMlmScanReq != NULL) &&
+ mac_ctx->lim.gpLimMlmScanReq->p2pSearch)
+ /*
+ * For unicast probe req mgmt from Join function we don't set
+ * above variables. So we need to add one more check whether it
+ * is pePersona is P2P_CLIENT or not
+ */
+ || ((pesession != NULL) &&
+ (CDF_P2P_CLIENT_MODE == pesession->pePersona))
+ ) {
+ txflag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME;
+ }
+
+ cdf_status =
+ wma_tx_frame(mac_ctx, packet,
+ (uint16_t) sizeof(tSirMacMgmtHdr) + payload,
+ TXRX_FRM_802_11_MGMT, ANI_TXDIR_TODS, 7,
+ lim_tx_complete, frame, txflag, sme_sessionid,
+ 0);
+ if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
+ lim_log(mac_ctx, LOGE,
+ FL("could not send Probe Request frame!"));
+ /* Pkt will be freed up by the callback */
+ return eSIR_FAILURE;
+ }
+
+ return eSIR_SUCCESS;
+} /* End lim_send_probe_req_mgmt_frame. */
+
+tSirRetStatus lim_get_addn_ie_for_probe_resp(tpAniSirGlobal pMac,
+ uint8_t *addIE, uint16_t *addnIELen,
+ uint8_t probeReqP2pIe)
+{
+ /* If Probe request doesn't have P2P IE, then take out P2P IE
+ from additional IE */
+ if (!probeReqP2pIe) {
+ uint8_t *tempbuf = NULL;
+ uint16_t tempLen = 0;
+ int left = *addnIELen;
+ uint8_t *ptr = addIE;
+ uint8_t elem_id, elem_len;
+
+ if (NULL == addIE) {
+ PELOGE(lim_log(pMac, LOGE, FL(" NULL addIE pointer"));)
+ return eSIR_FAILURE;
+ }
+
+ tempbuf = cdf_mem_malloc(left);
+ if (NULL == tempbuf) {
+ PELOGE(lim_log(pMac, LOGE,
+ FL
+ ("Unable to allocate memory to store addn IE"));
+ )
+ return eSIR_MEM_ALLOC_FAILED;
+ }
+
+ while (left >= 2) {
+ elem_id = ptr[0];
+ elem_len = ptr[1];
+ left -= 2;
+ if (elem_len > left) {
+ lim_log(pMac, LOGE,
+ FL
+ ("****Invalid IEs eid = %d elem_len=%d left=%d*****"),
+ elem_id, elem_len, left);
+ cdf_mem_free(tempbuf);
+ return eSIR_FAILURE;
+ }
+ if (!((SIR_MAC_EID_VENDOR == elem_id) &&
+ (memcmp
+ (&ptr[2], SIR_MAC_P2P_OUI,
+ SIR_MAC_P2P_OUI_SIZE) == 0))) {
+ cdf_mem_copy(tempbuf + tempLen, &ptr[0],
+ elem_len + 2);
+ tempLen += (elem_len + 2);
+ }
+ left -= elem_len;
+ ptr += (elem_len + 2);
+ }
+ cdf_mem_copy(addIE, tempbuf, tempLen);
+ *addnIELen = tempLen;
+ cdf_mem_free(tempbuf);
+ }
+ return eSIR_SUCCESS;
+}
+
+/**
+ * lim_send_probe_rsp_mgmt_frame() - Send probe response
+ *
+ * @mac_ctx: Handle for mac context
+ * @peer_macaddr: Mac address of requesting peer
+ * @ssid: SSID for response
+ * @n_staid: Station ID, currently unused.
+ * @pe_session: PE session id
+ * @keepalive: Keep alive flag. Currently unused.
+ * @preq_p2pie: P2P IE in incoming probe request
+ *
+ * Builds and sends probe response frame to the requesting peer
+ *
+ * Return: void
+ */
+
+void
+lim_send_probe_rsp_mgmt_frame(tpAniSirGlobal mac_ctx,
+ tSirMacAddr peer_macaddr,
+ tpAniSSID ssid,
+ short n_staid,
+ uint8_t keepalive,
+ tpPESession pe_session, uint8_t preq_p2pie)
+{
+ tDot11fProbeResponse *frm;
+ tSirRetStatus sir_status;
+ uint32_t cfg, payload, bytes, status;
+ tpSirMacMgmtHdr mac_hdr;
+ uint8_t *frame;
+ void *packet;
+ CDF_STATUS cdf_status;
+ uint32_t addn_ie_present = false;
+
+ uint16_t addn_ie_len = 0;
+ uint32_t wps_ap = 0, tmp;
+ uint8_t tx_flag = 0;
+ uint8_t *add_ie = NULL;
+ uint8_t *p2p_ie = NULL;
+ uint8_t noalen = 0;
+ uint8_t total_noalen = 0;
+ uint8_t noa_stream[SIR_MAX_NOA_ATTR_LEN + SIR_P2P_IE_HEADER_LEN];
+ uint8_t noa_ie[SIR_MAX_NOA_ATTR_LEN + SIR_P2P_IE_HEADER_LEN];
+ uint8_t sme_sessionid = 0;
+ bool is_vht_enabled = false;
+ tDot11fIEExtCap extracted_ext_cap;
+ bool extracted_ext_cap_flag = true;
+
+ /* We don't answer requests in this case*/
+ if (ANI_DRIVER_TYPE(mac_ctx) == eDRIVER_TYPE_MFG)
+ return;
+
+ if (NULL == pe_session)
+ return;
+
+ /*
+ * In case when cac timer is running for this SAP session then
+ * avoid sending probe rsp out. It is violation of dfs specification.
+ */
+ if (((pe_session->pePersona == CDF_SAP_MODE) ||
+ (pe_session->pePersona == CDF_P2P_GO_MODE)) &&
+ (true == mac_ctx->sap.SapDfsInfo.is_dfs_cac_timer_running)) {
+ CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO,
+ FL("CAC timer is running, probe response dropped"));
+ return;
+ }
+ sme_sessionid = pe_session->smeSessionId;
+ frm = cdf_mem_malloc(sizeof(tDot11fProbeResponse));
+ if (NULL == frm) {
+ lim_log(mac_ctx, LOGE,
+ FL("Unable to allocate memory"));
+ return;
+ }
+
+ cdf_mem_zero(&extracted_ext_cap, sizeof(extracted_ext_cap));
+
+ /*
+ * Fill out 'frm', after which we'll just hand the struct off to
+ * 'dot11f_pack_probe_response'.
+ */
+ cdf_mem_set((uint8_t *) frm, sizeof(tDot11fProbeResponse), 0);
+
+ /*
+ * Timestamp to be updated by TFP, below.
+ *
+ * Beacon Interval:
+ */
+ if (LIM_IS_AP_ROLE(pe_session)) {
+ frm->BeaconInterval.interval =
+ mac_ctx->sch.schObject.gSchBeaconInterval;
+ } else {
+ sir_status = wlan_cfg_get_int(mac_ctx,
+ WNI_CFG_BEACON_INTERVAL, &cfg);
+ if (eSIR_SUCCESS != sir_status) {
+ lim_log(mac_ctx, LOGP,
+ FL("Failed to get WNI_CFG_BEACON_INTERVAL (%d)."),
+ sir_status);
+ goto err_ret;
+ }
+ frm->BeaconInterval.interval = (uint16_t) cfg;
+ }
+
+ populate_dot11f_capabilities(mac_ctx, &frm->Capabilities, pe_session);
+ populate_dot11f_ssid(mac_ctx, (tSirMacSSid *) ssid, &frm->SSID);
+ populate_dot11f_supp_rates(mac_ctx, POPULATE_DOT11F_RATES_OPERATIONAL,
+ &frm->SuppRates, pe_session);
+
+ populate_dot11f_ds_params(mac_ctx, &frm->DSParams,
+ pe_session->currentOperChannel);
+ populate_dot11f_ibss_params(mac_ctx, &frm->IBSSParams, pe_session);
+
+ if (LIM_IS_AP_ROLE(pe_session)) {
+ if (pe_session->wps_state != SAP_WPS_DISABLED)
+ populate_dot11f_probe_res_wpsi_es(mac_ctx,
+ &frm->WscProbeRes,
+ pe_session);
+ } else {
+ if (wlan_cfg_get_int(mac_ctx, (uint16_t) WNI_CFG_WPS_ENABLE,
+ &tmp) != eSIR_SUCCESS)
+ lim_log(mac_ctx, LOGP, "Failed to cfg get id %d",
+ WNI_CFG_WPS_ENABLE);
+
+ wps_ap = tmp & WNI_CFG_WPS_ENABLE_AP;
+
+ if (wps_ap)
+ populate_dot11f_wsc_in_probe_res(mac_ctx,
+ &frm->WscProbeRes);
+
+ if (mac_ctx->lim.wscIeInfo.probeRespWscEnrollmentState ==
+ eLIM_WSC_ENROLL_BEGIN) {
+ populate_dot11f_wsc_registrar_info_in_probe_res(mac_ctx,
+ &frm->WscProbeRes);
+ mac_ctx->lim.wscIeInfo.probeRespWscEnrollmentState =
+ eLIM_WSC_ENROLL_IN_PROGRESS;
+ }
+
+ if (mac_ctx->lim.wscIeInfo.wscEnrollmentState ==
+ eLIM_WSC_ENROLL_END) {
+ de_populate_dot11f_wsc_registrar_info_in_probe_res(
+ mac_ctx, &frm->WscProbeRes);
+ mac_ctx->lim.wscIeInfo.probeRespWscEnrollmentState =
+ eLIM_WSC_ENROLL_NOOP;
+ }
+ }
+
+ populate_dot11f_country(mac_ctx, &frm->Country, pe_session);
+ populate_dot11f_edca_param_set(mac_ctx, &frm->EDCAParamSet, pe_session);
+
+ if (pe_session->dot11mode != WNI_CFG_DOT11_MODE_11B)
+ populate_dot11f_erp_info(mac_ctx, &frm->ERPInfo, pe_session);
+
+ populate_dot11f_ext_supp_rates(mac_ctx,
+ POPULATE_DOT11F_RATES_OPERATIONAL,
+ &frm->ExtSuppRates, pe_session);
+
+ /* Populate HT IEs, when operating in 11n */
+ if (pe_session->htCapability) {
+ populate_dot11f_ht_caps(mac_ctx, pe_session, &frm->HTCaps);
+ populate_dot11f_ht_info(mac_ctx, &frm->HTInfo, pe_session);
+ }
+#ifdef WLAN_FEATURE_11AC
+ if (pe_session->vhtCapability) {
+ lim_log(mac_ctx, LOG1, FL("Populate VHT IE in Probe Response"));
+ populate_dot11f_vht_caps(mac_ctx, pe_session, &frm->VHTCaps);
+ populate_dot11f_vht_operation(mac_ctx, pe_session,
+ &frm->VHTOperation);
+ /*
+ * we do not support multi users yet.
+ * populate_dot11f_vht_ext_bss_load( mac_ctx,
+ * &frm.VHTExtBssLoad );
+ */
+ is_vht_enabled = true;
+ }
+#endif
+
+ populate_dot11f_ext_cap(mac_ctx, is_vht_enabled, &frm->ExtCap,
+ pe_session);
+
+ if (pe_session->pLimStartBssReq) {
+ populate_dot11f_wpa(mac_ctx,
+ &(pe_session->pLimStartBssReq->rsnIE),
+ &frm->WPA);
+ populate_dot11f_rsn_opaque(mac_ctx,
+ &(pe_session->pLimStartBssReq->rsnIE),
+ &frm->RSNOpaque);
+ }
+
+ populate_dot11f_wmm(mac_ctx, &frm->WMMInfoAp, &frm->WMMParams,
+ &frm->WMMCaps, pe_session);
+
+#if defined(FEATURE_WLAN_WAPI)
+ if (pe_session->pLimStartBssReq)
+ populate_dot11f_wapi(mac_ctx,
+ &(pe_session->pLimStartBssReq->rsnIE),
+ &frm->WAPI);
+#endif /* defined(FEATURE_WLAN_WAPI) */
+
+ status = dot11f_get_packed_probe_response_size(mac_ctx, frm, &payload);
+ if (DOT11F_FAILED(status)) {
+ lim_log(mac_ctx, LOGP,
+ FL("Probe Response size error (0x%08x)."),
+ status);
+ /* We'll fall back on the worst case scenario: */
+ payload = sizeof(tDot11fProbeResponse);
+ } else if (DOT11F_WARNED(status)) {
+ lim_log(mac_ctx, LOGW,
+ FL("Probe Response size warning (0x%08x)."),
+ status);
+ }
+
+ bytes = payload + sizeof(tSirMacMgmtHdr);
+
+ if (mac_ctx->lim.gpLimRemainOnChanReq)
+ bytes += (mac_ctx->lim.gpLimRemainOnChanReq->length -
+ sizeof(tSirRemainOnChnReq));
+ else
+ /*
+ * Only use CFG for non-listen mode. This CFG is not working for
+ * concurrency. In listening mode, probe rsp IEs is passed in
+ * the message from SME to PE.
+ */
+ addn_ie_present =
+ (pe_session->addIeParams.probeRespDataLen != 0);
+
+ if (addn_ie_present) {
+
+ add_ie = cdf_mem_malloc(
+ pe_session->addIeParams.probeRespDataLen);
+ if (NULL == add_ie) {
+ lim_log(mac_ctx, LOGE,
+ FL("add_ie allocation failed"));
+ goto err_ret;
+ }
+
+ cdf_mem_copy(add_ie,
+ pe_session->addIeParams.probeRespData_buff,
+ pe_session->addIeParams.probeRespDataLen);
+ addn_ie_len = pe_session->addIeParams.probeRespDataLen;
+
+ if (eSIR_SUCCESS != lim_get_addn_ie_for_probe_resp(mac_ctx,
+ add_ie, &addn_ie_len, preq_p2pie)) {
+ lim_log(mac_ctx, LOGP,
+ FL("Unable to get addn_ie"));
+ goto err_ret;
+ }
+
+ sir_status = lim_strip_extcap_update_struct(mac_ctx,
+ add_ie, &addn_ie_len,
+ &extracted_ext_cap);
+ if (eSIR_SUCCESS != sir_status) {
+ extracted_ext_cap_flag = false;
+ lim_log(mac_ctx, LOG1,
+ FL("Unable to strip off ExtCap IE"));
+ }
+
+ bytes = bytes + addn_ie_len;
+
+ if (preq_p2pie)
+ p2p_ie = limGetP2pIEPtr(mac_ctx, &add_ie[0],
+ addn_ie_len);
+
+ if (p2p_ie != NULL) {
+ /* get NoA attribute stream P2P IE */
+ noalen = lim_get_noa_attr_stream(mac_ctx,
+ noa_stream, pe_session);
+ if (noalen != 0) {
+ total_noalen =
+ lim_build_p2p_ie(mac_ctx, &noa_ie[0],
+ &noa_stream[0], noalen);
+ bytes = bytes + total_noalen;
+ }
+ }
+ }
+
+ cdf_status = cds_packet_alloc((uint16_t) bytes, (void **)&frame,
+ (void **)&packet);
+ if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
+ lim_log(mac_ctx, LOGP, FL("Probe Response allocation failed"));
+ goto err_ret;
+ }
+ /* Paranoia: */
+ cdf_mem_set(frame, bytes, 0);
+
+ /* Next, we fill out the buffer descriptor: */
+ lim_populate_mac_header(mac_ctx, frame, SIR_MAC_MGMT_FRAME,
+ SIR_MAC_MGMT_PROBE_RSP, peer_macaddr,
+ pe_session->selfMacAddr);
+
+ mac_hdr = (tpSirMacMgmtHdr) frame;
+
+ sir_copy_mac_addr(mac_hdr->bssId, pe_session->bssId);
+
+ /* merge ExtCap IE */
+ if (extracted_ext_cap_flag)
+ lim_merge_extcap_struct(&frm->ExtCap, &extracted_ext_cap);
+
+ /* That done, pack the Probe Response: */
+ status =
+ dot11f_pack_probe_response(mac_ctx, frm,
+ frame + sizeof(tSirMacMgmtHdr),
+ payload, &payload);
+ if (DOT11F_FAILED(status)) {
+ lim_log(mac_ctx, LOGE,
+ FL("Probe Response pack failure (0x%08x)."),
+ status);
+ goto err_ret;
+ } else if (DOT11F_WARNED(status)) {
+ lim_log(mac_ctx, LOGW,
+ FL("Probe Response pack warning (0x%08x)."),
+ status);
+ }
+
+ lim_log(mac_ctx, LOG3, FL("Sending Probe Response frame to "));
+ lim_print_mac_addr(mac_ctx, peer_macaddr, LOG3);
+
+ mac_ctx->sys.probeRespond++;
+
+ if (mac_ctx->lim.gpLimRemainOnChanReq)
+ cdf_mem_copy(frame + sizeof(tSirMacMgmtHdr) + payload,
+ mac_ctx->lim.gpLimRemainOnChanReq->probeRspIe,
+ (mac_ctx->lim.gpLimRemainOnChanReq->length -
+ sizeof(tSirRemainOnChnReq)));
+
+ if (addn_ie_present)
+ cdf_mem_copy(frame + sizeof(tSirMacMgmtHdr) + payload,
+ &add_ie[0], addn_ie_len);
+
+ if (noalen != 0) {
+ if (total_noalen >
+ (SIR_MAX_NOA_ATTR_LEN + SIR_P2P_IE_HEADER_LEN)) {
+ lim_log(mac_ctx, LOGE,
+ FL("Not able to insert NoA, total len=%d"),
+ total_noalen);
+ goto err_ret;
+ } else {
+ cdf_mem_copy(&frame[bytes - (total_noalen)],
+ &noa_ie[0], total_noalen);
+ }
+ }
+
+ if ((SIR_BAND_5_GHZ == lim_get_rf_band(pe_session->currentOperChannel))
+ || (pe_session->pePersona == CDF_P2P_CLIENT_MODE) ||
+ (pe_session->pePersona == CDF_P2P_GO_MODE)
+ )
+ tx_flag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME;
+
+ /* Queue Probe Response frame in high priority WQ */
+ cdf_status = wma_tx_frame((tHalHandle) mac_ctx, packet,
+ (uint16_t) bytes,
+ TXRX_FRM_802_11_MGMT,
+ ANI_TXDIR_TODS,
+ 7, lim_tx_complete, frame, tx_flag,
+ sme_sessionid, 0);
+
+ /* Pkt will be freed up by the callback */
+ if (!CDF_IS_STATUS_SUCCESS(cdf_status))
+ lim_log(mac_ctx, LOGE, FL("Could not send Probe Response."));
+
+ if (add_ie != NULL)
+ cdf_mem_free(add_ie);
+
+ cdf_mem_free(frm);
+ return;
+
+err_ret:
+ if (add_ie != NULL)
+ cdf_mem_free(add_ie);
+ if (frm != NULL)
+ cdf_mem_free(frm);
+ if (packet != NULL)
+ cds_packet_free((void *)packet);
+ return;
+
+} /* End lim_send_probe_rsp_mgmt_frame. */
+
+void
+lim_send_addts_req_action_frame(tpAniSirGlobal pMac,
+ tSirMacAddr peerMacAddr,
+ tSirAddtsReqInfo *pAddTS, tpPESession psessionEntry)
+{
+ uint16_t i;
+ uint8_t *pFrame;
+ tDot11fAddTSRequest AddTSReq;
+ tDot11fWMMAddTSRequest WMMAddTSReq;
+ uint32_t nPayload, nBytes, nStatus;
+ tpSirMacMgmtHdr pMacHdr;
+ void *pPacket;
+#ifdef FEATURE_WLAN_ESE
+ uint32_t phyMode;
+#endif
+ CDF_STATUS cdf_status;
+ uint8_t txFlag = 0;
+ uint8_t smeSessionId = 0;
+
+ if (NULL == psessionEntry) {
+ return;
+ }
+
+ smeSessionId = psessionEntry->smeSessionId;
+
+ if (!pAddTS->wmeTspecPresent) {
+ cdf_mem_set((uint8_t *) &AddTSReq, sizeof(AddTSReq), 0);
+
+ AddTSReq.Action.action = SIR_MAC_QOS_ADD_TS_REQ;
+ AddTSReq.DialogToken.token = pAddTS->dialogToken;
+ AddTSReq.Category.category = SIR_MAC_ACTION_QOS_MGMT;
+ if (pAddTS->lleTspecPresent) {
+ populate_dot11f_tspec(&pAddTS->tspec, &AddTSReq.TSPEC);
+ } else {
+ populate_dot11f_wmmtspec(&pAddTS->tspec,
+ &AddTSReq.WMMTSPEC);
+ }
+
+ if (pAddTS->lleTspecPresent) {
+ AddTSReq.num_WMMTCLAS = 0;
+ AddTSReq.num_TCLAS = pAddTS->numTclas;
+ for (i = 0; i < pAddTS->numTclas; ++i) {
+ populate_dot11f_tclas(pMac, &pAddTS->tclasInfo[i],
+ &AddTSReq.TCLAS[i]);
+ }
+ } else {
+ AddTSReq.num_TCLAS = 0;
+ AddTSReq.num_WMMTCLAS = pAddTS->numTclas;
+ for (i = 0; i < pAddTS->numTclas; ++i) {
+ populate_dot11f_wmmtclas(pMac,
+ &pAddTS->tclasInfo[i],
+ &AddTSReq.WMMTCLAS[i]);
+ }
+ }
+
+ if (pAddTS->tclasProcPresent) {
+ if (pAddTS->lleTspecPresent) {
+ AddTSReq.TCLASSPROC.processing =
+ pAddTS->tclasProc;
+ AddTSReq.TCLASSPROC.present = 1;
+ } else {
+ AddTSReq.WMMTCLASPROC.version = 1;
+ AddTSReq.WMMTCLASPROC.processing =
+ pAddTS->tclasProc;
+ AddTSReq.WMMTCLASPROC.present = 1;
+ }
+ }
+
+ nStatus =
+ dot11f_get_packed_add_ts_request_size(pMac, &AddTSReq, &nPayload);
+ if (DOT11F_FAILED(nStatus)) {
+ lim_log(pMac, LOGP,
+ FL("Failed to calculate the packed size f"
+ "or an Add TS Request (0x%08x)."), nStatus);
+ /* We'll fall back on the worst case scenario: */
+ nPayload = sizeof(tDot11fAddTSRequest);
+ } else if (DOT11F_WARNED(nStatus)) {
+ lim_log(pMac, LOGW,
+ FL("There were warnings while calculating"
+ "the packed size for an Add TS Request"
+ " (0x%08x)."), nStatus);
+ }
+ } else {
+ cdf_mem_set((uint8_t *) &WMMAddTSReq, sizeof(WMMAddTSReq), 0);
+
+ WMMAddTSReq.Action.action = SIR_MAC_QOS_ADD_TS_REQ;
+ WMMAddTSReq.DialogToken.token = pAddTS->dialogToken;
+ WMMAddTSReq.Category.category = SIR_MAC_ACTION_WME;
+
+ /* WMM spec 2.2.10 - status code is only filled in for ADDTS response */
+ WMMAddTSReq.StatusCode.statusCode = 0;
+
+ populate_dot11f_wmmtspec(&pAddTS->tspec, &WMMAddTSReq.WMMTSPEC);
+#ifdef FEATURE_WLAN_ESE
+ lim_get_phy_mode(pMac, &phyMode, psessionEntry);
+
+ if (phyMode == WNI_CFG_PHY_MODE_11G
+ || phyMode == WNI_CFG_PHY_MODE_11A) {
+ pAddTS->tsrsIE.rates[0] = TSRS_11AG_RATE_6MBPS;
+ } else {
+ pAddTS->tsrsIE.rates[0] = TSRS_11B_RATE_5_5MBPS;
+ }
+ populate_dot11_tsrsie(pMac, &pAddTS->tsrsIE,
+ &WMMAddTSReq.ESETrafStrmRateSet,
+ sizeof(uint8_t));
+#endif
+ /* fillWmeTspecIE */
+
+ nStatus =
+ dot11f_get_packed_wmm_add_ts_request_size(pMac, &WMMAddTSReq,
+ &nPayload);
+ if (DOT11F_FAILED(nStatus)) {
+ lim_log(pMac, LOGP,
+ FL("Failed to calculate the packed size f"
+ "or a WMM Add TS Request (0x%08x)."),
+ nStatus);
+ /* We'll fall back on the worst case scenario: */
+ nPayload = sizeof(tDot11fAddTSRequest);
+ } else if (DOT11F_WARNED(nStatus)) {
+ lim_log(pMac, LOGW,
+ FL("There were warnings while calculating"
+ "the packed size for a WMM Add TS Requ"
+ "est (0x%08x)."), nStatus);
+ }
+ }
+
+ nBytes = nPayload + sizeof(tSirMacMgmtHdr);
+
+ cdf_status = cds_packet_alloc((uint16_t) nBytes, (void **)&pFrame,
+ (void **)&pPacket);
+ if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
+ lim_log(pMac, LOGP, FL("Failed to allocate %d bytes for an Ad"
+ "d TS Request."), nBytes);
+ return;
+ }
+ /* Paranoia: */
+ cdf_mem_set(pFrame, nBytes, 0);
+
+ /* Next, we fill out the buffer descriptor: */
+ lim_populate_mac_header(pMac, pFrame, SIR_MAC_MGMT_FRAME,
+ SIR_MAC_MGMT_ACTION, peerMacAddr, psessionEntry->selfMacAddr);
+ pMacHdr = (tpSirMacMgmtHdr) pFrame;
+
+ sir_copy_mac_addr(pMacHdr->bssId, psessionEntry->bssId);
+
+#ifdef WLAN_FEATURE_11W
+ lim_set_protected_bit(pMac, psessionEntry, peerMacAddr, pMacHdr);
+#endif
+
+ /* That done, pack the struct: */
+ if (!pAddTS->wmeTspecPresent) {
+ nStatus = dot11f_pack_add_ts_request(pMac, &AddTSReq,
+ pFrame +
+ sizeof(tSirMacMgmtHdr),
+ nPayload, &nPayload);
+ if (DOT11F_FAILED(nStatus)) {
+ lim_log(pMac, LOGE,
+ FL("Failed to pack an Add TS Request "
+ "(0x%08x)."), nStatus);
+ cds_packet_free((void *)pPacket);
+ return; /* allocated! */
+ } else if (DOT11F_WARNED(nStatus)) {
+ lim_log(pMac, LOGW,
+ FL("There were warnings while packing "
+ "an Add TS Request (0x%08x)."), nStatus);
+ }
+ } else {
+ nStatus = dot11f_pack_wmm_add_ts_request(pMac, &WMMAddTSReq,
+ pFrame +
+ sizeof(tSirMacMgmtHdr),
+ nPayload, &nPayload);
+ if (DOT11F_FAILED(nStatus)) {
+ lim_log(pMac, LOGE,
+ FL("Failed to pack a WMM Add TS Reque"
+ "st (0x%08x)."), nStatus);
+ cds_packet_free((void *)pPacket);
+ return; /* allocated! */
+ } else if (DOT11F_WARNED(nStatus)) {
+ lim_log(pMac, LOGW,
+ FL("There were warnings while packing "
+ "a WMM Add TS Request (0x%08x)."), nStatus);
+ }
+ }
+
+ PELOG3(lim_log(pMac, LOG3, FL("Sending an Add TS Request frame to "));
+ lim_print_mac_addr(pMac, peerMacAddr, LOG3);
+ )
+
+ if ((SIR_BAND_5_GHZ ==
+ lim_get_rf_band(psessionEntry->currentOperChannel))
+ || (psessionEntry->pePersona == CDF_P2P_CLIENT_MODE)
+ || (psessionEntry->pePersona == CDF_P2P_GO_MODE)
+ ) {
+ txFlag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME;
+ }
+
+ MTRACE(cdf_trace(CDF_MODULE_ID_PE, TRACE_CODE_TX_MGMT,
+ psessionEntry->peSessionId, pMacHdr->fc.subType));
+
+ /* Queue Addts Response frame in high priority WQ */
+ cdf_status = wma_tx_frame(pMac, pPacket, (uint16_t) nBytes,
+ TXRX_FRM_802_11_MGMT,
+ ANI_TXDIR_TODS,
+ 7, lim_tx_complete, pFrame, txFlag,
+ smeSessionId, 0);
+ MTRACE(cdf_trace(CDF_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE,
+ psessionEntry->peSessionId, cdf_status));
+
+ if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
+ lim_log(pMac, LOGE, FL("*** Could not send an Add TS Request"
+ " (%X) ***"), cdf_status);
+ /* Pkt will be freed up by the callback */
+ }
+
+} /* End lim_send_addts_req_action_frame. */
+
+/**
+ * lim_send_assoc_rsp_mgmt_frame() - Send assoc response
+ * @mac_ctx: Handle for mac context
+ * @status_code: Status code for assoc response frame
+ * @aid: Association ID
+ * @peer_addr: Mac address of requesting peer
+ * @subtype: Assoc/Reassoc
+ * @sta: Pointer to station node
+ * @pe_session: PE session id.
+ *
+ * Builds and sends association response frame to the requesting peer.
+ *
+ * Return: void
+ */
+
+void
+lim_send_assoc_rsp_mgmt_frame(tpAniSirGlobal mac_ctx,
+ uint16_t status_code, uint16_t aid, tSirMacAddr peer_addr,
+ uint8_t subtype, tpDphHashNode sta, tpPESession pe_session)
+{
+ static tDot11fAssocResponse frm;
+ uint8_t *frame;
+ tpSirMacMgmtHdr mac_hdr;
+ tSirRetStatus sir_status;
+ uint8_t lle_mode = 0, addts;
+ tHalBitVal qos_mode, wme_mode;
+ uint32_t payload, bytes, status;
+ void *packet;
+ CDF_STATUS cdf_status;
+ tUpdateBeaconParams beacon_params;
+ uint8_t tx_flag = 0;
+ uint32_t addn_ie_len = 0;
+ uint8_t add_ie[WNI_CFG_ASSOC_RSP_ADDNIE_DATA_LEN];
+ tpSirAssocReq assoc_req = NULL;
+ uint8_t sme_session = 0;
+ bool is_vht = false;
+ uint16_t stripoff_len = 0;
+ tDot11fIEExtCap extracted_ext_cap;
+ bool extracted_flag = false;
+#ifdef WLAN_FEATURE_11W
+ uint32_t retry_int;
+ uint32_t max_retries;
+#endif
+
+ if (NULL == pe_session) {
+ lim_log(mac_ctx, LOGE, FL("pe_session is NULL"));
+ return;
+ }
+
+ sme_session = pe_session->smeSessionId;
+
+ cdf_mem_set((uint8_t *) &frm, sizeof(frm), 0);
+
+ limGetQosMode(pe_session, &qos_mode);
+ limGetWmeMode(pe_session, &wme_mode);
+
+ /*
+ * An Add TS IE is added only if the AP supports it and
+ * the requesting STA sent a traffic spec.
+ */
+ addts = (qos_mode && sta && sta->qos.addtsPresent) ? 1 : 0;
+
+ frm.Status.status = status_code;
+
+ frm.AID.associd = aid | LIM_AID_MASK;
+
+ if (NULL == sta) {
+ populate_dot11f_supp_rates(mac_ctx,
+ POPULATE_DOT11F_RATES_OPERATIONAL,
+ &frm.SuppRates, pe_session);
+ populate_dot11f_ext_supp_rates(mac_ctx,
+ POPULATE_DOT11F_RATES_OPERATIONAL,
+ &frm.ExtSuppRates, pe_session);
+ } else {
+ populate_dot11f_assoc_rsp_rates(mac_ctx, &frm.SuppRates,
+ &frm.ExtSuppRates,
+ sta->supportedRates.llbRates,
+ sta->supportedRates.llaRates);
+ }
+
+ if (LIM_IS_AP_ROLE(pe_session) && sta != NULL &&
+ eSIR_SUCCESS == status_code) {
+ assoc_req = (tpSirAssocReq)
+ pe_session->parsedAssocReq[sta->assocId];
+ /*
+ * populate P2P IE in AssocRsp when assocReq from the peer
+ * includes P2P IE
+ */
+ if (assoc_req != NULL && assoc_req->addIEPresent)
+ populate_dot11_assoc_res_p2p_ie(mac_ctx,
+ &frm.P2PAssocRes,
+ assoc_req);
+ }
+
+ if (NULL != sta) {
+ if (eHAL_SET == qos_mode) {
+ if (sta->lleEnabled) {
+ lle_mode = 1;
+ populate_dot11f_edca_param_set(mac_ctx,
+ &frm.EDCAParamSet, pe_session);
+ }
+ }
+
+ if ((!lle_mode) && (eHAL_SET == wme_mode) && sta->wmeEnabled) {
+ populate_dot11f_wmm_params(mac_ctx, &frm.WMMParams,
+ pe_session);
+
+ if (sta->wsmEnabled)
+ populate_dot11f_wmm_caps(&frm.WMMCaps);
+ }
+
+ if (sta->mlmStaContext.htCapability &&
+ pe_session->htCapability) {
+ lim_log(mac_ctx, LOG1,
+ FL("Populate HT IEs in Assoc Response"));
+ populate_dot11f_ht_caps(mac_ctx, pe_session,
+ &frm.HTCaps);
+ populate_dot11f_ht_info(mac_ctx, &frm.HTInfo,
+ pe_session);
+ }
+#ifdef WLAN_FEATURE_11AC
+ if (sta->mlmStaContext.vhtCapability &&
+ pe_session->vhtCapability) {
+ lim_log(mac_ctx, LOG1,
+ FL("Populate VHT IEs in Assoc Response"));
+ populate_dot11f_vht_caps(mac_ctx, pe_session,
+ &frm.VHTCaps);
+ populate_dot11f_vht_operation(mac_ctx, pe_session,
+ &frm.VHTOperation);
+ is_vht = true;
+ }
+#endif
+
+ populate_dot11f_ext_cap(mac_ctx, is_vht, &frm.ExtCap,
+ pe_session);
+
+#ifdef WLAN_FEATURE_11W
+ if (eSIR_MAC_TRY_AGAIN_LATER == status_code) {
+ if (wlan_cfg_get_int
+ (mac_ctx, WNI_CFG_PMF_SA_QUERY_MAX_RETRIES,
+ &max_retries) != eSIR_SUCCESS)
+ lim_log(mac_ctx, LOGE,
+ FL("get WNI_CFG_PMF_SA_QUERY_MAX_RETRIES failure"));
+ else if (wlan_cfg_get_int
+ (mac_ctx,
+ WNI_CFG_PMF_SA_QUERY_RETRY_INTERVAL,
+ &retry_int) != eSIR_SUCCESS)
+ lim_log(mac_ctx, LOGE,
+ FL("get WNI_CFG_PMF_SA_QUERY_RETRY_INTERVAL failure"));
+ else
+ populate_dot11f_timeout_interval(mac_ctx,
+ &frm.TimeoutInterval,
+ SIR_MAC_TI_TYPE_ASSOC_COMEBACK,
+ (max_retries -
+ sta->pmfSaQueryRetryCount)
+ * retry_int);
+ }
+#endif
+ }
+
+ cdf_mem_set((uint8_t *) &beacon_params, sizeof(beacon_params), 0);
+
+ if (LIM_IS_AP_ROLE(pe_session) &&
+ (pe_session->gLimProtectionControl !=
+ WNI_CFG_FORCE_POLICY_PROTECTION_DISABLE))
+ lim_decide_ap_protection(mac_ctx, peer_addr,
+ &beacon_params, pe_session);
+
+ lim_update_short_preamble(mac_ctx, peer_addr, &beacon_params,
+ pe_session);
+ lim_update_short_slot_time(mac_ctx, peer_addr, &beacon_params,
+ pe_session);
+
+ /*
+ * Populate Do11capabilities after updating session with
+ * Assos req details
+ */
+ populate_dot11f_capabilities(mac_ctx, &frm.Capabilities, pe_session);
+
+ beacon_params.bssIdx = pe_session->bssIdx;
+
+ /* Send message to HAL about beacon parameter change. */
+ if ((false == mac_ctx->sap.SapDfsInfo.is_dfs_cac_timer_running)
+ && beacon_params.paramChangeBitmap) {
+ sch_set_fixed_beacon_fields(mac_ctx, pe_session);
+ lim_send_beacon_params(mac_ctx, &beacon_params, pe_session);
+ }
+ /* Allocate a buffer for this frame: */
+ status = dot11f_get_packed_assoc_response_size(mac_ctx, &frm, &payload);
+ if (DOT11F_FAILED(status)) {
+ lim_log(mac_ctx, LOGE,
+ FL("get Association Response size failure (0x%08x)."),
+ status);
+ return;
+ } else if (DOT11F_WARNED(status)) {
+ lim_log(mac_ctx, LOGW,
+ FL("get Association Response size warning (0x%08x)."),
+ status);
+ }
+
+ bytes = sizeof(tSirMacMgmtHdr) + payload;
+
+ if (assoc_req != NULL) {
+ addn_ie_len = (pe_session->addIeParams.assocRespDataLen != 0);
+
+ /* Nonzero length indicates Assoc rsp IE available */
+ if (addn_ie_len <= WNI_CFG_ASSOC_RSP_ADDNIE_DATA_LEN
+ && (bytes + addn_ie_len) <= SIR_MAX_PACKET_SIZE) {
+ cdf_mem_copy(add_ie,
+ pe_session->addIeParams.assocRespData_buff,
+ pe_session->addIeParams.assocRespDataLen);
+
+ cdf_mem_set((uint8_t *) &extracted_ext_cap,
+ sizeof(extracted_ext_cap), 0);
+
+ stripoff_len = addn_ie_len;
+ sir_status =
+ lim_strip_extcap_update_struct
+ (mac_ctx, &add_ie[0], &stripoff_len,
+ &extracted_ext_cap);
+ if (eSIR_SUCCESS != sir_status) {
+ lim_log(mac_ctx, LOG1,
+ FL("strip off extcap IE failed"));
+ } else {
+ addn_ie_len = stripoff_len;
+ extracted_flag = true;
+ }
+ bytes = bytes + addn_ie_len;
+ }
+ lim_log(mac_ctx, LOG1,
+ FL("addn_ie_len = %d for Assoc Resp : %d"),
+ addn_ie_len, assoc_req->addIEPresent);
+ }
+ cdf_status = cds_packet_alloc((uint16_t) bytes, (void **)&frame,
+ (void **)&packet);
+ if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
+ lim_log(mac_ctx, LOGP, FL("cds_packet_alloc failed."));
+ return;
+ }
+ /* Paranoia: */
+ cdf_mem_set(frame, bytes, 0);
+
+ /* Next, we fill out the buffer descriptor: */
+ lim_populate_mac_header(mac_ctx, frame, SIR_MAC_MGMT_FRAME,
+ (LIM_ASSOC == subtype) ?
+ SIR_MAC_MGMT_ASSOC_RSP : SIR_MAC_MGMT_REASSOC_RSP,
+ peer_addr,
+ pe_session->selfMacAddr);
+ mac_hdr = (tpSirMacMgmtHdr) frame;
+
+ sir_copy_mac_addr(mac_hdr->bssId, pe_session->bssId);
+
+ /* merge the ExtCap struct */
+ if (extracted_flag)
+ lim_merge_extcap_struct(&(frm.ExtCap), &extracted_ext_cap);
+ status = dot11f_pack_assoc_response(mac_ctx, &frm,
+ frame + sizeof(tSirMacMgmtHdr),
+ payload, &payload);
+ if (DOT11F_FAILED(status)) {
+ lim_log(mac_ctx, LOGE,
+ FL("Association Response pack failure(0x%08x)."),
+ status);
+ cds_packet_free((void *)packet);
+ return;
+ } else if (DOT11F_WARNED(status)) {
+ lim_log(mac_ctx, LOGW,
+ FL("Association Response pack warning (0x%08x)."),
+ status);
+ }
+
+ if (subtype == LIM_ASSOC)
+ lim_log(mac_ctx, LOG1,
+ FL("*** Sending Assoc Resp status %d aid %d to "),
+ status_code, aid);
+ else
+ lim_log(mac_ctx, LOG1,
+ FL("*** Sending ReAssoc Resp status %d aid %d to "),
+ status_code, aid);
+
+ lim_print_mac_addr(mac_ctx, mac_hdr->da, LOG1);
+
+ if (addn_ie_len && addn_ie_len <= WNI_CFG_ASSOC_RSP_ADDNIE_DATA_LEN)
+ cdf_mem_copy(frame + sizeof(tSirMacMgmtHdr) + payload,
+ &add_ie[0], addn_ie_len);
+
+ if ((SIR_BAND_5_GHZ ==
+ lim_get_rf_band(pe_session->currentOperChannel)) ||
+ (pe_session->pePersona == CDF_P2P_CLIENT_MODE) ||
+ (pe_session->pePersona == CDF_P2P_GO_MODE))
+ tx_flag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME;
+
+ MTRACE(cdf_trace(CDF_MODULE_ID_PE, TRACE_CODE_TX_MGMT,
+ pe_session->peSessionId, mac_hdr->fc.subType));
+ /* Queue Association Response frame in high priority WQ */
+ cdf_status = wma_tx_frame(mac_ctx, packet, (uint16_t) bytes,
+ TXRX_FRM_802_11_MGMT,
+ ANI_TXDIR_TODS,
+ 7, lim_tx_complete, frame, tx_flag,
+ sme_session, 0);
+ MTRACE(cdf_trace(CDF_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE,
+ pe_session->peSessionId, cdf_status));
+
+ /* Pkt will be freed up by the callback */
+ if (!CDF_IS_STATUS_SUCCESS(cdf_status))
+ lim_log(mac_ctx, LOGE,
+ FL("*** Could not Send Re/AssocRsp, retCode=%X ***"),
+ cdf_status);
+
+ /*
+ * update the ANI peer station count.
+ * FIXME_PROTECTION : take care of different type of station
+ * counter inside this function.
+ */
+ lim_util_count_sta_add(mac_ctx, sta, pe_session);
+
+}
+
+void
+lim_send_delts_req_action_frame(tpAniSirGlobal pMac,
+ tSirMacAddr peer,
+ uint8_t wmmTspecPresent,
+ tSirMacTSInfo *pTsinfo,
+ tSirMacTspecIE *pTspecIe, tpPESession psessionEntry)
+{
+ uint8_t *pFrame;
+ tpSirMacMgmtHdr pMacHdr;
+ tDot11fDelTS DelTS;
+ tDot11fWMMDelTS WMMDelTS;
+ uint32_t nBytes, nPayload, nStatus;
+ void *pPacket;
+ CDF_STATUS cdf_status;
+ uint8_t txFlag = 0;
+ uint8_t smeSessionId = 0;
+
+ if (NULL == psessionEntry) {
+ return;
+ }
+
+ smeSessionId = psessionEntry->smeSessionId;
+
+ if (!wmmTspecPresent) {
+ cdf_mem_set((uint8_t *) &DelTS, sizeof(DelTS), 0);
+
+ DelTS.Category.category = SIR_MAC_ACTION_QOS_MGMT;
+ DelTS.Action.action = SIR_MAC_QOS_DEL_TS_REQ;
+ populate_dot11f_ts_info(pTsinfo, &DelTS.TSInfo);
+
+ nStatus = dot11f_get_packed_del_ts_size(pMac, &DelTS, &nPayload);
+ if (DOT11F_FAILED(nStatus)) {
+ lim_log(pMac, LOGP,
+ FL("Failed to calculate the packed si"
+ "ze for a Del TS (0x%08x)."), nStatus);
+ /* We'll fall back on the worst case scenario: */
+ nPayload = sizeof(tDot11fDelTS);
+ } else if (DOT11F_WARNED(nStatus)) {
+ lim_log(pMac, LOGW,
+ FL("There were warnings while calcula"
+ "ting the packed size for a Del TS"
+ " (0x%08x)."), nStatus);
+ }
+ } else {
+ cdf_mem_set((uint8_t *) &WMMDelTS, sizeof(WMMDelTS), 0);
+
+ WMMDelTS.Category.category = SIR_MAC_ACTION_WME;
+ WMMDelTS.Action.action = SIR_MAC_QOS_DEL_TS_REQ;
+ WMMDelTS.DialogToken.token = 0;
+ WMMDelTS.StatusCode.statusCode = 0;
+ populate_dot11f_wmmtspec(pTspecIe, &WMMDelTS.WMMTSPEC);
+ nStatus =
+ dot11f_get_packed_wmm_del_ts_size(pMac, &WMMDelTS, &nPayload);
+ if (DOT11F_FAILED(nStatus)) {
+ lim_log(pMac, LOGP,
+ FL("Failed to calculate the packed si"
+ "ze for a WMM Del TS (0x%08x)."), nStatus);
+ /* We'll fall back on the worst case scenario: */
+ nPayload = sizeof(tDot11fDelTS);
+ } else if (DOT11F_WARNED(nStatus)) {
+ lim_log(pMac, LOGW,
+ FL("There were warnings while calcula"
+ "ting the packed size for a WMM De"
+ "l TS (0x%08x)."), nStatus);
+ }
+ }
+
+ nBytes = nPayload + sizeof(tSirMacMgmtHdr);
+
+ cdf_status =
+ cds_packet_alloc((uint16_t) nBytes, (void **)&pFrame,
+ (void **)&pPacket);
+ if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
+ lim_log(pMac, LOGP, FL("Failed to allocate %d bytes for an Ad"
+ "d TS Response."), nBytes);
+ return;
+ }
+ /* Paranoia: */
+ cdf_mem_set(pFrame, nBytes, 0);
+
+ /* Next, we fill out the buffer descriptor: */
+ lim_populate_mac_header(pMac, pFrame, SIR_MAC_MGMT_FRAME,
+ SIR_MAC_MGMT_ACTION, peer, psessionEntry->selfMacAddr);
+ pMacHdr = (tpSirMacMgmtHdr) pFrame;
+
+ sir_copy_mac_addr(pMacHdr->bssId, psessionEntry->bssId);
+
+#ifdef WLAN_FEATURE_11W
+ lim_set_protected_bit(pMac, psessionEntry, peer, pMacHdr);
+#endif
+
+ /* That done, pack the struct: */
+ if (!wmmTspecPresent) {
+ nStatus = dot11f_pack_del_ts(pMac, &DelTS,
+ pFrame + sizeof(tSirMacMgmtHdr),
+ nPayload, &nPayload);
+ if (DOT11F_FAILED(nStatus)) {
+ lim_log(pMac, LOGE,
+ FL("Failed to pack a Del TS frame (0x%08x)."),
+ nStatus);
+ cds_packet_free((void *)pPacket);
+ return; /* allocated! */
+ } else if (DOT11F_WARNED(nStatus)) {
+ lim_log(pMac, LOGW,
+ FL("There were warnings while packing "
+ "a Del TS frame (0x%08x)."), nStatus);
+ }
+ } else {
+ nStatus = dot11f_pack_wmm_del_ts(pMac, &WMMDelTS,
+ pFrame + sizeof(tSirMacMgmtHdr),
+ nPayload, &nPayload);
+ if (DOT11F_FAILED(nStatus)) {
+ lim_log(pMac, LOGE,
+ FL
+ ("Failed to pack a WMM Del TS frame (0x%08x)."),
+ nStatus);
+ cds_packet_free((void *)pPacket);
+ return; /* allocated! */
+ } else if (DOT11F_WARNED(nStatus)) {
+ lim_log(pMac, LOGW,
+ FL("There were warnings while packing "
+ "a WMM Del TS frame (0x%08x)."), nStatus);
+ }
+ }
+
+ PELOG1(lim_log
+ (pMac, LOG1, FL("Sending DELTS REQ (size %d) to "), nBytes);
+ lim_print_mac_addr(pMac, pMacHdr->da, LOG1);
+ )
+
+ if ((SIR_BAND_5_GHZ ==
+ lim_get_rf_band(psessionEntry->currentOperChannel))
+ || (psessionEntry->pePersona == CDF_P2P_CLIENT_MODE)
+ || (psessionEntry->pePersona == CDF_P2P_GO_MODE)
+ ) {
+ txFlag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME;
+ }
+
+ MTRACE(cdf_trace(CDF_MODULE_ID_PE, TRACE_CODE_TX_MGMT,
+ psessionEntry->peSessionId, pMacHdr->fc.subType));
+ cdf_status = wma_tx_frame(pMac, pPacket, (uint16_t) nBytes,
+ TXRX_FRM_802_11_MGMT,
+ ANI_TXDIR_TODS,
+ 7, lim_tx_complete, pFrame, txFlag,
+ smeSessionId, 0);
+ MTRACE(cdf_trace(CDF_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE,
+ psessionEntry->peSessionId, cdf_status));
+ /* Pkt will be freed up by the callback */
+ if (!CDF_IS_STATUS_SUCCESS(cdf_status))
+ lim_log(pMac, LOGE, FL("Failed to send Del TS (%X)!"),
+ cdf_status);
+
+} /* End lim_send_delts_req_action_frame. */
+
+/**
+ * lim_send_assoc_req_mgmt_frame() - Send association request
+ * @mac_ctx: Handle to MAC context
+ * @mlm_assoc_req: Association request information
+ * @pe_session: PE session information
+ *
+ * Builds and transmits association request frame to AP.
+ *
+ * Return: Void
+ */
+
+void
+lim_send_assoc_req_mgmt_frame(tpAniSirGlobal mac_ctx,
+ tLimMlmAssocReq *mlm_assoc_req,
+ tpPESession pe_session)
+{
+ tDot11fAssocRequest *frm;
+ uint16_t caps;
+ uint8_t *frame;
+ tSirRetStatus sir_status;
+ tLimMlmAssocCnf assoc_cnf;
+ uint32_t bytes, payload, status;
+ uint8_t qos_enabled, wme_enabled, wsm_enabled;
+ void *packet;
+ CDF_STATUS cdf_status;
+ uint16_t add_ie_len;
+ uint8_t *add_ie;
+ uint8_t *wps_ie = NULL;
+#if defined WLAN_FEATURE_VOWIFI
+ uint8_t power_caps = false;
+#endif
+ uint8_t tx_flag = 0;
+ uint8_t sme_sessionid = 0;
+ bool vht_enabled = false;
+ tDot11fIEExtCap extr_ext_cap;
+ bool extr_ext_flag = true;
+ tpSirMacMgmtHdr mac_hdr;
+
+ if (NULL == pe_session) {
+ lim_log(mac_ctx, LOGE, FL("pe_session is NULL"));
+ return;
+ }
+
+ sme_sessionid = pe_session->smeSessionId;
+
+ /* check this early to avoid unncessary operation */
+ if (NULL == pe_session->pLimJoinReq) {
+ lim_log(mac_ctx, LOGE, FL("pe_session->pLimJoinReq is NULL"));
+ return;
+ }
+ add_ie_len = pe_session->pLimJoinReq->addIEAssoc.length;
+ add_ie = pe_session->pLimJoinReq->addIEAssoc.addIEdata;
+
+ frm = cdf_mem_malloc(sizeof(tDot11fAssocRequest));
+ if (NULL == frm) {
+ lim_log(mac_ctx, LOGE, FL("Unable to allocate memory"));
+ return;
+ }
+
+ cdf_mem_set((uint8_t *) frm, sizeof(tDot11fAssocRequest), 0);
+
+ if (add_ie_len) {
+ cdf_mem_set((uint8_t *) &extr_ext_cap, sizeof(tDot11fIEExtCap),
+ 0);
+ sir_status = lim_strip_extcap_update_struct(mac_ctx,
+ add_ie, &add_ie_len, &extr_ext_cap);
+ if (eSIR_SUCCESS != sir_status) {
+ extr_ext_flag = false;
+ lim_log(mac_ctx, LOG1,
+ FL("Unable to Stripoff ExtCap IE from Assoc Req"));
+ } else {
+ struct s_ext_cap *p_ext_cap = (struct s_ext_cap *)
+ extr_ext_cap.bytes;
+
+ if (p_ext_cap->interworking_service)
+ p_ext_cap->qos_map = 1;
+ else {
+ /*
+ * No need to merge the EXT Cap from Supplicant
+ * if interworkingService is not set, as currently
+ * driver is only interested in interworkingService
+ * capability from supplicant. if in future any other
+ * EXT Cap info is required from supplicant
+ * it needs to be handled here.
+ */
+ extr_ext_flag = false;
+ }
+ }
+ } else {
+ lim_log(mac_ctx, LOG1, FL("No additional IE for Assoc Req"));
+ extr_ext_flag = false;
+ }
+
+ caps = mlm_assoc_req->capabilityInfo;
+#if defined(FEATURE_WLAN_WAPI)
+ /*
+ * According to WAPI standard:
+ * 7.3.1.4 Capability Information field
+ * In WAPI, non-AP STAs within an ESS set the Privacy subfield to 0
+ * in transmitted Association or Reassociation management frames.
+ * APs ignore the Privacy subfield within received Association and
+ * Reassociation management frames.
+ */
+ if (pe_session->encryptType == eSIR_ED_WPI)
+ ((tSirMacCapabilityInfo *) &caps)->privacy = 0;
+#endif
+ swap_bit_field16(caps, (uint16_t *) &frm->Capabilities);
+
+ frm->ListenInterval.interval = mlm_assoc_req->listenInterval;
+ populate_dot11f_ssid2(mac_ctx, &frm->SSID);
+ populate_dot11f_supp_rates(mac_ctx, POPULATE_DOT11F_RATES_OPERATIONAL,
+ &frm->SuppRates, pe_session);
+
+ qos_enabled = (pe_session->limQosEnabled) &&
+ SIR_MAC_GET_QOS(pe_session->limCurrentBssCaps);
+
+ wme_enabled = (pe_session->limWmeEnabled) &&
+ LIM_BSS_CAPS_GET(WME, pe_session->limCurrentBssQosCaps);
+
+ /* We prefer .11e asociations: */
+ if (qos_enabled)
+ wme_enabled = false;
+
+ wsm_enabled = (pe_session->limWsmEnabled) && wme_enabled &&
+ LIM_BSS_CAPS_GET(WSM, pe_session->limCurrentBssQosCaps);
+
+ if (pe_session->lim11hEnable &&
+ pe_session->pLimJoinReq->spectrumMgtIndicator == eSIR_TRUE) {
+#if defined WLAN_FEATURE_VOWIFI
+ power_caps = true;
+
+ populate_dot11f_power_caps(mac_ctx, &frm->PowerCaps,
+ LIM_ASSOC, pe_session);
+#endif
+ populate_dot11f_supp_channels(mac_ctx, &frm->SuppChannels,
+ LIM_ASSOC, pe_session);
+
+ }
+#if defined WLAN_FEATURE_VOWIFI
+ if (mac_ctx->rrm.rrmPEContext.rrmEnable &&
+ SIR_MAC_GET_RRM(pe_session->limCurrentBssCaps)) {
+ if (power_caps == false) {
+ power_caps = true;
+ populate_dot11f_power_caps(mac_ctx, &frm->PowerCaps,
+ LIM_ASSOC, pe_session);
+ }
+ }
+#endif
+
+ if (qos_enabled)
+ populate_dot11f_qos_caps_station(mac_ctx, &frm->QOSCapsStation);
+
+ populate_dot11f_ext_supp_rates(mac_ctx,
+ POPULATE_DOT11F_RATES_OPERATIONAL, &frm->ExtSuppRates,
+ pe_session);
+
+#if defined WLAN_FEATURE_VOWIFI
+ if (mac_ctx->rrm.rrmPEContext.rrmEnable &&
+ SIR_MAC_GET_RRM(pe_session->limCurrentBssCaps))
+ populate_dot11f_rrm_ie(mac_ctx, &frm->RRMEnabledCap,
+ pe_session);
+#endif
+ /*
+ * The join request *should* contain zero or one of the WPA and RSN
+ * IEs. The payload send along with the request is a
+ * 'tSirSmeJoinReq'; the IE portion is held inside a 'tSirRSNie':
+ * typedef struct sSirRSNie
+ * {
+ * uint16_t length;
+ * uint8_t rsnIEdata[SIR_MAC_MAX_IE_LENGTH+2];
+ * } tSirRSNie, *tpSirRSNie;
+ * So, we should be able to make the following two calls harmlessly,
+ * since they do nothing if they don't find the given IE in the
+ * bytestream with which they're provided.
+ * The net effect of this will be to faithfully transmit whatever
+ * security IE is in the join request.
+ * However, if we're associating for the purpose of WPS
+ * enrollment, and we've been configured to indicate that by
+ * eliding the WPA or RSN IE, we just skip this:
+ */
+ if (add_ie_len && add_ie)
+ wps_ie = limGetWscIEPtr(mac_ctx, add_ie, add_ie_len);
+
+ if (NULL == wps_ie) {
+ populate_dot11f_rsn_opaque(mac_ctx,
+ &(pe_session->pLimJoinReq->rsnIE),
+ &frm->RSNOpaque);
+ populate_dot11f_wpa_opaque(mac_ctx,
+ &(pe_session->pLimJoinReq->rsnIE),
+ &frm->WPAOpaque);
+#if defined(FEATURE_WLAN_WAPI)
+ populate_dot11f_wapi_opaque(mac_ctx,
+ &(pe_session->pLimJoinReq->rsnIE),
+ &frm->WAPIOpaque);
+#endif /* defined(FEATURE_WLAN_WAPI) */
+ }
+ /* include WME EDCA IE as well */
+ if (wme_enabled) {
+ populate_dot11f_wmm_info_station_per_session(mac_ctx,
+ pe_session, &frm->WMMInfoStation);
+
+ if (wsm_enabled)
+ populate_dot11f_wmm_caps(&frm->WMMCaps);
+ }
+
+ /*
+ * Populate HT IEs, when operating in 11n and
+ * when AP is also operating in 11n mode
+ */
+ if (pe_session->htCapability &&
+ mac_ctx->lim.htCapabilityPresentInBeacon) {
+ lim_log(mac_ctx, LOG1, FL("Populate HT Caps in Assoc Request"));
+ populate_dot11f_ht_caps(mac_ctx, pe_session, &frm->HTCaps);
+ }
+#ifdef WLAN_FEATURE_11AC
+ if (pe_session->vhtCapability &&
+ pe_session->vhtCapabilityPresentInBeacon) {
+ lim_log(mac_ctx, LOG1, FL("Populate VHT IEs in Assoc Request"));
+ populate_dot11f_vht_caps(mac_ctx, pe_session, &frm->VHTCaps);
+ vht_enabled = true;
+ }
+ if (!vht_enabled &&
+ pe_session->is_vendor_specific_vhtcaps) {
+ lim_log(mac_ctx, LOG1,
+ FL("Populate Vendor VHT IEs in Assoc Request"));
+ frm->vendor2_ie.present = 1;
+ frm->vendor2_ie.type =
+ pe_session->vendor_specific_vht_ie_type;
+ frm->vendor2_ie.sub_type =
+ pe_session->vendor_specific_vht_ie_sub_type;
+
+ frm->vendor2_ie.VHTCaps.present = 1;
+ populate_dot11f_vht_caps(mac_ctx, pe_session,
+ &frm->vendor2_ie.VHTCaps);
+ vht_enabled = true;
+ }
+
+#endif
+
+ populate_dot11f_ext_cap(mac_ctx, vht_enabled, &frm->ExtCap, pe_session);
+
+#if defined WLAN_FEATURE_VOWIFI_11R
+ if (pe_session->pLimJoinReq->is11Rconnection) {
+#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG
+ tSirBssDescription *bssdescr;
+
+ bssdescr = &pe_session->pLimJoinReq->bssDescription;
+ lim_log(mac_ctx, LOG1, FL("mdie = %02x %02x %02x"),
+ (unsigned int) bssdescr->mdie[0],
+ (unsigned int) bssdescr->mdie[1],
+ (unsigned int) bssdescr->mdie[2]);
+#endif
+ populate_mdie(mac_ctx, &frm->MobilityDomain,
+ pe_session->pLimJoinReq->bssDescription.mdie);
+ } else {
+ /* No 11r IEs dont send any MDIE */
+ lim_log(mac_ctx, LOG1, FL("MDIE not present"));
+ }
+#endif
+
+#ifdef FEATURE_WLAN_ESE
+ /*
+ * ESE Version IE will be included in association request
+ * when ESE is enabled on DUT through ini and it is also
+ * advertised by the peer AP to which we are trying to
+ * associate to.
+ */
+ if (pe_session->is_ese_version_ie_present &&
+ mac_ctx->roam.configParam.isEseIniFeatureEnabled)
+ populate_dot11f_ese_version(&frm->ESEVersion);
+ /* For ESE Associations fill the ESE IEs */
+ if (pe_session->isESEconnection &&
+ pe_session->pLimJoinReq->isESEFeatureIniEnabled) {
+#ifndef FEATURE_DISABLE_RM
+ populate_dot11f_ese_rad_mgmt_cap(&frm->ESERadMgmtCap);
+#endif
+ }
+#endif
+
+ status = dot11f_get_packed_assoc_request_size(mac_ctx, frm, &payload);
+ if (DOT11F_FAILED(status)) {
+ lim_log(mac_ctx, LOGP,
+ FL("Association Request packet size failure(0x%08x)."),
+ status);
+ /* We'll fall back on the worst case scenario: */
+ payload = sizeof(tDot11fAssocRequest);
+ } else if (DOT11F_WARNED(status)) {
+ lim_log(mac_ctx, LOGW,
+ FL("Association request packet size warning (0x%08x)."),
+ status);
+ }
+
+ bytes = payload + sizeof(tSirMacMgmtHdr) + add_ie_len;
+
+ cdf_status = cds_packet_alloc((uint16_t) bytes, (void **)&frame,
+ (void **)&packet);
+ if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
+ lim_log(mac_ctx, LOGP, FL("Failed to allocate %d bytes."),
+ bytes);
+
+ pe_session->limMlmState = pe_session->limPrevMlmState;
+ MTRACE(cdf_trace(CDF_MODULE_ID_PE, TRACE_CODE_MLM_STATE,
+ pe_session->peSessionId,
+ pe_session->limMlmState));
+
+ /* Update PE session id */
+ assoc_cnf.sessionId = pe_session->peSessionId;
+
+ assoc_cnf.resultCode = eSIR_SME_RESOURCES_UNAVAILABLE;
+
+ cds_packet_free((void *)packet);
+
+ lim_post_sme_message(mac_ctx, LIM_MLM_ASSOC_CNF,
+ (uint32_t *) &assoc_cnf);
+
+ cdf_mem_free(frm);
+ return;
+ }
+ /* Paranoia: */
+ cdf_mem_set(frame, bytes, 0);
+
+ /* Next, we fill out the buffer descriptor: */
+ lim_populate_mac_header(mac_ctx, frame, SIR_MAC_MGMT_FRAME,
+ SIR_MAC_MGMT_ASSOC_REQ, pe_session->bssId,
+ pe_session->selfMacAddr);
+ /* merge the ExtCap struct */
+ if (extr_ext_flag)
+ lim_merge_extcap_struct(&frm->ExtCap, &extr_ext_cap);
+ /* That done, pack the Assoc Request: */
+ status = dot11f_pack_assoc_request(mac_ctx, frm,
+ frame + sizeof(tSirMacMgmtHdr), payload, &payload);
+ if (DOT11F_FAILED(status)) {
+ lim_log(mac_ctx, LOGE,
+ FL("Assoc request pack failure (0x%08x)"), status);
+ cds_packet_free((void *)packet);
+ cdf_mem_free(frm);
+ return;
+ } else if (DOT11F_WARNED(status)) {
+ lim_log(mac_ctx, LOGW,
+ FL("Assoc request pack warning (0x%08x)"), status);
+ }
+
+ lim_log(mac_ctx, LOG1,
+ FL("*** Sending Association Request length %d to "), bytes);
+ if (pe_session->assocReq != NULL) {
+ cdf_mem_free(pe_session->assocReq);
+ pe_session->assocReq = NULL;
+ }
+
+ if (add_ie_len) {
+ cdf_mem_copy(frame + sizeof(tSirMacMgmtHdr) + payload,
+ add_ie, add_ie_len);
+ payload += add_ie_len;
+ }
+
+ pe_session->assocReq = cdf_mem_malloc(payload);
+ if (NULL == pe_session->assocReq) {
+ lim_log(mac_ctx, LOGE, FL("Unable to allocate memory"));
+ } else {
+ /*
+ * Store the Assoc request. This is sent to csr/hdd in
+ * join cnf response.
+ */
+ cdf_mem_copy(pe_session->assocReq,
+ frame + sizeof(tSirMacMgmtHdr), payload);
+ pe_session->assocReqLen = payload;
+ }
+
+ if ((SIR_BAND_5_GHZ == lim_get_rf_band(pe_session->currentOperChannel))
+ || (pe_session->pePersona == CDF_P2P_CLIENT_MODE)
+ || (pe_session->pePersona == CDF_P2P_GO_MODE)
+ )
+ tx_flag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME;
+
+ if (pe_session->pePersona == CDF_P2P_CLIENT_MODE)
+ tx_flag |= HAL_USE_PEER_STA_REQUESTED_MASK;
+
+#ifdef FEATURE_WLAN_DIAG_SUPPORT
+ lim_diag_event_report(mac_ctx, WLAN_PE_DIAG_ASSOC_START_EVENT,
+ pe_session, eSIR_SUCCESS, eSIR_SUCCESS);
+#endif
+ mac_hdr = (tpSirMacMgmtHdr) frame;
+ MTRACE(cdf_trace(CDF_MODULE_ID_PE, TRACE_CODE_TX_MGMT,
+ pe_session->peSessionId, mac_hdr->fc.subType));
+ cdf_status =
+ wma_tx_frame(mac_ctx, packet,
+ (uint16_t) (sizeof(tSirMacMgmtHdr) + payload),
+ TXRX_FRM_802_11_MGMT, ANI_TXDIR_TODS, 7,
+ lim_tx_complete, frame, tx_flag, sme_sessionid, 0);
+ MTRACE(cdf_trace
+ (CDF_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE,
+ pe_session->peSessionId, cdf_status));
+ if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
+ lim_log(mac_ctx, LOGE,
+ FL("Failed to send Association Request (%X)!"),
+ cdf_status);
+ /* Pkt will be freed up by the callback */
+ cdf_mem_free(frm);
+ return;
+ }
+ /* Free up buffer allocated for mlm_assoc_req */
+ cdf_mem_free(mlm_assoc_req);
+ mlm_assoc_req = NULL;
+ cdf_mem_free(frm);
+ return;
+}
+
+#if defined WLAN_FEATURE_VOWIFI_11R || defined FEATURE_WLAN_ESE || defined(FEATURE_WLAN_LFR)
+/**
+ * lim_send_reassoc_req_with_ft_ies_mgmt_frame() - Send Reassoc Req with FTIEs.
+ *
+ * @mac_ctx: Handle to mac context
+ * @mlm_reassoc_req: Original reassoc request
+ * @pe_session: PE session information
+ *
+ * It builds a reassoc request with FT IEs and sends it to AP through WMA.
+ * Then it creates assoc request and stores it for sending after join
+ * confirmation.
+ *
+ * Return: void
+ */
+
+void
+lim_send_reassoc_req_with_ft_ies_mgmt_frame(tpAniSirGlobal mac_ctx,
+ tLimMlmReassocReq *mlm_reassoc_req,
+ tpPESession pe_session)
+{
+ static tDot11fReAssocRequest frm;
+ uint16_t caps;
+ uint8_t *frame;
+ uint32_t bytes, payload, status;
+ uint8_t qos_enabled, wme_enabled, wsm_enabled;
+ void *packet;
+ CDF_STATUS cdf_status;
+#if defined WLAN_FEATURE_VOWIFI
+ uint8_t power_caps_populated = false;
+#endif
+ uint16_t ft_ies_length = 0;
+ uint8_t *body;
+ uint16_t add_ie_len;
+ uint8_t *add_ie;
+#if defined FEATURE_WLAN_ESE || defined(FEATURE_WLAN_LFR)
+ uint8_t *wps_ie = NULL;
+#endif
+ uint8_t tx_flag = 0;
+ uint8_t sme_sessionid = 0;
+ bool vht_enabled = false;
+ tpSirMacMgmtHdr mac_hdr;
+ tftSMEContext *ft_sme_context;
+
+ if (NULL == pe_session)
+ return;
+
+ sme_sessionid = pe_session->smeSessionId;
+
+ /* check this early to avoid unncessary operation */
+ if (NULL == pe_session->pLimReAssocReq)
+ return;
+
+ add_ie_len = pe_session->pLimReAssocReq->addIEAssoc.length;
+ add_ie = pe_session->pLimReAssocReq->addIEAssoc.addIEdata;
+ lim_log(mac_ctx, LOG1,
+ FL("called in state (%d)."), pe_session->limMlmState);
+
+ cdf_mem_set((uint8_t *) &frm, sizeof(frm), 0);
+
+ caps = mlm_reassoc_req->capabilityInfo;
+#if defined(FEATURE_WLAN_WAPI)
+ /*
+ * According to WAPI standard:
+ * 7.3.1.4 Capability Information field
+ * In WAPI, non-AP STAs within an ESS set the Privacy subfield
+ * to 0 in transmitted Association or Reassociation management
+ * frames. APs ignore the Privacy subfield within received
+ * Association and Reassociation management frames.
+ */
+ if (pe_session->encryptType == eSIR_ED_WPI)
+ ((tSirMacCapabilityInfo *) &caps)->privacy = 0;
+#endif
+ swap_bit_field16(caps, (uint16_t *) &frm.Capabilities);
+
+ frm.ListenInterval.interval = mlm_reassoc_req->listenInterval;
+
+ /*
+ * Get the old bssid of the older AP.
+ * The previous ap bssid is stored in the FT Session
+ * while creating the PE FT Session for reassociation.
+ */
+ cdf_mem_copy((uint8_t *)frm.CurrentAPAddress.mac,
+ pe_session->prev_ap_bssid, sizeof(tSirMacAddr));
+
+ populate_dot11f_ssid2(mac_ctx, &frm.SSID);
+ populate_dot11f_supp_rates(mac_ctx, POPULATE_DOT11F_RATES_OPERATIONAL,
+ &frm.SuppRates, pe_session);
+
+ qos_enabled = (pe_session->limQosEnabled) &&
+ SIR_MAC_GET_QOS(pe_session->limReassocBssCaps);
+
+ wme_enabled = (pe_session->limWmeEnabled) &&
+ LIM_BSS_CAPS_GET(WME, pe_session->limReassocBssQosCaps);
+
+ wsm_enabled = (pe_session->limWsmEnabled) && wme_enabled &&
+ LIM_BSS_CAPS_GET(WSM, pe_session->limReassocBssQosCaps);
+
+ if (pe_session->lim11hEnable &&
+ pe_session->pLimReAssocReq->spectrumMgtIndicator == eSIR_TRUE) {
+#if defined WLAN_FEATURE_VOWIFI
+ power_caps_populated = true;
+
+ populate_dot11f_power_caps(mac_ctx, &frm.PowerCaps,
+ LIM_REASSOC, pe_session);
+ populate_dot11f_supp_channels(mac_ctx, &frm.SuppChannels,
+ LIM_REASSOC, pe_session);
+#endif
+ }
+#if defined WLAN_FEATURE_VOWIFI
+ if (mac_ctx->rrm.rrmPEContext.rrmEnable &&
+ SIR_MAC_GET_RRM(pe_session->limCurrentBssCaps)) {
+ if (power_caps_populated == false) {
+ power_caps_populated = true;
+ populate_dot11f_power_caps(mac_ctx, &frm.PowerCaps,
+ LIM_REASSOC, pe_session);
+ }
+ }
+#endif
+
+ if (qos_enabled)
+ populate_dot11f_qos_caps_station(mac_ctx, &frm.QOSCapsStation);
+
+ populate_dot11f_ext_supp_rates(mac_ctx,
+ POPULATE_DOT11F_RATES_OPERATIONAL, &frm.ExtSuppRates,
+ pe_session);
+
+#if defined WLAN_FEATURE_VOWIFI
+ if (mac_ctx->rrm.rrmPEContext.rrmEnable &&
+ SIR_MAC_GET_RRM(pe_session->limReassocBssCaps)) {
+ populate_dot11f_rrm_ie(mac_ctx, &frm.RRMEnabledCap, pe_session);
+ }
+#endif
+
+ /*
+ * Ideally this should be enabled for 11r also. But 11r does
+ * not follow the usual norm of using the Opaque object
+ * for rsnie and fties. Instead we just add the rsnie and fties
+ * at the end of the pack routine for 11r.
+ * This should ideally! be fixed.
+ */
+#if defined FEATURE_WLAN_ESE || defined(FEATURE_WLAN_LFR)
+ /*
+ * The join request *should* contain zero or one of the WPA and RSN
+ * IEs. The payload send along with the request is a
+ * 'tSirSmeJoinReq'; the IE portion is held inside a 'tSirRSNie':
+ *
+ * typedef struct sSirRSNie
+ * {
+ * uint16_t length;
+ * uint8_t rsnIEdata[SIR_MAC_MAX_IE_LENGTH+2];
+ * } tSirRSNie, *tpSirRSNie;
+ *
+ * So, we should be able to make the following two calls harmlessly,
+ * since they do nothing if they don't find the given IE in the
+ * bytestream with which they're provided.
+ *
+ * The net effect of this will be to faithfully transmit whatever
+ * security IE is in the join request.
+
+ * However, if we're associating for the purpose of WPS
+ * enrollment, and we've been configured to indicate that by
+ * eliding the WPA or RSN IE, we just skip this:
+ */
+ if (!pe_session->is11Rconnection) {
+ if (add_ie_len && add_ie)
+ wps_ie = limGetWscIEPtr(mac_ctx, add_ie, add_ie_len);
+ if (NULL == wps_ie) {
+ populate_dot11f_rsn_opaque(mac_ctx,
+ &(pe_session->pLimReAssocReq->rsnIE),
+ &frm.RSNOpaque);
+ populate_dot11f_wpa_opaque(mac_ctx,
+ &(pe_session->pLimReAssocReq->rsnIE),
+ &frm.WPAOpaque);
+ }
+#ifdef FEATURE_WLAN_ESE
+ if (pe_session->pLimReAssocReq->cckmIE.length) {
+ populate_dot11f_ese_cckm_opaque(mac_ctx,
+ &(pe_session->pLimReAssocReq->cckmIE),
+ &frm.ESECckmOpaque);
+ }
+#endif
+ }
+#ifdef FEATURE_WLAN_ESE
+ /*
+ * ESE Version IE will be included in re-association request
+ * when ESE is enabled on DUT through ini and it is also
+ * advertised by the peer AP to which we are trying to
+ * associate to.
+ */
+ if (pe_session->is_ese_version_ie_present &&
+ mac_ctx->roam.configParam.isEseIniFeatureEnabled)
+ populate_dot11f_ese_version(&frm.ESEVersion);
+ /* For ESE Associations fill the ESE IEs */
+ if (pe_session->isESEconnection &&
+ pe_session->pLimReAssocReq->isESEFeatureIniEnabled) {
+#ifndef FEATURE_DISABLE_RM
+ populate_dot11f_ese_rad_mgmt_cap(&frm.ESERadMgmtCap);
+#endif
+ }
+#endif /* FEATURE_WLAN_ESE */
+#endif /* FEATURE_WLAN_ESE || FEATURE_WLAN_LFR */
+
+ /* include WME EDCA IE as well */
+ if (wme_enabled) {
+ populate_dot11f_wmm_info_station_per_session(mac_ctx,
+ pe_session, &frm.WMMInfoStation);
+ if (wsm_enabled)
+ populate_dot11f_wmm_caps(&frm.WMMCaps);
+#ifdef FEATURE_WLAN_ESE
+ if (pe_session->isESEconnection) {
+ uint32_t phymode;
+ uint8_t rate;
+
+ populate_dot11f_re_assoc_tspec(mac_ctx, &frm,
+ pe_session);
+
+ /*
+ * Populate the TSRS IE if TSPEC is included in
+ * the reassoc request
+ */
+ lim_get_phy_mode(mac_ctx, &phymode, pe_session);
+ if (phymode == WNI_CFG_PHY_MODE_11G ||
+ phymode == WNI_CFG_PHY_MODE_11A)
+ rate = TSRS_11AG_RATE_6MBPS;
+ else
+ rate = TSRS_11B_RATE_5_5MBPS;
+
+ if (pe_session->pLimReAssocReq->eseTspecInfo.
+ numTspecs) {
+ tSirMacESETSRSIE tsrs_ie;
+
+ tsrs_ie.tsid = 0;
+ tsrs_ie.rates[0] = rate;
+ populate_dot11_tsrsie(mac_ctx, &tsrs_ie,
+ &frm.ESETrafStrmRateSet,
+ sizeof(uint8_t));
+ }
+ }
+#endif
+ }
+
+ ft_sme_context = &mac_ctx->roam.roamSession[sme_sessionid].ftSmeContext;
+ if (pe_session->htCapability &&
+ mac_ctx->lim.htCapabilityPresentInBeacon) {
+ populate_dot11f_ht_caps(mac_ctx, pe_session, &frm.HTCaps);
+ }
+#if defined WLAN_FEATURE_VOWIFI_11R
+ if (pe_session->pLimReAssocReq->bssDescription.mdiePresent &&
+ (ft_sme_context->addMDIE == true)
+#if defined FEATURE_WLAN_ESE
+ && !pe_session->isESEconnection
+#endif
+ ) {
+ populate_mdie(mac_ctx, &frm.MobilityDomain,
+ pe_session->pLimReAssocReq->bssDescription.mdie);
+ }
+#endif
+
+#ifdef WLAN_FEATURE_11AC
+ if (pe_session->vhtCapability &&
+ pe_session->vhtCapabilityPresentInBeacon) {
+ lim_log(mac_ctx, LOG1,
+ FL("Populate VHT IEs in Re-Assoc Request"));
+ populate_dot11f_vht_caps(mac_ctx, pe_session, &frm.VHTCaps);
+ vht_enabled = true;
+ populate_dot11f_ext_cap(mac_ctx, vht_enabled, &frm.ExtCap,
+ pe_session);
+ }
+ if (!vht_enabled &&
+ pe_session->is_vendor_specific_vhtcaps) {
+ lim_log(mac_ctx, LOG1,
+ FL("Populate Vendor VHT IEs in Re-Assoc Request"));
+ frm.vendor2_ie.present = 1;
+ frm.vendor2_ie.type =
+ pe_session->vendor_specific_vht_ie_type;
+ frm.vendor2_ie.sub_type =
+ pe_session->vendor_specific_vht_ie_sub_type;
+ frm.vendor2_ie.VHTCaps.present = 1;
+ populate_dot11f_vht_caps(mac_ctx, pe_session,
+ &frm.vendor2_ie.VHTCaps);
+ vht_enabled = true;
+ }
+#endif
+
+ status = dot11f_get_packed_re_assoc_request_size(mac_ctx, &frm,
+ &payload);
+ if (DOT11F_FAILED(status)) {
+ lim_log(mac_ctx, LOGP,
+ FL("Failure in size calculation (0x%08x)."), status);
+ /* We'll fall back on the worst case scenario: */
+ payload = sizeof(tDot11fReAssocRequest);
+ } else if (DOT11F_WARNED(status)) {
+ lim_log(mac_ctx, LOGW,
+ FL("Warnings in size calculation(0x%08x)."), status);
+ }
+
+ bytes = payload + sizeof(tSirMacMgmtHdr) + add_ie_len;
+
+#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG
+ lim_log(mac_ctx, LOG1, FL("FT IE Reassoc Req (%d)."),
+ ft_sme_context->reassoc_ft_ies_length);
+#endif
+
+#if defined WLAN_FEATURE_VOWIFI_11R
+ if (pe_session->is11Rconnection)
+ ft_ies_length = ft_sme_context->reassoc_ft_ies_length;
+#endif
+
+ cdf_status = cds_packet_alloc((uint16_t) bytes + ft_ies_length,
+ (void **)&frame, (void **)&packet);
+ if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
+ pe_session->limMlmState = pe_session->limPrevMlmState;
+ MTRACE(cdf_trace(CDF_MODULE_ID_PE, TRACE_CODE_MLM_STATE,
+ pe_session->peSessionId,
+ pe_session->limMlmState));
+ lim_log(mac_ctx, LOGP, FL("Failed to alloc memory %d"), bytes);
+ goto end;
+ }
+ /* Paranoia: */
+ cdf_mem_set(frame, bytes + ft_ies_length, 0);
+
+#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG || defined FEATURE_WLAN_ESE || defined(FEATURE_WLAN_LFR)
+ lim_print_mac_addr(mac_ctx, pe_session->limReAssocbssId, LOG1);
+#endif
+ /* Next, we fill out the buffer descriptor: */
+ lim_populate_mac_header(mac_ctx, frame, SIR_MAC_MGMT_FRAME,
+ SIR_MAC_MGMT_REASSOC_REQ, pe_session->limReAssocbssId,
+ pe_session->selfMacAddr);
+ mac_hdr = (tpSirMacMgmtHdr) frame;
+ /* That done, pack the ReAssoc Request: */
+ status = dot11f_pack_re_assoc_request(mac_ctx, &frm, frame +
+ sizeof(tSirMacMgmtHdr),
+ payload, &payload);
+ if (DOT11F_FAILED(status)) {
+ lim_log(mac_ctx, LOGE, FL("Failure in pack (0x%08x)."), status);
+ cds_packet_free((void *)packet);
+ goto end;
+ } else if (DOT11F_WARNED(status)) {
+ lim_log(mac_ctx, LOGW, FL("Warnings in pack (0x%08x)."),
+ status);
+ }
+
+ lim_log(mac_ctx, LOG3,
+ FL("*** Sending Re-Assoc Request length %d %d to "),
+ bytes, payload);
+
+ if (pe_session->assocReq != NULL) {
+ cdf_mem_free(pe_session->assocReq);
+ pe_session->assocReq = NULL;
+ }
+
+ if (add_ie_len) {
+ cdf_mem_copy(frame + sizeof(tSirMacMgmtHdr) + payload,
+ add_ie, add_ie_len);
+ payload += add_ie_len;
+ }
+
+ pe_session->assocReq = cdf_mem_malloc(payload);
+ if (NULL == pe_session->assocReq) {
+ lim_log(mac_ctx, LOGE, FL("Failed to alloc memory"));
+ } else {
+ /*
+ * Store the Assoc request. This is sent to csr/hdd in
+ * join cnf response.
+ */
+ cdf_mem_copy(pe_session->assocReq,
+ frame + sizeof(tSirMacMgmtHdr), payload);
+ pe_session->assocReqLen = payload;
+ }
+
+ if (pe_session->is11Rconnection && ft_sme_context->reassoc_ft_ies) {
+ int i = 0;
+
+ body = frame + bytes;
+ for (i = 0; i < ft_ies_length; i++) {
+ *body = ft_sme_context->reassoc_ft_ies[i];
+ body++;
+ }
+ }
+#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG
+ PELOGE(lim_log(mac_ctx, LOG1, FL("Re-assoc Req Frame is: "));
+ sir_dump_buf(mac_ctx, SIR_LIM_MODULE_ID, LOG1,
+ (uint8_t *) frame, (bytes + ft_ies_length));
+ )
+#endif
+ if ((SIR_BAND_5_GHZ ==
+ lim_get_rf_band(pe_session->currentOperChannel)) ||
+ (pe_session->pePersona == CDF_P2P_CLIENT_MODE) ||
+ (pe_session->pePersona == CDF_P2P_GO_MODE)) {
+ tx_flag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME;
+ }
+
+ if (NULL != pe_session->assocReq) {
+ cdf_mem_free(pe_session->assocReq);
+ pe_session->assocReq = NULL;
+ }
+
+ pe_session->assocReq = cdf_mem_malloc(ft_ies_length);
+ if (NULL == pe_session->assocReq) {
+ lim_log(mac_ctx, LOGE, FL("Failed to alloc memory"));
+ pe_session->assocReqLen = 0;
+ } else {
+ /*
+ * Store the Assoc request. This is sent to csr/hdd in
+ * join cnf response.
+ */
+ cdf_mem_copy(pe_session->assocReq,
+ ft_sme_context->reassoc_ft_ies, (ft_ies_length));
+ pe_session->assocReqLen = (ft_ies_length);
+ }
+
+#ifdef FEATURE_WLAN_DIAG_SUPPORT
+ lim_diag_event_report(mac_ctx, WLAN_PE_DIAG_REASSOC_START_EVENT,
+ pe_session, eSIR_SUCCESS, eSIR_SUCCESS);
+#endif
+ MTRACE(cdf_trace(CDF_MODULE_ID_PE, TRACE_CODE_TX_MGMT,
+ pe_session->peSessionId, mac_hdr->fc.subType));
+ cdf_status = wma_tx_frame(mac_ctx, packet,
+ (uint16_t) (bytes + ft_ies_length),
+ TXRX_FRM_802_11_MGMT, ANI_TXDIR_TODS, 7,
+ lim_tx_complete, frame, tx_flag, sme_sessionid,
+ 0);
+ MTRACE(cdf_trace(CDF_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE,
+ pe_session->peSessionId, cdf_status));
+ if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
+ lim_log(mac_ctx, LOGE,
+ FL("Failed to send Re-Assoc Request (%X)!"),
+ cdf_status);
+ }
+
+end:
+ /* Free up buffer allocated for mlmAssocReq */
+ cdf_mem_free(mlm_reassoc_req);
+ pe_session->pLimMlmReassocReq = NULL;
+
+}
+
+void lim_send_retry_reassoc_req_frame(tpAniSirGlobal pMac,
+ tLimMlmReassocReq *pMlmReassocReq,
+ tpPESession psessionEntry)
+{
+ tLimMlmReassocCnf mlmReassocCnf; /* keep sme */
+ tLimMlmReassocReq *pTmpMlmReassocReq = NULL;
+ if (NULL == pTmpMlmReassocReq) {
+ pTmpMlmReassocReq = cdf_mem_malloc(sizeof(tLimMlmReassocReq));
+ if (NULL == pTmpMlmReassocReq)
+ goto end;
+ cdf_mem_set(pTmpMlmReassocReq, sizeof(tLimMlmReassocReq), 0);
+ cdf_mem_copy(pTmpMlmReassocReq, pMlmReassocReq,
+ sizeof(tLimMlmReassocReq));
+ }
+ /* Prepare and send Reassociation request frame */
+ /* start reassoc timer. */
+ pMac->lim.limTimers.gLimReassocFailureTimer.sessionId =
+ psessionEntry->peSessionId;
+ /* Start reassociation failure timer */
+ MTRACE(cdf_trace(CDF_MODULE_ID_PE, TRACE_CODE_TIMER_ACTIVATE,
+ psessionEntry->peSessionId, eLIM_REASSOC_FAIL_TIMER));
+ if (tx_timer_activate(&pMac->lim.limTimers.gLimReassocFailureTimer)
+ != TX_SUCCESS) {
+ /* Could not start reassoc failure timer. */
+ /* Log error */
+ lim_log(pMac, LOGP,
+ FL("could not start Reassociation failure timer"));
+ /* Return Reassoc confirm with */
+ /* Resources Unavailable */
+ mlmReassocCnf.resultCode = eSIR_SME_RESOURCES_UNAVAILABLE;
+ mlmReassocCnf.protStatusCode = eSIR_MAC_UNSPEC_FAILURE_STATUS;
+ goto end;
+ }
+
+ lim_send_reassoc_req_with_ft_ies_mgmt_frame(pMac, pTmpMlmReassocReq,
+ psessionEntry);
+ return;
+
+end:
+ /* Free up buffer allocated for reassocReq */
+ if (pMlmReassocReq != NULL) {
+ cdf_mem_free(pMlmReassocReq);
+ pMlmReassocReq = NULL;
+ }
+ if (pTmpMlmReassocReq != NULL) {
+ cdf_mem_free(pTmpMlmReassocReq);
+ pTmpMlmReassocReq = NULL;
+ }
+ mlmReassocCnf.resultCode = eSIR_SME_FT_REASSOC_FAILURE;
+ mlmReassocCnf.protStatusCode = eSIR_MAC_UNSPEC_FAILURE_STATUS;
+ /* Update PE sessio Id */
+ mlmReassocCnf.sessionId = psessionEntry->peSessionId;
+
+ lim_post_sme_message(pMac, LIM_MLM_REASSOC_CNF,
+ (uint32_t *) &mlmReassocCnf);
+}
+
+#endif /* WLAN_FEATURE_VOWIFI_11R */
+
+void
+lim_send_reassoc_req_mgmt_frame(tpAniSirGlobal pMac,
+ tLimMlmReassocReq *pMlmReassocReq,
+ tpPESession psessionEntry)
+{
+ static tDot11fReAssocRequest frm;
+ uint16_t caps;
+ uint8_t *pFrame;
+ uint32_t nBytes, nPayload, nStatus;
+ uint8_t fQosEnabled, fWmeEnabled, fWsmEnabled;
+ void *pPacket;
+ CDF_STATUS cdf_status;
+ uint16_t nAddIELen;
+ uint8_t *pAddIE;
+ uint8_t *wpsIe = NULL;
+ uint8_t txFlag = 0;
+#if defined WLAN_FEATURE_VOWIFI
+ uint8_t PowerCapsPopulated = false;
+#endif
+ uint8_t smeSessionId = 0;
+ bool isVHTEnabled = false;
+ tpSirMacMgmtHdr pMacHdr;
+
+ if (NULL == psessionEntry) {
+ return;
+ }
+
+ smeSessionId = psessionEntry->smeSessionId;
+
+ /* check this early to avoid unncessary operation */
+ if (NULL == psessionEntry->pLimReAssocReq) {
+ return;
+ }
+ nAddIELen = psessionEntry->pLimReAssocReq->addIEAssoc.length;
+ pAddIE = psessionEntry->pLimReAssocReq->addIEAssoc.addIEdata;
+
+ cdf_mem_set((uint8_t *) &frm, sizeof(frm), 0);
+
+ caps = pMlmReassocReq->capabilityInfo;
+#if defined(FEATURE_WLAN_WAPI)
+ /* CR: 262463 :
+ According to WAPI standard:
+ 7.3.1.4 Capability Information field
+ In WAPI, non-AP STAs within an ESS set the Privacy subfield to 0 in transmitted
+ Association or Reassociation management frames. APs ignore the Privacy subfield within received Association and
+ Reassociation management frames. */
+ if (psessionEntry->encryptType == eSIR_ED_WPI)
+ ((tSirMacCapabilityInfo *) &caps)->privacy = 0;
+#endif
+ swap_bit_field16(caps, (uint16_t *) &frm.Capabilities);
+
+ frm.ListenInterval.interval = pMlmReassocReq->listenInterval;
+
+ cdf_mem_copy((uint8_t *) frm.CurrentAPAddress.mac,
+ (uint8_t *) psessionEntry->bssId, 6);
+
+ populate_dot11f_ssid2(pMac, &frm.SSID);
+ populate_dot11f_supp_rates(pMac, POPULATE_DOT11F_RATES_OPERATIONAL,
+ &frm.SuppRates, psessionEntry);
+
+ fQosEnabled = (psessionEntry->limQosEnabled) &&
+ SIR_MAC_GET_QOS(psessionEntry->limReassocBssCaps);
+
+ fWmeEnabled = (psessionEntry->limWmeEnabled) &&
+ LIM_BSS_CAPS_GET(WME, psessionEntry->limReassocBssQosCaps);
+
+ fWsmEnabled = (psessionEntry->limWsmEnabled) && fWmeEnabled &&
+ LIM_BSS_CAPS_GET(WSM, psessionEntry->limReassocBssQosCaps);
+
+ if (psessionEntry->lim11hEnable &&
+ psessionEntry->pLimReAssocReq->spectrumMgtIndicator == eSIR_TRUE) {
+#if defined WLAN_FEATURE_VOWIFI
+ PowerCapsPopulated = true;
+ populate_dot11f_power_caps(pMac, &frm.PowerCaps, LIM_REASSOC,
+ psessionEntry);
+ populate_dot11f_supp_channels(pMac, &frm.SuppChannels, LIM_REASSOC,
+ psessionEntry);
+#endif
+ }
+#if defined WLAN_FEATURE_VOWIFI
+ if (pMac->rrm.rrmPEContext.rrmEnable &&
+ SIR_MAC_GET_RRM(psessionEntry->limCurrentBssCaps)) {
+ if (PowerCapsPopulated == false) {
+ PowerCapsPopulated = true;
+ populate_dot11f_power_caps(pMac, &frm.PowerCaps,
+ LIM_REASSOC, psessionEntry);
+ }
+ }
+#endif
+
+ if (fQosEnabled)
+ populate_dot11f_qos_caps_station(pMac, &frm.QOSCapsStation);
+
+ populate_dot11f_ext_supp_rates(pMac, POPULATE_DOT11F_RATES_OPERATIONAL,
+ &frm.ExtSuppRates, psessionEntry);
+
+#if defined WLAN_FEATURE_VOWIFI
+ if (pMac->rrm.rrmPEContext.rrmEnable &&
+ SIR_MAC_GET_RRM(psessionEntry->limReassocBssCaps)) {
+ populate_dot11f_rrm_ie(pMac, &frm.RRMEnabledCap, psessionEntry);
+ }
+#endif
+ /* The join request *should* contain zero or one of the WPA and RSN */
+ /* IEs. The payload send along with the request is a */
+ /* 'tSirSmeJoinReq'; the IE portion is held inside a 'tSirRSNie': */
+
+ /* typedef struct sSirRSNie */
+ /* { */
+ /* uint16_t length; */
+ /* uint8_t rsnIEdata[SIR_MAC_MAX_IE_LENGTH+2]; */
+ /* } tSirRSNie, *tpSirRSNie; */
+
+ /* So, we should be able to make the following two calls harmlessly, */
+ /* since they do nothing if they don't find the given IE in the */
+ /* bytestream with which they're provided. */
+
+ /* The net effect of this will be to faithfully transmit whatever */
+ /* security IE is in the join request. */
+
+ /**However*, if we're associating for the purpose of WPS */
+ /* enrollment, and we've been configured to indicate that by */
+ /* eliding the WPA or RSN IE, we just skip this: */
+ if (nAddIELen && pAddIE) {
+ wpsIe = limGetWscIEPtr(pMac, pAddIE, nAddIELen);
+ }
+ if (NULL == wpsIe) {
+ populate_dot11f_rsn_opaque(pMac,
+ &(psessionEntry->pLimReAssocReq->rsnIE),
+ &frm.RSNOpaque);
+ populate_dot11f_wpa_opaque(pMac,
+ &(psessionEntry->pLimReAssocReq->rsnIE),
+ &frm.WPAOpaque);
+#if defined(FEATURE_WLAN_WAPI)
+ populate_dot11f_wapi_opaque(pMac,
+ &(psessionEntry->pLimReAssocReq->
+ rsnIE), &frm.WAPIOpaque);
+#endif /* defined(FEATURE_WLAN_WAPI) */
+ }
+ /* include WME EDCA IE as well */
+ if (fWmeEnabled) {
+ populate_dot11f_wmm_info_station_per_session(pMac,
+ psessionEntry,
+ &frm.WMMInfoStation);
+
+ if (fWsmEnabled)
+ populate_dot11f_wmm_caps(&frm.WMMCaps);
+ }
+
+ if (psessionEntry->htCapability &&
+ pMac->lim.htCapabilityPresentInBeacon) {
+ populate_dot11f_ht_caps(pMac, psessionEntry, &frm.HTCaps);
+ }
+#ifdef WLAN_FEATURE_11AC
+ if (psessionEntry->vhtCapability &&
+ psessionEntry->vhtCapabilityPresentInBeacon) {
+ lim_log(pMac, LOGW, FL("Populate VHT IEs in Re-Assoc Request"));
+ populate_dot11f_vht_caps(pMac, psessionEntry, &frm.VHTCaps);
+ isVHTEnabled = true;
+ }
+#endif
+
+ populate_dot11f_ext_cap(pMac, isVHTEnabled, &frm.ExtCap, psessionEntry);
+
+ nStatus = dot11f_get_packed_re_assoc_request_size(pMac, &frm, &nPayload);
+ if (DOT11F_FAILED(nStatus)) {
+ lim_log(pMac, LOGP, FL("Failed to calculate the packed size f"
+ "or a Re-Association Request (0x%08x)."),
+ nStatus);
+ /* We'll fall back on the worst case scenario: */
+ nPayload = sizeof(tDot11fReAssocRequest);
+ } else if (DOT11F_WARNED(nStatus)) {
+ lim_log(pMac, LOGW, FL("There were warnings while calculating "
+ "the packed size for a Re-Association Re "
+ "quest(0x%08x)."), nStatus);
+ }
+
+ nBytes = nPayload + sizeof(tSirMacMgmtHdr) + nAddIELen;
+
+ cdf_status = cds_packet_alloc((uint16_t) nBytes, (void **)&pFrame,
+ (void **)&pPacket);
+ if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
+ psessionEntry->limMlmState = psessionEntry->limPrevMlmState;
+ MTRACE(cdf_trace(CDF_MODULE_ID_PE, TRACE_CODE_MLM_STATE,
+ psessionEntry->peSessionId,
+ psessionEntry->limMlmState));
+ lim_log(pMac, LOGP,
+ FL("Failed to allocate %d bytes for a Re-As"
+ "sociation Request."), nBytes);
+ goto end;
+ }
+ /* Paranoia: */
+ cdf_mem_set(pFrame, nBytes, 0);
+
+ /* Next, we fill out the buffer descriptor: */
+ lim_populate_mac_header(pMac, pFrame, SIR_MAC_MGMT_FRAME,
+ SIR_MAC_MGMT_REASSOC_REQ, psessionEntry->limReAssocbssId,
+ psessionEntry->selfMacAddr);
+ pMacHdr = (tpSirMacMgmtHdr) pFrame;
+
+ /* That done, pack the Probe Request: */
+ nStatus = dot11f_pack_re_assoc_request(pMac, &frm, pFrame +
+ sizeof(tSirMacMgmtHdr),
+ nPayload, &nPayload);
+ if (DOT11F_FAILED(nStatus)) {
+ lim_log(pMac, LOGE, FL("Failed to pack a Re-Association Reque"
+ "st (0x%08x)."), nStatus);
+ cds_packet_free((void *)pPacket);
+ goto end;
+ } else if (DOT11F_WARNED(nStatus)) {
+ lim_log(pMac, LOGW, FL("There were warnings while packing a R"
+ "e-Association Request (0x%08x)."),
+ nStatus);
+ }
+
+ PELOG1(lim_log
+ (pMac, LOG1,
+ FL("*** Sending Re-Association Request length %d" "to "),
+ nBytes);
+ )
+
+ if (psessionEntry->assocReq != NULL) {
+ cdf_mem_free(psessionEntry->assocReq);
+ psessionEntry->assocReq = NULL;
+ }
+
+ if (nAddIELen) {
+ cdf_mem_copy(pFrame + sizeof(tSirMacMgmtHdr) + nPayload,
+ pAddIE, nAddIELen);
+ nPayload += nAddIELen;
+ }
+
+ psessionEntry->assocReq = cdf_mem_malloc(nPayload);
+ if (NULL == psessionEntry->assocReq) {
+ PELOGE(lim_log
+ (pMac, LOGE,
+ FL("Unable to allocate memory to store assoc request"));
+ )
+ } else {
+ /* Store the Assoc request. This is sent to csr/hdd in join cnf response. */
+ cdf_mem_copy(psessionEntry->assocReq,
+ pFrame + sizeof(tSirMacMgmtHdr), nPayload);
+ psessionEntry->assocReqLen = nPayload;
+ }
+
+ if ((SIR_BAND_5_GHZ == lim_get_rf_band(psessionEntry->currentOperChannel))
+ || (psessionEntry->pePersona == CDF_P2P_CLIENT_MODE) ||
+ (psessionEntry->pePersona == CDF_P2P_GO_MODE)
+ ) {
+ txFlag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME;
+ }
+
+ if (psessionEntry->pePersona == CDF_P2P_CLIENT_MODE) {
+ txFlag |= HAL_USE_PEER_STA_REQUESTED_MASK;
+ }
+
+#ifdef FEATURE_WLAN_DIAG_SUPPORT
+ lim_diag_event_report(pMac, WLAN_PE_DIAG_REASSOC_START_EVENT,
+ psessionEntry, eSIR_SUCCESS, eSIR_SUCCESS);
+#endif
+ MTRACE(cdf_trace(CDF_MODULE_ID_PE, TRACE_CODE_TX_MGMT,
+ psessionEntry->peSessionId, pMacHdr->fc.subType));
+ cdf_status =
+ wma_tx_frame(pMac, pPacket,
+ (uint16_t) (sizeof(tSirMacMgmtHdr) + nPayload),
+ TXRX_FRM_802_11_MGMT, ANI_TXDIR_TODS, 7,
+ lim_tx_complete, pFrame, txFlag, smeSessionId, 0);
+ MTRACE(cdf_trace
+ (CDF_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE,
+ psessionEntry->peSessionId, cdf_status));
+ if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
+ lim_log(pMac, LOGE,
+ FL("Failed to send Re-Association Request (%X)!"),
+ cdf_status);
+ /* Pkt will be freed up by the callback */
+ }
+
+end:
+ /* Free up buffer allocated for mlmAssocReq */
+ cdf_mem_free(pMlmReassocReq);
+ psessionEntry->pLimMlmReassocReq = NULL;
+
+} /* lim_send_reassoc_req_mgmt_frame */
+
+/**
+ * lim_send_auth_mgmt_frame() - Send an Authentication frame
+ *
+ * @mac_ctx: Pointer to Global MAC structure
+ * @auth_frame: Pointer to Authentication frame structure
+ * @peer_addr: MAC address of destination peer
+ * @wep_bit: wep bit in frame control for Authentication frame3
+ * @session: PE session information
+ *
+ * This function is called by lim_process_mlm_messages(). Authentication frame
+ * is formatted and sent when this function is called.
+ *
+ * Return: void
+ */
+
+void
+lim_send_auth_mgmt_frame(tpAniSirGlobal mac_ctx,
+ tpSirMacAuthFrameBody auth_frame,
+ tSirMacAddr peer_addr,
+ uint8_t wep_bit, tpPESession session)
+{
+ uint8_t *frame, *body;
+ uint32_t frame_len = 0, body_len = 0;
+ tpSirMacMgmtHdr mac_hdr;
+ void *packet;
+ CDF_STATUS cdf_status;
+ uint8_t tx_flag = 0;
+ uint8_t sme_sessionid = 0;
+ uint16_t ft_ies_length = 0;
+
+ if (NULL == session) {
+ lim_log(mac_ctx, LOGE, FL("Error: psession Entry is NULL"));
+ return;
+ }
+
+ sme_sessionid = session->smeSessionId;
+
+ lim_log(mac_ctx, LOG1,
+ FL("Sending Auth seq# %d status %d (%d) to " MAC_ADDRESS_STR),
+ auth_frame->authTransactionSeqNumber,
+ auth_frame->authStatusCode,
+ (auth_frame->authStatusCode == eSIR_MAC_SUCCESS_STATUS),
+ MAC_ADDR_ARRAY(peer_addr));
+
+ switch (auth_frame->authTransactionSeqNumber) {
+ case SIR_MAC_AUTH_FRAME_1:
+ /*
+ * Allocate buffer for Authenticaton frame of size
+ * equal to management frame header length plus 2 bytes
+ * each for auth algorithm number, transaction number
+ * and status code.
+ */
+
+ frame_len = sizeof(tSirMacMgmtHdr) +
+ SIR_MAC_AUTH_CHALLENGE_OFFSET;
+ body_len = SIR_MAC_AUTH_CHALLENGE_OFFSET;
+
+#if defined WLAN_FEATURE_VOWIFI_11R
+ if (auth_frame->authAlgoNumber == eSIR_FT_AUTH) {
+ if (NULL != session->ftPEContext.pFTPreAuthReq &&
+ 0 != session->ftPEContext.pFTPreAuthReq->
+ ft_ies_length) {
+ ft_ies_length = session->ftPEContext.
+ pFTPreAuthReq->ft_ies_length;
+ frame_len += ft_ies_length;
+ lim_log(mac_ctx, LOG3,
+ FL("Auth frame, FTIES length added=%d"),
+ ft_ies_length);
+ } else {
+ lim_log(mac_ctx, LOG3,
+ FL("Auth frame, Does not contain FTIES!!!"));
+ frame_len += (2 + SIR_MDIE_SIZE);
+ }
+ }
+#endif
+ break;
+
+ case SIR_MAC_AUTH_FRAME_2:
+ if ((auth_frame->authAlgoNumber == eSIR_OPEN_SYSTEM) ||
+ ((auth_frame->authAlgoNumber == eSIR_SHARED_KEY) &&
+ (auth_frame->authStatusCode !=
+ eSIR_MAC_SUCCESS_STATUS))) {
+ /*
+ * Allocate buffer for Authenticaton frame of size
+ * equal to management frame header length plus
+ * 2 bytes each for auth algorithm number,
+ * transaction number and status code.
+ */
+
+ frame_len = sizeof(tSirMacMgmtHdr) +
+ SIR_MAC_AUTH_CHALLENGE_OFFSET;
+ body_len = SIR_MAC_AUTH_CHALLENGE_OFFSET;
+ } else {
+ /*
+ * Shared Key algorithm with challenge text
+ * to be sent.
+ *
+ * Allocate buffer for Authenticaton frame of size
+ * equal to management frame header length plus
+ * 2 bytes each for auth algorithm number,
+ * transaction number, status code and 128 bytes
+ * for challenge text.
+ */
+
+ frame_len = sizeof(tSirMacMgmtHdr) +
+ sizeof(tSirMacAuthFrame);
+ body_len = sizeof(tSirMacAuthFrameBody);
+ }
+ break;
+
+ case SIR_MAC_AUTH_FRAME_3:
+ if (wep_bit == LIM_WEP_IN_FC) {
+ /*
+ * Auth frame3 to be sent with encrypted framebody
+ *
+ * Allocate buffer for Authenticaton frame of size
+ * equal to management frame header length plus 2 bytes
+ * each for auth algorithm number, transaction number,
+ * status code, 128 bytes for challenge text and
+ * 4 bytes each for IV & ICV.
+ */
+
+ frame_len = sizeof(tSirMacMgmtHdr) +
+ LIM_ENCR_AUTH_BODY_LEN;
+ body_len = LIM_ENCR_AUTH_BODY_LEN;
+ } else {
+
+ /*
+ * Auth frame3 to be sent without encrypted framebody
+ *
+ * Allocate buffer for Authenticaton frame of size equal
+ * to management frame header length plus 2 bytes each
+ * for auth algorithm number, transaction number and
+ * status code.
+ */
+
+ frame_len = sizeof(tSirMacMgmtHdr) +
+ SIR_MAC_AUTH_CHALLENGE_OFFSET;
+ body_len = SIR_MAC_AUTH_CHALLENGE_OFFSET;
+ }
+ break;
+
+ case SIR_MAC_AUTH_FRAME_4:
+ /*
+ * Allocate buffer for Authenticaton frame of size equal
+ * to management frame header length plus 2 bytes each
+ * for auth algorithm number, transaction number and
+ * status code.
+ */
+
+ frame_len = sizeof(tSirMacMgmtHdr) +
+ SIR_MAC_AUTH_CHALLENGE_OFFSET;
+ body_len = SIR_MAC_AUTH_CHALLENGE_OFFSET;
+
+ break;
+ } /* switch (auth_frame->authTransactionSeqNumber) */
+
+ cdf_status = cds_packet_alloc((uint16_t) frame_len, (void **)&frame,
+ (void **)&packet);
+
+ if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
+ lim_log(mac_ctx, LOGP,
+ FL("call to bufAlloc failed for AUTH frame"));
+ return;
+ }
+
+ cdf_mem_zero(frame, frame_len);
+
+ /* Prepare BD */
+ lim_populate_mac_header(mac_ctx, frame, SIR_MAC_MGMT_FRAME,
+ SIR_MAC_MGMT_AUTH, peer_addr, session->selfMacAddr);
+ mac_hdr = (tpSirMacMgmtHdr) frame;
+ mac_hdr->fc.wep = wep_bit;
+
+ /* Prepare BSSId */
+ if (LIM_IS_AP_ROLE(session) ||
+ LIM_IS_BT_AMP_AP_ROLE(session))
+ cdf_mem_copy((uint8_t *) mac_hdr->bssId,
+ (uint8_t *) session->bssId,
+ sizeof(tSirMacAddr));
+
+ /* Prepare Authentication frame body */
+ body = frame + sizeof(tSirMacMgmtHdr);
+
+ if (wep_bit == LIM_WEP_IN_FC) {
+ cdf_mem_copy(body, (uint8_t *) auth_frame, body_len);
+
+ lim_log(mac_ctx, LOG1,
+ FL("*** Sending Auth seq# 3 status %d (%d) to"
+ MAC_ADDRESS_STR),
+ auth_frame->authStatusCode,
+ (auth_frame->authStatusCode == eSIR_MAC_SUCCESS_STATUS),
+ MAC_ADDR_ARRAY(mac_hdr->da));
+
+ } else {
+ *((uint16_t *) (body)) =
+ sir_swap_u16if_needed(auth_frame->authAlgoNumber);
+ body += sizeof(uint16_t);
+ body_len -= sizeof(uint16_t);
+
+ *((uint16_t *) (body)) =
+ sir_swap_u16if_needed(
+ auth_frame->authTransactionSeqNumber);
+ body += sizeof(uint16_t);
+ body_len -= sizeof(uint16_t);
+
+ *((uint16_t *) (body)) =
+ sir_swap_u16if_needed(auth_frame->authStatusCode);
+ body += sizeof(uint16_t);
+ body_len -= sizeof(uint16_t);
+ if (body_len <= (sizeof(auth_frame->type) +
+ sizeof(auth_frame->length) +
+ sizeof(auth_frame->challengeText)))
+ cdf_mem_copy(body, (uint8_t *) &auth_frame->type,
+ body_len);
+
+#if defined WLAN_FEATURE_VOWIFI_11R
+ if ((auth_frame->authAlgoNumber == eSIR_FT_AUTH) &&
+ (auth_frame->authTransactionSeqNumber ==
+ SIR_MAC_AUTH_FRAME_1) &&
+ (session->ftPEContext.pFTPreAuthReq != NULL)) {
+
+ if (ft_ies_length > 0) {
+ cdf_mem_copy(body,
+ session->ftPEContext.
+ pFTPreAuthReq->ft_ies,
+ ft_ies_length);
+#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG
+ lim_log(mac_ctx, LOG2,
+ FL("Auth1 Frame FTIE is: "));
+ sir_dump_buf(mac_ctx, SIR_LIM_MODULE_ID, LOG2,
+ (uint8_t *) body,
+ ft_ies_length);
+#endif
+ } else if (NULL != session->ftPEContext.
+ pFTPreAuthReq->pbssDescription) {
+ /* MDID attr is 54 */
+ *body = SIR_MDIE_ELEMENT_ID;
+ body++;
+ *body = SIR_MDIE_SIZE;
+ body++;
+ cdf_mem_copy(body,
+ &session->ftPEContext.pFTPreAuthReq->
+ pbssDescription->mdie[0],
+ SIR_MDIE_SIZE);
+ }
+ }
+#endif
+
+ lim_log(mac_ctx, LOG1,
+ FL("*** Sending Auth seq# %d status %d (%d) to "
+ MAC_ADDRESS_STR),
+ auth_frame->authTransactionSeqNumber,
+ auth_frame->authStatusCode,
+ (auth_frame->authStatusCode ==
+ eSIR_MAC_SUCCESS_STATUS),
+ MAC_ADDR_ARRAY(mac_hdr->da));
+ }
+ sir_dump_buf(mac_ctx, SIR_LIM_MODULE_ID, LOG2, frame, frame_len);
+
+ if ((SIR_BAND_5_GHZ == lim_get_rf_band(session->currentOperChannel))
+ || (session->pePersona == CDF_P2P_CLIENT_MODE)
+ || (session->pePersona == CDF_P2P_GO_MODE)
+#if defined(WLAN_FEATURE_VOWIFI_11R) || defined(FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
+ || ((NULL != session->ftPEContext.pFTPreAuthReq) &&
+ (SIR_BAND_5_GHZ ==
+ lim_get_rf_band(session->ftPEContext.pFTPreAuthReq->
+ preAuthchannelNum)))
+#endif
+ )
+ tx_flag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME;
+
+
+ if (session->pePersona == CDF_P2P_CLIENT_MODE)
+ tx_flag |= HAL_USE_PEER_STA_REQUESTED_MASK;
+
+
+ MTRACE(cdf_trace(CDF_MODULE_ID_PE, TRACE_CODE_TX_MGMT,
+ session->peSessionId, mac_hdr->fc.subType));
+ /* Queue Authentication frame in high priority WQ */
+ cdf_status = wma_tx_frame(mac_ctx, packet, (uint16_t) frame_len,
+ TXRX_FRM_802_11_MGMT,
+ ANI_TXDIR_TODS, 7, lim_tx_complete,
+ frame, tx_flag, sme_sessionid, 0);
+ MTRACE(cdf_trace(CDF_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE,
+ session->peSessionId, cdf_status));
+ if (!CDF_IS_STATUS_SUCCESS(cdf_status))
+ lim_log(mac_ctx, LOGE,
+ FL("*** Could not send Auth frame, retCode=%X ***"),
+ cdf_status);
+
+ return;
+}
+
+CDF_STATUS lim_send_deauth_cnf(tpAniSirGlobal pMac)
+{
+ uint16_t aid;
+ tpDphHashNode pStaDs;
+ tLimMlmDeauthReq *pMlmDeauthReq;
+ tLimMlmDeauthCnf mlmDeauthCnf;
+ tpPESession psessionEntry;
+
+ pMlmDeauthReq = pMac->lim.limDisassocDeauthCnfReq.pMlmDeauthReq;
+ if (pMlmDeauthReq) {
+ if (tx_timer_running(&pMac->lim.limTimers.gLimDeauthAckTimer)) {
+ lim_deactivate_and_change_timer(pMac,
+ eLIM_DEAUTH_ACK_TIMER);
+ }
+
+ psessionEntry = pe_find_session_by_session_id(pMac,
+ pMlmDeauthReq->sessionId);
+ if (psessionEntry == NULL) {
+ PELOGE(lim_log(pMac, LOGE,
+ FL
+ ("session does not exist for given sessionId"));
+ )
+ mlmDeauthCnf.resultCode =
+ eSIR_SME_INVALID_PARAMETERS;
+ goto end;
+ }
+
+ pStaDs =
+ dph_lookup_hash_entry(pMac, pMlmDeauthReq->peerMacAddr, &aid,
+ &psessionEntry->dph.dphHashTable);
+ if (pStaDs == NULL) {
+ mlmDeauthCnf.resultCode = eSIR_SME_INVALID_PARAMETERS;
+ goto end;
+ }
+
+ /* / Receive path cleanup with dummy packet */
+ lim_ft_cleanup_pre_auth_info(pMac, psessionEntry);
+ lim_cleanup_rx_path(pMac, pStaDs, psessionEntry);
+ /* / Free up buffer allocated for mlmDeauthReq */
+ cdf_mem_free(pMlmDeauthReq);
+ pMac->lim.limDisassocDeauthCnfReq.pMlmDeauthReq = NULL;
+ }
+ return CDF_STATUS_SUCCESS;
+end:
+ cdf_mem_copy((uint8_t *) &mlmDeauthCnf.peerMacAddr,
+ (uint8_t *) pMlmDeauthReq->peerMacAddr,
+ sizeof(tSirMacAddr));
+ mlmDeauthCnf.deauthTrigger = pMlmDeauthReq->deauthTrigger;
+ mlmDeauthCnf.aid = pMlmDeauthReq->aid;
+ mlmDeauthCnf.sessionId = pMlmDeauthReq->sessionId;
+
+ /* Free up buffer allocated */
+ /* for mlmDeauthReq */
+ cdf_mem_free(pMlmDeauthReq);
+
+ lim_post_sme_message(pMac,
+ LIM_MLM_DEAUTH_CNF, (uint32_t *) &mlmDeauthCnf);
+ return CDF_STATUS_SUCCESS;
+}
+
+/**
+ * lim_send_disassoc_cnf() - Send disassoc confirmation to SME
+ *
+ * @mac_ctx: Handle to MAC context
+ *
+ * Sends disassoc confirmation to SME. Removes disassoc request stored
+ * in lim.
+ *
+ * Return: CDF_STATUS_SUCCESS
+ */
+
+CDF_STATUS lim_send_disassoc_cnf(tpAniSirGlobal mac_ctx)
+{
+ uint16_t aid;
+ tpDphHashNode sta_ds;
+ tLimMlmDisassocCnf disassoc_cnf;
+ tpPESession pe_session;
+ tLimMlmDisassocReq *disassoc_req;
+
+ disassoc_req = mac_ctx->lim.limDisassocDeauthCnfReq.pMlmDisassocReq;
+ if (disassoc_req) {
+ if (tx_timer_running(
+ &mac_ctx->lim.limTimers.gLimDisassocAckTimer))
+ lim_deactivate_and_change_timer(mac_ctx,
+ eLIM_DISASSOC_ACK_TIMER);
+
+ pe_session = pe_find_session_by_session_id(
+ mac_ctx, disassoc_req->sessionId);
+ if (pe_session == NULL) {
+ lim_log(mac_ctx, LOGE,
+ FL("No session for given sessionId"));
+ disassoc_cnf.resultCode =
+ eSIR_SME_INVALID_PARAMETERS;
+ goto end;
+ }
+
+ sta_ds = dph_lookup_hash_entry(mac_ctx,
+ disassoc_req->peerMacAddr, &aid,
+ &pe_session->dph.dphHashTable);
+ if (sta_ds == NULL) {
+ lim_log(mac_ctx, LOGE, FL("StaDs Null"));
+ disassoc_cnf.resultCode = eSIR_SME_INVALID_PARAMETERS;
+ goto end;
+ }
+ /* Receive path cleanup with dummy packet */
+ if (eSIR_SUCCESS !=
+ lim_cleanup_rx_path(mac_ctx, sta_ds, pe_session)) {
+ disassoc_cnf.resultCode =
+ eSIR_SME_RESOURCES_UNAVAILABLE;
+ lim_log(mac_ctx, LOGE, FL("cleanup_rx_path error"));
+ goto end;
+ }
+#ifdef WLAN_FEATURE_VOWIFI_11R
+ if (LIM_IS_STA_ROLE(pe_session) && (
+#ifdef FEATURE_WLAN_ESE
+ (pe_session->isESEconnection) ||
+#endif
+#ifdef FEATURE_WLAN_LFR
+ (pe_session->isFastRoamIniFeatureEnabled) ||
+#endif
+ (pe_session->is11Rconnection)) &&
+ (disassoc_req->reasonCode !=
+ eSIR_MAC_DISASSOC_DUE_TO_FTHANDOFF_REASON)) {
+ lim_log(mac_ctx, LOGE,
+ FL("FT Preauth Session (%p,%d) Clean up"),
+ pe_session, pe_session->peSessionId);
+
+#if defined WLAN_FEATURE_VOWIFI_11R
+ /* Delete FT session if there exists one */
+ lim_ft_cleanup_pre_auth_info(mac_ctx, pe_session);
+#endif
+ } else {
+ lim_log(mac_ctx, LOGE,
+ FL("No FT Preauth Session Clean up in role %d"
+#ifdef FEATURE_WLAN_ESE
+ " isESE %d"
+#endif
+#ifdef FEATURE_WLAN_LFR
+ " isLFR %d"
+#endif
+ " is11r %d reason %d"),
+ GET_LIM_SYSTEM_ROLE(pe_session),
+#ifdef FEATURE_WLAN_ESE
+ pe_session->isESEconnection,
+#endif
+#ifdef FEATURE_WLAN_LFR
+ pe_session->isFastRoamIniFeatureEnabled,
+#endif
+ pe_session->is11Rconnection,
+ disassoc_req->reasonCode);
+ }
+#endif
+ /* Free up buffer allocated for mlmDisassocReq */
+ cdf_mem_free(disassoc_req);
+ mac_ctx->lim.limDisassocDeauthCnfReq.pMlmDisassocReq = NULL;
+ return CDF_STATUS_SUCCESS;
+ } else {
+ return CDF_STATUS_SUCCESS;
+ }
+end:
+ cdf_mem_copy((uint8_t *) &disassoc_cnf.peerMacAddr,
+ (uint8_t *) disassoc_req->peerMacAddr,
+ sizeof(tSirMacAddr));
+ disassoc_cnf.aid = disassoc_req->aid;
+ disassoc_cnf.disassocTrigger = disassoc_req->disassocTrigger;
+
+ /* Update PE session ID */
+ disassoc_cnf.sessionId = disassoc_req->sessionId;
+
+ if (disassoc_req != NULL) {
+ /* / Free up buffer allocated for mlmDisassocReq */
+ cdf_mem_free(disassoc_req);
+ mac_ctx->lim.limDisassocDeauthCnfReq.pMlmDisassocReq = NULL;
+ }
+
+ lim_post_sme_message(mac_ctx, LIM_MLM_DISASSOC_CNF,
+ (uint32_t *) &disassoc_cnf);
+ return CDF_STATUS_SUCCESS;
+}
+
+CDF_STATUS lim_disassoc_tx_complete_cnf(tpAniSirGlobal pMac,
+ uint32_t txCompleteSuccess)
+{
+ return lim_send_disassoc_cnf(pMac);
+}
+
+CDF_STATUS lim_deauth_tx_complete_cnf(tpAniSirGlobal pMac,
+ uint32_t txCompleteSuccess)
+{
+ return lim_send_deauth_cnf(pMac);
+}
+
+/**
+ * \brief This function is called to send Disassociate frame.
+ *
+ *
+ * \param pMac Pointer to Global MAC structure
+ *
+ * \param nReason Indicates the reason that need to be sent in
+ * Disassociation frame
+ *
+ * \param peerMacAddr MAC address of the STA to which Disassociation frame is
+ * sent
+ *
+ *
+ */
+
+void
+lim_send_disassoc_mgmt_frame(tpAniSirGlobal pMac,
+ uint16_t nReason,
+ tSirMacAddr peer,
+ tpPESession psessionEntry, bool waitForAck)
+{
+ tDot11fDisassociation frm;
+ uint8_t *pFrame;
+ tpSirMacMgmtHdr pMacHdr;
+ uint32_t nBytes, nPayload, nStatus;
+ void *pPacket;
+ CDF_STATUS cdf_status;
+ uint8_t txFlag = 0;
+ uint32_t val = 0;
+ uint8_t smeSessionId = 0;
+ if (NULL == psessionEntry) {
+ return;
+ }
+
+ /*
+ * In case when cac timer is running for this SAP session then
+ * avoid sending disassoc out. It is violation of dfs specification.
+ */
+ if (((psessionEntry->pePersona == CDF_SAP_MODE) ||
+ (psessionEntry->pePersona == CDF_P2P_GO_MODE)) &&
+ (true == pMac->sap.SapDfsInfo.is_dfs_cac_timer_running)) {
+ CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO,
+ FL
+ ("CAC timer is running, drop disassoc from going out"));
+ return;
+ }
+ smeSessionId = psessionEntry->smeSessionId;
+
+ cdf_mem_set((uint8_t *) &frm, sizeof(frm), 0);
+
+ frm.Reason.code = nReason;
+
+ nStatus = dot11f_get_packed_disassociation_size(pMac, &frm, &nPayload);
+ if (DOT11F_FAILED(nStatus)) {
+ lim_log(pMac, LOGP, FL("Failed to calculate the packed size f"
+ "or a Disassociation (0x%08x)."),
+ nStatus);
+ /* We'll fall back on the worst case scenario: */
+ nPayload = sizeof(tDot11fDisassociation);
+ } else if (DOT11F_WARNED(nStatus)) {
+ lim_log(pMac, LOGW, FL("There were warnings while calculating "
+ "the packed size for a Disassociation "
+ "(0x%08x)."), nStatus);
+ }
+
+ nBytes = nPayload + sizeof(tSirMacMgmtHdr);
+
+ cdf_status = cds_packet_alloc((uint16_t) nBytes, (void **)&pFrame,
+ (void **)&pPacket);
+ if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
+ lim_log(pMac, LOGP, FL("Failed to allocate %d bytes for a Dis"
+ "association."), nBytes);
+ return;
+ }
+ /* Paranoia: */
+ cdf_mem_set(pFrame, nBytes, 0);
+
+ /* Next, we fill out the buffer descriptor: */
+ lim_populate_mac_header(pMac, pFrame, SIR_MAC_MGMT_FRAME,
+ SIR_MAC_MGMT_DISASSOC, peer, psessionEntry->selfMacAddr);
+ pMacHdr = (tpSirMacMgmtHdr) pFrame;
+
+ /* Prepare the BSSID */
+ sir_copy_mac_addr(pMacHdr->bssId, psessionEntry->bssId);
+
+#ifdef WLAN_FEATURE_11W
+ lim_set_protected_bit(pMac, psessionEntry, peer, pMacHdr);
+#endif
+
+ nStatus = dot11f_pack_disassociation(pMac, &frm, pFrame +
+ sizeof(tSirMacMgmtHdr),
+ nPayload, &nPayload);
+ if (DOT11F_FAILED(nStatus)) {
+ lim_log(pMac, LOGE,
+ FL("Failed to pack a Disassociation (0x%08x)."),
+ nStatus);
+ cds_packet_free((void *)pPacket);
+ return; /* allocated! */
+ } else if (DOT11F_WARNED(nStatus)) {
+ lim_log(pMac, LOGW, FL("There were warnings while packing a D"
+ "isassociation (0x%08x)."), nStatus);
+ }
+
+ lim_log(pMac, LOG1,
+ FL("***Sessionid %d Sending Disassociation frame with "
+ "reason %u and waitForAck %d to " MAC_ADDRESS_STR " ,From "
+ MAC_ADDRESS_STR), psessionEntry->peSessionId, nReason,
+ waitForAck, MAC_ADDR_ARRAY(pMacHdr->da),
+ MAC_ADDR_ARRAY(psessionEntry->selfMacAddr));
+
+ if ((SIR_BAND_5_GHZ == lim_get_rf_band(psessionEntry->currentOperChannel))
+ || (psessionEntry->pePersona == CDF_P2P_CLIENT_MODE) ||
+ (psessionEntry->pePersona == CDF_P2P_GO_MODE)
+ ) {
+ txFlag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME;
+ }
+
+ if ((psessionEntry->pePersona == CDF_P2P_CLIENT_MODE) ||
+ (psessionEntry->pePersona == CDF_P2P_GO_MODE)) {
+ txFlag |= HAL_USE_PEER_STA_REQUESTED_MASK;
+ }
+
+ if (waitForAck) {
+ MTRACE(cdf_trace(CDF_MODULE_ID_PE, TRACE_CODE_TX_MGMT,
+ psessionEntry->peSessionId,
+ pMacHdr->fc.subType));
+ /* Queue Disassociation frame in high priority WQ */
+ /* get the duration from the request */
+ cdf_status =
+ wma_tx_frameWithTxComplete(pMac, pPacket, (uint16_t) nBytes,
+ TXRX_FRM_802_11_MGMT,
+ ANI_TXDIR_TODS, 7, lim_tx_complete,
+ pFrame, lim_disassoc_tx_complete_cnf,
+ txFlag, smeSessionId, false, 0);
+ MTRACE(cdf_trace
+ (CDF_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE,
+ psessionEntry->peSessionId, cdf_status));
+
+ val = SYS_MS_TO_TICKS(LIM_DISASSOC_DEAUTH_ACK_TIMEOUT);
+
+ if (tx_timer_change
+ (&pMac->lim.limTimers.gLimDisassocAckTimer, val, 0)
+ != TX_SUCCESS) {
+ lim_log(pMac, LOGP,
+ FL("Unable to change Disassoc ack Timer val"));
+ return;
+ } else if (TX_SUCCESS !=
+ tx_timer_activate(&pMac->lim.limTimers.
+ gLimDisassocAckTimer)) {
+ lim_log(pMac, LOGP,
+ FL("Unable to activate Disassoc ack Timer"));
+ lim_deactivate_and_change_timer(pMac,
+ eLIM_DISASSOC_ACK_TIMER);
+ return;
+ }
+ } else {
+ MTRACE(cdf_trace(CDF_MODULE_ID_PE, TRACE_CODE_TX_MGMT,
+ psessionEntry->peSessionId,
+ pMacHdr->fc.subType));
+ /* Queue Disassociation frame in high priority WQ */
+ cdf_status = wma_tx_frame(pMac, pPacket, (uint16_t) nBytes,
+ TXRX_FRM_802_11_MGMT,
+ ANI_TXDIR_TODS,
+ 7,
+ lim_tx_complete, pFrame, txFlag,
+ smeSessionId, 0);
+ MTRACE(cdf_trace
+ (CDF_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE,
+ psessionEntry->peSessionId, cdf_status));
+ if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
+ lim_log(pMac, LOGE,
+ FL("Failed to send Disassociation (%X)!"),
+ cdf_status);
+ /* Pkt will be freed up by the callback */
+ }
+ }
+} /* End lim_send_disassoc_mgmt_frame. */
+
+/**
+ * \brief This function is called to send a Deauthenticate frame
+ *
+ *
+ * \param pMac Pointer to global MAC structure
+ *
+ * \param nReason Indicates the reason that need to be sent in the
+ * Deauthenticate frame
+ *
+ * \param peeer address of the STA to which the frame is to be sent
+ *
+ *
+ */
+
+void
+lim_send_deauth_mgmt_frame(tpAniSirGlobal pMac,
+ uint16_t nReason,
+ tSirMacAddr peer,
+ tpPESession psessionEntry, bool waitForAck)
+{
+ tDot11fDeAuth frm;
+ uint8_t *pFrame;
+ tpSirMacMgmtHdr pMacHdr;
+ uint32_t nBytes, nPayload, nStatus;
+ void *pPacket;
+ CDF_STATUS cdf_status;
+ uint8_t txFlag = 0;
+ uint32_t val = 0;
+#ifdef FEATURE_WLAN_TDLS
+ uint16_t aid;
+ tpDphHashNode pStaDs;
+#endif
+ uint8_t smeSessionId = 0;
+
+ if (NULL == psessionEntry) {
+ return;
+ }
+
+ /*
+ * In case when cac timer is running for this SAP session then
+ * avoid deauth frame out. It is violation of dfs specification.
+ */
+ if (((psessionEntry->pePersona == CDF_SAP_MODE) ||
+ (psessionEntry->pePersona == CDF_P2P_GO_MODE)) &&
+ (true == pMac->sap.SapDfsInfo.is_dfs_cac_timer_running)) {
+ CDF_TRACE(CDF_MODULE_ID_SAP, CDF_TRACE_LEVEL_INFO,
+ FL
+ ("CAC timer is running, drop the deauth from going out"));
+ return;
+ }
+ smeSessionId = psessionEntry->smeSessionId;
+
+ cdf_mem_set((uint8_t *) &frm, sizeof(frm), 0);
+
+ frm.Reason.code = nReason;
+
+ nStatus = dot11f_get_packed_de_auth_size(pMac, &frm, &nPayload);
+ if (DOT11F_FAILED(nStatus)) {
+ lim_log(pMac, LOGP, FL("Failed to calculate the packed size f"
+ "or a De-Authentication (0x%08x)."),
+ nStatus);
+ /* We'll fall back on the worst case scenario: */
+ nPayload = sizeof(tDot11fDeAuth);
+ } else if (DOT11F_WARNED(nStatus)) {
+ lim_log(pMac, LOGW, FL("There were warnings while calculating "
+ "the packed size for a De-Authentication "
+ "(0x%08x)."), nStatus);
+ }
+
+ nBytes = nPayload + sizeof(tSirMacMgmtHdr);
+
+ cdf_status = cds_packet_alloc((uint16_t) nBytes, (void **)&pFrame,
+ (void **)&pPacket);
+ if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
+ lim_log(pMac, LOGP, FL("Failed to allocate %d bytes for a De-"
+ "Authentication."), nBytes);
+ return;
+ }
+ /* Paranoia: */
+ cdf_mem_set(pFrame, nBytes, 0);
+
+ /* Next, we fill out the buffer descriptor: */
+ lim_populate_mac_header(pMac, pFrame, SIR_MAC_MGMT_FRAME,
+ SIR_MAC_MGMT_DEAUTH, peer, psessionEntry->selfMacAddr);
+ pMacHdr = (tpSirMacMgmtHdr) pFrame;
+
+ /* Prepare the BSSID */
+ sir_copy_mac_addr(pMacHdr->bssId, psessionEntry->bssId);
+
+#ifdef WLAN_FEATURE_11W
+ lim_set_protected_bit(pMac, psessionEntry, peer, pMacHdr);
+#endif
+
+ nStatus = dot11f_pack_de_auth(pMac, &frm, pFrame +
+ sizeof(tSirMacMgmtHdr), nPayload, &nPayload);
+ if (DOT11F_FAILED(nStatus)) {
+ lim_log(pMac, LOGE,
+ FL("Failed to pack a DeAuthentication (0x%08x)."),
+ nStatus);
+ cds_packet_free((void *)pPacket);
+ return;
+ } else if (DOT11F_WARNED(nStatus)) {
+ lim_log(pMac, LOGW, FL("There were warnings while packing a D"
+ "e-Authentication (0x%08x)."), nStatus);
+ }
+ lim_log(pMac, LOG1, FL("***Sessionid %d Sending Deauth frame with "
+ "reason %u and waitForAck %d to " MAC_ADDRESS_STR
+ " ,From " MAC_ADDRESS_STR),
+ psessionEntry->peSessionId, nReason, waitForAck,
+ MAC_ADDR_ARRAY(pMacHdr->da),
+ MAC_ADDR_ARRAY(psessionEntry->selfMacAddr));
+
+ if ((SIR_BAND_5_GHZ == lim_get_rf_band(psessionEntry->currentOperChannel))
+ || (psessionEntry->pePersona == CDF_P2P_CLIENT_MODE) ||
+ (psessionEntry->pePersona == CDF_P2P_GO_MODE)
+ ) {
+ txFlag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME;
+ }
+
+ if ((psessionEntry->pePersona == CDF_P2P_CLIENT_MODE) ||
+ (psessionEntry->pePersona == CDF_P2P_GO_MODE)) {
+ txFlag |= HAL_USE_PEER_STA_REQUESTED_MASK;
+ }
+#ifdef FEATURE_WLAN_TDLS
+ pStaDs =
+ dph_lookup_hash_entry(pMac, peer, &aid,
+ &psessionEntry->dph.dphHashTable);
+#endif
+
+ if (waitForAck) {
+ MTRACE(cdf_trace(CDF_MODULE_ID_PE, TRACE_CODE_TX_MGMT,
+ psessionEntry->peSessionId,
+ pMacHdr->fc.subType));
+ /* Queue Disassociation frame in high priority WQ */
+ cdf_status =
+ wma_tx_frameWithTxComplete(pMac, pPacket, (uint16_t) nBytes,
+ TXRX_FRM_802_11_MGMT,
+ ANI_TXDIR_TODS, 7, lim_tx_complete,
+ pFrame, lim_deauth_tx_complete_cnf,
+ txFlag, smeSessionId, false, 0);
+ MTRACE(cdf_trace
+ (CDF_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE,
+ psessionEntry->peSessionId, cdf_status));
+ /* Pkt will be freed up by the callback lim_tx_complete */
+ if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
+ lim_log(pMac, LOGE,
+ FL("Failed to send De-Authentication (%X)!"),
+ cdf_status);
+
+ /* Call lim_process_deauth_ack_timeout which will send
+ * DeauthCnf for this frame
+ */
+ lim_process_deauth_ack_timeout(pMac);
+ return;
+ }
+
+ val = SYS_MS_TO_TICKS(LIM_DISASSOC_DEAUTH_ACK_TIMEOUT);
+
+ if (tx_timer_change
+ (&pMac->lim.limTimers.gLimDeauthAckTimer, val, 0)
+ != TX_SUCCESS) {
+ lim_log(pMac, LOGP,
+ FL("Unable to change Deauth ack Timer val"));
+ return;
+ } else if (TX_SUCCESS !=
+ tx_timer_activate(&pMac->lim.limTimers.
+ gLimDeauthAckTimer)) {
+ lim_log(pMac, LOGP,
+ FL("Unable to activate Deauth ack Timer"));
+ lim_deactivate_and_change_timer(pMac,
+ eLIM_DEAUTH_ACK_TIMER);
+ return;
+ }
+ } else {
+ MTRACE(cdf_trace(CDF_MODULE_ID_PE, TRACE_CODE_TX_MGMT,
+ psessionEntry->peSessionId,
+ pMacHdr->fc.subType));
+#ifdef FEATURE_WLAN_TDLS
+ if ((NULL != pStaDs)
+ && (STA_ENTRY_TDLS_PEER == pStaDs->staType)) {
+ /* Queue Disassociation frame in high priority WQ */
+ cdf_status =
+ wma_tx_frame(pMac, pPacket, (uint16_t) nBytes,
+ TXRX_FRM_802_11_MGMT, ANI_TXDIR_IBSS,
+ 7, lim_tx_complete, pFrame, txFlag,
+ smeSessionId, 0);
+ } else {
+#endif
+ /* Queue Disassociation frame in high priority WQ */
+ cdf_status =
+ wma_tx_frame(pMac, pPacket, (uint16_t) nBytes,
+ TXRX_FRM_802_11_MGMT, ANI_TXDIR_TODS,
+ 7, lim_tx_complete, pFrame, txFlag,
+ smeSessionId, 0);
+#ifdef FEATURE_WLAN_TDLS
+ }
+#endif
+ MTRACE(cdf_trace(CDF_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE,
+ psessionEntry->peSessionId, cdf_status));
+ if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
+ lim_log(pMac, LOGE,
+ FL("Failed to send De-Authentication (%X)!"),
+ cdf_status);
+ /* Pkt will be freed up by the callback */
+ }
+ }
+
+} /* End lim_send_deauth_mgmt_frame. */
+
+#ifdef ANI_SUPPORT_11H
+/**
+ * \brief Send a Measurement Report Action frame
+ *
+ *
+ * \param pMac Pointer to the global MAC structure
+ *
+ * \param pMeasReqFrame Address of a tSirMacMeasReqActionFrame
+ *
+ * \return eSIR_SUCCESS on success, eSIR_FAILURE else
+ *
+ *
+ */
+
+tSirRetStatus
+lim_send_meas_report_frame(tpAniSirGlobal pMac,
+ tpSirMacMeasReqActionFrame pMeasReqFrame,
+ tSirMacAddr peer, tpPESession psessionEntry)
+{
+ tDot11fMeasurementReport frm;
+ uint8_t *pFrame;
+ tSirRetStatus nSirStatus;
+ tpSirMacMgmtHdr pMacHdr;
+ uint32_t nBytes, nPayload, nStatus;
+ void *pPacket;
+ CDF_STATUS cdf_status;
+
+ cdf_mem_set((uint8_t *) &frm, sizeof(frm), 0);
+
+ frm.Category.category = SIR_MAC_ACTION_SPECTRUM_MGMT;
+ frm.Action.action = SIR_MAC_ACTION_MEASURE_REPORT_ID;
+ frm.DialogToken.token = pMeasReqFrame->actionHeader.dialogToken;
+
+ switch (pMeasReqFrame->measReqIE.measType) {
+ case SIR_MAC_BASIC_MEASUREMENT_TYPE:
+ nSirStatus =
+ populate_dot11f_measurement_report0(pMac, pMeasReqFrame,
+ &frm.MeasurementReport);
+ break;
+ case SIR_MAC_CCA_MEASUREMENT_TYPE:
+ nSirStatus =
+ populate_dot11f_measurement_report1(pMac, pMeasReqFrame,
+ &frm.MeasurementReport);
+ break;
+ case SIR_MAC_RPI_MEASUREMENT_TYPE:
+ nSirStatus =
+ populate_dot11f_measurement_report2(pMac, pMeasReqFrame,
+ &frm.MeasurementReport);
+ break;
+ default:
+ lim_log(pMac, LOGE, FL("Unknown measurement type %d in limSen"
+ "dMeasReportFrame."),
+ pMeasReqFrame->measReqIE.measType);
+ return eSIR_FAILURE;
+ }
+
+ if (eSIR_SUCCESS != nSirStatus)
+ return eSIR_FAILURE;
+
+ nStatus = dot11f_get_packed_measurement_report_size(pMac, &frm, &nPayload);
+ if (DOT11F_FAILED(nStatus)) {
+ lim_log(pMac, LOGP, FL("Failed to calculate the packed size f"
+ "or a Measurement Report (0x%08x)."),
+ nStatus);
+ /* We'll fall back on the worst case scenario: */
+ nPayload = sizeof(tDot11fMeasurementReport);
+ } else if (DOT11F_WARNED(nStatus)) {
+ lim_log(pMac, LOGW, FL("There were warnings while calculating "
+ "the packed size for a Measurement Rep"
+ "ort (0x%08x)."), nStatus);
+ }
+
+ nBytes = nPayload + sizeof(tSirMacMgmtHdr);
+
+ cdf_status =
+ cds_packet_alloc(pMac->hHdd, TXRX_FRM_802_11_MGMT,
+ (uint16_t) nBytes, (void **)&pFrame,
+ (void **)&pPacket);
+ if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
+ lim_log(pMac, LOGP, FL("Failed to allocate %d bytes for a De-"
+ "Authentication."), nBytes);
+ return eSIR_FAILURE;
+ }
+ /* Paranoia: */
+ cdf_mem_set(pFrame, nBytes, 0);
+
+ /* Next, we fill out the buffer descriptor: */
+ lim_populate_mac_header(pMac, pFrame, SIR_MAC_MGMT_FRAME,
+ SIR_MAC_MGMT_ACTION, peer);
+ pMacHdr = (tpSirMacMgmtHdr) pFrame;
+
+ cdf_mem_copy(pMacHdr->bssId, psessionEntry->bssId, sizeof(tSirMacAddr));
+
+#ifdef WLAN_FEATURE_11W
+ lim_set_protected_bit(pMac, psessionEntry, peer, pMacHdr);
+#endif
+
+ nStatus = dot11f_pack_measurement_report(pMac, &frm, pFrame +
+ sizeof(tSirMacMgmtHdr),
+ nPayload, &nPayload);
+ if (DOT11F_FAILED(nStatus)) {
+ lim_log(pMac, LOGE,
+ FL("Failed to pack a Measurement Report (0x%08x)."),
+ nStatus);
+ cds_packet_free(pMac->hHdd, TXRX_FRM_802_11_MGMT,
+ (void *)pFrame, (void *)pPacket);
+ return eSIR_FAILURE; /* allocated! */
+ } else if (DOT11F_WARNED(nStatus)) {
+ lim_log(pMac, LOGW, FL("There were warnings while packing a M"
+ "easurement Report (0x%08x)."), nStatus);
+ }
+
+ MTRACE(cdf_trace(CDF_MODULE_ID_PE, TRACE_CODE_TX_MGMT,
+ ((psessionEntry) ? psessionEntry->
+ peSessionId : NO_SESSION), pMacHdr->fc.subType));
+ cdf_status =
+ wma_tx_frame(pMac, pPacket, (uint16_t) nBytes,
+ TXRX_FRM_802_11_MGMT, ANI_TXDIR_TODS, 7,
+ lim_tx_complete, pFrame, 0, 0);
+ MTRACE(cdf_trace
+ (CDF_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE,
+ ((psessionEntry) ? psessionEntry->peSessionId : NO_SESSION),
+ cdf_status));
+ if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
+ lim_log(pMac, LOGE,
+ FL("Failed to send a Measurement Report (%X)!"),
+ cdf_status);
+ /* Pkt will be freed up by the callback */
+ return eSIR_FAILURE; /* just allocated... */
+ }
+
+ return eSIR_SUCCESS;
+
+} /* End lim_send_meas_report_frame. */
+
+/**
+ * \brief Send a TPC Request Action frame
+ *
+ *
+ * \param pMac Pointer to the global MAC datastructure
+ *
+ * \param peer MAC address to which the frame should be sent
+ *
+ *
+ */
+
+void
+lim_send_tpc_request_frame(tpAniSirGlobal pMac,
+ tSirMacAddr peer, tpPESession psessionEntry)
+{
+ tDot11fTPCRequest frm;
+ uint8_t *pFrame;
+ tpSirMacMgmtHdr pMacHdr;
+ uint32_t nBytes, nPayload, nStatus;
+ void *pPacket;
+ CDF_STATUS cdf_status;
+
+ cdf_mem_set((uint8_t *) &frm, sizeof(frm), 0);
+
+ frm.Category.category = SIR_MAC_ACTION_SPECTRUM_MGMT;
+ frm.Action.action = SIR_MAC_ACTION_TPC_REQUEST_ID;
+ frm.DialogToken.token = 1;
+ frm.TPCRequest.present = 1;
+
+ nStatus = dot11f_get_packed_tpc_request_size(pMac, &frm, &nPayload);
+ if (DOT11F_FAILED(nStatus)) {
+ lim_log(pMac, LOGP, FL("Failed to calculate the packed size f"
+ "or a TPC Request (0x%08x)."), nStatus);
+ /* We'll fall back on the worst case scenario: */
+ nPayload = sizeof(tDot11fTPCRequest);
+ } else if (DOT11F_WARNED(nStatus)) {
+ lim_log(pMac, LOGW, FL("There were warnings while calculating "
+ "the packed size for a TPC Request (0x"
+ "%08x)."), nStatus);
+ }
+
+ nBytes = nPayload + sizeof(tSirMacMgmtHdr);
+
+ cdf_status =
+ cds_packet_alloc(pMac->hHdd, TXRX_FRM_802_11_MGMT,
+ (uint16_t) nBytes, (void **)&pFrame,
+ (void **)&pPacket);
+ if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
+ lim_log(pMac, LOGP, FL("Failed to allocate %d bytes for a TPC"
+ " Request."), nBytes);
+ return;
+ }
+ /* Paranoia: */
+ cdf_mem_set(pFrame, nBytes, 0);
+
+ /* Next, we fill out the buffer descriptor: */
+ lim_populate_mac_header(pMac, pFrame, SIR_MAC_MGMT_FRAME,
+ SIR_MAC_MGMT_ACTION, peer);
+ pMacHdr = (tpSirMacMgmtHdr) pFrame;
+
+ cdf_mem_copy(pMacHdr->bssId, psessionEntry->bssId, sizeof(tSirMacAddr));
+
+#ifdef WLAN_FEATURE_11W
+ lim_set_protected_bit(pMac, psessionEntry, peer, pMacHdr);
+#endif
+
+ nStatus = dot11f_pack_tpc_request(pMac, &frm, pFrame +
+ sizeof(tSirMacMgmtHdr),
+ nPayload, &nPayload);
+ if (DOT11F_FAILED(nStatus)) {
+ lim_log(pMac, LOGE, FL("Failed to pack a TPC Request (0x%08x)."),
+ nStatus);
+ cds_packet_free(pMac->hHdd, TXRX_FRM_802_11_MGMT,
+ (void *)pFrame, (void *)pPacket);
+ return; /* allocated! */
+ } else if (DOT11F_WARNED(nStatus)) {
+ lim_log(pMac, LOGW, FL("There were warnings while packing a T"
+ "PC Request (0x%08x)."), nStatus);
+ }
+
+ MTRACE(cdf_trace(CDF_MODULE_ID_PE, TRACE_CODE_TX_MGMT,
+ ((psessionEntry) ? psessionEntry->
+ peSessionId : NO_SESSION), pMacHdr->fc.subType));
+ cdf_status =
+ wma_tx_frame(pMac, pPacket, (uint16_t) nBytes,
+ TXRX_FRM_802_11_MGMT, ANI_TXDIR_TODS, 7,
+ lim_tx_complete, pFrame, 0, 0);
+ MTRACE(cdf_trace
+ (CDF_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE,
+ ((psessionEntry) ? psessionEntry->peSessionId : NO_SESSION),
+ cdf_status));
+ if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
+ lim_log(pMac, LOGE,
+ FL("Failed to send a TPC Request (%X)!"),
+ cdf_status);
+ /* Pkt will be freed up by the callback */
+ }
+
+} /* End lim_send_tpc_request_frame. */
+
+/**
+ * \brief Send a TPC Report Action frame
+ *
+ *
+ * \param pMac Pointer to the global MAC datastructure
+ *
+ * \param pTpcReqFrame Pointer to the received TPC Request
+ *
+ * \return eSIR_SUCCESS on success, eSIR_FAILURE else
+ *
+ *
+ */
+
+tSirRetStatus
+lim_send_tpc_report_frame(tpAniSirGlobal pMac,
+ tpSirMacTpcReqActionFrame pTpcReqFrame,
+ tSirMacAddr peer, tpPESession psessionEntry)
+{
+ tDot11fTPCReport frm;
+ uint8_t *pFrame;
+ tpSirMacMgmtHdr pMacHdr;
+ uint32_t nBytes, nPayload, nStatus;
+ void *pPacket;
+ CDF_STATUS cdf_status;
+
+ cdf_mem_set((uint8_t *) &frm, sizeof(frm), 0);
+
+ frm.Category.category = SIR_MAC_ACTION_SPECTRUM_MGMT;
+ frm.Action.action = SIR_MAC_ACTION_TPC_REPORT_ID;
+ frm.DialogToken.token = pTpcReqFrame->actionHeader.dialogToken;
+
+ frm.TPCReport.tx_power = 0;
+ frm.TPCReport.link_margin = 0;
+ frm.TPCReport.present = 1;
+
+ nStatus = dot11f_get_packed_tpc_report_size(pMac, &frm, &nPayload);
+ if (DOT11F_FAILED(nStatus)) {
+ lim_log(pMac, LOGP, FL("Failed to calculate the packed size f"
+ "or a TPC Report (0x%08x)."), nStatus);
+ /* We'll fall back on the worst case scenario: */
+ nPayload = sizeof(tDot11fTPCReport);
+ } else if (DOT11F_WARNED(nStatus)) {
+ lim_log(pMac, LOGW, FL("There were warnings while calculating "
+ "the packed size for a TPC Report (0x"
+ "%08x)."), nStatus);
+ }
+
+ nBytes = nPayload + sizeof(tSirMacMgmtHdr);
+
+ cdf_status =
+ cds_packet_alloc(pMac->hHdd, TXRX_FRM_802_11_MGMT,
+ (uint16_t) nBytes, (void **)&pFrame,
+ (void **)&pPacket);
+ if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
+ lim_log(pMac, LOGP, FL("Failed to allocate %d bytes for a TPC"
+ " Report."), nBytes);
+ return eSIR_FAILURE;
+ }
+ /* Paranoia: */
+ cdf_mem_set(pFrame, nBytes, 0);
+
+ /* Next, we fill out the buffer descriptor: */
+ lim_populate_mac_header(pMac, pFrame, SIR_MAC_MGMT_FRAME,
+ SIR_MAC_MGMT_ACTION, peer);
+
+ pMacHdr = (tpSirMacMgmtHdr) pFrame;
+
+ cdf_mem_copy(pMacHdr->bssId, psessionEntry->bssId, sizeof(tSirMacAddr));
+
+#ifdef WLAN_FEATURE_11W
+ lim_set_protected_bit(pMac, psessionEntry, peer, pMacHdr);
+#endif
+
+ nStatus = dot11f_pack_tpc_report(pMac, &frm, pFrame +
+ sizeof(tSirMacMgmtHdr),
+ nPayload, &nPayload);
+ if (DOT11F_FAILED(nStatus)) {
+ lim_log(pMac, LOGE, FL("Failed to pack a TPC Report (0x%08x)."),
+ nStatus);
+ cds_packet_free(pMac->hHdd, TXRX_FRM_802_11_MGMT,
+ (void *)pFrame, (void *)pPacket);
+ return eSIR_FAILURE; /* allocated! */
+ } else if (DOT11F_WARNED(nStatus)) {
+ lim_log(pMac, LOGW, FL("There were warnings while packing a T"
+ "PC Report (0x%08x)."), nStatus);
+ }
+
+ MTRACE(cdf_trace(CDF_MODULE_ID_PE, TRACE_CODE_TX_MGMT,
+ ((psessionEntry) ? psessionEntry->
+ peSessionId : NO_SESSION), pMacHdr->fc.subType));
+ cdf_status =
+ wma_tx_frame(pMac, pPacket, (uint16_t) nBytes,
+ TXRX_FRM_802_11_MGMT, ANI_TXDIR_TODS, 7,
+ lim_tx_complete, pFrame, 0, 0);
+ MTRACE(cdf_trace
+ (CDF_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE,
+ ((psessionEntry) ? psessionEntry->peSessionId : NO_SESSION),
+ cdf_status));
+ if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
+ lim_log(pMac, LOGE,
+ FL("Failed to send a TPC Report (%X)!"),
+ cdf_status);
+ /* Pkt will be freed up by the callback */
+ return eSIR_FAILURE; /* just allocated... */
+ }
+
+ return eSIR_SUCCESS;
+
+} /* End lim_send_tpc_report_frame. */
+#endif /* ANI_SUPPORT_11H */
+
+/**
+ * \brief Send a Channel Switch Announcement
+ *
+ *
+ * \param pMac Pointer to the global MAC datastructure
+ *
+ * \param peer MAC address to which this frame will be sent
+ *
+ * \param nMode
+ *
+ * \param nNewChannel
+ *
+ * \param nCount
+ *
+ * \return eSIR_SUCCESS on success, eSIR_FAILURE else
+ *
+ *
+ */
+
+tSirRetStatus
+lim_send_channel_switch_mgmt_frame(tpAniSirGlobal pMac,
+ tSirMacAddr peer,
+ uint8_t nMode,
+ uint8_t nNewChannel,
+ uint8_t nCount, tpPESession psessionEntry)
+{
+ tDot11fChannelSwitch frm;
+ uint8_t *pFrame;
+ tpSirMacMgmtHdr pMacHdr;
+ uint32_t nBytes, nPayload, nStatus; /* , nCfg; */
+ void *pPacket;
+ CDF_STATUS cdf_status;
+ uint8_t txFlag = 0;
+
+ uint8_t smeSessionId = 0;
+
+ if (psessionEntry == NULL) {
+ PELOGE(lim_log(pMac, LOGE, FL("Session entry is NULL!!!"));)
+ return eSIR_FAILURE;
+ }
+ smeSessionId = psessionEntry->smeSessionId;
+
+ cdf_mem_set((uint8_t *) &frm, sizeof(frm), 0);
+
+ frm.Category.category = SIR_MAC_ACTION_SPECTRUM_MGMT;
+ frm.Action.action = SIR_MAC_ACTION_CHANNEL_SWITCH_ID;
+ frm.ChanSwitchAnn.switchMode = nMode;
+ frm.ChanSwitchAnn.newChannel = nNewChannel;
+ frm.ChanSwitchAnn.switchCount = nCount;
+ frm.ChanSwitchAnn.present = 1;
+
+ nStatus = dot11f_get_packed_channel_switch_size(pMac, &frm, &nPayload);
+ if (DOT11F_FAILED(nStatus)) {
+ lim_log(pMac, LOGP, FL("Failed to calculate the packed size f"
+ "or a Channel Switch (0x%08x)."),
+ nStatus);
+ /* We'll fall back on the worst case scenario: */
+ nPayload = sizeof(tDot11fChannelSwitch);
+ } else if (DOT11F_WARNED(nStatus)) {
+ lim_log(pMac, LOGW, FL("There were warnings while calculating "
+ "the packed size for a Channel Switch (0x"
+ "%08x)."), nStatus);
+ }
+
+ nBytes = nPayload + sizeof(tSirMacMgmtHdr);
+
+ cdf_status =
+ cds_packet_alloc((uint16_t) nBytes, (void **)&pFrame,
+ (void **)&pPacket);
+ if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
+ lim_log(pMac, LOGP, FL("Failed to allocate %d bytes for a TPC"
+ " Report."), nBytes);
+ return eSIR_FAILURE;
+ }
+ /* Paranoia: */
+ cdf_mem_set(pFrame, nBytes, 0);
+
+ /* Next, we fill out the buffer descriptor: */
+ lim_populate_mac_header(pMac, pFrame, SIR_MAC_MGMT_FRAME,
+ SIR_MAC_MGMT_ACTION, peer,
+ psessionEntry->selfMacAddr);
+ pMacHdr = (tpSirMacMgmtHdr) pFrame;
+ cdf_mem_copy((uint8_t *) pMacHdr->bssId,
+ (uint8_t *) psessionEntry->bssId, sizeof(tSirMacAddr));
+
+#ifdef WLAN_FEATURE_11W
+ lim_set_protected_bit(pMac, psessionEntry, peer, pMacHdr);
+#endif
+
+ nStatus = dot11f_pack_channel_switch(pMac, &frm, pFrame +
+ sizeof(tSirMacMgmtHdr),
+ nPayload, &nPayload);
+ if (DOT11F_FAILED(nStatus)) {
+ lim_log(pMac, LOGE,
+ FL("Failed to pack a Channel Switch (0x%08x)."),
+ nStatus);
+ cds_packet_free((void *)pPacket);
+ return eSIR_FAILURE; /* allocated! */
+ } else if (DOT11F_WARNED(nStatus)) {
+ lim_log(pMac, LOGW, FL("There were warnings while packing a C"
+ "hannel Switch (0x%08x)."), nStatus);
+ }
+
+ if ((SIR_BAND_5_GHZ == lim_get_rf_band(psessionEntry->currentOperChannel))
+ || (psessionEntry->pePersona == CDF_P2P_CLIENT_MODE) ||
+ (psessionEntry->pePersona == CDF_P2P_GO_MODE)
+ ) {
+ txFlag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME;
+ }
+
+ MTRACE(cdf_trace(CDF_MODULE_ID_PE, TRACE_CODE_TX_MGMT,
+ psessionEntry->peSessionId, pMacHdr->fc.subType));
+ cdf_status = wma_tx_frame(pMac, pPacket, (uint16_t) nBytes,
+ TXRX_FRM_802_11_MGMT,
+ ANI_TXDIR_TODS,
+ 7, lim_tx_complete, pFrame, txFlag,
+ smeSessionId, 0);
+ MTRACE(cdf_trace(CDF_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE,
+ psessionEntry->peSessionId, cdf_status));
+ if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
+ lim_log(pMac, LOGE,
+ FL("Failed to send a Channel Switch (%X)!"),
+ cdf_status);
+ /* Pkt will be freed up by the callback */
+ return eSIR_FAILURE;
+ }
+
+ return eSIR_SUCCESS;
+
+} /* End lim_send_channel_switch_mgmt_frame. */
+
+#ifdef WLAN_FEATURE_11AC
+tSirRetStatus
+lim_send_vht_opmode_notification_frame(tpAniSirGlobal pMac,
+ tSirMacAddr peer,
+ uint8_t nMode, tpPESession psessionEntry)
+{
+ tDot11fOperatingMode frm;
+ uint8_t *pFrame;
+ tpSirMacMgmtHdr pMacHdr;
+ uint32_t nBytes, nPayload = 0, nStatus; /* , nCfg; */
+ void *pPacket;
+ CDF_STATUS cdf_status;
+ uint8_t txFlag = 0;
+
+ uint8_t smeSessionId = 0;
+
+ if (psessionEntry == NULL) {
+ PELOGE(lim_log(pMac, LOGE, FL("Session entry is NULL!!!"));)
+ return eSIR_FAILURE;
+ }
+ smeSessionId = psessionEntry->smeSessionId;
+
+ cdf_mem_set((uint8_t *) &frm, sizeof(frm), 0);
+
+ frm.Category.category = SIR_MAC_ACTION_VHT;
+ frm.Action.action = SIR_MAC_VHT_OPMODE_NOTIFICATION;
+ frm.OperatingMode.chanWidth = nMode;
+ frm.OperatingMode.rxNSS = 0;
+ frm.OperatingMode.rxNSSType = 0;
+
+ nStatus = dot11f_get_packed_operating_mode_size(pMac, &frm, &nPayload);
+ if (DOT11F_FAILED(nStatus)) {
+ lim_log(pMac, LOGP, FL("Failed to calculate the packed size f"
+ "or a Operating Mode (0x%08x)."),
+ nStatus);
+ /* We'll fall back on the worst case scenario: */
+ nPayload = sizeof(tDot11fOperatingMode);
+ } else if (DOT11F_WARNED(nStatus)) {
+ lim_log(pMac, LOGW, FL("There were warnings while calculating "
+ "the packed size for a Operating Mode (0x"
+ "%08x)."), nStatus);
+ }
+
+ nBytes = nPayload + sizeof(tSirMacMgmtHdr);
+
+ cdf_status =
+ cds_packet_alloc((uint16_t) nBytes, (void **)&pFrame,
+ (void **)&pPacket);
+ if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
+ lim_log(pMac, LOGP,
+ FL("Failed to allocate %d bytes for a Operating Mode"
+ " Report."), nBytes);
+ return eSIR_FAILURE;
+ }
+ /* Paranoia: */
+ cdf_mem_set(pFrame, nBytes, 0);
+
+ /* Next, we fill out the buffer descriptor: */
+ if (psessionEntry->pePersona == CDF_SAP_MODE)
+ lim_populate_mac_header(pMac, pFrame, SIR_MAC_MGMT_FRAME,
+ SIR_MAC_MGMT_ACTION, peer,
+ psessionEntry->selfMacAddr);
+ else
+ lim_populate_mac_header(pMac, pFrame, SIR_MAC_MGMT_FRAME,
+ SIR_MAC_MGMT_ACTION, psessionEntry->bssId,
+ psessionEntry->selfMacAddr);
+ pMacHdr = (tpSirMacMgmtHdr) pFrame;
+ cdf_mem_copy((uint8_t *) pMacHdr->bssId,
+ (uint8_t *) psessionEntry->bssId, sizeof(tSirMacAddr));
+ nStatus = dot11f_pack_operating_mode(pMac, &frm, pFrame +
+ sizeof(tSirMacMgmtHdr),
+ nPayload, &nPayload);
+ if (DOT11F_FAILED(nStatus)) {
+ lim_log(pMac, LOGE,
+ FL("Failed to pack a Operating Mode (0x%08x)."),
+ nStatus);
+ cds_packet_free((void *)pPacket);
+ return eSIR_FAILURE; /* allocated! */
+ } else if (DOT11F_WARNED(nStatus)) {
+ lim_log(pMac, LOGW,
+ FL("There were warnings while packing a Operating Mode"
+ " (0x%08x)."), nStatus);
+ }
+ if ((SIR_BAND_5_GHZ == lim_get_rf_band(psessionEntry->currentOperChannel))
+ || (psessionEntry->pePersona == CDF_P2P_CLIENT_MODE) ||
+ (psessionEntry->pePersona == CDF_P2P_GO_MODE)
+ ) {
+ txFlag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME;
+ }
+
+ MTRACE(cdf_trace(CDF_MODULE_ID_PE, TRACE_CODE_TX_MGMT,
+ psessionEntry->peSessionId, pMacHdr->fc.subType));
+ cdf_status = wma_tx_frame(pMac, pPacket, (uint16_t) nBytes,
+ TXRX_FRM_802_11_MGMT,
+ ANI_TXDIR_TODS,
+ 7, lim_tx_complete, pFrame, txFlag,
+ smeSessionId, 0);
+ MTRACE(cdf_trace(CDF_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE,
+ psessionEntry->peSessionId, cdf_status));
+ if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
+ lim_log(pMac, LOGE,
+ FL("Failed to send a Channel Switch (%X)!"),
+ cdf_status);
+ /* Pkt will be freed up by the callback */
+ return eSIR_FAILURE;
+ }
+
+ return eSIR_SUCCESS;
+}
+
+/**
+ * \brief Send a VHT Channel Switch Announcement
+ *
+ *
+ * \param pMac Pointer to the global MAC datastructure
+ *
+ * \param peer MAC address to which this frame will be sent
+ *
+ * \param nChanWidth
+ *
+ * \param nNewChannel
+ *
+ *
+ * \return eSIR_SUCCESS on success, eSIR_FAILURE else
+ *
+ *
+ */
+
+tSirRetStatus
+lim_send_vht_channel_switch_mgmt_frame(tpAniSirGlobal pMac,
+ tSirMacAddr peer,
+ uint8_t nChanWidth,
+ uint8_t nNewChannel,
+ uint8_t ncbMode, tpPESession psessionEntry)
+{
+ tDot11fChannelSwitch frm;
+ uint8_t *pFrame;
+ tpSirMacMgmtHdr pMacHdr;
+ uint32_t nBytes, nPayload, nStatus; /* , nCfg; */
+ void *pPacket;
+ CDF_STATUS cdf_status;
+ uint8_t txFlag = 0;
+
+ uint8_t smeSessionId = 0;
+
+ if (psessionEntry == NULL) {
+ PELOGE(lim_log(pMac, LOGE, FL("Session entry is NULL!!!"));)
+ return eSIR_FAILURE;
+ }
+ smeSessionId = psessionEntry->smeSessionId;
+
+ cdf_mem_set((uint8_t *) &frm, sizeof(frm), 0);
+
+ frm.Category.category = SIR_MAC_ACTION_SPECTRUM_MGMT;
+ frm.Action.action = SIR_MAC_ACTION_CHANNEL_SWITCH_ID;
+ frm.ChanSwitchAnn.switchMode = 1;
+ frm.ChanSwitchAnn.newChannel = nNewChannel;
+ frm.ChanSwitchAnn.switchCount = 1;
+ frm.sec_chan_offset_ele.secondaryChannelOffset =
+ lim_get_htcb_state(ncbMode);
+ frm.sec_chan_offset_ele.present = 1;
+ frm.WiderBWChanSwitchAnn.newChanWidth = nChanWidth;
+ frm.WiderBWChanSwitchAnn.newCenterChanFreq0 =
+ lim_get_center_channel(pMac, nNewChannel, ncbMode, nChanWidth);
+ frm.WiderBWChanSwitchAnn.newCenterChanFreq1 = 0;
+ frm.ChanSwitchAnn.present = 1;
+ frm.WiderBWChanSwitchAnn.present = 1;
+
+ nStatus = dot11f_get_packed_channel_switch_size(pMac, &frm, &nPayload);
+ if (DOT11F_FAILED(nStatus)) {
+ lim_log(pMac, LOGP, FL("Failed to calculate the packed size f"
+ "or a Channel Switch (0x%08x)."),
+ nStatus);
+ /* We'll fall back on the worst case scenario: */
+ nPayload = sizeof(tDot11fChannelSwitch);
+ } else if (DOT11F_WARNED(nStatus)) {
+ lim_log(pMac, LOGW, FL("There were warnings while calculating "
+ "the packed size for a Channel Switch (0x"
+ "%08x)."), nStatus);
+ }
+
+ nBytes = nPayload + sizeof(tSirMacMgmtHdr);
+
+ cdf_status =
+ cds_packet_alloc((uint16_t) nBytes, (void **)&pFrame,
+ (void **)&pPacket);
+ if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
+ lim_log(pMac, LOGP, FL("Failed to allocate %d bytes for a TPC"
+ " Report."), nBytes);
+ return eSIR_FAILURE;
+ }
+ /* Paranoia: */
+ cdf_mem_set(pFrame, nBytes, 0);
+
+ /* Next, we fill out the buffer descriptor: */
+ lim_populate_mac_header(pMac, pFrame, SIR_MAC_MGMT_FRAME,
+ SIR_MAC_MGMT_ACTION, peer, psessionEntry->selfMacAddr);
+ pMacHdr = (tpSirMacMgmtHdr) pFrame;
+ cdf_mem_copy((uint8_t *) pMacHdr->bssId,
+ (uint8_t *) psessionEntry->bssId, sizeof(tSirMacAddr));
+ nStatus = dot11f_pack_channel_switch(pMac, &frm, pFrame +
+ sizeof(tSirMacMgmtHdr),
+ nPayload, &nPayload);
+ if (DOT11F_FAILED(nStatus)) {
+ lim_log(pMac, LOGE,
+ FL("Failed to pack a Channel Switch (0x%08x)."),
+ nStatus);
+ cds_packet_free((void *)pPacket);
+ return eSIR_FAILURE; /* allocated! */
+ } else if (DOT11F_WARNED(nStatus)) {
+ lim_log(pMac, LOGW, FL("There were warnings while packing a C"
+ "hannel Switch (0x%08x)."), nStatus);
+ }
+
+ if ((SIR_BAND_5_GHZ == lim_get_rf_band(psessionEntry->currentOperChannel))
+ || (psessionEntry->pePersona == CDF_P2P_CLIENT_MODE) ||
+ (psessionEntry->pePersona == CDF_P2P_GO_MODE)
+ ) {
+ txFlag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME;
+ }
+
+ MTRACE(cdf_trace(CDF_MODULE_ID_PE, TRACE_CODE_TX_MGMT,
+ psessionEntry->peSessionId, pMacHdr->fc.subType));
+ cdf_status = wma_tx_frame(pMac, pPacket, (uint16_t) nBytes,
+ TXRX_FRM_802_11_MGMT,
+ ANI_TXDIR_TODS,
+ 7, lim_tx_complete, pFrame, txFlag,
+ smeSessionId, 0);
+ MTRACE(cdf_trace(CDF_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE,
+ psessionEntry->peSessionId, cdf_status));
+ if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
+ lim_log(pMac, LOGE,
+ FL("Failed to send a Channel Switch (%X)!"),
+ cdf_status);
+ /* Pkt will be freed up by the callback */
+ return eSIR_FAILURE;
+ }
+
+ return eSIR_SUCCESS;
+
+} /* End lim_send_vht_channel_switch_mgmt_frame. */
+
+#endif
+
+#if defined WLAN_FEATURE_VOWIFI
+
+/**
+ * \brief Send a Neighbor Report Request Action frame
+ *
+ *
+ * \param pMac Pointer to the global MAC structure
+ *
+ * \param pNeighborReq Address of a tSirMacNeighborReportReq
+ *
+ * \param peer mac address of peer station.
+ *
+ * \param psessionEntry address of session entry.
+ *
+ * \return eSIR_SUCCESS on success, eSIR_FAILURE else
+ *
+ *
+ */
+
+tSirRetStatus
+lim_send_neighbor_report_request_frame(tpAniSirGlobal pMac,
+ tpSirMacNeighborReportReq pNeighborReq,
+ tSirMacAddr peer, tpPESession psessionEntry)
+{
+ tSirRetStatus statusCode = eSIR_SUCCESS;
+ tDot11fNeighborReportRequest frm;
+ uint8_t *pFrame;
+ tpSirMacMgmtHdr pMacHdr;
+ uint32_t nBytes, nPayload, nStatus;
+ void *pPacket;
+ CDF_STATUS cdf_status;
+ uint8_t txFlag = 0;
+ uint8_t smeSessionId = 0;
+
+ if (psessionEntry == NULL) {
+ lim_log(pMac, LOGE,
+ FL
+ ("(psession == NULL) in Request to send Neighbor Report request action frame"));
+ return eSIR_FAILURE;
+ }
+ smeSessionId = psessionEntry->smeSessionId;
+ cdf_mem_set((uint8_t *) &frm, sizeof(frm), 0);
+
+ frm.Category.category = SIR_MAC_ACTION_RRM;
+ frm.Action.action = SIR_MAC_RRM_NEIGHBOR_REQ;
+ frm.DialogToken.token = pNeighborReq->dialogToken;
+
+ if (pNeighborReq->ssid_present) {
+ populate_dot11f_ssid(pMac, &pNeighborReq->ssid, &frm.SSID);
+ }
+
+ nStatus =
+ dot11f_get_packed_neighbor_report_request_size(pMac, &frm, &nPayload);
+ if (DOT11F_FAILED(nStatus)) {
+ lim_log(pMac, LOGP, FL("Failed to calculate the packed size f"
+ "or a Neighbor Report Request(0x%08x)."),
+ nStatus);
+ /* We'll fall back on the worst case scenario: */
+ nPayload = sizeof(tDot11fNeighborReportRequest);
+ } else if (DOT11F_WARNED(nStatus)) {
+ lim_log(pMac, LOGW, FL("There were warnings while calculating "
+ "the packed size for a Neighbor Rep"
+ "ort Request(0x%08x)."), nStatus);
+ }
+
+ nBytes = nPayload + sizeof(tSirMacMgmtHdr);
+
+ cdf_status =
+ cds_packet_alloc((uint16_t) nBytes, (void **)&pFrame,
+ (void **)&pPacket);
+ if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
+ lim_log(pMac, LOGP,
+ FL("Failed to allocate %d bytes for a Neighbor "
+ "Report Request."), nBytes);
+ return eSIR_FAILURE;
+ }
+ /* Paranoia: */
+ cdf_mem_set(pFrame, nBytes, 0);
+
+ /* Copy necessary info to BD */
+ lim_populate_mac_header(pMac, pFrame, SIR_MAC_MGMT_FRAME,
+ SIR_MAC_MGMT_ACTION, peer, psessionEntry->selfMacAddr);
+
+ /* Update A3 with the BSSID */
+ pMacHdr = (tpSirMacMgmtHdr) pFrame;
+
+ sir_copy_mac_addr(pMacHdr->bssId, psessionEntry->bssId);
+
+#ifdef WLAN_FEATURE_11W
+ lim_set_protected_bit(pMac, psessionEntry, peer, pMacHdr);
+#endif
+
+ /* Now, we're ready to "pack" the frames */
+ nStatus = dot11f_pack_neighbor_report_request(pMac,
+ &frm,
+ pFrame +
+ sizeof(tSirMacMgmtHdr),
+ nPayload, &nPayload);
+
+ if (DOT11F_FAILED(nStatus)) {
+ lim_log(pMac, LOGE,
+ FL
+ ("Failed to pack an Neighbor Report Request (0x%08x)."),
+ nStatus);
+
+ /* FIXME - Need to convert to tSirRetStatus */
+ statusCode = eSIR_FAILURE;
+ goto returnAfterError;
+ } else if (DOT11F_WARNED(nStatus)) {
+ lim_log(pMac, LOGW,
+ FL("There were warnings while packing Neighbor Report "
+ "Request (0x%08x)."), nStatus);
+ }
+
+ lim_log(pMac, LOGW, FL("Sending a Neighbor Report Request to "));
+ lim_print_mac_addr(pMac, peer, LOGW);
+
+ if ((SIR_BAND_5_GHZ == lim_get_rf_band(psessionEntry->currentOperChannel))
+ || (psessionEntry->pePersona == CDF_P2P_CLIENT_MODE) ||
+ (psessionEntry->pePersona == CDF_P2P_GO_MODE)
+ ) {
+ txFlag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME;
+ }
+
+ MTRACE(cdf_trace(CDF_MODULE_ID_PE, TRACE_CODE_TX_MGMT,
+ psessionEntry->peSessionId, pMacHdr->fc.subType));
+ cdf_status = wma_tx_frame(pMac,
+ pPacket,
+ (uint16_t) nBytes,
+ TXRX_FRM_802_11_MGMT,
+ ANI_TXDIR_TODS,
+ 7, lim_tx_complete, pFrame, txFlag,
+ smeSessionId, 0);
+ MTRACE(cdf_trace(CDF_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE,
+ psessionEntry->peSessionId, cdf_status));
+ if (CDF_STATUS_SUCCESS != cdf_status) {
+ PELOGE(lim_log
+ (pMac, LOGE, FL("wma_tx_frame FAILED! Status [%d]"),
+ cdf_status);
+ )
+ statusCode = eSIR_FAILURE;
+ /* Pkt will be freed up by the callback */
+ return statusCode;
+ } else
+ return eSIR_SUCCESS;
+
+returnAfterError:
+ cds_packet_free((void *)pPacket);
+
+ return statusCode;
+} /* End lim_send_neighbor_report_request_frame. */
+
+/**
+ * \brief Send a Link Report Action frame
+ *
+ *
+ * \param pMac Pointer to the global MAC structure
+ *
+ * \param pLinkReport Address of a tSirMacLinkReport
+ *
+ * \param peer mac address of peer station.
+ *
+ * \param psessionEntry address of session entry.
+ *
+ * \return eSIR_SUCCESS on success, eSIR_FAILURE else
+ *
+ *
+ */
+
+tSirRetStatus
+lim_send_link_report_action_frame(tpAniSirGlobal pMac,
+ tpSirMacLinkReport pLinkReport,
+ tSirMacAddr peer, tpPESession psessionEntry)
+{
+ tSirRetStatus statusCode = eSIR_SUCCESS;
+ tDot11fLinkMeasurementReport frm;
+ uint8_t *pFrame;
+ tpSirMacMgmtHdr pMacHdr;
+ uint32_t nBytes, nPayload, nStatus;
+ void *pPacket;
+ CDF_STATUS cdf_status;
+ uint8_t txFlag = 0;
+ uint8_t smeSessionId = 0;
+
+ if (psessionEntry == NULL) {
+ lim_log(pMac, LOGE,
+ FL
+ ("(psession == NULL) in Request to send Link Report action frame"));
+ return eSIR_FAILURE;
+ }
+
+ cdf_mem_set((uint8_t *) &frm, sizeof(frm), 0);
+
+ frm.Category.category = SIR_MAC_ACTION_RRM;
+ frm.Action.action = SIR_MAC_RRM_LINK_MEASUREMENT_RPT;
+ frm.DialogToken.token = pLinkReport->dialogToken;
+
+ /* IEEE Std. 802.11 7.3.2.18. for the report element. */
+ /* Even though TPC report an IE, it is represented using fixed fields since it is positioned */
+ /* in the middle of other fixed fields in the link report frame(IEEE Std. 802.11k section7.4.6.4 */
+ /* and frame parser always expects IEs to come after all fixed fields. It is easier to handle */
+ /* such case this way than changing the frame parser. */
+ frm.TPCEleID.TPCId = SIR_MAC_TPC_RPT_EID;
+ frm.TPCEleLen.TPCLen = 2;
+ frm.TxPower.txPower = pLinkReport->txPower;
+ frm.LinkMargin.linkMargin = 0;
+
+ frm.RxAntennaId.antennaId = pLinkReport->rxAntenna;
+ frm.TxAntennaId.antennaId = pLinkReport->txAntenna;
+ frm.RCPI.rcpi = pLinkReport->rcpi;
+ frm.RSNI.rsni = pLinkReport->rsni;
+
+ nStatus =
+ dot11f_get_packed_link_measurement_report_size(pMac, &frm, &nPayload);
+ if (DOT11F_FAILED(nStatus)) {
+ lim_log(pMac, LOGP, FL("Failed to calculate the packed size f"
+ "or a Link Report (0x%08x)."), nStatus);
+ /* We'll fall back on the worst case scenario: */
+ nPayload = sizeof(tDot11fLinkMeasurementReport);
+ } else if (DOT11F_WARNED(nStatus)) {
+ lim_log(pMac, LOGW, FL("There were warnings while calculating "
+ "the packed size for a Link Rep"
+ "ort (0x%08x)."), nStatus);
+ }
+
+ nBytes = nPayload + sizeof(tSirMacMgmtHdr);
+
+ cdf_status =
+ cds_packet_alloc((uint16_t) nBytes, (void **)&pFrame,
+ (void **)&pPacket);
+ if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
+ lim_log(pMac, LOGP, FL("Failed to allocate %d bytes for a Link "
+ "Report."), nBytes);
+ return eSIR_FAILURE;
+ }
+ /* Paranoia: */
+ cdf_mem_set(pFrame, nBytes, 0);
+
+ /* Copy necessary info to BD */
+ lim_populate_mac_header(pMac, pFrame, SIR_MAC_MGMT_FRAME,
+ SIR_MAC_MGMT_ACTION, peer, psessionEntry->selfMacAddr);
+
+ /* Update A3 with the BSSID */
+ pMacHdr = (tpSirMacMgmtHdr) pFrame;
+
+ sir_copy_mac_addr(pMacHdr->bssId, psessionEntry->bssId);
+
+#ifdef WLAN_FEATURE_11W
+ lim_set_protected_bit(pMac, psessionEntry, peer, pMacHdr);
+#endif
+
+ /* Now, we're ready to "pack" the frames */
+ nStatus = dot11f_pack_link_measurement_report(pMac,
+ &frm,
+ pFrame +
+ sizeof(tSirMacMgmtHdr),
+ nPayload, &nPayload);
+
+ if (DOT11F_FAILED(nStatus)) {
+ lim_log(pMac, LOGE,
+ FL("Failed to pack an Link Report (0x%08x)."), nStatus);
+
+ /* FIXME - Need to convert to tSirRetStatus */
+ statusCode = eSIR_FAILURE;
+ goto returnAfterError;
+ } else if (DOT11F_WARNED(nStatus)) {
+ lim_log(pMac, LOGW,
+ FL
+ ("There were warnings while packing Link Report (0x%08x)."),
+ nStatus);
+ }
+
+ lim_log(pMac, LOGW, FL("Sending a Link Report to "));
+ lim_print_mac_addr(pMac, peer, LOGW);
+
+ if ((SIR_BAND_5_GHZ == lim_get_rf_band(psessionEntry->currentOperChannel))
+ || (psessionEntry->pePersona == CDF_P2P_CLIENT_MODE) ||
+ (psessionEntry->pePersona == CDF_P2P_GO_MODE)) {
+ txFlag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME;
+ }
+
+ MTRACE(cdf_trace(CDF_MODULE_ID_PE, TRACE_CODE_TX_MGMT,
+ psessionEntry->peSessionId, pMacHdr->fc.subType));
+ cdf_status = wma_tx_frame(pMac,
+ pPacket,
+ (uint16_t) nBytes,
+ TXRX_FRM_802_11_MGMT,
+ ANI_TXDIR_TODS,
+ 7, lim_tx_complete, pFrame, txFlag,
+ smeSessionId, 0);
+ MTRACE(cdf_trace(CDF_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE,
+ psessionEntry->peSessionId, cdf_status));
+ if (CDF_STATUS_SUCCESS != cdf_status) {
+ PELOGE(lim_log
+ (pMac, LOGE, FL("wma_tx_frame FAILED! Status [%d]"),
+ cdf_status);
+ )
+ statusCode = eSIR_FAILURE;
+ /* Pkt will be freed up by the callback */
+ return statusCode;
+ } else
+ return eSIR_SUCCESS;
+
+returnAfterError:
+ cds_packet_free((void *)pPacket);
+
+ return statusCode;
+} /* End lim_send_link_report_action_frame. */
+
+/**
+ * \brief Send a Beacon Report Action frame
+ *
+ *
+ * \param pMac Pointer to the global MAC structure
+ *
+ * \param dialog_token dialog token to be used in the action frame.
+ *
+ * \param num_report number of reports in pRRMReport.
+ *
+ * \param pRRMReport Address of a tSirMacRadioMeasureReport.
+ *
+ * \param peer mac address of peer station.
+ *
+ * \param psessionEntry address of session entry.
+ *
+ * \return eSIR_SUCCESS on success, eSIR_FAILURE else
+ *
+ *
+ */
+
+tSirRetStatus
+lim_send_radio_measure_report_action_frame(tpAniSirGlobal pMac,
+ uint8_t dialog_token,
+ uint8_t num_report,
+ tpSirMacRadioMeasureReport pRRMReport,
+ tSirMacAddr peer,
+ tpPESession psessionEntry)
+{
+ tSirRetStatus statusCode = eSIR_SUCCESS;
+ uint8_t *pFrame;
+ tpSirMacMgmtHdr pMacHdr;
+ uint32_t nBytes, nPayload, nStatus;
+ void *pPacket;
+ CDF_STATUS cdf_status;
+ uint8_t i;
+ uint8_t txFlag = 0;
+ uint8_t smeSessionId = 0;
+
+ tDot11fRadioMeasurementReport *frm =
+ cdf_mem_malloc(sizeof(tDot11fRadioMeasurementReport));
+ if (!frm) {
+ lim_log(pMac, LOGE,
+ FL
+ ("Not enough memory to allocate tDot11fRadioMeasurementReport"));
+ return eSIR_MEM_ALLOC_FAILED;
+ }
+
+ if (psessionEntry == NULL) {
+ lim_log(pMac, LOGE,
+ FL
+ ("(psession == NULL) in Request to send Beacon Report action frame"));
+ cdf_mem_free(frm);
+ return eSIR_FAILURE;
+ }
+ cdf_mem_set((uint8_t *) frm, sizeof(*frm), 0);
+
+ frm->Category.category = SIR_MAC_ACTION_RRM;
+ frm->Action.action = SIR_MAC_RRM_RADIO_MEASURE_RPT;
+ frm->DialogToken.token = dialog_token;
+
+ frm->num_MeasurementReport =
+ (num_report >
+ RADIO_REPORTS_MAX_IN_A_FRAME) ? RADIO_REPORTS_MAX_IN_A_FRAME :
+ num_report;
+
+ for (i = 0; i < frm->num_MeasurementReport; i++) {
+ frm->MeasurementReport[i].type = pRRMReport[i].type;
+ frm->MeasurementReport[i].token = pRRMReport[i].token;
+ frm->MeasurementReport[i].late = 0; /* IEEE 802.11k section 7.3.22. (always zero in rrm) */
+ switch (pRRMReport[i].type) {
+ case SIR_MAC_RRM_BEACON_TYPE:
+ populate_dot11f_beacon_report(pMac,
+ &frm->MeasurementReport[i],
+ &pRRMReport[i].report.
+ beaconReport);
+ frm->MeasurementReport[i].incapable =
+ pRRMReport[i].incapable;
+ frm->MeasurementReport[i].refused =
+ pRRMReport[i].refused;
+ frm->MeasurementReport[i].present = 1;
+ break;
+ default:
+ frm->MeasurementReport[i].incapable =
+ pRRMReport[i].incapable;
+ frm->MeasurementReport[i].refused =
+ pRRMReport[i].refused;
+ frm->MeasurementReport[i].present = 1;
+ break;
+ }
+ }
+
+ nStatus =
+ dot11f_get_packed_radio_measurement_report_size(pMac, frm, &nPayload);
+ if (DOT11F_FAILED(nStatus)) {
+ lim_log(pMac, LOGP, FL("Failed to calculate the packed size f"
+ "or a Radio Measure Report (0x%08x)."),
+ nStatus);
+ /* We'll fall back on the worst case scenario: */
+ nPayload = sizeof(tDot11fLinkMeasurementReport);
+ cdf_mem_free(frm);
+ return eSIR_FAILURE;
+ } else if (DOT11F_WARNED(nStatus)) {
+ lim_log(pMac, LOGW, FL("There were warnings while calculating "
+ "the packed size for a Radio Measure Rep"
+ "ort (0x%08x)."), nStatus);
+ }
+
+ nBytes = nPayload + sizeof(tSirMacMgmtHdr);
+
+ cdf_status =
+ cds_packet_alloc((uint16_t) nBytes, (void **)&pFrame,
+ (void **)&pPacket);
+ if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
+ lim_log(pMac, LOGP,
+ FL("Failed to allocate %d bytes for a Radio Measure "
+ "Report."), nBytes);
+ cdf_mem_free(frm);
+ return eSIR_FAILURE;
+ }
+ /* Paranoia: */
+ cdf_mem_set(pFrame, nBytes, 0);
+
+ /* Copy necessary info to BD */
+ lim_populate_mac_header(pMac, pFrame, SIR_MAC_MGMT_FRAME,
+ SIR_MAC_MGMT_ACTION, peer, psessionEntry->selfMacAddr);
+
+ /* Update A3 with the BSSID */
+ pMacHdr = (tpSirMacMgmtHdr) pFrame;
+
+ sir_copy_mac_addr(pMacHdr->bssId, psessionEntry->bssId);
+
+#ifdef WLAN_FEATURE_11W
+ lim_set_protected_bit(pMac, psessionEntry, peer, pMacHdr);
+#endif
+
+ /* Now, we're ready to "pack" the frames */
+ nStatus = dot11f_pack_radio_measurement_report(pMac,
+ frm,
+ pFrame +
+ sizeof(tSirMacMgmtHdr),
+ nPayload, &nPayload);
+
+ if (DOT11F_FAILED(nStatus)) {
+ lim_log(pMac, LOGE,
+ FL("Failed to pack an Radio Measure Report (0x%08x)."),
+ nStatus);
+
+ /* FIXME - Need to convert to tSirRetStatus */
+ statusCode = eSIR_FAILURE;
+ goto returnAfterError;
+ } else if (DOT11F_WARNED(nStatus)) {
+ lim_log(pMac, LOGW,
+ FL("There were warnings while packing Radio "
+ "Measure Report (0x%08x)."), nStatus);
+ }
+
+ lim_log(pMac, LOGW, FL("Sending a Radio Measure Report to "));
+ lim_print_mac_addr(pMac, peer, LOGW);
+
+ if ((SIR_BAND_5_GHZ == lim_get_rf_band(psessionEntry->currentOperChannel))
+ || (psessionEntry->pePersona == CDF_P2P_CLIENT_MODE) ||
+ (psessionEntry->pePersona == CDF_P2P_GO_MODE)
+ ) {
+ txFlag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME;
+ }
+
+ MTRACE(cdf_trace(CDF_MODULE_ID_PE, TRACE_CODE_TX_MGMT,
+ psessionEntry->peSessionId, pMacHdr->fc.subType));
+ cdf_status = wma_tx_frame(pMac,
+ pPacket,
+ (uint16_t) nBytes,
+ TXRX_FRM_802_11_MGMT,
+ ANI_TXDIR_TODS,
+ 7, lim_tx_complete, pFrame, txFlag,
+ smeSessionId, 0);
+ MTRACE(cdf_trace(CDF_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE,
+ psessionEntry->peSessionId, cdf_status));
+ if (CDF_STATUS_SUCCESS != cdf_status) {
+ PELOGE(lim_log
+ (pMac, LOGE, FL("wma_tx_frame FAILED! Status [%d]"),
+ cdf_status);
+ )
+ statusCode = eSIR_FAILURE;
+ /* Pkt will be freed up by the callback */
+ cdf_mem_free(frm);
+ return statusCode;
+ } else {
+ cdf_mem_free(frm);
+ return eSIR_SUCCESS;
+ }
+
+returnAfterError:
+ cdf_mem_free(frm);
+ cds_packet_free((void *)pPacket);
+ return statusCode;
+}
+
+#endif
+
+#ifdef WLAN_FEATURE_11W
+/**
+ * \brief Send SA query request action frame to peer
+ *
+ * \sa lim_send_sa_query_request_frame
+ *
+ *
+ * \param pMac The global tpAniSirGlobal object
+ *
+ * \param transId Transaction identifier
+ *
+ * \param peer The Mac address of the station to which this action frame is addressed
+ *
+ * \param psessionEntry The PE session entry
+ *
+ * \return eSIR_SUCCESS if setup completes successfully
+ * eSIR_FAILURE is some problem is encountered
+ */
+
+tSirRetStatus lim_send_sa_query_request_frame(tpAniSirGlobal pMac, uint8_t *transId,
+ tSirMacAddr peer,
+ tpPESession psessionEntry)
+{
+
+ tDot11fSaQueryReq frm; /* SA query request action frame */
+ uint8_t *pFrame;
+ tSirRetStatus nSirStatus;
+ tpSirMacMgmtHdr pMacHdr;
+ uint32_t nBytes, nPayload, nStatus;
+ void *pPacket;
+ CDF_STATUS cdf_status;
+ uint8_t txFlag = 0;
+ uint8_t smeSessionId = 0;
+
+ cdf_mem_set((uint8_t *) &frm, sizeof(frm), 0);
+ frm.Category.category = SIR_MAC_ACTION_SA_QUERY;
+ /* 11w action field is :
+ action: 0 --> SA Query Request action frame
+ action: 1 --> SA Query Response action frame */
+ frm.Action.action = SIR_MAC_SA_QUERY_REQ;
+ /* 11w SA Query Request transId */
+ cdf_mem_copy(&frm.TransactionId.transId[0], &transId[0], 2);
+
+ nStatus = dot11f_get_packed_sa_query_req_size(pMac, &frm, &nPayload);
+ if (DOT11F_FAILED(nStatus)) {
+ lim_log(pMac, LOGP, FL("Failed to calculate the packed size "
+ "for an SA Query Request (0x%08x)."),
+ nStatus);
+ /* We'll fall back on the worst case scenario: */
+ nPayload = sizeof(tDot11fSaQueryReq);
+ } else if (DOT11F_WARNED(nStatus)) {
+ lim_log(pMac, LOGW, FL("There were warnings while calculating "
+ "the packed size for an SA Query Request"
+ " (0x%08x)."), nStatus);
+ }
+
+ nBytes = nPayload + sizeof(tSirMacMgmtHdr);
+ cdf_status =
+ cds_packet_alloc(nBytes, (void **)&pFrame, (void **)&pPacket);
+ if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
+ lim_log(pMac, LOGP,
+ FL("Failed to allocate %d bytes for a SA Query Request "
+ "action frame"), nBytes);
+ return eSIR_FAILURE;
+ }
+ /* Paranoia: */
+ cdf_mem_set(pFrame, nBytes, 0);
+
+ /* Copy necessary info to BD */
+ lim_populate_mac_header(pMac, pFrame, SIR_MAC_MGMT_FRAME,
+ SIR_MAC_MGMT_ACTION, peer, psessionEntry->selfMacAddr);
+
+ /* Update A3 with the BSSID */
+ pMacHdr = (tpSirMacMgmtHdr) pFrame;
+
+ sir_copy_mac_addr(pMacHdr->bssId, psessionEntry->bssId);
+
+ /* Since this is a SA Query Request, set the "protect" (aka WEP) bit */
+ /* in the FC */
+ lim_set_protected_bit(pMac, psessionEntry, peer, pMacHdr);
+
+ /* Pack 11w SA Query Request frame */
+ nStatus = dot11f_pack_sa_query_req(pMac,
+ &frm,
+ pFrame + sizeof(tSirMacMgmtHdr),
+ nPayload, &nPayload);
+
+ if (DOT11F_FAILED(nStatus)) {
+ lim_log(pMac, LOGE,
+ FL("Failed to pack an SA Query Request (0x%08x)."),
+ nStatus);
+ /* FIXME - Need to convert to tSirRetStatus */
+ nSirStatus = eSIR_FAILURE;
+ goto returnAfterError;
+ } else if (DOT11F_WARNED(nStatus)) {
+ lim_log(pMac, LOGW,
+ FL
+ ("There were warnings while packing SA Query Request (0x%08x)."),
+ nStatus);
+ }
+
+ lim_log(pMac, LOG1, FL("Sending an SA Query Request to "));
+ lim_print_mac_addr(pMac, peer, LOG1);
+ lim_log(pMac, LOG1, FL("Sending an SA Query Request from "));
+ lim_print_mac_addr(pMac, psessionEntry->selfMacAddr, LOG1);
+
+ if ((SIR_BAND_5_GHZ == lim_get_rf_band(psessionEntry->currentOperChannel))
+#ifdef WLAN_FEATURE_P2P
+ || (psessionEntry->pePersona == CDF_P2P_CLIENT_MODE) ||
+ (psessionEntry->pePersona == CDF_P2P_GO_MODE)
+#endif
+ ) {
+ txFlag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME;
+ }
+ smeSessionId = psessionEntry->smeSessionId;
+
+ cdf_status = wma_tx_frame(pMac,
+ pPacket,
+ (uint16_t) nBytes,
+ TXRX_FRM_802_11_MGMT,
+ ANI_TXDIR_TODS,
+ 7, lim_tx_complete, pFrame, txFlag,
+ smeSessionId, 0);
+ if (CDF_STATUS_SUCCESS != cdf_status) {
+ PELOGE(lim_log
+ (pMac, LOGE, FL("wma_tx_frame FAILED! Status [%d]"),
+ cdf_status);
+ )
+ nSirStatus = eSIR_FAILURE;
+ /* Pkt will be freed up by the callback */
+ return nSirStatus;
+ } else {
+ return eSIR_SUCCESS;
+ }
+
+returnAfterError:
+ cds_packet_free((void *)pPacket);
+ return nSirStatus;
+} /* End lim_send_sa_query_request_frame */
+
+/**
+ * \brief Send SA query response action frame to peer
+ *
+ * \sa lim_send_sa_query_response_frame
+ *
+ *
+ * \param pMac The global tpAniSirGlobal object
+ *
+ * \param transId Transaction identifier received in SA query request action frame
+ *
+ * \param peer The Mac address of the AP to which this action frame is addressed
+ *
+ * \param psessionEntry The PE session entry
+ *
+ * \return eSIR_SUCCESS if setup completes successfully
+ * eSIR_FAILURE is some problem is encountered
+ */
+
+tSirRetStatus lim_send_sa_query_response_frame(tpAniSirGlobal pMac,
+ uint8_t *transId, tSirMacAddr peer,
+ tpPESession psessionEntry)
+{
+
+ tDot11fSaQueryRsp frm; /* SA query reponse action frame */
+ uint8_t *pFrame;
+ tSirRetStatus nSirStatus;
+ tpSirMacMgmtHdr pMacHdr;
+ uint32_t nBytes, nPayload, nStatus;
+ void *pPacket;
+ CDF_STATUS cdf_status;
+ uint8_t txFlag = 0;
+ uint8_t smeSessionId = 0;
+
+ smeSessionId = psessionEntry->smeSessionId;
+
+ cdf_mem_set((uint8_t *) &frm, sizeof(frm), 0);
+ frm.Category.category = SIR_MAC_ACTION_SA_QUERY;
+ /*11w action field is :
+ action: 0 --> SA query request action frame
+ action: 1 --> SA query response action frame */
+ frm.Action.action = SIR_MAC_SA_QUERY_RSP;
+ /*11w SA query response transId is same as
+ SA query request transId */
+ cdf_mem_copy(&frm.TransactionId.transId[0], &transId[0], 2);
+
+ nStatus = dot11f_get_packed_sa_query_rsp_size(pMac, &frm, &nPayload);
+ if (DOT11F_FAILED(nStatus)) {
+ lim_log(pMac, LOGP, FL("Failed to calculate the packed size f"
+ "or a SA Query Response (0x%08x)."),
+ nStatus);
+ /* We'll fall back on the worst case scenario: */
+ nPayload = sizeof(tDot11fSaQueryRsp);
+ } else if (DOT11F_WARNED(nStatus)) {
+ lim_log(pMac, LOGW, FL("There were warnings while calculating "
+ "the packed size for an SA Query Response"
+ " (0x%08x)."), nStatus);
+ }
+
+ nBytes = nPayload + sizeof(tSirMacMgmtHdr);
+ cdf_status =
+ cds_packet_alloc(nBytes, (void **)&pFrame, (void **)&pPacket);
+ if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
+ lim_log(pMac, LOGP,
+ FL("Failed to allocate %d bytes for a SA query response"
+ " action frame"), nBytes);
+ return eSIR_FAILURE;
+ }
+ /* Paranoia: */
+ cdf_mem_set(pFrame, nBytes, 0);
+
+ /* Copy necessary info to BD */
+ lim_populate_mac_header(pMac, pFrame, SIR_MAC_MGMT_FRAME,
+ SIR_MAC_MGMT_ACTION, peer, psessionEntry->selfMacAddr);
+
+ /* Update A3 with the BSSID */
+ pMacHdr = (tpSirMacMgmtHdr) pFrame;
+
+ sir_copy_mac_addr(pMacHdr->bssId, psessionEntry->bssId);
+
+ /* Since this is a SA Query Response, set the "protect" (aka WEP) bit */
+ /* in the FC */
+ lim_set_protected_bit(pMac, psessionEntry, peer, pMacHdr);
+
+ /* Pack 11w SA query response frame */
+ nStatus = dot11f_pack_sa_query_rsp(pMac,
+ &frm,
+ pFrame + sizeof(tSirMacMgmtHdr),
+ nPayload, &nPayload);
+
+ if (DOT11F_FAILED(nStatus)) {
+ lim_log(pMac, LOGE,
+ FL("Failed to pack an SA Query Response (0x%08x)."),
+ nStatus);
+ /* FIXME - Need to convert to tSirRetStatus */
+ nSirStatus = eSIR_FAILURE;
+ goto returnAfterError;
+ } else if (DOT11F_WARNED(nStatus)) {
+ lim_log(pMac, LOGW,
+ FL
+ ("There were warnings while packing SA Query Response (0x%08x)."),
+ nStatus);
+ }
+
+ lim_log(pMac, LOG1, FL("Sending a SA Query Response to "));
+ lim_print_mac_addr(pMac, peer, LOGW);
+
+ if ((SIR_BAND_5_GHZ == lim_get_rf_band(psessionEntry->currentOperChannel))
+#ifdef WLAN_FEATURE_P2P
+ || (psessionEntry->pePersona == CDF_P2P_CLIENT_MODE) ||
+ (psessionEntry->pePersona == CDF_P2P_GO_MODE)
+#endif
+ ) {
+ txFlag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME;
+ }
+
+ MTRACE(cdf_trace(CDF_MODULE_ID_PE, TRACE_CODE_TX_MGMT,
+ psessionEntry->peSessionId, pMacHdr->fc.subType));
+ cdf_status = wma_tx_frame(pMac,
+ pPacket,
+ (uint16_t) nBytes,
+ TXRX_FRM_802_11_MGMT,
+ ANI_TXDIR_TODS,
+ 7, lim_tx_complete, pFrame, txFlag,
+ smeSessionId, 0);
+ MTRACE(cdf_trace(CDF_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE,
+ psessionEntry->peSessionId, cdf_status));
+ if (CDF_STATUS_SUCCESS != cdf_status) {
+ PELOGE(lim_log
+ (pMac, LOGE, FL("wma_tx_frame FAILED! Status [%d]"),
+ cdf_status);
+ )
+ nSirStatus = eSIR_FAILURE;
+ /* Pkt will be freed up by the callback */
+ return nSirStatus;
+ } else {
+ return eSIR_SUCCESS;
+ }
+
+returnAfterError:
+ cds_packet_free((void *)pPacket);
+ return nSirStatus;
+} /* End lim_send_sa_query_response_frame */
+#endif
diff --git a/core/mac/src/pe/lim/lim_send_messages.c b/core/mac/src/pe/lim/lim_send_messages.c
new file mode 100644
index 0000000..e47bf2f
--- /dev/null
+++ b/core/mac/src/pe/lim/lim_send_messages.c
@@ -0,0 +1,854 @@
+/*
+ * Copyright (c) 2011-2015 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.
+ */
+
+/*
+ *
+ * lim_send_messages.c: Provides functions to send messages or Indications to HAL.
+ * Author: Sunit Bhatia
+ * Date: 09/21/2006
+ * History:-
+ * Date Modified by Modification Information
+ *
+ * --------------------------------------------------------------------------
+ *
+ */
+#include "lim_send_messages.h"
+#include "cfg_api.h"
+#include "lim_trace.h"
+#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */
+#include "host_diag_core_log.h"
+#endif /* FEATURE_WLAN_DIAG_SUPPORT */
+/* When beacon filtering is enabled, firmware will
+ * analyze the selected beacons received during BMPS,
+ * and monitor any changes in the IEs as listed below.
+ * The format of the table is:
+ * - EID
+ * - Check for IE presence
+ * - Byte offset
+ * - Byte value
+ * - Bit Mask
+ * - Byte refrence
+ */
+static tBeaconFilterIe beacon_filter_table[] = {
+ {SIR_MAC_DS_PARAM_SET_EID, 0, {0, 0, DS_PARAM_CHANNEL_MASK, 0} },
+ {SIR_MAC_ERP_INFO_EID, 0, {0, 0, ERP_FILTER_MASK, 0} },
+ {SIR_MAC_EDCA_PARAM_SET_EID, 0, {0, 0, EDCA_FILTER_MASK, 0} },
+ {SIR_MAC_QOS_CAPABILITY_EID, 0, {0, 0, QOS_FILTER_MASK, 0} },
+ {SIR_MAC_CHNL_SWITCH_ANN_EID, 1, {0, 0, 0, 0} },
+ {SIR_MAC_HT_INFO_EID, 0, {0, 0, HT_BYTE0_FILTER_MASK, 0} },
+ {SIR_MAC_HT_INFO_EID, 0, {2, 0, HT_BYTE2_FILTER_MASK, 0} },
+ {SIR_MAC_HT_INFO_EID, 0, {5, 0, HT_BYTE5_FILTER_MASK, 0} }
+#if defined WLAN_FEATURE_VOWIFI
+ , {SIR_MAC_PWR_CONSTRAINT_EID, 0, {0, 0, 0, 0} }
+#endif
+#ifdef WLAN_FEATURE_11AC
+ , {SIR_MAC_VHT_OPMODE_EID, 0, {0, 0, 0, 0} }
+ , {SIR_MAC_VHT_OPERATION_EID, 0, {0, 0, VHTOP_CHWIDTH_MASK, 0} }
+#endif
+};
+
+/**
+ * lim_send_cf_params()
+ *
+ ***FUNCTION:
+ * This function is called to send CFP Parameters to WMA, when they are changed.
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ * NA
+ *
+ ***NOTE:
+ * NA
+ *
+ * @param pMac pointer to Global Mac structure.
+ * @param bssIdx Bss Index of the BSS to which STA is associated.
+ * @param cfpCount CFP Count, if that is changed.
+ * @param cfpPeriod CFP Period if that is changed.
+ *
+ * @return success if message send is ok, else false.
+ */
+tSirRetStatus lim_send_cf_params(tpAniSirGlobal pMac, uint8_t bssIdx,
+ uint8_t cfpCount, uint8_t cfpPeriod)
+{
+ tpUpdateCFParams pCFParams = NULL;
+ tSirRetStatus retCode = eSIR_SUCCESS;
+ tSirMsgQ msgQ;
+
+ pCFParams = cdf_mem_malloc(sizeof(tUpdateCFParams));
+ if (NULL == pCFParams) {
+ lim_log(pMac, LOGP,
+ FL("Unable to allocate memory during Update CF Params"));
+ retCode = eSIR_MEM_ALLOC_FAILED;
+ goto returnFailure;
+ }
+ cdf_mem_set((uint8_t *) pCFParams, sizeof(tUpdateCFParams), 0);
+ pCFParams->cfpCount = cfpCount;
+ pCFParams->cfpPeriod = cfpPeriod;
+ pCFParams->bssIdx = bssIdx;
+
+ msgQ.type = WMA_UPDATE_CF_IND;
+ msgQ.reserved = 0;
+ msgQ.bodyptr = pCFParams;
+ msgQ.bodyval = 0;
+ lim_log(pMac, LOG3, FL("Sending WMA_UPDATE_CF_IND..."));
+ MTRACE(mac_trace_msg_tx(pMac, NO_SESSION, msgQ.type));
+ retCode = wma_post_ctrl_msg(pMac, &msgQ);
+ if (eSIR_SUCCESS != retCode) {
+ cdf_mem_free(pCFParams);
+ lim_log(pMac, LOGP,
+ FL("Posting WMA_UPDATE_CF_IND failed, reason=%X"),
+ retCode);
+ }
+returnFailure:
+ return retCode;
+}
+
+/**
+ * lim_send_beacon_params() - updates bcn params to WMA
+ *
+ * @pMac : pointer to Global Mac structure.
+ * @tpUpdateBeaconParams : pointer to the structure, which contains the beacon
+ * parameters which are changed.
+ *
+ * This function is called to send beacon interval, short preamble or other
+ * parameters to WMA, which are changed and indication is received in beacon.
+ *
+ * @return success if message send is ok, else false.
+ */
+tSirRetStatus lim_send_beacon_params(tpAniSirGlobal pMac,
+ tpUpdateBeaconParams pUpdatedBcnParams,
+ tpPESession psessionEntry)
+{
+ tpUpdateBeaconParams pBcnParams = NULL;
+ tSirRetStatus retCode = eSIR_SUCCESS;
+ tSirMsgQ msgQ;
+
+ pBcnParams = cdf_mem_malloc(sizeof(*pBcnParams));
+ if (NULL == pBcnParams) {
+ lim_log(pMac, LOGP,
+ FL("Unable to allocate memory during Update Beacon Params"));
+ return eSIR_MEM_ALLOC_FAILED;
+ }
+ cdf_mem_copy((uint8_t *) pBcnParams, pUpdatedBcnParams,
+ sizeof(*pBcnParams));
+ msgQ.type = WMA_UPDATE_BEACON_IND;
+ msgQ.reserved = 0;
+ msgQ.bodyptr = pBcnParams;
+ msgQ.bodyval = 0;
+ PELOG3(lim_log(pMac, LOG3,
+ FL("Sending WMA_UPDATE_BEACON_IND, paramChangeBitmap in hex = %x"),
+ pUpdatedBcnParams->paramChangeBitmap);)
+ if (NULL == psessionEntry) {
+ cdf_mem_free(pBcnParams);
+ MTRACE(mac_trace_msg_tx(pMac, NO_SESSION, msgQ.type));
+ return eSIR_FAILURE;
+ } else {
+ MTRACE(mac_trace_msg_tx(pMac,
+ psessionEntry->peSessionId,
+ msgQ.type));
+ }
+ pBcnParams->smeSessionId = psessionEntry->smeSessionId;
+ retCode = wma_post_ctrl_msg(pMac, &msgQ);
+ if (eSIR_SUCCESS != retCode) {
+ cdf_mem_free(pBcnParams);
+ lim_log(pMac, LOGP,
+ FL("Posting WMA_UPDATE_BEACON_IND, reason=%X"),
+ retCode);
+ }
+ lim_send_beacon_ind(pMac, psessionEntry);
+ return retCode;
+}
+
+/**
+ * lim_send_switch_chnl_params()
+ *
+ ***FUNCTION:
+ * This function is called to send Channel Switch Indication to WMA
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ * NA
+ *
+ ***NOTE:
+ * NA
+ *
+ * @param pMac pointer to Global Mac structure.
+ * @param chnlNumber New Channel Number to be switched to.
+ * @param ch_width an enum for channel width.
+ * @param localPowerConstraint 11h local power constraint value
+ *
+ * @return success if message send is ok, else false.
+ */
+#if !defined WLAN_FEATURE_VOWIFI
+tSirRetStatus lim_send_switch_chnl_params(tpAniSirGlobal pMac,
+ uint8_t chnlNumber,
+ uint8_t ch_center_freq_seg0,
+ uint8_t ch_center_freq_seg1,
+ phy_ch_width ch_width,
+ uint8_t localPwrConstraint,
+ uint8_t peSessionId,
+ uint8_t is_restart)
+#else
+tSirRetStatus lim_send_switch_chnl_params(tpAniSirGlobal pMac,
+ uint8_t chnlNumber,
+ uint8_t ch_center_freq_seg0,
+ uint8_t ch_center_freq_seg1,
+ phy_ch_width ch_width,
+ tPowerdBm maxTxPower,
+ uint8_t peSessionId,
+ uint8_t is_restart)
+#endif
+{
+ tpSwitchChannelParams pChnlParams = NULL;
+ tSirMsgQ msgQ;
+ tpPESession pSessionEntry;
+ pSessionEntry = pe_find_session_by_session_id(pMac, peSessionId);
+ if (pSessionEntry == NULL) {
+ lim_log(pMac, LOGP, FL(
+ "Unable to get Session for session Id %d"),
+ peSessionId);
+ return eSIR_FAILURE;
+ }
+ pChnlParams = cdf_mem_malloc(sizeof(tSwitchChannelParams));
+ if (NULL == pChnlParams) {
+ lim_log(pMac, LOGP, FL(
+ "Unable to allocate memory for Switch Ch Params"));
+ return eSIR_MEM_ALLOC_FAILED;
+ }
+ cdf_mem_set((uint8_t *) pChnlParams, sizeof(tSwitchChannelParams), 0);
+ pChnlParams->channelNumber = chnlNumber;
+ pChnlParams->ch_center_freq_seg0 = ch_center_freq_seg0;
+ pChnlParams->ch_center_freq_seg1 = ch_center_freq_seg1;
+ pChnlParams->ch_width = ch_width;
+ cdf_mem_copy(pChnlParams->selfStaMacAddr, pSessionEntry->selfMacAddr,
+ sizeof(tSirMacAddr));
+#if defined WLAN_FEATURE_VOWIFI
+ pChnlParams->maxTxPower = maxTxPower;
+#else
+ pChnlParams->localPowerConstraint = localPwrConstraint;
+#endif
+ cdf_mem_copy(pChnlParams->bssId, pSessionEntry->bssId,
+ sizeof(tSirMacAddr));
+ pChnlParams->peSessionId = peSessionId;
+ pChnlParams->vhtCapable = pSessionEntry->vhtCapability;
+ pChnlParams->dot11_mode = pSessionEntry->dot11mode;
+ pChnlParams->nss = pSessionEntry->nss;
+ lim_log(pMac, LOG2, FL("nss value: %d"), pChnlParams->nss);
+
+ /*Set DFS flag for DFS channel */
+ if (cds_get_channel_state(chnlNumber) == CHANNEL_STATE_DFS)
+ pChnlParams->isDfsChannel = true;
+ else
+ pChnlParams->isDfsChannel = false;
+
+ pChnlParams->restart_on_chan_switch = is_restart;
+
+ /* we need to defer the message until we
+ * get the response back from WMA
+ */
+ SET_LIM_PROCESS_DEFD_MESGS(pMac, false);
+ msgQ.type = WMA_CHNL_SWITCH_REQ;
+ msgQ.reserved = 0;
+ msgQ.bodyptr = pChnlParams;
+ msgQ.bodyval = 0;
+#if defined WLAN_FEATURE_VOWIFI
+ PELOG3(lim_log(pMac, LOG3, FL(
+ "Sending CH_SWITCH_REQ, ch_width %d, ch_num %d, maxTxPower %d"),
+ pChnlParams->ch_width,
+ pChnlParams->channelNumber, pChnlParams->maxTxPower);)
+#else
+ PELOG3(lim_log(pMac, LOG3, FL(
+ "Sending CH_SWITCH_REQ, ch_width %d, ch_num %d, local_pwr_constraint %d"),
+ pChnlParams->ch_width,
+ pChnlParams->channelNumber,
+ pChnlParams->localPowerConstraint);)
+#endif
+ MTRACE(mac_trace_msg_tx(pMac, peSessionId, msgQ.type));
+ if (eSIR_SUCCESS != wma_post_ctrl_msg(pMac, &msgQ)) {
+ cdf_mem_free(pChnlParams);
+ lim_log(pMac, LOGP, FL(
+ "Posting CH_SWITCH_REQ to WMA failed"));
+ return eSIR_FAILURE;
+ }
+ return eSIR_SUCCESS;
+}
+
+/**
+ * lim_send_edca_params()
+ *
+ ***FUNCTION:
+ * This function is called to send dynamically changing EDCA Parameters to WMA.
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ * NA
+ *
+ ***NOTE:
+ * NA
+ *
+ * @param pMac pointer to Global Mac structure.
+ * @param tpUpdatedEdcaParams pointer to the structure which contains
+ * dynamically changing EDCA parameters.
+ * @param highPerformance If the peer is Airgo (taurus) then switch to highPerformance is true.
+ *
+ * @return success if message send is ok, else false.
+ */
+tSirRetStatus lim_send_edca_params(tpAniSirGlobal pMac,
+ tSirMacEdcaParamRecord *pUpdatedEdcaParams,
+ uint16_t bssIdx)
+{
+ tEdcaParams *pEdcaParams = NULL;
+ tSirRetStatus retCode = eSIR_SUCCESS;
+ tSirMsgQ msgQ;
+ uint8_t i;
+
+ pEdcaParams = cdf_mem_malloc(sizeof(tEdcaParams));
+ if (NULL == pEdcaParams) {
+ lim_log(pMac, LOGP,
+ FL("Unable to allocate memory during Update EDCA Params"));
+ retCode = eSIR_MEM_ALLOC_FAILED;
+ return retCode;
+ }
+ pEdcaParams->bssIdx = bssIdx;
+ pEdcaParams->acbe = pUpdatedEdcaParams[EDCA_AC_BE];
+ pEdcaParams->acbk = pUpdatedEdcaParams[EDCA_AC_BK];
+ pEdcaParams->acvi = pUpdatedEdcaParams[EDCA_AC_VI];
+ pEdcaParams->acvo = pUpdatedEdcaParams[EDCA_AC_VO];
+ msgQ.type = WMA_UPDATE_EDCA_PROFILE_IND;
+ msgQ.reserved = 0;
+ msgQ.bodyptr = pEdcaParams;
+ msgQ.bodyval = 0;
+ PELOG1(lim_log(pMac, LOG1,
+ FL("Sending WMA_UPDATE_EDCA_PROFILE_IND, EDCA Parameters:"));)
+ for (i = 0; i < MAX_NUM_AC; i++) {
+ PELOG1(lim_log(pMac, LOG1,
+ FL("AC[%d]: AIFSN %d, ACM %d, CWmin %d, CWmax %d, TxOp %d "),
+ i, pUpdatedEdcaParams[i].aci.aifsn,
+ pUpdatedEdcaParams[i].aci.acm,
+ pUpdatedEdcaParams[i].cw.min,
+ pUpdatedEdcaParams[i].cw.max,
+ pUpdatedEdcaParams[i].txoplimit);)
+ }
+ MTRACE(mac_trace_msg_tx(pMac, NO_SESSION, msgQ.type));
+ retCode = wma_post_ctrl_msg(pMac, &msgQ);
+ if (eSIR_SUCCESS != retCode) {
+ cdf_mem_free(pEdcaParams);
+ lim_log(pMac, LOGP,
+ FL("Posting WMA_UPDATE_EDCA_PROFILE_IND failed, reason=%X"),
+ retCode);
+ }
+ return retCode;
+}
+
+/**
+ * lim_set_active_edca_params() - Choose best EDCA parameters
+ *
+ * @mac_ctx: pointer to Global Mac structure.
+ * @edca_params: pointer to the local EDCA parameters
+ * @pe_session: point to the session entry
+ *
+ * This function is called to set the most up-to-date EDCA parameters
+ * given the default local EDCA parameters. The rules are as following:
+ * - If ACM bit is set for all ACs, then downgrade everything to Best Effort.
+ * - If ACM is not set for any AC, then PE will use the default EDCA
+ * parameters as advertised by AP.
+ * - If ACM is set in any of the ACs, PE will use the EDCA parameters
+ * from the next best AC for which ACM is not enabled.
+ *
+ * Return: none
+ */
+
+void lim_set_active_edca_params(tpAniSirGlobal mac_ctx,
+ tSirMacEdcaParamRecord *edca_params,
+ tpPESession pe_session)
+{
+ uint8_t ac, new_ac, i;
+ uint8_t ac_admitted;
+#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */
+ host_log_qos_edca_pkt_type *log_ptr = NULL;
+#endif /* FEATURE_WLAN_DIAG_SUPPORT */
+ /* Initialize gLimEdcaParamsActive[] to be same as localEdcaParams */
+ pe_session->gLimEdcaParamsActive[EDCA_AC_BE] = edca_params[EDCA_AC_BE];
+ pe_session->gLimEdcaParamsActive[EDCA_AC_BK] = edca_params[EDCA_AC_BK];
+ pe_session->gLimEdcaParamsActive[EDCA_AC_VI] = edca_params[EDCA_AC_VI];
+ pe_session->gLimEdcaParamsActive[EDCA_AC_VO] = edca_params[EDCA_AC_VO];
+ /* An AC requires downgrade if the ACM bit is set, and the AC has not
+ * yet been admitted in uplink or bi-directions.
+ * If an AC requires downgrade, it will downgrade to the next beset AC
+ * for which ACM is not enabled.
+ *
+ * - There's no need to downgrade AC_BE since it IS the lowest AC. Hence
+ * start the for loop with AC_BK.
+ * - If ACM bit is set for an AC, initially downgrade it to AC_BE. Then
+ * traverse thru the AC list. If we do find the next best AC which is
+ * better than AC_BE, then use that one. For example, if ACM bits are set
+ * such that: BE_ACM=1, BK_ACM=1, VI_ACM=1, VO_ACM=0
+ * then all AC will be downgraded to AC_BE.
+ */
+ lim_log(mac_ctx, LOG1, FL("adAdmitMask[UPLINK] = 0x%x "),
+ pe_session->gAcAdmitMask[SIR_MAC_DIRECTION_UPLINK]);
+ lim_log(mac_ctx, LOG1, FL("adAdmitMask[DOWNLINK] = 0x%x "),
+ pe_session->gAcAdmitMask[SIR_MAC_DIRECTION_DNLINK]);
+ for (ac = EDCA_AC_BK; ac <= EDCA_AC_VO; ac++) {
+ ac_admitted =
+ ((pe_session->gAcAdmitMask[SIR_MAC_DIRECTION_UPLINK] &
+ (1 << ac)) >> ac);
+
+ lim_log(mac_ctx, LOG1,
+ FL("For AC[%d]: acm=%d, ac_admitted=%d "),
+ ac, edca_params[ac].aci.acm, ac_admitted);
+ if ((edca_params[ac].aci.acm == 1) && (ac_admitted == 0)) {
+ lim_log(mac_ctx, LOG1,
+ FL("We need to downgrade AC %d!! "), ac);
+ /* Loop backwards through AC values until it finds
+ * acm == 0 or reaches EDCA_AC_BE.
+ * Note that for block has no executable statements.
+ */
+ for (i = ac - 1;
+ (i > EDCA_AC_BE &&
+ (edca_params[i].aci.acm != 0));
+ i--)
+ ;
+ new_ac = i;
+ lim_log(mac_ctx, LOGW,
+ FL("Downgrading AC %d ---> AC %d "),
+ ac, new_ac);
+ pe_session->gLimEdcaParamsActive[ac] =
+ edca_params[new_ac];
+ }
+ }
+/* log: LOG_WLAN_QOS_EDCA_C */
+#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */
+ WLAN_HOST_DIAG_LOG_ALLOC(log_ptr, host_log_qos_edca_pkt_type,
+ LOG_WLAN_QOS_EDCA_C);
+ if (log_ptr) {
+ tSirMacEdcaParamRecord *rec;
+
+ rec = &pe_session->gLimEdcaParamsActive[EDCA_AC_BE];
+ log_ptr->aci_be = rec->aci.aci;
+ log_ptr->cw_be = rec->cw.max << 4 | rec->cw.min;
+ log_ptr->txoplimit_be = rec->txoplimit;
+
+ rec = &pe_session->gLimEdcaParamsActive[EDCA_AC_BK];
+ log_ptr->aci_bk = rec->aci.aci;
+ log_ptr->cw_bk = rec->cw.max << 4 | rec->cw.min;
+ log_ptr->txoplimit_bk = rec->txoplimit;
+
+ rec = &pe_session->gLimEdcaParamsActive[EDCA_AC_VI];
+ log_ptr->aci_vi = rec->aci.aci;
+ log_ptr->cw_vi = rec->cw.max << 4 | rec->cw.min;
+ log_ptr->txoplimit_vi = rec->txoplimit;
+
+ rec = &pe_session->gLimEdcaParamsActive[EDCA_AC_VO];
+ log_ptr->aci_vo = rec->aci.aci;
+ log_ptr->cw_vo = rec->cw.max << 4 | rec->cw.min;
+ log_ptr->txoplimit_vo = rec->txoplimit;
+ }
+ WLAN_HOST_DIAG_LOG_REPORT(log_ptr);
+#endif /* FEATURE_WLAN_DIAG_SUPPORT */
+
+ return;
+}
+
+/** ---------------------------------------------------------
+ \fn lim_set_link_state
+ \brief LIM sends a message to WMA to set the link state
+ \param tpAniSirGlobal pMac
+ \param tSirLinkState state
+ \return None
+ -----------------------------------------------------------*/
+tSirRetStatus lim_set_link_state(tpAniSirGlobal pMac, tSirLinkState state,
+ tSirMacAddr bssId, tSirMacAddr selfMacAddr,
+ tpSetLinkStateCallback callback,
+ void *callbackArg)
+{
+ tSirMsgQ msgQ;
+ tSirRetStatus retCode;
+ tpLinkStateParams pLinkStateParams = NULL;
+ /* Allocate memory. */
+ pLinkStateParams = cdf_mem_malloc(sizeof(tLinkStateParams));
+ if (NULL == pLinkStateParams) {
+ lim_log(pMac, LOGP,
+ FL
+ ("Unable to allocate memory while sending Set Link State"));
+ retCode = eSIR_MEM_ALLOC_FAILED;
+ return retCode;
+ }
+ cdf_mem_set((uint8_t *) pLinkStateParams, sizeof(tLinkStateParams), 0);
+ pLinkStateParams->state = state;
+ pLinkStateParams->callback = callback;
+ pLinkStateParams->callbackArg = callbackArg;
+
+ /* Copy Mac address */
+ sir_copy_mac_addr(pLinkStateParams->bssid, bssId);
+ sir_copy_mac_addr(pLinkStateParams->selfMacAddr, selfMacAddr);
+
+ msgQ.type = WMA_SET_LINK_STATE;
+ msgQ.reserved = 0;
+ msgQ.bodyptr = pLinkStateParams;
+ msgQ.bodyval = 0;
+
+ MTRACE(mac_trace_msg_tx(pMac, NO_SESSION, msgQ.type));
+
+ retCode = (uint32_t) wma_post_ctrl_msg(pMac, &msgQ);
+ if (retCode != eSIR_SUCCESS) {
+ cdf_mem_free(pLinkStateParams);
+ lim_log(pMac, LOGP,
+ FL("Posting link state %d failed, reason = %x "), state,
+ retCode);
+ }
+ return retCode;
+}
+
+#ifdef WLAN_FEATURE_VOWIFI_11R
+extern tSirRetStatus lim_set_link_state_ft(tpAniSirGlobal pMac, tSirLinkState
+ state, tSirMacAddr bssId,
+ tSirMacAddr selfMacAddr, int ft,
+ tpPESession psessionEntry)
+{
+ tSirMsgQ msgQ;
+ tSirRetStatus retCode;
+ tpLinkStateParams pLinkStateParams = NULL;
+ /* Allocate memory. */
+ pLinkStateParams = cdf_mem_malloc(sizeof(tLinkStateParams));
+ if (NULL == pLinkStateParams) {
+ lim_log(pMac, LOGP,
+ FL
+ ("Unable to allocate memory while sending Set Link State"));
+ retCode = eSIR_MEM_ALLOC_FAILED;
+ return retCode;
+ }
+ cdf_mem_set((uint8_t *) pLinkStateParams, sizeof(tLinkStateParams), 0);
+ pLinkStateParams->state = state;
+ /* Copy Mac address */
+ sir_copy_mac_addr(pLinkStateParams->bssid, bssId);
+ sir_copy_mac_addr(pLinkStateParams->selfMacAddr, selfMacAddr);
+ pLinkStateParams->ft = 1;
+ pLinkStateParams->session = psessionEntry;
+
+ msgQ.type = WMA_SET_LINK_STATE;
+ msgQ.reserved = 0;
+ msgQ.bodyptr = pLinkStateParams;
+ msgQ.bodyval = 0;
+ if (NULL == psessionEntry) {
+ MTRACE(mac_trace_msg_tx(pMac, NO_SESSION, msgQ.type));
+ } else {
+ MTRACE(mac_trace_msg_tx
+ (pMac, psessionEntry->peSessionId, msgQ.type));
+ }
+
+ retCode = (uint32_t) wma_post_ctrl_msg(pMac, &msgQ);
+ if (retCode != eSIR_SUCCESS) {
+ cdf_mem_free(pLinkStateParams);
+ lim_log(pMac, LOGP,
+ FL("Posting link state %d failed, reason = %x "), state,
+ retCode);
+ }
+ return retCode;
+}
+#endif
+
+/** ---------------------------------------------------------
+ \fn lim_send_beacon_filter_info
+ \brief LIM sends beacon filtering info to WMA
+ \param tpAniSirGlobal pMac
+ \return None
+ -----------------------------------------------------------*/
+tSirRetStatus lim_send_beacon_filter_info(tpAniSirGlobal pMac,
+ tpPESession psessionEntry)
+{
+ tpBeaconFilterMsg pBeaconFilterMsg = NULL;
+ tSirRetStatus retCode = eSIR_SUCCESS;
+ tSirMsgQ msgQ;
+ uint8_t *ptr;
+ uint32_t i;
+ uint32_t msgSize;
+ tpBeaconFilterIe pIe;
+
+ if (psessionEntry == NULL) {
+ lim_log(pMac, LOGE, FL("Fail to find the right session "));
+ retCode = eSIR_FAILURE;
+ return retCode;
+ }
+ msgSize = sizeof(tBeaconFilterMsg) + sizeof(beacon_filter_table);
+ pBeaconFilterMsg = cdf_mem_malloc(msgSize);
+ if (NULL == pBeaconFilterMsg) {
+ lim_log(pMac, LOGP,
+ FL("Fail to allocate memory for beaconFiilterMsg "));
+ retCode = eSIR_MEM_ALLOC_FAILED;
+ return retCode;
+ }
+ cdf_mem_set((uint8_t *) pBeaconFilterMsg, msgSize, 0);
+ /* Fill in capability Info and mask */
+ /* Don't send this message if no active Infra session is found. */
+ pBeaconFilterMsg->capabilityInfo = psessionEntry->limCurrentBssCaps;
+ pBeaconFilterMsg->capabilityMask = CAPABILITY_FILTER_MASK;
+ pBeaconFilterMsg->beaconInterval =
+ (uint16_t) psessionEntry->beaconParams.beaconInterval;
+ /* Fill in number of IEs in beacon_filter_table */
+ pBeaconFilterMsg->ieNum =
+ (uint16_t) (sizeof(beacon_filter_table) / sizeof(tBeaconFilterIe));
+ /* Fill the BSSIDX */
+ pBeaconFilterMsg->bssIdx = psessionEntry->bssIdx;
+
+ /* Fill message with info contained in the beacon_filter_table */
+ ptr = (uint8_t *) pBeaconFilterMsg + sizeof(tBeaconFilterMsg);
+ for (i = 0; i < (pBeaconFilterMsg->ieNum); i++) {
+ pIe = (tpBeaconFilterIe) ptr;
+ pIe->elementId = beacon_filter_table[i].elementId;
+ pIe->checkIePresence = beacon_filter_table[i].checkIePresence;
+ pIe->byte.offset = beacon_filter_table[i].byte.offset;
+ pIe->byte.value = beacon_filter_table[i].byte.value;
+ pIe->byte.bitMask = beacon_filter_table[i].byte.bitMask;
+ pIe->byte.ref = beacon_filter_table[i].byte.ref;
+ ptr += sizeof(tBeaconFilterIe);
+ }
+ msgQ.type = WMA_BEACON_FILTER_IND;
+ msgQ.reserved = 0;
+ msgQ.bodyptr = pBeaconFilterMsg;
+ msgQ.bodyval = 0;
+ lim_log(pMac, LOG3, FL("Sending WMA_BEACON_FILTER_IND..."));
+ MTRACE(mac_trace_msg_tx(pMac, psessionEntry->peSessionId, msgQ.type));
+ retCode = wma_post_ctrl_msg(pMac, &msgQ);
+ if (eSIR_SUCCESS != retCode) {
+ cdf_mem_free(pBeaconFilterMsg);
+ lim_log(pMac, LOGP,
+ FL("Posting WMA_BEACON_FILTER_IND failed, reason=%X"),
+ retCode);
+ return retCode;
+ }
+ return retCode;
+}
+
+#ifdef WLAN_FEATURE_11AC
+tSirRetStatus lim_send_mode_update(tpAniSirGlobal pMac,
+ tUpdateVHTOpMode *pTempParam,
+ tpPESession psessionEntry)
+{
+ tUpdateVHTOpMode *pVhtOpMode = NULL;
+ tSirRetStatus retCode = eSIR_SUCCESS;
+ tSirMsgQ msgQ;
+
+ pVhtOpMode = cdf_mem_malloc(sizeof(tUpdateVHTOpMode));
+ if (NULL == pVhtOpMode) {
+ lim_log(pMac, LOGP,
+ FL("Unable to allocate memory during Update Op Mode"));
+ return eSIR_MEM_ALLOC_FAILED;
+ }
+ cdf_mem_copy((uint8_t *) pVhtOpMode, pTempParam,
+ sizeof(tUpdateVHTOpMode));
+ msgQ.type = WMA_UPDATE_OP_MODE;
+ msgQ.reserved = 0;
+ msgQ.bodyptr = pVhtOpMode;
+ msgQ.bodyval = 0;
+ lim_log(pMac, LOG3, FL(
+ "Sending WMA_UPDATE_OP_MODE, op_mode %d, sta_id %d"),
+ pVhtOpMode->opMode, pVhtOpMode->staId);
+ if (NULL == psessionEntry)
+ MTRACE(mac_trace_msg_tx(pMac, NO_SESSION, msgQ.type));
+ else
+ MTRACE(mac_trace_msg_tx(pMac,
+ psessionEntry->peSessionId,
+ msgQ.type));
+ retCode = wma_post_ctrl_msg(pMac, &msgQ);
+ if (eSIR_SUCCESS != retCode) {
+ cdf_mem_free(pVhtOpMode);
+ lim_log(pMac, LOGP,
+ FL("Posting WMA_UPDATE_OP_MODE failed, reason=%X"),
+ retCode);
+ }
+
+ return retCode;
+}
+
+tSirRetStatus lim_send_rx_nss_update(tpAniSirGlobal pMac,
+ tUpdateRxNss *pTempParam,
+ tpPESession psessionEntry)
+{
+ tUpdateRxNss *pRxNss = NULL;
+ tSirRetStatus retCode = eSIR_SUCCESS;
+ tSirMsgQ msgQ;
+
+ pRxNss = cdf_mem_malloc(sizeof(tUpdateRxNss));
+ if (NULL == pRxNss) {
+ lim_log(pMac, LOGP,
+ FL("Unable to allocate memory during Update Rx Nss"));
+ return eSIR_MEM_ALLOC_FAILED;
+ }
+ cdf_mem_copy((uint8_t *) pRxNss, pTempParam, sizeof(tUpdateRxNss));
+ msgQ.type = WMA_UPDATE_RX_NSS;
+ msgQ.reserved = 0;
+ msgQ.bodyptr = pRxNss;
+ msgQ.bodyval = 0;
+ PELOG3(lim_log(pMac, LOG3, FL("Sending WMA_UPDATE_RX_NSS"));)
+ if (NULL == psessionEntry)
+ MTRACE(mac_trace_msg_tx(pMac, NO_SESSION, msgQ.type));
+ else
+ MTRACE(mac_trace_msg_tx(pMac,
+ psessionEntry->peSessionId,
+ msgQ.type));
+ retCode = wma_post_ctrl_msg(pMac, &msgQ);
+ if (eSIR_SUCCESS != retCode) {
+ cdf_mem_free(pRxNss);
+ lim_log(pMac, LOGP,
+ FL("Posting WMA_UPDATE_RX_NSS failed, reason=%X"),
+ retCode);
+ }
+
+ return retCode;
+}
+
+tSirRetStatus lim_set_membership(tpAniSirGlobal pMac,
+ tUpdateMembership *pTempParam,
+ tpPESession psessionEntry)
+{
+ tUpdateMembership *pMembership = NULL;
+ tSirRetStatus retCode = eSIR_SUCCESS;
+ tSirMsgQ msgQ;
+
+ pMembership = cdf_mem_malloc(sizeof(tUpdateMembership));
+ if (NULL == pMembership) {
+ lim_log(pMac, LOGP,
+ FL("Unable to allocate memory during Update Membership Mode"));
+ return eSIR_MEM_ALLOC_FAILED;
+ }
+ cdf_mem_copy((uint8_t *) pMembership, pTempParam,
+ sizeof(tUpdateMembership));
+
+ msgQ.type = WMA_UPDATE_MEMBERSHIP;
+ msgQ.reserved = 0;
+ msgQ.bodyptr = pMembership;
+ msgQ.bodyval = 0;
+ PELOG3(lim_log(pMac, LOG3, FL("Sending WMA_UPDATE_MEMBERSHIP"));)
+ if (NULL == psessionEntry)
+ MTRACE(mac_trace_msg_tx(pMac, NO_SESSION, msgQ.type));
+ else
+ MTRACE(mac_trace_msg_tx(pMac,
+ psessionEntry->peSessionId,
+ msgQ.type));
+ retCode = wma_post_ctrl_msg(pMac, &msgQ);
+ if (eSIR_SUCCESS != retCode) {
+ cdf_mem_free(pMembership);
+ lim_log(pMac, LOGP,
+ FL("Posting WMA_UPDATE_MEMBERSHIP failed, reason=%X"),
+ retCode);
+ }
+
+ return retCode;
+}
+
+tSirRetStatus lim_set_user_pos(tpAniSirGlobal pMac,
+ tUpdateUserPos *pTempParam,
+ tpPESession psessionEntry)
+{
+ tUpdateUserPos *pUserPos = NULL;
+ tSirRetStatus retCode = eSIR_SUCCESS;
+ tSirMsgQ msgQ;
+
+ pUserPos = cdf_mem_malloc(sizeof(tUpdateUserPos));
+ if (NULL == pUserPos) {
+ lim_log(pMac, LOGP,
+ FL("Unable to allocate memory during Update User Position"));
+ return eSIR_MEM_ALLOC_FAILED;
+ }
+ cdf_mem_copy((uint8_t *) pUserPos, pTempParam, sizeof(tUpdateUserPos));
+
+ msgQ.type = WMA_UPDATE_USERPOS;
+ msgQ.reserved = 0;
+ msgQ.bodyptr = pUserPos;
+ msgQ.bodyval = 0;
+ PELOG3(lim_log(pMac, LOG3, FL("Sending WMA_UPDATE_USERPOS"));)
+ if (NULL == psessionEntry)
+ MTRACE(mac_trace_msg_tx(pMac, NO_SESSION, msgQ.type));
+ else
+ MTRACE(mac_trace_msg_tx(pMac,
+ psessionEntry->peSessionId,
+ msgQ.type));
+ retCode = wma_post_ctrl_msg(pMac, &msgQ);
+ if (eSIR_SUCCESS != retCode) {
+ cdf_mem_free(pUserPos);
+ lim_log(pMac, LOGP,
+ FL("Posting WMA_UPDATE_USERPOS failed, reason=%X"),
+ retCode);
+ }
+
+ return retCode;
+}
+
+#endif
+
+#ifdef WLAN_FEATURE_11W
+/**
+ * lim_send_exclude_unencrypt_ind() - sends WMA_EXCLUDE_UNENCRYPTED_IND to HAL
+ * @pMac: mac global context
+ * @excludeUnenc: true: ignore, false: indicate
+ * @psessionEntry: session context
+ *
+ * LIM sends a message to HAL to indicate whether to ignore or indicate the
+ * unprotected packet error.
+ *
+ * Return: status of operation
+ */
+tSirRetStatus lim_send_exclude_unencrypt_ind(tpAniSirGlobal pMac,
+ bool excludeUnenc,
+ tpPESession psessionEntry)
+{
+ tSirRetStatus retCode = eSIR_SUCCESS;
+ tSirMsgQ msgQ;
+ tSirWlanExcludeUnencryptParam *pExcludeUnencryptParam;
+
+ pExcludeUnencryptParam =
+ cdf_mem_malloc(sizeof(tSirWlanExcludeUnencryptParam));
+ if (NULL == pExcludeUnencryptParam) {
+ lim_log(pMac, LOGP,
+ FL("Unable to allocate memory during lim_send_exclude_unencrypt_ind"));
+ return eSIR_MEM_ALLOC_FAILED;
+ }
+
+ pExcludeUnencryptParam->excludeUnencrypt = excludeUnenc;
+ sir_copy_mac_addr(pExcludeUnencryptParam->bssId, psessionEntry->bssId);
+
+ msgQ.type = WMA_EXCLUDE_UNENCRYPTED_IND;
+ msgQ.reserved = 0;
+ msgQ.bodyptr = pExcludeUnencryptParam;
+ msgQ.bodyval = 0;
+ PELOG3(lim_log(pMac, LOG3, FL("Sending WMA_EXCLUDE_UNENCRYPTED_IND"));)
+ MTRACE(mac_trace_msg_tx(pMac, psessionEntry->peSessionId, msgQ.type));
+ retCode = wma_post_ctrl_msg(pMac, &msgQ);
+ if (eSIR_SUCCESS != retCode) {
+ cdf_mem_free(pExcludeUnencryptParam);
+ lim_log(pMac, LOGP,
+ FL("Posting WMA_EXCLUDE_UNENCRYPTED_IND failed, reason=%X"),
+ retCode);
+ }
+
+ return retCode;
+}
+#endif
diff --git a/core/mac/src/pe/lim/lim_send_messages.h b/core/mac/src/pe/lim/lim_send_messages.h
new file mode 100644
index 0000000..d884de7
--- /dev/null
+++ b/core/mac/src/pe/lim/lim_send_messages.h
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2011-2015 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.
+ */
+
+/*
+ *
+ * lim_send_messages.h: Provides functions to send messages or Indications to HAL.
+ * Author: Sunit Bhatia
+ * Date: 09/21/2006
+ * History:-
+ * Date Modified by Modification Information
+ *
+ * --------------------------------------------------------------------------
+ *
+ */
+#ifndef __LIM_SEND_MESSAGES_H
+#define __LIM_SEND_MESSAGES_H
+
+#include "ani_global.h"
+#include "lim_types.h"
+#include "wma_if.h"
+#include "sir_params.h"
+tSirRetStatus lim_send_cf_params(tpAniSirGlobal pMac, uint8_t bssIdx,
+ uint8_t cfpCount, uint8_t cfpPeriod);
+tSirRetStatus lim_send_beacon_params(tpAniSirGlobal pMac,
+ tpUpdateBeaconParams pUpdatedBcnParams,
+ tpPESession psessionEntry);
+/* tSirRetStatus lim_send_beacon_params(tpAniSirGlobal pMac, tpUpdateBeaconParams pUpdatedBcnParams); */
+#ifdef WLAN_FEATURE_11AC
+tSirRetStatus lim_send_mode_update(tpAniSirGlobal pMac,
+ tUpdateVHTOpMode *tempParam,
+ tpPESession psessionEntry);
+tSirRetStatus lim_send_rx_nss_update(tpAniSirGlobal pMac,
+ tUpdateRxNss *tempParam,
+ tpPESession psessionEntry);
+
+uint32_t lim_get_center_channel(tpAniSirGlobal pMac,
+ uint8_t primarychanNum,
+ ePhyChanBondState secondaryChanOffset,
+ uint8_t chanWidth);
+
+tSirRetStatus lim_set_membership(tpAniSirGlobal pMac,
+ tUpdateMembership *pTempParam,
+ tpPESession psessionEntry);
+
+tSirRetStatus lim_set_user_pos(tpAniSirGlobal pMac,
+ tUpdateUserPos *pTempParam,
+ tpPESession psessionEntry);
+#endif
+#if defined WLAN_FEATURE_VOWIFI
+tSirRetStatus lim_send_switch_chnl_params(tpAniSirGlobal pMac,
+ uint8_t chnlNumber,
+ uint8_t ch_center_freq_seg0,
+ uint8_t ch_center_freq_seg1,
+ phy_ch_width ch_width,
+ tPowerdBm maxTxPower,
+ uint8_t peSessionId,
+ uint8_t is_restart);
+#else
+tSirRetStatus lim_send_switch_chnl_params(tpAniSirGlobal pMac,
+ uint8_t chnlNumber,
+ uint8_t ch_center_freq_seg0,
+ uint8_t ch_center_freq_seg1,
+ phy_ch_width ch_width,
+ uint8_t localPwrConstraint,
+ uint8_t peSessionId,
+ uint8_t is_restart);
+#endif
+tSirRetStatus lim_send_edca_params(tpAniSirGlobal pMac,
+ tSirMacEdcaParamRecord *pUpdatedEdcaParams,
+ uint16_t bssIdx);
+tSirRetStatus lim_set_link_state(tpAniSirGlobal pMac, tSirLinkState state,
+ tSirMacAddr bssId, tSirMacAddr selfMac,
+ tpSetLinkStateCallback callback,
+ void *callbackArg);
+#ifdef WLAN_FEATURE_VOWIFI_11R
+extern tSirRetStatus lim_set_link_state_ft(tpAniSirGlobal pMac, tSirLinkState
+ state, tSirMacAddr bssId,
+ tSirMacAddr selfMacAddr, int ft,
+ tpPESession psessionEntry);
+#endif
+void lim_set_active_edca_params(tpAniSirGlobal pMac,
+ tSirMacEdcaParamRecord *plocalEdcaParams,
+ tpPESession psessionEntry);
+#define CAPABILITY_FILTER_MASK 0x73CF
+#define ERP_FILTER_MASK 0xF8
+#define EDCA_FILTER_MASK 0xF0
+#define QOS_FILTER_MASK 0xF0
+#define HT_BYTE0_FILTER_MASK 0x0
+#define HT_BYTE2_FILTER_MASK 0xEB
+#define HT_BYTE5_FILTER_MASK 0xFD
+#define DS_PARAM_CHANNEL_MASK 0x0
+#define VHTOP_CHWIDTH_MASK 0xFC
+
+tSirRetStatus lim_send_beacon_filter_info(tpAniSirGlobal pMac,
+ tpPESession psessionEntry);
+
+#ifdef WLAN_FEATURE_11W
+tSirRetStatus lim_send_exclude_unencrypt_ind(tpAniSirGlobal pMac,
+ bool excludeUnenc,
+ tpPESession psessionEntry);
+#endif
+#endif
diff --git a/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c b/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c
new file mode 100644
index 0000000..e27113c
--- /dev/null
+++ b/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c
@@ -0,0 +1,2370 @@
+/*
+ * Copyright (c) 2012-2015 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_send_sme_rspMessages.cc contains the functions
+ * for sending SME response/notification messages to applications
+ * above MAC software.
+ * Author: Chandra Modumudi
+ * Date: 02/13/02
+ * History:-
+ * Date Modified by Modification Information
+ * --------------------------------------------------------------------
+ */
+
+#include "cdf_types.h"
+#include "wni_api.h"
+#include "sir_common.h"
+#include "ani_global.h"
+
+#include "wni_cfg.h"
+#include "sys_def.h"
+#include "cfg_api.h"
+
+#include "sch_api.h"
+#include "utils_api.h"
+#include "lim_utils.h"
+#include "lim_security_utils.h"
+#include "lim_ser_des_utils.h"
+#include "lim_send_sme_rsp_messages.h"
+#include "lim_ibss_peer_mgmt.h"
+#include "lim_session_utils.h"
+#include "lim_types.h"
+#include "sir_api.h"
+
+static void lim_handle_join_rsp_status(tpAniSirGlobal mac_ctx,
+ tpPESession session_entry, tSirResultCodes result_code,
+ tpSirSmeJoinRsp sme_join_rsp);
+
+/**
+ * lim_send_sme_rsp() - Send Response to upper layers
+ * @mac_ctx: Pointer to Global MAC structure
+ * @msg_type: Indicates message type
+ * @result_code: Indicates the result of previously issued
+ * eWNI_SME_msg_type_REQ message
+ *
+ * This function is called by lim_process_sme_req_messages() to send
+ * eWNI_SME_START_RSP, eWNI_SME_STOP_BSS_RSP
+ * or eWNI_SME_SWITCH_CHL_RSP messages to applications above MAC
+ * Software.
+ *
+ * Return: None
+ */
+
+void
+lim_send_sme_rsp(tpAniSirGlobal mac_ctx, uint16_t msg_type,
+ tSirResultCodes result_code, uint8_t sme_session_id,
+ uint16_t sme_transaction_id)
+{
+ tSirMsgQ msg;
+ tSirSmeRsp *sme_rsp;
+
+ lim_log(mac_ctx, LOG1, FL("Sending message %s with reasonCode %s"),
+ lim_msg_str(msg_type), lim_result_code_str(result_code));
+
+ sme_rsp = cdf_mem_malloc(sizeof(tSirSmeRsp));
+ if (NULL == sme_rsp) {
+ /* Buffer not available. Log error */
+ CDF_TRACE(CDF_MODULE_ID_PE, LOGP,
+ FL("call to AllocateMemory failed for eWNI_SME_*_RSP"));
+ return;
+ }
+
+ sme_rsp->messageType = msg_type;
+ sme_rsp->length = sizeof(tSirSmeRsp);
+ sme_rsp->statusCode = result_code;
+
+ sme_rsp->sessionId = sme_session_id;
+ sme_rsp->transactionId = sme_transaction_id;
+
+ msg.type = msg_type;
+ msg.bodyptr = sme_rsp;
+ msg.bodyval = 0;
+ MTRACE(mac_trace_msg_tx(mac_ctx, sme_session_id, msg.type));
+
+#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */
+ switch (msg_type) {
+ case eWNI_SME_STOP_BSS_RSP:
+ lim_diag_event_report(mac_ctx, WLAN_PE_DIAG_STOP_BSS_RSP_EVENT,
+ NULL, (uint16_t) result_code, 0);
+ break;
+ }
+#endif /* FEATURE_WLAN_DIAG_SUPPORT */
+ lim_sys_process_mmh_msg_api(mac_ctx, &msg, ePROT);
+}
+
+
+
+/**
+ * lim_send_sme_roc_rsp() - Send Response to SME
+ * @mac_ctx: Pointer to Global MAC structure
+ * @status: Resume link status
+ * @result_code: Result of the ROC request
+ * @sme_session_id: SME sesson Id
+ * @scan_id: Scan Identifier
+ *
+ * This function is called to send ROC rsp
+ * message to SME.
+ *
+ * Return: None
+ */
+void
+lim_send_sme_roc_rsp(tpAniSirGlobal mac_ctx, uint16_t msg_type,
+ tSirResultCodes result_code, uint8_t sme_session_id,
+ uint32_t scan_id)
+{
+ tSirMsgQ msg;
+ struct sir_roc_rsp *sme_rsp;
+
+ lim_log(mac_ctx, LOG1,
+ FL("Sending message %s with reasonCode %s scanId %d"),
+ lim_msg_str(msg_type), lim_result_code_str(result_code),
+ scan_id);
+
+ sme_rsp = cdf_mem_malloc(sizeof(struct sir_roc_rsp));
+ if (NULL == sme_rsp) {
+ CDF_TRACE(CDF_MODULE_ID_PE, LOGP,
+ FL("call to AllocateMemory failed for eWNI_SME_*_RSP"));
+ return;
+ }
+
+ sme_rsp->message_type = msg_type;
+ sme_rsp->length = sizeof(struct sir_roc_rsp);
+ sme_rsp->status = result_code;
+
+ sme_rsp->session_id = sme_session_id;
+ sme_rsp->scan_id = scan_id;
+
+ msg.type = msg_type;
+ msg.bodyptr = sme_rsp;
+ msg.bodyval = 0;
+ MTRACE(mac_trace_msg_tx(mac_ctx, sme_session_id, msg.type));
+ lim_sys_process_mmh_msg_api(mac_ctx, &msg, ePROT);
+}
+
+
+/**
+ * lim_send_sme_join_reassoc_rsp_after_resume() - Send Response to SME
+ * @mac_ctx Pointer to Global MAC structure
+ * @status Resume link status
+ * @ctx context passed while calling resmune link.
+ * (join response to be sent)
+ *
+ * This function is called to send Join/Reassoc rsp
+ * message to SME after the resume link.
+ *
+ * Return: None
+ */
+static void lim_send_sme_join_reassoc_rsp_after_resume(tpAniSirGlobal mac_ctx,
+ CDF_STATUS status, uint32_t *ctx)
+{
+ tSirMsgQ msg;
+ tpSirSmeJoinRsp sme_join_rsp = (tpSirSmeJoinRsp) ctx;
+
+ msg.type = sme_join_rsp->messageType;
+ msg.bodyptr = sme_join_rsp;
+ msg.bodyval = 0;
+ MTRACE(mac_trace_msg_tx(mac_ctx, NO_SESSION, msg.type));
+ lim_sys_process_mmh_msg_api(mac_ctx, &msg, ePROT);
+}
+
+/**
+ * lim_handle_join_rsp_status() - Handle the response.
+ * @mac_ctx: Pointer to Global MAC structure
+ * @session_entry: PE Session Info
+ * @result_code: Indicates the result of previously issued
+ * eWNI_SME_msgType_REQ message
+ * @sme_join_rsp The received response.
+ *
+ * This function will handle both the success and failure status
+ * of the received response.
+ *
+ * Return: None
+ */
+static void lim_handle_join_rsp_status(tpAniSirGlobal mac_ctx,
+ tpPESession session_entry, tSirResultCodes result_code,
+ tpSirSmeJoinRsp sme_join_rsp)
+{
+#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH
+ tSirSmeHTProfile *ht_profile;
+#endif
+ if (result_code == eSIR_SME_SUCCESS) {
+ if (session_entry->beacon != NULL) {
+ sme_join_rsp->beaconLength = session_entry->bcnLen;
+ cdf_mem_copy(sme_join_rsp->frames,
+ session_entry->beacon,
+ sme_join_rsp->beaconLength);
+ cdf_mem_free(session_entry->beacon);
+ session_entry->beacon = NULL;
+#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG
+ lim_log(mac_ctx, LOG1, FL("Beacon=%d"),
+ session_entry->bcnLen);
+#endif
+ }
+ if (session_entry->assocReq != NULL) {
+ sme_join_rsp->assocReqLength =
+ session_entry->assocReqLen;
+ cdf_mem_copy(sme_join_rsp->frames +
+ session_entry->bcnLen, session_entry->assocReq,
+ sme_join_rsp->assocReqLength);
+ cdf_mem_free(session_entry->assocReq);
+ session_entry->assocReq = NULL;
+#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG
+ lim_log(mac_ctx,
+ LOG1, FL("AssocReq=%d"),
+ session_entry->assocReqLen);
+#endif
+ }
+ if (session_entry->assocRsp != NULL) {
+ sme_join_rsp->assocRspLength =
+ session_entry->assocRspLen;
+ cdf_mem_copy(sme_join_rsp->frames +
+ session_entry->bcnLen +
+ session_entry->assocReqLen,
+ session_entry->assocRsp,
+ sme_join_rsp->assocRspLength);
+ cdf_mem_free(session_entry->assocRsp);
+ session_entry->assocRsp = NULL;
+ }
+#ifdef WLAN_FEATURE_VOWIFI_11R
+ if (session_entry->ricData != NULL) {
+ sme_join_rsp->parsedRicRspLen =
+ session_entry->RICDataLen;
+ cdf_mem_copy(sme_join_rsp->frames +
+ session_entry->bcnLen +
+ session_entry->assocReqLen +
+ session_entry->assocRspLen,
+ session_entry->ricData,
+ sme_join_rsp->parsedRicRspLen);
+ cdf_mem_free(session_entry->ricData);
+ session_entry->ricData = NULL;
+ lim_log(mac_ctx, LOG1, FL("RicLength=%d"),
+ sme_join_rsp->parsedRicRspLen);
+ }
+#endif
+#ifdef FEATURE_WLAN_ESE
+ if (session_entry->tspecIes != NULL) {
+ sme_join_rsp->tspecIeLen =
+ session_entry->tspecLen;
+ cdf_mem_copy(sme_join_rsp->frames +
+ session_entry->bcnLen +
+ session_entry->assocReqLen +
+ session_entry->assocRspLen +
+ session_entry->RICDataLen,
+ session_entry->tspecIes,
+ sme_join_rsp->tspecIeLen);
+ cdf_mem_free(session_entry->tspecIes);
+ session_entry->tspecIes = NULL;
+ lim_log(mac_ctx, LOG1, FL("ESE-TspecLen=%d"),
+ session_entry->tspecLen);
+ }
+#endif
+ sme_join_rsp->aid = session_entry->limAID;
+#ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG
+ lim_log(mac_ctx, LOG1, FL("AssocRsp=%d"),
+ session_entry->assocRspLen);
+#endif
+ sme_join_rsp->vht_channel_width =
+ session_entry->ch_width;
+#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH
+ if (session_entry->cc_switch_mode !=
+ CDF_MCC_TO_SCC_SWITCH_DISABLE) {
+ ht_profile = &sme_join_rsp->HTProfile;
+ ht_profile->htSupportedChannelWidthSet =
+ session_entry->htSupportedChannelWidthSet;
+ ht_profile->htRecommendedTxWidthSet =
+ session_entry->htRecommendedTxWidthSet;
+ ht_profile->htSecondaryChannelOffset =
+ session_entry->htSecondaryChannelOffset;
+ ht_profile->dot11mode = session_entry->dot11mode;
+ ht_profile->htCapability = session_entry->htCapability;
+#ifdef WLAN_FEATURE_11AC
+ ht_profile->vhtCapability =
+ session_entry->vhtCapability;
+ ht_profile->vhtTxChannelWidthSet =
+ session_entry->vhtTxChannelWidthSet;
+ ht_profile->apCenterChan = session_entry->ch_center_freq_seg0;
+ ht_profile->apChanWidth = session_entry->ch_width;
+#endif
+ }
+#endif
+ } else {
+ if (session_entry->beacon != NULL) {
+ cdf_mem_free(session_entry->beacon);
+ session_entry->beacon = NULL;
+ }
+ if (session_entry->assocReq != NULL) {
+ cdf_mem_free(session_entry->assocReq);
+ session_entry->assocReq = NULL;
+ }
+ if (session_entry->assocRsp != NULL) {
+ cdf_mem_free(session_entry->assocRsp);
+ session_entry->assocRsp = NULL;
+ }
+#ifdef WLAN_FEATURE_VOWIFI_11R
+ if (session_entry->ricData != NULL) {
+ cdf_mem_free(session_entry->ricData);
+ session_entry->ricData = NULL;
+ }
+#endif
+#ifdef FEATURE_WLAN_ESE
+ if (session_entry->tspecIes != NULL) {
+ cdf_mem_free(session_entry->tspecIes);
+ session_entry->tspecIes = NULL;
+ }
+#endif
+ }
+}
+/**
+ * lim_send_sme_join_reassoc_rsp() - Send Response to Upper Layers
+ * @mac_ctx: Pointer to Global MAC structure
+ * @msg_type: Indicates message type
+ * @result_code: Indicates the result of previously issued
+ * eWNI_SME_msgType_REQ message
+ * @prot_status_code: Protocol Status Code
+ * @session_entry: PE Session Info
+ * @sme_session_id: SME Session ID
+ * @sme_transaction_id: SME Transaction ID
+ *
+ * This function is called by lim_process_sme_req_messages() to send
+ * eWNI_SME_JOIN_RSP or eWNI_SME_REASSOC_RSP messages to applications
+ * above MAC Software.
+ *
+ * Return: None
+ */
+
+void
+lim_send_sme_join_reassoc_rsp(tpAniSirGlobal mac_ctx, uint16_t msg_type,
+ tSirResultCodes result_code, uint16_t prot_status_code,
+ tpPESession session_entry, uint8_t sme_session_id,
+ uint16_t sme_transaction_id)
+{
+ tpSirSmeJoinRsp sme_join_rsp;
+ uint32_t rsp_len;
+ tpDphHashNode sta_ds = NULL;
+#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */
+ if (msg_type == eWNI_SME_REASSOC_RSP)
+ lim_diag_event_report(mac_ctx, WLAN_PE_DIAG_REASSOC_RSP_EVENT,
+ session_entry, (uint16_t) result_code, 0);
+ else
+ lim_diag_event_report(mac_ctx, WLAN_PE_DIAG_JOIN_RSP_EVENT,
+ session_entry, (uint16_t) result_code, 0);
+#endif /* FEATURE_WLAN_DIAG_SUPPORT */
+
+ lim_log(mac_ctx, LOG1, FL("Sending message %s with reasonCode %s"),
+ lim_msg_str(msg_type), lim_result_code_str(result_code));
+
+ if (session_entry == NULL) {
+ rsp_len = sizeof(tSirSmeJoinRsp);
+ sme_join_rsp = cdf_mem_malloc(rsp_len);
+ if (NULL == sme_join_rsp) {
+ lim_log(mac_ctx, LOGP,
+ FL("Mem Alloc fail - JOIN/REASSOC_RSP"));
+ return;
+ }
+
+ cdf_mem_set((uint8_t *) sme_join_rsp, rsp_len, 0);
+ sme_join_rsp->beaconLength = 0;
+ sme_join_rsp->assocReqLength = 0;
+ sme_join_rsp->assocRspLength = 0;
+ } else {
+ rsp_len = session_entry->assocReqLen +
+ session_entry->assocRspLen + session_entry->bcnLen +
+#ifdef WLAN_FEATURE_VOWIFI_11R
+ session_entry->RICDataLen +
+#endif
+#ifdef FEATURE_WLAN_ESE
+ session_entry->tspecLen +
+#endif
+ sizeof(tSirSmeJoinRsp) - sizeof(uint8_t);
+ sme_join_rsp = cdf_mem_malloc(rsp_len);
+ if (NULL == sme_join_rsp) {
+ lim_log(mac_ctx, LOGP,
+ FL("MemAlloc fail - JOIN/REASSOC_RSP"));
+ return;
+ }
+ cdf_mem_set((uint8_t *) sme_join_rsp, rsp_len, 0);
+ if (result_code == eSIR_SME_SUCCESS) {
+ sta_ds = dph_get_hash_entry(mac_ctx,
+ DPH_STA_HASH_INDEX_PEER,
+ &session_entry->dph.dphHashTable);
+ if (sta_ds == NULL) {
+ lim_log(mac_ctx, LOGE,
+ FL("Get Self Sta Entry fail"));
+ } else {
+ /* Pass the peer's staId */
+ sme_join_rsp->staId = sta_ds->staIndex;
+ sme_join_rsp->ucastSig =
+ sta_ds->ucUcastSig;
+ sme_join_rsp->bcastSig =
+ sta_ds->ucBcastSig;
+ sme_join_rsp->timingMeasCap =
+ sta_ds->timingMeasCap;
+#ifdef FEATURE_WLAN_TDLS
+ sme_join_rsp->tdls_prohibited =
+ session_entry->tdls_prohibited;
+ sme_join_rsp->tdls_chan_swit_prohibited =
+ session_entry->tdls_chan_swit_prohibited;
+#endif
+ }
+ }
+ sme_join_rsp->beaconLength = 0;
+ sme_join_rsp->assocReqLength = 0;
+ sme_join_rsp->assocRspLength = 0;
+#ifdef WLAN_FEATURE_VOWIFI_11R
+ sme_join_rsp->parsedRicRspLen = 0;
+#endif
+#ifdef FEATURE_WLAN_ESE
+ sme_join_rsp->tspecIeLen = 0;
+#endif
+
+ lim_handle_join_rsp_status(mac_ctx, session_entry, result_code,
+ sme_join_rsp);
+ }
+
+ sme_join_rsp->messageType = msg_type;
+ sme_join_rsp->length = (uint16_t) rsp_len;
+ sme_join_rsp->statusCode = result_code;
+ sme_join_rsp->protStatusCode = prot_status_code;
+
+ sme_join_rsp->sessionId = sme_session_id;
+ sme_join_rsp->transactionId = sme_transaction_id;
+
+ lim_send_sme_join_reassoc_rsp_after_resume(mac_ctx, CDF_STATUS_SUCCESS,
+ (uint32_t *)sme_join_rsp);
+}
+
+/**
+ * lim_send_sme_start_bss_rsp()
+ *
+ ***FUNCTION:
+ * This function is called to send eWNI_SME_START_BSS_RSP
+ * message to applications above MAC Software.
+ *
+ ***PARAMS:
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ * NA
+ *
+ ***NOTE:
+ * NA
+ *
+ * @param pMac Pointer to Global MAC structure
+ * @param msgType Indicates message type
+ * @param resultCode Indicates the result of previously issued
+ * eWNI_SME_msgType_REQ message
+ *
+ * @return None
+ */
+
+void
+lim_send_sme_start_bss_rsp(tpAniSirGlobal pMac,
+ uint16_t msgType, tSirResultCodes resultCode,
+ tpPESession psessionEntry, uint8_t smesessionId,
+ uint16_t smetransactionId)
+{
+
+ uint16_t size = 0;
+ tSirMsgQ mmhMsg;
+ tSirSmeStartBssRsp *pSirSmeRsp;
+ uint16_t ieLen;
+ uint16_t ieOffset, curLen;
+
+ PELOG1(lim_log(pMac, LOG1, FL("Sending message %s with reasonCode %s"),
+ lim_msg_str(msgType), lim_result_code_str(resultCode));
+ )
+
+ size = sizeof(tSirSmeStartBssRsp);
+
+ if (psessionEntry == NULL) {
+ pSirSmeRsp = cdf_mem_malloc(size);
+ if (NULL == pSirSmeRsp) {
+ /* / Buffer not available. Log error */
+ lim_log(pMac, LOGP,
+ FL
+ ("call to AllocateMemory failed for eWNI_SME_START_BSS_RSP"));
+ return;
+ }
+ cdf_mem_set((uint8_t *) pSirSmeRsp, size, 0);
+
+ } else {
+ /* subtract size of beaconLength + Mac Hdr + Fixed Fields before SSID */
+ ieOffset = sizeof(tAniBeaconStruct) + SIR_MAC_B_PR_SSID_OFFSET;
+ ieLen = psessionEntry->schBeaconOffsetBegin
+ + psessionEntry->schBeaconOffsetEnd - ieOffset;
+ /* calculate the memory size to allocate */
+ size += ieLen;
+
+ pSirSmeRsp = cdf_mem_malloc(size);
+ if (NULL == pSirSmeRsp) {
+ /* / Buffer not available. Log error */
+ lim_log(pMac, LOGP,
+ FL
+ ("call to AllocateMemory failed for eWNI_SME_START_BSS_RSP"));
+
+ return;
+ }
+ cdf_mem_set((uint8_t *) pSirSmeRsp, size, 0);
+ size = sizeof(tSirSmeStartBssRsp);
+ if (resultCode == eSIR_SME_SUCCESS) {
+
+ sir_copy_mac_addr(pSirSmeRsp->bssDescription.bssId,
+ psessionEntry->bssId);
+
+ /* Read beacon interval from session */
+ pSirSmeRsp->bssDescription.beaconInterval =
+ (uint16_t) psessionEntry->beaconParams.
+ beaconInterval;
+ pSirSmeRsp->bssType = psessionEntry->bssType;
+
+ if (cfg_get_capability_info
+ (pMac, &pSirSmeRsp->bssDescription.capabilityInfo,
+ psessionEntry)
+ != eSIR_SUCCESS)
+ lim_log(pMac, LOGP,
+ FL
+ ("could not retrieve Capabilities value"));
+
+ lim_get_phy_mode(pMac,
+ (uint32_t *) &pSirSmeRsp->bssDescription.
+ nwType, psessionEntry);
+
+ pSirSmeRsp->bssDescription.channelId =
+ psessionEntry->currentOperChannel;
+
+ curLen = psessionEntry->schBeaconOffsetBegin - ieOffset;
+ cdf_mem_copy((uint8_t *) &pSirSmeRsp->bssDescription.
+ ieFields,
+ psessionEntry->pSchBeaconFrameBegin +
+ ieOffset, (uint32_t) curLen);
+
+ cdf_mem_copy(((uint8_t *) &pSirSmeRsp->bssDescription.
+ ieFields) + curLen,
+ psessionEntry->pSchBeaconFrameEnd,
+ (uint32_t) psessionEntry->
+ schBeaconOffsetEnd);
+
+ /* subtracting size of length indicator itself and size of pointer to ieFields */
+ pSirSmeRsp->bssDescription.length =
+ sizeof(tSirBssDescription) - sizeof(uint16_t) -
+ sizeof(uint32_t) + ieLen;
+ /* This is the size of the message, subtracting the size of the pointer to ieFields */
+ size += ieLen - sizeof(uint32_t);
+#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH
+ if (psessionEntry->cc_switch_mode
+ != CDF_MCC_TO_SCC_SWITCH_DISABLE) {
+ pSirSmeRsp->HTProfile.
+ htSupportedChannelWidthSet =
+ psessionEntry->htSupportedChannelWidthSet;
+ pSirSmeRsp->HTProfile.htRecommendedTxWidthSet =
+ psessionEntry->htRecommendedTxWidthSet;
+ pSirSmeRsp->HTProfile.htSecondaryChannelOffset =
+ psessionEntry->htSecondaryChannelOffset;
+ pSirSmeRsp->HTProfile.dot11mode =
+ psessionEntry->dot11mode;
+ pSirSmeRsp->HTProfile.htCapability =
+ psessionEntry->htCapability;
+#ifdef WLAN_FEATURE_11AC
+ pSirSmeRsp->HTProfile.vhtCapability =
+ psessionEntry->vhtCapability;
+ pSirSmeRsp->HTProfile.vhtTxChannelWidthSet =
+ psessionEntry->vhtTxChannelWidthSet;
+ pSirSmeRsp->HTProfile.apCenterChan =
+ psessionEntry->ch_center_freq_seg0;
+ pSirSmeRsp->HTProfile.apChanWidth =
+ psessionEntry->ch_width;
+#endif
+ }
+#endif
+ }
+
+ }
+
+ pSirSmeRsp->messageType = msgType;
+ pSirSmeRsp->length = size;
+
+ /* Update SME session Id and transaction Id */
+ pSirSmeRsp->sessionId = smesessionId;
+ pSirSmeRsp->transactionId = smetransactionId;
+ pSirSmeRsp->statusCode = resultCode;
+ if (psessionEntry != NULL)
+ pSirSmeRsp->staId = psessionEntry->staId; /* else it will be always zero smeRsp StaID = 0 */
+
+ mmhMsg.type = msgType;
+ mmhMsg.bodyptr = pSirSmeRsp;
+ mmhMsg.bodyval = 0;
+ if (psessionEntry == NULL) {
+ MTRACE(mac_trace_msg_tx(pMac, NO_SESSION, mmhMsg.type));
+ } else {
+ MTRACE(mac_trace_msg_tx
+ (pMac, psessionEntry->peSessionId, mmhMsg.type));
+ }
+#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */
+ lim_diag_event_report(pMac, WLAN_PE_DIAG_START_BSS_RSP_EVENT,
+ psessionEntry, (uint16_t) resultCode, 0);
+#endif /* FEATURE_WLAN_DIAG_SUPPORT */
+
+ lim_sys_process_mmh_msg_api(pMac, &mmhMsg, ePROT);
+} /*** end lim_send_sme_start_bss_rsp() ***/
+
+#define LIM_MAX_NUM_OF_SCAN_RESULTS_REPORTED 20
+#define LIM_SIZE_OF_EACH_BSS 400 /* this is a rough estimate */
+
+/**
+ * lim_send_sme_scan_rsp() - Send scan response to SME
+ * @pMac: Pointer to Global MAC structure
+ * @length: Indicates length of message
+ * @resultCode: Indicates the result of previously issued
+ * eWNI_SME_SCAN_REQ message
+ * @scan_id: scan identifier
+ *
+ * This function is called by lim_process_sme_req_messages() to send
+ * eWNI_SME_SCAN_RSP message to applications above MAC
+ *
+ * return: None
+ */
+
+void
+lim_send_sme_scan_rsp(tpAniSirGlobal pMac, tSirResultCodes resultCode,
+ uint8_t smesessionId, uint16_t smetranscationId,
+ uint32_t scan_id)
+{
+ lim_log(pMac, LOG1,
+ FL("Sending message SME_SCAN_RSP reasonCode %s scanId %d"),
+ lim_result_code_str(resultCode), scan_id);
+ lim_post_sme_scan_rsp_message(pMac, resultCode, smesessionId,
+ smetranscationId, scan_id);
+}
+
+/**
+ * lim_post_sme_scan_rsp_message()
+ *
+ ***FUNCTION:
+ * This function is called by lim_send_sme_scan_rsp() to send
+ * eWNI_SME_SCAN_RSP message with failed result code
+ *
+ ***NOTE:
+ * NA
+ *
+ * @param pMac Pointer to Global MAC structure
+ * @param length Indicates length of message
+ * @param resultCode failed result code
+ *
+ * @return None
+ */
+
+void
+lim_post_sme_scan_rsp_message(tpAniSirGlobal pMac,
+ tSirResultCodes resultCode, uint8_t smesessionId,
+ uint16_t smetransactionId,
+ uint32_t scan_id)
+{
+ tpSirSmeScanRsp pSirSmeScanRsp;
+ tSirMsgQ mmhMsg;
+
+ lim_log(pMac, LOG1, FL("send SME_SCAN_RSP (reasonCode %s)."),
+ lim_result_code_str(resultCode));
+
+ pSirSmeScanRsp = cdf_mem_malloc(sizeof(tSirSmeScanRsp));
+ if (NULL == pSirSmeScanRsp) {
+ lim_log(pMac, LOGP,
+ FL("AllocateMemory failed for eWNI_SME_SCAN_RSP"));
+ return;
+ }
+ cdf_mem_set((void *)pSirSmeScanRsp, sizeof(tSirSmeScanRsp), 0);
+
+ pSirSmeScanRsp->messageType = eWNI_SME_SCAN_RSP;
+ pSirSmeScanRsp->statusCode = resultCode;
+
+ /*Update SME session Id and transaction Id */
+ pSirSmeScanRsp->sessionId = smesessionId;
+ pSirSmeScanRsp->transcationId = smetransactionId;
+ pSirSmeScanRsp->scan_id = scan_id;
+
+ mmhMsg.type = eWNI_SME_SCAN_RSP;
+ mmhMsg.bodyptr = pSirSmeScanRsp;
+ mmhMsg.bodyval = 0;
+
+ MTRACE(mac_trace_msg_tx(pMac, NO_SESSION, mmhMsg.type));
+#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */
+ lim_diag_event_report(pMac, WLAN_PE_DIAG_SCAN_RSP_EVENT, NULL,
+ (uint16_t) resultCode, 0);
+#endif /* FEATURE_WLAN_DIAG_SUPPORT */
+
+ lim_sys_process_mmh_msg_api(pMac, &mmhMsg, ePROT);
+ return;
+
+} /*** lim_post_sme_scan_rsp_message ***/
+
+#ifdef FEATURE_OEM_DATA_SUPPORT
+
+/**
+ * lim_send_sme_oem_data_rsp()
+ *
+ ***FUNCTION:
+ * This function is called by lim_process_sme_req_messages() to send
+ * eWNI_SME_OEM_DATA_RSP message to applications above MAC
+ * Software.
+ *
+ ***PARAMS:
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ * NA
+ *
+ ***NOTE:
+ * NA
+ *
+ * @param pMac Pointer to Global MAC structure
+ * @param pMsgBuf Indicates the mlm message
+ * @param resultCode Indicates the result of previously issued
+ * eWNI_SME_OEM_DATA_RSP message
+ *
+ * @return None
+ */
+
+void lim_send_sme_oem_data_rsp(tpAniSirGlobal pMac, uint32_t *pMsgBuf,
+ tSirResultCodes resultCode)
+{
+ tSirMsgQ mmhMsg;
+ tSirOemDataRsp *pSirSmeOemDataRsp = NULL;
+ tLimMlmOemDataRsp *pMlmOemDataRsp = NULL;
+ uint16_t msgLength;
+
+ /* get the pointer to the mlm message */
+ pMlmOemDataRsp = (tLimMlmOemDataRsp *) (pMsgBuf);
+
+ msgLength = sizeof(tSirOemDataRsp);
+
+ /* now allocate memory for the char buffer */
+ pSirSmeOemDataRsp = cdf_mem_malloc(msgLength);
+ if (NULL == pSirSmeOemDataRsp) {
+ lim_log(pMac, LOGP,
+ FL
+ ("call to AllocateMemory failed for pSirSmeOemDataRsp"));
+ return;
+ }
+#if defined (ANI_LITTLE_BYTE_ENDIAN)
+ sir_store_u16_n((uint8_t *) &pSirSmeOemDataRsp->length, msgLength);
+ sir_store_u16_n((uint8_t *) &pSirSmeOemDataRsp->messageType,
+ eWNI_SME_OEM_DATA_RSP);
+#else
+ pSirSmeOemDataRsp->length = msgLength;
+ pSirSmeOemDataRsp->messageType = eWNI_SME_OEM_DATA_RSP;
+#endif
+
+ cdf_mem_copy(pSirSmeOemDataRsp->oemDataRsp, pMlmOemDataRsp->oemDataRsp,
+ OEM_DATA_RSP_SIZE);
+
+ /* Now free the memory from MLM Rsp Message */
+ cdf_mem_free(pMlmOemDataRsp);
+
+ mmhMsg.type = eWNI_SME_OEM_DATA_RSP;
+ mmhMsg.bodyptr = pSirSmeOemDataRsp;
+ mmhMsg.bodyval = 0;
+
+ lim_sys_process_mmh_msg_api(pMac, &mmhMsg, ePROT);
+
+ return;
+} /*** lim_send_sme_oem_data_rsp ***/
+
+#endif
+
+void lim_send_sme_disassoc_deauth_ntf(tpAniSirGlobal pMac,
+ CDF_STATUS status, uint32_t *pCtx)
+{
+ tSirMsgQ mmhMsg;
+ tSirMsgQ *pMsg = (tSirMsgQ *) pCtx;
+
+ mmhMsg.type = pMsg->type;
+ mmhMsg.bodyptr = pMsg;
+ mmhMsg.bodyval = 0;
+
+ MTRACE(mac_trace_msg_tx(pMac, NO_SESSION, mmhMsg.type));
+
+ lim_sys_process_mmh_msg_api(pMac, &mmhMsg, ePROT);
+}
+
+/**
+ * lim_send_sme_disassoc_ntf()
+ *
+ ***FUNCTION:
+ * This function is called by limProcessSmeMessages() to send
+ * eWNI_SME_DISASSOC_RSP/IND message to host
+ *
+ ***PARAMS:
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ * NA
+ *
+ ***NOTE:
+ * This function is used for sending eWNI_SME_DISASSOC_CNF,
+ * or eWNI_SME_DISASSOC_IND to host depending on
+ * disassociation trigger.
+ *
+ * @param peerMacAddr Indicates the peer MAC addr to which
+ * disassociate was initiated
+ * @param reasonCode Indicates the reason for Disassociation
+ * @param disassocTrigger Indicates the trigger for Disassociation
+ * @param aid Indicates the STAID. This parameter is
+ * present only on AP.
+ *
+ * @return None
+ */
+void
+lim_send_sme_disassoc_ntf(tpAniSirGlobal pMac,
+ tSirMacAddr peerMacAddr,
+ tSirResultCodes reasonCode,
+ uint16_t disassocTrigger,
+ uint16_t aid,
+ uint8_t smesessionId,
+ uint16_t smetransactionId, tpPESession psessionEntry)
+{
+
+ uint8_t *pBuf;
+ tSirSmeDisassocRsp *pSirSmeDisassocRsp;
+ tSirSmeDisassocInd *pSirSmeDisassocInd;
+ uint32_t *pMsg;
+ bool failure = false;
+
+ lim_log(pMac, LOG1, FL("Disassoc Ntf with trigger : %d reasonCode: %d"),
+ disassocTrigger, reasonCode);
+
+ switch (disassocTrigger) {
+ case eLIM_PEER_ENTITY_DISASSOC:
+ if (reasonCode != eSIR_SME_STA_NOT_ASSOCIATED) {
+ failure = true;
+ goto error;
+ }
+
+ case eLIM_HOST_DISASSOC:
+ /**
+ * Disassociation response due to
+ * host triggered disassociation
+ */
+
+ pSirSmeDisassocRsp = cdf_mem_malloc(sizeof(tSirSmeDisassocRsp));
+ if (NULL == pSirSmeDisassocRsp) {
+ /* Log error */
+ lim_log(pMac, LOGP, FL("Memory allocation failed"));
+ failure = true;
+ goto error;
+ }
+ lim_log(pMac, LOG1, FL("send eWNI_SME_DISASSOC_RSP with "
+ "retCode: %d for " MAC_ADDRESS_STR),
+ reasonCode, MAC_ADDR_ARRAY(peerMacAddr));
+ pSirSmeDisassocRsp->messageType = eWNI_SME_DISASSOC_RSP;
+ pSirSmeDisassocRsp->length = sizeof(tSirSmeDisassocRsp);
+ /* sessionId */
+ pBuf = (uint8_t *) &pSirSmeDisassocRsp->sessionId;
+ *pBuf = smesessionId;
+ pBuf++;
+
+ /* transactionId */
+ lim_copy_u16(pBuf, smetransactionId);
+ pBuf += sizeof(uint16_t);
+
+ /* statusCode */
+ lim_copy_u32(pBuf, reasonCode);
+ pBuf += sizeof(tSirResultCodes);
+
+ /* peerMacAddr */
+ cdf_mem_copy(pBuf, peerMacAddr, sizeof(tSirMacAddr));
+ pBuf += sizeof(tSirMacAddr);
+
+ /* Clear Station Stats */
+ /* for sta, it is always 1, IBSS is handled at halInitSta */
+
+#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */
+
+ lim_diag_event_report(pMac, WLAN_PE_DIAG_DISASSOC_RSP_EVENT,
+ psessionEntry, (uint16_t) reasonCode, 0);
+#endif
+ pMsg = (uint32_t *) pSirSmeDisassocRsp;
+ break;
+
+ default:
+ /**
+ * Disassociation indication due to Disassociation
+ * frame reception from peer entity or due to
+ * loss of link with peer entity.
+ */
+ pSirSmeDisassocInd = cdf_mem_malloc(sizeof(tSirSmeDisassocInd));
+ if (NULL == pSirSmeDisassocInd) {
+ /* Log error */
+ lim_log(pMac, LOGP, FL("Memory allocation failed"));
+ failure = true;
+ goto error;
+ }
+ lim_log(pMac, LOG1, FL("send eWNI_SME_DISASSOC_IND with "
+ "retCode: %d for " MAC_ADDRESS_STR),
+ reasonCode, MAC_ADDR_ARRAY(peerMacAddr));
+ pSirSmeDisassocInd->messageType = eWNI_SME_DISASSOC_IND;
+ pSirSmeDisassocInd->length = sizeof(tSirSmeDisassocInd);
+
+ /* Update SME session Id and Transaction Id */
+ pSirSmeDisassocInd->sessionId = smesessionId;
+ pSirSmeDisassocInd->transactionId = smetransactionId;
+ pSirSmeDisassocInd->reasonCode = reasonCode;
+ pBuf = (uint8_t *) &pSirSmeDisassocInd->statusCode;
+
+ lim_copy_u32(pBuf, reasonCode);
+ pBuf += sizeof(tSirResultCodes);
+
+ cdf_mem_copy(pBuf, psessionEntry->bssId, sizeof(tSirMacAddr));
+ pBuf += sizeof(tSirMacAddr);
+
+ cdf_mem_copy(pBuf, peerMacAddr, sizeof(tSirMacAddr));
+
+#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */
+ lim_diag_event_report(pMac, WLAN_PE_DIAG_DISASSOC_IND_EVENT,
+ psessionEntry, (uint16_t) reasonCode, 0);
+#endif
+ pMsg = (uint32_t *) pSirSmeDisassocInd;
+
+ break;
+ }
+
+error:
+ /* Delete the PE session Created */
+ if ((psessionEntry != NULL) &&
+ (LIM_IS_STA_ROLE(psessionEntry) ||
+ LIM_IS_BT_AMP_STA_ROLE(psessionEntry))) {
+ pe_delete_session(pMac, psessionEntry);
+ }
+
+ if (false == failure)
+ lim_send_sme_disassoc_deauth_ntf(pMac, CDF_STATUS_SUCCESS,
+ (uint32_t *) pMsg);
+} /*** end lim_send_sme_disassoc_ntf() ***/
+
+/** -----------------------------------------------------------------
+ \brief lim_send_sme_disassoc_ind() - sends SME_DISASSOC_IND
+
+ After receiving disassociation frame from peer entity, this
+ function sends a eWNI_SME_DISASSOC_IND to SME with a specific
+ reason code.
+
+ \param pMac - global mac structure
+ \param pStaDs - station dph hash node
+ \return none
+ \sa
+ ----------------------------------------------------------------- */
+void
+lim_send_sme_disassoc_ind(tpAniSirGlobal pMac, tpDphHashNode pStaDs,
+ tpPESession psessionEntry)
+{
+ tSirMsgQ mmhMsg;
+ tSirSmeDisassocInd *pSirSmeDisassocInd;
+
+ pSirSmeDisassocInd = cdf_mem_malloc(sizeof(tSirSmeDisassocInd));
+ if (NULL == pSirSmeDisassocInd) {
+ lim_log(pMac, LOGP,
+ FL("AllocateMemory failed for eWNI_SME_DISASSOC_IND"));
+ return;
+ }
+
+ pSirSmeDisassocInd->messageType = eWNI_SME_DISASSOC_IND;
+ pSirSmeDisassocInd->length = sizeof(tSirSmeDisassocInd);
+
+ pSirSmeDisassocInd->sessionId = psessionEntry->smeSessionId;
+ pSirSmeDisassocInd->transactionId = psessionEntry->transactionId;
+ pSirSmeDisassocInd->statusCode = pStaDs->mlmStaContext.disassocReason;
+ pSirSmeDisassocInd->reasonCode = pStaDs->mlmStaContext.disassocReason;
+
+ cdf_mem_copy(pSirSmeDisassocInd->bssId, psessionEntry->bssId,
+ sizeof(tSirMacAddr));
+
+ cdf_mem_copy(pSirSmeDisassocInd->peerMacAddr, pStaDs->staAddr,
+ sizeof(tSirMacAddr));
+
+ pSirSmeDisassocInd->staId = pStaDs->staIndex;
+
+ mmhMsg.type = eWNI_SME_DISASSOC_IND;
+ mmhMsg.bodyptr = pSirSmeDisassocInd;
+ mmhMsg.bodyval = 0;
+
+ MTRACE(mac_trace_msg_tx(pMac, psessionEntry->peSessionId, mmhMsg.type));
+#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */
+ lim_diag_event_report(pMac, WLAN_PE_DIAG_DISASSOC_IND_EVENT, psessionEntry,
+ 0, (uint16_t) pStaDs->mlmStaContext.disassocReason);
+#endif /* FEATURE_WLAN_DIAG_SUPPORT */
+
+ lim_sys_process_mmh_msg_api(pMac, &mmhMsg, ePROT);
+
+} /*** end lim_send_sme_disassoc_ind() ***/
+
+/** -----------------------------------------------------------------
+ \brief lim_send_sme_deauth_ind() - sends SME_DEAUTH_IND
+
+ After receiving deauthentication frame from peer entity, this
+ function sends a eWNI_SME_DEAUTH_IND to SME with a specific
+ reason code.
+
+ \param pMac - global mac structure
+ \param pStaDs - station dph hash node
+ \return none
+ \sa
+ ----------------------------------------------------------------- */
+void
+lim_send_sme_deauth_ind(tpAniSirGlobal pMac, tpDphHashNode pStaDs,
+ tpPESession psessionEntry)
+{
+ tSirMsgQ mmhMsg;
+ tSirSmeDeauthInd *pSirSmeDeauthInd;
+
+ pSirSmeDeauthInd = cdf_mem_malloc(sizeof(tSirSmeDeauthInd));
+ if (NULL == pSirSmeDeauthInd) {
+ lim_log(pMac, LOGP,
+ FL("AllocateMemory failed for eWNI_SME_DEAUTH_IND "));
+ return;
+ }
+
+ pSirSmeDeauthInd->messageType = eWNI_SME_DEAUTH_IND;
+ pSirSmeDeauthInd->length = sizeof(tSirSmeDeauthInd);
+
+ pSirSmeDeauthInd->sessionId = psessionEntry->smeSessionId;
+ pSirSmeDeauthInd->transactionId = psessionEntry->transactionId;
+ if (eSIR_INFRA_AP_MODE == psessionEntry->bssType) {
+ pSirSmeDeauthInd->statusCode =
+ (tSirResultCodes) pStaDs->mlmStaContext.cleanupTrigger;
+ } else {
+ /* Need to indicatet he reascon code over the air */
+ pSirSmeDeauthInd->statusCode =
+ (tSirResultCodes) pStaDs->mlmStaContext.disassocReason;
+ }
+ /* BSSID */
+ cdf_mem_copy(pSirSmeDeauthInd->bssId, psessionEntry->bssId,
+ sizeof(tSirMacAddr));
+ /* peerMacAddr */
+ cdf_mem_copy(pSirSmeDeauthInd->peerMacAddr, pStaDs->staAddr,
+ sizeof(tSirMacAddr));
+ pSirSmeDeauthInd->reasonCode = pStaDs->mlmStaContext.disassocReason;
+
+ pSirSmeDeauthInd->staId = pStaDs->staIndex;
+
+ mmhMsg.type = eWNI_SME_DEAUTH_IND;
+ mmhMsg.bodyptr = pSirSmeDeauthInd;
+ mmhMsg.bodyval = 0;
+
+ MTRACE(mac_trace_msg_tx(pMac, psessionEntry->peSessionId, mmhMsg.type));
+#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */
+ lim_diag_event_report(pMac, WLAN_PE_DIAG_DEAUTH_IND_EVENT, psessionEntry,
+ 0, pStaDs->mlmStaContext.cleanupTrigger);
+#endif /* FEATURE_WLAN_DIAG_SUPPORT */
+
+ lim_sys_process_mmh_msg_api(pMac, &mmhMsg, ePROT);
+ return;
+} /*** end lim_send_sme_deauth_ind() ***/
+
+#ifdef FEATURE_WLAN_TDLS
+/**
+ * lim_send_sme_tdls_del_sta_ind()
+ *
+ ***FUNCTION:
+ * This function is called to send the TDLS STA context deletion to SME.
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ *
+ ***NOTE:
+ * NA
+ *
+ * @param pMac - Pointer to global MAC structure
+ * @param pStaDs - Pointer to internal STA Datastructure
+ * @param psessionEntry - Pointer to the session entry
+ * @param reasonCode - Reason for TDLS sta deletion
+ * @return None
+ */
+void
+lim_send_sme_tdls_del_sta_ind(tpAniSirGlobal pMac, tpDphHashNode pStaDs,
+ tpPESession psessionEntry, uint16_t reasonCode)
+{
+ tSirMsgQ mmhMsg;
+ tSirTdlsDelStaInd *pSirTdlsDelStaInd;
+
+ pSirTdlsDelStaInd = cdf_mem_malloc(sizeof(tSirTdlsDelStaInd));
+ if (NULL == pSirTdlsDelStaInd) {
+ lim_log(pMac, LOGP,
+ FL
+ ("AllocateMemory failed for eWNI_SME_TDLS_DEL_STA_IND "));
+ return;
+ }
+ /* messageType */
+ pSirTdlsDelStaInd->messageType = eWNI_SME_TDLS_DEL_STA_IND;
+ pSirTdlsDelStaInd->length = sizeof(tSirTdlsDelStaInd);
+
+ /* sessionId */
+ pSirTdlsDelStaInd->sessionId = psessionEntry->smeSessionId;
+
+ /* peerMacAddr */
+ cdf_mem_copy(pSirTdlsDelStaInd->peerMac, pStaDs->staAddr,
+ sizeof(tSirMacAddr));
+
+ /* staId */
+ lim_copy_u16((uint8_t *) (&pSirTdlsDelStaInd->staId),
+ (uint16_t) pStaDs->staIndex);
+
+ /* reasonCode */
+ lim_copy_u16((uint8_t *) (&pSirTdlsDelStaInd->reasonCode), reasonCode);
+
+ mmhMsg.type = eWNI_SME_TDLS_DEL_STA_IND;
+ mmhMsg.bodyptr = pSirTdlsDelStaInd;
+ mmhMsg.bodyval = 0;
+
+ lim_sys_process_mmh_msg_api(pMac, &mmhMsg, ePROT);
+ return;
+} /*** end lim_send_sme_tdls_del_sta_ind() ***/
+
+/**
+ * lim_send_sme_tdls_delete_all_peer_ind()
+ *
+ ***FUNCTION:
+ * This function is called to send the eWNI_SME_TDLS_DEL_ALL_PEER_IND
+ * message to SME.
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ *
+ ***NOTE:
+ * NA
+ *
+ * @param pMac - Pointer to global MAC structure
+ * @param psessionEntry - Pointer to the session entry
+ * @return None
+ */
+void
+lim_send_sme_tdls_delete_all_peer_ind(tpAniSirGlobal pMac, tpPESession psessionEntry)
+{
+ tSirMsgQ mmhMsg;
+ tSirTdlsDelAllPeerInd *pSirTdlsDelAllPeerInd;
+
+ pSirTdlsDelAllPeerInd = cdf_mem_malloc(sizeof(tSirTdlsDelAllPeerInd));
+ if (NULL == pSirTdlsDelAllPeerInd) {
+ lim_log(pMac, LOGP,
+ FL
+ ("AllocateMemory failed for eWNI_SME_TDLS_DEL_ALL_PEER_IND"));
+ return;
+ }
+ /* messageType */
+ pSirTdlsDelAllPeerInd->messageType = eWNI_SME_TDLS_DEL_ALL_PEER_IND;
+ pSirTdlsDelAllPeerInd->length = sizeof(tSirTdlsDelAllPeerInd);
+
+ /* sessionId */
+ pSirTdlsDelAllPeerInd->sessionId = psessionEntry->smeSessionId;
+
+ mmhMsg.type = eWNI_SME_TDLS_DEL_ALL_PEER_IND;
+ mmhMsg.bodyptr = pSirTdlsDelAllPeerInd;
+ mmhMsg.bodyval = 0;
+
+ lim_sys_process_mmh_msg_api(pMac, &mmhMsg, ePROT);
+ return;
+} /*** end lim_send_sme_tdls_delete_all_peer_ind() ***/
+
+/**
+ * lim_send_sme_mgmt_tx_completion()
+ *
+ ***FUNCTION:
+ * This function is called to send the eWNI_SME_MGMT_FRM_TX_COMPLETION_IND
+ * message to SME.
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ *
+ ***NOTE:
+ * NA
+ *
+ * @param pMac - Pointer to global MAC structure
+ * @param psessionEntry - Pointer to the session entry
+ * @param txCompleteStatus - TX Complete Status of Mgmt Frames
+ * @return None
+ */
+void
+lim_send_sme_mgmt_tx_completion(tpAniSirGlobal pMac,
+ tpPESession psessionEntry, uint32_t txCompleteStatus)
+{
+ tSirMsgQ mmhMsg;
+ tSirMgmtTxCompletionInd *pSirMgmtTxCompletionInd;
+
+ pSirMgmtTxCompletionInd =
+ cdf_mem_malloc(sizeof(tSirMgmtTxCompletionInd));
+ if (NULL == pSirMgmtTxCompletionInd) {
+ lim_log(pMac, LOGP,
+ FL
+ ("AllocateMemory failed for eWNI_SME_MGMT_FRM_TX_COMPLETION_IND"));
+ return;
+ }
+ /* messageType */
+ pSirMgmtTxCompletionInd->messageType =
+ eWNI_SME_MGMT_FRM_TX_COMPLETION_IND;
+ pSirMgmtTxCompletionInd->length = sizeof(tSirMgmtTxCompletionInd);
+
+ /* sessionId */
+ pSirMgmtTxCompletionInd->sessionId = psessionEntry->smeSessionId;
+
+ pSirMgmtTxCompletionInd->txCompleteStatus = txCompleteStatus;
+
+ mmhMsg.type = eWNI_SME_MGMT_FRM_TX_COMPLETION_IND;
+ mmhMsg.bodyptr = pSirMgmtTxCompletionInd;
+ mmhMsg.bodyval = 0;
+
+ lim_sys_process_mmh_msg_api(pMac, &mmhMsg, ePROT);
+ return;
+} /*** end lim_send_sme_tdls_delete_all_peer_ind() ***/
+
+void lim_send_sme_tdls_event_notify(tpAniSirGlobal pMac, uint16_t msgType,
+ void *events)
+{
+ tSirMsgQ mmhMsg;
+
+ switch (msgType) {
+ case SIR_HAL_TDLS_SHOULD_DISCOVER:
+ mmhMsg.type = eWNI_SME_TDLS_SHOULD_DISCOVER;
+ break;
+ case SIR_HAL_TDLS_SHOULD_TEARDOWN:
+ mmhMsg.type = eWNI_SME_TDLS_SHOULD_TEARDOWN;
+ break;
+ case SIR_HAL_TDLS_PEER_DISCONNECTED:
+ mmhMsg.type = eWNI_SME_TDLS_PEER_DISCONNECTED;
+ break;
+ }
+
+ mmhMsg.bodyptr = events;
+ mmhMsg.bodyval = 0;
+ lim_sys_process_mmh_msg_api(pMac, &mmhMsg, ePROT);
+ return;
+}
+#endif /* FEATURE_WLAN_TDLS */
+
+/**
+ * lim_send_sme_deauth_ntf()
+ *
+ ***FUNCTION:
+ * This function is called by limProcessSmeMessages() to send
+ * eWNI_SME_DISASSOC_RSP/IND message to host
+ *
+ ***PARAMS:
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ * NA
+ *
+ ***NOTE:
+ * This function is used for sending eWNI_SME_DEAUTH_CNF or
+ * eWNI_SME_DEAUTH_IND to host depending on deauthentication trigger.
+ *
+ * @param peerMacAddr Indicates the peer MAC addr to which
+ * deauthentication was initiated
+ * @param reasonCode Indicates the reason for Deauthetication
+ * @param deauthTrigger Indicates the trigger for Deauthetication
+ * @param aid Indicates the STAID. This parameter is present
+ * only on AP.
+ *
+ * @return None
+ */
+void
+lim_send_sme_deauth_ntf(tpAniSirGlobal pMac, tSirMacAddr peerMacAddr,
+ tSirResultCodes reasonCode, uint16_t deauthTrigger,
+ uint16_t aid, uint8_t smesessionId,
+ uint16_t smetransactionId)
+{
+ uint8_t *pBuf;
+ tSirSmeDeauthRsp *pSirSmeDeauthRsp;
+ tSirSmeDeauthInd *pSirSmeDeauthInd;
+ tpPESession psessionEntry;
+ uint8_t sessionId;
+ uint32_t *pMsg;
+
+ psessionEntry = pe_find_session_by_bssid(pMac, peerMacAddr, &sessionId);
+ switch (deauthTrigger) {
+ case eLIM_PEER_ENTITY_DEAUTH:
+ return;
+
+ case eLIM_HOST_DEAUTH:
+ /**
+ * Deauthentication response to host triggered
+ * deauthentication.
+ */
+ pSirSmeDeauthRsp = cdf_mem_malloc(sizeof(tSirSmeDeauthRsp));
+ if (NULL == pSirSmeDeauthRsp) {
+ /* Log error */
+ lim_log(pMac, LOGP,
+ FL
+ ("call to AllocateMemory failed for eWNI_SME_DEAUTH_RSP"));
+
+ return;
+ }
+ lim_log(pMac, LOG1, FL("send eWNI_SME_DEAUTH_RSP with "
+ "retCode: %d for" MAC_ADDRESS_STR),
+ reasonCode, MAC_ADDR_ARRAY(peerMacAddr));
+ pSirSmeDeauthRsp->messageType = eWNI_SME_DEAUTH_RSP;
+ pSirSmeDeauthRsp->length = sizeof(tSirSmeDeauthRsp);
+ pSirSmeDeauthRsp->statusCode = reasonCode;
+ pSirSmeDeauthRsp->sessionId = smesessionId;
+ pSirSmeDeauthRsp->transactionId = smetransactionId;
+
+ pBuf = (uint8_t *) pSirSmeDeauthRsp->peerMacAddr;
+ cdf_mem_copy(pBuf, peerMacAddr, sizeof(tSirMacAddr));
+
+#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */
+ lim_diag_event_report(pMac, WLAN_PE_DIAG_DEAUTH_RSP_EVENT,
+ psessionEntry, 0, (uint16_t) reasonCode);
+#endif
+ pMsg = (uint32_t *) pSirSmeDeauthRsp;
+
+ break;
+
+ default:
+ /**
+ * Deauthentication indication due to Deauthentication
+ * frame reception from peer entity or due to
+ * loss of link with peer entity.
+ */
+ pSirSmeDeauthInd = cdf_mem_malloc(sizeof(tSirSmeDeauthInd));
+ if (NULL == pSirSmeDeauthInd) {
+ /* Log error */
+ lim_log(pMac, LOGP,
+ FL
+ ("call to AllocateMemory failed for eWNI_SME_DEAUTH_Ind"));
+
+ return;
+ }
+ lim_log(pMac, LOG1, FL("send eWNI_SME_DEAUTH_IND with "
+ "retCode: %d for " MAC_ADDRESS_STR),
+ reasonCode, MAC_ADDR_ARRAY(peerMacAddr));
+ pSirSmeDeauthInd->messageType = eWNI_SME_DEAUTH_IND;
+ pSirSmeDeauthInd->length = sizeof(tSirSmeDeauthInd);
+ pSirSmeDeauthInd->reasonCode = eSIR_MAC_UNSPEC_FAILURE_REASON;
+
+ /* sessionId */
+ pBuf = (uint8_t *) &pSirSmeDeauthInd->sessionId;
+ *pBuf++ = smesessionId;
+
+ /* transaction ID */
+ lim_copy_u16(pBuf, smetransactionId);
+ pBuf += sizeof(uint16_t);
+
+ /* status code */
+ lim_copy_u32(pBuf, reasonCode);
+ pBuf += sizeof(tSirResultCodes);
+
+ /* bssId */
+ cdf_mem_copy(pBuf, psessionEntry->bssId, sizeof(tSirMacAddr));
+ pBuf += sizeof(tSirMacAddr);
+
+ /* peerMacAddr */
+ cdf_mem_copy(pSirSmeDeauthInd->peerMacAddr, peerMacAddr,
+ sizeof(tSirMacAddr));
+
+#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */
+ lim_diag_event_report(pMac, WLAN_PE_DIAG_DEAUTH_IND_EVENT,
+ psessionEntry, 0, (uint16_t) reasonCode);
+#endif /* FEATURE_WLAN_DIAG_SUPPORT */
+ pMsg = (uint32_t *) pSirSmeDeauthInd;
+
+ break;
+ }
+
+ /*Delete the PE session created */
+ if (psessionEntry != NULL) {
+ pe_delete_session(pMac, psessionEntry);
+ }
+
+ lim_send_sme_disassoc_deauth_ntf(pMac, CDF_STATUS_SUCCESS,
+ (uint32_t *) pMsg);
+
+} /*** end lim_send_sme_deauth_ntf() ***/
+
+/**
+ * lim_send_sme_wm_status_change_ntf() - Send Notification
+ * @mac_ctx: Global MAC Context
+ * @status_change_code: Indicates the change in the wireless medium.
+ * @status_change_info: Indicates the information associated with
+ * change in the wireless medium.
+ * @info_len: Indicates the length of status change information
+ * being sent.
+ * @session_id SessionID
+ *
+ * This function is called by limProcessSmeMessages() to send
+ * eWNI_SME_WM_STATUS_CHANGE_NTF message to host.
+ *
+ * Return: None
+ */
+void
+lim_send_sme_wm_status_change_ntf(tpAniSirGlobal mac_ctx,
+ tSirSmeStatusChangeCode status_change_code,
+ uint32_t *status_change_info, uint16_t info_len, uint8_t session_id)
+{
+ tSirMsgQ msg;
+ tSirSmeWmStatusChangeNtf *wm_status_change_ntf;
+
+ wm_status_change_ntf = cdf_mem_malloc(sizeof(tSirSmeWmStatusChangeNtf));
+ if (NULL == wm_status_change_ntf) {
+ lim_log(mac_ctx, LOGE,
+ FL("Mem Alloc failed - eWNI_SME_WM_STATUS_CHANGE_NTF"));
+ return;
+ }
+
+ msg.type = eWNI_SME_WM_STATUS_CHANGE_NTF;
+ msg.bodyval = 0;
+ msg.bodyptr = wm_status_change_ntf;
+
+ switch (status_change_code) {
+ case eSIR_SME_RADAR_DETECTED:
+ break;
+ default:
+ wm_status_change_ntf->messageType =
+ eWNI_SME_WM_STATUS_CHANGE_NTF;
+ wm_status_change_ntf->statusChangeCode = status_change_code;
+ wm_status_change_ntf->length = sizeof(tSirSmeWmStatusChangeNtf);
+ wm_status_change_ntf->sessionId = session_id;
+ if (sizeof(wm_status_change_ntf->statusChangeInfo) >=
+ info_len) {
+ cdf_mem_copy(
+ (uint8_t *) &wm_status_change_ntf->statusChangeInfo,
+ (uint8_t *) status_change_info, info_len);
+ }
+ lim_log(mac_ctx, LOGE,
+ FL("**---** StatusChg: code 0x%x, length %d **---**"),
+ status_change_code, info_len);
+ break;
+ }
+
+ MTRACE(mac_trace_msg_tx(mac_ctx, session_id, msg.type));
+ if (eSIR_SUCCESS != lim_sys_process_mmh_msg_api(mac_ctx, &msg, ePROT)) {
+ cdf_mem_free(wm_status_change_ntf);
+ lim_log(mac_ctx, LOGP,
+ FL("lim_sys_process_mmh_msg_api failed"));
+ }
+
+} /*** end lim_send_sme_wm_status_change_ntf() ***/
+
+/**
+ * lim_send_sme_set_context_rsp()
+ *
+ ***FUNCTION:
+ * This function is called by limProcessSmeMessages() to send
+ * eWNI_SME_SETCONTEXT_RSP message to host
+ *
+ ***PARAMS:
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ * NA
+ *
+ ***NOTE:
+ *
+ * @param pMac Pointer to Global MAC structure
+ * @param peerMacAddr Indicates the peer MAC addr to which
+ * setContext was performed
+ * @param aid Indicates the aid corresponding to the peer MAC
+ * address
+ * @param resultCode Indicates the result of previously issued
+ * eWNI_SME_SETCONTEXT_RSP message
+ *
+ * @return None
+ */
+void
+lim_send_sme_set_context_rsp(tpAniSirGlobal pMac,
+ tSirMacAddr peerMacAddr, uint16_t aid,
+ tSirResultCodes resultCode,
+ tpPESession psessionEntry, uint8_t smesessionId,
+ uint16_t smetransactionId)
+{
+
+ uint8_t *pBuf;
+ tSirMsgQ mmhMsg;
+ tSirSmeSetContextRsp *pSirSmeSetContextRsp;
+
+ pSirSmeSetContextRsp = cdf_mem_malloc(sizeof(tSirSmeSetContextRsp));
+ if (NULL == pSirSmeSetContextRsp) {
+ /* Log error */
+ lim_log(pMac, LOGP,
+ FL
+ ("call to AllocateMemory failed for SmeSetContextRsp"));
+
+ return;
+ }
+
+ pSirSmeSetContextRsp->messageType = eWNI_SME_SETCONTEXT_RSP;
+ pSirSmeSetContextRsp->length = sizeof(tSirSmeSetContextRsp);
+ pSirSmeSetContextRsp->statusCode = resultCode;
+
+ pBuf = pSirSmeSetContextRsp->peerMacAddr;
+
+ cdf_mem_copy(pBuf, (uint8_t *) peerMacAddr, sizeof(tSirMacAddr));
+ pBuf += sizeof(tSirMacAddr);
+
+ /* Update SME session and transaction Id */
+ pSirSmeSetContextRsp->sessionId = smesessionId;
+ pSirSmeSetContextRsp->transactionId = smetransactionId;
+
+ mmhMsg.type = eWNI_SME_SETCONTEXT_RSP;
+ mmhMsg.bodyptr = pSirSmeSetContextRsp;
+ mmhMsg.bodyval = 0;
+ if (NULL == psessionEntry) {
+ MTRACE(mac_trace_msg_tx(pMac, NO_SESSION, mmhMsg.type));
+ } else {
+ MTRACE(mac_trace_msg_tx
+ (pMac, psessionEntry->peSessionId, mmhMsg.type));
+ }
+
+#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */
+ lim_diag_event_report(pMac, WLAN_PE_DIAG_SETCONTEXT_RSP_EVENT,
+ psessionEntry, (uint16_t) resultCode, 0);
+#endif /* FEATURE_WLAN_DIAG_SUPPORT */
+
+ lim_sys_process_mmh_msg_api(pMac, &mmhMsg, ePROT);
+} /*** end lim_send_sme_set_context_rsp() ***/
+
+/**
+ * lim_send_sme_neighbor_bss_ind()
+ *
+ ***FUNCTION:
+ * This function is called by lim_lookup_nadd_hash_entry() to send
+ * eWNI_SME_NEIGHBOR_BSS_IND message to host
+ *
+ ***PARAMS:
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ * NA
+ *
+ ***NOTE:
+ * This function is used for sending eWNI_SME_NEIGHBOR_BSS_IND to
+ * host upon detecting new BSS during background scanning if CFG
+ * option is enabled for sending such indication
+ *
+ * @param pMac - Pointer to Global MAC structure
+ * @return None
+ */
+
+void
+lim_send_sme_neighbor_bss_ind(tpAniSirGlobal pMac, tLimScanResultNode *pBssDescr)
+{
+ tSirMsgQ msgQ;
+ uint32_t val;
+ tSirSmeNeighborBssInd *pNewBssInd;
+
+ if ((pMac->lim.gLimSmeState != eLIM_SME_LINK_EST_WT_SCAN_STATE) ||
+ ((pMac->lim.gLimSmeState == eLIM_SME_LINK_EST_WT_SCAN_STATE) &&
+ pMac->lim.gLimRspReqd)) {
+ /* LIM is not in background scan state OR */
+ /* current scan is initiated by HDD. */
+ /* No need to send new BSS indication to HDD */
+ return;
+ }
+
+ if (wlan_cfg_get_int(pMac, WNI_CFG_NEW_BSS_FOUND_IND, &val) !=
+ eSIR_SUCCESS) {
+ lim_log(pMac, LOGP,
+ FL("could not get NEIGHBOR_BSS_IND from CFG"));
+
+ return;
+ }
+
+ if (val == 0)
+ return;
+
+ /**
+ * Need to indicate new BSSs found during
+ * background scanning to host.
+ * Allocate buffer for sending indication.
+ * Length of buffer is length of BSS description
+ * and length of header itself
+ */
+ val = pBssDescr->bssDescription.length + sizeof(uint16_t) +
+ sizeof(uint32_t) + sizeof(uint8_t);
+ pNewBssInd = cdf_mem_malloc(val);
+ if (NULL == pNewBssInd) {
+ /* Log error */
+ lim_log(pMac, LOGP,
+ FL
+ ("call to AllocateMemory failed for eWNI_SME_NEIGHBOR_BSS_IND"));
+
+ return;
+ }
+
+ pNewBssInd->messageType = eWNI_SME_NEIGHBOR_BSS_IND;
+ pNewBssInd->length = (uint16_t) val;
+ pNewBssInd->sessionId = 0;
+
+ cdf_mem_copy((uint8_t *) pNewBssInd->bssDescription,
+ (uint8_t *) &pBssDescr->bssDescription,
+ pBssDescr->bssDescription.length + sizeof(uint16_t));
+
+ msgQ.type = eWNI_SME_NEIGHBOR_BSS_IND;
+ msgQ.bodyptr = pNewBssInd;
+ msgQ.bodyval = 0;
+ MTRACE(mac_trace_msg_tx(pMac, NO_SESSION, msgQ.type));
+ lim_sys_process_mmh_msg_api(pMac, &msgQ, ePROT);
+} /*** end lim_send_sme_neighbor_bss_ind() ***/
+
+/** -----------------------------------------------------------------
+ \brief lim_send_sme_addts_rsp() - sends SME ADDTS RSP
+ \ This function sends a eWNI_SME_ADDTS_RSP to SME.
+ \ SME only looks at rc and tspec field.
+ \param pMac - global mac structure
+ \param rspReqd - is SmeAddTsRsp required
+ \param status - status code of SME_ADD_TS_RSP
+ \return tspec
+ \sa
+ ----------------------------------------------------------------- */
+void
+lim_send_sme_addts_rsp(tpAniSirGlobal pMac, uint8_t rspReqd, uint32_t status,
+ tpPESession psessionEntry, tSirMacTspecIE tspec,
+ uint8_t smesessionId, uint16_t smetransactionId)
+{
+ tpSirAddtsRsp rsp;
+ tSirMsgQ mmhMsg;
+
+ if (!rspReqd)
+ return;
+
+ rsp = cdf_mem_malloc(sizeof(tSirAddtsRsp));
+ if (NULL == rsp) {
+ lim_log(pMac, LOGP, FL("AllocateMemory failed for ADDTS_RSP"));
+ return;
+ }
+
+ cdf_mem_set((uint8_t *) rsp, sizeof(*rsp), 0);
+ rsp->messageType = eWNI_SME_ADDTS_RSP;
+ rsp->rc = status;
+ rsp->rsp.status = (enum eSirMacStatusCodes)status;
+ rsp->rsp.tspec = tspec;
+ /* Update SME session Id and transcation Id */
+ rsp->sessionId = smesessionId;
+ rsp->transactionId = smetransactionId;
+
+ mmhMsg.type = eWNI_SME_ADDTS_RSP;
+ mmhMsg.bodyptr = rsp;
+ mmhMsg.bodyval = 0;
+ if (NULL == psessionEntry) {
+ MTRACE(mac_trace_msg_tx(pMac, NO_SESSION, mmhMsg.type));
+ } else {
+ MTRACE(mac_trace_msg_tx
+ (pMac, psessionEntry->peSessionId, mmhMsg.type));
+ }
+#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */
+ lim_diag_event_report(pMac, WLAN_PE_DIAG_ADDTS_RSP_EVENT, psessionEntry, 0,
+ 0);
+#endif /* FEATURE_WLAN_DIAG_SUPPORT */
+
+ lim_sys_process_mmh_msg_api(pMac, &mmhMsg, ePROT);
+ return;
+}
+
+void
+lim_send_sme_delts_rsp(tpAniSirGlobal pMac, tpSirDeltsReq delts, uint32_t status,
+ tpPESession psessionEntry, uint8_t smesessionId,
+ uint16_t smetransactionId)
+{
+ tpSirDeltsRsp rsp;
+ tSirMsgQ mmhMsg;
+
+ lim_log(pMac, LOGW, "SendSmeDeltsRsp (aid %d, tsid %d, up %d) status %d",
+ delts->aid,
+ delts->req.tsinfo.traffic.tsid,
+ delts->req.tsinfo.traffic.userPrio, status);
+ if (!delts->rspReqd)
+ return;
+
+ rsp = cdf_mem_malloc(sizeof(tSirDeltsRsp));
+ if (NULL == rsp) {
+ /* Log error */
+ lim_log(pMac, LOGP, FL("AllocateMemory failed for DELTS_RSP"));
+ return;
+ }
+ cdf_mem_set((uint8_t *) rsp, sizeof(*rsp), 0);
+
+ if (psessionEntry != NULL) {
+
+ rsp->aid = delts->aid;
+ cdf_mem_copy((uint8_t *) &rsp->macAddr[0],
+ (uint8_t *) &delts->macAddr[0], 6);
+ cdf_mem_copy((uint8_t *) &rsp->rsp, (uint8_t *) &delts->req,
+ sizeof(tSirDeltsReqInfo));
+ }
+
+ rsp->messageType = eWNI_SME_DELTS_RSP;
+ rsp->rc = status;
+
+ /* Update SME session Id and transcation Id */
+ rsp->sessionId = smesessionId;
+ rsp->transactionId = smetransactionId;
+
+ mmhMsg.type = eWNI_SME_DELTS_RSP;
+ mmhMsg.bodyptr = rsp;
+ mmhMsg.bodyval = 0;
+ if (NULL == psessionEntry) {
+ MTRACE(mac_trace_msg_tx(pMac, NO_SESSION, mmhMsg.type));
+ } else {
+ MTRACE(mac_trace_msg_tx
+ (pMac, psessionEntry->peSessionId, mmhMsg.type));
+ }
+#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */
+ lim_diag_event_report(pMac, WLAN_PE_DIAG_DELTS_RSP_EVENT, psessionEntry,
+ (uint16_t) status, 0);
+#endif /* FEATURE_WLAN_DIAG_SUPPORT */
+
+ lim_sys_process_mmh_msg_api(pMac, &mmhMsg, ePROT);
+}
+
+void
+lim_send_sme_delts_ind(tpAniSirGlobal pMac, tpSirDeltsReqInfo delts, uint16_t aid,
+ tpPESession psessionEntry)
+{
+ tpSirDeltsRsp rsp;
+ tSirMsgQ mmhMsg;
+
+ lim_log(pMac, LOGW, "SendSmeDeltsInd (aid %d, tsid %d, up %d)",
+ aid, delts->tsinfo.traffic.tsid, delts->tsinfo.traffic.userPrio);
+
+ rsp = cdf_mem_malloc(sizeof(tSirDeltsRsp));
+ if (NULL == rsp) {
+ /* Log error */
+ lim_log(pMac, LOGP, FL("AllocateMemory failed for DELTS_IND"));
+ return;
+ }
+ cdf_mem_set((uint8_t *) rsp, sizeof(*rsp), 0);
+
+ rsp->messageType = eWNI_SME_DELTS_IND;
+ rsp->rc = eSIR_SUCCESS;
+ rsp->aid = aid;
+ cdf_mem_copy((uint8_t *) &rsp->rsp, (uint8_t *) delts, sizeof(*delts));
+
+ /* Update SME session Id and SME transaction Id */
+
+ rsp->sessionId = psessionEntry->smeSessionId;
+ rsp->transactionId = psessionEntry->transactionId;
+
+ mmhMsg.type = eWNI_SME_DELTS_IND;
+ mmhMsg.bodyptr = rsp;
+ mmhMsg.bodyval = 0;
+ MTRACE(mac_trace_msg_tx(pMac, psessionEntry->peSessionId, mmhMsg.type));
+#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */
+ lim_diag_event_report(pMac, WLAN_PE_DIAG_DELTS_IND_EVENT, psessionEntry, 0,
+ 0);
+#endif /* FEATURE_WLAN_DIAG_SUPPORT */
+
+ lim_sys_process_mmh_msg_api(pMac, &mmhMsg, ePROT);
+}
+
+/**
+ * lim_send_sme_pe_statistics_rsp()
+ *
+ ***FUNCTION:
+ * This function is called to send 802.11 statistics response to HDD.
+ * This function posts the result back to HDD. This is a response to
+ * HDD's request for statistics.
+ *
+ ***PARAMS:
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ * NA
+ *
+ ***NOTE:
+ * NA
+ *
+ * @param pMac Pointer to Global MAC structure
+ * @param p80211Stats Statistics sent in response
+ * @param resultCode TODO:
+ *
+ *
+ * @return none
+ */
+
+void
+lim_send_sme_pe_statistics_rsp(tpAniSirGlobal pMac, uint16_t msgType, void *stats)
+{
+ tSirMsgQ mmhMsg;
+ uint8_t sessionId;
+ tAniGetPEStatsRsp *pPeStats = (tAniGetPEStatsRsp *) stats;
+ tpPESession pPeSessionEntry;
+
+ /* Get the Session Id based on Sta Id */
+ pPeSessionEntry =
+ pe_find_session_by_sta_id(pMac, pPeStats->staId, &sessionId);
+
+ /* Fill the Session Id */
+ if (NULL != pPeSessionEntry) {
+ /* Fill the Session Id */
+ pPeStats->sessionId = pPeSessionEntry->smeSessionId;
+ }
+
+ pPeStats->msgType = eWNI_SME_GET_STATISTICS_RSP;
+
+ /* msgType should be WMA_GET_STATISTICS_RSP */
+ mmhMsg.type = eWNI_SME_GET_STATISTICS_RSP;
+
+ mmhMsg.bodyptr = stats;
+ mmhMsg.bodyval = 0;
+ MTRACE(mac_trace_msg_tx(pMac, NO_SESSION, mmhMsg.type));
+ lim_sys_process_mmh_msg_api(pMac, &mmhMsg, ePROT);
+
+ return;
+
+} /*** end lim_send_sme_pe_statistics_rsp() ***/
+
+#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
+/**
+ * lim_send_sme_pe_ese_tsm_rsp()
+ *
+ ***FUNCTION:
+ * This function is called to send tsm stats response to HDD.
+ * This function posts the result back to HDD. This is a response to
+ * HDD's request to get tsm stats.
+ *
+ ***PARAMS:
+ * @param pMac - Pointer to global pMac structure
+ * @param pStats - Pointer to TSM Stats
+ *
+ * @return none
+ */
+
+void lim_send_sme_pe_ese_tsm_rsp(tpAniSirGlobal pMac, tAniGetTsmStatsRsp *pStats)
+{
+ tSirMsgQ mmhMsg;
+ uint8_t sessionId;
+ tAniGetTsmStatsRsp *pPeStats = (tAniGetTsmStatsRsp *) pStats;
+ tpPESession pPeSessionEntry = NULL;
+
+ /* Get the Session Id based on Sta Id */
+ pPeSessionEntry =
+ pe_find_session_by_sta_id(pMac, pPeStats->staId, &sessionId);
+
+ /* Fill the Session Id */
+ if (NULL != pPeSessionEntry) {
+ /* Fill the Session Id */
+ pPeStats->sessionId = pPeSessionEntry->smeSessionId;
+ } else {
+ PELOGE(lim_log
+ (pMac, LOGE, FL("Session not found for the Sta id(%d)"),
+ pPeStats->staId);
+ )
+ return;
+ }
+
+ pPeStats->msgType = eWNI_SME_GET_TSM_STATS_RSP;
+ pPeStats->tsmMetrics.RoamingCount
+ = pPeSessionEntry->eseContext.tsm.tsmMetrics.RoamingCount;
+ pPeStats->tsmMetrics.RoamingDly
+ = pPeSessionEntry->eseContext.tsm.tsmMetrics.RoamingDly;
+
+ mmhMsg.type = eWNI_SME_GET_TSM_STATS_RSP;
+ mmhMsg.bodyptr = pStats;
+ mmhMsg.bodyval = 0;
+ MTRACE(mac_trace_msg_tx(pMac, sessionId, mmhMsg.type));
+ lim_sys_process_mmh_msg_api(pMac, &mmhMsg, ePROT);
+
+ return;
+} /*** end lim_send_sme_pe_ese_tsm_rsp() ***/
+
+#endif /* FEATURE_WLAN_ESE) && FEATURE_WLAN_ESE_UPLOAD */
+
+void
+lim_send_sme_ibss_peer_ind(tpAniSirGlobal pMac,
+ tSirMacAddr peerMacAddr,
+ uint16_t staIndex,
+ uint8_t ucastIdx,
+ uint8_t bcastIdx,
+ uint8_t *beacon,
+ uint16_t beaconLen, uint16_t msgType, uint8_t sessionId)
+{
+ tSirMsgQ mmhMsg;
+ tSmeIbssPeerInd *pNewPeerInd;
+
+ pNewPeerInd = cdf_mem_malloc(sizeof(tSmeIbssPeerInd) + beaconLen);
+ if (NULL == pNewPeerInd) {
+ PELOGE(lim_log(pMac, LOGE, FL("Failed to allocate memory"));)
+ return;
+ }
+
+ cdf_mem_set((void *)pNewPeerInd, (sizeof(tSmeIbssPeerInd) + beaconLen),
+ 0);
+
+ cdf_mem_copy((uint8_t *) pNewPeerInd->peerAddr,
+ peerMacAddr, sizeof(tSirMacAddr));
+ pNewPeerInd->staId = staIndex;
+ pNewPeerInd->ucastSig = ucastIdx;
+ pNewPeerInd->bcastSig = bcastIdx;
+ pNewPeerInd->mesgLen = sizeof(tSmeIbssPeerInd) + beaconLen;
+ pNewPeerInd->mesgType = msgType;
+ pNewPeerInd->sessionId = sessionId;
+
+ if (beacon != NULL) {
+ cdf_mem_copy((void *)((uint8_t *) pNewPeerInd +
+ sizeof(tSmeIbssPeerInd)), (void *)beacon,
+ beaconLen);
+ }
+
+ mmhMsg.type = msgType;
+ mmhMsg.bodyptr = pNewPeerInd;
+ MTRACE(mac_trace_msg_tx(pMac, sessionId, mmhMsg.type));
+ lim_sys_process_mmh_msg_api(pMac, &mmhMsg, ePROT);
+
+}
+
+/**
+ * lim_handle_csa_offload_msg() - Handle CSA offload message
+ * @mac_ctx: pointer to global adapter context
+ * @msg: Message pointer.
+ *
+ * Return: None
+ */
+void lim_handle_csa_offload_msg(tpAniSirGlobal mac_ctx, tpSirMsgQ msg)
+{
+ tpPESession session_entry;
+ tSirMsgQ mmh_msg;
+ tpCSAOffloadParams csa_params = (tpCSAOffloadParams) (msg->bodyptr);
+ tpSmeCsaOffloadInd csa_offload_ind;
+ tpDphHashNode sta_ds = NULL;
+ uint8_t session_id;
+ uint16_t aid = 0;
+ tLimWiderBWChannelSwitchInfo *chnl_switch_info = NULL;
+
+ if (!csa_params) {
+ lim_log(mac_ctx, LOGE, FL("limMsgQ body ptr is NULL"));
+ return;
+ }
+
+ session_entry =
+ pe_find_session_by_bssid(mac_ctx,
+ csa_params->bssId, &session_id);
+ if (!session_entry) {
+ lim_log(mac_ctx, LOGE,
+ FL("Session does not exist"));
+ goto err;
+ }
+
+ sta_ds = dph_lookup_hash_entry(mac_ctx, session_entry->bssId, &aid,
+ &session_entry->dph.dphHashTable);
+
+ if (!sta_ds) {
+ lim_log(mac_ctx, LOGE,
+ FL("sta_ds does not exist"));
+ goto err;
+ }
+
+ if (LIM_IS_STA_ROLE(session_entry)) {
+ session_entry->gLimChannelSwitch.switchMode =
+ csa_params->switchmode;
+ /* timer already started by firmware, switch immediately */
+ session_entry->gLimChannelSwitch.switchCount = 0;
+ session_entry->gLimChannelSwitch.primaryChannel =
+ csa_params->channel;
+ session_entry->gLimChannelSwitch.state =
+ eLIM_CHANNEL_SWITCH_PRIMARY_ONLY;
+ session_entry->gLimChannelSwitch.ch_width = CH_WIDTH_20MHZ;
+
+ if (session_entry->vhtCapability &&
+ session_entry->htSupportedChannelWidthSet) {
+ chnl_switch_info =
+ &session_entry->gLimWiderBWChannelSwitch;
+ if (csa_params->ies_present_flag & lim_wbw_ie_present) {
+ chnl_switch_info->newChanWidth =
+ csa_params->new_ch_width;
+ chnl_switch_info->newCenterChanFreq0 =
+ csa_params->new_ch_freq_seg1;
+ chnl_switch_info->newCenterChanFreq1 =
+ csa_params->new_ch_freq_seg2;
+ session_entry->gLimChannelSwitch.state =
+ eLIM_CHANNEL_SWITCH_PRIMARY_AND_SECONDARY;
+ session_entry->gLimChannelSwitch.ch_width =
+ csa_params->new_ch_width + 1;
+ }
+ } else if (session_entry->htSupportedChannelWidthSet) {
+ if (csa_params->sec_chan_offset) {
+ session_entry->gLimChannelSwitch.ch_width =
+ CH_WIDTH_40MHZ;
+ session_entry->gLimChannelSwitch.state =
+ eLIM_CHANNEL_SWITCH_PRIMARY_AND_SECONDARY;
+ } else {
+ session_entry->htSupportedChannelWidthSet =
+ WNI_CFG_CHANNEL_BONDING_MODE_DISABLE;
+ session_entry->htRecommendedTxWidthSet =
+ session_entry->htSupportedChannelWidthSet;
+ }
+ }
+ lim_log(mac_ctx, LOG1, FL("new ch width = %d"),
+ session_entry->gLimChannelSwitch.ch_width);
+
+ lim_prepare_for11h_channel_switch(mac_ctx, session_entry);
+ csa_offload_ind = cdf_mem_malloc(sizeof(tSmeCsaOffloadInd));
+ if (NULL == csa_offload_ind) {
+ lim_log(mac_ctx, LOGE,
+ FL("memalloc fail eWNI_SME_CSA_OFFLOAD_EVENT"));
+ goto err;
+ }
+
+ cdf_mem_set(csa_offload_ind, sizeof(tSmeCsaOffloadInd), 0);
+ csa_offload_ind->mesgType = eWNI_SME_CSA_OFFLOAD_EVENT;
+ csa_offload_ind->mesgLen = sizeof(tSmeCsaOffloadInd);
+ cdf_mem_copy(csa_offload_ind->bssId, session_entry->bssId,
+ sizeof(tSirMacAddr));
+ mmh_msg.type = eWNI_SME_CSA_OFFLOAD_EVENT;
+ mmh_msg.bodyptr = csa_offload_ind;
+ mmh_msg.bodyval = 0;
+ lim_log(mac_ctx, LOG1,
+ FL("Sending eWNI_SME_CSA_OFFLOAD_EVENT to SME. "));
+ MTRACE(mac_trace_msg_tx
+ (mac_ctx, session_entry->peSessionId, mmh_msg.type));
+#ifdef FEATURE_WLAN_DIAG_SUPPORT
+ lim_diag_event_report(mac_ctx,
+ WLAN_PE_DIAG_SWITCH_CHL_IND_EVENT, session_entry,
+ eSIR_SUCCESS, eSIR_SUCCESS);
+#endif
+ lim_sys_process_mmh_msg_api(mac_ctx, &mmh_msg, ePROT);
+ }
+
+err:
+ cdf_mem_free(csa_params);
+}
+
+/*--------------------------------------------------------------------------
+ \brief pe_delete_session() - Handle the Delete BSS Response from HAL.
+
+ \param pMac - pointer to global adapter context
+ \param sessionId - Message pointer.
+
+ \sa
+ --------------------------------------------------------------------------*/
+
+void lim_handle_delete_bss_rsp(tpAniSirGlobal pMac, tpSirMsgQ MsgQ)
+{
+ tpPESession psessionEntry;
+ tpDeleteBssParams pDelBss = (tpDeleteBssParams) (MsgQ->bodyptr);
+
+ psessionEntry =
+ pe_find_session_by_session_id(pMac, pDelBss->sessionId);
+ if (psessionEntry == NULL) {
+ lim_log(pMac, LOGE,
+ FL("Session Does not exist for given sessionID %d"),
+ pDelBss->sessionId);
+ return;
+ }
+ if (LIM_IS_IBSS_ROLE(psessionEntry)) {
+ lim_ibss_del_bss_rsp(pMac, MsgQ->bodyptr, psessionEntry);
+ } else if (LIM_IS_UNKNOWN_ROLE(psessionEntry)) {
+ lim_process_sme_del_bss_rsp(pMac, MsgQ->bodyval, psessionEntry);
+ }
+
+ else
+ lim_process_mlm_del_bss_rsp(pMac, MsgQ, psessionEntry);
+
+}
+
+#ifdef WLAN_FEATURE_VOWIFI_11R
+/** -----------------------------------------------------------------
+ \brief lim_send_sme_aggr_qos_rsp() - sends SME FT AGGR QOS RSP
+ \ This function sends a eWNI_SME_FT_AGGR_QOS_RSP to SME.
+ \ SME only looks at rc and tspec field.
+ \param pMac - global mac structure
+ \param rspReqd - is SmeAddTsRsp required
+ \param status - status code of eWNI_SME_FT_AGGR_QOS_RSP
+ \return tspec
+ \sa
+ ----------------------------------------------------------------- */
+void
+lim_send_sme_aggr_qos_rsp(tpAniSirGlobal pMac, tpSirAggrQosRsp aggrQosRsp,
+ uint8_t smesessionId)
+{
+ tSirMsgQ mmhMsg;
+
+ mmhMsg.type = eWNI_SME_FT_AGGR_QOS_RSP;
+ mmhMsg.bodyptr = aggrQosRsp;
+ mmhMsg.bodyval = 0;
+ MTRACE(mac_trace_msg_tx(pMac, smesessionId, mmhMsg.type));
+ lim_sys_process_mmh_msg_api(pMac, &mmhMsg, ePROT);
+
+ return;
+}
+#endif
+
+void lim_send_sme_max_assoc_exceeded_ntf(tpAniSirGlobal pMac, tSirMacAddr peerMacAddr,
+ uint8_t smesessionId)
+{
+ tSirMsgQ mmhMsg;
+ tSmeMaxAssocInd *pSmeMaxAssocInd;
+
+ pSmeMaxAssocInd = cdf_mem_malloc(sizeof(tSmeMaxAssocInd));
+ if (NULL == pSmeMaxAssocInd) {
+ PELOGE(lim_log(pMac, LOGE, FL("Failed to allocate memory"));)
+ return;
+ }
+ cdf_mem_set((void *)pSmeMaxAssocInd, sizeof(tSmeMaxAssocInd), 0);
+ cdf_mem_copy((uint8_t *) pSmeMaxAssocInd->peerMac,
+ (uint8_t *) peerMacAddr, sizeof(tSirMacAddr));
+ pSmeMaxAssocInd->mesgType = eWNI_SME_MAX_ASSOC_EXCEEDED;
+ pSmeMaxAssocInd->mesgLen = sizeof(tSmeMaxAssocInd);
+ pSmeMaxAssocInd->sessionId = smesessionId;
+ mmhMsg.type = pSmeMaxAssocInd->mesgType;
+ mmhMsg.bodyptr = pSmeMaxAssocInd;
+ PELOG1(lim_log(pMac, LOG1, FL("msgType %s peerMacAddr " MAC_ADDRESS_STR
+ " sme session id %d"),
+ "eWNI_SME_MAX_ASSOC_EXCEEDED",
+ MAC_ADDR_ARRAY(peerMacAddr));
+ )
+ MTRACE(mac_trace_msg_tx(pMac, smesessionId, mmhMsg.type));
+ lim_sys_process_mmh_msg_api(pMac, &mmhMsg, ePROT);
+
+ return;
+}
+
+/** -----------------------------------------------------------------
+ \brief lim_send_sme_dfs_event_notify() - sends
+ eWNI_SME_DFS_RADAR_FOUND
+ After receiving WMI_PHYERR_EVENTID indication frame from FW, this
+ function sends a eWNI_SME_DFS_RADAR_FOUND to SME to notify
+ that a RADAR is found on current operating channel and SAP-
+ has to move to a new channel.
+ \param pMac - global mac structure
+ \param msgType - message type received from lower layer
+ \param event - event data received from lower layer
+ \return none
+ \sa
+ ----------------------------------------------------------------- */
+void
+lim_send_sme_dfs_event_notify(tpAniSirGlobal pMac, uint16_t msgType, void *event)
+{
+ tSirMsgQ mmhMsg;
+ mmhMsg.type = eWNI_SME_DFS_RADAR_FOUND;
+ mmhMsg.bodyptr = event;
+ mmhMsg.bodyval = 0;
+ lim_sys_process_mmh_msg_api(pMac, &mmhMsg, ePROT);
+ return;
+}
+
+/*--------------------------------------------------------------------------
+ \brief lim_send_dfs_chan_sw_ie_update()
+ This timer handler updates the channel switch IE in beacon template
+
+ \param pMac - pointer to global adapter context
+ \return - channel to scan from valid session else zero.
+ \sa
+ --------------------------------------------------------------------------*/
+static void
+lim_send_dfs_chan_sw_ie_update(tpAniSirGlobal pMac, tpPESession psessionEntry)
+{
+
+ /* Update the beacon template and send to FW */
+ if (sch_set_fixed_beacon_fields(pMac, psessionEntry) != eSIR_SUCCESS) {
+ PELOGE(lim_log(pMac, LOGE, FL("Unable to set CSA IE in beacon"));)
+ return;
+ }
+
+ /* Send update beacon template message */
+ lim_send_beacon_ind(pMac, psessionEntry);
+ PELOG1(lim_log(pMac, LOG1,
+ FL(" Updated CSA IE, IE COUNT = %d"),
+ psessionEntry->gLimChannelSwitch.switchCount);
+ )
+
+ return;
+}
+
+/** -----------------------------------------------------------------
+ \brief lim_send_sme_ap_channel_switch_resp() - sends
+ eWNI_SME_CHANNEL_CHANGE_RSP
+ After receiving WMA_SWITCH_CHANNEL_RSP indication this
+ function sends a eWNI_SME_CHANNEL_CHANGE_RSP to SME to notify
+ that the Channel change has been done to the specified target
+ channel in the Channel change request
+ \param pMac - global mac structure
+ \param psessionEntry - session info
+ \param pChnlParams - Channel switch params
+ --------------------------------------------------------------------*/
+void
+lim_send_sme_ap_channel_switch_resp(tpAniSirGlobal pMac,
+ tpPESession psessionEntry,
+ tpSwitchChannelParams pChnlParams)
+{
+ tSirMsgQ mmhMsg;
+ tpSwitchChannelParams pSmeSwithChnlParams;
+ uint8_t channelId;
+
+ pSmeSwithChnlParams = (tSwitchChannelParams *)
+ cdf_mem_malloc(sizeof(tSwitchChannelParams));
+ if (NULL == pSmeSwithChnlParams) {
+ lim_log(pMac, LOGP,
+ FL("AllocateMemory failed for pSmeSwithChnlParams\n"));
+ return;
+ }
+
+ cdf_mem_set((void *)pSmeSwithChnlParams,
+ sizeof(tSwitchChannelParams), 0);
+
+ cdf_mem_copy(pSmeSwithChnlParams, pChnlParams,
+ sizeof(tSwitchChannelParams));
+
+ channelId = pSmeSwithChnlParams->channelNumber;
+
+ /*
+ * Pass the sme sessionID to SME instead
+ * PE session ID.
+ */
+ pSmeSwithChnlParams->peSessionId = psessionEntry->smeSessionId;
+
+ mmhMsg.type = eWNI_SME_CHANNEL_CHANGE_RSP;
+ mmhMsg.bodyptr = (void *)pSmeSwithChnlParams;
+ mmhMsg.bodyval = 0;
+ lim_sys_process_mmh_msg_api(pMac, &mmhMsg, ePROT);
+
+ /*
+ * We should start beacon transmission only if the new
+ * channel after channel change is Non-DFS. For a DFS
+ * channel, PE will receive an explicit request from
+ * upper layers to start the beacon transmission .
+ */
+
+ if (CHANNEL_STATE_DFS != cds_get_channel_state(channelId)) {
+ if (channelId == psessionEntry->currentOperChannel) {
+ lim_apply_configuration(pMac, psessionEntry);
+ lim_send_beacon_ind(pMac, psessionEntry);
+ } else {
+ PELOG1(lim_log(pMac, LOG1,
+ FL
+ ("Failed to Transmit Beacons on channel = %d"
+ "after AP channel change response"),
+ psessionEntry->bcnLen);
+ )
+ }
+ }
+ return;
+}
+
+/** -----------------------------------------------------------------
+ \brief lim_process_beacon_tx_success_ind() - This function is used
+ explicitely to handle successful beacon transmission indication
+ from the FW. This is a generic event generated by the FW afer the
+ first beacon is sent out after the beacon template update by the
+ host
+ \param pMac - global mac structure
+ \param psessionEntry - session info
+ \return none
+ \sa
+ ----------------------------------------------------------------- */
+void
+lim_process_beacon_tx_success_ind(tpAniSirGlobal pMac, uint16_t msgType, void *event)
+{
+ /* Currently, this event is used only for DFS channel switch announcement
+ * IE update in the template. If required to be used for other IE updates
+ * add appropriate code by introducing a state variable
+ */
+ tpPESession psessionEntry;
+ tSirMsgQ mmhMsg;
+ tSirSmeCSAIeTxCompleteRsp *pChanSwTxResponse;
+ struct sir_beacon_tx_complete_rsp *beacon_tx_comp_rsp_ptr;
+ uint8_t length = sizeof(tSirSmeCSAIeTxCompleteRsp);
+ tpSirFirstBeaconTxCompleteInd pBcnTxInd =
+ (tSirFirstBeaconTxCompleteInd *) event;
+
+ psessionEntry = pe_find_session_by_bss_idx(pMac, pBcnTxInd->bssIdx);
+ if (psessionEntry == NULL) {
+ lim_log(pMac, LOGE,
+ FL("Session Does not exist for given sessionID"));
+ return;
+ }
+
+ if (LIM_IS_AP_ROLE(psessionEntry) &&
+ true == psessionEntry->dfsIncludeChanSwIe) {
+ /* Send only 5 beacons with CSA IE Set in when a radar is detected */
+ if (psessionEntry->gLimChannelSwitch.switchCount > 0) {
+ /*
+ * Send the next beacon with updated CSA IE count
+ */
+ lim_send_dfs_chan_sw_ie_update(pMac, psessionEntry);
+ /* Decrement the IE count */
+ psessionEntry->gLimChannelSwitch.switchCount--;
+ } else {
+ /* Done with CSA IE update, send response back to SME */
+ psessionEntry->gLimChannelSwitch.switchCount = 0;
+ if (pMac->sap.SapDfsInfo.disable_dfs_ch_switch == false)
+ psessionEntry->gLimChannelSwitch.switchMode = 0;
+ psessionEntry->dfsIncludeChanSwIe = false;
+ psessionEntry->dfsIncludeChanWrapperIe = false;
+
+ pChanSwTxResponse = (tSirSmeCSAIeTxCompleteRsp *)
+ cdf_mem_malloc(length);
+
+ if (NULL == pChanSwTxResponse) {
+ lim_log(pMac, LOGP,
+ FL
+ ("AllocateMemory failed for tSirSmeCSAIeTxCompleteRsp"));
+ return;
+ }
+
+ cdf_mem_set((void *)pChanSwTxResponse, length, 0);
+ pChanSwTxResponse->sessionId =
+ psessionEntry->smeSessionId;
+ pChanSwTxResponse->chanSwIeTxStatus =
+ CDF_STATUS_SUCCESS;
+
+ mmhMsg.type = eWNI_SME_DFS_CSAIE_TX_COMPLETE_IND;
+ mmhMsg.bodyptr = pChanSwTxResponse;
+ mmhMsg.bodyval = 0;
+ lim_sys_process_mmh_msg_api(pMac, &mmhMsg, ePROT);
+ }
+ }
+
+ if (LIM_IS_AP_ROLE(psessionEntry) &&
+ psessionEntry->gLimOperatingMode.present) {
+ /* Done with nss update, send response back to SME */
+ psessionEntry->gLimOperatingMode.present = 0;
+ beacon_tx_comp_rsp_ptr = (struct sir_beacon_tx_complete_rsp *)
+ cdf_mem_malloc(sizeof(*beacon_tx_comp_rsp_ptr));
+ if (NULL == beacon_tx_comp_rsp_ptr) {
+ lim_log(pMac, LOGP,
+ FL
+ ("AllocateMemory failed for beacon_tx_comp_rsp_ptr"));
+ return;
+ }
+ cdf_mem_set((void *)beacon_tx_comp_rsp_ptr,
+ sizeof(*beacon_tx_comp_rsp_ptr), 0);
+ beacon_tx_comp_rsp_ptr->session_id =
+ psessionEntry->smeSessionId;
+ beacon_tx_comp_rsp_ptr->tx_status = CDF_STATUS_SUCCESS;
+ mmhMsg.type = eWNI_SME_NSS_UPDATE_RSP;
+ mmhMsg.bodyptr = beacon_tx_comp_rsp_ptr;
+ mmhMsg.bodyval = 0;
+ lim_sys_process_mmh_msg_api(pMac, &mmhMsg, ePROT);
+ }
+ return;
+}
diff --git a/core/mac/src/pe/lim/lim_send_sme_rsp_messages.h b/core/mac/src/pe/lim/lim_send_sme_rsp_messages.h
new file mode 100644
index 0000000..e707481
--- /dev/null
+++ b/core/mac/src/pe/lim/lim_send_sme_rsp_messages.h
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2012-2014 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_send_sme_rsp_messages.h contains the definitions for
+ * sending SME response/notification messages to applications above
+ * MAC software.
+ * Author: Chandra Modumudi
+ * Date: 02/11/02
+ * History:-
+ * Date Modified by Modification Information
+ * --------------------------------------------------------------------
+ *
+ */
+#ifndef __LIM_SEND_SME_RSP_H
+#define __LIM_SEND_SME_RSP_H
+
+#include "sir_common.h"
+#include "sir_api.h"
+#include "sir_mac_prot_def.h"
+
+/* Functions for sending responses to Host */
+void lim_send_sme_rsp(tpAniSirGlobal, uint16_t, tSirResultCodes, uint8_t,
+ uint16_t);
+void lim_send_sme_roc_rsp(tpAniSirGlobal mac_ctx, uint16_t msg_type,
+ tSirResultCodes result_code, uint8_t sme_session_id,
+ uint32_t scan_id);
+void lim_send_sme_start_bss_rsp(tpAniSirGlobal, uint16_t, tSirResultCodes,
+ tpPESession, uint8_t, uint16_t);
+void lim_send_sme_scan_rsp(tpAniSirGlobal, tSirResultCodes, uint8_t,
+ uint16_t, uint32_t scan_id);
+void lim_post_sme_scan_rsp_message(tpAniSirGlobal, tSirResultCodes,
+ uint8_t, uint16_t, uint32_t scan_id);
+
+void lim_send_sme_join_reassoc_rsp(tpAniSirGlobal, uint16_t, tSirResultCodes,
+ uint16_t, tpPESession, uint8_t, uint16_t);
+void lim_send_sme_disassoc_ntf(tpAniSirGlobal, tSirMacAddr, tSirResultCodes,
+ uint16_t, uint16_t, uint8_t, uint16_t, tpPESession);
+void lim_send_sme_deauth_ntf(tpAniSirGlobal, tSirMacAddr, tSirResultCodes, uint16_t,
+ uint16_t, uint8_t, uint16_t);
+void lim_send_sme_disassoc_ind(tpAniSirGlobal, tpDphHashNode, tpPESession);
+void lim_send_sme_deauth_ind(tpAniSirGlobal, tpDphHashNode,
+ tpPESession psessionEntry);
+void lim_send_sme_wm_status_change_ntf(tpAniSirGlobal, tSirSmeStatusChangeCode,
+ uint32_t *, uint16_t, uint8_t);
+void lim_send_sme_set_context_rsp(tpAniSirGlobal, tSirMacAddr, uint16_t,
+ tSirResultCodes, tpPESession, uint8_t, uint16_t);
+void lim_send_sme_neighbor_bss_ind(tpAniSirGlobal, tLimScanResultNode *);
+void lim_handle_delete_bss_rsp(tpAniSirGlobal pMac, tpSirMsgQ MsgQ);
+void lim_handle_csa_offload_msg(tpAniSirGlobal mac_ctx, tpSirMsgQ msg);
+
+#ifdef WLAN_FEATURE_VOWIFI_11R
+void
+lim_send_sme_aggr_qos_rsp(tpAniSirGlobal pMac, tpSirAggrQosRsp aggrQosRsp,
+ uint8_t smesessionId);
+#endif /*WLAN_FEATURE_VOWIFI_11R */
+
+void lim_send_sme_addts_rsp(tpAniSirGlobal pMac, uint8_t rspReqd, uint32_t status,
+ tpPESession psessionEntry, tSirMacTspecIE tspec,
+ uint8_t smesessionId, uint16_t smetransactionId);
+void lim_send_sme_delts_rsp(tpAniSirGlobal pMac, tpSirDeltsReq delts,
+ uint32_t status, tpPESession psessionEntry,
+ uint8_t smessionId, uint16_t smetransactionId);
+void lim_send_sme_delts_ind(tpAniSirGlobal pMac, tpSirDeltsReqInfo delts,
+ uint16_t aid, tpPESession);
+void lim_send_sme_stats_rsp(tpAniSirGlobal pMac, uint16_t msgtype, void *stats);
+
+void lim_send_sme_pe_statistics_rsp(tpAniSirGlobal pMac, uint16_t msgtype,
+ void *stats);
+#ifdef FEATURE_WLAN_ESE_UPLOAD
+void lim_send_sme_pe_ese_tsm_rsp(tpAniSirGlobal pMac, tAniGetTsmStatsRsp *pStats);
+#endif
+
+void lim_send_sme_ibss_peer_ind(tpAniSirGlobal pMac, tSirMacAddr peerMacAddr,
+ uint16_t staIndex, uint8_t ucastIdx,
+ uint8_t bcastIdx, uint8_t *beacon,
+ uint16_t beaconLen, uint16_t msgType,
+ uint8_t sessionId);
+#ifdef FEATURE_OEM_DATA_SUPPORT
+void lim_send_sme_oem_data_rsp(tpAniSirGlobal pMac, uint32_t *pMsgBuf,
+ tSirResultCodes resultCode);
+#endif
+
+void lim_send_sme_max_assoc_exceeded_ntf(tpAniSirGlobal pMac, tSirMacAddr peerMacAddr,
+ uint8_t smesessionId);
+#ifdef FEATURE_WLAN_TDLS
+void lim_send_sme_tdls_link_establish_req_rsp(tpAniSirGlobal pMac, uint8_t sessionId,
+ tSirMacAddr peerMac,
+ tDphHashNode *pStaDs, uint8_t status);
+void lim_send_sme_tdls_event_notify(tpAniSirGlobal pMac, uint16_t msgType,
+ void *events);
+#endif
+
+void lim_send_sme_dfs_event_notify(tpAniSirGlobal pMac, uint16_t msgType,
+ void *event);
+void lim_send_sme_ap_channel_switch_resp(tpAniSirGlobal pMac,
+ tpPESession psessionEntry,
+ tpSwitchChannelParams pChnlParams);
+void
+lim_process_beacon_tx_success_ind(tpAniSirGlobal pMac, uint16_t msgType,
+ void *event);
+
+typedef enum {
+ lim_csa_ie_present = 0x00000001,
+ lim_xcsa_ie_present = 0x00000002,
+ lim_wbw_ie_present = 0x00000004,
+ lim_cswarp_ie_present = 0x00000008,
+} lim_csa_event_ies_present_flag;
+
+#endif /* __LIM_SEND_SME_RSP_H */
diff --git a/core/mac/src/pe/lim/lim_ser_des_utils.c b/core/mac/src/pe/lim/lim_ser_des_utils.c
new file mode 100644
index 0000000..bd778f5
--- /dev/null
+++ b/core/mac/src/pe/lim/lim_ser_des_utils.c
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2011-2015 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_ser_des_utils.cc contains the serializer/deserializer
+ * utility functions LIM uses while communicating with upper layer
+ * software entities
+ * Author: Chandra Modumudi
+ * Date: 10/20/02
+ * History:-
+ * Date Modified by Modification Information
+ * --------------------------------------------------------------------
+ */
+
+#include "ani_system_defs.h"
+#include "utils_api.h"
+#include "lim_types.h"
+#include "lim_utils.h"
+#include "lim_ser_des_utils.h"
+
+/**---------------------------------------------------------------
+ \fn lim_get_session_info
+ \brief This function returns the sessionId and transactionId
+ \ of a message. This assumes that the message structure
+ \ is of format:
+ \ uint16_t messageType
+ \ uint16_t messageLength
+ \ uint8_t sessionId
+ \ uint16_t transactionId
+ \param pMac - pMac global structure
+ \param *pBuf - pointer to the message buffer
+ \param sessionId - returned session id value
+ \param transactionId - returned transaction ID value
+ \return None
+ ------------------------------------------------------------------*/
+void
+lim_get_session_info(tpAniSirGlobal pMac, uint8_t *pBuf, uint8_t *sessionId,
+ uint16_t *transactionId)
+{
+ if (!pBuf) {
+ lim_log(pMac, LOGE, FL("NULL ptr received. "));
+ return;
+ }
+
+ pBuf += sizeof(uint16_t); /* skip message type */
+ pBuf += sizeof(uint16_t); /* skip message length */
+
+ *sessionId = *pBuf; /* get sessionId */
+ pBuf++;
+ *transactionId = lim_get_u16(pBuf); /* get transactionId */
+
+ return;
+}
diff --git a/core/mac/src/pe/lim/lim_ser_des_utils.h b/core/mac/src/pe/lim/lim_ser_des_utils.h
new file mode 100644
index 0000000..f05f4dd
--- /dev/null
+++ b/core/mac/src/pe/lim/lim_ser_des_utils.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2011-2015 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_ser_des_utils.h contains the utility definitions
+ * LIM uses while processing messages from upper layer software
+ * modules
+ * Author: Chandra Modumudi
+ * Date: 10/20/02
+ * History:-
+ * Date Modified by Modification Information
+ * --------------------------------------------------------------------
+ */
+#ifndef __LIM_SERDES_UTILS_H
+#define __LIM_SERDES_UTILS_H
+
+#include "sir_api.h"
+#include "ani_system_defs.h"
+#include "sir_mac_prot_def.h"
+#include "utils_api.h"
+#include "lim_types.h"
+#include "lim_prop_exts_utils.h"
+
+void lim_get_session_info(tpAniSirGlobal pMac, uint8_t *,
+ uint8_t *, uint16_t *);
+
+/* Byte String <--> uint16_t/uint32_t copy functions */
+static inline void lim_copy_u16(uint8_t *ptr, uint16_t u16Val)
+{
+#if ((defined(ANI_OS_TYPE_QNX) && defined(ANI_LITTLE_BYTE_ENDIAN)) || \
+ (defined(ANI_OS_TYPE_ANDROID) && defined(ANI_LITTLE_BYTE_ENDIAN)))
+ *ptr++ = (uint8_t) (u16Val & 0xff);
+ *ptr = (uint8_t) ((u16Val >> 8) & 0xff);
+#else
+#error "Unknown combination of OS Type and endianess"
+#endif
+}
+
+static inline uint16_t lim_get_u16(uint8_t *ptr)
+{
+#if ((defined(ANI_OS_TYPE_QNX) && defined(ANI_LITTLE_BYTE_ENDIAN)) || \
+ (defined(ANI_OS_TYPE_ANDROID) && defined(ANI_LITTLE_BYTE_ENDIAN)))
+ return ((uint16_t) (*(ptr + 1) << 8)) | ((uint16_t) (*ptr));
+#else
+#error "Unknown combination of OS Type and endianess"
+#endif
+}
+
+static inline void lim_copy_u32(uint8_t *ptr, uint32_t u32Val)
+{
+#if ((defined(ANI_OS_TYPE_QNX) && defined(ANI_LITTLE_BYTE_ENDIAN)) || \
+ (defined(ANI_OS_TYPE_ANDROID) && defined(ANI_LITTLE_BYTE_ENDIAN)))
+ *ptr++ = (uint8_t) (u32Val & 0xff);
+ *ptr++ = (uint8_t) ((u32Val >> 8) & 0xff);
+ *ptr++ = (uint8_t) ((u32Val >> 16) & 0xff);
+ *ptr = (uint8_t) ((u32Val >> 24) & 0xff);
+#else
+#error "Unknown combination of OS Type and endianess"
+#endif
+}
+
+static inline uint32_t lim_get_u32(uint8_t *ptr)
+{
+#if ((defined(ANI_OS_TYPE_QNX) && defined(ANI_LITTLE_BYTE_ENDIAN)) || \
+ (defined(ANI_OS_TYPE_ANDROID) && defined(ANI_LITTLE_BYTE_ENDIAN)))
+ return ((*(ptr + 3) << 24) |
+ (*(ptr + 2) << 16) | (*(ptr + 1) << 8) | (*(ptr)));
+#else
+#error "Unknown combination of OS Type and endianess"
+#endif
+}
+
+#endif /* __LIM_SERDES_UTILS_H */
diff --git a/core/mac/src/pe/lim/lim_session.c b/core/mac/src/pe/lim/lim_session.c
new file mode 100644
index 0000000..6c73b4c
--- /dev/null
+++ b/core/mac/src/pe/lim/lim_session.c
@@ -0,0 +1,767 @@
+/*
+ * Copyright (c) 2011-2015 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.
+ */
+
+/**=========================================================================
+
+ \file lim_session.c
+
+ \brief implementation for lim Session related APIs
+
+ \author Sunit Bhatia
+
+ ========================================================================*/
+
+/*--------------------------------------------------------------------------
+ Include Files
+ ------------------------------------------------------------------------*/
+#include "ani_global.h"
+#include "lim_debug.h"
+#ifdef WLAN_FEATURE_VOWIFI_11R
+#include "lim_ft_defs.h"
+#include "lim_ft.h"
+#endif
+#include "lim_session.h"
+#include "lim_utils.h"
+
+#include "sch_api.h"
+#include "lim_send_messages.h"
+
+/*--------------------------------------------------------------------------
+
+ \brief pe_init_beacon_params() - Initialize the beaconParams structure
+
+ \param tpPESession - pointer to the session context or NULL if session can not be created.
+ \return void
+ \sa
+
+ --------------------------------------------------------------------------*/
+
+void pe_init_beacon_params(tpAniSirGlobal pMac, tpPESession psessionEntry)
+{
+ psessionEntry->beaconParams.beaconInterval = 0;
+ psessionEntry->beaconParams.fShortPreamble = 0;
+ psessionEntry->beaconParams.llaCoexist = 0;
+ psessionEntry->beaconParams.llbCoexist = 0;
+ psessionEntry->beaconParams.llgCoexist = 0;
+ psessionEntry->beaconParams.ht20Coexist = 0;
+ psessionEntry->beaconParams.llnNonGFCoexist = 0;
+ psessionEntry->beaconParams.fRIFSMode = 0;
+ psessionEntry->beaconParams.fLsigTXOPProtectionFullSupport = 0;
+ psessionEntry->beaconParams.gHTObssMode = 0;
+
+ /* Number of legacy STAs associated */
+ cdf_mem_set((void *)&psessionEntry->gLim11bParams,
+ sizeof(tLimProtStaParams), 0);
+ cdf_mem_set((void *)&psessionEntry->gLim11aParams,
+ sizeof(tLimProtStaParams), 0);
+ cdf_mem_set((void *)&psessionEntry->gLim11gParams,
+ sizeof(tLimProtStaParams), 0);
+ cdf_mem_set((void *)&psessionEntry->gLimNonGfParams,
+ sizeof(tLimProtStaParams), 0);
+ cdf_mem_set((void *)&psessionEntry->gLimHt20Params,
+ sizeof(tLimProtStaParams), 0);
+ cdf_mem_set((void *)&psessionEntry->gLimLsigTxopParams,
+ sizeof(tLimProtStaParams), 0);
+ cdf_mem_set((void *)&psessionEntry->gLimOlbcParams,
+ sizeof(tLimProtStaParams), 0);
+}
+
+/*
+ * pe_reset_protection_callback() - resets protection structs so that when an AP
+ * causing use of protection goes away, corresponding protection bit can be
+ * reset
+ * @ptr: pointer to pSessionEntry
+ *
+ * This function resets protection structs so that when an AP causing use of
+ * protection goes away, corresponding protection bit can be reset. This allowes
+ * protection bits to be reset once legacy overlapping APs are gone.
+ *
+ * Return: void
+ */
+void pe_reset_protection_callback(void *ptr)
+{
+ tpPESession pe_session_entry = (tpPESession)ptr;
+ tpAniSirGlobal mac_ctx = (tpAniSirGlobal)pe_session_entry->mac_ctx;
+ int8_t i = 0;
+ tUpdateBeaconParams beacon_params;
+ uint16_t current_protection_state = 0;
+ tpDphHashNode station_hash_node = NULL;
+ tSirMacHTOperatingMode old_op_mode;
+ bool bcn_prms_changed = false;
+
+ if (pe_session_entry->valid == false) {
+ CDF_TRACE(CDF_MODULE_ID_PE,
+ CDF_TRACE_LEVEL_ERROR,
+ FL("session already deleted. exiting timer callback"));
+ return;
+ }
+
+ current_protection_state |=
+ pe_session_entry->gLimOverlap11gParams.protectionEnabled |
+ pe_session_entry->gLimOverlap11aParams.protectionEnabled << 1 |
+ pe_session_entry->gLimOverlapHt20Params.protectionEnabled << 2 |
+ pe_session_entry->gLimOverlapNonGfParams.protectionEnabled << 3 |
+ pe_session_entry->gLimOlbcParams.protectionEnabled << 4;
+
+ CDF_TRACE(CDF_MODULE_ID_PE,
+ CDF_TRACE_LEVEL_INFO,
+ FL("old protection state: 0x%04X, new protection state: 0x%04X\n"),
+ pe_session_entry->old_protection_state,
+ current_protection_state);
+
+ cdf_mem_zero(&pe_session_entry->gLimOverlap11gParams,
+ sizeof(pe_session_entry->gLimOverlap11gParams));
+ cdf_mem_zero(&pe_session_entry->gLimOverlap11aParams,
+ sizeof(pe_session_entry->gLimOverlap11aParams));
+ cdf_mem_zero(&pe_session_entry->gLimOverlapHt20Params,
+ sizeof(pe_session_entry->gLimOverlapHt20Params));
+ cdf_mem_zero(&pe_session_entry->gLimOverlapNonGfParams,
+ sizeof(pe_session_entry->gLimOverlapNonGfParams));
+
+ cdf_mem_zero(&pe_session_entry->gLimOlbcParams,
+ sizeof(pe_session_entry->gLimOlbcParams));
+
+ cdf_mem_zero(&pe_session_entry->beaconParams,
+ sizeof(pe_session_entry->beaconParams));
+
+ cdf_mem_zero(&mac_ctx->lim.gLimOverlap11gParams,
+ sizeof(mac_ctx->lim.gLimOverlap11gParams));
+ cdf_mem_zero(&mac_ctx->lim.gLimOverlap11aParams,
+ sizeof(mac_ctx->lim.gLimOverlap11aParams));
+ cdf_mem_zero(&mac_ctx->lim.gLimOverlapHt20Params,
+ sizeof(mac_ctx->lim.gLimOverlapHt20Params));
+ cdf_mem_zero(&mac_ctx->lim.gLimOverlapNonGfParams,
+ sizeof(mac_ctx->lim.gLimOverlapNonGfParams));
+
+ old_op_mode = pe_session_entry->htOperMode;
+ pe_session_entry->htOperMode = eSIR_HT_OP_MODE_PURE;
+
+ cdf_mem_zero(&beacon_params, sizeof(tUpdateBeaconParams));
+ /* index 0, is self node, peers start from 1 */
+ for (i = 1 ; i <= mac_ctx->lim.gLimAssocStaLimit ; i++)
+ {
+ station_hash_node = dph_get_hash_entry(mac_ctx, i,
+ &pe_session_entry->dph.dphHashTable);
+ if (NULL == station_hash_node)
+ continue;
+ lim_decide_ap_protection(mac_ctx, station_hash_node->staAddr,
+ &beacon_params, pe_session_entry);
+ }
+
+ if (pe_session_entry->htOperMode != old_op_mode)
+ bcn_prms_changed = true;
+
+ if ((current_protection_state !=
+ pe_session_entry->old_protection_state) &&
+ (false == mac_ctx->sap.SapDfsInfo.is_dfs_cac_timer_running)) {
+ CDF_TRACE(CDF_MODULE_ID_PE,
+ CDF_TRACE_LEVEL_ERROR,
+ FL("protection changed, update beacon template\n"));
+ /* update beacon fix params and send update to FW */
+ cdf_mem_zero(&beacon_params, sizeof(tUpdateBeaconParams));
+ beacon_params.bssIdx = pe_session_entry->bssIdx;
+ beacon_params.fShortPreamble =
+ pe_session_entry->beaconParams.fShortPreamble;
+ beacon_params.beaconInterval =
+ pe_session_entry->beaconParams.beaconInterval;
+ beacon_params.llaCoexist =
+ pe_session_entry->beaconParams.llaCoexist;
+ beacon_params.llbCoexist =
+ pe_session_entry->beaconParams.llbCoexist;
+ beacon_params.llgCoexist =
+ pe_session_entry->beaconParams.llgCoexist;
+ beacon_params.ht20MhzCoexist =
+ pe_session_entry->beaconParams.ht20Coexist;
+ beacon_params.llnNonGFCoexist =
+ pe_session_entry->beaconParams.llnNonGFCoexist;
+ beacon_params.fLsigTXOPProtectionFullSupport =
+ pe_session_entry->beaconParams.
+ fLsigTXOPProtectionFullSupport;
+ beacon_params.fRIFSMode =
+ pe_session_entry->beaconParams.fRIFSMode;
+ beacon_params.smeSessionId =
+ pe_session_entry->smeSessionId;
+ bcn_prms_changed = true;
+ }
+
+ if (bcn_prms_changed) {
+ sch_set_fixed_beacon_fields(mac_ctx, pe_session_entry);
+ lim_send_beacon_params(mac_ctx, &beacon_params, pe_session_entry);
+ }
+
+ pe_session_entry->old_protection_state = current_protection_state;
+ if (cdf_mc_timer_start(&pe_session_entry->
+ protection_fields_reset_timer,
+ SCH_PROTECTION_RESET_TIME)
+ != CDF_STATUS_SUCCESS) {
+ CDF_TRACE(CDF_MODULE_ID_PE,
+ CDF_TRACE_LEVEL_ERROR,
+ FL("cannot create or start protectionFieldsResetTimer\n"));
+ }
+}
+
+/**
+ * pe_create_session() creates a new PE session given the BSSID
+ * @param pMac: pointer to global adapter context
+ * @param bssid: BSSID of the new session
+ * @param sessionId: session ID is returned here, if session is created.
+ * @param bssType: station or a
+ *
+ * This function returns the session context and the session ID if the session
+ * corresponding to the passed BSSID is found in the PE session table.
+ *
+ * Return: tpPESession: pointer to the session context or NULL if session
+ * can not be created.
+ */
+
+tpPESession
+pe_create_session(tpAniSirGlobal pMac, uint8_t *bssid, uint8_t *sessionId,
+ uint16_t numSta, tSirBssType bssType)
+{
+ CDF_STATUS status;
+ uint8_t i;
+ tpPESession session_ptr;
+ for (i = 0; i < pMac->lim.maxBssId; i++) {
+ /* Find first free room in session table */
+ if (pMac->lim.gpSession[i].valid == true)
+ continue;
+ break;
+ }
+
+ if (i == pMac->lim.maxBssId) {
+ lim_log(pMac, LOGE,
+ FL("Session can't be created. Reached max sessions\n"));
+ return NULL;
+ }
+
+ session_ptr = &pMac->lim.gpSession[i];
+ cdf_mem_set((void *)session_ptr, sizeof(tPESession), 0);
+ /* Allocate space for Station Table for this session. */
+ session_ptr->dph.dphHashTable.pHashTable =
+ cdf_mem_malloc(sizeof(tpDphHashNode) * (numSta + 1));
+ if (NULL == session_ptr->dph.dphHashTable.pHashTable) {
+ lim_log(pMac, LOGE, FL("memory allocate failed!"));
+ return NULL;
+ }
+
+ session_ptr->dph.dphHashTable.pDphNodeArray =
+ cdf_mem_malloc(sizeof(tDphHashNode) * (numSta + 1));
+ if (NULL == session_ptr->dph.dphHashTable.pDphNodeArray) {
+ lim_log(pMac, LOGE, FL("memory allocate failed!"));
+ cdf_mem_free(session_ptr->dph.dphHashTable.pHashTable);
+ session_ptr->dph.dphHashTable.
+ pHashTable = NULL;
+ return NULL;
+ }
+
+ session_ptr->dph.dphHashTable.size = numSta + 1;
+ dph_hash_table_class_init(pMac, &session_ptr->dph.dphHashTable);
+ session_ptr->gpLimPeerIdxpool = cdf_mem_malloc(
+ sizeof(*(session_ptr->gpLimPeerIdxpool)) * (numSta + 1));
+ if (NULL == session_ptr->gpLimPeerIdxpool) {
+ lim_log(pMac, LOGE, FL("memory allocate failed!"));
+ cdf_mem_free(session_ptr->dph.dphHashTable.pHashTable);
+ cdf_mem_free(session_ptr->dph.dphHashTable.pDphNodeArray);
+ session_ptr->dph.dphHashTable.pHashTable = NULL;
+ session_ptr->dph.dphHashTable.pDphNodeArray = NULL;
+ return NULL;
+ }
+ cdf_mem_set(session_ptr->gpLimPeerIdxpool,
+ sizeof(*session_ptr->gpLimPeerIdxpool) * (numSta + 1),
+ 0);
+ session_ptr->freePeerIdxHead = 0;
+ session_ptr->freePeerIdxTail = 0;
+ session_ptr->gLimNumOfCurrentSTAs = 0;
+ /* Copy the BSSID to the session table */
+ sir_copy_mac_addr(session_ptr->bssId, bssid);
+ session_ptr->valid = true;
+ /* Intialize the SME and MLM states to IDLE */
+ session_ptr->limMlmState = eLIM_MLM_IDLE_STATE;
+ session_ptr->limSmeState = eLIM_SME_IDLE_STATE;
+ session_ptr->limCurrentAuthType = eSIR_OPEN_SYSTEM;
+ pe_init_beacon_params(pMac, &pMac->lim.gpSession[i]);
+#ifdef WLAN_FEATURE_VOWIFI_11R
+ session_ptr->is11Rconnection = false;
+#endif
+#ifdef FEATURE_WLAN_ESE
+ session_ptr->isESEconnection = false;
+#endif
+#if defined WLAN_FEATURE_VOWIFI_11R || defined FEATURE_WLAN_ESE || defined(FEATURE_WLAN_LFR)
+ session_ptr->isFastTransitionEnabled = false;
+#endif
+#ifdef FEATURE_WLAN_LFR
+ session_ptr->isFastRoamIniFeatureEnabled = false;
+#endif
+ *sessionId = i;
+ session_ptr->gLimPhyMode = WNI_CFG_PHY_MODE_11G;
+ /* Initialize CB mode variables when session is created */
+ session_ptr->htSupportedChannelWidthSet = 0;
+ session_ptr->htRecommendedTxWidthSet = 0;
+ session_ptr->htSecondaryChannelOffset = 0;
+#ifdef FEATURE_WLAN_TDLS
+ cdf_mem_set(session_ptr->peerAIDBitmap,
+ sizeof(session_ptr->peerAIDBitmap), 0);
+ session_ptr->tdls_prohibited = false;
+ session_ptr->tdls_chan_swit_prohibited = false;
+#endif
+ session_ptr->fWaitForProbeRsp = 0;
+ session_ptr->fIgnoreCapsChange = 0;
+
+ CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_DEBUG,
+ FL("Create a new PE session(%d), BSSID: "MAC_ADDRESS_STR" Max No. of STA %d"),
+ session_ptr->peSessionId, MAC_ADDR_ARRAY(bssid), numSta);
+
+ if (eSIR_INFRA_AP_MODE == bssType
+ || eSIR_IBSS_MODE == bssType
+ || eSIR_BTAMP_AP_MODE == bssType) {
+ session_ptr->pSchProbeRspTemplate =
+ cdf_mem_malloc(SCH_MAX_PROBE_RESP_SIZE);
+ session_ptr->pSchBeaconFrameBegin =
+ cdf_mem_malloc(SCH_MAX_BEACON_SIZE);
+ session_ptr->pSchBeaconFrameEnd =
+ cdf_mem_malloc(SCH_MAX_BEACON_SIZE);
+ if ((NULL == session_ptr->pSchProbeRspTemplate)
+ || (NULL == session_ptr->pSchBeaconFrameBegin)
+ || (NULL == session_ptr->pSchBeaconFrameEnd)) {
+ lim_log(pMac, LOGE, FL("memory allocate failed!"));
+ cdf_mem_free(session_ptr->dph.dphHashTable.pHashTable);
+ cdf_mem_free(session_ptr->dph.dphHashTable.pDphNodeArray);
+ cdf_mem_free(session_ptr->gpLimPeerIdxpool);
+ cdf_mem_free(session_ptr->pSchProbeRspTemplate);
+ cdf_mem_free(session_ptr->pSchBeaconFrameBegin);
+ cdf_mem_free(session_ptr->pSchBeaconFrameEnd);
+
+ session_ptr->dph.dphHashTable.pHashTable = NULL;
+ session_ptr->dph.dphHashTable.pDphNodeArray = NULL;
+ session_ptr->gpLimPeerIdxpool = NULL;
+ session_ptr->pSchProbeRspTemplate = NULL;
+ session_ptr->pSchBeaconFrameBegin = NULL;
+ session_ptr->pSchBeaconFrameEnd = NULL;
+ return NULL;
+ }
+ }
+#if defined WLAN_FEATURE_VOWIFI_11R
+ if (eSIR_INFRASTRUCTURE_MODE == bssType)
+ lim_ft_open(pMac, &pMac->lim.gpSession[i]);
+#endif
+ if (eSIR_INFRA_AP_MODE == bssType) {
+ session_ptr->old_protection_state = 0;
+ session_ptr->mac_ctx = (void *)pMac;
+ status = cdf_mc_timer_init(
+ &session_ptr->protection_fields_reset_timer,
+ CDF_TIMER_TYPE_SW, pe_reset_protection_callback,
+ (void *)&pMac->lim.gpSession[i]);
+ if (status == CDF_STATUS_SUCCESS) {
+ status = cdf_mc_timer_start(
+ &session_ptr->protection_fields_reset_timer,
+ SCH_PROTECTION_RESET_TIME);
+ }
+ if (status != CDF_STATUS_SUCCESS)
+ CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_ERROR,
+ FL("cannot create or start protectionFieldsResetTimer\n"));
+ }
+ return &pMac->lim.gpSession[i];
+}
+
+/*--------------------------------------------------------------------------
+ \brief pe_find_session_by_bssid() - looks up the PE session given the BSSID.
+
+ This function returns the session context and the session ID if the session
+ corresponding to the given BSSID is found in the PE session table.
+
+ \param pMac - pointer to global adapter context
+ \param bssid - BSSID of the session
+ \param sessionId -session ID is returned here, if session is found.
+
+ \return tpPESession - pointer to the session context or NULL if session is not found.
+
+ \sa
+ --------------------------------------------------------------------------*/
+tpPESession pe_find_session_by_bssid(tpAniSirGlobal pMac, uint8_t *bssid,
+ uint8_t *sessionId)
+{
+ uint8_t i;
+
+ for (i = 0; i < pMac->lim.maxBssId; i++) {
+ /* If BSSID matches return corresponding tables address */
+ if ((pMac->lim.gpSession[i].valid)
+ && (sir_compare_mac_addr(pMac->lim.gpSession[i].bssId, bssid)))
+ {
+ *sessionId = i;
+ return (&pMac->lim.gpSession[i]);
+ }
+ }
+
+ lim_log(pMac, LOG4, FL("Session lookup fails for BSSID: \n "));
+ lim_print_mac_addr(pMac, bssid, LOG4);
+ return (NULL);
+
+}
+
+/*--------------------------------------------------------------------------
+ \brief pe_find_session_by_bss_idx() - looks up the PE session given the bssIdx.
+
+ This function returns the session context if the session
+ corresponding to the given bssIdx is found in the PE session table.
+ \param pMac - pointer to global adapter context
+ \param bssIdx - bss index of the session
+ \return tpPESession - pointer to the session context or NULL if session is not found.
+ \sa
+ --------------------------------------------------------------------------*/
+tpPESession pe_find_session_by_bss_idx(tpAniSirGlobal pMac, uint8_t bssIdx)
+{
+ uint8_t i;
+ for (i = 0; i < pMac->lim.maxBssId; i++) {
+ /* If BSSID matches return corresponding tables address */
+ if ((pMac->lim.gpSession[i].valid)
+ && (pMac->lim.gpSession[i].bssIdx == bssIdx)) {
+ return &pMac->lim.gpSession[i];
+ }
+ }
+ lim_log(pMac, LOG4, FL("Session lookup fails for bssIdx: %d"), bssIdx);
+ return NULL;
+}
+
+/*--------------------------------------------------------------------------
+ \brief pe_find_session_by_session_id() - looks up the PE session given the session ID.
+
+ This function returns the session context if the session
+ corresponding to the given session ID is found in the PE session table.
+
+ \param pMac - pointer to global adapter context
+ \param sessionId -session ID for which session context needs to be looked up.
+
+ \return tpPESession - pointer to the session context or NULL if session is not found.
+
+ \sa
+ --------------------------------------------------------------------------*/
+tpPESession pe_find_session_by_session_id(tpAniSirGlobal pMac, uint8_t sessionId)
+{
+ if (sessionId >= pMac->lim.maxBssId) {
+ lim_log(pMac, LOGE, FL("Invalid sessionId: %d \n "), sessionId);
+ return (NULL);
+ }
+ if ((pMac->lim.gpSession[sessionId].valid == true)) {
+ return (&pMac->lim.gpSession[sessionId]);
+ }
+ return (NULL);
+
+}
+
+/**
+ * pe_find_session_by_sta_id() - looks up the PE session given staid.
+ * @mac_ctx: pointer to global adapter context
+ * @staid: StaId of the session
+ * @session_id: session ID is returned here, if session is found.
+ *
+ * This function returns the session context and the session ID if the session
+ * corresponding to the given StaId is found in the PE session table.
+ *
+ * Return: session pointer
+ */
+tpPESession
+pe_find_session_by_sta_id(tpAniSirGlobal mac_ctx,
+ uint8_t staid,
+ uint8_t *session_id)
+{
+ uint8_t i, j;
+ tpPESession session_ptr;
+ dphHashTableClass *dph_ptr;
+
+ for (i = 0; i < mac_ctx->lim.maxBssId; i++) {
+ if (!mac_ctx->lim.gpSession[i].valid)
+ continue;
+ session_ptr = &mac_ctx->lim.gpSession[i];
+ dph_ptr = &session_ptr->dph.dphHashTable;
+ for (j = 0; j < dph_ptr->size; j++) {
+ if (dph_ptr->pDphNodeArray[j].valid
+ && dph_ptr->pDphNodeArray[j].added
+ && staid == dph_ptr->pDphNodeArray[j].staIndex) {
+ *session_id = i;
+ return session_ptr;
+ }
+ }
+ }
+
+ lim_log(mac_ctx, LOG4,
+ FL("Session lookup fails for StaId: %d\n "), staid);
+ return NULL;
+}
+
+/**
+ * pe_delete_session() - deletes the PE session given the session ID.
+ * @mac_ctx: pointer to global adapter context
+ * @session: session to be deleted.
+ *
+ * Deletes the given PE session
+ *
+ * Return: void
+ */
+void pe_delete_session(tpAniSirGlobal mac_ctx, tpPESession session)
+{
+ uint16_t i = 0;
+ uint16_t n;
+ TX_TIMER *timer_ptr;
+
+ CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_DEBUG,
+ FL("Trying to delete PE session %d Opmode %d BssIdx %d BSSID: "MAC_ADDRESS_STR),
+ session->peSessionId, session->operMode,
+ session->bssIdx,
+ MAC_ADDR_ARRAY(session->bssId));
+ for (n = 0; n < (mac_ctx->lim.maxStation + 1); n++) {
+ timer_ptr = &mac_ctx->lim.limTimers.gpLimCnfWaitTimer[n];
+ if (session->peSessionId == timer_ptr->sessionId)
+ if (true == tx_timer_running(timer_ptr))
+ tx_timer_deactivate(timer_ptr);
+ }
+
+#if defined (WLAN_FEATURE_VOWIFI_11R)
+ /* Delete FT related information */
+ lim_ft_cleanup(mac_ctx, session);
+#endif
+ if (session->pLimStartBssReq != NULL) {
+ cdf_mem_free(session->pLimStartBssReq);
+ session->pLimStartBssReq = NULL;
+ }
+
+ if (session->pLimJoinReq != NULL) {
+ cdf_mem_free(session->pLimJoinReq);
+ session->pLimJoinReq = NULL;
+ }
+
+ if (session->pLimReAssocReq != NULL) {
+ cdf_mem_free(session->pLimReAssocReq);
+ session->pLimReAssocReq = NULL;
+ }
+
+ if (session->pLimMlmJoinReq != NULL) {
+ cdf_mem_free(session->pLimMlmJoinReq);
+ session->pLimMlmJoinReq = NULL;
+ }
+
+ if (session->dph.dphHashTable.pHashTable != NULL) {
+ cdf_mem_free(session->dph.dphHashTable.pHashTable);
+ session->dph.dphHashTable.pHashTable = NULL;
+ }
+
+ if (session->dph.dphHashTable.pDphNodeArray != NULL) {
+ cdf_mem_free(session->dph.dphHashTable.pDphNodeArray);
+ session->dph.dphHashTable.pDphNodeArray = NULL;
+ }
+
+ if (session->gpLimPeerIdxpool != NULL) {
+ cdf_mem_free(session->gpLimPeerIdxpool);
+ session->gpLimPeerIdxpool = NULL;
+ }
+
+ if (session->beacon != NULL) {
+ cdf_mem_free(session->beacon);
+ session->beacon = NULL;
+ }
+
+ if (session->assocReq != NULL) {
+ cdf_mem_free(session->assocReq);
+ session->assocReq = NULL;
+ }
+
+ if (session->assocRsp != NULL) {
+ cdf_mem_free(session->assocRsp);
+ session->assocRsp = NULL;
+ }
+
+ if (session->parsedAssocReq != NULL) {
+ tpSirAssocReq tmp_ptr = NULL;
+ /* Cleanup the individual allocation first */
+ for (i = 0; i < session->dph.dphHashTable.size; i++) {
+ if (session->parsedAssocReq[i] == NULL)
+ continue;
+ tmp_ptr = ((tpSirAssocReq)
+ (session->parsedAssocReq[i]));
+ if (tmp_ptr->assocReqFrame) {
+ cdf_mem_free(tmp_ptr->assocReqFrame);
+ tmp_ptr->assocReqFrame = NULL;
+ tmp_ptr->assocReqFrameLength = 0;
+ }
+ cdf_mem_free(session->parsedAssocReq[i]);
+ session->parsedAssocReq[i] = NULL;
+ }
+ /* Cleanup the whole block */
+ cdf_mem_free(session->parsedAssocReq);
+ session->parsedAssocReq = NULL;
+ }
+ if (NULL != session->limAssocResponseData) {
+ cdf_mem_free(session->limAssocResponseData);
+ session->limAssocResponseData = NULL;
+ }
+#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
+ if (NULL != session->pLimMlmReassocRetryReq) {
+ cdf_mem_free(session->pLimMlmReassocRetryReq);
+ session->pLimMlmReassocRetryReq = NULL;
+ }
+#endif
+ if (NULL != session->pLimMlmReassocReq) {
+ cdf_mem_free(session->pLimMlmReassocReq);
+ session->pLimMlmReassocReq = NULL;
+ }
+
+ if (NULL != session->pSchProbeRspTemplate) {
+ cdf_mem_free(session->pSchProbeRspTemplate);
+ session->pSchProbeRspTemplate = NULL;
+ }
+
+ if (NULL != session->pSchBeaconFrameBegin) {
+ cdf_mem_free(session->pSchBeaconFrameBegin);
+ session->pSchBeaconFrameBegin = NULL;
+ }
+
+ if (NULL != session->pSchBeaconFrameEnd) {
+ cdf_mem_free(session->pSchBeaconFrameEnd);
+ session->pSchBeaconFrameEnd = NULL;
+ }
+
+ /* Must free the buffer before peSession invalid */
+ if (NULL != session->addIeParams.probeRespData_buff) {
+ cdf_mem_free(session->addIeParams.probeRespData_buff);
+ session->addIeParams.probeRespData_buff = NULL;
+ session->addIeParams.probeRespDataLen = 0;
+ }
+ if (NULL != session->addIeParams.assocRespData_buff) {
+ cdf_mem_free(session->addIeParams.assocRespData_buff);
+ session->addIeParams.assocRespData_buff = NULL;
+ session->addIeParams.assocRespDataLen = 0;
+ }
+ if (NULL != session->addIeParams.probeRespBCNData_buff) {
+ cdf_mem_free(session->addIeParams.probeRespBCNData_buff);
+ session->addIeParams.probeRespBCNData_buff = NULL;
+ session->addIeParams.probeRespBCNDataLen = 0;
+ }
+#ifdef WLAN_FEATURE_11W
+ /* if PMF connection */
+ if (session->limRmfEnabled)
+ cdf_mc_timer_destroy(&session->pmfComebackTimer);
+#endif
+
+ if (LIM_IS_AP_ROLE(session)) {
+ cdf_mc_timer_stop(&session->protection_fields_reset_timer);
+ cdf_mc_timer_destroy(&session->protection_fields_reset_timer);
+ }
+
+ session->valid = false;
+
+ if (LIM_IS_AP_ROLE(session))
+ lim_check_and_reset_protection_params(mac_ctx);
+
+ return;
+}
+
+/*--------------------------------------------------------------------------
+ \brief pe_find_session_by_peer_sta() - looks up the PE session given the Station Address.
+
+ This function returns the session context and the session ID if the session
+ corresponding to the given station address is found in the PE session table.
+
+ \param pMac - pointer to global adapter context
+ \param sa - Peer STA Address of the session
+ \param sessionId -session ID is returned here, if session is found.
+
+ \return tpPESession - pointer to the session context or NULL if session is not found.
+
+ \sa
+ --------------------------------------------------------------------------*/
+
+tpPESession pe_find_session_by_peer_sta(tpAniSirGlobal pMac, uint8_t *sa,
+ uint8_t *sessionId)
+{
+ uint8_t i;
+ tpDphHashNode pSta;
+ uint16_t aid;
+
+ for (i = 0; i < pMac->lim.maxBssId; i++) {
+ if ((pMac->lim.gpSession[i].valid)) {
+ pSta =
+ dph_lookup_hash_entry(pMac, sa, &aid,
+ &pMac->lim.gpSession[i].dph.
+ dphHashTable);
+ if (pSta != NULL) {
+ *sessionId = i;
+ return &pMac->lim.gpSession[i];
+ }
+ }
+ }
+
+ lim_log(pMac, LOG1, FL("Session lookup fails for Peer StaId: \n "));
+ lim_print_mac_addr(pMac, sa, LOG1);
+ return NULL;
+}
+
+/**
+ * pe_find_session_by_sme_session_id() - looks up the PE session for given sme
+ * session id
+ * @mac_ctx: pointer to global adapter context
+ * @sme_session_id: sme session id
+ *
+ * looks up the PE session for given sme session id
+ *
+ * Return: pe session entry for given sme session if found else NULL
+ */
+tpPESession pe_find_session_by_sme_session_id(tpAniSirGlobal mac_ctx,
+ uint8_t sme_session_id)
+{
+ uint8_t i;
+ for (i = 0; i < mac_ctx->lim.maxBssId; i++) {
+ if ((mac_ctx->lim.gpSession[i].valid) &&
+ (mac_ctx->lim.gpSession[i].smeSessionId ==
+ sme_session_id)) {
+ return &mac_ctx->lim.gpSession[i];
+ }
+ }
+ lim_log(mac_ctx, LOG4,
+ FL("Session lookup fails for smeSessionID: %d"),
+ sme_session_id);
+ return NULL;
+}
+
+/**
+ * pe_get_active_session_count() - function to return active pe session count
+ *
+ * @mac_ctx: pointer to global mac structure
+ *
+ * returns number of active pe session count
+ *
+ * Return: 0 if there are no active sessions else return number of active
+ * sessions
+ */
+uint8_t pe_get_active_session_count(tpAniSirGlobal mac_ctx)
+{
+ uint8_t i, active_session_count = 0;
+
+ for (i = 0; i < mac_ctx->lim.maxBssId; i++)
+ if (mac_ctx->lim.gpSession[i].valid)
+ active_session_count++;
+
+ return active_session_count;
+}
diff --git a/core/mac/src/pe/lim/lim_session_utils.c b/core/mac/src/pe/lim/lim_session_utils.c
new file mode 100644
index 0000000..49b37a1
--- /dev/null
+++ b/core/mac/src/pe/lim/lim_session_utils.c
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2011-2015 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.
+ */
+
+/**=========================================================================
+
+ \file lim_session_utils.c
+ \brief implementation for lim Session Utility APIs
+ \author Sunit Bhatia
+ ========================================================================*/
+
+/*--------------------------------------------------------------------------
+ Include Files
+ ------------------------------------------------------------------------*/
+#include "ani_global.h"
+#include "lim_debug.h"
+#ifdef WLAN_FEATURE_VOWIFI_11R
+#include "lim_ft_defs.h"
+#endif
+#include "lim_session.h"
+#include "lim_session_utils.h"
+#include "lim_utils.h"
+
+/**
+ * is_lim_session_off_channel() - checks if any other off channel session exists
+ * @mac_ctx: Global MAC context.
+ * @sessionId: PE session ID.
+ *
+ * Return: This function returns true if the session Id passed needs to be on
+ * a different channel than atleast one session already active.
+ **/
+uint8_t is_lim_session_off_channel(tpAniSirGlobal mac_ctx, uint8_t session_id)
+{
+ uint8_t i;
+
+ if (session_id >= mac_ctx->lim.maxBssId) {
+ lim_log(mac_ctx, LOGE, FL("Invalid session_id:%d"), session_id);
+ return false;
+ }
+
+ for (i = 0; i < mac_ctx->lim.maxBssId; i++) {
+ /* Skip the session_id that is to be joined. */
+ if (i == session_id)
+ continue;
+ /*
+ * if another session is valid and it is on different channel
+ * then it is an off channel operation.
+ */
+ if ((mac_ctx->lim.gpSession[i].valid) &&
+ (mac_ctx->lim.gpSession[i].currentOperChannel !=
+ mac_ctx->lim.gpSession[session_id].currentOperChannel))
+ return true;
+ }
+ return false;
+
+}
+
+/**
+ * lim_is_chan_switch_running() - check if channel switch is happening
+ * @mac_ctx: Global MAC context.
+ *
+ * Return: 1 - if channel switch is happening on any session.
+ * 0 - if channel switch is not happening.
+ **/
+uint8_t lim_is_chan_switch_running(tpAniSirGlobal mac_ctx)
+{
+ uint8_t i;
+
+ for (i = 0; i < mac_ctx->lim.maxBssId; i++)
+ if (mac_ctx->lim.gpSession[i].valid &&
+ mac_ctx->lim.gpSession[i].gLimSpecMgmt.dot11hChanSwState
+ == eLIM_11H_CHANSW_RUNNING)
+ return 1;
+ return 0;
+}
+
+/**
+ * lim_is_in_mcc() - check if device is in MCC
+ * @mac_ctx: Global MAC context.
+ *
+ * Return: true - if in MCC.
+ * false - Not in MCC
+ **/
+uint8_t lim_is_in_mcc(tpAniSirGlobal mac_ctx)
+{
+ uint8_t i;
+ uint8_t chan = 0;
+ uint8_t curr_oper_channel = 0;
+
+ for (i = 0; i < mac_ctx->lim.maxBssId; i++) {
+ /*
+ * if another session is valid and it is on different channel
+ * it is an off channel operation.
+ */
+ if ((mac_ctx->lim.gpSession[i].valid)) {
+ curr_oper_channel =
+ mac_ctx->lim.gpSession[i].currentOperChannel;
+ if (chan == 0)
+ chan = curr_oper_channel;
+ else if (chan != curr_oper_channel)
+ return true;
+ }
+ }
+ return false;
+}
+
+/**
+ * pe_get_current_stas_count() - Total stations associated on all sessions.
+ * @mac_ctx: Global MAC context.
+ *
+ * Return: true - Number of stations active on all sessions.
+ **/
+uint8_t pe_get_current_stas_count(tpAniSirGlobal mac_ctx)
+{
+ uint8_t i;
+ uint8_t stacount = 0;
+ for (i = 0; i < mac_ctx->lim.maxBssId; i++)
+ if (mac_ctx->lim.gpSession[i].valid == true)
+ stacount +=
+ mac_ctx->lim.gpSession[i].gLimNumOfCurrentSTAs;
+ return stacount;
+}
diff --git a/core/mac/src/pe/lim/lim_session_utils.h b/core/mac/src/pe/lim/lim_session_utils.h
new file mode 100644
index 0000000..d1dd7d1
--- /dev/null
+++ b/core/mac/src/pe/lim/lim_session_utils.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2012-2015 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.
+ */
+
+#if !defined(__LIM_SESSION_UTILS_H)
+#define __LIM_SESSION_UTILS_H
+
+uint8_t is_lim_session_off_channel(tpAniSirGlobal pMac, uint8_t sessionId);
+uint8_t lim_is_chan_switch_running(tpAniSirGlobal pMac);
+uint8_t lim_is_in_mcc(tpAniSirGlobal pMac);
+uint8_t pe_get_current_stas_count(tpAniSirGlobal pMac);
+
+#endif /* #if !defined( __LIM_SESSION_UTILS_H ) */
diff --git a/core/mac/src/pe/lim/lim_sme_req_utils.c b/core/mac/src/pe/lim/lim_sme_req_utils.c
new file mode 100644
index 0000000..550231f
--- /dev/null
+++ b/core/mac/src/pe/lim/lim_sme_req_utils.c
@@ -0,0 +1,925 @@
+/*
+ * Copyright (c) 2011-2015 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_sme_req_utils.cc contains the utility functions
+ * for processing SME request messages.
+ * Author: Chandra Modumudi
+ * Date: 02/11/02
+ * History:-
+ * Date Modified by Modification Information
+ * --------------------------------------------------------------------
+ * 05/26/10 js WPA handling in (Re)Assoc frames
+ *
+ */
+
+#include "wni_api.h"
+#include "wni_cfg.h"
+#include "cfg_api.h"
+#include "sir_api.h"
+#include "sch_api.h"
+#include "utils_api.h"
+#include "lim_types.h"
+#include "lim_utils.h"
+#include "lim_assoc_utils.h"
+#include "lim_security_utils.h"
+#include "lim_ser_des_utils.h"
+
+/**
+ * lim_is_rs_nie_valid_in_sme_req_message()
+ *
+ * @mac_ctx Pointer to Global MAC structure
+ * @rsn_ie Pointer to received RSN IE
+ *
+ * This function is called to verify if the RSN IE received in various SME_REQ
+ * messages is valid or not
+ *
+ * Return: true when RSN IE is valid, false otherwise
+ *
+ */
+
+static uint8_t
+lim_is_rsn_ie_valid_in_sme_req_message(tpAniSirGlobal mac_ctx, tpSirRSNie rsn_ie)
+{
+ uint8_t start = 0;
+ uint32_t privacy, val;
+ int len;
+
+ if (wlan_cfg_get_int(mac_ctx, WNI_CFG_PRIVACY_ENABLED,
+ &privacy) != eSIR_SUCCESS) {
+ lim_log(mac_ctx, LOGP, FL("Unable to retrieve POI from CFG"));
+ }
+
+ if (wlan_cfg_get_int(mac_ctx, WNI_CFG_RSN_ENABLED, &val)
+ != eSIR_SUCCESS) {
+ lim_log(mac_ctx, LOGP,
+ FL("Unable to retrieve RSN_ENABLED from CFG"));
+ }
+
+ if (rsn_ie->length && (!privacy || !val)) {
+ /* Privacy & RSN not enabled in CFG.
+ * In order to allow mixed mode for Guest access
+ * allow BSS creation/join with no Privacy capability
+ * yet advertising WPA IE
+ */
+ PELOG1(lim_log(mac_ctx, LOG1,
+ FL("RSN ie len %d PRIVACY %d RSN %d"),
+ rsn_ie->length, privacy, val);)
+ }
+
+ if (!rsn_ie->length)
+ return true;
+
+ if ((rsn_ie->rsnIEdata[0] != DOT11F_EID_RSN)
+#ifdef FEATURE_WLAN_WAPI
+ && (rsn_ie->rsnIEdata[0] != DOT11F_EID_WAPI)
+#endif
+ && (rsn_ie->rsnIEdata[0] != DOT11F_EID_WPA)) {
+ lim_log(mac_ctx, LOGE, FL("RSN/WPA/WAPI EID %d not [%d || %d]"),
+ rsn_ie->rsnIEdata[0], DOT11F_EID_RSN,
+ DOT11F_EID_WPA);
+ return false;
+ }
+
+ len = rsn_ie->length;
+ start = 0;
+ while (len > 0) {
+ switch (rsn_ie->rsnIEdata[start]) {
+ case DOT11F_EID_RSN:
+ /* Check validity of RSN IE */
+ if ((rsn_ie->rsnIEdata[start + 1] >
+ DOT11F_IE_RSN_MAX_LEN)
+ || (rsn_ie->rsnIEdata[start + 1] <
+ DOT11F_IE_RSN_MIN_LEN)) {
+ lim_log(mac_ctx, LOGE,
+ FL("RSN IE len %d not [%d,%d]"),
+ rsn_ie->rsnIEdata[start + 1],
+ DOT11F_IE_RSN_MIN_LEN,
+ DOT11F_IE_RSN_MAX_LEN);
+ return false;
+ }
+ break;
+ case DOT11F_EID_WPA:
+ /* Check validity of WPA IE */
+ if (SIR_MAC_MAX_IE_LENGTH <= start)
+ break;
+
+ if (start <= (SIR_MAC_MAX_IE_LENGTH - sizeof(uint32_t)))
+ val = sir_read_u32((uint8_t *) &
+ rsn_ie->rsnIEdata[start + 2]);
+
+ if ((rsn_ie->rsnIEdata[start + 1] <
+ DOT11F_IE_WPA_MIN_LEN)
+ || (rsn_ie->rsnIEdata[start + 1] >
+ DOT11F_IE_WPA_MAX_LEN)
+ || (SIR_MAC_WPA_OUI != val)) {
+ lim_log(mac_ctx, LOGE,
+ FL("WPA IE len %d not [%d,%d] OR data 0x%x not 0x%x"),
+ rsn_ie->rsnIEdata[start + 1],
+ DOT11F_IE_WPA_MIN_LEN,
+ DOT11F_IE_WPA_MAX_LEN,
+ val, SIR_MAC_WPA_OUI);
+ return false;
+ }
+ break;
+#ifdef FEATURE_WLAN_WAPI
+ case DOT11F_EID_WAPI:
+ if ((rsn_ie->rsnIEdata[start + 1] >
+ DOT11F_IE_WAPI_MAX_LEN)
+ || (rsn_ie->rsnIEdata[start + 1] <
+ DOT11F_IE_WAPI_MIN_LEN)) {
+ lim_log(mac_ctx, LOGE,
+ FL("WAPI IE len %d not [%d,%d]"),
+ rsn_ie->rsnIEdata[start + 1],
+ DOT11F_IE_WAPI_MIN_LEN,
+ DOT11F_IE_WAPI_MAX_LEN);
+ return false;
+ }
+ break;
+#endif
+ default:
+ /* we will never be here, simply for completeness */
+ return false;
+ } /* end of switch */
+ /* EID + length field + length */
+ start += 2 + rsn_ie->rsnIEdata[start + 1];
+ len -= start;
+ } /* end while loop */
+ return true;
+} /*** end lim_is_rs_nie_valid_in_sme_req_message() ***/
+
+/**
+ * lim_is_addie_valid_in_sme_req_message()
+ *
+ ***FUNCTION:
+ * This function is called to verify if the Add IE
+ * received in various SME_REQ messages is valid or not
+ *
+ ***LOGIC:
+ * Add IE validity checks are performed on only length
+ *
+ ***ASSUMPTIONS:
+ *
+ ***NOTE:
+ *
+ * @param pMac Pointer to Global MAC structure
+ * @param pWSCie Pointer to received WSC IE
+ * @return true when WSC IE is valid, false otherwise
+ */
+
+static uint8_t
+lim_is_addie_valid_in_sme_req_message(tpAniSirGlobal pMac, tpSirAddie pAddie)
+{
+ int left = pAddie->length;
+ uint8_t *ptr = pAddie->addIEdata;
+ uint8_t elem_id, elem_len;
+
+ if (left == 0)
+ return true;
+
+ while (left >= 2) {
+ elem_id = ptr[0];
+ elem_len = ptr[1];
+ left -= 2;
+ if (elem_len > left) {
+ lim_log(pMac, LOGE,
+ FL
+ ("****Invalid Add IEs eid = %d elem_len=%d left=%d*****"),
+ elem_id, elem_len, left);
+ return false;
+ }
+
+ left -= elem_len;
+ ptr += (elem_len + 2);
+ }
+ /* there shouldn't be any left byte */
+
+ return true;
+} /*** end lim_is_addie_valid_in_sme_req_message() ***/
+
+/**
+ * lim_set_rs_nie_wp_aiefrom_sme_start_bss_req_message() - to set rsnie/wpaie
+ *
+ * @mac_ctx : Pointer to Global MAC structure
+ * @rsn_ie : Pointer to received RSN IE
+ * @session : Pointer to pe session
+ *
+ * This function is called to verify if the RSN IE received in various
+ * SME_REQ messages is valid or not. RSN IE validity checks are performed in
+ * this function
+ *
+ * Return: true when RSN IE is valid, false otherwise
+ */
+uint8_t
+lim_set_rs_nie_wp_aiefrom_sme_start_bss_req_message(tpAniSirGlobal mac_ctx,
+ tpSirRSNie rsn_ie,
+ tpPESession session)
+{
+ uint8_t wpa_idx = 0;
+ uint32_t privacy, val;
+
+ if (wlan_cfg_get_int(mac_ctx, WNI_CFG_PRIVACY_ENABLED,
+ &privacy) != eSIR_SUCCESS)
+ lim_log(mac_ctx, LOGP, FL("Unable to retrieve POI from CFG"));
+
+ if (wlan_cfg_get_int(mac_ctx, WNI_CFG_RSN_ENABLED,
+ &val) != eSIR_SUCCESS)
+ lim_log(mac_ctx, LOGP,
+ FL("Unable to retrieve RSN_ENABLED from CFG"));
+
+ if (rsn_ie->length && (!privacy || !val)) {
+ /*
+ * Privacy & RSN not enabled in CFG.
+ * In order to allow mixed mode for Guest access
+ * allow BSS creation/join with no Privacy capability
+ * yet advertising WPA IE
+ */
+ lim_log(mac_ctx, LOG1,
+ FL("RSN ie len %d but PRIVACY %d RSN %d"),
+ rsn_ie->length, privacy, val);
+ }
+
+ if (!rsn_ie->length)
+ return true;
+
+ if ((rsn_ie->rsnIEdata[0] != SIR_MAC_RSN_EID) &&
+ (rsn_ie->rsnIEdata[0] != SIR_MAC_WPA_EID)) {
+ lim_log(mac_ctx, LOGE, FL("RSN/WPA EID %d not [%d || %d]"),
+ rsn_ie->rsnIEdata[0], SIR_MAC_RSN_EID,
+ SIR_MAC_WPA_EID);
+ return false;
+ }
+ /* Check validity of RSN IE */
+ if ((rsn_ie->rsnIEdata[0] == SIR_MAC_RSN_EID) &&
+ (rsn_ie->rsnIEdata[1] < SIR_MAC_RSN_IE_MIN_LENGTH)) {
+ lim_log(mac_ctx, LOGE, FL("RSN IE len %d not [%d,%d]"),
+ rsn_ie->rsnIEdata[1], SIR_MAC_RSN_IE_MIN_LENGTH,
+ SIR_MAC_RSN_IE_MAX_LENGTH);
+ return false;
+ }
+
+ if (rsn_ie->length > rsn_ie->rsnIEdata[1] + 2) {
+ if (rsn_ie->rsnIEdata[0] != SIR_MAC_RSN_EID) {
+ lim_log(mac_ctx, LOGE,
+ FL("First byte[%d] in rsnIEdata isn't RSN_EID"),
+ rsn_ie->rsnIEdata[1]);
+ return false;
+ }
+ lim_log(mac_ctx, LOG1,
+ FL("WPA IE is present along with WPA2 IE"));
+ wpa_idx = 2 + rsn_ie->rsnIEdata[1];
+ } else if ((rsn_ie->length == rsn_ie->rsnIEdata[1] + 2) &&
+ (rsn_ie->rsnIEdata[0] == SIR_MAC_RSN_EID)) {
+ lim_log(mac_ctx, LOG1, FL("Only RSN IE is present"));
+ dot11f_unpack_ie_rsn(mac_ctx, &rsn_ie->rsnIEdata[2],
+ (uint8_t) rsn_ie->length,
+ &session->gStartBssRSNIe);
+ } else if ((rsn_ie->length == rsn_ie->rsnIEdata[1] + 2)
+ && (rsn_ie->rsnIEdata[0] == SIR_MAC_WPA_EID)) {
+ lim_log(mac_ctx, LOG1, FL("Only WPA IE is present"));
+ dot11f_unpack_ie_wpa(mac_ctx, &rsn_ie->rsnIEdata[6],
+ (uint8_t) rsn_ie->length - 4,
+ &session->gStartBssWPAIe);
+ }
+ /* Check validity of WPA IE */
+ if (wpa_idx + 6 >= SIR_MAC_MAX_IE_LENGTH)
+ return false;
+
+ val = sir_read_u32((uint8_t *)&rsn_ie->rsnIEdata[wpa_idx + 2]);
+ if ((rsn_ie->rsnIEdata[wpa_idx] == SIR_MAC_WPA_EID)
+ && ((rsn_ie->rsnIEdata[wpa_idx + 1] < SIR_MAC_WPA_IE_MIN_LENGTH)
+ || (SIR_MAC_WPA_OUI != val))) {
+ lim_log(mac_ctx, LOGE,
+ FL("WPA IE len %d not [%d,%d] OR data 0x%x not 0x%x"),
+ rsn_ie->rsnIEdata[1],
+ SIR_MAC_RSN_IE_MIN_LENGTH,
+ SIR_MAC_RSN_IE_MAX_LENGTH, val,
+ SIR_MAC_WPA_OUI);
+ return false;
+ } else {
+ /* Both RSN and WPA IEs are present */
+ dot11f_unpack_ie_rsn(mac_ctx, &rsn_ie->rsnIEdata[2],
+ (uint8_t) rsn_ie->length,
+ &session->gStartBssRSNIe);
+ dot11f_unpack_ie_wpa(mac_ctx, &rsn_ie->rsnIEdata[wpa_idx + 6],
+ rsn_ie->rsnIEdata[wpa_idx + 1] - 4,
+ &session->gStartBssWPAIe);
+ }
+ return true;
+}
+
+/**
+ * lim_is_bss_descr_valid_in_sme_req_message()
+ *
+ ***FUNCTION:
+ * This function is called to verify if the BSS Descr
+ * received in various SME_REQ messages is valid or not
+ *
+ ***LOGIC:
+ * BSS Descritipion validity checks are performed in this function
+ *
+ ***ASSUMPTIONS:
+ *
+ ***NOTE:
+ *
+ * @param pMac Pointer to Global MAC structure
+ * @param pBssDescr Pointer to received Bss Descritipion
+ * @return true when BSS description is valid, false otherwise
+ */
+
+static uint8_t
+lim_is_bss_descr_valid_in_sme_req_message(tpAniSirGlobal pMac,
+ tpSirBssDescription pBssDescr)
+{
+ uint8_t valid = true;
+
+ if (lim_is_addr_bc(pBssDescr->bssId) || !pBssDescr->channelId) {
+ valid = false;
+ goto end;
+ }
+
+end:
+ return valid;
+} /*** end lim_is_bss_descr_valid_in_sme_req_message() ***/
+
+/**
+ * lim_is_sme_start_bss_req_valid() - To validate sme start bss request
+ *
+ * @mac_ctx: Pointer to Global MAC structure
+ * @start_bss_req: Pointer to received SME_START_BSS_REQ message
+ *
+ * This function is called by lim_process_sme_req_messages() upon
+ * receiving SME_START_BSS_REQ message from application.
+ *
+ * Return: true when received SME_START_BSS_REQ is formatted correctly false
+ * otherwise
+ */
+
+uint8_t
+lim_is_sme_start_bss_req_valid(tpAniSirGlobal mac_ctx,
+ tpSirSmeStartBssReq start_bss_req)
+{
+ uint8_t i = 0;
+ tSirMacRateSet *opr_rates = &start_bss_req->operationalRateSet;
+
+ PELOG1(lim_log(mac_ctx, LOG1,
+ FL("Parsed START_BSS_REQ fields are bssType=%d, channelId=%d, SSID len=%d, rsnIE len=%d, nwType=%d, rateset len=%d"),
+ start_bss_req->bssType, start_bss_req->channelId,
+ start_bss_req->ssId.length, start_bss_req->rsnIE.length,
+ start_bss_req->nwType, opr_rates->numRates);)
+
+ switch (start_bss_req->bssType) {
+ case eSIR_INFRASTRUCTURE_MODE:
+ /**
+ * Should not have received start BSS req with bssType
+ * Infrastructure on STA.
+ */
+ lim_log(mac_ctx, LOGE,
+ FL("Invalid bssType %d in eWNI_SME_START_BSS_REQ"),
+ start_bss_req->bssType);
+ return false;
+ break;
+ case eSIR_IBSS_MODE:
+ break;
+ case eSIR_BTAMP_STA_MODE:
+ break;
+ case eSIR_BTAMP_AP_MODE:
+ break;
+ case eSIR_INFRA_AP_MODE:
+ break;
+ default:
+ /**
+ * Should not have received start BSS req with bssType
+ * other than Infrastructure/IBSS.
+ */
+ lim_log(mac_ctx, LOGW,
+ FL("Invalid bssType %d in eWNI_SME_START_BSS_REQ"),
+ start_bss_req->bssType);
+ return false;
+ }
+
+ if (start_bss_req->bssType == eSIR_IBSS_MODE
+ && (!start_bss_req->ssId.length
+ || start_bss_req->ssId.length > SIR_MAC_MAX_SSID_LENGTH)) {
+ lim_log(mac_ctx, LOGW,
+ FL("Invalid SSID length in eWNI_SME_START_BSS_REQ"));
+ return false;
+ }
+
+ if (!lim_is_rsn_ie_valid_in_sme_req_message(mac_ctx,
+ &start_bss_req->rsnIE))
+ return false;
+
+ if (start_bss_req->nwType != eSIR_11A_NW_TYPE
+ && start_bss_req->nwType != eSIR_11B_NW_TYPE
+ && start_bss_req->nwType != eSIR_11G_NW_TYPE)
+ return false;
+
+ if (start_bss_req->nwType == eSIR_11A_NW_TYPE) {
+ for (i = 0; i < opr_rates->numRates; i++) {
+ if (sirIsArate(opr_rates->rate[i] & 0x7F))
+ continue;
+
+ lim_log(mac_ctx, LOGW,
+ FL("Invalid operational 11A rates"));
+ sir_dump_buf(mac_ctx, SIR_LIM_MODULE_ID, LOG2,
+ opr_rates->rate, opr_rates->numRates);
+ return false;
+ }
+ return true;
+ }
+ /* check if all the rates in the opr rate set are legal 11G rates */
+ if (start_bss_req->nwType == eSIR_11G_NW_TYPE) {
+ for (i = 0; i < opr_rates->numRates; i++) {
+ if (sirIsGrate(opr_rates->rate[i] & 0x7F))
+ continue;
+
+ lim_log(mac_ctx, LOGW,
+ FL("Invalid operational 11G rates"));
+ sir_dump_buf(mac_ctx, SIR_LIM_MODULE_ID, LOG2,
+ opr_rates->rate, opr_rates->numRates);
+ return false;
+ }
+ return true;
+ }
+
+ for (i = 0; i < opr_rates->numRates; i++) {
+ if (sirIsBrate(opr_rates->rate[i] & 0x7F))
+ continue;
+
+ lim_log(mac_ctx, LOGW,
+ FL("Invalid operational 11B rates"));
+ sir_dump_buf(mac_ctx, SIR_LIM_MODULE_ID, LOG2,
+ opr_rates->rate, opr_rates->numRates);
+ return false;
+ }
+ return true;
+}
+
+/**
+ * lim_is_sme_join_req_valid()
+ *
+ ***FUNCTION:
+ * This function is called by lim_process_sme_req_messages() upon
+ * receiving SME_JOIN_REQ message from application.
+ *
+ ***LOGIC:
+ * Message validity checks are performed in this function
+ *
+ ***ASSUMPTIONS:
+ *
+ ***NOTE:
+ *
+ * @param pMac Pointer to Global MAC structure
+ * @param pJoinReq Pointer to received SME_JOIN_REQ message
+ * @return true when received SME_JOIN_REQ is formatted correctly
+ * false otherwise
+ */
+
+uint8_t lim_is_sme_join_req_valid(tpAniSirGlobal pMac, tpSirSmeJoinReq pJoinReq)
+{
+ uint8_t valid = true;
+
+ if (!lim_is_rsn_ie_valid_in_sme_req_message(pMac, &pJoinReq->rsnIE)) {
+ lim_log(pMac, LOGE,
+ FL("received SME_JOIN_REQ with invalid RSNIE"));
+ valid = false;
+ goto end;
+ }
+
+ if (!lim_is_addie_valid_in_sme_req_message(pMac, &pJoinReq->addIEScan)) {
+ lim_log(pMac, LOGE,
+ FL
+ ("received SME_JOIN_REQ with invalid additional IE for scan"));
+ valid = false;
+ goto end;
+ }
+
+ if (!lim_is_addie_valid_in_sme_req_message(pMac, &pJoinReq->addIEAssoc)) {
+ lim_log(pMac, LOGE,
+ FL
+ ("received SME_JOIN_REQ with invalid additional IE for assoc"));
+ valid = false;
+ goto end;
+ }
+
+ if (!lim_is_bss_descr_valid_in_sme_req_message(pMac, &pJoinReq->bssDescription)) {
+ /* / Received eWNI_SME_JOIN_REQ with invalid BSS Info */
+ /* Log the event */
+ lim_log(pMac, LOGE,
+ FL("received SME_JOIN_REQ with invalid bssInfo"));
+
+ valid = false;
+ goto end;
+ }
+
+ /*
+ Reject Join Req if the Self Mac Address and
+ the Ap's Mac Address is same
+ */
+ if (cdf_mem_compare((uint8_t *) pJoinReq->selfMacAddr,
+ (uint8_t *) pJoinReq->bssDescription.bssId,
+ (uint8_t) (sizeof(tSirMacAddr)))) {
+ /* Log the event */
+ lim_log(pMac, LOGE,
+ FL
+ ("received SME_JOIN_REQ with Self Mac and BSSID Same"));
+
+ valid = false;
+ goto end;
+ }
+
+end:
+ return valid;
+} /*** end lim_is_sme_join_req_valid() ***/
+
+/**
+ * lim_is_sme_disassoc_req_valid()
+ *
+ ***FUNCTION:
+ * This function is called by lim_process_sme_req_messages() upon
+ * receiving SME_DISASSOC_REQ message from application.
+ *
+ ***LOGIC:
+ * Message validity checks are performed in this function
+ *
+ ***ASSUMPTIONS:
+ *
+ ***NOTE:
+ *
+ * @param pMac Pointer to Global MAC structure
+ * @param pDisassocReq Pointer to received SME_DISASSOC_REQ message
+ * @return true When received SME_DISASSOC_REQ is formatted
+ * correctly
+ * false otherwise
+ */
+
+uint8_t
+lim_is_sme_disassoc_req_valid(tpAniSirGlobal pMac,
+ tpSirSmeDisassocReq pDisassocReq,
+ tpPESession psessionEntry)
+{
+ if (lim_is_group_addr(pDisassocReq->peerMacAddr) &&
+ !lim_is_addr_bc(pDisassocReq->peerMacAddr))
+ return false;
+
+ return true;
+} /*** end lim_is_sme_disassoc_req_valid() ***/
+
+/**
+ * lim_is_sme_disassoc_cnf_valid()
+ *
+ ***FUNCTION:
+ * This function is called by lim_process_sme_req_messages() upon
+ * receiving SME_DISASSOC_CNF message from application.
+ *
+ ***LOGIC:
+ * Message validity checks are performed in this function
+ *
+ ***ASSUMPTIONS:
+ *
+ ***NOTE:
+ *
+ * @param pMac Pointer to Global MAC structure
+ * @param pDisassocCnf Pointer to received SME_DISASSOC_REQ message
+ * @return true When received SME_DISASSOC_CNF is formatted
+ * correctly
+ * false otherwise
+ */
+
+uint8_t
+lim_is_sme_disassoc_cnf_valid(tpAniSirGlobal pMac,
+ tpSirSmeDisassocCnf pDisassocCnf,
+ tpPESession psessionEntry)
+{
+ if (lim_is_group_addr(pDisassocCnf->peerMacAddr))
+ return false;
+
+ return true;
+} /*** end lim_is_sme_disassoc_cnf_valid() ***/
+
+/**
+ * lim_is_sme_deauth_req_valid()
+ *
+ ***FUNCTION:
+ * This function is called by lim_process_sme_req_messages() upon
+ * receiving SME_DEAUTH_REQ message from application.
+ *
+ ***LOGIC:
+ * Message validity checks are performed in this function
+ *
+ ***ASSUMPTIONS:
+ *
+ ***NOTE:
+ *
+ * @param pMac Pointer to Global MAC structure
+ * @param pDeauthReq Pointer to received SME_DEAUTH_REQ message
+ * @return true When received SME_DEAUTH_REQ is formatted correctly
+ * false otherwise
+ */
+
+uint8_t
+lim_is_sme_deauth_req_valid(tpAniSirGlobal pMac, tpSirSmeDeauthReq pDeauthReq,
+ tpPESession psessionEntry)
+{
+ if (lim_is_group_addr(pDeauthReq->peerMacAddr) &&
+ !lim_is_addr_bc(pDeauthReq->peerMacAddr))
+ return false;
+
+ return true;
+} /*** end lim_is_sme_deauth_req_valid() ***/
+
+/**
+ * lim_is_sme_scan_req_valid()
+ *
+ ***FUNCTION:
+ * This function is called by lim_process_sme_req_messages() upon
+ * receiving SME_SCAN_REQ message from application.
+ *
+ ***LOGIC:
+ * Message validity checks are performed in this function
+ *
+ ***ASSUMPTIONS:
+ *
+ ***NOTE:
+ *
+ * @param pScanReq Pointer to received SME_SCAN_REQ message
+ * @return true when received SME_SCAN_REQ is formatted correctly
+ * false otherwise
+ */
+
+uint8_t lim_is_sme_scan_req_valid(tpAniSirGlobal pMac, tpSirSmeScanReq pScanReq)
+{
+ uint8_t valid = true;
+ uint8_t i = 0;
+
+ if (pScanReq->numSsid > SIR_SCAN_MAX_NUM_SSID) {
+ valid = false;
+ lim_log(pMac, LOGE,
+ FL("Number of SSIDs > SIR_SCAN_MAX_NUM_SSID"));
+ goto end;
+ }
+
+ for (i = 0; i < pScanReq->numSsid; i++) {
+ if (pScanReq->ssId[i].length > SIR_MAC_MAX_SSID_LENGTH) {
+ lim_log(pMac, LOGE,
+ FL
+ ("Requested SSID length > SIR_MAC_MAX_SSID_LENGTH"));
+ valid = false;
+ goto end;
+ }
+ }
+ if ((pScanReq->bssType < 0) || (pScanReq->bssType > eSIR_AUTO_MODE)) {
+ lim_log(pMac, LOGE, FL("Invalid BSS Type"));
+ valid = false;
+ }
+ if (lim_is_group_addr(pScanReq->bssId) && !lim_is_addr_bc(pScanReq->bssId)) {
+ valid = false;
+ lim_log(pMac, LOGE,
+ FL("BSSID is group addr and is not Broadcast Addr"));
+ }
+ if (!
+ (pScanReq->scanType == eSIR_PASSIVE_SCAN
+ || pScanReq->scanType == eSIR_ACTIVE_SCAN)) {
+ valid = false;
+ lim_log(pMac, LOGE, FL("Invalid Scan Type"));
+ }
+ if (pScanReq->channelList.numChannels > SIR_MAX_NUM_CHANNELS) {
+ valid = false;
+ lim_log(pMac, LOGE,
+ FL("Number of Channels > SIR_MAX_NUM_CHANNELS"));
+ }
+
+ /*
+ ** check min/max channelTime range
+ **/
+ if (valid) {
+ if ((pScanReq->scanType == eSIR_ACTIVE_SCAN) &&
+ (pScanReq->maxChannelTime < pScanReq->minChannelTime)) {
+ lim_log(pMac, LOGE,
+ FL("Max Channel Time < Min Channel Time"));
+ valid = false;
+ goto end;
+ }
+ }
+
+end:
+ return valid;
+} /*** end lim_is_sme_scan_req_valid() ***/
+
+/**
+ * lim_is_sme_set_context_req_valid()
+ *
+ ***FUNCTION:
+ * This function is called by lim_process_sme_req_messages() upon
+ * receiving SME_SET_CONTEXT_REQ message from application.
+ *
+ ***LOGIC:
+ * Message validity checks are performed in this function
+ *
+ ***ASSUMPTIONS:
+ *
+ ***NOTE:
+ *
+ * @param pMsg - Pointer to received SME_SET_CONTEXT_REQ message
+ * @return true when received SME_SET_CONTEXT_REQ is formatted correctly
+ * false otherwise
+ */
+
+uint8_t
+lim_is_sme_set_context_req_valid(tpAniSirGlobal pMac,
+ tpSirSmeSetContextReq pSetContextReq)
+{
+ uint8_t i = 0;
+ uint8_t valid = true;
+ tpSirKeys pKey = pSetContextReq->keyMaterial.key;
+
+ if ((pSetContextReq->keyMaterial.edType != eSIR_ED_WEP40) &&
+ (pSetContextReq->keyMaterial.edType != eSIR_ED_WEP104) &&
+ (pSetContextReq->keyMaterial.edType != eSIR_ED_NONE) &&
+#ifdef FEATURE_WLAN_WAPI
+ (pSetContextReq->keyMaterial.edType != eSIR_ED_WPI) &&
+#endif
+ !pSetContextReq->keyMaterial.numKeys) {
+ /**
+ * No keys present in case of TKIP or CCMP
+ * Log error.
+ */
+ lim_log(pMac, LOGW,
+ FL
+ ("No keys present in SME_SETCONTEXT_REQ for edType=%d"),
+ pSetContextReq->keyMaterial.edType);
+
+ valid = false;
+ goto end;
+ }
+
+ if (pSetContextReq->keyMaterial.numKeys &&
+ (pSetContextReq->keyMaterial.edType == eSIR_ED_NONE)) {
+ /**
+ * Keys present in case of no ED policy
+ * Log error.
+ */
+ lim_log(pMac, LOGW,
+ FL("Keys present in SME_SETCONTEXT_REQ for edType=%d"),
+ pSetContextReq->keyMaterial.edType);
+
+ valid = false;
+ goto end;
+ }
+
+ if (pSetContextReq->keyMaterial.edType >= eSIR_ED_NOT_IMPLEMENTED) {
+ /**
+ * Invalid edType in the message
+ * Log error.
+ */
+ lim_log(pMac, LOGW,
+ FL("Invalid edType=%d in SME_SETCONTEXT_REQ"),
+ pSetContextReq->keyMaterial.edType);
+
+ valid = false;
+ goto end;
+ } else if (pSetContextReq->keyMaterial.edType > eSIR_ED_NONE) {
+ uint32_t poi;
+
+ if (wlan_cfg_get_int(pMac, WNI_CFG_PRIVACY_ENABLED,
+ &poi) != eSIR_SUCCESS) {
+ lim_log(pMac, LOGP,
+ FL("Unable to retrieve POI from CFG"));
+ }
+
+ if (!poi) {
+ /**
+ * Privacy is not enabled
+ * In order to allow mixed mode for Guest access
+ * allow BSS creation/join with no Privacy capability
+ * yet advertising WPA IE
+ */
+ PELOG1(lim_log(pMac, LOG1,
+ FL
+ ("Privacy is not enabled, yet non-None EDtype=%d in SME_SETCONTEXT_REQ"),
+ pSetContextReq->keyMaterial.edType);
+ )
+ }
+ }
+
+ for (i = 0; i < pSetContextReq->keyMaterial.numKeys; i++) {
+ if (((pSetContextReq->keyMaterial.edType == eSIR_ED_WEP40) &&
+ (pKey->keyLength != 5)) ||
+ ((pSetContextReq->keyMaterial.edType == eSIR_ED_WEP104) &&
+ (pKey->keyLength != 13)) ||
+ ((pSetContextReq->keyMaterial.edType == eSIR_ED_TKIP) &&
+ (pKey->keyLength != 32)) ||
+#ifdef FEATURE_WLAN_WAPI
+ ((pSetContextReq->keyMaterial.edType == eSIR_ED_WPI) &&
+ (pKey->keyLength != 32)) ||
+#endif
+ ((pSetContextReq->keyMaterial.edType == eSIR_ED_CCMP) &&
+ (pKey->keyLength != 16))) {
+ /**
+ * Invalid key length for a given ED type
+ * Log error.
+ */
+ lim_log(pMac, LOGW,
+ FL
+ ("Invalid keyLength =%d for edType=%d in SME_SETCONTEXT_REQ"),
+ pKey->keyLength,
+ pSetContextReq->keyMaterial.edType);
+
+ valid = false;
+ goto end;
+ }
+ pKey++;
+ }
+
+end:
+ return valid;
+} /*** end lim_is_sme_set_context_req_valid() ***/
+
+/**
+ * lim_is_sme_stop_bss_req_valid()
+ *
+ ***FUNCTION:
+ * This function is called by lim_process_sme_req_messages() upon
+ * receiving SME_STOP_BSS_REQ message from application.
+ *
+ ***LOGIC:
+ * Message validity checks are performed in this function
+ *
+ ***ASSUMPTIONS:
+ *
+ ***NOTE:
+ *
+ * @param pMsg - Pointer to received SME_STOP_BSS_REQ message
+ * @return true when received SME_STOP_BSS_REQ is formatted correctly
+ * false otherwise
+ */
+
+uint8_t lim_is_sme_stop_bss_req_valid(uint32_t *pMsg)
+{
+ uint8_t valid = true;
+
+ return valid;
+} /*** end lim_is_sme_stop_bss_req_valid() ***/
+
+/**
+ * lim_get_bss_id_from_sme_join_req_msg()
+ *
+ ***FUNCTION:
+ * This function is called in various places to get BSSID
+ * from BSS description/Neighbor BSS Info in the SME_JOIN_REQ/
+ * SME_REASSOC_REQ message.
+ *
+ ***PARAMS:
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ * NA
+ *
+ ***NOTE:
+ * NA
+ *
+ * @param pBuf - Pointer to received SME_JOIN/SME_REASSOC_REQ
+ * message
+ * @return pBssId - Pointer to BSSID
+ */
+
+uint8_t *lim_get_bss_id_from_sme_join_req_msg(uint8_t *pBuf)
+{
+ if (!pBuf)
+ return NULL;
+
+ pBuf += sizeof(uint32_t); /* skip message header */
+
+ pBuf += lim_get_u16(pBuf) + sizeof(uint16_t); /* skip RSN IE */
+
+ pBuf += sizeof(uint16_t); /* skip length of BSS description */
+
+ return (pBuf);
+} /*** end lim_get_bss_id_from_sme_join_req_msg() ***/
diff --git a/core/mac/src/pe/lim/lim_sme_req_utils.h b/core/mac/src/pe/lim/lim_sme_req_utils.h
new file mode 100644
index 0000000..7e89373
--- /dev/null
+++ b/core/mac/src/pe/lim/lim_sme_req_utils.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2011-2012,2014-2015 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_sme_req_utils.h contains the utility definitions
+ * LIM uses while processing SME request messsages.
+ * Author: Chandra Modumudi
+ * Date: 02/13/02
+ * History:-
+ * Date Modified by Modification Information
+ * --------------------------------------------------------------------
+ */
+#ifndef __LIM_SME_REQ_UTILS_H
+#define __LIM_SME_REQ_UTILS_H
+
+#include "sir_api.h"
+#include "lim_types.h"
+
+/* LIM SME request messages related utility functions */
+uint8_t lim_is_sme_start_bss_req_valid(tpAniSirGlobal, tpSirSmeStartBssReq);
+uint8_t lim_set_rs_nie_wp_aiefrom_sme_start_bss_req_message(tpAniSirGlobal,
+ tpSirRSNie, tpPESession);
+uint8_t lim_is_sme_scan_req_valid(tpAniSirGlobal, tpSirSmeScanReq);
+uint8_t lim_is_sme_join_req_valid(tpAniSirGlobal, tpSirSmeJoinReq);
+uint8_t lim_is_sme_disassoc_req_valid(tpAniSirGlobal, tpSirSmeDisassocReq,
+ tpPESession);
+uint8_t lim_is_sme_deauth_req_valid(tpAniSirGlobal, tpSirSmeDeauthReq, tpPESession);
+uint8_t lim_is_sme_set_context_req_valid(tpAniSirGlobal, tpSirSmeSetContextReq);
+uint8_t lim_is_sme_stop_bss_req_valid(uint32_t *);
+uint8_t *lim_get_bss_id_from_sme_join_req_msg(uint8_t *);
+uint8_t lim_is_sme_disassoc_cnf_valid(tpAniSirGlobal, tpSirSmeDisassocCnf,
+ tpPESession);
+
+#endif /* __LIM_SME_REQ_UTILS_H */
diff --git a/core/mac/src/pe/lim/lim_sta_hash_api.c b/core/mac/src/pe/lim/lim_sta_hash_api.c
new file mode 100644
index 0000000..794ebaa
--- /dev/null
+++ b/core/mac/src/pe/lim/lim_sta_hash_api.c
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2011-2012, 2014 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.
+ */
+
+/*
+ *
+ * lim_sta_hash_api.c: Provides access functions to get/set values of station hash entry fields.
+ * Author: Sunit Bhatia
+ * Date: 09/19/2006
+ * History:-
+ * Date Modified by Modification Information
+ *
+ * --------------------------------------------------------------------------
+ *
+ */
+
+#include "lim_sta_hash_api.h"
+
+/**
+ * lim_get_sta_hash_bssidx()
+ *
+ ***FUNCTION:
+ * This function is called to Get the Bss Index of the currently associated Station.
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ * NA
+ *
+ ***NOTE:
+ * NA
+ *
+ * @param pMac pointer to Global Mac structure.
+ * @param assocId AssocID of the Station.
+ * @param bssidx pointer to the bss index, which will be returned by the function.
+ *
+ * @return success if GET operation is ok, else Failure.
+ */
+
+tSirRetStatus lim_get_sta_hash_bssidx(tpAniSirGlobal pMac, uint16_t assocId,
+ uint8_t *bssidx, tpPESession psessionEntry)
+{
+ tpDphHashNode pSta =
+ dph_get_hash_entry(pMac, assocId, &psessionEntry->dph.dphHashTable);
+
+ if (pSta == NULL) {
+ PELOGE(lim_log(pMac, LOGE, FL("invalid STA %d"), assocId);)
+ return eSIR_LIM_INVALID_STA;
+ }
+
+ *bssidx = (uint8_t) pSta->bssId;
+ return eSIR_SUCCESS;
+}
diff --git a/core/mac/src/pe/lim/lim_sta_hash_api.h b/core/mac/src/pe/lim/lim_sta_hash_api.h
new file mode 100644
index 0000000..9a34091
--- /dev/null
+++ b/core/mac/src/pe/lim/lim_sta_hash_api.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2011-2012, 2014 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_sta_hash_api.h contains the
+ * function prototypes for accessing station hash entry fields.
+ *
+ * Author: Sunit Bhatia
+ * Date: 09/19/2006
+ * History:-
+ * Date Modified by Modification Information
+ * --------------------------------------------------------------------
+ *
+ */
+
+#ifndef __LIM_STA_HASH_API_H__
+#define __LIM_STA_HASH_API_H__
+
+#include "ani_global.h"
+#include "lim_types.h"
+
+tSirRetStatus lim_get_sta_hash_bssidx(tpAniSirGlobal pMac, uint16_t assocId,
+ uint8_t *bssidx, tpPESession psessionEntry);
+
+#endif
diff --git a/core/mac/src/pe/lim/lim_timer_utils.c b/core/mac/src/pe/lim/lim_timer_utils.c
new file mode 100644
index 0000000..f68f7b0
--- /dev/null
+++ b/core/mac/src/pe/lim/lim_timer_utils.c
@@ -0,0 +1,1357 @@
+/*
+ * Copyright (c) 2011-2015 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_timer_utils.cc contains the utility functions
+ * LIM uses for handling various timers.
+ * Author: Chandra Modumudi
+ * Date: 02/13/02
+ * History:-
+ * Date Modified by Modification Information
+ * --------------------------------------------------------------------
+ */
+
+#include "lim_types.h"
+#include "lim_utils.h"
+#include "lim_assoc_utils.h"
+#include "lim_security_utils.h"
+
+/* channel Switch Timer in ticks */
+#define LIM_CHANNEL_SWITCH_TIMER_TICKS 1
+/* Lim Quite timer in ticks */
+#define LIM_QUIET_TIMER_TICKS 100
+/* Lim Quite BSS timer interval in ticks */
+#define LIM_QUIET_BSS_TIMER_TICK 100
+/* Lim KeepAlive timer default (3000)ms */
+#define LIM_KEEPALIVE_TIMER_MS 3000
+/* Lim JoinProbeRequest Retry timer default (200)ms */
+#define LIM_JOIN_PROBE_REQ_TIMER_MS 200
+
+/* This timer is a periodic timer which expires at every 1 sec to
+ convert ACTIVE DFS channel to DFS channels */
+#define ACTIVE_TO_PASSIVE_CONVERISON_TIMEOUT 1000
+
+static bool
+lim_create_non_ap_timers(tpAniSirGlobal pMac)
+{
+ uint32_t cfgValue;
+ /* Create Channel Switch Timer */
+ if (tx_timer_create(&pMac->lim.limTimers.gLimChannelSwitchTimer,
+ "CHANNEL SWITCH TIMER",
+ lim_channel_switch_timer_handler, 0,
+ LIM_CHANNEL_SWITCH_TIMER_TICKS,
+ 0, TX_NO_ACTIVATE) != TX_SUCCESS) {
+ lim_log(pMac, LOGP, FL("failed to create Ch Switch timer"));
+ return false;
+ }
+ /* Create Quiet Timer
+ * This is used on the STA to go and shut-off Tx/Rx "after" the
+ * specified quiteInterval
+ */
+ if (tx_timer_create(&pMac->lim.limTimers.gLimQuietTimer,
+ "QUIET TIMER", lim_quiet_timer_handler,
+ SIR_LIM_QUIET_TIMEOUT, LIM_QUIET_TIMER_TICKS,
+ 0, TX_NO_ACTIVATE) != TX_SUCCESS) {
+ lim_log(pMac, LOGP, FL("failed to create Quiet Begin Timer"));
+ return false;
+ }
+ /* Create Quiet BSS Timer
+ * After the specified quiteInterval, determined by gLimQuietTimer, this
+ * timer, gLimQuietBssTimer, trigger and put the STA to sleep for the
+ * specified gLimQuietDuration
+ */
+ if (tx_timer_create(&pMac->lim.limTimers.gLimQuietBssTimer,
+ "QUIET BSS TIMER", lim_quiet_bss_timer_handler,
+ SIR_LIM_QUIET_BSS_TIMEOUT, LIM_QUIET_BSS_TIMER_TICK,
+ 0, TX_NO_ACTIVATE) != TX_SUCCESS) {
+ lim_log(pMac, LOGP, FL("failed to create Quiet Bss Timer"));
+ return false;
+ }
+
+ if (wlan_cfg_get_int(pMac, WNI_CFG_JOIN_FAILURE_TIMEOUT,
+ &cfgValue) != eSIR_SUCCESS)
+ lim_log(pMac, LOGP,
+ FL("could not retrieve JoinFailureTimeout value"));
+ cfgValue = SYS_MS_TO_TICKS(cfgValue);
+ /* Create Join failure timer and activate it later */
+ if (tx_timer_create(&pMac->lim.limTimers.gLimJoinFailureTimer,
+ "JOIN FAILURE TIMEOUT",
+ lim_timer_handler, SIR_LIM_JOIN_FAIL_TIMEOUT,
+ cfgValue, 0,
+ TX_NO_ACTIVATE) != TX_SUCCESS) {
+ /* / Could not create Join failure timer. */
+ /* Log error */
+ lim_log(pMac, LOGP,
+ FL("could not create Join failure timer"));
+ return false;
+ }
+ /* Send unicast probe req frame every 200 ms */
+ if (tx_timer_create(&pMac->lim.limTimers.gLimPeriodicJoinProbeReqTimer,
+ "Periodic Join Probe Request Timer",
+ lim_timer_handler,
+ SIR_LIM_PERIODIC_JOIN_PROBE_REQ_TIMEOUT,
+ SYS_MS_TO_TICKS(LIM_JOIN_PROBE_REQ_TIMER_MS), 0,
+ TX_NO_ACTIVATE) != TX_SUCCESS) {
+ lim_log(pMac, LOGP,
+ FL("could not create Periodic Join Probe Request tmr"));
+ return false;
+ }
+
+ if (wlan_cfg_get_int(pMac, WNI_CFG_ASSOCIATION_FAILURE_TIMEOUT,
+ &cfgValue) != eSIR_SUCCESS)
+ lim_log(pMac, LOGP,
+ FL("could not retrieve AssocFailureTimeout value"));
+
+ cfgValue = SYS_MS_TO_TICKS(cfgValue);
+ /* Create Association failure timer and activate it later */
+ if (tx_timer_create(&pMac->lim.limTimers.gLimAssocFailureTimer,
+ "ASSOC FAILURE TIMEOUT",
+ lim_assoc_failure_timer_handler, LIM_ASSOC,
+ cfgValue, 0, TX_NO_ACTIVATE) != TX_SUCCESS) {
+ lim_log(pMac, LOGP,
+ FL("could not create Association failure timer"));
+ return false;
+ }
+ if (wlan_cfg_get_int(pMac, WNI_CFG_REASSOCIATION_FAILURE_TIMEOUT,
+ &cfgValue) != eSIR_SUCCESS)
+ lim_log(pMac, LOGP,
+ FL("could not retrieve ReassocFailureTimeout value"));
+
+ cfgValue = SYS_MS_TO_TICKS(cfgValue);
+ /* Create Association failure timer and activate it later */
+ if (tx_timer_create
+ (&pMac->lim.limTimers.gLimReassocFailureTimer,
+ "REASSOC FAILURE TIMEOUT", lim_assoc_failure_timer_handler,
+ LIM_REASSOC, cfgValue, 0, TX_NO_ACTIVATE) != TX_SUCCESS) {
+ lim_log(pMac, LOGP,
+ FL("could not create Reassociation failure timer"));
+ return false;
+ }
+
+ if (wlan_cfg_get_int(pMac, WNI_CFG_ADDTS_RSP_TIMEOUT, &cfgValue)
+ != eSIR_SUCCESS)
+ lim_log(pMac, LOGP,
+ FL("Fail to get WNI_CFG_ADDTS_RSP_TIMEOUT "));
+
+ cfgValue = SYS_MS_TO_TICKS(cfgValue);
+
+ /* Create Addts response timer and activate it later */
+ if (tx_timer_create(&pMac->lim.limTimers.gLimAddtsRspTimer,
+ "ADDTS RSP TIMEOUT",
+ lim_addts_response_timer_handler,
+ SIR_LIM_ADDTS_RSP_TIMEOUT,
+ cfgValue, 0, TX_NO_ACTIVATE) != TX_SUCCESS) {
+ lim_log(pMac, LOGP,
+ FL("could not create Addts response timer"));
+ return false;
+ }
+
+ if (wlan_cfg_get_int(pMac, WNI_CFG_AUTHENTICATE_FAILURE_TIMEOUT,
+ &cfgValue) != eSIR_SUCCESS)
+ lim_log(pMac, LOGP,
+ FL("could not retrieve AuthFailureTimeout value"));
+
+ cfgValue = SYS_MS_TO_TICKS(cfgValue);
+ /* Create Auth failure timer and activate it later */
+ if (tx_timer_create(&pMac->lim.limTimers.gLimAuthFailureTimer,
+ "AUTH FAILURE TIMEOUT",
+ lim_timer_handler,
+ SIR_LIM_AUTH_FAIL_TIMEOUT,
+ cfgValue, 0, TX_NO_ACTIVATE) != TX_SUCCESS) {
+ lim_log(pMac, LOGP, FL("could not create Auth failure timer"));
+ return false;
+ }
+
+ if (wlan_cfg_get_int(pMac, WNI_CFG_PROBE_AFTER_HB_FAIL_TIMEOUT,
+ &cfgValue) != eSIR_SUCCESS)
+ lim_log(pMac, LOGP,
+ FL("could not retrieve PROBE_AFTER_HB_FAIL_TIMEOUT value"));
+
+ /* Change timer to reactivate it in future */
+ cfgValue = SYS_MS_TO_TICKS(cfgValue);
+ if (tx_timer_create(&pMac->lim.limTimers.gLimProbeAfterHBTimer,
+ "Probe after Heartbeat TIMEOUT",
+ lim_timer_handler,
+ SIR_LIM_PROBE_HB_FAILURE_TIMEOUT,
+ cfgValue, 0, TX_NO_ACTIVATE) != TX_SUCCESS) {
+ lim_log(pMac, LOGP, FL("unable to create ProbeAfterHBTimer"));
+ return false;
+ }
+
+ return true;
+}
+/**
+ * lim_create_timers()
+ *
+ * @pMac : Pointer to Global MAC structure
+ *
+ * This function is called upon receiving
+ * 1. SME_START_REQ for STA in ESS role
+ * 2. SME_START_BSS_REQ for AP role & STA in IBSS role
+ *
+ * @return : status of operation
+ */
+
+uint32_t lim_create_timers(tpAniSirGlobal pMac)
+{
+ uint32_t cfgValue, i = 0;
+ uint32_t cfgValue1;
+
+ PELOG1(lim_log(pMac, LOG1,
+ FL("Creating Timers used by LIM module in Role %d"),
+ pMac->lim.gLimSystemRole);)
+
+ if (wlan_cfg_get_int(pMac, WNI_CFG_ACTIVE_MINIMUM_CHANNEL_TIME,
+ &cfgValue) != eSIR_SUCCESS) {
+ lim_log(pMac, LOGP,
+ FL("could not retrieve MinChannelTimeout value"));
+ }
+ cfgValue = SYS_MS_TO_TICKS(cfgValue);
+ /* Periodic probe request timer value is half of the Min channel
+ * timer. Probe request sends periodically till min/max channel
+ * timer expires
+ */
+ cfgValue1 = cfgValue / 2;
+ /* Create periodic probe request timer and activate them later */
+ if (cfgValue1 >= 1
+ && (tx_timer_create(&pMac->lim.limTimers.gLimPeriodicProbeReqTimer,
+ "Periodic Probe Request Timer", lim_timer_handler,
+ SIR_LIM_PERIODIC_PROBE_REQ_TIMEOUT, cfgValue1, 0,
+ TX_NO_ACTIVATE) != TX_SUCCESS)) {
+ lim_log(pMac, LOGP,
+ FL("could not create periodic probe timer"));
+ goto err_timer;
+ }
+
+ if (wlan_cfg_get_int(pMac, WNI_CFG_ACTIVE_MAXIMUM_CHANNEL_TIME,
+ &cfgValue) != eSIR_SUCCESS)
+ lim_log(pMac, LOGP,
+ FL("could not retrieve MAXChannelTimeout value"));
+
+ cfgValue = SYS_MS_TO_TICKS(cfgValue);
+ /* Limiting max numm of probe req for each channel scan */
+ pMac->lim.maxProbe = (cfgValue / cfgValue1);
+
+ if (pMac->lim.gLimSystemRole != eLIM_AP_ROLE)
+ if (false == lim_create_non_ap_timers(pMac))
+ goto err_timer;
+
+ cfgValue = SYS_MS_TO_TICKS(LIM_HASH_MISS_TIMER_MS);
+
+ if (tx_timer_create(
+ &pMac->lim.limTimers.gLimSendDisassocFrameThresholdTimer,
+ "Disassoc throttle TIMEOUT",
+ lim_send_disassoc_frame_threshold_handler,
+ SIR_LIM_HASH_MISS_THRES_TIMEOUT, cfgValue, cfgValue,
+ TX_AUTO_ACTIVATE) != TX_SUCCESS) {
+ lim_log(pMac, LOGP,
+ FL("create Disassociate throttle timer failed"));
+ goto err_timer;
+ }
+ PELOG1(lim_log(pMac, LOG1, FL("Created Disassociate throttle timer "));)
+
+ /* Create all CNF_WAIT Timers upfront */
+ if (wlan_cfg_get_int(pMac, WNI_CFG_WT_CNF_TIMEOUT, &cfgValue)
+ != eSIR_SUCCESS) {
+ lim_log(pMac, LOGP, FL("could not retrieve CNF timeout value"));
+ }
+
+ cfgValue = SYS_MS_TO_TICKS(cfgValue);
+ for (i = 0; i < (pMac->lim.maxStation + 1); i++) {
+ if (tx_timer_create(&pMac->lim.limTimers.gpLimCnfWaitTimer[i],
+ "CNF_MISS_TIMEOUT",
+ lim_cnf_wait_tmer_handler,
+ (uint32_t) i, cfgValue,
+ 0, TX_NO_ACTIVATE) != TX_SUCCESS) {
+ lim_log(pMac, LOGP, FL("Cannot create CNF wait timer"));
+ goto err_timer;
+ }
+ }
+
+ /* Alloc and init table for the preAuth timer list */
+ if (wlan_cfg_get_int(pMac, WNI_CFG_MAX_NUM_PRE_AUTH,
+ &cfgValue) != eSIR_SUCCESS)
+ lim_log(pMac, LOGP, FL("could not retrieve mac preauth value"));
+ pMac->lim.gLimPreAuthTimerTable.numEntry = cfgValue;
+ pMac->lim.gLimPreAuthTimerTable.pTable =
+ cdf_mem_malloc(cfgValue * sizeof(tLimPreAuthNode));
+
+ if (pMac->lim.gLimPreAuthTimerTable.pTable == NULL) {
+ lim_log(pMac, LOGP, FL("AllocateMemory failed!"));
+ goto err_timer;
+ }
+
+ lim_init_pre_auth_timer_table(pMac, &pMac->lim.gLimPreAuthTimerTable);
+ PELOG1(lim_log(pMac, LOG1,
+ FL("alloc and init table for preAuth timers"));)
+
+ if (wlan_cfg_get_int(pMac, WNI_CFG_OLBC_DETECT_TIMEOUT,
+ &cfgValue) != eSIR_SUCCESS)
+ lim_log(pMac, LOGP,
+ FL("could not retrieve OLBD detect timeout value"));
+
+ cfgValue = SYS_MS_TO_TICKS(cfgValue);
+ if (tx_timer_create(&pMac->lim.limTimers.gLimUpdateOlbcCacheTimer,
+ "OLBC UPDATE CACHE TIMEOUT",
+ lim_update_olbc_cache_timer_handler,
+ SIR_LIM_UPDATE_OLBC_CACHEL_TIMEOUT, cfgValue,
+ cfgValue, TX_NO_ACTIVATE) != TX_SUCCESS) {
+ lim_log(pMac, LOGP, FL("Cannot create update OLBC cache tmr"));
+ goto err_timer;
+ }
+#ifdef WLAN_FEATURE_VOWIFI_11R
+ /* In future we need to use the auth timer, cause the pre auth session
+ * will be introduced before sending Auth frame. We need to go off
+ * channel and come back to home channel
+ */
+ cfgValue = 1000;
+ cfgValue = SYS_MS_TO_TICKS(cfgValue);
+ if (tx_timer_create(&pMac->lim.limTimers.gLimFTPreAuthRspTimer,
+ "FT PREAUTH RSP TIMEOUT",
+ lim_timer_handler, SIR_LIM_FT_PREAUTH_RSP_TIMEOUT,
+ cfgValue, 0, TX_NO_ACTIVATE) != TX_SUCCESS) {
+ lim_log(pMac, LOGP, FL("could not create Join failure timer"));
+ goto err_timer;
+ }
+#endif
+ cfgValue = 1000;
+ cfgValue = SYS_MS_TO_TICKS(cfgValue);
+ if (tx_timer_create(&pMac->lim.limTimers.gLimRemainOnChannelTimer,
+ "FT PREAUTH RSP TIMEOUT",
+ lim_timer_handler, SIR_LIM_REMAIN_CHN_TIMEOUT,
+ cfgValue, 0, TX_NO_ACTIVATE) != TX_SUCCESS) {
+ lim_log(pMac, LOGP, FL("could not create Join failure timer"));
+ goto err_timer;
+ }
+
+ cfgValue = 1000;
+ cfgValue = SYS_MS_TO_TICKS(cfgValue);
+ if (tx_timer_create(&pMac->lim.limTimers.gLimDisassocAckTimer,
+ "DISASSOC ACK TIMEOUT",
+ lim_timer_handler, SIR_LIM_DISASSOC_ACK_TIMEOUT,
+ cfgValue, 0, TX_NO_ACTIVATE) != TX_SUCCESS) {
+ lim_log(pMac, LOGP, FL("could not DISASSOC ACK TIMEOUT timer"));
+ goto err_timer;
+ }
+
+ cfgValue = 1000;
+ cfgValue = SYS_MS_TO_TICKS(cfgValue);
+ if (tx_timer_create(&pMac->lim.limTimers.gLimDeauthAckTimer,
+ "DISASSOC ACK TIMEOUT",
+ lim_timer_handler, SIR_LIM_DEAUTH_ACK_TIMEOUT,
+ cfgValue, 0, TX_NO_ACTIVATE) != TX_SUCCESS) {
+ lim_log(pMac, LOGP,
+ FL("could not create DEAUTH ACK TIMEOUT timer"));
+ goto err_timer;
+ }
+
+ /* (> no of BI* no of TUs per BI * 1TU in msec +
+ * p2p start time offset*1 TU in msec = 2*100*1.024 + 5*1.024
+ * = 204.8 + 5.12 = 209.20)
+ */
+ cfgValue = LIM_INSERT_SINGLESHOTNOA_TIMEOUT_VALUE;
+ cfgValue = SYS_MS_TO_TICKS(cfgValue);
+ if (tx_timer_create(
+ &pMac->lim.limTimers.gLimP2pSingleShotNoaInsertTimer,
+ "Single Shot NOA Insert timeout", lim_timer_handler,
+ SIR_LIM_INSERT_SINGLESHOT_NOA_TIMEOUT, cfgValue, 0,
+ TX_NO_ACTIVATE) != TX_SUCCESS) {
+ lim_log(pMac, LOGP,
+ FL("Can't create Single Shot NOA Insert Timeout tmr"));
+ goto err_timer;
+ }
+
+ cfgValue = ACTIVE_TO_PASSIVE_CONVERISON_TIMEOUT;
+ cfgValue = SYS_MS_TO_TICKS(cfgValue);
+ if (tx_timer_create(
+ &pMac->lim.limTimers.gLimActiveToPassiveChannelTimer,
+ "ACTIVE TO PASSIVE CHANNEL", lim_timer_handler,
+ SIR_LIM_CONVERT_ACTIVE_CHANNEL_TO_PASSIVE, cfgValue, 0,
+ TX_NO_ACTIVATE) != TX_SUCCESS) {
+ lim_log(pMac, LOGW,
+ FL("could not create timer for passive channel to active channel"));
+ goto err_timer;
+ }
+
+ return TX_SUCCESS;
+
+err_timer:
+ tx_timer_delete(&pMac->lim.limTimers.gLimDeauthAckTimer);
+ tx_timer_delete(&pMac->lim.limTimers.gLimDisassocAckTimer);
+ tx_timer_delete(&pMac->lim.limTimers.gLimRemainOnChannelTimer);
+ tx_timer_delete(&pMac->lim.limTimers.gLimFTPreAuthRspTimer);
+ tx_timer_delete(&pMac->lim.limTimers.gLimUpdateOlbcCacheTimer);
+ while (((int32_t)-- i) >= 0) {
+ tx_timer_delete(&pMac->lim.limTimers.gpLimCnfWaitTimer[i]);
+ }
+ tx_timer_delete(&pMac->lim.limTimers.
+ gLimSendDisassocFrameThresholdTimer);
+ tx_timer_delete(&pMac->lim.limTimers.gLimProbeAfterHBTimer);
+ tx_timer_delete(&pMac->lim.limTimers.gLimAuthFailureTimer);
+ tx_timer_delete(&pMac->lim.limTimers.gLimAddtsRspTimer);
+ tx_timer_delete(&pMac->lim.limTimers.gLimReassocFailureTimer);
+ tx_timer_delete(&pMac->lim.limTimers.gLimAssocFailureTimer);
+ tx_timer_delete(&pMac->lim.limTimers.gLimJoinFailureTimer);
+ tx_timer_delete(&pMac->lim.limTimers.gLimPeriodicJoinProbeReqTimer);
+ tx_timer_delete(&pMac->lim.limTimers.gLimQuietBssTimer);
+ tx_timer_delete(&pMac->lim.limTimers.gLimQuietTimer);
+ tx_timer_delete(&pMac->lim.limTimers.gLimChannelSwitchTimer);
+ tx_timer_delete(&pMac->lim.limTimers.gLimPeriodicProbeReqTimer);
+ tx_timer_delete(&pMac->lim.limTimers.gLimP2pSingleShotNoaInsertTimer);
+ tx_timer_delete(&pMac->lim.limTimers.gLimActiveToPassiveChannelTimer);
+
+ if (NULL != pMac->lim.gLimPreAuthTimerTable.pTable) {
+ cdf_mem_free(pMac->lim.gLimPreAuthTimerTable.pTable);
+ pMac->lim.gLimPreAuthTimerTable.pTable = NULL;
+ }
+ return TX_TIMER_ERROR;
+} /****** end lim_create_timers() ******/
+
+/**
+ * lim_timer_handler()
+ *
+ ***FUNCTION:
+ * This function is called upon
+ * 1. MIN_CHANNEL, MAX_CHANNEL timer expiration during scanning
+ * 2. JOIN_FAILURE timer expiration while joining a BSS
+ * 3. AUTH_FAILURE timer expiration while authenticating with a peer
+ * 4. Heartbeat timer expiration on STA
+ * 5. Background scan timer expiration on STA
+ * 6. AID release, Pre-auth cleanup and Link monitoring timer
+ * expiration on AP
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ * NA
+ *
+ ***NOTE:
+ * NA
+ *
+ * @param param - Message corresponding to the timer that expired
+ *
+ * @return None
+ */
+
+void lim_timer_handler(void *pMacGlobal, uint32_t param)
+{
+ uint32_t statusCode;
+ tSirMsgQ msg;
+ tpAniSirGlobal pMac = (tpAniSirGlobal) pMacGlobal;
+
+ /* Prepare and post message to LIM Message Queue */
+
+ msg.type = (uint16_t) param;
+ msg.bodyptr = NULL;
+ msg.bodyval = 0;
+
+ if ((statusCode = lim_post_msg_api(pMac, &msg)) != eSIR_SUCCESS)
+ lim_log(pMac, LOGE,
+ FL("posting message %X to LIM failed, reason=%d"),
+ msg.type, statusCode);
+} /****** end lim_timer_handler() ******/
+
+/**
+ * lim_addts_response_timer_handler()
+ *
+ ***FUNCTION:
+ * This function is called upon Addts response timer expiration on sta
+ *
+ ***LOGIC:
+ * Message SIR_LIM_ADDTS_RSP_TIMEOUT is posted to gSirLimMsgQ
+ * when this function is executed.
+ *
+ ***ASSUMPTIONS:
+ * NA
+ *
+ ***NOTE:
+ * NA
+ *
+ * @param param - pointer to pre-auth node
+ *
+ * @return None
+ */
+
+void lim_addts_response_timer_handler(void *pMacGlobal, uint32_t param)
+{
+ tSirMsgQ msg;
+ tpAniSirGlobal pMac = (tpAniSirGlobal) pMacGlobal;
+
+ /* Prepare and post message to LIM Message Queue */
+
+ msg.type = SIR_LIM_ADDTS_RSP_TIMEOUT;
+ msg.bodyval = param;
+ msg.bodyptr = NULL;
+
+ lim_post_msg_api(pMac, &msg);
+} /****** end lim_auth_response_timer_handler() ******/
+
+/**
+ * lim_auth_response_timer_handler()
+ *
+ ***FUNCTION:
+ * This function is called upon Auth response timer expiration on AP
+ *
+ ***LOGIC:
+ * Message SIR_LIM_AUTH_RSP_TIMEOUT is posted to gSirLimMsgQ
+ * when this function is executed.
+ *
+ ***ASSUMPTIONS:
+ * NA
+ *
+ ***NOTE:
+ * NA
+ *
+ * @param param - pointer to pre-auth node
+ *
+ * @return None
+ */
+
+void lim_auth_response_timer_handler(void *pMacGlobal, uint32_t param)
+{
+ tSirMsgQ msg;
+ tpAniSirGlobal pMac = (tpAniSirGlobal) pMacGlobal;
+
+ /* Prepare and post message to LIM Message Queue */
+
+ msg.type = SIR_LIM_AUTH_RSP_TIMEOUT;
+ msg.bodyptr = NULL;
+ msg.bodyval = (uint32_t) param;
+
+ lim_post_msg_api(pMac, &msg);
+} /****** end lim_auth_response_timer_handler() ******/
+
+/**
+ * lim_assoc_failure_timer_handler()
+ *
+ * @mac_global : Pointer to Global MAC structure
+ * @param : Indicates whether this is assoc or reassoc failure timeout
+ *
+ * This function is called upon Re/Assoc failure timer expiration on STA.
+ * Message SIR_LIM_ASSOC_FAIL_TIMEOUT is posted to gSirLimMsgQ when this
+ * function is executed.
+ *
+ * Return void
+ */
+void lim_assoc_failure_timer_handler(void *mac_global, uint32_t param)
+{
+ tSirMsgQ msg;
+ tpAniSirGlobal mac_ctx = (tpAniSirGlobal) mac_global;
+ tpPESession session = NULL;
+
+#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
+ session = mac_ctx->lim.pSessionEntry;
+ if (LIM_REASSOC == param && NULL != session
+ && session->limMlmState == eLIM_MLM_WT_FT_REASSOC_RSP_STATE) {
+ lim_log(mac_ctx, LOGE, FL("Reassoc timeout happened"));
+ if (mac_ctx->lim.reAssocRetryAttempt <
+ LIM_MAX_REASSOC_RETRY_LIMIT) {
+ lim_send_retry_reassoc_req_frame(mac_ctx,
+ session->pLimMlmReassocRetryReq, session);
+ mac_ctx->lim.reAssocRetryAttempt++;
+ lim_log(mac_ctx, LOGW,
+ FL("Reassoc request retry is sent %d times"),
+ mac_ctx->lim.reAssocRetryAttempt);
+ return;
+ } else {
+ lim_log(mac_ctx, LOGW,
+ FL("Reassoc request retry MAX(%d) reached"),
+ LIM_MAX_REASSOC_RETRY_LIMIT);
+ if (NULL != session->pLimMlmReassocRetryReq) {
+ cdf_mem_free(session->pLimMlmReassocRetryReq);
+ session->pLimMlmReassocRetryReq = NULL;
+ }
+ }
+ }
+#endif
+ /* Prepare and post message to LIM Message Queue */
+ msg.type = SIR_LIM_ASSOC_FAIL_TIMEOUT;
+ msg.bodyval = (uint32_t) param;
+ msg.bodyptr = NULL;
+ lim_post_msg_api(mac_ctx, &msg);
+} /****** end lim_assoc_failure_timer_handler() ******/
+
+/**
+ * lim_update_olbc_cache_timer_handler()
+ *
+ ***FUNCTION:
+ * This function is called upon update olbc cache timer expiration
+ * on STA
+ *
+ ***LOGIC:
+ * Message SIR_LIM_UPDATE_OLBC_CACHEL_TIMEOUT is posted to gSirLimMsgQ
+ * when this function is executed.
+ *
+ ***ASSUMPTIONS:
+ * NA
+ *
+ ***NOTE:
+ * NA
+ *
+ * @param
+ *
+ * @return None
+ */
+void lim_update_olbc_cache_timer_handler(void *pMacGlobal, uint32_t param)
+{
+ tSirMsgQ msg;
+ tpAniSirGlobal pMac = (tpAniSirGlobal) pMacGlobal;
+
+ /* Prepare and post message to LIM Message Queue */
+
+ msg.type = SIR_LIM_UPDATE_OLBC_CACHEL_TIMEOUT;
+ msg.bodyval = 0;
+ msg.bodyptr = NULL;
+
+ lim_post_msg_api(pMac, &msg);
+} /****** end lim_update_olbc_cache_timer_handler() ******/
+
+/**
+ * lim_deactivate_and_change_timer()
+ *
+ ***FUNCTION:
+ * This function is called to deactivate and change a timer
+ * for future re-activation
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ * NA
+ *
+ ***NOTE:
+ * NA
+ *
+ * @param pMac - Pointer to Global MAC structure
+ * @param timerId - enum of timer to be deactivated and changed
+ * This enum is defined in lim_utils.h file
+ *
+ * @return None
+ */
+
+void lim_deactivate_and_change_timer(tpAniSirGlobal pMac, uint32_t timerId)
+{
+ uint32_t val = 0;
+
+ MTRACE(mac_trace
+ (pMac, TRACE_CODE_TIMER_DEACTIVATE, NO_SESSION, timerId));
+
+ switch (timerId) {
+ case eLIM_ADDTS_RSP_TIMER:
+ pMac->lim.gLimAddtsRspTimerCount++;
+ if (tx_timer_deactivate(&pMac->lim.limTimers.gLimAddtsRspTimer)
+ != TX_SUCCESS) {
+ /* Could not deactivate AddtsRsp Timer */
+ /* Log error */
+ lim_log(pMac, LOGP,
+ FL("Unable to deactivate AddtsRsp timer"));
+ }
+ break;
+
+ case eLIM_PERIODIC_PROBE_REQ_TIMER:
+ if (tx_timer_deactivate
+ (&pMac->lim.limTimers.gLimPeriodicProbeReqTimer)
+ != TX_SUCCESS) {
+ /* Could not deactivate min channel timer. */
+ /* Log error */
+ lim_log(pMac, LOGP,
+ FL("Unable to deactivate periodic timer"));
+ }
+
+ val =
+ SYS_MS_TO_TICKS(pMac->lim.gpLimMlmScanReq->minChannelTime) /
+ 2;
+ if (tx_timer_change
+ (&pMac->lim.limTimers.gLimPeriodicProbeReqTimer, val,
+ 0) != TX_SUCCESS) {
+ /* Could not change min channel timer. */
+ /* Log error */
+ lim_log(pMac, LOGP,
+ FL("Unable to change periodic timer"));
+ }
+
+ break;
+
+ case eLIM_JOIN_FAIL_TIMER:
+ if (tx_timer_deactivate
+ (&pMac->lim.limTimers.gLimJoinFailureTimer)
+ != TX_SUCCESS) {
+ /**
+ * Could not deactivate Join Failure
+ * timer. Log error.
+ */
+ lim_log(pMac, LOGP,
+ FL("Unable to deactivate Join Failure timer"));
+ }
+
+ if (wlan_cfg_get_int(pMac, WNI_CFG_JOIN_FAILURE_TIMEOUT,
+ &val) != eSIR_SUCCESS) {
+ /**
+ * Could not get JoinFailureTimeout value
+ * from CFG. Log error.
+ */
+ lim_log(pMac, LOGP,
+ FL
+ ("could not retrieve JoinFailureTimeout value"));
+ }
+ val = SYS_MS_TO_TICKS(val);
+
+ if (tx_timer_change(&pMac->lim.limTimers.gLimJoinFailureTimer,
+ val, 0) != TX_SUCCESS) {
+ /**
+ * Could not change Join Failure
+ * timer. Log error.
+ */
+ lim_log(pMac, LOGP,
+ FL("Unable to change Join Failure timer"));
+ }
+
+ break;
+
+ case eLIM_PERIODIC_JOIN_PROBE_REQ_TIMER:
+ if (tx_timer_deactivate
+ (&pMac->lim.limTimers.gLimPeriodicJoinProbeReqTimer)
+ != TX_SUCCESS) {
+ /* Could not deactivate periodic join req Times. */
+ lim_log(pMac, LOGP,
+ FL
+ ("Unable to deactivate periodic join request timer"));
+ }
+
+ val = SYS_MS_TO_TICKS(LIM_JOIN_PROBE_REQ_TIMER_MS);
+ if (tx_timer_change
+ (&pMac->lim.limTimers.gLimPeriodicJoinProbeReqTimer, val,
+ 0) != TX_SUCCESS) {
+ /* Could not change periodic join req times. */
+ /* Log error */
+ lim_log(pMac, LOGP,
+ FL
+ ("Unable to change periodic join request timer"));
+ }
+
+ break;
+
+ case eLIM_AUTH_FAIL_TIMER:
+ if (tx_timer_deactivate
+ (&pMac->lim.limTimers.gLimAuthFailureTimer)
+ != TX_SUCCESS) {
+ /* Could not deactivate Auth failure timer. */
+ /* Log error */
+ lim_log(pMac, LOGP,
+ FL("Unable to deactivate auth failure timer"));
+ }
+ /* Change timer to reactivate it in future */
+ if (wlan_cfg_get_int(pMac, WNI_CFG_AUTHENTICATE_FAILURE_TIMEOUT,
+ &val) != eSIR_SUCCESS) {
+ /**
+ * Could not get AuthFailureTimeout value
+ * from CFG. Log error.
+ */
+ lim_log(pMac, LOGP,
+ FL
+ ("could not retrieve AuthFailureTimeout value"));
+ }
+ val = SYS_MS_TO_TICKS(val);
+
+ if (tx_timer_change(&pMac->lim.limTimers.gLimAuthFailureTimer,
+ val, 0) != TX_SUCCESS) {
+ /* Could not change Authentication failure timer. */
+ /* Log error */
+ lim_log(pMac, LOGP,
+ FL("unable to change Auth failure timer"));
+ }
+
+ break;
+
+ case eLIM_ASSOC_FAIL_TIMER:
+ if (tx_timer_deactivate
+ (&pMac->lim.limTimers.gLimAssocFailureTimer) !=
+ TX_SUCCESS) {
+ /* Could not deactivate Association failure timer. */
+ /* Log error */
+ lim_log(pMac, LOGP,
+ FL
+ ("unable to deactivate Association failure timer"));
+ }
+ /* Change timer to reactivate it in future */
+ if (wlan_cfg_get_int(pMac, WNI_CFG_ASSOCIATION_FAILURE_TIMEOUT,
+ &val) != eSIR_SUCCESS) {
+ /**
+ * Could not get AssocFailureTimeout value
+ * from CFG. Log error.
+ */
+ lim_log(pMac, LOGP,
+ FL
+ ("could not retrieve AssocFailureTimeout value"));
+ }
+ val = SYS_MS_TO_TICKS(val);
+
+ if (tx_timer_change(&pMac->lim.limTimers.gLimAssocFailureTimer,
+ val, 0) != TX_SUCCESS) {
+ /* Could not change Association failure timer. */
+ /* Log error */
+ lim_log(pMac, LOGP,
+ FL("unable to change Assoc failure timer"));
+ }
+
+ break;
+
+ case eLIM_REASSOC_FAIL_TIMER:
+ if (tx_timer_deactivate
+ (&pMac->lim.limTimers.gLimReassocFailureTimer) !=
+ TX_SUCCESS) {
+ /* Could not deactivate Reassociation failure timer. */
+ /* Log error */
+ lim_log(pMac, LOGP,
+ FL
+ ("unable to deactivate Reassoc failure timer"));
+ }
+ /* Change timer to reactivate it in future */
+ if (wlan_cfg_get_int(pMac, WNI_CFG_REASSOCIATION_FAILURE_TIMEOUT,
+ &val) != eSIR_SUCCESS) {
+ /**
+ * Could not get ReassocFailureTimeout value
+ * from CFG. Log error.
+ */
+ lim_log(pMac, LOGP,
+ FL
+ ("could not retrieve ReassocFailureTimeout value"));
+ }
+ val = SYS_MS_TO_TICKS(val);
+
+ if (tx_timer_change
+ (&pMac->lim.limTimers.gLimReassocFailureTimer, val,
+ 0) != TX_SUCCESS) {
+ /* Could not change Reassociation failure timer. */
+ /* Log error */
+ lim_log(pMac, LOGP,
+ FL
+ ("unable to change Reassociation failure timer"));
+ }
+
+ break;
+
+ case eLIM_PROBE_AFTER_HB_TIMER:
+ if (tx_timer_deactivate
+ (&pMac->lim.limTimers.gLimProbeAfterHBTimer) !=
+ TX_SUCCESS) {
+ /* Could not deactivate Heartbeat timer. */
+ /* Log error */
+ lim_log(pMac, LOGP,
+ FL("unable to deactivate probeAfterHBTimer"));
+ } else {
+ lim_log(pMac, LOG1,
+ FL("Deactivated probe after hb timer"));
+ }
+
+ if (wlan_cfg_get_int(pMac, WNI_CFG_PROBE_AFTER_HB_FAIL_TIMEOUT,
+ &val) != eSIR_SUCCESS) {
+ /**
+ * Could not get PROBE_AFTER_HB_FAILURE
+ * value from CFG. Log error.
+ */
+ lim_log(pMac, LOGP,
+ FL
+ ("could not retrieve PROBE_AFTER_HB_FAIL_TIMEOUT value"));
+ }
+ /* Change timer to reactivate it in future */
+ val = SYS_MS_TO_TICKS(val);
+
+ if (tx_timer_change(&pMac->lim.limTimers.gLimProbeAfterHBTimer,
+ val, 0) != TX_SUCCESS) {
+ /* Could not change HeartBeat timer. */
+ /* Log error */
+ lim_log(pMac, LOGP,
+ FL("unable to change ProbeAfterHBTimer"));
+ } else {
+ lim_log(pMac, LOGW,
+ FL("Probe after HB timer value is changed = %u"),
+ val);
+ }
+
+ break;
+
+ case eLIM_LEARN_DURATION_TIMER:
+ break;
+
+#ifdef WLAN_FEATURE_VOWIFI_11R
+ case eLIM_FT_PREAUTH_RSP_TIMER:
+ if (tx_timer_deactivate
+ (&pMac->lim.limTimers.gLimFTPreAuthRspTimer) !=
+ TX_SUCCESS) {
+ /**
+ ** Could not deactivate Join Failure
+ ** timer. Log error.
+ **/
+ lim_log(pMac, LOGP,
+ FL
+ ("Unable to deactivate Preauth response Failure timer"));
+ return;
+ }
+ val = 1000;
+ val = SYS_MS_TO_TICKS(val);
+ if (tx_timer_change(&pMac->lim.limTimers.gLimFTPreAuthRspTimer,
+ val, 0) != TX_SUCCESS) {
+ /**
+ * Could not change Join Failure
+ * timer. Log error.
+ */
+ lim_log(pMac, LOGP,
+ FL("Unable to change Join Failure timer"));
+ return;
+ }
+ break;
+#endif
+ case eLIM_REMAIN_CHN_TIMER:
+ if (tx_timer_deactivate
+ (&pMac->lim.limTimers.gLimRemainOnChannelTimer) !=
+ TX_SUCCESS) {
+ /**
+ ** Could not deactivate Join Failure
+ ** timer. Log error.
+ **/
+ lim_log(pMac, LOGP,
+ FL("Unable to deactivate Remain on Chn timer"));
+ return;
+ }
+ val = 1000;
+ val = SYS_MS_TO_TICKS(val);
+ if (tx_timer_change
+ (&pMac->lim.limTimers.gLimRemainOnChannelTimer, val,
+ 0) != TX_SUCCESS) {
+ /**
+ * Could not change Join Failure
+ * timer. Log error.
+ */
+ lim_log(pMac, LOGP, FL("Unable to change timer"));
+ return;
+ }
+ break;
+
+ case eLIM_CONVERT_ACTIVE_CHANNEL_TO_PASSIVE:
+ if (tx_timer_deactivate
+ (&pMac->lim.limTimers.gLimActiveToPassiveChannelTimer) !=
+ TX_SUCCESS) {
+ /**
+ ** Could not deactivate Active to passive channel timer.
+ ** Log error.
+ **/
+ lim_log(pMac, LOGP, FL("Unable to Deactivate "
+ "Active to passive channel timer"));
+ return;
+ }
+ val = ACTIVE_TO_PASSIVE_CONVERISON_TIMEOUT;
+ val = SYS_MS_TO_TICKS(val);
+ if (tx_timer_change
+ (&pMac->lim.limTimers.gLimActiveToPassiveChannelTimer, val,
+ 0) != TX_SUCCESS) {
+ /**
+ * Could not change timer to check scan type for passive channel.
+ * timer. Log error.
+ */
+ lim_log(pMac, LOGP, FL("Unable to change timer"));
+ return;
+ }
+ break;
+
+ case eLIM_DISASSOC_ACK_TIMER:
+ if (tx_timer_deactivate
+ (&pMac->lim.limTimers.gLimDisassocAckTimer) != TX_SUCCESS) {
+ /**
+ ** Could not deactivate Join Failure
+ ** timer. Log error.
+ **/
+ lim_log(pMac, LOGP,
+ FL("Unable to deactivate Disassoc ack timer"));
+ return;
+ }
+ val = 1000;
+ val = SYS_MS_TO_TICKS(val);
+ if (tx_timer_change(&pMac->lim.limTimers.gLimDisassocAckTimer,
+ val, 0) != TX_SUCCESS) {
+ /**
+ * Could not change Join Failure
+ * timer. Log error.
+ */
+ lim_log(pMac, LOGP, FL("Unable to change timer"));
+ return;
+ }
+ break;
+
+ case eLIM_DEAUTH_ACK_TIMER:
+ if (tx_timer_deactivate(&pMac->lim.limTimers.gLimDeauthAckTimer)
+ != TX_SUCCESS) {
+ /**
+ ** Could not deactivate Join Failure
+ ** timer. Log error.
+ **/
+ lim_log(pMac, LOGP,
+ FL("Unable to deactivate Deauth ack timer"));
+ return;
+ }
+ val = 1000;
+ val = SYS_MS_TO_TICKS(val);
+ if (tx_timer_change(&pMac->lim.limTimers.gLimDeauthAckTimer,
+ val, 0) != TX_SUCCESS) {
+ /**
+ * Could not change Join Failure
+ * timer. Log error.
+ */
+ lim_log(pMac, LOGP, FL("Unable to change timer"));
+ return;
+ }
+ break;
+
+ case eLIM_INSERT_SINGLESHOT_NOA_TIMER:
+ if (tx_timer_deactivate
+ (&pMac->lim.limTimers.gLimP2pSingleShotNoaInsertTimer) !=
+ TX_SUCCESS) {
+ /**
+ ** Could not deactivate SingleShot NOA Insert
+ ** timer. Log error.
+ **/
+ lim_log(pMac, LOGP,
+ FL
+ ("Unable to deactivate SingleShot NOA Insert timer"));
+ return;
+ }
+ val = LIM_INSERT_SINGLESHOTNOA_TIMEOUT_VALUE;
+ val = SYS_MS_TO_TICKS(val);
+ if (tx_timer_change
+ (&pMac->lim.limTimers.gLimP2pSingleShotNoaInsertTimer, val,
+ 0) != TX_SUCCESS) {
+ /**
+ * Could not change Single Shot NOA Insert
+ * timer. Log error.
+ */
+ lim_log(pMac, LOGP, FL("Unable to change timer"));
+ return;
+ }
+ break;
+
+ default:
+ /* Invalid timerId. Log error */
+ break;
+ }
+} /****** end lim_deactivate_and_change_timer() ******/
+
+/**
+ * lim_deactivate_and_change_per_sta_id_timer()
+ *
+ *
+ * @brief: This function is called to deactivate and change a per STA timer
+ * for future re-activation
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ * NA
+ *
+ * @note staId for eLIM_AUTH_RSP_TIMER is auth Node Index.
+ *
+ * @param pMac - Pointer to Global MAC structure
+ * @param timerId - enum of timer to be deactivated and changed
+ * This enum is defined in lim_utils.h file
+ * @param staId - staId
+ *
+ * @return None
+ */
+
+void
+lim_deactivate_and_change_per_sta_id_timer(tpAniSirGlobal pMac, uint32_t timerId,
+ uint16_t staId)
+{
+ uint32_t val;
+ MTRACE(mac_trace
+ (pMac, TRACE_CODE_TIMER_DEACTIVATE, NO_SESSION, timerId));
+
+ switch (timerId) {
+ case eLIM_CNF_WAIT_TIMER:
+
+ if (tx_timer_deactivate
+ (&pMac->lim.limTimers.gpLimCnfWaitTimer[staId])
+ != TX_SUCCESS) {
+ lim_log(pMac, LOGP,
+ FL("unable to deactivate CNF wait timer"));
+
+ }
+ /* Change timer to reactivate it in future */
+
+ if (wlan_cfg_get_int(pMac, WNI_CFG_WT_CNF_TIMEOUT,
+ &val) != eSIR_SUCCESS) {
+ /**
+ * Could not get cnf timeout value
+ * from CFG. Log error.
+ */
+ lim_log(pMac, LOGP,
+ FL("could not retrieve cnf timeout value"));
+ }
+ val = SYS_MS_TO_TICKS(val);
+
+ if (tx_timer_change
+ (&pMac->lim.limTimers.gpLimCnfWaitTimer[staId], val,
+ val) != TX_SUCCESS) {
+ /* Could not change cnf timer. */
+ /* Log error */
+ lim_log(pMac, LOGP,
+ FL("unable to change cnf wait timer"));
+ }
+
+ break;
+
+ case eLIM_AUTH_RSP_TIMER:
+ {
+ tLimPreAuthNode *pAuthNode;
+
+ pAuthNode =
+ lim_get_pre_auth_node_from_index(pMac,
+ &pMac->lim.
+ gLimPreAuthTimerTable,
+ staId);
+
+ if (pAuthNode == NULL) {
+ lim_log(pMac, LOGP,
+ FL("Invalid Pre Auth Index passed :%d"),
+ staId);
+ break;
+ }
+
+ if (tx_timer_deactivate(&pAuthNode->timer) !=
+ TX_SUCCESS) {
+ /* Could not deactivate auth response timer. */
+ /* Log error */
+ lim_log(pMac, LOGP,
+ FL
+ ("unable to deactivate auth response timer"));
+ }
+ /* Change timer to reactivate it in future */
+
+ if (wlan_cfg_get_int
+ (pMac, WNI_CFG_AUTHENTICATE_RSP_TIMEOUT,
+ &val) != eSIR_SUCCESS) {
+ /**
+ * Could not get auth rsp timeout value
+ * from CFG. Log error.
+ */
+ lim_log(pMac, LOGP,
+ FL
+ ("could not retrieve auth response timeout value"));
+ }
+
+ val = SYS_MS_TO_TICKS(val);
+
+ if (tx_timer_change(&pAuthNode->timer, val, 0) !=
+ TX_SUCCESS) {
+ /* Could not change auth rsp timer. */
+ /* Log error */
+ lim_log(pMac, LOGP,
+ FL("unable to change auth rsp timer"));
+ }
+ }
+ break;
+
+ default:
+ /* Invalid timerId. Log error */
+ break;
+
+ }
+}
+
+/**
+ * lim_activate_cnf_timer()
+ *
+ ***FUNCTION:
+ * This function is called to activate a per STA timer
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ * NA
+ *
+ ***NOTE:
+ * NA
+ *
+ * @param pMac - Pointer to Global MAC structure
+ * @param StaId - staId
+ *
+ * @return None
+ */
+
+void lim_activate_cnf_timer(tpAniSirGlobal pMac, uint16_t staId,
+ tpPESession psessionEntry)
+{
+ MTRACE(mac_trace
+ (pMac, TRACE_CODE_TIMER_ACTIVATE, psessionEntry->peSessionId,
+ eLIM_CNF_WAIT_TIMER));
+ pMac->lim.limTimers.gpLimCnfWaitTimer[staId].sessionId =
+ psessionEntry->peSessionId;
+ if (tx_timer_activate(&pMac->lim.limTimers.gpLimCnfWaitTimer[staId])
+ != TX_SUCCESS) {
+ lim_log(pMac, LOGP, FL("could not activate cnf wait timer"));
+ }
+}
+
+/**
+ * lim_activate_auth_rsp_timer()
+ *
+ ***FUNCTION:
+ * This function is called to activate a per STA timer
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ * NA
+ *
+ ***NOTE:
+ * NA
+ *
+ * @param pMac - Pointer to Global MAC structure
+ * @param id - id
+ *
+ * @return None
+ */
+
+void lim_activate_auth_rsp_timer(tpAniSirGlobal pMac, tLimPreAuthNode *pAuthNode)
+{
+ MTRACE(mac_trace
+ (pMac, TRACE_CODE_TIMER_ACTIVATE, NO_SESSION,
+ eLIM_AUTH_RESP_TIMER));
+ if (tx_timer_activate(&pAuthNode->timer) != TX_SUCCESS) {
+ /* / Could not activate auth rsp timer. */
+ /* Log error */
+ lim_log(pMac, LOGP, FL("could not activate auth rsp timer"));
+ }
+}
+
+/**
+ * lim_send_disassoc_frame_threshold_handler()
+ *
+ ***FUNCTION:
+ * This function reloads the credit to the send disassociate frame bucket
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ *
+ ***NOTE:
+ * NA
+ *
+ * @param
+ *
+ * @return None
+ */
+
+void lim_send_disassoc_frame_threshold_handler(void *pMacGlobal, uint32_t param)
+{
+ tSirMsgQ msg;
+ uint32_t statusCode;
+ tpAniSirGlobal pMac = (tpAniSirGlobal) pMacGlobal;
+
+ msg.type = SIR_LIM_HASH_MISS_THRES_TIMEOUT;
+ msg.bodyval = 0;
+ msg.bodyptr = NULL;
+
+ if ((statusCode = lim_post_msg_api(pMac, &msg)) != eSIR_SUCCESS)
+ lim_log(pMac, LOGE,
+ FL("posting to LIM failed, reason=%d"), statusCode);
+
+}
+
+/**
+ * limAssocCnfWaitTmerHandler()
+ *
+ ***FUNCTION:
+ * This function post a message to send a disassociate frame out.
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ *
+ ***NOTE:
+ * NA
+ *
+ * @param
+ *
+ * @return None
+ */
+
+void lim_cnf_wait_tmer_handler(void *pMacGlobal, uint32_t param)
+{
+ tSirMsgQ msg;
+ uint32_t statusCode;
+ tpAniSirGlobal pMac = (tpAniSirGlobal) pMacGlobal;
+
+ msg.type = SIR_LIM_CNF_WAIT_TIMEOUT;
+ msg.bodyval = (uint32_t) param;
+ msg.bodyptr = NULL;
+
+ if ((statusCode = lim_post_msg_api(pMac, &msg)) != eSIR_SUCCESS)
+ lim_log(pMac, LOGE,
+ FL("posting to LIM failed, reason=%d"), statusCode);
+
+}
+
+void lim_channel_switch_timer_handler(void *pMacGlobal, uint32_t param)
+{
+ tSirMsgQ msg;
+ tpAniSirGlobal pMac = (tpAniSirGlobal) pMacGlobal;
+
+ PELOG1(lim_log(pMac, LOG1,
+ FL("ChannelSwitch Timer expired. Posting msg to LIM "));
+ )
+
+ msg.type = SIR_LIM_CHANNEL_SWITCH_TIMEOUT;
+ msg.bodyval = (uint32_t) param;
+ msg.bodyptr = NULL;
+
+ lim_post_msg_api(pMac, &msg);
+}
+
+void lim_quiet_timer_handler(void *pMacGlobal, uint32_t param)
+{
+ tSirMsgQ msg;
+ tpAniSirGlobal pMac = (tpAniSirGlobal) pMacGlobal;
+
+ msg.type = SIR_LIM_QUIET_TIMEOUT;
+ msg.bodyval = (uint32_t) param;
+ msg.bodyptr = NULL;
+
+ PELOG1(lim_log(pMac, LOG1, FL("Post SIR_LIM_QUIET_TIMEOUT msg. "));)
+ lim_post_msg_api(pMac, &msg);
+}
+
+void lim_quiet_bss_timer_handler(void *pMacGlobal, uint32_t param)
+{
+ tSirMsgQ msg;
+ tpAniSirGlobal pMac = (tpAniSirGlobal) pMacGlobal;
+
+ msg.type = SIR_LIM_QUIET_BSS_TIMEOUT;
+ msg.bodyval = (uint32_t) param;
+ msg.bodyptr = NULL;
+ PELOG1(lim_log(pMac, LOG1, FL("Post SIR_LIM_QUIET_BSS_TIMEOUT msg. "));)
+ lim_post_msg_api(pMac, &msg);
+}
+
diff --git a/core/mac/src/pe/lim/lim_timer_utils.h b/core/mac/src/pe/lim/lim_timer_utils.h
new file mode 100644
index 0000000..b133d71
--- /dev/null
+++ b/core/mac/src/pe/lim/lim_timer_utils.h
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2011-2014 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_timer_utils.h contains the utility definitions
+ * LIM uses for timer handling.
+ * Author: Chandra Modumudi
+ * Date: 02/13/02
+ * History:-
+ * Date Modified by Modification Information
+ * --------------------------------------------------------------------
+ */
+#ifndef __LIM_TIMER_UTILS_H
+#define __LIM_TIMER_UTILS_H
+
+#include "lim_types.h"
+
+/* Timer related functions */
+enum {
+ eLIM_MIN_CHANNEL_TIMER,
+ eLIM_MAX_CHANNEL_TIMER,
+ eLIM_JOIN_FAIL_TIMER,
+ eLIM_AUTH_FAIL_TIMER,
+ eLIM_AUTH_RESP_TIMER,
+ eLIM_ASSOC_FAIL_TIMER,
+ eLIM_REASSOC_FAIL_TIMER,
+ eLIM_PRE_AUTH_CLEANUP_TIMER,
+ eLIM_CNF_WAIT_TIMER,
+ eLIM_AUTH_RSP_TIMER,
+ eLIM_UPDATE_OLBC_CACHE_TIMER,
+ eLIM_PROBE_AFTER_HB_TIMER,
+ eLIM_ADDTS_RSP_TIMER,
+ eLIM_CHANNEL_SWITCH_TIMER,
+ eLIM_LEARN_DURATION_TIMER,
+ eLIM_QUIET_TIMER,
+ eLIM_QUIET_BSS_TIMER,
+ eLIM_WPS_OVERLAP_TIMER,
+#ifdef WLAN_FEATURE_VOWIFI_11R
+ eLIM_FT_PREAUTH_RSP_TIMER,
+#endif
+ eLIM_REMAIN_CHN_TIMER,
+ eLIM_PERIODIC_PROBE_REQ_TIMER,
+#ifdef FEATURE_WLAN_ESE
+ eLIM_TSM_TIMER,
+#endif
+ eLIM_DISASSOC_ACK_TIMER,
+ eLIM_DEAUTH_ACK_TIMER,
+ eLIM_PERIODIC_JOIN_PROBE_REQ_TIMER,
+ eLIM_INSERT_SINGLESHOT_NOA_TIMER,
+ eLIM_CONVERT_ACTIVE_CHANNEL_TO_PASSIVE
+};
+
+#define LIM_DISASSOC_DEAUTH_ACK_TIMEOUT 500
+#define LIM_INSERT_SINGLESHOTNOA_TIMEOUT_VALUE 500
+
+/* Timer Handler functions */
+uint32_t lim_create_timers(tpAniSirGlobal);
+void lim_timer_handler(void *, uint32_t);
+void lim_auth_response_timer_handler(void *, uint32_t);
+void lim_assoc_failure_timer_handler(void *, uint32_t);
+void limReassocFailureTimerHandler(void *, uint32_t);
+
+void lim_deactivate_and_change_timer(tpAniSirGlobal, uint32_t);
+void limDummyPktExpTimerHandler(void *, uint32_t);
+void lim_send_disassoc_frame_threshold_handler(void *, uint32_t);
+void lim_cnf_wait_tmer_handler(void *, uint32_t);
+void lim_deactivate_and_change_per_sta_id_timer(tpAniSirGlobal, uint32_t, uint16_t);
+void lim_activate_cnf_timer(tpAniSirGlobal, uint16_t, tpPESession);
+void lim_activate_auth_rsp_timer(tpAniSirGlobal, tLimPreAuthNode *);
+void lim_update_olbc_cache_timer_handler(void *, uint32_t);
+void lim_addts_response_timer_handler(void *, uint32_t);
+void lim_channel_switch_timer_handler(void *, uint32_t);
+void lim_quiet_timer_handler(void *, uint32_t);
+void lim_quiet_bss_timer_handler(void *, uint32_t);
+void limCBScanIntervalTimerHandler(void *, uint32_t);
+void limCBScanDurationTimerHandler(void *, uint32_t);
+#endif /* __LIM_TIMER_UTILS_H */
diff --git a/core/mac/src/pe/lim/lim_trace.c b/core/mac/src/pe/lim/lim_trace.c
new file mode 100644
index 0000000..3847127
--- /dev/null
+++ b/core/mac/src/pe/lim/lim_trace.c
@@ -0,0 +1,483 @@
+/*
+ * Copyright (c) 2013-2015 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.
+ */
+
+/**=========================================================================
+
+ \file lim_trace.c
+
+ \brief implementation for trace related APIs
+
+ \author Sunit Bhatia
+
+ ========================================================================*/
+
+/*--------------------------------------------------------------------------
+ Include Files
+ ------------------------------------------------------------------------*/
+
+#include "ani_global.h" /* for tpAniSirGlobal */
+
+#include "lim_trace.h"
+#include "lim_timer_utils.h"
+#include "cdf_trace.h"
+
+#ifdef LIM_TRACE_RECORD
+uint32_t g_mgmt_frame_stats[14];
+
+#define LIM_TRACE_MAX_SUBTYPES 14
+
+static uint8_t *__lim_trace_get_timer_string(uint16_t timerId)
+{
+ switch (timerId) {
+ CASE_RETURN_STRING(eLIM_MIN_CHANNEL_TIMER);
+ CASE_RETURN_STRING(eLIM_MAX_CHANNEL_TIMER);
+ CASE_RETURN_STRING(eLIM_JOIN_FAIL_TIMER);
+ CASE_RETURN_STRING(eLIM_AUTH_FAIL_TIMER);
+ CASE_RETURN_STRING(eLIM_AUTH_RESP_TIMER);
+ CASE_RETURN_STRING(eLIM_ASSOC_FAIL_TIMER);
+ CASE_RETURN_STRING(eLIM_REASSOC_FAIL_TIMER);
+ CASE_RETURN_STRING(eLIM_PRE_AUTH_CLEANUP_TIMER);
+ CASE_RETURN_STRING(eLIM_CNF_WAIT_TIMER);
+ CASE_RETURN_STRING(eLIM_AUTH_RSP_TIMER);
+ CASE_RETURN_STRING(eLIM_UPDATE_OLBC_CACHE_TIMER);
+ CASE_RETURN_STRING(eLIM_PROBE_AFTER_HB_TIMER);
+ CASE_RETURN_STRING(eLIM_ADDTS_RSP_TIMER);
+ CASE_RETURN_STRING(eLIM_CHANNEL_SWITCH_TIMER);
+ CASE_RETURN_STRING(eLIM_LEARN_DURATION_TIMER);
+ CASE_RETURN_STRING(eLIM_QUIET_TIMER);
+ CASE_RETURN_STRING(eLIM_QUIET_BSS_TIMER);
+ CASE_RETURN_STRING(eLIM_WPS_OVERLAP_TIMER);
+#ifdef WLAN_FEATURE_VOWIFI_11R
+ CASE_RETURN_STRING(eLIM_FT_PREAUTH_RSP_TIMER);
+#endif
+ CASE_RETURN_STRING(eLIM_REMAIN_CHN_TIMER);
+ CASE_RETURN_STRING(eLIM_PERIODIC_PROBE_REQ_TIMER);
+#ifdef FEATURE_WLAN_ESE
+ CASE_RETURN_STRING(eLIM_TSM_TIMER);
+#endif
+ CASE_RETURN_STRING(eLIM_DISASSOC_ACK_TIMER);
+ CASE_RETURN_STRING(eLIM_DEAUTH_ACK_TIMER);
+ CASE_RETURN_STRING(eLIM_PERIODIC_JOIN_PROBE_REQ_TIMER);
+ CASE_RETURN_STRING(eLIM_INSERT_SINGLESHOT_NOA_TIMER);
+ CASE_RETURN_STRING(eLIM_CONVERT_ACTIVE_CHANNEL_TO_PASSIVE);
+ default:
+ return ("UNKNOWN");
+ break;
+ }
+}
+
+static uint8_t *__lim_trace_get_mgmt_drop_reason_string(uint16_t dropReason)
+{
+
+ switch (dropReason) {
+ CASE_RETURN_STRING(eMGMT_DROP_INFRA_BCN_IN_IBSS);
+ CASE_RETURN_STRING(eMGMT_DROP_INVALID_SIZE);
+ CASE_RETURN_STRING(eMGMT_DROP_NON_SCAN_MODE_FRAME);
+ CASE_RETURN_STRING(eMGMT_DROP_NOT_LAST_IBSS_BCN);
+ CASE_RETURN_STRING(eMGMT_DROP_NO_DROP);
+ CASE_RETURN_STRING(eMGMT_DROP_SCAN_MODE_FRAME);
+
+ default:
+ return ("UNKNOWN");
+ break;
+ }
+}
+
+void lim_trace_init(tpAniSirGlobal pMac)
+{
+ cdf_trace_register(CDF_MODULE_ID_PE, (tp_cdf_trace_cb) & lim_trace_dump);
+}
+
+void lim_trace_dump(tpAniSirGlobal pMac, tp_cdf_trace_record pRecord,
+ uint16_t recIndex)
+{
+
+ static char *frameSubtypeStr[LIM_TRACE_MAX_SUBTYPES] = {
+ "Association request",
+ "Association response",
+ "Reassociation request",
+ "Reassociation response",
+ "Probe request",
+ "Probe response",
+ NULL,
+ NULL,
+ "Beacon",
+ "ATIM",
+ "Disassociation",
+ "Authentication",
+ "Deauthentication",
+ "Action"
+ };
+
+ switch (pRecord->code) {
+ case TRACE_CODE_MLM_STATE:
+ lim_log(pMac, LOGE,
+ "%04d %012llu S%d %-14s %-30s(0x%x) ", recIndex,
+ pRecord->time, pRecord->session, "MLM State:",
+ lim_trace_get_mlm_state_string((uint16_t) pRecord->data),
+ pRecord->data);
+ break;
+ case TRACE_CODE_SME_STATE:
+ lim_log(pMac, LOGE,
+ "%04d %012llu S%d %-14s %-30s(0x%x) ", recIndex,
+ pRecord->time, pRecord->session, "SME State:",
+ lim_trace_get_sme_state_string((uint16_t) pRecord->data),
+ pRecord->data);
+ break;
+ case TRACE_CODE_TX_MGMT:
+ lim_log(pMac, LOGE,
+ "%04d %012llu S%d %-14s %-30s(0x%x) ", recIndex,
+ pRecord->time, pRecord->session, "TX Mgmt:",
+ frameSubtypeStr[pRecord->data], pRecord->data);
+ break;
+
+ case TRACE_CODE_RX_MGMT:
+ if (LIM_TRACE_MAX_SUBTYPES <=
+ LIM_TRACE_GET_SUBTYPE(pRecord->data)) {
+ lim_log(pMac, LOGE, "Wrong Subtype - %d",
+ LIM_TRACE_GET_SUBTYPE(pRecord->data));
+ } else {
+ lim_log(pMac, LOGE,
+ "%04d %012llu S%d %-14s %-30s(%d) SN: %d ",
+ recIndex, pRecord->time, pRecord->session,
+ "RX Mgmt:",
+ frameSubtypeStr[LIM_TRACE_GET_SUBTYPE
+ (pRecord->data)],
+ LIM_TRACE_GET_SUBTYPE(pRecord->data),
+ LIM_TRACE_GET_SSN(pRecord->data));
+ }
+ break;
+ case TRACE_CODE_RX_MGMT_DROP:
+ lim_log(pMac, LOGE, "%04d %012llu S%d %-14s %-30s(%d) ",
+ recIndex, pRecord->time, pRecord->session,
+ "Drop RX Mgmt:",
+ __lim_trace_get_mgmt_drop_reason_string((uint16_t) pRecord->
+ data), pRecord->data);
+ break;
+
+ case TRACE_CODE_RX_MGMT_TSF:
+ lim_log(pMac, LOGE,
+ "%04d %012llu S%d %-14s %-30s0x%x(%d) ",
+ recIndex, pRecord->time, pRecord->session,
+ "RX Mgmt TSF:", " ", pRecord->data, pRecord->data);
+ break;
+
+ case TRACE_CODE_TX_COMPLETE:
+ lim_log(pMac, LOGE, "%04d %012llu S%d %-14s %d ", recIndex,
+ pRecord->time, pRecord->session, "TX Complete",
+ pRecord->data);
+ break;
+
+ case TRACE_CODE_TX_SME_MSG:
+ lim_log(pMac, LOGE,
+ "%04d %012llu S%d %-14s %-30s(0x%x) ", recIndex,
+ pRecord->time, pRecord->session, "TX SME Msg:",
+ mac_trace_get_sme_msg_string((uint16_t) pRecord->data),
+ pRecord->data);
+ break;
+ case TRACE_CODE_RX_SME_MSG:
+ lim_log(pMac, LOGE,
+ "%04d %012llu S%d %-14s %-30s(0x%x) ", recIndex,
+ pRecord->time, pRecord->session,
+ LIM_TRACE_GET_DEFRD_OR_DROPPED(pRecord->
+ data) ? "Def/Drp LIM Msg:"
+ : "RX Sme Msg:",
+ mac_trace_get_sme_msg_string((uint16_t) pRecord->data),
+ pRecord->data);
+ break;
+
+ case TRACE_CODE_TX_WMA_MSG:
+ lim_log(pMac, LOGE,
+ "%04d %012llu S%d %-14s %-30s(0x%x) ", recIndex,
+ pRecord->time, pRecord->session, "TX WMA Msg:",
+ mac_trace_get_wma_msg_string((uint16_t) pRecord->data),
+ pRecord->data);
+ break;
+
+ case TRACE_CODE_RX_WMA_MSG:
+ lim_log(pMac, LOGE,
+ "%04d %012llu S%d %-14s %-30s(0x%x) ", recIndex,
+ pRecord->time, pRecord->session,
+ LIM_TRACE_GET_DEFRD_OR_DROPPED(pRecord->
+ data) ? "Def/Drp LIM Msg:"
+ : "RX WMA Msg:",
+ mac_trace_get_wma_msg_string((uint16_t) pRecord->data),
+ pRecord->data);
+ break;
+
+ case TRACE_CODE_TX_LIM_MSG:
+ lim_log(pMac, LOGE,
+ "%04d %012llu S%d %-14s %-30s(0x%x) ", recIndex,
+ pRecord->time, pRecord->session, "TX LIM Msg:",
+ mac_trace_get_lim_msg_string((uint16_t) pRecord->data),
+ pRecord->data);
+ break;
+ case TRACE_CODE_RX_LIM_MSG:
+ lim_log(pMac, LOGE,
+ "%04d %012llu S%d %-14s %-30s(0x%x) ", recIndex,
+ pRecord->time, pRecord->session,
+ LIM_TRACE_GET_DEFRD_OR_DROPPED(pRecord->
+ data) ? "Def/Drp LIM Msg:"
+ : "RX LIM Msg",
+ mac_trace_get_lim_msg_string((uint16_t) pRecord->data),
+ pRecord->data);
+ break;
+ case TRACE_CODE_TX_CFG_MSG:
+ lim_log(pMac, LOGE,
+ "%04d %012llu S%d %-14s %-30s(0x%x) ", recIndex,
+ pRecord->time, pRecord->session, "TX CFG Msg:",
+ mac_trace_get_cfg_msg_string((uint16_t) pRecord->data),
+ pRecord->data);
+ break;
+ case TRACE_CODE_RX_CFG_MSG:
+ lim_log(pMac, LOGE,
+ "%04d %012llu S%d %-14s %-30s(0x%x) ", recIndex,
+ pRecord->time, pRecord->session,
+ LIM_TRACE_GET_DEFRD_OR_DROPPED(pRecord->
+ data) ? "Def/Drp LIM Msg:"
+ : "RX CFG Msg:",
+ mac_trace_get_cfg_msg_string((uint16_t)
+ MAC_TRACE_GET_MSG_ID(pRecord->
+ data)),
+ pRecord->data);
+ break;
+
+ case TRACE_CODE_TIMER_ACTIVATE:
+ lim_log(pMac, LOGE,
+ "%04d %012llu S%d %-14s %-30s(0x%x) ", recIndex,
+ pRecord->time, pRecord->session, "Timer Actvtd",
+ __lim_trace_get_timer_string((uint16_t) pRecord->data),
+ pRecord->data);
+ break;
+ case TRACE_CODE_TIMER_DEACTIVATE:
+ lim_log(pMac, LOGE,
+ "%04d %012llu S%d %-14s %-30s(0x%x) ", recIndex,
+ pRecord->time, pRecord->session, "Timer DeActvtd",
+ __lim_trace_get_timer_string((uint16_t) pRecord->data),
+ pRecord->data);
+ break;
+
+ case TRACE_CODE_INFO_LOG:
+ lim_log(pMac, LOGE,
+ "%04d %012llu S%d %-14s %-30s(0x%x) \n",
+ recIndex, pRecord->time, pRecord->session,
+ "INFORMATION_LOG",
+ mac_trace_get_info_log_string((uint16_t) pRecord->data),
+ pRecord->data);
+ break;
+ default:
+ lim_log(pMac, LOGE, "%04d %012llu S%d %-14s(%d) (0x%x) ",
+ recIndex, pRecord->time, pRecord->session,
+ "Unknown Code", pRecord->code, pRecord->data);
+ break;
+ }
+}
+
+void mac_trace_msg_tx(tpAniSirGlobal pMac, uint8_t session, uint32_t data)
+{
+
+ uint16_t msgId = (uint16_t) MAC_TRACE_GET_MSG_ID(data);
+ uint8_t moduleId = (uint8_t) MAC_TRACE_GET_MODULE_ID(data);
+
+ switch (moduleId) {
+ case SIR_LIM_MODULE_ID:
+ if (msgId >= SIR_LIM_ITC_MSG_TYPES_BEGIN)
+ mac_trace(pMac, TRACE_CODE_TX_LIM_MSG, session, data);
+ else
+ mac_trace(pMac, TRACE_CODE_TX_SME_MSG, session, data);
+ break;
+ case SIR_WMA_MODULE_ID:
+ mac_trace(pMac, TRACE_CODE_TX_WMA_MSG, session, data);
+ break;
+ case SIR_CFG_MODULE_ID:
+ mac_trace(pMac, TRACE_CODE_TX_CFG_MSG, session, data);
+ break;
+ default:
+ mac_trace(pMac, moduleId, session, data);
+ break;
+ }
+}
+
+void mac_trace_msg_tx_new(tpAniSirGlobal pMac, uint8_t module, uint8_t session,
+ uint32_t data)
+{
+ uint16_t msgId = (uint16_t) MAC_TRACE_GET_MSG_ID(data);
+ uint8_t moduleId = (uint8_t) MAC_TRACE_GET_MODULE_ID(data);
+
+ switch (moduleId) {
+ case SIR_LIM_MODULE_ID:
+ if (msgId >= SIR_LIM_ITC_MSG_TYPES_BEGIN)
+ mac_trace_new(pMac, module, TRACE_CODE_TX_LIM_MSG,
+ session, data);
+ else
+ mac_trace_new(pMac, module, TRACE_CODE_TX_SME_MSG,
+ session, data);
+ break;
+ case SIR_WMA_MODULE_ID:
+ mac_trace_new(pMac, module, TRACE_CODE_TX_WMA_MSG, session, data);
+ break;
+ case SIR_CFG_MODULE_ID:
+ mac_trace_new(pMac, module, TRACE_CODE_TX_CFG_MSG, session, data);
+ break;
+ default:
+ mac_trace(pMac, moduleId, session, data);
+ break;
+ }
+}
+
+/*
+ * bit31: Rx message defferred or not
+ * bit 0-15: message ID:
+ */
+void mac_trace_msg_rx(tpAniSirGlobal pMac, uint8_t session, uint32_t data)
+{
+ uint16_t msgId = (uint16_t) MAC_TRACE_GET_MSG_ID(data);
+ uint8_t moduleId = (uint8_t) MAC_TRACE_GET_MODULE_ID(data);
+
+ switch (moduleId) {
+ case SIR_LIM_MODULE_ID:
+ if (msgId >= SIR_LIM_ITC_MSG_TYPES_BEGIN)
+ mac_trace(pMac, TRACE_CODE_RX_LIM_MSG, session, data);
+ else
+ mac_trace(pMac, TRACE_CODE_RX_SME_MSG, session, data);
+ break;
+ case SIR_WMA_MODULE_ID:
+ mac_trace(pMac, TRACE_CODE_RX_WMA_MSG, session, data);
+ break;
+ case SIR_CFG_MODULE_ID:
+ mac_trace(pMac, TRACE_CODE_RX_CFG_MSG, session, data);
+ break;
+ default:
+ mac_trace(pMac, moduleId, session, data);
+ break;
+ }
+}
+
+/*
+ * bit31: Rx message defferred or not
+ * bit 0-15: message ID:
+ */
+void mac_trace_msg_rx_new(tpAniSirGlobal pMac, uint8_t module, uint8_t session,
+ uint32_t data)
+{
+ uint16_t msgId = (uint16_t) MAC_TRACE_GET_MSG_ID(data);
+ uint8_t moduleId = (uint8_t) MAC_TRACE_GET_MODULE_ID(data);
+
+ switch (moduleId) {
+ case SIR_LIM_MODULE_ID:
+ if (msgId >= SIR_LIM_ITC_MSG_TYPES_BEGIN)
+ mac_trace_new(pMac, module, TRACE_CODE_RX_LIM_MSG,
+ session, data);
+ else
+ mac_trace_new(pMac, module, TRACE_CODE_RX_SME_MSG,
+ session, data);
+ break;
+ case SIR_WMA_MODULE_ID:
+ mac_trace_new(pMac, module, TRACE_CODE_RX_WMA_MSG, session, data);
+ break;
+ case SIR_CFG_MODULE_ID:
+ mac_trace_new(pMac, module, TRACE_CODE_RX_CFG_MSG, session, data);
+ break;
+ default:
+ mac_trace(pMac, moduleId, session, data);
+ break;
+ }
+}
+
+uint8_t *lim_trace_get_mlm_state_string(uint32_t mlmState)
+{
+ switch (mlmState) {
+ CASE_RETURN_STRING(eLIM_MLM_OFFLINE_STATE);
+ CASE_RETURN_STRING(eLIM_MLM_IDLE_STATE);
+ CASE_RETURN_STRING(eLIM_MLM_WT_PROBE_RESP_STATE);
+ CASE_RETURN_STRING(eLIM_MLM_PASSIVE_SCAN_STATE);
+ CASE_RETURN_STRING(eLIM_MLM_WT_JOIN_BEACON_STATE);
+ CASE_RETURN_STRING(eLIM_MLM_JOINED_STATE);
+ CASE_RETURN_STRING(eLIM_MLM_BSS_STARTED_STATE);
+ CASE_RETURN_STRING(eLIM_MLM_WT_AUTH_FRAME2_STATE);
+ CASE_RETURN_STRING(eLIM_MLM_WT_AUTH_FRAME3_STATE);
+ CASE_RETURN_STRING(eLIM_MLM_WT_AUTH_FRAME4_STATE);
+ CASE_RETURN_STRING(eLIM_MLM_AUTH_RSP_TIMEOUT_STATE);
+ CASE_RETURN_STRING(eLIM_MLM_AUTHENTICATED_STATE);
+ CASE_RETURN_STRING(eLIM_MLM_WT_ASSOC_RSP_STATE);
+ CASE_RETURN_STRING(eLIM_MLM_WT_REASSOC_RSP_STATE);
+ CASE_RETURN_STRING(eLIM_MLM_ASSOCIATED_STATE);
+ CASE_RETURN_STRING(eLIM_MLM_REASSOCIATED_STATE);
+ CASE_RETURN_STRING(eLIM_MLM_LINK_ESTABLISHED_STATE);
+ CASE_RETURN_STRING(eLIM_MLM_WT_ASSOC_CNF_STATE);
+ CASE_RETURN_STRING(eLIM_MLM_LEARN_STATE);
+ CASE_RETURN_STRING(eLIM_MLM_WT_ADD_BSS_RSP_STATE);
+ CASE_RETURN_STRING(eLIM_MLM_WT_DEL_BSS_RSP_STATE);
+ CASE_RETURN_STRING(eLIM_MLM_WT_ADD_BSS_RSP_ASSOC_STATE);
+ CASE_RETURN_STRING(eLIM_MLM_WT_ADD_BSS_RSP_PREASSOC_STATE);
+ CASE_RETURN_STRING(eLIM_MLM_WT_ADD_BSS_RSP_REASSOC_STATE);
+ CASE_RETURN_STRING(eLIM_MLM_WT_ADD_STA_RSP_STATE);
+ CASE_RETURN_STRING(eLIM_MLM_WT_DEL_STA_RSP_STATE);
+ CASE_RETURN_STRING(eLIM_MLM_WT_ASSOC_DEL_STA_RSP_STATE);
+ CASE_RETURN_STRING(eLIM_MLM_WT_SET_BSS_KEY_STATE);
+ CASE_RETURN_STRING(eLIM_MLM_WT_SET_STA_KEY_STATE);
+ CASE_RETURN_STRING(eLIM_MLM_WT_SET_STA_BCASTKEY_STATE);
+ CASE_RETURN_STRING(eLIM_MLM_WT_SET_MIMOPS_STATE);
+ default:
+ return ("UNKNOWN");
+ break;
+ }
+}
+
+uint8_t *lim_trace_get_sme_state_string(uint32_t smeState)
+{
+ switch (smeState) {
+
+ CASE_RETURN_STRING(eLIM_SME_OFFLINE_STATE);
+ CASE_RETURN_STRING(eLIM_SME_IDLE_STATE);
+ CASE_RETURN_STRING(eLIM_SME_SUSPEND_STATE);
+ CASE_RETURN_STRING(eLIM_SME_WT_SCAN_STATE);
+ CASE_RETURN_STRING(eLIM_SME_WT_JOIN_STATE);
+ CASE_RETURN_STRING(eLIM_SME_WT_AUTH_STATE);
+ CASE_RETURN_STRING(eLIM_SME_WT_ASSOC_STATE);
+ CASE_RETURN_STRING(eLIM_SME_WT_REASSOC_STATE);
+ CASE_RETURN_STRING(eLIM_SME_WT_REASSOC_LINK_FAIL_STATE);
+ CASE_RETURN_STRING(eLIM_SME_JOIN_FAILURE_STATE);
+ CASE_RETURN_STRING(eLIM_SME_ASSOCIATED_STATE);
+ CASE_RETURN_STRING(eLIM_SME_REASSOCIATED_STATE);
+ CASE_RETURN_STRING(eLIM_SME_LINK_EST_STATE);
+ CASE_RETURN_STRING(eLIM_SME_LINK_EST_WT_SCAN_STATE);
+ CASE_RETURN_STRING(eLIM_SME_WT_PRE_AUTH_STATE);
+ CASE_RETURN_STRING(eLIM_SME_WT_DISASSOC_STATE);
+ CASE_RETURN_STRING(eLIM_SME_WT_DEAUTH_STATE);
+ CASE_RETURN_STRING(eLIM_SME_WT_START_BSS_STATE);
+ CASE_RETURN_STRING(eLIM_SME_WT_STOP_BSS_STATE);
+ CASE_RETURN_STRING(eLIM_SME_NORMAL_STATE);
+ CASE_RETURN_STRING(eLIM_SME_CHANNEL_SCAN_STATE);
+ CASE_RETURN_STRING(eLIM_SME_NORMAL_CHANNEL_SCAN_STATE);
+ default:
+ return ("UNKNOWN");
+ break;
+ }
+}
+
+#endif
diff --git a/core/mac/src/pe/lim/lim_types.h b/core/mac/src/pe/lim/lim_types.h
new file mode 100644
index 0000000..715e775
--- /dev/null
+++ b/core/mac/src/pe/lim/lim_types.h
@@ -0,0 +1,867 @@
+/*
+ * Copyright (c) 2012-2015 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_types.h contains the definitions used by all
+ * all LIM modules.
+ * Author: Chandra Modumudi
+ * Date: 02/11/02
+ * History:-
+ * Date Modified by Modification Information
+ * --------------------------------------------------------------------
+ *
+ */
+#ifndef __LIM_TYPES_H
+#define __LIM_TYPES_H
+
+#include "wni_api.h"
+#include "sir_api.h"
+#include "sir_common.h"
+#include "sir_mac_prot_def.h"
+#include "utils_api.h"
+
+#include "lim_api.h"
+#include "lim_debug.h"
+#include "lim_send_sme_rsp_messages.h"
+#include "sys_global.h"
+#include "dph_global.h"
+#include "parser_api.h"
+#include "wma_if.h"
+
+#define LINK_TEST_DEFER 1
+
+#define TRACE_EVENT_CNF_TIMER_DEACT 0x6600
+#define TRACE_EVENT_CNF_TIMER_ACT 0x6601
+#define TRACE_EVENT_AUTH_RSP_TIMER_DEACT 0x6602
+#define TRACE_EVENT_AUTH_RSP_TIMER_ACT 0x6603
+
+/* MLM message types */
+#define LIM_MLM_MSG_START 1000
+#define LIM_MLM_SCAN_REQ LIM_MLM_MSG_START
+#define LIM_MLM_SCAN_CNF (LIM_MLM_MSG_START + 1)
+#define LIM_MLM_START_REQ (LIM_MLM_MSG_START + 2)
+#define LIM_MLM_START_CNF (LIM_MLM_MSG_START + 3)
+#define LIM_MLM_JOIN_REQ (LIM_MLM_MSG_START + 4)
+#define LIM_MLM_JOIN_CNF (LIM_MLM_MSG_START + 5)
+#define LIM_MLM_AUTH_REQ (LIM_MLM_MSG_START + 6)
+#define LIM_MLM_AUTH_CNF (LIM_MLM_MSG_START + 7)
+#define LIM_MLM_AUTH_IND (LIM_MLM_MSG_START + 8)
+#define LIM_MLM_ASSOC_REQ (LIM_MLM_MSG_START + 9)
+#define LIM_MLM_ASSOC_CNF (LIM_MLM_MSG_START + 10)
+#define LIM_MLM_ASSOC_IND (LIM_MLM_MSG_START + 11)
+#define LIM_MLM_DISASSOC_REQ (LIM_MLM_MSG_START + 12)
+#define LIM_MLM_DISASSOC_CNF (LIM_MLM_MSG_START + 13)
+#define LIM_MLM_DISASSOC_IND (LIM_MLM_MSG_START + 14)
+#define LIM_MLM_REASSOC_REQ (LIM_MLM_MSG_START + 15)
+#define LIM_MLM_REASSOC_CNF (LIM_MLM_MSG_START + 16)
+#define LIM_MLM_REASSOC_IND (LIM_MLM_MSG_START + 17)
+#define LIM_MLM_DEAUTH_REQ (LIM_MLM_MSG_START + 18)
+#define LIM_MLM_DEAUTH_CNF (LIM_MLM_MSG_START + 19)
+#define LIM_MLM_DEAUTH_IND (LIM_MLM_MSG_START + 20)
+#define LIM_MLM_TSPEC_REQ (LIM_MLM_MSG_START + 21)
+#define LIM_MLM_TSPEC_CNF (LIM_MLM_MSG_START + 22)
+#define LIM_MLM_TSPEC_IND (LIM_MLM_MSG_START + 23)
+#define LIM_MLM_SETKEYS_REQ (LIM_MLM_MSG_START + 24)
+#define LIM_MLM_SETKEYS_CNF (LIM_MLM_MSG_START + 25)
+#define LIM_MLM_LINK_TEST_STOP_REQ (LIM_MLM_MSG_START + 30)
+#define LIM_MLM_PURGE_STA_IND (LIM_MLM_MSG_START + 31)
+/*
+ * Values (LIM_MLM_MSG_START + 32) through
+ * (LIM_MLM_MSG_START + 40) are unused.
+ */
+#ifdef FEATURE_OEM_DATA_SUPPORT
+#define LIM_MLM_OEM_DATA_REQ (LIM_MLM_MSG_START + 41)
+#define LIM_MLM_OEM_DATA_CNF (LIM_MLM_MSG_START + 42)
+#endif
+
+#define LIM_HASH_ADD 0
+#define LIM_HASH_UPDATE 1
+
+#define LIM_WEP_IN_FC 1
+#define LIM_NO_WEP_IN_FC 0
+
+#define LIM_DECRYPT_ICV_FAIL 1
+
+/* / Definitions to distinquish between Association/Reassociaton */
+#define LIM_ASSOC 0
+#define LIM_REASSOC 1
+
+/* / Minimum Memory blocks require for different scenario */
+#define LIM_MIN_MEM_ASSOC 4
+
+/* / Verifies whether given mac addr matches the CURRENT Bssid */
+#define IS_CURRENT_BSSID(pMac, addr, psessionEntry) (cdf_mem_compare(addr, \
+ psessionEntry->bssId, \
+ sizeof(psessionEntry->bssId)))
+/* / Verifies whether given addr matches the REASSOC Bssid */
+#define IS_REASSOC_BSSID(pMac, addr, psessionEntry) (cdf_mem_compare(addr, \
+ psessionEntry->limReAssocbssId, \
+ sizeof(psessionEntry->limReAssocbssId)))
+
+#define REQ_TYPE_REGISTRAR (0x2)
+#define REQ_TYPE_WLAN_MANAGER_REGISTRAR (0x3)
+
+#define RESP_TYPE_REGISTRAR (0x2)
+#define RESP_TYPE_ENROLLEE_INFO_ONLY (0x0)
+#define RESP_TYPE_ENROLLEE_OPEN_8021X (0x1)
+#define RESP_TYPE_AP (0x3)
+#define LIM_TX_FRAMES_THRESHOLD_ON_CHIP 300
+
+
+#define HAL_TXCOMP_REQUESTED_MASK 0x1 /* bit 0 for TxComp intr requested. */
+#define HAL_USE_SELF_STA_REQUESTED_MASK 0x2 /* bit 1 for STA overwrite with selfSta Requested. */
+#define HAL_TX_NO_ENCRYPTION_MASK 0x4 /* bit 2. If set, the frame is not to be encrypted */
+#if defined(LIBRA_WAPI_SUPPORT)
+#define HAL_WAPI_STA_MASK 0x8 /* bit 3. If set, this frame is for WAPI station */
+#endif
+
+#define HAL_TRIGGER_ENABLED_AC_MASK 0x10 /* bit 4 for data frames belonging to trigger enabled AC */
+#define HAL_USE_NO_ACK_REQUESTED_MASK 0x20
+
+#define HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME 0x40 /* Bit 6 will be used to control BD rate for Management frames */
+#define HAL_USE_PEER_STA_REQUESTED_MASK 0x80 /* bit 7 will be used to control frames for p2p interface */
+
+#ifdef FEATURE_WLAN_TDLS
+#define HAL_TDLS_PEER_STA_MASK 0x80 /* bit 7 set for TDLS peer station */
+#endif
+
+
+/* enums used by LIM are as follows */
+
+enum eLimDisassocTrigger {
+ eLIM_HOST_DISASSOC,
+ eLIM_PEER_ENTITY_DISASSOC,
+ eLIM_LINK_MONITORING_DISASSOC,
+ eLIM_PROMISCUOUS_MODE_DISASSOC,
+ eLIM_HOST_DEAUTH,
+ eLIM_PEER_ENTITY_DEAUTH,
+ eLIM_LINK_MONITORING_DEAUTH,
+ eLIM_JOIN_FAILURE,
+ eLIM_REASSOC_REJECT
+};
+
+/* Reason code to determine the channel change context while sending
+ * WMA_CHNL_SWITCH_REQ message to HAL
+ */
+enum eChannelChangeReasonCodes {
+ LIM_SWITCH_CHANNEL_REASSOC,
+ LIM_SWITCH_CHANNEL_JOIN,
+ LIM_SWITCH_CHANNEL_OPERATION, /* Generic change channel */
+ LIM_SWITCH_CHANNEL_SAP_DFS, /* DFS channel change */
+};
+
+typedef struct sLimAuthRspTimeout {
+ tSirMacAddr peerMacAddr;
+} tLimAuthRspTimeout;
+
+typedef struct sLimMlmStartReq {
+ tSirMacSSid ssId;
+ tSirBssType bssType;
+ tSirMacAddr bssId;
+ tSirMacBeaconInterval beaconPeriod;
+ uint8_t dtimPeriod;
+ tSirMacCfParamSet cfParamSet;
+ tSirMacChanNum channelNumber;
+ ePhyChanBondState cbMode;
+ uint16_t atimWindow;
+ tSirMacRateSet rateSet;
+ uint8_t sessionId; /* Added For BT-AMP Support */
+
+ /* Parameters reqd for new HAL (message) interface */
+ tSirNwType nwType;
+ uint8_t htCapable;
+ tSirMacHTOperatingMode htOperMode;
+ uint8_t dualCTSProtection;
+ uint8_t txChannelWidthSet;
+ uint8_t ssidHidden;
+ uint8_t wps_state;
+ uint8_t obssProtEnabled;
+} tLimMlmStartReq, *tpLimMlmStartReq;
+
+typedef struct sLimMlmStartCnf {
+ tSirResultCodes resultCode;
+ uint8_t sessionId;
+} tLimMlmStartCnf, *tpLimMlmStartCnf;
+
+typedef struct sLimMlmScanCnf {
+ tSirResultCodes resultCode;
+ uint16_t scanResultLength;
+ tSirBssDescription bssDescription[1];
+ uint8_t sessionId;
+} tLimMlmScanCnf, *tpLimMlmScanCnf;
+
+typedef struct sLimScanResult {
+ uint16_t numBssDescriptions;
+ tSirBssDescription bssDescription[1];
+} tLimScanResult;
+
+typedef struct sLimMlmJoinCnf {
+ tSirResultCodes resultCode;
+ uint16_t protStatusCode;
+ uint8_t sessionId;
+} tLimMlmJoinCnf, *tpLimMlmJoinCnf;
+
+typedef struct sLimMlmAssocReq {
+ tSirMacAddr peerMacAddr;
+ uint32_t assocFailureTimeout;
+ uint16_t capabilityInfo;
+ tSirMacListenInterval listenInterval;
+ uint8_t sessionId;
+} tLimMlmAssocReq, *tpLimMlmAssocReq;
+
+typedef struct sLimMlmAssocCnf {
+ tSirResultCodes resultCode; /* Internal status code. */
+ uint16_t protStatusCode; /* Protocol Status code. */
+ uint8_t sessionId;
+} tLimMlmAssocCnf, *tpLimMlmAssocCnf;
+
+typedef struct sLimMlmAssocInd {
+ tSirMacAddr peerMacAddr;
+ uint16_t aid;
+ tAniAuthType authType;
+ tAniSSID ssId;
+ tSirRSNie rsnIE;
+ tSirWAPIie wapiIE;
+ tSirAddie addIE; /* additional IE received from the peer, which possibly includes WSC IE and/or P2P IE. */
+ tSirMacCapabilityInfo capabilityInfo;
+ tAniBool spectrumMgtIndicator;
+ tSirMacPowerCapInfo powerCap;
+ tSirSupChnl supportedChannels;
+ uint8_t sessionId;
+
+ tAniBool WmmStaInfoPresent;
+
+ /* Required for indicating the frames to upper layer */
+ uint32_t beaconLength;
+ uint8_t *beaconPtr;
+ uint32_t assocReqLength;
+ uint8_t *assocReqPtr;
+ tSirSmeChanInfo chan_info;
+} tLimMlmAssocInd, *tpLimMlmAssocInd;
+
+typedef struct sLimMlmReassocReq {
+ tSirMacAddr peerMacAddr;
+ uint32_t reassocFailureTimeout;
+ uint16_t capabilityInfo;
+ tSirMacListenInterval listenInterval;
+ uint8_t sessionId;
+} tLimMlmReassocReq, *tpLimMlmReassocReq;
+
+typedef struct sLimMlmReassocCnf {
+ tSirResultCodes resultCode;
+ uint16_t protStatusCode; /* Protocol Status code. */
+ uint8_t sessionId;
+} tLimMlmReassocCnf, *tpLimMlmReassocCnf;
+
+typedef struct sLimMlmReassocInd {
+ tSirMacAddr peerMacAddr;
+ tSirMacAddr currentApAddr;
+ uint16_t aid;
+ tAniAuthType authType;
+ tAniSSID ssId;
+ tSirRSNie rsnIE;
+ tSirWAPIie wapiIE;
+ tSirAddie addIE; /* additional IE received from the peer, which can be WSC IE and/or P2P IE. */
+ tSirMacCapabilityInfo capabilityInfo;
+ tAniBool spectrumMgtIndicator;
+ tSirMacPowerCapInfo powerCap;
+ tSirSupChnl supportedChannels;
+
+ tAniBool WmmStaInfoPresent;
+
+ /* Required for indicating the frames to upper layer */
+ uint32_t beaconLength;
+ uint8_t *beaconPtr;
+ uint32_t assocReqLength;
+ uint8_t *assocReqPtr;
+} tLimMlmReassocInd, *tpLimMlmReassocInd;
+
+typedef struct sLimMlmAuthCnf {
+ tSirMacAddr peerMacAddr;
+ tAniAuthType authType;
+ tSirResultCodes resultCode;
+ uint16_t protStatusCode;
+ uint8_t sessionId;
+} tLimMlmAuthCnf, *tpLimMlmAuthCnf;
+
+typedef struct sLimMlmDeauthReq {
+ tSirMacAddr peerMacAddr;
+ uint16_t reasonCode;
+ uint16_t deauthTrigger;
+ uint16_t aid;
+ uint8_t sessionId; /* Added for BT-AMP SUPPORT */
+
+} tLimMlmDeauthReq, *tpLimMlmDeauthReq;
+
+typedef struct sLimMlmDeauthCnf {
+ tSirMacAddr peerMacAddr;
+ tSirResultCodes resultCode;
+ uint16_t deauthTrigger;
+ uint16_t aid;
+ uint8_t sessionId;
+} tLimMlmDeauthCnf, *tpLimMLmDeauthCnf;
+
+typedef struct sLimMlmDeauthInd {
+ tSirMacAddr peerMacAddr;
+ uint16_t reasonCode;
+ uint16_t deauthTrigger;
+ uint16_t aid;
+} tLimMlmDeauthInd, *tpLimMlmDeauthInd;
+
+typedef struct sLimMlmDisassocReq {
+ tSirMacAddr peerMacAddr;
+ uint16_t reasonCode;
+ uint16_t disassocTrigger;
+ uint16_t aid;
+ uint8_t sessionId;
+} tLimMlmDisassocReq, *tpLimMlmDisassocReq;
+
+typedef struct sLimMlmDisassocCnf {
+ tSirMacAddr peerMacAddr;
+ tSirResultCodes resultCode;
+ uint16_t disassocTrigger;
+ uint16_t aid;
+ uint8_t sessionId;
+} tLimMlmDisassocCnf, *tpLimMlmDisassocCnf;
+
+typedef struct sLimMlmDisassocInd {
+ tSirMacAddr peerMacAddr;
+ uint16_t reasonCode;
+ uint16_t disassocTrigger;
+ uint16_t aid;
+ uint8_t sessionId;
+} tLimMlmDisassocInd, *tpLimMlmDisassocInd;
+
+typedef struct sLimMlmPurgeStaReq {
+ tSirMacAddr peerMacAddr;
+ uint16_t aid;
+ uint8_t sessionId; /* Added For BT-AMP Support */
+} tLimMlmPurgeStaReq, *tpLimMlmPurgeStaReq;
+
+typedef struct sLimMlmPurgeStaInd {
+ tSirMacAddr peerMacAddr;
+ uint16_t reasonCode;
+ uint16_t purgeTrigger;
+ uint16_t aid;
+ uint8_t sessionId;
+} tLimMlmPurgeStaInd, *tpLimMlmPurgeStaInd;
+
+typedef struct sLimMlmSetKeysCnf {
+ tSirMacAddr peerMacAddr;
+ uint16_t resultCode;
+ uint16_t aid;
+ uint8_t sessionId;
+} tLimMlmSetKeysCnf, *tpLimMlmSetKeysCnf;
+
+typedef struct sLimMlmResetReq {
+ tSirMacAddr macAddr;
+ uint8_t performCleanup;
+ uint8_t sessionId;
+} tLimMlmResetReq, *tpLimMlmResetReq;
+
+typedef struct sLimMlmResetCnf {
+ tSirMacAddr macAddr;
+ tSirResultCodes resultCode;
+ uint8_t sessionId;
+} tLimMlmResetCnf, *tpLimMlmResetCnf;
+
+typedef struct sLimMlmLinkTestStopReq {
+ tSirMacAddr peerMacAddr;
+ uint8_t sessionId;
+} tLimMlmLinkTestStopReq, *tpLimMlmLinkTestStopReq;
+
+/* Function templates */
+
+bool lim_process_sme_req_messages(tpAniSirGlobal, tpSirMsgQ);
+void lim_process_mlm_req_messages(tpAniSirGlobal, tpSirMsgQ);
+void lim_process_mlm_rsp_messages(tpAniSirGlobal, uint32_t, uint32_t *);
+void lim_process_sme_del_bss_rsp(tpAniSirGlobal, uint32_t, tpPESession);
+
+void lim_get_random_bssid(tpAniSirGlobal pMac, uint8_t *data);
+
+/* Function to handle HT and HT IE CFG parameter intializations */
+void handle_ht_capabilityand_ht_info(struct sAniSirGlobal *pMac,
+ tpPESession psessionEntry);
+
+/* Function to handle CFG parameter updates */
+void lim_handle_cf_gparam_update(tpAniSirGlobal, uint32_t);
+
+void lim_handle_param_update(tpAniSirGlobal pMac, eUpdateIEsType cfgId);
+
+/* Function to apply CFG parameters before join/reassoc/start BSS */
+void lim_apply_configuration(tpAniSirGlobal, tpPESession);
+
+void lim_set_cfg_protection(tpAniSirGlobal pMac, tpPESession pesessionEntry);
+
+/* Function to Initialize MLM state machine on STA */
+void lim_init_mlm(tpAniSirGlobal);
+
+/* Function to cleanup MLM state machine */
+void lim_cleanup_mlm(tpAniSirGlobal);
+
+/* Function to cleanup LMM state machine */
+void lim_cleanup_lmm(tpAniSirGlobal);
+
+/* Management frame handling functions */
+void lim_process_beacon_frame(tpAniSirGlobal, uint8_t *, tpPESession);
+void lim_process_beacon_frame_no_session(tpAniSirGlobal, uint8_t *);
+void lim_process_probe_req_frame(tpAniSirGlobal, uint8_t *, tpPESession);
+void lim_process_probe_rsp_frame(tpAniSirGlobal, uint8_t *, tpPESession);
+void lim_process_probe_rsp_frame_no_session(tpAniSirGlobal, uint8_t *);
+void lim_process_probe_req_frame_multiple_bss(tpAniSirGlobal, uint8_t *,
+ tpPESession);
+
+/* Process Auth frame when we have a session in progress. */
+void lim_process_auth_frame(tpAniSirGlobal, uint8_t *, tpPESession);
+#ifdef WLAN_FEATURE_VOWIFI_11R
+tSirRetStatus lim_process_auth_frame_no_session(tpAniSirGlobal pMac, uint8_t *,
+ void *body);
+#endif
+
+void lim_process_assoc_req_frame(tpAniSirGlobal, uint8_t *, uint8_t, tpPESession);
+void lim_send_mlm_assoc_ind(tpAniSirGlobal pMac, tpDphHashNode pStaDs,
+ tpPESession psessionEntry);
+
+void lim_process_assoc_rsp_frame(tpAniSirGlobal, uint8_t *, uint8_t, tpPESession);
+void lim_process_disassoc_frame(tpAniSirGlobal, uint8_t *, tpPESession);
+void lim_process_deauth_frame(tpAniSirGlobal, uint8_t *, tpPESession);
+void lim_process_action_frame(tpAniSirGlobal, uint8_t *, tpPESession);
+void lim_process_action_frame_no_session(tpAniSirGlobal pMac, uint8_t *pRxMetaInfo);
+
+void lim_populate_p2p_mac_header(tpAniSirGlobal, uint8_t *);
+void lim_populate_mac_header(tpAniSirGlobal, uint8_t *, uint8_t, uint8_t,
+ tSirMacAddr, tSirMacAddr);
+tSirRetStatus lim_send_probe_req_mgmt_frame(tpAniSirGlobal, tSirMacSSid *,
+ tSirMacAddr, uint8_t, tSirMacAddr,
+ uint32_t, uint32_t, uint8_t *);
+void lim_send_probe_rsp_mgmt_frame(tpAniSirGlobal, tSirMacAddr, tpAniSSID, short,
+ uint8_t, tpPESession, uint8_t);
+void lim_send_auth_mgmt_frame(tpAniSirGlobal, tSirMacAuthFrameBody *, tSirMacAddr,
+ uint8_t, tpPESession);
+void lim_send_assoc_req_mgmt_frame(tpAniSirGlobal, tLimMlmAssocReq *, tpPESession);
+void lim_send_reassoc_req_mgmt_frame(tpAniSirGlobal, tLimMlmReassocReq *,
+ tpPESession);
+#ifdef WLAN_FEATURE_VOWIFI_11R
+void lim_send_reassoc_req_with_ft_ies_mgmt_frame(tpAniSirGlobal pMac,
+ tLimMlmReassocReq *pMlmReassocReq,
+ tpPESession psessionEntry);
+#endif
+void lim_send_delts_req_action_frame(tpAniSirGlobal pMac, tSirMacAddr peer,
+ uint8_t wmmTspecPresent,
+ tSirMacTSInfo *pTsinfo,
+ tSirMacTspecIE *pTspecIe,
+ tpPESession psessionEntry);
+void lim_send_addts_req_action_frame(tpAniSirGlobal pMac, tSirMacAddr peerMacAddr,
+ tSirAddtsReqInfo *addts, tpPESession);
+void lim_send_addts_rsp_action_frame(tpAniSirGlobal pMac, tSirMacAddr peerMacAddr,
+ uint16_t statusCode, tSirAddtsReqInfo *addts,
+ tSirMacScheduleIE *pSchedule, tpPESession);
+
+void lim_send_assoc_rsp_mgmt_frame(tpAniSirGlobal, uint16_t, uint16_t, tSirMacAddr,
+ uint8_t, tpDphHashNode pSta, tpPESession);
+
+void lim_send_disassoc_mgmt_frame(tpAniSirGlobal, uint16_t, tSirMacAddr,
+ tpPESession, bool waitForAck);
+void lim_send_deauth_mgmt_frame(tpAniSirGlobal, uint16_t, tSirMacAddr, tpPESession,
+ bool waitForAck);
+
+tSirResultCodes lim_mlm_add_bss(tpAniSirGlobal, tLimMlmStartReq *,
+ tpPESession psessionEntry);
+
+tSirRetStatus lim_send_channel_switch_mgmt_frame(tpAniSirGlobal, tSirMacAddr,
+ uint8_t, uint8_t, uint8_t,
+ tpPESession);
+
+#ifdef WLAN_FEATURE_11AC
+tSirRetStatus lim_send_vht_opmode_notification_frame(tpAniSirGlobal pMac,
+ tSirMacAddr peer, uint8_t nMode,
+ tpPESession psessionEntry);
+tSirRetStatus lim_send_vht_channel_switch_mgmt_frame(tpAniSirGlobal pMac,
+ tSirMacAddr peer,
+ uint8_t nChanWidth,
+ uint8_t nNewChannel,
+ uint8_t ncbMode,
+ tpPESession psessionEntry);
+#endif
+
+#if defined WLAN_FEATURE_VOWIFI
+tSirRetStatus lim_send_neighbor_report_request_frame(tpAniSirGlobal,
+ tpSirMacNeighborReportReq,
+ tSirMacAddr, tpPESession);
+tSirRetStatus lim_send_link_report_action_frame(tpAniSirGlobal, tpSirMacLinkReport,
+ tSirMacAddr, tpPESession);
+tSirRetStatus lim_send_radio_measure_report_action_frame(tpAniSirGlobal, uint8_t,
+ uint8_t,
+ tpSirMacRadioMeasureReport,
+ tSirMacAddr, tpPESession);
+#endif
+
+
+#ifdef FEATURE_WLAN_TDLS
+void lim_init_tdls_data(tpAniSirGlobal, tpPESession);
+tSirRetStatus lim_process_sme_tdls_mgmt_send_req(tpAniSirGlobal pMac,
+ uint32_t *pMsgBuf);
+tSirRetStatus lim_process_sme_tdls_add_sta_req(tpAniSirGlobal pMac,
+ uint32_t *pMsgBuf);
+tSirRetStatus lim_process_sme_tdls_link_establish_req(tpAniSirGlobal pMac,
+ uint32_t *pMsgBuf);
+tSirRetStatus lim_process_sme_tdls_del_sta_req(tpAniSirGlobal pMac,
+ uint32_t *pMsgBuf);
+void lim_send_sme_tdls_delete_all_peer_ind(tpAniSirGlobal pMac,
+ tpPESession psessionEntry);
+void lim_send_sme_mgmt_tx_completion(tpAniSirGlobal pMac, tpPESession psessionEntry,
+ uint32_t txCompleteStatus);
+tSirRetStatus lim_delete_tdls_peers(tpAniSirGlobal pMac,
+ tpPESession psessionEntry);
+CDF_STATUS lim_process_tdls_add_sta_rsp(tpAniSirGlobal pMac, void *msg, tpPESession);
+tSirRetStatus lim_send_tdls_teardown_frame(tpAniSirGlobal pMac,
+ tSirMacAddr peerMac, uint16_t reason,
+ uint8_t responder,
+ tpPESession psessionEntry,
+ uint8_t *addIe, uint16_t addIeLen);
+#endif
+
+/* Algorithms & Link Monitoring related functions */
+/* / Function that handles heartbeat failure */
+void lim_handle_heart_beat_failure(tpAniSirGlobal, tpPESession);
+
+/* / Function that triggers link tear down with AP upon HB failure */
+void lim_tear_down_link_with_ap(tpAniSirGlobal, uint8_t, tSirMacReasonCodes);
+
+/* / Function that processes Max retries interrupt from TFP */
+void limHandleMaxRetriesInterrupt(uint32_t);
+
+/* / Function that processes messages deferred during Learn mode */
+void lim_process_deferred_message_queue(tpAniSirGlobal);
+
+/* / Function that defers the messages received */
+uint32_t lim_defer_msg(tpAniSirGlobal, tSirMsgQ *);
+
+/* / Function that Switches the Channel and sets the CB Mode */
+void lim_set_channel(tpAniSirGlobal pMac, uint8_t channel,
+ uint8_t ch_center_freq_seg0, uint8_t ch_center_freq_seg1,
+ phy_ch_width ch_width, tPowerdBm maxTxPower,
+ uint8_t peSessionId);
+
+
+/* / Function that completes channel scan */
+void lim_complete_mlm_scan(tpAniSirGlobal, tSirResultCodes);
+
+#ifdef ANI_SUPPORT_11H
+/* / Function that sends Measurement Report action frame */
+tSirRetStatus lim_send_meas_report_frame(tpAniSirGlobal, tpSirMacMeasReqActionFrame,
+ tSirMacAddr, tpPESession psessionEntry);
+
+/* / Function that sends TPC Report action frame */
+tSirRetStatus lim_send_tpc_report_frame(tpAniSirGlobal, tpSirMacTpcReqActionFrame,
+ tSirMacAddr, tpPESession psessionEntry);
+#endif
+
+/* / Function that sends TPC Request action frame */
+void lim_send_tpc_request_frame(tpAniSirGlobal, tSirMacAddr,
+ tpPESession psessionEntry);
+
+/* Function(s) to handle responses received from HAL */
+void lim_process_mlm_add_bss_rsp(tpAniSirGlobal pMac, tpSirMsgQ limMsgQ);
+void lim_process_mlm_add_sta_rsp(tpAniSirGlobal pMac, tpSirMsgQ limMsgQt,
+ tpPESession psessionEntry);
+void lim_process_mlm_del_sta_rsp(tpAniSirGlobal pMac, tpSirMsgQ limMsgQ);
+void lim_process_mlm_del_bss_rsp(tpAniSirGlobal pMac, tpSirMsgQ limMsgQ,
+ tpPESession);
+void lim_process_sta_mlm_add_sta_rsp(tpAniSirGlobal pMac, tpSirMsgQ limMsgQ,
+ tpPESession psessionEntry);
+void lim_process_sta_mlm_del_sta_rsp(tpAniSirGlobal pMac, tpSirMsgQ limMsgQ,
+ tpPESession psessionEntry);
+void lim_process_sta_mlm_del_bss_rsp(tpAniSirGlobal pMac, tpSirMsgQ limMsgQ,
+ tpPESession psessionEntry);
+void lim_process_mlm_set_sta_key_rsp(tpAniSirGlobal pMac, tpSirMsgQ limMsgQ);
+void lim_process_mlm_set_bss_key_rsp(tpAniSirGlobal pMac, tpSirMsgQ limMsgQ);
+
+/* Function to process WMA_SWITCH_CHANNEL_RSP message */
+void lim_process_switch_channel_rsp(tpAniSirGlobal pMac, void *);
+
+void lim_covert_channel_scan_type(tpAniSirGlobal pMac, uint8_t channelNum,
+ bool passiveToActive);
+void lim_set_dfs_channel_list(tpAniSirGlobal pMac, uint8_t channelNum,
+ tSirDFSChannelList *dfsChannelList);
+void limContinueChannelLearn(tpAniSirGlobal);
+/* WLAN_SUSPEND_LINK Related */
+uint8_t lim_is_link_suspended(tpAniSirGlobal pMac);
+/* end WLAN_SUSPEND_LINK Related */
+
+#ifdef WLAN_FEATURE_11W
+/* 11w send SA query request action frame */
+tSirRetStatus lim_send_sa_query_request_frame(tpAniSirGlobal pMac, uint8_t *transId,
+ tSirMacAddr peer,
+ tpPESession psessionEntry);
+/* 11w SA query request action frame handler */
+tSirRetStatus lim_send_sa_query_response_frame(tpAniSirGlobal pMac,
+ uint8_t *transId, tSirMacAddr peer,
+ tpPESession psessionEntry);
+#endif
+
+/* Inline functions */
+
+/**
+ * lim_post_sme_message()
+ *
+ ***FUNCTION:
+ * This function is called by limProcessMlmMessages(). In this
+ * function MLM sub-module invokes MLM ind/cnf primitives.
+ *
+ ***LOGIC:
+ * Initially MLM makes an SME function call to invoke MLM ind/cnf
+ * primitive. In future this can be enhanced to 'post' messages to SME.
+ *
+ ***ASSUMPTIONS:
+ * NA
+ *
+ ***NOTE:
+ * NA
+ *
+ * @param pMac Pointer to Global MAC structure
+ * @param msgType Indicates the MLM primitive message type
+ * @param *pMsgBuf A pointer to the MLM message buffer
+ *
+ * @return None
+ */
+static inline void
+lim_post_sme_message(tpAniSirGlobal pMac, uint32_t msgType, uint32_t *pMsgBuf)
+{
+ tSirMsgQ msg;
+
+ if (pMsgBuf == NULL) {
+ lim_log(pMac, LOGE, FL("Buffer is Pointing to NULL"));
+ return;
+ }
+
+ msg.type = (uint16_t) msgType;
+ msg.bodyptr = pMsgBuf;
+ msg.bodyval = 0;
+ if (msgType > eWNI_SME_MSG_TYPES_BEGIN)
+ lim_process_sme_req_messages(pMac, &msg);
+ else
+ lim_process_mlm_rsp_messages(pMac, msgType, pMsgBuf);
+} /*** end lim_post_sme_message() ***/
+
+/**
+ * lim_post_mlm_message()
+ *
+ ***FUNCTION:
+ * This function is called by limProcessSmeMessages(). In this
+ * function SME invokes MLME primitives.
+ *
+ ***PARAMS:
+ *
+ ***LOGIC:
+ * Initially SME makes an MLM function call to invoke MLM primitive.
+ * In future this can be enhanced to 'post' messages to MLM.
+ *
+ ***ASSUMPTIONS:
+ * NA
+ *
+ ***NOTE:
+ * NA
+ *
+ * @param pMac Pointer to Global MAC structure
+ * @param msgType Indicates the MLM primitive message type
+ * @param *pMsgBuf A pointer to the MLM message buffer
+ *
+ * @return None
+ */
+static inline void
+lim_post_mlm_message(tpAniSirGlobal pMac, uint32_t msgType, uint32_t *pMsgBuf)
+{
+
+ tSirMsgQ msg;
+ if (pMsgBuf == NULL) {
+ lim_log(pMac, LOGE, FL("Buffer is Pointing to NULL"));
+ return;
+ }
+ msg.type = (uint16_t) msgType;
+ msg.bodyptr = pMsgBuf;
+ msg.bodyval = 0;
+ lim_process_mlm_req_messages(pMac, &msg);
+} /*** end lim_post_mlm_message() ***/
+
+/**
+ * lim_get_current_scan_channel()
+ *
+ ***FUNCTION:
+ * This function is called in various places to get current channel
+ * number being scanned.
+ *
+ ***PARAMS:
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ * NA
+ *
+ ***NOTE:
+ * NA
+ *
+ * @param pMac Pointer to Global MAC structure
+ * @return Channel number
+ */
+static inline uint8_t lim_get_current_scan_channel(tpAniSirGlobal pMac)
+{
+ uint8_t *pChanNum =
+ pMac->lim.gpLimMlmScanReq->channelList.channelNumber;
+
+ return *(pChanNum + pMac->lim.gLimCurrentScanChannelId);
+} /*** end lim_get_current_scan_channel() ***/
+
+/**
+ * lim_get_ielen_from_bss_description()
+ *
+ ***FUNCTION:
+ * This function is called in various places to get IE length
+ * from tSirBssDescription structure
+ * number being scanned.
+ *
+ ***PARAMS:
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ * NA
+ *
+ ***NOTE:
+ * NA
+ *
+ * @param pBssDescr
+ * @return Total IE length
+ */
+
+static inline uint16_t
+lim_get_ielen_from_bss_description(tpSirBssDescription pBssDescr)
+{
+ uint16_t ielen;
+
+ if (!pBssDescr)
+ return 0;
+
+ /*
+ * Length of BSS desription is without length of
+ * length itself and length of pointer
+ * that holds ieFields
+ *
+ * <------------sizeof(tSirBssDescription)-------------------->
+ * +--------+---------------------------------+---------------+
+ * | length | other fields | pointer to IEs|
+ * +--------+---------------------------------+---------------+
+ * ^
+ * ieFields
+ */
+
+ ielen = (uint16_t)(pBssDescr->length + sizeof(pBssDescr->length) -
+ GET_FIELD_OFFSET(tSirBssDescription, ieFields));
+
+ return ielen;
+} /*** end lim_get_ielen_from_bss_description() ***/
+
+/**
+ * lim_send_beacon_ind()
+ *
+ ***FUNCTION:
+ * This function is called to send the beacon indication
+ * number being scanned.
+ *
+ ***PARAMS:
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ */
+
+void lim_send_beacon_ind(tpAniSirGlobal pMac, tpPESession psessionEntry);
+
+void
+lim_send_vdev_restart(tpAniSirGlobal pMac, tpPESession psessionEntry,
+ uint8_t sessionId);
+
+void lim_get_wpspbc_sessions(tpAniSirGlobal pMac, uint8_t *addr, uint8_t *uuid_e,
+ eWPSPBCOverlap *overlap, tpPESession psessionEntry);
+void limWPSPBCTimeout(tpAniSirGlobal pMac, tpPESession psessionEntry);
+void lim_wpspbc_close(tpAniSirGlobal pMac, tpPESession psessionEntry);
+void lim_remove_pbc_sessions(tpAniSirGlobal pMac, tSirMacAddr pRemoveMac,
+ tpPESession psessionEntry);
+
+#define LIM_WPS_OVERLAP_TIMER_MS 10000
+void
+lim_change_channel_with_callback(tpAniSirGlobal pMac, uint8_t newChannel,
+ CHANGE_CHANNEL_CALLBACK callback,
+ uint32_t *cbdata, tpPESession psessionEntry);
+
+void lim_send_sme_mgmt_frame_ind(tpAniSirGlobal pMac, uint8_t frameType,
+ uint8_t *frame, uint32_t frameLen,
+ uint16_t sessionId, uint32_t rxChan,
+ tpPESession psessionEntry, int8_t rxRssi);
+void lim_process_remain_on_chn_timeout(tpAniSirGlobal pMac);
+void lim_process_insert_single_shot_noa_timeout(tpAniSirGlobal pMac);
+void lim_convert_active_channel_to_passive_channel(tpAniSirGlobal pMac);
+void lim_send_p2p_action_frame(tpAniSirGlobal pMac, tpSirMsgQ pMsg);
+void lim_abort_remain_on_chan(tpAniSirGlobal pMac, uint8_t sessionId,
+ uint32_t scan_id);
+tSirRetStatus __lim_process_sme_no_a_update(tpAniSirGlobal pMac, uint32_t *pMsgBuf);
+void lim_process_regd_defd_sme_req_after_noa_start(tpAniSirGlobal pMac);
+
+void lim_process_disassoc_ack_timeout(tpAniSirGlobal pMac);
+void lim_process_deauth_ack_timeout(tpAniSirGlobal pMac);
+CDF_STATUS lim_send_disassoc_cnf(tpAniSirGlobal pMac);
+CDF_STATUS lim_send_deauth_cnf(tpAniSirGlobal pMac);
+CDF_STATUS lim_disassoc_tx_complete_cnf(tpAniSirGlobal pMac,
+ uint32_t txCompleteSuccess);
+CDF_STATUS lim_deauth_tx_complete_cnf(tpAniSirGlobal pMac,
+ uint32_t txCompleteSuccess);
+
+#ifdef WLAN_FEATURE_VOWIFI_11R
+typedef struct sSetLinkCbackParams {
+ void *cbackDataPtr;
+} tSetLinkCbackParams;
+#endif
+
+void lim_process_rx_scan_event(tpAniSirGlobal mac, void *buf);
+
+int lim_process_remain_on_chnl_req(tpAniSirGlobal pMac, uint32_t *pMsg);
+void lim_remain_on_chn_rsp(tpAniSirGlobal pMac, CDF_STATUS status, uint32_t *data);
+
+/* / Bit value data structure */
+typedef enum sHalBitVal /* For Bit operations */
+{
+ eHAL_CLEAR,
+ eHAL_SET
+} tHalBitVal;
+
+enum {
+ eHI_PRI,
+ ePROT,
+ eDBG
+};
+
+#endif /* __LIM_TYPES_H */
diff --git a/core/mac/src/pe/lim/lim_utils.c b/core/mac/src/pe/lim/lim_utils.c
new file mode 100644
index 0000000..d34c2a3
--- /dev/null
+++ b/core/mac/src/pe/lim/lim_utils.c
@@ -0,0 +1,7145 @@
+/*
+ * Copyright (c) 2011-2015 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_utils.cc contains the utility functions
+ * LIM uses.
+ * Author: Chandra Modumudi
+ * Date: 02/13/02
+ * History:-
+ * Date Modified by Modification Information
+ * --------------------------------------------------------------------
+ */
+
+#include "sch_api.h"
+#include "lim_utils.h"
+#include "lim_types.h"
+#include "lim_security_utils.h"
+#include "lim_prop_exts_utils.h"
+#include "lim_send_messages.h"
+#include "lim_ser_des_utils.h"
+#include "lim_admit_control.h"
+#include "lim_sta_hash_api.h"
+#include "dot11f.h"
+#include "dot11fdefs.h"
+#include "wmm_apsd.h"
+#include "lim_trace.h"
+#ifdef FEATURE_WLAN_DIAG_SUPPORT
+#include "host_diag_core_event.h"
+#endif /* FEATURE_WLAN_DIAG_SUPPORT */
+#include "lim_ibss_peer_mgmt.h"
+#include "lim_session_utils.h"
+#ifdef WLAN_FEATURE_VOWIFI_11R
+#include "lim_ft_defs.h"
+#endif
+#include "lim_session.h"
+#include "cds_reg_service.h"
+
+#ifdef WLAN_FEATURE_11W
+#include "wni_cfg.h"
+#endif
+#define ASCII_SPACE_CHARACTER 0x20
+
+#define SUCCESS 1
+
+#define MAX_BA_WINDOW_SIZE_FOR_CISCO 25
+
+/** -------------------------------------------------------------
+ \fn lim_delete_dialogue_token_list
+ \brief deletes the complete lim dialogue token linked list.
+ \param tpAniSirGlobal pMac
+ \return None
+ -------------------------------------------------------------*/
+void lim_delete_dialogue_token_list(tpAniSirGlobal pMac)
+{
+ tpDialogueToken pCurrNode = pMac->lim.pDialogueTokenHead;
+
+ while (NULL != pMac->lim.pDialogueTokenHead) {
+ pCurrNode = pMac->lim.pDialogueTokenHead;
+ pMac->lim.pDialogueTokenHead =
+ pMac->lim.pDialogueTokenHead->next;
+ cdf_mem_free(pCurrNode);
+ pCurrNode = NULL;
+ }
+ pMac->lim.pDialogueTokenTail = NULL;
+}
+
+char *lim_dot11_reason_str(uint16_t reasonCode)
+{
+ switch (reasonCode) {
+ case 0:
+ return " ";
+ CASE_RETURN_STRING(eSIR_MAC_UNSPEC_FAILURE_REASON);
+ CASE_RETURN_STRING(eSIR_MAC_PREV_AUTH_NOT_VALID_REASON);
+ CASE_RETURN_STRING(eSIR_MAC_DEAUTH_LEAVING_BSS_REASON);
+ CASE_RETURN_STRING(eSIR_MAC_DISASSOC_DUE_TO_INACTIVITY_REASON);
+ CASE_RETURN_STRING(eSIR_MAC_DISASSOC_DUE_TO_DISABILITY_REASON);
+ CASE_RETURN_STRING
+ (eSIR_MAC_CLASS2_FRAME_FROM_NON_AUTH_STA_REASON);
+ CASE_RETURN_STRING
+ (eSIR_MAC_CLASS3_FRAME_FROM_NON_ASSOC_STA_REASON);
+ CASE_RETURN_STRING(eSIR_MAC_DISASSOC_LEAVING_BSS_REASON);
+ CASE_RETURN_STRING(eSIR_MAC_STA_NOT_PRE_AUTHENTICATED_REASON);
+ CASE_RETURN_STRING(eSIR_MAC_PWR_CAPABILITY_BAD_REASON);
+ CASE_RETURN_STRING(eSIR_MAC_SPRTD_CHANNELS_BAD_REASON);
+
+ CASE_RETURN_STRING(eSIR_MAC_INVALID_IE_REASON);
+ CASE_RETURN_STRING(eSIR_MAC_MIC_FAILURE_REASON);
+ CASE_RETURN_STRING(eSIR_MAC_4WAY_HANDSHAKE_TIMEOUT_REASON);
+ CASE_RETURN_STRING(eSIR_MAC_GR_KEY_UPDATE_TIMEOUT_REASON);
+ CASE_RETURN_STRING(eSIR_MAC_RSN_IE_MISMATCH_REASON);
+
+ CASE_RETURN_STRING(eSIR_MAC_INVALID_MC_CIPHER_REASON);
+ CASE_RETURN_STRING(eSIR_MAC_INVALID_UC_CIPHER_REASON);
+ CASE_RETURN_STRING(eSIR_MAC_INVALID_AKMP_REASON);
+ CASE_RETURN_STRING(eSIR_MAC_UNSUPPORTED_RSN_IE_VER_REASON);
+ CASE_RETURN_STRING(eSIR_MAC_INVALID_RSN_CAPABILITIES_REASON);
+ CASE_RETURN_STRING(eSIR_MAC_1X_AUTH_FAILURE_REASON);
+ CASE_RETURN_STRING(eSIR_MAC_CIPHER_SUITE_REJECTED_REASON);
+#ifdef FEATURE_WLAN_TDLS
+ CASE_RETURN_STRING(eSIR_MAC_TDLS_TEARDOWN_PEER_UNREACHABLE);
+ CASE_RETURN_STRING(eSIR_MAC_TDLS_TEARDOWN_UNSPEC_REASON);
+#endif
+ /* Reserved 27 - 30 */
+#ifdef WLAN_FEATURE_11W
+ CASE_RETURN_STRING
+ (eSIR_MAC_ROBUST_MGMT_FRAMES_POLICY_VIOLATION);
+#endif
+ CASE_RETURN_STRING(eSIR_MAC_QOS_UNSPECIFIED_REASON);
+ CASE_RETURN_STRING(eSIR_MAC_QAP_NO_BANDWIDTH_REASON);
+ CASE_RETURN_STRING(eSIR_MAC_XS_UNACKED_FRAMES_REASON);
+ CASE_RETURN_STRING(eSIR_MAC_BAD_TXOP_USE_REASON);
+ CASE_RETURN_STRING(eSIR_MAC_PEER_STA_REQ_LEAVING_BSS_REASON);
+ CASE_RETURN_STRING(eSIR_MAC_PEER_REJECT_MECHANISIM_REASON);
+ CASE_RETURN_STRING(eSIR_MAC_MECHANISM_NOT_SETUP_REASON);
+
+ CASE_RETURN_STRING(eSIR_MAC_PEER_TIMEDOUT_REASON);
+ CASE_RETURN_STRING(eSIR_MAC_CIPHER_NOT_SUPPORTED_REASON);
+ CASE_RETURN_STRING(eSIR_MAC_DISASSOC_DUE_TO_FTHANDOFF_REASON);
+ /* Reserved 47 - 65535 */
+ default:
+ return "Unknown";
+ }
+}
+
+char *lim_mlm_state_str(tLimMlmStates state)
+{
+ switch (state) {
+ case eLIM_MLM_OFFLINE_STATE:
+ return "eLIM_MLM_OFFLINE_STATE";
+ case eLIM_MLM_IDLE_STATE:
+ return "eLIM_MLM_IDLE_STATE";
+ case eLIM_MLM_WT_PROBE_RESP_STATE:
+ return "eLIM_MLM_WT_PROBE_RESP_STATE";
+ case eLIM_MLM_PASSIVE_SCAN_STATE:
+ return "eLIM_MLM_PASSIVE_SCAN_STATE";
+ case eLIM_MLM_WT_JOIN_BEACON_STATE:
+ return "eLIM_MLM_WT_JOIN_BEACON_STATE";
+ case eLIM_MLM_JOINED_STATE:
+ return "eLIM_MLM_JOINED_STATE";
+ case eLIM_MLM_BSS_STARTED_STATE:
+ return "eLIM_MLM_BSS_STARTED_STATE";
+ case eLIM_MLM_WT_AUTH_FRAME2_STATE:
+ return "eLIM_MLM_WT_AUTH_FRAME2_STATE";
+ case eLIM_MLM_WT_AUTH_FRAME3_STATE:
+ return "eLIM_MLM_WT_AUTH_FRAME3_STATE";
+ case eLIM_MLM_WT_AUTH_FRAME4_STATE:
+ return "eLIM_MLM_WT_AUTH_FRAME4_STATE";
+ case eLIM_MLM_AUTH_RSP_TIMEOUT_STATE:
+ return "eLIM_MLM_AUTH_RSP_TIMEOUT_STATE";
+ case eLIM_MLM_AUTHENTICATED_STATE:
+ return "eLIM_MLM_AUTHENTICATED_STATE";
+ case eLIM_MLM_WT_ASSOC_RSP_STATE:
+ return "eLIM_MLM_WT_ASSOC_RSP_STATE";
+ case eLIM_MLM_WT_REASSOC_RSP_STATE:
+ return "eLIM_MLM_WT_REASSOC_RSP_STATE";
+ case eLIM_MLM_WT_FT_REASSOC_RSP_STATE:
+ return "eLIM_MLM_WT_FT_REASSOC_RSP_STATE";
+ case eLIM_MLM_WT_DEL_STA_RSP_STATE:
+ return "eLIM_MLM_WT_DEL_STA_RSP_STATE";
+ case eLIM_MLM_WT_DEL_BSS_RSP_STATE:
+ return "eLIM_MLM_WT_DEL_BSS_RSP_STATE";
+ case eLIM_MLM_WT_ADD_STA_RSP_STATE:
+ return "eLIM_MLM_WT_ADD_STA_RSP_STATE";
+ case eLIM_MLM_WT_ADD_BSS_RSP_STATE:
+ return "eLIM_MLM_WT_ADD_BSS_RSP_STATE";
+ case eLIM_MLM_REASSOCIATED_STATE:
+ return "eLIM_MLM_REASSOCIATED_STATE";
+ case eLIM_MLM_LINK_ESTABLISHED_STATE:
+ return "eLIM_MLM_LINK_ESTABLISHED_STATE";
+ case eLIM_MLM_WT_ASSOC_CNF_STATE:
+ return "eLIM_MLM_WT_ASSOC_CNF_STATE";
+ case eLIM_MLM_WT_ADD_BSS_RSP_ASSOC_STATE:
+ return "eLIM_MLM_WT_ADD_BSS_RSP_ASSOC_STATE";
+ case eLIM_MLM_WT_ADD_BSS_RSP_REASSOC_STATE:
+ return "eLIM_MLM_WT_ADD_BSS_RSP_REASSOC_STATE";
+ case eLIM_MLM_WT_ADD_BSS_RSP_FT_REASSOC_STATE:
+ return "eLIM_MLM_WT_ADD_BSS_RSP_FT_REASSOC_STATE";
+ case eLIM_MLM_WT_ASSOC_DEL_STA_RSP_STATE:
+ return "eLIM_MLM_WT_ASSOC_DEL_STA_RSP_STATE";
+ case eLIM_MLM_WT_SET_BSS_KEY_STATE:
+ return "eLIM_MLM_WT_SET_BSS_KEY_STATE";
+ case eLIM_MLM_WT_SET_STA_KEY_STATE:
+ return "eLIM_MLM_WT_SET_STA_KEY_STATE";
+ default:
+ return "INVALID MLM state";
+ }
+}
+
+void
+lim_print_mlm_state(tpAniSirGlobal pMac, uint16_t logLevel, tLimMlmStates state)
+{
+ lim_log(pMac, logLevel, lim_mlm_state_str(state));
+}
+
+char *lim_sme_state_str(tLimSmeStates state)
+{
+ switch (state) {
+ case eLIM_SME_OFFLINE_STATE:
+ return "eLIM_SME_OFFLINE_STATE";
+ case eLIM_SME_IDLE_STATE:
+ return "eLIM_SME_OFFLINE_STATE";
+ case eLIM_SME_SUSPEND_STATE:
+ return "eLIM_SME_SUSPEND_STATE";
+ case eLIM_SME_WT_SCAN_STATE:
+ return "eLIM_SME_WT_SCAN_STATE";
+ case eLIM_SME_WT_JOIN_STATE:
+ return "eLIM_SME_WT_JOIN_STATE";
+ case eLIM_SME_WT_AUTH_STATE:
+ return "eLIM_SME_WT_AUTH_STATE";
+ case eLIM_SME_WT_ASSOC_STATE:
+ return "eLIM_SME_WT_ASSOC_STATE";
+ case eLIM_SME_WT_REASSOC_STATE:
+ return "eLIM_SME_WT_REASSOC_STATE";
+ case eLIM_SME_WT_REASSOC_LINK_FAIL_STATE:
+ return "eLIM_SME_WT_REASSOC_LINK_FAIL_STATE";
+ case eLIM_SME_JOIN_FAILURE_STATE:
+ return "eLIM_SME_JOIN_FAILURE_STATE";
+ case eLIM_SME_ASSOCIATED_STATE:
+ return "eLIM_SME_ASSOCIATED_STATE";
+ case eLIM_SME_REASSOCIATED_STATE:
+ return "eLIM_SME_REASSOCIATED_STATE";
+ case eLIM_SME_LINK_EST_STATE:
+ return "eLIM_SME_LINK_EST_STATE";
+ case eLIM_SME_LINK_EST_WT_SCAN_STATE:
+ return "eLIM_SME_LINK_EST_WT_SCAN_STATE";
+ case eLIM_SME_WT_PRE_AUTH_STATE:
+ return "eLIM_SME_WT_PRE_AUTH_STATE";
+ case eLIM_SME_WT_DISASSOC_STATE:
+ return "eLIM_SME_WT_DISASSOC_STATE";
+ case eLIM_SME_WT_DEAUTH_STATE:
+ return "eLIM_SME_WT_DEAUTH_STATE";
+ case eLIM_SME_WT_START_BSS_STATE:
+ return "eLIM_SME_WT_START_BSS_STATE";
+ case eLIM_SME_WT_STOP_BSS_STATE:
+ return "eLIM_SME_WT_STOP_BSS_STATE";
+ case eLIM_SME_NORMAL_STATE:
+ return "eLIM_SME_NORMAL_STATE";
+ case eLIM_SME_CHANNEL_SCAN_STATE:
+ return "eLIM_SME_CHANNEL_SCAN_STATE";
+ case eLIM_SME_NORMAL_CHANNEL_SCAN_STATE:
+ return "eLIM_SME_NORMAL_CHANNEL_SCAN_STATE";
+ default:
+ return "INVALID SME STATE";
+ }
+}
+
+void
+lim_print_sme_state(tpAniSirGlobal pMac, uint16_t logLevel, tLimSmeStates state)
+{
+ lim_log(pMac, logLevel, lim_sme_state_str(state));
+}
+
+char *lim_msg_str(uint32_t msgType)
+{
+#ifdef FIXME_GEN6
+ switch (msgType) {
+ case eWNI_SME_SYS_READY_IND:
+ return "eWNI_SME_SYS_READY_IND";
+ case eWNI_SME_SCAN_REQ:
+ return "eWNI_SME_SCAN_REQ";
+#ifdef FEATURE_OEM_DATA_SUPPORT
+ case eWNI_SME_OEM_DATA_REQ:
+ return "eWNI_SME_OEM_DATA_REQ";
+ case eWNI_SME_OEM_DATA_RSP:
+ return "eWNI_SME_OEM_DATA_RSP";
+#endif
+ case eWNI_SME_SCAN_RSP:
+ return "eWNI_SME_SCAN_RSP";
+ case eWNI_SME_JOIN_REQ:
+ return "eWNI_SME_JOIN_REQ";
+ case eWNI_SME_JOIN_RSP:
+ return "eWNI_SME_JOIN_RSP";
+ case eWNI_SME_SETCONTEXT_REQ:
+ return "eWNI_SME_SETCONTEXT_REQ";
+ case eWNI_SME_SETCONTEXT_RSP:
+ return "eWNI_SME_SETCONTEXT_RSP";
+ case eWNI_SME_REASSOC_REQ:
+ return "eWNI_SME_REASSOC_REQ";
+ case eWNI_SME_REASSOC_RSP:
+ return "eWNI_SME_REASSOC_RSP";
+ case eWNI_SME_DISASSOC_REQ:
+ return "eWNI_SME_DISASSOC_REQ";
+ case eWNI_SME_DISASSOC_RSP:
+ return "eWNI_SME_DISASSOC_RSP";
+ case eWNI_SME_DISASSOC_IND:
+ return "eWNI_SME_DISASSOC_IND";
+ case eWNI_SME_DISASSOC_CNF:
+ return "eWNI_SME_DISASSOC_CNF";
+ case eWNI_SME_DEAUTH_REQ:
+ return "eWNI_SME_DEAUTH_REQ";
+ case eWNI_SME_DEAUTH_RSP:
+ return "eWNI_SME_DEAUTH_RSP";
+ case eWNI_SME_DEAUTH_IND:
+ return "eWNI_SME_DEAUTH_IND";
+ case eWNI_SME_WM_STATUS_CHANGE_NTF:
+ return "eWNI_SME_WM_STATUS_CHANGE_NTF";
+ case eWNI_SME_START_BSS_REQ:
+ return "eWNI_SME_START_BSS_REQ";
+ case eWNI_SME_START_BSS_RSP:
+ return "eWNI_SME_START_BSS_RSP";
+ case eWNI_SME_ASSOC_IND:
+ return "eWNI_SME_ASSOC_IND";
+ case eWNI_SME_ASSOC_CNF:
+ return "eWNI_SME_ASSOC_CNF";
+ case eWNI_SME_SWITCH_CHL_IND:
+ return "eWNI_SME_SWITCH_CHL_IND";
+ case eWNI_SME_STOP_BSS_REQ:
+ return "eWNI_SME_STOP_BSS_REQ";
+ case eWNI_SME_STOP_BSS_RSP:
+ return "eWNI_SME_STOP_BSS_RSP";
+ case eWNI_SME_NEIGHBOR_BSS_IND:
+ return "eWNI_SME_NEIGHBOR_BSS_IND";
+ case eWNI_SME_DEAUTH_CNF:
+ return "eWNI_SME_DEAUTH_CNF";
+ case eWNI_SME_ADDTS_REQ:
+ return "eWNI_SME_ADDTS_REQ";
+ case eWNI_SME_ADDTS_RSP:
+ return "eWNI_SME_ADDTS_RSP";
+ case eWNI_SME_DELTS_REQ:
+ return "eWNI_SME_DELTS_REQ";
+ case eWNI_SME_DELTS_RSP:
+ return "eWNI_SME_DELTS_RSP";
+ case eWNI_SME_DELTS_IND:
+ return "eWNI_SME_DELTS_IND";
+ case WMA_SUSPEND_ACTIVITY_RSP:
+ return "WMA_SUSPEND_ACTIVITY_RSP";
+ case SIR_LIM_RETRY_INTERRUPT_MSG:
+ return "SIR_LIM_RETRY_INTERRUPT_MSG";
+ case SIR_BB_XPORT_MGMT_MSG:
+ return "SIR_BB_XPORT_MGMT_MSG";
+ case SIR_LIM_INV_KEY_INTERRUPT_MSG:
+ return "SIR_LIM_INV_KEY_INTERRUPT_MSG";
+ case SIR_LIM_KEY_ID_INTERRUPT_MSG:
+ return "SIR_LIM_KEY_ID_INTERRUPT_MSG";
+ case SIR_LIM_REPLAY_THRES_INTERRUPT_MSG:
+ return "SIR_LIM_REPLAY_THRES_INTERRUPT_MSG";
+ case SIR_LIM_JOIN_FAIL_TIMEOUT:
+ return "SIR_LIM_JOIN_FAIL_TIMEOUT";
+ case SIR_LIM_AUTH_FAIL_TIMEOUT:
+ return "SIR_LIM_AUTH_FAIL_TIMEOUT";
+ case SIR_LIM_AUTH_RSP_TIMEOUT:
+ return "SIR_LIM_AUTH_RSP_TIMEOUT";
+ case SIR_LIM_ASSOC_FAIL_TIMEOUT:
+ return "SIR_LIM_ASSOC_FAIL_TIMEOUT";
+ case SIR_LIM_REASSOC_FAIL_TIMEOUT:
+ return "SIR_LIM_REASSOC_FAIL_TIMEOUT";
+ case SIR_LIM_HEART_BEAT_TIMEOUT:
+ return "SIR_LIM_HEART_BEAT_TIMEOUT";
+ case SIR_LIM_ADDTS_RSP_TIMEOUT:
+ return "SIR_LIM_ADDTS_RSP_TIMEOUT";
+ case SIR_LIM_LINK_TEST_DURATION_TIMEOUT:
+ return "SIR_LIM_LINK_TEST_DURATION_TIMEOUT";
+ case SIR_LIM_HASH_MISS_THRES_TIMEOUT:
+ return "SIR_LIM_HASH_MISS_THRES_TIMEOUT";
+ case SIR_LIM_UPDATE_OLBC_CACHEL_TIMEOUT:
+ return "SIR_LIM_UPDATE_OLBC_CACHEL_TIMEOUT";
+ case SIR_LIM_CNF_WAIT_TIMEOUT:
+ return "SIR_LIM_CNF_WAIT_TIMEOUT";
+ case SIR_LIM_RADAR_DETECT_IND:
+ return "SIR_LIM_RADAR_DETECT_IND";
+#ifdef WLAN_FEATURE_VOWIFI_11R
+ case SIR_LIM_FT_PREAUTH_RSP_TIMEOUT:
+ return "SIR_LIM_FT_PREAUTH_RSP_TIMEOUT";
+#endif
+
+ case WNI_CFG_PARAM_UPDATE_IND:
+ return "WNI_CFG_PARAM_UPDATE_IND";
+ case WNI_CFG_DNLD_REQ:
+ return "WNI_CFG_DNLD_REQ";
+ case WNI_CFG_DNLD_CNF:
+ return "WNI_CFG_DNLD_CNF";
+ case WNI_CFG_GET_RSP:
+ return "WNI_CFG_GET_RSP";
+ case WNI_CFG_SET_CNF:
+ return "WNI_CFG_SET_CNF";
+ case WNI_CFG_GET_ATTRIB_RSP:
+ return "WNI_CFG_GET_ATTRIB_RSP";
+ case WNI_CFG_ADD_GRP_ADDR_CNF:
+ return "WNI_CFG_ADD_GRP_ADDR_CNF";
+ case WNI_CFG_DEL_GRP_ADDR_CNF:
+ return "WNI_CFG_DEL_GRP_ADDR_CNF";
+ case ANI_CFG_GET_RADIO_STAT_RSP:
+ return "ANI_CFG_GET_RADIO_STAT_RSP";
+ case ANI_CFG_GET_PER_STA_STAT_RSP:
+ return "ANI_CFG_GET_PER_STA_STAT_RSP";
+ case ANI_CFG_GET_AGG_STA_STAT_RSP:
+ return "ANI_CFG_GET_AGG_STA_STAT_RSP";
+ case ANI_CFG_CLEAR_STAT_RSP:
+ return "ANI_CFG_CLEAR_STAT_RSP";
+ case WNI_CFG_DNLD_RSP:
+ return "WNI_CFG_DNLD_RSP";
+ case WNI_CFG_GET_REQ:
+ return "WNI_CFG_GET_REQ";
+ case WNI_CFG_SET_REQ:
+ return "WNI_CFG_SET_REQ";
+ case WNI_CFG_SET_REQ_NO_RSP:
+ return "WNI_CFG_SET_REQ_NO_RSP";
+ case eWNI_PMC_ENTER_IMPS_RSP:
+ return "eWNI_PMC_ENTER_IMPS_RSP";
+ case eWNI_PMC_EXIT_IMPS_RSP:
+ return "eWNI_PMC_EXIT_IMPS_RSP";
+ case eWNI_PMC_ENTER_BMPS_RSP:
+ return "eWNI_PMC_ENTER_BMPS_RSP";
+ case eWNI_PMC_EXIT_BMPS_RSP:
+ return "eWNI_PMC_EXIT_BMPS_RSP";
+ case eWNI_PMC_EXIT_BMPS_IND:
+ return "eWNI_PMC_EXIT_BMPS_IND";
+ case eWNI_SME_SET_BCN_FILTER_REQ:
+ return "eWNI_SME_SET_BCN_FILTER_REQ";
+#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
+ case eWNI_SME_GET_TSM_STATS_REQ:
+ return "eWNI_SME_GET_TSM_STATS_REQ";
+ case eWNI_SME_GET_TSM_STATS_RSP:
+ return "eWNI_SME_GET_TSM_STATS_RSP";
+#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
+ case eWNI_SME_CSA_OFFLOAD_EVENT:
+ return "eWNI_SME_CSA_OFFLOAD_EVENT";
+ case eWNI_SME_SET_HW_MODE_REQ:
+ return "eWNI_SME_SET_HW_MODE_REQ";
+ case eWNI_SME_SET_HW_MODE_RESP:
+ return "eWNI_SME_SET_HW_MODE_RESP";
+ case eWNI_SME_HW_MODE_TRANS_IND:
+ return "eWNI_SME_HW_MODE_TRANS_IND";
+ default:
+ return "INVALID SME message";
+ }
+#endif
+ return "";
+}
+
+char *lim_result_code_str(tSirResultCodes resultCode)
+{
+ switch (resultCode) {
+ case eSIR_SME_SUCCESS:
+ return "eSIR_SME_SUCCESS";
+ case eSIR_LOGP_EXCEPTION:
+ return "eSIR_LOGP_EXCEPTION";
+ case eSIR_SME_INVALID_PARAMETERS:
+ return "eSIR_SME_INVALID_PARAMETERS";
+ case eSIR_SME_UNEXPECTED_REQ_RESULT_CODE:
+ return "eSIR_SME_UNEXPECTED_REQ_RESULT_CODE";
+ case eSIR_SME_RESOURCES_UNAVAILABLE:
+ return "eSIR_SME_RESOURCES_UNAVAILABLE";
+ case eSIR_SME_SCAN_FAILED:
+ return "eSIR_SME_SCAN_FAILED";
+ case eSIR_SME_BSS_ALREADY_STARTED_OR_JOINED:
+ return "eSIR_SME_BSS_ALREADY_STARTED_OR_JOINED";
+ case eSIR_SME_LOST_LINK_WITH_PEER_RESULT_CODE:
+ return "eSIR_SME_LOST_LINK_WITH_PEER_RESULT_CODE";
+ case eSIR_SME_REFUSED:
+ return "eSIR_SME_REFUSED";
+ case eSIR_SME_JOIN_TIMEOUT_RESULT_CODE:
+ return "eSIR_SME_JOIN_TIMEOUT_RESULT_CODE";
+ case eSIR_SME_AUTH_TIMEOUT_RESULT_CODE:
+ return "eSIR_SME_AUTH_TIMEOUT_RESULT_CODE";
+ case eSIR_SME_ASSOC_TIMEOUT_RESULT_CODE:
+ return "eSIR_SME_ASSOC_TIMEOUT_RESULT_CODE";
+ case eSIR_SME_REASSOC_TIMEOUT_RESULT_CODE:
+ return "eSIR_SME_REASSOC_TIMEOUT_RESULT_CODE";
+ case eSIR_SME_MAX_NUM_OF_PRE_AUTH_REACHED:
+ return "eSIR_SME_MAX_NUM_OF_PRE_AUTH_REACHED";
+ case eSIR_SME_AUTH_REFUSED:
+ return "eSIR_SME_AUTH_REFUSED";
+ case eSIR_SME_INVALID_WEP_DEFAULT_KEY:
+ return "eSIR_SME_INVALID_WEP_DEFAULT_KEY";
+ case eSIR_SME_ASSOC_REFUSED:
+ return "eSIR_SME_ASSOC_REFUSED";
+ case eSIR_SME_REASSOC_REFUSED:
+ return "eSIR_SME_REASSOC_REFUSED";
+ case eSIR_SME_STA_NOT_AUTHENTICATED:
+ return "eSIR_SME_STA_NOT_AUTHENTICATED";
+ case eSIR_SME_STA_NOT_ASSOCIATED:
+ return "eSIR_SME_STA_NOT_ASSOCIATED";
+ case eSIR_SME_ALREADY_JOINED_A_BSS:
+ return "eSIR_SME_ALREADY_JOINED_A_BSS";
+ case eSIR_SME_MORE_SCAN_RESULTS_FOLLOW:
+ return "eSIR_SME_MORE_SCAN_RESULTS_FOLLOW";
+ case eSIR_SME_INVALID_ASSOC_RSP_RXED:
+ return "eSIR_SME_INVALID_ASSOC_RSP_RXED";
+ case eSIR_SME_MIC_COUNTER_MEASURES:
+ return "eSIR_SME_MIC_COUNTER_MEASURES";
+ case eSIR_SME_ADDTS_RSP_TIMEOUT:
+ return "eSIR_SME_ADDTS_RSP_TIMEOUT";
+ case eSIR_SME_CHANNEL_SWITCH_FAIL:
+ return "eSIR_SME_CHANNEL_SWITCH_FAIL";
+ case eSIR_SME_HAL_SCAN_INIT_FAILED:
+ return "eSIR_SME_HAL_SCAN_INIT_FAILED";
+ case eSIR_SME_HAL_SCAN_END_FAILED:
+ return "eSIR_SME_HAL_SCAN_END_FAILED";
+ case eSIR_SME_HAL_SCAN_FINISH_FAILED:
+ return "eSIR_SME_HAL_SCAN_FINISH_FAILED";
+ case eSIR_SME_HAL_SEND_MESSAGE_FAIL:
+ return "eSIR_SME_HAL_SEND_MESSAGE_FAIL";
+
+ default:
+ return "INVALID resultCode";
+ }
+}
+
+void lim_print_msg_name(tpAniSirGlobal pMac, uint16_t logLevel, uint32_t msgType)
+{
+ lim_log(pMac, logLevel, lim_msg_str(msgType));
+}
+
+/**
+ * lim_init_mlm()
+ *
+ ***FUNCTION:
+ * This function is called by limProcessSmeMessages() to
+ * initialize MLM state machine on STA
+ *
+ ***PARAMS:
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ * NA
+ *
+ ***NOTE:
+ * NA
+ *
+ * @param pMac Pointer to Global MAC structure
+ * @return None
+ */
+void lim_init_mlm(tpAniSirGlobal pMac)
+{
+ uint32_t retVal;
+
+ pMac->lim.gLimTimersCreated = 0;
+
+ MTRACE(mac_trace
+ (pMac, TRACE_CODE_MLM_STATE, NO_SESSION,
+ pMac->lim.gLimMlmState));
+
+
+ /* / Initialize number of pre-auth contexts */
+ pMac->lim.gLimNumPreAuthContexts = 0;
+
+ /* / Initialize MAC based Authentication STA list */
+ lim_init_pre_auth_list(pMac);
+
+ /* Create timers used by LIM */
+ retVal = lim_create_timers(pMac);
+ if (retVal == TX_SUCCESS) {
+ pMac->lim.gLimTimersCreated = 1;
+ } else {
+ lim_log(pMac, LOGP,
+ FL(" lim_create_timers Failed to create lim timers "));
+ }
+} /*** end lim_init_mlm() ***/
+
+/**
+ * lim_deactivate_del_sta() - This function deactivate/delete associates STA
+ * @mac_ctx: pointer to Global Mac Structure
+ * @bss_entry: index for bss_entry
+ * @psession_entry: pointer to session entry
+ * @sta_ds: pointer to tpDphHashNode
+ *
+ * Function deactivate/delete associates STA
+ *
+ * Return: none
+ */
+static void lim_deactivate_del_sta(tpAniSirGlobal mac_ctx, uint32_t bss_entry,
+ tpPESession psession_entry, tpDphHashNode sta_ds)
+{
+ uint32_t sta_entry;
+
+ for (sta_entry = 1; sta_entry < mac_ctx->lim.gLimAssocStaLimit;
+ sta_entry++) {
+ psession_entry = &mac_ctx->lim.gpSession[bss_entry];
+ sta_ds = dph_get_hash_entry(mac_ctx, sta_entry,
+ &psession_entry->dph.dphHashTable);
+ if (NULL == sta_ds)
+ continue;
+
+ CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_ERROR,
+ FL("Deleting pmfSaQueryTimer for staid[%d]"),
+ sta_ds->staIndex);
+ tx_timer_deactivate(&sta_ds->pmfSaQueryTimer);
+ tx_timer_delete(&sta_ds->pmfSaQueryTimer);
+ }
+}
+
+/**
+ * lim_cleanup_mlm() - This function is called to cleanup
+ * @mac_ctx: Pointer to Global MAC structure
+ *
+ * Function is called to cleanup any resources allocated by the MLM
+ * state machine.
+ *
+ * Return: none
+ */
+void lim_cleanup_mlm(tpAniSirGlobal mac_ctx)
+{
+ uint32_t n;
+ tLimPreAuthNode *pAuthNode;
+#ifdef WLAN_FEATURE_11W
+ uint32_t bss_entry;
+ tpDphHashNode sta_ds = NULL;
+ tpPESession psession_entry = NULL;
+#endif
+ tLimTimers *lim_timer = NULL;
+
+ if (mac_ctx->lim.gLimTimersCreated == 1) {
+ lim_timer = &mac_ctx->lim.limTimers;
+
+ /* Deactivate and delete Periodic Probe channel timers. */
+ tx_timer_deactivate(&lim_timer->gLimPeriodicProbeReqTimer);
+ tx_timer_delete(&lim_timer->gLimPeriodicProbeReqTimer);
+
+ /* Deactivate and delete channel switch timer. */
+ tx_timer_deactivate(&lim_timer->gLimChannelSwitchTimer);
+ tx_timer_delete(&lim_timer->gLimChannelSwitchTimer);
+
+ /* Deactivate and delete addts response timer. */
+ tx_timer_deactivate(&lim_timer->gLimAddtsRspTimer);
+ tx_timer_delete(&lim_timer->gLimAddtsRspTimer);
+
+ /* Deactivate and delete Join failure timer. */
+ tx_timer_deactivate(&lim_timer->gLimJoinFailureTimer);
+ tx_timer_delete(&lim_timer->gLimJoinFailureTimer);
+
+ /* Deactivate and delete Periodic Join Probe Request timer. */
+ tx_timer_deactivate(&lim_timer->gLimPeriodicJoinProbeReqTimer);
+ tx_timer_delete(&lim_timer->gLimPeriodicJoinProbeReqTimer);
+
+ /* Deactivate and delete Association failure timer. */
+ tx_timer_deactivate(&lim_timer->gLimAssocFailureTimer);
+ tx_timer_delete(&lim_timer->gLimAssocFailureTimer);
+
+ /* Deactivate and delete Reassociation failure timer. */
+ tx_timer_deactivate(&lim_timer->gLimReassocFailureTimer);
+ tx_timer_delete(&lim_timer->gLimReassocFailureTimer);
+
+ /* Deactivate and delete Authentication failure timer. */
+ tx_timer_deactivate(&lim_timer->gLimAuthFailureTimer);
+ tx_timer_delete(&lim_timer->gLimAuthFailureTimer);
+
+ /* Deactivate and delete wait-for-probe-after-Heartbeat timer. */
+ tx_timer_deactivate(&lim_timer->gLimProbeAfterHBTimer);
+ tx_timer_delete(&lim_timer->gLimProbeAfterHBTimer);
+
+ /* Deactivate and delete Quiet timer. */
+ tx_timer_deactivate(&lim_timer->gLimQuietTimer);
+ tx_timer_delete(&lim_timer->gLimQuietTimer);
+
+ /* Deactivate and delete Quiet BSS timer. */
+ tx_timer_deactivate(&lim_timer->gLimQuietBssTimer);
+ tx_timer_delete(&lim_timer->gLimQuietBssTimer);
+
+ /* Deactivate and delete cnf wait timer */
+ for (n = 0; n < (mac_ctx->lim.maxStation + 1); n++) {
+ tx_timer_deactivate(&lim_timer->gpLimCnfWaitTimer[n]);
+ tx_timer_delete(&lim_timer->gpLimCnfWaitTimer[n]);
+ }
+
+ pAuthNode = mac_ctx->lim.gLimPreAuthTimerTable.pTable;
+
+ /* Deactivate any Authentication response timers */
+ lim_delete_pre_auth_list(mac_ctx);
+
+ for (n = 0; n < mac_ctx->lim.gLimPreAuthTimerTable.numEntry;
+ n++, pAuthNode++) {
+ /*
+ * Delete any Authentication response
+ * timers, which might have been started.
+ */
+ tx_timer_delete(&pAuthNode->timer);
+ }
+
+ /* Deactivate and delete Hash Miss throttle timer */
+ tx_timer_deactivate(&lim_timer->
+ gLimSendDisassocFrameThresholdTimer);
+ tx_timer_delete(&lim_timer->
+ gLimSendDisassocFrameThresholdTimer);
+
+ tx_timer_deactivate(&lim_timer->gLimUpdateOlbcCacheTimer);
+ tx_timer_delete(&lim_timer->gLimUpdateOlbcCacheTimer);
+ tx_timer_deactivate(&lim_timer->gLimPreAuthClnupTimer);
+ tx_timer_delete(&lim_timer->gLimPreAuthClnupTimer);
+
+#ifdef WLAN_FEATURE_VOWIFI_11R
+ /* Deactivate and delete FT Preauth response timer */
+ tx_timer_deactivate(&lim_timer->gLimFTPreAuthRspTimer);
+ tx_timer_delete(&lim_timer->gLimFTPreAuthRspTimer);
+#endif
+
+ /* Deactivate and delete remain on channel timer */
+ tx_timer_deactivate(&lim_timer->gLimRemainOnChannelTimer);
+ tx_timer_delete(&lim_timer->gLimRemainOnChannelTimer);
+
+
+ tx_timer_deactivate(&lim_timer->gLimDisassocAckTimer);
+ tx_timer_delete(&lim_timer->gLimDisassocAckTimer);
+
+ tx_timer_deactivate(&lim_timer->gLimDeauthAckTimer);
+ tx_timer_delete(&lim_timer->gLimDeauthAckTimer);
+
+ tx_timer_deactivate(&lim_timer->
+ gLimP2pSingleShotNoaInsertTimer);
+ tx_timer_delete(&lim_timer->
+ gLimP2pSingleShotNoaInsertTimer);
+
+ tx_timer_deactivate(&lim_timer->
+ gLimActiveToPassiveChannelTimer);
+ tx_timer_delete(&lim_timer->
+ gLimActiveToPassiveChannelTimer);
+
+ mac_ctx->lim.gLimTimersCreated = 0;
+ }
+#ifdef WLAN_FEATURE_11W
+ /*
+ * When SSR is triggered, we need to loop through
+ * each STA associated per BSSId and deactivate/delete
+ * the pmfSaQueryTimer for it
+ */
+ if (cds_is_logp_in_progress()) {
+ CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_ERROR,
+ FL("SSR is detected, proceed to clean up pmfSaQueryTimer"));
+ for (bss_entry = 0; bss_entry < mac_ctx->lim.maxBssId;
+ bss_entry++) {
+ if (!mac_ctx->lim.gpSession[bss_entry].valid)
+ continue;
+ lim_deactivate_del_sta(mac_ctx, bss_entry,
+ psession_entry, sta_ds);
+ }
+ }
+#endif
+
+} /*** end lim_cleanup_mlm() ***/
+
+/**
+ * lim_cleanup_lmm()
+ *
+ ***FUNCTION:
+ * This function is called to cleanup any resources
+ * allocated by LMM sub-module.
+ *
+ ***PARAMS:
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ * NA
+ *
+ ***NOTE:
+ * NA
+ *
+ * @param pMac Pointer to Global MAC structure
+ * @return None
+ */
+
+void lim_cleanup_lmm(tpAniSirGlobal pMac)
+{
+} /*** end lim_cleanup_lmm() ***/
+
+/**
+ * lim_is_addr_bc()
+ *
+ ***FUNCTION:
+ * This function is called in various places within LIM code
+ * to determine whether passed MAC address is a broadcast or not
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ * NA
+ *
+ ***NOTE:
+ * NA
+ *
+ * @param macAddr Indicates MAC address that need to be determined
+ * whether it is Broadcast address or not
+ *
+ * @return true if passed address is Broadcast address else false
+ */
+
+uint8_t lim_is_addr_bc(tSirMacAddr macAddr)
+{
+ int i;
+ for (i = 0; i < 6; i++) {
+ if ((macAddr[i] & 0xFF) != 0xFF)
+ return false;
+ }
+
+ return true;
+} /****** end lim_is_addr_bc() ******/
+
+/**
+ * lim_is_group_addr()
+ *
+ ***FUNCTION:
+ * This function is called in various places within LIM code
+ * to determine whether passed MAC address is a group address or not
+ *
+ ***LOGIC:
+ * If least significant bit of first octet of the MAC address is
+ * set to 1, it is a Group address.
+ *
+ ***ASSUMPTIONS:
+ * NA
+ *
+ ***NOTE:
+ * NA
+ *
+ * @param macAddr Indicates MAC address that need to be determined
+ * whether it is Group address or not
+ *
+ * @return true if passed address is Group address else false
+ */
+
+uint8_t lim_is_group_addr(tSirMacAddr macAddr)
+{
+ if ((macAddr[0] & 0x01) == 0x01)
+ return true;
+ else
+ return false;
+} /****** end lim_is_group_addr() ******/
+
+/**
+ * lim_print_mac_addr()
+ *
+ ***FUNCTION:
+ * This function is called to print passed MAC address
+ * in : format.
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ * NA
+ *
+ ***NOTE:
+ * @param macAddr - MacAddr to be printed
+ * @param logLevel - Loglevel to be used
+ *
+ * @return None.
+ */
+
+void lim_print_mac_addr(tpAniSirGlobal pMac, tSirMacAddr macAddr, uint8_t logLevel)
+{
+ lim_log(pMac, logLevel, FL(MAC_ADDRESS_STR), MAC_ADDR_ARRAY(macAddr));
+} /****** end lim_print_mac_addr() ******/
+
+/*
+ * lim_reset_deferred_msg_q()
+ *
+ ***FUNCTION:
+ * This function resets the deferred message queue parameters.
+ *
+ ***PARAMS:
+ * @param pMac - Pointer to Global MAC structure
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ * NA
+ *
+ ***NOTE:
+ * NA
+ *
+ ***RETURNS:
+ * None
+ */
+
+void lim_reset_deferred_msg_q(tpAniSirGlobal pMac)
+{
+ pMac->lim.gLimDeferredMsgQ.size =
+ pMac->lim.gLimDeferredMsgQ.write =
+ pMac->lim.gLimDeferredMsgQ.read = 0;
+
+}
+
+#define LIM_DEFERRED_Q_CHECK_THRESHOLD (MAX_DEFERRED_QUEUE_LEN/2)
+#define LIM_MAX_NUM_MGMT_FRAME_DEFERRED (MAX_DEFERRED_QUEUE_LEN/2)
+
+/**
+ * lim_write_deferred_msg_q() - This function queues up a deferred message
+ *
+ * @mac_ctx: Pointer to Global MAC structure
+ * @lim_msg: a LIM message
+ *
+ * Function queues up a deferred message for later processing on the
+ * STA side.
+ *
+ * Return: none
+ */
+
+uint8_t lim_write_deferred_msg_q(tpAniSirGlobal mac_ctx, tpSirMsgQ lim_msg)
+{
+ lim_log(mac_ctx, LOG1,
+ FL("Queue a deferred message (size %d, write %d) - type 0x%x "),
+ mac_ctx->lim.gLimDeferredMsgQ.size,
+ mac_ctx->lim.gLimDeferredMsgQ.write,
+ lim_msg->type);
+
+ /* check if the deferred message queue is full */
+ if (mac_ctx->lim.gLimDeferredMsgQ.size >= MAX_DEFERRED_QUEUE_LEN) {
+ if (!(mac_ctx->lim.deferredMsgCnt & 0xF)) {
+ lim_log(mac_ctx, LOGE,
+ FL("queue->MsgQ full Msg:%d Msgs Failed:%d"),
+ lim_msg->type,
+ ++mac_ctx->lim.deferredMsgCnt);
+ } else {
+ mac_ctx->lim.deferredMsgCnt++;
+ }
+ return TX_QUEUE_FULL;
+ }
+
+ /*
+ * In the application, there should not be more than 1 message get
+ * queued up. If happens, flags a warning. In the future, this can
+ * happen.
+ */
+ if (mac_ctx->lim.gLimDeferredMsgQ.size > 0)
+ lim_log(mac_ctx, LOGW,
+ FL("%d Deferred Msg (type 0x%x, scan %d, global sme %d, global mlme %d, addts %d)"),
+ mac_ctx->lim.gLimDeferredMsgQ.size,
+ lim_msg->type,
+ lim_is_system_in_scan_state(mac_ctx),
+ mac_ctx->lim.gLimSmeState,
+ mac_ctx->lim.gLimMlmState,
+ mac_ctx->lim.gLimAddtsSent);
+
+ /*
+ * To prevent the deferred Q is full of management frames, only give
+ * them certain space
+ */
+ if ((SIR_BB_XPORT_MGMT_MSG == lim_msg->type) &&
+ (LIM_DEFERRED_Q_CHECK_THRESHOLD <
+ mac_ctx->lim.gLimDeferredMsgQ.size)) {
+ uint16_t idx, count = 0;
+ for (idx = 0; idx < mac_ctx->lim.gLimDeferredMsgQ.size;
+ idx++) {
+ if (SIR_BB_XPORT_MGMT_MSG ==
+ mac_ctx->lim.gLimDeferredMsgQ.
+ deferredQueue[idx].type) {
+ count++;
+ }
+ }
+ if (LIM_MAX_NUM_MGMT_FRAME_DEFERRED < count) {
+ /*
+ * We reach the quota for management frames,
+ * drop this one
+ */
+ lim_log(mac_ctx, LOGW,
+ FL("Too many queue->MsgQ Msg: %d (count=%d)"),
+ lim_msg->type, count);
+ /* Return error, caller knows what to do */
+ return TX_QUEUE_FULL;
+ }
+ }
+
+ ++mac_ctx->lim.gLimDeferredMsgQ.size;
+
+ /* reset the count here since we are able to defer the message */
+ if (mac_ctx->lim.deferredMsgCnt != 0)
+ mac_ctx->lim.deferredMsgCnt = 0;
+
+ /* if the write pointer hits the end of the queue, rewind it */
+ if (mac_ctx->lim.gLimDeferredMsgQ.write >= MAX_DEFERRED_QUEUE_LEN)
+ mac_ctx->lim.gLimDeferredMsgQ.write = 0;
+
+ /* save the message to the queue and advanced the write pointer */
+ cdf_mem_copy((uint8_t *) &mac_ctx->lim.gLimDeferredMsgQ.
+ deferredQueue[mac_ctx->lim.gLimDeferredMsgQ.write++],
+ (uint8_t *) lim_msg, sizeof(tSirMsgQ));
+ return TX_SUCCESS;
+
+}
+
+/*
+ * lim_read_deferred_msg_q()
+ *
+ ***FUNCTION:
+ * This function dequeues a deferred message for processing on the
+ * STA side.
+ *
+ ***PARAMS:
+ * @param pMac - Pointer to Global MAC structure
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ * NA
+ *
+ ***NOTE:
+ *
+ *
+ ***RETURNS:
+ * Returns the message at the head of the deferred message queue
+ */
+
+tSirMsgQ *lim_read_deferred_msg_q(tpAniSirGlobal pMac)
+{
+ tSirMsgQ *msg;
+
+ /*
+ ** check any messages left. If no, return
+ **/
+ if (pMac->lim.gLimDeferredMsgQ.size <= 0)
+ return NULL;
+
+ /*
+ ** decrement the queue size
+ **/
+ pMac->lim.gLimDeferredMsgQ.size--;
+
+ /*
+ ** retrieve the message from the head of the queue
+ **/
+ msg =
+ &pMac->lim.gLimDeferredMsgQ.deferredQueue[pMac->lim.
+ gLimDeferredMsgQ.read];
+
+ /*
+ ** advance the read pointer
+ **/
+ pMac->lim.gLimDeferredMsgQ.read++;
+
+ /*
+ ** if the read pointer hits the end of the queue, rewind it
+ **/
+ if (pMac->lim.gLimDeferredMsgQ.read >= MAX_DEFERRED_QUEUE_LEN)
+ pMac->lim.gLimDeferredMsgQ.read = 0;
+
+ PELOG1(lim_log(pMac, LOG1,
+ FL
+ ("** DeQueue a deferred message (size %d read %d) - type 0x%x **"),
+ pMac->lim.gLimDeferredMsgQ.size,
+ pMac->lim.gLimDeferredMsgQ.read, msg->type);
+ )
+
+ PELOG1(lim_log
+ (pMac, LOG1,
+ FL
+ ("DQ msg -- scan %d, global sme %d, global mlme %d, addts %d"),
+ lim_is_system_in_scan_state(pMac), pMac->lim.gLimSmeState,
+ pMac->lim.gLimMlmState, pMac->lim.gLimAddtsSent);
+ )
+
+ return msg;
+}
+
+tSirRetStatus
+lim_sys_process_mmh_msg_api(tpAniSirGlobal pMac, tSirMsgQ *pMsg, uint8_t qType)
+{
+ /* FIXME */
+ sys_process_mmh_msg(pMac, pMsg);
+ return eSIR_SUCCESS;
+}
+
+/*
+ * lim_handle_update_olbc_cache() - This function update olbc cache
+ *
+ * @mac_ctx: Pointer to Global MAC structure
+ *
+ * Function updates olbc cache
+ *
+ * Return: none
+ */
+void lim_handle_update_olbc_cache(tpAniSirGlobal mac_ctx)
+{
+ int i;
+ static int enable;
+ tUpdateBeaconParams beaconParams;
+
+ tpPESession psessionEntry = lim_is_ap_session_active(mac_ctx);
+
+ if (psessionEntry == NULL) {
+ lim_log(mac_ctx, LOGE, FL(" Session not found"));
+ return;
+ }
+
+ cdf_mem_set((uint8_t *) &beaconParams, sizeof(tUpdateBeaconParams), 0);
+ beaconParams.bssIdx = psessionEntry->bssIdx;
+
+ beaconParams.paramChangeBitmap = 0;
+ /*
+ * This is doing a 2 pass check. The first pass is to invalidate
+ * all the cache entries. The second pass is to decide whether to
+ * disable protection.
+ */
+ if (!enable) {
+ lim_log(mac_ctx, LOG2, FL("Resetting OLBC cache"));
+ psessionEntry->gLimOlbcParams.numSta = 0;
+ psessionEntry->gLimOverlap11gParams.numSta = 0;
+ psessionEntry->gLimOverlapHt20Params.numSta = 0;
+ psessionEntry->gLimNonGfParams.numSta = 0;
+ psessionEntry->gLimLsigTxopParams.numSta = 0;
+
+ for (i = 0; i < LIM_PROT_STA_OVERLAP_CACHE_SIZE; i++)
+ mac_ctx->lim.protStaOverlapCache[i].active = false;
+
+ enable = 1;
+ } else {
+ if ((!psessionEntry->gLimOlbcParams.numSta) &&
+ (psessionEntry->gLimOlbcParams.protectionEnabled) &&
+ (!psessionEntry->gLim11bParams.protectionEnabled)) {
+ lim_log(mac_ctx, LOG1,
+ FL("Overlap cache clear and no 11B STA set"));
+ lim_enable11g_protection(mac_ctx, false, true,
+ &beaconParams,
+ psessionEntry);
+ }
+
+ if ((!psessionEntry->gLimOverlap11gParams.numSta) &&
+ (psessionEntry->gLimOverlap11gParams.protectionEnabled)
+ && (!psessionEntry->gLim11gParams.protectionEnabled)) {
+ lim_log(mac_ctx, LOG1,
+ FL("Overlap cache clear and no 11G STA set"));
+ lim_enable_ht_protection_from11g(mac_ctx, false, true,
+ &beaconParams,
+ psessionEntry);
+ }
+
+ if ((!psessionEntry->gLimOverlapHt20Params.numSta) &&
+ (psessionEntry->gLimOverlapHt20Params.protectionEnabled)
+ && (!psessionEntry->gLimHt20Params.protectionEnabled)) {
+ lim_log(mac_ctx, LOG1,
+ FL("Overlap cache clear and no HT20 STA set"));
+ lim_enable11g_protection(mac_ctx, false, true,
+ &beaconParams,
+ psessionEntry);
+ }
+
+ enable = 0;
+ }
+
+ if ((false == mac_ctx->sap.SapDfsInfo.is_dfs_cac_timer_running)
+ && beaconParams.paramChangeBitmap) {
+ sch_set_fixed_beacon_fields(mac_ctx, psessionEntry);
+ lim_send_beacon_params(mac_ctx, &beaconParams, psessionEntry);
+ }
+ /* Start OLBC timer */
+ if (tx_timer_activate(&mac_ctx->lim.limTimers.gLimUpdateOlbcCacheTimer)
+ != TX_SUCCESS)
+ lim_log(mac_ctx, LOGE, FL("tx_timer_activate failed"));
+}
+
+/**
+ * lim_is_null_ssid() - This function checks if ssid supplied is Null SSID
+ * @ssid: pointer to tSirMacSSid
+ *
+ * Function checks if ssid supplied is Null SSID
+ *
+ * Return: none
+ */
+
+uint8_t lim_is_null_ssid(tSirMacSSid *ssid)
+{
+ uint8_t fnull_ssid = false;
+ uint32_t ssid_len;
+ uint8_t *ssid_str;
+
+ if (0 == ssid->length) {
+ fnull_ssid = true;
+ return fnull_ssid;
+ }
+ /* If the first charactes is space, then check if all
+ * characters in SSID are spaces to consider it as NULL SSID
+ */
+ if ((ASCII_SPACE_CHARACTER == ssid->ssId[0]) &&
+ (ssid->length == 1)){
+ fnull_ssid = true;
+ return fnull_ssid;
+ } else {
+ /* check if all the charactes in SSID are NULL */
+ ssid_len = ssid->length;
+ ssid_str = ssid->ssId;
+
+ while (ssid_len) {
+ if (*ssid_str)
+ return fnull_ssid;
+
+ ssid_str++;
+ ssid_len--;
+ }
+
+ if (0 == ssid_len) {
+ fnull_ssid = true;
+ return fnull_ssid;
+ }
+ }
+
+ return fnull_ssid;
+}
+
+/** -------------------------------------------------------------
+ \fn lim_update_prot_sta_params
+ \brief updates protection related counters.
+ \param tpAniSirGlobal pMac
+ \param tSirMacAddr peerMacAddr
+ \param tLimProtStaCacheType protStaCacheType
+ \param tHalBitVal gfSupported
+ \param tHalBitVal lsigTxopSupported
+ \return None
+ -------------------------------------------------------------*/
+void
+lim_update_prot_sta_params(tpAniSirGlobal pMac,
+ tSirMacAddr peerMacAddr,
+ tLimProtStaCacheType protStaCacheType,
+ tHalBitVal gfSupported, tHalBitVal lsigTxopSupported,
+ tpPESession psessionEntry)
+{
+ uint32_t i;
+
+ PELOG1(lim_log(pMac, LOG1, FL("A STA is associated:"));
+ lim_log(pMac, LOG1, FL("Addr : "));
+ lim_print_mac_addr(pMac, peerMacAddr, LOG1);
+ )
+
+ for (i = 0; i < LIM_PROT_STA_CACHE_SIZE; i++) {
+ if (psessionEntry->protStaCache[i].active) {
+ PELOG1(lim_log(pMac, LOG1, FL("Addr: "));)
+ PELOG1(lim_print_mac_addr
+ (pMac, psessionEntry->protStaCache[i].addr,
+ LOG1);
+ )
+
+ if (cdf_mem_compare
+ (psessionEntry->protStaCache[i].addr,
+ peerMacAddr, sizeof(tSirMacAddr))) {
+ PELOG1(lim_log
+ (pMac, LOG1,
+ FL
+ ("matching cache entry at %d already active."),
+ i);
+ )
+ return;
+ }
+ }
+ }
+
+ for (i = 0; i < LIM_PROT_STA_CACHE_SIZE; i++) {
+ if (!psessionEntry->protStaCache[i].active)
+ break;
+ }
+
+ if (i >= LIM_PROT_STA_CACHE_SIZE) {
+ PELOGE(lim_log(pMac, LOGE, FL("No space in ProtStaCache"));)
+ return;
+ }
+
+ cdf_mem_copy(psessionEntry->protStaCache[i].addr,
+ peerMacAddr, sizeof(tSirMacAddr));
+
+ psessionEntry->protStaCache[i].protStaCacheType = protStaCacheType;
+ psessionEntry->protStaCache[i].active = true;
+ if (eLIM_PROT_STA_CACHE_TYPE_llB == protStaCacheType) {
+ psessionEntry->gLim11bParams.numSta++;
+ lim_log(pMac, LOG1, FL("11B, "));
+ } else if (eLIM_PROT_STA_CACHE_TYPE_llG == protStaCacheType) {
+ psessionEntry->gLim11gParams.numSta++;
+ lim_log(pMac, LOG1, FL("11G, "));
+ } else if (eLIM_PROT_STA_CACHE_TYPE_HT20 == protStaCacheType) {
+ psessionEntry->gLimHt20Params.numSta++;
+ lim_log(pMac, LOG1, FL("HT20, "));
+ }
+
+ if (!gfSupported) {
+ psessionEntry->gLimNonGfParams.numSta++;
+ lim_log(pMac, LOG1, FL("NonGf, "));
+ }
+ if (!lsigTxopSupported) {
+ psessionEntry->gLimLsigTxopParams.numSta++;
+ lim_log(pMac, LOG1, FL("!lsigTxopSupported"));
+ }
+} /* --------------------------------------------------------------------- */
+
+/** -------------------------------------------------------------
+ \fn lim_decide_ap_protection
+ \brief Decides all the protection related staiton coexistence and also sets
+ \ short preamble and short slot appropriately. This function will be called
+ \ when AP is ready to send assocRsp tp the station joining right now.
+ \param tpAniSirGlobal pMac
+ \param tSirMacAddr peerMacAddr
+ \return None
+ -------------------------------------------------------------*/
+void
+lim_decide_ap_protection(tpAniSirGlobal pMac, tSirMacAddr peerMacAddr,
+ tpUpdateBeaconParams pBeaconParams,
+ tpPESession psessionEntry)
+{
+ uint16_t tmpAid;
+ tpDphHashNode pStaDs;
+ tSirRFBand rfBand = SIR_BAND_UNKNOWN;
+ uint32_t phyMode;
+ tLimProtStaCacheType protStaCacheType =
+ eLIM_PROT_STA_CACHE_TYPE_INVALID;
+ tHalBitVal gfSupported = eHAL_SET, lsigTxopSupported = eHAL_SET;
+
+ pBeaconParams->paramChangeBitmap = 0;
+ /* check whether to enable protection or not */
+ pStaDs =
+ dph_lookup_hash_entry(pMac, peerMacAddr, &tmpAid,
+ &psessionEntry->dph.dphHashTable);
+ if (NULL == pStaDs) {
+ PELOG1(lim_log(pMac, LOG1, FL("pStaDs is NULL"));)
+ return;
+ }
+ lim_get_rf_band_new(pMac, &rfBand, psessionEntry);
+ /* if we are in 5 GHZ band */
+ if (SIR_BAND_5_GHZ == rfBand) {
+ /* We are 11N. we need to protect from 11A and Ht20. we don't need any other protection in 5 GHZ. */
+ /* HT20 case is common between both the bands and handled down as common code. */
+ if (true == psessionEntry->htCapability) {
+ /* we are 11N and 11A station is joining. */
+ /* protection from 11A required. */
+ if (false == pStaDs->mlmStaContext.htCapability) {
+ lim_update_11a_protection(pMac, true, false,
+ pBeaconParams,
+ psessionEntry);
+ return;
+ }
+ }
+ } else if (SIR_BAND_2_4_GHZ == rfBand) {
+ lim_get_phy_mode(pMac, &phyMode, psessionEntry);
+
+ /* We are 11G. Check if we need protection from 11b Stations. */
+ if ((phyMode == WNI_CFG_PHY_MODE_11G) &&
+ (false == psessionEntry->htCapability)) {
+
+ if (pStaDs->erpEnabled == eHAL_CLEAR) {
+ protStaCacheType = eLIM_PROT_STA_CACHE_TYPE_llB;
+ /* enable protection */
+ PELOG3(lim_log
+ (pMac, LOG3,
+ FL("Enabling protection from 11B"));
+ )
+ lim_enable11g_protection(pMac, true, false,
+ pBeaconParams,
+ psessionEntry);
+ }
+ }
+ /* HT station. */
+ if (true == psessionEntry->htCapability) {
+ /* check if we need protection from 11b station */
+ if ((pStaDs->erpEnabled == eHAL_CLEAR) &&
+ (!pStaDs->mlmStaContext.htCapability)) {
+ protStaCacheType = eLIM_PROT_STA_CACHE_TYPE_llB;
+ /* enable protection */
+ PELOG3(lim_log
+ (pMac, LOG3,
+ FL("Enabling protection from 11B"));
+ )
+ lim_enable11g_protection(pMac, true, false,
+ pBeaconParams,
+ psessionEntry);
+ }
+ /* station being joined is non-11b and non-ht ==> 11g device */
+ else if (!pStaDs->mlmStaContext.htCapability) {
+ protStaCacheType = eLIM_PROT_STA_CACHE_TYPE_llG;
+ /* enable protection */
+ lim_enable_ht_protection_from11g(pMac, true, false,
+ pBeaconParams,
+ psessionEntry);
+ }
+ /* ERP mode is enabled for the latest station joined */
+ /* latest station joined is HT capable */
+ /* This case is being handled in common code (commn between both the bands) below. */
+ }
+ }
+ /* we are HT and HT station is joining. This code is common for both the bands. */
+ if ((true == psessionEntry->htCapability) &&
+ (true == pStaDs->mlmStaContext.htCapability)) {
+ if (!pStaDs->htGreenfield) {
+ lim_enable_ht_non_gf_protection(pMac, true, false,
+ pBeaconParams,
+ psessionEntry);
+ gfSupported = eHAL_CLEAR;
+ }
+ /* Station joining is HT 20Mhz */
+ if ((eHT_CHANNEL_WIDTH_20MHZ ==
+ pStaDs->htSupportedChannelWidthSet) &&
+ (eHT_CHANNEL_WIDTH_20MHZ !=
+ psessionEntry->htSupportedChannelWidthSet)){
+ protStaCacheType = eLIM_PROT_STA_CACHE_TYPE_HT20;
+ lim_enable_ht20_protection(pMac, true, false,
+ pBeaconParams, psessionEntry);
+ }
+ /* Station joining does not support LSIG TXOP Protection */
+ if (!pStaDs->htLsigTXOPProtection) {
+ lim_enable_ht_lsig_txop_protection(pMac, false, false,
+ pBeaconParams,
+ psessionEntry);
+ lsigTxopSupported = eHAL_CLEAR;
+ }
+ }
+
+ lim_update_prot_sta_params(pMac, peerMacAddr, protStaCacheType,
+ gfSupported, lsigTxopSupported, psessionEntry);
+
+ return;
+}
+
+/** -------------------------------------------------------------
+ \fn lim_enable_overlap11g_protection
+ \brief wrapper function for setting overlap 11g protection.
+ \param tpAniSirGlobal pMac
+ \param tpUpdateBeaconParams pBeaconParams
+ \param tpSirMacMgmtHdr pMh
+ \return None
+ -------------------------------------------------------------*/
+void
+lim_enable_overlap11g_protection(tpAniSirGlobal pMac,
+ tpUpdateBeaconParams pBeaconParams,
+ tpSirMacMgmtHdr pMh, tpPESession psessionEntry)
+{
+ lim_update_overlap_sta_param(pMac, pMh->bssId,
+ &(psessionEntry->gLimOlbcParams));
+
+ if (psessionEntry->gLimOlbcParams.numSta &&
+ !psessionEntry->gLimOlbcParams.protectionEnabled) {
+ /* enable protection */
+ PELOG1(lim_log(pMac, LOG1, FL("OLBC happens!!!"));)
+ lim_enable11g_protection(pMac, true, true, pBeaconParams,
+ psessionEntry);
+ }
+}
+
+/**
+ * lim_update_short_preamble() - This function Updates short preamble
+ * @mac_ctx: pointer to Global MAC structure
+ * @peer_mac_addr: pointer to tSirMacAddr
+ * @pbeaconparams: pointer to tpUpdateBeaconParams
+ * @psession_entry: pointer to tpPESession
+ *
+ * Function Updates short preamble if needed when a new station joins
+ *
+ * Return: none
+ */
+void
+lim_update_short_preamble(tpAniSirGlobal mac_ctx, tSirMacAddr peer_mac_addr,
+ tpUpdateBeaconParams beaconparams,
+ tpPESession psession_entry)
+{
+ uint16_t aid;
+ tpDphHashNode sta_ds;
+ uint32_t phy_mode;
+ uint16_t i;
+
+ /* check whether to enable protection or not */
+ sta_ds =
+ dph_lookup_hash_entry(mac_ctx, peer_mac_addr, &aid,
+ &psession_entry->dph.dphHashTable);
+
+ lim_get_phy_mode(mac_ctx, &phy_mode, psession_entry);
+
+ if (sta_ds == NULL || phy_mode != WNI_CFG_PHY_MODE_11G)
+ return;
+
+ if (sta_ds->shortPreambleEnabled != eHAL_CLEAR)
+ return;
+
+ lim_log(mac_ctx, LOG1,
+ FL("Short Preamble is not enabled in Assoc Req from "));
+
+ lim_print_mac_addr(mac_ctx, peer_mac_addr, LOG1);
+
+ for (i = 0; i < LIM_PROT_STA_CACHE_SIZE; i++) {
+ if (LIM_IS_AP_ROLE(psession_entry) &&
+ (psession_entry->gLimNoShortParams.
+ staNoShortCache[i].active) &&
+ (cdf_mem_compare
+ (psession_entry->gLimNoShortParams.
+ staNoShortCache[i].addr,
+ peer_mac_addr, sizeof(tSirMacAddr))))
+ return;
+ else if (!LIM_IS_AP_ROLE(psession_entry) &&
+ (mac_ctx->lim.gLimNoShortParams.
+ staNoShortCache[i].active) &&
+ (cdf_mem_compare(mac_ctx->lim.gLimNoShortParams.
+ staNoShortCache[i].addr,
+ peer_mac_addr,
+ sizeof(tSirMacAddr))))
+ return;
+ }
+
+ for (i = 0; i < LIM_PROT_STA_CACHE_SIZE; i++) {
+ if (LIM_IS_AP_ROLE(psession_entry) &&
+ !psession_entry->gLimNoShortParams.
+ staNoShortCache[i].active)
+ break;
+ else if (!mac_ctx->lim.gLimNoShortParams.
+ staNoShortCache[i].active)
+ break;
+ }
+
+ if (i >= LIM_PROT_STA_CACHE_SIZE) {
+ tLimNoShortParams *lim_params =
+ &psession_entry->gLimNoShortParams;
+ if (LIM_IS_AP_ROLE(psession_entry)) {
+ lim_log(mac_ctx, LOGE,
+ FL("No space in Short cache (#active %d, #sta %d) for sta "),
+ i,
+ lim_params->numNonShortPreambleSta);
+ lim_print_mac_addr(mac_ctx, peer_mac_addr, LOGE);
+ return;
+ } else {
+ lim_log(mac_ctx, LOGE,
+ FL("No space in Short cache (#active %d, #sta %d) for sta "),
+ i,
+ lim_params->numNonShortPreambleSta);
+ lim_print_mac_addr(mac_ctx, peer_mac_addr, LOGE);
+ return;
+ }
+
+ }
+
+ if (LIM_IS_AP_ROLE(psession_entry)) {
+ cdf_mem_copy(psession_entry->gLimNoShortParams.
+ staNoShortCache[i].addr,
+ peer_mac_addr, sizeof(tSirMacAddr));
+ psession_entry->gLimNoShortParams.staNoShortCache[i].
+ active = true;
+ psession_entry->gLimNoShortParams.numNonShortPreambleSta++;
+ } else {
+ cdf_mem_copy(mac_ctx->lim.gLimNoShortParams.
+ staNoShortCache[i].addr,
+ peer_mac_addr, sizeof(tSirMacAddr));
+ mac_ctx->lim.gLimNoShortParams.staNoShortCache[i].active = true;
+ mac_ctx->lim.gLimNoShortParams.numNonShortPreambleSta++;
+ }
+
+ /* enable long preamble */
+ lim_log(mac_ctx, LOG1, FL("Disabling short preamble"));
+
+ if (lim_enable_short_preamble(mac_ctx, false, beaconparams,
+ psession_entry) != eSIR_SUCCESS)
+ lim_log(mac_ctx, LOGE, FL("Cannot enable long preamble"));
+}
+
+/**
+ * lim_update_short_slot_time() - This function Updates short slot time
+ * @mac_ctx: pointer to Global MAC structure
+ * @peer_mac_addr: pointer to tSirMacAddr
+ * @beaconparams: pointer to tpUpdateBeaconParams
+ * @psession_entry: pointer to tpPESession
+ *
+ * Function Updates short slot time if needed when a new station joins
+ *
+ * Return: None
+ */
+void
+lim_update_short_slot_time(tpAniSirGlobal mac_ctx, tSirMacAddr peer_mac_addr,
+ tpUpdateBeaconParams beaconparams,
+ tpPESession session_entry)
+{
+ uint16_t aid;
+ tpDphHashNode sta_ds;
+ uint32_t phy_mode;
+ uint32_t val;
+ uint16_t i;
+
+ /* check whether to enable protection or not */
+ sta_ds =
+ dph_lookup_hash_entry(mac_ctx, peer_mac_addr, &aid,
+ &session_entry->dph.dphHashTable);
+ lim_get_phy_mode(mac_ctx, &phy_mode, session_entry);
+
+ if (sta_ds == NULL || phy_mode != WNI_CFG_PHY_MODE_11G)
+ return;
+
+ /*
+ * Only in case of softap in 11g mode, slot time might change
+ * depending on the STA being added. In 11a case, it should
+ * be always 1 and in 11b case, it should be always 0.
+ * Only when the new STA has short slot time disabled, we need to
+ * change softap's overall slot time settings else the default for
+ * softap is always short slot enabled. When the last long slot STA
+ * leaves softAP, we take care of it in lim_decide_short_slot
+ */
+ if (sta_ds->shortSlotTimeEnabled == eHAL_CLEAR) {
+ lim_log(mac_ctx, LOG1,
+ FL("Short Slot Time is not enabled in Assoc Req from "));
+ lim_print_mac_addr(mac_ctx, peer_mac_addr, LOG1);
+ for (i = 0; i < LIM_PROT_STA_CACHE_SIZE; i++) {
+ if (LIM_IS_AP_ROLE(session_entry) &&
+ session_entry->gLimNoShortSlotParams.
+ staNoShortSlotCache[i].active) {
+ if (cdf_mem_compare(
+ session_entry->gLimNoShortSlotParams.
+ staNoShortSlotCache[i].addr,
+ peer_mac_addr, sizeof(tSirMacAddr)))
+ return;
+ } else if (!LIM_IS_AP_ROLE(session_entry)) {
+ if (mac_ctx->lim.gLimNoShortSlotParams.
+ staNoShortSlotCache[i].active) {
+ if (cdf_mem_compare(mac_ctx->lim.
+ gLimNoShortSlotParams.
+ staNoShortSlotCache[i].
+ addr, peer_mac_addr,
+ sizeof(tSirMacAddr)))
+ return;
+ }
+ }
+ }
+ for (i = 0; i < LIM_PROT_STA_CACHE_SIZE; i++) {
+ if (LIM_IS_AP_ROLE(session_entry) &&
+ !session_entry->gLimNoShortSlotParams.
+ staNoShortSlotCache[i].active)
+ break;
+ else {
+ if (!mac_ctx->lim.gLimNoShortSlotParams.
+ staNoShortSlotCache[i].active)
+ break;
+ }
+ }
+
+ if (i >= LIM_PROT_STA_CACHE_SIZE) {
+ if (LIM_IS_AP_ROLE(session_entry)) {
+ lim_log(mac_ctx, LOGE,
+ FL("No space in ShortSlot cache (#active %d, #sta %d) for sta "),
+ i,
+ session_entry->gLimNoShortSlotParams.
+ numNonShortSlotSta);
+ lim_print_mac_addr(mac_ctx, peer_mac_addr,
+ LOGE);
+ return;
+ } else {
+ lim_log(mac_ctx, LOGE,
+ FL("No space in ShortSlot cache (#active %d, #sta %d) for sta "),
+ i,
+ mac_ctx->lim.gLimNoShortSlotParams.
+ numNonShortSlotSta);
+ lim_print_mac_addr(mac_ctx, peer_mac_addr,
+ LOGE);
+ return;
+ }
+ }
+
+ if (LIM_IS_AP_ROLE(session_entry)) {
+ cdf_mem_copy(session_entry->gLimNoShortSlotParams.
+ staNoShortSlotCache[i].addr,
+ peer_mac_addr, sizeof(tSirMacAddr));
+ session_entry->gLimNoShortSlotParams.
+ staNoShortSlotCache[i].active = true;
+ session_entry->gLimNoShortSlotParams.
+ numNonShortSlotSta++;
+ } else {
+ cdf_mem_copy(mac_ctx->lim.gLimNoShortSlotParams.
+ staNoShortSlotCache[i].addr,
+ peer_mac_addr, sizeof(tSirMacAddr));
+ mac_ctx->lim.gLimNoShortSlotParams.
+ staNoShortSlotCache[i].active = true;
+ mac_ctx->lim.gLimNoShortSlotParams.
+ numNonShortSlotSta++;
+ }
+ wlan_cfg_get_int(mac_ctx,
+ WNI_CFG_11G_SHORT_SLOT_TIME_ENABLED,
+ &val);
+ /*
+ * Here we check if we are AP role and short slot enabled
+ * (both admin and oper modes) but we have atleast one STA
+ * connected with only long slot enabled, we need to change
+ * our beacon/pb rsp to broadcast short slot disabled
+ */
+ if ((LIM_IS_AP_ROLE(session_entry)) && (val &&
+ session_entry->gLimNoShortSlotParams.numNonShortSlotSta
+ && session_entry->shortSlotTimeSupported)) {
+ /* enable long slot time */
+ beaconparams->fShortSlotTime = false;
+ beaconparams->paramChangeBitmap |=
+ PARAM_SHORT_SLOT_TIME_CHANGED;
+ lim_log(mac_ctx, LOG1,
+ FL("Disable short slot time. Enable long slot time."));
+ session_entry->shortSlotTimeSupported = false;
+ } else if (!LIM_IS_AP_ROLE(session_entry) &&
+ (val && mac_ctx->lim.gLimNoShortSlotParams.
+ numNonShortSlotSta &&
+ session_entry->shortSlotTimeSupported)) {
+ /* enable long slot time */
+ beaconparams->fShortSlotTime = false;
+ beaconparams->paramChangeBitmap |=
+ PARAM_SHORT_SLOT_TIME_CHANGED;
+ lim_log(mac_ctx, LOG1,
+ FL("Disable short slot time. Enable long slot time."));
+ session_entry->shortSlotTimeSupported =
+ false;
+ }
+ }
+}
+
+/** -------------------------------------------------------------
+ \fn lim_decide_sta_protection_on_assoc
+ \brief Decide protection related settings on Sta while association.
+ \param tpAniSirGlobal pMac
+ \param tpSchBeaconStruct pBeaconStruct
+ \return None
+ -------------------------------------------------------------*/
+void
+lim_decide_sta_protection_on_assoc(tpAniSirGlobal pMac,
+ tpSchBeaconStruct pBeaconStruct,
+ tpPESession psessionEntry)
+{
+ tSirRFBand rfBand = SIR_BAND_UNKNOWN;
+ uint32_t phyMode = WNI_CFG_PHY_MODE_NONE;
+
+ lim_get_rf_band_new(pMac, &rfBand, psessionEntry);
+ lim_get_phy_mode(pMac, &phyMode, psessionEntry);
+
+ if (SIR_BAND_5_GHZ == rfBand) {
+ if ((eSIR_HT_OP_MODE_MIXED == pBeaconStruct->HTInfo.opMode) ||
+ (eSIR_HT_OP_MODE_OVERLAP_LEGACY ==
+ pBeaconStruct->HTInfo.opMode)) {
+ if (pMac->lim.cfgProtection.fromlla)
+ psessionEntry->beaconParams.llaCoexist = true;
+ } else if (eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT ==
+ pBeaconStruct->HTInfo.opMode) {
+ if (pMac->lim.cfgProtection.ht20)
+ psessionEntry->beaconParams.ht20Coexist = true;
+ }
+
+ } else if (SIR_BAND_2_4_GHZ == rfBand) {
+ /* spec 7.3.2.13 */
+ /* UseProtection will be set when nonERP STA is associated. */
+ /* NonERPPresent bit will be set when: */
+ /* --nonERP Sta is associated OR */
+ /* --nonERP Sta exists in overlapping BSS */
+ /* when useProtection is not set then protection from nonERP stations is optional. */
+
+ /* CFG protection from 11b is enabled and */
+ /* 11B device in the BSS */
+ /* TODO, This is not sessionized */
+ if (phyMode != WNI_CFG_PHY_MODE_11B) {
+ if (pMac->lim.cfgProtection.fromllb &&
+ pBeaconStruct->erpPresent &&
+ (pBeaconStruct->erpIEInfo.useProtection ||
+ pBeaconStruct->erpIEInfo.nonErpPresent)) {
+ psessionEntry->beaconParams.llbCoexist = true;
+ }
+ /* AP has no 11b station associated. */
+ else {
+ psessionEntry->beaconParams.llbCoexist = false;
+ }
+ }
+ /* following code block is only for HT station. */
+ if ((psessionEntry->htCapability) &&
+ (pBeaconStruct->HTInfo.present)) {
+ tDot11fIEHTInfo htInfo = pBeaconStruct->HTInfo;
+
+ /* Obss Non HT STA present mode */
+ psessionEntry->beaconParams.gHTObssMode =
+ (uint8_t) htInfo.obssNonHTStaPresent;
+
+ /* CFG protection from 11G is enabled and */
+ /* our AP has at least one 11G station associated. */
+ if (pMac->lim.cfgProtection.fromllg &&
+ ((eSIR_HT_OP_MODE_MIXED == htInfo.opMode) ||
+ (eSIR_HT_OP_MODE_OVERLAP_LEGACY == htInfo.opMode))
+ && (!psessionEntry->beaconParams.llbCoexist)) {
+ if (pMac->lim.cfgProtection.fromllg)
+ psessionEntry->beaconParams.llgCoexist =
+ true;
+ }
+ /* AP has only HT stations associated and at least one station is HT 20 */
+ /* disable protection from any non-HT devices. */
+ /* decision for disabling protection from 11b has already been taken above. */
+ if (eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT == htInfo.opMode) {
+ /* Disable protection from 11G station. */
+ psessionEntry->beaconParams.llgCoexist = false;
+ /* CFG protection from HT 20 is enabled. */
+ if (pMac->lim.cfgProtection.ht20)
+ psessionEntry->beaconParams.
+ ht20Coexist = true;
+ }
+ /* Disable protection from non-HT and HT20 devices. */
+ /* decision for disabling protection from 11b has already been taken above. */
+ if (eSIR_HT_OP_MODE_PURE == htInfo.opMode) {
+ psessionEntry->beaconParams.llgCoexist = false;
+ psessionEntry->beaconParams.ht20Coexist = false;
+ }
+
+ }
+ }
+ /* protection related factors other than HT operating mode. Applies to 2.4 GHZ as well as 5 GHZ. */
+ if ((psessionEntry->htCapability) && (pBeaconStruct->HTInfo.present)) {
+ tDot11fIEHTInfo htInfo = pBeaconStruct->HTInfo;
+ psessionEntry->beaconParams.fRIFSMode =
+ (uint8_t) htInfo.rifsMode;
+ psessionEntry->beaconParams.llnNonGFCoexist =
+ (uint8_t) htInfo.nonGFDevicesPresent;
+ psessionEntry->beaconParams.fLsigTXOPProtectionFullSupport =
+ (uint8_t) htInfo.lsigTXOPProtectionFullSupport;
+ }
+}
+
+
+/**
+ * lim_decide_sta_11bg_protection() - decides protection related settings on sta
+ * @mac_ctx: pointer to global mac structure
+ * @beacon_struct: pointer to tpschbeaconstruct
+ * @beaconparams: pointer to tpupdatebeaconparams
+ * @psession_entry: pointer to tppesession
+ * @phy_mode: phy mode index
+ *
+ * decides 11bg protection related settings on sta while processing beacon
+ *
+ * Return: none
+ */
+static void
+lim_decide_sta_11bg_protection(tpAniSirGlobal mac_ctx,
+ tpSchBeaconStruct beacon_struct,
+ tpUpdateBeaconParams beaconparams,
+ tpPESession psession_entry,
+ uint32_t phy_mode)
+{
+
+ tDot11fIEHTInfo htInfo;
+
+ /*
+ * spec 7.3.2.13
+ * UseProtection will be set when nonERP STA is associated.
+ * NonERPPresent bit will be set when:
+ * --nonERP Sta is associated OR
+ * --nonERP Sta exists in overlapping BSS
+ * when useProtection is not set then protection from
+ * nonERP stations is optional.
+ */
+ if (phy_mode != WNI_CFG_PHY_MODE_11B) {
+ if (beacon_struct->erpPresent &&
+ (beacon_struct->erpIEInfo.useProtection ||
+ beacon_struct->erpIEInfo.nonErpPresent)) {
+ lim_enable11g_protection(mac_ctx, true, false,
+ beaconparams,
+ psession_entry);
+ }
+ /* AP has no 11b station associated. */
+ else {
+ /* disable protection from 11b station */
+ lim_enable11g_protection(mac_ctx, false, false,
+ beaconparams,
+ psession_entry);
+ }
+ }
+
+ if (!(psession_entry->htCapability) ||
+ !(beacon_struct->HTInfo.present))
+ return;
+
+ /* following code is only for HT station. */
+
+ htInfo = beacon_struct->HTInfo;
+ /* AP has at least one 11G station associated. */
+ if (((eSIR_HT_OP_MODE_MIXED == htInfo.opMode) ||
+ (eSIR_HT_OP_MODE_OVERLAP_LEGACY == htInfo.opMode)) &&
+ (!psession_entry->beaconParams.llbCoexist)) {
+ lim_enable_ht_protection_from11g(mac_ctx, true, false,
+ beaconparams, psession_entry);
+
+ }
+ /*
+ * no HT operating mode change ==> no change in
+ * protection settings except for MIXED_MODE/Legacy
+ * Mode.
+ */
+ /*
+ * in Mixed mode/legacy Mode even if there is no
+ * change in HT operating mode, there might be
+ * change in 11bCoexist or 11gCoexist. Hence this
+ * check is being done after mixed/legacy mode
+ * check.
+ */
+ if (mac_ctx->lim.gHTOperMode !=
+ (tSirMacHTOperatingMode)htInfo.opMode) {
+ mac_ctx->lim.gHTOperMode =
+ (tSirMacHTOperatingMode) htInfo.opMode;
+ /*
+ * AP has only HT stations associated and
+ * at least one station is HT 20
+ */
+
+ /* disable protection from any non-HT devices. */
+
+ /*
+ * decision for disabling protection from
+ * 11b has already been taken above.
+ */
+ if (eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT ==
+ htInfo.opMode) {
+ /* Disable protection from 11G station. */
+ lim_enable_ht_protection_from11g(mac_ctx, false,
+ false, beaconparams,
+ psession_entry);
+
+ lim_enable_ht20_protection(mac_ctx, true, false,
+ beaconparams,
+ psession_entry);
+ }
+ /*
+ * Disable protection from non-HT and
+ * HT20 devices.
+ */
+ /*
+ * decision for disabling protection from
+ * 11b has already been taken above.
+ */
+ else if (eSIR_HT_OP_MODE_PURE == htInfo.opMode) {
+ lim_enable_ht_protection_from11g(mac_ctx, false,
+ false, beaconparams,
+ psession_entry);
+
+ lim_enable_ht20_protection(mac_ctx, false,
+ false, beaconparams,
+ psession_entry);
+
+ }
+ }
+
+}
+
+/**
+ * lim_decide_sta_protection() - decides protection related settings on sta
+ * @mac_ctx: pointer to global mac structure
+ * @beacon_struct: pointer to tpschbeaconstruct
+ * @beaconparams: pointer to tpupdatebeaconparams
+ * @psession_entry: pointer to tppesession
+ *
+ * decides protection related settings on sta while processing beacon
+ *
+ * Return: none
+ */
+void
+lim_decide_sta_protection(tpAniSirGlobal mac_ctx,
+ tpSchBeaconStruct beacon_struct,
+ tpUpdateBeaconParams beaconparams,
+ tpPESession psession_entry)
+{
+
+ tSirRFBand rfband = SIR_BAND_UNKNOWN;
+ uint32_t phy_mode = WNI_CFG_PHY_MODE_NONE;
+
+ lim_get_rf_band_new(mac_ctx, &rfband, psession_entry);
+ lim_get_phy_mode(mac_ctx, &phy_mode, psession_entry);
+
+ if ((SIR_BAND_5_GHZ == rfband) &&
+ /* we are HT capable. */
+ (true == psession_entry->htCapability) &&
+ (beacon_struct->HTInfo.present)) {
+ /*
+ * we are HT capable, AP's HT OPMode is
+ * mixed / overlap legacy ==> need protection
+ * from 11A.
+ */
+ if ((eSIR_HT_OP_MODE_MIXED ==
+ beacon_struct->HTInfo.opMode) ||
+ (eSIR_HT_OP_MODE_OVERLAP_LEGACY ==
+ beacon_struct->HTInfo.opMode)) {
+ lim_update_11a_protection(mac_ctx, true, false,
+ beaconparams, psession_entry);
+ }
+ /*
+ * we are HT capable, AP's HT OPMode is
+ * HT20 ==> disable protection from 11A if
+ * enabled.
+ */
+ /* protection from HT20 if needed. */
+ else if (eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT ==
+ beacon_struct->HTInfo.opMode) {
+ lim_update_11a_protection(mac_ctx, false, false,
+ beaconparams, psession_entry);
+ lim_enable_ht20_protection(mac_ctx, true, false,
+ beaconparams, psession_entry);
+ } else if (eSIR_HT_OP_MODE_PURE ==
+ beacon_struct->HTInfo.opMode) {
+ lim_update_11a_protection(mac_ctx, false, false,
+ beaconparams, psession_entry);
+ lim_enable_ht20_protection(mac_ctx, false,
+ false, beaconparams,
+ psession_entry);
+ }
+ } else if (SIR_BAND_2_4_GHZ == rfband) {
+ lim_decide_sta_11bg_protection(mac_ctx, beacon_struct,
+ beaconparams, psession_entry, phy_mode);
+ }
+ /*
+ * following code block is only for HT station.
+ * (2.4 GHZ as well as 5 GHZ)
+ */
+ if ((psession_entry->htCapability) && (beacon_struct->HTInfo.present)) {
+ tDot11fIEHTInfo htInfo = beacon_struct->HTInfo;
+ /*
+ * Check for changes in protection related factors other
+ * than HT operating mode.
+ */
+ /*
+ * Check for changes in RIFS mode, nonGFDevicesPresent,
+ * lsigTXOPProtectionFullSupport.
+ */
+ if (psession_entry->beaconParams.fRIFSMode !=
+ (uint8_t) htInfo.rifsMode) {
+ beaconparams->fRIFSMode =
+ psession_entry->beaconParams.fRIFSMode =
+ (uint8_t) htInfo.rifsMode;
+ beaconparams->paramChangeBitmap |=
+ PARAM_RIFS_MODE_CHANGED;
+ }
+
+ if (psession_entry->beaconParams.llnNonGFCoexist !=
+ htInfo.nonGFDevicesPresent) {
+ beaconparams->llnNonGFCoexist =
+ psession_entry->beaconParams.llnNonGFCoexist =
+ (uint8_t) htInfo.nonGFDevicesPresent;
+ beaconparams->paramChangeBitmap |=
+ PARAM_NON_GF_DEVICES_PRESENT_CHANGED;
+ }
+
+ if (psession_entry->beaconParams.
+ fLsigTXOPProtectionFullSupport !=
+ (uint8_t) htInfo.lsigTXOPProtectionFullSupport) {
+ beaconparams->fLsigTXOPProtectionFullSupport =
+ psession_entry->beaconParams.
+ fLsigTXOPProtectionFullSupport =
+ (uint8_t) htInfo.
+ lsigTXOPProtectionFullSupport;
+ beaconparams->paramChangeBitmap |=
+ PARAM_LSIG_TXOP_FULL_SUPPORT_CHANGED;
+ }
+ /*
+ * For Station just update the global lim variable,
+ * no need to send message to HAL since Station already
+ * taking care of HT OPR Mode=01,
+ * meaning AP is seeing legacy
+ */
+ /* stations in overlapping BSS. */
+ if (psession_entry->beaconParams.gHTObssMode !=
+ (uint8_t) htInfo.obssNonHTStaPresent)
+ psession_entry->beaconParams.gHTObssMode =
+ (uint8_t) htInfo.obssNonHTStaPresent;
+
+ }
+}
+
+/**
+ * lim_process_channel_switch_timeout()
+ *
+ ***FUNCTION:
+ * This function is invoked when Channel Switch Timer expires at
+ * the STA. Now, STA must stop traffic, and then change/disable
+ * primary or secondary channel.
+ *
+ *
+ ***NOTE:
+ * @param pMac - Pointer to Global MAC structure
+ * @return None
+ */
+void lim_process_channel_switch_timeout(tpAniSirGlobal pMac)
+{
+ tpPESession psessionEntry = NULL;
+ uint8_t channel; /* This is received and stored from channelSwitch Action frame */
+
+ psessionEntry = pe_find_session_by_session_id(pMac,
+ pMac->lim.limTimers.gLimChannelSwitchTimer.sessionId);
+ if (psessionEntry == NULL) {
+ lim_log(pMac, LOGP,
+ FL("Session Does not exist for given sessionID"));
+ return;
+ }
+
+ if (!LIM_IS_STA_ROLE(psessionEntry)) {
+ PELOGW(lim_log
+ (pMac, LOGW,
+ "Channel switch can be done only in STA role, Current Role = %d",
+ GET_LIM_SYSTEM_ROLE(psessionEntry));
+ )
+ return;
+ }
+
+ channel = psessionEntry->gLimChannelSwitch.primaryChannel;
+ /* Restore Channel Switch parameters to default */
+ psessionEntry->gLimChannelSwitch.switchTimeoutValue = 0;
+
+ /* Channel-switch timeout has occurred. reset the state */
+ psessionEntry->gLimSpecMgmt.dot11hChanSwState = eLIM_11H_CHANSW_END;
+
+ /* Check if the AP is switching to a channel that we support.
+ * Else, just don't bother to switch. Indicate HDD to look for a
+ * better AP to associate
+ */
+ if (!lim_is_channel_valid_for_channel_switch(pMac, channel)) {
+ /* We need to restore pre-channelSwitch state on the STA */
+ if (lim_restore_pre_channel_switch_state(pMac, psessionEntry) !=
+ eSIR_SUCCESS) {
+ lim_log(pMac, LOGP,
+ FL
+ ("Could not restore pre-channelSwitch (11h) state, resetting the system"));
+ return;
+ }
+
+ /* If the channel-list that AP is asking us to switch is invalid,
+ * then we cannot switch the channel. Just disassociate from AP.
+ * We will find a better AP !!!
+ */
+ lim_tear_down_link_with_ap(pMac,
+ pMac->lim.limTimers.
+ gLimChannelSwitchTimer.sessionId,
+ eSIR_MAC_UNSPEC_FAILURE_REASON);
+ return;
+ }
+ lim_covert_channel_scan_type(pMac, psessionEntry->currentOperChannel,
+ false);
+ pMac->lim.dfschannelList.timeStamp[psessionEntry->currentOperChannel] =
+ 0;
+ switch (psessionEntry->gLimChannelSwitch.state) {
+ case eLIM_CHANNEL_SWITCH_PRIMARY_ONLY:
+ PELOGW(lim_log(pMac, LOGW, FL("CHANNEL_SWITCH_PRIMARY_ONLY "));)
+ lim_switch_primary_channel(pMac,
+ psessionEntry->gLimChannelSwitch.
+ primaryChannel, psessionEntry);
+ psessionEntry->gLimChannelSwitch.state =
+ eLIM_CHANNEL_SWITCH_IDLE;
+ break;
+ case eLIM_CHANNEL_SWITCH_PRIMARY_AND_SECONDARY:
+ PELOGW(lim_log
+ (pMac, LOGW, FL("CHANNEL_SWITCH_PRIMARY_AND_SECONDARY"));
+ )
+ lim_switch_primary_secondary_channel(pMac, psessionEntry,
+ psessionEntry->gLimChannelSwitch.primaryChannel,
+ psessionEntry->gLimChannelSwitch.ch_center_freq_seg0,
+ psessionEntry->gLimChannelSwitch.ch_center_freq_seg1,
+ psessionEntry->gLimChannelSwitch.ch_width);
+ psessionEntry->gLimChannelSwitch.state =
+ eLIM_CHANNEL_SWITCH_IDLE;
+ break;
+
+ case eLIM_CHANNEL_SWITCH_IDLE:
+ default:
+ PELOGE(lim_log(pMac, LOGE, FL("incorrect state "));)
+ if (lim_restore_pre_channel_switch_state(pMac, psessionEntry) !=
+ eSIR_SUCCESS) {
+ lim_log(pMac, LOGP,
+ FL
+ ("Could not restore pre-channelSwitch (11h) state, resetting the system"));
+ }
+ return; /* Please note, this is 'return' and not 'break' */
+ }
+}
+
+/**
+ * lim_update_channel_switch() - This Function updates channel switch
+ * @mac_ctx: pointer to Global MAC structure
+ * @beacon: pointer to tpSirProbeRespBeacon
+ * @psessionentry: pointer to tpPESession
+ *
+ * This function is invoked whenever Station receives
+ * either 802.11h channel switch IE or airgo proprietary
+ * channel switch IE.
+ *
+ * Return: none
+ */
+void
+lim_update_channel_switch(struct sAniSirGlobal *mac_ctx,
+ tpSirProbeRespBeacon beacon,
+ tpPESession psession_entry)
+{
+ uint16_t beacon_period;
+ tDot11fIEChanSwitchAnn *chnl_switch;
+ tLimChannelSwitchInfo *ch_switch_params;
+#ifdef WLAN_FEATURE_11AC
+ tDot11fIEWiderBWChanSwitchAnn *widerchnl_switch;
+#endif
+
+ beacon_period = psession_entry->beaconParams.beaconInterval;
+
+ /* 802.11h standard channel switch IE */
+ chnl_switch = &(beacon->channelSwitchIE);
+ ch_switch_params = &psession_entry->gLimChannelSwitch;
+ ch_switch_params->primaryChannel =
+ chnl_switch->newChannel;
+ ch_switch_params->switchCount = chnl_switch->switchCount;
+ ch_switch_params->switchTimeoutValue =
+ SYS_MS_TO_TICKS(beacon_period) * (chnl_switch->switchCount);
+ ch_switch_params->switchMode = chnl_switch->switchMode;
+#ifdef WLAN_FEATURE_11AC
+ widerchnl_switch = &(beacon->WiderBWChanSwitchAnn);
+ if (beacon->WiderBWChanSwitchAnnPresent) {
+ psession_entry->gLimWiderBWChannelSwitch.newChanWidth =
+ widerchnl_switch->newChanWidth;
+ psession_entry->gLimWiderBWChannelSwitch.newCenterChanFreq0 =
+ widerchnl_switch->newCenterChanFreq0;
+ psession_entry->gLimWiderBWChannelSwitch.newCenterChanFreq1 =
+ widerchnl_switch->newCenterChanFreq1;
+ }
+#endif
+
+ /* Only primary channel switch element is present */
+ ch_switch_params->state =
+ eLIM_CHANNEL_SWITCH_PRIMARY_ONLY;
+ ch_switch_params->ch_width = CH_WIDTH_20MHZ;
+
+ /*
+ * Do not bother to look and operate on extended channel switch element
+ * if our own channel-bonding state is not enabled
+ */
+ if (psession_entry->htSupportedChannelWidthSet &&
+ beacon->sec_chan_offset_present) {
+ if (beacon->sec_chan_offset.secondaryChannelOffset ==
+ PHY_DOUBLE_CHANNEL_LOW_PRIMARY) {
+ ch_switch_params->state =
+ eLIM_CHANNEL_SWITCH_PRIMARY_AND_SECONDARY;
+ ch_switch_params->ch_width = CH_WIDTH_40MHZ;
+ ch_switch_params->ch_center_freq_seg0 =
+ ch_switch_params->primaryChannel + 2;
+ } else if (beacon->sec_chan_offset.secondaryChannelOffset ==
+ PHY_DOUBLE_CHANNEL_HIGH_PRIMARY) {
+ ch_switch_params->state =
+ eLIM_CHANNEL_SWITCH_PRIMARY_AND_SECONDARY;
+ ch_switch_params->ch_width = CH_WIDTH_40MHZ;
+ ch_switch_params->ch_center_freq_seg0 =
+ ch_switch_params->primaryChannel - 2;
+ }
+#ifdef WLAN_FEATURE_11AC
+ if (psession_entry->vhtCapability &&
+ beacon->WiderBWChanSwitchAnnPresent) {
+ ch_switch_params->ch_width =
+ widerchnl_switch->newChanWidth + 1;
+ ch_switch_params->ch_center_freq_seg0 =
+ psession_entry->gLimWiderBWChannelSwitch.
+ newCenterChanFreq0;
+ ch_switch_params->ch_center_freq_seg1 =
+ psession_entry->gLimWiderBWChannelSwitch.
+ newCenterChanFreq1;
+#endif
+ }
+ }
+ if (eSIR_SUCCESS != lim_start_channel_switch(mac_ctx, psession_entry))
+ lim_log(mac_ctx, LOGW, FL("Could not start Channel Switch"));
+
+ lim_log(mac_ctx, LOGW,
+ FL("session %d primary chl %d, ch_width %d, count %d (%d ticks)"),
+ psession_entry->peSessionId,
+ psession_entry->gLimChannelSwitch.primaryChannel,
+ psession_entry->gLimChannelSwitch.ch_width,
+ psession_entry->gLimChannelSwitch.switchCount,
+ psession_entry->gLimChannelSwitch.switchTimeoutValue);
+ return;
+}
+
+/**
+ * lim_cancel_dot11h_channel_switch
+ *
+ ***FUNCTION:
+ * This function is called when STA does not send updated channel-swith IE
+ * after indicating channel-switch start. This will cancel the channel-swith
+ * timer which is already running.
+ *
+ ***LOGIC:
+ *
+ ***ASSUMPTIONS:
+ *
+ ***NOTE:
+ *
+ * @param pMac - Pointer to Global MAC structure
+ *
+ * @return None
+ */
+void lim_cancel_dot11h_channel_switch(tpAniSirGlobal pMac,
+ tpPESession psessionEntry)
+{
+ if (!LIM_IS_STA_ROLE(psessionEntry))
+ return;
+
+ PELOGW(lim_log
+ (pMac, LOGW, FL("Received a beacon without channel switch IE"));
+ )
+ MTRACE(mac_trace
+ (pMac, TRACE_CODE_TIMER_DEACTIVATE,
+ psessionEntry->peSessionId, eLIM_CHANNEL_SWITCH_TIMER));
+
+ if (tx_timer_deactivate(&pMac->lim.limTimers.gLimChannelSwitchTimer) !=
+ eSIR_SUCCESS) {
+ PELOGE(lim_log(pMac, LOGE, FL("tx_timer_deactivate failed!"));)
+ }
+
+ /* We need to restore pre-channelSwitch state on the STA */
+ if (lim_restore_pre_channel_switch_state(pMac, psessionEntry) !=
+ eSIR_SUCCESS) {
+ PELOGE(lim_log
+ (pMac, LOGE,
+ FL
+ ("LIM: Could not restore pre-channelSwitch (11h) state, resetting the system"));
+ )
+
+ }
+}
+
+/**
+ * lim_cancel_dot11h_quiet()
+ *
+ * @mac_ctx: pointer to global mac structure
+ * @psession_entry: pointer to tppesession
+ *
+ * Cancel the quieting on Station if latest beacon
+ * doesn't contain quiet IE in it.
+ *
+ * Return: none
+ */
+void lim_cancel_dot11h_quiet(tpAniSirGlobal pMac, tpPESession psessionEntry)
+{
+ if (!LIM_IS_STA_ROLE(psessionEntry))
+ return;
+
+ if (psessionEntry->gLimSpecMgmt.quietState == eLIM_QUIET_BEGIN) {
+ MTRACE(mac_trace
+ (pMac, TRACE_CODE_TIMER_DEACTIVATE,
+ psessionEntry->peSessionId, eLIM_QUIET_TIMER));
+ if (tx_timer_deactivate(&pMac->lim.limTimers.gLimQuietTimer) !=
+ TX_SUCCESS) {
+ PELOGE(lim_log
+ (pMac, LOGE, FL("tx_timer_deactivate failed"));
+ )
+ }
+ } else if (psessionEntry->gLimSpecMgmt.quietState == eLIM_QUIET_RUNNING) {
+ MTRACE(mac_trace
+ (pMac, TRACE_CODE_TIMER_DEACTIVATE,
+ psessionEntry->peSessionId, eLIM_QUIET_BSS_TIMER));
+ if (tx_timer_deactivate(&pMac->lim.limTimers.gLimQuietBssTimer)
+ != TX_SUCCESS) {
+ PELOGE(lim_log
+ (pMac, LOGE, FL("tx_timer_deactivate failed"));
+ )
+ }
+ /**
+ * If the channel switch is already running in silent mode, dont resume the
+ * transmission. Channel switch timer when timeout, transmission will be resumed.
+ */
+ if (!
+ ((psessionEntry->gLimSpecMgmt.dot11hChanSwState ==
+ eLIM_11H_CHANSW_RUNNING)
+ && (psessionEntry->gLimChannelSwitch.switchMode ==
+ eSIR_CHANSW_MODE_SILENT))) {
+ lim_frame_transmission_control(pMac, eLIM_TX_ALL,
+ eLIM_RESUME_TX);
+ lim_restore_pre_quiet_state(pMac, psessionEntry);
+ }
+ }
+ psessionEntry->gLimSpecMgmt.quietState = eLIM_QUIET_INIT;
+}
+
+/**
+ * lim_process_quiet_timeout
+ *
+ * FUNCTION:
+ * This function is active only on the STA.
+ * Handles SIR_LIM_QUIET_TIMEOUT
+ *
+ * LOGIC:
+ * This timeout can occur under only one circumstance:
+ *
+ * 1) When gLimQuietState = eLIM_QUIET_BEGIN
+ * This indicates that the timeout "interval" has
+ * expired. This is a trigger for the STA to now
+ * shut-off Tx/Rx for the specified gLimQuietDuration
+ * -> The TIMER object gLimQuietBssTimer is
+ * activated
+ * -> With timeout = gLimQuietDuration
+ * -> gLimQuietState is set to eLIM_QUIET_RUNNING
+ *
+ * ASSUMPTIONS:
+ * Using two TIMER objects -
+ * gLimQuietTimer & gLimQuietBssTimer
+ *
+ * NOTE:
+ *
+ * @param pMac - Pointer to Global MAC structure
+ *
+ * @return None
+ */
+void lim_process_quiet_timeout(tpAniSirGlobal pMac)
+{
+ tpPESession psessionEntry;
+
+ psessionEntry = pe_find_session_by_session_id(pMac,
+ pMac->lim.limTimers.gLimQuietTimer.sessionId);
+ if (psessionEntry == NULL) {
+ lim_log(pMac, LOGE,
+ FL("Session Does not exist for given sessionID"));
+ return;
+ }
+
+ PELOG1(lim_log
+ (pMac, LOG1, FL("quietState = %d"),
+ psessionEntry->gLimSpecMgmt.quietState);
+ )
+ switch (psessionEntry->gLimSpecMgmt.quietState) {
+ case eLIM_QUIET_BEGIN:
+ /* Time to Stop data traffic for quietDuration */
+ /* lim_deactivate_and_change_timer(pMac, eLIM_QUIET_BSS_TIMER); */
+ if (TX_SUCCESS != tx_timer_deactivate(
+ &pMac->lim.limTimers.gLimQuietBssTimer)) {
+ lim_log(pMac, LOGE,
+ FL
+ ("Unable to de-activate gLimQuietBssTimer! Will attempt to activate anyway..."));
+ }
+ /* gLimQuietDuration appears to be in units of ticks */
+ /* Use it as is */
+ if (TX_SUCCESS !=
+ tx_timer_change(&pMac->lim.limTimers.gLimQuietBssTimer,
+ psessionEntry->gLimSpecMgmt.quietDuration,
+ 0)) {
+ lim_log(pMac, LOGE,
+ FL
+ ("Unable to change gLimQuietBssTimer! Will still attempt to activate anyway..."));
+ }
+ MTRACE(mac_trace
+ (pMac, TRACE_CODE_TIMER_ACTIVATE,
+ pMac->lim.limTimers.gLimQuietTimer.sessionId,
+ eLIM_QUIET_BSS_TIMER));
+ if (TX_SUCCESS !=
+ tx_timer_activate(&pMac->lim.limTimers.gLimQuietBssTimer)) {
+ lim_log(pMac, LOGW,
+ FL
+ ("Unable to activate gLimQuietBssTimer! The STA will be unable to honor Quiet BSS..."));
+ } else {
+ /* Transition to eLIM_QUIET_RUNNING */
+ psessionEntry->gLimSpecMgmt.quietState =
+ eLIM_QUIET_RUNNING;
+ /* Shut-off Tx/Rx for gLimSpecMgmt.quietDuration */
+ /* freeze the transmission */
+ lim_frame_transmission_control(pMac, eLIM_TX_ALL,
+ eLIM_STOP_TX);
+
+ lim_log(pMac, LOG2,
+ FL("Quiet BSS: STA shutting down for %d ticks"),
+ psessionEntry->gLimSpecMgmt.quietDuration);
+ }
+ break;
+
+ case eLIM_QUIET_RUNNING:
+ case eLIM_QUIET_INIT:
+ case eLIM_QUIET_END:
+ default:
+ /* */
+ /* As of now, nothing to be done */
+ /* */
+ break;
+ }
+}
+
+/**
+ * lim_process_quiet_bss_timeout() - Handles SIR_LIM_QUIET_BSS_TIMEOUT
+ * @mac_ctx: pointer to Globale Mac Structure
+ *
+ * This function is active on the AP and STA.
+ * Handles SIR_LIM_QUIET_BSS_TIMEOUT
+ *
+ * On the AP -
+ * When the SIR_LIM_QUIET_BSS_TIMEOUT is triggered, it is
+ * an indication for the AP to START sending out the
+ * Quiet BSS IE.
+ * If 802.11H is enabled, the Quiet BSS IE is sent as per
+ * the 11H spec
+ * If 802.11H is not enabled, the Quiet BSS IE is sent as
+ * a Proprietary IE. This will be understood by all the
+ * TITAN STA's
+ * Transitioning gLimQuietState to eLIM_QUIET_BEGIN will
+ * initiate the SCH to include the Quiet BSS IE in all
+ * its subsequent Beacons/PR's.
+ * The Quiet BSS IE will be included in all the Beacons
+ * & PR's until the next DTIM period
+ *
+ * On the STA -
+ * When gLimQuietState = eLIM_QUIET_RUNNING
+ * This indicates that the STA was successfully shut-off
+ * for the specified gLimQuietDuration. This is a trigger
+ * for the STA to now resume data traffic.
+ * -> gLimQuietState is set to eLIM_QUIET_INIT
+ *
+ *
+ * Return: none
+ */
+void lim_process_quiet_bss_timeout(tpAniSirGlobal mac_ctx)
+{
+ tpPESession psession_entry = NULL;
+ tLimTimers *lim_timer = &mac_ctx->lim.limTimers;
+
+ psession_entry = pe_find_session_by_session_id(mac_ctx,
+ lim_timer->gLimQuietBssTimer.sessionId);
+
+ if (psession_entry == NULL) {
+ lim_log(mac_ctx, LOGP,
+ FL("Session Does not exist for given sessionID"));
+ return;
+ }
+
+ lim_log(mac_ctx, LOG1, FL("quietState = %d"),
+ psession_entry->gLimSpecMgmt.quietState);
+
+ if (LIM_IS_AP_ROLE(psession_entry))
+ return;
+
+ /* eLIM_STA_ROLE */
+ switch (psession_entry->gLimSpecMgmt.quietState) {
+ case eLIM_QUIET_RUNNING:
+ /* Transition to eLIM_QUIET_INIT */
+ psession_entry->gLimSpecMgmt.quietState = eLIM_QUIET_INIT;
+
+ /*
+ * Resume data traffic only if channel switch is
+ * not running in silent mode.
+ */
+ if (!((psession_entry->gLimSpecMgmt.dot11hChanSwState ==
+ eLIM_11H_CHANSW_RUNNING) &&
+ (psession_entry->gLimChannelSwitch.switchMode ==
+ eSIR_CHANSW_MODE_SILENT))) {
+ lim_frame_transmission_control(mac_ctx, eLIM_TX_ALL,
+ eLIM_RESUME_TX);
+ lim_restore_pre_quiet_state(mac_ctx, psession_entry);
+ }
+ lim_log(mac_ctx, LOG2, FL("Quiet BSS: Resuming traffic..."));
+ break;
+
+ case eLIM_QUIET_INIT:
+ case eLIM_QUIET_BEGIN:
+ case eLIM_QUIET_END:
+ lim_log(mac_ctx, LOG2, FL("Quiet state not in RUNNING"));
+ /*
+ * If the quiet period has ended, then resume the
+ * frame transmission
+ */
+ lim_frame_transmission_control(mac_ctx, eLIM_TX_ALL,
+ eLIM_RESUME_TX);
+ lim_restore_pre_quiet_state(mac_ctx, psession_entry);
+ psession_entry->gLimSpecMgmt.quietState = eLIM_QUIET_INIT;
+ break;
+
+ default:
+ /* As of now, nothing to be done */
+ break;
+ }
+}
+
+/**----------------------------------------------
+ \fn lim_start_quiet_timer
+ \brief Starts the quiet timer.
+
+ \param pMac
+ \return NONE
+ -----------------------------------------------*/
+void lim_start_quiet_timer(tpAniSirGlobal pMac, uint8_t sessionId)
+{
+ tpPESession psessionEntry;
+ psessionEntry = pe_find_session_by_session_id(pMac, sessionId);
+
+ if (psessionEntry == NULL) {
+ lim_log(pMac, LOGP,
+ FL("Session Does not exist for given sessionID"));
+ return;
+ }
+
+ if (!LIM_IS_STA_ROLE(psessionEntry))
+ return;
+ /* First, de-activate Timer, if its already active */
+ lim_cancel_dot11h_quiet(pMac, psessionEntry);
+
+ MTRACE(mac_trace
+ (pMac, TRACE_CODE_TIMER_ACTIVATE, sessionId, eLIM_QUIET_TIMER));
+ if (TX_SUCCESS !=
+ tx_timer_deactivate(&pMac->lim.limTimers.gLimQuietTimer)) {
+ lim_log(pMac, LOGE,
+ FL
+ ("Unable to deactivate gLimQuietTimer! Will still attempt to re-activate anyway..."));
+ }
+ /* Set the NEW timeout value, in ticks */
+ if (TX_SUCCESS != tx_timer_change(&pMac->lim.limTimers.gLimQuietTimer,
+ SYS_MS_TO_TICKS(psessionEntry->
+ gLimSpecMgmt.
+ quietTimeoutValue),
+ 0)) {
+ lim_log(pMac, LOGE,
+ FL
+ ("Unable to change gLimQuietTimer! Will still attempt to re-activate anyway..."));
+ }
+
+ pMac->lim.limTimers.gLimQuietTimer.sessionId = sessionId;
+ if (TX_SUCCESS !=
+ tx_timer_activate(&pMac->lim.limTimers.gLimQuietTimer)) {
+ lim_log(pMac, LOGE,
+ FL
+ ("Unable to activate gLimQuietTimer! STA cannot honor Quiet BSS!"));
+ lim_restore_pre_quiet_state(pMac, psessionEntry);
+
+ psessionEntry->gLimSpecMgmt.quietState = eLIM_QUIET_INIT;
+ return;
+ }
+}
+
+/** ------------------------------------------------------------------------ **/
+/**
+ * keep track of the number of ANI peers associated in the BSS
+ * For the first and last ANI peer, we have to update EDCA params as needed
+ *
+ * When the first ANI peer joins the BSS, we notify SCH
+ * When the last ANI peer leaves the BSS, we notfiy SCH
+ */
+void
+lim_util_count_sta_add(tpAniSirGlobal pMac,
+ tpDphHashNode pSta, tpPESession psessionEntry)
+{
+
+ if ((!pSta) || (!pSta->valid) || (pSta->fAniCount))
+ return;
+
+ pSta->fAniCount = 1;
+
+ if (pMac->lim.gLimNumOfAniSTAs++ != 0)
+ return;
+
+ /* get here only if this is the first ANI peer in the BSS */
+ sch_edca_profile_update(pMac, psessionEntry);
+}
+
+void
+lim_util_count_sta_del(tpAniSirGlobal pMac,
+ tpDphHashNode pSta, tpPESession psessionEntry)
+{
+
+ if ((pSta == NULL) || (!pSta->fAniCount))
+ return;
+
+ /* Only if sta is invalid and the validInDummyState bit is set to 1,
+ * then go ahead and update the count and profiles. This ensures
+ * that the "number of ani station" count is properly incremented/decremented.
+ */
+ if (pSta->valid == 1)
+ return;
+
+ pSta->fAniCount = 0;
+
+ if (pMac->lim.gLimNumOfAniSTAs <= 0) {
+ lim_log(pMac, LOGE,
+ FL
+ ("CountStaDel: ignoring Delete Req when AniPeer count is %d"),
+ pMac->lim.gLimNumOfAniSTAs);
+ return;
+ }
+
+ pMac->lim.gLimNumOfAniSTAs--;
+
+ if (pMac->lim.gLimNumOfAniSTAs != 0)
+ return;
+
+ /* get here only if this is the last ANI peer in the BSS */
+ sch_edca_profile_update(pMac, psessionEntry);
+}
+
+/**
+ * lim_switch_channel_cback()
+ *
+ ***FUNCTION:
+ * This is the callback function registered while requesting to switch channel
+ * after AP indicates a channel switch for spectrum management (11h).
+ *
+ ***NOTE:
+ * @param pMac Pointer to Global MAC structure
+ * @param status Status of channel switch request
+ * @param data User data
+ * @param psessionEntry Session information
+ * @return NONE
+ */
+void lim_switch_channel_cback(tpAniSirGlobal pMac, CDF_STATUS status,
+ uint32_t *data, tpPESession psessionEntry)
+{
+ tSirMsgQ mmhMsg = { 0 };
+ tSirSmeSwitchChannelInd *pSirSmeSwitchChInd;
+
+ psessionEntry->currentOperChannel = psessionEntry->currentReqChannel;
+
+ /* We need to restore pre-channelSwitch state on the STA */
+ if (lim_restore_pre_channel_switch_state(pMac, psessionEntry) !=
+ eSIR_SUCCESS) {
+ lim_log(pMac, LOGP,
+ FL
+ ("Could not restore pre-channelSwitch (11h) state, resetting the system"));
+ return;
+ }
+
+ mmhMsg.type = eWNI_SME_SWITCH_CHL_IND;
+ pSirSmeSwitchChInd = cdf_mem_malloc(sizeof(tSirSmeSwitchChannelInd));
+ if (NULL == pSirSmeSwitchChInd) {
+ lim_log(pMac, LOGP,
+ FL("Failed to allocate buffer for buffer descriptor"));
+ return;
+ }
+
+ pSirSmeSwitchChInd->messageType = eWNI_SME_SWITCH_CHL_IND;
+ pSirSmeSwitchChInd->length = sizeof(tSirSmeSwitchChannelInd);
+ pSirSmeSwitchChInd->newChannelId =
+ psessionEntry->gLimChannelSwitch.primaryChannel;
+ pSirSmeSwitchChInd->sessionId = psessionEntry->smeSessionId;
+ cdf_mem_copy(pSirSmeSwitchChInd->bssId, psessionEntry->bssId,
+ sizeof(tSirMacAddr));
+ mmhMsg.bodyptr = pSirSmeSwitchChInd;
+ mmhMsg.bodyval = 0;
+
+ MTRACE(mac_trace_msg_tx(pMac, psessionEntry->peSessionId, mmhMsg.type));
+
+ sys_process_mmh_msg(pMac, &mmhMsg);
+}
+
+/**
+ * lim_switch_primary_channel()
+ *
+ ***FUNCTION:
+ * This function changes the current operating channel
+ * and sets the new new channel ID in WNI_CFG_CURRENT_CHANNEL.
+ *
+ ***NOTE:
+ * @param pMac Pointer to Global MAC structure
+ * @param newChannel new chnannel ID
+ * @return NONE
+ */
+void lim_switch_primary_channel(tpAniSirGlobal pMac, uint8_t newChannel,
+ tpPESession psessionEntry)
+{
+#if !defined WLAN_FEATURE_VOWIFI
+ uint32_t localPwrConstraint;
+#endif
+
+ PELOG3(lim_log
+ (pMac, LOG3,
+ FL("lim_switch_primary_channel: old chnl %d --> new chnl %d "),
+ psessionEntry->currentOperChannel, newChannel);
+ )
+ psessionEntry->currentReqChannel = newChannel;
+ psessionEntry->limRFBand = lim_get_rf_band(newChannel);
+
+ psessionEntry->channelChangeReasonCode = LIM_SWITCH_CHANNEL_OPERATION;
+
+ pMac->lim.gpchangeChannelCallback = lim_switch_channel_cback;
+ pMac->lim.gpchangeChannelData = NULL;
+
+#if defined WLAN_FEATURE_VOWIFI
+ lim_send_switch_chnl_params(pMac, newChannel, 0, 0, CH_WIDTH_20MHZ,
+ psessionEntry->maxTxPower,
+ psessionEntry->peSessionId, false);
+#else
+ if (wlan_cfg_get_int
+ (pMac, WNI_CFG_LOCAL_POWER_CONSTRAINT,
+ &localPwrConstraint) != eSIR_SUCCESS) {
+ lim_log(pMac, LOGP,
+ FL("Unable to read Local Power Constraint from cfg"));
+ return;
+ }
+ lim_send_switch_chnl_params(pMac, newChannel, 0, 0, CH_WIDTH_20MHZ,
+ (tPowerdBm) localPwrConstraint,
+ psessionEntry->peSessionId, false);
+#endif
+ return;
+}
+
+/**
+ * lim_switch_primary_secondary_channel()
+ *
+ ***FUNCTION:
+ * This function changes the primary and secondary channel.
+ * If 11h is enabled and user provides a "new channel ID"
+ * that is different from the current operating channel,
+ * then we must set this new channel in WNI_CFG_CURRENT_CHANNEL,
+ * assign notify LIM of such change.
+ *
+ ***NOTE:
+ * @param pMac Pointer to Global MAC structure
+ * @param newChannel New chnannel ID (or current channel ID)
+ * @param subband CB secondary info:
+ * - eANI_CB_SECONDARY_NONE
+ * - eANI_CB_SECONDARY_UP
+ * - eANI_CB_SECONDARY_DOWN
+ * @return NONE
+ */
+void lim_switch_primary_secondary_channel(tpAniSirGlobal pMac,
+ tpPESession psessionEntry,
+ uint8_t newChannel,
+ uint8_t ch_center_freq_seg0,
+ uint8_t ch_center_freq_seg1,
+ phy_ch_width ch_width)
+{
+#if !defined WLAN_FEATURE_VOWIFI
+ uint32_t localPwrConstraint;
+#endif
+ uint8_t subband = 0;
+#if !defined WLAN_FEATURE_VOWIFI
+ if (wlan_cfg_get_int
+ (pMac, WNI_CFG_LOCAL_POWER_CONSTRAINT,
+ &localPwrConstraint) != eSIR_SUCCESS) {
+ lim_log(pMac, LOGP,
+ FL("Unable to get Local Power Constraint from cfg"));
+ return;
+ }
+#endif
+ /* Assign the callback to resume TX once channel is changed. */
+ psessionEntry->currentReqChannel = newChannel;
+ psessionEntry->limRFBand = lim_get_rf_band(newChannel);
+ psessionEntry->channelChangeReasonCode = LIM_SWITCH_CHANNEL_OPERATION;
+ pMac->lim.gpchangeChannelCallback = lim_switch_channel_cback;
+ pMac->lim.gpchangeChannelData = NULL;
+
+#if defined WLAN_FEATURE_VOWIFI
+ lim_send_switch_chnl_params(pMac, newChannel, ch_center_freq_seg0,
+ ch_center_freq_seg1, ch_width,
+ psessionEntry->maxTxPower,
+ psessionEntry->peSessionId,
+ false);
+#else
+ lim_send_switch_chnl_params(pMac, newChannel, ch_center_freq_seg0,
+ ch_center_freq_seg1, ch_width,
+ psessionEntry->peSessionId,
+ false);
+#endif
+
+ /* Store the new primary and secondary channel in session entries if different */
+ if (psessionEntry->currentOperChannel != newChannel) {
+ lim_log(pMac, LOGW,
+ FL("switch old chnl %d --> new chnl %d "),
+ psessionEntry->currentOperChannel, newChannel);
+ psessionEntry->currentOperChannel = newChannel;
+ }
+ if (psessionEntry->htSecondaryChannelOffset != subband) {
+ lim_log(pMac, LOGW,
+ FL("switch old sec chnl %d --> new sec chnl %d "),
+ psessionEntry->htSecondaryChannelOffset, subband);
+ psessionEntry->htSecondaryChannelOffset = subband;
+ if (psessionEntry->htSecondaryChannelOffset ==
+ PHY_SINGLE_CHANNEL_CENTERED) {
+ psessionEntry->htSupportedChannelWidthSet =
+ WNI_CFG_CHANNEL_BONDING_MODE_DISABLE;
+ } else {
+ psessionEntry->htSupportedChannelWidthSet =
+ WNI_CFG_CHANNEL_BONDING_MODE_ENABLE;
+ }
+ psessionEntry->htRecommendedTxWidthSet =
+ psessionEntry->htSupportedChannelWidthSet;
+ }
+
+ return;
+}
+
+/**
+ * lim_active_scan_allowed()
+ *
+ ***FUNCTION:
+ * Checks if active scans are permitted on the given channel
+ *
+ ***LOGIC:
+ * The config variable SCAN_CONTROL_LIST contains pairs of (channelNum, activeScanAllowed)
+ * Need to check if the channelNum matches, then depending on the corresponding
+ * scan flag, return true (for activeScanAllowed==1) or false (otherwise).
+ *
+ ***ASSUMPTIONS:
+ *
+ ***NOTE:
+ *
+ * @param pMac Pointer to Global MAC structure
+ * @param channelNum channel number
+ * @return None
+ */
+
+uint8_t lim_active_scan_allowed(tpAniSirGlobal pMac, uint8_t channelNum)
+{
+ uint32_t i;
+ uint8_t channelPair[WNI_CFG_SCAN_CONTROL_LIST_LEN];
+ uint32_t len = WNI_CFG_SCAN_CONTROL_LIST_LEN;
+ if (wlan_cfg_get_str(pMac, WNI_CFG_SCAN_CONTROL_LIST, channelPair, &len)
+ != eSIR_SUCCESS) {
+ PELOGE(lim_log
+ (pMac, LOGE, FL("Unable to get scan control list"));
+ )
+ return false;
+ }
+
+ if (len > WNI_CFG_SCAN_CONTROL_LIST_LEN) {
+ lim_log(pMac, LOGE, FL("Invalid scan control list length:%d"),
+ len);
+ return false;
+ }
+
+ for (i = 0; (i + 1) < len; i += 2) {
+ if (channelPair[i] == channelNum)
+ return ((channelPair[i + 1] ==
+ eSIR_ACTIVE_SCAN) ? true : false);
+ }
+ return false;
+}
+
+/**
+ * lim_get_ht_capability()
+ *
+ ***FUNCTION:
+ * A utility function that returns the "current HT capability state" for the HT
+ * capability of interest (as requested in the API)
+ *
+ ***LOGIC:
+ * This routine will return with the "current" setting of a requested HT
+ * capability. This state info could be retrieved from -
+ * a) CFG (for static entries)
+ * b) Run time info
+ * - Dynamic state maintained by LIM
+ * - Configured at radio init time by SME
+ *
+ *
+ ***ASSUMPTIONS:
+ * NA
+ *
+ ***NOTE:
+ *
+ * @param pMac Pointer to Global MAC structure
+ * @param htCap The HT capability being queried
+ * @return uint8_t The current state of the requested HT capability is returned in a
+ * uint8_t variable
+ */
+
+uint8_t lim_get_ht_capability(tpAniSirGlobal pMac,
+ uint32_t htCap, tpPESession psessionEntry)
+{
+ uint8_t retVal = 0;
+ uint8_t *ptr;
+ uint32_t cfgValue;
+ tSirMacHTCapabilityInfo macHTCapabilityInfo = { 0 };
+ tSirMacExtendedHTCapabilityInfo macExtHTCapabilityInfo = { 0 };
+ tSirMacTxBFCapabilityInfo macTxBFCapabilityInfo = { 0 };
+ tSirMacASCapabilityInfo macASCapabilityInfo = { 0 };
+
+ /* */
+ /* Determine which CFG to read from. Not ALL of the HT */
+ /* related CFG's need to be read each time this API is */
+ /* accessed */
+ /* */
+ if (htCap >= eHT_ANTENNA_SELECTION && htCap < eHT_SI_GRANULARITY) {
+ /* Get Antenna Seletion HT Capabilities */
+ if (eSIR_SUCCESS !=
+ wlan_cfg_get_int(pMac, WNI_CFG_AS_CAP, &cfgValue))
+ cfgValue = 0;
+ ptr = (uint8_t *) &macASCapabilityInfo;
+ *((uint8_t *) ptr) = (uint8_t) (cfgValue & 0xff);
+ } else {
+ if (htCap >= eHT_TX_BEAMFORMING &&
+ htCap < eHT_ANTENNA_SELECTION) {
+ /* Get Transmit Beam Forming HT Capabilities */
+ if (eSIR_SUCCESS !=
+ wlan_cfg_get_int(pMac, WNI_CFG_TX_BF_CAP, &cfgValue))
+ cfgValue = 0;
+ ptr = (uint8_t *) &macTxBFCapabilityInfo;
+ *((uint32_t *) ptr) = (uint32_t) (cfgValue);
+ } else {
+ if (htCap >= eHT_PCO && htCap < eHT_TX_BEAMFORMING) {
+ /* Get Extended HT Capabilities */
+ if (eSIR_SUCCESS !=
+ wlan_cfg_get_int(pMac,
+ WNI_CFG_EXT_HT_CAP_INFO,
+ &cfgValue))
+ cfgValue = 0;
+ ptr = (uint8_t *) &macExtHTCapabilityInfo;
+ *((uint16_t *) ptr) =
+ (uint16_t) (cfgValue & 0xffff);
+ } else {
+ if (htCap < eHT_MAX_RX_AMPDU_FACTOR) {
+ /* Get HT Capabilities */
+ if (eSIR_SUCCESS !=
+ wlan_cfg_get_int(pMac,
+ WNI_CFG_HT_CAP_INFO,
+ &cfgValue))
+ cfgValue = 0;
+ ptr = (uint8_t *) &macHTCapabilityInfo;
+ /* CR 265282 MDM SoftAP 2.4PL: SoftAP boot up crash in 2.4 PL builds while same WLAN SU is working on 2.1 PL */
+ *ptr++ = cfgValue & 0xff;
+ *ptr = (cfgValue >> 8) & 0xff;
+ }
+ }
+ }
+ }
+
+ switch (htCap) {
+ case eHT_LSIG_TXOP_PROTECTION:
+ retVal = pMac->lim.gHTLsigTXOPProtection;
+ break;
+
+ case eHT_STBC_CONTROL_FRAME:
+ retVal = (uint8_t) macHTCapabilityInfo.stbcControlFrame;
+ break;
+
+ case eHT_PSMP:
+ retVal = pMac->lim.gHTPSMPSupport;
+ break;
+
+ case eHT_DSSS_CCK_MODE_40MHZ:
+ retVal = pMac->lim.gHTDsssCckRate40MHzSupport;
+ break;
+
+ case eHT_MAX_AMSDU_LENGTH:
+ retVal = (uint8_t) macHTCapabilityInfo.maximalAMSDUsize;
+ break;
+
+ case eHT_RX_STBC:
+ retVal = (uint8_t) psessionEntry->htConfig.ht_rx_stbc;
+ break;
+
+ case eHT_TX_STBC:
+ retVal = (uint8_t) psessionEntry->htConfig.ht_tx_stbc;
+ break;
+
+ case eHT_SHORT_GI_40MHZ:
+ retVal = (uint8_t)
+ (psessionEntry->htConfig.ht_sgi) ? macHTCapabilityInfo.
+ shortGI40MHz : 0;
+ break;
+
+ case eHT_SHORT_GI_20MHZ:
+ retVal = (uint8_t)
+ (psessionEntry->htConfig.ht_sgi) ? macHTCapabilityInfo.
+ shortGI20MHz : 0;
+ break;
+
+ case eHT_GREENFIELD:
+ retVal = (uint8_t) macHTCapabilityInfo.greenField;
+ break;
+
+ case eHT_MIMO_POWER_SAVE:
+ retVal = (uint8_t) pMac->lim.gHTMIMOPSState;
+ break;
+
+ case eHT_SUPPORTED_CHANNEL_WIDTH_SET:
+ retVal = (uint8_t) psessionEntry->htSupportedChannelWidthSet;
+ break;
+
+ case eHT_ADVANCED_CODING:
+ retVal = (uint8_t) psessionEntry->htConfig.ht_rx_ldpc;
+ break;
+
+ case eHT_MAX_RX_AMPDU_FACTOR:
+ retVal = pMac->lim.gHTMaxRxAMpduFactor;
+ break;
+
+ case eHT_MPDU_DENSITY:
+ retVal = pMac->lim.gHTAMpduDensity;
+ break;
+
+ case eHT_PCO:
+ retVal = (uint8_t) macExtHTCapabilityInfo.pco;
+ break;
+
+ case eHT_TRANSITION_TIME:
+ retVal = (uint8_t) macExtHTCapabilityInfo.transitionTime;
+ break;
+
+ case eHT_MCS_FEEDBACK:
+ retVal = (uint8_t) macExtHTCapabilityInfo.mcsFeedback;
+ break;
+
+ case eHT_TX_BEAMFORMING:
+ retVal = (uint8_t) macTxBFCapabilityInfo.txBF;
+ break;
+
+ case eHT_ANTENNA_SELECTION:
+ retVal = (uint8_t) macASCapabilityInfo.antennaSelection;
+ break;
+
+ case eHT_SI_GRANULARITY:
+ retVal = pMac->lim.gHTServiceIntervalGranularity;
+ break;
+
+ case eHT_CONTROLLED_ACCESS:
+ retVal = pMac->lim.gHTControlledAccessOnly;
+ break;
+
+ case eHT_RIFS_MODE:
+ retVal = psessionEntry->beaconParams.fRIFSMode;
+ break;
+
+ case eHT_RECOMMENDED_TX_WIDTH_SET:
+ retVal = psessionEntry->htRecommendedTxWidthSet;
+ break;
+
+ case eHT_EXTENSION_CHANNEL_OFFSET:
+ retVal = psessionEntry->htSecondaryChannelOffset;
+ break;
+
+ case eHT_OP_MODE:
+ if (LIM_IS_AP_ROLE(psessionEntry))
+ retVal = psessionEntry->htOperMode;
+ else
+ retVal = pMac->lim.gHTOperMode;
+ break;
+
+ case eHT_BASIC_STBC_MCS:
+ retVal = pMac->lim.gHTSTBCBasicMCS;
+ break;
+
+ case eHT_DUAL_CTS_PROTECTION:
+ retVal = pMac->lim.gHTDualCTSProtection;
+ break;
+
+ case eHT_LSIG_TXOP_PROTECTION_FULL_SUPPORT:
+ retVal =
+ psessionEntry->beaconParams.fLsigTXOPProtectionFullSupport;
+ break;
+
+ case eHT_PCO_ACTIVE:
+ retVal = pMac->lim.gHTPCOActive;
+ break;
+
+ case eHT_PCO_PHASE:
+ retVal = pMac->lim.gHTPCOPhase;
+ break;
+
+ default:
+ break;
+ }
+
+ return retVal;
+}
+
+/**
+ * lim_enable_11a_protection() - updates protection params for enable 11a
+ * protection request
+ * @mac_ctx: pointer to Global MAC structure
+ * @overlap: 1=> called from overlap context, 0 => called from assoc context.
+ * @bcn_prms: beacon parameters
+ * @pe_session: pe session entry
+ *
+ * This fucntion updates protection params for enable 11a protection request
+ *
+ * @Return: void
+ */
+static void
+lim_enable_11a_protection(tpAniSirGlobal mac_ctx,
+ uint8_t overlap,
+ tpUpdateBeaconParams bcn_prms,
+ tpPESession pe_session)
+{
+ /*
+ * If we are AP and HT capable, we need to set the HT OP mode
+ * appropriately.
+ */
+ if ((LIM_IS_AP_ROLE(pe_session) || LIM_IS_BT_AMP_AP_ROLE(pe_session))
+ && (true == pe_session->htCapability)) {
+ if (overlap) {
+ mac_ctx->lim.gLimOverlap11aParams.protectionEnabled =
+ true;
+ if ((eSIR_HT_OP_MODE_OVERLAP_LEGACY !=
+ mac_ctx->lim.gHTOperMode)
+ && (eSIR_HT_OP_MODE_MIXED !=
+ mac_ctx->lim.gHTOperMode)) {
+ mac_ctx->lim.gHTOperMode =
+ eSIR_HT_OP_MODE_OVERLAP_LEGACY;
+ pe_session->htOperMode =
+ eSIR_HT_OP_MODE_OVERLAP_LEGACY;
+ lim_enable_ht_rifs_protection(mac_ctx, true,
+ overlap, bcn_prms, pe_session);
+ lim_enable_ht_obss_protection(mac_ctx, true,
+ overlap, bcn_prms, pe_session);
+ }
+ } else {
+ pe_session->gLim11aParams.protectionEnabled = true;
+ if (eSIR_HT_OP_MODE_MIXED != pe_session->htOperMode) {
+ mac_ctx->lim.gHTOperMode =
+ eSIR_HT_OP_MODE_MIXED;
+ pe_session->htOperMode = eSIR_HT_OP_MODE_MIXED;
+ lim_enable_ht_rifs_protection(mac_ctx, true,
+ overlap, bcn_prms, pe_session);
+ lim_enable_ht_obss_protection(mac_ctx, true,
+ overlap, bcn_prms, pe_session);
+ }
+ }
+ }
+ /* This part is common for station as well. */
+ if (false == pe_session->beaconParams.llaCoexist) {
+ lim_log(mac_ctx, LOGW,
+ FL(" => protection from 11A Enabled"));
+ bcn_prms->llaCoexist = true;
+ pe_session->beaconParams.llaCoexist = true;
+ bcn_prms->paramChangeBitmap |= PARAM_llACOEXIST_CHANGED;
+ }
+}
+
+/**
+ * lim_disable_11a_protection() - updates protection params for disable 11a
+ * protection request
+ * @mac_ctx: pointer to Global MAC structure
+ * @overlap: 1=> called from overlap context, 0 => called from assoc context.
+ * @bcn_prms: beacon parameters
+ * @pe_session: pe session entry
+ *
+ * This fucntion updates protection params for disable 11a protection request
+ *
+ * @Return: void
+ */
+static void
+lim_disable_11a_protection(tpAniSirGlobal mac_ctx,
+ uint8_t overlap,
+ tpUpdateBeaconParams bcn_prms,
+ tpPESession pe_session)
+{
+ if (false == pe_session->beaconParams.llaCoexist)
+ return;
+
+ /* for station role */
+ if (!LIM_IS_AP_ROLE(pe_session)) {
+ lim_log(mac_ctx, LOGW,
+ FL("===> Protection from 11A Disabled"));
+ bcn_prms->llaCoexist = false;
+ pe_session->beaconParams.llaCoexist = false;
+ bcn_prms->paramChangeBitmap |= PARAM_llACOEXIST_CHANGED;
+ return;
+ }
+ /*
+ * for AP role.
+ * we need to take care of HT OP mode change if needed.
+ * We need to take care of Overlap cases.
+ */
+ if (overlap) {
+ /* Overlap Legacy protection disabled. */
+ mac_ctx->lim.gLimOverlap11aParams.protectionEnabled = false;
+
+ /*
+ * We need to take care of HT OP mode iff we are HT AP.
+ * OR no HT op-mode change is needed if any of the overlap
+ * protection enabled.
+ */
+ if (!pe_session->htCapability ||
+ (mac_ctx->lim.gLimOverlap11aParams.protectionEnabled
+ || mac_ctx->lim.gLimOverlapHt20Params.protectionEnabled
+ || mac_ctx->lim.gLimOverlapNonGfParams.protectionEnabled))
+ goto disable_11a_end;
+
+ /* Check if there is a need to change HT OP mode. */
+ if (eSIR_HT_OP_MODE_OVERLAP_LEGACY ==
+ mac_ctx->lim.gHTOperMode) {
+ lim_enable_ht_rifs_protection(mac_ctx, false, overlap,
+ bcn_prms, pe_session);
+ lim_enable_ht_obss_protection(mac_ctx, false, overlap,
+ bcn_prms, pe_session);
+
+ if (pe_session->gLimHt20Params.protectionEnabled)
+ mac_ctx->lim.gHTOperMode =
+ eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT;
+ else
+ mac_ctx->lim.gHTOperMode = eSIR_HT_OP_MODE_PURE;
+ }
+ } else {
+ /* Disable protection from 11A stations. */
+ pe_session->gLim11aParams.protectionEnabled = false;
+ lim_enable_ht_obss_protection(mac_ctx, false, overlap,
+ bcn_prms, pe_session);
+
+ /*
+ * Check if any other non-HT protection enabled. Right now we
+ * are in HT OP Mixed mode. Change HT op mode appropriately.
+ */
+
+ /* Change HT OP mode to 01 if any overlap protection enabled */
+ if (mac_ctx->lim.gLimOverlap11aParams.protectionEnabled
+ || mac_ctx->lim.gLimOverlapHt20Params.protectionEnabled
+ || mac_ctx->lim.gLimOverlapNonGfParams.protectionEnabled) {
+ mac_ctx->lim.gHTOperMode =
+ eSIR_HT_OP_MODE_OVERLAP_LEGACY;
+ pe_session->htOperMode = eSIR_HT_OP_MODE_OVERLAP_LEGACY;
+ lim_enable_ht_rifs_protection(mac_ctx, true, overlap,
+ bcn_prms, pe_session);
+ } else if (pe_session->gLimHt20Params.protectionEnabled) {
+ mac_ctx->lim.gHTOperMode =
+ eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT;
+ pe_session->htOperMode =
+ eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT;
+ lim_enable_ht_rifs_protection(mac_ctx, false, overlap,
+ bcn_prms, pe_session);
+ } else {
+ mac_ctx->lim.gHTOperMode = eSIR_HT_OP_MODE_PURE;
+ pe_session->htOperMode = eSIR_HT_OP_MODE_PURE;
+ lim_enable_ht_rifs_protection(mac_ctx, false, overlap,
+ bcn_prms, pe_session);
+ }
+ }
+
+disable_11a_end:
+ if (!mac_ctx->lim.gLimOverlap11aParams.protectionEnabled &&
+ !pe_session->gLim11aParams.protectionEnabled) {
+ lim_log(mac_ctx, LOGW,
+ FL("===> Protection from 11A Disabled"));
+ bcn_prms->llaCoexist = false;
+ pe_session->beaconParams.llaCoexist = false;
+ bcn_prms->paramChangeBitmap |= PARAM_llACOEXIST_CHANGED;
+ }
+}
+
+/**
+ * lim_update_11a_protection() - based on config setting enables\disables 11a
+ * protection.
+ * @mac_ctx: pointer to Global MAC structure
+ * @enable: 1=> enable protection, 0=> disable protection.
+ * @overlap: 1=> called from overlap context, 0 => called from assoc context.
+ * @bcn_prms: beacon parameters
+ * @session: pe session entry
+ *
+ * This based on config setting enables\disables 11a protection.
+ *
+ * @Return: success of failure of operation
+ */
+tSirRetStatus
+lim_update_11a_protection(tpAniSirGlobal mac_ctx, uint8_t enable,
+ uint8_t overlap, tpUpdateBeaconParams bcn_prms,
+ tpPESession session)
+{
+ if (NULL == session) {
+ lim_log(mac_ctx, LOGW, FL("session is NULL"));
+ return eSIR_FAILURE;
+ }
+ /* overlapping protection configuration check. */
+ if (!overlap) {
+ /* normal protection config check */
+ if ((LIM_IS_AP_ROLE(session)) &&
+ (!session->cfgProtection.fromlla)) {
+ /* protection disabled. */
+ lim_log(mac_ctx, LOGW,
+ FL("protection from 11a is disabled"));
+ return eSIR_SUCCESS;
+ }
+ }
+
+ if (enable)
+ lim_enable_11a_protection(mac_ctx, overlap, bcn_prms, session);
+ else
+ lim_disable_11a_protection(mac_ctx, overlap, bcn_prms, session);
+
+ return eSIR_SUCCESS;
+}
+
+/**
+ * lim_handle_enable11g_protection_enabled() - handle 11g protection enabled
+ * @mac_ctx: pointer to Globale Mac structure
+ * @beaconparams: pointer to tpUpdateBeaconParams
+ * @overlap: 1=> called from overlap context, 0 => called from assoc context.
+ * @session_entry: pointer to tpPESession
+ *
+ * Function handles 11g protection enaled case
+ *
+ * Return: none
+ */
+static void
+lim_handle_enable11g_protection_enabled(tpAniSirGlobal mac_ctx,
+ tpUpdateBeaconParams beaconparams,
+ uint8_t overlap, tpPESession session_entry)
+{
+ /*
+ * If we are AP and HT capable, we need to set the HT OP mode
+ * appropriately.
+ */
+ if (LIM_IS_AP_ROLE(session_entry) && overlap) {
+ session_entry->gLimOlbcParams.protectionEnabled = true;
+
+ lim_log(mac_ctx, LOG1, FL("protection from olbc is enabled"));
+
+ if (true == session_entry->htCapability) {
+ if ((eSIR_HT_OP_MODE_OVERLAP_LEGACY !=
+ session_entry->htOperMode) &&
+ (eSIR_HT_OP_MODE_MIXED !=
+ session_entry->htOperMode)) {
+ session_entry->htOperMode =
+ eSIR_HT_OP_MODE_OVERLAP_LEGACY;
+ }
+ /*
+ * CR-263021: OBSS bit is not switching back to 0 after
+ * disabling the overlapping legacy BSS
+ */
+ /*
+ * This fixes issue of OBSS bit not set after 11b, 11g
+ * station leaves
+ */
+ lim_enable_ht_rifs_protection(mac_ctx, true,
+ overlap, beaconparams, session_entry);
+ /*
+ * Not processing OBSS bit from other APs, as we are
+ * already taking care of Protection from overlapping
+ * BSS based on erp IE or useProtection bit
+ */
+ lim_enable_ht_obss_protection(mac_ctx, true,
+ overlap, beaconparams, session_entry);
+ }
+ } else if (LIM_IS_AP_ROLE(session_entry) && !overlap) {
+ session_entry->gLim11bParams.protectionEnabled = true;
+ lim_log(mac_ctx, LOG1, FL("protection from 11b is enabled"));
+ if (true == session_entry->htCapability) {
+ if (eSIR_HT_OP_MODE_MIXED !=
+ session_entry->htOperMode) {
+ session_entry->htOperMode =
+ eSIR_HT_OP_MODE_MIXED;
+ lim_enable_ht_rifs_protection(mac_ctx,
+ true, overlap, beaconparams,
+ session_entry);
+ lim_enable_ht_obss_protection(mac_ctx,
+ true, overlap, beaconparams,
+ session_entry);
+ }
+ }
+ } else if (LIM_IS_BT_AMP_AP_ROLE(session_entry) &&
+ (true == session_entry->htCapability) && overlap) {
+ session_entry->gLimOlbcParams.protectionEnabled = true;
+ if ((eSIR_HT_OP_MODE_OVERLAP_LEGACY !=
+ mac_ctx->lim.gHTOperMode) &&
+ (eSIR_HT_OP_MODE_MIXED !=
+ mac_ctx->lim.gHTOperMode)) {
+ mac_ctx->lim.gHTOperMode =
+ eSIR_HT_OP_MODE_OVERLAP_LEGACY;
+ }
+ /*
+ * CR-263021: OBSS bit is not switching back to 0 after
+ * disabling the overlapping legacy BSS
+ */
+ /*
+ * This fixes issue of OBSS bit not set after 11b, 11g station
+ * leaves
+ */
+ lim_enable_ht_rifs_protection(mac_ctx, true, overlap,
+ beaconparams, session_entry);
+ /*
+ * Not processing OBSS bit from other APs, as we are already
+ * taking care of Protection from overlapping BSS based on erp
+ * IE or useProtection bit
+ */
+ lim_enable_ht_obss_protection(mac_ctx, true, overlap,
+ beaconparams, session_entry);
+ } else if (LIM_IS_BT_AMP_AP_ROLE(session_entry) &&
+ (true == session_entry->htCapability) && !overlap) {
+ session_entry->gLim11bParams.protectionEnabled = true;
+ if (eSIR_HT_OP_MODE_MIXED !=
+ mac_ctx->lim.gHTOperMode) {
+ mac_ctx->lim.gHTOperMode =
+ eSIR_HT_OP_MODE_MIXED;
+ lim_enable_ht_rifs_protection(mac_ctx, true,
+ overlap, beaconparams, session_entry);
+ lim_enable_ht_obss_protection(mac_ctx, true,
+ overlap, beaconparams, session_entry);
+ }
+ }
+ /* This part is common for staiton as well. */
+ if (false == session_entry->beaconParams.llbCoexist) {
+ lim_log(mac_ctx, LOG1, FL("=> 11G Protection Enabled"));
+ beaconparams->llbCoexist =
+ session_entry->beaconParams.llbCoexist = true;
+ beaconparams->paramChangeBitmap |=
+ PARAM_llBCOEXIST_CHANGED;
+ }
+}
+
+/**
+ * lim_handle_11g_protection_for_11bcoexist() - 11g protection for 11b co-ex
+ * @mac_ctx: pointer to Globale Mac structure
+ * @beaconparams: pointer to tpUpdateBeaconParams
+ * @overlap: 1=> called from overlap context, 0 => called from assoc context.
+ * @session_entry: pointer to tpPESession
+ *
+ * Function handles 11g protection for 11b co-exist
+ *
+ * Return: none
+ */
+static void
+lim_handle_11g_protection_for_11bcoexist(tpAniSirGlobal mac_ctx,
+ tpUpdateBeaconParams beaconparams,
+ uint8_t overlap, tpPESession session_entry)
+{
+ /*
+ * For AP role:
+ * we need to take care of HT OP mode change if needed.
+ * We need to take care of Overlap cases.
+ */
+ if (LIM_IS_AP_ROLE(session_entry) && overlap) {
+ /* Overlap Legacy protection disabled. */
+ session_entry->gLimOlbcParams.protectionEnabled = false;
+
+ /* We need to take care of HT OP mode if we are HT AP. */
+ if (session_entry->htCapability) {
+ /*
+ * no HT op mode change if any of the overlap
+ * protection enabled.
+ */
+ if (!(session_entry->gLimOverlap11gParams.
+ protectionEnabled ||
+ session_entry->gLimOverlapHt20Params.
+ protectionEnabled ||
+ session_entry->gLimOverlapNonGfParams.
+ protectionEnabled) &&
+ /*
+ * Check if there is a need to change HT
+ * OP mode.
+ */
+ (eSIR_HT_OP_MODE_OVERLAP_LEGACY ==
+ session_entry->htOperMode)) {
+ lim_enable_ht_rifs_protection(mac_ctx, false,
+ overlap, beaconparams, session_entry);
+ lim_enable_ht_obss_protection(mac_ctx, false,
+ overlap, beaconparams, session_entry);
+ if (session_entry->gLimHt20Params.
+ protectionEnabled) {
+ if(eHT_CHANNEL_WIDTH_20MHZ ==
+ session_entry->htSupportedChannelWidthSet)
+ session_entry->htOperMode =
+ eSIR_HT_OP_MODE_PURE;
+ else
+ session_entry->htOperMode =
+ eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT;
+ } else
+ session_entry->htOperMode =
+ eSIR_HT_OP_MODE_PURE;
+ }
+ }
+ } else if (LIM_IS_AP_ROLE(session_entry) && !overlap) {
+ /* Disable protection from 11B stations. */
+ session_entry->gLim11bParams.protectionEnabled = false;
+ lim_log(mac_ctx, LOG1, FL("===> 11B Protection Disabled"));
+ /* Check if any other non-HT protection enabled. */
+ if (!session_entry->gLim11gParams.protectionEnabled) {
+ /* Right now we are in HT OP Mixed mode. */
+ /* Change HT op mode appropriately. */
+ lim_enable_ht_obss_protection(mac_ctx, false, overlap,
+ beaconparams, session_entry);
+ /*
+ * Change HT OP mode to 01 if any overlap protection
+ * enabled
+ */
+ if (session_entry->gLimOlbcParams.protectionEnabled ||
+ session_entry->gLimOverlap11gParams.
+ protectionEnabled ||
+ session_entry->gLimOverlapHt20Params.
+ protectionEnabled ||
+ session_entry->gLimOverlapNonGfParams.
+ protectionEnabled) {
+ session_entry->htOperMode =
+ eSIR_HT_OP_MODE_OVERLAP_LEGACY;
+ lim_log(mac_ctx, LOG1,
+ FL("===> 11G Protection Disabled"));
+ lim_enable_ht_rifs_protection(mac_ctx, true,
+ overlap, beaconparams,
+ session_entry);
+ } else if (session_entry->gLimHt20Params.
+ protectionEnabled) {
+ /* Commenting because of CR 258588 WFA cert */
+ /* session_entry->htOperMode =
+ eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT; */
+ session_entry->htOperMode =
+ eSIR_HT_OP_MODE_PURE;
+ lim_log(mac_ctx, LOG1,
+ FL("===> 11G Protection Disabled"));
+ lim_enable_ht_rifs_protection(mac_ctx, false,
+ overlap, beaconparams,
+ session_entry);
+ } else {
+ session_entry->htOperMode =
+ eSIR_HT_OP_MODE_PURE;
+ lim_enable_ht_rifs_protection(mac_ctx, false,
+ overlap, beaconparams,
+ session_entry);
+ }
+ }
+ }
+ if (LIM_IS_AP_ROLE(session_entry)) {
+ if (!session_entry->gLimOlbcParams.protectionEnabled &&
+ !session_entry->gLim11bParams.protectionEnabled) {
+ lim_log(mac_ctx, LOG1,
+ FL("===> 11G Protection Disabled"));
+ beaconparams->llbCoexist =
+ session_entry->beaconParams.llbCoexist =
+ false;
+ beaconparams->paramChangeBitmap |=
+ PARAM_llBCOEXIST_CHANGED;
+ }
+ }
+ if (LIM_IS_BT_AMP_AP_ROLE(session_entry) && overlap) {
+ /* Overlap Legacy protection disabled. */
+ session_entry->gLimOlbcParams.protectionEnabled = false;
+
+ /* We need to take care of HT OP mode iff we are HT AP. */
+ if (session_entry->htCapability) {
+ /*
+ * no HT op mode change if any of the overlap protection
+ * enabled.
+ */
+ if (!(mac_ctx->lim.gLimOverlap11gParams.
+ protectionEnabled ||
+ mac_ctx->lim.gLimOverlapHt20Params.
+ protectionEnabled ||
+ mac_ctx->lim.gLimOverlapNonGfParams.
+ protectionEnabled) &&
+ /*
+ * Check if there is a need to change HT
+ * OP mode.
+ */
+ (eSIR_HT_OP_MODE_OVERLAP_LEGACY ==
+ mac_ctx->lim.gHTOperMode)) {
+ lim_enable_ht_rifs_protection(mac_ctx,
+ false, overlap, beaconparams,
+ session_entry);
+ lim_enable_ht_obss_protection(mac_ctx,
+ false, overlap, beaconparams,
+ session_entry);
+ if (session_entry->gLimHt20Params.
+ protectionEnabled)
+ mac_ctx->lim.gHTOperMode =
+ eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT;
+ else
+ mac_ctx->lim.gHTOperMode =
+ eSIR_HT_OP_MODE_PURE;
+ }
+ }
+ } else if (LIM_IS_BT_AMP_AP_ROLE(session_entry) && !overlap) {
+ /* Disable protection from 11B stations. */
+ session_entry->gLim11bParams.protectionEnabled = false;
+ /* Check if any other non-HT protection enabled. */
+ if (!session_entry->gLim11gParams.protectionEnabled) {
+ /* Right now we are in HT OP Mixed mode. */
+ /* Change HT op mode appropriately. */
+ lim_enable_ht_obss_protection(mac_ctx, false,
+ overlap, beaconparams, session_entry);
+ /*
+ * Change HT OP mode to 01 if any overlap protection
+ * enabled
+ */
+ if (session_entry->gLimOlbcParams.protectionEnabled ||
+ mac_ctx->lim.gLimOverlap11gParams.
+ protectionEnabled ||
+ mac_ctx->lim.gLimOverlapHt20Params.
+ protectionEnabled ||
+ mac_ctx->lim.gLimOverlapNonGfParams.
+ protectionEnabled) {
+ mac_ctx->lim.gHTOperMode =
+ eSIR_HT_OP_MODE_OVERLAP_LEGACY;
+ lim_enable_ht_rifs_protection(mac_ctx,
+ true, overlap, beaconparams,
+ session_entry);
+ } else if (session_entry->gLimHt20Params.
+ protectionEnabled) {
+ mac_ctx->lim.gHTOperMode =
+ eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT;
+ lim_enable_ht_rifs_protection(mac_ctx,
+ false, overlap, beaconparams,
+ session_entry);
+ } else {
+ mac_ctx->lim.gHTOperMode =
+ eSIR_HT_OP_MODE_PURE;
+ lim_enable_ht_rifs_protection(mac_ctx,
+ false, overlap, beaconparams,
+ session_entry);
+ }
+ }
+ }
+ if (LIM_IS_BT_AMP_AP_ROLE(session_entry)) {
+ if (!session_entry->gLimOlbcParams.protectionEnabled &&
+ !session_entry->gLim11bParams.protectionEnabled) {
+ lim_log(mac_ctx, LOG1,
+ FL("===> 11G Protection Disabled"));
+ beaconparams->llbCoexist =
+ session_entry->beaconParams.llbCoexist =
+ false;
+ beaconparams->paramChangeBitmap |=
+ PARAM_llBCOEXIST_CHANGED;
+ }
+ }
+ /* For station role */
+ if (!LIM_IS_AP_ROLE(session_entry) &&
+ !LIM_IS_BT_AMP_AP_ROLE(session_entry)) {
+ lim_log(mac_ctx, LOG1, FL("===> 11G Protection Disabled"));
+ beaconparams->llbCoexist =
+ session_entry->beaconParams.llbCoexist = false;
+ beaconparams->paramChangeBitmap |=
+ PARAM_llBCOEXIST_CHANGED;
+ }
+}
+
+/**
+ * lim_enable11g_protection() - Function to enable 11g protection
+ * @mac_ctx: pointer to Global Mac structure
+ * @enable: 1=> enable protection, 0=> disable protection.
+ * @overlap: 1=> called from overlap context, 0 => called from assoc context.
+ * @beaconparams: pointer to tpUpdateBeaconParams
+ * @session_entry: pointer to tpPESession
+ *
+ * based on config setting enables\disables 11g protection.
+ *
+ * Return: Success - eSIR_SUCCESS - Success, Error number - Failure
+ */
+tSirRetStatus
+lim_enable11g_protection(tpAniSirGlobal mac_ctx, uint8_t enable,
+ uint8_t overlap, tpUpdateBeaconParams beaconparams,
+ tpPESession session_entry)
+{
+
+ /* overlapping protection configuration check. */
+ if (!overlap) {
+ /* normal protection config check */
+ if ((LIM_IS_AP_ROLE(session_entry)) &&
+ !session_entry->cfgProtection.fromllb) {
+ /* protection disabled. */
+ lim_log(mac_ctx, LOG1,
+ FL("protection from 11b is disabled"));
+ return eSIR_SUCCESS;
+ } else if (!LIM_IS_AP_ROLE(session_entry)) {
+ if (!mac_ctx->lim.cfgProtection.fromllb) {
+ /* protection disabled. */
+ lim_log(mac_ctx, LOG1,
+ FL("protection from 11b is disabled"));
+ return eSIR_SUCCESS;
+ }
+ }
+ }
+
+ if (enable) {
+ lim_handle_enable11g_protection_enabled(mac_ctx, beaconparams,
+ overlap, session_entry);
+ } else if (true == session_entry->beaconParams.llbCoexist) {
+ lim_handle_11g_protection_for_11bcoexist(mac_ctx, beaconparams,
+ overlap, session_entry);
+ }
+ return eSIR_SUCCESS;
+}
+
+/** -------------------------------------------------------------
+ \fn lim_enable_ht_protection_from11g
+ \brief based on cofig enables\disables protection from 11g.
+ \param uint8_t enable : 1=> enable protection, 0=> disable protection.
+ \param uint8_t overlap: 1=> called from overlap context, 0 => called from assoc context.
+ \param tpUpdateBeaconParams pBeaconParams
+ \return None
+ -------------------------------------------------------------*/
+tSirRetStatus
+lim_enable_ht_protection_from11g(tpAniSirGlobal pMac, uint8_t enable,
+ uint8_t overlap,
+ tpUpdateBeaconParams pBeaconParams,
+ tpPESession psessionEntry)
+{
+ if (!psessionEntry->htCapability)
+ return eSIR_SUCCESS; /* protection from 11g is only for HT stations. */
+
+ /* overlapping protection configuration check. */
+ if (overlap) {
+ if ((LIM_IS_AP_ROLE(psessionEntry))
+ && (!psessionEntry->cfgProtection.overlapFromllg)) {
+ /* protection disabled. */
+ PELOG3(lim_log
+ (pMac, LOG3,
+ FL("overlap protection from 11g is disabled"));
+ );
+ return eSIR_SUCCESS;
+ } else if (LIM_IS_BT_AMP_AP_ROLE(psessionEntry) &&
+ (!pMac->lim.cfgProtection.overlapFromllg)) {
+ /* protection disabled. */
+ PELOG3(lim_log
+ (pMac, LOG3,
+ FL("overlap protection from 11g is disabled"));
+ );
+ return eSIR_SUCCESS;
+ }
+ } else {
+ /* normal protection config check */
+ if (LIM_IS_AP_ROLE(psessionEntry) &&
+ !psessionEntry->cfgProtection.fromllg) {
+ /* protection disabled. */
+ PELOG3(lim_log
+ (pMac, LOG3,
+ FL("protection from 11g is disabled"));
+ )
+ return eSIR_SUCCESS;
+ } else if (!LIM_IS_AP_ROLE(psessionEntry)) {
+ if (!pMac->lim.cfgProtection.fromllg) {
+ /* protection disabled. */
+ PELOG3(lim_log
+ (pMac, LOG3,
+ FL("protection from 11g is disabled"));
+ )
+ return eSIR_SUCCESS;
+ }
+ }
+ }
+ if (enable) {
+ /* If we are AP and HT capable, we need to set the HT OP mode */
+ /* appropriately. */
+
+ if (LIM_IS_AP_ROLE(psessionEntry)) {
+ if (overlap) {
+ psessionEntry->gLimOverlap11gParams.
+ protectionEnabled = true;
+ /* 11g exists in overlap BSS. */
+ /* need not to change the operating mode to overlap_legacy */
+ /* if higher or same protection operating mode is enabled right now. */
+ if ((eSIR_HT_OP_MODE_OVERLAP_LEGACY !=
+ psessionEntry->htOperMode)
+ && (eSIR_HT_OP_MODE_MIXED !=
+ psessionEntry->htOperMode)) {
+ psessionEntry->htOperMode =
+ eSIR_HT_OP_MODE_OVERLAP_LEGACY;
+ }
+ lim_enable_ht_rifs_protection(pMac, true, overlap,
+ pBeaconParams,
+ psessionEntry);
+ lim_enable_ht_obss_protection(pMac, true, overlap,
+ pBeaconParams,
+ psessionEntry);
+ } else {
+ /* 11g is associated to an AP operating in 11n mode. */
+ /* Change the HT operating mode to 'mixed mode'. */
+ psessionEntry->gLim11gParams.protectionEnabled =
+ true;
+ if (eSIR_HT_OP_MODE_MIXED !=
+ psessionEntry->htOperMode) {
+ psessionEntry->htOperMode =
+ eSIR_HT_OP_MODE_MIXED;
+ lim_enable_ht_rifs_protection(pMac, true,
+ overlap,
+ pBeaconParams,
+ psessionEntry);
+ lim_enable_ht_obss_protection(pMac, true,
+ overlap,
+ pBeaconParams,
+ psessionEntry);
+ }
+ }
+ } else if (LIM_IS_BT_AMP_AP_ROLE(psessionEntry)) {
+ if (overlap) {
+ pMac->lim.gLimOverlap11gParams.
+ protectionEnabled = true;
+ /* 11g exists in overlap BSS. */
+ /* need not to change the operating mode to overlap_legacy */
+ /* if higher or same protection operating mode is enabled right now. */
+ if ((eSIR_HT_OP_MODE_OVERLAP_LEGACY !=
+ pMac->lim.gHTOperMode)
+ && (eSIR_HT_OP_MODE_MIXED !=
+ pMac->lim.gHTOperMode)) {
+ pMac->lim.gHTOperMode =
+ eSIR_HT_OP_MODE_OVERLAP_LEGACY;
+ lim_enable_ht_rifs_protection(pMac, true,
+ overlap,
+ pBeaconParams,
+ psessionEntry);
+ }
+ } else {
+ /* 11g is associated to an AP operating in 11n mode. */
+ /* Change the HT operating mode to 'mixed mode'. */
+ psessionEntry->gLim11gParams.protectionEnabled =
+ true;
+ if (eSIR_HT_OP_MODE_MIXED !=
+ pMac->lim.gHTOperMode) {
+ pMac->lim.gHTOperMode =
+ eSIR_HT_OP_MODE_MIXED;
+ lim_enable_ht_rifs_protection(pMac, true,
+ overlap,
+ pBeaconParams,
+ psessionEntry);
+ lim_enable_ht_obss_protection(pMac, true,
+ overlap,
+ pBeaconParams,
+ psessionEntry);
+ }
+ }
+ }
+ /* This part is common for staiton as well. */
+ if (false == psessionEntry->beaconParams.llgCoexist) {
+ pBeaconParams->llgCoexist =
+ psessionEntry->beaconParams.llgCoexist = true;
+ pBeaconParams->paramChangeBitmap |=
+ PARAM_llGCOEXIST_CHANGED;
+ } else if (true ==
+ psessionEntry->gLimOverlap11gParams.
+ protectionEnabled) {
+ /* As operating mode changed after G station assoc some way to update beacon */
+ /* This addresses the issue of mode not changing to - 11 in beacon when OBSS overlap is enabled */
+ /* pMac->sch.schObject.fBeaconChanged = 1; */
+ pBeaconParams->paramChangeBitmap |=
+ PARAM_llGCOEXIST_CHANGED;
+ }
+ } else if (true == psessionEntry->beaconParams.llgCoexist) {
+ /* for AP role. */
+ /* we need to take care of HT OP mode change if needed. */
+ /* We need to take care of Overlap cases. */
+
+ if (LIM_IS_AP_ROLE(psessionEntry)) {
+ if (overlap) {
+ /* Overlap Legacy protection disabled. */
+ if (psessionEntry->gLim11gParams.numSta == 0)
+ psessionEntry->gLimOverlap11gParams.
+ protectionEnabled = false;
+
+ /* no HT op mode change if any of the overlap protection enabled. */
+ if (!
+ (psessionEntry->gLimOlbcParams.
+ protectionEnabled
+ || psessionEntry->gLimOverlapHt20Params.
+ protectionEnabled
+ || psessionEntry->gLimOverlapNonGfParams.
+ protectionEnabled)) {
+ /* Check if there is a need to change HT OP mode. */
+ if (eSIR_HT_OP_MODE_OVERLAP_LEGACY ==
+ psessionEntry->htOperMode) {
+ lim_enable_ht_rifs_protection(pMac,
+ false,
+ overlap,
+ pBeaconParams,
+ psessionEntry);
+ lim_enable_ht_obss_protection(pMac,
+ false,
+ overlap,
+ pBeaconParams,
+ psessionEntry);
+
+ if (psessionEntry->gLimHt20Params.protectionEnabled) {
+ if(eHT_CHANNEL_WIDTH_20MHZ ==
+ psessionEntry->htSupportedChannelWidthSet)
+ psessionEntry->htOperMode =
+ eSIR_HT_OP_MODE_PURE;
+ else
+ psessionEntry->htOperMode =
+ eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT;
+ } else
+ psessionEntry->htOperMode =
+ eSIR_HT_OP_MODE_PURE;
+ }
+ }
+ } else {
+ /* Disable protection from 11G stations. */
+ psessionEntry->gLim11gParams.protectionEnabled =
+ false;
+ /* Check if any other non-HT protection enabled. */
+ if (!psessionEntry->gLim11bParams.
+ protectionEnabled) {
+
+ /* Right now we are in HT OP Mixed mode. */
+ /* Change HT op mode appropriately. */
+ lim_enable_ht_obss_protection(pMac, false,
+ overlap,
+ pBeaconParams,
+ psessionEntry);
+
+ /* Change HT OP mode to 01 if any overlap protection enabled */
+ if (psessionEntry->gLimOlbcParams.
+ protectionEnabled
+ || psessionEntry->
+ gLimOverlap11gParams.
+ protectionEnabled
+ || psessionEntry->
+ gLimOverlapHt20Params.
+ protectionEnabled
+ || psessionEntry->
+ gLimOverlapNonGfParams.
+ protectionEnabled) {
+ psessionEntry->htOperMode =
+ eSIR_HT_OP_MODE_OVERLAP_LEGACY;
+ lim_enable_ht_rifs_protection(pMac,
+ true,
+ overlap,
+ pBeaconParams,
+ psessionEntry);
+ } else if (psessionEntry->
+ gLimHt20Params.
+ protectionEnabled) {
+ /* Commenting because of CR 258588 WFA cert */
+ /* psessionEntry->htOperMode = eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT; */
+ psessionEntry->htOperMode =
+ eSIR_HT_OP_MODE_PURE;
+ lim_enable_ht_rifs_protection(pMac,
+ false,
+ overlap,
+ pBeaconParams,
+ psessionEntry);
+ } else {
+ psessionEntry->htOperMode =
+ eSIR_HT_OP_MODE_PURE;
+ lim_enable_ht_rifs_protection(pMac,
+ false,
+ overlap,
+ pBeaconParams,
+ psessionEntry);
+ }
+ }
+ }
+ if (!psessionEntry->gLimOverlap11gParams.
+ protectionEnabled
+ && !psessionEntry->gLim11gParams.
+ protectionEnabled) {
+ PELOG1(lim_log
+ (pMac, LOG1,
+ FL
+ ("===> Protection from 11G Disabled"));
+ )
+ pBeaconParams->llgCoexist =
+ psessionEntry->beaconParams.llgCoexist =
+ false;
+ pBeaconParams->paramChangeBitmap |=
+ PARAM_llGCOEXIST_CHANGED;
+ }
+ } else if (LIM_IS_BT_AMP_AP_ROLE(psessionEntry)) {
+ if (overlap) {
+ /* Overlap Legacy protection disabled. */
+ pMac->lim.gLimOverlap11gParams.
+ protectionEnabled = false;
+
+ /* no HT op mode change if any of the overlap protection enabled. */
+ if (!
+ (psessionEntry->gLimOlbcParams.
+ protectionEnabled
+ || psessionEntry->gLimOverlapHt20Params.
+ protectionEnabled
+ || psessionEntry->gLimOverlapNonGfParams.
+ protectionEnabled)) {
+ /* Check if there is a need to change HT OP mode. */
+ if (eSIR_HT_OP_MODE_OVERLAP_LEGACY ==
+ pMac->lim.gHTOperMode) {
+ lim_enable_ht_rifs_protection(pMac,
+ false,
+ overlap,
+ pBeaconParams,
+ psessionEntry);
+ lim_enable_ht_obss_protection(pMac,
+ false,
+ overlap,
+ pBeaconParams,
+ psessionEntry);
+
+ if (psessionEntry->
+ gLimHt20Params.
+ protectionEnabled)
+ pMac->lim.gHTOperMode =
+ eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT;
+ else
+ pMac->lim.gHTOperMode =
+ eSIR_HT_OP_MODE_PURE;
+ }
+ }
+ } else {
+ /* Disable protection from 11G stations. */
+ psessionEntry->gLim11gParams.protectionEnabled =
+ false;
+ /* Check if any other non-HT protection enabled. */
+ if (!psessionEntry->gLim11bParams.
+ protectionEnabled) {
+
+ /* Right now we are in HT OP Mixed mode. */
+ /* Change HT op mode appropriately. */
+ lim_enable_ht_obss_protection(pMac, false,
+ overlap,
+ pBeaconParams,
+ psessionEntry);
+
+ /* Change HT OP mode to 01 if any overlap protection enabled */
+ if (psessionEntry->gLimOlbcParams.
+ protectionEnabled
+ || pMac->lim.gLimOverlap11gParams.
+ protectionEnabled
+ || pMac->lim.gLimOverlapHt20Params.
+ protectionEnabled
+ || pMac->lim.gLimOverlapNonGfParams.
+ protectionEnabled) {
+ pMac->lim.gHTOperMode =
+ eSIR_HT_OP_MODE_OVERLAP_LEGACY;
+ lim_enable_ht_rifs_protection(pMac,
+ true,
+ overlap,
+ pBeaconParams,
+ psessionEntry);
+ } else if (psessionEntry->
+ gLimHt20Params.
+ protectionEnabled) {
+ pMac->lim.gHTOperMode =
+ eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT;
+ lim_enable_ht_rifs_protection(pMac,
+ false,
+ overlap,
+ pBeaconParams,
+ psessionEntry);
+ } else {
+ pMac->lim.gHTOperMode =
+ eSIR_HT_OP_MODE_PURE;
+ lim_enable_ht_rifs_protection(pMac,
+ false,
+ overlap,
+ pBeaconParams,
+ psessionEntry);
+ }
+ }
+ }
+ if (!pMac->lim.gLimOverlap11gParams.protectionEnabled &&
+ !psessionEntry->gLim11gParams.protectionEnabled) {
+ PELOG1(lim_log
+ (pMac, LOG1,
+ FL
+ ("===> Protection from 11G Disabled"));
+ )
+ pBeaconParams->llgCoexist =
+ psessionEntry->beaconParams.llgCoexist =
+ false;
+ pBeaconParams->paramChangeBitmap |=
+ PARAM_llGCOEXIST_CHANGED;
+ }
+ }
+ /* for station role */
+ else {
+ PELOG1(lim_log
+ (pMac, LOG1,
+ FL("===> Protection from 11G Disabled"));
+ )
+ pBeaconParams->llgCoexist =
+ psessionEntry->beaconParams.llgCoexist = false;
+ pBeaconParams->paramChangeBitmap |=
+ PARAM_llGCOEXIST_CHANGED;
+ }
+ }
+ return eSIR_SUCCESS;
+}
+
+/* FIXME_PROTECTION : need to check for no APSD whenever we want to enable this protection. */
+/* This check will be done at the caller. */
+
+/** -------------------------------------------------------------
+ \fn limEnableHtObssProtection
+ \brief based on cofig enables\disables obss protection.
+ \param uint8_t enable : 1=> enable protection, 0=> disable protection.
+ \param uint8_t overlap: 1=> called from overlap context, 0 => called from assoc context.
+ \param tpUpdateBeaconParams pBeaconParams
+ \return None
+ -------------------------------------------------------------*/
+tSirRetStatus
+lim_enable_ht_obss_protection(tpAniSirGlobal pMac, uint8_t enable,
+ uint8_t overlap, tpUpdateBeaconParams pBeaconParams,
+ tpPESession psessionEntry)
+{
+
+ if (!psessionEntry->htCapability)
+ return eSIR_SUCCESS; /* this protection is only for HT stations. */
+
+ /* overlapping protection configuration check. */
+ if (overlap) {
+ /* overlapping protection configuration check. */
+ } else {
+ /* normal protection config check */
+ if ((LIM_IS_AP_ROLE(psessionEntry)) &&
+ !psessionEntry->cfgProtection.obss) { /* ToDo Update this field */
+ /* protection disabled. */
+ PELOG1(lim_log
+ (pMac, LOG1,
+ FL("protection from Obss is disabled"));
+ )
+ return eSIR_SUCCESS;
+ } else if (!LIM_IS_AP_ROLE(psessionEntry)) {
+ if (!pMac->lim.cfgProtection.obss) { /* ToDo Update this field */
+ /* protection disabled. */
+ PELOG1(lim_log
+ (pMac, LOG1,
+ FL("protection from Obss is disabled"));
+ )
+ return eSIR_SUCCESS;
+ }
+ }
+ }
+
+ if (LIM_IS_AP_ROLE(psessionEntry)) {
+ if ((enable)
+ && (false == psessionEntry->beaconParams.gHTObssMode)) {
+ PELOG1(lim_log
+ (pMac, LOG1, FL("=>obss protection enabled"));
+ )
+ psessionEntry->beaconParams.gHTObssMode = true;
+ pBeaconParams->paramChangeBitmap |= PARAM_OBSS_MODE_CHANGED; /* UPDATE AN ENUM FOR OBSS MODE <todo> */
+
+ } else if (!enable
+ && (true ==
+ psessionEntry->beaconParams.gHTObssMode)) {
+ PELOG1(lim_log
+ (pMac, LOG1,
+ FL("===> obss Protection disabled"));
+ )
+ psessionEntry->beaconParams.gHTObssMode = false;
+ pBeaconParams->paramChangeBitmap |=
+ PARAM_OBSS_MODE_CHANGED;
+
+ }
+/* CR-263021: OBSS bit is not switching back to 0 after disabling the overlapping legacy BSS */
+ if (!enable && !overlap) {
+ psessionEntry->gLimOverlap11gParams.protectionEnabled =
+ false;
+ }
+ } else {
+ if ((enable)
+ && (false == psessionEntry->beaconParams.gHTObssMode)) {
+ PELOG1(lim_log
+ (pMac, LOG1, FL("=>obss protection enabled"));
+ )
+ psessionEntry->beaconParams.gHTObssMode = true;
+ pBeaconParams->paramChangeBitmap |= PARAM_OBSS_MODE_CHANGED; /* UPDATE AN ENUM FOR OBSS MODE <todo> */
+
+ } else if (!enable
+ && (true ==
+ psessionEntry->beaconParams.gHTObssMode)) {
+
+ PELOG1(lim_log
+ (pMac, LOG1,
+ FL("===> obss Protection disabled"));
+ )
+ psessionEntry->beaconParams.gHTObssMode = false;
+ pBeaconParams->paramChangeBitmap |=
+ PARAM_OBSS_MODE_CHANGED;
+
+ }
+ }
+ return eSIR_SUCCESS;
+}
+
+/**
+ * lim_handle_ht20protection_enabled() - Handle ht20 protection enabled
+ * @mac_ctx: pointer to Gloal Mac Structure
+ * @overlap: variable for overlap detection
+ * @beaconparams: pointer to tpUpdateBeaconParams
+ * @session_entry: pointer to tpPESession
+ *
+ * Function handles ht20 protection enabled
+ *
+ * Return: none
+ */
+static void lim_handle_ht20protection_enabled(tpAniSirGlobal mac_ctx,
+ uint8_t overlap, tpUpdateBeaconParams beaconparams,
+ tpPESession session_entry)
+{
+ /*
+ * If we are AP and HT capable, we need to set the HT OP mode
+ * appropriately.
+ */
+ if (LIM_IS_AP_ROLE(session_entry) && overlap) {
+ session_entry->gLimOverlapHt20Params.protectionEnabled = true;
+ if ((eSIR_HT_OP_MODE_OVERLAP_LEGACY !=
+ session_entry->htOperMode) &&
+ (eSIR_HT_OP_MODE_MIXED !=
+ session_entry->htOperMode)) {
+ session_entry->htOperMode =
+ eSIR_HT_OP_MODE_OVERLAP_LEGACY;
+ lim_enable_ht_rifs_protection(mac_ctx, true,
+ overlap, beaconparams, session_entry);
+ }
+ } else if (LIM_IS_AP_ROLE(session_entry) && !overlap) {
+ session_entry->gLimHt20Params.protectionEnabled = true;
+ if (eSIR_HT_OP_MODE_PURE == session_entry->htOperMode) {
+ if (session_entry->htSupportedChannelWidthSet !=
+ eHT_CHANNEL_WIDTH_20MHZ)
+ session_entry->htOperMode =
+ eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT;
+ lim_enable_ht_rifs_protection(mac_ctx, false,
+ overlap, beaconparams, session_entry);
+ lim_enable_ht_obss_protection(mac_ctx, false,
+ overlap, beaconparams, session_entry);
+ }
+ } else if (LIM_IS_BT_AMP_AP_ROLE(session_entry) && overlap) {
+ mac_ctx->lim.gLimOverlapHt20Params.protectionEnabled =
+ true;
+ if ((eSIR_HT_OP_MODE_OVERLAP_LEGACY !=
+ mac_ctx->lim.gHTOperMode) &&
+ (eSIR_HT_OP_MODE_MIXED !=
+ mac_ctx->lim.gHTOperMode)) {
+ mac_ctx->lim.gHTOperMode =
+ eSIR_HT_OP_MODE_OVERLAP_LEGACY;
+ lim_enable_ht_rifs_protection(mac_ctx, true,
+ overlap, beaconparams, session_entry);
+ }
+ } else if (LIM_IS_BT_AMP_AP_ROLE(session_entry) && !overlap) {
+ session_entry->gLimHt20Params.protectionEnabled = true;
+ if (eSIR_HT_OP_MODE_PURE == mac_ctx->lim.gHTOperMode) {
+ mac_ctx->lim.gHTOperMode =
+ eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT;
+ lim_enable_ht_rifs_protection(mac_ctx, false,
+ overlap, beaconparams, session_entry);
+ lim_enable_ht_obss_protection(mac_ctx, false,
+ overlap, beaconparams, session_entry);
+ }
+ }
+ /* This part is common for staiton as well. */
+ if (false == session_entry->beaconParams.ht20Coexist) {
+ lim_log(mac_ctx, LOG1,
+ FL("=> Protection from HT20 Enabled"));
+ beaconparams->ht20MhzCoexist =
+ session_entry->beaconParams.ht20Coexist = true;
+ beaconparams->paramChangeBitmap |=
+ PARAM_HT20MHZCOEXIST_CHANGED;
+ }
+}
+
+/**
+ * lim_handle_ht20coexist_ht20protection() - ht20 protection for ht20 coexist
+ * @mac_ctx: pointer to Gloal Mac Structure
+ * @beaconparams: pointer to tpUpdateBeaconParams
+ * @session_entry: pointer to tpPESession
+ * @overlap: variable for overlap detection
+ *
+ * Function handles ht20 protection for ht20 coexist
+ *
+ * Return: none
+ */
+static void lim_handle_ht20coexist_ht20protection(tpAniSirGlobal mac_ctx,
+ tpUpdateBeaconParams beaconparams,
+ tpPESession session_entry, uint8_t overlap)
+{
+ /*
+ * For AP role:
+ * we need to take care of HT OP mode change if needed.
+ * We need to take care of Overlap cases.
+ */
+ if (LIM_IS_AP_ROLE(session_entry) && overlap) {
+ /* Overlap Legacy protection disabled. */
+ session_entry->gLimOverlapHt20Params.protectionEnabled =
+ false;
+ /*
+ * no HT op mode change if any of the overlap
+ * protection enabled.
+ */
+ if (!(session_entry->gLimOlbcParams.protectionEnabled ||
+ session_entry->gLimOverlap11gParams.protectionEnabled ||
+ session_entry->gLimOverlapHt20Params.protectionEnabled
+ || session_entry->gLimOverlapNonGfParams.
+ protectionEnabled) &&
+ /*
+ * Check if there is a need to change HT
+ * OP mode.
+ */
+ (eSIR_HT_OP_MODE_OVERLAP_LEGACY ==
+ session_entry->htOperMode)) {
+ if (session_entry->gLimHt20Params.
+ protectionEnabled) {
+ if(eHT_CHANNEL_WIDTH_20MHZ ==
+ session_entry->htSupportedChannelWidthSet)
+ session_entry->htOperMode =
+ eSIR_HT_OP_MODE_PURE;
+ else
+ session_entry->htOperMode =
+ eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT;
+
+ lim_enable_ht_rifs_protection(mac_ctx,
+ false, overlap, beaconparams,
+ session_entry);
+ lim_enable_ht_obss_protection(mac_ctx,
+ false, overlap, beaconparams,
+ session_entry);
+ } else {
+ session_entry->htOperMode =
+ eSIR_HT_OP_MODE_PURE;
+ }
+ }
+ } else if (LIM_IS_AP_ROLE(session_entry) && !overlap) {
+ /* Disable protection from 11G stations. */
+ session_entry->gLimHt20Params.protectionEnabled = false;
+ /* Change HT op mode appropriately. */
+ if (eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT ==
+ session_entry->htOperMode) {
+ session_entry->htOperMode =
+ eSIR_HT_OP_MODE_PURE;
+ lim_enable_ht_rifs_protection(mac_ctx, false,
+ overlap, beaconparams, session_entry);
+ lim_enable_ht_obss_protection(mac_ctx, false,
+ overlap, beaconparams, session_entry);
+ }
+ }
+ if (LIM_IS_AP_ROLE(session_entry)) {
+ lim_log(mac_ctx, LOG1,
+ FL("===> Protection from HT 20 Disabled"));
+ beaconparams->ht20MhzCoexist =
+ session_entry->beaconParams.ht20Coexist = false;
+ beaconparams->paramChangeBitmap |=
+ PARAM_HT20MHZCOEXIST_CHANGED;
+ }
+ if (LIM_IS_BT_AMP_AP_ROLE(session_entry) && overlap) {
+ /* Overlap Legacy protection disabled. */
+ mac_ctx->lim.gLimOverlapHt20Params.protectionEnabled = false;
+ /*
+ * no HT op mode change if any of the overlap
+ * protection enabled.
+ */
+ if (!(session_entry->gLimOlbcParams.protectionEnabled ||
+ mac_ctx->lim.gLimOverlap11gParams.protectionEnabled ||
+ mac_ctx->lim.gLimOverlapHt20Params.protectionEnabled ||
+ mac_ctx->lim.gLimOverlapNonGfParams.protectionEnabled)
+ /*
+ * Check if there is a need to change
+ * HT OP mode.
+ */
+ && (eSIR_HT_OP_MODE_OVERLAP_LEGACY ==
+ mac_ctx->lim.gHTOperMode)) {
+ if (session_entry->gLimHt20Params.protectionEnabled) {
+ mac_ctx->lim.gHTOperMode =
+ eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT;
+ lim_enable_ht_rifs_protection(mac_ctx, false,
+ overlap, beaconparams, session_entry);
+ lim_enable_ht_obss_protection(mac_ctx, false,
+ overlap, beaconparams, session_entry);
+ } else {
+ mac_ctx->lim.gHTOperMode = eSIR_HT_OP_MODE_PURE;
+ }
+ }
+ } else if (LIM_IS_BT_AMP_AP_ROLE(session_entry) && !overlap) {
+ /* Disable protection from 11G stations. */
+ session_entry->gLimHt20Params.protectionEnabled = false;
+
+ /* Change HT op mode appropriately. */
+ if (eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT ==
+ mac_ctx->lim.gHTOperMode) {
+ mac_ctx->lim.gHTOperMode =
+ eSIR_HT_OP_MODE_PURE;
+ lim_enable_ht_rifs_protection(mac_ctx, false,
+ overlap, beaconparams, session_entry);
+ lim_enable_ht_obss_protection(mac_ctx, false,
+ overlap, beaconparams, session_entry);
+ }
+ }
+ if (LIM_IS_BT_AMP_AP_ROLE(session_entry)) {
+ lim_log(mac_ctx, LOG1,
+ FL("===> Protection from HT 20 Disabled"));
+ beaconparams->ht20MhzCoexist =
+ session_entry->beaconParams.ht20Coexist = false;
+ beaconparams->paramChangeBitmap |=
+ PARAM_HT20MHZCOEXIST_CHANGED;
+ }
+
+ if (!LIM_IS_AP_ROLE(session_entry) &&
+ !LIM_IS_BT_AMP_AP_ROLE(session_entry)) {
+ /* For station role */
+ lim_log(mac_ctx, LOG1,
+ FL("===> Protection from HT20 Disabled"));
+ beaconparams->ht20MhzCoexist =
+ session_entry->beaconParams.ht20Coexist = false;
+ beaconparams->paramChangeBitmap |=
+ PARAM_HT20MHZCOEXIST_CHANGED;
+ }
+}
+
+/**
+ * lim_enable_ht20_protection() - Function to enable ht20 protection
+ * @mac_ctx: pointer to Global Mac structure
+ * @enable: 1=> enable protection, 0=> disable protection.
+ * @overlap: 1=> called from overlap context, 0 => called from assoc context.
+ * @beaconparams: pointer to tpUpdateBeaconParams
+ * @session_entry: pointer to tpPESession
+ *
+ * based on cofig enables\disables protection from Ht20
+ *
+ * Return: 0 - success
+ */
+tSirRetStatus lim_enable_ht20_protection(tpAniSirGlobal mac_ctx, uint8_t enable,
+ uint8_t overlap, tpUpdateBeaconParams beaconparams,
+ tpPESession session_entry)
+{
+ /* This protection is only for HT stations. */
+ if (!session_entry->htCapability)
+ return eSIR_SUCCESS;
+
+ /* overlapping protection configuration check. */
+ if (!overlap) {
+ /* normal protection config check */
+ if ((LIM_IS_AP_ROLE(session_entry)) &&
+ !session_entry->cfgProtection.ht20) {
+ /* protection disabled. */
+ lim_log(mac_ctx, LOG3,
+ FL("protection from HT20 is disabled"));
+ return eSIR_SUCCESS;
+ } else if (!LIM_IS_AP_ROLE(session_entry)) {
+ if (!mac_ctx->lim.cfgProtection.ht20) {
+ /* protection disabled. */
+ lim_log(mac_ctx, LOG3,
+ FL("protection from HT20 is disabled"));
+ return eSIR_SUCCESS;
+ }
+ }
+ }
+
+ if (enable)
+ lim_handle_ht20protection_enabled(mac_ctx, overlap,
+ beaconparams, session_entry);
+ else if (true == session_entry->beaconParams.ht20Coexist)
+ lim_handle_ht20coexist_ht20protection(mac_ctx, beaconparams,
+ session_entry, overlap);
+
+ return eSIR_SUCCESS;
+}
+
+/** -------------------------------------------------------------
+ \fn lim_enable_ht_non_gf_protection
+ \brief based on cofig enables\disables protection from NonGf.
+ \param uint8_t enable : 1=> enable protection, 0=> disable protection.
+ \param uint8_t overlap: 1=> called from overlap context, 0 => called from assoc context.
+ \param tpUpdateBeaconParams pBeaconParams
+ \return None
+ -------------------------------------------------------------*/
+tSirRetStatus
+lim_enable_ht_non_gf_protection(tpAniSirGlobal pMac, uint8_t enable,
+ uint8_t overlap, tpUpdateBeaconParams pBeaconParams,
+ tpPESession psessionEntry)
+{
+ if (!psessionEntry->htCapability)
+ return eSIR_SUCCESS; /* this protection is only for HT stations. */
+
+ /* overlapping protection configuration check. */
+ if (overlap) {
+ } else {
+ /* normal protection config check */
+ if (LIM_IS_AP_ROLE(psessionEntry) &&
+ !psessionEntry->cfgProtection.nonGf) {
+ /* protection disabled. */
+ PELOG3(lim_log
+ (pMac, LOG3,
+ FL("protection from NonGf is disabled"));
+ )
+ return eSIR_SUCCESS;
+ } else if (!LIM_IS_AP_ROLE(psessionEntry)) {
+ /* normal protection config check */
+ if (!pMac->lim.cfgProtection.nonGf) {
+ /* protection disabled. */
+ PELOG3(lim_log
+ (pMac, LOG3,
+ FL
+ ("protection from NonGf is disabled"));
+ )
+ return eSIR_SUCCESS;
+ }
+ }
+ }
+ if (LIM_IS_AP_ROLE(psessionEntry)) {
+ if ((enable)
+ && (false == psessionEntry->beaconParams.llnNonGFCoexist)) {
+ PELOG1(lim_log
+ (pMac, LOG1,
+ FL(" => Protection from non GF Enabled"));
+ )
+ pBeaconParams->llnNonGFCoexist =
+ psessionEntry->beaconParams.llnNonGFCoexist = true;
+ pBeaconParams->paramChangeBitmap |=
+ PARAM_NON_GF_DEVICES_PRESENT_CHANGED;
+ } else if (!enable
+ && (true ==
+ psessionEntry->beaconParams.llnNonGFCoexist)) {
+ PELOG1(lim_log
+ (pMac, LOG1,
+ FL("===> Protection from Non GF Disabled"));
+ )
+ pBeaconParams->llnNonGFCoexist =
+ psessionEntry->beaconParams.llnNonGFCoexist = false;
+ pBeaconParams->paramChangeBitmap |=
+ PARAM_NON_GF_DEVICES_PRESENT_CHANGED;
+ }
+ } else {
+ if ((enable)
+ && (false == psessionEntry->beaconParams.llnNonGFCoexist)) {
+ PELOG1(lim_log
+ (pMac, LOG1,
+ FL(" => Protection from non GF Enabled"));
+ )
+ pBeaconParams->llnNonGFCoexist =
+ psessionEntry->beaconParams.llnNonGFCoexist = true;
+ pBeaconParams->paramChangeBitmap |=
+ PARAM_NON_GF_DEVICES_PRESENT_CHANGED;
+ } else if (!enable
+ && (true ==
+ psessionEntry->beaconParams.llnNonGFCoexist)) {
+ PELOG1(lim_log
+ (pMac, LOG1,
+ FL("===> Protection from Non GF Disabled"));
+ )
+ pBeaconParams->llnNonGFCoexist =
+ psessionEntry->beaconParams.llnNonGFCoexist = false;
+ pBeaconParams->paramChangeBitmap |=
+ PARAM_NON_GF_DEVICES_PRESENT_CHANGED;
+ }
+ }
+
+ return eSIR_SUCCESS;
+}
+
+/** -------------------------------------------------------------
+ \fn lim_enable_ht_lsig_txop_protection
+ \brief based on cofig enables\disables LsigTxop protection.
+ \param uint8_t enable : 1=> enable protection, 0=> disable protection.
+ \param uint8_t overlap: 1=> called from overlap context, 0 => called from assoc context.
+ \param tpUpdateBeaconParams pBeaconParams
+ \return None
+ -------------------------------------------------------------*/
+tSirRetStatus
+lim_enable_ht_lsig_txop_protection(tpAniSirGlobal pMac, uint8_t enable,
+ uint8_t overlap,
+ tpUpdateBeaconParams pBeaconParams,
+ tpPESession psessionEntry)
+{
+ if (!psessionEntry->htCapability)
+ return eSIR_SUCCESS; /* this protection is only for HT stations. */
+
+ /* overlapping protection configuration check. */
+ if (overlap) {
+ } else {
+ /* normal protection config check */
+ if (LIM_IS_AP_ROLE(psessionEntry) &&
+ !psessionEntry->cfgProtection.lsigTxop) {
+ /* protection disabled. */
+ PELOG3(lim_log
+ (pMac, LOG3,
+ FL
+ (" protection from LsigTxop not supported is disabled"));
+ )
+ return eSIR_SUCCESS;
+ } else if (!LIM_IS_AP_ROLE(psessionEntry)) {
+ /* normal protection config check */
+ if (!pMac->lim.cfgProtection.lsigTxop) {
+ /* protection disabled. */
+ PELOG3(lim_log
+ (pMac, LOG3,
+ FL
+ (" protection from LsigTxop not supported is disabled"));
+ )
+ return eSIR_SUCCESS;
+ }
+ }
+ }
+
+ if (LIM_IS_AP_ROLE(psessionEntry)) {
+ if ((enable)
+ && (false ==
+ psessionEntry->beaconParams.
+ fLsigTXOPProtectionFullSupport)) {
+ PELOG1(lim_log
+ (pMac, LOG1,
+ FL(" => Protection from LsigTxop Enabled"));
+ )
+ pBeaconParams->fLsigTXOPProtectionFullSupport =
+ psessionEntry->beaconParams.
+ fLsigTXOPProtectionFullSupport = true;
+ pBeaconParams->paramChangeBitmap |=
+ PARAM_LSIG_TXOP_FULL_SUPPORT_CHANGED;
+ } else if (!enable
+ && (true ==
+ psessionEntry->beaconParams.
+ fLsigTXOPProtectionFullSupport)) {
+ PELOG1(lim_log
+ (pMac, LOG1,
+ FL("===> Protection from LsigTxop Disabled"));
+ )
+ pBeaconParams->fLsigTXOPProtectionFullSupport =
+ psessionEntry->beaconParams.
+ fLsigTXOPProtectionFullSupport = false;
+ pBeaconParams->paramChangeBitmap |=
+ PARAM_LSIG_TXOP_FULL_SUPPORT_CHANGED;
+ }
+ } else {
+ if ((enable)
+ && (false ==
+ psessionEntry->beaconParams.
+ fLsigTXOPProtectionFullSupport)) {
+ PELOG1(lim_log
+ (pMac, LOG1,
+ FL(" => Protection from LsigTxop Enabled"));
+ )
+ pBeaconParams->fLsigTXOPProtectionFullSupport =
+ psessionEntry->beaconParams.
+ fLsigTXOPProtectionFullSupport = true;
+ pBeaconParams->paramChangeBitmap |=
+ PARAM_LSIG_TXOP_FULL_SUPPORT_CHANGED;
+ } else if (!enable
+ && (true ==
+ psessionEntry->beaconParams.
+ fLsigTXOPProtectionFullSupport)) {
+ PELOG1(lim_log
+ (pMac, LOG1,
+ FL("===> Protection from LsigTxop Disabled"));
+ )
+ pBeaconParams->fLsigTXOPProtectionFullSupport =
+ psessionEntry->beaconParams.
+ fLsigTXOPProtectionFullSupport = false;
+ pBeaconParams->paramChangeBitmap |=
+ PARAM_LSIG_TXOP_FULL_SUPPORT_CHANGED;
+ }
+ }
+ return eSIR_SUCCESS;
+}
+
+/* FIXME_PROTECTION : need to check for no APSD whenever we want to enable this protection. */
+/* This check will be done at the caller. */
+/** -------------------------------------------------------------
+ \fn lim_enable_ht_rifs_protection
+ \brief based on cofig enables\disables Rifs protection.
+ \param uint8_t enable : 1=> enable protection, 0=> disable protection.
+ \param uint8_t overlap: 1=> called from overlap context, 0 => called from assoc context.
+ \param tpUpdateBeaconParams pBeaconParams
+ \return None
+ -------------------------------------------------------------*/
+tSirRetStatus
+lim_enable_ht_rifs_protection(tpAniSirGlobal pMac, uint8_t enable,
+ uint8_t overlap, tpUpdateBeaconParams pBeaconParams,
+ tpPESession psessionEntry)
+{
+ if (!psessionEntry->htCapability)
+ return eSIR_SUCCESS; /* this protection is only for HT stations. */
+
+ /* overlapping protection configuration check. */
+ if (overlap) {
+ } else {
+ /* normal protection config check */
+ if (LIM_IS_AP_ROLE(psessionEntry) &&
+ !psessionEntry->cfgProtection.rifs) {
+ /* protection disabled. */
+ PELOG3(lim_log
+ (pMac, LOG3,
+ FL(" protection from Rifs is disabled"));
+ )
+ return eSIR_SUCCESS;
+ } else if (!LIM_IS_AP_ROLE(psessionEntry)) {
+ /* normal protection config check */
+ if (!pMac->lim.cfgProtection.rifs) {
+ /* protection disabled. */
+ PELOG3(lim_log
+ (pMac, LOG3,
+ FL
+ (" protection from Rifs is disabled"));
+ )
+ return eSIR_SUCCESS;
+ }
+ }
+ }
+
+ if (LIM_IS_AP_ROLE(psessionEntry)) {
+ /* Disabling the RIFS Protection means Enable the RIFS mode of operation in the BSS */
+ if ((!enable)
+ && (false == psessionEntry->beaconParams.fRIFSMode)) {
+ PELOG1(lim_log
+ (pMac, LOG1, FL(" => Rifs protection Disabled"));
+ )
+ pBeaconParams->fRIFSMode =
+ psessionEntry->beaconParams.fRIFSMode = true;
+ pBeaconParams->paramChangeBitmap |=
+ PARAM_RIFS_MODE_CHANGED;
+ }
+ /* Enabling the RIFS Protection means Disable the RIFS mode of operation in the BSS */
+ else if (enable
+ && (true == psessionEntry->beaconParams.fRIFSMode)) {
+ PELOG1(lim_log
+ (pMac, LOG1, FL("===> Rifs Protection Enabled"));
+ )
+ pBeaconParams->fRIFSMode =
+ psessionEntry->beaconParams.fRIFSMode = false;
+ pBeaconParams->paramChangeBitmap |=
+ PARAM_RIFS_MODE_CHANGED;
+ }
+ } else {
+ /* Disabling the RIFS Protection means Enable the RIFS mode of operation in the BSS */
+ if ((!enable)
+ && (false == psessionEntry->beaconParams.fRIFSMode)) {
+ PELOG1(lim_log
+ (pMac, LOG1, FL(" => Rifs protection Disabled"));
+ )
+ pBeaconParams->fRIFSMode =
+ psessionEntry->beaconParams.fRIFSMode = true;
+ pBeaconParams->paramChangeBitmap |=
+ PARAM_RIFS_MODE_CHANGED;
+ }
+ /* Enabling the RIFS Protection means Disable the RIFS mode of operation in the BSS */
+ else if (enable
+ && (true == psessionEntry->beaconParams.fRIFSMode)) {
+ PELOG1(lim_log
+ (pMac, LOG1, FL("===> Rifs Protection Enabled"));
+ )
+ pBeaconParams->fRIFSMode =
+ psessionEntry->beaconParams.fRIFSMode = false;
+ pBeaconParams->paramChangeBitmap |=
+ PARAM_RIFS_MODE_CHANGED;
+ }
+ }
+ return eSIR_SUCCESS;
+}
+
+/* --------------------------------------------------------------------- */
+/**
+ * lim_enable_short_preamble
+ *
+ * FUNCTION:
+ * Enable/Disable short preamble
+ *
+ * LOGIC:
+ *
+ * ASSUMPTIONS:
+ *
+ * NOTE:
+ *
+ * @param enable Flag to enable/disable short preamble
+ * @return None
+ */
+
+tSirRetStatus
+lim_enable_short_preamble(tpAniSirGlobal pMac, uint8_t enable,
+ tpUpdateBeaconParams pBeaconParams,
+ tpPESession psessionEntry)
+{
+ uint32_t val;
+
+ if (wlan_cfg_get_int(pMac, WNI_CFG_SHORT_PREAMBLE, &val) != eSIR_SUCCESS) {
+ /* Could not get short preamble enabled flag from CFG. Log error. */
+ lim_log(pMac, LOGP,
+ FL("could not retrieve short preamble flag"));
+ return eSIR_FAILURE;
+ }
+
+ if (!val)
+ return eSIR_SUCCESS;
+
+ if (wlan_cfg_get_int(pMac, WNI_CFG_11G_SHORT_PREAMBLE_ENABLED, &val) !=
+ eSIR_SUCCESS) {
+ lim_log(pMac, LOGP,
+ FL
+ ("could not retrieve 11G short preamble switching enabled flag"));
+ return eSIR_FAILURE;
+ }
+
+ if (!val) /* 11G short preamble switching is disabled. */
+ return eSIR_SUCCESS;
+
+ if (LIM_IS_AP_ROLE(psessionEntry)) {
+ if (enable && (psessionEntry->beaconParams.fShortPreamble == 0)) {
+ PELOG1(lim_log
+ (pMac, LOG1, FL("===> Short Preamble Enabled"));
+ )
+ psessionEntry->beaconParams.fShortPreamble = true;
+ pBeaconParams->fShortPreamble =
+ (uint8_t) psessionEntry->beaconParams.
+ fShortPreamble;
+ pBeaconParams->paramChangeBitmap |=
+ PARAM_SHORT_PREAMBLE_CHANGED;
+ } else if (!enable
+ && (psessionEntry->beaconParams.fShortPreamble ==
+ 1)) {
+ PELOG1(lim_log
+ (pMac, LOG1, FL("===> Short Preamble Disabled"));
+ )
+ psessionEntry->beaconParams.fShortPreamble = false;
+ pBeaconParams->fShortPreamble =
+ (uint8_t) psessionEntry->beaconParams.
+ fShortPreamble;
+ pBeaconParams->paramChangeBitmap |=
+ PARAM_SHORT_PREAMBLE_CHANGED;
+ }
+ }
+
+ return eSIR_SUCCESS;
+}
+
+/**
+ * lim_tx_complete
+ *
+ * Function:
+ * This is LIM's very own "TX MGMT frame complete" completion routine.
+ *
+ * Logic:
+ * LIM wants to send a MGMT frame (broadcast or unicast)
+ * LIM allocates memory using cds_packet_alloc( ..., **pData, **pPacket )
+ * LIM transmits the MGMT frame using the API:
+ * wma_tx_frame( ... pPacket, ..., (void *) lim_tx_complete, pData )
+ * HDD, via wma_tx_frame/DXE, "transfers" the packet over to BMU
+ * HDD, if it determines that a TX completion routine (in this case
+ * lim_tx_complete) has been provided, will invoke this callback
+ * LIM will try to free the TX MGMT packet that was earlier allocated, in order
+ * to send this MGMT frame, using the PAL API cds_packet_free( ... pData, pPacket )
+ *
+ * Assumptions:
+ * Presently, this is ONLY being used for MGMT frames/packets
+ * TODO:
+ * Would it do good for LIM to have some sort of "signature" validation to
+ * ensure that the pData argument passed in was a buffer that was actually
+ * allocated by LIM and/or is not corrupted?
+ *
+ * Note: FIXME and TODO
+ * Looks like cds_packet_free() is interested in pPacket. But, when this completion
+ * routine is called, only pData is made available to LIM!!
+ *
+ * @param void A pointer to pData. Shouldn't it be pPacket?!
+ *
+ * @return none
+ */
+void lim_tx_complete(tHalHandle hHal, void *data, bool free)
+{
+ if (free)
+ cds_packet_free((void *)data);
+}
+
+/**
+ * \brief This function updates lim global structure, if CB parameters in the BSS
+ * have changed, and sends an indication to HAL also with the
+ * updated HT Parameters.
+ * This function does not detect the change in the primary channel, that is done as part
+ * of channel Swtich IE processing.
+ * If STA is configured with '20Mhz only' mode, then this function does not do anything
+ * This function changes the CB mode, only if the self capability is set to '20 as well as 40Mhz'
+ *
+ *
+ * \param pMac Pointer to global MAC structure
+ *
+ * \param pRcvdHTInfo Pointer to HT Info IE obtained from a Beacon or
+ * Probe Response
+ *
+ * \param bssIdx BSS Index of the Bss to which Station is associated.
+ *
+ *
+ */
+
+void lim_update_sta_run_time_ht_switch_chnl_params(tpAniSirGlobal pMac,
+ tDot11fIEHTInfo *pHTInfo,
+ uint8_t bssIdx,
+ tpPESession psessionEntry)
+{
+ uint8_t center_freq = 0;
+#if !defined WLAN_FEATURE_VOWIFI
+ uint32_t localPwrConstraint;
+#endif
+
+ /* If self capability is set to '20Mhz only', then do not change the CB mode. */
+ if (!lim_get_ht_capability
+ (pMac, eHT_SUPPORTED_CHANNEL_WIDTH_SET, psessionEntry))
+ return;
+
+#if !defined WLAN_FEATURE_VOWIFI
+ if (wlan_cfg_get_int
+ (pMac, WNI_CFG_LOCAL_POWER_CONSTRAINT,
+ &localPwrConstraint) != eSIR_SUCCESS) {
+ lim_log(pMac, LOGP,
+ FL("Unable to get Local Power Constraint from cfg"));
+ return;
+ }
+#endif
+
+ if (psessionEntry->ftPEContext.ftPreAuthSession) {
+ lim_log(pMac, LOGE,
+ FL("FT PREAUTH channel change is in progress"));
+ return;
+ }
+
+ if (psessionEntry->htSecondaryChannelOffset !=
+ (uint8_t) pHTInfo->secondaryChannelOffset
+ || psessionEntry->htRecommendedTxWidthSet !=
+ (uint8_t) pHTInfo->recommendedTxWidthSet) {
+ psessionEntry->htSecondaryChannelOffset =
+ (ePhyChanBondState) pHTInfo->secondaryChannelOffset;
+ psessionEntry->htRecommendedTxWidthSet =
+ (uint8_t) pHTInfo->recommendedTxWidthSet;
+ if (eHT_CHANNEL_WIDTH_40MHZ ==
+ psessionEntry->htRecommendedTxWidthSet) {
+ if (PHY_DOUBLE_CHANNEL_LOW_PRIMARY ==
+ pHTInfo->secondaryChannelOffset)
+ center_freq = pHTInfo->primaryChannel + 2;
+ else if (PHY_DOUBLE_CHANNEL_HIGH_PRIMARY ==
+ pHTInfo->secondaryChannelOffset)
+ center_freq = pHTInfo->primaryChannel - 2;
+ }
+
+ /* notify HAL */
+ lim_log(pMac, LOGW, FL("Channel Information in HT IE change"
+ "d; sending notification to HAL."));
+ lim_log(pMac, LOGW, FL("Primary Channel: %d, Secondary Chan"
+ "nel Offset: %d, Channel Width: %d"),
+ pHTInfo->primaryChannel, center_freq,
+ psessionEntry->htRecommendedTxWidthSet);
+ psessionEntry->channelChangeReasonCode =
+ LIM_SWITCH_CHANNEL_OPERATION;
+ pMac->lim.gpchangeChannelCallback = NULL;
+ pMac->lim.gpchangeChannelData = NULL;
+
+#if defined WLAN_FEATURE_VOWIFI
+ lim_send_switch_chnl_params(pMac, (uint8_t) pHTInfo->primaryChannel,
+ center_freq, 0,
+ psessionEntry->htRecommendedTxWidthSet,
+ psessionEntry->maxTxPower,
+ psessionEntry->peSessionId,
+ true);
+#else
+ lim_send_switch_chnl_params(pMac, (uint8_t) pHTInfo->primaryChannel,
+ center_freq, 0,
+ psessionEntry->htRecommendedTxWidthSet,
+ (tPowerdBm) localPwrConstraint,
+ psessionEntry->peSessionId,
+ true);
+#endif
+
+ /* In case of IBSS, if STA should update HT Info IE in its beacons. */
+ if (LIM_IS_IBSS_ROLE(psessionEntry)) {
+ sch_set_fixed_beacon_fields(pMac, psessionEntry);
+ }
+
+ }
+} /* End limUpdateStaRunTimeHTParams. */
+
+/**
+ * \brief This function updates the lim global structure, if any of the
+ * HT Capabilities have changed.
+ *
+ *
+ * \param pMac Pointer to Global MAC structure
+ *
+ * \param pHTCapability Pointer to HT Capability Information Element
+ * obtained from a Beacon or Probe Response
+ *
+ *
+ *
+ */
+
+void lim_update_sta_run_time_ht_capability(tpAniSirGlobal pMac,
+ tDot11fIEHTCaps *pHTCaps)
+{
+
+ if (pMac->lim.gHTLsigTXOPProtection !=
+ (uint8_t) pHTCaps->lsigTXOPProtection) {
+ pMac->lim.gHTLsigTXOPProtection =
+ (uint8_t) pHTCaps->lsigTXOPProtection;
+ /* Send change notification to HAL */
+ }
+
+ if (pMac->lim.gHTAMpduDensity != (uint8_t) pHTCaps->mpduDensity) {
+ pMac->lim.gHTAMpduDensity = (uint8_t) pHTCaps->mpduDensity;
+ /* Send change notification to HAL */
+ }
+
+ if (pMac->lim.gHTMaxRxAMpduFactor !=
+ (uint8_t) pHTCaps->maxRxAMPDUFactor) {
+ pMac->lim.gHTMaxRxAMpduFactor =
+ (uint8_t) pHTCaps->maxRxAMPDUFactor;
+ /* Send change notification to HAL */
+ }
+
+} /* End lim_update_sta_run_time_ht_capability. */
+
+/**
+ * \brief This function updates lim global structure, if any of the HT
+ * Info Parameters have changed.
+ *
+ *
+ * \param pMac Pointer to the global MAC structure
+ *
+ * \param pHTInfo Pointer to the HT Info IE obtained from a Beacon or
+ * Probe Response
+ *
+ *
+ */
+
+void lim_update_sta_run_time_ht_info(tpAniSirGlobal pMac,
+ tDot11fIEHTInfo *pHTInfo,
+ tpPESession psessionEntry)
+{
+ if (psessionEntry->htRecommendedTxWidthSet !=
+ (uint8_t) pHTInfo->recommendedTxWidthSet) {
+ psessionEntry->htRecommendedTxWidthSet =
+ (uint8_t) pHTInfo->recommendedTxWidthSet;
+ /* Send change notification to HAL */
+ }
+
+ if (psessionEntry->beaconParams.fRIFSMode !=
+ (uint8_t) pHTInfo->rifsMode) {
+ psessionEntry->beaconParams.fRIFSMode =
+ (uint8_t) pHTInfo->rifsMode;
+ /* Send change notification to HAL */
+ }
+
+ if (pMac->lim.gHTServiceIntervalGranularity !=
+ (uint8_t) pHTInfo->serviceIntervalGranularity) {
+ pMac->lim.gHTServiceIntervalGranularity =
+ (uint8_t) pHTInfo->serviceIntervalGranularity;
+ /* Send change notification to HAL */
+ }
+
+ if (pMac->lim.gHTOperMode != (tSirMacHTOperatingMode) pHTInfo->opMode) {
+ pMac->lim.gHTOperMode =
+ (tSirMacHTOperatingMode) pHTInfo->opMode;
+ /* Send change notification to HAL */
+ }
+
+ if (psessionEntry->beaconParams.llnNonGFCoexist !=
+ pHTInfo->nonGFDevicesPresent) {
+ psessionEntry->beaconParams.llnNonGFCoexist =
+ (uint8_t) pHTInfo->nonGFDevicesPresent;
+ }
+
+ if (pMac->lim.gHTSTBCBasicMCS != (uint8_t) pHTInfo->basicSTBCMCS) {
+ pMac->lim.gHTSTBCBasicMCS = (uint8_t) pHTInfo->basicSTBCMCS;
+ /* Send change notification to HAL */
+ }
+
+ if (pMac->lim.gHTDualCTSProtection !=
+ (uint8_t) pHTInfo->dualCTSProtection) {
+ pMac->lim.gHTDualCTSProtection =
+ (uint8_t) pHTInfo->dualCTSProtection;
+ /* Send change notification to HAL */
+ }
+
+ if (pMac->lim.gHTSecondaryBeacon != (uint8_t) pHTInfo->secondaryBeacon) {
+ pMac->lim.gHTSecondaryBeacon =
+ (uint8_t) pHTInfo->secondaryBeacon;
+ /* Send change notification to HAL */
+ }
+
+ if (psessionEntry->beaconParams.fLsigTXOPProtectionFullSupport !=
+ (uint8_t) pHTInfo->lsigTXOPProtectionFullSupport) {
+ psessionEntry->beaconParams.fLsigTXOPProtectionFullSupport =
+ (uint8_t) pHTInfo->lsigTXOPProtectionFullSupport;
+ /* Send change notification to HAL */
+ }
+
+ if (pMac->lim.gHTPCOActive != (uint8_t) pHTInfo->pcoActive) {
+ pMac->lim.gHTPCOActive = (uint8_t) pHTInfo->pcoActive;
+ /* Send change notification to HAL */
+ }
+
+ if (pMac->lim.gHTPCOPhase != (uint8_t) pHTInfo->pcoPhase) {
+ pMac->lim.gHTPCOPhase = (uint8_t) pHTInfo->pcoPhase;
+ /* Send change notification to HAL */
+ }
+
+} /* End lim_update_sta_run_time_ht_info. */
+
+/** -------------------------------------------------------------
+ \fn lim_process_hal_ind_messages
+ \brief callback function for HAL indication
+ \param tpAniSirGlobal pMac
+ \param uint32_t mesgId
+ \param void *mesgParam
+ \return tSirRetStatu - status
+ -------------------------------------------------------------*/
+
+tSirRetStatus lim_process_hal_ind_messages(tpAniSirGlobal pMac, uint32_t msgId,
+ void *msgParam)
+{
+ /* its PE's responsibility to free msgparam when its done extracting the message parameters. */
+ tSirMsgQ msg;
+
+ switch (msgId) {
+ case SIR_LIM_DEL_TS_IND:
+ case SIR_LIM_DELETE_STA_CONTEXT_IND:
+ case SIR_LIM_BEACON_GEN_IND:
+ msg.type = (uint16_t) msgId;
+ msg.bodyptr = msgParam;
+ msg.bodyval = 0;
+ break;
+
+ default:
+ cdf_mem_free(msgParam);
+ lim_log(pMac, LOGP, FL("invalid message id = %d received"),
+ msgId);
+ return eSIR_FAILURE;
+ }
+
+ if (lim_post_msg_api(pMac, &msg) != eSIR_SUCCESS) {
+ cdf_mem_free(msgParam);
+ lim_log(pMac, LOGP, FL("lim_post_msg_api failed for msgid = %d"),
+ msg.type);
+ return eSIR_FAILURE;
+ }
+ return eSIR_SUCCESS;
+}
+
+/**
+ * lim_validate_delts_req() - This function validates DelTs req
+ * @mac_ctx: pointer to Global Mac structure
+ * @delts_req: pointer to delete traffic stream structure
+ * @peer_mac_addr: variable for peer mac address
+ *
+ * Function validates DelTs req originated by SME or by HAL and also
+ * sends halMsg_DelTs to HAL
+ *
+ * Return: eSIR_SUCCESS - Success, eSIR_FAILURE - Failure
+ */
+
+tSirRetStatus
+lim_validate_delts_req(tpAniSirGlobal mac_ctx, tpSirDeltsReq delts_req,
+ tSirMacAddr peer_mac_addr, tpPESession psession_entry)
+{
+ tpDphHashNode sta;
+ uint8_t ts_status;
+ tSirMacTSInfo *tsinfo;
+ uint32_t i;
+ uint8_t tspec_idx;
+
+ /*
+ * if sta
+ * - verify assoc state
+ * - del tspec locally
+ * if ap
+ * - verify sta is in assoc state
+ * - del sta tspec locally
+ */
+ if (delts_req == NULL) {
+ lim_log(mac_ctx, LOGE,
+ FL("Delete TS request pointer is NULL"));
+ return eSIR_FAILURE;
+ }
+
+ if (LIM_IS_STA_ROLE(psession_entry) ||
+ LIM_IS_BT_AMP_STA_ROLE(psession_entry)) {
+ uint32_t val;
+
+ /* station always talks to the AP */
+ sta = dph_get_hash_entry(mac_ctx, DPH_STA_HASH_INDEX_PEER,
+ &psession_entry->dph.dphHashTable);
+
+ val = sizeof(tSirMacAddr);
+ sir_copy_mac_addr(peer_mac_addr, psession_entry->bssId);
+
+ } else {
+ uint16_t associd;
+ uint8_t *macaddr = (uint8_t *) peer_mac_addr;
+
+ associd = delts_req->aid;
+ if (associd != 0)
+ sta = dph_get_hash_entry(mac_ctx, associd,
+ &psession_entry->dph.dphHashTable);
+ else
+ sta = dph_lookup_hash_entry(mac_ctx,
+ delts_req->macAddr,
+ &associd,
+ &psession_entry->dph.
+ dphHashTable);
+
+ if (sta != NULL)
+ /* TBD: check sta assoc state as well */
+ for (i = 0; i < sizeof(tSirMacAddr); i++)
+ macaddr[i] = sta->staAddr[i];
+ }
+
+ if (sta == NULL) {
+ lim_log(mac_ctx, LOGE,
+ FL("Cannot find station context for delts req"));
+ return eSIR_FAILURE;
+ }
+
+ if ((!sta->valid) ||
+ (sta->mlmStaContext.mlmState !=
+ eLIM_MLM_LINK_ESTABLISHED_STATE)) {
+ lim_log(mac_ctx, LOGE,
+ FL("Invalid Sta (or state) for DelTsReq"));
+ return eSIR_FAILURE;
+ }
+
+ delts_req->req.wsmTspecPresent = 0;
+ delts_req->req.wmeTspecPresent = 0;
+ delts_req->req.lleTspecPresent = 0;
+
+ if ((sta->wsmEnabled) &&
+ (delts_req->req.tspec.tsinfo.traffic.accessPolicy !=
+ SIR_MAC_ACCESSPOLICY_EDCA))
+ delts_req->req.wsmTspecPresent = 1;
+ else if (sta->wmeEnabled)
+ delts_req->req.wmeTspecPresent = 1;
+ else if (sta->lleEnabled)
+ delts_req->req.lleTspecPresent = 1;
+ else {
+ lim_log(mac_ctx, LOGW,
+ FL("DELTS_REQ ignore - qos is disabled"));
+ return eSIR_FAILURE;
+ }
+
+ tsinfo = delts_req->req.wmeTspecPresent ? &delts_req->req.tspec.tsinfo
+ : &delts_req->req.tsinfo;
+ lim_log(mac_ctx, LOG1,
+ FL("received DELTS_REQ message (wmeTspecPresent = %d, lleTspecPresent = %d, wsmTspecPresent = %d, tsid %d, up %d, direction = %d)"),
+ delts_req->req.wmeTspecPresent,
+ delts_req->req.lleTspecPresent,
+ delts_req->req.wsmTspecPresent, tsinfo->traffic.tsid,
+ tsinfo->traffic.userPrio, tsinfo->traffic.direction);
+
+ /* if no Access Control, ignore the request */
+ if (lim_admit_control_delete_ts(mac_ctx, sta->assocId, tsinfo,
+ &ts_status, &tspec_idx) != eSIR_SUCCESS) {
+ lim_log(mac_ctx, LOGE,
+ FL("ERROR DELTS request for sta assocId %d (tsid %d, up %d)"),
+ sta->assocId, tsinfo->traffic.tsid,
+ tsinfo->traffic.userPrio);
+ return eSIR_FAILURE;
+ } else if ((tsinfo->traffic.accessPolicy == SIR_MAC_ACCESSPOLICY_HCCA)
+ || (tsinfo->traffic.accessPolicy ==
+ SIR_MAC_ACCESSPOLICY_BOTH)) {
+ /* edca only now. */
+ } else if (tsinfo->traffic.accessPolicy == SIR_MAC_ACCESSPOLICY_EDCA) {
+ /* send message to HAL to delete TS */
+ if (eSIR_SUCCESS !=
+ lim_send_hal_msg_del_ts(mac_ctx, sta->staIndex,
+ tspec_idx, delts_req->req,
+ psession_entry->peSessionId,
+ psession_entry->bssId)) {
+ lim_log(mac_ctx, LOGW,
+ FL("DelTs with UP %d failed in lim_send_hal_msg_del_ts - ignoring request"),
+ tsinfo->traffic.userPrio);
+ return eSIR_FAILURE;
+ }
+ }
+ return eSIR_SUCCESS;
+}
+
+/** -------------------------------------------------------------
+ \fn lim_register_hal_ind_call_back
+ \brief registers callback function to HAL for any indication.
+ \param tpAniSirGlobal pMac
+ \return none.
+ -------------------------------------------------------------*/
+void lim_register_hal_ind_call_back(tpAniSirGlobal pMac)
+{
+ tSirMsgQ msg;
+ tpHalIndCB pHalCB;
+
+ pHalCB = cdf_mem_malloc(sizeof(tHalIndCB));
+ if (NULL == pHalCB) {
+ lim_log(pMac, LOGP, FL("AllocateMemory() failed"));
+ return;
+ }
+
+ pHalCB->pHalIndCB = lim_process_hal_ind_messages;
+
+ msg.type = WMA_REGISTER_PE_CALLBACK;
+ msg.bodyptr = pHalCB;
+ msg.bodyval = 0;
+
+ MTRACE(mac_trace_msg_tx(pMac, NO_SESSION, msg.type));
+ if (eSIR_SUCCESS != wma_post_ctrl_msg(pMac, &msg)) {
+ cdf_mem_free(pHalCB);
+ lim_log(pMac, LOGP, FL("wma_post_ctrl_msg() failed"));
+ }
+
+ return;
+}
+
+/**
+ * lim_process_del_ts_ind() - handle del_ts_ind from HAL
+ *
+ * @mac_ctx: pointer to Global Mac Structure
+ * @lim_msg: pointer to msg buff
+ *
+ * handles the DeleteTS indication coming from HAL or generated by PE itself
+ * in some error cases. Validates the request, sends the DelTs action frame
+ * to the Peer and sends DelTs indicatoin to HDD.
+ *
+ * Return: none
+ */
+void lim_process_del_ts_ind(tpAniSirGlobal pMac, tpSirMsgQ limMsg)
+{
+ tpDphHashNode pSta;
+ tpDelTsParams pDelTsParam = (tpDelTsParams) (limMsg->bodyptr);
+ tpSirDeltsReq pDelTsReq = NULL;
+ tSirMacAddr peerMacAddr;
+ tpSirDeltsReqInfo pDelTsReqInfo;
+ tpLimTspecInfo pTspecInfo;
+ tpPESession psessionEntry;
+ uint8_t sessionId;
+
+ psessionEntry = pe_find_session_by_bssid(pMac, pDelTsParam->bssId,
+ &sessionId);
+ if (psessionEntry == NULL) {
+ lim_log(pMac, LOGE,
+ FL("session does not exist for given BssId"));
+ cdf_mem_free(limMsg->bodyptr);
+ limMsg->bodyptr = NULL;
+ return;
+ }
+
+ pTspecInfo = &(pMac->lim.tspecInfo[pDelTsParam->tspecIdx]);
+ if (pTspecInfo->inuse == false) {
+ PELOGE(lim_log
+ (pMac, LOGE,
+ FL("tspec entry with index %d is not in use"),
+ pDelTsParam->tspecIdx);
+ )
+ goto error1;
+ }
+
+ pSta =
+ dph_get_hash_entry(pMac, pTspecInfo->assocId,
+ &psessionEntry->dph.dphHashTable);
+ if (pSta == NULL) {
+ lim_log(pMac, LOGE,
+ FL("Could not find entry in DPH table for assocId = %d"),
+ pTspecInfo->assocId);
+ goto error1;
+ }
+
+ pDelTsReq = cdf_mem_malloc(sizeof(tSirDeltsReq));
+ if (NULL == pDelTsReq) {
+ PELOGE(lim_log(pMac, LOGE, FL("AllocateMemory() failed"));)
+ goto error1;
+ }
+
+ cdf_mem_set((uint8_t *) pDelTsReq, sizeof(tSirDeltsReq), 0);
+
+ if (pSta->wmeEnabled)
+ cdf_mem_copy(&(pDelTsReq->req.tspec), &(pTspecInfo->tspec),
+ sizeof(tSirMacTspecIE));
+ else
+ cdf_mem_copy(&(pDelTsReq->req.tsinfo),
+ &(pTspecInfo->tspec.tsinfo),
+ sizeof(tSirMacTSInfo));
+
+ /* validate the req */
+ if (eSIR_SUCCESS !=
+ lim_validate_delts_req(pMac, pDelTsReq, peerMacAddr, psessionEntry)) {
+ PELOGE(lim_log(pMac, LOGE, FL("lim_validate_delts_req failed"));)
+ goto error2;
+ }
+ PELOG1(lim_log(pMac, LOG1, "Sent DELTS request to station with "
+ "assocId = %d MacAddr = " MAC_ADDRESS_STR,
+ pDelTsReq->aid, MAC_ADDR_ARRAY(peerMacAddr));
+ )
+
+ lim_send_delts_req_action_frame(pMac, peerMacAddr,
+ pDelTsReq->req.wmeTspecPresent,
+ &pDelTsReq->req.tsinfo,
+ &pDelTsReq->req.tspec, psessionEntry);
+
+ /* prepare and send an sme indication to HDD */
+ pDelTsReqInfo = cdf_mem_malloc(sizeof(tSirDeltsReqInfo));
+ if (NULL == pDelTsReqInfo) {
+ PELOGE(lim_log(pMac, LOGE, FL("AllocateMemory() failed"));)
+ goto error3;
+ }
+ cdf_mem_set((uint8_t *) pDelTsReqInfo, sizeof(tSirDeltsReqInfo), 0);
+
+ if (pSta->wmeEnabled)
+ cdf_mem_copy(&(pDelTsReqInfo->tspec), &(pTspecInfo->tspec),
+ sizeof(tSirMacTspecIE));
+ else
+ cdf_mem_copy(&(pDelTsReqInfo->tsinfo),
+ &(pTspecInfo->tspec.tsinfo),
+ sizeof(tSirMacTSInfo));
+
+ lim_send_sme_delts_ind(pMac, pDelTsReqInfo, pDelTsReq->aid, psessionEntry);
+
+error3:
+ cdf_mem_free(pDelTsReqInfo);
+error2:
+ cdf_mem_free(pDelTsReq);
+error1:
+ cdf_mem_free(limMsg->bodyptr);
+ limMsg->bodyptr = NULL;
+ return;
+}
+
+/**
+ * @function : lim_post_sm_state_update()
+ *
+ * @brief : This function Updates the HAL and Softmac about the change in the STA's SMPS state.
+ *
+ * LOGIC:
+ *
+ * ASSUMPTIONS:
+ * NA
+ *
+ * NOTE:
+ * NA
+ *
+ * @param pMac - Pointer to Global MAC structure
+ * @param limMsg - Lim Message structure object with the MimoPSparam in body
+ * @return None
+ */
+tSirRetStatus
+lim_post_sm_state_update(tpAniSirGlobal pMac,
+ uint16_t staIdx, tSirMacHTMIMOPowerSaveState state,
+ uint8_t *pPeerStaMac, uint8_t sessionId)
+{
+ tSirRetStatus retCode = eSIR_SUCCESS;
+ tSirMsgQ msgQ;
+ tpSetMIMOPS pMIMO_PSParams;
+
+ msgQ.reserved = 0;
+ msgQ.type = WMA_SET_MIMOPS_REQ;
+
+ /* Allocate for WMA_SET_MIMOPS_REQ */
+ pMIMO_PSParams = cdf_mem_malloc(sizeof(tSetMIMOPS));
+ if (NULL == pMIMO_PSParams) {
+ lim_log(pMac, LOGP, FL(" AllocateMemory failed"));
+ return eSIR_MEM_ALLOC_FAILED;
+ }
+
+ pMIMO_PSParams->htMIMOPSState = state;
+ pMIMO_PSParams->staIdx = staIdx;
+ pMIMO_PSParams->fsendRsp = true;
+ pMIMO_PSParams->sessionId = sessionId;
+ cdf_mem_copy(pMIMO_PSParams->peerMac, pPeerStaMac, sizeof(tSirMacAddr));
+
+ msgQ.bodyptr = pMIMO_PSParams;
+ msgQ.bodyval = 0;
+
+ lim_log(pMac, LOG2, FL("Sending WMA_SET_MIMOPS_REQ..."));
+
+ MTRACE(mac_trace_msg_tx(pMac, NO_SESSION, msgQ.type));
+ retCode = wma_post_ctrl_msg(pMac, &msgQ);
+ if (eSIR_SUCCESS != retCode) {
+ lim_log(pMac, LOGP,
+ FL
+ ("Posting WMA_SET_MIMOPS_REQ to HAL failed! Reason = %d"),
+ retCode);
+ cdf_mem_free(pMIMO_PSParams);
+ return retCode;
+ }
+
+ return retCode;
+}
+
+void lim_pkt_free(tpAniSirGlobal pMac,
+ eFrameType frmType, uint8_t *pRxPacketInfo, void *pBody)
+{
+ (void)pMac;
+ (void)frmType;
+ (void)pRxPacketInfo;
+ (void)pBody;
+}
+
+/**
+ * lim_get_b_dfrom_rx_packet()
+ *
+ ***FUNCTION:
+ * This function is called to get pointer to Polaris
+ * Buffer Descriptor containing MAC header & other control
+ * info from the body of the message posted to LIM.
+ *
+ ***LOGIC:
+ * NA
+ *
+ ***ASSUMPTIONS:
+ * NA
+ *
+ ***NOTE:
+ * NA
+ *
+ * @param body - Received message body
+ * @param pRxPacketInfo - Pointer to received BD
+ * @return None
+ */
+
+void
+lim_get_b_dfrom_rx_packet(tpAniSirGlobal pMac, void *body, uint32_t **pRxPacketInfo)
+{
+ *pRxPacketInfo = (uint32_t *) body;
+} /*** end lim_get_b_dfrom_rx_packet() ***/
+
+void lim_resset_scan_channel_info(tpAniSirGlobal pMac)
+{
+ cdf_mem_set(&pMac->lim.scanChnInfo, sizeof(tLimScanChnInfo), 0);
+}
+
+/**
+ * @function : lim_is_channel_valid_for_channel_switch()
+ *
+ * @brief : This function checks if the channel to which AP
+ * is expecting us to switch, is a valid channel for us.
+ * LOGIC:
+ *
+ * ASSUMPTIONS:
+ * NA
+ *
+ * NOTE:
+ * NA
+ *
+ * @param pMac - Pointer to Global MAC structure
+ * @param channel - New channel to which we are expected to move
+ * @return None
+ */
+tAniBool lim_is_channel_valid_for_channel_switch(tpAniSirGlobal pMac, uint8_t channel)
+{
+ uint8_t index;
+ uint32_t validChannelListLen = WNI_CFG_VALID_CHANNEL_LIST_LEN;
+ tSirMacChanNum validChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN];
+
+ if (wlan_cfg_get_str(pMac, WNI_CFG_VALID_CHANNEL_LIST,
+ (uint8_t *) validChannelList,
+ (uint32_t *) &validChannelListLen) !=
+ eSIR_SUCCESS) {
+ PELOGE(lim_log
+ (pMac, LOGE,
+ FL("could not retrieve valid channel list"));
+ )
+ return eSIR_FALSE;
+ }
+
+ for (index = 0; index < validChannelListLen; index++) {
+ if (validChannelList[index] == channel)
+ return eSIR_TRUE;
+ }
+
+ /* channel does not belong to list of valid channels */
+ return eSIR_FALSE;
+}
+
+/**------------------------------------------------------
+ \fn __lim_fill_tx_control_params
+ \brief Fill the message for stopping/resuming tx.
+
+ \param pMac
+ \param pTxCtrlMsg - Pointer to tx control message.
+ \param type - Which way we want to stop/ resume tx.
+ \param mode - To stop/resume.
+ -------------------------------------------------------*/
+static CDF_STATUS
+__lim_fill_tx_control_params(tpAniSirGlobal pMac, tpTxControlParams pTxCtrlMsg,
+ tLimQuietTxMode type, tLimControlTx mode)
+{
+
+ tpPESession psessionEntry = &pMac->lim.gpSession[0];
+
+ if (mode == eLIM_STOP_TX)
+ pTxCtrlMsg->stopTx = true;
+ else
+ pTxCtrlMsg->stopTx = false;
+
+ switch (type) {
+ case eLIM_TX_ALL:
+ /** Stops/resumes transmission completely */
+ pTxCtrlMsg->fCtrlGlobal = 1;
+ break;
+
+ case eLIM_TX_BSS_BUT_BEACON:
+ /** Stops/resumes transmission on a particular BSS. Stopping BSS, doesnt
+ * stop beacon transmission.
+ */
+ pTxCtrlMsg->ctrlBss = 1;
+ pTxCtrlMsg->bssBitmap |= (1 << psessionEntry->bssIdx);
+ break;
+
+ case eLIM_TX_STA:
+ /** Memory for station bitmap is allocated dynamically in caller of this
+ * so decode properly here and fill the bitmap. Now not implemented,
+ * fall through.
+ */
+ case eLIM_TX_BSS:
+ /* Fall thru... */
+ default:
+ PELOGW(lim_log(pMac, LOGW, FL("Invalid case: Not Handled"));)
+ return CDF_STATUS_E_FAILURE;
+ }
+
+ return CDF_STATUS_SUCCESS;
+}
+
+/**
+ * @function : lim_frame_transmission_control()
+ *
+ * @brief : This API is called by the user to halt/resume any frame
+ * transmission from the device. If stopped, all frames will be
+ * queued starting from hardware. Then back-pressure
+ * is built till the driver.
+ * LOGIC:
+ *
+ * ASSUMPTIONS:
+ * NA
+ *
+ * NOTE:
+ * NA
+ *
+ * @param pMac - Pointer to Global MAC structure
+ * @return None
+ */
+void lim_frame_transmission_control(tpAniSirGlobal pMac, tLimQuietTxMode type,
+ tLimControlTx mode)
+{
+
+ CDF_STATUS status = CDF_STATUS_E_FAILURE;
+ tpTxControlParams pTxCtrlMsg;
+ tSirMsgQ msgQ;
+ uint8_t nBytes = 0; /* No of bytes required for station bitmap. */
+
+ /** Allocate only required number of bytes for station bitmap
+ * Make it to align to 4 byte boundary */
+ nBytes = (uint8_t) HALMSG_NUMBYTES_STATION_BITMAP(pMac->lim.maxStation);
+
+ pTxCtrlMsg = cdf_mem_malloc(sizeof(*pTxCtrlMsg) + nBytes);
+ if (NULL == pTxCtrlMsg) {
+ lim_log(pMac, LOGP, FL("AllocateMemory() failed"));
+ return;
+ }
+
+ cdf_mem_set((void *)pTxCtrlMsg, (sizeof(*pTxCtrlMsg) + nBytes), 0);
+ status = __lim_fill_tx_control_params(pMac, pTxCtrlMsg, type, mode);
+ if (status != CDF_STATUS_SUCCESS) {
+ cdf_mem_free(pTxCtrlMsg);
+ lim_log(pMac, LOGP,
+ FL("__lim_fill_tx_control_params failed, status = %d"),
+ status);
+ return;
+ }
+
+ msgQ.bodyptr = (void *)pTxCtrlMsg;
+ msgQ.bodyval = 0;
+ msgQ.reserved = 0;
+ msgQ.type = WMA_TRANSMISSION_CONTROL_IND;
+
+ MTRACE(mac_trace_msg_tx(pMac, NO_SESSION, msgQ.type));
+ if (wma_post_ctrl_msg(pMac, &msgQ) != eSIR_SUCCESS) {
+ cdf_mem_free(pTxCtrlMsg);
+ lim_log(pMac, LOGP, FL("Posting Message to HAL failed"));
+ return;
+ }
+
+ if (mode == eLIM_STOP_TX) {
+ PELOG1(lim_log
+ (pMac, LOG1,
+ FL
+ ("Stopping the transmission of all packets, indicated softmac"));
+ )
+ } else {
+ PELOG1(lim_log
+ (pMac, LOG1,
+ FL
+ ("Resuming the transmission of all packets, indicated softmac"));
+ )
+ }
+ return;
+}
+
+/**
+ * @function : lim_restore_pre_channel_switch_state()
+ *
+ * @brief : This API is called by the user to undo any
+ * specific changes done on the device during
+ * channel switch.
+ * LOGIC:
+ *
+ * ASSUMPTIONS:
+ * NA
+ *
+ * NOTE:
+ * NA
+ *
+ * @param pMac - Pointer to Global MAC structure
+ * @return None
+ */
+
+tSirRetStatus
+lim_restore_pre_channel_switch_state(tpAniSirGlobal pMac, tpPESession psessionEntry)
+{
+
+ tSirRetStatus retCode = eSIR_SUCCESS;
+
+ if (!LIM_IS_STA_ROLE(psessionEntry))
+ return retCode;
+
+ /* Channel switch should be ready for the next time */
+ psessionEntry->gLimSpecMgmt.dot11hChanSwState = eLIM_11H_CHANSW_INIT;
+
+ /* Restore the frame transmission, all the time. */
+ lim_frame_transmission_control(pMac, eLIM_TX_ALL, eLIM_RESUME_TX);
+
+ return retCode;
+}
+
+/**--------------------------------------------
+ \fn lim_restore_pre_quiet_state
+ \brief Restore the pre quiet state
+
+ \param pMac
+ \return NONE
+ ---------------------------------------------*/
+tSirRetStatus lim_restore_pre_quiet_state(tpAniSirGlobal pMac,
+ tpPESession psessionEntry)
+{
+
+ tSirRetStatus retCode = eSIR_SUCCESS;
+
+ if (pMac->lim.gLimSystemRole != eLIM_STA_ROLE)
+ return retCode;
+
+ /* Quiet should be ready for the next time */
+ psessionEntry->gLimSpecMgmt.quietState = eLIM_QUIET_INIT;
+
+ /* Restore the frame transmission, all the time. */
+ if (psessionEntry->gLimSpecMgmt.quietState == eLIM_QUIET_RUNNING)
+ lim_frame_transmission_control(pMac, eLIM_TX_ALL, eLIM_RESUME_TX);
+
+ return retCode;
+}
+
+/**
+ * @function: lim_prepare_for11h_channel_switch()
+ *
+ * @brief : This API is called by the user to prepare for
+ * 11h channel switch. As of now, the API does
+ * very minimal work. User can add more into the
+ * same API if needed.
+ * LOGIC:
+ *
+ * ASSUMPTIONS:
+ * NA
+ *
+ * NOTE:
+ * NA
+ *
+ * @param pMac - Pointer to Global MAC structure
+ * @param psessionEntry
+ * @return None
+ */
+void
+lim_prepare_for11h_channel_switch(tpAniSirGlobal pMac, tpPESession psessionEntry)
+{
+ if (!LIM_IS_STA_ROLE(psessionEntry))
+ return;
+
+ /* Flag to indicate 11h channel switch in progress */
+ psessionEntry->gLimSpecMgmt.dot11hChanSwState = eLIM_11H_CHANSW_RUNNING;
+
+ if (pMac->lim.gLimSmeState == eLIM_SME_LINK_EST_WT_SCAN_STATE ||
+ pMac->lim.gLimSmeState == eLIM_SME_CHANNEL_SCAN_STATE) {
+ PELOGE(lim_log
+ (pMac, LOG1,
+ FL("Posting finish scan as we are in scan state"));
+ )
+ /* Stop ongoing scanning if any */
+ if (GET_LIM_PROCESS_DEFD_MESGS(pMac)) {
+ /* Set the resume channel to Any valid channel (invalid). */
+ /* This will instruct HAL to set it to any previous valid channel. */
+ pe_set_resume_channel(pMac, 0, 0);
+ } else {
+ lim_restore_pre_channel_switch_state(pMac, psessionEntry);
+ }
+ return;
+ } else {
+ PELOGE(lim_log
+ (pMac, LOG1,
+ FL("Not in scan state, start channel switch timer"));
+ )
+ /** We are safe to switch channel at this point */
+ lim_stop_tx_and_switch_channel(pMac, psessionEntry->peSessionId);
+ }
+}
+
+/**----------------------------------------------------
+ \fn lim_get_nw_type
+
+ \brief Get type of the network from data packet or beacon
+ \param pMac
+ \param channelNum - Channel number
+ \param type - Type of packet.
+ \param pBeacon - Pointer to beacon or probe response
+
+ \return Network type a/b/g.
+ -----------------------------------------------------*/
+tSirNwType lim_get_nw_type(tpAniSirGlobal pMac, uint8_t channelNum, uint32_t type,
+ tpSchBeaconStruct pBeacon)
+{
+ tSirNwType nwType = eSIR_11B_NW_TYPE;
+
+ if (type == SIR_MAC_DATA_FRAME) {
+ if ((channelNum > 0) && (channelNum < 15)) {
+ nwType = eSIR_11G_NW_TYPE;
+ } else {
+ nwType = eSIR_11A_NW_TYPE;
+ }
+ } else {
+ if ((channelNum > 0) && (channelNum < 15)) {
+ int i;
+ /* 11b or 11g packet */
+ /* 11g iff extended Rate IE is present or */
+ /* if there is an A rate in suppRate IE */
+ for (i = 0; i < pBeacon->supportedRates.numRates; i++) {
+ if (sirIsArate
+ (pBeacon->supportedRates.rate[i] & 0x7f)) {
+ nwType = eSIR_11G_NW_TYPE;
+ break;
+ }
+ }
+ if (pBeacon->extendedRatesPresent) {
+ PELOG3(lim_log
+ (pMac, LOG3, FL("Beacon, nwtype=G"));
+ )
+ nwType = eSIR_11G_NW_TYPE;
+ }
+ } else {
+ /* 11a packet */
+ PELOG3(lim_log(pMac, LOG3, FL("Beacon, nwtype=A"));)
+ nwType = eSIR_11A_NW_TYPE;
+ }
+ }
+ return nwType;
+}
+
+/**---------------------------------------------------------
+ \fn lim_get_channel_from_beacon
+ \brief To extract channel number from beacon
+
+ \param pMac
+ \param pBeacon - Pointer to beacon or probe rsp
+ \return channel number
+ -----------------------------------------------------------*/
+uint8_t lim_get_channel_from_beacon(tpAniSirGlobal pMac, tpSchBeaconStruct pBeacon)
+{
+ uint8_t channelNum = 0;
+
+ if (pBeacon->dsParamsPresent)
+ channelNum = pBeacon->channelNumber;
+ else if (pBeacon->HTInfo.present)
+ channelNum = pBeacon->HTInfo.primaryChannel;
+ else
+ channelNum = pBeacon->channelNumber;
+
+ return channelNum;
+}
+
+void lim_set_tspec_uapsd_mask_per_session(tpAniSirGlobal pMac,
+ tpPESession psessionEntry,
+ tSirMacTSInfo *pTsInfo, uint32_t action)
+{
+ uint8_t userPrio = (uint8_t) pTsInfo->traffic.userPrio;
+ uint16_t direction = pTsInfo->traffic.direction;
+ uint8_t ac = upToAc(userPrio);
+
+ PELOG1(lim_log
+ (pMac, LOG1, FL("Set UAPSD mask for AC %d, dir %d, action=%d")
+ , ac, direction, action);
+ )
+
+ /* Converting AC to appropriate Uapsd Bit Mask
+ * AC_BE(0) --> UAPSD_BITOFFSET_ACVO(3)
+ * AC_BK(1) --> UAPSD_BITOFFSET_ACVO(2)
+ * AC_VI(2) --> UAPSD_BITOFFSET_ACVO(1)
+ * AC_VO(3) --> UAPSD_BITOFFSET_ACVO(0)
+ */
+ ac = ((~ac) & 0x3);
+
+ if (action == CLEAR_UAPSD_MASK) {
+ if (direction == SIR_MAC_DIRECTION_UPLINK)
+ psessionEntry->gUapsdPerAcTriggerEnableMask &=
+ ~(1 << ac);
+ else if (direction == SIR_MAC_DIRECTION_DNLINK)
+ psessionEntry->gUapsdPerAcDeliveryEnableMask &=
+ ~(1 << ac);
+ else if (direction == SIR_MAC_DIRECTION_BIDIR) {
+ psessionEntry->gUapsdPerAcTriggerEnableMask &=
+ ~(1 << ac);
+ psessionEntry->gUapsdPerAcDeliveryEnableMask &=
+ ~(1 << ac);
+ }
+ } else if (action == SET_UAPSD_MASK) {
+ if (direction == SIR_MAC_DIRECTION_UPLINK)
+ psessionEntry->gUapsdPerAcTriggerEnableMask |=
+ (1 << ac);
+ else if (direction == SIR_MAC_DIRECTION_DNLINK)
+ psessionEntry->gUapsdPerAcDeliveryEnableMask |=
+ (1 << ac);
+ else if (direction == SIR_MAC_DIRECTION_BIDIR) {
+ psessionEntry->gUapsdPerAcTriggerEnableMask |=
+ (1 << ac);
+ psessionEntry->gUapsdPerAcDeliveryEnableMask |=
+ (1 << ac);
+ }
+ }
+
+ lim_log(pMac, LOG1,
+ FL("New psessionEntry->gUapsdPerAcTriggerEnableMask = 0x%x "),
+ psessionEntry->gUapsdPerAcTriggerEnableMask);
+ lim_log(pMac, LOG1,
+ FL("New psessionEntry->gUapsdPerAcDeliveryEnableMask = 0x%x "),
+ psessionEntry->gUapsdPerAcDeliveryEnableMask);
+
+ return;
+}
+
+/**
+ * lim_handle_heart_beat_timeout_for_session() - Handle heart beat time out
+ * @mac_ctx: pointer to Global Mac Structure
+ * @psession_entry: pointer to tpPESession
+ *
+ * Function handles heart beat time out for session
+ *
+ * Return: none
+ */
+void lim_handle_heart_beat_timeout_for_session(tpAniSirGlobal mac_ctx,
+ tpPESession psession_entry)
+{
+ if (psession_entry->valid == true) {
+ if (psession_entry->bssType == eSIR_IBSS_MODE)
+ lim_ibss_heart_beat_handle(mac_ctx, psession_entry);
+
+ if ((psession_entry->bssType == eSIR_INFRASTRUCTURE_MODE) &&
+ (LIM_IS_STA_ROLE(psession_entry)))
+ lim_handle_heart_beat_failure(mac_ctx, psession_entry);
+ }
+ /*
+ * In the function lim_handle_heart_beat_failure things can change
+ * so check for the session entry valid and the other things
+ * again
+ */
+ if ((psession_entry->valid == true) &&
+ (psession_entry->bssType == eSIR_INFRASTRUCTURE_MODE) &&
+ (LIM_IS_STA_ROLE(psession_entry)) &&
+ (psession_entry->LimHBFailureStatus == true)) {
+ tLimTimers *lim_timer = &mac_ctx->lim.limTimers;
+ /*
+ * Activate Probe After HeartBeat Timer incase HB
+ * Failure detected
+ */
+ PELOGW(lim_log(mac_ctx, LOGW,
+ FL("Sending Probe for Session: %d"),
+ psession_entry->bssIdx);)
+ lim_deactivate_and_change_timer(mac_ctx,
+ eLIM_PROBE_AFTER_HB_TIMER);
+ MTRACE(mac_trace(mac_ctx, TRACE_CODE_TIMER_ACTIVATE, 0,
+ eLIM_PROBE_AFTER_HB_TIMER));
+ if (tx_timer_activate(&lim_timer->gLimProbeAfterHBTimer)
+ != TX_SUCCESS)
+ lim_log(mac_ctx, LOGP,
+ FL("Fail to re-activate Probe-after-hb timer"));
+ }
+}
+
+uint8_t lim_get_current_operating_channel(tpAniSirGlobal pMac)
+{
+ uint8_t i;
+ for (i = 0; i < pMac->lim.maxBssId; i++) {
+ if (pMac->lim.gpSession[i].valid == true) {
+ if ((pMac->lim.gpSession[i].bssType ==
+ eSIR_INFRASTRUCTURE_MODE)
+ && (pMac->lim.gpSession[i].limSystemRole ==
+ eLIM_STA_ROLE)) {
+ return pMac->lim.gpSession[i].
+ currentOperChannel;
+ }
+ }
+ }
+ return 0;
+}
+
+void lim_process_add_sta_rsp(tpAniSirGlobal pMac, tpSirMsgQ limMsgQ)
+{
+ tpPESession psessionEntry;
+ tpAddStaParams pAddStaParams;
+
+ pAddStaParams = (tpAddStaParams) limMsgQ->bodyptr;
+
+ psessionEntry = pe_find_session_by_session_id(pMac,
+ pAddStaParams->sessionId);
+ if (psessionEntry == NULL) {
+ lim_log(pMac, LOGP,
+ FL("Session Does not exist for given sessionID"));
+ cdf_mem_free(pAddStaParams);
+ return;
+ }
+ psessionEntry->csaOffloadEnable = pAddStaParams->csaOffloadEnable;
+ if (LIM_IS_IBSS_ROLE(psessionEntry))
+ (void)lim_ibss_add_sta_rsp(pMac, limMsgQ->bodyptr, psessionEntry);
+#ifdef FEATURE_WLAN_TDLS
+ else if (pMac->lim.gLimAddStaTdls) {
+ lim_process_tdls_add_sta_rsp(pMac, limMsgQ->bodyptr, psessionEntry);
+ pMac->lim.gLimAddStaTdls = false;
+ }
+#endif
+ else
+ lim_process_mlm_add_sta_rsp(pMac, limMsgQ, psessionEntry);
+
+}
+
+/**
+ * lim_update_beacon() - This function updates beacon
+ * @mac_ctx: pointer to Global Mac Structure
+ *
+ * This Function is invoked to update the beacon
+ *
+ * Return: none
+ */
+void lim_update_beacon(tpAniSirGlobal mac_ctx)
+{
+ uint8_t i;
+
+ for (i = 0; i < mac_ctx->lim.maxBssId; i++) {
+ if (mac_ctx->lim.gpSession[i].valid != true)
+ continue;
+ if (((mac_ctx->lim.gpSession[i].limSystemRole == eLIM_AP_ROLE)
+ || (mac_ctx->lim.gpSession[i].limSystemRole ==
+ eLIM_STA_IN_IBSS_ROLE))
+ && (eLIM_SME_NORMAL_STATE ==
+ mac_ctx->lim.gpSession[i].limSmeState)) {
+
+ sch_set_fixed_beacon_fields(mac_ctx,
+ &mac_ctx->lim.gpSession[i]);
+
+ if (false == mac_ctx->sap.SapDfsInfo.
+ is_dfs_cac_timer_running)
+ lim_send_beacon_ind(mac_ctx,
+ &mac_ctx->lim.gpSession[i]);
+ } else if (((mac_ctx->lim.gpSession[i].limSystemRole ==
+ eLIM_BT_AMP_AP_ROLE) ||
+ (mac_ctx->lim.gpSession[i].limSystemRole ==
+ eLIM_BT_AMP_STA_ROLE)) &&
+ (mac_ctx->lim.gpSession[i].statypeForBss ==
+ STA_ENTRY_SELF)){
+ sch_set_fixed_beacon_fields(mac_ctx,
+ &mac_ctx->lim.gpSession[i]);
+ }
+ }
+}
+
+/**
+ * lim_handle_heart_beat_failure_timeout - handle heart beat failure
+ * @mac_ctx: pointer to Global Mac Structure
+ *
+ * Function handle heart beat failure timeout
+ *
+ * Return: none
+ */
+void lim_handle_heart_beat_failure_timeout(tpAniSirGlobal mac_ctx)
+{
+ uint8_t i;
+ tpPESession psession_entry;
+ /*
+ * Probe response is not received after HB failure.
+ * This is handled by LMM sub module.
+ */
+ for (i = 0; i < mac_ctx->lim.maxBssId; i++) {
+ if (mac_ctx->lim.gpSession[i].valid != true)
+ continue;
+ psession_entry = &mac_ctx->lim.gpSession[i];
+ if (psession_entry->LimHBFailureStatus != true)
+ continue;
+ lim_log(mac_ctx, LOGE, FL("SME %d, MLME %d, HB-Count %d"),
+ psession_entry->limSmeState,
+ psession_entry->limMlmState,
+ psession_entry->LimRxedBeaconCntDuringHB);
+
+#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM
+ lim_diag_event_report(mac_ctx, WLAN_PE_DIAG_HB_FAILURE_TIMEOUT,
+ psession_entry, 0, 0);
+#endif
+ if ((psession_entry->limMlmState ==
+ eLIM_MLM_LINK_ESTABLISHED_STATE) &&
+ (psession_entry->limSmeState !=
+ eLIM_SME_WT_DISASSOC_STATE) &&
+ (psession_entry->limSmeState !=
+ eLIM_SME_WT_DEAUTH_STATE) &&
+ ((!LIM_IS_CONNECTION_ACTIVE(psession_entry)) ||
+ /*
+ * Disconnect even if we have not received a single
+ * beacon after connection.
+ */
+ (psession_entry->currentBssBeaconCnt == 0))) {
+ lim_log(mac_ctx, LOGE, FL("for session:%d "),
+ psession_entry->peSessionId);
+ /*
+ * AP did not respond to Probe Request.
+ * Tear down link with it.
+ */
+ lim_tear_down_link_with_ap(mac_ctx,
+ psession_entry->peSessionId,
+ eSIR_BEACON_MISSED);
+ mac_ctx->lim.gLimProbeFailureAfterHBfailedCnt++;
+ } else {
+ lim_log(mac_ctx, LOGE,
+ FL("Unexpected wt-probe-timeout in state "));
+ lim_print_mlm_state(mac_ctx, LOGE,
+ psession_entry->limMlmState);
+ }
+ }
+ /*
+ * Deactivate Timer ProbeAfterHB Timer -> As its a oneshot timer,
+ * need not deactivate the timer
+ * tx_timer_deactivate(&pMac->lim.limTimers.gLimProbeAfterHBTimer);
+ */
+}
+
+/*
+ * This function assumes there will not be more than one IBSS session active at any time.
+ */
+tpPESession lim_is_ibss_session_active(tpAniSirGlobal pMac)
+{
+ uint8_t i;
+
+ for (i = 0; i < pMac->lim.maxBssId; i++) {
+ if ((pMac->lim.gpSession[i].valid) &&
+ (pMac->lim.gpSession[i].limSystemRole ==
+ eLIM_STA_IN_IBSS_ROLE))
+ return &pMac->lim.gpSession[i];
+ }
+
+ return NULL;
+}
+
+tpPESession lim_is_ap_session_active(tpAniSirGlobal pMac)
+{
+ uint8_t i;
+
+ for (i = 0; i < pMac->lim.maxBssId; i++) {
+ if ((pMac->lim.gpSession[i].valid) &&
+ ((pMac->lim.gpSession[i].limSystemRole == eLIM_AP_ROLE) ||
+ (pMac->lim.gpSession[i].limSystemRole ==
+ eLIM_BT_AMP_AP_ROLE)))
+ return &pMac->lim.gpSession[i];
+ }
+
+ return NULL;
+}
+
+/**---------------------------------------------------------
+ \fn lim_handle_defer_msg_error
+ \brief handles error scenario, when the msg can not be deferred.
+ \param pMac
+ \param pLimMsg LIM msg, which could not be deferred.
+ \return void
+ -----------------------------------------------------------*/
+
+void lim_handle_defer_msg_error(tpAniSirGlobal pMac, tpSirMsgQ pLimMsg)
+{
+ if (SIR_BB_XPORT_MGMT_MSG == pLimMsg->type) {
+ cds_pkt_return_packet((cds_pkt_t *) pLimMsg->bodyptr);
+ pLimMsg->bodyptr = NULL;
+ } else if (pLimMsg->bodyptr != NULL) {
+ cdf_mem_free(pLimMsg->bodyptr);
+ pLimMsg->bodyptr = NULL;
+ }
+
+}
+
+#ifdef FEATURE_WLAN_DIAG_SUPPORT
+/**---------------------------------------------------------
+ \fn lim_diag_event_report
+ \brief This function reports Diag event
+ \param pMac
+ \param eventType
+ \param bssid
+ \param status
+ \param reasonCode
+ \return void
+ -----------------------------------------------------------*/
+void lim_diag_event_report(tpAniSirGlobal pMac, uint16_t eventType,
+ tpPESession pSessionEntry, uint16_t status,
+ uint16_t reasonCode)
+{
+ tSirMacAddr nullBssid = { 0, 0, 0, 0, 0, 0 };
+ WLAN_HOST_DIAG_EVENT_DEF(peEvent, host_event_wlan_pe_payload_type);
+
+ cdf_mem_set(&peEvent, sizeof(host_event_wlan_pe_payload_type), 0);
+
+ if (NULL == pSessionEntry) {
+ cdf_mem_copy(peEvent.bssid, nullBssid, sizeof(tSirMacAddr));
+ peEvent.sme_state = (uint16_t) pMac->lim.gLimSmeState;
+ peEvent.mlm_state = (uint16_t) pMac->lim.gLimMlmState;
+
+ } else {
+ cdf_mem_copy(peEvent.bssid, pSessionEntry->bssId,
+ sizeof(tSirMacAddr));
+ peEvent.sme_state = (uint16_t) pSessionEntry->limSmeState;
+ peEvent.mlm_state = (uint16_t) pSessionEntry->limMlmState;
+ }
+ peEvent.event_type = eventType;
+ peEvent.status = status;
+ peEvent.reason_code = reasonCode;
+
+ WLAN_HOST_DIAG_EVENT_REPORT(&peEvent, EVENT_WLAN_PE);
+ return;
+}
+
+#endif /* FEATURE_WLAN_DIAG_SUPPORT */
+
+uint8_t *lim_get_ie_ptr_new(tpAniSirGlobal pMac, uint8_t *pIes, int length,
+ uint8_t eid, eSizeOfLenField size_of_len_field)
+{
+ int left = length;
+ uint8_t *ptr = pIes;
+ uint8_t elem_id;
+ uint16_t elem_len;
+
+ while (left >= (size_of_len_field + 1)) {
+ elem_id = ptr[0];
+ if (size_of_len_field == TWO_BYTE) {
+ elem_len = ((uint16_t) ptr[1]) | (ptr[2] << 8);
+ } else {
+ elem_len = ptr[1];
+ }
+
+ left -= (size_of_len_field + 1);
+ if (elem_len > left) {
+ lim_log(pMac, LOGE,
+ FL
+ ("****Invalid IEs eid = %d elem_len=%d left=%d*****"),
+ eid, elem_len, left);
+ return NULL;
+ }
+ if (elem_id == eid) {
+ return ptr;
+ }
+
+ left -= elem_len;
+ ptr += (elem_len + (size_of_len_field + 1));
+ }
+ return NULL;
+}
+
+/* Returns length of P2P stream and Pointer ie passed to this function is filled with noa stream */
+
+uint8_t lim_build_p2p_ie(tpAniSirGlobal pMac, uint8_t *ie, uint8_t *data,
+ uint8_t ie_len)
+{
+ int length = 0;
+ uint8_t *ptr = ie;
+
+ ptr[length++] = SIR_MAC_EID_VENDOR;
+ ptr[length++] = ie_len + SIR_MAC_P2P_OUI_SIZE;
+ cdf_mem_copy(&ptr[length], SIR_MAC_P2P_OUI, SIR_MAC_P2P_OUI_SIZE);
+ cdf_mem_copy(&ptr[length + SIR_MAC_P2P_OUI_SIZE], data, ie_len);
+ return ie_len + SIR_P2P_IE_HEADER_LEN;
+}
+
+/* Returns length of NoA stream and Pointer pNoaStream passed to this function is filled with noa stream */
+
+uint8_t lim_get_noa_attr_stream_in_mult_p2p_ies(tpAniSirGlobal pMac,
+ uint8_t *noaStream, uint8_t noaLen,
+ uint8_t overFlowLen)
+{
+ uint8_t overFlowP2pStream[SIR_MAX_NOA_ATTR_LEN];
+
+ if ((noaLen <= (SIR_MAX_NOA_ATTR_LEN + SIR_P2P_IE_HEADER_LEN)) &&
+ (noaLen >= overFlowLen) && (overFlowLen <= SIR_MAX_NOA_ATTR_LEN)) {
+ cdf_mem_copy(overFlowP2pStream,
+ noaStream + noaLen - overFlowLen, overFlowLen);
+ noaStream[noaLen - overFlowLen] = SIR_MAC_EID_VENDOR;
+ noaStream[noaLen - overFlowLen + 1] =
+ overFlowLen + SIR_MAC_P2P_OUI_SIZE;
+ cdf_mem_copy(noaStream + noaLen - overFlowLen + 2,
+ SIR_MAC_P2P_OUI, SIR_MAC_P2P_OUI_SIZE);
+ cdf_mem_copy(noaStream + noaLen + 2 + SIR_MAC_P2P_OUI_SIZE -
+ overFlowLen, overFlowP2pStream, overFlowLen);
+ }
+
+ return noaLen + SIR_P2P_IE_HEADER_LEN;
+
+}
+
+/* Returns length of NoA stream and Pointer pNoaStream passed to this function is filled with noa stream */
+uint8_t lim_get_noa_attr_stream(tpAniSirGlobal pMac, uint8_t *pNoaStream,
+ tpPESession psessionEntry)
+{
+ uint8_t len = 0;
+
+ uint8_t *pBody = pNoaStream;
+
+ if ((psessionEntry != NULL) && (psessionEntry->valid) &&
+ (psessionEntry->pePersona == CDF_P2P_GO_MODE)) {
+ if ((!(psessionEntry->p2pGoPsUpdate.uNoa1Duration))
+ && (!(psessionEntry->p2pGoPsUpdate.uNoa2Duration))
+ && (!psessionEntry->p2pGoPsUpdate.oppPsFlag)
+ )
+ return 0; /* No NoA Descriptor then return 0 */
+
+ pBody[0] = SIR_P2P_NOA_ATTR;
+
+ pBody[3] = psessionEntry->p2pGoPsUpdate.index;
+ pBody[4] =
+ psessionEntry->p2pGoPsUpdate.ctWin | (psessionEntry->
+ p2pGoPsUpdate.
+ oppPsFlag << 7);
+ len = 5;
+ pBody += len;
+
+ if (psessionEntry->p2pGoPsUpdate.uNoa1Duration) {
+ *pBody = psessionEntry->p2pGoPsUpdate.uNoa1IntervalCnt;
+ pBody += 1;
+ len += 1;
+
+ *((uint32_t *) (pBody)) =
+ sir_swap_u32if_needed(psessionEntry->p2pGoPsUpdate.
+ uNoa1Duration);
+ pBody += sizeof(uint32_t);
+ len += 4;
+
+ *((uint32_t *) (pBody)) =
+ sir_swap_u32if_needed(psessionEntry->p2pGoPsUpdate.
+ uNoa1Interval);
+ pBody += sizeof(uint32_t);
+ len += 4;
+
+ *((uint32_t *) (pBody)) =
+ sir_swap_u32if_needed(psessionEntry->p2pGoPsUpdate.
+ uNoa1StartTime);
+ pBody += sizeof(uint32_t);
+ len += 4;
+
+ }
+
+ if (psessionEntry->p2pGoPsUpdate.uNoa2Duration) {
+ *pBody = psessionEntry->p2pGoPsUpdate.uNoa2IntervalCnt;
+ pBody += 1;
+ len += 1;
+
+ *((uint32_t *) (pBody)) =
+ sir_swap_u32if_needed(psessionEntry->p2pGoPsUpdate.
+ uNoa2Duration);
+ pBody += sizeof(uint32_t);
+ len += 4;
+
+ *((uint32_t *) (pBody)) =
+ sir_swap_u32if_needed(psessionEntry->p2pGoPsUpdate.
+ uNoa2Interval);
+ pBody += sizeof(uint32_t);
+ len += 4;
+
+ *((uint32_t *) (pBody)) =
+ sir_swap_u32if_needed(psessionEntry->p2pGoPsUpdate.
+ uNoa2StartTime);
+ pBody += sizeof(uint32_t);
+ len += 4;
+
+ }
+
+ pBody = pNoaStream + 1;
+ *((uint16_t *) (pBody)) = sir_swap_u16if_needed(len - 3); /*one byte for Attr and 2 bytes for length */
+
+ return len;
+
+ }
+ return 0;
+
+}
+
+void pe_set_resume_channel(tpAniSirGlobal pMac, uint16_t channel,
+ ePhyChanBondState phyCbState)
+{
+
+ pMac->lim.gResumeChannel = channel;
+ pMac->lim.gResumePhyCbState = phyCbState;
+}
+
+bool lim_is_noa_insert_reqd(tpAniSirGlobal pMac)
+{
+ uint8_t i;
+ for (i = 0; i < pMac->lim.maxBssId; i++) {
+ if (pMac->lim.gpSession[i].valid == true) {
+ if ((eLIM_AP_ROLE ==
+ pMac->lim.gpSession[i].limSystemRole)
+ && (CDF_P2P_GO_MODE ==
+ pMac->lim.gpSession[i].pePersona)
+ ) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+bool lim_isconnected_on_dfs_channel(uint8_t currentChannel)
+{
+ if (CHANNEL_STATE_DFS ==
+ cds_get_channel_state(currentChannel)) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+#ifdef WLAN_FEATURE_11W
+void lim_pmf_sa_query_timer_handler(void *pMacGlobal, uint32_t param)
+{
+ tpAniSirGlobal pMac = (tpAniSirGlobal) pMacGlobal;
+ tPmfSaQueryTimerId timerId;
+ tpPESession psessionEntry;
+ tpDphHashNode pSta;
+ uint32_t maxRetries;
+
+ lim_log(pMac, LOG1, FL("SA Query timer fires"));
+ timerId.value = param;
+
+ /* Check that SA Query is in progress */
+ psessionEntry = pe_find_session_by_session_id(pMac,
+ timerId.fields.sessionId);
+ if (psessionEntry == NULL) {
+ lim_log(pMac, LOGE,
+ FL("Session does not exist for given session ID %d"),
+ timerId.fields.sessionId);
+ return;
+ }
+ pSta = dph_get_hash_entry(pMac, timerId.fields.peerIdx,
+ &psessionEntry->dph.dphHashTable);
+ if (pSta == NULL) {
+ lim_log(pMac, LOGE,
+ FL("Entry does not exist for given peer index %d"),
+ timerId.fields.peerIdx);
+ return;
+ }
+ if (DPH_SA_QUERY_IN_PROGRESS != pSta->pmfSaQueryState)
+ return;
+
+ /* Increment the retry count, check if reached maximum */
+ if (wlan_cfg_get_int(pMac, WNI_CFG_PMF_SA_QUERY_MAX_RETRIES,
+ &maxRetries) != eSIR_SUCCESS) {
+ lim_log(pMac, LOGE,
+ FL
+ ("Could not retrieve PMF SA Query maximum retries value"));
+ pSta->pmfSaQueryState = DPH_SA_QUERY_NOT_IN_PROGRESS;
+ return;
+ }
+ pSta->pmfSaQueryRetryCount++;
+ if (pSta->pmfSaQueryRetryCount >= maxRetries) {
+ lim_log(pMac, LOGE, FL("SA Query timed out,Deleting STA"));
+ lim_print_mac_addr(pMac, pSta->staAddr, LOGE);
+ lim_send_disassoc_mgmt_frame(pMac,
+ eSIR_MAC_DISASSOC_DUE_TO_INACTIVITY_REASON,
+ pSta->staAddr, psessionEntry, false);
+ lim_trigger_sta_deletion(pMac, pSta, psessionEntry);
+ pSta->pmfSaQueryState = DPH_SA_QUERY_TIMED_OUT;
+ return;
+ }
+ /* Retry SA Query */
+ lim_send_sa_query_request_frame(pMac,
+ (uint8_t *) &(pSta->
+ pmfSaQueryCurrentTransId),
+ pSta->staAddr, psessionEntry);
+ pSta->pmfSaQueryCurrentTransId++;
+ lim_log(pMac, LOGE, FL("Starting SA Query retry %d"),
+ pSta->pmfSaQueryRetryCount);
+ if (tx_timer_activate(&pSta->pmfSaQueryTimer) != TX_SUCCESS) {
+ lim_log(pMac, LOGE, FL("PMF SA Query timer activation failed!"));
+ pSta->pmfSaQueryState = DPH_SA_QUERY_NOT_IN_PROGRESS;
+ }
+}
+#endif
+
+#ifdef WLAN_FEATURE_11AC
+bool lim_check_vht_op_mode_change(tpAniSirGlobal pMac, tpPESession psessionEntry,
+ uint8_t chanWidth, uint8_t staId,
+ uint8_t *peerMac)
+{
+ tUpdateVHTOpMode tempParam;
+
+ tempParam.opMode = chanWidth;
+ tempParam.staId = staId;
+ tempParam.smesessionId = psessionEntry->smeSessionId;
+ cdf_mem_copy(tempParam.peer_mac, peerMac, sizeof(tSirMacAddr));
+
+ lim_send_mode_update(pMac, &tempParam, psessionEntry);
+
+ return true;
+}
+
+bool lim_set_nss_change(tpAniSirGlobal pMac, tpPESession psessionEntry,
+ uint8_t rxNss, uint8_t staId, uint8_t *peerMac)
+{
+ tUpdateRxNss tempParam;
+
+ tempParam.rxNss = rxNss;
+ tempParam.staId = staId;
+ tempParam.smesessionId = psessionEntry->smeSessionId;
+ cdf_mem_copy(tempParam.peer_mac, peerMac, sizeof(tSirMacAddr));
+
+ lim_send_rx_nss_update(pMac, &tempParam, psessionEntry);
+
+ return true;
+}
+
+bool lim_check_membership_user_position(tpAniSirGlobal pMac,
+ tpPESession psessionEntry,
+ uint32_t membership, uint32_t userPosition,
+ uint8_t staId)
+{
+ tUpdateMembership tempParamMembership;
+ tUpdateUserPos tempParamUserPosition;
+
+ tempParamMembership.membership = membership;
+ tempParamMembership.staId = staId;
+ tempParamMembership.smesessionId = psessionEntry->smeSessionId;
+ cdf_mem_copy(tempParamMembership.peer_mac, psessionEntry->bssId,
+ sizeof(tSirMacAddr));
+
+ lim_set_membership(pMac, &tempParamMembership, psessionEntry);
+
+ tempParamUserPosition.userPos = userPosition;
+ tempParamUserPosition.staId = staId;
+ tempParamUserPosition.smesessionId = psessionEntry->smeSessionId;
+ cdf_mem_copy(tempParamUserPosition.peer_mac, psessionEntry->bssId,
+ sizeof(tSirMacAddr));
+
+ lim_set_user_pos(pMac, &tempParamUserPosition, psessionEntry);
+
+ return true;
+}
+#endif
+
+void lim_get_short_slot_from_phy_mode(tpAniSirGlobal pMac, tpPESession psessionEntry,
+ uint32_t phyMode, uint8_t *pShortSlotEnabled)
+{
+ uint8_t val = 0;
+
+ /* only 2.4G band should have short slot enable, rest it should be default */
+ if (phyMode == WNI_CFG_PHY_MODE_11G) {
+ /* short slot is default in all other modes */
+ if ((psessionEntry->pePersona == CDF_SAP_MODE) ||
+ (psessionEntry->pePersona == CDF_IBSS_MODE) ||
+ (psessionEntry->pePersona == CDF_P2P_GO_MODE)) {
+ val = true;
+ }
+ /* Program Polaris based on AP capability */
+ if (psessionEntry->limMlmState == eLIM_MLM_WT_JOIN_BEACON_STATE) {
+ /* Joining BSS. */
+ val =
+ SIR_MAC_GET_SHORT_SLOT_TIME(psessionEntry->
+ limCurrentBssCaps);
+ } else if (psessionEntry->limMlmState ==
+ eLIM_MLM_WT_REASSOC_RSP_STATE) {
+ /* Reassociating with AP. */
+ val =
+ SIR_MAC_GET_SHORT_SLOT_TIME(psessionEntry->
+ limReassocBssCaps);
+ }
+ } else {
+ /*
+ * 11B does not short slot and short slot is default
+ * for 11A mode. Hence, not need to set this bit
+ */
+ val = false;
+ }
+
+ lim_log(pMac, LOG1, FL("phyMode = %u shortslotsupported = %u"), phyMode,
+ val);
+ *pShortSlotEnabled = val;
+}
+
+#ifdef WLAN_FEATURE_11W
+/**
+ *
+ * \brief This function is called by various LIM modules to correctly set
+ * the Protected bit in the Frame Control Field of the 802.11 frame MAC header
+ *
+ *
+ * \param pMac Pointer to Global MAC structure
+ *
+ * \param psessionEntry Pointer to session corresponding to the connection
+ *
+ * \param peer Peer address of the STA to which the frame is to be sent
+ *
+ * \param pMacHdr Pointer to the frame MAC header
+ *
+ * \return nothing
+ *
+ *
+ */
+void
+lim_set_protected_bit(tpAniSirGlobal pMac,
+ tpPESession psessionEntry,
+ tSirMacAddr peer, tpSirMacMgmtHdr pMacHdr)
+{
+ uint16_t aid;
+ tpDphHashNode pStaDs;
+
+ if (LIM_IS_AP_ROLE(psessionEntry) ||
+ LIM_IS_BT_AMP_AP_ROLE(psessionEntry)) {
+
+ pStaDs = dph_lookup_hash_entry(pMac, peer, &aid,
+ &psessionEntry->dph.dphHashTable);
+ if (pStaDs != NULL) {
+ /* rmfenabled will be set at the time of addbss.
+ * but sometimes EAP auth fails and keys are not
+ * installed then if we send any management frame
+ * like deauth/disassoc with this bit set then
+ * firmware crashes. so check for keys are
+ * installed or not also before setting the bit
+ */
+ if (pStaDs->rmfEnabled && pStaDs->is_key_installed)
+ pMacHdr->fc.wep = 1;
+ }
+ } else if (psessionEntry->limRmfEnabled &&
+ psessionEntry->is_key_installed) {
+ pMacHdr->fc.wep = 1;
+ }
+} /*** end lim_set_protected_bit() ***/
+#endif
+
+void lim_set_ht_caps(tpAniSirGlobal p_mac, tpPESession p_session_entry,
+ uint8_t *p_ie_start, uint32_t num_bytes)
+{
+ uint8_t *p_ie = NULL;
+ tDot11fIEHTCaps dot11_ht_cap = {0,};
+
+ populate_dot11f_ht_caps(p_mac, p_session_entry, &dot11_ht_cap);
+ p_ie = lim_get_ie_ptr_new(p_mac, p_ie_start, num_bytes,
+ DOT11F_EID_HTCAPS, ONE_BYTE);
+ lim_log(p_mac, LOG2, FL("p_ie %p dot11_ht_cap.supportedMCSSet[0]=0x%x"),
+ p_ie, dot11_ht_cap.supportedMCSSet[0]);
+ if (p_ie) {
+ /* convert from unpacked to packed structure */
+ tHtCaps *p_ht_cap = (tHtCaps *) &p_ie[2];
+
+ p_ht_cap->advCodingCap = dot11_ht_cap.advCodingCap;
+ p_ht_cap->supportedChannelWidthSet =
+ dot11_ht_cap.supportedChannelWidthSet;
+ p_ht_cap->mimoPowerSave = dot11_ht_cap.mimoPowerSave;
+ p_ht_cap->greenField = dot11_ht_cap.greenField;
+ p_ht_cap->shortGI20MHz = dot11_ht_cap.shortGI20MHz;
+ p_ht_cap->shortGI40MHz = dot11_ht_cap.shortGI40MHz;
+ p_ht_cap->txSTBC = dot11_ht_cap.txSTBC;
+ p_ht_cap->rxSTBC = dot11_ht_cap.rxSTBC;
+ p_ht_cap->delayedBA = dot11_ht_cap.delayedBA;
+ p_ht_cap->maximalAMSDUsize = dot11_ht_cap.maximalAMSDUsize;
+ p_ht_cap->dsssCckMode40MHz = dot11_ht_cap.dsssCckMode40MHz;
+ p_ht_cap->psmp = dot11_ht_cap.psmp;
+ p_ht_cap->stbcControlFrame = dot11_ht_cap.stbcControlFrame;
+ p_ht_cap->lsigTXOPProtection = dot11_ht_cap.lsigTXOPProtection;
+ p_ht_cap->maxRxAMPDUFactor = dot11_ht_cap.maxRxAMPDUFactor;
+ p_ht_cap->mpduDensity = dot11_ht_cap.mpduDensity;
+ cdf_mem_copy((void *)p_ht_cap->supportedMCSSet,
+ (void *)(dot11_ht_cap.supportedMCSSet),
+ sizeof(p_ht_cap->supportedMCSSet));
+ p_ht_cap->pco = dot11_ht_cap.pco;
+ p_ht_cap->transitionTime = dot11_ht_cap.transitionTime;
+ p_ht_cap->mcsFeedback = dot11_ht_cap.mcsFeedback;
+ p_ht_cap->txBF = dot11_ht_cap.txBF;
+ p_ht_cap->rxStaggeredSounding =
+ dot11_ht_cap.rxStaggeredSounding;
+ p_ht_cap->txStaggeredSounding =
+ dot11_ht_cap.txStaggeredSounding;
+ p_ht_cap->rxZLF = dot11_ht_cap.rxZLF;
+ p_ht_cap->txZLF = dot11_ht_cap.txZLF;
+ p_ht_cap->implicitTxBF = dot11_ht_cap.implicitTxBF;
+ p_ht_cap->calibration = dot11_ht_cap.calibration;
+ p_ht_cap->explicitCSITxBF = dot11_ht_cap.explicitCSITxBF;
+ p_ht_cap->explicitUncompressedSteeringMatrix =
+ dot11_ht_cap.explicitUncompressedSteeringMatrix;
+ p_ht_cap->explicitBFCSIFeedback =
+ dot11_ht_cap.explicitBFCSIFeedback;
+ p_ht_cap->explicitUncompressedSteeringMatrixFeedback =
+ dot11_ht_cap.explicitUncompressedSteeringMatrixFeedback;
+ p_ht_cap->explicitCompressedSteeringMatrixFeedback =
+ dot11_ht_cap.explicitCompressedSteeringMatrixFeedback;
+ p_ht_cap->csiNumBFAntennae = dot11_ht_cap.csiNumBFAntennae;
+ p_ht_cap->uncompressedSteeringMatrixBFAntennae =
+ dot11_ht_cap.uncompressedSteeringMatrixBFAntennae;
+ p_ht_cap->compressedSteeringMatrixBFAntennae =
+ dot11_ht_cap.compressedSteeringMatrixBFAntennae;
+ p_ht_cap->antennaSelection = dot11_ht_cap.antennaSelection;
+ p_ht_cap->explicitCSIFeedbackTx =
+ dot11_ht_cap.explicitCSIFeedbackTx;
+ p_ht_cap->antennaIndicesFeedbackTx =
+ dot11_ht_cap.antennaIndicesFeedbackTx;
+ p_ht_cap->explicitCSIFeedback =
+ dot11_ht_cap.explicitCSIFeedback;
+ p_ht_cap->antennaIndicesFeedback =
+ dot11_ht_cap.antennaIndicesFeedback;
+ p_ht_cap->rxAS = dot11_ht_cap.rxAS;
+ p_ht_cap->txSoundingPPDUs = dot11_ht_cap.txSoundingPPDUs;
+ }
+}
+
+#ifdef WLAN_FEATURE_11AC
+void lim_set_vht_caps(tpAniSirGlobal p_mac, tpPESession p_session_entry,
+ uint8_t *p_ie_start, uint32_t num_bytes)
+{
+ uint8_t *p_ie = NULL;
+ tDot11fIEVHTCaps dot11_vht_cap;
+
+ populate_dot11f_vht_caps(p_mac, p_session_entry, &dot11_vht_cap);
+ p_ie = lim_get_ie_ptr_new(p_mac, p_ie_start, num_bytes,
+ DOT11F_EID_VHTCAPS, ONE_BYTE);
+
+ if (p_ie) {
+ tSirMacVHTCapabilityInfo *vht_cap =
+ (tSirMacVHTCapabilityInfo *) &p_ie[2];
+ tSirVhtMcsInfo *vht_mcs = (tSirVhtMcsInfo *) &p_ie[2 +
+ sizeof(tSirMacVHTCapabilityInfo)];
+
+ union {
+ uint16_t u_value;
+ tSirMacVHTRxSupDataRateInfo vht_rx_supp_rate;
+ tSirMacVHTTxSupDataRateInfo vht_tx_supp_rate;
+ } u_vht_data_rate_info;
+
+ vht_cap->maxMPDULen = dot11_vht_cap.maxMPDULen;
+ vht_cap->supportedChannelWidthSet =
+ dot11_vht_cap.supportedChannelWidthSet;
+ vht_cap->ldpcCodingCap = dot11_vht_cap.ldpcCodingCap;
+ vht_cap->shortGI80MHz = dot11_vht_cap.shortGI80MHz;
+ vht_cap->shortGI160and80plus80MHz =
+ dot11_vht_cap.shortGI160and80plus80MHz;
+ vht_cap->txSTBC = dot11_vht_cap.txSTBC;
+ vht_cap->rxSTBC = dot11_vht_cap.rxSTBC;
+ vht_cap->suBeamFormerCap = dot11_vht_cap.suBeamFormerCap;
+ vht_cap->suBeamformeeCap = dot11_vht_cap.suBeamformeeCap;
+ vht_cap->csnofBeamformerAntSup =
+ dot11_vht_cap.csnofBeamformerAntSup;
+ vht_cap->numSoundingDim = dot11_vht_cap.numSoundingDim;
+ vht_cap->muBeamformerCap = dot11_vht_cap.muBeamformerCap;
+ vht_cap->muBeamformeeCap = dot11_vht_cap.muBeamformeeCap;
+ vht_cap->vhtTXOPPS = dot11_vht_cap.vhtTXOPPS;
+ vht_cap->htcVHTCap = dot11_vht_cap.htcVHTCap;
+ vht_cap->maxAMPDULenExp = dot11_vht_cap.maxAMPDULenExp;
+ vht_cap->vhtLinkAdaptCap = dot11_vht_cap.vhtLinkAdaptCap;
+ vht_cap->rxAntPattern = dot11_vht_cap.rxAntPattern;
+ vht_cap->txAntPattern = dot11_vht_cap.txAntPattern;
+ vht_cap->reserved1 = dot11_vht_cap.reserved1;
+
+ /* Populate VHT MCS Information */
+ vht_mcs->rxMcsMap = dot11_vht_cap.rxMCSMap;
+ u_vht_data_rate_info.vht_rx_supp_rate.rxSupDataRate =
+ dot11_vht_cap.rxHighSupDataRate;
+ u_vht_data_rate_info.vht_rx_supp_rate.reserved =
+ dot11_vht_cap.reserved2;
+ vht_mcs->rxHighest = u_vht_data_rate_info.u_value;
+
+ vht_mcs->txMcsMap = dot11_vht_cap.txMCSMap;
+ u_vht_data_rate_info.vht_tx_supp_rate.txSupDataRate =
+ dot11_vht_cap.txSupDataRate;
+ u_vht_data_rate_info.vht_tx_supp_rate.reserved =
+ dot11_vht_cap.reserved3;
+ vht_mcs->txHighest = u_vht_data_rate_info.u_value;
+ }
+}
+#endif /* WLAN_FEATURE_11AC */
+
+/**
+ * lim_validate_received_frame_a1_addr() - To validate received frame's A1 addr
+ * @mac_ctx: pointer to mac context
+ * @a1: received frame's a1 address which is nothing but our self address
+ * @session: PE session pointer
+ *
+ * This routine will validate, A1 addres of the received frame
+ *
+ * Return: true or false
+ */
+bool lim_validate_received_frame_a1_addr(tpAniSirGlobal mac_ctx,
+ tSirMacAddr a1, tpPESession session)
+{
+ if (mac_ctx == NULL || session == NULL) {
+ CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_INFO,
+ "mac or session context is null");
+ /* let main routine handle it */
+ return true;
+ }
+ if (lim_is_group_addr(a1) || lim_is_addr_bc(a1)) {
+ /* just for fail safe, don't handle MC/BC a1 in this routine */
+ return true;
+ }
+ if (!cdf_mem_compare(a1, session->selfMacAddr, 6)) {
+ lim_log(mac_ctx, LOGE,
+ FL("Invalid A1 address in received frame"));
+ return false;
+ }
+ return true;
+}
+
+/**
+ * lim_check_and_reset_protection_params() - reset protection related parameters
+ *
+ * @mac_ctx: pointer to global mac structure
+ *
+ * resets protection related global parameters if the pe active session count
+ * is zero.
+ *
+ * Return: None
+ */
+void lim_check_and_reset_protection_params(tpAniSirGlobal mac_ctx)
+{
+ if (!pe_get_active_session_count(mac_ctx)) {
+ cdf_mem_zero(&mac_ctx->lim.gLimOverlap11gParams,
+ sizeof(mac_ctx->lim.gLimOverlap11gParams));
+ cdf_mem_zero(&mac_ctx->lim.gLimOverlap11aParams,
+ sizeof(mac_ctx->lim.gLimOverlap11aParams));
+ cdf_mem_zero(&mac_ctx->lim.gLimOverlapHt20Params,
+ sizeof(mac_ctx->lim.gLimOverlapHt20Params));
+ cdf_mem_zero(&mac_ctx->lim.gLimOverlapNonGfParams,
+ sizeof(mac_ctx->lim.gLimOverlapNonGfParams));
+
+ mac_ctx->lim.gHTOperMode = eSIR_HT_OP_MODE_PURE;
+ }
+}
+
+/**
+ * lim_set_stads_rtt_cap() - update station node RTT capability
+ * @sta_ds: Station hash node
+ * @ext_cap: Pointer to extended capability
+ * @mac_ctx: global MAC context
+ *
+ * This funciton update hash node's RTT capability based on received
+ * Extended capability IE.
+ *
+ * Return: None
+ */
+void lim_set_stads_rtt_cap(tpDphHashNode sta_ds, struct s_ext_cap *ext_cap,
+ tpAniSirGlobal mac_ctx)
+{
+ sta_ds->timingMeasCap = 0;
+ sta_ds->timingMeasCap |= (ext_cap->timing_meas) ?
+ RTT_TIMING_MEAS_CAPABILITY :
+ RTT_INVALID;
+ sta_ds->timingMeasCap |= (ext_cap->fine_time_meas_initiator) ?
+ RTT_FINE_TIME_MEAS_INITIATOR_CAPABILITY :
+ RTT_INVALID;
+ sta_ds->timingMeasCap |= (ext_cap->fine_time_meas_responder) ?
+ RTT_FINE_TIME_MEAS_RESPONDER_CAPABILITY :
+ RTT_INVALID;
+
+ lim_log(mac_ctx, LOG1,
+ FL("ExtCap present, timingMeas: %d Initiator: %d Responder: %d"),
+ ext_cap->timing_meas, ext_cap->fine_time_meas_initiator,
+ ext_cap->fine_time_meas_responder);
+}
+
+/**
+ * lim_send_ext_cap_ie() - send ext cap IE to FW
+ * @mac_ctx: global MAC context
+ * @session_entry: PE session
+ * @extra_extcap: extracted ext cap
+ * @merge: merge extra ext cap
+ *
+ * This function is invoked after VDEV is created to update firmware
+ * about the extended capabilities that the corresponding VDEV is capable
+ * of. Since STA/SAP can have different Extended capabilities set, this function
+ * is called per vdev creation.
+ *
+ * Return: CDF_STATUS
+ */
+CDF_STATUS lim_send_ext_cap_ie(tpAniSirGlobal mac_ctx,
+ uint32_t session_id,
+ tDot11fIEExtCap *extra_extcap, bool merge)
+{
+ tDot11fIEExtCap ext_cap_data = {0};
+ uint32_t dot11mode, num_bytes;
+ bool vht_enabled = false;
+ struct vdev_ie_info *vdev_ie;
+ cds_msg_t msg = {0};
+ tSirRetStatus status;
+ uint8_t *temp, i;
+
+ wlan_cfg_get_int(mac_ctx, WNI_CFG_DOT11_MODE, &dot11mode);
+ if (IS_DOT11_MODE_VHT(dot11mode))
+ vht_enabled = true;
+
+ status = populate_dot11f_ext_cap(mac_ctx, vht_enabled, &ext_cap_data,
+ NULL);
+ if (eSIR_SUCCESS != status) {
+ lim_log(mac_ctx, LOGE, FL("Failed to populate ext cap IE"));
+ return CDF_STATUS_E_FAILURE;
+ }
+
+ num_bytes = ext_cap_data.num_bytes;
+
+ if (merge && NULL != extra_extcap && extra_extcap->num_bytes > 0) {
+ if (extra_extcap->num_bytes > ext_cap_data.num_bytes)
+ num_bytes = extra_extcap->num_bytes;
+ lim_merge_extcap_struct(&ext_cap_data, extra_extcap);
+ }
+
+ /* Allocate memory for the WMI request, and copy the parameter */
+ vdev_ie = cdf_mem_malloc(sizeof(*vdev_ie) + num_bytes);
+ if (!vdev_ie) {
+ lim_log(mac_ctx, LOGE, FL("Failed to allocate memory"));
+ return CDF_STATUS_E_NOMEM;
+ }
+
+ vdev_ie->vdev_id = session_id;
+ vdev_ie->ie_id = DOT11F_EID_EXTCAP;
+ vdev_ie->length = num_bytes;
+
+ lim_log(mac_ctx, LOG1, FL("vdev %d ieid %d len %d"), session_id,
+ DOT11F_EID_EXTCAP, num_bytes);
+ temp = ext_cap_data.bytes;
+ for (i = 0; i < num_bytes; i++, temp++)
+ lim_log(mac_ctx, LOG1, FL("%d byte is %02x"), i+1, *temp);
+
+ vdev_ie->data = (uint8_t *)vdev_ie + sizeof(*vdev_ie);
+ cdf_mem_copy(vdev_ie->data, ext_cap_data.bytes, num_bytes);
+
+ msg.type = WMA_SET_IE_INFO;
+ msg.bodyptr = vdev_ie;
+ msg.reserved = 0;
+
+ if (CDF_STATUS_SUCCESS !=
+ cds_mq_post_message(CDF_MODULE_ID_WMA, &msg)) {
+ lim_log(mac_ctx, LOGE,
+ FL("Not able to post WMA_SET_IE_INFO to WDA"));
+ cdf_mem_free(vdev_ie);
+ return CDF_STATUS_E_FAILURE;
+ }
+
+ return CDF_STATUS_SUCCESS;
+}
+
+/**
+ * lim_strip_extcap_ie() - strip extended capability IE from IE buffer
+ * @mac_ctx: global MAC context
+ * @addn_ie: Additional IE buffer
+ * @addn_ielen: Length of additional IE
+ * @extracted_ie: if not NULL, copy the stripped IE to this buffer
+ *
+ * This utility function is used to strip of the extended capability IE present
+ * in additional IE buffer.
+ *
+ * Return: tSirRetStatus
+ */
+tSirRetStatus lim_strip_extcap_ie(tpAniSirGlobal mac_ctx,
+ uint8_t *addn_ie, uint16_t *addn_ielen, uint8_t *extracted_ie)
+{
+ uint8_t *tempbuf = NULL;
+ uint16_t templen = 0;
+ int left = *addn_ielen;
+ uint8_t *ptr = addn_ie;
+ uint8_t elem_id, elem_len;
+
+ if (NULL == addn_ie) {
+ lim_log(mac_ctx, LOG1, FL("NULL addn_ie pointer"));
+ return eSIR_IGNORE_IE;
+ }
+
+ tempbuf = cdf_mem_malloc(left);
+ if (NULL == tempbuf) {
+ lim_log(mac_ctx, LOGE, FL("Unable to allocate memory"));
+ return eSIR_MEM_ALLOC_FAILED;
+ }
+
+ while (left >= 2) {
+ elem_id = ptr[0];
+ elem_len = ptr[1];
+ left -= 2;
+ if (elem_len > left) {
+ lim_log(mac_ctx, LOGE,
+ FL("Invalid IEs eid = %d elem_len=%d left=%d"),
+ elem_id, elem_len, left);
+ cdf_mem_free(tempbuf);
+ return eSIR_FAILURE;
+ }
+ if (!(DOT11F_EID_EXTCAP == elem_id)) {
+ cdf_mem_copy(tempbuf + templen, &ptr[0], elem_len + 2);
+ templen += (elem_len + 2);
+ } else {
+ if (NULL != extracted_ie) {
+ cdf_mem_set(extracted_ie,
+ DOT11F_IE_EXTCAP_MAX_LEN + 2, 0);
+ if (elem_len <= DOT11F_IE_EXTCAP_MAX_LEN)
+ cdf_mem_copy(extracted_ie, &ptr[0],
+ elem_len + 2);
+ }
+ }
+ left -= elem_len;
+ ptr += (elem_len + 2);
+ }
+ cdf_mem_copy(addn_ie, tempbuf, templen);
+
+ *addn_ielen = templen;
+ cdf_mem_free(tempbuf);
+
+ return eSIR_SUCCESS;
+}
+
+/**
+ * lim_update_extcap_struct() - poputlate the dot11f structure
+ * @mac_ctx: global MAC context
+ * @buf: extracted IE buffer
+ * @dst: extended capability IE structure to be updated
+ *
+ * This function is used to update the extended capability structure
+ * with @buf.
+ *
+ * Return: None
+ */
+void lim_update_extcap_struct(tpAniSirGlobal mac_ctx,
+ uint8_t *buf, tDot11fIEExtCap *dst)
+{
+ uint8_t out[DOT11F_IE_EXTCAP_MAX_LEN];
+
+ if (NULL == buf) {
+ lim_log(mac_ctx, LOGE, FL("Invalid Buffer Address"));
+ return;
+ }
+
+ if (NULL == dst) {
+ lim_log(mac_ctx, LOGE, FL("NULL dst pointer"));
+ return;
+ }
+
+ if (DOT11F_EID_EXTCAP != buf[0] || buf[1] > DOT11F_IE_EXTCAP_MAX_LEN) {
+ lim_log(mac_ctx, LOG1, FL("Invalid IEs eid = %d elem_len=%d "),
+ buf[0], buf[1]);
+ return;
+ }
+
+ cdf_mem_set((uint8_t *)&out[0], DOT11F_IE_EXTCAP_MAX_LEN, 0);
+ cdf_mem_copy(&out[0], &buf[2], DOT11F_IE_EXTCAP_MAX_LEN);
+
+ if (DOT11F_PARSE_SUCCESS != dot11f_unpack_ie_ext_cap(mac_ctx, &out[0],
+ DOT11F_IE_EXTCAP_MAX_LEN, dst))
+ lim_log(mac_ctx, LOGE, FL("dot11f_unpack Parse Error "));
+}
+
+/**
+ * lim_strip_extcap_update_struct - strip extended capability IE and populate
+ * the dot11f structure
+ * @mac_ctx: global MAC context
+ * @addn_ie: Additional IE buffer
+ * @addn_ielen: Length of additional IE
+ * @dst: extended capability IE structure to be updated
+ *
+ * This function is used to strip extended capability IE from IE buffer and
+ * update the passed structure.
+ *
+ * Return: tSirRetStatus
+ */
+tSirRetStatus lim_strip_extcap_update_struct(tpAniSirGlobal mac_ctx,
+ uint8_t *addn_ie, uint16_t *addn_ielen, tDot11fIEExtCap *dst)
+{
+ uint8_t extracted_buff[DOT11F_IE_EXTCAP_MAX_LEN + 2];
+ tSirRetStatus status;
+
+ cdf_mem_set((uint8_t *)&extracted_buff[0], DOT11F_IE_EXTCAP_MAX_LEN + 2,
+ 0);
+ status = lim_strip_extcap_ie(mac_ctx, addn_ie, addn_ielen,
+ extracted_buff);
+ if (eSIR_SUCCESS != status) {
+ lim_log(mac_ctx, LOG1,
+ FL("Failed to strip extcap IE status = (%d)."), status);
+ return status;
+ }
+
+ /* update the extracted ExtCap to struct*/
+ lim_update_extcap_struct(mac_ctx, extracted_buff, dst);
+ return status;
+}
+
+/**
+ * lim_merge_extcap_struct() - merge extended capabilities info
+ * @dst: destination extended capabilities
+ * @src: source extended capabilities
+ *
+ * This function is used to take @src info and merge it with @dst
+ * extended capabilities info.
+ *
+ * Return: None
+ */
+void lim_merge_extcap_struct(tDot11fIEExtCap *dst,
+ tDot11fIEExtCap *src)
+{
+ uint8_t *tempdst = (uint8_t *)dst->bytes;
+ uint8_t *tempsrc = (uint8_t *)src->bytes;
+ uint8_t structlen = member_size(tDot11fIEExtCap, bytes);
+
+ while (tempdst && tempsrc && structlen--) {
+ *tempdst |= *tempsrc;
+ tempdst++;
+ tempsrc++;
+ }
+}
+
diff --git a/core/mac/src/pe/lim/lim_utils.h b/core/mac/src/pe/lim/lim_utils.h
new file mode 100644
index 0000000..76b000c
--- /dev/null
+++ b/core/mac/src/pe/lim/lim_utils.h
@@ -0,0 +1,591 @@
+/*
+ * Copyright (c) 2012-2015 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_utils.h contains the utility definitions
+ * LIM uses.
+ * Author: Chandra Modumudi
+ * Date: 02/13/02
+ * History:-
+ * Date Modified by Modification Information
+ * --------------------------------------------------------------------
+ */
+#ifndef __LIM_UTILS_H
+#define __LIM_UTILS_H
+
+#include "sir_api.h"
+#include "sir_debug.h"
+#include "cfg_api.h"
+
+#include "lim_types.h"
+#include "lim_scan_result_utils.h"
+#include "lim_timer_utils.h"
+#include "lim_trace.h"
+typedef enum {
+ ONE_BYTE = 1,
+ TWO_BYTE = 2
+} eSizeOfLenField;
+
+#define MIN_TX_PWR_CAP 8
+#define MAX_TX_PWR_CAP 22
+
+#define LIM_STA_ID_MASK 0x00FF
+#define LIM_AID_MASK 0xC000
+#define LIM_SPECTRUM_MANAGEMENT_BIT_MASK 0x0100
+#define LIM_RRM_BIT_MASK 0x1000
+#define LIM_SHORT_PREAMBLE_BIT_MASK 0x0020
+#define LIM_IMMEDIATE_BLOCK_ACK_MASK 0x8000
+#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_ESE) || defined(FEATURE_WLAN_LFR)
+#define LIM_MAX_REASSOC_RETRY_LIMIT 2
+#endif
+
+/* classifier ID is coded as 0-3: tsid, 4-5:direction */
+#define LIM_MAKE_CLSID(tsid, dir) (((tsid) & 0x0F) | (((dir) & 0x03) << 4))
+
+#define VHT_MCS_3x3_MASK 0x30
+#define VHT_MCS_2x2_MASK 0x0C
+
+#ifdef WLAN_FEATURE_11W
+typedef union uPmfSaQueryTimerId {
+ struct {
+ uint8_t sessionId;
+ uint16_t peerIdx;
+ } fields;
+ uint32_t value;
+} tPmfSaQueryTimerId, *tpPmfSaQueryTimerId;
+#endif
+
+/* LIM utility functions */
+void limGetBssidFromPkt(tpAniSirGlobal, uint8_t *, uint8_t *, uint32_t *);
+char *lim_dot11_reason_str(uint16_t reasonCode);
+char *lim_mlm_state_str(tLimMlmStates state);
+char *lim_sme_state_str(tLimSmeStates state);
+char *lim_msg_str(uint32_t msgType);
+char *lim_result_code_str(tSirResultCodes resultCode);
+char *lim_dot11_mode_str(tpAniSirGlobal pMac, uint8_t dot11Mode);
+void lim_print_mlm_state(tpAniSirGlobal pMac, uint16_t logLevel,
+ tLimMlmStates state);
+void lim_print_sme_state(tpAniSirGlobal pMac, uint16_t logLevel,
+ tLimSmeStates state);
+void lim_print_msg_name(tpAniSirGlobal pMac, uint16_t logLevel, uint32_t msgType);
+
+#if defined FEATURE_WLAN_ESE || defined WLAN_FEATURE_VOWIFI
+extern tSirRetStatus lim_send_set_max_tx_power_req(tpAniSirGlobal pMac,
+ tPowerdBm txPower,
+ tpPESession pSessionEntry);
+extern uint8_t lim_get_max_tx_power(tPowerdBm regMax, tPowerdBm apTxPower,
+ uint8_t iniTxPower);
+#endif
+uint8_t lim_is_addr_bc(tSirMacAddr);
+uint8_t lim_is_group_addr(tSirMacAddr);
+
+/* check for type of scan allowed */
+uint8_t lim_active_scan_allowed(tpAniSirGlobal, uint8_t);
+
+/* AID pool management functions */
+void lim_init_peer_idxpool(tpAniSirGlobal, tpPESession);
+uint16_t lim_assign_peer_idx(tpAniSirGlobal, tpPESession);
+
+void lim_enable_overlap11g_protection(tpAniSirGlobal pMac,
+ tpUpdateBeaconParams pBeaconParams,
+ tpSirMacMgmtHdr pMh,
+ tpPESession psessionEntry);
+void lim_update_overlap_sta_param(tpAniSirGlobal pMac, tSirMacAddr bssId,
+ tpLimProtStaParams pStaParams);
+void lim_update_short_preamble(tpAniSirGlobal pMac, tSirMacAddr peerMacAddr,
+ tpUpdateBeaconParams pBeaconParams,
+ tpPESession psessionEntry);
+void lim_update_short_slot_time(tpAniSirGlobal pMac, tSirMacAddr peerMacAddr,
+ tpUpdateBeaconParams pBeaconParams,
+ tpPESession psessionEntry);
+
+/*
+ * The below 'product' check tobe removed if 'Association' is
+ * allowed in IBSS.
+ */
+void lim_release_peer_idx(tpAniSirGlobal, uint16_t, tpPESession);
+
+void lim_decide_ap_protection(tpAniSirGlobal pMac, tSirMacAddr peerMacAddr,
+ tpUpdateBeaconParams pBeaconParams, tpPESession);
+void lim_decide_ap_protection_on_delete(tpAniSirGlobal pMac,
+ tpDphHashNode pStaDs,
+ tpUpdateBeaconParams pBeaconParams,
+ tpPESession psessionEntry);
+
+extern tSirRetStatus lim_update_11a_protection(tpAniSirGlobal pMac,
+ uint8_t enable,
+ uint8_t overlap,
+ tpUpdateBeaconParams pBeaconParams,
+ tpPESession);
+extern tSirRetStatus lim_enable11g_protection(tpAniSirGlobal pMac,
+ uint8_t enable,
+ uint8_t overlap,
+ tpUpdateBeaconParams pBeaconParams,
+ tpPESession psessionEntry);
+extern tSirRetStatus lim_enable_ht_protection_from11g(tpAniSirGlobal pMac,
+ uint8_t enable,
+ uint8_t overlap,
+ tpUpdateBeaconParams
+ pBeaconParams,
+ tpPESession psessionEntry);
+extern tSirRetStatus lim_enable_ht20_protection(tpAniSirGlobal pMac,
+ uint8_t enable, uint8_t overlap,
+ tpUpdateBeaconParams pBeaconParams,
+ tpPESession sessionEntry);
+extern tSirRetStatus lim_enable_ht_non_gf_protection(tpAniSirGlobal pMac,
+ uint8_t enable, uint8_t overlap,
+ tpUpdateBeaconParams
+ pBeaconParams, tpPESession);
+extern tSirRetStatus lim_enable_ht_rifs_protection(tpAniSirGlobal pMac,
+ uint8_t enable, uint8_t overlap,
+ tpUpdateBeaconParams
+ pBeaconParams,
+ tpPESession psessionEntry);
+extern tSirRetStatus lim_enable_ht_lsig_txop_protection(tpAniSirGlobal pMac,
+ uint8_t enable,
+ uint8_t overlap,
+ tpUpdateBeaconParams
+ pBeaconParams, tpPESession);
+extern tSirRetStatus lim_enable_short_preamble(tpAniSirGlobal pMac,
+ uint8_t enable,
+ tpUpdateBeaconParams pBeaconParams,
+ tpPESession psessionEntry);
+extern tSirRetStatus lim_enable_ht_obss_protection(tpAniSirGlobal pMac,
+ uint8_t enable, uint8_t overlap,
+ tpUpdateBeaconParams
+ pBeaconParams, tpPESession);
+void lim_decide_sta_protection(tpAniSirGlobal pMac,
+ tpSchBeaconStruct pBeaconStruct,
+ tpUpdateBeaconParams pBeaconParams,
+ tpPESession psessionEntry);
+void lim_decide_sta_protection_on_assoc(tpAniSirGlobal pMac,
+ tpSchBeaconStruct pBeaconStruct,
+ tpPESession psessionEntry);
+void lim_update_sta_run_time_ht_switch_chnl_params(tpAniSirGlobal pMac,
+ tDot11fIEHTInfo *pHTInfo,
+ uint8_t bssIdx,
+ tpPESession psessionEntry);
+/* Print MAC address utility function */
+void lim_print_mac_addr(tpAniSirGlobal, tSirMacAddr, uint8_t);
+
+/* Deferred Message Queue read/write */
+uint8_t lim_write_deferred_msg_q(tpAniSirGlobal pMac, tpSirMsgQ limMsg);
+tSirMsgQ *lim_read_deferred_msg_q(tpAniSirGlobal pMac);
+void lim_handle_defer_msg_error(tpAniSirGlobal pMac, tpSirMsgQ pLimMsg);
+
+/* Deferred Message Queue Reset */
+void lim_reset_deferred_msg_q(tpAniSirGlobal pMac);
+
+tSirRetStatus lim_sys_process_mmh_msg_api(tpAniSirGlobal, tSirMsgQ *, uint8_t);
+
+void lim_handle_update_olbc_cache(tpAniSirGlobal pMac);
+
+uint8_t lim_is_null_ssid(tSirMacSSid *pSsid);
+
+/* 11h Support */
+void lim_stop_tx_and_switch_channel(tpAniSirGlobal pMac, uint8_t sessionId);
+void lim_process_channel_switch_timeout(tpAniSirGlobal);
+tSirRetStatus lim_start_channel_switch(tpAniSirGlobal pMac,
+ tpPESession psessionEntry);
+void lim_update_channel_switch(tpAniSirGlobal, tpSirProbeRespBeacon,
+ tpPESession psessionEntry);
+void lim_process_quiet_timeout(tpAniSirGlobal);
+void lim_process_quiet_bss_timeout(tpAniSirGlobal);
+
+void lim_start_quiet_timer(tpAniSirGlobal pMac, uint8_t sessionId);
+void lim_switch_primary_channel(tpAniSirGlobal, uint8_t, tpPESession);
+void lim_switch_primary_secondary_channel(tpAniSirGlobal pMac,
+ tpPESession psessionEntry,
+ uint8_t newChannel,
+ uint8_t ch_center_freq_seg0,
+ uint8_t ch_center_freq_seg1,
+ phy_ch_width ch_width);
+void limUpdateStaRunTimeHTSwtichChnlParams(tpAniSirGlobal pMac,
+ tDot11fIEHTInfo *pRcvdHTInfo,
+ uint8_t bssIdx);
+void lim_update_sta_run_time_ht_capability(tpAniSirGlobal pMac,
+ tDot11fIEHTCaps *pHTCaps);
+void lim_update_sta_run_time_ht_info(struct sAniSirGlobal *pMac,
+ tDot11fIEHTInfo *pRcvdHTInfo,
+ tpPESession psessionEntry);
+void lim_cancel_dot11h_channel_switch(tpAniSirGlobal pMac,
+ tpPESession psessionEntry);
+void lim_cancel_dot11h_quiet(tpAniSirGlobal pMac, tpPESession psessionEntry);
+tAniBool lim_is_channel_valid_for_channel_switch(tpAniSirGlobal pMac,
+ uint8_t channel);
+void lim_frame_transmission_control(tpAniSirGlobal pMac, tLimQuietTxMode type,
+ tLimControlTx mode);
+tSirRetStatus lim_restore_pre_channel_switch_state(tpAniSirGlobal pMac,
+ tpPESession psessionEntry);
+tSirRetStatus lim_restore_pre_quiet_state(tpAniSirGlobal pMac,
+ tpPESession psessionEntry);
+
+void lim_prepare_for11h_channel_switch(tpAniSirGlobal pMac,
+ tpPESession psessionEntry);
+void lim_switch_channel_cback(tpAniSirGlobal pMac, CDF_STATUS status,
+ uint32_t *data, tpPESession psessionEntry);
+
+static inline tSirRFBand lim_get_rf_band(uint8_t channel)
+{
+ if ((channel >= SIR_11A_CHANNEL_BEGIN) &&
+ (channel <= SIR_11A_CHANNEL_END))
+ return SIR_BAND_5_GHZ;
+
+ if ((channel >= SIR_11B_CHANNEL_BEGIN) &&
+ (channel <= SIR_11B_CHANNEL_END))
+ return SIR_BAND_2_4_GHZ;
+
+ return SIR_BAND_UNKNOWN;
+}
+
+static inline tSirRetStatus
+lim_get_mgmt_staid(tpAniSirGlobal pMac, uint16_t *staid,
+ tpPESession psessionEntry)
+{
+ if (LIM_IS_AP_ROLE(psessionEntry))
+ *staid = 1;
+ else if (LIM_IS_STA_ROLE(psessionEntry))
+ *staid = 0;
+ else
+ return eSIR_FAILURE;
+
+ return eSIR_SUCCESS;
+}
+
+static inline uint8_t lim_is_system_in_set_mimops_state(tpAniSirGlobal pMac)
+{
+ if (pMac->lim.gLimMlmState == eLIM_MLM_WT_SET_MIMOPS_STATE)
+ return true;
+ return false;
+}
+
+static inline uint8_t
+is_entering_mimo_ps(tSirMacHTMIMOPowerSaveState curState,
+ tSirMacHTMIMOPowerSaveState newState)
+{
+ if (curState == eSIR_HT_MIMO_PS_NO_LIMIT &&
+ (newState == eSIR_HT_MIMO_PS_DYNAMIC
+ || newState == eSIR_HT_MIMO_PS_STATIC))
+ return true;
+ return false;
+}
+
+static inline int lim_select_cb_mode(tDphHashNode *pStaDs,
+ tpPESession psessionEntry, uint8_t channel,
+ uint8_t chan_bw)
+{
+ if (pStaDs->mlmStaContext.vhtCapability && chan_bw) {
+ if (channel == 36 || channel == 52 || channel == 100 ||
+ channel == 116 || channel == 149) {
+ return PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW - 1;
+ } else if (channel == 40 || channel == 56 || channel == 104 ||
+ channel == 120 || channel == 153) {
+ return PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW - 1;
+ } else if (channel == 44 || channel == 60 || channel == 108 ||
+ channel == 124 || channel == 157) {
+ return PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH - 1;
+ } else if (channel == 48 || channel == 64 || channel == 112 ||
+ channel == 128 || channel == 161) {
+ return PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH - 1;
+ } else if (channel == 165) {
+ return PHY_SINGLE_CHANNEL_CENTERED;
+ }
+ } else if (pStaDs->mlmStaContext.htCapability) {
+ if (channel == 40 || channel == 48 || channel == 56 ||
+ channel == 64 || channel == 104 || channel == 112 ||
+ channel == 120 || channel == 128 || channel == 136 ||
+ channel == 144 || channel == 153 || channel == 161) {
+ return PHY_DOUBLE_CHANNEL_LOW_PRIMARY;
+ } else if (channel == 36 || channel == 44 || channel == 52 ||
+ channel == 60 || channel == 100 ||
+ channel == 108 || channel == 116 ||
+ channel == 124 || channel == 132 ||
+ channel == 140 || channel == 149 ||
+ channel == 157) {
+ return PHY_DOUBLE_CHANNEL_HIGH_PRIMARY;
+ } else if (channel == 165) {
+ return PHY_SINGLE_CHANNEL_CENTERED;
+ }
+ }
+ return PHY_SINGLE_CHANNEL_CENTERED;
+}
+
+/* ANI peer station count management and associated actions */
+void lim_util_count_sta_add(tpAniSirGlobal pMac, tpDphHashNode pSta,
+ tpPESession psessionEntry);
+void lim_util_count_sta_del(tpAniSirGlobal pMac, tpDphHashNode pSta,
+ tpPESession psessionEntry);
+
+uint8_t lim_get_ht_capability(tpAniSirGlobal, uint32_t, tpPESession);
+void lim_tx_complete(tHalHandle hHal, void *pData, bool free);
+
+/**
+ * This function will be registered with HAL for callback when TSPEC inactivity
+ * timer fires.
+ */
+
+void lim_process_del_ts_ind(tpAniSirGlobal pMac, tpSirMsgQ limMsg);
+tSirRetStatus lim_process_hal_ind_messages(tpAniSirGlobal pMac, uint32_t mesgId,
+ void *mesgParam);
+tSirRetStatus lim_validate_delts_req(tpAniSirGlobal pMac,
+ tpSirDeltsReq pDeltsReq,
+ tSirMacAddr peerMacAddr,
+ tpPESession psessionEntry);
+
+/* callback function registration to HAL for any indication. */
+void lim_register_hal_ind_call_back(tpAniSirGlobal pMac);
+void lim_pkt_free(tpAniSirGlobal pMac,
+ eFrameType frmType, uint8_t *pBD, void *body);
+
+void lim_get_b_dfrom_rx_packet(tpAniSirGlobal pMac, void *body, uint32_t **pBD);
+
+/**
+ * utils_power_xy() - calc result of base raised to power
+ * @base: Base value
+ * @power: Base raised to this Power value
+ *
+ * Given a base(X) and power(Y), this API will return
+ * the result of base raised to power - (X ^ Y)
+ *
+ * Return: Result of X^Y
+ *
+ */
+static inline uint32_t utils_power_xy(uint16_t base, uint16_t power)
+{
+ uint32_t result = 1, i;
+
+ for (i = 0; i < power; i++)
+ result *= base;
+
+ return result;
+}
+
+tSirRetStatus lim_post_sm_state_update(tpAniSirGlobal pMac,
+ uint16_t StaIdx,
+ tSirMacHTMIMOPowerSaveState MIMOPSState,
+ uint8_t *pPeerStaMac, uint8_t sessionId);
+
+void lim_delete_sta_context(tpAniSirGlobal pMac, tpSirMsgQ limMsg);
+void lim_delete_dialogue_token_list(tpAniSirGlobal pMac);
+void lim_resset_scan_channel_info(tpAniSirGlobal pMac);
+uint8_t lim_get_channel_from_beacon(tpAniSirGlobal pMac,
+ tpSchBeaconStruct pBeacon);
+tSirNwType lim_get_nw_type(tpAniSirGlobal pMac, uint8_t channelNum,
+ uint32_t type, tpSchBeaconStruct pBeacon);
+
+void lim_set_tspec_uapsd_mask_per_session(tpAniSirGlobal pMac,
+ tpPESession psessionEntry,
+ tSirMacTSInfo *pTsInfo, uint32_t action);
+
+void lim_handle_heart_beat_timeout_for_session(tpAniSirGlobal pMac,
+ tpPESession psessionEntry);
+
+void lim_process_add_sta_rsp(tpAniSirGlobal pMac, tpSirMsgQ pMsgQ);
+
+void lim_update_beacon(tpAniSirGlobal pMac);
+
+void lim_process_ap_mlm_add_sta_rsp(tpAniSirGlobal pMac, tpSirMsgQ limMsgQ,
+ tpPESession psessionEntry);
+void lim_process_bt_amp_ap_mlm_del_bss_rsp(tpAniSirGlobal pMac,
+ tpSirMsgQ limMsgQ,
+ tpPESession psessionEntry);
+
+void lim_process_bt_amp_ap_mlm_del_sta_rsp(tpAniSirGlobal pMac,
+ tpSirMsgQ limMsgQ,
+ tpPESession psessionEntry);
+
+tpPESession lim_is_ibss_session_active(tpAniSirGlobal pMac);
+tpPESession lim_is_ap_session_active(tpAniSirGlobal pMac);
+void lim_handle_heart_beat_failure_timeout(tpAniSirGlobal pMac);
+
+uint8_t *lim_get_ie_ptr_new(tpAniSirGlobal pMac, uint8_t *pIes, int length,
+ uint8_t eid, eSizeOfLenField size_of_len_field);
+
+#define limGetWscIEPtr(pMac, ie, ie_len) \
+ cfg_get_vendor_ie_ptr_from_oui(pMac, SIR_MAC_WSC_OUI, \
+ SIR_MAC_WSC_OUI_SIZE, ie, ie_len)
+
+#define limGetP2pIEPtr(pMac, ie, ie_len) \
+ cfg_get_vendor_ie_ptr_from_oui(pMac, SIR_MAC_P2P_OUI, \
+ SIR_MAC_P2P_OUI_SIZE, ie, ie_len)
+
+uint8_t lim_get_noa_attr_stream_in_mult_p2p_ies(tpAniSirGlobal pMac,
+ uint8_t *noaStream, uint8_t noaLen,
+ uint8_t overFlowLen);
+uint8_t lim_get_noa_attr_stream(tpAniSirGlobal pMac, uint8_t *pNoaStream,
+ tpPESession psessionEntry);
+
+uint8_t lim_build_p2p_ie(tpAniSirGlobal pMac, uint8_t *ie, uint8_t *data,
+ uint8_t ie_len);
+bool lim_is_noa_insert_reqd(tpAniSirGlobal pMac);
+bool lim_isconnected_on_dfs_channel(uint8_t currentChannel);
+uint8_t lim_get_current_operating_channel(tpAniSirGlobal pMac);
+
+#ifdef WLAN_FEATURE_11AC
+bool lim_check_vht_op_mode_change(tpAniSirGlobal pMac,
+ tpPESession psessionEntry,
+ uint8_t chanWidth, uint8_t staId,
+ uint8_t *peerMac);
+bool lim_set_nss_change(tpAniSirGlobal pMac, tpPESession psessionEntry,
+ uint8_t rxNss, uint8_t staId, uint8_t *peerMac);
+bool lim_check_membership_user_position(tpAniSirGlobal pMac,
+ tpPESession psessionEntry,
+ uint32_t membership, uint32_t userPosition,
+ uint8_t staId);
+#endif
+
+#ifdef FEATURE_WLAN_DIAG_SUPPORT
+
+typedef enum {
+ WLAN_PE_DIAG_SCAN_REQ_EVENT = 0,
+ WLAN_PE_DIAG_SCAN_ABORT_IND_EVENT,
+ WLAN_PE_DIAG_SCAN_RSP_EVENT,
+ WLAN_PE_DIAG_JOIN_REQ_EVENT,
+ WLAN_PE_DIAG_JOIN_RSP_EVENT,
+ WLAN_PE_DIAG_SETCONTEXT_REQ_EVENT,
+ WLAN_PE_DIAG_SETCONTEXT_RSP_EVENT,
+ WLAN_PE_DIAG_REASSOC_REQ_EVENT,
+ WLAN_PE_DIAG_REASSOC_RSP_EVENT,
+ WLAN_PE_DIAG_AUTH_REQ_EVENT,
+ WLAN_PE_DIAG_AUTH_RSP_EVENT = 10,
+ WLAN_PE_DIAG_DISASSOC_REQ_EVENT,
+ WLAN_PE_DIAG_DISASSOC_RSP_EVENT,
+ WLAN_PE_DIAG_DISASSOC_IND_EVENT,
+ WLAN_PE_DIAG_DISASSOC_CNF_EVENT,
+ WLAN_PE_DIAG_DEAUTH_REQ_EVENT,
+ WLAN_PE_DIAG_DEAUTH_RSP_EVENT,
+ WLAN_PE_DIAG_DEAUTH_IND_EVENT,
+ WLAN_PE_DIAG_START_BSS_REQ_EVENT,
+ WLAN_PE_DIAG_START_BSS_RSP_EVENT,
+ WLAN_PE_DIAG_AUTH_IND_EVENT = 20,
+ WLAN_PE_DIAG_ASSOC_IND_EVENT,
+ WLAN_PE_DIAG_ASSOC_CNF_EVENT,
+ WLAN_PE_DIAG_REASSOC_IND_EVENT,
+ WLAN_PE_DIAG_SWITCH_CHL_IND_EVENT,
+ WLAN_PE_DIAG_STOP_BSS_REQ_EVENT,
+ WLAN_PE_DIAG_STOP_BSS_RSP_EVENT,
+ WLAN_PE_DIAG_DEAUTH_CNF_EVENT,
+ WLAN_PE_DIAG_ADDTS_REQ_EVENT,
+ WLAN_PE_DIAG_ADDTS_RSP_EVENT,
+ WLAN_PE_DIAG_DELTS_REQ_EVENT = 30,
+ WLAN_PE_DIAG_DELTS_RSP_EVENT,
+ WLAN_PE_DIAG_DELTS_IND_EVENT,
+ WLAN_PE_DIAG_ENTER_BMPS_REQ_EVENT,
+ WLAN_PE_DIAG_ENTER_BMPS_RSP_EVENT,
+ WLAN_PE_DIAG_EXIT_BMPS_REQ_EVENT,
+ WLAN_PE_DIAG_EXIT_BMPS_RSP_EVENT,
+ WLAN_PE_DIAG_EXIT_BMPS_IND_EVENT,
+ WLAN_PE_DIAG_ENTER_UAPSD_REQ_EVENT,
+ WLAN_PE_DIAG_ENTER_UAPSD_RSP_EVENT,
+ WLAN_PE_DIAG_EXIT_UAPSD_REQ_EVENT = 40,
+ WLAN_PE_DIAG_EXIT_UAPSD_RSP_EVENT,
+ WLAN_PE_DIAG_WOWL_ADD_BCAST_PTRN_EVENT,
+ WLAN_PE_DIAG_WOWL_DEL_BCAST_PTRN_EVENT,
+ WLAN_PE_DIAG_ENTER_WOWL_REQ_EVENT,
+ WLAN_PE_DIAG_ENTER_WOWL_RSP_EVENT,
+ WLAN_PE_DIAG_EXIT_WOWL_REQ_EVENT,
+ WLAN_PE_DIAG_EXIT_WOWL_RSP_EVENT,
+ WLAN_PE_DIAG_HB_FAILURE_TIMEOUT,
+ WLAN_PE_DIAG_PRE_AUTH_REQ_EVENT,
+ WLAN_PE_DIAG_PRE_AUTH_RSP_EVENT = 50,
+ WLAN_PE_DIAG_PREAUTH_DONE,
+ WLAN_PE_DIAG_REASSOCIATING,
+ WLAN_PE_DIAG_CONNECTED,
+ WLAN_PE_DIAG_ASSOC_REQ_EVENT,
+ WLAN_PE_DIAG_AUTH_COMP_EVENT,
+ WLAN_PE_DIAG_ASSOC_COMP_EVENT,
+ WLAN_PE_DIAG_AUTH_START_EVENT,
+ WLAN_PE_DIAG_ASSOC_START_EVENT,
+ WLAN_PE_DIAG_REASSOC_START_EVENT,
+ WLAN_PE_DIAG_ROAM_AUTH_START_EVENT = 60,
+ WLAN_PE_DIAG_ROAM_AUTH_COMP_EVENT,
+ WLAN_PE_DIAG_ROAM_ASSOC_START_EVENT,
+ WLAN_PE_DIAG_ROAM_ASSOC_COMP_EVENT,
+ RESERVED1, /* = 64 for SCAN_COMPLETE */
+ RESERVED2, /* = 65 for SCAN_RES_FOUND */
+} WLAN_PE_DIAG_EVENT_TYPE;
+
+void lim_diag_event_report(tpAniSirGlobal pMac, uint16_t eventType,
+ tpPESession pSessionEntry, uint16_t status,
+ uint16_t reasonCode);
+#endif /* FEATURE_WLAN_DIAG_SUPPORT */
+
+void pe_set_resume_channel(tpAniSirGlobal pMac, uint16_t channel,
+ ePhyChanBondState cbState);
+
+void lim_get_short_slot_from_phy_mode(tpAniSirGlobal pMac,
+ tpPESession psessionEntry,
+ uint32_t phyMode, uint8_t *pShortSlotEnable);
+
+void lim_clean_up_disassoc_deauth_req(tpAniSirGlobal pMac, uint8_t *staMac,
+ bool cleanRxPath);
+
+bool lim_check_disassoc_deauth_ack_pending(tpAniSirGlobal pMac,
+ uint8_t *staMac);
+
+#ifdef WLAN_FEATURE_11W
+void lim_pmf_sa_query_timer_handler(void *pMacGlobal, uint32_t param);
+#endif
+
+void lim_set_protected_bit(tpAniSirGlobal pMac,
+ tpPESession psessionEntry,
+ tSirMacAddr peer, tpSirMacMgmtHdr pMacHdr);
+
+#ifdef WLAN_FEATURE_11W
+void lim_pmf_comeback_timer_callback(void *context);
+#endif /* WLAN_FEATURE_11W */
+
+void lim_set_ht_caps(tpAniSirGlobal p_mac,
+ tpPESession p_session_ntry,
+ uint8_t *p_ie_start,
+ uint32_t num_bytes);
+
+#ifdef WLAN_FEATURE_11AC
+void lim_set_vht_caps(tpAniSirGlobal p_mac,
+ tpPESession p_session_entry,
+ uint8_t *p_ie_start,
+ uint32_t num_bytes);
+#endif /* WLAN_FEATURE_11AC */
+bool lim_validate_received_frame_a1_addr(tpAniSirGlobal mac_ctx,
+ tSirMacAddr a1, tpPESession session);
+void lim_set_stads_rtt_cap(tpDphHashNode sta_ds, struct s_ext_cap *ext_cap,
+ tpAniSirGlobal mac_ctx);
+
+void lim_check_and_reset_protection_params(tpAniSirGlobal mac_ctx);
+
+CDF_STATUS lim_send_ext_cap_ie(tpAniSirGlobal mac_ctx, uint32_t session_id,
+ tDot11fIEExtCap *extracted_extcap, bool merge);
+
+tSirRetStatus lim_strip_extcap_ie(tpAniSirGlobal mac_ctx, uint8_t *addn_ie,
+ uint16_t *addn_ielen, uint8_t *extracted_extcap);
+void lim_update_extcap_struct(tpAniSirGlobal mac_ctx, uint8_t *buf,
+ tDot11fIEExtCap *ext_cap);
+tSirRetStatus lim_strip_extcap_update_struct(tpAniSirGlobal mac_ctx,
+ uint8_t *addn_ie, uint16_t *addn_ielen, tDot11fIEExtCap *dst);
+void lim_merge_extcap_struct(tDot11fIEExtCap *dst, tDot11fIEExtCap *src);
+
+#endif /* __LIM_UTILS_H */
diff --git a/core/mac/src/pe/rrm/rrm_api.c b/core/mac/src/pe/rrm/rrm_api.c
new file mode 100644
index 0000000..5b85bf9
--- /dev/null
+++ b/core/mac/src/pe/rrm/rrm_api.c
@@ -0,0 +1,1495 @@
+/*
+ * Copyright (c) 2012-2015 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.
+ */
+
+/**=========================================================================
+
+ \file rrm_api.c
+
+ \brief implementation for PE RRM APIs
+
+ ========================================================================*/
+
+/* $Header$ */
+
+#if defined WLAN_FEATURE_VOWIFI
+
+/*--------------------------------------------------------------------------
+ Include Files
+ ------------------------------------------------------------------------*/
+#include "cds_api.h"
+#include "wni_api.h"
+#include "sir_api.h"
+#include "ani_global.h"
+#include "wni_cfg.h"
+#include "lim_types.h"
+#include "lim_utils.h"
+#include "lim_send_sme_rsp_messages.h"
+#include "parser_api.h"
+#include "lim_send_messages.h"
+#include "rrm_global.h"
+#include "rrm_api.h"
+
+uint8_t
+rrm_get_min_of_max_tx_power(tpAniSirGlobal pMac,
+ tPowerdBm regMax, tPowerdBm apTxPower)
+{
+ uint8_t maxTxPower = 0;
+ uint8_t txPower = CDF_MIN(regMax, (apTxPower));
+ if ((txPower >= RRM_MIN_TX_PWR_CAP) && (txPower <= RRM_MAX_TX_PWR_CAP))
+ maxTxPower = txPower;
+ else if (txPower < RRM_MIN_TX_PWR_CAP)
+ maxTxPower = RRM_MIN_TX_PWR_CAP;
+ else
+ maxTxPower = RRM_MAX_TX_PWR_CAP;
+
+ lim_log(pMac, LOG3,
+ "%s: regulatoryMax = %d, apTxPwr = %d, maxTxpwr = %d",
+ __func__, regMax, apTxPower, maxTxPower);
+ return maxTxPower;
+}
+
+/* -------------------------------------------------------------------- */
+/**
+ * rrm_cache_mgmt_tx_power
+ **
+ * FUNCTION: Store Tx power for management frames.
+ *
+ * LOGIC:
+ *
+ * ASSUMPTIONS:
+ *
+ * NOTE:
+ *
+ * @param pSessionEntry session entry.
+ * @return None
+ */
+void
+rrm_cache_mgmt_tx_power(tpAniSirGlobal pMac, tPowerdBm txPower,
+ tpPESession pSessionEntry)
+{
+ lim_log(pMac, LOG3, "Cache Mgmt Tx Power = %d", txPower);
+
+ if (pSessionEntry == NULL) {
+ lim_log(pMac, LOG3, "%s: pSessionEntry is NULL", __func__);
+ pMac->rrm.rrmPEContext.txMgmtPower = txPower;
+ } else
+ pSessionEntry->txMgmtPower = txPower;
+}
+
+/* -------------------------------------------------------------------- */
+/**
+ * rrm_get_mgmt_tx_power
+ *
+ * FUNCTION: Get the Tx power for management frames.
+ *
+ * LOGIC:
+ *
+ * ASSUMPTIONS:
+ *
+ * NOTE:
+ *
+ * @param pSessionEntry session entry.
+ * @return txPower
+ */
+tPowerdBm rrm_get_mgmt_tx_power(tpAniSirGlobal pMac, tpPESession pSessionEntry)
+{
+ lim_log(pMac, LOG3, "RrmGetMgmtTxPower called");
+
+ if (pSessionEntry == NULL) {
+ lim_log(pMac, LOG3, "%s: txpower from rrmPEContext: %d",
+ __func__, pMac->rrm.rrmPEContext.txMgmtPower);
+ return pMac->rrm.rrmPEContext.txMgmtPower;
+ }
+
+ return pSessionEntry->txMgmtPower;
+}
+
+/* -------------------------------------------------------------------- */
+/**
+ * rrm_send_set_max_tx_power_req
+ *
+ * FUNCTION: Send WMA_SET_MAX_TX_POWER_REQ message to change the max tx power.
+ *
+ * LOGIC:
+ *
+ * ASSUMPTIONS:
+ *
+ * NOTE:
+ *
+ * @param txPower txPower to be set.
+ * @param pSessionEntry session entry.
+ * @return None
+ */
+tSirRetStatus
+rrm_send_set_max_tx_power_req(tpAniSirGlobal pMac, tPowerdBm txPower,
+ tpPESession pSessionEntry)
+{
+ tpMaxTxPowerParams pMaxTxParams;
+ tSirRetStatus retCode = eSIR_SUCCESS;
+ tSirMsgQ msgQ;
+
+ if (pSessionEntry == NULL) {
+ PELOGE(lim_log(pMac, LOGE, FL("Invalid parameters"));)
+ return eSIR_FAILURE;
+ }
+ pMaxTxParams = cdf_mem_malloc(sizeof(tMaxTxPowerParams));
+ if (NULL == pMaxTxParams) {
+ lim_log(pMac, LOGP,
+ FL("Unable to allocate memory for pMaxTxParams "));
+ return eSIR_MEM_ALLOC_FAILED;
+
+ }
+ /* Allocated memory for pMaxTxParams...will be freed in other module */
+ pMaxTxParams->power = txPower;
+ cdf_mem_copy(pMaxTxParams->bssId, pSessionEntry->bssId,
+ sizeof(tSirMacAddr));
+ cdf_mem_copy(pMaxTxParams->selfStaMacAddr, pSessionEntry->selfMacAddr,
+ sizeof(tSirMacAddr));
+
+ msgQ.type = WMA_SET_MAX_TX_POWER_REQ;
+ msgQ.reserved = 0;
+ msgQ.bodyptr = pMaxTxParams;
+ msgQ.bodyval = 0;
+
+ lim_log(pMac, LOG3,
+ FL("Sending WMA_SET_MAX_TX_POWER_REQ with power(%d) to HAL"),
+ txPower);
+
+ MTRACE(mac_trace_msg_tx(pMac, pSessionEntry->peSessionId, msgQ.type));
+ if (eSIR_SUCCESS != (retCode = wma_post_ctrl_msg(pMac, &msgQ))) {
+ lim_log(pMac, LOGP,
+ FL
+ ("Posting WMA_SET_MAX_TX_POWER_REQ to HAL failed, reason=%X"),
+ retCode);
+ cdf_mem_free(pMaxTxParams);
+ return retCode;
+ }
+ return retCode;
+}
+
+/* -------------------------------------------------------------------- */
+/**
+ * rrm_set_max_tx_power_rsp
+ *
+ * FUNCTION: Process WMA_SET_MAX_TX_POWER_RSP message.
+ *
+ * LOGIC:
+ *
+ * ASSUMPTIONS:
+ *
+ * NOTE:
+ *
+ * @param txPower txPower to be set.
+ * @param pSessionEntry session entry.
+ * @return None
+ */
+tSirRetStatus rrm_set_max_tx_power_rsp(tpAniSirGlobal pMac, tpSirMsgQ limMsgQ)
+{
+ tSirRetStatus retCode = eSIR_SUCCESS;
+ tpMaxTxPowerParams pMaxTxParams = (tpMaxTxPowerParams) limMsgQ->bodyptr;
+ tpPESession pSessionEntry;
+ uint8_t sessionId, i;
+ tSirMacAddr bssid = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
+
+ if (cdf_mem_compare(bssid, pMaxTxParams->bssId, sizeof(tSirMacAddr))) {
+ for (i = 0; i < pMac->lim.maxBssId; i++) {
+ if ((pMac->lim.gpSession[i].valid == true)) {
+ pSessionEntry = &pMac->lim.gpSession[i];
+ rrm_cache_mgmt_tx_power(pMac, pMaxTxParams->power,
+ pSessionEntry);
+ }
+ }
+ } else {
+ if ((pSessionEntry =
+ pe_find_session_by_bssid(pMac, pMaxTxParams->bssId,
+ &sessionId)) == NULL) {
+ PELOGE(lim_log
+ (pMac, LOGE, FL("Unable to find session:"));
+ )
+ retCode = eSIR_FAILURE;
+ } else {
+ rrm_cache_mgmt_tx_power(pMac, pMaxTxParams->power,
+ pSessionEntry);
+ }
+ }
+
+ cdf_mem_free(limMsgQ->bodyptr);
+ limMsgQ->bodyptr = NULL;
+ return retCode;
+}
+
+/* -------------------------------------------------------------------- */
+/**
+ * rrm_process_link_measurement_request
+ *
+ * FUNCTION: Processes the Link measurement request and send the report.
+ *
+ * LOGIC:
+ *
+ * ASSUMPTIONS:
+ *
+ * NOTE:
+ *
+ * @param pBd pointer to BD to extract RSSI and SNR
+ * @param pLinkReq pointer to the Link request frame structure.
+ * @param pSessionEntry session entry.
+ * @return None
+ */
+tSirRetStatus
+rrm_process_link_measurement_request(tpAniSirGlobal pMac,
+ uint8_t *pRxPacketInfo,
+ tDot11fLinkMeasurementRequest *pLinkReq,
+ tpPESession pSessionEntry)
+{
+ tSirMacLinkReport LinkReport;
+ tpSirMacMgmtHdr pHdr;
+ int8_t currentRSSI = 0;
+
+ lim_log(pMac, LOG3, "Received Link measurement request");
+
+ if (pRxPacketInfo == NULL || pLinkReq == NULL || pSessionEntry == NULL) {
+ PELOGE(lim_log(pMac, LOGE,
+ "%s Invalid parameters - Ignoring the request",
+ __func__);
+ )
+ return eSIR_FAILURE;
+ }
+ pHdr = WMA_GET_RX_MAC_HEADER(pRxPacketInfo);
+
+ LinkReport.txPower = lim_get_max_tx_power(pLinkReq->MaxTxPower.maxTxPower,
+ pLinkReq->MaxTxPower.maxTxPower,
+ pMac->roam.configParam.
+ nTxPowerCap);
+
+ if ((LinkReport.txPower != (uint8_t) (pSessionEntry->maxTxPower)) &&
+ (eSIR_SUCCESS == rrm_send_set_max_tx_power_req(pMac,
+ (tPowerdBm) (LinkReport.
+ txPower),
+ pSessionEntry))) {
+ PELOGW(lim_log
+ (pMac, LOGW,
+ FL(" maxTx power in link report is not same as local..."
+ " Local = %d Link Request TxPower = %d"
+ " Link Report TxPower = %d"),
+ pSessionEntry->maxTxPower, LinkReport.txPower,
+ pLinkReq->MaxTxPower.maxTxPower);
+ )
+ pSessionEntry->maxTxPower =
+ (tPowerdBm) (LinkReport.txPower);
+ }
+
+ LinkReport.dialogToken = pLinkReq->DialogToken.token;
+ LinkReport.rxAntenna = 0;
+ LinkReport.txAntenna = 0;
+ currentRSSI = WMA_GET_RX_RSSI_DB(pRxPacketInfo);
+
+ lim_log(pMac, LOG1, "Received Link report frame with %d", currentRSSI);
+
+ /* 2008 11k spec reference: 18.4.8.5 RCPI Measurement */
+ if ((currentRSSI) <= RCPI_LOW_RSSI_VALUE)
+ LinkReport.rcpi = 0;
+ else if ((currentRSSI > RCPI_LOW_RSSI_VALUE) && (currentRSSI <= 0))
+ LinkReport.rcpi = CALCULATE_RCPI(currentRSSI);
+ else
+ LinkReport.rcpi = RCPI_MAX_VALUE;
+
+ LinkReport.rsni = WMA_GET_RX_SNR(pRxPacketInfo);
+
+ lim_log(pMac, LOG3, "Sending Link report frame");
+
+ return lim_send_link_report_action_frame(pMac, &LinkReport, pHdr->sa,
+ pSessionEntry);
+}
+
+/* -------------------------------------------------------------------- */
+/**
+ * rrm_process_neighbor_report_response
+ *
+ * FUNCTION: Processes the Neighbor Report response from the peer AP.
+ *
+ * LOGIC:
+ *
+ * ASSUMPTIONS:
+ *
+ * NOTE:
+ *
+ * @param pNeighborRep pointer to the Neighbor report frame structure.
+ * @param pSessionEntry session entry.
+ * @return None
+ */
+tSirRetStatus
+rrm_process_neighbor_report_response(tpAniSirGlobal pMac,
+ tDot11fNeighborReportResponse *pNeighborRep,
+ tpPESession pSessionEntry)
+{
+ tSirRetStatus status = eSIR_FAILURE;
+ tpSirNeighborReportInd pSmeNeighborRpt = NULL;
+ uint16_t length;
+ uint8_t i;
+ tSirMsgQ mmhMsg;
+
+ if (pNeighborRep == NULL || pSessionEntry == NULL) {
+ PELOGE(lim_log(pMac, LOGE, FL(" Invalid parameters"));)
+ return status;
+ }
+
+ lim_log(pMac, LOG3, FL("Neighbor report response received "));
+
+ /* Dialog token */
+ if (pMac->rrm.rrmPEContext.DialogToken !=
+ pNeighborRep->DialogToken.token) {
+ PELOGE(lim_log
+ (pMac, LOGE,
+ "Dialog token mismatch in the received Neighbor report");
+ )
+ return eSIR_FAILURE;
+ }
+ if (pNeighborRep->num_NeighborReport == 0) {
+ PELOGE(lim_log
+ (pMac, LOGE,
+ "No neighbor report in the frame...Dropping it");
+ )
+ return eSIR_FAILURE;
+ }
+ length = (sizeof(tSirNeighborReportInd)) +
+ (sizeof(tSirNeighborBssDescription) *
+ (pNeighborRep->num_NeighborReport - 1));
+
+ /* Prepare the request to send to SME. */
+ pSmeNeighborRpt = cdf_mem_malloc(length);
+ if (NULL == pSmeNeighborRpt) {
+ PELOGE(lim_log(pMac, LOGP, FL("Unable to allocate memory"));)
+ return eSIR_MEM_ALLOC_FAILED;
+
+ }
+ cdf_mem_set(pSmeNeighborRpt, length, 0);
+
+ /* Allocated memory for pSmeNeighborRpt...will be freed by other module */
+
+ for (i = 0; i < pNeighborRep->num_NeighborReport; i++) {
+ pSmeNeighborRpt->sNeighborBssDescription[i].length = sizeof(tSirNeighborBssDescription); /*+ any optional ies */
+ cdf_mem_copy(pSmeNeighborRpt->sNeighborBssDescription[i].bssId,
+ pNeighborRep->NeighborReport[i].bssid,
+ sizeof(tSirMacAddr));
+ pSmeNeighborRpt->sNeighborBssDescription[i].bssidInfo.rrmInfo.
+ fApPreauthReachable =
+ pNeighborRep->NeighborReport[i].APReachability;
+ pSmeNeighborRpt->sNeighborBssDescription[i].bssidInfo.rrmInfo.
+ fSameSecurityMode =
+ pNeighborRep->NeighborReport[i].Security;
+ pSmeNeighborRpt->sNeighborBssDescription[i].bssidInfo.rrmInfo.
+ fSameAuthenticator =
+ pNeighborRep->NeighborReport[i].KeyScope;
+ pSmeNeighborRpt->sNeighborBssDescription[i].bssidInfo.rrmInfo.
+ fCapSpectrumMeasurement =
+ pNeighborRep->NeighborReport[i].SpecMgmtCap;
+ pSmeNeighborRpt->sNeighborBssDescription[i].bssidInfo.rrmInfo.
+ fCapQos = pNeighborRep->NeighborReport[i].QosCap;
+ pSmeNeighborRpt->sNeighborBssDescription[i].bssidInfo.rrmInfo.
+ fCapApsd = pNeighborRep->NeighborReport[i].apsd;
+ pSmeNeighborRpt->sNeighborBssDescription[i].bssidInfo.rrmInfo.
+ fCapRadioMeasurement = pNeighborRep->NeighborReport[i].rrm;
+ pSmeNeighborRpt->sNeighborBssDescription[i].bssidInfo.rrmInfo.
+ fCapDelayedBlockAck =
+ pNeighborRep->NeighborReport[i].DelayedBA;
+ pSmeNeighborRpt->sNeighborBssDescription[i].bssidInfo.rrmInfo.
+ fCapImmediateBlockAck =
+ pNeighborRep->NeighborReport[i].ImmBA;
+ pSmeNeighborRpt->sNeighborBssDescription[i].bssidInfo.rrmInfo.
+ fMobilityDomain =
+ pNeighborRep->NeighborReport[i].MobilityDomain;
+
+ pSmeNeighborRpt->sNeighborBssDescription[i].regClass =
+ pNeighborRep->NeighborReport[i].regulatoryClass;
+ pSmeNeighborRpt->sNeighborBssDescription[i].channel =
+ pNeighborRep->NeighborReport[i].channel;
+ pSmeNeighborRpt->sNeighborBssDescription[i].phyType =
+ pNeighborRep->NeighborReport[i].PhyType;
+ }
+
+ pSmeNeighborRpt->messageType = eWNI_SME_NEIGHBOR_REPORT_IND;
+ pSmeNeighborRpt->length = length;
+ pSmeNeighborRpt->sessionId = pSessionEntry->smeSessionId;
+ pSmeNeighborRpt->numNeighborReports = pNeighborRep->num_NeighborReport;
+ cdf_mem_copy(pSmeNeighborRpt->bssId, pSessionEntry->bssId,
+ sizeof(tSirMacAddr));
+
+ /* Send request to SME. */
+ mmhMsg.type = pSmeNeighborRpt->messageType;
+ mmhMsg.bodyptr = pSmeNeighborRpt;
+ MTRACE(mac_trace_msg_tx(pMac, pSessionEntry->peSessionId, mmhMsg.type));
+ status = lim_sys_process_mmh_msg_api(pMac, &mmhMsg, ePROT);
+
+ return status;
+
+}
+
+/* -------------------------------------------------------------------- */
+/**
+ * rrm_process_neighbor_report_req
+ *
+ * FUNCTION:
+ *
+ * LOGIC: Create a Neighbor report request and send it to peer.
+ *
+ * ASSUMPTIONS:
+ *
+ * NOTE:
+ *
+ * @param pNeighborReq Neighbor report request params .
+ * @return None
+ */
+tSirRetStatus
+rrm_process_neighbor_report_req(tpAniSirGlobal pMac,
+ tpSirNeighborReportReqInd pNeighborReq)
+{
+ tSirRetStatus status = eSIR_SUCCESS;
+ tSirMacNeighborReportReq NeighborReportReq;
+ tpPESession pSessionEntry;
+ uint8_t sessionId;
+
+ if (pNeighborReq == NULL) {
+ PELOGE(lim_log(pMac, LOGE, "NeighborReq is NULL");)
+ return eSIR_FAILURE;
+ }
+ if ((pSessionEntry =
+ pe_find_session_by_bssid(pMac, pNeighborReq->bssId,
+ &sessionId)) == NULL) {
+ PELOGE(lim_log
+ (pMac, LOGE,
+ FL("session does not exist for given bssId"));
+ )
+ return eSIR_FAILURE;
+ }
+
+ lim_log(pMac, LOG1, FL("SSID present = %d "), pNeighborReq->noSSID);
+
+ cdf_mem_set(&NeighborReportReq, sizeof(tSirMacNeighborReportReq), 0);
+
+ NeighborReportReq.dialogToken = ++pMac->rrm.rrmPEContext.DialogToken;
+ NeighborReportReq.ssid_present = !pNeighborReq->noSSID;
+ if (NeighborReportReq.ssid_present) {
+ cdf_mem_copy(&NeighborReportReq.ssid, &pNeighborReq->ucSSID,
+ sizeof(tSirMacSSid));
+ PELOGE(sir_dump_buf
+ (pMac, SIR_LIM_MODULE_ID, LOGE,
+ (uint8_t *) NeighborReportReq.ssid.ssId,
+ NeighborReportReq.ssid.length);
+ )
+ }
+
+ status =
+ lim_send_neighbor_report_request_frame(pMac, &NeighborReportReq,
+ pNeighborReq->bssId,
+ pSessionEntry);
+
+ return status;
+}
+
+#define ABS(x) ((x < 0) ? -x : x)
+/* -------------------------------------------------------------------- */
+/**
+ * rrm_process_beacon_report_req
+ *
+ * FUNCTION: Processes the Beacon report request from the peer AP.
+ *
+ * LOGIC:
+ *
+ * ASSUMPTIONS:
+ *
+ * NOTE:
+ *
+ * @param pCurrentReq pointer to the current Req comtext.
+ * @param pBeaconReq pointer to the beacon report request IE from the peer.
+ * @param pSessionEntry session entry.
+ * @return None
+ */
+static tRrmRetStatus
+rrm_process_beacon_report_req(tpAniSirGlobal pMac,
+ tpRRMReq pCurrentReq,
+ tDot11fIEMeasurementRequest *pBeaconReq,
+ tpPESession pSessionEntry)
+{
+ tSirMsgQ mmhMsg;
+ tpSirBeaconReportReqInd pSmeBcnReportReq;
+ uint8_t num_channels = 0, num_APChanReport;
+ uint16_t measDuration, maxMeasduration;
+ int8_t maxDuration;
+ uint8_t sign;
+
+ if (pBeaconReq->measurement_request.Beacon.BeaconReporting.present &&
+ (pBeaconReq->measurement_request.Beacon.BeaconReporting.
+ reportingCondition != 0)) {
+ /* Repeated measurement is not supported. This means number of repetitions should be zero.(Already checked) */
+ /* All test case in VoWifi(as of version 0.36) use zero for number of repetitions. */
+ /* Beacon reporting should not be included in request if number of repetitons is zero. */
+ /* IEEE Std 802.11k-2008 Table 7-29g and section 11.10.8.1 */
+
+ PELOGE(lim_log
+ (pMac, LOGE,
+ "Dropping the request: Reporting condition included in beacon report request and it is not zero");
+ )
+ return eRRM_INCAPABLE;
+ }
+
+ /* The logic here is to check the measurement duration passed in the beacon request. Following are the cases handled.
+ Case 1: If measurement duration received in the beacon request is greater than the max measurement duration advertised
+ in the RRM capabilities(Assoc Req), and Duration Mandatory bit is set to 1, REFUSE the beacon request
+ Case 2: If measurement duration received in the beacon request is greater than the max measurement duration advertised
+ in the RRM capabilities(Assoc Req), and Duration Mandatory bit is set to 0, perform measurement for
+ the duration advertised in the RRM capabilities
+
+ maxMeasurementDuration = 2^(nonOperatingChanMax - 4) * BeaconInterval
+ */
+ maxDuration =
+ pMac->rrm.rrmPEContext.rrmEnabledCaps.nonOperatingChanMax - 4;
+ sign = (maxDuration < 0) ? 1 : 0;
+ maxDuration = (1L << ABS(maxDuration));
+ if (!sign)
+ maxMeasduration =
+ maxDuration * pSessionEntry->beaconParams.beaconInterval;
+ else
+ maxMeasduration =
+ pSessionEntry->beaconParams.beaconInterval / maxDuration;
+
+ measDuration = pBeaconReq->measurement_request.Beacon.meas_duration;
+
+ lim_log(pMac, LOG3,
+ "maxDuration = %d sign = %d maxMeasduration = %d measDuration = %d",
+ maxDuration, sign, maxMeasduration, measDuration);
+
+ if (maxMeasduration < measDuration) {
+ if (pBeaconReq->durationMandatory) {
+ PELOGE(lim_log
+ (pMac, LOGE,
+ "Dropping the request: duration mandatory and maxduration > measduration");
+ )
+ return eRRM_REFUSED;
+ } else
+ measDuration = maxMeasduration;
+ }
+ /* Cache the data required for sending report. */
+ pCurrentReq->request.Beacon.reportingDetail =
+ pBeaconReq->measurement_request.Beacon.BcnReportingDetail.
+ present ? pBeaconReq->measurement_request.Beacon.BcnReportingDetail.
+ reportingDetail : BEACON_REPORTING_DETAIL_ALL_FF_IE;
+
+ if (pBeaconReq->measurement_request.Beacon.RequestedInfo.present) {
+ pCurrentReq->request.Beacon.reqIes.pElementIds =
+ cdf_mem_malloc(sizeof(uint8_t) *
+ pBeaconReq->measurement_request.Beacon.
+ RequestedInfo.num_requested_eids);
+ if (NULL == pCurrentReq->request.Beacon.reqIes.pElementIds) {
+ lim_log(pMac, LOGP,
+ FL
+ ("Unable to allocate memory for request IEs buffer"));
+ return eRRM_FAILURE;
+ }
+ lim_log(pMac, LOG3, FL(" Allocated memory for pElementIds"));
+
+ pCurrentReq->request.Beacon.reqIes.num =
+ pBeaconReq->measurement_request.Beacon.RequestedInfo.
+ num_requested_eids;
+ cdf_mem_copy(pCurrentReq->request.Beacon.reqIes.pElementIds,
+ pBeaconReq->measurement_request.Beacon.
+ RequestedInfo.requested_eids,
+ pCurrentReq->request.Beacon.reqIes.num);
+ }
+
+ if (pBeaconReq->measurement_request.Beacon.num_APChannelReport) {
+ for (num_APChanReport = 0;
+ num_APChanReport <
+ pBeaconReq->measurement_request.Beacon.num_APChannelReport;
+ num_APChanReport++)
+ num_channels +=
+ pBeaconReq->measurement_request.Beacon.
+ APChannelReport[num_APChanReport].num_channelList;
+ }
+ /* Prepare the request to send to SME. */
+ pSmeBcnReportReq = cdf_mem_malloc(sizeof(tSirBeaconReportReqInd));
+ if (NULL == pSmeBcnReportReq) {
+ lim_log(pMac, LOGP,
+ FL
+ ("Unable to allocate memory during Beacon Report Req Ind to SME"));
+
+ return eRRM_FAILURE;
+
+ }
+
+ cdf_mem_set(pSmeBcnReportReq, sizeof(tSirBeaconReportReqInd), 0);
+
+ /* Allocated memory for pSmeBcnReportReq....will be freed by other modulea */
+ cdf_mem_copy(pSmeBcnReportReq->bssId, pSessionEntry->bssId,
+ sizeof(tSirMacAddr));
+ pSmeBcnReportReq->messageType = eWNI_SME_BEACON_REPORT_REQ_IND;
+ pSmeBcnReportReq->length = sizeof(tSirBeaconReportReqInd);
+ pSmeBcnReportReq->uDialogToken = pBeaconReq->measurement_token;
+ pSmeBcnReportReq->msgSource = eRRM_MSG_SOURCE_11K;
+ pSmeBcnReportReq->randomizationInterval =
+ SYS_TU_TO_MS(pBeaconReq->measurement_request.Beacon.randomization);
+ pSmeBcnReportReq->channelInfo.regulatoryClass =
+ pBeaconReq->measurement_request.Beacon.regClass;
+ pSmeBcnReportReq->channelInfo.channelNum =
+ pBeaconReq->measurement_request.Beacon.channel;
+ pSmeBcnReportReq->measurementDuration[0] = SYS_TU_TO_MS(measDuration);
+ pSmeBcnReportReq->fMeasurementtype[0] =
+ pBeaconReq->measurement_request.Beacon.meas_mode;
+ cdf_mem_copy(pSmeBcnReportReq->macaddrBssid,
+ pBeaconReq->measurement_request.Beacon.BSSID,
+ sizeof(tSirMacAddr));
+
+ if (pBeaconReq->measurement_request.Beacon.SSID.present) {
+ pSmeBcnReportReq->ssId.length =
+ pBeaconReq->measurement_request.Beacon.SSID.num_ssid;
+ cdf_mem_copy(pSmeBcnReportReq->ssId.ssId,
+ pBeaconReq->measurement_request.Beacon.SSID.ssid,
+ pSmeBcnReportReq->ssId.length);
+ }
+
+ pCurrentReq->token = pBeaconReq->measurement_token;
+
+ pSmeBcnReportReq->channelList.numChannels = num_channels;
+ if (pBeaconReq->measurement_request.Beacon.num_APChannelReport) {
+ uint8_t *pChanList =
+ pSmeBcnReportReq->channelList.channelNumber;
+ for (num_APChanReport = 0;
+ num_APChanReport <
+ pBeaconReq->measurement_request.Beacon.num_APChannelReport;
+ num_APChanReport++) {
+ cdf_mem_copy(pChanList,
+ pBeaconReq->measurement_request.Beacon.
+ APChannelReport[num_APChanReport].
+ channelList,
+ pBeaconReq->measurement_request.Beacon.
+ APChannelReport[num_APChanReport].
+ num_channelList);
+
+ pChanList +=
+ pBeaconReq->measurement_request.Beacon.
+ APChannelReport[num_APChanReport].num_channelList;
+ }
+ }
+ /* Send request to SME. */
+ mmhMsg.type = eWNI_SME_BEACON_REPORT_REQ_IND;
+ mmhMsg.bodyptr = pSmeBcnReportReq;
+ MTRACE(mac_trace_msg_tx(pMac, pSessionEntry->peSessionId, mmhMsg.type));
+ return lim_sys_process_mmh_msg_api(pMac, &mmhMsg, ePROT);
+}
+
+/* -------------------------------------------------------------------- */
+/**
+ * rrm_fill_beacon_ies
+ *
+ * FUNCTION:
+ *
+ * LOGIC: Fills Fixed fields and Ies in bss description to an array of uint8_t.
+ *
+ * ASSUMPTIONS:
+ *
+ * NOTE:
+ *
+ * @param pIes - pointer to the buffer that should be populated with ies.
+ * @param pNumIes - returns the num of ies filled in this param.
+ * @param pIesMaxSize - Max size of the buffer pIes.
+ * @param eids - pointer to array of eids. If NULL, all ies will be populated.
+ * @param numEids - number of elements in array eids.
+ * @param pBssDesc - pointer to Bss Description.
+ * @return None
+ */
+static void
+rrm_fill_beacon_ies(tpAniSirGlobal pMac,
+ uint8_t *pIes, uint8_t *pNumIes, uint8_t pIesMaxSize,
+ uint8_t *eids, uint8_t numEids, tpSirBssDescription pBssDesc)
+{
+ uint8_t len, *pBcnIes, count = 0, i;
+ uint8_t BcnNumIes;
+
+ if ((pIes == NULL) || (pNumIes == NULL) || (pBssDesc == NULL)) {
+ PELOGE(lim_log(pMac, LOGE, FL(" Invalid parameters"));)
+ return;
+ }
+ /* Make sure that if eid is null, numEids is set to zero. */
+ numEids = (eids == NULL) ? 0 : numEids;
+
+ pBcnIes = (uint8_t *) &pBssDesc->ieFields[0];
+ BcnNumIes = (uint8_t) GET_IE_LEN_IN_BSS(pBssDesc->length);
+
+ *pNumIes = 0;
+
+ *((uint32_t *) pIes) = pBssDesc->timeStamp[0];
+ *pNumIes += sizeof(uint32_t);
+ pIes += sizeof(uint32_t);
+ *((uint32_t *) pIes) = pBssDesc->timeStamp[1];
+ *pNumIes += sizeof(uint32_t);
+ pIes += sizeof(uint32_t);
+ *((uint16_t *) pIes) = pBssDesc->beaconInterval;
+ *pNumIes += sizeof(uint16_t);
+ pIes += sizeof(uint16_t);
+ *((uint16_t *) pIes) = pBssDesc->capabilityInfo;
+ *pNumIes += sizeof(uint16_t);
+ pIes += sizeof(uint16_t);
+
+ while (BcnNumIes > 0) {
+ len = *(pBcnIes + 1) + 2; /* element id + length. */
+ lim_log(pMac, LOG3, "EID = %d, len = %d total = %d",
+ *pBcnIes, *(pBcnIes + 1), len);
+
+ i = 0;
+ do {
+ if (((eids == NULL) || (*pBcnIes == eids[i])) &&
+ ((*pNumIes) + len) < pIesMaxSize) {
+ lim_log(pMac, LOG3, "Adding Eid %d, len=%d",
+ *pBcnIes, len);
+
+ cdf_mem_copy(pIes, pBcnIes, len);
+ pIes += len;
+ *pNumIes += len;
+ count++;
+ break;
+ }
+ i++;
+ } while (i < numEids);
+
+ pBcnIes += len;
+ BcnNumIes -= len;
+ }
+ lim_log(pMac, LOG1, "Total length of Ies added = %d", *pNumIes);
+}
+
+/* -------------------------------------------------------------------- */
+/**
+ * rrm_process_beacon_report_xmit
+ *
+ * FUNCTION:
+ *
+ * LOGIC: Create a Radio measurement report action frame and send it to peer.
+ *
+ * ASSUMPTIONS:
+ *
+ * NOTE:
+ *
+ * @param pBcnReport Data for beacon report IE from SME.
+ * @return None
+ */
+tSirRetStatus
+rrm_process_beacon_report_xmit(tpAniSirGlobal pMac,
+ tpSirBeaconReportXmitInd pBcnReport)
+{
+ tSirRetStatus status = eSIR_SUCCESS;
+ tSirMacRadioMeasureReport *pReport = NULL;
+ tpRRMReq pCurrentReq = pMac->rrm.rrmPEContext.pCurrentReq;
+ tpPESession pSessionEntry;
+ uint8_t sessionId;
+ uint8_t flagBSSPresent = false, bssDescCnt = 0;
+
+ lim_log(pMac, LOG1, "Received beacon report xmit indication");
+
+ if (NULL == pBcnReport) {
+ PELOGE(lim_log(pMac, LOGE, "Received pBcnReport is NULL in PE");)
+ return eSIR_FAILURE;
+ }
+
+ if (NULL == pCurrentReq) {
+ PELOGE(lim_log(pMac, LOGE,
+ "Received report xmit while there is no request pending in PE");
+ )
+ return eSIR_FAILURE;
+ }
+
+ if ((pBcnReport->numBssDesc) ||
+ (!pBcnReport->numBssDesc && pCurrentReq->sendEmptyBcnRpt)) {
+ pBcnReport->numBssDesc =
+ (pBcnReport->numBssDesc ==
+ RRM_BCN_RPT_NO_BSS_INFO) ? RRM_BCN_RPT_MIN_RPT :
+ pBcnReport->numBssDesc;
+
+ if (NULL == (pSessionEntry = pe_find_session_by_bssid(pMac,
+ pBcnReport->
+ bssId,
+ &sessionId)))
+ {
+ PELOGE(lim_log
+ (pMac, LOGE,
+ FL("session does not exist for given bssId"));
+ )
+ return eSIR_FAILURE;
+ }
+
+ pReport = cdf_mem_malloc(pBcnReport->numBssDesc *
+ sizeof(tSirMacRadioMeasureReport));
+
+ if (NULL == pReport) {
+ PELOGE(lim_log
+ (pMac, LOGE,
+ FL("RRM Report is NULL, allocation failed"));
+ )
+ return eSIR_MEM_ALLOC_FAILED;
+ }
+
+ cdf_mem_zero(pReport,
+ pBcnReport->numBssDesc *
+ sizeof(tSirMacRadioMeasureReport));
+
+ for (bssDescCnt = 0; bssDescCnt < pBcnReport->numBssDesc;
+ bssDescCnt++) {
+ /* Prepare the beacon report and send it to the peer. */
+ pReport[bssDescCnt].token = pBcnReport->uDialogToken;
+ pReport[bssDescCnt].refused = 0;
+ pReport[bssDescCnt].incapable = 0;
+ pReport[bssDescCnt].type = SIR_MAC_RRM_BEACON_TYPE;
+
+ /* If the scan result is NULL then send report request with */
+ /* option subelement as NULL.. */
+ if (NULL != pBcnReport->pBssDescription[bssDescCnt]) {
+ flagBSSPresent = true;
+ }
+ /* Valid response is included if the size of beacon xmit */
+ /* is == size of beacon xmit ind + ies */
+ if (pBcnReport->length >=
+ sizeof(tSirBeaconReportXmitInd)) {
+ pReport[bssDescCnt].report.beaconReport.
+ regClass = pBcnReport->regClass;
+ if (flagBSSPresent) {
+ pReport[bssDescCnt].report.beaconReport.
+ channel =
+ pBcnReport->
+ pBssDescription[bssDescCnt]->
+ channelId;
+ cdf_mem_copy(pReport[bssDescCnt].report.
+ beaconReport.measStartTime,
+ pBcnReport->
+ pBssDescription
+ [bssDescCnt]->startTSF,
+ sizeof(pBcnReport->
+ pBssDescription
+ [bssDescCnt]->
+ startTSF));
+ pReport[bssDescCnt].report.beaconReport.
+ measDuration =
+ SYS_MS_TO_TU(pBcnReport->duration);
+ pReport[bssDescCnt].report.beaconReport.
+ phyType =
+ pBcnReport->
+ pBssDescription[bssDescCnt]->nwType;
+ pReport[bssDescCnt].report.beaconReport.
+ bcnProbeRsp = 1;
+ pReport[bssDescCnt].report.beaconReport.
+ rsni =
+ pBcnReport->
+ pBssDescription[bssDescCnt]->sinr;
+ pReport[bssDescCnt].report.beaconReport.
+ rcpi =
+ pBcnReport->
+ pBssDescription[bssDescCnt]->rssi;
+
+ pReport[bssDescCnt].report.beaconReport.
+ antennaId = 0;
+ pReport[bssDescCnt].report.beaconReport.
+ parentTSF =
+ pBcnReport->
+ pBssDescription[bssDescCnt]->
+ parentTSF;
+ cdf_mem_copy(pReport[bssDescCnt].report.
+ beaconReport.bssid,
+ pBcnReport->
+ pBssDescription
+ [bssDescCnt]->bssId,
+ sizeof(tSirMacAddr));
+ }
+
+ switch (pCurrentReq->request.Beacon.
+ reportingDetail) {
+ case BEACON_REPORTING_DETAIL_NO_FF_IE:
+ /* 0 No need to include any elements. */
+ lim_log(pMac, LOG3,
+ "No reporting detail requested");
+ break;
+ case BEACON_REPORTING_DETAIL_ALL_FF_REQ_IE:
+ /* 1: Include all FFs and Requested Ies. */
+ lim_log(pMac, LOG3,
+ "Only requested IEs in reporting detail requested");
+
+ if (flagBSSPresent) {
+ rrm_fill_beacon_ies(pMac,
+ (uint8_t *) &
+ pReport
+ [bssDescCnt].
+ report.
+ beaconReport.
+ Ies[0],
+ (uint8_t *) &
+ pReport
+ [bssDescCnt].
+ report.
+ beaconReport.
+ numIes,
+ BEACON_REPORT_MAX_IES,
+ pCurrentReq->
+ request.Beacon.
+ reqIes.
+ pElementIds,
+ pCurrentReq->
+ request.Beacon.
+ reqIes.num,
+ pBcnReport->
+ pBssDescription
+ [bssDescCnt]);
+ }
+
+ break;
+ case BEACON_REPORTING_DETAIL_ALL_FF_IE:
+ /* 2 / default - Include all FFs and all Ies. */
+ default:
+ lim_log(pMac, LOG3,
+ "Default all IEs and FFs");
+ if (flagBSSPresent) {
+ rrm_fill_beacon_ies(pMac,
+ (uint8_t *) &
+ pReport
+ [bssDescCnt].
+ report.
+ beaconReport.
+ Ies[0],
+ (uint8_t *) &
+ pReport
+ [bssDescCnt].
+ report.
+ beaconReport.
+ numIes,
+ BEACON_REPORT_MAX_IES,
+ NULL, 0,
+ pBcnReport->
+ pBssDescription
+ [bssDescCnt]);
+ }
+ break;
+ }
+ }
+ }
+
+ lim_log(pMac, LOG1, "Sending Action frame with %d bss info",
+ bssDescCnt);
+ lim_send_radio_measure_report_action_frame(pMac,
+ pCurrentReq->dialog_token,
+ bssDescCnt, pReport,
+ pBcnReport->bssId,
+ pSessionEntry);
+
+ pCurrentReq->sendEmptyBcnRpt = false;
+ }
+
+ if (pBcnReport->fMeasureDone) {
+ lim_log(pMac, LOG3, "Measurement done....cleanup the context");
+
+ rrm_cleanup(pMac);
+ }
+
+ if (NULL != pReport)
+ cdf_mem_free(pReport);
+
+ return status;
+}
+
+void rrm_process_beacon_request_failure(tpAniSirGlobal pMac,
+ tpPESession pSessionEntry, tSirMacAddr peer,
+ tRrmRetStatus status)
+{
+ tpSirMacRadioMeasureReport pReport = NULL;
+ tpRRMReq pCurrentReq = pMac->rrm.rrmPEContext.pCurrentReq;
+
+ pReport = cdf_mem_malloc(sizeof(tSirMacRadioMeasureReport));
+ if (NULL == pReport) {
+ lim_log(pMac, LOGP,
+ FL
+ ("Unable to allocate memory during RRM Req processing"));
+ return;
+ }
+ cdf_mem_set(pReport, sizeof(tSirMacRadioMeasureReport), 0);
+ pReport->token = pCurrentReq->token;
+ pReport->type = SIR_MAC_RRM_BEACON_TYPE;
+
+ switch (status) {
+ case eRRM_REFUSED:
+ pReport->refused = 1;
+ break;
+ case eRRM_INCAPABLE:
+ pReport->incapable = 1;
+ break;
+ default:
+ PELOGE(lim_log(pMac, LOGE,
+ FL
+ (" Beacon request processing failed no report sent with status %d "),
+ status);
+ );
+ cdf_mem_free(pReport);
+ return;
+ }
+
+ lim_send_radio_measure_report_action_frame(pMac, pCurrentReq->dialog_token, 1,
+ pReport, peer, pSessionEntry);
+
+ cdf_mem_free(pReport);
+ lim_log(pMac, LOG3, FL(" Free memory for pReport"));
+ return;
+}
+
+/* -------------------------------------------------------------------- */
+/**
+ * rrm_process_radio_measurement_request
+ *
+ * FUNCTION: Processes the Radio Resource Measurement request.
+ *
+ * LOGIC:
+
+ *
+ * ASSUMPTIONS:
+ *
+ * NOTE:
+ *
+ * @param peer Macaddress of the peer requesting the radio measurement.
+ * @param pRRMReq Array of Measurement request IEs
+ * @param pSessionEntry session entry.
+ * @return None
+ */
+tSirRetStatus
+rrm_process_radio_measurement_request(tpAniSirGlobal pMac,
+ tSirMacAddr peer,
+ tDot11fRadioMeasurementRequest *pRRMReq,
+ tpPESession pSessionEntry)
+{
+ uint8_t i;
+ tSirRetStatus status = eSIR_SUCCESS;
+ tpSirMacRadioMeasureReport pReport = NULL;
+ uint8_t num_report = 0;
+ tpRRMReq pCurrentReq = pMac->rrm.rrmPEContext.pCurrentReq;
+ tRrmRetStatus rrmStatus = eRRM_SUCCESS;
+
+ if (!pRRMReq->num_MeasurementRequest) {
+ /* No measurement requests.... */
+ /* */
+ pReport = cdf_mem_malloc(sizeof(tSirMacRadioMeasureReport));
+ if (NULL == pReport) {
+ lim_log(pMac, LOGP,
+ FL
+ ("Unable to allocate memory during RRM Req processing"));
+ return eSIR_MEM_ALLOC_FAILED;
+ }
+ cdf_mem_set(pReport, sizeof(tSirMacRadioMeasureReport), 0);
+ PELOGE(lim_log(pMac, LOGE,
+ FL
+ ("No requestIes in the measurement request, sending incapable report"));
+ )
+ pReport->incapable = 1;
+ num_report = 1;
+ lim_send_radio_measure_report_action_frame(pMac,
+ pRRMReq->DialogToken.token,
+ num_report, pReport, peer,
+ pSessionEntry);
+ cdf_mem_free(pReport);
+ return eSIR_FAILURE;
+ }
+ /* PF Fix */
+ if (pRRMReq->NumOfRepetitions.repetitions > 0) {
+ lim_log(pMac, LOG1,
+ FL(" number of repetitions %d"),
+ pRRMReq->NumOfRepetitions.repetitions);
+
+ /* Send a report with incapable bit set. Not supporting repetitions. */
+ pReport = cdf_mem_malloc(sizeof(tSirMacRadioMeasureReport));
+ if (NULL == pReport) {
+ lim_log(pMac, LOGP,
+ FL
+ ("Unable to allocate memory during RRM Req processing"));
+ return eSIR_MEM_ALLOC_FAILED;
+ }
+ cdf_mem_set(pReport, sizeof(tSirMacRadioMeasureReport), 0);
+ PELOGE(lim_log(pMac, LOGE, FL(" Allocated memory for pReport"));)
+ pReport->incapable = 1;
+ pReport->type = pRRMReq->MeasurementRequest[0].measurement_type;
+ num_report = 1;
+ goto end;
+
+ }
+
+ for (i = 0; i < pRRMReq->num_MeasurementRequest; i++) {
+ switch (pRRMReq->MeasurementRequest[i].measurement_type) {
+ case SIR_MAC_RRM_BEACON_TYPE:
+ /* Process beacon request. */
+ if (pCurrentReq) {
+ if (pReport == NULL) /* Allocate memory to send reports for any subsequent requests. */
+ {
+ pReport =
+ cdf_mem_malloc(sizeof
+ (tSirMacRadioMeasureReport)
+ *
+ (pRRMReq->
+ num_MeasurementRequest
+ - i));
+ if (NULL == pReport) {
+ lim_log(pMac, LOGP,
+ FL
+ ("Unable to allocate memory during RRM Req processing"));
+ return eSIR_MEM_ALLOC_FAILED;
+ }
+ cdf_mem_set(pReport,
+ sizeof
+ (tSirMacRadioMeasureReport)
+ *
+ (pRRMReq->
+ num_MeasurementRequest -
+ i), 0);
+ lim_log(pMac, LOG3,
+ FL
+ (" rrm beacon type refused of %d report in beacon table"),
+ num_report);
+
+ }
+ pReport[num_report].refused = 1;
+ pReport[num_report].type =
+ SIR_MAC_RRM_BEACON_TYPE;
+ pReport[num_report].token =
+ pRRMReq->MeasurementRequest[i].
+ measurement_token;
+ num_report++;
+ continue;
+ } else {
+ pCurrentReq =
+ cdf_mem_malloc(sizeof(*pCurrentReq));
+ if (NULL == pCurrentReq) {
+ lim_log(pMac, LOGP,
+ FL
+ ("Unable to allocate memory during RRM Req processing"));
+ cdf_mem_free(pReport);
+ return eSIR_MEM_ALLOC_FAILED;
+ }
+ lim_log(pMac, LOG3,
+ FL(" Processing Beacon Report request"));
+ cdf_mem_set(pCurrentReq, sizeof(*pCurrentReq),
+ 0);
+ pCurrentReq->dialog_token =
+ pRRMReq->DialogToken.token;
+ pCurrentReq->token =
+ pRRMReq->MeasurementRequest[i].
+ measurement_token;
+ pCurrentReq->sendEmptyBcnRpt = true;
+ pMac->rrm.rrmPEContext.pCurrentReq =
+ pCurrentReq;
+ rrmStatus =
+ rrm_process_beacon_report_req(pMac, pCurrentReq,
+ &pRRMReq->
+ MeasurementRequest
+ [i],
+ pSessionEntry);
+ if (eRRM_SUCCESS != rrmStatus) {
+ rrm_process_beacon_request_failure(pMac,
+ pSessionEntry,
+ peer,
+ rrmStatus);
+ rrm_cleanup(pMac);
+ }
+ }
+ break;
+ case SIR_MAC_RRM_LCI_TYPE:
+ case SIR_MAC_RRM_LOCATION_CIVIC_TYPE:
+ case SIR_MAC_RRM_FINE_TIME_MEAS_TYPE:
+ lim_log(pMac, LOG1,
+ FL("RRM with type: %d sent to userspace"),
+ pRRMReq->MeasurementRequest[i].measurement_type);
+ break;
+ default:
+ /* Send a report with incapabale bit set. */
+ if (pReport == NULL) /* Allocate memory to send reports for any subsequent requests. */
+ {
+ pReport =
+ cdf_mem_malloc(sizeof
+ (tSirMacRadioMeasureReport)
+ *
+ (pRRMReq->
+ num_MeasurementRequest -
+ i));
+ if (NULL == pReport) {
+ lim_log(pMac, LOGP,
+ FL
+ ("Unable to allocate memory during RRM Req processing"));
+ return eSIR_MEM_ALLOC_FAILED;
+ }
+ cdf_mem_set(pReport,
+ sizeof(tSirMacRadioMeasureReport)
+ * (pRRMReq->num_MeasurementRequest -
+ i), 0);
+ lim_log(pMac, LOG3,
+ FL
+ ("rrm beacon type incapable of %d report "),
+ num_report);
+ }
+ pReport[num_report].incapable = 1;
+ pReport[num_report].type =
+ pRRMReq->MeasurementRequest[i].measurement_type;
+ pReport[num_report].token =
+ pRRMReq->MeasurementRequest[i].measurement_token;
+ num_report++;
+ break;
+ }
+ }
+
+end:
+ if (pReport) {
+ lim_send_radio_measure_report_action_frame(pMac,
+ pRRMReq->DialogToken.token,
+ num_report, pReport, peer,
+ pSessionEntry);
+
+ cdf_mem_free(pReport);
+ lim_log(pMac, LOG3, FL(" Free memory for pReport"));
+ }
+ return status;
+
+}
+
+/* -------------------------------------------------------------------- */
+/**
+ * rrm_update_start_tsf
+ **
+ * FUNCTION: Store start TSF of measurement.
+ *
+ * LOGIC:
+ *
+ * ASSUMPTIONS:
+ *
+ * NOTE:
+ *
+ * @param startTSF - TSF value at the start of measurement.
+ * @return None
+ */
+void rrm_update_start_tsf(tpAniSirGlobal pMac, uint32_t startTSF[2])
+{
+ pMac->rrm.rrmPEContext.startTSF[0] = startTSF[0];
+ pMac->rrm.rrmPEContext.startTSF[1] = startTSF[1];
+}
+
+/* -------------------------------------------------------------------- */
+/**
+ * rrm_get_start_tsf
+ *
+ * FUNCTION: Get the Start TSF.
+ *
+ * LOGIC:
+ *
+ * ASSUMPTIONS:
+ *
+ * NOTE:
+ *
+ * @param startTSF - store star TSF in this buffer.
+ * @return txPower
+ */
+void rrm_get_start_tsf(tpAniSirGlobal pMac, uint32_t *pStartTSF)
+{
+ pStartTSF[0] = pMac->rrm.rrmPEContext.startTSF[0];
+ pStartTSF[1] = pMac->rrm.rrmPEContext.startTSF[1];
+
+}
+
+/* -------------------------------------------------------------------- */
+/**
+ * rrm_get_capabilities
+ *
+ * FUNCTION:
+ * Returns a pointer to tpRRMCaps with all the caps enabled in RRM
+ *
+ * LOGIC:
+ *
+ * ASSUMPTIONS:
+ *
+ * NOTE:
+ *
+ * @param pSessionEntry
+ * @return pointer to tRRMCaps
+ */
+tpRRMCaps rrm_get_capabilities(tpAniSirGlobal pMac, tpPESession pSessionEntry)
+{
+ return &pMac->rrm.rrmPEContext.rrmEnabledCaps;
+}
+
+/* -------------------------------------------------------------------- */
+/**
+ * rrm_update_config
+ *
+ * FUNCTION:
+ * Update the configuration. This is called from lim_update_config.
+ *
+ * LOGIC:
+ *
+ * ASSUMPTIONS:
+ *
+ * NOTE:
+ *
+ * @param pSessionEntry
+ * @return pointer to tRRMCaps
+ */
+void rrm_update_config(tpAniSirGlobal pMac, tpPESession pSessionEntry)
+{
+ uint32_t val;
+ tpRRMCaps pRRMCaps = &pMac->rrm.rrmPEContext.rrmEnabledCaps;
+
+ if (wlan_cfg_get_int(pMac, WNI_CFG_RRM_ENABLED, &val) != eSIR_SUCCESS) {
+ lim_log(pMac, LOGP, FL("cfg get rrm enabled failed"));
+ return;
+ }
+ pMac->rrm.rrmPEContext.rrmEnable = (val) ? 1 : 0;
+
+ if (wlan_cfg_get_int(pMac, WNI_CFG_RRM_OPERATING_CHAN_MAX, &val) !=
+ eSIR_SUCCESS) {
+ lim_log(pMac, LOGP,
+ FL
+ ("cfg get rrm operating channel max measurement duration failed"));
+ return;
+ }
+ pRRMCaps->operatingChanMax = (uint8_t) val;
+
+ if (wlan_cfg_get_int(pMac, WNI_CFG_RRM_NON_OPERATING_CHAN_MAX, &val) !=
+ eSIR_SUCCESS) {
+ lim_log(pMac, LOGP,
+ FL
+ ("cfg get rrm non-operating channel max measurement duration failed"));
+ return;
+ }
+ pRRMCaps->nonOperatingChanMax = (uint8_t) val;
+
+ lim_log(pMac, LOG1,
+ "RRM enabled = %d OperatingChanMax = %d NonOperatingMax = %d",
+ pMac->rrm.rrmPEContext.rrmEnable,
+ pRRMCaps->operatingChanMax, pRRMCaps->nonOperatingChanMax);
+}
+
+/* -------------------------------------------------------------------- */
+/**
+ * rrm_initialize
+ *
+ * FUNCTION:
+ * Initialize RRM module
+ *
+ * LOGIC:
+ *
+ * ASSUMPTIONS:
+ *
+ * NOTE:
+ *
+ * @return None
+ */
+
+tSirRetStatus rrm_initialize(tpAniSirGlobal pMac)
+{
+ tpRRMCaps pRRMCaps = &pMac->rrm.rrmPEContext.rrmEnabledCaps;
+
+ pMac->rrm.rrmPEContext.pCurrentReq = NULL;
+ pMac->rrm.rrmPEContext.txMgmtPower = 0;
+ pMac->rrm.rrmPEContext.DialogToken = 0;
+
+ pMac->rrm.rrmPEContext.rrmEnable = 0;
+
+ cdf_mem_set(pRRMCaps, sizeof(tRRMCaps), 0);
+ pRRMCaps->LinkMeasurement = 1;
+ pRRMCaps->NeighborRpt = 1;
+ pRRMCaps->BeaconPassive = 1;
+ pRRMCaps->BeaconActive = 1;
+ pRRMCaps->BeaconTable = 1;
+ pRRMCaps->APChanReport = 1;
+ pRRMCaps->fine_time_meas_rpt = 1;
+ pRRMCaps->lci_capability = 1;
+
+ pRRMCaps->operatingChanMax = 3;
+ pRRMCaps->nonOperatingChanMax = 3;
+
+ return eSIR_SUCCESS;
+}
+
+/* -------------------------------------------------------------------- */
+/**
+ * rrm_cleanup
+ *
+ * FUNCTION:
+ * cleanup RRM module
+ *
+ * LOGIC:
+ *
+ * ASSUMPTIONS:
+ *
+ * NOTE:
+ *
+ * @param mode
+ * @param rate
+ * @return None
+ */
+
+tSirRetStatus rrm_cleanup(tpAniSirGlobal pMac)
+{
+ if (pMac->rrm.rrmPEContext.pCurrentReq) {
+ if (pMac->rrm.rrmPEContext.pCurrentReq->request.Beacon.reqIes.
+ pElementIds) {
+ cdf_mem_free(pMac->rrm.rrmPEContext.pCurrentReq->
+ request.Beacon.reqIes.pElementIds);
+ lim_log(pMac, LOG4, FL(" Free memory for pElementIds"));
+ }
+
+ cdf_mem_free(pMac->rrm.rrmPEContext.pCurrentReq);
+ lim_log(pMac, LOG4, FL(" Free memory for pCurrentReq"));
+ }
+
+ pMac->rrm.rrmPEContext.pCurrentReq = NULL;
+ return eSIR_SUCCESS;
+}
+
+/* -------------------------------------------------------------------- */
+/**
+ * rrm_process_message
+ *
+ * FUNCTION: Processes the next received Radio Resource Management message
+ *
+ * LOGIC:
+ *
+ * ASSUMPTIONS:
+ *
+ * NOTE:
+ *
+ * @param None
+ * @return None
+ */
+
+void rrm_process_message(tpAniSirGlobal pMac, tpSirMsgQ pMsg)
+{
+ switch (pMsg->type) {
+ case eWNI_SME_NEIGHBOR_REPORT_REQ_IND:
+ rrm_process_neighbor_report_req(pMac, pMsg->bodyptr);
+ break;
+ case eWNI_SME_BEACON_REPORT_RESP_XMIT_IND:
+ rrm_process_beacon_report_xmit(pMac, pMsg->bodyptr);
+ break;
+ }
+
+}
+
+#endif
diff --git a/core/mac/src/pe/sch/sch_api.c b/core/mac/src/pe/sch/sch_api.c
new file mode 100644
index 0000000..1a11104
--- /dev/null
+++ b/core/mac/src/pe/sch/sch_api.c
@@ -0,0 +1,625 @@
+/*
+ * Copyright (c) 2011-2015 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 sch_api.cc contains functions related to the API exposed
+ * by scheduler module
+ *
+ * Author: Sandesh Goel
+ * Date: 02/25/02
+ * History:-
+ * Date Modified by Modification Information
+ * --------------------------------------------------------------------
+ *
+ */
+#include "cds_api.h"
+#include "ani_global.h"
+#include "wni_cfg.h"
+
+#include "sir_mac_prot_def.h"
+#include "sir_mac_prop_exts.h"
+#include "sir_common.h"
+
+#include "cfg_api.h"
+
+#include "lim_api.h"
+
+#include "sch_api.h"
+#include "sch_debug.h"
+
+#include "sch_sys_params.h"
+#include "lim_trace.h"
+#include "lim_types.h"
+
+#include "wma_types.h"
+
+/* -------------------------------------------------------------------- */
+/* */
+/* Static Variables */
+/* */
+/* ------------------------------------------------------------------- */
+
+/* -------------------------------------------------------------------- */
+/**
+ * sch_get_cfp_count
+ *
+ * FUNCTION:
+ * Function used by other Sirius modules to read CFPcount
+ *
+ * LOGIC:
+ *
+ * ASSUMPTIONS:
+ *
+ * NOTE:
+ *
+ * @param None
+ * @return None
+ */
+
+uint8_t sch_get_cfp_count(tpAniSirGlobal pMac)
+{
+ return pMac->sch.schObject.gSchCFPCount;
+}
+
+/* -------------------------------------------------------------------- */
+/**
+ * sch_get_cfp_dur_remaining
+ *
+ * FUNCTION:
+ * Function used by other Sirius modules to read CFPDuration remaining
+ *
+ * LOGIC:
+ *
+ * ASSUMPTIONS:
+ *
+ * NOTE:
+ *
+ * @param None
+ * @return None
+ */
+
+uint16_t sch_get_cfp_dur_remaining(tpAniSirGlobal pMac)
+{
+ return pMac->sch.schObject.gSchCFPDurRemaining;
+}
+
+/* -------------------------------------------------------------------- */
+/**
+ * sch_init_globals
+ *
+ * FUNCTION:
+ * Initialize globals
+ *
+ * LOGIC:
+ *
+ * ASSUMPTIONS:
+ *
+ * NOTE:
+ *
+ * @param None
+ * @return None
+ */
+
+void sch_init_globals(tpAniSirGlobal pMac)
+{
+ pMac->sch.gSchHcfEnabled = false;
+
+ pMac->sch.gSchScanRequested = false;
+ pMac->sch.gSchScanReqRcvd = false;
+
+ pMac->sch.gSchGenBeacon = 1;
+ pMac->sch.gSchBeaconsSent = 0;
+ pMac->sch.gSchBeaconsWritten = 0;
+ pMac->sch.gSchBcnParseErrorCnt = 0;
+ pMac->sch.gSchBcnIgnored = 0;
+ pMac->sch.gSchBBXportRcvCnt = 0;
+ pMac->sch.gSchUnknownRcvCnt = 0;
+ pMac->sch.gSchBcnRcvCnt = 0;
+ pMac->sch.gSchRRRcvCnt = 0;
+ pMac->sch.qosNullCnt = 0;
+ pMac->sch.numData = 0;
+ pMac->sch.numPoll = 0;
+ pMac->sch.numCorrupt = 0;
+ pMac->sch.numBogusInt = 0;
+ pMac->sch.numTxAct0 = 0;
+ pMac->sch.rrTimeout = SCH_RR_TIMEOUT;
+ pMac->sch.pollPeriod = SCH_POLL_PERIOD;
+ pMac->sch.multipleSched = 1;
+ pMac->sch.maxPollTimeouts = 20;
+ pMac->sch.checkCfbFlagStuck = 0;
+}
+
+/* -------------------------------------------------------------------- */
+/**
+ * sch_post_message
+ *
+ * FUNCTION:
+ * Post the beacon message to the scheduler message queue
+ *
+ * LOGIC:
+ *
+ * ASSUMPTIONS:
+ *
+ * NOTE:
+ *
+ * @param pMsg pointer to message
+ * @return None
+ */
+
+tSirRetStatus sch_post_message(tpAniSirGlobal pMac, tpSirMsgQ pMsg)
+{
+ sch_process_message(pMac, pMsg);
+
+ return eSIR_SUCCESS;
+}
+
+/* --------------------------------------------------------------------------- */
+/**
+ * sch_send_start_scan_rsp
+ *
+ * FUNCTION:
+ *
+ * LOGIC:
+ *
+ * ASSUMPTIONS:
+ *
+ * NOTE:
+ *
+ * @param None
+ * @return None
+ */
+
+void sch_send_start_scan_rsp(tpAniSirGlobal pMac)
+{
+ tSirMsgQ msgQ;
+ uint32_t retCode;
+
+ PELOG1(sch_log(pMac, LOG1, FL("Sending LIM message to go into scan"));)
+ msgQ.type = SIR_SCH_START_SCAN_RSP;
+ if ((retCode = lim_post_msg_api(pMac, &msgQ)) != eSIR_SUCCESS)
+ sch_log(pMac, LOGE,
+ FL("Posting START_SCAN_RSP to LIM failed, reason=%X"),
+ retCode);
+}
+
+/**
+ * sch_send_beacon_req
+ *
+ * FUNCTION:
+ *
+ * LOGIC:
+ * 1) SCH received SIR_SCH_BEACON_GEN_IND
+ * 2) SCH updates TIM IE and other beacon related IE's
+ * 3) SCH sends WMA_SEND_BEACON_REQ to HAL. HAL then copies the beacon
+ * template to memory
+ *
+ * ASSUMPTIONS:
+ * Memory allocation is reqd to send this message and SCH allocates memory.
+ * The assumption is that HAL will "free" this memory.
+ *
+ * NOTE:
+ *
+ * @param pMac global
+ *
+ * @param beaconPayload
+ *
+ * @param size - Length of the beacon
+ *
+ * @return CDF_STATUS
+ */
+tSirRetStatus sch_send_beacon_req(tpAniSirGlobal pMac, uint8_t *beaconPayload,
+ uint16_t size, tpPESession psessionEntry)
+{
+ tSirMsgQ msgQ;
+ tpSendbeaconParams beaconParams = NULL;
+ tSirRetStatus retCode;
+
+ sch_log(pMac, LOG2,
+ FL
+ ("Indicating HAL to copy the beacon template [%d bytes] to memory"),
+ size);
+
+ beaconParams = cdf_mem_malloc(sizeof(tSendbeaconParams));
+ if (NULL == beaconParams)
+ return eSIR_MEM_ALLOC_FAILED;
+
+ msgQ.type = WMA_SEND_BEACON_REQ;
+
+ /* No Dialog Token reqd, as a response is not solicited */
+ msgQ.reserved = 0;
+
+ /* Fill in tSendbeaconParams members */
+ cdf_mem_copy(beaconParams->bssId, psessionEntry->bssId,
+ sizeof(psessionEntry->bssId));
+
+ if (LIM_IS_IBSS_ROLE(psessionEntry)) {
+ beaconParams->timIeOffset = 0;
+ } else {
+ beaconParams->timIeOffset = psessionEntry->schBeaconOffsetBegin;
+ }
+
+ /* p2pIeOffset should be atleast greater than timIeOffset */
+ if ((pMac->sch.schObject.p2pIeOffset != 0) &&
+ (pMac->sch.schObject.p2pIeOffset <
+ psessionEntry->schBeaconOffsetBegin)) {
+ sch_log(pMac, LOGE, FL("Invalid p2pIeOffset:[%d]"),
+ pMac->sch.schObject.p2pIeOffset);
+ CDF_ASSERT(0);
+ cdf_mem_free(beaconParams);
+ return eSIR_FAILURE;
+ }
+ beaconParams->p2pIeOffset = pMac->sch.schObject.p2pIeOffset;
+#ifdef WLAN_SOFTAP_FW_BEACON_TX_PRNT_LOG
+ sch_log(pMac, LOGE, FL("TimIeOffset:[%d]"), beaconParams->TimIeOffset);
+#endif
+
+ beaconParams->beacon = beaconPayload;
+ beaconParams->beaconLength = (uint32_t) size;
+ msgQ.bodyptr = beaconParams;
+ msgQ.bodyval = 0;
+
+ /* Keep a copy of recent beacon frame sent */
+
+ /* free previous copy of the beacon */
+ if (psessionEntry->beacon) {
+ cdf_mem_free(psessionEntry->beacon);
+ }
+
+ psessionEntry->bcnLen = 0;
+ psessionEntry->beacon = NULL;
+
+ psessionEntry->beacon = cdf_mem_malloc(size);
+ if (psessionEntry->beacon != NULL) {
+ cdf_mem_copy(psessionEntry->beacon, beaconPayload, size);
+ psessionEntry->bcnLen = size;
+ }
+
+ MTRACE(mac_trace_msg_tx(pMac, psessionEntry->peSessionId, msgQ.type));
+ if (eSIR_SUCCESS != (retCode = wma_post_ctrl_msg(pMac, &msgQ))) {
+ sch_log(pMac, LOGE,
+ FL("Posting SEND_BEACON_REQ to HAL failed, reason=%X"),
+ retCode);
+ } else {
+ sch_log(pMac, LOG2,
+ FL("Successfully posted WMA_SEND_BEACON_REQ to HAL"));
+
+ if (LIM_IS_AP_ROLE(psessionEntry) &&
+ (pMac->sch.schObject.fBeaconChanged)) {
+ if (eSIR_SUCCESS !=
+ (retCode =
+ lim_send_probe_rsp_template_to_hal(pMac, psessionEntry,
+ &psessionEntry->
+ DefProbeRspIeBitmap
+ [0]))) {
+ /* check whether we have to free any memory */
+ sch_log(pMac, LOGE,
+ FL
+ ("FAILED to send probe response template with retCode %d"),
+ retCode);
+ }
+ }
+ }
+
+ return retCode;
+}
+
+uint32_t lim_remove_p2p_ie_from_add_ie(tpAniSirGlobal pMac,
+ tpPESession psessionEntry,
+ uint8_t *addIeWoP2pIe,
+ uint32_t *addnIELenWoP2pIe)
+{
+ uint32_t left = psessionEntry->addIeParams.probeRespDataLen;
+ uint8_t *ptr = psessionEntry->addIeParams.probeRespData_buff;
+ uint8_t elem_id,elem_len;
+ uint32_t offset = 0;
+ uint8_t eid = 0xDD;
+
+ cdf_mem_copy(addIeWoP2pIe, ptr, left);
+ *addnIELenWoP2pIe = left;
+
+ if (addIeWoP2pIe != NULL) {
+ while (left >= 2) {
+ elem_id = ptr[0];
+ elem_len = ptr[1];
+ left -= 2;
+ if(elem_len > left) {
+ sch_log(pMac, LOGE, FL("Invalid IEs"));
+ return eSIR_FAILURE;
+ }
+ if ((elem_id == eid) &&
+ (cdf_mem_compare(&ptr[2],
+ "\x50\x6f\x9a\x09", 4))) {
+ left -= elem_len;
+ ptr += (elem_len + 2);
+ cdf_mem_copy(&addIeWoP2pIe[offset], ptr, left);
+ *addnIELenWoP2pIe -= (2 + elem_len);
+ } else {
+ left -= elem_len;
+ ptr += (elem_len + 2);
+ offset += 2 + elem_len;
+ }
+ }
+ }
+ return eSIR_SUCCESS;
+}
+
+uint32_t lim_send_probe_rsp_template_to_hal(tpAniSirGlobal pMac,
+ tpPESession psessionEntry,
+ uint32_t *IeBitmap)
+{
+ tSirMsgQ msgQ;
+ uint8_t *pFrame2Hal = psessionEntry->pSchProbeRspTemplate;
+ tpSendProbeRespParams pprobeRespParams = NULL;
+ uint32_t retCode = eSIR_FAILURE;
+ uint32_t nPayload, nBytes, nStatus;
+ tpSirMacMgmtHdr pMacHdr;
+ uint32_t addnIEPresent = false;
+ uint32_t addnIELen = 0;
+ uint8_t *addIE = NULL;
+ uint8_t *addIeWoP2pIe = NULL;
+ uint32_t addnIELenWoP2pIe = 0;
+ uint32_t retStatus;
+
+ nStatus =
+ dot11f_get_packed_probe_response_size(pMac,
+ &psessionEntry->probeRespFrame,
+ &nPayload);
+ if (DOT11F_FAILED(nStatus)) {
+ sch_log(pMac, LOGE, FL("Failed to calculate the packed size f"
+ "or a Probe Response (0x%08x)."),
+ nStatus);
+ /* We'll fall back on the worst case scenario: */
+ nPayload = sizeof(tDot11fProbeResponse);
+ } else if (DOT11F_WARNED(nStatus)) {
+ sch_log(pMac, LOGE, FL("There were warnings while calculating"
+ "the packed size for a Probe Response "
+ "(0x%08x)."), nStatus);
+ }
+
+ nBytes = nPayload + sizeof(tSirMacMgmtHdr);
+
+ /* Check if probe response IE is present or not */
+ addnIEPresent = (psessionEntry->addIeParams.probeRespDataLen != 0);
+ if (addnIEPresent) {
+ /*
+ * probe response template should not have P2P IE.
+ * In case probe request has P2P IE or WPS IE, the
+ * probe request will be forwarded to the Host and
+ * Host will send the probe response. In other cases
+ * FW will send the probe response. So, if the template
+ * has P2P IE, the probe response sent to non P2P devices
+ * by the FW, may also have P2P IE which will fail
+ * P2P cert case 6.1.3
+ */
+ addIeWoP2pIe = cdf_mem_malloc(psessionEntry->addIeParams.
+ probeRespDataLen);
+ if (NULL == addIeWoP2pIe) {
+ sch_log(pMac, LOGE,
+ FL("FAILED to alloc memory when removing P2P IE"));
+ return eSIR_MEM_ALLOC_FAILED;
+ }
+
+ retStatus = lim_remove_p2p_ie_from_add_ie(pMac, psessionEntry,
+ addIeWoP2pIe, &addnIELenWoP2pIe);
+ if (retStatus != eSIR_SUCCESS) {
+ cdf_mem_free(addIeWoP2pIe);
+ return eSIR_FAILURE;
+ }
+
+ /* Probe rsp IE available */
+ /*need to check the data length */
+ addIE =
+ cdf_mem_malloc(addnIELenWoP2pIe);
+ if (NULL == addIE) {
+ sch_log(pMac, LOGE,
+ FL
+ ("Unable to get WNI_CFG_PROBE_RSP_ADDNIE_DATA1 length"));
+ cdf_mem_free(addIeWoP2pIe);
+ return eSIR_MEM_ALLOC_FAILED;
+ }
+ addnIELen = addnIELenWoP2pIe;
+
+ if (addnIELen <= WNI_CFG_PROBE_RSP_ADDNIE_DATA1_LEN && addnIELen
+ && (nBytes + addnIELen) <= SIR_MAX_PACKET_SIZE) {
+
+ cdf_mem_copy(addIE,
+ addIeWoP2pIe,
+ addnIELenWoP2pIe);
+ }
+ cdf_mem_free(addIeWoP2pIe);
+ }
+
+ if (addnIEPresent) {
+ if ((nBytes + addnIELen) <= SIR_MAX_PACKET_SIZE)
+ nBytes += addnIELen;
+ else
+ addnIEPresent = false; /* Dont include the IE. */
+ }
+ /* Paranoia: */
+ cdf_mem_set(pFrame2Hal, nBytes, 0);
+
+ /* Next, we fill out the buffer descriptor: */
+ lim_populate_mac_header(pMac, pFrame2Hal, SIR_MAC_MGMT_FRAME,
+ SIR_MAC_MGMT_PROBE_RSP,
+ psessionEntry->selfMacAddr,
+ psessionEntry->selfMacAddr);
+
+ pMacHdr = (tpSirMacMgmtHdr) pFrame2Hal;
+
+ sir_copy_mac_addr(pMacHdr->bssId, psessionEntry->bssId);
+
+ /* That done, pack the Probe Response: */
+ nStatus =
+ dot11f_pack_probe_response(pMac, &psessionEntry->probeRespFrame,
+ pFrame2Hal + sizeof(tSirMacMgmtHdr),
+ nPayload, &nPayload);
+
+ if (DOT11F_FAILED(nStatus)) {
+ sch_log(pMac, LOGE,
+ FL("Failed to pack a Probe Response (0x%08x)."),
+ nStatus);
+
+ cdf_mem_free(addIE);
+ return retCode; /* allocated! */
+ } else if (DOT11F_WARNED(nStatus)) {
+ sch_log(pMac, LOGE, FL("There were warnings while packing a P"
+ "robe Response (0x%08x)."), nStatus);
+ }
+
+ if (addnIEPresent) {
+ cdf_mem_copy(&pFrame2Hal[nBytes - addnIELen],
+ &addIE[0], addnIELen);
+ }
+
+ /* free the allocated Memory */
+ cdf_mem_free(addIE);
+
+ pprobeRespParams = cdf_mem_malloc(sizeof(tSendProbeRespParams));
+ if (NULL == pprobeRespParams) {
+ sch_log(pMac, LOGE,
+ FL
+ ("lim_send_probe_rsp_template_to_hal: HAL probe response params malloc failed for bytes %d"),
+ nBytes);
+ } else {
+ sir_copy_mac_addr(pprobeRespParams->bssId, psessionEntry->bssId);
+ pprobeRespParams->pProbeRespTemplate = pFrame2Hal;
+ pprobeRespParams->probeRespTemplateLen = nBytes;
+ cdf_mem_copy(pprobeRespParams->ucProxyProbeReqValidIEBmap,
+ IeBitmap, (sizeof(uint32_t) * 8));
+ msgQ.type = WMA_SEND_PROBE_RSP_TMPL;
+ msgQ.reserved = 0;
+ msgQ.bodyptr = pprobeRespParams;
+ msgQ.bodyval = 0;
+
+ if (eSIR_SUCCESS != (retCode = wma_post_ctrl_msg(pMac, &msgQ))) {
+ /* free the allocated Memory */
+ sch_log(pMac, LOGE,
+ FL
+ ("lim_send_probe_rsp_template_to_hal: FAIL bytes %d retcode[%X]"),
+ nBytes, retCode);
+ cdf_mem_free(pprobeRespParams);
+ } else {
+ sch_log(pMac, LOG1,
+ FL
+ ("lim_send_probe_rsp_template_to_hal: Probe response template msg posted to HAL of bytes %d"),
+ nBytes);
+ }
+ }
+
+ return retCode;
+}
+
+/**
+ * sch_gen_timing_advert_frame() - Generate the TA frame and populate the buffer
+ * @pMac: the global MAC context
+ * @self_addr: the self MAC address
+ * @buf: the buffer that will contain the frame
+ * @timestamp_offset: return for the offset of the timestamp field
+ * @time_value_offset: return for the time_value field in the TA IE
+ *
+ * Return: the length of the buffer.
+ */
+int sch_gen_timing_advert_frame(tpAniSirGlobal mac_ctx, tSirMacAddr self_addr,
+ uint8_t **buf, uint32_t *timestamp_offset, uint32_t *time_value_offset)
+{
+ tDot11fTimingAdvertisementFrame frame;
+ uint32_t payload_size, buf_size;
+ int status;
+ struct cdf_mac_addr wildcard_bssid = {
+ {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
+ };
+
+ cdf_mem_zero((uint8_t *)&frame, sizeof(tDot11fTimingAdvertisementFrame));
+
+ /* Populate the TA fields */
+ status = populate_dot11f_timing_advert_frame(mac_ctx, &frame);
+ if (status) {
+ sch_log(mac_ctx, LOGE, FL("Error populating TA frame %x"),
+ status);
+ return status;
+ }
+
+ status = dot11f_get_packed_timing_advertisement_frame_size(mac_ctx,
+ &frame, &payload_size);
+ if (DOT11F_FAILED(status)) {
+ sch_log(mac_ctx, LOGE, FL("Error getting packed frame size %x"),
+ status);
+ return status;
+ } else if (DOT11F_WARNED(status)) {
+ sch_log(mac_ctx, LOGW, FL("Warning getting packed frame size"));
+ }
+
+ buf_size = sizeof(tSirMacMgmtHdr) + payload_size;
+ *buf = cdf_mem_malloc(buf_size);
+ if (*buf == NULL) {
+ sch_log(mac_ctx, LOGE, FL("Cannot allocate memory"));
+ return eSIR_FAILURE;
+ }
+ cdf_mem_zero(*buf, buf_size);
+
+ payload_size = 0;
+ status = dot11f_pack_timing_advertisement_frame(mac_ctx, &frame,
+ *buf + sizeof(tSirMacMgmtHdr), buf_size -
+ sizeof(tSirMacMgmtHdr), &payload_size);
+ sch_log(mac_ctx, LOGE, FL("TA payload size2 = %d"), payload_size);
+ if (DOT11F_FAILED(status)) {
+ sch_log(mac_ctx, LOGE, FL("Error packing frame %x"), status);
+ goto fail;
+ } else if (DOT11F_WARNED(status)) {
+ sch_log(mac_ctx, LOGE, FL("Warning packing frame"));
+ }
+
+ lim_populate_mac_header(mac_ctx, *buf, SIR_MAC_MGMT_FRAME,
+ SIR_MAC_MGMT_TIME_ADVERT, wildcard_bssid.bytes, self_addr);
+
+ /* The timestamp field is right after the header */
+ *timestamp_offset = sizeof(tSirMacMgmtHdr);
+
+ *time_value_offset = sizeof(tSirMacMgmtHdr) +
+ sizeof(tDot11fFfTimeStamp) + sizeof(tDot11fFfCapabilities);
+
+ /* Add the Country IE length */
+ dot11f_get_packed_ie_country(mac_ctx, &frame.Country,
+ time_value_offset);
+ /* Add 2 for Country IE EID and Length fields */
+ *time_value_offset += 2;
+
+ /* Add the PowerConstraint IE size */
+ if (frame.Country.present == 1)
+ *time_value_offset += 3;
+
+ /* Add the offset inside TA IE */
+ *time_value_offset += 3;
+
+ return payload_size + sizeof(tSirMacMgmtHdr);
+
+fail:
+ if (*buf)
+ cdf_mem_free(*buf);
+ return status;
+}
diff --git a/core/mac/src/pe/sch/sch_beacon_gen.c b/core/mac/src/pe/sch/sch_beacon_gen.c
new file mode 100644
index 0000000..365b349
--- /dev/null
+++ b/core/mac/src/pe/sch/sch_beacon_gen.c
@@ -0,0 +1,930 @@
+/*
+ * Copyright (c) 2012-2015 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 sch_beacon_gen.cc contains beacon generation related
+ * functions
+ *
+ * Author: Sandesh Goel
+ * Date: 02/25/02
+ * History:-
+ * Date Modified by Modification Information
+ * --------------------------------------------------------------------
+ *
+ */
+
+#include "cds_api.h"
+#include "wni_cfg.h"
+#include "ani_global.h"
+#include "sir_mac_prot_def.h"
+
+#include "lim_utils.h"
+#include "lim_api.h"
+
+#include "wma_if.h"
+#include "cfg_api.h"
+#include "sch_api.h"
+
+#include "parser_api.h"
+
+#include "sch_debug.h"
+
+/* */
+/* March 15, 2006 */
+/* Temporarily (maybe for all of Alpha-1), assuming TIM = 0 */
+/* */
+
+const uint8_t p2p_oui[] = { 0x50, 0x6F, 0x9A, 0x9 };
+
+tSirRetStatus sch_get_p2p_ie_offset(uint8_t *pExtraIe, uint32_t extraIeLen,
+ uint16_t *pP2pIeOffset)
+{
+ tSirRetStatus status = eSIR_FAILURE;
+ *pP2pIeOffset = 0;
+
+ /* Extra IE is not present */
+ if (0 == extraIeLen) {
+ return status;
+ }
+ /* Calculate the P2P IE Offset */
+ do {
+ if (*pExtraIe == 0xDD) {
+ if (cdf_mem_compare
+ ((void *)(pExtraIe + 2), &p2p_oui, sizeof(p2p_oui))) {
+ status = eSIR_SUCCESS;
+ break;
+ }
+ }
+
+ (*pP2pIeOffset)++;
+ pExtraIe++;
+ } while (--extraIeLen > 0);
+
+ return status;
+}
+
+/**
+ * sch_append_addn_ie() - adds additional IEs to frame
+ * @mac_ctx: mac global context
+ * @session: pe session pointer
+ * @frm: frame where additional IE is to be added
+ * @max_bcn_size: max beacon size
+ * @num_bytes: final size
+ *
+ * Return: status of operation
+ */
+tSirRetStatus
+sch_append_addn_ie(tpAniSirGlobal mac_ctx, tpPESession session,
+ uint8_t *frm, uint32_t max_bcn_size, uint32_t *num_bytes)
+{
+ tSirRetStatus status = eSIR_FAILURE;
+ uint32_t present, len;
+ uint8_t add_ie[WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA_LEN];
+ uint8_t *p2p_ie = NULL;
+ uint8_t noa_len = 0;
+ uint8_t noa_strm[SIR_MAX_NOA_ATTR_LEN + SIR_P2P_IE_HEADER_LEN];
+
+ present = (session->addIeParams.probeRespBCNDataLen != 0);
+ if (!present)
+ return status;
+
+ len = session->addIeParams.probeRespBCNDataLen;
+ if (!(len <= WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA_LEN && len &&
+ ((len + *num_bytes) <= max_bcn_size)))
+ return status;
+
+ cdf_mem_copy(&add_ie[0], session->addIeParams.probeRespBCNData_buff,
+ len);
+
+ p2p_ie = limGetP2pIEPtr(mac_ctx, &add_ie[0], len);
+ if ((p2p_ie != NULL) && !mac_ctx->beacon_offload) {
+ /* get NoA attribute stream P2P IE */
+ noa_len = lim_get_noa_attr_stream(mac_ctx, noa_strm, session);
+ if (noa_len) {
+ if ((noa_len + len) <=
+ WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA_LEN) {
+ cdf_mem_copy(&add_ie[len], noa_strm, noa_len);
+ len += noa_len;
+ p2p_ie[1] += noa_len;
+ } else {
+ sch_log(mac_ctx, LOGE,
+ FL("Not able to insert NoA because of length constraint"));
+ }
+ }
+ }
+ if (len <= WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA_LEN) {
+ cdf_mem_copy(frm, &add_ie[0], len);
+ *num_bytes = *num_bytes + len;
+ } else {
+ sch_log(mac_ctx, LOGW,
+ FL("Not able to insert because of len constraint %d"),
+ len);
+ }
+ return status;
+}
+
+/**
+ * sch_set_fixed_beacon_fields() - sets the fixed params in beacon frame
+ * @mac_ctx: mac global context
+ * @session: pe session entry
+ * @band: out param, band caclculated
+ * @opr_ch: operating channels
+ *
+ * Return: status of operation
+ */
+
+tSirRetStatus
+sch_set_fixed_beacon_fields(tpAniSirGlobal mac_ctx, tpPESession session)
+{
+ tpAniBeaconStruct bcn_struct = (tpAniBeaconStruct)
+ session->pSchBeaconFrameBegin;
+ tpSirMacMgmtHdr mac;
+ uint16_t offset;
+ uint8_t *ptr;
+ tDot11fBeacon1 *bcn_1;
+ tDot11fBeacon2 *bcn_2;
+ uint32_t i, n_status, n_bytes;
+ uint32_t wps_ap_enable = 0, tmp;
+ tDot11fIEWscProbeRes *wsc_prb_res;
+ uint8_t *extra_ie = NULL;
+ uint32_t extra_ie_len = 0;
+ uint16_t extra_ie_offset = 0;
+ uint16_t p2p_ie_offset = 0;
+ tSirRetStatus status = eSIR_SUCCESS;
+ bool is_vht_enabled = false;
+
+ bcn_1 = cdf_mem_malloc(sizeof(tDot11fBeacon1));
+ if (NULL == bcn_1) {
+ sch_log(mac_ctx, LOGE, FL("Failed to allocate memory"));
+ return eSIR_MEM_ALLOC_FAILED;
+ }
+
+ bcn_2 = cdf_mem_malloc(sizeof(tDot11fBeacon2));
+ if (NULL == bcn_2) {
+ sch_log(mac_ctx, LOGE, FL("Failed to allocate memory"));
+ cdf_mem_free(bcn_1);
+ return eSIR_MEM_ALLOC_FAILED;
+ }
+
+ wsc_prb_res = cdf_mem_malloc(sizeof(tDot11fIEWscProbeRes));
+ if (NULL == wsc_prb_res) {
+ sch_log(mac_ctx, LOGE, FL("Failed to allocate memory"));
+ cdf_mem_free(bcn_1);
+ cdf_mem_free(bcn_2);
+ return eSIR_MEM_ALLOC_FAILED;
+ }
+
+ sch_log(mac_ctx, LOG1, FL("Setting fixed beacon fields"));
+
+ /*
+ * First set the fixed fields:
+ * set the TFP headers, set the mac header
+ */
+ cdf_mem_set((uint8_t *) &bcn_struct->macHdr, sizeof(tSirMacMgmtHdr), 0);
+ mac = (tpSirMacMgmtHdr) &bcn_struct->macHdr;
+ mac->fc.type = SIR_MAC_MGMT_FRAME;
+ mac->fc.subType = SIR_MAC_MGMT_BEACON;
+
+ for (i = 0; i < 6; i++)
+ mac->da[i] = 0xff;
+
+ cdf_mem_copy(mac->sa, session->selfMacAddr,
+ sizeof(session->selfMacAddr));
+ cdf_mem_copy(mac->bssId, session->bssId, sizeof(session->bssId));
+
+ mac->fc.fromDS = 0;
+ mac->fc.toDS = 0;
+
+ /* Now set the beacon body */
+ cdf_mem_set((uint8_t *) bcn_1, sizeof(tDot11fBeacon1), 0);
+
+ /* Skip over the timestamp (it'll be updated later). */
+ bcn_1->BeaconInterval.interval =
+ mac_ctx->sch.schObject.gSchBeaconInterval;
+ populate_dot11f_capabilities(mac_ctx, &bcn_1->Capabilities, session);
+ if (session->ssidHidden) {
+ bcn_1->SSID.present = 1;
+ /* rest of the fileds are 0 for hidden ssid */
+ if ((session->ssId.length) &&
+ (session->ssidHidden == eHIDDEN_SSID_ZERO_CONTENTS))
+ bcn_1->SSID.num_ssid = session->ssId.length;
+ } else {
+ populate_dot11f_ssid(mac_ctx, &session->ssId, &bcn_1->SSID);
+ }
+
+ populate_dot11f_supp_rates(mac_ctx, POPULATE_DOT11F_RATES_OPERATIONAL,
+ &bcn_1->SuppRates, session);
+ populate_dot11f_ds_params(mac_ctx, &bcn_1->DSParams,
+ session->currentOperChannel);
+ populate_dot11f_ibss_params(mac_ctx, &bcn_1->IBSSParams, session);
+
+ offset = sizeof(tAniBeaconStruct);
+ ptr = session->pSchBeaconFrameBegin + offset;
+
+ if (LIM_IS_AP_ROLE(session)) {
+ /* Initialize the default IE bitmap to zero */
+ cdf_mem_set((uint8_t *) &(session->DefProbeRspIeBitmap),
+ (sizeof(uint32_t) * 8), 0);
+
+ /* Initialize the default IE bitmap to zero */
+ cdf_mem_set((uint8_t *) &(session->probeRespFrame),
+ sizeof(session->probeRespFrame), 0);
+
+ /*
+ * Can be efficiently updated whenever new IE added in Probe
+ * response in future
+ */
+ if (lim_update_probe_rsp_template_ie_bitmap_beacon1(mac_ctx,
+ bcn_1, session) != eSIR_SUCCESS)
+ sch_log(mac_ctx, LOGE,
+ FL("Failed to build ProbeRsp template"));
+ }
+
+ n_status = dot11f_pack_beacon1(mac_ctx, bcn_1, ptr,
+ SCH_MAX_BEACON_SIZE - offset, &n_bytes);
+ if (DOT11F_FAILED(n_status)) {
+ sch_log(mac_ctx, LOGE,
+ FL("Failed to packed a tDot11fBeacon1 (0x%08x.)."),
+ n_status);
+ cdf_mem_free(bcn_1);
+ cdf_mem_free(bcn_2);
+ cdf_mem_free(wsc_prb_res);
+ return eSIR_FAILURE;
+ } else if (DOT11F_WARNED(n_status)) {
+ sch_log(mac_ctx, LOGE,
+ FL("Warnings while packing a tDot11fBeacon1(0x%08x.)."),
+ n_status);
+ }
+ /*changed to correct beacon corruption */
+ cdf_mem_set((uint8_t *) bcn_2, sizeof(tDot11fBeacon2), 0);
+ session->schBeaconOffsetBegin = offset + (uint16_t) n_bytes;
+ sch_log(mac_ctx, LOG1, FL("Initialized beacon begin, offset %d"),
+ offset);
+
+ /* Initialize the 'new' fields at the end of the beacon */
+
+ if ((session->limSystemRole == eLIM_AP_ROLE) &&
+ session->dfsIncludeChanSwIe == true)
+ populate_dot_11_f_ext_chann_switch_ann(mac_ctx,
+ &bcn_2->ext_chan_switch_ann,
+ session);
+
+ populate_dot11f_country(mac_ctx, &bcn_2->Country, session);
+ if (bcn_1->Capabilities.qos)
+ populate_dot11f_edca_param_set(mac_ctx, &bcn_2->EDCAParamSet,
+ session);
+
+ if (session->lim11hEnable) {
+ populate_dot11f_power_constraints(mac_ctx,
+ &bcn_2->PowerConstraints);
+ populate_dot11f_tpc_report(mac_ctx, &bcn_2->TPCReport, session);
+ /* Need to insert channel switch announcement here */
+ if ((LIM_IS_AP_ROLE(session)
+ || LIM_IS_P2P_DEVICE_GO(session))
+ && session->dfsIncludeChanSwIe == true) {
+ /*
+ * Channel switch announcement only if radar is detected
+ * and SAP has instructed to announce channel switch IEs
+ * in beacon and probe responses
+ */
+ populate_dot11f_chan_switch_ann(mac_ctx,
+ &bcn_2->ChanSwitchAnn, session);
+
+ /*
+ * TODO: depending the CB mode, extended channel switch
+ * announcement need to be called
+ */
+ /*
+ populate_dot11f_ext_chan_switch_ann(mac_ctx,
+ &bcn_2->ExtChanSwitchAnn, session);
+ */
+#ifdef WLAN_FEATURE_11AC
+ /*
+ * TODO: If in 11AC mode, wider bw channel switch
+ * announcement needs to be called
+ */
+ /*
+ populate_dot11f_wider_bw_chan_switch_ann(mac_ctx,
+ &bcn_2->WiderBWChanSwitchAnn, session);
+ */
+#endif
+ /*
+ * Populate the Channel Switch Wrapper Element if
+ * SAP operates in 40/80 Mhz Channel Width.
+ */
+ if (true == session->dfsIncludeChanWrapperIe)
+ populate_dot11f_chan_switch_wrapper(mac_ctx,
+ &bcn_2->ChannelSwitchWrapper, session);
+ }
+ }
+
+#ifdef FEATURE_AP_MCC_CH_AVOIDANCE
+ /* populate proprietary IE for MDM device operating in AP-MCC */
+ populate_dot11f_avoid_channel_ie(mac_ctx, &bcn_2->QComVendorIE,
+ session);
+#endif /* FEATURE_AP_MCC_CH_AVOIDANCE */
+
+ if (session->dot11mode != WNI_CFG_DOT11_MODE_11B)
+ populate_dot11f_erp_info(mac_ctx, &bcn_2->ERPInfo, session);
+
+ if (session->htCapability) {
+ populate_dot11f_ht_caps(mac_ctx, session, &bcn_2->HTCaps);
+ populate_dot11f_ht_info(mac_ctx, &bcn_2->HTInfo, session);
+ }
+#ifdef WLAN_FEATURE_11AC
+ if (session->vhtCapability) {
+ sch_log(mac_ctx, LOGW, FL("Populate VHT IEs in Beacon"));
+ populate_dot11f_vht_caps(mac_ctx, session, &bcn_2->VHTCaps);
+ populate_dot11f_vht_operation(mac_ctx, session,
+ &bcn_2->VHTOperation);
+ is_vht_enabled = true;
+ /* following is for MU MIMO: we do not support it yet */
+ /*
+ populate_dot11f_vht_ext_bss_load( mac_ctx, &bcn2.VHTExtBssLoad);
+ */
+ if (session->gLimOperatingMode.present)
+ populate_dot11f_operating_mode(mac_ctx,
+ &bcn_2->OperatingMode, session);
+ }
+#endif
+ populate_dot11f_ext_cap(mac_ctx, is_vht_enabled, &bcn_2->ExtCap,
+ session);
+ populate_dot11f_ext_supp_rates(mac_ctx,
+ POPULATE_DOT11F_RATES_OPERATIONAL,
+ &bcn_2->ExtSuppRates, session);
+
+ if (session->pLimStartBssReq != NULL) {
+ populate_dot11f_wpa(mac_ctx, &session->pLimStartBssReq->rsnIE,
+ &bcn_2->WPA);
+ populate_dot11f_rsn_opaque(mac_ctx,
+ &session->pLimStartBssReq->rsnIE,
+ &bcn_2->RSNOpaque);
+ }
+
+ if (session->limWmeEnabled)
+ populate_dot11f_wmm(mac_ctx, &bcn_2->WMMInfoAp,
+ &bcn_2->WMMParams, &bcn_2->WMMCaps, session);
+ if (LIM_IS_AP_ROLE(session)) {
+ if (session->wps_state != SAP_WPS_DISABLED) {
+ populate_dot11f_beacon_wpsi_es(mac_ctx,
+ &bcn_2->WscBeacon, session);
+ }
+ } else {
+ if (wlan_cfg_get_int(mac_ctx,
+ (uint16_t) WNI_CFG_WPS_ENABLE, &tmp) != eSIR_SUCCESS)
+ sch_log(mac_ctx, LOGP, FL("Failed to cfg get id %d"),
+ WNI_CFG_WPS_ENABLE);
+
+ wps_ap_enable = tmp & WNI_CFG_WPS_ENABLE_AP;
+
+ if (wps_ap_enable)
+ populate_dot11f_wsc(mac_ctx, &bcn_2->WscBeacon);
+
+ if (mac_ctx->lim.wscIeInfo.wscEnrollmentState ==
+ eLIM_WSC_ENROLL_BEGIN) {
+ populate_dot11f_wsc_registrar_info(mac_ctx,
+ &bcn_2->WscBeacon);
+ mac_ctx->lim.wscIeInfo.wscEnrollmentState =
+ eLIM_WSC_ENROLL_IN_PROGRESS;
+ }
+
+ if (mac_ctx->lim.wscIeInfo.wscEnrollmentState ==
+ eLIM_WSC_ENROLL_END) {
+ de_populate_dot11f_wsc_registrar_info(mac_ctx,
+ &bcn_2->WscBeacon);
+ mac_ctx->lim.wscIeInfo.wscEnrollmentState =
+ eLIM_WSC_ENROLL_NOOP;
+ }
+ }
+
+ if ((LIM_IS_AP_ROLE(session))) {
+ /*
+ * Can be efficiently updated whenever new IE added in Probe
+ * response in future
+ */
+ lim_update_probe_rsp_template_ie_bitmap_beacon2(mac_ctx, bcn_2,
+ &session->DefProbeRspIeBitmap[0],
+ &session->probeRespFrame);
+
+ /* update probe response WPS IE instead of beacon WPS IE */
+ if (session->wps_state != SAP_WPS_DISABLED) {
+ if (session->APWPSIEs.SirWPSProbeRspIE.FieldPresent)
+ populate_dot11f_probe_res_wpsi_es(mac_ctx,
+ wsc_prb_res, session);
+ else
+ wsc_prb_res->present = 0;
+ if (wsc_prb_res->present) {
+ set_probe_rsp_ie_bitmap(
+ &session->DefProbeRspIeBitmap[0],
+ SIR_MAC_WPA_EID);
+ cdf_mem_copy((void *)
+ &session->probeRespFrame.WscProbeRes,
+ (void *)wsc_prb_res,
+ sizeof(tDot11fIEWscProbeRes));
+ }
+ }
+
+ }
+
+ n_status = dot11f_pack_beacon2(mac_ctx, bcn_2,
+ session->pSchBeaconFrameEnd,
+ SCH_MAX_BEACON_SIZE, &n_bytes);
+ if (DOT11F_FAILED(n_status)) {
+ sch_log(mac_ctx, LOGE,
+ FL("Failed to packed a tDot11fBeacon2 (0x%08x.)."),
+ n_status);
+ cdf_mem_free(bcn_1);
+ cdf_mem_free(bcn_2);
+ cdf_mem_free(wsc_prb_res);
+ return eSIR_FAILURE;
+ } else if (DOT11F_WARNED(n_status)) {
+ sch_log(mac_ctx, LOGE,
+ FL("Warnings while packing a tDot11fBeacon2(0x%08x.)."),
+ n_status);
+ }
+
+ extra_ie = session->pSchBeaconFrameEnd + n_bytes;
+ extra_ie_offset = n_bytes;
+ /* TODO: Append additional IE here. */
+ sch_append_addn_ie(mac_ctx, session,
+ session->pSchBeaconFrameEnd + n_bytes,
+ SCH_MAX_BEACON_SIZE, &n_bytes);
+ session->schBeaconOffsetEnd = (uint16_t) n_bytes;
+ extra_ie_len = n_bytes - extra_ie_offset;
+ /* Get the p2p Ie Offset */
+ status = sch_get_p2p_ie_offset(extra_ie, extra_ie_len, &p2p_ie_offset);
+ if (eSIR_SUCCESS == status)
+ /* Update the P2P Ie Offset */
+ mac_ctx->sch.schObject.p2pIeOffset =
+ session->schBeaconOffsetBegin + TIM_IE_SIZE +
+ extra_ie_offset + p2p_ie_offset;
+ else
+ mac_ctx->sch.schObject.p2pIeOffset = 0;
+
+ sch_log(mac_ctx, LOG1, FL("Initialized beacon end, offset %d"),
+ session->schBeaconOffsetEnd);
+ mac_ctx->sch.schObject.fBeaconChanged = 1;
+ cdf_mem_free(bcn_1);
+ cdf_mem_free(bcn_2);
+ cdf_mem_free(wsc_prb_res);
+ return eSIR_SUCCESS;
+}
+
+tSirRetStatus lim_update_probe_rsp_template_ie_bitmap_beacon1(tpAniSirGlobal pMac,
+ tDot11fBeacon1 *beacon1,
+ tpPESession
+ psessionEntry)
+{
+ uint32_t *DefProbeRspIeBitmap;
+ tDot11fProbeResponse *prb_rsp;
+ if (!psessionEntry) {
+ sch_log(pMac, LOGE, FL("PESession is null!"));
+ return eSIR_FAILURE;
+ }
+ DefProbeRspIeBitmap = &psessionEntry->DefProbeRspIeBitmap[0];
+ prb_rsp = &psessionEntry->probeRespFrame;
+ prb_rsp->BeaconInterval = beacon1->BeaconInterval;
+ cdf_mem_copy((void *)&prb_rsp->Capabilities,
+ (void *)&beacon1->Capabilities,
+ sizeof(beacon1->Capabilities));
+
+ /* SSID */
+ if (beacon1->SSID.present) {
+ set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap, SIR_MAC_SSID_EID);
+ /* populating it, because probe response has to go with SSID even in hidden case */
+ populate_dot11f_ssid(pMac, &psessionEntry->ssId, &prb_rsp->SSID);
+ }
+ /* supported rates */
+ if (beacon1->SuppRates.present) {
+ set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap, SIR_MAC_RATESET_EID);
+ cdf_mem_copy((void *)&prb_rsp->SuppRates,
+ (void *)&beacon1->SuppRates,
+ sizeof(beacon1->SuppRates));
+
+ }
+ /* DS Parameter set */
+ if (beacon1->DSParams.present) {
+ set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap,
+ SIR_MAC_DS_PARAM_SET_EID);
+ cdf_mem_copy((void *)&prb_rsp->DSParams,
+ (void *)&beacon1->DSParams,
+ sizeof(beacon1->DSParams));
+
+ }
+
+ /* IBSS params will not be present in the Beacons transmitted by AP */
+ return eSIR_SUCCESS;
+}
+
+void lim_update_probe_rsp_template_ie_bitmap_beacon2(tpAniSirGlobal pMac,
+ tDot11fBeacon2 *beacon2,
+ uint32_t *DefProbeRspIeBitmap,
+ tDot11fProbeResponse *prb_rsp)
+{
+ /* IBSS parameter set - will not be present in probe response tx by AP */
+ /* country */
+ if (beacon2->Country.present) {
+ set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap, SIR_MAC_COUNTRY_EID);
+ cdf_mem_copy((void *)&prb_rsp->Country,
+ (void *)&beacon2->Country,
+ sizeof(beacon2->Country));
+
+ }
+ /* Power constraint */
+ if (beacon2->PowerConstraints.present) {
+ set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap,
+ SIR_MAC_PWR_CONSTRAINT_EID);
+ cdf_mem_copy((void *)&prb_rsp->PowerConstraints,
+ (void *)&beacon2->PowerConstraints,
+ sizeof(beacon2->PowerConstraints));
+
+ }
+ /* Channel Switch Annoouncement SIR_MAC_CHNL_SWITCH_ANN_EID */
+ if (beacon2->ChanSwitchAnn.present) {
+ set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap,
+ SIR_MAC_CHNL_SWITCH_ANN_EID);
+ cdf_mem_copy((void *)&prb_rsp->ChanSwitchAnn,
+ (void *)&beacon2->ChanSwitchAnn,
+ sizeof(beacon2->ChanSwitchAnn));
+
+ }
+
+#ifdef FEATURE_AP_MCC_CH_AVOIDANCE
+ if (beacon2->QComVendorIE.present) {
+ set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap,
+ SIR_MAC_QCOM_VENDOR_EID);
+ cdf_mem_copy((void *)&prb_rsp->QComVendorIE,
+ (void *)&beacon2->QComVendorIE,
+ sizeof(beacon2->QComVendorIE));
+ }
+#endif /* FEATURE_AP_MCC_CH_AVOIDANCE */
+
+ /* ERP information */
+ if (beacon2->ERPInfo.present) {
+ set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap, SIR_MAC_ERP_INFO_EID);
+ cdf_mem_copy((void *)&prb_rsp->ERPInfo,
+ (void *)&beacon2->ERPInfo,
+ sizeof(beacon2->ERPInfo));
+
+ }
+ /* Extended supported rates */
+ if (beacon2->ExtSuppRates.present) {
+ set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap,
+ SIR_MAC_EXTENDED_RATE_EID);
+ cdf_mem_copy((void *)&prb_rsp->ExtSuppRates,
+ (void *)&beacon2->ExtSuppRates,
+ sizeof(beacon2->ExtSuppRates));
+
+ }
+
+ /* WPA */
+ if (beacon2->WPA.present) {
+ set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap, SIR_MAC_WPA_EID);
+ cdf_mem_copy((void *)&prb_rsp->WPA, (void *)&beacon2->WPA,
+ sizeof(beacon2->WPA));
+
+ }
+
+ /* RSN */
+ if (beacon2->RSNOpaque.present) {
+ set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap, SIR_MAC_RSN_EID);
+ cdf_mem_copy((void *)&prb_rsp->RSNOpaque,
+ (void *)&beacon2->RSNOpaque,
+ sizeof(beacon2->RSNOpaque));
+ }
+
+ /* EDCA Parameter set */
+ if (beacon2->EDCAParamSet.present) {
+ set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap,
+ SIR_MAC_EDCA_PARAM_SET_EID);
+ cdf_mem_copy((void *)&prb_rsp->EDCAParamSet,
+ (void *)&beacon2->EDCAParamSet,
+ sizeof(beacon2->EDCAParamSet));
+
+ }
+ /* Vendor specific - currently no vendor specific IEs added */
+ /* Requested IEs - currently we are not processing this will be added later */
+ /* HT capability IE */
+ if (beacon2->HTCaps.present) {
+ set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap,
+ SIR_MAC_HT_CAPABILITIES_EID);
+ cdf_mem_copy((void *)&prb_rsp->HTCaps, (void *)&beacon2->HTCaps,
+ sizeof(beacon2->HTCaps));
+ }
+ /* HT Info IE */
+ if (beacon2->HTInfo.present) {
+ set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap, SIR_MAC_HT_INFO_EID);
+ cdf_mem_copy((void *)&prb_rsp->HTInfo, (void *)&beacon2->HTInfo,
+ sizeof(beacon2->HTInfo));
+ }
+#ifdef WLAN_FEATURE_11AC
+ if (beacon2->VHTCaps.present) {
+ set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap,
+ SIR_MAC_VHT_CAPABILITIES_EID);
+ cdf_mem_copy((void *)&prb_rsp->VHTCaps,
+ (void *)&beacon2->VHTCaps,
+ sizeof(beacon2->VHTCaps));
+ }
+ if (beacon2->VHTOperation.present) {
+ set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap,
+ SIR_MAC_VHT_OPERATION_EID);
+ cdf_mem_copy((void *)&prb_rsp->VHTOperation,
+ (void *)&beacon2->VHTOperation,
+ sizeof(beacon2->VHTOperation));
+ }
+ if (beacon2->VHTExtBssLoad.present) {
+ set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap,
+ SIR_MAC_VHT_EXT_BSS_LOAD_EID);
+ cdf_mem_copy((void *)&prb_rsp->VHTExtBssLoad,
+ (void *)&beacon2->VHTExtBssLoad,
+ sizeof(beacon2->VHTExtBssLoad));
+ }
+#endif
+
+ /* WMM IE */
+ if (beacon2->WMMParams.present) {
+ set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap, SIR_MAC_WPA_EID);
+ cdf_mem_copy((void *)&prb_rsp->WMMParams,
+ (void *)&beacon2->WMMParams,
+ sizeof(beacon2->WMMParams));
+ }
+ /* WMM capability - most of the case won't be present */
+ if (beacon2->WMMCaps.present) {
+ set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap, SIR_MAC_WPA_EID);
+ cdf_mem_copy((void *)&prb_rsp->WMMCaps,
+ (void *)&beacon2->WMMCaps,
+ sizeof(beacon2->WMMCaps));
+ }
+
+ /* Extended Capability */
+ if (beacon2->ExtCap.present) {
+ set_probe_rsp_ie_bitmap(DefProbeRspIeBitmap, DOT11F_EID_EXTCAP);
+ cdf_mem_copy((void *)&prb_rsp->ExtCap,
+ (void *)&beacon2->ExtCap,
+ sizeof(beacon2->ExtCap));
+ }
+
+}
+
+void set_probe_rsp_ie_bitmap(uint32_t *IeBitmap, uint32_t pos)
+{
+ uint32_t index, temp;
+
+ index = pos >> 5;
+ if (index >= 8) {
+ return;
+ }
+ temp = IeBitmap[index];
+
+ temp |= 1 << (pos & 0x1F);
+
+ IeBitmap[index] = temp;
+}
+
+/* -------------------------------------------------------------------- */
+/**
+ * write_beacon_to_memory
+ *
+ * FUNCTION:
+ *
+ * LOGIC:
+ *
+ * ASSUMPTIONS:
+ *
+ * NOTE:
+ *
+ * @param None
+ * @param size Size of the beacon to write to memory
+ * @param length Length field of the beacon to write to memory
+ * @return None
+ */
+
+void write_beacon_to_memory(tpAniSirGlobal pMac, uint16_t size, uint16_t length,
+ tpPESession psessionEntry)
+{
+ uint16_t i;
+ tpAniBeaconStruct pBeacon;
+
+ /* copy end of beacon only if length > 0 */
+ if (length > 0) {
+ for (i = 0; i < psessionEntry->schBeaconOffsetEnd; i++)
+ psessionEntry->pSchBeaconFrameBegin[size++] =
+ psessionEntry->pSchBeaconFrameEnd[i];
+ }
+ /* Update the beacon length */
+ pBeacon = (tpAniBeaconStruct) psessionEntry->pSchBeaconFrameBegin;
+ /* Do not include the beaconLength indicator itself */
+ if (length == 0) {
+ pBeacon->beaconLength = 0;
+ /* Dont copy entire beacon, Copy length field alone */
+ size = 4;
+ } else
+ pBeacon->beaconLength = (uint32_t) size - sizeof(uint32_t);
+
+ /* write size bytes from pSchBeaconFrameBegin */
+ PELOG2(sch_log(pMac, LOG2, FL("Beacon size - %d bytes"), size);)
+ PELOG2(sir_dump_buf
+ (pMac, SIR_SCH_MODULE_ID, LOG2,
+ psessionEntry->pSchBeaconFrameBegin, size);
+ )
+
+ if (!pMac->sch.schObject.fBeaconChanged)
+ return;
+
+ pMac->sch.gSchGenBeacon = 1;
+ if (pMac->sch.gSchGenBeacon) {
+ pMac->sch.gSchBeaconsSent++;
+
+ /* */
+ /* Copy beacon data to SoftMAC shared memory... */
+ /* Do this by sending a message to HAL */
+ /* */
+
+ size = (size + 3) & (~3);
+ if (eSIR_SUCCESS !=
+ sch_send_beacon_req(pMac, psessionEntry->pSchBeaconFrameBegin,
+ size, psessionEntry))
+ PELOGE(sch_log
+ (pMac, LOGE,
+ FL
+ ("sch_send_beacon_req() returned an error (zsize %d)"),
+ size);
+ )
+ else {
+ pMac->sch.gSchBeaconsWritten++;
+ }
+ }
+ pMac->sch.schObject.fBeaconChanged = 0;
+}
+
+/**
+ * sch_generate_tim
+ *
+ * FUNCTION:
+ * Generate TIM
+ *
+ * LOGIC:
+ *
+ * ASSUMPTIONS:
+ *
+ * NOTE:
+ *
+ * @param pMac pointer to global mac structure
+ * @param **pPtr pointer to the buffer, where the TIM bit is to be written.
+ * @param *timLength pointer to limLength, which needs to be returned.
+ * @return None
+ */
+void sch_generate_tim(tpAniSirGlobal pMac, uint8_t **pPtr, uint16_t *timLength,
+ uint8_t dtimPeriod)
+{
+ uint8_t *ptr = *pPtr;
+ uint32_t val = 0;
+ uint32_t minAid = 1; /* Always start with AID 1 as minimum */
+ uint32_t maxAid = HAL_NUM_STA;
+
+ /* Generate partial virtual bitmap */
+ uint8_t N1 = minAid / 8;
+ uint8_t N2 = maxAid / 8;
+ if (N1 & 1)
+ N1--;
+
+ *timLength = N2 - N1 + 4;
+ val = dtimPeriod;
+
+ /*
+ * Write 0xFF to firmware's field to detect firmware's mal-function
+ * early. DTIM count and bitmap control usually cannot be 0xFF, so it
+ * is easy to know that firmware never updated DTIM count/bitmap control
+ * field after host driver downloaded beacon template if end-user complaints
+ * that DTIM count and bitmapControl is 0xFF.
+ */
+ *ptr++ = SIR_MAC_TIM_EID;
+ *ptr++ = (uint8_t) (*timLength);
+ /* location for dtimCount. will be filled in by FW. */
+ *ptr++ = 0xFF;
+ *ptr++ = (uint8_t) val;
+ /* location for bitmap control. will be filled in by FW. */
+ *ptr++ = 0xFF;
+ ptr += (N2 - N1 + 1);
+
+ PELOG2(sir_dump_buf
+ (pMac, SIR_SCH_MODULE_ID, LOG2, *pPtr, (*timLength) + 2);
+ )
+ * pPtr = ptr;
+}
+/* -------------------------------------------------------------------- */
+/**
+ * @function: SchProcessPreBeaconInd
+ *
+ * @brief : Process the PreBeacon Indication from the Lim
+ *
+ * ASSUMPTIONS:
+ *
+ * NOTE:
+ *
+ * @param : pMac - tpAniSirGlobal
+ *
+ * @return None
+ */
+
+void sch_process_pre_beacon_ind(tpAniSirGlobal pMac, tpSirMsgQ limMsg)
+{
+ tpBeaconGenParams pMsg = (tpBeaconGenParams) limMsg->bodyptr;
+ uint32_t beaconSize;
+ tpPESession psessionEntry;
+ uint8_t sessionId;
+
+ if ((psessionEntry =
+ pe_find_session_by_bssid(pMac, pMsg->bssId, &sessionId)) == NULL) {
+ PELOGE(sch_log(pMac, LOGE, FL("session lookup fails"));)
+ goto end;
+ }
+
+ beaconSize = psessionEntry->schBeaconOffsetBegin;
+
+ /* If SME is not in normal mode, no need to generate beacon */
+ if (psessionEntry->limSmeState != eLIM_SME_NORMAL_STATE) {
+ PELOGE(sch_log
+ (pMac, LOG1,
+ FL("PreBeaconInd received in invalid state: %d"),
+ psessionEntry->limSmeState);
+ )
+ goto end;
+ }
+
+ switch (GET_LIM_SYSTEM_ROLE(psessionEntry)) {
+
+ case eLIM_STA_IN_IBSS_ROLE:
+ case eLIM_BT_AMP_AP_ROLE:
+ case eLIM_BT_AMP_STA_ROLE:
+ /* generate IBSS parameter set */
+ if (psessionEntry->statypeForBss == STA_ENTRY_SELF)
+ write_beacon_to_memory(pMac, (uint16_t) beaconSize,
+ (uint16_t) beaconSize,
+ psessionEntry);
+ else
+ PELOGE(sch_log
+ (pMac, LOGE,
+ FL
+ ("can not send beacon for PEER session entry"));
+ )
+ break;
+
+ case eLIM_AP_ROLE: {
+ uint8_t *ptr =
+ &psessionEntry->pSchBeaconFrameBegin[psessionEntry->
+ schBeaconOffsetBegin];
+ uint16_t timLength = 0;
+ if (psessionEntry->statypeForBss == STA_ENTRY_SELF) {
+ sch_generate_tim(pMac, &ptr, &timLength,
+ psessionEntry->dtimPeriod);
+ beaconSize += 2 + timLength;
+ write_beacon_to_memory(pMac, (uint16_t) beaconSize,
+ (uint16_t) beaconSize,
+ psessionEntry);
+ } else
+ PELOGE(sch_log
+ (pMac, LOGE,
+ FL
+ ("can not send beacon for PEER session entry"));
+ )
+ }
+ break;
+
+ default:
+ PELOGE(sch_log
+ (pMac, LOGE,
+ FL
+ ("Error-PE has Receive PreBeconGenIndication when System is in %d role"),
+ GET_LIM_SYSTEM_ROLE(psessionEntry));
+ )
+ }
+
+end:
+ cdf_mem_free(pMsg);
+
+ }
diff --git a/core/mac/src/pe/sch/sch_beacon_process.c b/core/mac/src/pe/sch/sch_beacon_process.c
new file mode 100644
index 0000000..a8f2a46
--- /dev/null
+++ b/core/mac/src/pe/sch/sch_beacon_process.c
@@ -0,0 +1,1011 @@
+/*
+ * Copyright (c) 2012-2015 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 sch_beacon_process.cc contains beacon processing related
+ * functions
+ *
+ * Author: Sandesh Goel
+ * Date: 02/25/02
+ * History:-
+ * Date Modified by Modification Information
+ * --------------------------------------------------------------------
+ *
+ */
+
+#include "cds_api.h"
+#include "wni_cfg.h"
+
+#include "cfg_api.h"
+#include "lim_api.h"
+#include "utils_api.h"
+#include "sch_debug.h"
+#include "sch_api.h"
+
+#include "lim_utils.h"
+#include "lim_send_messages.h"
+#include "lim_sta_hash_api.h"
+
+#if defined WLAN_FEATURE_VOWIFI
+#include "rrm_api.h"
+#endif
+
+#ifdef FEATURE_WLAN_DIAG_SUPPORT
+#include "host_diag_core_log.h"
+#endif /* FEATURE_WLAN_DIAG_SUPPORT */
+
+/**
+ * Number of bytes of variation in beacon length from the last beacon
+ * to trigger reprogramming of rx delay register
+ */
+#define SCH_BEACON_LEN_DELTA 3
+
+/* calculate 2^cw - 1 */
+#define CW_GET(cw) (((cw) == 0) ? 1 : ((1 << (cw)) - 1))
+
+static void
+ap_beacon_process_5_ghz(tpAniSirGlobal mac_ctx, uint8_t *rx_pkt_info,
+ tpSchBeaconStruct bcn_struct,
+ tpUpdateBeaconParams bcn_prm, tpPESession session,
+ uint32_t phy_mode)
+{
+ tpSirMacMgmtHdr mac_hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info);
+ if (!session->htCapability)
+ return;
+
+ if (bcn_struct->channelNumber != session->currentOperChannel)
+ return;
+
+ /* 11a (non HT) AP overlaps or */
+ /* HT AP with HT op mode as mixed overlaps. */
+ /* HT AP with HT op mode as overlap legacy overlaps. */
+ if (!bcn_struct->HTInfo.present
+ || (eSIR_HT_OP_MODE_MIXED == bcn_struct->HTInfo.opMode)
+ || (eSIR_HT_OP_MODE_OVERLAP_LEGACY == bcn_struct->HTInfo.opMode)) {
+ lim_update_overlap_sta_param(mac_ctx, mac_hdr->bssId,
+ &(mac_ctx->lim.gLimOverlap11aParams));
+
+ if (mac_ctx->lim.gLimOverlap11aParams.numSta
+ && !mac_ctx->lim.gLimOverlap11aParams.protectionEnabled) {
+ lim_update_11a_protection(mac_ctx, true, true,
+ bcn_prm, session);
+ }
+ return;
+ }
+ /* HT AP with HT20 op mode overlaps. */
+ if (eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT != bcn_struct->HTInfo.opMode)
+ return;
+
+ lim_update_overlap_sta_param(mac_ctx, mac_hdr->bssId,
+ &(mac_ctx->lim.gLimOverlapHt20Params));
+
+ if (mac_ctx->lim.gLimOverlapHt20Params.numSta
+ && !mac_ctx->lim.gLimOverlapHt20Params.protectionEnabled)
+ lim_enable_ht20_protection(mac_ctx, true, true,
+ bcn_prm, session);
+}
+
+static void
+ap_beacon_process_24_ghz(tpAniSirGlobal mac_ctx, uint8_t *rx_pkt_info,
+ tpSchBeaconStruct bcn_struct,
+ tpUpdateBeaconParams bcn_prm, tpPESession session,
+ uint32_t phy_mode)
+{
+ tpSirMacMgmtHdr mac_hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info);
+ bool tmp_exp = false;
+ /* We are 11G AP. */
+ if ((phy_mode == WNI_CFG_PHY_MODE_11G) &&
+ (false == session->htCapability)) {
+ if (bcn_struct->channelNumber != session->currentOperChannel)
+ return;
+
+ tmp_exp = (!bcn_struct->erpPresent
+ && !bcn_struct->HTInfo.present)
+ /* if erp not present then 11B AP overlapping */
+ || (!mac_ctx->roam.configParam.ignore_peer_erp_info &&
+ bcn_struct->erpPresent &&
+ (bcn_struct->erpIEInfo.useProtection
+ || bcn_struct->erpIEInfo.nonErpPresent));
+ if (!tmp_exp)
+ return;
+#ifdef FEATURE_WLAN_ESE
+ if (session->isESEconnection)
+ CDF_TRACE(CDF_MODULE_ID_PE,
+ CDF_TRACE_LEVEL_INFO,
+ FL("[INFOLOG]ESE 11g erpPresent=%d useProtection=%d nonErpPresent=%d"),
+ bcn_struct->erpPresent,
+ bcn_struct->erpIEInfo.useProtection,
+ bcn_struct->erpIEInfo.nonErpPresent);
+#endif
+ lim_enable_overlap11g_protection(mac_ctx, bcn_prm,
+ mac_hdr, session);
+ return;
+ }
+ /* handling the case when HT AP has overlapping legacy BSS. */
+ if (!session->htCapability)
+ return;
+
+ if (bcn_struct->channelNumber != session->currentOperChannel)
+ return;
+
+ tmp_exp = (!bcn_struct->erpPresent && !bcn_struct->HTInfo.present)
+ /* if erp not present then 11B AP overlapping */
+ || (!mac_ctx->roam.configParam.ignore_peer_erp_info &&
+ bcn_struct->erpPresent &&
+ (bcn_struct->erpIEInfo.useProtection
+ || bcn_struct->erpIEInfo.nonErpPresent));
+ if (tmp_exp) {
+#ifdef FEATURE_WLAN_ESE
+ if (session->isESEconnection) {
+ CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_INFO,
+ FL("[INFOLOG]ESE 11g erpPresent=%d useProtection=%d nonErpPresent=%d"),
+ bcn_struct->erpPresent,
+ bcn_struct->erpIEInfo.useProtection,
+ bcn_struct->erpIEInfo.nonErpPresent);
+ }
+#endif
+ lim_enable_overlap11g_protection(mac_ctx, bcn_prm,
+ mac_hdr, session);
+ }
+ /* 11g device overlaps */
+ tmp_exp = bcn_struct->erpPresent
+ && !(bcn_struct->erpIEInfo.useProtection
+ || bcn_struct->erpIEInfo.nonErpPresent)
+ && !(bcn_struct->HTInfo.present);
+ if (tmp_exp) {
+ lim_update_overlap_sta_param(mac_ctx, mac_hdr->bssId,
+ &(session->gLimOverlap11gParams));
+
+ if (session->gLimOverlap11gParams.numSta
+ && !session->gLimOverlap11gParams.protectionEnabled)
+ lim_enable_ht_protection_from11g(mac_ctx, true, true,
+ bcn_prm, session);
+ }
+ /* ht device overlaps.
+ * here we will check for HT related devices only which might need
+ * protection. check for 11b and 11g is already done in the previous
+ * blocks. so we will not check for HT operating mode as MIXED.
+ */
+ if (!bcn_struct->HTInfo.present)
+ return;
+
+ /*
+ * if we are not already in mixed mode or legacy mode as HT operating
+ * mode and received beacon has HT operating mode as legacy then we need
+ * to enable protection from 11g station. we don't need protection from
+ * 11b because if that's needed then our operating mode would have
+ * already been set to legacy in the previous blocks.
+ */
+ if (eSIR_HT_OP_MODE_OVERLAP_LEGACY == bcn_struct->HTInfo.opMode) {
+ if (eSIR_HT_OP_MODE_OVERLAP_LEGACY == mac_ctx->lim.gHTOperMode
+ || eSIR_HT_OP_MODE_MIXED == mac_ctx->lim.gHTOperMode)
+ return;
+ lim_update_overlap_sta_param(mac_ctx, mac_hdr->bssId,
+ &(session->gLimOverlap11gParams));
+ if (session->gLimOverlap11gParams.numSta
+ && !session->gLimOverlap11gParams.protectionEnabled)
+ lim_enable_ht_protection_from11g(mac_ctx, true, true,
+ bcn_prm, session);
+ return;
+ }
+
+ if (eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT == bcn_struct->HTInfo.opMode) {
+ lim_update_overlap_sta_param(mac_ctx, mac_hdr->bssId,
+ &(session->gLimOverlapHt20Params));
+ if (session->gLimOverlapHt20Params.numSta
+ && !session->gLimOverlapHt20Params.protectionEnabled)
+ lim_enable_ht20_protection(mac_ctx, true, true,
+ bcn_prm, session);
+ }
+}
+
+/**
+ * ap_beacon_process() - processes incoming beacons
+ *
+ * @mac_ctx: mac global context
+ * @rx_pkt_info: incoming beacon packet
+ * @bcn_struct: beacon struct
+ * @bcn_prm: beacon params
+ * @session: pe session entry
+ *
+ * Return: void
+ */
+static void
+ap_beacon_process(tpAniSirGlobal mac_ctx, uint8_t *rx_pkt_info,
+ tpSchBeaconStruct bcn_struct,
+ tpUpdateBeaconParams bcn_prm, tpPESession session)
+{
+ uint32_t phy_mode;
+ tSirRFBand rf_band = SIR_BAND_UNKNOWN;
+ /* Get RF band from session */
+ rf_band = session->limRFBand;
+
+ lim_get_phy_mode(mac_ctx, &phy_mode, session);
+
+ if (SIR_BAND_5_GHZ == rf_band)
+ ap_beacon_process_5_ghz(mac_ctx, rx_pkt_info, bcn_struct,
+ bcn_prm, session, phy_mode);
+ else if (SIR_BAND_2_4_GHZ == rf_band)
+ ap_beacon_process_24_ghz(mac_ctx, rx_pkt_info, bcn_struct,
+ bcn_prm, session, phy_mode);
+ mac_ctx->sch.gSchBcnIgnored++;
+}
+
+/* -------------------------------------------------------------------- */
+
+/**
+ * __sch_beacon_process_no_session
+ *
+ * FUNCTION:
+ * Process the received beacon frame when
+ * -- Station is not scanning
+ * -- No corresponding session is found
+ *
+ * LOGIC:
+ * Following scenarios exist when Session Does not exist:
+ * * IBSS Beacons, when IBSS session already exists with same SSID,
+ * but from STA which has not yet joined and has a different BSSID.
+ * - invoke lim_handle_ibs_scoalescing with the session context of existing IBSS session.
+ *
+ * * IBSS Beacons when IBSS session does not exist, only Infra or BT-AMP session exists,
+ * then save the beacon in the scan results and throw it away.
+ *
+ * * Infra Beacons
+ * - beacons received when no session active
+ * should not come here, it should be handled as part of scanning,
+ * else they should not be getting received, should update scan results and drop it if that happens.
+ * - beacons received when IBSS session active:
+ * update scan results and drop it.
+ * - beacons received when Infra session(STA) is active:
+ * update scan results and drop it
+ * - beacons received when BT-STA session is active:
+ * update scan results and drop it.
+ * - beacons received when Infra/BT-STA or Infra/IBSS is active.
+ * update scan results and drop it.
+ *
+
+ */
+static void __sch_beacon_process_no_session(tpAniSirGlobal pMac,
+ tpSchBeaconStruct pBeacon,
+ uint8_t *pRxPacketInfo)
+{
+ tpPESession psessionEntry = NULL;
+
+ if ((psessionEntry = lim_is_ibss_session_active(pMac)) != NULL) {
+ lim_handle_ibss_coalescing(pMac, pBeacon, pRxPacketInfo,
+ psessionEntry);
+ }
+ /* If station(STA/BT-STA/BT-AP/IBSS) mode, Always save the beacon in the scan results, if atleast one session is active */
+ /* sch_beacon_processNoSession will be called only when there is atleast one session active, so not checking */
+ /* it again here. */
+ lim_check_and_add_bss_description(pMac, pBeacon, pRxPacketInfo, false,
+ false);
+ return;
+}
+
+/**
+ * get_operating_channel_width() - Get operating channel width
+ * @pStaDs - station entry.
+ *
+ * This function returns the oeprating channgl width based on
+ * the supported channel width entry.
+ *
+ * Return: tSirMacHTChannelWidth on success
+ */
+tSirMacHTChannelWidth get_operating_channel_width(tpDphHashNode stads)
+{
+ tSirMacHTChannelWidth ch_width = eHT_CHANNEL_WIDTH_20MHZ;
+
+ if (stads->vhtSupportedChannelWidthSet ==
+ WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ)
+ ch_width = eHT_CHANNEL_WIDTH_160MHZ;
+ else if (stads->vhtSupportedChannelWidthSet ==
+ WNI_CFG_VHT_CHANNEL_WIDTH_80_PLUS_80MHZ)
+ ch_width = eHT_CHANNEL_WIDTH_160MHZ;
+ else if (stads->vhtSupportedChannelWidthSet ==
+ WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ)
+ ch_width = eHT_CHANNEL_WIDTH_80MHZ;
+ else if (stads->htSupportedChannelWidthSet)
+ ch_width = eHT_CHANNEL_WIDTH_40MHZ;
+ else
+ ch_width = eHT_CHANNEL_WIDTH_20MHZ;
+
+ return ch_width;
+}
+
+/*
+ * sch_bcn_process_sta_bt_amp_sta() - Process the received beacon frame for sta,
+ * bt_amp_sta
+ *
+ * @mac_ctx: mac_ctx
+ * @bcn: beacon struct
+ * @rx_pkt_info: received packet info
+ * @session: pe session pointer
+ * @bssIdx: bss index
+ * @beaconParams: update beacon params
+ * @sendProbeReq: out flag to indicate if probe rsp is to be sent
+ * @pMh: mac header
+ *
+ * Process the received beacon frame for sta, bt_amp_sta
+ *
+ * Return: success of failure of operation
+ */
+static bool
+sch_bcn_process_sta_bt_amp_sta(tpAniSirGlobal mac_ctx,
+ tpSchBeaconStruct bcn,
+ uint8_t *rx_pkt_info,
+ tpPESession session, uint8_t *bssIdx,
+ tUpdateBeaconParams *beaconParams,
+ uint8_t *sendProbeReq, tpSirMacMgmtHdr pMh)
+{
+ uint32_t bi;
+ tpDphHashNode pStaDs = NULL;
+ /*
+ * This handles two cases:
+ * -- Infra STA receving beacons from AP
+ * -- BTAMP_STA receving beacons from BTAMP_AP
+ */
+ /* Always save the beacon into LIM's cached scan results */
+ lim_check_and_add_bss_description(mac_ctx, bcn, rx_pkt_info,
+ false, false);
+
+ /**
+ * This is the Beacon received from the AP we're currently associated
+ * with. Check if there are any changes in AP's capabilities
+ */
+ if ((uint8_t) bcn->channelNumber != session->currentOperChannel) {
+ PELOGE(sch_log(mac_ctx, LOGE,
+ FL("Channel Change from %d --> %d - Ignoring beacon!"),
+ session->currentOperChannel,
+ bcn->channelNumber);)
+ return false;
+ }
+ lim_detect_change_in_ap_capabilities(mac_ctx, bcn, session);
+ if (lim_get_sta_hash_bssidx(mac_ctx, DPH_STA_HASH_INDEX_PEER, bssIdx,
+ session) != eSIR_SUCCESS)
+ return false;
+
+ beaconParams->bssIdx = *bssIdx;
+ cdf_mem_copy((uint8_t *) &session->lastBeaconTimeStamp,
+ (uint8_t *) bcn->timeStamp, sizeof(uint64_t));
+ session->lastBeaconDtimCount = bcn->tim.dtimCount;
+ session->lastBeaconDtimPeriod = bcn->tim.dtimPeriod;
+ session->currentBssBeaconCnt++;
+
+ MTRACE(mac_trace(mac_ctx, TRACE_CODE_RX_MGMT_TSF,
+ session->peSessionId, bcn->timeStamp[0]);)
+ MTRACE(mac_trace(mac_ctx, TRACE_CODE_RX_MGMT_TSF,
+ session->peSessionId, bcn->timeStamp[1]);)
+
+ /* Read beacon interval session Entry */
+ bi = session->beaconParams.beaconInterval;
+ if (bi != bcn->beaconInterval) {
+ PELOG1(sch_log(mac_ctx, LOG1,
+ FL("Beacon interval changed from %d to %d"),
+ bcn->beaconInterval, bi);)
+
+ bi = bcn->beaconInterval;
+ session->beaconParams.beaconInterval = (uint16_t) bi;
+ beaconParams->paramChangeBitmap |= PARAM_BCN_INTERVAL_CHANGED;
+ beaconParams->beaconInterval = (uint16_t) bi;
+ }
+
+ if (bcn->cfPresent) {
+ cfg_set_int(mac_ctx, WNI_CFG_CFP_PERIOD,
+ bcn->cfParamSet.cfpPeriod);
+ lim_send_cf_params(mac_ctx, *bssIdx,
+ bcn->cfParamSet.cfpCount,
+ bcn->cfParamSet.cfpPeriod);
+ }
+
+ /* No need to send DTIM Period and Count to HAL/SMAC */
+ /* SMAC already parses TIM bit. */
+ if (bcn->timPresent)
+ cfg_set_int(mac_ctx, WNI_CFG_DTIM_PERIOD, bcn->tim.dtimPeriod);
+
+ if (mac_ctx->lim.gLimProtectionControl !=
+ WNI_CFG_FORCE_POLICY_PROTECTION_DISABLE)
+ lim_decide_sta_protection(mac_ctx, bcn, beaconParams, session);
+
+ if (bcn->erpPresent) {
+ if (bcn->erpIEInfo.barkerPreambleMode)
+ lim_enable_short_preamble(mac_ctx, false,
+ beaconParams, session);
+ else
+ lim_enable_short_preamble(mac_ctx, true,
+ beaconParams, session);
+ }
+ lim_update_short_slot(mac_ctx, bcn, beaconParams, session);
+
+ pStaDs = dph_get_hash_entry(mac_ctx, DPH_STA_HASH_INDEX_PEER,
+ &session->dph.dphHashTable);
+ if ((bcn->wmeEdcaPresent && (session->limWmeEnabled))
+ || (bcn->edcaPresent && (session->limQosEnabled))) {
+ if (bcn->edcaParams.qosInfo.count !=
+ session->gLimEdcaParamSetCount) {
+ if (sch_beacon_edca_process(mac_ctx, &bcn->edcaParams,
+ session) != eSIR_SUCCESS) {
+ PELOGE(sch_log(mac_ctx, LOGE,
+ FL("EDCA parameter processing error"));)
+ } else if (pStaDs != NULL) {
+ /* If needed, downgrade the EDCA parameters */
+ lim_set_active_edca_params(mac_ctx,
+ session->gLimEdcaParams, session);
+ lim_send_edca_params(mac_ctx,
+ session->gLimEdcaParamsActive,
+ pStaDs->bssId);
+ } else {
+ PELOGE(sch_log(mac_ctx, LOGE,
+ FL("Self Entry missing in Hash Table"));)
+ }
+ }
+ return true;
+ }
+
+ if ((bcn->qosCapabilityPresent && session->limQosEnabled)
+ && (bcn->qosCapability.qosInfo.count !=
+ session->gLimEdcaParamSetCount))
+ *sendProbeReq = true;
+
+ return true;
+}
+
+/**
+ * update_nss() - Function to update NSS
+ * @mac_ctx: pointer to Global Mac structure
+ * @sta_ds: pointer to tpDphHashNode
+ * @beacon: pointer to tpSchBeaconStruct
+ * @session_entry: pointer to tpPESession
+ * @mgmt_hdr: pointer to tpSirMacMgmtHdr
+ *
+ * function to update NSS
+ *
+ * Return: none
+ */
+void update_nss(tpAniSirGlobal mac_ctx, tpDphHashNode sta_ds,
+ tpSchBeaconStruct beacon, tpPESession session_entry,
+ tpSirMacMgmtHdr mgmt_hdr)
+{
+ if (sta_ds->vhtSupportedRxNss != (beacon->OperatingMode.rxNSS + 1)) {
+ sta_ds->vhtSupportedRxNss =
+ beacon->OperatingMode.rxNSS + 1;
+ lim_set_nss_change(mac_ctx, session_entry,
+ sta_ds->vhtSupportedRxNss, sta_ds->staIndex,
+ mgmt_hdr->sa);
+ }
+}
+
+/*
+ * sch_bcn_process_sta_bt_amp_sta_ibss() - Process the received beacon frame
+ * for sta, bt_amp_sta and ibss
+ *
+ * @mac_ctx: mac_ctx
+ * @bcn: beacon struct
+ * @rx_pkt_info: received packet info
+ * @session: pe session pointer
+ * @bssIdx: bss index
+ * @beaconParams: update beacon params
+ * @sendProbeReq: out flag to indicate if probe rsp is to be sent
+ * @pMh: mac header
+ *
+ * Process the received beacon frame for sta, bt_amp_sta and ibss
+ *
+ * Return: void
+ */
+static void
+sch_bcn_process_sta_bt_amp_sta_ibss(tpAniSirGlobal mac_ctx,
+ tpSchBeaconStruct bcn,
+ uint8_t *rx_pkt_info,
+ tpPESession session, uint8_t *bssIdx,
+ tUpdateBeaconParams *beaconParams,
+ uint8_t *sendProbeReq, tpSirMacMgmtHdr pMh)
+{
+ tpDphHashNode pStaDs = NULL;
+ uint16_t aid;
+ uint8_t operMode;
+ uint8_t chWidth = 0;
+ uint8_t cb_mode;
+
+ if (RF_CHAN_14 >= session->currentOperChannel)
+ cb_mode = mac_ctx->roam.configParam.channelBondingMode24GHz;
+ else
+ cb_mode = mac_ctx->roam.configParam.channelBondingMode5GHz;
+ /* check for VHT capability */
+ pStaDs = dph_lookup_hash_entry(mac_ctx, pMh->sa, &aid,
+ &session->dph.dphHashTable);
+ if ((NULL == pStaDs) ||
+ (WNI_CFG_CHANNEL_BONDING_MODE_DISABLE == cb_mode))
+ return;
+
+ if (session->vhtCapability && bcn->OperatingMode.present) {
+ operMode = get_operating_channel_width(pStaDs);
+ if (operMode == bcn->OperatingMode.chanWidth)
+ return;
+
+ PELOGE(sch_log(mac_ctx, LOGE,
+ FL("received OpMode Chanwidth %d, staIdx = %d"),
+ bcn->OperatingMode.chanWidth, pStaDs->staIndex);)
+ PELOGE(sch_log(mac_ctx, LOGE,
+ FL("MAC - %0x:%0x:%0x:%0x:%0x:%0x"),
+ pMh->sa[0], pMh->sa[1],
+ pMh->sa[2], pMh->sa[3],
+ pMh->sa[4], pMh->sa[5]);)
+
+ if (bcn->OperatingMode.chanWidth ==
+ eHT_CHANNEL_WIDTH_160MHZ) {
+ PELOGE(sch_log(mac_ctx, LOGE,
+ FL("Updating the CH Width to 160MHz"));)
+ pStaDs->vhtSupportedChannelWidthSet =
+ WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ;
+ pStaDs->htSupportedChannelWidthSet =
+ eHT_CHANNEL_WIDTH_40MHZ;
+ } else if (bcn->OperatingMode.chanWidth ==
+ eHT_CHANNEL_WIDTH_80MHZ) {
+ PELOGE(sch_log(mac_ctx, LOGE,
+ FL("Updating the CH Width to 80MHz"));)
+ pStaDs->vhtSupportedChannelWidthSet =
+ WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ;
+ pStaDs->htSupportedChannelWidthSet =
+ eHT_CHANNEL_WIDTH_40MHZ;
+ } else if (bcn->OperatingMode.chanWidth ==
+ eHT_CHANNEL_WIDTH_40MHZ) {
+ PELOGE(sch_log(mac_ctx, LOGE,
+ FL("Updating the CH Width to 40MHz"));)
+ pStaDs->vhtSupportedChannelWidthSet =
+ WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ;
+ pStaDs->htSupportedChannelWidthSet =
+ eHT_CHANNEL_WIDTH_40MHZ;
+ } else if (bcn->OperatingMode.chanWidth ==
+ eHT_CHANNEL_WIDTH_20MHZ) {
+ PELOGE(sch_log(mac_ctx, LOGE,
+ FL("Updating the CH Width to 20MHz"));)
+ pStaDs->vhtSupportedChannelWidthSet =
+ WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ;
+ pStaDs->htSupportedChannelWidthSet =
+ eHT_CHANNEL_WIDTH_20MHZ;
+ }
+ lim_check_vht_op_mode_change(mac_ctx, session,
+ bcn->OperatingMode.chanWidth,
+ pStaDs->staIndex, pMh->sa);
+ update_nss(mac_ctx, pStaDs, bcn, session, pMh);
+ return;
+ }
+
+ if (!(session->vhtCapability && bcn->VHTOperation.present))
+ return;
+
+ operMode = pStaDs->vhtSupportedChannelWidthSet;
+ if (operMode == bcn->VHTOperation.chanWidth)
+ return;
+
+ PELOGE(sch_log(mac_ctx, LOGE,
+ FL("received VHTOP CHWidth %d staIdx = %d"),
+ bcn->VHTOperation.chanWidth, pStaDs->staIndex);)
+ PELOGE(sch_log(mac_ctx, LOGE,
+ FL(" MAC - %0x:%0x:%0x:%0x:%0x:%0x"),
+ pMh->sa[0], pMh->sa[1],
+ pMh->sa[2], pMh->sa[3],
+ pMh->sa[4], pMh->sa[5]);)
+
+ if (bcn->VHTOperation.chanWidth ==
+ WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ) {
+ PELOGE(sch_log(mac_ctx, LOGE,
+ FL("Updating the CH Width to 160MHz"));)
+ pStaDs->vhtSupportedChannelWidthSet =
+ WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ;
+ pStaDs->htSupportedChannelWidthSet =
+ eHT_CHANNEL_WIDTH_40MHZ;
+ chWidth = eHT_CHANNEL_WIDTH_160MHZ;
+ } else if (bcn->VHTOperation.chanWidth ==
+ WNI_CFG_VHT_CHANNEL_WIDTH_80_PLUS_80MHZ) {
+ PELOGE(sch_log(mac_ctx, LOGE,
+ FL("Updating the CH Width to 160MHz"));)
+ pStaDs->vhtSupportedChannelWidthSet =
+ WNI_CFG_VHT_CHANNEL_WIDTH_80_PLUS_80MHZ;
+ pStaDs->htSupportedChannelWidthSet = eHT_CHANNEL_WIDTH_40MHZ;
+ chWidth = eHT_CHANNEL_WIDTH_160MHZ;
+ } else if (bcn->VHTOperation.chanWidth ==
+ WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ) {
+ PELOGE(sch_log(mac_ctx, LOGE,
+ FL("Updating the CH Width to 80MHz"));)
+ pStaDs->vhtSupportedChannelWidthSet =
+ WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ;
+ pStaDs->htSupportedChannelWidthSet = eHT_CHANNEL_WIDTH_40MHZ;
+ chWidth = eHT_CHANNEL_WIDTH_80MHZ;
+ } else if (bcn->VHTOperation.chanWidth ==
+ WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ) {
+ pStaDs->vhtSupportedChannelWidthSet =
+ WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ;
+ if (bcn->HTCaps.supportedChannelWidthSet) {
+ PELOGE(sch_log(mac_ctx, LOGE,
+ FL("Updating the CH Width to 40MHz"));)
+ pStaDs->htSupportedChannelWidthSet =
+ eHT_CHANNEL_WIDTH_40MHZ;
+ chWidth = eHT_CHANNEL_WIDTH_40MHZ;
+ } else {
+ PELOGE(sch_log(mac_ctx, LOGE,
+ FL("Updating the CH Width to 20MHz"));)
+ pStaDs->htSupportedChannelWidthSet =
+ eHT_CHANNEL_WIDTH_20MHZ;
+ chWidth = eHT_CHANNEL_WIDTH_20MHZ;
+ }
+ }
+ lim_check_vht_op_mode_change(mac_ctx, session, chWidth,
+ pStaDs->staIndex, pMh->sa);
+ return;
+}
+
+/*
+ * __sch_beacon_process_for_session() - Process the received beacon frame when
+ * station is not scanning and corresponding session is found
+ *
+ *
+ * @mac_ctx: mac_ctx
+ * @bcn: beacon struct
+ * @rx_pkt_info: received packet info
+ * @session: pe session pointer
+ *
+ * Following scenarios exist when Session exists
+ * IBSS STA receving beacons from IBSS Peers, who are part of IBSS.
+ * - call lim_handle_ibs_scoalescing with that session context.
+ * Infra STA receving beacons from AP to which it is connected
+ * - call sch_beacon_processFromAP with that session's context.
+ * BTAMP STA receving beacons from BTAMP AP
+ * - call sch_beacon_processFromAP with that session's context.
+ * BTAMP AP receiving beacons from BTAMP STA
+ * (here need to make sure BTAP creates session entry for BT STA)
+ * - just update the beacon count for heart beat purposes for now,
+ * for now, don't process the beacon.
+ * Infra/IBSS both active and receives IBSS beacon:
+ * - call lim_handle_ibs_scoalescing with that session context.
+ * Infra/IBSS both active and receives Infra beacon:
+ * - call sch_beacon_processFromAP with that session's context.
+ * any updates to EDCA parameters will be effective for IBSS as well,
+ * even though no WMM for IBSS ?? Need to figure out how to handle
+ * this scenario.
+ * Infra/BTSTA both active and receive Infra beacon.
+ * - change in EDCA parameters on Infra affect the BTSTA link.
+ * Update the same parameters on BT link
+ * Infra/BTSTA both active and receive BT-AP beacon.
+ * - update beacon cnt for heartbeat
+ * Infra/BTAP both active and receive Infra beacon.
+ * - BT-AP starts advertising BE parameters from Infra AP, if they get
+ * changed.
+ * Infra/BTAP both active and receive BTSTA beacon.
+ * - update beacon cnt for heartbeat
+ *
+ * Return: void
+ */
+static void __sch_beacon_process_for_session(tpAniSirGlobal mac_ctx,
+ tpSchBeaconStruct bcn,
+ uint8_t *rx_pkt_info,
+ tpPESession session)
+{
+ tPowerdBm localRRMConstraint = 0;
+ uint8_t bssIdx = 0;
+ tUpdateBeaconParams beaconParams;
+ uint8_t sendProbeReq = false;
+#ifdef WLAN_FEATURE_11AC
+ tpSirMacMgmtHdr pMh = WMA_GET_RX_MAC_HEADER(rx_pkt_info);
+#endif
+#if defined FEATURE_WLAN_ESE || defined WLAN_FEATURE_VOWIFI
+ tPowerdBm regMax = 0, maxTxPower = 0;
+#endif
+ cdf_mem_zero(&beaconParams, sizeof(tUpdateBeaconParams));
+ beaconParams.paramChangeBitmap = 0;
+
+ if (LIM_IS_IBSS_ROLE(session)) {
+ lim_handle_ibss_coalescing(mac_ctx, bcn, rx_pkt_info, session);
+ } else if (LIM_IS_STA_ROLE(session)
+ || LIM_IS_BT_AMP_STA_ROLE(session)) {
+ if (false == sch_bcn_process_sta_bt_amp_sta(mac_ctx, bcn,
+ rx_pkt_info, session, &bssIdx,
+ &beaconParams, &sendProbeReq, pMh))
+ return;
+ }
+
+ if (session->htCapability && bcn->HTInfo.present)
+ lim_update_sta_run_time_ht_switch_chnl_params(mac_ctx,
+ &bcn->HTInfo, bssIdx, session);
+
+ if (LIM_IS_STA_ROLE(session)
+ || LIM_IS_BT_AMP_STA_ROLE(session)
+ || LIM_IS_IBSS_ROLE(session)) {
+ /* Channel Switch information element updated */
+ if (bcn->channelSwitchPresent) {
+ lim_update_channel_switch(mac_ctx, bcn, session);
+ } else if (session->gLimSpecMgmt.dot11hChanSwState ==
+ eLIM_11H_CHANSW_RUNNING) {
+ lim_cancel_dot11h_channel_switch(mac_ctx, session);
+ }
+ }
+#ifdef WLAN_FEATURE_11AC
+ if (LIM_IS_STA_ROLE(session)
+ || LIM_IS_BT_AMP_STA_ROLE(session)
+ || LIM_IS_IBSS_ROLE(session))
+ sch_bcn_process_sta_bt_amp_sta_ibss(mac_ctx, bcn,
+ rx_pkt_info, session, &bssIdx,
+ &beaconParams, &sendProbeReq, pMh);
+#endif
+
+#if defined (FEATURE_WLAN_ESE) || defined (WLAN_FEATURE_VOWIFI)
+ /* Obtain the Max Tx power for the current regulatory */
+ regMax = cfg_get_regulatory_max_transmit_power(mac_ctx,
+ session->currentOperChannel);
+#endif
+
+#if defined WLAN_FEATURE_VOWIFI
+ if (mac_ctx->rrm.rrmPEContext.rrmEnable
+ && bcn->powerConstraintPresent)
+ localRRMConstraint =
+ bcn->localPowerConstraint.localPowerConstraints;
+ else
+ localRRMConstraint = 0;
+ maxTxPower = lim_get_max_tx_power(regMax, regMax - localRRMConstraint,
+ mac_ctx->roam.configParam.nTxPowerCap);
+#elif defined FEATURE_WLAN_ESE
+ maxTxPower = regMax;
+#endif
+
+#if defined FEATURE_WLAN_ESE
+ if (session->isESEconnection) {
+ tPowerdBm localESEConstraint = 0;
+ if (bcn->eseTxPwr.present) {
+ localESEConstraint = bcn->eseTxPwr.power_limit;
+ maxTxPower = lim_get_max_tx_power(maxTxPower,
+ localESEConstraint,
+ mac_ctx->roam.configParam.nTxPowerCap);
+ }
+ sch_log(mac_ctx, LOG1,
+ FL("RegMax = %d, localEseCons = %d, MaxTx = %d"),
+ regMax, localESEConstraint, maxTxPower);
+ }
+#endif
+
+#if defined (FEATURE_WLAN_ESE) || defined (WLAN_FEATURE_VOWIFI)
+ /* If maxTxPower is increased or decreased */
+ if (maxTxPower != session->maxTxPower) {
+ sch_log(mac_ctx, LOG1,
+ FL("Local power constraint change..updating new maxTx power %d to HAL"),
+ maxTxPower);
+ if (lim_send_set_max_tx_power_req(mac_ctx, maxTxPower, session)
+ == eSIR_SUCCESS)
+ session->maxTxPower = maxTxPower;
+ }
+#endif
+
+ /* Indicate to LIM that Beacon is received */
+ if (bcn->HTInfo.present)
+ lim_received_hb_handler(mac_ctx,
+ (uint8_t) bcn->HTInfo.primaryChannel, session);
+ else
+ lim_received_hb_handler(mac_ctx, (uint8_t) bcn->channelNumber,
+ session);
+
+ /*
+ * I don't know if any additional IE is required here. Currently, not
+ * include addIE.
+ */
+ if (sendProbeReq)
+ lim_send_probe_req_mgmt_frame(mac_ctx, &session->ssId,
+ session->bssId, session->currentOperChannel,
+ session->selfMacAddr, session->dot11mode, 0, NULL);
+
+ if ((false == mac_ctx->sap.SapDfsInfo.is_dfs_cac_timer_running)
+ && beaconParams.paramChangeBitmap) {
+ PELOGW(sch_log(mac_ctx, LOGW,
+ FL("Beacon for session[%d] got changed."),
+ session->peSessionId);)
+ PELOGW(sch_log(mac_ctx, LOGW,
+ FL("sending beacon param change bitmap: 0x%x "),
+ beaconParams.paramChangeBitmap);)
+ lim_send_beacon_params(mac_ctx, &beaconParams, session);
+ }
+}
+
+/**
+ * sch_beacon_process() - process the beacon frame
+ *
+ * @mac_ctx: mac global context
+ * @rx_pkt_info: pointer to buffer descriptor
+ *
+ * @return None
+ */
+void
+sch_beacon_process(tpAniSirGlobal mac_ctx, uint8_t *rx_pkt_info,
+ tpPESession session)
+{
+ static tSchBeaconStruct bcn;
+ tUpdateBeaconParams bcn_prm;
+ tpPESession ap_session = NULL;
+#ifdef WLAN_FEATURE_MBSSID
+ uint8_t i;
+#endif
+
+ cdf_mem_zero(&bcn_prm, sizeof(tUpdateBeaconParams));
+ bcn_prm.paramChangeBitmap = 0;
+ mac_ctx->sch.gSchBcnRcvCnt++;
+ /* Convert the beacon frame into a structure */
+ if (sir_convert_beacon_frame2_struct(mac_ctx, (uint8_t *) rx_pkt_info,
+ &bcn) != eSIR_SUCCESS) {
+ PELOGE(sch_log(mac_ctx, LOGE, FL("beacon parsing failed"));)
+ mac_ctx->sch.gSchBcnParseErrorCnt++;
+ return;
+ }
+
+ if (bcn.ssidPresent)
+ bcn.ssId.ssId[bcn.ssId.length] = 0;
+ /*
+ * First process the beacon in the context of any existing AP or BTAP
+ * session. This takes cares of following two scenarios:
+ * - session = NULL:
+ * e.g. beacon received from a neighboring BSS, you want to apply the
+ * protection settings to BTAP/InfraAP beacons
+ * - session is non NULL:
+ * e.g. beacon received is from the INFRA AP to which you are connected
+ * on another concurrent link. In this case also, we want to apply the
+ * protection settings(as advertised by Infra AP) to BTAP beacons
+ */
+#ifdef WLAN_FEATURE_MBSSID
+ for (i = 0; i < mac_ctx->lim.maxBssId; i++) {
+ ap_session = pe_find_session_by_session_id(mac_ctx, i);
+ if (!((ap_session != NULL) &&
+ (!(WMA_GET_OFFLOADSCANLEARN(rx_pkt_info)))))
+ continue;
+
+ if (!LIM_IS_AP_ROLE(ap_session))
+ continue;
+
+ bcn_prm.bssIdx = ap_session->bssIdx;
+ if (ap_session->gLimProtectionControl !=
+ WNI_CFG_FORCE_POLICY_PROTECTION_DISABLE)
+ ap_beacon_process(mac_ctx, rx_pkt_info,
+ &bcn, &bcn_prm, ap_session);
+
+ if ((false == mac_ctx->sap.SapDfsInfo.is_dfs_cac_timer_running)
+ && bcn_prm.paramChangeBitmap) {
+ /* Update the bcn and apply the new settings to HAL */
+ sch_set_fixed_beacon_fields(mac_ctx, ap_session);
+ PELOG1(sch_log(mac_ctx, LOG1,
+ FL("Beacon for PE session[%d] got changed."),
+ ap_session->peSessionId);)
+ PELOG1(sch_log(mac_ctx, LOG1,
+ FL("sending beacon param change bitmap: 0x%x"),
+ bcn_prm.paramChangeBitmap);)
+ lim_send_beacon_params(mac_ctx, &bcn_prm, ap_session);
+ }
+ }
+#else
+ ap_session = lim_is_ap_session_active(mac_ctx);
+ if ((ap_session != NULL)
+ && (!(WMA_GET_OFFLOADSCANLEARN(rx_pkt_info)))) {
+ bcn_prm.bssIdx = ap_session->bssIdx;
+ if (ap_session->gLimProtectionControl !=
+ WNI_CFG_FORCE_POLICY_PROTECTION_DISABLE)
+ ap_beacon_process(mac_ctx, rx_pkt_info, &bcn,
+ &bcn_prm, ap_session);
+
+ if ((false == mac_ctx->sap.SapDfsInfo.is_dfs_cac_timer_running)
+ && bcn_prm.paramChangeBitmap) {
+ /* Update the bcn and apply the new settings to HAL */
+ sch_set_fixed_beacon_fields(mac_ctx, ap_session);
+ PELOG1(sch_log(mac_ctx, LOG1,
+ FL("Beacon for PE session[%d] got changed."),
+ ap_session->peSessionId);)
+ PELOG1(sch_log(mac_ctx, LOG1,
+ FL("sending beacon param change bitmap: 0x%x "),
+ bcn_prm.paramChangeBitmap);)
+ lim_send_beacon_params(mac_ctx, &bcn_prm, ap_session);
+ }
+ }
+#endif
+ /*
+ * Now process the beacon in the context of the BSS which is
+ * transmitting the beacons, if one is found
+ */
+ if (session == NULL)
+ __sch_beacon_process_no_session(mac_ctx, &bcn, rx_pkt_info);
+ else
+ __sch_beacon_process_for_session(mac_ctx, &bcn, rx_pkt_info,
+ session);
+}
+
+/**
+ * sch_beacon_edca_process(): Process the EDCA parameter set in the received
+ * beacon frame
+ *
+ * @mac_ctx: mac global context
+ * @edca: reference to edca parameters in beacon struct
+ * @session : pesession entry
+ *
+ * @return status of operation
+ */
+tSirRetStatus
+sch_beacon_edca_process(tpAniSirGlobal pMac, tSirMacEdcaParamSetIE *edca,
+ tpPESession session)
+{
+ uint8_t i;
+#ifdef FEATURE_WLAN_DIAG_SUPPORT
+ host_log_qos_edca_pkt_type *log_ptr = NULL;
+#endif /* FEATURE_WLAN_DIAG_SUPPORT */
+
+ PELOG1(sch_log(pMac, LOG1,
+ FL("Updating parameter set count: Old %d ---> new %d"),
+ session->gLimEdcaParamSetCount, edca->qosInfo.count);)
+
+ session->gLimEdcaParamSetCount = edca->qosInfo.count;
+ session->gLimEdcaParams[EDCA_AC_BE] = edca->acbe;
+ session->gLimEdcaParams[EDCA_AC_BK] = edca->acbk;
+ session->gLimEdcaParams[EDCA_AC_VI] = edca->acvi;
+ session->gLimEdcaParams[EDCA_AC_VO] = edca->acvo;
+#ifdef FEATURE_WLAN_DIAG_SUPPORT
+ WLAN_HOST_DIAG_LOG_ALLOC(log_ptr, host_log_qos_edca_pkt_type,
+ LOG_WLAN_QOS_EDCA_C);
+ if (log_ptr) {
+ log_ptr->aci_be = session->gLimEdcaParams[EDCA_AC_BE].aci.aci;
+ log_ptr->cw_be =
+ session->gLimEdcaParams[EDCA_AC_BE].cw.max << 4
+ | session->gLimEdcaParams[EDCA_AC_BE].cw.min;
+ log_ptr->txoplimit_be =
+ session->gLimEdcaParams[EDCA_AC_BE].txoplimit;
+ log_ptr->aci_bk =
+ session->gLimEdcaParams[EDCA_AC_BK].aci.aci;
+ log_ptr->cw_bk =
+ session->gLimEdcaParams[EDCA_AC_BK].cw.max << 4
+ | session->gLimEdcaParams[EDCA_AC_BK].cw.min;
+ log_ptr->txoplimit_bk =
+ session->gLimEdcaParams[EDCA_AC_BK].txoplimit;
+ log_ptr->aci_vi =
+ session->gLimEdcaParams[EDCA_AC_VI].aci.aci;
+ log_ptr->cw_vi =
+ session->gLimEdcaParams[EDCA_AC_VI].cw.max << 4
+ | session->gLimEdcaParams[EDCA_AC_VI].cw.min;
+ log_ptr->txoplimit_vi =
+ session->gLimEdcaParams[EDCA_AC_VI].txoplimit;
+ log_ptr->aci_vo =
+ session->gLimEdcaParams[EDCA_AC_VO].aci.aci;
+ log_ptr->cw_vo =
+ session->gLimEdcaParams[EDCA_AC_VO].cw.max << 4
+ | session->gLimEdcaParams[EDCA_AC_VO].cw.min;
+ log_ptr->txoplimit_vo =
+ session->gLimEdcaParams[EDCA_AC_VO].txoplimit;
+ }
+ WLAN_HOST_DIAG_LOG_REPORT(log_ptr);
+#endif /* FEATURE_WLAN_DIAG_SUPPORT */
+ PELOG1(sch_log(pMac, LOGE,
+ FL("Updating Local EDCA Params(gLimEdcaParams) to: "));)
+ for (i = 0; i < MAX_NUM_AC; i++) {
+ PELOG1(sch_log(pMac, LOG1,
+ FL("AC[%d]: AIFSN: %d, ACM %d, CWmin %d, CWmax %d, TxOp %d"),
+ i, session->gLimEdcaParams[i].aci.aifsn,
+ session->gLimEdcaParams[i].aci.acm,
+ session->gLimEdcaParams[i].cw.min,
+ session->gLimEdcaParams[i].cw.max,
+ session->gLimEdcaParams[i].txoplimit);)
+ }
+ return eSIR_SUCCESS;
+}
diff --git a/core/mac/src/pe/sch/sch_debug.c b/core/mac/src/pe/sch/sch_debug.c
new file mode 100644
index 0000000..47c0714
--- /dev/null
+++ b/core/mac/src/pe/sch/sch_debug.c
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2011-2014 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 sch_debug.cc contains some debug functions.
+ *
+ * Author: Sandesh Goel
+ * Date: 02/25/02
+ * History:-
+ * Date Modified by Modification Information
+ * --------------------------------------------------------------------
+ *
+ */
+
+#include "cdf_trace.h"
+#include "sch_debug.h"
+#define LOG_SIZE 256
+
+void sch_log(tpAniSirGlobal pMac, uint32_t loglevel, const char *pString, ...)
+{
+
+ CDF_TRACE_LEVEL cdf_debug_level;
+ char logBuffer[LOG_SIZE];
+ va_list marker;
+
+ /* getting proper Debug level */
+ cdf_debug_level = get_vos_debug_level(loglevel);
+
+ /* extracting arguments from pstring */
+ va_start(marker, pString);
+ vsnprintf(logBuffer, LOG_SIZE, pString, marker);
+ CDF_TRACE(CDF_MODULE_ID_PE, cdf_debug_level, "%s", logBuffer);
+ va_end(marker);
+}
+
+/* -------------------------------------------------------------------- */
diff --git a/core/mac/src/pe/sch/sch_debug.h b/core/mac/src/pe/sch/sch_debug.h
new file mode 100644
index 0000000..d27f727
--- /dev/null
+++ b/core/mac/src/pe/sch/sch_debug.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2011-2015 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 sch_debug.h contains some debug macros.
+ *
+ * Author: Sandesh Goel
+ * Date: 02/25/02
+ * History:-
+ * Date Modified by Modification Information
+ * --------------------------------------------------------------------
+ *
+ */
+
+#ifndef __SCH_DEBUG_H__
+#define __SCH_DEBUG_H__
+
+#include "utils_api.h"
+#include "sir_debug.h"
+
+#if !defined(__printf)
+#define __printf(a, b)
+#endif
+
+void __printf(3, 4) sch_log(tpAniSirGlobal pMac, uint32_t loglevel,
+ const char *pString, ...);
+
+#endif
diff --git a/core/mac/src/pe/sch/sch_message.c b/core/mac/src/pe/sch/sch_message.c
new file mode 100644
index 0000000..e746f8b
--- /dev/null
+++ b/core/mac/src/pe/sch/sch_message.c
@@ -0,0 +1,574 @@
+/*
+ * Copyright (c) 2012-2015 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.
+ */
+
+#include "cds_api.h"
+#include "sir_common.h"
+
+#include "wni_cfg.h"
+#include "ani_global.h"
+#include "cfg_api.h"
+#include "lim_api.h"
+#include "lim_send_messages.h"
+
+#include "sch_api.h"
+#include "sch_debug.h"
+
+/* / Minimum beacon interval allowed (in Kus) */
+#define SCH_BEACON_INTERVAL_MIN 10
+
+/* / Maximum beacon interval allowed (in Kus) */
+#define SCH_BEACON_INTERVAL_MAX 10000
+
+/* / convert the CW values into a uint16_t */
+#define GET_CW(pCw) ((uint16_t) ((*(pCw) << 8) + *((pCw) + 1)))
+
+/* local functions */
+static tSirRetStatus get_wmm_local_params(tpAniSirGlobal pMac,
+ uint32_t
+ params[]
+ [WNI_CFG_EDCA_ANI_ACBK_LOCAL_LEN]);
+static void set_sch_edca_params(tpAniSirGlobal pMac,
+ uint32_t params[][WNI_CFG_EDCA_ANI_ACBK_LOCAL_LEN],
+ tpPESession psessionEntry);
+
+/* -------------------------------------------------------------------- */
+/**
+ * sch_set_beacon_interval
+ *
+ * FUNCTION:
+ *
+ * LOGIC:
+ *
+ * ASSUMPTIONS:
+ *
+ * NOTE:
+ *
+ * @param None
+ * @return None
+ */
+
+void sch_set_beacon_interval(tpAniSirGlobal pMac, tpPESession psessionEntry)
+{
+ uint32_t bi;
+
+ bi = psessionEntry->beaconParams.beaconInterval;
+
+ if (bi < SCH_BEACON_INTERVAL_MIN || bi > SCH_BEACON_INTERVAL_MAX) {
+ sch_log(pMac, LOGE,
+ FL("Invalid beacon interval %d (should be [%d,%d]"), bi,
+ SCH_BEACON_INTERVAL_MIN, SCH_BEACON_INTERVAL_MAX);
+ return;
+ }
+
+ pMac->sch.schObject.gSchBeaconInterval = (uint16_t) bi;
+}
+
+/* -------------------------------------------------------------------- */
+/**
+ * sch_process_message
+ *
+ * FUNCTION:
+ *
+ * LOGIC:
+ *
+ * ASSUMPTIONS:
+ *
+ * NOTE:
+ *
+ * @param None
+ * @return None
+ */
+
+void sch_process_message(tpAniSirGlobal pMac, tpSirMsgQ pSchMsg)
+{
+ uint32_t val;
+
+ tpPESession psessionEntry = &pMac->lim.gpSession[0];
+ PELOG3(sch_log(pMac, LOG3, FL("Received message (%x) "), pSchMsg->type);)
+
+ switch (pSchMsg->type) {
+
+ case SIR_SCH_CHANNEL_SWITCH_REQUEST:
+ sch_log(pMac, LOGE, FL("Channel switch request not handled"));
+ break;
+
+ case SIR_SCH_START_SCAN_REQ:
+ pMac->sch.gSchScanReqRcvd = true;
+ if (pMac->sch.gSchHcfEnabled) {
+ /* In HCF mode, wait for TFP to stop before sending a response */
+ if (pMac->sch.schObject.gSchCFBInitiated ||
+ pMac->sch.schObject.gSchCFPInitiated) {
+ PELOG1(sch_log(pMac, LOG1,
+ FL
+ ("Waiting for TFP to halt before sending "
+ "start scan response"));
+ )
+ } else
+ sch_send_start_scan_rsp(pMac);
+ } else {
+ /* In eDCF mode, send the response right away */
+ sch_send_start_scan_rsp(pMac);
+ }
+ break;
+
+ case SIR_SCH_END_SCAN_NTF:
+ PELOG3(sch_log(pMac, LOG3,
+ FL("Received STOP_SCAN_NTF from LIM"));
+ )
+ pMac->sch.gSchScanReqRcvd = false;
+ break;
+
+ case SIR_CFG_PARAM_UPDATE_IND:
+
+ if (wlan_cfg_get_int(pMac, (uint16_t) pSchMsg->bodyval, &val) !=
+ eSIR_SUCCESS)
+ sch_log(pMac, LOGP, FL("failed to cfg get id %d"),
+ pSchMsg->bodyval);
+
+ switch (pSchMsg->bodyval) {
+ case WNI_CFG_BEACON_INTERVAL:
+ /* What to do for IBSS ?? - TBD */
+ if (LIM_IS_AP_ROLE(psessionEntry))
+ sch_set_beacon_interval(pMac, psessionEntry);
+ break;
+
+ case WNI_CFG_DTIM_PERIOD:
+ pMac->sch.schObject.gSchDTIMCount = 0;
+ break;
+
+ case WNI_CFG_CFP_PERIOD:
+ pMac->sch.schObject.gSchCFPCount = 0;
+ break;
+
+ case WNI_CFG_EDCA_PROFILE:
+ sch_edca_profile_update(pMac, psessionEntry);
+ break;
+
+ case WNI_CFG_EDCA_ANI_ACBK_LOCAL:
+ case WNI_CFG_EDCA_ANI_ACBE_LOCAL:
+ case WNI_CFG_EDCA_ANI_ACVI_LOCAL:
+ case WNI_CFG_EDCA_ANI_ACVO_LOCAL:
+ case WNI_CFG_EDCA_WME_ACBK_LOCAL:
+ case WNI_CFG_EDCA_WME_ACBE_LOCAL:
+ case WNI_CFG_EDCA_WME_ACVI_LOCAL:
+ case WNI_CFG_EDCA_WME_ACVO_LOCAL:
+ if (LIM_IS_AP_ROLE(psessionEntry))
+ sch_qos_update_local(pMac, psessionEntry);
+ break;
+
+ case WNI_CFG_EDCA_ANI_ACBK:
+ case WNI_CFG_EDCA_ANI_ACBE:
+ case WNI_CFG_EDCA_ANI_ACVI:
+ case WNI_CFG_EDCA_ANI_ACVO:
+ case WNI_CFG_EDCA_WME_ACBK:
+ case WNI_CFG_EDCA_WME_ACBE:
+ case WNI_CFG_EDCA_WME_ACVI:
+ case WNI_CFG_EDCA_WME_ACVO:
+ if (LIM_IS_AP_ROLE(psessionEntry)) {
+ psessionEntry->gLimEdcaParamSetCount++;
+ sch_qos_update_broadcast(pMac, psessionEntry);
+ }
+ break;
+
+ default:
+ sch_log(pMac, LOGE,
+ FL("Cfg param %d indication not handled"),
+ pSchMsg->bodyval);
+ }
+ break;
+
+ default:
+ sch_log(pMac, LOGE, FL("Unknown message in schMsgQ type %d"),
+ pSchMsg->type);
+ }
+
+}
+
+/* get the local or broadcast parameters based on the profile sepcified in the config */
+/* params are delivered in this order: BK, BE, VI, VO */
+tSirRetStatus
+sch_get_params(tpAniSirGlobal pMac,
+ uint32_t params[][WNI_CFG_EDCA_ANI_ACBK_LOCAL_LEN], uint8_t local)
+{
+ uint32_t val;
+ uint32_t i, idx;
+ uint32_t *prf;
+
+ uint32_t ani_l[] = {
+ WNI_CFG_EDCA_ANI_ACBE_LOCAL, WNI_CFG_EDCA_ANI_ACBK_LOCAL,
+ WNI_CFG_EDCA_ANI_ACVI_LOCAL, WNI_CFG_EDCA_ANI_ACVO_LOCAL};
+ uint32_t wme_l[] = {
+ WNI_CFG_EDCA_WME_ACBE_LOCAL, WNI_CFG_EDCA_WME_ACBK_LOCAL,
+ WNI_CFG_EDCA_WME_ACVI_LOCAL, WNI_CFG_EDCA_WME_ACVO_LOCAL};
+ uint32_t ani_b[] = { WNI_CFG_EDCA_ANI_ACBE, WNI_CFG_EDCA_ANI_ACBK,
+ WNI_CFG_EDCA_ANI_ACVI, WNI_CFG_EDCA_ANI_ACVO};
+ uint32_t wme_b[] = { WNI_CFG_EDCA_WME_ACBE, WNI_CFG_EDCA_WME_ACBK,
+ WNI_CFG_EDCA_WME_ACVI, WNI_CFG_EDCA_WME_ACVO};
+
+ if (wlan_cfg_get_int(pMac, WNI_CFG_EDCA_PROFILE, &val) != eSIR_SUCCESS) {
+ sch_log(pMac, LOGP, FL("failed to cfg get EDCA_PROFILE id %d"),
+ WNI_CFG_EDCA_PROFILE);
+ return eSIR_FAILURE;
+ }
+
+ if (val >= WNI_CFG_EDCA_PROFILE_MAX) {
+ sch_log(pMac, LOGE,
+ FL("Invalid EDCA_PROFILE %d, using %d instead"), val,
+ WNI_CFG_EDCA_PROFILE_ANI);
+ val = WNI_CFG_EDCA_PROFILE_ANI;
+ }
+
+ sch_log(pMac, LOGW, FL("EdcaProfile: Using %d (%s)"), val,
+ ((val == WNI_CFG_EDCA_PROFILE_WMM) ? "WMM" : "HiPerf"));
+
+ if (local) {
+ switch (val) {
+ case WNI_CFG_EDCA_PROFILE_WMM:
+ prf = &wme_l[0];
+ break;
+ case WNI_CFG_EDCA_PROFILE_ANI:
+ default:
+ prf = &ani_l[0];
+ break;
+ }
+ } else {
+ switch (val) {
+ case WNI_CFG_EDCA_PROFILE_WMM:
+ prf = &wme_b[0];
+ break;
+ case WNI_CFG_EDCA_PROFILE_ANI:
+ default:
+ prf = &ani_b[0];
+ break;
+ }
+ }
+
+ for (i = 0; i < 4; i++) {
+ uint8_t data[WNI_CFG_EDCA_ANI_ACBK_LEN];
+ uint32_t len = WNI_CFG_EDCA_ANI_ACBK_LOCAL_LEN;
+ if (wlan_cfg_get_str
+ (pMac, (uint16_t) prf[i], (uint8_t *) &data[0],
+ &len) != eSIR_SUCCESS) {
+ sch_log(pMac, LOGP, FL("cfgGet failed for %d"), prf[i]);
+ return eSIR_FAILURE;
+ }
+ if (len > WNI_CFG_EDCA_ANI_ACBK_LOCAL_LEN) {
+ sch_log(pMac, LOGE,
+ FL("cfgGet for %d: length is %d instead of %d"),
+ prf[i], len, WNI_CFG_EDCA_ANI_ACBK_LOCAL_LEN);
+ return eSIR_FAILURE;
+ }
+ for (idx = 0; idx < len; idx++)
+ params[i][idx] = (uint32_t) data[idx];
+ }
+ PELOG1(sch_log
+ (pMac, LOG1, FL("GetParams: local=%d, profile = %d Done"), local,
+ val);
+ )
+ return eSIR_SUCCESS;
+}
+
+/**
+ * broadcast_wmm_of_concurrent_sta_session() - broadcasts wmm info
+ * @mac_ctx: mac global context
+ * @session: pesession entry
+ *
+ * Return: void
+ */
+static void
+broadcast_wmm_of_concurrent_sta_session(tpAniSirGlobal mac_ctx,
+ tpPESession session)
+{
+ uint8_t i, j;
+ tpPESession concurrent_session = NULL;
+
+ for (i = 0; i < mac_ctx->lim.maxBssId; i++) {
+ /*
+ * Find another INFRA STA AP session on same operating channel.
+ * The session entry passed to this API is for GO/SoftAP session
+ * that is getting added currently
+ */
+ if (!((mac_ctx->lim.gpSession[i].valid == true) &&
+ (mac_ctx->lim.gpSession[i].peSessionId !=
+ session->peSessionId)
+ && (mac_ctx->lim.gpSession[i].currentOperChannel ==
+ session->currentOperChannel)
+ && (mac_ctx->lim.gpSession[i].limSystemRole
+ == eLIM_STA_ROLE)))
+ continue;
+
+ concurrent_session = &(mac_ctx->lim.gpSession[i]);
+ break;
+ }
+
+ if (concurrent_session == NULL)
+ return;
+ /*
+ * Once atleast one concurrent session on same channel is found and WMM
+ * broadcast params for current SoftAP/GO session updated, return
+ */
+ for (j = 0; j < MAX_NUM_AC; j++) {
+ session->gLimEdcaParamsBC[j].aci.acm =
+ concurrent_session->gLimEdcaParams[j].aci.acm;
+ session->gLimEdcaParamsBC[j].aci.aifsn =
+ concurrent_session->gLimEdcaParams[j].aci.aifsn;
+ session->gLimEdcaParamsBC[j].cw.min =
+ concurrent_session->gLimEdcaParams[j].cw.min;
+ session->gLimEdcaParamsBC[j].cw.max =
+ concurrent_session->gLimEdcaParams[j].cw.max;
+ session->gLimEdcaParamsBC[j].txoplimit =
+ concurrent_session->gLimEdcaParams[j].txoplimit;
+ PELOG1(sch_log(mac_ctx, LOG1,
+ FL("QoSUpdateBCast changed again due to concurrent INFRA STA session: AC :%d: AIFSN: %d, ACM %d, CWmin %d, CWmax %d, TxOp %d"),
+ j, session->gLimEdcaParamsBC[j].aci.aifsn,
+ session->gLimEdcaParamsBC[j].aci.acm,
+ session->gLimEdcaParamsBC[j].cw.min,
+ session->gLimEdcaParamsBC[j].cw.max,
+ session->gLimEdcaParamsBC[j].txoplimit);)
+ }
+}
+
+void sch_qos_update_broadcast(tpAniSirGlobal pMac, tpPESession psessionEntry)
+{
+ uint32_t params[4][WNI_CFG_EDCA_ANI_ACBK_LOCAL_LEN];
+ uint32_t cwminidx, cwmaxidx, txopidx;
+ uint32_t phyMode;
+ uint8_t i;
+
+ if (sch_get_params(pMac, params, false) != eSIR_SUCCESS) {
+ PELOGE(sch_log(pMac, LOGE, FL("QosUpdateBroadcast: failed"));)
+ return;
+ }
+ lim_get_phy_mode(pMac, &phyMode, psessionEntry);
+
+ PELOG1(sch_log(pMac, LOG1, "QosUpdBcast: mode %d", phyMode);)
+
+ if (phyMode == WNI_CFG_PHY_MODE_11G) {
+ cwminidx = WNI_CFG_EDCA_PROFILE_CWMING_IDX;
+ cwmaxidx = WNI_CFG_EDCA_PROFILE_CWMAXG_IDX;
+ txopidx = WNI_CFG_EDCA_PROFILE_TXOPG_IDX;
+ } else if (phyMode == WNI_CFG_PHY_MODE_11B) {
+ cwminidx = WNI_CFG_EDCA_PROFILE_CWMINB_IDX;
+ cwmaxidx = WNI_CFG_EDCA_PROFILE_CWMAXB_IDX;
+ txopidx = WNI_CFG_EDCA_PROFILE_TXOPB_IDX;
+ } else {
+ /* This can happen if mode is not set yet, assume 11a mode */
+ cwminidx = WNI_CFG_EDCA_PROFILE_CWMINA_IDX;
+ cwmaxidx = WNI_CFG_EDCA_PROFILE_CWMAXA_IDX;
+ txopidx = WNI_CFG_EDCA_PROFILE_TXOPA_IDX;
+ }
+
+ for (i = 0; i < MAX_NUM_AC; i++) {
+ psessionEntry->gLimEdcaParamsBC[i].aci.acm =
+ (uint8_t) params[i][WNI_CFG_EDCA_PROFILE_ACM_IDX];
+ psessionEntry->gLimEdcaParamsBC[i].aci.aifsn =
+ (uint8_t) params[i][WNI_CFG_EDCA_PROFILE_AIFSN_IDX];
+ psessionEntry->gLimEdcaParamsBC[i].cw.min =
+ convert_cw(GET_CW(¶ms[i][cwminidx]));
+ psessionEntry->gLimEdcaParamsBC[i].cw.max =
+ convert_cw(GET_CW(¶ms[i][cwmaxidx]));
+ psessionEntry->gLimEdcaParamsBC[i].txoplimit =
+ (uint16_t) params[i][txopidx];
+
+ PELOG1(sch_log
+ (pMac, LOG1,
+ "QoSUpdateBCast: AC :%d: AIFSN: %d, ACM %d, CWmin %d, CWmax %d, TxOp %d",
+ i, psessionEntry->gLimEdcaParamsBC[i].aci.aifsn,
+ psessionEntry->gLimEdcaParamsBC[i].aci.acm,
+ psessionEntry->gLimEdcaParamsBC[i].cw.min,
+ psessionEntry->gLimEdcaParamsBC[i].cw.max,
+ psessionEntry->gLimEdcaParamsBC[i].txoplimit);
+ )
+
+ }
+
+ /* If there exists a concurrent STA-AP session, use its WMM params to broadcast in beacons. WFA Wifi Direct test plan 6.1.14 requirement */
+ broadcast_wmm_of_concurrent_sta_session(pMac, psessionEntry);
+
+ if (sch_set_fixed_beacon_fields(pMac, psessionEntry) != eSIR_SUCCESS)
+ PELOGE(sch_log(pMac, LOGE, "Unable to set beacon fields!");)
+}
+
+void sch_qos_update_local(tpAniSirGlobal pMac, tpPESession psessionEntry)
+{
+
+ uint32_t params[4][WNI_CFG_EDCA_ANI_ACBK_LOCAL_LEN];
+
+ if (sch_get_params(pMac, params, true /*local */) != eSIR_SUCCESS) {
+ PELOGE(sch_log(pMac, LOGE, FL("sch_get_params(local) failed"));)
+ return;
+ }
+
+ set_sch_edca_params(pMac, params, psessionEntry);
+
+ /* For AP, the bssID is stored in LIM Global context. */
+ lim_send_edca_params(pMac, psessionEntry->gLimEdcaParams,
+ psessionEntry->bssIdx);
+}
+
+/** ----------------------------------------------------------
+ \fn sch_set_default_edca_params
+ \brief This function sets the gLimEdcaParams to the default
+ \ local wmm profile.
+ \param tpAniSirGlobal pMac
+ \return none
+ \ ------------------------------------------------------------ */
+void sch_set_default_edca_params(tpAniSirGlobal pMac, tpPESession psessionEntry)
+{
+ uint32_t params[4][WNI_CFG_EDCA_ANI_ACBK_LOCAL_LEN];
+
+ if (get_wmm_local_params(pMac, params) != eSIR_SUCCESS) {
+ PELOGE(sch_log(pMac, LOGE, FL("get_wmm_local_params() failed"));)
+ return;
+ }
+
+ set_sch_edca_params(pMac, params, psessionEntry);
+ return;
+}
+
+/** ----------------------------------------------------------
+ \fn set_sch_edca_params
+ \brief This function fills in the gLimEdcaParams structure
+ \ with the given edca params.
+ \param tpAniSirGlobal pMac
+ \return none
+ \ ------------------------------------------------------------ */
+static void
+set_sch_edca_params(tpAniSirGlobal pMac,
+ uint32_t params[][WNI_CFG_EDCA_ANI_ACBK_LOCAL_LEN],
+ tpPESession psessionEntry)
+{
+ uint32_t i;
+ uint32_t cwminidx, cwmaxidx, txopidx;
+ uint32_t phyMode;
+
+ lim_get_phy_mode(pMac, &phyMode, psessionEntry);
+
+ PELOG1(sch_log(pMac, LOG1, FL("lim_get_phy_mode() = %d"), phyMode);)
+ /* if (pMac->lim.gLimPhyMode == WNI_CFG_PHY_MODE_11G) */
+ if (phyMode == WNI_CFG_PHY_MODE_11G) {
+ cwminidx = WNI_CFG_EDCA_PROFILE_CWMING_IDX;
+ cwmaxidx = WNI_CFG_EDCA_PROFILE_CWMAXG_IDX;
+ txopidx = WNI_CFG_EDCA_PROFILE_TXOPG_IDX;
+ }
+ /* else if (pMac->lim.gLimPhyMode == WNI_CFG_PHY_MODE_11B) */
+ else if (phyMode == WNI_CFG_PHY_MODE_11B) {
+ cwminidx = WNI_CFG_EDCA_PROFILE_CWMINB_IDX;
+ cwmaxidx = WNI_CFG_EDCA_PROFILE_CWMAXB_IDX;
+ txopidx = WNI_CFG_EDCA_PROFILE_TXOPB_IDX;
+ } else {
+ /* This can happen if mode is not set yet, assume 11a mode */
+ cwminidx = WNI_CFG_EDCA_PROFILE_CWMINA_IDX;
+ cwmaxidx = WNI_CFG_EDCA_PROFILE_CWMAXA_IDX;
+ txopidx = WNI_CFG_EDCA_PROFILE_TXOPA_IDX;
+ }
+
+ for (i = 0; i < MAX_NUM_AC; i++) {
+ psessionEntry->gLimEdcaParams[i].aci.acm =
+ (uint8_t) params[i][WNI_CFG_EDCA_PROFILE_ACM_IDX];
+ psessionEntry->gLimEdcaParams[i].aci.aifsn =
+ (uint8_t) params[i][WNI_CFG_EDCA_PROFILE_AIFSN_IDX];
+ psessionEntry->gLimEdcaParams[i].cw.min =
+ convert_cw(GET_CW(¶ms[i][cwminidx]));
+ psessionEntry->gLimEdcaParams[i].cw.max =
+ convert_cw(GET_CW(¶ms[i][cwmaxidx]));
+ psessionEntry->gLimEdcaParams[i].txoplimit =
+ (uint16_t) params[i][txopidx];
+
+ PELOG1(sch_log
+ (pMac, LOG1,
+ FL
+ ("AC :%d: AIFSN: %d, ACM %d, CWmin %d, CWmax %d, TxOp %d"),
+ i, psessionEntry->gLimEdcaParams[i].aci.aifsn,
+ psessionEntry->gLimEdcaParams[i].aci.acm,
+ psessionEntry->gLimEdcaParams[i].cw.min,
+ psessionEntry->gLimEdcaParams[i].cw.max,
+ psessionEntry->gLimEdcaParams[i].txoplimit);
+ )
+
+ }
+ return;
+}
+
+/** ----------------------------------------------------------
+ \fn get_wmm_local_params
+ \brief This function gets the WMM local edca parameters.
+ \param tpAniSirGlobal pMac
+ \param uint32_t params[][WNI_CFG_EDCA_ANI_ACBK_LOCAL_LEN]
+ \return none
+ \ ------------------------------------------------------------ */
+static tSirRetStatus
+get_wmm_local_params(tpAniSirGlobal pMac,
+ uint32_t params[][WNI_CFG_EDCA_ANI_ACBK_LOCAL_LEN])
+{
+ uint32_t i, idx;
+ uint32_t *prf;
+ uint32_t wme_l[] = {
+ WNI_CFG_EDCA_WME_ACBE_LOCAL, WNI_CFG_EDCA_WME_ACBK_LOCAL,
+ WNI_CFG_EDCA_WME_ACVI_LOCAL, WNI_CFG_EDCA_WME_ACVO_LOCAL};
+
+ prf = &wme_l[0];
+ for (i = 0; i < 4; i++) {
+ uint8_t data[WNI_CFG_EDCA_ANI_ACBK_LEN];
+ uint32_t len = WNI_CFG_EDCA_ANI_ACBK_LOCAL_LEN;
+ if (wlan_cfg_get_str
+ (pMac, (uint16_t) prf[i], (uint8_t *) &data[0],
+ &len) != eSIR_SUCCESS) {
+ sch_log(pMac, LOGP, FL("cfgGet failed for %d"), prf[i]);
+ return eSIR_FAILURE;
+ }
+ if (len > WNI_CFG_EDCA_ANI_ACBK_LOCAL_LEN) {
+ sch_log(pMac, LOGE,
+ FL("cfgGet for %d: length is %d instead of %d"),
+ prf[i], len, WNI_CFG_EDCA_ANI_ACBK_LOCAL_LEN);
+ return eSIR_FAILURE;
+ }
+ for (idx = 0; idx < len; idx++)
+ params[i][idx] = (uint32_t) data[idx];
+ }
+ return eSIR_SUCCESS;
+}
+
+/** ----------------------------------------------------------
+ \fn sch_edca_profile_update
+ \brief This function updates the local and broadcast
+ \ EDCA params in the gLimEdcaParams structure. It also
+ \ updates the edcaParamSetCount.
+ \param tpAniSirGlobal pMac
+ \return none
+ \ ------------------------------------------------------------ */
+void sch_edca_profile_update(tpAniSirGlobal pMac, tpPESession psessionEntry)
+{
+ if (LIM_IS_AP_ROLE(psessionEntry) ||
+ LIM_IS_IBSS_ROLE(psessionEntry)) {
+ sch_qos_update_local(pMac, psessionEntry);
+ psessionEntry->gLimEdcaParamSetCount++;
+ sch_qos_update_broadcast(pMac, psessionEntry);
+ }
+}
+
+/* -------------------------------------------------------------------- */
diff --git a/core/mac/src/pe/sch/sch_sys_params.h b/core/mac/src/pe/sch/sch_sys_params.h
new file mode 100644
index 0000000..adf5c19
--- /dev/null
+++ b/core/mac/src/pe/sch/sch_sys_params.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2011-2012, 2014 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 sch_sys_params.h contains scheduler parameter definitions
+ *
+ * Author: Sandesh Goel
+ * Date: 02/25/02
+ * History:-
+ * Date Modified by Modification Information
+ * --------------------------------------------------------------------
+ *
+ */
+
+#ifndef __SCH_SYS_PARAMS_H__
+#define __SCH_SYS_PARAMS_H__
+
+/* / Unsolicited poll period (ms) (0 to disable) */
+#define SCH_POLL_PERIOD 1000
+
+/* / RR timeout value (ms) (0 to disable) */
+#define SCH_RR_TIMEOUT_MS 40
+
+/* / Default CP:CFP ratio */
+#define SCH_DEFAULT_CP_TO_CFP_RATIO 0
+
+/* / Default maximum CFP duration (us) */
+#define SCH_DEFAULT_MAX_CFP_TIME 60000
+
+/* / Default minimum CP duration (us) */
+#define SCH_DEFAULT_MIN_CP_TIME 100
+
+/* / Amount of delay prior to starting CFP (us) */
+#define SCH_CFP_START_DELAY 100
+
+/* / Unit of Txop in micro seconds */
+#define TXOP_UNIT_IN_USEC 32
+
+/* / Minimum amount of time granted per instruction on average (units of txop) */
+#define MIN_TXOP_PER_INSTRUCTION 50
+
+/* / Maximum amount of time granted per instruction (units of txop) */
+#define MAX_TXOP_PER_INSTRUCTION 300 /* HACK - 100 */
+
+/* / Maximum amount of time granted to one entire schedule (units of txop) */
+#define MAX_TXOP_PER_SCHEDULE 400
+
+/* / Scheduling quantum (units of TXOP) */
+#define SCH_QUANTUM_QUEUE 4
+
+/* / Maximum unused quantum allowed to be accumulated by a queue */
+#define MAX_ACCUMULATED_QUANTUM 500
+
+/* / Minimum allocated quantum for an uplink flow before a poll instruction is written */
+#define SCH_MIN_UL_ALLOC 12
+
+/* ---- Scheduling Policy ---- */
+
+/* / Number of QOS classes */
+#define SCH_NUM_QOS_CLASSES 2
+
+#define SCH_POLICY_STRICT_PRI 0
+#define SCH_POLICY_DRR 1
+
+/* / Scheduling quantum for each class if using DRR */
+#define SCH_QUANTUM_CLASS 100
+
+/* / The default scheduling policy between classes */
+#define SCH_POLICY_DEFAULT SCH_POLICY_STRICT_PRI
+
+/* Scheduling weights for each priority */
+
+#define SCH_QUANTUM_0 40
+#define SCH_QUANTUM_1 36
+#define SCH_QUANTUM_2 32
+#define SCH_QUANTUM_3 28
+#define SCH_QUANTUM_4 24
+#define SCH_QUANTUM_5 20
+#define SCH_QUANTUM_6 16
+#define SCH_QUANTUM_7 12
+
+#endif