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"
35 #define BA_ORI_INIT_SEQ (pEntry->TxSeq[TID]) //1 // inital sequence number of BA session
37 #define ORI_SESSION_MAX_RETRY 8
38 #define ORI_BA_SESSION_TIMEOUT (2000) // ms
39 #define REC_BA_SESSION_IDLE_TIMEOUT (1000) // ms
41 #define REORDERING_PACKET_TIMEOUT ((100 * HZ)/1000) // system ticks -- 100 ms
42 #define MAX_REORDERING_PACKET_TIMEOUT ((3000 * HZ)/1000) // system ticks -- 100 ms
44 #define RESET_RCV_SEQ (0xFFFF)
46 static void ba_mpdu_blk_free(PRTMP_ADAPTER pAd, struct reordering_mpdu *mpdu_blk);
49 BA_ORI_ENTRY *BATableAllocOriEntry(
53 BA_REC_ENTRY *BATableAllocRecEntry(
57 VOID BAOriSessionSetupTimeout(
58 IN PVOID SystemSpecific1,
59 IN PVOID FunctionContext,
60 IN PVOID SystemSpecific2,
61 IN PVOID SystemSpecific3);
63 VOID BARecSessionIdleTimeout(
64 IN PVOID SystemSpecific1,
65 IN PVOID FunctionContext,
66 IN PVOID SystemSpecific2,
67 IN PVOID SystemSpecific3);
70 BUILD_TIMER_FUNCTION(BAOriSessionSetupTimeout);
71 BUILD_TIMER_FUNCTION(BARecSessionIdleTimeout);
73 #define ANNOUNCE_REORDERING_PACKET(_pAd, _mpdu_blk) \
74 Announce_Reordering_Packet(_pAd, _mpdu_blk);
76 VOID BA_MaxWinSizeReasign(
78 IN MAC_TABLE_ENTRY *pEntryPeer,
84 if (pAd->MACVersion >= RALINK_2883_VERSION) // 3*3
86 if (pAd->MACVersion >= RALINK_3070_VERSION)
88 if (pEntryPeer->WepStatus != Ndis802_11EncryptionDisabled)
89 MaxSize = 7; // for non-open mode
96 else if (pAd->MACVersion >= RALINK_2880E_VERSION) // 2880 e
98 if (pEntryPeer->WepStatus != Ndis802_11EncryptionDisabled)
99 MaxSize = 7; // for non-open mode
106 DBGPRINT(RT_DEBUG_TRACE, ("ba> Win Size = %d, Max Size = %d\n",
107 *pWinSize, MaxSize));
109 if ((*pWinSize) > MaxSize)
111 DBGPRINT(RT_DEBUG_TRACE, ("ba> reassign max win size from %d to %d\n",
112 *pWinSize, MaxSize));
118 void Announce_Reordering_Packet(IN PRTMP_ADAPTER pAd,
119 IN struct reordering_mpdu *mpdu)
121 PNDIS_PACKET pPacket;
123 pPacket = mpdu->pPacket;
128 BA_Reorder_AMSDU_Annnounce(pAd, pPacket);
133 // pass this 802.3 packet to upper layer or forward this packet to WM directly
136 #ifdef CONFIG_STA_SUPPORT
137 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
138 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pPacket, RTMP_GET_PACKET_IF(pPacket));
139 #endif // CONFIG_STA_SUPPORT //
144 * Insert a reordering mpdu into sorted linked list by sequence no.
146 BOOLEAN ba_reordering_mpdu_insertsorted(struct reordering_list *list, struct reordering_mpdu *mpdu)
149 struct reordering_mpdu **ppScan = &list->next;
151 while (*ppScan != NULL)
153 if (SEQ_SMALLER((*ppScan)->Sequence, mpdu->Sequence, MAXSEQ))
155 ppScan = &(*ppScan)->next;
157 else if ((*ppScan)->Sequence == mpdu->Sequence)
159 /* give up this duplicated frame */
169 mpdu->next = *ppScan;
177 * caller lock critical section if necessary
179 static inline void ba_enqueue(struct reordering_list *list, struct reordering_mpdu *mpdu_blk)
182 mpdu_blk->next = list->next;
183 list->next = mpdu_blk;
187 * caller lock critical section if necessary
189 static inline struct reordering_mpdu * ba_dequeue(struct reordering_list *list)
191 struct reordering_mpdu *mpdu_blk = NULL;
198 mpdu_blk = list->next;
201 list->next = mpdu_blk->next;
202 mpdu_blk->next = NULL;
209 static inline struct reordering_mpdu *ba_reordering_mpdu_dequeue(struct reordering_list *list)
211 return(ba_dequeue(list));
215 static inline struct reordering_mpdu *ba_reordering_mpdu_probe(struct reordering_list *list)
224 * free all resource for reordering mechanism
226 void ba_reordering_resource_release(PRTMP_ADAPTER pAd)
229 PBA_REC_ENTRY pBAEntry;
230 struct reordering_mpdu *mpdu_blk;
235 /* I. release all pending reordering packet */
236 NdisAcquireSpinLock(&pAd->BATabLock);
237 for (i = 0; i < MAX_LEN_OF_BA_REC_TABLE; i++)
239 pBAEntry = &Tab->BARecEntry[i];
240 if (pBAEntry->REC_BA_Status != Recipient_NONE)
242 while ((mpdu_blk = ba_reordering_mpdu_dequeue(&pBAEntry->list)))
244 ASSERT(mpdu_blk->pPacket);
245 RELEASE_NDIS_PACKET(pAd, mpdu_blk->pPacket, NDIS_STATUS_FAILURE);
246 ba_mpdu_blk_free(pAd, mpdu_blk);
250 NdisReleaseSpinLock(&pAd->BATabLock);
252 ASSERT(pBAEntry->list.qlen == 0);
253 /* II. free memory of reordering mpdu table */
254 NdisAcquireSpinLock(&pAd->mpdu_blk_pool.lock);
255 os_free_mem(pAd, pAd->mpdu_blk_pool.mem);
256 NdisReleaseSpinLock(&pAd->mpdu_blk_pool.lock);
262 * Allocate all resource for reordering mechanism
264 BOOLEAN ba_reordering_resource_init(PRTMP_ADAPTER pAd, int num)
268 struct reordering_mpdu *mpdu_blk;
269 struct reordering_list *freelist;
271 /* allocate spinlock */
272 NdisAllocateSpinLock(&pAd->mpdu_blk_pool.lock);
274 /* initialize freelist */
275 freelist = &pAd->mpdu_blk_pool.freelist;
276 freelist->next = NULL;
279 DBGPRINT(RT_DEBUG_TRACE, ("Allocate %d memory for BA reordering\n", (UINT32)(num*sizeof(struct reordering_mpdu))));
281 /* allocate number of mpdu_blk memory */
282 os_alloc_mem(pAd, (PUCHAR *)&mem, (num*sizeof(struct reordering_mpdu)));
284 pAd->mpdu_blk_pool.mem = mem;
288 DBGPRINT(RT_DEBUG_ERROR, ("Can't Allocate Memory for BA Reordering\n"));
292 /* build mpdu_blk free list */
293 for (i=0; i<num; i++)
296 mpdu_blk = (struct reordering_mpdu *) mem;
297 /* initial mpdu_blk */
298 NdisZeroMemory(mpdu_blk, sizeof(struct reordering_mpdu));
300 mem += sizeof(struct reordering_mpdu);
301 /* insert mpdu_blk into freelist */
302 ba_enqueue(freelist, mpdu_blk);
308 //static int blk_count=0; // sample take off, no use
310 static struct reordering_mpdu *ba_mpdu_blk_alloc(PRTMP_ADAPTER pAd)
312 struct reordering_mpdu *mpdu_blk;
314 NdisAcquireSpinLock(&pAd->mpdu_blk_pool.lock);
315 mpdu_blk = ba_dequeue(&pAd->mpdu_blk_pool.freelist);
320 NdisZeroMemory(mpdu_blk, sizeof(struct reordering_mpdu));
322 NdisReleaseSpinLock(&pAd->mpdu_blk_pool.lock);
326 static void ba_mpdu_blk_free(PRTMP_ADAPTER pAd, struct reordering_mpdu *mpdu_blk)
330 NdisAcquireSpinLock(&pAd->mpdu_blk_pool.lock);
332 ba_enqueue(&pAd->mpdu_blk_pool.freelist, mpdu_blk);
333 NdisReleaseSpinLock(&pAd->mpdu_blk_pool.lock);
337 static USHORT ba_indicate_reordering_mpdus_in_order(
338 IN PRTMP_ADAPTER pAd,
339 IN PBA_REC_ENTRY pBAEntry,
342 struct reordering_mpdu *mpdu_blk;
343 USHORT LastIndSeq = RESET_RCV_SEQ;
345 NdisAcquireSpinLock(&pBAEntry->RxReRingLock);
347 while ((mpdu_blk = ba_reordering_mpdu_probe(&pBAEntry->list)))
349 /* find in-order frame */
350 if (!SEQ_STEPONE(mpdu_blk->Sequence, StartSeq, MAXSEQ))
354 /* dequeue in-order frame from reodering list */
355 mpdu_blk = ba_reordering_mpdu_dequeue(&pBAEntry->list);
356 /* pass this frame up */
357 ANNOUNCE_REORDERING_PACKET(pAd, mpdu_blk);
358 /* move to next sequence */
359 StartSeq = mpdu_blk->Sequence;
360 LastIndSeq = StartSeq;
362 ba_mpdu_blk_free(pAd, mpdu_blk);
365 NdisReleaseSpinLock(&pBAEntry->RxReRingLock);
367 /* update last indicated sequence */
371 static void ba_indicate_reordering_mpdus_le_seq(
372 IN PRTMP_ADAPTER pAd,
373 IN PBA_REC_ENTRY pBAEntry,
376 struct reordering_mpdu *mpdu_blk;
378 NdisAcquireSpinLock(&pBAEntry->RxReRingLock);
379 while ((mpdu_blk = ba_reordering_mpdu_probe(&pBAEntry->list)))
381 /* find in-order frame */
382 if ((mpdu_blk->Sequence == Sequence) || SEQ_SMALLER(mpdu_blk->Sequence, Sequence, MAXSEQ))
384 /* dequeue in-order frame from reodering list */
385 mpdu_blk = ba_reordering_mpdu_dequeue(&pBAEntry->list);
386 /* pass this frame up */
387 ANNOUNCE_REORDERING_PACKET(pAd, mpdu_blk);
389 ba_mpdu_blk_free(pAd, mpdu_blk);
396 NdisReleaseSpinLock(&pBAEntry->RxReRingLock);
400 static void ba_refresh_reordering_mpdus(
401 IN PRTMP_ADAPTER pAd,
402 PBA_REC_ENTRY pBAEntry)
404 struct reordering_mpdu *mpdu_blk;
406 NdisAcquireSpinLock(&pBAEntry->RxReRingLock);
408 /* dequeue in-order frame from reodering list */
409 while ((mpdu_blk = ba_reordering_mpdu_dequeue(&pBAEntry->list)))
411 /* pass this frame up */
412 ANNOUNCE_REORDERING_PACKET(pAd, mpdu_blk);
414 pBAEntry->LastIndSeq = mpdu_blk->Sequence;
415 ba_mpdu_blk_free(pAd, mpdu_blk);
417 /* update last indicated sequence */
419 ASSERT(pBAEntry->list.qlen == 0);
420 pBAEntry->LastIndSeq = RESET_RCV_SEQ;
421 NdisReleaseSpinLock(&pBAEntry->RxReRingLock);
426 void ba_flush_reordering_timeout_mpdus(
427 IN PRTMP_ADAPTER pAd,
428 IN PBA_REC_ENTRY pBAEntry,
434 // if ((RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+REORDERING_PACKET_TIMEOUT)) &&
435 // (pBAEntry->list.qlen > ((pBAEntry->BAWinSize*7)/8))) //||
436 // (RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+(10*REORDERING_PACKET_TIMEOUT))) &&
437 // (pBAEntry->list.qlen > (pBAEntry->BAWinSize/8)))
438 if (RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+(MAX_REORDERING_PACKET_TIMEOUT/6)))
439 &&(pBAEntry->list.qlen > 1)
442 DBGPRINT(RT_DEBUG_TRACE,("timeout[%d] (%08lx-%08lx = %d > %d): %x, flush all!\n ", pBAEntry->list.qlen, Now32, (pBAEntry->LastIndSeqAtTimer),
443 (int)((long) Now32 - (long)(pBAEntry->LastIndSeqAtTimer)), MAX_REORDERING_PACKET_TIMEOUT,
444 pBAEntry->LastIndSeq));
445 ba_refresh_reordering_mpdus(pAd, pBAEntry);
446 pBAEntry->LastIndSeqAtTimer = Now32;
449 if (RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+(REORDERING_PACKET_TIMEOUT)))
450 && (pBAEntry->list.qlen > 0)
453 // printk("timeout[%d] (%lx-%lx = %d > %d): %x, ", pBAEntry->list.qlen, Now32, (pBAEntry->LastIndSeqAtTimer),
454 // (int)((long) Now32 - (long)(pBAEntry->LastIndSeqAtTimer)), REORDERING_PACKET_TIMEOUT,
455 // pBAEntry->LastIndSeq);
457 // force LastIndSeq to shift to LastIndSeq+1
459 Sequence = (pBAEntry->LastIndSeq+1) & MAXSEQ;
460 ba_indicate_reordering_mpdus_le_seq(pAd, pBAEntry, Sequence);
461 pBAEntry->LastIndSeqAtTimer = Now32;
462 pBAEntry->LastIndSeq = Sequence;
464 // indicate in-order mpdus
466 Sequence = ba_indicate_reordering_mpdus_in_order(pAd, pBAEntry, Sequence);
467 if (Sequence != RESET_RCV_SEQ)
469 pBAEntry->LastIndSeq = Sequence;
472 //printk("%x, flush one!\n", pBAEntry->LastIndSeq);
479 * generate ADDBA request to
480 * set up BA agreement
482 VOID BAOriSessionSetUp(
483 IN PRTMP_ADAPTER pAd,
484 IN MAC_TABLE_ENTRY *pEntry,
491 //MLME_ADDBA_REQ_STRUCT AddbaReq;
492 BA_ORI_ENTRY *pBAEntry = NULL;
496 if ((pAd->CommonCfg.BACapability.field.AutoBA != TRUE) && (isForced == FALSE))
499 // if this entry is limited to use legacy tx mode, it doesn't generate BA.
500 if (RTMPStaFixedTxMode(pAd, pEntry) != FIXED_TXMODE_HT)
503 if ((pEntry->BADeclineBitmap & (1<<TID)) && (isForced == FALSE))
505 // try again after 3 secs
507 // printk("DeCline BA from Peer\n");
512 Idx = pEntry->BAOriWcidArray[TID];
515 // allocate a BA session
516 pBAEntry = BATableAllocOriEntry(pAd, &Idx);
517 if (pBAEntry == NULL)
519 DBGPRINT(RT_DEBUG_TRACE,("ADDBA - MlmeADDBAAction() allocate BA session failed \n"));
525 pBAEntry =&pAd->BATable.BAOriEntry[Idx];
528 if (pBAEntry->ORI_BA_Status >= Originator_WaitRes)
533 pEntry->BAOriWcidArray[TID] = Idx;
535 // Initialize BA session
536 pBAEntry->ORI_BA_Status = Originator_WaitRes;
537 pBAEntry->Wcid = pEntry->Aid;
538 pBAEntry->BAWinSize = pAd->CommonCfg.BACapability.field.RxBAWinLimit;
539 pBAEntry->Sequence = BA_ORI_INIT_SEQ;
540 pBAEntry->Token = 1; // (2008-01-21) Jan Lee recommends it - this token can't be 0
542 pBAEntry->TimeOutValue = TimeOut;
543 pBAEntry->pAdapter = pAd;
545 DBGPRINT(RT_DEBUG_TRACE,("Send AddBA to %02x:%02x:%02x:%02x:%02x:%02x Tid:%d isForced:%d Wcid:%d\n"
546 ,pEntry->Addr[0],pEntry->Addr[1],pEntry->Addr[2]
547 ,pEntry->Addr[3],pEntry->Addr[4],pEntry->Addr[5]
548 ,TID,isForced,pEntry->Aid));
550 if (!(pEntry->TXBAbitmap & (1<<TID)))
552 RTMPInitTimer(pAd, &pBAEntry->ORIBATimer, GET_TIMER_FUNCTION(BAOriSessionSetupTimeout), pBAEntry, FALSE);
555 RTMPCancelTimer(&pBAEntry->ORIBATimer, &Cancelled);
557 // set timer to send ADDBA request
558 RTMPSetTimer(&pBAEntry->ORIBATimer, DelayTime);
561 VOID BAOriSessionAdd(
562 IN PRTMP_ADAPTER pAd,
563 IN MAC_TABLE_ENTRY *pEntry,
564 IN PFRAME_ADDBA_RSP pFrame)
566 BA_ORI_ENTRY *pBAEntry = NULL;
570 PUCHAR pOutBuffer2 = NULL;
575 TID = pFrame->BaParm.TID;
576 Idx = pEntry->BAOriWcidArray[TID];
577 pBAEntry =&pAd->BATable.BAOriEntry[Idx];
579 // Start fill in parameters.
580 if ((Idx !=0) && (pBAEntry->TID == TID) && (pBAEntry->ORI_BA_Status == Originator_WaitRes))
582 pBAEntry->BAWinSize = min(pBAEntry->BAWinSize, ((UCHAR)pFrame->BaParm.BufSize));
583 BA_MaxWinSizeReasign(pAd, pEntry, &pBAEntry->BAWinSize);
585 pBAEntry->TimeOutValue = pFrame->TimeOutValue;
586 pBAEntry->ORI_BA_Status = Originator_Done;
587 // reset sequence number
588 pBAEntry->Sequence = BA_ORI_INIT_SEQ;
590 pEntry->TXBAbitmap |= (1<<TID);
591 RTMPCancelTimer(&pBAEntry->ORIBATimer, &Cancelled);
593 pBAEntry->ORIBATimer.TimerValue = 0; //pFrame->TimeOutValue;
595 DBGPRINT(RT_DEBUG_TRACE,("%s : TXBAbitmap = %x, BAWinSize = %d, TimeOut = %ld\n", __func__, pEntry->TXBAbitmap,
596 pBAEntry->BAWinSize, pBAEntry->ORIBATimer.TimerValue));
599 NStatus = MlmeAllocateMemory(pAd, &pOutBuffer2); //Get an unused nonpaged memory
600 if (NStatus != NDIS_STATUS_SUCCESS)
602 DBGPRINT(RT_DEBUG_TRACE,("BA - BAOriSessionAdd() allocate memory failed \n"));
607 #ifdef CONFIG_STA_SUPPORT
608 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
609 BarHeaderInit(pAd, &FrameBar, pAd->MacTab.Content[pBAEntry->Wcid].Addr, pAd->CurrentAddress);
610 #endif // CONFIG_STA_SUPPORT //
612 FrameBar.StartingSeq.field.FragNum = 0; // make sure sequence not clear in DEL function.
613 FrameBar.StartingSeq.field.StartSeq = pBAEntry->Sequence; // make sure sequence not clear in DEL funciton.
614 FrameBar.BarControl.TID = pBAEntry->TID; // make sure sequence not clear in DEL funciton.
615 MakeOutgoingFrame(pOutBuffer2, &FrameLen,
616 sizeof(FRAME_BAR), &FrameBar,
618 MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer2, FrameLen);
619 MlmeFreeMemory(pAd, pOutBuffer2);
622 if (pBAEntry->ORIBATimer.TimerValue)
623 RTMPSetTimer(&pBAEntry->ORIBATimer, pBAEntry->ORIBATimer.TimerValue); // in mSec
627 BOOLEAN BARecSessionAdd(
628 IN PRTMP_ADAPTER pAd,
629 IN MAC_TABLE_ENTRY *pEntry,
630 IN PFRAME_ADDBA_REQ pFrame)
632 BA_REC_ENTRY *pBAEntry = NULL;
633 BOOLEAN Status = TRUE;
645 TID = pFrame->BaParm.TID;
647 BAWinSize = min(((UCHAR)pFrame->BaParm.BufSize), (UCHAR)pAd->CommonCfg.BACapability.field.RxBAWinLimit);
655 Idx = pEntry->BARecWcidArray[TID];
660 pBAEntry = BATableAllocRecEntry(pAd, &Idx);
664 pBAEntry = &pAd->BATable.BARecEntry[Idx];
665 // flush all pending reordering mpdus
666 ba_refresh_reordering_mpdus(pAd, pBAEntry);
669 DBGPRINT(RT_DEBUG_TRACE,("%s(%ld): Idx = %d, BAWinSize(req %d) = %d\n", __func__, pAd->BATable.numAsRecipient, Idx,
670 pFrame->BaParm.BufSize, BAWinSize));
672 // Start fill in parameters.
673 if (pBAEntry != NULL)
675 ASSERT(pBAEntry->list.qlen == 0);
677 pBAEntry->REC_BA_Status = Recipient_HandleRes;
678 pBAEntry->BAWinSize = BAWinSize;
679 pBAEntry->Wcid = pEntry->Aid;
681 pBAEntry->TimeOutValue = pFrame->TimeOutValue;
682 pBAEntry->REC_BA_Status = Recipient_Accept;
683 // initial sequence number
684 pBAEntry->LastIndSeq = RESET_RCV_SEQ; //pFrame->BaStartSeq.field.StartSeq;
686 printk("Start Seq = %08x\n", pFrame->BaStartSeq.field.StartSeq);
688 if (pEntry->RXBAbitmap & (1<<TID))
690 RTMPCancelTimer(&pBAEntry->RECBATimer, &Cancelled);
694 RTMPInitTimer(pAd, &pBAEntry->RECBATimer, GET_TIMER_FUNCTION(BARecSessionIdleTimeout), pBAEntry, TRUE);
698 pEntry->RXBAbitmap |= (1<<TID);
699 pEntry->BARecWcidArray[TID] = Idx;
701 pEntry->BADeclineBitmap &= ~(1<<TID);
703 // Set BA session mask in WCID table.
704 RT28XX_ADD_BA_SESSION_TO_ASIC(pAd, pEntry->Aid, TID);
706 DBGPRINT(RT_DEBUG_TRACE,("MACEntry[%d]RXBAbitmap = 0x%x. BARecWcidArray=%d\n",
707 pEntry->Aid, pEntry->RXBAbitmap, pEntry->BARecWcidArray[TID]));
712 DBGPRINT(RT_DEBUG_TRACE,("Can't Accept ADDBA for %02x:%02x:%02x:%02x:%02x:%02x TID = %d\n",
713 PRINT_MAC(pEntry->Addr), TID));
719 BA_REC_ENTRY *BATableAllocRecEntry(
720 IN PRTMP_ADAPTER pAd,
724 BA_REC_ENTRY *pBAEntry = NULL;
727 NdisAcquireSpinLock(&pAd->BATabLock);
729 if (pAd->BATable.numAsRecipient >= MAX_BARECI_SESSION)
731 printk("BA Recipeint Session (%ld) > %d\n", pAd->BATable.numAsRecipient,
736 // reserve idx 0 to identify BAWcidArray[TID] as empty
737 for (i=1; i < MAX_LEN_OF_BA_REC_TABLE; i++)
739 pBAEntry =&pAd->BATable.BARecEntry[i];
740 if ((pBAEntry->REC_BA_Status == Recipient_NONE))
743 pAd->BATable.numAsRecipient++;
744 pBAEntry->REC_BA_Status = Recipient_USED;
751 NdisReleaseSpinLock(&pAd->BATabLock);
755 BA_ORI_ENTRY *BATableAllocOriEntry(
756 IN PRTMP_ADAPTER pAd,
760 BA_ORI_ENTRY *pBAEntry = NULL;
762 NdisAcquireSpinLock(&pAd->BATabLock);
764 if (pAd->BATable.numAsOriginator >= (MAX_LEN_OF_BA_ORI_TABLE))
769 // reserve idx 0 to identify BAWcidArray[TID] as empty
770 for (i=1; i<MAX_LEN_OF_BA_ORI_TABLE; i++)
772 pBAEntry =&pAd->BATable.BAOriEntry[i];
773 if ((pBAEntry->ORI_BA_Status == Originator_NONE))
776 pAd->BATable.numAsOriginator++;
777 pBAEntry->ORI_BA_Status = Originator_USED;
778 pBAEntry->pAdapter = pAd;
785 NdisReleaseSpinLock(&pAd->BATabLock);
790 VOID BATableFreeOriEntry(
791 IN PRTMP_ADAPTER pAd,
794 BA_ORI_ENTRY *pBAEntry = NULL;
795 MAC_TABLE_ENTRY *pEntry;
798 if ((Idx == 0) || (Idx >= MAX_LEN_OF_BA_ORI_TABLE))
801 pBAEntry =&pAd->BATable.BAOriEntry[Idx];
803 if (pBAEntry->ORI_BA_Status != Originator_NONE)
805 pEntry = &pAd->MacTab.Content[pBAEntry->Wcid];
806 pEntry->BAOriWcidArray[pBAEntry->TID] = 0;
809 NdisAcquireSpinLock(&pAd->BATabLock);
810 if (pBAEntry->ORI_BA_Status == Originator_Done)
812 pEntry->TXBAbitmap &= (~(1<<(pBAEntry->TID) ));
813 DBGPRINT(RT_DEBUG_TRACE, ("BATableFreeOriEntry numAsOriginator= %ld\n", pAd->BATable.numAsRecipient));
814 // Erase Bitmap flag.
817 ASSERT(pAd->BATable.numAsOriginator != 0);
819 pAd->BATable.numAsOriginator -= 1;
821 pBAEntry->ORI_BA_Status = Originator_NONE;
823 NdisReleaseSpinLock(&pAd->BATabLock);
828 VOID BATableFreeRecEntry(
829 IN PRTMP_ADAPTER pAd,
832 BA_REC_ENTRY *pBAEntry = NULL;
833 MAC_TABLE_ENTRY *pEntry;
836 if ((Idx == 0) || (Idx >= MAX_LEN_OF_BA_REC_TABLE))
839 pBAEntry =&pAd->BATable.BARecEntry[Idx];
841 if (pBAEntry->REC_BA_Status != Recipient_NONE)
843 pEntry = &pAd->MacTab.Content[pBAEntry->Wcid];
844 pEntry->BARecWcidArray[pBAEntry->TID] = 0;
846 NdisAcquireSpinLock(&pAd->BATabLock);
848 ASSERT(pAd->BATable.numAsRecipient != 0);
850 pAd->BATable.numAsRecipient -= 1;
852 pBAEntry->REC_BA_Status = Recipient_NONE;
853 NdisReleaseSpinLock(&pAd->BATabLock);
858 VOID BAOriSessionTearDown(
859 IN OUT PRTMP_ADAPTER pAd,
863 IN BOOLEAN bForceSend)
866 BA_ORI_ENTRY *pBAEntry;
869 if (Wcid >= MAX_LEN_OF_MAC_TABLE)
875 // Locate corresponding BA Originator Entry in BA Table with the (pAddr,TID).
877 Idx = pAd->MacTab.Content[Wcid].BAOriWcidArray[TID];
878 if ((Idx == 0) || (Idx >= MAX_LEN_OF_BA_ORI_TABLE))
880 if (bForceSend == TRUE)
882 // force send specified TID DelBA
883 MLME_DELBA_REQ_STRUCT DelbaReq;
884 MLME_QUEUE_ELEM *Elem = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG);
886 NdisZeroMemory(&DelbaReq, sizeof(DelbaReq));
887 NdisZeroMemory(Elem, sizeof(MLME_QUEUE_ELEM));
889 COPY_MAC_ADDR(DelbaReq.Addr, pAd->MacTab.Content[Wcid].Addr);
890 DelbaReq.Wcid = Wcid;
892 DelbaReq.Initiator = ORIGINATOR;
894 Elem->MsgLen = sizeof(DelbaReq);
895 NdisMoveMemory(Elem->Msg, &DelbaReq, sizeof(DelbaReq));
896 MlmeDELBAAction(pAd, Elem);
899 MlmeEnqueue(pAd, ACTION_STATE_MACHINE, MT2_MLME_ORI_DELBA_CATE, sizeof(MLME_DELBA_REQ_STRUCT), (PVOID)&DelbaReq);
900 RT28XX_MLME_HANDLER(pAd);
907 DBGPRINT(RT_DEBUG_TRACE,("%s===>Wcid=%d.TID=%d \n", __func__, Wcid, TID));
909 pBAEntry = &pAd->BATable.BAOriEntry[Idx];
910 DBGPRINT(RT_DEBUG_TRACE,("\t===>Idx = %ld, Wcid=%d.TID=%d, ORI_BA_Status = %d \n", Idx, Wcid, TID, pBAEntry->ORI_BA_Status));
912 // Prepare DelBA action frame and send to the peer.
914 if ((bPassive == FALSE) && (TID == pBAEntry->TID) && (pBAEntry->ORI_BA_Status == Originator_Done))
916 MLME_DELBA_REQ_STRUCT DelbaReq;
917 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;
927 Elem->MsgLen = sizeof(DelbaReq);
928 NdisMoveMemory(Elem->Msg, &DelbaReq, sizeof(DelbaReq));
929 MlmeDELBAAction(pAd, Elem);
932 MlmeEnqueue(pAd, ACTION_STATE_MACHINE, MT2_MLME_ORI_DELBA_CATE, sizeof(MLME_DELBA_REQ_STRUCT), (PVOID)&DelbaReq);
933 RT28XX_MLME_HANDLER(pAd);
936 RTMPCancelTimer(&pBAEntry->ORIBATimer, &Cancelled);
937 BATableFreeOriEntry(pAd, Idx);
941 //BAOriSessionSetUp(pAd, &pAd->MacTab.Content[Wcid], TID, 0, 10000, TRUE);
945 VOID BARecSessionTearDown(
946 IN OUT PRTMP_ADAPTER pAd,
952 BA_REC_ENTRY *pBAEntry;
954 if (Wcid >= MAX_LEN_OF_MAC_TABLE)
960 // Locate corresponding BA Originator Entry in BA Table with the (pAddr,TID).
962 Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID];
966 DBGPRINT(RT_DEBUG_TRACE,("%s===>Wcid=%d.TID=%d \n", __func__, Wcid, TID));
969 pBAEntry = &pAd->BATable.BARecEntry[Idx];
970 DBGPRINT(RT_DEBUG_TRACE,("\t===>Idx = %ld, Wcid=%d.TID=%d, REC_BA_Status = %d \n", Idx, Wcid, TID, pBAEntry->REC_BA_Status));
972 // Prepare DelBA action frame and send to the peer.
974 if ((TID == pBAEntry->TID) && (pBAEntry->REC_BA_Status == Recipient_Accept))
976 MLME_DELBA_REQ_STRUCT DelbaReq;
978 MLME_QUEUE_ELEM *Elem = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG);
982 RTMPCancelTimer(&pBAEntry->RECBATimer, &Cancelled);
985 // 1. Send DELBA Action Frame
987 if (bPassive == FALSE)
989 NdisZeroMemory(&DelbaReq, sizeof(DelbaReq));
990 NdisZeroMemory(Elem, sizeof(MLME_QUEUE_ELEM));
992 COPY_MAC_ADDR(DelbaReq.Addr, pAd->MacTab.Content[Wcid].Addr);
993 DelbaReq.Wcid = Wcid;
995 DelbaReq.Initiator = RECIPIENT;
997 Elem->MsgLen = sizeof(DelbaReq);
998 NdisMoveMemory(Elem->Msg, &DelbaReq, sizeof(DelbaReq));
999 MlmeDELBAAction(pAd, Elem);
1002 MlmeEnqueue(pAd, ACTION_STATE_MACHINE, MT2_MLME_ORI_DELBA_CATE, sizeof(MLME_DELBA_REQ_STRUCT), (PVOID)&DelbaReq);
1003 RT28XX_MLME_HANDLER(pAd);
1009 // 2. Free resource of BA session
1011 // flush all pending reordering mpdus
1012 ba_refresh_reordering_mpdus(pAd, pBAEntry);
1014 NdisAcquireSpinLock(&pAd->BATabLock);
1016 // Erase Bitmap flag.
1017 pBAEntry->LastIndSeq = RESET_RCV_SEQ;
1018 pBAEntry->BAWinSize = 0;
1019 // Erase Bitmap flag at software mactable
1020 pAd->MacTab.Content[Wcid].RXBAbitmap &= (~(1<<(pBAEntry->TID)));
1021 pAd->MacTab.Content[Wcid].BARecWcidArray[TID] = 0;
1023 RT28XX_DEL_BA_SESSION_FROM_ASIC(pAd, Wcid, TID);
1025 NdisReleaseSpinLock(&pAd->BATabLock);
1029 BATableFreeRecEntry(pAd, Idx);
1032 VOID BASessionTearDownALL(
1033 IN OUT PRTMP_ADAPTER pAd,
1038 for (i=0; i<NUM_OF_TID; i++)
1040 BAOriSessionTearDown(pAd, Wcid, i, FALSE, FALSE);
1041 BARecSessionTearDown(pAd, Wcid, i, FALSE);
1047 ==========================================================================
1049 Retry sending ADDBA Reqest.
1051 IRQL = DISPATCH_LEVEL
1054 p8023Header: if this is already 802.3 format, p8023Header is NULL
1056 Return : TRUE if put into rx reordering buffer, shouldn't indicaterxhere.
1057 FALSE , then continue indicaterx at this moment.
1058 ==========================================================================
1060 VOID BAOriSessionSetupTimeout(
1061 IN PVOID SystemSpecific1,
1062 IN PVOID FunctionContext,
1063 IN PVOID SystemSpecific2,
1064 IN PVOID SystemSpecific3)
1066 BA_ORI_ENTRY *pBAEntry = (BA_ORI_ENTRY *)FunctionContext;
1067 MAC_TABLE_ENTRY *pEntry;
1070 if (pBAEntry == NULL)
1073 pAd = pBAEntry->pAdapter;
1075 #ifdef CONFIG_STA_SUPPORT
1076 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1078 // Do nothing if monitor mode is on
1079 if (MONITOR_ON(pAd))
1082 #endif // CONFIG_STA_SUPPORT //
1084 pEntry = &pAd->MacTab.Content[pBAEntry->Wcid];
1086 if ((pBAEntry->ORI_BA_Status == Originator_WaitRes) && (pBAEntry->Token < ORI_SESSION_MAX_RETRY))
1088 MLME_ADDBA_REQ_STRUCT AddbaReq;
1090 NdisZeroMemory(&AddbaReq, sizeof(AddbaReq));
1091 COPY_MAC_ADDR(AddbaReq.pAddr, pEntry->Addr);
1092 AddbaReq.Wcid = (UCHAR)(pEntry->Aid);
1093 AddbaReq.TID = pBAEntry->TID;
1094 AddbaReq.BaBufSize = pAd->CommonCfg.BACapability.field.RxBAWinLimit;
1095 AddbaReq.TimeOutValue = 0;
1096 AddbaReq.Token = pBAEntry->Token;
1097 MlmeEnqueue(pAd, ACTION_STATE_MACHINE, MT2_MLME_ADD_BA_CATE, sizeof(MLME_ADDBA_REQ_STRUCT), (PVOID)&AddbaReq);
1098 RT28XX_MLME_HANDLER(pAd);
1099 //DBGPRINT(RT_DEBUG_TRACE,("BA Ori Session Timeout(%d) : Send ADD BA again\n", pBAEntry->Token));
1101 DBGPRINT(RT_DEBUG_TRACE,("BA Ori Session Timeout(%d) to %02x:%02x:%02x:%02x:%02x:%02x Tid:%d Wcid:%d\n"
1103 ,pEntry->Addr[0],pEntry->Addr[1],pEntry->Addr[2]
1104 ,pEntry->Addr[3],pEntry->Addr[4],pEntry->Addr[5]
1105 ,pBAEntry->TID,pEntry->Aid));
1108 RTMPSetTimer(&pBAEntry->ORIBATimer, ORI_BA_SESSION_TIMEOUT);
1112 BATableFreeOriEntry(pAd, pEntry->BAOriWcidArray[pBAEntry->TID]);
1117 ==========================================================================
1119 Retry sending ADDBA Reqest.
1121 IRQL = DISPATCH_LEVEL
1124 p8023Header: if this is already 802.3 format, p8023Header is NULL
1126 Return : TRUE if put into rx reordering buffer, shouldn't indicaterxhere.
1127 FALSE , then continue indicaterx at this moment.
1128 ==========================================================================
1130 VOID BARecSessionIdleTimeout(
1131 IN PVOID SystemSpecific1,
1132 IN PVOID FunctionContext,
1133 IN PVOID SystemSpecific2,
1134 IN PVOID SystemSpecific3)
1137 BA_REC_ENTRY *pBAEntry = (BA_REC_ENTRY *)FunctionContext;
1141 if (pBAEntry == NULL)
1144 if ((pBAEntry->REC_BA_Status == Recipient_Accept))
1146 NdisGetSystemUpTime(&Now32);
1148 if (RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer + REC_BA_SESSION_IDLE_TIMEOUT)))
1150 pAd = pBAEntry->pAdapter;
1151 // flush all pending reordering mpdus
1152 ba_refresh_reordering_mpdus(pAd, pBAEntry);
1153 printk("%ld: REC BA session Timeout\n", Now32);
1159 VOID PeerAddBAReqAction(
1160 IN PRTMP_ADAPTER pAd,
1161 IN MLME_QUEUE_ELEM *Elem)
1168 FRAME_ADDBA_RSP ADDframe;
1169 PUCHAR pOutBuffer = NULL;
1170 NDIS_STATUS NStatus;
1171 PFRAME_ADDBA_REQ pAddreqFrame = NULL;
1175 PMAC_TABLE_ENTRY pMacEntry;
1177 DBGPRINT(RT_DEBUG_TRACE, ("%s ==> (Wcid = %d)\n", __func__, Elem->Wcid));
1179 //hex_dump("AddBAReq", Elem->Msg, Elem->MsgLen);
1181 //ADDBA Request from unknown peer, ignore this.
1182 if (Elem->Wcid >= MAX_LEN_OF_MAC_TABLE)
1185 pMacEntry = &pAd->MacTab.Content[Elem->Wcid];
1186 DBGPRINT(RT_DEBUG_TRACE,("BA - PeerAddBAReqAction----> \n"));
1187 ptemp = (PULONG)Elem->Msg;
1188 //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)));
1190 if (PeerAddBAReqActionSanity(pAd, Elem->Msg, Elem->MsgLen, pAddr))
1193 if ((pAd->CommonCfg.bBADecline == FALSE) && IS_HT_STA(pMacEntry))
1195 pAddreqFrame = (PFRAME_ADDBA_REQ)(&Elem->Msg[0]);
1196 printk("Rcv Wcid(%d) AddBAReq\n", Elem->Wcid);
1197 if (BARecSessionAdd(pAd, &pAd->MacTab.Content[Elem->Wcid], pAddreqFrame))
1200 Status = 38; // more parameters have invalid values
1204 Status = 37; // the request has been declined.
1208 if (pAd->MacTab.Content[Elem->Wcid].ValidAsCLI)
1209 ASSERT(pAd->MacTab.Content[Elem->Wcid].Sst == SST_ASSOC);
1211 pAddreqFrame = (PFRAME_ADDBA_REQ)(&Elem->Msg[0]);
1212 // 2. Always send back ADDBA Response
1213 NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory
1214 if (NStatus != NDIS_STATUS_SUCCESS)
1216 DBGPRINT(RT_DEBUG_TRACE,("ACTION - PeerBAAction() allocate memory failed \n"));
1220 NdisZeroMemory(&ADDframe, sizeof(FRAME_ADDBA_RSP));
1221 // 2-1. Prepare ADDBA Response frame.
1222 #ifdef CONFIG_STA_SUPPORT
1223 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1226 ActHeaderInit(pAd, &ADDframe.Hdr, pAddr, pAd->CurrentAddress, pAd->CommonCfg.Bssid);
1228 ActHeaderInit(pAd, &ADDframe.Hdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pAddr);
1230 #endif // CONFIG_STA_SUPPORT //
1231 ADDframe.Category = CATEGORY_BA;
1232 ADDframe.Action = ADDBA_RESP;
1233 ADDframe.Token = pAddreqFrame->Token;
1234 // What is the Status code?? need to check.
1235 ADDframe.StatusCode = Status;
1236 ADDframe.BaParm.BAPolicy = IMMED_BA;
1237 ADDframe.BaParm.AMSDUSupported = 0;
1238 ADDframe.BaParm.TID = pAddreqFrame->BaParm.TID;
1239 ADDframe.BaParm.BufSize = min(((UCHAR)pAddreqFrame->BaParm.BufSize), (UCHAR)pAd->CommonCfg.BACapability.field.RxBAWinLimit);
1240 if (ADDframe.BaParm.BufSize == 0)
1242 ADDframe.BaParm.BufSize = 64;
1244 ADDframe.TimeOutValue = 0; //pAddreqFrame->TimeOutValue;
1246 *(USHORT *)(&ADDframe.BaParm) = cpu2le16(*(USHORT *)(&ADDframe.BaParm));
1247 ADDframe.StatusCode = cpu2le16(ADDframe.StatusCode);
1248 ADDframe.TimeOutValue = cpu2le16(ADDframe.TimeOutValue);
1250 MakeOutgoingFrame(pOutBuffer, &FrameLen,
1251 sizeof(FRAME_ADDBA_RSP), &ADDframe,
1253 MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
1254 MlmeFreeMemory(pAd, pOutBuffer);
1256 DBGPRINT(RT_DEBUG_TRACE, ("%s(%d): TID(%d), BufSize(%d) <== \n", __func__, Elem->Wcid, ADDframe.BaParm.TID,
1257 ADDframe.BaParm.BufSize));
1261 VOID PeerAddBARspAction(
1262 IN PRTMP_ADAPTER pAd,
1263 IN MLME_QUEUE_ELEM *Elem)
1267 //PUCHAR pOutBuffer = NULL;
1268 PFRAME_ADDBA_RSP pFrame = NULL;
1269 //PBA_ORI_ENTRY pBAEntry;
1271 //ADDBA Response from unknown peer, ignore this.
1272 if (Elem->Wcid >= MAX_LEN_OF_MAC_TABLE)
1275 DBGPRINT(RT_DEBUG_TRACE, ("%s ==> Wcid(%d)\n", __func__, Elem->Wcid));
1277 //hex_dump("PeerAddBARspAction()", Elem->Msg, Elem->MsgLen);
1279 if (PeerAddBARspActionSanity(pAd, Elem->Msg, Elem->MsgLen))
1281 pFrame = (PFRAME_ADDBA_RSP)(&Elem->Msg[0]);
1283 DBGPRINT(RT_DEBUG_TRACE, ("\t\t StatusCode = %d\n", pFrame->StatusCode));
1284 switch (pFrame->StatusCode)
1287 // I want a BAsession with this peer as an originator.
1288 BAOriSessionAdd(pAd, &pAd->MacTab.Content[Elem->Wcid], pFrame);
1291 // check status == USED ???
1292 BAOriSessionTearDown(pAd, Elem->Wcid, pFrame->BaParm.TID, TRUE, FALSE);
1295 // Rcv Decline StatusCode
1296 if ((pFrame->StatusCode == 37)
1297 #ifdef CONFIG_STA_SUPPORT
1298 || ((pAd->OpMode == OPMODE_STA) && STA_TGN_WIFI_ON(pAd) && (pFrame->StatusCode != 0))
1299 #endif // CONFIG_STA_SUPPORT //
1302 pAd->MacTab.Content[Elem->Wcid].BADeclineBitmap |= 1<<pFrame->BaParm.TID;
1307 VOID PeerDelBAAction(
1308 IN PRTMP_ADAPTER pAd,
1309 IN MLME_QUEUE_ELEM *Elem)
1313 //PUCHAR pOutBuffer = NULL;
1314 PFRAME_DELBA_REQ pDelFrame = NULL;
1316 DBGPRINT(RT_DEBUG_TRACE,("%s ==>\n", __func__));
1317 //DELBA Request from unknown peer, ignore this.
1318 if (PeerDelBAActionSanity(pAd, Elem->Wcid, Elem->Msg, Elem->MsgLen))
1320 pDelFrame = (PFRAME_DELBA_REQ)(&Elem->Msg[0]);
1321 if (pDelFrame->DelbaParm.Initiator == ORIGINATOR)
1323 DBGPRINT(RT_DEBUG_TRACE,("BA - PeerDelBAAction----> ORIGINATOR\n"));
1324 BARecSessionTearDown(pAd, Elem->Wcid, pDelFrame->DelbaParm.TID, TRUE);
1328 DBGPRINT(RT_DEBUG_TRACE,("BA - PeerDelBAAction----> RECIPIENT, Reason = %d\n", pDelFrame->ReasonCode));
1329 //hex_dump("DelBA Frame", pDelFrame, Elem->MsgLen);
1330 BAOriSessionTearDown(pAd, Elem->Wcid, pDelFrame->DelbaParm.TID, TRUE, FALSE);
1336 BOOLEAN CntlEnqueueForRecv(
1337 IN PRTMP_ADAPTER pAd,
1340 IN PFRAME_BA_REQ pMsg)
1342 PFRAME_BA_REQ pFrame = pMsg;
1343 //PRTMP_REORDERBUF pBuffer;
1344 //PRTMP_REORDERBUF pDmaBuf;
1345 PBA_REC_ENTRY pBAEntry;
1351 TID = (UCHAR)pFrame->BARControl.TID;
1353 DBGPRINT(RT_DEBUG_TRACE, ("%s(): BAR-Wcid(%ld), Tid (%d)\n", __func__, Wcid, TID));
1354 //hex_dump("BAR", (PCHAR) pFrame, MsgLen);
1355 // Do nothing if the driver is starting halt state.
1356 // This might happen when timer already been fired before cancel timer with mlmehalt
1357 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
1360 // First check the size, it MUST not exceed the mlme queue size
1361 if (MsgLen > MGMT_DMA_BUFFER_SIZE)
1363 DBGPRINT_ERR(("CntlEnqueueForRecv: frame too large, size = %ld \n", MsgLen));
1366 else if (MsgLen != sizeof(FRAME_BA_REQ))
1368 DBGPRINT_ERR(("CntlEnqueueForRecv: BlockAck Request frame length size = %ld incorrect\n", MsgLen));
1371 else if (MsgLen != sizeof(FRAME_BA_REQ))
1373 DBGPRINT_ERR(("CntlEnqueueForRecv: BlockAck Request frame length size = %ld incorrect\n", MsgLen));
1377 if ((Wcid < MAX_LEN_OF_MAC_TABLE) && (TID < 8))
1379 // if this receiving packet is from SA that is in our OriEntry. Since WCID <9 has direct mapping. no need search.
1380 Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID];
1381 pBAEntry = &pAd->BATable.BARecEntry[Idx];
1388 DBGPRINT(RT_DEBUG_TRACE, ("BAR(%ld) : Tid (%d) - %04x:%04x\n", Wcid, TID, pFrame->BAStartingSeq.field.StartSeq, pBAEntry->LastIndSeq ));
1390 if (SEQ_SMALLER(pBAEntry->LastIndSeq, pFrame->BAStartingSeq.field.StartSeq, MAXSEQ))
1392 //printk("BAR Seq = %x, LastIndSeq = %x\n", pFrame->BAStartingSeq.field.StartSeq, pBAEntry->LastIndSeq);
1393 ba_indicate_reordering_mpdus_le_seq(pAd, pBAEntry, pFrame->BAStartingSeq.field.StartSeq);
1394 pBAEntry->LastIndSeq = (pFrame->BAStartingSeq.field.StartSeq == 0) ? MAXSEQ :(pFrame->BAStartingSeq.field.StartSeq -1);
1396 //ba_refresh_reordering_mpdus(pAd, pBAEntry);
1401 Description : Send PSMP Action frame If PSMP mode switches.
1403 VOID SendPSMPAction(
1404 IN PRTMP_ADAPTER pAd,
1408 PUCHAR pOutBuffer = NULL;
1409 NDIS_STATUS NStatus;
1411 FRAME_PSMP_ACTION Frame;
1418 NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory
1419 if (NStatus != NDIS_STATUS_SUCCESS)
1421 DBGPRINT(RT_DEBUG_ERROR,("BA - MlmeADDBAAction() allocate memory failed \n"));
1424 #ifdef CONFIG_STA_SUPPORT
1425 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1426 ActHeaderInit(pAd, &Frame.Hdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pAd->MacTab.Content[Wcid].Addr);
1427 #endif // CONFIG_STA_SUPPORT //
1429 Frame.Category = CATEGORY_HT;
1430 Frame.Action = SMPS_ACTION;
1437 // disable MMPS BBP control register
1438 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &bbpdata);
1439 bbpdata &= ~(0x04); //bit 2
1440 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, bbpdata);
1442 // disable MMPS MAC control register
1443 RTMP_IO_READ32(pAd, 0x1210, &macdata);
1444 macdata &= ~(0x09); //bit 0, 3
1445 RTMP_IO_WRITE32(pAd, 0x1210, macdata);
1454 // enable MMPS BBP control register
1455 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &bbpdata);
1456 bbpdata |= 0x04; //bit 2
1457 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, bbpdata);
1459 // enable MMPS MAC control register
1460 RTMP_IO_READ32(pAd, 0x1210, &macdata);
1461 macdata |= 0x09; //bit 0, 3
1462 RTMP_IO_WRITE32(pAd, 0x1210, macdata);
1471 // enable MMPS BBP control register
1472 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &bbpdata);
1473 bbpdata |= 0x04; //bit 2
1474 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, bbpdata);
1476 // enable MMPS MAC control register
1477 RTMP_IO_READ32(pAd, 0x1210, &macdata);
1478 macdata |= 0x09; //bit 0, 3
1479 RTMP_IO_WRITE32(pAd, 0x1210, macdata);
1485 MakeOutgoingFrame(pOutBuffer, &FrameLen,
1486 sizeof(FRAME_PSMP_ACTION), &Frame,
1488 MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
1489 MlmeFreeMemory(pAd, pOutBuffer);
1490 DBGPRINT(RT_DEBUG_ERROR,("HT - SendPSMPAction( %d ) \n", Frame.Psmp));
1494 #define RADIO_MEASUREMENT_REQUEST_ACTION 0
1496 typedef struct PACKED
1498 UCHAR RegulatoryClass;
1499 UCHAR ChannelNumber;
1500 USHORT RandomInterval;
1501 USHORT MeasurementDuration;
1502 UCHAR MeasurementMode;
1503 UCHAR BSSID[MAC_ADDR_LEN];
1504 UCHAR ReportingCondition;
1506 UCHAR SSIDIE[2]; // 2 byte
1509 typedef struct PACKED
1521 void convert_reordering_packet_to_preAMSDU_or_802_3_packet(
1522 IN PRTMP_ADAPTER pAd,
1524 IN UCHAR FromWhichBSSID)
1526 PNDIS_PACKET pRxPkt;
1527 UCHAR Header802_3[LENGTH_802_3];
1529 // 1. get 802.3 Header
1531 // a. pointer pRxBlk->pData to payload
1532 // b. modify pRxBlk->DataSize
1534 #ifdef CONFIG_STA_SUPPORT
1535 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1536 RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3);
1537 #endif // CONFIG_STA_SUPPORT //
1539 ASSERT(pRxBlk->pRxPacket);
1540 pRxPkt = RTPKT_TO_OSPKT(pRxBlk->pRxPacket);
1542 RTPKT_TO_OSPKT(pRxPkt)->dev = get_netdev_from_bssid(pAd, FromWhichBSSID);
1543 RTPKT_TO_OSPKT(pRxPkt)->data = pRxBlk->pData;
1544 RTPKT_TO_OSPKT(pRxPkt)->len = pRxBlk->DataSize;
1545 RTPKT_TO_OSPKT(pRxPkt)->tail = RTPKT_TO_OSPKT(pRxPkt)->data + RTPKT_TO_OSPKT(pRxPkt)->len;
1548 // copy 802.3 header, if necessary
1550 if (!RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU))
1553 #ifdef CONFIG_STA_SUPPORT
1554 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1557 NdisMoveMemory(skb_push(pRxPkt, LENGTH_802_3), Header802_3, LENGTH_802_3);
1560 #endif // CONFIG_STA_SUPPORT //
1565 #define INDICATE_LEGACY_OR_AMSDU(_pAd, _pRxBlk, _fromWhichBSSID) \
1568 if (RX_BLK_TEST_FLAG(_pRxBlk, fRX_AMSDU)) \
1570 Indicate_AMSDU_Packet(_pAd, _pRxBlk, _fromWhichBSSID); \
1572 else if (RX_BLK_TEST_FLAG(_pRxBlk, fRX_EAP)) \
1574 Indicate_EAPOL_Packet(_pAd, _pRxBlk, _fromWhichBSSID); \
1578 Indicate_Legacy_Packet(_pAd, _pRxBlk, _fromWhichBSSID); \
1584 static VOID ba_enqueue_reordering_packet(
1585 IN PRTMP_ADAPTER pAd,
1586 IN PBA_REC_ENTRY pBAEntry,
1588 IN UCHAR FromWhichBSSID)
1590 struct reordering_mpdu *mpdu_blk;
1591 UINT16 Sequence = (UINT16) pRxBlk->pHeader->Sequence;
1593 mpdu_blk = ba_mpdu_blk_alloc(pAd);
1594 if (mpdu_blk != NULL)
1596 // Write RxD buffer address & allocated buffer length
1597 NdisAcquireSpinLock(&pBAEntry->RxReRingLock);
1599 mpdu_blk->Sequence = Sequence;
1601 mpdu_blk->bAMSDU = RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU);
1603 convert_reordering_packet_to_preAMSDU_or_802_3_packet(pAd, pRxBlk, FromWhichBSSID);
1605 STATS_INC_RX_PACKETS(pAd, FromWhichBSSID);
1608 // it is necessary for reordering packet to record
1609 // which BSS it come from
1611 RTMP_SET_PACKET_IF(pRxBlk->pRxPacket, FromWhichBSSID);
1613 mpdu_blk->pPacket = pRxBlk->pRxPacket;
1615 if (ba_reordering_mpdu_insertsorted(&pBAEntry->list, mpdu_blk) == FALSE)
1617 // had been already within reordering list
1619 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_SUCCESS);
1620 ba_mpdu_blk_free(pAd, mpdu_blk);
1623 ASSERT((0<= pBAEntry->list.qlen) && (pBAEntry->list.qlen <= pBAEntry->BAWinSize));
1624 NdisReleaseSpinLock(&pBAEntry->RxReRingLock);
1628 DBGPRINT(RT_DEBUG_ERROR, ("!!! (%d) Can't allocate reordering mpdu blk\n",
1629 pBAEntry->list.qlen));
1631 * flush all pending reordering mpdus
1632 * and receving mpdu to upper layer
1633 * make tcp/ip to take care reordering mechanism
1635 //ba_refresh_reordering_mpdus(pAd, pBAEntry);
1636 ba_indicate_reordering_mpdus_le_seq(pAd, pBAEntry, Sequence);
1638 pBAEntry->LastIndSeq = Sequence;
1639 INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID);
1645 ==========================================================================
1647 Indicate this packet to upper layer or put it into reordering buffer
1650 pRxBlk : carry necessary packet info 802.11 format
1651 FromWhichBSSID : the packet received from which BSS
1657 the packet queued into reordering buffer need to cover to 802.3 format
1659 ==========================================================================
1662 VOID Indicate_AMPDU_Packet(
1663 IN PRTMP_ADAPTER pAd,
1665 IN UCHAR FromWhichBSSID)
1668 PBA_REC_ENTRY pBAEntry = NULL;
1669 UINT16 Sequence = pRxBlk->pHeader->Sequence;
1671 UCHAR Wcid = pRxBlk->pRxWI->WirelessCliID;
1672 UCHAR TID = pRxBlk->pRxWI->TID;
1675 if (!RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU) && (pRxBlk->DataSize > MAX_RX_PKT_LEN))
1678 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
1682 if (Wcid < MAX_LEN_OF_MAC_TABLE)
1684 Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID];
1687 /* Rec BA Session had been torn down */
1688 INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID);
1691 pBAEntry = &pAd->BATable.BARecEntry[Idx];
1698 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
1704 // update last rx time
1705 NdisGetSystemUpTime(&Now32);
1707 pBAEntry->rcvSeq = Sequence;
1710 ba_flush_reordering_timeout_mpdus(pAd, pBAEntry, Now32);
1711 pBAEntry->LastIndSeqAtTimer = Now32;
1714 // Reset Last Indicate Sequence
1716 if (pBAEntry->LastIndSeq == RESET_RCV_SEQ)
1718 ASSERT((pBAEntry->list.qlen == 0) && (pBAEntry->list.next == NULL));
1720 // reset rcv sequence of BA session
1721 pBAEntry->LastIndSeq = Sequence;
1722 pBAEntry->LastIndSeqAtTimer = Now32;
1723 INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID);
1729 // I. Check if in order.
1731 if (SEQ_STEPONE(Sequence, pBAEntry->LastIndSeq, MAXSEQ))
1735 pBAEntry->LastIndSeq = Sequence;
1736 INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID);
1737 LastIndSeq = ba_indicate_reordering_mpdus_in_order(pAd, pBAEntry, pBAEntry->LastIndSeq);
1738 if (LastIndSeq != RESET_RCV_SEQ)
1740 pBAEntry->LastIndSeq = LastIndSeq;
1742 pBAEntry->LastIndSeqAtTimer = Now32;
1745 // II. Drop Duplicated Packet
1747 else if (Sequence == pBAEntry->LastIndSeq)
1750 // drop and release packet
1751 pBAEntry->nDropPacket++;
1752 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
1755 // III. Drop Old Received Packet
1757 else if (SEQ_SMALLER(Sequence, pBAEntry->LastIndSeq, MAXSEQ))
1760 // drop and release packet
1761 pBAEntry->nDropPacket++;
1762 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
1765 // IV. Receive Sequence within Window Size
1767 else if (SEQ_SMALLER(Sequence, (((pBAEntry->LastIndSeq+pBAEntry->BAWinSize+1)) & MAXSEQ), MAXSEQ))
1769 ba_enqueue_reordering_packet(pAd, pBAEntry, pRxBlk, FromWhichBSSID);
1772 // V. Receive seq surpasses Win(lastseq + nMSDU). So refresh all reorder buffer
1776 LONG WinStartSeq, TmpSeq;
1779 TmpSeq = Sequence - (pBAEntry->BAWinSize) -1;
1782 TmpSeq = (MAXSEQ+1) + TmpSeq;
1784 WinStartSeq = (TmpSeq+1) & MAXSEQ;
1785 ba_indicate_reordering_mpdus_le_seq(pAd, pBAEntry, WinStartSeq);
1786 pBAEntry->LastIndSeq = WinStartSeq; //TmpSeq;
1788 pBAEntry->LastIndSeqAtTimer = Now32;
1790 ba_enqueue_reordering_packet(pAd, pBAEntry, pRxBlk, FromWhichBSSID);
1792 TmpSeq = ba_indicate_reordering_mpdus_in_order(pAd, pBAEntry, pBAEntry->LastIndSeq);
1793 if (TmpSeq != RESET_RCV_SEQ)
1795 pBAEntry->LastIndSeq = TmpSeq;
1800 #endif // DOT11_N_SUPPORT //