diff options
Diffstat (limited to 'wilink_6_1/stad/src/Data_link/txDataQueue.c')
-rw-r--r-- | wilink_6_1/stad/src/Data_link/txDataQueue.c | 697 |
1 files changed, 697 insertions, 0 deletions
diff --git a/wilink_6_1/stad/src/Data_link/txDataQueue.c b/wilink_6_1/stad/src/Data_link/txDataQueue.c new file mode 100644 index 0000000..f9d27e2 --- /dev/null +++ b/wilink_6_1/stad/src/Data_link/txDataQueue.c @@ -0,0 +1,697 @@ +/* + * txDataQueue.c + * + * Copyright(c) 1998 - 2009 Texas Instruments. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name Texas Instruments nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +/** \file txDataQueue.c + * \brief The Tx Data Queues module. + * + * \see txDataQueue.h + */ + + +#define __FILE_ID__ FILE_ID_60 +#include "paramOut.h" +#include "osApi.h" +#include "report.h" +#include "queue.h" +#include "context.h" +#include "Ethernet.h" +#include "TWDriver.h" +#include "DataCtrl_Api.h" +#include "txDataQueue.h" +#include "DrvMainModules.h" +#include "bmtrace_api.h" + + +/* Internal Functions prototypes */ +static void txDataQ_RunScheduler (TI_HANDLE hTxDataQ); +static void txDataQ_UpdateQueuesBusyState (TTxDataQ *pTxDataQ, TI_UINT32 uTidBitMap); + + +/*************************************************************************** +* PUBLIC FUNCTIONS IMPLEMENTATION * +****************************************************************************/ + + +/** + * \fn txDataQ_Create + * \brief Create the module and its queues + * + * Create the Tx Data module and its queues. + * + * \note + * \param hOs - Handle to the Os Abstraction Layer + * \return Handle to the allocated Tx Data Queue module (NULL if failed) + * \sa + */ +TI_HANDLE txDataQ_Create(TI_HANDLE hOs) +{ + TTxDataQ *pTxDataQ; + + /* allocate TxDataQueue module */ + pTxDataQ = os_memoryAlloc (hOs, (sizeof(TTxDataQ))); + + if (!pTxDataQ) + { + WLAN_OS_REPORT(("Error allocating the TxDataQueue Module\n")); + return NULL; + } + + /* Reset TxDataQueue module */ + os_memoryZero (hOs, pTxDataQ, (sizeof(TTxDataQ))); + + return (TI_HANDLE)pTxDataQ; +} + + +/** + * \fn txDataQ_Init + * \brief Save required modules handles + * + * Save other modules handles. + * + * \note + * \param pStadHandles - The driver modules handles + * \return void + * \sa + */ +void txDataQ_Init (TStadHandlesList *pStadHandles) +{ + TTxDataQ *pTxDataQ = (TTxDataQ *)(pStadHandles->hTxDataQ); + TI_UINT32 uNodeHeaderOffset = TI_FIELD_OFFSET(TTxnStruct, tTxnQNode); + TI_UINT8 uQueId; + + /* save modules handles */ + pTxDataQ->hContext = pStadHandles->hContext; + pTxDataQ->hTxCtrl = pStadHandles->hTxCtrl; + pTxDataQ->hOs = pStadHandles->hOs; + pTxDataQ->hReport = pStadHandles->hReport; + pTxDataQ->hTxMgmtQ = pStadHandles->hTxMgmtQ; + + /* Configures the Port Default status to Close */ + pTxDataQ->bDataPortEnable = TI_FALSE; + + /* Configures the LastQueId to zero => scheduler will strart from Queue 1*/ + pTxDataQ->uLastQueId = 0; + + /* init the number of the Data queue to be used */ + pTxDataQ->uNumQueues = MAX_NUM_OF_AC; + + /* init the max size of the Data queues */ + pTxDataQ->aQueueMaxSize[QOS_AC_BE] = DATA_QUEUE_DEPTH_BE; + pTxDataQ->aQueueMaxSize[QOS_AC_BK] = DATA_QUEUE_DEPTH_BK; + pTxDataQ->aQueueMaxSize[QOS_AC_VI] = DATA_QUEUE_DEPTH_VI; + pTxDataQ->aQueueMaxSize[QOS_AC_VO] = DATA_QUEUE_DEPTH_VO; + + /* Create the tx data queues */ + for (uQueId = 0; uQueId < pTxDataQ->uNumQueues; uQueId++) + { + pTxDataQ->aQueues[uQueId] = que_Create (pTxDataQ->hOs, + pTxDataQ->hReport, + pTxDataQ->aQueueMaxSize[uQueId], + uNodeHeaderOffset); + + /* If any Queues' allocation failed, print error, free TxDataQueue module and exit */ + if (pTxDataQ->aQueues[uQueId] == NULL) + { + TRACE0(pTxDataQ->hReport, REPORT_SEVERITY_CONSOLE , "Failed to create queue\n"); + WLAN_OS_REPORT(("Failed to create queue\n")); + os_memoryFree (pTxDataQ->hOs, pTxDataQ, sizeof(TTxDataQ)); + return; + } + + /* Configure the Queue default Mode to Open (not busy)*/ + pTxDataQ->aQueueBusy[uQueId] = TI_FALSE; + } + + /* Register to the context engine and get the client ID */ + pTxDataQ->uContextId = context_RegisterClient (pTxDataQ->hContext, + txDataQ_RunScheduler, + (TI_HANDLE)pTxDataQ, + TI_TRUE, + "TX_DATA", + sizeof("TX_DATA")); +} + + +/** + * \fn txDataQ_SetDefaults + * \brief Configure module with default settings + * + * Init the Tx Data queues. + * Register as the context-engine client. + * + * \note + * \param hTxDataQ - The object + * \param Other modules handles + * \return TI_OK on success or TI_NOK on failure + * \sa + */ +TI_STATUS txDataQ_SetDefaults (TI_HANDLE hTxDataQ, txDataInitParams_t *pTxDataInitParams) +{ + TTxDataQ *pTxDataQ = (TTxDataQ *)hTxDataQ; + TI_STATUS eStatus; + + /* configure the classifier sub-module */ + eStatus = txDataClsfr_Config (hTxDataQ, &pTxDataInitParams->ClsfrInitParam); + if (eStatus != TI_OK) + { + TRACE0(pTxDataQ->hReport, REPORT_SEVERITY_CONSOLE ,"FATAL ERROR: txDataQ_SetDefaults(): txDataClsfr_Config failed - Aborting\n"); + WLAN_OS_REPORT(("FATAL ERROR: txDataQ_SetDefaults(): txDataClsfr_Config failed - Aborting\n")); + return eStatus; + } + +TRACE0(pTxDataQ->hReport, REPORT_SEVERITY_INIT, ".....Tx Data Queue configured successfully\n"); + + return TI_OK; +} + + +/** + * \fn txDataQ_Destroy + * \brief Destroy the module and its queues + * + * Clear and destroy the queues and then destroy the module object. + * + * \note + * \param hTxDataQ - The object + * \return TI_OK - Unload succesfull, TI_NOK - Unload unsuccesfull + * \sa + */ +TI_STATUS txDataQ_Destroy (TI_HANDLE hTxDataQ) +{ + TTxDataQ *pTxDataQ = (TTxDataQ *)hTxDataQ; + TI_STATUS status = TI_OK; + TI_UINT32 uQueId; + + /* Dequeue and free all queued packets */ + txDataQ_ClearQueues (hTxDataQ); + + /* Free Data queues */ + for (uQueId = 0 ; uQueId < pTxDataQ->uNumQueues ; uQueId++) + { + if (que_Destroy(pTxDataQ->aQueues[uQueId]) != TI_OK) + { + TRACE1(pTxDataQ->hReport, REPORT_SEVERITY_ERROR, "txDataQueue_unLoad: fail to free Data Queue number: %d\n",uQueId); + status = TI_NOK; + } + } + + /* Free Tx Data Queue Module */ + os_memoryFree (pTxDataQ->hOs, pTxDataQ, sizeof(TTxDataQ)); + + return status; +} + + +/** + * \fn txDataQ_ClearQueues + * \brief Clear all queues + * + * Dequeue and free all queued packets. + * + * \note + * \param hTxDataQ - The object + * \return void + * \sa + */ +void txDataQ_ClearQueues (TI_HANDLE hTxDataQ) +{ + TTxDataQ *pTxDataQ = (TTxDataQ *)hTxDataQ; + TTxCtrlBlk *pPktCtrlBlk; + TI_UINT32 uQueId; + + /* Dequeue and free all queued packets */ + for (uQueId = 0 ; uQueId < pTxDataQ->uNumQueues ; uQueId++) + { + do { + context_EnterCriticalSection (pTxDataQ->hContext); + pPktCtrlBlk = (TTxCtrlBlk *) que_Dequeue(pTxDataQ->aQueues[uQueId]); + context_LeaveCriticalSection (pTxDataQ->hContext); + if (pPktCtrlBlk != NULL) { + txCtrl_FreePacket (pTxDataQ->hTxCtrl, pPktCtrlBlk, TI_NOK); + } + } while (pPktCtrlBlk != NULL); + } +} + + +/** + * \fn txDataQ_InsertPacket + * \brief Insert packet in queue and schedule task + * + * This function is called by the hard_start_xmit() callback function. + * If the packet it an EAPOL, forward it to the Mgmt-Queue. + * Otherwise, classify the packet, enqueue it and request + * context switch for handling it in the driver's context. + * + * \note + * \param hTxDataQ - The object + * \param pPktCtrlBlk - Pointer to the packet + * \param uPacketDtag - The packet priority optionaly set by the OAL + * \return TI_OK - if the packet was queued, TI_NOK - if the packet was dropped. + * \sa txDataQ_Run + */ +TI_STATUS txDataQ_InsertPacket (TI_HANDLE hTxDataQ, TTxCtrlBlk *pPktCtrlBlk, TI_UINT8 uPacketDtag) +{ + TTxDataQ *pTxDataQ = (TTxDataQ *)hTxDataQ; + TEthernetHeader *pEthHead = (TEthernetHeader *)(pPktCtrlBlk->tTxnStruct.aBuf[0]); + TI_STATUS eStatus; + TI_UINT32 uQueId; + TI_UINT32 uQueSize; + CL_TRACE_START_L3(); + + /* If packet is EAPOL, forward it to the Mgmt-Queue and exit */ + if (HTOWLANS(pEthHead->type) == ETHERTYPE_EAPOL) + { + pPktCtrlBlk->tTxPktParams.uPktType = TX_PKT_TYPE_EAPOL; + + return txMgmtQ_Xmit (pTxDataQ->hTxMgmtQ, pPktCtrlBlk, TI_TRUE); + /* Note: The last parameter indicates that we are running in external context */ + } + + pPktCtrlBlk->tTxPktParams.uPktType = TX_PKT_TYPE_ETHER; + + /* Enter critical section to protect classifier data and queue access */ + context_EnterCriticalSection (pTxDataQ->hContext); + + /* Call the Classify function to set the TID field */ + if (txDataClsfr_ClassifyTxPacket (hTxDataQ, pPktCtrlBlk, uPacketDtag) != TI_OK) + { +#ifdef TI_DBG + pTxDataQ->uClsfrMismatchCount++; +TRACE0(pTxDataQ->hReport, REPORT_SEVERITY_WARNING, "txDataQueue_xmit: No matching classifier found \n"); +#endif /* TI_DBG */ + } + + /* Enqueue the packet in the appropriate Queue */ + uQueId = aTidToQueueTable[pPktCtrlBlk->tTxDescriptor.tid]; + eStatus = que_Enqueue (pTxDataQ->aQueues[uQueId], (TI_HANDLE)pPktCtrlBlk); + + /* Get number of packets in current queue */ + uQueSize = que_Size (pTxDataQ->aQueues[uQueId]); + + /* Leave critical section */ + context_LeaveCriticalSection (pTxDataQ->hContext); + + /* If the queue was empty, request switch to driver context for handling queued packet(s) */ + if (uQueSize == 1) + { + context_RequestSchedule (pTxDataQ->hContext, pTxDataQ->uContextId); + } + + if (eStatus != TI_OK) + { + /* If the packet can't be queued drop it */ + txCtrl_FreePacket (pTxDataQ->hTxCtrl, pPktCtrlBlk, TI_NOK); + #ifdef TI_DBG + pTxDataQ->aQueueCounters[uQueId].uDroppedPacket++; + #endif /* TI_DBG */ + } + else + { + #ifdef TI_DBG + pTxDataQ->aQueueCounters[uQueId].uEnqueuePacket++; + #endif /* TI_DBG */ + } + + CL_TRACE_END_L3 ("tiwlan_drv.ko", "INHERIT", "TX", ""); + + return eStatus; +} + + +/** + * \fn txDataQ_StopQueue + * \brief Set queue's busy indication + * + * This function is called by the txCtrl_xmitData() if the queue's backpressure + * indication is set. + * It sets the internal queue's Busy indication. + * + * \note + * \param hTxDataQ - The object + * \param uTidBitMap - The changed TIDs busy bitmap + * \return void + * \sa txDataQ_UpdateBusyMap + */ +void txDataQ_StopQueue (TI_HANDLE hTxDataQ, TI_UINT32 uTidBitMap) +{ + TTxDataQ *pTxDataQ = (TTxDataQ *)hTxDataQ; + + /* Set the relevant queue(s) busy flag */ + txDataQ_UpdateQueuesBusyState (pTxDataQ, uTidBitMap); +} + + +/** + * \fn txDataQ_UpdateBusyMap + * \brief Set queue's busy indication + * + * This function is called by the txCtrl if the backpressure map per TID is changed. + * This could be as a result of Tx-Complete, admission change or association. + * The function modifies the internal queue's Busy indication and calls the scheduler. + * + * \note + * \param hTxDataQ - The object + * \param uTidBitMap - The changed TIDs busy bitmap + * \return void + * \sa txDataQ_StopQueue + */ +void txDataQ_UpdateBusyMap (TI_HANDLE hTxDataQ, TI_UINT32 tidBitMap) +{ + TTxDataQ *pTxDataQ = (TTxDataQ *)hTxDataQ; + + /* Update the Queue(s) mode */ + txDataQ_UpdateQueuesBusyState (pTxDataQ, tidBitMap); + + /* Run the scheduler */ + txDataQ_RunScheduler (hTxDataQ); +} + + +/** + * \fn txDataQ_StopAll + * \brief Disable Data-Queue module access to Tx path. + * + * Called by the Tx-Port when the data-queue module can't access the Tx path. + * Sets stop-all-queues indication. + * + * \note + * \param hTxDataQ - The object + * \return void + * \sa txDataQ_WakeAll + */ +void txDataQ_StopAll (TI_HANDLE hTxDataQ) +{ + TTxDataQ *pTxDataQ = (TTxDataQ *)hTxDataQ; + + /* Disable the data Tx port */ + pTxDataQ->bDataPortEnable = TI_FALSE; +} + + +/** + * \fn txDataQ_WakeAll + * \brief Enable Data-Queue module access to Tx path. + * + * Called by the Tx-Port when the data-queue module can access the Tx path. + * Clears the stop-all-queues indication and calls the scheduler. + * + * \note + * \param hTxDataQ - The object + * \return void + * \sa txDataQ_StopAll + */ +void txDataQ_WakeAll (TI_HANDLE hTxDataQ) +{ + TTxDataQ *pTxDataQ = (TTxDataQ *)hTxDataQ; + + /* Enable the data Tx port */ + pTxDataQ->bDataPortEnable = TI_TRUE; + + /* Run the scheduler */ + txDataQ_RunScheduler (hTxDataQ); +} + + +/*************************************************************************** +* DEBUG FUNCTIONS IMPLEMENTATION * +****************************************************************************/ + +#ifdef TI_DBG + +/** + * \fn txDataQ_PrintModuleParams + * \brief Print Module Parameters + * + * Print Module Parameters + * + * \note + * \param hTxDataQ - The object + * \return void + * \sa + */ +void txDataQ_PrintModuleParams (TI_HANDLE hTxDataQ) +{ + TTxDataQ *pTxDataQ = (TTxDataQ *)hTxDataQ; + TI_UINT32 qIndex; + + WLAN_OS_REPORT(("--------- txDataQueue_printModuleParams ----------\n\n")); + + WLAN_OS_REPORT(("bDataPortEnable = %d\n",pTxDataQ->bDataPortEnable)); + WLAN_OS_REPORT(("uNumQueues = %d\n",pTxDataQ->uNumQueues)); + WLAN_OS_REPORT(("uLastQueId = %d\n",pTxDataQ->uLastQueId)); + WLAN_OS_REPORT(("uContextId = %d\n",pTxDataQ->uContextId)); + + for (qIndex = 0; qIndex < pTxDataQ->uNumQueues; qIndex++) + { + WLAN_OS_REPORT(("aQueueBusy[%d] = %d\n", qIndex, pTxDataQ->aQueueBusy[qIndex])); + WLAN_OS_REPORT(("aQueueMaxSize[%d] = %d\n", qIndex, pTxDataQ->aQueueMaxSize[qIndex])); + } + + WLAN_OS_REPORT(("-------------- Queues Info -----------------------\n")); + for (qIndex = 0; qIndex < MAX_NUM_OF_AC; qIndex++) + { + WLAN_OS_REPORT(("Que %d:\n", qIndex)); + que_Print (pTxDataQ->aQueues[qIndex]); + } + + WLAN_OS_REPORT(("--------------------------------------------------\n\n")); +} + + +/** + * \fn txDataQ_PrintQueueStatistics + * \brief Print queues statistics + * + * Print queues statistics + * + * \note + * \param hTxDataQ - The object + * \return void + * \sa + */ +void txDataQ_PrintQueueStatistics (TI_HANDLE hTxDataQ) +{ +#ifdef REPORT_LOG + TTxDataQ *pTxDataQ = (TTxDataQ *)hTxDataQ; + TI_UINT32 qIndex; + + WLAN_OS_REPORT(("-------------- txDataQueue_printStatistics -------\n\n")); + + WLAN_OS_REPORT(("-------------- Classifier Mismatches = %d -------\n",pTxDataQ->uClsfrMismatchCount)); + + WLAN_OS_REPORT(("-------------- Enqueue to queues -----------------\n")); + for(qIndex = 0; qIndex < MAX_NUM_OF_AC; qIndex++) + WLAN_OS_REPORT(("Que[%d]: = %d\n",qIndex, pTxDataQ->aQueueCounters[qIndex].uEnqueuePacket)); + + WLAN_OS_REPORT(("-------------- Dequeue from queues ---------------\n")); + for(qIndex = 0; qIndex < MAX_NUM_OF_AC; qIndex++) + WLAN_OS_REPORT(("Que[%d]: = %d\n",qIndex, pTxDataQ->aQueueCounters[qIndex].uDequeuePacket)); + + WLAN_OS_REPORT(("-------------- Requeue to queues -----------------\n")); + for(qIndex = 0; qIndex < MAX_NUM_OF_AC; qIndex++) + WLAN_OS_REPORT(("Que[%d]: = %d\n",qIndex, pTxDataQ->aQueueCounters[qIndex].uRequeuePacket)); + + WLAN_OS_REPORT(("-------------- Sent to TxCtrl --------------------\n")); + for(qIndex = 0; qIndex < MAX_NUM_OF_AC; qIndex++) + WLAN_OS_REPORT(("Que[%d]: = %d\n",qIndex, pTxDataQ->aQueueCounters[qIndex].uXmittedPacket)); + + WLAN_OS_REPORT(("-------------- Dropped - Queue Full --------------\n")); + for(qIndex = 0; qIndex < MAX_NUM_OF_AC; qIndex++) + WLAN_OS_REPORT(("Que[%d]: = %d\n",qIndex, pTxDataQ->aQueueCounters[qIndex].uDroppedPacket)); + + WLAN_OS_REPORT(("--------------------------------------------------\n\n")); +#endif +} + + +/** + * \fn txDataQ_ResetQueueStatistics + * \brief Reset queues statistics + * + * Reset queues statistics + * + * \note + * \param hTxDataQ - The object + * \return void + * \sa + */ +void txDataQ_ResetQueueStatistics (TI_HANDLE hTxDataQ) +{ + TTxDataQ *pTxDataQ = (TTxDataQ *)hTxDataQ; + + os_memoryZero(pTxDataQ->hOs, &pTxDataQ->aQueueCounters, sizeof(pTxDataQ->aQueueCounters)); +} + + +#endif /* TI_DBG */ + + + +/*************************************************************************** +* INTERNAL FUNCTIONS IMPLEMENTATION * +****************************************************************************/ + + +/** + * \fn txDataQ_RunScheduler + * \brief The module's Tx scheduler + * + * This function is the Data-Queue scheduler. + * It selects a packet to transmit from the tx queues and sends it to the TxCtrl. + * The queues are selected in a round-robin order. + * The function is called by one of: + * txDataQ_Run() + * txDataQ_UpdateBusyMap() + * txDataQ_WakeAll() + * + * \note + * \param hTxDataQ - The object + * \return void + * \sa + */ +static void txDataQ_RunScheduler (TI_HANDLE hTxDataQ) +{ + TTxDataQ *pTxDataQ = (TTxDataQ *)hTxDataQ; + TI_UINT32 uIdleIterationsCount = 0; /* Count iterations without packet transmission (for exit criteria) */ + TI_UINT32 uQueId = pTxDataQ->uLastQueId; /* The last iteration queue */ + TI_STATUS eStatus; /* The return status of the txCtrl_xmitData function */ + TTxCtrlBlk *pPktCtrlBlk; /* Pointer to the packet to be dequeued and sent */ + + while(1) + { + /* check if the Data port is closed or if the scheduler couldn't send packet from + all queues => no packet can be transferred to the TNET */ + if ( !pTxDataQ->bDataPortEnable || (uIdleIterationsCount >= pTxDataQ->uNumQueues) ) + { + return; + } + + /* Selecting the next queue */ + uQueId++; + if (uQueId == pTxDataQ->uNumQueues) + { + uQueId = 0; + } + pTxDataQ->uLastQueId = uQueId; + + /* Increment the idle iterations counter */ + uIdleIterationsCount++; + + /* If the queue is busy (AC is full), continue to next queue. */ + if (pTxDataQ->aQueueBusy[uQueId]) + { + continue; + } + + /* Dequeue a packet in a critical section */ + context_EnterCriticalSection (pTxDataQ->hContext); + pPktCtrlBlk = (TTxCtrlBlk *) que_Dequeue (pTxDataQ->aQueues[uQueId]); + context_LeaveCriticalSection (pTxDataQ->hContext); + + /* If the queue was empty, continue to the next queue */ + if (pPktCtrlBlk == NULL) + { + continue; + } + +#ifdef TI_DBG + pTxDataQ->aQueueCounters[uQueId].uDequeuePacket++; +#endif /* TI_DBG */ + + /* Send the packet */ + eStatus = txCtrl_XmitData (pTxDataQ->hTxCtrl, pPktCtrlBlk); + + /* + * If the return status is busy it means that the packet was not sent + * so we need to requeue it for future try. + */ + if(eStatus == STATUS_XMIT_BUSY) + { + /* Requeue the packet in a critical section */ + context_EnterCriticalSection (pTxDataQ->hContext); + que_Requeue (pTxDataQ->aQueues[uQueId], (TI_HANDLE)pPktCtrlBlk); + context_LeaveCriticalSection (pTxDataQ->hContext); + +#ifdef TI_DBG + pTxDataQ->aQueueCounters[uQueId].uRequeuePacket++; +#endif /* TI_DBG */ + + continue; + } + + /* If we reach this point, a packet was sent successfully so reset the idle iterations counter. */ + uIdleIterationsCount = 0; + +#ifdef TI_DBG + pTxDataQ->aQueueCounters[uQueId].uXmittedPacket++; +#endif /* TI_DBG */ + + } /* End of while */ + + /* Unreachable code */ +} + + +/** + * \fn txDataQ_UpdateQueuesBusyState + * \brief Update queues' busy state + * + * Update the Queues Mode to Busy according to the input TidBitMap. +* Each Tid that is set indicates that the related Queue is Busy. +* + * \note + * \param hTxDataQ - The object + * \param uTidBitMap - The changed TIDs busy bitmap + * \return void + * \sa + */ +static void txDataQ_UpdateQueuesBusyState (TTxDataQ *pTxDataQ, TI_UINT32 uTidBitMap) +{ + TI_UINT32 uTidIdx; + + /* Go over the TidBitMap and update the related queue busy state */ + for (uTidIdx = 0; uTidIdx < MAX_NUM_OF_802_1d_TAGS; uTidIdx++, uTidBitMap >>= 1) + { + if (uTidBitMap & 0x1) /* this Tid is busy */ + { + pTxDataQ->aQueueBusy[aTidToQueueTable[uTidIdx]] = TI_TRUE; + } + else + { + pTxDataQ->aQueueBusy[aTidToQueueTable[uTidIdx]] = TI_FALSE; + } + } +} |