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
72static void   txCtrl_TxCompleteCb (TI_HANDLE hTxCtrl, TxResultDescriptor_t *pTxResultInfo);
73static void   txCtrl_BuildDataPkt (txCtrl_t *pTxCtrl, TTxCtrlBlk *pPktCtrlBlk,
74                                   TI_UINT32 uAc, TI_UINT32 uBackpressure);
75static void	  txCtrl_BuildMgmtPkt (txCtrl_t *pTxCtrl, TTxCtrlBlk *pPktCtrlBlk, TI_UINT32 uAc);
76static void   txCtrl_UpdateHighestAdmittedAcTable (txCtrl_t *pTxCtrl);
77static void   txCtrl_UpdateAcToTidMapping (txCtrl_t *pTxCtrl);
78static void   txCtrl_UpdateBackpressure (txCtrl_t *pTxCtrl, TI_UINT32 freedAcBitmap);
79static 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 */
85static 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 */
106static 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 */
132static 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*************************************************************************/
164TI_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***************************************************************************/
190void 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*************************************************************************/
268TI_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***************************************************************************/
296TI_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********************************************************************************/
330TI_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
345TRACE3(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
398TRACE2(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********************************************************************************/
428TI_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
480TRACE1(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***************************************************************************/
508void 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***************************************************************************/
530void *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***************************************************************************/
560void 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*************************************************************************/
604static 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	{
620TRACE2(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	}
624TRACE3(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
673TI_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***************************************************************************/
839static 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***************************************************************************/
892static 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***************************************************************************/
981static 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***************************************************************************/
1035static 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***************************************************************************/
1070static 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
1118static 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***************************************************************************/
1166static 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		{
1197TRACE1(pTxCtrl->hReport, REPORT_SEVERITY_ERROR, "txCtrl_UpdateTxCounters(): TxResult = %d !!!\n", pTxResultInfo->status);
1198		}
1199        else
1200        {
1201TRACE1(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***************************************************************************/
1311TI_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***************************************************************************/
1346TI_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