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