Home | History | Annotate | Download | only in Data_link
      1 /*
      2  * txDataQueue.c
      3  *
      4  * Copyright(c) 1998 - 2009 Texas Instruments. All rights reserved.
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  *
     11  *  * Redistributions of source code must retain the above copyright
     12  *    notice, this list of conditions and the following disclaimer.
     13  *  * Redistributions in binary form must reproduce the above copyright
     14  *    notice, this list of conditions and the following disclaimer in
     15  *    the documentation and/or other materials provided with the
     16  *    distribution.
     17  *  * Neither the name Texas Instruments nor the names of its
     18  *    contributors may be used to endorse or promote products derived
     19  *    from this software without specific prior written permission.
     20  *
     21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     24  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     25  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     26  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     27  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     28  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     29  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     30  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     31  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     32  */
     33 
     34 
     35 /** \file   txDataQueue.c
     36  *  \brief  The Tx Data Queues module.
     37  *
     38  *  \see    txDataQueue.h
     39  */
     40 
     41 
     42 #define __FILE_ID__  FILE_ID_60
     43 #include "paramOut.h"
     44 #include "osApi.h"
     45 #include "report.h"
     46 #include "queue.h"
     47 #include "context.h"
     48 #include "Ethernet.h"
     49 #include "TWDriver.h"
     50 #include "DataCtrl_Api.h"
     51 #include "txDataQueue.h"
     52 #include "DrvMainModules.h"
     53 #include "bmtrace_api.h"
     54 
     55 
     56 /* Internal Functions prototypes */
     57 static void txDataQ_RunScheduler (TI_HANDLE hTxDataQ);
     58 static void txDataQ_UpdateQueuesBusyState (TTxDataQ *pTxDataQ, TI_UINT32 uTidBitMap);
     59 
     60 
     61 /***************************************************************************
     62 *                      PUBLIC  FUNCTIONS  IMPLEMENTATION				   *
     63 ****************************************************************************/
     64 
     65 
     66 /**
     67  * \fn     txDataQ_Create
     68  * \brief  Create the module and its queues
     69  *
     70  * Create the Tx Data module and its queues.
     71  *
     72  * \note
     73  * \param  hOs - Handle to the Os Abstraction Layer
     74  * \return Handle to the allocated Tx Data Queue module (NULL if failed)
     75  * \sa
     76  */
     77 TI_HANDLE txDataQ_Create(TI_HANDLE hOs)
     78 {
     79     TTxDataQ *pTxDataQ;
     80 
     81     /* allocate TxDataQueue module */
     82     pTxDataQ = os_memoryAlloc (hOs, (sizeof(TTxDataQ)));
     83 
     84     if (!pTxDataQ)
     85 	{
     86         WLAN_OS_REPORT(("Error allocating the TxDataQueue Module\n"));
     87 		return NULL;
     88 	}
     89 
     90     /* Reset TxDataQueue module */
     91     os_memoryZero (hOs, pTxDataQ, (sizeof(TTxDataQ)));
     92 
     93     return (TI_HANDLE)pTxDataQ;
     94 }
     95 
     96 
     97 /**
     98  * \fn     txDataQ_Init
     99  * \brief  Save required modules handles
    100  *
    101  * Save other modules handles.
    102  *
    103  * \note
    104  * \param  pStadHandles  - The driver modules handles
    105  * \return void
    106  * \sa
    107  */
    108 void txDataQ_Init (TStadHandlesList *pStadHandles)
    109 {
    110     TTxDataQ  *pTxDataQ = (TTxDataQ *)(pStadHandles->hTxDataQ);
    111     TI_UINT32  uNodeHeaderOffset = TI_FIELD_OFFSET(TTxnStruct, tTxnQNode);
    112     TI_UINT8   uQueId;
    113 
    114     /* save modules handles */
    115     pTxDataQ->hContext	= pStadHandles->hContext;
    116     pTxDataQ->hTxCtrl	= pStadHandles->hTxCtrl;
    117     pTxDataQ->hOs		= pStadHandles->hOs;
    118     pTxDataQ->hReport	= pStadHandles->hReport;
    119     pTxDataQ->hTxMgmtQ	= pStadHandles->hTxMgmtQ;
    120 
    121     /* Configures the Port Default status to Close */
    122 	pTxDataQ->bDataPortEnable = TI_FALSE;
    123 
    124 	/* Configures the LastQueId to zero => scheduler will strart from Queue 1*/
    125 	pTxDataQ->uLastQueId = 0;
    126 
    127 	/* init the number of the Data queue to be used */
    128 	pTxDataQ->uNumQueues = MAX_NUM_OF_AC;
    129 
    130 	/* init the max size of the Data queues */
    131 	pTxDataQ->aQueueMaxSize[QOS_AC_BE] = DATA_QUEUE_DEPTH_BE;
    132 	pTxDataQ->aQueueMaxSize[QOS_AC_BK] = DATA_QUEUE_DEPTH_BK;
    133 	pTxDataQ->aQueueMaxSize[QOS_AC_VI] = DATA_QUEUE_DEPTH_VI;
    134 	pTxDataQ->aQueueMaxSize[QOS_AC_VO] = DATA_QUEUE_DEPTH_VO;
    135 
    136     /* Create the tx data queues */
    137 	for (uQueId = 0; uQueId < pTxDataQ->uNumQueues; uQueId++)
    138     {
    139         pTxDataQ->aQueues[uQueId] = que_Create (pTxDataQ->hOs,
    140                                                 pTxDataQ->hReport,
    141                                                 pTxDataQ->aQueueMaxSize[uQueId],
    142                                                 uNodeHeaderOffset);
    143 
    144 		/* If any Queues' allocation failed, print error, free TxDataQueue module and exit */
    145 		if (pTxDataQ->aQueues[uQueId] == NULL)
    146 		{
    147             TRACE0(pTxDataQ->hReport, REPORT_SEVERITY_CONSOLE , "Failed to create queue\n");
    148 			WLAN_OS_REPORT(("Failed to create queue\n"));
    149 			os_memoryFree (pTxDataQ->hOs, pTxDataQ, sizeof(TTxDataQ));
    150 			return;
    151 		}
    152 
    153 		/* Configure the Queue default Mode to Open (not busy)*/
    154 		pTxDataQ->aQueueBusy[uQueId] = TI_FALSE;
    155     }
    156 
    157     /* Register to the context engine and get the client ID */
    158     pTxDataQ->uContextId = context_RegisterClient (pTxDataQ->hContext,
    159                                                    txDataQ_RunScheduler,
    160                                                    (TI_HANDLE)pTxDataQ,
    161                                                    TI_TRUE,
    162                                                    "TX_DATA",
    163                                                    sizeof("TX_DATA"));
    164 }
    165 
    166 
    167 /**
    168  * \fn     txDataQ_SetDefaults
    169  * \brief  Configure module with default settings
    170  *
    171  * Init the Tx Data queues.
    172  * Register as the context-engine client.
    173  *
    174  * \note
    175  * \param  hTxDataQ - The object
    176  * \param  Other modules handles
    177  * \return TI_OK on success or TI_NOK on failure
    178  * \sa
    179  */
    180 TI_STATUS txDataQ_SetDefaults (TI_HANDLE  hTxDataQ, txDataInitParams_t *pTxDataInitParams)
    181 {
    182     TTxDataQ  *pTxDataQ = (TTxDataQ *)hTxDataQ;
    183 	TI_STATUS  eStatus;
    184 
    185     /* configure the classifier sub-module */
    186     eStatus = txDataClsfr_Config (hTxDataQ, &pTxDataInitParams->ClsfrInitParam);
    187     if (eStatus != TI_OK)
    188     {
    189         TRACE0(pTxDataQ->hReport, REPORT_SEVERITY_CONSOLE ,"FATAL ERROR: txDataQ_SetDefaults(): txDataClsfr_Config failed - Aborting\n");
    190         WLAN_OS_REPORT(("FATAL ERROR: txDataQ_SetDefaults(): txDataClsfr_Config failed - Aborting\n"));
    191         return eStatus;
    192     }
    193 
    194 TRACE0(pTxDataQ->hReport, REPORT_SEVERITY_INIT, ".....Tx Data Queue configured successfully\n");
    195 
    196     return TI_OK;
    197 }
    198 
    199 
    200 /**
    201  * \fn     txDataQ_Destroy
    202  * \brief  Destroy the module and its queues
    203  *
    204  * Clear and destroy the queues and then destroy the module object.
    205  *
    206  * \note
    207  * \param  hTxDataQ - The object
    208  * \return TI_OK - Unload succesfull, TI_NOK - Unload unsuccesfull
    209  * \sa
    210  */
    211 TI_STATUS txDataQ_Destroy (TI_HANDLE hTxDataQ)
    212 {
    213     TTxDataQ  *pTxDataQ = (TTxDataQ *)hTxDataQ;
    214     TI_STATUS  status = TI_OK;
    215     TI_UINT32  uQueId;
    216 
    217     /* Dequeue and free all queued packets */
    218     txDataQ_ClearQueues (hTxDataQ);
    219 
    220     /* Free Data queues */
    221     for (uQueId = 0 ; uQueId < pTxDataQ->uNumQueues ; uQueId++)
    222     {
    223         if (que_Destroy(pTxDataQ->aQueues[uQueId]) != TI_OK)
    224 		{
    225             TRACE1(pTxDataQ->hReport, REPORT_SEVERITY_ERROR, "txDataQueue_unLoad: fail to free Data Queue number: %d\n",uQueId);
    226 			status = TI_NOK;
    227 		}
    228     }
    229 
    230     /* Free Tx Data Queue Module */
    231     os_memoryFree (pTxDataQ->hOs, pTxDataQ, sizeof(TTxDataQ));
    232 
    233     return status;
    234 }
    235 
    236 
    237 /**
    238  * \fn     txDataQ_ClearQueues
    239  * \brief  Clear all queues
    240  *
    241  * Dequeue and free all queued packets.
    242  *
    243  * \note
    244  * \param  hTxDataQ - The object
    245  * \return void
    246  * \sa
    247  */
    248 void txDataQ_ClearQueues (TI_HANDLE hTxDataQ)
    249 {
    250     TTxDataQ   *pTxDataQ = (TTxDataQ *)hTxDataQ;
    251     TTxCtrlBlk *pPktCtrlBlk;
    252     TI_UINT32  uQueId;
    253 
    254     /* Dequeue and free all queued packets */
    255     for (uQueId = 0 ; uQueId < pTxDataQ->uNumQueues ; uQueId++)
    256     {
    257         do {
    258             context_EnterCriticalSection (pTxDataQ->hContext);
    259             pPktCtrlBlk = (TTxCtrlBlk *) que_Dequeue(pTxDataQ->aQueues[uQueId]);
    260             context_LeaveCriticalSection (pTxDataQ->hContext);
    261             if (pPktCtrlBlk != NULL) {
    262                 txCtrl_FreePacket (pTxDataQ->hTxCtrl, pPktCtrlBlk, TI_NOK);
    263             }
    264         } while (pPktCtrlBlk != NULL);
    265     }
    266 }
    267 
    268 
    269 /**
    270  * \fn     txDataQ_InsertPacket
    271  * \brief  Insert packet in queue and schedule task
    272  *
    273  * This function is called by the hard_start_xmit() callback function.
    274  * If the packet it an EAPOL, forward it to the Mgmt-Queue.
    275  * Otherwise, classify the packet, enqueue it and request
    276  *   context switch for handling it in the driver's context.
    277  *
    278  * \note
    279  * \param  hTxDataQ    - The object
    280  * \param  pPktCtrlBlk - Pointer to the packet
    281  * \param  uPacketDtag - The packet priority optionaly set by the OAL
    282  * \return TI_OK - if the packet was queued, TI_NOK - if the packet was dropped.
    283  * \sa     txDataQ_Run
    284  */
    285 TI_STATUS txDataQ_InsertPacket (TI_HANDLE hTxDataQ, TTxCtrlBlk *pPktCtrlBlk, TI_UINT8 uPacketDtag)
    286 {
    287     TTxDataQ        *pTxDataQ = (TTxDataQ *)hTxDataQ;
    288 	TEthernetHeader *pEthHead = (TEthernetHeader *)(pPktCtrlBlk->tTxnStruct.aBuf[0]);
    289 	TI_STATUS        eStatus;
    290     TI_UINT32        uQueId;
    291     TI_UINT32        uQueSize;
    292 	CL_TRACE_START_L3();
    293 
    294     /* If packet is EAPOL, forward it to the Mgmt-Queue and exit */
    295     if (HTOWLANS(pEthHead->type) == ETHERTYPE_EAPOL)
    296     {
    297 		pPktCtrlBlk->tTxPktParams.uPktType = TX_PKT_TYPE_EAPOL;
    298 
    299         return txMgmtQ_Xmit (pTxDataQ->hTxMgmtQ, pPktCtrlBlk, TI_TRUE);
    300         /* Note: The last parameter indicates that we are running in external context */
    301     }
    302 
    303     pPktCtrlBlk->tTxPktParams.uPktType = TX_PKT_TYPE_ETHER;
    304 
    305     /* Enter critical section to protect classifier data and queue access */
    306     context_EnterCriticalSection (pTxDataQ->hContext);
    307 
    308 	/* Call the Classify function to set the TID field */
    309 	if (txDataClsfr_ClassifyTxPacket (hTxDataQ, pPktCtrlBlk, uPacketDtag) != TI_OK)
    310 	{
    311 #ifdef TI_DBG
    312 		pTxDataQ->uClsfrMismatchCount++;
    313 TRACE0(pTxDataQ->hReport, REPORT_SEVERITY_WARNING, "txDataQueue_xmit: No matching classifier found \n");
    314 #endif /* TI_DBG */
    315 	}
    316 
    317 	/* Enqueue the packet in the appropriate Queue */
    318     uQueId = aTidToQueueTable[pPktCtrlBlk->tTxDescriptor.tid];
    319     eStatus = que_Enqueue (pTxDataQ->aQueues[uQueId], (TI_HANDLE)pPktCtrlBlk);
    320 
    321     /* Get number of packets in current queue */
    322     uQueSize = que_Size (pTxDataQ->aQueues[uQueId]);
    323 
    324     /* Leave critical section */
    325     context_LeaveCriticalSection (pTxDataQ->hContext);
    326 
    327     /* If the queue was empty, request switch to driver context for handling queued packet(s) */
    328     if (uQueSize == 1)
    329     {
    330         context_RequestSchedule (pTxDataQ->hContext, pTxDataQ->uContextId);
    331     }
    332 
    333 	if (eStatus != TI_OK)
    334     {
    335         /* If the packet can't be queued drop it */
    336         txCtrl_FreePacket (pTxDataQ->hTxCtrl, pPktCtrlBlk, TI_NOK);
    337       #ifdef TI_DBG
    338 		pTxDataQ->aQueueCounters[uQueId].uDroppedPacket++;
    339       #endif /* TI_DBG */
    340     }
    341 	else
    342     {
    343       #ifdef TI_DBG
    344 		pTxDataQ->aQueueCounters[uQueId].uEnqueuePacket++;
    345       #endif /* TI_DBG */
    346     }
    347 
    348     CL_TRACE_END_L3 ("tiwlan_drv.ko", "INHERIT", "TX", "");
    349 
    350     return eStatus;
    351 }
    352 
    353 
    354 /**
    355  * \fn     txDataQ_StopQueue
    356  * \brief  Set queue's busy indication
    357  *
    358  * This function is called by the txCtrl_xmitData() if the queue's backpressure
    359  *   indication is set.
    360  * It sets the internal queue's Busy indication.
    361  *
    362  * \note
    363  * \param  hTxDataQ - The object
    364  * \param  uTidBitMap   - The changed TIDs busy bitmap
    365  * \return void
    366  * \sa     txDataQ_UpdateBusyMap
    367  */
    368 void txDataQ_StopQueue (TI_HANDLE hTxDataQ, TI_UINT32 uTidBitMap)
    369 {
    370 	TTxDataQ *pTxDataQ = (TTxDataQ *)hTxDataQ;
    371 
    372 	/* Set the relevant queue(s) busy flag */
    373 	txDataQ_UpdateQueuesBusyState (pTxDataQ, uTidBitMap);
    374 }
    375 
    376 
    377 /**
    378  * \fn     txDataQ_UpdateBusyMap
    379  * \brief  Set queue's busy indication
    380  *
    381  * This function is called by the txCtrl if the backpressure map per TID is changed.
    382  * This could be as a result of Tx-Complete, admission change or association.
    383  * The function modifies the internal queue's Busy indication and calls the scheduler.
    384  *
    385  * \note
    386  * \param  hTxDataQ - The object
    387  * \param  uTidBitMap   - The changed TIDs busy bitmap
    388  * \return void
    389  * \sa     txDataQ_StopQueue
    390  */
    391 void txDataQ_UpdateBusyMap (TI_HANDLE hTxDataQ, TI_UINT32 tidBitMap)
    392 {
    393 	TTxDataQ *pTxDataQ = (TTxDataQ *)hTxDataQ;
    394 
    395 	/* Update the Queue(s) mode */
    396 	txDataQ_UpdateQueuesBusyState (pTxDataQ, tidBitMap);
    397 
    398 	/* Run the scheduler */
    399 	txDataQ_RunScheduler (hTxDataQ);
    400 }
    401 
    402 
    403 /**
    404  * \fn     txDataQ_StopAll
    405  * \brief  Disable Data-Queue module access to Tx path.
    406  *
    407  * Called by the Tx-Port when the data-queue module can't access the Tx path.
    408  * Sets stop-all-queues indication.
    409  *
    410  * \note
    411  * \param  hTxDataQ - The object
    412  * \return void
    413  * \sa     txDataQ_WakeAll
    414  */
    415 void txDataQ_StopAll (TI_HANDLE hTxDataQ)
    416 {
    417     TTxDataQ *pTxDataQ = (TTxDataQ *)hTxDataQ;
    418 
    419 	/* Disable the data Tx port */
    420 	pTxDataQ->bDataPortEnable = TI_FALSE;
    421 }
    422 
    423 
    424 /**
    425  * \fn     txDataQ_WakeAll
    426  * \brief  Enable Data-Queue module access to Tx path.
    427  *
    428  * Called by the Tx-Port when the data-queue module can access the Tx path.
    429  * Clears the stop-all-queues indication and calls the scheduler.
    430  *
    431  * \note
    432  * \param  hTxDataQ - The object
    433  * \return void
    434  * \sa     txDataQ_StopAll
    435  */
    436 void txDataQ_WakeAll (TI_HANDLE hTxDataQ)
    437 {
    438     TTxDataQ *pTxDataQ = (TTxDataQ *)hTxDataQ;
    439 
    440 	/* Enable the data Tx port */
    441 	pTxDataQ->bDataPortEnable = TI_TRUE;
    442 
    443 	/* Run the scheduler */
    444 	txDataQ_RunScheduler (hTxDataQ);
    445 }
    446 
    447 
    448 /***************************************************************************
    449 *                       DEBUG  FUNCTIONS  IMPLEMENTATION			       *
    450 ****************************************************************************/
    451 
    452 #ifdef TI_DBG
    453 
    454 /**
    455  * \fn     txDataQ_PrintModuleParams
    456  * \brief  Print Module Parameters
    457  *
    458  * Print Module Parameters
    459  *
    460  * \note
    461  * \param  hTxDataQ - The object
    462  * \return void
    463  * \sa
    464  */
    465 void txDataQ_PrintModuleParams (TI_HANDLE hTxDataQ)
    466 {
    467 	TTxDataQ *pTxDataQ = (TTxDataQ *)hTxDataQ;
    468 	TI_UINT32      qIndex;
    469 
    470 	WLAN_OS_REPORT(("--------- txDataQueue_printModuleParams ----------\n\n"));
    471 
    472 	WLAN_OS_REPORT(("bDataPortEnable = %d\n",pTxDataQ->bDataPortEnable));
    473 	WLAN_OS_REPORT(("uNumQueues      = %d\n",pTxDataQ->uNumQueues));
    474 	WLAN_OS_REPORT(("uLastQueId      = %d\n",pTxDataQ->uLastQueId));
    475 	WLAN_OS_REPORT(("uContextId      = %d\n",pTxDataQ->uContextId));
    476 
    477 	for (qIndex = 0; qIndex < pTxDataQ->uNumQueues; qIndex++)
    478     {
    479 		WLAN_OS_REPORT(("aQueueBusy[%d]	   = %d\n", qIndex, pTxDataQ->aQueueBusy[qIndex]));
    480         WLAN_OS_REPORT(("aQueueMaxSize[%d] = %d\n", qIndex, pTxDataQ->aQueueMaxSize[qIndex]));
    481     }
    482 
    483 	WLAN_OS_REPORT(("-------------- Queues Info -----------------------\n"));
    484 	for (qIndex = 0; qIndex < MAX_NUM_OF_AC; qIndex++)
    485     {
    486         WLAN_OS_REPORT(("Que %d:\n", qIndex));
    487         que_Print (pTxDataQ->aQueues[qIndex]);
    488     }
    489 
    490 	WLAN_OS_REPORT(("--------------------------------------------------\n\n"));
    491 }
    492 
    493 
    494 /**
    495  * \fn     txDataQ_PrintQueueStatistics
    496  * \brief  Print queues statistics
    497  *
    498  * Print queues statistics
    499  *
    500  * \note
    501  * \param  hTxDataQ - The object
    502  * \return void
    503  * \sa
    504  */
    505 void txDataQ_PrintQueueStatistics (TI_HANDLE hTxDataQ)
    506 {
    507 #ifdef REPORT_LOG
    508     TTxDataQ *pTxDataQ = (TTxDataQ *)hTxDataQ;
    509     TI_UINT32      qIndex;
    510 
    511     WLAN_OS_REPORT(("-------------- txDataQueue_printStatistics -------\n\n"));
    512 
    513     WLAN_OS_REPORT(("-------------- Classifier Mismatches = %d  -------\n",pTxDataQ->uClsfrMismatchCount));
    514 
    515     WLAN_OS_REPORT(("-------------- Enqueue to queues -----------------\n"));
    516     for(qIndex = 0; qIndex < MAX_NUM_OF_AC; qIndex++)
    517         WLAN_OS_REPORT(("Que[%d]: = %d\n",qIndex, pTxDataQ->aQueueCounters[qIndex].uEnqueuePacket));
    518 
    519     WLAN_OS_REPORT(("-------------- Dequeue from queues ---------------\n"));
    520     for(qIndex = 0; qIndex < MAX_NUM_OF_AC; qIndex++)
    521         WLAN_OS_REPORT(("Que[%d]: = %d\n",qIndex, pTxDataQ->aQueueCounters[qIndex].uDequeuePacket));
    522 
    523     WLAN_OS_REPORT(("-------------- Requeue to queues -----------------\n"));
    524     for(qIndex = 0; qIndex < MAX_NUM_OF_AC; qIndex++)
    525         WLAN_OS_REPORT(("Que[%d]: = %d\n",qIndex, pTxDataQ->aQueueCounters[qIndex].uRequeuePacket));
    526 
    527     WLAN_OS_REPORT(("-------------- Sent to TxCtrl --------------------\n"));
    528     for(qIndex = 0; qIndex < MAX_NUM_OF_AC; qIndex++)
    529         WLAN_OS_REPORT(("Que[%d]: = %d\n",qIndex, pTxDataQ->aQueueCounters[qIndex].uXmittedPacket));
    530 
    531     WLAN_OS_REPORT(("-------------- Dropped - Queue Full --------------\n"));
    532     for(qIndex = 0; qIndex < MAX_NUM_OF_AC; qIndex++)
    533         WLAN_OS_REPORT(("Que[%d]: = %d\n",qIndex, pTxDataQ->aQueueCounters[qIndex].uDroppedPacket));
    534 
    535     WLAN_OS_REPORT(("--------------------------------------------------\n\n"));
    536 #endif
    537 }
    538 
    539 
    540 /**
    541  * \fn     txDataQ_ResetQueueStatistics
    542  * \brief  Reset queues statistics
    543  *
    544  * Reset queues statistics
    545  *
    546  * \note
    547  * \param  hTxDataQ - The object
    548  * \return void
    549  * \sa
    550  */
    551 void txDataQ_ResetQueueStatistics (TI_HANDLE hTxDataQ)
    552 {
    553 	TTxDataQ *pTxDataQ = (TTxDataQ *)hTxDataQ;
    554 
    555     os_memoryZero(pTxDataQ->hOs, &pTxDataQ->aQueueCounters, sizeof(pTxDataQ->aQueueCounters));
    556 }
    557 
    558 
    559 #endif /* TI_DBG */
    560 
    561 
    562 
    563 /***************************************************************************
    564 *                      INTERNAL  FUNCTIONS  IMPLEMENTATION				   *
    565 ****************************************************************************/
    566 
    567 
    568 /**
    569  * \fn     txDataQ_RunScheduler
    570  * \brief  The module's Tx scheduler
    571  *
    572  * This function is the Data-Queue scheduler.
    573  * It selects a packet to transmit from the tx queues and sends it to the TxCtrl.
    574  * The queues are selected in a round-robin order.
    575  * The function is called by one of:
    576  *     txDataQ_Run()
    577  *     txDataQ_UpdateBusyMap()
    578  *     txDataQ_WakeAll()
    579  *
    580  * \note
    581  * \param  hTxDataQ - The object
    582  * \return void
    583  * \sa
    584  */
    585 static void txDataQ_RunScheduler (TI_HANDLE hTxDataQ)
    586 {
    587 	TTxDataQ   *pTxDataQ = (TTxDataQ *)hTxDataQ;
    588 	TI_UINT32  uIdleIterationsCount = 0;  /* Count iterations without packet transmission (for exit criteria) */
    589 	TI_UINT32  uQueId = pTxDataQ->uLastQueId;  /* The last iteration queue */
    590 	TI_STATUS  eStatus;  /* The return status of the txCtrl_xmitData function */
    591     TTxCtrlBlk *pPktCtrlBlk; /* Pointer to the packet to be dequeued and sent */
    592 
    593 	while(1)
    594 	{
    595 		/* check if the Data port is closed or if the scheduler couldn't send packet from
    596 		     all queues => no packet can be transferred to the TNET */
    597 		if ( !pTxDataQ->bDataPortEnable  ||  (uIdleIterationsCount >= pTxDataQ->uNumQueues) )
    598 		{
    599 			return;
    600 		}
    601 
    602 		/* Selecting the next queue */
    603 		uQueId++;
    604 		if (uQueId == pTxDataQ->uNumQueues)
    605         {
    606 			uQueId = 0;
    607         }
    608 		pTxDataQ->uLastQueId = uQueId;
    609 
    610 		/* Increment the idle iterations counter */
    611 		uIdleIterationsCount++;
    612 
    613 		/* If the queue is busy (AC is full), continue to next queue. */
    614 		if (pTxDataQ->aQueueBusy[uQueId])
    615         {
    616 			continue;
    617         }
    618 
    619 		/* Dequeue a packet in a critical section */
    620         context_EnterCriticalSection (pTxDataQ->hContext);
    621 		pPktCtrlBlk = (TTxCtrlBlk *) que_Dequeue (pTxDataQ->aQueues[uQueId]);
    622         context_LeaveCriticalSection (pTxDataQ->hContext);
    623 
    624 		/* If the queue was empty, continue to the next queue */
    625 		if (pPktCtrlBlk == NULL)
    626         {
    627 			continue;
    628         }
    629 
    630 #ifdef TI_DBG
    631 		pTxDataQ->aQueueCounters[uQueId].uDequeuePacket++;
    632 #endif /* TI_DBG */
    633 
    634 		/* Send the packet */
    635 		eStatus = txCtrl_XmitData (pTxDataQ->hTxCtrl, pPktCtrlBlk);
    636 
    637 		/*
    638          * If the return status is busy it means that the packet was not sent
    639          *   so we need to requeue it for future try.
    640          */
    641 		if(eStatus == STATUS_XMIT_BUSY)
    642 		{
    643             /* Requeue the packet in a critical section */
    644             context_EnterCriticalSection (pTxDataQ->hContext);
    645 			que_Requeue (pTxDataQ->aQueues[uQueId], (TI_HANDLE)pPktCtrlBlk);
    646             context_LeaveCriticalSection (pTxDataQ->hContext);
    647 
    648 #ifdef TI_DBG
    649 			pTxDataQ->aQueueCounters[uQueId].uRequeuePacket++;
    650 #endif /* TI_DBG */
    651 
    652 			continue;
    653 		}
    654 
    655 		/* If we reach this point, a packet was sent successfully so reset the idle iterations counter. */
    656 		uIdleIterationsCount = 0;
    657 
    658 #ifdef TI_DBG
    659 		pTxDataQ->aQueueCounters[uQueId].uXmittedPacket++;
    660 #endif /* TI_DBG */
    661 
    662 	} /* End of while */
    663 
    664 	/* Unreachable code */
    665 }
    666 
    667 
    668 /**
    669  * \fn     txDataQ_UpdateQueuesBusyState
    670  * \brief  Update queues' busy state
    671  *
    672  * Update the Queues Mode to Busy according to the input TidBitMap.
    673 *               Each Tid that is set indicates that the related Queue is Busy.
    674 *
    675  * \note
    676  * \param  hTxDataQ - The object
    677  * \param  uTidBitMap   - The changed TIDs busy bitmap
    678  * \return void
    679  * \sa
    680  */
    681 static void txDataQ_UpdateQueuesBusyState (TTxDataQ *pTxDataQ, TI_UINT32 uTidBitMap)
    682 {
    683 	TI_UINT32 uTidIdx;
    684 
    685 	/* Go over the TidBitMap and update the related queue busy state */
    686 	for (uTidIdx = 0; uTidIdx < MAX_NUM_OF_802_1d_TAGS; uTidIdx++, uTidBitMap >>= 1)
    687 	{
    688 		if (uTidBitMap & 0x1) /* this Tid is busy */
    689         {
    690 			pTxDataQ->aQueueBusy[aTidToQueueTable[uTidIdx]] = TI_TRUE;
    691         }
    692 		else
    693         {
    694 			pTxDataQ->aQueueBusy[aTidToQueueTable[uTidIdx]] = TI_FALSE;
    695         }
    696 	}
    697 }
    698