Home | History | Annotate | Download | only in Tx_HW_Queue
      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  ****************************************************************************/
     79 TI_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  ****************************************************************************/
    105 TI_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  ****************************************************************************/
    125 TI_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  ****************************************************************************/
    146 TI_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  ****************************************************************************/
    174 TI_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  ****************************************************************************/
    214 TI_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  ****************************************************************************/
    260 TI_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  ****************************************************************************/
    305 TI_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  ****************************************************************************/
    435 TI_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  ****************************************************************************/
    519 UINT8 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  ****************************************************************************/
    533 void 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