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