2 *************************************************************************
4 * 5F., No.36, Taiyuan St., Jhubei City,
8 * (c) Copyright 2002-2007, Ralink Technology, Inc.
10 * This program is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License as published by *
12 * the Free Software Foundation; either version 2 of the License, or *
13 * (at your option) any later version. *
15 * This program is distributed in the hope that it will be useful, *
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
18 * GNU General Public License for more details. *
20 * You should have received a copy of the GNU General Public License *
21 * along with this program; if not, write to the *
22 * Free Software Foundation, Inc., *
23 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
25 *************************************************************************
28 #ifdef DOT11_N_SUPPORT
30 #include "../rt_config.h"
34 #define BA_ORI_INIT_SEQ (pEntry->TxSeq[TID]) //1 // inital sequence number of BA session
36 #define ORI_SESSION_MAX_RETRY 8
37 #define ORI_BA_SESSION_TIMEOUT (2000) // ms
38 #define REC_BA_SESSION_IDLE_TIMEOUT (1000) // ms
40 #define REORDERING_PACKET_TIMEOUT ((100 * HZ)/1000) // system ticks -- 100 ms
41 #define MAX_REORDERING_PACKET_TIMEOUT ((3000 * HZ)/1000) // system ticks -- 100 ms
43 #define RESET_RCV_SEQ (0xFFFF)
45 static void ba_mpdu_blk_free(PRTMP_ADAPTER pAd
, struct reordering_mpdu
*mpdu_blk
);
48 BA_ORI_ENTRY
*BATableAllocOriEntry(
52 BA_REC_ENTRY
*BATableAllocRecEntry(
56 VOID
BAOriSessionSetupTimeout(
57 IN PVOID SystemSpecific1
,
58 IN PVOID FunctionContext
,
59 IN PVOID SystemSpecific2
,
60 IN PVOID SystemSpecific3
);
62 VOID
BARecSessionIdleTimeout(
63 IN PVOID SystemSpecific1
,
64 IN PVOID FunctionContext
,
65 IN PVOID SystemSpecific2
,
66 IN PVOID SystemSpecific3
);
69 BUILD_TIMER_FUNCTION(BAOriSessionSetupTimeout
);
70 BUILD_TIMER_FUNCTION(BARecSessionIdleTimeout
);
72 #define ANNOUNCE_REORDERING_PACKET(_pAd, _mpdu_blk) \
73 Announce_Reordering_Packet(_pAd, _mpdu_blk);
75 VOID
BA_MaxWinSizeReasign(
77 IN MAC_TABLE_ENTRY
*pEntryPeer
,
83 if (pAd
->MACVersion
>= RALINK_2883_VERSION
) // 3*3
85 if (pAd
->MACVersion
>= RALINK_3070_VERSION
)
87 if (pEntryPeer
->WepStatus
!= Ndis802_11EncryptionDisabled
)
88 MaxSize
= 7; // for non-open mode
95 else if (pAd
->MACVersion
>= RALINK_2880E_VERSION
) // 2880 e
97 if (pEntryPeer
->WepStatus
!= Ndis802_11EncryptionDisabled
)
98 MaxSize
= 7; // for non-open mode
105 DBGPRINT(RT_DEBUG_TRACE
, ("ba> Win Size = %d, Max Size = %d\n",
106 *pWinSize
, MaxSize
));
108 if ((*pWinSize
) > MaxSize
)
110 DBGPRINT(RT_DEBUG_TRACE
, ("ba> reassign max win size from %d to %d\n",
111 *pWinSize
, MaxSize
));
117 void Announce_Reordering_Packet(IN PRTMP_ADAPTER pAd
,
118 IN
struct reordering_mpdu
*mpdu
)
120 PNDIS_PACKET pPacket
;
122 pPacket
= mpdu
->pPacket
;
127 BA_Reorder_AMSDU_Annnounce(pAd
, pPacket
);
132 // pass this 802.3 packet to upper layer or forward this packet to WM directly
135 #ifdef CONFIG_STA_SUPPORT
136 IF_DEV_CONFIG_OPMODE_ON_STA(pAd
)
137 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd
, pPacket
, RTMP_GET_PACKET_IF(pPacket
));
138 #endif // CONFIG_STA_SUPPORT //
143 * Insert a reordering mpdu into sorted linked list by sequence no.
145 BOOLEAN
ba_reordering_mpdu_insertsorted(struct reordering_list
*list
, struct reordering_mpdu
*mpdu
)
148 struct reordering_mpdu
**ppScan
= &list
->next
;
150 while (*ppScan
!= NULL
)
152 if (SEQ_SMALLER((*ppScan
)->Sequence
, mpdu
->Sequence
, MAXSEQ
))
154 ppScan
= &(*ppScan
)->next
;
156 else if ((*ppScan
)->Sequence
== mpdu
->Sequence
)
158 /* give up this duplicated frame */
168 mpdu
->next
= *ppScan
;
176 * caller lock critical section if necessary
178 static inline void ba_enqueue(struct reordering_list
*list
, struct reordering_mpdu
*mpdu_blk
)
181 mpdu_blk
->next
= list
->next
;
182 list
->next
= mpdu_blk
;
186 * caller lock critical section if necessary
188 static inline struct reordering_mpdu
* ba_dequeue(struct reordering_list
*list
)
190 struct reordering_mpdu
*mpdu_blk
= NULL
;
197 mpdu_blk
= list
->next
;
200 list
->next
= mpdu_blk
->next
;
201 mpdu_blk
->next
= NULL
;
208 static inline struct reordering_mpdu
*ba_reordering_mpdu_dequeue(struct reordering_list
*list
)
210 return(ba_dequeue(list
));
214 static inline struct reordering_mpdu
*ba_reordering_mpdu_probe(struct reordering_list
*list
)
223 * free all resource for reordering mechanism
225 void ba_reordering_resource_release(PRTMP_ADAPTER pAd
)
228 PBA_REC_ENTRY pBAEntry
;
229 struct reordering_mpdu
*mpdu_blk
;
234 /* I. release all pending reordering packet */
235 NdisAcquireSpinLock(&pAd
->BATabLock
);
236 for (i
= 0; i
< MAX_LEN_OF_BA_REC_TABLE
; i
++)
238 pBAEntry
= &Tab
->BARecEntry
[i
];
239 if (pBAEntry
->REC_BA_Status
!= Recipient_NONE
)
241 while ((mpdu_blk
= ba_reordering_mpdu_dequeue(&pBAEntry
->list
)))
243 ASSERT(mpdu_blk
->pPacket
);
244 RELEASE_NDIS_PACKET(pAd
, mpdu_blk
->pPacket
, NDIS_STATUS_FAILURE
);
245 ba_mpdu_blk_free(pAd
, mpdu_blk
);
249 NdisReleaseSpinLock(&pAd
->BATabLock
);
251 ASSERT(pBAEntry
->list
.qlen
== 0);
252 /* II. free memory of reordering mpdu table */
253 NdisAcquireSpinLock(&pAd
->mpdu_blk_pool
.lock
);
254 os_free_mem(pAd
, pAd
->mpdu_blk_pool
.mem
);
255 NdisReleaseSpinLock(&pAd
->mpdu_blk_pool
.lock
);
261 * Allocate all resource for reordering mechanism
263 BOOLEAN
ba_reordering_resource_init(PRTMP_ADAPTER pAd
, int num
)
267 struct reordering_mpdu
*mpdu_blk
;
268 struct reordering_list
*freelist
;
270 /* allocate spinlock */
271 NdisAllocateSpinLock(&pAd
->mpdu_blk_pool
.lock
);
273 /* initialize freelist */
274 freelist
= &pAd
->mpdu_blk_pool
.freelist
;
275 freelist
->next
= NULL
;
278 DBGPRINT(RT_DEBUG_TRACE
, ("Allocate %d memory for BA reordering\n", (UINT32
)(num
*sizeof(struct reordering_mpdu
))));
280 /* allocate number of mpdu_blk memory */
281 os_alloc_mem(pAd
, (PUCHAR
*)&mem
, (num
*sizeof(struct reordering_mpdu
)));
283 pAd
->mpdu_blk_pool
.mem
= mem
;
287 DBGPRINT(RT_DEBUG_ERROR
, ("Can't Allocate Memory for BA Reordering\n"));
291 /* build mpdu_blk free list */
292 for (i
=0; i
<num
; i
++)
295 mpdu_blk
= (struct reordering_mpdu
*) mem
;
296 /* initial mpdu_blk */
297 NdisZeroMemory(mpdu_blk
, sizeof(struct reordering_mpdu
));
299 mem
+= sizeof(struct reordering_mpdu
);
300 /* insert mpdu_blk into freelist */
301 ba_enqueue(freelist
, mpdu_blk
);
307 //static int blk_count=0; // sample take off, no use
309 static struct reordering_mpdu
*ba_mpdu_blk_alloc(PRTMP_ADAPTER pAd
)
311 struct reordering_mpdu
*mpdu_blk
;
313 NdisAcquireSpinLock(&pAd
->mpdu_blk_pool
.lock
);
314 mpdu_blk
= ba_dequeue(&pAd
->mpdu_blk_pool
.freelist
);
319 NdisZeroMemory(mpdu_blk
, sizeof(struct reordering_mpdu
));
321 NdisReleaseSpinLock(&pAd
->mpdu_blk_pool
.lock
);
325 static void ba_mpdu_blk_free(PRTMP_ADAPTER pAd
, struct reordering_mpdu
*mpdu_blk
)
329 NdisAcquireSpinLock(&pAd
->mpdu_blk_pool
.lock
);
331 ba_enqueue(&pAd
->mpdu_blk_pool
.freelist
, mpdu_blk
);
332 NdisReleaseSpinLock(&pAd
->mpdu_blk_pool
.lock
);
336 static USHORT
ba_indicate_reordering_mpdus_in_order(
337 IN PRTMP_ADAPTER pAd
,
338 IN PBA_REC_ENTRY pBAEntry
,
341 struct reordering_mpdu
*mpdu_blk
;
342 USHORT LastIndSeq
= RESET_RCV_SEQ
;
344 NdisAcquireSpinLock(&pBAEntry
->RxReRingLock
);
346 while ((mpdu_blk
= ba_reordering_mpdu_probe(&pBAEntry
->list
)))
348 /* find in-order frame */
349 if (!SEQ_STEPONE(mpdu_blk
->Sequence
, StartSeq
, MAXSEQ
))
353 /* dequeue in-order frame from reodering list */
354 mpdu_blk
= ba_reordering_mpdu_dequeue(&pBAEntry
->list
);
355 /* pass this frame up */
356 ANNOUNCE_REORDERING_PACKET(pAd
, mpdu_blk
);
357 /* move to next sequence */
358 StartSeq
= mpdu_blk
->Sequence
;
359 LastIndSeq
= StartSeq
;
361 ba_mpdu_blk_free(pAd
, mpdu_blk
);
364 NdisReleaseSpinLock(&pBAEntry
->RxReRingLock
);
366 /* update last indicated sequence */
370 static void ba_indicate_reordering_mpdus_le_seq(
371 IN PRTMP_ADAPTER pAd
,
372 IN PBA_REC_ENTRY pBAEntry
,
375 struct reordering_mpdu
*mpdu_blk
;
377 NdisAcquireSpinLock(&pBAEntry
->RxReRingLock
);
378 while ((mpdu_blk
= ba_reordering_mpdu_probe(&pBAEntry
->list
)))
380 /* find in-order frame */
381 if ((mpdu_blk
->Sequence
== Sequence
) || SEQ_SMALLER(mpdu_blk
->Sequence
, Sequence
, MAXSEQ
))
383 /* dequeue in-order frame from reodering list */
384 mpdu_blk
= ba_reordering_mpdu_dequeue(&pBAEntry
->list
);
385 /* pass this frame up */
386 ANNOUNCE_REORDERING_PACKET(pAd
, mpdu_blk
);
388 ba_mpdu_blk_free(pAd
, mpdu_blk
);
395 NdisReleaseSpinLock(&pBAEntry
->RxReRingLock
);
399 static void ba_refresh_reordering_mpdus(
400 IN PRTMP_ADAPTER pAd
,
401 PBA_REC_ENTRY pBAEntry
)
403 struct reordering_mpdu
*mpdu_blk
;
405 NdisAcquireSpinLock(&pBAEntry
->RxReRingLock
);
407 /* dequeue in-order frame from reodering list */
408 while ((mpdu_blk
= ba_reordering_mpdu_dequeue(&pBAEntry
->list
)))
410 /* pass this frame up */
411 ANNOUNCE_REORDERING_PACKET(pAd
, mpdu_blk
);
413 pBAEntry
->LastIndSeq
= mpdu_blk
->Sequence
;
414 ba_mpdu_blk_free(pAd
, mpdu_blk
);
416 /* update last indicated sequence */
418 ASSERT(pBAEntry
->list
.qlen
== 0);
419 pBAEntry
->LastIndSeq
= RESET_RCV_SEQ
;
420 NdisReleaseSpinLock(&pBAEntry
->RxReRingLock
);
425 void ba_flush_reordering_timeout_mpdus(
426 IN PRTMP_ADAPTER pAd
,
427 IN PBA_REC_ENTRY pBAEntry
,
433 // if ((RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+REORDERING_PACKET_TIMEOUT)) &&
434 // (pBAEntry->list.qlen > ((pBAEntry->BAWinSize*7)/8))) //||
435 // (RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+(10*REORDERING_PACKET_TIMEOUT))) &&
436 // (pBAEntry->list.qlen > (pBAEntry->BAWinSize/8)))
437 if (RTMP_TIME_AFTER((unsigned long)Now32
, (unsigned long)(pBAEntry
->LastIndSeqAtTimer
+(MAX_REORDERING_PACKET_TIMEOUT
/6)))
438 &&(pBAEntry
->list
.qlen
> 1)
441 DBGPRINT(RT_DEBUG_TRACE
,("timeout[%d] (%08lx-%08lx = %d > %d): %x, flush all!\n ", pBAEntry
->list
.qlen
, Now32
, (pBAEntry
->LastIndSeqAtTimer
),
442 (int)((long) Now32
- (long)(pBAEntry
->LastIndSeqAtTimer
)), MAX_REORDERING_PACKET_TIMEOUT
,
443 pBAEntry
->LastIndSeq
));
444 ba_refresh_reordering_mpdus(pAd
, pBAEntry
);
445 pBAEntry
->LastIndSeqAtTimer
= Now32
;
448 if (RTMP_TIME_AFTER((unsigned long)Now32
, (unsigned long)(pBAEntry
->LastIndSeqAtTimer
+(REORDERING_PACKET_TIMEOUT
)))
449 && (pBAEntry
->list
.qlen
> 0)
452 // printk("timeout[%d] (%lx-%lx = %d > %d): %x, ", pBAEntry->list.qlen, Now32, (pBAEntry->LastIndSeqAtTimer),
453 // (int)((long) Now32 - (long)(pBAEntry->LastIndSeqAtTimer)), REORDERING_PACKET_TIMEOUT,
454 // pBAEntry->LastIndSeq);
456 // force LastIndSeq to shift to LastIndSeq+1
458 Sequence
= (pBAEntry
->LastIndSeq
+1) & MAXSEQ
;
459 ba_indicate_reordering_mpdus_le_seq(pAd
, pBAEntry
, Sequence
);
460 pBAEntry
->LastIndSeqAtTimer
= Now32
;
461 pBAEntry
->LastIndSeq
= Sequence
;
463 // indicate in-order mpdus
465 Sequence
= ba_indicate_reordering_mpdus_in_order(pAd
, pBAEntry
, Sequence
);
466 if (Sequence
!= RESET_RCV_SEQ
)
468 pBAEntry
->LastIndSeq
= Sequence
;
471 //printk("%x, flush one!\n", pBAEntry->LastIndSeq);
476 (RTMP_TIME_AFTER((unsigned long)Now32
, (unsigned long)(pBAEntry
->LastIndSeqAtTimer
+(MAX_REORDERING_PACKET_TIMEOUT
))) &&
477 (pBAEntry
->list
.qlen
> 1))
480 DBGPRINT(RT_DEBUG_TRACE
,("timeout[%d] (%lx-%lx = %d > %d): %x\n ", pBAEntry
->list
.qlen
, Now32
, (pBAEntry
->LastIndSeqAtTimer
),
481 (int)((long) Now32
- (long)(pBAEntry
->LastIndSeqAtTimer
)), MAX_REORDERING_PACKET_TIMEOUT
,
482 pBAEntry
->LastIndSeq
));
483 ba_refresh_reordering_mpdus(pAd
, pBAEntry
);
484 pBAEntry
->LastIndSeqAtTimer
= Now32
;
491 * generate ADDBA request to
492 * set up BA agreement
494 VOID
BAOriSessionSetUp(
495 IN PRTMP_ADAPTER pAd
,
496 IN MAC_TABLE_ENTRY
*pEntry
,
503 //MLME_ADDBA_REQ_STRUCT AddbaReq;
504 BA_ORI_ENTRY
*pBAEntry
= NULL
;
508 if ((pAd
->CommonCfg
.BACapability
.field
.AutoBA
!= TRUE
) && (isForced
== FALSE
))
511 // if this entry is limited to use legacy tx mode, it doesn't generate BA.
512 if (RTMPStaFixedTxMode(pAd
, pEntry
) != FIXED_TXMODE_HT
)
515 if ((pEntry
->BADeclineBitmap
& (1<<TID
)) && (isForced
== FALSE
))
517 // try again after 3 secs
519 // printk("DeCline BA from Peer\n");
524 Idx
= pEntry
->BAOriWcidArray
[TID
];
527 // allocate a BA session
528 pBAEntry
= BATableAllocOriEntry(pAd
, &Idx
);
529 if (pBAEntry
== NULL
)
531 DBGPRINT(RT_DEBUG_TRACE
,("ADDBA - MlmeADDBAAction() allocate BA session failed \n"));
537 pBAEntry
=&pAd
->BATable
.BAOriEntry
[Idx
];
540 if (pBAEntry
->ORI_BA_Status
>= Originator_WaitRes
)
545 pEntry
->BAOriWcidArray
[TID
] = Idx
;
547 // Initialize BA session
548 pBAEntry
->ORI_BA_Status
= Originator_WaitRes
;
549 pBAEntry
->Wcid
= pEntry
->Aid
;
550 pBAEntry
->BAWinSize
= pAd
->CommonCfg
.BACapability
.field
.RxBAWinLimit
;
551 pBAEntry
->Sequence
= BA_ORI_INIT_SEQ
;
552 pBAEntry
->Token
= 1; // (2008-01-21) Jan Lee recommends it - this token can't be 0
554 pBAEntry
->TimeOutValue
= TimeOut
;
555 pBAEntry
->pAdapter
= pAd
;
557 if (!(pEntry
->TXBAbitmap
& (1<<TID
)))
559 RTMPInitTimer(pAd
, &pBAEntry
->ORIBATimer
, GET_TIMER_FUNCTION(BAOriSessionSetupTimeout
), pBAEntry
, FALSE
);
562 RTMPCancelTimer(&pBAEntry
->ORIBATimer
, &Cancelled
);
564 // set timer to send ADDBA request
565 RTMPSetTimer(&pBAEntry
->ORIBATimer
, DelayTime
);
568 VOID
BAOriSessionAdd(
569 IN PRTMP_ADAPTER pAd
,
570 IN MAC_TABLE_ENTRY
*pEntry
,
571 IN PFRAME_ADDBA_RSP pFrame
)
573 BA_ORI_ENTRY
*pBAEntry
= NULL
;
577 PUCHAR pOutBuffer2
= NULL
;
582 TID
= pFrame
->BaParm
.TID
;
583 Idx
= pEntry
->BAOriWcidArray
[TID
];
584 pBAEntry
=&pAd
->BATable
.BAOriEntry
[Idx
];
586 // Start fill in parameters.
587 if ((Idx
!=0) && (pBAEntry
->TID
== TID
) && (pBAEntry
->ORI_BA_Status
== Originator_WaitRes
))
589 pBAEntry
->BAWinSize
= min(pBAEntry
->BAWinSize
, ((UCHAR
)pFrame
->BaParm
.BufSize
));
590 BA_MaxWinSizeReasign(pAd
, pEntry
, &pBAEntry
->BAWinSize
);
592 pBAEntry
->TimeOutValue
= pFrame
->TimeOutValue
;
593 pBAEntry
->ORI_BA_Status
= Originator_Done
;
594 // reset sequence number
595 pBAEntry
->Sequence
= BA_ORI_INIT_SEQ
;
597 pEntry
->TXBAbitmap
|= (1<<TID
);
598 RTMPCancelTimer(&pBAEntry
->ORIBATimer
, &Cancelled
);
600 pBAEntry
->ORIBATimer
.TimerValue
= 0; //pFrame->TimeOutValue;
602 DBGPRINT(RT_DEBUG_TRACE
,("%s : TXBAbitmap = %x, BAWinSize = %d, TimeOut = %ld\n", __func__
, pEntry
->TXBAbitmap
,
603 pBAEntry
->BAWinSize
, pBAEntry
->ORIBATimer
.TimerValue
));
606 NStatus
= MlmeAllocateMemory(pAd
, &pOutBuffer2
); //Get an unused nonpaged memory
607 if (NStatus
!= NDIS_STATUS_SUCCESS
)
609 DBGPRINT(RT_DEBUG_TRACE
,("BA - BAOriSessionAdd() allocate memory failed \n"));
614 #ifdef CONFIG_STA_SUPPORT
615 IF_DEV_CONFIG_OPMODE_ON_STA(pAd
)
616 BarHeaderInit(pAd
, &FrameBar
, pAd
->MacTab
.Content
[pBAEntry
->Wcid
].Addr
, pAd
->CurrentAddress
);
617 #endif // CONFIG_STA_SUPPORT //
619 FrameBar
.StartingSeq
.field
.FragNum
= 0; // make sure sequence not clear in DEL function.
620 FrameBar
.StartingSeq
.field
.StartSeq
= pBAEntry
->Sequence
; // make sure sequence not clear in DEL funciton.
621 FrameBar
.BarControl
.TID
= pBAEntry
->TID
; // make sure sequence not clear in DEL funciton.
622 MakeOutgoingFrame(pOutBuffer2
, &FrameLen
,
623 sizeof(FRAME_BAR
), &FrameBar
,
625 MiniportMMRequest(pAd
, QID_AC_BE
, pOutBuffer2
, FrameLen
);
626 MlmeFreeMemory(pAd
, pOutBuffer2
);
629 if (pBAEntry
->ORIBATimer
.TimerValue
)
630 RTMPSetTimer(&pBAEntry
->ORIBATimer
, pBAEntry
->ORIBATimer
.TimerValue
); // in mSec
634 BOOLEAN
BARecSessionAdd(
635 IN PRTMP_ADAPTER pAd
,
636 IN MAC_TABLE_ENTRY
*pEntry
,
637 IN PFRAME_ADDBA_REQ pFrame
)
639 BA_REC_ENTRY
*pBAEntry
= NULL
;
640 BOOLEAN Status
= TRUE
;
652 TID
= pFrame
->BaParm
.TID
;
654 BAWinSize
= min(((UCHAR
)pFrame
->BaParm
.BufSize
), (UCHAR
)pAd
->CommonCfg
.BACapability
.field
.RxBAWinLimit
);
662 Idx
= pEntry
->BARecWcidArray
[TID
];
667 pBAEntry
= BATableAllocRecEntry(pAd
, &Idx
);
671 pBAEntry
= &pAd
->BATable
.BARecEntry
[Idx
];
672 // flush all pending reordering mpdus
673 ba_refresh_reordering_mpdus(pAd
, pBAEntry
);
676 DBGPRINT(RT_DEBUG_TRACE
,("%s(%ld): Idx = %d, BAWinSize(req %d) = %d\n", __func__
, pAd
->BATable
.numAsRecipient
, Idx
,
677 pFrame
->BaParm
.BufSize
, BAWinSize
));
679 // Start fill in parameters.
680 if (pBAEntry
!= NULL
)
682 ASSERT(pBAEntry
->list
.qlen
== 0);
684 pBAEntry
->REC_BA_Status
= Recipient_HandleRes
;
685 pBAEntry
->BAWinSize
= BAWinSize
;
686 pBAEntry
->Wcid
= pEntry
->Aid
;
688 pBAEntry
->TimeOutValue
= pFrame
->TimeOutValue
;
689 pBAEntry
->REC_BA_Status
= Recipient_Accept
;
690 // initial sequence number
691 pBAEntry
->LastIndSeq
= RESET_RCV_SEQ
; //pFrame->BaStartSeq.field.StartSeq;
693 printk("Start Seq = %08x\n", pFrame
->BaStartSeq
.field
.StartSeq
);
695 if (pEntry
->RXBAbitmap
& (1<<TID
))
697 RTMPCancelTimer(&pBAEntry
->RECBATimer
, &Cancelled
);
701 RTMPInitTimer(pAd
, &pBAEntry
->RECBATimer
, GET_TIMER_FUNCTION(BARecSessionIdleTimeout
), pBAEntry
, TRUE
);
704 #if 0 // for debugging
705 RTMPSetTimer(&pBAEntry
->RECBATimer
, REC_BA_SESSION_IDLE_TIMEOUT
);
709 pEntry
->RXBAbitmap
|= (1<<TID
);
710 pEntry
->BARecWcidArray
[TID
] = Idx
;
712 pEntry
->BADeclineBitmap
&= ~(1<<TID
);
714 // Set BA session mask in WCID table.
715 RT28XX_ADD_BA_SESSION_TO_ASIC(pAd
, pEntry
->Aid
, TID
);
717 DBGPRINT(RT_DEBUG_TRACE
,("MACEntry[%d]RXBAbitmap = 0x%x. BARecWcidArray=%d\n",
718 pEntry
->Aid
, pEntry
->RXBAbitmap
, pEntry
->BARecWcidArray
[TID
]));
723 DBGPRINT(RT_DEBUG_TRACE
,("Can't Accept ADDBA for %02x:%02x:%02x:%02x:%02x:%02x TID = %d\n",
724 PRINT_MAC(pEntry
->Addr
), TID
));
730 BA_REC_ENTRY
*BATableAllocRecEntry(
731 IN PRTMP_ADAPTER pAd
,
735 BA_REC_ENTRY
*pBAEntry
= NULL
;
738 NdisAcquireSpinLock(&pAd
->BATabLock
);
740 if (pAd
->BATable
.numAsRecipient
>= MAX_BARECI_SESSION
)
742 printk("BA Recipeint Session (%ld) > %d\n", pAd
->BATable
.numAsRecipient
,
747 // reserve idx 0 to identify BAWcidArray[TID] as empty
748 for (i
=1; i
< MAX_LEN_OF_BA_REC_TABLE
; i
++)
750 pBAEntry
=&pAd
->BATable
.BARecEntry
[i
];
751 if ((pBAEntry
->REC_BA_Status
== Recipient_NONE
))
754 pAd
->BATable
.numAsRecipient
++;
755 pBAEntry
->REC_BA_Status
= Recipient_USED
;
762 NdisReleaseSpinLock(&pAd
->BATabLock
);
766 BA_ORI_ENTRY
*BATableAllocOriEntry(
767 IN PRTMP_ADAPTER pAd
,
771 BA_ORI_ENTRY
*pBAEntry
= NULL
;
773 NdisAcquireSpinLock(&pAd
->BATabLock
);
775 if (pAd
->BATable
.numAsOriginator
>= (MAX_LEN_OF_BA_ORI_TABLE
))
780 // reserve idx 0 to identify BAWcidArray[TID] as empty
781 for (i
=1; i
<MAX_LEN_OF_BA_ORI_TABLE
; i
++)
783 pBAEntry
=&pAd
->BATable
.BAOriEntry
[i
];
784 if ((pBAEntry
->ORI_BA_Status
== Originator_NONE
))
787 pAd
->BATable
.numAsOriginator
++;
788 pBAEntry
->ORI_BA_Status
= Originator_USED
;
789 pBAEntry
->pAdapter
= pAd
;
796 NdisReleaseSpinLock(&pAd
->BATabLock
);
801 VOID
BATableFreeOriEntry(
802 IN PRTMP_ADAPTER pAd
,
805 BA_ORI_ENTRY
*pBAEntry
= NULL
;
806 MAC_TABLE_ENTRY
*pEntry
;
809 if ((Idx
== 0) || (Idx
>= MAX_LEN_OF_BA_ORI_TABLE
))
812 pBAEntry
=&pAd
->BATable
.BAOriEntry
[Idx
];
814 if (pBAEntry
->ORI_BA_Status
!= Originator_NONE
)
816 pEntry
= &pAd
->MacTab
.Content
[pBAEntry
->Wcid
];
817 pEntry
->BAOriWcidArray
[pBAEntry
->TID
] = 0;
820 NdisAcquireSpinLock(&pAd
->BATabLock
);
821 if (pBAEntry
->ORI_BA_Status
== Originator_Done
)
823 pEntry
->TXBAbitmap
&= (~(1<<(pBAEntry
->TID
) ));
824 DBGPRINT(RT_DEBUG_TRACE
, ("BATableFreeOriEntry numAsOriginator= %ld\n", pAd
->BATable
.numAsRecipient
));
825 // Erase Bitmap flag.
828 ASSERT(pAd
->BATable
.numAsOriginator
!= 0);
830 pAd
->BATable
.numAsOriginator
-= 1;
832 pBAEntry
->ORI_BA_Status
= Originator_NONE
;
834 NdisReleaseSpinLock(&pAd
->BATabLock
);
839 VOID
BATableFreeRecEntry(
840 IN PRTMP_ADAPTER pAd
,
843 BA_REC_ENTRY
*pBAEntry
= NULL
;
844 MAC_TABLE_ENTRY
*pEntry
;
847 if ((Idx
== 0) || (Idx
>= MAX_LEN_OF_BA_REC_TABLE
))
850 pBAEntry
=&pAd
->BATable
.BARecEntry
[Idx
];
852 if (pBAEntry
->REC_BA_Status
!= Recipient_NONE
)
854 pEntry
= &pAd
->MacTab
.Content
[pBAEntry
->Wcid
];
855 pEntry
->BARecWcidArray
[pBAEntry
->TID
] = 0;
857 NdisAcquireSpinLock(&pAd
->BATabLock
);
859 ASSERT(pAd
->BATable
.numAsRecipient
!= 0);
861 pAd
->BATable
.numAsRecipient
-= 1;
863 pBAEntry
->REC_BA_Status
= Recipient_NONE
;
864 NdisReleaseSpinLock(&pAd
->BATabLock
);
869 VOID
BAOriSessionTearDown(
870 IN OUT PRTMP_ADAPTER pAd
,
874 IN BOOLEAN bForceSend
)
877 BA_ORI_ENTRY
*pBAEntry
;
880 if (Wcid
>= MAX_LEN_OF_MAC_TABLE
)
886 // Locate corresponding BA Originator Entry in BA Table with the (pAddr,TID).
888 Idx
= pAd
->MacTab
.Content
[Wcid
].BAOriWcidArray
[TID
];
889 if ((Idx
== 0) || (Idx
>= MAX_LEN_OF_BA_ORI_TABLE
))
891 if (bForceSend
== TRUE
)
893 // force send specified TID DelBA
894 MLME_DELBA_REQ_STRUCT DelbaReq
;
895 MLME_QUEUE_ELEM
*Elem
= (MLME_QUEUE_ELEM
*) kmalloc(sizeof(MLME_QUEUE_ELEM
), MEM_ALLOC_FLAG
);
897 NdisZeroMemory(&DelbaReq
, sizeof(DelbaReq
));
898 NdisZeroMemory(Elem
, sizeof(MLME_QUEUE_ELEM
));
900 COPY_MAC_ADDR(DelbaReq
.Addr
, pAd
->MacTab
.Content
[Wcid
].Addr
);
901 DelbaReq
.Wcid
= Wcid
;
903 DelbaReq
.Initiator
= ORIGINATOR
;
905 Elem
->MsgLen
= sizeof(DelbaReq
);
906 NdisMoveMemory(Elem
->Msg
, &DelbaReq
, sizeof(DelbaReq
));
907 MlmeDELBAAction(pAd
, Elem
);
910 MlmeEnqueue(pAd
, ACTION_STATE_MACHINE
, MT2_MLME_ORI_DELBA_CATE
, sizeof(MLME_DELBA_REQ_STRUCT
), (PVOID
)&DelbaReq
);
911 RT28XX_MLME_HANDLER(pAd
);
918 DBGPRINT(RT_DEBUG_TRACE
,("%s===>Wcid=%d.TID=%d \n", __func__
, Wcid
, TID
));
920 pBAEntry
= &pAd
->BATable
.BAOriEntry
[Idx
];
921 DBGPRINT(RT_DEBUG_TRACE
,("\t===>Idx = %ld, Wcid=%d.TID=%d, ORI_BA_Status = %d \n", Idx
, Wcid
, TID
, pBAEntry
->ORI_BA_Status
));
923 // Prepare DelBA action frame and send to the peer.
925 if ((bPassive
== FALSE
) && (TID
== pBAEntry
->TID
) && (pBAEntry
->ORI_BA_Status
== Originator_Done
))
927 MLME_DELBA_REQ_STRUCT DelbaReq
;
928 MLME_QUEUE_ELEM
*Elem
= (MLME_QUEUE_ELEM
*) kmalloc(sizeof(MLME_QUEUE_ELEM
), MEM_ALLOC_FLAG
);
930 NdisZeroMemory(&DelbaReq
, sizeof(DelbaReq
));
931 NdisZeroMemory(Elem
, sizeof(MLME_QUEUE_ELEM
));
933 COPY_MAC_ADDR(DelbaReq
.Addr
, pAd
->MacTab
.Content
[Wcid
].Addr
);
934 DelbaReq
.Wcid
= Wcid
;
935 DelbaReq
.TID
= pBAEntry
->TID
;
936 DelbaReq
.Initiator
= ORIGINATOR
;
938 Elem
->MsgLen
= sizeof(DelbaReq
);
939 NdisMoveMemory(Elem
->Msg
, &DelbaReq
, sizeof(DelbaReq
));
940 MlmeDELBAAction(pAd
, Elem
);
943 MlmeEnqueue(pAd
, ACTION_STATE_MACHINE
, MT2_MLME_ORI_DELBA_CATE
, sizeof(MLME_DELBA_REQ_STRUCT
), (PVOID
)&DelbaReq
);
944 RT28XX_MLME_HANDLER(pAd
);
947 RTMPCancelTimer(&pBAEntry
->ORIBATimer
, &Cancelled
);
948 BATableFreeOriEntry(pAd
, Idx
);
952 //BAOriSessionSetUp(pAd, &pAd->MacTab.Content[Wcid], TID, 0, 10000, TRUE);
956 VOID
BARecSessionTearDown(
957 IN OUT PRTMP_ADAPTER pAd
,
963 BA_REC_ENTRY
*pBAEntry
;
965 if (Wcid
>= MAX_LEN_OF_MAC_TABLE
)
971 // Locate corresponding BA Originator Entry in BA Table with the (pAddr,TID).
973 Idx
= pAd
->MacTab
.Content
[Wcid
].BARecWcidArray
[TID
];
977 DBGPRINT(RT_DEBUG_TRACE
,("%s===>Wcid=%d.TID=%d \n", __func__
, Wcid
, TID
));
980 pBAEntry
= &pAd
->BATable
.BARecEntry
[Idx
];
981 DBGPRINT(RT_DEBUG_TRACE
,("\t===>Idx = %ld, Wcid=%d.TID=%d, REC_BA_Status = %d \n", Idx
, Wcid
, TID
, pBAEntry
->REC_BA_Status
));
983 // Prepare DelBA action frame and send to the peer.
985 if ((TID
== pBAEntry
->TID
) && (pBAEntry
->REC_BA_Status
== Recipient_Accept
))
987 MLME_DELBA_REQ_STRUCT DelbaReq
;
989 MLME_QUEUE_ELEM
*Elem
= (MLME_QUEUE_ELEM
*) kmalloc(sizeof(MLME_QUEUE_ELEM
), MEM_ALLOC_FLAG
);
993 RTMPCancelTimer(&pBAEntry
->RECBATimer
, &Cancelled
);
996 // 1. Send DELBA Action Frame
998 if (bPassive
== FALSE
)
1000 NdisZeroMemory(&DelbaReq
, sizeof(DelbaReq
));
1001 NdisZeroMemory(Elem
, sizeof(MLME_QUEUE_ELEM
));
1003 COPY_MAC_ADDR(DelbaReq
.Addr
, pAd
->MacTab
.Content
[Wcid
].Addr
);
1004 DelbaReq
.Wcid
= Wcid
;
1006 DelbaReq
.Initiator
= RECIPIENT
;
1008 Elem
->MsgLen
= sizeof(DelbaReq
);
1009 NdisMoveMemory(Elem
->Msg
, &DelbaReq
, sizeof(DelbaReq
));
1010 MlmeDELBAAction(pAd
, Elem
);
1013 MlmeEnqueue(pAd
, ACTION_STATE_MACHINE
, MT2_MLME_ORI_DELBA_CATE
, sizeof(MLME_DELBA_REQ_STRUCT
), (PVOID
)&DelbaReq
);
1014 RT28XX_MLME_HANDLER(pAd
);
1020 // 2. Free resource of BA session
1022 // flush all pending reordering mpdus
1023 ba_refresh_reordering_mpdus(pAd
, pBAEntry
);
1025 NdisAcquireSpinLock(&pAd
->BATabLock
);
1027 // Erase Bitmap flag.
1028 pBAEntry
->LastIndSeq
= RESET_RCV_SEQ
;
1029 pBAEntry
->BAWinSize
= 0;
1030 // Erase Bitmap flag at software mactable
1031 pAd
->MacTab
.Content
[Wcid
].RXBAbitmap
&= (~(1<<(pBAEntry
->TID
)));
1032 pAd
->MacTab
.Content
[Wcid
].BARecWcidArray
[TID
] = 0;
1034 RT28XX_DEL_BA_SESSION_FROM_ASIC(pAd
, Wcid
, TID
);
1036 NdisReleaseSpinLock(&pAd
->BATabLock
);
1040 BATableFreeRecEntry(pAd
, Idx
);
1043 VOID
BASessionTearDownALL(
1044 IN OUT PRTMP_ADAPTER pAd
,
1049 for (i
=0; i
<NUM_OF_TID
; i
++)
1051 BAOriSessionTearDown(pAd
, Wcid
, i
, FALSE
, FALSE
);
1052 BARecSessionTearDown(pAd
, Wcid
, i
, FALSE
);
1058 ==========================================================================
1060 Retry sending ADDBA Reqest.
1062 IRQL = DISPATCH_LEVEL
1065 p8023Header: if this is already 802.3 format, p8023Header is NULL
1067 Return : TRUE if put into rx reordering buffer, shouldn't indicaterxhere.
1068 FALSE , then continue indicaterx at this moment.
1069 ==========================================================================
1071 VOID
BAOriSessionSetupTimeout(
1072 IN PVOID SystemSpecific1
,
1073 IN PVOID FunctionContext
,
1074 IN PVOID SystemSpecific2
,
1075 IN PVOID SystemSpecific3
)
1077 BA_ORI_ENTRY
*pBAEntry
= (BA_ORI_ENTRY
*)FunctionContext
;
1078 MAC_TABLE_ENTRY
*pEntry
;
1081 if (pBAEntry
== NULL
)
1084 pAd
= pBAEntry
->pAdapter
;
1086 #ifdef CONFIG_STA_SUPPORT
1087 IF_DEV_CONFIG_OPMODE_ON_STA(pAd
)
1089 // Do nothing if monitor mode is on
1090 if (MONITOR_ON(pAd
))
1093 #endif // CONFIG_STA_SUPPORT //
1095 pEntry
= &pAd
->MacTab
.Content
[pBAEntry
->Wcid
];
1097 if ((pBAEntry
->ORI_BA_Status
== Originator_WaitRes
) && (pBAEntry
->Token
< ORI_SESSION_MAX_RETRY
))
1099 MLME_ADDBA_REQ_STRUCT AddbaReq
;
1101 NdisZeroMemory(&AddbaReq
, sizeof(AddbaReq
));
1102 COPY_MAC_ADDR(AddbaReq
.pAddr
, pEntry
->Addr
);
1103 AddbaReq
.Wcid
= (UCHAR
)(pEntry
->Aid
);
1104 AddbaReq
.TID
= pBAEntry
->TID
;
1105 AddbaReq
.BaBufSize
= pAd
->CommonCfg
.BACapability
.field
.RxBAWinLimit
;
1106 AddbaReq
.TimeOutValue
= 0;
1107 AddbaReq
.Token
= pBAEntry
->Token
;
1108 MlmeEnqueue(pAd
, ACTION_STATE_MACHINE
, MT2_MLME_ADD_BA_CATE
, sizeof(MLME_ADDBA_REQ_STRUCT
), (PVOID
)&AddbaReq
);
1109 RT28XX_MLME_HANDLER(pAd
);
1110 DBGPRINT(RT_DEBUG_TRACE
,("BA Ori Session Timeout(%d) : Send ADD BA again\n", pBAEntry
->Token
));
1113 RTMPSetTimer(&pBAEntry
->ORIBATimer
, ORI_BA_SESSION_TIMEOUT
);
1117 BATableFreeOriEntry(pAd
, pEntry
->BAOriWcidArray
[pBAEntry
->TID
]);
1122 ==========================================================================
1124 Retry sending ADDBA Reqest.
1126 IRQL = DISPATCH_LEVEL
1129 p8023Header: if this is already 802.3 format, p8023Header is NULL
1131 Return : TRUE if put into rx reordering buffer, shouldn't indicaterxhere.
1132 FALSE , then continue indicaterx at this moment.
1133 ==========================================================================
1135 VOID
BARecSessionIdleTimeout(
1136 IN PVOID SystemSpecific1
,
1137 IN PVOID FunctionContext
,
1138 IN PVOID SystemSpecific2
,
1139 IN PVOID SystemSpecific3
)
1142 BA_REC_ENTRY
*pBAEntry
= (BA_REC_ENTRY
*)FunctionContext
;
1146 if (pBAEntry
== NULL
)
1149 if ((pBAEntry
->REC_BA_Status
== Recipient_Accept
))
1151 NdisGetSystemUpTime(&Now32
);
1153 if (RTMP_TIME_AFTER((unsigned long)Now32
, (unsigned long)(pBAEntry
->LastIndSeqAtTimer
+ REC_BA_SESSION_IDLE_TIMEOUT
)))
1155 pAd
= pBAEntry
->pAdapter
;
1156 // flush all pending reordering mpdus
1157 ba_refresh_reordering_mpdus(pAd
, pBAEntry
);
1158 printk("%ld: REC BA session Timeout\n", Now32
);
1164 VOID
PeerAddBAReqAction(
1165 IN PRTMP_ADAPTER pAd
,
1166 IN MLME_QUEUE_ELEM
*Elem
)
1173 FRAME_ADDBA_RSP ADDframe
;
1174 PUCHAR pOutBuffer
= NULL
;
1175 NDIS_STATUS NStatus
;
1176 PFRAME_ADDBA_REQ pAddreqFrame
= NULL
;
1180 PMAC_TABLE_ENTRY pMacEntry
;
1182 DBGPRINT(RT_DEBUG_TRACE
, ("%s ==> (Wcid = %d)\n", __func__
, Elem
->Wcid
));
1184 //hex_dump("AddBAReq", Elem->Msg, Elem->MsgLen);
1186 //ADDBA Request from unknown peer, ignore this.
1187 if (Elem
->Wcid
>= MAX_LEN_OF_MAC_TABLE
)
1190 pMacEntry
= &pAd
->MacTab
.Content
[Elem
->Wcid
];
1191 DBGPRINT(RT_DEBUG_TRACE
,("BA - PeerAddBAReqAction----> \n"));
1192 ptemp
= (PULONG
)Elem
->Msg
;
1193 //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)));
1195 if (PeerAddBAReqActionSanity(pAd
, Elem
->Msg
, Elem
->MsgLen
, pAddr
))
1198 if ((pAd
->CommonCfg
.bBADecline
== FALSE
) && IS_HT_STA(pMacEntry
))
1200 pAddreqFrame
= (PFRAME_ADDBA_REQ
)(&Elem
->Msg
[0]);
1201 printk("Rcv Wcid(%d) AddBAReq\n", Elem
->Wcid
);
1202 if (BARecSessionAdd(pAd
, &pAd
->MacTab
.Content
[Elem
->Wcid
], pAddreqFrame
))
1205 Status
= 38; // more parameters have invalid values
1209 Status
= 37; // the request has been declined.
1213 if (pAd
->MacTab
.Content
[Elem
->Wcid
].ValidAsCLI
)
1214 ASSERT(pAd
->MacTab
.Content
[Elem
->Wcid
].Sst
== SST_ASSOC
);
1216 pAddreqFrame
= (PFRAME_ADDBA_REQ
)(&Elem
->Msg
[0]);
1217 // 2. Always send back ADDBA Response
1218 NStatus
= MlmeAllocateMemory(pAd
, &pOutBuffer
); //Get an unused nonpaged memory
1219 if (NStatus
!= NDIS_STATUS_SUCCESS
)
1221 DBGPRINT(RT_DEBUG_TRACE
,("ACTION - PeerBAAction() allocate memory failed \n"));
1225 NdisZeroMemory(&ADDframe
, sizeof(FRAME_ADDBA_RSP
));
1226 // 2-1. Prepare ADDBA Response frame.
1227 #ifdef CONFIG_STA_SUPPORT
1228 IF_DEV_CONFIG_OPMODE_ON_STA(pAd
)
1231 ActHeaderInit(pAd
, &ADDframe
.Hdr
, pAddr
, pAd
->CurrentAddress
, pAd
->CommonCfg
.Bssid
);
1233 ActHeaderInit(pAd
, &ADDframe
.Hdr
, pAd
->CommonCfg
.Bssid
, pAd
->CurrentAddress
, pAddr
);
1235 #endif // CONFIG_STA_SUPPORT //
1236 ADDframe
.Category
= CATEGORY_BA
;
1237 ADDframe
.Action
= ADDBA_RESP
;
1238 ADDframe
.Token
= pAddreqFrame
->Token
;
1239 // What is the Status code?? need to check.
1240 ADDframe
.StatusCode
= Status
;
1241 ADDframe
.BaParm
.BAPolicy
= IMMED_BA
;
1242 ADDframe
.BaParm
.AMSDUSupported
= 0;
1243 ADDframe
.BaParm
.TID
= pAddreqFrame
->BaParm
.TID
;
1244 ADDframe
.BaParm
.BufSize
= min(((UCHAR
)pAddreqFrame
->BaParm
.BufSize
), (UCHAR
)pAd
->CommonCfg
.BACapability
.field
.RxBAWinLimit
);
1245 if (ADDframe
.BaParm
.BufSize
== 0)
1247 ADDframe
.BaParm
.BufSize
= 64;
1249 ADDframe
.TimeOutValue
= 0; //pAddreqFrame->TimeOutValue;
1251 *(USHORT
*)(&ADDframe
.BaParm
) = cpu2le16(*(USHORT
*)(&ADDframe
.BaParm
));
1252 ADDframe
.StatusCode
= cpu2le16(ADDframe
.StatusCode
);
1253 ADDframe
.TimeOutValue
= cpu2le16(ADDframe
.TimeOutValue
);
1255 MakeOutgoingFrame(pOutBuffer
, &FrameLen
,
1256 sizeof(FRAME_ADDBA_RSP
), &ADDframe
,
1258 MiniportMMRequest(pAd
, QID_AC_BE
, pOutBuffer
, FrameLen
);
1259 MlmeFreeMemory(pAd
, pOutBuffer
);
1261 DBGPRINT(RT_DEBUG_TRACE
, ("%s(%d): TID(%d), BufSize(%d) <== \n", __func__
, Elem
->Wcid
, ADDframe
.BaParm
.TID
,
1262 ADDframe
.BaParm
.BufSize
));
1266 VOID
PeerAddBARspAction(
1267 IN PRTMP_ADAPTER pAd
,
1268 IN MLME_QUEUE_ELEM
*Elem
)
1272 //PUCHAR pOutBuffer = NULL;
1273 PFRAME_ADDBA_RSP pFrame
= NULL
;
1274 //PBA_ORI_ENTRY pBAEntry;
1276 //ADDBA Response from unknown peer, ignore this.
1277 if (Elem
->Wcid
>= MAX_LEN_OF_MAC_TABLE
)
1280 DBGPRINT(RT_DEBUG_TRACE
, ("%s ==> Wcid(%d)\n", __func__
, Elem
->Wcid
));
1282 //hex_dump("PeerAddBARspAction()", Elem->Msg, Elem->MsgLen);
1284 if (PeerAddBARspActionSanity(pAd
, Elem
->Msg
, Elem
->MsgLen
))
1286 pFrame
= (PFRAME_ADDBA_RSP
)(&Elem
->Msg
[0]);
1288 DBGPRINT(RT_DEBUG_TRACE
, ("\t\t StatusCode = %d\n", pFrame
->StatusCode
));
1289 switch (pFrame
->StatusCode
)
1292 // I want a BAsession with this peer as an originator.
1293 BAOriSessionAdd(pAd
, &pAd
->MacTab
.Content
[Elem
->Wcid
], pFrame
);
1296 // check status == USED ???
1297 BAOriSessionTearDown(pAd
, Elem
->Wcid
, pFrame
->BaParm
.TID
, TRUE
, FALSE
);
1300 // Rcv Decline StatusCode
1301 if ((pFrame
->StatusCode
== 37)
1302 #ifdef CONFIG_STA_SUPPORT
1303 || ((pAd
->OpMode
== OPMODE_STA
) && STA_TGN_WIFI_ON(pAd
) && (pFrame
->StatusCode
!= 0))
1304 #endif // CONFIG_STA_SUPPORT //
1307 pAd
->MacTab
.Content
[Elem
->Wcid
].BADeclineBitmap
|= 1<<pFrame
->BaParm
.TID
;
1312 VOID
PeerDelBAAction(
1313 IN PRTMP_ADAPTER pAd
,
1314 IN MLME_QUEUE_ELEM
*Elem
)
1318 //PUCHAR pOutBuffer = NULL;
1319 PFRAME_DELBA_REQ pDelFrame
= NULL
;
1321 DBGPRINT(RT_DEBUG_TRACE
,("%s ==>\n", __func__
));
1322 //DELBA Request from unknown peer, ignore this.
1323 if (PeerDelBAActionSanity(pAd
, Elem
->Wcid
, Elem
->Msg
, Elem
->MsgLen
))
1325 pDelFrame
= (PFRAME_DELBA_REQ
)(&Elem
->Msg
[0]);
1326 if (pDelFrame
->DelbaParm
.Initiator
== ORIGINATOR
)
1328 DBGPRINT(RT_DEBUG_TRACE
,("BA - PeerDelBAAction----> ORIGINATOR\n"));
1329 BARecSessionTearDown(pAd
, Elem
->Wcid
, pDelFrame
->DelbaParm
.TID
, TRUE
);
1333 DBGPRINT(RT_DEBUG_TRACE
,("BA - PeerDelBAAction----> RECIPIENT, Reason = %d\n", pDelFrame
->ReasonCode
));
1334 //hex_dump("DelBA Frame", pDelFrame, Elem->MsgLen);
1335 BAOriSessionTearDown(pAd
, Elem
->Wcid
, pDelFrame
->DelbaParm
.TID
, TRUE
, FALSE
);
1341 BOOLEAN
CntlEnqueueForRecv(
1342 IN PRTMP_ADAPTER pAd
,
1345 IN PFRAME_BA_REQ pMsg
)
1347 PFRAME_BA_REQ pFrame
= pMsg
;
1348 //PRTMP_REORDERBUF pBuffer;
1349 //PRTMP_REORDERBUF pDmaBuf;
1350 PBA_REC_ENTRY pBAEntry
;
1356 TID
= (UCHAR
)pFrame
->BARControl
.TID
;
1358 DBGPRINT(RT_DEBUG_TRACE
, ("%s(): BAR-Wcid(%ld), Tid (%d)\n", __func__
, Wcid
, TID
));
1359 //hex_dump("BAR", (PCHAR) pFrame, MsgLen);
1360 // Do nothing if the driver is starting halt state.
1361 // This might happen when timer already been fired before cancel timer with mlmehalt
1362 if (RTMP_TEST_FLAG(pAd
, fRTMP_ADAPTER_HALT_IN_PROGRESS
| fRTMP_ADAPTER_NIC_NOT_EXIST
))
1365 // First check the size, it MUST not exceed the mlme queue size
1366 if (MsgLen
> MGMT_DMA_BUFFER_SIZE
)
1368 DBGPRINT_ERR(("CntlEnqueueForRecv: frame too large, size = %ld \n", MsgLen
));
1371 else if (MsgLen
!= sizeof(FRAME_BA_REQ
))
1373 DBGPRINT_ERR(("CntlEnqueueForRecv: BlockAck Request frame length size = %ld incorrect\n", MsgLen
));
1376 else if (MsgLen
!= sizeof(FRAME_BA_REQ
))
1378 DBGPRINT_ERR(("CntlEnqueueForRecv: BlockAck Request frame length size = %ld incorrect\n", MsgLen
));
1382 if ((Wcid
< MAX_LEN_OF_MAC_TABLE
) && (TID
< 8))
1384 // if this receiving packet is from SA that is in our OriEntry. Since WCID <9 has direct mapping. no need search.
1385 Idx
= pAd
->MacTab
.Content
[Wcid
].BARecWcidArray
[TID
];
1386 pBAEntry
= &pAd
->BATable
.BARecEntry
[Idx
];
1393 DBGPRINT(RT_DEBUG_TRACE
, ("BAR(%ld) : Tid (%d) - %04x:%04x\n", Wcid
, TID
, pFrame
->BAStartingSeq
.field
.StartSeq
, pBAEntry
->LastIndSeq
));
1395 if (SEQ_SMALLER(pBAEntry
->LastIndSeq
, pFrame
->BAStartingSeq
.field
.StartSeq
, MAXSEQ
))
1397 //printk("BAR Seq = %x, LastIndSeq = %x\n", pFrame->BAStartingSeq.field.StartSeq, pBAEntry->LastIndSeq);
1398 ba_indicate_reordering_mpdus_le_seq(pAd
, pBAEntry
, pFrame
->BAStartingSeq
.field
.StartSeq
);
1399 pBAEntry
->LastIndSeq
= (pFrame
->BAStartingSeq
.field
.StartSeq
== 0) ? MAXSEQ
:(pFrame
->BAStartingSeq
.field
.StartSeq
-1);
1401 //ba_refresh_reordering_mpdus(pAd, pBAEntry);
1406 Description : Send PSMP Action frame If PSMP mode switches.
1408 VOID
SendPSMPAction(
1409 IN PRTMP_ADAPTER pAd
,
1413 PUCHAR pOutBuffer
= NULL
;
1414 NDIS_STATUS NStatus
;
1416 FRAME_PSMP_ACTION Frame
;
1419 NStatus
= MlmeAllocateMemory(pAd
, &pOutBuffer
); //Get an unused nonpaged memory
1420 if (NStatus
!= NDIS_STATUS_SUCCESS
)
1422 DBGPRINT(RT_DEBUG_ERROR
,("BA - MlmeADDBAAction() allocate memory failed \n"));
1425 #ifdef CONFIG_STA_SUPPORT
1426 IF_DEV_CONFIG_OPMODE_ON_STA(pAd
)
1427 ActHeaderInit(pAd
, &Frame
.Hdr
, pAd
->CommonCfg
.Bssid
, pAd
->CurrentAddress
, pAd
->MacTab
.Content
[Wcid
].Addr
);
1428 #endif // CONFIG_STA_SUPPORT //
1430 Frame
.Category
= CATEGORY_HT
;
1431 Frame
.Action
= SMPS_ACTION
;
1444 MakeOutgoingFrame(pOutBuffer
, &FrameLen
,
1445 sizeof(FRAME_PSMP_ACTION
), &Frame
,
1447 MiniportMMRequest(pAd
, QID_AC_BE
, pOutBuffer
, FrameLen
);
1448 MlmeFreeMemory(pAd
, pOutBuffer
);
1449 DBGPRINT(RT_DEBUG_ERROR
,("HT - SendPSMPAction( %d ) \n", Frame
.Psmp
));
1453 #define RADIO_MEASUREMENT_REQUEST_ACTION 0
1455 typedef struct PACKED
1457 UCHAR RegulatoryClass
;
1458 UCHAR ChannelNumber
;
1459 USHORT RandomInterval
;
1460 USHORT MeasurementDuration
;
1461 UCHAR MeasurementMode
;
1462 UCHAR BSSID
[MAC_ADDR_LEN
];
1463 UCHAR ReportingCondition
;
1465 UCHAR SSIDIE
[2]; // 2 byte
1468 typedef struct PACKED
1480 void convert_reordering_packet_to_preAMSDU_or_802_3_packet(
1481 IN PRTMP_ADAPTER pAd
,
1483 IN UCHAR FromWhichBSSID
)
1485 PNDIS_PACKET pRxPkt
;
1486 UCHAR Header802_3
[LENGTH_802_3
];
1488 // 1. get 802.3 Header
1490 // a. pointer pRxBlk->pData to payload
1491 // b. modify pRxBlk->DataSize
1493 #ifdef CONFIG_STA_SUPPORT
1494 IF_DEV_CONFIG_OPMODE_ON_STA(pAd
)
1495 RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk
, Header802_3
);
1496 #endif // CONFIG_STA_SUPPORT //
1498 ASSERT(pRxBlk
->pRxPacket
);
1499 pRxPkt
= RTPKT_TO_OSPKT(pRxBlk
->pRxPacket
);
1501 RTPKT_TO_OSPKT(pRxPkt
)->dev
= get_netdev_from_bssid(pAd
, FromWhichBSSID
);
1502 RTPKT_TO_OSPKT(pRxPkt
)->data
= pRxBlk
->pData
;
1503 RTPKT_TO_OSPKT(pRxPkt
)->len
= pRxBlk
->DataSize
;
1504 RTPKT_TO_OSPKT(pRxPkt
)->tail
= RTPKT_TO_OSPKT(pRxPkt
)->data
+ RTPKT_TO_OSPKT(pRxPkt
)->len
;
1507 // copy 802.3 header, if necessary
1509 if (!RX_BLK_TEST_FLAG(pRxBlk
, fRX_AMSDU
))
1512 #ifdef CONFIG_STA_SUPPORT
1513 IF_DEV_CONFIG_OPMODE_ON_STA(pAd
)
1516 NdisMoveMemory(skb_push(pRxPkt
, LENGTH_802_3
), Header802_3
, LENGTH_802_3
);
1519 #endif // CONFIG_STA_SUPPORT //
1524 #define INDICATE_LEGACY_OR_AMSDU(_pAd, _pRxBlk, _fromWhichBSSID) \
1527 if (RX_BLK_TEST_FLAG(_pRxBlk, fRX_AMSDU)) \
1529 Indicate_AMSDU_Packet(_pAd, _pRxBlk, _fromWhichBSSID); \
1531 else if (RX_BLK_TEST_FLAG(_pRxBlk, fRX_EAP)) \
1533 Indicate_EAPOL_Packet(_pAd, _pRxBlk, _fromWhichBSSID); \
1537 Indicate_Legacy_Packet(_pAd, _pRxBlk, _fromWhichBSSID); \
1543 static VOID
ba_enqueue_reordering_packet(
1544 IN PRTMP_ADAPTER pAd
,
1545 IN PBA_REC_ENTRY pBAEntry
,
1547 IN UCHAR FromWhichBSSID
)
1549 struct reordering_mpdu
*mpdu_blk
;
1550 UINT16 Sequence
= (UINT16
) pRxBlk
->pHeader
->Sequence
;
1552 mpdu_blk
= ba_mpdu_blk_alloc(pAd
);
1553 if (mpdu_blk
!= NULL
)
1555 // Write RxD buffer address & allocated buffer length
1556 NdisAcquireSpinLock(&pBAEntry
->RxReRingLock
);
1558 mpdu_blk
->Sequence
= Sequence
;
1560 mpdu_blk
->bAMSDU
= RX_BLK_TEST_FLAG(pRxBlk
, fRX_AMSDU
);
1562 convert_reordering_packet_to_preAMSDU_or_802_3_packet(pAd
, pRxBlk
, FromWhichBSSID
);
1564 STATS_INC_RX_PACKETS(pAd
, FromWhichBSSID
);
1567 // it is necessary for reordering packet to record
1568 // which BSS it come from
1570 RTMP_SET_PACKET_IF(pRxBlk
->pRxPacket
, FromWhichBSSID
);
1572 mpdu_blk
->pPacket
= pRxBlk
->pRxPacket
;
1574 if (ba_reordering_mpdu_insertsorted(&pBAEntry
->list
, mpdu_blk
) == FALSE
)
1576 // had been already within reordering list
1578 RELEASE_NDIS_PACKET(pAd
, pRxBlk
->pRxPacket
, NDIS_STATUS_SUCCESS
);
1579 ba_mpdu_blk_free(pAd
, mpdu_blk
);
1582 ASSERT((0<= pBAEntry
->list
.qlen
) && (pBAEntry
->list
.qlen
<= pBAEntry
->BAWinSize
));
1583 NdisReleaseSpinLock(&pBAEntry
->RxReRingLock
);
1588 DBGPRINT(RT_DEBUG_ERROR
, ("!!! (%d:%d) Can't allocate reordering mpdu blk\n",
1589 blk_count
, pBAEntry
->list
.qlen
));
1591 DBGPRINT(RT_DEBUG_ERROR
, ("!!! (%d) Can't allocate reordering mpdu blk\n",
1592 pBAEntry
->list
.qlen
));
1595 * flush all pending reordering mpdus
1596 * and receving mpdu to upper layer
1597 * make tcp/ip to take care reordering mechanism
1599 //ba_refresh_reordering_mpdus(pAd, pBAEntry);
1600 ba_indicate_reordering_mpdus_le_seq(pAd
, pBAEntry
, Sequence
);
1602 pBAEntry
->LastIndSeq
= Sequence
;
1603 INDICATE_LEGACY_OR_AMSDU(pAd
, pRxBlk
, FromWhichBSSID
);
1609 ==========================================================================
1611 Indicate this packet to upper layer or put it into reordering buffer
1614 pRxBlk : carry necessary packet info 802.11 format
1615 FromWhichBSSID : the packet received from which BSS
1621 the packet queued into reordering buffer need to cover to 802.3 format
1623 ==========================================================================
1626 VOID
Indicate_AMPDU_Packet(
1627 IN PRTMP_ADAPTER pAd
,
1629 IN UCHAR FromWhichBSSID
)
1632 PBA_REC_ENTRY pBAEntry
= NULL
;
1633 UINT16 Sequence
= pRxBlk
->pHeader
->Sequence
;
1635 UCHAR Wcid
= pRxBlk
->pRxWI
->WirelessCliID
;
1636 UCHAR TID
= pRxBlk
->pRxWI
->TID
;
1639 if (!RX_BLK_TEST_FLAG(pRxBlk
, fRX_AMSDU
) && (pRxBlk
->DataSize
> MAX_RX_PKT_LEN
))
1641 #if 0 // sample take off, no use
1642 static int err_size
;
1645 if (err_size
> 20) {
1646 printk("AMPDU DataSize = %d\n", pRxBlk
->DataSize
);
1647 hex_dump("802.11 Header", (UCHAR
*)pRxBlk
->pHeader
, 24);
1648 hex_dump("Payload", pRxBlk
->pData
, 64);
1653 RELEASE_NDIS_PACKET(pAd
, pRxBlk
->pRxPacket
, NDIS_STATUS_FAILURE
);
1659 /* Rec BA Session had been torn down */
1660 INDICATE_LEGACY_OR_AMSDU(pAd
, pRxBlk
, FromWhichBSSID
);
1664 if (Wcid
< MAX_LEN_OF_MAC_TABLE
)
1666 Idx
= pAd
->MacTab
.Content
[Wcid
].BARecWcidArray
[TID
];
1669 /* Rec BA Session had been torn down */
1670 INDICATE_LEGACY_OR_AMSDU(pAd
, pRxBlk
, FromWhichBSSID
);
1673 pBAEntry
= &pAd
->BATable
.BARecEntry
[Idx
];
1680 RELEASE_NDIS_PACKET(pAd
, pRxBlk
->pRxPacket
, NDIS_STATUS_FAILURE
);
1686 // update last rx time
1687 NdisGetSystemUpTime(&Now32
);
1689 pBAEntry
->rcvSeq
= Sequence
;
1692 ba_flush_reordering_timeout_mpdus(pAd
, pBAEntry
, Now32
);
1693 pBAEntry
->LastIndSeqAtTimer
= Now32
;
1696 // Reset Last Indicate Sequence
1698 if (pBAEntry
->LastIndSeq
== RESET_RCV_SEQ
)
1700 ASSERT((pBAEntry
->list
.qlen
== 0) && (pBAEntry
->list
.next
== NULL
));
1702 // reset rcv sequence of BA session
1703 pBAEntry
->LastIndSeq
= Sequence
;
1704 pBAEntry
->LastIndSeqAtTimer
= Now32
;
1705 INDICATE_LEGACY_OR_AMSDU(pAd
, pRxBlk
, FromWhichBSSID
);
1711 // I. Check if in order.
1713 if (SEQ_STEPONE(Sequence
, pBAEntry
->LastIndSeq
, MAXSEQ
))
1717 pBAEntry
->LastIndSeq
= Sequence
;
1718 INDICATE_LEGACY_OR_AMSDU(pAd
, pRxBlk
, FromWhichBSSID
);
1719 LastIndSeq
= ba_indicate_reordering_mpdus_in_order(pAd
, pBAEntry
, pBAEntry
->LastIndSeq
);
1720 if (LastIndSeq
!= RESET_RCV_SEQ
)
1722 pBAEntry
->LastIndSeq
= LastIndSeq
;
1724 pBAEntry
->LastIndSeqAtTimer
= Now32
;
1727 // II. Drop Duplicated Packet
1729 else if (Sequence
== pBAEntry
->LastIndSeq
)
1732 // drop and release packet
1733 pBAEntry
->nDropPacket
++;
1734 RELEASE_NDIS_PACKET(pAd
, pRxBlk
->pRxPacket
, NDIS_STATUS_FAILURE
);
1737 // III. Drop Old Received Packet
1739 else if (SEQ_SMALLER(Sequence
, pBAEntry
->LastIndSeq
, MAXSEQ
))
1742 // drop and release packet
1743 pBAEntry
->nDropPacket
++;
1744 RELEASE_NDIS_PACKET(pAd
, pRxBlk
->pRxPacket
, NDIS_STATUS_FAILURE
);
1747 // IV. Receive Sequence within Window Size
1749 else if (SEQ_SMALLER(Sequence
, (((pBAEntry
->LastIndSeq
+pBAEntry
->BAWinSize
+1)) & MAXSEQ
), MAXSEQ
))
1751 ba_enqueue_reordering_packet(pAd
, pBAEntry
, pRxBlk
, FromWhichBSSID
);
1754 // V. Receive seq surpasses Win(lastseq + nMSDU). So refresh all reorder buffer
1759 ba_refresh_reordering_mpdus(pAd
, pBAEntry
);
1760 INDICATE_LEGACY_OR_AMSDU(pAd
, pRxBlk
, FromWhichBSSID
);
1762 LONG WinStartSeq
, TmpSeq
;
1765 TmpSeq
= Sequence
- (pBAEntry
->BAWinSize
) -1;
1768 TmpSeq
= (MAXSEQ
+1) + TmpSeq
;
1770 WinStartSeq
= (TmpSeq
+1) & MAXSEQ
;
1771 ba_indicate_reordering_mpdus_le_seq(pAd
, pBAEntry
, WinStartSeq
);
1772 pBAEntry
->LastIndSeq
= WinStartSeq
; //TmpSeq;
1774 pBAEntry
->LastIndSeqAtTimer
= Now32
;
1776 ba_enqueue_reordering_packet(pAd
, pBAEntry
, pRxBlk
, FromWhichBSSID
);
1778 TmpSeq
= ba_indicate_reordering_mpdus_in_order(pAd
, pBAEntry
, pBAEntry
->LastIndSeq
);
1779 if (TmpSeq
!= RESET_RCV_SEQ
)
1781 pBAEntry
->LastIndSeq
= TmpSeq
;
1787 #endif // DOT11_N_SUPPORT //