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