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 #ifdef DOT11_N_SUPPORT
31 #include "../rt_config.h"
35 #define BA_ORI_INIT_SEQ (pEntry->TxSeq[TID]) //1 // inital sequence number of BA session
37 #define ORI_SESSION_MAX_RETRY 8
38 #define ORI_BA_SESSION_TIMEOUT (2000) // ms
39 #define REC_BA_SESSION_IDLE_TIMEOUT (1000) // ms
41 #define REORDERING_PACKET_TIMEOUT ((100 * HZ)/1000) // system ticks -- 100 ms
42 #define MAX_REORDERING_PACKET_TIMEOUT ((3000 * HZ)/1000) // system ticks -- 100 ms
44 #define RESET_RCV_SEQ (0xFFFF)
46 static void ba_mpdu_blk_free(PRTMP_ADAPTER pAd
, struct reordering_mpdu
*mpdu_blk
);
49 BA_ORI_ENTRY
*BATableAllocOriEntry(
53 BA_REC_ENTRY
*BATableAllocRecEntry(
57 VOID
BAOriSessionSetupTimeout(
58 IN PVOID SystemSpecific1
,
59 IN PVOID FunctionContext
,
60 IN PVOID SystemSpecific2
,
61 IN PVOID SystemSpecific3
);
63 VOID
BARecSessionIdleTimeout(
64 IN PVOID SystemSpecific1
,
65 IN PVOID FunctionContext
,
66 IN PVOID SystemSpecific2
,
67 IN PVOID SystemSpecific3
);
70 BUILD_TIMER_FUNCTION(BAOriSessionSetupTimeout
);
71 BUILD_TIMER_FUNCTION(BARecSessionIdleTimeout
);
73 #define ANNOUNCE_REORDERING_PACKET(_pAd, _mpdu_blk) \
74 Announce_Reordering_Packet(_pAd, _mpdu_blk);
76 VOID
BA_MaxWinSizeReasign(
78 IN MAC_TABLE_ENTRY
*pEntryPeer
,
84 if (pAd
->MACVersion
>= RALINK_2883_VERSION
) // 3*3
86 if (pAd
->MACVersion
>= RALINK_3070_VERSION
)
88 if (pEntryPeer
->WepStatus
!= Ndis802_11EncryptionDisabled
)
89 MaxSize
= 7; // for non-open mode
96 else if (pAd
->MACVersion
>= RALINK_2880E_VERSION
) // 2880 e
98 if (pEntryPeer
->WepStatus
!= Ndis802_11EncryptionDisabled
)
99 MaxSize
= 7; // for non-open mode
106 DBGPRINT(RT_DEBUG_TRACE
, ("ba> Win Size = %d, Max Size = %d\n",
107 *pWinSize
, MaxSize
));
109 if ((*pWinSize
) > MaxSize
)
111 DBGPRINT(RT_DEBUG_TRACE
, ("ba> reassign max win size from %d to %d\n",
112 *pWinSize
, MaxSize
));
118 void Announce_Reordering_Packet(IN PRTMP_ADAPTER pAd
,
119 IN
struct reordering_mpdu
*mpdu
)
121 PNDIS_PACKET pPacket
;
123 pPacket
= mpdu
->pPacket
;
128 BA_Reorder_AMSDU_Annnounce(pAd
, pPacket
);
133 // pass this 802.3 packet to upper layer or forward this packet to WM directly
136 #ifdef CONFIG_STA_SUPPORT
137 IF_DEV_CONFIG_OPMODE_ON_STA(pAd
)
138 ANNOUNCE_OR_FORWARD_802_3_PACKET(pAd
, pPacket
, RTMP_GET_PACKET_IF(pPacket
));
139 #endif // CONFIG_STA_SUPPORT //
144 * Insert a reordering mpdu into sorted linked list by sequence no.
146 BOOLEAN
ba_reordering_mpdu_insertsorted(struct reordering_list
*list
, struct reordering_mpdu
*mpdu
)
149 struct reordering_mpdu
**ppScan
= &list
->next
;
151 while (*ppScan
!= NULL
)
153 if (SEQ_SMALLER((*ppScan
)->Sequence
, mpdu
->Sequence
, MAXSEQ
))
155 ppScan
= &(*ppScan
)->next
;
157 else if ((*ppScan
)->Sequence
== mpdu
->Sequence
)
159 /* give up this duplicated frame */
169 mpdu
->next
= *ppScan
;
177 * caller lock critical section if necessary
179 static inline void ba_enqueue(struct reordering_list
*list
, struct reordering_mpdu
*mpdu_blk
)
182 mpdu_blk
->next
= list
->next
;
183 list
->next
= mpdu_blk
;
187 * caller lock critical section if necessary
189 static inline struct reordering_mpdu
* ba_dequeue(struct reordering_list
*list
)
191 struct reordering_mpdu
*mpdu_blk
= NULL
;
198 mpdu_blk
= list
->next
;
201 list
->next
= mpdu_blk
->next
;
202 mpdu_blk
->next
= NULL
;
209 static inline struct reordering_mpdu
*ba_reordering_mpdu_dequeue(struct reordering_list
*list
)
211 return(ba_dequeue(list
));
215 static inline struct reordering_mpdu
*ba_reordering_mpdu_probe(struct reordering_list
*list
)
224 * free all resource for reordering mechanism
226 void ba_reordering_resource_release(PRTMP_ADAPTER pAd
)
229 PBA_REC_ENTRY pBAEntry
;
230 struct reordering_mpdu
*mpdu_blk
;
235 /* I. release all pending reordering packet */
236 NdisAcquireSpinLock(&pAd
->BATabLock
);
237 for (i
= 0; i
< MAX_LEN_OF_BA_REC_TABLE
; i
++)
239 pBAEntry
= &Tab
->BARecEntry
[i
];
240 if (pBAEntry
->REC_BA_Status
!= Recipient_NONE
)
242 while ((mpdu_blk
= ba_reordering_mpdu_dequeue(&pBAEntry
->list
)))
244 ASSERT(mpdu_blk
->pPacket
);
245 RELEASE_NDIS_PACKET(pAd
, mpdu_blk
->pPacket
, NDIS_STATUS_FAILURE
);
246 ba_mpdu_blk_free(pAd
, mpdu_blk
);
250 NdisReleaseSpinLock(&pAd
->BATabLock
);
252 ASSERT(pBAEntry
->list
.qlen
== 0);
253 /* II. free memory of reordering mpdu table */
254 NdisAcquireSpinLock(&pAd
->mpdu_blk_pool
.lock
);
255 os_free_mem(pAd
, pAd
->mpdu_blk_pool
.mem
);
256 NdisReleaseSpinLock(&pAd
->mpdu_blk_pool
.lock
);
262 * Allocate all resource for reordering mechanism
264 BOOLEAN
ba_reordering_resource_init(PRTMP_ADAPTER pAd
, int num
)
268 struct reordering_mpdu
*mpdu_blk
;
269 struct reordering_list
*freelist
;
271 /* allocate spinlock */
272 NdisAllocateSpinLock(&pAd
->mpdu_blk_pool
.lock
);
274 /* initialize freelist */
275 freelist
= &pAd
->mpdu_blk_pool
.freelist
;
276 freelist
->next
= NULL
;
279 DBGPRINT(RT_DEBUG_TRACE
, ("Allocate %d memory for BA reordering\n", (UINT32
)(num
*sizeof(struct reordering_mpdu
))));
281 /* allocate number of mpdu_blk memory */
282 os_alloc_mem(pAd
, (PUCHAR
*)&mem
, (num
*sizeof(struct reordering_mpdu
)));
284 pAd
->mpdu_blk_pool
.mem
= mem
;
288 DBGPRINT(RT_DEBUG_ERROR
, ("Can't Allocate Memory for BA Reordering\n"));
292 /* build mpdu_blk free list */
293 for (i
=0; i
<num
; i
++)
296 mpdu_blk
= (struct reordering_mpdu
*) mem
;
297 /* initial mpdu_blk */
298 NdisZeroMemory(mpdu_blk
, sizeof(struct reordering_mpdu
));
300 mem
+= sizeof(struct reordering_mpdu
);
301 /* insert mpdu_blk into freelist */
302 ba_enqueue(freelist
, mpdu_blk
);
308 //static int blk_count=0; // sample take off, no use
310 static struct reordering_mpdu
*ba_mpdu_blk_alloc(PRTMP_ADAPTER pAd
)
312 struct reordering_mpdu
*mpdu_blk
;
314 NdisAcquireSpinLock(&pAd
->mpdu_blk_pool
.lock
);
315 mpdu_blk
= ba_dequeue(&pAd
->mpdu_blk_pool
.freelist
);
320 NdisZeroMemory(mpdu_blk
, sizeof(struct reordering_mpdu
));
322 NdisReleaseSpinLock(&pAd
->mpdu_blk_pool
.lock
);
326 static void ba_mpdu_blk_free(PRTMP_ADAPTER pAd
, struct reordering_mpdu
*mpdu_blk
)
330 NdisAcquireSpinLock(&pAd
->mpdu_blk_pool
.lock
);
332 ba_enqueue(&pAd
->mpdu_blk_pool
.freelist
, mpdu_blk
);
333 NdisReleaseSpinLock(&pAd
->mpdu_blk_pool
.lock
);
337 static USHORT
ba_indicate_reordering_mpdus_in_order(
338 IN PRTMP_ADAPTER pAd
,
339 IN PBA_REC_ENTRY pBAEntry
,
342 struct reordering_mpdu
*mpdu_blk
;
343 USHORT LastIndSeq
= RESET_RCV_SEQ
;
345 NdisAcquireSpinLock(&pBAEntry
->RxReRingLock
);
347 while ((mpdu_blk
= ba_reordering_mpdu_probe(&pBAEntry
->list
)))
349 /* find in-order frame */
350 if (!SEQ_STEPONE(mpdu_blk
->Sequence
, StartSeq
, MAXSEQ
))
354 /* dequeue in-order frame from reodering list */
355 mpdu_blk
= ba_reordering_mpdu_dequeue(&pBAEntry
->list
);
356 /* pass this frame up */
357 ANNOUNCE_REORDERING_PACKET(pAd
, mpdu_blk
);
358 /* move to next sequence */
359 StartSeq
= mpdu_blk
->Sequence
;
360 LastIndSeq
= StartSeq
;
362 ba_mpdu_blk_free(pAd
, mpdu_blk
);
365 NdisReleaseSpinLock(&pBAEntry
->RxReRingLock
);
367 /* update last indicated sequence */
371 static void ba_indicate_reordering_mpdus_le_seq(
372 IN PRTMP_ADAPTER pAd
,
373 IN PBA_REC_ENTRY pBAEntry
,
376 struct reordering_mpdu
*mpdu_blk
;
378 NdisAcquireSpinLock(&pBAEntry
->RxReRingLock
);
379 while ((mpdu_blk
= ba_reordering_mpdu_probe(&pBAEntry
->list
)))
381 /* find in-order frame */
382 if ((mpdu_blk
->Sequence
== Sequence
) || SEQ_SMALLER(mpdu_blk
->Sequence
, Sequence
, MAXSEQ
))
384 /* dequeue in-order frame from reodering list */
385 mpdu_blk
= ba_reordering_mpdu_dequeue(&pBAEntry
->list
);
386 /* pass this frame up */
387 ANNOUNCE_REORDERING_PACKET(pAd
, mpdu_blk
);
389 ba_mpdu_blk_free(pAd
, mpdu_blk
);
396 NdisReleaseSpinLock(&pBAEntry
->RxReRingLock
);
400 static void ba_refresh_reordering_mpdus(
401 IN PRTMP_ADAPTER pAd
,
402 PBA_REC_ENTRY pBAEntry
)
404 struct reordering_mpdu
*mpdu_blk
;
406 NdisAcquireSpinLock(&pBAEntry
->RxReRingLock
);
408 /* dequeue in-order frame from reodering list */
409 while ((mpdu_blk
= ba_reordering_mpdu_dequeue(&pBAEntry
->list
)))
411 /* pass this frame up */
412 ANNOUNCE_REORDERING_PACKET(pAd
, mpdu_blk
);
414 pBAEntry
->LastIndSeq
= mpdu_blk
->Sequence
;
415 ba_mpdu_blk_free(pAd
, mpdu_blk
);
417 /* update last indicated sequence */
419 ASSERT(pBAEntry
->list
.qlen
== 0);
420 pBAEntry
->LastIndSeq
= RESET_RCV_SEQ
;
421 NdisReleaseSpinLock(&pBAEntry
->RxReRingLock
);
426 void ba_flush_reordering_timeout_mpdus(
427 IN PRTMP_ADAPTER pAd
,
428 IN PBA_REC_ENTRY pBAEntry
,
434 // if ((RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+REORDERING_PACKET_TIMEOUT)) &&
435 // (pBAEntry->list.qlen > ((pBAEntry->BAWinSize*7)/8))) //||
436 // (RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+(10*REORDERING_PACKET_TIMEOUT))) &&
437 // (pBAEntry->list.qlen > (pBAEntry->BAWinSize/8)))
438 if (RTMP_TIME_AFTER((unsigned long)Now32
, (unsigned long)(pBAEntry
->LastIndSeqAtTimer
+(MAX_REORDERING_PACKET_TIMEOUT
/6)))
439 &&(pBAEntry
->list
.qlen
> 1)
442 DBGPRINT(RT_DEBUG_TRACE
,("timeout[%d] (%08lx-%08lx = %d > %d): %x, flush all!\n ", pBAEntry
->list
.qlen
, Now32
, (pBAEntry
->LastIndSeqAtTimer
),
443 (int)((long) Now32
- (long)(pBAEntry
->LastIndSeqAtTimer
)), MAX_REORDERING_PACKET_TIMEOUT
,
444 pBAEntry
->LastIndSeq
));
445 ba_refresh_reordering_mpdus(pAd
, pBAEntry
);
446 pBAEntry
->LastIndSeqAtTimer
= Now32
;
449 if (RTMP_TIME_AFTER((unsigned long)Now32
, (unsigned long)(pBAEntry
->LastIndSeqAtTimer
+(REORDERING_PACKET_TIMEOUT
)))
450 && (pBAEntry
->list
.qlen
> 0)
454 // force LastIndSeq to shift to LastIndSeq+1
456 Sequence
= (pBAEntry
->LastIndSeq
+1) & MAXSEQ
;
457 ba_indicate_reordering_mpdus_le_seq(pAd
, pBAEntry
, Sequence
);
458 pBAEntry
->LastIndSeqAtTimer
= Now32
;
459 pBAEntry
->LastIndSeq
= Sequence
;
461 // indicate in-order mpdus
463 Sequence
= ba_indicate_reordering_mpdus_in_order(pAd
, pBAEntry
, Sequence
);
464 if (Sequence
!= RESET_RCV_SEQ
)
466 pBAEntry
->LastIndSeq
= Sequence
;
472 (RTMP_TIME_AFTER((unsigned long)Now32
, (unsigned long)(pBAEntry
->LastIndSeqAtTimer
+(MAX_REORDERING_PACKET_TIMEOUT
))) &&
473 (pBAEntry
->list
.qlen
> 1))
476 DBGPRINT(RT_DEBUG_TRACE
,("timeout[%d] (%lx-%lx = %d > %d): %x\n ", pBAEntry
->list
.qlen
, Now32
, (pBAEntry
->LastIndSeqAtTimer
),
477 (int)((long) Now32
- (long)(pBAEntry
->LastIndSeqAtTimer
)), MAX_REORDERING_PACKET_TIMEOUT
,
478 pBAEntry
->LastIndSeq
));
479 ba_refresh_reordering_mpdus(pAd
, pBAEntry
);
480 pBAEntry
->LastIndSeqAtTimer
= Now32
;
487 * generate ADDBA request to
488 * set up BA agreement
490 VOID
BAOriSessionSetUp(
491 IN PRTMP_ADAPTER pAd
,
492 IN MAC_TABLE_ENTRY
*pEntry
,
499 //MLME_ADDBA_REQ_STRUCT AddbaReq;
500 BA_ORI_ENTRY
*pBAEntry
= NULL
;
504 if ((pAd
->CommonCfg
.BACapability
.field
.AutoBA
!= TRUE
) && (isForced
== FALSE
))
507 // if this entry is limited to use legacy tx mode, it doesn't generate BA.
508 if (RTMPStaFixedTxMode(pAd
, pEntry
) != FIXED_TXMODE_HT
)
511 if ((pEntry
->BADeclineBitmap
& (1<<TID
)) && (isForced
== FALSE
))
513 // try again after 3 secs
515 // printk("DeCline BA from Peer\n");
520 Idx
= pEntry
->BAOriWcidArray
[TID
];
523 // allocate a BA session
524 pBAEntry
= BATableAllocOriEntry(pAd
, &Idx
);
525 if (pBAEntry
== NULL
)
527 DBGPRINT(RT_DEBUG_TRACE
,("ADDBA - MlmeADDBAAction() allocate BA session failed \n"));
533 pBAEntry
=&pAd
->BATable
.BAOriEntry
[Idx
];
536 if (pBAEntry
->ORI_BA_Status
>= Originator_WaitRes
)
541 pEntry
->BAOriWcidArray
[TID
] = Idx
;
543 // Initialize BA session
544 pBAEntry
->ORI_BA_Status
= Originator_WaitRes
;
545 pBAEntry
->Wcid
= pEntry
->Aid
;
546 pBAEntry
->BAWinSize
= pAd
->CommonCfg
.BACapability
.field
.RxBAWinLimit
;
547 pBAEntry
->Sequence
= BA_ORI_INIT_SEQ
;
548 pBAEntry
->Token
= 1; // (2008-01-21) Jan Lee recommends it - this token can't be 0
550 pBAEntry
->TimeOutValue
= TimeOut
;
551 pBAEntry
->pAdapter
= pAd
;
553 if (!(pEntry
->TXBAbitmap
& (1<<TID
)))
555 RTMPInitTimer(pAd
, &pBAEntry
->ORIBATimer
, GET_TIMER_FUNCTION(BAOriSessionSetupTimeout
), pBAEntry
, FALSE
);
558 RTMPCancelTimer(&pBAEntry
->ORIBATimer
, &Cancelled
);
560 // set timer to send ADDBA request
561 RTMPSetTimer(&pBAEntry
->ORIBATimer
, DelayTime
);
564 VOID
BAOriSessionAdd(
565 IN PRTMP_ADAPTER pAd
,
566 IN MAC_TABLE_ENTRY
*pEntry
,
567 IN PFRAME_ADDBA_RSP pFrame
)
569 BA_ORI_ENTRY
*pBAEntry
= NULL
;
573 PUCHAR pOutBuffer2
= NULL
;
578 TID
= pFrame
->BaParm
.TID
;
579 Idx
= pEntry
->BAOriWcidArray
[TID
];
580 pBAEntry
=&pAd
->BATable
.BAOriEntry
[Idx
];
582 // Start fill in parameters.
583 if ((Idx
!=0) && (pBAEntry
->TID
== TID
) && (pBAEntry
->ORI_BA_Status
== Originator_WaitRes
))
585 pBAEntry
->BAWinSize
= min(pBAEntry
->BAWinSize
, ((UCHAR
)pFrame
->BaParm
.BufSize
));
586 BA_MaxWinSizeReasign(pAd
, pEntry
, &pBAEntry
->BAWinSize
);
588 pBAEntry
->TimeOutValue
= pFrame
->TimeOutValue
;
589 pBAEntry
->ORI_BA_Status
= Originator_Done
;
590 // reset sequence number
591 pBAEntry
->Sequence
= BA_ORI_INIT_SEQ
;
593 pEntry
->TXBAbitmap
|= (1<<TID
);
594 RTMPCancelTimer(&pBAEntry
->ORIBATimer
, &Cancelled
);
596 pBAEntry
->ORIBATimer
.TimerValue
= 0; //pFrame->TimeOutValue;
598 DBGPRINT(RT_DEBUG_TRACE
,("%s : TXBAbitmap = %x, BAWinSize = %d, TimeOut = %ld\n", __FUNCTION__
, pEntry
->TXBAbitmap
,
599 pBAEntry
->BAWinSize
, pBAEntry
->ORIBATimer
.TimerValue
));
602 NStatus
= MlmeAllocateMemory(pAd
, &pOutBuffer2
); //Get an unused nonpaged memory
603 if (NStatus
!= NDIS_STATUS_SUCCESS
)
605 DBGPRINT(RT_DEBUG_TRACE
,("BA - BAOriSessionAdd() allocate memory failed \n"));
610 #ifdef CONFIG_STA_SUPPORT
611 IF_DEV_CONFIG_OPMODE_ON_STA(pAd
)
612 BarHeaderInit(pAd
, &FrameBar
, pAd
->MacTab
.Content
[pBAEntry
->Wcid
].Addr
, pAd
->CurrentAddress
);
613 #endif // CONFIG_STA_SUPPORT //
615 FrameBar
.StartingSeq
.field
.FragNum
= 0; // make sure sequence not clear in DEL function.
616 FrameBar
.StartingSeq
.field
.StartSeq
= pBAEntry
->Sequence
; // make sure sequence not clear in DEL funciton.
617 FrameBar
.BarControl
.TID
= pBAEntry
->TID
; // make sure sequence not clear in DEL funciton.
618 MakeOutgoingFrame(pOutBuffer2
, &FrameLen
,
619 sizeof(FRAME_BAR
), &FrameBar
,
621 MiniportMMRequest(pAd
, QID_AC_BE
, pOutBuffer2
, FrameLen
);
622 MlmeFreeMemory(pAd
, pOutBuffer2
);
625 if (pBAEntry
->ORIBATimer
.TimerValue
)
626 RTMPSetTimer(&pBAEntry
->ORIBATimer
, pBAEntry
->ORIBATimer
.TimerValue
); // in mSec
630 BOOLEAN
BARecSessionAdd(
631 IN PRTMP_ADAPTER pAd
,
632 IN MAC_TABLE_ENTRY
*pEntry
,
633 IN PFRAME_ADDBA_REQ pFrame
)
635 BA_REC_ENTRY
*pBAEntry
= NULL
;
636 BOOLEAN Status
= TRUE
;
648 TID
= pFrame
->BaParm
.TID
;
650 BAWinSize
= min(((UCHAR
)pFrame
->BaParm
.BufSize
), (UCHAR
)pAd
->CommonCfg
.BACapability
.field
.RxBAWinLimit
);
658 Idx
= pEntry
->BARecWcidArray
[TID
];
663 pBAEntry
= BATableAllocRecEntry(pAd
, &Idx
);
667 pBAEntry
= &pAd
->BATable
.BARecEntry
[Idx
];
668 // flush all pending reordering mpdus
669 ba_refresh_reordering_mpdus(pAd
, pBAEntry
);
672 DBGPRINT(RT_DEBUG_TRACE
,("%s(%ld): Idx = %d, BAWinSize(req %d) = %d\n", __FUNCTION__
, pAd
->BATable
.numAsRecipient
, Idx
,
673 pFrame
->BaParm
.BufSize
, BAWinSize
));
675 // Start fill in parameters.
676 if (pBAEntry
!= NULL
)
678 ASSERT(pBAEntry
->list
.qlen
== 0);
680 pBAEntry
->REC_BA_Status
= Recipient_HandleRes
;
681 pBAEntry
->BAWinSize
= BAWinSize
;
682 pBAEntry
->Wcid
= pEntry
->Aid
;
684 pBAEntry
->TimeOutValue
= pFrame
->TimeOutValue
;
685 pBAEntry
->REC_BA_Status
= Recipient_Accept
;
686 // initial sequence number
687 pBAEntry
->LastIndSeq
= RESET_RCV_SEQ
; //pFrame->BaStartSeq.field.StartSeq;
689 printk("Start Seq = %08x\n", pFrame
->BaStartSeq
.field
.StartSeq
);
691 if (pEntry
->RXBAbitmap
& (1<<TID
))
693 RTMPCancelTimer(&pBAEntry
->RECBATimer
, &Cancelled
);
697 RTMPInitTimer(pAd
, &pBAEntry
->RECBATimer
, GET_TIMER_FUNCTION(BARecSessionIdleTimeout
), pBAEntry
, TRUE
);
700 #if 0 // for debugging
701 RTMPSetTimer(&pBAEntry
->RECBATimer
, REC_BA_SESSION_IDLE_TIMEOUT
);
705 pEntry
->RXBAbitmap
|= (1<<TID
);
706 pEntry
->BARecWcidArray
[TID
] = Idx
;
708 pEntry
->BADeclineBitmap
&= ~(1<<TID
);
710 // Set BA session mask in WCID table.
711 RT28XX_ADD_BA_SESSION_TO_ASIC(pAd
, pEntry
->Aid
, TID
);
713 DBGPRINT(RT_DEBUG_TRACE
,("MACEntry[%d]RXBAbitmap = 0x%x. BARecWcidArray=%d\n",
714 pEntry
->Aid
, pEntry
->RXBAbitmap
, pEntry
->BARecWcidArray
[TID
]));
719 DBGPRINT(RT_DEBUG_TRACE
,("Can't Accept ADDBA for %02x:%02x:%02x:%02x:%02x:%02x TID = %d\n",
720 PRINT_MAC(pEntry
->Addr
), TID
));
726 BA_REC_ENTRY
*BATableAllocRecEntry(
727 IN PRTMP_ADAPTER pAd
,
731 BA_REC_ENTRY
*pBAEntry
= NULL
;
734 NdisAcquireSpinLock(&pAd
->BATabLock
);
736 if (pAd
->BATable
.numAsRecipient
>= MAX_BARECI_SESSION
)
738 printk("BA Recipeint Session (%ld) > %d\n", pAd
->BATable
.numAsRecipient
,
743 // reserve idx 0 to identify BAWcidArray[TID] as empty
744 for (i
=1; i
< MAX_LEN_OF_BA_REC_TABLE
; i
++)
746 pBAEntry
=&pAd
->BATable
.BARecEntry
[i
];
747 if ((pBAEntry
->REC_BA_Status
== Recipient_NONE
))
750 pAd
->BATable
.numAsRecipient
++;
751 pBAEntry
->REC_BA_Status
= Recipient_USED
;
758 NdisReleaseSpinLock(&pAd
->BATabLock
);
762 BA_ORI_ENTRY
*BATableAllocOriEntry(
763 IN PRTMP_ADAPTER pAd
,
767 BA_ORI_ENTRY
*pBAEntry
= NULL
;
769 NdisAcquireSpinLock(&pAd
->BATabLock
);
771 if (pAd
->BATable
.numAsOriginator
>= (MAX_LEN_OF_BA_ORI_TABLE
))
776 // reserve idx 0 to identify BAWcidArray[TID] as empty
777 for (i
=1; i
<MAX_LEN_OF_BA_ORI_TABLE
; i
++)
779 pBAEntry
=&pAd
->BATable
.BAOriEntry
[i
];
780 if ((pBAEntry
->ORI_BA_Status
== Originator_NONE
))
783 pAd
->BATable
.numAsOriginator
++;
784 pBAEntry
->ORI_BA_Status
= Originator_USED
;
785 pBAEntry
->pAdapter
= pAd
;
792 NdisReleaseSpinLock(&pAd
->BATabLock
);
797 VOID
BATableFreeOriEntry(
798 IN PRTMP_ADAPTER pAd
,
801 BA_ORI_ENTRY
*pBAEntry
= NULL
;
802 MAC_TABLE_ENTRY
*pEntry
;
805 if ((Idx
== 0) || (Idx
>= MAX_LEN_OF_BA_ORI_TABLE
))
808 pBAEntry
=&pAd
->BATable
.BAOriEntry
[Idx
];
810 if (pBAEntry
->ORI_BA_Status
!= Originator_NONE
)
812 pEntry
= &pAd
->MacTab
.Content
[pBAEntry
->Wcid
];
813 pEntry
->BAOriWcidArray
[pBAEntry
->TID
] = 0;
816 NdisAcquireSpinLock(&pAd
->BATabLock
);
817 if (pBAEntry
->ORI_BA_Status
== Originator_Done
)
819 pEntry
->TXBAbitmap
&= (~(1<<(pBAEntry
->TID
) ));
820 DBGPRINT(RT_DEBUG_TRACE
, ("BATableFreeOriEntry numAsOriginator= %ld\n", pAd
->BATable
.numAsRecipient
));
821 // Erase Bitmap flag.
824 ASSERT(pAd
->BATable
.numAsOriginator
!= 0);
826 pAd
->BATable
.numAsOriginator
-= 1;
828 pBAEntry
->ORI_BA_Status
= Originator_NONE
;
830 NdisReleaseSpinLock(&pAd
->BATabLock
);
835 VOID
BATableFreeRecEntry(
836 IN PRTMP_ADAPTER pAd
,
839 BA_REC_ENTRY
*pBAEntry
= NULL
;
840 MAC_TABLE_ENTRY
*pEntry
;
843 if ((Idx
== 0) || (Idx
>= MAX_LEN_OF_BA_REC_TABLE
))
846 pBAEntry
=&pAd
->BATable
.BARecEntry
[Idx
];
848 if (pBAEntry
->REC_BA_Status
!= Recipient_NONE
)
850 pEntry
= &pAd
->MacTab
.Content
[pBAEntry
->Wcid
];
851 pEntry
->BARecWcidArray
[pBAEntry
->TID
] = 0;
853 NdisAcquireSpinLock(&pAd
->BATabLock
);
855 ASSERT(pAd
->BATable
.numAsRecipient
!= 0);
857 pAd
->BATable
.numAsRecipient
-= 1;
859 pBAEntry
->REC_BA_Status
= Recipient_NONE
;
860 NdisReleaseSpinLock(&pAd
->BATabLock
);
865 VOID
BAOriSessionTearDown(
866 IN OUT PRTMP_ADAPTER pAd
,
870 IN BOOLEAN bForceSend
)
873 BA_ORI_ENTRY
*pBAEntry
;
876 if (Wcid
>= MAX_LEN_OF_MAC_TABLE
)
882 // Locate corresponding BA Originator Entry in BA Table with the (pAddr,TID).
884 Idx
= pAd
->MacTab
.Content
[Wcid
].BAOriWcidArray
[TID
];
885 if ((Idx
== 0) || (Idx
>= MAX_LEN_OF_BA_ORI_TABLE
))
887 if (bForceSend
== TRUE
)
889 // force send specified TID DelBA
890 MLME_DELBA_REQ_STRUCT DelbaReq
;
891 MLME_QUEUE_ELEM
*Elem
= (MLME_QUEUE_ELEM
*) kmalloc(sizeof(MLME_QUEUE_ELEM
), MEM_ALLOC_FLAG
);
893 NdisZeroMemory(&DelbaReq
, sizeof(DelbaReq
));
894 NdisZeroMemory(Elem
, sizeof(MLME_QUEUE_ELEM
));
896 COPY_MAC_ADDR(DelbaReq
.Addr
, pAd
->MacTab
.Content
[Wcid
].Addr
);
897 DelbaReq
.Wcid
= Wcid
;
899 DelbaReq
.Initiator
= ORIGINATOR
;
901 Elem
->MsgLen
= sizeof(DelbaReq
);
902 NdisMoveMemory(Elem
->Msg
, &DelbaReq
, sizeof(DelbaReq
));
903 MlmeDELBAAction(pAd
, Elem
);
906 MlmeEnqueue(pAd
, ACTION_STATE_MACHINE
, MT2_MLME_ORI_DELBA_CATE
, sizeof(MLME_DELBA_REQ_STRUCT
), (PVOID
)&DelbaReq
);
907 RT28XX_MLME_HANDLER(pAd
);
914 DBGPRINT(RT_DEBUG_TRACE
,("%s===>Wcid=%d.TID=%d \n", __FUNCTION__
, Wcid
, TID
));
916 pBAEntry
= &pAd
->BATable
.BAOriEntry
[Idx
];
917 DBGPRINT(RT_DEBUG_TRACE
,("\t===>Idx = %ld, Wcid=%d.TID=%d, ORI_BA_Status = %d \n", Idx
, Wcid
, TID
, pBAEntry
->ORI_BA_Status
));
919 // Prepare DelBA action frame and send to the peer.
921 if ((bPassive
== FALSE
) && (TID
== pBAEntry
->TID
) && (pBAEntry
->ORI_BA_Status
== Originator_Done
))
923 MLME_DELBA_REQ_STRUCT DelbaReq
;
924 MLME_QUEUE_ELEM
*Elem
= (MLME_QUEUE_ELEM
*) kmalloc(sizeof(MLME_QUEUE_ELEM
), MEM_ALLOC_FLAG
);
926 NdisZeroMemory(&DelbaReq
, sizeof(DelbaReq
));
927 NdisZeroMemory(Elem
, sizeof(MLME_QUEUE_ELEM
));
929 COPY_MAC_ADDR(DelbaReq
.Addr
, pAd
->MacTab
.Content
[Wcid
].Addr
);
930 DelbaReq
.Wcid
= Wcid
;
931 DelbaReq
.TID
= pBAEntry
->TID
;
932 DelbaReq
.Initiator
= ORIGINATOR
;
934 Elem
->MsgLen
= sizeof(DelbaReq
);
935 NdisMoveMemory(Elem
->Msg
, &DelbaReq
, sizeof(DelbaReq
));
936 MlmeDELBAAction(pAd
, Elem
);
939 MlmeEnqueue(pAd
, ACTION_STATE_MACHINE
, MT2_MLME_ORI_DELBA_CATE
, sizeof(MLME_DELBA_REQ_STRUCT
), (PVOID
)&DelbaReq
);
940 RT28XX_MLME_HANDLER(pAd
);
943 RTMPCancelTimer(&pBAEntry
->ORIBATimer
, &Cancelled
);
944 BATableFreeOriEntry(pAd
, Idx
);
948 //BAOriSessionSetUp(pAd, &pAd->MacTab.Content[Wcid], TID, 0, 10000, TRUE);
952 VOID
BARecSessionTearDown(
953 IN OUT PRTMP_ADAPTER pAd
,
959 BA_REC_ENTRY
*pBAEntry
;
961 if (Wcid
>= MAX_LEN_OF_MAC_TABLE
)
967 // Locate corresponding BA Originator Entry in BA Table with the (pAddr,TID).
969 Idx
= pAd
->MacTab
.Content
[Wcid
].BARecWcidArray
[TID
];
973 DBGPRINT(RT_DEBUG_TRACE
,("%s===>Wcid=%d.TID=%d \n", __FUNCTION__
, Wcid
, TID
));
976 pBAEntry
= &pAd
->BATable
.BARecEntry
[Idx
];
977 DBGPRINT(RT_DEBUG_TRACE
,("\t===>Idx = %ld, Wcid=%d.TID=%d, REC_BA_Status = %d \n", Idx
, Wcid
, TID
, pBAEntry
->REC_BA_Status
));
979 // Prepare DelBA action frame and send to the peer.
981 if ((TID
== pBAEntry
->TID
) && (pBAEntry
->REC_BA_Status
== Recipient_Accept
))
983 MLME_DELBA_REQ_STRUCT DelbaReq
;
985 MLME_QUEUE_ELEM
*Elem
= (MLME_QUEUE_ELEM
*) kmalloc(sizeof(MLME_QUEUE_ELEM
), MEM_ALLOC_FLAG
);
989 RTMPCancelTimer(&pBAEntry
->RECBATimer
, &Cancelled
);
992 // 1. Send DELBA Action Frame
994 if (bPassive
== FALSE
)
996 NdisZeroMemory(&DelbaReq
, sizeof(DelbaReq
));
997 NdisZeroMemory(Elem
, sizeof(MLME_QUEUE_ELEM
));
999 COPY_MAC_ADDR(DelbaReq
.Addr
, pAd
->MacTab
.Content
[Wcid
].Addr
);
1000 DelbaReq
.Wcid
= Wcid
;
1002 DelbaReq
.Initiator
= RECIPIENT
;
1004 Elem
->MsgLen
= sizeof(DelbaReq
);
1005 NdisMoveMemory(Elem
->Msg
, &DelbaReq
, sizeof(DelbaReq
));
1006 MlmeDELBAAction(pAd
, Elem
);
1009 MlmeEnqueue(pAd
, ACTION_STATE_MACHINE
, MT2_MLME_ORI_DELBA_CATE
, sizeof(MLME_DELBA_REQ_STRUCT
), (PVOID
)&DelbaReq
);
1010 RT28XX_MLME_HANDLER(pAd
);
1016 // 2. Free resource of BA session
1018 // flush all pending reordering mpdus
1019 ba_refresh_reordering_mpdus(pAd
, pBAEntry
);
1021 NdisAcquireSpinLock(&pAd
->BATabLock
);
1023 // Erase Bitmap flag.
1024 pBAEntry
->LastIndSeq
= RESET_RCV_SEQ
;
1025 pBAEntry
->BAWinSize
= 0;
1026 // Erase Bitmap flag at software mactable
1027 pAd
->MacTab
.Content
[Wcid
].RXBAbitmap
&= (~(1<<(pBAEntry
->TID
)));
1028 pAd
->MacTab
.Content
[Wcid
].BARecWcidArray
[TID
] = 0;
1030 RT28XX_DEL_BA_SESSION_FROM_ASIC(pAd
, Wcid
, TID
);
1032 NdisReleaseSpinLock(&pAd
->BATabLock
);
1036 BATableFreeRecEntry(pAd
, Idx
);
1039 VOID
BASessionTearDownALL(
1040 IN OUT PRTMP_ADAPTER pAd
,
1045 for (i
=0; i
<NUM_OF_TID
; i
++)
1047 BAOriSessionTearDown(pAd
, Wcid
, i
, FALSE
, FALSE
);
1048 BARecSessionTearDown(pAd
, Wcid
, i
, FALSE
);
1054 ==========================================================================
1056 Retry sending ADDBA Reqest.
1058 IRQL = DISPATCH_LEVEL
1061 p8023Header: if this is already 802.3 format, p8023Header is NULL
1063 Return : TRUE if put into rx reordering buffer, shouldn't indicaterxhere.
1064 FALSE , then continue indicaterx at this moment.
1065 ==========================================================================
1067 VOID
BAOriSessionSetupTimeout(
1068 IN PVOID SystemSpecific1
,
1069 IN PVOID FunctionContext
,
1070 IN PVOID SystemSpecific2
,
1071 IN PVOID SystemSpecific3
)
1073 BA_ORI_ENTRY
*pBAEntry
= (BA_ORI_ENTRY
*)FunctionContext
;
1074 MAC_TABLE_ENTRY
*pEntry
;
1077 if (pBAEntry
== NULL
)
1080 pAd
= pBAEntry
->pAdapter
;
1082 #ifdef CONFIG_STA_SUPPORT
1083 IF_DEV_CONFIG_OPMODE_ON_STA(pAd
)
1085 // Do nothing if monitor mode is on
1086 if (MONITOR_ON(pAd
))
1089 #endif // CONFIG_STA_SUPPORT //
1092 // Nothing to do in ATE mode.
1095 #endif // RALINK_ATE //
1097 pEntry
= &pAd
->MacTab
.Content
[pBAEntry
->Wcid
];
1099 if ((pBAEntry
->ORI_BA_Status
== Originator_WaitRes
) && (pBAEntry
->Token
< ORI_SESSION_MAX_RETRY
))
1101 MLME_ADDBA_REQ_STRUCT AddbaReq
;
1103 NdisZeroMemory(&AddbaReq
, sizeof(AddbaReq
));
1104 COPY_MAC_ADDR(AddbaReq
.pAddr
, pEntry
->Addr
);
1105 AddbaReq
.Wcid
= (UCHAR
)(pEntry
->Aid
);
1106 AddbaReq
.TID
= pBAEntry
->TID
;
1107 AddbaReq
.BaBufSize
= pAd
->CommonCfg
.BACapability
.field
.RxBAWinLimit
;
1108 AddbaReq
.TimeOutValue
= 0;
1109 AddbaReq
.Token
= pBAEntry
->Token
;
1110 MlmeEnqueue(pAd
, ACTION_STATE_MACHINE
, MT2_MLME_ADD_BA_CATE
, sizeof(MLME_ADDBA_REQ_STRUCT
), (PVOID
)&AddbaReq
);
1111 RT28XX_MLME_HANDLER(pAd
);
1112 DBGPRINT(RT_DEBUG_TRACE
,("BA Ori Session Timeout(%d) : Send ADD BA again\n", pBAEntry
->Token
));
1115 RTMPSetTimer(&pBAEntry
->ORIBATimer
, ORI_BA_SESSION_TIMEOUT
);
1119 BATableFreeOriEntry(pAd
, pEntry
->BAOriWcidArray
[pBAEntry
->TID
]);
1124 ==========================================================================
1126 Retry sending ADDBA Reqest.
1128 IRQL = DISPATCH_LEVEL
1131 p8023Header: if this is already 802.3 format, p8023Header is NULL
1133 Return : TRUE if put into rx reordering buffer, shouldn't indicaterxhere.
1134 FALSE , then continue indicaterx at this moment.
1135 ==========================================================================
1137 VOID
BARecSessionIdleTimeout(
1138 IN PVOID SystemSpecific1
,
1139 IN PVOID FunctionContext
,
1140 IN PVOID SystemSpecific2
,
1141 IN PVOID SystemSpecific3
)
1144 BA_REC_ENTRY
*pBAEntry
= (BA_REC_ENTRY
*)FunctionContext
;
1148 if (pBAEntry
== NULL
)
1151 if ((pBAEntry
->REC_BA_Status
== Recipient_Accept
))
1153 NdisGetSystemUpTime(&Now32
);
1155 if (RTMP_TIME_AFTER((unsigned long)Now32
, (unsigned long)(pBAEntry
->LastIndSeqAtTimer
+ REC_BA_SESSION_IDLE_TIMEOUT
)))
1157 pAd
= pBAEntry
->pAdapter
;
1158 // flush all pending reordering mpdus
1159 ba_refresh_reordering_mpdus(pAd
, pBAEntry
);
1160 printk("%ld: REC BA session Timeout\n", Now32
);
1166 VOID
PeerAddBAReqAction(
1167 IN PRTMP_ADAPTER pAd
,
1168 IN MLME_QUEUE_ELEM
*Elem
)
1175 FRAME_ADDBA_RSP ADDframe
;
1176 PUCHAR pOutBuffer
= NULL
;
1177 NDIS_STATUS NStatus
;
1178 PFRAME_ADDBA_REQ pAddreqFrame
= NULL
;
1182 PMAC_TABLE_ENTRY pMacEntry
;
1184 DBGPRINT(RT_DEBUG_TRACE
, ("%s ==> (Wcid = %d)\n", __FUNCTION__
, Elem
->Wcid
));
1186 //hex_dump("AddBAReq", Elem->Msg, Elem->MsgLen);
1188 //ADDBA Request from unknown peer, ignore this.
1189 if (Elem
->Wcid
>= MAX_LEN_OF_MAC_TABLE
)
1192 pMacEntry
= &pAd
->MacTab
.Content
[Elem
->Wcid
];
1193 DBGPRINT(RT_DEBUG_TRACE
,("BA - PeerAddBAReqAction----> \n"));
1194 ptemp
= (PULONG
)Elem
->Msg
;
1195 //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)));
1197 if (PeerAddBAReqActionSanity(pAd
, Elem
->Msg
, Elem
->MsgLen
, pAddr
))
1200 if ((pAd
->CommonCfg
.bBADecline
== FALSE
) && IS_HT_STA(pMacEntry
))
1202 pAddreqFrame
= (PFRAME_ADDBA_REQ
)(&Elem
->Msg
[0]);
1203 printk("Rcv Wcid(%d) AddBAReq\n", Elem
->Wcid
);
1204 if (BARecSessionAdd(pAd
, &pAd
->MacTab
.Content
[Elem
->Wcid
], pAddreqFrame
))
1207 Status
= 38; // more parameters have invalid values
1211 Status
= 37; // the request has been declined.
1215 if (pAd
->MacTab
.Content
[Elem
->Wcid
].ValidAsCLI
)
1216 ASSERT(pAd
->MacTab
.Content
[Elem
->Wcid
].Sst
== SST_ASSOC
);
1218 pAddreqFrame
= (PFRAME_ADDBA_REQ
)(&Elem
->Msg
[0]);
1219 // 2. Always send back ADDBA Response
1220 NStatus
= MlmeAllocateMemory(pAd
, &pOutBuffer
); //Get an unused nonpaged memory
1221 if (NStatus
!= NDIS_STATUS_SUCCESS
)
1223 DBGPRINT(RT_DEBUG_TRACE
,("ACTION - PeerBAAction() allocate memory failed \n"));
1227 NdisZeroMemory(&ADDframe
, sizeof(FRAME_ADDBA_RSP
));
1228 // 2-1. Prepare ADDBA Response frame.
1229 #ifdef CONFIG_STA_SUPPORT
1230 IF_DEV_CONFIG_OPMODE_ON_STA(pAd
)
1233 ActHeaderInit(pAd
, &ADDframe
.Hdr
, pAddr
, pAd
->CurrentAddress
, pAd
->CommonCfg
.Bssid
);
1235 #ifdef QOS_DLS_SUPPORT
1236 if (pAd
->MacTab
.Content
[Elem
->Wcid
].ValidAsDls
)
1237 ActHeaderInit(pAd
, &ADDframe
.Hdr
, pAddr
, pAd
->CurrentAddress
, pAd
->CommonCfg
.Bssid
);
1239 #endif // QOS_DLS_SUPPORT //
1240 ActHeaderInit(pAd
, &ADDframe
.Hdr
, pAd
->CommonCfg
.Bssid
, pAd
->CurrentAddress
, pAddr
);
1242 #endif // CONFIG_STA_SUPPORT //
1243 ADDframe
.Category
= CATEGORY_BA
;
1244 ADDframe
.Action
= ADDBA_RESP
;
1245 ADDframe
.Token
= pAddreqFrame
->Token
;
1246 // What is the Status code?? need to check.
1247 ADDframe
.StatusCode
= Status
;
1248 ADDframe
.BaParm
.BAPolicy
= IMMED_BA
;
1249 ADDframe
.BaParm
.AMSDUSupported
= 0;
1250 ADDframe
.BaParm
.TID
= pAddreqFrame
->BaParm
.TID
;
1251 ADDframe
.BaParm
.BufSize
= min(((UCHAR
)pAddreqFrame
->BaParm
.BufSize
), (UCHAR
)pAd
->CommonCfg
.BACapability
.field
.RxBAWinLimit
);
1252 if (ADDframe
.BaParm
.BufSize
== 0)
1254 ADDframe
.BaParm
.BufSize
= 64;
1256 ADDframe
.TimeOutValue
= 0; //pAddreqFrame->TimeOutValue;
1258 *(USHORT
*)(&ADDframe
.BaParm
) = cpu2le16(*(USHORT
*)(&ADDframe
.BaParm
));
1259 ADDframe
.StatusCode
= cpu2le16(ADDframe
.StatusCode
);
1260 ADDframe
.TimeOutValue
= cpu2le16(ADDframe
.TimeOutValue
);
1262 MakeOutgoingFrame(pOutBuffer
, &FrameLen
,
1263 sizeof(FRAME_ADDBA_RSP
), &ADDframe
,
1265 MiniportMMRequest(pAd
, QID_AC_BE
, pOutBuffer
, FrameLen
);
1266 MlmeFreeMemory(pAd
, pOutBuffer
);
1268 DBGPRINT(RT_DEBUG_TRACE
, ("%s(%d): TID(%d), BufSize(%d) <== \n", __FUNCTION__
, Elem
->Wcid
, ADDframe
.BaParm
.TID
,
1269 ADDframe
.BaParm
.BufSize
));
1273 VOID
PeerAddBARspAction(
1274 IN PRTMP_ADAPTER pAd
,
1275 IN MLME_QUEUE_ELEM
*Elem
)
1279 //PUCHAR pOutBuffer = NULL;
1280 PFRAME_ADDBA_RSP pFrame
= NULL
;
1281 //PBA_ORI_ENTRY pBAEntry;
1283 //ADDBA Response from unknown peer, ignore this.
1284 if (Elem
->Wcid
>= MAX_LEN_OF_MAC_TABLE
)
1287 DBGPRINT(RT_DEBUG_TRACE
, ("%s ==> Wcid(%d)\n", __FUNCTION__
, Elem
->Wcid
));
1289 //hex_dump("PeerAddBARspAction()", Elem->Msg, Elem->MsgLen);
1291 if (PeerAddBARspActionSanity(pAd
, Elem
->Msg
, Elem
->MsgLen
))
1293 pFrame
= (PFRAME_ADDBA_RSP
)(&Elem
->Msg
[0]);
1295 DBGPRINT(RT_DEBUG_TRACE
, ("\t\t StatusCode = %d\n", pFrame
->StatusCode
));
1296 switch (pFrame
->StatusCode
)
1299 // I want a BAsession with this peer as an originator.
1300 BAOriSessionAdd(pAd
, &pAd
->MacTab
.Content
[Elem
->Wcid
], pFrame
);
1303 // check status == USED ???
1304 BAOriSessionTearDown(pAd
, Elem
->Wcid
, pFrame
->BaParm
.TID
, TRUE
, FALSE
);
1307 // Rcv Decline StatusCode
1308 if ((pFrame
->StatusCode
== 37)
1309 #ifdef CONFIG_STA_SUPPORT
1310 || ((pAd
->OpMode
== OPMODE_STA
) && STA_TGN_WIFI_ON(pAd
) && (pFrame
->StatusCode
!= 0))
1311 #endif // CONFIG_STA_SUPPORT //
1314 pAd
->MacTab
.Content
[Elem
->Wcid
].BADeclineBitmap
|= 1<<pFrame
->BaParm
.TID
;
1319 VOID
PeerDelBAAction(
1320 IN PRTMP_ADAPTER pAd
,
1321 IN MLME_QUEUE_ELEM
*Elem
)
1325 //PUCHAR pOutBuffer = NULL;
1326 PFRAME_DELBA_REQ pDelFrame
= NULL
;
1328 DBGPRINT(RT_DEBUG_TRACE
,("%s ==>\n", __FUNCTION__
));
1329 //DELBA Request from unknown peer, ignore this.
1330 if (PeerDelBAActionSanity(pAd
, Elem
->Wcid
, Elem
->Msg
, Elem
->MsgLen
))
1332 pDelFrame
= (PFRAME_DELBA_REQ
)(&Elem
->Msg
[0]);
1333 if (pDelFrame
->DelbaParm
.Initiator
== ORIGINATOR
)
1335 DBGPRINT(RT_DEBUG_TRACE
,("BA - PeerDelBAAction----> ORIGINATOR\n"));
1336 BARecSessionTearDown(pAd
, Elem
->Wcid
, pDelFrame
->DelbaParm
.TID
, TRUE
);
1340 DBGPRINT(RT_DEBUG_TRACE
,("BA - PeerDelBAAction----> RECIPIENT, Reason = %d\n", pDelFrame
->ReasonCode
));
1341 //hex_dump("DelBA Frame", pDelFrame, Elem->MsgLen);
1342 BAOriSessionTearDown(pAd
, Elem
->Wcid
, pDelFrame
->DelbaParm
.TID
, TRUE
, FALSE
);
1348 BOOLEAN
CntlEnqueueForRecv(
1349 IN PRTMP_ADAPTER pAd
,
1352 IN PFRAME_BA_REQ pMsg
)
1354 PFRAME_BA_REQ pFrame
= pMsg
;
1355 //PRTMP_REORDERBUF pBuffer;
1356 //PRTMP_REORDERBUF pDmaBuf;
1357 PBA_REC_ENTRY pBAEntry
;
1363 TID
= (UCHAR
)pFrame
->BARControl
.TID
;
1365 DBGPRINT(RT_DEBUG_TRACE
, ("%s(): BAR-Wcid(%ld), Tid (%d)\n", __FUNCTION__
, Wcid
, TID
));
1366 //hex_dump("BAR", (PCHAR) pFrame, MsgLen);
1367 // Do nothing if the driver is starting halt state.
1368 // This might happen when timer already been fired before cancel timer with mlmehalt
1369 if (RTMP_TEST_FLAG(pAd
, fRTMP_ADAPTER_HALT_IN_PROGRESS
| fRTMP_ADAPTER_NIC_NOT_EXIST
))
1372 // First check the size, it MUST not exceed the mlme queue size
1373 if (MsgLen
> MGMT_DMA_BUFFER_SIZE
)
1375 DBGPRINT_ERR(("CntlEnqueueForRecv: frame too large, size = %ld \n", MsgLen
));
1378 else if (MsgLen
!= sizeof(FRAME_BA_REQ
))
1380 DBGPRINT_ERR(("CntlEnqueueForRecv: BlockAck Request frame length size = %ld incorrect\n", MsgLen
));
1383 else if (MsgLen
!= sizeof(FRAME_BA_REQ
))
1385 DBGPRINT_ERR(("CntlEnqueueForRecv: BlockAck Request frame length size = %ld incorrect\n", MsgLen
));
1389 if ((Wcid
< MAX_LEN_OF_MAC_TABLE
) && (TID
< 8))
1391 // if this receiving packet is from SA that is in our OriEntry. Since WCID <9 has direct mapping. no need search.
1392 Idx
= pAd
->MacTab
.Content
[Wcid
].BARecWcidArray
[TID
];
1393 pBAEntry
= &pAd
->BATable
.BARecEntry
[Idx
];
1400 DBGPRINT(RT_DEBUG_TRACE
, ("BAR(%ld) : Tid (%d) - %04x:%04x\n", Wcid
, TID
, pFrame
->BAStartingSeq
.field
.StartSeq
, pBAEntry
->LastIndSeq
));
1402 if (SEQ_SMALLER(pBAEntry
->LastIndSeq
, pFrame
->BAStartingSeq
.field
.StartSeq
, MAXSEQ
))
1404 //printk("BAR Seq = %x, LastIndSeq = %x\n", pFrame->BAStartingSeq.field.StartSeq, pBAEntry->LastIndSeq);
1405 ba_indicate_reordering_mpdus_le_seq(pAd
, pBAEntry
, pFrame
->BAStartingSeq
.field
.StartSeq
);
1406 pBAEntry
->LastIndSeq
= (pFrame
->BAStartingSeq
.field
.StartSeq
== 0) ? MAXSEQ
:(pFrame
->BAStartingSeq
.field
.StartSeq
-1);
1408 //ba_refresh_reordering_mpdus(pAd, pBAEntry);
1413 Description : Send PSMP Action frame If PSMP mode switches.
1415 VOID
SendPSMPAction(
1416 IN PRTMP_ADAPTER pAd
,
1420 PUCHAR pOutBuffer
= NULL
;
1421 NDIS_STATUS NStatus
;
1423 FRAME_PSMP_ACTION Frame
;
1426 NStatus
= MlmeAllocateMemory(pAd
, &pOutBuffer
); //Get an unused nonpaged memory
1427 if (NStatus
!= NDIS_STATUS_SUCCESS
)
1429 DBGPRINT(RT_DEBUG_ERROR
,("BA - MlmeADDBAAction() allocate memory failed \n"));
1432 #ifdef CONFIG_STA_SUPPORT
1433 IF_DEV_CONFIG_OPMODE_ON_STA(pAd
)
1434 ActHeaderInit(pAd
, &Frame
.Hdr
, pAd
->CommonCfg
.Bssid
, pAd
->CurrentAddress
, pAd
->MacTab
.Content
[Wcid
].Addr
);
1435 #endif // CONFIG_STA_SUPPORT //
1437 Frame
.Category
= CATEGORY_HT
;
1438 Frame
.Action
= SMPS_ACTION
;
1451 MakeOutgoingFrame(pOutBuffer
, &FrameLen
,
1452 sizeof(FRAME_PSMP_ACTION
), &Frame
,
1454 MiniportMMRequest(pAd
, QID_AC_BE
, pOutBuffer
, FrameLen
);
1455 MlmeFreeMemory(pAd
, pOutBuffer
);
1456 DBGPRINT(RT_DEBUG_ERROR
,("HT - SendPSMPAction( %d ) \n", Frame
.Psmp
));
1460 #define RADIO_MEASUREMENT_REQUEST_ACTION 0
1462 typedef struct PACKED
1464 UCHAR RegulatoryClass
;
1465 UCHAR ChannelNumber
;
1466 USHORT RandomInterval
;
1467 USHORT MeasurementDuration
;
1468 UCHAR MeasurementMode
;
1469 UCHAR BSSID
[MAC_ADDR_LEN
];
1470 UCHAR ReportingCondition
;
1472 UCHAR SSIDIE
[2]; // 2 byte
1475 typedef struct PACKED
1487 void convert_reordering_packet_to_preAMSDU_or_802_3_packet(
1488 IN PRTMP_ADAPTER pAd
,
1490 IN UCHAR FromWhichBSSID
)
1492 PNDIS_PACKET pRxPkt
;
1493 UCHAR Header802_3
[LENGTH_802_3
];
1495 // 1. get 802.3 Header
1497 // a. pointer pRxBlk->pData to payload
1498 // b. modify pRxBlk->DataSize
1500 #ifdef CONFIG_STA_SUPPORT
1501 IF_DEV_CONFIG_OPMODE_ON_STA(pAd
)
1502 RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk
, Header802_3
);
1503 #endif // CONFIG_STA_SUPPORT //
1505 ASSERT(pRxBlk
->pRxPacket
);
1506 pRxPkt
= RTPKT_TO_OSPKT(pRxBlk
->pRxPacket
);
1508 RTPKT_TO_OSPKT(pRxPkt
)->dev
= get_netdev_from_bssid(pAd
, FromWhichBSSID
);
1509 RTPKT_TO_OSPKT(pRxPkt
)->data
= pRxBlk
->pData
;
1510 RTPKT_TO_OSPKT(pRxPkt
)->len
= pRxBlk
->DataSize
;
1511 RTPKT_TO_OSPKT(pRxPkt
)->tail
= RTPKT_TO_OSPKT(pRxPkt
)->data
+ RTPKT_TO_OSPKT(pRxPkt
)->len
;
1514 // copy 802.3 header, if necessary
1516 if (!RX_BLK_TEST_FLAG(pRxBlk
, fRX_AMSDU
))
1519 #ifdef CONFIG_STA_SUPPORT
1520 IF_DEV_CONFIG_OPMODE_ON_STA(pAd
)
1523 NdisMoveMemory(skb_push(pRxPkt
, LENGTH_802_3
), Header802_3
, LENGTH_802_3
);
1526 NdisMoveMemory(net_pkt_push(pRxPkt
, LENGTH_802_3
), Header802_3
, LENGTH_802_3
);
1529 #endif // CONFIG_STA_SUPPORT //
1534 #define INDICATE_LEGACY_OR_AMSDU(_pAd, _pRxBlk, _fromWhichBSSID) \
1537 if (RX_BLK_TEST_FLAG(_pRxBlk, fRX_AMSDU)) \
1539 Indicate_AMSDU_Packet(_pAd, _pRxBlk, _fromWhichBSSID); \
1541 else if (RX_BLK_TEST_FLAG(_pRxBlk, fRX_EAP)) \
1543 Indicate_EAPOL_Packet(_pAd, _pRxBlk, _fromWhichBSSID); \
1547 Indicate_Legacy_Packet(_pAd, _pRxBlk, _fromWhichBSSID); \
1553 static VOID
ba_enqueue_reordering_packet(
1554 IN PRTMP_ADAPTER pAd
,
1555 IN PBA_REC_ENTRY pBAEntry
,
1557 IN UCHAR FromWhichBSSID
)
1559 struct reordering_mpdu
*mpdu_blk
;
1560 UINT16 Sequence
= (UINT16
) pRxBlk
->pHeader
->Sequence
;
1562 mpdu_blk
= ba_mpdu_blk_alloc(pAd
);
1563 if (mpdu_blk
!= NULL
)
1565 // Write RxD buffer address & allocated buffer length
1566 NdisAcquireSpinLock(&pBAEntry
->RxReRingLock
);
1568 mpdu_blk
->Sequence
= Sequence
;
1570 mpdu_blk
->bAMSDU
= RX_BLK_TEST_FLAG(pRxBlk
, fRX_AMSDU
);
1572 convert_reordering_packet_to_preAMSDU_or_802_3_packet(pAd
, pRxBlk
, FromWhichBSSID
);
1574 STATS_INC_RX_PACKETS(pAd
, FromWhichBSSID
);
1577 // it is necessary for reordering packet to record
1578 // which BSS it come from
1580 RTMP_SET_PACKET_IF(pRxBlk
->pRxPacket
, FromWhichBSSID
);
1582 mpdu_blk
->pPacket
= pRxBlk
->pRxPacket
;
1584 if (ba_reordering_mpdu_insertsorted(&pBAEntry
->list
, mpdu_blk
) == FALSE
)
1586 // had been already within reordering list
1588 RELEASE_NDIS_PACKET(pAd
, pRxBlk
->pRxPacket
, NDIS_STATUS_SUCCESS
);
1589 ba_mpdu_blk_free(pAd
, mpdu_blk
);
1592 ASSERT((0<= pBAEntry
->list
.qlen
) && (pBAEntry
->list
.qlen
<= pBAEntry
->BAWinSize
));
1593 NdisReleaseSpinLock(&pBAEntry
->RxReRingLock
);
1598 DBGPRINT(RT_DEBUG_ERROR
, ("!!! (%d:%d) Can't allocate reordering mpdu blk\n",
1599 blk_count
, pBAEntry
->list
.qlen
));
1601 DBGPRINT(RT_DEBUG_ERROR
, ("!!! (%d) Can't allocate reordering mpdu blk\n",
1602 pBAEntry
->list
.qlen
));
1605 * flush all pending reordering mpdus
1606 * and receving mpdu to upper layer
1607 * make tcp/ip to take care reordering mechanism
1609 //ba_refresh_reordering_mpdus(pAd, pBAEntry);
1610 ba_indicate_reordering_mpdus_le_seq(pAd
, pBAEntry
, Sequence
);
1612 pBAEntry
->LastIndSeq
= Sequence
;
1613 INDICATE_LEGACY_OR_AMSDU(pAd
, pRxBlk
, FromWhichBSSID
);
1619 ==========================================================================
1621 Indicate this packet to upper layer or put it into reordering buffer
1624 pRxBlk : carry necessary packet info 802.11 format
1625 FromWhichBSSID : the packet received from which BSS
1631 the packet queued into reordering buffer need to cover to 802.3 format
1633 ==========================================================================
1636 VOID
Indicate_AMPDU_Packet(
1637 IN PRTMP_ADAPTER pAd
,
1639 IN UCHAR FromWhichBSSID
)
1642 PBA_REC_ENTRY pBAEntry
= NULL
;
1643 UINT16 Sequence
= pRxBlk
->pHeader
->Sequence
;
1645 UCHAR Wcid
= pRxBlk
->pRxWI
->WirelessCliID
;
1646 UCHAR TID
= pRxBlk
->pRxWI
->TID
;
1649 if (!RX_BLK_TEST_FLAG(pRxBlk
, fRX_AMSDU
) && (pRxBlk
->DataSize
> MAX_RX_PKT_LEN
))
1651 #if 0 // sample take off, no use
1652 static int err_size
;
1655 if (err_size
> 20) {
1656 printk("AMPDU DataSize = %d\n", pRxBlk
->DataSize
);
1657 hex_dump("802.11 Header", (UCHAR
*)pRxBlk
->pHeader
, 24);
1658 hex_dump("Payload", pRxBlk
->pData
, 64);
1663 RELEASE_NDIS_PACKET(pAd
, pRxBlk
->pRxPacket
, NDIS_STATUS_FAILURE
);
1669 /* Rec BA Session had been torn down */
1670 INDICATE_LEGACY_OR_AMSDU(pAd
, pRxBlk
, FromWhichBSSID
);
1674 if (Wcid
< MAX_LEN_OF_MAC_TABLE
)
1676 Idx
= pAd
->MacTab
.Content
[Wcid
].BARecWcidArray
[TID
];
1679 /* Rec BA Session had been torn down */
1680 INDICATE_LEGACY_OR_AMSDU(pAd
, pRxBlk
, FromWhichBSSID
);
1683 pBAEntry
= &pAd
->BATable
.BARecEntry
[Idx
];
1690 RELEASE_NDIS_PACKET(pAd
, pRxBlk
->pRxPacket
, NDIS_STATUS_FAILURE
);
1696 // update last rx time
1697 NdisGetSystemUpTime(&Now32
);
1699 pBAEntry
->rcvSeq
= Sequence
;
1702 ba_flush_reordering_timeout_mpdus(pAd
, pBAEntry
, Now32
);
1703 pBAEntry
->LastIndSeqAtTimer
= Now32
;
1706 // Reset Last Indicate Sequence
1708 if (pBAEntry
->LastIndSeq
== RESET_RCV_SEQ
)
1710 ASSERT((pBAEntry
->list
.qlen
== 0) && (pBAEntry
->list
.next
== NULL
));
1712 // reset rcv sequence of BA session
1713 pBAEntry
->LastIndSeq
= Sequence
;
1714 pBAEntry
->LastIndSeqAtTimer
= Now32
;
1715 INDICATE_LEGACY_OR_AMSDU(pAd
, pRxBlk
, FromWhichBSSID
);
1721 // I. Check if in order.
1723 if (SEQ_STEPONE(Sequence
, pBAEntry
->LastIndSeq
, MAXSEQ
))
1727 pBAEntry
->LastIndSeq
= Sequence
;
1728 INDICATE_LEGACY_OR_AMSDU(pAd
, pRxBlk
, FromWhichBSSID
);
1729 LastIndSeq
= ba_indicate_reordering_mpdus_in_order(pAd
, pBAEntry
, pBAEntry
->LastIndSeq
);
1730 if (LastIndSeq
!= RESET_RCV_SEQ
)
1732 pBAEntry
->LastIndSeq
= LastIndSeq
;
1734 pBAEntry
->LastIndSeqAtTimer
= Now32
;
1737 // II. Drop Duplicated Packet
1739 else if (Sequence
== pBAEntry
->LastIndSeq
)
1742 // drop and release packet
1743 pBAEntry
->nDropPacket
++;
1744 RELEASE_NDIS_PACKET(pAd
, pRxBlk
->pRxPacket
, NDIS_STATUS_FAILURE
);
1747 // III. Drop Old Received Packet
1749 else if (SEQ_SMALLER(Sequence
, pBAEntry
->LastIndSeq
, MAXSEQ
))
1752 // drop and release packet
1753 pBAEntry
->nDropPacket
++;
1754 RELEASE_NDIS_PACKET(pAd
, pRxBlk
->pRxPacket
, NDIS_STATUS_FAILURE
);
1757 // IV. Receive Sequence within Window Size
1759 else if (SEQ_SMALLER(Sequence
, (((pBAEntry
->LastIndSeq
+pBAEntry
->BAWinSize
+1)) & MAXSEQ
), MAXSEQ
))
1761 ba_enqueue_reordering_packet(pAd
, pBAEntry
, pRxBlk
, FromWhichBSSID
);
1764 // V. Receive seq surpasses Win(lastseq + nMSDU). So refresh all reorder buffer
1769 ba_refresh_reordering_mpdus(pAd
, pBAEntry
);
1770 INDICATE_LEGACY_OR_AMSDU(pAd
, pRxBlk
, FromWhichBSSID
);
1772 LONG WinStartSeq
, TmpSeq
;
1775 TmpSeq
= Sequence
- (pBAEntry
->BAWinSize
) -1;
1778 TmpSeq
= (MAXSEQ
+1) + TmpSeq
;
1780 WinStartSeq
= (TmpSeq
+1) & MAXSEQ
;
1781 ba_indicate_reordering_mpdus_le_seq(pAd
, pBAEntry
, WinStartSeq
);
1782 pBAEntry
->LastIndSeq
= WinStartSeq
; //TmpSeq;
1784 pBAEntry
->LastIndSeqAtTimer
= Now32
;
1786 ba_enqueue_reordering_packet(pAd
, pBAEntry
, pRxBlk
, FromWhichBSSID
);
1788 TmpSeq
= ba_indicate_reordering_mpdus_in_order(pAd
, pBAEntry
, pBAEntry
->LastIndSeq
);
1789 if (TmpSeq
!= RESET_RCV_SEQ
)
1791 pBAEntry
->LastIndSeq
= TmpSeq
;
1797 #endif // DOT11_N_SUPPORT //