Home | History | Annotate | Download | only in Data_link
      1 /*
      2  * txCtrl.c
      3  *
      4  * Copyright(c) 1998 - 2010 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 /*      MODULE: txCtrl.c                                                       */
     37 /*    PURPOSE:  The central Tx path module.                                    */
     38 /*              Prepares Tx packets sent from the data-queue and mgmt-queue    */
     39 /*                for copy to the FW, including building the header and the    */
     40 /*                Tx-descriptor.                                               */
     41 /*                                                                             */
     42 /*******************************************************************************/
     43 #define __FILE_ID__  FILE_ID_56
     44 #include "tidef.h"
     45 #include "paramOut.h"
     46 #include "osApi.h"
     47 #include "TWDriver.h"
     48 #include "DataCtrl_Api.h"
     49 #include "802_11Defs.h"
     50 #include "Ethernet.h"
     51 #include "report.h"
     52 #include "timer.h"
     53 #include "TI_IPC_Api.h"
     54 #include "EvHandler.h"
     55 #include "qosMngr_API.h"
     56 #include "healthMonitor.h"
     57 #include "txCtrl.h"
     58 #include "txCtrl_Api.h"
     59 #include "DrvMainModules.h"
     60 #ifdef XCC_MODULE_INCLUDED
     61 #include "XCCMngr.h"
     62 #endif
     63 #include "bmtrace_api.h"
     64 
     65 
     66 /*
     67  * Module internal functions prototypes:
     68  */
     69 
     70 /* Note: put here and not in txCtrl.h to avoid warning in the txCtrl submodules that include txCtrl.h */
     71 
     72 static void   txCtrl_TxCompleteCb (TI_HANDLE hTxCtrl, TxResultDescriptor_t *pTxResultInfo);
     73 static void   txCtrl_BuildDataPkt (txCtrl_t *pTxCtrl, TTxCtrlBlk *pPktCtrlBlk,
     74                                    TI_UINT32 uAc, TI_UINT32 uBackpressure);
     75 static void	  txCtrl_BuildMgmtPkt (txCtrl_t *pTxCtrl, TTxCtrlBlk *pPktCtrlBlk, TI_UINT32 uAc);
     76 static void   txCtrl_UpdateHighestAdmittedAcTable (txCtrl_t *pTxCtrl);
     77 static void   txCtrl_UpdateAcToTidMapping (txCtrl_t *pTxCtrl);
     78 static void   txCtrl_UpdateBackpressure (txCtrl_t *pTxCtrl, TI_UINT32 freedAcBitmap);
     79 static void   txCtrl_UpdateTxCounters (txCtrl_t *pTxCtrl,
     80                                        TxResultDescriptor_t *pTxResultInfo,
     81                                        TTxCtrlBlk *pPktCtrlBlk,
     82                                        TI_UINT32 ac,
     83                                        TI_BOOL bIsDataPkt);
     84 #ifdef XCC_MODULE_INCLUDED  /* Needed only for XCC-V4 */
     85 static void   txCtrl_SetTxDelayCounters (txCtrl_t *pTxCtrl,
     86                                          TI_UINT32 ac,
     87                                          TI_UINT32 fwDelay,
     88                                          TI_UINT32 driverDelay,
     89                                          TI_UINT32 mediumDelay);
     90 #endif /* XCC_MODULE_INCLUDED */
     91 
     92 
     93 /********************************************************************************
     94 *																				*
     95 *                       MACROS and INLINE FUNCTIONS           					*
     96 *																				*
     97 *********************************************************************************/
     98 /* Get the highest admitted AC equal or below the requested one. */
     99 /* AC to TID translation is bivalent so update TID only if the AC was changed. */
    100 #define SELECT_AC_FOR_TID(ptc,tid,ac)                      \
    101 	ac = ptc->highestAdmittedAc[WMEQosTagToACTable[tid]];  \
    102     if (ac != WMEQosTagToACTable[tid])                     \
    103 		tid = WMEQosAcToTid[ac]
    104 
    105 /* Update packet length in the descriptor according to HW interface requirements */
    106 static inline TI_UINT16 txCtrl_TranslateLengthToFw (TTxCtrlBlk *pPktCtrlBlk)
    107 {
    108     TI_UINT16 uPktLen = pPktCtrlBlk->tTxDescriptor.length;
    109     TI_UINT16 uLastWordPad;
    110     TI_UINT32 uBufNum;
    111 
    112     uPktLen = (uPktLen + 3) & 0xFFFC;                               /* Add alignment bytes if needed */
    113     uLastWordPad = uPktLen - pPktCtrlBlk->tTxDescriptor.length;     /* Find number of alignment bytes added */
    114     uPktLen = uPktLen >> 2;                                         /* Convert length to words */
    115 	pPktCtrlBlk->tTxDescriptor.length = ENDIAN_HANDLE_WORD(uPktLen);/* Save FW format length in descriptor */
    116 
    117     /* Find last buffer (last buffer in use is pointed by uBufNum-1) */
    118     for (uBufNum = 1; uBufNum < MAX_XFER_BUFS; uBufNum++)
    119     {
    120         if (pPktCtrlBlk->tTxnStruct.aLen[uBufNum] == 0)
    121         {
    122             break;
    123         }
    124     }
    125     /* Add last word alignment pad also to the last buffer length */
    126     pPktCtrlBlk->tTxnStruct.aLen[uBufNum - 1] += uLastWordPad;
    127 
    128     return uLastWordPad;
    129 }
    130 
    131 /* Translate packet timestamp to FW time, and update also lifeTime and uDriverDelay */
    132 static inline void txCtrl_TranslateTimeToFw (txCtrl_t *pTxCtrl, TTxCtrlBlk *pPktCtrlBlk, TI_UINT16 uLifeTime)
    133 {
    134     TI_UINT32 uPktStartTime = pPktCtrlBlk->tTxDescriptor.startTime;  /* Contains host start time */
    135 
    136     /* Save host packet handling time until this point (for statistics) */
    137     pPktCtrlBlk->tTxPktParams.uDriverDelay = os_timeStampMs (pTxCtrl->hOs) - uPktStartTime;
    138 
    139     /* Translate packet timestamp to FW time and undate descriptor */
    140     uPktStartTime = TWD_TranslateToFwTime (pTxCtrl->hTWD, uPktStartTime);
    141 	pPktCtrlBlk->tTxDescriptor.startTime = ENDIAN_HANDLE_LONG (uPktStartTime);
    142 	pPktCtrlBlk->tTxDescriptor.lifeTime  = ENDIAN_HANDLE_WORD (uLifeTime);
    143 }
    144 
    145 
    146 
    147 /********************************************************************************
    148 *																				*
    149 *                       PUBLIC  FUNCTIONS  IMPLEMENTATION						*
    150 *																				*
    151 *********************************************************************************/
    152 
    153 /*************************************************************************
    154 *                        txCtrl_Create                                   *
    155 **************************************************************************
    156 * DESCRIPTION:  This function initializes the Tx module.
    157 *
    158 * INPUT:        hOs - handle to Os Abstraction Layer
    159 *
    160 * OUTPUT:
    161 *
    162 * RETURN:       Handle to the allocated Tx data control block
    163 *************************************************************************/
    164 TI_HANDLE txCtrl_Create (TI_HANDLE hOs)
    165 {
    166 	txCtrl_t *pTxCtrl;
    167 
    168 	/* allocate Tx module control block */
    169 	pTxCtrl = os_memoryAlloc(hOs, (sizeof(txCtrl_t)));
    170 
    171 	if (!pTxCtrl)
    172 		return NULL;
    173 
    174 	/* reset tx control object */
    175 	os_memoryZero(hOs, pTxCtrl, (sizeof(txCtrl_t)));
    176 
    177 	pTxCtrl->TxEventDistributor = DistributorMgr_Create(hOs, MAX_TX_NOTIF_REQ_ELMENTS);
    178 
    179 	pTxCtrl->hOs = hOs;
    180 
    181 	return pTxCtrl;
    182 }
    183 
    184 
    185 /***************************************************************************
    186 *                           txCtrl_Init                                  *
    187 ****************************************************************************
    188 * DESCRIPTION:  This function configures the TxCtrl module.
    189 ***************************************************************************/
    190 void txCtrl_Init (TStadHandlesList *pStadHandles)
    191 {
    192 	txCtrl_t *pTxCtrl = (txCtrl_t *)(pStadHandles->hTxCtrl);
    193 	TI_UINT32 ac;
    194 
    195 	/* Save other modules handles */
    196 	pTxCtrl->hOs			= pStadHandles->hOs;
    197 	pTxCtrl->hReport		= pStadHandles->hReport;
    198 	pTxCtrl->hCtrlData		= pStadHandles->hCtrlData;
    199 	pTxCtrl->hTWD		    = pStadHandles->hTWD;
    200 	pTxCtrl->hTxDataQ	    = pStadHandles->hTxDataQ;
    201 	pTxCtrl->hTxMgmtQ	    = pStadHandles->hTxMgmtQ;
    202 	pTxCtrl->hEvHandler		= pStadHandles->hEvHandler;
    203 	pTxCtrl->hHealthMonitor = pStadHandles->hHealthMonitor;
    204 	pTxCtrl->hTimer         = pStadHandles->hTimer;
    205 	pTxCtrl->hStaCap        = pStadHandles->hStaCap;
    206 	pTxCtrl->hXCCMngr       = pStadHandles->hXCCMngr;
    207 	pTxCtrl->hQosMngr       = pStadHandles->hQosMngr;
    208 	pTxCtrl->hRxData        = pStadHandles->hRxData;
    209 
    210 	/* Set Tx parameters to defaults */
    211 	pTxCtrl->headerConverMode = HDR_CONVERT_NONE;
    212 	pTxCtrl->currentPrivacyInvokedMode = DEF_CURRENT_PRIVACY_MODE;
    213 	pTxCtrl->eapolEncryptionStatus = DEF_EAPOL_ENCRYPTION_STATUS;
    214 	pTxCtrl->encryptionFieldSize = 0;
    215 	pTxCtrl->currBssType = BSS_INFRASTRUCTURE;
    216 	pTxCtrl->busyAcBitmap = 0;
    217 	pTxCtrl->dbgPktSeqNum = 0;
    218 	pTxCtrl->bCreditCalcTimerRunning = TI_FALSE;
    219 	pTxCtrl->genericEthertype = ETHERTYPE_EAPOL;
    220 
    221 	for (ac = 0; ac < MAX_NUM_OF_AC; ac++)
    222 	{
    223 		pTxCtrl->aMsduLifeTimeTu[ac] = MGMT_PKT_LIFETIME_TU;
    224 		pTxCtrl->ackPolicy[ac] = ACK_POLICY_LEGACY;
    225 		pTxCtrl->admissionState[ac] = AC_ADMITTED;
    226 		pTxCtrl->admissionRequired[ac] = ADMISSION_NOT_REQUIRED;
    227 		pTxCtrl->useAdmissionAlgo[ac] = TI_FALSE;
    228 		pTxCtrl->mediumTime[ac] = 0;
    229 		pTxCtrl->lastCreditCalcTimeStamp[ac] = 0;
    230 		pTxCtrl->credit[ac] = 0;
    231 	}
    232 
    233 	/* Reset counters */
    234 	txCtrlParams_resetCounters (pStadHandles->hTxCtrl);
    235 
    236 #ifdef TI_DBG
    237 	txCtrlParams_resetDbgCounters (pStadHandles->hTxCtrl);
    238 #endif
    239 
    240 	/* Register the Tx-Complete callback function. */
    241 	TWD_RegisterCb (pTxCtrl->hTWD,
    242 			TWD_EVENT_TX_RESULT_SEND_PKT_COMPLETE,
    243 			(void*)txCtrl_TxCompleteCb,
    244 			pStadHandles->hTxCtrl);
    245 
    246 	/* Register the Update-Busy-Map callback function. */
    247 	TWD_RegisterCb (pTxCtrl->hTWD,
    248 			TWD_EVENT_TX_HW_QUEUE_UPDATE_BUSY_MAP,
    249 			(void *)txCtrl_UpdateBackpressure,
    250 			pStadHandles->hTxCtrl);
    251 
    252 	TRACE0(pTxCtrl->hReport, REPORT_SEVERITY_INIT, ".....Tx Data configured successfully\n");
    253 }
    254 
    255 
    256 /*************************************************************************
    257 *                        txCtrl_SetDefaults                                   *
    258 **************************************************************************
    259 * DESCRIPTION:
    260 *
    261 * INPUT:
    262 *               txDataInitParams - Tx Data creation parameters
    263 *
    264 * OUTPUT:
    265 *
    266 * RETURN:
    267 *************************************************************************/
    268 TI_STATUS txCtrl_SetDefaults (TI_HANDLE hTxCtrl, txDataInitParams_t *txDataInitParams)
    269 {
    270 	txCtrl_t *pTxCtrl = (txCtrl_t *)hTxCtrl;
    271 
    272 	pTxCtrl->creditCalculationTimeout = txDataInitParams->creditCalculationTimeout;
    273 	pTxCtrl->bCreditCalcTimerEnabled  = txDataInitParams->bCreditCalcTimerEnabled;
    274 
    275 	/* Update queues mapping (AC/TID/Backpressure) after module init. */
    276 	txCtrl_UpdateQueuesMapping (hTxCtrl);
    277 
    278 	/* allocate timer for credit calculation */
    279 	pTxCtrl->hCreditTimer = tmr_CreateTimer (pTxCtrl->hTimer);
    280 	if (pTxCtrl->hCreditTimer == NULL)
    281 	{
    282 		TRACE0(pTxCtrl->hReport, REPORT_SEVERITY_ERROR, "txCtrl_SetDefaults(): Failed to create hCreditTimer!\n");
    283 		return TI_NOK;
    284 	}
    285 
    286 	return TI_OK;
    287 }
    288 
    289 
    290 /***************************************************************************
    291 *                           txCtrl_Unload                                  *
    292 ****************************************************************************
    293 * DESCRIPTION:  This function unload the tx ctrl module.
    294 *
    295 ***************************************************************************/
    296 TI_STATUS txCtrl_Unload (TI_HANDLE hTxCtrl)
    297 {
    298     txCtrl_t *pTxCtrl = (txCtrl_t *)hTxCtrl;
    299 
    300     if (pTxCtrl == NULL)
    301     {
    302         return TI_NOK;
    303     }
    304 
    305     DistributorMgr_Destroy (pTxCtrl->TxEventDistributor);
    306 
    307 	if (pTxCtrl->hCreditTimer)
    308 	{
    309 		tmr_DestroyTimer (pTxCtrl->hCreditTimer);
    310 	}
    311 
    312     /* free Tx Data control block */
    313     os_memoryFree (pTxCtrl->hOs, pTxCtrl, sizeof(txCtrl_t));
    314 
    315     return TI_OK;
    316 }
    317 
    318 
    319 
    320 /*******************************************************************************
    321 *                          txCtrl_XmitData		                               *
    322 ********************************************************************************
    323 * DESCRIPTION:  Get a packet from the data-queue, allocate HW resources and CtrlBlk,
    324 *				  build header and descriptor, and send it to HW by TxXfer.
    325 *
    326 * RETURNS:      STATUS_XMIT_SUCCESS - Packet sent succesfully
    327 *				STATUS_XMIT_BUSY    - Packet dropped due to lack of HW resources, retransmit later.
    328 *				STATUS_XMIT_ERROR   - Packet dropped due to an unexpected problem (bug).
    329 ********************************************************************************/
    330 TI_STATUS txCtrl_XmitData (TI_HANDLE hTxCtrl, TTxCtrlBlk *pPktCtrlBlk)
    331 {
    332     txCtrl_t   *pTxCtrl = (txCtrl_t *)hTxCtrl;
    333 	ETxnStatus eStatus;       /* The Xfer return value (different than this function's return values). */
    334 	TI_UINT32  uAc;
    335 	TI_UINT32  uBackpressure = 0; /* HwQueue's indication when the current queue becomes busy. */
    336     ETxHwQueStatus eHwQueStatus;
    337 	CL_TRACE_START_L3();
    338 
    339 	/* Get an admitted AC corresponding to the packet TID.
    340 	 * If downgraded due to admission limitation, the TID is downgraded as well.
    341 	 */
    342 	SELECT_AC_FOR_TID (pTxCtrl, pPktCtrlBlk->tTxDescriptor.tid, uAc);
    343 
    344 #ifdef TI_DBG
    345 TRACE3(pTxCtrl->hReport, REPORT_SEVERITY_INFORMATION, "txCtrl_XmitData(): Pkt Tx, DescID=%d, AC=%d, Len=%d\n", pPktCtrlBlk->tTxDescriptor.descID, uAc, pPktCtrlBlk->tTxDescriptor.length );
    346 
    347 	pTxCtrl->dbgCounters.dbgNumPktsSent[uAc]++;
    348 #endif
    349 
    350 	/* Call TxHwQueue for Hw resources allocation. */
    351 	{
    352 		CL_TRACE_START_L4();
    353 		eHwQueStatus = TWD_txHwQueue_AllocResources (pTxCtrl->hTWD, pPktCtrlBlk);
    354 		CL_TRACE_END_L4("tiwlan_drv.ko", "INHERIT", "TX", ".allocResources");
    355 	}
    356 
    357 	/* If the current AC can't get more packets, stop it in data-queue module. */
    358 	if (eHwQueStatus == TX_HW_QUE_STATUS_STOP_NEXT)
    359 	{
    360 #ifdef TI_DBG
    361 		pTxCtrl->dbgCounters.dbgNumPktsBackpressure[uAc]++;
    362         TRACE2(pTxCtrl->hReport, REPORT_SEVERITY_INFORMATION, "txCtrl_XmitData(): Backpressure = 0x%x, queue = %d\n", uBackpressure, uAc);
    363 #endif
    364         uBackpressure = 1 << uAc;
    365 		pTxCtrl->busyAcBitmap |= uBackpressure; /* Set the busy bit of the current AC. */
    366 		txDataQ_StopQueue (pTxCtrl->hTxDataQ, pTxCtrl->admittedAcToTidMap[uAc]);
    367 	}
    368 
    369 	/* If current packet can't be transmitted due to lack of resources, return with BUSY value. */
    370 	else if (eHwQueStatus == TX_HW_QUE_STATUS_STOP_CURRENT)
    371 	{
    372 #ifdef TI_DBG
    373 		pTxCtrl->dbgCounters.dbgNumPktsBusy[uAc]++;
    374         TRACE1(pTxCtrl->hReport, REPORT_SEVERITY_INFORMATION, "txCtrl_XmitData(): Queue busy - Packet dropped, queue = %d\n", uAc);
    375 #endif
    376 		txDataQ_StopQueue (pTxCtrl->hTxDataQ, pTxCtrl->admittedAcToTidMap[uAc]);
    377 		CL_TRACE_END_L3("tiwlan_drv.ko", "INHERIT", "TX", "");
    378 		return STATUS_XMIT_BUSY;
    379 	}
    380 
    381 	/* Prepare the packet control-block including the Tx-descriptor. */
    382 	{
    383 		CL_TRACE_START_L4();
    384 		txCtrl_BuildDataPkt(pTxCtrl, pPktCtrlBlk, uAc, uBackpressure);
    385 		CL_TRACE_END_L4("tiwlan_drv.ko", "INHERIT", "TX", ".FillCtrlBlk");
    386 	}
    387 
    388 	/* Call the Tx-Xfer to start packet transfer to the FW and return its result. */
    389 	{
    390 		CL_TRACE_START_L4();
    391 		eStatus = TWD_txXfer_SendPacket (pTxCtrl->hTWD, pPktCtrlBlk);
    392 		CL_TRACE_END_L4("tiwlan_drv.ko", "INHERIT", "TX", ".XferSendPacket");
    393 	}
    394 
    395 	if (eStatus == TXN_STATUS_ERROR)
    396 	{
    397 #ifdef TI_DBG
    398 TRACE2(pTxCtrl->hReport, REPORT_SEVERITY_ERROR, "txCtrl_XmitData(): Xfer Error, queue = %d, Status = %d\n", uAc, eStatus);
    399 		pTxCtrl->dbgCounters.dbgNumPktsError[uAc]++;
    400 #endif
    401 
    402 		/* Free the packet resources (packet and CtrlBlk)  */
    403         txCtrl_FreePacket (pTxCtrl, pPktCtrlBlk, TI_NOK);
    404 
    405 		CL_TRACE_END_L3("tiwlan_drv.ko", "INHERIT", "TX", "");
    406 		return STATUS_XMIT_ERROR;
    407 	}
    408 
    409 #ifdef TI_DBG
    410     pTxCtrl->dbgCounters.dbgNumPktsSuccess[uAc]++;
    411 #endif
    412     CL_TRACE_END_L3("tiwlan_drv.ko", "INHERIT", "TX", "");
    413     return STATUS_XMIT_SUCCESS;
    414 }
    415 
    416 
    417 /*******************************************************************************
    418 *                          txCtrl_XmitMgmt		                               *
    419 ********************************************************************************
    420 * DESCRIPTION:  Get a packet from the Mgmt-Queue (management, EAPOL or IAPP),
    421 *				  allocate HW resources and CtrlBlk, build header if Ethernet (EAPOL),
    422 *				  build descriptor, and send packet to HW by TxXfer.
    423 *
    424 * RETURNS:      STATUS_XMIT_SUCCESS - Packet sent succesfully.
    425 *				STATUS_XMIT_BUSY - Packet dropped due to lack of HW resources, retransmit later.
    426 *				STATUS_XMIT_ERROR - Packet dropped due to an unexpected problem (bug).
    427 ********************************************************************************/
    428 TI_STATUS txCtrl_XmitMgmt (TI_HANDLE hTxCtrl, TTxCtrlBlk *pPktCtrlBlk)
    429 {
    430     txCtrl_t   *pTxCtrl = (txCtrl_t *)hTxCtrl;
    431 	ETxnStatus eStatus;      /* The Xfer return value (different than this function's return values). */
    432 	TI_UINT32  uAc;  /* The AC selected for the packet transmission. */
    433 	TI_UINT32  uBackpressure = 0;/* HwQueue's indication when the current queue becomes busy. */
    434     ETxHwQueStatus eHwQueStatus;
    435 
    436 	/* Get an admitted AC corresponding to the packet TID.
    437 	 * If downgraded due to admission limitation, the TID is downgraded as well.
    438 	 */
    439 	SELECT_AC_FOR_TID (pTxCtrl, pPktCtrlBlk->tTxDescriptor.tid, uAc);
    440 
    441 #ifdef TI_DBG
    442 	pTxCtrl->dbgCounters.dbgNumPktsSent[uAc]++;
    443 #endif
    444 
    445 	/* Call TxHwQueue for Hw resources allocation. */
    446    	eHwQueStatus = TWD_txHwQueue_AllocResources (pTxCtrl->hTWD, pPktCtrlBlk);
    447 
    448 	/* If the used AC can't get more packets, stop it in mgmt-queue module. */
    449 	if (eHwQueStatus == TX_HW_QUE_STATUS_STOP_NEXT)
    450 	{
    451 #ifdef TI_DBG
    452 		pTxCtrl->dbgCounters.dbgNumPktsBackpressure[uAc]++;
    453         TRACE2(pTxCtrl->hReport, REPORT_SEVERITY_INFORMATION, "txCtrl_XmitMgmt(): Backpressure = 0x%x, queue = %d\n", uBackpressure, uAc);
    454 #endif
    455         uBackpressure = 1 << uAc;
    456 		pTxCtrl->busyAcBitmap |= uBackpressure; /* Set the busy bit of the current AC. */
    457 		txMgmtQ_StopQueue (pTxCtrl->hTxMgmtQ, pTxCtrl->admittedAcToTidMap[uAc]);
    458 	}
    459 
    460 	/* If current packet can't be transmitted due to lack of resources, return with BUSY value. */
    461 	else if (eHwQueStatus == TX_HW_QUE_STATUS_STOP_CURRENT)
    462 	{
    463 #ifdef TI_DBG
    464 		pTxCtrl->dbgCounters.dbgNumPktsBusy[uAc]++;
    465         TRACE1(pTxCtrl->hReport, REPORT_SEVERITY_INFORMATION, "txCtrl_XmitMgmt(): Queue busy - Packet dropped, queue = %d\n", uAc);
    466 #endif
    467 		txMgmtQ_StopQueue (pTxCtrl->hTxMgmtQ, pTxCtrl->admittedAcToTidMap[uAc]);
    468 		return STATUS_XMIT_BUSY;
    469 	}
    470 
    471 	/* Prepare the packet control-block including the Tx-descriptor. */
    472 	txCtrl_BuildMgmtPkt (pTxCtrl, pPktCtrlBlk, uAc);
    473 
    474 	/* Call the Tx-Xfer to start packet transfer to the FW and return the result. */
    475 	eStatus = TWD_txXfer_SendPacket (pTxCtrl->hTWD, pPktCtrlBlk);
    476 
    477 	if (eStatus == TXN_STATUS_ERROR)
    478 	{
    479 #ifdef TI_DBG
    480 TRACE1(pTxCtrl->hReport, REPORT_SEVERITY_ERROR, "txCtrl_XmitMgmt(): Xfer Error, Status = %d\n", eStatus);
    481 		pTxCtrl->dbgCounters.dbgNumPktsError[uAc]++;
    482 #endif
    483 		/* Free the packet resources (packet and CtrlBlk)  */
    484         txCtrl_FreePacket (pTxCtrl, pPktCtrlBlk, TI_NOK);
    485 		return STATUS_XMIT_ERROR;
    486 	}
    487 
    488 #ifdef TI_DBG
    489     pTxCtrl->dbgCounters.dbgNumPktsSuccess[uAc]++;
    490 #endif
    491     return STATUS_XMIT_SUCCESS;
    492 }
    493 
    494 
    495 /***************************************************************************
    496 *                           txCtrl_UpdateQueuesMapping
    497 ****************************************************************************
    498 * DESCRIPTION:  This function should be called upon the following events:
    499 *					1) Init
    500 *					2) ACs admission required change (upon association)
    501 *					3) ACs admission state change (upon association and add/delete Tspec).
    502 *				It updates the following mappings (by this oredr!):
    503 *					1) Update mapping from requested-AC to highest-admitted-AC.
    504 *					2) Update mapping from actual-AC to requested-TID (for backpressure mapping).
    505 *					3) Update TID-backpressure bitmap, and if changed update data-queue and mgmt-queue.
    506 *
    507 ***************************************************************************/
    508 void txCtrl_UpdateQueuesMapping (TI_HANDLE hTxCtrl)
    509 {
    510 	txCtrl_t *pTxCtrl = (txCtrl_t *)hTxCtrl;
    511 
    512 	/* Update mapping from requested-AC to highest-admitted-AC. */
    513 	txCtrl_UpdateHighestAdmittedAcTable (pTxCtrl);
    514 
    515 	/* Update mapping from actual-AC to requested-TID (for backpressure mapping). */
    516 	txCtrl_UpdateAcToTidMapping (pTxCtrl);
    517 
    518 	/* Update TID-backpressure bitmap, and if changed update data-queue and mgmt-queue. */
    519 	txCtrl_UpdateBackpressure (pTxCtrl, 0);
    520 }
    521 
    522 
    523 /***************************************************************************
    524 *                           txCtrl_AllocPacketBuffer
    525 ****************************************************************************
    526 * DESCRIPTION:  Allocate a raw buffer for the whole Tx packet.
    527                 Used for driver generated packets and when the OAL needs to
    528                     copy the packet to a new buffer (e.g. to gather multiple buffers).
    529 ***************************************************************************/
    530 void *txCtrl_AllocPacketBuffer (TI_HANDLE hTxCtrl, TTxCtrlBlk *pPktCtrlBlk, TI_UINT32 uPacketLen)
    531 {
    532     txCtrl_t *pTxCtrl = (txCtrl_t *)hTxCtrl;
    533     void     *pRawBuf = os_memoryAlloc (pTxCtrl->hOs, uPacketLen);
    534 
    535     if (pRawBuf)
    536     {
    537         /* Indicate that the packet is in a raw buffer (i.e. not OS packet) and save its address and length */
    538         pPktCtrlBlk->tTxPktParams.uFlags |= TX_CTRL_FLAG_PKT_IN_RAW_BUF;
    539 
    540         /* Save buffer address and length for the free operation */
    541         pPktCtrlBlk->tTxPktParams.pInputPkt    = pRawBuf;
    542         pPktCtrlBlk->tTxPktParams.uInputPktLen = uPacketLen;
    543 
    544         TRACE2(pTxCtrl->hReport, REPORT_SEVERITY_INFORMATION, "txCtrl_AllocPacketBuffer(): pRawBuf = 0x%x, uPacketLen = %d\n", pRawBuf, uPacketLen);
    545     }
    546     else
    547     {
    548         TRACE1(pTxCtrl->hReport, REPORT_SEVERITY_ERROR, "txCtrl_AllocPacketBuffer(): uPacketLen = %d, returning NULL\n", uPacketLen);
    549     }
    550 
    551     return pRawBuf;
    552 }
    553 
    554 
    555 /***************************************************************************
    556 *                           txCtrl_FreePacket
    557 ****************************************************************************
    558 * DESCRIPTION:  Free the packet resources, including the packet and the CtrlBlk
    559 ***************************************************************************/
    560 void txCtrl_FreePacket (TI_HANDLE hTxCtrl, TTxCtrlBlk *pPktCtrlBlk, TI_STATUS eStatus)
    561 {
    562     txCtrl_t *pTxCtrl = (txCtrl_t *)hTxCtrl;
    563 
    564     TRACE3(pTxCtrl->hReport, REPORT_SEVERITY_INFORMATION, "txCtrl_FreePacket(): RawBufFlag = 0x%x, pBuf = 0x%x, Len = %d\n", (pPktCtrlBlk->tTxPktParams.uFlags & TX_CTRL_FLAG_PKT_IN_RAW_BUF), pPktCtrlBlk->tTxPktParams.pInputPkt, pPktCtrlBlk->tTxPktParams.uInputPktLen);
    565 
    566     /* If the packet is in a raw buffer, free its memory */
    567     if (pPktCtrlBlk->tTxPktParams.uFlags & TX_CTRL_FLAG_PKT_IN_RAW_BUF)
    568     {
    569         os_memoryFree (pTxCtrl->hOs,
    570                        pPktCtrlBlk->tTxPktParams.pInputPkt,
    571                        pPktCtrlBlk->tTxPktParams.uInputPktLen);
    572     }
    573     /* If the original packet is in OS format, call the OAL to free it */
    574     else
    575     {
    576         wlanDrvIf_FreeTxPacket (pTxCtrl->hOs, pPktCtrlBlk, eStatus);
    577     }
    578 
    579     /* Free the CtrlBlk */
    580     TWD_txCtrlBlk_Free (pTxCtrl->hTWD, pPktCtrlBlk);
    581 }
    582 
    583 
    584 
    585 /********************************************************************************
    586 *																				*
    587 *                       LOCAL  FUNCTIONS  IMPLEMENTATION						*
    588 *																				*
    589 *********************************************************************************/
    590 
    591 
    592 /*************************************************************************
    593 *                        txCtrl_TxCompleteCb		                             *
    594 **************************************************************************
    595 * DESCRIPTION:  Called by the TWD upon Tx-complete of one packet.
    596 *				Handle packet result:
    597 *				- Update counters (statistics and medium-usage)
    598 *				- Free the packet resources (Wbuf and CtrlBlk)
    599 *
    600 * INPUT:    hTWD -  The Tnetw-Driver handle.
    601 *		    pTxResultInfo - The packet's Tx result information.
    602 *
    603 *************************************************************************/
    604 static void txCtrl_TxCompleteCb (TI_HANDLE hTxCtrl, TxResultDescriptor_t *pTxResultInfo)
    605 {
    606     txCtrl_t    *pTxCtrl = (txCtrl_t *)hTxCtrl;
    607 	TTxCtrlBlk  *pPktCtrlBlk;
    608 	TI_UINT32	ac;
    609 	TI_BOOL	    bIsDataPkt;
    610 	CL_TRACE_START_L3();
    611 
    612 	/* Get packet ctrl-block by desc-ID. */
    613 	pPktCtrlBlk = TWD_txCtrlBlk_GetPointer (pTxCtrl->hTWD, pTxResultInfo->descID);
    614 	ac = WMEQosTagToACTable[pPktCtrlBlk->tTxDescriptor.tid];
    615 
    616 #ifdef TI_DBG
    617 	/* If the pointed entry is already free, print error and exit (not expected to happen). */
    618 	if (pPktCtrlBlk->pNextFreeEntry != NULL)
    619 	{
    620 TRACE2(pTxCtrl->hReport, REPORT_SEVERITY_ERROR, "txCtrl_TxCompleteCb(): Pkt already free!!, DescID=%d, AC=%d\n", pTxResultInfo->descID, ac);
    621 		CL_TRACE_END_L3("tiwlan_drv.ko", "INHERIT", "TX_Cmplt", "");
    622 		return;
    623 	}
    624 TRACE3(pTxCtrl->hReport, REPORT_SEVERITY_INFORMATION, "txCtrl_TxCompleteCb(): Pkt Tx Complete, DescID=%d, AC=%d, Status=%d\n", pTxResultInfo->descID, ac, pTxResultInfo->status);
    625 #endif
    626 	/* Update the TKIP/AES sequence-number according to the Tx data packet security-seq-num. */
    627 	/* Note: The FW always provides the last used seq-num so no need to check if the current
    628 			 packet is data and WEP is on. */
    629 	TWD_SetSecuritySeqNum (pTxCtrl->hTWD, pTxResultInfo->lsbSecuritySequenceNumber);
    630 
    631 	bIsDataPkt = ( (pPktCtrlBlk->tTxPktParams.uPktType == TX_PKT_TYPE_ETHER) ||
    632 		           (pPktCtrlBlk->tTxPktParams.uPktType == TX_PKT_TYPE_WLAN_DATA) );
    633 
    634 #ifdef XCC_MODULE_INCLUDED
    635 	/* If it's a XCC link-test packet, call its handler. */
    636 	if (pPktCtrlBlk->tTxPktParams.uFlags & TX_CTRL_FLAG_LINK_TEST)
    637     {
    638         CL_TRACE_START_L4();
    639         XCCMngr_LinkTestRetriesUpdate (pTxCtrl->hXCCMngr, pTxResultInfo->ackFailures);
    640         CL_TRACE_END_L4("tiwlan_drv.ko", "INHERIT", "TX_Cmplt", ".XCCLinkTest");
    641     }
    642 #endif
    643 
    644 	/* Add the medium usage time for the specific queue. */
    645 	pTxCtrl->totalUsedTime[ac] += (TI_UINT32)ENDIAN_HANDLE_WORD(pTxResultInfo->mediumUsage);
    646 
    647 	/* update TX counters for txDistributer */
    648     {
    649         CL_TRACE_START_L4();
    650         txCtrl_UpdateTxCounters (pTxCtrl, pTxResultInfo, pPktCtrlBlk, ac, bIsDataPkt);
    651         CL_TRACE_END_L4("tiwlan_drv.ko", "INHERIT", "TX_Cmplt", ".Cntrs");
    652     }
    653 
    654 	/* Free the packet resources (packet and CtrlBlk)  */
    655     txCtrl_FreePacket (pTxCtrl, pPktCtrlBlk, TI_OK);
    656 
    657 	CL_TRACE_END_L3("tiwlan_drv.ko", "INHERIT", "TX_Cmplt", "");
    658 }
    659 
    660 
    661 /***************************************************************************
    662 *                   txCtrl_BuildDataPktHdr                                 *
    663 ****************************************************************************
    664 * DESCRIPTION:  this function builds the WLAN header from ethernet format,
    665 *               including 802.11-MAC, LLC/SNAP, security padding, alignment padding.
    666 *
    667 * INPUTS:       hTxCtrl - the object
    668 *               pPktCtrlBlk - data packet control block (Ethernet header)
    669 *
    670 * RETURNS:      uHdrAlignPad - Num of bytes (0 or 2) added at the header's beginning for 4-bytes alignment.
    671 ***************************************************************************/
    672 
    673 TI_UINT32 txCtrl_BuildDataPktHdr (TI_HANDLE hTxCtrl, TTxCtrlBlk *pPktCtrlBlk, AckPolicy_e eAckPolicy)
    674 {
    675     txCtrl_t *pTxCtrl = (txCtrl_t *)hTxCtrl;
    676     TEthernetHeader     *pEthHeader;
    677     dot11_header_t      *pDot11Header;
    678     Wlan_LlcHeader_T    *pWlanSnapHeader;
    679 	EHeaderConvertMode	eQosMode = pTxCtrl->headerConverMode;
    680 	TI_UINT32			uHdrLen = 0;
    681 	TI_UINT32			uHdrAlignPad = 0;
    682 	TI_UINT16			uQosControl;
    683 	TI_UINT16			fc = 0;
    684  	TI_UINT16           typeLength;
    685 
    686 
    687 	/*
    688 	 * Handle encryption if needed, for data or EAPOL (decision was done at RSN):
    689 	 *   - Set WEP bit in header.
    690 	 *   - Add padding for FW security overhead: 4 bytes for TKIP, 8 for AES.
    691 	 */
    692 
    693        	if (( (pPktCtrlBlk->tTxPktParams.uPktType == TX_PKT_TYPE_EAPOL)
    694 			  &&
    695 			  pTxCtrl->eapolEncryptionStatus)
    696 		 ||
    697 			((pPktCtrlBlk->tTxPktParams.uPktType != TX_PKT_TYPE_EAPOL)
    698 			  &&
    699 			  pTxCtrl->currentPrivacyInvokedMode ))
    700         {
    701 			fc |= DOT11_FC_WEP;
    702 			uHdrLen += pTxCtrl->encryptionFieldSize;
    703 			uHdrAlignPad = pTxCtrl->encryptionFieldSize % 4;
    704 	}
    705 
    706 	/*
    707 	 * Handle QoS if needed:
    708 	 */
    709     if (eQosMode == HDR_CONVERT_QOS)
    710 	{
    711 		uHdrAlignPad = (uHdrAlignPad + HEADER_PAD_SIZE) % 4; /* Add 2 bytes pad at the header beginning for 4 bytes alignment. */
    712 		pDot11Header = (dot11_header_t *)&(pPktCtrlBlk->aPktHdr[uHdrAlignPad]);
    713 		uHdrLen += WLAN_QOS_HDR_LEN;
    714 
    715         /* add empty 4Byte for HT control field set via the FW */
    716         if (pTxCtrl->tTxCtrlHtControl.bHtEnable == TI_TRUE)
    717         {
    718             uHdrLen += WLAN_QOS_HT_CONTROL_FIELD_LEN;
    719             fc |= DOT11_FC_ORDER;
    720         }
    721 
    722 		/* Set Qos control fields. */
    723 		uQosControl = (TI_UINT16)(pPktCtrlBlk->tTxDescriptor.tid);
    724 		if ( TI_UNLIKELY(eAckPolicy == ACK_POLICY_NO_ACK) )
    725 			uQosControl |= DOT11_QOS_CONTROL_DONT_ACK;
    726 		COPY_WLAN_WORD(&pDot11Header->qosControl, &uQosControl); /* copy with endianess handling. */
    727 	}
    728 	else  /* No QoS (legacy header, padding is not needed). */
    729 	{
    730 		pDot11Header = (dot11_header_t *)&(pPktCtrlBlk->aPktHdr[uHdrAlignPad]);
    731 		uHdrLen += WLAN_HDR_LEN;
    732 	}
    733 	uHdrLen += uHdrAlignPad;
    734 
    735     /* Before the header translation the first buf-pointer points to the Ethernet header. */
    736 	pEthHeader = (TEthernetHeader *)(pPktCtrlBlk->tTxnStruct.aBuf[0]);
    737 
    738     if (TI_UNLIKELY(MAC_MULTICAST(pEthHeader->dst)))
    739     {
    740         pPktCtrlBlk->tTxPktParams.uFlags |= TX_CTRL_FLAG_MULTICAST;
    741         if (MAC_BROADCAST(pEthHeader->dst))
    742         {
    743             pPktCtrlBlk->tTxPktParams.uFlags |= TX_CTRL_FLAG_BROADCAST;
    744         }
    745     }
    746 
    747 	/* Set MAC header fields for Independent-BSS case. */
    748     if ( TI_UNLIKELY(pTxCtrl->currBssType == BSS_INDEPENDENT) )
    749     {
    750         MAC_COPY (pDot11Header->address1, pEthHeader->dst);
    751         MAC_COPY (pDot11Header->address2, pEthHeader->src);
    752         MAC_COPY (pDot11Header->address3, pTxCtrl->currBssId);
    753 
    754         if (eQosMode == HDR_CONVERT_QOS)
    755             fc |= DOT11_FC_DATA_QOS;
    756         else
    757             fc |= DOT11_FC_DATA;
    758     }
    759 
    760 	/* Set MAC header fields for Infrastructure-BSS case. */
    761     else
    762     {
    763         MAC_COPY (pDot11Header->address1, pTxCtrl->currBssId);
    764         MAC_COPY (pDot11Header->address2, pEthHeader->src);
    765         MAC_COPY (pDot11Header->address3, pEthHeader->dst);
    766 
    767         if (eQosMode == HDR_CONVERT_QOS)
    768             fc |= DOT11_FC_DATA_QOS | DOT11_FC_TO_DS;
    769         else
    770             fc |= DOT11_FC_DATA | DOT11_FC_TO_DS;
    771     }
    772 
    773 	COPY_WLAN_WORD(&pDot11Header->fc, &fc); /* copy with endianess handling. */
    774 
    775     /* Set the SNAP header pointer right after the other header parts handled above. */
    776     pWlanSnapHeader = (Wlan_LlcHeader_T *)&(pPktCtrlBlk->aPktHdr[uHdrLen]);
    777 
    778 	typeLength = HTOWLANS(pEthHeader->type);
    779 
    780     /* Detect the packet type and decide if to create a     */
    781     /*          new SNAP or leave the original LLC.         */
    782     /*------------------------------------------------------*/
    783    	if( typeLength > ETHERNET_MAX_PAYLOAD_SIZE )
    784     {
    785         /* Create the SNAP Header:     */
    786         /*-----------------------------*/
    787         /*
    788          * Make a working copy of the SNAP header
    789          * initialised to zero
    790          */
    791 
    792         pWlanSnapHeader->DSAP = SNAP_CHANNEL_ID;
    793         pWlanSnapHeader->SSAP = SNAP_CHANNEL_ID;
    794         pWlanSnapHeader->Control = LLC_CONTROL_UNNUMBERED_INFORMATION;
    795 
    796         /* Check to see if the Ethertype matches anything in the translation     */
    797         /* table (Appletalk AARP or DixII/IPX).  If so, add the 802.1h           */
    798         /* SNAP.                                                                 */
    799 
    800         if(( ETHERTYPE_APPLE_AARP == typeLength ) ||
    801            ( ETHERTYPE_DIX_II_IPX == typeLength ))
    802         {
    803             /* Fill out the SNAP Header with 802.1H extention   */
    804             pWlanSnapHeader->OUI[0] = SNAP_OUI_802_1H_BYTE0;
    805 			pWlanSnapHeader->OUI[1] = SNAP_OUI_802_1H_BYTE1;
    806 			pWlanSnapHeader->OUI[2] = SNAP_OUI_802_1H_BYTE2;
    807 
    808         }
    809         else
    810         {
    811             /* otherwise, add the RFC1042 SNAP   */
    812     		pWlanSnapHeader->OUI[0] = SNAP_OUI_RFC1042_BYTE0;
    813 			pWlanSnapHeader->OUI[1] = SNAP_OUI_RFC1042_BYTE0;
    814 			pWlanSnapHeader->OUI[2] = SNAP_OUI_RFC1042_BYTE0;
    815         }
    816 
    817         /* set type length */
    818         pWlanSnapHeader->Type = pEthHeader->type;
    819 
    820         /* Add the SNAP length to the total header length. */
    821         uHdrLen += sizeof(Wlan_LlcHeader_T);
    822     }
    823 
    824     /* Replace first buffer pointer and length to the descriptor and WLAN-header (instead of Ether header) */
    825     pPktCtrlBlk->tTxnStruct.aBuf[0] = (TI_UINT8 *)&(pPktCtrlBlk->tTxDescriptor);
    826     pPktCtrlBlk->tTxnStruct.aLen[0] = sizeof(TxIfDescriptor_t) + uHdrLen;
    827     pPktCtrlBlk->tTxDescriptor.length += pPktCtrlBlk->tTxnStruct.aLen[0] - ETHERNET_HDR_LEN;
    828 
    829 	/* Return the number of bytes (0 or 2) added at the header's beginning for 4-bytes alignment. */
    830     return uHdrAlignPad;
    831 }
    832 
    833 
    834 /***************************************************************************
    835 *                       txCtrl_BuildDataPkt
    836 ****************************************************************************
    837 * DESCRIPTION:  Prepare the Data packet control-block including the Tx-descriptor.
    838 ***************************************************************************/
    839 static void txCtrl_BuildDataPkt (txCtrl_t *pTxCtrl, TTxCtrlBlk *pPktCtrlBlk,
    840                                  TI_UINT32 uAc, TI_UINT32 uBackpressure)
    841 {
    842 	TI_UINT32 uHdrAlignPad; /* Num of bytes added between Tx-descriptor and header for 4 bytes alignment (0 or 2). */
    843     TI_UINT16 uLastWordPad; /* Num of bytes added at the end of the packet for 4 bytes alignment */
    844 	TI_UINT16 uTxDescAttr;
    845 	AckPolicy_e eAckPolicy = pTxCtrl->ackPolicy[uAc];
    846 
    847 	/* Build packet header (including MAC, LLC/SNAP, security padding, header alignment padding). */
    848     uHdrAlignPad = txCtrl_BuildDataPktHdr ((TI_HANDLE)pTxCtrl, pPktCtrlBlk, eAckPolicy);
    849 
    850 	/* Update packet length in the descriptor according to HW interface requirements */
    851     uLastWordPad = txCtrl_TranslateLengthToFw (pPktCtrlBlk);
    852 
    853     /* Set the descriptor attributes */
    854 	uTxDescAttr  = pTxCtrl->dataPktDescAttrib;
    855     uTxDescAttr |= uLastWordPad << TX_ATTR_OFST_LAST_WORD_PAD;
    856 	uTxDescAttr |= pTxCtrl->dataRatePolicy[uAc] << TX_ATTR_OFST_RATE_POLICY;
    857 	if (uHdrAlignPad)
    858 	{
    859 		uTxDescAttr |= TX_ATTR_HEADER_PAD;
    860 	}
    861 	if (uBackpressure)
    862     {
    863 		uTxDescAttr |= TX_ATTR_TX_CMPLT_REQ;  /* Request immediate Tx-Complete from FW if the AC is busy */
    864     }
    865     if (TI_UNLIKELY(pTxCtrl->currBssType == BSS_INDEPENDENT) &&
    866         (pPktCtrlBlk->tTxPktParams.uFlags & TX_CTRL_FLAG_MULTICAST))
    867 	{
    868         /* If packet is Broadcast in IBSS, overwrite rate policy with mgmt value. */
    869 		uTxDescAttr &= ~TX_ATTR_RATE_POLICY;
    870 		uTxDescAttr |= pTxCtrl->mgmtRatePolicy[uAc] << TX_ATTR_OFST_RATE_POLICY;
    871 	}
    872 	pPktCtrlBlk->tTxDescriptor.txAttr = ENDIAN_HANDLE_WORD(uTxDescAttr);
    873 
    874     /* Translate packet timestamp to FW time (also updates lifeTime and driverHandlingTime) */
    875     txCtrl_TranslateTimeToFw (pTxCtrl, pPktCtrlBlk, pTxCtrl->aMsduLifeTimeTu[uAc]);
    876 
    877     /* Indicate that the packet is transfered to the FW, and the descriptor fields are in FW format! */
    878     pPktCtrlBlk->tTxPktParams.uFlags |= TX_CTRL_FLAG_SENT_TO_FW;
    879 
    880 #ifdef TI_DBG
    881 	pTxCtrl->dbgPktSeqNum++;
    882 	pTxCtrl->dbgCounters.dbgNumPktsXfered[uAc]++;	/* Count packets sent to Xfer. */
    883 #endif
    884 }
    885 
    886 
    887 /***************************************************************************
    888 *                       txCtrl_BuildMgmtPkt
    889 ****************************************************************************
    890 * DESCRIPTION:  Prepare the Mgmt-Queue packet control-block including the Tx-descriptor.
    891 ***************************************************************************/
    892 static void txCtrl_BuildMgmtPkt (txCtrl_t *pTxCtrl, TTxCtrlBlk *pPktCtrlBlk, TI_UINT32 uAc)
    893 {
    894 	TI_UINT32 uHdrAlignPad; /* Num of bytes added between Tx-descriptor and header for alignment (0 or 2). */
    895     TI_UINT16 uLastWordPad; /* Num of bytes added at the end of the packet for 4 bytes alignment */
    896 	TI_UINT16 uTxDescAttr;
    897 	TI_UINT16 uRatePolicy;
    898 	TI_UINT8  uPktType = pPktCtrlBlk->tTxPktParams.uPktType;
    899 	dot11_header_t *pDot11Header;
    900 
    901 	/* If EAPOL packet (Ethernet), build header (including MAC,SNAP,security pad & alignment pad). */
    902 	if (uPktType == TX_PKT_TYPE_EAPOL)
    903 	{
    904         uHdrAlignPad = txCtrl_BuildDataPktHdr ((TI_HANDLE)pTxCtrl, pPktCtrlBlk, ACK_POLICY_LEGACY);
    905 
    906 		uRatePolicy = pTxCtrl->dataRatePolicy[uAc];
    907 	}
    908 
    909 	/*  Other types are already in WLAN format so copy header from Wbuf to Ctrl-Blk. */
    910 	else
    911 	{
    912 		TI_UINT32 uHdrLen = pPktCtrlBlk->tTxnStruct.aLen[0];
    913 		TI_UINT32 uHdrLenDelta; /* Add the header pad (2 bytes) and Tx-Descriptor length */
    914 
    915 		/*
    916          * Update the length fields to include the header pad and the Tx-Descriptor.
    917          * Note: The mgmt-queue provides the header length without the alignment pad, so if
    918 		 *       it's not 4-byte aligned, a 2-bytes pad was added at the header beginning.
    919 		 */
    920 		uHdrAlignPad = (uHdrLen & ALIGN_4BYTE_MASK) ? HEADER_PAD_SIZE : 0;
    921         uHdrLenDelta = uHdrAlignPad + sizeof(TxIfDescriptor_t);
    922         pPktCtrlBlk->tTxnStruct.aBuf[0]   -= uHdrLenDelta;
    923         pPktCtrlBlk->tTxnStruct.aLen[0]   += uHdrLenDelta;
    924         pPktCtrlBlk->tTxDescriptor.length += uHdrLenDelta;
    925 
    926 		uRatePolicy = pTxCtrl->mgmtRatePolicy[uAc];
    927 
    928         if (uPktType == TX_PKT_TYPE_WLAN_DATA)
    929 		{
    930 			/* If QoS mode, update TID in QoS header in case it was downgraded. */
    931 			/* Note: Qos-hdr update for EAPOL is done in txCtrl_BuildDataPktHeader() and doesn't exist in mgmt. */
    932 			if (pTxCtrl->headerConverMode == HDR_CONVERT_QOS)
    933 			{
    934 				TI_UINT16 tidWord = (TI_UINT16)pPktCtrlBlk->tTxDescriptor.tid;
    935 				pDot11Header = (dot11_header_t *)&(pPktCtrlBlk->aPktHdr[uHdrAlignPad]);
    936 				COPY_WLAN_WORD(&pDot11Header->qosControl, &tidWord); /* copy with endianess handling. */
    937 			}
    938 		}
    939 	}
    940 
    941 	/* Update packet length in the descriptor according to HW interface requirements */
    942     uLastWordPad = txCtrl_TranslateLengthToFw (pPktCtrlBlk);
    943 
    944 	/* Set fields in the descriptor attributes bitmap. */
    945 	uTxDescAttr  = uRatePolicy << TX_ATTR_OFST_RATE_POLICY;
    946 	uTxDescAttr |= pTxCtrl->txSessionCount << TX_ATTR_OFST_SESSION_COUNTER;
    947     uTxDescAttr |= uLastWordPad << TX_ATTR_OFST_LAST_WORD_PAD;
    948 	uTxDescAttr |= TX_ATTR_TX_CMPLT_REQ;
    949 	if (uHdrAlignPad)
    950     {
    951 		uTxDescAttr |= TX_ATTR_HEADER_PAD;
    952     }
    953 	pPktCtrlBlk->tTxDescriptor.txAttr = ENDIAN_HANDLE_WORD(uTxDescAttr);
    954 
    955     /* Translate packet timestamp to FW time (also updates lifeTime and driverHandlingTime) */
    956     txCtrl_TranslateTimeToFw (pTxCtrl, pPktCtrlBlk, MGMT_PKT_LIFETIME_TU);
    957 
    958     /* Indicate that the packet is transfered to the FW, and the descriptor fields are in FW format! */
    959     pPktCtrlBlk->tTxPktParams.uFlags |= TX_CTRL_FLAG_SENT_TO_FW;
    960 
    961 #ifdef TI_DBG
    962 	pTxCtrl->dbgPktSeqNum++;
    963 	pTxCtrl->dbgCounters.dbgNumPktsXfered[uAc]++;	/* Count packets sent to Xfer. */
    964 #endif
    965 }
    966 
    967 
    968 /***************************************************************************
    969 *                           txCtrl_UpdateHighestAdmittedAcTable
    970 ****************************************************************************
    971 * DESCRIPTION:  This function updates the table that provides for each requested AC
    972 *				  the highest AC that can be currently used, as follows:
    973 *					If requested AC is admitted use it.
    974 *					If not, find highest AC below it that doesn't require admission.
    975 *				This function should be called opon the following events:
    976 *					1) Init
    977 *					2) ACs admission required change (upon association)
    978 *					3) ACs admission state change (upon association and add/delete Tspec).
    979 *
    980 ***************************************************************************/
    981 static void txCtrl_UpdateHighestAdmittedAcTable (txCtrl_t *pTxCtrl)
    982 {
    983 	int			 inputIdx;
    984 	int			 outputIdx;
    985 	EAcTrfcType inputAc;
    986 	EAcTrfcType outputAc;
    987 
    988 	/* Loop over all ACs in priority order (BE is higher priority than BK). */
    989 	for (inputIdx = 0; inputIdx < MAX_NUM_OF_AC; inputIdx++)
    990 	{
    991 		inputAc = priorityOrderedAc[inputIdx];
    992 
    993 		/* If input AC is admitted, use it. */
    994 		if(pTxCtrl->admissionState[inputAc] == AC_ADMITTED)
    995 			pTxCtrl->highestAdmittedAc[inputAc] = inputAc;
    996 
    997 		/* If input AC is not admitted, find next highest priority AC that doesn't require admission. */
    998 		else
    999 		{
   1000 			/* Loop from input AC downward by priority order. */
   1001 			for (outputIdx = inputIdx; outputIdx >= 0; outputIdx--)
   1002 			{
   1003 				outputAc = priorityOrderedAc[outputIdx]; /* Get priority ordered AC. */
   1004 
   1005 				/* Break with first (highest) AC that doesn't require admission (we don't want to
   1006 				 *   redirect traffic to an AC that requires admission even if admitted for other traffic).
   1007 				 */
   1008 				if(pTxCtrl->admissionRequired[outputAc] == ADMISSION_NOT_REQUIRED)
   1009 					break;
   1010 			}
   1011 
   1012 			/* If we've found a valid AC insert it, else use BE as default. */
   1013 			if (outputIdx >= 0)
   1014 				pTxCtrl->highestAdmittedAc[inputAc] = outputAc;
   1015 			else
   1016 				pTxCtrl->highestAdmittedAc[inputAc] = QOS_AC_BE;
   1017 		}
   1018 	}
   1019 }
   1020 
   1021 
   1022 /***************************************************************************
   1023 *                           txCtrl_UpdateAcToTidMapping
   1024 ****************************************************************************
   1025 * DESCRIPTION:  This function updates the table that provides per each AC
   1026 *				  a bitmap of the TIDs that are mapped to it when transitting packets.
   1027 *				Note that this mapping considers the ACs admission states.
   1028 *				It is used for mapping ACs backpressure to TIDs (for updating the data/mgmt queues)
   1029 *
   1030 *				This table is updated after txCtrl_UpdateHighestAdmittedAcTable() is called!
   1031 *				It may also effect the backpressure picture seen by the Data-Queue and
   1032 *				  Mgmt-Queue, so they should be updated subsequently.
   1033 *
   1034 ***************************************************************************/
   1035 static void txCtrl_UpdateAcToTidMapping (txCtrl_t *pTxCtrl)
   1036 {
   1037 	TI_UINT32	tid;
   1038 	EAcTrfcType inputAc;
   1039 	EAcTrfcType admittedAc;
   1040 
   1041     os_memoryZero(pTxCtrl->hOs, (void *)&(pTxCtrl->admittedAcToTidMap[0]), sizeof(pTxCtrl->admittedAcToTidMap));
   1042 
   1043 	/* Loop over all TIDs. */
   1044 	for (tid = 0; tid < MAX_NUM_OF_802_1d_TAGS; tid++)
   1045 	{
   1046 		/* Find the AC that is used for transmitting this TID. */
   1047 		inputAc = (EAcTrfcType)WMEQosTagToACTable[tid];					/* Standard translation from TID to AC. */
   1048 		admittedAc = pTxCtrl->highestAdmittedAc[inputAc];	/* The actual AC that is used for Tx. */
   1049 
   1050 		/* Set the bit related to the TID in the correlated AC. */
   1051 		pTxCtrl->admittedAcToTidMap[admittedAc] |= 1 << tid;
   1052 	}
   1053 }
   1054 
   1055 
   1056 /***************************************************************************
   1057 *                           txCtrl_UpdateBackpressure
   1058 ****************************************************************************
   1059 * DESCRIPTION:  This function is called whenever the busy-TIDs bitmap may change,
   1060 *				  (except on packet-xmit - handled separately for performance).
   1061 *				This includes:
   1062 *					1) Init
   1063 *					2) ACs admission required change (upon association)
   1064 *					3) ACs admission state change (upon association and add/delete Tspec).
   1065 *					4) Tx-Complete - provides also freed ACs.
   1066 *
   1067 *				It updates the local bitmap, and the data-queue and mgmt-queue.
   1068 *
   1069 ***************************************************************************/
   1070 static void txCtrl_UpdateBackpressure (txCtrl_t *pTxCtrl, TI_UINT32 freedAcBitmap)
   1071 {
   1072 	TI_UINT32 busyAcBitmap = pTxCtrl->busyAcBitmap;
   1073 	TI_UINT32 busyTidBitmap = 0;
   1074 	TI_UINT32 ac = 0;
   1075 
   1076 
   1077 	busyAcBitmap &= ~freedAcBitmap;			/* Clear backpressure bits of freed ACs. */
   1078 	pTxCtrl->busyAcBitmap = busyAcBitmap;	/* Save new bitmap before manipulating it. */
   1079 
   1080 	/* Loop while there are busy ACs. */
   1081 	while (busyAcBitmap)
   1082 	{
   1083 		/* If the AC is busy, add its related TIDs to the total busy TIDs bitmap. */
   1084 		if (busyAcBitmap & 1)
   1085 			busyTidBitmap |= pTxCtrl->admittedAcToTidMap[ac];
   1086 
   1087 		/* Move to next AC. */
   1088 		busyAcBitmap = busyAcBitmap >> 1;
   1089 		ac++;
   1090 	}
   1091 
   1092     TRACE6(pTxCtrl->hReport, REPORT_SEVERITY_INFORMATION, "txCtrl_UpdateBackpressure(): busyTidBitmap = 0x%x, busyAcBitmap = 0x%x, HighestAdmittedAc[3,2,1,0] = %d, %d, %d, %d\n", busyTidBitmap, pTxCtrl->busyAcBitmap, pTxCtrl->highestAdmittedAc[3], 		pTxCtrl->highestAdmittedAc[2], pTxCtrl->highestAdmittedAc[1], pTxCtrl->highestAdmittedAc[0]);
   1093 
   1094 	/* Save new bitmap and update the data-queue and mgmt-queue. */
   1095 	pTxCtrl->busyTidBitmap = busyTidBitmap;
   1096 	txDataQ_UpdateBusyMap (pTxCtrl->hTxDataQ, busyTidBitmap);
   1097 	txMgmtQ_UpdateBusyMap (pTxCtrl->hTxMgmtQ, busyTidBitmap);
   1098 }
   1099 
   1100 
   1101 /****************************************************************************
   1102  *                      txCtrl_SetTxDelayCounters()
   1103  ****************************************************************************
   1104  * DESCRIPTION:          Update transmission path delay counters.
   1105 *
   1106 * INPUTS:       hTxCtrl - the object
   1107 *               ac - the AC to count delay for
   1108 *				fwDelay - the time consumed in FW for packet transmission
   1109 *				driverDelay - the time consumed in driver for packet transmission
   1110 *
   1111 * OUTPUT:
   1112 *
   1113 * RETURNS:
   1114  ****************************************************************************/
   1115 
   1116 #ifdef XCC_MODULE_INCLUDED  /* Needed only for XCC-V4 */
   1117 
   1118 static void txCtrl_SetTxDelayCounters (txCtrl_t *pTxCtrl,
   1119                                        TI_UINT32 ac,
   1120                                        TI_UINT32 fwDelay,
   1121                                        TI_UINT32 driverDelay,
   1122                                        TI_UINT32 mediumDelay)
   1123 {
   1124 	int     rangeIndex;
   1125 	TI_UINT32  totalTxDelayUsec = fwDelay + driverDelay;
   1126 
   1127 	/* Increment the delay range counter that the current packet Tx delay falls in. */
   1128 	for (rangeIndex = TX_DELAY_RANGE_MIN; rangeIndex <= TX_DELAY_RANGE_MAX; rangeIndex++)
   1129 	{
   1130 		if ( (totalTxDelayUsec >= txDelayRangeStart[rangeIndex]) &&
   1131 			 (totalTxDelayUsec <= txDelayRangeEnd  [rangeIndex]) )
   1132 		{
   1133 			pTxCtrl->txDataCounters[ac].txDelayHistogram[rangeIndex]++;
   1134 			break;
   1135 		}
   1136 	}
   1137 
   1138 	/* Update total delay and FW delay sums and packets number for average delay calculation. */
   1139 	/* Note: Accumulate Total-Delay in usec to avoid division per packet (convert to msec
   1140 	         only when results are requested by user). */
   1141 	if (pTxCtrl->SumTotalDelayUs[ac] < 0x7FFFFFFF) /* verify we are not close to the edge. */
   1142 	{
   1143 		pTxCtrl->txDataCounters[ac].NumPackets++;
   1144 		pTxCtrl->SumTotalDelayUs[ac] += totalTxDelayUsec;
   1145         pTxCtrl->txDataCounters[ac].SumFWDelayUs += fwDelay;
   1146         pTxCtrl->txDataCounters[ac].SumMacDelayUs += mediumDelay;
   1147 	}
   1148 	else  /* If we get close to overflow, restart average accumulation. */
   1149 	{
   1150 		pTxCtrl->txDataCounters[ac].NumPackets = 1;
   1151 		pTxCtrl->SumTotalDelayUs[ac] = totalTxDelayUsec;
   1152         pTxCtrl->txDataCounters[ac].SumFWDelayUs = fwDelay;
   1153         pTxCtrl->txDataCounters[ac].SumMacDelayUs = mediumDelay;
   1154 	}
   1155 }
   1156 
   1157 #endif /* XCC_MODULE_INCLUDED */
   1158 
   1159 
   1160 
   1161 /***************************************************************************
   1162 *                       txCtrl_UpdateTxCounters
   1163 ****************************************************************************
   1164 * DESCRIPTION:  Update Tx statistics counters according to the transmitted packet.
   1165 ***************************************************************************/
   1166 static void txCtrl_UpdateTxCounters (txCtrl_t *pTxCtrl,
   1167                                      TxResultDescriptor_t *pTxResultInfo,
   1168                                      TTxCtrlBlk *pPktCtrlBlk,
   1169                                      TI_UINT32 ac,
   1170                                      TI_BOOL bIsDataPkt)
   1171 {
   1172 	TI_UINT32 pktLen;
   1173     TI_UINT32 dataLen;
   1174 	TI_UINT32 retryHistogramIndex;
   1175     TI_UINT16 EventMask = 0;
   1176 
   1177     pktLen = (TI_UINT32)ENDIAN_HANDLE_WORD(pPktCtrlBlk->tTxDescriptor.length);
   1178     pktLen = pktLen << 2;
   1179 
   1180 #ifdef TI_DBG
   1181 
   1182 	/* update debug counters. */
   1183 	pTxCtrl->dbgCounters.dbgNumTxCmplt[ac]++;
   1184 	if (pTxResultInfo->status == TX_SUCCESS)
   1185 	{
   1186 		pTxCtrl->dbgCounters.dbgNumTxCmpltOk[ac]++;
   1187 		pTxCtrl->dbgCounters.dbgNumTxCmpltOkBytes[ac] += pktLen;
   1188 	}
   1189 	else
   1190 	{
   1191 		pTxCtrl->dbgCounters.dbgNumTxCmpltError[ac]++;
   1192 
   1193 		if (pTxResultInfo->status == TX_HW_ERROR        ||
   1194 			pTxResultInfo->status == TX_KEY_NOT_FOUND   ||
   1195 			pTxResultInfo->status == TX_PEER_NOT_FOUND)
   1196 		{
   1197 TRACE1(pTxCtrl->hReport, REPORT_SEVERITY_ERROR, "txCtrl_UpdateTxCounters(): TxResult = %d !!!\n", pTxResultInfo->status);
   1198 		}
   1199         else
   1200         {
   1201 TRACE1(pTxCtrl->hReport, REPORT_SEVERITY_WARNING, "txCtrl_UpdateTxCounters(): TxResult = %d !!!\n", pTxResultInfo->status);
   1202         }
   1203 	}
   1204 
   1205 #endif /* TI_DBG */
   1206 
   1207 	/* If it's not a data packet, exit (the formal statistics are only on network stack traffic). */
   1208 	if ( !bIsDataPkt )
   1209 		return;
   1210 
   1211 	if (pTxResultInfo->status == TX_SUCCESS)
   1212 	{
   1213 		/* update the retry histogram */
   1214 		retryHistogramIndex = (pTxResultInfo->ackFailures >= TX_RETRY_HISTOGRAM_SIZE) ?
   1215 							   (TX_RETRY_HISTOGRAM_SIZE - 1) : pTxResultInfo->ackFailures;
   1216 		pTxCtrl->txDataCounters[ac].RetryHistogram[retryHistogramIndex]++;
   1217 
   1218 #ifdef XCC_MODULE_INCLUDED
   1219 		/* update delay histogram */
   1220 		txCtrl_SetTxDelayCounters (pTxCtrl,
   1221         						   ac,
   1222         						   ENDIAN_HANDLE_LONG(pTxResultInfo->fwHandlingTime),
   1223         						   pPktCtrlBlk->tTxPktParams.uDriverDelay,
   1224         						   ENDIAN_HANDLE_LONG(pTxResultInfo->mediumDelay));
   1225 #endif
   1226 
   1227 		if (pTxCtrl->headerConverMode == HDR_CONVERT_QOS)
   1228         {
   1229 			dataLen = pktLen - (WLAN_WITH_SNAP_QOS_HEADER_MAX_SIZE - ETHERNET_HDR_LEN);
   1230         }
   1231         else
   1232         {
   1233 			dataLen = pktLen - (WLAN_WITH_SNAP_HEADER_MAX_SIZE - ETHERNET_HDR_LEN);
   1234         }
   1235 
   1236         if (pPktCtrlBlk->tTxPktParams.uFlags & TX_CTRL_FLAG_MULTICAST)
   1237         {
   1238             if (pPktCtrlBlk->tTxPktParams.uFlags & TX_CTRL_FLAG_BROADCAST)
   1239             {
   1240                 /* Broadcast frame */
   1241                 pTxCtrl->txDataCounters[ac].BroadcastFramesXmit++;
   1242                 pTxCtrl->txDataCounters[ac].BroadcastBytesXmit += dataLen;
   1243                 EventMask |= BROADCAST_BYTES_XFER;
   1244                 EventMask |= BROADCAST_FRAMES_XFER;
   1245             }
   1246             else
   1247             {
   1248                 /* Multicast Address */
   1249                 pTxCtrl->txDataCounters[ac].MulticastFramesXmit++;
   1250                 pTxCtrl->txDataCounters[ac].MulticastBytesXmit += dataLen;
   1251                 EventMask |= MULTICAST_BYTES_XFER;
   1252                 EventMask |= MULTICAST_FRAMES_XFER;
   1253             }
   1254         }
   1255         else
   1256         {
   1257             /* Save last data Tx rate for applications' query */
   1258             EHwBitRate eHwTxRate = ENDIAN_HANDLE_LONG((EHwBitRate)(pTxResultInfo->rate));
   1259             rate_PolicyToDrv (eHwTxRate, &pTxCtrl->eCurrentTxRate);
   1260 
   1261             /* Directed frame statistics */
   1262             pTxCtrl->txDataCounters[ac].DirectedFramesXmit++;
   1263             pTxCtrl->txDataCounters[ac].DirectedBytesXmit += dataLen;
   1264             EventMask |= DIRECTED_BYTES_XFER;
   1265             EventMask |= DIRECTED_FRAMES_XFER;
   1266         }
   1267 
   1268         pTxCtrl->txDataCounters[ac].XmitOk++;
   1269         EventMask |= XFER_OK;
   1270 
   1271 		/* update the max consecutive retry failures (if needed) */
   1272 		if (pTxCtrl->currentConsecutiveRetryFail > pTxCtrl->txDataCounters[ac].MaxConsecutiveRetryFail)
   1273         {
   1274 			pTxCtrl->txDataCounters[ac].MaxConsecutiveRetryFail = pTxCtrl->currentConsecutiveRetryFail;
   1275         }
   1276 		pTxCtrl->currentConsecutiveRetryFail = 0;
   1277 
   1278 		if(pTxCtrl->TxEventDistributor)
   1279         {
   1280 			DistributorMgr_EventCall(pTxCtrl->TxEventDistributor, EventMask, dataLen);
   1281         }
   1282 	}
   1283 	else	/* Handle Errors */
   1284 	{
   1285 		/*
   1286 			NOTE: if the FW sets more then 1 error bit  at a time change the error handling
   1287 			code below
   1288 		*/
   1289 		if (pTxResultInfo->status == TX_RETRY_EXCEEDED)
   1290 		{
   1291 			pTxCtrl->txDataCounters[ac].RetryFailCounter++;
   1292 			pTxCtrl->currentConsecutiveRetryFail++;
   1293 		}
   1294 		else if (pTxResultInfo->status == TX_TIMEOUT)
   1295 		{
   1296 			pTxCtrl->txDataCounters[ac].TxTimeoutCounter++;
   1297 		}
   1298 		else
   1299 		{
   1300 			pTxCtrl->txDataCounters[ac].OtherFailCounter++;
   1301 		}
   1302 	}
   1303 }
   1304 
   1305 
   1306 /***************************************************************************
   1307 *                           txCtrl_notifyFwReset                           *
   1308 ****************************************************************************
   1309 * DESCRIPTION:  Go over all CtrlBlk entries and free the active ones including the packet.
   1310 ***************************************************************************/
   1311 TI_STATUS txCtrl_NotifyFwReset (TI_HANDLE hTxCtrl)
   1312 {
   1313 	txCtrl_t   *pTxCtrl = (txCtrl_t *)hTxCtrl;
   1314 	TI_UINT32  entry;
   1315 	TTxCtrlBlk *pPktCtrlBlk;
   1316 
   1317 	pTxCtrl->busyAcBitmap = 0; /* clean busy bitmap */
   1318 	txCtrl_UpdateBackpressure(pTxCtrl, 0);
   1319 
   1320 	for (entry = 0; entry < CTRL_BLK_ENTRIES_NUM-1; entry++)
   1321 	{
   1322 		/* Get packet ctrl-block by desc-ID. */
   1323 		pPktCtrlBlk = TWD_txCtrlBlk_GetPointer(pTxCtrl->hTWD, entry);
   1324 		if (pPktCtrlBlk->pNextFreeEntry == 0)
   1325 		{
   1326 		    /* Don't free if the packet still in tx input queues */
   1327 		    if ((pPktCtrlBlk->tTxPktParams.uFlags & TX_CTRL_FLAG_SENT_TO_FW))
   1328 		    {
   1329 		        /* Free the packet resources (packet and CtrlBlk)  */
   1330 		        txCtrl_FreePacket (pTxCtrl, pPktCtrlBlk, TI_NOK);
   1331 		    }
   1332 		}
   1333 	}
   1334 
   1335 	return TI_OK;
   1336 } /* txCtrl_notifyFwReset */
   1337 
   1338 
   1339 /***************************************************************************
   1340 *                           txCtrl_CheckForTxStuck                         *
   1341 ****************************************************************************
   1342 * DESCRIPTION:  Check if there are stale packets in the TxCtrlTable.
   1343 * The criterion for staleness is function of life time (2 times the longest life time)
   1344 * Note that only packets that were not sent to the FW are checked for simplicity!
   1345 ***************************************************************************/
   1346 TI_STATUS txCtrl_CheckForTxStuck (TI_HANDLE hTxCtrl)
   1347 {
   1348 	txCtrl_t   *pTxCtrl = (txCtrl_t *)hTxCtrl;
   1349 	TI_UINT32  entry;
   1350 	TTxCtrlBlk *pPktCtrlBlk;
   1351 	TI_UINT32  uPktAge;		/* Time in uSec since packet start time. */
   1352 
   1353 	for (entry = 0; entry < CTRL_BLK_ENTRIES_NUM-1; entry++)
   1354 	{
   1355 		/* Get packet ctrl-block by desc-ID. */
   1356 		pPktCtrlBlk = TWD_txCtrlBlk_GetPointer(pTxCtrl->hTWD, entry);
   1357 
   1358         /* If entry is in use */
   1359 		if (pPktCtrlBlk->pNextFreeEntry == 0)
   1360 		{
   1361             /* If the packet wasn't sent to the FW yet (time is in host format) */
   1362             if ((pPktCtrlBlk->tTxPktParams.uFlags & TX_CTRL_FLAG_SENT_TO_FW) == 0)
   1363             {
   1364                 /* If packet age is more than twice the maximum lifetime, return NOK */
   1365                 uPktAge = os_timeStampMs (pTxCtrl->hOs) - pPktCtrlBlk->tTxDescriptor.startTime;
   1366                 if (uPktAge > ((MGMT_PKT_LIFETIME_TU << SHIFT_BETWEEN_TU_AND_USEC) * 2))
   1367                 {
   1368                     return TI_NOK; /* call for recovery */
   1369                 }
   1370             }
   1371 		}
   1372 	}
   1373 
   1374 	return TI_OK;
   1375 } /* txCtrl_FailureTest */
   1376 
   1377 
   1378 
   1379