blob: 1206f1ba630ff11fd1b71b6e6cb9b0634a78438d [file] [log] [blame]
/*
* Copyright (c) 2012-2018 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
* above copyright notice and this permission notice appear in all
* copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
/*
* This file was originally distributed by Qualcomm Atheros, Inc.
* under proprietary terms before Copyright ownership was assigned
* to the Linux Foundation.
*/
/**=========================================================================
\file smeApi.c
\brief Definitions for SME APIs
========================================================================*/
/*===========================================================================
EDIT HISTORY FOR FILE
This section contains comments describing changes made to the module.
Notice that changes are listed in reverse chronological order.
when who what, where, why
---------- --- --------------------------------------------------------
06/03/10 js Added support to hostapd driven
* deauth/disassoc/mic failure
===========================================================================*/
/*--------------------------------------------------------------------------
Include Files
------------------------------------------------------------------------*/
#include "smsDebug.h"
#include "sme_Api.h"
#include "csrInsideApi.h"
#include "smeInside.h"
#include "csrInternal.h"
#include "wlan_qct_wda.h"
#include "halMsgApi.h"
#include "vos_trace.h"
#include "sme_Trace.h"
#include "vos_types.h"
#include "vos_trace.h"
#include "vos_utils.h"
#include "sapApi.h"
#include "macTrace.h"
#ifdef WLAN_FEATURE_NAN
#include "nan_Api.h"
#endif
#include "regdomain_common.h"
#include "schApi.h"
#include "sme_nan_datapath.h"
#include "csrApi.h"
#include "utilsApi.h"
extern tSirRetStatus uMacPostCtrlMsg(void* pSirGlobal, tSirMbMsg* pMb);
#define LOG_SIZE 256
#define TL_INIT_STATE 0
static tSelfRecoveryStats gSelfRecoveryStats;
// TxMB Functions
extern eHalStatus pmcPrepareCommand( tpAniSirGlobal pMac, tANI_U32 sessionId,
eSmeCommandType cmdType, void *pvParam,
tANI_U32 size, tSmeCmd **ppCmd);
extern void pmcReleaseCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand );
extern void qosReleaseCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand );
extern void csr_release_roc_req_cmd(tpAniSirGlobal mac_ctx);
extern eHalStatus p2pProcessRemainOnChannelCmd(tpAniSirGlobal pMac, tSmeCmd *p2pRemainonChn);
extern eHalStatus sme_remainOnChnRsp( tpAniSirGlobal pMac, tANI_U8 *pMsg);
extern eHalStatus sme_remainOnChnReady( tHalHandle hHal, tANI_U8* pMsg);
extern eHalStatus p2pProcessNoAReq(tpAniSirGlobal pMac, tSmeCmd *pNoACmd);
static eHalStatus initSmeCmdList(tpAniSirGlobal pMac);
static void smeAbortCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand, tANI_BOOLEAN fStopping );
eCsrPhyMode sme_GetPhyMode(tHalHandle hHal);
eHalStatus sme_HandleChangeCountryCode(tpAniSirGlobal pMac, void *pMsgBuf);
void sme_DisconnectConnectedSessions(tpAniSirGlobal pMac);
eHalStatus sme_HandleGenericChangeCountryCode(tpAniSirGlobal pMac, void *pMsgBuf);
eHalStatus sme_HandlePreChannelSwitchInd(tHalHandle hHal, void *pMsgBuf);
eHalStatus sme_HandlePostChannelSwitchInd(tHalHandle hHal);
#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
tANI_BOOLEAN csrIsSupportedChannel(tpAniSirGlobal pMac, tANI_U8 channelId);
#endif
#ifdef WLAN_FEATURE_11W
eHalStatus sme_UnprotectedMgmtFrmInd( tHalHandle hHal,
tpSirSmeUnprotMgmtFrameInd pSmeMgmtFrm );
#endif
/* Message processor for events from DFS */
eHalStatus dfsMsgProcessor(tpAniSirGlobal pMac,
v_U16_t msg_type,void *pMsgBuf);
/* Channel Change Response Indication Handler */
eHalStatus sme_ProcessChannelChangeResp(tpAniSirGlobal pMac,
v_U16_t msg_type,void *pMsgBuf);
eHalStatus sme_process_set_max_tx_power(tpAniSirGlobal pMac,
tSmeCmd *command);
eHalStatus
sme_process_set_max_tx_power_per_band(tpAniSirGlobal mac_ctx,
tSmeCmd *command);
//Internal SME APIs
eHalStatus sme_AcquireGlobalLock( tSmeStruct *psSme)
{
eHalStatus status = eHAL_STATUS_INVALID_PARAMETER;
if(psSme)
{
if( VOS_IS_STATUS_SUCCESS( vos_lock_acquire( &psSme->lkSmeGlobalLock) ) )
{
status = eHAL_STATUS_SUCCESS;
}
}
return (status);
}
eHalStatus sme_ReleaseGlobalLock( tSmeStruct *psSme)
{
eHalStatus status = eHAL_STATUS_INVALID_PARAMETER;
if(psSme)
{
if( VOS_IS_STATUS_SUCCESS( vos_lock_release( &psSme->lkSmeGlobalLock) ) )
{
status = eHAL_STATUS_SUCCESS;
}
}
return (status);
}
/**
* free_sme_cmds() - This function frees memory allocated for SME commands
* @mac_ctx: Pointer to Global MAC structure
*
* This function frees memory allocated for SME commands
*
* @Return: void
*/
static void free_sme_cmds(tpAniSirGlobal mac_ctx)
{
uint32_t idx;
if (NULL == mac_ctx->sme.pSmeCmdBufAddr)
return;
for (idx = 0; idx < mac_ctx->sme.totalSmeCmd; idx++)
vos_mem_free(mac_ctx->sme.pSmeCmdBufAddr[idx]);
vos_mem_free(mac_ctx->sme.pSmeCmdBufAddr);
mac_ctx->sme.pSmeCmdBufAddr = NULL;
}
static eHalStatus initSmeCmdList(tpAniSirGlobal pMac)
{
eHalStatus status;
tSmeCmd *pCmd;
tANI_U32 cmd_idx;
uint32_t sme_cmd_ptr_ary_sz;
VOS_STATUS vosStatus;
vos_timer_t* cmdTimeoutTimer = NULL;
pMac->sme.totalSmeCmd = SME_TOTAL_COMMAND;
if (!HAL_STATUS_SUCCESS(status = csrLLOpen(pMac->hHdd,
&pMac->sme.smeCmdActiveList)))
goto end;
if (!HAL_STATUS_SUCCESS(status = csrLLOpen(pMac->hHdd,
&pMac->sme.smeCmdPendingList)))
goto end;
if (!HAL_STATUS_SUCCESS(status = csrLLOpen(pMac->hHdd,
&pMac->sme.smeScanCmdActiveList)))
goto end;
if (!HAL_STATUS_SUCCESS(status = csrLLOpen(pMac->hHdd,
&pMac->sme.smeScanCmdPendingList)))
goto end;
if (!HAL_STATUS_SUCCESS(status = csrLLOpen(pMac->hHdd,
&pMac->sme.smeCmdFreeList)))
goto end;
/* following pointer contains array of pointers for tSmeCmd* */
sme_cmd_ptr_ary_sz = sizeof(void*) * pMac->sme.totalSmeCmd;
pMac->sme.pSmeCmdBufAddr = vos_mem_malloc(sme_cmd_ptr_ary_sz);
if (NULL == pMac->sme.pSmeCmdBufAddr) {
status = eHAL_STATUS_FAILURE;
goto end;
}
status = eHAL_STATUS_SUCCESS;
vos_mem_set(pMac->sme.pSmeCmdBufAddr, sme_cmd_ptr_ary_sz, 0);
for (cmd_idx = 0; cmd_idx < pMac->sme.totalSmeCmd; cmd_idx++) {
/*
* Since total size of all commands together can be huge chunk of
* memory, allocate SME cmd individually. These SME CMDs are moved
* between pending and active queues. And these freeing of these
* queues just manipulates the list but does not actually frees SME
* CMD pointers. Hence store each SME CMD address in the array,
* sme.pSmeCmdBufAddr. This will later facilitate freeing up of all
* SME CMDs with just a for loop.
*/
pMac->sme.pSmeCmdBufAddr[cmd_idx] = vos_mem_malloc(sizeof(tSmeCmd));
if (NULL == pMac->sme.pSmeCmdBufAddr[cmd_idx]) {
status = eHAL_STATUS_FAILURE;
free_sme_cmds(pMac);
goto end;
}
pCmd = (tSmeCmd*)pMac->sme.pSmeCmdBufAddr[cmd_idx];
csrLLInsertTail(&pMac->sme.smeCmdFreeList, &pCmd->Link, LL_ACCESS_LOCK);
}
/* This timer is only to debug the active list command timeout */
cmdTimeoutTimer = (vos_timer_t*)vos_mem_malloc(sizeof(vos_timer_t));
if (cmdTimeoutTimer)
{
pMac->sme.smeCmdActiveList.cmdTimeoutTimer = cmdTimeoutTimer;
vosStatus =
vos_timer_init( pMac->sme.smeCmdActiveList.cmdTimeoutTimer,
VOS_TIMER_TYPE_SW,
activeListCmdTimeoutHandle,
(void*) pMac);
if (!VOS_IS_STATUS_SUCCESS(vosStatus))
{
VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
"Init Timer fail for active list command process time out");
vos_mem_free(pMac->sme.smeCmdActiveList.cmdTimeoutTimer);
}
else
{
pMac->sme.smeCmdActiveList.cmdTimeoutDuration =
CSR_ACTIVE_LIST_CMD_TIMEOUT_VALUE;
}
}
end:
if (!HAL_STATUS_SUCCESS(status))
smsLog(pMac, LOGE, "failed to initialize sme command list:%d\n",
status);
return (status);
}
void smeReleaseCommand(tpAniSirGlobal pMac, tSmeCmd *pCmd)
{
pCmd->command = eSmeNoCommand;
csrLLInsertTail(&pMac->sme.smeCmdFreeList, &pCmd->Link, LL_ACCESS_LOCK);
}
static void smeReleaseCmdList(tpAniSirGlobal pMac, tDblLinkList *pList)
{
tListElem *pEntry;
tSmeCmd *pCommand;
while((pEntry = csrLLRemoveHead(pList, LL_ACCESS_LOCK)) != NULL)
{
//TODO: base on command type to call release functions
//reinitialize different command types so they can be reused
pCommand = GET_BASE_ADDR( pEntry, tSmeCmd, Link );
smeAbortCommand(pMac, pCommand, eANI_BOOLEAN_TRUE);
}
}
static void purgeSmeCmdList(tpAniSirGlobal pMac)
{
//release any out standing commands back to free command list
smeReleaseCmdList(pMac, &pMac->sme.smeCmdPendingList);
smeReleaseCmdList(pMac, &pMac->sme.smeCmdActiveList);
smeReleaseCmdList(pMac, &pMac->sme.smeScanCmdPendingList);
smeReleaseCmdList(pMac, &pMac->sme.smeScanCmdActiveList);
}
void purgeSmeSessionCmdList(tpAniSirGlobal pMac, tANI_U32 sessionId,
tDblLinkList *pList)
{
//release any out standing commands back to free command list
tListElem *pEntry, *pNext;
tSmeCmd *pCommand;
tDblLinkList localList;
vos_mem_zero(&localList, sizeof(tDblLinkList));
if(!HAL_STATUS_SUCCESS(csrLLOpen(pMac->hHdd, &localList)))
{
smsLog(pMac, LOGE, FL(" failed to open list"));
return;
}
csrLLLock(pList);
pEntry = csrLLPeekHead(pList, LL_ACCESS_NOLOCK);
while(pEntry != NULL)
{
pNext = csrLLNext(pList, pEntry, LL_ACCESS_NOLOCK);
pCommand = GET_BASE_ADDR( pEntry, tSmeCmd, Link );
if(pCommand->sessionId == sessionId)
{
if(csrLLRemoveEntry(pList, pEntry, LL_ACCESS_NOLOCK))
{
csrLLInsertTail(&localList, pEntry, LL_ACCESS_NOLOCK);
}
}
pEntry = pNext;
}
csrLLUnlock(pList);
while( (pEntry = csrLLRemoveHead(&localList, LL_ACCESS_NOLOCK)) )
{
pCommand = GET_BASE_ADDR( pEntry, tSmeCmd, Link );
smeAbortCommand(pMac, pCommand, eANI_BOOLEAN_TRUE);
}
csrLLClose(&localList);
}
static eHalStatus freeSmeCmdList(tpAniSirGlobal pMac)
{
eHalStatus status = eHAL_STATUS_SUCCESS;
purgeSmeCmdList(pMac);
csrLLClose(&pMac->sme.smeCmdPendingList);
csrLLClose(&pMac->sme.smeCmdActiveList);
csrLLClose(&pMac->sme.smeScanCmdPendingList);
csrLLClose(&pMac->sme.smeScanCmdActiveList);
csrLLClose(&pMac->sme.smeCmdFreeList);
/*destroy active list command time out timer */
vos_timer_destroy(pMac->sme.smeCmdActiveList.cmdTimeoutTimer);
vos_mem_free(pMac->sme.smeCmdActiveList.cmdTimeoutTimer);
pMac->sme.smeCmdActiveList.cmdTimeoutTimer = NULL;
status = vos_lock_acquire(&pMac->sme.lkSmeGlobalLock);
if(status != eHAL_STATUS_SUCCESS)
{
smsLog(pMac, LOGE,
FL("Failed to acquire the lock status = %d"), status);
goto done;
}
free_sme_cmds(pMac);
status = vos_lock_release(&pMac->sme.lkSmeGlobalLock);
if(status != eHAL_STATUS_SUCCESS)
{
smsLog(pMac, LOGE,
FL("Failed to release the lock status = %d"), status);
}
done:
return (status);
}
void dumpCsrCommandInfo(tpAniSirGlobal pMac, tSmeCmd *pCmd)
{
switch( pCmd->command )
{
case eSmeCommandScan:
smsLog( pMac, LOGE, " scan command reason is %d", pCmd->u.scanCmd.reason );
break;
case eSmeCommandRoam:
smsLog( pMac, LOGE, " roam command reason is %d", pCmd->u.roamCmd.roamReason );
break;
case eSmeCommandWmStatusChange:
smsLog( pMac, LOGE, " WMStatusChange command type is %d", pCmd->u.wmStatusChangeCmd.Type );
break;
case eSmeCommandSetKey:
smsLog( pMac, LOGE, " setKey command auth(%d) enc(%d)",
pCmd->u.setKeyCmd.authType, pCmd->u.setKeyCmd.encType );
break;
case eSmeCommandRemoveKey:
smsLog( pMac, LOGE, " removeKey command auth(%d) enc(%d)",
pCmd->u.removeKeyCmd.authType, pCmd->u.removeKeyCmd.encType );
break;
default:
smsLog( pMac, LOGE, " default: Unhandled command %d",
pCmd->command);
break;
}
}
tSmeCmd *smeGetCommandBuffer( tpAniSirGlobal pMac )
{
tSmeCmd *pRetCmd = NULL, *pTempCmd = NULL;
tListElem *pEntry;
static int smeCommandQueueFull = 0;
pEntry = csrLLRemoveHead( &pMac->sme.smeCmdFreeList, LL_ACCESS_LOCK );
/*
* If we can get another MS Msg buffer, then we are ok. Just link
* the entry onto the linked list. (We are using the linked list
* to keep track of the message buffers).
*/
if ( pEntry )
{
pRetCmd = GET_BASE_ADDR( pEntry, tSmeCmd, Link );
/* reset when free list is available */
smeCommandQueueFull = 0;
}
else
{
int idx = 1;
//Cannot change pRetCmd here since it needs to return later.
pEntry = csrLLPeekHead( &pMac->sme.smeCmdActiveList, LL_ACCESS_LOCK );
if( pEntry )
{
pTempCmd = GET_BASE_ADDR( pEntry, tSmeCmd, Link );
}
smsLog( pMac, LOGE, "Out of command buffer.... command (0x%X) stuck",
(pTempCmd) ? pTempCmd->command : eSmeNoCommand );
if(pTempCmd)
{
if( eSmeCsrCommandMask & pTempCmd->command )
{
//CSR command is stuck. See what the reason code is for that command
dumpCsrCommandInfo(pMac, pTempCmd);
}
} //if(pTempCmd)
//dump what is in the pending queue
csrLLLock(&pMac->sme.smeCmdPendingList);
pEntry = csrLLPeekHead( &pMac->sme.smeCmdPendingList, LL_ACCESS_NOLOCK );
while(pEntry && !smeCommandQueueFull)
{
pTempCmd = GET_BASE_ADDR( pEntry, tSmeCmd, Link );
/* Print only 1st five commands from pending queue. */
if (idx <= 5)
smsLog( pMac, LOGE, "Out of command buffer.... SME pending command #%d (0x%X)",
idx, pTempCmd->command );
idx++;
if( eSmeCsrCommandMask & pTempCmd->command )
{
//CSR command is stuck. See what the reason code is for that command
dumpCsrCommandInfo(pMac, pTempCmd);
}
pEntry = csrLLNext( &pMac->sme.smeCmdPendingList, pEntry, LL_ACCESS_NOLOCK );
}
csrLLUnlock(&pMac->sme.smeCmdPendingList);
idx = 1;
//There may be some more command in CSR's own pending queue
csrLLLock(&pMac->roam.roamCmdPendingList);
pEntry = csrLLPeekHead( &pMac->roam.roamCmdPendingList, LL_ACCESS_NOLOCK );
while(pEntry && !smeCommandQueueFull)
{
pTempCmd = GET_BASE_ADDR( pEntry, tSmeCmd, Link );
/* Print only 1st five commands from CSR pending queue */
if (idx <= 5)
smsLog( pMac, LOGE,
"Out of command buffer.... CSR roamCmdPendingList command #%d (0x%X)",
idx, pTempCmd->command );
idx++;
dumpCsrCommandInfo(pMac, pTempCmd);
pEntry = csrLLNext( &pMac->roam.roamCmdPendingList, pEntry, LL_ACCESS_NOLOCK );
}
/* Increament static variable so that it prints pending command only once*/
smeCommandQueueFull++;
csrLLUnlock(&pMac->roam.roamCmdPendingList);
/* panic with out-of-command */
if (pMac->roam.configParam.enable_fatal_event) {
vos_flush_logs(WLAN_LOG_TYPE_FATAL,
WLAN_LOG_INDICATOR_HOST_DRIVER,
WLAN_LOG_REASON_SME_OUT_OF_CMD_BUF,
DUMP_NO_TRACE);
} else {
/* Trigger SSR */
vos_wlanRestart();
}
}
/* memset to zero */
if (pRetCmd) {
vos_mem_set((tANI_U8 *)&pRetCmd->command, sizeof(pRetCmd->command), 0);
vos_mem_set((tANI_U8 *)&pRetCmd->sessionId,
sizeof(pRetCmd->sessionId), 0);
vos_mem_set((tANI_U8 *)&pRetCmd->u, sizeof(pRetCmd->u), 0);
}
return(pRetCmd);
}
void smePushCommand( tpAniSirGlobal pMac, tSmeCmd *pCmd, tANI_BOOLEAN fHighPriority )
{
if (!SME_IS_START(pMac)) {
smsLog(pMac, LOGE, FL("Sme in stop state"));
return;
}
if ( fHighPriority )
{
csrLLInsertHead( &pMac->sme.smeCmdPendingList, &pCmd->Link, LL_ACCESS_LOCK );
}
else
{
csrLLInsertTail( &pMac->sme.smeCmdPendingList, &pCmd->Link, LL_ACCESS_LOCK );
}
// process the command queue...
smeProcessPendingQueue( pMac );
return;
}
static eSmeCommandType smeIsFullPowerNeeded( tpAniSirGlobal pMac, tSmeCmd *pCommand )
{
eSmeCommandType pmcCommand = eSmeNoCommand;
tANI_BOOLEAN fFullPowerNeeded = eANI_BOOLEAN_FALSE;
tPmcState pmcState;
eHalStatus status;
do
{
pmcState = pmcGetPmcState(pMac);
status = csrIsFullPowerNeeded( pMac, pCommand, NULL, &fFullPowerNeeded );
if( !HAL_STATUS_SUCCESS(status) )
{
//PMC state is not right for the command, drop it
return ( eSmeDropCommand );
}
if( fFullPowerNeeded ) break;
fFullPowerNeeded = ( ( eSmeCommandAddTs == pCommand->command ) ||
( eSmeCommandDelTs == pCommand->command ) );
if( fFullPowerNeeded ) break;
#ifdef FEATURE_OEM_DATA_SUPPORT
fFullPowerNeeded = (pmcState == IMPS &&
eSmeCommandOemDataReq == pCommand->command);
if(fFullPowerNeeded) break;
#endif
fFullPowerNeeded = (pmcState == IMPS &&
eSmeCommandRemainOnChannel == pCommand->command);
if(fFullPowerNeeded) break;
} while(0);
if( fFullPowerNeeded )
{
switch( pmcState )
{
case IMPS:
case STANDBY:
pmcCommand = eSmeCommandExitImps;
break;
case BMPS:
pmcCommand = eSmeCommandExitBmps;
break;
case UAPSD:
pmcCommand = eSmeCommandExitUapsd;
break;
case WOWL:
pmcCommand = eSmeCommandExitWowl;
break;
default:
break;
}
}
return ( pmcCommand );
}
static eSmeCommandType smePsOffloadIsFullPowerNeeded(tpAniSirGlobal pMac,
tSmeCmd *pCommand)
{
eSmeCommandType pmcCommand = eSmeNoCommand;
tANI_BOOLEAN fFullPowerNeeded = eANI_BOOLEAN_FALSE;
eHalStatus status;
tPmcState pmcState;
do
{
/* Check for CSR Commands which require full power */
status = csrPsOffloadIsFullPowerNeeded(pMac, pCommand, NULL,
&fFullPowerNeeded);
if(!HAL_STATUS_SUCCESS(status))
{
/* PMC state is not right for the command, drop it */
return eSmeDropCommand;
}
if(fFullPowerNeeded) break;
/* Check for SME Commands which require Full Power */
if((eSmeCommandAddTs == pCommand->command) ||
((eSmeCommandDelTs == pCommand->command)))
{
/* Get the PMC State */
pmcState = pmcOffloadGetPmcState(pMac, pCommand->sessionId);
switch(pmcState)
{
case REQUEST_BMPS:
case BMPS:
case REQUEST_START_UAPSD:
case REQUEST_STOP_UAPSD:
case UAPSD:
fFullPowerNeeded = eANI_BOOLEAN_TRUE;
break;
case STOPPED:
break;
default:
break;
}
break;
}
} while(0);
if(fFullPowerNeeded)
{
pmcCommand = eSmeCommandExitBmps;
}
return pmcCommand;
}
//For commands that need to do extra cleanup.
static void smeAbortCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand, tANI_BOOLEAN fStopping )
{
if( eSmePmcCommandMask & pCommand->command )
{
if(!pMac->psOffloadEnabled)
pmcAbortCommand( pMac, pCommand, fStopping );
else
pmcOffloadAbortCommand(pMac, pCommand, fStopping);
}
else if ( eSmeCsrCommandMask & pCommand->command )
{
csrAbortCommand( pMac, pCommand, fStopping );
}
else
{
switch( pCommand->command )
{
case eSmeCommandRemainOnChannel:
if (NULL != pCommand->u.remainChlCmd.callback)
{
remainOnChanCallback callback =
pCommand->u.remainChlCmd.callback;
/* process the msg */
if( callback )
{
callback(pMac, pCommand->u.remainChlCmd.callbackCtx,
eCSR_SCAN_ABORT );
}
}
smeReleaseCommand( pMac, pCommand );
break;
default:
smeReleaseCommand( pMac, pCommand );
break;
}
}
}
tListElem *csrGetCmdToProcess(tpAniSirGlobal pMac, tDblLinkList *pList,
tANI_U8 sessionId, tANI_BOOLEAN fInterlocked)
{
tListElem *pCurEntry = NULL;
tSmeCmd *pCommand;
/* Go through the list and return the command whose session id is not
* matching with the current ongoing scan cmd sessionId */
pCurEntry = csrLLPeekHead( pList, LL_ACCESS_LOCK );
while (pCurEntry)
{
pCommand = GET_BASE_ADDR(pCurEntry, tSmeCmd, Link);
if (pCommand->sessionId != sessionId)
{
smsLog(pMac, LOG1, "selected the command with different sessionId");
return pCurEntry;
}
pCurEntry = csrLLNext(pList, pCurEntry, fInterlocked);
}
smsLog(pMac, LOG1, "No command pending with different sessionId");
return NULL;
}
tANI_BOOLEAN smeProcessScanQueue(tpAniSirGlobal pMac)
{
tListElem *pEntry;
tSmeCmd *pCommand;
tListElem *pSmeEntry = NULL;
tSmeCmd *pSmeCommand = NULL;
tANI_BOOLEAN status = eANI_BOOLEAN_TRUE;
if ((!csrLLIsListEmpty(&pMac->sme.smeCmdActiveList, LL_ACCESS_LOCK ))) {
pSmeEntry = csrLLPeekHead(&pMac->sme.smeCmdActiveList,
LL_ACCESS_LOCK);
if (pSmeEntry)
pSmeCommand = GET_BASE_ADDR(pSmeEntry, tSmeCmd, Link) ;
}
csrLLLock( &pMac->sme.smeScanCmdActiveList );
if (csrLLIsListEmpty( &pMac->sme.smeScanCmdActiveList,
LL_ACCESS_NOLOCK ))
{
if (!csrLLIsListEmpty(&pMac->sme.smeScanCmdPendingList,
LL_ACCESS_LOCK))
{
pEntry = csrLLPeekHead( &pMac->sme.smeScanCmdPendingList,
LL_ACCESS_LOCK );
if (pEntry) {
pCommand = GET_BASE_ADDR( pEntry, tSmeCmd, Link );
if (pSmeCommand != NULL) {
/* if there is an active SME command, do not process
* the pending scan cmd
*/
smsLog(pMac, LOG1, "SME scan cmd is pending on session %d",
pSmeCommand->sessionId);
status = eANI_BOOLEAN_FALSE;
goto end;
}
//We cannot execute any command in wait-for-key state until setKey is through.
if (CSR_IS_WAIT_FOR_KEY( pMac, pCommand->sessionId))
{
if (!CSR_IS_SET_KEY_COMMAND(pCommand))
{
smsLog(pMac, LOGE,
" Cannot process command(%d) while waiting for key",
pCommand->command);
status = eANI_BOOLEAN_FALSE;
goto end;
}
}
if ( csrLLRemoveEntry( &pMac->sme.smeScanCmdPendingList,
pEntry, LL_ACCESS_LOCK ) )
{
csrLLInsertHead( &pMac->sme.smeScanCmdActiveList,
&pCommand->Link, LL_ACCESS_NOLOCK );
switch (pCommand->command)
{
case eSmeCommandScan:
smsLog(pMac, LOG1,
" Processing scan offload command ");
csrProcessScanCommand( pMac, pCommand );
break;
case eSmeCommandRemainOnChannel:
smsLog(pMac, LOG1,
"Processing req remain on channel offload"
" command");
p2pProcessRemainOnChannelCmd(pMac, pCommand);
break;
default:
smsLog(pMac, LOGE,
" Something wrong, wrong command enqueued"
" to smeScanCmdPendingList");
pEntry = csrLLRemoveHead(
&pMac->sme.smeScanCmdActiveList,
LL_ACCESS_NOLOCK );
pCommand = GET_BASE_ADDR( pEntry, tSmeCmd, Link );
smeReleaseCommand( pMac, pCommand );
break;
}
}
}
}
}
end:
csrLLUnlock(&pMac->sme.smeScanCmdActiveList);
return status;
}
tANI_BOOLEAN smeProcessCommand( tpAniSirGlobal pMac )
{
tANI_BOOLEAN fContinue = eANI_BOOLEAN_FALSE;
eHalStatus status = eHAL_STATUS_SUCCESS;
tListElem *pEntry;
tSmeCmd *pCommand;
tListElem *pSmeEntry;
tSmeCmd *pSmeCommand;
eSmeCommandType pmcCommand = eSmeNoCommand;
/*
* If the ActiveList is empty, then nothing is active so we can process a
* pending command.
* Always lock active list before locking pending list.
*/
csrLLLock( &pMac->sme.smeCmdActiveList );
if ( csrLLIsListEmpty( &pMac->sme.smeCmdActiveList, LL_ACCESS_NOLOCK ) )
{
if(!csrLLIsListEmpty(&pMac->sme.smeCmdPendingList, LL_ACCESS_LOCK))
{
/* If scan command is pending in the smeScanCmdActive list
* then pick the command from smeCmdPendingList which is
* not matching with the scan command session id.
* At any point of time only one command will be allowed
* on a single session. */
if ((pMac->fScanOffload) &&
(!csrLLIsListEmpty(&pMac->sme.smeScanCmdActiveList,
LL_ACCESS_LOCK)))
{
pSmeEntry = csrLLPeekHead(&pMac->sme.smeScanCmdActiveList,
LL_ACCESS_LOCK);
if (pSmeEntry)
{
pSmeCommand = GET_BASE_ADDR(pSmeEntry, tSmeCmd, Link);
pEntry = csrGetCmdToProcess(pMac,
&pMac->sme.smeCmdPendingList,
pSmeCommand->sessionId,
LL_ACCESS_LOCK);
goto sme_process_cmd;
}
}
//Peek the command
pEntry = csrLLPeekHead( &pMac->sme.smeCmdPendingList, LL_ACCESS_LOCK );
sme_process_cmd:
if( pEntry )
{
pCommand = GET_BASE_ADDR( pEntry, tSmeCmd, Link );
/* Allow only disconnect command
* in wait-for-key state until setKey is through.
*/
if( CSR_IS_WAIT_FOR_KEY( pMac, pCommand->sessionId ) &&
!CSR_IS_DISCONNECT_COMMAND( pCommand ) )
{
if (CSR_IS_CLOSE_SESSION_COMMAND(pCommand)) {
tSmeCmd *sme_cmd = NULL;
smsLog(pMac, LOGE,
FL("SessionId %d: close session command issued while waiting for key, issue disconnect first"),
pCommand->sessionId);
status = csr_prepare_disconnect_command(pMac,
pCommand->sessionId, &sme_cmd);
if (HAL_STATUS_SUCCESS(status) && sme_cmd) {
csrLLLock(&pMac->sme.smeCmdPendingList);
csrLLInsertHead(&pMac->sme.smeCmdPendingList,
&sme_cmd->Link, LL_ACCESS_NOLOCK);
pEntry = csrLLPeekHead(&pMac->sme.smeCmdPendingList,
LL_ACCESS_NOLOCK);
csrLLUnlock(&pMac->sme.smeCmdPendingList);
goto sme_process_cmd;
}
}
if( !CSR_IS_SET_KEY_COMMAND( pCommand ) )
{
csrLLUnlock( &pMac->sme.smeCmdActiveList );
smsLog(pMac, LOGE, FL("SessionId %d: Cannot process "
"command(%d) while waiting for key"),
pCommand->sessionId, pCommand->command);
fContinue = eANI_BOOLEAN_FALSE;
goto sme_process_scan_queue;
}
}
if(pMac->psOffloadEnabled)
pmcCommand = smePsOffloadIsFullPowerNeeded(pMac, pCommand);
else
pmcCommand = smeIsFullPowerNeeded( pMac, pCommand );
if( eSmeDropCommand == pmcCommand )
{
csrLLUnlock(&pMac->sme.smeCmdActiveList);
//This command is not ok for current PMC state
if( csrLLRemoveEntry( &pMac->sme.smeCmdPendingList, pEntry, LL_ACCESS_LOCK ) )
{
smeAbortCommand( pMac, pCommand, eANI_BOOLEAN_FALSE );
}
//tell caller to continue
fContinue = eANI_BOOLEAN_TRUE;
goto sme_process_scan_queue;
}
else if( eSmeNoCommand != pmcCommand )
{
tExitBmpsInfo exitBmpsInfo;
void *pv = NULL;
tANI_U32 size = 0;
tSmeCmd *pPmcCmd = NULL;
if( eSmeCommandExitBmps == pmcCommand )
{
exitBmpsInfo.exitBmpsReason = eSME_REASON_OTHER;
pv = (void *)&exitBmpsInfo;
size = sizeof(tExitBmpsInfo);
}
//pmcCommand has to be one of the exit power save command
status = pmcPrepareCommand(pMac, pCommand->sessionId,
pmcCommand, pv, size,
&pPmcCmd);
if( HAL_STATUS_SUCCESS( status ) && pPmcCmd )
{
//Force this command to wake up the chip
csrLLInsertHead( &pMac->sme.smeCmdActiveList, &pPmcCmd->Link, LL_ACCESS_NOLOCK );
MTRACE(vos_trace(VOS_MODULE_ID_SME,
TRACE_CODE_SME_COMMAND, pPmcCmd->sessionId, pPmcCmd->command));
csrLLUnlock( &pMac->sme.smeCmdActiveList );
/* Handle PS Offload Case Separately */
if(pMac->psOffloadEnabled)
{
fContinue = pmcOffloadProcessCommand(pMac, pPmcCmd);
}
else
{
fContinue = pmcProcessCommand( pMac, pPmcCmd );
}
if( fContinue )
{
//The command failed, remove it
if( csrLLRemoveEntry( &pMac->sme.smeCmdActiveList, &pPmcCmd->Link, LL_ACCESS_NOLOCK ) )
{
pmcReleaseCommand( pMac, pPmcCmd );
}
}
}
else
{
csrLLUnlock( &pMac->sme.smeCmdActiveList );
smsLog( pMac, LOGE, FL( "Cannot issue command(0x%X) to wake up the chip. Status = %d"), pmcCommand, status );
//Let it retry
fContinue = eANI_BOOLEAN_TRUE;
}
goto sme_process_scan_queue;
}
if ( csrLLRemoveEntry( &pMac->sme.smeCmdPendingList, pEntry, LL_ACCESS_LOCK ) )
{
// we can reuse the pCommand
// Insert the command onto the ActiveList...
csrLLInsertHead( &pMac->sme.smeCmdActiveList, &pCommand->Link, LL_ACCESS_NOLOCK );
// .... and process the command.
MTRACE(vos_trace(VOS_MODULE_ID_SME,
TRACE_CODE_SME_COMMAND, pCommand->sessionId, pCommand->command));
switch ( pCommand->command )
{
case eSmeCommandScan:
csrLLUnlock( &pMac->sme.smeCmdActiveList );
status = csrProcessScanCommand( pMac, pCommand );
break;
case eSmeCommandRoam:
csrLLUnlock( &pMac->sme.smeCmdActiveList );
status = csrRoamProcessCommand( pMac, pCommand );
if(!HAL_STATUS_SUCCESS(status))
{
if( csrLLRemoveEntry( &pMac->sme.smeCmdActiveList,
&pCommand->Link, LL_ACCESS_LOCK ) )
{
csrReleaseCommandRoam( pMac, pCommand );
}
}
break;
case eSmeCommandWmStatusChange:
csrLLUnlock( &pMac->sme.smeCmdActiveList );
csrRoamProcessWmStatusChangeCommand(pMac, pCommand);
fContinue = eANI_BOOLEAN_TRUE;
break;
case eSmeCommandSetKey:
csrLLUnlock( &pMac->sme.smeCmdActiveList );
status = csrRoamProcessSetKeyCommand( pMac, pCommand );
if(!HAL_STATUS_SUCCESS(status))
{
if( csrLLRemoveEntry( &pMac->sme.smeCmdActiveList,
&pCommand->Link, LL_ACCESS_LOCK ) )
{
csrReleaseCommandSetKey( pMac, pCommand );
}
}
break;
case eSmeCommandRemoveKey:
csrLLUnlock( &pMac->sme.smeCmdActiveList );
status = csrRoamProcessRemoveKeyCommand( pMac, pCommand );
if(!HAL_STATUS_SUCCESS(status))
{
if( csrLLRemoveEntry( &pMac->sme.smeCmdActiveList,
&pCommand->Link, LL_ACCESS_LOCK ) )
{
csrReleaseCommandRemoveKey( pMac, pCommand );
}
}
break;
case eSmeCommandAddStaSession:
csrLLUnlock( &pMac->sme.smeCmdActiveList );
csrProcessAddStaSessionCommand( pMac, pCommand );
break;
case eSmeCommandNdpInitiatorRequest:
csrLLUnlock(&pMac->sme.smeCmdActiveList);
if (csr_process_ndp_initiator_request(pMac,
pCommand) != eHAL_STATUS_SUCCESS) {
if (csrLLRemoveEntry(
&pMac->sme.smeCmdActiveList,
&pCommand->Link, LL_ACCESS_LOCK)) {
csrReleaseCommand(pMac, pCommand);
}
}
break;
case eSmeCommandNdpResponderRequest:
csrLLUnlock(&pMac->sme.smeCmdActiveList);
status =
csr_process_ndp_responder_request(pMac,
pCommand);
if (!HAL_STATUS_SUCCESS(status)) {
if (csrLLRemoveEntry(
&pMac->sme.smeCmdActiveList,
&pCommand->Link, LL_ACCESS_LOCK))
csrReleaseCommand(pMac, pCommand);
}
break;
case eSmeCommandNdpDataEndInitiatorRequest:
csrLLUnlock(&pMac->sme.smeCmdActiveList);
status = csr_process_ndp_data_end_request(pMac,
pCommand);
if (!HAL_STATUS_SUCCESS(status)) {
if (csrLLRemoveEntry(
&pMac->sme.smeCmdActiveList,
&pCommand->Link, LL_ACCESS_LOCK))
csrReleaseCommand(pMac, pCommand);
}
break;
case eSmeCommandDelStaSession:
csrLLUnlock( &pMac->sme.smeCmdActiveList );
csrProcessDelStaSessionCommand( pMac, pCommand );
break;
case eSmeCommandSetMaxTxPower:
csrLLUnlock(&pMac->sme.smeCmdActiveList);
sme_process_set_max_tx_power(pMac, pCommand);
/* We need to re-run the command */
fContinue = eANI_BOOLEAN_TRUE;
/* No Rsp expected, free cmd from active list */
if(csrLLRemoveEntry(&pMac->sme.smeCmdActiveList,
&pCommand->Link, LL_ACCESS_LOCK)) {
csrReleaseCommand(pMac, pCommand);
}
pMac->max_power_cmd_pending = false;
break;
case eSmeCommandSetMaxTxPowerPerBand:
csrLLUnlock(&pMac->sme.smeCmdActiveList);
sme_process_set_max_tx_power_per_band(pMac,
pCommand);
/* We need to re-run the command */
fContinue = eANI_BOOLEAN_TRUE;
/* No Rsp expected, free cmd from active list */
if (csrLLRemoveEntry(&pMac->sme.smeCmdActiveList,
&pCommand->Link, LL_ACCESS_LOCK)) {
csrReleaseCommand(pMac, pCommand);
}
pMac->max_power_cmd_pending = false;
break;
#ifdef FEATURE_OEM_DATA_SUPPORT
case eSmeCommandOemDataReq:
csrLLUnlock(&pMac->sme.smeCmdActiveList);
oemData_ProcessOemDataReqCommand(pMac, pCommand);
break;
#endif
case eSmeCommandRemainOnChannel:
csrLLUnlock(&pMac->sme.smeCmdActiveList);
p2pProcessRemainOnChannelCmd(pMac, pCommand);
break;
case eSmeCommandNoAUpdate:
csrLLUnlock( &pMac->sme.smeCmdActiveList );
p2pProcessNoAReq(pMac,pCommand);
break;
case eSmeCommandEnterImps:
case eSmeCommandExitImps:
case eSmeCommandEnterBmps:
case eSmeCommandExitBmps:
case eSmeCommandEnterUapsd:
case eSmeCommandExitUapsd:
case eSmeCommandEnterWowl:
case eSmeCommandExitWowl:
csrLLUnlock( &pMac->sme.smeCmdActiveList );
if(pMac->psOffloadEnabled)
{
fContinue =
pmcOffloadProcessCommand(pMac, pCommand);
}
else
{
fContinue = pmcProcessCommand(pMac, pCommand);
}
if( fContinue )
{
//The command failed, remove it
if( csrLLRemoveEntry( &pMac->sme.smeCmdActiveList,
&pCommand->Link, LL_ACCESS_LOCK ) )
{
pmcReleaseCommand( pMac, pCommand );
}
}
break;
//Treat standby differently here because caller may not be able to handle
//the failure so we do our best here
case eSmeCommandEnterStandby:
if( csrIsConnStateDisconnected( pMac, pCommand->sessionId ) )
{
//It can continue
csrLLUnlock( &pMac->sme.smeCmdActiveList );
if(pMac->psOffloadEnabled)
{
fContinue =
pmcOffloadProcessCommand(pMac, pCommand);
}
else
{
fContinue =
pmcProcessCommand(pMac, pCommand);
}
if( fContinue )
{
//The command failed, remove it
if( csrLLRemoveEntry( &pMac->sme.smeCmdActiveList,
&pCommand->Link, LL_ACCESS_LOCK ) )
{
pmcReleaseCommand( pMac, pCommand );
}
}
}
else
{
//Need to issue a disconnect first before processing this command
tSmeCmd *pNewCmd;
//We need to re-run the command
fContinue = eANI_BOOLEAN_TRUE;
//Pull off the standby command first
if( csrLLRemoveEntry( &pMac->sme.smeCmdActiveList,
&pCommand->Link, LL_ACCESS_NOLOCK ) )
{
csrLLUnlock( &pMac->sme.smeCmdActiveList );
//Need to call CSR function here because the disconnect command
//is handled by CSR
pNewCmd = csrGetCommandBuffer( pMac );
if( NULL != pNewCmd )
{
//Put the standby command to the head of the pending list first
csrLLInsertHead( &pMac->sme.smeCmdPendingList, &pCommand->Link,
LL_ACCESS_LOCK );
pNewCmd->command = eSmeCommandRoam;
pNewCmd->u.roamCmd.roamReason = eCsrForcedDisassoc;
//Put the disassoc command before the standby command
csrLLInsertHead( &pMac->sme.smeCmdPendingList, &pNewCmd->Link,
LL_ACCESS_LOCK );
}
else
{
//Continue the command here
if(pMac->psOffloadEnabled)
{
fContinue =
pmcOffloadProcessCommand(pMac,
pCommand);
}
else
{
fContinue = pmcProcessCommand(pMac,
pCommand);
}
if( fContinue )
{
//The command failed, remove it
if( csrLLRemoveEntry( &pMac->sme.smeCmdActiveList,
&pCommand->Link, LL_ACCESS_LOCK ) )
{
pmcReleaseCommand( pMac, pCommand );
}
}
}
}
else
{
csrLLUnlock( &pMac->sme.smeCmdActiveList );
smsLog( pMac, LOGE, FL(" failed to remove standby command") );
VOS_ASSERT(0);
}
}
break;
case eSmeCommandAddTs:
case eSmeCommandDelTs:
csrLLUnlock( &pMac->sme.smeCmdActiveList );
#ifndef WLAN_MDM_CODE_REDUCTION_OPT
fContinue = qosProcessCommand( pMac, pCommand );
if( fContinue )
{
//The command failed, remove it
if( csrLLRemoveEntry( &pMac->sme.smeCmdActiveList,
&pCommand->Link, LL_ACCESS_NOLOCK ) )
{
//#ifndef WLAN_MDM_CODE_REDUCTION_OPT
qosReleaseCommand( pMac, pCommand );
//#endif /* WLAN_MDM_CODE_REDUCTION_OPT*/
}
}
#endif
break;
#ifdef FEATURE_WLAN_TDLS
case eSmeCommandTdlsSendMgmt:
case eSmeCommandTdlsAddPeer:
case eSmeCommandTdlsDelPeer:
case eSmeCommandTdlsLinkEstablish:
{
VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO,
"sending TDLS Command 0x%x to PE", pCommand->command);
csrLLUnlock(&pMac->sme.smeCmdActiveList);
status = csrTdlsProcessCmd(pMac, pCommand);
if (!HAL_STATUS_SUCCESS(status)) {
if (csrLLRemoveEntry(&pMac->sme.smeCmdActiveList,
&pCommand->Link,
LL_ACCESS_LOCK)) {
vos_mem_zero(&pCommand->u.tdlsCmd,
sizeof(tTdlsCmd));
csrReleaseCommand(pMac, pCommand);
}
}
}
break ;
#endif
default:
//something is wrong
//remove it from the active list
smsLog(pMac, LOGE, " csrProcessCommand processes an unknown command %d", pCommand->command);
pEntry = csrLLRemoveHead( &pMac->sme.smeCmdActiveList, LL_ACCESS_NOLOCK );
csrLLUnlock( &pMac->sme.smeCmdActiveList );
pCommand = GET_BASE_ADDR( pEntry, tSmeCmd, Link );
smeReleaseCommand( pMac, pCommand );
status = eHAL_STATUS_FAILURE;
break;
}
if(!HAL_STATUS_SUCCESS(status))
{
fContinue = eANI_BOOLEAN_TRUE;
}
}//if(pEntry)
else
{
//This is odd. Some one else pull off the command.
csrLLUnlock( &pMac->sme.smeCmdActiveList );
VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO,
"Remove entry failed");
}
}
else
{
csrLLUnlock( &pMac->sme.smeCmdActiveList );
VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO,
"Get Pending command failed");
}
}
else
{
//No command waiting
csrLLUnlock( &pMac->sme.smeCmdActiveList );
/*
* This is only used to restart an idle mode scan,
* it means at least one other idle scan has finished.
* Moreover Idle Scan is not supported with power
* save offload supported
*/
if(!pMac->psOffloadEnabled &&
pMac->scan.fRestartIdleScan &&
eANI_BOOLEAN_FALSE == pMac->scan.fCancelIdleScan)
{
tANI_U32 nTime = 0;
pMac->scan.fRestartIdleScan = eANI_BOOLEAN_FALSE;
if(!HAL_STATUS_SUCCESS(csrScanTriggerIdleScan(pMac, &nTime)))
{
csrScanStartIdleScanTimer(pMac, nTime);
}
}
}
}
else {
csrLLUnlock( &pMac->sme.smeCmdActiveList );
}
sme_process_scan_queue:
if (pMac->fScanOffload && !(smeProcessScanQueue(pMac)))
fContinue = eANI_BOOLEAN_FALSE;
return ( fContinue );
}
void smeProcessPendingQueue( tpAniSirGlobal pMac )
{
while( smeProcessCommand( pMac ) );
}
tANI_BOOLEAN smeCommandPending(tpAniSirGlobal pMac)
{
return ( !csrLLIsListEmpty( &pMac->sme.smeCmdActiveList, LL_ACCESS_NOLOCK ) ||
!csrLLIsListEmpty(&pMac->sme.smeCmdPendingList, LL_ACCESS_NOLOCK) );
}
/**
* sme_get_sessionid_from_activelist() - gets session id
* @mac: mac context
*
* This function is used to get session id from sme command
* active list
*
* Return: returns session id
*/
uint32_t sme_get_sessionid_from_activelist(tpAniSirGlobal mac)
{
tListElem *entry;
tSmeCmd *command;
uint32_t session_id = 0;
entry = csrLLPeekHead(&mac->sme.smeCmdActiveList, LL_ACCESS_LOCK);
if (entry) {
command = GET_BASE_ADDR(entry, tSmeCmd, Link);
session_id = command->sessionId;
}
return session_id;
}
/**
* sme_state_info_dump() - prints state information of sme layer
* @buf: buffer pointer
* @size: size of buffer to be filled
*
* This function is used to dump state information of sme layer
*
* Return: None
*/
static void sme_state_info_dump(char **buf_ptr, uint16_t *size)
{
uint32_t session_id;
tHalHandle hal;
tpAniSirGlobal mac;
v_CONTEXT_t vos_ctx_ptr;
uint16_t len = 0;
char *buf = *buf_ptr;
/* get the global voss context */
vos_ctx_ptr = vos_get_global_context(VOS_MODULE_ID_VOSS, NULL);
if (NULL == vos_ctx_ptr) {
VOS_ASSERT(0);
return;
}
hal = vos_get_context(VOS_MODULE_ID_SME, vos_ctx_ptr);
if (NULL == hal) {
VOS_ASSERT(0);
return;
}
mac = PMAC_STRUCT(hal);
smsLog(mac, LOG1, FL("size of buffer: %d"), *size);
session_id = sme_get_sessionid_from_activelist(mac);
len += vos_scnprintf(buf + len, *size - len,
"\n active command sessionid %d", session_id);
len += vos_scnprintf(buf + len, *size - len,
"\n NeighborRoamState: %d",
mac->roam.neighborRoamInfo[session_id].neighborRoamState);
len += vos_scnprintf(buf + len, *size - len,
"\n RoamState: %d", mac->roam.curState[session_id]);
len += vos_scnprintf(buf + len, *size - len,
"\n RoamSubState: %d", mac->roam.curSubState[session_id]);
len += vos_scnprintf(buf + len, *size - len,
"\n ConnectState: %d",
mac->roam.roamSession[session_id].connectState);
len += vos_scnprintf(buf + len, *size - len,
"\n pmcState: %d", mac->pmc.pmcState);
len += vos_scnprintf(buf + len, *size - len,
"\n PmmState: %d", mac->pmm.gPmmState);
*size -= len;
*buf_ptr += len;
}
/**
* sme_register_debug_callback() - registration function sme layer
* to print sme state information
*
* Return: None
*/
static void sme_register_debug_callback(void)
{
vos_register_debug_callback(VOS_MODULE_ID_SME, &sme_state_info_dump);
}
//Global APIs
/*--------------------------------------------------------------------------
\brief sme_Open() - Initialize all SME modules and put them at idle state
The function initializes each module inside SME, PMC, CCM, CSR, etc. . Upon
successfully return, all modules are at idle state ready to start.
smeOpen must be called before any other SME APIs can be involved.
smeOpen must be called after macOpen.
This is a synchronous call
\param hHal - The handle returned by macOpen.
\return eHAL_STATUS_SUCCESS - SME is successfully initialized.
Other status means SME is failed to be initialized
\sa
--------------------------------------------------------------------------*/
eHalStatus sme_Open(tHalHandle hHal)
{
eHalStatus status = eHAL_STATUS_FAILURE;
tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
do {
pMac->sme.state = SME_STATE_STOP;
pMac->sme.currDeviceMode = VOS_STA_MODE;
if( !VOS_IS_STATUS_SUCCESS( vos_lock_init( &pMac->sme.lkSmeGlobalLock ) ) )
{
smsLog( pMac, LOGE, "sme_Open failed init lock" );
status = eHAL_STATUS_FAILURE;
break;
}
status = ccmOpen(hHal);
if ( ! HAL_STATUS_SUCCESS( status ) ) {
smsLog( pMac, LOGE,
"ccmOpen failed during initialization with status=%d", status );
break;
}
status = csrOpen(pMac);
if ( ! HAL_STATUS_SUCCESS( status ) ) {
smsLog( pMac, LOGE,
"csrOpen failed during initialization with status=%d", status );
break;
}
if(!pMac->psOffloadEnabled)
{
status = pmcOpen(hHal);
if ( ! HAL_STATUS_SUCCESS( status ) ) {
smsLog( pMac, LOGE,
"pmcOpen failed during initialization with status=%d",
status );
break;
}
}
else
{
status = pmcOffloadOpen(hHal);
if (! HAL_STATUS_SUCCESS(status)) {
smsLog( pMac, LOGE,
"pmcOffloadOpen failed during initialization with status=%d",
status );
break;
}
}
#ifdef FEATURE_WLAN_TDLS
pMac->isTdlsPowerSaveProhibited = 0;
#endif
#ifndef WLAN_MDM_CODE_REDUCTION_OPT
status = sme_QosOpen(pMac);
if ( ! HAL_STATUS_SUCCESS( status ) ) {
smsLog( pMac, LOGE,
"Qos open failed during initialization with status=%d", status );
break;
}
#endif
#ifdef FEATURE_OEM_DATA_SUPPORT
status = oemData_OemDataReqOpen(pMac);
if ( ! HAL_STATUS_SUCCESS( status ) ) {
smsLog(pMac, LOGE,
"oemData_OemDataReqOpen failed during initialization with status=%d", status );
break;
}
#endif
if(!HAL_STATUS_SUCCESS((status = initSmeCmdList(pMac))))
break;
#if defined WLAN_FEATURE_VOWIFI
status = rrmOpen(pMac);
if ( ! HAL_STATUS_SUCCESS( status ) ) {
smsLog( pMac, LOGE,
"rrmOpen open failed during initialization with status=%d", status );
break;
}
#endif
sme_p2pOpen(pMac);
smeTraceInit(pMac);
sme_register_debug_callback();
}while (0);
return status;
}
/*
* sme_init_chan_list, triggers channel setup based on country code.
*/
eHalStatus sme_init_chan_list(tHalHandle hal, v_U8_t *alpha2,
COUNTRY_CODE_SOURCE cc_src)
{
tpAniSirGlobal pmac = PMAC_STRUCT(hal);
if ((cc_src == COUNTRY_CODE_SET_BY_USER) &&
(pmac->roam.configParam.fSupplicantCountryCodeHasPriority))
{
pmac->roam.configParam.Is11dSupportEnabled = eANI_BOOLEAN_FALSE;
}
return csr_init_chan_list(pmac, alpha2);
}
/*--------------------------------------------------------------------------
\brief sme_set11dinfo() - Set the 11d information about valid channels
and there power using information from nvRAM
This function is called only for AP.
This is a synchronous call
\param hHal - The handle returned by macOpen.
\Param pSmeConfigParams - a pointer to a caller allocated object of
typedef struct _smeConfigParams.
\return eHAL_STATUS_SUCCESS - SME update the config parameters successfully.
Other status means SME is failed to update the config parameters.
\sa
--------------------------------------------------------------------------*/
eHalStatus sme_set11dinfo(tHalHandle hHal, tpSmeConfigParams pSmeConfigParams)
{
eHalStatus status = eHAL_STATUS_FAILURE;
tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
MTRACE(vos_trace(VOS_MODULE_ID_SME,
TRACE_CODE_SME_RX_HDD_MSG_SET_11DINFO, NO_SESSION, 0));
if (NULL == pSmeConfigParams ) {
smsLog( pMac, LOGE,
"Empty config param structure for SME, nothing to update");
return status;
}
status = csrSetChannels(hHal, &pSmeConfigParams->csrConfig );
if ( ! HAL_STATUS_SUCCESS( status ) ) {
smsLog( pMac, LOGE, "csrChangeDefaultConfigParam failed with status=%d",
status );
}
return status;
}
/*--------------------------------------------------------------------------
\brief sme_getSoftApDomain() - Get the current regulatory domain of softAp.
This is a synchronous call
\param hHal - The handle returned by HostapdAdapter.
\Param v_REGDOMAIN_t - The current Regulatory Domain requested for SoftAp.
\return eHAL_STATUS_SUCCESS - SME successfully completed the request.
Other status means, failed to get the current regulatory domain.
\sa
--------------------------------------------------------------------------*/
eHalStatus sme_getSoftApDomain(tHalHandle hHal, v_REGDOMAIN_t *domainIdSoftAp)
{
eHalStatus status = eHAL_STATUS_FAILURE;
tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
MTRACE(vos_trace(VOS_MODULE_ID_SME,
TRACE_CODE_SME_RX_HDD_MSG_GET_SOFTAP_DOMAIN, NO_SESSION, 0));
if (NULL == domainIdSoftAp ) {
smsLog( pMac, LOGE, "Uninitialized domain Id");
return status;
}
*domainIdSoftAp = pMac->scan.domainIdCurrent;
status = eHAL_STATUS_SUCCESS;
return status;
}
eHalStatus sme_setRegInfo(tHalHandle hHal, tANI_U8 *apCntryCode)
{
eHalStatus status = eHAL_STATUS_FAILURE;
tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
MTRACE(vos_trace(VOS_MODULE_ID_SME,
TRACE_CODE_SME_RX_HDD_MSG_SET_REGINFO, NO_SESSION, 0));
if (NULL == apCntryCode ) {
smsLog( pMac, LOGE, "Empty Country Code, nothing to update");
return status;
}
status = csrSetRegInfo(hHal, apCntryCode );
if ( ! HAL_STATUS_SUCCESS( status ) ) {
smsLog( pMac, LOGE, "csrSetRegInfo failed with status=%d",
status );
}
return status;
}
#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
eHalStatus sme_SetPlmRequest(tHalHandle hHal, tpSirPlmReq pPlmReq)
{
eHalStatus status;
tANI_BOOLEAN ret = eANI_BOOLEAN_FALSE;
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
tANI_U8 ch_list[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
tANI_U8 count, valid_count = 0;
vos_msg_t msg;
if (eHAL_STATUS_SUCCESS == (status = sme_AcquireGlobalLock(&pMac->sme)))
{
tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, pPlmReq->sessionId );
if(!pSession)
{
smsLog(pMac, LOGE, FL("session %d not found"), pPlmReq->sessionId);
sme_ReleaseGlobalLock( &pMac->sme );
return eHAL_STATUS_FAILURE;
}
if( !pSession->sessionActive )
{
VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
"%s Invalid Sessionid", __func__);
sme_ReleaseGlobalLock( &pMac->sme );
return eHAL_STATUS_FAILURE;
}
if (pPlmReq->enable) {
/* validating channel numbers */
for (count = 0; count < pPlmReq->plmNumCh; count++) {
ret = csrIsSupportedChannel(pMac, pPlmReq->plmChList[count]);
if (ret && pPlmReq->plmChList[count] > 14)
{
if (NV_CHANNEL_DFS ==
vos_nv_getChannelEnabledState(pPlmReq->plmChList[count]))
{
/* DFS channel is provided, no PLM bursts can be
* transmitted. Ignoring these channels.
*/
VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO,
"%s DFS channel %d ignored for PLM", __func__,
pPlmReq->plmChList[count]);
continue;
}
}
else if (!ret)
{
/* Not supported, ignore the channel */
VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO,
"%s Unsupported channel %d ignored for PLM",
__func__, pPlmReq->plmChList[count]);
continue;
}
ch_list[valid_count] = pPlmReq->plmChList[count];
valid_count++;
} /* End of for () */
/* Copying back the valid channel list to plm struct */
vos_mem_set((void *)pPlmReq->plmChList, pPlmReq->plmNumCh, 0);
if (valid_count)
vos_mem_copy(pPlmReq->plmChList, ch_list, valid_count);
/* All are invalid channels, FW need to send the PLM
* report with "incapable" bit set.
*/
pPlmReq->plmNumCh = valid_count;
} /* PLM START */
msg.type = WDA_SET_PLM_REQ;
msg.reserved = 0;
msg.bodyptr = pPlmReq;
if (!VOS_IS_STATUS_SUCCESS(vos_mq_post_message(VOS_MODULE_ID_WDA, &msg)))
{
VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
"%s: Not able to post WDA_SET_PLM_REQ message to WDA",
__func__);
sme_ReleaseGlobalLock(&pMac->sme);
return eHAL_STATUS_FAILURE;
}
sme_ReleaseGlobalLock(&pMac->sme);
}
return (status);
}
#endif
#ifdef FEATURE_WLAN_SCAN_PNO
/*--------------------------------------------------------------------------
\brief sme_UpdateChannelConfig() - Update channel configuration in RIVA.
It is used at driver start up to inform RIVA of the default channel
configuration.
This is a synchronous call
\param hHal - The handle returned by macOpen.
\return eHAL_STATUS_SUCCESS - SME update the channel config successfully.
Other status means SME is failed to update the channel config.
\sa
--------------------------------------------------------------------------*/
eHalStatus sme_UpdateChannelConfig(tHalHandle hHal)
{
tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
MTRACE(vos_trace(VOS_MODULE_ID_SME,
TRACE_CODE_SME_RX_HDD_MSG_UPDATE_CHANNEL_CONFIG, NO_SESSION, 0));
pmcUpdateScanParams( pMac, &(pMac->roam.configParam),
&pMac->scan.base20MHzChannels, FALSE);
return eHAL_STATUS_SUCCESS;
}
#endif // FEATURE_WLAN_SCAN_PNLO
/*--------------------------------------------------------------------------
\brief sme_UpdateConfig() - Change configurations for all SME modules
The function updates some configuration for modules in SME, CCM, CSR, etc
during SMEs close open sequence.
Modules inside SME apply the new configuration at the next transaction.
This is a synchronous call
\param hHal - The handle returned by macOpen.
\Param pSmeConfigParams - a pointer to a caller allocated object of
typedef struct _smeConfigParams.
\return eHAL_STATUS_SUCCESS - SME update the config parameters successfully.
Other status means SME is failed to update the config parameters.
\sa
--------------------------------------------------------------------------*/
eHalStatus sme_UpdateConfig(tHalHandle hHal, tpSmeConfigParams pSmeConfigParams)
{
eHalStatus status = eHAL_STATUS_FAILURE;
tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
MTRACE(vos_trace(VOS_MODULE_ID_SME,
TRACE_CODE_SME_RX_HDD_MSG_UPDATE_CONFIG, NO_SESSION, 0));
if (NULL == pSmeConfigParams ) {
smsLog( pMac, LOGE,
"Empty config param structure for SME, nothing to update");
return status;
}
status = csrChangeDefaultConfigParam(pMac, &pSmeConfigParams->csrConfig);
if ( ! HAL_STATUS_SUCCESS( status ) ) {
smsLog( pMac, LOGE, "csrChangeDefaultConfigParam failed with status=%d",
status );
}
#if defined WLAN_FEATURE_VOWIFI
status = rrmChangeDefaultConfigParam(hHal, &pSmeConfigParams->rrmConfig);
if ( ! HAL_STATUS_SUCCESS( status ) ) {
smsLog( pMac, LOGE, "rrmChangeDefaultConfigParam failed with status=%d",
status );
}
#endif
//For SOC, CFG is set before start
//We don't want to apply global CFG in connect state because that may cause some side affect
if(
csrIsAllSessionDisconnected( pMac) )
{
csrSetGlobalCfgs(pMac);
}
/* update the directed scan offload setting */
pMac->fScanOffload = pSmeConfigParams->fScanOffload;
if (pMac->fScanOffload)
{
/*
* If scan offload is enabled then lim has allow the sending of
* scan request to firmware even in power save mode. The firmware has
* to take care of exiting from power save mode
*/
status = ccmCfgSetInt(hHal, WNI_CFG_SCAN_IN_POWERSAVE,
eANI_BOOLEAN_TRUE, NULL, eANI_BOOLEAN_FALSE);
if (eHAL_STATUS_SUCCESS != status)
{
VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
"Could not pass on WNI_CFG_SCAN_IN_POWERSAVE to CCM");
}
}
pMac->isCoalesingInIBSSAllowed =
pSmeConfigParams->csrConfig.isCoalesingInIBSSAllowed;
/* update the p2p listen offload setting */
pMac->fP2pListenOffload = pSmeConfigParams->fP2pListenOffload;
/* update p2p offload status */
pMac->pnoOffload = pSmeConfigParams->pnoOffload;
pMac->fEnableDebugLog = pSmeConfigParams->fEnableDebugLog;
/* update interface configuration */
pMac->sme.max_intf_count = pSmeConfigParams->max_intf_count;
pMac->enable5gEBT = pSmeConfigParams->enable5gEBT;
pMac->sme.enableSelfRecovery = pSmeConfigParams->enableSelfRecovery;
pMac->f_sta_miracast_mcc_rest_time_val =
pSmeConfigParams->f_sta_miracast_mcc_rest_time_val;
#ifdef FEATURE_AP_MCC_CH_AVOIDANCE
pMac->sap.sap_channel_avoidance = pSmeConfigParams->sap_channel_avoidance;
#endif /* FEATURE_AP_MCC_CH_AVOIDANCE */
pMac->f_prefer_non_dfs_on_radar =
pSmeConfigParams->f_prefer_non_dfs_on_radar;
pMac->fine_time_meas_cap = pSmeConfigParams->fine_time_meas_cap;
pMac->snr_monitor_enabled = pSmeConfigParams->snr_monitor_enabled;
pMac->sub20_config_info = pSmeConfigParams->sub20_config_info;
pMac->sub20_channelwidth = pSmeConfigParams->sub20_channelwidth;
pMac->sub20_dynamic_channelwidth =
pSmeConfigParams->sub20_dynamic_channelwidth;
pMac->sta_auth_retries_for_code17 =
pSmeConfigParams->csrConfig.sta_auth_retries_for_code17;
pMac->sta_change_cc_via_beacon =
pSmeConfigParams->sta_change_cc_via_beacon;
return status;
}
/**
* sme_update_roam_params - Store/Update the roaming params
* @hHal Handle for Hal layer
* @session_id SME Session ID
* @roam_params_src The source buffer to copy
* @update_param Type of parameter to be updated
*
* Return: Return the status of the updation.
*/
eHalStatus sme_update_roam_params(tHalHandle hHal,
uint8_t session_id, struct roam_ext_params roam_params_src,
int update_param)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
struct roam_ext_params *roam_params_dst;
uint8_t i;
roam_params_dst = &pMac->roam.configParam.roam_params;
switch(update_param) {
case REASON_ROAM_EXT_SCAN_PARAMS_CHANGED:
roam_params_dst->raise_rssi_thresh_5g =
roam_params_src.raise_rssi_thresh_5g;
roam_params_dst->drop_rssi_thresh_5g =
roam_params_src.drop_rssi_thresh_5g;
roam_params_dst->raise_factor_5g=
roam_params_src.raise_factor_5g;
roam_params_dst->drop_factor_5g =
roam_params_src.drop_factor_5g;
roam_params_dst->max_raise_rssi_5g =
roam_params_src.max_raise_rssi_5g;
roam_params_dst->max_drop_rssi_5g=
roam_params_src.max_drop_rssi_5g;
roam_params_dst->alert_rssi_threshold =
roam_params_src.alert_rssi_threshold;
roam_params_dst->is_5g_pref_enabled = true;
break;
case REASON_ROAM_SET_SSID_ALLOWED:
vos_mem_set(&roam_params_dst->ssid_allowed_list, 0,
sizeof(tSirMacSSid) * MAX_SSID_ALLOWED_LIST);
roam_params_dst->num_ssid_allowed_list=
roam_params_src.num_ssid_allowed_list;
for (i=0; i<roam_params_dst->num_ssid_allowed_list; i++) {
roam_params_dst->ssid_allowed_list[i].length =
roam_params_src.ssid_allowed_list[i].length;
vos_mem_copy(roam_params_dst->ssid_allowed_list[i].ssId,
roam_params_src.ssid_allowed_list[i].ssId,
roam_params_dst->ssid_allowed_list[i].length);
}
break;
case REASON_ROAM_SET_FAVORED_BSSID:
vos_mem_set(&roam_params_dst->bssid_favored, 0,
sizeof(tSirMacAddr) * MAX_BSSID_FAVORED);
roam_params_dst->num_bssid_favored=
roam_params_src.num_bssid_favored;
for (i=0; i<roam_params_dst->num_bssid_favored; i++) {
vos_mem_copy(&roam_params_dst->bssid_favored[i],
&roam_params_src.bssid_favored[i],
sizeof(tSirMacAddr));
roam_params_dst->bssid_favored_factor[i] =
roam_params_src.bssid_favored_factor[i];
}
break;
case REASON_ROAM_SET_BLACKLIST_BSSID:
vos_mem_set(&roam_params_dst->bssid_avoid_list, 0,
sizeof(tSirMacAddr) * MAX_BSSID_AVOID_LIST);
roam_params_dst->num_bssid_avoid_list =
roam_params_src.num_bssid_avoid_list;
for (i=0; i<roam_params_dst->num_bssid_avoid_list; i++) {
vos_mem_copy(&roam_params_dst->bssid_avoid_list[i],
&roam_params_src.bssid_avoid_list[i],
sizeof(tSirMacAddr));
}
break;
case REASON_ROAM_GOOD_RSSI_CHANGED:
roam_params_dst->good_rssi_roam =
roam_params_src.good_rssi_roam;
break;
default:
break;
}
csrRoamOffloadScan(pMac, session_id,
ROAM_SCAN_OFFLOAD_UPDATE_CFG, update_param);
return 0;
}
#ifdef WLAN_FEATURE_GTK_OFFLOAD
void sme_ProcessGetGtkInfoRsp( tHalHandle hHal,
tpSirGtkOffloadGetInfoRspParams pGtkOffloadGetInfoRsp)
{
tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
if (NULL == pMac)
{
VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL,
"%s: pMac is null", __func__);
return ;
}
if (pMac->pmc.GtkOffloadGetInfoCB == NULL)
{
VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
"%s: HDD callback is null", __func__);
return ;
}
pMac->pmc.GtkOffloadGetInfoCB(pMac->pmc.GtkOffloadGetInfoCBContext,
pGtkOffloadGetInfoRsp);
}
#endif
/*--------------------------------------------------------------------------
\fn - sme_ProcessReadyToSuspend
\brief - On getting ready to suspend indication, this function calls
callback registered (HDD callbacks) with SME to inform
ready to suspend indication.
\param hHal - Handle returned by macOpen.
pReadyToSuspend - Parameter received along with ready to suspend
indication from WMA.
\return None
\sa
--------------------------------------------------------------------------*/
void sme_ProcessReadyToSuspend( tHalHandle hHal,
tpSirReadyToSuspendInd pReadyToSuspend)
{
tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
if (NULL == pMac)
{
VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL,
"%s: pMac is null", __func__);
return ;
}
if (NULL != pMac->readyToSuspendCallback)
{
pMac->readyToSuspendCallback (pMac->readyToSuspendContext,
pReadyToSuspend->suspended);
pMac->readyToSuspendCallback = NULL;
}
}
#ifdef WLAN_FEATURE_EXTWOW_SUPPORT
/*--------------------------------------------------------------------------
\fn - sme_ProcessReadyToExtWoW
\brief - On getting ready to Ext WoW indication, this function calls
callback registered (HDD callbacks) with SME to inform
ready to ExtWoW indication.
\param hHal - Handle returned by macOpen.
pReadyToExtWoW - Parameter received along with ready to Ext WoW
indication from WMA.
\return None
\sa
--------------------------------------------------------------------------*/
void sme_ProcessReadyToExtWoW( tHalHandle hHal,
tpSirReadyToExtWoWInd pReadyToExtWoW)
{
tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
if (NULL == pMac)
{
VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL,
"%s: pMac is null", __func__);
return ;
}
if (NULL != pMac->readyToExtWoWCallback)
{
pMac->readyToExtWoWCallback (pMac->readyToExtWoWContext,
pReadyToExtWoW->status);
pMac->readyToExtWoWCallback = NULL;
pMac->readyToExtWoWContext = NULL;
}
}
#endif
/* ---------------------------------------------------------------------------
\fn sme_ChangeConfigParams
\brief The SME API exposed for HDD to provide config params to SME during
SMEs stop -> start sequence.
If HDD changed the domain that will cause a reset. This function will
provide the new set of 11d information for the new domain. Currently this
API provides info regarding 11d only at reset but we can extend this for
other params (PMC, QoS) which needs to be initialized again at reset.
This is a synchronous call
\param hHal - The handle returned by macOpen.
\Param
pUpdateConfigParam - a pointer to a structure (tCsrUpdateConfigParam) that
currently provides 11d related information like Country code,
Regulatory domain, valid channel list, Tx power per channel, a
list with active/passive scan allowed per valid channel.
\return eHalStatus
---------------------------------------------------------------------------*/
eHalStatus sme_ChangeConfigParams(tHalHandle hHal,
tCsrUpdateConfigParam *pUpdateConfigParam)
{
eHalStatus status = eHAL_STATUS_FAILURE;
tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
if (NULL == pUpdateConfigParam ) {
smsLog( pMac, LOGE,
"Empty config param structure for SME, nothing to reset");
return status;
}
status = csrChangeConfigParams(pMac, pUpdateConfigParam);
if ( ! HAL_STATUS_SUCCESS( status ) ) {
smsLog( pMac, LOGE, "csrUpdateConfigParam failed with status=%d",
status );
}
return status;
}
/*--------------------------------------------------------------------------
\brief sme_HDDReadyInd() - SME sends eWNI_SME_SYS_READY_IND to PE to inform
that the NIC is ready to run.
The function is called by HDD at the end of initialization stage so PE/HAL can
enable the NIC to running state.
This is a synchronous call
\param hHal - The handle returned by macOpen.
\return eHAL_STATUS_SUCCESS - eWNI_SME_SYS_READY_IND is sent to PE
successfully.
Other status means SME failed to send the message to PE.
\sa
--------------------------------------------------------------------------*/
eHalStatus sme_HDDReadyInd(tHalHandle hHal)
{
tSirSmeReadyReq Msg;
eHalStatus status = eHAL_STATUS_FAILURE;
tPmcPowerState powerState;
tPmcSwitchState hwWlanSwitchState;
tPmcSwitchState swWlanSwitchState;
tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
MTRACE(vos_trace(VOS_MODULE_ID_SME,
TRACE_CODE_SME_RX_HDD_MSG_HDDREADYIND, NO_SESSION, 0));
do
{
Msg.messageType = eWNI_SME_SYS_READY_IND;
Msg.length = sizeof( tSirSmeReadyReq );
if (eSIR_FAILURE != uMacPostCtrlMsg( hHal, (tSirMbMsg*)&Msg ))
{
status = eHAL_STATUS_SUCCESS;
}
else
{
smsLog( pMac, LOGE,
"uMacPostCtrlMsg failed to send eWNI_SME_SYS_READY_IND");
break;
}
if(!pMac->psOffloadEnabled)
{
status = pmcQueryPowerState( hHal, &powerState,
&hwWlanSwitchState, &swWlanSwitchState );
if ( ! HAL_STATUS_SUCCESS( status ) )
{
smsLog( pMac, LOGE, "pmcQueryPowerState failed with status=%d",
status );
break;
}
if ( (ePMC_SWITCH_OFF != hwWlanSwitchState) &&
(ePMC_SWITCH_OFF != swWlanSwitchState) )
{
status = csrReady(pMac);
if ( ! HAL_STATUS_SUCCESS( status ) )
{
smsLog( pMac, LOGE, "csrReady failed with status=%d", status );
break;
}
status = pmcReady(hHal);
if ( ! HAL_STATUS_SUCCESS( status ) )
{
smsLog( pMac, LOGE, "pmcReady failed with status=%d", status );
break;
}
#if defined WLAN_FEATURE_VOWIFI
if(VOS_STATUS_SUCCESS != rrmReady(hHal))
{
status = eHAL_STATUS_FAILURE;
smsLog( pMac, LOGE, "rrmReady failed");
break;
}
#endif
}
}
else
{
status = csrReady(pMac);
if (!HAL_STATUS_SUCCESS(status))
{
smsLog( pMac, LOGE, "csrReady failed with status=%d", status );
break;
}
#if defined WLAN_FEATURE_VOWIFI
if(VOS_STATUS_SUCCESS != rrmReady(hHal))
{
status = eHAL_STATUS_FAILURE;
smsLog( pMac, LOGE, "rrmReady failed");
break;
}
#endif
}
pMac->sme.state = SME_STATE_READY;
} while( 0 );
return status;
}
/**
* sme_set_allowed_action_frames() - Set allowed action frames to wma
* @hal: Handler to HAL
* @bitmap0: bitmap to set
* @is_sta: boolean to indicate sta interface
*
* This function conveys the list of action frames that needs to be forwarded
* to driver by FW. Rest of the action frames can be dropped in FW. Bitmask is
* set with ALLOWED_ACTION_FRAMES_BITMAP0~7
*
* Return: None
*/
void sme_set_allowed_action_frames(tHalHandle hal,
uint32_t bitmap0, bool is_sta)
{
eHalStatus status;
tpAniSirGlobal mac = PMAC_STRUCT(hal);
vos_msg_t message;
VOS_STATUS vos_status;
struct sir_allowed_action_frames *sir_allowed_action_frames;
sir_allowed_action_frames =
vos_mem_malloc(sizeof(*sir_allowed_action_frames));
if (!sir_allowed_action_frames) {
VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
"Not able to allocate memory for WDA_SET_ALLOWED_ACTION_FRAMES_IND");
return;
}
vos_mem_zero(sir_allowed_action_frames,
sizeof(*sir_allowed_action_frames));
sir_allowed_action_frames->operation = WOW_ACTION_WAKEUP_OPERATION_SET;
sir_allowed_action_frames->action_category_map[0] = bitmap0;
sir_allowed_action_frames->action_category_map[1] =
(ALLOWED_ACTION_FRAMES_BITMAP1);
sir_allowed_action_frames->action_category_map[2] =
(ALLOWED_ACTION_FRAMES_BITMAP2);
sir_allowed_action_frames->action_category_map[3] =
(ALLOWED_ACTION_FRAMES_BITMAP3);
sir_allowed_action_frames->action_category_map[4] =
(ALLOWED_ACTION_FRAMES_BITMAP4);
sir_allowed_action_frames->action_category_map[5] =
(ALLOWED_ACTION_FRAMES_BITMAP5);
sir_allowed_action_frames->action_category_map[6] =
(ALLOWED_ACTION_FRAMES_BITMAP6);
sir_allowed_action_frames->action_category_map[7] =
(ALLOWED_ACTION_FRAMES_BITMAP7);
if (is_sta)
sir_allowed_action_frames->
action_per_category[SIR_MAC_ACTION_SPECTRUM_MGMT] =
DROP_SPEC_MGMT_ACTION_FRAME_BITMAP;
status = sme_AcquireGlobalLock(&mac->sme);
if (status == eHAL_STATUS_SUCCESS) {
/* serialize the req through MC thread */
message.bodyptr = sir_allowed_action_frames;
message.type = SIR_HAL_SET_ALLOWED_ACTION_FRAMES;
vos_status = vos_mq_post_message(VOS_MQ_ID_WDA, &message);
if (!VOS_IS_STATUS_SUCCESS(vos_status)) {
VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
"Not able to post SIR_HAL_SET_ALLOWED_ACTION_FRAMES message to HAL");
vos_mem_free(sir_allowed_action_frames);
}
sme_ReleaseGlobalLock( &mac->sme );
} else {
VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: "
"sme_AcquireGlobalLock error", __func__);
vos_mem_free(sir_allowed_action_frames);
}
return;
}
/**
* sme_handle_cc_change_ind() - handle new country code
* @hal_ptr: Handler to HAL
* @msg_buf: contain new country code.
*
* Return: eHAL_STATUS_SUCCESS on success,
* eHAL_STATUS_INVALID_PARAMETER on failure.
*/
eHalStatus sme_handle_cc_change_ind(tHalHandle hal_ptr, void *msg_buf)
{
eHalStatus status = eHAL_STATUS_FAILURE;
tpAniSirGlobal mac_ptr = PMAC_STRUCT(hal_ptr);
v_REGDOMAIN_t domainId;
struct sme_change_country_code_ind * change_cc_ind =
(struct sme_change_country_code_ind *)msg_buf;
status =
csrGetRegulatoryDomainForCountry(mac_ptr,
change_cc_ind->country_code,
&domainId, COUNTRY_IE);
return (status);
}
/*--------------------------------------------------------------------------
\brief sme_Start() - Put all SME modules at ready state.
The function starts each module in SME, PMC, CCM, CSR, etc. . Upon
successfully return, all modules are ready to run.
This is a synchronous call
\param hHal - The handle returned by macOpen.
\return eHAL_STATUS_SUCCESS - SME is ready.
Other status means SME is failed to start
\sa
--------------------------------------------------------------------------*/
eHalStatus sme_Start(tHalHandle hHal)
{
eHalStatus status = eHAL_STATUS_FAILURE;
tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
do
{
status = csrStart(pMac);
if ( ! HAL_STATUS_SUCCESS( status ) ) {
smsLog( pMac, LOGE, "csrStart failed during smeStart with status=%d",
status );
break;
}
if(!pMac->psOffloadEnabled)
{
status = pmcStart(hHal);
if ( ! HAL_STATUS_SUCCESS( status ) ) {
smsLog( pMac, LOGE,
"pmcStart failed during smeStart with status=%d",
status );
break;
}
}
else
{
status = pmcOffloadStart(hHal);
if ( ! HAL_STATUS_SUCCESS( status ) ) {
smsLog( pMac, LOGE,
"pmcOffloadStart failed during smeStart with status=%d",
status );
break;
}
}
pMac->sme.state = SME_STATE_START;
}while (0);
sme_set_allowed_action_frames(hHal, ALLOWED_ACTION_FRAMES_BITMAP0_STA, true);
return status;
}
#ifdef WLAN_FEATURE_PACKET_FILTERING
/******************************************************************************
*
* Name: sme_PCFilterMatchCountResponseHandler
*
* Description:
* Invoke Packet Coalescing Filter Match Count callback routine
*
* Parameters:
* hHal - HAL handle for device
* pMsg - Pointer to tRcvFltPktMatchRsp structure
*
* Returns: eHalStatus
*
******************************************************************************/
eHalStatus sme_PCFilterMatchCountResponseHandler(tHalHandle hHal, void* pMsg)
{
tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
eHalStatus status = eHAL_STATUS_SUCCESS;
tpSirRcvFltPktMatchRsp pRcvFltPktMatchRsp = (tpSirRcvFltPktMatchRsp)pMsg;
if (NULL == pMsg)
{
smsLog(pMac, LOGE, "in %s msg ptr is NULL", __func__);
status = eHAL_STATUS_FAILURE;
}
else
{
smsLog(pMac, LOG2, "SME: entering "
"sme_FilterMatchCountResponseHandler");
/* Call Packet Coalescing Filter Match Count callback routine. */
if (pMac->pmc.FilterMatchCountCB != NULL)
pMac->pmc.FilterMatchCountCB(pMac->pmc.FilterMatchCountCBContext,
pRcvFltPktMatchRsp);
smsLog(pMac, LOG1, "%s: status=0x%x", __func__,
pRcvFltPktMatchRsp->status);
pMac->pmc.FilterMatchCountCB = NULL;
pMac->pmc.FilterMatchCountCBContext = NULL;
}
return(status);
}
#endif // WLAN_FEATURE_PACKET_FILTERING
#ifdef WLAN_FEATURE_11W
/*------------------------------------------------------------------
*
* Handle the unprotected management frame indication from LIM and
* forward it to HDD.
*
*------------------------------------------------------------------*/
eHalStatus sme_UnprotectedMgmtFrmInd( tHalHandle hHal,
tpSirSmeUnprotMgmtFrameInd pSmeMgmtFrm)
{
tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
eHalStatus status = eHAL_STATUS_SUCCESS;
tCsrRoamInfo pRoamInfo = {0};
tANI_U32 SessionId = pSmeMgmtFrm->sessionId;
pRoamInfo.nFrameLength = pSmeMgmtFrm->frameLen;
pRoamInfo.pbFrames = pSmeMgmtFrm->frameBuf;
pRoamInfo.frameType = pSmeMgmtFrm->frameType;
/* forward the mgmt frame to HDD */
csrRoamCallCallback(pMac, SessionId, &pRoamInfo, 0, eCSR_ROAM_UNPROT_MGMT_FRAME_IND, 0);
return status;
}
#endif
/*------------------------------------------------------------------
*
* Handle the DFS Radar Event and indicate it to the SAP
*
*------------------------------------------------------------------*/
eHalStatus dfsMsgProcessor(tpAniSirGlobal pMac, v_U16_t msgType, void *pMsgBuf)
{
eHalStatus status = eHAL_STATUS_SUCCESS;
tCsrRoamInfo roamInfo = {0};
tSirSmeDfsEventInd *dfs_event;
tSirSmeCSAIeTxCompleteRsp *csaIeTxCompleteRsp;
tANI_U32 sessionId = 0;
eRoamCmdStatus roamStatus;
eCsrRoamResult roamResult;
int i;
switch (msgType)
{
case eWNI_SME_DFS_RADAR_FOUND:
{
/* Radar found !! */
dfs_event = (tSirSmeDfsEventInd *)pMsgBuf;
if (NULL == dfs_event)
{
smsLog(pMac, LOGE,
"%s: pMsg is NULL for eWNI_SME_DFS_RADAR_FOUND message",
__func__);
return eHAL_STATUS_FAILURE;
}
sessionId = dfs_event->sessionId;
roamInfo.dfs_event.sessionId = sessionId;
roamInfo.dfs_event.chan_list.nchannels =
dfs_event->chan_list.nchannels;
for (i = 0; i < dfs_event->chan_list.nchannels; i++)
{
roamInfo.dfs_event.chan_list.channels[i] =
dfs_event->chan_list.channels[i];
}
roamInfo.dfs_event.dfs_radar_status = dfs_event->dfs_radar_status;
roamInfo.dfs_event.use_nol = dfs_event->use_nol;
roamStatus = eCSR_ROAM_DFS_RADAR_IND;
roamResult = eCSR_ROAM_RESULT_DFS_RADAR_FOUND_IND;
VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_MED,
"sapdfs: Radar indication event occurred");
break;
}
case eWNI_SME_DFS_CSAIE_TX_COMPLETE_IND:
{
csaIeTxCompleteRsp = (tSirSmeCSAIeTxCompleteRsp *)pMsgBuf;
if (NULL == csaIeTxCompleteRsp)
{
smsLog(pMac, LOGE,
"%s: pMsg is NULL for eWNI_SME_DFS_CSAIE_TX_COMPLETE_IND",
__func__);
return eHAL_STATUS_FAILURE;
}
sessionId = csaIeTxCompleteRsp->sessionId;
roamStatus = eCSR_ROAM_DFS_CHAN_SW_NOTIFY;
roamResult = eCSR_ROAM_RESULT_DFS_CHANSW_UPDATE_SUCCESS;
VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO_MED,
"sapdfs: Received eWNI_SME_DFS_CSAIE_TX_COMPLETE_IND for session id [%d]",
sessionId );
break;
}
default:
{
smsLog(pMac, LOG1, "%s: Invalid DFS message = 0x%x", __func__,
msgType);
status = eHAL_STATUS_FAILURE;
return status;
}
}
/* Indicate Radar Event to SAP */
csrRoamCallCallback(pMac, sessionId, &roamInfo, 0,
roamStatus, roamResult);
return status;
}
/**
* sme_extended_change_channel_ind()- function to indicate ECSA
* action frame is received in lim to SAP
* @mac_ctx: pointer to global mac structure
* @msg_buf: contain new channel and session id.
*
* This function is called to post ECSA action frame
* receive event to SAP.
*
* Return: success if msg indicated to SAP else return failure
*/
static eHalStatus sme_extended_change_channel_ind(tpAniSirGlobal mac_ctx,
void *msg_buf)
{
struct sir_sme_ext_cng_chan_ind *ext_chan_ind;
eHalStatus status = eHAL_STATUS_SUCCESS;
uint32_t session_id = 0;
tCsrRoamInfo roamInfo = {0};
eRoamCmdStatus roamStatus;
eCsrRoamResult roamResult;
ext_chan_ind = msg_buf;
if (NULL == ext_chan_ind) {
smsLog(mac_ctx, LOGE,
FL("pMsg is NULL for eWNI_SME_EXT_CHANGE_CHANNEL_IND"));
return eHAL_STATUS_FAILURE;
}
session_id = ext_chan_ind->session_id;
roamInfo.target_channel = ext_chan_ind->new_channel;
roamStatus = eCSR_ROAM_EXT_CHG_CHNL_IND;
roamResult = eCSR_ROAM_EXT_CHG_CHNL_UPDATE_IND;
smsLog(mac_ctx, LOG1,
FL("sapdfs: Received eWNI_SME_EXT_CHANGE_CHANNEL_IND for session id [%d]"),
session_id);
/* Indicate Ext Channel Change event to SAP */
csrRoamCallCallback(mac_ctx, session_id, &roamInfo, 0,
roamStatus, roamResult);
return status;
}
#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
/*------------------------------------------------------------------
*
* Handle the tsm ie indication from LIM and forward it to HDD.
*
*------------------------------------------------------------------*/
eHalStatus sme_TsmIeInd(tHalHandle hHal, tSirSmeTsmIEInd *pSmeTsmIeInd)
{
tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
eHalStatus status = eHAL_STATUS_SUCCESS;
tCsrRoamInfo pRoamInfo = {0};
tANI_U32 SessionId = pSmeTsmIeInd->sessionId;
pRoamInfo.tsmIe.tsid= pSmeTsmIeInd->tsmIe.tsid;
pRoamInfo.tsmIe.state= pSmeTsmIeInd->tsmIe.state;
pRoamInfo.tsmIe.msmt_interval= pSmeTsmIeInd->tsmIe.msmt_interval;
/* forward the tsm ie information to HDD */
csrRoamCallCallback(pMac,
SessionId,
&pRoamInfo,
0,
eCSR_ROAM_TSM_IE_IND,
0);
return status;
}
/* ---------------------------------------------------------------------------
\fn sme_SetCCKMIe
\brief function to store the CCKM IE passed from supplicant and use
it while packing reassociation request
\param hHal - HAL handle for device
\param sessionId - Session Identifier
\param pCckmIe - pointer to CCKM IE data
\param pCckmIeLen - length of the CCKM IE
\- return Success or failure
-------------------------------------------------------------------------*/
eHalStatus sme_SetCCKMIe(tHalHandle hHal, tANI_U8 sessionId,
tANI_U8 *pCckmIe, tANI_U8 cckmIeLen)
{
tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
eHalStatus status = eHAL_STATUS_SUCCESS;
status = sme_AcquireGlobalLock( &pMac->sme );
if ( HAL_STATUS_SUCCESS( status ) )
{
csrSetCCKMIe(pMac, sessionId, pCckmIe, cckmIeLen);
sme_ReleaseGlobalLock( &pMac->sme );
}
return status;
}
/* ---------------------------------------------------------------------------
\fn sme_SetEseBeaconRequest
\brief function to set ESE beacon request parameters
\param hHal - HAL handle for device
\param sessionId - Session id
\param pEseBcnReq - pointer to ESE beacon request
\- return Success or failure
-------------------------------------------------------------------------*/
eHalStatus sme_SetEseBeaconRequest(tHalHandle hHal, const tANI_U8 sessionId,
const tCsrEseBeaconReq* pEseBcnReq)
{
eHalStatus status = eSIR_SUCCESS;
tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
tpSirBeaconReportReqInd pSmeBcnReportReq = NULL;
tCsrEseBeaconReqParams *pBeaconReq = NULL;
tANI_U8 counter = 0;
tCsrRoamSession *pSession = CSR_GET_SESSION(pMac, sessionId);
tpRrmSMEContext pSmeRrmContext = &pMac->rrm.rrmSmeContext;
if (pSmeRrmContext->eseBcnReqInProgress == TRUE)
{
smsLog(pMac, LOGE, "A Beacon Report Req is already in progress");
return eHAL_STATUS_RESOURCES;
}
/* Store the info in RRM context */
vos_mem_copy(&pSmeRrmContext->eseBcnReqInfo, pEseBcnReq, sizeof(tCsrEseBeaconReq));
//Prepare the request to send to SME.
pSmeBcnReportReq = vos_mem_malloc(sizeof( tSirBeaconReportReqInd ));
if(NULL == pSmeBcnReportReq)
{
smsLog(pMac, LOGP, "Memory Allocation Failure!!! ESE BcnReq Ind to SME");
return eSIR_FAILURE;
}
pSmeRrmContext->eseBcnReqInProgress = TRUE;
smsLog(pMac, LOGE, "Sending Beacon Report Req to SME");
vos_mem_zero( pSmeBcnReportReq, sizeof( tSirBeaconReportReqInd ));
pSmeBcnReportReq->messageType = eWNI_SME_BEACON_REPORT_REQ_IND;
pSmeBcnReportReq->length = sizeof( tSirBeaconReportReqInd );
vos_mem_copy( pSmeBcnReportReq->bssId, pSession->connectedProfile.bssid, sizeof(tSirMacAddr) );
pSmeBcnReportReq->channelInfo.channelNum = 255;
pSmeBcnReportReq->channelList.numChannels = pEseBcnReq->numBcnReqIe;
pSmeBcnReportReq->msgSource = eRRM_MSG_SOURCE_ESE_UPLOAD;
for (counter = 0; counter < pEseBcnReq->numBcnReqIe; counter++)
{
pBeaconReq = (tCsrEseBeaconReqParams *)&pEseBcnReq->bcnReq[counter];
pSmeBcnReportReq->fMeasurementtype[counter] = pBeaconReq->scanMode;
pSmeBcnReportReq->measurementDuration[counter] = SYS_TU_TO_MS(pBeaconReq->measurementDuration);
pSmeBcnReportReq->channelList.channelNumber[counter] = pBeaconReq->channel;
}
status = sme_RrmProcessBeaconReportReqInd(pMac, pSmeBcnReportReq);
if(status != eHAL_STATUS_SUCCESS)
pSmeRrmContext->eseBcnReqInProgress = FALSE;
vos_mem_free(pSmeBcnReportReq);
return status;
}
#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
eHalStatus sme_IbssPeerInfoResponseHandleer( tHalHandle hHal,
tpSirIbssGetPeerInfoRspParams pIbssPeerInfoParams)
{
tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
if (NULL == pMac)
{
VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL,
"%s: pMac is null", __func__);
return eHAL_STATUS_FAILURE;
}
if (pMac->sme.peerInfoParams.peerInfoCbk == NULL)
{
VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
"%s: HDD callback is null", __func__);
return eHAL_STATUS_FAILURE;
}
pMac->sme.peerInfoParams.peerInfoCbk(pMac->sme.peerInfoParams.pUserData,
&pIbssPeerInfoParams->ibssPeerInfoRspParams);
return eHAL_STATUS_SUCCESS;
}
/*--------------------------------------------------------------------------
\brief sme_ProcessMsg() - The main message processor for SME.
The function is called by a message dispatcher when to process a message
targeted for SME.
This is a synchronous call
\param hHal - The handle returned by macOpen.
\param pMsg - A pointer to a caller allocated object of tSirMsgQ.
\return eHAL_STATUS_SUCCESS - SME successfully process the message.
Other status means SME failed to process the message to HAL.
\sa
--------------------------------------------------------------------------*/
eHalStatus sme_ProcessMsg(tHalHandle hHal, vos_msg_t* pMsg)
{
eHalStatus status = eHAL_STATUS_FAILURE;
tpAniSirGlobal pMac = PMAC_STRUCT( hHal );
if (pMsg == NULL) {
smsLog( pMac, LOGE, "Empty message for SME, nothing to process");
return status;
}
status = sme_AcquireGlobalLock( &pMac->sme );
if ( HAL_STATUS_SUCCESS( status ) )
{
if( SME_IS_START(pMac) )
{
switch (pMsg->type) { // TODO: Will be modified to do a range check for msgs instead of having cases for each msgs
#ifdef WLAN_FEATURE_ROAM_OFFLOAD
case eWNI_SME_HO_FAIL_IND:
VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
"LFR3:%s: Rcvd eWNI_SME_HO_FAIL_IND", __func__);
csrProcessHOFailInd(pMac, pMsg->bodyptr);
vos_mem_free(pMsg->bodyptr);
break;
case eWNI_SME_ROAM_OFFLOAD_SYNCH_IND:
csrProcessRoamOffloadSynchInd(pMac,
(tpSirRoamOffloadSynchInd)pMsg->bodyptr);
vos_mem_free(pMsg->bodyptr);
break;
#endif
case eWNI_PMC_ENTER_BMPS_RSP:
case eWNI_PMC_EXIT_BMPS_RSP:
case eWNI_PMC_EXIT_BMPS_IND:
case eWNI_PMC_ENTER_IMPS_RSP:
case eWNI_PMC_EXIT_IMPS_RSP:
case eWNI_PMC_SMPS_STATE_IND:
case eWNI_PMC_ENTER_UAPSD_RSP:
case eWNI_PMC_EXIT_UAPSD_RSP:
case eWNI_PMC_ENTER_WOWL_RSP:
case eWNI_PMC_EXIT_WOWL_RSP:
//PMC
if (pMsg->bodyptr)
{
if(!pMac->psOffloadEnabled)
{
pmcMessageProcessor(hHal, pMsg->bodyptr);
}
else
{
pmcOffloadMessageProcessor(hHal, pMsg->bodyptr);
}
status = eHAL_STATUS_SUCCESS;
vos_mem_free(pMsg->bodyptr);
} else {
smsLog( pMac, LOGE, "Empty rsp message for PMC, nothing to process");
}
break;
case WNI_CFG_SET_CNF:
case WNI_CFG_DNLD_CNF:
case WNI_CFG_GET_RSP:
case WNI_CFG_ADD_GRP_ADDR_CNF:
case WNI_CFG_DEL_GRP_ADDR_CNF:
//CCM
if (pMsg->bodyptr)
{
ccmCfgCnfMsgHandler(hHal, pMsg->bodyptr);
status = eHAL_STATUS_SUCCESS;
vos_mem_free(pMsg->bodyptr);
} else {
smsLog( pMac, LOGE, "Empty rsp message for CCM, nothing to process");
}
break;
case eWNI_SME_ADDTS_RSP:
case eWNI_SME_DELTS_RSP:
case eWNI_SME_DELTS_IND:
#ifdef WLAN_FEATURE_VOWIFI_11R
case eWNI_SME_FT_AGGR_QOS_RSP:
#endif
//QoS
if (pMsg->bodyptr)
{
#ifndef WLAN_MDM_CODE_REDUCTION_OPT
status = sme_QosMsgProcessor(pMac, pMsg->type, pMsg->bodyptr);
vos_mem_free(pMsg->bodyptr);
#endif
} else {
smsLog( pMac, LOGE, "Empty rsp message for QoS, nothing to process");
}
break;
#if defined WLAN_FEATURE_VOWIFI
case eWNI_SME_NEIGHBOR_REPORT_IND:
case eWNI_SME_BEACON_REPORT_REQ_IND:
#if defined WLAN_VOWIFI_DEBUG
smsLog( pMac, LOGE, "Received RRM message. Message Id = %d", pMsg->type );
#endif
if ( pMsg->bodyptr )
{
status = sme_RrmMsgProcessor( pMac, pMsg->type, pMsg->bodyptr );
vos_mem_free(pMsg->bodyptr);
}
else
{
smsLog( pMac, LOGE, "Empty message for RRM, nothing to process");
}
break;
#endif
#ifdef FEATURE_OEM_DATA_SUPPORT
//Handle the eWNI_SME_OEM_DATA_RSP:
case eWNI_SME_OEM_DATA_RSP:
if(pMsg->bodyptr)
{
status = sme_HandleOemDataRsp(pMac, pMsg->bodyptr);
vos_mem_free(pMsg->bodyptr);
}
else
{
smsLog( pMac, LOGE, "Empty rsp message for oemData_ (eWNI_SME_OEM_DATA_RSP), nothing to process");
}
smeProcessPendingQueue( pMac );
break;
#endif
case eWNI_SME_ADD_STA_SELF_RSP:
if(pMsg->bodyptr)
{
status = csrProcessAddStaSessionRsp(pMac, pMsg->bodyptr);
vos_mem_free(pMsg->bodyptr);
}
else
{
smsLog( pMac, LOGE, "Empty rsp message for meas (eWNI_SME_ADD_STA_SELF_RSP), nothing to process");
}
break;
case eWNI_SME_DEL_STA_SELF_RSP:
if(pMsg->bodyptr)
{
status = csrProcessDelStaSessionRsp(pMac, pMsg->bodyptr);
vos_mem_free(pMsg->bodyptr);
}
else
{
smsLog( pMac, LOGE, "Empty rsp message for meas (eWNI_SME_DEL_STA_SELF_RSP), nothing to process");
}
break;
case eWNI_SME_REMAIN_ON_CHN_RSP:
if(pMsg->bodyptr)
{
status = sme_remainOnChnRsp(pMac, pMsg->bodyptr);
vos_mem_free(pMsg->bodyptr);
}
else
{
smsLog( pMac, LOGE, "Empty rsp message for meas (eWNI_SME_REMAIN_ON_CHN_RSP), nothing to process");
}
break;
case eWNI_SME_REMAIN_ON_CHN_RDY_IND:
if(pMsg->bodyptr)
{
status = sme_remainOnChnReady(pMac, pMsg->bodyptr);
vos_mem_free(pMsg->bodyptr);
}
else
{
smsLog( pMac, LOGE, "Empty rsp message for meas (eWNI_SME_REMAIN_ON_CHN_RDY_IND), nothing to process");
}
break;
#ifdef FEATURE_WLAN_SCAN_PNO
case eWNI_SME_PREF_NETWORK_FOUND_IND:
MTRACE(vos_trace(VOS_MODULE_ID_SME, TRACE_CODE_SME_RX_WDA_MSG,
NO_SESSION, pMsg->type));
if(pMsg->bodyptr)
{
status = sme_PreferredNetworkFoundInd((void *)pMac, pMsg->bodyptr);
vos_mem_free(pMsg->bodyptr);
}
else
{
smsLog(pMac, LOGE, "Empty rsp message for meas (eWNI_SME_PREF_NETWORK_FOUND_IND), nothing to process");
}
break;
#endif // FEATURE_WLAN_SCAN_PNO
case eWNI_SME_TX_PER_HIT_IND:
MTRACE(vos_trace(VOS_MODULE_ID_SME, TRACE_CODE_SME_RX_WDA_MSG,
NO_SESSION, pMsg->type));
if (pMac->sme.pTxPerHitCallback)
{
pMac->sme.pTxPerHitCallback(pMac->sme.pTxPerHitCbContext);
}
break;
case eWNI_SME_CHANGE_COUNTRY_CODE:
if(pMsg->bodyptr)
{
status = sme_HandleChangeCountryCode((void *)pMac, pMsg->bodyptr);
vos_mem_free(pMsg->bodyptr);
}
else
{
smsLog(pMac, LOGE, "Empty rsp message for message (eWNI_SME_CHANGE_COUNTRY_CODE), nothing to process");
}
break;
case eWNI_SME_GENERIC_CHANGE_COUNTRY_CODE:
if (pMsg->bodyptr)
{
status = sme_HandleGenericChangeCountryCode((void *)pMac, pMsg->bodyptr);
vos_mem_free(pMsg->bodyptr);
}
else
{
smsLog(pMac, LOGE, "Empty rsp message for message (eWNI_SME_GENERIC_CHANGE_COUNTRY_CODE), nothing to process");
}
break;
#ifdef WLAN_FEATURE_PACKET_FILTERING
case eWNI_PMC_PACKET_COALESCING_FILTER_MATCH_COUNT_RSP:
MTRACE(vos_trace(VOS_MODULE_ID_SME, TRACE_CODE_SME_RX_WDA_MSG,
NO_SESSION, pMsg->type));
if(pMsg->bodyptr)
{
status = sme_PCFilterMatchCountResponseHandler((void *)pMac, pMsg->bodyptr);
vos_mem_free(pMsg->bodyptr);
}
else
{
smsLog(pMac, LOGE, "Empty rsp message for meas "
"(PACKET_COALESCING_FILTER_MATCH_COUNT_RSP), nothing to process");
}
break;
#endif // WLAN_FEATURE_PACKET_FILTERING
case eWNI_SME_PRE_SWITCH_CHL_IND:
if(pMsg->bodyptr)
{
status = sme_HandlePreChannelSwitchInd(pMac,pMsg->bodyptr);
vos_mem_free(pMsg->bodyptr);
}
else
{
smsLog(pMac, LOGE, "Empty rsp message for meas "
"(eWNI_SME_PRE_SWITCH_CHL_IND), nothing to process");
}
break;
case eWNI_SME_CC_CHANGE_IND:
if(pMsg->bodyptr)
{
status = sme_handle_cc_change_ind(pMac,pMsg->bodyptr);
vos_mem_free(pMsg->bodyptr);
}
else
{
smsLog(pMac, LOGE, "Empty rsp message for meas "
"(eWNI_SME_CC_CHANGE_IND), nothing to process");
}
break;
case eWNI_SME_POST_SWITCH_CHL_IND:
{
status = sme_HandlePostChannelSwitchInd(pMac);
break;
}
#ifdef WLAN_WAKEUP_EVENTS
case eWNI_SME_WAKE_REASON_IND:
MTRACE(vos_trace(VOS_MODULE_ID_SME, TRACE_CODE_SME_RX_WDA_MSG,
NO_SESSION, pMsg->type));
if(pMsg->bodyptr)
{
status = sme_WakeReasonIndCallback((void *)pMac, pMsg->bodyptr);
vos_mem_free(pMsg->bodyptr);
}
else
{
smsLog(pMac, LOGE, "Empty rsp message for meas (eWNI_SME_WAKE_REASON_IND), nothing to process");
}
break;
#endif // WLAN_WAKEUP_EVENTS
#ifdef FEATURE_WLAN_TDLS
/*
* command received from PE, SME tdls msg processor shall be called
* to process commands received from PE
*/
case eWNI_SME_TDLS_SEND_MGMT_RSP:
case eWNI_SME_TDLS_ADD_STA_RSP:
case eWNI_SME_TDLS_DEL_STA_RSP:
case eWNI_SME_TDLS_DEL_STA_IND:
case eWNI_SME_TDLS_DEL_ALL_PEER_IND:
case eWNI_SME_MGMT_FRM_TX_COMPLETION_IND:
case eWNI_SME_TDLS_LINK_ESTABLISH_RSP:
case eWNI_SME_TDLS_SHOULD_DISCOVER:
case eWNI_SME_TDLS_SHOULD_TEARDOWN:
case eWNI_SME_TDLS_PEER_DISCONNECTED:
{
if (pMsg->bodyptr)
{
status = tdlsMsgProcessor(pMac, pMsg->type, pMsg->bodyptr);
vos_mem_free(pMsg->bodyptr);
}
else
{
smsLog( pMac, LOGE,
"Empty rsp message for TDLS, nothing to process");
}
break;
}
#endif
#ifdef WLAN_FEATURE_11W
case eWNI_SME_UNPROT_MGMT_FRM_IND:
if (pMsg->bodyptr)
{
sme_UnprotectedMgmtFrmInd(pMac, pMsg->bodyptr);
vos_mem_free(pMsg->bodyptr);
}
else
{
smsLog(pMac, LOGE, "Empty rsp message for meas (eWNI_SME_UNPROT_MGMT_FRM_IND), nothing to process");
}
break;
#endif
#if defined(FEATURE_WLAN_ESE) && defined(FEATURE_WLAN_ESE_UPLOAD)
case eWNI_SME_TSM_IE_IND:
{
if (pMsg->bodyptr)
{
sme_TsmIeInd(pMac, pMsg->bodyptr);
vos_mem_free(pMsg->bodyptr);
}
else
{
smsLog(pMac, LOGE,
"Empty rsp message for (eWNI_SME_TSM_IE_IND), nothing to process");
}
break;
}
#endif /* FEATURE_WLAN_ESE && FEATURE_WLAN_ESE_UPLOAD */
#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
case eWNI_SME_ROAM_SCAN_OFFLOAD_RSP:
status = csrRoamOffloadScanRspHdlr((void *)pMac, pMsg->bodyptr);
vos_mem_free(pMsg->bodyptr);
break;
#endif // WLAN_FEATURE_ROAM_SCAN_OFFLOAD
#ifdef WLAN_FEATURE_GTK_OFFLOAD
case eWNI_PMC_GTK_OFFLOAD_GETINFO_RSP:
MTRACE(vos_trace(VOS_MODULE_ID_SME, TRACE_CODE_SME_RX_WDA_MSG,
NO_SESSION, pMsg->type));
if (pMsg->bodyptr)
{
sme_ProcessGetGtkInfoRsp(pMac, pMsg->bodyptr);
vos_mem_free(pMsg->bodyptr);
}
else
{
smsLog(pMac, LOGE, "Empty rsp message for (eWNI_PMC_GTK_OFFLOAD_GETINFO_RSP), nothing to process");
}
break ;
#endif
#ifdef FEATURE_WLAN_LPHB
/* LPHB timeout indication arrived, send IND to client */
case eWNI_SME_LPHB_IND:
MTRACE(vos_trace(VOS_MODULE_ID_SME, TRACE_CODE_SME_RX_WDA_MSG,
NO_SESSION, pMsg->type));
if (pMac->sme.pLphbIndCb)
{
pMac->sme.pLphbIndCb(pMac->hHdd, pMsg->bodyptr);
}
vos_mem_free(pMsg->bodyptr);
break;
#endif /* FEATURE_WLAN_LPHB */
case eWNI_SME_IBSS_PEER_INFO_RSP:
MTRACE(vos_trace(VOS_MODULE_ID_SME, TRACE_CODE_SME_RX_WDA_MSG,
NO_SESSION, pMsg->type));
if (pMsg->bodyptr)
{
sme_IbssPeerInfoResponseHandleer(pMac, pMsg->bodyptr);
vos_mem_free(pMsg->bodyptr);
}
else
{
smsLog(pMac, LOGE,
"Empty rsp message for (eWNI_SME_IBSS_PEER_INFO_RSP),"
" nothing to process");
}
break ;
case eWNI_SME_READY_TO_SUSPEND_IND:
if (pMsg->bodyptr)
{
sme_ProcessReadyToSuspend(pMac, pMsg->bodyptr);
vos_mem_free(pMsg->bodyptr);
}
else
{
smsLog(pMac, LOGE, "Empty rsp message for (eWNI_SME_READY_TO_SUSPEND_IND), nothing to process");
}
break ;
#ifdef WLAN_FEATURE_EXTWOW_SUPPORT
case eWNI_SME_READY_TO_EXTWOW_IND:
if (pMsg->bodyptr)
{
sme_ProcessReadyToExtWoW(pMac, pMsg->bodyptr);
vos_mem_free(pMsg->bodyptr);
}
else
{
smsLog(pMac, LOGE, "Empty rsp message"
"for (eWNI_SME_READY_TO_EXTWOW_IND), nothing to process");
}
break ;
#endif
#ifdef FEATURE_WLAN_CH_AVOID
/* channel avoid message arrived, send IND to client */
case eWNI_SME_CH_AVOID_IND:
MTRACE(vos_trace(VOS_MODULE_ID_SME, TRACE_CODE_SME_RX_WDA_MSG,
NO_SESSION, pMsg->type));
if (pMac->sme.pChAvoidNotificationCb)
{
VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO,
"%s: CH avoid notification", __func__);
pMac->sme.pChAvoidNotificationCb(pMac->hHdd, pMsg->bodyptr);
}
vos_mem_free(pMsg->bodyptr);
break;
#endif /* FEATURE_WLAN_CH_AVOID */
#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
case eWNI_SME_AUTO_SHUTDOWN_IND:
if (pMac->sme.pAutoShutdownNotificationCb)
{
VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO,
"%s: Auto shutdown notification", __func__);
pMac->sme.pAutoShutdownNotificationCb();
}
vos_mem_free(pMsg->bodyptr);
break;
#endif
case eWNI_SME_DFS_RADAR_FOUND:
case eWNI_SME_DFS_CSAIE_TX_COMPLETE_IND:
{
status = dfsMsgProcessor(pMac, pMsg->type, pMsg->bodyptr);