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