static USHORT ba_indicate_reordering_mpdus_in_order( IN PRTMP_ADAPTER pAd, IN PBA_REC_ENTRY pBAEntry, IN USHORT StartSeq) { struct reordering_mpdu *mpdu_blk; USHORT LastIndSeq = RESET_RCV_SEQ; NdisAcquireSpinLock(&pBAEntry->RxReRingLock); while ((mpdu_blk = ba_reordering_mpdu_probe(&pBAEntry->list))) { /* find in-order frame */ if (!SEQ_STEPONE(mpdu_blk->Sequence, StartSeq, MAXSEQ)) { break; } /* dequeue in-order frame from reodering list */ mpdu_blk = ba_reordering_mpdu_dequeue(&pBAEntry->list); /* pass this frame up */ ANNOUNCE_REORDERING_PACKET(pAd, mpdu_blk); /* move to next sequence */ StartSeq = mpdu_blk->Sequence; LastIndSeq = StartSeq; /* free mpdu_blk */ ba_mpdu_blk_free(pAd, mpdu_blk); } NdisReleaseSpinLock(&pBAEntry->RxReRingLock); /* update last indicated sequence */ return LastIndSeq; }
static void ba_indicate_reordering_mpdus_le_seq( IN PRTMP_ADAPTER pAd, IN PBA_REC_ENTRY pBAEntry, IN USHORT Sequence) { struct reordering_mpdu *mpdu_blk; NdisAcquireSpinLock(&pBAEntry->RxReRingLock); while ((mpdu_blk = ba_reordering_mpdu_probe(&pBAEntry->list))) { /* find in-order frame */ if ((mpdu_blk->Sequence == Sequence) || SEQ_SMALLER(mpdu_blk->Sequence, Sequence, MAXSEQ)) { /* dequeue in-order frame from reodering list */ mpdu_blk = ba_reordering_mpdu_dequeue(&pBAEntry->list); /* pass this frame up */ ANNOUNCE_REORDERING_PACKET(pAd, mpdu_blk); /* free mpdu_blk */ ba_mpdu_blk_free(pAd, mpdu_blk); } else { break; } } NdisReleaseSpinLock(&pBAEntry->RxReRingLock); }
/* * free all resource for reordering mechanism */ void ba_reordering_resource_release(PRTMP_ADAPTER pAd) { BA_TABLE *Tab; PBA_REC_ENTRY pBAEntry; struct reordering_mpdu *mpdu_blk; int i; Tab = &pAd->BATable; /* I. release all pending reordering packet */ NdisAcquireSpinLock(&pAd->BATabLock); for (i = 0; i < MAX_LEN_OF_BA_REC_TABLE; i++) { pBAEntry = &Tab->BARecEntry[i]; if (pBAEntry->REC_BA_Status != Recipient_NONE) { while ((mpdu_blk = ba_reordering_mpdu_dequeue(&pBAEntry->list))) { ASSERT(mpdu_blk->pPacket); RELEASE_NDIS_PACKET(pAd, mpdu_blk->pPacket, NDIS_STATUS_FAILURE); ba_mpdu_blk_free(pAd, mpdu_blk); } } } NdisReleaseSpinLock(&pAd->BATabLock); ASSERT(pBAEntry->list.qlen == 0); /* II. free memory of reordering mpdu table */ NdisAcquireSpinLock(&pAd->mpdu_blk_pool.lock); os_free_mem(pAd, pAd->mpdu_blk_pool.mem); NdisReleaseSpinLock(&pAd->mpdu_blk_pool.lock); }
static u16 ba_indicate_reordering_mpdus_in_order(struct rt_rtmp_adapter *pAd, struct rt_ba_rec_entry *pBAEntry, u16 StartSeq) { struct reordering_mpdu *mpdu_blk; u16 LastIndSeq = RESET_RCV_SEQ; NdisAcquireSpinLock(&pBAEntry->RxReRingLock); while ((mpdu_blk = ba_reordering_mpdu_probe(&pBAEntry->list))) { /* find in-order frame */ if (!SEQ_STEPONE(mpdu_blk->Sequence, StartSeq, MAXSEQ)) { break; } /* dequeue in-order frame from reodering list */ mpdu_blk = ba_reordering_mpdu_dequeue(&pBAEntry->list); /* pass this frame up */ ANNOUNCE_REORDERING_PACKET(pAd, mpdu_blk); /* move to next sequence */ StartSeq = mpdu_blk->Sequence; LastIndSeq = StartSeq; /* free mpdu_blk */ ba_mpdu_blk_free(pAd, mpdu_blk); } NdisReleaseSpinLock(&pBAEntry->RxReRingLock); /* update last indicated sequence */ return LastIndSeq; }
static void ba_enqueue_reordering_packet(struct rt_rtmp_adapter *pAd, struct rt_ba_rec_entry *pBAEntry, struct rt_rx_blk *pRxBlk, u8 FromWhichBSSID) { struct reordering_mpdu *mpdu_blk; u16 Sequence = (u16)pRxBlk->pHeader->Sequence; mpdu_blk = ba_mpdu_blk_alloc(pAd); if ((mpdu_blk != NULL) && (!RX_BLK_TEST_FLAG(pRxBlk, fRX_EAP))) { /* Write RxD buffer address & allocated buffer length */ NdisAcquireSpinLock(&pBAEntry->RxReRingLock); mpdu_blk->Sequence = Sequence; mpdu_blk->bAMSDU = RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU); convert_reordering_packet_to_preAMSDU_or_802_3_packet(pAd, pRxBlk, FromWhichBSSID); STATS_INC_RX_PACKETS(pAd, FromWhichBSSID); /* */ /* it is necessary for reordering packet to record */ /* which BSS it come from */ /* */ RTMP_SET_PACKET_IF(pRxBlk->pRxPacket, FromWhichBSSID); mpdu_blk->pPacket = pRxBlk->pRxPacket; if (ba_reordering_mpdu_insertsorted(&pBAEntry->list, mpdu_blk) == FALSE) { /* had been already within reordering list */ /* don't indicate */ RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_SUCCESS); ba_mpdu_blk_free(pAd, mpdu_blk); } ASSERT((0 <= pBAEntry->list.qlen) && (pBAEntry->list.qlen <= pBAEntry->BAWinSize)); NdisReleaseSpinLock(&pBAEntry->RxReRingLock); } else { DBGPRINT(RT_DEBUG_ERROR, (" (%d) Can't allocate reordering mpdu blk\n", pBAEntry->list.qlen)); /* * flush all pending reordering mpdus * and receving mpdu to upper layer * make tcp/ip to take care reordering mechanism */ /*ba_refresh_reordering_mpdus(pAd, pBAEntry); */ ba_indicate_reordering_mpdus_le_seq(pAd, pBAEntry, Sequence); pBAEntry->LastIndSeq = Sequence; INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID); } }
static void ba_refresh_reordering_mpdus(struct rt_rtmp_adapter *pAd, struct rt_ba_rec_entry *pBAEntry) { struct reordering_mpdu *mpdu_blk; NdisAcquireSpinLock(&pBAEntry->RxReRingLock); /* dequeue in-order frame from reodering list */ while ((mpdu_blk = ba_reordering_mpdu_dequeue(&pBAEntry->list))) { /* pass this frame up */ ANNOUNCE_REORDERING_PACKET(pAd, mpdu_blk); pBAEntry->LastIndSeq = mpdu_blk->Sequence; ba_mpdu_blk_free(pAd, mpdu_blk); /* update last indicated sequence */ } ASSERT(pBAEntry->list.qlen == 0); pBAEntry->LastIndSeq = RESET_RCV_SEQ; NdisReleaseSpinLock(&pBAEntry->RxReRingLock); }
static void ba_indicate_reordering_mpdus_le_seq(struct rt_rtmp_adapter *pAd, struct rt_ba_rec_entry *pBAEntry, u16 Sequence) { struct reordering_mpdu *mpdu_blk; NdisAcquireSpinLock(&pBAEntry->RxReRingLock); while ((mpdu_blk = ba_reordering_mpdu_probe(&pBAEntry->list))) { /* find in-order frame */ if ((mpdu_blk->Sequence == Sequence) || SEQ_SMALLER(mpdu_blk->Sequence, Sequence, MAXSEQ)) { /* dequeue in-order frame from reodering list */ mpdu_blk = ba_reordering_mpdu_dequeue(&pBAEntry->list); /* pass this frame up */ ANNOUNCE_REORDERING_PACKET(pAd, mpdu_blk); /* free mpdu_blk */ ba_mpdu_blk_free(pAd, mpdu_blk); } else { break; } } NdisReleaseSpinLock(&pBAEntry->RxReRingLock); }