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