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 *************************************************************************
28 #ifdef DOT11_N_SUPPORT
30 #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 * HZ)/1000) // system ticks -- 100 ms
41 #define MAX_REORDERING_PACKET_TIMEOUT ((3000 * 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 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
136 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pPacket, RTMP_GET_PACKET_IF(pPacket));
141 * Insert a reordering mpdu into sorted linked list by sequence no.
143 BOOLEAN ba_reordering_mpdu_insertsorted(struct reordering_list *list, struct reordering_mpdu *mpdu)
146 struct reordering_mpdu **ppScan = &list->next;
148 while (*ppScan != NULL)
150 if (SEQ_SMALLER((*ppScan)->Sequence, mpdu->Sequence, MAXSEQ))
152 ppScan = &(*ppScan)->next;
154 else if ((*ppScan)->Sequence == mpdu->Sequence)
156 /* give up this duplicated frame */
166 mpdu->next = *ppScan;
174 * caller lock critical section if necessary
176 static inline void ba_enqueue(struct reordering_list *list, struct reordering_mpdu *mpdu_blk)
179 mpdu_blk->next = list->next;
180 list->next = mpdu_blk;
184 * caller lock critical section if necessary
186 static inline struct reordering_mpdu * ba_dequeue(struct reordering_list *list)
188 struct reordering_mpdu *mpdu_blk = NULL;
195 mpdu_blk = list->next;
198 list->next = mpdu_blk->next;
199 mpdu_blk->next = NULL;
206 static inline struct reordering_mpdu *ba_reordering_mpdu_dequeue(struct reordering_list *list)
208 return(ba_dequeue(list));
212 static inline struct reordering_mpdu *ba_reordering_mpdu_probe(struct reordering_list *list)
221 * free all resource for reordering mechanism
223 void ba_reordering_resource_release(PRTMP_ADAPTER pAd)
226 PBA_REC_ENTRY pBAEntry;
227 struct reordering_mpdu *mpdu_blk;
232 /* I. release all pending reordering packet */
233 NdisAcquireSpinLock(&pAd->BATabLock);
234 for (i = 0; i < MAX_LEN_OF_BA_REC_TABLE; i++)
236 pBAEntry = &Tab->BARecEntry[i];
237 if (pBAEntry->REC_BA_Status != Recipient_NONE)
239 while ((mpdu_blk = ba_reordering_mpdu_dequeue(&pBAEntry->list)))
241 ASSERT(mpdu_blk->pPacket);
242 RELEASE_NDIS_PACKET(pAd, mpdu_blk->pPacket, NDIS_STATUS_FAILURE);
243 ba_mpdu_blk_free(pAd, mpdu_blk);
247 NdisReleaseSpinLock(&pAd->BATabLock);
249 ASSERT(pBAEntry->list.qlen == 0);
250 /* II. free memory of reordering mpdu table */
251 NdisAcquireSpinLock(&pAd->mpdu_blk_pool.lock);
252 os_free_mem(pAd, pAd->mpdu_blk_pool.mem);
253 NdisReleaseSpinLock(&pAd->mpdu_blk_pool.lock);
259 * Allocate all resource for reordering mechanism
261 BOOLEAN ba_reordering_resource_init(PRTMP_ADAPTER pAd, int num)
265 struct reordering_mpdu *mpdu_blk;
266 struct reordering_list *freelist;
268 /* allocate spinlock */
269 NdisAllocateSpinLock(&pAd->mpdu_blk_pool.lock);
271 /* initialize freelist */
272 freelist = &pAd->mpdu_blk_pool.freelist;
273 freelist->next = NULL;
276 DBGPRINT(RT_DEBUG_TRACE, ("Allocate %d memory for BA reordering\n", (UINT32)(num*sizeof(struct reordering_mpdu))));
278 /* allocate number of mpdu_blk memory */
279 os_alloc_mem(pAd, (PUCHAR *)&mem, (num*sizeof(struct reordering_mpdu)));
281 pAd->mpdu_blk_pool.mem = mem;
285 DBGPRINT(RT_DEBUG_ERROR, ("Can't Allocate Memory for BA Reordering\n"));
289 /* build mpdu_blk free list */
290 for (i=0; i<num; i++)
293 mpdu_blk = (struct reordering_mpdu *) mem;
294 /* initial mpdu_blk */
295 NdisZeroMemory(mpdu_blk, sizeof(struct reordering_mpdu));
297 mem += sizeof(struct reordering_mpdu);
298 /* insert mpdu_blk into freelist */
299 ba_enqueue(freelist, mpdu_blk);
305 //static int blk_count=0; // sample take off, no use
307 static struct reordering_mpdu *ba_mpdu_blk_alloc(PRTMP_ADAPTER pAd)
309 struct reordering_mpdu *mpdu_blk;
311 NdisAcquireSpinLock(&pAd->mpdu_blk_pool.lock);
312 mpdu_blk = ba_dequeue(&pAd->mpdu_blk_pool.freelist);
317 NdisZeroMemory(mpdu_blk, sizeof(struct reordering_mpdu));
319 NdisReleaseSpinLock(&pAd->mpdu_blk_pool.lock);
323 static void ba_mpdu_blk_free(PRTMP_ADAPTER pAd, struct reordering_mpdu *mpdu_blk)
327 NdisAcquireSpinLock(&pAd->mpdu_blk_pool.lock);
329 ba_enqueue(&pAd->mpdu_blk_pool.freelist, mpdu_blk);
330 NdisReleaseSpinLock(&pAd->mpdu_blk_pool.lock);
334 static USHORT ba_indicate_reordering_mpdus_in_order(
335 IN PRTMP_ADAPTER pAd,
336 IN PBA_REC_ENTRY pBAEntry,
339 struct reordering_mpdu *mpdu_blk;
340 USHORT LastIndSeq = RESET_RCV_SEQ;
342 NdisAcquireSpinLock(&pBAEntry->RxReRingLock);
344 while ((mpdu_blk = ba_reordering_mpdu_probe(&pBAEntry->list)))
346 /* find in-order frame */
347 if (!SEQ_STEPONE(mpdu_blk->Sequence, StartSeq, MAXSEQ))
351 /* dequeue in-order frame from reodering list */
352 mpdu_blk = ba_reordering_mpdu_dequeue(&pBAEntry->list);
353 /* pass this frame up */
354 ANNOUNCE_REORDERING_PACKET(pAd, mpdu_blk);
355 /* move to next sequence */
356 StartSeq = mpdu_blk->Sequence;
357 LastIndSeq = StartSeq;
359 ba_mpdu_blk_free(pAd, mpdu_blk);
362 NdisReleaseSpinLock(&pBAEntry->RxReRingLock);
364 /* update last indicated sequence */
368 static void ba_indicate_reordering_mpdus_le_seq(
369 IN PRTMP_ADAPTER pAd,
370 IN PBA_REC_ENTRY pBAEntry,
373 struct reordering_mpdu *mpdu_blk;
375 NdisAcquireSpinLock(&pBAEntry->RxReRingLock);
376 while ((mpdu_blk = ba_reordering_mpdu_probe(&pBAEntry->list)))
378 /* find in-order frame */
379 if ((mpdu_blk->Sequence == Sequence) || SEQ_SMALLER(mpdu_blk->Sequence, Sequence, MAXSEQ))
381 /* dequeue in-order frame from reodering list */
382 mpdu_blk = ba_reordering_mpdu_dequeue(&pBAEntry->list);
383 /* pass this frame up */
384 ANNOUNCE_REORDERING_PACKET(pAd, mpdu_blk);
386 ba_mpdu_blk_free(pAd, mpdu_blk);
393 NdisReleaseSpinLock(&pBAEntry->RxReRingLock);
397 static void ba_refresh_reordering_mpdus(
398 IN PRTMP_ADAPTER pAd,
399 PBA_REC_ENTRY pBAEntry)
401 struct reordering_mpdu *mpdu_blk;
403 NdisAcquireSpinLock(&pBAEntry->RxReRingLock);
405 /* dequeue in-order frame from reodering list */
406 while ((mpdu_blk = ba_reordering_mpdu_dequeue(&pBAEntry->list)))
408 /* pass this frame up */
409 ANNOUNCE_REORDERING_PACKET(pAd, mpdu_blk);
411 pBAEntry->LastIndSeq = mpdu_blk->Sequence;
412 ba_mpdu_blk_free(pAd, mpdu_blk);
414 /* update last indicated sequence */
416 ASSERT(pBAEntry->list.qlen == 0);
417 pBAEntry->LastIndSeq = RESET_RCV_SEQ;
418 NdisReleaseSpinLock(&pBAEntry->RxReRingLock);
423 void ba_flush_reordering_timeout_mpdus(
424 IN PRTMP_ADAPTER pAd,
425 IN PBA_REC_ENTRY pBAEntry,
431 // if ((RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+REORDERING_PACKET_TIMEOUT)) &&
432 // (pBAEntry->list.qlen > ((pBAEntry->BAWinSize*7)/8))) //||
433 // (RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+(10*REORDERING_PACKET_TIMEOUT))) &&
434 // (pBAEntry->list.qlen > (pBAEntry->BAWinSize/8)))
435 if (RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+(MAX_REORDERING_PACKET_TIMEOUT/6)))
436 &&(pBAEntry->list.qlen > 1)
439 DBGPRINT(RT_DEBUG_TRACE,("timeout[%d] (%08lx-%08lx = %d > %d): %x, flush all!\n ", pBAEntry->list.qlen, Now32, (pBAEntry->LastIndSeqAtTimer),
440 (int)((long) Now32 - (long)(pBAEntry->LastIndSeqAtTimer)), MAX_REORDERING_PACKET_TIMEOUT,
441 pBAEntry->LastIndSeq));
442 ba_refresh_reordering_mpdus(pAd, pBAEntry);
443 pBAEntry->LastIndSeqAtTimer = Now32;
446 if (RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+(REORDERING_PACKET_TIMEOUT)))
447 && (pBAEntry->list.qlen > 0)
450 // printk("timeout[%d] (%lx-%lx = %d > %d): %x, ", pBAEntry->list.qlen, Now32, (pBAEntry->LastIndSeqAtTimer),
451 // (int)((long) Now32 - (long)(pBAEntry->LastIndSeqAtTimer)), REORDERING_PACKET_TIMEOUT,
452 // pBAEntry->LastIndSeq);
454 // force LastIndSeq to shift to LastIndSeq+1
456 Sequence = (pBAEntry->LastIndSeq+1) & MAXSEQ;
457 ba_indicate_reordering_mpdus_le_seq(pAd, pBAEntry, Sequence);
458 pBAEntry->LastIndSeqAtTimer = Now32;
459 pBAEntry->LastIndSeq = Sequence;
461 // indicate in-order mpdus
463 Sequence = ba_indicate_reordering_mpdus_in_order(pAd, pBAEntry, Sequence);
464 if (Sequence != RESET_RCV_SEQ)
466 pBAEntry->LastIndSeq = Sequence;
469 //printk("%x, flush one!\n", pBAEntry->LastIndSeq);
474 (RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+(MAX_REORDERING_PACKET_TIMEOUT))) &&
475 (pBAEntry->list.qlen > 1))
478 DBGPRINT(RT_DEBUG_TRACE,("timeout[%d] (%lx-%lx = %d > %d): %x\n ", pBAEntry->list.qlen, Now32, (pBAEntry->LastIndSeqAtTimer),
479 (int)((long) Now32 - (long)(pBAEntry->LastIndSeqAtTimer)), MAX_REORDERING_PACKET_TIMEOUT,
480 pBAEntry->LastIndSeq));
481 ba_refresh_reordering_mpdus(pAd, pBAEntry);
482 pBAEntry->LastIndSeqAtTimer = Now32;
489 * generate ADDBA request to
490 * set up BA agreement
492 VOID BAOriSessionSetUp(
493 IN PRTMP_ADAPTER pAd,
494 IN MAC_TABLE_ENTRY *pEntry,
501 //MLME_ADDBA_REQ_STRUCT AddbaReq;
502 BA_ORI_ENTRY *pBAEntry = NULL;
506 if ((pAd->CommonCfg.BACapability.field.AutoBA != TRUE) && (isForced == FALSE))
509 // if this entry is limited to use legacy tx mode, it doesn't generate BA.
510 if (RTMPStaFixedTxMode(pAd, pEntry) != FIXED_TXMODE_HT)
513 if ((pEntry->BADeclineBitmap & (1<<TID)) && (isForced == FALSE))
515 // try again after 3 secs
517 // printk("DeCline BA from Peer\n");
522 Idx = pEntry->BAOriWcidArray[TID];
525 // allocate a BA session
526 pBAEntry = BATableAllocOriEntry(pAd, &Idx);
527 if (pBAEntry == NULL)
529 DBGPRINT(RT_DEBUG_TRACE,("ADDBA - MlmeADDBAAction() allocate BA session failed \n"));
535 pBAEntry =&pAd->BATable.BAOriEntry[Idx];
538 if (pBAEntry->ORI_BA_Status >= Originator_WaitRes)
543 pEntry->BAOriWcidArray[TID] = Idx;
545 // Initialize BA session
546 pBAEntry->ORI_BA_Status = Originator_WaitRes;
547 pBAEntry->Wcid = pEntry->Aid;
548 pBAEntry->BAWinSize = pAd->CommonCfg.BACapability.field.RxBAWinLimit;
549 pBAEntry->Sequence = BA_ORI_INIT_SEQ;
550 pBAEntry->Token = 1; // (2008-01-21) Jan Lee recommends it - this token can't be 0
552 pBAEntry->TimeOutValue = TimeOut;
553 pBAEntry->pAdapter = pAd;
555 if (!(pEntry->TXBAbitmap & (1<<TID)))
557 RTMPInitTimer(pAd, &pBAEntry->ORIBATimer, GET_TIMER_FUNCTION(BAOriSessionSetupTimeout), pBAEntry, FALSE);
560 RTMPCancelTimer(&pBAEntry->ORIBATimer, &Cancelled);
562 // set timer to send ADDBA request
563 RTMPSetTimer(&pBAEntry->ORIBATimer, DelayTime);
566 VOID BAOriSessionAdd(
567 IN PRTMP_ADAPTER pAd,
568 IN MAC_TABLE_ENTRY *pEntry,
569 IN PFRAME_ADDBA_RSP pFrame)
571 BA_ORI_ENTRY *pBAEntry = NULL;
575 PUCHAR pOutBuffer2 = NULL;
580 TID = pFrame->BaParm.TID;
581 Idx = pEntry->BAOriWcidArray[TID];
582 pBAEntry =&pAd->BATable.BAOriEntry[Idx];
584 // Start fill in parameters.
585 if ((Idx !=0) && (pBAEntry->TID == TID) && (pBAEntry->ORI_BA_Status == Originator_WaitRes))
587 pBAEntry->BAWinSize = min(pBAEntry->BAWinSize, ((UCHAR)pFrame->BaParm.BufSize));
588 BA_MaxWinSizeReasign(pAd, pEntry, &pBAEntry->BAWinSize);
590 pBAEntry->TimeOutValue = pFrame->TimeOutValue;
591 pBAEntry->ORI_BA_Status = Originator_Done;
592 // reset sequence number
593 pBAEntry->Sequence = BA_ORI_INIT_SEQ;
595 pEntry->TXBAbitmap |= (1<<TID);
596 RTMPCancelTimer(&pBAEntry->ORIBATimer, &Cancelled);
598 pBAEntry->ORIBATimer.TimerValue = 0; //pFrame->TimeOutValue;
600 DBGPRINT(RT_DEBUG_TRACE,("%s : TXBAbitmap = %x, BAWinSize = %d, TimeOut = %ld\n", __func__, pEntry->TXBAbitmap,
601 pBAEntry->BAWinSize, pBAEntry->ORIBATimer.TimerValue));
604 NStatus = MlmeAllocateMemory(pAd, &pOutBuffer2); //Get an unused nonpaged memory
605 if (NStatus != NDIS_STATUS_SUCCESS)
607 DBGPRINT(RT_DEBUG_TRACE,("BA - BAOriSessionAdd() allocate memory failed \n"));
611 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
612 BarHeaderInit(pAd, &FrameBar, pAd->MacTab.Content[pBAEntry->Wcid].Addr, pAd->CurrentAddress);
614 FrameBar.StartingSeq.field.FragNum = 0; // make sure sequence not clear in DEL function.
615 FrameBar.StartingSeq.field.StartSeq = pBAEntry->Sequence; // make sure sequence not clear in DEL funciton.
616 FrameBar.BarControl.TID = pBAEntry->TID; // make sure sequence not clear in DEL funciton.
617 MakeOutgoingFrame(pOutBuffer2, &FrameLen,
618 sizeof(FRAME_BAR), &FrameBar,
620 MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer2, FrameLen);
621 MlmeFreeMemory(pAd, pOutBuffer2);
624 if (pBAEntry->ORIBATimer.TimerValue)
625 RTMPSetTimer(&pBAEntry->ORIBATimer, pBAEntry->ORIBATimer.TimerValue); // in mSec
629 BOOLEAN BARecSessionAdd(
630 IN PRTMP_ADAPTER pAd,
631 IN MAC_TABLE_ENTRY *pEntry,
632 IN PFRAME_ADDBA_REQ pFrame)
634 BA_REC_ENTRY *pBAEntry = NULL;
635 BOOLEAN Status = TRUE;
647 TID = pFrame->BaParm.TID;
649 BAWinSize = min(((UCHAR)pFrame->BaParm.BufSize), (UCHAR)pAd->CommonCfg.BACapability.field.RxBAWinLimit);
657 Idx = pEntry->BARecWcidArray[TID];
662 pBAEntry = BATableAllocRecEntry(pAd, &Idx);
666 pBAEntry = &pAd->BATable.BARecEntry[Idx];
667 // flush all pending reordering mpdus
668 ba_refresh_reordering_mpdus(pAd, pBAEntry);
671 DBGPRINT(RT_DEBUG_TRACE,("%s(%ld): Idx = %d, BAWinSize(req %d) = %d\n", __func__, pAd->BATable.numAsRecipient, Idx,
672 pFrame->BaParm.BufSize, BAWinSize));
674 // Start fill in parameters.
675 if (pBAEntry != NULL)
677 ASSERT(pBAEntry->list.qlen == 0);
679 pBAEntry->REC_BA_Status = Recipient_HandleRes;
680 pBAEntry->BAWinSize = BAWinSize;
681 pBAEntry->Wcid = pEntry->Aid;
683 pBAEntry->TimeOutValue = pFrame->TimeOutValue;
684 pBAEntry->REC_BA_Status = Recipient_Accept;
685 // initial sequence number
686 pBAEntry->LastIndSeq = RESET_RCV_SEQ; //pFrame->BaStartSeq.field.StartSeq;
688 printk("Start Seq = %08x\n", pFrame->BaStartSeq.field.StartSeq);
690 if (pEntry->RXBAbitmap & (1<<TID))
692 RTMPCancelTimer(&pBAEntry->RECBATimer, &Cancelled);
696 RTMPInitTimer(pAd, &pBAEntry->RECBATimer, GET_TIMER_FUNCTION(BARecSessionIdleTimeout), pBAEntry, TRUE);
699 #if 0 // for debugging
700 RTMPSetTimer(&pBAEntry->RECBATimer, REC_BA_SESSION_IDLE_TIMEOUT);
704 pEntry->RXBAbitmap |= (1<<TID);
705 pEntry->BARecWcidArray[TID] = Idx;
707 pEntry->BADeclineBitmap &= ~(1<<TID);
709 // Set BA session mask in WCID table.
710 RT28XX_ADD_BA_SESSION_TO_ASIC(pAd, pEntry->Aid, TID);
712 DBGPRINT(RT_DEBUG_TRACE,("MACEntry[%d]RXBAbitmap = 0x%x. BARecWcidArray=%d\n",
713 pEntry->Aid, pEntry->RXBAbitmap, pEntry->BARecWcidArray[TID]));
718 DBGPRINT(RT_DEBUG_TRACE,("Can't Accept ADDBA for %02x:%02x:%02x:%02x:%02x:%02x TID = %d\n",
719 PRINT_MAC(pEntry->Addr), TID));
725 BA_REC_ENTRY *BATableAllocRecEntry(
726 IN PRTMP_ADAPTER pAd,
730 BA_REC_ENTRY *pBAEntry = NULL;
733 NdisAcquireSpinLock(&pAd->BATabLock);
735 if (pAd->BATable.numAsRecipient >= MAX_BARECI_SESSION)
737 printk("BA Recipeint Session (%ld) > %d\n", pAd->BATable.numAsRecipient,
742 // reserve idx 0 to identify BAWcidArray[TID] as empty
743 for (i=1; i < MAX_LEN_OF_BA_REC_TABLE; i++)
745 pBAEntry =&pAd->BATable.BARecEntry[i];
746 if ((pBAEntry->REC_BA_Status == Recipient_NONE))
749 pAd->BATable.numAsRecipient++;
750 pBAEntry->REC_BA_Status = Recipient_USED;
757 NdisReleaseSpinLock(&pAd->BATabLock);
761 BA_ORI_ENTRY *BATableAllocOriEntry(
762 IN PRTMP_ADAPTER pAd,
766 BA_ORI_ENTRY *pBAEntry = NULL;
768 NdisAcquireSpinLock(&pAd->BATabLock);
770 if (pAd->BATable.numAsOriginator >= (MAX_LEN_OF_BA_ORI_TABLE))
775 // reserve idx 0 to identify BAWcidArray[TID] as empty
776 for (i=1; i<MAX_LEN_OF_BA_ORI_TABLE; i++)
778 pBAEntry =&pAd->BATable.BAOriEntry[i];
779 if ((pBAEntry->ORI_BA_Status == Originator_NONE))
782 pAd->BATable.numAsOriginator++;
783 pBAEntry->ORI_BA_Status = Originator_USED;
784 pBAEntry->pAdapter = pAd;
791 NdisReleaseSpinLock(&pAd->BATabLock);
796 VOID BATableFreeOriEntry(
797 IN PRTMP_ADAPTER pAd,
800 BA_ORI_ENTRY *pBAEntry = NULL;
801 MAC_TABLE_ENTRY *pEntry;
804 if ((Idx == 0) || (Idx >= MAX_LEN_OF_BA_ORI_TABLE))
807 pBAEntry =&pAd->BATable.BAOriEntry[Idx];
809 if (pBAEntry->ORI_BA_Status != Originator_NONE)
811 pEntry = &pAd->MacTab.Content[pBAEntry->Wcid];
812 pEntry->BAOriWcidArray[pBAEntry->TID] = 0;
815 NdisAcquireSpinLock(&pAd->BATabLock);
816 if (pBAEntry->ORI_BA_Status == Originator_Done)
818 pEntry->TXBAbitmap &= (~(1<<(pBAEntry->TID) ));
819 DBGPRINT(RT_DEBUG_TRACE, ("BATableFreeOriEntry numAsOriginator= %ld\n", pAd->BATable.numAsRecipient));
820 // Erase Bitmap flag.
823 ASSERT(pAd->BATable.numAsOriginator != 0);
825 pAd->BATable.numAsOriginator -= 1;
827 pBAEntry->ORI_BA_Status = Originator_NONE;
829 NdisReleaseSpinLock(&pAd->BATabLock);
834 VOID BATableFreeRecEntry(
835 IN PRTMP_ADAPTER pAd,
838 BA_REC_ENTRY *pBAEntry = NULL;
839 MAC_TABLE_ENTRY *pEntry;
842 if ((Idx == 0) || (Idx >= MAX_LEN_OF_BA_REC_TABLE))
845 pBAEntry =&pAd->BATable.BARecEntry[Idx];
847 if (pBAEntry->REC_BA_Status != Recipient_NONE)
849 pEntry = &pAd->MacTab.Content[pBAEntry->Wcid];
850 pEntry->BARecWcidArray[pBAEntry->TID] = 0;
852 NdisAcquireSpinLock(&pAd->BATabLock);
854 ASSERT(pAd->BATable.numAsRecipient != 0);
856 pAd->BATable.numAsRecipient -= 1;
858 pBAEntry->REC_BA_Status = Recipient_NONE;
859 NdisReleaseSpinLock(&pAd->BATabLock);
864 VOID BAOriSessionTearDown(
865 IN OUT PRTMP_ADAPTER pAd,
869 IN BOOLEAN bForceSend)
872 BA_ORI_ENTRY *pBAEntry;
875 if (Wcid >= MAX_LEN_OF_MAC_TABLE)
881 // Locate corresponding BA Originator Entry in BA Table with the (pAddr,TID).
883 Idx = pAd->MacTab.Content[Wcid].BAOriWcidArray[TID];
884 if ((Idx == 0) || (Idx >= MAX_LEN_OF_BA_ORI_TABLE))
886 if (bForceSend == TRUE)
888 // force send specified TID DelBA
889 MLME_DELBA_REQ_STRUCT DelbaReq;
890 MLME_QUEUE_ELEM *Elem = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG);
892 NdisZeroMemory(&DelbaReq, sizeof(DelbaReq));
893 NdisZeroMemory(Elem, sizeof(MLME_QUEUE_ELEM));
895 COPY_MAC_ADDR(DelbaReq.Addr, pAd->MacTab.Content[Wcid].Addr);
896 DelbaReq.Wcid = Wcid;
898 DelbaReq.Initiator = ORIGINATOR;
900 Elem->MsgLen = sizeof(DelbaReq);
901 NdisMoveMemory(Elem->Msg, &DelbaReq, sizeof(DelbaReq));
902 MlmeDELBAAction(pAd, Elem);
905 MlmeEnqueue(pAd, ACTION_STATE_MACHINE, MT2_MLME_ORI_DELBA_CATE, sizeof(MLME_DELBA_REQ_STRUCT), (PVOID)&DelbaReq);
906 RT28XX_MLME_HANDLER(pAd);
913 DBGPRINT(RT_DEBUG_TRACE,("%s===>Wcid=%d.TID=%d \n", __func__, Wcid, TID));
915 pBAEntry = &pAd->BATable.BAOriEntry[Idx];
916 DBGPRINT(RT_DEBUG_TRACE,("\t===>Idx = %ld, Wcid=%d.TID=%d, ORI_BA_Status = %d \n", Idx, Wcid, TID, pBAEntry->ORI_BA_Status));
918 // Prepare DelBA action frame and send to the peer.
920 if ((bPassive == FALSE) && (TID == pBAEntry->TID) && (pBAEntry->ORI_BA_Status == Originator_Done))
922 MLME_DELBA_REQ_STRUCT DelbaReq;
923 MLME_QUEUE_ELEM *Elem = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG);
925 NdisZeroMemory(&DelbaReq, sizeof(DelbaReq));
926 NdisZeroMemory(Elem, sizeof(MLME_QUEUE_ELEM));
928 COPY_MAC_ADDR(DelbaReq.Addr, pAd->MacTab.Content[Wcid].Addr);
929 DelbaReq.Wcid = Wcid;
930 DelbaReq.TID = pBAEntry->TID;
931 DelbaReq.Initiator = ORIGINATOR;
933 Elem->MsgLen = sizeof(DelbaReq);
934 NdisMoveMemory(Elem->Msg, &DelbaReq, sizeof(DelbaReq));
935 MlmeDELBAAction(pAd, Elem);
938 MlmeEnqueue(pAd, ACTION_STATE_MACHINE, MT2_MLME_ORI_DELBA_CATE, sizeof(MLME_DELBA_REQ_STRUCT), (PVOID)&DelbaReq);
939 RT28XX_MLME_HANDLER(pAd);
942 RTMPCancelTimer(&pBAEntry->ORIBATimer, &Cancelled);
943 BATableFreeOriEntry(pAd, Idx);
947 //BAOriSessionSetUp(pAd, &pAd->MacTab.Content[Wcid], TID, 0, 10000, TRUE);
951 VOID BARecSessionTearDown(
952 IN OUT PRTMP_ADAPTER pAd,
958 BA_REC_ENTRY *pBAEntry;
960 if (Wcid >= MAX_LEN_OF_MAC_TABLE)
966 // Locate corresponding BA Originator Entry in BA Table with the (pAddr,TID).
968 Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID];
972 DBGPRINT(RT_DEBUG_TRACE,("%s===>Wcid=%d.TID=%d \n", __func__, Wcid, TID));
975 pBAEntry = &pAd->BATable.BARecEntry[Idx];
976 DBGPRINT(RT_DEBUG_TRACE,("\t===>Idx = %ld, Wcid=%d.TID=%d, REC_BA_Status = %d \n", Idx, Wcid, TID, pBAEntry->REC_BA_Status));
978 // Prepare DelBA action frame and send to the peer.
980 if ((TID == pBAEntry->TID) && (pBAEntry->REC_BA_Status == Recipient_Accept))
982 MLME_DELBA_REQ_STRUCT DelbaReq;
984 MLME_QUEUE_ELEM *Elem = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG);
988 RTMPCancelTimer(&pBAEntry->RECBATimer, &Cancelled);
991 // 1. Send DELBA Action Frame
993 if (bPassive == FALSE)
995 NdisZeroMemory(&DelbaReq, sizeof(DelbaReq));
996 NdisZeroMemory(Elem, sizeof(MLME_QUEUE_ELEM));
998 COPY_MAC_ADDR(DelbaReq.Addr, pAd->MacTab.Content[Wcid].Addr);
999 DelbaReq.Wcid = Wcid;
1001 DelbaReq.Initiator = RECIPIENT;
1003 Elem->MsgLen = sizeof(DelbaReq);
1004 NdisMoveMemory(Elem->Msg, &DelbaReq, sizeof(DelbaReq));
1005 MlmeDELBAAction(pAd, Elem);
1008 MlmeEnqueue(pAd, ACTION_STATE_MACHINE, MT2_MLME_ORI_DELBA_CATE, sizeof(MLME_DELBA_REQ_STRUCT), (PVOID)&DelbaReq);
1009 RT28XX_MLME_HANDLER(pAd);
1015 // 2. Free resource of BA session
1017 // flush all pending reordering mpdus
1018 ba_refresh_reordering_mpdus(pAd, pBAEntry);
1020 NdisAcquireSpinLock(&pAd->BATabLock);
1022 // Erase Bitmap flag.
1023 pBAEntry->LastIndSeq = RESET_RCV_SEQ;
1024 pBAEntry->BAWinSize = 0;
1025 // Erase Bitmap flag at software mactable
1026 pAd->MacTab.Content[Wcid].RXBAbitmap &= (~(1<<(pBAEntry->TID)));
1027 pAd->MacTab.Content[Wcid].BARecWcidArray[TID] = 0;
1029 RT28XX_DEL_BA_SESSION_FROM_ASIC(pAd, Wcid, TID);
1031 NdisReleaseSpinLock(&pAd->BATabLock);
1035 BATableFreeRecEntry(pAd, Idx);
1038 VOID BASessionTearDownALL(
1039 IN OUT PRTMP_ADAPTER pAd,
1044 for (i=0; i<NUM_OF_TID; i++)
1046 BAOriSessionTearDown(pAd, Wcid, i, FALSE, FALSE);
1047 BARecSessionTearDown(pAd, Wcid, i, FALSE);
1053 ==========================================================================
1055 Retry sending ADDBA Reqest.
1057 IRQL = DISPATCH_LEVEL
1060 p8023Header: if this is already 802.3 format, p8023Header is NULL
1062 Return : TRUE if put into rx reordering buffer, shouldn't indicaterxhere.
1063 FALSE , then continue indicaterx at this moment.
1064 ==========================================================================
1066 VOID BAOriSessionSetupTimeout(
1067 IN PVOID SystemSpecific1,
1068 IN PVOID FunctionContext,
1069 IN PVOID SystemSpecific2,
1070 IN PVOID SystemSpecific3)
1072 BA_ORI_ENTRY *pBAEntry = (BA_ORI_ENTRY *)FunctionContext;
1073 MAC_TABLE_ENTRY *pEntry;
1076 if (pBAEntry == NULL)
1079 pAd = pBAEntry->pAdapter;
1081 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1083 // Do nothing if monitor mode is on
1084 if (MONITOR_ON(pAd))
1088 pEntry = &pAd->MacTab.Content[pBAEntry->Wcid];
1090 if ((pBAEntry->ORI_BA_Status == Originator_WaitRes) && (pBAEntry->Token < ORI_SESSION_MAX_RETRY))
1092 MLME_ADDBA_REQ_STRUCT AddbaReq;
1094 NdisZeroMemory(&AddbaReq, sizeof(AddbaReq));
1095 COPY_MAC_ADDR(AddbaReq.pAddr, pEntry->Addr);
1096 AddbaReq.Wcid = (UCHAR)(pEntry->Aid);
1097 AddbaReq.TID = pBAEntry->TID;
1098 AddbaReq.BaBufSize = pAd->CommonCfg.BACapability.field.RxBAWinLimit;
1099 AddbaReq.TimeOutValue = 0;
1100 AddbaReq.Token = pBAEntry->Token;
1101 MlmeEnqueue(pAd, ACTION_STATE_MACHINE, MT2_MLME_ADD_BA_CATE, sizeof(MLME_ADDBA_REQ_STRUCT), (PVOID)&AddbaReq);
1102 RT28XX_MLME_HANDLER(pAd);
1103 DBGPRINT(RT_DEBUG_TRACE,("BA Ori Session Timeout(%d) : Send ADD BA again\n", pBAEntry->Token));
1106 RTMPSetTimer(&pBAEntry->ORIBATimer, ORI_BA_SESSION_TIMEOUT);
1110 BATableFreeOriEntry(pAd, pEntry->BAOriWcidArray[pBAEntry->TID]);
1115 ==========================================================================
1117 Retry sending ADDBA Reqest.
1119 IRQL = DISPATCH_LEVEL
1122 p8023Header: if this is already 802.3 format, p8023Header is NULL
1124 Return : TRUE if put into rx reordering buffer, shouldn't indicaterxhere.
1125 FALSE , then continue indicaterx at this moment.
1126 ==========================================================================
1128 VOID BARecSessionIdleTimeout(
1129 IN PVOID SystemSpecific1,
1130 IN PVOID FunctionContext,
1131 IN PVOID SystemSpecific2,
1132 IN PVOID SystemSpecific3)
1135 BA_REC_ENTRY *pBAEntry = (BA_REC_ENTRY *)FunctionContext;
1139 if (pBAEntry == NULL)
1142 if ((pBAEntry->REC_BA_Status == Recipient_Accept))
1144 NdisGetSystemUpTime(&Now32);
1146 if (RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer + REC_BA_SESSION_IDLE_TIMEOUT)))
1148 pAd = pBAEntry->pAdapter;
1149 // flush all pending reordering mpdus
1150 ba_refresh_reordering_mpdus(pAd, pBAEntry);
1151 printk("%ld: REC BA session Timeout\n", Now32);
1157 VOID PeerAddBAReqAction(
1158 IN PRTMP_ADAPTER pAd,
1159 IN MLME_QUEUE_ELEM *Elem)
1166 FRAME_ADDBA_RSP ADDframe;
1167 PUCHAR pOutBuffer = NULL;
1168 NDIS_STATUS NStatus;
1169 PFRAME_ADDBA_REQ pAddreqFrame = NULL;
1173 PMAC_TABLE_ENTRY pMacEntry;
1175 DBGPRINT(RT_DEBUG_TRACE, ("%s ==> (Wcid = %d)\n", __func__, Elem->Wcid));
1177 //hex_dump("AddBAReq", Elem->Msg, Elem->MsgLen);
1179 //ADDBA Request from unknown peer, ignore this.
1180 if (Elem->Wcid >= MAX_LEN_OF_MAC_TABLE)
1183 pMacEntry = &pAd->MacTab.Content[Elem->Wcid];
1184 DBGPRINT(RT_DEBUG_TRACE,("BA - PeerAddBAReqAction----> \n"));
1185 ptemp = (PULONG)Elem->Msg;
1186 //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)));
1188 if (PeerAddBAReqActionSanity(pAd, Elem->Msg, Elem->MsgLen, pAddr))
1191 if ((pAd->CommonCfg.bBADecline == FALSE) && IS_HT_STA(pMacEntry))
1193 pAddreqFrame = (PFRAME_ADDBA_REQ)(&Elem->Msg[0]);
1194 printk("Rcv Wcid(%d) AddBAReq\n", Elem->Wcid);
1195 if (BARecSessionAdd(pAd, &pAd->MacTab.Content[Elem->Wcid], pAddreqFrame))
1198 Status = 38; // more parameters have invalid values
1202 Status = 37; // the request has been declined.
1206 if (pAd->MacTab.Content[Elem->Wcid].ValidAsCLI)
1207 ASSERT(pAd->MacTab.Content[Elem->Wcid].Sst == SST_ASSOC);
1209 pAddreqFrame = (PFRAME_ADDBA_REQ)(&Elem->Msg[0]);
1210 // 2. Always send back ADDBA Response
1211 NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory
1212 if (NStatus != NDIS_STATUS_SUCCESS)
1214 DBGPRINT(RT_DEBUG_TRACE,("ACTION - PeerBAAction() allocate memory failed \n"));
1218 NdisZeroMemory(&ADDframe, sizeof(FRAME_ADDBA_RSP));
1220 // 2-1. Prepare ADDBA Response frame.
1221 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1224 ActHeaderInit(pAd, &ADDframe.Hdr, pAddr, pAd->CurrentAddress, pAd->CommonCfg.Bssid);
1226 ActHeaderInit(pAd, &ADDframe.Hdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pAddr);
1229 ADDframe.Category = CATEGORY_BA;
1230 ADDframe.Action = ADDBA_RESP;
1231 ADDframe.Token = pAddreqFrame->Token;
1232 // What is the Status code?? need to check.
1233 ADDframe.StatusCode = Status;
1234 ADDframe.BaParm.BAPolicy = IMMED_BA;
1235 ADDframe.BaParm.AMSDUSupported = 0;
1236 ADDframe.BaParm.TID = pAddreqFrame->BaParm.TID;
1237 ADDframe.BaParm.BufSize = min(((UCHAR)pAddreqFrame->BaParm.BufSize), (UCHAR)pAd->CommonCfg.BACapability.field.RxBAWinLimit);
1238 if (ADDframe.BaParm.BufSize == 0)
1240 ADDframe.BaParm.BufSize = 64;
1242 ADDframe.TimeOutValue = 0; //pAddreqFrame->TimeOutValue;
1244 *(USHORT *)(&ADDframe.BaParm) = cpu2le16(*(USHORT *)(&ADDframe.BaParm));
1245 ADDframe.StatusCode = cpu2le16(ADDframe.StatusCode);
1246 ADDframe.TimeOutValue = cpu2le16(ADDframe.TimeOutValue);
1248 MakeOutgoingFrame(pOutBuffer, &FrameLen,
1249 sizeof(FRAME_ADDBA_RSP), &ADDframe,
1251 MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
1252 MlmeFreeMemory(pAd, pOutBuffer);
1254 DBGPRINT(RT_DEBUG_TRACE, ("%s(%d): TID(%d), BufSize(%d) <== \n", __func__, Elem->Wcid, ADDframe.BaParm.TID,
1255 ADDframe.BaParm.BufSize));
1259 VOID PeerAddBARspAction(
1260 IN PRTMP_ADAPTER pAd,
1261 IN MLME_QUEUE_ELEM *Elem)
1265 //PUCHAR pOutBuffer = NULL;
1266 PFRAME_ADDBA_RSP pFrame = NULL;
1267 //PBA_ORI_ENTRY pBAEntry;
1269 //ADDBA Response from unknown peer, ignore this.
1270 if (Elem->Wcid >= MAX_LEN_OF_MAC_TABLE)
1273 DBGPRINT(RT_DEBUG_TRACE, ("%s ==> Wcid(%d)\n", __func__, Elem->Wcid));
1275 //hex_dump("PeerAddBARspAction()", Elem->Msg, Elem->MsgLen);
1277 if (PeerAddBARspActionSanity(pAd, Elem->Msg, Elem->MsgLen))
1279 pFrame = (PFRAME_ADDBA_RSP)(&Elem->Msg[0]);
1281 DBGPRINT(RT_DEBUG_TRACE, ("\t\t StatusCode = %d\n", pFrame->StatusCode));
1282 switch (pFrame->StatusCode)
1285 // I want a BAsession with this peer as an originator.
1286 BAOriSessionAdd(pAd, &pAd->MacTab.Content[Elem->Wcid], pFrame);
1289 // check status == USED ???
1290 BAOriSessionTearDown(pAd, Elem->Wcid, pFrame->BaParm.TID, TRUE, FALSE);
1293 // Rcv Decline StatusCode
1294 if ((pFrame->StatusCode == 37)
1295 || ((pAd->OpMode == OPMODE_STA) && STA_TGN_WIFI_ON(pAd) && (pFrame->StatusCode != 0))
1298 pAd->MacTab.Content[Elem->Wcid].BADeclineBitmap |= 1<<pFrame->BaParm.TID;
1303 VOID PeerDelBAAction(
1304 IN PRTMP_ADAPTER pAd,
1305 IN MLME_QUEUE_ELEM *Elem)
1309 //PUCHAR pOutBuffer = NULL;
1310 PFRAME_DELBA_REQ pDelFrame = NULL;
1312 DBGPRINT(RT_DEBUG_TRACE,("%s ==>\n", __func__));
1313 //DELBA Request from unknown peer, ignore this.
1314 if (PeerDelBAActionSanity(pAd, Elem->Wcid, Elem->Msg, Elem->MsgLen))
1316 pDelFrame = (PFRAME_DELBA_REQ)(&Elem->Msg[0]);
1317 if (pDelFrame->DelbaParm.Initiator == ORIGINATOR)
1319 DBGPRINT(RT_DEBUG_TRACE,("BA - PeerDelBAAction----> ORIGINATOR\n"));
1320 BARecSessionTearDown(pAd, Elem->Wcid, pDelFrame->DelbaParm.TID, TRUE);
1324 DBGPRINT(RT_DEBUG_TRACE,("BA - PeerDelBAAction----> RECIPIENT, Reason = %d\n", pDelFrame->ReasonCode));
1325 //hex_dump("DelBA Frame", pDelFrame, Elem->MsgLen);
1326 BAOriSessionTearDown(pAd, Elem->Wcid, pDelFrame->DelbaParm.TID, TRUE, FALSE);
1332 BOOLEAN CntlEnqueueForRecv(
1333 IN PRTMP_ADAPTER pAd,
1336 IN PFRAME_BA_REQ pMsg)
1338 PFRAME_BA_REQ pFrame = pMsg;
1339 //PRTMP_REORDERBUF pBuffer;
1340 //PRTMP_REORDERBUF pDmaBuf;
1341 PBA_REC_ENTRY pBAEntry;
1347 TID = (UCHAR)pFrame->BARControl.TID;
1349 DBGPRINT(RT_DEBUG_TRACE, ("%s(): BAR-Wcid(%ld), Tid (%d)\n", __func__, Wcid, TID));
1350 //hex_dump("BAR", (PCHAR) pFrame, MsgLen);
1351 // Do nothing if the driver is starting halt state.
1352 // This might happen when timer already been fired before cancel timer with mlmehalt
1353 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
1356 // First check the size, it MUST not exceed the mlme queue size
1357 if (MsgLen > MGMT_DMA_BUFFER_SIZE)
1359 DBGPRINT_ERR(("CntlEnqueueForRecv: frame too large, size = %ld \n", MsgLen));
1362 else if (MsgLen != sizeof(FRAME_BA_REQ))
1364 DBGPRINT_ERR(("CntlEnqueueForRecv: BlockAck Request frame length size = %ld incorrect\n", MsgLen));
1367 else if (MsgLen != sizeof(FRAME_BA_REQ))
1369 DBGPRINT_ERR(("CntlEnqueueForRecv: BlockAck Request frame length size = %ld incorrect\n", MsgLen));
1373 if ((Wcid < MAX_LEN_OF_MAC_TABLE) && (TID < 8))
1375 // if this receiving packet is from SA that is in our OriEntry. Since WCID <9 has direct mapping. no need search.
1376 Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID];
1377 pBAEntry = &pAd->BATable.BARecEntry[Idx];
1384 DBGPRINT(RT_DEBUG_TRACE, ("BAR(%ld) : Tid (%d) - %04x:%04x\n", Wcid, TID, pFrame->BAStartingSeq.field.StartSeq, pBAEntry->LastIndSeq ));
1386 if (SEQ_SMALLER(pBAEntry->LastIndSeq, pFrame->BAStartingSeq.field.StartSeq, MAXSEQ))
1388 //printk("BAR Seq = %x, LastIndSeq = %x\n", pFrame->BAStartingSeq.field.StartSeq, pBAEntry->LastIndSeq);
1389 ba_indicate_reordering_mpdus_le_seq(pAd, pBAEntry, pFrame->BAStartingSeq.field.StartSeq);
1390 pBAEntry->LastIndSeq = (pFrame->BAStartingSeq.field.StartSeq == 0) ? MAXSEQ :(pFrame->BAStartingSeq.field.StartSeq -1);
1392 //ba_refresh_reordering_mpdus(pAd, pBAEntry);
1397 Description : Send PSMP Action frame If PSMP mode switches.
1399 VOID SendPSMPAction(
1400 IN PRTMP_ADAPTER pAd,
1404 PUCHAR pOutBuffer = NULL;
1405 NDIS_STATUS NStatus;
1407 FRAME_PSMP_ACTION Frame;
1410 NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory
1411 if (NStatus != NDIS_STATUS_SUCCESS)
1413 DBGPRINT(RT_DEBUG_ERROR,("BA - MlmeADDBAAction() allocate memory failed \n"));
1417 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1418 ActHeaderInit(pAd, &Frame.Hdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pAd->MacTab.Content[Wcid].Addr);
1420 Frame.Category = CATEGORY_HT;
1421 Frame.Action = SMPS_ACTION;
1434 MakeOutgoingFrame(pOutBuffer, &FrameLen,
1435 sizeof(FRAME_PSMP_ACTION), &Frame,
1437 MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
1438 MlmeFreeMemory(pAd, pOutBuffer);
1439 DBGPRINT(RT_DEBUG_ERROR,("HT - SendPSMPAction( %d ) \n", Frame.Psmp));
1443 #define RADIO_MEASUREMENT_REQUEST_ACTION 0
1445 typedef struct PACKED
1447 UCHAR RegulatoryClass;
1448 UCHAR ChannelNumber;
1449 USHORT RandomInterval;
1450 USHORT MeasurementDuration;
1451 UCHAR MeasurementMode;
1452 UCHAR BSSID[MAC_ADDR_LEN];
1453 UCHAR ReportingCondition;
1455 UCHAR SSIDIE[2]; // 2 byte
1458 typedef struct PACKED
1470 void convert_reordering_packet_to_preAMSDU_or_802_3_packet(
1471 IN PRTMP_ADAPTER pAd,
1473 IN UCHAR FromWhichBSSID)
1475 PNDIS_PACKET pRxPkt;
1476 UCHAR Header802_3[LENGTH_802_3];
1478 // 1. get 802.3 Header
1480 // a. pointer pRxBlk->pData to payload
1481 // b. modify pRxBlk->DataSize
1483 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1484 RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3);
1486 ASSERT(pRxBlk->pRxPacket);
1487 pRxPkt = RTPKT_TO_OSPKT(pRxBlk->pRxPacket);
1489 RTPKT_TO_OSPKT(pRxPkt)->dev = get_netdev_from_bssid(pAd, FromWhichBSSID);
1490 RTPKT_TO_OSPKT(pRxPkt)->data = pRxBlk->pData;
1491 RTPKT_TO_OSPKT(pRxPkt)->len = pRxBlk->DataSize;
1492 RTPKT_TO_OSPKT(pRxPkt)->tail = RTPKT_TO_OSPKT(pRxPkt)->data + RTPKT_TO_OSPKT(pRxPkt)->len;
1495 // copy 802.3 header, if necessary
1497 if (!RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU))
1499 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1502 NdisMoveMemory(skb_push(pRxPkt, LENGTH_802_3), Header802_3, LENGTH_802_3);
1509 #define INDICATE_LEGACY_OR_AMSDU(_pAd, _pRxBlk, _fromWhichBSSID) \
1512 if (RX_BLK_TEST_FLAG(_pRxBlk, fRX_AMSDU)) \
1514 Indicate_AMSDU_Packet(_pAd, _pRxBlk, _fromWhichBSSID); \
1516 else if (RX_BLK_TEST_FLAG(_pRxBlk, fRX_EAP)) \
1518 Indicate_EAPOL_Packet(_pAd, _pRxBlk, _fromWhichBSSID); \
1522 Indicate_Legacy_Packet(_pAd, _pRxBlk, _fromWhichBSSID); \
1528 static VOID ba_enqueue_reordering_packet(
1529 IN PRTMP_ADAPTER pAd,
1530 IN PBA_REC_ENTRY pBAEntry,
1532 IN UCHAR FromWhichBSSID)
1534 struct reordering_mpdu *mpdu_blk;
1535 UINT16 Sequence = (UINT16) pRxBlk->pHeader->Sequence;
1537 mpdu_blk = ba_mpdu_blk_alloc(pAd);
1538 if (mpdu_blk != NULL)
1540 // Write RxD buffer address & allocated buffer length
1541 NdisAcquireSpinLock(&pBAEntry->RxReRingLock);
1543 mpdu_blk->Sequence = Sequence;
1545 mpdu_blk->bAMSDU = RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU);
1547 convert_reordering_packet_to_preAMSDU_or_802_3_packet(pAd, pRxBlk, FromWhichBSSID);
1549 STATS_INC_RX_PACKETS(pAd, FromWhichBSSID);
1552 // it is necessary for reordering packet to record
1553 // which BSS it come from
1555 RTMP_SET_PACKET_IF(pRxBlk->pRxPacket, FromWhichBSSID);
1557 mpdu_blk->pPacket = pRxBlk->pRxPacket;
1559 if (ba_reordering_mpdu_insertsorted(&pBAEntry->list, mpdu_blk) == FALSE)
1561 // had been already within reordering list
1563 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_SUCCESS);
1564 ba_mpdu_blk_free(pAd, mpdu_blk);
1567 ASSERT((0<= pBAEntry->list.qlen) && (pBAEntry->list.qlen <= pBAEntry->BAWinSize));
1568 NdisReleaseSpinLock(&pBAEntry->RxReRingLock);
1573 DBGPRINT(RT_DEBUG_ERROR, ("!!! (%d:%d) Can't allocate reordering mpdu blk\n",
1574 blk_count, pBAEntry->list.qlen));
1576 DBGPRINT(RT_DEBUG_ERROR, ("!!! (%d) Can't allocate reordering mpdu blk\n",
1577 pBAEntry->list.qlen));
1580 * flush all pending reordering mpdus
1581 * and receving mpdu to upper layer
1582 * make tcp/ip to take care reordering mechanism
1584 //ba_refresh_reordering_mpdus(pAd, pBAEntry);
1585 ba_indicate_reordering_mpdus_le_seq(pAd, pBAEntry, Sequence);
1587 pBAEntry->LastIndSeq = Sequence;
1588 INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID);
1594 ==========================================================================
1596 Indicate this packet to upper layer or put it into reordering buffer
1599 pRxBlk : carry necessary packet info 802.11 format
1600 FromWhichBSSID : the packet received from which BSS
1606 the packet queued into reordering buffer need to cover to 802.3 format
1608 ==========================================================================
1611 VOID Indicate_AMPDU_Packet(
1612 IN PRTMP_ADAPTER pAd,
1614 IN UCHAR FromWhichBSSID)
1617 PBA_REC_ENTRY pBAEntry = NULL;
1618 UINT16 Sequence = pRxBlk->pHeader->Sequence;
1620 UCHAR Wcid = pRxBlk->pRxWI->WirelessCliID;
1621 UCHAR TID = pRxBlk->pRxWI->TID;
1624 if (!RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU) && (pRxBlk->DataSize > MAX_RX_PKT_LEN))
1626 #if 0 // sample take off, no use
1627 static int err_size;
1630 if (err_size > 20) {
1631 printk("AMPDU DataSize = %d\n", pRxBlk->DataSize);
1632 hex_dump("802.11 Header", (UCHAR *)pRxBlk->pHeader, 24);
1633 hex_dump("Payload", pRxBlk->pData, 64);
1638 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
1644 /* Rec BA Session had been torn down */
1645 INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID);
1649 if (Wcid < MAX_LEN_OF_MAC_TABLE)
1651 Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID];
1654 /* Rec BA Session had been torn down */
1655 INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID);
1658 pBAEntry = &pAd->BATable.BARecEntry[Idx];
1665 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
1671 // update last rx time
1672 NdisGetSystemUpTime(&Now32);
1674 pBAEntry->rcvSeq = Sequence;
1677 ba_flush_reordering_timeout_mpdus(pAd, pBAEntry, Now32);
1678 pBAEntry->LastIndSeqAtTimer = Now32;
1681 // Reset Last Indicate Sequence
1683 if (pBAEntry->LastIndSeq == RESET_RCV_SEQ)
1685 ASSERT((pBAEntry->list.qlen == 0) && (pBAEntry->list.next == NULL));
1687 // reset rcv sequence of BA session
1688 pBAEntry->LastIndSeq = Sequence;
1689 pBAEntry->LastIndSeqAtTimer = Now32;
1690 INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID);
1696 // I. Check if in order.
1698 if (SEQ_STEPONE(Sequence, pBAEntry->LastIndSeq, MAXSEQ))
1702 pBAEntry->LastIndSeq = Sequence;
1703 INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID);
1704 LastIndSeq = ba_indicate_reordering_mpdus_in_order(pAd, pBAEntry, pBAEntry->LastIndSeq);
1705 if (LastIndSeq != RESET_RCV_SEQ)
1707 pBAEntry->LastIndSeq = LastIndSeq;
1709 pBAEntry->LastIndSeqAtTimer = Now32;
1712 // II. Drop Duplicated Packet
1714 else if (Sequence == pBAEntry->LastIndSeq)
1717 // drop and release packet
1718 pBAEntry->nDropPacket++;
1719 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
1722 // III. Drop Old Received Packet
1724 else if (SEQ_SMALLER(Sequence, pBAEntry->LastIndSeq, MAXSEQ))
1727 // drop and release packet
1728 pBAEntry->nDropPacket++;
1729 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
1732 // IV. Receive Sequence within Window Size
1734 else if (SEQ_SMALLER(Sequence, (((pBAEntry->LastIndSeq+pBAEntry->BAWinSize+1)) & MAXSEQ), MAXSEQ))
1736 ba_enqueue_reordering_packet(pAd, pBAEntry, pRxBlk, FromWhichBSSID);
1739 // V. Receive seq surpasses Win(lastseq + nMSDU). So refresh all reorder buffer
1744 ba_refresh_reordering_mpdus(pAd, pBAEntry);
1745 INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID);
1747 LONG WinStartSeq, TmpSeq;
1750 TmpSeq = Sequence - (pBAEntry->BAWinSize) -1;
1753 TmpSeq = (MAXSEQ+1) + TmpSeq;
1755 WinStartSeq = (TmpSeq+1) & MAXSEQ;
1756 ba_indicate_reordering_mpdus_le_seq(pAd, pBAEntry, WinStartSeq);
1757 pBAEntry->LastIndSeq = WinStartSeq; //TmpSeq;
1759 pBAEntry->LastIndSeqAtTimer = Now32;
1761 ba_enqueue_reordering_packet(pAd, pBAEntry, pRxBlk, FromWhichBSSID);
1763 TmpSeq = ba_indicate_reordering_mpdus_in_order(pAd, pBAEntry, pBAEntry->LastIndSeq);
1764 if (TmpSeq != RESET_RCV_SEQ)
1766 pBAEntry->LastIndSeq = TmpSeq;
1772 #endif // DOT11_N_SUPPORT //