]> bbs.cooldavid.org Git - net-next-2.6.git/blame - drivers/staging/rt3090/common/ba_action.c
Staging: rt2860: add RT3090 chipset support
[net-next-2.6.git] / drivers / staging / rt3090 / common / ba_action.c
CommitLineData
36c7928c
BZ
1/*
2 *************************************************************************
3 * Ralink Tech Inc.
4 * 5F., No.36, Taiyuan St., Jhubei City,
5 * Hsinchu County 302,
6 * Taiwan, R.O.C.
7 *
8 * (c) Copyright 2002-2007, Ralink Technology, Inc.
9 *
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. *
14 * *
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. *
19 * *
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. *
24 * *
25 *************************************************************************
26 */
27
28
29#ifdef DOT11_N_SUPPORT
30
31#include "../rt_config.h"
32
33
34#define BA_ORI_INIT_SEQ (pEntry->TxSeq[TID]) //1 // inital sequence number of BA session
35
36#define ORI_SESSION_MAX_RETRY 8
37#define ORI_BA_SESSION_TIMEOUT (2000) // ms
38#define REC_BA_SESSION_IDLE_TIMEOUT (1000) // ms
39
40#define REORDERING_PACKET_TIMEOUT ((100 * OS_HZ)/1000) // system ticks -- 100 ms
41#define MAX_REORDERING_PACKET_TIMEOUT ((3000 * OS_HZ)/1000) // system ticks -- 100 ms
42
43#define RESET_RCV_SEQ (0xFFFF)
44
45static void ba_mpdu_blk_free(PRTMP_ADAPTER pAd, struct reordering_mpdu *mpdu_blk);
46
47
48BA_ORI_ENTRY *BATableAllocOriEntry(
49 IN PRTMP_ADAPTER pAd,
50 OUT USHORT *Idx);
51
52BA_REC_ENTRY *BATableAllocRecEntry(
53 IN PRTMP_ADAPTER pAd,
54 OUT USHORT *Idx);
55
56VOID BAOriSessionSetupTimeout(
57 IN PVOID SystemSpecific1,
58 IN PVOID FunctionContext,
59 IN PVOID SystemSpecific2,
60 IN PVOID SystemSpecific3);
61
62VOID BARecSessionIdleTimeout(
63 IN PVOID SystemSpecific1,
64 IN PVOID FunctionContext,
65 IN PVOID SystemSpecific2,
66 IN PVOID SystemSpecific3);
67
68
69BUILD_TIMER_FUNCTION(BAOriSessionSetupTimeout);
70BUILD_TIMER_FUNCTION(BARecSessionIdleTimeout);
71
72#define ANNOUNCE_REORDERING_PACKET(_pAd, _mpdu_blk) \
73 Announce_Reordering_Packet(_pAd, _mpdu_blk);
74
75VOID BA_MaxWinSizeReasign(
76 IN PRTMP_ADAPTER pAd,
77 IN MAC_TABLE_ENTRY *pEntryPeer,
78 OUT UCHAR *pWinSize)
79{
80 UCHAR MaxSize;
81
82
83 if (pAd->MACVersion >= RALINK_2883_VERSION) // 3*3
84 {
85 if (pAd->MACVersion >= RALINK_3070_VERSION)
86 {
87 if (pEntryPeer->WepStatus != Ndis802_11EncryptionDisabled)
88 MaxSize = 7; // for non-open mode
89 else
90 MaxSize = 13;
91 }
92 else
93 MaxSize = 31;
94 }
95 else if (pAd->MACVersion >= RALINK_2880E_VERSION) // 2880 e
96 {
97 if (pEntryPeer->WepStatus != Ndis802_11EncryptionDisabled)
98 MaxSize = 7; // for non-open mode
99 else
100 MaxSize = 13;
101 }
102 else
103 MaxSize = 7;
104
105 DBGPRINT(RT_DEBUG_TRACE, ("ba> Win Size = %d, Max Size = %d\n",
106 *pWinSize, MaxSize));
107
108 if ((*pWinSize) > MaxSize)
109 {
110 DBGPRINT(RT_DEBUG_TRACE, ("ba> reassign max win size from %d to %d\n",
111 *pWinSize, MaxSize));
112
113 *pWinSize = MaxSize;
114 }
115}
116
117void Announce_Reordering_Packet(IN PRTMP_ADAPTER pAd,
118 IN struct reordering_mpdu *mpdu)
119{
120 PNDIS_PACKET pPacket;
121
122 pPacket = mpdu->pPacket;
123
124 if (mpdu->bAMSDU)
125 {
126 ASSERT(0);
127 BA_Reorder_AMSDU_Annnounce(pAd, pPacket);
128 }
129 else
130 {
131 //
132 // pass this 802.3 packet to upper layer or forward this packet to WM directly
133 //
134
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 //
139 }
140}
141
142/*
143 * Insert a reordering mpdu into sorted linked list by sequence no.
144 */
145BOOLEAN ba_reordering_mpdu_insertsorted(struct reordering_list *list, struct reordering_mpdu *mpdu)
146{
147
148 struct reordering_mpdu **ppScan = &list->next;
149
150 while (*ppScan != NULL)
151 {
152 if (SEQ_SMALLER((*ppScan)->Sequence, mpdu->Sequence, MAXSEQ))
153 {
154 ppScan = &(*ppScan)->next;
155 }
156 else if ((*ppScan)->Sequence == mpdu->Sequence)
157 {
158 /* give up this duplicated frame */
159 return(FALSE);
160 }
161 else
162 {
163 /* find position */
164 break;
165 }
166 }
167
168 mpdu->next = *ppScan;
169 *ppScan = mpdu;
170 list->qlen++;
171 return TRUE;
172}
173
174
175/*
176 * caller lock critical section if necessary
177 */
178static inline void ba_enqueue(struct reordering_list *list, struct reordering_mpdu *mpdu_blk)
179{
180 list->qlen++;
181 mpdu_blk->next = list->next;
182 list->next = mpdu_blk;
183}
184
185/*
186 * caller lock critical section if necessary
187 */
188static inline struct reordering_mpdu * ba_dequeue(struct reordering_list *list)
189{
190 struct reordering_mpdu *mpdu_blk = NULL;
191
192 ASSERT(list);
193
194 if (list->qlen)
195 {
196 list->qlen--;
197 mpdu_blk = list->next;
198 if (mpdu_blk)
199 {
200 list->next = mpdu_blk->next;
201 mpdu_blk->next = NULL;
202 }
203 }
204 return mpdu_blk;
205}
206
207
208static inline struct reordering_mpdu *ba_reordering_mpdu_dequeue(struct reordering_list *list)
209{
210 return(ba_dequeue(list));
211}
212
213
214static inline struct reordering_mpdu *ba_reordering_mpdu_probe(struct reordering_list *list)
215 {
216 ASSERT(list);
217
218 return(list->next);
219 }
220
221
222/*
223 * free all resource for reordering mechanism
224 */
225void ba_reordering_resource_release(PRTMP_ADAPTER pAd)
226{
227 BA_TABLE *Tab;
228 PBA_REC_ENTRY pBAEntry;
229 struct reordering_mpdu *mpdu_blk;
230 int i;
231
232 Tab = &pAd->BATable;
233
234 /* I. release all pending reordering packet */
235 NdisAcquireSpinLock(&pAd->BATabLock);
236 for (i = 0; i < MAX_LEN_OF_BA_REC_TABLE; i++)
237 {
238 pBAEntry = &Tab->BARecEntry[i];
239 if (pBAEntry->REC_BA_Status != Recipient_NONE)
240 {
241 while ((mpdu_blk = ba_reordering_mpdu_dequeue(&pBAEntry->list)))
242 {
243 ASSERT(mpdu_blk->pPacket);
244 RELEASE_NDIS_PACKET(pAd, mpdu_blk->pPacket, NDIS_STATUS_FAILURE);
245 ba_mpdu_blk_free(pAd, mpdu_blk);
246 }
247 }
248 }
249 NdisReleaseSpinLock(&pAd->BATabLock);
250
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);
256}
257
258
259
260/*
261 * Allocate all resource for reordering mechanism
262 */
263BOOLEAN ba_reordering_resource_init(PRTMP_ADAPTER pAd, int num)
264{
265 int i;
266 PUCHAR mem;
267 struct reordering_mpdu *mpdu_blk;
268 struct reordering_list *freelist;
269
270 /* allocate spinlock */
271 NdisAllocateSpinLock(&pAd->mpdu_blk_pool.lock);
272
273 /* initialize freelist */
274 freelist = &pAd->mpdu_blk_pool.freelist;
275 freelist->next = NULL;
276 freelist->qlen = 0;
277
278 DBGPRINT(RT_DEBUG_TRACE, ("Allocate %d memory for BA reordering\n", (UINT32)(num*sizeof(struct reordering_mpdu))));
279
280 /* allocate number of mpdu_blk memory */
281 os_alloc_mem(pAd, (PUCHAR *)&mem, (num*sizeof(struct reordering_mpdu)));
282
283 pAd->mpdu_blk_pool.mem = mem;
284
285 if (mem == NULL)
286 {
287 DBGPRINT(RT_DEBUG_ERROR, ("Can't Allocate Memory for BA Reordering\n"));
288 return(FALSE);
289 }
290
291 /* build mpdu_blk free list */
292 for (i=0; i<num; i++)
293 {
294 /* get mpdu_blk */
295 mpdu_blk = (struct reordering_mpdu *) mem;
296 /* initial mpdu_blk */
297 NdisZeroMemory(mpdu_blk, sizeof(struct reordering_mpdu));
298 /* next mpdu_blk */
299 mem += sizeof(struct reordering_mpdu);
300 /* insert mpdu_blk into freelist */
301 ba_enqueue(freelist, mpdu_blk);
302 }
303
304 return(TRUE);
305}
306
307//static int blk_count=0; // sample take off, no use
308
309static struct reordering_mpdu *ba_mpdu_blk_alloc(PRTMP_ADAPTER pAd)
310{
311 struct reordering_mpdu *mpdu_blk;
312
313 NdisAcquireSpinLock(&pAd->mpdu_blk_pool.lock);
314 mpdu_blk = ba_dequeue(&pAd->mpdu_blk_pool.freelist);
315 if (mpdu_blk)
316 {
317// blk_count++;
318 /* reset mpdu_blk */
319 NdisZeroMemory(mpdu_blk, sizeof(struct reordering_mpdu));
320 }
321 NdisReleaseSpinLock(&pAd->mpdu_blk_pool.lock);
322 return mpdu_blk;
323}
324
325static void ba_mpdu_blk_free(PRTMP_ADAPTER pAd, struct reordering_mpdu *mpdu_blk)
326{
327 ASSERT(mpdu_blk);
328
329 NdisAcquireSpinLock(&pAd->mpdu_blk_pool.lock);
330// blk_count--;
331 ba_enqueue(&pAd->mpdu_blk_pool.freelist, mpdu_blk);
332 NdisReleaseSpinLock(&pAd->mpdu_blk_pool.lock);
333}
334
335
336static USHORT ba_indicate_reordering_mpdus_in_order(
337 IN PRTMP_ADAPTER pAd,
338 IN PBA_REC_ENTRY pBAEntry,
339 IN USHORT StartSeq)
340{
341 struct reordering_mpdu *mpdu_blk;
342 USHORT LastIndSeq = RESET_RCV_SEQ;
343
344 NdisAcquireSpinLock(&pBAEntry->RxReRingLock);
345
346 while ((mpdu_blk = ba_reordering_mpdu_probe(&pBAEntry->list)))
347 {
348 /* find in-order frame */
349 if (!SEQ_STEPONE(mpdu_blk->Sequence, StartSeq, MAXSEQ))
350 {
351 break;
352 }
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;
360 /* free mpdu_blk */
361 ba_mpdu_blk_free(pAd, mpdu_blk);
362 }
363
364 NdisReleaseSpinLock(&pBAEntry->RxReRingLock);
365
366 /* update last indicated sequence */
367 return LastIndSeq;
368}
369
370static void ba_indicate_reordering_mpdus_le_seq(
371 IN PRTMP_ADAPTER pAd,
372 IN PBA_REC_ENTRY pBAEntry,
373 IN USHORT Sequence)
374{
375 struct reordering_mpdu *mpdu_blk;
376
377 NdisAcquireSpinLock(&pBAEntry->RxReRingLock);
378 while ((mpdu_blk = ba_reordering_mpdu_probe(&pBAEntry->list)))
379 {
380 /* find in-order frame */
381 if ((mpdu_blk->Sequence == Sequence) || SEQ_SMALLER(mpdu_blk->Sequence, Sequence, MAXSEQ))
382 {
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);
387 /* free mpdu_blk */
388 ba_mpdu_blk_free(pAd, mpdu_blk);
389 }
390 else
391 {
392 break;
393 }
394 }
395 NdisReleaseSpinLock(&pBAEntry->RxReRingLock);
396}
397
398
399static void ba_refresh_reordering_mpdus(
400 IN PRTMP_ADAPTER pAd,
401 PBA_REC_ENTRY pBAEntry)
402{
403 struct reordering_mpdu *mpdu_blk;
404
405 NdisAcquireSpinLock(&pBAEntry->RxReRingLock);
406
407 /* dequeue in-order frame from reodering list */
408 while ((mpdu_blk = ba_reordering_mpdu_dequeue(&pBAEntry->list)))
409 {
410 /* pass this frame up */
411 ANNOUNCE_REORDERING_PACKET(pAd, mpdu_blk);
412
413 pBAEntry->LastIndSeq = mpdu_blk->Sequence;
414 ba_mpdu_blk_free(pAd, mpdu_blk);
415
416 /* update last indicated sequence */
417 }
418 ASSERT(pBAEntry->list.qlen == 0);
419 pBAEntry->LastIndSeq = RESET_RCV_SEQ;
420 NdisReleaseSpinLock(&pBAEntry->RxReRingLock);
421}
422
423
424//static
425void ba_flush_reordering_timeout_mpdus(
426 IN PRTMP_ADAPTER pAd,
427 IN PBA_REC_ENTRY pBAEntry,
428 IN ULONG Now32)
429
430{
431 USHORT Sequence;
432
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)
439 )
440 {
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;
446 }
447 else
448 if (RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+(REORDERING_PACKET_TIMEOUT)))
449 && (pBAEntry->list.qlen > 0)
450 )
451 {
452// DBGPRINT(RT_DEBUG_OFF, ("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));
455 //
456 // force LastIndSeq to shift to LastIndSeq+1
457 //
458 Sequence = (pBAEntry->LastIndSeq+1) & MAXSEQ;
459 ba_indicate_reordering_mpdus_le_seq(pAd, pBAEntry, Sequence);
460 pBAEntry->LastIndSeqAtTimer = Now32;
461 pBAEntry->LastIndSeq = Sequence;
462 //
463 // indicate in-order mpdus
464 //
465 Sequence = ba_indicate_reordering_mpdus_in_order(pAd, pBAEntry, Sequence);
466 if (Sequence != RESET_RCV_SEQ)
467 {
468 pBAEntry->LastIndSeq = Sequence;
469 }
470
471 DBGPRINT(RT_DEBUG_OFF, ("%x, flush one!\n", pBAEntry->LastIndSeq));
472
473 }
474}
475
476
477/*
478 * generate ADDBA request to
479 * set up BA agreement
480 */
481VOID BAOriSessionSetUp(
482 IN PRTMP_ADAPTER pAd,
483 IN MAC_TABLE_ENTRY *pEntry,
484 IN UCHAR TID,
485 IN USHORT TimeOut,
486 IN ULONG DelayTime,
487 IN BOOLEAN isForced)
488
489{
490 //MLME_ADDBA_REQ_STRUCT AddbaReq;
491 BA_ORI_ENTRY *pBAEntry = NULL;
492 USHORT Idx;
493 BOOLEAN Cancelled;
494
495 if ((pAd->CommonCfg.BACapability.field.AutoBA != TRUE) && (isForced == FALSE))
496 return;
497
498 // if this entry is limited to use legacy tx mode, it doesn't generate BA.
499 if (RTMPStaFixedTxMode(pAd, pEntry) != FIXED_TXMODE_HT)
500 return;
501
502 if ((pEntry->BADeclineBitmap & (1<<TID)) && (isForced == FALSE))
503 {
504 // try again after 3 secs
505 DelayTime = 3000;
506// DBGPRINT(RT_DEBUG_TRACE, ("DeCline BA from Peer\n"));
507// return;
508 }
509
510
511 Idx = pEntry->BAOriWcidArray[TID];
512 if (Idx == 0)
513 {
514 // allocate a BA session
515 pBAEntry = BATableAllocOriEntry(pAd, &Idx);
516 if (pBAEntry == NULL)
517 {
518 DBGPRINT(RT_DEBUG_TRACE,("ADDBA - MlmeADDBAAction() allocate BA session failed \n"));
519 return;
520 }
521 }
522 else
523 {
524 pBAEntry =&pAd->BATable.BAOriEntry[Idx];
525 }
526
527 if (pBAEntry->ORI_BA_Status >= Originator_WaitRes)
528 {
529 return;
530 }
531
532 pEntry->BAOriWcidArray[TID] = Idx;
533
534 // Initialize BA session
535 pBAEntry->ORI_BA_Status = Originator_WaitRes;
536 pBAEntry->Wcid = pEntry->Aid;
537 pBAEntry->BAWinSize = pAd->CommonCfg.BACapability.field.RxBAWinLimit;
538 pBAEntry->Sequence = BA_ORI_INIT_SEQ;
539 pBAEntry->Token = 1; // (2008-01-21) Jan Lee recommends it - this token can't be 0
540 pBAEntry->TID = TID;
541 pBAEntry->TimeOutValue = TimeOut;
542 pBAEntry->pAdapter = pAd;
543
544 if (!(pEntry->TXBAbitmap & (1<<TID)))
545 {
546 RTMPInitTimer(pAd, &pBAEntry->ORIBATimer, GET_TIMER_FUNCTION(BAOriSessionSetupTimeout), pBAEntry, FALSE);
547 }
548 else
549 RTMPCancelTimer(&pBAEntry->ORIBATimer, &Cancelled);
550
551 // set timer to send ADDBA request
552 RTMPSetTimer(&pBAEntry->ORIBATimer, DelayTime);
553}
554
555VOID BAOriSessionAdd(
556 IN PRTMP_ADAPTER pAd,
557 IN MAC_TABLE_ENTRY *pEntry,
558 IN PFRAME_ADDBA_RSP pFrame)
559{
560 BA_ORI_ENTRY *pBAEntry = NULL;
561 BOOLEAN Cancelled;
562 UCHAR TID;
563 USHORT Idx;
564 PUCHAR pOutBuffer2 = NULL;
565 NDIS_STATUS NStatus;
566 ULONG FrameLen;
567 FRAME_BAR FrameBar;
568
569 TID = pFrame->BaParm.TID;
570 Idx = pEntry->BAOriWcidArray[TID];
571 pBAEntry =&pAd->BATable.BAOriEntry[Idx];
572
573 // Start fill in parameters.
574 if ((Idx !=0) && (pBAEntry->TID == TID) && (pBAEntry->ORI_BA_Status == Originator_WaitRes))
575 {
576 pBAEntry->BAWinSize = min(pBAEntry->BAWinSize, ((UCHAR)pFrame->BaParm.BufSize));
577 BA_MaxWinSizeReasign(pAd, pEntry, &pBAEntry->BAWinSize);
578
579 pBAEntry->TimeOutValue = pFrame->TimeOutValue;
580 pBAEntry->ORI_BA_Status = Originator_Done;
581 pAd->BATable.numDoneOriginator ++;
582
583 // reset sequence number
584 pBAEntry->Sequence = BA_ORI_INIT_SEQ;
585 // Set Bitmap flag.
586 pEntry->TXBAbitmap |= (1<<TID);
587 RTMPCancelTimer(&pBAEntry->ORIBATimer, &Cancelled);
588
589 pBAEntry->ORIBATimer.TimerValue = 0; //pFrame->TimeOutValue;
590
591 DBGPRINT(RT_DEBUG_TRACE,("%s : TXBAbitmap = %x, BAWinSize = %d, TimeOut = %ld\n", __FUNCTION__, pEntry->TXBAbitmap,
592 pBAEntry->BAWinSize, pBAEntry->ORIBATimer.TimerValue));
593
594 // SEND BAR ;
595 NStatus = MlmeAllocateMemory(pAd, &pOutBuffer2); //Get an unused nonpaged memory
596 if (NStatus != NDIS_STATUS_SUCCESS)
597 {
598 DBGPRINT(RT_DEBUG_TRACE,("BA - BAOriSessionAdd() allocate memory failed \n"));
599 return;
600 }
601
602
603#ifdef CONFIG_STA_SUPPORT
604 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
605 BarHeaderInit(pAd, &FrameBar, pAd->MacTab.Content[pBAEntry->Wcid].Addr, pAd->CurrentAddress);
606#endif // CONFIG_STA_SUPPORT //
607
608 FrameBar.StartingSeq.field.FragNum = 0; // make sure sequence not clear in DEL function.
609 FrameBar.StartingSeq.field.StartSeq = pBAEntry->Sequence; // make sure sequence not clear in DEL funciton.
610 FrameBar.BarControl.TID = pBAEntry->TID; // make sure sequence not clear in DEL funciton.
611 MakeOutgoingFrame(pOutBuffer2, &FrameLen,
612 sizeof(FRAME_BAR), &FrameBar,
613 END_OF_ARGS);
614 MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer2, FrameLen);
615 MlmeFreeMemory(pAd, pOutBuffer2);
616
617
618 if (pBAEntry->ORIBATimer.TimerValue)
619 RTMPSetTimer(&pBAEntry->ORIBATimer, pBAEntry->ORIBATimer.TimerValue); // in mSec
620 }
621}
622
623BOOLEAN BARecSessionAdd(
624 IN PRTMP_ADAPTER pAd,
625 IN MAC_TABLE_ENTRY *pEntry,
626 IN PFRAME_ADDBA_REQ pFrame)
627{
628 BA_REC_ENTRY *pBAEntry = NULL;
629 BOOLEAN Status = TRUE;
630 BOOLEAN Cancelled;
631 USHORT Idx;
632 UCHAR TID;
633 UCHAR BAWinSize;
634 //UINT32 Value;
635 //UINT offset;
636
637
638 ASSERT(pEntry);
639
640 // find TID
641 TID = pFrame->BaParm.TID;
642
643 BAWinSize = min(((UCHAR)pFrame->BaParm.BufSize), (UCHAR)pAd->CommonCfg.BACapability.field.RxBAWinLimit);
644
645 // Intel patch
646 if (BAWinSize == 0)
647 {
648 BAWinSize = 64;
649 }
650
651 Idx = pEntry->BARecWcidArray[TID];
652
653
654 if (Idx == 0)
655 {
656 pBAEntry = BATableAllocRecEntry(pAd, &Idx);
657 }
658 else
659 {
660 pBAEntry = &pAd->BATable.BARecEntry[Idx];
661 // flush all pending reordering mpdus
662 ba_refresh_reordering_mpdus(pAd, pBAEntry);
663 }
664
665 DBGPRINT(RT_DEBUG_TRACE,("%s(%ld): Idx = %d, BAWinSize(req %d) = %d\n", __FUNCTION__, pAd->BATable.numAsRecipient, Idx,
666 pFrame->BaParm.BufSize, BAWinSize));
667
668 // Start fill in parameters.
669 if (pBAEntry != NULL)
670 {
671 ASSERT(pBAEntry->list.qlen == 0);
672
673 pBAEntry->REC_BA_Status = Recipient_HandleRes;
674 pBAEntry->BAWinSize = BAWinSize;
675 pBAEntry->Wcid = pEntry->Aid;
676 pBAEntry->TID = TID;
677 pBAEntry->TimeOutValue = pFrame->TimeOutValue;
678 pBAEntry->REC_BA_Status = Recipient_Accept;
679 // initial sequence number
680 pBAEntry->LastIndSeq = RESET_RCV_SEQ; //pFrame->BaStartSeq.field.StartSeq;
681
682 DBGPRINT(RT_DEBUG_OFF, ("Start Seq = %08x\n", pFrame->BaStartSeq.field.StartSeq));
683
684 if (pEntry->RXBAbitmap & (1<<TID))
685 {
686 RTMPCancelTimer(&pBAEntry->RECBATimer, &Cancelled);
687 }
688 else
689 {
690 RTMPInitTimer(pAd, &pBAEntry->RECBATimer, GET_TIMER_FUNCTION(BARecSessionIdleTimeout), pBAEntry, TRUE);
691 }
692
693
694 // Set Bitmap flag.
695 pEntry->RXBAbitmap |= (1<<TID);
696 pEntry->BARecWcidArray[TID] = Idx;
697
698 pEntry->BADeclineBitmap &= ~(1<<TID);
699
700 // Set BA session mask in WCID table.
701 RTMP_ADD_BA_SESSION_TO_ASIC(pAd, pEntry->Aid, TID);
702
703 DBGPRINT(RT_DEBUG_TRACE,("MACEntry[%d]RXBAbitmap = 0x%x. BARecWcidArray=%d\n",
704 pEntry->Aid, pEntry->RXBAbitmap, pEntry->BARecWcidArray[TID]));
705 }
706 else
707 {
708 Status = FALSE;
709 DBGPRINT(RT_DEBUG_TRACE,("Can't Accept ADDBA for %02x:%02x:%02x:%02x:%02x:%02x TID = %d\n",
710 PRINT_MAC(pEntry->Addr), TID));
711 }
712 return(Status);
713}
714
715
716BA_REC_ENTRY *BATableAllocRecEntry(
717 IN PRTMP_ADAPTER pAd,
718 OUT USHORT *Idx)
719{
720 int i;
721 BA_REC_ENTRY *pBAEntry = NULL;
722
723
724 NdisAcquireSpinLock(&pAd->BATabLock);
725
726 if (pAd->BATable.numAsRecipient >= MAX_BARECI_SESSION)
727 {
728 DBGPRINT(RT_DEBUG_OFF, ("BA Recipeint Session (%ld) > %d\n",
729 pAd->BATable.numAsRecipient, MAX_BARECI_SESSION));
730 goto done;
731 }
732
733 // reserve idx 0 to identify BAWcidArray[TID] as empty
734 for (i=1; i < MAX_LEN_OF_BA_REC_TABLE; i++)
735 {
736 pBAEntry =&pAd->BATable.BARecEntry[i];
737 if ((pBAEntry->REC_BA_Status == Recipient_NONE))
738 {
739 // get one
740 pAd->BATable.numAsRecipient++;
741 pBAEntry->REC_BA_Status = Recipient_USED;
742 *Idx = i;
743 break;
744 }
745 }
746
747done:
748 NdisReleaseSpinLock(&pAd->BATabLock);
749 return pBAEntry;
750}
751
752BA_ORI_ENTRY *BATableAllocOriEntry(
753 IN PRTMP_ADAPTER pAd,
754 OUT USHORT *Idx)
755{
756 int i;
757 BA_ORI_ENTRY *pBAEntry = NULL;
758
759 NdisAcquireSpinLock(&pAd->BATabLock);
760
761 if (pAd->BATable.numAsOriginator >= (MAX_LEN_OF_BA_ORI_TABLE))
762 {
763 goto done;
764 }
765
766 // reserve idx 0 to identify BAWcidArray[TID] as empty
767 for (i=1; i<MAX_LEN_OF_BA_ORI_TABLE; i++)
768 {
769 pBAEntry =&pAd->BATable.BAOriEntry[i];
770 if ((pBAEntry->ORI_BA_Status == Originator_NONE))
771 {
772 // get one
773 pAd->BATable.numAsOriginator++;
774 pBAEntry->ORI_BA_Status = Originator_USED;
775 pBAEntry->pAdapter = pAd;
776 *Idx = i;
777 break;
778 }
779 }
780
781done:
782 NdisReleaseSpinLock(&pAd->BATabLock);
783 return pBAEntry;
784}
785
786
787VOID BATableFreeOriEntry(
788 IN PRTMP_ADAPTER pAd,
789 IN ULONG Idx)
790{
791 BA_ORI_ENTRY *pBAEntry = NULL;
792 MAC_TABLE_ENTRY *pEntry;
793
794
795 if ((Idx == 0) || (Idx >= MAX_LEN_OF_BA_ORI_TABLE))
796 return;
797
798 pBAEntry =&pAd->BATable.BAOriEntry[Idx];
799
800 if (pBAEntry->ORI_BA_Status != Originator_NONE)
801 {
802 pEntry = &pAd->MacTab.Content[pBAEntry->Wcid];
803 pEntry->BAOriWcidArray[pBAEntry->TID] = 0;
804
805
806 NdisAcquireSpinLock(&pAd->BATabLock);
807 if (pBAEntry->ORI_BA_Status == Originator_Done)
808 {
809 pAd->BATable.numDoneOriginator -= 1;
810 pEntry->TXBAbitmap &= (~(1<<(pBAEntry->TID) ));
811 DBGPRINT(RT_DEBUG_TRACE, ("BATableFreeOriEntry numAsOriginator= %ld\n", pAd->BATable.numAsRecipient));
812 // Erase Bitmap flag.
813 }
814
815 ASSERT(pAd->BATable.numAsOriginator != 0);
816
817 pAd->BATable.numAsOriginator -= 1;
818
819 pBAEntry->ORI_BA_Status = Originator_NONE;
820 pBAEntry->Token = 0;
821 NdisReleaseSpinLock(&pAd->BATabLock);
822 }
823}
824
825
826VOID BATableFreeRecEntry(
827 IN PRTMP_ADAPTER pAd,
828 IN ULONG Idx)
829{
830 BA_REC_ENTRY *pBAEntry = NULL;
831 MAC_TABLE_ENTRY *pEntry;
832
833
834 if ((Idx == 0) || (Idx >= MAX_LEN_OF_BA_REC_TABLE))
835 return;
836
837 pBAEntry =&pAd->BATable.BARecEntry[Idx];
838
839 if (pBAEntry->REC_BA_Status != Recipient_NONE)
840 {
841 pEntry = &pAd->MacTab.Content[pBAEntry->Wcid];
842 pEntry->BARecWcidArray[pBAEntry->TID] = 0;
843
844 NdisAcquireSpinLock(&pAd->BATabLock);
845
846 ASSERT(pAd->BATable.numAsRecipient != 0);
847
848 pAd->BATable.numAsRecipient -= 1;
849
850 pBAEntry->REC_BA_Status = Recipient_NONE;
851 NdisReleaseSpinLock(&pAd->BATabLock);
852 }
853}
854
855
856VOID BAOriSessionTearDown(
857 IN OUT PRTMP_ADAPTER pAd,
858 IN UCHAR Wcid,
859 IN UCHAR TID,
860 IN BOOLEAN bPassive,
861 IN BOOLEAN bForceSend)
862{
863 ULONG Idx = 0;
864 BA_ORI_ENTRY *pBAEntry;
865 BOOLEAN Cancelled;
866
867 if (Wcid >= MAX_LEN_OF_MAC_TABLE)
868 {
869 return;
870 }
871
872 //
873 // Locate corresponding BA Originator Entry in BA Table with the (pAddr,TID).
874 //
875 Idx = pAd->MacTab.Content[Wcid].BAOriWcidArray[TID];
876 if ((Idx == 0) || (Idx >= MAX_LEN_OF_BA_ORI_TABLE))
877 {
878 if (bForceSend == TRUE)
879 {
880 // force send specified TID DelBA
881 MLME_DELBA_REQ_STRUCT DelbaReq;
882 MLME_QUEUE_ELEM *Elem = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG);
883 if (Elem != NULL)
884 {
885 NdisZeroMemory(&DelbaReq, sizeof(DelbaReq));
886 NdisZeroMemory(Elem, sizeof(MLME_QUEUE_ELEM));
887
888 COPY_MAC_ADDR(DelbaReq.Addr, pAd->MacTab.Content[Wcid].Addr);
889 DelbaReq.Wcid = Wcid;
890 DelbaReq.TID = TID;
891 DelbaReq.Initiator = ORIGINATOR;
892 Elem->MsgLen = sizeof(DelbaReq);
893 NdisMoveMemory(Elem->Msg, &DelbaReq, sizeof(DelbaReq));
894 MlmeDELBAAction(pAd, Elem);
895 kfree(Elem);
896 }
897 else
898 {
899 DBGPRINT(RT_DEBUG_ERROR, ("%s(bForceSend):alloc memory failed!\n", __FUNCTION__));
900 }
901 }
902
903 return;
904 }
905
906 DBGPRINT(RT_DEBUG_TRACE,("%s===>Wcid=%d.TID=%d \n", __FUNCTION__, Wcid, TID));
907
908 pBAEntry = &pAd->BATable.BAOriEntry[Idx];
909 DBGPRINT(RT_DEBUG_TRACE,("\t===>Idx = %ld, Wcid=%d.TID=%d, ORI_BA_Status = %d \n", Idx, Wcid, TID, pBAEntry->ORI_BA_Status));
910 //
911 // Prepare DelBA action frame and send to the peer.
912 //
913 if ((bPassive == FALSE) && (TID == pBAEntry->TID) && (pBAEntry->ORI_BA_Status == Originator_Done))
914 {
915 MLME_DELBA_REQ_STRUCT DelbaReq;
916 MLME_QUEUE_ELEM *Elem = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG);
917 if (Elem != NULL)
918 {
919 NdisZeroMemory(&DelbaReq, sizeof(DelbaReq));
920 NdisZeroMemory(Elem, sizeof(MLME_QUEUE_ELEM));
921
922 COPY_MAC_ADDR(DelbaReq.Addr, pAd->MacTab.Content[Wcid].Addr);
923 DelbaReq.Wcid = Wcid;
924 DelbaReq.TID = pBAEntry->TID;
925 DelbaReq.Initiator = ORIGINATOR;
926 Elem->MsgLen = sizeof(DelbaReq);
927 NdisMoveMemory(Elem->Msg, &DelbaReq, sizeof(DelbaReq));
928 MlmeDELBAAction(pAd, Elem);
929 kfree(Elem);
930 }
931 else
932 {
933 DBGPRINT(RT_DEBUG_ERROR, ("%s():alloc memory failed!\n", __FUNCTION__));
934 return;
935 }
936 }
937 RTMPCancelTimer(&pBAEntry->ORIBATimer, &Cancelled);
938 BATableFreeOriEntry(pAd, Idx);
939
940 if (bPassive)
941 {
942 //BAOriSessionSetUp(pAd, &pAd->MacTab.Content[Wcid], TID, 0, 10000, TRUE);
943 }
944}
945
946VOID BARecSessionTearDown(
947 IN OUT PRTMP_ADAPTER pAd,
948 IN UCHAR Wcid,
949 IN UCHAR TID,
950 IN BOOLEAN bPassive)
951{
952 ULONG Idx = 0;
953 BA_REC_ENTRY *pBAEntry;
954
955 if (Wcid >= MAX_LEN_OF_MAC_TABLE)
956 {
957 return;
958 }
959
960 //
961 // Locate corresponding BA Originator Entry in BA Table with the (pAddr,TID).
962 //
963 Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID];
964 if (Idx == 0)
965 return;
966
967 DBGPRINT(RT_DEBUG_TRACE,("%s===>Wcid=%d.TID=%d \n", __FUNCTION__, Wcid, TID));
968
969
970 pBAEntry = &pAd->BATable.BARecEntry[Idx];
971 DBGPRINT(RT_DEBUG_TRACE,("\t===>Idx = %ld, Wcid=%d.TID=%d, REC_BA_Status = %d \n", Idx, Wcid, TID, pBAEntry->REC_BA_Status));
972 //
973 // Prepare DelBA action frame and send to the peer.
974 //
975 if ((TID == pBAEntry->TID) && (pBAEntry->REC_BA_Status == Recipient_Accept))
976 {
977 MLME_DELBA_REQ_STRUCT DelbaReq;
978 BOOLEAN Cancelled;
979 //ULONG offset;
980 //UINT32 VALUE;
981
982 RTMPCancelTimer(&pBAEntry->RECBATimer, &Cancelled);
983
984 //
985 // 1. Send DELBA Action Frame
986 //
987 if (bPassive == FALSE)
988 {
989 MLME_QUEUE_ELEM *Elem = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG);
990 if (Elem != NULL)
991 {
992 NdisZeroMemory(&DelbaReq, sizeof(DelbaReq));
993 NdisZeroMemory(Elem, sizeof(MLME_QUEUE_ELEM));
994
995 COPY_MAC_ADDR(DelbaReq.Addr, pAd->MacTab.Content[Wcid].Addr);
996 DelbaReq.Wcid = Wcid;
997 DelbaReq.TID = TID;
998 DelbaReq.Initiator = RECIPIENT;
999 Elem->MsgLen = sizeof(DelbaReq);
1000 NdisMoveMemory(Elem->Msg, &DelbaReq, sizeof(DelbaReq));
1001 MlmeDELBAAction(pAd, Elem);
1002 kfree(Elem);
1003 }
1004 else
1005 {
1006 DBGPRINT(RT_DEBUG_ERROR, ("%s():alloc memory failed!\n", __FUNCTION__));
1007 return;
1008 }
1009 }
1010
1011
1012 //
1013 // 2. Free resource of BA session
1014 //
1015 // flush all pending reordering mpdus
1016 ba_refresh_reordering_mpdus(pAd, pBAEntry);
1017
1018 NdisAcquireSpinLock(&pAd->BATabLock);
1019
1020 // Erase Bitmap flag.
1021 pBAEntry->LastIndSeq = RESET_RCV_SEQ;
1022 pBAEntry->BAWinSize = 0;
1023 // Erase Bitmap flag at software mactable
1024 pAd->MacTab.Content[Wcid].RXBAbitmap &= (~(1<<(pBAEntry->TID)));
1025 pAd->MacTab.Content[Wcid].BARecWcidArray[TID] = 0;
1026
1027 RTMP_DEL_BA_SESSION_FROM_ASIC(pAd, Wcid, TID);
1028
1029 NdisReleaseSpinLock(&pAd->BATabLock);
1030
1031 }
1032
1033 BATableFreeRecEntry(pAd, Idx);
1034}
1035
1036VOID BASessionTearDownALL(
1037 IN OUT PRTMP_ADAPTER pAd,
1038 IN UCHAR Wcid)
1039{
1040 int i;
1041
1042 for (i=0; i<NUM_OF_TID; i++)
1043 {
1044 BAOriSessionTearDown(pAd, Wcid, i, FALSE, FALSE);
1045 BARecSessionTearDown(pAd, Wcid, i, FALSE);
1046 }
1047}
1048
1049
1050/*
1051 ==========================================================================
1052 Description:
1053 Retry sending ADDBA Reqest.
1054
1055 IRQL = DISPATCH_LEVEL
1056
1057 Parametrs:
1058 p8023Header: if this is already 802.3 format, p8023Header is NULL
1059
1060 Return : TRUE if put into rx reordering buffer, shouldn't indicaterxhere.
1061 FALSE , then continue indicaterx at this moment.
1062 ==========================================================================
1063 */
1064VOID BAOriSessionSetupTimeout(
1065 IN PVOID SystemSpecific1,
1066 IN PVOID FunctionContext,
1067 IN PVOID SystemSpecific2,
1068 IN PVOID SystemSpecific3)
1069{
1070 BA_ORI_ENTRY *pBAEntry = (BA_ORI_ENTRY *)FunctionContext;
1071 MAC_TABLE_ENTRY *pEntry;
1072 PRTMP_ADAPTER pAd;
1073
1074 if (pBAEntry == NULL)
1075 return;
1076
1077 pAd = pBAEntry->pAdapter;
1078
1079#ifdef CONFIG_STA_SUPPORT
1080 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1081 {
1082 // Do nothing if monitor mode is on
1083 if (MONITOR_ON(pAd))
1084 return;
1085 }
1086#endif // CONFIG_STA_SUPPORT //
1087
1088#ifdef RALINK_ATE
1089 // Nothing to do in ATE mode.
1090 if (ATE_ON(pAd))
1091 return;
1092#endif // RALINK_ATE //
1093
1094 pEntry = &pAd->MacTab.Content[pBAEntry->Wcid];
1095
1096 if ((pBAEntry->ORI_BA_Status == Originator_WaitRes) && (pBAEntry->Token < ORI_SESSION_MAX_RETRY))
1097 {
1098 MLME_ADDBA_REQ_STRUCT AddbaReq;
1099
1100 NdisZeroMemory(&AddbaReq, sizeof(AddbaReq));
1101 COPY_MAC_ADDR(AddbaReq.pAddr, pEntry->Addr);
1102 AddbaReq.Wcid = (UCHAR)(pEntry->Aid);
1103 AddbaReq.TID = pBAEntry->TID;
1104 AddbaReq.BaBufSize = pAd->CommonCfg.BACapability.field.RxBAWinLimit;
1105 AddbaReq.TimeOutValue = 0;
1106 AddbaReq.Token = pBAEntry->Token;
1107 MlmeEnqueue(pAd, ACTION_STATE_MACHINE, MT2_MLME_ADD_BA_CATE, sizeof(MLME_ADDBA_REQ_STRUCT), (PVOID)&AddbaReq);
1108 RTMP_MLME_HANDLER(pAd);
1109 DBGPRINT(RT_DEBUG_TRACE,("BA Ori Session Timeout(%d) : Send ADD BA again\n", pBAEntry->Token));
1110
1111 pBAEntry->Token++;
1112 RTMPSetTimer(&pBAEntry->ORIBATimer, ORI_BA_SESSION_TIMEOUT);
1113 }
1114 else
1115 {
1116 BATableFreeOriEntry(pAd, pEntry->BAOriWcidArray[pBAEntry->TID]);
1117 }
1118}
1119
1120/*
1121 ==========================================================================
1122 Description:
1123 Retry sending ADDBA Reqest.
1124
1125 IRQL = DISPATCH_LEVEL
1126
1127 Parametrs:
1128 p8023Header: if this is already 802.3 format, p8023Header is NULL
1129
1130 Return : TRUE if put into rx reordering buffer, shouldn't indicaterxhere.
1131 FALSE , then continue indicaterx at this moment.
1132 ==========================================================================
1133 */
1134VOID BARecSessionIdleTimeout(
1135 IN PVOID SystemSpecific1,
1136 IN PVOID FunctionContext,
1137 IN PVOID SystemSpecific2,
1138 IN PVOID SystemSpecific3)
1139{
1140
1141 BA_REC_ENTRY *pBAEntry = (BA_REC_ENTRY *)FunctionContext;
1142 PRTMP_ADAPTER pAd;
1143 ULONG Now32;
1144
1145 if (pBAEntry == NULL)
1146 return;
1147
1148 if ((pBAEntry->REC_BA_Status == Recipient_Accept))
1149 {
1150 NdisGetSystemUpTime(&Now32);
1151
1152 if (RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer + REC_BA_SESSION_IDLE_TIMEOUT)))
1153 {
1154 pAd = pBAEntry->pAdapter;
1155 // flush all pending reordering mpdus
1156 ba_refresh_reordering_mpdus(pAd, pBAEntry);
1157 DBGPRINT(RT_DEBUG_OFF, ("%ld: REC BA session Timeout\n", Now32));
1158 }
1159 }
1160}
1161
1162
1163VOID PeerAddBAReqAction(
1164 IN PRTMP_ADAPTER pAd,
1165 IN MLME_QUEUE_ELEM *Elem)
1166
1167{
1168 // 7.4.4.1
1169 //ULONG Idx;
1170 UCHAR Status = 1;
1171 UCHAR pAddr[6];
1172 FRAME_ADDBA_RSP ADDframe;
1173 PUCHAR pOutBuffer = NULL;
1174 NDIS_STATUS NStatus;
1175 PFRAME_ADDBA_REQ pAddreqFrame = NULL;
1176 //UCHAR BufSize;
1177 ULONG FrameLen;
1178 PULONG ptemp;
1179 PMAC_TABLE_ENTRY pMacEntry;
1180
1181 DBGPRINT(RT_DEBUG_TRACE, ("%s ==> (Wcid = %d)\n", __FUNCTION__, Elem->Wcid));
1182
1183 //hex_dump("AddBAReq", Elem->Msg, Elem->MsgLen);
1184
1185 //ADDBA Request from unknown peer, ignore this.
1186 if (Elem->Wcid >= MAX_LEN_OF_MAC_TABLE)
1187 return;
1188
1189 pMacEntry = &pAd->MacTab.Content[Elem->Wcid];
1190 DBGPRINT(RT_DEBUG_TRACE,("BA - PeerAddBAReqAction----> \n"));
1191 ptemp = (PULONG)Elem->Msg;
1192 //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)));
1193
1194 if (PeerAddBAReqActionSanity(pAd, Elem->Msg, Elem->MsgLen, pAddr))
1195 {
1196
1197 if ((pAd->CommonCfg.bBADecline == FALSE) && IS_HT_STA(pMacEntry))
1198 {
1199 pAddreqFrame = (PFRAME_ADDBA_REQ)(&Elem->Msg[0]);
1200 DBGPRINT(RT_DEBUG_OFF, ("Rcv Wcid(%d) AddBAReq\n", Elem->Wcid));
1201 if (BARecSessionAdd(pAd, &pAd->MacTab.Content[Elem->Wcid], pAddreqFrame))
1202 Status = 0;
1203 else
1204 Status = 38; // more parameters have invalid values
1205 }
1206 else
1207 {
1208 Status = 37; // the request has been declined.
1209 }
1210 }
1211
1212 if (pAd->MacTab.Content[Elem->Wcid].ValidAsCLI)
1213 ASSERT(pAd->MacTab.Content[Elem->Wcid].Sst == SST_ASSOC);
1214
1215 pAddreqFrame = (PFRAME_ADDBA_REQ)(&Elem->Msg[0]);
1216 // 2. Always send back ADDBA Response
1217 NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory
1218 if (NStatus != NDIS_STATUS_SUCCESS)
1219 {
1220 DBGPRINT(RT_DEBUG_TRACE,("ACTION - PeerBAAction() allocate memory failed \n"));
1221 return;
1222 }
1223
1224 NdisZeroMemory(&ADDframe, sizeof(FRAME_ADDBA_RSP));
1225 // 2-1. Prepare ADDBA Response frame.
1226#ifdef CONFIG_STA_SUPPORT
1227 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1228 {
1229 if (ADHOC_ON(pAd))
1230 ActHeaderInit(pAd, &ADDframe.Hdr, pAddr, pAd->CurrentAddress, pAd->CommonCfg.Bssid);
1231 else
1232#ifdef QOS_DLS_SUPPORT
1233 if (pAd->MacTab.Content[Elem->Wcid].ValidAsDls)
1234 ActHeaderInit(pAd, &ADDframe.Hdr, pAddr, pAd->CurrentAddress, pAd->CommonCfg.Bssid);
1235 else
1236#endif // QOS_DLS_SUPPORT //
1237 ActHeaderInit(pAd, &ADDframe.Hdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pAddr);
1238 }
1239#endif // CONFIG_STA_SUPPORT //
1240 ADDframe.Category = CATEGORY_BA;
1241 ADDframe.Action = ADDBA_RESP;
1242 ADDframe.Token = pAddreqFrame->Token;
1243 // What is the Status code?? need to check.
1244 ADDframe.StatusCode = Status;
1245 ADDframe.BaParm.BAPolicy = IMMED_BA;
1246 ADDframe.BaParm.AMSDUSupported = 0;
1247 ADDframe.BaParm.TID = pAddreqFrame->BaParm.TID;
1248 ADDframe.BaParm.BufSize = min(((UCHAR)pAddreqFrame->BaParm.BufSize), (UCHAR)pAd->CommonCfg.BACapability.field.RxBAWinLimit);
1249 if (ADDframe.BaParm.BufSize == 0)
1250 {
1251 ADDframe.BaParm.BufSize = 64;
1252 }
1253 ADDframe.TimeOutValue = 0; //pAddreqFrame->TimeOutValue;
1254
1255 *(USHORT *)(&ADDframe.BaParm) = cpu2le16(*(USHORT *)(&ADDframe.BaParm));
1256 ADDframe.StatusCode = cpu2le16(ADDframe.StatusCode);
1257 ADDframe.TimeOutValue = cpu2le16(ADDframe.TimeOutValue);
1258
1259 MakeOutgoingFrame(pOutBuffer, &FrameLen,
1260 sizeof(FRAME_ADDBA_RSP), &ADDframe,
1261 END_OF_ARGS);
1262 MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
1263 MlmeFreeMemory(pAd, pOutBuffer);
1264
1265 DBGPRINT(RT_DEBUG_TRACE, ("%s(%d): TID(%d), BufSize(%d) <== \n", __FUNCTION__, Elem->Wcid, ADDframe.BaParm.TID,
1266 ADDframe.BaParm.BufSize));
1267}
1268
1269
1270VOID PeerAddBARspAction(
1271 IN PRTMP_ADAPTER pAd,
1272 IN MLME_QUEUE_ELEM *Elem)
1273
1274{
1275 //UCHAR Idx, i;
1276 //PUCHAR pOutBuffer = NULL;
1277 PFRAME_ADDBA_RSP pFrame = NULL;
1278 //PBA_ORI_ENTRY pBAEntry;
1279
1280 //ADDBA Response from unknown peer, ignore this.
1281 if (Elem->Wcid >= MAX_LEN_OF_MAC_TABLE)
1282 return;
1283
1284 DBGPRINT(RT_DEBUG_TRACE, ("%s ==> Wcid(%d)\n", __FUNCTION__, Elem->Wcid));
1285
1286 //hex_dump("PeerAddBARspAction()", Elem->Msg, Elem->MsgLen);
1287
1288 if (PeerAddBARspActionSanity(pAd, Elem->Msg, Elem->MsgLen))
1289 {
1290 pFrame = (PFRAME_ADDBA_RSP)(&Elem->Msg[0]);
1291
1292 DBGPRINT(RT_DEBUG_TRACE, ("\t\t StatusCode = %d\n", pFrame->StatusCode));
1293 switch (pFrame->StatusCode)
1294 {
1295 case 0:
1296 // I want a BAsession with this peer as an originator.
1297 BAOriSessionAdd(pAd, &pAd->MacTab.Content[Elem->Wcid], pFrame);
1298 break;
1299 default:
1300 // check status == USED ???
1301 BAOriSessionTearDown(pAd, Elem->Wcid, pFrame->BaParm.TID, TRUE, FALSE);
1302 break;
1303 }
1304 // Rcv Decline StatusCode
1305 if ((pFrame->StatusCode == 37)
1306#ifdef CONFIG_STA_SUPPORT
1307 || ((pAd->OpMode == OPMODE_STA) && STA_TGN_WIFI_ON(pAd) && (pFrame->StatusCode != 0))
1308#endif // CONFIG_STA_SUPPORT //
1309 )
1310 {
1311 pAd->MacTab.Content[Elem->Wcid].BADeclineBitmap |= 1<<pFrame->BaParm.TID;
1312 }
1313 }
1314}
1315
1316VOID PeerDelBAAction(
1317 IN PRTMP_ADAPTER pAd,
1318 IN MLME_QUEUE_ELEM *Elem)
1319
1320{
1321 //UCHAR Idx;
1322 //PUCHAR pOutBuffer = NULL;
1323 PFRAME_DELBA_REQ pDelFrame = NULL;
1324
1325 DBGPRINT(RT_DEBUG_TRACE,("%s ==>\n", __FUNCTION__));
1326 //DELBA Request from unknown peer, ignore this.
1327 if (PeerDelBAActionSanity(pAd, Elem->Wcid, Elem->Msg, Elem->MsgLen))
1328 {
1329 pDelFrame = (PFRAME_DELBA_REQ)(&Elem->Msg[0]);
1330 if (pDelFrame->DelbaParm.Initiator == ORIGINATOR)
1331 {
1332 DBGPRINT(RT_DEBUG_TRACE,("BA - PeerDelBAAction----> ORIGINATOR\n"));
1333 BARecSessionTearDown(pAd, Elem->Wcid, pDelFrame->DelbaParm.TID, TRUE);
1334 }
1335 else
1336 {
1337 DBGPRINT(RT_DEBUG_TRACE,("BA - PeerDelBAAction----> RECIPIENT, Reason = %d\n", pDelFrame->ReasonCode));
1338 //hex_dump("DelBA Frame", pDelFrame, Elem->MsgLen);
1339 BAOriSessionTearDown(pAd, Elem->Wcid, pDelFrame->DelbaParm.TID, TRUE, FALSE);
1340 }
1341 }
1342}
1343
1344
1345BOOLEAN CntlEnqueueForRecv(
1346 IN PRTMP_ADAPTER pAd,
1347 IN ULONG Wcid,
1348 IN ULONG MsgLen,
1349 IN PFRAME_BA_REQ pMsg)
1350{
1351 PFRAME_BA_REQ pFrame = pMsg;
1352 //PRTMP_REORDERBUF pBuffer;
1353 //PRTMP_REORDERBUF pDmaBuf;
1354 PBA_REC_ENTRY pBAEntry;
1355 //BOOLEAN Result;
1356 ULONG Idx;
1357 //UCHAR NumRxPkt;
1358 UCHAR TID;//, i;
1359
1360 TID = (UCHAR)pFrame->BARControl.TID;
1361
1362 DBGPRINT(RT_DEBUG_TRACE, ("%s(): BAR-Wcid(%ld), Tid (%d)\n", __FUNCTION__, Wcid, TID));
1363 //hex_dump("BAR", (PCHAR) pFrame, MsgLen);
1364 // Do nothing if the driver is starting halt state.
1365 // This might happen when timer already been fired before cancel timer with mlmehalt
1366 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
1367 return FALSE;
1368
1369 // First check the size, it MUST not exceed the mlme queue size
1370 if (MsgLen > MGMT_DMA_BUFFER_SIZE)
1371 {
1372 DBGPRINT_ERR(("CntlEnqueueForRecv: frame too large, size = %ld \n", MsgLen));
1373 return FALSE;
1374 }
1375 else if (MsgLen != sizeof(FRAME_BA_REQ))
1376 {
1377 DBGPRINT_ERR(("CntlEnqueueForRecv: BlockAck Request frame length size = %ld incorrect\n", MsgLen));
1378 return FALSE;
1379 }
1380 else if (MsgLen != sizeof(FRAME_BA_REQ))
1381 {
1382 DBGPRINT_ERR(("CntlEnqueueForRecv: BlockAck Request frame length size = %ld incorrect\n", MsgLen));
1383 return FALSE;
1384 }
1385
1386 if ((Wcid < MAX_LEN_OF_MAC_TABLE) && (TID < 8))
1387 {
1388 // if this receiving packet is from SA that is in our OriEntry. Since WCID <9 has direct mapping. no need search.
1389 Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID];
1390 pBAEntry = &pAd->BATable.BARecEntry[Idx];
1391 }
1392 else
1393 {
1394 return FALSE;
1395 }
1396
1397 DBGPRINT(RT_DEBUG_TRACE, ("BAR(%ld) : Tid (%d) - %04x:%04x\n", Wcid, TID, pFrame->BAStartingSeq.field.StartSeq, pBAEntry->LastIndSeq ));
1398
1399 if (SEQ_SMALLER(pBAEntry->LastIndSeq, pFrame->BAStartingSeq.field.StartSeq, MAXSEQ))
1400 {
1401 //DBGPRINT(RT_DEBUG_TRACE, ("BAR Seq = %x, LastIndSeq = %x\n", pFrame->BAStartingSeq.field.StartSeq, pBAEntry->LastIndSeq));
1402 ba_indicate_reordering_mpdus_le_seq(pAd, pBAEntry, pFrame->BAStartingSeq.field.StartSeq);
1403 pBAEntry->LastIndSeq = (pFrame->BAStartingSeq.field.StartSeq == 0) ? MAXSEQ :(pFrame->BAStartingSeq.field.StartSeq -1);
1404 }
1405 //ba_refresh_reordering_mpdus(pAd, pBAEntry);
1406 return TRUE;
1407}
1408
1409/*
1410Description : Send PSMP Action frame If PSMP mode switches.
1411*/
1412VOID SendPSMPAction(
1413 IN PRTMP_ADAPTER pAd,
1414 IN UCHAR Wcid,
1415 IN UCHAR Psmp)
1416{
1417 PUCHAR pOutBuffer = NULL;
1418 NDIS_STATUS NStatus;
1419 //ULONG Idx;
1420 FRAME_PSMP_ACTION Frame;
1421 ULONG FrameLen;
1422
1423 NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory
1424 if (NStatus != NDIS_STATUS_SUCCESS)
1425 {
1426 DBGPRINT(RT_DEBUG_ERROR,("BA - MlmeADDBAAction() allocate memory failed \n"));
1427 return;
1428 }
1429#ifdef CONFIG_STA_SUPPORT
1430 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1431 ActHeaderInit(pAd, &Frame.Hdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pAd->MacTab.Content[Wcid].Addr);
1432#endif // CONFIG_STA_SUPPORT //
1433
1434 Frame.Category = CATEGORY_HT;
1435 Frame.Action = SMPS_ACTION;
1436 switch (Psmp)
1437 {
1438 case MMPS_ENABLE:
1439#ifdef RT30xx
1440 if (IS_RT30xx(pAd)
1441 &&(pAd->Antenna.field.RxPath>1||pAd->Antenna.field.TxPath>1))
1442 {
1443 RTMP_ASIC_MMPS_DISABLE(pAd);
1444 }
1445#endif // RT30xx //
1446 Frame.Psmp = 0;
1447 break;
1448 case MMPS_DYNAMIC:
1449 Frame.Psmp = 3;
1450 break;
1451 case MMPS_STATIC:
1452#ifdef RT30xx
1453 if (IS_RT30xx(pAd)
1454 &&(pAd->Antenna.field.RxPath>1||pAd->Antenna.field.TxPath>1))
1455 {
1456 RTMP_ASIC_MMPS_ENABLE(pAd);
1457 }
1458#endif // RT30xx //
1459 Frame.Psmp = 1;
1460 break;
1461 }
1462 MakeOutgoingFrame(pOutBuffer, &FrameLen,
1463 sizeof(FRAME_PSMP_ACTION), &Frame,
1464 END_OF_ARGS);
1465 MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
1466 MlmeFreeMemory(pAd, pOutBuffer);
1467 DBGPRINT(RT_DEBUG_ERROR,("HT - SendPSMPAction( %d ) \n", Frame.Psmp));
1468}
1469
1470
1471#define RADIO_MEASUREMENT_REQUEST_ACTION 0
1472
1473typedef struct PACKED
1474{
1475 UCHAR RegulatoryClass;
1476 UCHAR ChannelNumber;
1477 USHORT RandomInterval;
1478 USHORT MeasurementDuration;
1479 UCHAR MeasurementMode;
1480 UCHAR BSSID[MAC_ADDR_LEN];
1481 UCHAR ReportingCondition;
1482 UCHAR Threshold;
1483 UCHAR SSIDIE[2]; // 2 byte
1484} BEACON_REQUEST;
1485
1486typedef struct PACKED
1487{
1488 UCHAR ID;
1489 UCHAR Length;
1490 UCHAR Token;
1491 UCHAR RequestMode;
1492 UCHAR Type;
1493} MEASUREMENT_REQ;
1494
1495
1496
1497
1498void convert_reordering_packet_to_preAMSDU_or_802_3_packet(
1499 IN PRTMP_ADAPTER pAd,
1500 IN RX_BLK *pRxBlk,
1501 IN UCHAR FromWhichBSSID)
1502{
1503 PNDIS_PACKET pRxPkt;
1504 UCHAR Header802_3[LENGTH_802_3];
1505
1506 // 1. get 802.3 Header
1507 // 2. remove LLC
1508 // a. pointer pRxBlk->pData to payload
1509 // b. modify pRxBlk->DataSize
1510
1511#ifdef CONFIG_STA_SUPPORT
1512 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1513 RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3);
1514#endif // CONFIG_STA_SUPPORT //
1515
1516 ASSERT(pRxBlk->pRxPacket);
1517 pRxPkt = RTPKT_TO_OSPKT(pRxBlk->pRxPacket);
1518
1519 SET_OS_PKT_NETDEV(pRxPkt, get_netdev_from_bssid(pAd, FromWhichBSSID));
1520 SET_OS_PKT_DATAPTR(pRxPkt, pRxBlk->pData);
1521 SET_OS_PKT_LEN(pRxPkt, pRxBlk->DataSize);
1522 SET_OS_PKT_DATATAIL(pRxPkt, pRxBlk->pData, pRxBlk->DataSize);
1523
1524 //
1525 // copy 802.3 header, if necessary
1526 //
1527 if (!RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU))
1528 {
1529
1530#ifdef CONFIG_STA_SUPPORT
1531 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1532 {
1533#ifdef LINUX
1534 NdisMoveMemory(skb_push(pRxPkt, LENGTH_802_3), Header802_3, LENGTH_802_3);
1535#endif
1536 }
1537#endif // CONFIG_STA_SUPPORT //
1538 }
1539}
1540
1541
1542#define INDICATE_LEGACY_OR_AMSDU(_pAd, _pRxBlk, _fromWhichBSSID) \
1543 do \
1544 { \
1545 if (RX_BLK_TEST_FLAG(_pRxBlk, fRX_AMSDU)) \
1546 { \
1547 Indicate_AMSDU_Packet(_pAd, _pRxBlk, _fromWhichBSSID); \
1548 } \
1549 else if (RX_BLK_TEST_FLAG(_pRxBlk, fRX_EAP)) \
1550 { \
1551 Indicate_EAPOL_Packet(_pAd, _pRxBlk, _fromWhichBSSID); \
1552 } \
1553 else \
1554 { \
1555 Indicate_Legacy_Packet(_pAd, _pRxBlk, _fromWhichBSSID); \
1556 } \
1557 } while (0);
1558
1559
1560
1561static VOID ba_enqueue_reordering_packet(
1562 IN PRTMP_ADAPTER pAd,
1563 IN PBA_REC_ENTRY pBAEntry,
1564 IN RX_BLK *pRxBlk,
1565 IN UCHAR FromWhichBSSID)
1566{
1567 struct reordering_mpdu *mpdu_blk;
1568 UINT16 Sequence = (UINT16) pRxBlk->pHeader->Sequence;
1569
1570 mpdu_blk = ba_mpdu_blk_alloc(pAd);
1571 if ((mpdu_blk != NULL) &&
1572 (!RX_BLK_TEST_FLAG(pRxBlk, fRX_EAP)))
1573 {
1574 // Write RxD buffer address & allocated buffer length
1575 NdisAcquireSpinLock(&pBAEntry->RxReRingLock);
1576
1577 mpdu_blk->Sequence = Sequence;
1578
1579 mpdu_blk->bAMSDU = RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU);
1580
1581 convert_reordering_packet_to_preAMSDU_or_802_3_packet(pAd, pRxBlk, FromWhichBSSID);
1582
1583 STATS_INC_RX_PACKETS(pAd, FromWhichBSSID);
1584
1585 //
1586 // it is necessary for reordering packet to record
1587 // which BSS it come from
1588 //
1589 RTMP_SET_PACKET_IF(pRxBlk->pRxPacket, FromWhichBSSID);
1590
1591 mpdu_blk->pPacket = pRxBlk->pRxPacket;
1592
1593 if (ba_reordering_mpdu_insertsorted(&pBAEntry->list, mpdu_blk) == FALSE)
1594 {
1595 // had been already within reordering list
1596 // don't indicate
1597 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_SUCCESS);
1598 ba_mpdu_blk_free(pAd, mpdu_blk);
1599 }
1600
1601 ASSERT((0<= pBAEntry->list.qlen) && (pBAEntry->list.qlen <= pBAEntry->BAWinSize));
1602 NdisReleaseSpinLock(&pBAEntry->RxReRingLock);
1603 }
1604 else
1605 {
1606 DBGPRINT(RT_DEBUG_ERROR, ("!!! (%d) Can't allocate reordering mpdu blk\n",
1607 pBAEntry->list.qlen));
1608 /*
1609 * flush all pending reordering mpdus
1610 * and receving mpdu to upper layer
1611 * make tcp/ip to take care reordering mechanism
1612 */
1613 //ba_refresh_reordering_mpdus(pAd, pBAEntry);
1614 ba_indicate_reordering_mpdus_le_seq(pAd, pBAEntry, Sequence);
1615
1616 pBAEntry->LastIndSeq = Sequence;
1617 INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID);
1618 }
1619}
1620
1621
1622/*
1623 ==========================================================================
1624 Description:
1625 Indicate this packet to upper layer or put it into reordering buffer
1626
1627 Parametrs:
1628 pRxBlk : carry necessary packet info 802.11 format
1629 FromWhichBSSID : the packet received from which BSS
1630
1631 Return :
1632 none
1633
1634 Note :
1635 the packet queued into reordering buffer need to cover to 802.3 format
1636 or pre_AMSDU format
1637 ==========================================================================
1638 */
1639
1640VOID Indicate_AMPDU_Packet(
1641 IN PRTMP_ADAPTER pAd,
1642 IN RX_BLK *pRxBlk,
1643 IN UCHAR FromWhichBSSID)
1644{
1645 USHORT Idx;
1646 PBA_REC_ENTRY pBAEntry = NULL;
1647 UINT16 Sequence = pRxBlk->pHeader->Sequence;
1648 ULONG Now32;
1649 UCHAR Wcid = pRxBlk->pRxWI->WirelessCliID;
1650 UCHAR TID = pRxBlk->pRxWI->TID;
1651
1652
1653 if (!RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU) && (pRxBlk->DataSize > MAX_RX_PKT_LEN))
1654 {
1655 // release packet
1656 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
1657 return;
1658 }
1659
1660
1661
1662 if (Wcid < MAX_LEN_OF_MAC_TABLE)
1663 {
1664 Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID];
1665 if (Idx == 0)
1666 {
1667 /* Rec BA Session had been torn down */
1668 INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID);
1669 return;
1670 }
1671 pBAEntry = &pAd->BATable.BARecEntry[Idx];
1672 }
1673 else
1674 {
1675 // impossible !!!
1676 ASSERT(0);
1677 // release packet
1678 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
1679 return;
1680 }
1681
1682 ASSERT(pBAEntry);
1683
1684 // update last rx time
1685 NdisGetSystemUpTime(&Now32);
1686
1687 pBAEntry->rcvSeq = Sequence;
1688
1689
1690 ba_flush_reordering_timeout_mpdus(pAd, pBAEntry, Now32);
1691 pBAEntry->LastIndSeqAtTimer = Now32;
1692
1693 //
1694 // Reset Last Indicate Sequence
1695 //
1696 if (pBAEntry->LastIndSeq == RESET_RCV_SEQ)
1697 {
1698 ASSERT((pBAEntry->list.qlen == 0) && (pBAEntry->list.next == NULL));
1699
1700 // reset rcv sequence of BA session
1701 pBAEntry->LastIndSeq = Sequence;
1702 pBAEntry->LastIndSeqAtTimer = Now32;
1703 INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID);
1704 return;
1705 }
1706
1707 //
1708 // I. Check if in order.
1709 //
1710 if (SEQ_STEPONE(Sequence, pBAEntry->LastIndSeq, MAXSEQ))
1711 {
1712 USHORT LastIndSeq;
1713
1714 pBAEntry->LastIndSeq = Sequence;
1715 INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID);
1716 LastIndSeq = ba_indicate_reordering_mpdus_in_order(pAd, pBAEntry, pBAEntry->LastIndSeq);
1717 if (LastIndSeq != RESET_RCV_SEQ)
1718 {
1719 pBAEntry->LastIndSeq = LastIndSeq;
1720 }
1721 pBAEntry->LastIndSeqAtTimer = Now32;
1722 }
1723 //
1724 // II. Drop Duplicated Packet
1725 //
1726 else if (Sequence == pBAEntry->LastIndSeq)
1727 {
1728
1729 // drop and release packet
1730 pBAEntry->nDropPacket++;
1731 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
1732 }
1733 //
1734 // III. Drop Old Received Packet
1735 //
1736 else if (SEQ_SMALLER(Sequence, pBAEntry->LastIndSeq, MAXSEQ))
1737 {
1738
1739 // drop and release packet
1740 pBAEntry->nDropPacket++;
1741 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
1742 }
1743 //
1744 // IV. Receive Sequence within Window Size
1745 //
1746 else if (SEQ_SMALLER(Sequence, (((pBAEntry->LastIndSeq+pBAEntry->BAWinSize+1)) & MAXSEQ), MAXSEQ))
1747 {
1748 ba_enqueue_reordering_packet(pAd, pBAEntry, pRxBlk, FromWhichBSSID);
1749 }
1750 //
1751 // V. Receive seq surpasses Win(lastseq + nMSDU). So refresh all reorder buffer
1752 //
1753 else
1754 {
1755 LONG WinStartSeq, TmpSeq;
1756
1757
1758 TmpSeq = Sequence - (pBAEntry->BAWinSize) -1;
1759 if (TmpSeq < 0)
1760 {
1761 TmpSeq = (MAXSEQ+1) + TmpSeq;
1762 }
1763 WinStartSeq = (TmpSeq+1) & MAXSEQ;
1764 ba_indicate_reordering_mpdus_le_seq(pAd, pBAEntry, WinStartSeq);
1765 pBAEntry->LastIndSeq = WinStartSeq; //TmpSeq;
1766
1767 pBAEntry->LastIndSeqAtTimer = Now32;
1768
1769 ba_enqueue_reordering_packet(pAd, pBAEntry, pRxBlk, FromWhichBSSID);
1770
1771 TmpSeq = ba_indicate_reordering_mpdus_in_order(pAd, pBAEntry, pBAEntry->LastIndSeq);
1772 if (TmpSeq != RESET_RCV_SEQ)
1773 {
1774 pBAEntry->LastIndSeq = TmpSeq;
1775 }
1776 }
1777}
1778
1779#endif // DOT11_N_SUPPORT //