Staging: rt2870: remove dead CONFIG_AP_SUPPORT code
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / staging / rt2870 / common / ba_action.c
blob072f272f672d58dde5076ee3dba8748b10fe5527
1 /*
2 *************************************************************************
3 * Ralink Tech Inc.
4 * 5F., No.36, Taiyuan St., Jhubei City,
5 * Hsinchu County 302,
6 * Taiwan, R.O.C.
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. *
14 * *
15 * This program is distributed in the hope that it will be useful, *
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
18 * GNU General Public License for more details. *
19 * *
20 * You should have received a copy of the GNU General Public License *
21 * along with this program; if not, write to the *
22 * Free Software Foundation, Inc., *
23 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
24 * *
25 *************************************************************************
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(
48 IN PRTMP_ADAPTER pAd,
49 OUT USHORT *Idx);
51 BA_REC_ENTRY *BATableAllocRecEntry(
52 IN PRTMP_ADAPTER pAd,
53 OUT USHORT *Idx);
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(
75 IN PRTMP_ADAPTER pAd,
76 IN MAC_TABLE_ENTRY *pEntryPeer,
77 OUT UCHAR *pWinSize)
79 UCHAR MaxSize;
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
88 else
89 MaxSize = 13;
91 else
92 MaxSize = 31;
94 else if (pAd->MACVersion >= RALINK_2880E_VERSION) // 2880 e
96 if (pEntryPeer->WepStatus != Ndis802_11EncryptionDisabled)
97 MaxSize = 7; // for non-open mode
98 else
99 MaxSize = 13;
101 else
102 MaxSize = 7;
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));
112 *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;
123 if (mpdu->bAMSDU)
125 ASSERT(0);
126 BA_Reorder_AMSDU_Annnounce(pAd, pPacket);
128 else
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 */
155 return(FALSE);
157 else
159 /* find position */
160 break;
164 mpdu->next = *ppScan;
165 *ppScan = mpdu;
166 list->qlen++;
167 return TRUE;
172 * caller lock critical section if necessary
174 static inline void ba_enqueue(struct reordering_list *list, struct reordering_mpdu *mpdu_blk)
176 list->qlen++;
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;
188 ASSERT(list);
190 if (list->qlen)
192 list->qlen--;
193 mpdu_blk = list->next;
194 if (mpdu_blk)
196 list->next = mpdu_blk->next;
197 mpdu_blk->next = NULL;
200 return mpdu_blk;
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)
212 ASSERT(list);
214 return(list->next);
219 * free all resource for reordering mechanism
221 void ba_reordering_resource_release(PRTMP_ADAPTER pAd)
223 BA_TABLE *Tab;
224 PBA_REC_ENTRY pBAEntry;
225 struct reordering_mpdu *mpdu_blk;
226 int i;
228 Tab = &pAd->BATable;
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)
261 int i;
262 PUCHAR mem;
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;
272 freelist->qlen = 0;
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;
281 if (mem == NULL)
283 DBGPRINT(RT_DEBUG_ERROR, ("Can't Allocate Memory for BA Reordering\n"));
284 return(FALSE);
287 /* build mpdu_blk free list */
288 for (i=0; i<num; i++)
290 /* get mpdu_blk */
291 mpdu_blk = (struct reordering_mpdu *) mem;
292 /* initial mpdu_blk */
293 NdisZeroMemory(mpdu_blk, sizeof(struct reordering_mpdu));
294 /* next mpdu_blk */
295 mem += sizeof(struct reordering_mpdu);
296 /* insert mpdu_blk into freelist */
297 ba_enqueue(freelist, mpdu_blk);
300 return(TRUE);
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);
311 if (mpdu_blk)
313 // blk_count++;
314 /* reset mpdu_blk */
315 NdisZeroMemory(mpdu_blk, sizeof(struct reordering_mpdu));
317 NdisReleaseSpinLock(&pAd->mpdu_blk_pool.lock);
318 return mpdu_blk;
321 static void ba_mpdu_blk_free(PRTMP_ADAPTER pAd, struct reordering_mpdu *mpdu_blk)
323 ASSERT(mpdu_blk);
325 NdisAcquireSpinLock(&pAd->mpdu_blk_pool.lock);
326 // blk_count--;
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,
335 IN USHORT StartSeq)
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))
347 break;
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;
356 /* free mpdu_blk */
357 ba_mpdu_blk_free(pAd, mpdu_blk);
360 NdisReleaseSpinLock(&pBAEntry->RxReRingLock);
362 /* update last indicated sequence */
363 return LastIndSeq;
366 static void ba_indicate_reordering_mpdus_le_seq(
367 IN PRTMP_ADAPTER pAd,
368 IN PBA_REC_ENTRY pBAEntry,
369 IN USHORT Sequence)
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);
383 /* free mpdu_blk */
384 ba_mpdu_blk_free(pAd, mpdu_blk);
386 else
388 break;
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);
420 //static
421 void ba_flush_reordering_timeout_mpdus(
422 IN PRTMP_ADAPTER pAd,
423 IN PBA_REC_ENTRY pBAEntry,
424 IN ULONG Now32)
427 USHORT Sequence;
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;
443 else
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;
465 #if 0
466 else if (
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;
477 #endif
482 * generate ADDBA request to
483 * set up BA agreement
485 VOID BAOriSessionSetUp(
486 IN PRTMP_ADAPTER pAd,
487 IN MAC_TABLE_ENTRY *pEntry,
488 IN UCHAR TID,
489 IN USHORT TimeOut,
490 IN ULONG DelayTime,
491 IN BOOLEAN isForced)
494 //MLME_ADDBA_REQ_STRUCT AddbaReq;
495 BA_ORI_ENTRY *pBAEntry = NULL;
496 USHORT Idx;
497 BOOLEAN Cancelled;
499 if ((pAd->CommonCfg.BACapability.field.AutoBA != TRUE) && (isForced == FALSE))
500 return;
502 // if this entry is limited to use legacy tx mode, it doesn't generate BA.
503 if (RTMPStaFixedTxMode(pAd, pEntry) != FIXED_TXMODE_HT)
504 return;
506 if ((pEntry->BADeclineBitmap & (1<<TID)) && (isForced == FALSE))
508 // try again after 3 secs
509 DelayTime = 3000;
510 // printk("DeCline BA from Peer\n");
511 // return;
515 Idx = pEntry->BAOriWcidArray[TID];
516 if (Idx == 0)
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"));
523 return;
526 else
528 pBAEntry =&pAd->BATable.BAOriEntry[Idx];
531 if (pBAEntry->ORI_BA_Status >= Originator_WaitRes)
533 return;
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
544 pBAEntry->TID = TID;
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);
552 else
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;
565 BOOLEAN Cancelled;
566 UCHAR TID;
567 USHORT Idx;
568 PUCHAR pOutBuffer2 = NULL;
569 NDIS_STATUS NStatus;
570 ULONG FrameLen;
571 FRAME_BAR FrameBar;
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;
587 // Set Bitmap flag.
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));
596 // SEND BAR ;
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"));
601 return;
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,
611 END_OF_ARGS);
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;
628 BOOLEAN Cancelled;
629 USHORT Idx;
630 UCHAR TID;
631 UCHAR BAWinSize;
632 //UINT32 Value;
633 //UINT offset;
636 ASSERT(pEntry);
638 // find TID
639 TID = pFrame->BaParm.TID;
641 BAWinSize = min(((UCHAR)pFrame->BaParm.BufSize), (UCHAR)pAd->CommonCfg.BACapability.field.RxBAWinLimit);
643 // Intel patch
644 if (BAWinSize == 0)
646 BAWinSize = 64;
649 Idx = pEntry->BARecWcidArray[TID];
652 if (Idx == 0)
654 pBAEntry = BATableAllocRecEntry(pAd, &Idx);
656 else
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;
674 pBAEntry->TID = TID;
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);
686 else
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);
693 #endif
695 // Set Bitmap flag.
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]));
707 else
709 Status = FALSE;
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));
713 return(Status);
717 BA_REC_ENTRY *BATableAllocRecEntry(
718 IN PRTMP_ADAPTER pAd,
719 OUT USHORT *Idx)
721 int i;
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,
730 MAX_BARECI_SESSION);
731 goto done;
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))
740 // get one
741 pAd->BATable.numAsRecipient++;
742 pBAEntry->REC_BA_Status = Recipient_USED;
743 *Idx = i;
744 break;
748 done:
749 NdisReleaseSpinLock(&pAd->BATabLock);
750 return pBAEntry;
753 BA_ORI_ENTRY *BATableAllocOriEntry(
754 IN PRTMP_ADAPTER pAd,
755 OUT USHORT *Idx)
757 int i;
758 BA_ORI_ENTRY *pBAEntry = NULL;
760 NdisAcquireSpinLock(&pAd->BATabLock);
762 if (pAd->BATable.numAsOriginator >= (MAX_LEN_OF_BA_ORI_TABLE))
764 goto done;
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))
773 // get one
774 pAd->BATable.numAsOriginator++;
775 pBAEntry->ORI_BA_Status = Originator_USED;
776 pBAEntry->pAdapter = pAd;
777 *Idx = i;
778 break;
782 done:
783 NdisReleaseSpinLock(&pAd->BATabLock);
784 return pBAEntry;
788 VOID BATableFreeOriEntry(
789 IN PRTMP_ADAPTER pAd,
790 IN ULONG Idx)
792 BA_ORI_ENTRY *pBAEntry = NULL;
793 MAC_TABLE_ENTRY *pEntry;
796 if ((Idx == 0) || (Idx >= MAX_LEN_OF_BA_ORI_TABLE))
797 return;
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;
820 pBAEntry->Token = 0;
821 NdisReleaseSpinLock(&pAd->BATabLock);
826 VOID BATableFreeRecEntry(
827 IN PRTMP_ADAPTER pAd,
828 IN ULONG Idx)
830 BA_REC_ENTRY *pBAEntry = NULL;
831 MAC_TABLE_ENTRY *pEntry;
834 if ((Idx == 0) || (Idx >= MAX_LEN_OF_BA_REC_TABLE))
835 return;
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,
858 IN UCHAR Wcid,
859 IN UCHAR TID,
860 IN BOOLEAN bPassive,
861 IN BOOLEAN bForceSend)
863 ULONG Idx = 0;
864 BA_ORI_ENTRY *pBAEntry;
865 BOOLEAN Cancelled;
867 if (Wcid >= MAX_LEN_OF_MAC_TABLE)
869 return;
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;
889 DelbaReq.TID = TID;
890 DelbaReq.Initiator = ORIGINATOR;
891 #if 1
892 Elem->MsgLen = sizeof(DelbaReq);
893 NdisMoveMemory(Elem->Msg, &DelbaReq, sizeof(DelbaReq));
894 MlmeDELBAAction(pAd, Elem);
895 kfree(Elem);
896 #else
897 MlmeEnqueue(pAd, ACTION_STATE_MACHINE, MT2_MLME_ORI_DELBA_CATE, sizeof(MLME_DELBA_REQ_STRUCT), (PVOID)&DelbaReq);
898 RT28XX_MLME_HANDLER(pAd);
899 #endif
902 return;
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;
924 #if 1
925 Elem->MsgLen = sizeof(DelbaReq);
926 NdisMoveMemory(Elem->Msg, &DelbaReq, sizeof(DelbaReq));
927 MlmeDELBAAction(pAd, Elem);
928 kfree(Elem);
929 #else
930 MlmeEnqueue(pAd, ACTION_STATE_MACHINE, MT2_MLME_ORI_DELBA_CATE, sizeof(MLME_DELBA_REQ_STRUCT), (PVOID)&DelbaReq);
931 RT28XX_MLME_HANDLER(pAd);
932 #endif
934 RTMPCancelTimer(&pBAEntry->ORIBATimer, &Cancelled);
935 BATableFreeOriEntry(pAd, Idx);
937 if (bPassive)
939 //BAOriSessionSetUp(pAd, &pAd->MacTab.Content[Wcid], TID, 0, 10000, TRUE);
943 VOID BARecSessionTearDown(
944 IN OUT PRTMP_ADAPTER pAd,
945 IN UCHAR Wcid,
946 IN UCHAR TID,
947 IN BOOLEAN bPassive)
949 ULONG Idx = 0;
950 BA_REC_ENTRY *pBAEntry;
952 if (Wcid >= MAX_LEN_OF_MAC_TABLE)
954 return;
958 // Locate corresponding BA Originator Entry in BA Table with the (pAddr,TID).
960 Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID];
961 if (Idx == 0)
962 return;
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;
975 BOOLEAN Cancelled;
976 MLME_QUEUE_ELEM *Elem = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG);
977 //ULONG offset;
978 //UINT32 VALUE;
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;
992 DelbaReq.TID = TID;
993 DelbaReq.Initiator = RECIPIENT;
994 #if 1
995 Elem->MsgLen = sizeof(DelbaReq);
996 NdisMoveMemory(Elem->Msg, &DelbaReq, sizeof(DelbaReq));
997 MlmeDELBAAction(pAd, Elem);
998 kfree(Elem);
999 #else
1000 MlmeEnqueue(pAd, ACTION_STATE_MACHINE, MT2_MLME_ORI_DELBA_CATE, sizeof(MLME_DELBA_REQ_STRUCT), (PVOID)&DelbaReq);
1001 RT28XX_MLME_HANDLER(pAd);
1002 #endif
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,
1032 IN UCHAR Wcid)
1034 int i;
1036 for (i=0; i<NUM_OF_TID; i++)
1038 BAOriSessionTearDown(pAd, Wcid, i, FALSE, FALSE);
1039 BARecSessionTearDown(pAd, Wcid, i, FALSE);
1045 ==========================================================================
1046 Description:
1047 Retry sending ADDBA Reqest.
1049 IRQL = DISPATCH_LEVEL
1051 Parametrs:
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;
1066 PRTMP_ADAPTER pAd;
1068 if (pBAEntry == NULL)
1069 return;
1071 pAd = pBAEntry->pAdapter;
1073 // Do nothing if monitor mode is on
1074 if (MONITOR_ON(pAd))
1075 return;
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));
1094 pBAEntry->Token++;
1095 RTMPSetTimer(&pBAEntry->ORIBATimer, ORI_BA_SESSION_TIMEOUT);
1097 else
1099 BATableFreeOriEntry(pAd, pEntry->BAOriWcidArray[pBAEntry->TID]);
1104 ==========================================================================
1105 Description:
1106 Retry sending ADDBA Reqest.
1108 IRQL = DISPATCH_LEVEL
1110 Parametrs:
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;
1125 PRTMP_ADAPTER pAd;
1126 ULONG Now32;
1128 if (pBAEntry == NULL)
1129 return;
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)
1151 // 7.4.4.1
1152 //ULONG Idx;
1153 UCHAR Status = 1;
1154 UCHAR pAddr[6];
1155 FRAME_ADDBA_RSP ADDframe;
1156 PUCHAR pOutBuffer = NULL;
1157 NDIS_STATUS NStatus;
1158 PFRAME_ADDBA_REQ pAddreqFrame = NULL;
1159 //UCHAR BufSize;
1160 ULONG FrameLen;
1161 PULONG ptemp;
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)
1170 return;
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))
1185 Status = 0;
1186 else
1187 Status = 38; // more parameters have invalid values
1189 else
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"));
1204 return;
1207 NdisZeroMemory(&ADDframe, sizeof(FRAME_ADDBA_RSP));
1209 // 2-1. Prepare ADDBA Response frame.
1211 if (ADHOC_ON(pAd))
1212 ActHeaderInit(pAd, &ADDframe.Hdr, pAddr, pAd->CurrentAddress, pAd->CommonCfg.Bssid);
1213 else
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,
1238 END_OF_ARGS);
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)
1252 //UCHAR Idx, i;
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)
1259 return;
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)
1272 case 0:
1273 // I want a BAsession with this peer as an originator.
1274 BAOriSessionAdd(pAd, &pAd->MacTab.Content[Elem->Wcid], pFrame);
1275 break;
1276 default:
1277 // check status == USED ???
1278 BAOriSessionTearDown(pAd, Elem->Wcid, pFrame->BaParm.TID, TRUE, FALSE);
1279 break;
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)
1296 //UCHAR Idx;
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);
1310 else
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,
1322 IN ULONG Wcid,
1323 IN ULONG MsgLen,
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;
1330 //BOOLEAN Result;
1331 ULONG Idx;
1332 //UCHAR NumRxPkt;
1333 UCHAR TID;//, i;
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))
1342 return FALSE;
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));
1348 return FALSE;
1350 else if (MsgLen != sizeof(FRAME_BA_REQ))
1352 DBGPRINT_ERR(("CntlEnqueueForRecv: BlockAck Request frame length size = %ld incorrect\n", MsgLen));
1353 return FALSE;
1355 else if (MsgLen != sizeof(FRAME_BA_REQ))
1357 DBGPRINT_ERR(("CntlEnqueueForRecv: BlockAck Request frame length size = %ld incorrect\n", MsgLen));
1358 return FALSE;
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];
1367 else
1369 return FALSE;
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);
1381 return TRUE;
1385 Description : Send PSMP Action frame If PSMP mode switches.
1387 VOID SendPSMPAction(
1388 IN PRTMP_ADAPTER pAd,
1389 IN UCHAR Wcid,
1390 IN UCHAR Psmp)
1392 PUCHAR pOutBuffer = NULL;
1393 NDIS_STATUS NStatus;
1394 //ULONG Idx;
1395 FRAME_PSMP_ACTION Frame;
1396 ULONG FrameLen;
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"));
1402 return;
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;
1409 switch (Psmp)
1411 case MMPS_ENABLE:
1412 Frame.Psmp = 0;
1413 break;
1414 case MMPS_DYNAMIC:
1415 Frame.Psmp = 3;
1416 break;
1417 case MMPS_STATIC:
1418 Frame.Psmp = 1;
1419 break;
1421 MakeOutgoingFrame(pOutBuffer, &FrameLen,
1422 sizeof(FRAME_PSMP_ACTION), &Frame,
1423 END_OF_ARGS);
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;
1441 UCHAR Threshold;
1442 UCHAR SSIDIE[2]; // 2 byte
1443 } BEACON_REQUEST;
1445 typedef struct PACKED
1447 UCHAR ID;
1448 UCHAR Length;
1449 UCHAR Token;
1450 UCHAR RequestMode;
1451 UCHAR Type;
1452 } MEASUREMENT_REQ;
1457 void convert_reordering_packet_to_preAMSDU_or_802_3_packet(
1458 IN PRTMP_ADAPTER pAd,
1459 IN RX_BLK *pRxBlk,
1460 IN UCHAR FromWhichBSSID)
1462 PNDIS_PACKET pRxPkt;
1463 UCHAR Header802_3[LENGTH_802_3];
1465 // 1. get 802.3 Header
1466 // 2. remove LLC
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))
1485 #ifdef LINUX
1486 NdisMoveMemory(skb_push(pRxPkt, LENGTH_802_3), Header802_3, LENGTH_802_3);
1487 #endif
1492 #define INDICATE_LEGACY_OR_AMSDU(_pAd, _pRxBlk, _fromWhichBSSID) \
1493 do \
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); \
1503 else \
1505 Indicate_Legacy_Packet(_pAd, _pRxBlk, _fromWhichBSSID); \
1507 } while (0);
1511 static VOID ba_enqueue_reordering_packet(
1512 IN PRTMP_ADAPTER pAd,
1513 IN PBA_REC_ENTRY pBAEntry,
1514 IN RX_BLK *pRxBlk,
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
1545 // don't indicate
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);
1553 else
1555 #if 0
1556 DBGPRINT(RT_DEBUG_ERROR, ("!!! (%d:%d) Can't allocate reordering mpdu blk\n",
1557 blk_count, pBAEntry->list.qlen));
1558 #else
1559 DBGPRINT(RT_DEBUG_ERROR, ("!!! (%d) Can't allocate reordering mpdu blk\n",
1560 pBAEntry->list.qlen));
1561 #endif
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 ==========================================================================
1578 Description:
1579 Indicate this packet to upper layer or put it into reordering buffer
1581 Parametrs:
1582 pRxBlk : carry necessary packet info 802.11 format
1583 FromWhichBSSID : the packet received from which BSS
1585 Return :
1586 none
1588 Note :
1589 the packet queued into reordering buffer need to cover to 802.3 format
1590 or pre_AMSDU format
1591 ==========================================================================
1594 VOID Indicate_AMPDU_Packet(
1595 IN PRTMP_ADAPTER pAd,
1596 IN RX_BLK *pRxBlk,
1597 IN UCHAR FromWhichBSSID)
1599 USHORT Idx;
1600 PBA_REC_ENTRY pBAEntry = NULL;
1601 UINT16 Sequence = pRxBlk->pHeader->Sequence;
1602 ULONG Now32;
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;
1612 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);
1617 err_size = 0;
1619 #endif
1620 // release packet
1621 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
1622 return;
1626 #if 0 // test
1627 /* Rec BA Session had been torn down */
1628 INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID);
1629 return;
1630 #endif
1632 if (Wcid < MAX_LEN_OF_MAC_TABLE)
1634 Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID];
1635 if (Idx == 0)
1637 /* Rec BA Session had been torn down */
1638 INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID);
1639 return;
1641 pBAEntry = &pAd->BATable.BARecEntry[Idx];
1643 else
1645 // impossible !!!
1646 ASSERT(0);
1647 // release packet
1648 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
1649 return;
1652 ASSERT(pBAEntry);
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);
1674 return;
1679 // I. Check if in order.
1681 if (SEQ_STEPONE(Sequence, pBAEntry->LastIndSeq, MAXSEQ))
1683 USHORT LastIndSeq;
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
1724 else
1726 #if 0
1727 ba_refresh_reordering_mpdus(pAd, pBAEntry);
1728 INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID);
1729 #else
1730 LONG WinStartSeq, TmpSeq;
1733 TmpSeq = Sequence - (pBAEntry->BAWinSize) -1;
1734 if (TmpSeq < 0)
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;
1751 #endif