1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29#ifdef DOT11_N_SUPPORT
30
31#include "../rt_config.h"
32
33
34#define BA_ORI_INIT_SEQ (pEntry->TxSeq[TID])
35
36#define ORI_SESSION_MAX_RETRY 8
37#define ORI_BA_SESSION_TIMEOUT (2000)
38#define REC_BA_SESSION_IDLE_TIMEOUT (1000)
39
40#define REORDERING_PACKET_TIMEOUT ((100 * OS_HZ)/1000)
41#define MAX_REORDERING_PACKET_TIMEOUT ((3000 * OS_HZ)/1000)
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)
84 {
85 if (pAd->MACVersion >= RALINK_3070_VERSION)
86 {
87 if (pEntryPeer->WepStatus != Ndis802_11EncryptionDisabled)
88 MaxSize = 7;
89 else
90 MaxSize = 13;
91 }
92 else
93 MaxSize = 31;
94 }
95 else if (pAd->MACVersion >= RALINK_2880E_VERSION)
96 {
97 if (pEntryPeer->WepStatus != Ndis802_11EncryptionDisabled)
98 MaxSize = 7;
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
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
139 }
140}
141
142
143
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
159 return(FALSE);
160 }
161 else
162 {
163
164 break;
165 }
166 }
167
168 mpdu->next = *ppScan;
169 *ppScan = mpdu;
170 list->qlen++;
171 return TRUE;
172}
173
174
175
176
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
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
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
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
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
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
271 NdisAllocateSpinLock(&pAd->mpdu_blk_pool.lock);
272
273
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
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
292 for (i=0; i<num; i++)
293 {
294
295 mpdu_blk = (struct reordering_mpdu *) mem;
296
297 NdisZeroMemory(mpdu_blk, sizeof(struct reordering_mpdu));
298
299 mem += sizeof(struct reordering_mpdu);
300
301 ba_enqueue(freelist, mpdu_blk);
302 }
303
304 return(TRUE);
305}
306
307
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
318
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
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
349 if (!SEQ_STEPONE(mpdu_blk->Sequence, StartSeq, MAXSEQ))
350 {
351 break;
352 }
353
354 mpdu_blk = ba_reordering_mpdu_dequeue(&pBAEntry->list);
355
356 ANNOUNCE_REORDERING_PACKET(pAd, mpdu_blk);
357
358 StartSeq = mpdu_blk->Sequence;
359 LastIndSeq = StartSeq;
360
361 ba_mpdu_blk_free(pAd, mpdu_blk);
362 }
363
364 NdisReleaseSpinLock(&pBAEntry->RxReRingLock);
365
366
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
381 if ((mpdu_blk->Sequence == Sequence) || SEQ_SMALLER(mpdu_blk->Sequence, Sequence, MAXSEQ))
382 {
383
384 mpdu_blk = ba_reordering_mpdu_dequeue(&pBAEntry->list);
385
386 ANNOUNCE_REORDERING_PACKET(pAd, mpdu_blk);
387
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
408 while ((mpdu_blk = ba_reordering_mpdu_dequeue(&pBAEntry->list)))
409 {
410
411 ANNOUNCE_REORDERING_PACKET(pAd, mpdu_blk);
412
413 pBAEntry->LastIndSeq = mpdu_blk->Sequence;
414 ba_mpdu_blk_free(pAd, mpdu_blk);
415
416
417 }
418 ASSERT(pBAEntry->list.qlen == 0);
419 pBAEntry->LastIndSeq = RESET_RCV_SEQ;
420 NdisReleaseSpinLock(&pBAEntry->RxReRingLock);
421}
422
423
424
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
434
435
436
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
453
454
455
456
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
464
465 Sequence = ba_indicate_reordering_mpdus_in_order(pAd, pBAEntry, Sequence);
466 if (Sequence != RESET_RCV_SEQ)
467 {
468 pBAEntry->LastIndSeq = Sequence;
469 }
470
471 DBGPRINT(RT_DEBUG_OFF, ("%x, flush one!\n", pBAEntry->LastIndSeq));
472
473 }
474}
475
476
477
478
479
480
481VOID BAOriSessionSetUp(
482 IN PRTMP_ADAPTER pAd,
483 IN MAC_TABLE_ENTRY *pEntry,
484 IN UCHAR TID,
485 IN USHORT TimeOut,
486 IN ULONG DelayTime,
487 IN BOOLEAN isForced)
488
489{
490
491 BA_ORI_ENTRY *pBAEntry = NULL;
492 USHORT Idx;
493 BOOLEAN Cancelled;
494
495 if ((pAd->CommonCfg.BACapability.field.AutoBA != TRUE) && (isForced == FALSE))
496 return;
497
498
499 if (RTMPStaFixedTxMode(pAd, pEntry) != FIXED_TXMODE_HT)
500 return;
501
502 if ((pEntry->BADeclineBitmap & (1<<TID)) && (isForced == FALSE))
503 {
504
505 DelayTime = 3000;
506
507
508 }
509
510
511 Idx = pEntry->BAOriWcidArray[TID];
512 if (Idx == 0)
513 {
514
515 pBAEntry = BATableAllocOriEntry(pAd, &Idx);
516 if (pBAEntry == NULL)
517 {
518 DBGPRINT(RT_DEBUG_TRACE,("ADDBA - MlmeADDBAAction() allocate BA session failed \n"));
519 return;
520 }
521 }
522 else
523 {
524 pBAEntry =&pAd->BATable.BAOriEntry[Idx];
525 }
526
527 if (pBAEntry->ORI_BA_Status >= Originator_WaitRes)
528 {
529 return;
530 }
531
532 pEntry->BAOriWcidArray[TID] = Idx;
533
534
535 pBAEntry->ORI_BA_Status = Originator_WaitRes;
536 pBAEntry->Wcid = pEntry->Aid;
537 pBAEntry->BAWinSize = pAd->CommonCfg.BACapability.field.RxBAWinLimit;
538 pBAEntry->Sequence = BA_ORI_INIT_SEQ;
539 pBAEntry->Token = 1;
540 pBAEntry->TID = TID;
541 pBAEntry->TimeOutValue = TimeOut;
542 pBAEntry->pAdapter = pAd;
543
544 if (!(pEntry->TXBAbitmap & (1<<TID)))
545 {
546 RTMPInitTimer(pAd, &pBAEntry->ORIBATimer, GET_TIMER_FUNCTION(BAOriSessionSetupTimeout), pBAEntry, FALSE);
547 }
548 else
549 RTMPCancelTimer(&pBAEntry->ORIBATimer, &Cancelled);
550
551
552 RTMPSetTimer(&pBAEntry->ORIBATimer, DelayTime);
553}
554
555VOID BAOriSessionAdd(
556 IN PRTMP_ADAPTER pAd,
557 IN MAC_TABLE_ENTRY *pEntry,
558 IN PFRAME_ADDBA_RSP pFrame)
559{
560 BA_ORI_ENTRY *pBAEntry = NULL;
561 BOOLEAN Cancelled;
562 UCHAR TID;
563 USHORT Idx;
564 PUCHAR pOutBuffer2 = NULL;
565 NDIS_STATUS NStatus;
566 ULONG FrameLen;
567 FRAME_BAR FrameBar;
568
569 TID = pFrame->BaParm.TID;
570 Idx = pEntry->BAOriWcidArray[TID];
571 pBAEntry =&pAd->BATable.BAOriEntry[Idx];
572
573
574 if ((Idx !=0) && (pBAEntry->TID == TID) && (pBAEntry->ORI_BA_Status == Originator_WaitRes))
575 {
576 pBAEntry->BAWinSize = min(pBAEntry->BAWinSize, ((UCHAR)pFrame->BaParm.BufSize));
577 BA_MaxWinSizeReasign(pAd, pEntry, &pBAEntry->BAWinSize);
578
579 pBAEntry->TimeOutValue = pFrame->TimeOutValue;
580 pBAEntry->ORI_BA_Status = Originator_Done;
581 pAd->BATable.numDoneOriginator ++;
582
583
584 pBAEntry->Sequence = BA_ORI_INIT_SEQ;
585
586 pEntry->TXBAbitmap |= (1<<TID);
587 RTMPCancelTimer(&pBAEntry->ORIBATimer, &Cancelled);
588
589 pBAEntry->ORIBATimer.TimerValue = 0;
590
591 DBGPRINT(RT_DEBUG_TRACE,("%s : TXBAbitmap = %x, BAWinSize = %d, TimeOut = %ld\n", __FUNCTION__, pEntry->TXBAbitmap,
592 pBAEntry->BAWinSize, pBAEntry->ORIBATimer.TimerValue));
593
594
595 NStatus = MlmeAllocateMemory(pAd, &pOutBuffer2);
596 if (NStatus != NDIS_STATUS_SUCCESS)
597 {
598 DBGPRINT(RT_DEBUG_TRACE,("BA - BAOriSessionAdd() allocate memory failed \n"));
599 return;
600 }
601
602
603#ifdef CONFIG_STA_SUPPORT
604 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
605 BarHeaderInit(pAd, &FrameBar, pAd->MacTab.Content[pBAEntry->Wcid].Addr, pAd->CurrentAddress);
606#endif
607
608 FrameBar.StartingSeq.field.FragNum = 0;
609 FrameBar.StartingSeq.field.StartSeq = pBAEntry->Sequence;
610 FrameBar.BarControl.TID = pBAEntry->TID;
611 MakeOutgoingFrame(pOutBuffer2, &FrameLen,
612 sizeof(FRAME_BAR), &FrameBar,
613 END_OF_ARGS);
614 MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer2, FrameLen);
615 MlmeFreeMemory(pAd, pOutBuffer2);
616
617
618 if (pBAEntry->ORIBATimer.TimerValue)
619 RTMPSetTimer(&pBAEntry->ORIBATimer, pBAEntry->ORIBATimer.TimerValue);
620 }
621}
622
623BOOLEAN BARecSessionAdd(
624 IN PRTMP_ADAPTER pAd,
625 IN MAC_TABLE_ENTRY *pEntry,
626 IN PFRAME_ADDBA_REQ pFrame)
627{
628 BA_REC_ENTRY *pBAEntry = NULL;
629 BOOLEAN Status = TRUE;
630 BOOLEAN Cancelled;
631 USHORT Idx;
632 UCHAR TID;
633 UCHAR BAWinSize;
634
635
636
637
638 ASSERT(pEntry);
639
640
641 TID = pFrame->BaParm.TID;
642
643 BAWinSize = min(((UCHAR)pFrame->BaParm.BufSize), (UCHAR)pAd->CommonCfg.BACapability.field.RxBAWinLimit);
644
645
646 if (BAWinSize == 0)
647 {
648 BAWinSize = 64;
649 }
650
651 Idx = pEntry->BARecWcidArray[TID];
652
653
654 if (Idx == 0)
655 {
656 pBAEntry = BATableAllocRecEntry(pAd, &Idx);
657 }
658 else
659 {
660 pBAEntry = &pAd->BATable.BARecEntry[Idx];
661
662 ba_refresh_reordering_mpdus(pAd, pBAEntry);
663 }
664
665 DBGPRINT(RT_DEBUG_TRACE,("%s(%ld): Idx = %d, BAWinSize(req %d) = %d\n", __FUNCTION__, pAd->BATable.numAsRecipient, Idx,
666 pFrame->BaParm.BufSize, BAWinSize));
667
668
669 if (pBAEntry != NULL)
670 {
671 ASSERT(pBAEntry->list.qlen == 0);
672
673 pBAEntry->REC_BA_Status = Recipient_HandleRes;
674 pBAEntry->BAWinSize = BAWinSize;
675 pBAEntry->Wcid = pEntry->Aid;
676 pBAEntry->TID = TID;
677 pBAEntry->TimeOutValue = pFrame->TimeOutValue;
678 pBAEntry->REC_BA_Status = Recipient_Accept;
679
680 pBAEntry->LastIndSeq = RESET_RCV_SEQ;
681
682 DBGPRINT(RT_DEBUG_OFF, ("Start Seq = %08x\n", pFrame->BaStartSeq.field.StartSeq));
683
684 if (pEntry->RXBAbitmap & (1<<TID))
685 {
686 RTMPCancelTimer(&pBAEntry->RECBATimer, &Cancelled);
687 }
688 else
689 {
690 RTMPInitTimer(pAd, &pBAEntry->RECBATimer, GET_TIMER_FUNCTION(BARecSessionIdleTimeout), pBAEntry, TRUE);
691 }
692
693
694
695 pEntry->RXBAbitmap |= (1<<TID);
696 pEntry->BARecWcidArray[TID] = Idx;
697
698 pEntry->BADeclineBitmap &= ~(1<<TID);
699
700
701 RTMP_ADD_BA_SESSION_TO_ASIC(pAd, pEntry->Aid, TID);
702
703 DBGPRINT(RT_DEBUG_TRACE,("MACEntry[%d]RXBAbitmap = 0x%x. BARecWcidArray=%d\n",
704 pEntry->Aid, pEntry->RXBAbitmap, pEntry->BARecWcidArray[TID]));
705 }
706 else
707 {
708 Status = FALSE;
709 DBGPRINT(RT_DEBUG_TRACE,("Can't Accept ADDBA for %02x:%02x:%02x:%02x:%02x:%02x TID = %d\n",
710 PRINT_MAC(pEntry->Addr), TID));
711 }
712 return(Status);
713}
714
715
716BA_REC_ENTRY *BATableAllocRecEntry(
717 IN PRTMP_ADAPTER pAd,
718 OUT USHORT *Idx)
719{
720 int i;
721 BA_REC_ENTRY *pBAEntry = NULL;
722
723
724 NdisAcquireSpinLock(&pAd->BATabLock);
725
726 if (pAd->BATable.numAsRecipient >= MAX_BARECI_SESSION)
727 {
728 DBGPRINT(RT_DEBUG_OFF, ("BA Recipeint Session (%ld) > %d\n",
729 pAd->BATable.numAsRecipient, MAX_BARECI_SESSION));
730 goto done;
731 }
732
733
734 for (i=1; i < MAX_LEN_OF_BA_REC_TABLE; i++)
735 {
736 pBAEntry =&pAd->BATable.BARecEntry[i];
737 if ((pBAEntry->REC_BA_Status == Recipient_NONE))
738 {
739
740 pAd->BATable.numAsRecipient++;
741 pBAEntry->REC_BA_Status = Recipient_USED;
742 *Idx = i;
743 break;
744 }
745 }
746
747done:
748 NdisReleaseSpinLock(&pAd->BATabLock);
749 return pBAEntry;
750}
751
752BA_ORI_ENTRY *BATableAllocOriEntry(
753 IN PRTMP_ADAPTER pAd,
754 OUT USHORT *Idx)
755{
756 int i;
757 BA_ORI_ENTRY *pBAEntry = NULL;
758
759 NdisAcquireSpinLock(&pAd->BATabLock);
760
761 if (pAd->BATable.numAsOriginator >= (MAX_LEN_OF_BA_ORI_TABLE))
762 {
763 goto done;
764 }
765
766
767 for (i=1; i<MAX_LEN_OF_BA_ORI_TABLE; i++)
768 {
769 pBAEntry =&pAd->BATable.BAOriEntry[i];
770 if ((pBAEntry->ORI_BA_Status == Originator_NONE))
771 {
772
773 pAd->BATable.numAsOriginator++;
774 pBAEntry->ORI_BA_Status = Originator_USED;
775 pBAEntry->pAdapter = pAd;
776 *Idx = i;
777 break;
778 }
779 }
780
781done:
782 NdisReleaseSpinLock(&pAd->BATabLock);
783 return pBAEntry;
784}
785
786
787VOID BATableFreeOriEntry(
788 IN PRTMP_ADAPTER pAd,
789 IN ULONG Idx)
790{
791 BA_ORI_ENTRY *pBAEntry = NULL;
792 MAC_TABLE_ENTRY *pEntry;
793
794
795 if ((Idx == 0) || (Idx >= MAX_LEN_OF_BA_ORI_TABLE))
796 return;
797
798 pBAEntry =&pAd->BATable.BAOriEntry[Idx];
799
800 if (pBAEntry->ORI_BA_Status != Originator_NONE)
801 {
802 pEntry = &pAd->MacTab.Content[pBAEntry->Wcid];
803 pEntry->BAOriWcidArray[pBAEntry->TID] = 0;
804
805
806 NdisAcquireSpinLock(&pAd->BATabLock);
807 if (pBAEntry->ORI_BA_Status == Originator_Done)
808 {
809 pAd->BATable.numDoneOriginator -= 1;
810 pEntry->TXBAbitmap &= (~(1<<(pBAEntry->TID) ));
811 DBGPRINT(RT_DEBUG_TRACE, ("BATableFreeOriEntry numAsOriginator= %ld\n", pAd->BATable.numAsRecipient));
812
813 }
814
815 ASSERT(pAd->BATable.numAsOriginator != 0);
816
817 pAd->BATable.numAsOriginator -= 1;
818
819 pBAEntry->ORI_BA_Status = Originator_NONE;
820 pBAEntry->Token = 0;
821 NdisReleaseSpinLock(&pAd->BATabLock);
822 }
823}
824
825
826VOID BATableFreeRecEntry(
827 IN PRTMP_ADAPTER pAd,
828 IN ULONG Idx)
829{
830 BA_REC_ENTRY *pBAEntry = NULL;
831 MAC_TABLE_ENTRY *pEntry;
832
833
834 if ((Idx == 0) || (Idx >= MAX_LEN_OF_BA_REC_TABLE))
835 return;
836
837 pBAEntry =&pAd->BATable.BARecEntry[Idx];
838
839 if (pBAEntry->REC_BA_Status != Recipient_NONE)
840 {
841 pEntry = &pAd->MacTab.Content[pBAEntry->Wcid];
842 pEntry->BARecWcidArray[pBAEntry->TID] = 0;
843
844 NdisAcquireSpinLock(&pAd->BATabLock);
845
846 ASSERT(pAd->BATable.numAsRecipient != 0);
847
848 pAd->BATable.numAsRecipient -= 1;
849
850 pBAEntry->REC_BA_Status = Recipient_NONE;
851 NdisReleaseSpinLock(&pAd->BATabLock);
852 }
853}
854
855
856VOID BAOriSessionTearDown(
857 IN OUT PRTMP_ADAPTER pAd,
858 IN UCHAR Wcid,
859 IN UCHAR TID,
860 IN BOOLEAN bPassive,
861 IN BOOLEAN bForceSend)
862{
863 ULONG Idx = 0;
864 BA_ORI_ENTRY *pBAEntry;
865 BOOLEAN Cancelled;
866
867 if (Wcid >= MAX_LEN_OF_MAC_TABLE)
868 {
869 return;
870 }
871
872
873
874
875 Idx = pAd->MacTab.Content[Wcid].BAOriWcidArray[TID];
876 if ((Idx == 0) || (Idx >= MAX_LEN_OF_BA_ORI_TABLE))
877 {
878 if (bForceSend == TRUE)
879 {
880
881 MLME_DELBA_REQ_STRUCT DelbaReq;
882 MLME_QUEUE_ELEM *Elem = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG);
883 if (Elem != NULL)
884 {
885 NdisZeroMemory(&DelbaReq, sizeof(DelbaReq));
886 NdisZeroMemory(Elem, sizeof(MLME_QUEUE_ELEM));
887
888 COPY_MAC_ADDR(DelbaReq.Addr, pAd->MacTab.Content[Wcid].Addr);
889 DelbaReq.Wcid = Wcid;
890 DelbaReq.TID = TID;
891 DelbaReq.Initiator = ORIGINATOR;
892 Elem->MsgLen = sizeof(DelbaReq);
893 NdisMoveMemory(Elem->Msg, &DelbaReq, sizeof(DelbaReq));
894 MlmeDELBAAction(pAd, Elem);
895 kfree(Elem);
896 }
897 else
898 {
899 DBGPRINT(RT_DEBUG_ERROR, ("%s(bForceSend):alloc memory failed!\n", __FUNCTION__));
900 }
901 }
902
903 return;
904 }
905
906 DBGPRINT(RT_DEBUG_TRACE,("%s===>Wcid=%d.TID=%d \n", __FUNCTION__, Wcid, TID));
907
908 pBAEntry = &pAd->BATable.BAOriEntry[Idx];
909 DBGPRINT(RT_DEBUG_TRACE,("\t===>Idx = %ld, Wcid=%d.TID=%d, ORI_BA_Status = %d \n", Idx, Wcid, TID, pBAEntry->ORI_BA_Status));
910
911
912
913 if ((bPassive == FALSE) && (TID == pBAEntry->TID) && (pBAEntry->ORI_BA_Status == Originator_Done))
914 {
915 MLME_DELBA_REQ_STRUCT DelbaReq;
916 MLME_QUEUE_ELEM *Elem = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG);
917 if (Elem != NULL)
918 {
919 NdisZeroMemory(&DelbaReq, sizeof(DelbaReq));
920 NdisZeroMemory(Elem, sizeof(MLME_QUEUE_ELEM));
921
922 COPY_MAC_ADDR(DelbaReq.Addr, pAd->MacTab.Content[Wcid].Addr);
923 DelbaReq.Wcid = Wcid;
924 DelbaReq.TID = pBAEntry->TID;
925 DelbaReq.Initiator = ORIGINATOR;
926 Elem->MsgLen = sizeof(DelbaReq);
927 NdisMoveMemory(Elem->Msg, &DelbaReq, sizeof(DelbaReq));
928 MlmeDELBAAction(pAd, Elem);
929 kfree(Elem);
930 }
931 else
932 {
933 DBGPRINT(RT_DEBUG_ERROR, ("%s():alloc memory failed!\n", __FUNCTION__));
934 return;
935 }
936 }
937 RTMPCancelTimer(&pBAEntry->ORIBATimer, &Cancelled);
938 BATableFreeOriEntry(pAd, Idx);
939
940 if (bPassive)
941 {
942
943 }
944}
945
946VOID BARecSessionTearDown(
947 IN OUT PRTMP_ADAPTER pAd,
948 IN UCHAR Wcid,
949 IN UCHAR TID,
950 IN BOOLEAN bPassive)
951{
952 ULONG Idx = 0;
953 BA_REC_ENTRY *pBAEntry;
954
955 if (Wcid >= MAX_LEN_OF_MAC_TABLE)
956 {
957 return;
958 }
959
960
961
962
963 Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID];
964 if (Idx == 0)
965 return;
966
967 DBGPRINT(RT_DEBUG_TRACE,("%s===>Wcid=%d.TID=%d \n", __FUNCTION__, Wcid, TID));
968
969
970 pBAEntry = &pAd->BATable.BARecEntry[Idx];
971 DBGPRINT(RT_DEBUG_TRACE,("\t===>Idx = %ld, Wcid=%d.TID=%d, REC_BA_Status = %d \n", Idx, Wcid, TID, pBAEntry->REC_BA_Status));
972
973
974
975 if ((TID == pBAEntry->TID) && (pBAEntry->REC_BA_Status == Recipient_Accept))
976 {
977 MLME_DELBA_REQ_STRUCT DelbaReq;
978 BOOLEAN Cancelled;
979
980
981
982 RTMPCancelTimer(&pBAEntry->RECBATimer, &Cancelled);
983
984
985
986
987 if (bPassive == FALSE)
988 {
989 MLME_QUEUE_ELEM *Elem = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG);
990 if (Elem != NULL)
991 {
992 NdisZeroMemory(&DelbaReq, sizeof(DelbaReq));
993 NdisZeroMemory(Elem, sizeof(MLME_QUEUE_ELEM));
994
995 COPY_MAC_ADDR(DelbaReq.Addr, pAd->MacTab.Content[Wcid].Addr);
996 DelbaReq.Wcid = Wcid;
997 DelbaReq.TID = TID;
998 DelbaReq.Initiator = RECIPIENT;
999 Elem->MsgLen = sizeof(DelbaReq);
1000 NdisMoveMemory(Elem->Msg, &DelbaReq, sizeof(DelbaReq));
1001 MlmeDELBAAction(pAd, Elem);
1002 kfree(Elem);
1003 }
1004 else
1005 {
1006 DBGPRINT(RT_DEBUG_ERROR, ("%s():alloc memory failed!\n", __FUNCTION__));
1007 return;
1008 }
1009 }
1010
1011
1012
1013
1014
1015
1016 ba_refresh_reordering_mpdus(pAd, pBAEntry);
1017
1018 NdisAcquireSpinLock(&pAd->BATabLock);
1019
1020
1021 pBAEntry->LastIndSeq = RESET_RCV_SEQ;
1022 pBAEntry->BAWinSize = 0;
1023
1024 pAd->MacTab.Content[Wcid].RXBAbitmap &= (~(1<<(pBAEntry->TID)));
1025 pAd->MacTab.Content[Wcid].BARecWcidArray[TID] = 0;
1026
1027 RTMP_DEL_BA_SESSION_FROM_ASIC(pAd, Wcid, TID);
1028
1029 NdisReleaseSpinLock(&pAd->BATabLock);
1030
1031 }
1032
1033 BATableFreeRecEntry(pAd, Idx);
1034}
1035
1036VOID BASessionTearDownALL(
1037 IN OUT PRTMP_ADAPTER pAd,
1038 IN UCHAR Wcid)
1039{
1040 int i;
1041
1042 for (i=0; i<NUM_OF_TID; i++)
1043 {
1044 BAOriSessionTearDown(pAd, Wcid, i, FALSE, FALSE);
1045 BARecSessionTearDown(pAd, Wcid, i, FALSE);
1046 }
1047}
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064VOID BAOriSessionSetupTimeout(
1065 IN PVOID SystemSpecific1,
1066 IN PVOID FunctionContext,
1067 IN PVOID SystemSpecific2,
1068 IN PVOID SystemSpecific3)
1069{
1070 BA_ORI_ENTRY *pBAEntry = (BA_ORI_ENTRY *)FunctionContext;
1071 MAC_TABLE_ENTRY *pEntry;
1072 PRTMP_ADAPTER pAd;
1073
1074 if (pBAEntry == NULL)
1075 return;
1076
1077 pAd = pBAEntry->pAdapter;
1078
1079#ifdef CONFIG_STA_SUPPORT
1080 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1081 {
1082
1083 if (MONITOR_ON(pAd))
1084 return;
1085 }
1086#endif
1087
1088#ifdef RALINK_ATE
1089
1090 if (ATE_ON(pAd))
1091 return;
1092#endif
1093
1094 pEntry = &pAd->MacTab.Content[pBAEntry->Wcid];
1095
1096 if ((pBAEntry->ORI_BA_Status == Originator_WaitRes) && (pBAEntry->Token < ORI_SESSION_MAX_RETRY))
1097 {
1098 MLME_ADDBA_REQ_STRUCT AddbaReq;
1099
1100 NdisZeroMemory(&AddbaReq, sizeof(AddbaReq));
1101 COPY_MAC_ADDR(AddbaReq.pAddr, pEntry->Addr);
1102 AddbaReq.Wcid = (UCHAR)(pEntry->Aid);
1103 AddbaReq.TID = pBAEntry->TID;
1104 AddbaReq.BaBufSize = pAd->CommonCfg.BACapability.field.RxBAWinLimit;
1105 AddbaReq.TimeOutValue = 0;
1106 AddbaReq.Token = pBAEntry->Token;
1107 MlmeEnqueue(pAd, ACTION_STATE_MACHINE, MT2_MLME_ADD_BA_CATE, sizeof(MLME_ADDBA_REQ_STRUCT), (PVOID)&AddbaReq);
1108 RTMP_MLME_HANDLER(pAd);
1109 DBGPRINT(RT_DEBUG_TRACE,("BA Ori Session Timeout(%d) : Send ADD BA again\n", pBAEntry->Token));
1110
1111 pBAEntry->Token++;
1112 RTMPSetTimer(&pBAEntry->ORIBATimer, ORI_BA_SESSION_TIMEOUT);
1113 }
1114 else
1115 {
1116 BATableFreeOriEntry(pAd, pEntry->BAOriWcidArray[pBAEntry->TID]);
1117 }
1118}
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134VOID BARecSessionIdleTimeout(
1135 IN PVOID SystemSpecific1,
1136 IN PVOID FunctionContext,
1137 IN PVOID SystemSpecific2,
1138 IN PVOID SystemSpecific3)
1139{
1140
1141 BA_REC_ENTRY *pBAEntry = (BA_REC_ENTRY *)FunctionContext;
1142 PRTMP_ADAPTER pAd;
1143 ULONG Now32;
1144
1145 if (pBAEntry == NULL)
1146 return;
1147
1148 if ((pBAEntry->REC_BA_Status == Recipient_Accept))
1149 {
1150 NdisGetSystemUpTime(&Now32);
1151
1152 if (RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer + REC_BA_SESSION_IDLE_TIMEOUT)))
1153 {
1154 pAd = pBAEntry->pAdapter;
1155
1156 ba_refresh_reordering_mpdus(pAd, pBAEntry);
1157 DBGPRINT(RT_DEBUG_OFF, ("%ld: REC BA session Timeout\n", Now32));
1158 }
1159 }
1160}
1161
1162
1163VOID PeerAddBAReqAction(
1164 IN PRTMP_ADAPTER pAd,
1165 IN MLME_QUEUE_ELEM *Elem)
1166
1167{
1168
1169
1170 UCHAR Status = 1;
1171 UCHAR pAddr[6];
1172 FRAME_ADDBA_RSP ADDframe;
1173 PUCHAR pOutBuffer = NULL;
1174 NDIS_STATUS NStatus;
1175 PFRAME_ADDBA_REQ pAddreqFrame = NULL;
1176
1177 ULONG FrameLen;
1178 PULONG ptemp;
1179 PMAC_TABLE_ENTRY pMacEntry;
1180
1181 DBGPRINT(RT_DEBUG_TRACE, ("%s ==> (Wcid = %d)\n", __FUNCTION__, Elem->Wcid));
1182
1183
1184
1185
1186 if (Elem->Wcid >= MAX_LEN_OF_MAC_TABLE)
1187 return;
1188
1189 pMacEntry = &pAd->MacTab.Content[Elem->Wcid];
1190 DBGPRINT(RT_DEBUG_TRACE,("BA - PeerAddBAReqAction----> \n"));
1191 ptemp = (PULONG)Elem->Msg;
1192
1193
1194 if (PeerAddBAReqActionSanity(pAd, Elem->Msg, Elem->MsgLen, pAddr))
1195 {
1196
1197 if ((pAd->CommonCfg.bBADecline == FALSE) && IS_HT_STA(pMacEntry))
1198 {
1199 pAddreqFrame = (PFRAME_ADDBA_REQ)(&Elem->Msg[0]);
1200 DBGPRINT(RT_DEBUG_OFF, ("Rcv Wcid(%d) AddBAReq\n", Elem->Wcid));
1201 if (BARecSessionAdd(pAd, &pAd->MacTab.Content[Elem->Wcid], pAddreqFrame))
1202 Status = 0;
1203 else
1204 Status = 38;
1205 }
1206 else
1207 {
1208 Status = 37;
1209 }
1210 }
1211
1212 if (pAd->MacTab.Content[Elem->Wcid].ValidAsCLI)
1213 ASSERT(pAd->MacTab.Content[Elem->Wcid].Sst == SST_ASSOC);
1214
1215 pAddreqFrame = (PFRAME_ADDBA_REQ)(&Elem->Msg[0]);
1216
1217 NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);
1218 if (NStatus != NDIS_STATUS_SUCCESS)
1219 {
1220 DBGPRINT(RT_DEBUG_TRACE,("ACTION - PeerBAAction() allocate memory failed \n"));
1221 return;
1222 }
1223
1224 NdisZeroMemory(&ADDframe, sizeof(FRAME_ADDBA_RSP));
1225
1226#ifdef CONFIG_STA_SUPPORT
1227 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1228 {
1229 if (ADHOC_ON(pAd))
1230 ActHeaderInit(pAd, &ADDframe.Hdr, pAddr, pAd->CurrentAddress, pAd->CommonCfg.Bssid);
1231 else
1232#ifdef QOS_DLS_SUPPORT
1233 if (pAd->MacTab.Content[Elem->Wcid].ValidAsDls)
1234 ActHeaderInit(pAd, &ADDframe.Hdr, pAddr, pAd->CurrentAddress, pAd->CommonCfg.Bssid);
1235 else
1236#endif
1237 ActHeaderInit(pAd, &ADDframe.Hdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pAddr);
1238 }
1239#endif
1240 ADDframe.Category = CATEGORY_BA;
1241 ADDframe.Action = ADDBA_RESP;
1242 ADDframe.Token = pAddreqFrame->Token;
1243
1244 ADDframe.StatusCode = Status;
1245 ADDframe.BaParm.BAPolicy = IMMED_BA;
1246 ADDframe.BaParm.AMSDUSupported = 0;
1247 ADDframe.BaParm.TID = pAddreqFrame->BaParm.TID;
1248 ADDframe.BaParm.BufSize = min(((UCHAR)pAddreqFrame->BaParm.BufSize), (UCHAR)pAd->CommonCfg.BACapability.field.RxBAWinLimit);
1249 if (ADDframe.BaParm.BufSize == 0)
1250 {
1251 ADDframe.BaParm.BufSize = 64;
1252 }
1253 ADDframe.TimeOutValue = 0;
1254
1255 *(USHORT *)(&ADDframe.BaParm) = cpu2le16(*(USHORT *)(&ADDframe.BaParm));
1256 ADDframe.StatusCode = cpu2le16(ADDframe.StatusCode);
1257 ADDframe.TimeOutValue = cpu2le16(ADDframe.TimeOutValue);
1258
1259 MakeOutgoingFrame(pOutBuffer, &FrameLen,
1260 sizeof(FRAME_ADDBA_RSP), &ADDframe,
1261 END_OF_ARGS);
1262 MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
1263 MlmeFreeMemory(pAd, pOutBuffer);
1264
1265 DBGPRINT(RT_DEBUG_TRACE, ("%s(%d): TID(%d), BufSize(%d) <== \n", __FUNCTION__, Elem->Wcid, ADDframe.BaParm.TID,
1266 ADDframe.BaParm.BufSize));
1267}
1268
1269
1270VOID PeerAddBARspAction(
1271 IN PRTMP_ADAPTER pAd,
1272 IN MLME_QUEUE_ELEM *Elem)
1273
1274{
1275
1276
1277 PFRAME_ADDBA_RSP pFrame = NULL;
1278
1279
1280
1281 if (Elem->Wcid >= MAX_LEN_OF_MAC_TABLE)
1282 return;
1283
1284 DBGPRINT(RT_DEBUG_TRACE, ("%s ==> Wcid(%d)\n", __FUNCTION__, Elem->Wcid));
1285
1286
1287
1288 if (PeerAddBARspActionSanity(pAd, Elem->Msg, Elem->MsgLen))
1289 {
1290 pFrame = (PFRAME_ADDBA_RSP)(&Elem->Msg[0]);
1291
1292 DBGPRINT(RT_DEBUG_TRACE, ("\t\t StatusCode = %d\n", pFrame->StatusCode));
1293 switch (pFrame->StatusCode)
1294 {
1295 case 0:
1296
1297 BAOriSessionAdd(pAd, &pAd->MacTab.Content[Elem->Wcid], pFrame);
1298 break;
1299 default:
1300
1301 BAOriSessionTearDown(pAd, Elem->Wcid, pFrame->BaParm.TID, TRUE, FALSE);
1302 break;
1303 }
1304
1305 if ((pFrame->StatusCode == 37)
1306#ifdef CONFIG_STA_SUPPORT
1307 || ((pAd->OpMode == OPMODE_STA) && STA_TGN_WIFI_ON(pAd) && (pFrame->StatusCode != 0))
1308#endif
1309 )
1310 {
1311 pAd->MacTab.Content[Elem->Wcid].BADeclineBitmap |= 1<<pFrame->BaParm.TID;
1312 }
1313 }
1314}
1315
1316VOID PeerDelBAAction(
1317 IN PRTMP_ADAPTER pAd,
1318 IN MLME_QUEUE_ELEM *Elem)
1319
1320{
1321
1322
1323 PFRAME_DELBA_REQ pDelFrame = NULL;
1324
1325 DBGPRINT(RT_DEBUG_TRACE,("%s ==>\n", __FUNCTION__));
1326
1327 if (PeerDelBAActionSanity(pAd, Elem->Wcid, Elem->Msg, Elem->MsgLen))
1328 {
1329 pDelFrame = (PFRAME_DELBA_REQ)(&Elem->Msg[0]);
1330 if (pDelFrame->DelbaParm.Initiator == ORIGINATOR)
1331 {
1332 DBGPRINT(RT_DEBUG_TRACE,("BA - PeerDelBAAction----> ORIGINATOR\n"));
1333 BARecSessionTearDown(pAd, Elem->Wcid, pDelFrame->DelbaParm.TID, TRUE);
1334 }
1335 else
1336 {
1337 DBGPRINT(RT_DEBUG_TRACE,("BA - PeerDelBAAction----> RECIPIENT, Reason = %d\n", pDelFrame->ReasonCode));
1338
1339 BAOriSessionTearDown(pAd, Elem->Wcid, pDelFrame->DelbaParm.TID, TRUE, FALSE);
1340 }
1341 }
1342}
1343
1344
1345BOOLEAN CntlEnqueueForRecv(
1346 IN PRTMP_ADAPTER pAd,
1347 IN ULONG Wcid,
1348 IN ULONG MsgLen,
1349 IN PFRAME_BA_REQ pMsg)
1350{
1351 PFRAME_BA_REQ pFrame = pMsg;
1352
1353
1354 PBA_REC_ENTRY pBAEntry;
1355
1356 ULONG Idx;
1357
1358 UCHAR TID;
1359
1360 TID = (UCHAR)pFrame->BARControl.TID;
1361
1362 DBGPRINT(RT_DEBUG_TRACE, ("%s(): BAR-Wcid(%ld), Tid (%d)\n", __FUNCTION__, Wcid, TID));
1363
1364
1365
1366 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
1367 return FALSE;
1368
1369
1370 if (MsgLen > MGMT_DMA_BUFFER_SIZE)
1371 {
1372 DBGPRINT_ERR(("CntlEnqueueForRecv: frame too large, size = %ld \n", MsgLen));
1373 return FALSE;
1374 }
1375 else if (MsgLen != sizeof(FRAME_BA_REQ))
1376 {
1377 DBGPRINT_ERR(("CntlEnqueueForRecv: BlockAck Request frame length size = %ld incorrect\n", MsgLen));
1378 return FALSE;
1379 }
1380 else if (MsgLen != sizeof(FRAME_BA_REQ))
1381 {
1382 DBGPRINT_ERR(("CntlEnqueueForRecv: BlockAck Request frame length size = %ld incorrect\n", MsgLen));
1383 return FALSE;
1384 }
1385
1386 if ((Wcid < MAX_LEN_OF_MAC_TABLE) && (TID < 8))
1387 {
1388
1389 Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID];
1390 pBAEntry = &pAd->BATable.BARecEntry[Idx];
1391 }
1392 else
1393 {
1394 return FALSE;
1395 }
1396
1397 DBGPRINT(RT_DEBUG_TRACE, ("BAR(%ld) : Tid (%d) - %04x:%04x\n", Wcid, TID, pFrame->BAStartingSeq.field.StartSeq, pBAEntry->LastIndSeq ));
1398
1399 if (SEQ_SMALLER(pBAEntry->LastIndSeq, pFrame->BAStartingSeq.field.StartSeq, MAXSEQ))
1400 {
1401
1402 ba_indicate_reordering_mpdus_le_seq(pAd, pBAEntry, pFrame->BAStartingSeq.field.StartSeq);
1403 pBAEntry->LastIndSeq = (pFrame->BAStartingSeq.field.StartSeq == 0) ? MAXSEQ :(pFrame->BAStartingSeq.field.StartSeq -1);
1404 }
1405
1406 return TRUE;
1407}
1408
1409
1410
1411
1412VOID SendPSMPAction(
1413 IN PRTMP_ADAPTER pAd,
1414 IN UCHAR Wcid,
1415 IN UCHAR Psmp)
1416{
1417 PUCHAR pOutBuffer = NULL;
1418 NDIS_STATUS NStatus;
1419
1420 FRAME_PSMP_ACTION Frame;
1421 ULONG FrameLen;
1422
1423 NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);
1424 if (NStatus != NDIS_STATUS_SUCCESS)
1425 {
1426 DBGPRINT(RT_DEBUG_ERROR,("BA - MlmeADDBAAction() allocate memory failed \n"));
1427 return;
1428 }
1429#ifdef CONFIG_STA_SUPPORT
1430 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1431 ActHeaderInit(pAd, &Frame.Hdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pAd->MacTab.Content[Wcid].Addr);
1432#endif
1433
1434 Frame.Category = CATEGORY_HT;
1435 Frame.Action = SMPS_ACTION;
1436 switch (Psmp)
1437 {
1438 case MMPS_ENABLE:
1439#ifdef RT30xx
1440 if (IS_RT30xx(pAd)
1441 &&(pAd->Antenna.field.RxPath>1||pAd->Antenna.field.TxPath>1))
1442 {
1443 RTMP_ASIC_MMPS_DISABLE(pAd);
1444 }
1445#endif
1446 Frame.Psmp = 0;
1447 break;
1448 case MMPS_DYNAMIC:
1449 Frame.Psmp = 3;
1450 break;
1451 case MMPS_STATIC:
1452#ifdef RT30xx
1453 if (IS_RT30xx(pAd)
1454 &&(pAd->Antenna.field.RxPath>1||pAd->Antenna.field.TxPath>1))
1455 {
1456 RTMP_ASIC_MMPS_ENABLE(pAd);
1457 }
1458#endif
1459 Frame.Psmp = 1;
1460 break;
1461 }
1462 MakeOutgoingFrame(pOutBuffer, &FrameLen,
1463 sizeof(FRAME_PSMP_ACTION), &Frame,
1464 END_OF_ARGS);
1465 MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
1466 MlmeFreeMemory(pAd, pOutBuffer);
1467 DBGPRINT(RT_DEBUG_ERROR,("HT - SendPSMPAction( %d ) \n", Frame.Psmp));
1468}
1469
1470
1471#define RADIO_MEASUREMENT_REQUEST_ACTION 0
1472
1473typedef struct PACKED
1474{
1475 UCHAR RegulatoryClass;
1476 UCHAR ChannelNumber;
1477 USHORT RandomInterval;
1478 USHORT MeasurementDuration;
1479 UCHAR MeasurementMode;
1480 UCHAR BSSID[MAC_ADDR_LEN];
1481 UCHAR ReportingCondition;
1482 UCHAR Threshold;
1483 UCHAR SSIDIE[2];
1484} BEACON_REQUEST;
1485
1486typedef struct PACKED
1487{
1488 UCHAR ID;
1489 UCHAR Length;
1490 UCHAR Token;
1491 UCHAR RequestMode;
1492 UCHAR Type;
1493} MEASUREMENT_REQ;
1494
1495
1496
1497
1498void convert_reordering_packet_to_preAMSDU_or_802_3_packet(
1499 IN PRTMP_ADAPTER pAd,
1500 IN RX_BLK *pRxBlk,
1501 IN UCHAR FromWhichBSSID)
1502{
1503 PNDIS_PACKET pRxPkt;
1504 UCHAR Header802_3[LENGTH_802_3];
1505
1506
1507
1508
1509
1510
1511#ifdef CONFIG_STA_SUPPORT
1512 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1513 RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3);
1514#endif
1515
1516 ASSERT(pRxBlk->pRxPacket);
1517 pRxPkt = RTPKT_TO_OSPKT(pRxBlk->pRxPacket);
1518
1519 SET_OS_PKT_NETDEV(pRxPkt, get_netdev_from_bssid(pAd, FromWhichBSSID));
1520 SET_OS_PKT_DATAPTR(pRxPkt, pRxBlk->pData);
1521 SET_OS_PKT_LEN(pRxPkt, pRxBlk->DataSize);
1522 SET_OS_PKT_DATATAIL(pRxPkt, pRxBlk->pData, pRxBlk->DataSize);
1523
1524
1525
1526
1527 if (!RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU))
1528 {
1529
1530#ifdef CONFIG_STA_SUPPORT
1531 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1532 {
1533#ifdef LINUX
1534 NdisMoveMemory(skb_push(pRxPkt, LENGTH_802_3), Header802_3, LENGTH_802_3);
1535#endif
1536 }
1537#endif
1538 }
1539}
1540
1541
1542#define INDICATE_LEGACY_OR_AMSDU(_pAd, _pRxBlk, _fromWhichBSSID) \
1543 do \
1544 { \
1545 if (RX_BLK_TEST_FLAG(_pRxBlk, fRX_AMSDU)) \
1546 { \
1547 Indicate_AMSDU_Packet(_pAd, _pRxBlk, _fromWhichBSSID); \
1548 } \
1549 else if (RX_BLK_TEST_FLAG(_pRxBlk, fRX_EAP)) \
1550 { \
1551 Indicate_EAPOL_Packet(_pAd, _pRxBlk, _fromWhichBSSID); \
1552 } \
1553 else \
1554 { \
1555 Indicate_Legacy_Packet(_pAd, _pRxBlk, _fromWhichBSSID); \
1556 } \
1557 } while (0);
1558
1559
1560
1561static VOID ba_enqueue_reordering_packet(
1562 IN PRTMP_ADAPTER pAd,
1563 IN PBA_REC_ENTRY pBAEntry,
1564 IN RX_BLK *pRxBlk,
1565 IN UCHAR FromWhichBSSID)
1566{
1567 struct reordering_mpdu *mpdu_blk;
1568 UINT16 Sequence = (UINT16) pRxBlk->pHeader->Sequence;
1569
1570 mpdu_blk = ba_mpdu_blk_alloc(pAd);
1571 if ((mpdu_blk != NULL) &&
1572 (!RX_BLK_TEST_FLAG(pRxBlk, fRX_EAP)))
1573 {
1574
1575 NdisAcquireSpinLock(&pBAEntry->RxReRingLock);
1576
1577 mpdu_blk->Sequence = Sequence;
1578
1579 mpdu_blk->bAMSDU = RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU);
1580
1581 convert_reordering_packet_to_preAMSDU_or_802_3_packet(pAd, pRxBlk, FromWhichBSSID);
1582
1583 STATS_INC_RX_PACKETS(pAd, FromWhichBSSID);
1584
1585
1586
1587
1588
1589 RTMP_SET_PACKET_IF(pRxBlk->pRxPacket, FromWhichBSSID);
1590
1591 mpdu_blk->pPacket = pRxBlk->pRxPacket;
1592
1593 if (ba_reordering_mpdu_insertsorted(&pBAEntry->list, mpdu_blk) == FALSE)
1594 {
1595
1596
1597 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_SUCCESS);
1598 ba_mpdu_blk_free(pAd, mpdu_blk);
1599 }
1600
1601 ASSERT((0<= pBAEntry->list.qlen) && (pBAEntry->list.qlen <= pBAEntry->BAWinSize));
1602 NdisReleaseSpinLock(&pBAEntry->RxReRingLock);
1603 }
1604 else
1605 {
1606 DBGPRINT(RT_DEBUG_ERROR, ("!!! (%d) Can't allocate reordering mpdu blk\n",
1607 pBAEntry->list.qlen));
1608
1609
1610
1611
1612
1613
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
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
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
1656 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
1657 return;
1658 }
1659
1660
1661
1662 if (Wcid < MAX_LEN_OF_MAC_TABLE)
1663 {
1664 Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID];
1665 if (Idx == 0)
1666 {
1667
1668 INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID);
1669 return;
1670 }
1671 pBAEntry = &pAd->BATable.BARecEntry[Idx];
1672 }
1673 else
1674 {
1675
1676 ASSERT(0);
1677
1678 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
1679 return;
1680 }
1681
1682 ASSERT(pBAEntry);
1683
1684
1685 NdisGetSystemUpTime(&Now32);
1686
1687 pBAEntry->rcvSeq = Sequence;
1688
1689
1690 ba_flush_reordering_timeout_mpdus(pAd, pBAEntry, Now32);
1691 pBAEntry->LastIndSeqAtTimer = Now32;
1692
1693
1694
1695
1696 if (pBAEntry->LastIndSeq == RESET_RCV_SEQ)
1697 {
1698 ASSERT((pBAEntry->list.qlen == 0) && (pBAEntry->list.next == NULL));
1699
1700
1701 pBAEntry->LastIndSeq = Sequence;
1702 pBAEntry->LastIndSeqAtTimer = Now32;
1703 INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID);
1704 return;
1705 }
1706
1707
1708
1709
1710 if (SEQ_STEPONE(Sequence, pBAEntry->LastIndSeq, MAXSEQ))
1711 {
1712 USHORT LastIndSeq;
1713
1714 pBAEntry->LastIndSeq = Sequence;
1715 INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID);
1716 LastIndSeq = ba_indicate_reordering_mpdus_in_order(pAd, pBAEntry, pBAEntry->LastIndSeq);
1717 if (LastIndSeq != RESET_RCV_SEQ)
1718 {
1719 pBAEntry->LastIndSeq = LastIndSeq;
1720 }
1721 pBAEntry->LastIndSeqAtTimer = Now32;
1722 }
1723
1724
1725
1726 else if (Sequence == pBAEntry->LastIndSeq)
1727 {
1728
1729
1730 pBAEntry->nDropPacket++;
1731 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
1732 }
1733
1734
1735
1736 else if (SEQ_SMALLER(Sequence, pBAEntry->LastIndSeq, MAXSEQ))
1737 {
1738
1739
1740 pBAEntry->nDropPacket++;
1741 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
1742 }
1743
1744
1745
1746 else if (SEQ_SMALLER(Sequence, (((pBAEntry->LastIndSeq+pBAEntry->BAWinSize+1)) & MAXSEQ), MAXSEQ))
1747 {
1748 ba_enqueue_reordering_packet(pAd, pBAEntry, pRxBlk, FromWhichBSSID);
1749 }
1750
1751
1752
1753 else
1754 {
1755 LONG WinStartSeq, TmpSeq;
1756
1757
1758 TmpSeq = Sequence - (pBAEntry->BAWinSize) -1;
1759 if (TmpSeq < 0)
1760 {
1761 TmpSeq = (MAXSEQ+1) + TmpSeq;
1762 }
1763 WinStartSeq = (TmpSeq+1) & MAXSEQ;
1764 ba_indicate_reordering_mpdus_le_seq(pAd, pBAEntry, WinStartSeq);
1765 pBAEntry->LastIndSeq = WinStartSeq;
1766
1767 pBAEntry->LastIndSeqAtTimer = Now32;
1768
1769 ba_enqueue_reordering_packet(pAd, pBAEntry, pRxBlk, FromWhichBSSID);
1770
1771 TmpSeq = ba_indicate_reordering_mpdus_in_order(pAd, pBAEntry, pBAEntry->LastIndSeq);
1772 if (TmpSeq != RESET_RCV_SEQ)
1773 {
1774 pBAEntry->LastIndSeq = TmpSeq;
1775 }
1776 }
1777}
1778
1779#endif
1780