Staging: add rt2870 wireless driver
[deliverable/linux.git] / drivers / staging / rt2870 / common / ba_action.c
1 /*
2 *************************************************************************
3 * Ralink Tech Inc.
4 * 5F., No.36, Taiyuan St., Jhubei City,
5 * Hsinchu County 302,
6 * Taiwan, R.O.C.
7 *
8 * (c) Copyright 2002-2007, Ralink Technology, Inc.
9 *
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 *************************************************************************
26 */
27
28
29 #ifdef DOT11_N_SUPPORT
30
31 #include "../rt_config.h"
32
33
34
35 #define BA_ORI_INIT_SEQ (pEntry->TxSeq[TID]) //1 // inital sequence number of BA session
36
37 #define ORI_SESSION_MAX_RETRY 8
38 #define ORI_BA_SESSION_TIMEOUT (2000) // ms
39 #define REC_BA_SESSION_IDLE_TIMEOUT (1000) // ms
40
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
43
44 #define RESET_RCV_SEQ (0xFFFF)
45
46 static void ba_mpdu_blk_free(PRTMP_ADAPTER pAd, struct reordering_mpdu *mpdu_blk);
47
48
49 BA_ORI_ENTRY *BATableAllocOriEntry(
50 IN PRTMP_ADAPTER pAd,
51 OUT USHORT *Idx);
52
53 BA_REC_ENTRY *BATableAllocRecEntry(
54 IN PRTMP_ADAPTER pAd,
55 OUT USHORT *Idx);
56
57 VOID BAOriSessionSetupTimeout(
58 IN PVOID SystemSpecific1,
59 IN PVOID FunctionContext,
60 IN PVOID SystemSpecific2,
61 IN PVOID SystemSpecific3);
62
63 VOID BARecSessionIdleTimeout(
64 IN PVOID SystemSpecific1,
65 IN PVOID FunctionContext,
66 IN PVOID SystemSpecific2,
67 IN PVOID SystemSpecific3);
68
69
70 BUILD_TIMER_FUNCTION(BAOriSessionSetupTimeout);
71 BUILD_TIMER_FUNCTION(BARecSessionIdleTimeout);
72
73 #define ANNOUNCE_REORDERING_PACKET(_pAd, _mpdu_blk) \
74 Announce_Reordering_Packet(_pAd, _mpdu_blk);
75
76 VOID BA_MaxWinSizeReasign(
77 IN PRTMP_ADAPTER pAd,
78 IN MAC_TABLE_ENTRY *pEntryPeer,
79 OUT UCHAR *pWinSize)
80 {
81 UCHAR MaxSize;
82
83
84 if (pAd->MACVersion >= RALINK_2883_VERSION) // 3*3
85 {
86 if (pAd->MACVersion >= RALINK_3070_VERSION)
87 {
88 if (pEntryPeer->WepStatus != Ndis802_11EncryptionDisabled)
89 MaxSize = 7; // for non-open mode
90 else
91 MaxSize = 13;
92 }
93 else
94 MaxSize = 31;
95 }
96 else if (pAd->MACVersion >= RALINK_2880E_VERSION) // 2880 e
97 {
98 if (pEntryPeer->WepStatus != Ndis802_11EncryptionDisabled)
99 MaxSize = 7; // for non-open mode
100 else
101 MaxSize = 13;
102 }
103 else
104 MaxSize = 7;
105
106 DBGPRINT(RT_DEBUG_TRACE, ("ba> Win Size = %d, Max Size = %d\n",
107 *pWinSize, MaxSize));
108
109 if ((*pWinSize) > MaxSize)
110 {
111 DBGPRINT(RT_DEBUG_TRACE, ("ba> reassign max win size from %d to %d\n",
112 *pWinSize, MaxSize));
113
114 *pWinSize = MaxSize;
115 }
116 }
117
118 void Announce_Reordering_Packet(IN PRTMP_ADAPTER pAd,
119 IN struct reordering_mpdu *mpdu)
120 {
121 PNDIS_PACKET pPacket;
122
123 pPacket = mpdu->pPacket;
124
125 if (mpdu->bAMSDU)
126 {
127 ASSERT(0);
128 BA_Reorder_AMSDU_Annnounce(pAd, pPacket);
129 }
130 else
131 {
132 //
133 // pass this 802.3 packet to upper layer or forward this packet to WM directly
134 //
135
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 //
140 }
141 }
142
143 /*
144 * Insert a reordering mpdu into sorted linked list by sequence no.
145 */
146 BOOLEAN ba_reordering_mpdu_insertsorted(struct reordering_list *list, struct reordering_mpdu *mpdu)
147 {
148
149 struct reordering_mpdu **ppScan = &list->next;
150
151 while (*ppScan != NULL)
152 {
153 if (SEQ_SMALLER((*ppScan)->Sequence, mpdu->Sequence, MAXSEQ))
154 {
155 ppScan = &(*ppScan)->next;
156 }
157 else if ((*ppScan)->Sequence == mpdu->Sequence)
158 {
159 /* give up this duplicated frame */
160 return(FALSE);
161 }
162 else
163 {
164 /* find position */
165 break;
166 }
167 }
168
169 mpdu->next = *ppScan;
170 *ppScan = mpdu;
171 list->qlen++;
172 return TRUE;
173 }
174
175
176 /*
177 * caller lock critical section if necessary
178 */
179 static inline void ba_enqueue(struct reordering_list *list, struct reordering_mpdu *mpdu_blk)
180 {
181 list->qlen++;
182 mpdu_blk->next = list->next;
183 list->next = mpdu_blk;
184 }
185
186 /*
187 * caller lock critical section if necessary
188 */
189 static inline struct reordering_mpdu * ba_dequeue(struct reordering_list *list)
190 {
191 struct reordering_mpdu *mpdu_blk = NULL;
192
193 ASSERT(list);
194
195 if (list->qlen)
196 {
197 list->qlen--;
198 mpdu_blk = list->next;
199 if (mpdu_blk)
200 {
201 list->next = mpdu_blk->next;
202 mpdu_blk->next = NULL;
203 }
204 }
205 return mpdu_blk;
206 }
207
208
209 static inline struct reordering_mpdu *ba_reordering_mpdu_dequeue(struct reordering_list *list)
210 {
211 return(ba_dequeue(list));
212 }
213
214
215 static inline struct reordering_mpdu *ba_reordering_mpdu_probe(struct reordering_list *list)
216 {
217 ASSERT(list);
218
219 return(list->next);
220 }
221
222
223 /*
224 * free all resource for reordering mechanism
225 */
226 void ba_reordering_resource_release(PRTMP_ADAPTER pAd)
227 {
228 BA_TABLE *Tab;
229 PBA_REC_ENTRY pBAEntry;
230 struct reordering_mpdu *mpdu_blk;
231 int i;
232
233 Tab = &pAd->BATable;
234
235 /* I. release all pending reordering packet */
236 NdisAcquireSpinLock(&pAd->BATabLock);
237 for (i = 0; i < MAX_LEN_OF_BA_REC_TABLE; i++)
238 {
239 pBAEntry = &Tab->BARecEntry[i];
240 if (pBAEntry->REC_BA_Status != Recipient_NONE)
241 {
242 while ((mpdu_blk = ba_reordering_mpdu_dequeue(&pBAEntry->list)))
243 {
244 ASSERT(mpdu_blk->pPacket);
245 RELEASE_NDIS_PACKET(pAd, mpdu_blk->pPacket, NDIS_STATUS_FAILURE);
246 ba_mpdu_blk_free(pAd, mpdu_blk);
247 }
248 }
249 }
250 NdisReleaseSpinLock(&pAd->BATabLock);
251
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);
257 }
258
259
260
261 /*
262 * Allocate all resource for reordering mechanism
263 */
264 BOOLEAN ba_reordering_resource_init(PRTMP_ADAPTER pAd, int num)
265 {
266 int i;
267 PUCHAR mem;
268 struct reordering_mpdu *mpdu_blk;
269 struct reordering_list *freelist;
270
271 /* allocate spinlock */
272 NdisAllocateSpinLock(&pAd->mpdu_blk_pool.lock);
273
274 /* initialize freelist */
275 freelist = &pAd->mpdu_blk_pool.freelist;
276 freelist->next = NULL;
277 freelist->qlen = 0;
278
279 DBGPRINT(RT_DEBUG_TRACE, ("Allocate %d memory for BA reordering\n", (UINT32)(num*sizeof(struct reordering_mpdu))));
280
281 /* allocate number of mpdu_blk memory */
282 os_alloc_mem(pAd, (PUCHAR *)&mem, (num*sizeof(struct reordering_mpdu)));
283
284 pAd->mpdu_blk_pool.mem = mem;
285
286 if (mem == NULL)
287 {
288 DBGPRINT(RT_DEBUG_ERROR, ("Can't Allocate Memory for BA Reordering\n"));
289 return(FALSE);
290 }
291
292 /* build mpdu_blk free list */
293 for (i=0; i<num; i++)
294 {
295 /* get mpdu_blk */
296 mpdu_blk = (struct reordering_mpdu *) mem;
297 /* initial mpdu_blk */
298 NdisZeroMemory(mpdu_blk, sizeof(struct reordering_mpdu));
299 /* next mpdu_blk */
300 mem += sizeof(struct reordering_mpdu);
301 /* insert mpdu_blk into freelist */
302 ba_enqueue(freelist, mpdu_blk);
303 }
304
305 return(TRUE);
306 }
307
308 //static int blk_count=0; // sample take off, no use
309
310 static struct reordering_mpdu *ba_mpdu_blk_alloc(PRTMP_ADAPTER pAd)
311 {
312 struct reordering_mpdu *mpdu_blk;
313
314 NdisAcquireSpinLock(&pAd->mpdu_blk_pool.lock);
315 mpdu_blk = ba_dequeue(&pAd->mpdu_blk_pool.freelist);
316 if (mpdu_blk)
317 {
318 // blk_count++;
319 /* reset mpdu_blk */
320 NdisZeroMemory(mpdu_blk, sizeof(struct reordering_mpdu));
321 }
322 NdisReleaseSpinLock(&pAd->mpdu_blk_pool.lock);
323 return mpdu_blk;
324 }
325
326 static void ba_mpdu_blk_free(PRTMP_ADAPTER pAd, struct reordering_mpdu *mpdu_blk)
327 {
328 ASSERT(mpdu_blk);
329
330 NdisAcquireSpinLock(&pAd->mpdu_blk_pool.lock);
331 // blk_count--;
332 ba_enqueue(&pAd->mpdu_blk_pool.freelist, mpdu_blk);
333 NdisReleaseSpinLock(&pAd->mpdu_blk_pool.lock);
334 }
335
336
337 static USHORT ba_indicate_reordering_mpdus_in_order(
338 IN PRTMP_ADAPTER pAd,
339 IN PBA_REC_ENTRY pBAEntry,
340 IN USHORT StartSeq)
341 {
342 struct reordering_mpdu *mpdu_blk;
343 USHORT LastIndSeq = RESET_RCV_SEQ;
344
345 NdisAcquireSpinLock(&pBAEntry->RxReRingLock);
346
347 while ((mpdu_blk = ba_reordering_mpdu_probe(&pBAEntry->list)))
348 {
349 /* find in-order frame */
350 if (!SEQ_STEPONE(mpdu_blk->Sequence, StartSeq, MAXSEQ))
351 {
352 break;
353 }
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;
361 /* free mpdu_blk */
362 ba_mpdu_blk_free(pAd, mpdu_blk);
363 }
364
365 NdisReleaseSpinLock(&pBAEntry->RxReRingLock);
366
367 /* update last indicated sequence */
368 return LastIndSeq;
369 }
370
371 static void ba_indicate_reordering_mpdus_le_seq(
372 IN PRTMP_ADAPTER pAd,
373 IN PBA_REC_ENTRY pBAEntry,
374 IN USHORT Sequence)
375 {
376 struct reordering_mpdu *mpdu_blk;
377
378 NdisAcquireSpinLock(&pBAEntry->RxReRingLock);
379 while ((mpdu_blk = ba_reordering_mpdu_probe(&pBAEntry->list)))
380 {
381 /* find in-order frame */
382 if ((mpdu_blk->Sequence == Sequence) || SEQ_SMALLER(mpdu_blk->Sequence, Sequence, MAXSEQ))
383 {
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);
388 /* free mpdu_blk */
389 ba_mpdu_blk_free(pAd, mpdu_blk);
390 }
391 else
392 {
393 break;
394 }
395 }
396 NdisReleaseSpinLock(&pBAEntry->RxReRingLock);
397 }
398
399
400 static void ba_refresh_reordering_mpdus(
401 IN PRTMP_ADAPTER pAd,
402 PBA_REC_ENTRY pBAEntry)
403 {
404 struct reordering_mpdu *mpdu_blk;
405
406 NdisAcquireSpinLock(&pBAEntry->RxReRingLock);
407
408 /* dequeue in-order frame from reodering list */
409 while ((mpdu_blk = ba_reordering_mpdu_dequeue(&pBAEntry->list)))
410 {
411 /* pass this frame up */
412 ANNOUNCE_REORDERING_PACKET(pAd, mpdu_blk);
413
414 pBAEntry->LastIndSeq = mpdu_blk->Sequence;
415 ba_mpdu_blk_free(pAd, mpdu_blk);
416
417 /* update last indicated sequence */
418 }
419 ASSERT(pBAEntry->list.qlen == 0);
420 pBAEntry->LastIndSeq = RESET_RCV_SEQ;
421 NdisReleaseSpinLock(&pBAEntry->RxReRingLock);
422 }
423
424
425 //static
426 void ba_flush_reordering_timeout_mpdus(
427 IN PRTMP_ADAPTER pAd,
428 IN PBA_REC_ENTRY pBAEntry,
429 IN ULONG Now32)
430
431 {
432 USHORT Sequence;
433
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)
440 )
441 {
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;
447 }
448 else
449 if (RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+(REORDERING_PACKET_TIMEOUT)))
450 && (pBAEntry->list.qlen > 0)
451 )
452 {
453 //
454 // force LastIndSeq to shift to LastIndSeq+1
455 //
456 Sequence = (pBAEntry->LastIndSeq+1) & MAXSEQ;
457 ba_indicate_reordering_mpdus_le_seq(pAd, pBAEntry, Sequence);
458 pBAEntry->LastIndSeqAtTimer = Now32;
459 pBAEntry->LastIndSeq = Sequence;
460 //
461 // indicate in-order mpdus
462 //
463 Sequence = ba_indicate_reordering_mpdus_in_order(pAd, pBAEntry, Sequence);
464 if (Sequence != RESET_RCV_SEQ)
465 {
466 pBAEntry->LastIndSeq = Sequence;
467 }
468
469 }
470 #if 0
471 else if (
472 (RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+(MAX_REORDERING_PACKET_TIMEOUT))) &&
473 (pBAEntry->list.qlen > 1))
474 )
475 {
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;
481 }
482 #endif
483 }
484
485
486 /*
487 * generate ADDBA request to
488 * set up BA agreement
489 */
490 VOID BAOriSessionSetUp(
491 IN PRTMP_ADAPTER pAd,
492 IN MAC_TABLE_ENTRY *pEntry,
493 IN UCHAR TID,
494 IN USHORT TimeOut,
495 IN ULONG DelayTime,
496 IN BOOLEAN isForced)
497
498 {
499 //MLME_ADDBA_REQ_STRUCT AddbaReq;
500 BA_ORI_ENTRY *pBAEntry = NULL;
501 USHORT Idx;
502 BOOLEAN Cancelled;
503
504 if ((pAd->CommonCfg.BACapability.field.AutoBA != TRUE) && (isForced == FALSE))
505 return;
506
507 // if this entry is limited to use legacy tx mode, it doesn't generate BA.
508 if (RTMPStaFixedTxMode(pAd, pEntry) != FIXED_TXMODE_HT)
509 return;
510
511 if ((pEntry->BADeclineBitmap & (1<<TID)) && (isForced == FALSE))
512 {
513 // try again after 3 secs
514 DelayTime = 3000;
515 // printk("DeCline BA from Peer\n");
516 // return;
517 }
518
519
520 Idx = pEntry->BAOriWcidArray[TID];
521 if (Idx == 0)
522 {
523 // allocate a BA session
524 pBAEntry = BATableAllocOriEntry(pAd, &Idx);
525 if (pBAEntry == NULL)
526 {
527 DBGPRINT(RT_DEBUG_TRACE,("ADDBA - MlmeADDBAAction() allocate BA session failed \n"));
528 return;
529 }
530 }
531 else
532 {
533 pBAEntry =&pAd->BATable.BAOriEntry[Idx];
534 }
535
536 if (pBAEntry->ORI_BA_Status >= Originator_WaitRes)
537 {
538 return;
539 }
540
541 pEntry->BAOriWcidArray[TID] = Idx;
542
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
549 pBAEntry->TID = TID;
550 pBAEntry->TimeOutValue = TimeOut;
551 pBAEntry->pAdapter = pAd;
552
553 if (!(pEntry->TXBAbitmap & (1<<TID)))
554 {
555 RTMPInitTimer(pAd, &pBAEntry->ORIBATimer, GET_TIMER_FUNCTION(BAOriSessionSetupTimeout), pBAEntry, FALSE);
556 }
557 else
558 RTMPCancelTimer(&pBAEntry->ORIBATimer, &Cancelled);
559
560 // set timer to send ADDBA request
561 RTMPSetTimer(&pBAEntry->ORIBATimer, DelayTime);
562 }
563
564 VOID BAOriSessionAdd(
565 IN PRTMP_ADAPTER pAd,
566 IN MAC_TABLE_ENTRY *pEntry,
567 IN PFRAME_ADDBA_RSP pFrame)
568 {
569 BA_ORI_ENTRY *pBAEntry = NULL;
570 BOOLEAN Cancelled;
571 UCHAR TID;
572 USHORT Idx;
573 PUCHAR pOutBuffer2 = NULL;
574 NDIS_STATUS NStatus;
575 ULONG FrameLen;
576 FRAME_BAR FrameBar;
577
578 TID = pFrame->BaParm.TID;
579 Idx = pEntry->BAOriWcidArray[TID];
580 pBAEntry =&pAd->BATable.BAOriEntry[Idx];
581
582 // Start fill in parameters.
583 if ((Idx !=0) && (pBAEntry->TID == TID) && (pBAEntry->ORI_BA_Status == Originator_WaitRes))
584 {
585 pBAEntry->BAWinSize = min(pBAEntry->BAWinSize, ((UCHAR)pFrame->BaParm.BufSize));
586 BA_MaxWinSizeReasign(pAd, pEntry, &pBAEntry->BAWinSize);
587
588 pBAEntry->TimeOutValue = pFrame->TimeOutValue;
589 pBAEntry->ORI_BA_Status = Originator_Done;
590 // reset sequence number
591 pBAEntry->Sequence = BA_ORI_INIT_SEQ;
592 // Set Bitmap flag.
593 pEntry->TXBAbitmap |= (1<<TID);
594 RTMPCancelTimer(&pBAEntry->ORIBATimer, &Cancelled);
595
596 pBAEntry->ORIBATimer.TimerValue = 0; //pFrame->TimeOutValue;
597
598 DBGPRINT(RT_DEBUG_TRACE,("%s : TXBAbitmap = %x, BAWinSize = %d, TimeOut = %ld\n", __FUNCTION__, pEntry->TXBAbitmap,
599 pBAEntry->BAWinSize, pBAEntry->ORIBATimer.TimerValue));
600
601 // SEND BAR ;
602 NStatus = MlmeAllocateMemory(pAd, &pOutBuffer2); //Get an unused nonpaged memory
603 if (NStatus != NDIS_STATUS_SUCCESS)
604 {
605 DBGPRINT(RT_DEBUG_TRACE,("BA - BAOriSessionAdd() allocate memory failed \n"));
606 return;
607 }
608
609
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 //
614
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,
620 END_OF_ARGS);
621 MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer2, FrameLen);
622 MlmeFreeMemory(pAd, pOutBuffer2);
623
624
625 if (pBAEntry->ORIBATimer.TimerValue)
626 RTMPSetTimer(&pBAEntry->ORIBATimer, pBAEntry->ORIBATimer.TimerValue); // in mSec
627 }
628 }
629
630 BOOLEAN BARecSessionAdd(
631 IN PRTMP_ADAPTER pAd,
632 IN MAC_TABLE_ENTRY *pEntry,
633 IN PFRAME_ADDBA_REQ pFrame)
634 {
635 BA_REC_ENTRY *pBAEntry = NULL;
636 BOOLEAN Status = TRUE;
637 BOOLEAN Cancelled;
638 USHORT Idx;
639 UCHAR TID;
640 UCHAR BAWinSize;
641 //UINT32 Value;
642 //UINT offset;
643
644
645 ASSERT(pEntry);
646
647 // find TID
648 TID = pFrame->BaParm.TID;
649
650 BAWinSize = min(((UCHAR)pFrame->BaParm.BufSize), (UCHAR)pAd->CommonCfg.BACapability.field.RxBAWinLimit);
651
652 // Intel patch
653 if (BAWinSize == 0)
654 {
655 BAWinSize = 64;
656 }
657
658 Idx = pEntry->BARecWcidArray[TID];
659
660
661 if (Idx == 0)
662 {
663 pBAEntry = BATableAllocRecEntry(pAd, &Idx);
664 }
665 else
666 {
667 pBAEntry = &pAd->BATable.BARecEntry[Idx];
668 // flush all pending reordering mpdus
669 ba_refresh_reordering_mpdus(pAd, pBAEntry);
670 }
671
672 DBGPRINT(RT_DEBUG_TRACE,("%s(%ld): Idx = %d, BAWinSize(req %d) = %d\n", __FUNCTION__, pAd->BATable.numAsRecipient, Idx,
673 pFrame->BaParm.BufSize, BAWinSize));
674
675 // Start fill in parameters.
676 if (pBAEntry != NULL)
677 {
678 ASSERT(pBAEntry->list.qlen == 0);
679
680 pBAEntry->REC_BA_Status = Recipient_HandleRes;
681 pBAEntry->BAWinSize = BAWinSize;
682 pBAEntry->Wcid = pEntry->Aid;
683 pBAEntry->TID = TID;
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;
688
689 printk("Start Seq = %08x\n", pFrame->BaStartSeq.field.StartSeq);
690
691 if (pEntry->RXBAbitmap & (1<<TID))
692 {
693 RTMPCancelTimer(&pBAEntry->RECBATimer, &Cancelled);
694 }
695 else
696 {
697 RTMPInitTimer(pAd, &pBAEntry->RECBATimer, GET_TIMER_FUNCTION(BARecSessionIdleTimeout), pBAEntry, TRUE);
698 }
699
700 #if 0 // for debugging
701 RTMPSetTimer(&pBAEntry->RECBATimer, REC_BA_SESSION_IDLE_TIMEOUT);
702 #endif
703
704 // Set Bitmap flag.
705 pEntry->RXBAbitmap |= (1<<TID);
706 pEntry->BARecWcidArray[TID] = Idx;
707
708 pEntry->BADeclineBitmap &= ~(1<<TID);
709
710 // Set BA session mask in WCID table.
711 RT28XX_ADD_BA_SESSION_TO_ASIC(pAd, pEntry->Aid, TID);
712
713 DBGPRINT(RT_DEBUG_TRACE,("MACEntry[%d]RXBAbitmap = 0x%x. BARecWcidArray=%d\n",
714 pEntry->Aid, pEntry->RXBAbitmap, pEntry->BARecWcidArray[TID]));
715 }
716 else
717 {
718 Status = FALSE;
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));
721 }
722 return(Status);
723 }
724
725
726 BA_REC_ENTRY *BATableAllocRecEntry(
727 IN PRTMP_ADAPTER pAd,
728 OUT USHORT *Idx)
729 {
730 int i;
731 BA_REC_ENTRY *pBAEntry = NULL;
732
733
734 NdisAcquireSpinLock(&pAd->BATabLock);
735
736 if (pAd->BATable.numAsRecipient >= MAX_BARECI_SESSION)
737 {
738 printk("BA Recipeint Session (%ld) > %d\n", pAd->BATable.numAsRecipient,
739 MAX_BARECI_SESSION);
740 goto done;
741 }
742
743 // reserve idx 0 to identify BAWcidArray[TID] as empty
744 for (i=1; i < MAX_LEN_OF_BA_REC_TABLE; i++)
745 {
746 pBAEntry =&pAd->BATable.BARecEntry[i];
747 if ((pBAEntry->REC_BA_Status == Recipient_NONE))
748 {
749 // get one
750 pAd->BATable.numAsRecipient++;
751 pBAEntry->REC_BA_Status = Recipient_USED;
752 *Idx = i;
753 break;
754 }
755 }
756
757 done:
758 NdisReleaseSpinLock(&pAd->BATabLock);
759 return pBAEntry;
760 }
761
762 BA_ORI_ENTRY *BATableAllocOriEntry(
763 IN PRTMP_ADAPTER pAd,
764 OUT USHORT *Idx)
765 {
766 int i;
767 BA_ORI_ENTRY *pBAEntry = NULL;
768
769 NdisAcquireSpinLock(&pAd->BATabLock);
770
771 if (pAd->BATable.numAsOriginator >= (MAX_LEN_OF_BA_ORI_TABLE))
772 {
773 goto done;
774 }
775
776 // reserve idx 0 to identify BAWcidArray[TID] as empty
777 for (i=1; i<MAX_LEN_OF_BA_ORI_TABLE; i++)
778 {
779 pBAEntry =&pAd->BATable.BAOriEntry[i];
780 if ((pBAEntry->ORI_BA_Status == Originator_NONE))
781 {
782 // get one
783 pAd->BATable.numAsOriginator++;
784 pBAEntry->ORI_BA_Status = Originator_USED;
785 pBAEntry->pAdapter = pAd;
786 *Idx = i;
787 break;
788 }
789 }
790
791 done:
792 NdisReleaseSpinLock(&pAd->BATabLock);
793 return pBAEntry;
794 }
795
796
797 VOID BATableFreeOriEntry(
798 IN PRTMP_ADAPTER pAd,
799 IN ULONG Idx)
800 {
801 BA_ORI_ENTRY *pBAEntry = NULL;
802 MAC_TABLE_ENTRY *pEntry;
803
804
805 if ((Idx == 0) || (Idx >= MAX_LEN_OF_BA_ORI_TABLE))
806 return;
807
808 pBAEntry =&pAd->BATable.BAOriEntry[Idx];
809
810 if (pBAEntry->ORI_BA_Status != Originator_NONE)
811 {
812 pEntry = &pAd->MacTab.Content[pBAEntry->Wcid];
813 pEntry->BAOriWcidArray[pBAEntry->TID] = 0;
814
815
816 NdisAcquireSpinLock(&pAd->BATabLock);
817 if (pBAEntry->ORI_BA_Status == Originator_Done)
818 {
819 pEntry->TXBAbitmap &= (~(1<<(pBAEntry->TID) ));
820 DBGPRINT(RT_DEBUG_TRACE, ("BATableFreeOriEntry numAsOriginator= %ld\n", pAd->BATable.numAsRecipient));
821 // Erase Bitmap flag.
822 }
823
824 ASSERT(pAd->BATable.numAsOriginator != 0);
825
826 pAd->BATable.numAsOriginator -= 1;
827
828 pBAEntry->ORI_BA_Status = Originator_NONE;
829 pBAEntry->Token = 0;
830 NdisReleaseSpinLock(&pAd->BATabLock);
831 }
832 }
833
834
835 VOID BATableFreeRecEntry(
836 IN PRTMP_ADAPTER pAd,
837 IN ULONG Idx)
838 {
839 BA_REC_ENTRY *pBAEntry = NULL;
840 MAC_TABLE_ENTRY *pEntry;
841
842
843 if ((Idx == 0) || (Idx >= MAX_LEN_OF_BA_REC_TABLE))
844 return;
845
846 pBAEntry =&pAd->BATable.BARecEntry[Idx];
847
848 if (pBAEntry->REC_BA_Status != Recipient_NONE)
849 {
850 pEntry = &pAd->MacTab.Content[pBAEntry->Wcid];
851 pEntry->BARecWcidArray[pBAEntry->TID] = 0;
852
853 NdisAcquireSpinLock(&pAd->BATabLock);
854
855 ASSERT(pAd->BATable.numAsRecipient != 0);
856
857 pAd->BATable.numAsRecipient -= 1;
858
859 pBAEntry->REC_BA_Status = Recipient_NONE;
860 NdisReleaseSpinLock(&pAd->BATabLock);
861 }
862 }
863
864
865 VOID BAOriSessionTearDown(
866 IN OUT PRTMP_ADAPTER pAd,
867 IN UCHAR Wcid,
868 IN UCHAR TID,
869 IN BOOLEAN bPassive,
870 IN BOOLEAN bForceSend)
871 {
872 ULONG Idx = 0;
873 BA_ORI_ENTRY *pBAEntry;
874 BOOLEAN Cancelled;
875
876 if (Wcid >= MAX_LEN_OF_MAC_TABLE)
877 {
878 return;
879 }
880
881 //
882 // Locate corresponding BA Originator Entry in BA Table with the (pAddr,TID).
883 //
884 Idx = pAd->MacTab.Content[Wcid].BAOriWcidArray[TID];
885 if ((Idx == 0) || (Idx >= MAX_LEN_OF_BA_ORI_TABLE))
886 {
887 if (bForceSend == TRUE)
888 {
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);
892
893 NdisZeroMemory(&DelbaReq, sizeof(DelbaReq));
894 NdisZeroMemory(Elem, sizeof(MLME_QUEUE_ELEM));
895
896 COPY_MAC_ADDR(DelbaReq.Addr, pAd->MacTab.Content[Wcid].Addr);
897 DelbaReq.Wcid = Wcid;
898 DelbaReq.TID = TID;
899 DelbaReq.Initiator = ORIGINATOR;
900 #if 1
901 Elem->MsgLen = sizeof(DelbaReq);
902 NdisMoveMemory(Elem->Msg, &DelbaReq, sizeof(DelbaReq));
903 MlmeDELBAAction(pAd, Elem);
904 kfree(Elem);
905 #else
906 MlmeEnqueue(pAd, ACTION_STATE_MACHINE, MT2_MLME_ORI_DELBA_CATE, sizeof(MLME_DELBA_REQ_STRUCT), (PVOID)&DelbaReq);
907 RT28XX_MLME_HANDLER(pAd);
908 #endif
909 }
910
911 return;
912 }
913
914 DBGPRINT(RT_DEBUG_TRACE,("%s===>Wcid=%d.TID=%d \n", __FUNCTION__, Wcid, TID));
915
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));
918 //
919 // Prepare DelBA action frame and send to the peer.
920 //
921 if ((bPassive == FALSE) && (TID == pBAEntry->TID) && (pBAEntry->ORI_BA_Status == Originator_Done))
922 {
923 MLME_DELBA_REQ_STRUCT DelbaReq;
924 MLME_QUEUE_ELEM *Elem = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG);
925
926 NdisZeroMemory(&DelbaReq, sizeof(DelbaReq));
927 NdisZeroMemory(Elem, sizeof(MLME_QUEUE_ELEM));
928
929 COPY_MAC_ADDR(DelbaReq.Addr, pAd->MacTab.Content[Wcid].Addr);
930 DelbaReq.Wcid = Wcid;
931 DelbaReq.TID = pBAEntry->TID;
932 DelbaReq.Initiator = ORIGINATOR;
933 #if 1
934 Elem->MsgLen = sizeof(DelbaReq);
935 NdisMoveMemory(Elem->Msg, &DelbaReq, sizeof(DelbaReq));
936 MlmeDELBAAction(pAd, Elem);
937 kfree(Elem);
938 #else
939 MlmeEnqueue(pAd, ACTION_STATE_MACHINE, MT2_MLME_ORI_DELBA_CATE, sizeof(MLME_DELBA_REQ_STRUCT), (PVOID)&DelbaReq);
940 RT28XX_MLME_HANDLER(pAd);
941 #endif
942 }
943 RTMPCancelTimer(&pBAEntry->ORIBATimer, &Cancelled);
944 BATableFreeOriEntry(pAd, Idx);
945
946 if (bPassive)
947 {
948 //BAOriSessionSetUp(pAd, &pAd->MacTab.Content[Wcid], TID, 0, 10000, TRUE);
949 }
950 }
951
952 VOID BARecSessionTearDown(
953 IN OUT PRTMP_ADAPTER pAd,
954 IN UCHAR Wcid,
955 IN UCHAR TID,
956 IN BOOLEAN bPassive)
957 {
958 ULONG Idx = 0;
959 BA_REC_ENTRY *pBAEntry;
960
961 if (Wcid >= MAX_LEN_OF_MAC_TABLE)
962 {
963 return;
964 }
965
966 //
967 // Locate corresponding BA Originator Entry in BA Table with the (pAddr,TID).
968 //
969 Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID];
970 if (Idx == 0)
971 return;
972
973 DBGPRINT(RT_DEBUG_TRACE,("%s===>Wcid=%d.TID=%d \n", __FUNCTION__, Wcid, TID));
974
975
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));
978 //
979 // Prepare DelBA action frame and send to the peer.
980 //
981 if ((TID == pBAEntry->TID) && (pBAEntry->REC_BA_Status == Recipient_Accept))
982 {
983 MLME_DELBA_REQ_STRUCT DelbaReq;
984 BOOLEAN Cancelled;
985 MLME_QUEUE_ELEM *Elem = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG);
986 //ULONG offset;
987 //UINT32 VALUE;
988
989 RTMPCancelTimer(&pBAEntry->RECBATimer, &Cancelled);
990
991 //
992 // 1. Send DELBA Action Frame
993 //
994 if (bPassive == FALSE)
995 {
996 NdisZeroMemory(&DelbaReq, sizeof(DelbaReq));
997 NdisZeroMemory(Elem, sizeof(MLME_QUEUE_ELEM));
998
999 COPY_MAC_ADDR(DelbaReq.Addr, pAd->MacTab.Content[Wcid].Addr);
1000 DelbaReq.Wcid = Wcid;
1001 DelbaReq.TID = TID;
1002 DelbaReq.Initiator = RECIPIENT;
1003 #if 1
1004 Elem->MsgLen = sizeof(DelbaReq);
1005 NdisMoveMemory(Elem->Msg, &DelbaReq, sizeof(DelbaReq));
1006 MlmeDELBAAction(pAd, Elem);
1007 kfree(Elem);
1008 #else
1009 MlmeEnqueue(pAd, ACTION_STATE_MACHINE, MT2_MLME_ORI_DELBA_CATE, sizeof(MLME_DELBA_REQ_STRUCT), (PVOID)&DelbaReq);
1010 RT28XX_MLME_HANDLER(pAd);
1011 #endif
1012 }
1013
1014
1015 //
1016 // 2. Free resource of BA session
1017 //
1018 // flush all pending reordering mpdus
1019 ba_refresh_reordering_mpdus(pAd, pBAEntry);
1020
1021 NdisAcquireSpinLock(&pAd->BATabLock);
1022
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;
1029
1030 RT28XX_DEL_BA_SESSION_FROM_ASIC(pAd, Wcid, TID);
1031
1032 NdisReleaseSpinLock(&pAd->BATabLock);
1033
1034 }
1035
1036 BATableFreeRecEntry(pAd, Idx);
1037 }
1038
1039 VOID BASessionTearDownALL(
1040 IN OUT PRTMP_ADAPTER pAd,
1041 IN UCHAR Wcid)
1042 {
1043 int i;
1044
1045 for (i=0; i<NUM_OF_TID; i++)
1046 {
1047 BAOriSessionTearDown(pAd, Wcid, i, FALSE, FALSE);
1048 BARecSessionTearDown(pAd, Wcid, i, FALSE);
1049 }
1050 }
1051
1052
1053 /*
1054 ==========================================================================
1055 Description:
1056 Retry sending ADDBA Reqest.
1057
1058 IRQL = DISPATCH_LEVEL
1059
1060 Parametrs:
1061 p8023Header: if this is already 802.3 format, p8023Header is NULL
1062
1063 Return : TRUE if put into rx reordering buffer, shouldn't indicaterxhere.
1064 FALSE , then continue indicaterx at this moment.
1065 ==========================================================================
1066 */
1067 VOID BAOriSessionSetupTimeout(
1068 IN PVOID SystemSpecific1,
1069 IN PVOID FunctionContext,
1070 IN PVOID SystemSpecific2,
1071 IN PVOID SystemSpecific3)
1072 {
1073 BA_ORI_ENTRY *pBAEntry = (BA_ORI_ENTRY *)FunctionContext;
1074 MAC_TABLE_ENTRY *pEntry;
1075 PRTMP_ADAPTER pAd;
1076
1077 if (pBAEntry == NULL)
1078 return;
1079
1080 pAd = pBAEntry->pAdapter;
1081
1082 #ifdef CONFIG_STA_SUPPORT
1083 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1084 {
1085 // Do nothing if monitor mode is on
1086 if (MONITOR_ON(pAd))
1087 return;
1088 }
1089 #endif // CONFIG_STA_SUPPORT //
1090
1091 #ifdef RALINK_ATE
1092 // Nothing to do in ATE mode.
1093 if (ATE_ON(pAd))
1094 return;
1095 #endif // RALINK_ATE //
1096
1097 pEntry = &pAd->MacTab.Content[pBAEntry->Wcid];
1098
1099 if ((pBAEntry->ORI_BA_Status == Originator_WaitRes) && (pBAEntry->Token < ORI_SESSION_MAX_RETRY))
1100 {
1101 MLME_ADDBA_REQ_STRUCT AddbaReq;
1102
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));
1113
1114 pBAEntry->Token++;
1115 RTMPSetTimer(&pBAEntry->ORIBATimer, ORI_BA_SESSION_TIMEOUT);
1116 }
1117 else
1118 {
1119 BATableFreeOriEntry(pAd, pEntry->BAOriWcidArray[pBAEntry->TID]);
1120 }
1121 }
1122
1123 /*
1124 ==========================================================================
1125 Description:
1126 Retry sending ADDBA Reqest.
1127
1128 IRQL = DISPATCH_LEVEL
1129
1130 Parametrs:
1131 p8023Header: if this is already 802.3 format, p8023Header is NULL
1132
1133 Return : TRUE if put into rx reordering buffer, shouldn't indicaterxhere.
1134 FALSE , then continue indicaterx at this moment.
1135 ==========================================================================
1136 */
1137 VOID BARecSessionIdleTimeout(
1138 IN PVOID SystemSpecific1,
1139 IN PVOID FunctionContext,
1140 IN PVOID SystemSpecific2,
1141 IN PVOID SystemSpecific3)
1142 {
1143
1144 BA_REC_ENTRY *pBAEntry = (BA_REC_ENTRY *)FunctionContext;
1145 PRTMP_ADAPTER pAd;
1146 ULONG Now32;
1147
1148 if (pBAEntry == NULL)
1149 return;
1150
1151 if ((pBAEntry->REC_BA_Status == Recipient_Accept))
1152 {
1153 NdisGetSystemUpTime(&Now32);
1154
1155 if (RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer + REC_BA_SESSION_IDLE_TIMEOUT)))
1156 {
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);
1161 }
1162 }
1163 }
1164
1165
1166 VOID PeerAddBAReqAction(
1167 IN PRTMP_ADAPTER pAd,
1168 IN MLME_QUEUE_ELEM *Elem)
1169
1170 {
1171 // 7.4.4.1
1172 //ULONG Idx;
1173 UCHAR Status = 1;
1174 UCHAR pAddr[6];
1175 FRAME_ADDBA_RSP ADDframe;
1176 PUCHAR pOutBuffer = NULL;
1177 NDIS_STATUS NStatus;
1178 PFRAME_ADDBA_REQ pAddreqFrame = NULL;
1179 //UCHAR BufSize;
1180 ULONG FrameLen;
1181 PULONG ptemp;
1182 PMAC_TABLE_ENTRY pMacEntry;
1183
1184 DBGPRINT(RT_DEBUG_TRACE, ("%s ==> (Wcid = %d)\n", __FUNCTION__, Elem->Wcid));
1185
1186 //hex_dump("AddBAReq", Elem->Msg, Elem->MsgLen);
1187
1188 //ADDBA Request from unknown peer, ignore this.
1189 if (Elem->Wcid >= MAX_LEN_OF_MAC_TABLE)
1190 return;
1191
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)));
1196
1197 if (PeerAddBAReqActionSanity(pAd, Elem->Msg, Elem->MsgLen, pAddr))
1198 {
1199
1200 if ((pAd->CommonCfg.bBADecline == FALSE) && IS_HT_STA(pMacEntry))
1201 {
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))
1205 Status = 0;
1206 else
1207 Status = 38; // more parameters have invalid values
1208 }
1209 else
1210 {
1211 Status = 37; // the request has been declined.
1212 }
1213 }
1214
1215 if (pAd->MacTab.Content[Elem->Wcid].ValidAsCLI)
1216 ASSERT(pAd->MacTab.Content[Elem->Wcid].Sst == SST_ASSOC);
1217
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)
1222 {
1223 DBGPRINT(RT_DEBUG_TRACE,("ACTION - PeerBAAction() allocate memory failed \n"));
1224 return;
1225 }
1226
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)
1231 {
1232 if (ADHOC_ON(pAd))
1233 ActHeaderInit(pAd, &ADDframe.Hdr, pAddr, pAd->CurrentAddress, pAd->CommonCfg.Bssid);
1234 else
1235 #ifdef QOS_DLS_SUPPORT
1236 if (pAd->MacTab.Content[Elem->Wcid].ValidAsDls)
1237 ActHeaderInit(pAd, &ADDframe.Hdr, pAddr, pAd->CurrentAddress, pAd->CommonCfg.Bssid);
1238 else
1239 #endif // QOS_DLS_SUPPORT //
1240 ActHeaderInit(pAd, &ADDframe.Hdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pAddr);
1241 }
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)
1253 {
1254 ADDframe.BaParm.BufSize = 64;
1255 }
1256 ADDframe.TimeOutValue = 0; //pAddreqFrame->TimeOutValue;
1257
1258 *(USHORT *)(&ADDframe.BaParm) = cpu2le16(*(USHORT *)(&ADDframe.BaParm));
1259 ADDframe.StatusCode = cpu2le16(ADDframe.StatusCode);
1260 ADDframe.TimeOutValue = cpu2le16(ADDframe.TimeOutValue);
1261
1262 MakeOutgoingFrame(pOutBuffer, &FrameLen,
1263 sizeof(FRAME_ADDBA_RSP), &ADDframe,
1264 END_OF_ARGS);
1265 MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
1266 MlmeFreeMemory(pAd, pOutBuffer);
1267
1268 DBGPRINT(RT_DEBUG_TRACE, ("%s(%d): TID(%d), BufSize(%d) <== \n", __FUNCTION__, Elem->Wcid, ADDframe.BaParm.TID,
1269 ADDframe.BaParm.BufSize));
1270 }
1271
1272
1273 VOID PeerAddBARspAction(
1274 IN PRTMP_ADAPTER pAd,
1275 IN MLME_QUEUE_ELEM *Elem)
1276
1277 {
1278 //UCHAR Idx, i;
1279 //PUCHAR pOutBuffer = NULL;
1280 PFRAME_ADDBA_RSP pFrame = NULL;
1281 //PBA_ORI_ENTRY pBAEntry;
1282
1283 //ADDBA Response from unknown peer, ignore this.
1284 if (Elem->Wcid >= MAX_LEN_OF_MAC_TABLE)
1285 return;
1286
1287 DBGPRINT(RT_DEBUG_TRACE, ("%s ==> Wcid(%d)\n", __FUNCTION__, Elem->Wcid));
1288
1289 //hex_dump("PeerAddBARspAction()", Elem->Msg, Elem->MsgLen);
1290
1291 if (PeerAddBARspActionSanity(pAd, Elem->Msg, Elem->MsgLen))
1292 {
1293 pFrame = (PFRAME_ADDBA_RSP)(&Elem->Msg[0]);
1294
1295 DBGPRINT(RT_DEBUG_TRACE, ("\t\t StatusCode = %d\n", pFrame->StatusCode));
1296 switch (pFrame->StatusCode)
1297 {
1298 case 0:
1299 // I want a BAsession with this peer as an originator.
1300 BAOriSessionAdd(pAd, &pAd->MacTab.Content[Elem->Wcid], pFrame);
1301 break;
1302 default:
1303 // check status == USED ???
1304 BAOriSessionTearDown(pAd, Elem->Wcid, pFrame->BaParm.TID, TRUE, FALSE);
1305 break;
1306 }
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 //
1312 )
1313 {
1314 pAd->MacTab.Content[Elem->Wcid].BADeclineBitmap |= 1<<pFrame->BaParm.TID;
1315 }
1316 }
1317 }
1318
1319 VOID PeerDelBAAction(
1320 IN PRTMP_ADAPTER pAd,
1321 IN MLME_QUEUE_ELEM *Elem)
1322
1323 {
1324 //UCHAR Idx;
1325 //PUCHAR pOutBuffer = NULL;
1326 PFRAME_DELBA_REQ pDelFrame = NULL;
1327
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))
1331 {
1332 pDelFrame = (PFRAME_DELBA_REQ)(&Elem->Msg[0]);
1333 if (pDelFrame->DelbaParm.Initiator == ORIGINATOR)
1334 {
1335 DBGPRINT(RT_DEBUG_TRACE,("BA - PeerDelBAAction----> ORIGINATOR\n"));
1336 BARecSessionTearDown(pAd, Elem->Wcid, pDelFrame->DelbaParm.TID, TRUE);
1337 }
1338 else
1339 {
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);
1343 }
1344 }
1345 }
1346
1347
1348 BOOLEAN CntlEnqueueForRecv(
1349 IN PRTMP_ADAPTER pAd,
1350 IN ULONG Wcid,
1351 IN ULONG MsgLen,
1352 IN PFRAME_BA_REQ pMsg)
1353 {
1354 PFRAME_BA_REQ pFrame = pMsg;
1355 //PRTMP_REORDERBUF pBuffer;
1356 //PRTMP_REORDERBUF pDmaBuf;
1357 PBA_REC_ENTRY pBAEntry;
1358 //BOOLEAN Result;
1359 ULONG Idx;
1360 //UCHAR NumRxPkt;
1361 UCHAR TID;//, i;
1362
1363 TID = (UCHAR)pFrame->BARControl.TID;
1364
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))
1370 return FALSE;
1371
1372 // First check the size, it MUST not exceed the mlme queue size
1373 if (MsgLen > MGMT_DMA_BUFFER_SIZE)
1374 {
1375 DBGPRINT_ERR(("CntlEnqueueForRecv: frame too large, size = %ld \n", MsgLen));
1376 return FALSE;
1377 }
1378 else if (MsgLen != sizeof(FRAME_BA_REQ))
1379 {
1380 DBGPRINT_ERR(("CntlEnqueueForRecv: BlockAck Request frame length size = %ld incorrect\n", MsgLen));
1381 return FALSE;
1382 }
1383 else if (MsgLen != sizeof(FRAME_BA_REQ))
1384 {
1385 DBGPRINT_ERR(("CntlEnqueueForRecv: BlockAck Request frame length size = %ld incorrect\n", MsgLen));
1386 return FALSE;
1387 }
1388
1389 if ((Wcid < MAX_LEN_OF_MAC_TABLE) && (TID < 8))
1390 {
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];
1394 }
1395 else
1396 {
1397 return FALSE;
1398 }
1399
1400 DBGPRINT(RT_DEBUG_TRACE, ("BAR(%ld) : Tid (%d) - %04x:%04x\n", Wcid, TID, pFrame->BAStartingSeq.field.StartSeq, pBAEntry->LastIndSeq ));
1401
1402 if (SEQ_SMALLER(pBAEntry->LastIndSeq, pFrame->BAStartingSeq.field.StartSeq, MAXSEQ))
1403 {
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);
1407 }
1408 //ba_refresh_reordering_mpdus(pAd, pBAEntry);
1409 return TRUE;
1410 }
1411
1412 /*
1413 Description : Send PSMP Action frame If PSMP mode switches.
1414 */
1415 VOID SendPSMPAction(
1416 IN PRTMP_ADAPTER pAd,
1417 IN UCHAR Wcid,
1418 IN UCHAR Psmp)
1419 {
1420 PUCHAR pOutBuffer = NULL;
1421 NDIS_STATUS NStatus;
1422 //ULONG Idx;
1423 FRAME_PSMP_ACTION Frame;
1424 ULONG FrameLen;
1425
1426 NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory
1427 if (NStatus != NDIS_STATUS_SUCCESS)
1428 {
1429 DBGPRINT(RT_DEBUG_ERROR,("BA - MlmeADDBAAction() allocate memory failed \n"));
1430 return;
1431 }
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 //
1436
1437 Frame.Category = CATEGORY_HT;
1438 Frame.Action = SMPS_ACTION;
1439 switch (Psmp)
1440 {
1441 case MMPS_ENABLE:
1442 Frame.Psmp = 0;
1443 break;
1444 case MMPS_DYNAMIC:
1445 Frame.Psmp = 3;
1446 break;
1447 case MMPS_STATIC:
1448 Frame.Psmp = 1;
1449 break;
1450 }
1451 MakeOutgoingFrame(pOutBuffer, &FrameLen,
1452 sizeof(FRAME_PSMP_ACTION), &Frame,
1453 END_OF_ARGS);
1454 MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
1455 MlmeFreeMemory(pAd, pOutBuffer);
1456 DBGPRINT(RT_DEBUG_ERROR,("HT - SendPSMPAction( %d ) \n", Frame.Psmp));
1457 }
1458
1459
1460 #define RADIO_MEASUREMENT_REQUEST_ACTION 0
1461
1462 typedef struct PACKED
1463 {
1464 UCHAR RegulatoryClass;
1465 UCHAR ChannelNumber;
1466 USHORT RandomInterval;
1467 USHORT MeasurementDuration;
1468 UCHAR MeasurementMode;
1469 UCHAR BSSID[MAC_ADDR_LEN];
1470 UCHAR ReportingCondition;
1471 UCHAR Threshold;
1472 UCHAR SSIDIE[2]; // 2 byte
1473 } BEACON_REQUEST;
1474
1475 typedef struct PACKED
1476 {
1477 UCHAR ID;
1478 UCHAR Length;
1479 UCHAR Token;
1480 UCHAR RequestMode;
1481 UCHAR Type;
1482 } MEASUREMENT_REQ;
1483
1484
1485
1486
1487 void convert_reordering_packet_to_preAMSDU_or_802_3_packet(
1488 IN PRTMP_ADAPTER pAd,
1489 IN RX_BLK *pRxBlk,
1490 IN UCHAR FromWhichBSSID)
1491 {
1492 PNDIS_PACKET pRxPkt;
1493 UCHAR Header802_3[LENGTH_802_3];
1494
1495 // 1. get 802.3 Header
1496 // 2. remove LLC
1497 // a. pointer pRxBlk->pData to payload
1498 // b. modify pRxBlk->DataSize
1499
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 //
1504
1505 ASSERT(pRxBlk->pRxPacket);
1506 pRxPkt = RTPKT_TO_OSPKT(pRxBlk->pRxPacket);
1507
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;
1512
1513 //
1514 // copy 802.3 header, if necessary
1515 //
1516 if (!RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU))
1517 {
1518
1519 #ifdef CONFIG_STA_SUPPORT
1520 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1521 {
1522 #ifdef LINUX
1523 NdisMoveMemory(skb_push(pRxPkt, LENGTH_802_3), Header802_3, LENGTH_802_3);
1524 #endif
1525 #ifdef UCOS
1526 NdisMoveMemory(net_pkt_push(pRxPkt, LENGTH_802_3), Header802_3, LENGTH_802_3);
1527 #endif
1528 }
1529 #endif // CONFIG_STA_SUPPORT //
1530 }
1531 }
1532
1533
1534 #define INDICATE_LEGACY_OR_AMSDU(_pAd, _pRxBlk, _fromWhichBSSID) \
1535 do \
1536 { \
1537 if (RX_BLK_TEST_FLAG(_pRxBlk, fRX_AMSDU)) \
1538 { \
1539 Indicate_AMSDU_Packet(_pAd, _pRxBlk, _fromWhichBSSID); \
1540 } \
1541 else if (RX_BLK_TEST_FLAG(_pRxBlk, fRX_EAP)) \
1542 { \
1543 Indicate_EAPOL_Packet(_pAd, _pRxBlk, _fromWhichBSSID); \
1544 } \
1545 else \
1546 { \
1547 Indicate_Legacy_Packet(_pAd, _pRxBlk, _fromWhichBSSID); \
1548 } \
1549 } while (0);
1550
1551
1552
1553 static VOID ba_enqueue_reordering_packet(
1554 IN PRTMP_ADAPTER pAd,
1555 IN PBA_REC_ENTRY pBAEntry,
1556 IN RX_BLK *pRxBlk,
1557 IN UCHAR FromWhichBSSID)
1558 {
1559 struct reordering_mpdu *mpdu_blk;
1560 UINT16 Sequence = (UINT16) pRxBlk->pHeader->Sequence;
1561
1562 mpdu_blk = ba_mpdu_blk_alloc(pAd);
1563 if (mpdu_blk != NULL)
1564 {
1565 // Write RxD buffer address & allocated buffer length
1566 NdisAcquireSpinLock(&pBAEntry->RxReRingLock);
1567
1568 mpdu_blk->Sequence = Sequence;
1569
1570 mpdu_blk->bAMSDU = RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU);
1571
1572 convert_reordering_packet_to_preAMSDU_or_802_3_packet(pAd, pRxBlk, FromWhichBSSID);
1573
1574 STATS_INC_RX_PACKETS(pAd, FromWhichBSSID);
1575
1576 //
1577 // it is necessary for reordering packet to record
1578 // which BSS it come from
1579 //
1580 RTMP_SET_PACKET_IF(pRxBlk->pRxPacket, FromWhichBSSID);
1581
1582 mpdu_blk->pPacket = pRxBlk->pRxPacket;
1583
1584 if (ba_reordering_mpdu_insertsorted(&pBAEntry->list, mpdu_blk) == FALSE)
1585 {
1586 // had been already within reordering list
1587 // don't indicate
1588 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_SUCCESS);
1589 ba_mpdu_blk_free(pAd, mpdu_blk);
1590 }
1591
1592 ASSERT((0<= pBAEntry->list.qlen) && (pBAEntry->list.qlen <= pBAEntry->BAWinSize));
1593 NdisReleaseSpinLock(&pBAEntry->RxReRingLock);
1594 }
1595 else
1596 {
1597 #if 0
1598 DBGPRINT(RT_DEBUG_ERROR, ("!!! (%d:%d) Can't allocate reordering mpdu blk\n",
1599 blk_count, pBAEntry->list.qlen));
1600 #else
1601 DBGPRINT(RT_DEBUG_ERROR, ("!!! (%d) Can't allocate reordering mpdu blk\n",
1602 pBAEntry->list.qlen));
1603 #endif
1604 /*
1605 * flush all pending reordering mpdus
1606 * and receving mpdu to upper layer
1607 * make tcp/ip to take care reordering mechanism
1608 */
1609 //ba_refresh_reordering_mpdus(pAd, pBAEntry);
1610 ba_indicate_reordering_mpdus_le_seq(pAd, pBAEntry, Sequence);
1611
1612 pBAEntry->LastIndSeq = Sequence;
1613 INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID);
1614 }
1615 }
1616
1617
1618 /*
1619 ==========================================================================
1620 Description:
1621 Indicate this packet to upper layer or put it into reordering buffer
1622
1623 Parametrs:
1624 pRxBlk : carry necessary packet info 802.11 format
1625 FromWhichBSSID : the packet received from which BSS
1626
1627 Return :
1628 none
1629
1630 Note :
1631 the packet queued into reordering buffer need to cover to 802.3 format
1632 or pre_AMSDU format
1633 ==========================================================================
1634 */
1635
1636 VOID Indicate_AMPDU_Packet(
1637 IN PRTMP_ADAPTER pAd,
1638 IN RX_BLK *pRxBlk,
1639 IN UCHAR FromWhichBSSID)
1640 {
1641 USHORT Idx;
1642 PBA_REC_ENTRY pBAEntry = NULL;
1643 UINT16 Sequence = pRxBlk->pHeader->Sequence;
1644 ULONG Now32;
1645 UCHAR Wcid = pRxBlk->pRxWI->WirelessCliID;
1646 UCHAR TID = pRxBlk->pRxWI->TID;
1647
1648
1649 if (!RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU) && (pRxBlk->DataSize > MAX_RX_PKT_LEN))
1650 {
1651 #if 0 // sample take off, no use
1652 static int err_size;
1653
1654 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);
1659 err_size = 0;
1660 }
1661 #endif
1662 // release packet
1663 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
1664 return;
1665 }
1666
1667
1668 #if 0 // test
1669 /* Rec BA Session had been torn down */
1670 INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID);
1671 return;
1672 #endif
1673
1674 if (Wcid < MAX_LEN_OF_MAC_TABLE)
1675 {
1676 Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID];
1677 if (Idx == 0)
1678 {
1679 /* Rec BA Session had been torn down */
1680 INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID);
1681 return;
1682 }
1683 pBAEntry = &pAd->BATable.BARecEntry[Idx];
1684 }
1685 else
1686 {
1687 // impossible !!!
1688 ASSERT(0);
1689 // release packet
1690 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
1691 return;
1692 }
1693
1694 ASSERT(pBAEntry);
1695
1696 // update last rx time
1697 NdisGetSystemUpTime(&Now32);
1698
1699 pBAEntry->rcvSeq = Sequence;
1700
1701
1702 ba_flush_reordering_timeout_mpdus(pAd, pBAEntry, Now32);
1703 pBAEntry->LastIndSeqAtTimer = Now32;
1704
1705 //
1706 // Reset Last Indicate Sequence
1707 //
1708 if (pBAEntry->LastIndSeq == RESET_RCV_SEQ)
1709 {
1710 ASSERT((pBAEntry->list.qlen == 0) && (pBAEntry->list.next == NULL));
1711
1712 // reset rcv sequence of BA session
1713 pBAEntry->LastIndSeq = Sequence;
1714 pBAEntry->LastIndSeqAtTimer = Now32;
1715 INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID);
1716 return;
1717 }
1718
1719
1720 //
1721 // I. Check if in order.
1722 //
1723 if (SEQ_STEPONE(Sequence, pBAEntry->LastIndSeq, MAXSEQ))
1724 {
1725 USHORT LastIndSeq;
1726
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)
1731 {
1732 pBAEntry->LastIndSeq = LastIndSeq;
1733 }
1734 pBAEntry->LastIndSeqAtTimer = Now32;
1735 }
1736 //
1737 // II. Drop Duplicated Packet
1738 //
1739 else if (Sequence == pBAEntry->LastIndSeq)
1740 {
1741
1742 // drop and release packet
1743 pBAEntry->nDropPacket++;
1744 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
1745 }
1746 //
1747 // III. Drop Old Received Packet
1748 //
1749 else if (SEQ_SMALLER(Sequence, pBAEntry->LastIndSeq, MAXSEQ))
1750 {
1751
1752 // drop and release packet
1753 pBAEntry->nDropPacket++;
1754 RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
1755 }
1756 //
1757 // IV. Receive Sequence within Window Size
1758 //
1759 else if (SEQ_SMALLER(Sequence, (((pBAEntry->LastIndSeq+pBAEntry->BAWinSize+1)) & MAXSEQ), MAXSEQ))
1760 {
1761 ba_enqueue_reordering_packet(pAd, pBAEntry, pRxBlk, FromWhichBSSID);
1762 }
1763 //
1764 // V. Receive seq surpasses Win(lastseq + nMSDU). So refresh all reorder buffer
1765 //
1766 else
1767 {
1768 #if 0
1769 ba_refresh_reordering_mpdus(pAd, pBAEntry);
1770 INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID);
1771 #else
1772 LONG WinStartSeq, TmpSeq;
1773
1774
1775 TmpSeq = Sequence - (pBAEntry->BAWinSize) -1;
1776 if (TmpSeq < 0)
1777 {
1778 TmpSeq = (MAXSEQ+1) + TmpSeq;
1779 }
1780 WinStartSeq = (TmpSeq+1) & MAXSEQ;
1781 ba_indicate_reordering_mpdus_le_seq(pAd, pBAEntry, WinStartSeq);
1782 pBAEntry->LastIndSeq = WinStartSeq; //TmpSeq;
1783
1784 pBAEntry->LastIndSeqAtTimer = Now32;
1785
1786 ba_enqueue_reordering_packet(pAd, pBAEntry, pRxBlk, FromWhichBSSID);
1787
1788 TmpSeq = ba_indicate_reordering_mpdus_in_order(pAd, pBAEntry, pBAEntry->LastIndSeq);
1789 if (TmpSeq != RESET_RCV_SEQ)
1790 {
1791 pBAEntry->LastIndSeq = TmpSeq;
1792 }
1793 #endif
1794 }
1795 }
1796
1797 #endif // DOT11_N_SUPPORT //
1798
This page took 0.069283 seconds and 5 git commands to generate.