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 #include "../rt_config.h"
32 #define BA_ORI_INIT_SEQ (pEntry->TxSeq[TID]) //1 // inital sequence number of BA session
34 #define ORI_SESSION_MAX_RETRY 8
35 #define ORI_BA_SESSION_TIMEOUT (2000) // ms
36 #define REC_BA_SESSION_IDLE_TIMEOUT (1000) // ms
38 #define REORDERING_PACKET_TIMEOUT ((100 * OS_HZ)/1000) // system ticks -- 100 ms
39 #define MAX_REORDERING_PACKET_TIMEOUT ((3000 * OS_HZ)/1000) // system ticks -- 100 ms
41 #define RESET_RCV_SEQ (0xFFFF)
43 static void ba_mpdu_blk_free(PRTMP_ADAPTER pAd, struct reordering_mpdu *mpdu_blk);
46 BA_ORI_ENTRY *BATableAllocOriEntry(
50 BA_REC_ENTRY *BATableAllocRecEntry(
54 VOID BAOriSessionSetupTimeout(
55 IN PVOID SystemSpecific1,
56 IN PVOID FunctionContext,
57 IN PVOID SystemSpecific2,
58 IN PVOID SystemSpecific3);
60 VOID BARecSessionIdleTimeout(
61 IN PVOID SystemSpecific1,
62 IN PVOID FunctionContext,
63 IN PVOID SystemSpecific2,
64 IN PVOID SystemSpecific3);
67 BUILD_TIMER_FUNCTION(BAOriSessionSetupTimeout);
68 BUILD_TIMER_FUNCTION(BARecSessionIdleTimeout);
70 #define ANNOUNCE_REORDERING_PACKET(_pAd, _mpdu_blk) \
71 Announce_Reordering_Packet(_pAd, _mpdu_blk);
73 VOID BA_MaxWinSizeReasign(
75 IN MAC_TABLE_ENTRY *pEntryPeer,
81 if (pAd->MACVersion >= RALINK_2883_VERSION) // 3*3
83 if (pAd->MACVersion >= RALINK_3070_VERSION)
85 if (pEntryPeer->WepStatus != Ndis802_11EncryptionDisabled)
86 MaxSize = 7; // for non-open mode
93 else if (pAd->MACVersion >= RALINK_2880E_VERSION) // 2880 e
95 if (pEntryPeer->WepStatus != Ndis802_11EncryptionDisabled)
96 MaxSize = 7; // for non-open mode
103 DBGPRINT(RT_DEBUG_TRACE, ("ba> Win Size = %d, Max Size = %d\n",
104 *pWinSize, MaxSize));
106 if ((*pWinSize) > MaxSize)
108 DBGPRINT(RT_DEBUG_TRACE, ("ba> reassign max win size from %d to %d\n",
109 *pWinSize, MaxSize));
115 void Announce_Reordering_Packet(IN PRTMP_ADAPTER pAd,
116 IN struct reordering_mpdu *mpdu)
118 PNDIS_PACKET pPacket;
120 pPacket = mpdu->pPacket;
125 BA_Reorder_AMSDU_Annnounce(pAd, pPacket);
130 // pass this 802.3 packet to upper layer or forward this packet to WM directly
133 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pPacket, RTMP_GET_PACKET_IF(pPacket));
138 * Insert a reordering mpdu into sorted linked list by sequence no.
140 BOOLEAN ba_reordering_mpdu_insertsorted(struct reordering_list *list, struct reordering_mpdu *mpdu)
143 struct reordering_mpdu **ppScan = &list->next;
145 while (*ppScan != NULL)
147 if (SEQ_SMALLER((*ppScan)->Sequence, mpdu->Sequence, MAXSEQ))
149 ppScan = &(*ppScan)->next;
151 else if ((*ppScan)->Sequence == mpdu->Sequence)
153 /* give up this duplicated frame */
163 mpdu->next = *ppScan;
171 * caller lock critical section if necessary
173 static inline void ba_enqueue(struct reordering_list *list, struct reordering_mpdu *mpdu_blk)
176 mpdu_blk->next = list->next;
177 list->next = mpdu_blk;
181 * caller lock critical section if necessary
183 static inline struct reordering_mpdu * ba_dequeue(struct reordering_list *list)
185 struct reordering_mpdu *mpdu_blk = NULL;
192 mpdu_blk = list->next;
195 list->next = mpdu_blk->next;
196 mpdu_blk->next = NULL;
203 static inline struct reordering_mpdu *ba_reordering_mpdu_dequeue(struct reordering_list *list)
205 return(ba_dequeue(list));
209 static inline struct reordering_mpdu *ba_reordering_mpdu_probe(struct reordering_list *list)
218 * free all resource for reordering mechanism
220 void ba_reordering_resource_release(PRTMP_ADAPTER pAd)
223 PBA_REC_ENTRY pBAEntry;
224 struct reordering_mpdu *mpdu_blk;
229 /* I. release all pending reordering packet */
230 NdisAcquireSpinLock(&pAd->BATabLock);
231 for (i = 0; i < MAX_LEN_OF_BA_REC_TABLE; i++)
233 pBAEntry = &Tab->BARecEntry[i];
234 if (pBAEntry->REC_BA_Status != Recipient_NONE)
236 while ((mpdu_blk = ba_reordering_mpdu_dequeue(&pBAEntry->list)))
238 ASSERT(mpdu_blk->pPacket);
239 RELEASE_NDIS_PACKET(pAd, mpdu_blk->pPacket, NDIS_STATUS_FAILURE);
240 ba_mpdu_blk_free(pAd, mpdu_blk);
244 NdisReleaseSpinLock(&pAd->BATabLock);
246 ASSERT(pBAEntry->list.qlen == 0);
247 /* II. free memory of reordering mpdu table */
248 NdisAcquireSpinLock(&pAd->mpdu_blk_pool.lock);
249 os_free_mem(pAd, pAd->mpdu_blk_pool.mem);
250 NdisReleaseSpinLock(&pAd->mpdu_blk_pool.lock);
256 * Allocate all resource for reordering mechanism
258 BOOLEAN ba_reordering_resource_init(PRTMP_ADAPTER pAd, int num)
262 struct reordering_mpdu *mpdu_blk;
263 struct reordering_list *freelist;
265 /* allocate spinlock */
266 NdisAllocateSpinLock(&pAd->mpdu_blk_pool.lock);
268 /* initialize freelist */
269 freelist = &pAd->mpdu_blk_pool.freelist;
270 freelist->next = NULL;
273 DBGPRINT(RT_DEBUG_TRACE, ("Allocate %d memory for BA reordering\n", (UINT32)(num*sizeof(struct reordering_mpdu))));
275 /* allocate number of mpdu_blk memory */
276 os_alloc_mem(pAd, (PUCHAR *)&mem, (num*sizeof(struct reordering_mpdu)));
278 pAd->mpdu_blk_pool.mem = mem;
282 DBGPRINT(RT_DEBUG_ERROR, ("Can't Allocate Memory for BA Reordering\n"));
286 /* build mpdu_blk free list */
287 for (i=0; i<num; i++)
290 mpdu_blk = (struct reordering_mpdu *) mem;
291 /* initial mpdu_blk */
292 NdisZeroMemory(mpdu_blk, sizeof(struct reordering_mpdu));
294 mem += sizeof(struct reordering_mpdu);
295 /* insert mpdu_blk into freelist */
296 ba_enqueue(freelist, mpdu_blk);
302 //static int blk_count=0; // sample take off, no use
304 static struct reordering_mpdu *ba_mpdu_blk_alloc(PRTMP_ADAPTER pAd)
306 struct reordering_mpdu *mpdu_blk;
308 NdisAcquireSpinLock(&pAd->mpdu_blk_pool.lock);
309 mpdu_blk = ba_dequeue(&pAd->mpdu_blk_pool.freelist);
314 NdisZeroMemory(mpdu_blk, sizeof(struct reordering_mpdu));
316 NdisReleaseSpinLock(&pAd->mpdu_blk_pool.lock);
320 static void ba_mpdu_blk_free(PRTMP_ADAPTER pAd, struct reordering_mpdu *mpdu_blk)
324 NdisAcquireSpinLock(&pAd->mpdu_blk_pool.lock);
326 ba_enqueue(&pAd->mpdu_blk_pool.freelist, mpdu_blk);
327 NdisReleaseSpinLock(&pAd->mpdu_blk_pool.lock);
331 static USHORT ba_indicate_reordering_mpdus_in_order(
332 IN PRTMP_ADAPTER pAd,
333 IN PBA_REC_ENTRY pBAEntry,
336 struct reordering_mpdu *mpdu_blk;
337 USHORT LastIndSeq = RESET_RCV_SEQ;
339 NdisAcquireSpinLock(&pBAEntry->RxReRingLock);
341 while ((mpdu_blk = ba_reordering_mpdu_probe(&pBAEntry->list)))
343 /* find in-order frame */
344 if (!SEQ_STEPONE(mpdu_blk->Sequence, StartSeq, MAXSEQ))
348 /* dequeue in-order frame from reodering list */
349 mpdu_blk = ba_reordering_mpdu_dequeue(&pBAEntry->list);
350 /* pass this frame up */
351 ANNOUNCE_REORDERING_PACKET(pAd, mpdu_blk);
352 /* move to next sequence */
353 StartSeq = mpdu_blk->Sequence;
354 LastIndSeq = StartSeq;
356 ba_mpdu_blk_free(pAd, mpdu_blk);
359 NdisReleaseSpinLock(&pBAEntry->RxReRingLock);
361 /* update last indicated sequence */
365 static void ba_indicate_reordering_mpdus_le_seq(
366 IN PRTMP_ADAPTER pAd,
367 IN PBA_REC_ENTRY pBAEntry,
370 struct reordering_mpdu *mpdu_blk;
372 NdisAcquireSpinLock(&pBAEntry->RxReRingLock);
373 while ((mpdu_blk = ba_reordering_mpdu_probe(&pBAEntry->list)))
375 /* find in-order frame */
376 if ((mpdu_blk->Sequence == Sequence) || SEQ_SMALLER(mpdu_blk->Sequence, Sequence, MAXSEQ))
378 /* dequeue in-order frame from reodering list */
379 mpdu_blk = ba_reordering_mpdu_dequeue(&pBAEntry->list);
380 /* pass this frame up */
381 ANNOUNCE_REORDERING_PACKET(pAd, mpdu_blk);
383 ba_mpdu_blk_free(pAd, mpdu_blk);
390 NdisReleaseSpinLock(&pBAEntry->RxReRingLock);
394 static void ba_refresh_reordering_mpdus(
395 IN PRTMP_ADAPTER pAd,
396 PBA_REC_ENTRY pBAEntry)
398 struct reordering_mpdu *mpdu_blk;
400 NdisAcquireSpinLock(&pBAEntry->RxReRingLock);
402 /* dequeue in-order frame from reodering list */
403 while ((mpdu_blk = ba_reordering_mpdu_dequeue(&pBAEntry->list)))
405 /* pass this frame up */
406 ANNOUNCE_REORDERING_PACKET(pAd, mpdu_blk);
408 pBAEntry->LastIndSeq = mpdu_blk->Sequence;
409 ba_mpdu_blk_free(pAd, mpdu_blk);
411 /* update last indicated sequence */
413 ASSERT(pBAEntry->list.qlen == 0);
414 pBAEntry->LastIndSeq = RESET_RCV_SEQ;
415 NdisReleaseSpinLock(&pBAEntry->RxReRingLock);
420 void ba_flush_reordering_timeout_mpdus(
421 IN PRTMP_ADAPTER pAd,
422 IN PBA_REC_ENTRY pBAEntry,
428 // if ((RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+REORDERING_PACKET_TIMEOUT)) &&
429 // (pBAEntry->list.qlen > ((pBAEntry->BAWinSize*7)/8))) //||
430 // (RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+(10*REORDERING_PACKET_TIMEOUT))) &&
431 // (pBAEntry->list.qlen > (pBAEntry->BAWinSize/8)))
432 if (RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+(MAX_REORDERING_PACKET_TIMEOUT/6)))
433 &&(pBAEntry->list.qlen > 1)
436 DBGPRINT(RT_DEBUG_TRACE,("timeout[%d] (%08lx-%08lx = %d > %d): %x, flush all!\n ", pBAEntry->list.qlen, Now32, (pBAEntry->LastIndSeqAtTimer),
437 (int)((long) Now32 - (long)(pBAEntry->LastIndSeqAtTimer)), MAX_REORDERING_PACKET_TIMEOUT,
438 pBAEntry->LastIndSeq));
439 ba_refresh_reordering_mpdus(pAd, pBAEntry);
440 pBAEntry->LastIndSeqAtTimer = Now32;
443 if (RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+(REORDERING_PACKET_TIMEOUT)))
444 && (pBAEntry->list.qlen > 0)
448 // force LastIndSeq to shift to LastIndSeq+1
450 Sequence = (pBAEntry->LastIndSeq+1) & MAXSEQ;
451 ba_indicate_reordering_mpdus_le_seq(pAd, pBAEntry, Sequence);
452 pBAEntry->LastIndSeqAtTimer = Now32;
453 pBAEntry->LastIndSeq = Sequence;
455 // indicate in-order mpdus
457 Sequence = ba_indicate_reordering_mpdus_in_order(pAd, pBAEntry, Sequence);
458 if (Sequence != RESET_RCV_SEQ)
460 pBAEntry->LastIndSeq = Sequence;
463 DBGPRINT(RT_DEBUG_OFF, ("%x, flush one!\n", pBAEntry->LastIndSeq));
470 * generate ADDBA request to
471 * set up BA agreement
473 VOID BAOriSessionSetUp(
474 IN PRTMP_ADAPTER pAd,
475 IN MAC_TABLE_ENTRY *pEntry,
482 //MLME_ADDBA_REQ_STRUCT AddbaReq;
483 BA_ORI_ENTRY *pBAEntry = NULL;
487 if ((pAd->CommonCfg.BACapability.field.AutoBA != TRUE) && (isForced == FALSE))
490 // if this entry is limited to use legacy tx mode, it doesn't generate BA.
491 if (RTMPStaFixedTxMode(pAd, pEntry) != FIXED_TXMODE_HT)
494 if ((pEntry->BADeclineBitmap & (1<<TID)) && (isForced == FALSE))
496 // try again after 3 secs
498 // DBGPRINT(RT_DEBUG_TRACE, ("DeCline BA from Peer\n"));
503 Idx = pEntry->BAOriWcidArray[TID];
506 // allocate a BA session
507 pBAEntry = BATableAllocOriEntry(pAd, &Idx);
508 if (pBAEntry == NULL)
510 DBGPRINT(RT_DEBUG_TRACE,("ADDBA - MlmeADDBAAction() allocate BA session failed \n"));
516 pBAEntry =&pAd->BATable.BAOriEntry[Idx];
519 if (pBAEntry->ORI_BA_Status >= Originator_WaitRes)
524 pEntry->BAOriWcidArray[TID] = Idx;
526 // Initialize BA session
527 pBAEntry->ORI_BA_Status = Originator_WaitRes;
528 pBAEntry->Wcid = pEntry->Aid;
529 pBAEntry->BAWinSize = pAd->CommonCfg.BACapability.field.RxBAWinLimit;
530 pBAEntry->Sequence = BA_ORI_INIT_SEQ;
531 pBAEntry->Token = 1; // (2008-01-21) Jan Lee recommends it - this token can't be 0
533 pBAEntry->TimeOutValue = TimeOut;
534 pBAEntry->pAdapter = pAd;
536 if (!(pEntry->TXBAbitmap & (1<<TID)))
538 RTMPInitTimer(pAd, &pBAEntry->ORIBATimer, GET_TIMER_FUNCTION(BAOriSessionSetupTimeout), pBAEntry, FALSE);
541 RTMPCancelTimer(&pBAEntry->ORIBATimer, &Cancelled);
543 // set timer to send ADDBA request
544 RTMPSetTimer(&pBAEntry->ORIBATimer, DelayTime);
547 VOID BAOriSessionAdd(
548 IN PRTMP_ADAPTER pAd,
549 IN MAC_TABLE_ENTRY *pEntry,
550 IN PFRAME_ADDBA_RSP pFrame)
552 BA_ORI_ENTRY *pBAEntry = NULL;
556 PUCHAR pOutBuffer2 = NULL;
561 TID = pFrame->BaParm.TID;
562 Idx = pEntry->BAOriWcidArray[TID];
563 pBAEntry =&pAd->BATable.BAOriEntry[Idx];
565 // Start fill in parameters.
566 if ((Idx !=0) && (pBAEntry->TID == TID) && (pBAEntry->ORI_BA_Status == Originator_WaitRes))
568 pBAEntry->BAWinSize = min(pBAEntry->BAWinSize, ((UCHAR)pFrame->BaParm.BufSize));
569 BA_MaxWinSizeReasign(pAd, pEntry, &pBAEntry->BAWinSize);
571 pBAEntry->TimeOutValue = pFrame->TimeOutValue;
572 pBAEntry->ORI_BA_Status = Originator_Done;
573 pAd->BATable.numDoneOriginator ++;
575 // reset sequence number
576 pBAEntry->Sequence = BA_ORI_INIT_SEQ;
578 pEntry->TXBAbitmap |= (1<<TID);
579 RTMPCancelTimer(&pBAEntry->ORIBATimer, &Cancelled);
581 pBAEntry->ORIBATimer.TimerValue = 0; //pFrame->TimeOutValue;
583 DBGPRINT(RT_DEBUG_TRACE,("%s : TXBAbitmap = %x, BAWinSize = %d, TimeOut = %ld\n", __func__, pEntry->TXBAbitmap,
584 pBAEntry->BAWinSize, pBAEntry->ORIBATimer.TimerValue));
587 NStatus = MlmeAllocateMemory(pAd, &pOutBuffer2); //Get an unused nonpaged memory
588 if (NStatus != NDIS_STATUS_SUCCESS)
590 DBGPRINT(RT_DEBUG_TRACE,("BA - BAOriSessionAdd() allocate memory failed \n"));
594 BarHeaderInit(pAd, &FrameBar, pAd->MacTab.Content[pBAEntry->Wcid].Addr, pAd->CurrentAddress);
596 FrameBar.StartingSeq.field.FragNum = 0; // make sure sequence not clear in DEL function.
597 FrameBar.StartingSeq.field.StartSeq = pBAEntry->Sequence; // make sure sequence not clear in DEL funciton.
598 FrameBar.BarControl.TID = pBAEntry->TID; // make sure sequence not clear in DEL funciton.
599 MakeOutgoingFrame(pOutBuffer2, &FrameLen,
600 sizeof(FRAME_BAR), &FrameBar,
602 MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer2, FrameLen);
603 MlmeFreeMemory(pAd, pOutBuffer2);
606 if (pBAEntry->ORIBATimer.TimerValue)
607 RTMPSetTimer(&pBAEntry->ORIBATimer, pBAEntry->ORIBATimer.TimerValue); // in mSec
611 BOOLEAN BARecSessionAdd(
612 IN PRTMP_ADAPTER pAd,
613 IN MAC_TABLE_ENTRY *pEntry,
614 IN PFRAME_ADDBA_REQ pFrame)
616 BA_REC_ENTRY *pBAEntry = NULL;
617 BOOLEAN Status = TRUE;
629 TID = pFrame->BaParm.TID;
631 BAWinSize = min(((UCHAR)pFrame->BaParm.BufSize), (UCHAR)pAd->CommonCfg.BACapability.field.RxBAWinLimit);
639 Idx = pEntry->BARecWcidArray[TID];
644 pBAEntry = BATableAllocRecEntry(pAd, &Idx);
648 pBAEntry = &pAd->BATable.BARecEntry[Idx];
649 // flush all pending reordering mpdus
650 ba_refresh_reordering_mpdus(pAd, pBAEntry);
653 DBGPRINT(RT_DEBUG_TRACE,("%s(%ld): Idx = %d, BAWinSize(req %d) = %d\n", __func__, pAd->BATable.numAsRecipient, Idx,
654 pFrame->BaParm.BufSize, BAWinSize));
656 // Start fill in parameters.
657 if (pBAEntry != NULL)
659 ASSERT(pBAEntry->list.qlen == 0);
661 pBAEntry->REC_BA_Status = Recipient_HandleRes;
662 pBAEntry->BAWinSize = BAWinSize;
663 pBAEntry->Wcid = pEntry->Aid;
665 pBAEntry->TimeOutValue = pFrame->TimeOutValue;
666 pBAEntry->REC_BA_Status = Recipient_Accept;
667 // initial sequence number
668 pBAEntry->LastIndSeq = RESET_RCV_SEQ; //pFrame->BaStartSeq.field.StartSeq;
670 DBGPRINT(RT_DEBUG_OFF, ("Start Seq = %08x\n", pFrame->BaStartSeq.field.StartSeq));
672 if (pEntry->RXBAbitmap & (1<<TID))
674 RTMPCancelTimer(&pBAEntry->RECBATimer, &Cancelled);
678 RTMPInitTimer(pAd, &pBAEntry->RECBATimer, GET_TIMER_FUNCTION(BARecSessionIdleTimeout), pBAEntry, TRUE);
682 pEntry->RXBAbitmap |= (1<<TID);
683 pEntry->BARecWcidArray[TID] = Idx;
685 pEntry->BADeclineBitmap &= ~(1<<TID);
687 // Set BA session mask in WCID table.
688 RTMP_ADD_BA_SESSION_TO_ASIC(pAd, pEntry->Aid, TID);
690 DBGPRINT(RT_DEBUG_TRACE,("MACEntry[%d]RXBAbitmap = 0x%x. BARecWcidArray=%d\n",
691 pEntry->Aid, pEntry->RXBAbitmap, pEntry->BARecWcidArray[TID]));
696 DBGPRINT(RT_DEBUG_TRACE,("Can't Accept ADDBA for %02x:%02x:%02x:%02x:%02x:%02x TID = %d\n",
697 PRINT_MAC(pEntry->Addr), TID));
703 BA_REC_ENTRY *BATableAllocRecEntry(
704 IN PRTMP_ADAPTER pAd,
708 BA_REC_ENTRY *pBAEntry = NULL;
711 NdisAcquireSpinLock(&pAd->BATabLock);
713 if (pAd->BATable.numAsRecipient >= MAX_BARECI_SESSION)
715 DBGPRINT(RT_DEBUG_OFF, ("BA Recipeint Session (%ld) > %d\n",
716 pAd->BATable.numAsRecipient, MAX_BARECI_SESSION));
720 // reserve idx 0 to identify BAWcidArray[TID] as empty
721 for (i=1; i < MAX_LEN_OF_BA_REC_TABLE; i++)
723 pBAEntry =&pAd->BATable.BARecEntry[i];
724 if ((pBAEntry->REC_BA_Status == Recipient_NONE))
727 pAd->BATable.numAsRecipient++;
728 pBAEntry->REC_BA_Status = Recipient_USED;
735 NdisReleaseSpinLock(&pAd->BATabLock);
739 BA_ORI_ENTRY *BATableAllocOriEntry(
740 IN PRTMP_ADAPTER pAd,
744 BA_ORI_ENTRY *pBAEntry = NULL;
746 NdisAcquireSpinLock(&pAd->BATabLock);
748 if (pAd->BATable.numAsOriginator >= (MAX_LEN_OF_BA_ORI_TABLE))
753 // reserve idx 0 to identify BAWcidArray[TID] as empty
754 for (i=1; i<MAX_LEN_OF_BA_ORI_TABLE; i++)
756 pBAEntry =&pAd->BATable.BAOriEntry[i];
757 if ((pBAEntry->ORI_BA_Status == Originator_NONE))
760 pAd->BATable.numAsOriginator++;
761 pBAEntry->ORI_BA_Status = Originator_USED;
762 pBAEntry->pAdapter = pAd;
769 NdisReleaseSpinLock(&pAd->BATabLock);
774 VOID BATableFreeOriEntry(
775 IN PRTMP_ADAPTER pAd,
778 BA_ORI_ENTRY *pBAEntry = NULL;
779 MAC_TABLE_ENTRY *pEntry;
782 if ((Idx == 0) || (Idx >= MAX_LEN_OF_BA_ORI_TABLE))
785 pBAEntry =&pAd->BATable.BAOriEntry[Idx];
787 if (pBAEntry->ORI_BA_Status != Originator_NONE)
789 pEntry = &pAd->MacTab.Content[pBAEntry->Wcid];
790 pEntry->BAOriWcidArray[pBAEntry->TID] = 0;
793 NdisAcquireSpinLock(&pAd->BATabLock);
794 if (pBAEntry->ORI_BA_Status == Originator_Done)
796 pAd->BATable.numDoneOriginator -= 1;
797 pEntry->TXBAbitmap &= (~(1<<(pBAEntry->TID) ));
798 DBGPRINT(RT_DEBUG_TRACE, ("BATableFreeOriEntry numAsOriginator= %ld\n", pAd->BATable.numAsRecipient));
799 // Erase Bitmap flag.
802 ASSERT(pAd->BATable.numAsOriginator != 0);
804 pAd->BATable.numAsOriginator -= 1;
806 pBAEntry->ORI_BA_Status = Originator_NONE;
808 NdisReleaseSpinLock(&pAd->BATabLock);
813 VOID BATableFreeRecEntry(
814 IN PRTMP_ADAPTER pAd,
817 BA_REC_ENTRY *pBAEntry = NULL;
818 MAC_TABLE_ENTRY *pEntry;
821 if ((Idx == 0) || (Idx >= MAX_LEN_OF_BA_REC_TABLE))
824 pBAEntry =&pAd->BATable.BARecEntry[Idx];
826 if (pBAEntry->REC_BA_Status != Recipient_NONE)
828 pEntry = &pAd->MacTab.Content[pBAEntry->Wcid];
829 pEntry->BARecWcidArray[pBAEntry->TID] = 0;
831 NdisAcquireSpinLock(&pAd->BATabLock);
833 ASSERT(pAd->BATable.numAsRecipient != 0);
835 pAd->BATable.numAsRecipient -= 1;
837 pBAEntry->REC_BA_Status = Recipient_NONE;
838 NdisReleaseSpinLock(&pAd->BATabLock);
843 VOID BAOriSessionTearDown(
844 IN OUT PRTMP_ADAPTER pAd,
848 IN BOOLEAN bForceSend)
851 BA_ORI_ENTRY *pBAEntry;
854 if (Wcid >= MAX_LEN_OF_MAC_TABLE)
860 // Locate corresponding BA Originator Entry in BA Table with the (pAddr,TID).
862 Idx = pAd->MacTab.Content[Wcid].BAOriWcidArray[TID];
863 if ((Idx == 0) || (Idx >= MAX_LEN_OF_BA_ORI_TABLE))
865 if (bForceSend == TRUE)
867 // force send specified TID DelBA
868 MLME_DELBA_REQ_STRUCT DelbaReq;
869 MLME_QUEUE_ELEM *Elem = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG);
872 NdisZeroMemory(&DelbaReq, sizeof(DelbaReq));
873 NdisZeroMemory(Elem, sizeof(MLME_QUEUE_ELEM));
875 COPY_MAC_ADDR(DelbaReq.Addr, pAd->MacTab.Content[Wcid].Addr);
876 DelbaReq.Wcid = Wcid;
878 DelbaReq.Initiator = ORIGINATOR;
879 Elem->MsgLen = sizeof(DelbaReq);
880 NdisMoveMemory(Elem->Msg, &DelbaReq, sizeof(DelbaReq));
881 MlmeDELBAAction(pAd, Elem);
886 DBGPRINT(RT_DEBUG_ERROR, ("%s(bForceSend):alloc memory failed!\n", __func__));
893 DBGPRINT(RT_DEBUG_TRACE,("%s===>Wcid=%d.TID=%d \n", __func__, Wcid, TID));
895 pBAEntry = &pAd->BATable.BAOriEntry[Idx];
896 DBGPRINT(RT_DEBUG_TRACE,("\t===>Idx = %ld, Wcid=%d.TID=%d, ORI_BA_Status = %d \n", Idx, Wcid, TID, pBAEntry->ORI_BA_Status));
898 // Prepare DelBA action frame and send to the peer.
900 if ((bPassive == FALSE) && (TID == pBAEntry->TID) && (pBAEntry->ORI_BA_Status == Originator_Done))
902 MLME_DELBA_REQ_STRUCT DelbaReq;
903 MLME_QUEUE_ELEM *Elem = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG);
906 NdisZeroMemory(&DelbaReq, sizeof(DelbaReq));
907 NdisZeroMemory(Elem, sizeof(MLME_QUEUE_ELEM));
909 COPY_MAC_ADDR(DelbaReq.Addr, pAd->MacTab.Content[Wcid].Addr);
910 DelbaReq.Wcid = Wcid;
911 DelbaReq.TID = pBAEntry->TID;
912 DelbaReq.Initiator = ORIGINATOR;
913 Elem->MsgLen = sizeof(DelbaReq);
914 NdisMoveMemory(Elem->Msg, &DelbaReq, sizeof(DelbaReq));
915 MlmeDELBAAction(pAd, Elem);
920 DBGPRINT(RT_DEBUG_ERROR, ("%s():alloc memory failed!\n", __func__));
924 RTMPCancelTimer(&pBAEntry->ORIBATimer, &Cancelled);
925 BATableFreeOriEntry(pAd, Idx);
929 //BAOriSessionSetUp(pAd, &pAd->MacTab.Content[Wcid], TID, 0, 10000, TRUE);
933 VOID BARecSessionTearDown(
934 IN OUT PRTMP_ADAPTER pAd,
940 BA_REC_ENTRY *pBAEntry;
942 if (Wcid >= MAX_LEN_OF_MAC_TABLE)
948 // Locate corresponding BA Originator Entry in BA Table with the (pAddr,TID).
950 Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID];
954 DBGPRINT(RT_DEBUG_TRACE,("%s===>Wcid=%d.TID=%d \n", __func__, Wcid, TID));
957 pBAEntry = &pAd->BATable.BARecEntry[Idx];
958 DBGPRINT(RT_DEBUG_TRACE,("\t===>Idx = %ld, Wcid=%d.TID=%d, REC_BA_Status = %d \n", Idx, Wcid, TID, pBAEntry->REC_BA_Status));
960 // Prepare DelBA action frame and send to the peer.
962 if ((TID == pBAEntry->TID) && (pBAEntry->REC_BA_Status == Recipient_Accept))
964 MLME_DELBA_REQ_STRUCT DelbaReq;
969 RTMPCancelTimer(&pBAEntry->RECBATimer, &Cancelled);
972 // 1. Send DELBA Action Frame
974 if (bPassive == FALSE)
976 MLME_QUEUE_ELEM *Elem = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG);
979 NdisZeroMemory(&DelbaReq, sizeof(DelbaReq));
980 NdisZeroMemory(Elem, sizeof(MLME_QUEUE_ELEM));
982 COPY_MAC_ADDR(DelbaReq.Addr, pAd->MacTab.Content[Wcid].Addr);
983 DelbaReq.Wcid = Wcid;
985 DelbaReq.Initiator = RECIPIENT;
986 Elem->MsgLen = sizeof(DelbaReq);
987 NdisMoveMemory(Elem->Msg, &DelbaReq, sizeof(DelbaReq));
988 MlmeDELBAAction(pAd, Elem);
993 DBGPRINT(RT_DEBUG_ERROR, ("%s():alloc memory failed!\n", __func__));
1000 // 2. Free resource of BA session
1002 // flush all pending reordering mpdus
1003 ba_refresh_reordering_mpdus(pAd, pBAEntry);
1005 NdisAcquireSpinLock(&pAd->BATabLock);
1007 // Erase Bitmap flag.
1008 pBAEntry->LastIndSeq = RESET_RCV_SEQ;
1009 pBAEntry->BAWinSize = 0;
1010 // Erase Bitmap flag at software mactable
1011 pAd->MacTab.Content[Wcid].RXBAbitmap &= (~(1<<(pBAEntry->TID)));
1012 pAd->MacTab.Content[Wcid].BARecWcidArray[TID] = 0;
1014 RTMP_DEL_BA_SESSION_FROM_ASIC(pAd, Wcid, TID);
1016 NdisReleaseSpinLock(&pAd->BATabLock);
1020 BATableFreeRecEntry(pAd, Idx);
1023 VOID BASessionTearDownALL(
1024 IN OUT PRTMP_ADAPTER pAd,
1029 for (i=0; i<NUM_OF_TID; i++)
1031 BAOriSessionTearDown(pAd, Wcid, i, FALSE, FALSE);
1032 BARecSessionTearDown(pAd, Wcid, i, FALSE);
1038 ==========================================================================
1040 Retry sending ADDBA Reqest.
1042 IRQL = DISPATCH_LEVEL
1045 p8023Header: if this is already 802.3 format, p8023Header is NULL
1047 Return : TRUE if put into rx reordering buffer, shouldn't indicaterxhere.
1048 FALSE , then continue indicaterx at this moment.
1049 ==========================================================================
1051 VOID BAOriSessionSetupTimeout(
1052 IN PVOID SystemSpecific1,
1053 IN PVOID FunctionContext,
1054 IN PVOID SystemSpecific2,
1055 IN PVOID SystemSpecific3)
1057 BA_ORI_ENTRY *pBAEntry = (BA_ORI_ENTRY *)FunctionContext;
1058 MAC_TABLE_ENTRY *pEntry;
1061 if (pBAEntry == NULL)
1064 pAd = pBAEntry->pAdapter;
1067 // Do nothing if monitor mode is on
1068 if (MONITOR_ON(pAd))
1073 pEntry = &pAd->MacTab.Content[pBAEntry->Wcid];
1075 if ((pBAEntry->ORI_BA_Status == Originator_WaitRes) && (pBAEntry->Token < ORI_SESSION_MAX_RETRY))
1077 MLME_ADDBA_REQ_STRUCT AddbaReq;
1079 NdisZeroMemory(&AddbaReq, sizeof(AddbaReq));
1080 COPY_MAC_ADDR(AddbaReq.pAddr, pEntry->Addr);
1081 AddbaReq.Wcid = (UCHAR)(pEntry->Aid);
1082 AddbaReq.TID = pBAEntry->TID;
1083 AddbaReq.BaBufSize = pAd->CommonCfg.BACapability.field.RxBAWinLimit;
1084 AddbaReq.TimeOutValue = 0;
1085 AddbaReq.Token = pBAEntry->Token;
1086 MlmeEnqueue(pAd, ACTION_STATE_MACHINE, MT2_MLME_ADD_BA_CATE, sizeof(MLME_ADDBA_REQ_STRUCT), (PVOID)&AddbaReq);
1087 RTMP_MLME_HANDLER(pAd);
1088 DBGPRINT(RT_DEBUG_TRACE,("BA Ori Session Timeout(%d) : Send ADD BA again\n", pBAEntry->Token));
1091 RTMPSetTimer(&pBAEntry->ORIBATimer, ORI_BA_SESSION_TIMEOUT);
1095 BATableFreeOriEntry(pAd, pEntry->BAOriWcidArray[pBAEntry->TID]);
1100 ==========================================================================
1102 Retry sending ADDBA Reqest.
1104 IRQL = DISPATCH_LEVEL
1107 p8023Header: if this is already 802.3 format, p8023Header is NULL
1109 Return : TRUE if put into rx reordering buffer, shouldn't indicaterxhere.
1110 FALSE , then continue indicaterx at this moment.
1111 ==========================================================================
1113 VOID BARecSessionIdleTimeout(
1114 IN PVOID SystemSpecific1,
1115 IN PVOID FunctionContext,
1116 IN PVOID SystemSpecific2,
1117 IN PVOID SystemSpecific3)
1120 BA_REC_ENTRY *pBAEntry = (BA_REC_ENTRY *)FunctionContext;
1124 if (pBAEntry == NULL)
1127 if ((pBAEntry->REC_BA_Status == Recipient_Accept))
1129 NdisGetSystemUpTime(&Now32);
1131 if (RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer + REC_BA_SESSION_IDLE_TIMEOUT)))
1133 pAd = pBAEntry->pAdapter;
1134 // flush all pending reordering mpdus
1135 ba_refresh_reordering_mpdus(pAd, pBAEntry);
1136 DBGPRINT(RT_DEBUG_OFF, ("%ld: REC BA session Timeout\n", Now32));
1142 VOID PeerAddBAReqAction(
1143 IN PRTMP_ADAPTER pAd,
1144 IN MLME_QUEUE_ELEM *Elem)
1151 FRAME_ADDBA_RSP ADDframe;
1152 PUCHAR pOutBuffer = NULL;
1153 NDIS_STATUS NStatus;
1154 PFRAME_ADDBA_REQ pAddreqFrame = NULL;
1158 PMAC_TABLE_ENTRY pMacEntry;
1160 DBGPRINT(RT_DEBUG_TRACE, ("%s ==> (Wcid = %d)\n", __func__, Elem->Wcid));
1162 //hex_dump("AddBAReq", Elem->Msg, Elem->MsgLen);
1164 //ADDBA Request from unknown peer, ignore this.
1165 if (Elem->Wcid >= MAX_LEN_OF_MAC_TABLE)
1168 pMacEntry = &pAd->MacTab.Content[Elem->Wcid];
1169 DBGPRINT(RT_DEBUG_TRACE,("BA - PeerAddBAReqAction----> \n"));
1170 ptemp = (PULONG)Elem->Msg;
1171 //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)));
1173 if (PeerAddBAReqActionSanity(pAd, Elem->Msg, Elem->MsgLen, pAddr))
1176 if ((pAd->CommonCfg.bBADecline == FALSE) && IS_HT_STA(pMacEntry))
1178 pAddreqFrame = (PFRAME_ADDBA_REQ)(&Elem->Msg[0]);
1179 DBGPRINT(RT_DEBUG_OFF, ("Rcv Wcid(%d) AddBAReq\n", Elem->Wcid));
1180 if (BARecSessionAdd(pAd, &pAd->MacTab.Content[Elem->Wcid], pAddreqFrame))
1183 Status = 38; // more parameters have invalid values
1187 Status = 37; // the request has been declined.
1191 if (pAd->MacTab.Content[Elem->Wcid].ValidAsCLI)
1192 ASSERT(pAd->MacTab.Content[Elem->Wcid].Sst == SST_ASSOC);
1194 pAddreqFrame = (PFRAME_ADDBA_REQ)(&Elem->Msg[0]);
1195 // 2. Always send back ADDBA Response
1196 NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory
1197 if (NStatus != NDIS_STATUS_SUCCESS)
1199 DBGPRINT(RT_DEBUG_TRACE,("ACTION - PeerBAAction() allocate memory failed \n"));
1203 NdisZeroMemory(&ADDframe, sizeof(FRAME_ADDBA_RSP));
1205 // 2-1. Prepare ADDBA Response frame.
1208 ActHeaderInit(pAd, &ADDframe.Hdr, pAddr, pAd->CurrentAddress, pAd->CommonCfg.Bssid);
1210 ActHeaderInit(pAd, &ADDframe.Hdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pAddr);
1213 ADDframe.Category = CATEGORY_BA;
1214 ADDframe.Action = ADDBA_RESP;
1215 ADDframe.Token = pAddreqFrame->Token;
1216 // What is the Status code?? need to check.
1217 ADDframe.StatusCode = Status;
1218 ADDframe.BaParm.BAPolicy = IMMED_BA;
1219 ADDframe.BaParm.AMSDUSupported = 0;
1220 ADDframe.BaParm.TID = pAddreqFrame->BaParm.TID;
1221 ADDframe.BaParm.BufSize = min(((UCHAR)pAddreqFrame->BaParm.BufSize), (UCHAR)pAd->CommonCfg.BACapability.field.RxBAWinLimit);
1222 if (ADDframe.BaParm.BufSize == 0)
1224 ADDframe.BaParm.BufSize = 64;
1226 ADDframe.TimeOutValue = 0; //pAddreqFrame->TimeOutValue;
1228 *(USHORT *)(&ADDframe.BaParm) = cpu2le16(*(USHORT *)(&ADDframe.BaParm));
1229 ADDframe.StatusCode = cpu2le16(ADDframe.StatusCode);
1230 ADDframe.TimeOutValue = cpu2le16(ADDframe.TimeOutValue);
1232 MakeOutgoingFrame(pOutBuffer, &FrameLen,
1233 sizeof(FRAME_ADDBA_RSP), &ADDframe,
1235 MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
1236 MlmeFreeMemory(pAd, pOutBuffer);
1238 DBGPRINT(RT_DEBUG_TRACE, ("%s(%d): TID(%d), BufSize(%d) <== \n", __func__, Elem->Wcid, ADDframe.BaParm.TID,
1239 ADDframe.BaParm.BufSize));
1243 VOID PeerAddBARspAction(
1244 IN PRTMP_ADAPTER pAd,
1245 IN MLME_QUEUE_ELEM *Elem)
1249 //PUCHAR pOutBuffer = NULL;
1250 PFRAME_ADDBA_RSP pFrame = NULL;
1251 //PBA_ORI_ENTRY pBAEntry;
1253 //ADDBA Response from unknown peer, ignore this.
1254 if (Elem->Wcid >= MAX_LEN_OF_MAC_TABLE)
1257 DBGPRINT(RT_DEBUG_TRACE, ("%s ==> Wcid(%d)\n", __func__, Elem->Wcid));
1259 //hex_dump("PeerAddBARspAction()", Elem->Msg, Elem->MsgLen);
1261 if (PeerAddBARspActionSanity(pAd, Elem->Msg, Elem->MsgLen))
1263 pFrame = (PFRAME_ADDBA_RSP)(&Elem->Msg[0]);
1265 DBGPRINT(RT_DEBUG_TRACE, ("\t\t StatusCode = %d\n", pFrame->StatusCode));
1266 switch (pFrame->StatusCode)
1269 // I want a BAsession with this peer as an originator.
1270 BAOriSessionAdd(pAd, &pAd->MacTab.Content[Elem->Wcid], pFrame);
1273 // check status == USED ???
1274 BAOriSessionTearDown(pAd, Elem->Wcid, pFrame->BaParm.TID, TRUE, FALSE);
1277 // Rcv Decline StatusCode
1278 if ((pFrame->StatusCode == 37)
1279 || ((pAd->OpMode == OPMODE_STA) && STA_TGN_WIFI_ON(pAd) && (pFrame->StatusCode != 0))
1282 pAd->MacTab.Content[Elem->Wcid].BADeclineBitmap |= 1<<pFrame->BaParm.TID;
1287 VOID PeerDelBAAction(
1288 IN PRTMP_ADAPTER pAd,
1289 IN MLME_QUEUE_ELEM *Elem)
1293 //PUCHAR pOutBuffer = NULL;
1294 PFRAME_DELBA_REQ pDelFrame = NULL;
1296 DBGPRINT(RT_DEBUG_TRACE,("%s ==>\n", __func__));
1297 //DELBA Request from unknown peer, ignore this.
1298 if (PeerDelBAActionSanity(pAd, Elem->Wcid, Elem->Msg, Elem->MsgLen))
1300 pDelFrame = (PFRAME_DELBA_REQ)(&Elem->Msg[0]);
1301 if (pDelFrame->DelbaParm.Initiator == ORIGINATOR)
1303 DBGPRINT(RT_DEBUG_TRACE,("BA - PeerDelBAAction----> ORIGINATOR\n"));
1304 BARecSessionTearDown(pAd, Elem->Wcid, pDelFrame->DelbaParm.TID, TRUE);
1308 DBGPRINT(RT_DEBUG_TRACE,("BA - PeerDelBAAction----> RECIPIENT, Reason = %d\n", pDelFrame->ReasonCode));
1309 //hex_dump("DelBA Frame", pDelFrame, Elem->MsgLen);
1310 BAOriSessionTearDown(pAd, Elem->Wcid, pDelFrame->DelbaParm.TID, TRUE, FALSE);
1316 BOOLEAN CntlEnqueueForRecv(
1317 IN PRTMP_ADAPTER pAd,
1320 IN PFRAME_BA_REQ pMsg)
1322 PFRAME_BA_REQ pFrame = pMsg;
1323 //PRTMP_REORDERBUF pBuffer;
1324 //PRTMP_REORDERBUF pDmaBuf;
1325 PBA_REC_ENTRY pBAEntry;
1331 TID = (UCHAR)pFrame->BARControl.TID;
1333 DBGPRINT(RT_DEBUG_TRACE, ("%s(): BAR-Wcid(%ld), Tid (%d)\n", __func__, Wcid, TID));
1334 //hex_dump("BAR", (PCHAR) pFrame, MsgLen);
1335 // Do nothing if the driver is starting halt state.
1336 // This might happen when timer already been fired before cancel timer with mlmehalt
1337 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
1340 // First check the size, it MUST not exceed the mlme queue size
1341 if (MsgLen > MGMT_DMA_BUFFER_SIZE)
1343 DBGPRINT_ERR(("CntlEnqueueForRecv: frame too large, size = %ld \n", MsgLen));
1346 else if (MsgLen != sizeof(FRAME_BA_REQ))
1348 DBGPRINT_ERR(("CntlEnqueueForRecv: BlockAck Request frame length size = %ld incorrect\n", MsgLen));
1351 else if (MsgLen != sizeof(FRAME_BA_REQ))
1353 DBGPRINT_ERR(("CntlEnqueueForRecv: BlockAck Request frame length size = %ld incorrect\n", MsgLen));
1357 if ((Wcid < MAX_LEN_OF_MAC_TABLE) && (TID < 8))
1359 // if this receiving packet is from SA that is in our OriEntry. Since WCID <9 has direct mapping. no need search.
1360 Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID];
1361 pBAEntry = &pAd->BATable.BARecEntry[Idx];
1368 DBGPRINT(RT_DEBUG_TRACE, ("BAR(%ld) : Tid (%d) - %04x:%04x\n", Wcid, TID, pFrame->BAStartingSeq.field.StartSeq, pBAEntry->LastIndSeq ));
1370 if (SEQ_SMALLER(pBAEntry->LastIndSeq, pFrame->BAStartingSeq.field.StartSeq, MAXSEQ))
1372 //DBGPRINT(RT_DEBUG_TRACE, ("BAR Seq = %x, LastIndSeq = %x\n", pFrame->BAStartingSeq.field.StartSeq, pBAEntry->LastIndSeq));
1373 ba_indicate_reordering_mpdus_le_seq(pAd, pBAEntry, pFrame->BAStartingSeq.field.StartSeq);
1374 pBAEntry->LastIndSeq = (pFrame->BAStartingSeq.field.StartSeq == 0) ? MAXSEQ :(pFrame->BAStartingSeq.field.StartSeq -1);
1376 //ba_refresh_reordering_mpdus(pAd, pBAEntry);
1381 Description : Send PSMP Action frame If PSMP mode switches.
1383 VOID SendPSMPAction(
1384 IN PRTMP_ADAPTER pAd,
1388 PUCHAR pOutBuffer = NULL;
1389 NDIS_STATUS NStatus;
1391 FRAME_PSMP_ACTION Frame;
1394 NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory
1395 if (NStatus != NDIS_STATUS_SUCCESS)
1397 DBGPRINT(RT_DEBUG_ERROR,("BA - MlmeADDBAAction() allocate memory failed \n"));
1401 ActHeaderInit(pAd, &Frame.Hdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pAd->MacTab.Content[Wcid].Addr);
1403 Frame.Category = CATEGORY_HT;
1404 Frame.Action = SMPS_ACTION;
1410 &&(pAd->Antenna.field.RxPath>1||pAd->Antenna.field.TxPath>1))
1412 RTMP_ASIC_MMPS_DISABLE(pAd);
1423 &&(pAd->Antenna.field.RxPath>1||pAd->Antenna.field.TxPath>1))
1425 RTMP_ASIC_MMPS_ENABLE(pAd);
1431 MakeOutgoingFrame(pOutBuffer, &FrameLen,
1432 sizeof(FRAME_PSMP_ACTION), &Frame,
1434 MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
1435 MlmeFreeMemory(pAd, pOutBuffer);
1436 DBGPRINT(RT_DEBUG_ERROR,("HT - SendPSMPAction( %d ) \n", Frame.Psmp));
1440 #define RADIO_MEASUREMENT_REQUEST_ACTION 0
1442 typedef struct PACKED
1444 UCHAR RegulatoryClass;
1445 UCHAR ChannelNumber;
1446 USHORT RandomInterval;
1447 USHORT MeasurementDuration;
1448 UCHAR MeasurementMode;
1449 UCHAR BSSID[MAC_ADDR_LEN];
1450 UCHAR ReportingCondition;
1452 UCHAR SSIDIE[2]; // 2 byte
1455 typedef struct PACKED
1467 void convert_reordering_packet_to_preAMSDU_or_802_3_packet(
1468 IN PRTMP_ADAPTER pAd,
1470 IN UCHAR FromWhichBSSID)
1472 PNDIS_PACKET pRxPkt;
1473 UCHAR Header802_3[LENGTH_802_3];
1475 // 1. get 802.3 Header
1477 // a. pointer pRxBlk->pData to payload
1478 // b. modify pRxBlk->DataSize
1480 RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3);
1482 ASSERT(pRxBlk->pRxPacket);
1483 pRxPkt = RTPKT_TO_OSPKT(pRxBlk->pRxPacket);
1485 SET_OS_PKT_NETDEV(pRxPkt, get_netdev_from_bssid(pAd, FromWhichBSSID));
1486 SET_OS_PKT_DATAPTR(pRxPkt, pRxBlk->pData);
1487 SET_OS_PKT_LEN(pRxPkt, pRxBlk->DataSize);
1488 SET_OS_PKT_DATATAIL(pRxPkt, pRxBlk->pData, pRxBlk->DataSize);
1491 // copy 802.3 header, if necessary
1493 if (!RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU))
1497 NdisMoveMemory(skb_push(pRxPkt, LENGTH_802_3), Header802_3, LENGTH_802_3);
1504 #define INDICATE_LEGACY_OR_AMSDU(_pAd, _pRxBlk, _fromWhichBSSID) \
1507 if (RX_BLK_TEST_FLAG(_pRxBlk, fRX_AMSDU)) \
1509 Indicate_AMSDU_Packet(_pAd, _pRxBlk, _fromWhichBSSID); \
1511 else if (RX_BLK_TEST_FLAG(_pRxBlk, fRX_EAP)) \
1513 Indicate_EAPOL_Packet(_pAd, _pRxBlk, _fromWhichBSSID); \
1517 Indicate_Legacy_Packet(_pAd, _pRxBlk, _fromWhichBSSID); \
1523 static VOID ba_enqueue_reordering_packet(
1524 IN PRTMP_ADAPTER pAd,
1525 IN PBA_REC_ENTRY pBAEntry,
1527 IN UCHAR FromWhichBSSID)
1529 struct reordering_mpdu *mpdu_blk;
1530 UINT16 Sequence = (UINT16) pRxBlk->pHeader->Sequence;
1532 mpdu_blk = ba_mpdu_blk_alloc(pAd);
1533 if ((mpdu_blk != NULL) &&
1534 (!RX_BLK_TEST_FLAG(pRxBlk, fRX_EAP)))
1536 // Write RxD buffer address & allocated buffer length
1537 NdisAcquireSpinLock(&pBAEntry->RxReRingLock);
1539 mpdu_blk->Sequence = Sequence;
1541 mpdu_blk->bAMSDU = RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU);
1543 convert_reordering_packet_to_preAMSDU_or_802_3_packet(pAd, pRxBlk, FromWhichBSSID);
1545 STATS_INC_RX_PACKETS(pAd, FromWhichBSSID);
1548 // it is necessary for reordering packet to record
1549 // which BSS it come from
1551 RTMP_SET_PACKET_IF(pRxBlk->pRxPacket, FromWhichBSSID);
1553 mpdu_blk->pPacket = pRxBlk->pRxPacket;
1555 if (ba_reordering_mpdu_insertsorted(&pBAEntry->list, mpdu_blk) == FALSE)
1557 // had been already within reordering list
1559 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_SUCCESS);
1560 ba_mpdu_blk_free(pAd, mpdu_blk);
1563 ASSERT((0<= pBAEntry->list.qlen) && (pBAEntry->list.qlen <= pBAEntry->BAWinSize));
1564 NdisReleaseSpinLock(&pBAEntry->RxReRingLock);
1568 DBGPRINT(RT_DEBUG_ERROR, ("!!! (%d) Can't allocate reordering mpdu blk\n",
1569 pBAEntry->list.qlen));
1572 * flush all pending reordering mpdus
1573 * and receving mpdu to upper layer
1574 * make tcp/ip to take care reordering mechanism
1576 //ba_refresh_reordering_mpdus(pAd, pBAEntry);
1577 ba_indicate_reordering_mpdus_le_seq(pAd, pBAEntry, Sequence);
1579 pBAEntry->LastIndSeq = Sequence;
1580 INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID);
1586 ==========================================================================
1588 Indicate this packet to upper layer or put it into reordering buffer
1591 pRxBlk : carry necessary packet info 802.11 format
1592 FromWhichBSSID : the packet received from which BSS
1598 the packet queued into reordering buffer need to cover to 802.3 format
1600 ==========================================================================
1603 VOID Indicate_AMPDU_Packet(
1604 IN PRTMP_ADAPTER pAd,
1606 IN UCHAR FromWhichBSSID)
1609 PBA_REC_ENTRY pBAEntry = NULL;
1610 UINT16 Sequence = pRxBlk->pHeader->Sequence;
1612 UCHAR Wcid = pRxBlk->pRxWI->WirelessCliID;
1613 UCHAR TID = pRxBlk->pRxWI->TID;
1616 if (!RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU) && (pRxBlk->DataSize > MAX_RX_PKT_LEN))
1619 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
1623 if (Wcid < MAX_LEN_OF_MAC_TABLE)
1625 Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID];
1628 /* Rec BA Session had been torn down */
1629 INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID);
1632 pBAEntry = &pAd->BATable.BARecEntry[Idx];
1639 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
1645 // update last rx time
1646 NdisGetSystemUpTime(&Now32);
1648 pBAEntry->rcvSeq = Sequence;
1651 ba_flush_reordering_timeout_mpdus(pAd, pBAEntry, Now32);
1652 pBAEntry->LastIndSeqAtTimer = Now32;
1655 // Reset Last Indicate Sequence
1657 if (pBAEntry->LastIndSeq == RESET_RCV_SEQ)
1659 ASSERT((pBAEntry->list.qlen == 0) && (pBAEntry->list.next == NULL));
1661 // reset rcv sequence of BA session
1662 pBAEntry->LastIndSeq = Sequence;
1663 pBAEntry->LastIndSeqAtTimer = Now32;
1664 INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID);
1670 // I. Check if in order.
1672 if (SEQ_STEPONE(Sequence, pBAEntry->LastIndSeq, MAXSEQ))
1676 pBAEntry->LastIndSeq = Sequence;
1677 INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID);
1678 LastIndSeq = ba_indicate_reordering_mpdus_in_order(pAd, pBAEntry, pBAEntry->LastIndSeq);
1679 if (LastIndSeq != RESET_RCV_SEQ)
1681 pBAEntry->LastIndSeq = LastIndSeq;
1683 pBAEntry->LastIndSeqAtTimer = Now32;
1686 // II. Drop Duplicated Packet
1688 else if (Sequence == pBAEntry->LastIndSeq)
1691 // drop and release packet
1692 pBAEntry->nDropPacket++;
1693 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
1696 // III. Drop Old Received Packet
1698 else if (SEQ_SMALLER(Sequence, pBAEntry->LastIndSeq, MAXSEQ))
1701 // drop and release packet
1702 pBAEntry->nDropPacket++;
1703 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
1706 // IV. Receive Sequence within Window Size
1708 else if (SEQ_SMALLER(Sequence, (((pBAEntry->LastIndSeq+pBAEntry->BAWinSize+1)) & MAXSEQ), MAXSEQ))
1710 ba_enqueue_reordering_packet(pAd, pBAEntry, pRxBlk, FromWhichBSSID);
1713 // V. Receive seq surpasses Win(lastseq + nMSDU). So refresh all reorder buffer
1717 LONG WinStartSeq, TmpSeq;
1720 TmpSeq = Sequence - (pBAEntry->BAWinSize) -1;
1723 TmpSeq = (MAXSEQ+1) + TmpSeq;
1725 WinStartSeq = (TmpSeq+1) & MAXSEQ;
1726 ba_indicate_reordering_mpdus_le_seq(pAd, pBAEntry, WinStartSeq);
1727 pBAEntry->LastIndSeq = WinStartSeq; //TmpSeq;
1729 pBAEntry->LastIndSeqAtTimer = Now32;
1731 ba_enqueue_reordering_packet(pAd, pBAEntry, pRxBlk, FromWhichBSSID);
1733 TmpSeq = ba_indicate_reordering_mpdus_in_order(pAd, pBAEntry, pBAEntry->LastIndSeq);
1734 if (TmpSeq != RESET_RCV_SEQ)
1736 pBAEntry->LastIndSeq = TmpSeq;