• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * RxQueue.c
3  *
4  * Copyright(c) 1998 - 2009 Texas Instruments. All rights reserved.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  *  * Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  *  * Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in
15  *    the documentation and/or other materials provided with the
16  *    distribution.
17  *  * Neither the name Texas Instruments nor the names of its
18  *    contributors may be used to endorse or promote products derived
19  *    from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 
35 /** \file   RxQueue.c
36  *  \brief  RX Queue module that responsible to support re-ordering of received packets to upper layers.
37  *
38  *  \see    RxQueue.h
39  */
40 #define __FILE_ID__  FILE_ID_98
41 #include "tidef.h"
42 #include "osApi.h"
43 #include "report.h"
44 #include "RxBuf.h"
45 #include "TWDriver.h"
46 #include "public_descriptors.h"
47 
48 /************************ static definition declaration *****************************/
49 #define RX_QUEUE_ARRAY_SIZE		                            8
50 #define RX_QUEUE_ARRAY_SIZE_BIT_MASK                        0x7 /* RX_QUEUE_ARRAY_SIZE -1 */
51 #define RX_QUEUE_WIN_SIZE		                            RX_QUEUE_ARRAY_SIZE
52 
53 #define BA_SESSION_IS_A_BIGGER_THAN_B(A,B)       (((((A)-(B)) & 0xFFF) < 0x7FF) && ((A)!=(B)))
54 #define BA_SESSION_IS_A_BIGGER_EQUAL_THAN_B(A,B) (((((A)-(B)) & 0xFFF) < 0x7FF))
55 #define SEQ_NUM_WRAP 0x1000
56 #define SEQ_NUM_MASK 0xFFF
57 
58 
59 /************************ static structures declaration *****************************/
60 /* structure describe one entry of save packet information in the packet queue array */
61 typedef struct
62 {
63     void                *pPacket;	/* Packet address of the packet */
64     TI_STATUS	        tStatus;	/* RxXfer status. */
65     TI_UINT16           uFrameSn;
66 } TRxQueuePacketEntry;
67 
68 /* structure describe set of data that one Tid, also including the arras himself */
69 typedef struct
70 {
71     /* array packets Entries */
72     TRxQueuePacketEntry aPaketsQueue [RX_QUEUE_ARRAY_SIZE];
73     /* TID BA state */
74     TI_BOOL	            aTidBaEstablished;
75     /* index that winStar point on */
76     TI_UINT32 	        aWinStartArrayInex;
77     /* windows size */
78     TI_UINT32	        aTidWinSize;
79 	/* expected sequence number (ESN) */
80     TI_UINT16	        aTidExpectedSn;
81 } TRxQueueTidDataBase;
82 
83 /* structure describe set of data that assist of manage one SA RxQueue arrays */
84 typedef struct
85 {
86     TRxQueueTidDataBase tSa1ArrayMng [MAX_NUM_OF_802_1d_TAGS];
87 } TRxQueueArraysMng;
88 
89 /* main RxQueue structure in order to management the packets disordered array. */
90 typedef struct
91 {
92     TI_HANDLE           hOs;                        /* OS handler */
93     TI_HANDLE           hReport;                    /* Report handler */
94     TRxQueueArraysMng   tRxQueueArraysMng;          /* manage each Source Address RxQueue arrays */
95     TPacketReceiveCb    tReceivePacketCB;           /* Receive packets CB address */
96     TI_HANDLE           hReceivePacketCB_handle;    /* Receive packets CB handler */
97 
98 } TRxQueue;
99 
100 /************************ static function declaration *****************************/
101 static TI_STATUS RxQueue_PassPacket (TI_HANDLE hRxQueue, TI_STATUS tStatus, const void *pBuffer);
102 
103 /**
104  * \fn     RxQueue_Create()
105  * \brief  Create the RxQueue module.
106  *
107  * Allocate and clear the RxQueue module object.
108  *
109  * \param  hOs - Handle to Os Abstraction Layer
110  * \return Handle of the allocated object
111  * \sa     RxQueue_Destroy
112  */
RxQueue_Create(TI_HANDLE hOs)113 TI_HANDLE RxQueue_Create (TI_HANDLE hOs)
114 {
115 	TRxQueue *pRxQueue;
116 
117 	/* allocate module object */
118 	pRxQueue = os_memoryAlloc (hOs, sizeof(TRxQueue));
119 
120 	if (!pRxQueue)
121 	{
122 		WLAN_OS_REPORT (("RxQueue_Create():  Allocation failed!!\n"));
123 		return NULL;
124 	}
125 
126     os_memoryZero (hOs, pRxQueue, (sizeof(TRxQueue)));
127 
128     pRxQueue->hOs = hOs;
129 
130 	return (pRxQueue);
131 }
132 
133 
134 /**
135  * \fn     RxQueue_Destroy()
136  * \brief  Destroy the module.
137  *
138  * Free the module's queues and object.
139  *
140  * \param  hRxQueue - The module object
141  * \return TI_OK on success or TI_NOK on failure
142  * \sa     RxQueue_Create
143  */
RxQueue_Destroy(TI_HANDLE hRxQueue)144 TI_STATUS RxQueue_Destroy (TI_HANDLE hRxQueue)
145 {
146     TRxQueue *pRxQueue = (TRxQueue *)hRxQueue;
147 
148     /* free module object */
149 	os_memoryFree (pRxQueue->hOs, pRxQueue, sizeof(TRxQueue));
150 
151     return TI_OK;
152 }
153 
154 
155 /**
156  * \fn     RxQueue_Init()
157  * \brief  Init required handles
158  *
159  * Init required handles and module variables.
160  *
161  * \note
162  * \param  hRxQueue - The module object
163  * \param  hReport - Report module Handles
164  * \return TI_OK on success or TI_NOK on failure
165  * \sa
166  */
RxQueue_Init(TI_HANDLE hRxQueue,TI_HANDLE hReport)167 TI_STATUS RxQueue_Init (TI_HANDLE hRxQueue, TI_HANDLE hReport)
168 {
169 	TRxQueue *pRxQueue = (TRxQueue *)hRxQueue;
170 
171     pRxQueue->hReport   = hReport;
172 
173 	return TI_OK;
174 }
175 
176 
177 /**
178  * \fn     RxQueue_Register_CB()
179  * \brief  Register the function to be called for received Rx.
180  *
181  * \note
182  * \param  hRxQueue - The module object
183  * \param  CallBackID - event ID
184  * \param  CBFunc - function address.
185  * \param  CBObj - function parameter.
186  * \return TI_OK on success or TI_NOK on failure
187  * \sa
188  */
RxQueue_Register_CB(TI_HANDLE hRxQueue,TI_UINT32 uCallBackID,void * CBFunc,TI_HANDLE CBObj)189 void RxQueue_Register_CB (TI_HANDLE hRxQueue, TI_UINT32 uCallBackID, void *CBFunc, TI_HANDLE CBObj)
190 {
191     TRxQueue* pRxQueue = (TRxQueue *)hRxQueue;
192 
193     TRACE1(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION , "RxQueue_Register_CB: CallBack ID = 0x%x\n", uCallBackID);
194 
195     switch(uCallBackID)
196     {
197     case TWD_INT_RECEIVE_PACKET:
198         pRxQueue->tReceivePacketCB = (TPacketReceiveCb)CBFunc;
199         pRxQueue->hReceivePacketCB_handle = CBObj;
200         break;
201 
202     default:
203         TRACE0(pRxQueue->hReport, REPORT_SEVERITY_ERROR , "RxQueue_Register_CB: Illegal value\n");
204         break;
205     }
206 }
207 
208 /**
209  * \fn     RxQueue_CloseBaSession ()
210  * \brief  Close BA session receiver and pass all packets in the TID queue to upper layer.
211  *
212  * \note
213  * \param  hRxQueue - RxQueue handle.
214  * \param  uFrameTid - TID session.
215  * \return None
216  * \sa
217  */
RxQueue_CloseBaSession(TI_HANDLE hRxQueue,TI_UINT8 uFrameTid)218 void RxQueue_CloseBaSession(TI_HANDLE hRxQueue, TI_UINT8 uFrameTid)
219 {
220     TRxQueue            *pRxQueue     = (TRxQueue *)hRxQueue;
221     TI_UINT32            i;
222     /*set the SA Tid pointer */
223     TRxQueueTidDataBase *pTidDataBase = &(pRxQueue->tRxQueueArraysMng.tSa1ArrayMng[uFrameTid]);
224 
225     /* TID illegal value ? */
226     if (uFrameTid >= MAX_NUM_OF_802_1d_TAGS)
227     {
228         TRACE1(pRxQueue->hReport, REPORT_SEVERITY_ERROR , "RxQueue_CloseBaSession: BA event - DELBA frame with TID value too big, TID = %d\n", uFrameTid);
229 
230         return;
231     }
232 
233     if(pTidDataBase->aTidBaEstablished == TI_TRUE)
234     {
235         /* clean BA session */
236         pTidDataBase->aTidBaEstablished = TI_FALSE;
237 
238         /* pass all valid entries at the array */
239         for (i = 0; (i < RX_QUEUE_ARRAY_SIZE) && (i < RX_QUEUE_WIN_SIZE); i++)
240         {
241             if (pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket != NULL)
242             {
243                 RxQueue_PassPacket (pRxQueue,
244                                     pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].tStatus,
245                                     pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket);
246 
247                 pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket = NULL;
248             }
249 
250             pTidDataBase->aWinStartArrayInex ++;
251 
252             /* aWinStartArrayInex % RX_QUEUE_ARRAY_SIZE */
253             pTidDataBase->aWinStartArrayInex &= RX_QUEUE_ARRAY_SIZE_BIT_MASK;
254         }
255     }
256 }
257 
258 
259 /**
260  * \fn     RxQueue_PassPacket()
261  * \brief  Responsible on decode packet parameters and pass it to upper layer.
262  *
263  * \note
264  * \param  hRxQueue - RxQueue handle.
265  * \param  aStatus - RxXfer status that indicate if the upper layer should free the packet or use it.
266  * \param  pFrame - paket address of the packet
267  * \param  pRxParams - address to structure of the Rx Descriptor received by FW.
268  * \return TI_OK on success or TI_NOK on failure
269  * \sa
270  */
RxQueue_PassPacket(TI_HANDLE hRxQueue,TI_STATUS tStatus,const void * pBuffer)271 static TI_STATUS RxQueue_PassPacket (TI_HANDLE hRxQueue, TI_STATUS tStatus, const void *pBuffer)
272 {
273 
274     TRxQueue            *pRxQueue   = (TRxQueue *)hRxQueue;
275 
276     if (tStatus == TI_OK)
277     {
278         /* Get the mac header location in the packet Buffer */
279         dot11_header_t *pMacHdr = (dot11_header_t *)(TI_UINT8*)RX_BUF_DATA(pBuffer);
280 
281         /* Handle endian for the frame control fields */
282         pMacHdr->fc  = ENDIAN_HANDLE_WORD(pMacHdr->fc);
283         pMacHdr->duration = ENDIAN_HANDLE_WORD(pMacHdr->duration);
284         pMacHdr->seqCtrl = ENDIAN_HANDLE_WORD(pMacHdr->seqCtrl);
285     }
286     else
287     {
288         RxIfDescriptor_t    *pRxParams  = (RxIfDescriptor_t*)pBuffer;
289 
290         pRxParams->status &= ~RX_DESC_STATUS_MASK;
291         pRxParams->status |= RX_DESC_STATUS_DRIVER_RX_Q_FAIL;
292     }
293 
294     TRACE0(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION , "RxQueue_PassPacket: call TWD_OWNER_RX_QUEUE CB. In std rxData_ReceivePacket()\n");
295 
296     /* Set the packet to upper layer */
297     /* if the packet status not success it will be discarded */
298     pRxQueue->tReceivePacketCB (pRxQueue->hReceivePacketCB_handle, pBuffer);
299 
300     return TI_OK;
301 }
302 
303 
304 /**
305  * \fn     RxQueue_ReceivePacket()
306  * \brief  Main function of the RxQueue module.
307  * Responsible on reorder of the packets from the RxXfer to the RX module.
308  * Call from RxXfer in order to pass packet to uppers layers.
309  * In order to save disordered packets the module use array of structures per TID
310  * that each entry describe a packet. The array elements is sorted in the way that
311  * the winStart array index represent always the winStar packet and the lowest SN.
312  * Each increment index represent index at the BA window. Array index winEnd  always
313  * represent winEnd packet. The indexes of winStart and winEnd handled in cyclic manner.
314  * The function functionality devided to parts:
315  *   Part 1:
316  * in case the modulo receive packet with SN equal to winStart:
317  * "	pass it to upper layers
318  * "	increases winStart and array index winStart
319  * "	validate that all sequential queue packet are pass to the upper layers.
320  *   Part 2:
321  * in case the modulo receive packet that SN between winStart to winEnd:
322  * "	Save it sorted at the array at index: Save index = ((SN - winStart) + index array winStart) % arraySize.
323  *   Part 3:
324  * in case the modulo receive packet that SN higher then winEnd:
325  * "	Update winStart and WinEnd.
326  * "	Save it sorted at the array in index winEnd index.
327  * "	Pass to the upper layers all packets at the array indexes from old winStart index to the updated winStart index.
328  *   Part 4 + 5:
329  * in case the modulo receive BA event packet:
330  * "	Update winStart and WinEnd
331  * "	Pass to the upper layers all packets at the array indexes from old winStart index to the updated winStart index.
332  * "	Free BA event packet via pass it to upper layers with error status.
333  *
334  * \note
335  * \param  hRxQueue - RxQueue handle.
336  * \param  aStatus - RxXfer status that indicate if the upper layer should free the packet or use it.
337  * \param  pBuffer - paket address of the packet
338  * \return None
339  * \sa
340  */
RxQueue_ReceivePacket(TI_HANDLE hRxQueue,const void * pBuffer)341 void RxQueue_ReceivePacket (TI_HANDLE hRxQueue, const void * pBuffer)
342 {
343     TRxQueue            *pRxQueue   = (TRxQueue *)hRxQueue;
344     RxIfDescriptor_t    *pRxParams  = (RxIfDescriptor_t*)pBuffer;
345     TI_UINT8            *pFrame     = RX_BUF_DATA((TI_UINT8 *)pBuffer);
346     TI_STATUS           tStatus     = TI_OK;
347     dot11_header_t      *pHdr       = (dot11_header_t *)pFrame;
348     TI_UINT16		    uQosControl;
349 
350     COPY_WLAN_WORD(&uQosControl, &pHdr->qosControl); /* copy with endianess handling. */
351 
352     /*
353      * Retrieving the TAG from the packet itself and not from the Rx Descriptor since by now it is not correct
354      * Note: in the DR TAG_CLASS_EAPOL packet handled as TAG_CLASS_QOS_DATA
355      */
356     if (IS_QOS_FRAME(*(TI_UINT16*)pFrame) && (pRxParams->packet_class_tag != TAG_CLASS_QOS_DATA) && (pRxParams->packet_class_tag != TAG_CLASS_AMSDU))
357 	{
358         TRACE1(pRxQueue->hReport, REPORT_SEVERITY_WARNING, "RxQueue_ReceivePacket: BAD CLASS TAG =0x%x from FW.\n", pRxParams->packet_class_tag);
359 
360         /* Get AMSDU bit from frame */
361         if( uQosControl & DOT11_QOS_CONTROL_FIELD_A_MSDU_BITS)
362         {
363             pRxParams->packet_class_tag = TAG_CLASS_AMSDU;
364         }
365         else
366         {
367             pRxParams->packet_class_tag = TAG_CLASS_QOS_DATA;
368         }
369     }
370 
371     /*
372      * packet doesn't need reorder ?
373      */
374     if ((pRxParams->packet_class_tag != TAG_CLASS_QOS_DATA) && (pRxParams->packet_class_tag != TAG_CLASS_BA_EVENT) && (pRxParams->packet_class_tag != TAG_CLASS_AMSDU))
375     {
376         TRACE0(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: pass packet without reorder.\n");
377 
378         RxQueue_PassPacket (pRxQueue, tStatus, pBuffer);
379 
380         return;
381     }
382 
383 
384     /*
385      * pRxParams->type == TAG_CLASS_QOS_DATA ?
386      */
387     if ((pRxParams->packet_class_tag == TAG_CLASS_QOS_DATA) || (pRxParams->packet_class_tag == TAG_CLASS_AMSDU))
388     {
389         TI_UINT8            uFrameTid;
390         TI_UINT16           uFrameSn;
391         TI_UINT16		    uSequenceControl;
392         TRxQueueTidDataBase *pTidDataBase;
393 
394         /* Get TID from frame */
395         uFrameTid = uQosControl & DOT11_QOS_CONTROL_FIELD_TID_BITS;
396 
397         /* TID illegal value ? */
398         if (uFrameTid >= MAX_NUM_OF_802_1d_TAGS)
399         {
400             TRACE1(pRxQueue->hReport, REPORT_SEVERITY_ERROR, "RxQueue_ReceivePacket: TID value too big, TID = %d. packet discarded!\n",uFrameTid);
401 
402             RxQueue_PassPacket (pRxQueue, TI_NOK, pBuffer);
403 
404             return;
405         }
406 
407         /*set the SA Tid pointer */
408         pTidDataBase = &(pRxQueue->tRxQueueArraysMng.tSa1ArrayMng[uFrameTid]);
409 
410         /* TID legal value */
411         /* packet TID BA not established ? */
412         if (pTidDataBase->aTidBaEstablished != TI_TRUE)
413         {
414             TRACE0(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: pass packet without reorder.\n");
415 
416             RxQueue_PassPacket (pRxQueue, tStatus, pBuffer);
417 
418             return;
419         }
420 
421         /* packet TID BA established */
422         /* Get Sequence Number from frame */
423         COPY_WLAN_WORD(&uSequenceControl, &pHdr->seqCtrl); /* copy with endianess handling. */
424         uFrameSn = (uSequenceControl & DOT11_SC_SEQ_NUM_MASK) >> 4;
425 
426         /*
427          * note:
428          * the FW never send paket, in establish TID BA, that the SN less then ESN !!!
429          */
430 
431         /* frame Sequence Number is the expected one ? */
432         if (uFrameSn == pTidDataBase->aTidExpectedSn)
433         {
434             TRACE0(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: frame Sequence Number == expected one Sequence Number.\n");
435 
436             /* pass the packet */
437             RxQueue_PassPacket (pRxQueue, tStatus, pBuffer);
438 
439             pTidDataBase->aTidExpectedSn++;
440             pTidDataBase->aTidExpectedSn &= 0xfff;
441 
442             /* increase the ArrayInex to the next */
443             pTidDataBase->aWinStartArrayInex++;
444 
445             /* aWinStartArrayInex % RX_QUEUE_ARRAY_SIZE */
446             pTidDataBase->aWinStartArrayInex &= RX_QUEUE_ARRAY_SIZE_BIT_MASK;
447 
448             /* pass all saved queue packets with SN higher then the expected one */
449             while (pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket != NULL)
450             {
451                 RxQueue_PassPacket (pRxQueue,
452                                     pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].tStatus,
453                                     pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket);
454 
455                 pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket = NULL;
456 
457                 pTidDataBase->aWinStartArrayInex++;
458 
459                 /* aWinStartArrayInex % RX_QUEUE_ARRAY_SIZE */
460                 pTidDataBase->aWinStartArrayInex &= RX_QUEUE_ARRAY_SIZE_BIT_MASK;
461 
462                  pTidDataBase->aTidExpectedSn++;
463 				 pTidDataBase->aTidExpectedSn &= 0xfff;
464             }
465 
466             return;
467         }
468 
469         /* frame Sequence Number is lower then Expected sequence number (ISN) ? */
470         if (! BA_SESSION_IS_A_BIGGER_THAN_B (uFrameSn, pTidDataBase->aTidExpectedSn))
471         {
472 			/* WLAN_OS_REPORT(("%s: ERROR - SN=%u is less than ESN=%u\n", __FUNCTION__, uFrameSn, pTidDataBase->aTidExpectedSn)); */
473 
474 			TRACE2(pRxQueue->hReport, REPORT_SEVERITY_ERROR,
475 				   "RxQueue_ReceivePacket: frame SN=%u is less than ESN=%u\n",uFrameSn,pTidDataBase->aTidExpectedSn);
476 
477 			RxQueue_PassPacket (pRxQueue, TI_NOK, pBuffer);
478 
479             return;
480         }
481 
482         /* frame Sequence Number between winStart and winEnd ? */
483         if ((BA_SESSION_IS_A_BIGGER_THAN_B (uFrameSn, pTidDataBase->aTidExpectedSn)) &&
484             /* mean: uFrameSn <= pTidDataBase->aTidExpectedSn + pTidDataBase->aTidWinSize) */
485             ( ! BA_SESSION_IS_A_BIGGER_THAN_B (uFrameSn,(pTidDataBase->aTidExpectedSn + pTidDataBase->aTidWinSize - 1))))
486         {
487             TI_UINT16 uSaveInex = pTidDataBase->aWinStartArrayInex + (TI_UINT16)((uFrameSn + SEQ_NUM_WRAP - pTidDataBase->aTidExpectedSn) & SEQ_NUM_MASK);
488             /* uSaveInex % RX_QUEUE_ARRAY_SIZE */
489             uSaveInex &= RX_QUEUE_ARRAY_SIZE_BIT_MASK;
490 
491 
492 			if (pTidDataBase->aPaketsQueue[uSaveInex].pPacket == NULL)
493 			{
494                 /* save the packet in the queue */
495                 pTidDataBase->aPaketsQueue[uSaveInex].tStatus = tStatus;
496                 pTidDataBase->aPaketsQueue[uSaveInex].pPacket = (void *)pBuffer;
497                 pTidDataBase->aPaketsQueue[uSaveInex].uFrameSn = uFrameSn;
498 			}
499 			else
500 			{
501 				 TRACE1(pRxQueue->hReport, REPORT_SEVERITY_ERROR, "RxQueue_ReceivePacket: frame Sequence has allready saved. uFrameSn = %d\n",uFrameSn);
502 				 RxQueue_PassPacket (pRxQueue, TI_NOK, pBuffer);
503 				 return;
504 			}
505             return;
506         }
507 
508 
509         /*
510         frame Sequence Number higher then winEnd ?
511         */
512         if ( BA_SESSION_IS_A_BIGGER_THAN_B (uFrameSn, (pTidDataBase->aTidExpectedSn + pTidDataBase->aTidWinSize - 1)) )
513         {
514             TI_UINT32 i;
515             TI_UINT16 uNewWinStartSn = (uFrameSn + SEQ_NUM_WRAP - pTidDataBase->aTidWinSize + 1) & SEQ_NUM_MASK;
516             TI_UINT16 uSaveInex;
517 
518 			TRACE0(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: frame Sequence Number higher then winEnd.\n");
519 
520             /* increase the ArrayInex to the next */
521             pTidDataBase->aWinStartArrayInex++;
522 
523             /* aWinStartArrayInex % RX_QUEUE_ARRAY_SIZE */
524             pTidDataBase->aWinStartArrayInex &= RX_QUEUE_ARRAY_SIZE_BIT_MASK;
525 
526             /* update the Expected SN since the current one is lost */
527             pTidDataBase->aTidExpectedSn++;
528             pTidDataBase->aTidExpectedSn &= 0xFFF;
529 
530             /* pass all saved queue packets with SN lower then the new win start */
531             for (i = 0;
532                  BA_SESSION_IS_A_BIGGER_THAN_B(uNewWinStartSn,pTidDataBase->aTidExpectedSn) &&
533                   (i < RX_QUEUE_ARRAY_SIZE) &&
534                   (i < pTidDataBase->aTidWinSize);
535                  i++)
536             {
537                 if (pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket != NULL)
538                 {
539                     RxQueue_PassPacket (pRxQueue,
540                                         pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].tStatus,
541                                         pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket);
542 
543                     pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket = NULL;
544                 }
545 
546                 pTidDataBase->aWinStartArrayInex++;
547 
548                 /* aWinStartArrayInex % RX_QUEUE_ARRAY_SIZE */
549                 pTidDataBase->aWinStartArrayInex &= RX_QUEUE_ARRAY_SIZE_BIT_MASK;
550 
551                 pTidDataBase->aTidExpectedSn++;
552                 pTidDataBase->aTidExpectedSn &= 0xFFF;
553 
554             }
555 
556             /* Calculate the new Expected SN */
557             if (i == pTidDataBase->aTidWinSize)
558             {
559                 pTidDataBase->aTidExpectedSn = uNewWinStartSn;
560             }
561             else
562             {
563                 /* Incase the uWinStartDelta lower than aTidWinSize check if ther are packets stored in Array */
564                 while (pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket != NULL) {
565                     RxQueue_PassPacket (pRxQueue,
566                                             pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].tStatus,
567                                             pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket);
568 
569                     pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket = NULL;
570 
571                     pTidDataBase->aWinStartArrayInex++;
572 
573                     /* aWinStartArrayInex % RX_QUEUE_ARRAY_SIZE */
574                     pTidDataBase->aWinStartArrayInex &= RX_QUEUE_ARRAY_SIZE_BIT_MASK;
575 
576                     pTidDataBase->aTidExpectedSn++;
577                     pTidDataBase->aTidExpectedSn &= 0xFFF;
578                 }
579             }
580 
581             if(pTidDataBase->aTidExpectedSn == uFrameSn)
582             {
583                 /* pass the packet */
584                 RxQueue_PassPacket (pRxQueue, tStatus, pBuffer);
585                 pTidDataBase->aTidExpectedSn++;
586 				pTidDataBase->aTidExpectedSn &= 0xfff;
587             }
588             else
589             {
590                 uSaveInex = pTidDataBase->aWinStartArrayInex + (TI_UINT16)((uFrameSn + SEQ_NUM_WRAP - pTidDataBase->aTidExpectedSn) & SEQ_NUM_MASK);
591 
592 				/* uSaveInex % RX_QUEUE_ARRAY_SIZE */
593 				uSaveInex &= RX_QUEUE_ARRAY_SIZE_BIT_MASK;
594 
595             /* save the packet in the last entry of the queue */
596                pTidDataBase->aPaketsQueue[uSaveInex].tStatus = tStatus;
597                pTidDataBase->aPaketsQueue[uSaveInex].pPacket = (void *)pBuffer;
598                pTidDataBase->aPaketsQueue[uSaveInex].pPacket = (void *)pBuffer;
599             }
600 
601             return;
602         }
603     }
604 
605 
606     /*
607      * BA event ?
608      */
609     if (pRxParams->packet_class_tag == TAG_CLASS_BA_EVENT)
610     {
611         TRxQueueTidDataBase *pTidDataBase;
612         TI_UINT8            *pDataFrameBody;
613         TI_UINT16           ufc;
614         TI_UINT8            uFrameTid;
615         TI_UINT16           uStartingSequenceNumber;
616         TI_UINT16           uWinStartDelta;
617         TI_UINT16           uBarControlField;
618         TI_UINT16           uBaStartingSequenceControlField;
619         TI_UINT16           uBAParameterField;
620         TI_UINT32           i;
621 
622         /* Get sub type from frame */
623         COPY_WLAN_WORD(&ufc, &pHdr->fc); /* copy with endianess handling. */
624 
625         /* get the type to BA event */
626         switch ((dot11_Fc_Sub_Type_e)(ufc & DOT11_FC_SUB_MASK))
627         {
628         case DOT11_FC_SUB_BAR:
629             TRACE0(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION , "RxQueue_ReceivePacket: BA event - BAR frame.\n");
630 
631             /* get pointer to the frame body */
632             pDataFrameBody = pFrame + sizeof(dot11_BarFrameHeader_t);
633 
634             /* Get TID from BAR frame */
635             COPY_WLAN_WORD (&uBarControlField, (TI_UINT16 *)pDataFrameBody); /* copy with endianess handling. */
636             uFrameTid = (uBarControlField & DOT11_BAR_CONTROL_FIELD_TID_BITS) >> 12;
637 
638             /* TID illegal value ? */
639             if (uFrameTid >= MAX_NUM_OF_802_1d_TAGS)
640             {
641                 TRACE1(pRxQueue->hReport, REPORT_SEVERITY_ERROR , "RxQueue_ReceivePacket: BA event - BAR frame with TID value too big, TID = %d.\n",uFrameTid);
642 
643                 RxQueue_PassPacket (pRxQueue, TI_NOK, pBuffer);
644 
645                 return;
646             }
647 
648             /* set the SA Tid pointer */
649             pTidDataBase = &(pRxQueue->tRxQueueArraysMng.tSa1ArrayMng[uFrameTid]);
650 
651             /* TID legal value */
652             /* packet TID BA not established ? */
653             if (pTidDataBase->aTidBaEstablished != TI_TRUE)
654             {
655                 TRACE1(pRxQueue->hReport, REPORT_SEVERITY_ERROR , "RxQueue_ReceivePacket: BA event - BAR frame for TID not established, TID = %d.\n",uFrameTid);
656 
657                 RxQueue_PassPacket (pRxQueue, TI_NOK, pBuffer);
658 
659                 return;
660             }
661 
662             /* Get Starting Sequence number from BAR frame */
663             pDataFrameBody = pDataFrameBody + 2;
664             COPY_WLAN_WORD (&uBaStartingSequenceControlField, (TI_UINT16 *)pDataFrameBody); /* copy with endianess handling. */
665             uStartingSequenceNumber = (uBaStartingSequenceControlField & DOT11_SC_SEQ_NUM_MASK) >> 4;
666 
667             /* Starting Sequence Number is higher then winStart ? */
668             if ( BA_SESSION_IS_A_BIGGER_THAN_B (uStartingSequenceNumber, pTidDataBase->aTidExpectedSn) )
669             {
670                 uWinStartDelta = (uStartingSequenceNumber + SEQ_NUM_WRAP - pTidDataBase->aTidExpectedSn) & SEQ_NUM_MASK;
671 
672                 /* pass all saved queue packets with SN lower then the new win start */
673                 for (i = 0;
674                      ((i < uWinStartDelta) || (pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket != NULL)) &&
675                       (i < RX_QUEUE_ARRAY_SIZE) &&
676                       (i < RX_QUEUE_WIN_SIZE);
677                      i++)
678                 {
679                     if (pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket != NULL)
680                     {
681                         RxQueue_PassPacket (pRxQueue,
682                                             pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].tStatus,
683                                             pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket);
684 
685                         pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket = NULL;
686                     }
687 
688                     pTidDataBase->aWinStartArrayInex++;
689 
690                     /* aWinStartArrayInex % RX_QUEUE_ARRAY_SIZE */
691                     pTidDataBase->aWinStartArrayInex &= RX_QUEUE_ARRAY_SIZE_BIT_MASK;
692                 }
693 
694                 pTidDataBase->aTidExpectedSn = uStartingSequenceNumber;
695             }
696             break;
697 
698 
699         case DOT11_FC_SUB_ACTION:
700             /* get pointer to the frame body */
701             pDataFrameBody = pFrame + sizeof(dot11_mgmtHeader_t);
702 
703             /* get Action field from BA action frame */
704             pDataFrameBody++;
705             switch(*pDataFrameBody)
706             {
707             case DOT11_BA_ACTION_ADDBA:
708 
709                 TRACE0( pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: BA event - ADDBA frame.\n");
710 
711                 /* get TID field and winSize from ADDBA action frame */
712                 pDataFrameBody = pDataFrameBody + 2;
713                 COPY_WLAN_WORD(&uBAParameterField, (TI_UINT16 *)pDataFrameBody); /* copy with endianess handling. */
714                 uFrameTid = (uBAParameterField & DOT11_BA_PARAMETER_SET_FIELD_TID_BITS) >> 2;
715 
716                 /* TID illegal value ? */
717                 if (uFrameTid >= MAX_NUM_OF_802_1d_TAGS)
718                 {
719                     TRACE1(pRxQueue->hReport, REPORT_SEVERITY_ERROR , "RxQueue_ReceivePacket: BA event - ADDBA frame with TID value too big, TID = %d.\n",uFrameTid);
720 
721                     RxQueue_PassPacket (pRxQueue, TI_NOK, pBuffer);
722 
723                     return;
724                 }
725 
726                 /*set the SA Tid pointer */
727                 pTidDataBase = &(pRxQueue->tRxQueueArraysMng.tSa1ArrayMng[uFrameTid]);
728 
729                 /* TID legal value */
730                 /* packet TID BA established ? */
731                 if (pTidDataBase->aTidBaEstablished == TI_TRUE)
732                 {
733                     TRACE1(pRxQueue->hReport, REPORT_SEVERITY_ERROR , "RxQueue_ReceivePacket: BA event - ADDBA frame for TID already established, TID = %d.\n",uFrameTid);
734 
735                     RxQueue_PassPacket (pRxQueue, TI_NOK, pBuffer);
736 
737                     return;
738                 }
739 
740                 /* get winSize from ADDBA action frame */
741                 pTidDataBase->aTidWinSize = (uBAParameterField & DOT11_BA_PARAMETER_SET_FIELD_WINSIZE_BITS) >> 6;
742 
743                 /* winSize illegal value ? */
744                 if (pTidDataBase->aTidWinSize > RX_QUEUE_WIN_SIZE)
745                 {
746                     /* In case the win Size is higher then 8 the driver and the FW set it to 8 and inform the AP in ADDBA respond */
747                     pTidDataBase->aTidWinSize = RX_QUEUE_WIN_SIZE;
748                 }
749 
750                 /* packet TID BA not yet established and winSize legal */
751                 /* establishe BA TID */
752                 pTidDataBase->aTidBaEstablished = TI_TRUE;
753 
754                 /* get initial sequence number (ISN) from ADDBA action frame */
755                 pDataFrameBody = pDataFrameBody + 4;
756                 COPY_WLAN_WORD (&uStartingSequenceNumber, (TI_UINT16 *)pDataFrameBody); /* copy with endianess handling. */
757                 pTidDataBase->aTidExpectedSn = (uStartingSequenceNumber & DOT11_SC_SEQ_NUM_MASK) >> 4;
758                 pTidDataBase->aWinStartArrayInex = 0;
759                 os_memoryZero (pRxQueue->hOs, pTidDataBase->aPaketsQueue, sizeof (TRxQueuePacketEntry) * RX_QUEUE_ARRAY_SIZE);
760                 break;
761 
762             case DOT11_BA_ACTION_DELBA:
763 
764                 TRACE0( pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: BA event - DELBA frame.\n");
765 
766                 /* get TID field and winSize from ADDBA action frame */
767                 pDataFrameBody = pDataFrameBody + 2;
768                 COPY_WLAN_WORD(&uBAParameterField, (TI_UINT16 *)pDataFrameBody); /* copy with endianess handling. */
769                 uFrameTid = (uBAParameterField & DOT11_DELBA_PARAMETER_FIELD_TID_BITS) >> 12;
770 
771                 /* TID illegal value ? */
772                 if (uFrameTid >= MAX_NUM_OF_802_1d_TAGS)
773                 {
774                     TRACE1(pRxQueue->hReport, REPORT_SEVERITY_ERROR , "RxQueue_ReceivePacket: BA event - DELBA frame with TID value too big, TID = %d.\n",uFrameTid);
775 
776                     RxQueue_PassPacket (pRxQueue, TI_NOK, pBuffer);
777 
778                     return;
779                 }
780 
781                 /*set the SA Tid pointer */
782                 pTidDataBase = &(pRxQueue->tRxQueueArraysMng.tSa1ArrayMng[uFrameTid]);
783 
784                 /* TID legal value */
785                 /* packet TID BA not established ? */
786                 if (pTidDataBase->aTidBaEstablished != TI_TRUE)
787                 {
788                     TRACE1(pRxQueue->hReport, REPORT_SEVERITY_ERROR , "RxQueue_ReceivePacket: BA event - DELBA frame for TID not established, TID = %d.\n",uFrameTid);
789 
790                     RxQueue_PassPacket (pRxQueue, TI_NOK, pBuffer);
791 
792                     return;
793                 }
794 
795                 RxQueue_CloseBaSession(hRxQueue, uFrameTid);
796                 break;
797 
798             default:
799                 TRACE1(pRxQueue->hReport, REPORT_SEVERITY_ERROR , "RxQueue_ReceivePacket: BA event Action field from BA action frame illegal. action = 0x%x\n",*pDataFrameBody);
800 
801                 RxQueue_PassPacket (pRxQueue, TI_NOK, pBuffer);
802 
803                 return;
804             }
805             break;
806 
807         default:
808             TRACE1(pRxQueue->hReport, REPORT_SEVERITY_ERROR , "RxQueue_ReceivePacket: BA event with Subtype illegal. Subtype = 0x%x\n",((ufc & DOT11_FC_SUB_MASK) >> 4));
809 
810             RxQueue_PassPacket (pRxQueue, TI_NOK, pBuffer);
811 
812             return;
813           }
814 
815     }
816 
817     TRACE1(pRxQueue->hReport, REPORT_SEVERITY_ERROR, "RxQueue_ReceivePacket: unknow type tag. tag = %d\n", pRxParams->packet_class_tag);
818 
819     RxQueue_PassPacket (pRxQueue, tStatus, pBuffer);
820 
821     return;
822 }
823 
824