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