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