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