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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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