2 *************************************************************************
4 * 5F., No.36, Taiyuan St., Jhubei City,
8 * (c) Copyright 2002-2007, Ralink Technology, Inc.
10 * This program is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License as published by *
12 * the Free Software Foundation; either version 2 of the License, or *
13 * (at your option) any later version. *
15 * This program is distributed in the hope that it will be useful, *
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
18 * GNU General Public License for more details. *
20 * You should have received a copy of the GNU General Public License *
21 * along with this program; if not, write to the *
22 * Free Software Foundation, Inc., *
23 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
25 *************************************************************************
29 #ifdef DOT11_N_SUPPORT
31 #include "../rt_config.h"
34 #define BA_ORI_INIT_SEQ (pEntry->TxSeq[TID]) //1 // inital sequence number of BA session
36 #define ORI_SESSION_MAX_RETRY 8
37 #define ORI_BA_SESSION_TIMEOUT (2000) // ms
38 #define REC_BA_SESSION_IDLE_TIMEOUT (1000) // ms
40 #define REORDERING_PACKET_TIMEOUT ((100 * OS_HZ)/1000) // system ticks -- 100 ms
41 #define MAX_REORDERING_PACKET_TIMEOUT ((3000 * OS_HZ)/1000) // system ticks -- 100 ms
43 #define RESET_RCV_SEQ (0xFFFF)
45 static void ba_mpdu_blk_free(PRTMP_ADAPTER pAd, struct reordering_mpdu *mpdu_blk);
48 BA_ORI_ENTRY *BATableAllocOriEntry(
52 BA_REC_ENTRY *BATableAllocRecEntry(
56 VOID BAOriSessionSetupTimeout(
57 IN PVOID SystemSpecific1,
58 IN PVOID FunctionContext,
59 IN PVOID SystemSpecific2,
60 IN PVOID SystemSpecific3);
62 VOID BARecSessionIdleTimeout(
63 IN PVOID SystemSpecific1,
64 IN PVOID FunctionContext,
65 IN PVOID SystemSpecific2,
66 IN PVOID SystemSpecific3);
69 BUILD_TIMER_FUNCTION(BAOriSessionSetupTimeout);
70 BUILD_TIMER_FUNCTION(BARecSessionIdleTimeout);
72 #define ANNOUNCE_REORDERING_PACKET(_pAd, _mpdu_blk) \
73 Announce_Reordering_Packet(_pAd, _mpdu_blk);
75 VOID BA_MaxWinSizeReasign(
77 IN MAC_TABLE_ENTRY *pEntryPeer,
83 if (pAd->MACVersion >= RALINK_2883_VERSION) // 3*3
85 if (pAd->MACVersion >= RALINK_3070_VERSION)
87 if (pEntryPeer->WepStatus != Ndis802_11EncryptionDisabled)
88 MaxSize = 7; // for non-open mode
95 else if (pAd->MACVersion >= RALINK_2880E_VERSION) // 2880 e
97 if (pEntryPeer->WepStatus != Ndis802_11EncryptionDisabled)
98 MaxSize = 7; // for non-open mode
105 DBGPRINT(RT_DEBUG_TRACE, ("ba> Win Size = %d, Max Size = %d\n",
106 *pWinSize, MaxSize));
108 if ((*pWinSize) > MaxSize)
110 DBGPRINT(RT_DEBUG_TRACE, ("ba> reassign max win size from %d to %d\n",
111 *pWinSize, MaxSize));
117 void Announce_Reordering_Packet(IN PRTMP_ADAPTER pAd,
118 IN struct reordering_mpdu *mpdu)
120 PNDIS_PACKET pPacket;
122 pPacket = mpdu->pPacket;
127 BA_Reorder_AMSDU_Annnounce(pAd, pPacket);
132 // pass this 802.3 packet to upper layer or forward this packet to WM directly
135 #ifdef CONFIG_STA_SUPPORT
136 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
137 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pPacket, RTMP_GET_PACKET_IF(pPacket));
138 #endif // CONFIG_STA_SUPPORT //
143 * Insert a reordering mpdu into sorted linked list by sequence no.
145 BOOLEAN ba_reordering_mpdu_insertsorted(struct reordering_list *list, struct reordering_mpdu *mpdu)
148 struct reordering_mpdu **ppScan = &list->next;
150 while (*ppScan != NULL)
152 if (SEQ_SMALLER((*ppScan)->Sequence, mpdu->Sequence, MAXSEQ))
154 ppScan = &(*ppScan)->next;
156 else if ((*ppScan)->Sequence == mpdu->Sequence)
158 /* give up this duplicated frame */
168 mpdu->next = *ppScan;
176 * caller lock critical section if necessary
178 static inline void ba_enqueue(struct reordering_list *list, struct reordering_mpdu *mpdu_blk)
181 mpdu_blk->next = list->next;
182 list->next = mpdu_blk;
186 * caller lock critical section if necessary
188 static inline struct reordering_mpdu * ba_dequeue(struct reordering_list *list)
190 struct reordering_mpdu *mpdu_blk = NULL;
197 mpdu_blk = list->next;
200 list->next = mpdu_blk->next;
201 mpdu_blk->next = NULL;
208 static inline struct reordering_mpdu *ba_reordering_mpdu_dequeue(struct reordering_list *list)
210 return(ba_dequeue(list));
214 static inline struct reordering_mpdu *ba_reordering_mpdu_probe(struct reordering_list *list)
223 * free all resource for reordering mechanism
225 void ba_reordering_resource_release(PRTMP_ADAPTER pAd)
228 PBA_REC_ENTRY pBAEntry;
229 struct reordering_mpdu *mpdu_blk;
234 /* I. release all pending reordering packet */
235 NdisAcquireSpinLock(&pAd->BATabLock);
236 for (i = 0; i < MAX_LEN_OF_BA_REC_TABLE; i++)
238 pBAEntry = &Tab->BARecEntry[i];
239 if (pBAEntry->REC_BA_Status != Recipient_NONE)
241 while ((mpdu_blk = ba_reordering_mpdu_dequeue(&pBAEntry->list)))
243 ASSERT(mpdu_blk->pPacket);
244 RELEASE_NDIS_PACKET(pAd, mpdu_blk->pPacket, NDIS_STATUS_FAILURE);
245 ba_mpdu_blk_free(pAd, mpdu_blk);
249 NdisReleaseSpinLock(&pAd->BATabLock);
251 ASSERT(pBAEntry->list.qlen == 0);
252 /* II. free memory of reordering mpdu table */
253 NdisAcquireSpinLock(&pAd->mpdu_blk_pool.lock);
254 os_free_mem(pAd, pAd->mpdu_blk_pool.mem);
255 NdisReleaseSpinLock(&pAd->mpdu_blk_pool.lock);
261 * Allocate all resource for reordering mechanism
263 BOOLEAN ba_reordering_resource_init(PRTMP_ADAPTER pAd, int num)
267 struct reordering_mpdu *mpdu_blk;
268 struct reordering_list *freelist;
270 /* allocate spinlock */
271 NdisAllocateSpinLock(&pAd->mpdu_blk_pool.lock);
273 /* initialize freelist */
274 freelist = &pAd->mpdu_blk_pool.freelist;
275 freelist->next = NULL;
278 DBGPRINT(RT_DEBUG_TRACE, ("Allocate %d memory for BA reordering\n", (UINT32)(num*sizeof(struct reordering_mpdu))));
280 /* allocate number of mpdu_blk memory */
281 os_alloc_mem(pAd, (PUCHAR *)&mem, (num*sizeof(struct reordering_mpdu)));
283 pAd->mpdu_blk_pool.mem = mem;
287 DBGPRINT(RT_DEBUG_ERROR, ("Can't Allocate Memory for BA Reordering\n"));
291 /* build mpdu_blk free list */
292 for (i=0; i<num; i++)
295 mpdu_blk = (struct reordering_mpdu *) mem;
296 /* initial mpdu_blk */
297 NdisZeroMemory(mpdu_blk, sizeof(struct reordering_mpdu));
299 mem += sizeof(struct reordering_mpdu);
300 /* insert mpdu_blk into freelist */
301 ba_enqueue(freelist, mpdu_blk);
307 //static int blk_count=0; // sample take off, no use
309 static struct reordering_mpdu *ba_mpdu_blk_alloc(PRTMP_ADAPTER pAd)
311 struct reordering_mpdu *mpdu_blk;
313 NdisAcquireSpinLock(&pAd->mpdu_blk_pool.lock);
314 mpdu_blk = ba_dequeue(&pAd->mpdu_blk_pool.freelist);
319 NdisZeroMemory(mpdu_blk, sizeof(struct reordering_mpdu));
321 NdisReleaseSpinLock(&pAd->mpdu_blk_pool.lock);
325 static void ba_mpdu_blk_free(PRTMP_ADAPTER pAd, struct reordering_mpdu *mpdu_blk)
329 NdisAcquireSpinLock(&pAd->mpdu_blk_pool.lock);
331 ba_enqueue(&pAd->mpdu_blk_pool.freelist, mpdu_blk);
332 NdisReleaseSpinLock(&pAd->mpdu_blk_pool.lock);
336 static USHORT ba_indicate_reordering_mpdus_in_order(
337 IN PRTMP_ADAPTER pAd,
338 IN PBA_REC_ENTRY pBAEntry,
341 struct reordering_mpdu *mpdu_blk;
342 USHORT LastIndSeq = RESET_RCV_SEQ;
344 NdisAcquireSpinLock(&pBAEntry->RxReRingLock);
346 while ((mpdu_blk = ba_reordering_mpdu_probe(&pBAEntry->list)))
348 /* find in-order frame */
349 if (!SEQ_STEPONE(mpdu_blk->Sequence, StartSeq, MAXSEQ))
353 /* dequeue in-order frame from reodering list */
354 mpdu_blk = ba_reordering_mpdu_dequeue(&pBAEntry->list);
355 /* pass this frame up */
356 ANNOUNCE_REORDERING_PACKET(pAd, mpdu_blk);
357 /* move to next sequence */
358 StartSeq = mpdu_blk->Sequence;
359 LastIndSeq = StartSeq;
361 ba_mpdu_blk_free(pAd, mpdu_blk);
364 NdisReleaseSpinLock(&pBAEntry->RxReRingLock);
366 /* update last indicated sequence */
370 static void ba_indicate_reordering_mpdus_le_seq(
371 IN PRTMP_ADAPTER pAd,
372 IN PBA_REC_ENTRY pBAEntry,
375 struct reordering_mpdu *mpdu_blk;
377 NdisAcquireSpinLock(&pBAEntry->RxReRingLock);
378 while ((mpdu_blk = ba_reordering_mpdu_probe(&pBAEntry->list)))
380 /* find in-order frame */
381 if ((mpdu_blk->Sequence == Sequence) || SEQ_SMALLER(mpdu_blk->Sequence, Sequence, MAXSEQ))
383 /* dequeue in-order frame from reodering list */
384 mpdu_blk = ba_reordering_mpdu_dequeue(&pBAEntry->list);
385 /* pass this frame up */
386 ANNOUNCE_REORDERING_PACKET(pAd, mpdu_blk);
388 ba_mpdu_blk_free(pAd, mpdu_blk);
395 NdisReleaseSpinLock(&pBAEntry->RxReRingLock);
399 static void ba_refresh_reordering_mpdus(
400 IN PRTMP_ADAPTER pAd,
401 PBA_REC_ENTRY pBAEntry)
403 struct reordering_mpdu *mpdu_blk;
405 NdisAcquireSpinLock(&pBAEntry->RxReRingLock);
407 /* dequeue in-order frame from reodering list */
408 while ((mpdu_blk = ba_reordering_mpdu_dequeue(&pBAEntry->list)))
410 /* pass this frame up */
411 ANNOUNCE_REORDERING_PACKET(pAd, mpdu_blk);
413 pBAEntry->LastIndSeq = mpdu_blk->Sequence;
414 ba_mpdu_blk_free(pAd, mpdu_blk);
416 /* update last indicated sequence */
418 ASSERT(pBAEntry->list.qlen == 0);
419 pBAEntry->LastIndSeq = RESET_RCV_SEQ;
420 NdisReleaseSpinLock(&pBAEntry->RxReRingLock);
425 void ba_flush_reordering_timeout_mpdus(
426 IN PRTMP_ADAPTER pAd,
427 IN PBA_REC_ENTRY pBAEntry,
433 // if ((RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+REORDERING_PACKET_TIMEOUT)) &&
434 // (pBAEntry->list.qlen > ((pBAEntry->BAWinSize*7)/8))) //||
435 // (RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+(10*REORDERING_PACKET_TIMEOUT))) &&
436 // (pBAEntry->list.qlen > (pBAEntry->BAWinSize/8)))
437 if (RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+(MAX_REORDERING_PACKET_TIMEOUT/6)))
438 &&(pBAEntry->list.qlen > 1)
441 DBGPRINT(RT_DEBUG_TRACE,("timeout[%d] (%08lx-%08lx = %d > %d): %x, flush all!\n ", pBAEntry->list.qlen, Now32, (pBAEntry->LastIndSeqAtTimer),
442 (int)((long) Now32 - (long)(pBAEntry->LastIndSeqAtTimer)), MAX_REORDERING_PACKET_TIMEOUT,
443 pBAEntry->LastIndSeq));
444 ba_refresh_reordering_mpdus(pAd, pBAEntry);
445 pBAEntry->LastIndSeqAtTimer = Now32;
448 if (RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+(REORDERING_PACKET_TIMEOUT)))
449 && (pBAEntry->list.qlen > 0)
452 // DBGPRINT(RT_DEBUG_OFF, ("timeout[%d] (%lx-%lx = %d > %d): %x, ", pBAEntry->list.qlen, Now32, (pBAEntry->LastIndSeqAtTimer),
453 // (int)((long) Now32 - (long)(pBAEntry->LastIndSeqAtTimer)), REORDERING_PACKET_TIMEOUT,
454 // pBAEntry->LastIndSeq));
456 // force LastIndSeq to shift to LastIndSeq+1
458 Sequence = (pBAEntry->LastIndSeq+1) & MAXSEQ;
459 ba_indicate_reordering_mpdus_le_seq(pAd, pBAEntry, Sequence);
460 pBAEntry->LastIndSeqAtTimer = Now32;
461 pBAEntry->LastIndSeq = Sequence;
463 // indicate in-order mpdus
465 Sequence = ba_indicate_reordering_mpdus_in_order(pAd, pBAEntry, Sequence);
466 if (Sequence != RESET_RCV_SEQ)
468 pBAEntry->LastIndSeq = Sequence;
471 DBGPRINT(RT_DEBUG_OFF, ("%x, flush one!\n", pBAEntry->LastIndSeq));
478 * generate ADDBA request to
479 * set up BA agreement
481 VOID BAOriSessionSetUp(
482 IN PRTMP_ADAPTER pAd,
483 IN MAC_TABLE_ENTRY *pEntry,
490 //MLME_ADDBA_REQ_STRUCT AddbaReq;
491 BA_ORI_ENTRY *pBAEntry = NULL;
495 if ((pAd->CommonCfg.BACapability.field.AutoBA != TRUE) && (isForced == FALSE))
498 // if this entry is limited to use legacy tx mode, it doesn't generate BA.
499 if (RTMPStaFixedTxMode(pAd, pEntry) != FIXED_TXMODE_HT)
502 if ((pEntry->BADeclineBitmap & (1<<TID)) && (isForced == FALSE))
504 // try again after 3 secs
506 // DBGPRINT(RT_DEBUG_TRACE, ("DeCline BA from Peer\n"));
511 Idx = pEntry->BAOriWcidArray[TID];
514 // allocate a BA session
515 pBAEntry = BATableAllocOriEntry(pAd, &Idx);
516 if (pBAEntry == NULL)
518 DBGPRINT(RT_DEBUG_TRACE,("ADDBA - MlmeADDBAAction() allocate BA session failed \n"));
524 pBAEntry =&pAd->BATable.BAOriEntry[Idx];
527 if (pBAEntry->ORI_BA_Status >= Originator_WaitRes)
532 pEntry->BAOriWcidArray[TID] = Idx;
534 // Initialize BA session
535 pBAEntry->ORI_BA_Status = Originator_WaitRes;
536 pBAEntry->Wcid = pEntry->Aid;
537 pBAEntry->BAWinSize = pAd->CommonCfg.BACapability.field.RxBAWinLimit;
538 pBAEntry->Sequence = BA_ORI_INIT_SEQ;
539 pBAEntry->Token = 1; // (2008-01-21) Jan Lee recommends it - this token can't be 0
541 pBAEntry->TimeOutValue = TimeOut;
542 pBAEntry->pAdapter = pAd;
544 if (!(pEntry->TXBAbitmap & (1<<TID)))
546 RTMPInitTimer(pAd, &pBAEntry->ORIBATimer, GET_TIMER_FUNCTION(BAOriSessionSetupTimeout), pBAEntry, FALSE);
549 RTMPCancelTimer(&pBAEntry->ORIBATimer, &Cancelled);
551 // set timer to send ADDBA request
552 RTMPSetTimer(&pBAEntry->ORIBATimer, DelayTime);
555 VOID BAOriSessionAdd(
556 IN PRTMP_ADAPTER pAd,
557 IN MAC_TABLE_ENTRY *pEntry,
558 IN PFRAME_ADDBA_RSP pFrame)
560 BA_ORI_ENTRY *pBAEntry = NULL;
564 PUCHAR pOutBuffer2 = NULL;
569 TID = pFrame->BaParm.TID;
570 Idx = pEntry->BAOriWcidArray[TID];
571 pBAEntry =&pAd->BATable.BAOriEntry[Idx];
573 // Start fill in parameters.
574 if ((Idx !=0) && (pBAEntry->TID == TID) && (pBAEntry->ORI_BA_Status == Originator_WaitRes))
576 pBAEntry->BAWinSize = min(pBAEntry->BAWinSize, ((UCHAR)pFrame->BaParm.BufSize));
577 BA_MaxWinSizeReasign(pAd, pEntry, &pBAEntry->BAWinSize);
579 pBAEntry->TimeOutValue = pFrame->TimeOutValue;
580 pBAEntry->ORI_BA_Status = Originator_Done;
581 pAd->BATable.numDoneOriginator ++;
583 // reset sequence number
584 pBAEntry->Sequence = BA_ORI_INIT_SEQ;
586 pEntry->TXBAbitmap |= (1<<TID);
587 RTMPCancelTimer(&pBAEntry->ORIBATimer, &Cancelled);
589 pBAEntry->ORIBATimer.TimerValue = 0; //pFrame->TimeOutValue;
591 DBGPRINT(RT_DEBUG_TRACE,("%s : TXBAbitmap = %x, BAWinSize = %d, TimeOut = %ld\n", __FUNCTION__, pEntry->TXBAbitmap,
592 pBAEntry->BAWinSize, pBAEntry->ORIBATimer.TimerValue));
595 NStatus = MlmeAllocateMemory(pAd, &pOutBuffer2); //Get an unused nonpaged memory
596 if (NStatus != NDIS_STATUS_SUCCESS)
598 DBGPRINT(RT_DEBUG_TRACE,("BA - BAOriSessionAdd() allocate memory failed \n"));
603 #ifdef CONFIG_STA_SUPPORT
604 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
605 BarHeaderInit(pAd, &FrameBar, pAd->MacTab.Content[pBAEntry->Wcid].Addr, pAd->CurrentAddress);
606 #endif // CONFIG_STA_SUPPORT //
608 FrameBar.StartingSeq.field.FragNum = 0; // make sure sequence not clear in DEL function.
609 FrameBar.StartingSeq.field.StartSeq = pBAEntry->Sequence; // make sure sequence not clear in DEL funciton.
610 FrameBar.BarControl.TID = pBAEntry->TID; // make sure sequence not clear in DEL funciton.
611 MakeOutgoingFrame(pOutBuffer2, &FrameLen,
612 sizeof(FRAME_BAR), &FrameBar,
614 MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer2, FrameLen);
615 MlmeFreeMemory(pAd, pOutBuffer2);
618 if (pBAEntry->ORIBATimer.TimerValue)
619 RTMPSetTimer(&pBAEntry->ORIBATimer, pBAEntry->ORIBATimer.TimerValue); // in mSec
623 BOOLEAN BARecSessionAdd(
624 IN PRTMP_ADAPTER pAd,
625 IN MAC_TABLE_ENTRY *pEntry,
626 IN PFRAME_ADDBA_REQ pFrame)
628 BA_REC_ENTRY *pBAEntry = NULL;
629 BOOLEAN Status = TRUE;
641 TID = pFrame->BaParm.TID;
643 BAWinSize = min(((UCHAR)pFrame->BaParm.BufSize), (UCHAR)pAd->CommonCfg.BACapability.field.RxBAWinLimit);
651 Idx = pEntry->BARecWcidArray[TID];
656 pBAEntry = BATableAllocRecEntry(pAd, &Idx);
660 pBAEntry = &pAd->BATable.BARecEntry[Idx];
661 // flush all pending reordering mpdus
662 ba_refresh_reordering_mpdus(pAd, pBAEntry);
665 DBGPRINT(RT_DEBUG_TRACE,("%s(%ld): Idx = %d, BAWinSize(req %d) = %d\n", __FUNCTION__, pAd->BATable.numAsRecipient, Idx,
666 pFrame->BaParm.BufSize, BAWinSize));
668 // Start fill in parameters.
669 if (pBAEntry != NULL)
671 ASSERT(pBAEntry->list.qlen == 0);
673 pBAEntry->REC_BA_Status = Recipient_HandleRes;
674 pBAEntry->BAWinSize = BAWinSize;
675 pBAEntry->Wcid = pEntry->Aid;
677 pBAEntry->TimeOutValue = pFrame->TimeOutValue;
678 pBAEntry->REC_BA_Status = Recipient_Accept;
679 // initial sequence number
680 pBAEntry->LastIndSeq = RESET_RCV_SEQ; //pFrame->BaStartSeq.field.StartSeq;
682 DBGPRINT(RT_DEBUG_OFF, ("Start Seq = %08x\n", pFrame->BaStartSeq.field.StartSeq));
684 if (pEntry->RXBAbitmap & (1<<TID))
686 RTMPCancelTimer(&pBAEntry->RECBATimer, &Cancelled);
690 RTMPInitTimer(pAd, &pBAEntry->RECBATimer, GET_TIMER_FUNCTION(BARecSessionIdleTimeout), pBAEntry, TRUE);
695 pEntry->RXBAbitmap |= (1<<TID);
696 pEntry->BARecWcidArray[TID] = Idx;
698 pEntry->BADeclineBitmap &= ~(1<<TID);
700 // Set BA session mask in WCID table.
701 RTMP_ADD_BA_SESSION_TO_ASIC(pAd, pEntry->Aid, TID);
703 DBGPRINT(RT_DEBUG_TRACE,("MACEntry[%d]RXBAbitmap = 0x%x. BARecWcidArray=%d\n",
704 pEntry->Aid, pEntry->RXBAbitmap, pEntry->BARecWcidArray[TID]));
709 DBGPRINT(RT_DEBUG_TRACE,("Can't Accept ADDBA for %02x:%02x:%02x:%02x:%02x:%02x TID = %d\n",
710 PRINT_MAC(pEntry->Addr), TID));
716 BA_REC_ENTRY *BATableAllocRecEntry(
717 IN PRTMP_ADAPTER pAd,
721 BA_REC_ENTRY *pBAEntry = NULL;
724 NdisAcquireSpinLock(&pAd->BATabLock);
726 if (pAd->BATable.numAsRecipient >= MAX_BARECI_SESSION)
728 DBGPRINT(RT_DEBUG_OFF, ("BA Recipeint Session (%ld) > %d\n",
729 pAd->BATable.numAsRecipient, MAX_BARECI_SESSION));
733 // reserve idx 0 to identify BAWcidArray[TID] as empty
734 for (i=1; i < MAX_LEN_OF_BA_REC_TABLE; i++)
736 pBAEntry =&pAd->BATable.BARecEntry[i];
737 if ((pBAEntry->REC_BA_Status == Recipient_NONE))
740 pAd->BATable.numAsRecipient++;
741 pBAEntry->REC_BA_Status = Recipient_USED;
748 NdisReleaseSpinLock(&pAd->BATabLock);
752 BA_ORI_ENTRY *BATableAllocOriEntry(
753 IN PRTMP_ADAPTER pAd,
757 BA_ORI_ENTRY *pBAEntry = NULL;
759 NdisAcquireSpinLock(&pAd->BATabLock);
761 if (pAd->BATable.numAsOriginator >= (MAX_LEN_OF_BA_ORI_TABLE))
766 // reserve idx 0 to identify BAWcidArray[TID] as empty
767 for (i=1; i<MAX_LEN_OF_BA_ORI_TABLE; i++)
769 pBAEntry =&pAd->BATable.BAOriEntry[i];
770 if ((pBAEntry->ORI_BA_Status == Originator_NONE))
773 pAd->BATable.numAsOriginator++;
774 pBAEntry->ORI_BA_Status = Originator_USED;
775 pBAEntry->pAdapter = pAd;
782 NdisReleaseSpinLock(&pAd->BATabLock);
787 VOID BATableFreeOriEntry(
788 IN PRTMP_ADAPTER pAd,
791 BA_ORI_ENTRY *pBAEntry = NULL;
792 MAC_TABLE_ENTRY *pEntry;
795 if ((Idx == 0) || (Idx >= MAX_LEN_OF_BA_ORI_TABLE))
798 pBAEntry =&pAd->BATable.BAOriEntry[Idx];
800 if (pBAEntry->ORI_BA_Status != Originator_NONE)
802 pEntry = &pAd->MacTab.Content[pBAEntry->Wcid];
803 pEntry->BAOriWcidArray[pBAEntry->TID] = 0;
806 NdisAcquireSpinLock(&pAd->BATabLock);
807 if (pBAEntry->ORI_BA_Status == Originator_Done)
809 pAd->BATable.numDoneOriginator -= 1;
810 pEntry->TXBAbitmap &= (~(1<<(pBAEntry->TID) ));
811 DBGPRINT(RT_DEBUG_TRACE, ("BATableFreeOriEntry numAsOriginator= %ld\n", pAd->BATable.numAsRecipient));
812 // Erase Bitmap flag.
815 ASSERT(pAd->BATable.numAsOriginator != 0);
817 pAd->BATable.numAsOriginator -= 1;
819 pBAEntry->ORI_BA_Status = Originator_NONE;
821 NdisReleaseSpinLock(&pAd->BATabLock);
826 VOID BATableFreeRecEntry(
827 IN PRTMP_ADAPTER pAd,
830 BA_REC_ENTRY *pBAEntry = NULL;
831 MAC_TABLE_ENTRY *pEntry;
834 if ((Idx == 0) || (Idx >= MAX_LEN_OF_BA_REC_TABLE))
837 pBAEntry =&pAd->BATable.BARecEntry[Idx];
839 if (pBAEntry->REC_BA_Status != Recipient_NONE)
841 pEntry = &pAd->MacTab.Content[pBAEntry->Wcid];
842 pEntry->BARecWcidArray[pBAEntry->TID] = 0;
844 NdisAcquireSpinLock(&pAd->BATabLock);
846 ASSERT(pAd->BATable.numAsRecipient != 0);
848 pAd->BATable.numAsRecipient -= 1;
850 pBAEntry->REC_BA_Status = Recipient_NONE;
851 NdisReleaseSpinLock(&pAd->BATabLock);
856 VOID BAOriSessionTearDown(
857 IN OUT PRTMP_ADAPTER pAd,
861 IN BOOLEAN bForceSend)
864 BA_ORI_ENTRY *pBAEntry;
867 if (Wcid >= MAX_LEN_OF_MAC_TABLE)
873 // Locate corresponding BA Originator Entry in BA Table with the (pAddr,TID).
875 Idx = pAd->MacTab.Content[Wcid].BAOriWcidArray[TID];
876 if ((Idx == 0) || (Idx >= MAX_LEN_OF_BA_ORI_TABLE))
878 if (bForceSend == TRUE)
880 // force send specified TID DelBA
881 MLME_DELBA_REQ_STRUCT DelbaReq;
882 MLME_QUEUE_ELEM *Elem = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG);
885 NdisZeroMemory(&DelbaReq, sizeof(DelbaReq));
886 NdisZeroMemory(Elem, sizeof(MLME_QUEUE_ELEM));
888 COPY_MAC_ADDR(DelbaReq.Addr, pAd->MacTab.Content[Wcid].Addr);
889 DelbaReq.Wcid = Wcid;
891 DelbaReq.Initiator = ORIGINATOR;
892 Elem->MsgLen = sizeof(DelbaReq);
893 NdisMoveMemory(Elem->Msg, &DelbaReq, sizeof(DelbaReq));
894 MlmeDELBAAction(pAd, Elem);
899 DBGPRINT(RT_DEBUG_ERROR, ("%s(bForceSend):alloc memory failed!\n", __FUNCTION__));
906 DBGPRINT(RT_DEBUG_TRACE,("%s===>Wcid=%d.TID=%d \n", __FUNCTION__, Wcid, TID));
908 pBAEntry = &pAd->BATable.BAOriEntry[Idx];
909 DBGPRINT(RT_DEBUG_TRACE,("\t===>Idx = %ld, Wcid=%d.TID=%d, ORI_BA_Status = %d \n", Idx, Wcid, TID, pBAEntry->ORI_BA_Status));
911 // Prepare DelBA action frame and send to the peer.
913 if ((bPassive == FALSE) && (TID == pBAEntry->TID) && (pBAEntry->ORI_BA_Status == Originator_Done))
915 MLME_DELBA_REQ_STRUCT DelbaReq;
916 MLME_QUEUE_ELEM *Elem = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG);
919 NdisZeroMemory(&DelbaReq, sizeof(DelbaReq));
920 NdisZeroMemory(Elem, sizeof(MLME_QUEUE_ELEM));
922 COPY_MAC_ADDR(DelbaReq.Addr, pAd->MacTab.Content[Wcid].Addr);
923 DelbaReq.Wcid = Wcid;
924 DelbaReq.TID = pBAEntry->TID;
925 DelbaReq.Initiator = ORIGINATOR;
926 Elem->MsgLen = sizeof(DelbaReq);
927 NdisMoveMemory(Elem->Msg, &DelbaReq, sizeof(DelbaReq));
928 MlmeDELBAAction(pAd, Elem);
933 DBGPRINT(RT_DEBUG_ERROR, ("%s():alloc memory failed!\n", __FUNCTION__));
937 RTMPCancelTimer(&pBAEntry->ORIBATimer, &Cancelled);
938 BATableFreeOriEntry(pAd, Idx);
942 //BAOriSessionSetUp(pAd, &pAd->MacTab.Content[Wcid], TID, 0, 10000, TRUE);
946 VOID BARecSessionTearDown(
947 IN OUT PRTMP_ADAPTER pAd,
953 BA_REC_ENTRY *pBAEntry;
955 if (Wcid >= MAX_LEN_OF_MAC_TABLE)
961 // Locate corresponding BA Originator Entry in BA Table with the (pAddr,TID).
963 Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID];
967 DBGPRINT(RT_DEBUG_TRACE,("%s===>Wcid=%d.TID=%d \n", __FUNCTION__, Wcid, TID));
970 pBAEntry = &pAd->BATable.BARecEntry[Idx];
971 DBGPRINT(RT_DEBUG_TRACE,("\t===>Idx = %ld, Wcid=%d.TID=%d, REC_BA_Status = %d \n", Idx, Wcid, TID, pBAEntry->REC_BA_Status));
973 // Prepare DelBA action frame and send to the peer.
975 if ((TID == pBAEntry->TID) && (pBAEntry->REC_BA_Status == Recipient_Accept))
977 MLME_DELBA_REQ_STRUCT DelbaReq;
982 RTMPCancelTimer(&pBAEntry->RECBATimer, &Cancelled);
985 // 1. Send DELBA Action Frame
987 if (bPassive == FALSE)
989 MLME_QUEUE_ELEM *Elem = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG);
992 NdisZeroMemory(&DelbaReq, sizeof(DelbaReq));
993 NdisZeroMemory(Elem, sizeof(MLME_QUEUE_ELEM));
995 COPY_MAC_ADDR(DelbaReq.Addr, pAd->MacTab.Content[Wcid].Addr);
996 DelbaReq.Wcid = Wcid;
998 DelbaReq.Initiator = RECIPIENT;
999 Elem->MsgLen = sizeof(DelbaReq);
1000 NdisMoveMemory(Elem->Msg, &DelbaReq, sizeof(DelbaReq));
1001 MlmeDELBAAction(pAd, Elem);
1006 DBGPRINT(RT_DEBUG_ERROR, ("%s():alloc memory failed!\n", __FUNCTION__));
1013 // 2. Free resource of BA session
1015 // flush all pending reordering mpdus
1016 ba_refresh_reordering_mpdus(pAd, pBAEntry);
1018 NdisAcquireSpinLock(&pAd->BATabLock);
1020 // Erase Bitmap flag.
1021 pBAEntry->LastIndSeq = RESET_RCV_SEQ;
1022 pBAEntry->BAWinSize = 0;
1023 // Erase Bitmap flag at software mactable
1024 pAd->MacTab.Content[Wcid].RXBAbitmap &= (~(1<<(pBAEntry->TID)));
1025 pAd->MacTab.Content[Wcid].BARecWcidArray[TID] = 0;
1027 RTMP_DEL_BA_SESSION_FROM_ASIC(pAd, Wcid, TID);
1029 NdisReleaseSpinLock(&pAd->BATabLock);
1033 BATableFreeRecEntry(pAd, Idx);
1036 VOID BASessionTearDownALL(
1037 IN OUT PRTMP_ADAPTER pAd,
1042 for (i=0; i<NUM_OF_TID; i++)
1044 BAOriSessionTearDown(pAd, Wcid, i, FALSE, FALSE);
1045 BARecSessionTearDown(pAd, Wcid, i, FALSE);
1051 ==========================================================================
1053 Retry sending ADDBA Reqest.
1055 IRQL = DISPATCH_LEVEL
1058 p8023Header: if this is already 802.3 format, p8023Header is NULL
1060 Return : TRUE if put into rx reordering buffer, shouldn't indicaterxhere.
1061 FALSE , then continue indicaterx at this moment.
1062 ==========================================================================
1064 VOID BAOriSessionSetupTimeout(
1065 IN PVOID SystemSpecific1,
1066 IN PVOID FunctionContext,
1067 IN PVOID SystemSpecific2,
1068 IN PVOID SystemSpecific3)
1070 BA_ORI_ENTRY *pBAEntry = (BA_ORI_ENTRY *)FunctionContext;
1071 MAC_TABLE_ENTRY *pEntry;
1074 if (pBAEntry == NULL)
1077 pAd = pBAEntry->pAdapter;
1079 #ifdef CONFIG_STA_SUPPORT
1080 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1082 // Do nothing if monitor mode is on
1083 if (MONITOR_ON(pAd))
1086 #endif // CONFIG_STA_SUPPORT //
1089 // Nothing to do in ATE mode.
1092 #endif // RALINK_ATE //
1094 pEntry = &pAd->MacTab.Content[pBAEntry->Wcid];
1096 if ((pBAEntry->ORI_BA_Status == Originator_WaitRes) && (pBAEntry->Token < ORI_SESSION_MAX_RETRY))
1098 MLME_ADDBA_REQ_STRUCT AddbaReq;
1100 NdisZeroMemory(&AddbaReq, sizeof(AddbaReq));
1101 COPY_MAC_ADDR(AddbaReq.pAddr, pEntry->Addr);
1102 AddbaReq.Wcid = (UCHAR)(pEntry->Aid);
1103 AddbaReq.TID = pBAEntry->TID;
1104 AddbaReq.BaBufSize = pAd->CommonCfg.BACapability.field.RxBAWinLimit;
1105 AddbaReq.TimeOutValue = 0;
1106 AddbaReq.Token = pBAEntry->Token;
1107 MlmeEnqueue(pAd, ACTION_STATE_MACHINE, MT2_MLME_ADD_BA_CATE, sizeof(MLME_ADDBA_REQ_STRUCT), (PVOID)&AddbaReq);
1108 RTMP_MLME_HANDLER(pAd);
1109 DBGPRINT(RT_DEBUG_TRACE,("BA Ori Session Timeout(%d) : Send ADD BA again\n", pBAEntry->Token));
1112 RTMPSetTimer(&pBAEntry->ORIBATimer, ORI_BA_SESSION_TIMEOUT);
1116 BATableFreeOriEntry(pAd, pEntry->BAOriWcidArray[pBAEntry->TID]);
1121 ==========================================================================
1123 Retry sending ADDBA Reqest.
1125 IRQL = DISPATCH_LEVEL
1128 p8023Header: if this is already 802.3 format, p8023Header is NULL
1130 Return : TRUE if put into rx reordering buffer, shouldn't indicaterxhere.
1131 FALSE , then continue indicaterx at this moment.
1132 ==========================================================================
1134 VOID BARecSessionIdleTimeout(
1135 IN PVOID SystemSpecific1,
1136 IN PVOID FunctionContext,
1137 IN PVOID SystemSpecific2,
1138 IN PVOID SystemSpecific3)
1141 BA_REC_ENTRY *pBAEntry = (BA_REC_ENTRY *)FunctionContext;
1145 if (pBAEntry == NULL)
1148 if ((pBAEntry->REC_BA_Status == Recipient_Accept))
1150 NdisGetSystemUpTime(&Now32);
1152 if (RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer + REC_BA_SESSION_IDLE_TIMEOUT)))
1154 pAd = pBAEntry->pAdapter;
1155 // flush all pending reordering mpdus
1156 ba_refresh_reordering_mpdus(pAd, pBAEntry);
1157 DBGPRINT(RT_DEBUG_OFF, ("%ld: REC BA session Timeout\n", Now32));
1163 VOID PeerAddBAReqAction(
1164 IN PRTMP_ADAPTER pAd,
1165 IN MLME_QUEUE_ELEM *Elem)
1172 FRAME_ADDBA_RSP ADDframe;
1173 PUCHAR pOutBuffer = NULL;
1174 NDIS_STATUS NStatus;
1175 PFRAME_ADDBA_REQ pAddreqFrame = NULL;
1179 PMAC_TABLE_ENTRY pMacEntry;
1181 DBGPRINT(RT_DEBUG_TRACE, ("%s ==> (Wcid = %d)\n", __FUNCTION__, Elem->Wcid));
1183 //hex_dump("AddBAReq", Elem->Msg, Elem->MsgLen);
1185 //ADDBA Request from unknown peer, ignore this.
1186 if (Elem->Wcid >= MAX_LEN_OF_MAC_TABLE)
1189 pMacEntry = &pAd->MacTab.Content[Elem->Wcid];
1190 DBGPRINT(RT_DEBUG_TRACE,("BA - PeerAddBAReqAction----> \n"));
1191 ptemp = (PULONG)Elem->Msg;
1192 //DBGPRINT_RAW(RT_DEBUG_EMU, ("%08x:: %08x:: %08x:: %08x:: %08x:: %08x:: %08x:: %08x:: %08x\n", *(ptemp), *(ptemp+1), *(ptemp+2), *(ptemp+3), *(ptemp+4), *(ptemp+5), *(ptemp+6), *(ptemp+7), *(ptemp+8)));
1194 if (PeerAddBAReqActionSanity(pAd, Elem->Msg, Elem->MsgLen, pAddr))
1197 if ((pAd->CommonCfg.bBADecline == FALSE) && IS_HT_STA(pMacEntry))
1199 pAddreqFrame = (PFRAME_ADDBA_REQ)(&Elem->Msg[0]);
1200 DBGPRINT(RT_DEBUG_OFF, ("Rcv Wcid(%d) AddBAReq\n", Elem->Wcid));
1201 if (BARecSessionAdd(pAd, &pAd->MacTab.Content[Elem->Wcid], pAddreqFrame))
1204 Status = 38; // more parameters have invalid values
1208 Status = 37; // the request has been declined.
1212 if (pAd->MacTab.Content[Elem->Wcid].ValidAsCLI)
1213 ASSERT(pAd->MacTab.Content[Elem->Wcid].Sst == SST_ASSOC);
1215 pAddreqFrame = (PFRAME_ADDBA_REQ)(&Elem->Msg[0]);
1216 // 2. Always send back ADDBA Response
1217 NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory
1218 if (NStatus != NDIS_STATUS_SUCCESS)
1220 DBGPRINT(RT_DEBUG_TRACE,("ACTION - PeerBAAction() allocate memory failed \n"));
1224 NdisZeroMemory(&ADDframe, sizeof(FRAME_ADDBA_RSP));
1225 // 2-1. Prepare ADDBA Response frame.
1226 #ifdef CONFIG_STA_SUPPORT
1227 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1230 ActHeaderInit(pAd, &ADDframe.Hdr, pAddr, pAd->CurrentAddress, pAd->CommonCfg.Bssid);
1232 #ifdef QOS_DLS_SUPPORT
1233 if (pAd->MacTab.Content[Elem->Wcid].ValidAsDls)
1234 ActHeaderInit(pAd, &ADDframe.Hdr, pAddr, pAd->CurrentAddress, pAd->CommonCfg.Bssid);
1236 #endif // QOS_DLS_SUPPORT //
1237 ActHeaderInit(pAd, &ADDframe.Hdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pAddr);
1239 #endif // CONFIG_STA_SUPPORT //
1240 ADDframe.Category = CATEGORY_BA;
1241 ADDframe.Action = ADDBA_RESP;
1242 ADDframe.Token = pAddreqFrame->Token;
1243 // What is the Status code?? need to check.
1244 ADDframe.StatusCode = Status;
1245 ADDframe.BaParm.BAPolicy = IMMED_BA;
1246 ADDframe.BaParm.AMSDUSupported = 0;
1247 ADDframe.BaParm.TID = pAddreqFrame->BaParm.TID;
1248 ADDframe.BaParm.BufSize = min(((UCHAR)pAddreqFrame->BaParm.BufSize), (UCHAR)pAd->CommonCfg.BACapability.field.RxBAWinLimit);
1249 if (ADDframe.BaParm.BufSize == 0)
1251 ADDframe.BaParm.BufSize = 64;
1253 ADDframe.TimeOutValue = 0; //pAddreqFrame->TimeOutValue;
1255 *(USHORT *)(&ADDframe.BaParm) = cpu2le16(*(USHORT *)(&ADDframe.BaParm));
1256 ADDframe.StatusCode = cpu2le16(ADDframe.StatusCode);
1257 ADDframe.TimeOutValue = cpu2le16(ADDframe.TimeOutValue);
1259 MakeOutgoingFrame(pOutBuffer, &FrameLen,
1260 sizeof(FRAME_ADDBA_RSP), &ADDframe,
1262 MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
1263 MlmeFreeMemory(pAd, pOutBuffer);
1265 DBGPRINT(RT_DEBUG_TRACE, ("%s(%d): TID(%d), BufSize(%d) <== \n", __FUNCTION__, Elem->Wcid, ADDframe.BaParm.TID,
1266 ADDframe.BaParm.BufSize));
1270 VOID PeerAddBARspAction(
1271 IN PRTMP_ADAPTER pAd,
1272 IN MLME_QUEUE_ELEM *Elem)
1276 //PUCHAR pOutBuffer = NULL;
1277 PFRAME_ADDBA_RSP pFrame = NULL;
1278 //PBA_ORI_ENTRY pBAEntry;
1280 //ADDBA Response from unknown peer, ignore this.
1281 if (Elem->Wcid >= MAX_LEN_OF_MAC_TABLE)
1284 DBGPRINT(RT_DEBUG_TRACE, ("%s ==> Wcid(%d)\n", __FUNCTION__, Elem->Wcid));
1286 //hex_dump("PeerAddBARspAction()", Elem->Msg, Elem->MsgLen);
1288 if (PeerAddBARspActionSanity(pAd, Elem->Msg, Elem->MsgLen))
1290 pFrame = (PFRAME_ADDBA_RSP)(&Elem->Msg[0]);
1292 DBGPRINT(RT_DEBUG_TRACE, ("\t\t StatusCode = %d\n", pFrame->StatusCode));
1293 switch (pFrame->StatusCode)
1296 // I want a BAsession with this peer as an originator.
1297 BAOriSessionAdd(pAd, &pAd->MacTab.Content[Elem->Wcid], pFrame);
1300 // check status == USED ???
1301 BAOriSessionTearDown(pAd, Elem->Wcid, pFrame->BaParm.TID, TRUE, FALSE);
1304 // Rcv Decline StatusCode
1305 if ((pFrame->StatusCode == 37)
1306 #ifdef CONFIG_STA_SUPPORT
1307 || ((pAd->OpMode == OPMODE_STA) && STA_TGN_WIFI_ON(pAd) && (pFrame->StatusCode != 0))
1308 #endif // CONFIG_STA_SUPPORT //
1311 pAd->MacTab.Content[Elem->Wcid].BADeclineBitmap |= 1<<pFrame->BaParm.TID;
1316 VOID PeerDelBAAction(
1317 IN PRTMP_ADAPTER pAd,
1318 IN MLME_QUEUE_ELEM *Elem)
1322 //PUCHAR pOutBuffer = NULL;
1323 PFRAME_DELBA_REQ pDelFrame = NULL;
1325 DBGPRINT(RT_DEBUG_TRACE,("%s ==>\n", __FUNCTION__));
1326 //DELBA Request from unknown peer, ignore this.
1327 if (PeerDelBAActionSanity(pAd, Elem->Wcid, Elem->Msg, Elem->MsgLen))
1329 pDelFrame = (PFRAME_DELBA_REQ)(&Elem->Msg[0]);
1330 if (pDelFrame->DelbaParm.Initiator == ORIGINATOR)
1332 DBGPRINT(RT_DEBUG_TRACE,("BA - PeerDelBAAction----> ORIGINATOR\n"));
1333 BARecSessionTearDown(pAd, Elem->Wcid, pDelFrame->DelbaParm.TID, TRUE);
1337 DBGPRINT(RT_DEBUG_TRACE,("BA - PeerDelBAAction----> RECIPIENT, Reason = %d\n", pDelFrame->ReasonCode));
1338 //hex_dump("DelBA Frame", pDelFrame, Elem->MsgLen);
1339 BAOriSessionTearDown(pAd, Elem->Wcid, pDelFrame->DelbaParm.TID, TRUE, FALSE);
1345 BOOLEAN CntlEnqueueForRecv(
1346 IN PRTMP_ADAPTER pAd,
1349 IN PFRAME_BA_REQ pMsg)
1351 PFRAME_BA_REQ pFrame = pMsg;
1352 //PRTMP_REORDERBUF pBuffer;
1353 //PRTMP_REORDERBUF pDmaBuf;
1354 PBA_REC_ENTRY pBAEntry;
1360 TID = (UCHAR)pFrame->BARControl.TID;
1362 DBGPRINT(RT_DEBUG_TRACE, ("%s(): BAR-Wcid(%ld), Tid (%d)\n", __FUNCTION__, Wcid, TID));
1363 //hex_dump("BAR", (PCHAR) pFrame, MsgLen);
1364 // Do nothing if the driver is starting halt state.
1365 // This might happen when timer already been fired before cancel timer with mlmehalt
1366 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
1369 // First check the size, it MUST not exceed the mlme queue size
1370 if (MsgLen > MGMT_DMA_BUFFER_SIZE)
1372 DBGPRINT_ERR(("CntlEnqueueForRecv: frame too large, size = %ld \n", MsgLen));
1375 else if (MsgLen != sizeof(FRAME_BA_REQ))
1377 DBGPRINT_ERR(("CntlEnqueueForRecv: BlockAck Request frame length size = %ld incorrect\n", MsgLen));
1380 else if (MsgLen != sizeof(FRAME_BA_REQ))
1382 DBGPRINT_ERR(("CntlEnqueueForRecv: BlockAck Request frame length size = %ld incorrect\n", MsgLen));
1386 if ((Wcid < MAX_LEN_OF_MAC_TABLE) && (TID < 8))
1388 // if this receiving packet is from SA that is in our OriEntry. Since WCID <9 has direct mapping. no need search.
1389 Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID];
1390 pBAEntry = &pAd->BATable.BARecEntry[Idx];
1397 DBGPRINT(RT_DEBUG_TRACE, ("BAR(%ld) : Tid (%d) - %04x:%04x\n", Wcid, TID, pFrame->BAStartingSeq.field.StartSeq, pBAEntry->LastIndSeq ));
1399 if (SEQ_SMALLER(pBAEntry->LastIndSeq, pFrame->BAStartingSeq.field.StartSeq, MAXSEQ))
1401 //DBGPRINT(RT_DEBUG_TRACE, ("BAR Seq = %x, LastIndSeq = %x\n", pFrame->BAStartingSeq.field.StartSeq, pBAEntry->LastIndSeq));
1402 ba_indicate_reordering_mpdus_le_seq(pAd, pBAEntry, pFrame->BAStartingSeq.field.StartSeq);
1403 pBAEntry->LastIndSeq = (pFrame->BAStartingSeq.field.StartSeq == 0) ? MAXSEQ :(pFrame->BAStartingSeq.field.StartSeq -1);
1405 //ba_refresh_reordering_mpdus(pAd, pBAEntry);
1410 Description : Send PSMP Action frame If PSMP mode switches.
1412 VOID SendPSMPAction(
1413 IN PRTMP_ADAPTER pAd,
1417 PUCHAR pOutBuffer = NULL;
1418 NDIS_STATUS NStatus;
1420 FRAME_PSMP_ACTION Frame;
1423 NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory
1424 if (NStatus != NDIS_STATUS_SUCCESS)
1426 DBGPRINT(RT_DEBUG_ERROR,("BA - MlmeADDBAAction() allocate memory failed \n"));
1429 #ifdef CONFIG_STA_SUPPORT
1430 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1431 ActHeaderInit(pAd, &Frame.Hdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pAd->MacTab.Content[Wcid].Addr);
1432 #endif // CONFIG_STA_SUPPORT //
1434 Frame.Category = CATEGORY_HT;
1435 Frame.Action = SMPS_ACTION;
1441 &&(pAd->Antenna.field.RxPath>1||pAd->Antenna.field.TxPath>1))
1443 RTMP_ASIC_MMPS_DISABLE(pAd);
1454 &&(pAd->Antenna.field.RxPath>1||pAd->Antenna.field.TxPath>1))
1456 RTMP_ASIC_MMPS_ENABLE(pAd);
1462 MakeOutgoingFrame(pOutBuffer, &FrameLen,
1463 sizeof(FRAME_PSMP_ACTION), &Frame,
1465 MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
1466 MlmeFreeMemory(pAd, pOutBuffer);
1467 DBGPRINT(RT_DEBUG_ERROR,("HT - SendPSMPAction( %d ) \n", Frame.Psmp));
1471 #define RADIO_MEASUREMENT_REQUEST_ACTION 0
1473 typedef struct PACKED
1475 UCHAR RegulatoryClass;
1476 UCHAR ChannelNumber;
1477 USHORT RandomInterval;
1478 USHORT MeasurementDuration;
1479 UCHAR MeasurementMode;
1480 UCHAR BSSID[MAC_ADDR_LEN];
1481 UCHAR ReportingCondition;
1483 UCHAR SSIDIE[2]; // 2 byte
1486 typedef struct PACKED
1498 void convert_reordering_packet_to_preAMSDU_or_802_3_packet(
1499 IN PRTMP_ADAPTER pAd,
1501 IN UCHAR FromWhichBSSID)
1503 PNDIS_PACKET pRxPkt;
1504 UCHAR Header802_3[LENGTH_802_3];
1506 // 1. get 802.3 Header
1508 // a. pointer pRxBlk->pData to payload
1509 // b. modify pRxBlk->DataSize
1511 #ifdef CONFIG_STA_SUPPORT
1512 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1513 RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3);
1514 #endif // CONFIG_STA_SUPPORT //
1516 ASSERT(pRxBlk->pRxPacket);
1517 pRxPkt = RTPKT_TO_OSPKT(pRxBlk->pRxPacket);
1519 SET_OS_PKT_NETDEV(pRxPkt, get_netdev_from_bssid(pAd, FromWhichBSSID));
1520 SET_OS_PKT_DATAPTR(pRxPkt, pRxBlk->pData);
1521 SET_OS_PKT_LEN(pRxPkt, pRxBlk->DataSize);
1522 SET_OS_PKT_DATATAIL(pRxPkt, pRxBlk->pData, pRxBlk->DataSize);
1525 // copy 802.3 header, if necessary
1527 if (!RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU))
1530 #ifdef CONFIG_STA_SUPPORT
1531 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1534 NdisMoveMemory(skb_push(pRxPkt, LENGTH_802_3), Header802_3, LENGTH_802_3);
1537 #endif // CONFIG_STA_SUPPORT //
1542 #define INDICATE_LEGACY_OR_AMSDU(_pAd, _pRxBlk, _fromWhichBSSID) \
1545 if (RX_BLK_TEST_FLAG(_pRxBlk, fRX_AMSDU)) \
1547 Indicate_AMSDU_Packet(_pAd, _pRxBlk, _fromWhichBSSID); \
1549 else if (RX_BLK_TEST_FLAG(_pRxBlk, fRX_EAP)) \
1551 Indicate_EAPOL_Packet(_pAd, _pRxBlk, _fromWhichBSSID); \
1555 Indicate_Legacy_Packet(_pAd, _pRxBlk, _fromWhichBSSID); \
1561 static VOID ba_enqueue_reordering_packet(
1562 IN PRTMP_ADAPTER pAd,
1563 IN PBA_REC_ENTRY pBAEntry,
1565 IN UCHAR FromWhichBSSID)
1567 struct reordering_mpdu *mpdu_blk;
1568 UINT16 Sequence = (UINT16) pRxBlk->pHeader->Sequence;
1570 mpdu_blk = ba_mpdu_blk_alloc(pAd);
1571 if ((mpdu_blk != NULL) &&
1572 (!RX_BLK_TEST_FLAG(pRxBlk, fRX_EAP)))
1574 // Write RxD buffer address & allocated buffer length
1575 NdisAcquireSpinLock(&pBAEntry->RxReRingLock);
1577 mpdu_blk->Sequence = Sequence;
1579 mpdu_blk->bAMSDU = RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU);
1581 convert_reordering_packet_to_preAMSDU_or_802_3_packet(pAd, pRxBlk, FromWhichBSSID);
1583 STATS_INC_RX_PACKETS(pAd, FromWhichBSSID);
1586 // it is necessary for reordering packet to record
1587 // which BSS it come from
1589 RTMP_SET_PACKET_IF(pRxBlk->pRxPacket, FromWhichBSSID);
1591 mpdu_blk->pPacket = pRxBlk->pRxPacket;
1593 if (ba_reordering_mpdu_insertsorted(&pBAEntry->list, mpdu_blk) == FALSE)
1595 // had been already within reordering list
1597 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_SUCCESS);
1598 ba_mpdu_blk_free(pAd, mpdu_blk);
1601 ASSERT((0<= pBAEntry->list.qlen) && (pBAEntry->list.qlen <= pBAEntry->BAWinSize));
1602 NdisReleaseSpinLock(&pBAEntry->RxReRingLock);
1606 DBGPRINT(RT_DEBUG_ERROR, ("!!! (%d) Can't allocate reordering mpdu blk\n",
1607 pBAEntry->list.qlen));
1609 * flush all pending reordering mpdus
1610 * and receving mpdu to upper layer
1611 * make tcp/ip to take care reordering mechanism
1613 //ba_refresh_reordering_mpdus(pAd, pBAEntry);
1614 ba_indicate_reordering_mpdus_le_seq(pAd, pBAEntry, Sequence);
1616 pBAEntry->LastIndSeq = Sequence;
1617 INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID);
1623 ==========================================================================
1625 Indicate this packet to upper layer or put it into reordering buffer
1628 pRxBlk : carry necessary packet info 802.11 format
1629 FromWhichBSSID : the packet received from which BSS
1635 the packet queued into reordering buffer need to cover to 802.3 format
1637 ==========================================================================
1640 VOID Indicate_AMPDU_Packet(
1641 IN PRTMP_ADAPTER pAd,
1643 IN UCHAR FromWhichBSSID)
1646 PBA_REC_ENTRY pBAEntry = NULL;
1647 UINT16 Sequence = pRxBlk->pHeader->Sequence;
1649 UCHAR Wcid = pRxBlk->pRxWI->WirelessCliID;
1650 UCHAR TID = pRxBlk->pRxWI->TID;
1653 if (!RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU) && (pRxBlk->DataSize > MAX_RX_PKT_LEN))
1656 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
1662 if (Wcid < MAX_LEN_OF_MAC_TABLE)
1664 Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID];
1667 /* Rec BA Session had been torn down */
1668 INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID);
1671 pBAEntry = &pAd->BATable.BARecEntry[Idx];
1678 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
1684 // update last rx time
1685 NdisGetSystemUpTime(&Now32);
1687 pBAEntry->rcvSeq = Sequence;
1690 ba_flush_reordering_timeout_mpdus(pAd, pBAEntry, Now32);
1691 pBAEntry->LastIndSeqAtTimer = Now32;
1694 // Reset Last Indicate Sequence
1696 if (pBAEntry->LastIndSeq == RESET_RCV_SEQ)
1698 ASSERT((pBAEntry->list.qlen == 0) && (pBAEntry->list.next == NULL));
1700 // reset rcv sequence of BA session
1701 pBAEntry->LastIndSeq = Sequence;
1702 pBAEntry->LastIndSeqAtTimer = Now32;
1703 INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID);
1708 // I. Check if in order.
1710 if (SEQ_STEPONE(Sequence, pBAEntry->LastIndSeq, MAXSEQ))
1714 pBAEntry->LastIndSeq = Sequence;
1715 INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID);
1716 LastIndSeq = ba_indicate_reordering_mpdus_in_order(pAd, pBAEntry, pBAEntry->LastIndSeq);
1717 if (LastIndSeq != RESET_RCV_SEQ)
1719 pBAEntry->LastIndSeq = LastIndSeq;
1721 pBAEntry->LastIndSeqAtTimer = Now32;
1724 // II. Drop Duplicated Packet
1726 else if (Sequence == pBAEntry->LastIndSeq)
1729 // drop and release packet
1730 pBAEntry->nDropPacket++;
1731 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
1734 // III. Drop Old Received Packet
1736 else if (SEQ_SMALLER(Sequence, pBAEntry->LastIndSeq, MAXSEQ))
1739 // drop and release packet
1740 pBAEntry->nDropPacket++;
1741 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
1744 // IV. Receive Sequence within Window Size
1746 else if (SEQ_SMALLER(Sequence, (((pBAEntry->LastIndSeq+pBAEntry->BAWinSize+1)) & MAXSEQ), MAXSEQ))
1748 ba_enqueue_reordering_packet(pAd, pBAEntry, pRxBlk, FromWhichBSSID);
1751 // V. Receive seq surpasses Win(lastseq + nMSDU). So refresh all reorder buffer
1755 LONG WinStartSeq, TmpSeq;
1758 TmpSeq = Sequence - (pBAEntry->BAWinSize) -1;
1761 TmpSeq = (MAXSEQ+1) + TmpSeq;
1763 WinStartSeq = (TmpSeq+1) & MAXSEQ;
1764 ba_indicate_reordering_mpdus_le_seq(pAd, pBAEntry, WinStartSeq);
1765 pBAEntry->LastIndSeq = WinStartSeq; //TmpSeq;
1767 pBAEntry->LastIndSeqAtTimer = Now32;
1769 ba_enqueue_reordering_packet(pAd, pBAEntry, pRxBlk, FromWhichBSSID);
1771 TmpSeq = ba_indicate_reordering_mpdus_in_order(pAd, pBAEntry, pBAEntry->LastIndSeq);
1772 if (TmpSeq != RESET_RCV_SEQ)
1774 pBAEntry->LastIndSeq = TmpSeq;
1779 #endif // DOT11_N_SUPPORT //