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