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 /* MODULE: Tx.c */ 38 /* PURPOSE: Tx module functions */ 39 /* */ 40 /***************************************************************************/ 41 #include "osTIType.h" 42 #include "paramIn.h" 43 #include "paramOut.h" 44 #include "osApi.h" 45 #include "tx.h" 46 #include "DataCtrl_Api.h" 47 #include "siteMgrApi.h" 48 #include "802_11Defs.h" 49 #include "Ethernet.h" 50 /* GWSI_LAYER */ 51 #include "Core_AdaptTx.h" 52 53 #include "memMngrEx.h" 54 #include "report.h" 55 #include "utils.h" 56 #include "measurementMgrApi.h" 57 #include "TI_IPC_Api.h" 58 #include "EvHandler.h" 59 #include "qosMngr_API.h" 60 #include "PowerMgr_API.h" 61 #include "bufferPoolApi.h" 62 #include "TNETW_Driver_api.h" 63 64 /* 65 This is an Ethernet Version 2 frame: 66 67 +--------------+ 68 | | The destination address is a six byte Media Access 69 | Destination | Control (MAC) address, usually burned into the 70 | 6 bytes | ROM of the Ethernet card. 71 +--------------+ 72 | | The source address is a six byte MAC address, and 73 | Source | can signify a physical station or a broadcast. 74 | 6 bytes | 75 +--------------+ 76 | Type | The Type field it must be grater then 1500 dec. 77 | 2 bytes | 78 +--------------+ 79 | | Any higher layer information is placed in the 80 | Data | data field, which could contain protocol 81 | | information or user data. 82 ~ ~ 83 ~ ~ 84 | 46 to 1500 | 85 | bytes | 86 | | 87 +--------------+ 88 | FCS | 89 | 4 bytes | 90 +--------------+ 91 92 93 94 */ 95 /* 96 97 802.2 SNAP DATA Frame 98 +----------------+ 99 | | 100 | Destination | 101 | 6 bytes | 102 +----------------+ 103 | | 104 | Source | 105 | 6 bytes | 106 +----------------+ 107 | Frame Length | Must be <= 1500 Dec. 108 | 2 bytes | 109 +----------------+ 110 | DSAP - 1 byte | = 0xAA ( SNAP ) 111 +----------------+ 112 | SSAP - 1 byte | = 0xAA ( SNAP ) 113 +----------------+ 114 |Control - 1 byte| = 0x03 115 +----------------+ 116 | OUI - 3 bytes | = 0x0 117 | | 118 +----------------+ 119 | Type - 2 bytes | = Ethernet type (IP=0x0800) 120 +----------------+ 121 | | 122 | Data | 123 | | 124 ~ ~ 125 ~ ~ 126 | 46 to 1500 | 127 | bytes | 128 | | 129 +----------------+ 130 | FCS | 131 | 4 bytes | 132 +----------------+ 133 134 135 136 137 802.11 DATA Frame 138 +----------------+ 139 | | 140 | Frame Control | 141 | 2 bytes | 142 +----------------+ 143 | | 144 | Duration ID | 145 | 2 bytes | 146 +----------------+ 147 | | 148 | Address 1 | 149 | 6 bytes | 150 +----------------+ 151 | | 152 | Address 2 | 153 | 6 bytes | 154 +----------------+ 155 | | 156 | Address 3 | 157 | 6 bytes | 158 +----------------+ 159 | | 160 | Sequence Cntrl | 161 | 2 bytes | 162 +----------------+ 163 | | 164 | Address 4 | 165 | 6 bytes | 166 +----------------+ 167 | DSAP - 1 byte | = 0xAA ( SNAP ) 168 +----------------+ 169 | SSAP - 1 byte | = 0xAA ( SNAP ) 170 +----------------+ 171 |Control - 1 byte| = 0x03 172 +----------------+ 173 | OUI - 3 bytes | = 0x0 174 | | 175 +----------------+ 176 | Type - 2 bytes | = Ethernet type (IP=0x0800) 177 +----------------+ 178 | | 179 | Data | 180 | | 181 ~ ~ 182 ~ ~ 183 | 46 to 1500 | 184 | bytes | 185 | | 186 +----------------+ 187 | FCS | 188 | 4 bytes | 189 +----------------+ 190 191 */ 192 193 /* Tx queue selection definitions */ 194 #define Q_LEAST_WEIGHT 0xFFFFFFFF /* Use least possible weight as init value (highest value is lowest priority). */ 195 #define Q_SELECTION_HISTORY_LEVEL 5 /* Count down from this value if queue is selected to Tx. */ 196 197 198 #define MANAGEMENT_QUEUE_SIZE 16 199 200 #define DEFAULT_QUEUE_TO_HAL 1 201 202 #define EAPOL_PACKET 0x8E88 203 204 /* defined in QosMngr.c - used to update QosControl (userPriority) of a given packet after it has been "downgraded" due to admission control */ 205 extern UINT8 wmeAcToUpIndex[MAX_NUM_OF_AC]; 206 207 /* defined in qosMngr.c - used to identify voice packets in NON QOS APs */ 208 extern int WMEQosTagToACTable[MAX_NUM_OF_802_1d_TAGS]; 209 210 /* this macro accesses the WME Tag-to-AC conversion array in order to enable identifying voice packets even on NON QOS APs */ 211 #define GET_WME_AC_TYPE_FROM_MSDU(pMsdu) (WMEQosTagToACTable[pMsdu->qosTag]) 212 213 #define GET_QUEUE_INDEX(pTxData,acIndex) (pTxData->txDataAcTrfcCtrl[acIndex].QueueIndex) 214 215 #define ABS(a) (((int)(a) >= 0) ? (a) : -((int)(a))) 216 217 static void txData_convertEthToWlanHeader (txData_t *pTxData, mem_MSDU_T *pMsdu); 218 219 static TI_STATUS txData_schedulerSelectQueueToTransmitFrom( TI_HANDLE hTxData, MsduList_t** pMsduListPtr,UINT8 *selectedQueueIndex ); 220 221 static void txData_startTxSchedulerFromTimer(TI_HANDLE hTxData); 222 223 static void txData_calcCreditFromTimer(TI_HANDLE hTxData); 224 225 static void txData_UpdateTxCounters( TI_HANDLE hTxData, txCompleteAttr_t *pTxCompleteAttr ); 226 227 static void txData_SetTxDelayCounters( TI_HANDLE hTxData, UINT32 txQid, txCompleteAttr_t *pTxCompleteAttr, UINT32 driverDelay ); 228 229 static int txData_selectQueueAndUpdateUserPriority (txData_t *pTxData, mem_MSDU_T *pMsdu, int *selectedQueue, acTrfcType_e *selectedAc); 230 231 static int txData_getHighestAdmittedAc(txData_t *pTxData, int startingAcIndex); 232 233 static void txData_startVadTimer(TI_HANDLE hTxData, UINT16 voiceDuration); 234 static void txData_stopVadTimer(TI_HANDLE hTxData); 235 static void txData_setVadTimer(TI_HANDLE hTxData, BOOL vadEnabled, UINT16 duration); 236 static void txData_resetVadTimer(TI_HANDLE hTxData); 237 static void txData_vadTimeout(TI_HANDLE hTxData); 238 #ifdef TI_DBG 239 240 static void txData_printTxThroughputPerQueue(TI_HANDLE hTxData); 241 242 static void txData_printTxAirThroughputPerQueue(TI_HANDLE hTxData); 243 244 static void txData_printJitter(TI_HANDLE hTxData); 245 246 #endif 247 248 static BOOL txData_acVoPsPollMode(txData_t *pTxData); 249 250 static UINT32 txDataTimeToMsduExpiry( TI_HANDLE htxData, mem_MSDU_T* pMsdu, UINT8 Qid); 251 252 static UINT8 txData_GetAcIdFromQid(TI_HANDLE hTxData,UINT8 Qid); 253 254 TI_STATUS txData_setMediumUsageThresholds(TI_HANDLE hTxData, 255 UINT8 acID, 256 INT32 highMediumUsageThreshold, 257 INT32 lowMediumUsageThreshold); 258 259 static void txData_SetQidToAcTable(TI_HANDLE hTxData,UINT8 QidStart, UINT8 QidEnd,UINT8 AcId); 260 261 /* The TX delay histogram ranges start and end in msec. */ 262 static UINT32 txDelayRangeStart[TX_DELAY_RANGES_NUM] = { 0, 1, 10, 20, 40, 60, 80, 100, 200 }; 263 static UINT32 txDelayRangeEnd [TX_DELAY_RANGES_NUM] = { 1, 10, 20, 40, 60, 80, 100, 200, 0xFFFFFFFF }; 264 265 /************************************************************************* 266 * txData_create * 267 ************************************************************************** 268 * DESCRIPTION: This function initializes the Tx module. 269 * 270 * INPUT: hOs - handle to Os Abstraction Layer 271 * txDataInitParams - Tx Data creation parameters 272 * OUTPUT: 273 * 274 * RETURN: Handle to the allocated Tx data control block 275 *************************************************************************/ 276 TI_HANDLE txData_create(txDataInitParams_t *txDataInitParams, 277 TI_HANDLE hOs) 278 { 279 280 txData_t *hTxData; 281 MsduList_t *mgmtMsduList; 282 MsduList_t *dataMsduListArr[MAX_NUM_OF_TX_QUEUES]; 283 void* pTimer; 284 #ifdef TI_DBG 285 void* pThroughputTimer; 286 void* pAirThroughputTimer; 287 void* pJitterTimer; 288 #endif 289 void* pCreditTimer; 290 void* pVadTimer; 291 int queueIndex = 0; 292 293 294 /* check parameters validity */ 295 if( txDataInitParams->txDataNumOfDataQueues > MAX_NUM_OF_TX_QUEUES || 296 txDataInitParams->txDataNumOfDataQueues <= 0 ) 297 { 298 WLAN_OS_REPORT(("FATAL ERROR - UNABLE TO CREATE TX MODULE. Number of queues error = %d.",txDataInitParams->txDataNumOfDataQueues)); 299 return NULL; 300 } 301 302 /* allocate Tx module control block */ 303 hTxData = os_memoryAlloc(hOs, (sizeof(txData_t))); 304 305 if(!hTxData) 306 return NULL; 307 308 /* reset tx control block */ 309 os_memoryZero(hOs, hTxData, (sizeof(txData_t))); 310 311 /* allocate the buffer pool */ 312 hTxData->hBufferPool = bufferPool_create( hOs, 313 HAL_CTRL_ACX_TX_DESC_DEF * MAX_NUM_OF_TX_QUEUES, 314 sizeof(txPacketIdAttr_t) ); 315 if ( NULL == hTxData->hBufferPool ) 316 { 317 utils_nullMemoryFree(hOs, hTxData, sizeof(txData_t)); 318 return NULL; 319 } 320 321 /* allocate Timer to use for scheduler trigger */ 322 pTimer = os_timerCreate(hOs, txData_startTxSchedulerFromTimer, hTxData); 323 if(!pTimer) 324 { 325 bufferPool_destroy( hTxData->hBufferPool ); 326 utils_nullMemoryFree(hOs, hTxData, sizeof(txData_t)); 327 return NULL; 328 } 329 330 /* allocate Timer for vad operation */ 331 pVadTimer = os_timerCreate(hOs, txData_vadTimeout, hTxData); 332 if(!pVadTimer) 333 { 334 bufferPool_destroy( hTxData->hBufferPool ); 335 utils_nullTimerDestroy (hOs, pTimer); 336 utils_nullMemoryFree(hOs, hTxData, sizeof(txData_t)); 337 return NULL; 338 } 339 #ifdef TI_DBG 340 /* allocate timer for debug throughput per queue */ 341 pThroughputTimer = os_timerCreate(hOs, txData_printTxThroughputPerQueue, hTxData); 342 if(!pThroughputTimer) 343 { 344 bufferPool_destroy( hTxData->hBufferPool ); 345 utils_nullTimerDestroy(hOs, pTimer); 346 utils_nullMemoryFree(hOs, hTxData, sizeof(txData_t)); 347 return NULL; 348 } 349 350 /* allocate timer for debug throughput per queue */ 351 pAirThroughputTimer = os_timerCreate (hOs, txData_printTxAirThroughputPerQueue, hTxData); 352 if (!pAirThroughputTimer) 353 { 354 bufferPool_destroy (hTxData->hBufferPool); 355 utils_nullTimerDestroy (hOs, pTimer); 356 utils_nullTimerDestroy (hOs, pThroughputTimer); 357 utils_nullMemoryFree (hOs, hTxData, sizeof(txData_t)); 358 return NULL; 359 } 360 361 /* allocate timer for debug throughput per queue */ 362 pJitterTimer = os_timerCreate (hOs, txData_printJitter, hTxData); 363 if (!pJitterTimer) 364 { 365 bufferPool_destroy (hTxData->hBufferPool); 366 utils_nullTimerDestroy (hOs, pTimer); 367 utils_nullTimerDestroy (hOs, pThroughputTimer); 368 utils_nullTimerDestroy (hOs, pAirThroughputTimer); 369 utils_nullMemoryFree (hOs, hTxData, sizeof(txData_t)); 370 return NULL; 371 } 372 #endif 373 374 /* allocate timer for credit calculation */ 375 pCreditTimer = os_timerCreate(hOs, txData_calcCreditFromTimer, hTxData); 376 if(!pCreditTimer) 377 { 378 bufferPool_destroy( hTxData->hBufferPool ); 379 utils_nullTimerDestroy(hOs, pTimer); 380 #ifdef TI_DBG 381 utils_nullTimerDestroy(hOs, pThroughputTimer); 382 utils_nullTimerDestroy(hOs, pAirThroughputTimer); 383 utils_nullTimerDestroy(hOs, pJitterTimer); 384 #endif 385 utils_nullMemoryFree(hOs, hTxData, sizeof(txData_t)); 386 return NULL; 387 } 388 389 /* initialize management queue */ 390 mgmtMsduList = msduList_CreateNewMsduList( hOs); 391 if(!mgmtMsduList) 392 { 393 bufferPool_destroy( hTxData->hBufferPool ); 394 utils_nullTimerDestroy(hOs, pTimer); 395 #ifdef TI_DBG 396 utils_nullTimerDestroy(hOs, pThroughputTimer); 397 utils_nullTimerDestroy(hOs, pAirThroughputTimer); 398 utils_nullTimerDestroy(hOs, pJitterTimer); 399 #endif 400 utils_nullTimerDestroy(hOs, pCreditTimer); 401 utils_nullMemoryFree(hOs, hTxData, sizeof(txData_t)); 402 return NULL; 403 } 404 405 /* initialize tx data queues */ 406 for(queueIndex = 0 ; queueIndex < MAX_NUM_OF_TX_QUEUES ; queueIndex++) 407 { 408 dataMsduListArr[queueIndex] = msduList_CreateNewMsduList( hOs); 409 if(!dataMsduListArr[queueIndex]) 410 { 411 bufferPool_destroy( hTxData->hBufferPool ); 412 utils_nullTimerDestroy(hOs, pTimer); 413 #ifdef TI_DBG 414 utils_nullTimerDestroy(hOs, pThroughputTimer); 415 utils_nullTimerDestroy(hOs, pAirThroughputTimer); 416 utils_nullTimerDestroy(hOs, pJitterTimer); 417 #endif 418 utils_nullTimerDestroy(hOs, pCreditTimer); 419 utils_nullMemoryFree(hOs, mgmtMsduList, sizeof(MsduList_t)); 420 queueIndex--; 421 for(; queueIndex >= 0 ; queueIndex--) 422 { 423 utils_nullMemoryFree(hOs, dataMsduListArr[queueIndex], sizeof(MsduList_t)); 424 } 425 utils_nullMemoryFree(hOs, hTxData, sizeof(txData_t)); 426 return NULL; 427 } 428 } 429 430 hTxData->txDataNumOfQueues = txDataInitParams->txDataNumOfDataQueues; 431 432 /* Threshold to decide whether we drop the packet, or sending it to Fw */ 433 /* example: value of 75 will drop any MSDU that stayed it the Driver */ 434 /* Queues for more than 75% of the time that was originally defined for it */ 435 hTxData->uFracOfLifeTimeToDrop = txDataInitParams->uFracOfLifeTimeToDrop; 436 437 hTxData->TxEventDistributor = DistributorMgr_Create(hOs,MAX_TX_NOTIF_REQ_ELMENTS); 438 439 hTxData->mngMsduList = mgmtMsduList; 440 for(queueIndex = 0 ; queueIndex < MAX_NUM_OF_TX_QUEUES ; queueIndex++) 441 { 442 hTxData->dataMsduListArr[queueIndex] = dataMsduListArr[queueIndex]; 443 } 444 hTxData->pSchedulerTimer = pTimer; 445 hTxData->pVadTimer = pVadTimer; 446 hTxData->bSchedulerTimerRunning = FALSE; 447 #ifdef TI_DBG 448 hTxData->pThroughputTimer = pThroughputTimer; 449 hTxData->pAirThroughputTimer = pAirThroughputTimer; 450 hTxData->pJitterTimer = pJitterTimer; 451 #endif 452 hTxData->pCreditTimer = pCreditTimer; 453 454 hTxData->hOs = hOs; 455 456 hTxData->bVadTimerEnabled = FALSE; 457 hTxData->vadTimerDuration = 0; 458 459 hTxData->creditCalculationTimeout = txDataInitParams->creditCalculationTimeout; 460 hTxData->bCreditCalcTimerEnabled = txDataInitParams->bCreditCalcTimerEnabled; 461 hTxData->admCtrlDelayDueToMediumTimeOverUsage = txDataInitParams->admCtrlDelayDueToMediumTimeOverUsage; 462 hTxData->admissionDownGradeEnable = txDataInitParams->admissionDownGradeEnable; 463 464 465 return(hTxData); 466 } 467 468 /*************************************************************************** 469 * txData_config * 470 **************************************************************************** 471 * DESCRIPTION: This function configures the Tx Data module 472 * 473 * INPUTS: hTxData - The object 474 * hCtrlData - Handle to the Ctrl Data object 475 * hOs - Handle to the Os Abstraction Layer 476 * hReport - Handle to the Report object 477 * hMemMngr - Handle to the Memory manager object 478 479 * OUTPUT: 480 * 481 * RETURNS: OK - Configuration unsuccessful 482 * NOK - Configuration unsuccessful 483 ***************************************************************************/ 484 485 TI_STATUS txData_config(TI_HANDLE hTxData, 486 TI_HANDLE hCtrlData, 487 TI_HANDLE hTnetwDrv, 488 TI_HANDLE hWhalCtrl, 489 TI_HANDLE hOs, 490 TI_HANDLE hReport, 491 TI_HANDLE hMemMngr, 492 TI_HANDLE hSiteMgr, 493 TI_HANDLE hEvHandler, 494 TI_HANDLE hQosMngr, 495 TI_HANDLE hPowerMgr) 496 { 497 int qIndex; 498 txData_t *pTxData = (txData_t *)hTxData; 499 500 /* configure modules handles */ 501 pTxData->hCtrlData = hCtrlData; 502 pTxData->hTnetwDrv = hTnetwDrv; 503 pTxData->hWhalCtrl= hWhalCtrl; 504 pTxData->hOs = hOs; 505 pTxData->hReport = hReport; 506 pTxData->hMemMngr = hMemMngr; 507 pTxData->hSiteMgr = hSiteMgr; 508 pTxData->hEvHandler = hEvHandler; 509 pTxData->hQosMngr = hQosMngr; 510 pTxData->hPowerMgr = hPowerMgr; 511 512 /* set Tx parameters */ 513 pTxData->txDataPortStatus = DEF_TX_PORT_STATUS; 514 pTxData->savePortStatus = DEF_TX_PORT_STATUS; 515 pTxData->txDataCurrentPrivacyInvokedMode = DEF_CURRENT_PRIVACY_INVOKED_MODE; 516 pTxData->saveTxDataCurrentPrivacyInvokedMode = DEF_CURRENT_PRIVACY_INVOKED_MODE; 517 pTxData->txDataEapolEncryptionStatus = DEF_EAPOL_ENCRYPTION_STATUS; 518 pTxData->saveTxDataEapolEncryptionStatus = DEF_EAPOL_ENCRYPTION_STATUS; 519 520 pTxData->txDataIsSchedulerInWork = DEF_IS_SCHEDULER_IN_WORK; 521 pTxData->txDataHalInterfaceStatus = DEF_HAL_INTERFACE_STATUS; 522 523 /* Initialize the parameters related to GWSI and to Scheduler in Work */ 524 pTxData->txDataGwsiInterfaceStatus = GWSI_OPEN; 525 pTxData->txDataIsSchedulerInWork = FALSE; 526 527 pTxData->bCreditCalcTimerRunning = FALSE; 528 529 /* encryption header size */ 530 pTxData->encryptionFieldSize = 0; 531 pTxData->saveEncryptionFieldSize = 0; 532 533 /* configure the packet ID buffer pool */ 534 bufferPool_config( pTxData->hBufferPool, hReport ); 535 536 /* configure the Tx queues (msdu lists) */ 537 /* num of elements is configured by qosMngr */ 538 for (qIndex = 0; qIndex < MAX_NUM_OF_TX_QUEUES; qIndex++) 539 { 540 if( (msduList_ConfigMsduList( pTxData->dataMsduListArr[qIndex], pTxData->hMemMngr, 541 pTxData->hReport,pTxData->hOs,0 )) != OK ) 542 { 543 WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG, 544 ("Error configure DataMsduList num: %d\n",qIndex)); 545 } 546 547 /* 548 * Mark all queues available for TX 549 */ 550 pTxData->txDataAvailableQueue[qIndex] = TRUE; 551 } 552 553 if( (msduList_ConfigMsduList( pTxData->mngMsduList, pTxData->hMemMngr, 554 pTxData->hReport, pTxData->hOs,MANAGEMENT_QUEUE_SIZE )) != OK ) 555 { 556 WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG, 557 ("Error configure MgmtMsduList\n")); 558 } 559 560 /* reset counters */ 561 txData_resetCounters (pTxData); 562 txData_resetDbgCounters (pTxData); 563 564 WLAN_REPORT_INIT(pTxData->hReport, TX_DATA_MODULE_LOG, 565 (".....Tx Data configured successfully\n")); 566 567 #ifdef NO_COPY_NDIS_BUFFERS 568 WLAN_REPORT_INFORMATION(pTxData->hReport, TX_DATA_MODULE_LOG, 569 ("Driver configured to work in NO COPY MSDU BUFFERS.")); 570 #else 571 WLAN_REPORT_INFORMATION(pTxData->hReport, TX_DATA_MODULE_LOG, 572 ("Driver is configured to work in COPY MSDU BUFFERS.")); 573 #endif 574 575 576 return OK; 577 578 } 579 580 /*************************************************************************** 581 * txData_unLoad * 582 **************************************************************************** 583 * DESCRIPTION: This function unload the tx data module. It first free the 584 * MsduLists and then free the Tx data control block 585 * 586 * INPUTS: hTxData - the object 587 * 588 * OUTPUT: 589 * 590 * RETURNS: OK - Unload succesfull 591 * NOK - Unload unsuccesfull 592 ***************************************************************************/ 593 594 TI_STATUS txData_unLoad(TI_HANDLE hTxData) 595 { 596 txData_t *pTxData = (txData_t *)hTxData; 597 TI_STATUS status = OK; 598 int queueIndex; 599 600 /* check parameters validity */ 601 if( pTxData == NULL ) 602 { 603 return NOK; 604 } 605 606 /* free Data queue msdu list */ 607 for(queueIndex = 0;queueIndex < MAX_NUM_OF_TX_QUEUES; queueIndex++) 608 { 609 if (msduList_FreeMsduList( pTxData->dataMsduListArr[queueIndex]) != OK) 610 { 611 WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG, 612 (" txData_unLoad() : fail to free Data MsduList number: %d\n",queueIndex)); 613 status = NOK; 614 } 615 } 616 617 /* free Mgmt queue msdu list */ 618 if (msduList_FreeMsduList( pTxData->mngMsduList) != OK) 619 { 620 WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG, 621 (" txData_unLoad() : fail to free Mgmt MsduList \n")); 622 status = NOK; 623 } 624 625 DistributorMgr_Destroy(pTxData->TxEventDistributor); 626 627 /* free Timer */ 628 utils_nullTimerDestroy(pTxData->hOs, pTxData->pSchedulerTimer); 629 utils_nullTimerDestroy(pTxData->hOs, pTxData->pVadTimer); 630 #ifdef TI_DBG 631 utils_nullTimerDestroy(pTxData->hOs, pTxData->pThroughputTimer); 632 utils_nullTimerDestroy(pTxData->hOs, pTxData->pAirThroughputTimer); 633 utils_nullTimerDestroy(pTxData->hOs, pTxData->pJitterTimer); 634 #endif 635 utils_nullTimerDestroy(pTxData->hOs, pTxData->pCreditTimer); 636 637 /* release the packet ID buffer pool */ 638 bufferPool_destroy( pTxData->hBufferPool ); 639 640 /* free Tx Data control block */ 641 os_memoryFree(pTxData->hOs, pTxData, sizeof(txData_t)); 642 643 return status; 644 } 645 646 /**************************************************************************** 647 * txData_stop * 648 ***************************************************************************** 649 * DESCRIPTION: this function stop the tx data. It empties the tx queues (msdu 650 * lists) from the msdu's and return all tx data parameters to 651 * default values 652 * 653 * INPUTS: hTxData - the object 654 * 655 * OUTPUT: 656 * 657 * RETURNS: OK - stop successful 658 * NOK - stop unsuccessful 659 ****************************************************************************/ 660 661 TI_STATUS txData_stop(TI_HANDLE hTxData) 662 { 663 txData_t *pTxData = (txData_t *)hTxData; 664 int queueIndex; 665 666 pTxData->savePortStatus = pTxData->txDataPortStatus; 667 668 /* stop scheduler timer trigger */ 669 if ( TRUE == pTxData->bSchedulerTimerRunning ) 670 { 671 os_timerStop(pTxData->hOs, pTxData->pSchedulerTimer); 672 } 673 674 /* stop vad timer */ 675 if ( TRUE == pTxData->bVadTimerEnabled ) 676 { 677 os_timerStop(pTxData->hOs, pTxData->pVadTimer); 678 } 679 /* stop throughput timer */ 680 if(pTxData->txThroughputTimerEnable == TRUE) 681 { 682 os_timerStop(pTxData->hOs, pTxData->pThroughputTimer); 683 pTxData->txThroughputTimerEnable = FALSE; 684 } 685 686 /* stop throughput timer */ 687 if (pTxData->txAirThroughputTimerEnable) 688 { 689 os_timerStop (pTxData->hOs, pTxData->pAirThroughputTimer); 690 pTxData->txAirThroughputTimerEnable = FALSE; 691 } 692 693 /* stop credit calculation timer */ 694 if ( pTxData->bCreditCalcTimerRunning ) 695 { 696 os_timerStop(pTxData->hOs, pTxData->pCreditTimer); 697 pTxData->bCreditCalcTimerRunning = FALSE; 698 } 699 700 /* empty Tx data queue from Msdus */ 701 for(queueIndex = 0;queueIndex < MAX_NUM_OF_TX_QUEUES; queueIndex++) 702 { 703 if( msduList_EmptyMsduList( pTxData->dataMsduListArr[queueIndex] ) != OK) 704 { 705 WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG, 706 (" txData_stop() : fail to empty Data Msdu List number: %d\n",queueIndex)); 707 return NOK; 708 } 709 } 710 /* empty Tx Mgmt queue from Msdus */ 711 if( msduList_EmptyMsduList( pTxData->mngMsduList ) != OK) 712 { 713 WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG, 714 (" txData_stop() : fail to empty Mgmt Msdu List \n")); 715 return NOK; 716 } 717 718 /* set Tx parameters to default values */ 719 pTxData->txDataPortStatus = DEF_TX_PORT_STATUS; 720 pTxData->saveTxDataCurrentPrivacyInvokedMode = pTxData->txDataCurrentPrivacyInvokedMode; 721 pTxData->saveTxDataEapolEncryptionStatus = pTxData->txDataEapolEncryptionStatus; 722 pTxData->saveEncryptionFieldSize = pTxData->encryptionFieldSize; 723 724 pTxData->txDataCurrentPrivacyInvokedMode = DEF_CURRENT_PRIVACY_INVOKED_MODE; 725 pTxData->txDataEapolEncryptionStatus = DEF_EAPOL_ENCRYPTION_STATUS; 726 pTxData->encryptionFieldSize = 0; 727 728 729 WLAN_REPORT_INFORMATION(pTxData->hReport, TX_DATA_MODULE_LOG, 730 (" txData_stop() : Succeeded.\n")); 731 732 return OK; 733 734 } 735 736 /**************************************************************************** 737 * txData_start * 738 ***************************************************************************** 739 * DESCRIPTION: this function start the tx data. 740 * 741 * INPUTS: hTxData - the object 742 * 743 * OUTPUT: 744 * 745 * RETURNS: OK - stop succesfull 746 * NOK - stop unsuccesfull 747 ****************************************************************************/ 748 TI_STATUS txData_start(TI_HANDLE hTxData) 749 { 750 txData_t *pTxData = (txData_t *)hTxData; 751 752 /* check parameters validity */ 753 if( pTxData == NULL ) 754 { 755 WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG, 756 (" txData_start() : Illegal value for hTxData\n")); 757 return NOK; 758 } 759 760 pTxData->txDataPortStatus = pTxData->savePortStatus; 761 762 return OK; 763 } 764 765 /**************************************************************************** 766 * txData_recoveryIndication * 767 ***************************************************************************** 768 * DESCRIPTION: this function clears information on recovery. 769 * 770 * INPUTS: hTxData - the object 771 * 772 * OUTPUT: 773 * 774 * RETURNS: 775 ****************************************************************************/ 776 void txData_recoveryIndication (TI_HANDLE hTxData) 777 { 778 txData_t *pTxData = (txData_t *)hTxData; 779 int queueIndex; 780 781 /* Reinitializes packet ID buffer pool (mark all buffers as available) */ 782 bufferPool_reinit (pTxData->hBufferPool); 783 784 /* Empty Tx data queue from Msdus */ 785 for (queueIndex = 0; queueIndex < MAX_NUM_OF_TX_QUEUES; queueIndex++) 786 { 787 if (msduList_EmptyMsduList (pTxData->dataMsduListArr[queueIndex]) != OK) 788 { 789 WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG, 790 (" txData_stop() : fail to empty data MSDU list number: %d\n", queueIndex)); 791 } 792 } 793 794 /* Empty Tx management queue from MSDU's */ 795 if (msduList_EmptyMsduList (pTxData->mngMsduList) != OK) 796 { 797 WLAN_REPORT_ERROR (pTxData->hReport, TX_DATA_MODULE_LOG, 798 (" txData_stop() : fail to empty management MSDU list\n")); 799 } 800 801 /* 802 * Set GWSI interfaces status as 'opened' 803 * because it can be undefined upon recovery 804 */ 805 pTxData->txDataGwsiInterfaceStatus = GWSI_OPEN; 806 807 for (queueIndex = 0; queueIndex < MAX_NUM_OF_TX_QUEUES; queueIndex++) 808 { 809 /* 810 * Mark all queues available for TX 811 */ 812 pTxData->txDataAvailableQueue[queueIndex] = TRUE; 813 } 814 } 815 816 817 /*************************************************************************** 818 * txData_checkQueueSize * 819 **************************************************************************** 820 * DESCRIPTION: Check the Tx Queue size 821 * 822 * INPUTS: hTxData - the object 823 * 824 * OUTPUT: 825 * 826 * RETURNS: OK 827 * NOK - The queue is full 828 ***************************************************************************/ 829 TI_STATUS txData_checkQueueSize(TI_HANDLE hTxData,UINT8 qIndex) 830 { 831 txData_t *pTxData = (txData_t *)hTxData; 832 TI_STATUS Status = OK; 833 834 txData_startTxScheduler(pTxData); 835 836 if (pTxData->dataMsduListArr[qIndex]->CurrNumOfMsdu == pTxData->dataMsduListArr[qIndex]->maxNumOfMsdu) 837 Status = NOK; 838 839 return Status; 840 } 841 842 /*************************************************************************** 843 * txData_copyPacketToMsdu * 844 **************************************************************************** 845 * DESCRIPTION: 846 * 847 * INPUTS: hTxData - the object 848 * 849 * OUTPUT: 850 * 851 * RETURNS: OK 852 * NOK - The queue is full 853 ***************************************************************************/ 854 TI_STATUS txData_copyPacketToMsdu(TI_HANDLE hTxData,mem_MSDU_T **pMsdu, int FreeOldMsdu) 855 { 856 #ifdef NO_COPY_NDIS_BUFFERS 857 txData_t *pTxData = (txData_t *)hTxData; 858 859 TI_STATUS Status = OK; 860 mem_BD_T *pCurrBd; 861 mem_MSDU_T *tempMsdu; 862 UINT8 *pMsduData; 863 UINT8 *pCurrBufData; 864 dot11_header_t *pdot11Header; 865 866 867 /* 868 * Allocate MSDU+BD+BUFFER+TX_DESCRIPTOR_SIZE to copy to !! 869 */ 870 if(wlan_memMngrAllocMSDU(pTxData->hMemMngr,&tempMsdu,(*pMsdu)->dataLen+TX_TOTAL_OFFSET_BEFORE_DATA,TX_MODULE) != OK) 871 { 872 WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG, 873 (" txData_copyPacketToMsdu() : No Memory in MemMgr \n")); 874 875 return NOK; 876 } 877 878 tempMsdu->dataLen = 0; 879 tempMsdu->firstBDPtr->length = 0; 880 tempMsdu->txFlags = (*pMsdu)->txFlags; 881 882 pCurrBd = (*pMsdu)->firstBDPtr; 883 pMsduData = tempMsdu->firstBDPtr->data + TX_TOTAL_OFFSET_BEFORE_DATA; 884 while(pCurrBd) 885 { 886 pCurrBufData = pCurrBd->data + pCurrBd->dataOffset; 887 /* Copy the packet */ 888 os_memoryCopy(pTxData->hOs, pMsduData, pCurrBufData, pCurrBd->length); 889 tempMsdu->dataLen += pCurrBd->length - TNETWIF_WRITE_OFFSET_BYTES; 890 tempMsdu->firstBDPtr->length += pCurrBd->length; 891 pMsduData += pCurrBd->length; 892 893 pCurrBd = pCurrBd->nextBDPtr; 894 } 895 896 tempMsdu->headerLen = (*pMsdu)->headerLen; 897 898 txData_convertEthToWlanHeader( pTxData, tempMsdu ); 899 900 /* set wep bit if needed */ 901 if((tempMsdu->txFlags & TX_DATA_DATA_MSDU) && (pTxData->txDataCurrentPrivacyInvokedMode)) 902 { 903 pdot11Header = (dot11_header_t*)(memMgr_BufData(pMsdu->firstBDPtr) + memMgr_BufOffset(pMsdu->firstBDPtr)); 904 pdot11Header->fc |= DOT11_FC_WEP; 905 } 906 else if ((tempMsdu->txFlags & TX_DATA_EAPOL_MSDU ) && (pTxData->txDataEapolEncryptionStatus)) 907 { 908 pdot11Header = (dot11_header_t*)(memMgr_BufData(pMsdu->firstBDPtr) + memMgr_BufOffset(pMsdu->firstBDPtr)); 909 pdot11Header->fc |= DOT11_FC_WEP; 910 } 911 912 if (FreeOldMsdu) 913 wlan_memMngrFreeMSDU(pTxData->hMemMngr, memMgr_MsduHandle((*pMsdu))); 914 915 (*pMsdu) = tempMsdu; 916 917 #endif 918 919 return OK; 920 } 921 922 /*************************************************************************** 923 * txData_sendPktToWlan * 924 **************************************************************************** 925 * DESCRIPTION: This function is called by the Os Abstraction Layer in order 926 * to send packet to the wireless LAN. It calls the header 927 * conversion function and passes the to sendMsdu function. 928 * 929 * INPUTS: hTxData - the object 930 * pMsdu - pointer the packet in 802.3 format 931 * 932 * OUTPUT: 933 * 934 * RETURNS: OK 935 * NOK 936 ***************************************************************************/ 937 938 TI_STATUS txData_sendPktToWlan(TI_HANDLE hTxData, mem_MSDU_T *pMsdu, UINT8 pkt_DTag) 939 { 940 EthernetHeader_t *pEthHeader; 941 UINT16 TypeLength; 942 TI_STATUS Status; 943 mem_BD_T* tempBd; 944 BOOL UseConvertHeader = TRUE; 945 946 txData_t *pTxData = (txData_t *)hTxData; 947 948 /* check parameters validity */ 949 if( pTxData == NULL || pMsdu == NULL ) 950 { 951 return NOK; 952 } 953 954 pEthHeader = (EthernetHeader_t*)(memMgr_BufData(pMsdu->firstBDPtr)+memMgr_BufOffset(pMsdu->firstBDPtr)); 955 956 /* check if the frame is multicast/broadcast - need for the transmission rate */ 957 if(IsMacAddressGroup( &pEthHeader->DstAddr )) 958 pMsdu->txFlags |= TX_DATA_MULTICAST_FRAME; 959 960 TypeLength = pEthHeader->TypeLength; 961 962 /* Call the Classify function in the Control Module to set the qosTag of the MSDU */ 963 if (ctrlData_ClsfrClassifyTxMSDU(pTxData->hCtrlData, pMsdu, pkt_DTag) != OK) 964 { 965 WLAN_REPORT_DEBUG_TX(pTxData->hReport, 966 (" txData_sendPktToWlan(): No matching classifier found\n")); 967 } 968 969 970 /* filter MSDU according to Tx Port Status and the Eth Type */ 971 if ( pTxData->txDataPortStatus != OPEN ) 972 { 973 int queueIndex; 974 int acIndex; 975 976 WLAN_REPORT_WARNING(pTxData->hReport, TX_DATA_MODULE_LOG, 977 (" txData_sendPktToWlan() : try to transmit Msdu while port is not open (txDataPortStatus = 0x%x)\n", pTxData->txDataPortStatus)); 978 979 /* Find AC and Tx-queue in order to update the correct Queue measurements */ 980 acIndex = GET_WME_AC_TYPE_FROM_MSDU(pMsdu); 981 queueIndex = GET_QUEUE_INDEX(pTxData,acIndex); 982 983 984 /* updating the measurements - dropped packet counter */ 985 pTxData->txDataReportedCounters[queueIndex].OtherFailCounter++; 986 pTxData->txDataReportedCounters[queueIndex].NumPackets++; 987 988 if((pTxData->txDataPortStatus == CLOSE) || (pTxData->txDataPortStatus == OPEN_NOTIFY) ) 989 { 990 WLAN_REPORT_WARNING(pTxData->hReport, TX_DATA_MODULE_LOG, 991 (" txData_sendPktToWlan() : try to transmit Msdu while port is not open (txDataPortStatus = 0x%x)\n", pTxData->txDataPortStatus)); 992 993 /* In case the function return status is NOK, no need to call Os free function */ 994 /* Set freefunc in the msdu to null. In this case the MemMngr will not call */ 995 /* the Os free function */ 996 memMgr_MsduFreeFuncGet(pMsdu) = NULL; 997 998 /* free MSDU */ 999 if( (wlan_memMngrFreeMSDU(pTxData->hMemMngr, memMgr_MsduHandle(pMsdu))) != OK ) 1000 { 1001 WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG, 1002 (" txData_sendPktToWlan() : free msdu failed \n")); 1003 } 1004 1005 return NOK; 1006 } 1007 1008 /* filter Data frames while port is open only for Eapol's */ 1009 if( (pTxData->txDataPortStatus == OPEN_EAPOL) && (TypeLength != EAPOL_PACKET) ) 1010 { 1011 WLAN_REPORT_WARNING(pTxData->hReport, TX_DATA_MODULE_LOG, 1012 (" txData_sendPktToWlan() : try to transmit Non Eapol packet while port is open for eapols only\n")); 1013 1014 /* In case the function return status is NOK, no need to call Os free function. */ 1015 /* Set freefunc in the msdu to null. In this case the MemMngr will not call */ 1016 /* the Os free function - because the return staus to the Os is NOK the buffer */ 1017 /* free by the Os */ 1018 memMgr_MsduFreeFuncGet(pMsdu) = NULL; 1019 1020 /* frre MSDU */ 1021 if ((wlan_memMngrFreeMSDU(pTxData->hMemMngr, memMgr_MsduHandle(pMsdu))) != OK) 1022 { 1023 WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG, 1024 (" txData_sendPktToWlan() : free msdu failed \n")); 1025 } 1026 1027 return NOK; 1028 } 1029 } 1030 1031 /* PORT IS OPEN */ 1032 #ifdef CORE_TX_DBG 1033 WLAN_REPORT_INFORMATION(pTxData->hReport, TX_DATA_MODULE_LOG, 1034 (" txData_sendPktToWlan: port is open \n")); 1035 #endif 1036 1037 1038 if( TypeLength != EAPOL_PACKET ) 1039 { 1040 pMsdu->txFlags |= TX_DATA_DATA_MSDU; 1041 } 1042 else 1043 { 1044 WLAN_REPORT_INFORMATION(pTxData->hReport, TX_DATA_MODULE_LOG, 1045 (" txData_sendPktToWlan() : Tx an EAPOL frame tranferred to HAL\n")); 1046 1047 /* because EAPOL is sent from Mgmt queue */ 1048 pMsdu->txFlags |= TX_DATA_EAPOL_MSDU; 1049 } 1050 1051 UseConvertHeader = TRUE; /* a patch for WinCe */ 1052 #ifdef NO_COPY_NDIS_BUFFERS 1053 if (pMsdu->txFlags & TX_DATA_FROM_OS) 1054 UseConvertHeader = FALSE; /* don't convert on external (OS) packets */ 1055 #endif 1056 1057 if (UseConvertHeader == TRUE) 1058 { 1059 /* Header conversion from Ethernet to 802.11 */ 1060 txData_convertEthToWlanHeader( pTxData, pMsdu ); 1061 } 1062 1063 /* update last BD */ 1064 tempBd = pMsdu->firstBDPtr; 1065 while(tempBd->nextBDPtr) 1066 { 1067 tempBd = tempBd->nextBDPtr; 1068 } 1069 pMsdu->lastBDPtr = tempBd; 1070 1071 Status = txData_txSendMsdu( pTxData, pMsdu ); 1072 if( Status == NOK ) 1073 { 1074 WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG, 1075 (" txData_sendPktToWlan() : txData_txSendMsdu failed \n")); 1076 } 1077 1078 if ((OK == Status) && (GET_WME_AC_TYPE_FROM_MSDU(pMsdu) == QOS_AC_VO)) 1079 { 1080 txData_resetVadTimer(pTxData); 1081 } 1082 return Status; 1083 } 1084 1085 /*************************************************************************** 1086 * txData_txSendMsdu * 1087 **************************************************************************** 1088 * DESCRIPTION: This function is insert the MSDU to transmit to the proper 1089 * tx queue and give a trigger to the scheduler to start 1090 * transmission to the wireless LAN. 1091 * 1092 * INPUTS: hTxData - the object 1093 * pMsdu - pointer the MSDU in 802.11 format 1094 * 1095 * OUTPUT: 1096 * 1097 * RETURNS: OK 1098 * NOK 1099 ***************************************************************************/ 1100 1101 TI_STATUS txData_txSendMsdu(TI_HANDLE hTxData, mem_MSDU_T *pMsdu ) 1102 { 1103 dot11_header_t *pdot11Header; 1104 TI_STATUS Status = OK; 1105 int queueIndex; 1106 acTrfcType_e acIndex; 1107 1108 1109 txData_t *pTxData = (txData_t *)hTxData; 1110 1111 /* ctrlData_txMsdu(pTxData->hCtrlData,&pMsdu); 4x related */ 1112 1113 if(pMsdu == NULL) 1114 { 1115 WLAN_REPORT_INFORMATION(pTxData->hReport, TX_DATA_MODULE_LOG, 1116 (" txData_txSendMsdu() : DISCARD Packet...... \n")); 1117 txData_startTxScheduler(pTxData); 1118 1119 return NOK; 1120 } 1121 1122 1123 #ifndef NO_COPY_NDIS_BUFFERS /* buffers are copied by OAL*/ 1124 /* set wep bit if needed */ 1125 if((pMsdu->txFlags & TX_DATA_DATA_MSDU) && (pTxData->txDataCurrentPrivacyInvokedMode)) 1126 { 1127 /* update offset of header */ 1128 pdot11Header = (dot11_header_t*)(memMgr_BufData(pMsdu->firstBDPtr) + memMgr_BufOffset(pMsdu->firstBDPtr)); 1129 pdot11Header->fc |= DOT11_FC_WEP; 1130 } 1131 else if ((pMsdu->txFlags & TX_DATA_EAPOL_MSDU ) && (pTxData->txDataEapolEncryptionStatus)) 1132 { 1133 /* update offset of header */ 1134 pdot11Header = (dot11_header_t*)(memMgr_BufData(pMsdu->firstBDPtr) + memMgr_BufOffset(pMsdu->firstBDPtr)); 1135 pdot11Header->fc |= DOT11_FC_WEP; 1136 } 1137 #endif /*NO_COPY_NDIS_BUFFERS*/ 1138 1139 #ifdef EXC_MODULE_INCLUDED 1140 if ((pMsdu->txFlags & TX_DATA_IAPP_MSDU) && (pTxData->txDataCurrentPrivacyInvokedMode)) 1141 { 1142 /* update offset of header */ 1143 pdot11Header = (dot11_header_t*)(memMgr_BufData(pMsdu->firstBDPtr) + memMgr_BufOffset(pMsdu->firstBDPtr)); 1144 pdot11Header->fc |= DOT11_FC_WEP; 1145 } 1146 #endif 1147 1148 1149 WLAN_REPORT_DEBUG_TX(pTxData->hReport, 1150 (" txData_txSendMsdu() : Sending PAcket pMsdu %x pMsdu->txFlags %x \n",pMsdu,pMsdu->txFlags)); 1151 1152 /* insert the msdu to the the appropriate queue */ 1153 if( (pMsdu->txFlags & TX_DATA_DATA_MSDU) || (pMsdu->txFlags & TX_DATA_NULL_MSDU) ) 1154 { 1155 /* Find Tx-queue and AC to use for Tx, and if downgraded from original one update the UP. */ 1156 txData_selectQueueAndUpdateUserPriority (pTxData, pMsdu, &queueIndex, &acIndex); 1157 1158 /* set insertion time for further expiry timeout calculation */ 1159 pMsdu->insertionTime = os_timeStampUs (pTxData->hOs); 1160 1161 /* see if the frame is tagged VO. */ 1162 /* Note: Check actual tag even if current not working in WME, to support voice anyway. */ 1163 if( GET_WME_AC_TYPE_FROM_MSDU(pMsdu) == QOS_AC_VO) 1164 { 1165 /* 1166 * If the frame is tagged VO and power save is on, send psPoll before the VO frame. 1167 */ 1168 if(txData_acVoPsPollMode(pTxData) == TRUE) 1169 { 1170 mem_MSDU_T *pMsduPsPoll; 1171 1172 if(txData_getPsPollFrame(pTxData,&pMsduPsPoll) == OK) 1173 { 1174 /* increment debug counters */ 1175 pTxData->txDataDbgCounters.dbgInsertToMsduListBytes[queueIndex] += pMsduPsPoll->dataLen; 1176 pTxData->txDataDbgCounters.dbgInsertToMsduListPackets[queueIndex]++; 1177 1178 /* set insertion time for further expiry timeout calculation */ 1179 pMsduPsPoll->insertionTime = os_timeStampUs (pTxData->hOs); 1180 1181 /* insert to queueIndex queue */ 1182 if( msduList_Insert( pTxData->dataMsduListArr[queueIndex] , &pMsduPsPoll ) != OK ) 1183 { 1184 pTxData->txDataDbgCounters.dbgDropedFromMsduListPackets[queueIndex]++; 1185 /* the first msdu in list has removed and the new one has inserted */ 1186 WLAN_REPORT_WARNING(pTxData->hReport, TX_DATA_MODULE_LOG, 1187 (" txData_sendPktToWlan() : Msdu List num %d was full \n",queueIndex)); 1188 1189 /* free the msdu which removed from the list (returned in pMsdu) */ 1190 /*---------------------------------------------------------------*/ 1191 /* set msdu tx status to Fail (this status is used by OS) */ 1192 memMgr_MsduFreeArg2Get(pMsduPsPoll) = NOK; 1193 1194 /* free the msdu */ 1195 wlan_memMngrFreeMSDU(pTxData->hMemMngr, memMgr_MsduHandle(pMsduPsPoll)); 1196 pTxData->txDataDbgCounters.dbgDropedPacketsCounter++; 1197 }/*msduList_Insert*/ 1198 }/*txData_getPsPollFrame*/ 1199 }/*txData_acVoPsPollMode*/ 1200 } 1201 1202 /* insert to data queue */ 1203 /* if we didn't succeed to insert psPolls exclude VO packet also */ 1204 if( msduList_Insert( pTxData->dataMsduListArr[queueIndex] , &pMsdu ) != OK ) 1205 { 1206 1207 pTxData->txDataDbgCounters.dbgDropedFromMsduListPackets[queueIndex]++; 1208 /* the first msdu in list has removed and the new one has inserted */ 1209 WLAN_REPORT_WARNING(pTxData->hReport, TX_DATA_MODULE_LOG, 1210 (" txData_txSendMsdu() : Data Msdu [%d] List was full \n",queueIndex)); 1211 1212 /* free the msdu which removed from the list (returned in pMsdu) */ 1213 /*---------------------------------------------------------------*/ 1214 /* set msdu tx status to Fail (this status is used by OS) */ 1215 memMgr_MsduFreeArg2Get(pMsdu) = NOK; 1216 1217 /* free the msdu */ 1218 wlan_memMngrFreeMSDU(pTxData->hMemMngr, memMgr_MsduHandle(pMsdu)); 1219 pTxData->txDataDbgCounters.dbgDropedPacketsCounter++; 1220 1221 pTxData->txDataReportedCounters[queueIndex].NumPackets++; 1222 pTxData->txDataReportedCounters[queueIndex].OtherFailCounter++; 1223 1224 return OK; 1225 } 1226 1227 /* increament debug counters */ 1228 pTxData->txDataDbgCounters.dbgInsertToMsduListBytes[queueIndex] += pMsdu->dataLen; 1229 pTxData->txDataDbgCounters.dbgInsertToMsduListPackets[queueIndex]++; 1230 1231 WLAN_REPORT_DEBUG_TX(pTxData->hReport, 1232 (" txData_txSendMsdu() : insert data packet to queue # %d \n",queueIndex)); 1233 } 1234 else 1235 { 1236 /* Management frame, Eapol and null frame (for measuring a non serving channel) 1237 are also sent from the mgmt queue */ 1238 1239 /* set insertion time for further expiry timeout calculation */ 1240 pMsdu->insertionTime = os_timeStampUs (pTxData->hOs); 1241 1242 WLAN_REPORT_DEBUG_TX(pTxData->hReport, 1243 (" txData_txSendMsdu() : insert mngt packet to Management queue pMsdu %x \n",pMsdu)); 1244 1245 if( msduList_Insert( pTxData->mngMsduList , &pMsdu ) != OK ) 1246 { 1247 /* the first msdu in list has removed and the new one has inserted */ 1248 WLAN_REPORT_WARNING(pTxData->hReport, TX_DATA_MODULE_LOG, 1249 (" txData_txSendMsdu() : Mgmt Msdu List was full \n")); 1250 1251 /* free the msdu which removed from the list (returned in pMsdu) */ 1252 /*---------------------------------------------------------------*/ 1253 /* set msdu tx status to Fail (this status is used by OS) */ 1254 memMgr_MsduFreeArg2Get(pMsdu) = NOK; 1255 1256 /* free the msdu */ 1257 wlan_memMngrFreeMSDU(pTxData->hMemMngr, memMgr_MsduHandle(pMsdu)); 1258 pTxData->txDataDbgCounters.dbgDropedPacketsCounter++; 1259 } 1260 } 1261 1262 { 1263 /* call the scheduler in order to transmit the frame to the Hal */ 1264 Status = txData_startTxScheduler(pTxData); 1265 if ( Status == NOK ) 1266 { 1267 WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG, 1268 (" txData_txSendMsdu() : txData_startTxScheduler error \n")); 1269 } 1270 } 1271 1272 /* this is the status of the current Msdu */ 1273 return OK; 1274 } 1275 1276 /*************************************************************************** 1277 * txData_startTxScheduler * 1278 **************************************************************************** 1279 * DESCRIPTION: This function start the transmission process. 1280 * It select msdu to transmit from the tx queues and send 1281 * it to the Hal 1282 * 1283 * INPUTS: hTxData - the object 1284 * 1285 * OUTPUT: 1286 * 1287 * RETURNS: OK 1288 * NOK 1289 ***************************************************************************/ 1290 1291 TI_STATUS txData_startTxScheduler(TI_HANDLE hTxData) 1292 { 1293 txData_t *pTxData = (txData_t *)hTxData; 1294 mem_MSDU_T *pMsdu; 1295 MsduList_t *pMsduList = NULL; 1296 txData_attr_t txAttr; 1297 UINT8 count, selectedQueueIndex; 1298 TI_STATUS txStatus; 1299 txPacketIdAttr_t *pPacketId; 1300 dot11_header_t *pDot11Header; 1301 bssType_e currBssType; 1302 macAddress_t currBssId; 1303 UINT32 msduTimeToExpiry; 1304 1305 #ifdef SUPPORT_4X 1306 hwTxInformation_t hwTxInformation; 1307 BOOL fourXEnable; 1308 #endif 1309 1310 /* check if HAL is open now - used for recovery only!!! */ 1311 if ( pTxData->txDataHalInterfaceStatus == TX_DATA_CLOSED ) 1312 { 1313 return OK; /* TODO ronen: doesn't seem to be used any more, remove */ 1314 } 1315 1316 /* Checking if Tx is now disabled */ 1317 if(pTxData->txDisable == DISABLE_IMMEDIATELY) 1318 { 1319 WLAN_REPORT_WARNING(pTxData->hReport, TX_DATA_MODULE_LOG, 1320 (" txData_startTxScheduler() : Tx Disabled!!! \n")); 1321 1322 /* start scheduler timer */ 1323 if ( FALSE == pTxData->bSchedulerTimerRunning ) 1324 { 1325 os_timerStart( pTxData->hOs, pTxData->pSchedulerTimer, SCHEDULER_TIMER, FALSE ); 1326 pTxData->bSchedulerTimerRunning = TRUE; 1327 } 1328 1329 pTxData->txDataIsSchedulerInWork = FALSE; 1330 return OK; 1331 } 1332 1333 /* 1334 * in case of non serialized system no need to 1335 * run the scheduler if it is already in work 1336 */ 1337 if(pTxData->txDataIsSchedulerInWork == TRUE) 1338 { 1339 WLAN_REPORT_WARNING(pTxData->hReport, TX_DATA_MODULE_LOG, 1340 (" txData_startTxScheduler() : Scheduler already in work...........!!!! \n")); 1341 return OK; 1342 } 1343 else 1344 { 1345 pTxData->txDataIsSchedulerInWork = TRUE; 1346 } 1347 1348 /* try to transmit DEF_SCHEDULER_THRESHOLD MSDUs */ 1349 count = DEF_SCHEDULER_THRESHOLD; 1350 1351 /* 1352 * if non of the queues is available non msdu will be selected 1353 */ 1354 1355 while ( (0 < count--) && (GWSI_OPEN == pTxData->txDataGwsiInterfaceStatus) ) 1356 { 1357 /* select queue to transmit from */ 1358 if( txData_schedulerSelectQueueToTransmitFrom( pTxData, &pMsduList,&selectedQueueIndex ) != TX_QUEUE_SELECTED_OK) 1359 { 1360 WLAN_REPORT_DEBUG_TX(pTxData->hReport, 1361 (" txData_startTxScheduler() : No Msdu waiting to transmit \n")); 1362 1363 pTxData->txDataIsSchedulerInWork = FALSE; 1364 return OK; 1365 } 1366 1367 WLAN_REPORT_DEBUG_TX(pTxData->hReport, 1368 (" txData_startTxScheduler() : txData_schedulerSelectQueueToTransmitFrom Returned from selectedQueueIndex %d \n",selectedQueueIndex)); 1369 1370 1371 #ifdef SUPPORT_4X 1372 1373 ctrlData_get4xStatus(pTxData->hCtrlData,&fourXEnable); 1374 1375 if(fourXEnable == TRUE && pMsduList != pTxData->mngMsduList) 1376 { 1377 /* 1378 * receive Acx tx queuue information for transmission decision 1379 */ 1380 whalTx_getTxQueueInfo(pTxData->hWhalTx, 1381 DEFAULT_QUEUE_TO_HAL, 1382 &hwTxInformation.hwNumOfFreeMsdu, 1383 &hwTxInformation.hwNumOfBusyMsdu, 1384 &hwTxInformation.hwNumOfFreeBDs, 1385 &hwTxInformation.hwTotalAvailMem ); 1386 1387 /* 1388 * call ctrl Data - DequeueMsdu... 1389 * pMsdu - the msdu to transmit. 1390 * txAttr - the tx attributes for msdu transmission 1391 */ 1392 status = ctrlData_txDequeueMsdu(pTxData->hCtrlData, &pMsdu, pMsduList, &txAttr, &hwTxInformation); 1393 1394 if(status == DO_NOT_SEND_MSDU) 1395 { 1396 WLAN_REPORT_ERROR(pTxData->hReport, 1397 (" txData_startTxScheduler() : TX_STATUS_PENDING \n")); 1398 1399 pTxData->txDataIsSchedulerInWork = FALSE; 1400 1401 return TX_STATUS_PENDING; 1402 } 1403 } 1404 1405 #else /* if not SUPPORT_4X */ 1406 1407 { 1408 /* increment debug counter */ 1409 pTxData->txDataDbgCounters.dbgScheduledOutPackets[selectedQueueIndex]++; 1410 1411 if( msduList_WatchFirst( pMsduList ,&pMsdu) != OK ) 1412 { 1413 WLAN_REPORT_ERROR( pTxData->hReport, TX_DATA_MODULE_LOG, 1414 ("Unable to retrieve first MSDU from queue index:%d\n", selectedQueueIndex) ); 1415 pTxData->txDataIsSchedulerInWork = FALSE; 1416 return OK; 1417 } 1418 1419 WLAN_REPORT_DEBUG_TX(pTxData->hReport, 1420 (" txData_startTxScheduler() : After msduList_WatchFirst pMsdu %d \n",pMsdu)); 1421 1422 #ifdef NO_COPY_NDIS_BUFFERS 1423 1424 if(pMsdu->txFlags & TX_DATA_FROM_OS) 1425 { 1426 if(txData_copyPacketToMsdu(pTxData, &pMsdu, 1 /* do FreeOldMsdu */) != OK) 1427 { 1428 WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG, 1429 (" txData_startTxScheduler() : txData_copyPacketToMsdu FAILED \n")); 1430 1431 pTxData->txDataIsSchedulerInWork = FALSE; 1432 return NOK; 1433 } 1434 } 1435 1436 #endif /* NO_COPY_NDIS_BUFFERS */ 1437 1438 } 1439 1440 #endif /* SUPPORT_4X */ 1441 1442 /* check MSDU expiry time, and if it didn't expire send it to GWSI */ 1443 if ((msduTimeToExpiry = txDataTimeToMsduExpiry (hTxData, pMsdu, selectedQueueIndex)) == 0) 1444 { 1445 /* MSDU time expired - drop it */ 1446 WLAN_REPORT_INFORMATION(pTxData->hReport, TX_DATA_MODULE_LOG, 1447 ("txData_startTxScheduler drop msdu due to expiry time, queueId = %d \n",selectedQueueIndex)); 1448 1449 /* Get MSDU with dequeuing */ 1450 if ( (msduList_GetFirst( pMsduList, &pMsdu )) != OK ) 1451 { 1452 /* No MSDU is waiting to transmit */ 1453 WLAN_REPORT_ERROR (pTxData->hReport, TX_DATA_MODULE_LOG, 1454 ("%s: can't get Msdu from pMsduList[ %d ] \n", __FUNCTION__, selectedQueueIndex)); 1455 pTxData->txDataIsSchedulerInWork = FALSE; 1456 return NOK; 1457 } 1458 1459 1460 pTxData->txDataDbgCounters.dbgDroppedDueExpiryTimePackets[selectedQueueIndex]++; 1461 1462 pTxData->txDataReportedCounters[selectedQueueIndex].NumPackets++; 1463 pTxData->txDataReportedCounters[selectedQueueIndex].OtherFailCounter++; 1464 1465 /* free the MSDU */ 1466 memMgr_MsduFreeArg2Get(pMsdu) = OK; 1467 1468 if( (wlan_memMngrFreeMSDU(pTxData->hMemMngr, memMgr_MsduHandle(pMsdu))) != OK ) 1469 { 1470 WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG, 1471 (" txData_startTxScheduler() : free msdu failed \n")); 1472 } 1473 1474 /* continue to next packet */ 1475 continue; 1476 } 1477 1478 /* Collect txAttr from control */ 1479 ctrlData_getTxAttributes(pTxData->hCtrlData, pMsdu->txFlags, &txAttr, selectedQueueIndex); 1480 1481 /* allocate a buffer for packet ID storage */ 1482 pPacketId = (txPacketIdAttr_t*)bufferPool_allocateBuffer( pTxData->hBufferPool ); 1483 if ( BUFFER_POOL_NO_BUFFER == pPacketId ) 1484 { 1485 WLAN_REPORT_ERROR (pTxData->hReport, TX_DATA_MODULE_LOG, 1486 (" %s : No PacketID Available!!\n", __FUNCTION__)); 1487 1488 /* shouldn't happen, since we have enough packet ID buffers as the FW has TX descriptors! */ 1489 pTxData->txDataIsSchedulerInWork = FALSE; 1490 return NOK; 1491 } 1492 1493 /* store necessary information in packet ID */ 1494 pPacketId->pMsdu = pMsdu; 1495 if (pMsdu->txFlags & TX_DATA_DATA_MSDU) 1496 { 1497 pPacketId->bDataMsdu = TRUE; 1498 } 1499 else 1500 { 1501 pPacketId->bDataMsdu = FALSE; 1502 } 1503 pPacketId->txQid = selectedQueueIndex; 1504 pPacketId->txCompleteFlags = pMsdu->txCompleteFlags; 1505 pPacketId->maxTransmitRate = txAttr.HwRate; 1506 #ifdef TI_DBG 1507 os_memoryZero (pTxData->hOs, pPacketId->timeStamp, sizeof(pPacketId->timeStamp)); 1508 pPacketId->timeStamp[0] = os_timeStampUs (pTxData->hOs); 1509 #endif 1510 1511 pPacketId->msduDataLen = pMsdu->dataLen; 1512 1513 /* destination mac */ 1514 pDot11Header = (dot11_header_t*)(memMgr_BufData(pMsdu->firstBDPtr)+ memMgr_BufOffset(pMsdu->firstBDPtr)); 1515 ctrlData_getCurrBssTypeAndCurrBssId(pTxData->hCtrlData, &currBssId, &currBssType); 1516 if(currBssType == BSS_INDEPENDENT) 1517 MAC_COPY( pTxData->hOs, &(pPacketId->destinationMac), &(pDot11Header->address1) ); 1518 else 1519 MAC_COPY( pTxData->hOs, &(pPacketId->destinationMac), &(pDot11Header->address3) ); 1520 1521 /* mark in packet ID that XFER done and TX complete were not called yet */ 1522 pPacketId->bTxCompleteCalled = pPacketId->bXferDoneCalled = FALSE; 1523 1524 1525 #ifdef TI_DBG 1526 if ((pMsdu->txFlags & TX_DATA_DATA_MSDU) != 0 && pMsdu->timeStampNum > 0) 1527 { 1528 UINT32 uCoreDelay; 1529 1530 /* add time stamp */ 1531 wlan_memMngrAddTimeStamp (pTxData->hMemMngr, pMsdu); 1532 1533 uCoreDelay = pMsdu->timeStamp[pMsdu->timeStampNum - 1] - pMsdu->timeStamp[0]; 1534 1535 /* update core delay and jitter */ 1536 pTxData->txJitter[selectedQueueIndex].jitter.core += 1537 ABS (pTxData->txJitter[selectedQueueIndex].last_delay.core - uCoreDelay); 1538 pTxData->txJitter[selectedQueueIndex].last_delay.core = uCoreDelay; 1539 pTxData->txJitter[selectedQueueIndex].delay.core += uCoreDelay; 1540 pTxData->txJitter[selectedQueueIndex].count.core ++; 1541 if (uCoreDelay > pTxData->txJitter[selectedQueueIndex].max_delay.core) 1542 pTxData->txJitter[selectedQueueIndex].max_delay.core = uCoreDelay; 1543 } 1544 #endif 1545 1546 /* send the packet to the GWSI layer */ 1547 txStatus = CORE_AdaptTx_SendPacket( CORE_AdaptTx_handle, selectedQueueIndex, pMsdu, &txAttr, (UINT32)pPacketId, msduTimeToExpiry ); 1548 1549 WLAN_REPORT_DEBUG_TX (pTxData->hReport, 1550 ("txData_startTxScheduler(): called CORE_AdaptTx_SendPacket pMsdu=%d, selectedQueueIndex=%d,txStatus=%d\n", 1551 pMsdu,selectedQueueIndex,txStatus)); 1552 1553 switch ( txStatus ) 1554 { 1555 /* 1556 * XFER_DONE is received when the packet has been synchronously transferred to the FW. 1557 * in this case, XFER complete will not be called, only TX complete 1558 */ 1559 case SEND_PACKET_XFER_DONE: 1560 1561 pPacketId->driverHandlingTime = (os_timeStampUs (pTxData->hOs) - pMsdu->insertionTime) / 1000; 1562 1563 /* Get MSDU with dequeuing */ 1564 if ( (msduList_GetFirst( pMsduList, &pMsdu )) != OK ) 1565 { 1566 /* No MSDU is waiting to transmit */ 1567 WLAN_REPORT_ERROR (pTxData->hReport, TX_DATA_MODULE_LOG, 1568 (" %s : can't get Msdu from pMsduList[ %d ] \n", __FUNCTION__, selectedQueueIndex)); 1569 pTxData->txDataIsSchedulerInWork = FALSE; 1570 return NOK; 1571 } 1572 1573 /* free the MSDU, since XFER complete won't be called */ 1574 if ( (wlan_memMngrFreeMSDU(pTxData->hMemMngr, memMgr_MsduHandle(pMsdu))) != OK ) 1575 { 1576 WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG, 1577 ("%s: free msdu failed \n", __FUNCTION__)); 1578 pTxData->txDataIsSchedulerInWork = FALSE; 1579 return NOK; 1580 } 1581 else 1582 { 1583 pTxData->txDataDbgCounters.dbgNumOfMsduFreeInTxTransfer[ pPacketId->txQid ]++; 1584 } 1585 1586 /* Nullify the MSDU pointer, just in case */ 1587 pPacketId->pMsdu = NULL; 1588 1589 /* mark in packet ID that XFER done was called */ 1590 pPacketId->bXferDoneCalled = TRUE; 1591 1592 /* increment debug counter */ 1593 pTxData->txDataDbgCounters.dbgSendToGwsiQosPackets[ selectedQueueIndex ]++; 1594 pTxData->txDataDbgCounters.dbgNumOfMsduXferDoneInShceduler[ selectedQueueIndex ]++; 1595 break; 1596 1597 /* 1598 * SUCCESS is received when the packet has not yet been sent to the FW, but another packet 1599 * transfer can start immediately 1600 */ 1601 case SEND_PACKET_SUCCESS: 1602 /* Get msdu with dequeuing */ 1603 if ( (msduList_GetFirst( pMsduList, &pMsdu )) != OK ) 1604 { 1605 /* No msdu is waiting to transmit */ 1606 WLAN_REPORT_ERROR (pTxData->hReport, TX_DATA_MODULE_LOG, 1607 (" %s : can't get Msdu from pMsduList[ %d ] \n", __FUNCTION__, selectedQueueIndex)); 1608 pTxData->txDataIsSchedulerInWork = FALSE; 1609 return NOK; 1610 } 1611 1612 /* increment debug counter */ 1613 pTxData->txDataDbgCounters.dbgNumOfMsduSuccessInScheduler[ selectedQueueIndex ]++; 1614 pTxData->txDataDbgCounters.dbgSendToGwsiQosPackets[selectedQueueIndex]++; 1615 break; 1616 1617 /* 1618 * PENDING is received when the packet has been received by the GWSI layer, and the double buffer 1619 * mechanism is busy. It indicates that no more packets (from all queues) are to be sent until a 1620 * XFER complete indication is received 1621 */ 1622 case SEND_PACKET_PENDING: 1623 /* Get msdu with dequeuing */ 1624 if ( (msduList_GetFirst( pMsduList, &pMsdu )) != OK ) 1625 { 1626 /* No msdu is waiting to transmit */ 1627 WLAN_REPORT_ERROR (pTxData->hReport, TX_DATA_MODULE_LOG, 1628 (" %s : can't get Msdu from pMsduList[ %d ] \n", __FUNCTION__, selectedQueueIndex)); 1629 pTxData->txDataIsSchedulerInWork = FALSE; 1630 return NOK; 1631 } 1632 1633 /* mark the GWSI interface state as pending (no more frames can be sent) */ 1634 pTxData->txDataGwsiInterfaceStatus = GWSI_PENDING; 1635 1636 /* increment debug counter */ 1637 pTxData->txDataDbgCounters.dbgNumOfMsduPendingInScheduler[ selectedQueueIndex ]++; 1638 pTxData->txDataDbgCounters.dbgSendToGwsiQosPackets[selectedQueueIndex]++; 1639 break; 1640 1641 /* 1642 * BUSY is received when the packet has NOT been received by the GWSI layer (and needs to be 1643 * retransmitted). It indicates that the specific FW queue is full and no more packets from this 1644 * specific queue are to be sent until a TX complete indication for this queue is received (but 1645 * packets from other queues may be sent). 1646 */ 1647 case SEND_PACKET_BUSY: 1648 /* don't dequeue the packet! it was not sent! */ 1649 1650 /* in addition, release the packet ID buffer */ 1651 bufferPool_releaseBuffer( pTxData->hBufferPool, pPacketId ); 1652 1653 /* mark the specific queue as not available */ 1654 pTxData->txDataAvailableQueue[ selectedQueueIndex ] = FALSE; 1655 1656 /* update debug counters */ 1657 pTxData->txDataDbgCounters.dbgNumOfMsduBusyInScheduler[ selectedQueueIndex ]++; 1658 1659 break; 1660 1661 /* 1662 * ERROR is received when a frame is sent although a PENDING indication had been previously 1663 * received and no XFER complete had been receive since, or because a BUSY indication had been 1664 * received for a specific queue and no TX complete for this queue had been received since (and 1665 * a packet from this queue had been sent now). 1666 */ 1667 case SEND_PACKET_ERROR: 1668 /* don't dequeue the packet! it was not sent! */ 1669 1670 /* in addition, release the packet ID buffer */ 1671 bufferPool_releaseBuffer( pTxData->hBufferPool, pPacketId ); 1672 1673 /* start scheduler timer */ 1674 if ( FALSE == pTxData->bSchedulerTimerRunning ) 1675 { 1676 os_timerStart( pTxData->hOs, pTxData->pSchedulerTimer, SCHEDULER_TIMER, FALSE ); 1677 pTxData->bSchedulerTimerRunning = TRUE; 1678 } 1679 pTxData->txDataIsSchedulerInWork = FALSE; 1680 WLAN_REPORT_ERROR( pTxData->hReport, TX_DATA_MODULE_LOG, 1681 (" %s: received status SEND_PACKET_ERROR from CORE_AdaptTx_SendPacket\n", __FUNCTION__) ); 1682 1683 /* update debug counters */ 1684 pTxData->txDataDbgCounters.dbgNumOfMsduErrorInScheduler[ selectedQueueIndex ]++; 1685 1686 return NOK; 1687 1688 /* break; - unreachable*/ 1689 1690 case SEND_PACKET_RECOVERY: 1691 break; 1692 1693 default: 1694 WLAN_REPORT_ERROR( pTxData->hReport, TX_DATA_MODULE_LOG, 1695 (" %s: received status %d from CORE_AdaptTx_SendPacket\n", __FUNCTION__, txStatus) ); 1696 break; 1697 } 1698 1699 WLAN_REPORT_INFORMATION (pTxData->hReport, TX_DATA_MODULE_LOG, 1700 ("txData_startTxScheduler() : MSDU sent: TxQ = %d TxStatus = %d\n", selectedQueueIndex, txStatus)); 1701 } /* end of while (count) */ 1702 1703 pTxData->txDataIsSchedulerInWork = FALSE; 1704 1705 return OK; 1706 } 1707 /*************************************************************************** 1708 * txData_sendPacketTransfer * 1709 **************************************************************************** 1710 * DESCRIPTION: GWSI sendPacketTransfer CB. called after transferring a packet 1711 * to TNET. 1712 * The function free the transfered MSDU and set GWSI port status 1713 * to OPEN. This is the only function which synchronized GWSI port 1714 * status. 1715 * TNET queues buffer status are updated and the scheduler is executed 1716 * trying to send another MSDU. 1717 * 1718 * INPUTS: hTxData - the object 1719 * 1720 * OUTPUT: 1721 * 1722 * RETURNS: void 1723 * 1724 ***************************************************************************/ 1725 void txData_sendPacketTransfer(TI_HANDLE hTxData, 1726 UINT32 aPacketIdAttr) 1727 { 1728 txData_t *pTxData = (txData_t *)hTxData; 1729 txPacketIdAttr_t* pPacketId = (txPacketIdAttr_t*)aPacketIdAttr; 1730 1731 1732 WLAN_REPORT_INFORMATION(pTxData->hReport, TX_DATA_MODULE_LOG, 1733 ("%s: XFER complete CB called\n", __FUNCTION__)); 1734 pTxData->txDataDbgCounters.dbgNumOfMsduTxTransferCB[ pPacketId->txQid ]++; 1735 1736 WLAN_REPORT_DEBUG_TX(pTxData->hReport, 1737 ("%s: XFER complete CB called\n", __FUNCTION__)); 1738 1739 /* updating GWSI status to open */ 1740 pTxData->txDataGwsiInterfaceStatus = GWSI_OPEN; 1741 1742 /* free the MSDU */ 1743 if ( pPacketId->pMsdu != NULL ) 1744 { 1745 pPacketId->driverHandlingTime = (os_timeStampUs (pTxData->hOs) - pPacketId->pMsdu->insertionTime) / 1000; 1746 1747 if( (wlan_memMngrFreeMSDU(pTxData->hMemMngr, memMgr_MsduHandle(pPacketId->pMsdu))) != OK ) 1748 { 1749 WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG, 1750 ("%s: free msdu failed \n", __FUNCTION__)); 1751 } 1752 else 1753 { 1754 pTxData->txDataDbgCounters.dbgNumOfMsduFreeInTxTransfer[ pPacketId->txQid ]++; 1755 } 1756 } 1757 else 1758 { 1759 WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG, 1760 ("%s: pMsdu = NULL !!!!\n", __FUNCTION__)); 1761 pTxData->txDataDbgCounters.dbgNumOfNullMsdu++; 1762 } 1763 1764 1765 /* nullify the MSDU pointer, just in case */ 1766 pPacketId->pMsdu = NULL; 1767 1768 /* mark in packet ID that XFER done was called */ 1769 pPacketId->bXferDoneCalled = TRUE; 1770 1771 /* 1772 * and check if to release packet ID. In rare cases, TX complete can be called before XFER done. In these 1773 * cases, the packet ID should be released here. 1774 */ 1775 if ( TRUE == pPacketId->bTxCompleteCalled ) 1776 { 1777 bufferPool_releaseBuffer( pTxData->hBufferPool, (bufferPool_buffer_t)aPacketIdAttr ); 1778 } 1779 1780 /* 1781 * check port status - if it is disconnected, it means the STA is disconnected, and thus 1782 * the XFER complete is ignored, to avoid race conditions (when, for example, the MSDU was 1783 * already freed on txData_stop) 1784 */ 1785 if ( CLOSE == pTxData->txDataPortStatus ) 1786 { 1787 WLAN_REPORT_WARNING( pTxData->hReport, TX_DATA_MODULE_LOG, 1788 (" %s: XFER complete CB called when port is CLOSED!", __FUNCTION__)); 1789 return; 1790 } 1791 1792 /* try to schedule another MSDU */ 1793 txData_startTxScheduler(hTxData); 1794 } 1795 1796 1797 /*************************************************************************** 1798 * txData_txCompleteUpdate * 1799 **************************************************************************** 1800 * DESCRIPTION: check if there are more packets in the queue to transmit, 1801 * and that the queues in the HW are empty. if so then release 1802 * the HW. else call to the scheduler. 1803 * 1804 * INPUTS: hTxData - the object 1805 * txStatus - status of Tx (OK = ok, other = failed) 1806 * TxQid - The Tx queue index. 1807 * 1808 * OUTPUT: 1809 * 1810 * RETURNS: TI_STATUS - is success then OK, else NOK 1811 * 1812 ***************************************************************************/ 1813 TI_STATUS txData_txCompleteUpdate(TI_HANDLE hTxData, txCompleteAttr_t *pCmpltAttr) 1814 { 1815 txData_t *pTxData = (txData_t *)hTxData; 1816 UINT8 qIndex; 1817 txPacketIdAttr_t* pPacketId = (txPacketIdAttr_t*)pCmpltAttr->packetId; 1818 1819 /* 1820 * when host processes the packets , we not working with Queue free event 1821 * so queue status in TNET is updated in tx complete and the scheduler is triggered. 1822 */ 1823 qIndex = pPacketId->txQid; 1824 1825 WLAN_REPORT_INFORMATION(pTxData->hReport, TX_DATA_MODULE_LOG, 1826 ("txData_txCompleteUpdate , queueId: %d status: %d\n", qIndex, pCmpltAttr->status)); 1827 1828 /* 1829 * first update that TNET Queue is available to get another packet 1830 */ 1831 pTxData->txDataAvailableQueue[qIndex] = TRUE; 1832 1833 /* update TX counters for txDistributer */ 1834 txData_UpdateTxCounters( hTxData, pCmpltAttr ); 1835 1836 /* update dbg counters */ 1837 pTxData->txDataDbgCounters.dbgNumOfsendPacketComplete[qIndex]++; 1838 if (pCmpltAttr->status == SEND_COMPLETE_SUCCESS) 1839 { 1840 pTxData->txDataDbgCounters.dbgTxCmpltOk[qIndex]++; 1841 pTxData->txDataDbgCounters.dbgTxCmpltOkBytes[qIndex] += pPacketId->msduDataLen; 1842 #if defined(TI_DBG) 1843 pTxData->txJitter[qIndex].jitter.air += 1844 ABS (pTxData->txJitter[qIndex].last_delay.air - pCmpltAttr->actualDurationInAir); 1845 pTxData->txJitter[qIndex].jitter.fw += 1846 ABS (pTxData->txJitter[qIndex].last_delay.fw - pCmpltAttr->fwHandlingTime); 1847 pTxData->txJitter[qIndex].last_delay.fw = pCmpltAttr->fwHandlingTime; 1848 pTxData->txJitter[qIndex].last_delay.air = pCmpltAttr->actualDurationInAir; 1849 pTxData->txJitter[qIndex].delay.fw += pCmpltAttr->fwHandlingTime; 1850 pTxData->txJitter[qIndex].delay.air += pCmpltAttr->actualDurationInAir; 1851 if (pCmpltAttr->fwHandlingTime > pTxData->txJitter[qIndex].max_delay.fw) 1852 pTxData->txJitter[qIndex].max_delay.fw = pCmpltAttr->fwHandlingTime; 1853 if (pCmpltAttr->actualDurationInAir > pTxData->txJitter[qIndex].max_delay.air) 1854 pTxData->txJitter[qIndex].max_delay.air = pCmpltAttr->actualDurationInAir; 1855 #endif 1856 } 1857 else 1858 { 1859 pTxData->txDataDbgCounters.dbgTxCmpltError[qIndex]++; 1860 /* on error, update TX counters (xmit error count) */ 1861 } 1862 1863 1864 /* check asynchronous in packetId */ 1865 if ( (pTxData->txDataDbgCounters.dbgNumOfMsduTxTransferCB[qIndex] + pTxData->txDataDbgCounters.dbgNumOfMsduXferDoneInShceduler[qIndex])< 1866 pTxData->txDataDbgCounters.dbgNumOfsendPacketComplete[qIndex]) 1867 { 1868 WLAN_REPORT_INFORMATION(pTxData->hReport, TX_DATA_MODULE_LOG, 1869 ("txData_txCompleteUpdate , qIndex = %d Num of XFER done CB + XFER done status = %d dbgNumOfsendPacketComplete = %d!!!!\n", 1870 qIndex, pTxData->txDataDbgCounters.dbgNumOfMsduTxTransferCB[qIndex] + 1871 pTxData->txDataDbgCounters.dbgNumOfMsduXferDoneInShceduler[qIndex], 1872 pTxData->txDataDbgCounters.dbgNumOfsendPacketComplete[qIndex])); 1873 } 1874 1875 /* check if XFER done was called for this packet */ 1876 if ( TRUE == pPacketId->bXferDoneCalled ) 1877 { 1878 /* free the packet ID buffer */ 1879 bufferPool_releaseBuffer( pTxData->hBufferPool, (bufferPool_buffer_t)pPacketId ); 1880 } 1881 else 1882 { 1883 /* 1884 * in rare cases, TX complete can be called before XFER done. If this is the case, 1885 * simply mark that TX complete was called. The packet ID will be freed on XFER done 1886 */ 1887 pPacketId->bTxCompleteCalled = TRUE; 1888 } 1889 1890 /* run the scheduler */ 1891 txData_startTxScheduler(hTxData); 1892 1893 return OK; 1894 } 1895 1896 /*************************************************************************** 1897 * txData_sendPacketDebug * 1898 **************************************************************************** 1899 * DESCRIPTION: GWSI sendPacketDebug CB, called upon issuing interrupt to TNET. 1900 * The function calculates GWSI delay and jitter. 1901 * 1902 * INPUTS: hTxData - the object 1903 * uPacketId - packet handle 1904 * OUTPUT: 1905 * 1906 * RETURNS: void 1907 * 1908 ***************************************************************************/ 1909 #ifdef TI_DBG 1910 void txData_sendPacketDebug (TI_HANDLE hTxData, UINT32 uPacketId, UINT32 uDebugInfo) 1911 { 1912 1913 txData_t *pTxData = (txData_t *)hTxData; 1914 txPacketIdAttr_t* pPacketId = (txPacketIdAttr_t *)uPacketId; 1915 1916 if (pTxData != NULL && pPacketId != NULL) 1917 { 1918 UINT32 uXferDelay = os_timeStampUs (pTxData->hOs); 1919 1920 switch (uDebugInfo) 1921 { 1922 case 0: 1923 /* Calculate full XFER delay */ 1924 if (uXferDelay >= pPacketId->timeStamp[0]) 1925 { 1926 uXferDelay -= pPacketId->timeStamp[0]; 1927 1928 /* Update jitter statistics */ 1929 pTxData->txJitter[pPacketId->txQid].delay.xfer += uXferDelay; 1930 pTxData->txJitter[pPacketId->txQid].jitter.xfer += 1931 ABS (uXferDelay - pTxData->txJitter[pPacketId->txQid].last_delay.xfer); 1932 pTxData->txJitter[pPacketId->txQid].last_delay.xfer = uXferDelay; 1933 pTxData->txJitter[pPacketId->txQid].count.xfer ++; 1934 if (uXferDelay > pTxData->txJitter[pPacketId->txQid].max_delay.xfer) 1935 pTxData->txJitter[pPacketId->txQid].max_delay.xfer = uXferDelay; 1936 } 1937 break; 1938 1939 default: 1940 if (uDebugInfo < 5) 1941 pPacketId->timeStamp[uDebugInfo] = uXferDelay; 1942 break; 1943 } 1944 } 1945 } 1946 #endif 1947 1948 1949 /*************************************************************************** 1950 * txData_getHighestAdmittedAc * 1951 **************************************************************************** 1952 * DESCRIPTION: This function calculate the highest admitted AC starting from 1953 * a given ac index. if it fails it returns acIndex of Best effort. 1954 * 1955 * INPUTS: hTxData - the object 1956 * qosTag - Qos tag 1957 * 1958 * OUTPUT: 1959 * 1960 * RETURNS: OK 1961 * NOK 1962 ***************************************************************************/ 1963 1964 static int txData_getHighestAdmittedAc(txData_t *pTxData, int startingAcIndex) 1965 { 1966 int qIndex; 1967 1968 if ((startingAcIndex > MAX_NUM_OF_AC - 1) || (startingAcIndex < FIRST_AC_INDEX)) 1969 { 1970 WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG, 1971 (" txData_getHighestAdmittedAc() : failed, startingAcIndex = %d \n",startingAcIndex)); 1972 return QOS_AC_BE; 1973 } 1974 1975 qIndex = GET_QUEUE_INDEX(pTxData, startingAcIndex); 1976 1977 /* If desired queue is not admitted, find highest Tx queue that doesn't require admission. */ 1978 if(pTxData->dataMsduListArr[qIndex]->admissionState == AC_NOT_ADMITTED) 1979 { 1980 while(qIndex >= 0) 1981 { 1982 if(pTxData->dataMsduListArr[qIndex]->admissionRequired == ADMISSION_NOT_REQUIRED) 1983 break; 1984 qIndex--; 1985 } 1986 } 1987 1988 if(qIndex < 0) 1989 { 1990 WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG, 1991 (" txData_getHighestAdmittedAc() : failed, qIndex = %d \n",qIndex)); 1992 return startingAcIndex; 1993 } 1994 1995 return pTxData->dataMsduListArr[qIndex]->acId; 1996 } 1997 1998 1999 2000 /*************************************************************************** 2001 * txData_selectQueueAndUpdateUserPriority * 2002 **************************************************************************** 2003 * DESCRIPTION: This function calculate the queue index according to msdu qos tag 2004 * if the queue isn't admitted tt returns the highest admitted queue 2005 * bellow. 2006 * In addition, if the MSDU has been downgraded due to admission control, 2007 * we update the QosControl accordingly 2008 * 2009 * INPUTS: hTxData - the object 2010 * pMSDU - pointer to packet 2011 * 2012 * OUTPUT: selectedQueue - pointer to result variable which will hold the selected queue index 2013 * acIndex - selected admission control 2014 * 2015 * RETURNS: OK 2016 * NOK 2017 ***************************************************************************/ 2018 static int txData_selectQueueAndUpdateUserPriority (txData_t *pTxData, mem_MSDU_T *pMsdu, int *selectedQueue, acTrfcType_e *selectedAc) 2019 { 2020 int startingAcIndex; 2021 int acIndex; 2022 dot11_header_t *pdot11Header; 2023 2024 if (pMsdu->qosTag > MAX_NUM_OF_802_1d_TAGS - 1) 2025 { 2026 WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG, 2027 (" txData_selectQueueAndUpdateUserPriority() : txData_getQueueIndex failed, pMsdu->qosTag = %d \n",pMsdu->qosTag)); 2028 *selectedAc = QOS_AC_BE; 2029 *selectedQueue = GET_QUEUE_INDEX(pTxData, QOS_AC_BE); 2030 return NOK; 2031 } 2032 /* calc ac according tag to ac table */ 2033 acIndex = startingAcIndex = pTxData->txDataQosParams.tag_ToAcClsfrTable[pMsdu->qosTag]; 2034 2035 /* get highest admitted AC */ 2036 if(pTxData->admissionDownGradeEnable == TRUE) 2037 acIndex = txData_getHighestAdmittedAc(pTxData,startingAcIndex); 2038 2039 /* If the highest admitted AC is not the "starting" AC that we originally desired, we were downgraded due to admission control 2040 and we should update the QosControl field accordingly 2041 In addition, we do not want to modify the QosControl unless the header actually contains Qos data */ 2042 if ((acIndex != startingAcIndex) && (pTxData->txDataQosParams.headerConverMode == QOS_CONVERT)) 2043 { 2044 pdot11Header = (dot11_header_t*)(memMgr_BufData(pMsdu->firstBDPtr)+ memMgr_BufOffset(pMsdu->firstBDPtr)); 2045 2046 pdot11Header->qosControl = wmeAcToUpIndex[acIndex]; 2047 } 2048 2049 /* convert acIndex to qIndex */ 2050 *selectedQueue = pTxData->txDataAcTrfcCtrl[acIndex].QueueIndex; 2051 *selectedAc = (acTrfcType_e)acIndex; 2052 2053 return OK; 2054 } 2055 2056 2057 2058 /*************************************************************************** 2059 * txData_acVoPsPollMode * 2060 **************************************************************************** 2061 * DESCRIPTION: This function determines if we are current in power save mode 2062 * sending voice packet with SW ps-poll method. 2063 * 2064 * INPUTS: hTxData - the object 2065 * qosTag - Qos tag 2066 * 2067 * OUTPUT: 2068 * 2069 * RETURNS: TRUE 2070 * FALSE 2071 ***************************************************************************/ 2072 2073 static BOOL txData_acVoPsPollMode(txData_t *pTxData) 2074 { 2075 BOOL ps_status = FALSE; 2076 2077 ps_status = PowerMgr_getPsStatus(pTxData->hPowerMgr); 2078 2079 if (ps_status && 2080 pTxData->txDataAcTrfcCtrl[QOS_AC_VO].PsMode == PS_SCHEME_LEGACY_PSPOLL) 2081 { 2082 return TRUE; 2083 } 2084 2085 return FALSE; 2086 } 2087 2088 2089 2090 /*************************************************************************** 2091 * txData_disableTransmission * 2092 **************************************************************************** 2093 * DESCRIPTION: This function sets an internal flag in order to diable 2094 * transmission. 2095 * 2096 * INPUTS: hTxData - the object 2097 * reason - indicates if the reason for transmission disable 2098 * is measuring of non serving channel or Switch Channel command 2099 * 2100 * OUTPUT: 2101 * 2102 * RETURNS: OK on success, NOK otherwise 2103 ***************************************************************************/ 2104 TI_STATUS txData_disableTransmission(TI_HANDLE hTxData,txDisableReason_e reason) 2105 { 2106 txData_t *pTxData = (txData_t *)hTxData; 2107 pTxData->txDisable = reason; 2108 return OK; 2109 } 2110 2111 /*************************************************************************** 2112 * txData_enableTransmission * 2113 **************************************************************************** 2114 * DESCRIPTION: This function sets an internal flag in order to enable 2115 * back the transmission. 2116 * 2117 * INPUTS: hTxData - the object 2118 * 2119 * 2120 * OUTPUT: 2121 * 2122 * RETURNS: OK on success, NOK otherwise 2123 ***************************************************************************/ 2124 TI_STATUS txData_enableTransmission(TI_HANDLE hTxData) 2125 { 2126 txData_t *pTxData = (txData_t *)hTxData; 2127 pTxData->txDisable = NO_DISABLE; 2128 txData_startTxScheduler(pTxData); 2129 2130 return OK; 2131 } 2132 2133 2134 2135 /*************************************************************************** 2136 * txData_schedulerSelectQueueToTransmitFrom * 2137 **************************************************************************** 2138 * DESCRIPTION: This function selects the tx queue to transmit MSDU from. 2139 * Management MSDUs are selected in first priority. 2140 * For data MSDUs, the queue selection is done by the following order: 2141 * 1) The queue is not empty. 2142 * 2) It is permitted to transmit (admitted and not blocked by mediumTime). 2143 * 3) It has minimal number of Hw blocks waiting for Tx. 2144 * Note: this is to fill all queues for efficient EDCA process in FW. 2145 * 4) It has minimal history-counter (shows it wasn't selected lately). 2146 * 5) It is the highest priority queue. 2147 * 2148 * Note: Selection between queues is done by step 'n' only if all steps before it 2149 * gave identical results. Also, steps 1 & 2 are mandatory for selection. 2150 * 2151 * INPUTS: hTxData - the object 2152 * 2153 * OUTPUT: pMsduListPtr - a pointer to the selected queue list-pointer. 2154 * selectedQueueIndex - a pointer to the selected queue index. 2155 * 2156 * RETURNS: TX_QUEUE_SELECTED_OK - a queue was selected. 2157 * NO_TX_QUEUE_SELECTED - no msdu to transmit. 2158 ***************************************************************************/ 2159 2160 static TI_STATUS txData_schedulerSelectQueueToTransmitFrom( TI_HANDLE hTxData, MsduList_t** pMsduListPtr,UINT8 *selectedQueueIndex ) 2161 { 2162 txData_t *pTxData = (txData_t *)hTxData; 2163 UINT8 acIndex; 2164 int qIndex; 2165 UINT32 currentTimeStamp = os_timeStampMs(pTxData->hOs); 2166 UINT32 AllQueuesMinTime = 0; 2167 UINT32 currQueuesTime = 0; 2168 MsduList_t *pMsduList; 2169 UINT32 currentQueueWeight; 2170 UINT32 bestWeight = Q_LEAST_WEIGHT; /* Weight of preferred queue (lowest value is selected). */ 2171 int bestWeightQueueIndex = 0; /* Index of preferred queue. */ 2172 MsduList_t *bestWeightQueueList = NULL; /* Pointer to the preferred queue list. */ 2173 2174 /* If management MSDU is waiting, select it and return. */ 2175 if( pTxData->mngMsduList->CurrNumOfMsdu > 0 ) 2176 { 2177 *pMsduListPtr = pTxData->mngMsduList; 2178 2179 /* get highest admitted AC starting from VO */ 2180 acIndex = txData_getHighestAdmittedAc(pTxData,QOS_AC_VO); 2181 2182 /* convert acIndex to queue index */ 2183 *selectedQueueIndex = GET_QUEUE_INDEX(pTxData,acIndex); 2184 2185 2186 if (pTxData->txDataAvailableQueue[*selectedQueueIndex] == TRUE) 2187 { 2188 WLAN_REPORT_INFORMATION (pTxData->hReport, TX_DATA_MODULE_LOG, 2189 (" txData_schedulerSelectQueueToTransmitFrom() : Management MSDU selected to Tx\n")); 2190 return TX_QUEUE_SELECTED_OK; 2191 } 2192 else 2193 { 2194 WLAN_REPORT_INFORMATION (pTxData->hReport, TX_DATA_MODULE_LOG, 2195 (" txData_schedulerSelectQueueToTransmitFrom() : pTxData->txDataAvailableQueue[%d] = FALSE \n",*selectedQueueIndex)); 2196 } 2197 } 2198 2199 2200 /* 2201 * Loop over all core data Tx queues and look for the preferred one to transmit from: 2202 * ================================================================================= 2203 * Note: Starting from the highest priority ensures that if multiple queues have 2204 * identical status, the highest priority one among them will be selected. 2205 */ 2206 for (qIndex = MAX_NUM_OF_TX_QUEUES - 1; qIndex >= 0; qIndex--) 2207 { 2208 pMsduList = pTxData->dataMsduListArr[qIndex]; 2209 2210 if (pMsduList->selectionHistoryCounter) 2211 pMsduList->selectionHistoryCounter--; 2212 2213 /* If queue is empty or is not admitted to transmit, continue to next queue. */ 2214 if ((pMsduList->CurrNumOfMsdu == 0) || (pMsduList->admissionState != AC_ADMITTED)) 2215 continue; 2216 2217 /* 2218 * see only if Queue is available. 2219 * continue to the next Q if not available 2220 */ 2221 if (pTxData->txDataAvailableQueue[qIndex] == FALSE) 2222 continue; 2223 2224 /* If we are configured to enforce excess Tx time limits, handle the algorithm. */ 2225 if (pMsduList->useAdmissionAlgo) 2226 { 2227 /* Handle case of timer wraparound. */ 2228 if (currentTimeStamp < pMsduList->lastTimeStamp) 2229 pMsduList->lastTimeStamp = 0; 2230 2231 /* If we it's not time to enable Tx yet for this queue, update time to try again if needed. */ 2232 if (currentTimeStamp < pMsduList->lastTimeStamp + pMsduList->enableTransmissionTime) 2233 { 2234 /* currQueuesTime represents the amount of time the tx scheduler has to wait before 2235 it will be able to transmit from this queue. */ 2236 currQueuesTime = (pMsduList->lastTimeStamp + pMsduList->enableTransmissionTime - currentTimeStamp); 2237 2238 /* Update the minimum time left till we can Tx from any of the queues. */ 2239 if (AllQueuesMinTime == 0) 2240 AllQueuesMinTime = currQueuesTime; 2241 else 2242 AllQueuesMinTime = MIN(AllQueuesMinTime, currQueuesTime); 2243 2244 /* We can't Tx from this queue yet so continue to next queue. */ 2245 continue; 2246 } 2247 } 2248 2249 /**** If we got here, this queue has something to Tx and it is permitted to Tx now. ****/ 2250 2251 /* Now calculate this queue's weight for selection: 2252 * Higher 16 bits: Number of used HW blocks by this AC. 2253 * Lower 16 bits: Count down from last time it was selected. */ 2254 currentQueueWeight = (UINT32)TnetwDrv_txHwQueue_GetUsedHwBlks( pTxData->hTnetwDrv, qIndex ) << 16; 2255 currentQueueWeight |= (UINT32)pMsduList->selectionHistoryCounter; 2256 2257 /* If current queue's weight isn't lower (lower is better!) than previous queues, 2258 continue to next queue. */ 2259 if (currentQueueWeight >= bestWeight) 2260 continue; 2261 2262 /* Save weight, index and list-pointer of best candidate queue so far . */ 2263 bestWeight = currentQueueWeight; 2264 bestWeightQueueIndex = qIndex; 2265 bestWeightQueueList = pMsduList; 2266 } 2267 2268 2269 /* If we have a delayed queue, we need to re-trigger the scheduler later by timer. */ 2270 if (AllQueuesMinTime != 0) 2271 { 2272 /* msdu is waiting to transmit */ 2273 WLAN_REPORT_INFORMATION (pTxData->hReport, TX_DATA_MODULE_LOG, 2274 (" txData_schedulerSelectQueueToTransmitFrom() : Start mediumTime timer for - %d ms\n", AllQueuesMinTime)); 2275 2276 if ( pTxData->bSchedulerTimerRunning == TRUE ) 2277 { 2278 os_timerStop(pTxData->hOs, pTxData->pSchedulerTimer); 2279 } 2280 os_timerStart(pTxData->hOs,pTxData->pSchedulerTimer, AllQueuesMinTime, FALSE); 2281 pTxData->bSchedulerTimerRunning = TRUE; 2282 } 2283 2284 2285 /* If we have a queue we can transmit from: */ 2286 if (bestWeight != Q_LEAST_WEIGHT) 2287 { 2288 /* Set selected queue history counter to its initial value, indicating it was selected 2289 lately and its priority is temporarily reduced. */ 2290 bestWeightQueueList->selectionHistoryCounter = Q_SELECTION_HISTORY_LEVEL; 2291 2292 /* Provide the selected queue index and list pointer. */ 2293 *pMsduListPtr = bestWeightQueueList; 2294 *selectedQueueIndex = bestWeightQueueIndex; 2295 2296 WLAN_REPORT_INFORMATION (pTxData->hReport, TX_DATA_MODULE_LOG, 2297 (" txData_schedulerSelectQueueToTransmitFrom() : Selected-TxQ = %d, Weight = 0x%x\n", 2298 bestWeightQueueIndex, bestWeight)); 2299 2300 return TX_QUEUE_SELECTED_OK; 2301 } 2302 2303 2304 /* If we got here, no queue is currently suitable for transmition. */ 2305 WLAN_REPORT_DEBUG_TX(pTxData->hReport, 2306 (" txData_schedulerSelectQueueToTransmitFrom() : No queue selected for Tx\n")); 2307 2308 return NO_TX_QUEUE_SELECTED; 2309 } 2310 2311 2312 2313 /*************************************************************************** 2314 * txData_getParam * 2315 **************************************************************************** 2316 * DESCRIPTION: get a specific parameter 2317 * 2318 * INPUTS: hTxData - the object 2319 * 2320 * OUTPUT: pParamInfo - structure which include the value of 2321 * the requested parameter 2322 * 2323 * RETURNS: OK 2324 * NOK 2325 ***************************************************************************/ 2326 TI_STATUS txData_getParam(TI_HANDLE hTxData, paramInfo_t *pParamInfo) 2327 { 2328 txData_t *pTxData = (txData_t *)hTxData; 2329 UINT32 tID; 2330 2331 /* check handle validity */ 2332 if( pTxData == NULL ) 2333 { 2334 WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG, 2335 (" txData_getParam() : Illegal parametrs value \n")); 2336 return NOK; 2337 } 2338 2339 switch (pParamInfo->paramType) 2340 { 2341 case TX_DATA_PORT_STATUS_PARAM: 2342 pParamInfo->content.txDataPortStatus = pTxData->txDataPortStatus; 2343 break; 2344 2345 case TX_DATA_CURRENT_PRIVACY_INVOKE_MODE_PARAM: 2346 pParamInfo->content.txDataCurrentPrivacyInvokedMode = pTxData->txDataCurrentPrivacyInvokedMode; 2347 break; 2348 2349 case TX_DATA_EAPOL_ENCRYPTION_STATUS_PARAM: 2350 pParamInfo->content.txDataEapolEncryptionStatus = pTxData->txDataEapolEncryptionStatus; 2351 break; 2352 2353 case TX_DATA_CONVERT_HEADER_MODE: 2354 pParamInfo->content.txDataQosParams.qosParams.headerConverMode = pTxData->txDataQosParams.headerConverMode; 2355 break; 2356 2357 case TX_DATA_COUNTERS_PARAM: 2358 os_memoryCopy( pTxData->hOs, &(pTxData->tempTxDataCounters[ 0 ]), &(pTxData->txDataCounters[ 0 ]), 2359 sizeof(txDataCounters_t) * MAX_NUM_OF_TX_QUEUES ); 2360 pParamInfo->content.pTxDataCounters = &(pTxData->tempTxDataCounters[ 0 ]); 2361 break; 2362 2363 case TX_DATA_REPORT_TS_STATISTICS: 2364 tID = GET_QUEUE_INDEX(pTxData, pParamInfo->content.tsMetricsCounters.acID); 2365 os_memoryCopy(pTxData->hOs, 2366 pParamInfo->content.tsMetricsCounters.pTxDataCounters, 2367 &(pTxData->txDataReportedCounters[tID]), 2368 sizeof(txDataCounters_t)); 2369 os_memoryZero(pTxData->hOs, 2370 &(pTxData->txDataReportedCounters[tID]), 2371 sizeof(txDataCounters_t)); 2372 break; 2373 2374 case TX_DATA_GET_VAD: 2375 pParamInfo->content.txDataVadTimerParams.vadTimerEnabled = pTxData->bVadTimerEnabled; 2376 pParamInfo->content.txDataVadTimerParams.vadTimerDuration = pTxData->vadTimerDuration; 2377 2378 WLAN_REPORT_INFORMATION(pTxData->hReport, TX_DATA_MODULE_LOG, 2379 ("txData_setParams: GET_VAD (enable=%d; duration=%d ms)\n", 2380 pTxData->bVadTimerEnabled, pTxData->vadTimerDuration)); 2381 2382 break; 2383 2384 default: 2385 return (PARAM_NOT_SUPPORTED); 2386 /* WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG, 2387 (" txData_getParam() : PARAMETER NOT SUPPORTED \n")); 2388 return NOK; 2389 break; - unreachable*/ 2390 } 2391 2392 return (OK); 2393 } 2394 2395 2396 2397 /*************************************************************************** 2398 * txData_setParam * 2399 **************************************************************************** 2400 * DESCRIPTION: set a specific parameter 2401 * 2402 * INPUTS: hTxData - the object 2403 * pParamInfo - structure which include the value to set for 2404 * the requested parameter 2405 * 2406 * OUTPUT: 2407 * 2408 * RETURNS: OK 2409 * NOK 2410 ***************************************************************************/ 2411 TI_STATUS txData_setParam(TI_HANDLE hTxData, paramInfo_t *pParamInfo) 2412 { 2413 txData_t *pTxData = (txData_t *)hTxData; 2414 UINT8 queueIndex; 2415 UINT8 acID = pParamInfo->content.txDataQosParams.acID; /* Note: acID is relevant only in 2416 some of the param-types!! */ 2417 2418 /* check handle validity */ 2419 if( pTxData == NULL ) 2420 { 2421 WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG, 2422 (" txData_setParam() : Illegal parametrs value \n")); 2423 return NOK; 2424 } 2425 2426 2427 switch (pParamInfo->paramType) 2428 { 2429 case TX_DATA_PORT_STATUS_PARAM: 2430 2431 { 2432 /* Set the new TX port status CLOSE/OPEN_NOTIFY/OPEN_EAPOL/OPEN */ 2433 WLAN_REPORT_DEBUG_TX (pTxData->hReport, 2434 (("txData_setParam: Set txDataPortStatus from 0x%x to 0x%x\n"), 2435 pTxData->txDataPortStatus , pParamInfo->content.txDataPortStatus)); 2436 2437 pTxData->txDataPortStatus = pParamInfo->content.txDataPortStatus; 2438 break; 2439 } 2440 2441 case TX_DATA_CURRENT_PRIVACY_INVOKE_MODE_PARAM: 2442 pTxData->txDataCurrentPrivacyInvokedMode = pParamInfo->content.txDataCurrentPrivacyInvokedMode; 2443 break; 2444 2445 case TX_DATA_EAPOL_ENCRYPTION_STATUS_PARAM: 2446 pTxData->txDataEapolEncryptionStatus = pParamInfo->content.txDataEapolEncryptionStatus; 2447 break; 2448 2449 case TX_DATA_HAL_INTERFACE_STATUS_PARAM: 2450 pTxData->txDataHalInterfaceStatus = pParamInfo->content.txDataHalInterfaceStatus; 2451 break; 2452 2453 case TX_DATA_PS_MODE_PARAM: 2454 pTxData->txDataAcTrfcCtrl[acID].PsMode = 2455 pParamInfo->content.txDataQosParams.acTrfcCtrl.PsMode; 2456 break; 2457 2458 case TX_DATA_CONFIG_TX_QUEUE_SIZE: 2459 queueIndex = pParamInfo->content.txDataQosParams.acTrfcCtrl.QueueIndex; 2460 pTxData->txDataAcTrfcCtrl[acID].TxQueueSize = 2461 pParamInfo->content.txDataQosParams.acTrfcCtrl.TxQueueSize; 2462 if(queueIndex >= MAX_NUM_OF_TX_QUEUES) 2463 { 2464 WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG, 2465 ("Error configure Data MsduList , wrong queue index = %d\n", queueIndex)); 2466 return NOK; 2467 } 2468 pTxData->dataMsduListArr[queueIndex]->acId = acID; 2469 pTxData->txDataAcTrfcCtrl[acID].QueueIndex = queueIndex; 2470 2471 /* also set the opposute direction conversion table (queue ID -> ac ID) */ 2472 txData_SetQidToAcTable( hTxData, queueIndex, queueIndex, acID ); 2473 2474 if( (msduList_SetMsduListNumOfElements( pTxData->dataMsduListArr[queueIndex], 2475 pTxData->txDataAcTrfcCtrl[acID].TxQueueSize)) != OK ) 2476 { 2477 WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG, 2478 ("Error configure MgmtMsduList\n")); 2479 return NOK; 2480 } 2481 break; 2482 2483 case TX_DATA_CONFIG_TX_QUEUE_OVFLOW_POLICY: 2484 queueIndex = pParamInfo->content.txDataQosParams.acTrfcCtrl.QueueIndex; 2485 pTxData->txDataAcTrfcCtrl[acID].QueueOvFlowPolicy = pParamInfo->content.txDataQosParams.acTrfcCtrl.QueueOvFlowPolicy; 2486 if(queueIndex >= MAX_NUM_OF_TX_QUEUES) 2487 { 2488 WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG, 2489 ("Error configure MsduList over flow policy , wrong queue index = %d\n",queueIndex)); 2490 return NOK; 2491 } 2492 pTxData->txDataAcTrfcCtrl[acID].QueueIndex = queueIndex; 2493 msduList_SetMsduListOverFlowPolicy(pTxData->dataMsduListArr[pTxData->txDataAcTrfcCtrl[acID].QueueIndex], 2494 pTxData->txDataAcTrfcCtrl[acID].QueueOvFlowPolicy); 2495 break; 2496 2497 case TX_DATA_CONFIG_AC_MSDU_LIFE_TIME: 2498 pTxData->txDataAcTrfcCtrl[acID].MsduLifeTime = 1000 * pParamInfo->content.txDataQosParams.acTrfcCtrl.MsduLifeTime; 2499 break; 2500 2501 case TX_DATA_CONFIG_AC_ACK_POLICY: 2502 pTxData->txDataAcTrfcCtrl[acID].ackPolicy = pParamInfo->content.txDataQosParams.acTrfcCtrl.ackPolicy; 2503 break; 2504 2505 case TX_DATA_AC_ADMISSION_STATE: 2506 pTxData->dataMsduListArr[GET_QUEUE_INDEX(pTxData, acID)]->admissionRequired = 2507 pParamInfo->content.txDataQosParams.qosParams.admissionRequired; 2508 2509 pTxData->dataMsduListArr[GET_QUEUE_INDEX(pTxData, acID)]->admissionState = 2510 pParamInfo->content.txDataQosParams.qosParams.admissionState; 2511 break; 2512 2513 case TX_DATA_CONVERT_HEADER_MODE: 2514 pTxData->txDataQosParams.headerConverMode = pParamInfo->content.txDataQosParams.qosParams.headerConverMode; 2515 break; 2516 2517 case TX_DATA_TAG_TO_AC_CLASSIFIER_TABLE: 2518 os_memoryCopy(pTxData->hOs,(pTxData->txDataQosParams.tag_ToAcClsfrTable), 2519 pParamInfo->content.txDataQosParams.qosParams.tag_ToAcClsfrTable,sizeof(acTrfcType_e) * MAX_NUM_OF_802_1d_TAGS); 2520 break; 2521 2522 case TX_DATA_SET_AC_QUEUE_INDEX: 2523 queueIndex = pParamInfo->content.txDataQosParams.acTrfcCtrl.QueueIndex; 2524 2525 pTxData->txDataAcTrfcCtrl[pParamInfo->content.txDataQosParams.acID].QueueIndex = queueIndex; 2526 /* also set the opposute direction conversion table (queue ID -> ac ID) */ 2527 txData_SetQidToAcTable( hTxData, queueIndex, queueIndex, acID ); 2528 break; 2529 2530 case TX_DATA_SET_MEDIUM_USAGE_THRESHOLD: 2531 txData_setMediumUsageThresholds (hTxData, 2532 (UINT8)pParamInfo->content.txDataMediumUsageThreshold.uAC, 2533 pParamInfo->content.txDataMediumUsageThreshold.uHighThreshold, 2534 pParamInfo->content.txDataMediumUsageThreshold.uLowThreshold); 2535 break; 2536 2537 case TX_DATA_GET_MEDIUM_USAGE_THRESHOLD: 2538 /* SET operation is performed, but actually this is only for AC parameter transfer from Utility Adapter to driver, since copy 2539 of user supplied block of data (and vice versa) is only performed in SetParam calls, the driver can also modify the supplied 2540 structure and thus return it to user mode */ 2541 queueIndex = pTxData->txDataAcTrfcCtrl[pParamInfo->content.txDataMediumUsageThreshold.uAC].QueueIndex; 2542 2543 /* get threshold */ 2544 pParamInfo->content.txDataMediumUsageThreshold.uHighThreshold = pTxData->dataMsduListArr[queueIndex]->highMediumUsageThreshold; 2545 pParamInfo->content.txDataMediumUsageThreshold.uLowThreshold = pTxData->dataMsduListArr[queueIndex]->lowMediumUsageThreshold; 2546 2547 break; 2548 2549 case TX_DATA_POLL_AP_PACKETS_FROM_AC: 2550 2551 queueIndex = pTxData->txDataAcTrfcCtrl[pParamInfo->content.txDataPollApPacketsFromACid].QueueIndex; 2552 2553 if (queueIndex <= QOS_AC_MAX) 2554 return (txData_sendVadFrame (pTxData, queueIndex)); 2555 else 2556 return PARAM_VALUE_NOT_VALID; 2557 2558 /* break; - unreachable */ 2559 2560 case TX_DATA_ENCRYPTION_FIELD_SIZE: 2561 /* set the space to reserve for encrypted frames */ 2562 pTxData->encryptionFieldSize = pParamInfo->content.txDataEncryptionFieldSize; 2563 break; 2564 2565 case TX_DATA_RESET_COUNTERS_PARAM: 2566 txData_resetCounters( hTxData ); 2567 break; 2568 2569 case TX_DATA_SET_VAD: 2570 { 2571 BOOL bVadTimerEnabled; 2572 UINT16 vadTimerDuration; 2573 2574 bVadTimerEnabled = pParamInfo->content.txDataVadTimerParams.vadTimerEnabled; 2575 vadTimerDuration = pParamInfo->content.txDataVadTimerParams.vadTimerDuration; 2576 WLAN_REPORT_INFORMATION(pTxData->hReport, TX_DATA_MODULE_LOG, 2577 ("txData_setParams: SET_VAD (enable=%d; duration=%d ms)\n", 2578 bVadTimerEnabled, vadTimerDuration)); 2579 2580 txData_setVadTimer(hTxData, bVadTimerEnabled, vadTimerDuration); 2581 } 2582 2583 break; 2584 2585 default: 2586 return (PARAM_NOT_SUPPORTED); 2587 /* WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG, 2588 (" txData_setParam() : PARAMETER NOT SUPPORTED \n")); 2589 return NOK; 2590 break; - unreachable */ 2591 } 2592 2593 return (OK); 2594 } 2595 2596 2597 /*************************************************************************** 2598 * txData_convertEthToWlanHeader * 2599 **************************************************************************** 2600 * DESCRIPTION: this function convert the msdu header from ethernet format 2601 * to the 802.11 header format 2602 * 2603 * INPUTS: hTxData - the object 2604 * pMsdu - msdu in ethernet format 2605 * 2606 * OUTPUT: pMsdu - msdu in 802.11 format 2607 * 2608 * RETURNS: 2609 ***************************************************************************/ 2610 static void txData_convertEthToWlanHeader (txData_t *pTxData, mem_MSDU_T *pMsdu) 2611 { 2612 EthernetHeader_t *pEthHeader; 2613 dot11_header_t dot11Header; 2614 Wlan_LlcHeader_T WlanSnapHeader; 2615 UINT16 swapedTypeLength; 2616 bssType_e currBssType; 2617 macAddress_t currBssId; 2618 UINT8 SNAP_OUI_802_1H[] = SNAP_OUI_802_1H_BYTES; 2619 UINT8 SNAP_OUI_RFC1042[] = SNAP_OUI_RFC1042_BYTES; 2620 acTrfcType_e acIndex; 2621 char* pData; 2622 2623 /* initialize the frame header length */ 2624 pMsdu->headerLen = txData_GetWlanHeaderLength( pTxData, 2625 memMgr_BufData(pMsdu->firstBDPtr) + 2626 memMgr_BufOffset(pMsdu->firstBDPtr), 2627 pMsdu->txFlags ); 2628 2629 /* 2630 * Set the Eth pointer to the beginning of the first Bd 2631 */ 2632 pEthHeader = (EthernetHeader_t*)(memMgr_BufData(pMsdu->firstBDPtr) + memMgr_BufOffset(pMsdu->firstBDPtr)); 2633 2634 /* 2635 * Initialize working copy of the dot11header to zero 2636 */ 2637 os_memoryZero(pTxData->hOs,&dot11Header,sizeof(dot11_header_t)); 2638 2639 /* 2640 * Convert the header 802.3 ---> 802.11 onto the dot11Header working copy 2641 */ 2642 /* set Qos control */ 2643 if( pTxData->txDataQosParams.headerConverMode == QOS_CONVERT ) 2644 { 2645 /* set qos Tag */ 2646 dot11Header.qosControl = ((UINT16)pMsdu->qosTag & QOS_CONTROL_TAG_MASK); 2647 2648 /* 2649 * set ac ack policy according to the 2650 * Ack policy defined for the particular AC 2651 */ 2652 acIndex = (acTrfcType_e)GET_WME_AC_TYPE_FROM_MSDU(pMsdu); 2653 if(pTxData->txDataAcTrfcCtrl[acIndex].ackPolicy == ACK_POLICY_LEGACY) 2654 { 2655 dot11Header.qosControl &= ~DOT11_QOS_CONTROL_DONT_ACK; 2656 } 2657 else 2658 { 2659 dot11Header.qosControl |= DOT11_QOS_CONTROL_DONT_ACK; 2660 } 2661 } 2662 2663 /* receive BssId and Bss Type from control module */ 2664 ctrlData_getCurrBssTypeAndCurrBssId(pTxData->hCtrlData, &currBssId, &currBssType); 2665 2666 if (currBssType == BSS_INDEPENDENT) 2667 { 2668 MAC_COPY(pTxData->hOs,(&dot11Header.address1),(&pEthHeader->DstAddr)); 2669 MAC_COPY(pTxData->hOs,(&dot11Header.address2),(&pEthHeader->SrcAddr)); 2670 MAC_COPY(pTxData->hOs,(&dot11Header.address3),(&currBssId)); 2671 2672 if( pTxData->txDataQosParams.headerConverMode == QOS_CONVERT ) 2673 dot11Header.fc = DOT11_FC_DATA_QOS; 2674 else 2675 dot11Header.fc = DOT11_FC_DATA; 2676 } 2677 else /* infrastructure BSS */ 2678 { 2679 MAC_COPY(pTxData->hOs,(&dot11Header.address1),(&currBssId)); 2680 MAC_COPY(pTxData->hOs,(&dot11Header.address2),(&pEthHeader->SrcAddr)); 2681 MAC_COPY(pTxData->hOs,(&dot11Header.address3),(&pEthHeader->DstAddr)); 2682 2683 if( pTxData->txDataQosParams.headerConverMode == QOS_CONVERT ) 2684 dot11Header.fc = DOT11_FC_DATA_QOS | DOT11_FC_TO_DS; 2685 else 2686 dot11Header.fc = DOT11_FC_DATA | DOT11_FC_TO_DS; 2687 } 2688 2689 swapedTypeLength = wlan_htons(pEthHeader->TypeLength); 2690 2691 /* Detect the packet type and decide if to create a */ 2692 /* new SNAP or leave the original LLC. */ 2693 /*------------------------------------------------------*/ 2694 if( swapedTypeLength > ETHERNET_MAX_PAYLOAD_SIZE ) 2695 { 2696 /* Create the SNAP Header: */ 2697 /*-----------------------------*/ 2698 /* 2699 * Make a working copy of the SNAP header 2700 * initialised to zero 2701 */ 2702 os_memoryZero(pTxData->hOs,&WlanSnapHeader,sizeof(Wlan_LlcHeader_T)); 2703 WlanSnapHeader.DSAP = SNAP_CHANNEL_ID; 2704 WlanSnapHeader.SSAP = SNAP_CHANNEL_ID; 2705 WlanSnapHeader.Control = LLC_CONTROL_UNNUMBERED_INFORMATION; 2706 2707 /* Check to see if the Ethertype matches anything in the translation */ 2708 /* table (Appletalk AARP or DixII/IPX). If so, add the 802.1h */ 2709 /* SNAP. */ 2710 2711 if(( ETHERTYPE_APPLE_AARP == swapedTypeLength ) || 2712 ( ETHERTYPE_DIX_II_IPX == swapedTypeLength )) 2713 { 2714 /* Fill out the SNAP Header with 802.1H extention */ 2715 os_memoryCopy(pTxData->hOs, &WlanSnapHeader.OUI, SNAP_OUI_802_1H, 2716 sizeof( WlanSnapHeader.OUI ) ); 2717 } 2718 else 2719 { 2720 /* otherwise, add the RFC1042 SNAP */ 2721 os_memoryCopy(pTxData->hOs, &WlanSnapHeader.OUI, SNAP_OUI_RFC1042, 2722 sizeof( WlanSnapHeader.OUI) ); 2723 } 2724 /* set type length */ 2725 WlanSnapHeader.Type = pEthHeader->TypeLength; 2726 } 2727 2728 /* 2729 * Now - copy wlan header and snap overriding Ethernet header. 2730 */ 2731 2732 /* 2733 first the wlan header 2734 the header might not include the qosControl which will be erase 2735 later by the snap header 2736 */ 2737 /* pData starts after the reserved place for bus txn and the TxDescriptor */ 2738 2739 /* update data offset - bus txn extra space + TxDescriptor */ 2740 memMgr_BufOffset(pMsdu->firstBDPtr) = TX_TOTAL_OFFSET_BEFORE_DATA; 2741 2742 pData = memMgr_BufData(pMsdu->firstBDPtr) + memMgr_BufOffset(pMsdu->firstBDPtr); 2743 os_memoryCopy(pTxData->hOs,pData,&dot11Header,pMsdu->headerLen); 2744 2745 /* update data length */ 2746 pMsdu->dataLen = pMsdu->dataLen - ETHERNET_HDR_LEN + pMsdu->headerLen; 2747 2748 /* now the snap */ 2749 if( swapedTypeLength > ETHERNET_MAX_PAYLOAD_SIZE ) 2750 { 2751 pData += (pMsdu->headerLen - sizeof(Wlan_LlcHeader_T)); 2752 os_memoryCopy(pTxData->hOs,pData,&WlanSnapHeader,sizeof(Wlan_LlcHeader_T)); 2753 } 2754 2755 return; 2756 } 2757 2758 /*************************************************************************** 2759 * txData_resetCounters * 2760 **************************************************************************** 2761 * DESCRIPTION: Reset the tx data module counters 2762 * 2763 * INPUTS: hTxData - the object 2764 * 2765 * OUTPUT: 2766 * 2767 * RETURNS: 2768 ***************************************************************************/ 2769 void txData_resetCounters(TI_HANDLE hTxData) 2770 { 2771 txData_t *pTxData = (txData_t *)hTxData; 2772 2773 os_memoryZero(pTxData->hOs, &pTxData->txDataCounters, sizeof(txDataCounters_t) * MAX_NUM_OF_TX_QUEUES); 2774 pTxData->currentConsecutiveRetryFail = 0; 2775 } 2776 2777 /*************************************************************************** 2778 * txData_resetDbgCounters * 2779 **************************************************************************** 2780 * DESCRIPTION: Reset the tx data module debug counters 2781 * 2782 * INPUTS: hTxData - the object 2783 * 2784 * OUTPUT: 2785 * 2786 * RETURNS: 2787 ***************************************************************************/ 2788 void txData_resetDbgCounters(TI_HANDLE hTxData) 2789 { 2790 txData_t *pTxData = (txData_t *)hTxData; 2791 2792 os_memoryZero(pTxData->hOs, &pTxData->txDataDbgCounters, sizeof(txDataDbgCounters_t)); 2793 } 2794 2795 /*************************************************************************** 2796 * txData_DistributorTxEvent * 2797 **************************************************************************** 2798 * DESCRIPTION: 2799 * 2800 * 2801 * INPUTS: 2802 * 2803 * 2804 * 2805 * OUTPUT: 2806 * 2807 * RETURNS: 2808 * 2809 ***************************************************************************/ 2810 static VOID txData_DistributorTxEvent(txData_t *pTxData,UINT16 Mask,int DataLen) 2811 { 2812 if(pTxData->TxEventDistributor) 2813 DistributorMgr_EventCall(pTxData->TxEventDistributor,Mask,DataLen); 2814 2815 } 2816 2817 /*************************************************************************** 2818 * txData_RegNotif * 2819 ****************************************************************************/ 2820 TI_HANDLE txData_RegNotif(TI_HANDLE hTxData,UINT16 EventMask,GeneralEventCall_t CallBack,TI_HANDLE context,UINT32 Cookie) 2821 { 2822 txData_t *pTxData = (txData_t *)hTxData; 2823 if (!hTxData) 2824 return NULL; 2825 return DistributorMgr_Reg(pTxData->TxEventDistributor,EventMask,(TI_HANDLE)CallBack,context,Cookie); 2826 } 2827 2828 2829 /*************************************************************************** 2830 * txData_AddToNotifMask * 2831 ****************************************************************************/ 2832 TI_STATUS txData_AddToNotifMask(TI_HANDLE hTxData,TI_HANDLE Notifh,UINT16 EventMask) 2833 { 2834 txData_t *pTxData = (txData_t *)hTxData; 2835 if (!hTxData) 2836 return NOK; 2837 return DistributorMgr_AddToMask(pTxData->TxEventDistributor,Notifh,EventMask); 2838 } 2839 2840 2841 /*************************************************************************** 2842 * TxData_UnRegNotif * 2843 ****************************************************************************/ 2844 TI_STATUS txData_UnRegNotif(TI_HANDLE hTxData,TI_HANDLE RegEventHandle) 2845 { 2846 TI_STATUS status; 2847 txData_t *pTxData = (txData_t *)hTxData; 2848 2849 if (!hTxData) 2850 return NOK; 2851 2852 status = DistributorMgr_UnReg(pTxData->TxEventDistributor,RegEventHandle); 2853 return status; 2854 } 2855 2856 /**************************************************************************** 2857 * txData_SetTxDelayCounters() 2858 **************************************************************************** 2859 * DESCRIPTION: Update transmission path delay counters. 2860 * 2861 * INPUTS: hTxData - the object 2862 * txQid - the queue to count delay for 2863 * pTxCompleteAttr - struct containing the necessary FW delay data 2864 * driverDelay - the time consumed in driver for packet transmission 2865 * 2866 * OUTPUT: 2867 * 2868 * RETURNS: 2869 ****************************************************************************/ 2870 static void txData_SetTxDelayCounters( TI_HANDLE hTxData, UINT32 txQid, txCompleteAttr_t *pTxCompleteAttr, UINT32 driverDelay ) 2871 { 2872 txData_t *pTxData = (txData_t *)hTxData; 2873 int rangeIndex; 2874 UINT32 totalTxDelayMs; 2875 2876 /* Add 1 to the total time so that Total time will always be greater than fwHandlingTime */ 2877 totalTxDelayMs = driverDelay + (pTxCompleteAttr->fwHandlingTime / 1000) + 1; 2878 2879 /* Increment the delay range counter that the current packet Tx delay falls in. */ 2880 for (rangeIndex = TX_DELAY_RANGE_MIN; rangeIndex <= TX_DELAY_RANGE_MAX; rangeIndex++) 2881 { 2882 if ( (totalTxDelayMs >= txDelayRangeStart[rangeIndex]) && 2883 (totalTxDelayMs <= txDelayRangeEnd [rangeIndex]) ) 2884 { 2885 pTxData->txDataCounters[ txQid ].txDelayHistogram[ rangeIndex ]++; 2886 pTxData->txDataReportedCounters[ txQid ].txDelayHistogram[ rangeIndex ]++; 2887 break; 2888 } 2889 } 2890 2891 /* Update total delay and MAC delay sums and packets number for average delay calculation. */ 2892 if (pTxData->txDataCounters[ txQid ].SumTotalDelayMs < 0x7FFFFFFF) /* verify we are not close to the edge. */ 2893 { 2894 pTxData->txDataCounters[ txQid ].NumPackets++; 2895 pTxData->txDataCounters[ txQid ].SumTotalDelayMs += totalTxDelayMs; 2896 pTxData->txDataCounters[ txQid ].SumFWDelayUs += pTxCompleteAttr->fwHandlingTime; 2897 pTxData->txDataCounters[ txQid ].SumMacDelayUs += pTxCompleteAttr->mediumDelay; 2898 } 2899 else /* If we get close to overflow, restart average accumulation. */ 2900 { 2901 pTxData->txDataCounters[ txQid ].NumPackets = 1; 2902 pTxData->txDataCounters[ txQid ].SumTotalDelayMs = totalTxDelayMs; 2903 pTxData->txDataCounters[ txQid ].SumFWDelayUs = pTxCompleteAttr->fwHandlingTime; 2904 pTxData->txDataCounters[ txQid ].SumMacDelayUs = pTxCompleteAttr->mediumDelay; 2905 } 2906 pTxData->txDataReportedCounters[ txQid ].NumPackets++; 2907 pTxData->txDataReportedCounters[ txQid ].SumTotalDelayMs += totalTxDelayMs; 2908 pTxData->txDataReportedCounters[ txQid ].SumFWDelayUs += pTxCompleteAttr->fwHandlingTime; 2909 pTxData->txDataReportedCounters[ txQid ].SumMacDelayUs += pTxCompleteAttr->mediumDelay; 2910 } 2911 2912 /*************************************************************************** 2913 * txData_UpdateTxCounters * 2914 **************************************************************************** 2915 * DESCRIPTION: free the transmitted msdu 2916 * 2917 * INPUTS: hTxData - the object 2918 * pTxCompletAttr - all atributes passed along with the TX 2919 * complete indication 2920 * 2921 * OUTPUT: 2922 * 2923 * RETURNS: 2924 ***************************************************************************/ 2925 void txData_UpdateTxCounters( TI_HANDLE hTxData, txCompleteAttr_t *pTxCompleteAttr ) 2926 { 2927 txData_t *pTxData = (txData_t*)hTxData; 2928 txPacketIdAttr_t *pPacketId = (txPacketIdAttr_t *)(pTxCompleteAttr->packetId); 2929 UINT16 EventMask = 0; 2930 UINT32 dataLen, TxQid = pPacketId->txQid; 2931 UINT32 retryHistogramIndex; 2932 2933 switch ( pTxCompleteAttr->status ) 2934 { 2935 case SEND_COMPLETE_SUCCESS: 2936 /* update the retry histogram */ 2937 retryHistogramIndex = (pTxCompleteAttr->ackFailures >= TX_RETRY_HISTOGRAM_SIZE ? 2938 TX_RETRY_HISTOGRAM_SIZE - 1 : 2939 pTxCompleteAttr->ackFailures); 2940 pTxData->txDataCounters[ TxQid ].RetryHistogram[ retryHistogramIndex ]++; 2941 2942 /* update delay histogram */ 2943 txData_SetTxDelayCounters( hTxData, TxQid, pTxCompleteAttr, pPacketId->driverHandlingTime ); 2944 2945 if ( (TRUE == pPacketId->bDataMsdu) && (pTxData->txDataQosParams.headerConverMode == QOS_CONVERT) ) 2946 { 2947 dataLen = pPacketId->msduDataLen - (WLAN_WITH_SNAP_QOS_HEADER_MAX_SIZE - ETHERNET_HDR_LEN); 2948 } 2949 else 2950 { 2951 dataLen = pPacketId->msduDataLen - (WLAN_WITH_SNAP_HEADER_MAX_SIZE - ETHERNET_HDR_LEN); 2952 } 2953 2954 if ( IsMacAddressDirected( &(pPacketId->destinationMac) ) ) 2955 { 2956 /* Directed frame */ 2957 pTxData->txDataCounters[TxQid].DirectedFramesXmit++; 2958 pTxData->txDataCounters[TxQid].DirectedBytesXmit += dataLen; 2959 EventMask |= DIRECTED_BYTES_XFER; 2960 EventMask |= DIRECTED_FRAMES_XFER; 2961 } 2962 else if ( IsMacAddressBroadcast( &(pPacketId->destinationMac) ) ) 2963 { 2964 /* Broadcast frame */ 2965 pTxData->txDataCounters[TxQid].BroadcastFramesXmit++; 2966 pTxData->txDataCounters[TxQid].BroadcastBytesXmit += dataLen; 2967 EventMask |= BROADCAST_BYTES_XFER; 2968 EventMask |= BROADCAST_FRAMES_XFER; 2969 } 2970 else 2971 { 2972 /* Multicast Address */ 2973 pTxData->txDataCounters[TxQid].MulticastFramesXmit++; 2974 pTxData->txDataCounters[TxQid].MulticastBytesXmit += dataLen; 2975 EventMask |= MULTICAST_BYTES_XFER; 2976 EventMask |= MULTICAST_FRAMES_XFER; 2977 } 2978 pTxData->txDataCounters[TxQid].XmitOk++; 2979 EventMask |= XFER_OK; 2980 2981 /* update the max consecutive retry failures (if needed) */ 2982 if (pTxData->currentConsecutiveRetryFail > pTxData->txDataCounters[ TxQid ].MaxConsecutiveRetryFail) 2983 { 2984 pTxData->txDataCounters[TxQid].MaxConsecutiveRetryFail = pTxData->currentConsecutiveRetryFail; 2985 } 2986 pTxData->currentConsecutiveRetryFail = 0; 2987 2988 txData_DistributorTxEvent( pTxData, EventMask, dataLen ); 2989 break; 2990 2991 case SEND_COMPLETE_RETRY_EXCEEDED: 2992 2993 pTxData->txDataCounters[ TxQid ].RetryFailCounter++; 2994 pTxData->currentConsecutiveRetryFail++; 2995 pTxData->txDataReportedCounters[ TxQid ].OtherFailCounter++; 2996 break; 2997 2998 case SEND_COMPLETE_LIFETIME_EXCEEDED: 2999 pTxData->txDataCounters[ TxQid ].TxTimeoutCounter++; 3000 pTxData->txDataReportedCounters[ TxQid ].OtherFailCounter++; 3001 break; 3002 3003 case SEND_COMPLETE_NO_LINK: 3004 pTxData->txDataCounters[ TxQid ].NoLinkCounter++; 3005 pTxData->txDataReportedCounters[ TxQid ].OtherFailCounter++; 3006 break; 3007 3008 case SEND_COMPLETE_MAC_CRASHED: /* curently not used */ 3009 default: 3010 pTxData->txDataCounters[ TxQid ].OtherFailCounter++; 3011 pTxData->txDataReportedCounters[ TxQid ].OtherFailCounter++; 3012 break; 3013 } 3014 } 3015 3016 static void txData_startVadTimer(TI_HANDLE hTxData, UINT16 voiceDuration) 3017 { 3018 txData_t *pTxData = (txData_t*)hTxData; 3019 3020 if (FALSE == pTxData->bVadTimerEnabled) 3021 { 3022 WLAN_REPORT_INFORMATION(pTxData->hReport, TX_DATA_MODULE_LOG, 3023 ("txData_startVadTimer: (voiceDuration is %d) .....................\n", voiceDuration)); 3024 pTxData->vadTimerDuration = voiceDuration; 3025 pTxData->bVadTimerEnabled = TRUE; 3026 os_timerStart(pTxData->hOs, pTxData->pVadTimer, voiceDuration, TRUE); 3027 3028 } 3029 else 3030 { 3031 WLAN_REPORT_INFORMATION(pTxData->hReport, TX_DATA_MODULE_LOG, 3032 ("txData_startVadTimer: nothing done. VAD is already started ........\n", voiceDuration)); 3033 } 3034 } 3035 3036 static void txData_stopVadTimer(TI_HANDLE hTxData) 3037 { 3038 txData_t *pTxData = (txData_t*)hTxData; 3039 3040 if (pTxData->bVadTimerEnabled) 3041 { 3042 WLAN_REPORT_INFORMATION(pTxData->hReport, TX_DATA_MODULE_LOG, ("txData_stopVadTimer ...\n")); 3043 os_timerStop(pTxData->hOs, pTxData->pVadTimer); 3044 pTxData->bVadTimerEnabled = FALSE; 3045 } 3046 } 3047 3048 static void txData_setVadTimer(TI_HANDLE hTxData, BOOL vadEnabled, UINT16 duration) 3049 { 3050 txData_t *pTxData = (txData_t*)hTxData; 3051 3052 WLAN_REPORT_INFORMATION(pTxData->hReport, TX_DATA_MODULE_LOG, ("txData_setVadTimer (%d, %d)\n", vadEnabled, duration)); 3053 if (vadEnabled) 3054 txData_startVadTimer(hTxData, duration); 3055 else 3056 txData_stopVadTimer(hTxData); 3057 } 3058 3059 static void txData_resetVadTimer(TI_HANDLE hTxData) 3060 { 3061 txData_t *pTxData = (txData_t*)hTxData; 3062 // UINT32 timeStamp; 3063 3064 if (pTxData->bVadTimerEnabled) 3065 { 3066 /* 3067 timeStamp = os_timeStampMs(pTxData->hOs); 3068 printk("resetVadTimer: timestamp = %d\n", timeStamp); 3069 */ 3070 os_timerStop(pTxData->hOs, pTxData->pVadTimer); 3071 os_timerStart(pTxData->hOs, pTxData->pVadTimer, pTxData->vadTimerDuration, TRUE); 3072 } 3073 } 3074 3075 static void txData_vadTimeout(TI_HANDLE hTxData) 3076 { 3077 txData_t *pTxData = (txData_t*)hTxData; 3078 // UINT32 timeStamp; 3079 /* 3080 timeStamp = os_timeStampMs(pTxData->hOs); 3081 printk("vadTimeout: timestamp = %d\n", timeStamp); 3082 */ 3083 txData_sendVadFrame (pTxData, QOS_AC_VO); 3084 } 3085 3086 /*************************************************************************** 3087 * txData_startTxSchedulerFromTimer * 3088 **************************************************************************** 3089 * DESCRIPTION: 3090 * 3091 * INPUTS: 3092 * 3093 * OUTPUT: 3094 * 3095 * RETURNS: 3096 ***************************************************************************/ 3097 static void txData_startTxSchedulerFromTimer(TI_HANDLE hTxData) 3098 { 3099 WLAN_REPORT_DEBUG_TX(((txData_t *)hTxData)->hReport, 3100 ("in txData_startTxSchedulerFromTimer.....................\n")); 3101 3102 txData_startTxScheduler(hTxData); 3103 } 3104 3105 /*********************************************************************** 3106 * txData_sendNullFrame 3107 *********************************************************************** 3108 DESCRIPTION: Send Null frame Function. 3109 The function does the following: 3110 - Builds Null Data Frame with PS bit set to On or Off. 3111 - Allocates MSDU frame. 3112 - Sends the frame. 3113 3114 INPUT: hTxData - Tx Data Pointer. 3115 powerSaveMode - Indicates if to switch the Power Save 3116 mode to On or Off. 3117 module - The calling module. 3118 3119 OUTPUT: None 3120 3121 RETURN: OK on success, NOK otherwise 3122 ************************************************************************/ 3123 TI_STATUS txData_sendNullFrame(TI_HANDLE hTxData, 3124 BOOL powerSaveOn, 3125 allocatingModule_e module) 3126 { 3127 TI_STATUS status; 3128 mem_MSDU_T *pMsdu; 3129 paramInfo_t daParam, saParam; 3130 dot11_header_t *pFrame; /* Note : there is no body for null frame */ 3131 txData_t *pTxData = (txData_t *)hTxData; 3132 3133 /* Getting new msdu */ 3134 status = wlan_memMngrAllocMSDU(pTxData->hMemMngr, &pMsdu, WLAN_HDR_LEN + TX_TOTAL_OFFSET_BEFORE_DATA, module); 3135 if (status != OK) 3136 return NOK; 3137 3138 pFrame = (dot11_header_t*)(pMsdu->firstBDPtr->data + TX_TOTAL_OFFSET_BEFORE_DATA); 3139 3140 /* Setting the Frame Control with Data frame type and Null frame sub type*/ 3141 pFrame->fc = 0; 3142 pFrame->fc |= DOT11_FC_DATA_NULL_FUNCTION; 3143 pFrame->fc |= DOT11_FC_TO_DS; 3144 3145 /* setting the Power Save bit in the Frame control field*/ 3146 if(powerSaveOn == TRUE) 3147 pFrame->fc |= (0x1 << DOT11_FC_PWR_MGMT_SHIFT); 3148 3149 daParam.paramType = CTRL_DATA_CURRENT_BSSID_PARAM; 3150 status = ctrlData_getParam(pTxData->hCtrlData, &daParam); 3151 if (status != OK) 3152 { 3153 wlan_memMngrFreeMSDU(pTxData->hMemMngr, pMsdu->handle); 3154 return NOK; 3155 } 3156 3157 /* copy destination mac address */ 3158 MAC_COPY(pTxData->hOs, (&pFrame->address3), (&daParam.content.ctrlDataCurrentBSSID)); 3159 3160 saParam.paramType = CTRL_DATA_MAC_ADDRESS; 3161 status = ctrlData_getParam(pTxData->hCtrlData, &saParam); 3162 if (status != OK) 3163 { 3164 wlan_memMngrFreeMSDU(pTxData->hMemMngr, pMsdu->handle); 3165 return NOK; 3166 } 3167 3168 /* copy source mac address */ 3169 MAC_COPY(pTxData->hOs, (&pFrame->address2), (&saParam.content.ctrlDataCurrentBSSID)); 3170 3171 /* copy BSSID (destination mac address) */ 3172 MAC_COPY(pTxData->hOs, (&pFrame->address1), (&daParam.content.ctrlDataCurrentBSSID)); 3173 3174 /* Update MSDU parameters */ 3175 pMsdu->headerLen = pMsdu->dataLen = WLAN_HDR_LEN; 3176 pMsdu->firstBDPtr->length = pMsdu->dataLen + TX_TOTAL_OFFSET_BEFORE_DATA; 3177 3178 /* send the packet to the TX */ 3179 pMsdu->qosTag = 0; 3180 pMsdu->txFlags |= TX_DATA_NULL_MSDU; 3181 3182 status = txData_txSendMsdu(hTxData, pMsdu); 3183 3184 return status; 3185 } 3186 3187 /*********************************************************************** 3188 * txData_sendVadFrame 3189 *********************************************************************** 3190 DESCRIPTION: Send a polling frame to retrieve downlink traffic from 3191 the AP. Activated by the voice application when there is 3192 no uplink traffic during a voice call. 3193 The polling is either PS-Poll (for legacy PS) or QoS-Null 3194 (for UPSD). 3195 Null frame is currently added after PS-Poll to trigger 3196 the triggered-scan which is only triggered by data frames! 3197 Note that currently the acID parameter is ignored to insure this 3198 function is not activated for other ACs than Voice (to add this 3199 flexibility the txData_txSendMsdu() function should be updated. 3200 3201 INPUT: acID - Currently not used! Supporting only AC_VO! 3202 3203 OUTPUT: None 3204 3205 RETURN: OK on success, NOK otherwise 3206 ************************************************************************/ 3207 3208 TI_STATUS txData_sendVadFrame(TI_HANDLE hTxData, UINT8 acID) 3209 { 3210 mem_MSDU_T *pMsdu; 3211 TI_STATUS status; 3212 txData_t *pTxData = (txData_t *)hTxData; 3213 paramInfo_t param; 3214 3215 if (pTxData->txDataPortStatus != OPEN) 3216 { 3217 WLAN_REPORT_INFORMATION(pTxData->hReport, TX_DATA_MODULE_LOG, 3218 ("txData_sendVadFrame(): While port status is %d\n", pTxData->txDataPortStatus )); 3219 return NOK; 3220 } 3221 3222 param.paramType = QOS_MNGR_ACTIVE_PROTOCOL; 3223 status = qosMngr_getParams(pTxData->hQosMngr, ¶m); 3224 3225 /* For WME - send QoS-Null-Data. */ 3226 if (param.content.qosSiteProtocol == WME) 3227 { 3228 /* Send QoS-Null frame to retrieve downlink packets and to trigger the triggered-scan. */ 3229 /* Note: If VO mode is PSPOLL, the txData_txSendMsdu() will add the PS-Poll frame. */ 3230 if((status = txData_buildQosNullDataFrame(pTxData,&pMsdu,wmeAcToUpIndex[QOS_AC_VO])) == OK) 3231 status = txData_txSendMsdu(hTxData, pMsdu); 3232 3233 WLAN_REPORT_INFORMATION(pTxData->hReport, TX_DATA_MODULE_LOG, 3234 ("txData_sendVadFrame(): WME site...Sending QoS-Null frame, Status=%d\n", status)); 3235 } 3236 3237 /* For non-WME - send PS-Poll plus Null-Data. */ 3238 else 3239 { 3240 /* Send PS-Poll to retrieve downlink packets. */ 3241 if((status = txData_getPsPollFrame(pTxData,&pMsdu)) == OK) 3242 status = txData_txSendMsdu(hTxData, pMsdu); 3243 3244 /* Send also a null frame to trigger the triggered-scan in the FW. */ 3245 /* Note: Needed because the scan is triggered only by data frames, so PS-Poll is not enough!. */ 3246 /* Note: The txData_txSendMsdu() won't send another PS-Poll before the null frame since 3247 pMsdu->qosTag is set to 0 for null (and not voice). */ 3248 status = txData_sendNullFrame(hTxData, FALSE, TX_MODULE); 3249 3250 WLAN_REPORT_INFORMATION(pTxData->hReport, TX_DATA_MODULE_LOG, 3251 ("txData_sendVadFrame(): Non-WME site...Sending PS-Poll and Null frame, Status=%d\n", status)); 3252 } 3253 3254 return status; 3255 } 3256 3257 3258 /*********************************************************************** 3259 * txData_getPsPollFrame 3260 *********************************************************************** 3261 DESCRIPTION: builds PS POLL frame Function. 3262 The function does the following: 3263 - Builds PS POLL Control Frame with PS bit set to On . 3264 - Allocates MSDU frame. 3265 - Sends the frame. 3266 3267 ---------------------------- 3268 PS Poll - 802.11 Mac Header 3269 ---------------------------- 3270 Version 0 3271 Type %01 (Control) 3272 Subtype %1010 (PS Poll) 3273 Frame Control Flag %00010000 (Power Management Bit set -> Power Save mode) 3274 Assoc ID association ID 3275 BSSID MAC addr of BSSID 3276 Transmitter MAC addr of sender 3277 ---------------------------- 3278 3279 typedef struct 3280 { 3281 UINT16 fc; 3282 UINT16 AID; 3283 macAddress_t BSSID; 3284 macAddress_t TA; 3285 } dot11_PsPollFrameHeader_t; 3286 3287 3288 INPUT: 3289 3290 OUTPUT: None 3291 3292 RETURN: OK on success, NOK otherwise 3293 ************************************************************************/ 3294 TI_STATUS txData_getPsPollFrame(TI_HANDLE hTxData,mem_MSDU_T **pMsduPsPoll) 3295 { 3296 TI_STATUS status = OK; 3297 UINT32 timeStamp ; 3298 paramInfo_t daParam, saParam; 3299 whalParamInfo_t whalParam; 3300 dot11_PsPollFrameHeader_t *pFrame; /* Note : there is no body for null frame */ 3301 txData_t *pTxData = (txData_t *)hTxData; 3302 mem_MSDU_T *pMsdu; 3303 /* Getting new msdu */ 3304 status = wlan_memMngrAllocMSDU(pTxData->hMemMngr, &pMsdu, WLAN_HDR_LEN + TX_TOTAL_OFFSET_BEFORE_DATA, TX_MODULE); 3305 if (status != OK) 3306 { 3307 return NOK; 3308 } 3309 3310 3311 pFrame = (dot11_PsPollFrameHeader_t*)(pMsdu->firstBDPtr->data + TX_TOTAL_OFFSET_BEFORE_DATA); 3312 3313 /* 3314 ** Building the Frame Control word (16 bits) 3315 ** --------------------------------------------- 3316 */ 3317 pFrame->fc = 0; 3318 3319 /* 3320 ** Type = Control 3321 ** SubType = Power Save (PS) POLL, */ 3322 pFrame->fc |= DOT11_FC_PS_POLL; 3323 3324 /* 3325 ** setting the Power Management bit in the Frame control field 3326 ** to be "Power Save mode" 3327 */ 3328 pFrame->fc |= (0x1 << DOT11_FC_PWR_MGMT_SHIFT); 3329 3330 /* 3331 ** Association ID 3332 ** ----------------- 3333 */ 3334 whalParam.paramType = HAL_CTRL_AID_PARAM; 3335 status = whalCtrl_GetParam (pTxData->hWhalCtrl, &whalParam) ; 3336 if (status != OK) 3337 { 3338 wlan_memMngrFreeMSDU(pTxData->hMemMngr, pMsdu->handle); 3339 return NOK; 3340 } 3341 /* AID should have its two MSB bit Set to "1"*/ 3342 pFrame->AID = whalParam.content.halCtrlAid | 0xC000; 3343 WLAN_REPORT_WARNING(pTxData->hReport, TX_DATA_MODULE_LOG, 3344 (" AID 4 = %d \n", (whalParam.content.halCtrlAid | 0xC000))); 3345 3346 /* 3347 ** BSSID 3348 ** --------- 3349 */ 3350 daParam.paramType = CTRL_DATA_CURRENT_BSSID_PARAM; 3351 status = ctrlData_getParam(pTxData->hCtrlData, &daParam); 3352 if (status != OK) 3353 { 3354 wlan_memMngrFreeMSDU(pTxData->hMemMngr, pMsdu->handle); 3355 return NOK; 3356 } 3357 /* copy destination mac address */ 3358 MAC_COPY(pTxData->hOs, (&pFrame->BSSID), (&daParam.content.ctrlDataCurrentBSSID)); 3359 3360 3361 3362 3363 /* 3364 ** TA - Transmiter (MAC) Address 3365 ** ------------------------------- 3366 */ 3367 saParam.paramType = CTRL_DATA_MAC_ADDRESS; 3368 status = ctrlData_getParam(pTxData->hCtrlData, &saParam); 3369 if (status != OK) 3370 { 3371 wlan_memMngrFreeMSDU(pTxData->hMemMngr, pMsdu->handle); 3372 return NOK; 3373 } 3374 /* copy source mac address */ 3375 MAC_COPY(pTxData->hOs, (&pFrame->TA), (&saParam.content.ctrlDataCurrentBSSID)); 3376 3377 timeStamp = os_timeStampMs(pTxData->hOs); 3378 3379 WLAN_REPORT_INFORMATION(pTxData->hReport, TX_DATA_MODULE_LOG, 3380 (" txData_sendPsPollFrame() : time = %d insert PS_POLL frame to Driver queue \n", timeStamp)); 3381 3382 /* Update MSDU parameters */ 3383 pMsdu->headerLen = pMsdu->dataLen = sizeof(dot11_PsPollFrameHeader_t); 3384 pMsdu->firstBDPtr->length = pMsdu->dataLen + TX_TOTAL_OFFSET_BEFORE_DATA; 3385 3386 pMsdu->txFlags |= TX_DATA_PS_POLL; 3387 3388 3389 if (status == OK) 3390 WLAN_REPORT_INFORMATION(pTxData->hReport, TX_DATA_MODULE_LOG, 3391 ("in txData_sendPsPollFrame: enter PS_POLL to queue\n")); 3392 else 3393 WLAN_REPORT_INFORMATION(pTxData->hReport, TX_DATA_MODULE_LOG, 3394 ("in txData_sendPsPollFrame: didn't enter PS_POLL to queue\n")); 3395 3396 *pMsduPsPoll = pMsdu; 3397 3398 return status; 3399 } 3400 3401 3402 /*********************************************************************** 3403 * txData_updateUsedTime 3404 *********************************************************************** 3405 DESCRIPTION: This function is called for every txComplete in order 3406 to update the transmisssion time. 3407 3408 INPUT: hTxData - handale to the ts data object 3409 qNum - the queue that the frame transmitted from 3410 usedTime - the time of the transmission (in microseconds) 3411 3412 OUTPUT: None 3413 3414 RETURN: OK on success 3415 ************************************************************************/ 3416 TI_STATUS txData_updateUsedTime(TI_HANDLE hTxData, UINT32 qNum, UINT16 usedTime) 3417 { 3418 txData_t *pTxData = (txData_t *)hTxData; 3419 3420 /* addd the used time for the specific queue */ 3421 pTxData->dataMsduListArr[qNum]->totalUsedTime += usedTime; 3422 3423 return OK; 3424 } 3425 3426 3427 /*********************************************************************** 3428 * txData_calcCreditFromTimer 3429 *********************************************************************** 3430 DESCRIPTION: This function is called when credit calculation timer 3431 is expired. it calculate the credit for the admission ctrl 3432 credit algorithm 3433 3434 3435 INPUT: hTxData - handle to the ts data object 3436 3437 OUTPUT: None 3438 3439 RETURN: void 3440 ************************************************************************/ 3441 static void txData_calcCreditFromTimer(TI_HANDLE hTxData) 3442 { 3443 UINT32 qNum; 3444 OS_802_11_THRESHOLD_CROSS_INDICATION_PARAMS mediumTimeCross; 3445 txData_t *pTxData = (txData_t *)hTxData; 3446 INT32 prevCredit; 3447 INT32 highCreditThreshold; 3448 INT32 lowCreditThreshold; 3449 MsduList_t *pMsduList; 3450 INT32 usageRatio; 3451 INT32 currUsage; 3452 INT32 prevUsage; 3453 3454 /* get current time stamp */ 3455 UINT32 currentTimeStamp = os_timeStampMs(pTxData->hOs); 3456 3457 3458 for(qNum = 0 ; qNum< MAX_NUM_OF_TX_QUEUES ; qNum++) 3459 { 3460 pMsduList = pTxData->dataMsduListArr[qNum]; 3461 3462 /* check if this queue is under admission ctrl opration */ 3463 if(pMsduList->mediumTime == 0) 3464 { 3465 WLAN_REPORT_INFORMATION(pTxData->hReport, TX_DATA_MODULE_LOG, 3466 (" txData_calcCreditFromTimer() :qNum = %d mediumTime = 0 \n",qNum)); 3467 3468 continue; 3469 } 3470 3471 /* in case of wraparound */ 3472 if(currentTimeStamp < pMsduList->lastTimeStamp) 3473 pMsduList->lastTimeStamp = 0; 3474 3475 /* store prev credit */ 3476 prevCredit = pMsduList->credit; 3477 3478 /* Calculate the medium usage ratio: totalUsedTime / mediumTime * 1000 3479 Note that since the totalUsedTime is in usec and not msec we don't multiply by 1000. */ 3480 usageRatio = pMsduList->totalUsedTime / pMsduList->mediumTime; 3481 3482 /* calculate credit */ 3483 pMsduList->credit = pMsduList->credit + (currentTimeStamp - pMsduList->lastTimeStamp) - usageRatio; 3484 3485 /* update last time stamp */ 3486 pMsduList->lastTimeStamp = currentTimeStamp; 3487 3488 /* check if credit exceeds above mediumTime or below -mediumTime */ 3489 if (pMsduList->credit > (INT32)(pMsduList->mediumTime) ) 3490 { 3491 /* in case of credit is big than mediumTime -> set credit to medium time */ 3492 pMsduList->credit = pMsduList->mediumTime; 3493 pMsduList->enableTransmissionTime = 0; 3494 } 3495 3496 /* If credit is lower than -mediumTime we exceed the admitted time. */ 3497 else if (pMsduList->credit <= (INT32)(0 - pMsduList->mediumTime)) 3498 { 3499 /* Only delay transmission on this AC if the "delay" registry key is TRUE */ 3500 if(pTxData->admCtrlDelayDueToMediumTimeOverUsage == TRUE) 3501 pMsduList->enableTransmissionTime = (0 - pMsduList->credit) - pMsduList->mediumTime; 3502 } 3503 3504 WLAN_REPORT_INFORMATION(pTxData->hReport, TX_DATA_MODULE_LOG, 3505 ("credit = %d | TotalUsedTime = %d | enableTransmissionTime = %d\n", 3506 pMsduList->credit, pMsduList->totalUsedTime/1000, pMsduList->enableTransmissionTime)); 3507 3508 /* Check medium-usage threshold cross events */ 3509 /*********************************************/ 3510 /* 3511 * The medium-usage events are defined as follows: 3512 * The high threshold triggers event only when crossed upward (traffic increased above threshold). 3513 * The low threshold triggers event only when crossed downward (traffic decreased below threshold). 3514 * Thus, the two thresholds provide hysteresis and prevent multiple triggering. 3515 * The high threshold should be greater than the low threshold. 3516 */ 3517 3518 highCreditThreshold = (INT32)((pMsduList->mediumTime)*(pMsduList->highMediumUsageThreshold)/100); 3519 lowCreditThreshold = (INT32)((pMsduList->mediumTime)*(pMsduList->lowMediumUsageThreshold)/100); 3520 3521 /* The credit is getting more negative as we get closer to the medium usage limit, so we invert 3522 it before comparing to the thresholds (lower credit means higher usage). */ 3523 currUsage = -pMsduList->credit; 3524 prevUsage = -prevCredit; 3525 3526 /* crossing below the low threshold */ 3527 if ( (currUsage < lowCreditThreshold) && (prevUsage >= lowCreditThreshold) ) 3528 { 3529 /* send event */ 3530 mediumTimeCross.uAC = txData_GetAcIdFromQid( hTxData, qNum ); 3531 mediumTimeCross.uHighOrLowThresholdFlag = (UINT32)LOW_THRESHOLD_CROSS; 3532 mediumTimeCross.uAboveOrBelowFlag = (UINT32)CROSS_BELOW; 3533 3534 EvHandlerSendEvent(pTxData->hEvHandler, IPC_EVENT_MEDIUM_TIME_CROSS, (UINT8 *)&mediumTimeCross,sizeof(OS_802_11_THRESHOLD_CROSS_INDICATION_PARAMS)); 3535 WLAN_REPORT_INFORMATION(pTxData->hReport, TX_DATA_MODULE_LOG, 3536 ("crossed below low threshold !!! prevUsage = %d, currUsage = %d, lowCreditThreshold = %d\n", 3537 prevUsage, currUsage, lowCreditThreshold)); 3538 } 3539 3540 /* crossing above the high threshold */ 3541 else if ( (currUsage > highCreditThreshold) && (prevUsage <= highCreditThreshold) ) 3542 { 3543 /* send event */ 3544 mediumTimeCross.uAC = txData_GetAcIdFromQid( hTxData, qNum ); 3545 mediumTimeCross.uHighOrLowThresholdFlag = (UINT32)HIGH_THRESHOLD_CROSS; 3546 mediumTimeCross.uAboveOrBelowFlag = (UINT32)CROSS_ABOVE; 3547 3548 EvHandlerSendEvent(pTxData->hEvHandler, IPC_EVENT_MEDIUM_TIME_CROSS, (UINT8 *)&mediumTimeCross,sizeof(OS_802_11_THRESHOLD_CROSS_INDICATION_PARAMS)); 3549 WLAN_REPORT_INFORMATION(pTxData->hReport, TX_DATA_MODULE_LOG, 3550 ("crossed above high threshold !!! prevUsage = %d, currUsage = %d, highCreditThreshold = %d\n", 3551 prevUsage, currUsage, highCreditThreshold)); 3552 } 3553 3554 /* reset totalUsedTime */ 3555 pMsduList->totalUsedTime = 0; 3556 3557 } 3558 3559 } 3560 3561 3562 /*********************************************************************** 3563 * txData_setAdmisionCtrlParams 3564 *********************************************************************** 3565 DESCRIPTION: This function is called for add/delete a tspec in order 3566 to update parameters. 3567 3568 INPUT: hTxData - handale to the ts data object 3569 acID - the AC of the tspec 3570 mediumTime - tha alocated medium time for this UP 3571 minimumPHYRate - the min phy rate to send a packet of this UP 3572 admFlag - indicate if the its addition or deletion of tspec 3573 3574 OUTPUT: None 3575 3576 RETURN: void 3577 ************************************************************************/ 3578 TI_STATUS txData_setAdmisionCtrlParams(TI_HANDLE hTxData, 3579 UINT8 acID, 3580 UINT16 mediumTime, 3581 UINT32 minimumPHYRate, 3582 BOOL admFlag) 3583 { 3584 UINT8 queueIndex; 3585 UINT8 i; 3586 txData_t *pTxData = (txData_t *)hTxData; 3587 MsduList_t *pMsduList; 3588 3589 /* find queue from AC */ 3590 queueIndex = pTxData->txDataAcTrfcCtrl[acID].QueueIndex; 3591 3592 pMsduList = pTxData->dataMsduListArr[queueIndex]; 3593 3594 if(admFlag == TRUE) 3595 { 3596 /* tspaec added */ 3597 pMsduList->mediumTime = mediumTime; 3598 3599 /* in case of medium time>0 set relevant parameters to the credit algo calculation */ 3600 pMsduList->admissionState = AC_ADMITTED; 3601 3602 /* enable admission algo for this queue */ 3603 pMsduList->useAdmissionAlgo = TRUE; 3604 3605 pMsduList->lastTimeStamp = os_timeStampMs(pTxData->hOs); 3606 pMsduList->enableTransmissionTime = 0; 3607 pMsduList->credit = mediumTime; 3608 } 3609 else 3610 { 3611 /* tspaec deleted */ 3612 pMsduList->mediumTime = 0; 3613 3614 /* in case of medium time=0 reset relevant parameters */ 3615 pMsduList->admissionState = AC_NOT_ADMITTED; 3616 3617 pMsduList->useAdmissionAlgo = FALSE; 3618 pMsduList->lastTimeStamp = 0; 3619 pMsduList->enableTransmissionTime = 0; 3620 pMsduList->credit = 0; 3621 3622 } 3623 3624 /* If the timer was not enabled in registry than we will never set it */ 3625 if ( pTxData->bCreditCalcTimerEnabled ) 3626 { 3627 /* enable disable credit calculation timer */ 3628 for(i = 0 ; i < MAX_NUM_OF_TX_QUEUES ; i++) 3629 { 3630 if(pTxData->dataMsduListArr[i]->useAdmissionAlgo == TRUE) 3631 { 3632 if(pTxData->bCreditCalcTimerRunning == FALSE) 3633 { 3634 pTxData->bCreditCalcTimerRunning = TRUE; 3635 os_timerStart(pTxData->hOs, pTxData->pCreditTimer, pTxData->creditCalculationTimeout, TRUE); 3636 } 3637 3638 return OK; 3639 } 3640 } 3641 /* in all queues useAdmissionAlgo is not TRUE */ 3642 if ( pTxData->bCreditCalcTimerRunning ) 3643 { 3644 os_timerStop(pTxData->hOs, pTxData->pCreditTimer); 3645 pTxData->bCreditCalcTimerRunning = FALSE; 3646 } 3647 } 3648 3649 return OK; 3650 3651 } 3652 3653 3654 /*********************************************************************** 3655 * txData_setPsVoiceDeliveryMode 3656 *********************************************************************** 3657 DESCRIPTION: This function is called for add/delete a tspec in order 3658 to set the PS mode for a specific UP 3659 3660 INPUT: hTxData - handale to the ts data object 3661 userPriority - the user priority of the tspec 3662 PsMode - tha PS mode for the specific UP 3663 3664 OUTPUT: None 3665 3666 RETURN: OK on success, NOK otherwise 3667 ************************************************************************/ 3668 TI_STATUS txData_setPsVoiceDeliveryMode(TI_HANDLE hTxData, PSScheme_e PsMode) 3669 { 3670 txData_t *pTxData = (txData_t *)hTxData; 3671 pTxData->txDataAcTrfcCtrl[QOS_AC_VO].PsMode = PsMode; 3672 return OK; 3673 } 3674 3675 /*********************************************************************** 3676 * txData_setMediumUsageThresholds 3677 *********************************************************************** 3678 DESCRIPTION: This function is called in order to set the threshold 3679 for the medium time usage 3680 3681 INPUT: hTxData - handale to the ts data object 3682 acID - the AC 3683 highMediumUsageThreshold - high threshold 3684 lowMediumUsageThreshold - lowhreshold 3685 3686 OUTPUT: None 3687 3688 RETURN: OK on success, NOK otherwise 3689 ************************************************************************/ 3690 TI_STATUS txData_setMediumUsageThresholds(TI_HANDLE hTxData, 3691 UINT8 acID, 3692 INT32 highMediumUsageThreshold, 3693 INT32 lowMediumUsageThreshold) 3694 { 3695 txData_t *pTxData = (txData_t *)hTxData; 3696 3697 UINT8 queueIndex; 3698 3699 /* validate AC */ 3700 if(acID >= MAX_NUM_OF_AC) 3701 return NOK; 3702 3703 /* find queu from ac */ 3704 queueIndex = pTxData->txDataAcTrfcCtrl[acID].QueueIndex; 3705 3706 /* set threshold */ 3707 pTxData->dataMsduListArr[queueIndex]->lowMediumUsageThreshold = lowMediumUsageThreshold; 3708 pTxData->dataMsduListArr[queueIndex]->highMediumUsageThreshold = highMediumUsageThreshold; 3709 3710 return OK; 3711 3712 } 3713 3714 /*********************************************************************** 3715 * txData_isQueueUseMediumTime 3716 *********************************************************************** 3717 DESCRIPTION: 3718 3719 INPUT: hTxData - handale to the ts data object 3720 3721 OUTPUT: None 3722 3723 RETURN: OK on success, NOK otherwise 3724 ************************************************************************/ 3725 3726 BOOL txData_isQueueUseMediumTime(TI_HANDLE hTxData, UINT8 qNum) 3727 { 3728 txData_t *pTxData = (txData_t *)hTxData; 3729 3730 if(pTxData->dataMsduListArr[qNum]->mediumTime == 0) 3731 return FALSE; 3732 else 3733 return TRUE; 3734 3735 } 3736 3737 3738 3739 void Test_HeaderConvertion(TI_HANDLE hTxData, mem_MSDU_T *pMsdu) 3740 { 3741 txData_t *pTxData = (txData_t *)hTxData; 3742 3743 print_MsduDataHeader(pTxData->hMemMngr, pMsdu); 3744 3745 txData_convertEthToWlanHeader( pTxData, pMsdu ); 3746 3747 print_MsduDataHeader(pTxData->hMemMngr, pMsdu); 3748 3749 } 3750 3751 3752 #ifdef TI_DBG 3753 void txData_printTxBlock(TI_HANDLE hTxData) 3754 { 3755 txData_t *pTxData = (txData_t *)hTxData; 3756 int i; 3757 3758 WLAN_OS_REPORT(("hCtrlData = 0x%X\n", pTxData->hCtrlData)); 3759 WLAN_OS_REPORT(("hTnetwDrv = 0x%X\n", pTxData->hTnetwDrv)); 3760 WLAN_OS_REPORT(("hOs = 0x%X\n", pTxData->hOs)); 3761 WLAN_OS_REPORT(("hReport = 0x%X\n", pTxData->hReport)); 3762 WLAN_OS_REPORT(("hMemMngr = 0x%X\n", pTxData->hMemMngr)); 3763 WLAN_OS_REPORT(("pSchedulerTimer = 0x%X\n", pTxData->pSchedulerTimer)); 3764 3765 WLAN_OS_REPORT(("hCriticalSectionProtect = 0x%X\n", pTxData->hCriticalSectionProtect)); 3766 3767 WLAN_OS_REPORT(("txDataPortStatus = %d\n", pTxData->txDataPortStatus)); 3768 WLAN_OS_REPORT(("txDataCurrentPrivacyInvokedMode = %d\n", pTxData->txDataCurrentPrivacyInvokedMode)); 3769 WLAN_OS_REPORT(("txDataEapolEncryptionStatus = %d\n", pTxData->txDataEapolEncryptionStatus)); 3770 3771 WLAN_OS_REPORT(("txDataIsSchedulerInWork = %d\n", pTxData->txDataIsSchedulerInWork)); 3772 3773 WLAN_OS_REPORT(("txDataNumOfQueues = %d\n", pTxData->txDataNumOfQueues)); 3774 WLAN_OS_REPORT(("mngMsduList = 0x%X\n", pTxData->mngMsduList)); 3775 for(i=0 ; i < MAX_NUM_OF_TX_QUEUES; i++ ) 3776 { 3777 WLAN_OS_REPORT(("dataMsduList %d = 0x%X\n",i, pTxData->dataMsduListArr[i])); 3778 } 3779 3780 } 3781 3782 3783 /* 3784 void printFullMsduList(MsduList_t *this); 3785 void printMsduList(MsduList_t *this); 3786 */ 3787 void txData_printDataMsduList(TI_HANDLE hTxData) 3788 { 3789 txData_t *pTxData = (txData_t *)hTxData; 3790 int i; 3791 3792 for(i=0 ; i < MAX_NUM_OF_TX_QUEUES; i++ ) 3793 { 3794 WLAN_OS_REPORT(("List : %d \n", i)); 3795 printMsduList(pTxData->dataMsduListArr[i]); 3796 } 3797 3798 3799 } 3800 3801 void txData_fullPrintDataMsduList(TI_HANDLE hTxData) 3802 { 3803 txData_t *pTxData = (txData_t *)hTxData; 3804 int i; 3805 3806 for(i=0 ; i < MAX_NUM_OF_TX_QUEUES; i++ ) 3807 { 3808 WLAN_OS_REPORT(("List : %d \n", i)); 3809 printFullMsduList(pTxData->dataMsduListArr[i]); 3810 } 3811 } 3812 3813 void txData_printMgmtMsduList(TI_HANDLE hTxData) 3814 { 3815 txData_t *pTxData = (txData_t *)hTxData; 3816 3817 printMsduList(pTxData->mngMsduList); 3818 3819 3820 } 3821 3822 void txData_fullPrintMgmtMsduList(TI_HANDLE hTxData) 3823 { 3824 txData_t *pTxData = (txData_t *)hTxData; 3825 3826 printFullMsduList(pTxData->mngMsduList); 3827 } 3828 3829 3830 void txData_printTxCounters(TI_HANDLE hTxData) 3831 { 3832 txData_t *pTxData = (txData_t *)hTxData; 3833 int TxQid; 3834 3835 for (TxQid = 0; TxQid < MAX_NUM_OF_TX_QUEUES; TxQid++) 3836 { 3837 WLAN_OS_REPORT(("Tx Queue %d:\n", TxQid)); 3838 WLAN_OS_REPORT(("===========\n")); 3839 WLAN_OS_REPORT(("XmitOk = %d\n", pTxData->txDataCounters[TxQid].XmitOk)); 3840 WLAN_OS_REPORT(("DirectedBytesXmit = %d\n", pTxData->txDataCounters[TxQid].DirectedBytesXmit)); 3841 WLAN_OS_REPORT(("DirectedFramesXmit = %d\n", pTxData->txDataCounters[TxQid].DirectedFramesXmit)); 3842 WLAN_OS_REPORT(("MulticastBytesXmit = %d\n", pTxData->txDataCounters[TxQid].MulticastBytesXmit)); 3843 WLAN_OS_REPORT(("MulticastFramesXmit = %d\n", pTxData->txDataCounters[TxQid].MulticastFramesXmit)); 3844 WLAN_OS_REPORT(("BroadcastBytesXmit = %d\n", pTxData->txDataCounters[TxQid].BroadcastBytesXmit)); 3845 WLAN_OS_REPORT(("BroadcastFramesXmit = %d\n", pTxData->txDataCounters[TxQid].BroadcastFramesXmit)); 3846 } 3847 3848 /* dbg functions */ 3849 WLAN_OS_REPORT(("\nTx Debug info:\n", TxQid)); 3850 WLAN_OS_REPORT(("==============\n")); 3851 WLAN_OS_REPORT(("DropedPacketsCounter = %d\n", pTxData->txDataDbgCounters.dbgDropedPacketsCounter)); 3852 WLAN_OS_REPORT(("NumOfNullMsdu (in sendPacketTransfer) = %d\n", pTxData->txDataDbgCounters.dbgNumOfNullMsdu)); 3853 } 3854 3855 3856 void txData_printTxQosCounters(TI_HANDLE hTxData) 3857 { 3858 txData_t *pTxData = (txData_t *)hTxData; 3859 int qIndex; 3860 3861 WLAN_OS_REPORT(("-------------- Tx Queues Statistics ---------------\n\n")); 3862 WLAN_OS_REPORT(("Successed copied = Scheduled - Droped\n")); 3863 WLAN_OS_REPORT(("Successed copied = Scheduled out - check size failed\n")); 3864 3865 WLAN_OS_REPORT(("-------------- Scheduled To Core queues ---------------\n")); 3866 for(qIndex = 0; qIndex < MAX_NUM_OF_TX_QUEUES; qIndex++) 3867 { 3868 WLAN_OS_REPORT(("Queue %d = %d\n",qIndex, pTxData->txDataDbgCounters.dbgInsertToMsduListPackets[qIndex])); 3869 } 3870 3871 WLAN_OS_REPORT(("-------------- Droped From Core queues ---------------\n")); 3872 for(qIndex = 0; qIndex < MAX_NUM_OF_TX_QUEUES; qIndex++) 3873 { 3874 WLAN_OS_REPORT(("Queue %d = %d\n",qIndex, pTxData->txDataDbgCounters.dbgDropedFromMsduListPackets[qIndex])); 3875 } 3876 3877 WLAN_OS_REPORT(("-------------- Scheduled out from Core queues ---------------\n")); 3878 for(qIndex = 0; qIndex < MAX_NUM_OF_TX_QUEUES; qIndex++) 3879 { 3880 WLAN_OS_REPORT(("Queue %d = %d\n",qIndex, pTxData->txDataDbgCounters.dbgScheduledOutPackets[qIndex])); 3881 } 3882 3883 WLAN_OS_REPORT(("--Dropped due Expiry Time in Core Queues (dropped after %d %% of total time)--\n",pTxData->uFracOfLifeTimeToDrop)); 3884 for(qIndex = 0; qIndex < MAX_NUM_OF_TX_QUEUES; qIndex++) 3885 { 3886 WLAN_OS_REPORT(("Queue %d = %d\n",qIndex, pTxData->txDataDbgCounters.dbgDroppedDueExpiryTimePackets[qIndex])); 3887 } 3888 WLAN_OS_REPORT(("-------------- Free MSDUs in sendPacketTransfer ---------------\n")); 3889 for(qIndex = 0; qIndex < MAX_NUM_OF_TX_QUEUES; qIndex++) 3890 { 3891 WLAN_OS_REPORT(("Queue %d = %d\n",qIndex, pTxData->txDataDbgCounters.dbgNumOfMsduFreeInTxTransfer[qIndex])); 3892 } 3893 3894 WLAN_OS_REPORT(("-------------- sendPacketTransfer CB number ---------------\n")); 3895 for(qIndex = 0; qIndex < MAX_NUM_OF_TX_QUEUES; qIndex++) 3896 { 3897 WLAN_OS_REPORT(("Queue %d = %d\n",qIndex, pTxData->txDataDbgCounters.dbgNumOfMsduTxTransferCB[qIndex])); 3898 } 3899 3900 WLAN_OS_REPORT(("-------------- XFER done in scheduler ---------------\n")); 3901 for(qIndex = 0; qIndex < MAX_NUM_OF_TX_QUEUES; qIndex++) 3902 { 3903 WLAN_OS_REPORT(("Queue %d = %d\n",qIndex, pTxData->txDataDbgCounters.dbgNumOfMsduXferDoneInShceduler[qIndex])); 3904 } 3905 3906 WLAN_OS_REPORT(("-------------- Success in scheduler ---------------\n")); 3907 for(qIndex = 0; qIndex < MAX_NUM_OF_TX_QUEUES; qIndex++) 3908 { 3909 WLAN_OS_REPORT(("Queue %d = %d\n",qIndex, pTxData->txDataDbgCounters.dbgNumOfMsduSuccessInScheduler[qIndex])); 3910 } 3911 3912 WLAN_OS_REPORT(("-------------- Pending in scheduler ---------------\n")); 3913 for(qIndex = 0; qIndex < MAX_NUM_OF_TX_QUEUES; qIndex++) 3914 { 3915 WLAN_OS_REPORT(("Queue %d = %d\n",qIndex, pTxData->txDataDbgCounters.dbgNumOfMsduPendingInScheduler[qIndex])); 3916 } 3917 3918 WLAN_OS_REPORT(("-------------- Busy in scheduler ---------------\n")); 3919 for(qIndex = 0; qIndex < MAX_NUM_OF_TX_QUEUES; qIndex++) 3920 { 3921 WLAN_OS_REPORT(("Queue %d = %d\n",qIndex, pTxData->txDataDbgCounters.dbgNumOfMsduBusyInScheduler[qIndex])); 3922 } 3923 3924 WLAN_OS_REPORT(("-------------- Error in scheduler ---------------\n")); 3925 for(qIndex = 0; qIndex < MAX_NUM_OF_TX_QUEUES; qIndex++) 3926 { 3927 WLAN_OS_REPORT(("Queue %d = %d\n",qIndex, pTxData->txDataDbgCounters.dbgNumOfMsduErrorInScheduler[qIndex])); 3928 } 3929 3930 WLAN_OS_REPORT(("-------------- sendPacketComplete ---------------\n")); 3931 for(qIndex = 0; qIndex < MAX_NUM_OF_TX_QUEUES; qIndex++) 3932 { 3933 WLAN_OS_REPORT(("Queue %d = %d\n",qIndex, pTxData->txDataDbgCounters.dbgNumOfsendPacketComplete[qIndex])); 3934 } 3935 3936 WLAN_OS_REPORT(("-------------- sendPacketComplete Error---------------\n")); 3937 for(qIndex = 0; qIndex < MAX_NUM_OF_TX_QUEUES; qIndex++) 3938 { 3939 WLAN_OS_REPORT(("Queue %d = %d\n",qIndex, pTxData->txDataDbgCounters.dbgTxCmpltError[qIndex])); 3940 } 3941 3942 3943 3944 WLAN_OS_REPORT(("-------------- Number of MSDUs successfuly sent to GWSI layer ---------------\n")); 3945 for(qIndex = 0; qIndex < MAX_NUM_OF_TX_QUEUES; qIndex++) 3946 { 3947 WLAN_OS_REPORT(("Queue %d = %d\n",qIndex, pTxData->txDataDbgCounters.dbgSendToGwsiQosPackets[qIndex])); 3948 } 3949 3950 WLAN_OS_REPORT(("-------------- Current GWSI port status: %s --------------\n", 3951 (GWSI_OPEN == pTxData->txDataGwsiInterfaceStatus ? "OPEN" : "PENDING") )); 3952 3953 WLAN_OS_REPORT(("-------------- HW queue available status ---------------\n")); 3954 for(qIndex = 0; qIndex < MAX_NUM_OF_TX_QUEUES; qIndex++) 3955 { 3956 WLAN_OS_REPORT(("Queue %d %s\n",qIndex, 3957 (TRUE == pTxData->txDataAvailableQueue[qIndex] ? "Available" : "Not available") )); 3958 } 3959 } 3960 3961 3962 void txData_printQosParams(TI_HANDLE hTxData) 3963 { 3964 UINT8 acID; 3965 UINT8 qIndex; 3966 txData_t *pTxData = (txData_t *)hTxData; 3967 3968 for(acID = FIRST_AC_INDEX;acID < MAX_NUM_OF_AC; acID++) 3969 { 3970 switch(acID) 3971 { 3972 case QOS_AC_BE: 3973 WLAN_OS_REPORT(("BE Params:\n")); 3974 break; 3975 case QOS_AC_BK: 3976 WLAN_OS_REPORT(("BK params:\n")); 3977 break; 3978 case QOS_AC_VI: 3979 WLAN_OS_REPORT(("VI params:\n")); 3980 break; 3981 case QOS_AC_VO: 3982 WLAN_OS_REPORT(("VO params:\n")); 3983 break; 3984 default: 3985 break; 3986 } 3987 3988 switch(pTxData->txDataAcTrfcCtrl[acID].PsMode) 3989 { 3990 case PS_SCHEME_UPSD_TRIGGER: 3991 WLAN_OS_REPORT(("PsMode = UPSD\n")); 3992 3993 break; 3994 case PS_SCHEME_LEGACY_PSPOLL: 3995 WLAN_OS_REPORT(("PsMode = PS_POLL\n")); 3996 3997 break; 3998 case PS_SCHEME_LEGACY: 3999 WLAN_OS_REPORT(("PsMode = PS_SCHEME_REGULAR\n")); 4000 break; 4001 4002 case PS_SCHEME_SAPSD: 4003 WLAN_OS_REPORT(("PsMode = S-APSD\n")); 4004 break; 4005 4006 default: 4007 WLAN_OS_REPORT(("Error: PsMode = %d\n", pTxData->txDataAcTrfcCtrl[acID].PsMode)); 4008 break; 4009 } 4010 WLAN_OS_REPORT(("QueueIndex = %d\n", pTxData->txDataAcTrfcCtrl[acID].QueueIndex)); 4011 WLAN_OS_REPORT(("TxQueueSize = %d\n", pTxData->txDataAcTrfcCtrl[acID].TxQueueSize)); 4012 4013 qIndex = GET_QUEUE_INDEX(pTxData, acID); 4014 4015 if(pTxData->dataMsduListArr[qIndex]->admissionState == AC_NOT_ADMITTED) 4016 WLAN_OS_REPORT(("admissionState = Not Admitted\n\n" )); 4017 else 4018 WLAN_OS_REPORT(("admissionState = Admitted\n\n" )); 4019 4020 } 4021 4022 switch(pTxData->txDataQosParams.headerConverMode) 4023 { 4024 case NO_CONVERT: 4025 WLAN_OS_REPORT(("headerConverMode = NO_CONVERT\n")); 4026 break; 4027 case QOS_CONVERT: 4028 WLAN_OS_REPORT(("headerConverMode = QOS_CONVERT\n")); 4029 break; 4030 case LEGACY_CONVERT: 4031 WLAN_OS_REPORT(("headerConverMode = LEGACY_CONVERT\n")); 4032 break; 4033 } 4034 4035 WLAN_OS_REPORT(("tag_ToQueueClfrTable = %d, %d, %d, %d, %d, %d, %d, %d\n", 4036 pTxData->txDataQosParams.tag_ToAcClsfrTable[0], 4037 pTxData->txDataQosParams.tag_ToAcClsfrTable[1], 4038 pTxData->txDataQosParams.tag_ToAcClsfrTable[2], 4039 pTxData->txDataQosParams.tag_ToAcClsfrTable[3], 4040 pTxData->txDataQosParams.tag_ToAcClsfrTable[4], 4041 pTxData->txDataQosParams.tag_ToAcClsfrTable[5], 4042 pTxData->txDataQosParams.tag_ToAcClsfrTable[6], 4043 pTxData->txDataQosParams.tag_ToAcClsfrTable[7])); 4044 } 4045 4046 void txData_StartTxThroughputTimer(TI_HANDLE hTxData) 4047 { 4048 int counterIndex; 4049 4050 txData_t *pTxData = (txData_t *)hTxData; 4051 4052 if(pTxData->txThroughputTimerEnable == FALSE) 4053 { 4054 for(counterIndex = 0 ; counterIndex < MAX_NUM_OF_TX_QUEUES ; counterIndex++) 4055 { 4056 /* reset throughput counters */ 4057 pTxData->txDataDbgCounters.dbgInsertToMsduListBytes[counterIndex] = 0; 4058 4059 4060 } 4061 4062 pTxData->txThroughputTimerEnable = TRUE; 4063 4064 /* start throughput timer */ 4065 os_timerStart(pTxData->hOs, pTxData->pThroughputTimer, THROUGHPUT_TIMER, TRUE); 4066 } 4067 } 4068 4069 void txData_StopTxThroughputTimer(TI_HANDLE hTxData) 4070 { 4071 txData_t *pTxData = (txData_t *)hTxData; 4072 4073 if(pTxData->txThroughputTimerEnable == TRUE) 4074 { 4075 os_timerStop(pTxData->hOs, pTxData->pThroughputTimer); 4076 pTxData->txThroughputTimerEnable = FALSE; 4077 } 4078 } 4079 4080 static void txData_printTxThroughputPerQueue(TI_HANDLE hTxData) 4081 { 4082 txData_t *pTxData = (txData_t *)hTxData; 4083 4084 int qIndex; 4085 4086 WLAN_OS_REPORT(("\n")); 4087 WLAN_OS_REPORT(("\n")); 4088 WLAN_OS_REPORT(("-------------- Tx Throughput per Queues Statistics ---------------\n")); 4089 WLAN_OS_REPORT(("-------------- Send To Wlan Per Queue Throughput---------------\n")); 4090 4091 for(qIndex = 0 ; qIndex < MAX_NUM_OF_TX_QUEUES ; qIndex++) 4092 { 4093 4094 WLAN_OS_REPORT(("Queue %d = %d KBits/sec\n", qIndex,pTxData->txDataDbgCounters.dbgInsertToMsduListBytes[qIndex]*8/1024)); 4095 /* reset throughput counters */ 4096 pTxData->txDataDbgCounters.dbgInsertToMsduListBytes[qIndex] = 0; 4097 } 4098 } 4099 4100 void txData_StartTxAirThroughputTimer (TI_HANDLE hTxData) 4101 { 4102 unsigned counterIndex; 4103 4104 txData_t *pTxData = (txData_t *)hTxData; 4105 4106 if (!pTxData->txAirThroughputTimerEnable) 4107 { 4108 for (counterIndex = 0; counterIndex < MAX_NUM_OF_TX_QUEUES; counterIndex++) 4109 { 4110 /* reset throughput counters */ 4111 pTxData->txDataDbgCounters.dbgTxCmpltOkBytes[counterIndex] = 0; 4112 } 4113 4114 pTxData->txAirThroughputTimerEnable = TRUE; 4115 4116 /* start throughput timer */ 4117 os_timerStart (pTxData->hOs, pTxData->pAirThroughputTimer, THROUGHPUT_TIMER, TRUE); 4118 } 4119 } 4120 4121 void txData_StopTxAirThroughputTimer (TI_HANDLE hTxData) 4122 { 4123 txData_t *pTxData = (txData_t *)hTxData; 4124 4125 if (pTxData->txAirThroughputTimerEnable) 4126 { 4127 os_timerStop (pTxData->hOs, pTxData->pAirThroughputTimer); 4128 pTxData->txAirThroughputTimerEnable = FALSE; 4129 } 4130 } 4131 4132 static void txData_printTxAirThroughputPerQueue (TI_HANDLE hTxData) 4133 { 4134 txData_t *pTxData = (txData_t *)hTxData; 4135 4136 int qIndex; 4137 4138 WLAN_OS_REPORT (("\n")); 4139 WLAN_OS_REPORT (("\n")); 4140 WLAN_OS_REPORT (("-------------- Tx Air Throughput per Queue Statistics ---------------\n")); 4141 WLAN_OS_REPORT (("-------------- Send to WLAN per Queue Throughput---------------\n")); 4142 4143 for (qIndex = 0; qIndex < MAX_NUM_OF_TX_QUEUES; qIndex++) 4144 { 4145 4146 WLAN_OS_REPORT (("Queue %d = %d KBits/sec\n", qIndex, pTxData->txDataDbgCounters.dbgTxCmpltOkBytes[qIndex] * 8 / 1024)); 4147 /* reset throughput counters */ 4148 pTxData->txDataDbgCounters.dbgTxCmpltOkBytes[qIndex] = 0; 4149 } 4150 } 4151 4152 void txData_StartJitterTimer (TI_HANDLE hTxData) 4153 { 4154 unsigned u_ac; 4155 4156 txData_t *pTxData = (txData_t *)hTxData; 4157 4158 if (!pTxData->txJitterTimerEnable) 4159 { 4160 for (u_ac = 0; u_ac < MAX_NUM_OF_TX_QUEUES; u_ac++) 4161 { 4162 /* reset jitter intervals */ 4163 pTxData->txJitter[u_ac].jitter.core = 0; 4164 pTxData->txJitter[u_ac].jitter.xfer = 0; 4165 pTxData->txJitter[u_ac].jitter.air = 0; 4166 pTxData->txJitter[u_ac].jitter.fw = 0; 4167 4168 pTxData->txJitter[u_ac].delay.core = 0; 4169 pTxData->txJitter[u_ac].delay.xfer = 0; 4170 pTxData->txJitter[u_ac].delay.wait = 0; 4171 pTxData->txJitter[u_ac].delay.fw = 0; 4172 pTxData->txJitter[u_ac].delay.air = 0; 4173 4174 pTxData->txJitter[u_ac].last_delay.core = 0; 4175 pTxData->txJitter[u_ac].last_delay.xfer = 0; 4176 pTxData->txJitter[u_ac].last_delay.fw = 0; 4177 pTxData->txJitter[u_ac].last_delay.air = 0; 4178 4179 pTxData->txJitter[u_ac].max_delay.core = 0; 4180 pTxData->txJitter[u_ac].max_delay.xfer = 0; 4181 pTxData->txJitter[u_ac].max_delay.fw = 0; 4182 pTxData->txJitter[u_ac].max_delay.air = 0; 4183 4184 pTxData->txJitter[u_ac].count.core = 0; 4185 pTxData->txJitter[u_ac].count.xfer = 0; 4186 pTxData->txJitter[u_ac].count.wait = 0; 4187 pTxData->txJitter[u_ac].count.fw = 4188 pTxData->txDataDbgCounters.dbgTxCmpltOk[u_ac]; 4189 pTxData->txJitter[u_ac].count.fw_err = 4190 pTxData->txDataDbgCounters.dbgTxCmpltError[u_ac]; 4191 } 4192 4193 pTxData->txJitterTimerEnable = TRUE; 4194 4195 /* start throughput timer */ 4196 os_timerStart (pTxData->hOs, pTxData->pJitterTimer, THROUGHPUT_TIMER, TRUE); 4197 } 4198 } 4199 4200 void txData_StopJitterTimer (TI_HANDLE hTxData) 4201 { 4202 txData_t *pTxData = (txData_t *)hTxData; 4203 4204 if (pTxData->txJitterTimerEnable) 4205 { 4206 os_timerStop (pTxData->hOs, pTxData->pJitterTimer); 4207 pTxData->txJitterTimerEnable = FALSE; 4208 } 4209 } 4210 4211 static void txData_printJitter (TI_HANDLE hTxData) 4212 { 4213 unsigned u_ac; 4214 txData_t *pTxData = (txData_t *)hTxData; 4215 4216 WLAN_OS_REPORT (("\n")); 4217 WLAN_OS_REPORT (("\n")); 4218 WLAN_OS_REPORT (("-------------- Tx Jitter per Queue Statistics ---------------\n")); 4219 4220 for (u_ac = 0; u_ac < MAX_NUM_OF_TX_QUEUES; u_ac ++) 4221 { 4222 UINT32 u_ok = pTxData->txDataDbgCounters.dbgTxCmpltOk[u_ac] - 4223 pTxData->txJitter[u_ac].count.fw; 4224 UINT32 u_nok = pTxData->txDataDbgCounters.dbgTxCmpltError[u_ac] - 4225 pTxData->txJitter[u_ac].count.fw_err; 4226 4227 if (u_ok + u_nok) 4228 { 4229 WLAN_OS_REPORT (("Queue [%d], drop=%d%%\n", u_ac, u_nok * 100 / (u_ok + u_nok))); 4230 4231 if (pTxData->txJitter[u_ac].count.core) 4232 { 4233 WLAN_OS_REPORT ((" Core: avg.delay=%6d, max.delay=%6d, jitter=%6d\n", 4234 pTxData->txJitter[u_ac].delay.core / pTxData->txJitter[u_ac].count.core, 4235 pTxData->txJitter[u_ac].max_delay.core, 4236 pTxData->txJitter[u_ac].jitter.core / pTxData->txJitter[u_ac].count.core)); 4237 } 4238 if (pTxData->txJitter[u_ac].count.xfer) 4239 { 4240 WLAN_OS_REPORT ((" Xfer: avg.delay=%6d, max.delay=%6d, jitter=%6d\n", 4241 pTxData->txJitter[u_ac].delay.xfer / pTxData->txJitter[u_ac].count.xfer, 4242 pTxData->txJitter[u_ac].max_delay.xfer, 4243 pTxData->txJitter[u_ac].jitter.xfer / pTxData->txJitter[u_ac].count.xfer)); 4244 } 4245 if (pTxData->txJitter[u_ac].count.wait) 4246 { 4247 WLAN_OS_REPORT ((" Wait: avg.delay=%6d\n", 4248 pTxData->txJitter[u_ac].delay.wait / pTxData->txJitter[u_ac].count.wait)); 4249 } 4250 if (u_ok > 0) 4251 { 4252 WLAN_OS_REPORT ((" Fw: avg.delay=%6d, max.delay=%6d, jitter=%6d\n", 4253 pTxData->txJitter[u_ac].delay.fw / u_ok, 4254 pTxData->txJitter[u_ac].max_delay.fw, 4255 pTxData->txJitter[u_ac].jitter.fw / u_ok)); 4256 WLAN_OS_REPORT ((" Air: avg.delay=%6d, max.delay=%6d, jitter=%6d\n", 4257 pTxData->txJitter[u_ac].delay.air / u_ok, 4258 pTxData->txJitter[u_ac].max_delay.air, 4259 pTxData->txJitter[u_ac].jitter.air / u_ok)); 4260 } 4261 } 4262 4263 /* Update/reset jitter info */ 4264 pTxData->txJitter[u_ac].jitter.core = 0; 4265 pTxData->txJitter[u_ac].jitter.xfer = 0; 4266 pTxData->txJitter[u_ac].jitter.fw = 0; 4267 pTxData->txJitter[u_ac].jitter.air = 0; 4268 4269 pTxData->txJitter[u_ac].delay.core = 0; 4270 pTxData->txJitter[u_ac].delay.xfer = 0; 4271 pTxData->txJitter[u_ac].delay.wait = 0; 4272 pTxData->txJitter[u_ac].delay.fw = 0; 4273 pTxData->txJitter[u_ac].delay.air = 0; 4274 4275 pTxData->txJitter[u_ac].max_delay.core = 0; 4276 pTxData->txJitter[u_ac].max_delay.xfer = 0; 4277 pTxData->txJitter[u_ac].max_delay.fw = 0; 4278 pTxData->txJitter[u_ac].max_delay.air = 0; 4279 4280 pTxData->txJitter[u_ac].count.core = 0; 4281 pTxData->txJitter[u_ac].count.xfer = 0; 4282 pTxData->txJitter[u_ac].count.wait = 0; 4283 pTxData->txJitter[u_ac].count.fw = 4284 pTxData->txDataDbgCounters.dbgTxCmpltOk[u_ac]; 4285 pTxData->txJitter[u_ac].count.fw_err = 4286 pTxData->txDataDbgCounters.dbgTxCmpltError[u_ac]; 4287 } 4288 } 4289 4290 #endif /* TI_BDG */ 4291 4292 /*********************************************************************** 4293 * txData_buildQosNullDataFrame 4294 *********************************************************************** 4295 DESCRIPTION: builds QOS_NULL_DATA frame. 4296 4297 INPUT: 4298 4299 OUTPUT: None 4300 4301 RETURN: OK on success, NOK otherwise 4302 ************************************************************************/ 4303 TI_STATUS txData_buildQosNullDataFrame(TI_HANDLE hTxData,mem_MSDU_T **pMsduPsPoll, UINT8 userPriority) 4304 { 4305 TI_STATUS status = OK; 4306 paramInfo_t daParam, saParam; 4307 dot11_header_t *pFrame; /* Note : there is no body for null frame */ 4308 4309 txData_t *pTxData = (txData_t *)hTxData; 4310 mem_MSDU_T *pMsdu; 4311 4312 status = wlan_memMngrAllocMSDU(pTxData->hMemMngr, &pMsdu, WLAN_QOS_HDR_LEN + TX_TOTAL_OFFSET_BEFORE_DATA, TX_MODULE); 4313 4314 if (status != OK) 4315 { 4316 return NOK; 4317 } 4318 pFrame = (dot11_header_t*)(pMsdu->firstBDPtr->data+ TX_TOTAL_OFFSET_BEFORE_DATA); 4319 4320 /* Build frame control */ 4321 pFrame->fc = DOT11_FC_DATA_NULL_QOS; 4322 pFrame->fc |= (0x1 << DOT11_FC_TO_DS_SHIFT); 4323 4324 pFrame->qosControl = (userPriority << QOS_CONTROL_UP_SHIFT); 4325 4326 pFrame->fc = ENDIAN_HANDLE_WORD(pFrame->fc); 4327 4328 /* BSSID */ 4329 daParam.paramType = CTRL_DATA_CURRENT_BSSID_PARAM; 4330 status = ctrlData_getParam(pTxData->hCtrlData, &daParam); 4331 if (status != OK) 4332 { 4333 wlan_memMngrFreeMSDU(pTxData->hMemMngr, pMsdu->handle); 4334 return NOK; 4335 } 4336 MAC_COPY(pTxData->hOs, (&pFrame->address3), (&daParam.content.ctrlDataCurrentBSSID)); 4337 MAC_COPY(pTxData->hOs, (&pFrame->address1), (&daParam.content.ctrlDataCurrentBSSID)); 4338 4339 /* Source MAC address */ 4340 saParam.paramType = CTRL_DATA_MAC_ADDRESS; 4341 status = ctrlData_getParam(pTxData->hCtrlData, &saParam); 4342 if (status != OK) 4343 { 4344 wlan_memMngrFreeMSDU(pTxData->hMemMngr, pMsdu->handle); 4345 return NOK; 4346 } 4347 /* copy source mac address */ 4348 MAC_COPY(pTxData->hOs, (&pFrame->address2), (&saParam.content.ctrlDataDeviceMacAddress)); 4349 4350 /* Update MSDU parameters */ 4351 pMsdu->headerLen = WLAN_QOS_HDR_LEN; 4352 pMsdu->dataLen = WLAN_QOS_HDR_LEN; 4353 pMsdu->firstBDPtr->length = WLAN_QOS_HDR_LEN; 4354 4355 pMsdu->qosTag = userPriority; 4356 pMsdu->txFlags |= TX_DATA_NULL_MSDU; 4357 4358 // all data or mgmt packets built on host must have the correct 4359 // offset set to point to the start of the mac frame 4360 memMgr_BufOffset(pMsdu->firstBDPtr) = TX_TOTAL_OFFSET_BEFORE_DATA; 4361 4362 4363 *pMsduPsPoll = pMsdu; 4364 4365 return status; 4366 } 4367 4368 4369 /**************************************************************************** 4370 * txData_SetQidToAcTable() 4371 **************************************************************************** 4372 * DESCRIPTION: set Qid according to Queue ID 4373 ****************************************************************************/ 4374 void txData_SetQidToAcTable(TI_HANDLE hTxData,UINT8 QidStart, UINT8 QidEnd,UINT8 AcId) 4375 { 4376 int i; 4377 txData_t *pTxData = (txData_t *)hTxData; 4378 4379 for(i = QidStart ; i <= QidEnd; i++) 4380 pTxData->QidToAcTable[i] = AcId; 4381 4382 } 4383 4384 /**************************************************************************** 4385 * txData_GetAcIdFromQid() 4386 **************************************************************************** 4387 * DESCRIPTION: Get the Ac Id according to the Queue id 4388 ****************************************************************************/ 4389 UINT8 txData_GetAcIdFromQid(TI_HANDLE hTxData,UINT8 Qid) 4390 { 4391 txData_t *pTxData = (txData_t *)hTxData; 4392 return (pTxData->QidToAcTable[Qid]); 4393 } 4394 4395 /**************************************************************************** 4396 * txData_GetWlanHeaderLength() 4397 **************************************************************************** 4398 * DESCRIPTION: calculates the WLAN header length, according to QoS, 4399 * current encryption, and packet type 4400 ****************************************************************************/ 4401 UINT32 txData_GetWlanHeaderLength( TI_HANDLE hTxData, void *pData, UINT32 txFlags ) 4402 { 4403 txData_t *pTxData = (txData_t*)hTxData; 4404 UINT32 wlanHeaderLength = 0; 4405 EthernetHeader_t *pEthHeader; 4406 UINT16 swapedTypeLength; 4407 4408 4409 /* management frames never have QoS or encryption padding */ 4410 if ( txFlags & TX_DATA_MGMT_MSDU ) 4411 { 4412 return WLAN_HDR_LEN; 4413 } 4414 4415 /* 4416 * Determine 802.11 header length 4417 * QoS Header is longer (2 Bytes) 4418 */ 4419 if ( pTxData->txDataQosParams.headerConverMode == QOS_CONVERT ) 4420 { 4421 wlanHeaderLength = WLAN_QOS_HDR_LEN; 4422 } 4423 else 4424 { 4425 wlanHeaderLength = WLAN_HDR_LEN; 4426 } 4427 4428 if ( txFlags & TX_DATA_EAPOL_MSDU ) 4429 { 4430 /* EAPOLs should always contain SNAP */ 4431 wlanHeaderLength += WLAN_SNAP_HDR_LEN; 4432 /* EAPOL encryption is set by the RSN module */ 4433 if ( TRUE == pTxData->txDataEapolEncryptionStatus ) 4434 { 4435 wlanHeaderLength += pTxData->encryptionFieldSize; 4436 } 4437 return wlanHeaderLength; 4438 } 4439 4440 /* add encryption overhead - 4 bytes for TKIP, 8 for AES. Actual decision was done at RSN */ 4441 if (pTxData->txDataCurrentPrivacyInvokedMode == TRUE) 4442 { 4443 wlanHeaderLength += pTxData->encryptionFieldSize; 4444 } 4445 4446 /* 4447 * IAPP header should always include SNAP, but this is already included in the frame 4448 * body itself, so it is not added here 4449 */ 4450 if ( txFlags & TX_DATA_IAPP_MSDU ) 4451 { 4452 return wlanHeaderLength; 4453 } 4454 4455 /* stat frames are checked if they already contain SNAP header or not */ 4456 if ( txFlags & TX_DATA_DATA_MSDU ) 4457 { 4458 /* 4459 * Detect the packet type and decide if to create a 4460 * new SNAP or leave the original LLC. 4461 */ 4462 pEthHeader = (EthernetHeader_t *)pData; 4463 swapedTypeLength = wlan_htons(pEthHeader->TypeLength); 4464 4465 /* 4466 * if the "type" field is greater than 1500 bytes, it means the frame we received has 4467 * Ethernet II header (destination MAC, source MAC, type, 14 bytes total), and therefore 4468 * we need to reserve 8 more bytes after the 802.11 header for LLC/SNAP header. 4469 * If this field is smaller than or equal to 1500, this is not really a "type" field of 4470 * Ethernet II header, but rather a 802.3 size field. since 802.3 already has 8 bytes 4471 * LLC/SNAP header (other than the 802.3 14 bytes of destination MAC, source MAC and size), 4472 * there is no need to reserve 8 more bytes. 4473 */ 4474 if ( swapedTypeLength > ETHERNET_MAX_PAYLOAD_SIZE ) 4475 { 4476 return wlanHeaderLength + WLAN_SNAP_HDR_LEN; 4477 } 4478 else 4479 { 4480 return wlanHeaderLength; 4481 } 4482 } 4483 else 4484 { 4485 WLAN_REPORT_ERROR( pTxData->hReport, TX_DATA_MODULE_LOG, 4486 (" %s: trying to get header length for packet with txFlags: 0x%x\n", __FUNCTION__, txFlags) ); 4487 return 0; 4488 } 4489 } 4490 4491 /**************************************************************************** 4492 * txDataMsduTimeExpired() 4493 **************************************************************************** 4494 * DESCRIPTION: calculates the time left until MSDU will expire, retunrs the 4495 * time in TUs, or 0 if the MSDU has already expired. 4496 ****************************************************************************/ 4497 UINT32 txDataTimeToMsduExpiry (TI_HANDLE hTxData, mem_MSDU_T* pMsdu, UINT8 qID) 4498 { 4499 txData_t *pTxData = (txData_t*)hTxData; 4500 UINT32 acID, uPassedTime; 4501 4502 /* translate queue ID to AC ID */ 4503 acID = txData_GetAcIdFromQid (hTxData, qID); 4504 4505 /* get time passed since insertion */ 4506 uPassedTime = os_timeStampUs (pTxData->hOs) - pMsdu->insertionTime; 4507 4508 /* if the passed time is smaller than a certain proportion of the MsduLifeTime - it's O.K. */ 4509 if (uPassedTime < 4510 ((pTxData->uFracOfLifeTimeToDrop * pTxData->txDataAcTrfcCtrl[acID].MsduLifeTime) / 100)) 4511 { 4512 return (pTxData->txDataAcTrfcCtrl[acID].MsduLifeTime - uPassedTime) >> 10; 4513 } 4514 4515 /* timer expired, or about to expire --> drop it.*/ 4516 return 0; 4517 } 4518 4519 4520 /**************************************************************************** 4521 * txData_startAfterRecovery * 4522 ***************************************************************************** 4523 * DESCRIPTION: This function start the tx data after recovery. 4524 * It uses params that save before recovery. 4525 * 4526 * INPUTS: hTxData - the object 4527 * 4528 * OUTPUT: 4529 * 4530 * RETURNS: OK - stop succesfull 4531 * NOK - stop unsuccesfull 4532 ****************************************************************************/ 4533 TI_STATUS txData_startAfterRecovery(TI_HANDLE hTxData) 4534 { 4535 txData_t *pTxData = (txData_t *)hTxData; 4536 4537 /* check parameters validity */ 4538 if( pTxData == NULL ) 4539 { 4540 WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG, 4541 (" txData_start() : Illegal value for hTxData\n")); 4542 return NOK; 4543 } 4544 4545 pTxData->txDataPortStatus = pTxData->savePortStatus; 4546 pTxData->txDataCurrentPrivacyInvokedMode = pTxData->saveTxDataCurrentPrivacyInvokedMode; 4547 pTxData->txDataEapolEncryptionStatus = pTxData->saveTxDataEapolEncryptionStatus; 4548 pTxData->encryptionFieldSize = pTxData->saveEncryptionFieldSize; 4549 4550 /* start scheduler timer */ 4551 os_timerStart(pTxData->hOs, pTxData->pSchedulerTimer, SCHEDULER_TIMER, TRUE); 4552 pTxData->bSchedulerTimerRunning = TRUE; 4553 4554 return OK; 4555 } 4556 4557 4558