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"
29 #include <linux/kernel.h>
31 #define BA_ORI_INIT_SEQ (pEntry->TxSeq[TID]) /*1 // initial sequence number of BA session */
33 #define ORI_SESSION_MAX_RETRY 8
34 #define ORI_BA_SESSION_TIMEOUT (2000) /* ms */
35 #define REC_BA_SESSION_IDLE_TIMEOUT (1000) /* ms */
37 #define REORDERING_PACKET_TIMEOUT ((100 * OS_HZ)/1000) /* system ticks -- 100 ms */
38 #define MAX_REORDERING_PACKET_TIMEOUT ((3000 * OS_HZ)/1000) /* system ticks -- 100 ms */
40 #define RESET_RCV_SEQ (0xFFFF)
42 static void ba_mpdu_blk_free(struct rt_rtmp_adapter
*pAd
,
43 struct reordering_mpdu
*mpdu_blk
);
45 struct rt_ba_ori_entry
*BATableAllocOriEntry(struct rt_rtmp_adapter
*pAd
, u16
* Idx
);
47 struct rt_ba_rec_entry
*BATableAllocRecEntry(struct rt_rtmp_adapter
*pAd
, u16
* Idx
);
49 void BAOriSessionSetupTimeout(void *SystemSpecific1
,
50 void *FunctionContext
,
51 void *SystemSpecific2
,
52 void *SystemSpecific3
);
54 void BARecSessionIdleTimeout(void *SystemSpecific1
,
55 void *FunctionContext
,
56 void *SystemSpecific2
,
57 void *SystemSpecific3
);
59 BUILD_TIMER_FUNCTION(BAOriSessionSetupTimeout
);
60 BUILD_TIMER_FUNCTION(BARecSessionIdleTimeout
);
62 #define ANNOUNCE_REORDERING_PACKET(_pAd, _mpdu_blk) \
63 Announce_Reordering_Packet(_pAd, _mpdu_blk);
65 void BA_MaxWinSizeReasign(struct rt_rtmp_adapter
*pAd
,
66 struct rt_mac_table_entry
*pEntryPeer
, u8
* pWinSize
)
70 if (pAd
->MACVersion
>= RALINK_2883_VERSION
) /* 3*3 */
72 if (pAd
->MACVersion
>= RALINK_3070_VERSION
) {
73 if (pEntryPeer
->WepStatus
!=
74 Ndis802_11EncryptionDisabled
)
75 MaxSize
= 7; /* for non-open mode */
80 } else if (pAd
->MACVersion
>= RALINK_2880E_VERSION
) /* 2880 e */
82 if (pEntryPeer
->WepStatus
!= Ndis802_11EncryptionDisabled
)
83 MaxSize
= 7; /* for non-open mode */
89 DBGPRINT(RT_DEBUG_TRACE
, ("ba> Win Size = %d, Max Size = %d\n",
92 if ((*pWinSize
) > MaxSize
) {
93 DBGPRINT(RT_DEBUG_TRACE
,
94 ("ba> reassign max win size from %d to %d\n",
101 void Announce_Reordering_Packet(struct rt_rtmp_adapter
*pAd
,
102 IN
struct reordering_mpdu
*mpdu
)
106 pPacket
= mpdu
->pPacket
;
110 BA_Reorder_AMSDU_Announce(pAd
, pPacket
);
113 /* pass this 802.3 packet to upper layer or forward this packet to WM directly */
116 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd
, pPacket
,
117 RTMP_GET_PACKET_IF(pPacket
));
122 * Insert a reordering mpdu into sorted linked list by sequence no.
124 BOOLEAN
ba_reordering_mpdu_insertsorted(struct reordering_list
*list
,
125 struct reordering_mpdu
*mpdu
)
128 struct reordering_mpdu
**ppScan
= &list
->next
;
130 while (*ppScan
!= NULL
) {
131 if (SEQ_SMALLER((*ppScan
)->Sequence
, mpdu
->Sequence
, MAXSEQ
)) {
132 ppScan
= &(*ppScan
)->next
;
133 } else if ((*ppScan
)->Sequence
== mpdu
->Sequence
) {
134 /* give up this duplicated frame */
142 mpdu
->next
= *ppScan
;
149 * caller lock critical section if necessary
151 static inline void ba_enqueue(struct reordering_list
*list
,
152 struct reordering_mpdu
*mpdu_blk
)
155 mpdu_blk
->next
= list
->next
;
156 list
->next
= mpdu_blk
;
160 * caller lock critical section if necessary
162 static inline struct reordering_mpdu
*ba_dequeue(struct reordering_list
*list
)
164 struct reordering_mpdu
*mpdu_blk
= NULL
;
170 mpdu_blk
= list
->next
;
172 list
->next
= mpdu_blk
->next
;
173 mpdu_blk
->next
= NULL
;
179 static inline struct reordering_mpdu
*ba_reordering_mpdu_dequeue(struct
183 return (ba_dequeue(list
));
186 static inline struct reordering_mpdu
*ba_reordering_mpdu_probe(struct
196 * free all resource for reordering mechanism
198 void ba_reordering_resource_release(struct rt_rtmp_adapter
*pAd
)
200 struct rt_ba_table
*Tab
;
201 struct rt_ba_rec_entry
*pBAEntry
;
202 struct reordering_mpdu
*mpdu_blk
;
207 /* I. release all pending reordering packet */
208 NdisAcquireSpinLock(&pAd
->BATabLock
);
209 for (i
= 0; i
< MAX_LEN_OF_BA_REC_TABLE
; i
++) {
210 pBAEntry
= &Tab
->BARecEntry
[i
];
211 if (pBAEntry
->REC_BA_Status
!= Recipient_NONE
) {
213 ba_reordering_mpdu_dequeue(&pBAEntry
->list
))) {
214 ASSERT(mpdu_blk
->pPacket
);
215 RELEASE_NDIS_PACKET(pAd
, mpdu_blk
->pPacket
,
216 NDIS_STATUS_FAILURE
);
217 ba_mpdu_blk_free(pAd
, mpdu_blk
);
221 NdisReleaseSpinLock(&pAd
->BATabLock
);
223 ASSERT(pBAEntry
->list
.qlen
== 0);
224 /* II. free memory of reordering mpdu table */
225 NdisAcquireSpinLock(&pAd
->mpdu_blk_pool
.lock
);
226 os_free_mem(pAd
, pAd
->mpdu_blk_pool
.mem
);
227 NdisReleaseSpinLock(&pAd
->mpdu_blk_pool
.lock
);
231 * Allocate all resource for reordering mechanism
233 BOOLEAN
ba_reordering_resource_init(struct rt_rtmp_adapter
*pAd
, int num
)
237 struct reordering_mpdu
*mpdu_blk
;
238 struct reordering_list
*freelist
;
240 /* allocate spinlock */
241 NdisAllocateSpinLock(&pAd
->mpdu_blk_pool
.lock
);
243 /* initialize freelist */
244 freelist
= &pAd
->mpdu_blk_pool
.freelist
;
245 freelist
->next
= NULL
;
248 DBGPRINT(RT_DEBUG_TRACE
,
249 ("Allocate %d memory for BA reordering\n",
250 (u32
)(num
* sizeof(struct reordering_mpdu
))));
252 /* allocate number of mpdu_blk memory */
253 os_alloc_mem(pAd
, (u8
**) & mem
,
254 (num
* sizeof(struct reordering_mpdu
)));
256 pAd
->mpdu_blk_pool
.mem
= mem
;
259 DBGPRINT(RT_DEBUG_ERROR
,
260 ("Can't Allocate Memory for BA Reordering\n"));
264 /* build mpdu_blk free list */
265 for (i
= 0; i
< num
; i
++) {
267 mpdu_blk
= (struct reordering_mpdu
*)mem
;
268 /* initial mpdu_blk */
269 NdisZeroMemory(mpdu_blk
, sizeof(struct reordering_mpdu
));
271 mem
+= sizeof(struct reordering_mpdu
);
272 /* insert mpdu_blk into freelist */
273 ba_enqueue(freelist
, mpdu_blk
);
279 /*static int blk_count=0; // sample take off, no use */
281 static struct reordering_mpdu
*ba_mpdu_blk_alloc(struct rt_rtmp_adapter
*pAd
)
283 struct reordering_mpdu
*mpdu_blk
;
285 NdisAcquireSpinLock(&pAd
->mpdu_blk_pool
.lock
);
286 mpdu_blk
= ba_dequeue(&pAd
->mpdu_blk_pool
.freelist
);
290 NdisZeroMemory(mpdu_blk
, sizeof(struct reordering_mpdu
));
292 NdisReleaseSpinLock(&pAd
->mpdu_blk_pool
.lock
);
296 static void ba_mpdu_blk_free(struct rt_rtmp_adapter
*pAd
,
297 struct reordering_mpdu
*mpdu_blk
)
301 NdisAcquireSpinLock(&pAd
->mpdu_blk_pool
.lock
);
303 ba_enqueue(&pAd
->mpdu_blk_pool
.freelist
, mpdu_blk
);
304 NdisReleaseSpinLock(&pAd
->mpdu_blk_pool
.lock
);
307 static u16
ba_indicate_reordering_mpdus_in_order(struct rt_rtmp_adapter
*pAd
,
308 struct rt_ba_rec_entry
*pBAEntry
,
311 struct reordering_mpdu
*mpdu_blk
;
312 u16 LastIndSeq
= RESET_RCV_SEQ
;
314 NdisAcquireSpinLock(&pBAEntry
->RxReRingLock
);
316 while ((mpdu_blk
= ba_reordering_mpdu_probe(&pBAEntry
->list
))) {
317 /* find in-order frame */
318 if (!SEQ_STEPONE(mpdu_blk
->Sequence
, StartSeq
, MAXSEQ
)) {
321 /* dequeue in-order frame from reodering list */
322 mpdu_blk
= ba_reordering_mpdu_dequeue(&pBAEntry
->list
);
323 /* pass this frame up */
324 ANNOUNCE_REORDERING_PACKET(pAd
, mpdu_blk
);
325 /* move to next sequence */
326 StartSeq
= mpdu_blk
->Sequence
;
327 LastIndSeq
= StartSeq
;
329 ba_mpdu_blk_free(pAd
, mpdu_blk
);
332 NdisReleaseSpinLock(&pBAEntry
->RxReRingLock
);
334 /* update last indicated sequence */
338 static void ba_indicate_reordering_mpdus_le_seq(struct rt_rtmp_adapter
*pAd
,
339 struct rt_ba_rec_entry
*pBAEntry
,
342 struct reordering_mpdu
*mpdu_blk
;
344 NdisAcquireSpinLock(&pBAEntry
->RxReRingLock
);
345 while ((mpdu_blk
= ba_reordering_mpdu_probe(&pBAEntry
->list
))) {
346 /* find in-order frame */
347 if ((mpdu_blk
->Sequence
== Sequence
)
348 || SEQ_SMALLER(mpdu_blk
->Sequence
, Sequence
, MAXSEQ
)) {
349 /* dequeue in-order frame from reodering list */
350 mpdu_blk
= ba_reordering_mpdu_dequeue(&pBAEntry
->list
);
351 /* pass this frame up */
352 ANNOUNCE_REORDERING_PACKET(pAd
, mpdu_blk
);
354 ba_mpdu_blk_free(pAd
, mpdu_blk
);
359 NdisReleaseSpinLock(&pBAEntry
->RxReRingLock
);
362 static void ba_refresh_reordering_mpdus(struct rt_rtmp_adapter
*pAd
,
363 struct rt_ba_rec_entry
*pBAEntry
)
365 struct reordering_mpdu
*mpdu_blk
;
367 NdisAcquireSpinLock(&pBAEntry
->RxReRingLock
);
369 /* dequeue in-order frame from reodering list */
370 while ((mpdu_blk
= ba_reordering_mpdu_dequeue(&pBAEntry
->list
))) {
371 /* pass this frame up */
372 ANNOUNCE_REORDERING_PACKET(pAd
, mpdu_blk
);
374 pBAEntry
->LastIndSeq
= mpdu_blk
->Sequence
;
375 ba_mpdu_blk_free(pAd
, mpdu_blk
);
377 /* update last indicated sequence */
379 ASSERT(pBAEntry
->list
.qlen
== 0);
380 pBAEntry
->LastIndSeq
= RESET_RCV_SEQ
;
381 NdisReleaseSpinLock(&pBAEntry
->RxReRingLock
);
385 void ba_flush_reordering_timeout_mpdus(struct rt_rtmp_adapter
*pAd
,
386 struct rt_ba_rec_entry
*pBAEntry
,
391 /* if ((RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+REORDERING_PACKET_TIMEOUT)) && */
392 /* (pBAEntry->list.qlen > ((pBAEntry->BAWinSize*7)/8))) //|| */
393 /* (RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+(10*REORDERING_PACKET_TIMEOUT))) && */
394 /* (pBAEntry->list.qlen > (pBAEntry->BAWinSize/8))) */
396 ((unsigned long)Now32
,
397 (unsigned long)(pBAEntry
->LastIndSeqAtTimer
+
398 (MAX_REORDERING_PACKET_TIMEOUT
/ 6)))
399 && (pBAEntry
->list
.qlen
> 1)
401 DBGPRINT(RT_DEBUG_TRACE
,
402 ("timeout[%d] (%08lx-%08lx = %d > %d): %x, flush all!\n ",
403 pBAEntry
->list
.qlen
, Now32
,
404 (pBAEntry
->LastIndSeqAtTimer
),
406 (long)(pBAEntry
->LastIndSeqAtTimer
)),
407 MAX_REORDERING_PACKET_TIMEOUT
, pBAEntry
->LastIndSeq
));
408 ba_refresh_reordering_mpdus(pAd
, pBAEntry
);
409 pBAEntry
->LastIndSeqAtTimer
= Now32
;
412 ((unsigned long)Now32
,
413 (unsigned long)(pBAEntry
->LastIndSeqAtTimer
+
414 (REORDERING_PACKET_TIMEOUT
)))
415 && (pBAEntry
->list
.qlen
> 0)
418 /* force LastIndSeq to shift to LastIndSeq+1 */
420 Sequence
= (pBAEntry
->LastIndSeq
+ 1) & MAXSEQ
;
421 ba_indicate_reordering_mpdus_le_seq(pAd
, pBAEntry
, Sequence
);
422 pBAEntry
->LastIndSeqAtTimer
= Now32
;
423 pBAEntry
->LastIndSeq
= Sequence
;
425 /* indicate in-order mpdus */
428 ba_indicate_reordering_mpdus_in_order(pAd
, pBAEntry
,
430 if (Sequence
!= RESET_RCV_SEQ
) {
431 pBAEntry
->LastIndSeq
= Sequence
;
434 DBGPRINT(RT_DEBUG_OFF
,
435 ("%x, flush one!\n", pBAEntry
->LastIndSeq
));
441 * generate ADDBA request to
442 * set up BA agreement
444 void BAOriSessionSetUp(struct rt_rtmp_adapter
*pAd
,
445 struct rt_mac_table_entry
*pEntry
,
448 unsigned long DelayTime
, IN BOOLEAN isForced
)
450 /*struct rt_mlme_addba_req AddbaReq; */
451 struct rt_ba_ori_entry
*pBAEntry
= NULL
;
455 if ((pAd
->CommonCfg
.BACapability
.field
.AutoBA
!= TRUE
)
456 && (isForced
== FALSE
))
459 /* if this entry is limited to use legacy tx mode, it doesn't generate BA. */
460 if (RTMPStaFixedTxMode(pAd
, pEntry
) != FIXED_TXMODE_HT
)
463 if ((pEntry
->BADeclineBitmap
& (1 << TID
)) && (isForced
== FALSE
)) {
464 /* try again after 3 secs */
466 /* DBGPRINT(RT_DEBUG_TRACE, ("DeCline BA from Peer\n")); */
470 Idx
= pEntry
->BAOriWcidArray
[TID
];
472 /* allocate a BA session */
473 pBAEntry
= BATableAllocOriEntry(pAd
, &Idx
);
474 if (pBAEntry
== NULL
) {
475 DBGPRINT(RT_DEBUG_TRACE
,
476 ("ADDBA - MlmeADDBAAction() allocate BA session failed \n"));
480 pBAEntry
= &pAd
->BATable
.BAOriEntry
[Idx
];
483 if (pBAEntry
->ORI_BA_Status
>= Originator_WaitRes
) {
487 pEntry
->BAOriWcidArray
[TID
] = Idx
;
489 /* Initialize BA session */
490 pBAEntry
->ORI_BA_Status
= Originator_WaitRes
;
491 pBAEntry
->Wcid
= pEntry
->Aid
;
492 pBAEntry
->BAWinSize
= pAd
->CommonCfg
.BACapability
.field
.RxBAWinLimit
;
493 pBAEntry
->Sequence
= BA_ORI_INIT_SEQ
;
494 pBAEntry
->Token
= 1; /* (2008-01-21) Jan Lee recommends it - this token can't be 0 */
496 pBAEntry
->TimeOutValue
= TimeOut
;
497 pBAEntry
->pAdapter
= pAd
;
499 if (!(pEntry
->TXBAbitmap
& (1 << TID
))) {
500 RTMPInitTimer(pAd
, &pBAEntry
->ORIBATimer
,
501 GET_TIMER_FUNCTION(BAOriSessionSetupTimeout
),
504 RTMPCancelTimer(&pBAEntry
->ORIBATimer
, &Cancelled
);
506 /* set timer to send ADDBA request */
507 RTMPSetTimer(&pBAEntry
->ORIBATimer
, DelayTime
);
510 void BAOriSessionAdd(struct rt_rtmp_adapter
*pAd
,
511 struct rt_mac_table_entry
*pEntry
, struct rt_frame_addba_rsp
* pFrame
)
513 struct rt_ba_ori_entry
*pBAEntry
= NULL
;
517 u8
*pOutBuffer2
= NULL
;
519 unsigned long FrameLen
;
520 struct rt_frame_bar FrameBar
;
522 TID
= pFrame
->BaParm
.TID
;
523 Idx
= pEntry
->BAOriWcidArray
[TID
];
524 pBAEntry
= &pAd
->BATable
.BAOriEntry
[Idx
];
526 /* Start fill in parameters. */
527 if ((Idx
!= 0) && (pBAEntry
->TID
== TID
)
528 && (pBAEntry
->ORI_BA_Status
== Originator_WaitRes
)) {
529 pBAEntry
->BAWinSize
=
530 min(pBAEntry
->BAWinSize
, ((u8
)pFrame
->BaParm
.BufSize
));
531 BA_MaxWinSizeReasign(pAd
, pEntry
, &pBAEntry
->BAWinSize
);
533 pBAEntry
->TimeOutValue
= pFrame
->TimeOutValue
;
534 pBAEntry
->ORI_BA_Status
= Originator_Done
;
535 pAd
->BATable
.numDoneOriginator
++;
537 /* reset sequence number */
538 pBAEntry
->Sequence
= BA_ORI_INIT_SEQ
;
539 /* Set Bitmap flag. */
540 pEntry
->TXBAbitmap
|= (1 << TID
);
541 RTMPCancelTimer(&pBAEntry
->ORIBATimer
, &Cancelled
);
543 pBAEntry
->ORIBATimer
.TimerValue
= 0; /*pFrame->TimeOutValue; */
545 DBGPRINT(RT_DEBUG_TRACE
,
546 ("%s : TXBAbitmap = %x, BAWinSize = %d, TimeOut = %ld\n",
547 __func__
, pEntry
->TXBAbitmap
, pBAEntry
->BAWinSize
,
548 pBAEntry
->ORIBATimer
.TimerValue
));
551 NStatus
= MlmeAllocateMemory(pAd
, &pOutBuffer2
); /*Get an unused nonpaged memory */
552 if (NStatus
!= NDIS_STATUS_SUCCESS
) {
553 DBGPRINT(RT_DEBUG_TRACE
,
554 ("BA - BAOriSessionAdd() allocate memory failed \n"));
558 BarHeaderInit(pAd
, &FrameBar
,
559 pAd
->MacTab
.Content
[pBAEntry
->Wcid
].Addr
,
560 pAd
->CurrentAddress
);
562 FrameBar
.StartingSeq
.field
.FragNum
= 0; /* make sure sequence not clear in DEL function. */
563 FrameBar
.StartingSeq
.field
.StartSeq
= pBAEntry
->Sequence
; /* make sure sequence not clear in DEL funciton. */
564 FrameBar
.BarControl
.TID
= pBAEntry
->TID
; /* make sure sequence not clear in DEL funciton. */
565 MakeOutgoingFrame(pOutBuffer2
, &FrameLen
,
566 sizeof(struct rt_frame_bar
), &FrameBar
, END_OF_ARGS
);
567 MiniportMMRequest(pAd
, QID_AC_BE
, pOutBuffer2
, FrameLen
);
568 MlmeFreeMemory(pAd
, pOutBuffer2
);
570 if (pBAEntry
->ORIBATimer
.TimerValue
)
571 RTMPSetTimer(&pBAEntry
->ORIBATimer
, pBAEntry
->ORIBATimer
.TimerValue
); /* in mSec */
575 BOOLEAN
BARecSessionAdd(struct rt_rtmp_adapter
*pAd
,
576 struct rt_mac_table_entry
*pEntry
, struct rt_frame_addba_req
* pFrame
)
578 struct rt_ba_rec_entry
*pBAEntry
= NULL
;
579 BOOLEAN Status
= TRUE
;
590 TID
= pFrame
->BaParm
.TID
;
593 min(((u8
)pFrame
->BaParm
.BufSize
),
594 (u8
)pAd
->CommonCfg
.BACapability
.field
.RxBAWinLimit
);
597 if (BAWinSize
== 0) {
601 Idx
= pEntry
->BARecWcidArray
[TID
];
604 pBAEntry
= BATableAllocRecEntry(pAd
, &Idx
);
606 pBAEntry
= &pAd
->BATable
.BARecEntry
[Idx
];
607 /* flush all pending reordering mpdus */
608 ba_refresh_reordering_mpdus(pAd
, pBAEntry
);
611 DBGPRINT(RT_DEBUG_TRACE
,
612 ("%s(%ld): Idx = %d, BAWinSize(req %d) = %d\n", __func__
,
613 pAd
->BATable
.numAsRecipient
, Idx
, pFrame
->BaParm
.BufSize
,
616 /* Start fill in parameters. */
617 if (pBAEntry
!= NULL
) {
618 ASSERT(pBAEntry
->list
.qlen
== 0);
620 pBAEntry
->REC_BA_Status
= Recipient_HandleRes
;
621 pBAEntry
->BAWinSize
= BAWinSize
;
622 pBAEntry
->Wcid
= pEntry
->Aid
;
624 pBAEntry
->TimeOutValue
= pFrame
->TimeOutValue
;
625 pBAEntry
->REC_BA_Status
= Recipient_Accept
;
626 /* initial sequence number */
627 pBAEntry
->LastIndSeq
= RESET_RCV_SEQ
; /*pFrame->BaStartSeq.field.StartSeq; */
629 DBGPRINT(RT_DEBUG_OFF
,
630 ("Start Seq = %08x\n",
631 pFrame
->BaStartSeq
.field
.StartSeq
));
633 if (pEntry
->RXBAbitmap
& (1 << TID
)) {
634 RTMPCancelTimer(&pBAEntry
->RECBATimer
, &Cancelled
);
636 RTMPInitTimer(pAd
, &pBAEntry
->RECBATimer
,
638 (BARecSessionIdleTimeout
), pBAEntry
,
642 /* Set Bitmap flag. */
643 pEntry
->RXBAbitmap
|= (1 << TID
);
644 pEntry
->BARecWcidArray
[TID
] = Idx
;
646 pEntry
->BADeclineBitmap
&= ~(1 << TID
);
648 /* Set BA session mask in WCID table. */
649 RTMP_ADD_BA_SESSION_TO_ASIC(pAd
, pEntry
->Aid
, TID
);
651 DBGPRINT(RT_DEBUG_TRACE
,
652 ("MACEntry[%d]RXBAbitmap = 0x%x. BARecWcidArray=%d\n",
653 pEntry
->Aid
, pEntry
->RXBAbitmap
,
654 pEntry
->BARecWcidArray
[TID
]));
657 DBGPRINT(RT_DEBUG_TRACE
,
658 ("Can't Accept ADDBA for %pM TID = %d\n",
664 struct rt_ba_rec_entry
*BATableAllocRecEntry(struct rt_rtmp_adapter
*pAd
, u16
* Idx
)
667 struct rt_ba_rec_entry
*pBAEntry
= NULL
;
669 NdisAcquireSpinLock(&pAd
->BATabLock
);
671 if (pAd
->BATable
.numAsRecipient
>= MAX_BARECI_SESSION
) {
672 DBGPRINT(RT_DEBUG_OFF
, ("BA Recipeint Session (%ld) > %d\n",
673 pAd
->BATable
.numAsRecipient
,
674 MAX_BARECI_SESSION
));
677 /* reserve idx 0 to identify BAWcidArray[TID] as empty */
678 for (i
= 1; i
< MAX_LEN_OF_BA_REC_TABLE
; i
++) {
679 pBAEntry
= &pAd
->BATable
.BARecEntry
[i
];
680 if ((pBAEntry
->REC_BA_Status
== Recipient_NONE
)) {
682 pAd
->BATable
.numAsRecipient
++;
683 pBAEntry
->REC_BA_Status
= Recipient_USED
;
690 NdisReleaseSpinLock(&pAd
->BATabLock
);
694 struct rt_ba_ori_entry
*BATableAllocOriEntry(struct rt_rtmp_adapter
*pAd
, u16
* Idx
)
697 struct rt_ba_ori_entry
*pBAEntry
= NULL
;
699 NdisAcquireSpinLock(&pAd
->BATabLock
);
701 if (pAd
->BATable
.numAsOriginator
>= (MAX_LEN_OF_BA_ORI_TABLE
)) {
704 /* reserve idx 0 to identify BAWcidArray[TID] as empty */
705 for (i
= 1; i
< MAX_LEN_OF_BA_ORI_TABLE
; i
++) {
706 pBAEntry
= &pAd
->BATable
.BAOriEntry
[i
];
707 if ((pBAEntry
->ORI_BA_Status
== Originator_NONE
)) {
709 pAd
->BATable
.numAsOriginator
++;
710 pBAEntry
->ORI_BA_Status
= Originator_USED
;
711 pBAEntry
->pAdapter
= pAd
;
718 NdisReleaseSpinLock(&pAd
->BATabLock
);
722 void BATableFreeOriEntry(struct rt_rtmp_adapter
*pAd
, unsigned long Idx
)
724 struct rt_ba_ori_entry
*pBAEntry
= NULL
;
725 struct rt_mac_table_entry
*pEntry
;
727 if ((Idx
== 0) || (Idx
>= MAX_LEN_OF_BA_ORI_TABLE
))
730 pBAEntry
= &pAd
->BATable
.BAOriEntry
[Idx
];
732 if (pBAEntry
->ORI_BA_Status
!= Originator_NONE
) {
733 pEntry
= &pAd
->MacTab
.Content
[pBAEntry
->Wcid
];
734 pEntry
->BAOriWcidArray
[pBAEntry
->TID
] = 0;
736 NdisAcquireSpinLock(&pAd
->BATabLock
);
737 if (pBAEntry
->ORI_BA_Status
== Originator_Done
) {
738 pAd
->BATable
.numDoneOriginator
-= 1;
739 pEntry
->TXBAbitmap
&= (~(1 << (pBAEntry
->TID
)));
740 DBGPRINT(RT_DEBUG_TRACE
,
741 ("BATableFreeOriEntry numAsOriginator= %ld\n",
742 pAd
->BATable
.numAsRecipient
));
743 /* Erase Bitmap flag. */
746 ASSERT(pAd
->BATable
.numAsOriginator
!= 0);
748 pAd
->BATable
.numAsOriginator
-= 1;
750 pBAEntry
->ORI_BA_Status
= Originator_NONE
;
752 NdisReleaseSpinLock(&pAd
->BATabLock
);
756 void BATableFreeRecEntry(struct rt_rtmp_adapter
*pAd
, unsigned long Idx
)
758 struct rt_ba_rec_entry
*pBAEntry
= NULL
;
759 struct rt_mac_table_entry
*pEntry
;
761 if ((Idx
== 0) || (Idx
>= MAX_LEN_OF_BA_REC_TABLE
))
764 pBAEntry
= &pAd
->BATable
.BARecEntry
[Idx
];
766 if (pBAEntry
->REC_BA_Status
!= Recipient_NONE
) {
767 pEntry
= &pAd
->MacTab
.Content
[pBAEntry
->Wcid
];
768 pEntry
->BARecWcidArray
[pBAEntry
->TID
] = 0;
770 NdisAcquireSpinLock(&pAd
->BATabLock
);
772 ASSERT(pAd
->BATable
.numAsRecipient
!= 0);
774 pAd
->BATable
.numAsRecipient
-= 1;
776 pBAEntry
->REC_BA_Status
= Recipient_NONE
;
777 NdisReleaseSpinLock(&pAd
->BATabLock
);
781 void BAOriSessionTearDown(struct rt_rtmp_adapter
*pAd
,
784 IN BOOLEAN bPassive
, IN BOOLEAN bForceSend
)
786 unsigned long Idx
= 0;
787 struct rt_ba_ori_entry
*pBAEntry
;
790 if (Wcid
>= MAX_LEN_OF_MAC_TABLE
) {
794 /* Locate corresponding BA Originator Entry in BA Table with the (pAddr,TID). */
796 Idx
= pAd
->MacTab
.Content
[Wcid
].BAOriWcidArray
[TID
];
797 if ((Idx
== 0) || (Idx
>= MAX_LEN_OF_BA_ORI_TABLE
)) {
798 if (bForceSend
== TRUE
) {
799 /* force send specified TID DelBA */
800 struct rt_mlme_delba_req DelbaReq
;
801 struct rt_mlme_queue_elem
*Elem
=
802 kmalloc(sizeof(struct rt_mlme_queue_elem
),
805 NdisZeroMemory(&DelbaReq
, sizeof(DelbaReq
));
806 NdisZeroMemory(Elem
, sizeof(struct rt_mlme_queue_elem
));
808 COPY_MAC_ADDR(DelbaReq
.Addr
,
809 pAd
->MacTab
.Content
[Wcid
].Addr
);
810 DelbaReq
.Wcid
= Wcid
;
812 DelbaReq
.Initiator
= ORIGINATOR
;
813 Elem
->MsgLen
= sizeof(DelbaReq
);
814 NdisMoveMemory(Elem
->Msg
, &DelbaReq
,
816 MlmeDELBAAction(pAd
, Elem
);
819 DBGPRINT(RT_DEBUG_ERROR
,
820 ("%s(bForceSend):alloc memory failed!\n",
828 DBGPRINT(RT_DEBUG_TRACE
,
829 ("%s===>Wcid=%d.TID=%d \n", __func__
, Wcid
, TID
));
831 pBAEntry
= &pAd
->BATable
.BAOriEntry
[Idx
];
832 DBGPRINT(RT_DEBUG_TRACE
,
833 ("\t===>Idx = %ld, Wcid=%d.TID=%d, ORI_BA_Status = %d \n", Idx
,
834 Wcid
, TID
, pBAEntry
->ORI_BA_Status
));
836 /* Prepare DelBA action frame and send to the peer. */
838 if ((bPassive
== FALSE
) && (TID
== pBAEntry
->TID
)
839 && (pBAEntry
->ORI_BA_Status
== Originator_Done
)) {
840 struct rt_mlme_delba_req DelbaReq
;
841 struct rt_mlme_queue_elem
*Elem
=
842 kmalloc(sizeof(struct rt_mlme_queue_elem
),
845 NdisZeroMemory(&DelbaReq
, sizeof(DelbaReq
));
846 NdisZeroMemory(Elem
, sizeof(struct rt_mlme_queue_elem
));
848 COPY_MAC_ADDR(DelbaReq
.Addr
,
849 pAd
->MacTab
.Content
[Wcid
].Addr
);
850 DelbaReq
.Wcid
= Wcid
;
851 DelbaReq
.TID
= pBAEntry
->TID
;
852 DelbaReq
.Initiator
= ORIGINATOR
;
853 Elem
->MsgLen
= sizeof(DelbaReq
);
854 NdisMoveMemory(Elem
->Msg
, &DelbaReq
, sizeof(DelbaReq
));
855 MlmeDELBAAction(pAd
, Elem
);
858 DBGPRINT(RT_DEBUG_ERROR
,
859 ("%s():alloc memory failed!\n", __func__
));
863 RTMPCancelTimer(&pBAEntry
->ORIBATimer
, &Cancelled
);
864 BATableFreeOriEntry(pAd
, Idx
);
867 /*BAOriSessionSetUp(pAd, &pAd->MacTab.Content[Wcid], TID, 0, 10000, TRUE); */
871 void BARecSessionTearDown(struct rt_rtmp_adapter
*pAd
,
872 u8 Wcid
, u8 TID
, IN BOOLEAN bPassive
)
874 unsigned long Idx
= 0;
875 struct rt_ba_rec_entry
*pBAEntry
;
877 if (Wcid
>= MAX_LEN_OF_MAC_TABLE
) {
881 /* Locate corresponding BA Originator Entry in BA Table with the (pAddr,TID). */
883 Idx
= pAd
->MacTab
.Content
[Wcid
].BARecWcidArray
[TID
];
887 DBGPRINT(RT_DEBUG_TRACE
,
888 ("%s===>Wcid=%d.TID=%d \n", __func__
, Wcid
, TID
));
890 pBAEntry
= &pAd
->BATable
.BARecEntry
[Idx
];
891 DBGPRINT(RT_DEBUG_TRACE
,
892 ("\t===>Idx = %ld, Wcid=%d.TID=%d, REC_BA_Status = %d \n", Idx
,
893 Wcid
, TID
, pBAEntry
->REC_BA_Status
));
895 /* Prepare DelBA action frame and send to the peer. */
897 if ((TID
== pBAEntry
->TID
)
898 && (pBAEntry
->REC_BA_Status
== Recipient_Accept
)) {
899 struct rt_mlme_delba_req DelbaReq
;
901 /*unsigned long offset; */
904 RTMPCancelTimer(&pBAEntry
->RECBATimer
, &Cancelled
);
907 /* 1. Send DELBA Action Frame */
909 if (bPassive
== FALSE
) {
910 struct rt_mlme_queue_elem
*Elem
=
911 kmalloc(sizeof(struct rt_mlme_queue_elem
),
914 NdisZeroMemory(&DelbaReq
, sizeof(DelbaReq
));
915 NdisZeroMemory(Elem
, sizeof(struct rt_mlme_queue_elem
));
917 COPY_MAC_ADDR(DelbaReq
.Addr
,
918 pAd
->MacTab
.Content
[Wcid
].Addr
);
919 DelbaReq
.Wcid
= Wcid
;
921 DelbaReq
.Initiator
= RECIPIENT
;
922 Elem
->MsgLen
= sizeof(DelbaReq
);
923 NdisMoveMemory(Elem
->Msg
, &DelbaReq
,
925 MlmeDELBAAction(pAd
, Elem
);
928 DBGPRINT(RT_DEBUG_ERROR
,
929 ("%s():alloc memory failed!\n",
936 /* 2. Free resource of BA session */
938 /* flush all pending reordering mpdus */
939 ba_refresh_reordering_mpdus(pAd
, pBAEntry
);
941 NdisAcquireSpinLock(&pAd
->BATabLock
);
943 /* Erase Bitmap flag. */
944 pBAEntry
->LastIndSeq
= RESET_RCV_SEQ
;
945 pBAEntry
->BAWinSize
= 0;
946 /* Erase Bitmap flag at software mactable */
947 pAd
->MacTab
.Content
[Wcid
].RXBAbitmap
&=
948 (~(1 << (pBAEntry
->TID
)));
949 pAd
->MacTab
.Content
[Wcid
].BARecWcidArray
[TID
] = 0;
951 RTMP_DEL_BA_SESSION_FROM_ASIC(pAd
, Wcid
, TID
);
953 NdisReleaseSpinLock(&pAd
->BATabLock
);
957 BATableFreeRecEntry(pAd
, Idx
);
960 void BASessionTearDownALL(struct rt_rtmp_adapter
*pAd
, u8 Wcid
)
964 for (i
= 0; i
< NUM_OF_TID
; i
++) {
965 BAOriSessionTearDown(pAd
, Wcid
, i
, FALSE
, FALSE
);
966 BARecSessionTearDown(pAd
, Wcid
, i
, FALSE
);
971 ==========================================================================
973 Retry sending ADDBA Reqest.
975 IRQL = DISPATCH_LEVEL
978 p8023Header: if this is already 802.3 format, p8023Header is NULL
980 Return : TRUE if put into rx reordering buffer, shouldn't indicaterxhere.
981 FALSE , then continue indicaterx at this moment.
982 ==========================================================================
984 void BAOriSessionSetupTimeout(void *SystemSpecific1
,
985 void *FunctionContext
,
986 void *SystemSpecific2
,
987 void *SystemSpecific3
)
989 struct rt_ba_ori_entry
*pBAEntry
= (struct rt_ba_ori_entry
*)FunctionContext
;
990 struct rt_mac_table_entry
*pEntry
;
991 struct rt_rtmp_adapter
*pAd
;
993 if (pBAEntry
== NULL
)
996 pAd
= pBAEntry
->pAdapter
;
999 /* Do nothing if monitor mode is on */
1000 if (MONITOR_ON(pAd
))
1004 pEntry
= &pAd
->MacTab
.Content
[pBAEntry
->Wcid
];
1006 if ((pBAEntry
->ORI_BA_Status
== Originator_WaitRes
)
1007 && (pBAEntry
->Token
< ORI_SESSION_MAX_RETRY
)) {
1008 struct rt_mlme_addba_req AddbaReq
;
1010 NdisZeroMemory(&AddbaReq
, sizeof(AddbaReq
));
1011 COPY_MAC_ADDR(AddbaReq
.pAddr
, pEntry
->Addr
);
1012 AddbaReq
.Wcid
= (u8
)(pEntry
->Aid
);
1013 AddbaReq
.TID
= pBAEntry
->TID
;
1014 AddbaReq
.BaBufSize
=
1015 pAd
->CommonCfg
.BACapability
.field
.RxBAWinLimit
;
1016 AddbaReq
.TimeOutValue
= 0;
1017 AddbaReq
.Token
= pBAEntry
->Token
;
1018 MlmeEnqueue(pAd
, ACTION_STATE_MACHINE
, MT2_MLME_ADD_BA_CATE
,
1019 sizeof(struct rt_mlme_addba_req
), (void *)& AddbaReq
);
1020 RTMP_MLME_HANDLER(pAd
);
1021 DBGPRINT(RT_DEBUG_TRACE
,
1022 ("BA Ori Session Timeout(%d) : Send ADD BA again\n",
1026 RTMPSetTimer(&pBAEntry
->ORIBATimer
, ORI_BA_SESSION_TIMEOUT
);
1028 BATableFreeOriEntry(pAd
, pEntry
->BAOriWcidArray
[pBAEntry
->TID
]);
1033 ==========================================================================
1035 Retry sending ADDBA Reqest.
1037 IRQL = DISPATCH_LEVEL
1040 p8023Header: if this is already 802.3 format, p8023Header is NULL
1042 Return : TRUE if put into rx reordering buffer, shouldn't indicaterxhere.
1043 FALSE , then continue indicaterx at this moment.
1044 ==========================================================================
1046 void BARecSessionIdleTimeout(void *SystemSpecific1
,
1047 void *FunctionContext
,
1048 void *SystemSpecific2
, void *SystemSpecific3
)
1051 struct rt_ba_rec_entry
*pBAEntry
= (struct rt_ba_rec_entry
*)FunctionContext
;
1052 struct rt_rtmp_adapter
*pAd
;
1053 unsigned long Now32
;
1055 if (pBAEntry
== NULL
)
1058 if ((pBAEntry
->REC_BA_Status
== Recipient_Accept
)) {
1059 NdisGetSystemUpTime(&Now32
);
1062 ((unsigned long)Now32
,
1063 (unsigned long)(pBAEntry
->LastIndSeqAtTimer
+
1064 REC_BA_SESSION_IDLE_TIMEOUT
))) {
1065 pAd
= pBAEntry
->pAdapter
;
1066 /* flush all pending reordering mpdus */
1067 ba_refresh_reordering_mpdus(pAd
, pBAEntry
);
1068 DBGPRINT(RT_DEBUG_OFF
,
1069 ("%ld: REC BA session Timeout\n", Now32
));
1074 void PeerAddBAReqAction(struct rt_rtmp_adapter
*pAd
, struct rt_mlme_queue_elem
*Elem
)
1077 /*unsigned long Idx; */
1080 struct rt_frame_addba_rsp ADDframe
;
1081 u8
*pOutBuffer
= NULL
;
1083 struct rt_frame_addba_req
* pAddreqFrame
= NULL
;
1085 unsigned long FrameLen
;
1086 unsigned long *ptemp
;
1087 struct rt_mac_table_entry
*pMacEntry
;
1089 DBGPRINT(RT_DEBUG_TRACE
,
1090 ("%s ==> (Wcid = %d)\n", __func__
, Elem
->Wcid
));
1092 /*hex_dump("AddBAReq", Elem->Msg, Elem->MsgLen); */
1094 /*ADDBA Request from unknown peer, ignore this. */
1095 if (Elem
->Wcid
>= MAX_LEN_OF_MAC_TABLE
)
1098 pMacEntry
= &pAd
->MacTab
.Content
[Elem
->Wcid
];
1099 DBGPRINT(RT_DEBUG_TRACE
, ("BA - PeerAddBAReqAction----> \n"));
1100 ptemp
= (unsigned long *)Elem
->Msg
;
1101 /*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))); */
1103 if (PeerAddBAReqActionSanity(pAd
, Elem
->Msg
, Elem
->MsgLen
, pAddr
)) {
1105 if ((pAd
->CommonCfg
.bBADecline
== FALSE
)
1106 && IS_HT_STA(pMacEntry
)) {
1107 pAddreqFrame
= (struct rt_frame_addba_req
*) (&Elem
->Msg
[0]);
1108 DBGPRINT(RT_DEBUG_OFF
,
1109 ("Rcv Wcid(%d) AddBAReq\n", Elem
->Wcid
));
1111 (pAd
, &pAd
->MacTab
.Content
[Elem
->Wcid
],
1115 Status
= 38; /* more parameters have invalid values */
1117 Status
= 37; /* the request has been declined. */
1121 if (pAd
->MacTab
.Content
[Elem
->Wcid
].ValidAsCLI
)
1122 ASSERT(pAd
->MacTab
.Content
[Elem
->Wcid
].Sst
== SST_ASSOC
);
1124 pAddreqFrame
= (struct rt_frame_addba_req
*) (&Elem
->Msg
[0]);
1125 /* 2. Always send back ADDBA Response */
1126 NStatus
= MlmeAllocateMemory(pAd
, &pOutBuffer
); /*Get an unused nonpaged memory */
1127 if (NStatus
!= NDIS_STATUS_SUCCESS
) {
1128 DBGPRINT(RT_DEBUG_TRACE
,
1129 ("ACTION - PeerBAAction() allocate memory failed \n"));
1133 NdisZeroMemory(&ADDframe
, sizeof(struct rt_frame_addba_rsp
));
1135 /* 2-1. Prepare ADDBA Response frame. */
1138 ActHeaderInit(pAd
, &ADDframe
.Hdr
, pAddr
,
1139 pAd
->CurrentAddress
,
1140 pAd
->CommonCfg
.Bssid
);
1142 ActHeaderInit(pAd
, &ADDframe
.Hdr
, pAd
->CommonCfg
.Bssid
,
1143 pAd
->CurrentAddress
, pAddr
);
1146 ADDframe
.Category
= CATEGORY_BA
;
1147 ADDframe
.Action
= ADDBA_RESP
;
1148 ADDframe
.Token
= pAddreqFrame
->Token
;
1149 /* What is the Status code?? need to check. */
1150 ADDframe
.StatusCode
= Status
;
1151 ADDframe
.BaParm
.BAPolicy
= IMMED_BA
;
1152 ADDframe
.BaParm
.AMSDUSupported
= 0;
1153 ADDframe
.BaParm
.TID
= pAddreqFrame
->BaParm
.TID
;
1154 ADDframe
.BaParm
.BufSize
=
1155 min(((u8
)pAddreqFrame
->BaParm
.BufSize
),
1156 (u8
)pAd
->CommonCfg
.BACapability
.field
.RxBAWinLimit
);
1157 if (ADDframe
.BaParm
.BufSize
== 0) {
1158 ADDframe
.BaParm
.BufSize
= 64;
1160 ADDframe
.TimeOutValue
= 0; /*pAddreqFrame->TimeOutValue; */
1162 *(u16
*) (&ADDframe
.BaParm
) =
1163 cpu2le16(*(u16
*) (&ADDframe
.BaParm
));
1164 ADDframe
.StatusCode
= cpu2le16(ADDframe
.StatusCode
);
1165 ADDframe
.TimeOutValue
= cpu2le16(ADDframe
.TimeOutValue
);
1167 MakeOutgoingFrame(pOutBuffer
, &FrameLen
,
1168 sizeof(struct rt_frame_addba_rsp
), &ADDframe
, END_OF_ARGS
);
1169 MiniportMMRequest(pAd
, QID_AC_BE
, pOutBuffer
, FrameLen
);
1170 MlmeFreeMemory(pAd
, pOutBuffer
);
1172 DBGPRINT(RT_DEBUG_TRACE
,
1173 ("%s(%d): TID(%d), BufSize(%d) <== \n", __func__
, Elem
->Wcid
,
1174 ADDframe
.BaParm
.TID
, ADDframe
.BaParm
.BufSize
));
1177 void PeerAddBARspAction(struct rt_rtmp_adapter
*pAd
, struct rt_mlme_queue_elem
*Elem
)
1180 /*u8 * pOutBuffer = NULL; */
1181 struct rt_frame_addba_rsp
* pFrame
= NULL
;
1182 /*struct rt_ba_ori_entry *pBAEntry; */
1184 /*ADDBA Response from unknown peer, ignore this. */
1185 if (Elem
->Wcid
>= MAX_LEN_OF_MAC_TABLE
)
1188 DBGPRINT(RT_DEBUG_TRACE
, ("%s ==> Wcid(%d)\n", __func__
, Elem
->Wcid
));
1190 /*hex_dump("PeerAddBARspAction()", Elem->Msg, Elem->MsgLen); */
1192 if (PeerAddBARspActionSanity(pAd
, Elem
->Msg
, Elem
->MsgLen
)) {
1193 pFrame
= (struct rt_frame_addba_rsp
*) (&Elem
->Msg
[0]);
1195 DBGPRINT(RT_DEBUG_TRACE
,
1196 ("\t\t StatusCode = %d\n", pFrame
->StatusCode
));
1197 switch (pFrame
->StatusCode
) {
1199 /* I want a BAsession with this peer as an originator. */
1200 BAOriSessionAdd(pAd
, &pAd
->MacTab
.Content
[Elem
->Wcid
],
1204 /* check status == USED ??? */
1205 BAOriSessionTearDown(pAd
, Elem
->Wcid
,
1206 pFrame
->BaParm
.TID
, TRUE
, FALSE
);
1209 /* Rcv Decline StatusCode */
1210 if ((pFrame
->StatusCode
== 37)
1211 || ((pAd
->OpMode
== OPMODE_STA
) && STA_TGN_WIFI_ON(pAd
)
1212 && (pFrame
->StatusCode
!= 0))
1214 pAd
->MacTab
.Content
[Elem
->Wcid
].BADeclineBitmap
|=
1215 1 << pFrame
->BaParm
.TID
;
1220 void PeerDelBAAction(struct rt_rtmp_adapter
*pAd
, struct rt_mlme_queue_elem
*Elem
)
1223 /*u8 * pOutBuffer = NULL; */
1224 struct rt_frame_delba_req
* pDelFrame
= NULL
;
1226 DBGPRINT(RT_DEBUG_TRACE
, ("%s ==>\n", __func__
));
1227 /*DELBA Request from unknown peer, ignore this. */
1228 if (PeerDelBAActionSanity(pAd
, Elem
->Wcid
, Elem
->Msg
, Elem
->MsgLen
)) {
1229 pDelFrame
= (struct rt_frame_delba_req
*) (&Elem
->Msg
[0]);
1230 if (pDelFrame
->DelbaParm
.Initiator
== ORIGINATOR
) {
1231 DBGPRINT(RT_DEBUG_TRACE
,
1232 ("BA - PeerDelBAAction----> ORIGINATOR\n"));
1233 BARecSessionTearDown(pAd
, Elem
->Wcid
,
1234 pDelFrame
->DelbaParm
.TID
, TRUE
);
1236 DBGPRINT(RT_DEBUG_TRACE
,
1237 ("BA - PeerDelBAAction----> RECIPIENT, Reason = %d\n",
1238 pDelFrame
->ReasonCode
));
1239 /*hex_dump("DelBA Frame", pDelFrame, Elem->MsgLen); */
1240 BAOriSessionTearDown(pAd
, Elem
->Wcid
,
1241 pDelFrame
->DelbaParm
.TID
, TRUE
,
1247 BOOLEAN
CntlEnqueueForRecv(struct rt_rtmp_adapter
*pAd
,
1249 unsigned long MsgLen
, struct rt_frame_ba_req
* pMsg
)
1251 struct rt_frame_ba_req
* pFrame
= pMsg
;
1252 /*PRTMP_REORDERBUF pBuffer; */
1253 /*PRTMP_REORDERBUF pDmaBuf; */
1254 struct rt_ba_rec_entry
*pBAEntry
;
1255 /*BOOLEAN Result; */
1260 TID
= (u8
)pFrame
->BARControl
.TID
;
1262 DBGPRINT(RT_DEBUG_TRACE
,
1263 ("%s(): BAR-Wcid(%ld), Tid (%d)\n", __func__
, Wcid
, TID
));
1264 /*hex_dump("BAR", (char *)pFrame, MsgLen); */
1265 /* Do nothing if the driver is starting halt state. */
1266 /* This might happen when timer already been fired before cancel timer with mlmehalt */
1268 (pAd
, fRTMP_ADAPTER_HALT_IN_PROGRESS
| fRTMP_ADAPTER_NIC_NOT_EXIST
))
1271 /* First check the size, it MUST not exceed the mlme queue size */
1272 if (MsgLen
> MGMT_DMA_BUFFER_SIZE
) {
1273 DBGPRINT_ERR("CntlEnqueueForRecv: frame too large, size = %ld \n", MsgLen
);
1275 } else if (MsgLen
!= sizeof(struct rt_frame_ba_req
)) {
1276 DBGPRINT_ERR("CntlEnqueueForRecv: BlockAck Request frame length size = %ld incorrect\n", MsgLen
);
1278 } else if (MsgLen
!= sizeof(struct rt_frame_ba_req
)) {
1279 DBGPRINT_ERR("CntlEnqueueForRecv: BlockAck Request frame length size = %ld incorrect\n", MsgLen
);
1283 if ((Wcid
< MAX_LEN_OF_MAC_TABLE
) && (TID
< 8)) {
1284 /* if this receiving packet is from SA that is in our OriEntry. Since WCID <9 has direct mapping. no need search. */
1285 Idx
= pAd
->MacTab
.Content
[Wcid
].BARecWcidArray
[TID
];
1286 pBAEntry
= &pAd
->BATable
.BARecEntry
[Idx
];
1291 DBGPRINT(RT_DEBUG_TRACE
,
1292 ("BAR(%ld) : Tid (%d) - %04x:%04x\n", Wcid
, TID
,
1293 pFrame
->BAStartingSeq
.field
.StartSeq
, pBAEntry
->LastIndSeq
));
1296 (pBAEntry
->LastIndSeq
, pFrame
->BAStartingSeq
.field
.StartSeq
,
1298 /*DBGPRINT(RT_DEBUG_TRACE, ("BAR Seq = %x, LastIndSeq = %x\n", pFrame->BAStartingSeq.field.StartSeq, pBAEntry->LastIndSeq)); */
1299 ba_indicate_reordering_mpdus_le_seq(pAd
, pBAEntry
,
1300 pFrame
->BAStartingSeq
.field
.
1302 pBAEntry
->LastIndSeq
=
1303 (pFrame
->BAStartingSeq
.field
.StartSeq
==
1304 0) ? MAXSEQ
: (pFrame
->BAStartingSeq
.field
.StartSeq
- 1);
1306 /*ba_refresh_reordering_mpdus(pAd, pBAEntry); */
1311 Description : Send PSMP Action frame If PSMP mode switches.
1313 void SendPSMPAction(struct rt_rtmp_adapter
*pAd
, u8 Wcid
, u8 Psmp
)
1315 u8
*pOutBuffer
= NULL
;
1317 /*unsigned long Idx; */
1318 struct rt_frame_psmp_action Frame
;
1319 unsigned long FrameLen
;
1321 NStatus
= MlmeAllocateMemory(pAd
, &pOutBuffer
); /*Get an unused nonpaged memory */
1322 if (NStatus
!= NDIS_STATUS_SUCCESS
) {
1323 DBGPRINT(RT_DEBUG_ERROR
,
1324 ("BA - MlmeADDBAAction() allocate memory failed \n"));
1328 ActHeaderInit(pAd
, &Frame
.Hdr
, pAd
->CommonCfg
.Bssid
,
1329 pAd
->CurrentAddress
, pAd
->MacTab
.Content
[Wcid
].Addr
);
1331 Frame
.Category
= CATEGORY_HT
;
1332 Frame
.Action
= SMPS_ACTION
;
1337 && (pAd
->Antenna
.field
.RxPath
> 1
1338 || pAd
->Antenna
.field
.TxPath
> 1)) {
1339 RTMP_ASIC_MMPS_DISABLE(pAd
);
1341 #endif /* RT30xx // */
1350 && (pAd
->Antenna
.field
.RxPath
> 1
1351 || pAd
->Antenna
.field
.TxPath
> 1)) {
1352 RTMP_ASIC_MMPS_ENABLE(pAd
);
1354 #endif /* RT30xx // */
1358 MakeOutgoingFrame(pOutBuffer
, &FrameLen
,
1359 sizeof(struct rt_frame_psmp_action
), &Frame
, END_OF_ARGS
);
1360 MiniportMMRequest(pAd
, QID_AC_BE
, pOutBuffer
, FrameLen
);
1361 MlmeFreeMemory(pAd
, pOutBuffer
);
1362 DBGPRINT(RT_DEBUG_ERROR
, ("HT - SendPSMPAction( %d ) \n", Frame
.Psmp
));
1365 #define RADIO_MEASUREMENT_REQUEST_ACTION 0
1367 struct PACKED rt_beacon_request
{
1371 u16 MeasurementDuration
;
1373 u8 BSSID
[MAC_ADDR_LEN
];
1374 u8 ReportingCondition
;
1376 u8 SSIDIE
[2]; /* 2 byte */
1379 struct PACKED rt_measurement_req
{
1387 void convert_reordering_packet_to_preAMSDU_or_802_3_packet(struct rt_rtmp_adapter
*pAd
,
1388 struct rt_rx_blk
*pRxBlk
,
1393 u8 Header802_3
[LENGTH_802_3
];
1395 /* 1. get 802.3 Header */
1397 /* a. pointer pRxBlk->pData to payload */
1398 /* b. modify pRxBlk->DataSize */
1400 RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk
, Header802_3
);
1402 ASSERT(pRxBlk
->pRxPacket
);
1403 pRxPkt
= RTPKT_TO_OSPKT(pRxBlk
->pRxPacket
);
1405 SET_OS_PKT_NETDEV(pRxPkt
, get_netdev_from_bssid(pAd
, FromWhichBSSID
));
1406 SET_OS_PKT_DATAPTR(pRxPkt
, pRxBlk
->pData
);
1407 SET_OS_PKT_LEN(pRxPkt
, pRxBlk
->DataSize
);
1408 SET_OS_PKT_DATATAIL(pRxPkt
, pRxBlk
->pData
, pRxBlk
->DataSize
);
1411 /* copy 802.3 header, if necessary */
1413 if (!RX_BLK_TEST_FLAG(pRxBlk
, fRX_AMSDU
)) {
1416 NdisMoveMemory(skb_push(pRxPkt
, LENGTH_802_3
),
1417 Header802_3
, LENGTH_802_3
);
1423 #define INDICATE_LEGACY_OR_AMSDU(_pAd, _pRxBlk, _fromWhichBSSID) \
1426 if (RX_BLK_TEST_FLAG(_pRxBlk, fRX_AMSDU)) \
1428 Indicate_AMSDU_Packet(_pAd, _pRxBlk, _fromWhichBSSID); \
1430 else if (RX_BLK_TEST_FLAG(_pRxBlk, fRX_EAP)) \
1432 Indicate_EAPOL_Packet(_pAd, _pRxBlk, _fromWhichBSSID); \
1436 Indicate_Legacy_Packet(_pAd, _pRxBlk, _fromWhichBSSID); \
1440 static void ba_enqueue_reordering_packet(struct rt_rtmp_adapter
*pAd
,
1441 struct rt_ba_rec_entry
*pBAEntry
,
1442 struct rt_rx_blk
*pRxBlk
,
1445 struct reordering_mpdu
*mpdu_blk
;
1446 u16 Sequence
= (u16
)pRxBlk
->pHeader
->Sequence
;
1448 mpdu_blk
= ba_mpdu_blk_alloc(pAd
);
1449 if ((mpdu_blk
!= NULL
) && (!RX_BLK_TEST_FLAG(pRxBlk
, fRX_EAP
))) {
1450 /* Write RxD buffer address & allocated buffer length */
1451 NdisAcquireSpinLock(&pBAEntry
->RxReRingLock
);
1453 mpdu_blk
->Sequence
= Sequence
;
1455 mpdu_blk
->bAMSDU
= RX_BLK_TEST_FLAG(pRxBlk
, fRX_AMSDU
);
1457 convert_reordering_packet_to_preAMSDU_or_802_3_packet(pAd
,
1461 STATS_INC_RX_PACKETS(pAd
, FromWhichBSSID
);
1464 /* it is necessary for reordering packet to record */
1465 /* which BSS it come from */
1467 RTMP_SET_PACKET_IF(pRxBlk
->pRxPacket
, FromWhichBSSID
);
1469 mpdu_blk
->pPacket
= pRxBlk
->pRxPacket
;
1471 if (ba_reordering_mpdu_insertsorted(&pBAEntry
->list
, mpdu_blk
)
1473 /* had been already within reordering list */
1474 /* don't indicate */
1475 RELEASE_NDIS_PACKET(pAd
, pRxBlk
->pRxPacket
,
1476 NDIS_STATUS_SUCCESS
);
1477 ba_mpdu_blk_free(pAd
, mpdu_blk
);
1480 ASSERT((0 <= pBAEntry
->list
.qlen
)
1481 && (pBAEntry
->list
.qlen
<= pBAEntry
->BAWinSize
));
1482 NdisReleaseSpinLock(&pBAEntry
->RxReRingLock
);
1484 DBGPRINT(RT_DEBUG_ERROR
,
1485 (" (%d) Can't allocate reordering mpdu blk\n",
1486 pBAEntry
->list
.qlen
));
1489 * flush all pending reordering mpdus
1490 * and receiving mpdu to upper layer
1491 * make tcp/ip to take care reordering mechanism
1493 /*ba_refresh_reordering_mpdus(pAd, pBAEntry); */
1494 ba_indicate_reordering_mpdus_le_seq(pAd
, pBAEntry
, Sequence
);
1496 pBAEntry
->LastIndSeq
= Sequence
;
1497 INDICATE_LEGACY_OR_AMSDU(pAd
, pRxBlk
, FromWhichBSSID
);
1502 ==========================================================================
1504 Indicate this packet to upper layer or put it into reordering buffer
1507 pRxBlk : carry necessary packet info 802.11 format
1508 FromWhichBSSID : the packet received from which BSS
1514 the packet queued into reordering buffer need to cover to 802.3 format
1516 ==========================================================================
1519 void Indicate_AMPDU_Packet(struct rt_rtmp_adapter
*pAd
,
1520 struct rt_rx_blk
*pRxBlk
, u8 FromWhichBSSID
)
1523 struct rt_ba_rec_entry
*pBAEntry
= NULL
;
1524 u16 Sequence
= pRxBlk
->pHeader
->Sequence
;
1525 unsigned long Now32
;
1526 u8 Wcid
= pRxBlk
->pRxWI
->WirelessCliID
;
1527 u8 TID
= pRxBlk
->pRxWI
->TID
;
1529 if (!RX_BLK_TEST_FLAG(pRxBlk
, fRX_AMSDU
)
1530 && (pRxBlk
->DataSize
> MAX_RX_PKT_LEN
)) {
1531 /* release packet */
1532 RELEASE_NDIS_PACKET(pAd
, pRxBlk
->pRxPacket
,
1533 NDIS_STATUS_FAILURE
);
1537 if (Wcid
< MAX_LEN_OF_MAC_TABLE
) {
1538 Idx
= pAd
->MacTab
.Content
[Wcid
].BARecWcidArray
[TID
];
1540 /* Rec BA Session had been torn down */
1541 INDICATE_LEGACY_OR_AMSDU(pAd
, pRxBlk
, FromWhichBSSID
);
1544 pBAEntry
= &pAd
->BATable
.BARecEntry
[Idx
];
1548 /* release packet */
1549 RELEASE_NDIS_PACKET(pAd
, pRxBlk
->pRxPacket
,
1550 NDIS_STATUS_FAILURE
);
1556 /* update last rx time */
1557 NdisGetSystemUpTime(&Now32
);
1559 pBAEntry
->rcvSeq
= Sequence
;
1561 ba_flush_reordering_timeout_mpdus(pAd
, pBAEntry
, Now32
);
1562 pBAEntry
->LastIndSeqAtTimer
= Now32
;
1565 /* Reset Last Indicate Sequence */
1567 if (pBAEntry
->LastIndSeq
== RESET_RCV_SEQ
) {
1568 ASSERT((pBAEntry
->list
.qlen
== 0)
1569 && (pBAEntry
->list
.next
== NULL
));
1571 /* reset rcv sequence of BA session */
1572 pBAEntry
->LastIndSeq
= Sequence
;
1573 pBAEntry
->LastIndSeqAtTimer
= Now32
;
1574 INDICATE_LEGACY_OR_AMSDU(pAd
, pRxBlk
, FromWhichBSSID
);
1579 /* I. Check if in order. */
1581 if (SEQ_STEPONE(Sequence
, pBAEntry
->LastIndSeq
, MAXSEQ
)) {
1584 pBAEntry
->LastIndSeq
= Sequence
;
1585 INDICATE_LEGACY_OR_AMSDU(pAd
, pRxBlk
, FromWhichBSSID
);
1587 ba_indicate_reordering_mpdus_in_order(pAd
, pBAEntry
,
1588 pBAEntry
->LastIndSeq
);
1589 if (LastIndSeq
!= RESET_RCV_SEQ
) {
1590 pBAEntry
->LastIndSeq
= LastIndSeq
;
1592 pBAEntry
->LastIndSeqAtTimer
= Now32
;
1595 /* II. Drop Duplicated Packet */
1597 else if (Sequence
== pBAEntry
->LastIndSeq
) {
1599 /* drop and release packet */
1600 pBAEntry
->nDropPacket
++;
1601 RELEASE_NDIS_PACKET(pAd
, pRxBlk
->pRxPacket
,
1602 NDIS_STATUS_FAILURE
);
1605 /* III. Drop Old Received Packet */
1607 else if (SEQ_SMALLER(Sequence
, pBAEntry
->LastIndSeq
, MAXSEQ
)) {
1609 /* drop and release packet */
1610 pBAEntry
->nDropPacket
++;
1611 RELEASE_NDIS_PACKET(pAd
, pRxBlk
->pRxPacket
,
1612 NDIS_STATUS_FAILURE
);
1615 /* IV. Receive Sequence within Window Size */
1617 else if (SEQ_SMALLER
1619 (((pBAEntry
->LastIndSeq
+ pBAEntry
->BAWinSize
+ 1)) & MAXSEQ
),
1621 ba_enqueue_reordering_packet(pAd
, pBAEntry
, pRxBlk
,
1625 /* V. Receive seq surpasses Win(lastseq + nMSDU). So refresh all reorder buffer */
1628 long WinStartSeq
, TmpSeq
;
1630 TmpSeq
= Sequence
- (pBAEntry
->BAWinSize
) - 1;
1632 TmpSeq
= (MAXSEQ
+ 1) + TmpSeq
;
1634 WinStartSeq
= (TmpSeq
+ 1) & MAXSEQ
;
1635 ba_indicate_reordering_mpdus_le_seq(pAd
, pBAEntry
, WinStartSeq
);
1636 pBAEntry
->LastIndSeq
= WinStartSeq
; /*TmpSeq; */
1638 pBAEntry
->LastIndSeqAtTimer
= Now32
;
1640 ba_enqueue_reordering_packet(pAd
, pBAEntry
, pRxBlk
,
1644 ba_indicate_reordering_mpdus_in_order(pAd
, pBAEntry
,
1645 pBAEntry
->LastIndSeq
);
1646 if (TmpSeq
!= RESET_RCV_SEQ
) {
1647 pBAEntry
->LastIndSeq
= TmpSeq
;