2 *************************************************************************
4 * 5F., No.36, Taiyuan St., Jhubei City,
8 * (c) Copyright 2002-2007, Ralink Technology, Inc.
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. *
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. *
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. *
25 *************************************************************************
29 #include "../rt_config.h"
33 #define BA_ORI_INIT_SEQ (pEntry->TxSeq[TID]) //1 // inital sequence number of BA session
35 #define ORI_SESSION_MAX_RETRY 8
36 #define ORI_BA_SESSION_TIMEOUT (2000) // ms
37 #define REC_BA_SESSION_IDLE_TIMEOUT (1000) // ms
39 #define REORDERING_PACKET_TIMEOUT ((100 * HZ)/1000) // system ticks -- 100 ms
40 #define MAX_REORDERING_PACKET_TIMEOUT ((3000 * HZ)/1000) // system ticks -- 100 ms
42 #define RESET_RCV_SEQ (0xFFFF)
44 static void ba_mpdu_blk_free(PRTMP_ADAPTER pAd
, struct reordering_mpdu
*mpdu_blk
);
47 BA_ORI_ENTRY
*BATableAllocOriEntry(
51 BA_REC_ENTRY
*BATableAllocRecEntry(
55 VOID
BAOriSessionSetupTimeout(
56 IN PVOID SystemSpecific1
,
57 IN PVOID FunctionContext
,
58 IN PVOID SystemSpecific2
,
59 IN PVOID SystemSpecific3
);
61 VOID
BARecSessionIdleTimeout(
62 IN PVOID SystemSpecific1
,
63 IN PVOID FunctionContext
,
64 IN PVOID SystemSpecific2
,
65 IN PVOID SystemSpecific3
);
68 BUILD_TIMER_FUNCTION(BAOriSessionSetupTimeout
);
69 BUILD_TIMER_FUNCTION(BARecSessionIdleTimeout
);
71 #define ANNOUNCE_REORDERING_PACKET(_pAd, _mpdu_blk) \
72 Announce_Reordering_Packet(_pAd, _mpdu_blk);
74 VOID
BA_MaxWinSizeReasign(
76 IN MAC_TABLE_ENTRY
*pEntryPeer
,
82 if (pAd
->MACVersion
>= RALINK_2883_VERSION
) // 3*3
84 if (pAd
->MACVersion
>= RALINK_3070_VERSION
)
86 if (pEntryPeer
->WepStatus
!= Ndis802_11EncryptionDisabled
)
87 MaxSize
= 7; // for non-open mode
94 else if (pAd
->MACVersion
>= RALINK_2880E_VERSION
) // 2880 e
96 if (pEntryPeer
->WepStatus
!= Ndis802_11EncryptionDisabled
)
97 MaxSize
= 7; // for non-open mode
104 DBGPRINT(RT_DEBUG_TRACE
, ("ba> Win Size = %d, Max Size = %d\n",
105 *pWinSize
, MaxSize
));
107 if ((*pWinSize
) > MaxSize
)
109 DBGPRINT(RT_DEBUG_TRACE
, ("ba> reassign max win size from %d to %d\n",
110 *pWinSize
, MaxSize
));
116 void Announce_Reordering_Packet(IN PRTMP_ADAPTER pAd
,
117 IN
struct reordering_mpdu
*mpdu
)
119 PNDIS_PACKET pPacket
;
121 pPacket
= mpdu
->pPacket
;
126 BA_Reorder_AMSDU_Annnounce(pAd
, pPacket
);
131 // pass this 802.3 packet to upper layer or forward this packet to WM directly
134 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd
, pPacket
, RTMP_GET_PACKET_IF(pPacket
));
139 * Insert a reordering mpdu into sorted linked list by sequence no.
141 BOOLEAN
ba_reordering_mpdu_insertsorted(struct reordering_list
*list
, struct reordering_mpdu
*mpdu
)
144 struct reordering_mpdu
**ppScan
= &list
->next
;
146 while (*ppScan
!= NULL
)
148 if (SEQ_SMALLER((*ppScan
)->Sequence
, mpdu
->Sequence
, MAXSEQ
))
150 ppScan
= &(*ppScan
)->next
;
152 else if ((*ppScan
)->Sequence
== mpdu
->Sequence
)
154 /* give up this duplicated frame */
164 mpdu
->next
= *ppScan
;
172 * caller lock critical section if necessary
174 static inline void ba_enqueue(struct reordering_list
*list
, struct reordering_mpdu
*mpdu_blk
)
177 mpdu_blk
->next
= list
->next
;
178 list
->next
= mpdu_blk
;
182 * caller lock critical section if necessary
184 static inline struct reordering_mpdu
* ba_dequeue(struct reordering_list
*list
)
186 struct reordering_mpdu
*mpdu_blk
= NULL
;
193 mpdu_blk
= list
->next
;
196 list
->next
= mpdu_blk
->next
;
197 mpdu_blk
->next
= NULL
;
204 static inline struct reordering_mpdu
*ba_reordering_mpdu_dequeue(struct reordering_list
*list
)
206 return(ba_dequeue(list
));
210 static inline struct reordering_mpdu
*ba_reordering_mpdu_probe(struct reordering_list
*list
)
219 * free all resource for reordering mechanism
221 void ba_reordering_resource_release(PRTMP_ADAPTER pAd
)
224 PBA_REC_ENTRY pBAEntry
;
225 struct reordering_mpdu
*mpdu_blk
;
230 /* I. release all pending reordering packet */
231 NdisAcquireSpinLock(&pAd
->BATabLock
);
232 for (i
= 0; i
< MAX_LEN_OF_BA_REC_TABLE
; i
++)
234 pBAEntry
= &Tab
->BARecEntry
[i
];
235 if (pBAEntry
->REC_BA_Status
!= Recipient_NONE
)
237 while ((mpdu_blk
= ba_reordering_mpdu_dequeue(&pBAEntry
->list
)))
239 ASSERT(mpdu_blk
->pPacket
);
240 RELEASE_NDIS_PACKET(pAd
, mpdu_blk
->pPacket
, NDIS_STATUS_FAILURE
);
241 ba_mpdu_blk_free(pAd
, mpdu_blk
);
245 NdisReleaseSpinLock(&pAd
->BATabLock
);
247 ASSERT(pBAEntry
->list
.qlen
== 0);
248 /* II. free memory of reordering mpdu table */
249 NdisAcquireSpinLock(&pAd
->mpdu_blk_pool
.lock
);
250 os_free_mem(pAd
, pAd
->mpdu_blk_pool
.mem
);
251 NdisReleaseSpinLock(&pAd
->mpdu_blk_pool
.lock
);
257 * Allocate all resource for reordering mechanism
259 BOOLEAN
ba_reordering_resource_init(PRTMP_ADAPTER pAd
, int num
)
263 struct reordering_mpdu
*mpdu_blk
;
264 struct reordering_list
*freelist
;
266 /* allocate spinlock */
267 NdisAllocateSpinLock(&pAd
->mpdu_blk_pool
.lock
);
269 /* initialize freelist */
270 freelist
= &pAd
->mpdu_blk_pool
.freelist
;
271 freelist
->next
= NULL
;
274 DBGPRINT(RT_DEBUG_TRACE
, ("Allocate %d memory for BA reordering\n", (UINT32
)(num
*sizeof(struct reordering_mpdu
))));
276 /* allocate number of mpdu_blk memory */
277 os_alloc_mem(pAd
, (PUCHAR
*)&mem
, (num
*sizeof(struct reordering_mpdu
)));
279 pAd
->mpdu_blk_pool
.mem
= mem
;
283 DBGPRINT(RT_DEBUG_ERROR
, ("Can't Allocate Memory for BA Reordering\n"));
287 /* build mpdu_blk free list */
288 for (i
=0; i
<num
; i
++)
291 mpdu_blk
= (struct reordering_mpdu
*) mem
;
292 /* initial mpdu_blk */
293 NdisZeroMemory(mpdu_blk
, sizeof(struct reordering_mpdu
));
295 mem
+= sizeof(struct reordering_mpdu
);
296 /* insert mpdu_blk into freelist */
297 ba_enqueue(freelist
, mpdu_blk
);
303 //static int blk_count=0; // sample take off, no use
305 static struct reordering_mpdu
*ba_mpdu_blk_alloc(PRTMP_ADAPTER pAd
)
307 struct reordering_mpdu
*mpdu_blk
;
309 NdisAcquireSpinLock(&pAd
->mpdu_blk_pool
.lock
);
310 mpdu_blk
= ba_dequeue(&pAd
->mpdu_blk_pool
.freelist
);
315 NdisZeroMemory(mpdu_blk
, sizeof(struct reordering_mpdu
));
317 NdisReleaseSpinLock(&pAd
->mpdu_blk_pool
.lock
);
321 static void ba_mpdu_blk_free(PRTMP_ADAPTER pAd
, struct reordering_mpdu
*mpdu_blk
)
325 NdisAcquireSpinLock(&pAd
->mpdu_blk_pool
.lock
);
327 ba_enqueue(&pAd
->mpdu_blk_pool
.freelist
, mpdu_blk
);
328 NdisReleaseSpinLock(&pAd
->mpdu_blk_pool
.lock
);
332 static USHORT
ba_indicate_reordering_mpdus_in_order(
333 IN PRTMP_ADAPTER pAd
,
334 IN PBA_REC_ENTRY pBAEntry
,
337 struct reordering_mpdu
*mpdu_blk
;
338 USHORT LastIndSeq
= RESET_RCV_SEQ
;
340 NdisAcquireSpinLock(&pBAEntry
->RxReRingLock
);
342 while ((mpdu_blk
= ba_reordering_mpdu_probe(&pBAEntry
->list
)))
344 /* find in-order frame */
345 if (!SEQ_STEPONE(mpdu_blk
->Sequence
, StartSeq
, MAXSEQ
))
349 /* dequeue in-order frame from reodering list */
350 mpdu_blk
= ba_reordering_mpdu_dequeue(&pBAEntry
->list
);
351 /* pass this frame up */
352 ANNOUNCE_REORDERING_PACKET(pAd
, mpdu_blk
);
353 /* move to next sequence */
354 StartSeq
= mpdu_blk
->Sequence
;
355 LastIndSeq
= StartSeq
;
357 ba_mpdu_blk_free(pAd
, mpdu_blk
);
360 NdisReleaseSpinLock(&pBAEntry
->RxReRingLock
);
362 /* update last indicated sequence */
366 static void ba_indicate_reordering_mpdus_le_seq(
367 IN PRTMP_ADAPTER pAd
,
368 IN PBA_REC_ENTRY pBAEntry
,
371 struct reordering_mpdu
*mpdu_blk
;
373 NdisAcquireSpinLock(&pBAEntry
->RxReRingLock
);
374 while ((mpdu_blk
= ba_reordering_mpdu_probe(&pBAEntry
->list
)))
376 /* find in-order frame */
377 if ((mpdu_blk
->Sequence
== Sequence
) || SEQ_SMALLER(mpdu_blk
->Sequence
, Sequence
, MAXSEQ
))
379 /* dequeue in-order frame from reodering list */
380 mpdu_blk
= ba_reordering_mpdu_dequeue(&pBAEntry
->list
);
381 /* pass this frame up */
382 ANNOUNCE_REORDERING_PACKET(pAd
, mpdu_blk
);
384 ba_mpdu_blk_free(pAd
, mpdu_blk
);
391 NdisReleaseSpinLock(&pBAEntry
->RxReRingLock
);
395 static void ba_refresh_reordering_mpdus(
396 IN PRTMP_ADAPTER pAd
,
397 PBA_REC_ENTRY pBAEntry
)
399 struct reordering_mpdu
*mpdu_blk
;
401 NdisAcquireSpinLock(&pBAEntry
->RxReRingLock
);
403 /* dequeue in-order frame from reodering list */
404 while ((mpdu_blk
= ba_reordering_mpdu_dequeue(&pBAEntry
->list
)))
406 /* pass this frame up */
407 ANNOUNCE_REORDERING_PACKET(pAd
, mpdu_blk
);
409 pBAEntry
->LastIndSeq
= mpdu_blk
->Sequence
;
410 ba_mpdu_blk_free(pAd
, mpdu_blk
);
412 /* update last indicated sequence */
414 ASSERT(pBAEntry
->list
.qlen
== 0);
415 pBAEntry
->LastIndSeq
= RESET_RCV_SEQ
;
416 NdisReleaseSpinLock(&pBAEntry
->RxReRingLock
);
421 void ba_flush_reordering_timeout_mpdus(
422 IN PRTMP_ADAPTER pAd
,
423 IN PBA_REC_ENTRY pBAEntry
,
429 // if ((RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+REORDERING_PACKET_TIMEOUT)) &&
430 // (pBAEntry->list.qlen > ((pBAEntry->BAWinSize*7)/8))) //||
431 // (RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+(10*REORDERING_PACKET_TIMEOUT))) &&
432 // (pBAEntry->list.qlen > (pBAEntry->BAWinSize/8)))
433 if (RTMP_TIME_AFTER((unsigned long)Now32
, (unsigned long)(pBAEntry
->LastIndSeqAtTimer
+(MAX_REORDERING_PACKET_TIMEOUT
/6)))
434 &&(pBAEntry
->list
.qlen
> 1)
437 DBGPRINT(RT_DEBUG_TRACE
,("timeout[%d] (%08lx-%08lx = %d > %d): %x, flush all!\n ", pBAEntry
->list
.qlen
, Now32
, (pBAEntry
->LastIndSeqAtTimer
),
438 (int)((long) Now32
- (long)(pBAEntry
->LastIndSeqAtTimer
)), MAX_REORDERING_PACKET_TIMEOUT
,
439 pBAEntry
->LastIndSeq
));
440 ba_refresh_reordering_mpdus(pAd
, pBAEntry
);
441 pBAEntry
->LastIndSeqAtTimer
= Now32
;
444 if (RTMP_TIME_AFTER((unsigned long)Now32
, (unsigned long)(pBAEntry
->LastIndSeqAtTimer
+(REORDERING_PACKET_TIMEOUT
)))
445 && (pBAEntry
->list
.qlen
> 0)
449 // force LastIndSeq to shift to LastIndSeq+1
451 Sequence
= (pBAEntry
->LastIndSeq
+1) & MAXSEQ
;
452 ba_indicate_reordering_mpdus_le_seq(pAd
, pBAEntry
, Sequence
);
453 pBAEntry
->LastIndSeqAtTimer
= Now32
;
454 pBAEntry
->LastIndSeq
= Sequence
;
456 // indicate in-order mpdus
458 Sequence
= ba_indicate_reordering_mpdus_in_order(pAd
, pBAEntry
, Sequence
);
459 if (Sequence
!= RESET_RCV_SEQ
)
461 pBAEntry
->LastIndSeq
= Sequence
;
467 (RTMP_TIME_AFTER((unsigned long)Now32
, (unsigned long)(pBAEntry
->LastIndSeqAtTimer
+(MAX_REORDERING_PACKET_TIMEOUT
))) &&
468 (pBAEntry
->list
.qlen
> 1))
471 DBGPRINT(RT_DEBUG_TRACE
,("timeout[%d] (%lx-%lx = %d > %d): %x\n ", pBAEntry
->list
.qlen
, Now32
, (pBAEntry
->LastIndSeqAtTimer
),
472 (int)((long) Now32
- (long)(pBAEntry
->LastIndSeqAtTimer
)), MAX_REORDERING_PACKET_TIMEOUT
,
473 pBAEntry
->LastIndSeq
));
474 ba_refresh_reordering_mpdus(pAd
, pBAEntry
);
475 pBAEntry
->LastIndSeqAtTimer
= Now32
;
482 * generate ADDBA request to
483 * set up BA agreement
485 VOID
BAOriSessionSetUp(
486 IN PRTMP_ADAPTER pAd
,
487 IN MAC_TABLE_ENTRY
*pEntry
,
494 //MLME_ADDBA_REQ_STRUCT AddbaReq;
495 BA_ORI_ENTRY
*pBAEntry
= NULL
;
499 if ((pAd
->CommonCfg
.BACapability
.field
.AutoBA
!= TRUE
) && (isForced
== FALSE
))
502 // if this entry is limited to use legacy tx mode, it doesn't generate BA.
503 if (RTMPStaFixedTxMode(pAd
, pEntry
) != FIXED_TXMODE_HT
)
506 if ((pEntry
->BADeclineBitmap
& (1<<TID
)) && (isForced
== FALSE
))
508 // try again after 3 secs
510 // printk("DeCline BA from Peer\n");
515 Idx
= pEntry
->BAOriWcidArray
[TID
];
518 // allocate a BA session
519 pBAEntry
= BATableAllocOriEntry(pAd
, &Idx
);
520 if (pBAEntry
== NULL
)
522 DBGPRINT(RT_DEBUG_TRACE
,("ADDBA - MlmeADDBAAction() allocate BA session failed \n"));
528 pBAEntry
=&pAd
->BATable
.BAOriEntry
[Idx
];
531 if (pBAEntry
->ORI_BA_Status
>= Originator_WaitRes
)
536 pEntry
->BAOriWcidArray
[TID
] = Idx
;
538 // Initialize BA session
539 pBAEntry
->ORI_BA_Status
= Originator_WaitRes
;
540 pBAEntry
->Wcid
= pEntry
->Aid
;
541 pBAEntry
->BAWinSize
= pAd
->CommonCfg
.BACapability
.field
.RxBAWinLimit
;
542 pBAEntry
->Sequence
= BA_ORI_INIT_SEQ
;
543 pBAEntry
->Token
= 1; // (2008-01-21) Jan Lee recommends it - this token can't be 0
545 pBAEntry
->TimeOutValue
= TimeOut
;
546 pBAEntry
->pAdapter
= pAd
;
548 if (!(pEntry
->TXBAbitmap
& (1<<TID
)))
550 RTMPInitTimer(pAd
, &pBAEntry
->ORIBATimer
, GET_TIMER_FUNCTION(BAOriSessionSetupTimeout
), pBAEntry
, FALSE
);
553 RTMPCancelTimer(&pBAEntry
->ORIBATimer
, &Cancelled
);
555 // set timer to send ADDBA request
556 RTMPSetTimer(&pBAEntry
->ORIBATimer
, DelayTime
);
559 VOID
BAOriSessionAdd(
560 IN PRTMP_ADAPTER pAd
,
561 IN MAC_TABLE_ENTRY
*pEntry
,
562 IN PFRAME_ADDBA_RSP pFrame
)
564 BA_ORI_ENTRY
*pBAEntry
= NULL
;
568 PUCHAR pOutBuffer2
= NULL
;
573 TID
= pFrame
->BaParm
.TID
;
574 Idx
= pEntry
->BAOriWcidArray
[TID
];
575 pBAEntry
=&pAd
->BATable
.BAOriEntry
[Idx
];
577 // Start fill in parameters.
578 if ((Idx
!=0) && (pBAEntry
->TID
== TID
) && (pBAEntry
->ORI_BA_Status
== Originator_WaitRes
))
580 pBAEntry
->BAWinSize
= min(pBAEntry
->BAWinSize
, ((UCHAR
)pFrame
->BaParm
.BufSize
));
581 BA_MaxWinSizeReasign(pAd
, pEntry
, &pBAEntry
->BAWinSize
);
583 pBAEntry
->TimeOutValue
= pFrame
->TimeOutValue
;
584 pBAEntry
->ORI_BA_Status
= Originator_Done
;
585 // reset sequence number
586 pBAEntry
->Sequence
= BA_ORI_INIT_SEQ
;
588 pEntry
->TXBAbitmap
|= (1<<TID
);
589 RTMPCancelTimer(&pBAEntry
->ORIBATimer
, &Cancelled
);
591 pBAEntry
->ORIBATimer
.TimerValue
= 0; //pFrame->TimeOutValue;
593 DBGPRINT(RT_DEBUG_TRACE
,("%s : TXBAbitmap = %x, BAWinSize = %d, TimeOut = %ld\n", __func__
, pEntry
->TXBAbitmap
,
594 pBAEntry
->BAWinSize
, pBAEntry
->ORIBATimer
.TimerValue
));
597 NStatus
= MlmeAllocateMemory(pAd
, &pOutBuffer2
); //Get an unused nonpaged memory
598 if (NStatus
!= NDIS_STATUS_SUCCESS
)
600 DBGPRINT(RT_DEBUG_TRACE
,("BA - BAOriSessionAdd() allocate memory failed \n"));
604 BarHeaderInit(pAd
, &FrameBar
, pAd
->MacTab
.Content
[pBAEntry
->Wcid
].Addr
, pAd
->CurrentAddress
);
606 FrameBar
.StartingSeq
.field
.FragNum
= 0; // make sure sequence not clear in DEL function.
607 FrameBar
.StartingSeq
.field
.StartSeq
= pBAEntry
->Sequence
; // make sure sequence not clear in DEL funciton.
608 FrameBar
.BarControl
.TID
= pBAEntry
->TID
; // make sure sequence not clear in DEL funciton.
609 MakeOutgoingFrame(pOutBuffer2
, &FrameLen
,
610 sizeof(FRAME_BAR
), &FrameBar
,
612 MiniportMMRequest(pAd
, QID_AC_BE
, pOutBuffer2
, FrameLen
);
613 MlmeFreeMemory(pAd
, pOutBuffer2
);
616 if (pBAEntry
->ORIBATimer
.TimerValue
)
617 RTMPSetTimer(&pBAEntry
->ORIBATimer
, pBAEntry
->ORIBATimer
.TimerValue
); // in mSec
621 BOOLEAN
BARecSessionAdd(
622 IN PRTMP_ADAPTER pAd
,
623 IN MAC_TABLE_ENTRY
*pEntry
,
624 IN PFRAME_ADDBA_REQ pFrame
)
626 BA_REC_ENTRY
*pBAEntry
= NULL
;
627 BOOLEAN Status
= TRUE
;
639 TID
= pFrame
->BaParm
.TID
;
641 BAWinSize
= min(((UCHAR
)pFrame
->BaParm
.BufSize
), (UCHAR
)pAd
->CommonCfg
.BACapability
.field
.RxBAWinLimit
);
649 Idx
= pEntry
->BARecWcidArray
[TID
];
654 pBAEntry
= BATableAllocRecEntry(pAd
, &Idx
);
658 pBAEntry
= &pAd
->BATable
.BARecEntry
[Idx
];
659 // flush all pending reordering mpdus
660 ba_refresh_reordering_mpdus(pAd
, pBAEntry
);
663 DBGPRINT(RT_DEBUG_TRACE
,("%s(%ld): Idx = %d, BAWinSize(req %d) = %d\n", __func__
, pAd
->BATable
.numAsRecipient
, Idx
,
664 pFrame
->BaParm
.BufSize
, BAWinSize
));
666 // Start fill in parameters.
667 if (pBAEntry
!= NULL
)
669 ASSERT(pBAEntry
->list
.qlen
== 0);
671 pBAEntry
->REC_BA_Status
= Recipient_HandleRes
;
672 pBAEntry
->BAWinSize
= BAWinSize
;
673 pBAEntry
->Wcid
= pEntry
->Aid
;
675 pBAEntry
->TimeOutValue
= pFrame
->TimeOutValue
;
676 pBAEntry
->REC_BA_Status
= Recipient_Accept
;
677 // initial sequence number
678 pBAEntry
->LastIndSeq
= RESET_RCV_SEQ
; //pFrame->BaStartSeq.field.StartSeq;
680 printk("Start Seq = %08x\n", pFrame
->BaStartSeq
.field
.StartSeq
);
682 if (pEntry
->RXBAbitmap
& (1<<TID
))
684 RTMPCancelTimer(&pBAEntry
->RECBATimer
, &Cancelled
);
688 RTMPInitTimer(pAd
, &pBAEntry
->RECBATimer
, GET_TIMER_FUNCTION(BARecSessionIdleTimeout
), pBAEntry
, TRUE
);
691 #if 0 // for debugging
692 RTMPSetTimer(&pBAEntry
->RECBATimer
, REC_BA_SESSION_IDLE_TIMEOUT
);
696 pEntry
->RXBAbitmap
|= (1<<TID
);
697 pEntry
->BARecWcidArray
[TID
] = Idx
;
699 pEntry
->BADeclineBitmap
&= ~(1<<TID
);
701 // Set BA session mask in WCID table.
702 RT28XX_ADD_BA_SESSION_TO_ASIC(pAd
, pEntry
->Aid
, TID
);
704 DBGPRINT(RT_DEBUG_TRACE
,("MACEntry[%d]RXBAbitmap = 0x%x. BARecWcidArray=%d\n",
705 pEntry
->Aid
, pEntry
->RXBAbitmap
, pEntry
->BARecWcidArray
[TID
]));
710 DBGPRINT(RT_DEBUG_TRACE
,("Can't Accept ADDBA for %02x:%02x:%02x:%02x:%02x:%02x TID = %d\n",
711 PRINT_MAC(pEntry
->Addr
), TID
));
717 BA_REC_ENTRY
*BATableAllocRecEntry(
718 IN PRTMP_ADAPTER pAd
,
722 BA_REC_ENTRY
*pBAEntry
= NULL
;
725 NdisAcquireSpinLock(&pAd
->BATabLock
);
727 if (pAd
->BATable
.numAsRecipient
>= MAX_BARECI_SESSION
)
729 printk("BA Recipeint Session (%ld) > %d\n", pAd
->BATable
.numAsRecipient
,
734 // reserve idx 0 to identify BAWcidArray[TID] as empty
735 for (i
=1; i
< MAX_LEN_OF_BA_REC_TABLE
; i
++)
737 pBAEntry
=&pAd
->BATable
.BARecEntry
[i
];
738 if ((pBAEntry
->REC_BA_Status
== Recipient_NONE
))
741 pAd
->BATable
.numAsRecipient
++;
742 pBAEntry
->REC_BA_Status
= Recipient_USED
;
749 NdisReleaseSpinLock(&pAd
->BATabLock
);
753 BA_ORI_ENTRY
*BATableAllocOriEntry(
754 IN PRTMP_ADAPTER pAd
,
758 BA_ORI_ENTRY
*pBAEntry
= NULL
;
760 NdisAcquireSpinLock(&pAd
->BATabLock
);
762 if (pAd
->BATable
.numAsOriginator
>= (MAX_LEN_OF_BA_ORI_TABLE
))
767 // reserve idx 0 to identify BAWcidArray[TID] as empty
768 for (i
=1; i
<MAX_LEN_OF_BA_ORI_TABLE
; i
++)
770 pBAEntry
=&pAd
->BATable
.BAOriEntry
[i
];
771 if ((pBAEntry
->ORI_BA_Status
== Originator_NONE
))
774 pAd
->BATable
.numAsOriginator
++;
775 pBAEntry
->ORI_BA_Status
= Originator_USED
;
776 pBAEntry
->pAdapter
= pAd
;
783 NdisReleaseSpinLock(&pAd
->BATabLock
);
788 VOID
BATableFreeOriEntry(
789 IN PRTMP_ADAPTER pAd
,
792 BA_ORI_ENTRY
*pBAEntry
= NULL
;
793 MAC_TABLE_ENTRY
*pEntry
;
796 if ((Idx
== 0) || (Idx
>= MAX_LEN_OF_BA_ORI_TABLE
))
799 pBAEntry
=&pAd
->BATable
.BAOriEntry
[Idx
];
801 if (pBAEntry
->ORI_BA_Status
!= Originator_NONE
)
803 pEntry
= &pAd
->MacTab
.Content
[pBAEntry
->Wcid
];
804 pEntry
->BAOriWcidArray
[pBAEntry
->TID
] = 0;
807 NdisAcquireSpinLock(&pAd
->BATabLock
);
808 if (pBAEntry
->ORI_BA_Status
== Originator_Done
)
810 pEntry
->TXBAbitmap
&= (~(1<<(pBAEntry
->TID
) ));
811 DBGPRINT(RT_DEBUG_TRACE
, ("BATableFreeOriEntry numAsOriginator= %ld\n", pAd
->BATable
.numAsRecipient
));
812 // Erase Bitmap flag.
815 ASSERT(pAd
->BATable
.numAsOriginator
!= 0);
817 pAd
->BATable
.numAsOriginator
-= 1;
819 pBAEntry
->ORI_BA_Status
= Originator_NONE
;
821 NdisReleaseSpinLock(&pAd
->BATabLock
);
826 VOID
BATableFreeRecEntry(
827 IN PRTMP_ADAPTER pAd
,
830 BA_REC_ENTRY
*pBAEntry
= NULL
;
831 MAC_TABLE_ENTRY
*pEntry
;
834 if ((Idx
== 0) || (Idx
>= MAX_LEN_OF_BA_REC_TABLE
))
837 pBAEntry
=&pAd
->BATable
.BARecEntry
[Idx
];
839 if (pBAEntry
->REC_BA_Status
!= Recipient_NONE
)
841 pEntry
= &pAd
->MacTab
.Content
[pBAEntry
->Wcid
];
842 pEntry
->BARecWcidArray
[pBAEntry
->TID
] = 0;
844 NdisAcquireSpinLock(&pAd
->BATabLock
);
846 ASSERT(pAd
->BATable
.numAsRecipient
!= 0);
848 pAd
->BATable
.numAsRecipient
-= 1;
850 pBAEntry
->REC_BA_Status
= Recipient_NONE
;
851 NdisReleaseSpinLock(&pAd
->BATabLock
);
856 VOID
BAOriSessionTearDown(
857 IN OUT PRTMP_ADAPTER pAd
,
861 IN BOOLEAN bForceSend
)
864 BA_ORI_ENTRY
*pBAEntry
;
867 if (Wcid
>= MAX_LEN_OF_MAC_TABLE
)
873 // Locate corresponding BA Originator Entry in BA Table with the (pAddr,TID).
875 Idx
= pAd
->MacTab
.Content
[Wcid
].BAOriWcidArray
[TID
];
876 if ((Idx
== 0) || (Idx
>= MAX_LEN_OF_BA_ORI_TABLE
))
878 if (bForceSend
== TRUE
)
880 // force send specified TID DelBA
881 MLME_DELBA_REQ_STRUCT DelbaReq
;
882 MLME_QUEUE_ELEM
*Elem
= (MLME_QUEUE_ELEM
*) kmalloc(sizeof(MLME_QUEUE_ELEM
), MEM_ALLOC_FLAG
);
884 NdisZeroMemory(&DelbaReq
, sizeof(DelbaReq
));
885 NdisZeroMemory(Elem
, sizeof(MLME_QUEUE_ELEM
));
887 COPY_MAC_ADDR(DelbaReq
.Addr
, pAd
->MacTab
.Content
[Wcid
].Addr
);
888 DelbaReq
.Wcid
= Wcid
;
890 DelbaReq
.Initiator
= ORIGINATOR
;
892 Elem
->MsgLen
= sizeof(DelbaReq
);
893 NdisMoveMemory(Elem
->Msg
, &DelbaReq
, sizeof(DelbaReq
));
894 MlmeDELBAAction(pAd
, Elem
);
897 MlmeEnqueue(pAd
, ACTION_STATE_MACHINE
, MT2_MLME_ORI_DELBA_CATE
, sizeof(MLME_DELBA_REQ_STRUCT
), (PVOID
)&DelbaReq
);
898 RT28XX_MLME_HANDLER(pAd
);
905 DBGPRINT(RT_DEBUG_TRACE
,("%s===>Wcid=%d.TID=%d \n", __func__
, Wcid
, TID
));
907 pBAEntry
= &pAd
->BATable
.BAOriEntry
[Idx
];
908 DBGPRINT(RT_DEBUG_TRACE
,("\t===>Idx = %ld, Wcid=%d.TID=%d, ORI_BA_Status = %d \n", Idx
, Wcid
, TID
, pBAEntry
->ORI_BA_Status
));
910 // Prepare DelBA action frame and send to the peer.
912 if ((bPassive
== FALSE
) && (TID
== pBAEntry
->TID
) && (pBAEntry
->ORI_BA_Status
== Originator_Done
))
914 MLME_DELBA_REQ_STRUCT DelbaReq
;
915 MLME_QUEUE_ELEM
*Elem
= (MLME_QUEUE_ELEM
*) kmalloc(sizeof(MLME_QUEUE_ELEM
), MEM_ALLOC_FLAG
);
917 NdisZeroMemory(&DelbaReq
, sizeof(DelbaReq
));
918 NdisZeroMemory(Elem
, sizeof(MLME_QUEUE_ELEM
));
920 COPY_MAC_ADDR(DelbaReq
.Addr
, pAd
->MacTab
.Content
[Wcid
].Addr
);
921 DelbaReq
.Wcid
= Wcid
;
922 DelbaReq
.TID
= pBAEntry
->TID
;
923 DelbaReq
.Initiator
= ORIGINATOR
;
925 Elem
->MsgLen
= sizeof(DelbaReq
);
926 NdisMoveMemory(Elem
->Msg
, &DelbaReq
, sizeof(DelbaReq
));
927 MlmeDELBAAction(pAd
, Elem
);
930 MlmeEnqueue(pAd
, ACTION_STATE_MACHINE
, MT2_MLME_ORI_DELBA_CATE
, sizeof(MLME_DELBA_REQ_STRUCT
), (PVOID
)&DelbaReq
);
931 RT28XX_MLME_HANDLER(pAd
);
934 RTMPCancelTimer(&pBAEntry
->ORIBATimer
, &Cancelled
);
935 BATableFreeOriEntry(pAd
, Idx
);
939 //BAOriSessionSetUp(pAd, &pAd->MacTab.Content[Wcid], TID, 0, 10000, TRUE);
943 VOID
BARecSessionTearDown(
944 IN OUT PRTMP_ADAPTER pAd
,
950 BA_REC_ENTRY
*pBAEntry
;
952 if (Wcid
>= MAX_LEN_OF_MAC_TABLE
)
958 // Locate corresponding BA Originator Entry in BA Table with the (pAddr,TID).
960 Idx
= pAd
->MacTab
.Content
[Wcid
].BARecWcidArray
[TID
];
964 DBGPRINT(RT_DEBUG_TRACE
,("%s===>Wcid=%d.TID=%d \n", __func__
, Wcid
, TID
));
967 pBAEntry
= &pAd
->BATable
.BARecEntry
[Idx
];
968 DBGPRINT(RT_DEBUG_TRACE
,("\t===>Idx = %ld, Wcid=%d.TID=%d, REC_BA_Status = %d \n", Idx
, Wcid
, TID
, pBAEntry
->REC_BA_Status
));
970 // Prepare DelBA action frame and send to the peer.
972 if ((TID
== pBAEntry
->TID
) && (pBAEntry
->REC_BA_Status
== Recipient_Accept
))
974 MLME_DELBA_REQ_STRUCT DelbaReq
;
976 MLME_QUEUE_ELEM
*Elem
= (MLME_QUEUE_ELEM
*) kmalloc(sizeof(MLME_QUEUE_ELEM
), MEM_ALLOC_FLAG
);
980 RTMPCancelTimer(&pBAEntry
->RECBATimer
, &Cancelled
);
983 // 1. Send DELBA Action Frame
985 if (bPassive
== FALSE
)
987 NdisZeroMemory(&DelbaReq
, sizeof(DelbaReq
));
988 NdisZeroMemory(Elem
, sizeof(MLME_QUEUE_ELEM
));
990 COPY_MAC_ADDR(DelbaReq
.Addr
, pAd
->MacTab
.Content
[Wcid
].Addr
);
991 DelbaReq
.Wcid
= Wcid
;
993 DelbaReq
.Initiator
= RECIPIENT
;
995 Elem
->MsgLen
= sizeof(DelbaReq
);
996 NdisMoveMemory(Elem
->Msg
, &DelbaReq
, sizeof(DelbaReq
));
997 MlmeDELBAAction(pAd
, Elem
);
1000 MlmeEnqueue(pAd
, ACTION_STATE_MACHINE
, MT2_MLME_ORI_DELBA_CATE
, sizeof(MLME_DELBA_REQ_STRUCT
), (PVOID
)&DelbaReq
);
1001 RT28XX_MLME_HANDLER(pAd
);
1007 // 2. Free resource of BA session
1009 // flush all pending reordering mpdus
1010 ba_refresh_reordering_mpdus(pAd
, pBAEntry
);
1012 NdisAcquireSpinLock(&pAd
->BATabLock
);
1014 // Erase Bitmap flag.
1015 pBAEntry
->LastIndSeq
= RESET_RCV_SEQ
;
1016 pBAEntry
->BAWinSize
= 0;
1017 // Erase Bitmap flag at software mactable
1018 pAd
->MacTab
.Content
[Wcid
].RXBAbitmap
&= (~(1<<(pBAEntry
->TID
)));
1019 pAd
->MacTab
.Content
[Wcid
].BARecWcidArray
[TID
] = 0;
1021 RT28XX_DEL_BA_SESSION_FROM_ASIC(pAd
, Wcid
, TID
);
1023 NdisReleaseSpinLock(&pAd
->BATabLock
);
1027 BATableFreeRecEntry(pAd
, Idx
);
1030 VOID
BASessionTearDownALL(
1031 IN OUT PRTMP_ADAPTER pAd
,
1036 for (i
=0; i
<NUM_OF_TID
; i
++)
1038 BAOriSessionTearDown(pAd
, Wcid
, i
, FALSE
, FALSE
);
1039 BARecSessionTearDown(pAd
, Wcid
, i
, FALSE
);
1045 ==========================================================================
1047 Retry sending ADDBA Reqest.
1049 IRQL = DISPATCH_LEVEL
1052 p8023Header: if this is already 802.3 format, p8023Header is NULL
1054 Return : TRUE if put into rx reordering buffer, shouldn't indicaterxhere.
1055 FALSE , then continue indicaterx at this moment.
1056 ==========================================================================
1058 VOID
BAOriSessionSetupTimeout(
1059 IN PVOID SystemSpecific1
,
1060 IN PVOID FunctionContext
,
1061 IN PVOID SystemSpecific2
,
1062 IN PVOID SystemSpecific3
)
1064 BA_ORI_ENTRY
*pBAEntry
= (BA_ORI_ENTRY
*)FunctionContext
;
1065 MAC_TABLE_ENTRY
*pEntry
;
1068 if (pBAEntry
== NULL
)
1071 pAd
= pBAEntry
->pAdapter
;
1073 // Do nothing if monitor mode is on
1074 if (MONITOR_ON(pAd
))
1077 pEntry
= &pAd
->MacTab
.Content
[pBAEntry
->Wcid
];
1079 if ((pBAEntry
->ORI_BA_Status
== Originator_WaitRes
) && (pBAEntry
->Token
< ORI_SESSION_MAX_RETRY
))
1081 MLME_ADDBA_REQ_STRUCT AddbaReq
;
1083 NdisZeroMemory(&AddbaReq
, sizeof(AddbaReq
));
1084 COPY_MAC_ADDR(AddbaReq
.pAddr
, pEntry
->Addr
);
1085 AddbaReq
.Wcid
= (UCHAR
)(pEntry
->Aid
);
1086 AddbaReq
.TID
= pBAEntry
->TID
;
1087 AddbaReq
.BaBufSize
= pAd
->CommonCfg
.BACapability
.field
.RxBAWinLimit
;
1088 AddbaReq
.TimeOutValue
= 0;
1089 AddbaReq
.Token
= pBAEntry
->Token
;
1090 MlmeEnqueue(pAd
, ACTION_STATE_MACHINE
, MT2_MLME_ADD_BA_CATE
, sizeof(MLME_ADDBA_REQ_STRUCT
), (PVOID
)&AddbaReq
);
1091 RT28XX_MLME_HANDLER(pAd
);
1092 DBGPRINT(RT_DEBUG_TRACE
,("BA Ori Session Timeout(%d) : Send ADD BA again\n", pBAEntry
->Token
));
1095 RTMPSetTimer(&pBAEntry
->ORIBATimer
, ORI_BA_SESSION_TIMEOUT
);
1099 BATableFreeOriEntry(pAd
, pEntry
->BAOriWcidArray
[pBAEntry
->TID
]);
1104 ==========================================================================
1106 Retry sending ADDBA Reqest.
1108 IRQL = DISPATCH_LEVEL
1111 p8023Header: if this is already 802.3 format, p8023Header is NULL
1113 Return : TRUE if put into rx reordering buffer, shouldn't indicaterxhere.
1114 FALSE , then continue indicaterx at this moment.
1115 ==========================================================================
1117 VOID
BARecSessionIdleTimeout(
1118 IN PVOID SystemSpecific1
,
1119 IN PVOID FunctionContext
,
1120 IN PVOID SystemSpecific2
,
1121 IN PVOID SystemSpecific3
)
1124 BA_REC_ENTRY
*pBAEntry
= (BA_REC_ENTRY
*)FunctionContext
;
1128 if (pBAEntry
== NULL
)
1131 if ((pBAEntry
->REC_BA_Status
== Recipient_Accept
))
1133 NdisGetSystemUpTime(&Now32
);
1135 if (RTMP_TIME_AFTER((unsigned long)Now32
, (unsigned long)(pBAEntry
->LastIndSeqAtTimer
+ REC_BA_SESSION_IDLE_TIMEOUT
)))
1137 pAd
= pBAEntry
->pAdapter
;
1138 // flush all pending reordering mpdus
1139 ba_refresh_reordering_mpdus(pAd
, pBAEntry
);
1140 printk("%ld: REC BA session Timeout\n", Now32
);
1146 VOID
PeerAddBAReqAction(
1147 IN PRTMP_ADAPTER pAd
,
1148 IN MLME_QUEUE_ELEM
*Elem
)
1155 FRAME_ADDBA_RSP ADDframe
;
1156 PUCHAR pOutBuffer
= NULL
;
1157 NDIS_STATUS NStatus
;
1158 PFRAME_ADDBA_REQ pAddreqFrame
= NULL
;
1162 PMAC_TABLE_ENTRY pMacEntry
;
1164 DBGPRINT(RT_DEBUG_TRACE
, ("%s ==> (Wcid = %d)\n", __func__
, Elem
->Wcid
));
1166 //hex_dump("AddBAReq", Elem->Msg, Elem->MsgLen);
1168 //ADDBA Request from unknown peer, ignore this.
1169 if (Elem
->Wcid
>= MAX_LEN_OF_MAC_TABLE
)
1172 pMacEntry
= &pAd
->MacTab
.Content
[Elem
->Wcid
];
1173 DBGPRINT(RT_DEBUG_TRACE
,("BA - PeerAddBAReqAction----> \n"));
1174 ptemp
= (PULONG
)Elem
->Msg
;
1175 //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)));
1177 if (PeerAddBAReqActionSanity(pAd
, Elem
->Msg
, Elem
->MsgLen
, pAddr
))
1180 if ((pAd
->CommonCfg
.bBADecline
== FALSE
) && IS_HT_STA(pMacEntry
))
1182 pAddreqFrame
= (PFRAME_ADDBA_REQ
)(&Elem
->Msg
[0]);
1183 printk("Rcv Wcid(%d) AddBAReq\n", Elem
->Wcid
);
1184 if (BARecSessionAdd(pAd
, &pAd
->MacTab
.Content
[Elem
->Wcid
], pAddreqFrame
))
1187 Status
= 38; // more parameters have invalid values
1191 Status
= 37; // the request has been declined.
1195 if (pAd
->MacTab
.Content
[Elem
->Wcid
].ValidAsCLI
)
1196 ASSERT(pAd
->MacTab
.Content
[Elem
->Wcid
].Sst
== SST_ASSOC
);
1198 pAddreqFrame
= (PFRAME_ADDBA_REQ
)(&Elem
->Msg
[0]);
1199 // 2. Always send back ADDBA Response
1200 NStatus
= MlmeAllocateMemory(pAd
, &pOutBuffer
); //Get an unused nonpaged memory
1201 if (NStatus
!= NDIS_STATUS_SUCCESS
)
1203 DBGPRINT(RT_DEBUG_TRACE
,("ACTION - PeerBAAction() allocate memory failed \n"));
1207 NdisZeroMemory(&ADDframe
, sizeof(FRAME_ADDBA_RSP
));
1209 // 2-1. Prepare ADDBA Response frame.
1212 ActHeaderInit(pAd
, &ADDframe
.Hdr
, pAddr
, pAd
->CurrentAddress
, pAd
->CommonCfg
.Bssid
);
1214 ActHeaderInit(pAd
, &ADDframe
.Hdr
, pAd
->CommonCfg
.Bssid
, pAd
->CurrentAddress
, pAddr
);
1217 ADDframe
.Category
= CATEGORY_BA
;
1218 ADDframe
.Action
= ADDBA_RESP
;
1219 ADDframe
.Token
= pAddreqFrame
->Token
;
1220 // What is the Status code?? need to check.
1221 ADDframe
.StatusCode
= Status
;
1222 ADDframe
.BaParm
.BAPolicy
= IMMED_BA
;
1223 ADDframe
.BaParm
.AMSDUSupported
= 0;
1224 ADDframe
.BaParm
.TID
= pAddreqFrame
->BaParm
.TID
;
1225 ADDframe
.BaParm
.BufSize
= min(((UCHAR
)pAddreqFrame
->BaParm
.BufSize
), (UCHAR
)pAd
->CommonCfg
.BACapability
.field
.RxBAWinLimit
);
1226 if (ADDframe
.BaParm
.BufSize
== 0)
1228 ADDframe
.BaParm
.BufSize
= 64;
1230 ADDframe
.TimeOutValue
= 0; //pAddreqFrame->TimeOutValue;
1232 *(USHORT
*)(&ADDframe
.BaParm
) = cpu2le16(*(USHORT
*)(&ADDframe
.BaParm
));
1233 ADDframe
.StatusCode
= cpu2le16(ADDframe
.StatusCode
);
1234 ADDframe
.TimeOutValue
= cpu2le16(ADDframe
.TimeOutValue
);
1236 MakeOutgoingFrame(pOutBuffer
, &FrameLen
,
1237 sizeof(FRAME_ADDBA_RSP
), &ADDframe
,
1239 MiniportMMRequest(pAd
, QID_AC_BE
, pOutBuffer
, FrameLen
);
1240 MlmeFreeMemory(pAd
, pOutBuffer
);
1242 DBGPRINT(RT_DEBUG_TRACE
, ("%s(%d): TID(%d), BufSize(%d) <== \n", __func__
, Elem
->Wcid
, ADDframe
.BaParm
.TID
,
1243 ADDframe
.BaParm
.BufSize
));
1247 VOID
PeerAddBARspAction(
1248 IN PRTMP_ADAPTER pAd
,
1249 IN MLME_QUEUE_ELEM
*Elem
)
1253 //PUCHAR pOutBuffer = NULL;
1254 PFRAME_ADDBA_RSP pFrame
= NULL
;
1255 //PBA_ORI_ENTRY pBAEntry;
1257 //ADDBA Response from unknown peer, ignore this.
1258 if (Elem
->Wcid
>= MAX_LEN_OF_MAC_TABLE
)
1261 DBGPRINT(RT_DEBUG_TRACE
, ("%s ==> Wcid(%d)\n", __func__
, Elem
->Wcid
));
1263 //hex_dump("PeerAddBARspAction()", Elem->Msg, Elem->MsgLen);
1265 if (PeerAddBARspActionSanity(pAd
, Elem
->Msg
, Elem
->MsgLen
))
1267 pFrame
= (PFRAME_ADDBA_RSP
)(&Elem
->Msg
[0]);
1269 DBGPRINT(RT_DEBUG_TRACE
, ("\t\t StatusCode = %d\n", pFrame
->StatusCode
));
1270 switch (pFrame
->StatusCode
)
1273 // I want a BAsession with this peer as an originator.
1274 BAOriSessionAdd(pAd
, &pAd
->MacTab
.Content
[Elem
->Wcid
], pFrame
);
1277 // check status == USED ???
1278 BAOriSessionTearDown(pAd
, Elem
->Wcid
, pFrame
->BaParm
.TID
, TRUE
, FALSE
);
1281 // Rcv Decline StatusCode
1282 if ((pFrame
->StatusCode
== 37)
1283 || ((pAd
->OpMode
== OPMODE_STA
) && STA_TGN_WIFI_ON(pAd
) && (pFrame
->StatusCode
!= 0))
1286 pAd
->MacTab
.Content
[Elem
->Wcid
].BADeclineBitmap
|= 1<<pFrame
->BaParm
.TID
;
1291 VOID
PeerDelBAAction(
1292 IN PRTMP_ADAPTER pAd
,
1293 IN MLME_QUEUE_ELEM
*Elem
)
1297 //PUCHAR pOutBuffer = NULL;
1298 PFRAME_DELBA_REQ pDelFrame
= NULL
;
1300 DBGPRINT(RT_DEBUG_TRACE
,("%s ==>\n", __func__
));
1301 //DELBA Request from unknown peer, ignore this.
1302 if (PeerDelBAActionSanity(pAd
, Elem
->Wcid
, Elem
->Msg
, Elem
->MsgLen
))
1304 pDelFrame
= (PFRAME_DELBA_REQ
)(&Elem
->Msg
[0]);
1305 if (pDelFrame
->DelbaParm
.Initiator
== ORIGINATOR
)
1307 DBGPRINT(RT_DEBUG_TRACE
,("BA - PeerDelBAAction----> ORIGINATOR\n"));
1308 BARecSessionTearDown(pAd
, Elem
->Wcid
, pDelFrame
->DelbaParm
.TID
, TRUE
);
1312 DBGPRINT(RT_DEBUG_TRACE
,("BA - PeerDelBAAction----> RECIPIENT, Reason = %d\n", pDelFrame
->ReasonCode
));
1313 //hex_dump("DelBA Frame", pDelFrame, Elem->MsgLen);
1314 BAOriSessionTearDown(pAd
, Elem
->Wcid
, pDelFrame
->DelbaParm
.TID
, TRUE
, FALSE
);
1320 BOOLEAN
CntlEnqueueForRecv(
1321 IN PRTMP_ADAPTER pAd
,
1324 IN PFRAME_BA_REQ pMsg
)
1326 PFRAME_BA_REQ pFrame
= pMsg
;
1327 //PRTMP_REORDERBUF pBuffer;
1328 //PRTMP_REORDERBUF pDmaBuf;
1329 PBA_REC_ENTRY pBAEntry
;
1335 TID
= (UCHAR
)pFrame
->BARControl
.TID
;
1337 DBGPRINT(RT_DEBUG_TRACE
, ("%s(): BAR-Wcid(%ld), Tid (%d)\n", __func__
, Wcid
, TID
));
1338 //hex_dump("BAR", (PCHAR) pFrame, MsgLen);
1339 // Do nothing if the driver is starting halt state.
1340 // This might happen when timer already been fired before cancel timer with mlmehalt
1341 if (RTMP_TEST_FLAG(pAd
, fRTMP_ADAPTER_HALT_IN_PROGRESS
| fRTMP_ADAPTER_NIC_NOT_EXIST
))
1344 // First check the size, it MUST not exceed the mlme queue size
1345 if (MsgLen
> MGMT_DMA_BUFFER_SIZE
)
1347 DBGPRINT_ERR(("CntlEnqueueForRecv: frame too large, size = %ld \n", MsgLen
));
1350 else if (MsgLen
!= sizeof(FRAME_BA_REQ
))
1352 DBGPRINT_ERR(("CntlEnqueueForRecv: BlockAck Request frame length size = %ld incorrect\n", MsgLen
));
1355 else if (MsgLen
!= sizeof(FRAME_BA_REQ
))
1357 DBGPRINT_ERR(("CntlEnqueueForRecv: BlockAck Request frame length size = %ld incorrect\n", MsgLen
));
1361 if ((Wcid
< MAX_LEN_OF_MAC_TABLE
) && (TID
< 8))
1363 // if this receiving packet is from SA that is in our OriEntry. Since WCID <9 has direct mapping. no need search.
1364 Idx
= pAd
->MacTab
.Content
[Wcid
].BARecWcidArray
[TID
];
1365 pBAEntry
= &pAd
->BATable
.BARecEntry
[Idx
];
1372 DBGPRINT(RT_DEBUG_TRACE
, ("BAR(%ld) : Tid (%d) - %04x:%04x\n", Wcid
, TID
, pFrame
->BAStartingSeq
.field
.StartSeq
, pBAEntry
->LastIndSeq
));
1374 if (SEQ_SMALLER(pBAEntry
->LastIndSeq
, pFrame
->BAStartingSeq
.field
.StartSeq
, MAXSEQ
))
1376 //printk("BAR Seq = %x, LastIndSeq = %x\n", pFrame->BAStartingSeq.field.StartSeq, pBAEntry->LastIndSeq);
1377 ba_indicate_reordering_mpdus_le_seq(pAd
, pBAEntry
, pFrame
->BAStartingSeq
.field
.StartSeq
);
1378 pBAEntry
->LastIndSeq
= (pFrame
->BAStartingSeq
.field
.StartSeq
== 0) ? MAXSEQ
:(pFrame
->BAStartingSeq
.field
.StartSeq
-1);
1380 //ba_refresh_reordering_mpdus(pAd, pBAEntry);
1385 Description : Send PSMP Action frame If PSMP mode switches.
1387 VOID
SendPSMPAction(
1388 IN PRTMP_ADAPTER pAd
,
1392 PUCHAR pOutBuffer
= NULL
;
1393 NDIS_STATUS NStatus
;
1395 FRAME_PSMP_ACTION Frame
;
1398 NStatus
= MlmeAllocateMemory(pAd
, &pOutBuffer
); //Get an unused nonpaged memory
1399 if (NStatus
!= NDIS_STATUS_SUCCESS
)
1401 DBGPRINT(RT_DEBUG_ERROR
,("BA - MlmeADDBAAction() allocate memory failed \n"));
1405 ActHeaderInit(pAd
, &Frame
.Hdr
, pAd
->CommonCfg
.Bssid
, pAd
->CurrentAddress
, pAd
->MacTab
.Content
[Wcid
].Addr
);
1407 Frame
.Category
= CATEGORY_HT
;
1408 Frame
.Action
= SMPS_ACTION
;
1421 MakeOutgoingFrame(pOutBuffer
, &FrameLen
,
1422 sizeof(FRAME_PSMP_ACTION
), &Frame
,
1424 MiniportMMRequest(pAd
, QID_AC_BE
, pOutBuffer
, FrameLen
);
1425 MlmeFreeMemory(pAd
, pOutBuffer
);
1426 DBGPRINT(RT_DEBUG_ERROR
,("HT - SendPSMPAction( %d ) \n", Frame
.Psmp
));
1430 #define RADIO_MEASUREMENT_REQUEST_ACTION 0
1432 typedef struct PACKED
1434 UCHAR RegulatoryClass
;
1435 UCHAR ChannelNumber
;
1436 USHORT RandomInterval
;
1437 USHORT MeasurementDuration
;
1438 UCHAR MeasurementMode
;
1439 UCHAR BSSID
[MAC_ADDR_LEN
];
1440 UCHAR ReportingCondition
;
1442 UCHAR SSIDIE
[2]; // 2 byte
1445 typedef struct PACKED
1457 void convert_reordering_packet_to_preAMSDU_or_802_3_packet(
1458 IN PRTMP_ADAPTER pAd
,
1460 IN UCHAR FromWhichBSSID
)
1462 PNDIS_PACKET pRxPkt
;
1463 UCHAR Header802_3
[LENGTH_802_3
];
1465 // 1. get 802.3 Header
1467 // a. pointer pRxBlk->pData to payload
1468 // b. modify pRxBlk->DataSize
1470 RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk
, Header802_3
);
1472 ASSERT(pRxBlk
->pRxPacket
);
1473 pRxPkt
= RTPKT_TO_OSPKT(pRxBlk
->pRxPacket
);
1475 RTPKT_TO_OSPKT(pRxPkt
)->dev
= get_netdev_from_bssid(pAd
, FromWhichBSSID
);
1476 RTPKT_TO_OSPKT(pRxPkt
)->data
= pRxBlk
->pData
;
1477 RTPKT_TO_OSPKT(pRxPkt
)->len
= pRxBlk
->DataSize
;
1478 RTPKT_TO_OSPKT(pRxPkt
)->tail
= RTPKT_TO_OSPKT(pRxPkt
)->data
+ RTPKT_TO_OSPKT(pRxPkt
)->len
;
1481 // copy 802.3 header, if necessary
1483 if (!RX_BLK_TEST_FLAG(pRxBlk
, fRX_AMSDU
))
1486 NdisMoveMemory(skb_push(pRxPkt
, LENGTH_802_3
), Header802_3
, LENGTH_802_3
);
1492 #define INDICATE_LEGACY_OR_AMSDU(_pAd, _pRxBlk, _fromWhichBSSID) \
1495 if (RX_BLK_TEST_FLAG(_pRxBlk, fRX_AMSDU)) \
1497 Indicate_AMSDU_Packet(_pAd, _pRxBlk, _fromWhichBSSID); \
1499 else if (RX_BLK_TEST_FLAG(_pRxBlk, fRX_EAP)) \
1501 Indicate_EAPOL_Packet(_pAd, _pRxBlk, _fromWhichBSSID); \
1505 Indicate_Legacy_Packet(_pAd, _pRxBlk, _fromWhichBSSID); \
1511 static VOID
ba_enqueue_reordering_packet(
1512 IN PRTMP_ADAPTER pAd
,
1513 IN PBA_REC_ENTRY pBAEntry
,
1515 IN UCHAR FromWhichBSSID
)
1517 struct reordering_mpdu
*mpdu_blk
;
1518 UINT16 Sequence
= (UINT16
) pRxBlk
->pHeader
->Sequence
;
1520 mpdu_blk
= ba_mpdu_blk_alloc(pAd
);
1521 if (mpdu_blk
!= NULL
)
1523 // Write RxD buffer address & allocated buffer length
1524 NdisAcquireSpinLock(&pBAEntry
->RxReRingLock
);
1526 mpdu_blk
->Sequence
= Sequence
;
1528 mpdu_blk
->bAMSDU
= RX_BLK_TEST_FLAG(pRxBlk
, fRX_AMSDU
);
1530 convert_reordering_packet_to_preAMSDU_or_802_3_packet(pAd
, pRxBlk
, FromWhichBSSID
);
1532 STATS_INC_RX_PACKETS(pAd
, FromWhichBSSID
);
1535 // it is necessary for reordering packet to record
1536 // which BSS it come from
1538 RTMP_SET_PACKET_IF(pRxBlk
->pRxPacket
, FromWhichBSSID
);
1540 mpdu_blk
->pPacket
= pRxBlk
->pRxPacket
;
1542 if (ba_reordering_mpdu_insertsorted(&pBAEntry
->list
, mpdu_blk
) == FALSE
)
1544 // had been already within reordering list
1546 RELEASE_NDIS_PACKET(pAd
, pRxBlk
->pRxPacket
, NDIS_STATUS_SUCCESS
);
1547 ba_mpdu_blk_free(pAd
, mpdu_blk
);
1550 ASSERT((0<= pBAEntry
->list
.qlen
) && (pBAEntry
->list
.qlen
<= pBAEntry
->BAWinSize
));
1551 NdisReleaseSpinLock(&pBAEntry
->RxReRingLock
);
1556 DBGPRINT(RT_DEBUG_ERROR
, ("!!! (%d:%d) Can't allocate reordering mpdu blk\n",
1557 blk_count
, pBAEntry
->list
.qlen
));
1559 DBGPRINT(RT_DEBUG_ERROR
, ("!!! (%d) Can't allocate reordering mpdu blk\n",
1560 pBAEntry
->list
.qlen
));
1563 * flush all pending reordering mpdus
1564 * and receving mpdu to upper layer
1565 * make tcp/ip to take care reordering mechanism
1567 //ba_refresh_reordering_mpdus(pAd, pBAEntry);
1568 ba_indicate_reordering_mpdus_le_seq(pAd
, pBAEntry
, Sequence
);
1570 pBAEntry
->LastIndSeq
= Sequence
;
1571 INDICATE_LEGACY_OR_AMSDU(pAd
, pRxBlk
, FromWhichBSSID
);
1577 ==========================================================================
1579 Indicate this packet to upper layer or put it into reordering buffer
1582 pRxBlk : carry necessary packet info 802.11 format
1583 FromWhichBSSID : the packet received from which BSS
1589 the packet queued into reordering buffer need to cover to 802.3 format
1591 ==========================================================================
1594 VOID
Indicate_AMPDU_Packet(
1595 IN PRTMP_ADAPTER pAd
,
1597 IN UCHAR FromWhichBSSID
)
1600 PBA_REC_ENTRY pBAEntry
= NULL
;
1601 UINT16 Sequence
= pRxBlk
->pHeader
->Sequence
;
1603 UCHAR Wcid
= pRxBlk
->pRxWI
->WirelessCliID
;
1604 UCHAR TID
= pRxBlk
->pRxWI
->TID
;
1607 if (!RX_BLK_TEST_FLAG(pRxBlk
, fRX_AMSDU
) && (pRxBlk
->DataSize
> MAX_RX_PKT_LEN
))
1609 #if 0 // sample take off, no use
1610 static int err_size
;
1613 if (err_size
> 20) {
1614 printk("AMPDU DataSize = %d\n", pRxBlk
->DataSize
);
1615 hex_dump("802.11 Header", (UCHAR
*)pRxBlk
->pHeader
, 24);
1616 hex_dump("Payload", pRxBlk
->pData
, 64);
1621 RELEASE_NDIS_PACKET(pAd
, pRxBlk
->pRxPacket
, NDIS_STATUS_FAILURE
);
1627 /* Rec BA Session had been torn down */
1628 INDICATE_LEGACY_OR_AMSDU(pAd
, pRxBlk
, FromWhichBSSID
);
1632 if (Wcid
< MAX_LEN_OF_MAC_TABLE
)
1634 Idx
= pAd
->MacTab
.Content
[Wcid
].BARecWcidArray
[TID
];
1637 /* Rec BA Session had been torn down */
1638 INDICATE_LEGACY_OR_AMSDU(pAd
, pRxBlk
, FromWhichBSSID
);
1641 pBAEntry
= &pAd
->BATable
.BARecEntry
[Idx
];
1648 RELEASE_NDIS_PACKET(pAd
, pRxBlk
->pRxPacket
, NDIS_STATUS_FAILURE
);
1654 // update last rx time
1655 NdisGetSystemUpTime(&Now32
);
1657 pBAEntry
->rcvSeq
= Sequence
;
1660 ba_flush_reordering_timeout_mpdus(pAd
, pBAEntry
, Now32
);
1661 pBAEntry
->LastIndSeqAtTimer
= Now32
;
1664 // Reset Last Indicate Sequence
1666 if (pBAEntry
->LastIndSeq
== RESET_RCV_SEQ
)
1668 ASSERT((pBAEntry
->list
.qlen
== 0) && (pBAEntry
->list
.next
== NULL
));
1670 // reset rcv sequence of BA session
1671 pBAEntry
->LastIndSeq
= Sequence
;
1672 pBAEntry
->LastIndSeqAtTimer
= Now32
;
1673 INDICATE_LEGACY_OR_AMSDU(pAd
, pRxBlk
, FromWhichBSSID
);
1679 // I. Check if in order.
1681 if (SEQ_STEPONE(Sequence
, pBAEntry
->LastIndSeq
, MAXSEQ
))
1685 pBAEntry
->LastIndSeq
= Sequence
;
1686 INDICATE_LEGACY_OR_AMSDU(pAd
, pRxBlk
, FromWhichBSSID
);
1687 LastIndSeq
= ba_indicate_reordering_mpdus_in_order(pAd
, pBAEntry
, pBAEntry
->LastIndSeq
);
1688 if (LastIndSeq
!= RESET_RCV_SEQ
)
1690 pBAEntry
->LastIndSeq
= LastIndSeq
;
1692 pBAEntry
->LastIndSeqAtTimer
= Now32
;
1695 // II. Drop Duplicated Packet
1697 else if (Sequence
== pBAEntry
->LastIndSeq
)
1700 // drop and release packet
1701 pBAEntry
->nDropPacket
++;
1702 RELEASE_NDIS_PACKET(pAd
, pRxBlk
->pRxPacket
, NDIS_STATUS_FAILURE
);
1705 // III. Drop Old Received Packet
1707 else if (SEQ_SMALLER(Sequence
, pBAEntry
->LastIndSeq
, MAXSEQ
))
1710 // drop and release packet
1711 pBAEntry
->nDropPacket
++;
1712 RELEASE_NDIS_PACKET(pAd
, pRxBlk
->pRxPacket
, NDIS_STATUS_FAILURE
);
1715 // IV. Receive Sequence within Window Size
1717 else if (SEQ_SMALLER(Sequence
, (((pBAEntry
->LastIndSeq
+pBAEntry
->BAWinSize
+1)) & MAXSEQ
), MAXSEQ
))
1719 ba_enqueue_reordering_packet(pAd
, pBAEntry
, pRxBlk
, FromWhichBSSID
);
1722 // V. Receive seq surpasses Win(lastseq + nMSDU). So refresh all reorder buffer
1727 ba_refresh_reordering_mpdus(pAd
, pBAEntry
);
1728 INDICATE_LEGACY_OR_AMSDU(pAd
, pRxBlk
, FromWhichBSSID
);
1730 LONG WinStartSeq
, TmpSeq
;
1733 TmpSeq
= Sequence
- (pBAEntry
->BAWinSize
) -1;
1736 TmpSeq
= (MAXSEQ
+1) + TmpSeq
;
1738 WinStartSeq
= (TmpSeq
+1) & MAXSEQ
;
1739 ba_indicate_reordering_mpdus_le_seq(pAd
, pBAEntry
, WinStartSeq
);
1740 pBAEntry
->LastIndSeq
= WinStartSeq
; //TmpSeq;
1742 pBAEntry
->LastIndSeqAtTimer
= Now32
;
1744 ba_enqueue_reordering_packet(pAd
, pBAEntry
, pRxBlk
, FromWhichBSSID
);
1746 TmpSeq
= ba_indicate_reordering_mpdus_in_order(pAd
, pBAEntry
, pBAEntry
->LastIndSeq
);
1747 if (TmpSeq
!= RESET_RCV_SEQ
)
1749 pBAEntry
->LastIndSeq
= TmpSeq
;