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