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