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