• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 */
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 	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 *************************************************************************/
txCtrl_SetDefaults(TI_HANDLE hTxCtrl,txDataInitParams_t * txDataInitParams)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 ***************************************************************************/
txCtrl_Unload(TI_HANDLE hTxCtrl)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 ********************************************************************************/
txCtrl_XmitData(TI_HANDLE hTxCtrl,TTxCtrlBlk * pPktCtrlBlk)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 ********************************************************************************/
txCtrl_XmitMgmt(TI_HANDLE hTxCtrl,TTxCtrlBlk * pPktCtrlBlk)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 ***************************************************************************/
txCtrl_UpdateQueuesMapping(TI_HANDLE hTxCtrl)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 ***************************************************************************/
txCtrl_AllocPacketBuffer(TI_HANDLE hTxCtrl,TTxCtrlBlk * pPktCtrlBlk,TI_UINT32 uPacketLen)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 ***************************************************************************/
txCtrl_FreePacket(TI_HANDLE hTxCtrl,TTxCtrlBlk * pPktCtrlBlk,TI_STATUS eStatus)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 *************************************************************************/
txCtrl_TxCompleteCb(TI_HANDLE hTxCtrl,TxResultDescriptor_t * pTxResultInfo)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 
txCtrl_BuildDataPktHdr(TI_HANDLE hTxCtrl,TTxCtrlBlk * pPktCtrlBlk,AckPolicy_e eAckPolicy)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 ***************************************************************************/
txCtrl_BuildDataPkt(txCtrl_t * pTxCtrl,TTxCtrlBlk * pPktCtrlBlk,TI_UINT32 uAc,TI_UINT32 uBackpressure)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 ***************************************************************************/
txCtrl_BuildMgmtPkt(txCtrl_t * pTxCtrl,TTxCtrlBlk * pPktCtrlBlk,TI_UINT32 uAc)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 ***************************************************************************/
txCtrl_UpdateHighestAdmittedAcTable(txCtrl_t * pTxCtrl)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 ***************************************************************************/
txCtrl_UpdateAcToTidMapping(txCtrl_t * pTxCtrl)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 ***************************************************************************/
txCtrl_UpdateBackpressure(txCtrl_t * pTxCtrl,TI_UINT32 freedAcBitmap)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 
txCtrl_SetTxDelayCounters(txCtrl_t * pTxCtrl,TI_UINT32 ac,TI_UINT32 fwDelay,TI_UINT32 driverDelay,TI_UINT32 mediumDelay)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 ***************************************************************************/
txCtrl_UpdateTxCounters(txCtrl_t * pTxCtrl,TxResultDescriptor_t * pTxResultInfo,TTxCtrlBlk * pPktCtrlBlk,TI_UINT32 ac,TI_BOOL bIsDataPkt)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 ***************************************************************************/
txCtrl_NotifyFwReset(TI_HANDLE hTxCtrl)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 ***************************************************************************/
txCtrl_CheckForTxStuck(TI_HANDLE hTxCtrl)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