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 // inital 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_Annnounce(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 receving 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;