| /* |
| * RxQueue.c |
| * |
| * Copyright(c) 1998 - 2010 Texas Instruments. All rights reserved. |
| * All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * |
| * * Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * * Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in |
| * the documentation and/or other materials provided with the |
| * distribution. |
| * * Neither the name Texas Instruments nor the names of its |
| * contributors may be used to endorse or promote products derived |
| * from this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| |
| /** \file RxQueue.c |
| * \brief RX Queue module that responsible to support re-ordering of received packets to upper layers. |
| * |
| * \see RxQueue.h |
| */ |
| #define __FILE_ID__ FILE_ID_98 |
| #include "tidef.h" |
| #include "osApi.h" |
| #include "report.h" |
| #include "RxBuf.h" |
| #include "TWDriver.h" |
| #include "public_descriptors.h" |
| #include "timer.h" |
| |
| /************************ static definition declaration *****************************/ |
| #define RX_QUEUE_ARRAY_SIZE 8 |
| #define RX_QUEUE_ARRAY_SIZE_BIT_MASK 0x7 /* RX_QUEUE_ARRAY_SIZE -1 */ |
| #define RX_QUEUE_WIN_SIZE RX_QUEUE_ARRAY_SIZE |
| #define BA_SESSION_TIME_TO_SLEEP (50) |
| |
| #define BA_SESSION_IS_A_BIGGER_THAN_B(A,B) (((((A)-(B)) & 0xFFF) < 0x7FF) && ((A)!=(B))) |
| #define BA_SESSION_IS_A_BIGGER_EQUAL_THAN_B(A,B) (((((A)-(B)) & 0xFFF) < 0x7FF)) |
| #define SEQ_NUM_WRAP 0x1000 |
| #define SEQ_NUM_MASK 0xFFF |
| |
| |
| /************************ static structures declaration *****************************/ |
| /* structure describe one entry of save packet information in the packet queue array */ |
| typedef struct |
| { |
| void *pPacket; /* Packet address of the packet */ |
| TI_STATUS tStatus; /* RxXfer status. */ |
| TI_UINT16 uFrameSn; |
| } TRxQueuePacketEntry; |
| |
| /* structure describe set of data that one Tid, also including the arras himself */ |
| typedef struct |
| { |
| /* array packets Entries */ |
| TRxQueuePacketEntry aPaketsQueue [RX_QUEUE_ARRAY_SIZE]; |
| /* TID BA state */ |
| TI_BOOL aTidBaEstablished; |
| /* index that winStar point on */ |
| TI_UINT32 aWinStartArrayInex; |
| /* windows size */ |
| TI_UINT32 aTidWinSize; |
| /* expected sequence number (ESN) */ |
| TI_UINT16 aTidExpectedSn; |
| } TRxQueueTidDataBase; |
| |
| /* structure describe set of data that assist of manage one SA RxQueue arrays */ |
| typedef struct |
| { |
| TRxQueueTidDataBase tSa1ArrayMng [MAX_NUM_OF_802_1d_TAGS]; |
| } TRxQueueArraysMng; |
| |
| typedef struct |
| { |
| TI_BOOL bPacketMiss; /* True - Wait for missing packets start timer |
| False - all packets received in order */ |
| TI_UINT16 aPacketsStored; /* Represent the number of packets in Queue, 0 - Queue is empty */ |
| TI_UINT8 aFrameTid; /* save the TID of the missing packet */ |
| } TPacketTimeout; |
| |
| |
| /* main RxQueue structure in order to management the packets disordered array. */ |
| typedef struct |
| { |
| TI_HANDLE hOs; /* OS handler */ |
| TI_HANDLE hReport; /* Report handler */ |
| TI_HANDLE hTimer; /* Timer Handle */ |
| TRxQueueArraysMng tRxQueueArraysMng; /* manage each Source Address RxQueue arrays */ |
| TPacketReceiveCb tReceivePacketCB; /* Receive packets CB address */ |
| TI_HANDLE hReceivePacketCB_handle; /* Receive packets CB handler */ |
| TPacketTimeout tPacketTimeout; /* save information about the missing packet */ |
| } TRxQueue; |
| |
| /************************ static function declaration *****************************/ |
| static TI_STATUS RxQueue_PassPacket (TI_HANDLE hRxQueue, TI_STATUS tStatus, const void *pBuffer); |
| static void RxQueue_PacketTimeOut (TI_HANDLE hRxQueue, TI_BOOL bTwdInitOccured); |
| |
| /** |
| * \fn RxQueue_Create() |
| * \brief Create the RxQueue module. |
| * |
| * Allocate and clear the RxQueue module object. |
| * |
| * \param hOs - Handle to Os Abstraction Layer |
| * \return Handle of the allocated object |
| * \sa RxQueue_Destroy |
| */ |
| TI_HANDLE RxQueue_Create (TI_HANDLE hOs) |
| { |
| TRxQueue *pRxQueue; |
| |
| /* allocate module object */ |
| pRxQueue = os_memoryAlloc (hOs, sizeof(TRxQueue)); |
| |
| if (!pRxQueue) |
| { |
| WLAN_OS_REPORT (("RxQueue_Create(): Allocation failed!!\n")); |
| return NULL; |
| } |
| |
| os_memoryZero (hOs, pRxQueue, (sizeof(TRxQueue))); |
| |
| pRxQueue->hOs = hOs; |
| |
| return (pRxQueue); |
| } |
| |
| |
| /** |
| * \fn RxQueue_Destroy() |
| * \brief Destroy the module. |
| * |
| * Free the module's queues and object. |
| * |
| * \param hRxQueue - The module object |
| * \return TI_OK on success or TI_NOK on failure |
| * \sa RxQueue_Create |
| */ |
| TI_STATUS RxQueue_Destroy (TI_HANDLE hRxQueue) |
| { |
| TRxQueue *pRxQueue; |
| |
| if (hRxQueue) { |
| pRxQueue = (TRxQueue *)hRxQueue; |
| |
| if (pRxQueue->hTimer) { |
| tmr_DestroyTimer (pRxQueue->hTimer); |
| pRxQueue->hTimer = NULL; |
| } |
| |
| /* free module object */ |
| os_memoryFree (pRxQueue->hOs, pRxQueue, sizeof(TRxQueue)); |
| |
| return TI_OK; |
| } |
| |
| return TI_NOK; |
| } |
| |
| |
| /** |
| * \fn RxQueue_Init() |
| * \brief Init required handles |
| * |
| * Init required handles and module variables. |
| * |
| * \note |
| * \param hRxQueue - The module object |
| * \param hReport - Report module Handles |
| * \return TI_OK on success or TI_NOK on failure |
| * \sa |
| */ |
| TI_STATUS RxQueue_Init (TI_HANDLE hRxQueue, TI_HANDLE hReport, TI_HANDLE hTimerModule) |
| { |
| TRxQueue *pRxQueue = (TRxQueue *)hRxQueue; |
| |
| pRxQueue->hReport = hReport; |
| |
| pRxQueue->hTimer = tmr_CreateTimer (hTimerModule); |
| |
| return TI_OK; |
| } |
| |
| |
| /** |
| * \fn RxQueue_Register_CB() |
| * \brief Register the function to be called for received Rx. |
| * |
| * \note |
| * \param hRxQueue - The module object |
| * \param CallBackID - event ID |
| * \param CBFunc - function address. |
| * \param CBObj - function parameter. |
| * \return TI_OK on success or TI_NOK on failure |
| * \sa |
| */ |
| void RxQueue_Register_CB (TI_HANDLE hRxQueue, TI_UINT32 uCallBackID, void *CBFunc, TI_HANDLE CBObj) |
| { |
| TRxQueue* pRxQueue = (TRxQueue *)hRxQueue; |
| |
| TRACE1(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION , "RxQueue_Register_CB: CallBack ID = 0x%x\n", uCallBackID); |
| |
| switch(uCallBackID) |
| { |
| case TWD_INT_RECEIVE_PACKET: |
| pRxQueue->tReceivePacketCB = (TPacketReceiveCb)CBFunc; |
| pRxQueue->hReceivePacketCB_handle = CBObj; |
| break; |
| |
| default: |
| TRACE0(pRxQueue->hReport, REPORT_SEVERITY_ERROR , "RxQueue_Register_CB: Illegal value\n"); |
| break; |
| } |
| } |
| |
| /** |
| * \fn RxQueue_CloseBaSession () |
| * \brief Close BA session receiver and pass all packets in the TID queue to upper layer. |
| * |
| * \note |
| * \param hRxQueue - RxQueue handle. |
| * \param uFrameTid - TID session. |
| * \return None |
| * \sa |
| */ |
| void RxQueue_CloseBaSession(TI_HANDLE hRxQueue, TI_UINT8 uFrameTid) |
| { |
| TRxQueue *pRxQueue = (TRxQueue *)hRxQueue; |
| TI_UINT32 i; |
| /*set the SA Tid pointer */ |
| TRxQueueTidDataBase *pTidDataBase = &(pRxQueue->tRxQueueArraysMng.tSa1ArrayMng[uFrameTid]); |
| |
| /* TID illegal value ? */ |
| if (uFrameTid >= MAX_NUM_OF_802_1d_TAGS) |
| { |
| TRACE1(pRxQueue->hReport, REPORT_SEVERITY_ERROR , "RxQueue_CloseBaSession: BA event - DELBA frame with TID value too big, TID = %d\n", uFrameTid); |
| |
| return; |
| } |
| |
| if(pTidDataBase->aTidBaEstablished == TI_TRUE) |
| { |
| /* clean BA session */ |
| pTidDataBase->aTidBaEstablished = TI_FALSE; |
| |
| /* pass all valid entries at the array */ |
| for (i = 0; (i < RX_QUEUE_ARRAY_SIZE) && (i < RX_QUEUE_WIN_SIZE); i++) |
| { |
| if (pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket != NULL) |
| { |
| RxQueue_PassPacket (pRxQueue, |
| pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].tStatus, |
| pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket); |
| |
| pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket = NULL; |
| |
| pRxQueue->tPacketTimeout.aPacketsStored--; |
| } |
| |
| pTidDataBase->aWinStartArrayInex ++; |
| |
| /* aWinStartArrayInex % RX_QUEUE_ARRAY_SIZE */ |
| pTidDataBase->aWinStartArrayInex &= RX_QUEUE_ARRAY_SIZE_BIT_MASK; |
| } |
| |
| if (pRxQueue->tPacketTimeout.bPacketMiss) |
| { |
| tmr_StopTimer (pRxQueue->hTimer); |
| pRxQueue->tPacketTimeout.bPacketMiss = TI_FALSE; |
| } |
| } |
| } |
| |
| |
| /** |
| * \fn RxQueue_PassPacket() |
| * \brief Responsible on decode packet parameters and pass it to upper layer. |
| * |
| * \note |
| * \param hRxQueue - RxQueue handle. |
| * \param aStatus - RxXfer status that indicate if the upper layer should free the packet or use it. |
| * \param pFrame - paket address of the packet |
| * \param pRxParams - address to structure of the Rx Descriptor received by FW. |
| * \return TI_OK on success or TI_NOK on failure |
| * \sa |
| */ |
| static TI_STATUS RxQueue_PassPacket (TI_HANDLE hRxQueue, TI_STATUS tStatus, const void *pBuffer) |
| { |
| |
| TRxQueue *pRxQueue = (TRxQueue *)hRxQueue; |
| |
| if (tStatus == TI_OK) |
| { |
| /* Get the mac header location in the packet Buffer */ |
| dot11_header_t *pMacHdr = (dot11_header_t *)(TI_UINT8*)RX_BUF_DATA(pBuffer); |
| |
| /* Handle endian for the frame control fields */ |
| pMacHdr->fc = ENDIAN_HANDLE_WORD(pMacHdr->fc); |
| pMacHdr->duration = ENDIAN_HANDLE_WORD(pMacHdr->duration); |
| pMacHdr->seqCtrl = ENDIAN_HANDLE_WORD(pMacHdr->seqCtrl); |
| } |
| else |
| { |
| RxIfDescriptor_t *pRxParams = (RxIfDescriptor_t*)pBuffer; |
| |
| pRxParams->status &= ~RX_DESC_STATUS_MASK; |
| pRxParams->status |= RX_DESC_STATUS_DRIVER_RX_Q_FAIL; |
| } |
| |
| TRACE0(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION , "RxQueue_PassPacket: call TWD_OWNER_RX_QUEUE CB. In std rxData_ReceivePacket()\n"); |
| |
| /* Set the packet to upper layer */ |
| /* if the packet status not success it will be discarded */ |
| pRxQueue->tReceivePacketCB (pRxQueue->hReceivePacketCB_handle, pBuffer); |
| |
| return TI_OK; |
| } |
| |
| |
| /** |
| * \fn RxQueue_ReceivePacket() |
| * \brief Main function of the RxQueue module. |
| * Responsible on reorder of the packets from the RxXfer to the RX module. |
| * Call from RxXfer in order to pass packet to uppers layers. |
| * In order to save disordered packets the module use array of structures per TID |
| * that each entry describe a packet. The array elements is sorted in the way that |
| * the winStart array index represent always the winStart packet and the lowest SN. |
| * Each increment index represent index at the BA window. Array index winEnd always |
| * represent winEnd packet. The indexes of winStart and winEnd handled in cyclic manner. |
| * The function functionality devided to parts: |
| * Part 1: |
| * in case the modulo receive packet with SN equal to winStart: |
| * " pass it to upper layers |
| * " increases winStart and array index winStart |
| * " validate that all sequential queue packet are pass to the upper layers. |
| * Part 2: |
| * in case the modulo receive packet that SN between winStart to winEnd: |
| * " Save it sorted at the array at index: Save index = ((SN - winStart) + index array winStart) % arraySize. |
| * Part 3: |
| * in case the modulo receive packet that SN higher than winEnd: |
| * " Update winStart and WinEnd. |
| * " Save it sorted at the array in index winEnd index. |
| * " Pass to the upper layers all packets at the array indexes from old winStart index to the updated winStart index. |
| * Part 4 + 5: |
| * in case the modulo receive BA event packet: |
| * " Update winStart and WinEnd |
| * " Pass to the upper layers all packets at the array indexes from old winStart index to the updated winStart index. |
| * " Free BA event packet via pass it to upper layers with error status. |
| * |
| * \note |
| * \param hRxQueue - RxQueue handle. |
| * \param aStatus - RxXfer status that indicate if the upper layer should free the packet or use it. |
| * \param pBuffer - paket address of the packet |
| * \return None |
| * \sa |
| */ |
| void RxQueue_ReceivePacket (TI_HANDLE hRxQueue, const void * pBuffer) |
| { |
| TRxQueue *pRxQueue = (TRxQueue *)hRxQueue; |
| RxIfDescriptor_t *pRxParams = (RxIfDescriptor_t*)pBuffer; |
| TI_UINT8 *pFrame = RX_BUF_DATA((TI_UINT8 *)pBuffer); |
| TI_STATUS tStatus = TI_OK; |
| dot11_header_t *pHdr = (dot11_header_t *)pFrame; |
| TI_UINT16 uQosControl; |
| |
| COPY_WLAN_WORD(&uQosControl, &pHdr->qosControl); /* copy with endianess handling. */ |
| |
| TRACE2(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: packet_class_tag = 0x%x(%d)",pRxParams->packet_class_tag,pRxParams->packet_class_tag); |
| |
| /* |
| * Retrieving the TAG from the packet itself and not from the Rx Descriptor since by now it is not correct |
| * Note: in the DR TAG_CLASS_EAPOL packet handled as TAG_CLASS_QOS_DATA |
| */ |
| if (IS_QOS_FRAME(*(TI_UINT16*)pFrame) && (pRxParams->packet_class_tag != TAG_CLASS_QOS_DATA) && (pRxParams->packet_class_tag != TAG_CLASS_AMSDU)) |
| { |
| TRACE1(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: BAD CLASS TAG =0x%x from FW.\n", pRxParams->packet_class_tag); |
| |
| /* Get AMSDU bit from frame */ |
| if( uQosControl & DOT11_QOS_CONTROL_FIELD_A_MSDU_BITS) |
| { |
| pRxParams->packet_class_tag = TAG_CLASS_AMSDU; |
| } |
| else |
| { |
| pRxParams->packet_class_tag = TAG_CLASS_QOS_DATA; |
| } |
| } |
| |
| /* |
| * packet doesn't need reorder ? |
| */ |
| if ((pRxParams->packet_class_tag != TAG_CLASS_QOS_DATA) && (pRxParams->packet_class_tag != TAG_CLASS_BA_EVENT) && (pRxParams->packet_class_tag != TAG_CLASS_AMSDU)) |
| { |
| TRACE0(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: pass packet without reorder.\n"); |
| |
| RxQueue_PassPacket (pRxQueue, tStatus, pBuffer); |
| |
| return; |
| } |
| |
| |
| /* |
| * pRxParams->type == TAG_CLASS_QOS_DATA ? |
| */ |
| if ((pRxParams->packet_class_tag == TAG_CLASS_QOS_DATA) || (pRxParams->packet_class_tag == TAG_CLASS_AMSDU)) |
| { |
| TI_UINT8 uFrameTid; |
| TI_UINT16 uFrameSn; |
| TI_UINT16 uSequenceControl; |
| TRxQueueTidDataBase *pTidDataBase; |
| |
| /* Get TID from frame */ |
| uFrameTid = uQosControl & DOT11_QOS_CONTROL_FIELD_TID_BITS; |
| |
| TRACE0(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: QoS Packet received"); |
| TRACE2(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: uFrameTid = 0x%x(%d)",uFrameTid,uFrameTid); |
| |
| /* TID illegal value ? */ |
| if (uFrameTid >= MAX_NUM_OF_802_1d_TAGS) |
| { |
| TRACE1(pRxQueue->hReport, REPORT_SEVERITY_ERROR, "RxQueue_ReceivePacket: TID value too big, TID = %d. packet discarded!\n",uFrameTid); |
| |
| RxQueue_PassPacket (pRxQueue, TI_NOK, pBuffer); |
| |
| return; |
| } |
| |
| /* Set the SA Tid pointer */ |
| pTidDataBase = &(pRxQueue->tRxQueueArraysMng.tSa1ArrayMng[uFrameTid]); |
| |
| /* TID legal value */ |
| /* Packet TID BA session not established ? */ |
| if (pTidDataBase->aTidBaEstablished != TI_TRUE) |
| { |
| TRACE0(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: pass packet without reorder.\n"); |
| |
| RxQueue_PassPacket (pRxQueue, tStatus, pBuffer); |
| |
| return; |
| } |
| |
| /* packet TID BA established */ |
| /* Get Sequence Number from frame */ |
| COPY_WLAN_WORD(&uSequenceControl, &pHdr->seqCtrl); /* copy with endianess handling. */ |
| uFrameSn = (uSequenceControl & DOT11_SC_SEQ_NUM_MASK) >> 4; |
| |
| TRACE2(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: uFrameSn = 0x%x(%d)", uFrameSn, uFrameSn); |
| TRACE2(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: aTidExpectedSn = 0x%x(%d)",pTidDataBase->aTidExpectedSn, pTidDataBase->aTidExpectedSn); |
| |
| /* |
| * Note: |
| * The FW never sends packet, in establish TID BA, with SN less than ESN !!! |
| */ |
| |
| /* Part 1 - Frame Sequence Number is the expected one ? */ |
| if (uFrameSn == pTidDataBase->aTidExpectedSn) |
| { |
| TRACE0(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: frame Sequence Number == expected one Sequence Number.\n"); |
| |
| /* Stop timer in case that the expected SN received and timer was running */ |
| |
| |
| /* If we wait for 2 consecutive packets we should not stop the timer - This is why we are checking after the while loop, if we have |
| more packets stored, and if we have, we start the timer again. |
| */ |
| if (pRxQueue->tPacketTimeout.bPacketMiss) |
| { |
| tmr_StopTimer (pRxQueue->hTimer); |
| pRxQueue->tPacketTimeout.bPacketMiss = TI_FALSE; |
| } |
| |
| |
| /* Pass the packet */ |
| RxQueue_PassPacket (pRxQueue, tStatus, pBuffer); |
| |
| /* Increase expected SN to the next */ |
| pTidDataBase->aTidExpectedSn++; |
| pTidDataBase->aTidExpectedSn &= 0xfff; /* SN is 12 bits long */ |
| |
| /* Increase the ArrayInex to the next */ |
| pTidDataBase->aWinStartArrayInex++; |
| |
| /* aWinStartArrayInex % RX_QUEUE_ARRAY_SIZE */ |
| pTidDataBase->aWinStartArrayInex &= RX_QUEUE_ARRAY_SIZE_BIT_MASK; |
| |
| /* Pass all saved queue packets with SN higher than the expected one */ |
| while (pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket != NULL) |
| { |
| TRACE0(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: Pass all saved queue packets with SN higher than the expected one that was just received."); |
| TRACE2(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: aTidExpectedSn = 0x%x(%d)", pTidDataBase->aTidExpectedSn, pTidDataBase->aTidExpectedSn); |
| TRACE2(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: aWinStartArrayInex = 0x%x(%d)", pTidDataBase->aWinStartArrayInex, pTidDataBase->aWinStartArrayInex); |
| |
| RxQueue_PassPacket (pRxQueue, |
| pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].tStatus, |
| pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket); |
| |
| pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket = NULL; |
| |
| pTidDataBase->aWinStartArrayInex++; |
| |
| /* aWinStartArrayInex % RX_QUEUE_ARRAY_SIZE */ |
| pTidDataBase->aWinStartArrayInex &= RX_QUEUE_ARRAY_SIZE_BIT_MASK; |
| |
| pTidDataBase->aTidExpectedSn++; |
| pTidDataBase->aTidExpectedSn &= 0xfff; /* SN is 12 bits long */ |
| |
| /* Decrease the packets in queue */ |
| pRxQueue->tPacketTimeout.aPacketsStored--; |
| } |
| |
| |
| /* aTidExpectedSn % 0xfff in order to tack care of wrap around */ |
| pTidDataBase->aTidExpectedSn &= 0xfff; |
| |
| /* If there are still packets stored in the queue - start timer */ |
| if (pRxQueue->tPacketTimeout.aPacketsStored) |
| { |
| tmr_StartTimer (pRxQueue->hTimer, RxQueue_PacketTimeOut, pRxQueue, BA_SESSION_TIME_TO_SLEEP, TI_FALSE); |
| |
| pRxQueue->tPacketTimeout.bPacketMiss = TI_TRUE; |
| pRxQueue->tPacketTimeout.aFrameTid = uFrameTid; |
| } |
| |
| return; |
| } |
| |
| /* Frame Sequence Number is lower than Expected sequence number (ISN) ? */ |
| if (! BA_SESSION_IS_A_BIGGER_THAN_B (uFrameSn, pTidDataBase->aTidExpectedSn)) |
| { |
| /* WLAN_OS_REPORT(("%s: ERROR - SN=%u is less than ESN=%u\n", __FUNCTION__, uFrameSn, pTidDataBase->aTidExpectedSn)); */ |
| TRACE0(pRxQueue->hReport, REPORT_SEVERITY_ERROR, "RxQueue_ReceivePacket: frame Sequence Number is lower than expected sequence number.\n"); |
| |
| RxQueue_PassPacket (pRxQueue, tStatus, pBuffer); |
| |
| return; |
| } |
| |
| /* Part 2 - Frame Sequence Number between winStart and winEnd ? */ |
| if ((BA_SESSION_IS_A_BIGGER_THAN_B (uFrameSn, pTidDataBase->aTidExpectedSn)) && |
| /* mean: uFrameSn <= pTidDataBase->aTidExpectedSn + pTidDataBase->aTidWinSize) */ |
| ( ! BA_SESSION_IS_A_BIGGER_THAN_B (uFrameSn,(pTidDataBase->aTidExpectedSn + pTidDataBase->aTidWinSize - 1)))) |
| { |
| TI_UINT16 uSaveIndex = pTidDataBase->aWinStartArrayInex + (TI_UINT16)((uFrameSn + SEQ_NUM_WRAP - pTidDataBase->aTidExpectedSn) & SEQ_NUM_MASK); |
| |
| /* uSaveIndex % RX_QUEUE_ARRAY_SIZE */ |
| uSaveIndex &= RX_QUEUE_ARRAY_SIZE_BIT_MASK; |
| |
| TRACE0(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: frame Sequence Number between winStart and winEnd.\n"); |
| TRACE2(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: uSaveIndex = 0x%x(%d)",uSaveIndex,uSaveIndex); |
| |
| /* Before storing packet in queue, make sure the place in the queue is vacant */ |
| if (pTidDataBase->aPaketsQueue[uSaveIndex].pPacket == NULL) |
| { |
| TRACE0(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: Enter packet to Reorder Queue"); |
| |
| /* Store the packet in the queue */ |
| pTidDataBase->aPaketsQueue[uSaveIndex].tStatus = tStatus; |
| pTidDataBase->aPaketsQueue[uSaveIndex].pPacket = (void *)pBuffer; |
| pTidDataBase->aPaketsQueue[uSaveIndex].uFrameSn = uFrameSn; |
| |
| pRxQueue->tPacketTimeout.aPacketsStored++; |
| |
| |
| /* Start Timer [only if timer is not already started - according to bPacketMiss] */ |
| if(pRxQueue->tPacketTimeout.bPacketMiss == TI_FALSE) |
| { |
| tmr_StartTimer (pRxQueue->hTimer, RxQueue_PacketTimeOut, pRxQueue, BA_SESSION_TIME_TO_SLEEP, TI_FALSE); |
| pRxQueue->tPacketTimeout.bPacketMiss = TI_TRUE; |
| pRxQueue->tPacketTimeout.aFrameTid = uFrameTid; |
| } |
| } |
| else |
| { |
| TRACE1(pRxQueue->hReport, REPORT_SEVERITY_ERROR, "RxQueue_ReceivePacket: frame Sequence has already saved. uFrameSn = %d\n", uFrameSn); |
| |
| RxQueue_PassPacket (pRxQueue, TI_NOK, pBuffer); |
| return; |
| } |
| return; |
| } |
| |
| |
| /* |
| Part 3 - Frame Sequence Number higher than winEnd ? |
| */ |
| if ( BA_SESSION_IS_A_BIGGER_THAN_B (uFrameSn, (pTidDataBase->aTidExpectedSn + pTidDataBase->aTidWinSize - 1)) ) |
| { |
| TI_UINT32 i; |
| TI_UINT16 uNewWinStartSn = (uFrameSn + SEQ_NUM_WRAP - pTidDataBase->aTidWinSize + 1) & SEQ_NUM_MASK; |
| TI_UINT16 uSaveIndex; |
| |
| |
| TRACE0(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: frame Sequence Number higher than winEnd.\n"); |
| TRACE2(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: uNewWinStartSn = 0x%x(%d) STOP TIMER",uNewWinStartSn,uNewWinStartSn); |
| |
| /* If timer is on - stop it */ |
| if (pRxQueue->tPacketTimeout.bPacketMiss) |
| { |
| tmr_StopTimer (pRxQueue->hTimer); |
| pRxQueue->tPacketTimeout.bPacketMiss = TI_FALSE; |
| } |
| |
| /* Increase the ArrayInex to the next */ |
| pTidDataBase->aWinStartArrayInex++; |
| |
| /* aWinStartArrayInex % RX_QUEUE_ARRAY_SIZE */ |
| pTidDataBase->aWinStartArrayInex &= RX_QUEUE_ARRAY_SIZE_BIT_MASK; |
| |
| /* Update the Expected SN since the current one is lost */ |
| pTidDataBase->aTidExpectedSn++; |
| pTidDataBase->aTidExpectedSn &= 0xFFF; |
| |
| /* Pass all saved queue packets with SN lower than the new win start */ |
| for (i = 0; |
| BA_SESSION_IS_A_BIGGER_THAN_B(uNewWinStartSn,pTidDataBase->aTidExpectedSn) && |
| (i < RX_QUEUE_ARRAY_SIZE) && |
| (i < pTidDataBase->aTidWinSize); |
| i++) |
| { |
| TRACE2(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: aTidExpectedSn = 0x%x(%d)",pTidDataBase->aTidExpectedSn,pTidDataBase->aTidExpectedSn); |
| TRACE2(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: aWinStartArrayInex = 0x%x(%d)",pTidDataBase->aWinStartArrayInex,pTidDataBase->aWinStartArrayInex); |
| |
| if (pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket != NULL) |
| { |
| TRACE0(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: Send Packet to Upper layer"); |
| RxQueue_PassPacket (pRxQueue, |
| pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].tStatus, |
| pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket); |
| |
| pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket = NULL; |
| |
| pRxQueue->tPacketTimeout.aPacketsStored--; |
| } |
| |
| pTidDataBase->aWinStartArrayInex++; |
| |
| /* aWinStartArrayInex % RX_QUEUE_ARRAY_SIZE */ |
| pTidDataBase->aWinStartArrayInex &= RX_QUEUE_ARRAY_SIZE_BIT_MASK; |
| |
| pTidDataBase->aTidExpectedSn++; |
| pTidDataBase->aTidExpectedSn &= 0xFFF; |
| |
| } |
| |
| TRACE2(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: aTidExpectedSn = 0x%x(%d)",pTidDataBase->aTidExpectedSn,pTidDataBase->aTidExpectedSn); |
| TRACE1(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: i = %d",i); |
| |
| /* Calculate the new Expected SN */ |
| if (i == pTidDataBase->aTidWinSize) |
| { |
| TRACE0(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: Set aTidExpectedSn to uNewWinStartSn"); |
| pTidDataBase->aTidExpectedSn = uNewWinStartSn; |
| } |
| else |
| { |
| TRACE0(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: Send all saved packets"); |
| /* In case the uWinStartDelta lower than aTidWinSize check if ther are packets stored in Array */ |
| |
| while (pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket != NULL) |
| { |
| TRACE2(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: Send packet with SN = 0x%x(%d)",pTidDataBase->aTidExpectedSn,pTidDataBase->aTidExpectedSn); |
| |
| RxQueue_PassPacket ( pRxQueue, |
| pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].tStatus, |
| pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket |
| ); |
| pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket = NULL; |
| |
| pTidDataBase->aWinStartArrayInex++; |
| |
| /* aWinStartArrayInex % RX_QUEUE_ARRAY_SIZE */ |
| pTidDataBase->aWinStartArrayInex &= RX_QUEUE_ARRAY_SIZE_BIT_MASK; |
| |
| pTidDataBase->aTidExpectedSn++; |
| pTidDataBase->aTidExpectedSn &= 0xFFF; |
| |
| pRxQueue->tPacketTimeout.aPacketsStored--; |
| } |
| } |
| |
| TRACE2(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: aTidExpectedSn = 0x%x(%d)",pTidDataBase->aTidExpectedSn,pTidDataBase->aTidExpectedSn); |
| |
| if(pTidDataBase->aTidExpectedSn == uFrameSn) |
| { |
| TRACE0(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: Send current packet to uper layer"); |
| /* pass the packet */ |
| RxQueue_PassPacket (pRxQueue, tStatus, pBuffer); |
| pTidDataBase->aTidExpectedSn++; |
| pTidDataBase->aTidExpectedSn &= 0xfff; |
| } |
| else |
| { |
| uSaveIndex = pTidDataBase->aWinStartArrayInex + (TI_UINT16)((uFrameSn + SEQ_NUM_WRAP - pTidDataBase->aTidExpectedSn) & SEQ_NUM_MASK); |
| |
| TRACE0(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: Enter current packet to Reorder Queue"); |
| TRACE2(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: uSaveIndex = 0x%x(%d)", uSaveIndex, uSaveIndex); |
| |
| /* uSaveIndex % RX_QUEUE_ARRAY_SIZE */ |
| uSaveIndex &= RX_QUEUE_ARRAY_SIZE_BIT_MASK; |
| |
| /* Save the packet in the last entry of the queue */ |
| pTidDataBase->aPaketsQueue[uSaveIndex].tStatus = tStatus; |
| pTidDataBase->aPaketsQueue[uSaveIndex].pPacket = (void *)pBuffer; |
| pTidDataBase->aPaketsQueue[uSaveIndex].pPacket = (void *)pBuffer; |
| |
| pRxQueue->tPacketTimeout.aPacketsStored++; |
| } |
| |
| |
| /* aTidExpectedSn % 0xfff in order to tack care of wrap around */ |
| pTidDataBase->aTidExpectedSn &= 0xfff; |
| |
| /* If there are still packets stored in the queue - start timer */ |
| if (pRxQueue->tPacketTimeout.aPacketsStored) |
| { |
| tmr_StartTimer (pRxQueue->hTimer, RxQueue_PacketTimeOut, pRxQueue, BA_SESSION_TIME_TO_SLEEP, TI_FALSE); |
| pRxQueue->tPacketTimeout.bPacketMiss = TI_TRUE; |
| pRxQueue->tPacketTimeout.aFrameTid = uFrameTid; |
| } |
| |
| return; |
| } |
| } |
| |
| |
| /* |
| * BA event ? |
| */ |
| if (pRxParams->packet_class_tag == TAG_CLASS_BA_EVENT) |
| { |
| TRxQueueTidDataBase *pTidDataBase; |
| TI_UINT8 *pDataFrameBody; |
| TI_UINT16 ufc; |
| TI_UINT8 uFrameTid; |
| TI_UINT16 uStartingSequenceNumber; |
| TI_UINT16 uWinStartDelta; |
| TI_UINT16 uBarControlField; |
| TI_UINT16 uBaStartingSequenceControlField; |
| TI_UINT16 uBAParameterField; |
| TI_UINT32 i; |
| |
| /* Get sub type from frame */ |
| COPY_WLAN_WORD(&ufc, &pHdr->fc); /* copy with endianess handling. */ |
| |
| /* get the type to BA event */ |
| switch ((dot11_Fc_Sub_Type_e)(ufc & DOT11_FC_SUB_MASK)) |
| { |
| case DOT11_FC_SUB_BAR: |
| TRACE0(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION , "RxQueue_ReceivePacket: BA event - BAR frame.\n"); |
| |
| /* get pointer to the frame body */ |
| pDataFrameBody = pFrame + sizeof(dot11_BarFrameHeader_t); |
| |
| /* Get TID from BAR frame */ |
| COPY_WLAN_WORD (&uBarControlField, (TI_UINT16 *)pDataFrameBody); /* copy with endianess handling. */ |
| uFrameTid = (uBarControlField & DOT11_BAR_CONTROL_FIELD_TID_BITS) >> 12; |
| |
| /* TID illegal value ? */ |
| if (uFrameTid >= MAX_NUM_OF_802_1d_TAGS) |
| { |
| TRACE1(pRxQueue->hReport, REPORT_SEVERITY_ERROR , "RxQueue_ReceivePacket: BA event - BAR frame with TID value too big, TID = %d.\n",uFrameTid); |
| |
| RxQueue_PassPacket (pRxQueue, TI_NOK, pBuffer); |
| |
| return; |
| } |
| |
| /* set the SA Tid pointer */ |
| pTidDataBase = &(pRxQueue->tRxQueueArraysMng.tSa1ArrayMng[uFrameTid]); |
| |
| /* TID legal value */ |
| /* packet TID BA not established ? */ |
| if (pTidDataBase->aTidBaEstablished != TI_TRUE) |
| { |
| TRACE1(pRxQueue->hReport, REPORT_SEVERITY_ERROR , "RxQueue_ReceivePacket: BA event - BAR frame for TID not established, TID = %d.\n",uFrameTid); |
| |
| RxQueue_PassPacket (pRxQueue, TI_NOK, pBuffer); |
| |
| return; |
| } |
| |
| /* Get Starting Sequence number from BAR frame */ |
| pDataFrameBody = pDataFrameBody + 2; |
| COPY_WLAN_WORD (&uBaStartingSequenceControlField, (TI_UINT16 *)pDataFrameBody); /* copy with endianess handling. */ |
| uStartingSequenceNumber = (uBaStartingSequenceControlField & DOT11_SC_SEQ_NUM_MASK) >> 4; |
| |
| /* Starting Sequence Number is higher than winStart ? */ |
| if ( BA_SESSION_IS_A_BIGGER_THAN_B (uStartingSequenceNumber, pTidDataBase->aTidExpectedSn) ) |
| { |
| uWinStartDelta = uStartingSequenceNumber - pTidDataBase->aTidExpectedSn; |
| if (pRxQueue->tPacketTimeout.bPacketMiss) |
| { |
| tmr_StopTimer (pRxQueue->hTimer); |
| pRxQueue->tPacketTimeout.bPacketMiss = TI_FALSE; |
| } |
| |
| /* pass all saved queue packets with SN lower than the new win start */ |
| for (i = 0; |
| ((i < uWinStartDelta) || (pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket != NULL)) && |
| (i < RX_QUEUE_ARRAY_SIZE) && |
| (i < RX_QUEUE_WIN_SIZE); |
| i++) |
| { |
| if (pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket != NULL) |
| { |
| RxQueue_PassPacket (pRxQueue, |
| pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].tStatus, |
| pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket); |
| |
| pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket = NULL; |
| pRxQueue->tPacketTimeout.aPacketsStored--; |
| } |
| |
| pTidDataBase->aWinStartArrayInex++; |
| |
| /* aWinStartArrayInex % RX_QUEUE_ARRAY_SIZE */ |
| pTidDataBase->aWinStartArrayInex &= RX_QUEUE_ARRAY_SIZE_BIT_MASK; |
| } |
| |
| if (pRxQueue->tPacketTimeout.aPacketsStored) |
| { |
| tmr_StartTimer (pRxQueue->hTimer, RxQueue_PacketTimeOut, pRxQueue, BA_SESSION_TIME_TO_SLEEP, TI_FALSE); |
| pRxQueue->tPacketTimeout.bPacketMiss = TI_TRUE; |
| pRxQueue->tPacketTimeout.aFrameTid = uFrameTid; |
| } |
| |
| |
| pTidDataBase->aTidExpectedSn = uStartingSequenceNumber; |
| } |
| break; |
| |
| |
| case DOT11_FC_SUB_ACTION: |
| /* get pointer to the frame body */ |
| pDataFrameBody = pFrame + sizeof(dot11_mgmtHeader_t); |
| |
| /* get Action field from BA action frame */ |
| pDataFrameBody++; |
| switch(*pDataFrameBody) |
| { |
| case DOT11_BA_ACTION_ADDBA: |
| |
| |
| /* get TID field and winSize from ADDBA action frame */ |
| pDataFrameBody = pDataFrameBody + 2; |
| COPY_WLAN_WORD(&uBAParameterField, (TI_UINT16 *)pDataFrameBody); /* copy with endianess handling. */ |
| uFrameTid = (uBAParameterField & DOT11_BA_PARAMETER_SET_FIELD_TID_BITS) >> 2; |
| |
| /* TID illegal value ? */ |
| if (uFrameTid >= MAX_NUM_OF_802_1d_TAGS) |
| { |
| TRACE1(pRxQueue->hReport, REPORT_SEVERITY_ERROR , "RxQueue_ReceivePacket: BA event - ADDBA frame with TID value too big, TID = %d.\n",uFrameTid); |
| |
| RxQueue_PassPacket (pRxQueue, TI_NOK, pBuffer); |
| |
| return; |
| } |
| |
| /*set the SA Tid pointer */ |
| pTidDataBase = &(pRxQueue->tRxQueueArraysMng.tSa1ArrayMng[uFrameTid]); |
| |
| /* TID legal value */ |
| /* packet TID BA established ? */ |
| if (pTidDataBase->aTidBaEstablished == TI_TRUE) |
| { |
| TRACE1(pRxQueue->hReport, REPORT_SEVERITY_ERROR , "RxQueue_ReceivePacket: BA event - ADDBA frame for TID already established, TID = %d.\n",uFrameTid); |
| |
| RxQueue_PassPacket (pRxQueue, TI_NOK, pBuffer); |
| |
| return; |
| } |
| |
| /* get winSize from ADDBA action frame */ |
| pTidDataBase->aTidWinSize = (uBAParameterField & DOT11_BA_PARAMETER_SET_FIELD_WINSIZE_BITS) >> 6; |
| |
| /* winSize illegal value ? */ |
| if (pTidDataBase->aTidWinSize > RX_QUEUE_WIN_SIZE) |
| { |
| /* In case the win Size is higher than 8 the driver and the FW set it to 8 and inform the AP in ADDBA respond */ |
| pTidDataBase->aTidWinSize = RX_QUEUE_WIN_SIZE; |
| } |
| |
| /* packet TID BA not yet established and winSize legal */ |
| /* establishe BA TID */ |
| pTidDataBase->aTidBaEstablished = TI_TRUE; |
| |
| /* get initial sequence number (ISN) from ADDBA action frame */ |
| pDataFrameBody = pDataFrameBody + 4; |
| COPY_WLAN_WORD (&uStartingSequenceNumber, (TI_UINT16 *)pDataFrameBody); /* copy with endianess handling. */ |
| pTidDataBase->aTidExpectedSn = (uStartingSequenceNumber & DOT11_SC_SEQ_NUM_MASK) >> 4; |
| pTidDataBase->aWinStartArrayInex = 0; |
| os_memoryZero (pRxQueue->hOs, pTidDataBase->aPaketsQueue, sizeof (TRxQueuePacketEntry) * RX_QUEUE_ARRAY_SIZE); |
| break; |
| |
| case DOT11_BA_ACTION_DELBA: |
| |
| |
| /* get TID field and winSize from ADDBA action frame */ |
| pDataFrameBody = pDataFrameBody + 1; |
| COPY_WLAN_WORD(&uBAParameterField, (TI_UINT16 *)pDataFrameBody); /* copy with endianess handling. */ |
| uFrameTid = (uBAParameterField & DOT11_DELBA_PARAMETER_FIELD_TID_BITS) >> 12; |
| |
| /* TID illegal value ? */ |
| if (uFrameTid >= MAX_NUM_OF_802_1d_TAGS) |
| { |
| TRACE1(pRxQueue->hReport, REPORT_SEVERITY_ERROR , "RxQueue_ReceivePacket: BA event - DELBA frame with TID value too big, TID = %d.\n",uFrameTid); |
| |
| RxQueue_PassPacket (pRxQueue, TI_NOK, pBuffer); |
| |
| return; |
| } |
| |
| /*set the SA Tid pointer */ |
| pTidDataBase = &(pRxQueue->tRxQueueArraysMng.tSa1ArrayMng[uFrameTid]); |
| |
| /* TID legal value */ |
| /* packet TID BA not established ? */ |
| if (pTidDataBase->aTidBaEstablished != TI_TRUE) |
| { |
| TRACE1(pRxQueue->hReport, REPORT_SEVERITY_ERROR , "RxQueue_ReceivePacket: BA event - DELBA frame for TID not established, TID = %d.\n",uFrameTid); |
| |
| RxQueue_PassPacket (pRxQueue, TI_NOK, pBuffer); |
| |
| return; |
| } |
| |
| RxQueue_CloseBaSession(hRxQueue, uFrameTid); |
| break; |
| |
| default: |
| TRACE1(pRxQueue->hReport, REPORT_SEVERITY_ERROR , "RxQueue_ReceivePacket: BA event Action field from BA action frame illegal. action = 0x%x\n",*pDataFrameBody); |
| |
| RxQueue_PassPacket (pRxQueue, TI_NOK, pBuffer); |
| |
| return; |
| } |
| break; |
| |
| default: |
| TRACE1(pRxQueue->hReport, REPORT_SEVERITY_ERROR , "RxQueue_ReceivePacket: BA event with Subtype illegal. Subtype = 0x%x\n",((ufc & DOT11_FC_SUB_MASK) >> 4)); |
| |
| RxQueue_PassPacket (pRxQueue, TI_NOK, pBuffer); |
| |
| return; |
| } |
| |
| } |
| |
| TRACE1(pRxQueue->hReport, REPORT_SEVERITY_ERROR, "RxQueue_ReceivePacket: unknow type tag. tag = %d\n", pRxParams->packet_class_tag); |
| |
| RxQueue_PassPacket (pRxQueue, tStatus, pBuffer); |
| |
| return; |
| } |
| |
| |
| /* |
| Function Name : RxQueue_PacketTimeOut |
| |
| Description : This function sends all consecutive old packets stored in a specific TID queue to the upper layer. |
| |
| This function is called on timer wake up. |
| [The timer is started when we have stored packets in the RxQueue]. |
| |
| |
| Parameters : hRxQueue - A handle to the RxQueue structure. |
| bTwdInitOccured - Not used. |
| |
| Returned Value: void |
| */ |
| static void RxQueue_PacketTimeOut (TI_HANDLE hRxQueue, TI_BOOL bTwdInitOccured) |
| { |
| TRxQueue *pRxQueue = (TRxQueue *)hRxQueue; |
| TRxQueueTidDataBase *pTidDataBase; |
| |
| pRxQueue->tPacketTimeout.bPacketMiss = TI_FALSE; |
| |
| /* Set the SA Tid pointer */ |
| pTidDataBase = &(pRxQueue->tRxQueueArraysMng.tSa1ArrayMng[pRxQueue->tPacketTimeout.aFrameTid]); |
| |
| |
| if (pRxQueue->tPacketTimeout.aPacketsStored) |
| { |
| |
| /* Find the first stored packet */ |
| while (pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket == NULL) |
| { |
| pTidDataBase->aWinStartArrayInex++; |
| |
| /* aWinStartArrayInex % RX_QUEUE_ARRAY_SIZE */ |
| pTidDataBase->aWinStartArrayInex &= RX_QUEUE_ARRAY_SIZE_BIT_MASK; |
| |
| pTidDataBase->aTidExpectedSn++; |
| pTidDataBase->aTidExpectedSn &= 0xFFF; |
| } |
| |
| |
| /* Send all packets in order */ |
| while ((pRxQueue->tPacketTimeout.aPacketsStored > 0) && (pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket != NULL)) |
| { |
| |
| RxQueue_PassPacket (pRxQueue, |
| pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].tStatus, |
| pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket); |
| |
| pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket = NULL; |
| |
| pTidDataBase->aWinStartArrayInex++; |
| |
| /* aWinStartArrayInex % RX_QUEUE_ARRAY_SIZE */ |
| pTidDataBase->aWinStartArrayInex &= RX_QUEUE_ARRAY_SIZE_BIT_MASK; |
| |
| pTidDataBase->aTidExpectedSn++; |
| pTidDataBase->aTidExpectedSn &= 0xFFF; |
| |
| pRxQueue->tPacketTimeout.aPacketsStored--; |
| |
| } |
| } |
| |
| if (pRxQueue->tPacketTimeout.aPacketsStored) |
| { |
| tmr_StartTimer (pRxQueue->hTimer, RxQueue_PacketTimeOut, pRxQueue, BA_SESSION_TIME_TO_SLEEP, TI_FALSE); |
| pRxQueue->tPacketTimeout.bPacketMiss = TI_TRUE; |
| } |
| } |