Ejemplo n.º 1
0
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;
}
Ejemplo n.º 2
0
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;
}
Ejemplo n.º 3
0
void Indicate_AMPDU_Packet(struct rt_rtmp_adapter *pAd,
			   struct rt_rx_blk *pRxBlk, u8 FromWhichBSSID)
{
	u16 Idx;
	struct rt_ba_rec_entry *pBAEntry = NULL;
	u16 Sequence = pRxBlk->pHeader->Sequence;
	unsigned long Now32;
	u8 Wcid = pRxBlk->pRxWI->WirelessCliID;
	u8 TID = pRxBlk->pRxWI->TID;

	if (!RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU)
	    && (pRxBlk->DataSize > MAX_RX_PKT_LEN)) {
		/* release packet */
		RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket,
				    NDIS_STATUS_FAILURE);
		return;
	}

	if (Wcid < MAX_LEN_OF_MAC_TABLE) {
		Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID];
		if (Idx == 0) {
			/* Rec BA Session had been torn down */
			INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID);
			return;
		}
		pBAEntry = &pAd->BATable.BARecEntry[Idx];
	} else {
		/* impossible ! */
		ASSERT(0);
		/* release packet */
		RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket,
				    NDIS_STATUS_FAILURE);
		return;
	}

	ASSERT(pBAEntry);

	/* update last rx time */
	NdisGetSystemUpTime(&Now32);

	pBAEntry->rcvSeq = Sequence;

	ba_flush_reordering_timeout_mpdus(pAd, pBAEntry, Now32);
	pBAEntry->LastIndSeqAtTimer = Now32;

	/* */
	/* Reset Last Indicate Sequence */
	/* */
	if (pBAEntry->LastIndSeq == RESET_RCV_SEQ) {
		ASSERT((pBAEntry->list.qlen == 0)
		       && (pBAEntry->list.next == NULL));

		/* reset rcv sequence of BA session */
		pBAEntry->LastIndSeq = Sequence;
		pBAEntry->LastIndSeqAtTimer = Now32;
		INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID);
		return;
	}

	/* */
	/* I. Check if in order. */
	/* */
	if (SEQ_STEPONE(Sequence, pBAEntry->LastIndSeq, MAXSEQ)) {
		u16 LastIndSeq;

		pBAEntry->LastIndSeq = Sequence;
		INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID);
		LastIndSeq =
		    ba_indicate_reordering_mpdus_in_order(pAd, pBAEntry,
							  pBAEntry->LastIndSeq);
		if (LastIndSeq != RESET_RCV_SEQ) {
			pBAEntry->LastIndSeq = LastIndSeq;
		}
		pBAEntry->LastIndSeqAtTimer = Now32;
	}
	/* */
	/* II. Drop Duplicated Packet */
	/* */
	else if (Sequence == pBAEntry->LastIndSeq) {

		/* drop and release packet */
		pBAEntry->nDropPacket++;
		RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket,
				    NDIS_STATUS_FAILURE);
	}
	/* */
	/* III. Drop Old Received Packet */
	/* */
	else if (SEQ_SMALLER(Sequence, pBAEntry->LastIndSeq, MAXSEQ)) {

		/* drop and release packet */
		pBAEntry->nDropPacket++;
		RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket,
				    NDIS_STATUS_FAILURE);
	}
	/* */
	/* IV. Receive Sequence within Window Size */
	/* */
	else if (SEQ_SMALLER
		 (Sequence,
		  (((pBAEntry->LastIndSeq + pBAEntry->BAWinSize + 1)) & MAXSEQ),
		  MAXSEQ)) {
		ba_enqueue_reordering_packet(pAd, pBAEntry, pRxBlk,
					     FromWhichBSSID);
	}
	/* */
	/* V. Receive seq surpasses Win(lastseq + nMSDU). So refresh all reorder buffer */
	/* */
	else {
		long WinStartSeq, TmpSeq;

		TmpSeq = Sequence - (pBAEntry->BAWinSize) - 1;
		if (TmpSeq < 0) {
			TmpSeq = (MAXSEQ + 1) + TmpSeq;
		}
		WinStartSeq = (TmpSeq + 1) & MAXSEQ;
		ba_indicate_reordering_mpdus_le_seq(pAd, pBAEntry, WinStartSeq);
		pBAEntry->LastIndSeq = WinStartSeq;	/*TmpSeq; */

		pBAEntry->LastIndSeqAtTimer = Now32;

		ba_enqueue_reordering_packet(pAd, pBAEntry, pRxBlk,
					     FromWhichBSSID);

		TmpSeq =
		    ba_indicate_reordering_mpdus_in_order(pAd, pBAEntry,
							  pBAEntry->LastIndSeq);
		if (TmpSeq != RESET_RCV_SEQ) {
			pBAEntry->LastIndSeq = TmpSeq;
		}
	}
}