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