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