blob: 52439a2c0c43461ca866986272041af05a4303b7 [file] [log] [blame]
/*
* Copyright (c) 2012-2014, 2016-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.
*/
/*===========================================================================
L I M _ P 2 P . C
OVERVIEW:
This software unit holds the implementation of the WLAN Protocol Engine for
P2P.
===========================================================================*/
/*===========================================================================
EDIT HISTORY FOR FILE
This section contains comments describing changes made to the module.
Notice that changes are listed in reverse chronological order.
$Header$$DateTime$$Author$
when who what, where, why
---------- --- --------------------------------------------------------
2011-05-02 djindal Corrected file indentation and changed remain on channel
handling for concurrency.
===========================================================================*/
#include "limUtils.h"
#include "limSessionUtils.h"
#include "wlan_qct_wda.h"
#define PROBE_RSP_IE_OFFSET 36
#define BSSID_OFFSET 16
#define ADDR2_OFFSET 10
#define ACTION_OFFSET 24
/* A DFS channel can be ACTIVE for max 9000 msec, from the last
received Beacon/Prpbe Resp. */
#define MAX_TIME_TO_BE_ACTIVE_CHANNEL 9000
#define REMAIN_ON_CHANNEL_UNKNOWN_ACTION_CATEGORY 0x20
#define VENDOR_SPECIFIC_ELEMENT_ID 221
#define REMAIN_ON_CHANNEL_MSG_SIZE 55
#define REMAIN_ON_CHANNEL_FIRST_MARKER_FRAME 1
#define REMAIN_ON_CHANNEL_SECOND_MARKER_FRAME 2
void limRemainOnChnlSuspendLinkHdlr(tpAniSirGlobal pMac, eHalStatus status,
tANI_U32 *data);
void limRemainOnChnlSetLinkStat(tpAniSirGlobal pMac, eHalStatus status,
tANI_U32 *data, tpPESession psessionEntry);
void limExitRemainOnChannel(tpAniSirGlobal pMac, eHalStatus status,
tANI_U32 *data, tpPESession psessionEntry);
void limRemainOnChnRsp(tpAniSirGlobal pMac, eHalStatus status, tANI_U32 *data);
extern tSirRetStatus limSetLinkState(
tpAniSirGlobal pMac, tSirLinkState state,
tSirMacAddr bssId, tSirMacAddr selfMacAddr,
tpSetLinkStateCallback callback, void *callbackArg);
static tSirRetStatus limCreateSessionForRemainOnChn(tpAniSirGlobal pMac, tPESession **ppP2pSession);
eHalStatus limP2PActionCnf(tpAniSirGlobal pMac, void *pData);
/*----------------------------------------------------------------------------
*
* The function limSendRemainOnChannelDebugMarkerFrame, prepares Marker frame
* for Start and End of remain on channel with RemainOnChannelMsg as Vendor
* Specific information element of the frame.
*
*----------------------------------------------------------------------------*/
tSirRetStatus limSendRemainOnChannelDebugMarkerFrame(tpAniSirGlobal pMac,
tANI_U8 *remainOnChannelMsg)
{
tSirMacAddr magicMacAddr= {0x11, 0x22, 0x33, 0x44, 0x55, 0x66};
tANI_U32 nBytes, nPayload;
tSirRetStatus nSirStatus;
tANI_U8 *pFrame;
void *pPacket;
eHalStatus halstatus;
tANI_U8 txFlag = 0;
publicVendorSpecific *pPublicVendorSpecific;
pPublicVendorSpecific = vos_mem_malloc(sizeof(publicVendorSpecific));
if( pPublicVendorSpecific == NULL )
{
limLog( pMac, LOGE,
FL( "Unable to allocate memory for Vendor specific information"
" element" ) );
return eSIR_MEM_ALLOC_FAILED;
}
// Assigning Action category code as unknown as this is debug marker frame
pPublicVendorSpecific->category = REMAIN_ON_CHANNEL_UNKNOWN_ACTION_CATEGORY;
pPublicVendorSpecific->elementid = VENDOR_SPECIFIC_ELEMENT_ID;
pPublicVendorSpecific->length = strlen(remainOnChannelMsg);
nPayload = sizeof(publicVendorSpecific) + pPublicVendorSpecific->length;
nBytes = nPayload + sizeof( tSirMacMgmtHdr );
halstatus = palPktAlloc( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT,
( tANI_U16 )nBytes, ( void** ) &pFrame,
( void** ) &pPacket );
if ( ! HAL_STATUS_SUCCESS ( halstatus ) )
{
limLog( pMac, LOGE, FL("Failed to allocate %d bytes for a Remain"
" on channel action frame."), nBytes );
nSirStatus = eSIR_MEM_ALLOC_FAILED;
goto end;
}
vos_mem_zero( pFrame, nBytes );
// Populate frame with MAC header
nSirStatus = limPopulateMacHeader( pMac, pFrame, SIR_MAC_MGMT_FRAME,
SIR_MAC_MGMT_ACTION, magicMacAddr,
pMac->lim.gSelfMacAddr);
if ( eSIR_SUCCESS != nSirStatus )
{
limLog( pMac, LOGE, FL("Failed to populate the buffer descriptor for a"
" Action frame for remain on channel.") );
palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT,
( void* ) pFrame, ( void* ) pPacket );
goto end;
}
// Copy Public Vendor specific fields to frame's information element
vos_mem_copy( (pFrame + (sizeof( tSirMacMgmtHdr ))),
pPublicVendorSpecific, sizeof(publicVendorSpecific) );
// Copy Remain On channel message to Vendor Specific information field
vos_mem_copy( (pFrame + (nBytes - pPublicVendorSpecific->length)),
remainOnChannelMsg, pPublicVendorSpecific->length );
halstatus = halTxFrame( pMac, pPacket,
( tANI_U16 ) sizeof(tSirMacMgmtHdr) + nPayload,
HAL_TXRX_FRM_802_11_MGMT,
ANI_TXDIR_TODS,
7,//SMAC_SWBD_TX_TID_MGMT_HIGH,
limTxComplete, pFrame, txFlag );
if ( ! HAL_STATUS_SUCCESS ( halstatus ) )
{
limLog( pMac, LOGE, FL("could not send marker frame for"
" remain on channel!" ));
//Pkt will be freed up by the callback
nSirStatus = eSIR_FAILURE;
goto end;
}
nSirStatus = eSIR_SUCCESS;
end:
vos_mem_free( pPublicVendorSpecific );
return nSirStatus;
}
/*-------------------------------------------------------------------------
*
* This function forms message for start of remain on channel with channel
* number, duration and sequence number. This message is added as data of
* vendor specific information element of Debug Marker Frame. Message will
* be in form "START-REMAIN-ON-CHANNEL<first/second-frame>-CHN=<channel>"
* "-FOR-DUR=<duraion>-SEQ=<sequence-num>"
*
*-------------------------------------------------------------------------*/
eHalStatus limPrepareAndSendStartRemainOnChannelMsg(tpAniSirGlobal pMac,
tSirRemainOnChnReq *MsgRemainonChannel, tANI_U8 id)
{
tANI_U8 *startRemainOnChannelMsg;
eHalStatus status = eHAL_STATUS_SUCCESS;
startRemainOnChannelMsg = vos_mem_malloc( REMAIN_ON_CHANNEL_MSG_SIZE );
if( NULL == startRemainOnChannelMsg )
{
limLog(pMac, LOGE,
FL("Unable to allocate memory for remain on channel message"));
return eHAL_STATUS_FAILURE;
}
snprintf(startRemainOnChannelMsg, REMAIN_ON_CHANNEL_MSG_SIZE,
"START-REMAIN-ON-CHANNEL%d-CHN=%d-FOR-DUR=%d-SEQ=%d",
id, MsgRemainonChannel->chnNum, MsgRemainonChannel->duration,
pMac->lim.remOnChnSeqNum);
if( eSIR_FAILURE == limSendRemainOnChannelDebugMarkerFrame(pMac,
startRemainOnChannelMsg) )
{
limLog( pMac, LOGE,
"%s: Could not send %d debug marker frame at start"
" of remain on channel", __func__, id);
status = eHAL_STATUS_FAILURE;
}
vos_mem_free( startRemainOnChannelMsg );
return status;
}
/*----------------------------------------------------------------------------
*
* This function forms message for cancel of remain on channel. This message
* is added as data of Vendor Specific information element of debug marker
* frame.Message will be in form "CANCEL-REMAIN-ON-CHANNEL<first/second-frame>"
* "-SEQ=<sequence-num>"
*
*----------------------------------------------------------------------------*/
eHalStatus limPrepareAndSendCancelRemainOnChannelMsg(tpAniSirGlobal pMac,
tANI_U8 id)
{
tANI_U8 *cancelRemainOnChannelMsg;
eHalStatus status = eHAL_STATUS_SUCCESS;
cancelRemainOnChannelMsg = vos_mem_malloc( REMAIN_ON_CHANNEL_MSG_SIZE );
if( NULL == cancelRemainOnChannelMsg )
{
limLog( pMac, LOGE,
FL( "Unable to allocate memory for end of"
" remain on channel message" ));
return eHAL_STATUS_FAILURE;
}
snprintf(cancelRemainOnChannelMsg, REMAIN_ON_CHANNEL_MSG_SIZE,
"CANCEL-REMAIN-ON-CHANNEL%d-SEQ=%d",
id, pMac->lim.remOnChnSeqNum);
if( eSIR_FAILURE == limSendRemainOnChannelDebugMarkerFrame(pMac,
cancelRemainOnChannelMsg) )
{
limLog( pMac, LOGE,
"%s: Could not send %d marker frame to debug cancel"
" remain on channel", __func__, id);
status = eHAL_STATUS_FAILURE;
}
vos_mem_free( cancelRemainOnChannelMsg );
return status;
}
/*------------------------------------------------------------------
*
* Below function is callback function, it is called when
* WDA_SET_LINK_STATE_RSP is received from WDI. callback function for
* P2P of limSetLinkState
*
*------------------------------------------------------------------*/
void limSetLinkStateP2PCallback(tpAniSirGlobal pMac, void *callbackArg)
{
tSirRemainOnChnReq *MsgRemainonChannel = pMac->lim.gpLimRemainOnChanReq;
//Send Ready on channel indication to SME
if(pMac->lim.gpLimRemainOnChanReq)
{
limSendSmeRsp(pMac, eWNI_SME_REMAIN_ON_CHN_RDY_IND, eHAL_STATUS_SUCCESS,
pMac->lim.gpLimRemainOnChanReq->sessionId, 0);
if(pMac->lim.gDebugP2pRemainOnChannel)
{
if( eHAL_STATUS_SUCCESS == limPrepareAndSendStartRemainOnChannelMsg(
pMac,
MsgRemainonChannel,
REMAIN_ON_CHANNEL_SECOND_MARKER_FRAME) )
{
limLog( pMac, LOGE,
"%s: Successfully sent 2nd Marker frame "
"seq num = %d on start ROC", __func__,
pMac->lim.remOnChnSeqNum);
}
}
}
else
{
//This is possible in case remain on channel is aborted
limLog( pMac, LOGE, FL(" NULL pointer of gpLimRemainOnChanReq") );
}
}
/*------------------------------------------------------------------
*
* Remain on channel req handler. Initiate the INIT_SCAN, CHN_CHANGE
* and SET_LINK Request from SME, chnNum and duration to remain on channel.
*
*------------------------------------------------------------------*/
int limProcessRemainOnChnlReq(tpAniSirGlobal pMac, tANI_U32 *pMsg)
{
tSirRemainOnChnReq *MsgBuff = (tSirRemainOnChnReq *)pMsg;
pMac->lim.gpLimRemainOnChanReq = MsgBuff;
pMac->lim.gLimPrevMlmState = pMac->lim.gLimMlmState;
pMac->lim.gLimMlmState = eLIM_MLM_P2P_LISTEN_STATE;
pMac->lim.gTotalScanDuration = MsgBuff->duration;
/* 1st we need to suspend link with callback to initiate change channel */
limSuspendLink(pMac, eSIR_CHECK_LINK_TRAFFIC_BEFORE_SCAN,
limRemainOnChnlSuspendLinkHdlr, NULL);
return FALSE;
}
tSirRetStatus limCreateSessionForRemainOnChn(tpAniSirGlobal pMac, tPESession **ppP2pSession)
{
tSirRetStatus nSirStatus = eSIR_FAILURE;
tpPESession psessionEntry;
tANI_U8 sessionId;
tANI_U32 val;
if(pMac->lim.gpLimRemainOnChanReq && ppP2pSession)
{
if((psessionEntry = peCreateSession(pMac,
pMac->lim.gpLimRemainOnChanReq->selfMacAddr, &sessionId, 1)) == NULL)
{
limLog(pMac, LOGE, FL("Session Can not be created "));
/* send remain on chn failure */
return nSirStatus;
}
/* Store PE sessionId in session Table */
psessionEntry->peSessionId = sessionId;
/* Store SME session Id in sessionTable */
psessionEntry->smeSessionId = pMac->lim.gpLimRemainOnChanReq->sessionId;
psessionEntry->limSystemRole = eLIM_P2P_DEVICE_ROLE;
CFG_GET_STR( nSirStatus, pMac, WNI_CFG_SUPPORTED_RATES_11A,
psessionEntry->rateSet.rate, val , SIR_MAC_MAX_NUMBER_OF_RATES );
psessionEntry->rateSet.numRates = val;
CFG_GET_STR( nSirStatus, pMac, WNI_CFG_EXTENDED_OPERATIONAL_RATE_SET,
psessionEntry->extRateSet.rate, val,
WNI_CFG_EXTENDED_OPERATIONAL_RATE_SET_LEN );
psessionEntry->extRateSet.numRates = val;
sirCopyMacAddr(psessionEntry->selfMacAddr,
pMac->lim.gpLimRemainOnChanReq->selfMacAddr);
psessionEntry->currentOperChannel = pMac->lim.gpLimRemainOnChanReq->chnNum;
nSirStatus = eSIR_SUCCESS;
*ppP2pSession = psessionEntry;
}
return nSirStatus;
}
/*------------------------------------------------------------------
*
* limSuspenLink callback, on success link suspend, trigger change chn
*
*
*------------------------------------------------------------------*/
tSirRetStatus limRemainOnChnlChangeChnReq(tpAniSirGlobal pMac,
eHalStatus status, tANI_U32 *data)
{
tpPESession psessionEntry;
tANI_U8 sessionId = 0;
tSirRetStatus nSirStatus = eSIR_FAILURE;
if( NULL == pMac->lim.gpLimRemainOnChanReq )
{
//RemainOnChannel may have aborted
PELOGE(limLog( pMac, LOGE, FL(" gpLimRemainOnChanReq is NULL") );)
return nSirStatus;
}
/* The link is not suspended */
if (status != eHAL_STATUS_SUCCESS)
{
PELOGE(limLog( pMac, LOGE, FL(" Suspend link Failure ") );)
goto error;
}
if((psessionEntry = peFindSessionByBssid(
pMac,pMac->lim.gpLimRemainOnChanReq->selfMacAddr, &sessionId)) != NULL)
{
goto change_channel;
}
else /* Session Entry does not exist for given BSSId */
{
/* Try to Create a new session */
if(eSIR_SUCCESS != limCreateSessionForRemainOnChn(pMac, &psessionEntry))
{
limLog(pMac, LOGE, FL("Session Can not be created "));
/* send remain on chn failure */
goto error;
}
}
change_channel:
/* change channel to the requested by RemainOn Chn*/
limChangeChannelWithCallback(pMac,
pMac->lim.gpLimRemainOnChanReq->chnNum,
limRemainOnChnlSetLinkStat, NULL, psessionEntry);
return eSIR_SUCCESS;
error:
limRemainOnChnRsp(pMac,eHAL_STATUS_FAILURE, NULL);
return eSIR_FAILURE;
}
void limRemainOnChnlSuspendLinkHdlr(tpAniSirGlobal pMac, eHalStatus status,
tANI_U32 *data)
{
limRemainOnChnlChangeChnReq(pMac, status, data);
return;
}
/*------------------------------------------------------------------
*
* Set the LINK state to LISTEN to allow only PROBE_REQ and Action frames
*
*------------------------------------------------------------------*/
void limRemainOnChnlSetLinkStat(tpAniSirGlobal pMac, eHalStatus status,
tANI_U32 *data, tpPESession psessionEntry)
{
tSirRemainOnChnReq *MsgRemainonChannel = pMac->lim.gpLimRemainOnChanReq;
tSirMacAddr nullBssid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
if (status != eHAL_STATUS_SUCCESS)
{
limLog( pMac, LOGE, FL("Change channel not successful"));
goto error;
}
// Start timer here to come back to operating channel.
pMac->lim.p2pRemOnChanTimeStamp = vos_timer_get_system_time();
pMac->lim.gTotalScanDuration = MsgRemainonChannel->duration;
if (pMac->lim.gDebugP2pRemainOnChannel)
{
pMac->lim.remOnChnSeqNum++;
if( eHAL_STATUS_SUCCESS == limPrepareAndSendStartRemainOnChannelMsg(
pMac, MsgRemainonChannel,
REMAIN_ON_CHANNEL_FIRST_MARKER_FRAME) )
{
limLog( pMac, LOGE,
"%s: Successfully sent 1st marker frame with seq num = %d"
" on start ROC", __func__, pMac->lim.remOnChnSeqNum);
}
}
if ((limSetLinkState(pMac, MsgRemainonChannel->isProbeRequestAllowed?
eSIR_LINK_LISTEN_STATE:eSIR_LINK_SEND_ACTION_STATE,nullBssid,
pMac->lim.gSelfMacAddr, limSetLinkStateP2PCallback,
NULL)) != eSIR_SUCCESS)
{
limLog( pMac, LOGE, "Unable to change link state");
goto error;
}
return;
error:
limRemainOnChnRsp(pMac,eHAL_STATUS_FAILURE, NULL);
return;
}
/*------------------------------------------------------------------
*
* lim Insert NOA timer timeout callback - when timer fires, deactivate it and send
* scan rsp to csr/hdd
*
*------------------------------------------------------------------*/
void limProcessInsertSingleShotNOATimeout(tpAniSirGlobal pMac)
{
/* timeout means start NOA did not arrive; we need to deactivate and change the timer for
* future activations
*/
limDeactivateAndChangeTimer(pMac, eLIM_INSERT_SINGLESHOT_NOA_TIMER);
/* Even if insert NOA timedout, go ahead and process/send stored SME request */
limProcessRegdDefdSmeReqAfterNOAStart(pMac);
return;
}
/*-----------------------------------------------------------------
* lim Insert Timer callback function to check active DFS channels
* and convert them to passive channels if there was no
* beacon/proberesp for MAX_TIME_TO_BE_ACTIVE_CHANNEL time
*------------------------------------------------------------------*/
void limConvertActiveChannelToPassiveChannel(tpAniSirGlobal pMac )
{
v_TIME_t currentTime;
v_TIME_t lastTime = 0;
v_TIME_t timeDiff;
tANI_U8 i;
currentTime = vos_timer_get_system_time();
for (i = 1; i < SIR_MAX_24G_5G_CHANNEL_RANGE ; i++)
{
if ((pMac->lim.dfschannelList.timeStamp[i]) != 0)
{
lastTime = pMac->lim.dfschannelList.timeStamp[i];
if (currentTime >= lastTime)
{
timeDiff = (currentTime - lastTime);
}
else
{
timeDiff = (0xFFFFFFFF - lastTime) + currentTime;
}
if (timeDiff >= MAX_TIME_TO_BE_ACTIVE_CHANNEL)
{
limCovertChannelScanType( pMac, i,FALSE);
pMac->lim.dfschannelList.timeStamp[i] = 0;
}
}
}
/* lastTime is zero if there is no DFS active channels in the list.
* If this is non zero then we have active DFS channels so restart the timer.
*/
if (lastTime != 0)
{
if (tx_timer_activate(
&pMac->lim.limTimers.gLimActiveToPassiveChannelTimer)
!= TX_SUCCESS)
{
limLog(pMac, LOGE, FL("Could not activate Active to Passive Channel timer"));
}
}
return;
}
/*------------------------------------------------------------------
*
* limSetLinkState callback function.
*
*------------------------------------------------------------------*/
void limSetlinkStateCallback(tpAniSirGlobal pMac, void *callbackArg)
{
if(pMac->lim.gDebugP2pRemainOnChannel)
{
if (eHAL_STATUS_SUCCESS == limPrepareAndSendCancelRemainOnChannelMsg(
pMac,
REMAIN_ON_CHANNEL_SECOND_MARKER_FRAME))
{
limLog( pMac, LOGE,
"%s: Successfully sent 2nd marker frame with seq num=%d"
" on cancel ROC", __func__, pMac->lim.remOnChnSeqNum);
}
}
return;
}
/*------------------------------------------------------------------
*
* limchannelchange callback, on success channel change, set the
* link_state to LISTEN
*
*------------------------------------------------------------------*/
void limProcessRemainOnChnTimeout(tpAniSirGlobal pMac)
{
tpPESession psessionEntry;
tANI_U8 sessionId;
tSirMacAddr nullBssid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
if (NULL == pMac->lim.gpLimRemainOnChanReq)
{
limLog( pMac, LOGE, "No Remain on channel pending");
return;
}
if(pMac->lim.gDebugP2pRemainOnChannel)
{
if (eHAL_STATUS_SUCCESS == limPrepareAndSendCancelRemainOnChannelMsg(
pMac,
REMAIN_ON_CHANNEL_FIRST_MARKER_FRAME))
{
limLog( pMac, LOGE,
"%s: Successfully sent 1st marker frame with seqnum = %d"
" on cancel ROC", __func__, pMac->lim.remOnChnSeqNum);
}
}
/* get the previous valid LINK state */
if (limSetLinkState(pMac, eSIR_LINK_IDLE_STATE, nullBssid,
pMac->lim.gSelfMacAddr, limSetlinkStateCallback, NULL) != eSIR_SUCCESS)
{
limLog( pMac, LOGE, "Unable to change link state");
return;
}
if (pMac->lim.gLimMlmState != eLIM_MLM_P2P_LISTEN_STATE )
{
limRemainOnChnRsp(pMac,eHAL_STATUS_SUCCESS, NULL);
}
else
{
/* get the session */
if((psessionEntry = peFindSessionByBssid(
pMac,pMac->lim.gpLimRemainOnChanReq->selfMacAddr, &sessionId)) == NULL)
{
limLog(pMac, LOGE,
FL("Session Does not exist for given sessionID"));
goto error;
}
limExitRemainOnChannel(pMac, eHAL_STATUS_SUCCESS, NULL, psessionEntry);
return;
error:
limRemainOnChnRsp(pMac,eHAL_STATUS_FAILURE, NULL);
}
return;
}
/*------------------------------------------------------------------
*
* limchannelchange callback, on success channel change, set the link_state
* to LISTEN
*
*------------------------------------------------------------------*/
void limExitRemainOnChannel(tpAniSirGlobal pMac, eHalStatus status,
tANI_U32 *data, tpPESession psessionEntry)
{
if (status != eHAL_STATUS_SUCCESS)
{
PELOGE(limLog( pMac, LOGE, "Remain on Channel Failed");)
goto error;
}
//Set the resume channel to Any valid channel (invalid).
//This will instruct HAL to set it to any previous valid channel.
peSetResumeChannel(pMac, 0, 0);
limResumeLink(pMac, limRemainOnChnRsp, NULL);
return;
error:
limRemainOnChnRsp(pMac,eHAL_STATUS_FAILURE, NULL);
return;
}
/*------------------------------------------------------------------
*
* Send remain on channel respone: Success/ Failure
*
*------------------------------------------------------------------*/
void limRemainOnChnRsp(tpAniSirGlobal pMac, eHalStatus status, tANI_U32 *data)
{
tpPESession psessionEntry;
tANI_U8 sessionId;
tSirRemainOnChnReq *MsgRemainonChannel = pMac->lim.gpLimRemainOnChanReq;
tSirMacAddr nullBssid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
tANI_U32 txStatus = 0;
tSirTxBdStatus txBdStatus = {0};
if ( NULL == MsgRemainonChannel )
{
PELOGE(limLog( pMac, LOGP,
"%s: No Pointer for Remain on Channel Req", __func__);)
return;
}
limLog( pMac, LOG1, "Remain on channel rsp with status %d", status);
//Incase of the Remain on Channel Failure Case
//Cleanup Everything
if(eHAL_STATUS_FAILURE == status)
{
//Set the Link State to Idle
/* get the previous valid LINK state */
if (limSetLinkState(pMac, eSIR_LINK_IDLE_STATE, nullBssid,
pMac->lim.gSelfMacAddr, NULL, NULL) != eSIR_SUCCESS)
{
limLog( pMac, LOGE, "Unable to change link state");
}
SET_LIM_PROCESS_DEFD_MESGS(pMac, true);
}
/* delete the session */
if((psessionEntry = peFindSessionByBssid(pMac,
MsgRemainonChannel->selfMacAddr,&sessionId)) != NULL)
{
if ( eLIM_P2P_DEVICE_ROLE == psessionEntry->limSystemRole )
{
peDeleteSession( pMac, psessionEntry);
}
}
/* Post the meessage to Sme */
limSendSmeRsp(pMac, eWNI_SME_REMAIN_ON_CHN_RSP, status,
MsgRemainonChannel->sessionId, 0);
vos_mem_free(pMac->lim.gpLimRemainOnChanReq);
pMac->lim.gpLimRemainOnChanReq = NULL;
pMac->lim.gLimMlmState = pMac->lim.gLimPrevMlmState;
/* If remain on channel timer expired and action frame is pending then
* indicaiton confirmation with status failure */
if (pMac->lim.mgmtFrameSessionId != 0xff)
{
limLog(pMac, LOGE,
FL("Remain on channel expired, Action frame status failure"));
if (IS_FEATURE_SUPPORTED_BY_FW(ENHANCED_TXBD_COMPLETION))
limP2PActionCnf(pMac, &txBdStatus);
else
limP2PActionCnf(pMac, &txStatus);
}
return;
}
/*------------------------------------------------------------------
*
* Indicate the Mgmt Frame received to SME to HDD callback
* handle Probe_req/Action frame currently
*
*------------------------------------------------------------------*/
void limSendSmeMgmtFrameInd(
tpAniSirGlobal pMac, tANI_U16 sessionId,
tANI_U8 *pRxPacketInfo, tpPESession psessionEntry,
tANI_S8 rxRssi)
{
tpSirSmeMgmtFrameInd pSirSmeMgmtFrame = NULL;
tANI_U16 length;
tANI_U8 frameType;
tpSirMacMgmtHdr frame;
tANI_U32 frameLen;
tANI_U8 rfBand = 0;
tANI_U32 rxChannel;
frame = WDA_GET_RX_MAC_HEADER(pRxPacketInfo);
frameLen = WDA_GET_RX_PAYLOAD_LEN(pRxPacketInfo) + sizeof(tSirMacMgmtHdr);
length = sizeof(tSirSmeMgmtFrameInd) + frameLen;
frameType = frame->fc.subType;
rfBand = WDA_GET_RX_RFBAND(pRxPacketInfo);
rxChannel = WDA_GET_RX_CH( pRxPacketInfo );
pSirSmeMgmtFrame = vos_mem_malloc(length);
if (NULL == pSirSmeMgmtFrame)
{
limLog(pMac, LOGP,
FL("AllocateMemory failed for eWNI_SME_LISTEN_RSP"));
return;
}
vos_mem_set((void*)pSirSmeMgmtFrame, length, 0);
pSirSmeMgmtFrame->frameLen = frameLen;
pSirSmeMgmtFrame->sessionId = sessionId;
pSirSmeMgmtFrame->frameType = frameType;
pSirSmeMgmtFrame->rxRssi = rxRssi;
if (( IS_5G_BAND(rfBand)))
{
rxChannel = limUnmapChannel(rxChannel);
limLog(pMac, LOG1,
FL("rxChannel after unmapping is %d"), rxChannel);
if ( !rxChannel )
{
tpPESession pTempSessionEntry = limIsApSessionActive(pMac);
if(pMac->lim.gpLimRemainOnChanReq != NULL)
{
rxChannel = pMac->lim.gpLimRemainOnChanReq->chnNum;
limLog(pMac, LOG1,
FL("ROC timer is running."
" Assign ROC channel to rxChannel i.e., %d"), rxChannel);
}
else if ( (pTempSessionEntry != NULL) &&
(SIR_BAND_5_GHZ !=
limGetRFBand(pTempSessionEntry->currentOperChannel)) )
limLog(pMac, LOGW,
FL("No active p2p GO in 5GHz"
" but recvd Action frame in 5GHz"));
}
}
/*
* Work around to address LIM sending wrong channel to HDD for p2p action
* frames(In case of auto GO) recieved on 5GHz channel.
* As RXP has only 4bits to store the channel, we need some mechanism to
* to distinguish between 2.4Ghz/5GHz channel. if gLimRemainOnChannelTImer
* is not running and if we get a frame then pass the Go session
* operating channel to HDD. Some vendors create separate p2p interface
* after group formation. In that case LIM session entry will be NULL for
* p2p device address. So search for p2p go session and pass it's
* operating channel.
* Need to revisit this path in case of GO+CLIENT concurrency.
*/
if (NULL == pMac->lim.gpLimRemainOnChanReq)
{
tpPESession pTempSessionEntry = psessionEntry;
if( ( (NULL != pTempSessionEntry) ||
(pTempSessionEntry = limIsApSessionActive(pMac)) ) &&
(SIR_BAND_5_GHZ == limGetRFBand(pTempSessionEntry->currentOperChannel)) )
{
rxChannel = pTempSessionEntry->currentOperChannel;
limLog(pMac, LOG1,
FL("Invalid rxChannel."
" Assign GO session op channel to rxChannel i.e., %d"), rxChannel);
}
}
pSirSmeMgmtFrame->rxChan = rxChannel;
vos_mem_zero(pSirSmeMgmtFrame->frameBuf, frameLen);
vos_mem_copy(pSirSmeMgmtFrame->frameBuf, frame, frameLen);
if (pMac->mgmt_frame_ind_cb)
pMac->mgmt_frame_ind_cb(pSirSmeMgmtFrame);
else
{
limLog(pMac, LOGW,
FL("Management indication callback not registered!!"));
}
vos_mem_free(pSirSmeMgmtFrame);
return;
} /*** end limSendSmeListenRsp() ***/
eHalStatus limP2PActionCnf(tpAniSirGlobal pMac, void *pData)
{
tANI_U32 txCompleteSuccess;
tpSirTxBdStatus pTxBdStatus;
if (!pData)
{
limLog(pMac, LOG1,
FL(" pData is NULL"));
return eHAL_STATUS_FAILURE;
}
if (IS_FEATURE_SUPPORTED_BY_FW(ENHANCED_TXBD_COMPLETION))
{
pTxBdStatus = (tpSirTxBdStatus) pData;
txCompleteSuccess = pTxBdStatus->txCompleteStatus;
limLog(pMac, LOG1,
FL("txCompleteSuccess %d, Token %u, Session Id %d"),
txCompleteSuccess, pTxBdStatus->txBdToken,
pMac->lim.mgmtFrameSessionId);
}
else
{
txCompleteSuccess = *((tANI_U32*) pData);
limLog(pMac, LOG1,
FL(" %s txCompleteSuccess %d, Session Id %d"),
__func__, txCompleteSuccess, pMac->lim.mgmtFrameSessionId);
}
if (pMac->lim.mgmtFrameSessionId != 0xff)
{
/* The session entry might be invalid(0xff) action confirmation received after
* remain on channel timer expired */
limSendSmeRsp(pMac, eWNI_SME_ACTION_FRAME_SEND_CNF,
(txCompleteSuccess ? eSIR_SME_SUCCESS : eSIR_SME_SEND_ACTION_FAIL),
pMac->lim.mgmtFrameSessionId, 0);
pMac->lim.mgmtFrameSessionId = 0xff;
}
return eHAL_STATUS_SUCCESS;
}
void limSetHtCaps(tpAniSirGlobal pMac, tpPESession psessionEntry, tANI_U8 *pIeStartPtr,tANI_U32 nBytes)
{
v_U8_t *pIe=NULL;
tDot11fIEHTCaps dot11HtCap;
PopulateDot11fHTCaps(pMac, psessionEntry, &dot11HtCap);
pIe = limGetIEPtr(pMac,pIeStartPtr, nBytes,
DOT11F_EID_HTCAPS,ONE_BYTE);
limLog( pMac, LOG2, FL("pIe %pK dot11HtCap.supportedMCSSet[0]=0x%x"),
pIe, dot11HtCap.supportedMCSSet[0]);
if(pIe)
{
tHtCaps *pHtcap = (tHtCaps *)&pIe[2]; //convert from unpacked to packed structure
pHtcap->advCodingCap = dot11HtCap.advCodingCap;
pHtcap->supportedChannelWidthSet = dot11HtCap.supportedChannelWidthSet;
pHtcap->mimoPowerSave = dot11HtCap.mimoPowerSave;
pHtcap->greenField = dot11HtCap.greenField;
pHtcap->shortGI20MHz = dot11HtCap.shortGI20MHz;
pHtcap->shortGI40MHz = dot11HtCap.shortGI40MHz;
pHtcap->txSTBC = dot11HtCap.txSTBC;
pHtcap->rxSTBC = dot11HtCap.rxSTBC;
pHtcap->delayedBA = dot11HtCap.delayedBA ;
pHtcap->maximalAMSDUsize = dot11HtCap.maximalAMSDUsize;
pHtcap->dsssCckMode40MHz = dot11HtCap.dsssCckMode40MHz;
pHtcap->psmp = dot11HtCap.psmp;
pHtcap->stbcControlFrame = dot11HtCap.stbcControlFrame;
pHtcap->lsigTXOPProtection = dot11HtCap.lsigTXOPProtection;
pHtcap->maxRxAMPDUFactor = dot11HtCap.maxRxAMPDUFactor;
pHtcap->mpduDensity = dot11HtCap.mpduDensity;
vos_mem_copy((void *)pHtcap->supportedMCSSet,
(void *)(dot11HtCap.supportedMCSSet),
sizeof(pHtcap->supportedMCSSet));
pHtcap->pco = dot11HtCap.pco;
pHtcap->transitionTime = dot11HtCap.transitionTime;
pHtcap->mcsFeedback = dot11HtCap.mcsFeedback;
pHtcap->txBF = dot11HtCap.txBF;
pHtcap->rxStaggeredSounding = dot11HtCap.rxStaggeredSounding;
pHtcap->txStaggeredSounding = dot11HtCap.txStaggeredSounding;
pHtcap->rxZLF = dot11HtCap.rxZLF;
pHtcap->txZLF = dot11HtCap.txZLF;
pHtcap->implicitTxBF = dot11HtCap.implicitTxBF;
pHtcap->calibration = dot11HtCap.calibration;
pHtcap->explicitCSITxBF = dot11HtCap.explicitCSITxBF;
pHtcap->explicitUncompressedSteeringMatrix =
dot11HtCap.explicitUncompressedSteeringMatrix;
pHtcap->explicitBFCSIFeedback = dot11HtCap.explicitBFCSIFeedback;
pHtcap->explicitUncompressedSteeringMatrixFeedback =
dot11HtCap.explicitUncompressedSteeringMatrixFeedback;
pHtcap->explicitCompressedSteeringMatrixFeedback =
dot11HtCap.explicitCompressedSteeringMatrixFeedback;
pHtcap->csiNumBFAntennae = dot11HtCap.csiNumBFAntennae;
pHtcap->uncompressedSteeringMatrixBFAntennae =
dot11HtCap.uncompressedSteeringMatrixBFAntennae;
pHtcap->compressedSteeringMatrixBFAntennae =
dot11HtCap.compressedSteeringMatrixBFAntennae;
pHtcap->antennaSelection = dot11HtCap.antennaSelection;
pHtcap->explicitCSIFeedbackTx = dot11HtCap.explicitCSIFeedbackTx;
pHtcap->antennaIndicesFeedbackTx = dot11HtCap.antennaIndicesFeedbackTx;
pHtcap->explicitCSIFeedback = dot11HtCap.explicitCSIFeedback;
pHtcap->antennaIndicesFeedback = dot11HtCap.antennaIndicesFeedback;
pHtcap->rxAS = dot11HtCap.rxAS;
pHtcap->txSoundingPPDUs = dot11HtCap.txSoundingPPDUs;
}
}
void limSendP2PActionFrame(tpAniSirGlobal pMac, tpSirMsgQ pMsg)
{
tSirMbMsgP2p *pMbMsg = (tSirMbMsgP2p *)pMsg->bodyptr;
tANI_U32 nBytes;
tANI_U8 *pFrame;
void *pPacket;
eHalStatus halstatus;
tANI_U32 txFlag = 0;
tpSirMacFrameCtl pFc = (tpSirMacFrameCtl ) pMbMsg->data;
tANI_U8 noaLen = 0;
tANI_U8 noaStream[SIR_MAX_NOA_ATTR_LEN + (2*SIR_P2P_IE_HEADER_LEN)];
tANI_U8 origLen = 0;
tANI_U8 sessionId = 0;
v_U8_t *pP2PIe = NULL;
tpPESession psessionEntry;
v_U8_t *pPresenceRspNoaAttr = NULL;
v_U8_t *pNewP2PIe = NULL;
v_U16_t remainLen = 0;
#ifdef WLAN_FEATURE_11W
tpSirMacMgmtHdr pMacHdr;
tpSirMacActionFrameHdr pActionHdr;
#endif
nBytes = pMbMsg->msgLen - sizeof(tSirMbMsg);
limLog( pMac, LOG1, FL("sending pFc->type=%d pFc->subType=%d"),
pFc->type, pFc->subType);
psessionEntry = peFindSessionByBssid(pMac,
(tANI_U8*)pMbMsg->data + BSSID_OFFSET, &sessionId);
/* Check for session corresponding to ADDR2 As Supplicant is filling
ADDR2 with BSSID */
if( NULL == psessionEntry )
{
psessionEntry = peFindSessionByBssid(pMac,
(tANI_U8*)pMbMsg->data + ADDR2_OFFSET, &sessionId);
}
if( NULL == psessionEntry )
{
tANI_U8 isSessionActive = 0;
tANI_U8 i;
/* If we are not able to find psessionEntry entry, then try to find
active session, if found any active sessions then send the
action frame, If no active sessions found then drop the frame */
for (i =0; i < pMac->lim.maxBssId;i++)
{
psessionEntry = peFindSessionBySessionId(pMac,i);
if ( NULL != psessionEntry)
{
isSessionActive = 1;
break;
}
}
if( !isSessionActive )
{
limSendSmeRsp(pMac, eWNI_SME_ACTION_FRAME_SEND_CNF,
eHAL_STATUS_FAILURE, pMbMsg->sessionId, 0);
return;
}
}
if ((SIR_MAC_MGMT_FRAME == pFc->type)&&
((SIR_MAC_MGMT_PROBE_RSP == pFc->subType)||
(SIR_MAC_MGMT_ACTION == pFc->subType)))
{
//if this is a probe RSP being sent from wpa_supplicant
if (SIR_MAC_MGMT_PROBE_RSP == pFc->subType)
{
//get proper offset for Probe RSP
pP2PIe = limGetP2pIEPtr(pMac,
(tANI_U8*)pMbMsg->data + PROBE_RSP_IE_OFFSET,
nBytes - PROBE_RSP_IE_OFFSET);
while ((NULL != pP2PIe) && (SIR_MAC_MAX_IE_LENGTH == pP2PIe[1]))
{
remainLen = nBytes - (pP2PIe - (tANI_U8*)pMbMsg->data);
if (remainLen > 2)
{
pNewP2PIe = limGetP2pIEPtr(pMac,
pP2PIe+SIR_MAC_MAX_IE_LENGTH + 2, remainLen);
}
if (pNewP2PIe)
{
pP2PIe = pNewP2PIe;
pNewP2PIe = NULL;
}
else
{
break;
}
} //end of while
}
else
{
if (SIR_MAC_ACTION_VENDOR_SPECIFIC_CATEGORY ==
*((v_U8_t *)pMbMsg->data+ACTION_OFFSET))
{
tpSirMacP2PActionFrameHdr pActionHdr =
(tpSirMacP2PActionFrameHdr)((v_U8_t *)pMbMsg->data +
ACTION_OFFSET);
if (vos_mem_compare( pActionHdr->Oui,
SIR_MAC_P2P_OUI, SIR_MAC_P2P_OUI_SIZE ) &&
(SIR_MAC_ACTION_P2P_SUBTYPE_PRESENCE_RSP ==
pActionHdr->OuiSubType))
{ //In case of Presence RSP response
pP2PIe = limGetP2pIEPtr(pMac,
(v_U8_t *)pMbMsg->data + ACTION_OFFSET +
sizeof(tSirMacP2PActionFrameHdr),
(nBytes - ACTION_OFFSET -
sizeof(tSirMacP2PActionFrameHdr)));
if( NULL != pP2PIe )
{
//extract the presence of NoA attribute inside P2P IE
pPresenceRspNoaAttr =
limGetIEPtr(pMac,pP2PIe + SIR_P2P_IE_HEADER_LEN,
pP2PIe[1], SIR_P2P_NOA_ATTR,TWO_BYTE);
}
}
}
}
if (pP2PIe != NULL)
{
//get NoA attribute stream P2P IE
noaLen = limGetNoaAttrStream(pMac, noaStream, psessionEntry);
//need to append NoA attribute in P2P IE
if (noaLen > 0)
{
origLen = pP2PIe[1];
//if Presence Rsp has NoAttr
if (pPresenceRspNoaAttr)
{
v_U16_t noaAttrLen = pPresenceRspNoaAttr[1] |
(pPresenceRspNoaAttr[2]<<8);
/*One byte for attribute, 2bytes for length*/
origLen -= (noaAttrLen + 1 + 2);
//remove those bytes to copy
nBytes -= (noaAttrLen + 1 + 2);
//remove NoA from original Len
pP2PIe[1] = origLen;
}
if ((pP2PIe[1] + (tANI_U16)noaLen)> SIR_MAC_MAX_IE_LENGTH)
{
//Form the new NoA Byte array in multiple P2P IEs
noaLen = limGetNoaAttrStreamInMultP2pIes(pMac, noaStream,
noaLen,((pP2PIe[1] + (tANI_U16)noaLen)-
SIR_MAC_MAX_IE_LENGTH));
pP2PIe[1] = SIR_MAC_MAX_IE_LENGTH;
}
else
{
pP2PIe[1] += noaLen; //increment the length of P2P IE
}
nBytes += noaLen;
limLog( pMac, LOGE,
FL("noaLen=%d origLen=%d pP2PIe=%pK"
" nBytes=%d nBytesToCopy=%zu"),
noaLen,origLen, pP2PIe, nBytes,
((pP2PIe + origLen + 2) - (v_U8_t *)pMbMsg->data));
}
}
if (SIR_MAC_MGMT_PROBE_RSP == pFc->subType)
{
limSetHtCaps( pMac, psessionEntry, (tANI_U8*)pMbMsg->data + PROBE_RSP_IE_OFFSET,
nBytes - PROBE_RSP_IE_OFFSET);
}
if ((SIR_MAC_MGMT_ACTION == pFc->subType) &&
(0 != pMbMsg->wait))
{
if (pMac->lim.gpLimRemainOnChanReq == NULL)
{
limLog( pMac, LOGE,
FL("Failed to Send Action frame"));
limSendSmeRsp(pMac, eWNI_SME_ACTION_FRAME_SEND_CNF,
eHAL_STATUS_FAILURE, pMbMsg->sessionId, 0);
return;
}
}
}
// Ok-- try to allocate some memory:
halstatus = palPktAlloc( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT,
(tANI_U16)nBytes, ( void** ) &pFrame, (void**) &pPacket);
if ( ! HAL_STATUS_SUCCESS ( halstatus ) )
{
limLog( pMac, LOGE, FL("Failed to allocate %d bytes for a Probe"
" Request."), nBytes );
return;
}
// Paranoia:
vos_mem_set(pFrame, nBytes, 0);
if ((noaLen > 0) && (noaLen<(SIR_MAX_NOA_ATTR_LEN + SIR_P2P_IE_HEADER_LEN)))
{
// Add 2 bytes for length and Arribute field
v_U32_t nBytesToCopy = ((pP2PIe + origLen + 2 ) -
(v_U8_t *)pMbMsg->data);
vos_mem_copy(pFrame, pMbMsg->data, nBytesToCopy);
vos_mem_copy((pFrame + nBytesToCopy), noaStream, noaLen);
vos_mem_copy((pFrame + nBytesToCopy + noaLen),
pMbMsg->data + nBytesToCopy, nBytes - nBytesToCopy - noaLen);
}
else
{
vos_mem_copy(pFrame, pMbMsg->data, nBytes);
}
#ifdef WLAN_FEATURE_11W
pActionHdr = (tpSirMacActionFrameHdr) (pFrame + sizeof(tSirMacMgmtHdr));
pMacHdr = (tpSirMacMgmtHdr)pFrame;
/*
* Setting Protected bit only for Robust Action Frames
* This has to be based on the current Connection with the station
* limSetProtectedBit API will set the protected bit if connection is PMF
*/
if ((SIR_MAC_MGMT_ACTION == pFc->subType) &&
psessionEntry->limRmfEnabled && (!limIsGroupAddr(pMacHdr->da)) &&
lim_is_robust_mgmt_action_frame(pActionHdr->category)) {
/* All psession checks are already done at start */
limSetProtectedBit(pMac, psessionEntry, pMacHdr->da, pMacHdr);
}
#endif
/* Use BD rate 2 for all P2P related frames. As these frames need to go
* at OFDM rates. And BD rate2 we configured at 6Mbps.
*/
txFlag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME;
if (SIR_MAC_MGMT_ACTION == pFc->subType)
{
limLog( pMac, LOG1, FL("Sending Action Frame over WQ5"));
txFlag |= HAL_USE_FW_IN_TX_PATH;
}
if ( (SIR_MAC_MGMT_PROBE_RSP == pFc->subType) ||
(pMbMsg->noack)
)
{
halstatus = halTxFrame( pMac, pPacket, (tANI_U16)nBytes,
HAL_TXRX_FRM_802_11_MGMT, ANI_TXDIR_TODS,
7,/*SMAC_SWBD_TX_TID_MGMT_HIGH */ limTxComplete, pFrame,
txFlag );
if (!pMbMsg->noack)
{
limSendSmeRsp(pMac, eWNI_SME_ACTION_FRAME_SEND_CNF,
halstatus, pMbMsg->sessionId, 0);
}
pMac->lim.mgmtFrameSessionId = 0xff;
}
else
{
pMac->lim.mgmtFrameSessionId = 0xff;
halstatus = halTxFrameWithTxComplete( pMac, pPacket, (tANI_U16)nBytes,
HAL_TXRX_FRM_802_11_MGMT, ANI_TXDIR_TODS,
7,/*SMAC_SWBD_TX_TID_MGMT_HIGH */ limTxComplete, pFrame,
limP2PActionCnf, txFlag, pMac->lim.txBdToken++ );
if ( ! HAL_STATUS_SUCCESS ( halstatus ) )
{
limLog( pMac, LOGE, FL("could not send action frame!" ));
limSendSmeRsp(pMac, eWNI_SME_ACTION_FRAME_SEND_CNF, halstatus,
pMbMsg->sessionId, 0);
pMac->lim.mgmtFrameSessionId = 0xff;
}
else
{
pMac->lim.mgmtFrameSessionId = pMbMsg->sessionId;
limLog( pMac, LOG2, FL("lim.actionFrameSessionId = %u" ),
pMac->lim.mgmtFrameSessionId);
}
}
return;
}
void limAbortRemainOnChan(tpAniSirGlobal pMac)
{
limProcessRemainOnChnTimeout(pMac);
limLog( pMac, LOG1, FL("Abort ROC !!!" ));
return;
}
/* Power Save Related Functions */
tSirRetStatus __limProcessSmeNoAUpdate(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf)
{
tpP2pPsConfig pNoA;
tpP2pPsParams pMsgNoA;
tSirMsgQ msg;
pNoA = (tpP2pPsConfig) pMsgBuf;
pMsgNoA = vos_mem_malloc(sizeof( tP2pPsConfig ));
if (NULL == pMsgNoA)
{
limLog( pMac, LOGE,
FL( "Unable to allocate memory during NoA Update" ));
return eSIR_MEM_ALLOC_FAILED;
}
vos_mem_set((tANI_U8 *)pMsgNoA, sizeof(tP2pPsConfig), 0);
pMsgNoA->opp_ps = pNoA->opp_ps;
pMsgNoA->ctWindow = pNoA->ctWindow;
pMsgNoA->duration = pNoA->duration;
pMsgNoA->interval = pNoA->interval;
pMsgNoA->count = pNoA->count;
pMsgNoA->single_noa_duration = pNoA->single_noa_duration;
pMsgNoA->psSelection = pNoA->psSelection;
msg.type = WDA_SET_P2P_GO_NOA_REQ;
msg.reserved = 0;
msg.bodyptr = pMsgNoA;
msg.bodyval = 0;
if(eSIR_SUCCESS != wdaPostCtrlMsg(pMac, &msg))
{
limLog(pMac, LOGE, FL("halPostMsgApi failed"));
return eSIR_FAILURE;
}
return eSIR_SUCCESS;
} /*** end __limProcessSmeGoNegReq() ***/