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