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"
30 #define BA_ORI_INIT_SEQ (pEntry->TxSeq[TID]) /*1 // inital sequence number of BA session */
32 #define ORI_SESSION_MAX_RETRY 8
33 #define ORI_BA_SESSION_TIMEOUT (2000) /* ms */
34 #define REC_BA_SESSION_IDLE_TIMEOUT (1000) /* ms */
36 #define REORDERING_PACKET_TIMEOUT ((100 * OS_HZ)/1000) /* system ticks -- 100 ms */
37 #define MAX_REORDERING_PACKET_TIMEOUT ((3000 * OS_HZ)/1000) /* system ticks -- 100 ms */
39 #define RESET_RCV_SEQ (0xFFFF)
41 static void ba_mpdu_blk_free(struct rt_rtmp_adapter *pAd,
42 struct reordering_mpdu *mpdu_blk);
44 struct rt_ba_ori_entry *BATableAllocOriEntry(struct rt_rtmp_adapter *pAd, u16 * Idx);
46 struct rt_ba_rec_entry *BATableAllocRecEntry(struct rt_rtmp_adapter *pAd, u16 * Idx);
48 void BAOriSessionSetupTimeout(void *SystemSpecific1,
49 void *FunctionContext,
50 void *SystemSpecific2,
51 void *SystemSpecific3);
53 void BARecSessionIdleTimeout(void *SystemSpecific1,
54 void *FunctionContext,
55 void *SystemSpecific2,
56 void *SystemSpecific3);
58 BUILD_TIMER_FUNCTION(BAOriSessionSetupTimeout);
59 BUILD_TIMER_FUNCTION(BARecSessionIdleTimeout);
61 #define ANNOUNCE_REORDERING_PACKET(_pAd, _mpdu_blk) \
62 Announce_Reordering_Packet(_pAd, _mpdu_blk);
64 void BA_MaxWinSizeReasign(struct rt_rtmp_adapter *pAd,
65 struct rt_mac_table_entry *pEntryPeer, u8 * pWinSize)
69 if (pAd->MACVersion >= RALINK_2883_VERSION) /* 3*3 */
71 if (pAd->MACVersion >= RALINK_3070_VERSION) {
72 if (pEntryPeer->WepStatus !=
73 Ndis802_11EncryptionDisabled)
74 MaxSize = 7; /* for non-open mode */
79 } else if (pAd->MACVersion >= RALINK_2880E_VERSION) /* 2880 e */
81 if (pEntryPeer->WepStatus != Ndis802_11EncryptionDisabled)
82 MaxSize = 7; /* for non-open mode */
88 DBGPRINT(RT_DEBUG_TRACE, ("ba> Win Size = %d, Max Size = %d\n",
91 if ((*pWinSize) > MaxSize) {
92 DBGPRINT(RT_DEBUG_TRACE,
93 ("ba> reassign max win size from %d to %d\n",
100 void Announce_Reordering_Packet(struct rt_rtmp_adapter *pAd,
101 IN struct reordering_mpdu *mpdu)
105 pPacket = mpdu->pPacket;
109 BA_Reorder_AMSDU_Annnounce(pAd, pPacket);
112 /* pass this 802.3 packet to upper layer or forward this packet to WM directly */
115 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd, pPacket,
116 RTMP_GET_PACKET_IF(pPacket));
121 * Insert a reordering mpdu into sorted linked list by sequence no.
123 BOOLEAN ba_reordering_mpdu_insertsorted(struct reordering_list *list,
124 struct reordering_mpdu *mpdu)
127 struct reordering_mpdu **ppScan = &list->next;
129 while (*ppScan != NULL) {
130 if (SEQ_SMALLER((*ppScan)->Sequence, mpdu->Sequence, MAXSEQ)) {
131 ppScan = &(*ppScan)->next;
132 } else if ((*ppScan)->Sequence == mpdu->Sequence) {
133 /* give up this duplicated frame */
141 mpdu->next = *ppScan;
148 * caller lock critical section if necessary
150 static inline void ba_enqueue(struct reordering_list *list,
151 struct reordering_mpdu *mpdu_blk)
154 mpdu_blk->next = list->next;
155 list->next = mpdu_blk;
159 * caller lock critical section if necessary
161 static inline struct reordering_mpdu *ba_dequeue(struct reordering_list *list)
163 struct reordering_mpdu *mpdu_blk = NULL;
169 mpdu_blk = list->next;
171 list->next = mpdu_blk->next;
172 mpdu_blk->next = NULL;
178 static inline struct reordering_mpdu *ba_reordering_mpdu_dequeue(struct
182 return (ba_dequeue(list));
185 static inline struct reordering_mpdu *ba_reordering_mpdu_probe(struct
195 * free all resource for reordering mechanism
197 void ba_reordering_resource_release(struct rt_rtmp_adapter *pAd)
199 struct rt_ba_table *Tab;
200 struct rt_ba_rec_entry *pBAEntry;
201 struct reordering_mpdu *mpdu_blk;
206 /* I. release all pending reordering packet */
207 NdisAcquireSpinLock(&pAd->BATabLock);
208 for (i = 0; i < MAX_LEN_OF_BA_REC_TABLE; i++) {
209 pBAEntry = &Tab->BARecEntry[i];
210 if (pBAEntry->REC_BA_Status != Recipient_NONE) {
212 ba_reordering_mpdu_dequeue(&pBAEntry->list))) {
213 ASSERT(mpdu_blk->pPacket);
214 RELEASE_NDIS_PACKET(pAd, mpdu_blk->pPacket,
215 NDIS_STATUS_FAILURE);
216 ba_mpdu_blk_free(pAd, mpdu_blk);
220 NdisReleaseSpinLock(&pAd->BATabLock);
222 ASSERT(pBAEntry->list.qlen == 0);
223 /* II. free memory of reordering mpdu table */
224 NdisAcquireSpinLock(&pAd->mpdu_blk_pool.lock);
225 os_free_mem(pAd, pAd->mpdu_blk_pool.mem);
226 NdisReleaseSpinLock(&pAd->mpdu_blk_pool.lock);
230 * Allocate all resource for reordering mechanism
232 BOOLEAN ba_reordering_resource_init(struct rt_rtmp_adapter *pAd, int num)
236 struct reordering_mpdu *mpdu_blk;
237 struct reordering_list *freelist;
239 /* allocate spinlock */
240 NdisAllocateSpinLock(&pAd->mpdu_blk_pool.lock);
242 /* initialize freelist */
243 freelist = &pAd->mpdu_blk_pool.freelist;
244 freelist->next = NULL;
247 DBGPRINT(RT_DEBUG_TRACE,
248 ("Allocate %d memory for BA reordering\n",
249 (u32)(num * sizeof(struct reordering_mpdu))));
251 /* allocate number of mpdu_blk memory */
252 os_alloc_mem(pAd, (u8 **) & mem,
253 (num * sizeof(struct reordering_mpdu)));
255 pAd->mpdu_blk_pool.mem = mem;
258 DBGPRINT(RT_DEBUG_ERROR,
259 ("Can't Allocate Memory for BA Reordering\n"));
263 /* build mpdu_blk free list */
264 for (i = 0; i < num; i++) {
266 mpdu_blk = (struct reordering_mpdu *)mem;
267 /* initial mpdu_blk */
268 NdisZeroMemory(mpdu_blk, sizeof(struct reordering_mpdu));
270 mem += sizeof(struct reordering_mpdu);
271 /* insert mpdu_blk into freelist */
272 ba_enqueue(freelist, mpdu_blk);
278 /*static int blk_count=0; // sample take off, no use */
280 static struct reordering_mpdu *ba_mpdu_blk_alloc(struct rt_rtmp_adapter *pAd)
282 struct reordering_mpdu *mpdu_blk;
284 NdisAcquireSpinLock(&pAd->mpdu_blk_pool.lock);
285 mpdu_blk = ba_dequeue(&pAd->mpdu_blk_pool.freelist);
289 NdisZeroMemory(mpdu_blk, sizeof(struct reordering_mpdu));
291 NdisReleaseSpinLock(&pAd->mpdu_blk_pool.lock);
295 static void ba_mpdu_blk_free(struct rt_rtmp_adapter *pAd,
296 struct reordering_mpdu *mpdu_blk)
300 NdisAcquireSpinLock(&pAd->mpdu_blk_pool.lock);
302 ba_enqueue(&pAd->mpdu_blk_pool.freelist, mpdu_blk);
303 NdisReleaseSpinLock(&pAd->mpdu_blk_pool.lock);
306 static u16 ba_indicate_reordering_mpdus_in_order(struct rt_rtmp_adapter *pAd,
307 struct rt_ba_rec_entry *pBAEntry,
310 struct reordering_mpdu *mpdu_blk;
311 u16 LastIndSeq = RESET_RCV_SEQ;
313 NdisAcquireSpinLock(&pBAEntry->RxReRingLock);
315 while ((mpdu_blk = ba_reordering_mpdu_probe(&pBAEntry->list))) {
316 /* find in-order frame */
317 if (!SEQ_STEPONE(mpdu_blk->Sequence, StartSeq, MAXSEQ)) {
320 /* dequeue in-order frame from reodering list */
321 mpdu_blk = ba_reordering_mpdu_dequeue(&pBAEntry->list);
322 /* pass this frame up */
323 ANNOUNCE_REORDERING_PACKET(pAd, mpdu_blk);
324 /* move to next sequence */
325 StartSeq = mpdu_blk->Sequence;
326 LastIndSeq = StartSeq;
328 ba_mpdu_blk_free(pAd, mpdu_blk);
331 NdisReleaseSpinLock(&pBAEntry->RxReRingLock);
333 /* update last indicated sequence */
337 static void ba_indicate_reordering_mpdus_le_seq(struct rt_rtmp_adapter *pAd,
338 struct rt_ba_rec_entry *pBAEntry,
341 struct reordering_mpdu *mpdu_blk;
343 NdisAcquireSpinLock(&pBAEntry->RxReRingLock);
344 while ((mpdu_blk = ba_reordering_mpdu_probe(&pBAEntry->list))) {
345 /* find in-order frame */
346 if ((mpdu_blk->Sequence == Sequence)
347 || SEQ_SMALLER(mpdu_blk->Sequence, Sequence, 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);
353 ba_mpdu_blk_free(pAd, mpdu_blk);
358 NdisReleaseSpinLock(&pBAEntry->RxReRingLock);
361 static void ba_refresh_reordering_mpdus(struct rt_rtmp_adapter *pAd,
362 struct rt_ba_rec_entry *pBAEntry)
364 struct reordering_mpdu *mpdu_blk;
366 NdisAcquireSpinLock(&pBAEntry->RxReRingLock);
368 /* dequeue in-order frame from reodering list */
369 while ((mpdu_blk = ba_reordering_mpdu_dequeue(&pBAEntry->list))) {
370 /* pass this frame up */
371 ANNOUNCE_REORDERING_PACKET(pAd, mpdu_blk);
373 pBAEntry->LastIndSeq = mpdu_blk->Sequence;
374 ba_mpdu_blk_free(pAd, mpdu_blk);
376 /* update last indicated sequence */
378 ASSERT(pBAEntry->list.qlen == 0);
379 pBAEntry->LastIndSeq = RESET_RCV_SEQ;
380 NdisReleaseSpinLock(&pBAEntry->RxReRingLock);
384 void ba_flush_reordering_timeout_mpdus(struct rt_rtmp_adapter *pAd,
385 struct rt_ba_rec_entry *pBAEntry,
390 /* if ((RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+REORDERING_PACKET_TIMEOUT)) && */
391 /* (pBAEntry->list.qlen > ((pBAEntry->BAWinSize*7)/8))) //|| */
392 /* (RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+(10*REORDERING_PACKET_TIMEOUT))) && */
393 /* (pBAEntry->list.qlen > (pBAEntry->BAWinSize/8))) */
395 ((unsigned long)Now32,
396 (unsigned long)(pBAEntry->LastIndSeqAtTimer +
397 (MAX_REORDERING_PACKET_TIMEOUT / 6)))
398 && (pBAEntry->list.qlen > 1)
400 DBGPRINT(RT_DEBUG_TRACE,
401 ("timeout[%d] (%08lx-%08lx = %d > %d): %x, flush all!\n ",
402 pBAEntry->list.qlen, Now32,
403 (pBAEntry->LastIndSeqAtTimer),
405 (long)(pBAEntry->LastIndSeqAtTimer)),
406 MAX_REORDERING_PACKET_TIMEOUT, pBAEntry->LastIndSeq));
407 ba_refresh_reordering_mpdus(pAd, pBAEntry);
408 pBAEntry->LastIndSeqAtTimer = Now32;
411 ((unsigned long)Now32,
412 (unsigned long)(pBAEntry->LastIndSeqAtTimer +
413 (REORDERING_PACKET_TIMEOUT)))
414 && (pBAEntry->list.qlen > 0)
417 /* force LastIndSeq to shift to LastIndSeq+1 */
419 Sequence = (pBAEntry->LastIndSeq + 1) & MAXSEQ;
420 ba_indicate_reordering_mpdus_le_seq(pAd, pBAEntry, Sequence);
421 pBAEntry->LastIndSeqAtTimer = Now32;
422 pBAEntry->LastIndSeq = Sequence;
424 /* indicate in-order mpdus */
427 ba_indicate_reordering_mpdus_in_order(pAd, pBAEntry,
429 if (Sequence != RESET_RCV_SEQ) {
430 pBAEntry->LastIndSeq = Sequence;
433 DBGPRINT(RT_DEBUG_OFF,
434 ("%x, flush one!\n", pBAEntry->LastIndSeq));
440 * generate ADDBA request to
441 * set up BA agreement
443 void BAOriSessionSetUp(struct rt_rtmp_adapter *pAd,
444 struct rt_mac_table_entry *pEntry,
447 unsigned long DelayTime, IN BOOLEAN isForced)
449 /*struct rt_mlme_addba_req AddbaReq; */
450 struct rt_ba_ori_entry *pBAEntry = NULL;
454 if ((pAd->CommonCfg.BACapability.field.AutoBA != TRUE)
455 && (isForced == FALSE))
458 /* if this entry is limited to use legacy tx mode, it doesn't generate BA. */
459 if (RTMPStaFixedTxMode(pAd, pEntry) != FIXED_TXMODE_HT)
462 if ((pEntry->BADeclineBitmap & (1 << TID)) && (isForced == FALSE)) {
463 /* try again after 3 secs */
465 /* DBGPRINT(RT_DEBUG_TRACE, ("DeCline BA from Peer\n")); */
469 Idx = pEntry->BAOriWcidArray[TID];
471 /* allocate a BA session */
472 pBAEntry = BATableAllocOriEntry(pAd, &Idx);
473 if (pBAEntry == NULL) {
474 DBGPRINT(RT_DEBUG_TRACE,
475 ("ADDBA - MlmeADDBAAction() allocate BA session failed \n"));
479 pBAEntry = &pAd->BATable.BAOriEntry[Idx];
482 if (pBAEntry->ORI_BA_Status >= Originator_WaitRes) {
486 pEntry->BAOriWcidArray[TID] = Idx;
488 /* Initialize BA session */
489 pBAEntry->ORI_BA_Status = Originator_WaitRes;
490 pBAEntry->Wcid = pEntry->Aid;
491 pBAEntry->BAWinSize = pAd->CommonCfg.BACapability.field.RxBAWinLimit;
492 pBAEntry->Sequence = BA_ORI_INIT_SEQ;
493 pBAEntry->Token = 1; /* (2008-01-21) Jan Lee recommends it - this token can't be 0 */
495 pBAEntry->TimeOutValue = TimeOut;
496 pBAEntry->pAdapter = pAd;
498 if (!(pEntry->TXBAbitmap & (1 << TID))) {
499 RTMPInitTimer(pAd, &pBAEntry->ORIBATimer,
500 GET_TIMER_FUNCTION(BAOriSessionSetupTimeout),
503 RTMPCancelTimer(&pBAEntry->ORIBATimer, &Cancelled);
505 /* set timer to send ADDBA request */
506 RTMPSetTimer(&pBAEntry->ORIBATimer, DelayTime);
509 void BAOriSessionAdd(struct rt_rtmp_adapter *pAd,
510 struct rt_mac_table_entry *pEntry, struct rt_frame_addba_rsp * pFrame)
512 struct rt_ba_ori_entry *pBAEntry = NULL;
516 u8 *pOutBuffer2 = NULL;
518 unsigned long FrameLen;
519 struct rt_frame_bar FrameBar;
521 TID = pFrame->BaParm.TID;
522 Idx = pEntry->BAOriWcidArray[TID];
523 pBAEntry = &pAd->BATable.BAOriEntry[Idx];
525 /* Start fill in parameters. */
526 if ((Idx != 0) && (pBAEntry->TID == TID)
527 && (pBAEntry->ORI_BA_Status == Originator_WaitRes)) {
528 pBAEntry->BAWinSize =
529 min(pBAEntry->BAWinSize, ((u8)pFrame->BaParm.BufSize));
530 BA_MaxWinSizeReasign(pAd, pEntry, &pBAEntry->BAWinSize);
532 pBAEntry->TimeOutValue = pFrame->TimeOutValue;
533 pBAEntry->ORI_BA_Status = Originator_Done;
534 pAd->BATable.numDoneOriginator++;
536 /* reset sequence number */
537 pBAEntry->Sequence = BA_ORI_INIT_SEQ;
538 /* Set Bitmap flag. */
539 pEntry->TXBAbitmap |= (1 << TID);
540 RTMPCancelTimer(&pBAEntry->ORIBATimer, &Cancelled);
542 pBAEntry->ORIBATimer.TimerValue = 0; /*pFrame->TimeOutValue; */
544 DBGPRINT(RT_DEBUG_TRACE,
545 ("%s : TXBAbitmap = %x, BAWinSize = %d, TimeOut = %ld\n",
546 __func__, pEntry->TXBAbitmap, pBAEntry->BAWinSize,
547 pBAEntry->ORIBATimer.TimerValue));
550 NStatus = MlmeAllocateMemory(pAd, &pOutBuffer2); /*Get an unused nonpaged memory */
551 if (NStatus != NDIS_STATUS_SUCCESS) {
552 DBGPRINT(RT_DEBUG_TRACE,
553 ("BA - BAOriSessionAdd() allocate memory failed \n"));
557 BarHeaderInit(pAd, &FrameBar,
558 pAd->MacTab.Content[pBAEntry->Wcid].Addr,
559 pAd->CurrentAddress);
561 FrameBar.StartingSeq.field.FragNum = 0; /* make sure sequence not clear in DEL function. */
562 FrameBar.StartingSeq.field.StartSeq = pBAEntry->Sequence; /* make sure sequence not clear in DEL funciton. */
563 FrameBar.BarControl.TID = pBAEntry->TID; /* make sure sequence not clear in DEL funciton. */
564 MakeOutgoingFrame(pOutBuffer2, &FrameLen,
565 sizeof(struct rt_frame_bar), &FrameBar, END_OF_ARGS);
566 MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer2, FrameLen);
567 MlmeFreeMemory(pAd, pOutBuffer2);
569 if (pBAEntry->ORIBATimer.TimerValue)
570 RTMPSetTimer(&pBAEntry->ORIBATimer, pBAEntry->ORIBATimer.TimerValue); /* in mSec */
574 BOOLEAN BARecSessionAdd(struct rt_rtmp_adapter *pAd,
575 struct rt_mac_table_entry *pEntry, struct rt_frame_addba_req * pFrame)
577 struct rt_ba_rec_entry *pBAEntry = NULL;
578 BOOLEAN Status = TRUE;
589 TID = pFrame->BaParm.TID;
592 min(((u8)pFrame->BaParm.BufSize),
593 (u8)pAd->CommonCfg.BACapability.field.RxBAWinLimit);
596 if (BAWinSize == 0) {
600 Idx = pEntry->BARecWcidArray[TID];
603 pBAEntry = BATableAllocRecEntry(pAd, &Idx);
605 pBAEntry = &pAd->BATable.BARecEntry[Idx];
606 /* flush all pending reordering mpdus */
607 ba_refresh_reordering_mpdus(pAd, pBAEntry);
610 DBGPRINT(RT_DEBUG_TRACE,
611 ("%s(%ld): Idx = %d, BAWinSize(req %d) = %d\n", __func__,
612 pAd->BATable.numAsRecipient, Idx, pFrame->BaParm.BufSize,
615 /* Start fill in parameters. */
616 if (pBAEntry != NULL) {
617 ASSERT(pBAEntry->list.qlen == 0);
619 pBAEntry->REC_BA_Status = Recipient_HandleRes;
620 pBAEntry->BAWinSize = BAWinSize;
621 pBAEntry->Wcid = pEntry->Aid;
623 pBAEntry->TimeOutValue = pFrame->TimeOutValue;
624 pBAEntry->REC_BA_Status = Recipient_Accept;
625 /* initial sequence number */
626 pBAEntry->LastIndSeq = RESET_RCV_SEQ; /*pFrame->BaStartSeq.field.StartSeq; */
628 DBGPRINT(RT_DEBUG_OFF,
629 ("Start Seq = %08x\n",
630 pFrame->BaStartSeq.field.StartSeq));
632 if (pEntry->RXBAbitmap & (1 << TID)) {
633 RTMPCancelTimer(&pBAEntry->RECBATimer, &Cancelled);
635 RTMPInitTimer(pAd, &pBAEntry->RECBATimer,
637 (BARecSessionIdleTimeout), pBAEntry,
641 /* Set Bitmap flag. */
642 pEntry->RXBAbitmap |= (1 << TID);
643 pEntry->BARecWcidArray[TID] = Idx;
645 pEntry->BADeclineBitmap &= ~(1 << TID);
647 /* Set BA session mask in WCID table. */
648 RTMP_ADD_BA_SESSION_TO_ASIC(pAd, pEntry->Aid, TID);
650 DBGPRINT(RT_DEBUG_TRACE,
651 ("MACEntry[%d]RXBAbitmap = 0x%x. BARecWcidArray=%d\n",
652 pEntry->Aid, pEntry->RXBAbitmap,
653 pEntry->BARecWcidArray[TID]));
656 DBGPRINT(RT_DEBUG_TRACE,
657 ("Can't Accept ADDBA for %02x:%02x:%02x:%02x:%02x:%02x TID = %d\n",
658 PRINT_MAC(pEntry->Addr), TID));
663 struct rt_ba_rec_entry *BATableAllocRecEntry(struct rt_rtmp_adapter *pAd, u16 * Idx)
666 struct rt_ba_rec_entry *pBAEntry = NULL;
668 NdisAcquireSpinLock(&pAd->BATabLock);
670 if (pAd->BATable.numAsRecipient >= MAX_BARECI_SESSION) {
671 DBGPRINT(RT_DEBUG_OFF, ("BA Recipeint Session (%ld) > %d\n",
672 pAd->BATable.numAsRecipient,
673 MAX_BARECI_SESSION));
676 /* reserve idx 0 to identify BAWcidArray[TID] as empty */
677 for (i = 1; i < MAX_LEN_OF_BA_REC_TABLE; i++) {
678 pBAEntry = &pAd->BATable.BARecEntry[i];
679 if ((pBAEntry->REC_BA_Status == Recipient_NONE)) {
681 pAd->BATable.numAsRecipient++;
682 pBAEntry->REC_BA_Status = Recipient_USED;
689 NdisReleaseSpinLock(&pAd->BATabLock);
693 struct rt_ba_ori_entry *BATableAllocOriEntry(struct rt_rtmp_adapter *pAd, u16 * Idx)
696 struct rt_ba_ori_entry *pBAEntry = NULL;
698 NdisAcquireSpinLock(&pAd->BATabLock);
700 if (pAd->BATable.numAsOriginator >= (MAX_LEN_OF_BA_ORI_TABLE)) {
703 /* reserve idx 0 to identify BAWcidArray[TID] as empty */
704 for (i = 1; i < MAX_LEN_OF_BA_ORI_TABLE; i++) {
705 pBAEntry = &pAd->BATable.BAOriEntry[i];
706 if ((pBAEntry->ORI_BA_Status == Originator_NONE)) {
708 pAd->BATable.numAsOriginator++;
709 pBAEntry->ORI_BA_Status = Originator_USED;
710 pBAEntry->pAdapter = pAd;
717 NdisReleaseSpinLock(&pAd->BATabLock);
721 void BATableFreeOriEntry(struct rt_rtmp_adapter *pAd, unsigned long Idx)
723 struct rt_ba_ori_entry *pBAEntry = NULL;
724 struct rt_mac_table_entry *pEntry;
726 if ((Idx == 0) || (Idx >= MAX_LEN_OF_BA_ORI_TABLE))
729 pBAEntry = &pAd->BATable.BAOriEntry[Idx];
731 if (pBAEntry->ORI_BA_Status != Originator_NONE) {
732 pEntry = &pAd->MacTab.Content[pBAEntry->Wcid];
733 pEntry->BAOriWcidArray[pBAEntry->TID] = 0;
735 NdisAcquireSpinLock(&pAd->BATabLock);
736 if (pBAEntry->ORI_BA_Status == Originator_Done) {
737 pAd->BATable.numDoneOriginator -= 1;
738 pEntry->TXBAbitmap &= (~(1 << (pBAEntry->TID)));
739 DBGPRINT(RT_DEBUG_TRACE,
740 ("BATableFreeOriEntry numAsOriginator= %ld\n",
741 pAd->BATable.numAsRecipient));
742 /* Erase Bitmap flag. */
745 ASSERT(pAd->BATable.numAsOriginator != 0);
747 pAd->BATable.numAsOriginator -= 1;
749 pBAEntry->ORI_BA_Status = Originator_NONE;
751 NdisReleaseSpinLock(&pAd->BATabLock);
755 void BATableFreeRecEntry(struct rt_rtmp_adapter *pAd, unsigned long Idx)
757 struct rt_ba_rec_entry *pBAEntry = NULL;
758 struct rt_mac_table_entry *pEntry;
760 if ((Idx == 0) || (Idx >= MAX_LEN_OF_BA_REC_TABLE))
763 pBAEntry = &pAd->BATable.BARecEntry[Idx];
765 if (pBAEntry->REC_BA_Status != Recipient_NONE) {
766 pEntry = &pAd->MacTab.Content[pBAEntry->Wcid];
767 pEntry->BARecWcidArray[pBAEntry->TID] = 0;
769 NdisAcquireSpinLock(&pAd->BATabLock);
771 ASSERT(pAd->BATable.numAsRecipient != 0);
773 pAd->BATable.numAsRecipient -= 1;
775 pBAEntry->REC_BA_Status = Recipient_NONE;
776 NdisReleaseSpinLock(&pAd->BATabLock);
780 void BAOriSessionTearDown(struct rt_rtmp_adapter *pAd,
783 IN BOOLEAN bPassive, IN BOOLEAN bForceSend)
785 unsigned long Idx = 0;
786 struct rt_ba_ori_entry *pBAEntry;
789 if (Wcid >= MAX_LEN_OF_MAC_TABLE) {
793 /* Locate corresponding BA Originator Entry in BA Table with the (pAddr,TID). */
795 Idx = pAd->MacTab.Content[Wcid].BAOriWcidArray[TID];
796 if ((Idx == 0) || (Idx >= MAX_LEN_OF_BA_ORI_TABLE)) {
797 if (bForceSend == TRUE) {
798 /* force send specified TID DelBA */
799 struct rt_mlme_delba_req DelbaReq;
800 struct rt_mlme_queue_elem *Elem =
801 (struct rt_mlme_queue_elem *)kmalloc(sizeof(struct rt_mlme_queue_elem),
804 NdisZeroMemory(&DelbaReq, sizeof(DelbaReq));
805 NdisZeroMemory(Elem, sizeof(struct rt_mlme_queue_elem));
807 COPY_MAC_ADDR(DelbaReq.Addr,
808 pAd->MacTab.Content[Wcid].Addr);
809 DelbaReq.Wcid = Wcid;
811 DelbaReq.Initiator = ORIGINATOR;
812 Elem->MsgLen = sizeof(DelbaReq);
813 NdisMoveMemory(Elem->Msg, &DelbaReq,
815 MlmeDELBAAction(pAd, Elem);
818 DBGPRINT(RT_DEBUG_ERROR,
819 ("%s(bForceSend):alloc memory failed!\n",
827 DBGPRINT(RT_DEBUG_TRACE,
828 ("%s===>Wcid=%d.TID=%d \n", __func__, Wcid, TID));
830 pBAEntry = &pAd->BATable.BAOriEntry[Idx];
831 DBGPRINT(RT_DEBUG_TRACE,
832 ("\t===>Idx = %ld, Wcid=%d.TID=%d, ORI_BA_Status = %d \n", Idx,
833 Wcid, TID, pBAEntry->ORI_BA_Status));
835 /* Prepare DelBA action frame and send to the peer. */
837 if ((bPassive == FALSE) && (TID == pBAEntry->TID)
838 && (pBAEntry->ORI_BA_Status == Originator_Done)) {
839 struct rt_mlme_delba_req DelbaReq;
840 struct rt_mlme_queue_elem *Elem =
841 (struct rt_mlme_queue_elem *)kmalloc(sizeof(struct rt_mlme_queue_elem),
844 NdisZeroMemory(&DelbaReq, sizeof(DelbaReq));
845 NdisZeroMemory(Elem, sizeof(struct rt_mlme_queue_elem));
847 COPY_MAC_ADDR(DelbaReq.Addr,
848 pAd->MacTab.Content[Wcid].Addr);
849 DelbaReq.Wcid = Wcid;
850 DelbaReq.TID = pBAEntry->TID;
851 DelbaReq.Initiator = ORIGINATOR;
852 Elem->MsgLen = sizeof(DelbaReq);
853 NdisMoveMemory(Elem->Msg, &DelbaReq, sizeof(DelbaReq));
854 MlmeDELBAAction(pAd, Elem);
857 DBGPRINT(RT_DEBUG_ERROR,
858 ("%s():alloc memory failed!\n", __func__));
862 RTMPCancelTimer(&pBAEntry->ORIBATimer, &Cancelled);
863 BATableFreeOriEntry(pAd, Idx);
866 /*BAOriSessionSetUp(pAd, &pAd->MacTab.Content[Wcid], TID, 0, 10000, TRUE); */
870 void BARecSessionTearDown(struct rt_rtmp_adapter *pAd,
871 u8 Wcid, u8 TID, IN BOOLEAN bPassive)
873 unsigned long Idx = 0;
874 struct rt_ba_rec_entry *pBAEntry;
876 if (Wcid >= MAX_LEN_OF_MAC_TABLE) {
880 /* Locate corresponding BA Originator Entry in BA Table with the (pAddr,TID). */
882 Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID];
886 DBGPRINT(RT_DEBUG_TRACE,
887 ("%s===>Wcid=%d.TID=%d \n", __func__, Wcid, TID));
889 pBAEntry = &pAd->BATable.BARecEntry[Idx];
890 DBGPRINT(RT_DEBUG_TRACE,
891 ("\t===>Idx = %ld, Wcid=%d.TID=%d, REC_BA_Status = %d \n", Idx,
892 Wcid, TID, pBAEntry->REC_BA_Status));
894 /* Prepare DelBA action frame and send to the peer. */
896 if ((TID == pBAEntry->TID)
897 && (pBAEntry->REC_BA_Status == Recipient_Accept)) {
898 struct rt_mlme_delba_req DelbaReq;
900 /*unsigned long offset; */
903 RTMPCancelTimer(&pBAEntry->RECBATimer, &Cancelled);
906 /* 1. Send DELBA Action Frame */
908 if (bPassive == FALSE) {
909 struct rt_mlme_queue_elem *Elem =
910 (struct rt_mlme_queue_elem *)kmalloc(sizeof(struct rt_mlme_queue_elem),
913 NdisZeroMemory(&DelbaReq, sizeof(DelbaReq));
914 NdisZeroMemory(Elem, sizeof(struct rt_mlme_queue_elem));
916 COPY_MAC_ADDR(DelbaReq.Addr,
917 pAd->MacTab.Content[Wcid].Addr);
918 DelbaReq.Wcid = Wcid;
920 DelbaReq.Initiator = RECIPIENT;
921 Elem->MsgLen = sizeof(DelbaReq);
922 NdisMoveMemory(Elem->Msg, &DelbaReq,
924 MlmeDELBAAction(pAd, Elem);
927 DBGPRINT(RT_DEBUG_ERROR,
928 ("%s():alloc memory failed!\n",
935 /* 2. Free resource of BA session */
937 /* flush all pending reordering mpdus */
938 ba_refresh_reordering_mpdus(pAd, pBAEntry);
940 NdisAcquireSpinLock(&pAd->BATabLock);
942 /* Erase Bitmap flag. */
943 pBAEntry->LastIndSeq = RESET_RCV_SEQ;
944 pBAEntry->BAWinSize = 0;
945 /* Erase Bitmap flag at software mactable */
946 pAd->MacTab.Content[Wcid].RXBAbitmap &=
947 (~(1 << (pBAEntry->TID)));
948 pAd->MacTab.Content[Wcid].BARecWcidArray[TID] = 0;
950 RTMP_DEL_BA_SESSION_FROM_ASIC(pAd, Wcid, TID);
952 NdisReleaseSpinLock(&pAd->BATabLock);
956 BATableFreeRecEntry(pAd, Idx);
959 void BASessionTearDownALL(struct rt_rtmp_adapter *pAd, u8 Wcid)
963 for (i = 0; i < NUM_OF_TID; i++) {
964 BAOriSessionTearDown(pAd, Wcid, i, FALSE, FALSE);
965 BARecSessionTearDown(pAd, Wcid, i, FALSE);
970 ==========================================================================
972 Retry sending ADDBA Reqest.
974 IRQL = DISPATCH_LEVEL
977 p8023Header: if this is already 802.3 format, p8023Header is NULL
979 Return : TRUE if put into rx reordering buffer, shouldn't indicaterxhere.
980 FALSE , then continue indicaterx at this moment.
981 ==========================================================================
983 void BAOriSessionSetupTimeout(void *SystemSpecific1,
984 void *FunctionContext,
985 void *SystemSpecific2,
986 void *SystemSpecific3)
988 struct rt_ba_ori_entry *pBAEntry = (struct rt_ba_ori_entry *)FunctionContext;
989 struct rt_mac_table_entry *pEntry;
990 struct rt_rtmp_adapter *pAd;
992 if (pBAEntry == NULL)
995 pAd = pBAEntry->pAdapter;
998 /* Do nothing if monitor mode is on */
1003 pEntry = &pAd->MacTab.Content[pBAEntry->Wcid];
1005 if ((pBAEntry->ORI_BA_Status == Originator_WaitRes)
1006 && (pBAEntry->Token < ORI_SESSION_MAX_RETRY)) {
1007 struct rt_mlme_addba_req AddbaReq;
1009 NdisZeroMemory(&AddbaReq, sizeof(AddbaReq));
1010 COPY_MAC_ADDR(AddbaReq.pAddr, pEntry->Addr);
1011 AddbaReq.Wcid = (u8)(pEntry->Aid);
1012 AddbaReq.TID = pBAEntry->TID;
1013 AddbaReq.BaBufSize =
1014 pAd->CommonCfg.BACapability.field.RxBAWinLimit;
1015 AddbaReq.TimeOutValue = 0;
1016 AddbaReq.Token = pBAEntry->Token;
1017 MlmeEnqueue(pAd, ACTION_STATE_MACHINE, MT2_MLME_ADD_BA_CATE,
1018 sizeof(struct rt_mlme_addba_req), (void *)& AddbaReq);
1019 RTMP_MLME_HANDLER(pAd);
1020 DBGPRINT(RT_DEBUG_TRACE,
1021 ("BA Ori Session Timeout(%d) : Send ADD BA again\n",
1025 RTMPSetTimer(&pBAEntry->ORIBATimer, ORI_BA_SESSION_TIMEOUT);
1027 BATableFreeOriEntry(pAd, pEntry->BAOriWcidArray[pBAEntry->TID]);
1032 ==========================================================================
1034 Retry sending ADDBA Reqest.
1036 IRQL = DISPATCH_LEVEL
1039 p8023Header: if this is already 802.3 format, p8023Header is NULL
1041 Return : TRUE if put into rx reordering buffer, shouldn't indicaterxhere.
1042 FALSE , then continue indicaterx at this moment.
1043 ==========================================================================
1045 void BARecSessionIdleTimeout(void *SystemSpecific1,
1046 void *FunctionContext,
1047 void *SystemSpecific2, void *SystemSpecific3)
1050 struct rt_ba_rec_entry *pBAEntry = (struct rt_ba_rec_entry *)FunctionContext;
1051 struct rt_rtmp_adapter *pAd;
1052 unsigned long Now32;
1054 if (pBAEntry == NULL)
1057 if ((pBAEntry->REC_BA_Status == Recipient_Accept)) {
1058 NdisGetSystemUpTime(&Now32);
1061 ((unsigned long)Now32,
1062 (unsigned long)(pBAEntry->LastIndSeqAtTimer +
1063 REC_BA_SESSION_IDLE_TIMEOUT))) {
1064 pAd = pBAEntry->pAdapter;
1065 /* flush all pending reordering mpdus */
1066 ba_refresh_reordering_mpdus(pAd, pBAEntry);
1067 DBGPRINT(RT_DEBUG_OFF,
1068 ("%ld: REC BA session Timeout\n", Now32));
1073 void PeerAddBAReqAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem)
1076 /*unsigned long Idx; */
1079 struct rt_frame_addba_rsp ADDframe;
1080 u8 *pOutBuffer = NULL;
1082 struct rt_frame_addba_req * pAddreqFrame = NULL;
1084 unsigned long FrameLen;
1085 unsigned long *ptemp;
1086 struct rt_mac_table_entry *pMacEntry;
1088 DBGPRINT(RT_DEBUG_TRACE,
1089 ("%s ==> (Wcid = %d)\n", __func__, Elem->Wcid));
1091 /*hex_dump("AddBAReq", Elem->Msg, Elem->MsgLen); */
1093 /*ADDBA Request from unknown peer, ignore this. */
1094 if (Elem->Wcid >= MAX_LEN_OF_MAC_TABLE)
1097 pMacEntry = &pAd->MacTab.Content[Elem->Wcid];
1098 DBGPRINT(RT_DEBUG_TRACE, ("BA - PeerAddBAReqAction----> \n"));
1099 ptemp = (unsigned long *)Elem->Msg;
1100 /*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))); */
1102 if (PeerAddBAReqActionSanity(pAd, Elem->Msg, Elem->MsgLen, pAddr)) {
1104 if ((pAd->CommonCfg.bBADecline == FALSE)
1105 && IS_HT_STA(pMacEntry)) {
1106 pAddreqFrame = (struct rt_frame_addba_req *) (&Elem->Msg[0]);
1107 DBGPRINT(RT_DEBUG_OFF,
1108 ("Rcv Wcid(%d) AddBAReq\n", Elem->Wcid));
1110 (pAd, &pAd->MacTab.Content[Elem->Wcid],
1114 Status = 38; /* more parameters have invalid values */
1116 Status = 37; /* the request has been declined. */
1120 if (pAd->MacTab.Content[Elem->Wcid].ValidAsCLI)
1121 ASSERT(pAd->MacTab.Content[Elem->Wcid].Sst == SST_ASSOC);
1123 pAddreqFrame = (struct rt_frame_addba_req *) (&Elem->Msg[0]);
1124 /* 2. Always send back ADDBA Response */
1125 NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /*Get an unused nonpaged memory */
1126 if (NStatus != NDIS_STATUS_SUCCESS) {
1127 DBGPRINT(RT_DEBUG_TRACE,
1128 ("ACTION - PeerBAAction() allocate memory failed \n"));
1132 NdisZeroMemory(&ADDframe, sizeof(struct rt_frame_addba_rsp));
1134 /* 2-1. Prepare ADDBA Response frame. */
1137 ActHeaderInit(pAd, &ADDframe.Hdr, pAddr,
1138 pAd->CurrentAddress,
1139 pAd->CommonCfg.Bssid);
1141 ActHeaderInit(pAd, &ADDframe.Hdr, pAd->CommonCfg.Bssid,
1142 pAd->CurrentAddress, pAddr);
1145 ADDframe.Category = CATEGORY_BA;
1146 ADDframe.Action = ADDBA_RESP;
1147 ADDframe.Token = pAddreqFrame->Token;
1148 /* What is the Status code?? need to check. */
1149 ADDframe.StatusCode = Status;
1150 ADDframe.BaParm.BAPolicy = IMMED_BA;
1151 ADDframe.BaParm.AMSDUSupported = 0;
1152 ADDframe.BaParm.TID = pAddreqFrame->BaParm.TID;
1153 ADDframe.BaParm.BufSize =
1154 min(((u8)pAddreqFrame->BaParm.BufSize),
1155 (u8)pAd->CommonCfg.BACapability.field.RxBAWinLimit);
1156 if (ADDframe.BaParm.BufSize == 0) {
1157 ADDframe.BaParm.BufSize = 64;
1159 ADDframe.TimeOutValue = 0; /*pAddreqFrame->TimeOutValue; */
1161 *(u16 *) (&ADDframe.BaParm) =
1162 cpu2le16(*(u16 *) (&ADDframe.BaParm));
1163 ADDframe.StatusCode = cpu2le16(ADDframe.StatusCode);
1164 ADDframe.TimeOutValue = cpu2le16(ADDframe.TimeOutValue);
1166 MakeOutgoingFrame(pOutBuffer, &FrameLen,
1167 sizeof(struct rt_frame_addba_rsp), &ADDframe, END_OF_ARGS);
1168 MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
1169 MlmeFreeMemory(pAd, pOutBuffer);
1171 DBGPRINT(RT_DEBUG_TRACE,
1172 ("%s(%d): TID(%d), BufSize(%d) <== \n", __func__, Elem->Wcid,
1173 ADDframe.BaParm.TID, ADDframe.BaParm.BufSize));
1176 void PeerAddBARspAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem)
1179 /*u8 * pOutBuffer = NULL; */
1180 struct rt_frame_addba_rsp * pFrame = NULL;
1181 /*struct rt_ba_ori_entry *pBAEntry; */
1183 /*ADDBA Response from unknown peer, ignore this. */
1184 if (Elem->Wcid >= MAX_LEN_OF_MAC_TABLE)
1187 DBGPRINT(RT_DEBUG_TRACE, ("%s ==> Wcid(%d)\n", __func__, Elem->Wcid));
1189 /*hex_dump("PeerAddBARspAction()", Elem->Msg, Elem->MsgLen); */
1191 if (PeerAddBARspActionSanity(pAd, Elem->Msg, Elem->MsgLen)) {
1192 pFrame = (struct rt_frame_addba_rsp *) (&Elem->Msg[0]);
1194 DBGPRINT(RT_DEBUG_TRACE,
1195 ("\t\t StatusCode = %d\n", pFrame->StatusCode));
1196 switch (pFrame->StatusCode) {
1198 /* I want a BAsession with this peer as an originator. */
1199 BAOriSessionAdd(pAd, &pAd->MacTab.Content[Elem->Wcid],
1203 /* check status == USED ??? */
1204 BAOriSessionTearDown(pAd, Elem->Wcid,
1205 pFrame->BaParm.TID, TRUE, FALSE);
1208 /* Rcv Decline StatusCode */
1209 if ((pFrame->StatusCode == 37)
1210 || ((pAd->OpMode == OPMODE_STA) && STA_TGN_WIFI_ON(pAd)
1211 && (pFrame->StatusCode != 0))
1213 pAd->MacTab.Content[Elem->Wcid].BADeclineBitmap |=
1214 1 << pFrame->BaParm.TID;
1219 void PeerDelBAAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem)
1222 /*u8 * pOutBuffer = NULL; */
1223 struct rt_frame_delba_req * pDelFrame = NULL;
1225 DBGPRINT(RT_DEBUG_TRACE, ("%s ==>\n", __func__));
1226 /*DELBA Request from unknown peer, ignore this. */
1227 if (PeerDelBAActionSanity(pAd, Elem->Wcid, Elem->Msg, Elem->MsgLen)) {
1228 pDelFrame = (struct rt_frame_delba_req *) (&Elem->Msg[0]);
1229 if (pDelFrame->DelbaParm.Initiator == ORIGINATOR) {
1230 DBGPRINT(RT_DEBUG_TRACE,
1231 ("BA - PeerDelBAAction----> ORIGINATOR\n"));
1232 BARecSessionTearDown(pAd, Elem->Wcid,
1233 pDelFrame->DelbaParm.TID, TRUE);
1235 DBGPRINT(RT_DEBUG_TRACE,
1236 ("BA - PeerDelBAAction----> RECIPIENT, Reason = %d\n",
1237 pDelFrame->ReasonCode));
1238 /*hex_dump("DelBA Frame", pDelFrame, Elem->MsgLen); */
1239 BAOriSessionTearDown(pAd, Elem->Wcid,
1240 pDelFrame->DelbaParm.TID, TRUE,
1246 BOOLEAN CntlEnqueueForRecv(struct rt_rtmp_adapter *pAd,
1248 unsigned long MsgLen, struct rt_frame_ba_req * pMsg)
1250 struct rt_frame_ba_req * pFrame = pMsg;
1251 /*PRTMP_REORDERBUF pBuffer; */
1252 /*PRTMP_REORDERBUF pDmaBuf; */
1253 struct rt_ba_rec_entry *pBAEntry;
1254 /*BOOLEAN Result; */
1259 TID = (u8)pFrame->BARControl.TID;
1261 DBGPRINT(RT_DEBUG_TRACE,
1262 ("%s(): BAR-Wcid(%ld), Tid (%d)\n", __func__, Wcid, TID));
1263 /*hex_dump("BAR", (char *)pFrame, MsgLen); */
1264 /* Do nothing if the driver is starting halt state. */
1265 /* This might happen when timer already been fired before cancel timer with mlmehalt */
1267 (pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
1270 /* First check the size, it MUST not exceed the mlme queue size */
1271 if (MsgLen > MGMT_DMA_BUFFER_SIZE) {
1272 DBGPRINT_ERR(("CntlEnqueueForRecv: frame too large, size = %ld \n", MsgLen));
1274 } else if (MsgLen != sizeof(struct rt_frame_ba_req)) {
1275 DBGPRINT_ERR(("CntlEnqueueForRecv: BlockAck Request frame length size = %ld incorrect\n", MsgLen));
1277 } else if (MsgLen != sizeof(struct rt_frame_ba_req)) {
1278 DBGPRINT_ERR(("CntlEnqueueForRecv: BlockAck Request frame length size = %ld incorrect\n", MsgLen));
1282 if ((Wcid < MAX_LEN_OF_MAC_TABLE) && (TID < 8)) {
1283 /* if this receiving packet is from SA that is in our OriEntry. Since WCID <9 has direct mapping. no need search. */
1284 Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID];
1285 pBAEntry = &pAd->BATable.BARecEntry[Idx];
1290 DBGPRINT(RT_DEBUG_TRACE,
1291 ("BAR(%ld) : Tid (%d) - %04x:%04x\n", Wcid, TID,
1292 pFrame->BAStartingSeq.field.StartSeq, pBAEntry->LastIndSeq));
1295 (pBAEntry->LastIndSeq, pFrame->BAStartingSeq.field.StartSeq,
1297 /*DBGPRINT(RT_DEBUG_TRACE, ("BAR Seq = %x, LastIndSeq = %x\n", pFrame->BAStartingSeq.field.StartSeq, pBAEntry->LastIndSeq)); */
1298 ba_indicate_reordering_mpdus_le_seq(pAd, pBAEntry,
1299 pFrame->BAStartingSeq.field.
1301 pBAEntry->LastIndSeq =
1302 (pFrame->BAStartingSeq.field.StartSeq ==
1303 0) ? MAXSEQ : (pFrame->BAStartingSeq.field.StartSeq - 1);
1305 /*ba_refresh_reordering_mpdus(pAd, pBAEntry); */
1310 Description : Send PSMP Action frame If PSMP mode switches.
1312 void SendPSMPAction(struct rt_rtmp_adapter *pAd, u8 Wcid, u8 Psmp)
1314 u8 *pOutBuffer = NULL;
1316 /*unsigned long Idx; */
1317 struct rt_frame_psmp_action Frame;
1318 unsigned long FrameLen;
1320 NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /*Get an unused nonpaged memory */
1321 if (NStatus != NDIS_STATUS_SUCCESS) {
1322 DBGPRINT(RT_DEBUG_ERROR,
1323 ("BA - MlmeADDBAAction() allocate memory failed \n"));
1327 ActHeaderInit(pAd, &Frame.Hdr, pAd->CommonCfg.Bssid,
1328 pAd->CurrentAddress, pAd->MacTab.Content[Wcid].Addr);
1330 Frame.Category = CATEGORY_HT;
1331 Frame.Action = SMPS_ACTION;
1336 && (pAd->Antenna.field.RxPath > 1
1337 || pAd->Antenna.field.TxPath > 1)) {
1338 RTMP_ASIC_MMPS_DISABLE(pAd);
1340 #endif /* RT30xx // */
1349 && (pAd->Antenna.field.RxPath > 1
1350 || pAd->Antenna.field.TxPath > 1)) {
1351 RTMP_ASIC_MMPS_ENABLE(pAd);
1353 #endif /* RT30xx // */
1357 MakeOutgoingFrame(pOutBuffer, &FrameLen,
1358 sizeof(struct rt_frame_psmp_action), &Frame, END_OF_ARGS);
1359 MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
1360 MlmeFreeMemory(pAd, pOutBuffer);
1361 DBGPRINT(RT_DEBUG_ERROR, ("HT - SendPSMPAction( %d ) \n", Frame.Psmp));
1364 #define RADIO_MEASUREMENT_REQUEST_ACTION 0
1366 struct PACKED rt_beacon_request {
1370 u16 MeasurementDuration;
1372 u8 BSSID[MAC_ADDR_LEN];
1373 u8 ReportingCondition;
1375 u8 SSIDIE[2]; /* 2 byte */
1378 struct PACKED rt_measurement_req {
1386 void convert_reordering_packet_to_preAMSDU_or_802_3_packet(struct rt_rtmp_adapter *pAd,
1387 struct rt_rx_blk *pRxBlk,
1392 u8 Header802_3[LENGTH_802_3];
1394 /* 1. get 802.3 Header */
1396 /* a. pointer pRxBlk->pData to payload */
1397 /* b. modify pRxBlk->DataSize */
1399 RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3);
1401 ASSERT(pRxBlk->pRxPacket);
1402 pRxPkt = RTPKT_TO_OSPKT(pRxBlk->pRxPacket);
1404 SET_OS_PKT_NETDEV(pRxPkt, get_netdev_from_bssid(pAd, FromWhichBSSID));
1405 SET_OS_PKT_DATAPTR(pRxPkt, pRxBlk->pData);
1406 SET_OS_PKT_LEN(pRxPkt, pRxBlk->DataSize);
1407 SET_OS_PKT_DATATAIL(pRxPkt, pRxBlk->pData, pRxBlk->DataSize);
1410 /* copy 802.3 header, if necessary */
1412 if (!RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU)) {
1415 NdisMoveMemory(skb_push(pRxPkt, LENGTH_802_3),
1416 Header802_3, LENGTH_802_3);
1422 #define INDICATE_LEGACY_OR_AMSDU(_pAd, _pRxBlk, _fromWhichBSSID) \
1425 if (RX_BLK_TEST_FLAG(_pRxBlk, fRX_AMSDU)) \
1427 Indicate_AMSDU_Packet(_pAd, _pRxBlk, _fromWhichBSSID); \
1429 else if (RX_BLK_TEST_FLAG(_pRxBlk, fRX_EAP)) \
1431 Indicate_EAPOL_Packet(_pAd, _pRxBlk, _fromWhichBSSID); \
1435 Indicate_Legacy_Packet(_pAd, _pRxBlk, _fromWhichBSSID); \
1439 static void ba_enqueue_reordering_packet(struct rt_rtmp_adapter *pAd,
1440 struct rt_ba_rec_entry *pBAEntry,
1441 struct rt_rx_blk *pRxBlk,
1444 struct reordering_mpdu *mpdu_blk;
1445 u16 Sequence = (u16)pRxBlk->pHeader->Sequence;
1447 mpdu_blk = ba_mpdu_blk_alloc(pAd);
1448 if ((mpdu_blk != NULL) && (!RX_BLK_TEST_FLAG(pRxBlk, fRX_EAP))) {
1449 /* Write RxD buffer address & allocated buffer length */
1450 NdisAcquireSpinLock(&pBAEntry->RxReRingLock);
1452 mpdu_blk->Sequence = Sequence;
1454 mpdu_blk->bAMSDU = RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU);
1456 convert_reordering_packet_to_preAMSDU_or_802_3_packet(pAd,
1460 STATS_INC_RX_PACKETS(pAd, FromWhichBSSID);
1463 /* it is necessary for reordering packet to record */
1464 /* which BSS it come from */
1466 RTMP_SET_PACKET_IF(pRxBlk->pRxPacket, FromWhichBSSID);
1468 mpdu_blk->pPacket = pRxBlk->pRxPacket;
1470 if (ba_reordering_mpdu_insertsorted(&pBAEntry->list, mpdu_blk)
1472 /* had been already within reordering list */
1473 /* don't indicate */
1474 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket,
1475 NDIS_STATUS_SUCCESS);
1476 ba_mpdu_blk_free(pAd, mpdu_blk);
1479 ASSERT((0 <= pBAEntry->list.qlen)
1480 && (pBAEntry->list.qlen <= pBAEntry->BAWinSize));
1481 NdisReleaseSpinLock(&pBAEntry->RxReRingLock);
1483 DBGPRINT(RT_DEBUG_ERROR,
1484 (" (%d) Can't allocate reordering mpdu blk\n",
1485 pBAEntry->list.qlen));
1488 * flush all pending reordering mpdus
1489 * and receving mpdu to upper layer
1490 * make tcp/ip to take care reordering mechanism
1492 /*ba_refresh_reordering_mpdus(pAd, pBAEntry); */
1493 ba_indicate_reordering_mpdus_le_seq(pAd, pBAEntry, Sequence);
1495 pBAEntry->LastIndSeq = Sequence;
1496 INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID);
1501 ==========================================================================
1503 Indicate this packet to upper layer or put it into reordering buffer
1506 pRxBlk : carry necessary packet info 802.11 format
1507 FromWhichBSSID : the packet received from which BSS
1513 the packet queued into reordering buffer need to cover to 802.3 format
1515 ==========================================================================
1518 void Indicate_AMPDU_Packet(struct rt_rtmp_adapter *pAd,
1519 struct rt_rx_blk *pRxBlk, u8 FromWhichBSSID)
1522 struct rt_ba_rec_entry *pBAEntry = NULL;
1523 u16 Sequence = pRxBlk->pHeader->Sequence;
1524 unsigned long Now32;
1525 u8 Wcid = pRxBlk->pRxWI->WirelessCliID;
1526 u8 TID = pRxBlk->pRxWI->TID;
1528 if (!RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU)
1529 && (pRxBlk->DataSize > MAX_RX_PKT_LEN)) {
1530 /* release packet */
1531 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket,
1532 NDIS_STATUS_FAILURE);
1536 if (Wcid < MAX_LEN_OF_MAC_TABLE) {
1537 Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID];
1539 /* Rec BA Session had been torn down */
1540 INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID);
1543 pBAEntry = &pAd->BATable.BARecEntry[Idx];
1547 /* release packet */
1548 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket,
1549 NDIS_STATUS_FAILURE);
1555 /* update last rx time */
1556 NdisGetSystemUpTime(&Now32);
1558 pBAEntry->rcvSeq = Sequence;
1560 ba_flush_reordering_timeout_mpdus(pAd, pBAEntry, Now32);
1561 pBAEntry->LastIndSeqAtTimer = Now32;
1564 /* Reset Last Indicate Sequence */
1566 if (pBAEntry->LastIndSeq == RESET_RCV_SEQ) {
1567 ASSERT((pBAEntry->list.qlen == 0)
1568 && (pBAEntry->list.next == NULL));
1570 /* reset rcv sequence of BA session */
1571 pBAEntry->LastIndSeq = Sequence;
1572 pBAEntry->LastIndSeqAtTimer = Now32;
1573 INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID);
1578 /* I. Check if in order. */
1580 if (SEQ_STEPONE(Sequence, pBAEntry->LastIndSeq, MAXSEQ)) {
1583 pBAEntry->LastIndSeq = Sequence;
1584 INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID);
1586 ba_indicate_reordering_mpdus_in_order(pAd, pBAEntry,
1587 pBAEntry->LastIndSeq);
1588 if (LastIndSeq != RESET_RCV_SEQ) {
1589 pBAEntry->LastIndSeq = LastIndSeq;
1591 pBAEntry->LastIndSeqAtTimer = Now32;
1594 /* II. Drop Duplicated Packet */
1596 else if (Sequence == pBAEntry->LastIndSeq) {
1598 /* drop and release packet */
1599 pBAEntry->nDropPacket++;
1600 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket,
1601 NDIS_STATUS_FAILURE);
1604 /* III. Drop Old Received Packet */
1606 else if (SEQ_SMALLER(Sequence, pBAEntry->LastIndSeq, MAXSEQ)) {
1608 /* drop and release packet */
1609 pBAEntry->nDropPacket++;
1610 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket,
1611 NDIS_STATUS_FAILURE);
1614 /* IV. Receive Sequence within Window Size */
1616 else if (SEQ_SMALLER
1618 (((pBAEntry->LastIndSeq + pBAEntry->BAWinSize + 1)) & MAXSEQ),
1620 ba_enqueue_reordering_packet(pAd, pBAEntry, pRxBlk,
1624 /* V. Receive seq surpasses Win(lastseq + nMSDU). So refresh all reorder buffer */
1627 long WinStartSeq, TmpSeq;
1629 TmpSeq = Sequence - (pBAEntry->BAWinSize) - 1;
1631 TmpSeq = (MAXSEQ + 1) + TmpSeq;
1633 WinStartSeq = (TmpSeq + 1) & MAXSEQ;
1634 ba_indicate_reordering_mpdus_le_seq(pAd, pBAEntry, WinStartSeq);
1635 pBAEntry->LastIndSeq = WinStartSeq; /*TmpSeq; */
1637 pBAEntry->LastIndSeqAtTimer = Now32;
1639 ba_enqueue_reordering_packet(pAd, pBAEntry, pRxBlk,
1643 ba_indicate_reordering_mpdus_in_order(pAd, pBAEntry,
1644 pBAEntry->LastIndSeq);
1645 if (TmpSeq != RESET_RCV_SEQ) {
1646 pBAEntry->LastIndSeq = TmpSeq;