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