示例#1
0
/**
 * \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 timer is started - stop it */
		if (pRxQueue->tPacketTimeout.bPacketMiss)
		{
			tmr_StopTimer (pRxQueue->hTimer);
			pRxQueue->tPacketTimeout.bPacketMiss = TI_FALSE;
		}
	}
}
示例#2
0
/**
 * \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) {

		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;

				pTidDataBase->uStoredPackets--;
			}

			pTidDataBase->aWinStartArrayInex ++;

			/* aWinStartArrayInex % RX_QUEUE_ARRAY_SIZE */
			pTidDataBase->aWinStartArrayInex &= RX_QUEUE_ARRAY_SIZE_BIT_MASK;
		}

		/* stop missing packet timer for this TID */
		StopMissingPktTimer(pRxQueue, uFrameTid);
	}
}
示例#3
0
/**
 * \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.
 *
 * SN range      :  0 - 4095
 * winStart range:  0 - 7       [0 - (RX_QUEUE_ARRAY_SIZE - 1)]
 * winSize       :  Determined by the BA session. We limit it to maximum 8 [RX_QUEUE_ARRAY_SIZE]
 * winEnd        :  = winStart + winSize - 1
 *
 * The function functionality devided to parts:
 *   Part 1:
 * In case the module received a packet with SN equal to the expected SN:
 * "	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 module received a packet with 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 module received a packet with 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 module received a BA event packet: [Remember: This is an Rx module - We expect BAR and not BA (as well as ADDBE / DELBA]
 * "	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 [contains the RxIfDescriptor_t added by the FW].
 * \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. */



	/*
	 * Retrieving the TAG from the packet itself and not from the Rx Descriptor since by now it is not correct.
	 * If the packet is a QoS packet but the tag is not TAG_CLASS_QOS_DATA or TAG_CLASS_AMSDU - force TAG_CLASS_QOS_DATA or TAG_CLASS_AMSDU.
	 *
	 * 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)) {


		/* 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)) {

		RxQueue_PassPacket (pRxQueue, TI_OK, 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;


		/* TID illegal value ? */
		if (uFrameTid >= MAX_NUM_OF_802_1d_TAGS) {

			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) {
			RxQueue_PassPacket (pRxQueue, TI_OK, pBuffer);

			return;
		}


		/* If we got here - 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;


		/*
		 * Note:
		 * The FW never sends packet, in establish TID BA, with SN less than ESN !!!
		 */


		/* Part 1 - Received Frame Sequence Number is the expected one ? */
		if (uFrameSn == pTidDataBase->aTidExpectedSn) {


			/*
			   If the expected SN received and timer was running - Stop the timer.

			   If we wait for more than one packet 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 (pTidDataBase->uMissingPktTimeStamp != 0xffffffff) {
				StopMissingPktTimer(pRxQueue, uFrameTid);
			}

			/* Pass the packet */
			RxQueue_PassPacket (pRxQueue, TI_OK, 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 consecutive packets with SN higher than the expected one */
			while (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; /* SN is 12 bits long */

				/* Decrease the packets in queue */
				pTidDataBase->uStoredPackets--;
			}


			/* 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 (pTidDataBase->uStoredPackets) {
				StartMissingPktTimer(pRxQueue, 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)); */

			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;


			/* Before storing packet in queue, make sure the place in the queue is vacant */
			if (pTidDataBase->aPaketsQueue[uSaveIndex].pPacket == NULL) {

				/* Store the packet in the queue */
				pTidDataBase->aPaketsQueue[uSaveIndex].tStatus  = tStatus;
				pTidDataBase->aPaketsQueue[uSaveIndex].pPacket  = (void *)pBuffer;
				pTidDataBase->aPaketsQueue[uSaveIndex].uFrameSn = uFrameSn;

				pTidDataBase->uStoredPackets++;


				/* Start Timer */
				StartMissingPktTimer(pRxQueue, uFrameTid);
			} else {

				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;


			/* stop timer */
			if (pTidDataBase->uMissingPktTimeStamp != 0xffffffff) {
				StopMissingPktTimer(pRxQueue, uFrameTid);
			}

			/* 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++) {

				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;

					pTidDataBase->uStoredPackets--;
				}

				pTidDataBase->aWinStartArrayInex++;

				/* aWinStartArrayInex % RX_QUEUE_ARRAY_SIZE */
				pTidDataBase->aWinStartArrayInex &= RX_QUEUE_ARRAY_SIZE_BIT_MASK;

				pTidDataBase->aTidExpectedSn++;
				pTidDataBase->aTidExpectedSn &= 0xFFF;

			}


			/* Calculate the new Expected SN */
			if (i == pTidDataBase->aTidWinSize) {
				pTidDataBase->aTidExpectedSn = uNewWinStartSn;
			} else {
				/* In case the uWinStartDelta lower than aTidWinSize - check if there are packets stored in Array */

				while (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;


					pTidDataBase->uStoredPackets--;
				}
			}


			if (pTidDataBase->aTidExpectedSn == uFrameSn) {
				/* 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);


				/* 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;

				pTidDataBase->uStoredPackets++;
			}



			/* aTidExpectedSn % 0xfff in order to take care of wrap around */
			pTidDataBase->aTidExpectedSn &= 0xfff;

			/* If there are still packets stored in the queue - start timer */
			if (pTidDataBase->uStoredPackets) {
				StartMissingPktTimer(pRxQueue, uFrameTid);
			}

			return;
		}
	}
示例#4
0
文件: RxQueue.c 项目: aleho/ti_wilink
/** 
 * \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 winStar 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 then 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. */

    /* 
     * 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_WARNING, "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;

        /* 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 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;

        /* 
         * note: 
         * the FW never send paket, in establish TID BA, that the SN less then ESN !!! 
         */

        /* 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");

            /* pass the packet */
            RxQueue_PassPacket (pRxQueue, tStatus, pBuffer);

            pTidDataBase->aTidExpectedSn++;
            pTidDataBase->aTidExpectedSn &= 0xfff;

            /* 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 then the expected one */
            while (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;
            }

            return;
        }

        /* frame Sequence Number is lower then 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)); */
			
			TRACE2(pRxQueue->hReport, REPORT_SEVERITY_ERROR, 
				   "RxQueue_ReceivePacket: frame SN=%u is less than ESN=%u\n",uFrameSn,pTidDataBase->aTidExpectedSn);

			RxQueue_PassPacket (pRxQueue, TI_NOK, pBuffer);

            return;
        }

        /* 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 uSaveInex = pTidDataBase->aWinStartArrayInex + (TI_UINT16)((uFrameSn + SEQ_NUM_WRAP - pTidDataBase->aTidExpectedSn) & SEQ_NUM_MASK);  
            /* uSaveInex % RX_QUEUE_ARRAY_SIZE */
            uSaveInex &= RX_QUEUE_ARRAY_SIZE_BIT_MASK; 

          
			if (pTidDataBase->aPaketsQueue[uSaveInex].pPacket == NULL)
			{
                /* save the packet in the queue */
                pTidDataBase->aPaketsQueue[uSaveInex].tStatus = tStatus;
                pTidDataBase->aPaketsQueue[uSaveInex].pPacket = (void *)pBuffer;
                pTidDataBase->aPaketsQueue[uSaveInex].uFrameSn = uFrameSn;
			}
			else
			{
 				 TRACE1(pRxQueue->hReport, REPORT_SEVERITY_ERROR, "RxQueue_ReceivePacket: frame Sequence has allready saved. uFrameSn = %d\n",uFrameSn);

				 RxQueue_PassPacket (pRxQueue, TI_NOK, pBuffer);
				 return;
			}
            return;
        }


        /* 
        frame Sequence Number higher then 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 uSaveInex;
            
			TRACE0(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: frame Sequence Number higher then winEnd.\n");

            /* 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 then 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++)
            {
                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;
                }

                pTidDataBase->aWinStartArrayInex++;

                /* aWinStartArrayInex % RX_QUEUE_ARRAY_SIZE */
                pTidDataBase->aWinStartArrayInex &= RX_QUEUE_ARRAY_SIZE_BIT_MASK;

                pTidDataBase->aTidExpectedSn++;
                pTidDataBase->aTidExpectedSn &= 0xFFF;

            }

            /* Calculate the new Expected SN */
            if (i == pTidDataBase->aTidWinSize)
            {
                pTidDataBase->aTidExpectedSn = uNewWinStartSn;
            }
            else
            {
                /* Incase the uWinStartDelta lower than aTidWinSize check if ther are packets stored in Array */
                while (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;
                }
            }

            if(pTidDataBase->aTidExpectedSn == uFrameSn)
            {
                /* pass the packet */
                RxQueue_PassPacket (pRxQueue, tStatus, pBuffer);
                pTidDataBase->aTidExpectedSn++;
				pTidDataBase->aTidExpectedSn &= 0xfff; 
            }
            else
            {
                uSaveInex = pTidDataBase->aWinStartArrayInex + (TI_UINT16)((uFrameSn + SEQ_NUM_WRAP - pTidDataBase->aTidExpectedSn) & SEQ_NUM_MASK);  

				/* uSaveInex % RX_QUEUE_ARRAY_SIZE */
				uSaveInex &= RX_QUEUE_ARRAY_SIZE_BIT_MASK; 

				/* save the packet in the last entry of the queue */
				pTidDataBase->aPaketsQueue[uSaveInex].tStatus = tStatus;
				pTidDataBase->aPaketsQueue[uSaveInex].pPacket = (void *)pBuffer;
				pTidDataBase->aPaketsQueue[uSaveInex].pPacket = (void *)pBuffer;
            }

            return;
        }
    }
示例#5
0
/**
 * \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.
 *
 * SN range      :  0 - 4095
 * winStart range:  0 - 7       [0 - (RX_QUEUE_ARRAY_SIZE - 1)]
 * winSize       :  Determined by the BA session. We limit it to maximum 8 [RX_QUEUE_ARRAY_SIZE]
 * winEnd        :  = winStart + winSize - 1
 *
 * The function functionality devided to parts:
 *   Part 1:
 * In case the module received a packet with SN equal to the expected SN:
 * "	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 module received a packet with 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 module received a packet with 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 module received a BA event packet: [Remember: This is an Rx module - We expect BAR and not BA (as well as ADDBE / DELBA]
 * "	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 [contains the RxIfDescriptor_t added by the FW].
 * \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.
	 * If the packet is a QoS packet but the tag is not TAG_CLASS_QOS_DATA or TAG_CLASS_AMSDU - force TAG_CLASS_QOS_DATA or TAG_CLASS_AMSDU.
	 *
	 * 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, TI_OK, 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, TI_OK, pBuffer);

			return;
		}


		/* If we got here - 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 - Received 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");


			/*
			   If the expected SN received and timer was running - Stop the timer.

			   If we wait for more than one packet 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, TI_OK, 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 consecutive 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)); */
			TRACE2(pRxQueue->hReport, REPORT_SEVERITY_WARNING, "RxQueue_ReceivePacket: frame Sequence Number (%d) is lower than expected sequence number (%d).\n", uFrameSn, pTidDataBase->aTidExpectedSn);

			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 there 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 take 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;
		}
	}