blob: f65ed038dae4d8fcfb14ca8fafc1bc92b87ce005 [file] [log] [blame]
/*
* Copyright (c) 2012-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.
*/
/*===========================================================================
W L A N _ Q C T _ T L _ B A. C
OVERVIEW:
This software unit holds the implementation of the WLAN Transport Layer
Block Ack session support. Also included are the AMSDU de-aggregation
completion and MSDU re-ordering functionality.
The functions externalized by this module are to be called ONLY by the main
TL module or the HAL layer.
DEPENDENCIES:
Are listed for each API below.
===========================================================================*/
/*===========================================================================
EDIT HISTORY FOR FILE
This section contains comments describing changes made to the module.
Notice that changes are listed in reverse chronological order.
$Header$$DateTime$$Author$
when who what, where, why
---------- --- --------------------------------------------------------
2010-10-xx dli Change ucCIndex to point to the slot the next frame to be expected to fwd
2008-08-22 sch Update based on unit test
2008-07-31 lti Created module
===========================================================================*/
/*----------------------------------------------------------------------------
* Include Files
* -------------------------------------------------------------------------*/
#include "wlan_qct_tl.h"
#include "wlan_qct_wda.h"
#include "wlan_qct_tli.h"
#include "wlan_qct_tli_ba.h"
#include "wlan_qct_hal.h"
#include "wlan_qct_tl_trace.h"
#include "vos_trace.h"
#include "vos_types.h"
#include "vos_list.h"
#include "vos_lock.h"
#include "tlDebug.h"
/*----------------------------------------------------------------------------
* Preprocessor Definitions and Constants
* -------------------------------------------------------------------------*/
//#define WLANTL_REORDER_DEBUG_MSG_ENABLE
#define WLANTL_BA_REORDERING_AGING_TIMER 30 /* 30 millisec */
#define WLANTL_BA_MIN_FREE_RX_VOS_BUFFER 0 /* RX VOS buffer low threshold */
#define CSN_WRAP_AROUND_THRESHOLD 3000 /* CSN wrap around threshold */
const v_U8_t WLANTL_TID_2_AC[WLAN_MAX_TID] = { WLANTL_AC_BE,
WLANTL_AC_BK,
WLANTL_AC_BK,
WLANTL_AC_BE,
WLANTL_AC_VI,
WLANTL_AC_VI,
WLANTL_AC_VO,
WLANTL_AC_VO };
/*==========================================================================
FUNCTION tlReorderingAgingTimerExpierCB
DESCRIPTION
After aging timer expiered, all Qed frames have to be routed to upper
layer. Otherwise, there is possibilitied that ahng some frames
PARAMETERS
v_PVOID_t timerUdata Timer callback user data
Has information about where frames should be
routed
RETURN VALUE
VOS_STATUS_SUCCESS General success
VOS_STATUS_E_INVAL Invalid frame handle
============================================================================*/
v_VOID_t WLANTL_ReorderingAgingTimerExpierCB
(
v_PVOID_t timerUdata
)
{
WLANTL_TIMER_EXPIER_UDATA_T *expireHandle;
WLANTL_BAReorderType *ReorderInfo;
WLANTL_CbType *pTLHandle;
WLANTL_STAClientType* pClientSTA = NULL;
vos_pkt_t *vosDataBuff;
VOS_STATUS status = VOS_STATUS_SUCCESS;
v_U8_t ucSTAID;
v_U8_t ucTID;
v_U8_t opCode;
WLANTL_RxMetaInfoType wRxMetaInfo;
v_U32_t fwIdx = 0;
WDI_DS_RxMetaInfoType *pRxMetadata;
vos_pkt_t *pCurrent;
vos_pkt_t *pNext;
v_S15_t seq = 0;
v_U32_t cIndex;
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
if(NULL == timerUdata)
{
TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,"Timer Callback User data NULL"));
return;
}
expireHandle = (WLANTL_TIMER_EXPIER_UDATA_T *)timerUdata;
ucSTAID = (v_U8_t)expireHandle->STAID;
ucTID = expireHandle->TID;
if(WLANTL_STA_ID_INVALID(ucSTAID) || WLANTL_TID_INVALID(ucTID))
{
TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,"SID %d or TID %d is not valid",
ucSTAID, ucTID));
return;
}
pTLHandle = (WLANTL_CbType *)expireHandle->pTLHandle;
if(NULL == pTLHandle)
{
TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,"TL Control block NULL"));
return;
}
pClientSTA = pTLHandle->atlSTAClients[ucSTAID];
if( NULL == pClientSTA ){
TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
"TL:STA Memory not allocated STA ID: %d, %s", ucSTAID, __func__));
return;
}
ReorderInfo = &pClientSTA->atlBAReorderInfo[ucTID];
if(NULL == ReorderInfo)
{
TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,"Reorder data NULL, this could not happen SID %d, TID %d",
ucSTAID, ucTID));
return;
}
if(0 == pClientSTA->atlBAReorderInfo[ucTID].ucExists)
{
TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,"Reorder session doesn't exist SID %d, TID %d",
ucSTAID, ucTID));
return;
}
if(!VOS_IS_STATUS_SUCCESS(vos_lock_acquire(&ReorderInfo->reorderLock)))
{
TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,"WLANTL_ReorderingAgingTimerExpierCB, Get LOCK Fail"));
return;
}
if( 0 == pClientSTA->atlBAReorderInfo[ucTID].ucExists )
{
vos_lock_release(&ReorderInfo->reorderLock);
return;
}
opCode = WLANTL_OPCODE_FWDALL_DROPCUR;
vosDataBuff = NULL;
MTRACE(vos_trace(VOS_MODULE_ID_TL, TRACE_CODE_TL_REORDER_TIMER_EXP_CB,
ucSTAID , opCode ));
TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO,"BA timeout with %d pending frames, curIdx %d", ReorderInfo->pendingFramesCount, ReorderInfo->ucCIndex));
if(ReorderInfo->pendingFramesCount == 0)
{
if(!VOS_IS_STATUS_SUCCESS(vos_lock_release(&ReorderInfo->reorderLock)))
{
TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,"WLANTL_ReorderingAgingTimerExpierCB, Release LOCK Fail"));
}
return;
}
if(0 == ReorderInfo->ucCIndex)
{
fwIdx = ReorderInfo->winSize;
}
else
{
fwIdx = ReorderInfo->ucCIndex - 1;
}
cIndex = ReorderInfo->ucCIndex;
status = WLANTL_ChainFrontPkts(fwIdx, opCode,
&vosDataBuff, ReorderInfo, NULL);
ReorderInfo->ucCIndex = cIndex;
if(!VOS_IS_STATUS_SUCCESS(status))
{
TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,"Make packet chain fail with Qed frames %d", status));
if(!VOS_IS_STATUS_SUCCESS(vos_lock_release(&ReorderInfo->reorderLock)))
{
TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,"WLANTL_ReorderingAgingTimerExpierCB, Release LOCK Fail"));
}
return;
}
if(NULL == pClientSTA->pfnSTARx)
{
TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,"Callback function NULL with STAID %d", ucSTAID));
if(!VOS_IS_STATUS_SUCCESS(vos_lock_release(&ReorderInfo->reorderLock)))
{
TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,"WLANTL_ReorderingAgingTimerExpierCB, Release LOCK Fail"));
}
return;
}
if(NULL == vosDataBuff)
{
TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,"No pending frames, why triggered timer? "));
if(!VOS_IS_STATUS_SUCCESS(vos_lock_release(&ReorderInfo->reorderLock)))
{
TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,"WLANTL_ReorderingAgingTimerExpierCB, Release LOCK Fail"));
}
return;
}
/* Do replay check before giving packets to upper layer
replay check code : check whether replay check is needed or not */
if(VOS_TRUE == pClientSTA->ucIsReplayCheckValid) {
WLANTL_ReorderReplayCheck(pClientSTA, &vosDataBuff, ucTID);
}
pCurrent = vosDataBuff;
while (pCurrent != NULL)
{
vos_pkt_walk_packet_chain(pCurrent, &pNext, VOS_FALSE);
if (NULL == pNext)
{
/* This is the last packet, retrieve its sequence number */
pRxMetadata = WDI_DS_ExtractRxMetaData(VOS_TO_WPAL_PKT(pCurrent));
seq = WDA_GET_RX_REORDER_CUR_PKT_SEQ_NO(pRxMetadata);
}
pCurrent = pNext;
}
TLLOG1(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO,
"%s: Sending out Frame no: %d to HDD", __func__, seq));
ReorderInfo->LastSN = seq;
if( WLAN_STA_SOFTAP == pClientSTA->wSTADesc.wSTAType)
{
WLANTL_FwdPktToHDD( expireHandle->pAdapter, vosDataBuff, ucSTAID);
}
else
{
wRxMetaInfo.ucUP = ucTID;
pClientSTA->pfnSTARx(expireHandle->pAdapter,
vosDataBuff, ucSTAID, &wRxMetaInfo);
}
if(!VOS_IS_STATUS_SUCCESS(vos_lock_release(&ReorderInfo->reorderLock)))
{
TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,"WLANTL_ReorderingAgingTimerExpierCB, Release LOCK Fail"));
}
return;
}/*WLANTL_ReorderingAgingTimerExpierCB*/
/*----------------------------------------------------------------------------
INTERACTION WITH TL Main
---------------------------------------------------------------------------*/
/*==========================================================================
FUNCTION WLANTL_InitBAReorderBuffer
DESCRIPTION
Init Reorder buffer array
PARAMETERS
v_PVOID_t pvosGCtx Global context
RETURN VALUE
NONE
============================================================================*/
void WLANTL_InitBAReorderBuffer
(
v_PVOID_t pvosGCtx
)
{
WLANTL_CbType *pTLCb;
v_U32_t idx;
v_U32_t pIdx;
pTLCb = VOS_GET_TL_CB(pvosGCtx);
if (NULL == pTLCb)
{
TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
"%s: Invalid TL Control Block", __func__));
return;
}
for(idx = 0; idx < WLANTL_MAX_BA_SESSION; idx++)
{
pTLCb->reorderBufferPool[idx].isAvailable = VOS_TRUE;
for(pIdx = 0; pIdx < WLANTL_MAX_WINSIZE; pIdx++)
{
pTLCb->reorderBufferPool[idx].arrayBuffer[pIdx] = NULL;
pTLCb->reorderBufferPool[idx].ullReplayCounter[pIdx] = 0;
}
}
TLLOG4(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_LOW,"BA reorder buffer init"));
return;
}
/*==========================================================================
FUNCTION WLANTL_BaSessionAdd
DESCRIPTION
HAL notifies TL when a new Block Ack session is being added.
DEPENDENCIES
A BA session on Rx needs to be added in TL before the response is
being sent out
PARAMETERS
IN
pvosGCtx: pointer to the global vos context; a handle to TL's
control block can be extracted from its context
ucSTAId: identifier of the station for which requested the BA
session
ucTid: Tspec ID for the new BA session
uSize: size of the reordering window
RETURN VALUE
The result code associated with performing the operation
VOS_STATUS_E_INVAL: Input parameters are invalid
VOS_STATUS_E_FAULT: Station ID is outside array boundaries or pointer
to TL cb is NULL ; access would cause a page fault
VOS_STATUS_E_EXISTS: Station was not registered or BA session already
exists
VOS_STATUS_E_NOSUPPORT: Not yet supported
SIDE EFFECTS
============================================================================*/
VOS_STATUS
WLANTL_BaSessionAdd
(
v_PVOID_t pvosGCtx,
v_U16_t sessionID,
v_U32_t ucSTAId,
v_U8_t ucTid,
v_U32_t uBufferSize,
v_U32_t winSize,
v_U32_t SSN
)
{
WLANTL_CbType *pTLCb = NULL;
WLANTL_STAClientType *pClientSTA = NULL;
WLANTL_BAReorderType *reorderInfo;
v_U32_t idx;
VOS_STATUS status = VOS_STATUS_SUCCESS;
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/*------------------------------------------------------------------------
Sanity check
------------------------------------------------------------------------*/
if ( WLANTL_TID_INVALID(ucTid))
{
VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
"WLAN TL:Invalid parameter sent on WLANTL_BaSessionAdd");
return VOS_STATUS_E_INVAL;
}
if ( WLANTL_STA_ID_INVALID( ucSTAId ) )
{
VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
"WLAN TL:Invalid station id requested on WLANTL_BaSessionAdd");
return VOS_STATUS_E_FAULT;
}
/*------------------------------------------------------------------------
Extract TL control block and check existance
------------------------------------------------------------------------*/
pTLCb = VOS_GET_TL_CB(pvosGCtx);
if ( NULL == pTLCb )
{
VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
"WLAN TL:Invalid TL pointer from pvosGCtx on WLANTL_BaSessionAdd");
return VOS_STATUS_E_FAULT;
}
pClientSTA = pTLCb->atlSTAClients[ucSTAId];
if ( NULL == pClientSTA )
{
TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
"WLAN TL:Client Memory was not allocated on %s", __func__));
return VOS_STATUS_E_FAILURE;
}
if ( 0 == pClientSTA->ucExists )
{
VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
"WLAN TL:Station was not yet registered on WLANTL_BaSessionAdd");
return VOS_STATUS_E_EXISTS;
}
reorderInfo = &pClientSTA->atlBAReorderInfo[ucTid];
if (!VOS_IS_STATUS_SUCCESS(
vos_lock_acquire(&reorderInfo->reorderLock)))
{
TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
"%s: Release LOCK Fail", __func__));
return VOS_STATUS_E_FAULT;
}
/*------------------------------------------------------------------------
Verify that BA session was not already added
------------------------------------------------------------------------*/
if ( 0 != reorderInfo->ucExists )
{
reorderInfo->ucExists++;
VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
"WLAN TL:BA session already exists on WLANTL_BaSessionAdd");
vos_lock_release(&reorderInfo->reorderLock);
return VOS_STATUS_E_EXISTS;
}
/*------------------------------------------------------------------------
Initialize new BA session
------------------------------------------------------------------------*/
for(idx = 0; idx < WLANTL_MAX_BA_SESSION; idx++)
{
if(VOS_TRUE == pTLCb->reorderBufferPool[idx].isAvailable)
{
pClientSTA->atlBAReorderInfo[ucTid].reorderBuffer =
&(pTLCb->reorderBufferPool[idx]);
pTLCb->reorderBufferPool[idx].isAvailable = VOS_FALSE;
TLLOG4(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_LOW,"%dth buffer available, buffer PTR 0x%pK",
idx,
pClientSTA->atlBAReorderInfo[ucTid].reorderBuffer
));
break;
}
}
if (WLAN_STA_SOFTAP == pClientSTA->wSTADesc.wSTAType)
{
if (WLANTL_MAX_BA_SESSION == idx)
{
VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
"Number of Add BA request received more than allowed");
vos_lock_release(&reorderInfo->reorderLock);
return VOS_STATUS_E_NOSUPPORT;
}
}
reorderInfo->timerUdata.pAdapter = pvosGCtx;
reorderInfo->timerUdata.pTLHandle = (v_PVOID_t)pTLCb;
reorderInfo->timerUdata.STAID = ucSTAId;
reorderInfo->timerUdata.TID = ucTid;
/* BA aging timer */
status = vos_timer_init(&reorderInfo->agingTimer,
VOS_TIMER_TYPE_SW,
WLANTL_ReorderingAgingTimerExpierCB,
(v_PVOID_t)(&reorderInfo->timerUdata));
if(!VOS_IS_STATUS_SUCCESS(status))
{
TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
"%s: Timer Init Fail", __func__));
vos_lock_release(&reorderInfo->reorderLock);
return status;
}
pClientSTA->atlBAReorderInfo[ucTid].ucExists++;
pClientSTA->atlBAReorderInfo[ucTid].usCount = 0;
pClientSTA->atlBAReorderInfo[ucTid].ucCIndex = 0;
if(0 == winSize)
{
pClientSTA->atlBAReorderInfo[ucTid].winSize = WLANTL_MAX_WINSIZE;
}
else
{
pClientSTA->atlBAReorderInfo[ucTid].winSize = winSize;
}
pClientSTA->atlBAReorderInfo[ucTid].SSN = SSN;
pClientSTA->atlBAReorderInfo[ucTid].sessionID = sessionID;
pClientSTA->atlBAReorderInfo[ucTid].pendingFramesCount = 0;
pClientSTA->atlBAReorderInfo[ucTid].LastSN = SSN;
TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
"WLAN TL:New BA session added for STA: %d TID: %d",
ucSTAId, ucTid));
if(!VOS_IS_STATUS_SUCCESS(
vos_lock_release(&reorderInfo->reorderLock)))
{
TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
"%s: Release LOCK Fail", __func__));
return VOS_STATUS_E_FAULT;
}
return VOS_STATUS_SUCCESS;
}/* WLANTL_BaSessionAdd */
/*==========================================================================
FUNCTION WLANTL_BaSessionDel
DESCRIPTION
HAL notifies TL when a new Block Ack session is being deleted.
DEPENDENCIES
PARAMETERS
IN
pvosGCtx: pointer to the global vos context; a handle to TL's
control block can be extracted from its context
ucSTAId: identifier of the station for which requested the BA
session
ucTid: Tspec ID for the new BA session
RETURN VALUE
The result code associated with performing the operation
VOS_STATUS_E_INVAL: Input parameters are invalid
VOS_STATUS_E_FAULT: Station ID is outside array boundaries or pointer
to TL cb is NULL ; access would cause a page fault
VOS_STATUS_E_EXISTS: Station was not registered or BA session already
exists
VOS_STATUS_E_NOSUPPORT: Not yet supported
SIDE EFFECTS
============================================================================*/
VOS_STATUS
WLANTL_BaSessionDel
(
v_PVOID_t pvosGCtx,
v_U16_t ucSTAId,
v_U8_t ucTid
)
{
WLANTL_CbType* pTLCb = NULL;
WLANTL_STAClientType *pClientSTA = NULL;
vos_pkt_t* vosDataBuff = NULL;
VOS_STATUS vosStatus = VOS_STATUS_E_FAILURE;
VOS_STATUS lockStatus = VOS_STATUS_E_FAILURE;
WLANTL_BAReorderType* reOrderInfo = NULL;
WLANTL_RxMetaInfoType wRxMetaInfo;
v_U32_t fwIdx = 0;
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/*------------------------------------------------------------------------
Sanity check
------------------------------------------------------------------------*/
if ( WLANTL_TID_INVALID(ucTid))
{
VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
"WLAN TL:Invalid parameter sent on WLANTL_BaSessionDel");
return VOS_STATUS_E_INVAL;
}
if ( WLANTL_STA_ID_INVALID( ucSTAId ) )
{
VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
"WLAN TL:Invalid station id requested on WLANTL_BaSessionDel");
return VOS_STATUS_E_FAULT;
}
/*------------------------------------------------------------------------
Extract TL control block and check existance
------------------------------------------------------------------------*/
pTLCb = VOS_GET_TL_CB(pvosGCtx);
if ( NULL == pTLCb )
{
VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
"WLAN TL:Invalid TL pointer from pvosGCtx on WLANTL_BaSessionDel");
return VOS_STATUS_E_FAULT;
}
pClientSTA = pTLCb->atlSTAClients[ucSTAId];
if ( NULL == pClientSTA )
{
TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
"WLAN TL:Client Memory was not allocated on %s", __func__));
return VOS_STATUS_E_FAILURE;
}
if (( 0 == pClientSTA->ucExists ) &&
( 0 == pClientSTA->atlBAReorderInfo[ucTid].ucExists ))
{
VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_WARN,
"WLAN TL:Station was not yet registered on WLANTL_BaSessionDel");
return VOS_STATUS_E_EXISTS;
}
else if(( 0 == pClientSTA->ucExists ) &&
( 0 != pClientSTA->atlBAReorderInfo[ucTid].ucExists ))
{
VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_WARN,
"STA was deleted but BA info is still there, just remove BA info");
reOrderInfo = &pClientSTA->atlBAReorderInfo[ucTid];
reOrderInfo->reorderBuffer->isAvailable = VOS_TRUE;
memset(&reOrderInfo->reorderBuffer->arrayBuffer[0],
0,
WLANTL_MAX_WINSIZE * sizeof(v_PVOID_t));
vos_timer_destroy(&reOrderInfo->agingTimer);
memset(reOrderInfo, 0, sizeof(WLANTL_BAReorderType));
return VOS_STATUS_SUCCESS;
}
/*------------------------------------------------------------------------
Verify that BA session was added
------------------------------------------------------------------------*/
if ( 0 == pClientSTA->atlBAReorderInfo[ucTid].ucExists )
{
VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
"WLAN TL:BA session does not exists on WLANTL_BaSessionDel");
return VOS_STATUS_E_EXISTS;
}
/*------------------------------------------------------------------------
Send all pending packets to HDD
------------------------------------------------------------------------*/
reOrderInfo = &pClientSTA->atlBAReorderInfo[ucTid];
/*------------------------------------------------------------------------
Invalidate reorder info here. This ensures that no packets are
bufferd after reorder buffer is cleaned.
*/
lockStatus = vos_lock_acquire(&reOrderInfo->reorderLock);
if(!VOS_IS_STATUS_SUCCESS(lockStatus))
{
TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
"Unable to acquire reorder vos lock in %s", __func__));
return lockStatus;
}
pClientSTA->atlBAReorderInfo[ucTid].ucExists = 0;
TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
"WLAN TL: Fwd all packets to HDD on WLANTL_BaSessionDel"));
if(0 == reOrderInfo->ucCIndex)
{
fwIdx = reOrderInfo->winSize;
}
else
{
fwIdx = reOrderInfo->ucCIndex - 1;
}
if(0 != reOrderInfo->pendingFramesCount)
{
vosStatus = WLANTL_ChainFrontPkts(fwIdx,
WLANTL_OPCODE_FWDALL_DROPCUR,
&vosDataBuff, reOrderInfo, pTLCb);
}
if ((VOS_STATUS_SUCCESS == vosStatus) && (NULL != vosDataBuff))
{
TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
"WLAN TL: Chaining was successful sending all pkts to HDD : %x",
vosDataBuff ));
/* Do replay check before giving packets to upper layer
replay check code : check whether replay check is needed or not */
if(VOS_TRUE == pClientSTA->ucIsReplayCheckValid) {
WLANTL_ReorderReplayCheck(pClientSTA, &vosDataBuff, ucTid);
}
if ( WLAN_STA_SOFTAP == pClientSTA->wSTADesc.wSTAType )
{
WLANTL_FwdPktToHDD( pvosGCtx, vosDataBuff, ucSTAId);
}
else
{
wRxMetaInfo.ucUP = ucTid;
pClientSTA->pfnSTARx( pvosGCtx, vosDataBuff, ucSTAId,
&wRxMetaInfo );
}
}
/*------------------------------------------------------------------------
Delete reordering timer
------------------------------------------------------------------------*/
if(VOS_TIMER_STATE_RUNNING == vos_timer_getCurrentState(&reOrderInfo->agingTimer))
{
vosStatus = vos_timer_stop(&reOrderInfo->agingTimer);
if(!VOS_IS_STATUS_SUCCESS(vosStatus))
{
TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,"Timer stop fail: %d", vosStatus));
vos_lock_release(&reOrderInfo->reorderLock);
return vosStatus;
}
}
if(VOS_TIMER_STATE_STOPPED == vos_timer_getCurrentState(&reOrderInfo->agingTimer))
{
vosStatus = vos_timer_destroy(&reOrderInfo->agingTimer);
}
else
{
TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,"Timer is not stopped state current state is %d",
vos_timer_getCurrentState(&reOrderInfo->agingTimer)));
}
if ( VOS_STATUS_SUCCESS != vosStatus )
{
VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_WARN,
"WLAN TL:Failed to destroy reorder timer on WLANTL_BaSessionAdd");
}
/*------------------------------------------------------------------------
Delete session
------------------------------------------------------------------------*/
pClientSTA->atlBAReorderInfo[ucTid].usCount = 0;
pClientSTA->atlBAReorderInfo[ucTid].ucCIndex = 0;
reOrderInfo->winSize = 0;
reOrderInfo->SSN = 0;
reOrderInfo->sessionID = 0;
reOrderInfo->LastSN = 0;
MTRACE(vos_trace(VOS_MODULE_ID_TL, TRACE_CODE_TL_BA_SESSION_DEL,
ucSTAId, ucTid ));
TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
"WLAN TL: BA session deleted for STA: %d TID: %d",
ucSTAId, ucTid));
memset((v_U8_t *)(&reOrderInfo->reorderBuffer->arrayBuffer[0]),
0,
WLANTL_MAX_WINSIZE * sizeof(v_PVOID_t));
reOrderInfo->reorderBuffer->isAvailable = VOS_TRUE;
vos_lock_release(&reOrderInfo->reorderLock);
return VOS_STATUS_SUCCESS;
}/* WLANTL_BaSessionDel */
/*----------------------------------------------------------------------------
INTERACTION WITH TL main module
---------------------------------------------------------------------------*/
/*==========================================================================
AMSDU sub-frame processing module
==========================================================================*/
/*==========================================================================
FUNCTION WLANTL_AMSDUProcess
DESCRIPTION
Process A-MSDU sub-frame. Start of chain if marked as first frame.
Linked at the end of the existing AMSDU chain.
DEPENDENCIES
PARAMETERS
IN/OUT:
vosDataBuff: vos packet for the received data
outgoing contains the root of the chain for the rx
aggregated MSDU if the frame is marked as last; otherwise
NULL
IN
pvosGCtx: pointer to the global vos context; a handle to TL's
control block can be extracted from its context
pvBDHeader: pointer to the BD header
ucSTAId: Station ID
ucMPDUHLen: length of the MPDU header
usMPDULen: length of the MPDU
RETURN VALUE
The result code associated with performing the operation
VOS_STATUS_E_INVAL: invalid input parameters
VOS_STATUS_E_FAULT: pointer to TL cb is NULL ; access would cause a
page fault
VOS_STATUS_SUCCESS: Everything is good :)
Other values can be returned as a result of a function call, please check
corresponding API for more info.
SIDE EFFECTS
============================================================================*/
VOS_STATUS
WLANTL_AMSDUProcess
(
v_PVOID_t pvosGCtx,
vos_pkt_t** ppVosDataBuff,
v_PVOID_t pvBDHeader,
v_U8_t ucSTAId,
v_U8_t ucMPDUHLen,
v_U16_t usMPDULen
)
{
v_U8_t ucFsf; /* First AMSDU sub frame */
v_U8_t ucAef; /* Error in AMSDU sub frame */
WLANTL_CbType* pTLCb = NULL;
WLANTL_STAClientType *pClientSTA = NULL;
v_U8_t MPDUHeaderAMSDUHeader[WLANTL_MPDU_HEADER_LEN + TL_AMSDU_SUBFRM_HEADER_LEN];
v_U16_t subFrameLength;
v_U16_t paddingSize;
VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
v_U16_t MPDUDataOffset;
v_U16_t packetLength;
static v_U32_t numAMSDUFrames;
vos_pkt_t* vosDataBuff;
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/*------------------------------------------------------------------------
Sanity check
------------------------------------------------------------------------*/
if (( NULL == ppVosDataBuff ) || (NULL == *ppVosDataBuff) || ( NULL == pvBDHeader ) ||
( WLANTL_STA_ID_INVALID(ucSTAId)) )
{
VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
"WLAN TL:Invalid parameter sent on WLANTL_AMSDUProcess");
return VOS_STATUS_E_INVAL;
}
vosDataBuff = *ppVosDataBuff;
/*------------------------------------------------------------------------
Extract TL control block
------------------------------------------------------------------------*/
pTLCb = VOS_GET_TL_CB(pvosGCtx);
if ( NULL == pTLCb )
{
VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
"WLAN TL:Invalid TL pointer from pvosGCtx on WLANTL_AMSDUProcess");
return VOS_STATUS_E_FAULT;
}
pClientSTA = pTLCb->atlSTAClients[ucSTAId];
if ( NULL == pClientSTA )
{
TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
"WLAN TL:Client Memory was not allocated on %s", __func__));
return VOS_STATUS_E_FAILURE;
}
/*------------------------------------------------------------------------
Check frame
------------------------------------------------------------------------*/
ucAef = (v_U8_t)WDA_GET_RX_AEF( pvBDHeader );
ucFsf = (v_U8_t)WDA_GET_RX_ESF( pvBDHeader );
/* On Prima, MPDU data offset not includes BD header size */
MPDUDataOffset = (v_U16_t)WDA_GET_RX_MPDU_DATA_OFFSET(pvBDHeader);
if ( WLANHAL_RX_BD_AEF_SET == ucAef )
{
TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
"WLAN TL:Error in AMSDU - dropping entire chain"));
vos_pkt_return_packet(vosDataBuff);
*ppVosDataBuff = NULL;
return VOS_STATUS_SUCCESS; /*Not a transport error*/
}
if((0 != ucMPDUHLen) && ucFsf)
{
/*
* This is first AMSDU sub frame
* AMSDU Header should be removed
* MPDU header should be stored into context to recover next frames
*/
/* Assumed here Address4 is never part of AMSDU received at TL */
if (ucMPDUHLen > WLANTL_MPDU_HEADER_LEN)
{
TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,"MPDU Header length (%d) is greater",ucMPDUHLen));
vos_pkt_return_packet(vosDataBuff);
*ppVosDataBuff = NULL;
return VOS_STATUS_SUCCESS; /*Not a transport error*/
}
vStatus = vos_pkt_pop_head(vosDataBuff, MPDUHeaderAMSDUHeader, ucMPDUHLen + TL_AMSDU_SUBFRM_HEADER_LEN);
if(!VOS_IS_STATUS_SUCCESS(vStatus))
{
TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,"Pop MPDU AMSDU Header fail"));
vos_pkt_return_packet(vosDataBuff);
*ppVosDataBuff = NULL;
return VOS_STATUS_SUCCESS; /*Not a transport error*/
}
pClientSTA->ucMPDUHeaderLen = ucMPDUHLen;
vos_mem_copy(pClientSTA->aucMPDUHeader, MPDUHeaderAMSDUHeader, ucMPDUHLen);
/* AMSDU header stored to handle garbage data within next frame */
}
else
{
/* Trim garbage, size is frameLoop */
if(MPDUDataOffset > 0)
{
vStatus = vos_pkt_trim_head(vosDataBuff, MPDUDataOffset);
}
if(!VOS_IS_STATUS_SUCCESS(vStatus))
{
TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,"Trim Garbage Data fail"));
vos_pkt_return_packet(vosDataBuff);
*ppVosDataBuff = NULL;
return VOS_STATUS_SUCCESS; /*Not a transport error*/
}
/* Remove MPDU header and AMSDU header from the packet */
vStatus = vos_pkt_pop_head(vosDataBuff, MPDUHeaderAMSDUHeader, ucMPDUHLen + TL_AMSDU_SUBFRM_HEADER_LEN);
if(!VOS_IS_STATUS_SUCCESS(vStatus))
{
TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,"AMSDU Header Pop fail"));
vos_pkt_return_packet(vosDataBuff);
*ppVosDataBuff = NULL;
return VOS_STATUS_SUCCESS; /*Not a transport error*/
}
} /* End of henalding not first sub frame specific */
/* Put in MPDU header into all the frame */
vStatus = vos_pkt_push_head(vosDataBuff, pClientSTA->aucMPDUHeader, pClientSTA->ucMPDUHeaderLen);
if(!VOS_IS_STATUS_SUCCESS(vStatus))
{
TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,"MPDU Header Push back fail"));
vos_pkt_return_packet(vosDataBuff);
*ppVosDataBuff = NULL;
return VOS_STATUS_SUCCESS; /*Not a transport error*/
}
/* Find Padding and remove */
vos_mem_copy(&subFrameLength, MPDUHeaderAMSDUHeader + ucMPDUHLen + WLANTL_AMSDU_SUBFRAME_LEN_OFFSET, sizeof(v_U16_t));
subFrameLength = vos_be16_to_cpu(subFrameLength);
paddingSize = usMPDULen - ucMPDUHLen - subFrameLength - TL_AMSDU_SUBFRM_HEADER_LEN;
vos_pkt_get_packet_length(vosDataBuff, &packetLength);
if((paddingSize > 0) && (paddingSize < packetLength))
{
/* There is padding bits, remove it */
vos_pkt_trim_tail(vosDataBuff, paddingSize);
}
else if(0 == paddingSize)
{
/* No Padding bits */
/* Do Nothing */
}
else
{
/* Padding size is larger than Frame size, Actually negative */
/* Not a valid case, not a valid frame, drop it */
TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,"Padding Size is negative, no possible %d", paddingSize));
vos_pkt_return_packet(vosDataBuff);
*ppVosDataBuff = NULL;
return VOS_STATUS_SUCCESS; /*Not a transport error*/
}
numAMSDUFrames++;
if(0 == (numAMSDUFrames % 5000))
{
TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,"%u AMSDU frames arrived", numAMSDUFrames));
}
return VOS_STATUS_SUCCESS;
}/* WLANTL_AMSDUProcess */
/*==========================================================================
Re-ordering module
==========================================================================*/
/*==========================================================================
FUNCTION WLANTL_MSDUReorder
DESCRIPTION
MSDU reordering
DEPENDENCIES
PARAMETERS
IN
vosDataBuff: vos packet for the received data
pvBDHeader: pointer to the BD header
ucSTAId: Station ID
RETURN VALUE
The result code associated with performing the operation
VOS_STATUS_SUCCESS: Everything is good :)
SIDE EFFECTS
============================================================================*/
VOS_STATUS WLANTL_MSDUReorder
(
WLANTL_CbType *pTLCb,
vos_pkt_t **vosDataBuff,
v_PVOID_t pvBDHeader,
v_U8_t ucSTAId,
v_U8_t ucTid
)
{
WLANTL_BAReorderType *currentReorderInfo;
WLANTL_STAClientType *pClientSTA = NULL;
vos_pkt_t *vosPktIdx;
v_U8_t ucOpCode;
v_U8_t ucSlotIdx;
v_U8_t ucFwdIdx;
v_U16_t CSN;
v_U32_t ucCIndexOrig;
VOS_STATUS status = VOS_STATUS_SUCCESS;
VOS_STATUS lockStatus = VOS_STATUS_SUCCESS;
VOS_STATUS timerStatus = VOS_STATUS_SUCCESS;
VOS_TIMER_STATE timerState;
v_SIZE_t rxFree;
v_U64_t ullreplayCounter = 0; /* 48-bit replay counter */
v_U8_t ac;
v_U16_t reorderTime;
if((NULL == pTLCb) || (*vosDataBuff == NULL))
{
TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,"Invalid ARG pTLCb 0x%pK, vosDataBuff 0x%pK",
pTLCb, *vosDataBuff));
return VOS_STATUS_E_INVAL;
}
pClientSTA = pTLCb->atlSTAClients[ucSTAId];
if ( NULL == pClientSTA )
{
TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
"WLAN TL:Client Memory was not allocated on %s", __func__));
return VOS_STATUS_E_FAILURE;
}
currentReorderInfo = &pClientSTA->atlBAReorderInfo[ucTid];
lockStatus = vos_lock_acquire(&currentReorderInfo->reorderLock);
if(!VOS_IS_STATUS_SUCCESS(lockStatus))
{
TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,"WLANTL_MSDUReorder, Release LOCK Fail"));
return lockStatus;
}
if( pClientSTA->atlBAReorderInfo[ucTid].ucExists == 0 )
{
vos_lock_release(&currentReorderInfo->reorderLock);
return VOS_STATUS_E_INVAL;
}
ucOpCode = (v_U8_t)WDA_GET_RX_REORDER_OPCODE(pvBDHeader);
ucSlotIdx = (v_U8_t)WDA_GET_RX_REORDER_SLOT_IDX(pvBDHeader);
ucFwdIdx = (v_U8_t)WDA_GET_RX_REORDER_FWD_IDX(pvBDHeader);
CSN = (v_U16_t)WDA_GET_RX_REORDER_CUR_PKT_SEQ_NO(pvBDHeader);
/* Replay check code : check whether replay check is needed or not */
if(VOS_TRUE == pClientSTA->ucIsReplayCheckValid)
{
/* Getting 48-bit replay counter from the RX BD */
ullreplayCounter = WDA_DS_GetReplayCounter(pvBDHeader);
}
#ifdef WLANTL_REORDER_DEBUG_MSG_ENABLE
TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,"opCode %d SI %d, FI %d, CI %d seqNo %d", ucOpCode, ucSlotIdx, ucFwdIdx, currentReorderInfo->ucCIndex, CSN));
#else
TLLOG4(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_LOW,"opCode %d SI %d, FI %d, CI %d seqNo %d", ucOpCode, ucSlotIdx, ucFwdIdx, currentReorderInfo->ucCIndex, CSN));
#endif
// remember our current CI so that later we can tell if it advanced
ucCIndexOrig = currentReorderInfo->ucCIndex;
switch(ucOpCode)
{
case WLANTL_OPCODE_INVALID:
/* Do nothing just pass through current frame */
break;
case WLANTL_OPCODE_QCUR_FWDBUF:
if ((currentReorderInfo->LastSN > CSN) &&
!(currentReorderInfo->set_data_filter))
{
if ((currentReorderInfo->LastSN - CSN) < CSN_WRAP_AROUND_THRESHOLD)
{
//this frame is received after BA timer is expired, discard it
TLLOG1(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO,
"(QCUR_FWDBUF) dropping old frame, SN=%d LastSN=%d",
CSN, currentReorderInfo->LastSN));
if (vos_is_arp_pkt((*vosDataBuff)->pSkb, true))
vos_update_arp_rx_drop_reorder();
status = vos_pkt_return_packet(*vosDataBuff);
if (!VOS_IS_STATUS_SUCCESS(status))
{
TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
"(QCUR_FWDBUF) drop old frame fail %d", status));
}
*vosDataBuff = NULL;
lockStatus = vos_lock_release(&currentReorderInfo->reorderLock);
if (!VOS_IS_STATUS_SUCCESS(lockStatus))
{
TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
"WLANTL_MSDUReorder, Release LOCK Fail"));
return lockStatus;
}
return status;
}
}
currentReorderInfo->LastSN = CSN;
if(0 == currentReorderInfo->pendingFramesCount)
{
//This frame will be fwd'ed to the OS. The next slot is the one we expect next
currentReorderInfo->ucCIndex = (ucSlotIdx + 1) % currentReorderInfo->winSize;
lockStatus = vos_lock_release(&currentReorderInfo->reorderLock);
if(!VOS_IS_STATUS_SUCCESS(lockStatus))
{
TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,"WLANTL_MSDUReorder, Release LOCK Fail"));
return lockStatus;
}
return status;
}
status = WLANTL_QueueCurrent(currentReorderInfo,
vosDataBuff,
ucSlotIdx);
if(VOS_TRUE == pClientSTA->ucIsReplayCheckValid)
{
WLANTL_FillReplayCounter(currentReorderInfo,
ullreplayCounter, ucSlotIdx);
}
if(VOS_STATUS_E_RESOURCES == status)
{
MTRACE(vos_trace(VOS_MODULE_ID_TL, TRACE_CODE_TL_QUEUE_CURRENT,
currentReorderInfo->sessionID , ucOpCode ));
/* This is the case slot index is already cycle one route, route all the frames Qed */
vosPktIdx = NULL;
status = WLANTL_ChainFrontPkts(ucFwdIdx,
WLANTL_OPCODE_FWDALL_QCUR,
&vosPktIdx,
currentReorderInfo,
pTLCb);
if(!VOS_IS_STATUS_SUCCESS(status))
{
TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,"Make frame chain fail %d", status));
lockStatus = vos_lock_release(&currentReorderInfo->reorderLock);
if(!VOS_IS_STATUS_SUCCESS(lockStatus))
{
TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,"WLANTL_MSDUReorder, Release LOCK Fail"));
return lockStatus;
}
return status;
}
status = vos_pkt_chain_packet(vosPktIdx, *vosDataBuff, 1);
*vosDataBuff = vosPktIdx;
currentReorderInfo->pendingFramesCount = 0;
}
else
{
vosPktIdx = NULL;
status = WLANTL_ChainFrontPkts(ucFwdIdx,
WLANTL_OPCODE_QCUR_FWDBUF,
&vosPktIdx,
currentReorderInfo,
pTLCb);
if(!VOS_IS_STATUS_SUCCESS(status))
{
TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,"Make frame chain fail %d", status));
lockStatus = vos_lock_release(&currentReorderInfo->reorderLock);
if(!VOS_IS_STATUS_SUCCESS(lockStatus))
{
TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,"WLANTL_MSDUReorder, Release LOCK Fail"));
return lockStatus;
}
return status;
}
currentReorderInfo->ucCIndex = ucFwdIdx;
*vosDataBuff = vosPktIdx;
}
break;
case WLANTL_OPCODE_FWDBUF_FWDCUR:
vosPktIdx = NULL;
status = WLANTL_ChainFrontPkts(ucFwdIdx,
WLANTL_OPCODE_FWDBUF_FWDCUR,
&vosPktIdx,
currentReorderInfo,
pTLCb);
if(!VOS_IS_STATUS_SUCCESS(status))
{
TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,"Make frame chain fail %d", status));
lockStatus = vos_lock_release(&currentReorderInfo->reorderLock);
if(!VOS_IS_STATUS_SUCCESS(lockStatus))
{
TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,"WLANTL_MSDUReorder, Release LOCK Fail"));
return lockStatus;
}
return status;
}
if(NULL == vosPktIdx)
{
TLLOG4(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_LOW,"Nothing to chain, just send current frame"));
}
else
{
status = vos_pkt_chain_packet(vosPktIdx, *vosDataBuff, 1);
if(!VOS_IS_STATUS_SUCCESS(status))
{
TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,"Make frame chain with CUR frame fail %d",
status));
lockStatus = vos_lock_release(&currentReorderInfo->reorderLock);
if(!VOS_IS_STATUS_SUCCESS(lockStatus))
{
TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,"WLANTL_MSDUReorder, Release LOCK Fail"));
return lockStatus;
}
return status;
}
*vosDataBuff = vosPktIdx;
}
//ucFwdIdx is the slot this packet supposes to take but there is a hole there
//It looks that the chip will put the next packet into the slot ucFwdIdx.
currentReorderInfo->ucCIndex = ucFwdIdx;
break;
case WLANTL_OPCODE_QCUR:
if ((currentReorderInfo->LastSN > CSN) &&
!(currentReorderInfo->set_data_filter))
{
if ((currentReorderInfo->LastSN - CSN) < CSN_WRAP_AROUND_THRESHOLD)
{
// this frame is received after BA timer is expired, so disard it
TLLOG1(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO,
"(QCUR) dropping old frame, SN=%d LastSN=%d",
CSN, currentReorderInfo->LastSN));
status = vos_pkt_return_packet(*vosDataBuff);
if (!VOS_IS_STATUS_SUCCESS(status))
{
TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
"*** (QCUR) drop old frame fail %d", status));
}
*vosDataBuff = NULL;
lockStatus = vos_lock_release(&currentReorderInfo->reorderLock);
if (!VOS_IS_STATUS_SUCCESS(lockStatus))
{
TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
"WLANTL_MSDUReorder, Release LOCK Fail"));
return lockStatus;
}
return status;
}
}
status = WLANTL_QueueCurrent(currentReorderInfo,
vosDataBuff,
ucSlotIdx);
if(VOS_TRUE == pClientSTA->ucIsReplayCheckValid)
{
WLANTL_FillReplayCounter(currentReorderInfo,
ullreplayCounter, ucSlotIdx);
}
if(VOS_STATUS_E_RESOURCES == status)
{
MTRACE(vos_trace(VOS_MODULE_ID_TL, TRACE_CODE_TL_QUEUE_CURRENT,
currentReorderInfo->sessionID , ucOpCode ));
/* This is the case slot index is already cycle one route, route all the frames Qed */
vosPktIdx = NULL;
status = WLANTL_ChainFrontPkts(ucFwdIdx,
WLANTL_OPCODE_FWDALL_QCUR,
&vosPktIdx,
currentReorderInfo,
pTLCb);
if(!VOS_IS_STATUS_SUCCESS(status))
{
TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,"Make frame chain fail %d", status));
lockStatus = vos_lock_release(&currentReorderInfo->reorderLock);
if(!VOS_IS_STATUS_SUCCESS(lockStatus))
{
TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,"WLANTL_MSDUReorder, Release LOCK Fail"));
return lockStatus;
}
return status;
}
status = vos_pkt_chain_packet(vosPktIdx, *vosDataBuff, 1);
*vosDataBuff = vosPktIdx;
currentReorderInfo->pendingFramesCount = 0;
}
else
{
/* Since current Frame is Qed, no frame will be routed */
*vosDataBuff = NULL;
}
break;
case WLANTL_OPCODE_FWDBUF_QUEUECUR:
vosPktIdx = NULL;
status = WLANTL_ChainFrontPkts(ucFwdIdx,
WLANTL_OPCODE_FWDBUF_QUEUECUR,
&vosPktIdx,
currentReorderInfo,
pTLCb);
if(!VOS_IS_STATUS_SUCCESS(status))
{
TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,"Make chain with buffered frame fail %d",
status));
lockStatus = vos_lock_release(&currentReorderInfo->reorderLock);
if(!VOS_IS_STATUS_SUCCESS(lockStatus))
{
TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,"WLANTL_MSDUReorder, Release LOCK Fail"));
return lockStatus;
}
return status;
}
//This opCode means the window shift. Enforce the current Index
currentReorderInfo->ucCIndex = ucFwdIdx;
status = WLANTL_QueueCurrent(currentReorderInfo,
vosDataBuff,
ucSlotIdx);
if(VOS_TRUE == pClientSTA->ucIsReplayCheckValid)
{
WLANTL_FillReplayCounter(currentReorderInfo,
ullreplayCounter, ucSlotIdx);
}
if(VOS_STATUS_E_RESOURCES == status)
{
MTRACE(vos_trace(VOS_MODULE_ID_TL, TRACE_CODE_TL_QUEUE_CURRENT,
currentReorderInfo->sessionID , ucOpCode ));
vos_pkt_return_packet(vosPktIdx);
/* This is the case slot index is already cycle one route, route all the frames Qed */
vosPktIdx = NULL;
status = WLANTL_ChainFrontPkts(ucFwdIdx,
WLANTL_OPCODE_FWDALL_QCUR,
&vosPktIdx,
currentReorderInfo,
pTLCb);
if(!VOS_IS_STATUS_SUCCESS(status))
{
TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,"Make frame chain fail %d", status));
lockStatus = vos_lock_release(&currentReorderInfo->reorderLock);
if(!VOS_IS_STATUS_SUCCESS(lockStatus))
{
TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,"WLANTL_MSDUReorder, Release LOCK Fail"));
return lockStatus;
}
return status;
}
status = vos_pkt_chain_packet(vosPktIdx, *vosDataBuff, 1);
*vosDataBuff = vosPktIdx;
currentReorderInfo->pendingFramesCount = 0;
}
*vosDataBuff = vosPktIdx;
break;
case WLANTL_OPCODE_FWDBUF_DROPCUR:
vosPktIdx = NULL;
status = WLANTL_ChainFrontPkts(ucFwdIdx,
WLANTL_OPCODE_FWDBUF_DROPCUR,
&vosPktIdx,
currentReorderInfo,
pTLCb);
if(!VOS_IS_STATUS_SUCCESS(status))
{
TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,"Make chain with buffered frame fail %d",
status));
lockStatus = vos_lock_release(&currentReorderInfo->reorderLock);
if(!VOS_IS_STATUS_SUCCESS(lockStatus))
{
TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,"WLANTL_MSDUReorder, Release LOCK Fail"));
return lockStatus;
}
return status;
}
//Since BAR frame received, set the index to the right location
currentReorderInfo->ucCIndex = ucFwdIdx;
/* Current frame has to be dropped, BAR frame */
status = vos_pkt_return_packet(*vosDataBuff);
if(!VOS_IS_STATUS_SUCCESS(status))
{
TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,"Drop BAR frame fail %d",
status));
lockStatus = vos_lock_release(&currentReorderInfo->reorderLock);
if(!VOS_IS_STATUS_SUCCESS(lockStatus))
{
TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,"WLANTL_MSDUReorder, Release LOCK Fail"));
return lockStatus;
}
return status;
}
*vosDataBuff = vosPktIdx;
break;
case WLANTL_OPCODE_FWDALL_DROPCUR:
vosPktIdx = NULL;
status = WLANTL_ChainFrontPkts(ucFwdIdx,
WLANTL_OPCODE_FWDALL_DROPCUR,
&vosPktIdx,
currentReorderInfo,
pTLCb);
if(!VOS_IS_STATUS_SUCCESS(status))
{
TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,"Make chain with buffered frame fail %d",
status));
lockStatus = vos_lock_release(&currentReorderInfo->reorderLock);
if(!VOS_IS_STATUS_SUCCESS(lockStatus))
{
TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,"WLANTL_MSDUReorder, Release LOCK Fail"));
return lockStatus;
}
return status;
}
//Since BAR frame received and beyond cur window, set the index to the right location
currentReorderInfo->ucCIndex = 0;
status = vos_pkt_return_packet(*vosDataBuff);
if(!VOS_IS_STATUS_SUCCESS(status))
{
TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,"Drop BAR frame fail %d",
status));
lockStatus = vos_lock_release(&currentReorderInfo->reorderLock);
if(!VOS_IS_STATUS_SUCCESS(lockStatus))
{
TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,"WLANTL_MSDUReorder, Release LOCK Fail"));
return lockStatus;
}
return status;
}
*vosDataBuff = vosPktIdx;
break;
case WLANTL_OPCODE_FWDALL_QCUR:
vosPktIdx = NULL;
status = WLANTL_ChainFrontPkts(currentReorderInfo->winSize,
WLANTL_OPCODE_FWDALL_DROPCUR,
&vosPktIdx,
currentReorderInfo,
pTLCb);
if(!VOS_IS_STATUS_SUCCESS(status))
{
TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,"Make chain with buffered frame fail %d",
status));
lockStatus = vos_lock_release(&currentReorderInfo->reorderLock);
if(!VOS_IS_STATUS_SUCCESS(lockStatus))
{
TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,"WLANTL_MSDUReorder, Release LOCK Fail"));
return lockStatus;
}
return status;
}
status = WLANTL_QueueCurrent(currentReorderInfo,
vosDataBuff,
ucSlotIdx);
if(VOS_TRUE == pClientSTA->ucIsReplayCheckValid)
{
WLANTL_FillReplayCounter(currentReorderInfo,
ullreplayCounter, ucSlotIdx);
}
if(VOS_STATUS_E_RESOURCES == status)
{
MTRACE(vos_trace(VOS_MODULE_ID_TL, TRACE_CODE_TL_QUEUE_CURRENT,
currentReorderInfo->sessionID , ucOpCode ));
}
if(!VOS_IS_STATUS_SUCCESS(status))
{
TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,"Q Current frame fail %d",
status));
lockStatus = vos_lock_release(&currentReorderInfo->reorderLock);
if(!VOS_IS_STATUS_SUCCESS(lockStatus))
{
TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,"WLANTL_MSDUReorder, Release LOCK Fail"));
return lockStatus;
}
return status;
}
currentReorderInfo->ucCIndex = ucSlotIdx;
*vosDataBuff = vosPktIdx;
break;
case WLANTL_OPCODE_TEARDOWN:
// do we have a procedure in place to teardown BA?
// fall through to drop the current packet
case WLANTL_OPCODE_DROPCUR:
vos_pkt_return_packet(*vosDataBuff);
*vosDataBuff = NULL;
break;
default:
break;
}
/* Check the available VOS RX buffer size
* If remaining VOS RX buffer is too few, have to make space
* Route all the Qed frames upper layer
* Otherwise, RX thread could be stall */
vos_pkt_get_available_buffer_pool(VOS_PKT_TYPE_RX_RAW, &rxFree);
if(WLANTL_BA_MIN_FREE_RX_VOS_BUFFER >= rxFree)
{
TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO, "RX Free: %d", rxFree));
TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO, "RX free buffer count is too low, Pending frame count is %d",
currentReorderInfo->pendingFramesCount));
vosPktIdx = NULL;
status = WLANTL_ChainFrontPkts(ucFwdIdx,
WLANTL_OPCODE_FWDALL_DROPCUR,
&vosPktIdx,
currentReorderInfo,
pTLCb);
if(!VOS_IS_STATUS_SUCCESS(status))
{
TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,"Make frame chain fail %d", status));
lockStatus = vos_lock_release(&currentReorderInfo->reorderLock);
if(!VOS_IS_STATUS_SUCCESS(lockStatus))
{
TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,"WLANTL_MSDUReorder, Release LOCK Fail"));
return lockStatus;
}
return status;
}
if(NULL != *vosDataBuff)
{
TLLOG4(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_LOW,"Already something, Chain it"));
vos_pkt_chain_packet(*vosDataBuff, vosPktIdx, 1);
}
else
{
*vosDataBuff = vosPktIdx;
}
currentReorderInfo->pendingFramesCount = 0;
}
/*
* Current aging timer logic:
* 1) if we forwarded any packets and the timer is running:
* stop the timer
* 2) if there are packets queued and the timer is not running:
* start the timer
* 3) if timer is running and no pending frame:
* stop the timer
*/
timerState = vos_timer_getCurrentState(&currentReorderInfo->agingTimer);
if ((VOS_TIMER_STATE_RUNNING == timerState) &&
((ucCIndexOrig != currentReorderInfo->ucCIndex) ||
(0 == currentReorderInfo->pendingFramesCount)))
{
TLLOG4(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_LOW,"HOLE filled, Pending Frames Count %d",
currentReorderInfo->pendingFramesCount));
// we forwarded some packets so stop aging the current hole
timerStatus = vos_timer_stop(&currentReorderInfo->agingTimer);
timerState = VOS_TIMER_STATE_STOPPED;
// ignore the returned status since there is a race condition
// whereby between the time we called getCurrentState() and the
// time we call stop() the timer could have fired. In that case
// stop() will return an error, but we don't care since the
// timer has stopped
}
if (currentReorderInfo->pendingFramesCount > 0)
{
if (VOS_TIMER_STATE_STOPPED == timerState)
{
TLLOG4(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_LOW,"There is a new HOLE, Pending Frames Count %d",
currentReorderInfo->pendingFramesCount));
ac = WLANTL_TID_2_AC[ucTid];
if (WLANTL_AC_INVALID(ac))
{
reorderTime = WLANTL_BA_REORDERING_AGING_TIMER;
TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,"Invalid AC %d using default reorder time %d",
ac, reorderTime));
}
else
{
reorderTime = pTLCb->tlConfigInfo.ucReorderAgingTime[ac];
}
timerStatus = vos_timer_start(&currentReorderInfo->agingTimer,
reorderTime);
if(!VOS_IS_STATUS_SUCCESS(timerStatus))
{
TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,"Timer start fail: %d", timerStatus));
lockStatus = vos_lock_release(&currentReorderInfo->reorderLock);
if(!VOS_IS_STATUS_SUCCESS(lockStatus))
{
TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,"WLANTL_MSDUReorder, Release LOCK Fail"));
return lockStatus;
}
return timerStatus;
}
}
else
{
// we didn't forward any packets and the timer was already
// running so we're still aging the same hole
TLLOG4(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_LOW,"Still HOLE, Pending Frames Count %d",
currentReorderInfo->pendingFramesCount));
}
}
lockStatus = vos_lock_release(&currentReorderInfo->reorderLock);
if(!VOS_IS_STATUS_SUCCESS(lockStatus))
{
TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,"WLANTL_MSDUReorder, Release LOCK Fail"));
return lockStatus;
}
return VOS_STATUS_SUCCESS;
}/* WLANTL_MSDUReorder */
/*==========================================================================
Utility functions
==========================================================================*/
/*==========================================================================
FUNCTION WLANTL_QueueCurrent
DESCRIPTION
It will queue a packet at a given slot index in the MSDU reordering list.
DEPENDENCIES
PARAMETERS
IN
pwBaReorder: pointer to the BA reordering session info
vosDataBuff: data buffer to be queued
ucSlotIndex: slot index
RETURN VALUE
The result code associated with performing the operation
VOS_STATUS_SUCCESS: Everything is OK
SIDE EFFECTS
============================================================================*/
VOS_STATUS WLANTL_QueueCurrent
(
WLANTL_BAReorderType* pwBaReorder,
vos_pkt_t** vosDataBuff,
v_U8_t ucSlotIndex
)
{
VOS_STATUS status = VOS_STATUS_SUCCESS;
TLLOG4(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_LOW,"vos Packet has to be Qed 0x%pK",
*vosDataBuff));
if(NULL != pwBaReorder->reorderBuffer->arrayBuffer[ucSlotIndex])
{
MTRACE(vos_trace(VOS_MODULE_ID_TL, TRACE_CODE_TL_QUEUE_CURRENT,
pwBaReorder->sessionID , pwBaReorder->pendingFramesCount ));
MTRACE(vos_trace(VOS_MODULE_ID_TL, TRACE_CODE_TL_QUEUE_CURRENT,
pwBaReorder->sessionID , ucSlotIndex ));
TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO,"One Cycle rounded, lost many frames already, not in Q %d",
pwBaReorder->pendingFramesCount));
return VOS_STATUS_E_RESOURCES;
}
pwBaReorder->reorderBuffer->arrayBuffer[ucSlotIndex] =
(v_PVOID_t)(*vosDataBuff);
pwBaReorder->pendingFramesCount++;
TLLOG4(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_LOW,"Assigned, Pending Frames %d at slot %d, dataPtr 0x%x",
pwBaReorder->pendingFramesCount,
ucSlotIndex,
pwBaReorder->reorderBuffer->arrayBuffer[ucSlotIndex]));
return status;
}/*WLANTL_QueueCurrent*/
/*==========================================================================
FUNCTION WLANTL_ChainFrontPkts
DESCRIPTION
It will remove all the packets from the front of a vos list and chain
them to a vos pkt .
DEPENDENCIES
PARAMETERS
IN
ucCount: number of packets to extract
pwBaReorder: pointer to the BA reordering session info
OUT
vosDataBuff: data buffer containing the extracted chain of packets
RETURN VALUE
The result code associated with performing the operation
VOS_STATUS_SUCCESS: Everything is OK
SIDE EFFECTS
============================================================================*/
VOS_STATUS WLANTL_ChainFrontPkts
(
v_U32_t fwdIndex,
v_U8_t opCode,
vos_pkt_t **vosDataBuff,
WLANTL_BAReorderType *pwBaReorder,
WLANTL_CbType *pTLCb
)
{
VOS_STATUS status = VOS_STATUS_SUCCESS;
v_U32_t idx;
v_PVOID_t currentDataPtr = NULL;
int negDetect;
#ifdef WLANTL_REORDER_DEBUG_MSG_ENABLE
#define WLANTL_OUT_OF_WINDOW_IDX 65
v_U32_t frameIdx[2] = {0, 0}, ffidx = fwdIndex, idx2 = WLANTL_OUT_OF_WINDOW_IDX;
int pending = pwBaReorder->pendingFramesCount, start = WLANTL_OUT_OF_WINDOW_IDX, end;
#endif
if(pwBaReorder->ucCIndex >= fwdIndex)
{
fwdIndex += pwBaReorder->winSize;
}
if((WLANTL_OPCODE_FWDALL_DROPCUR == opCode) ||
(WLANTL_OPCODE_FWDALL_QCUR == opCode))
{
fwdIndex = pwBaReorder->ucCIndex + pwBaReorder->winSize;
}
TLLOG4(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_LOW,"Current Index %d, FWD Index %d, reorderBuffer 0x%pK",
pwBaReorder->ucCIndex % pwBaReorder->winSize,
fwdIndex % pwBaReorder->winSize,
pwBaReorder->reorderBuffer));
negDetect = pwBaReorder->pendingFramesCount;
for(idx = pwBaReorder->ucCIndex; idx <= fwdIndex; idx++)
{
currentDataPtr =
pwBaReorder->reorderBuffer->arrayBuffer[idx % pwBaReorder->winSize];
if(NULL != currentDataPtr)
{
#ifdef WLANTL_REORDER_DEBUG_MSG_ENABLE
idx2 = (idx >= pwBaReorder->winSize) ? (idx - pwBaReorder->winSize) : idx;
frameIdx[idx2 / 32] |= 1 << (idx2 % 32);
if(start == WLANTL_OUT_OF_WINDOW_IDX) start = idx2;
#endif
TLLOG4(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_LOW,"There is buffered frame %d",
idx % pwBaReorder->winSize));
if(NULL == *vosDataBuff)
{
*vosDataBuff = (vos_pkt_t *)currentDataPtr;
TLLOG4(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_LOW,"This is new head %d",
idx % pwBaReorder->winSize));
}
else
{
TLLOG4(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_LOW,"There is bufered Just add %d",
idx % pwBaReorder->winSize));
vos_pkt_chain_packet(*vosDataBuff,
(vos_pkt_t *)currentDataPtr,
VOS_TRUE);
}
pwBaReorder->reorderBuffer->arrayBuffer[idx % pwBaReorder->winSize]
= NULL;
pwBaReorder->pendingFramesCount--;
negDetect--;
if(negDetect < 0)
{
TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,"This is not possible, some balance has problem"));
VOS_ASSERT(0);
return VOS_STATUS_E_FAULT;
}
TLLOG4(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_LOW,"Slot Index %d, set as NULL, Pending Frames %d",
idx % pwBaReorder->winSize,
pwBaReorder->pendingFramesCount
));
pwBaReorder->ucCIndex = (idx + 1) % pwBaReorder->winSize;
}
else
{
TLLOG4(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_LOW,"Empty Array %d",
idx % pwBaReorder->winSize));
}
TLLOG4(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_LOW,"Current Index %d, winSize %d",
pwBaReorder->ucCIndex,
pwBaReorder->winSize
));
}
#ifdef WLANTL_REORDER_DEBUG_MSG_ENABLE
end = idx2;
TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,"Fwd 0x%08X-%08X opCode %d fwdIdx %d windowSize %d pending frame %d fw no. %d from idx %d to %d",
frameIdx[1], frameIdx[0], opCode, ffidx, pwBaReorder->winSize, pending, pending - negDetect, start, end));
#endif
return status;
}/*WLANTL_ChainFrontPkts*/
/*==========================================================================
FUNCTION WLANTL_FillReplayCounter
DESCRIPTION
It will fill repaly counter at a given slot index in the MSDU reordering list.
DEPENDENCIES
PARAMETERS
IN
pwBaReorder : pointer to the BA reordering session info
replayCounter: replay counter to be filled
ucSlotIndex : slot index
RETURN VALUE
NONE
SIDE EFFECTS
NONE
============================================================================*/
void WLANTL_FillReplayCounter
(
WLANTL_BAReorderType* pwBaReorder,
v_U64_t ullreplayCounter,
v_U8_t ucSlotIndex
)
{
//BAMSGDEBUG("replay counter to be filled in Qed frames %llu",
//replayCounter, 0, 0);
pwBaReorder->reorderBuffer->ullReplayCounter[ucSlotIndex] = ullreplayCounter;
//BAMSGDEBUG("Assigned, replay counter Pending Frames %d at slot %d, replay counter[0x%llX]\n",
//pwBaReorder->pendingFramesCount,
//ucSlotIndex,
//pwBaReorder->reorderBuffer->ullReplayCounter);
return;
}/*WLANTL_FillReplayCounter*/
void WLANTL_ReorderReplayCheck(WLANTL_STAClientType *pClientSTA,
vos_pkt_t **vosDataBuff, v_U8_t ucTid)
{
vos_pkt_t *pVosCurPkt;
vos_pkt_t *pNextVosPkt;
vos_pkt_t *pVosHeadPkt = NULL;
vos_pkt_t *pfreeVosPkt = NULL;
v_U64_t prevReplayCounter = 0;
v_BOOL_t status;
pVosCurPkt = *vosDataBuff;
do {
vos_pkt_walk_packet_chain(pVosCurPkt, &pNextVosPkt, VOS_FALSE);
prevReplayCounter = pClientSTA->ullReplayCounter[ucTid];
status = WLANTL_IsReplayPacket(pVosCurPkt->pn_num,
prevReplayCounter);
if(VOS_FALSE == status) {
pClientSTA->ullReplayCounter[ucTid] = pVosCurPkt->pn_num;
pVosHeadPkt = pVosCurPkt;
} else {
VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
"%s: Non-AMSDU Drop the replay packet PN: [0x%llX]",
__func__, pVosCurPkt->pn_num);
pClientSTA->ulTotalReplayPacketsDetected++;
pfreeVosPkt = pVosCurPkt;
pfreeVosPkt->pNext = NULL;
vos_pkt_return_packet(pfreeVosPkt);
if (pVosHeadPkt != NULL) {
pVosHeadPkt->pNext = pNextVosPkt;
}
else {
*vosDataBuff = pNextVosPkt;
}
}
pVosCurPkt = pNextVosPkt;
} while (pVosCurPkt);
}