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