1 /**************************************************************************** 2 **+-----------------------------------------------------------------------+** 3 **| |** 4 **| Copyright(c) 1998 - 2008 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 36 /***************************************************************************/ 37 /* */ 38 /* MODULE: */ 39 /* PURPOSE: */ 40 /* */ 41 /***************************************************************************/ 42 #include "fourX.h" 43 #include "report.h" 44 #include "osApi.h" 45 #include "utils.h" 46 #include "802_11Defs.h" 47 48 49 static Wlan4XType_t fourX_parseRxFrame(fourX_t* pFourX, mem_MSDU_T* msduPtr); 50 51 static TI_STATUS fourX_MakeConcatDecision(fourX_t* pFourX, 52 MsduList_t* pMsduList, 53 hwTxInformation_t* pHwTxInformation, 54 UINT32 numOfReadyMsdu, 55 UINT16* concatFlags, 56 UINT32* numOfMsduToConcat); 57 58 static TI_STATUS fourX_prepareMsduListToConcat(fourX_t* pFourX, 59 mem_MSDU_T** returnMsduPtr, 60 MsduList_t* pMsduList, 61 UINT32 maxNumMsduToConcat); 62 63 64 /************************************************************************* 65 * concat_create * 66 ************************************************************************** 67 * DESCRIPTION: This function initializes the Ctrl data module. 68 * 69 * INPUT: hOs - handle to Os Abstraction Layer 70 * 71 * OUTPUT: TxCmplt_CB - call back function that return to configMngr 72 * in order to register in the Hal 73 * 74 * RETURN: Handle to the allocated Ctrl data control block 75 ************************************************************************/ 76 77 fourX_t* fourX_create(TI_HANDLE hOs) 78 { 79 fourX_t* pFourX; 80 deConcatenator_t* pDeConcatenator; 81 concatenator_t* pConcatenator; 82 ackEmul_t* pAckEmul; 83 84 85 if( hOs == NULL ) 86 { 87 WLAN_OS_REPORT(("FATAL ERROR: fourX_create(): OS handle Error - Aborting\n")); 88 return NULL; 89 } 90 91 /* alocate concatenator block */ 92 pFourX = os_memoryAlloc(hOs, (sizeof(fourX_t))); 93 94 /* create 4x sub moduls */ 95 pConcatenator = concat_create(hOs); 96 pDeConcatenator = deConcat_create(hOs); 97 pAckEmul = ackEmul_create(hOs); 98 99 100 if ( (!pFourX) || (!pConcatenator) || (!pDeConcatenator) || (!pAckEmul)) 101 { 102 utils_nullMemoryFree(hOs, pDeConcatenator, sizeof(deConcatenator_t)); 103 utils_nullMemoryFree(hOs, pConcatenator, sizeof(concatenator_t)); 104 utils_nullMemoryFree(hOs, pAckEmul, sizeof(ackEmul_t)); 105 utils_nullMemoryFree(hOs, pFourX, sizeof(fourX_t)); 106 WLAN_OS_REPORT(("FATAL ERROR: fourX_create(): Error Creating fourX module- Aborting\n")); 107 return(NULL); 108 } 109 110 /* reset control module control block */ 111 os_memoryZero(hOs, pFourX, (sizeof(fourX_t))); 112 113 pFourX->pConcatenator = pConcatenator; 114 pFourX->pDeConcatenator = pDeConcatenator; 115 pFourX->pAckEmul = pAckEmul; 116 117 pFourX->hOs = hOs; 118 119 return(pFourX); 120 } 121 122 /*************************************************************************** 123 * ctrlData_config * 124 **************************************************************************** 125 * DESCRIPTION: This function configures the Ctrl Data module 126 * 127 * INPUTS: hCtrlData - The object 128 * hOs - Handle to the Os Abstraction Layer 129 * hReport - Handle to the Report object 130 * ctrlDataInitParams - pointer to Ctrl module init parameters 131 * OUTPUT: 132 * 133 * RETURNS: OK - Configuration succesfull 134 * NOK - Configuration unsuccesfull 135 ***************************************************************************/ 136 TI_STATUS fourX_config(fourX_t* pFourX, 137 TI_HANDLE hOs, 138 TI_HANDLE hReport, 139 TI_HANDLE hMemMngr, 140 TI_HANDLE hWhalCtrl, 141 TI_HANDLE hTxData, 142 fourXInitParams_t* fourXInitParams) 143 { 144 /* check parameters validity */ 145 if( (pFourX == NULL) || (hOs == NULL) || (hReport == NULL) || 146 (hMemMngr == NULL) || (hWhalCtrl == NULL) || (hTxData == NULL)) 147 { 148 WLAN_OS_REPORT(("FATAL ERROR: fourX_config(): Parameters Error - Aborting\n")); 149 return NOK; 150 } 151 152 /* set objects handles */ 153 pFourX->hOs = hOs; 154 pFourX->hReport = hReport; 155 pFourX->hMemMngr = hMemMngr; 156 pFourX->hWhalCtrl = hWhalCtrl; 157 pFourX->hTxData = hTxData; 158 159 /* configure 4x parameters - TODO USE fourXInitParams */ 160 pFourX->desiredConcatenationEnable = DESIRED_CONCATENATION_ENABLE_DEF; 161 pFourX->desiredCWMinEnable = DESIRED_CWMIN_ENABLE_DEF; 162 pFourX->desiredCWComboEnable = DESIRED_CWCOMBO_ENABLE_DEF; 163 pFourX->desiredAckEmulationEnable = DESIRED_ACKEMULATION_ENABLE_DEF; 164 pFourX->desiredERP_ProtectionEnable = DESIRED_ERP_PROTECTION_ENABLE_DEF; 165 pFourX->desiredMaxConcatSize = MAX_CONCAT_SIZE_DEF; 166 pFourX->desiredCWMin = CW_MIN_DEF; 167 pFourX->desiredCWMax = CW_MAX_DEF; 168 169 170 /* configure 4x sub modules */ 171 concat_config(pFourX->pConcatenator, hOs, hReport, hMemMngr); 172 deConcat_config(pFourX->pDeConcatenator, hOs, hReport, hMemMngr); 173 ackEmul_config(pFourX->pAckEmul,hWhalCtrl,hOs,hReport,hMemMngr); 174 175 176 WLAN_REPORT_INIT(pFourX->hReport, FOUR_X_MODULE_LOG, 177 (".....fouorX configured successfully\n")); 178 179 return OK; 180 } 181 182 /*************************************************************************** 183 * ctrlData_unLoad * 184 **************************************************************************** 185 * DESCRIPTION: This function unload the Ctrl data module. 186 * 187 * INPUTS: hCtrlData - the object 188 * 189 * OUTPUT: 190 * 191 * RETURNS: OK - Unload succesfull 192 * NOK - Unload unsuccesfull 193 ***************************************************************************/ 194 195 TI_STATUS fourX_destroy(fourX_t* pFourX) 196 { 197 concat_destroy(pFourX->pConcatenator); 198 deConcat_destroy(pFourX->pDeConcatenator); 199 ackEmul_destroy(pFourX->pAckEmul); 200 201 /* free control module controll block */ 202 os_memoryFree(pFourX->hOs, pFourX, sizeof(fourX_t)); 203 204 return OK; 205 } 206 207 208 static Wlan4XType_t fourX_parseRxFrame(fourX_t* pFourX, mem_MSDU_T* msduPtr) 209 { 210 dot114xMsdu_t* pdot114xHeader; 211 UINT8 tiSnapDataArray[8] = {0xAA,0xAA,0x03,0x08,0x00,0x28,0x60,0xD0}; 212 213 /* Check frame len validity */ 214 if(msduPtr->dataLen < sizeof(dot114xMsdu_t)) 215 return NOT_4X_MSDU; 216 217 pdot114xHeader = (dot114xMsdu_t*)memMgr_BufData(msduPtr->firstBDPtr); 218 219 /* 220 Verify a TI SNAP header. 221 */ 222 if( os_memoryCompare(pFourX->hOs, 223 (void*)&(pdot114xHeader->msduHeader.snapHeader), 224 tiSnapDataArray, 225 sizeof(Wlan_LlcHeader_T)) != 0) 226 { 227 return NOT_4X_MSDU; 228 } 229 230 switch (pdot114xHeader->header4x.type) 231 { 232 233 case CONCATENATION : 234 return CONCATENATION; 235 /* break; - unreachable*/ 236 237 case MANAGMENT_4X : 238 return MANAGMENT_4X; 239 /* break; - unreachable*/ 240 241 default: 242 return NOT_4X_MSDU; 243 /* break; - unreachable*/ 244 245 } 246 } 247 248 TI_STATUS fourX_rxMsdu(fourX_t* pFourX, mem_MSDU_T** rxMsduPtr) 249 { 250 Wlan4XType_t type4xMsdu; 251 mem_MSDU_T* currMsduPtr; 252 253 type4xMsdu = fourX_parseRxFrame(pFourX, *rxMsduPtr); 254 255 switch (type4xMsdu) 256 { 257 case CONCATENATION : 258 /* 259 * Deconcatenate Msdu 260 */ 261 WLAN_REPORT_INFORMATION(pFourX->hReport, FOUR_X_MODULE_LOG, 262 (" Received Concat msdu \n")); 263 if(deConcat_deConcatMsdu(pFourX->pDeConcatenator, rxMsduPtr) != OK) 264 { 265 WLAN_REPORT_ERROR(pFourX->hReport, FOUR_X_MODULE_LOG, 266 (" Failed to deconcat packet \n")); 267 268 return NOK; 269 } 270 break; 271 272 case MANAGMENT_4X : 273 break; 274 275 default: 276 break; 277 278 } 279 280 if(pFourX->ackEmulationEnable) 281 { 282 /* call ack emulation for each packet */ 283 currMsduPtr = *rxMsduPtr; 284 while(currMsduPtr) 285 { 286 wdrv_ackEmulationRxPacket(pFourX->pAckEmul, currMsduPtr); 287 currMsduPtr = currMsduPtr->nextMSDUinList; 288 } 289 } 290 return OK; 291 292 } 293 294 #define NUM_MSDU_TO_COPY 8 295 296 /*************************************************************************** 297 * fourX_CopyReplace 298 **************************************************************************** 299 * DESCRIPTION: This function copy OS data blocks to local data blocks 300 * in the MSDU in order to release OS resources and to enable 301 * high stream of data from the OS 302 * 303 * INPUTS: 304 * 305 * OUTPUT: 306 * 307 * RETURNS: 308 ***************************************************************************/ 309 TI_STATUS fourX_CopyReplace(fourX_t* pFourX, mem_MSDU_T **pMsdu, MsduList_t *pMsduList, mem_MSDU_T **pNewMsdu) 310 { 311 mem_MSDU_T *pOrigMsdu; 312 313 pOrigMsdu = (*pMsdu); 314 315 /* 316 * The copy is to new msdu pointed by pMsdu 317 */ 318 if(txData_copyPacketToMsdu(pFourX->hTxData, pMsdu, 0 /* dont FreeOldMsdu */) != OK) 319 { 320 /* no msdu to transmit */ 321 WLAN_REPORT_INFORMATION(pFourX->hReport, FOUR_X_MODULE_LOG, 322 (" fourX_CopyReplace() : txData_copyPacketToMsdu FAILED \n")); 323 324 return NOK; 325 } 326 327 /* 328 * Still use the old Msdu with its pointers, so swap the BDs of the new and the orig Msdu 329 */ 330 wlan_memMngrSwapMsdu(pFourX->hMemMngr, pOrigMsdu, (*pMsdu)); 331 332 /* return the new msdu to free later */ 333 (*pNewMsdu) = (*pMsdu); 334 /* use the orig Msdu */ 335 (*pMsdu) = pOrigMsdu; 336 337 return OK; 338 } 339 340 341 /*************************************************************************** 342 * fourX_CopyOsData 343 **************************************************************************** 344 * DESCRIPTION: This function scan the Msdu list and copy OS data blocks to 345 * local data blocks . 346 * in the MSDU in order to release OS resources and to enable 347 * high stream of data from the OS 348 * 349 * INPUTS: 350 * 351 * OUTPUT: 352 * 353 * RETURNS: 354 ***************************************************************************/ 355 UINT32 fourX_CopyOsData(fourX_t* pFourX, MsduList_t *pMsduList) 356 { 357 int NumMsduToCopy = 0; 358 mem_MSDU_T *pMsdu; 359 mem_MSDU_T *pNewMsdu=NULL; 360 mem_MSDU_T *pMsduFreeList=NULL; 361 mem_MSDU_T *pMsduFreeCurr=NULL; 362 mem_MSDU_T *pKeepNext=NULL; 363 int i; 364 int NumOfCopiedPackets=0; 365 366 os_protectLock(pMsduList->hOs, pMsduList->hCriticalSectionProtect); /* START OF CRITICAL SECTION */ 367 368 if (pMsduList->CurrNumOfMsdu == 0) 369 { 370 pFourX->counters.count6 = 0; 371 pFourX->counters.count7 = 0; 372 os_protectUnlock(pMsduList->hOs, pMsduList->hCriticalSectionProtect); /* END OF CRITICAL SECTION */ 373 return 0; 374 } 375 376 /* 377 * Find how many msdu to copy 378 */ 379 if (pMsduList->CurrNumOfMsdu <= NUM_MSDU_TO_COPY) 380 NumMsduToCopy = pMsduList->CurrNumOfMsdu; 381 else 382 NumMsduToCopy = NUM_MSDU_TO_COPY; 383 384 pMsdu=pMsduList->first; 385 386 /* 387 * Start the copy 388 */ 389 for (i=0; (i<NumMsduToCopy) ; i++) 390 { 391 if (pMsdu == NULL) 392 { 393 WLAN_REPORT_ERROR(pFourX->hReport, FOUR_X_MODULE_LOG, 394 (" fourX_CopyMsdu() : fourX_CopyReplace FAILED, pMsdu is NULL i=%d, Num=%d (Actual=%d) \n", i, NumMsduToCopy, pMsduList->CurrNumOfMsdu)); 395 396 break; 397 } 398 /* 399 * Already copied - skip it 400 */ 401 if (pMsdu->freeFunc == NULL) 402 { 403 pMsdu=pMsdu->nextMSDUinList; 404 NumOfCopiedPackets++; 405 continue; 406 } 407 408 WLAN_REPORT_INFORMATION(pFourX->hReport, FOUR_X_MODULE_LOG, 409 (" fourX_CopyMsdu() : i=%d, CopyReplace 0x%x\n", i , pMsdu)); 410 411 /* 412 * Copy and replace in the list 413 */ 414 if(fourX_CopyReplace(pFourX, &pMsdu, pMsduList, &pNewMsdu) != OK) 415 { 416 /* no msdu to transmit */ 417 WLAN_REPORT_ERROR(pFourX->hReport, FOUR_X_MODULE_LOG, 418 (" fourX_CopyMsdu() : fourX_CopyReplace FAILED \n")); 419 420 break; 421 } 422 423 /* 424 * Enter the new Msdu to the free list 425 */ 426 if (pMsduFreeList == NULL) 427 { 428 pMsduFreeList = pNewMsdu; 429 } 430 else 431 { 432 pMsduFreeCurr = pMsduFreeList; 433 while (pMsduFreeCurr->nextMSDUinList != NULL) 434 pMsduFreeCurr = pMsduFreeCurr->nextMSDUinList; 435 pMsduFreeCurr->nextMSDUinList = pNewMsdu; 436 } 437 pNewMsdu->nextMSDUinList = NULL; 438 439 /* copy the next msdu */ 440 pMsdu=pMsdu->nextMSDUinList; 441 NumOfCopiedPackets++; 442 } 443 444 pFourX->counters.count6 = pMsduList->CurrNumOfMsdu; 445 pFourX->counters.count7 = i; 446 447 /* !!!! This is the right place for the unlock */ 448 os_protectUnlock(pMsduList->hOs, pMsduList->hCriticalSectionProtect); /* END OF CRITICAL SECTION */ 449 450 /* 451 * free loop, do not call the free inside lock !!! 452 */ 453 pMsduFreeCurr = pMsduFreeList; 454 while (pMsduFreeCurr != NULL) 455 { 456 pKeepNext = pMsduFreeCurr->nextMSDUinList; 457 458 wlan_memMngrFreeMSDU(pFourX->hMemMngr, memMgr_MsduHandle(pMsduFreeCurr)); 459 460 pMsduFreeCurr=pKeepNext; 461 } 462 463 return NumOfCopiedPackets; 464 } 465 466 467 468 TI_STATUS fourX_txMsduDeQueue(fourX_t* pFourX, 469 mem_MSDU_T** returnMsduPtr, 470 MsduList_t* pMsduList, 471 hwTxInformation_t* pHwTxInformation) 472 { 473 TI_STATUS status; 474 mem_MSDU_T* firstMsduPtr; 475 UINT16 concatFlags = 0; 476 UINT32 numOfMsduToConcat; 477 UINT32 numMsdu = 0; 478 479 *returnMsduPtr = NULL; 480 481 482 #ifdef NO_COPY_NDIS_BUFFERS 483 /* 484 * Scan the Msdu list and copy OS data blocks to local data blocks . 485 * in the MSDU in order to release OS resources and to enable 486 * high stream of data from the OS. 487 */ 488 numMsdu = fourX_CopyOsData(pFourX, pMsduList); 489 /* This function copied up to 8 or numOfMsdu in list packets from OS to Shared memory 490 * As there is NDISfreeFunc after the copy, New un-copied packets can enter the msduList, 491 * but the scheduler was blocked from entering the send again. 492 */ 493 #else 494 495 if (pMsduList->CurrNumOfMsdu < NUM_MSDU_TO_COPY ) 496 numMsdu = pMsduList->CurrNumOfMsdu; 497 else 498 numMsdu = NUM_MSDU_TO_COPY; 499 #endif 500 501 /*if(pFourX->concatenationEnable != TRUE)*/ 502 status = fourX_MakeConcatDecision(pFourX,pMsduList,pHwTxInformation,numMsdu, 503 &concatFlags,&numOfMsduToConcat); 504 505 506 switch(status) 507 { 508 case MAKE_CONCATENATION: 509 510 /* 511 * Make Concatenation 512 */ 513 514 fourX_prepareMsduListToConcat(pFourX, 515 &firstMsduPtr, 516 pMsduList, 517 numOfMsduToConcat); 518 519 if(firstMsduPtr == NULL) 520 return NOK; 521 522 523 return concat_concatMsduList(pFourX->pConcatenator, 524 firstMsduPtr, 525 returnMsduPtr, 526 concatFlags); 527 528 529 case SEND_ONE_MSDU: 530 531 /* 532 * Send Only One Msdu 533 */ 534 535 if((msduList_GetFirst( pMsduList, returnMsduPtr )) != OK) 536 { 537 /* msdu list is empty - should never reach here */ 538 WLAN_REPORT_ERROR(pFourX->hReport, FOUR_X_MODULE_LOG, 539 (" fourX_txMsduDeQueue:msduList_GetFirst() : No Msdu to get in list \n")); 540 541 return NOK; 542 } 543 544 return OK; 545 546 case DO_NOT_SEND_MSDU: 547 548 /* 549 * Don't Send any Msdu 550 */ 551 552 return NOK; 553 554 default: 555 break; 556 557 } 558 return OK; 559 } 560 561 TI_STATUS fourX_txMsduBeforInsertToQueue(fourX_t* pFourX, 562 mem_MSDU_T** msduPtr) 563 { 564 /* no ACK emulation !!!!!!!!!!!!!!!!!! */ 565 #if 0 566 UINT32 discardPacket; 567 if(pFourX->ackEmulationEnable) 568 { 569 wdrv_ackEmulationTxPacket(pFourX->pAckEmul, *msduPtr, &discardPacket); 570 if (discardPacket == TRUE) 571 { 572 wlan_memMngrFreeMSDU(pFourX->hMemMngr, (*msduPtr)->handle); 573 (*msduPtr) = NULL; 574 return OK; 575 } 576 } 577 #endif 578 return OK; 579 } 580 581 static TI_STATUS fourX_prepareMsduListToConcat(fourX_t* pFourX, 582 mem_MSDU_T** returnMsduPtr, 583 MsduList_t* pMsduList, 584 UINT32 maxNumMsduToConcat) 585 { 586 mem_MSDU_T* currentMsduPtr; 587 mem_MSDU_T* PrevMsduPtr=NULL; 588 UINT32 totalLen = 0; 589 BOOL firsdMsduInList = TRUE; 590 UINT32 numOfMsdu = 0; 591 592 593 *returnMsduPtr = NULL; 594 595 while(maxNumMsduToConcat--) 596 { 597 /* prepare a link list of msdu in the concatenator format */ 598 if((msduList_WatchFirst( pMsduList, ¤tMsduPtr )) != OK) 599 { 600 /* msdu list is empty - can return now */ 601 WLAN_REPORT_INFORMATION(pFourX->hReport, FOUR_X_MODULE_LOG, 602 (" fourX_txMsduDeQueue: msduList_WatchFirst() : No Msdu to watch \n")); 603 break; 604 } 605 totalLen += currentMsduPtr->dataLen; 606 607 if(totalLen > 4032/*pFourX->currentMaxConcatSize*/) 608 break; 609 610 if((msduList_GetFirst( pMsduList, ¤tMsduPtr )) != OK) 611 { 612 /* msdu list is empty - should never reach here */ 613 WLAN_REPORT_ERROR(pFourX->hReport, FOUR_X_MODULE_LOG, 614 (" fourX_txMsduDeQueue:msduList_GetFirst() : No Msdu to get in list \n")); 615 break; 616 } 617 618 /* In this phase, the free func should be NULL !!!!!!!!!!! */ 619 if (currentMsduPtr->freeFunc) 620 { 621 WLAN_REPORT_ERROR(pFourX->hReport, FOUR_X_MODULE_LOG, 622 (" fourX_txMsduDeQueue:msduList_GetFirst() : fourX_prepareMsduListToConcat, free funct is not NULL !!!!!!!\n")); 623 } 624 625 numOfMsdu++; 626 627 if(firsdMsduInList == TRUE) 628 { 629 *returnMsduPtr = currentMsduPtr; 630 firsdMsduInList = FALSE; 631 } 632 else 633 { 634 PrevMsduPtr->nextMSDUinList = currentMsduPtr; 635 } 636 637 PrevMsduPtr = currentMsduPtr; 638 } 639 640 return OK; 641 } 642 643 static TI_STATUS fourX_MakeConcatDecision(fourX_t* pFourX, 644 MsduList_t* pMsduList, 645 hwTxInformation_t* pHwTxInformation, 646 UINT32 numOfReadyMsdu, 647 UINT16* concatFlags, 648 UINT32* numOfMsduToConcat) 649 { 650 memMgrResources_t memMgrResources; 651 652 #ifdef TNETW_MASTER_MODE 653 UINT32 limitResourcees; 654 #endif 655 656 *numOfMsduToConcat = 0; 657 658 /* get MemoryMgr resources for concatenation */ 659 wlan_memMngrGetMemMgrResources(pFourX->hMemMngr, &memMgrResources); 660 661 #ifdef TNETW_MASTER_MODE 662 limitResourcees = MIN(memMgrResources.numOfFreeBufPool2 ,(MIN(memMgrResources.numOfFreeBufPool1-1 , pHwTxInformation->hwNumOfFreeBDs))); 663 664 665 666 /* No free space in HW to send */ 667 if( (pHwTxInformation->hwNumOfFreeMsdu == 0) || (limitResourcees < 2) ) 668 { 669 pFourX->counters.count1++; 670 return DO_NOT_SEND_MSDU; 671 } 672 673 /* 674 * Phase 1: At least 3 waiting msdu for concat (and enough space in HW) 675 * -------------------------------------------------------------------- 676 * In case there are 2 msdu the decision will be later 677 * We have resources to send, decide if to concat, send single or wait. 678 */ 679 if( numOfReadyMsdu >= 3 ) 680 { 681 pFourX->counters.count2++; 682 /* We have enough msdus to concat. */ 683 *concatFlags = *concatFlags | WLAN_4X_CONCAT_MORE_BIT; 684 685 /* not enough free bd to send or concat - need at least 2 msdu and 2 bd for each + concat header bd */ 686 if (limitResourcees < 5) 687 return DO_NOT_SEND_MSDU; 688 689 /* minimum 2 bd for each msdu and one for cocat header */ 690 *numOfMsduToConcat = MIN( (limitResourcees - 1)>>1, numOfReadyMsdu); 691 692 /* minimum 2 msdu to concat */ 693 if (*numOfMsduToConcat < 2) 694 return SEND_ONE_MSDU; 695 696 return MAKE_CONCATENATION; 697 } 698 699 700 /* 701 * Phase 2: Less than 3 waiting msdu, and the HW already has Msdu to send 702 * ---------------------------------------------------------------------- 703 * It is allowed to delay the msdu and continue queueing more MSDU 704 */ 705 if(pHwTxInformation->hwNumOfBusyMsdu > 1) 706 { 707 pFourX->counters.count3++; 708 /* 709 * ACX has enough packets to send, delay the current sending. 710 */ 711 return DO_NOT_SEND_MSDU; 712 } 713 714 /* 715 * Phase 3: Less than 3 waiting msdu, and the HW is free to send 716 * ------------------------------------------------------------- 717 * It is NOT allowed to delay the msdu, so send it 718 */ 719 else 720 { 721 /* 722 * Phase 4: There are 2 msdu to concat and the HW is free to send 723 * -------------------------------------------------------------- 724 */ 725 if( numOfReadyMsdu > 1 ) 726 { 727 pFourX->counters.count4++; 728 /* We have enough msdus to concat. */ 729 *concatFlags = *concatFlags | WLAN_4X_CONCAT_MORE_BIT; 730 731 /* not enough free bd to send or concat - need at least 2 msdu and 2 bd for each + concat header bd */ 732 if (limitResourcees < 5) 733 return DO_NOT_SEND_MSDU; 734 735 /* minimum 2 bd for each msdu and one for cocat header */ 736 *numOfMsduToConcat = MIN( (limitResourcees - 1)>>1, numOfReadyMsdu); 737 738 /* minimum 2 msdu to concat */ 739 if (*numOfMsduToConcat < 2) 740 return SEND_ONE_MSDU; 741 742 return MAKE_CONCATENATION; 743 } 744 /* 745 * Phase 5: There are only one msdu to send, send it (no concatination) 746 * -------------------------------------------------------------------- 747 */ 748 else 749 { 750 pFourX->counters.count5++; 751 /* 752 * There space in HW and only one MSDU to send, send it as single. 753 */ 754 return SEND_ONE_MSDU; 755 } 756 } 757 758 759 #else /* SLAVE_MODE */ 760 if((pHwTxInformation->hwTotalAvailMem > 4095) && (numOfReadyMsdu > 1)) 761 { 762 *concatFlags = *concatFlags | WLAN_4X_CONCAT_MORE_BIT; 763 return MAKE_CONCATENATION; 764 } 765 else 766 { 767 if(pHwTxInformation->hwTotalAvailMem > pMsduList->first->dataLen) 768 return SEND_ONE_MSDU; 769 else 770 return DO_NOT_SEND_MSDU; 771 } 772 773 #endif /* MASTER/SALVE modes */ 774 775 776 777 } 778 779 780 /* debug functions */ 781 void fourX_printParams(fourX_t* pFourX) 782 { 783 784 WLAN_OS_REPORT((" FOUR X Parameters \n")); 785 WLAN_OS_REPORT(("-------------------------------------\n")); 786 787 WLAN_OS_REPORT(("hOs = 0x%X\n",pFourX->hOs )); 788 WLAN_OS_REPORT(("hReport = 0x%X\n",pFourX->hReport )); 789 WLAN_OS_REPORT(("hMemMngr = 0x%X\n\n",pFourX->hMemMngr )); 790 791 WLAN_OS_REPORT(("concatenationEnable = %d\n",pFourX->concatenationEnable )); 792 WLAN_OS_REPORT(("CWMinEnable = %d\n",pFourX->CWMinEnable )); 793 WLAN_OS_REPORT(("CWComboEnable = %d\n",pFourX->CWComboEnable )); 794 WLAN_OS_REPORT(("ackEmulationEnable = %d\n",pFourX->ackEmulationEnable )); 795 WLAN_OS_REPORT(("ERP_ProtectionEnable = %d\n\n",pFourX->ERP_ProtectionEnable )); 796 797 WLAN_OS_REPORT(("desiredConcatenationEnable = %d\n",pFourX->desiredConcatenationEnable )); 798 WLAN_OS_REPORT(("desiredCWMinEnable = %d\n",pFourX->desiredCWMinEnable )); 799 WLAN_OS_REPORT(("desiredCWComboEnable = %d\n",pFourX->desiredCWComboEnable )); 800 WLAN_OS_REPORT(("desiredAckEmulationEnable = %d\n",pFourX->desiredAckEmulationEnable )); 801 WLAN_OS_REPORT(("desiredERP_ProtectionEnable = %d\n\n",pFourX->desiredERP_ProtectionEnable )); 802 803 WLAN_OS_REPORT(("desiredMaxConcatSize = %d\n",pFourX->desiredMaxConcatSize )); 804 WLAN_OS_REPORT(("desiredCWMin = %d\n",pFourX->desiredCWMin )); 805 WLAN_OS_REPORT(("desiredCWMax = %d\n\n",pFourX->desiredCWMax )); 806 807 808 /* AP supported features */ 809 810 811 /* 4x parameters */ 812 WLAN_OS_REPORT(("currentMaxConcatSize = %d\n",pFourX->currentMaxConcatSize )); 813 WLAN_OS_REPORT(("currentCWMin = %d\n",pFourX->currentCWMin )); 814 WLAN_OS_REPORT(("currentCWMax = %d\n\n",pFourX->currentCWMax )); 815 816 817 WLAN_OS_REPORT(("ApFourX_Capabilities.fourXProtocolVersion = %d\n", pFourX->ApFourX_Capabilities.fourXProtocolVersion)); 818 WLAN_OS_REPORT(("-------------------------------------------------\n")); 819 820 WLAN_OS_REPORT(("AP_Cap.concatenationParams.enableDisable = %d\n", pFourX->ApFourX_Capabilities.concatenationParams.enableDisable)); 821 WLAN_OS_REPORT(("AP_Cap.concatenationParams.concatenationSize = %d\n", pFourX->ApFourX_Capabilities.concatenationParams.concatenationSize)); 822 823 WLAN_OS_REPORT(("AP_Cap.contentionWindowParams.enableDisable = %d\n", pFourX->ApFourX_Capabilities.contentionWindowParams.enableDisable)); 824 WLAN_OS_REPORT(("AP_Cap.contentionWindowParams.CWMin = %d\n", pFourX->ApFourX_Capabilities.contentionWindowParams.CWMin)); 825 WLAN_OS_REPORT(("AP_Cap.contentionWindowParams.CWMax = %d\n", pFourX->ApFourX_Capabilities.contentionWindowParams.CWMax)); 826 827 WLAN_OS_REPORT(("AP_Cap.CWCombParams.enableDisable = %d\n", pFourX->ApFourX_Capabilities.CWCombParams.enableDisable)); 828 WLAN_OS_REPORT(("AP_Cap.CWCombParams.DIFS = %d\n", pFourX->ApFourX_Capabilities.CWCombParams.DIFS)); 829 WLAN_OS_REPORT(("AP_Cap.CWCombParams.SLOT = %d\n", pFourX->ApFourX_Capabilities.CWCombParams.SLOT)); 830 WLAN_OS_REPORT(("AP_Cap.CWCombParams.CWMin = %d\n", pFourX->ApFourX_Capabilities.CWCombParams.CWMin)); 831 832 WLAN_OS_REPORT(("AP_Cap.ackEmulationParams.enableDisable = %d\n", pFourX->ApFourX_Capabilities.ackEmulationParams.enableDisable)); 833 834 WLAN_OS_REPORT(("AP_Cap.ERP_ProtectionParams.enableDisable = %d\n", pFourX->ApFourX_Capabilities.ERP_ProtectionParams.enableDisable)); 835 836 WLAN_OS_REPORT(("No Free Msdu in ACX = %d\n", pFourX->counters.count1)); 837 WLAN_OS_REPORT(("Concat more than 2 = %d\n", pFourX->counters.count2)); 838 WLAN_OS_REPORT(("Delay sending = %d\n", pFourX->counters.count3)); 839 WLAN_OS_REPORT(("Concat less than 3 = %d\n", pFourX->counters.count4)); 840 WLAN_OS_REPORT(("send one msdu = %d\n", pFourX->counters.count5)); 841 842 WLAN_OS_REPORT(("Msdu in Queue Total = %d\n", pFourX->counters.count6)); 843 WLAN_OS_REPORT(("Msdu in Queue Copied = %d\n", pFourX->counters.count7)); 844 845 } 846