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