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