1/**************************************************************************** 2**+-----------------------------------------------------------------------+** 3**| |** 4**| Copyright(c) 1998 - 2008 Texas Instruments. All rights reserved. |** 5**| All rights reserved. |** 6**| |** 7**| Redistribution and use in source and binary forms, with or without |** 8**| modification, are permitted provided that the following conditions |** 9**| are met: |** 10**| |** 11**| * Redistributions of source code must retain the above copyright |** 12**| notice, this list of conditions and the following disclaimer. |** 13**| * Redistributions in binary form must reproduce the above copyright |** 14**| notice, this list of conditions and the following disclaimer in |** 15**| the documentation and/or other materials provided with the |** 16**| distribution. |** 17**| * Neither the name Texas Instruments nor the names of its |** 18**| contributors may be used to endorse or promote products derived |** 19**| from this software without specific prior written permission. |** 20**| |** 21**| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |** 22**| "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |** 23**| LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |** 24**| A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |** 25**| OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |** 26**| SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |** 27**| LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |** 28**| DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |** 29**| THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |** 30**| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |** 31**| OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |** 32**| |** 33**+-----------------------------------------------------------------------+** 34****************************************************************************/ 35 36/**************************************************************************** 37 * 38 * MODULE: txHwQueue.c 39 * 40 * PURPOSE: manage the wlan hardware Tx memory blocks allocation per queue. 41 * 42 * DESCRIPTION: 43 * ============ 44 * This module is responsible for the HW Tx resources allocation (except 45 * the HW double buffer). 46 * The HW Tx resources are allocated and freed in the driver by pure 47 * calculations without accessing the FW. This is done by tracking the 48 * resources allocation and freeing, and checking against thresholds before 49 * each allocation. 50 ****************************************************************************/ 51 52#ifdef _WINDOWS 53#endif 54 55#include "whalCommon.h" 56#include "whalHwDefs.h" 57#include "whalCtrl_api.h" 58#include "whalParams.h" 59#include "txCtrlBlk_api.h" 60#include "txHwQueue_api.h" 61 62#include "txHwQueue.h" /* Local definitions */ 63 64 65 66 67 68/**************************************************************************** 69 * txHwQueue_Create() 70 **************************************************************************** 71 * DESCRIPTION: Create the Tx buffers pool object 72 * 73 * INPUTS: None 74 * 75 * OUTPUT: None 76 * 77 * RETURNS: The Created object 78 ****************************************************************************/ 79TI_HANDLE txHwQueue_Create(TI_HANDLE hOs) 80{ 81 TxHwQueueObj_t *pTxHwQueue; 82 83 pTxHwQueue = os_memoryAlloc(hOs, sizeof(TxHwQueueObj_t)); 84 if (pTxHwQueue == NULL) 85 return NULL; 86 87 os_memoryZero(hOs, pTxHwQueue, sizeof(TxHwQueueObj_t)); 88 89 pTxHwQueue->hOs = hOs; 90 91 return( (TI_HANDLE)pTxHwQueue ); 92} 93 94/**************************************************************************** 95 * txHwQueue_Destroy() 96 **************************************************************************** 97 * DESCRIPTION: Destroy the Tx buffers pool object 98 * 99 * INPUTS: hTxHwQueue - The object to free 100 * 101 * OUTPUT: None 102 * 103 * RETURNS: OK or NOK 104 ****************************************************************************/ 105TI_STATUS txHwQueue_Destroy(TI_HANDLE hTxHwQueue) 106{ 107 TxHwQueueObj_t *pTxHwQueue = (TxHwQueueObj_t *)hTxHwQueue; 108 109 if (pTxHwQueue) 110 os_memoryFree(pTxHwQueue->hOs, pTxHwQueue, sizeof(TxHwQueueObj_t)); 111 112 return OK; 113} 114 115 116 117 118/**************************************************************************** 119 * txHwQueue_init() 120 **************************************************************************** 121 122 DESCRIPTION: Initialize module handles. 123 124 ****************************************************************************/ 125TI_STATUS txHwQueue_init(TI_HANDLE hTxHwQueue, TI_HANDLE hReport, TI_HANDLE hWhalParams) 126{ 127 TxHwQueueObj_t *pTxHwQueue = (TxHwQueueObj_t *)hTxHwQueue; 128 129 pTxHwQueue->hReport = hReport; 130 pTxHwQueue->pWhalParams = (WhalParams_T *)hWhalParams; 131 132 return OK; 133} 134 135/**************************************************************************** 136 * txHwQueue_Config() 137 **************************************************************************** 138 * DESCRIPTION: Configure the Tx buffers pool object 139 * 140 * INPUTS: None 141 * 142 * OUTPUT: None 143 * 144 * RETURNS: 145 ****************************************************************************/ 146TI_STATUS txHwQueue_Config(TI_HANDLE hTxHwQueue, TnetwDrv_InitParams_t *pInitParams) 147{ 148 UINT8 acID; 149 150 /* Configure queue parameters to Tx-HW queue module */ 151 for(acID = 0 ; acID < MAX_NUM_OF_AC ; acID++) 152 { 153 txHwQueue_configQueue( hTxHwQueue, 154 acID, 155 pInitParams->whalCtrl_init.TxBlocksLowPercentPerAc[acID], 156 pInitParams->whalCtrl_init.TxBlocksHighPercentPerAc[acID]); 157 } 158 159 return OK; 160} 161 162 163/**************************************************************************** 164 * txHwQueue_setHwInfo() 165 **************************************************************************** 166 167 DESCRIPTION: 168 169 Called after the HW configuration in the driver init or recovery process. 170 Configure Tx HW information, including Tx-HW-blocks number, and per queue 171 Tx-descriptors number. Than, restart the module variables. 172 173 ****************************************************************************/ 174TI_STATUS txHwQueue_setHwInfo(TI_HANDLE hTxHwQueue, DmaParams_T *pDmaParams) 175{ 176 TxHwQueueObj_t *pTxHwQueue = (TxHwQueueObj_t *)hTxHwQueue; 177 int TxQid; 178 179 pTxHwQueue->NumBlocks = pDmaParams->NumTxBlocks - 1; /* One block must be always free for FW use. */ 180 181 /* Get the Tx descriptors number per queue. */ 182 for(TxQid = 0; TxQid < MAX_NUM_OF_TX_QUEUES ; TxQid++) 183 pTxHwQueue->TxHwQueueInfo[TxQid].numDescriptors = pDmaParams->TxNumDesc[TxQid]; 184 185 /* Restart the module variables. */ 186 txHwQueue_restart(hTxHwQueue); 187 188 return OK; 189} 190 191 192 193 194/**************************************************************************** 195 * txHwQueue_configQueue() 196 **************************************************************************** 197 DESCRIPTION: 198 199 Configure Tx HW queue blocks accounting parameters used in the allocate and free 200 procedures in this module. 201 202 Two thresholds are defined per queue: 203 a) TxBlocksLowPercentPerQueue[queue] - The lower threshold is the minimal number of 204 Tx blocks guaranteed for each queue. 205 The sum of all low thresholds should be less than 100%. 206 b) TxBlocksHighPercentPerQueue[queue] - The higher threshold is the maximal number of 207 Tx blocks that may be allocated to the queue. 208 The extra blocks above the low threshold can be allocated when needed only 209 if they are currently available and are not needed in order to guarantee 210 the other queues low threshold. 211 The sum of all high thresholds should be more than 100%. 212 213 ****************************************************************************/ 214TI_STATUS txHwQueue_configQueue(TI_HANDLE hTxHwQueue, UINT8 TxQid, 215 UINT16 percentOfBlockLowThreshold, UINT16 percentOfBlockHighThreshold) 216{ 217 TxHwQueueObj_t *pTxHwQueue = (TxHwQueueObj_t *)hTxHwQueue; 218 txHwQueueInfo_t *pQueueInfo = &(pTxHwQueue->TxHwQueueInfo[TxQid]); 219 220 /* Calculate queue's blocks high threshold: maximum number that may be allocated to it. */ 221 pQueueInfo->numBlocksHighThreshold = percentOfBlockHighThreshold * pTxHwQueue->NumBlocks / 100; 222 223 /* Calculate queue's blocks low threshold: minimum number that must be reserved for it. */ 224 pQueueInfo->numBlocksLowThreshold = percentOfBlockLowThreshold * pTxHwQueue->NumBlocks / 100; 225 226 /* Set the threshold for low block resources: when the next packet may not have enough blocks. */ 227 if (pQueueInfo->numBlocksLowThreshold > MAX_BLKS_PER_PKT) 228 pQueueInfo->lowResourceThresh = pQueueInfo->numBlocksLowThreshold - MAX_BLKS_PER_PKT; 229 else 230 pQueueInfo->lowResourceThresh = 0; 231 232 pQueueInfo->numBlocksUsed = 0; 233 pQueueInfo->numPackets = 0; 234 235 /* Since no blocks are used yet, reserved blocks number equals to the low threshold. */ 236 pQueueInfo->numBlocksReserved = pQueueInfo->numBlocksLowThreshold; 237 238 /* Accumulate total reserved blocks. */ 239 pTxHwQueue->TotalBlocksReserved += pQueueInfo->numBlocksReserved; 240 241 WLAN_REPORT_INIT(pTxHwQueue->hReport, TX_HW_QUEUE_MODULE_LOG, 242 ("txHwQueue_configQueue(): HighThresh=%d, LowThresh=%d, LowRsrcThresh=%d, TotalReserved=%d\n", 243 pQueueInfo->numBlocksHighThreshold, pQueueInfo->numBlocksLowThreshold, 244 pQueueInfo->lowResourceThresh, pTxHwQueue->TotalBlocksReserved)); 245 246 return OK; 247} 248 249 250 251 252/**************************************************************************** 253 * txHwQueue_restart() 254 **************************************************************************** 255 DESCRIPTION: 256 ============ 257 Restarts the Tx-HW-Queue module. 258 Should be called upon disconnect and recovery!! 259 ****************************************************************************/ 260TI_STATUS txHwQueue_restart(TI_HANDLE hTxHwQueue) 261{ 262 TxHwQueueObj_t *pTxHwQueue = (TxHwQueueObj_t *)hTxHwQueue; 263 txHwQueueInfo_t *pQueueInfo; 264 int TxQid; 265 266 /* All blocks are free at restart. 267 Note that free means all blocks that are currently not in use, 268 while reserved are a part of the free blocks that are the summary of all queues reserved blocks. 269 Each queue may take from the reserved part only up to its own reservation (according to 270 its low threshold). */ 271 272 pTxHwQueue->NumFree = pTxHwQueue->NumBlocks; 273 pTxHwQueue->TotalBlocksReserved = 0; 274 275 for(TxQid = 0; TxQid < MAX_NUM_OF_TX_QUEUES ; TxQid++) 276 { 277 pQueueInfo = &(pTxHwQueue->TxHwQueueInfo[TxQid]); 278 pQueueInfo->numBlocksUsed = 0; 279 pQueueInfo->numPackets = 0; 280 281 /* Since no blocks are used yet, reserved blocks number equals to the low threshold. */ 282 pQueueInfo->numBlocksReserved = pQueueInfo->numBlocksLowThreshold; 283 284 /* Accumulate total reserved blocks. */ 285 pTxHwQueue->TotalBlocksReserved += pQueueInfo->numBlocksReserved; 286 } 287 288 return OK; 289} 290 291 292 293 294/**************************************************************************** 295 * txHwQueue_alloc() 296 **************************************************************************** 297 * DESCRIPTION: 298 ============ 299 If the required blocks are available for the queue and there is an available 300 descriptor, update the blocks and descriptor allocation and return OK. 301 Else, return NOK. 302 If the queue's reaources (blocks) are low, indicate in the descriptor to get 303 Tx-complete from FW immediately. 304 ****************************************************************************/ 305TI_STATUS txHwQueue_alloc(TI_HANDLE hTxHwQueue, txCtrlBlkEntry_t *pPktCtrlBlk) 306{ 307 TxHwQueueObj_t *pTxHwQueue = (TxHwQueueObj_t *)hTxHwQueue; 308 UINT8 numBlksToAlloc; /* The number of blocks required for the current packet. */ 309 UINT8 maxAllowed; /* Max blocks that may be currently allocated to this Queue to obey the high threshold.*/ 310 UINT8 maxAvailable; /* Max blocks that are currently free and not reserved for other Queues. */ 311 UINT8 reserved; /* How many blocks are reserved to this Queue before this allocation. */ 312 txHwQueueInfo_t *pQueueInfo = &(pTxHwQueue->TxHwQueueInfo[pPktCtrlBlk->txDescriptor.xmitQueue]); 313 314 315 /***********************************************************************/ 316 /* Calculate packet fragmentation threshold and required HW blocks. */ 317 /***********************************************************************/ 318 319 txHwQueueCalc_BlocksNum(hTxHwQueue, pPktCtrlBlk); 320 321 322 /***********************************************************************/ 323 /* Check if the required resources are available */ 324 /***********************************************************************/ 325 326 /* If all queue's descriptors are occupied, return BUSY. */ 327 if (pQueueInfo->numPackets == pQueueInfo->numDescriptors) 328 { 329 WLAN_REPORT_INFORMATION(pTxHwQueue->hReport, TX_HW_QUEUE_MODULE_LOG, 330 ("txHwQueue_alloc(): No Descriptors, Queue=%d, Descriptors=%d, Packets=%d\n", 331 pPktCtrlBlk->txDescriptor.xmitQueue, pQueueInfo->numDescriptors, pQueueInfo->numPackets)); 332 return NOK; 333 } 334 335 reserved = pQueueInfo->numBlocksReserved; 336 numBlksToAlloc = pPktCtrlBlk->txDescriptor.numMemBlks; 337 338 /* Calculate how far we are from this Queue's high threshold limit (allowed = highThresh - used). */ 339 maxAllowed = pQueueInfo->numBlocksHighThreshold - pQueueInfo->numBlocksUsed; 340 341 /* Calculate how many buffers are available for this Queue: the total free buffers minus the buffers 342 that are reserved for other Queues (all reserved minus this Queue's reserved). */ 343 maxAvailable = pTxHwQueue->NumFree - (pTxHwQueue->TotalBlocksReserved - reserved); 344 345 /* If we need more blocks than are allowed or available, return BUSY. */ 346 if (numBlksToAlloc > min(maxAllowed, maxAvailable)) 347 { 348 WLAN_REPORT_INFORMATION(pTxHwQueue->hReport, TX_HW_QUEUE_MODULE_LOG, 349 ("txHwQueue_alloc(): No Hw-Blocks, Queue=%d, Req-blks=%d , Free=%d, Used=%d, available=%d\n", 350 pPktCtrlBlk->txDescriptor.xmitQueue, numBlksToAlloc, pTxHwQueue->NumFree, pQueueInfo->numBlocksUsed, maxAvailable)); 351 return NOK; 352 } 353 354 /***********************************************************************/ 355 /* Allocate required resources */ 356 /***********************************************************************/ 357 358 /* Update number of packets in FW (for descriptors allocation check). */ 359 pQueueInfo->numPackets++; 360 361 362 /* If we are currently using less than the low threshold (i.e. we have some reserved blocks), 363 blocks allocation should reduce the reserved blocks number as follows: 364 */ 365 if (reserved) 366 { 367 368 /* If adding the allocated blocks to the used blocks will pass the low-threshold, 369 only the part up to the low-threshold is subtracted from the reserved blocks. 370 This is because blocks are reserved for the Queue only up to its low-threshold. 371 372 0 old used low new used high 373 |######| | | | 374 |######| | | | 375 <------------ allocated -----------> 376 <----- old reserved ----> 377 new reserved = 0 (we passed the low threshold) 378 */ 379 if (numBlksToAlloc > reserved) 380 { 381 pQueueInfo->numBlocksReserved = 0; 382 pTxHwQueue->TotalBlocksReserved -= reserved; /* reduce change from total reserved.*/ 383 } 384 385 386 /* Else, if allocating less than reserved, 387 the allocated blocks are subtracted from the reserved blocks: 388 389 0 old used new used low high 390 |######| | | | 391 |######| | | | 392 <- allocated -> 393 <--------- old reserved ----------> 394 <-- new reserved --> 395 */ 396 else 397 { 398 pQueueInfo->numBlocksReserved -= numBlksToAlloc; 399 pTxHwQueue->TotalBlocksReserved -= numBlksToAlloc; /* reduce change from total reserved.*/ 400 } 401 } 402 403 404 /* Update total free blocks and Queue used blocks with the allocated blocks number. */ 405 pTxHwQueue->NumFree -= numBlksToAlloc; 406 pQueueInfo->numBlocksUsed += numBlksToAlloc; 407 408 /* If this queue has low resources (blocks or descriptors), set descriptor flag to get Tx-Complete from FW. */ 409 if ( (pQueueInfo->numBlocksUsed > pQueueInfo->lowResourceThresh) || 410 (pQueueInfo->numPackets == pQueueInfo->numDescriptors - 1) ) 411 { 412 #ifdef _WINDOWS 413 #else 414 pPktCtrlBlk->txDescriptor.txAttr |= TX_COMPLETE_REQUIRED_BIT; 415 #endif 416 } 417 418 WLAN_REPORT_INFORMATION(pTxHwQueue->hReport, TX_HW_QUEUE_MODULE_LOG, 419 ("txHwQueue_alloc(): SUCCESS, Queue=%d, Req-blks=%d , Free=%d, Used=%d, LowResources=%d\n", 420 pPktCtrlBlk->txDescriptor.xmitQueue, numBlksToAlloc, pTxHwQueue->NumFree, 421 pQueueInfo->numBlocksUsed, (pQueueInfo->numBlocksUsed > pQueueInfo->lowResourceThresh))); 422 423 return OK; 424} 425 426 427 428 429/**************************************************************************** 430 * txHwQueue_free() 431 **************************************************************************** 432 * DESCRIPTION: Decrement the number of used descriptors and used data blks 433 for the specific queue. 434 ****************************************************************************/ 435TI_STATUS txHwQueue_free(TI_HANDLE hTxHwQueue, txCtrlBlkEntry_t *pPktCtrlBlk) 436{ 437 TxHwQueueObj_t *pTxHwQueue = (TxHwQueueObj_t *)hTxHwQueue; 438 UINT8 numBlksToFree; /* The number of blocks freed by the current packet. */ 439 UINT8 lowThreshold; /* Minimum blocks that are guaranteed for this Queue. */ 440 UINT8 newUsed; /* Blocks that are used by this Queue after freeing these blocks. */ 441 UINT8 newReserved; /* How many blocks are reserved to this Queue after freeing. */ 442 txHwQueueInfo_t *pQueueInfo = &(pTxHwQueue->TxHwQueueInfo[pPktCtrlBlk->txDescriptor.xmitQueue]); 443 444 numBlksToFree = pPktCtrlBlk->txDescriptor.numMemBlks; 445 446 /* Update number of packets in FW (for descriptors allocation check). */ 447 pQueueInfo->numPackets--; 448 449#ifdef TI_DBG /* Debug Counters */ 450 /* Sanity check: make sure we don't free more blocks than are in use. */ 451 if (numBlksToFree > pQueueInfo->numBlocksUsed) 452 { 453 WLAN_REPORT_ERROR(pTxHwQueue->hReport, TX_HW_QUEUE_MODULE_LOG, 454 ("txHwQueue_free(): Try to free more blks than used: Queue %d, free %d, used %d\n", 455 pPktCtrlBlk->txDescriptor.xmitQueue, numBlksToFree, pQueueInfo->numBlocksUsed)); 456 return NOK; 457 } 458#endif 459 460 /* Update total free blocks and Queue used blocks with the freed blocks number. */ 461 pTxHwQueue->NumFree += numBlksToFree; 462 pQueueInfo->numBlocksUsed -= numBlksToFree; 463 464 465 lowThreshold = pQueueInfo->numBlocksLowThreshold; 466 newUsed = pQueueInfo->numBlocksUsed; 467 468 469 /* If after freeing the blocks we are using less than the low threshold, 470 update total reserved blocks number as follows: 471 (note: if we are above the low threshold after freeing the blocks we still have no reservation.) 472 */ 473 if (newUsed < lowThreshold) 474 { 475 newReserved = lowThreshold - newUsed; 476 pQueueInfo->numBlocksReserved = newReserved; 477 478 479 /* If freeing the blocks reduces the used blocks from above to below the low-threshold, 480 only the part from the low-threshold to the new used number is added to the 481 reserved blocks (because blocks are reserved for the Queue only up to its low-threshold): 482 483 0 new used low old used high 484 |###########|####################|################| | 485 |###########|####################|################| | 486 <-------------- freed --------------> 487 <-- new reserved --> 488 old reserved = 0 489 */ 490 if (numBlksToFree > newReserved) 491 pTxHwQueue->TotalBlocksReserved += newReserved; /* Add change to total reserved.*/ 492 493 494 /* Else, if we were under the low-threshold before freeing these blocks, 495 all freed blocks are added to the reserved blocks: 496 497 0 new used old used low high 498 |################|#################| | | 499 |################|#################| | | 500 <---- freed ----> 501 <- old reserved -> 502 <---------- new reserved ----------> 503 */ 504 else 505 pTxHwQueue->TotalBlocksReserved += numBlksToFree; /* Add change to total reserved.*/ 506 } 507 508 return OK; 509} 510 511 512 513 514/**************************************************************************** 515 * txHwQueue_GetUsedHwBlks() 516 **************************************************************************** 517 * DESCRIPTION: Provide the number of used HW Tx blocks of the given Queue. 518 ****************************************************************************/ 519UINT8 txHwQueue_GetUsedHwBlks(TI_HANDLE hTxHwQueue, int TxQid) 520{ 521 TxHwQueueObj_t *pTxHwQueue = (TxHwQueueObj_t *)hTxHwQueue; 522 return (pTxHwQueue->TxHwQueueInfo[TxQid].numBlocksUsed); 523} 524 525 526 527 528/**************************************************************************** 529 * txHwQueue_printInfo() 530 **************************************************************************** 531 * DESCRIPTION: Print the Hw Queue current information 532 ****************************************************************************/ 533void txHwQueue_printInfo(TI_HANDLE hTxHwQueue) 534{ 535#ifdef TI_DBG 536 TxHwQueueObj_t *pTxHwQueue = (TxHwQueueObj_t *)hTxHwQueue; 537 int TxQid; 538 539 /* Print the Tx-HW-Queue information: */ 540 WLAN_OS_REPORT(("Hw-Queues Information:\n")); 541 WLAN_OS_REPORT(("======================\n")); 542 WLAN_OS_REPORT(("Total Blocks: %d\n", pTxHwQueue->NumBlocks)); 543 WLAN_OS_REPORT(("Total Free Blocks: %d\n", pTxHwQueue->NumFree)); 544 WLAN_OS_REPORT(("Total Reserved Blocks: %d\n\n", pTxHwQueue->TotalBlocksReserved)); 545 546 for(TxQid = 0; TxQid < MAX_NUM_OF_TX_QUEUES; TxQid++) 547 { 548 WLAN_OS_REPORT(("Queue %d: Used=%d, Reserved=%d, LowThresh=%d, HighThresh=%d, LowRsrcThresh=%d, NumDesc=%d, UsedDesc=%d\n", 549 TxQid, 550 pTxHwQueue->TxHwQueueInfo[TxQid].numBlocksUsed, 551 pTxHwQueue->TxHwQueueInfo[TxQid].numBlocksReserved, 552 pTxHwQueue->TxHwQueueInfo[TxQid].numBlocksLowThreshold, 553 pTxHwQueue->TxHwQueueInfo[TxQid].numBlocksHighThreshold, 554 pTxHwQueue->TxHwQueueInfo[TxQid].lowResourceThresh, 555 pTxHwQueue->TxHwQueueInfo[TxQid].numDescriptors, 556 pTxHwQueue->TxHwQueueInfo[TxQid].numPackets)); 557 } 558#endif /* TI_DBG */ 559} 560 561