blob: cb1e80b15a620425ca127dbe8261da16222d6f9d [file] [log] [blame]
/*
* Copyright (c) 2011-2017 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
* above copyright notice and this permission notice appear in all
* copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
/*
* This file was originally distributed by Qualcomm Atheros, Inc.
* under proprietary terms before Copyright ownership was assigned
* to the Linux Foundation.
*/
/*
* This file limUtils.cc contains the utility functions
* LIM uses.
* Author: Chandra Modumudi
* Date: 02/13/02
* History:-
* Date Modified by Modification Information
* --------------------------------------------------------------------
*/
#include "schApi.h"
#include "limUtils.h"
#include "limTypes.h"
#include "limSecurityUtils.h"
#include "limPropExtsUtils.h"
#include "limSendMessages.h"
#include "limSerDesUtils.h"
#include "limAdmitControl.h"
#include "limStaHashApi.h"
#include "dot11f.h"
#include "dot11fdefs.h"
#include "wmmApsd.h"
#include "limTrace.h"
#ifdef FEATURE_WLAN_DIAG_SUPPORT
#include "vos_diag_core_event.h"
#endif //FEATURE_WLAN_DIAG_SUPPORT
#include "limIbssPeerMgmt.h"
#include "limSessionUtils.h"
#ifdef WLAN_FEATURE_VOWIFI_11R
#include "limFTDefs.h"
#endif
#include "limSession.h"
#include "vos_nvitem.h"
#include "pmmApi.h"
#ifdef WLAN_FEATURE_11W
#include "wni_cfg.h"
#endif
#ifdef SAP_AUTH_OFFLOAD
#include "limAssocUtils.h"
#endif
#include "nan_datapath.h"
/* Static global used to mark situations where pMac->lim.gLimTriggerBackgroundScanDuringQuietBss is SET
* and limTriggerBackgroundScanDuringQuietBss() returned failure. In this case, we will stop data
* traffic instead of going into scan. The recover function limProcessQuietBssTimeout() needs to have
* this information. */
static tAniBool glimTriggerBackgroundScanDuringQuietBss_Status = eSIR_TRUE;
/* 11A Channel list to decode RX BD channel information */
static const tANI_U8 abChannel[]= {36,40,44,48,52,56,60,64,100,104,108,112,116,
120,124,128,132,136,140,149,153,157,161,165
#ifdef FEATURE_WLAN_CH144
,144
#endif
};
#define abChannelSize (sizeof(abChannel)/ \
sizeof(abChannel[0]))
#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
static const tANI_U8 aUnsortedChannelList[]= {52,56,60,64,100,104,108,112,116,
120,124,128,132,136,140,36,40,44,48,149,153,157,161,165
#ifdef FEATURE_WLAN_CH144
,144
#endif
};
#define aUnsortedChannelListSize (sizeof(aUnsortedChannelList)/ \
sizeof(aUnsortedChannelList[0]))
#endif
#define SUCCESS 1
#define MAX_DTIM_PERIOD 15
#define MAX_DTIM_COUNT 15
#define DTIM_PERIOD_DEFAULT 1
#define DTIM_COUNT_DEFAULT 1
#define MAX_BA_WINDOW_SIZE_FOR_CISCO 25
/** -------------------------------------------------------------
\fn limAssignDialogueToken
\brief Assigns dialogue token.
\param tpAniSirGlobal pMac
\return tpDialogueToken - dialogueToken data structure.
-------------------------------------------------------------*/
tpDialogueToken
limAssignDialogueToken(tpAniSirGlobal pMac)
{
static tANI_U8 token;
tpDialogueToken pCurrNode;
pCurrNode = vos_mem_malloc(sizeof(tDialogueToken));
if ( NULL == pCurrNode )
{
PELOGE(limLog(pMac, LOGE, FL("AllocateMemory failed"));)
return NULL;
}
vos_mem_set((void *) pCurrNode, sizeof(tDialogueToken), 0);
//first node in the list is being added.
if(NULL == pMac->lim.pDialogueTokenHead)
{
pMac->lim.pDialogueTokenHead = pMac->lim.pDialogueTokenTail = pCurrNode;
}
else
{
pMac->lim.pDialogueTokenTail->next = pCurrNode;
pMac->lim.pDialogueTokenTail = pCurrNode;
}
//assocId and tid of the node will be filled in by caller.
pCurrNode->next = NULL;
pCurrNode->token = token++;
/* Dialog token should be a non-zero value */
if (0 == pCurrNode->token)
pCurrNode->token = token;
PELOG4(limLog(pMac, LOG4, FL("token assigned = %d"), pCurrNode->token);)
return pCurrNode;
}
/** -------------------------------------------------------------
\fn limSearchAndDeleteDialogueToken
\brief search dialogue token in the list and deletes it if found. returns failure if not found.
\param tpAniSirGlobal pMac
\param tANI_U8 token
\param tANI_U16 assocId
\param tANI_U16 tid
\return eSirRetStatus - status of the search
-------------------------------------------------------------*/
tSirRetStatus
limSearchAndDeleteDialogueToken(tpAniSirGlobal pMac, tANI_U8 token, tANI_U16 assocId, tANI_U16 tid)
{
tpDialogueToken pCurrNode = pMac->lim.pDialogueTokenHead;
tpDialogueToken pPrevNode = pMac->lim.pDialogueTokenHead;
//if the list is empty
if(NULL == pCurrNode)
return eSIR_FAILURE;
// if the matching node is the first node.
if(pCurrNode &&
(assocId == pCurrNode->assocId) &&
(tid == pCurrNode->tid))
{
pMac->lim.pDialogueTokenHead = pCurrNode->next;
//there was only one node in the list. So tail pointer also needs to be adjusted.
if(NULL == pMac->lim.pDialogueTokenHead)
pMac->lim.pDialogueTokenTail = NULL;
vos_mem_free(pCurrNode);
pMac->lim.pDialogueTokenHead = NULL;
return eSIR_SUCCESS;
}
//first node did not match. so move to the next one.
pCurrNode = pCurrNode->next;
while(NULL != pCurrNode )
{
if(token == pCurrNode->token)
{
break;
}
pPrevNode = pCurrNode;
pCurrNode = pCurrNode->next;
}
if(pCurrNode &&
(assocId == pCurrNode->assocId) &&
(tid == pCurrNode->tid))
{
pPrevNode->next = pCurrNode->next;
//if the node being deleted is the last one then we also need to move the tail pointer to the prevNode.
if(NULL == pCurrNode->next)
pMac->lim.pDialogueTokenTail = pPrevNode;
vos_mem_free(pCurrNode);
pMac->lim.pDialogueTokenHead = NULL;
return eSIR_SUCCESS;
}
PELOGW(limLog(pMac, LOGW, FL("LIM does not have matching dialogue token node"));)
return eSIR_FAILURE;
}
/** -------------------------------------------------------------
\fn limDeleteDialogueTokenList
\brief deletes the complete lim dialogue token linked list.
\param tpAniSirGlobal pMac
\return None
-------------------------------------------------------------*/
void
limDeleteDialogueTokenList(tpAniSirGlobal pMac)
{
tpDialogueToken pCurrNode = pMac->lim.pDialogueTokenHead;
while(NULL != pMac->lim.pDialogueTokenHead)
{
pCurrNode = pMac->lim.pDialogueTokenHead;
pMac->lim.pDialogueTokenHead = pMac->lim.pDialogueTokenHead->next;
vos_mem_free(pCurrNode);
pCurrNode = NULL;
}
pMac->lim.pDialogueTokenTail = NULL;
}
void
limGetBssidFromBD(tpAniSirGlobal pMac, tANI_U8 * pRxPacketInfo, tANI_U8 *bssId, tANI_U32 *pIgnore)
{
tpSirMacDataHdr3a pMh = WDA_GET_RX_MPDUHEADER3A(pRxPacketInfo);
*pIgnore = 0;
if (pMh->fc.toDS == 1 && pMh->fc.fromDS == 0)
{
vos_mem_copy( bssId, pMh->addr1, 6);
*pIgnore = 1;
}
else if (pMh->fc.toDS == 0 && pMh->fc.fromDS == 1)
{
vos_mem_copy ( bssId, pMh->addr2, 6);
*pIgnore = 1;
}
else if (pMh->fc.toDS == 0 && pMh->fc.fromDS == 0)
{
vos_mem_copy( bssId, pMh->addr3, 6);
*pIgnore = 0;
}
else
{
vos_mem_copy( bssId, pMh->addr1, 6);
*pIgnore = 1;
}
}
char *
limDot11ReasonStr(tANI_U16 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 *
limMlmStateStr(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
limPrintMlmState(tpAniSirGlobal pMac, tANI_U16 logLevel, tLimMlmStates state)
{
limLog(pMac, logLevel, limMlmStateStr(state));
}
char* limBssTypeStr(tSirBssType bssType)
{
switch(bssType)
{
case eSIR_INFRASTRUCTURE_MODE:
return "eSIR_INFRASTRUCTURE_MODE";
case eSIR_IBSS_MODE:
return "eSIR_IBSS_MODE";
case eSIR_BTAMP_STA_MODE:
return "eSIR_BTAMP_STA_MODE";
case eSIR_BTAMP_AP_MODE:
return "eSIR_BTAMP_AP_MODE";
case eSIR_AUTO_MODE:
return "eSIR_AUTO_MODE";
default:
return "Invalid BSS Type";
}
}
char *limResultCodeStr(tSirResultCodes resultCode)
{
switch (resultCode)
{
case eSIR_SME_SUCCESS:
return "eSIR_SME_SUCCESS";
case eSIR_EOF_SOF_EXCEPTION:
return "eSIR_EOF_SOF_EXCEPTION";
case eSIR_BMU_EXCEPTION:
return "eSIR_BMU_EXCEPTION";
case eSIR_LOW_PDU_EXCEPTION:
return "eSIR_LOW_PDU_EXCEPTION";
case eSIR_USER_TRIG_RESET:
return"eSIR_USER_TRIG_RESET";
case eSIR_LOGP_EXCEPTION:
return "eSIR_LOGP_EXCEPTION";
case eSIR_CP_EXCEPTION:
return "eSIR_CP_EXCEPTION";
case eSIR_STOP_BSS:
return "eSIR_STOP_BSS";
case eSIR_AHB_HANG_EXCEPTION:
return "eSIR_AHB_HANG_EXCEPTION";
case eSIR_DPU_EXCEPTION:
return "eSIR_DPU_EXCEPTION";
case eSIR_RXP_EXCEPTION:
return "eSIR_RXP_EXCEPTION";
case eSIR_MCPU_EXCEPTION:
return "eSIR_MCPU_EXCEPTION";
case eSIR_MCU_EXCEPTION:
return "eSIR_MCU_EXCEPTION";
case eSIR_MTU_EXCEPTION:
return "eSIR_MTU_EXCEPTION";
case eSIR_MIF_EXCEPTION:
return "eSIR_MIF_EXCEPTION";
case eSIR_FW_EXCEPTION:
return "eSIR_FW_EXCEPTION";
case eSIR_MAILBOX_SANITY_CHK_FAILED:
return "eSIR_MAILBOX_SANITY_CHK_FAILED";
case eSIR_RADIO_HW_SWITCH_STATUS_IS_OFF:
return "eSIR_RADIO_HW_SWITCH_STATUS_IS_OFF";
case eSIR_CFB_FLAG_STUCK_EXCEPTION:
return "eSIR_CFB_FLAG_STUCK_EXCEPTION";
case eSIR_SME_BASIC_RATES_NOT_SUPPORTED_STATUS:
return "eSIR_SME_BASIC_RATES_NOT_SUPPORTED_STATUS";
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_STA_DISASSOCIATED:
return "eSIR_SME_STA_DISASSOCIATED";
case eSIR_SME_ALREADY_JOINED_A_BSS:
return "eSIR_SME_ALREADY_JOINED_A_BSS";
case eSIR_ULA_COMPLETED:
return "eSIR_ULA_COMPLETED";
case eSIR_ULA_FAILURE:
return "eSIR_ULA_FAILURE";
case eSIR_SME_LINK_ESTABLISHED:
return "eSIR_SME_LINK_ESTABLISHED";
case eSIR_SME_UNABLE_TO_PERFORM_MEASUREMENTS:
return "eSIR_SME_UNABLE_TO_PERFORM_MEASUREMENTS";
case eSIR_SME_UNABLE_TO_PERFORM_DFS:
return "eSIR_SME_UNABLE_TO_PERFORM_DFS";
case eSIR_SME_DFS_FAILED:
return "eSIR_SME_DFS_FAILED";
case eSIR_SME_TRANSFER_STA:
return "eSIR_SME_TRANSFER_STA";
case eSIR_SME_INVALID_LINK_TEST_PARAMETERS:
return "eSIR_SME_INVALID_LINK_TEST_PARAMETERS";
case eSIR_SME_LINK_TEST_MAX_EXCEEDED:
return "eSIR_SME_LINK_TEST_MAX_EXCEEDED";
case eSIR_SME_UNSUPPORTED_RATE:
return "eSIR_SME_UNSUPPORTED_RATE";
case eSIR_SME_LINK_TEST_TIMEOUT:
return "eSIR_SME_LINK_TEST_TIMEOUT";
case eSIR_SME_LINK_TEST_COMPLETE:
return "eSIR_SME_LINK_TEST_COMPLETE";
case eSIR_SME_LINK_TEST_INVALID_STATE:
return "eSIR_SME_LINK_TEST_INVALID_STATE";
case eSIR_SME_LINK_TEST_INVALID_ADDRESS:
return "eSIR_SME_LINK_TEST_INVALID_ADDRESS";
case eSIR_SME_SETCONTEXT_FAILED:
return "eSIR_SME_SETCONTEXT_FAILED";
case eSIR_SME_BSS_RESTART:
return "eSIR_SME_BSS_RESTART";
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_RECEIVED:
return "eSIR_SME_RECEIVED";
case eSIR_SME_CHANNEL_SWITCH_FAIL:
return "eSIR_SME_CHANNEL_SWITCH_FAIL";
case eSIR_SME_CHANNEL_SWITCH_DISABLED:
return "eSIR_SME_CHANNEL_SWITCH_DISABLED";
case eSIR_SME_HAL_SCAN_INIT_FAILED:
return "eSIR_SME_HAL_SCAN_INIT_FAILED";
case eSIR_SME_HAL_SCAN_START_FAILED:
return "eSIR_SME_HAL_SCAN_START_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";
}
}
/**
* limInitMlm() - This function is called by limProcessSmeMessages()
* to initialize MLM state machine on STA
*
* @pMac: Pointer to Global MAC structure
*
* @Return: Status of operation
*/
tSirRetStatus
limInitMlm(tpAniSirGlobal pMac)
{
tANI_U32 retVal;
pMac->lim.gLimTimersCreated = 0;
MTRACE(macTrace(pMac, TRACE_CODE_MLM_STATE, NO_SESSION, pMac->lim.gLimMlmState));
/// Initialize scan result hash table
limReInitScanResults(pMac); //sep26th review
#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
/// Initialize lfr scan result hash table
// Could there be a problem in multisession with SAP/P2P GO, when in the
// middle of FW bg scan, SAP started; Again that could be a problem even on
// infra + SAP/P2P GO too - TBD
limReInitLfrScanResults(pMac);
#endif
/// Initialize number of pre-auth contexts
pMac->lim.gLimNumPreAuthContexts = 0;
/// Initialize MAC based Authentication STA list
limInitPreAuthList(pMac);
// Create timers used by LIM
retVal = limCreateTimers(pMac);
if(retVal != TX_SUCCESS) {
limLog(pMac, LOGP, FL(" limCreateTimers Failed to create lim timers "));
return eSIR_FAILURE;
}
pMac->lim.gLimTimersCreated = 1;
return eSIR_SUCCESS;
} /*** end limInitMlm() ***/
/**
* limCleanupMlm()
*
*FUNCTION:
* This function is called to cleanup any resources
* allocated by the MLM state machine.
*
*PARAMS:
*
*LOGIC:
*
*ASSUMPTIONS:
* NA
*
*NOTE:
* It is assumed that BSS is already informed that we're leaving it
* before this function is called.
*
* @param pMac Pointer to Global MAC structure
* @param None
* @return None
*/
void
limCleanupMlm(tpAniSirGlobal pMac)
{
tANI_U32 n;
tLimPreAuthNode **pAuthNode;
#ifdef WLAN_FEATURE_11W
tANI_U32 bss_entry, sta_entry;
tpDphHashNode pStaDs = NULL;
tpPESession psessionEntry = NULL;
#endif
if (pMac->lim.gLimTimersCreated == 1)
{
// Deactivate and delete MIN/MAX channel timers.
tx_timer_deactivate(&pMac->lim.limTimers.gLimMinChannelTimer);
tx_timer_delete(&pMac->lim.limTimers.gLimMinChannelTimer);
tx_timer_deactivate(&pMac->lim.limTimers.gLimMaxChannelTimer);
tx_timer_delete(&pMac->lim.limTimers.gLimMaxChannelTimer);
tx_timer_deactivate(&pMac->lim.limTimers.gLimPeriodicProbeReqTimer);
tx_timer_delete(&pMac->lim.limTimers.gLimPeriodicProbeReqTimer);
// Deactivate and delete channel switch timer.
tx_timer_deactivate(&pMac->lim.limTimers.gLimChannelSwitchTimer);
tx_timer_delete(&pMac->lim.limTimers.gLimChannelSwitchTimer);
// Deactivate and delete addts response timer.
tx_timer_deactivate(&pMac->lim.limTimers.gLimAddtsRspTimer);
tx_timer_delete(&pMac->lim.limTimers.gLimAddtsRspTimer);
// Deactivate and delete Join failure timer.
tx_timer_deactivate(&pMac->lim.limTimers.gLimJoinFailureTimer);
tx_timer_delete(&pMac->lim.limTimers.gLimJoinFailureTimer);
// Deactivate and delete Periodic Join Probe Request timer.
tx_timer_deactivate(&pMac->lim.limTimers.gLimPeriodicJoinProbeReqTimer);
tx_timer_delete(&pMac->lim.limTimers.gLimPeriodicJoinProbeReqTimer);
// Deactivate and delete Auth Retry timer.
tx_timer_deactivate(&pMac->lim.limTimers.g_lim_periodic_auth_retry_timer);
tx_timer_delete(&pMac->lim.limTimers.g_lim_periodic_auth_retry_timer);
// Deactivate and delete Association failure timer.
tx_timer_deactivate(&pMac->lim.limTimers.gLimAssocFailureTimer);
tx_timer_delete(&pMac->lim.limTimers.gLimAssocFailureTimer);
// Deactivate and delete Reassociation failure timer.
tx_timer_deactivate(&pMac->lim.limTimers.gLimReassocFailureTimer);
tx_timer_delete(&pMac->lim.limTimers.gLimReassocFailureTimer);
// Deactivate and delete Authentication failure timer.
tx_timer_deactivate(&pMac->lim.limTimers.gLimAuthFailureTimer);
tx_timer_delete(&pMac->lim.limTimers.gLimAuthFailureTimer);
// Deactivate and delete Heartbeat timer.
tx_timer_deactivate(&pMac->lim.limTimers.gLimHeartBeatTimer);
tx_timer_delete(&pMac->lim.limTimers.gLimHeartBeatTimer);
// Deactivate and delete wait-for-probe-after-Heartbeat timer.
tx_timer_deactivate(&pMac->lim.limTimers.gLimProbeAfterHBTimer);
tx_timer_delete(&pMac->lim.limTimers.gLimProbeAfterHBTimer);
// Deactivate and delete Quiet timer.
tx_timer_deactivate(&pMac->lim.limTimers.gLimQuietTimer);
tx_timer_delete(&pMac->lim.limTimers.gLimQuietTimer);
// Deactivate and delete Quiet BSS timer.
tx_timer_deactivate(&pMac->lim.limTimers.gLimQuietBssTimer);
tx_timer_delete(&pMac->lim.limTimers.gLimQuietBssTimer);
// Deactivate and delete LIM background scan timer.
tx_timer_deactivate(&pMac->lim.limTimers.gLimBackgroundScanTimer);
tx_timer_delete(&pMac->lim.limTimers.gLimBackgroundScanTimer);
// Deactivate and delete cnf wait timer
for (n = 0; n < (pMac->lim.maxStation + 1); n++)
{
tx_timer_deactivate(&pMac->lim.limTimers.gpLimCnfWaitTimer[n]);
tx_timer_delete(&pMac->lim.limTimers.gpLimCnfWaitTimer[n]);
}
// Deactivate and delete keepalive timer
tx_timer_deactivate(&pMac->lim.limTimers.gLimKeepaliveTimer);
tx_timer_delete(&pMac->lim.limTimers.gLimKeepaliveTimer);
pAuthNode = pMac->lim.gLimPreAuthTimerTable.pTable;
//Deactivate any Authentication response timers
limDeletePreAuthList(pMac);
for (n = 0; n < pMac->lim.gLimPreAuthTimerTable.numEntry; n++)
{
// Delete any Authentication response
// timers, which might have been started.
tx_timer_delete(&pAuthNode[n]->timer);
}
tx_timer_deactivate(&pMac->lim.limTimers.gLimUpdateOlbcCacheTimer);
tx_timer_delete(&pMac->lim.limTimers.gLimUpdateOlbcCacheTimer);
tx_timer_deactivate(&pMac->lim.limTimers.gLimPreAuthClnupTimer);
tx_timer_delete(&pMac->lim.limTimers.gLimPreAuthClnupTimer);
#ifdef WLAN_FEATURE_VOWIFI_11R
// Deactivate and delete FT Preauth response timer
tx_timer_deactivate(&pMac->lim.limTimers.gLimFTPreAuthRspTimer);
tx_timer_delete(&pMac->lim.limTimers.gLimFTPreAuthRspTimer);
#endif
// Deactivate and delete remain on channel timer
tx_timer_deactivate(&pMac->lim.limTimers.gLimRemainOnChannelTimer);
tx_timer_delete(&pMac->lim.limTimers.gLimRemainOnChannelTimer);
#if defined(FEATURE_WLAN_ESE) && !defined(FEATURE_WLAN_ESE_UPLOAD)
// Deactivate and delete TSM
tx_timer_deactivate(&pMac->lim.limTimers.gLimEseTsmTimer);
tx_timer_delete(&pMac->lim.limTimers.gLimEseTsmTimer);
#endif /* FEATURE_WLAN_ESE && !FEATURE_WLAN_ESE_UPLOAD */
tx_timer_deactivate(&pMac->lim.limTimers.gLimDisassocAckTimer);
tx_timer_delete(&pMac->lim.limTimers.gLimDisassocAckTimer);
tx_timer_deactivate(&pMac->lim.limTimers.gLimDeauthAckTimer);
tx_timer_delete(&pMac->lim.limTimers.gLimDeauthAckTimer);
tx_timer_deactivate(&pMac->lim.limTimers.gLimP2pSingleShotNoaInsertTimer);
tx_timer_delete(&pMac->lim.limTimers.gLimP2pSingleShotNoaInsertTimer);
tx_timer_deactivate(&pMac->lim.limTimers.gLimActiveToPassiveChannelTimer);
tx_timer_delete(&pMac->lim.limTimers.gLimActiveToPassiveChannelTimer);
pMac->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
*/
for (bss_entry = 0; bss_entry < pMac->lim.maxBssId; bss_entry++)
{
if (pMac->lim.gpSession[bss_entry].valid)
{
for (sta_entry = 1; sta_entry < pMac->lim.gLimAssocStaLimit;
sta_entry++)
{
psessionEntry = &pMac->lim.gpSession[bss_entry];
pStaDs = dphGetHashEntry(pMac, sta_entry,
&psessionEntry->dph.dphHashTable);
if (NULL == pStaDs)
{
continue;
}
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
FL("Deleting pmfSaQueryTimer for staid[%d]"),
pStaDs->staIndex) ;
tx_timer_deactivate(&pStaDs->pmfSaQueryTimer);
tx_timer_delete(&pStaDs->pmfSaQueryTimer);
}
}
}
#endif
/// Cleanup cached scan list
limReInitScanResults(pMac);
#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
/// Cleanup cached scan list
limReInitLfrScanResults(pMac);
#endif
} /*** end limCleanupMlm() ***/
/**
* limCleanupLmm()
*
*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
limCleanupLmm(tpAniSirGlobal pMac)
{
} /*** end limCleanupLmm() ***/
/**
* limIsAddrBC()
*
*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
*/
tANI_U8
limIsAddrBC(tSirMacAddr macAddr)
{
int i;
for (i = 0; i < 6; i++)
{
if ((macAddr[i] & 0xFF) != 0xFF)
return false;
}
return true;
} /****** end limIsAddrBC() ******/
/**
* limIsGroupAddr()
*
*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
*/
tANI_U8
limIsGroupAddr(tSirMacAddr macAddr)
{
if ((macAddr[0] & 0x01) == 0x01)
return true;
else
return false;
} /****** end limIsGroupAddr() ******/
/**
* limPostMsgApiNoWait()
*
*FUNCTION:
* This function is called from other thread while posting a
* message to LIM message Queue gSirLimMsgQ with NO_WAIT option
*
*LOGIC:
* NA
*
*ASSUMPTIONS:
* NA
*
*NOTE:
* NA
*
* @param pMsg - Pointer to the Global MAC structure
* @param pMsg - Pointer to the message structure
* @return None
*/
tANI_U32
limPostMsgApiNoWait(tpAniSirGlobal pMac, tSirMsgQ *pMsg)
{
limProcessMessages(pMac, pMsg);
return TX_SUCCESS;
} /*** end limPostMsgApiNoWait() ***/
/**
* limPrintMacAddr()
*
*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
limPrintMacAddr(tpAniSirGlobal pMac, tSirMacAddr macAddr, tANI_U8 logLevel)
{
limLog(pMac, logLevel,
FL(MAC_ADDRESS_STR), MAC_ADDR_ARRAY(macAddr));
} /****** end limPrintMacAddr() ******/
/*
* limResetDeferredMsgQ()
*
*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 limResetDeferredMsgQ(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)
/*
* limWriteDeferredMsgQ()
*
*FUNCTION:
* This function queues up a deferred message for later processing on the
* STA side.
*
*PARAMS:
* @param pMac - Pointer to Global MAC structure
* @param limMsg - a LIM message
*
*LOGIC:
*
*ASSUMPTIONS:
* NA
*
*NOTE:
* NA
*
*RETURNS:
* None
*/
tANI_U8 limWriteDeferredMsgQ(tpAniSirGlobal pMac, tpSirMsgQ limMsg)
{
PELOG1(limLog(pMac, LOG1,
FL("** Queue a deferred message (size %d, write %d) - type 0x%x **"),
pMac->lim.gLimDeferredMsgQ.size, pMac->lim.gLimDeferredMsgQ.write,
limMsg->type);)
/*
** check if the deferred message queue is full
**/
if (pMac->lim.gLimDeferredMsgQ.size >= MAX_DEFERRED_QUEUE_LEN)
{
if(!(pMac->lim.deferredMsgCnt & 0xF))
{
limLog(pMac, LOGE,
FL("Deferred Message Queue is full. Msg:%d Messages Failed:%d"),
limMsg->type, ++pMac->lim.deferredMsgCnt);
vos_flush_logs(WLAN_LOG_TYPE_NON_FATAL,
WLAN_LOG_INDICATOR_HOST_DRIVER,
WLAN_LOG_REASON_QUEUE_FULL,
DUMP_VOS_TRACE);
}
else
{
pMac->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 (pMac->lim.gLimDeferredMsgQ.size > 0)
{
PELOGW(limLog(pMac, LOGW, FL("%d Deferred messages (type 0x%x, scan %d, global sme %d, global mlme %d, addts %d)"),
pMac->lim.gLimDeferredMsgQ.size, limMsg->type,
limIsSystemInScanState(pMac),
pMac->lim.gLimSmeState, pMac->lim.gLimMlmState,
pMac->lim.gLimAddtsSent);)
}
/*
** To prevent the deferred Q is full of management frames, only give them certain space
**/
if( SIR_BB_XPORT_MGMT_MSG == limMsg->type )
{
if( LIM_DEFERRED_Q_CHECK_THRESHOLD < pMac->lim.gLimDeferredMsgQ.size )
{
tANI_U16 idx, count = 0;
for(idx = 0; idx < pMac->lim.gLimDeferredMsgQ.size; idx++)
{
if( SIR_BB_XPORT_MGMT_MSG == pMac->lim.gLimDeferredMsgQ.deferredQueue[idx].type )
{
count++;
}
}
if( LIM_MAX_NUM_MGMT_FRAME_DEFERRED < count )
{
//We reach the quota for management frames, drop this one
PELOGW(limLog(pMac, LOGW, FL("Cannot deferred. Msg: %d Too many (count=%d) already"), limMsg->type, count);)
//Return error, caller knows what to do
return TX_QUEUE_FULL;
}
}
}
++pMac->lim.gLimDeferredMsgQ.size;
/* reset the count here since we are able to defer the message */
if(pMac->lim.deferredMsgCnt != 0)
{
pMac->lim.deferredMsgCnt = 0;
}
/*
** if the write pointer hits the end of the queue, rewind it
**/
if (pMac->lim.gLimDeferredMsgQ.write >= MAX_DEFERRED_QUEUE_LEN)
pMac->lim.gLimDeferredMsgQ.write = 0;
/*
** save the message to the queue and advanced the write pointer
**/
vos_mem_copy( (tANI_U8 *)&pMac->lim.gLimDeferredMsgQ.deferredQueue[
pMac->lim.gLimDeferredMsgQ.write++],
(tANI_U8 *)limMsg,
sizeof(tSirMsgQ));
return TX_SUCCESS;
}
/*
* limReadDeferredMsgQ()
*
*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* limReadDeferredMsgQ(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(limLog(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(limLog(pMac, LOG1, FL("DQ msg -- scan %d, global sme %d, global mlme %d, addts %d"),
limIsSystemInScanState(pMac),
pMac->lim.gLimSmeState, pMac->lim.gLimMlmState,
pMac->lim.gLimAddtsSent);)
return(msg);
}
tSirRetStatus
limSysProcessMmhMsgApi(tpAniSirGlobal pMac,
tSirMsgQ *pMsg,
tANI_U8 qType)
{
// FIXME
SysProcessMmhMsg(pMac, pMsg);
return eSIR_SUCCESS;
}
void limHandleUpdateOlbcCache(tpAniSirGlobal pMac)
{
int i;
static int enable;
tUpdateBeaconParams beaconParams;
tpPESession psessionEntry = limIsApSessionActive(pMac);
if (psessionEntry == NULL)
{
PELOGE(limLog(pMac, LOGE, FL(" Session not found"));)
return;
}
vos_mem_set( ( tANI_U8* )&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)
{
PELOG2(limLog(pMac, 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++)
pMac->lim.protStaOverlapCache[i].active = false;
enable = 1;
}
else
{
if (!psessionEntry->gLimOlbcParams.numSta)
{
if (psessionEntry->gLimOlbcParams.protectionEnabled)
{
if (!psessionEntry->gLim11bParams.protectionEnabled)
{
PELOG1(limLog(pMac, LOG1, FL("Overlap cache all clear and no 11B STA detected"));)
limEnable11gProtection(pMac, false, true, &beaconParams, psessionEntry);
}
}
}
if (!psessionEntry->gLimOverlap11gParams.numSta)
{
if (psessionEntry->gLimOverlap11gParams.protectionEnabled)
{
if (!psessionEntry->gLim11gParams.protectionEnabled)
{
PELOG1(limLog(pMac, LOG1, FL("Overlap cache all clear and no 11G STA detected"));)
limEnableHtProtectionFrom11g(pMac, false, true, &beaconParams,psessionEntry);
}
}
}
if (!psessionEntry->gLimOverlapHt20Params.numSta)
{
if (psessionEntry->gLimOverlapHt20Params.protectionEnabled)
{
if (!psessionEntry->gLimHt20Params.protectionEnabled)
{
PELOG1(limLog(pMac, LOG1, FL("Overlap cache all clear and no HT20 STA detected"));)
limEnable11gProtection(pMac, false, true, &beaconParams,psessionEntry);
}
}
}
enable = 0;
}
if ((VOS_FALSE == pMac->sap.SapDfsInfo.is_dfs_cac_timer_running)
&& beaconParams.paramChangeBitmap)
{
schSetFixedBeaconFields(pMac,psessionEntry);
limSendBeaconParams(pMac, &beaconParams, psessionEntry);
}
// Start OLBC timer
if (tx_timer_activate(&pMac->lim.limTimers.gLimUpdateOlbcCacheTimer) != TX_SUCCESS)
{
limLog(pMac, LOGE, FL("tx_timer_activate failed"));
}
}
/**
* limIsNullSsid()
*
*FUNCTION:
* This function checks if Ssid supplied is Null SSID
*
*
*LOGIC:
*
*ASSUMPTIONS:
* NA
*
*NOTE:
* NA
*
* @param tSirMacSSid *
*
*
* @return true if SSID is Null SSID else false
*/
tANI_U8
limIsNullSsid( tSirMacSSid *pSsid )
{
tANI_U8 fNullSsid = false;
tANI_U32 SsidLength;
tANI_U8 *pSsidStr;
do
{
if ( 0 == pSsid->length )
{
fNullSsid = true;
break;
}
#define ASCII_SPACE_CHARACTER 0x20
/* If the first charactes is space and SSID length is 1
* then consider it as NULL SSID*/
if((ASCII_SPACE_CHARACTER == pSsid->ssId[0])&&
(pSsid->length == 1))
{
fNullSsid = true;
break;
}
else
{
/* check if all the charactes in SSID are NULL*/
SsidLength = pSsid->length;
pSsidStr = pSsid->ssId;
while ( SsidLength )
{
if( *pSsidStr )
break;
pSsidStr++;
SsidLength--;
}
if( 0 == SsidLength )
{
fNullSsid = true;
break;
}
}
}
while( 0 );
return fNullSsid;
} /****** end limIsNullSsid() ******/
/** -------------------------------------------------------------
\fn limUpdateProtStaParams
\brief updates protection related counters.
\param tpAniSirGlobal pMac
\param tSirMacAddr peerMacAddr
\param tLimProtStaCacheType protStaCacheType
\param tHalBitVal gfSupported
\param tHalBitVal lsigTxopSupported
\return None
-------------------------------------------------------------*/
void
limUpdateProtStaParams(tpAniSirGlobal pMac,
tSirMacAddr peerMacAddr, tLimProtStaCacheType protStaCacheType,
tHalBitVal gfSupported, tHalBitVal lsigTxopSupported,
tpPESession psessionEntry)
{
tANI_U32 i;
PELOG1(limLog(pMac,LOG1, FL("A STA is associated:"));
limLog(pMac,LOG1, FL("Addr : "));
limPrintMacAddr(pMac, peerMacAddr, LOG1);)
for (i=0; i<LIM_PROT_STA_CACHE_SIZE; i++)
{
if (psessionEntry->protStaCache[i].active)
{
PELOG1(limLog(pMac, LOG1, FL("Addr: "));)
PELOG1(limPrintMacAddr(pMac, psessionEntry->protStaCache[i].addr, LOG1);)
if (vos_mem_compare(
psessionEntry->protStaCache[i].addr,
peerMacAddr, sizeof(tSirMacAddr)))
{
PELOG1(limLog(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(limLog(pMac, LOGE, FL("No space in ProtStaCache"));)
return;
}
vos_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++;
limLog(pMac,LOG1, FL("11B, "));
}
else if(eLIM_PROT_STA_CACHE_TYPE_llG == protStaCacheType)
{
psessionEntry->gLim11gParams.numSta++;
limLog(pMac,LOG1, FL("11G, "));
}
else if(eLIM_PROT_STA_CACHE_TYPE_HT20 == protStaCacheType)
{
psessionEntry->gLimHt20Params.numSta++;
limLog(pMac,LOG1, FL("HT20, "));
}
if(!gfSupported)
{
psessionEntry->gLimNonGfParams.numSta++;
limLog(pMac,LOG1, FL("NonGf, "));
}
if(!lsigTxopSupported)
{
psessionEntry->gLimLsigTxopParams.numSta++;
limLog(pMac,LOG1, FL("!lsigTxopSupported"));
}
}// ---------------------------------------------------------------------
/** -------------------------------------------------------------
\fn limDecideApProtection
\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
limDecideApProtection(tpAniSirGlobal pMac, tSirMacAddr peerMacAddr, tpUpdateBeaconParams pBeaconParams,tpPESession psessionEntry)
{
tANI_U16 tmpAid;
tpDphHashNode pStaDs;
tSirRFBand rfBand = SIR_BAND_UNKNOWN;
tANI_U32 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 = dphLookupHashEntry(pMac, peerMacAddr, &tmpAid, &psessionEntry->dph.dphHashTable);
if(NULL == pStaDs)
{
PELOG1(limLog(pMac, LOG1, FL("pStaDs is NULL"));)
return;
}
limGetRfBand(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)
{
limEnable11aProtection(pMac, true, false, pBeaconParams,psessionEntry);
return;
}
}
}
else if(SIR_BAND_2_4_GHZ== rfBand)
{
limGetPhyMode(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(limLog(pMac, LOG3, FL("Enabling protection from 11B"));)
limEnable11gProtection(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(limLog(pMac, LOG3, FL("Enabling protection from 11B"));)
limEnable11gProtection(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
limEnableHtProtectionFrom11g(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)
{
limEnableHTNonGfProtection(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;
limEnableHT20Protection(pMac, true, false, pBeaconParams, psessionEntry);
}
//Station joining does not support LSIG TXOP Protection
if(!pStaDs->htLsigTXOPProtection)
{
limEnableHTLsigTxopProtection(pMac, false, false, pBeaconParams,psessionEntry);
lsigTxopSupported = eHAL_CLEAR;
}
}
limUpdateProtStaParams(pMac, peerMacAddr, protStaCacheType,
gfSupported, lsigTxopSupported, psessionEntry);
return;
}
/** -------------------------------------------------------------
\fn limEnableOverlap11gProtection
\brief wrapper function for setting overlap 11g protection.
\param tpAniSirGlobal pMac
\param tpUpdateBeaconParams pBeaconParams
\param tpSirMacMgmtHdr pMh
\return None
-------------------------------------------------------------*/
void
limEnableOverlap11gProtection(tpAniSirGlobal pMac,
tpUpdateBeaconParams pBeaconParams, tpSirMacMgmtHdr pMh,tpPESession psessionEntry)
{
limUpdateOverlapStaParam(pMac, pMh->bssId, &(psessionEntry->gLimOlbcParams));
if (psessionEntry->gLimOlbcParams.numSta &&
!psessionEntry->gLimOlbcParams.protectionEnabled)
{
// enable protection
PELOG1(limLog(pMac, LOG1, FL("OLBC happens!!!"));)
limEnable11gProtection(pMac, true, true, pBeaconParams,psessionEntry);
}
}
/** -------------------------------------------------------------
\fn limUpdateShortPreamble
\brief Updates short preamble if needed when a new station joins.
\param tpAniSirGlobal pMac
\param tSirMacAddr peerMacAddr
\param tpUpdateBeaconParams pBeaconParams
\return None
-------------------------------------------------------------*/
void
limUpdateShortPreamble(tpAniSirGlobal pMac, tSirMacAddr peerMacAddr,
tpUpdateBeaconParams pBeaconParams, tpPESession psessionEntry)
{
tANI_U16 tmpAid;
tpDphHashNode pStaDs;
tANI_U32 phyMode;
tANI_U16 i;
// check whether to enable protection or not
pStaDs = dphLookupHashEntry(pMac, peerMacAddr, &tmpAid, &psessionEntry->dph.dphHashTable);
limGetPhyMode(pMac, &phyMode, psessionEntry);
if (pStaDs != NULL && phyMode == WNI_CFG_PHY_MODE_11G)
{
if (pStaDs->shortPreambleEnabled == eHAL_CLEAR)
{
PELOG1(limLog(pMac,LOG1,FL("Short Preamble is not enabled in Assoc Req from "));
limPrintMacAddr(pMac, peerMacAddr, LOG1);)
for (i = 0; i < LIM_PROT_STA_CACHE_SIZE; i++) {
if (LIM_IS_AP_ROLE(psessionEntry) &&
psessionEntry->gLimNoShortParams.staNoShortCache[i].active) {
if (vos_mem_compare(
psessionEntry->gLimNoShortParams.staNoShortCache[i].addr,
peerMacAddr, sizeof(tSirMacAddr)))
return;
} else if (!LIM_IS_AP_ROLE(psessionEntry)) {
if (pMac->lim.gLimNoShortParams.staNoShortCache[i].active) {
if (vos_mem_compare(
pMac->lim.gLimNoShortParams.staNoShortCache[i].addr,
peerMacAddr, sizeof(tSirMacAddr)))
return;
}
}
}
for (i = 0; i < LIM_PROT_STA_CACHE_SIZE; i++) {
if (LIM_IS_AP_ROLE(psessionEntry) &&
!psessionEntry->gLimNoShortParams.staNoShortCache[i].active)
break;
else {
if (!pMac->lim.gLimNoShortParams.staNoShortCache[i].active)
break;
}
}
if (i >= LIM_PROT_STA_CACHE_SIZE) {
if (LIM_IS_AP_ROLE(psessionEntry)) {
limLog(pMac, LOGE, FL("No space in Short cache (#active %d, #sta %d) for sta "),
i, psessionEntry->gLimNoShortParams.numNonShortPreambleSta);
limPrintMacAddr(pMac, peerMacAddr, LOGE);
return;
} else {
limLog(pMac, LOGE, FL("No space in Short cache (#active %d, #sta %d) for sta "),
i, pMac->lim.gLimNoShortParams.numNonShortPreambleSta);
limPrintMacAddr(pMac, peerMacAddr, LOGE);
return;
}
}
if (LIM_IS_AP_ROLE(psessionEntry)) {
vos_mem_copy(psessionEntry->gLimNoShortParams.staNoShortCache[i].addr,
peerMacAddr, sizeof(tSirMacAddr));
psessionEntry->gLimNoShortParams.staNoShortCache[i].active = true;
psessionEntry->gLimNoShortParams.numNonShortPreambleSta++;
} else {
vos_mem_copy(pMac->lim.gLimNoShortParams.staNoShortCache[i].addr,
peerMacAddr, sizeof(tSirMacAddr));
pMac->lim.gLimNoShortParams.staNoShortCache[i].active = true;
pMac->lim.gLimNoShortParams.numNonShortPreambleSta++;
}
// enable long preamble
PELOG1(limLog(pMac, LOG1, FL("Disabling short preamble"));)
if (limEnableShortPreamble(pMac, false, pBeaconParams, psessionEntry) != eSIR_SUCCESS)
PELOGE(limLog(pMac, LOGE, FL("Cannot enable long preamble"));)
}
}
}
/** -------------------------------------------------------------
\fn limUpdateShortSlotTime
\brief Updates short slot time if needed when a new station joins.
\param tpAniSirGlobal pMac
\param tSirMacAddr peerMacAddr
\param tpUpdateBeaconParams pBeaconParams
\return None
-------------------------------------------------------------*/
void
limUpdateShortSlotTime(tpAniSirGlobal pMac, tSirMacAddr peerMacAddr,
tpUpdateBeaconParams pBeaconParams, tpPESession psessionEntry)
{
tANI_U16 tmpAid;
tpDphHashNode pStaDs;
tANI_U32 phyMode;
tANI_U32 val;
tANI_U16 i;
// check whether to enable protection or not
pStaDs = dphLookupHashEntry(pMac, peerMacAddr, &tmpAid, &psessionEntry->dph.dphHashTable);
limGetPhyMode(pMac, &phyMode, psessionEntry);
/* 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
*/
if (pStaDs != NULL && phyMode == WNI_CFG_PHY_MODE_11G)
{
/* 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 limDecideShortSlot
*/
if (pStaDs->shortSlotTimeEnabled == eHAL_CLEAR)
{
PELOG1(limLog(pMac, LOG1, FL("Short Slot Time is not enabled in Assoc Req from "));
limPrintMacAddr(pMac, peerMacAddr, LOG1);)
for (i = 0; i < LIM_PROT_STA_CACHE_SIZE; i++)
{
if (LIM_IS_AP_ROLE(psessionEntry) &&
psessionEntry->gLimNoShortSlotParams.staNoShortSlotCache[i].active) {
if (vos_mem_compare(
psessionEntry->gLimNoShortSlotParams.staNoShortSlotCache[i].addr,
peerMacAddr, sizeof(tSirMacAddr)))
return;
} else if (!LIM_IS_AP_ROLE(psessionEntry)) {
if (pMac->lim.gLimNoShortSlotParams.staNoShortSlotCache[i].active)
{
if (vos_mem_compare(
pMac->lim.gLimNoShortSlotParams.staNoShortSlotCache[i].addr,
peerMacAddr, sizeof(tSirMacAddr)))
return;
}
}
}
for (i = 0; i < LIM_PROT_STA_CACHE_SIZE; i++) {
if (LIM_IS_AP_ROLE(psessionEntry) &&
!psessionEntry->gLimNoShortSlotParams.staNoShortSlotCache[i].active)
break;
else {
if (!pMac->lim.gLimNoShortSlotParams.staNoShortSlotCache[i].active)
break;
}
}
if (i >= LIM_PROT_STA_CACHE_SIZE) {
if (LIM_IS_AP_ROLE(psessionEntry)) {
limLog(pMac, LOGE, FL("No space in ShortSlot cache (#active %d, #sta %d) for sta "),
i, psessionEntry->gLimNoShortSlotParams.numNonShortSlotSta);
limPrintMacAddr(pMac, peerMacAddr, LOGE);
return;
} else {
limLog(pMac, LOGE, FL("No space in ShortSlot cache (#active %d, #sta %d) for sta "),
i, pMac->lim.gLimNoShortSlotParams.numNonShortSlotSta);
limPrintMacAddr(pMac, peerMacAddr, LOGE);
return;
}
}
if (LIM_IS_AP_ROLE(psessionEntry)) {
vos_mem_copy(psessionEntry->gLimNoShortSlotParams.staNoShortSlotCache[i].addr,
peerMacAddr, sizeof(tSirMacAddr));
psessionEntry->gLimNoShortSlotParams.staNoShortSlotCache[i].active = true;
psessionEntry->gLimNoShortSlotParams.numNonShortSlotSta++;
} else {
vos_mem_copy( pMac->lim.gLimNoShortSlotParams.staNoShortSlotCache[i].addr,
peerMacAddr, sizeof(tSirMacAddr));
pMac->lim.gLimNoShortSlotParams.staNoShortSlotCache[i].active = true;
pMac->lim.gLimNoShortSlotParams.numNonShortSlotSta++;
}
wlan_cfgGetInt(pMac, 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(psessionEntry)) && (val &&
psessionEntry->gLimNoShortSlotParams.numNonShortSlotSta &&
psessionEntry->shortSlotTimeSupported)) {
// enable long slot time
pBeaconParams->fShortSlotTime = false;
pBeaconParams->paramChangeBitmap |= PARAM_SHORT_SLOT_TIME_CHANGED;
PELOG1(limLog(pMac, LOG1, FL("Disable short slot time. Enable long slot time."));)
psessionEntry->shortSlotTimeSupported = false;
} else if (!LIM_IS_AP_ROLE(psessionEntry)) {
if (val && pMac->lim.gLimNoShortSlotParams.numNonShortSlotSta &&
psessionEntry->shortSlotTimeSupported) {
// enable long slot time
pBeaconParams->fShortSlotTime = false;
pBeaconParams->paramChangeBitmap |= PARAM_SHORT_SLOT_TIME_CHANGED;
PELOG1(limLog(pMac, LOG1, FL("Disable short slot time. Enable long slot time."));)
psessionEntry->shortSlotTimeSupported = false;
}
}
}
}
}
/** -------------------------------------------------------------
\fn limDecideStaProtectionOnAssoc
\brief Decide protection related settings on Sta while association.
\param tpAniSirGlobal pMac
\param tpSchBeaconStruct pBeaconStruct
\return None
-------------------------------------------------------------*/
void
limDecideStaProtectionOnAssoc(tpAniSirGlobal pMac,
tpSchBeaconStruct pBeaconStruct, tpPESession psessionEntry)
{
tSirRFBand rfBand = SIR_BAND_UNKNOWN;
tANI_U32 phyMode = WNI_CFG_PHY_MODE_NONE;
limGetRfBand(pMac, &rfBand, psessionEntry);
limGetPhyMode(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 = (tANI_U8)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 =
( tANI_U8 ) htInfo.rifsMode;
psessionEntry->beaconParams.llnNonGFCoexist =
( tANI_U8 )htInfo.nonGFDevicesPresent;
psessionEntry->beaconParams.fLsigTXOPProtectionFullSupport =
( tANI_U8 )htInfo.lsigTXOPProtectionFullSupport;
}
}
/** -------------------------------------------------------------
\fn limDecideStaProtection
\brief Decides protection related settings on Sta while processing beacon.
\param tpAniSirGlobal pMac
\param tpUpdateBeaconParams pBeaconParams
\return None
-------------------------------------------------------------*/
void
limDecideStaProtection(tpAniSirGlobal pMac,
tpSchBeaconStruct pBeaconStruct, tpUpdateBeaconParams pBeaconParams, tpPESession psessionEntry)
{
tSirRFBand rfBand = SIR_BAND_UNKNOWN;
tANI_U32 phyMode = WNI_CFG_PHY_MODE_NONE;
limGetRfBand(pMac, &rfBand, psessionEntry);
limGetPhyMode(pMac, &phyMode, psessionEntry);
if(SIR_BAND_5_GHZ == rfBand)
{
//we are HT capable.
if((true == psessionEntry->htCapability) &&
(pBeaconStruct->HTInfo.present))
{
//we are HT capable, AP's HT OPMode is mixed / overlap legacy ==> need protection from 11A.
if((eSIR_HT_OP_MODE_MIXED == pBeaconStruct->HTInfo.opMode) ||
(eSIR_HT_OP_MODE_OVERLAP_LEGACY == pBeaconStruct->HTInfo.opMode))
{
limEnable11aProtection(pMac, true, false, pBeaconParams,psessionEntry);
}
//we are HT capable, AP's HT OPMode is HT20 ==> disable protection from 11A if enabled. enabled
//protection from HT20 if needed.
else if(eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT== pBeaconStruct->HTInfo.opMode)
{
limEnable11aProtection(pMac, false, false, pBeaconParams,psessionEntry);
limEnableHT20Protection(pMac, true, false, pBeaconParams,psessionEntry);
}
else if(eSIR_HT_OP_MODE_PURE == pBeaconStruct->HTInfo.opMode)
{
limEnable11aProtection(pMac, false, false, pBeaconParams,psessionEntry);
limEnableHT20Protection(pMac, false, false, pBeaconParams,psessionEntry);
}
}
}
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.
*/
if (phyMode != WNI_CFG_PHY_MODE_11B)
{
if (pBeaconStruct->erpPresent &&
(pBeaconStruct->erpIEInfo.useProtection ||
pBeaconStruct->erpIEInfo.nonErpPresent))
{
limEnable11gProtection(pMac, true, false, pBeaconParams, psessionEntry);
}
//AP has no 11b station associated.
else
{
//disable protection from 11b station
limEnable11gProtection(pMac, false, false, pBeaconParams, psessionEntry);
}
}
//following code block is only for HT station.
if((psessionEntry->htCapability) &&
(pBeaconStruct->HTInfo.present))
{
tDot11fIEHTInfo htInfo = pBeaconStruct->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))&&
(!psessionEntry->beaconParams.llbCoexist))
{
limEnableHtProtectionFrom11g(pMac, true, false, pBeaconParams,psessionEntry);
}
//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. that is why this check is being done after mixed/legacy mode check.
if ( pMac->lim.gHTOperMode != ( tSirMacHTOperatingMode )htInfo.opMode )
{
pMac->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.
limEnableHtProtectionFrom11g(pMac, false, false, pBeaconParams,psessionEntry);
limEnableHT20Protection(pMac, true, false, pBeaconParams,psessionEntry);
}
//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)
{
limEnableHtProtectionFrom11g(pMac, false, false, pBeaconParams,psessionEntry);
limEnableHT20Protection(pMac, false, false, pBeaconParams,psessionEntry);
}
}
}
}
//following code block is only for HT station. ( 2.4 GHZ as well as 5 GHZ)
if((psessionEntry->htCapability) &&
(pBeaconStruct->HTInfo.present))
{
tDot11fIEHTInfo htInfo = pBeaconStruct->HTInfo;
//Check for changes in protection related factors other than HT operating mode.
//Check for changes in RIFS mode, nonGFDevicesPresent, lsigTXOPProtectionFullSupport.
if ( psessionEntry->beaconParams.fRIFSMode !=
( tANI_U8 ) htInfo.rifsMode )
{
pBeaconParams->fRIFSMode =
psessionEntry->beaconParams.fRIFSMode =
( tANI_U8 ) htInfo.rifsMode;
pBeaconParams->paramChangeBitmap |= PARAM_RIFS_MODE_CHANGED;
}
if ( psessionEntry->beaconParams.llnNonGFCoexist !=
htInfo.nonGFDevicesPresent )
{
pBeaconParams->llnNonGFCoexist =
psessionEntry->beaconParams.llnNonGFCoexist =
( tANI_U8 )htInfo.nonGFDevicesPresent;
pBeaconParams->paramChangeBitmap |=
PARAM_NON_GF_DEVICES_PRESENT_CHANGED;
}
if ( psessionEntry->beaconParams.fLsigTXOPProtectionFullSupport !=
( tANI_U8 )htInfo.lsigTXOPProtectionFullSupport )
{
pBeaconParams->fLsigTXOPProtectionFullSupport =
psessionEntry->beaconParams.fLsigTXOPProtectionFullSupport =
( tANI_U8 )htInfo.lsigTXOPProtectionFullSupport;
pBeaconParams->paramChangeBitmap |=
PARAM_LSIG_TXOP_FULL_SUPPORT_CHANGED;
}
// For Station just update the global lim variable, no need to send message to HAL
// Station already taking care of HT OPR Mode=01, meaning AP is seeing legacy
//stations in overlapping BSS.
if ( psessionEntry->beaconParams.gHTObssMode != ( tANI_U8 )htInfo.obssNonHTStaPresent )
psessionEntry->beaconParams.gHTObssMode = ( tANI_U8 )htInfo.obssNonHTStaPresent ;
}
}
/**
* limProcessChannelSwitchTimeout()
*
*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 limProcessChannelSwitchTimeout(tpAniSirGlobal pMac)
{
tpPESession psessionEntry = NULL;
tANI_U8 channel; // This is received and stored from channelSwitch Action frame
tANI_U8 isSessionPowerActive = false;
psessionEntry = peFindSessionBySessionId(pMac,
pMac->lim.limTimers.gLimChannelSwitchTimer.sessionId);
if (!psessionEntry) {
limLog(pMac, LOGW, FL("Session Does not exist for given sessionID"));
return;
}
if (!LIM_IS_STA_ROLE(psessionEntry)) {
PELOGW(limLog(pMac, LOGW,
"Channel switch can be done only in STA role, Current Role = %d",
GET_LIM_SYSTEM_ROLE(psessionEntry));)
return;
}
if (psessionEntry->gLimSpecMgmt.dot11hChanSwState !=
eLIM_11H_CHANSW_RUNNING) {
limLog(pMac, LOGW,
FL("Channel switch timer should not have been running in state %d"),
psessionEntry->gLimSpecMgmt.dot11hChanSwState);
return;
}
if(pMac->psOffloadEnabled)
{
isSessionPowerActive = pmmPsOffloadIsActive(pMac, psessionEntry);
}
else
{
isSessionPowerActive = limIsSystemInActiveState(pMac);
}
channel = psessionEntry->gLimChannelSwitch.primaryChannel;
/*
* This potentially can create issues if the function tries to set
* channel while device is in power-save, hence putting an extra check
* to verify if the device is in power-save or not
*/
if(!isSessionPowerActive)
{
PELOGW(limLog(pMac, LOGW, FL("Device is not in active state, cannot switch channel"));)
return;
}
// 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;
/*
* If Lim allows Switch channel on same channel on which preauth
* is going on then LIM will not post resume link(WDA_FINISH_SCAN)
* during preauth rsp handling hence firmware may crash on ENTER/
* EXIT BMPS request.
*/
if(psessionEntry->ftPEContext.pFTPreAuthReq)
{
limLog(pMac, LOGE,
FL("Avoid Switch Channel req during pre auth"));
return;
}
/* If link is already suspended mean some off
* channel operation or scan is in progress, Allowing
* Change channel here will lead to either Init Scan
* sent twice or missing Finish scan when change
* channel is completed, this may lead
* to driver in invalid state and crash.
*/
if (limIsLinkSuspended(pMac))
{
limLog(pMac, LOGE, FL("Link is already suspended for "
"some other reason. Return here for sessionId:%d"),
pMac->lim.limTimers.gLimChannelSwitchTimer.sessionId);
return;
}
/* 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(!limIsChannelValidForChannelSwitch(pMac, channel))
{
/* We need to restore pre-channelSwitch state on the STA */
if(limRestorePreChannelSwitchState(pMac, psessionEntry) != eSIR_SUCCESS)
{
limLog(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 !!!
*/
if ((psessionEntry->limMlmState == eLIM_MLM_LINK_ESTABLISHED_STATE) &&
(psessionEntry->limSmeState != eLIM_SME_WT_DISASSOC_STATE)&&
(psessionEntry->limSmeState != eLIM_SME_WT_DEAUTH_STATE)) {
limLog(pMac, LOGE, FL("Invalid channel!! Disconnect.."));
limTearDownLinkWithAp(pMac,
pMac->lim.limTimers.gLimChannelSwitchTimer.sessionId,
eSIR_MAC_UNSPEC_FAILURE_REASON);
}
return;
}
limCovertChannelScanType(pMac, psessionEntry->currentOperChannel, false);
pMac->lim.dfschannelList.timeStamp[psessionEntry->currentOperChannel] = 0;
switch(psessionEntry->gLimChannelSwitch.state)
{
case eLIM_CHANNEL_SWITCH_PRIMARY_ONLY:
PELOGW(limLog(pMac, LOGW, FL("CHANNEL_SWITCH_PRIMARY_ONLY "));)
limSwitchPrimaryChannel(pMac, psessionEntry->gLimChannelSwitch.primaryChannel,psessionEntry);
psessionEntry->gLimChannelSwitch.state = eLIM_CHANNEL_SWITCH_IDLE;
break;
case eLIM_CHANNEL_SWITCH_SECONDARY_ONLY:
PELOGW(limLog(pMac, LOGW, FL("CHANNEL_SWITCH_SECONDARY_ONLY "));)
limSwitchPrimarySecondaryChannel(pMac, psessionEntry,
psessionEntry->currentOperChannel,
psessionEntry->gLimChannelSwitch.secondarySubBand);
psessionEntry->gLimChannelSwitch.state = eLIM_CHANNEL_SWITCH_IDLE;
break;
case eLIM_CHANNEL_SWITCH_PRIMARY_AND_SECONDARY:
PELOGW(limLog(pMac, LOGW, FL("CHANNEL_SWITCH_PRIMARY_AND_SECONDARY"));)
limSwitchPrimarySecondaryChannel(pMac, psessionEntry,
psessionEntry->gLimChannelSwitch.primaryChannel,
psessionEntry->gLimChannelSwitch.secondarySubBand);
psessionEntry->gLimChannelSwitch.state = eLIM_CHANNEL_SWITCH_IDLE;
break;
case eLIM_CHANNEL_SWITCH_IDLE:
default:
PELOGE(limLog(pMac, LOGE, FL("incorrect state "));)
if(limRestorePreChannelSwitchState(pMac, psessionEntry) != eSIR_SUCCESS)
{
limLog(pMac, LOGP, FL("Could not restore pre-channelSwitch (11h) state, resetting the system"));
}
return; /* Please note, this is 'return' and not 'break' */
}
}
/**
* limUpdateChannelSwitch()
*
*FUNCTION:
* This function is invoked whenever Station receives
* either 802.11h channel switch IE or airgo proprietary
* channel switch IE.
*
*NOTE:
* @param pMac - Pointer to Global MAC structure
* @return tpSirProbeRespBeacon - Pointer to Beacon/Probe Rsp
* @param psessionentry
*/
void
limUpdateChannelSwitch(struct sAniSirGlobal *pMac, tpSirProbeRespBeacon pBeacon,
tpPESession psessionEntry)
{
tANI_U16 beaconPeriod;
tDot11fIEChanSwitchAnn *pChnlSwitch;
#ifdef WLAN_FEATURE_11AC
tDot11fIEWiderBWChanSwitchAnn *pWiderChnlSwitch;
#endif
beaconPeriod = psessionEntry->beaconParams.beaconInterval;
/* 802.11h standard channel switch IE */
pChnlSwitch = &(pBeacon->channelSwitchIE);
psessionEntry->gLimChannelSwitch.primaryChannel = pChnlSwitch->newChannel;
psessionEntry->gLimChannelSwitch.switchCount = pChnlSwitch->switchCount;
psessionEntry->gLimChannelSwitch.switchTimeoutValue =
SYS_MS_TO_TICKS(beaconPeriod)* (pChnlSwitch->switchCount);
psessionEntry->gLimChannelSwitch.switchMode = pChnlSwitch->switchMode;
#ifdef WLAN_FEATURE_11AC
pWiderChnlSwitch = &(pBeacon->WiderBWChanSwitchAnn);
if (pBeacon->WiderBWChanSwitchAnnPresent) {
psessionEntry->gLimWiderBWChannelSwitch.newChanWidth =
pWiderChnlSwitch->newChanWidth;
psessionEntry->gLimWiderBWChannelSwitch.newCenterChanFreq0 =
pWiderChnlSwitch->newCenterChanFreq0;
psessionEntry->gLimWiderBWChannelSwitch.newCenterChanFreq1 =
pWiderChnlSwitch->newCenterChanFreq1;
}
#endif
/* Only primary channel switch element is present */
psessionEntry->gLimChannelSwitch.state = eLIM_CHANNEL_SWITCH_PRIMARY_ONLY;
psessionEntry->gLimChannelSwitch.secondarySubBand =
PHY_SINGLE_CHANNEL_CENTERED;
/* Do not bother to look and operate on extended channel switch element
* if our own channel-bonding state is not enabled
*/
if (psessionEntry->htSupportedChannelWidthSet) {
if (pBeacon->sec_chan_offset_present) {
if ((pBeacon->sec_chan_offset.secondaryChannelOffset ==
PHY_DOUBLE_CHANNEL_LOW_PRIMARY) ||
(pBeacon->sec_chan_offset.secondaryChannelOffset ==
PHY_DOUBLE_CHANNEL_HIGH_PRIMARY)) {
psessionEntry->gLimChannelSwitch.state =
eLIM_CHANNEL_SWITCH_PRIMARY_AND_SECONDARY;
psessionEntry->gLimChannelSwitch.secondarySubBand =
pBeacon->sec_chan_offset.secondaryChannelOffset;
}
#ifdef WLAN_FEATURE_11AC
if (psessionEntry->vhtCapability &&
pBeacon->WiderBWChanSwitchAnnPresent) {
if (pWiderChnlSwitch->newChanWidth ==
WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ) {
if (pBeacon->sec_chan_offset_present) {
if ((pBeacon->sec_chan_offset.secondaryChannelOffset ==
PHY_DOUBLE_CHANNEL_LOW_PRIMARY) ||
(pBeacon->sec_chan_offset.secondaryChannelOffset ==
PHY_DOUBLE_CHANNEL_HIGH_PRIMARY)) {
psessionEntry->gLimChannelSwitch.state =
eLIM_CHANNEL_SWITCH_PRIMARY_AND_SECONDARY;
psessionEntry->gLimChannelSwitch.secondarySubBand =
limGet11ACPhyCBState(pMac,
psessionEntry->gLimChannelSwitch.primaryChannel,
pBeacon->sec_chan_offset.secondaryChannelOffset,
pWiderChnlSwitch->newCenterChanFreq0,
psessionEntry);
}
}
}
}
#endif
}
}
if (eSIR_SUCCESS != limStartChannelSwitch(pMac, psessionEntry)) {
PELOGW(limLog(pMac, LOGW, FL("Could not start Channel Switch"));)
}
limLog(pMac, LOGW,
FL("session %d primary chl %d, subband %d, count %d (%d ticks)"),
psessionEntry->peSessionId,
psessionEntry->gLimChannelSwitch.primaryChannel,
psessionEntry->gLimChannelSwitch.secondarySubBand,
psessionEntry->gLimChannelSwitch.switchCount,
psessionEntry->gLimChannelSwitch.switchTimeoutValue);
return;
}
/**
* limCancelDot11hChannelSwitch
*
*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 limCancelDot11hChannelSwitch(tpAniSirGlobal pMac, tpPESession psessionEntry)
{
if (!LIM_IS_STA_ROLE(psessionEntry))
return;
PELOGW(limLog(pMac, LOGW, FL("Received a beacon without channel switch IE"));)
MTRACE(macTrace(pMac, TRACE_CODE_TIMER_DEACTIVATE, psessionEntry->peSessionId, eLIM_CHANNEL_SWITCH_TIMER));
if (tx_timer_deactivate(&pMac->lim.limTimers.gLimChannelSwitchTimer) != eSIR_SUCCESS)
{
PELOGE(limLog(pMac, LOGE, FL("tx_timer_deactivate failed!"));)
}
/* We need to restore pre-channelSwitch state on the STA */
if (limRestorePreChannelSwitchState(pMac, psessionEntry) != eSIR_SUCCESS)
{
PELOGE(limLog(pMac, LOGE, FL("LIM: Could not restore pre-channelSwitch (11h) state, resetting the system"));)
}
}
/**----------------------------------------------
\fn limCancelDot11hQuiet
\brief Cancel the quieting on Station if latest
beacon doesn't contain quiet IE in it.
\param pMac
\return NONE
-----------------------------------------------*/
void limCancelDot11hQuiet(tpAniSirGlobal pMac, tpPESession psessionEntry)
{
if (!LIM_IS_STA_ROLE(psessionEntry))
return;
if (psessionEntry->gLimSpecMgmt.quietState == eLIM_QUIET_BEGIN)
{
MTRACE(macTrace(pMac, TRACE_CODE_TIMER_DEACTIVATE, psessionEntry->peSessionId, eLIM_QUIET_TIMER));
if (tx_timer_deactivate(&pMac->lim.limTimers.gLimQuietTimer) != TX_SUCCESS)
{
PELOGE(limLog(pMac, LOGE, FL("tx_timer_deactivate failed"));)
}
}
else if (psessionEntry->gLimSpecMgmt.quietState == eLIM_QUIET_RUNNING)
{
MTRACE(macTrace(pMac, TRACE_CODE_TIMER_DEACTIVATE, psessionEntry->peSessionId, eLIM_QUIET_BSS_TIMER));
if (tx_timer_deactivate(&pMac->lim.limTimers.gLimQuietBssTimer) != TX_SUCCESS)
{
PELOGE(limLog(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)))
{
limFrameTransmissionControl(pMac, eLIM_TX_ALL, eLIM_RESUME_TX);
limRestorePreQuietState(pMac, psessionEntry);
}
}
psessionEntry->gLimSpecMgmt.quietState = eLIM_QUIET_INIT;
}
/**
* limProcessQuietTimeout
*
* 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 limProcessQuietTimeout(tpAniSirGlobal pMac)
{
tpPESession psessionEntry;
if((psessionEntry = peFindSessionBySessionId(pMac, pMac->lim.limTimers.gLimQuietTimer.sessionId))== NULL)
{
limLog(pMac, LOGE,FL("Session Does not exist for given sessionID"));
return;
}
PELOG1(limLog(pMac, LOG1, FL("quietState = %d"), psessionEntry->gLimSpecMgmt.quietState);)
switch( psessionEntry->gLimSpecMgmt.quietState )
{
case eLIM_QUIET_BEGIN:
// Time to Stop data traffic for quietDuration
//limDeactivateAndChangeTimer(pMac, eLIM_QUIET_BSS_TIMER);
if (TX_SUCCESS !=
tx_timer_deactivate(&pMac->lim.limTimers.gLimQuietBssTimer))
{
limLog( 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))
{
limLog( pMac, LOGE,
FL("Unable to change gLimQuietBssTimer! Will still attempt to activate anyway..."));
}
MTRACE(macTrace(pMac, TRACE_CODE_TIMER_ACTIVATE, pMac->lim.limTimers.gLimQuietTimer.sessionId, eLIM_QUIET_BSS_TIMER));
if( TX_SUCCESS !=
tx_timer_activate( &pMac->lim.limTimers.gLimQuietBssTimer ))
{
limLog( 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;
/* If we have sta bk scan triggered and trigger bk scan actually started successfully, */
/* print message, otherwise, stop data traffic and stay quiet */
if( pMac->lim.gLimTriggerBackgroundScanDuringQuietBss &&
(eSIR_TRUE == (glimTriggerBackgroundScanDuringQuietBss_Status = limTriggerBackgroundScanDuringQuietBss( pMac ))) )
{
limLog( pMac, LOG2,
FL("Attempting to trigger a background scan..."));
}
else
{
// Shut-off Tx/Rx for gLimSpecMgmt.quietDuration
/* freeze the transmission */
limFrameTransmissionControl(pMac, eLIM_TX_ALL, eLIM_STOP_TX);
limLog( 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;
}
}
/**
* limProcessQuietBssTimeout
*
* FUNCTION:
* This function is active on the AP and STA.
* Handles SIR_LIM_QUIET_BSS_TIMEOUT
*
* LOGIC:
* 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.
* 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
*
* ASSUMPTIONS:
*
* NOTE:
*
* @param pMac - Pointer to Global MAC structure
*
* @return None
*/
void limProcessQuietBssTimeout( tpAniSirGlobal pMac )
{
tpPESession psessionEntry;
if((psessionEntry = peFindSessionBySessionId(pMac, pMac->lim.limTimers.gLimQuietBssTimer.sessionId))== NULL)
{
limLog(pMac, LOGP,FL("Session Does not exist for given sessionID"));
return;
}
PELOG1(limLog(pMac, LOG1, FL("quietState = %d"), psessionEntry->gLimSpecMgmt.quietState);)
if (LIM_IS_AP_ROLE(psessionEntry)) {
} else {
// eLIM_STA_ROLE
switch( psessionEntry->gLimSpecMgmt.quietState )
{
case eLIM_QUIET_RUNNING:
// Transition to eLIM_QUIET_INIT
psessionEntry->gLimSpecMgmt.quietState = eLIM_QUIET_INIT;
if( !pMac->lim.gLimTriggerBackgroundScanDuringQuietBss || (glimTriggerBackgroundScanDuringQuietBss_Status == eSIR_FALSE) )
{
// Resume data traffic only if channel switch is not running in silent mode.
if (!((psessionEntry->gLimSpecMgmt.dot11hChanSwState == eLIM_11H_CHANSW_RUNNING) &&
(psessionEntry->gLimChannelSwitch.switchMode == eSIR_CHANSW_MODE_SILENT)))
{
limFrameTransmissionControl(pMac, eLIM_TX_ALL, eLIM_RESUME_TX);
limRestorePreQuietState(pMac, psessionEntry);
}
/* Reset status flag */
if(glimTriggerBackgroundScanDuringQuietBss_Status == eSIR_FALSE)
glimTriggerBackgroundScanDuringQuietBss_Status = eSIR_TRUE;
limLog( pMac, LOG2,
FL("Quiet BSS: Resuming traffic..."));
}
else
{
//
// Nothing specific to be done in this case
// A background scan that was triggered during
// SIR_LIM_QUIET_TIMEOUT will complete on its own
//
limLog( pMac, LOG2,
FL("Background scan should be complete now..."));
}
break;
case eLIM_QUIET_INIT:
case eLIM_QUIET_BEGIN:
case eLIM_QUIET_END:
PELOG2(limLog(pMac, LOG2, FL("Quiet state not in RUNNING"));)
/* If the quiet period has ended, then resume the frame transmission */
limFrameTransmissionControl(pMac, eLIM_TX_ALL, eLIM_RESUME_TX);
limRestorePreQuietState(pMac, psessionEntry);
psessionEntry->gLimSpecMgmt.quietState = eLIM_QUIET_INIT;
break;
default:
//
// As of now, nothing to be done
//
break;
}
}
}
/**----------------------------------------------
\fn limStartQuietTimer
\brief Starts the quiet timer.
\param pMac
\return NONE
-----------------------------------------------*/
void limStartQuietTimer(tpAniSirGlobal pMac, tANI_U8 sessionId)
{
tpPESession psessionEntry;
psessionEntry = peFindSessionBySessionId(pMac, sessionId);
if(psessionEntry == NULL) {
limLog(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
limCancelDot11hQuiet(pMac, psessionEntry);
MTRACE(macTrace(pMac, TRACE_CODE_TIMER_ACTIVATE, sessionId, eLIM_QUIET_TIMER));
if( TX_SUCCESS != tx_timer_deactivate(&pMac->lim.limTimers.gLimQuietTimer))
{
limLog( 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))
{
limLog( 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))
{
limLog( pMac, LOGE,
FL("Unable to activate gLimQuietTimer! STA cannot honor Quiet BSS!"));
limRestorePreQuietState(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 notify SCH
*/
void
limUtilCountStaAdd(
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
schEdcaProfileUpdate(pMac, psessionEntry);
}
void
limUtilCountStaDel(
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)
{
limLog(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
schEdcaProfileUpdate(pMac, psessionEntry);
}
/**
* limSwitchChannelCback()
*
*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 limSwitchChannelCback(tpAniSirGlobal pMac, eHalStatus status,
tANI_U32 *data, tpPESession psessionEntry)
{
tSirMsgQ mmhMsg = {0};
tSirSmeSwitchChannelInd *pSirSmeSwitchChInd;
psessionEntry->currentOperChannel = psessionEntry->currentReqChannel;
/* We need to restore pre-channelSwitch state on the STA */
if (limRestorePreChannelSwitchState(pMac, psessionEntry) != eSIR_SUCCESS)
{
limLog(pMac, LOGP, FL("Could not restore pre-channelSwitch (11h) state, resetting the system"));
return;
}
mmhMsg.type = eWNI_SME_SWITCH_CHL_REQ;
pSirSmeSwitchChInd = vos_mem_malloc(sizeof(tSirSmeSwitchChannelInd));
if ( NULL == pSirSmeSwitchChInd )
{
limLog(pMac, LOGP, FL("Failed to allocate buffer for buffer descriptor"));
return;
}
pSirSmeSwitchChInd->messageType = eWNI_SME_SWITCH_CHL_REQ;
pSirSmeSwitchChInd->length = sizeof(tSirSmeSwitchChannelInd);
pSirSmeSwitchChInd->newChannelId = psessionEntry->gLimChannelSwitch.primaryChannel;
pSirSmeSwitchChInd->sessionId = psessionEntry->smeSessionId;
vos_mem_copy( pSirSmeSwitchChInd->bssId, psessionEntry->bssId, sizeof(tSirMacAddr));
mmhMsg.bodyptr = pSirSmeSwitchChInd;
mmhMsg.bodyval = 0;
MTRACE(macTrace(pMac, TRACE_CODE_TX_SME_MSG, psessionEntry->peSessionId,
mmhMsg.type));
SysProcessMmhMsg(pMac, &mmhMsg);
}
/**
* limSwitchPrimaryChannel()
*
*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 channel ID
* @return NONE
*/
void limSwitchPrimaryChannel(tpAniSirGlobal pMac, tANI_U8 newChannel,tpPESession psessionEntry)
{
#if !defined WLAN_FEATURE_VOWIFI
tANI_U32 localPwrConstraint;
#endif
PELOG3(limLog(pMac, LOG3, FL("limSwitchPrimaryChannel: old chnl %d --> new chnl %d "),
psessionEntry->currentOperChannel, newChannel);)
psessionEntry->currentReqChannel = newChannel;
psessionEntry->limRFBand = limGetRFBand(newChannel);
psessionEntry->channelChangeReasonCode=LIM_SWITCH_CHANNEL_OPERATION;
pMac->lim.gpchangeChannelCallback = limSwitchChannelCback;
pMac->lim.gpchangeChannelData = NULL;
psessionEntry->sub20_channelwidth =
psessionEntry->lim_sub20_channel_switch_bandwidth;
#if defined WLAN_FEATURE_VOWIFI
limSendSwitchChnlParams(pMac, newChannel, PHY_SINGLE_CHANNEL_CENTERED,
psessionEntry->maxTxPower,
psessionEntry->peSessionId,
VOS_FALSE);
#else
if(wlan_cfgGetInt(pMac, WNI_CFG_LOCAL_POWER_CONSTRAINT, &localPwrConstraint) != eSIR_SUCCESS)
{
limLog( pMac, LOGP, FL( "Unable to read Local Power Constraint from cfg" ));
return;
}
limSendSwitchChnlParams(pMac, newChannel, PHY_SINGLE_CHANNEL_CENTERED,
(tPowerdBm)localPwrConstraint,
psessionEntry->peSessionId,
VOS_FALSE);
#endif
return;
}
/**
* limSwitchPrimarySecondaryChannel()
*
*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 channel 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 limSwitchPrimarySecondaryChannel(tpAniSirGlobal pMac, tpPESession psessionEntry, tANI_U8 newChannel, ePhyChanBondState subband)
{
#if !defined WLAN_FEATURE_VOWIFI
tANI_U32 localPwrConstraint;
#endif
#if !defined WLAN_FEATURE_VOWIFI
if(wlan_cfgGetInt(pMac, WNI_CFG_LOCAL_POWER_CONSTRAINT, &localPwrConstraint) != eSIR_SUCCESS) {
limLog( 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 = limGetRFBand(newChannel);
psessionEntry->channelChangeReasonCode = LIM_SWITCH_CHANNEL_OPERATION;
pMac->lim.gpchangeChannelCallback = limSwitchChannelCback;
pMac->lim.gpchangeChannelData = NULL;
psessionEntry->sub20_channelwidth =
psessionEntry->lim_sub20_channel_switch_bandwidth;
#if defined WLAN_FEATURE_VOWIFI
limSendSwitchChnlParams(pMac, newChannel, subband,
psessionEntry->maxTxPower,
psessionEntry->peSessionId,
VOS_FALSE);
#else
limSendSwitchChnlParams(pMac, newChannel, subband,
(tPowerdBm)localPwrConstraint,
psessionEntry->peSessionId,
VOS_FALSE);
#endif
// Store the new primary and secondary channel in session entries if different
if (psessionEntry->currentOperChannel != newChannel)
{
limLog(pMac, LOGW,
FL("switch old chnl %d --> new chnl %d "),
psessionEntry->currentOperChannel, newChannel);
psessionEntry->currentOperChannel = newChannel;
}
if (psessionEntry->htSecondaryChannelOffset != subband)
{
limLog(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;
}
/**
* limActiveScanAllowed()
*
*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
*/
tANI_U8 limActiveScanAllowed(
tpAniSirGlobal pMac,
tANI_U8 channelNum)
{
tANI_U32 i;
tANI_U8 channelPair[WNI_CFG_SCAN_CONTROL_LIST_LEN];
tANI_U32 len = WNI_CFG_SCAN_CONTROL_LIST_LEN;
if (wlan_cfgGetStr(pMac, WNI_CFG_SCAN_CONTROL_LIST, channelPair, &len)
!= eSIR_SUCCESS)
{
PELOGE(limLog(pMac, LOGE, FL("Unable to get scan control list"));)
return false;
}
if (len > WNI_CFG_SCAN_CONTROL_LIST_LEN)
{
limLog(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;
}
/**
* limTriggerBackgroundScanDuringQuietBss()
*
*FUNCTION:
* This function is applicable to the STA only.
* This function is called by limProcessQuietTimeout(),
* when it is time to honor the Quiet BSS IE from the AP.
*
*LOGIC:
* If 11H is enabled:
* We cannot trigger a background scan. The STA needs to
* shut-off Tx/Rx.
* If 11 is not enabled:
* Determine if the next channel that we are going to
* scan is NOT the same channel (or not) on which the
* Quiet BSS was requested.
* If yes, then we cannot trigger a background scan on
* this channel. Return with a false.
* If no, then trigger a background scan. Return with
* a true.
*
*ASSUMPTIONS:
*
*NOTE:
* This API is redundant if the existing API,
* limTriggerBackgroundScan(), were to return a valid
* response instead of returning void.
* If possible, try to revisit this API
*
* @param pMac Pointer to Global MAC structure
* @return eSIR_TRUE, if a background scan was attempted
* eSIR_FALSE, if not
*/
tAniBool limTriggerBackgroundScanDuringQuietBss( tpAniSirGlobal pMac )
{
tAniBool bScanTriggered = eSIR_FALSE;
tpPESession psessionEntry = &pMac->lim.gpSession[0];
if (!LIM_IS_STA_ROLE(psessionEntry))
return bScanTriggered;
if( !psessionEntry->lim11hEnable )
{
tSirMacChanNum bgScanChannelList[WNI_CFG_BG_SCAN_CHANNEL_LIST_LEN];
tANI_U32 len = WNI_CFG_BG_SCAN_CHANNEL_LIST_LEN;
// Determine the next scan channel
// Get background scan channel list from CFG
if( eSIR_SUCCESS == wlan_cfgGetStr( pMac,
WNI_CFG_BG_SCAN_CHANNEL_LIST,
(tANI_U8 *) bgScanChannelList,
(tANI_U32 *) &len ))
{
// Ensure that we do not go off scanning on the same
// channel on which the Quiet BSS was requested
if( psessionEntry->currentOperChannel!=
bgScanChannelList[pMac->lim.gLimBackgroundScanChannelId] )
{
// For now, try and attempt a background scan. It will
// be ideal if this API actually returns a success or
// failure instead of having a void return type
limTriggerBackgroundScan( pMac );
bScanTriggered = eSIR_TRUE;
}
else
{
limLog( pMac, LOGW,
FL("The next SCAN channel is the current operating channel on which a Quiet BSS is requested.! A background scan will not be triggered during this Quiet BSS period..."));
}
}
else
{
limLog( pMac, LOGW,
FL("Unable to retrieve WNI_CFG_VALID_CHANNEL_LIST from CFG! A background scan will not be triggered during this Quiet BSS period..."));
}
}
return bScanTriggered;
}
/**
* limGetHTCapability()
*
*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 tANI_U8 The current state of the requested HT capability is returned in a
* tANI_U8 variable
*/
tANI_U8 limGetHTCapability( tpAniSirGlobal pMac,
tANI_U32 htCap, tpPESession psessionEntry)
{
tANI_U8 retVal = 0;
tANI_U8 *ptr;
tANI_U32 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 Selection HT Capabilities */
if( eSIR_SUCCESS != wlan_cfgGetInt( pMac, WNI_CFG_AS_CAP, &cfgValue ))
cfgValue = 0;
ptr = (tANI_U8 *) &macASCapabilityInfo;
*((tANI_U8 *)ptr) = (tANI_U8) (cfgValue & 0xff);
}
else
{
if( htCap >= eHT_TX_BEAMFORMING &&
htCap < eHT_ANTENNA_SELECTION )
{
// Get Transmit Beam Forming HT Capabilities
if( eSIR_SUCCESS != wlan_cfgGetInt( pMac, WNI_CFG_TX_BF_CAP, &cfgValue ))
cfgValue = 0;
ptr = (tANI_U8 *) &macTxBFCapabilityInfo;
*((tANI_U32 *)ptr) = (tANI_U32) (cfgValue);
}
else
{
if( htCap >= eHT_PCO &&
htCap < eHT_TX_BEAMFORMING )
{
// Get Extended HT Capabilities
if( eSIR_SUCCESS != wlan_cfgGetInt( pMac, WNI_CFG_EXT_HT_CAP_INFO, &cfgValue ))
cfgValue = 0;
ptr = (tANI_U8 *) &macExtHTCapabilityInfo;
*((tANI_U16 *)ptr) = (tANI_U16) (cfgValue & 0xffff);
}
else
{
if( htCap < eHT_MAX_RX_AMPDU_FACTOR )
{
// Get HT Capabilities
if( eSIR_SUCCESS != wlan_cfgGetInt( pMac, WNI_CFG_HT_CAP_INFO, &cfgValue ))
cfgValue = 0;
ptr = (tANI_U8 *) &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 = (tANI_U8) 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 = (tANI_U8) macHTCapabilityInfo.maximalAMSDUsize;
break;
case eHT_MAX_AMSDU_NUM:
retVal = (tANI_U8) psessionEntry->max_amsdu_num;
break;
case eHT_DELAYED_BA:
retVal = (tANI_U8) macHTCapabilityInfo.delayedBA;
break;
case eHT_RX_STBC:
retVal = (tANI_U8) psessionEntry->htConfig.ht_rx_stbc;
break;
case eHT_TX_STBC:
retVal = (tANI_U8) psessionEntry->htConfig.ht_tx_stbc;
break;
case eHT_SHORT_GI_40MHZ:
retVal =(tANI_U8)
(psessionEntry->htConfig.ht_sgi)? macHTCapabilityInfo.shortGI40MHz : 0;
break;
case eHT_SHORT_GI_20MHZ:
retVal = (tANI_U8)
(psessionEntry->htConfig.ht_sgi)? macHTCapabilityInfo.shortGI20MHz : 0;
break;
case eHT_GREENFIELD:
retVal = (tANI_U8) macHTCapabilityInfo.greenField;
break;
case eHT_MIMO_POWER_SAVE:
retVal = (tANI_U8) pMac->lim.gHTMIMOPSState;
break;
case eHT_SUPPORTED_CHANNEL_WIDTH_SET:
retVal = (tANI_U8) psessionEntry->htSupportedChannelWidthSet;
break;
case eHT_ADVANCED_CODING:
retVal = (tANI_U8) 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 = (tANI_U8) macExtHTCapabilityInfo.pco;
break;
case eHT_TRANSITION_TIME:
retVal = (tANI_U8) macExtHTCapabilityInfo.transitionTime;
break;
case eHT_MCS_FEEDBACK:
retVal = (tANI_U8) macExtHTCapabilityInfo.mcsFeedback;
break;
case eHT_TX_BEAMFORMING:
retVal = (tANI_U8) macTxBFCapabilityInfo.txBF;
break;
case eHT_ANTENNA_SELECTION:
retVal = (tANI_U8) 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;
}
void limGetMyMacAddr(tpAniSirGlobal pMac, tANI_U8 *mac)
{
vos_mem_copy( mac, pMac->lim.gLimMyMacAddr, sizeof(tSirMacAddr));
return;
}
/** -------------------------------------------------------------
\fn limEnable11aProtection
\brief based on config setting enables\disables 11a protection.
\param tANI_U8 enable : 1=> enable protection, 0=> disable protection.
\param tANI_U8 overlap: 1=> called from overlap context, 0 => called from assoc context.
\param tpUpdateBeaconParams pBeaconParams
\return None
-------------------------------------------------------------*/
tSirRetStatus
limEnable11aProtection(tpAniSirGlobal pMac, tANI_U8 enable,
tANI_U8 overlap, tpUpdateBeaconParams pBeaconParams,tpPESession psessionEntry)
{
if(NULL == psessionEntry)
{
PELOG3(limLog(pMac, LOG3, FL("psessionEntry is NULL"));)
return eSIR_FAILURE;
}
//overlapping protection configuration check.
if (overlap) {
} else {
//normal protection config check
if (LIM_IS_AP_ROLE(psessionEntry) &&
(!psessionEntry->cfgProtection.fromlla)) {
// protection disabled.
PELOG3(limLog(pMac, LOG3, FL("protection from 11a 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) ||
LIM_IS_BT_AMP_AP_ROLE(psessionEntry)) &&
(true == psessionEntry->htCapability)) {
if(overlap)
{
pMac->lim.gLimOverlap11aParams.protectionEnabled = true;
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;
psessionEntry->htOperMode = eSIR_HT_OP_MODE_OVERLAP_LEGACY;
limEnableHtRifsProtection(pMac, true, overlap, pBeaconParams,psessionEntry);
limEnableHtOBSSProtection(pMac, true, overlap, pBeaconParams,psessionEntry);
}
}
else
{
psessionEntry->gLim11aParams.protectionEnabled = true;
if(eSIR_HT_OP_MODE_MIXED != psessionEntry->htOperMode)
{
pMac->lim.gHTOperMode = eSIR_HT_OP_MODE_MIXED;
psessionEntry->htOperMode = eSIR_HT_OP_MODE_MIXED;
limEnableHtRifsProtection(pMac, true, overlap, pBeaconParams,psessionEntry);
limEnableHtOBSSProtection(pMac, true, overlap, pBeaconParams,psessionEntry);
}
}
}
/* This part is common for station as well. */
if(false == psessionEntry->beaconParams.llaCoexist)
{
PELOG1(limLog(pMac, LOG1, FL(" => protection from 11A Enabled"));)
pBeaconParams->llaCoexist = psessionEntry->beaconParams.llaCoexist = true;
pBeaconParams->paramChangeBitmap |= PARAM_llACOEXIST_CHANGED;
}
}
else if (true == psessionEntry->beaconParams.llaCoexist)
{
//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.
pMac->lim.gLimOverlap11aParams.protectionEnabled = false;
/* We need to take care of HT OP mode if we are HT AP. */
if(psessionEntry->htCapability)
{
// no HT op mode change if any of the overlap protection enabled.
if(!(pMac->lim.gLimOverlap11aParams.protectionEnabled ||
pMac->lim.gLimOverlapHt20Params.protectionEnabled ||
pMac->lim.gLimOverlapNonGfParams.protectionEnabled))
{
//Check if there is a need to change HT OP mode.
if(eSIR_HT_OP_MODE_OVERLAP_LEGACY == pMac->lim.gHTOperMode)
{
limEnableHtRifsProtection(pMac, false, overlap, pBeaconParams,psessionEntry);
limEnableHtOBSSProtection(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 11A stations.
psessionEntry->gLim11aParams.protectionEnabled = false;
limEnableHtOBSSProtection(pMac, false, overlap, pBeaconParams,psessionEntry);
//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(pMac->lim.gLimOverlap11aParams.protectionEnabled ||
pMac->lim.gLimOverlapHt20Params.protectionEnabled ||
pMac->lim.gLimOverlapNonGfParams.protectionEnabled)
{
pMac->lim.gHTOperMode = eSIR_HT_OP_MODE_OVERLAP_LEGACY;
psessionEntry->htOperMode = eSIR_HT_OP_MODE_OVERLAP_LEGACY;
limEnableHtRifsProtection(pMac, true, overlap, pBeaconParams,psessionEntry);
}
else if(psessionEntry->gLimHt20Params.protectionEnabled)
{
pMac->lim.gHTOperMode = eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT;
psessionEntry->htOperMode = eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT;
limEnableHtRifsProtection(pMac, false, overlap, pBeaconParams,psessionEntry);
}
else
{
pMac->lim.gHTOperMode = eSIR_HT_OP_MODE_PURE;
psessionEntry->htOperMode = eSIR_HT_OP_MODE_PURE;
limEnableHtRifsProtection(pMac, false, overlap, pBeaconParams,psessionEntry);
}
}
if(!pMac->lim.gLimOverlap11aParams.protectionEnabled &&
!psessionEntry->gLim11aParams.protectionEnabled)
{
PELOG1(limLog(pMac, LOG1, FL("===> Protection from 11A Disabled"));)
pBeaconParams->llaCoexist = psessionEntry->beaconParams.llaCoexist = false;
pBeaconParams->paramChangeBitmap |= PARAM_llACOEXIST_CHANGED;
}
}
//for station role
else
{
PELOG1(limLog(pMac, LOG1, FL("===> Protection from 11A Disabled"));)
pBeaconParams->llaCoexist = psessionEntry->beaconParams.llaCoexist = false;
pBeaconParams->paramChangeBitmap |= PARAM_llACOEXIST_CHANGED;
}
}
return eSIR_SUCCESS;
}
/** -------------------------------------------------------------
\fn limEnable11gProtection
\brief based on config setting enables\disables 11g protection.
\param tANI_U8 enable : 1=> enable protection, 0=> disable protection.
\param tANI_U8 overlap: 1=> called from overlap context, 0 => called from assoc context.
\param tpUpdateBeaconParams pBeaconParams
\return None
-------------------------------------------------------------*/
tSirRetStatus
limEnable11gProtection(tpAniSirGlobal pMac, tANI_U8 enable,
tANI_U8 overlap, tpUpdateBeaconParams pBeaconParams,tpPESession psessionEntry)
{
//overlapping protection configuration check.
if (overlap) {
} else {
//normal protection config check
if (LIM_IS_AP_ROLE(psessionEntry) &&
!psessionEntry->cfgProtection.fromllb) {
// protection disabled.
PELOG1(limLog(pMac, LOG1, FL("protection from 11b is disabled"));)
return eSIR_SUCCESS;
} else if (!LIM_IS_AP_ROLE(psessionEntry)) {
if(!pMac->lim.cfgProtection.fromllb) {
// protection disabled.
PELOG1(limLog(pMac, LOG1, FL("protection from 11b 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->gLimOlbcParams.protectionEnabled = true;
PELOGE(limLog(pMac, LOG1, FL("protection from olbc is enabled"));)
if(true == psessionEntry->htCapability)
{
if((eSIR_HT_OP_MODE_OVERLAP_LEGACY != psessionEntry->htOperMode) &&
(eSIR_HT_OP_MODE_MIXED != psessionEntry->htOperMode))
{
psessionEntry->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
limEnableHtRifsProtection(pMac, true, overlap, pBeaconParams,psessionEntry);
//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
limEnableHtOBSSProtection(pMac, true, overlap, pBeaconParams, psessionEntry);
}
}
else
{
psessionEntry->gLim11bParams.protectionEnabled = true;
PELOGE(limLog(pMac, LOG1, FL("protection from 11b is enabled"));)
if(true == psessionEntry->htCapability)
{
if(eSIR_HT_OP_MODE_MIXED != psessionEntry->htOperMode)
{
psessionEntry->htOperMode = eSIR_HT_OP_MODE_MIXED;
limEnableHtRifsProtection(pMac, true, overlap, pBeaconParams,psessionEntry);
limEnableHtOBSSProtection(pMac, true, overlap, pBeaconParams,psessionEntry);
}
}
}
}else if (LIM_IS_BT_AMP_AP_ROLE(psessionEntry) &&
(true == psessionEntry->htCapability)) {
if(overlap)
{
psessionEntry->gLimOlbcParams.protectionEnabled = true;
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;
}
//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
limEnableHtRifsProtection(pMac, true, overlap, pBeaconParams,psessionEntry);
//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
limEnableHtOBSSProtection(pMac, true, overlap, pBeaconParams, psessionEntry);
}
else
{
psessionEntry->gLim11bParams.protectionEnabled = true;
if(eSIR_HT_OP_MODE_MIXED != pMac->lim.gHTOperMode)
{
pMac->lim.gHTOperMode = eSIR_HT_OP_MODE_MIXED;
limEnableHtRifsProtection(pMac, true, overlap, pBeaconParams,psessionEntry);
limEnableHtOBSSProtection(pMac, true, overlap, pBeaconParams,psessionEntry);
}
}
}
/* This part is common for station as well. */
if(false == psessionEntry->beaconParams.llbCoexist)
{
PELOG1(limLog(pMac, LOG1, FL("=> 11G Protection Enabled"));)
pBeaconParams->llbCoexist = psessionEntry->beaconParams.llbCoexist = true;
pBeaconParams->paramChangeBitmap |= PARAM_llBCOEXIST_CHANGED;
}
}
else if (true == psessionEntry->beaconParams.llbCoexist)
{
//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.
psessionEntry->gLimOlbcParams.protectionEnabled = false;
//We need to take care of HT OP mode if we are HT AP.
if(psessionEntry->htCapability)
{
// no HT op mode change if any of the overlap protection enabled.
if(!(psessionEntry->gLimOverlap11gParams.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)
{
limEnableHtRifsProtection(pMac, false, overlap, pBeaconParams,psessionEntry);
limEnableHtOBSSProtection(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 11B stations.
psessionEntry->gLim11bParams.protectionEnabled = false;
PELOGE(limLog(pMac, LOG1, FL("===> 11B Protection Disabled"));)
//Check if any other non-HT protection enabled.
if(!psessionEntry->gLim11gParams.protectionEnabled)
{
//Right now we are in HT OP Mixed mode.
//Change HT op mode appropriately.
limEnableHtOBSSProtection(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;
PELOGE(limLog(pMac, LOG1, FL("===> 11G Protection Disabled"));)
limEnableHtRifsProtection(pMac, true, overlap, pBeaconParams,psessionEntry);
}
else 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;
PELOGE(limLog(pMac, LOG1, FL("===> 11G Protection Disabled"));)
limEnableHtRifsProtection(pMac, false, overlap, pBeaconParams,psessionEntry);
}
else
{
psessionEntry->htOperMode = eSIR_HT_OP_MODE_PURE;
limEnableHtRifsProtection(pMac, false, overlap, pBeaconParams,psessionEntry);
}
}
}
if(!psessionEntry->gLimOlbcParams.protectionEnabled &&
!psessionEntry->gLim11bParams.protectionEnabled)
{
PELOGE(limLog(pMac, LOG1, FL("===> 11G Protection Disabled"));)
pBeaconParams->llbCoexist = psessionEntry->beaconParams.llbCoexist = false;
pBeaconParams->paramChangeBitmap |= PARAM_llBCOEXIST_CHANGED;
}
}else if(LIM_IS_BT_AMP_AP_ROLE(psessionEntry)) {
if(overlap)
{
//Overlap Legacy protection disabled.
psessionEntry->gLimOlbcParams.protectionEnabled = false;
/* We need to take care of HT OP mode if we are HT AP. */
if(psessionEntry->htCapability)
{
// no HT op mode change if any of the overlap protection enabled.
if(!(pMac->lim.gLimOverlap11gParams.protectionEnabled ||
pMac->lim.gLimOverlapHt20Params.protectionEnabled ||
pMac->lim.gLimOverlapNonGfParams.protectionEnabled))
{
//Check if there is a need to change HT OP mode.
if(eSIR_HT_OP_MODE_OVERLAP_LEGACY == pMac->lim.gHTOperMode)
{
limEnableHtRifsProtection(pMac, false, overlap, pBeaconParams,psessionEntry);
limEnableHtOBSSProtection(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 11B stations.
psessionEntry->gLim11bParams.protectionEnabled = false;
//Check if any other non-HT protection enabled.
if(!psessionEntry->gLim11gParams.protectionEnabled)
{
//Right now we are in HT OP Mixed mode.
//Change HT op mode appropriately.
limEnableHtOBSSProtection(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;
limEnableHtRifsProtection(pMac, true, overlap, pBeaconParams,psessionEntry);
}
else if(psessionEntry->gLimHt20Params.protectionEnabled)
{
pMac->lim.gHTOperMode = eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT;
limEnableHtRifsProtection(pMac, false, overlap, pBeaconParams,psessionEntry);
}
else
{
pMac->lim.gHTOperMode = eSIR_HT_OP_MODE_PURE;
limEnableHtRifsProtection(pMac, false, overlap, pBeaconParams,psessionEntry);
}
}
}
if(!psessionEntry->gLimOlbcParams.protectionEnabled &&
!psessionEntry->gLim11bParams.protectionEnabled)
{
PELOG1(limLog(pMac, LOG1, FL("===> 11G Protection Disabled"));)
pBeaconParams->llbCoexist = psessionEntry->beaconParams.llbCoexist = false;
pBeaconParams->paramChangeBitmap |= PARAM_llBCOEXIST_CHANGED;
}
}
//for station role
else
{
PELOG1(limLog(pMac, LOG1, FL("===> 11G Protection Disabled"));)
pBeaconParams->llbCoexist = psessionEntry->beaconParams.llbCoexist = false;
pBeaconParams->paramChangeBitmap |= PARAM_llBCOEXIST_CHANGED;
}
}
return eSIR_SUCCESS;
}
/** -------------------------------------------------------------
\fn limEnableHtProtectionFrom11g
\brief based on cofig enables\disables protection from 11g.
\param tANI_U8 enable : 1=> enable protection, 0=> disable protection.
\param tANI_U8 overlap: 1=> called from overlap context, 0 => called from assoc context.
\param tpUpdateBeaconParams pBeaconParams
\return None
-------------------------------------------------------------*/
tSirRetStatus
limEnableHtProtectionFrom11g(tpAniSirGlobal pMac, tANI_U8 enable,
tANI_U8 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(limLog(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(limLog(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(limLog(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(limLog(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;
}
limEnableHtRifsProtection(pMac, true, overlap, pBeaconParams,psessionEntry);
limEnableHtOBSSProtection(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;
limEnableHtRifsProtection(pMac, true, overlap, pBeaconParams,psessionEntry);
limEnableHtOBSSProtection(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;
limEnableHtRifsProtection(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;
limEnableHtRifsProtection(pMac, true, overlap, pBeaconParams,psessionEntry);
limEnableHtOBSSProtection(pMac, true, overlap, pBeaconParams,psessionEntry);
}
}
}
/* This part is common for station 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)
{
limEnableHtRifsProtection(pMac, false, overlap, pBeaconParams,psessionEntry);
limEnableHtOBSSProtection(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.
limEnableHtOBSSProtection(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;
limEnableHtRifsProtection(pMac, true, overlap, pBeaconParams,psessionEntry);
}
else 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;
limEnableHtRifsProtection(pMac, false, overlap, pBeaconParams,psessionEntry);
}
else
{
psessionEntry->htOperMode = eSIR_HT_OP_MODE_PURE;
limEnableHtRifsProtection(pMac, false, overlap, pBeaconParams,psessionEntry);
}
}
}
if(!psessionEntry->gLimOverlap11gParams.protectionEnabled &&
!psessionEntry->gLim11gParams.protectionEnabled)
{
limLog(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)
{
limEnableHtRifsProtection(pMac, false, overlap, pBeaconParams,psessionEntry);
limEnableHtOBSSProtection(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.
limEnableHtOBSSProtection(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;
limEnableHtRifsProtection(pMac, true, overlap, pBeaconParams,psessionEntry);
}
else if(psessionEntry->gLimHt20Params.protectionEnabled)
{
pMac->lim.gHTOperMode = eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT;
limEnableHtRifsProtection(pMac, false, overlap, pBeaconParams,psessionEntry);
}
else
{
pMac->lim.gHTOperMode = eSIR_HT_OP_MODE_PURE;
limEnableHtRifsProtection(pMac, false, overlap, pBeaconParams,psessionEntry);
}
}
}
if(!pMac->lim.gLimOverlap11gParams.protectionEnabled &&
!psessionEntry->gLim11gParams.protectionEnabled)
{
PELOG1(limLog(pMac, LOG1, FL("===> Protection from 11G Disabled"));)
pBeaconParams->llgCoexist = psessionEntry->beaconParams.llgCoexist = false;
pBeaconParams->paramChangeBitmap |= PARAM_llGCOEXIST_CHANGED;
}
}
//for station role
else
{
PELOG1(limLog(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 tANI_U8 enable : 1=> enable protection, 0=> disable protection.
\param tANI_U8 overlap: 1=> called from overlap context, 0 => called from assoc context.
\param tpUpdateBeaconParams pBeaconParams
\return None
-------------------------------------------------------------*/
tSirRetStatus
limEnableHtOBSSProtection(tpAniSirGlobal pMac, tANI_U8 enable,
tANI_U8 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(limLog(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(limLog(pMac, LOG1, FL("protection from Obss is disabled"));)
return eSIR_SUCCESS;
}
}
}
if (LIM_IS_AP_ROLE(psessionEntry)) {
if ((enable) && (false == psessionEntry->beaconParams.gHTObssMode) )
{
PELOG1(limLog(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(limLog(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(limLog(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(limLog(pMac, LOG1, FL("===> obss Protection disabled"));)
psessionEntry->beaconParams.gHTObssMode = false;
pBeaconParams->paramChangeBitmap |= PARAM_OBSS_MODE_CHANGED;
}
}
return eSIR_SUCCESS;
}
/** -------------------------------------------------------------
\fn limEnableHT20Protection
\brief based on cofig enables\disables protection from Ht20.
\param tANI_U8 enable : 1=> enable protection, 0=> disable protection.
\param tANI_U8 overlap: 1=> called from overlap context, 0 => called from assoc context.
\param tpUpdateBeaconParams pBeaconParams
\return None
-------------------------------------------------------------*/
tSirRetStatus
limEnableHT20Protection(tpAniSirGlobal pMac, tANI_U8 enable,
tANI_U8 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.ht20) {
// protection disabled.
PELOG3(limLog(pMac, LOG3, FL("protection from HT20 is disabled"));)
return eSIR_SUCCESS;
} else if (!LIM_IS_AP_ROLE(psessionEntry)) {
if (!pMac->lim.cfgProtection.ht20) {
// protection disabled.
PELOG3(limLog(pMac, LOG3, FL("protection from HT20 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->gLimOverlapHt20Params.protectionEnabled = true;
if((eSIR_HT_OP_MODE_OVERLAP_LEGACY != psessionEntry->htOperMode) &&
(eSIR_HT_OP_MODE_MIXED != psessionEntry->htOperMode))
{
psessionEntry->htOperMode = eSIR_HT_OP_MODE_OVERLAP_LEGACY;
limEnableHtRifsProtection(pMac, true, overlap, pBeaconParams,psessionEntry);
}
}
else
{
psessionEntry->gLimHt20Params.protectionEnabled = true;
if(eSIR_HT_OP_MODE_PURE == psessionEntry->htOperMode)
{
if (psessionEntry->htSupportedChannelWidthSet !=
eHT_CHANNEL_WIDTH_20MHZ)
psessionEntry->htOperMode =
eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT;
limEnableHtRifsProtection(pMac, false, overlap, pBeaconParams,psessionEntry);
limEnableHtOBSSProtection(pMac, false, overlap, pBeaconParams,psessionEntry);
}
}
} else if(LIM_IS_BT_AMP_AP_ROLE(psessionEntry)) {
if(overlap)
{
pMac->lim.gLimOverlapHt20Params.protectionEnabled = true;
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;
limEnableHtRifsProtection(pMac, true, overlap, pBeaconParams,psessionEntry);
}
}
else
{
psessionEntry->gLimHt20Params.protectionEnabled = true;
if(eSIR_HT_OP_MODE_PURE == pMac->lim.gHTOperMode)
{
pMac->lim.gHTOperMode = eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT;
limEnableHtRifsProtection(pMac, false, overlap, pBeaconParams,psessionEntry);
limEnableHtOBSSProtection(pMac, false, overlap, pBeaconParams,psessionEntry);
}
}
}
/* This part is common for station as well. */
if(false == psessionEntry->beaconParams.ht20Coexist)
{
PELOG1(limLog(pMac, LOG1, FL("=> Protection from HT20 Enabled"));)
pBeaconParams->ht20MhzCoexist = psessionEntry->beaconParams.ht20Coexist = true;
pBeaconParams->paramChangeBitmap |= PARAM_HT20MHZCOEXIST_CHANGED;
}
}
else if (true == psessionEntry->beaconParams.ht20Coexist)
{
//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.
psessionEntry->gLimOverlapHt20Params.protectionEnabled = false;
// no HT op mode change if any of the overlap protection enabled.
if(!(psessionEntry->gLimOlbcParams.protectionEnabled ||
psessionEntry->gLimOverlap11gParams.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)
{
if(psessionEntry->gLimHt20Params.protectionEnabled)
{
if (psessionEntry->htSupportedChannelWidthSet ==
eHT_CHANNEL_WIDTH_20MHZ)
psessionEntry->htOperMode = eSIR_HT_OP_MODE_PURE;
else
psessionEntry->htOperMode = eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT;
limEnableHtRifsProtection(pMac, false, overlap, pBeaconParams,psessionEntry);
limEnableHtOBSSProtection(pMac, false, overlap, pBeaconParams,psessionEntry);
}
else
{
psessionEntry->htOperMode = eSIR_HT_OP_MODE_PURE;
}
}
}
}
else
{
//Disable protection from 11G stations.
psessionEntry->gLimHt20Params.protectionEnabled = false;
//Change HT op mode appropriately.
if(eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT == psessionEntry->htOperMode)
{
psessionEntry->htOperMode = eSIR_HT_OP_MODE_PURE;
limEnableHtRifsProtection(pMac, false, overlap, pBeaconParams,psessionEntry);
limEnableHtOBSSProtection(pMac, false, overlap, pBeaconParams,psessionEntry);
}
}
PELOG1(limLog(pMac, LOG1, FL("===> Protection from HT 20 Disabled"));)
pBeaconParams->ht20MhzCoexist = psessionEntry->beaconParams.ht20Coexist = false;
pBeaconParams->paramChangeBitmap |= PARAM_HT20MHZCOEXIST_CHANGED;
} else if(LIM_IS_BT_AMP_AP_ROLE(psessionEntry)) {
if(overlap)
{
//Overlap Legacy protection disabled.
pMac->lim.gLimOverlapHt20Params.protectionEnabled = false;
// no HT op mode change if any of the overlap protection enabled.
if(!(psessionEntry->gLimOlbcParams.protectionEnabled ||
pMac->lim.gLimOverlap11gParams.protectionEnabled ||
pMac->lim.gLimOverlapHt20Params.protectionEnabled ||
pMac->lim.gLimOverlapNonGfParams.protectionEnabled))
{
//Check if there is a need to change HT OP mode.
if(eSIR_HT_OP_MODE_OVERLAP_LEGACY == pMac->lim.gHTOperMode)
{
if(psessionEntry->gLimHt20Params.protectionEnabled)
{
pMac->lim.gHTOperMode = eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT;
limEnableHtRifsProtection(pMac, false, overlap, pBeaconParams,psessionEntry);
limEnableHtOBSSProtection(pMac, false, overlap, pBeaconParams,psessionEntry);
}
else
{
pMac->lim.gHTOperMode = eSIR_HT_OP_MODE_PURE;
}
}
}
}
else
{
//Disable protection from 11G stations.
psessionEntry->gLimHt20Params.protectionEnabled = false;
//Change HT op mode appropriately.
if(eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT == pMac->lim.gHTOperMode)
{
pMac->lim.gHTOperMode = eSIR_HT_OP_MODE_PURE;
limEnableHtRifsProtection(pMac, false, overlap, pBeaconParams,psessionEntry);
limEnableHtOBSSProtection(pMac, false, overlap, pBeaconParams,psessionEntry);
}
}
PELOG1(limLog(pMac, LOG1, FL("===> Protection from HT 20 Disabled"));)
pBeaconParams->ht20MhzCoexist = psessionEntry->beaconParams.ht20Coexist = false;
pBeaconParams->paramChangeBitmap |= PARAM_HT20MHZCOEXIST_CHANGED;
}
//for station role
else
{
PELOG1(limLog(pMac, LOG1, FL("===> Protection from HT20 Disabled"));)
pBeaconParams->ht20MhzCoexist = psessionEntry->beaconParams.ht20Coexist = false;
pBeaconParams->paramChangeBitmap |= PARAM_HT20MHZCOEXIST_CHANGED;
}
}
return eSIR_SUCCESS;
}
/** -------------------------------------------------------------
\fn limEnableHTNonGfProtection
\brief based on cofig enables\disables protection from NonGf.
\param tANI_U8 enable : 1=> enable protection, 0=> disable protection.
\param tANI_U8 overlap: 1=> called from overlap context, 0 => called from assoc context.
\param tpUpdateBeaconParams pBeaconParams
\return None
-------------------------------------------------------------*/
tSirRetStatus
limEnableHTNonGfProtection(tpAniSirGlobal pMac, tANI_U8 enable,
tANI_U8 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(limLog(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(limLog(pMac, LOG3, FL("protection from NonGf is disabled"));)
return eSIR_SUCCESS;
}
}
}
if (LIM_IS_AP_ROLE(psessionEntry)) {
if ((enable) && (false == psessionEntry->beaconParams.llnNonGFCoexist))
{
PELOG1(limLog(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(limLog(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(limLog(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(limLog(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 limEnableHTLsigTxopProtection
\brief based on cofig enables\disables LsigTxop protection.
\param tANI_U8 enable : 1=> enable protection, 0=> disable protection.
\param tANI_U8 overlap: 1=> called from overlap context, 0 => called from assoc context.
\param tpUpdateBeaconParams pBeaconParams
\return None
-------------------------------------------------------------*/
tSirRetStatus
limEnableHTLsigTxopProtection(tpAniSirGlobal pMac, tANI_U8 enable,
tANI_U8 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(limLog(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(limLog(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(limLog(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(limLog(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(limLog(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(limLog(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 limEnableHtRifsProtection
\brief based on cofig enables\disables Rifs protection.
\param tANI_U8 enable : 1=> enable protection, 0=> disable protection.
\param tANI_U8 overlap: 1=> called from overlap context, 0 => called from assoc context.
\param tpUpdateBeaconParams pBeaconParams
\return None
-------------------------------------------------------------*/
tSirRetStatus
limEnableHtRifsProtection(tpAniSirGlobal pMac, tANI_U8 enable,
tANI_U8 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(limLog(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(limLog(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(limLog(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(limLog(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(limLog(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(limLog(pMac, LOG1, FL("===> Rifs Protection Enabled"));)
pBeaconParams->fRIFSMode = psessionEntry->beaconParams.fRIFSMode = false;
pBeaconParams->paramChangeBitmap |= PARAM_RIFS_MODE_CHANGED;
}
}
return eSIR_SUCCESS;
}
// ---------------------------------------------------------------------
/**
* limEnableShortPreamble
*
* FUNCTION:
* Enable/Disable short preamble
*
* LOGIC:
*
* ASSUMPTIONS:
*
* NOTE:
*
* @param enable Flag to enable/disable short preamble
* @return None
*/
tSirRetStatus
limEnableShortPreamble(tpAniSirGlobal pMac, tANI_U8 enable, tpUpdateBeaconParams pBeaconParams, tpPESession psessionEntry)
{
tANI_U32 val;
if (wlan_cfgGetInt(pMac, WNI_CFG_SHORT_PREAMBLE, &val) != eSIR_SUCCESS)
{
/* Could not get short preamble enabled flag from CFG. Log error. */
limLog(pMac, LOGP, FL("could not retrieve short preamble flag"));
return eSIR_FAILURE;
}
if (!val)
return eSIR_SUCCESS;
if (wlan_cfgGetInt(pMac, WNI_CFG_11G_SHORT_PREAMBLE_ENABLED, &val) != eSIR_SUCCESS)
{
limLog(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(limLog(pMac, LOG1, FL("===> Short Preamble Enabled"));)
psessionEntry->beaconParams.fShortPreamble = true;
pBeaconParams->fShortPreamble = (tANI_U8) psessionEntry->beaconParams.fShortPreamble;
pBeaconParams->paramChangeBitmap |= PARAM_SHORT_PREAMBLE_CHANGED;
}
else if (!enable && (psessionEntry->beaconParams.fShortPreamble == 1))
{
PELOG1(limLog(pMac, LOG1, FL("===> Short Preamble Disabled"));)
psessionEntry->beaconParams.fShortPreamble = false;
pBeaconParams->fShortPreamble = (tANI_U8) psessionEntry->beaconParams.fShortPreamble;
pBeaconParams->paramChangeBitmap |= PARAM_SHORT_PREAMBLE_CHANGED;
}
}
return eSIR_SUCCESS;
}
/**
* limTxComplete
*
* 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 palPktAlloc( ..., **pData, **pPacket )
* LIM transmits the MGMT frame using the API:
* halTxFrame( ... pPacket, ..., (void *) limTxComplete, pData )
* HDD, via halTxFrame/DXE, "transfers" the packet over to BMU
* HDD, if it determines that a TX completion routine (in this case
* limTxComplete) 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 palPktFree( ... 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 palPktFree() 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 limTxComplete( tHalHandle hHal, void *pData, v_BOOL_t free)
{
tpAniSirGlobal pMac;
pMac = (tpAniSirGlobal)hHal;
#ifdef FIXME_PRIMA
/* the trace logic needs to be fixed for Prima. Refer to CR 306075 */
#ifdef TRACE_RECORD
{
tpSirMacMgmtHdr mHdr;
v_U8_t *pRxBd;
vos_pkt_t *pVosPkt;
VOS_STATUS vosStatus;
pVosPkt = (vos_pkt_t *)pData;
vosStatus = vos_pkt_peek_data( pVosPkt, 0, (v_PVOID_t *)&pRxBd, WLANHAL_RX_BD_HEADER_SIZE);
if(VOS_IS_STATUS_SUCCESS(vosStatus))
{
mHdr = WDA_GET_RX_MAC_HEADER(pRxBd);
}
}
#endif
#endif
if (free)
palPktFree( pMac->hHdd,
HAL_TXRX_FRM_802_11_MGMT,
(void *) NULL, /* this is ignored and will likely be removed */
(void *) pData ); /* lim passed in pPacket in pData pointer */
}
/**
* \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 Switch 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 limUpdateStaRunTimeHTSwitchChnlParams( tpAniSirGlobal pMac,
tDot11fIEHTInfo *pHTInfo,
tANI_U8 bssIdx,
tpPESession psessionEntry)
{
ePhyChanBondState secondaryChnlOffset = PHY_SINGLE_CHANNEL_CENTERED;
#if !defined WLAN_FEATURE_VOWIFI
tANI_U32 localPwrConstraint;
#endif
//If self capability is set to '20Mhz only', then do not change the CB mode.
if( !limGetHTCapability( pMac, eHT_SUPPORTED_CHANNEL_WIDTH_SET, psessionEntry ))
return;
if ((RF_CHAN_14 >= psessionEntry->currentOperChannel) &&
psessionEntry->force_24ghz_in_ht20) {
limLog(pMac, LOG1,
FL("force_24_gh_in_ht20 is set and channel is 2.4 Ghz"));
return;
}
#if !defined WLAN_FEATURE_VOWIFI
if(wlan_cfgGetInt(pMac, WNI_CFG_LOCAL_POWER_CONSTRAINT, &localPwrConstraint) != eSIR_SUCCESS) {
limLog( pMac, LOGP, FL( "Unable to get Local Power Constraint from cfg" ));
return;
}
#endif
if (psessionEntry->ftPEContext.ftPreAuthSession) {
limLog( pMac, LOGE, FL( "FT PREAUTH channel change is in progress"));
return;
}
/*
* Do not try to switch channel if RoC is in progress. RoC code path uses
* pMac->lim.gpLimRemainOnChanReq to notify the upper layers that the device
* has started listening on the channel requested as part of RoC, if we set
* pMac->lim.gpLimRemainOnChanReq to NULL as we do below then the
* upper layers will think that the channel change is not successful and the
* RoC from the upper layer perspective will never end...
*/
if (pMac->lim.gpLimRemainOnChanReq)
{
limLog(pMac, LOGE, FL( "RoC is in progress"));
return;
}
if ( psessionEntry->htSecondaryChannelOffset != ( tANI_U8 ) pHTInfo->secondaryChannelOffset ||
psessionEntry->htRecommendedTxWidthSet != ( tANI_U8 ) pHTInfo->recommendedTxWidthSet )
{
psessionEntry->htSecondaryChannelOffset = ( ePhyChanBondState ) pHTInfo->secondaryChannelOffset;
psessionEntry->htRecommendedTxWidthSet = ( tANI_U8 ) pHTInfo->recommendedTxWidthSet;
if ( eHT_CHANNEL_WIDTH_40MHZ == psessionEntry->htRecommendedTxWidthSet )
secondaryChnlOffset = (ePhyChanBondState)pHTInfo->secondaryChannelOffset;
// Notify HAL
limLog( pMac, LOGW, FL( "Channel Information in HT IE change"
"d; sending notification to HAL." ) );
limLog( pMac, LOGW, FL( "Primary Channel: %d, Secondary Chan"
"nel Offset: %d, Channel Width: %d" ),
pHTInfo->primaryChannel, secondaryChnlOffset,
psessionEntry->htRecommendedTxWidthSet );
psessionEntry->channelChangeReasonCode=LIM_SWITCH_CHANNEL_OPERATION;
pMac->lim.gpchangeChannelCallback = NULL;
pMac->lim.gpchangeChannelData = NULL;
#if defined WLAN_FEATURE_VOWIFI
limSendSwitchChnlParams( pMac, ( tANI_U8 ) pHTInfo->primaryChannel,
secondaryChnlOffset, psessionEntry->maxTxPower,
psessionEntry->peSessionId, VOS_TRUE);
#else
limSendSwitchChnlParams( pMac, ( tANI_U8 ) pHTInfo->primaryChannel,
secondaryChnlOffset,
(tPowerdBm)localPwrConstraint,
psessionEntry->peSessionId, VOS_TRUE);
#endif
//In case of IBSS, if STA should update HT Info IE in its beacons.
if (LIM_IS_IBSS_ROLE(psessionEntry)) {
schSetFixedBeaconFields(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 limUpdateStaRunTimeHTCapability( tpAniSirGlobal pMac,
tDot11fIEHTCaps *pHTCaps )
{
if ( pMac->lim.gHTLsigTXOPProtection != ( tANI_U8 ) pHTCaps->lsigTXOPProtection )
{
pMac->lim.gHTLsigTXOPProtection = ( tANI_U8 ) pHTCaps->lsigTXOPProtection;
// Send change notification to HAL
}
if ( pMac->lim.gHTAMpduDensity != ( tANI_U8 ) pHTCaps->mpduDensity )
{
pMac->lim.gHTAMpduDensity = ( tANI_U8 ) pHTCaps->mpduDensity;
// Send change notification to HAL
}
if ( pMac->lim.gHTMaxRxAMpduFactor != ( tANI_U8 ) pHTCaps->maxRxAMPDUFactor )
{
pMac->lim.gHTMaxRxAMpduFactor = ( tANI_U8 ) pHTCaps->maxRxAMPDUFactor;
// Send change notification to HAL
}
} // End limUpdateStaRunTimeHTCapability.
/**
* \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 limUpdateStaRunTimeHTInfo( tpAniSirGlobal pMac,
tDot11fIEHTInfo *pHTInfo, tpPESession psessionEntry)
{
if ( psessionEntry->htRecommendedTxWidthSet != ( tANI_U8 )pHTInfo->recommendedTxWidthSet )
{
psessionEntry->htRecommendedTxWidthSet = ( tANI_U8 )pHTInfo->recommendedTxWidthSet;
// Send change notification to HAL
}
if ( psessionEntry->beaconParams.fRIFSMode != ( tANI_U8 )pHTInfo->rifsMode )
{
psessionEntry->beaconParams.fRIFSMode = ( tANI_U8 )pHTInfo->rifsMode;
// Send change notification to HAL
}
if ( pMac->lim.gHTServiceIntervalGranularity != ( tANI_U8 )pHTInfo->serviceIntervalGranularity )
{
pMac->lim.gHTServiceIntervalGranularity = ( tANI_U8 )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 = ( tANI_U8 )pHTInfo->nonGFDevicesPresent;
}
if ( pMac->lim.gHTSTBCBasicMCS != ( tANI_U8 )pHTInfo->basicSTBCMCS )
{
pMac->lim.gHTSTBCBasicMCS = ( tANI_U8 )pHTInfo->basicSTBCMCS;
// Send change notification to HAL
}
if ( pMac->lim.gHTDualCTSProtection != ( tANI_U8 )pHTInfo->dualCTSProtection )
{
pMac->lim.gHTDualCTSProtection = ( tANI_U8 )pHTInfo->dualCTSProtection;
// Send change notification to HAL
}
if ( pMac->lim.gHTSecondaryBeacon != ( tANI_U8 )pHTInfo->secondaryBeacon )
{
pMac->lim.gHTSecondaryBeacon = ( tANI_U8 )pHTInfo->secondaryBeacon;
// Send change notification to HAL
}
if ( psessionEntry->beaconParams.fLsigTXOPProtectionFullSupport != ( tANI_U8 )pHTInfo->lsigTXOPProtectionFullSupport )
{
psessionEntry->beaconParams.fLsigTXOPProtectionFullSupport = ( tANI_U8 )pHTInfo->lsigTXOPProtectionFullSupport;
// Send change notification to HAL
}
if ( pMac->lim.gHTPCOActive != ( tANI_U8 )pHTInfo->pcoActive )
{
pMac->lim.gHTPCOActive = ( tANI_U8 )pHTInfo->pcoActive;
// Send change notification to HAL
}
if ( pMac->lim.gHTPCOPhase != ( tANI_U8 )pHTInfo->pcoPhase )
{
pMac->lim.gHTPCOPhase = ( tANI_U8 )pHTInfo->pcoPhase;
// Send change notification to HAL
}
} // End limUpdateStaRunTimeHTInfo.
/** -------------------------------------------------------------
\fn limProcessHalIndMessages
\brief callback function for HAL indication
\param tpAniSirGlobal pMac
\param tANI_U32 mesgId
\param void *mesgParam
\return tSirRetStatu - status
-------------------------------------------------------------*/
tSirRetStatus limProcessHalIndMessages(tpAniSirGlobal pMac, tANI_U32 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 = (tANI_U16) msgId;
msg.bodyptr = msgParam;
msg.bodyval = 0;
break;
default:
vos_mem_free(msgParam);
limLog(pMac, LOGP, FL("invalid message id = %d received"), msgId);
return eSIR_FAILURE;
}
if (limPostMsgApi(pMac, &msg) != eSIR_SUCCESS)
{
vos_mem_free(msgParam);
limLog(pMac, LOGP, FL("limPostMsgApi failed for msgid = %d"), msg.type);
return eSIR_FAILURE;
}
return eSIR_SUCCESS;
}
/** -------------------------------------------------------------
\fn limValidateDeltsReq
\brief Validates DelTs req originated by SME or by HAL and also sends halMsg_DelTs to HAL
\param tpAniSirGlobal pMac
\param tpSirDeltsReq pDeltsReq
\param tSirMacAddr peerMacAddr
\return eSirRetStatus - status
-------------------------------------------------------------*/
tSirRetStatus
limValidateDeltsReq(tpAniSirGlobal pMac, tpSirDeltsReq pDeltsReq, tSirMacAddr peerMacAddr,tpPESession psessionEntry)
{
tpDphHashNode pSta;
tANI_U8 tsStatus;
tSirMacTSInfo *tsinfo;
tANI_U32 i;
tANI_U8 tspecIdx;
/* if sta
* - verify assoc state
* - del tspec locally
* if ap,
* - verify sta is in assoc state
* - del sta tspec locally
*/
if(pDeltsReq == NULL)
{
PELOGE(limLog(pMac, LOGE, FL("Delete TS request pointer is NULL"));)
return eSIR_FAILURE;
}
if (LIM_IS_STA_ROLE(psessionEntry) ||
LIM_IS_BT_AMP_STA_ROLE(psessionEntry)) {
tANI_U32 val;
// station always talks to the AP
pSta = dphGetHashEntry(pMac, DPH_STA_HASH_INDEX_PEER, &psessionEntry->dph.dphHashTable);
val = sizeof(tSirMacAddr);
sirCopyMacAddr(peerMacAddr,psessionEntry->bssId);
} else {
tANI_U16 assocId;
tANI_U8 *macaddr = (tANI_U8 *) peerMacAddr;
assocId = pDeltsReq->aid;
if (assocId != 0)
pSta = dphGetHashEntry(pMac, assocId, &psessionEntry->dph.dphHashTable);
else
pSta = dphLookupHashEntry(pMac, pDeltsReq->macAddr, &assocId, &psessionEntry->dph.dphHashTable);
if (pSta != NULL)
// TBD: check sta assoc state as well
for (i =0; i < sizeof(tSirMacAddr); i++)
macaddr[i] = pSta->staAddr[i];
}
if (pSta == NULL)
{
PELOGE(limLog(pMac, LOGE, "Cannot find station context for delts req");)
return eSIR_FAILURE;
}
if ((! pSta->valid) ||
(pSta->mlmStaContext.mlmState != eLIM_MLM_LINK_ESTABLISHED_STATE))
{
PELOGE(limLog(pMac, LOGE, "Invalid Sta (or state) for DelTsReq");)
return eSIR_FAILURE;
}
pDeltsReq->req.wsmTspecPresent = 0;
pDeltsReq->req.wmeTspecPresent = 0;
pDeltsReq->req.lleTspecPresent = 0;
if ((pSta->wsmEnabled) &&
(pDeltsReq->req.tspec.tsinfo.traffic.accessPolicy != SIR_MAC_ACCESSPOLICY_EDCA))
pDeltsReq->req.wsmTspecPresent = 1;
else if (pSta->wmeEnabled)
pDeltsReq->req.wmeTspecPresent = 1;
else if (pSta->lleEnabled)
pDeltsReq->req.lleTspecPresent = 1;
else
{
PELOGW(limLog(pMac, LOGW, FL("DELTS_REQ ignore - qos is disabled"));)
return eSIR_FAILURE;
}
tsinfo = pDeltsReq->req.wmeTspecPresent ? &pDeltsReq->req.tspec.tsinfo
: &pDeltsReq->req.tsinfo;
PELOG1(limLog(pMac, LOG1,
FL("received DELTS_REQ message (wmeTspecPresent = %d, lleTspecPresent = %d, wsmTspecPresent = %d, tsid %d, up %d, direction = %d)"),
pDeltsReq->req.wmeTspecPresent, pDeltsReq->req.lleTspecPresent, pDeltsReq->req.wsmTspecPresent,
tsinfo->traffic.tsid, tsinfo->traffic.userPrio, tsinfo->traffic.direction);)
// if no Access Control, ignore the request
if (limAdmitControlDeleteTS(pMac, pSta->assocId, tsinfo, &tsStatus, &tspecIdx)
!= eSIR_SUCCESS)
{
PELOGE(limLog(pMac, LOGE, "ERROR DELTS request for sta assocId %d (tsid %d, up %d)",
pSta->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 != limSendHalMsgDelTs(pMac,
pSta->staIndex,
tspecIdx,
pDeltsReq->req,
psessionEntry->peSessionId,
psessionEntry->bssId))
{
limLog(pMac, LOGW, FL("DelTs with UP %d failed in limSendHalMsgDelTs - ignoring request"),
tsinfo->traffic.userPrio);
return eSIR_FAILURE;
}
}
}
return eSIR_SUCCESS;
}
/** -------------------------------------------------------------
\fn limRegisterHalIndCallBack
\brief registers callback function to HAL for any indication.
\param tpAniSirGlobal pMac
\return none.
-------------------------------------------------------------*/
void
limRegisterHalIndCallBack(tpAniSirGlobal pMac)
{
tSirMsgQ msg;
tpHalIndCB pHalCB;
pHalCB = vos_mem_malloc(sizeof(tHalIndCB));
if ( NULL == pHalCB )
{
limLog(pMac, LOGP, FL("AllocateMemory() failed"));
return;
}
pHalCB->pHalIndCB = limProcessHalIndMessages;
msg.type = WDA_REGISTER_PE_CALLBACK;
msg.bodyptr = pHalCB;
msg.bodyval = 0;
MTRACE(macTraceMsgTx(pMac, NO_SESSION, msg.type));
if(eSIR_SUCCESS != wdaPostCtrlMsg(pMac, &msg))
{
vos_mem_free(pHalCB);
limLog(pMac, LOGP, FL("wdaPostCtrlMsg() failed"));
}
return;
}
/** -------------------------------------------------------------
\fn limProcessDelTsInd
\brief 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 indication to HDD.
\param tpAniSirGlobal pMac
\param tSirMsgQ limMsg
\return None
-------------------------------------------------------------*/
void
limProcessDelTsInd(tpAniSirGlobal pMac, tpSirMsgQ limMsg)
{
tpDphHashNode pSta;
tpDelTsParams pDelTsParam = (tpDelTsParams) (limMsg->bodyptr);
tpSirDeltsReq pDelTsReq = NULL;
tSirMacAddr peerMacAddr;
tpSirDeltsReqInfo pDelTsReqInfo;
tpLimTspecInfo pTspecInfo;
tpPESession psessionEntry;
tANI_U8 sessionId;
if((psessionEntry = peFindSessionByBssid(pMac,pDelTsParam->bssId,&sessionId))== NULL)
{
limLog(pMac, LOGE,FL("session does not exist for given BssId"));
vos_mem_free(limMsg->bodyptr);
limMsg->bodyptr = NULL;
return;
}
pTspecInfo = &(pMac->lim.tspecInfo[pDelTsParam->tspecIdx]);
if(pTspecInfo->inuse == false)
{
PELOGE(limLog(pMac, LOGE, FL("tspec entry with index %d is not in use"), pDelTsParam->tspecIdx);)
goto error1;
}
pSta = dphGetHashEntry(pMac, pTspecInfo->assocId, &psessionEntry->dph.dphHashTable);
if(pSta == NULL)
{
limLog(pMac, LOGE, FL("Could not find entry in DPH table for assocId = %d"),
pTspecInfo->assocId);
goto error1;
}
pDelTsReq = vos_mem_malloc(sizeof(tSirDeltsReq));
if ( NULL == pDelTsReq )
{
PELOGE(limLog(pMac, LOGE, FL("AllocateMemory() failed"));)
goto error1;
}
vos_mem_set( (tANI_U8 *)pDelTsReq, sizeof(tSirDeltsReq), 0);
if(pSta->wmeEnabled)
vos_mem_copy( &(pDelTsReq->req.tspec), &(pTspecInfo->tspec), sizeof(tSirMacTspecIE));
else
vos_mem_copy( &(pDelTsReq->req.tsinfo), &(pTspecInfo->tspec.tsinfo), sizeof(tSirMacTSInfo));
//validate the req
if (eSIR_SUCCESS != limValidateDeltsReq(pMac, pDelTsReq, peerMacAddr,psessionEntry))
{
PELOGE(limLog(pMac, LOGE, FL("limValidateDeltsReq failed"));)
goto error2;
}
PELOG1(limLog(pMac, LOG1, "Sent DELTS request to station with "
"assocId = %d MacAddr = "MAC_ADDRESS_STR,
pDelTsReq->aid, MAC_ADDR_ARRAY(peerMacAddr));)
limSendDeltsReqActionFrame(pMac, peerMacAddr, pDelTsReq->req.wmeTspecPresent, &pDelTsReq->req.tsinfo, &pDelTsReq->req.tspec,
psessionEntry);
// prepare and send an sme indication to HDD
pDelTsReqInfo = vos_mem_malloc(sizeof(tSirDeltsReqInfo));
if ( NULL == pDelTsReqInfo )
{
PELOGE(limLog(pMac, LOGE, FL("AllocateMemory() failed"));)
goto error3;
}
vos_mem_set( (tANI_U8 *)pDelTsReqInfo, sizeof(tSirDeltsReqInfo), 0);
if(pSta->wmeEnabled)
vos_mem_copy( &(pDelTsReqInfo->tspec), &(pTspecInfo->tspec), sizeof(tSirMacTspecIE));
else
vos_mem_copy( &(pDelTsReqInfo->tsinfo), &(pTspecInfo->tspec.tsinfo), sizeof(tSirMacTSInfo));
limSendSmeDeltsInd(pMac, pDelTsReqInfo, pDelTsReq->aid,psessionEntry);
error3:
vos_mem_free(pDelTsReqInfo);
error2:
vos_mem_free(pDelTsReq);
error1:
vos_mem_free(limMsg->bodyptr);
limMsg->bodyptr = NULL;
return;
}
/**
* @function : limPostSMStateUpdate()
*
* @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
limPostSMStateUpdate(tpAniSirGlobal pMac,
tANI_U16 staIdx, tSirMacHTMIMOPowerSaveState state,
tANI_U8 *pPeerStaMac, tANI_U8 sessionId)
{
tSirRetStatus retCode = eSIR_SUCCESS;
tSirMsgQ msgQ;
tpSetMIMOPS pMIMO_PSParams;
msgQ.reserved = 0;
msgQ.type = WDA_SET_MIMOPS_REQ;
// Allocate for WDA_SET_MIMOPS_REQ
pMIMO_PSParams = vos_mem_malloc(sizeof(tSetMIMOPS));
if ( NULL == pMIMO_PSParams )
{
limLog( 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;
vos_mem_copy(pMIMO_PSParams->peerMac, pPeerStaMac,
sizeof( tSirMacAddr ));
msgQ.bodyptr = pMIMO_PSParams;
msgQ.bodyval = 0;
limLog( pMac, LOG2, FL( "Sending WDA_SET_MIMOPS_REQ..." ));
MTRACE(macTraceMsgTx(pMac, NO_SESSION, msgQ.type));
retCode = wdaPostCtrlMsg( pMac, &msgQ );
if (eSIR_SUCCESS != retCode)
{
limLog( pMac, LOGP, FL("Posting WDA_SET_MIMOPS_REQ to HAL failed! Reason = %d"), retCode );
vos_mem_free(pMIMO_PSParams);
return retCode;
}
return retCode;
}
void limPktFree (
tpAniSirGlobal pMac,
eFrameType frmType,
tANI_U8 *pRxPacketInfo,
void *pBody)
{
(void) pMac; (void) frmType; (void) pRxPacketInfo; (void) pBody;
}
/**
* limGetBDfromRxPacket()
*
*FUNCTION:
* This function is called to get pointer to
* 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
limGetBDfromRxPacket(tpAniSirGlobal pMac, void *body, tANI_U32 **pRxPacketInfo)
{
*pRxPacketInfo = (tANI_U32 *) body;
} /*** end limGetBDfromRxPacket() ***/
void limRessetScanChannelInfo(tpAniSirGlobal pMac)
{
vos_mem_set(&pMac->lim.scanChnInfo, sizeof(tLimScanChnInfo), 0);
}
void limAddScanChannelInfo(tpAniSirGlobal pMac, tANI_U8 channelId)
{
tANI_U8 i;
tANI_BOOLEAN fFound = eANI_BOOLEAN_FALSE;
for(i = 0; i < pMac->lim.scanChnInfo.numChnInfo; i++)
{
if(pMac->lim.scanChnInfo.scanChn[i].channelId == channelId)
{
pMac->lim.scanChnInfo.scanChn[i].numTimeScan++;
fFound = eANI_BOOLEAN_TRUE;
break;
}
}
if(eANI_BOOLEAN_FALSE == fFound)
{
if(pMac->lim.scanChnInfo.numChnInfo < SIR_MAX_SUPPORTED_CHANNEL_LIST)
{
pMac->lim.scanChnInfo.scanChn[pMac->lim.scanChnInfo.numChnInfo].channelId = channelId;
pMac->lim.scanChnInfo.scanChn[pMac->lim.scanChnInfo.numChnInfo++].numTimeScan = 1;
}
else
{
PELOGW(limLog(pMac, LOGW, FL(" -- number of channels exceed mac"));)
}
}
}
/**
* lim_add_channel_status_info() - store
* chan status info into Global MAC structure
* @p_mac: Pointer to Global MAC structure
* @channel_stat: Pointer to chan status info reported by firmware
* @channel_id: current channel id
*
* Return: None
*/
void lim_add_channel_status_info(tpAniSirGlobal p_mac,
struct lim_channel_status *channel_stat, uint8_t channel_id)
{
uint8_t i;
boolean found = false;
struct lim_scan_channel_status *channel_info =
&p_mac->lim.scan_channel_status;
struct lim_channel_status *channel_status_list =
channel_info->channel_status_list;
uint8_t total_channel = channel_info->total_channel;
if (ACS_FW_REPORT_PARAM_CONFIGURED) {
for (i = 0; i < total_channel; i++) {
if (channel_status_list[i].channel_id == channel_id) {
if (channel_stat->cmd_flags ==
WMI_CHAN_INFO_END_RESP &&
channel_status_list[i].cmd_flags ==
WMI_CHAN_INFO_START_RESP) {
/* adjust to delta value for counts */
channel_stat->rx_clear_count -=
channel_status_list[i].rx_clear_count;
channel_stat->cycle_count -=
channel_status_list[i].cycle_count;
channel_stat->rx_frame_count -=
channel_status_list[i].rx_frame_count;
channel_stat->tx_frame_count -=
channel_status_list[i].tx_frame_count;
channel_stat->bss_rx_cycle_count -=
channel_status_list[i].bss_rx_cycle_count;
}
vos_mem_copy(
&channel_status_list[i],
channel_stat,
sizeof(*channel_status_list));
found = true;
break;
}
}
if (!found) {
if (total_channel <
SIR_MAX_SUPPORTED_ACS_CHANNEL_LIST) {
vos_mem_copy(
&channel_status_list[total_channel++],
channel_stat,
sizeof(*channel_status_list));
channel_info->total_channel = total_channel;
} else {
PELOGW(limLog(p_mac, LOGW,
FL("Chan cnt exceed, channel_id=%d"),
channel_id);)
}
}
}
return;
}
/**
* @function : limIsChannelValidForChannelSwitch()
*
* @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
limIsChannelValidForChannelSwitch(tpAniSirGlobal pMac, tANI_U8 channel)
{
tANI_U8 index;
tANI_U32 validChannelListLen = WNI_CFG_VALID_CHANNEL_LIST_LEN;
tSirMacChanNum validChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN];
if (wlan_cfgGetStr(pMac, WNI_CFG_VALID_CHANNEL_LIST,
(tANI_U8 *)validChannelList,
(tANI_U32 *)&validChannelListLen) != eSIR_SUCCESS)
{
PELOGE(limLog(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 __limFillTxControlParams
\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 eHalStatus
__limFillTxControlParams(tpAniSirGlobal pMac, tpTxControlParams pTxCtrlMsg,
tLimQuietTxMode type, tLimControlTx mode)
{
tpPESession psessionEntry = &pMac->lim.gpSession[0];
if (mode == eLIM_STOP_TX)
pTxCtrlMsg->stopTx = eANI_BOOLEAN_TRUE;
else
pTxCtrlMsg->stopTx = eANI_BOOLEAN_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(limLog(pMac, LOGW, FL("Invalid case: Not Handled"));)
return eHAL_STATUS_FAILURE;
}
return eHAL_STATUS_SUCCESS;
}
/**
* @function : limFrameTransmissionControl()
*
* @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 limFrameTransmissionControl(tpAniSirGlobal pMac, tLimQuietTxMode type, tLimControlTx mode)
{
eHalStatus status = eHAL_STATUS_FAILURE;
tpTxControlParams pTxCtrlMsg;
tSirMsgQ msgQ;
tANI_U8 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 = (tANI_U8)HALMSG_NUMBYTES_STATION_BITMAP(pMac->lim.maxStation);
pTxCtrlMsg = vos_mem_malloc(sizeof(*pTxCtrlMsg) + nBytes);
if ( NULL == pTxCtrlMsg )
{
limLog(pMac, LOGP, FL("AllocateMemory() failed"));
return;
}
vos_mem_set((void *) pTxCtrlMsg,
(sizeof(*pTxCtrlMsg) + nBytes), 0);
status = __limFillTxControlParams(pMac, pTxCtrlMsg, type, mode);
if (status != eHAL_STATUS_SUCCESS)
{
vos_mem_free(pTxCtrlMsg);
limLog(pMac, LOGP, FL("__limFillTxControlParams failed, status = %d"), status);
return;
}
msgQ.bodyptr = (void *) pTxCtrlMsg;
msgQ.bodyval = 0;
msgQ.reserved = 0;
msgQ.type = WDA_TRANSMISSION_CONTROL_IND;
MTRACE(macTraceMsgTx(pMac, NO_SESSION, msgQ.type));
if(wdaPostCtrlMsg( pMac, &msgQ) != eSIR_SUCCESS)
{
vos_mem_free(pTxCtrlMsg);
limLog( pMac, LOGP, FL("Posting Message to HAL failed"));
return;
}
if (mode == eLIM_STOP_TX)
{
PELOG1(limLog(pMac, LOG1, FL("Stopping the transmission of all packets, indicated softmac"));)
}
else
{
PELOG1(limLog(pMac, LOG1, FL("Resuming the transmission of all packets, indicated softmac"));)
}
return;
}
/**
* @function : limRestorePreChannelSwitchState()
*
* @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
limRestorePreChannelSwitchState(tpAniSirGlobal pMac, tpPESession psessionEntry)
{
tSirRetStatus retCode = eSIR_SUCCESS;
tANI_U32 val = 0;
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. */
limFrameTransmissionControl(pMac, eLIM_TX_ALL, eLIM_RESUME_TX);
/* Free to enter BMPS */
limSendSmePostChannelSwitchInd(pMac);
//Background scan is now enabled by SME
if(pMac->lim.gLimBackgroundScanTerminate == FALSE)
{
/* Enable background scan if already enabled, else don't bother */
if ((retCode = wlan_cfgGetInt(pMac, WNI_CFG_BACKGROUND_SCAN_PERIOD,
&val)) != eSIR_SUCCESS)
{
limLog(pMac, LOGP, FL("could not retrieve Background scan period value"));
return (retCode);
}
if (val > 0 && TX_TIMER_VALID(pMac->lim.limTimers.gLimBackgroundScanTimer))
{
MTRACE(macTrace(pMac, TRACE_CODE_TIMER_ACTIVATE,
psessionEntry->peSessionId, eLIM_BACKGROUND_SCAN_TIMER));
if(tx_timer_activate(&pMac->lim.limTimers.gLimBackgroundScanTimer) != TX_SUCCESS)
{
limLog(pMac, LOGP, FL("Could not restart background scan timer, doing LOGP"));
return (eSIR_FAILURE);
}
}
}
/* Enable heartbeat timer */
if (TX_TIMER_VALID(pMac->lim.limTimers.gLimHeartBeatTimer))
{
MTRACE(macTrace(pMac, TRACE_CODE_TIMER_ACTIVATE,
psessionEntry->peSessionId, eLIM_HEART_BEAT_TIMER));
if((limActivateHearBeatTimer(pMac, psessionEntry) != TX_SUCCESS) &&
(!IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
{
limLog(pMac, LOGP, FL("Could not restart heartbeat timer, doing LOGP"));
return (eSIR_FAILURE);
}
}
return (retCode);
}
/**--------------------------------------------
\fn limRestorePreQuietState
\brief Restore the pre quiet state
\param pMac
\return NONE
---------------------------------------------*/
tSirRetStatus limRestorePreQuietState(tpAniSirGlobal pMac, tpPESession psessionEntry)
{
tSirRetStatus retCode = eSIR_SUCCESS;
tANI_U32 val = 0;
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)
limFrameTransmissionControl(pMac, eLIM_TX_ALL, eLIM_RESUME_TX);
//Background scan is now enabled by SME
if(pMac->lim.gLimBackgroundScanTerminate == FALSE)
{
/* Enable background scan if already enabled, else don't bother */
if ((retCode = wlan_cfgGetInt(pMac, WNI_CFG_BACKGROUND_SCAN_PERIOD,
&val)) != eSIR_SUCCESS)
{
limLog(pMac, LOGP, FL("could not retrieve Background scan period value"));
return (retCode);
}
if (val > 0 && TX_TIMER_VALID(pMac->lim.limTimers.gLimBackgroundScanTimer))
{
MTRACE(macTrace(pMac, TRACE_CODE_TIMER_ACTIVATE, psessionEntry->peSessionId, eLIM_BACKGROUND_SCAN_TIMER));
if(tx_timer_activate(&pMac->lim.limTimers.gLimBackgroundScanTimer) != TX_SUCCESS)
{
limLog(pMac, LOGP, FL("Could not restart background scan timer, doing LOGP"));
return (eSIR_FAILURE);
}
}
}
/* Enable heartbeat timer */
if (TX_TIMER_VALID(pMac->lim.limTimers.gLimHeartBeatTimer))
{
MTRACE(macTrace(pMac, TRACE_CODE_TIMER_ACTIVATE, psessionEntry->peSessionId, eLIM_HEART_BEAT_TIMER));
if(limActivateHearBeatTimer(pMac, psessionEntry) != TX_SUCCESS)
{
limLog(pMac, LOGP, FL("Could not restart heartbeat timer, doing LOGP"));
return (eSIR_FAILURE);
}
}
return (retCode);
}
/**
* @function: limPrepareFor11hChannelSwitch()
*
* @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
limPrepareFor11hChannelSwitch(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;
/* Disable, Stop background scan if enabled and running */
limDeactivateAndChangeTimer(pMac, eLIM_BACKGROUND_SCAN_TIMER);
/* Stop heart-beat timer to stop heartbeat disassociation */
limHeartBeatDeactivateAndChangeTimer(pMac, psessionEntry);
if(pMac->lim.gLimSmeState == eLIM_SME_LINK_EST_WT_SCAN_STATE ||
pMac->lim.gLimSmeState == eLIM_SME_CHANNEL_SCAN_STATE)
{
PELOGE(limLog(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.
peSetResumeChannel(pMac, 0, 0);
limSendHalFinishScanReq(pMac, eLIM_HAL_FINISH_SCAN_WAIT_STATE);
}
else
{
limRestorePreChannelSwitchState(pMac, psessionEntry);
}
return;
}
else
{
PELOGE(limLog(pMac, LOG1, FL("Not in scan state, start channel switch timer"));)
/** We are safe to switch channel at this point */
limStopTxAndSwitchChannel(pMac, psessionEntry->peSessionId);
}
}
/**----------------------------------------------------
\fn limGetNwType
\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 limGetNwType(tpAniSirGlobal pMac, tANI_U8 channelNum, tANI_U32 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 if 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(limLog(pMac, LOG3, FL("Beacon, nwtype=G"));)
nwType = eSIR_11G_NW_TYPE;
}
}
else
{
// 11a packet
PELOG3(limLog(pMac, LOG3,FL("Beacon, nwtype=A"));)
nwType = eSIR_11A_NW_TYPE;
}
}
return nwType;
}
/**---------------------------------------------------------
\fn limGetChannelFromBeacon
\brief To extract channel number from beacon
\param pMac
\param pBeacon - Pointer to beacon or probe rsp
\return channel number
-----------------------------------------------------------*/
tANI_U8 limGetChannelFromBeacon(tpAniSirGlobal pMac, tpSchBeaconStruct pBeacon)
{
tANI_U8 channelNum = 0;
if (pBeacon->dsParamsPresent)
channelNum = pBeacon->channelNumber;
else if(pBeacon->HTInfo.present)
channelNum = pBeacon->HTInfo.primaryChannel;
else
channelNum = pBeacon->channelNumber;
return channelNum;
}
/** ---------------------------------------------------------
\fn limSetTspecUapsdMask
\brief This function sets the PE global variable:
\ 1) gUapsdPerAcTriggerEnableMask and
\ 2) gUapsdPerAcDeliveryEnableMask
\ based on the user priority field and direction field
\ in the TS Info Fields.
\
\ An AC is a trigger-enabled AC if the PSB subfield
\ is set to 1 in the up link direction.
\ An AC is a delivery-enabled AC if the PSB subfield
\ is set to 1 in the down-link direction.
\
\param tpAniSirGlobal pMac
\param tSirMacTSInfo pTsInfo
\param tANI_U32 action
\return None
------------------------------------------------------------*/
void limSetTspecUapsdMask(tpAniSirGlobal pMac, tSirMacTSInfo *pTsInfo, tANI_U32 action)
{
tANI_U8 userPrio = (tANI_U8)pTsInfo->traffic.userPrio;
tANI_U16 direction = pTsInfo->traffic.direction;
tANI_U8 ac = upToAc(userPrio);
PELOG1(limLog(pMac, LOG1, FL(" Set UAPSD mask for AC %d, direction %d, action=%d (1=set,0=clear) "),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)
pMac->lim.gUapsdPerAcTriggerEnableMask &= ~(1 << ac);
else if (direction == SIR_MAC_DIRECTION_DNLINK)
pMac->lim.gUapsdPerAcDeliveryEnableMask &= ~(1 << ac);
else if (direction == SIR_MAC_DIRECTION_BIDIR)
{
pMac->lim.gUapsdPerAcTriggerEnableMask &= ~(1 << ac);
pMac->lim.gUapsdPerAcDeliveryEnableMask &= ~(1 << ac);
}
}
else if (action == SET_UAPSD_MASK)
{
if (direction == SIR_MAC_DIRECTION_UPLINK)
pMac->lim.gUapsdPerAcTriggerEnableMask |= (1 << ac);
else if (direction == SIR_MAC_DIRECTION_DNLINK)
pMac->lim.gUapsdPerAcDeliveryEnableMask |= (1 << ac);
else if (direction == SIR_MAC_DIRECTION_BIDIR)
{
pMac->lim.gUapsdPerAcTriggerEnableMask |= (1 << ac);
pMac->lim.gUapsdPerAcDeliveryEnableMask |= (1 << ac);
}
}
limLog(pMac, LOG1, FL("New pMac->lim.gUapsdPerAcTriggerEnableMask = 0x%x "), pMac->lim.gUapsdPerAcTriggerEnableMask );
limLog(pMac, LOG1, FL("New pMac->lim.gUapsdPerAcDeliveryEnableMask = 0x%x "), pMac->lim.gUapsdPerAcDeliveryEnableMask );
return;
}
void limSetTspecUapsdMaskPerSession(tpAniSirGlobal pMac,
tpPESession psessionEntry, tSirMacTSInfo *pTsInfo, tANI_U32 action)
{
tANI_U8 userPrio = (tANI_U8)pTsInfo->traffic.userPrio;
tANI_U16 direction = pTsInfo->traffic.direction;
tANI_U8 ac = upToAc(userPrio);
PELOG1(limLog(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);
}
}
limLog(pMac, LOG1,
FL("New psessionEntry->gUapsdPerAcTriggerEnableMask = 0x%x "),
psessionEntry->gUapsdPerAcTriggerEnableMask );
limLog(pMac, LOG1,
FL("New psessionEntry->gUapsdPerAcDeliveryEnableMask = 0x%x "),
psessionEntry->gUapsdPerAcDeliveryEnableMask );
return;
}
void limHandleHeartBeatTimeout(tpAniSirGlobal pMac )
{
tANI_U8 i;
for(i =0;i < pMac->lim.maxBssId;i++)
{
if(pMac->lim.gpSession[i].valid == TRUE )
{
if(pMac->lim.gpSession[i].bssType == eSIR_IBSS_MODE)
{
limIbssHeartBeatHandle(pMac,&pMac->lim.gpSession[i]);
break;
}
if((pMac->lim.gpSession[i].bssType == eSIR_INFRASTRUCTURE_MODE) &&
(pMac->lim.gpSession[i].limSystemRole == eLIM_STA_ROLE))
{
limHandleHeartBeatFailure(pMac,&pMac->lim.gpSession[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))
{
if(pMac->lim.gpSession[i].LimHBFailureStatus == eANI_BOOLEAN_TRUE)
{
/* Activate Probe After HeartBeat Timer in-case
HB Failure detected */
PELOGW(limLog(pMac, LOGW,FL("Sending Probe for Session: %d"),
i);)
limDeactivateAndChangeTimer(pMac, eLIM_PROBE_AFTER_HB_TIMER);
MTRACE(macTrace(pMac, TRACE_CODE_TIMER_ACTIVATE, 0, eLIM_PROBE_AFTER_HB_TIMER));
if (tx_timer_activate(&pMac->lim.limTimers.gLimProbeAfterHBTimer) != TX_SUCCESS)
{
limLog(pMac, LOGP, FL("Fail to re-activate Probe-after-heartbeat timer"));
limReactivateHeartBeatTimer(pMac, &pMac->lim.gpSession[i]);
}
break;
}
}
}
}
}
void limHandleHeartBeatTimeoutForSession(tpAniSirGlobal pMac, tpPESession psessionEntry)
{
if(psessionEntry->valid == TRUE )
{
if(psessionEntry->bssType == eSIR_IBSS_MODE)
{
limIbssHeartBeatHandle(pMac,psessionEntry);
}
if((psessionEntry->bssType == eSIR_INFRASTRUCTURE_MODE) &&
LIM_IS_STA_ROLE(psessionEntry)) {
limHandleHeartBeatFailure(pMac,psessionEntry);
}
}
/* In the function limHandleHeartBeatFailure things can change so check for the session entry valid
and the other things again */
if(psessionEntry->valid == TRUE )
{
if((psessionEntry->bssType == eSIR_INFRASTRUCTURE_MODE) &&
LIM_IS_STA_ROLE(psessionEntry)) {
if(psessionEntry->LimHBFailureStatus == eANI_BOOLEAN_TRUE)
{
/* Activate Probe After HeartBeat Timer in-case
HB Failure detected */
PELOGW(limLog(pMac, LOGW,FL("Sending Probe for Session: %d"),
psessionEntry->bssIdx);)
limDeactivateAndChangeTimer(pMac, eLIM_PROBE_AFTER_HB_TIMER);
MTRACE(macTrace(pMac, TRACE_CODE_TIMER_ACTIVATE, 0, eLIM_PROBE_AFTER_HB_TIMER));
if (tx_timer_activate(&pMac->lim.limTimers.gLimProbeAfterHBTimer) != TX_SUCCESS)
{
limLog(pMac, LOGP, FL("Fail to re-activate Probe-after-heartbeat timer"));
limReactivateHeartBeatTimer(pMac, psessionEntry);
}
}
}
}
}
tANI_U8 limGetCurrentOperatingChannel(tpAniSirGlobal pMac)
{
tANI_U8 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;
}
/**
* limProcessAddStaRsp() - process WDA_ADD_STA_RSP from WMA
* @mac_ctx: Pointer to Global MAC structure
* @msg: msg from WMA
*
* @Return: None
*/
void limProcessAddStaRsp(tpAniSirGlobal mac_ctx, tpSirMsgQ msg)
{
tpPESession session;
tpAddStaParams add_sta_params;
if (NULL == msg) {
limLog(mac_ctx, LOGE, FL("NULL add_sta_rsp"));
return;
}
add_sta_params = (tpAddStaParams)msg->bodyptr;
session = peFindSessionBySessionId(mac_ctx, add_sta_params->sessionId);
if (NULL == session) {
limLog(mac_ctx, LOGP,
FL("Session does not exist for given sessionID"));
vos_mem_free(add_sta_params);
return;
}
session->csaOffloadEnable = add_sta_params->csaOffloadEnable;
if (LIM_IS_IBSS_ROLE(session)) {
limIbssAddStaRsp(mac_ctx, msg->bodyptr, session);
return;
}
if (LIM_IS_NDI_ROLE(session)) {
lim_ndp_add_sta_rsp(mac_ctx, session, msg->bodyptr);
return;
}
#ifdef FEATURE_WLAN_TDLS
if (mac_ctx->lim.gLimAddStaTdls) {
limProcessTdlsAddStaRsp(mac_ctx, msg->bodyptr, session);
mac_ctx->lim.gLimAddStaTdls = FALSE;
return;
}
#endif
limProcessMlmAddStaRsp(mac_ctx, msg, session);
}
void limUpdateBeacon(tpAniSirGlobal pMac)
{
tANI_U8 i;
for(i =0;i < pMac->lim.maxBssId;i++)
{
if(pMac->lim.gpSession[i].valid == TRUE )
{
if( ( (pMac->lim.gpSession[i].limSystemRole == eLIM_AP_ROLE) ||
(pMac->lim.gpSession[i].limSystemRole == eLIM_STA_IN_IBSS_ROLE) )
&& (eLIM_SME_NORMAL_STATE == pMac->lim.gpSession[i].limSmeState)
)
{
schSetFixedBeaconFields(pMac,&pMac->lim.gpSession[i]);
if (VOS_FALSE == pMac->sap.SapDfsInfo.is_dfs_cac_timer_running)
{
limSendBeaconInd(pMac, &pMac->lim.gpSession[i]);
}
}
else
{
if( (pMac->lim.gpSession[i].limSystemRole == eLIM_BT_AMP_AP_ROLE)||
(pMac->lim.gpSession[i].limSystemRole == eLIM_BT_AMP_STA_ROLE))
{
if(pMac->lim.gpSession[i].statypeForBss == STA_ENTRY_SELF)
{
schSetFixedBeaconFields(pMac,&pMac->lim.gpSession[i]);
}
}
}
}
}
}
void limHandleHeartBeatFailureTimeout(tpAniSirGlobal pMac)
{
tANI_U8 i;
tpPESession psessionEntry;
/* Probe response is not received after HB failure. This is handled by LMM sub module. */
for(i =0; i < pMac->lim.maxBssId; i++)
{
if(pMac->lim.gpSession[i].valid == TRUE)
{
psessionEntry = &pMac->lim.gpSession[i];
if(psessionEntry->LimHBFailureStatus == eANI_BOOLEAN_TRUE)
{
limLog(pMac, LOGE, FL(
"Probe_hb_failure: SME %d, MLME %d, HB Cnt %d, BCN cnt %d"),
psessionEntry->limSmeState,
psessionEntry->limMlmState,
psessionEntry->LimRxedBeaconCntDuringHB,
psessionEntry->currentBssBeaconCnt);
#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM //FEATURE_WLAN_DIAG_SUPPORT
limDiagEventReport(pMac, WLAN_PE_DIAG_HB_FAILURE_TIMEOUT, psessionEntry, 0, 0);
#endif
if (psessionEntry->limMlmState == eLIM_MLM_LINK_ESTABLISHED_STATE)
{
/*
* Disconnect even if we have not received a single beacon
* after connection.
*/
if (((!LIM_IS_CONNECTION_ACTIVE(psessionEntry)) ||
(0 == psessionEntry->currentBssBeaconCnt)) &&
(psessionEntry->limSmeState != eLIM_SME_WT_DISASSOC_STATE) &&
(psessionEntry->limSmeState != eLIM_SME_WT_DEAUTH_STATE))
{
limLog(pMac, LOGE, FL("Probe_hb_failure: for session:%d " ),psessionEntry->peSessionId);
/* AP did not respond to Probe Request. Tear down link with it.*/
limTearDownLinkWithAp(pMac,
psessionEntry->peSessionId,
eSIR_BEACON_MISSED);
pMac->lim.gLimProbeFailureAfterHBfailedCnt++ ;
}
else // restart heartbeat timer
{
limReactivateHeartBeatTimer(pMac, psessionEntry);
}
}
else
{
limLog(pMac, LOGE, FL("Unexpected wt-probe-timeout in state "));
limPrintMlmState(pMac, LOGE, psessionEntry->limMlmState);
limReactivateHeartBeatTimer(pMac, psessionEntry);
}
}
}
}
}
/*
* This function assumes there will not be more than one IBSS session active at any time.
*/
tpPESession limIsIBSSSessionActive(tpAniSirGlobal pMac)
{
tANI_U8 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 limIsApSessionActive(tpAniSirGlobal pMac)
{
tANI_U8 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 limHandleDeferMsgError
\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 limHandleDeferMsgError(tpAniSirGlobal pMac, tpSirMsgQ pLimMsg)
{
if(SIR_BB_XPORT_MGMT_MSG == pLimMsg->type)
{
vos_pkt_return_packet((vos_pkt_t*)pLimMsg->bodyptr);
pLimMsg->bodyptr = NULL;
}
else if(pLimMsg->bodyptr != NULL)
{
vos_mem_free(pLimMsg->bodyptr);
pLimMsg->bodyptr = NULL;
}
}
#ifdef FEATURE_WLAN_DIAG_SUPPORT
/**---------------------------------------------------------
\fn limDiagEventReport
\brief This function reports Diag event
\param pMac
\param eventType
\param bssid
\param status
\param reasonCode
\return void
-----------------------------------------------------------*/
void limDiagEventReport(tpAniSirGlobal pMac, tANI_U16 eventType, tpPESession pSessionEntry, tANI_U16 status, tANI_U16 reasonCode)
{
tSirMacAddr nullBssid = { 0, 0, 0, 0, 0, 0 };
WLAN_VOS_DIAG_EVENT_DEF(peEvent, vos_event_wlan_pe_payload_type);
vos_mem_set(&peEvent, sizeof(vos_event_wlan_pe_payload_type), 0);
if (NULL == pSessionEntry)
{
vos_mem_copy( peEvent.bssid, nullBssid, sizeof(tSirMacAddr));
peEvent.sme_state = (tANI_U16)pMac->lim.gLimSmeState;
peEvent.mlm_state = (tANI_U16)pMac->lim.gLimMlmState;
}
else
{
vos_mem_copy(peEvent.bssid, pSessionEntry->bssId, sizeof(tSirMacAddr));
peEvent.sme_state = (tANI_U16)pSessionEntry->limSmeState;
peEvent.mlm_state = (tANI_U16)pSessionEntry->limMlmState;
}
peEvent.event_type = eventType;
peEvent.status = status;
peEvent.reason_code = reasonCode;
WLAN_VOS_DIAG_EVENT_REPORT(&peEvent, EVENT_WLAN_PE);
return;
}
#endif /* FEATURE_WLAN_DIAG_SUPPORT */
void limProcessAddStaSelfRsp(tpAniSirGlobal pMac,tpSirMsgQ limMsgQ)
{
tpAddStaSelfParams pAddStaSelfParams;
tSirMsgQ mmhMsg;
tpSirSmeAddStaSelfRsp pRsp;
eHalStatus status;
pAddStaSelfParams = (tpAddStaSelfParams)limMsgQ->bodyptr;
pRsp = vos_mem_malloc(sizeof(tSirSmeAddStaSelfRsp));
if ( NULL == pRsp )
{
/// Buffer not available. Log error
limLog(pMac, LOGP, FL("call to AllocateMemory failed for Add Sta self RSP"));
vos_mem_free(pAddStaSelfParams);
limMsgQ->bodyptr = NULL;
return;
}
vos_mem_set((tANI_U8*)pRsp, sizeof(tSirSmeAddStaSelfRsp), 0);
pRsp->mesgType = eWNI_SME_ADD_STA_SELF_RSP;
pRsp->mesgLen = (tANI_U16) sizeof(tSirSmeAddStaSelfRsp);
pRsp->status = pAddStaSelfParams->status;
vos_mem_copy( pRsp->selfMacAddr, pAddStaSelfParams->selfMacAddr, sizeof(tSirMacAddr) );
/*
* For FW generated probe requests, Host needs to send Extended Capbilities
* IE information. With this fix, Host will send the extended capabilites
* on getting eWNI_SME_ADD_STA_SELF_RSP message(after vdev create).
*
* This information is required for only STA/P2P as they are the one which
* sends probe request.
*/
if (VOS_STATUS_SUCCESS == pRsp->status &&
(WMI_VDEV_TYPE_STA == pAddStaSelfParams->type ||
(WMI_VDEV_TYPE_AP == pAddStaSelfParams->type &&
WMI_UNIFIED_VDEV_SUBTYPE_P2P_DEVICE == pAddStaSelfParams->subType))) {
limLog(pMac, LOG1, FL("Add sta success - send ext cap IE"));
status = lim_send_ext_cap_ie(pMac, pAddStaSelfParams->sessionId, NULL,
false);
if (eHAL_STATUS_SUCCESS != status)
limLog(pMac, LOGE, FL("Unable to send ExtCap to FW"));
}
vos_mem_free(pAddStaSelfParams);
limMsgQ->bodyptr = NULL;
mmhMsg.type = eWNI_SME_ADD_STA_SELF_RSP;
mmhMsg.bodyptr = pRsp;
mmhMsg.bodyval = 0;
MTRACE(macTrace(pMac, TRACE_CODE_TX_SME_MSG, NO_SESSION, mmhMsg.type));
limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT);
}
/**
* lim_ScanTypetoString(): converts scan type enum to string.
* @scanType: enum value of scanType.
*/
const char * lim_ScanTypetoString(const v_U8_t scanType)
{
switch (scanType)
{
CASE_RETURN_STRING( eSIR_PASSIVE_SCAN );
CASE_RETURN_STRING( eSIR_ACTIVE_SCAN );
CASE_RETURN_STRING( eSIR_BEACON_TABLE );
default:
return "Unknown ScanType";
}
}
/**
* lim_BssTypetoString(): converts bss type enum to string.
* @bssType: enum value of bssType.
*/
const char * lim_BssTypetoString(const v_U8_t bssType)
{
switch (bssType)
{
CASE_RETURN_STRING( eSIR_INFRASTRUCTURE_MODE );
CASE_RETURN_STRING( eSIR_INFRA_AP_MODE );
CASE_RETURN_STRING( eSIR_IBSS_MODE );
CASE_RETURN_STRING( eSIR_BTAMP_STA_MODE );
CASE_RETURN_STRING( eSIR_BTAMP_AP_MODE );
CASE_RETURN_STRING( eSIR_AUTO_MODE );
CASE_RETURN_STRING(eSIR_NDI_MODE);
default:
return "Unknown BssType";
}
}
/**
* lim_BackgroundScanModetoString():converts BG scan type to string.
* @mode: enum value of BG scan type.
*/
const char *lim_BackgroundScanModetoString(const v_U8_t mode)
{
switch (mode)
{
CASE_RETURN_STRING( eSIR_AGGRESSIVE_BACKGROUND_SCAN );
CASE_RETURN_STRING( eSIR_NORMAL_BACKGROUND_SCAN );
CASE_RETURN_STRING( eSIR_ROAMING_SCAN );
default:
return "Unknown BgScanMode";
}
}
void limProcessDelStaSelfRsp(tpAniSirGlobal pMac,tpSirMsgQ limMsgQ)
{
tpDelStaSelfParams pDelStaSelfParams;
tSirMsgQ mmhMsg;
tpSirSmeDelStaSelfRsp pRsp;
pDelStaSelfParams = (tpDelStaSelfParams)limMsgQ->bodyptr;
pRsp = vos_mem_malloc(sizeof(tSirSmeDelStaSelfRsp));
if ( NULL == pRsp )
{
/// Buffer not available. Log error
limLog(pMac, LOGP, FL("call to AllocateMemory failed for Add Sta self RSP"));
vos_mem_free(pDelStaSelfParams);
limMsgQ->bodyptr = NULL;
return;
}
vos_mem_set((tANI_U8*)pRsp, sizeof(tSirSmeDelStaSelfRsp), 0);
pRsp->mesgType = eWNI_SME_DEL_STA_SELF_RSP;
pRsp->mesgLen = (tANI_U16) sizeof(tSirSmeDelStaSelfRsp);
pRsp->status = pDelStaSelfParams->status;
vos_mem_copy( pRsp->selfMacAddr, pDelStaSelfParams->selfMacAddr, sizeof(tSirMacAddr) );
vos_mem_free(pDelStaSelfParams);
limMsgQ->bodyptr = NULL;
mmhMsg.type = eWNI_SME_DEL_STA_SELF_RSP;
mmhMsg.bodyptr = pRsp;
mmhMsg.bodyval = 0;
MTRACE(macTrace(pMac, TRACE_CODE_TX_SME_MSG, NO_SESSION, mmhMsg.type));
limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT);
}
/***************************************************************
* tANI_U8 limUnmapChannel(tANI_U8 mapChannel)
* To unmap the channel to reverse the effect of mapping
* a band channel in hal .Mapping was done hal to overcome the
* limitation of the rxbd which use only 4 bit for channel number.
*****************************************************************/
tANI_U8 limUnmapChannel(tANI_U8 mapChannel)
{
return WDA_MapChannel(mapChannel);
}
v_U8_t* limGetIEPtr(tpAniSirGlobal pMac, v_U8_t *pIes, int length, v_U8_t eid,eSizeOfLenField size_of_len_field)
{
int left = length;
v_U8_t *ptr = pIes;
v_U8_t elem_id;
v_U16_t elem_len;
while(left >= (size_of_len_field+1))
{
elem_id = ptr[0];
if (size_of_len_field == TWO_BYTE)
{
elem_len = ((v_U16_t) ptr[1]) | (ptr[2]<<8);
}
else
{
elem_len = ptr[1];
}
left -= (size_of_len_field+1);
if(elem_len > left)
{
limLog(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
v_U8_t limBuildP2pIe(tpAniSirGlobal pMac, tANI_U8 *ie, tANI_U8 *data, tANI_U8 ie_len)
{
int length = 0;
tANI_U8 *ptr = ie;
ptr[length++] = SIR_MAC_EID_VENDOR;
ptr[length++] = ie_len + SIR_MAC_P2P_OUI_SIZE;
vos_mem_copy(&ptr[length], SIR_MAC_P2P_OUI, SIR_MAC_P2P_OUI_SIZE);
vos_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
v_U8_t limGetNoaAttrStreamInMultP2pIes(tpAniSirGlobal pMac,v_U8_t* noaStream,v_U8_t noaLen,v_U8_t overFlowLen)
{
v_U8_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))
{
vos_mem_copy(overFlowP2pStream,
noaStream + noaLen - overFlowLen, overFlowLen);
noaStream[noaLen - overFlowLen] = SIR_MAC_EID_VENDOR;
noaStream[noaLen - overFlowLen + 1] = overFlowLen + SIR_MAC_P2P_OUI_SIZE;
vos_mem_copy(noaStream+noaLen-overFlowLen + 2,
SIR_MAC_P2P_OUI, SIR_MAC_P2P_OUI_SIZE);
vos_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
v_U8_t limGetNoaAttrStream(tpAniSirGlobal pMac, v_U8_t*pNoaStream,tpPESession psessionEntry)
{
v_U8_t len=0;
v_U8_t *pBody = pNoaStream;
if ( (psessionEntry != NULL) && (psessionEntry->valid) &&
(psessionEntry->pePersona == VOS_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;
*((tANI_U32 *)(pBody)) = sirSwapU32ifNeeded(psessionEntry->p2pGoPsUpdate.uNoa1Duration);
pBody += sizeof(tANI_U32);
len +=4;
*((tANI_U32 *)(pBody)) = sirSwapU32ifNeeded(psessionEntry->p2pGoPsUpdate.uNoa1Interval);
pBody += sizeof(tANI_U32);
len +=4;
*((tANI_U32 *)(pBody)) = sirSwapU32ifNeeded(psessionEntry->p2pGoPsUpdate.uNoa1StartTime);
pBody += sizeof(tANI_U32);
len +=4;
}
if (psessionEntry->p2pGoPsUpdate.uNoa2Duration)
{
*pBody = psessionEntry->p2pGoPsUpdate.uNoa2IntervalCnt;
pBody += 1;
len +=1;
*((tANI_U32 *)(pBody)) = sirSwapU32ifNeeded(psessionEntry->p2pGoPsUpdate.uNoa2Duration);
pBody += sizeof(tANI_U32);
len +=4;
*((tANI_U32 *)(pBody)) = sirSwapU32ifNeeded(psessionEntry->p2pGoPsUpdate.uNoa2Interval);
pBody += sizeof(tANI_U32);
len +=4;
*((tANI_U32 *)(pBody)) = sirSwapU32ifNeeded(psessionEntry->p2pGoPsUpdate.uNoa2StartTime);
pBody += sizeof(tANI_U32);
len +=4;
}
pBody = pNoaStream + 1;
*((tANI_U16 *)(pBody)) = sirSwapU16ifNeeded(len-3);/*one byte for Attr and 2 bytes for length*/
return (len);
}
return 0;
}
void peSetResumeChannel(tpAniSirGlobal pMac, tANI_U16 channel, ePhyChanBondState phyCbState)
{
pMac->lim.gResumeChannel = channel;
pMac->lim.gResumePhyCbState = phyCbState;
}
/*--------------------------------------------------------------------------
\brief peGetResumeChannel() - Returns the channel number for scanning, from a valid session.
This function returns the channel to resume to during link resume. channel id of 0 means HAL will
resume to previous channel before link suspend
\param pMac - pointer to global adapter context
\return - channel to scan from valid session else zero.
\sa
--------------------------------------------------------------------------*/
void peGetResumeChannel(tpAniSirGlobal pMac, tANI_U8* resumeChannel, ePhyChanBondState* resumePhyCbState)
{
//Rationale - this could be the suspend/resume for assoc and it is essential that
//the new BSS is active for some time. Other BSS was anyway suspended.
//TODO: Comeup with a better alternative. Sending NULL with PM=0 on other BSS means
//there will be trouble. But since it is sent on current channel, it will be missed by peer
//and hence should be ok. Need to discuss this further
if( !limIsInMCC(pMac) )
{
//Get current active session channel
peGetActiveSessionChannel(pMac, resumeChannel, resumePhyCbState);
}
else
{
*resumeChannel = pMac->lim.gResumeChannel;
*resumePhyCbState = pMac->lim.gResumePhyCbState;
}
return;
}
tANI_BOOLEAN limIsNOAInsertReqd(tpAniSirGlobal pMac)
{
tANI_U8 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 )
&& ( VOS_P2P_GO_MODE == pMac->lim.gpSession[i].pePersona )
)
{
return TRUE;
}
}
}
return FALSE;
}
tANI_BOOLEAN limIsconnectedOnDFSChannel(tANI_U8 currentChannel)
{
if(NV_CHANNEL_DFS == vos_nv_getChannelEnabledState(currentChannel))
{
return eANI_BOOLEAN_TRUE;
}
else
{
return eANI_BOOLEAN_FALSE;
}
}
#ifdef WLAN_FEATURE_11W
void limPmfSaQueryTimerHandler(void *pMacGlobal, tANI_U32 param)
{
tpAniSirGlobal pMac = (tpAniSirGlobal)pMacGlobal;
tPmfSaQueryTimerId timerId;
tpPESession psessionEntry;
tpDphHashNode pSta;
tANI_U32 maxRetries;
limLog(pMac, LOG1, FL("SA Query timer fires"));
timerId.value = param;
// Check that SA Query is in progress
if ((psessionEntry = peFindSessionBySessionId(
pMac, timerId.fields.sessionId)) == NULL)
{
limLog(pMac, LOGE, FL("Session does not exist for given session ID %d"),
timerId.fields.sessionId);
return;
}
if ((pSta = dphGetHashEntry(pMac, timerId.fields.peerIdx,
&psessionEntry->dph.dphHashTable)) == NULL)
{
limLog(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_cfgGetInt(pMac, WNI_CFG_PMF_SA_QUERY_MAX_RETRIES,
&maxRetries) != eSIR_SUCCESS)
{
limLog(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)
{
limLog(pMac, LOGE, FL("SA Query timed out,Deleting STA"));
limPrintMacAddr(pMac, pSta->staAddr, LOGE);
limSendDisassocMgmtFrame(pMac,
eSIR_MAC_DISASSOC_DUE_TO_INACTIVITY_REASON,
pSta->staAddr, psessionEntry, FALSE);
limTriggerSTAdeletion(pMac, pSta, psessionEntry);
pSta->pmfSaQueryState = DPH_SA_QUERY_TIMED_OUT;
return;
}
// Retry SA Query
limSendSaQueryRequestFrame(pMac, (tANI_U8 *)&(pSta->pmfSaQueryCurrentTransId),
pSta->staAddr, psessionEntry);
pSta->pmfSaQueryCurrentTransId++;
limLog(pMac, LOGE, FL("Starting SA Query retry %d"), pSta->pmfSaQueryRetryCount);
if (tx_timer_activate(&pSta->pmfSaQueryTimer) != TX_SUCCESS)
{
limLog(pMac, LOGE, FL("PMF SA Query timer activation failed!"));
pSta->pmfSaQueryState = DPH_SA_QUERY_NOT_IN_PROGRESS;
}
}
#endif
#ifdef WLAN_FEATURE_11AC
tANI_BOOLEAN limCheckVHTOpModeChange( tpAniSirGlobal pMac, tpPESession psessionEntry,
tANI_U8 chanWidth, tANI_U8 chanMode,
tANI_U8 staId, tANI_U8 *peerMac)
{
tUpdateVHTOpMode tempParam;
tempParam.opMode = chanWidth;
tempParam.chanMode = chanMode;
tempParam.staId = staId;
tempParam.smesessionId = psessionEntry->smeSessionId;
vos_mem_copy(tempParam.peer_mac, peerMac,
sizeof(tSirMacAddr));
limSendModeUpdate( pMac, &tempParam, psessionEntry );
return eANI_BOOLEAN_TRUE;
}
tANI_BOOLEAN limSetNssChange( tpAniSirGlobal pMac, tpPESession psessionEntry, tANI_U8 rxNss,
tANI_U8 staId, tANI_U8 *peerMac)
{
tUpdateRxNss tempParam;
tempParam.rxNss = rxNss;
tempParam.staId = staId;
tempParam.smesessionId = psessionEntry->smeSessionId;
vos_mem_copy(tempParam.peer_mac, peerMac,
sizeof(tSirMacAddr));
limSendRxNssUpdate( pMac, &tempParam, psessionEntry );
return eANI_BOOLEAN_TRUE;
}
tANI_BOOLEAN limCheckMembershipUserPosition( tpAniSirGlobal pMac, tpPESession psessionEntry,
tANI_U32 membership, tANI_U32 userPosition,
tANI_U8 staId)
{
tUpdateMembership tempParamMembership;
tUpdateUserPos tempParamUserPosition;
tempParamMembership.membership = membership;
tempParamMembership.staId = staId;
tempParamMembership.smesessionId = psessionEntry->smeSessionId;
vos_mem_copy(tempParamMembership.peer_mac, psessionEntry->bssId,
sizeof( tSirMacAddr ));
limSetMembership( pMac, &tempParamMembership, psessionEntry );
tempParamUserPosition.userPos = userPosition;
tempParamUserPosition.staId = staId;
tempParamUserPosition.smesessionId = psessionEntry->smeSessionId;
vos_mem_copy(tempParamUserPosition.peer_mac, psessionEntry->bssId,
sizeof( tSirMacAddr ));
limSetUserPos( pMac, &tempParamUserPosition, psessionEntry );
return eANI_BOOLEAN_TRUE;
}
#endif
void limGetShortSlotFromPhyMode(tpAniSirGlobal pMac, tpPESession psessionEntry,
tANI_U32 phyMode, tANI_U8 *pShortSlotEnabled)
{
tANI_U8 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 == VOS_STA_SAP_MODE) ||
(psessionEntry->pePersona == VOS_IBSS_MODE) ||
(psessionEntry->pePersona == VOS_P2P_GO_MODE))
{
val = true;
}
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;
}
limLog(pMac, LOG1, FL("phyMode = %u shortslotsupported = %u"), phyMode, val);
*pShortSlotEnabled = val;
}
void limUtilsframeshtons(tpAniSirGlobal pCtx,
tANI_U8 *pOut,
tANI_U16 pIn,
tANI_U8 fMsb)
{
(void)pCtx;
#if defined ( DOT11F_LITTLE_ENDIAN_HOST )
if ( !fMsb )
{
DOT11F_MEMCPY(pCtx, pOut, &pIn, 2);
}
else
{
*pOut = ( pIn & 0xff00 ) >> 8;
*( pOut + 1 ) = pIn & 0xff;
}
#else
if ( !fMsb )
{
*pOut = pIn & 0xff;
*( pOut + 1 ) = ( pIn & 0xff00 ) >> 8;
}
else
{
DOT11F_MEMCPY(pCtx, pOut, &pIn, 2);
}
#endif
}
void limUtilsframeshtonl(tpAniSirGlobal pCtx,
tANI_U8 *pOut,
tANI_U32 pIn,
tANI_U8 fMsb)
{
(void)pCtx;
#if defined ( DOT11F_LITTLE_ENDIAN_HOST )
if ( !fMsb )
{
DOT11F_MEMCPY(pCtx, pOut, &pIn, 4);
}
else
{
*pOut = ( pIn & 0xff000000 ) >> 24;
*( pOut + 1 ) = ( pIn & 0x00ff0000 ) >> 16;
*( pOut + 2 ) = ( pIn & 0x0000ff00 ) >> 8;
*( pOut + 3 ) = ( pIn & 0x000000ff );
}
#else
if ( !fMsb )
{
*( pOut ) = ( pIn & 0x000000ff );
*( pOut + 1 ) = ( pIn & 0x0000ff00 ) >> 8;
*( pOut + 2 ) = ( pIn & 0x00ff0000 ) >> 16;
*( pOut + 3 ) = ( pIn & 0xff000000 ) >> 24;
}
else
{
DOT11F_MEMCPY(pCtx, pOut, &pIn, 4);
}
#endif
}
#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
limSetProtectedBit(tpAniSirGlobal pMac,
tpPESession psessionEntry,
tSirMacAddr peer,
tpSirMacMgmtHdr pMacHdr)
{
tANI_U16 aid;
tpDphHashNode pStaDs;
if (LIM_IS_AP_ROLE(psessionEntry) || LIM_IS_BT_AMP_AP_ROLE(psessionEntry)) {
pStaDs = dphLookupHashEntry( 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->isKeyInstalled)
pMacHdr->fc.wep = 1;
}
else if ( psessionEntry->limRmfEnabled && psessionEntry->isKeyInstalled)
pMacHdr->fc.wep = 1;
} /*** end limSetProtectedBit() ***/
#endif
tANI_U8* lim_get_ie_ptr(tANI_U8 *pIes, int length, tANI_U8 eid)
{
int left = length;
tANI_U8 *ptr = pIes;
tANI_U8 elem_id, elem_len;
while(left >= 2)
{
elem_id = ptr[0];
elem_len = ptr[1];
left -= 2;
if(elem_len > left)
{
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,
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 + 2);
}
return NULL;
}
void lim_set_ht_caps(tpAniSirGlobal p_mac, tpPESession p_session_entry,
tANI_U8 *p_ie_start,tANI_U32 num_bytes)
{
v_U8_t *p_ie=NULL;
tDot11fIEHTCaps dot11_ht_cap = {0,};
PopulateDot11fHTCaps(p_mac, p_session_entry, &dot11_ht_cap);
p_ie = limGetIEPtr(p_mac, p_ie_start, num_bytes, DOT11F_EID_HTCAPS,
ONE_BYTE);
limLog( p_mac, LOG2, FL("p_ie %pK 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;
vos_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,
tANI_U8 *p_ie_start,tANI_U32 num_bytes)
{
v_U8_t *p_ie=NULL;
tDot11fIEVHTCaps dot11_vht_cap;
PopulateDot11fVHTCaps(p_mac, p_session_entry, &dot11_vht_cap);
p_ie = limGetIEPtr(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 {
tANI_U16 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 */
#ifdef SAP_AUTH_OFFLOAD
static tpDphHashNode
_sap_offload_parse_assoc_req(tpAniSirGlobal pmac,
tpSirAssocReq assoc_req,
struct sap_offload_add_sta_req *add_sta_req, bool *pinuse)
{
tpSirMacAssocReqFrame mac_assoc_req = NULL;
tpSirAssocReq temp_assoc_req;
tSirRetStatus status;
tpSirMacMgmtHdr mac_hdr = NULL;
tpDphHashNode sta_ds = NULL;
uint8_t *frame_body;
tpPESession session_entry = limIsApSessionActive(pmac);
mac_hdr = (tpSirMacMgmtHdr)add_sta_req->conn_req;
if (dph_entry_exist(pmac,
mac_hdr->sa,
add_sta_req->assoc_id,
&session_entry->dph.dphHashTable)) {
*pinuse = true;
return NULL;
}
/* Update Attribute and Remove IE for
* Software AP Authentication Offload
*/
frame_body = (tANI_U8 *)add_sta_req->conn_req + sizeof(*mac_hdr);
mac_assoc_req = (tpSirMacAssocReqFrame)frame_body;
mac_assoc_req->capabilityInfo.privacy = 0;
if (mac_hdr->fc.subType == SIR_MAC_MGMT_ASSOC_REQ) {
status = sirConvertAssocReqFrame2Struct(pmac,
frame_body,
add_sta_req->conn_req_len,
assoc_req);
} else {
status = sirConvertReassocReqFrame2Struct(pmac,
frame_body,
add_sta_req->conn_req_len,
assoc_req);
}
if (status != eSIR_SUCCESS) {
limLog(pmac, LOGW, FL("sap_offload_add_sta_req parse error\n"));
goto error;
}
/* For software AP Auth Offload feature
* Host will take it as none security station
* Force change to none security
*/
assoc_req->rsnPresent = 0;
assoc_req->wpaPresent = 0;
sta_ds = dphAddHashEntry(pmac,
mac_hdr->sa,
add_sta_req->assoc_id,
&session_entry->dph.dphHashTable);
if (sta_ds == NULL) {
/* Could not add hash table entry at DPH */
limLog(pmac, LOGE,
FL("could not add hash entry at DPH for aid=%d, MacAddr:"
MAC_ADDRESS_STR),
add_sta_req->assoc_id,MAC_ADDR_ARRAY(mac_hdr->sa));
goto error;
}
if (session_entry->parsedAssocReq != NULL) {
temp_assoc_req = session_entry->parsedAssocReq[sta_ds->assocId];
if (temp_assoc_req != NULL) {
if (temp_assoc_req->assocReqFrame) {
vos_mem_free(temp_assoc_req->assocReqFrame);
temp_assoc_req->assocReqFrame = NULL;
temp_assoc_req->assocReqFrameLength = 0;
}
vos_mem_free(temp_assoc_req);
temp_assoc_req = NULL;
}
session_entry->parsedAssocReq[sta_ds->assocId] = assoc_req;
}
error:
return sta_ds;
}
static void
_sap_offload_parse_sta_capability(tpDphHashNode sta_ds,
tpSirAssocReq assoc_req,
struct sap_offload_add_sta_req *add_sta_req)
{
tpSirMacMgmtHdr mac_hdr = NULL;
mac_hdr = (tpSirMacMgmtHdr)add_sta_req->conn_req;
sta_ds->mlmStaContext.htCapability = assoc_req->HTCaps.present;
#ifdef WLAN_FEATURE_11AC
sta_ds->mlmStaContext.vhtCapability = assoc_req->VHTCaps.present;
#endif
sta_ds->qos.addtsPresent = (assoc_req->addtsPresent==0) ? false : true;
sta_ds->qos.addts = assoc_req->addtsReq;
sta_ds->qos.capability = assoc_req->qosCapability;
sta_ds->versionPresent = 0;
/* short slot and short preamble should be
* updated before doing limaddsta
*/
sta_ds->shortPreambleEnabled =
(tANI_U8)assoc_req->capabilityInfo.shortPreamble;
sta_ds->shortSlotTimeEnabled =
(tANI_U8)assoc_req->capabilityInfo.shortSlotTime;
sta_ds->valid = 0;
/* The Auth Type of Software AP Authentication Offload
* is always Open System is host side
*/
sta_ds->mlmStaContext.authType = eSIR_OPEN_SYSTEM;
sta_ds->staType = STA_ENTRY_PEER;
/* Re/Assoc Response frame to requesting STA */
sta_ds->mlmStaContext.subType = mac_hdr->fc.subType;
sta_ds->mlmStaContext.listenInterval = assoc_req->listenInterval;
sta_ds->mlmStaContext.capabilityInfo = assoc_req->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*/
sta_ds->timWaitCount =
(tANI_U8)GET_TIM_WAIT_COUNT(assoc_req->listenInterval);
/* Initialise the Current successful
* MPDU's tranfered to this STA count as 0
*/
sta_ds->curTxMpduCnt = 0;
}
static tSirRetStatus
_sap_offload_parse_sta_vht(tpAniSirGlobal pmac,
tpDphHashNode sta_ds,
tpSirAssocReq assoc_req)
{
tpPESession session_entry = limIsApSessionActive(pmac);
if (IS_DOT11_MODE_HT(session_entry->dot11mode) &&
assoc_req->HTCaps.present && assoc_req->wmeInfoPresent) {
sta_ds->htGreenfield = (tANI_U8)assoc_req->HTCaps.greenField;
sta_ds->htAMpduDensity = assoc_req->HTCaps.mpduDensity;
sta_ds->htDsssCckRate40MHzSupport =
(tANI_U8)assoc_req->HTCaps.dsssCckMode40MHz;
sta_ds->htLsigTXOPProtection =
(tANI_U8)assoc_req->HTCaps.lsigTXOPProtection;
sta_ds->htMaxAmsduLength =
(tANI_U8)assoc_req->HTCaps.maximalAMSDUsize;
sta_ds->htMaxRxAMpduFactor = assoc_req->HTCaps.maxRxAMPDUFactor;
sta_ds->htMIMOPSState = assoc_req->HTCaps.mimoPowerSave;
sta_ds->htShortGI20Mhz = (tANI_U8)assoc_req->HTCaps.shortGI20MHz;
sta_ds->htShortGI40Mhz = (tANI_U8)assoc_req->HTCaps.shortGI40MHz;
sta_ds->htSupportedChannelWidthSet =
(tANI_U8)assoc_req->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
*/
sta_ds->htSecondaryChannelOffset =
(sta_ds->htSupportedChannelWidthSet) ?
session_entry->htSecondaryChannelOffset : 0;
#ifdef WLAN_FEATURE_11AC
if (assoc_req->operMode.present) {
sta_ds->vhtSupportedChannelWidthSet =
(tANI_U8)((assoc_req->operMode.chanWidth ==
eHT_CHANNEL_WIDTH_80MHZ) ?
WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ :
WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ);
sta_ds->htSupportedChannelWidthSet =
(tANI_U8)(assoc_req->operMode.chanWidth ?
eHT_CHANNEL_WIDTH_40MHZ : eHT_CHANNEL_WIDTH_20MHZ);
} else if (assoc_req->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.
*/
sta_ds->vhtSupportedChannelWidthSet =
(tANI_U8)((sta_ds->htSupportedChannelWidthSet ==
eHT_CHANNEL_WIDTH_20MHZ) ?
WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ :
session_entry->vhtTxChannelWidthSet );
sta_ds->htMaxRxAMpduFactor = assoc_req->VHTCaps.maxAMPDULenExp;
}
/* Lesser among the AP and STA bandwidth of operation. */
sta_ds->htSupportedChannelWidthSet =
(sta_ds->htSupportedChannelWidthSet <
session_entry->htSupportedChannelWidthSet) ?
sta_ds->htSupportedChannelWidthSet :
session_entry->htSupportedChannelWidthSet ;
#endif
sta_ds->baPolicyFlag = 0xFF;
sta_ds->htLdpcCapable = (tANI_U8)assoc_req->HTCaps.advCodingCap;
}
if (assoc_req->VHTCaps.present && assoc_req->wmeInfoPresent) {
sta_ds->vhtLdpcCapable = (tANI_U8)assoc_req->VHTCaps.ldpcCodingCap;
}
if (!assoc_req->wmeInfoPresent) {
sta_ds->mlmStaContext.htCapability = 0;
#ifdef WLAN_FEATURE_11AC
sta_ds->mlmStaContext.vhtCapability = 0;
#endif
}
#ifdef WLAN_FEATURE_11AC
if (limPopulateMatchingRateSet(pmac,
sta_ds,
&(assoc_req->supportedRates),
&(assoc_req->extendedRates),
assoc_req->HTCaps.supportedMCSSet,
session_entry , &assoc_req->VHTCaps)
!= eSIR_SUCCESS) {
#else
if (limPopulateMatchingRateSet(pmac,
sta_ds,
&(assoc_req->supportedRates),
&(assoc_req->extendedRates),
assoc_req->HTCaps.supportedMCSSet,
&(assoc_req->propIEinfo.propRates),
session_entry) != eSIR_SUCCESS) {
#endif
limLog(pmac, LOGE,
FL("Rate set mismatched for aid=%d, MacAddr: "
MAC_ADDRESS_STR),
sta_ds->assocId, MAC_ADDR_ARRAY(sta_ds->staAddr));
goto error;
}
#ifdef WLAN_FEATURE_11AC
if (assoc_req->operMode.present) {
sta_ds->vhtSupportedRxNss = assoc_req->operMode.rxNSS + 1;
} else {
sta_ds->vhtSupportedRxNss =
((sta_ds->supportedRates.vhtRxMCSMap & MCSMAPMASK2x2)
== MCSMAPMASK2x2) ? 1 : 2;
}
#endif
return eSIR_SUCCESS;
error:
return eSIR_FAILURE;
}
static void
_sap_offload_parse_sta_qos(tpAniSirGlobal pmac,
tpDphHashNode sta_ds,
tpSirAssocReq assoc_req)
{
tHalBitVal qos_mode;
tHalBitVal wsm_mode, wme_mode;
tpPESession session_entry = limIsApSessionActive(pmac);
limGetQosMode(session_entry, &qos_mode);
sta_ds->qosMode = eANI_BOOLEAN_FALSE;
sta_ds->lleEnabled = eANI_BOOLEAN_FALSE;
if (assoc_req->capabilityInfo.qos && (qos_mode == eHAL_SET)) {
sta_ds->lleEnabled = eANI_BOOLEAN_TRUE;
sta_ds->qosMode = eANI_BOOLEAN_TRUE;
}
sta_ds->wmeEnabled = eANI_BOOLEAN_FALSE;
sta_ds->wsmEnabled = eANI_BOOLEAN_FALSE;
limGetWmeMode(session_entry, &wme_mode);
if ((!sta_ds->lleEnabled) && assoc_req->wmeInfoPresent &&
(wme_mode == eHAL_SET)) {
sta_ds->wmeEnabled = eANI_BOOLEAN_TRUE;
sta_ds->qosMode = eANI_BOOLEAN_TRUE;
limGetWsmMode(session_entry, &wsm_mode);
/* WMM_APSD - WMM_SA related processing should be
* separate; WMM_SA and WMM_APSD can coexist
*/
if (assoc_req->WMMInfoStation.present) {
/* check whether AP supports or not */
if ((session_entry->limSystemRole == eLIM_AP_ROLE)
&& (session_entry->apUapsdEnable == 0) &&
(assoc_req->WMMInfoStation.acbe_uapsd
|| assoc_req->WMMInfoStation.acbk_uapsd
|| assoc_req->WMMInfoStation.acvo_uapsd
|| assoc_req->WMMInfoStation.acvi_uapsd)) {
/*
* Received Re/Association Request from
* STA when UPASD is not supported
*/
limLog( pmac, LOGE, FL( "AP do not support UAPSD so reply "
"to STA accordingly" ));
/* update UAPSD and send it to LIM to add STA */
sta_ds->qos.capability.qosInfo.acbe_uapsd = 0;
sta_ds->qos.capability.qosInfo.acbk_uapsd = 0;
sta_ds->qos.capability.qosInfo.acvo_uapsd = 0;
sta_ds->qos.capability.qosInfo.acvi_uapsd = 0;
sta_ds->qos.capability.qosInfo.maxSpLen = 0;
} else {
/* update UAPSD and send it to LIM to add STA */
sta_ds->qos.capability.qosInfo.acbe_uapsd =
assoc_req->WMMInfoStation.acbe_uapsd;
sta_ds->qos.capability.qosInfo.acbk_uapsd =
assoc_req->WMMInfoStation.acbk_uapsd;
sta_ds->qos.capability.qosInfo.acvo_uapsd =
assoc_req->WMMInfoStation.acvo_uapsd;
sta_ds->qos.capability.qosInfo.acvi_uapsd =
assoc_req->WMMInfoStation.acvi_uapsd;
sta_ds->qos.capability.qosInfo.maxSpLen =
assoc_req->WMMInfoStation.max_sp_length;
}
}
if (assoc_req->wsmCapablePresent && (wsm_mode == eHAL_SET))
sta_ds->wsmEnabled = eANI_BOOLEAN_TRUE;
}
}
/**
* lim_pop_sap_deferred_msg() - pop deferred sap message
*
* @pmac: pointer to mac
* @psessionentry: session of this entry
*
* This function is used to pop msg that in the deferred queue.
*
*/
void
lim_pop_sap_deferred_msg(tpAniSirGlobal pmac, tpPESession sessionentry)
{
struct slim_deferred_sap_msg* pdefermsg, *tmp;
tpSirMacMgmtHdr mac_hdr;
struct sap_offload_add_sta_req *add_sta_req;
tANI_U32 assoc_id;
if (pmac == NULL || sessionentry == NULL )
return;
TAILQ_FOREACH_SAFE(pdefermsg, &pmac->lim.glim_sap_deferred_msgq.tq_head,
list_elem, tmp) {
add_sta_req = pdefermsg->deferredmsg.bodyptr;
if (add_sta_req == NULL) {
TAILQ_REMOVE(&pmac->lim.glim_sap_deferred_msgq.tq_head,
pdefermsg, list_elem);
limDeferMsg(pmac, &pdefermsg->deferredmsg);
vos_mem_free(pdefermsg);
continue;
}
assoc_id = add_sta_req->assoc_id;
mac_hdr = (tpSirMacMgmtHdr)add_sta_req->conn_req;
if (mac_hdr == NULL) {
TAILQ_REMOVE(&pmac->lim.glim_sap_deferred_msgq.tq_head,
pdefermsg, list_elem);
limDeferMsg(pmac, &pdefermsg->deferredmsg);
vos_mem_free(pdefermsg);
continue;
}
if (!dph_entry_exist(pmac,
mac_hdr->sa, assoc_id,
&sessionentry->dph.dphHashTable)) {
TAILQ_REMOVE(&pmac->lim.glim_sap_deferred_msgq.tq_head,
pdefermsg, list_elem);
limLog(pmac, LOGE, FL("pop def msg(H %pK T %pK)."
"assid= %d, %pM"),
TAILQ_FIRST(&pmac->lim.glim_sap_deferred_msgq.tq_head),
TAILQ_LAST(&pmac->lim.glim_sap_deferred_msgq.tq_head,
t_slim_deferred_sap_msg_head),
assoc_id, mac_hdr->sa);
limDeferMsg(pmac, &pdefermsg->deferredmsg);
vos_mem_free(pdefermsg);
}
limLog(pmac, LOGE, FL("msg not pop."
"assid= %d, %pM"), assoc_id, mac_hdr->sa);
}
}
/**
* lim_push_sap_deferred_msg() - push sap message into queue
*
* @pmac: pointer to mac
* @lim_msgq: msg queue to store deferred msg
*
* This function is used to store msg into deferred queue.
*
*/
void
lim_push_sap_deferred_msg(tpAniSirGlobal pmac, tpSirMsgQ lim_msgq)
{
struct slim_deferred_sap_msg *pdefermsg;
pdefermsg = vos_mem_malloc(sizeof(*pdefermsg));
if (pdefermsg == NULL) {
limLog(pmac, LOGE, FL("No mem for push msg %pK!"), lim_msgq);
vos_mem_free(lim_msgq->bodyptr);
return;
}
vos_mem_copy((tANI_U8 *)&pdefermsg->deferredmsg,
(tANI_U8 *)lim_msgq,
sizeof(tSirMsgQ));
TAILQ_INSERT_TAIL(&pmac->lim.glim_sap_deferred_msgq.tq_head, pdefermsg,
list_elem);
limLog(pmac, LOGW, FL("push def msg(H %pK T %pK): P %pK."),
TAILQ_FIRST(&pmac->lim.glim_sap_deferred_msgq.tq_head),
TAILQ_LAST(&pmac->lim.glim_sap_deferred_msgq.tq_head,
t_slim_deferred_sap_msg_head),
pdefermsg);
}
/**
* lim_init_sap_deferred_msg() - init sap deferred msg queue head
*
* @pmac: pointer to mac
*
* This function is used to int sap deferred msg queue head
*
*/
void
lim_init_sap_deferred_msg_queue(tpAniSirGlobal pmac)
{
TAILQ_INIT(&pmac->lim.glim_sap_deferred_msgq.tq_head);
}
/**
* lim_cleanup_sap_deferred_msg() - cleanup sap deferred msg queue elements
*
* @pmac: pointer to mac
*
* This function is used to cleanup sap deferred msg queue elements
*
*/
void
lim_cleanup_sap_deferred_msg_queue(tpAniSirGlobal pmac)
{
struct slim_deferred_sap_msg *pdefermsg;
tSirMsgQ *lim_msgq;
while (!TAILQ_EMPTY(&pmac->lim.glim_sap_deferred_msgq.tq_head)) {
pdefermsg = (struct slim_deferred_sap_msg*)TAILQ_FIRST(
&pmac->lim.glim_sap_deferred_msgq.tq_head);
lim_msgq = &pdefermsg->deferredmsg;
vos_mem_free(lim_msgq->bodyptr);
vos_mem_free(pdefermsg);
}
}
void lim_sap_offload_add_sta(tpAniSirGlobal pmac, tpSirMsgQ lim_msgq)
{
tpSirAssocReq assoc_req = NULL;
tpDphHashNode sta_ds = NULL;
tpSirMacMgmtHdr mac_hdr = NULL;
struct sap_offload_add_sta_req *add_sta_req = NULL;
tpPESession session_entry = limIsApSessionActive(pmac);
bool sta_inuse = false;
add_sta_req = (struct sap_offload_add_sta_req *)lim_msgq->bodyptr;
mac_hdr = (tpSirMacMgmtHdr)add_sta_req->conn_req;
limLog(pmac, LOGW, FL("sta %pM aid %d"),
mac_hdr->sa, add_sta_req->assoc_id);
if (session_entry == NULL) {
PELOGE(limLog(pmac, LOGE, FL(" Session not found"));)
return;
}
assoc_req = vos_mem_malloc(sizeof(*assoc_req));
if (NULL == assoc_req) {
PELOGE(limLog(pmac, LOGE, FL("Allocate Memory failed in assoc_req"));)
goto error;
}
vos_mem_set(assoc_req , sizeof(*assoc_req), 0);
/* parse Assoc req frame for station information */
sta_ds = _sap_offload_parse_assoc_req(pmac, assoc_req,
add_sta_req, &sta_inuse);
if (sta_inuse == true) {
lim_push_sap_deferred_msg(pmac, lim_msgq);
vos_mem_free(assoc_req );
return;
}
if (sta_ds == NULL) {
limSendDisassocMgmtFrame(pmac,
eSIR_MAC_UNSPEC_FAILURE_REASON,
mac_hdr->sa,
session_entry, FALSE);
PELOGE(limLog(pmac, LOGE, FL("could not add hash entry."
" disassoc sta %pM"),mac_hdr->sa);)
vos_mem_free(assoc_req);
goto error;
}
/* Parse Station Capability */
_sap_offload_parse_sta_capability(sta_ds, assoc_req, add_sta_req);
/* Parse Station HT/VHT information */
if (_sap_offload_parse_sta_vht(pmac, sta_ds, assoc_req)
== eSIR_FAILURE) {
limSendDisassocMgmtFrame(pmac,
eSIR_MAC_UNSPEC_FAILURE_REASON,
mac_hdr->sa,
session_entry, FALSE);
PELOGE(limLog(pmac, LOGE, FL("mismatch ht/vht information"
" disassoc sta %pM"),mac_hdr->sa);)
vos_mem_free(assoc_req);
goto error;
}
/* Parse Station QOS information */
_sap_offload_parse_sta_qos(pmac, sta_ds, assoc_req);
if (assoc_req->ExtCap.present) {
lim_set_stads_rtt_cap(sta_ds,
(struct s_ext_cap *) assoc_req->ExtCap.bytes);
} else {
sta_ds->timingMeasCap = 0;
PELOG1(limLog(pmac, LOG1, FL("ExtCap not present"));)
}
session_entry->parsedAssocReq[sta_ds->assocId] = assoc_req;
if (limAddSta(pmac, sta_ds, false, session_entry) != eSIR_SUCCESS) {
limLog(pmac, LOGE, FL("could not Add STA %pM with assocId=%d"),
mac_hdr->sa, sta_ds->assocId);
limSendDisassocMgmtFrame(pmac,
eSIR_MAC_UNSPEC_FAILURE_REASON,
mac_hdr->sa,
session_entry, FALSE);
}
error:
vos_mem_free(add_sta_req);
return;
}
void
lim_sap_offload_del_sta(tpAniSirGlobal pmac, tpSirMsgQ lim_msgq)
{
struct sap_offload_del_sta_req *del_sta_req = NULL;
tpDphHashNode sta_ds = NULL;
tANI_U16 assoc_id = 0;
tpPESession psession_entry = limIsApSessionActive(pmac);
if (psession_entry == NULL) {
PELOGE(limLog(pmac, LOGE, FL(" Session not found"));)
return;
}
del_sta_req = ( struct sap_offload_del_sta_req *)lim_msgq->bodyptr;
sta_ds = dphLookupHashEntry(pmac,
del_sta_req->sta_mac,
&assoc_id,
&psession_entry->dph.dphHashTable);
limLog(pmac, LOGW, FL("sta %pM aid %d reason %x flag %x"),
del_sta_req->sta_mac, del_sta_req->assoc_id,
del_sta_req->reason_code,del_sta_req->flags);
if (sta_ds == NULL) {
/*
* Disassociating STA is not associated.
* Log error
*/
PELOGE(limLog(pmac, LOGE,
FL("received del sta event that sta not exist in table "
"reasonCode=%d, addr "MAC_ADDRESS_STR),
del_sta_req->reason_code,
MAC_ADDR_ARRAY(del_sta_req->sta_mac));)
goto error;
}
if (assoc_id != (tANI_U16)del_sta_req->assoc_id) {
/*
* Associate Id mismatch
* Log error
*/
PELOGE(limLog(pmac, LOGE,
FL("received del sta event that sta assoc Id mismatch"));)
goto error;
}
sta_ds->mlmStaContext.cleanupTrigger = eLIM_PEER_ENTITY_DISASSOC;
if (SAP_OFL_DEL_STA_FLAG_RECONNECT == del_sta_req->flags) {
sta_ds->mlmStaContext.disassocReason =
(tSirMacReasonCodes)eSIR_SME_SAP_AUTH_OFFLOAD_PEER_UPDATE_STATUS;
} else {
sta_ds->mlmStaContext.disassocReason =
(tSirMacReasonCodes)del_sta_req->reason_code;
}
sta_ds->mlmStaContext.updateContext = 1;
limSendSmeDisassocInd(pmac, sta_ds, psession_entry);
error:
vos_mem_free(del_sta_req);
return;
}
#endif /* SAP_AUTH_OFFLOAD */
/**
* 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) {
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
"mac or session context is null");
/* let main routine handle it */
return true;
}
if (limIsGroupAddr(a1) || limIsAddrBC(a1)) {
/* just for fail safe, don't handle MC/BC a1 in this routine */
return true;
}
if (!vos_mem_compare(a1, session->selfMacAddr, 6)) {
limLog(mac_ctx, LOGE,
FL("Invalid A1 address in received frame"));
return false;
}
return true;
}
/**
* lim_set_stads_rtt_cap() - update station node RTT capability
* @sta_ds: Station hash node
* @ext_cap: Pointer to extended capability
*
* 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)
{
sta_ds->timingMeasCap = 0;
sta_ds->timingMeasCap |= (ext_cap->timingMeas)?
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_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)) {
vos_mem_zero(&mac_ctx->lim.gLimOverlap11gParams,
sizeof(mac_ctx->lim.gLimOverlap11gParams));
vos_mem_zero(&mac_ctx->lim.gLimOverlap11aParams,
sizeof(mac_ctx->lim.gLimOverlap11aParams));
vos_mem_zero(&mac_ctx->lim.gLimOverlapHt20Params,
sizeof(mac_ctx->lim.gLimOverlapHt20Params));
vos_mem_zero(&mac_ctx->lim.gLimOverlapNonGfParams,
sizeof(mac_ctx->lim.gLimOverlapNonGfParams));
mac_ctx->lim.gHTOperMode = eSIR_HT_OP_MODE_PURE;
}
}
/**
* 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: eHalStatus
*/
eHalStatus 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;
vos_msg_t msg = {0};
tSirRetStatus status;
uint8_t *temp, i;
wlan_cfgGetInt(mac_ctx, WNI_CFG_DOT11_MODE, &dot11mode);
if (IS_DOT11_MODE_VHT(dot11mode))
vht_enabled = true;
status = PopulateDot11fExtCap(mac_ctx, vht_enabled, &ext_cap_data,
NULL);
if (eSIR_SUCCESS != status) {
limLog(mac_ctx, LOGE, FL("Failed to populate ext cap IE"));
return eHAL_STATUS_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, true);
}
/* Allocate memory for the WMI request, and copy the parameter */
vdev_ie = vos_mem_malloc(sizeof(*vdev_ie) + num_bytes);
if (!vdev_ie) {
limLog(mac_ctx, LOGE, FL("Failed to allocate memory"));
return eHAL_STATUS_FAILED_ALLOC;
}
vdev_ie->vdev_id = session_id;
vdev_ie->ie_id = DOT11F_EID_EXTCAP;
vdev_ie->length = num_bytes;
limLog(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++)
limLog(mac_ctx, LOG2, FL("%d byte is %02x"), i+1, *temp);
vdev_ie->data = (uint8_t *)vdev_ie + sizeof(*vdev_ie);
vos_mem_copy(vdev_ie->data, ext_cap_data.bytes, num_bytes);
msg.type = WDA_SET_IE_INFO;
msg.bodyptr = vdev_ie;
msg.reserved = 0;
if (VOS_STATUS_SUCCESS !=
vos_mq_post_message(VOS_MODULE_ID_WDA, &msg)) {
limLog(mac_ctx, LOGE,
FL("Not able to post WDA_SET_IE_INFO to WDA"));
vos_mem_free(vdev_ie);
return eHAL_STATUS_FAILURE;
}
return eHAL_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) {
limLog(mac_ctx, LOG1, FL("NULL addn_ie pointer"));
return eSIR_IGNORE_IE ;
}
tempbuf = vos_mem_malloc(left);
if (NULL == tempbuf) {
limLog(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) {
limLog( mac_ctx, LOGE,
FL("Invalid IEs eid = %d elem_len=%d left=%d"),
elem_id, elem_len, left);
vos_mem_free(tempbuf);
return eSIR_FAILURE;
}
if (!(DOT11F_EID_EXTCAP == elem_id)) {
vos_mem_copy (tempbuf + templen, &ptr[0], elem_len + 2);
templen += (elem_len + 2);
} else {
if (NULL != extracted_ie) {
vos_mem_set(extracted_ie,
DOT11F_IE_EXTCAP_MAX_LEN + 2, 0);
if (elem_len <= DOT11F_IE_EXTCAP_MAX_LEN)
vos_mem_copy(extracted_ie, &ptr[0],
elem_len + 2);
}
}
left -= elem_len;
ptr += (elem_len + 2);
}
vos_mem_copy (addn_ie, tempbuf, templen);
*addn_ielen = templen;
vos_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) {
limLog( mac_ctx, LOGE, FL("Invalid Buffer Address"));
return;
}
if(NULL == dst) {
limLog(mac_ctx, LOGE, FL("NULL dst pointer"));
return ;
}
if (DOT11F_EID_EXTCAP != buf[0] || buf[1] > DOT11F_IE_EXTCAP_MAX_LEN) {
limLog(mac_ctx, LOG1, FL("Invalid IEs eid = %d elem_len=%d "),
buf[0],buf[1]);
return;
}
vos_mem_set((uint8_t *)&out[0], DOT11F_IE_EXTCAP_MAX_LEN, 0);
vos_mem_copy(&out[0], &buf[2], buf[1]);
if (DOT11F_PARSE_SUCCESS != dot11fUnpackIeExtCap(mac_ctx, &out[0],
buf[1], dst))
limLog(mac_ctx, LOGE, FL("dot11fUnpackIeExtCap 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;
vos_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) {
limLog(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
* @add: true if add the capabilites, false if strip the capabilites.
*
* This function is used to take @src info and add/strip it to/from
* @dst extended capabilities info.
*
* Return: None
*/
void lim_merge_extcap_struct(tDot11fIEExtCap *dst,
tDot11fIEExtCap *src,
bool add)
{
uint8_t *tempdst = (uint8_t *)dst->bytes;
uint8_t *tempsrc = (uint8_t *)src->bytes;
uint8_t structlen = member_size(tDot11fIEExtCap, bytes);
/* Return if @src not present */
if (!src->present)
return;
/* Return if strip the capabilites from @dst which not present */
if (!dst->present && !add)
return;
/* Merge the capabilites info in other cases */
while (tempdst && tempsrc && structlen--) {
if (add)
*tempdst |= *tempsrc;
else
*tempdst &= *tempsrc;
tempdst++;
tempsrc++;
}
dst->num_bytes = lim_compute_ext_cap_ie_length(dst);
if (dst->num_bytes == 0)
dst->present = 0;
else
dst->present = 1;
}
/**
* lim_get_80Mhz_center_channel - finds 80 Mhz center channel
*
* @primary_channel: Primary channel for given 80 MHz band
*
* There are fixed 80MHz band and for each fixed band there is only one center
* valid channel. Also location of primary channel decides what 80 MHz band will
* it use, hence it decides what center channel will be used. This function
* does thus calculation and returns the center channel.
*
* Return: center channel
*/
uint8_t
lim_get_80Mhz_center_channel(uint8_t primary_channel)
{
if(primary_channel >= 36 && primary_channel <= 48)
return (36+48)/2;
if(primary_channel >= 52 && primary_channel <= 64)
return (52+64)/2;
if(primary_channel >= 100 && primary_channel <= 112)
return (100+112)/2;
if(primary_channel >= 116 && primary_channel <= 128)
return (116+128)/2;
if(primary_channel >= 132 && primary_channel <= 144)
return (132+144)/2;
if(primary_channel >= 149 && primary_channel <= 161)
return (149+161)/2;
return HAL_INVALID_CHANNEL_ID;
}
/**
* lim_compute_ext_cap_ie_length - compute the length of ext cap ie
* based on the bits set
* @ext_cap: extended IEs structure
*
* Return: length of the ext cap ie, 0 means should not present
*/
tANI_U8 lim_compute_ext_cap_ie_length (tDot11fIEExtCap *ext_cap) {
tANI_U8 i = DOT11F_IE_EXTCAP_MAX_LEN;
while (i) {
if (ext_cap->bytes[i-1]) {
break;
}
i --;
}
return i;
}
/**
* lim_is_robust_mgmt_action_frame() - Check if action catagory is
* robust action frame
* @action_catagory: Action frame catagory.
*
* This function is used to check if given action catagory is robust
* action frame.
*
* Return: bool
*/
bool lim_is_robust_mgmt_action_frame(uint8_t action_catagory)
{
switch (action_catagory) {
/*
* NOTE: This function doesn't take care of the DMG
* (Directional Multi-Gigatbit) BSS case as 8011ad
* support is not yet added. In future, if the support
* is required then this function need few more arguments
* and little change in logic.
*/
case SIR_MAC_ACTION_SPECTRUM_MGMT:
case SIR_MAC_ACTION_QOS_MGMT:
case SIR_MAC_ACTION_DLP:
case SIR_MAC_ACTION_BLKACK:
case SIR_MAC_ACTION_RRM:
case SIR_MAC_ACTION_FAST_BSS_TRNST:
case SIR_MAC_ACTION_SA_QUERY:
case SIR_MAC_ACTION_PROT_DUAL_PUB:
case SIR_MAC_ACTION_WNM:
case SIR_MAC_ACITON_MESH:
case SIR_MAC_ACTION_MHF:
case SIR_MAC_ACTION_FST:
return true;
default:
VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO,
FL("non-PMF action category[%d] "),
action_catagory);
break;
}
return false;
}
/**
* lim_update_caps_info_for_bss - Update capability info for this BSS
*
* @mac_ctx: mac context
* @caps: Pointer to capability info to be updated
* @bss_caps: Capability info of the BSS
*
* Update the capability info in Assoc/Reassoc request frames and reset
* the spectrum management, short preamble, immediate block ack bits
* if the BSS doesnot support it
*
* Return: None
*/
void lim_update_caps_info_for_bss(tpAniSirGlobal mac_ctx,
uint16_t *caps, uint16_t bss_caps)
{
if (!(bss_caps & LIM_SPECTRUM_MANAGEMENT_BIT_MASK)) {
*caps &= (~LIM_SPECTRUM_MANAGEMENT_BIT_MASK);
limLog(mac_ctx, LOG1, FL("Clearing spectrum management:no AP support"));
}
if (!(bss_caps & LIM_SHORT_PREAMBLE_BIT_MASK)) {
*caps &= (~LIM_SHORT_PREAMBLE_BIT_MASK);
limLog(mac_ctx, LOG1, FL("Clearing short preamble:no AP support"));
}
if (!(bss_caps & LIM_IMMEDIATE_BLOCK_ACK_MASK)) {
*caps &= (~LIM_IMMEDIATE_BLOCK_ACK_MASK);
limLog(mac_ctx, LOG1, FL("Clearing Immed Blk Ack:no AP support"));
}
}
/*
* lim_parse_beacon_for_tim() - Extract TIM and beacon timestamp
* from beacon frame.
* @mac_ctx: mac context
* @rx_packet_info: beacon frame
* @session: Session on which beacon is received
*
* This function is used if beacon is corrupted and parser API fails to
* parse the whole beacon. Try to extract the TIM params and timestamp
* from the beacon, required to enter BMPS
*
* Return: void
*/
void lim_parse_beacon_for_tim(tpAniSirGlobal mac_ctx,
uint8_t* rx_packet_info, tpPESession session)
{
uint32_t frame_len;
uint8_t *frame;
uint8_t *ie_ptr;
tSirMacTim *tim;
frame = WDA_GET_RX_MPDU_DATA(rx_packet_info);
frame_len = WDA_GET_RX_PAYLOAD_LEN(rx_packet_info);
if (frame_len < (SIR_MAC_B_PR_SSID_OFFSET + SIR_MAC_MIN_IE_LEN)) {
limLog(mac_ctx, LOGE, FL("Beacon length too short to parse"));
return;
}
ie_ptr = lim_get_ie_ptr((frame + SIR_MAC_B_PR_SSID_OFFSET),
frame_len, SIR_MAC_TIM_EID);
if (NULL != ie_ptr) {
/* Ignore EID and Length field */
tim = (tSirMacTim *)(ie_ptr + IE_LEN_SIZE + IE_EID_SIZE);
vos_mem_copy((uint8_t*)&session->lastBeaconTimeStamp,
(uint8_t*)frame, sizeof(uint64_t));
if (tim->dtimCount >= MAX_DTIM_COUNT)
tim->dtimCount = DTIM_COUNT_DEFAULT;
if (tim->dtimPeriod >= MAX_DTIM_PERIOD)
tim->dtimPeriod = DTIM_PERIOD_DEFAULT;
session->lastBeaconDtimCount = tim->dtimCount;
session->lastBeaconDtimPeriod = tim->dtimPeriod;
session->currentBssBeaconCnt++;
limLog(mac_ctx, LOG1,
FL("currentBssBeaconCnt %d lastBeaconDtimCount %d lastBeaconDtimPeriod %d"),
session->currentBssBeaconCnt,
session->lastBeaconDtimCount,
session->lastBeaconDtimPeriod);
}
return;
}
bool lim_check_if_vendor_oui_match(tpAniSirGlobal mac_ctx,
uint8_t *oui, uint8_t oui_len,
uint8_t *ie, uint8_t ie_len)
{
uint8_t *ptr = ie;
uint8_t elem_id = 0;
if (NULL == ie || 0 == ie_len) {
limLog(mac_ctx, LOG1, FL("IE Null or ie len zero %d"), ie_len);
return false;
}
elem_id = *ie;
if (elem_id == IE_EID_VENDOR &&
!adf_os_mem_cmp(&ptr[2], oui, oui_len))
return true;
else
return false;
}