]>
Commit | Line | Data |
---|---|---|
36c7928c BZ |
1 | /* |
2 | ************************************************************************* | |
3 | * Ralink Tech Inc. | |
4 | * 5F., No.36, Taiyuan St., Jhubei City, | |
5 | * Hsinchu County 302, | |
6 | * Taiwan, R.O.C. | |
7 | * | |
8 | * (c) Copyright 2002-2007, Ralink Technology, Inc. | |
9 | * | |
10 | * This program is free software; you can redistribute it and/or modify * | |
11 | * it under the terms of the GNU General Public License as published by * | |
12 | * the Free Software Foundation; either version 2 of the License, or * | |
13 | * (at your option) any later version. * | |
14 | * * | |
15 | * This program is distributed in the hope that it will be useful, * | |
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * | |
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | |
18 | * GNU General Public License for more details. * | |
19 | * * | |
20 | * You should have received a copy of the GNU General Public License * | |
21 | * along with this program; if not, write to the * | |
22 | * Free Software Foundation, Inc., * | |
23 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * | |
24 | * * | |
25 | ************************************************************************* | |
26 | */ | |
27 | ||
28 | ||
29 | #ifdef DOT11_N_SUPPORT | |
30 | ||
31 | #include "../rt_config.h" | |
32 | ||
33 | ||
34 | #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 * OS_HZ)/1000) // system ticks -- 100 ms | |
41 | #define MAX_REORDERING_PACKET_TIMEOUT ((3000 * OS_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 | // DBGPRINT(RT_DEBUG_OFF, ("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 | DBGPRINT(RT_DEBUG_OFF, ("%x, flush one!\n", pBAEntry->LastIndSeq)); | |
472 | ||
473 | } | |
474 | } | |
475 | ||
476 | ||
477 | /* | |
478 | * generate ADDBA request to | |
479 | * set up BA agreement | |
480 | */ | |
481 | VOID BAOriSessionSetUp( | |
482 | IN PRTMP_ADAPTER pAd, | |
483 | IN MAC_TABLE_ENTRY *pEntry, | |
484 | IN UCHAR TID, | |
485 | IN USHORT TimeOut, | |
486 | IN ULONG DelayTime, | |
487 | IN BOOLEAN isForced) | |
488 | ||
489 | { | |
490 | //MLME_ADDBA_REQ_STRUCT AddbaReq; | |
491 | BA_ORI_ENTRY *pBAEntry = NULL; | |
492 | USHORT Idx; | |
493 | BOOLEAN Cancelled; | |
494 | ||
495 | if ((pAd->CommonCfg.BACapability.field.AutoBA != TRUE) && (isForced == FALSE)) | |
496 | return; | |
497 | ||
498 | // if this entry is limited to use legacy tx mode, it doesn't generate BA. | |
499 | if (RTMPStaFixedTxMode(pAd, pEntry) != FIXED_TXMODE_HT) | |
500 | return; | |
501 | ||
502 | if ((pEntry->BADeclineBitmap & (1<<TID)) && (isForced == FALSE)) | |
503 | { | |
504 | // try again after 3 secs | |
505 | DelayTime = 3000; | |
506 | // DBGPRINT(RT_DEBUG_TRACE, ("DeCline BA from Peer\n")); | |
507 | // return; | |
508 | } | |
509 | ||
510 | ||
511 | Idx = pEntry->BAOriWcidArray[TID]; | |
512 | if (Idx == 0) | |
513 | { | |
514 | // allocate a BA session | |
515 | pBAEntry = BATableAllocOriEntry(pAd, &Idx); | |
516 | if (pBAEntry == NULL) | |
517 | { | |
518 | DBGPRINT(RT_DEBUG_TRACE,("ADDBA - MlmeADDBAAction() allocate BA session failed \n")); | |
519 | return; | |
520 | } | |
521 | } | |
522 | else | |
523 | { | |
524 | pBAEntry =&pAd->BATable.BAOriEntry[Idx]; | |
525 | } | |
526 | ||
527 | if (pBAEntry->ORI_BA_Status >= Originator_WaitRes) | |
528 | { | |
529 | return; | |
530 | } | |
531 | ||
532 | pEntry->BAOriWcidArray[TID] = Idx; | |
533 | ||
534 | // Initialize BA session | |
535 | pBAEntry->ORI_BA_Status = Originator_WaitRes; | |
536 | pBAEntry->Wcid = pEntry->Aid; | |
537 | pBAEntry->BAWinSize = pAd->CommonCfg.BACapability.field.RxBAWinLimit; | |
538 | pBAEntry->Sequence = BA_ORI_INIT_SEQ; | |
539 | pBAEntry->Token = 1; // (2008-01-21) Jan Lee recommends it - this token can't be 0 | |
540 | pBAEntry->TID = TID; | |
541 | pBAEntry->TimeOutValue = TimeOut; | |
542 | pBAEntry->pAdapter = pAd; | |
543 | ||
544 | if (!(pEntry->TXBAbitmap & (1<<TID))) | |
545 | { | |
546 | RTMPInitTimer(pAd, &pBAEntry->ORIBATimer, GET_TIMER_FUNCTION(BAOriSessionSetupTimeout), pBAEntry, FALSE); | |
547 | } | |
548 | else | |
549 | RTMPCancelTimer(&pBAEntry->ORIBATimer, &Cancelled); | |
550 | ||
551 | // set timer to send ADDBA request | |
552 | RTMPSetTimer(&pBAEntry->ORIBATimer, DelayTime); | |
553 | } | |
554 | ||
555 | VOID BAOriSessionAdd( | |
556 | IN PRTMP_ADAPTER pAd, | |
557 | IN MAC_TABLE_ENTRY *pEntry, | |
558 | IN PFRAME_ADDBA_RSP pFrame) | |
559 | { | |
560 | BA_ORI_ENTRY *pBAEntry = NULL; | |
561 | BOOLEAN Cancelled; | |
562 | UCHAR TID; | |
563 | USHORT Idx; | |
564 | PUCHAR pOutBuffer2 = NULL; | |
565 | NDIS_STATUS NStatus; | |
566 | ULONG FrameLen; | |
567 | FRAME_BAR FrameBar; | |
568 | ||
569 | TID = pFrame->BaParm.TID; | |
570 | Idx = pEntry->BAOriWcidArray[TID]; | |
571 | pBAEntry =&pAd->BATable.BAOriEntry[Idx]; | |
572 | ||
573 | // Start fill in parameters. | |
574 | if ((Idx !=0) && (pBAEntry->TID == TID) && (pBAEntry->ORI_BA_Status == Originator_WaitRes)) | |
575 | { | |
576 | pBAEntry->BAWinSize = min(pBAEntry->BAWinSize, ((UCHAR)pFrame->BaParm.BufSize)); | |
577 | BA_MaxWinSizeReasign(pAd, pEntry, &pBAEntry->BAWinSize); | |
578 | ||
579 | pBAEntry->TimeOutValue = pFrame->TimeOutValue; | |
580 | pBAEntry->ORI_BA_Status = Originator_Done; | |
581 | pAd->BATable.numDoneOriginator ++; | |
582 | ||
583 | // reset sequence number | |
584 | pBAEntry->Sequence = BA_ORI_INIT_SEQ; | |
585 | // Set Bitmap flag. | |
586 | pEntry->TXBAbitmap |= (1<<TID); | |
587 | RTMPCancelTimer(&pBAEntry->ORIBATimer, &Cancelled); | |
588 | ||
589 | pBAEntry->ORIBATimer.TimerValue = 0; //pFrame->TimeOutValue; | |
590 | ||
591 | DBGPRINT(RT_DEBUG_TRACE,("%s : TXBAbitmap = %x, BAWinSize = %d, TimeOut = %ld\n", __FUNCTION__, pEntry->TXBAbitmap, | |
592 | pBAEntry->BAWinSize, pBAEntry->ORIBATimer.TimerValue)); | |
593 | ||
594 | // SEND BAR ; | |
595 | NStatus = MlmeAllocateMemory(pAd, &pOutBuffer2); //Get an unused nonpaged memory | |
596 | if (NStatus != NDIS_STATUS_SUCCESS) | |
597 | { | |
598 | DBGPRINT(RT_DEBUG_TRACE,("BA - BAOriSessionAdd() allocate memory failed \n")); | |
599 | return; | |
600 | } | |
601 | ||
602 | ||
603 | #ifdef CONFIG_STA_SUPPORT | |
604 | IF_DEV_CONFIG_OPMODE_ON_STA(pAd) | |
605 | BarHeaderInit(pAd, &FrameBar, pAd->MacTab.Content[pBAEntry->Wcid].Addr, pAd->CurrentAddress); | |
606 | #endif // CONFIG_STA_SUPPORT // | |
607 | ||
608 | FrameBar.StartingSeq.field.FragNum = 0; // make sure sequence not clear in DEL function. | |
609 | FrameBar.StartingSeq.field.StartSeq = pBAEntry->Sequence; // make sure sequence not clear in DEL funciton. | |
610 | FrameBar.BarControl.TID = pBAEntry->TID; // make sure sequence not clear in DEL funciton. | |
611 | MakeOutgoingFrame(pOutBuffer2, &FrameLen, | |
612 | sizeof(FRAME_BAR), &FrameBar, | |
613 | END_OF_ARGS); | |
614 | MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer2, FrameLen); | |
615 | MlmeFreeMemory(pAd, pOutBuffer2); | |
616 | ||
617 | ||
618 | if (pBAEntry->ORIBATimer.TimerValue) | |
619 | RTMPSetTimer(&pBAEntry->ORIBATimer, pBAEntry->ORIBATimer.TimerValue); // in mSec | |
620 | } | |
621 | } | |
622 | ||
623 | BOOLEAN BARecSessionAdd( | |
624 | IN PRTMP_ADAPTER pAd, | |
625 | IN MAC_TABLE_ENTRY *pEntry, | |
626 | IN PFRAME_ADDBA_REQ pFrame) | |
627 | { | |
628 | BA_REC_ENTRY *pBAEntry = NULL; | |
629 | BOOLEAN Status = TRUE; | |
630 | BOOLEAN Cancelled; | |
631 | USHORT Idx; | |
632 | UCHAR TID; | |
633 | UCHAR BAWinSize; | |
634 | //UINT32 Value; | |
635 | //UINT offset; | |
636 | ||
637 | ||
638 | ASSERT(pEntry); | |
639 | ||
640 | // find TID | |
641 | TID = pFrame->BaParm.TID; | |
642 | ||
643 | BAWinSize = min(((UCHAR)pFrame->BaParm.BufSize), (UCHAR)pAd->CommonCfg.BACapability.field.RxBAWinLimit); | |
644 | ||
645 | // Intel patch | |
646 | if (BAWinSize == 0) | |
647 | { | |
648 | BAWinSize = 64; | |
649 | } | |
650 | ||
651 | Idx = pEntry->BARecWcidArray[TID]; | |
652 | ||
653 | ||
654 | if (Idx == 0) | |
655 | { | |
656 | pBAEntry = BATableAllocRecEntry(pAd, &Idx); | |
657 | } | |
658 | else | |
659 | { | |
660 | pBAEntry = &pAd->BATable.BARecEntry[Idx]; | |
661 | // flush all pending reordering mpdus | |
662 | ba_refresh_reordering_mpdus(pAd, pBAEntry); | |
663 | } | |
664 | ||
665 | DBGPRINT(RT_DEBUG_TRACE,("%s(%ld): Idx = %d, BAWinSize(req %d) = %d\n", __FUNCTION__, pAd->BATable.numAsRecipient, Idx, | |
666 | pFrame->BaParm.BufSize, BAWinSize)); | |
667 | ||
668 | // Start fill in parameters. | |
669 | if (pBAEntry != NULL) | |
670 | { | |
671 | ASSERT(pBAEntry->list.qlen == 0); | |
672 | ||
673 | pBAEntry->REC_BA_Status = Recipient_HandleRes; | |
674 | pBAEntry->BAWinSize = BAWinSize; | |
675 | pBAEntry->Wcid = pEntry->Aid; | |
676 | pBAEntry->TID = TID; | |
677 | pBAEntry->TimeOutValue = pFrame->TimeOutValue; | |
678 | pBAEntry->REC_BA_Status = Recipient_Accept; | |
679 | // initial sequence number | |
680 | pBAEntry->LastIndSeq = RESET_RCV_SEQ; //pFrame->BaStartSeq.field.StartSeq; | |
681 | ||
682 | DBGPRINT(RT_DEBUG_OFF, ("Start Seq = %08x\n", pFrame->BaStartSeq.field.StartSeq)); | |
683 | ||
684 | if (pEntry->RXBAbitmap & (1<<TID)) | |
685 | { | |
686 | RTMPCancelTimer(&pBAEntry->RECBATimer, &Cancelled); | |
687 | } | |
688 | else | |
689 | { | |
690 | RTMPInitTimer(pAd, &pBAEntry->RECBATimer, GET_TIMER_FUNCTION(BARecSessionIdleTimeout), pBAEntry, TRUE); | |
691 | } | |
692 | ||
693 | ||
694 | // Set Bitmap flag. | |
695 | pEntry->RXBAbitmap |= (1<<TID); | |
696 | pEntry->BARecWcidArray[TID] = Idx; | |
697 | ||
698 | pEntry->BADeclineBitmap &= ~(1<<TID); | |
699 | ||
700 | // Set BA session mask in WCID table. | |
701 | RTMP_ADD_BA_SESSION_TO_ASIC(pAd, pEntry->Aid, TID); | |
702 | ||
703 | DBGPRINT(RT_DEBUG_TRACE,("MACEntry[%d]RXBAbitmap = 0x%x. BARecWcidArray=%d\n", | |
704 | pEntry->Aid, pEntry->RXBAbitmap, pEntry->BARecWcidArray[TID])); | |
705 | } | |
706 | else | |
707 | { | |
708 | Status = FALSE; | |
709 | DBGPRINT(RT_DEBUG_TRACE,("Can't Accept ADDBA for %02x:%02x:%02x:%02x:%02x:%02x TID = %d\n", | |
710 | PRINT_MAC(pEntry->Addr), TID)); | |
711 | } | |
712 | return(Status); | |
713 | } | |
714 | ||
715 | ||
716 | BA_REC_ENTRY *BATableAllocRecEntry( | |
717 | IN PRTMP_ADAPTER pAd, | |
718 | OUT USHORT *Idx) | |
719 | { | |
720 | int i; | |
721 | BA_REC_ENTRY *pBAEntry = NULL; | |
722 | ||
723 | ||
724 | NdisAcquireSpinLock(&pAd->BATabLock); | |
725 | ||
726 | if (pAd->BATable.numAsRecipient >= MAX_BARECI_SESSION) | |
727 | { | |
728 | DBGPRINT(RT_DEBUG_OFF, ("BA Recipeint Session (%ld) > %d\n", | |
729 | pAd->BATable.numAsRecipient, MAX_BARECI_SESSION)); | |
730 | goto done; | |
731 | } | |
732 | ||
733 | // reserve idx 0 to identify BAWcidArray[TID] as empty | |
734 | for (i=1; i < MAX_LEN_OF_BA_REC_TABLE; i++) | |
735 | { | |
736 | pBAEntry =&pAd->BATable.BARecEntry[i]; | |
737 | if ((pBAEntry->REC_BA_Status == Recipient_NONE)) | |
738 | { | |
739 | // get one | |
740 | pAd->BATable.numAsRecipient++; | |
741 | pBAEntry->REC_BA_Status = Recipient_USED; | |
742 | *Idx = i; | |
743 | break; | |
744 | } | |
745 | } | |
746 | ||
747 | done: | |
748 | NdisReleaseSpinLock(&pAd->BATabLock); | |
749 | return pBAEntry; | |
750 | } | |
751 | ||
752 | BA_ORI_ENTRY *BATableAllocOriEntry( | |
753 | IN PRTMP_ADAPTER pAd, | |
754 | OUT USHORT *Idx) | |
755 | { | |
756 | int i; | |
757 | BA_ORI_ENTRY *pBAEntry = NULL; | |
758 | ||
759 | NdisAcquireSpinLock(&pAd->BATabLock); | |
760 | ||
761 | if (pAd->BATable.numAsOriginator >= (MAX_LEN_OF_BA_ORI_TABLE)) | |
762 | { | |
763 | goto done; | |
764 | } | |
765 | ||
766 | // reserve idx 0 to identify BAWcidArray[TID] as empty | |
767 | for (i=1; i<MAX_LEN_OF_BA_ORI_TABLE; i++) | |
768 | { | |
769 | pBAEntry =&pAd->BATable.BAOriEntry[i]; | |
770 | if ((pBAEntry->ORI_BA_Status == Originator_NONE)) | |
771 | { | |
772 | // get one | |
773 | pAd->BATable.numAsOriginator++; | |
774 | pBAEntry->ORI_BA_Status = Originator_USED; | |
775 | pBAEntry->pAdapter = pAd; | |
776 | *Idx = i; | |
777 | break; | |
778 | } | |
779 | } | |
780 | ||
781 | done: | |
782 | NdisReleaseSpinLock(&pAd->BATabLock); | |
783 | return pBAEntry; | |
784 | } | |
785 | ||
786 | ||
787 | VOID BATableFreeOriEntry( | |
788 | IN PRTMP_ADAPTER pAd, | |
789 | IN ULONG Idx) | |
790 | { | |
791 | BA_ORI_ENTRY *pBAEntry = NULL; | |
792 | MAC_TABLE_ENTRY *pEntry; | |
793 | ||
794 | ||
795 | if ((Idx == 0) || (Idx >= MAX_LEN_OF_BA_ORI_TABLE)) | |
796 | return; | |
797 | ||
798 | pBAEntry =&pAd->BATable.BAOriEntry[Idx]; | |
799 | ||
800 | if (pBAEntry->ORI_BA_Status != Originator_NONE) | |
801 | { | |
802 | pEntry = &pAd->MacTab.Content[pBAEntry->Wcid]; | |
803 | pEntry->BAOriWcidArray[pBAEntry->TID] = 0; | |
804 | ||
805 | ||
806 | NdisAcquireSpinLock(&pAd->BATabLock); | |
807 | if (pBAEntry->ORI_BA_Status == Originator_Done) | |
808 | { | |
809 | pAd->BATable.numDoneOriginator -= 1; | |
810 | pEntry->TXBAbitmap &= (~(1<<(pBAEntry->TID) )); | |
811 | DBGPRINT(RT_DEBUG_TRACE, ("BATableFreeOriEntry numAsOriginator= %ld\n", pAd->BATable.numAsRecipient)); | |
812 | // Erase Bitmap flag. | |
813 | } | |
814 | ||
815 | ASSERT(pAd->BATable.numAsOriginator != 0); | |
816 | ||
817 | pAd->BATable.numAsOriginator -= 1; | |
818 | ||
819 | pBAEntry->ORI_BA_Status = Originator_NONE; | |
820 | pBAEntry->Token = 0; | |
821 | NdisReleaseSpinLock(&pAd->BATabLock); | |
822 | } | |
823 | } | |
824 | ||
825 | ||
826 | VOID BATableFreeRecEntry( | |
827 | IN PRTMP_ADAPTER pAd, | |
828 | IN ULONG Idx) | |
829 | { | |
830 | BA_REC_ENTRY *pBAEntry = NULL; | |
831 | MAC_TABLE_ENTRY *pEntry; | |
832 | ||
833 | ||
834 | if ((Idx == 0) || (Idx >= MAX_LEN_OF_BA_REC_TABLE)) | |
835 | return; | |
836 | ||
837 | pBAEntry =&pAd->BATable.BARecEntry[Idx]; | |
838 | ||
839 | if (pBAEntry->REC_BA_Status != Recipient_NONE) | |
840 | { | |
841 | pEntry = &pAd->MacTab.Content[pBAEntry->Wcid]; | |
842 | pEntry->BARecWcidArray[pBAEntry->TID] = 0; | |
843 | ||
844 | NdisAcquireSpinLock(&pAd->BATabLock); | |
845 | ||
846 | ASSERT(pAd->BATable.numAsRecipient != 0); | |
847 | ||
848 | pAd->BATable.numAsRecipient -= 1; | |
849 | ||
850 | pBAEntry->REC_BA_Status = Recipient_NONE; | |
851 | NdisReleaseSpinLock(&pAd->BATabLock); | |
852 | } | |
853 | } | |
854 | ||
855 | ||
856 | VOID BAOriSessionTearDown( | |
857 | IN OUT PRTMP_ADAPTER pAd, | |
858 | IN UCHAR Wcid, | |
859 | IN UCHAR TID, | |
860 | IN BOOLEAN bPassive, | |
861 | IN BOOLEAN bForceSend) | |
862 | { | |
863 | ULONG Idx = 0; | |
864 | BA_ORI_ENTRY *pBAEntry; | |
865 | BOOLEAN Cancelled; | |
866 | ||
867 | if (Wcid >= MAX_LEN_OF_MAC_TABLE) | |
868 | { | |
869 | return; | |
870 | } | |
871 | ||
872 | // | |
873 | // Locate corresponding BA Originator Entry in BA Table with the (pAddr,TID). | |
874 | // | |
875 | Idx = pAd->MacTab.Content[Wcid].BAOriWcidArray[TID]; | |
876 | if ((Idx == 0) || (Idx >= MAX_LEN_OF_BA_ORI_TABLE)) | |
877 | { | |
878 | if (bForceSend == TRUE) | |
879 | { | |
880 | // force send specified TID DelBA | |
881 | MLME_DELBA_REQ_STRUCT DelbaReq; | |
882 | MLME_QUEUE_ELEM *Elem = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG); | |
883 | if (Elem != NULL) | |
884 | { | |
885 | NdisZeroMemory(&DelbaReq, sizeof(DelbaReq)); | |
886 | NdisZeroMemory(Elem, sizeof(MLME_QUEUE_ELEM)); | |
887 | ||
888 | COPY_MAC_ADDR(DelbaReq.Addr, pAd->MacTab.Content[Wcid].Addr); | |
889 | DelbaReq.Wcid = Wcid; | |
890 | DelbaReq.TID = TID; | |
891 | DelbaReq.Initiator = ORIGINATOR; | |
892 | Elem->MsgLen = sizeof(DelbaReq); | |
893 | NdisMoveMemory(Elem->Msg, &DelbaReq, sizeof(DelbaReq)); | |
894 | MlmeDELBAAction(pAd, Elem); | |
895 | kfree(Elem); | |
896 | } | |
897 | else | |
898 | { | |
899 | DBGPRINT(RT_DEBUG_ERROR, ("%s(bForceSend):alloc memory failed!\n", __FUNCTION__)); | |
900 | } | |
901 | } | |
902 | ||
903 | return; | |
904 | } | |
905 | ||
906 | DBGPRINT(RT_DEBUG_TRACE,("%s===>Wcid=%d.TID=%d \n", __FUNCTION__, Wcid, TID)); | |
907 | ||
908 | pBAEntry = &pAd->BATable.BAOriEntry[Idx]; | |
909 | DBGPRINT(RT_DEBUG_TRACE,("\t===>Idx = %ld, Wcid=%d.TID=%d, ORI_BA_Status = %d \n", Idx, Wcid, TID, pBAEntry->ORI_BA_Status)); | |
910 | // | |
911 | // Prepare DelBA action frame and send to the peer. | |
912 | // | |
913 | if ((bPassive == FALSE) && (TID == pBAEntry->TID) && (pBAEntry->ORI_BA_Status == Originator_Done)) | |
914 | { | |
915 | MLME_DELBA_REQ_STRUCT DelbaReq; | |
916 | MLME_QUEUE_ELEM *Elem = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG); | |
917 | if (Elem != NULL) | |
918 | { | |
919 | NdisZeroMemory(&DelbaReq, sizeof(DelbaReq)); | |
920 | NdisZeroMemory(Elem, sizeof(MLME_QUEUE_ELEM)); | |
921 | ||
922 | COPY_MAC_ADDR(DelbaReq.Addr, pAd->MacTab.Content[Wcid].Addr); | |
923 | DelbaReq.Wcid = Wcid; | |
924 | DelbaReq.TID = pBAEntry->TID; | |
925 | DelbaReq.Initiator = ORIGINATOR; | |
926 | Elem->MsgLen = sizeof(DelbaReq); | |
927 | NdisMoveMemory(Elem->Msg, &DelbaReq, sizeof(DelbaReq)); | |
928 | MlmeDELBAAction(pAd, Elem); | |
929 | kfree(Elem); | |
930 | } | |
931 | else | |
932 | { | |
933 | DBGPRINT(RT_DEBUG_ERROR, ("%s():alloc memory failed!\n", __FUNCTION__)); | |
934 | return; | |
935 | } | |
936 | } | |
937 | RTMPCancelTimer(&pBAEntry->ORIBATimer, &Cancelled); | |
938 | BATableFreeOriEntry(pAd, Idx); | |
939 | ||
940 | if (bPassive) | |
941 | { | |
942 | //BAOriSessionSetUp(pAd, &pAd->MacTab.Content[Wcid], TID, 0, 10000, TRUE); | |
943 | } | |
944 | } | |
945 | ||
946 | VOID BARecSessionTearDown( | |
947 | IN OUT PRTMP_ADAPTER pAd, | |
948 | IN UCHAR Wcid, | |
949 | IN UCHAR TID, | |
950 | IN BOOLEAN bPassive) | |
951 | { | |
952 | ULONG Idx = 0; | |
953 | BA_REC_ENTRY *pBAEntry; | |
954 | ||
955 | if (Wcid >= MAX_LEN_OF_MAC_TABLE) | |
956 | { | |
957 | return; | |
958 | } | |
959 | ||
960 | // | |
961 | // Locate corresponding BA Originator Entry in BA Table with the (pAddr,TID). | |
962 | // | |
963 | Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID]; | |
964 | if (Idx == 0) | |
965 | return; | |
966 | ||
967 | DBGPRINT(RT_DEBUG_TRACE,("%s===>Wcid=%d.TID=%d \n", __FUNCTION__, Wcid, TID)); | |
968 | ||
969 | ||
970 | pBAEntry = &pAd->BATable.BARecEntry[Idx]; | |
971 | DBGPRINT(RT_DEBUG_TRACE,("\t===>Idx = %ld, Wcid=%d.TID=%d, REC_BA_Status = %d \n", Idx, Wcid, TID, pBAEntry->REC_BA_Status)); | |
972 | // | |
973 | // Prepare DelBA action frame and send to the peer. | |
974 | // | |
975 | if ((TID == pBAEntry->TID) && (pBAEntry->REC_BA_Status == Recipient_Accept)) | |
976 | { | |
977 | MLME_DELBA_REQ_STRUCT DelbaReq; | |
978 | BOOLEAN Cancelled; | |
979 | //ULONG offset; | |
980 | //UINT32 VALUE; | |
981 | ||
982 | RTMPCancelTimer(&pBAEntry->RECBATimer, &Cancelled); | |
983 | ||
984 | // | |
985 | // 1. Send DELBA Action Frame | |
986 | // | |
987 | if (bPassive == FALSE) | |
988 | { | |
989 | MLME_QUEUE_ELEM *Elem = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG); | |
990 | if (Elem != NULL) | |
991 | { | |
992 | NdisZeroMemory(&DelbaReq, sizeof(DelbaReq)); | |
993 | NdisZeroMemory(Elem, sizeof(MLME_QUEUE_ELEM)); | |
994 | ||
995 | COPY_MAC_ADDR(DelbaReq.Addr, pAd->MacTab.Content[Wcid].Addr); | |
996 | DelbaReq.Wcid = Wcid; | |
997 | DelbaReq.TID = TID; | |
998 | DelbaReq.Initiator = RECIPIENT; | |
999 | Elem->MsgLen = sizeof(DelbaReq); | |
1000 | NdisMoveMemory(Elem->Msg, &DelbaReq, sizeof(DelbaReq)); | |
1001 | MlmeDELBAAction(pAd, Elem); | |
1002 | kfree(Elem); | |
1003 | } | |
1004 | else | |
1005 | { | |
1006 | DBGPRINT(RT_DEBUG_ERROR, ("%s():alloc memory failed!\n", __FUNCTION__)); | |
1007 | return; | |
1008 | } | |
1009 | } | |
1010 | ||
1011 | ||
1012 | // | |
1013 | // 2. Free resource of BA session | |
1014 | // | |
1015 | // flush all pending reordering mpdus | |
1016 | ba_refresh_reordering_mpdus(pAd, pBAEntry); | |
1017 | ||
1018 | NdisAcquireSpinLock(&pAd->BATabLock); | |
1019 | ||
1020 | // Erase Bitmap flag. | |
1021 | pBAEntry->LastIndSeq = RESET_RCV_SEQ; | |
1022 | pBAEntry->BAWinSize = 0; | |
1023 | // Erase Bitmap flag at software mactable | |
1024 | pAd->MacTab.Content[Wcid].RXBAbitmap &= (~(1<<(pBAEntry->TID))); | |
1025 | pAd->MacTab.Content[Wcid].BARecWcidArray[TID] = 0; | |
1026 | ||
1027 | RTMP_DEL_BA_SESSION_FROM_ASIC(pAd, Wcid, TID); | |
1028 | ||
1029 | NdisReleaseSpinLock(&pAd->BATabLock); | |
1030 | ||
1031 | } | |
1032 | ||
1033 | BATableFreeRecEntry(pAd, Idx); | |
1034 | } | |
1035 | ||
1036 | VOID BASessionTearDownALL( | |
1037 | IN OUT PRTMP_ADAPTER pAd, | |
1038 | IN UCHAR Wcid) | |
1039 | { | |
1040 | int i; | |
1041 | ||
1042 | for (i=0; i<NUM_OF_TID; i++) | |
1043 | { | |
1044 | BAOriSessionTearDown(pAd, Wcid, i, FALSE, FALSE); | |
1045 | BARecSessionTearDown(pAd, Wcid, i, FALSE); | |
1046 | } | |
1047 | } | |
1048 | ||
1049 | ||
1050 | /* | |
1051 | ========================================================================== | |
1052 | Description: | |
1053 | Retry sending ADDBA Reqest. | |
1054 | ||
1055 | IRQL = DISPATCH_LEVEL | |
1056 | ||
1057 | Parametrs: | |
1058 | p8023Header: if this is already 802.3 format, p8023Header is NULL | |
1059 | ||
1060 | Return : TRUE if put into rx reordering buffer, shouldn't indicaterxhere. | |
1061 | FALSE , then continue indicaterx at this moment. | |
1062 | ========================================================================== | |
1063 | */ | |
1064 | VOID BAOriSessionSetupTimeout( | |
1065 | IN PVOID SystemSpecific1, | |
1066 | IN PVOID FunctionContext, | |
1067 | IN PVOID SystemSpecific2, | |
1068 | IN PVOID SystemSpecific3) | |
1069 | { | |
1070 | BA_ORI_ENTRY *pBAEntry = (BA_ORI_ENTRY *)FunctionContext; | |
1071 | MAC_TABLE_ENTRY *pEntry; | |
1072 | PRTMP_ADAPTER pAd; | |
1073 | ||
1074 | if (pBAEntry == NULL) | |
1075 | return; | |
1076 | ||
1077 | pAd = pBAEntry->pAdapter; | |
1078 | ||
1079 | #ifdef CONFIG_STA_SUPPORT | |
1080 | IF_DEV_CONFIG_OPMODE_ON_STA(pAd) | |
1081 | { | |
1082 | // Do nothing if monitor mode is on | |
1083 | if (MONITOR_ON(pAd)) | |
1084 | return; | |
1085 | } | |
1086 | #endif // CONFIG_STA_SUPPORT // | |
1087 | ||
1088 | #ifdef RALINK_ATE | |
1089 | // Nothing to do in ATE mode. | |
1090 | if (ATE_ON(pAd)) | |
1091 | return; | |
1092 | #endif // RALINK_ATE // | |
1093 | ||
1094 | pEntry = &pAd->MacTab.Content[pBAEntry->Wcid]; | |
1095 | ||
1096 | if ((pBAEntry->ORI_BA_Status == Originator_WaitRes) && (pBAEntry->Token < ORI_SESSION_MAX_RETRY)) | |
1097 | { | |
1098 | MLME_ADDBA_REQ_STRUCT AddbaReq; | |
1099 | ||
1100 | NdisZeroMemory(&AddbaReq, sizeof(AddbaReq)); | |
1101 | COPY_MAC_ADDR(AddbaReq.pAddr, pEntry->Addr); | |
1102 | AddbaReq.Wcid = (UCHAR)(pEntry->Aid); | |
1103 | AddbaReq.TID = pBAEntry->TID; | |
1104 | AddbaReq.BaBufSize = pAd->CommonCfg.BACapability.field.RxBAWinLimit; | |
1105 | AddbaReq.TimeOutValue = 0; | |
1106 | AddbaReq.Token = pBAEntry->Token; | |
1107 | MlmeEnqueue(pAd, ACTION_STATE_MACHINE, MT2_MLME_ADD_BA_CATE, sizeof(MLME_ADDBA_REQ_STRUCT), (PVOID)&AddbaReq); | |
1108 | RTMP_MLME_HANDLER(pAd); | |
1109 | DBGPRINT(RT_DEBUG_TRACE,("BA Ori Session Timeout(%d) : Send ADD BA again\n", pBAEntry->Token)); | |
1110 | ||
1111 | pBAEntry->Token++; | |
1112 | RTMPSetTimer(&pBAEntry->ORIBATimer, ORI_BA_SESSION_TIMEOUT); | |
1113 | } | |
1114 | else | |
1115 | { | |
1116 | BATableFreeOriEntry(pAd, pEntry->BAOriWcidArray[pBAEntry->TID]); | |
1117 | } | |
1118 | } | |
1119 | ||
1120 | /* | |
1121 | ========================================================================== | |
1122 | Description: | |
1123 | Retry sending ADDBA Reqest. | |
1124 | ||
1125 | IRQL = DISPATCH_LEVEL | |
1126 | ||
1127 | Parametrs: | |
1128 | p8023Header: if this is already 802.3 format, p8023Header is NULL | |
1129 | ||
1130 | Return : TRUE if put into rx reordering buffer, shouldn't indicaterxhere. | |
1131 | FALSE , then continue indicaterx at this moment. | |
1132 | ========================================================================== | |
1133 | */ | |
1134 | VOID BARecSessionIdleTimeout( | |
1135 | IN PVOID SystemSpecific1, | |
1136 | IN PVOID FunctionContext, | |
1137 | IN PVOID SystemSpecific2, | |
1138 | IN PVOID SystemSpecific3) | |
1139 | { | |
1140 | ||
1141 | BA_REC_ENTRY *pBAEntry = (BA_REC_ENTRY *)FunctionContext; | |
1142 | PRTMP_ADAPTER pAd; | |
1143 | ULONG Now32; | |
1144 | ||
1145 | if (pBAEntry == NULL) | |
1146 | return; | |
1147 | ||
1148 | if ((pBAEntry->REC_BA_Status == Recipient_Accept)) | |
1149 | { | |
1150 | NdisGetSystemUpTime(&Now32); | |
1151 | ||
1152 | if (RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer + REC_BA_SESSION_IDLE_TIMEOUT))) | |
1153 | { | |
1154 | pAd = pBAEntry->pAdapter; | |
1155 | // flush all pending reordering mpdus | |
1156 | ba_refresh_reordering_mpdus(pAd, pBAEntry); | |
1157 | DBGPRINT(RT_DEBUG_OFF, ("%ld: REC BA session Timeout\n", Now32)); | |
1158 | } | |
1159 | } | |
1160 | } | |
1161 | ||
1162 | ||
1163 | VOID PeerAddBAReqAction( | |
1164 | IN PRTMP_ADAPTER pAd, | |
1165 | IN MLME_QUEUE_ELEM *Elem) | |
1166 | ||
1167 | { | |
1168 | // 7.4.4.1 | |
1169 | //ULONG Idx; | |
1170 | UCHAR Status = 1; | |
1171 | UCHAR pAddr[6]; | |
1172 | FRAME_ADDBA_RSP ADDframe; | |
1173 | PUCHAR pOutBuffer = NULL; | |
1174 | NDIS_STATUS NStatus; | |
1175 | PFRAME_ADDBA_REQ pAddreqFrame = NULL; | |
1176 | //UCHAR BufSize; | |
1177 | ULONG FrameLen; | |
1178 | PULONG ptemp; | |
1179 | PMAC_TABLE_ENTRY pMacEntry; | |
1180 | ||
1181 | DBGPRINT(RT_DEBUG_TRACE, ("%s ==> (Wcid = %d)\n", __FUNCTION__, Elem->Wcid)); | |
1182 | ||
1183 | //hex_dump("AddBAReq", Elem->Msg, Elem->MsgLen); | |
1184 | ||
1185 | //ADDBA Request from unknown peer, ignore this. | |
1186 | if (Elem->Wcid >= MAX_LEN_OF_MAC_TABLE) | |
1187 | return; | |
1188 | ||
1189 | pMacEntry = &pAd->MacTab.Content[Elem->Wcid]; | |
1190 | DBGPRINT(RT_DEBUG_TRACE,("BA - PeerAddBAReqAction----> \n")); | |
1191 | ptemp = (PULONG)Elem->Msg; | |
1192 | //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))); | |
1193 | ||
1194 | if (PeerAddBAReqActionSanity(pAd, Elem->Msg, Elem->MsgLen, pAddr)) | |
1195 | { | |
1196 | ||
1197 | if ((pAd->CommonCfg.bBADecline == FALSE) && IS_HT_STA(pMacEntry)) | |
1198 | { | |
1199 | pAddreqFrame = (PFRAME_ADDBA_REQ)(&Elem->Msg[0]); | |
1200 | DBGPRINT(RT_DEBUG_OFF, ("Rcv Wcid(%d) AddBAReq\n", Elem->Wcid)); | |
1201 | if (BARecSessionAdd(pAd, &pAd->MacTab.Content[Elem->Wcid], pAddreqFrame)) | |
1202 | Status = 0; | |
1203 | else | |
1204 | Status = 38; // more parameters have invalid values | |
1205 | } | |
1206 | else | |
1207 | { | |
1208 | Status = 37; // the request has been declined. | |
1209 | } | |
1210 | } | |
1211 | ||
1212 | if (pAd->MacTab.Content[Elem->Wcid].ValidAsCLI) | |
1213 | ASSERT(pAd->MacTab.Content[Elem->Wcid].Sst == SST_ASSOC); | |
1214 | ||
1215 | pAddreqFrame = (PFRAME_ADDBA_REQ)(&Elem->Msg[0]); | |
1216 | // 2. Always send back ADDBA Response | |
1217 | NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory | |
1218 | if (NStatus != NDIS_STATUS_SUCCESS) | |
1219 | { | |
1220 | DBGPRINT(RT_DEBUG_TRACE,("ACTION - PeerBAAction() allocate memory failed \n")); | |
1221 | return; | |
1222 | } | |
1223 | ||
1224 | NdisZeroMemory(&ADDframe, sizeof(FRAME_ADDBA_RSP)); | |
1225 | // 2-1. Prepare ADDBA Response frame. | |
1226 | #ifdef CONFIG_STA_SUPPORT | |
1227 | IF_DEV_CONFIG_OPMODE_ON_STA(pAd) | |
1228 | { | |
1229 | if (ADHOC_ON(pAd)) | |
1230 | ActHeaderInit(pAd, &ADDframe.Hdr, pAddr, pAd->CurrentAddress, pAd->CommonCfg.Bssid); | |
1231 | else | |
1232 | #ifdef QOS_DLS_SUPPORT | |
1233 | if (pAd->MacTab.Content[Elem->Wcid].ValidAsDls) | |
1234 | ActHeaderInit(pAd, &ADDframe.Hdr, pAddr, pAd->CurrentAddress, pAd->CommonCfg.Bssid); | |
1235 | else | |
1236 | #endif // QOS_DLS_SUPPORT // | |
1237 | ActHeaderInit(pAd, &ADDframe.Hdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pAddr); | |
1238 | } | |
1239 | #endif // CONFIG_STA_SUPPORT // | |
1240 | ADDframe.Category = CATEGORY_BA; | |
1241 | ADDframe.Action = ADDBA_RESP; | |
1242 | ADDframe.Token = pAddreqFrame->Token; | |
1243 | // What is the Status code?? need to check. | |
1244 | ADDframe.StatusCode = Status; | |
1245 | ADDframe.BaParm.BAPolicy = IMMED_BA; | |
1246 | ADDframe.BaParm.AMSDUSupported = 0; | |
1247 | ADDframe.BaParm.TID = pAddreqFrame->BaParm.TID; | |
1248 | ADDframe.BaParm.BufSize = min(((UCHAR)pAddreqFrame->BaParm.BufSize), (UCHAR)pAd->CommonCfg.BACapability.field.RxBAWinLimit); | |
1249 | if (ADDframe.BaParm.BufSize == 0) | |
1250 | { | |
1251 | ADDframe.BaParm.BufSize = 64; | |
1252 | } | |
1253 | ADDframe.TimeOutValue = 0; //pAddreqFrame->TimeOutValue; | |
1254 | ||
1255 | *(USHORT *)(&ADDframe.BaParm) = cpu2le16(*(USHORT *)(&ADDframe.BaParm)); | |
1256 | ADDframe.StatusCode = cpu2le16(ADDframe.StatusCode); | |
1257 | ADDframe.TimeOutValue = cpu2le16(ADDframe.TimeOutValue); | |
1258 | ||
1259 | MakeOutgoingFrame(pOutBuffer, &FrameLen, | |
1260 | sizeof(FRAME_ADDBA_RSP), &ADDframe, | |
1261 | END_OF_ARGS); | |
1262 | MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); | |
1263 | MlmeFreeMemory(pAd, pOutBuffer); | |
1264 | ||
1265 | DBGPRINT(RT_DEBUG_TRACE, ("%s(%d): TID(%d), BufSize(%d) <== \n", __FUNCTION__, Elem->Wcid, ADDframe.BaParm.TID, | |
1266 | ADDframe.BaParm.BufSize)); | |
1267 | } | |
1268 | ||
1269 | ||
1270 | VOID PeerAddBARspAction( | |
1271 | IN PRTMP_ADAPTER pAd, | |
1272 | IN MLME_QUEUE_ELEM *Elem) | |
1273 | ||
1274 | { | |
1275 | //UCHAR Idx, i; | |
1276 | //PUCHAR pOutBuffer = NULL; | |
1277 | PFRAME_ADDBA_RSP pFrame = NULL; | |
1278 | //PBA_ORI_ENTRY pBAEntry; | |
1279 | ||
1280 | //ADDBA Response from unknown peer, ignore this. | |
1281 | if (Elem->Wcid >= MAX_LEN_OF_MAC_TABLE) | |
1282 | return; | |
1283 | ||
1284 | DBGPRINT(RT_DEBUG_TRACE, ("%s ==> Wcid(%d)\n", __FUNCTION__, Elem->Wcid)); | |
1285 | ||
1286 | //hex_dump("PeerAddBARspAction()", Elem->Msg, Elem->MsgLen); | |
1287 | ||
1288 | if (PeerAddBARspActionSanity(pAd, Elem->Msg, Elem->MsgLen)) | |
1289 | { | |
1290 | pFrame = (PFRAME_ADDBA_RSP)(&Elem->Msg[0]); | |
1291 | ||
1292 | DBGPRINT(RT_DEBUG_TRACE, ("\t\t StatusCode = %d\n", pFrame->StatusCode)); | |
1293 | switch (pFrame->StatusCode) | |
1294 | { | |
1295 | case 0: | |
1296 | // I want a BAsession with this peer as an originator. | |
1297 | BAOriSessionAdd(pAd, &pAd->MacTab.Content[Elem->Wcid], pFrame); | |
1298 | break; | |
1299 | default: | |
1300 | // check status == USED ??? | |
1301 | BAOriSessionTearDown(pAd, Elem->Wcid, pFrame->BaParm.TID, TRUE, FALSE); | |
1302 | break; | |
1303 | } | |
1304 | // Rcv Decline StatusCode | |
1305 | if ((pFrame->StatusCode == 37) | |
1306 | #ifdef CONFIG_STA_SUPPORT | |
1307 | || ((pAd->OpMode == OPMODE_STA) && STA_TGN_WIFI_ON(pAd) && (pFrame->StatusCode != 0)) | |
1308 | #endif // CONFIG_STA_SUPPORT // | |
1309 | ) | |
1310 | { | |
1311 | pAd->MacTab.Content[Elem->Wcid].BADeclineBitmap |= 1<<pFrame->BaParm.TID; | |
1312 | } | |
1313 | } | |
1314 | } | |
1315 | ||
1316 | VOID PeerDelBAAction( | |
1317 | IN PRTMP_ADAPTER pAd, | |
1318 | IN MLME_QUEUE_ELEM *Elem) | |
1319 | ||
1320 | { | |
1321 | //UCHAR Idx; | |
1322 | //PUCHAR pOutBuffer = NULL; | |
1323 | PFRAME_DELBA_REQ pDelFrame = NULL; | |
1324 | ||
1325 | DBGPRINT(RT_DEBUG_TRACE,("%s ==>\n", __FUNCTION__)); | |
1326 | //DELBA Request from unknown peer, ignore this. | |
1327 | if (PeerDelBAActionSanity(pAd, Elem->Wcid, Elem->Msg, Elem->MsgLen)) | |
1328 | { | |
1329 | pDelFrame = (PFRAME_DELBA_REQ)(&Elem->Msg[0]); | |
1330 | if (pDelFrame->DelbaParm.Initiator == ORIGINATOR) | |
1331 | { | |
1332 | DBGPRINT(RT_DEBUG_TRACE,("BA - PeerDelBAAction----> ORIGINATOR\n")); | |
1333 | BARecSessionTearDown(pAd, Elem->Wcid, pDelFrame->DelbaParm.TID, TRUE); | |
1334 | } | |
1335 | else | |
1336 | { | |
1337 | DBGPRINT(RT_DEBUG_TRACE,("BA - PeerDelBAAction----> RECIPIENT, Reason = %d\n", pDelFrame->ReasonCode)); | |
1338 | //hex_dump("DelBA Frame", pDelFrame, Elem->MsgLen); | |
1339 | BAOriSessionTearDown(pAd, Elem->Wcid, pDelFrame->DelbaParm.TID, TRUE, FALSE); | |
1340 | } | |
1341 | } | |
1342 | } | |
1343 | ||
1344 | ||
1345 | BOOLEAN CntlEnqueueForRecv( | |
1346 | IN PRTMP_ADAPTER pAd, | |
1347 | IN ULONG Wcid, | |
1348 | IN ULONG MsgLen, | |
1349 | IN PFRAME_BA_REQ pMsg) | |
1350 | { | |
1351 | PFRAME_BA_REQ pFrame = pMsg; | |
1352 | //PRTMP_REORDERBUF pBuffer; | |
1353 | //PRTMP_REORDERBUF pDmaBuf; | |
1354 | PBA_REC_ENTRY pBAEntry; | |
1355 | //BOOLEAN Result; | |
1356 | ULONG Idx; | |
1357 | //UCHAR NumRxPkt; | |
1358 | UCHAR TID;//, i; | |
1359 | ||
1360 | TID = (UCHAR)pFrame->BARControl.TID; | |
1361 | ||
1362 | DBGPRINT(RT_DEBUG_TRACE, ("%s(): BAR-Wcid(%ld), Tid (%d)\n", __FUNCTION__, Wcid, TID)); | |
1363 | //hex_dump("BAR", (PCHAR) pFrame, MsgLen); | |
1364 | // Do nothing if the driver is starting halt state. | |
1365 | // This might happen when timer already been fired before cancel timer with mlmehalt | |
1366 | if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)) | |
1367 | return FALSE; | |
1368 | ||
1369 | // First check the size, it MUST not exceed the mlme queue size | |
1370 | if (MsgLen > MGMT_DMA_BUFFER_SIZE) | |
1371 | { | |
1372 | DBGPRINT_ERR(("CntlEnqueueForRecv: frame too large, size = %ld \n", MsgLen)); | |
1373 | return FALSE; | |
1374 | } | |
1375 | else if (MsgLen != sizeof(FRAME_BA_REQ)) | |
1376 | { | |
1377 | DBGPRINT_ERR(("CntlEnqueueForRecv: BlockAck Request frame length size = %ld incorrect\n", MsgLen)); | |
1378 | return FALSE; | |
1379 | } | |
1380 | else if (MsgLen != sizeof(FRAME_BA_REQ)) | |
1381 | { | |
1382 | DBGPRINT_ERR(("CntlEnqueueForRecv: BlockAck Request frame length size = %ld incorrect\n", MsgLen)); | |
1383 | return FALSE; | |
1384 | } | |
1385 | ||
1386 | if ((Wcid < MAX_LEN_OF_MAC_TABLE) && (TID < 8)) | |
1387 | { | |
1388 | // if this receiving packet is from SA that is in our OriEntry. Since WCID <9 has direct mapping. no need search. | |
1389 | Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID]; | |
1390 | pBAEntry = &pAd->BATable.BARecEntry[Idx]; | |
1391 | } | |
1392 | else | |
1393 | { | |
1394 | return FALSE; | |
1395 | } | |
1396 | ||
1397 | DBGPRINT(RT_DEBUG_TRACE, ("BAR(%ld) : Tid (%d) - %04x:%04x\n", Wcid, TID, pFrame->BAStartingSeq.field.StartSeq, pBAEntry->LastIndSeq )); | |
1398 | ||
1399 | if (SEQ_SMALLER(pBAEntry->LastIndSeq, pFrame->BAStartingSeq.field.StartSeq, MAXSEQ)) | |
1400 | { | |
1401 | //DBGPRINT(RT_DEBUG_TRACE, ("BAR Seq = %x, LastIndSeq = %x\n", pFrame->BAStartingSeq.field.StartSeq, pBAEntry->LastIndSeq)); | |
1402 | ba_indicate_reordering_mpdus_le_seq(pAd, pBAEntry, pFrame->BAStartingSeq.field.StartSeq); | |
1403 | pBAEntry->LastIndSeq = (pFrame->BAStartingSeq.field.StartSeq == 0) ? MAXSEQ :(pFrame->BAStartingSeq.field.StartSeq -1); | |
1404 | } | |
1405 | //ba_refresh_reordering_mpdus(pAd, pBAEntry); | |
1406 | return TRUE; | |
1407 | } | |
1408 | ||
1409 | /* | |
1410 | Description : Send PSMP Action frame If PSMP mode switches. | |
1411 | */ | |
1412 | VOID SendPSMPAction( | |
1413 | IN PRTMP_ADAPTER pAd, | |
1414 | IN UCHAR Wcid, | |
1415 | IN UCHAR Psmp) | |
1416 | { | |
1417 | PUCHAR pOutBuffer = NULL; | |
1418 | NDIS_STATUS NStatus; | |
1419 | //ULONG Idx; | |
1420 | FRAME_PSMP_ACTION Frame; | |
1421 | ULONG FrameLen; | |
1422 | ||
1423 | NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory | |
1424 | if (NStatus != NDIS_STATUS_SUCCESS) | |
1425 | { | |
1426 | DBGPRINT(RT_DEBUG_ERROR,("BA - MlmeADDBAAction() allocate memory failed \n")); | |
1427 | return; | |
1428 | } | |
1429 | #ifdef CONFIG_STA_SUPPORT | |
1430 | IF_DEV_CONFIG_OPMODE_ON_STA(pAd) | |
1431 | ActHeaderInit(pAd, &Frame.Hdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pAd->MacTab.Content[Wcid].Addr); | |
1432 | #endif // CONFIG_STA_SUPPORT // | |
1433 | ||
1434 | Frame.Category = CATEGORY_HT; | |
1435 | Frame.Action = SMPS_ACTION; | |
1436 | switch (Psmp) | |
1437 | { | |
1438 | case MMPS_ENABLE: | |
1439 | #ifdef RT30xx | |
1440 | if (IS_RT30xx(pAd) | |
1441 | &&(pAd->Antenna.field.RxPath>1||pAd->Antenna.field.TxPath>1)) | |
1442 | { | |
1443 | RTMP_ASIC_MMPS_DISABLE(pAd); | |
1444 | } | |
1445 | #endif // RT30xx // | |
1446 | Frame.Psmp = 0; | |
1447 | break; | |
1448 | case MMPS_DYNAMIC: | |
1449 | Frame.Psmp = 3; | |
1450 | break; | |
1451 | case MMPS_STATIC: | |
1452 | #ifdef RT30xx | |
1453 | if (IS_RT30xx(pAd) | |
1454 | &&(pAd->Antenna.field.RxPath>1||pAd->Antenna.field.TxPath>1)) | |
1455 | { | |
1456 | RTMP_ASIC_MMPS_ENABLE(pAd); | |
1457 | } | |
1458 | #endif // RT30xx // | |
1459 | Frame.Psmp = 1; | |
1460 | break; | |
1461 | } | |
1462 | MakeOutgoingFrame(pOutBuffer, &FrameLen, | |
1463 | sizeof(FRAME_PSMP_ACTION), &Frame, | |
1464 | END_OF_ARGS); | |
1465 | MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); | |
1466 | MlmeFreeMemory(pAd, pOutBuffer); | |
1467 | DBGPRINT(RT_DEBUG_ERROR,("HT - SendPSMPAction( %d ) \n", Frame.Psmp)); | |
1468 | } | |
1469 | ||
1470 | ||
1471 | #define RADIO_MEASUREMENT_REQUEST_ACTION 0 | |
1472 | ||
1473 | typedef struct PACKED | |
1474 | { | |
1475 | UCHAR RegulatoryClass; | |
1476 | UCHAR ChannelNumber; | |
1477 | USHORT RandomInterval; | |
1478 | USHORT MeasurementDuration; | |
1479 | UCHAR MeasurementMode; | |
1480 | UCHAR BSSID[MAC_ADDR_LEN]; | |
1481 | UCHAR ReportingCondition; | |
1482 | UCHAR Threshold; | |
1483 | UCHAR SSIDIE[2]; // 2 byte | |
1484 | } BEACON_REQUEST; | |
1485 | ||
1486 | typedef struct PACKED | |
1487 | { | |
1488 | UCHAR ID; | |
1489 | UCHAR Length; | |
1490 | UCHAR Token; | |
1491 | UCHAR RequestMode; | |
1492 | UCHAR Type; | |
1493 | } MEASUREMENT_REQ; | |
1494 | ||
1495 | ||
1496 | ||
1497 | ||
1498 | void convert_reordering_packet_to_preAMSDU_or_802_3_packet( | |
1499 | IN PRTMP_ADAPTER pAd, | |
1500 | IN RX_BLK *pRxBlk, | |
1501 | IN UCHAR FromWhichBSSID) | |
1502 | { | |
1503 | PNDIS_PACKET pRxPkt; | |
1504 | UCHAR Header802_3[LENGTH_802_3]; | |
1505 | ||
1506 | // 1. get 802.3 Header | |
1507 | // 2. remove LLC | |
1508 | // a. pointer pRxBlk->pData to payload | |
1509 | // b. modify pRxBlk->DataSize | |
1510 | ||
1511 | #ifdef CONFIG_STA_SUPPORT | |
1512 | IF_DEV_CONFIG_OPMODE_ON_STA(pAd) | |
1513 | RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3); | |
1514 | #endif // CONFIG_STA_SUPPORT // | |
1515 | ||
1516 | ASSERT(pRxBlk->pRxPacket); | |
1517 | pRxPkt = RTPKT_TO_OSPKT(pRxBlk->pRxPacket); | |
1518 | ||
1519 | SET_OS_PKT_NETDEV(pRxPkt, get_netdev_from_bssid(pAd, FromWhichBSSID)); | |
1520 | SET_OS_PKT_DATAPTR(pRxPkt, pRxBlk->pData); | |
1521 | SET_OS_PKT_LEN(pRxPkt, pRxBlk->DataSize); | |
1522 | SET_OS_PKT_DATATAIL(pRxPkt, pRxBlk->pData, pRxBlk->DataSize); | |
1523 | ||
1524 | // | |
1525 | // copy 802.3 header, if necessary | |
1526 | // | |
1527 | if (!RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU)) | |
1528 | { | |
1529 | ||
1530 | #ifdef CONFIG_STA_SUPPORT | |
1531 | IF_DEV_CONFIG_OPMODE_ON_STA(pAd) | |
1532 | { | |
1533 | #ifdef LINUX | |
1534 | NdisMoveMemory(skb_push(pRxPkt, LENGTH_802_3), Header802_3, LENGTH_802_3); | |
1535 | #endif | |
1536 | } | |
1537 | #endif // CONFIG_STA_SUPPORT // | |
1538 | } | |
1539 | } | |
1540 | ||
1541 | ||
1542 | #define INDICATE_LEGACY_OR_AMSDU(_pAd, _pRxBlk, _fromWhichBSSID) \ | |
1543 | do \ | |
1544 | { \ | |
1545 | if (RX_BLK_TEST_FLAG(_pRxBlk, fRX_AMSDU)) \ | |
1546 | { \ | |
1547 | Indicate_AMSDU_Packet(_pAd, _pRxBlk, _fromWhichBSSID); \ | |
1548 | } \ | |
1549 | else if (RX_BLK_TEST_FLAG(_pRxBlk, fRX_EAP)) \ | |
1550 | { \ | |
1551 | Indicate_EAPOL_Packet(_pAd, _pRxBlk, _fromWhichBSSID); \ | |
1552 | } \ | |
1553 | else \ | |
1554 | { \ | |
1555 | Indicate_Legacy_Packet(_pAd, _pRxBlk, _fromWhichBSSID); \ | |
1556 | } \ | |
1557 | } while (0); | |
1558 | ||
1559 | ||
1560 | ||
1561 | static VOID ba_enqueue_reordering_packet( | |
1562 | IN PRTMP_ADAPTER pAd, | |
1563 | IN PBA_REC_ENTRY pBAEntry, | |
1564 | IN RX_BLK *pRxBlk, | |
1565 | IN UCHAR FromWhichBSSID) | |
1566 | { | |
1567 | struct reordering_mpdu *mpdu_blk; | |
1568 | UINT16 Sequence = (UINT16) pRxBlk->pHeader->Sequence; | |
1569 | ||
1570 | mpdu_blk = ba_mpdu_blk_alloc(pAd); | |
1571 | if ((mpdu_blk != NULL) && | |
1572 | (!RX_BLK_TEST_FLAG(pRxBlk, fRX_EAP))) | |
1573 | { | |
1574 | // Write RxD buffer address & allocated buffer length | |
1575 | NdisAcquireSpinLock(&pBAEntry->RxReRingLock); | |
1576 | ||
1577 | mpdu_blk->Sequence = Sequence; | |
1578 | ||
1579 | mpdu_blk->bAMSDU = RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU); | |
1580 | ||
1581 | convert_reordering_packet_to_preAMSDU_or_802_3_packet(pAd, pRxBlk, FromWhichBSSID); | |
1582 | ||
1583 | STATS_INC_RX_PACKETS(pAd, FromWhichBSSID); | |
1584 | ||
1585 | // | |
1586 | // it is necessary for reordering packet to record | |
1587 | // which BSS it come from | |
1588 | // | |
1589 | RTMP_SET_PACKET_IF(pRxBlk->pRxPacket, FromWhichBSSID); | |
1590 | ||
1591 | mpdu_blk->pPacket = pRxBlk->pRxPacket; | |
1592 | ||
1593 | if (ba_reordering_mpdu_insertsorted(&pBAEntry->list, mpdu_blk) == FALSE) | |
1594 | { | |
1595 | // had been already within reordering list | |
1596 | // don't indicate | |
1597 | RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_SUCCESS); | |
1598 | ba_mpdu_blk_free(pAd, mpdu_blk); | |
1599 | } | |
1600 | ||
1601 | ASSERT((0<= pBAEntry->list.qlen) && (pBAEntry->list.qlen <= pBAEntry->BAWinSize)); | |
1602 | NdisReleaseSpinLock(&pBAEntry->RxReRingLock); | |
1603 | } | |
1604 | else | |
1605 | { | |
1606 | DBGPRINT(RT_DEBUG_ERROR, ("!!! (%d) Can't allocate reordering mpdu blk\n", | |
1607 | pBAEntry->list.qlen)); | |
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 | // release packet | |
1656 | RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); | |
1657 | return; | |
1658 | } | |
1659 | ||
1660 | ||
1661 | ||
1662 | if (Wcid < MAX_LEN_OF_MAC_TABLE) | |
1663 | { | |
1664 | Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID]; | |
1665 | if (Idx == 0) | |
1666 | { | |
1667 | /* Rec BA Session had been torn down */ | |
1668 | INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID); | |
1669 | return; | |
1670 | } | |
1671 | pBAEntry = &pAd->BATable.BARecEntry[Idx]; | |
1672 | } | |
1673 | else | |
1674 | { | |
1675 | // impossible !!! | |
1676 | ASSERT(0); | |
1677 | // release packet | |
1678 | RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); | |
1679 | return; | |
1680 | } | |
1681 | ||
1682 | ASSERT(pBAEntry); | |
1683 | ||
1684 | // update last rx time | |
1685 | NdisGetSystemUpTime(&Now32); | |
1686 | ||
1687 | pBAEntry->rcvSeq = Sequence; | |
1688 | ||
1689 | ||
1690 | ba_flush_reordering_timeout_mpdus(pAd, pBAEntry, Now32); | |
1691 | pBAEntry->LastIndSeqAtTimer = Now32; | |
1692 | ||
1693 | // | |
1694 | // Reset Last Indicate Sequence | |
1695 | // | |
1696 | if (pBAEntry->LastIndSeq == RESET_RCV_SEQ) | |
1697 | { | |
1698 | ASSERT((pBAEntry->list.qlen == 0) && (pBAEntry->list.next == NULL)); | |
1699 | ||
1700 | // reset rcv sequence of BA session | |
1701 | pBAEntry->LastIndSeq = Sequence; | |
1702 | pBAEntry->LastIndSeqAtTimer = Now32; | |
1703 | INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID); | |
1704 | return; | |
1705 | } | |
1706 | ||
1707 | // | |
1708 | // I. Check if in order. | |
1709 | // | |
1710 | if (SEQ_STEPONE(Sequence, pBAEntry->LastIndSeq, MAXSEQ)) | |
1711 | { | |
1712 | USHORT LastIndSeq; | |
1713 | ||
1714 | pBAEntry->LastIndSeq = Sequence; | |
1715 | INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, FromWhichBSSID); | |
1716 | LastIndSeq = ba_indicate_reordering_mpdus_in_order(pAd, pBAEntry, pBAEntry->LastIndSeq); | |
1717 | if (LastIndSeq != RESET_RCV_SEQ) | |
1718 | { | |
1719 | pBAEntry->LastIndSeq = LastIndSeq; | |
1720 | } | |
1721 | pBAEntry->LastIndSeqAtTimer = Now32; | |
1722 | } | |
1723 | // | |
1724 | // II. Drop Duplicated Packet | |
1725 | // | |
1726 | else if (Sequence == pBAEntry->LastIndSeq) | |
1727 | { | |
1728 | ||
1729 | // drop and release packet | |
1730 | pBAEntry->nDropPacket++; | |
1731 | RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); | |
1732 | } | |
1733 | // | |
1734 | // III. Drop Old Received Packet | |
1735 | // | |
1736 | else if (SEQ_SMALLER(Sequence, pBAEntry->LastIndSeq, MAXSEQ)) | |
1737 | { | |
1738 | ||
1739 | // drop and release packet | |
1740 | pBAEntry->nDropPacket++; | |
1741 | RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); | |
1742 | } | |
1743 | // | |
1744 | // IV. Receive Sequence within Window Size | |
1745 | // | |
1746 | else if (SEQ_SMALLER(Sequence, (((pBAEntry->LastIndSeq+pBAEntry->BAWinSize+1)) & MAXSEQ), MAXSEQ)) | |
1747 | { | |
1748 | ba_enqueue_reordering_packet(pAd, pBAEntry, pRxBlk, FromWhichBSSID); | |
1749 | } | |
1750 | // | |
1751 | // V. Receive seq surpasses Win(lastseq + nMSDU). So refresh all reorder buffer | |
1752 | // | |
1753 | else | |
1754 | { | |
1755 | LONG WinStartSeq, TmpSeq; | |
1756 | ||
1757 | ||
1758 | TmpSeq = Sequence - (pBAEntry->BAWinSize) -1; | |
1759 | if (TmpSeq < 0) | |
1760 | { | |
1761 | TmpSeq = (MAXSEQ+1) + TmpSeq; | |
1762 | } | |
1763 | WinStartSeq = (TmpSeq+1) & MAXSEQ; | |
1764 | ba_indicate_reordering_mpdus_le_seq(pAd, pBAEntry, WinStartSeq); | |
1765 | pBAEntry->LastIndSeq = WinStartSeq; //TmpSeq; | |
1766 | ||
1767 | pBAEntry->LastIndSeqAtTimer = Now32; | |
1768 | ||
1769 | ba_enqueue_reordering_packet(pAd, pBAEntry, pRxBlk, FromWhichBSSID); | |
1770 | ||
1771 | TmpSeq = ba_indicate_reordering_mpdus_in_order(pAd, pBAEntry, pBAEntry->LastIndSeq); | |
1772 | if (TmpSeq != RESET_RCV_SEQ) | |
1773 | { | |
1774 | pBAEntry->LastIndSeq = TmpSeq; | |
1775 | } | |
1776 | } | |
1777 | } | |
1778 | ||
1779 | #endif // DOT11_N_SUPPORT // |