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