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