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