Home | History | Annotate | Download | only in Tx
      1 /****************************************************************************
      2 **+-----------------------------------------------------------------------+**
      3 **|                                                                       |**
      4 **| Copyright(c) 1998 - 2008 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 /*                                                                         */
     37 /*      MODULE: Tx.c                                                       */
     38 /*    PURPOSE:  Tx module functions                                        */
     39 /*                                                                         */
     40 /***************************************************************************/
     41 #include "osTIType.h"
     42 #include "paramIn.h"
     43 #include "paramOut.h"
     44 #include "osApi.h"
     45 #include "tx.h"
     46 #include "DataCtrl_Api.h"
     47 #include "siteMgrApi.h"
     48 #include "802_11Defs.h"
     49 #include "Ethernet.h"
     50 /* GWSI_LAYER */
     51 #include "Core_AdaptTx.h"
     52 
     53 #include "memMngrEx.h"
     54 #include "report.h"
     55 #include "utils.h"
     56 #include "measurementMgrApi.h"
     57 #include "TI_IPC_Api.h"
     58 #include "EvHandler.h"
     59 #include "qosMngr_API.h"
     60 #include "PowerMgr_API.h"
     61 #include "bufferPoolApi.h"
     62 #include "TNETW_Driver_api.h"
     63 
     64 /*
     65 This is an Ethernet Version 2 frame:
     66 
     67        +--------------+
     68        |              | The destination address is a six byte Media Access
     69        | Destination  | Control (MAC) address, usually burned into the
     70        |   6 bytes    | ROM of the Ethernet card.
     71        +--------------+
     72        |              | The source address is a six byte MAC address, and
     73        |   Source     | can signify a physical station or a broadcast.
     74        |   6 bytes    |
     75        +--------------+
     76        |     Type     | The Type field it must be grater then 1500 dec.
     77        |    2 bytes   |
     78        +--------------+
     79        |              |  Any higher layer information is placed in the
     80        |    Data      |  data field, which could contain protocol
     81        |              |  information or user data.
     82        ~              ~
     83        ~              ~
     84        |  46 to 1500  |
     85        |    bytes     |
     86        |              |
     87        +--------------+
     88        |     FCS      |
     89        |   4 bytes    |
     90        +--------------+
     91 
     92 
     93 
     94 */
     95 /*
     96 
     97         802.2 SNAP DATA Frame
     98        +----------------+
     99        |                |
    100        |  Destination   |
    101        |    6 bytes     |
    102        +----------------+
    103        |                |
    104        |     Source     |
    105        |    6 bytes     |
    106        +----------------+
    107        |  Frame Length  | Must be <= 1500 Dec.
    108        |    2 bytes     |
    109        +----------------+
    110        |  DSAP - 1 byte | = 0xAA ( SNAP )
    111        +----------------+
    112        |  SSAP - 1 byte | = 0xAA ( SNAP )
    113        +----------------+
    114        |Control - 1 byte| = 0x03
    115        +----------------+
    116        | OUI - 3 bytes  | = 0x0
    117        |                |
    118        +----------------+
    119        | Type - 2 bytes |  = Ethernet type (IP=0x0800)
    120        +----------------+
    121        |                |
    122        |      Data      |
    123        |                |
    124        ~                ~
    125        ~                ~
    126        |   46 to 1500   |
    127        |     bytes      |
    128        |                |
    129        +----------------+
    130        |      FCS       |
    131        |    4 bytes     |
    132        +----------------+
    133 
    134 
    135 
    136 
    137         802.11 DATA Frame
    138        +----------------+
    139        |                |
    140        |  Frame Control |
    141        |    2 bytes     |
    142        +----------------+
    143        |                |
    144        |  Duration ID   |
    145        |    2 bytes     |
    146        +----------------+
    147        |                |
    148        |   Address 1    |
    149        |    6 bytes     |
    150        +----------------+
    151        |                |
    152        |   Address 2    |
    153        |    6 bytes     |
    154        +----------------+
    155        |                |
    156        |   Address 3    |
    157        |    6 bytes     |
    158        +----------------+
    159        |                |
    160        | Sequence Cntrl |
    161        |    2 bytes     |
    162        +----------------+
    163        |                |
    164        |   Address 4    |
    165        |    6 bytes     |
    166        +----------------+
    167        |  DSAP - 1 byte | = 0xAA ( SNAP )
    168        +----------------+
    169        |  SSAP - 1 byte | = 0xAA ( SNAP )
    170        +----------------+
    171        |Control - 1 byte| = 0x03
    172        +----------------+
    173        | OUI - 3 bytes  | = 0x0
    174        |                |
    175        +----------------+
    176        | Type - 2 bytes |  = Ethernet type (IP=0x0800)
    177        +----------------+
    178        |                |
    179        |      Data      |
    180        |                |
    181        ~                ~
    182        ~                ~
    183        |   46 to 1500   |
    184        |     bytes      |
    185        |                |
    186        +----------------+
    187        |      FCS       |
    188        |    4 bytes     |
    189        +----------------+
    190 
    191 */
    192 
    193 /* Tx queue selection definitions */
    194 #define Q_LEAST_WEIGHT              0xFFFFFFFF /* Use least possible weight as init value (highest value is lowest priority). */
    195 #define Q_SELECTION_HISTORY_LEVEL   5   /* Count down from this value if queue is selected to Tx. */
    196 
    197 
    198 #define MANAGEMENT_QUEUE_SIZE           16
    199 
    200 #define DEFAULT_QUEUE_TO_HAL            1
    201 
    202 #define EAPOL_PACKET                    0x8E88
    203 
    204 /* defined in QosMngr.c - used to update QosControl (userPriority) of a given packet after it has been "downgraded" due to admission control */
    205 extern UINT8 wmeAcToUpIndex[MAX_NUM_OF_AC];
    206 
    207 /* defined in qosMngr.c - used to identify voice packets in NON QOS APs */
    208 extern int WMEQosTagToACTable[MAX_NUM_OF_802_1d_TAGS];
    209 
    210 /* this macro accesses the WME Tag-to-AC conversion array in order to enable identifying voice packets even on NON QOS APs */
    211 #define GET_WME_AC_TYPE_FROM_MSDU(pMsdu)  (WMEQosTagToACTable[pMsdu->qosTag])
    212 
    213 #define GET_QUEUE_INDEX(pTxData,acIndex)  (pTxData->txDataAcTrfcCtrl[acIndex].QueueIndex)
    214 
    215 #define ABS(a)  (((int)(a) >= 0) ? (a) : -((int)(a)))
    216 
    217 static void txData_convertEthToWlanHeader (txData_t *pTxData, mem_MSDU_T *pMsdu);
    218 
    219 static TI_STATUS txData_schedulerSelectQueueToTransmitFrom( TI_HANDLE hTxData, MsduList_t** pMsduListPtr,UINT8 *selectedQueueIndex );
    220 
    221 static void txData_startTxSchedulerFromTimer(TI_HANDLE hTxData);
    222 
    223 static void txData_calcCreditFromTimer(TI_HANDLE hTxData);
    224 
    225 static void txData_UpdateTxCounters( TI_HANDLE hTxData, txCompleteAttr_t *pTxCompleteAttr );
    226 
    227 static void txData_SetTxDelayCounters( TI_HANDLE hTxData, UINT32 txQid, txCompleteAttr_t *pTxCompleteAttr, UINT32 driverDelay );
    228 
    229 static int txData_selectQueueAndUpdateUserPriority (txData_t *pTxData, mem_MSDU_T *pMsdu, int *selectedQueue, acTrfcType_e *selectedAc);
    230 
    231 static int txData_getHighestAdmittedAc(txData_t *pTxData, int startingAcIndex);
    232 
    233 static void txData_startVadTimer(TI_HANDLE hTxData, UINT16 voiceDuration);
    234 static void txData_stopVadTimer(TI_HANDLE hTxData);
    235 static void txData_setVadTimer(TI_HANDLE hTxData, BOOL vadEnabled, UINT16 duration);
    236 static void txData_resetVadTimer(TI_HANDLE hTxData);
    237 static void txData_vadTimeout(TI_HANDLE hTxData);
    238 #ifdef TI_DBG
    239 
    240 static void txData_printTxThroughputPerQueue(TI_HANDLE hTxData);
    241 
    242 static void txData_printTxAirThroughputPerQueue(TI_HANDLE hTxData);
    243 
    244 static void txData_printJitter(TI_HANDLE hTxData);
    245 
    246 #endif
    247 
    248 static BOOL txData_acVoPsPollMode(txData_t *pTxData);
    249 
    250 static UINT32 txDataTimeToMsduExpiry( TI_HANDLE htxData, mem_MSDU_T* pMsdu, UINT8 Qid);
    251 
    252 static UINT8 txData_GetAcIdFromQid(TI_HANDLE hTxData,UINT8 Qid);
    253 
    254 TI_STATUS txData_setMediumUsageThresholds(TI_HANDLE     hTxData,
    255                                       UINT8             acID,
    256                                       INT32             highMediumUsageThreshold,
    257                                       INT32             lowMediumUsageThreshold);
    258 
    259 static void txData_SetQidToAcTable(TI_HANDLE hTxData,UINT8 QidStart, UINT8 QidEnd,UINT8 AcId);
    260 
    261 /* The TX delay histogram ranges start and end in msec. */
    262 static UINT32 txDelayRangeStart[TX_DELAY_RANGES_NUM] = { 0,  1, 10, 20, 40, 60,  80, 100, 200 };
    263 static UINT32 txDelayRangeEnd  [TX_DELAY_RANGES_NUM] = { 1, 10, 20, 40, 60, 80, 100, 200, 0xFFFFFFFF };
    264 
    265 /*************************************************************************
    266 *                        txData_create                                   *
    267 **************************************************************************
    268 * DESCRIPTION:  This function initializes the Tx module.
    269 *
    270 * INPUT:        hOs - handle to Os Abstraction Layer
    271 *               txDataInitParams - Tx Data creation parameters
    272 * OUTPUT:
    273 *
    274 * RETURN:       Handle to the allocated Tx data control block
    275 *************************************************************************/
    276 TI_HANDLE txData_create(txDataInitParams_t *txDataInitParams,
    277                         TI_HANDLE hOs)
    278 {
    279 
    280     txData_t *hTxData;
    281     MsduList_t *mgmtMsduList;
    282     MsduList_t *dataMsduListArr[MAX_NUM_OF_TX_QUEUES];
    283     void* pTimer;
    284   #ifdef TI_DBG
    285     void* pThroughputTimer;
    286     void* pAirThroughputTimer;
    287     void* pJitterTimer;
    288   #endif
    289     void* pCreditTimer;
    290     void* pVadTimer;
    291     int queueIndex = 0;
    292 
    293 
    294     /* check parameters validity */
    295     if( txDataInitParams->txDataNumOfDataQueues > MAX_NUM_OF_TX_QUEUES ||
    296         txDataInitParams->txDataNumOfDataQueues <= 0 )
    297     {
    298         WLAN_OS_REPORT(("FATAL ERROR - UNABLE TO CREATE TX MODULE. Number of queues error = %d.",txDataInitParams->txDataNumOfDataQueues));
    299         return NULL;
    300     }
    301 
    302     /* allocate Tx module control block */
    303     hTxData = os_memoryAlloc(hOs, (sizeof(txData_t)));
    304 
    305     if(!hTxData)
    306         return NULL;
    307 
    308     /* reset tx control block */
    309     os_memoryZero(hOs, hTxData, (sizeof(txData_t)));
    310 
    311     /* allocate the buffer pool */
    312     hTxData->hBufferPool = bufferPool_create( hOs,
    313                                               HAL_CTRL_ACX_TX_DESC_DEF * MAX_NUM_OF_TX_QUEUES,
    314                                               sizeof(txPacketIdAttr_t) );
    315     if ( NULL == hTxData->hBufferPool )
    316     {
    317         utils_nullMemoryFree(hOs, hTxData, sizeof(txData_t));
    318         return NULL;
    319     }
    320 
    321     /* allocate Timer to use for scheduler trigger */
    322     pTimer = os_timerCreate(hOs, txData_startTxSchedulerFromTimer, hTxData);
    323     if(!pTimer)
    324     {
    325         bufferPool_destroy( hTxData->hBufferPool );
    326         utils_nullMemoryFree(hOs, hTxData, sizeof(txData_t));
    327         return NULL;
    328     }
    329 
    330     /* allocate Timer for vad operation */
    331     pVadTimer = os_timerCreate(hOs, txData_vadTimeout, hTxData);
    332     if(!pVadTimer)
    333     {
    334         bufferPool_destroy( hTxData->hBufferPool );
    335         utils_nullTimerDestroy (hOs, pTimer);
    336         utils_nullMemoryFree(hOs, hTxData, sizeof(txData_t));
    337         return NULL;
    338     }
    339   #ifdef TI_DBG
    340     /* allocate timer for debug throughput per queue */
    341     pThroughputTimer = os_timerCreate(hOs, txData_printTxThroughputPerQueue, hTxData);
    342     if(!pThroughputTimer)
    343     {
    344         bufferPool_destroy( hTxData->hBufferPool );
    345         utils_nullTimerDestroy(hOs, pTimer);
    346         utils_nullMemoryFree(hOs, hTxData, sizeof(txData_t));
    347         return NULL;
    348     }
    349 
    350     /* allocate timer for debug throughput per queue */
    351     pAirThroughputTimer = os_timerCreate (hOs, txData_printTxAirThroughputPerQueue, hTxData);
    352     if (!pAirThroughputTimer)
    353     {
    354         bufferPool_destroy (hTxData->hBufferPool);
    355         utils_nullTimerDestroy (hOs, pTimer);
    356         utils_nullTimerDestroy (hOs, pThroughputTimer);
    357         utils_nullMemoryFree (hOs, hTxData, sizeof(txData_t));
    358         return NULL;
    359     }
    360 
    361     /* allocate timer for debug throughput per queue */
    362     pJitterTimer = os_timerCreate (hOs, txData_printJitter, hTxData);
    363     if (!pJitterTimer)
    364     {
    365         bufferPool_destroy (hTxData->hBufferPool);
    366         utils_nullTimerDestroy (hOs, pTimer);
    367         utils_nullTimerDestroy (hOs, pThroughputTimer);
    368         utils_nullTimerDestroy (hOs, pAirThroughputTimer);
    369         utils_nullMemoryFree (hOs, hTxData, sizeof(txData_t));
    370         return NULL;
    371     }
    372   #endif
    373 
    374     /* allocate timer for credit calculation */
    375     pCreditTimer = os_timerCreate(hOs, txData_calcCreditFromTimer, hTxData);
    376     if(!pCreditTimer)
    377     {
    378         bufferPool_destroy( hTxData->hBufferPool );
    379         utils_nullTimerDestroy(hOs, pTimer);
    380       #ifdef TI_DBG
    381         utils_nullTimerDestroy(hOs, pThroughputTimer);
    382         utils_nullTimerDestroy(hOs, pAirThroughputTimer);
    383         utils_nullTimerDestroy(hOs, pJitterTimer);
    384       #endif
    385         utils_nullMemoryFree(hOs, hTxData, sizeof(txData_t));
    386         return NULL;
    387     }
    388 
    389     /* initialize management queue */
    390     mgmtMsduList = msduList_CreateNewMsduList( hOs);
    391     if(!mgmtMsduList)
    392     {
    393         bufferPool_destroy( hTxData->hBufferPool );
    394         utils_nullTimerDestroy(hOs, pTimer);
    395       #ifdef TI_DBG
    396         utils_nullTimerDestroy(hOs, pThroughputTimer);
    397         utils_nullTimerDestroy(hOs, pAirThroughputTimer);
    398         utils_nullTimerDestroy(hOs, pJitterTimer);
    399       #endif
    400         utils_nullTimerDestroy(hOs, pCreditTimer);
    401         utils_nullMemoryFree(hOs, hTxData, sizeof(txData_t));
    402         return NULL;
    403     }
    404 
    405     /* initialize tx data queues */
    406     for(queueIndex = 0 ; queueIndex < MAX_NUM_OF_TX_QUEUES ; queueIndex++)
    407     {
    408         dataMsduListArr[queueIndex] = msduList_CreateNewMsduList( hOs);
    409         if(!dataMsduListArr[queueIndex])
    410         {
    411             bufferPool_destroy( hTxData->hBufferPool );
    412             utils_nullTimerDestroy(hOs, pTimer);
    413           #ifdef TI_DBG
    414             utils_nullTimerDestroy(hOs, pThroughputTimer);
    415             utils_nullTimerDestroy(hOs, pAirThroughputTimer);
    416             utils_nullTimerDestroy(hOs, pJitterTimer);
    417           #endif
    418             utils_nullTimerDestroy(hOs, pCreditTimer);
    419             utils_nullMemoryFree(hOs, mgmtMsduList, sizeof(MsduList_t));
    420             queueIndex--;
    421             for(; queueIndex >= 0 ; queueIndex--)
    422             {
    423                 utils_nullMemoryFree(hOs, dataMsduListArr[queueIndex], sizeof(MsduList_t));
    424             }
    425             utils_nullMemoryFree(hOs, hTxData, sizeof(txData_t));
    426             return NULL;
    427         }
    428     }
    429 
    430     hTxData->txDataNumOfQueues = txDataInitParams->txDataNumOfDataQueues;
    431 
    432     /* Threshold to decide whether we drop the packet, or sending it to Fw      */
    433     /* example: value of 75 will drop any MSDU that stayed it the Driver        */
    434     /* Queues for more than 75% of the time that was originally defined for it  */
    435     hTxData->uFracOfLifeTimeToDrop = txDataInitParams->uFracOfLifeTimeToDrop;
    436 
    437     hTxData->TxEventDistributor = DistributorMgr_Create(hOs,MAX_TX_NOTIF_REQ_ELMENTS);
    438 
    439     hTxData->mngMsduList = mgmtMsduList;
    440     for(queueIndex = 0 ; queueIndex < MAX_NUM_OF_TX_QUEUES ; queueIndex++)
    441     {
    442         hTxData->dataMsduListArr[queueIndex] = dataMsduListArr[queueIndex];
    443     }
    444     hTxData->pSchedulerTimer = pTimer;
    445     hTxData->pVadTimer = pVadTimer;
    446     hTxData->bSchedulerTimerRunning = FALSE;
    447   #ifdef TI_DBG
    448     hTxData->pThroughputTimer = pThroughputTimer;
    449     hTxData->pAirThroughputTimer = pAirThroughputTimer;
    450     hTxData->pJitterTimer = pJitterTimer;
    451   #endif
    452     hTxData->pCreditTimer = pCreditTimer;
    453 
    454     hTxData->hOs = hOs;
    455 
    456 	hTxData->bVadTimerEnabled = FALSE;
    457 	hTxData->vadTimerDuration = 0;
    458 
    459     hTxData->creditCalculationTimeout = txDataInitParams->creditCalculationTimeout;
    460     hTxData->bCreditCalcTimerEnabled  = txDataInitParams->bCreditCalcTimerEnabled;
    461     hTxData->admCtrlDelayDueToMediumTimeOverUsage = txDataInitParams->admCtrlDelayDueToMediumTimeOverUsage;
    462     hTxData->admissionDownGradeEnable = txDataInitParams->admissionDownGradeEnable;
    463 
    464 
    465     return(hTxData);
    466 }
    467 
    468 /***************************************************************************
    469 *                           txData_config                                  *
    470 ****************************************************************************
    471 * DESCRIPTION:  This function configures the Tx Data module
    472 *
    473 * INPUTS:       hTxData - The object
    474 *               hCtrlData - Handle to the Ctrl Data object
    475 *               hOs - Handle to the Os Abstraction Layer
    476 *               hReport - Handle to the Report object
    477 *               hMemMngr - Handle to the Memory manager object
    478 
    479 * OUTPUT:
    480 *
    481 * RETURNS:      OK - Configuration unsuccessful
    482 *               NOK - Configuration unsuccessful
    483 ***************************************************************************/
    484 
    485 TI_STATUS txData_config(TI_HANDLE       hTxData,
    486                      TI_HANDLE      hCtrlData,
    487                      TI_HANDLE      hTnetwDrv,
    488                      TI_HANDLE      hWhalCtrl,
    489                      TI_HANDLE      hOs,
    490                      TI_HANDLE      hReport,
    491                      TI_HANDLE      hMemMngr,
    492                      TI_HANDLE      hSiteMgr,
    493                      TI_HANDLE      hEvHandler,
    494                      TI_HANDLE      hQosMngr,
    495                      TI_HANDLE      hPowerMgr)
    496 {
    497     int qIndex;
    498     txData_t *pTxData = (txData_t *)hTxData;
    499 
    500     /* configure modules handles */
    501     pTxData->hCtrlData = hCtrlData;
    502     pTxData->hTnetwDrv = hTnetwDrv;
    503     pTxData->hWhalCtrl= hWhalCtrl;
    504     pTxData->hOs = hOs;
    505     pTxData->hReport = hReport;
    506     pTxData->hMemMngr = hMemMngr;
    507     pTxData->hSiteMgr = hSiteMgr;
    508     pTxData->hEvHandler = hEvHandler;
    509     pTxData->hQosMngr = hQosMngr;
    510     pTxData->hPowerMgr = hPowerMgr;
    511 
    512     /* set Tx parameters */
    513     pTxData->txDataPortStatus = DEF_TX_PORT_STATUS;
    514     pTxData->savePortStatus = DEF_TX_PORT_STATUS;
    515     pTxData->txDataCurrentPrivacyInvokedMode = DEF_CURRENT_PRIVACY_INVOKED_MODE;
    516     pTxData->saveTxDataCurrentPrivacyInvokedMode = DEF_CURRENT_PRIVACY_INVOKED_MODE;
    517     pTxData->txDataEapolEncryptionStatus = DEF_EAPOL_ENCRYPTION_STATUS;
    518     pTxData->saveTxDataEapolEncryptionStatus = DEF_EAPOL_ENCRYPTION_STATUS;
    519 
    520     pTxData->txDataIsSchedulerInWork = DEF_IS_SCHEDULER_IN_WORK;
    521     pTxData->txDataHalInterfaceStatus = DEF_HAL_INTERFACE_STATUS;
    522 
    523     /* Initialize the parameters related to GWSI and to Scheduler in Work */
    524     pTxData->txDataGwsiInterfaceStatus = GWSI_OPEN;
    525     pTxData->txDataIsSchedulerInWork = FALSE;
    526 
    527     pTxData->bCreditCalcTimerRunning = FALSE;
    528 
    529     /* encryption header size */
    530     pTxData->encryptionFieldSize = 0;
    531     pTxData->saveEncryptionFieldSize = 0;
    532 
    533     /* configure the packet ID buffer pool */
    534     bufferPool_config( pTxData->hBufferPool, hReport );
    535 
    536     /* configure the Tx queues (msdu lists) */
    537     /* num of elements is configured by qosMngr */
    538     for (qIndex = 0; qIndex < MAX_NUM_OF_TX_QUEUES; qIndex++)
    539     {
    540         if( (msduList_ConfigMsduList( pTxData->dataMsduListArr[qIndex], pTxData->hMemMngr,
    541                                     pTxData->hReport,pTxData->hOs,0 )) != OK )
    542         {
    543             WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG,
    544                     ("Error configure DataMsduList num: %d\n",qIndex));
    545         }
    546 
    547         /*
    548          * Mark all queues available for TX
    549          */
    550         pTxData->txDataAvailableQueue[qIndex] = TRUE;
    551     }
    552 
    553     if( (msduList_ConfigMsduList( pTxData->mngMsduList, pTxData->hMemMngr,
    554                                 pTxData->hReport, pTxData->hOs,MANAGEMENT_QUEUE_SIZE )) != OK )
    555     {
    556         WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG,
    557                 ("Error configure MgmtMsduList\n"));
    558     }
    559 
    560     /* reset counters */
    561     txData_resetCounters (pTxData);
    562     txData_resetDbgCounters (pTxData);
    563 
    564     WLAN_REPORT_INIT(pTxData->hReport, TX_DATA_MODULE_LOG,
    565                 (".....Tx Data configured successfully\n"));
    566 
    567 #ifdef NO_COPY_NDIS_BUFFERS
    568    WLAN_REPORT_INFORMATION(pTxData->hReport, TX_DATA_MODULE_LOG,
    569                      ("Driver configured to work in NO COPY MSDU BUFFERS."));
    570 #else
    571    WLAN_REPORT_INFORMATION(pTxData->hReport, TX_DATA_MODULE_LOG,
    572                      ("Driver is configured to work in COPY MSDU BUFFERS."));
    573 #endif
    574 
    575 
    576     return OK;
    577 
    578 }
    579 
    580 /***************************************************************************
    581 *                           txData_unLoad                                  *
    582 ****************************************************************************
    583 * DESCRIPTION:  This function unload the tx data module. It first free the
    584 *               MsduLists and then free the Tx data control block
    585 *
    586 * INPUTS:       hTxData - the object
    587 *
    588 * OUTPUT:
    589 *
    590 * RETURNS:      OK - Unload succesfull
    591 *               NOK - Unload unsuccesfull
    592 ***************************************************************************/
    593 
    594 TI_STATUS txData_unLoad(TI_HANDLE hTxData)
    595 {
    596     txData_t *pTxData = (txData_t *)hTxData;
    597     TI_STATUS   status = OK;
    598     int       queueIndex;
    599 
    600     /* check parameters validity */
    601     if( pTxData == NULL )
    602     {
    603         return NOK;
    604     }
    605 
    606     /* free Data queue msdu list */
    607     for(queueIndex = 0;queueIndex < MAX_NUM_OF_TX_QUEUES; queueIndex++)
    608     {
    609         if (msduList_FreeMsduList( pTxData->dataMsduListArr[queueIndex]) != OK)
    610         {
    611             WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG,
    612                 (" txData_unLoad() : fail to free Data MsduList number: %d\n",queueIndex));
    613             status = NOK;
    614         }
    615     }
    616 
    617     /* free Mgmt queue msdu list */
    618     if (msduList_FreeMsduList( pTxData->mngMsduList) != OK)
    619     {
    620         WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG,
    621             (" txData_unLoad() : fail to free Mgmt MsduList \n"));
    622         status = NOK;
    623     }
    624 
    625     DistributorMgr_Destroy(pTxData->TxEventDistributor);
    626 
    627     /* free Timer */
    628     utils_nullTimerDestroy(pTxData->hOs, pTxData->pSchedulerTimer);
    629     utils_nullTimerDestroy(pTxData->hOs, pTxData->pVadTimer);
    630   #ifdef TI_DBG
    631     utils_nullTimerDestroy(pTxData->hOs, pTxData->pThroughputTimer);
    632     utils_nullTimerDestroy(pTxData->hOs, pTxData->pAirThroughputTimer);
    633     utils_nullTimerDestroy(pTxData->hOs, pTxData->pJitterTimer);
    634   #endif
    635     utils_nullTimerDestroy(pTxData->hOs, pTxData->pCreditTimer);
    636 
    637     /* release the packet ID buffer pool */
    638     bufferPool_destroy( pTxData->hBufferPool );
    639 
    640     /* free Tx Data control block */
    641     os_memoryFree(pTxData->hOs, pTxData, sizeof(txData_t));
    642 
    643     return status;
    644 }
    645 
    646 /****************************************************************************
    647 *                               txData_stop                                 *
    648 *****************************************************************************
    649 * DESCRIPTION:  this function stop the tx data. It empties the tx queues (msdu
    650 *               lists) from the msdu's and return all tx data parameters to
    651 *               default values
    652 *
    653 * INPUTS:       hTxData - the object
    654 *
    655 * OUTPUT:
    656 *
    657 * RETURNS:      OK - stop successful
    658 *               NOK - stop unsuccessful
    659 ****************************************************************************/
    660 
    661 TI_STATUS txData_stop(TI_HANDLE hTxData)
    662 {
    663     txData_t *pTxData = (txData_t *)hTxData;
    664     int      queueIndex;
    665 
    666     pTxData->savePortStatus = pTxData->txDataPortStatus;
    667 
    668     /* stop scheduler timer trigger */
    669     if ( TRUE == pTxData->bSchedulerTimerRunning )
    670     {
    671         os_timerStop(pTxData->hOs, pTxData->pSchedulerTimer);
    672     }
    673 
    674     /* stop vad timer */
    675     if ( TRUE == pTxData->bVadTimerEnabled )
    676     {
    677         os_timerStop(pTxData->hOs, pTxData->pVadTimer);
    678     }
    679     /* stop throughput timer */
    680     if(pTxData->txThroughputTimerEnable == TRUE)
    681     {
    682         os_timerStop(pTxData->hOs, pTxData->pThroughputTimer);
    683         pTxData->txThroughputTimerEnable = FALSE;
    684     }
    685 
    686     /* stop throughput timer */
    687     if (pTxData->txAirThroughputTimerEnable)
    688     {
    689         os_timerStop (pTxData->hOs, pTxData->pAirThroughputTimer);
    690         pTxData->txAirThroughputTimerEnable = FALSE;
    691     }
    692 
    693     /* stop credit calculation timer */
    694     if ( pTxData->bCreditCalcTimerRunning )
    695     {
    696         os_timerStop(pTxData->hOs, pTxData->pCreditTimer);
    697         pTxData->bCreditCalcTimerRunning = FALSE;
    698     }
    699 
    700     /* empty Tx data queue from Msdus */
    701     for(queueIndex = 0;queueIndex < MAX_NUM_OF_TX_QUEUES; queueIndex++)
    702     {
    703         if( msduList_EmptyMsduList( pTxData->dataMsduListArr[queueIndex] ) != OK)
    704         {
    705             WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG,
    706                 (" txData_stop() : fail to empty Data Msdu List number: %d\n",queueIndex));
    707             return NOK;
    708         }
    709     }
    710     /* empty Tx Mgmt queue from Msdus */
    711     if( msduList_EmptyMsduList( pTxData->mngMsduList ) != OK)
    712     {
    713         WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG,
    714             (" txData_stop() : fail to empty Mgmt Msdu List \n"));
    715         return NOK;
    716     }
    717 
    718     /* set Tx parameters to default values */
    719     pTxData->txDataPortStatus = DEF_TX_PORT_STATUS;
    720     pTxData->saveTxDataCurrentPrivacyInvokedMode = pTxData->txDataCurrentPrivacyInvokedMode;
    721     pTxData->saveTxDataEapolEncryptionStatus = pTxData->txDataEapolEncryptionStatus;
    722     pTxData->saveEncryptionFieldSize = pTxData->encryptionFieldSize;
    723 
    724     pTxData->txDataCurrentPrivacyInvokedMode = DEF_CURRENT_PRIVACY_INVOKED_MODE;
    725     pTxData->txDataEapolEncryptionStatus = DEF_EAPOL_ENCRYPTION_STATUS;
    726     pTxData->encryptionFieldSize = 0;
    727 
    728 
    729     WLAN_REPORT_INFORMATION(pTxData->hReport, TX_DATA_MODULE_LOG,
    730         (" txData_stop() :  Succeeded.\n"));
    731 
    732     return OK;
    733 
    734 }
    735 
    736 /****************************************************************************
    737 *                               txData_start                                *
    738 *****************************************************************************
    739 * DESCRIPTION:  this function start the tx data.
    740 *
    741 * INPUTS:       hTxData - the object
    742 *
    743 * OUTPUT:
    744 *
    745 * RETURNS:      OK - stop succesfull
    746 *               NOK - stop unsuccesfull
    747 ****************************************************************************/
    748 TI_STATUS txData_start(TI_HANDLE hTxData)
    749 {
    750     txData_t *pTxData = (txData_t *)hTxData;
    751 
    752     /* check parameters validity */
    753     if( pTxData == NULL )
    754     {
    755         WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG,
    756             (" txData_start() : Illegal value for hTxData\n"));
    757         return NOK;
    758     }
    759 
    760     pTxData->txDataPortStatus = pTxData->savePortStatus;
    761 
    762     return OK;
    763 }
    764 
    765 /****************************************************************************
    766 *                       txData_recoveryIndication                           *
    767 *****************************************************************************
    768 * DESCRIPTION:  this function clears information on recovery.
    769 *
    770 * INPUTS:       hTxData - the object
    771 *
    772 * OUTPUT:
    773 *
    774 * RETURNS:
    775 ****************************************************************************/
    776 void txData_recoveryIndication (TI_HANDLE hTxData)
    777 {
    778     txData_t *pTxData = (txData_t *)hTxData;
    779     int queueIndex;
    780 
    781     /* Reinitializes packet ID buffer pool (mark all buffers as available) */
    782     bufferPool_reinit (pTxData->hBufferPool);
    783 
    784     /* Empty Tx data queue from Msdus */
    785     for (queueIndex = 0; queueIndex < MAX_NUM_OF_TX_QUEUES; queueIndex++)
    786     {
    787         if (msduList_EmptyMsduList (pTxData->dataMsduListArr[queueIndex]) != OK)
    788         {
    789             WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG,
    790                 (" txData_stop() : fail to empty data MSDU list number: %d\n", queueIndex));
    791         }
    792     }
    793 
    794     /* Empty Tx management queue from MSDU's */
    795     if (msduList_EmptyMsduList (pTxData->mngMsduList) != OK)
    796     {
    797         WLAN_REPORT_ERROR (pTxData->hReport, TX_DATA_MODULE_LOG,
    798                 (" txData_stop() : fail to empty management MSDU list\n"));
    799     }
    800 
    801     /*
    802      * Set GWSI interfaces status as 'opened'
    803      * because it can be undefined upon recovery
    804      */
    805     pTxData->txDataGwsiInterfaceStatus = GWSI_OPEN;
    806 
    807     for (queueIndex = 0; queueIndex < MAX_NUM_OF_TX_QUEUES; queueIndex++)
    808     {
    809         /*
    810          * Mark all queues available for TX
    811          */
    812         pTxData->txDataAvailableQueue[queueIndex] = TRUE;
    813     }
    814 }
    815 
    816 
    817 /***************************************************************************
    818 *                           txData_checkQueueSize                          *
    819 ****************************************************************************
    820 * DESCRIPTION:  Check the Tx Queue size
    821 *
    822 * INPUTS:       hTxData - the object
    823 *
    824 * OUTPUT:
    825 *
    826 * RETURNS:      OK
    827 *               NOK  - The queue is full
    828 ***************************************************************************/
    829 TI_STATUS txData_checkQueueSize(TI_HANDLE hTxData,UINT8 qIndex)
    830 {
    831     txData_t *pTxData = (txData_t *)hTxData;
    832     TI_STATUS Status = OK;
    833 
    834     txData_startTxScheduler(pTxData);
    835 
    836     if (pTxData->dataMsduListArr[qIndex]->CurrNumOfMsdu == pTxData->dataMsduListArr[qIndex]->maxNumOfMsdu)
    837         Status = NOK;
    838 
    839     return Status;
    840 }
    841 
    842 /***************************************************************************
    843 *                           txData_copyPacketToMsdu                        *
    844 ****************************************************************************
    845 * DESCRIPTION:
    846 *
    847 * INPUTS:       hTxData - the object
    848 *
    849 * OUTPUT:
    850 *
    851 * RETURNS:      OK
    852 *               NOK  - The queue is full
    853 ***************************************************************************/
    854 TI_STATUS txData_copyPacketToMsdu(TI_HANDLE hTxData,mem_MSDU_T **pMsdu, int FreeOldMsdu)
    855 {
    856 #ifdef NO_COPY_NDIS_BUFFERS
    857     txData_t *pTxData = (txData_t *)hTxData;
    858 
    859     TI_STATUS       Status = OK;
    860     mem_BD_T        *pCurrBd;
    861     mem_MSDU_T      *tempMsdu;
    862     UINT8           *pMsduData;
    863     UINT8           *pCurrBufData;
    864     dot11_header_t  *pdot11Header;
    865 
    866 
    867    /*
    868     * Allocate MSDU+BD+BUFFER+TX_DESCRIPTOR_SIZE to copy to !!
    869     */
    870     if(wlan_memMngrAllocMSDU(pTxData->hMemMngr,&tempMsdu,(*pMsdu)->dataLen+TX_TOTAL_OFFSET_BEFORE_DATA,TX_MODULE) != OK)
    871     {
    872         WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG,
    873             (" txData_copyPacketToMsdu() : No Memory in MemMgr \n"));
    874 
    875         return NOK;
    876     }
    877 
    878     tempMsdu->dataLen = 0;
    879     tempMsdu->firstBDPtr->length = 0;
    880     tempMsdu->txFlags = (*pMsdu)->txFlags;
    881 
    882     pCurrBd = (*pMsdu)->firstBDPtr;
    883     pMsduData = tempMsdu->firstBDPtr->data + TX_TOTAL_OFFSET_BEFORE_DATA;
    884     while(pCurrBd)
    885     {
    886         pCurrBufData = pCurrBd->data + pCurrBd->dataOffset;
    887         /* Copy the packet */
    888         os_memoryCopy(pTxData->hOs, pMsduData, pCurrBufData, pCurrBd->length);
    889         tempMsdu->dataLen += pCurrBd->length - TNETWIF_WRITE_OFFSET_BYTES;
    890         tempMsdu->firstBDPtr->length += pCurrBd->length;
    891         pMsduData += pCurrBd->length;
    892 
    893         pCurrBd = pCurrBd->nextBDPtr;
    894     }
    895 
    896     tempMsdu->headerLen = (*pMsdu)->headerLen;
    897 
    898     txData_convertEthToWlanHeader( pTxData, tempMsdu );
    899 
    900     /* set wep bit if needed */
    901     if((tempMsdu->txFlags & TX_DATA_DATA_MSDU) && (pTxData->txDataCurrentPrivacyInvokedMode))
    902     {
    903         pdot11Header = (dot11_header_t*)(memMgr_BufData(pMsdu->firstBDPtr) + memMgr_BufOffset(pMsdu->firstBDPtr));
    904         pdot11Header->fc |= DOT11_FC_WEP;
    905     }
    906     else if ((tempMsdu->txFlags & TX_DATA_EAPOL_MSDU ) && (pTxData->txDataEapolEncryptionStatus))
    907     {
    908         pdot11Header = (dot11_header_t*)(memMgr_BufData(pMsdu->firstBDPtr) + memMgr_BufOffset(pMsdu->firstBDPtr));
    909         pdot11Header->fc |= DOT11_FC_WEP;
    910     }
    911 
    912     if (FreeOldMsdu)
    913         wlan_memMngrFreeMSDU(pTxData->hMemMngr, memMgr_MsduHandle((*pMsdu)));
    914 
    915     (*pMsdu) = tempMsdu;
    916 
    917 #endif
    918 
    919     return OK;
    920 }
    921 
    922 /***************************************************************************
    923 *                           txData_sendPktToWlan                           *
    924 ****************************************************************************
    925 * DESCRIPTION:  This function is called by the Os Abstraction Layer in order
    926 *               to send packet to the wireless LAN. It calls the header
    927 *               conversion function and passes the to sendMsdu function.
    928 *
    929 * INPUTS:       hTxData - the object
    930 *               pMsdu - pointer the packet in 802.3 format
    931 *
    932 * OUTPUT:
    933 *
    934 * RETURNS:      OK
    935 *               NOK
    936 ***************************************************************************/
    937 
    938 TI_STATUS txData_sendPktToWlan(TI_HANDLE hTxData, mem_MSDU_T *pMsdu, UINT8 pkt_DTag)
    939 {
    940     EthernetHeader_t   *pEthHeader;
    941     UINT16              TypeLength;
    942     TI_STATUS Status;
    943     mem_BD_T*           tempBd;
    944     BOOL                UseConvertHeader = TRUE;
    945 
    946     txData_t *pTxData = (txData_t *)hTxData;
    947 
    948     /* check parameters validity */
    949     if( pTxData == NULL || pMsdu == NULL )
    950     {
    951         return NOK;
    952     }
    953 
    954     pEthHeader = (EthernetHeader_t*)(memMgr_BufData(pMsdu->firstBDPtr)+memMgr_BufOffset(pMsdu->firstBDPtr));
    955 
    956     /* check if the frame is multicast/broadcast - need for the transmission rate */
    957     if(IsMacAddressGroup( &pEthHeader->DstAddr ))
    958         pMsdu->txFlags |= TX_DATA_MULTICAST_FRAME;
    959 
    960     TypeLength = pEthHeader->TypeLength;
    961 
    962       /* Call the Classify function in the Control Module to set the qosTag of the MSDU  */
    963      if (ctrlData_ClsfrClassifyTxMSDU(pTxData->hCtrlData, pMsdu, pkt_DTag) != OK)
    964      {
    965         WLAN_REPORT_DEBUG_TX(pTxData->hReport,
    966                      (" txData_sendPktToWlan(): No matching classifier found\n"));
    967      }
    968 
    969 
    970     /* filter MSDU according to Tx Port Status and the Eth Type */
    971     if ( pTxData->txDataPortStatus != OPEN )
    972     {
    973         int queueIndex;
    974         int acIndex;
    975 
    976         WLAN_REPORT_WARNING(pTxData->hReport, TX_DATA_MODULE_LOG,
    977                 (" txData_sendPktToWlan() : try to transmit Msdu while port is not open (txDataPortStatus = 0x%x)\n", pTxData->txDataPortStatus));
    978 
    979         /* Find AC and Tx-queue in order to update the correct Queue measurements */
    980         acIndex = GET_WME_AC_TYPE_FROM_MSDU(pMsdu);
    981         queueIndex = GET_QUEUE_INDEX(pTxData,acIndex);
    982 
    983 
    984         /* updating the measurements - dropped packet counter */
    985         pTxData->txDataReportedCounters[queueIndex].OtherFailCounter++;
    986         pTxData->txDataReportedCounters[queueIndex].NumPackets++;
    987 
    988         if((pTxData->txDataPortStatus == CLOSE) || (pTxData->txDataPortStatus == OPEN_NOTIFY) )
    989         {
    990             WLAN_REPORT_WARNING(pTxData->hReport, TX_DATA_MODULE_LOG,
    991                 (" txData_sendPktToWlan() : try to transmit Msdu while port is not open (txDataPortStatus = 0x%x)\n", pTxData->txDataPortStatus));
    992 
    993             /* In case the function return status is NOK, no need to call Os free function  */
    994             /* Set freefunc in the msdu to null. In this case the MemMngr will not call     */
    995             /* the Os free function                                                         */
    996             memMgr_MsduFreeFuncGet(pMsdu) = NULL;
    997 
    998             /* free MSDU */
    999             if( (wlan_memMngrFreeMSDU(pTxData->hMemMngr, memMgr_MsduHandle(pMsdu))) != OK )
   1000             {
   1001                 WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG,
   1002                     (" txData_sendPktToWlan() : free msdu failed \n"));
   1003             }
   1004 
   1005             return NOK;
   1006         }
   1007 
   1008         /* filter Data frames while port is open only for Eapol's */
   1009         if( (pTxData->txDataPortStatus == OPEN_EAPOL) && (TypeLength != EAPOL_PACKET) )
   1010         {
   1011             WLAN_REPORT_WARNING(pTxData->hReport, TX_DATA_MODULE_LOG,
   1012                 (" txData_sendPktToWlan() : try to transmit Non Eapol packet while port is open for eapols only\n"));
   1013 
   1014             /* In case the function return status is NOK, no need to call Os free function. */
   1015             /* Set freefunc in the msdu to null. In this case the MemMngr will not call     */
   1016             /* the Os free function  - because the return staus to the Os is NOK the buffer */
   1017             /* free by the Os                                                               */
   1018             memMgr_MsduFreeFuncGet(pMsdu) = NULL;
   1019 
   1020             /* frre MSDU */
   1021             if ((wlan_memMngrFreeMSDU(pTxData->hMemMngr, memMgr_MsduHandle(pMsdu))) != OK)
   1022             {
   1023                 WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG,
   1024                     (" txData_sendPktToWlan() : free msdu failed \n"));
   1025             }
   1026 
   1027             return NOK;
   1028         }
   1029     }
   1030 
   1031     /* PORT IS OPEN */
   1032 #ifdef CORE_TX_DBG
   1033     WLAN_REPORT_INFORMATION(pTxData->hReport, TX_DATA_MODULE_LOG,
   1034                 (" txData_sendPktToWlan: port is open \n"));
   1035 #endif
   1036 
   1037 
   1038     if( TypeLength != EAPOL_PACKET )
   1039     {
   1040         pMsdu->txFlags |= TX_DATA_DATA_MSDU;
   1041     }
   1042     else
   1043     {
   1044         WLAN_REPORT_INFORMATION(pTxData->hReport, TX_DATA_MODULE_LOG,
   1045             (" txData_sendPktToWlan() : Tx an EAPOL frame tranferred to HAL\n"));
   1046 
   1047         /* because EAPOL is sent from Mgmt queue */
   1048         pMsdu->txFlags |= TX_DATA_EAPOL_MSDU;
   1049     }
   1050 
   1051     UseConvertHeader = TRUE; /* a patch for WinCe */
   1052 #ifdef NO_COPY_NDIS_BUFFERS
   1053     if (pMsdu->txFlags & TX_DATA_FROM_OS)
   1054         UseConvertHeader = FALSE;   /* don't convert on external (OS) packets */
   1055 #endif
   1056 
   1057         if (UseConvertHeader == TRUE)
   1058     {
   1059         /* Header conversion from Ethernet to 802.11 */
   1060         txData_convertEthToWlanHeader( pTxData, pMsdu );
   1061     }
   1062 
   1063     /* update last BD */
   1064     tempBd = pMsdu->firstBDPtr;
   1065     while(tempBd->nextBDPtr)
   1066     {
   1067         tempBd = tempBd->nextBDPtr;
   1068     }
   1069     pMsdu->lastBDPtr = tempBd;
   1070 
   1071     Status = txData_txSendMsdu( pTxData, pMsdu );
   1072     if( Status == NOK )
   1073     {
   1074         WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG,
   1075             (" txData_sendPktToWlan() : txData_txSendMsdu failed \n"));
   1076     }
   1077 
   1078     if ((OK == Status) && (GET_WME_AC_TYPE_FROM_MSDU(pMsdu) == QOS_AC_VO))
   1079     {
   1080 	txData_resetVadTimer(pTxData);
   1081     }
   1082     return Status;
   1083 }
   1084 
   1085 /***************************************************************************
   1086 *                           txData_txSendMsdu                              *
   1087 ****************************************************************************
   1088 * DESCRIPTION:  This function is insert the MSDU to transmit to the proper
   1089 *               tx queue and give a trigger to the scheduler to start
   1090 *               transmission to the wireless LAN.
   1091 *
   1092 * INPUTS:       hTxData - the object
   1093 *               pMsdu - pointer the MSDU in 802.11 format
   1094 *
   1095 * OUTPUT:
   1096 *
   1097 * RETURNS:  OK
   1098 *           NOK
   1099 ***************************************************************************/
   1100 
   1101 TI_STATUS txData_txSendMsdu(TI_HANDLE hTxData, mem_MSDU_T *pMsdu )
   1102 {
   1103     dot11_header_t     *pdot11Header;
   1104     TI_STATUS Status = OK;
   1105     int queueIndex;
   1106     acTrfcType_e acIndex;
   1107 
   1108 
   1109     txData_t *pTxData = (txData_t *)hTxData;
   1110 
   1111     /* ctrlData_txMsdu(pTxData->hCtrlData,&pMsdu); 4x related */
   1112 
   1113     if(pMsdu == NULL)
   1114     {
   1115         WLAN_REPORT_INFORMATION(pTxData->hReport, TX_DATA_MODULE_LOG,
   1116             (" txData_txSendMsdu() : DISCARD Packet...... \n"));
   1117         txData_startTxScheduler(pTxData);
   1118 
   1119         return NOK;
   1120     }
   1121 
   1122 
   1123 #ifndef NO_COPY_NDIS_BUFFERS /* buffers are copied by OAL*/
   1124     /* set wep bit if needed */
   1125     if((pMsdu->txFlags & TX_DATA_DATA_MSDU) && (pTxData->txDataCurrentPrivacyInvokedMode))
   1126     {
   1127         /* update offset of header */
   1128         pdot11Header = (dot11_header_t*)(memMgr_BufData(pMsdu->firstBDPtr) + memMgr_BufOffset(pMsdu->firstBDPtr));
   1129         pdot11Header->fc |= DOT11_FC_WEP;
   1130     }
   1131     else if ((pMsdu->txFlags & TX_DATA_EAPOL_MSDU ) && (pTxData->txDataEapolEncryptionStatus))
   1132     {
   1133         /* update offset of header */
   1134         pdot11Header = (dot11_header_t*)(memMgr_BufData(pMsdu->firstBDPtr) + memMgr_BufOffset(pMsdu->firstBDPtr));
   1135         pdot11Header->fc |= DOT11_FC_WEP;
   1136     }
   1137 #endif /*NO_COPY_NDIS_BUFFERS*/
   1138 
   1139 #ifdef EXC_MODULE_INCLUDED
   1140     if ((pMsdu->txFlags & TX_DATA_IAPP_MSDU) && (pTxData->txDataCurrentPrivacyInvokedMode))
   1141     {
   1142         /* update offset of header */
   1143         pdot11Header = (dot11_header_t*)(memMgr_BufData(pMsdu->firstBDPtr) + memMgr_BufOffset(pMsdu->firstBDPtr));
   1144         pdot11Header->fc |= DOT11_FC_WEP;
   1145     }
   1146 #endif
   1147 
   1148 
   1149     WLAN_REPORT_DEBUG_TX(pTxData->hReport,
   1150         (" txData_txSendMsdu() : Sending PAcket pMsdu %x pMsdu->txFlags %x \n",pMsdu,pMsdu->txFlags));
   1151 
   1152     /* insert the msdu to the the appropriate queue */
   1153     if( (pMsdu->txFlags & TX_DATA_DATA_MSDU) || (pMsdu->txFlags & TX_DATA_NULL_MSDU) )
   1154     {
   1155         /* Find Tx-queue and AC to use for Tx, and if downgraded from original one update the UP. */
   1156         txData_selectQueueAndUpdateUserPriority (pTxData, pMsdu, &queueIndex, &acIndex);
   1157 
   1158         /* set insertion time for further expiry timeout calculation */
   1159         pMsdu->insertionTime = os_timeStampUs (pTxData->hOs);
   1160 
   1161         /* see if the frame is tagged VO. */
   1162         /* Note: Check actual tag even if current not working in WME, to support voice anyway. */
   1163         if( GET_WME_AC_TYPE_FROM_MSDU(pMsdu) == QOS_AC_VO)
   1164         {
   1165             /*
   1166              * If the frame is tagged VO and power save is on, send psPoll before the VO frame.
   1167              */
   1168             if(txData_acVoPsPollMode(pTxData) == TRUE)
   1169             {
   1170                 mem_MSDU_T *pMsduPsPoll;
   1171 
   1172                 if(txData_getPsPollFrame(pTxData,&pMsduPsPoll) == OK)
   1173                 {
   1174                     /* increment debug counters */
   1175                     pTxData->txDataDbgCounters.dbgInsertToMsduListBytes[queueIndex] += pMsduPsPoll->dataLen;
   1176                     pTxData->txDataDbgCounters.dbgInsertToMsduListPackets[queueIndex]++;
   1177 
   1178                     /* set insertion time for further expiry timeout calculation */
   1179                     pMsduPsPoll->insertionTime = os_timeStampUs (pTxData->hOs);
   1180 
   1181                     /* insert to queueIndex queue */
   1182                     if( msduList_Insert( pTxData->dataMsduListArr[queueIndex] , &pMsduPsPoll ) != OK )
   1183                     {
   1184                         pTxData->txDataDbgCounters.dbgDropedFromMsduListPackets[queueIndex]++;
   1185                         /* the first msdu in list has removed and the new one has inserted */
   1186                         WLAN_REPORT_WARNING(pTxData->hReport, TX_DATA_MODULE_LOG,
   1187                                             (" txData_sendPktToWlan() : Msdu List num %d was full \n",queueIndex));
   1188 
   1189                         /* free the msdu which removed from the list (returned in pMsdu) */
   1190                         /*---------------------------------------------------------------*/
   1191                         /* set msdu tx status to Fail (this status is used by OS) */
   1192                         memMgr_MsduFreeArg2Get(pMsduPsPoll) = NOK;
   1193 
   1194                         /* free the msdu */
   1195                         wlan_memMngrFreeMSDU(pTxData->hMemMngr, memMgr_MsduHandle(pMsduPsPoll));
   1196                         pTxData->txDataDbgCounters.dbgDropedPacketsCounter++;
   1197                     }/*msduList_Insert*/
   1198                 }/*txData_getPsPollFrame*/
   1199             }/*txData_acVoPsPollMode*/
   1200         }
   1201 
   1202         /* insert to data queue */
   1203         /* if we didn't succeed to insert psPolls exclude VO packet also */
   1204         if( msduList_Insert( pTxData->dataMsduListArr[queueIndex] , &pMsdu ) != OK )
   1205         {
   1206 
   1207             pTxData->txDataDbgCounters.dbgDropedFromMsduListPackets[queueIndex]++;
   1208             /* the first msdu in list has removed and the new one has inserted */
   1209             WLAN_REPORT_WARNING(pTxData->hReport, TX_DATA_MODULE_LOG,
   1210                 (" txData_txSendMsdu() : Data Msdu [%d] List was full \n",queueIndex));
   1211 
   1212             /* free the msdu which removed from the list (returned in pMsdu) */
   1213             /*---------------------------------------------------------------*/
   1214             /* set msdu tx status to Fail (this status is used by OS) */
   1215             memMgr_MsduFreeArg2Get(pMsdu) = NOK;
   1216 
   1217             /* free the msdu */
   1218             wlan_memMngrFreeMSDU(pTxData->hMemMngr, memMgr_MsduHandle(pMsdu));
   1219             pTxData->txDataDbgCounters.dbgDropedPacketsCounter++;
   1220 
   1221             pTxData->txDataReportedCounters[queueIndex].NumPackets++;
   1222             pTxData->txDataReportedCounters[queueIndex].OtherFailCounter++;
   1223 
   1224             return OK;
   1225         }
   1226 
   1227         /* increament debug counters */
   1228         pTxData->txDataDbgCounters.dbgInsertToMsduListBytes[queueIndex] += pMsdu->dataLen;
   1229         pTxData->txDataDbgCounters.dbgInsertToMsduListPackets[queueIndex]++;
   1230 
   1231         WLAN_REPORT_DEBUG_TX(pTxData->hReport,
   1232             (" txData_txSendMsdu() : insert data packet to queue # %d \n",queueIndex));
   1233     }
   1234     else
   1235     {
   1236         /* Management frame, Eapol and null frame (for measuring a non serving channel)
   1237             are also sent from the mgmt queue */
   1238 
   1239         /* set insertion time for further expiry timeout calculation */
   1240         pMsdu->insertionTime = os_timeStampUs (pTxData->hOs);
   1241 
   1242         WLAN_REPORT_DEBUG_TX(pTxData->hReport,
   1243             (" txData_txSendMsdu() : insert mngt packet to Management queue pMsdu %x \n",pMsdu));
   1244 
   1245         if( msduList_Insert( pTxData->mngMsduList , &pMsdu ) != OK )
   1246         {
   1247             /* the first msdu in list has removed and the new one has inserted */
   1248             WLAN_REPORT_WARNING(pTxData->hReport, TX_DATA_MODULE_LOG,
   1249                 (" txData_txSendMsdu() : Mgmt Msdu List was full \n"));
   1250 
   1251             /* free the msdu which removed from the list (returned in pMsdu) */
   1252             /*---------------------------------------------------------------*/
   1253             /* set msdu tx status to Fail (this status is used by OS) */
   1254             memMgr_MsduFreeArg2Get(pMsdu) = NOK;
   1255 
   1256             /* free the msdu */
   1257             wlan_memMngrFreeMSDU(pTxData->hMemMngr, memMgr_MsduHandle(pMsdu));
   1258             pTxData->txDataDbgCounters.dbgDropedPacketsCounter++;
   1259         }
   1260     }
   1261 
   1262     {
   1263         /* call the scheduler in order to transmit the frame to the Hal */
   1264     Status = txData_startTxScheduler(pTxData);
   1265         if ( Status == NOK )
   1266         {
   1267             WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG,
   1268                 (" txData_txSendMsdu() : txData_startTxScheduler error \n"));
   1269         }
   1270     }
   1271 
   1272     /* this is the status of the current Msdu */
   1273     return OK;
   1274 }
   1275 
   1276 /***************************************************************************
   1277 *                       txData_startTxScheduler                            *
   1278 ****************************************************************************
   1279 * DESCRIPTION:  This function start the transmission process.
   1280 *               It select msdu to transmit from the tx queues and send
   1281 *               it to the Hal
   1282 *
   1283 * INPUTS:       hTxData - the object
   1284 *
   1285 * OUTPUT:
   1286 *
   1287 * RETURNS:  OK
   1288 *           NOK
   1289 ***************************************************************************/
   1290 
   1291 TI_STATUS txData_startTxScheduler(TI_HANDLE hTxData)
   1292 {
   1293     txData_t            *pTxData = (txData_t *)hTxData;
   1294     mem_MSDU_T          *pMsdu;
   1295     MsduList_t          *pMsduList = NULL;
   1296     txData_attr_t       txAttr;
   1297     UINT8               count, selectedQueueIndex;
   1298     TI_STATUS           txStatus;
   1299     txPacketIdAttr_t    *pPacketId;
   1300     dot11_header_t      *pDot11Header;
   1301     bssType_e           currBssType;
   1302     macAddress_t        currBssId;
   1303     UINT32              msduTimeToExpiry;
   1304 
   1305 #ifdef SUPPORT_4X
   1306     hwTxInformation_t   hwTxInformation;
   1307     BOOL                fourXEnable;
   1308 #endif
   1309 
   1310     /* check if HAL is open now - used for recovery only!!! */
   1311     if ( pTxData->txDataHalInterfaceStatus == TX_DATA_CLOSED )
   1312     {
   1313         return OK; /* TODO ronen: doesn't seem to be used any more, remove */
   1314     }
   1315 
   1316     /* Checking if Tx is now disabled */
   1317     if(pTxData->txDisable == DISABLE_IMMEDIATELY)
   1318     {
   1319         WLAN_REPORT_WARNING(pTxData->hReport, TX_DATA_MODULE_LOG,
   1320                 (" txData_startTxScheduler() : Tx Disabled!!! \n"));
   1321 
   1322         /* start scheduler timer */
   1323         if ( FALSE == pTxData->bSchedulerTimerRunning )
   1324         {
   1325             os_timerStart( pTxData->hOs, pTxData->pSchedulerTimer, SCHEDULER_TIMER, FALSE );
   1326             pTxData->bSchedulerTimerRunning = TRUE;
   1327         }
   1328 
   1329         pTxData->txDataIsSchedulerInWork = FALSE;
   1330         return OK;
   1331     }
   1332 
   1333    /*
   1334     * in case of non serialized system no need to
   1335     * run the scheduler if it is already in work
   1336     */
   1337     if(pTxData->txDataIsSchedulerInWork == TRUE)
   1338     {
   1339         WLAN_REPORT_WARNING(pTxData->hReport, TX_DATA_MODULE_LOG,
   1340             (" txData_startTxScheduler() : Scheduler already in work...........!!!! \n"));
   1341         return OK;
   1342     }
   1343     else
   1344     {
   1345         pTxData->txDataIsSchedulerInWork = TRUE;
   1346     }
   1347 
   1348     /* try to transmit DEF_SCHEDULER_THRESHOLD MSDUs */
   1349     count = DEF_SCHEDULER_THRESHOLD;
   1350 
   1351     /*
   1352      * if non of the queues is available non msdu will be selected
   1353      */
   1354 
   1355     while ( (0 < count--) && (GWSI_OPEN == pTxData->txDataGwsiInterfaceStatus) )
   1356     {
   1357         /* select queue to transmit from */
   1358         if( txData_schedulerSelectQueueToTransmitFrom( pTxData, &pMsduList,&selectedQueueIndex ) != TX_QUEUE_SELECTED_OK)
   1359         {
   1360             WLAN_REPORT_DEBUG_TX(pTxData->hReport,
   1361                     (" txData_startTxScheduler() : No Msdu waiting to transmit  \n"));
   1362 
   1363            pTxData->txDataIsSchedulerInWork = FALSE;
   1364             return OK;
   1365         }
   1366 
   1367         WLAN_REPORT_DEBUG_TX(pTxData->hReport,
   1368             (" txData_startTxScheduler() : txData_schedulerSelectQueueToTransmitFrom Returned from selectedQueueIndex %d   \n",selectedQueueIndex));
   1369 
   1370 
   1371 #ifdef SUPPORT_4X
   1372 
   1373         ctrlData_get4xStatus(pTxData->hCtrlData,&fourXEnable);
   1374 
   1375         if(fourXEnable == TRUE  && pMsduList != pTxData->mngMsduList)
   1376         {
   1377            /*
   1378             * receive Acx tx queuue information for transmission decision
   1379             */
   1380             whalTx_getTxQueueInfo(pTxData->hWhalTx,
   1381                                     DEFAULT_QUEUE_TO_HAL,
   1382                                     &hwTxInformation.hwNumOfFreeMsdu,
   1383                                     &hwTxInformation.hwNumOfBusyMsdu,
   1384                                     &hwTxInformation.hwNumOfFreeBDs,
   1385                                     &hwTxInformation.hwTotalAvailMem );
   1386 
   1387            /*
   1388             * call ctrl Data - DequeueMsdu...
   1389             * pMsdu - the msdu to transmit.
   1390             * txAttr - the tx attributes for msdu transmission
   1391             */
   1392             status = ctrlData_txDequeueMsdu(pTxData->hCtrlData, &pMsdu, pMsduList, &txAttr, &hwTxInformation);
   1393 
   1394             if(status == DO_NOT_SEND_MSDU)
   1395             {
   1396         WLAN_REPORT_ERROR(pTxData->hReport,
   1397                     (" txData_startTxScheduler() : TX_STATUS_PENDING  \n"));
   1398 
   1399                 pTxData->txDataIsSchedulerInWork = FALSE;
   1400 
   1401                 return TX_STATUS_PENDING;
   1402             }
   1403         }
   1404 
   1405 #else  /*  if not SUPPORT_4X  */
   1406 
   1407         {
   1408             /* increment debug counter */
   1409             pTxData->txDataDbgCounters.dbgScheduledOutPackets[selectedQueueIndex]++;
   1410 
   1411             if( msduList_WatchFirst( pMsduList ,&pMsdu) != OK )
   1412             {
   1413                 WLAN_REPORT_ERROR( pTxData->hReport, TX_DATA_MODULE_LOG,
   1414                                    ("Unable to retrieve first MSDU from queue index:%d\n", selectedQueueIndex) );
   1415                 pTxData->txDataIsSchedulerInWork = FALSE;
   1416                 return OK;
   1417             }
   1418 
   1419             WLAN_REPORT_DEBUG_TX(pTxData->hReport,
   1420                     (" txData_startTxScheduler() : After msduList_WatchFirst pMsdu %d   \n",pMsdu));
   1421 
   1422 #ifdef NO_COPY_NDIS_BUFFERS
   1423 
   1424             if(pMsdu->txFlags & TX_DATA_FROM_OS)
   1425             {
   1426                 if(txData_copyPacketToMsdu(pTxData, &pMsdu, 1 /* do FreeOldMsdu */) != OK)
   1427                 {
   1428                     WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG,
   1429                         (" txData_startTxScheduler() : txData_copyPacketToMsdu FAILED  \n"));
   1430 
   1431                     pTxData->txDataIsSchedulerInWork = FALSE;
   1432                     return NOK;
   1433                 }
   1434             }
   1435 
   1436 #endif /* NO_COPY_NDIS_BUFFERS */
   1437 
   1438         }
   1439 
   1440 #endif /* SUPPORT_4X */
   1441 
   1442         /* check MSDU expiry time, and if it didn't expire send it to GWSI */
   1443         if ((msduTimeToExpiry = txDataTimeToMsduExpiry (hTxData, pMsdu, selectedQueueIndex)) == 0)
   1444         {
   1445             /* MSDU time expired - drop it */
   1446             WLAN_REPORT_INFORMATION(pTxData->hReport, TX_DATA_MODULE_LOG,
   1447                 ("txData_startTxScheduler drop msdu due to expiry time, queueId = %d \n",selectedQueueIndex));
   1448 
   1449             /* Get MSDU with dequeuing */
   1450             if ( (msduList_GetFirst( pMsduList, &pMsdu )) != OK )
   1451             {
   1452                 /* No MSDU is waiting to transmit */
   1453                 WLAN_REPORT_ERROR (pTxData->hReport, TX_DATA_MODULE_LOG,
   1454                     ("%s: can't get Msdu from pMsduList[ %d ]  \n", __FUNCTION__, selectedQueueIndex));
   1455                 pTxData->txDataIsSchedulerInWork = FALSE;
   1456                 return NOK;
   1457             }
   1458 
   1459 
   1460             pTxData->txDataDbgCounters.dbgDroppedDueExpiryTimePackets[selectedQueueIndex]++;
   1461 
   1462             pTxData->txDataReportedCounters[selectedQueueIndex].NumPackets++;
   1463             pTxData->txDataReportedCounters[selectedQueueIndex].OtherFailCounter++;
   1464 
   1465             /* free the MSDU */
   1466             memMgr_MsduFreeArg2Get(pMsdu) = OK;
   1467 
   1468                 if( (wlan_memMngrFreeMSDU(pTxData->hMemMngr, memMgr_MsduHandle(pMsdu))) != OK )
   1469                 {
   1470                     WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG,
   1471                         (" txData_startTxScheduler() : free msdu failed \n"));
   1472                 }
   1473 
   1474             /* continue to next packet */
   1475             continue;
   1476         }
   1477 
   1478         /* Collect txAttr from control */
   1479         ctrlData_getTxAttributes(pTxData->hCtrlData, pMsdu->txFlags, &txAttr, selectedQueueIndex);
   1480 
   1481         /* allocate a buffer for packet ID storage */
   1482         pPacketId = (txPacketIdAttr_t*)bufferPool_allocateBuffer( pTxData->hBufferPool );
   1483         if ( BUFFER_POOL_NO_BUFFER == pPacketId )
   1484         {
   1485             WLAN_REPORT_ERROR (pTxData->hReport, TX_DATA_MODULE_LOG,
   1486                 (" %s : No PacketID Available!!\n", __FUNCTION__));
   1487 
   1488             /* shouldn't happen, since we have enough packet ID buffers as the FW has TX descriptors! */
   1489             pTxData->txDataIsSchedulerInWork = FALSE;
   1490             return NOK;
   1491         }
   1492 
   1493         /* store necessary information in packet ID */
   1494         pPacketId->pMsdu = pMsdu;
   1495         if (pMsdu->txFlags & TX_DATA_DATA_MSDU)
   1496         {
   1497             pPacketId->bDataMsdu = TRUE;
   1498         }
   1499         else
   1500         {
   1501             pPacketId->bDataMsdu = FALSE;
   1502         }
   1503         pPacketId->txQid = selectedQueueIndex;
   1504         pPacketId->txCompleteFlags = pMsdu->txCompleteFlags;
   1505         pPacketId->maxTransmitRate = txAttr.HwRate;
   1506       #ifdef TI_DBG
   1507         os_memoryZero (pTxData->hOs, pPacketId->timeStamp, sizeof(pPacketId->timeStamp));
   1508         pPacketId->timeStamp[0] = os_timeStampUs (pTxData->hOs);
   1509       #endif
   1510 
   1511         pPacketId->msduDataLen = pMsdu->dataLen;
   1512 
   1513         /* destination mac */
   1514         pDot11Header = (dot11_header_t*)(memMgr_BufData(pMsdu->firstBDPtr)+ memMgr_BufOffset(pMsdu->firstBDPtr));
   1515         ctrlData_getCurrBssTypeAndCurrBssId(pTxData->hCtrlData, &currBssId, &currBssType);
   1516         if(currBssType == BSS_INDEPENDENT)
   1517              MAC_COPY( pTxData->hOs, &(pPacketId->destinationMac), &(pDot11Header->address1) );
   1518         else
   1519              MAC_COPY( pTxData->hOs, &(pPacketId->destinationMac), &(pDot11Header->address3) );
   1520 
   1521         /* mark in packet ID that XFER done and TX complete were not called yet */
   1522         pPacketId->bTxCompleteCalled = pPacketId->bXferDoneCalled = FALSE;
   1523 
   1524 
   1525       #ifdef TI_DBG
   1526         if ((pMsdu->txFlags & TX_DATA_DATA_MSDU) != 0 && pMsdu->timeStampNum > 0)
   1527         {
   1528             UINT32 uCoreDelay;
   1529 
   1530             /* add time stamp */
   1531             wlan_memMngrAddTimeStamp (pTxData->hMemMngr, pMsdu);
   1532 
   1533             uCoreDelay = pMsdu->timeStamp[pMsdu->timeStampNum - 1] - pMsdu->timeStamp[0];
   1534 
   1535             /* update core delay and jitter */
   1536             pTxData->txJitter[selectedQueueIndex].jitter.core +=
   1537                 ABS (pTxData->txJitter[selectedQueueIndex].last_delay.core - uCoreDelay);
   1538             pTxData->txJitter[selectedQueueIndex].last_delay.core = uCoreDelay;
   1539             pTxData->txJitter[selectedQueueIndex].delay.core += uCoreDelay;
   1540             pTxData->txJitter[selectedQueueIndex].count.core ++;
   1541             if (uCoreDelay > pTxData->txJitter[selectedQueueIndex].max_delay.core)
   1542                 pTxData->txJitter[selectedQueueIndex].max_delay.core = uCoreDelay;
   1543         }
   1544       #endif
   1545 
   1546         /* send the packet to the GWSI layer */
   1547         txStatus = CORE_AdaptTx_SendPacket( CORE_AdaptTx_handle, selectedQueueIndex, pMsdu, &txAttr, (UINT32)pPacketId, msduTimeToExpiry );
   1548 
   1549         WLAN_REPORT_DEBUG_TX (pTxData->hReport,
   1550                               ("txData_startTxScheduler(): called CORE_AdaptTx_SendPacket pMsdu=%d, selectedQueueIndex=%d,txStatus=%d\n",
   1551                               pMsdu,selectedQueueIndex,txStatus));
   1552 
   1553         switch ( txStatus )
   1554         {
   1555         /*
   1556          * XFER_DONE is received when the packet has been synchronously transferred to the FW.
   1557          * in this case, XFER complete will not be called, only TX complete
   1558          */
   1559         case SEND_PACKET_XFER_DONE:
   1560 
   1561             pPacketId->driverHandlingTime = (os_timeStampUs (pTxData->hOs) - pMsdu->insertionTime) / 1000;
   1562 
   1563             /* Get MSDU with dequeuing */
   1564             if ( (msduList_GetFirst( pMsduList, &pMsdu )) != OK )
   1565             {
   1566                 /* No MSDU is waiting to transmit */
   1567                 WLAN_REPORT_ERROR (pTxData->hReport, TX_DATA_MODULE_LOG,
   1568                     (" %s : can't get Msdu from pMsduList[ %d ]  \n", __FUNCTION__, selectedQueueIndex));
   1569                 pTxData->txDataIsSchedulerInWork = FALSE;
   1570                 return NOK;
   1571             }
   1572 
   1573             /* free the MSDU, since XFER complete won't be called */
   1574             if ( (wlan_memMngrFreeMSDU(pTxData->hMemMngr, memMgr_MsduHandle(pMsdu))) != OK )
   1575             {
   1576                WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG,
   1577                    ("%s: free msdu failed \n", __FUNCTION__));
   1578                pTxData->txDataIsSchedulerInWork = FALSE;
   1579                return NOK;
   1580             }
   1581             else
   1582             {
   1583                 pTxData->txDataDbgCounters.dbgNumOfMsduFreeInTxTransfer[ pPacketId->txQid ]++;
   1584             }
   1585 
   1586             /* Nullify the MSDU pointer, just in case */
   1587             pPacketId->pMsdu = NULL;
   1588 
   1589             /* mark in packet ID that XFER done was called */
   1590             pPacketId->bXferDoneCalled = TRUE;
   1591 
   1592             /* increment debug counter */
   1593             pTxData->txDataDbgCounters.dbgSendToGwsiQosPackets[ selectedQueueIndex ]++;
   1594             pTxData->txDataDbgCounters.dbgNumOfMsduXferDoneInShceduler[ selectedQueueIndex ]++;
   1595             break;
   1596 
   1597         /*
   1598          * SUCCESS is received when the packet has not yet been sent to the FW, but another packet
   1599          * transfer can start immediately
   1600          */
   1601         case SEND_PACKET_SUCCESS:
   1602             /* Get msdu with dequeuing */
   1603             if ( (msduList_GetFirst( pMsduList, &pMsdu )) != OK )
   1604             {
   1605                 /* No msdu is waiting to transmit */
   1606                 WLAN_REPORT_ERROR (pTxData->hReport, TX_DATA_MODULE_LOG,
   1607                     (" %s : can't get Msdu from pMsduList[ %d ]  \n", __FUNCTION__, selectedQueueIndex));
   1608                 pTxData->txDataIsSchedulerInWork = FALSE;
   1609                 return NOK;
   1610             }
   1611 
   1612             /* increment debug counter */
   1613             pTxData->txDataDbgCounters.dbgNumOfMsduSuccessInScheduler[ selectedQueueIndex ]++;
   1614             pTxData->txDataDbgCounters.dbgSendToGwsiQosPackets[selectedQueueIndex]++;
   1615             break;
   1616 
   1617         /*
   1618          * PENDING is received when the packet has been received by the GWSI layer, and the double buffer
   1619          * mechanism is busy. It indicates that no more packets (from all queues) are to be sent until a
   1620          * XFER complete indication is received
   1621          */
   1622         case SEND_PACKET_PENDING:
   1623             /* Get msdu with dequeuing */
   1624             if ( (msduList_GetFirst( pMsduList, &pMsdu )) != OK )
   1625             {
   1626                 /* No msdu is waiting to transmit */
   1627                 WLAN_REPORT_ERROR (pTxData->hReport, TX_DATA_MODULE_LOG,
   1628                     (" %s : can't get Msdu from pMsduList[ %d ]  \n", __FUNCTION__, selectedQueueIndex));
   1629                 pTxData->txDataIsSchedulerInWork = FALSE;
   1630                 return NOK;
   1631             }
   1632 
   1633             /* mark the GWSI interface state as pending (no more frames can be sent) */
   1634             pTxData->txDataGwsiInterfaceStatus = GWSI_PENDING;
   1635 
   1636             /* increment debug counter */
   1637             pTxData->txDataDbgCounters.dbgNumOfMsduPendingInScheduler[ selectedQueueIndex ]++;
   1638             pTxData->txDataDbgCounters.dbgSendToGwsiQosPackets[selectedQueueIndex]++;
   1639             break;
   1640 
   1641         /*
   1642          * BUSY is received when the packet has NOT been received by the GWSI layer (and needs to be
   1643          * retransmitted). It indicates that the specific FW queue is full and no more packets from this
   1644          * specific queue are to be sent until a TX complete indication for this queue is received (but
   1645          * packets from other queues may be sent).
   1646          */
   1647         case SEND_PACKET_BUSY:
   1648             /* don't dequeue the packet! it was not sent! */
   1649 
   1650             /* in addition, release the packet ID buffer */
   1651             bufferPool_releaseBuffer( pTxData->hBufferPool, pPacketId );
   1652 
   1653             /* mark the specific queue as not available */
   1654             pTxData->txDataAvailableQueue[ selectedQueueIndex ] = FALSE;
   1655 
   1656             /* update debug counters */
   1657             pTxData->txDataDbgCounters.dbgNumOfMsduBusyInScheduler[ selectedQueueIndex ]++;
   1658 
   1659             break;
   1660 
   1661         /*
   1662          * ERROR is received when a frame is sent although a PENDING indication had been previously
   1663          * received and no XFER complete had been receive since, or because a BUSY indication had been
   1664          * received for a specific queue and no TX complete for this queue had been received since (and
   1665          * a packet from this queue had been sent now).
   1666          */
   1667         case SEND_PACKET_ERROR:
   1668             /* don't dequeue the packet! it was not sent! */
   1669 
   1670             /* in addition, release the packet ID buffer */
   1671             bufferPool_releaseBuffer( pTxData->hBufferPool, pPacketId );
   1672 
   1673             /* start scheduler timer */
   1674             if ( FALSE == pTxData->bSchedulerTimerRunning )
   1675             {
   1676                 os_timerStart( pTxData->hOs, pTxData->pSchedulerTimer, SCHEDULER_TIMER, FALSE );
   1677                 pTxData->bSchedulerTimerRunning = TRUE;
   1678             }
   1679             pTxData->txDataIsSchedulerInWork = FALSE;
   1680             WLAN_REPORT_ERROR( pTxData->hReport, TX_DATA_MODULE_LOG,
   1681                                 (" %s: received status SEND_PACKET_ERROR from CORE_AdaptTx_SendPacket\n", __FUNCTION__) );
   1682 
   1683             /* update debug counters */
   1684             pTxData->txDataDbgCounters.dbgNumOfMsduErrorInScheduler[ selectedQueueIndex ]++;
   1685 
   1686             return NOK;
   1687 
   1688 /*            break; - unreachable*/
   1689 
   1690         case SEND_PACKET_RECOVERY:
   1691             break;
   1692 
   1693         default:
   1694             WLAN_REPORT_ERROR( pTxData->hReport, TX_DATA_MODULE_LOG,
   1695                                (" %s: received status %d from CORE_AdaptTx_SendPacket\n", __FUNCTION__, txStatus) );
   1696             break;
   1697             }
   1698 
   1699             WLAN_REPORT_INFORMATION (pTxData->hReport, TX_DATA_MODULE_LOG,
   1700                 ("txData_startTxScheduler() : MSDU sent: TxQ = %d TxStatus = %d\n", selectedQueueIndex, txStatus));
   1701     }  /* end of while (count) */
   1702 
   1703     pTxData->txDataIsSchedulerInWork = FALSE;
   1704 
   1705     return OK;
   1706 }
   1707 /***************************************************************************
   1708 *                           txData_sendPacketTransfer                      *
   1709 ****************************************************************************
   1710 * DESCRIPTION:  GWSI sendPacketTransfer CB. called after transferring a packet
   1711 *               to TNET.
   1712 *               The function free the transfered MSDU and set GWSI port status
   1713 *               to OPEN. This is the only function which synchronized GWSI port
   1714 *               status.
   1715 *               TNET queues buffer status are updated and the scheduler is executed
   1716 *               trying to send another MSDU.
   1717 *
   1718 * INPUTS:       hTxData - the object
   1719 *
   1720 * OUTPUT:
   1721 *
   1722 * RETURNS:  void
   1723 *
   1724 ***************************************************************************/
   1725 void txData_sendPacketTransfer(TI_HANDLE          hTxData,
   1726                                UINT32    aPacketIdAttr)
   1727 {
   1728     txData_t *pTxData = (txData_t *)hTxData;
   1729     txPacketIdAttr_t* pPacketId = (txPacketIdAttr_t*)aPacketIdAttr;
   1730 
   1731 
   1732     WLAN_REPORT_INFORMATION(pTxData->hReport, TX_DATA_MODULE_LOG,
   1733             ("%s: XFER complete CB called\n", __FUNCTION__));
   1734     pTxData->txDataDbgCounters.dbgNumOfMsduTxTransferCB[ pPacketId->txQid ]++;
   1735 
   1736     WLAN_REPORT_DEBUG_TX(pTxData->hReport,
   1737         ("%s: XFER complete CB called\n", __FUNCTION__));
   1738 
   1739     /* updating GWSI status to open */
   1740     pTxData->txDataGwsiInterfaceStatus = GWSI_OPEN;
   1741 
   1742     /* free the MSDU */
   1743     if ( pPacketId->pMsdu != NULL )
   1744     {
   1745         pPacketId->driverHandlingTime = (os_timeStampUs (pTxData->hOs) - pPacketId->pMsdu->insertionTime) / 1000;
   1746 
   1747         if( (wlan_memMngrFreeMSDU(pTxData->hMemMngr, memMgr_MsduHandle(pPacketId->pMsdu))) != OK )
   1748         {
   1749            WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG,
   1750                ("%s: free msdu failed \n", __FUNCTION__));
   1751         }
   1752         else
   1753         {
   1754             pTxData->txDataDbgCounters.dbgNumOfMsduFreeInTxTransfer[ pPacketId->txQid ]++;
   1755         }
   1756     }
   1757     else
   1758     {
   1759         WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG,
   1760                 ("%s: pMsdu = NULL !!!!\n", __FUNCTION__));
   1761             pTxData->txDataDbgCounters.dbgNumOfNullMsdu++;
   1762     }
   1763 
   1764 
   1765     /* nullify the MSDU pointer, just in case */
   1766     pPacketId->pMsdu = NULL;
   1767 
   1768     /* mark in packet ID that XFER done was called */
   1769     pPacketId->bXferDoneCalled = TRUE;
   1770 
   1771     /*
   1772      * and check if to release packet ID. In rare cases, TX complete can be called before XFER done. In these
   1773      * cases, the packet ID should be released here.
   1774      */
   1775     if ( TRUE == pPacketId->bTxCompleteCalled )
   1776     {
   1777         bufferPool_releaseBuffer( pTxData->hBufferPool, (bufferPool_buffer_t)aPacketIdAttr );
   1778     }
   1779 
   1780     /*
   1781      * check port status - if it is disconnected, it means the STA is disconnected, and thus
   1782      * the XFER complete is ignored, to avoid race conditions (when, for example, the MSDU was
   1783      * already freed on txData_stop)
   1784      */
   1785     if ( CLOSE == pTxData->txDataPortStatus )
   1786     {
   1787         WLAN_REPORT_WARNING( pTxData->hReport, TX_DATA_MODULE_LOG,
   1788                              (" %s: XFER complete CB called when port is CLOSED!", __FUNCTION__));
   1789         return;
   1790     }
   1791 
   1792     /* try to schedule another MSDU */
   1793     txData_startTxScheduler(hTxData);
   1794 }
   1795 
   1796 
   1797 /***************************************************************************
   1798 *                           txData_txCompleteUpdate                        *
   1799 ****************************************************************************
   1800 * DESCRIPTION:  check if there are more packets in the queue to transmit,
   1801 *               and that the queues in the HW are empty. if so then release
   1802 *               the HW. else call to the scheduler.
   1803 *
   1804 * INPUTS:       hTxData - the object
   1805 *               txStatus - status of Tx (OK = ok, other = failed)
   1806 *               TxQid - The Tx queue index.
   1807 *
   1808 * OUTPUT:
   1809 *
   1810 * RETURNS:  TI_STATUS - is success then OK, else NOK
   1811 *
   1812 ***************************************************************************/
   1813 TI_STATUS txData_txCompleteUpdate(TI_HANDLE hTxData, txCompleteAttr_t *pCmpltAttr)
   1814 {
   1815     txData_t *pTxData = (txData_t *)hTxData;
   1816     UINT8 qIndex;
   1817     txPacketIdAttr_t* pPacketId = (txPacketIdAttr_t*)pCmpltAttr->packetId;
   1818 
   1819     /*
   1820      * when host processes the packets , we not working with Queue free event
   1821      * so queue status in TNET is updated in tx complete and the scheduler is triggered.
   1822      */
   1823     qIndex = pPacketId->txQid;
   1824 
   1825     WLAN_REPORT_INFORMATION(pTxData->hReport, TX_DATA_MODULE_LOG,
   1826             ("txData_txCompleteUpdate , queueId: %d  status: %d\n", qIndex, pCmpltAttr->status));
   1827 
   1828     /*
   1829      * first update that TNET Queue is available to get another packet
   1830      */
   1831     pTxData->txDataAvailableQueue[qIndex] = TRUE;
   1832 
   1833     /* update TX counters for txDistributer */
   1834     txData_UpdateTxCounters( hTxData, pCmpltAttr );
   1835 
   1836     /* update dbg counters */
   1837     pTxData->txDataDbgCounters.dbgNumOfsendPacketComplete[qIndex]++;
   1838     if (pCmpltAttr->status == SEND_COMPLETE_SUCCESS)
   1839     {
   1840         pTxData->txDataDbgCounters.dbgTxCmpltOk[qIndex]++;
   1841         pTxData->txDataDbgCounters.dbgTxCmpltOkBytes[qIndex] += pPacketId->msduDataLen;
   1842       #if defined(TI_DBG)
   1843         pTxData->txJitter[qIndex].jitter.air +=
   1844             ABS (pTxData->txJitter[qIndex].last_delay.air - pCmpltAttr->actualDurationInAir);
   1845         pTxData->txJitter[qIndex].jitter.fw +=
   1846             ABS (pTxData->txJitter[qIndex].last_delay.fw - pCmpltAttr->fwHandlingTime);
   1847         pTxData->txJitter[qIndex].last_delay.fw = pCmpltAttr->fwHandlingTime;
   1848         pTxData->txJitter[qIndex].last_delay.air = pCmpltAttr->actualDurationInAir;
   1849         pTxData->txJitter[qIndex].delay.fw += pCmpltAttr->fwHandlingTime;
   1850         pTxData->txJitter[qIndex].delay.air += pCmpltAttr->actualDurationInAir;
   1851         if (pCmpltAttr->fwHandlingTime > pTxData->txJitter[qIndex].max_delay.fw)
   1852             pTxData->txJitter[qIndex].max_delay.fw = pCmpltAttr->fwHandlingTime;
   1853         if (pCmpltAttr->actualDurationInAir > pTxData->txJitter[qIndex].max_delay.air)
   1854             pTxData->txJitter[qIndex].max_delay.air = pCmpltAttr->actualDurationInAir;
   1855       #endif
   1856     }
   1857     else
   1858     {
   1859         pTxData->txDataDbgCounters.dbgTxCmpltError[qIndex]++;
   1860         /* on error, update TX counters (xmit error count) */
   1861     }
   1862 
   1863 
   1864     /* check asynchronous in packetId */
   1865     if ( (pTxData->txDataDbgCounters.dbgNumOfMsduTxTransferCB[qIndex] +  pTxData->txDataDbgCounters.dbgNumOfMsduXferDoneInShceduler[qIndex])<
   1866          pTxData->txDataDbgCounters.dbgNumOfsendPacketComplete[qIndex])
   1867     {
   1868         WLAN_REPORT_INFORMATION(pTxData->hReport, TX_DATA_MODULE_LOG,
   1869                 ("txData_txCompleteUpdate ,  qIndex = %d Num of XFER done CB + XFER done status = %d  dbgNumOfsendPacketComplete = %d!!!!\n",
   1870                 qIndex, pTxData->txDataDbgCounters.dbgNumOfMsduTxTransferCB[qIndex] +
   1871                  pTxData->txDataDbgCounters.dbgNumOfMsduXferDoneInShceduler[qIndex],
   1872                 pTxData->txDataDbgCounters.dbgNumOfsendPacketComplete[qIndex]));
   1873     }
   1874 
   1875     /* check if XFER done was called for this packet */
   1876     if ( TRUE == pPacketId->bXferDoneCalled )
   1877     {
   1878         /* free the packet ID buffer */
   1879         bufferPool_releaseBuffer( pTxData->hBufferPool, (bufferPool_buffer_t)pPacketId );
   1880     }
   1881     else
   1882     {
   1883         /*
   1884          * in rare cases, TX complete can be called before XFER done. If this is the case,
   1885          * simply mark that TX complete was called. The packet ID will be freed on XFER done
   1886          */
   1887         pPacketId->bTxCompleteCalled = TRUE;
   1888     }
   1889 
   1890     /* run the scheduler */
   1891     txData_startTxScheduler(hTxData);
   1892 
   1893     return OK;
   1894 }
   1895 
   1896 /***************************************************************************
   1897 *                           txData_sendPacketDebug                         *
   1898 ****************************************************************************
   1899 * DESCRIPTION:  GWSI sendPacketDebug CB, called upon issuing interrupt to TNET.
   1900 *               The function calculates GWSI delay and jitter.
   1901 *
   1902 * INPUTS:       hTxData    - the object
   1903 *               uPacketId  - packet handle
   1904 * OUTPUT:
   1905 *
   1906 * RETURNS:  void
   1907 *
   1908 ***************************************************************************/
   1909 #ifdef TI_DBG
   1910 void txData_sendPacketDebug (TI_HANDLE hTxData, UINT32 uPacketId, UINT32 uDebugInfo)
   1911 {
   1912 
   1913     txData_t *pTxData = (txData_t *)hTxData;
   1914     txPacketIdAttr_t* pPacketId = (txPacketIdAttr_t *)uPacketId;
   1915 
   1916     if (pTxData != NULL && pPacketId != NULL)
   1917     {
   1918         UINT32 uXferDelay = os_timeStampUs (pTxData->hOs);
   1919 
   1920         switch (uDebugInfo)
   1921         {
   1922         case 0:
   1923             /* Calculate full XFER delay */
   1924             if (uXferDelay >= pPacketId->timeStamp[0])
   1925             {
   1926                 uXferDelay -= pPacketId->timeStamp[0];
   1927 
   1928                 /* Update jitter statistics */
   1929                 pTxData->txJitter[pPacketId->txQid].delay.xfer += uXferDelay;
   1930                 pTxData->txJitter[pPacketId->txQid].jitter.xfer +=
   1931                 ABS (uXferDelay - pTxData->txJitter[pPacketId->txQid].last_delay.xfer);
   1932                 pTxData->txJitter[pPacketId->txQid].last_delay.xfer = uXferDelay;
   1933                 pTxData->txJitter[pPacketId->txQid].count.xfer ++;
   1934                 if (uXferDelay > pTxData->txJitter[pPacketId->txQid].max_delay.xfer)
   1935                     pTxData->txJitter[pPacketId->txQid].max_delay.xfer = uXferDelay;
   1936             }
   1937             break;
   1938 
   1939         default:
   1940             if (uDebugInfo < 5)
   1941                 pPacketId->timeStamp[uDebugInfo] = uXferDelay;
   1942             break;
   1943         }
   1944     }
   1945 }
   1946 #endif
   1947 
   1948 
   1949 /***************************************************************************
   1950 *                           txData_getHighestAdmittedAc                     *
   1951 ****************************************************************************
   1952 * DESCRIPTION:  This function calculate the highest admitted AC starting from
   1953 *               a given ac index. if it fails it returns acIndex of Best effort.
   1954 *
   1955 * INPUTS:       hTxData - the object
   1956 *               qosTag - Qos tag
   1957 *
   1958 * OUTPUT:
   1959 *
   1960 * RETURNS:  OK
   1961 *           NOK
   1962 ***************************************************************************/
   1963 
   1964 static int txData_getHighestAdmittedAc(txData_t *pTxData, int startingAcIndex)
   1965 {
   1966     int qIndex;
   1967 
   1968     if ((startingAcIndex > MAX_NUM_OF_AC - 1) || (startingAcIndex < FIRST_AC_INDEX))
   1969     {
   1970         WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG,
   1971                           (" txData_getHighestAdmittedAc() :  failed, startingAcIndex = %d \n",startingAcIndex));
   1972         return QOS_AC_BE;
   1973     }
   1974 
   1975     qIndex = GET_QUEUE_INDEX(pTxData, startingAcIndex);
   1976 
   1977     /* If desired queue is not admitted, find highest Tx queue that doesn't require admission. */
   1978     if(pTxData->dataMsduListArr[qIndex]->admissionState == AC_NOT_ADMITTED)
   1979     {
   1980         while(qIndex >= 0)
   1981         {
   1982             if(pTxData->dataMsduListArr[qIndex]->admissionRequired == ADMISSION_NOT_REQUIRED)
   1983                 break;
   1984             qIndex--;
   1985         }
   1986     }
   1987 
   1988     if(qIndex < 0)
   1989     {
   1990         WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG,
   1991             (" txData_getHighestAdmittedAc() :  failed, qIndex = %d \n",qIndex));
   1992         return startingAcIndex;
   1993     }
   1994 
   1995     return pTxData->dataMsduListArr[qIndex]->acId;
   1996 }
   1997 
   1998 
   1999 
   2000 /***************************************************************************
   2001 *                           txData_selectQueueAndUpdateUserPriority                           *
   2002 ****************************************************************************
   2003 * DESCRIPTION:  This function calculate the queue index according to msdu qos tag
   2004 *               if the queue isn't admitted tt returns the highest admitted queue
   2005 *               bellow.
   2006 *               In addition, if the MSDU has been downgraded due to admission control,
   2007 *               we update the QosControl accordingly
   2008 *
   2009 * INPUTS:       hTxData - the object
   2010 *               pMSDU - pointer to packet
   2011 *
   2012 * OUTPUT:       selectedQueue - pointer to result variable which will hold the selected queue index
   2013 *               acIndex - selected admission control
   2014 *
   2015 * RETURNS:  OK
   2016 *           NOK
   2017 ***************************************************************************/
   2018 static int txData_selectQueueAndUpdateUserPriority (txData_t *pTxData, mem_MSDU_T *pMsdu, int *selectedQueue, acTrfcType_e *selectedAc)
   2019 {
   2020     int startingAcIndex;
   2021     int acIndex;
   2022     dot11_header_t      *pdot11Header;
   2023 
   2024     if (pMsdu->qosTag > MAX_NUM_OF_802_1d_TAGS - 1)
   2025     {
   2026         WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG,
   2027             (" txData_selectQueueAndUpdateUserPriority() : txData_getQueueIndex failed, pMsdu->qosTag = %d \n",pMsdu->qosTag));
   2028         *selectedAc = QOS_AC_BE;
   2029         *selectedQueue = GET_QUEUE_INDEX(pTxData, QOS_AC_BE);
   2030         return NOK;
   2031     }
   2032     /* calc ac according tag to ac table */
   2033     acIndex = startingAcIndex = pTxData->txDataQosParams.tag_ToAcClsfrTable[pMsdu->qosTag];
   2034 
   2035     /* get highest admitted AC */
   2036     if(pTxData->admissionDownGradeEnable == TRUE)
   2037         acIndex = txData_getHighestAdmittedAc(pTxData,startingAcIndex);
   2038 
   2039     /* If the highest admitted AC is not the "starting" AC that we originally desired, we were downgraded due to admission control
   2040        and we should update the QosControl field accordingly
   2041        In addition, we do not want to modify the QosControl unless the header actually contains Qos data */
   2042     if ((acIndex != startingAcIndex) && (pTxData->txDataQosParams.headerConverMode == QOS_CONVERT))
   2043     {
   2044       pdot11Header = (dot11_header_t*)(memMgr_BufData(pMsdu->firstBDPtr)+ memMgr_BufOffset(pMsdu->firstBDPtr));
   2045 
   2046       pdot11Header->qosControl = wmeAcToUpIndex[acIndex];
   2047     }
   2048 
   2049     /* convert acIndex to qIndex */
   2050     *selectedQueue = pTxData->txDataAcTrfcCtrl[acIndex].QueueIndex;
   2051     *selectedAc = (acTrfcType_e)acIndex;
   2052 
   2053     return OK;
   2054 }
   2055 
   2056 
   2057 
   2058 /***************************************************************************
   2059 *                           txData_acVoPsPollMode                          *
   2060 ****************************************************************************
   2061 * DESCRIPTION:  This function determines if we are current in power save mode
   2062 *               sending voice packet with SW ps-poll method.
   2063 *
   2064 * INPUTS:       hTxData - the object
   2065 *               qosTag - Qos tag
   2066 *
   2067 * OUTPUT:
   2068 *
   2069 * RETURNS:  TRUE
   2070 *           FALSE
   2071 ***************************************************************************/
   2072 
   2073 static BOOL txData_acVoPsPollMode(txData_t *pTxData)
   2074 {
   2075     BOOL ps_status = FALSE;
   2076 
   2077     ps_status = PowerMgr_getPsStatus(pTxData->hPowerMgr);
   2078 
   2079     if (ps_status &&
   2080         pTxData->txDataAcTrfcCtrl[QOS_AC_VO].PsMode == PS_SCHEME_LEGACY_PSPOLL)
   2081     {
   2082         return TRUE;
   2083     }
   2084 
   2085     return FALSE;
   2086 }
   2087 
   2088 
   2089 
   2090 /***************************************************************************
   2091 *                       txData_disableTransmission                         *
   2092 ****************************************************************************
   2093 * DESCRIPTION:  This function sets an internal flag in order to diable
   2094 *                   transmission.
   2095 *
   2096 * INPUTS:       hTxData - the object
   2097 *               reason  - indicates if the reason for transmission disable
   2098 *                           is measuring of non serving channel or Switch Channel command
   2099 *
   2100 * OUTPUT:
   2101 *
   2102 * RETURNS:       OK on success, NOK otherwise
   2103 ***************************************************************************/
   2104 TI_STATUS txData_disableTransmission(TI_HANDLE hTxData,txDisableReason_e reason)
   2105 {
   2106     txData_t *pTxData = (txData_t *)hTxData;
   2107     pTxData->txDisable = reason;
   2108     return OK;
   2109 }
   2110 
   2111 /***************************************************************************
   2112 *                       txData_enableTransmission                          *
   2113 ****************************************************************************
   2114 * DESCRIPTION:  This function sets an internal flag in order to enable
   2115 *                   back the transmission.
   2116 *
   2117 * INPUTS:       hTxData - the object
   2118 *
   2119 *
   2120 * OUTPUT:
   2121 *
   2122 * RETURNS:       OK on success, NOK otherwise
   2123 ***************************************************************************/
   2124 TI_STATUS txData_enableTransmission(TI_HANDLE hTxData)
   2125 {
   2126     txData_t *pTxData = (txData_t *)hTxData;
   2127     pTxData->txDisable = NO_DISABLE;
   2128     txData_startTxScheduler(pTxData);
   2129 
   2130     return OK;
   2131 }
   2132 
   2133 
   2134 
   2135 /***************************************************************************
   2136 *               txData_schedulerSelectQueueToTransmitFrom                  *
   2137 ****************************************************************************
   2138 * DESCRIPTION:  This function selects the tx queue to transmit MSDU from.
   2139 *               Management MSDUs are selected in first priority.
   2140 *               For data MSDUs, the queue selection is done by the following order:
   2141 *               1) The queue is not empty.
   2142 *               2) It is permitted to transmit (admitted and not blocked by mediumTime).
   2143 *               3) It has minimal number of Hw blocks waiting for Tx.
   2144 *                   Note: this is to fill all queues for efficient EDCA process in FW.
   2145 *               4) It has minimal history-counter (shows it wasn't selected lately).
   2146 *               5) It is the highest priority queue.
   2147 *
   2148 *               Note: Selection between queues is done by step 'n' only if all steps before it
   2149 *                       gave identical results. Also, steps 1 & 2 are mandatory for selection.
   2150 *
   2151 * INPUTS:       hTxData - the object
   2152 *
   2153 * OUTPUT:       pMsduListPtr -       a pointer to the selected queue list-pointer.
   2154 *               selectedQueueIndex - a pointer to the selected queue index.
   2155 *
   2156 * RETURNS:      TX_QUEUE_SELECTED_OK - a queue was selected.
   2157 *               NO_TX_QUEUE_SELECTED - no msdu to transmit.
   2158 ***************************************************************************/
   2159 
   2160 static TI_STATUS txData_schedulerSelectQueueToTransmitFrom( TI_HANDLE hTxData, MsduList_t** pMsduListPtr,UINT8 *selectedQueueIndex )
   2161 {
   2162     txData_t    *pTxData = (txData_t *)hTxData;
   2163     UINT8       acIndex;
   2164     int         qIndex;
   2165     UINT32      currentTimeStamp = os_timeStampMs(pTxData->hOs);
   2166     UINT32      AllQueuesMinTime = 0;
   2167     UINT32      currQueuesTime = 0;
   2168     MsduList_t  *pMsduList;
   2169     UINT32      currentQueueWeight;
   2170     UINT32      bestWeight = Q_LEAST_WEIGHT; /* Weight of preferred queue (lowest value is selected). */
   2171     int         bestWeightQueueIndex = 0;    /* Index of preferred queue. */
   2172     MsduList_t  *bestWeightQueueList = NULL; /* Pointer to the preferred queue list. */
   2173 
   2174     /* If management MSDU is waiting, select it and return. */
   2175     if( pTxData->mngMsduList->CurrNumOfMsdu > 0 )
   2176     {
   2177         *pMsduListPtr = pTxData->mngMsduList;
   2178 
   2179         /* get highest admitted AC starting from VO */
   2180         acIndex = txData_getHighestAdmittedAc(pTxData,QOS_AC_VO);
   2181 
   2182         /* convert acIndex to queue index */
   2183         *selectedQueueIndex = GET_QUEUE_INDEX(pTxData,acIndex);
   2184 
   2185 
   2186         if (pTxData->txDataAvailableQueue[*selectedQueueIndex] == TRUE)
   2187         {
   2188             WLAN_REPORT_INFORMATION (pTxData->hReport, TX_DATA_MODULE_LOG,
   2189                (" txData_schedulerSelectQueueToTransmitFrom() : Management MSDU selected to Tx\n"));
   2190             return TX_QUEUE_SELECTED_OK;
   2191         }
   2192         else
   2193         {
   2194             WLAN_REPORT_INFORMATION (pTxData->hReport, TX_DATA_MODULE_LOG,
   2195                 (" txData_schedulerSelectQueueToTransmitFrom() : pTxData->txDataAvailableQueue[%d] = FALSE  \n",*selectedQueueIndex));
   2196         }
   2197     }
   2198 
   2199 
   2200     /*
   2201      * Loop over all core data Tx queues and look for the preferred one to transmit from:
   2202      * =================================================================================
   2203      *   Note:  Starting from the highest priority ensures that if multiple queues have
   2204      *            identical status, the highest priority one among them will be selected.
   2205      */
   2206     for (qIndex = MAX_NUM_OF_TX_QUEUES - 1; qIndex >= 0; qIndex--)
   2207     {
   2208         pMsduList = pTxData->dataMsduListArr[qIndex];
   2209 
   2210         if (pMsduList->selectionHistoryCounter)
   2211             pMsduList->selectionHistoryCounter--;
   2212 
   2213         /* If queue is empty or is not admitted to transmit, continue to next queue.  */
   2214         if ((pMsduList->CurrNumOfMsdu == 0) || (pMsduList->admissionState != AC_ADMITTED))
   2215             continue;
   2216 
   2217         /*
   2218          * see only if Queue is available.
   2219          * continue to the next Q if not available
   2220          */
   2221         if (pTxData->txDataAvailableQueue[qIndex] == FALSE)
   2222             continue;
   2223 
   2224             /* If we are configured to enforce excess Tx time limits, handle the algorithm. */
   2225             if (pMsduList->useAdmissionAlgo)
   2226             {
   2227             /* Handle case of timer wraparound. */
   2228                 if (currentTimeStamp < pMsduList->lastTimeStamp)
   2229                     pMsduList->lastTimeStamp = 0;
   2230 
   2231             /* If we it's not time to enable Tx yet for this queue, update time to try again if needed. */
   2232             if (currentTimeStamp < pMsduList->lastTimeStamp + pMsduList->enableTransmissionTime)
   2233             {
   2234                 /* currQueuesTime represents the amount of time the tx scheduler has to wait before
   2235                     it will be able to transmit from this queue. */
   2236                     currQueuesTime = (pMsduList->lastTimeStamp + pMsduList->enableTransmissionTime - currentTimeStamp);
   2237 
   2238                 /* Update the minimum time left till we can Tx from any of the queues. */
   2239                 if (AllQueuesMinTime == 0)
   2240                         AllQueuesMinTime = currQueuesTime;
   2241                     else
   2242                         AllQueuesMinTime = MIN(AllQueuesMinTime, currQueuesTime);
   2243 
   2244                 /* We can't Tx from this queue yet so continue to next queue. */
   2245                 continue;
   2246             }
   2247         }
   2248 
   2249         /****  If we got here, this queue has something to Tx and it is permitted to Tx now. ****/
   2250 
   2251         /* Now calculate this queue's weight for selection:
   2252          *      Higher 16 bits:  Number of used HW blocks by this AC.
   2253          *      Lower  16 bits:  Count down from last time it was selected. */
   2254         currentQueueWeight  = (UINT32)TnetwDrv_txHwQueue_GetUsedHwBlks( pTxData->hTnetwDrv, qIndex ) << 16;
   2255         currentQueueWeight |= (UINT32)pMsduList->selectionHistoryCounter;
   2256 
   2257         /* If current queue's weight isn't lower (lower is better!) than previous queues,
   2258              continue to next queue. */
   2259         if (currentQueueWeight >= bestWeight)
   2260             continue;
   2261 
   2262         /* Save weight, index and list-pointer of best candidate queue so far . */
   2263         bestWeight = currentQueueWeight;
   2264         bestWeightQueueIndex = qIndex;
   2265         bestWeightQueueList = pMsduList;
   2266     }
   2267 
   2268 
   2269     /* If we have a delayed queue, we need to re-trigger the scheduler later by timer. */
   2270     if (AllQueuesMinTime != 0)
   2271     {
   2272         /* msdu is waiting to transmit */
   2273         WLAN_REPORT_INFORMATION (pTxData->hReport, TX_DATA_MODULE_LOG,
   2274             (" txData_schedulerSelectQueueToTransmitFrom() : Start mediumTime timer for - %d ms\n", AllQueuesMinTime));
   2275 
   2276         if ( pTxData->bSchedulerTimerRunning == TRUE )
   2277         {
   2278             os_timerStop(pTxData->hOs, pTxData->pSchedulerTimer);
   2279         }
   2280         os_timerStart(pTxData->hOs,pTxData->pSchedulerTimer, AllQueuesMinTime, FALSE);
   2281         pTxData->bSchedulerTimerRunning = TRUE;
   2282     }
   2283 
   2284 
   2285     /* If we have a queue we can transmit from:  */
   2286     if (bestWeight != Q_LEAST_WEIGHT)
   2287     {
   2288         /* Set selected queue history counter to its initial value, indicating it was selected
   2289             lately and its priority is temporarily reduced. */
   2290         bestWeightQueueList->selectionHistoryCounter = Q_SELECTION_HISTORY_LEVEL;
   2291 
   2292         /* Provide the selected queue index and list pointer. */
   2293         *pMsduListPtr = bestWeightQueueList;
   2294         *selectedQueueIndex = bestWeightQueueIndex;
   2295 
   2296         WLAN_REPORT_INFORMATION (pTxData->hReport, TX_DATA_MODULE_LOG,
   2297             (" txData_schedulerSelectQueueToTransmitFrom() : Selected-TxQ = %d,  Weight = 0x%x\n",
   2298                 bestWeightQueueIndex, bestWeight));
   2299 
   2300         return TX_QUEUE_SELECTED_OK;
   2301     }
   2302 
   2303 
   2304     /* If we got here, no queue is currently suitable for transmition. */
   2305     WLAN_REPORT_DEBUG_TX(pTxData->hReport,
   2306         (" txData_schedulerSelectQueueToTransmitFrom() : No queue selected for Tx\n"));
   2307 
   2308     return NO_TX_QUEUE_SELECTED;
   2309 }
   2310 
   2311 
   2312 
   2313 /***************************************************************************
   2314 *                           txData_getParam                                *
   2315 ****************************************************************************
   2316 * DESCRIPTION:  get a specific parameter
   2317 *
   2318 * INPUTS:       hTxData - the object
   2319 *
   2320 * OUTPUT:       pParamInfo - structure which include the value of
   2321 *               the requested parameter
   2322 *
   2323 * RETURNS:      OK
   2324 *               NOK
   2325 ***************************************************************************/
   2326 TI_STATUS txData_getParam(TI_HANDLE hTxData, paramInfo_t *pParamInfo)
   2327 {
   2328     txData_t *pTxData = (txData_t *)hTxData;
   2329     UINT32  tID;
   2330 
   2331     /* check handle validity */
   2332     if( pTxData == NULL  )
   2333     {
   2334         WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG,
   2335             (" txData_getParam() : Illegal parametrs value \n"));
   2336         return NOK;
   2337     }
   2338 
   2339     switch (pParamInfo->paramType)
   2340     {
   2341         case TX_DATA_PORT_STATUS_PARAM:
   2342             pParamInfo->content.txDataPortStatus = pTxData->txDataPortStatus;
   2343             break;
   2344 
   2345         case TX_DATA_CURRENT_PRIVACY_INVOKE_MODE_PARAM:
   2346             pParamInfo->content.txDataCurrentPrivacyInvokedMode = pTxData->txDataCurrentPrivacyInvokedMode;
   2347             break;
   2348 
   2349         case TX_DATA_EAPOL_ENCRYPTION_STATUS_PARAM:
   2350             pParamInfo->content.txDataEapolEncryptionStatus = pTxData->txDataEapolEncryptionStatus;
   2351             break;
   2352 
   2353         case TX_DATA_CONVERT_HEADER_MODE:
   2354             pParamInfo->content.txDataQosParams.qosParams.headerConverMode = pTxData->txDataQosParams.headerConverMode;
   2355             break;
   2356 
   2357         case TX_DATA_COUNTERS_PARAM:
   2358             os_memoryCopy( pTxData->hOs, &(pTxData->tempTxDataCounters[ 0 ]), &(pTxData->txDataCounters[ 0 ]),
   2359                            sizeof(txDataCounters_t) * MAX_NUM_OF_TX_QUEUES );
   2360             pParamInfo->content.pTxDataCounters = &(pTxData->tempTxDataCounters[ 0 ]);
   2361             break;
   2362 
   2363         case TX_DATA_REPORT_TS_STATISTICS:
   2364             tID = GET_QUEUE_INDEX(pTxData, pParamInfo->content.tsMetricsCounters.acID);
   2365             os_memoryCopy(pTxData->hOs,
   2366                           pParamInfo->content.tsMetricsCounters.pTxDataCounters,
   2367                           &(pTxData->txDataReportedCounters[tID]),
   2368                           sizeof(txDataCounters_t));
   2369             os_memoryZero(pTxData->hOs,
   2370                           &(pTxData->txDataReportedCounters[tID]),
   2371                           sizeof(txDataCounters_t));
   2372             break;
   2373 
   2374         case TX_DATA_GET_VAD:
   2375             pParamInfo->content.txDataVadTimerParams.vadTimerEnabled  = pTxData->bVadTimerEnabled;
   2376             pParamInfo->content.txDataVadTimerParams.vadTimerDuration = pTxData->vadTimerDuration;
   2377 
   2378        	    WLAN_REPORT_INFORMATION(pTxData->hReport, TX_DATA_MODULE_LOG,
   2379 	    	    ("txData_setParams: GET_VAD (enable=%d; duration=%d ms)\n",
   2380     		      pTxData->bVadTimerEnabled, pTxData->vadTimerDuration));
   2381 
   2382         	break;
   2383 
   2384         default:
   2385             return (PARAM_NOT_SUPPORTED);
   2386 /*            WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG,
   2387                 (" txData_getParam() : PARAMETER NOT SUPPORTED \n"));
   2388             return NOK;
   2389             break; - unreachable*/
   2390     }
   2391 
   2392     return (OK);
   2393 }
   2394 
   2395 
   2396 
   2397 /***************************************************************************
   2398 *                           txData_setParam                                *
   2399 ****************************************************************************
   2400 * DESCRIPTION:  set a specific parameter
   2401 *
   2402 * INPUTS:       hTxData - the object
   2403 *               pParamInfo - structure which include the value to set for
   2404 *               the requested parameter
   2405 *
   2406 * OUTPUT:
   2407 *
   2408 * RETURNS:      OK
   2409 *               NOK
   2410 ***************************************************************************/
   2411 TI_STATUS txData_setParam(TI_HANDLE hTxData, paramInfo_t *pParamInfo)
   2412 {
   2413     txData_t *pTxData = (txData_t *)hTxData;
   2414     UINT8 queueIndex;
   2415     UINT8 acID = pParamInfo->content.txDataQosParams.acID; /* Note: acID is relevant only in
   2416                                                                     some of the param-types!! */
   2417 
   2418     /* check handle validity */
   2419     if( pTxData == NULL  )
   2420     {
   2421         WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG,
   2422             (" txData_setParam() : Illegal parametrs value \n"));
   2423         return NOK;
   2424     }
   2425 
   2426 
   2427     switch (pParamInfo->paramType)
   2428     {
   2429     case TX_DATA_PORT_STATUS_PARAM:
   2430 
   2431     {
   2432         /* Set the new TX port status CLOSE/OPEN_NOTIFY/OPEN_EAPOL/OPEN */
   2433         WLAN_REPORT_DEBUG_TX (pTxData->hReport,
   2434                               (("txData_setParam: Set txDataPortStatus from 0x%x to 0x%x\n"),
   2435                                 pTxData->txDataPortStatus , pParamInfo->content.txDataPortStatus));
   2436 
   2437         pTxData->txDataPortStatus = pParamInfo->content.txDataPortStatus;
   2438         break;
   2439     }
   2440 
   2441     case TX_DATA_CURRENT_PRIVACY_INVOKE_MODE_PARAM:
   2442         pTxData->txDataCurrentPrivacyInvokedMode = pParamInfo->content.txDataCurrentPrivacyInvokedMode;
   2443         break;
   2444 
   2445     case TX_DATA_EAPOL_ENCRYPTION_STATUS_PARAM:
   2446         pTxData->txDataEapolEncryptionStatus = pParamInfo->content.txDataEapolEncryptionStatus;
   2447         break;
   2448 
   2449     case TX_DATA_HAL_INTERFACE_STATUS_PARAM:
   2450         pTxData->txDataHalInterfaceStatus = pParamInfo->content.txDataHalInterfaceStatus;
   2451         break;
   2452 
   2453     case TX_DATA_PS_MODE_PARAM:
   2454         pTxData->txDataAcTrfcCtrl[acID].PsMode =
   2455             pParamInfo->content.txDataQosParams.acTrfcCtrl.PsMode;
   2456         break;
   2457 
   2458     case TX_DATA_CONFIG_TX_QUEUE_SIZE:
   2459         queueIndex = pParamInfo->content.txDataQosParams.acTrfcCtrl.QueueIndex;
   2460            pTxData->txDataAcTrfcCtrl[acID].TxQueueSize =
   2461                pParamInfo->content.txDataQosParams.acTrfcCtrl.TxQueueSize;
   2462         if(queueIndex >= MAX_NUM_OF_TX_QUEUES)
   2463            {
   2464                WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG,
   2465                ("Error configure Data MsduList , wrong queue index = %d\n", queueIndex));
   2466             return NOK;
   2467         }
   2468         pTxData->dataMsduListArr[queueIndex]->acId = acID;
   2469         pTxData->txDataAcTrfcCtrl[acID].QueueIndex = queueIndex;
   2470 
   2471         /* also set the opposute direction conversion table (queue ID -> ac ID) */
   2472         txData_SetQidToAcTable( hTxData, queueIndex, queueIndex, acID );
   2473 
   2474         if( (msduList_SetMsduListNumOfElements( pTxData->dataMsduListArr[queueIndex],
   2475                 pTxData->txDataAcTrfcCtrl[acID].TxQueueSize)) != OK )
   2476            {
   2477                WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG,
   2478                        ("Error configure MgmtMsduList\n"));
   2479                return NOK;
   2480            }
   2481         break;
   2482 
   2483     case TX_DATA_CONFIG_TX_QUEUE_OVFLOW_POLICY:
   2484         queueIndex = pParamInfo->content.txDataQosParams.acTrfcCtrl.QueueIndex;
   2485         pTxData->txDataAcTrfcCtrl[acID].QueueOvFlowPolicy = pParamInfo->content.txDataQosParams.acTrfcCtrl.QueueOvFlowPolicy;
   2486         if(queueIndex >= MAX_NUM_OF_TX_QUEUES)
   2487         {
   2488             WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG,
   2489                  ("Error configure MsduList over flow policy , wrong queue index = %d\n",queueIndex));
   2490             return NOK;
   2491         }
   2492         pTxData->txDataAcTrfcCtrl[acID].QueueIndex  = queueIndex;
   2493         msduList_SetMsduListOverFlowPolicy(pTxData->dataMsduListArr[pTxData->txDataAcTrfcCtrl[acID].QueueIndex],
   2494                                            pTxData->txDataAcTrfcCtrl[acID].QueueOvFlowPolicy);
   2495         break;
   2496 
   2497     case TX_DATA_CONFIG_AC_MSDU_LIFE_TIME:
   2498         pTxData->txDataAcTrfcCtrl[acID].MsduLifeTime = 1000 * pParamInfo->content.txDataQosParams.acTrfcCtrl.MsduLifeTime;
   2499         break;
   2500 
   2501     case TX_DATA_CONFIG_AC_ACK_POLICY:
   2502         pTxData->txDataAcTrfcCtrl[acID].ackPolicy = pParamInfo->content.txDataQosParams.acTrfcCtrl.ackPolicy;
   2503         break;
   2504 
   2505     case TX_DATA_AC_ADMISSION_STATE:
   2506         pTxData->dataMsduListArr[GET_QUEUE_INDEX(pTxData, acID)]->admissionRequired =
   2507             pParamInfo->content.txDataQosParams.qosParams.admissionRequired;
   2508 
   2509         pTxData->dataMsduListArr[GET_QUEUE_INDEX(pTxData, acID)]->admissionState =
   2510             pParamInfo->content.txDataQosParams.qosParams.admissionState;
   2511         break;
   2512 
   2513     case TX_DATA_CONVERT_HEADER_MODE:
   2514         pTxData->txDataQosParams.headerConverMode = pParamInfo->content.txDataQosParams.qosParams.headerConverMode;
   2515         break;
   2516 
   2517     case TX_DATA_TAG_TO_AC_CLASSIFIER_TABLE:
   2518         os_memoryCopy(pTxData->hOs,(pTxData->txDataQosParams.tag_ToAcClsfrTable),
   2519             pParamInfo->content.txDataQosParams.qosParams.tag_ToAcClsfrTable,sizeof(acTrfcType_e) * MAX_NUM_OF_802_1d_TAGS);
   2520         break;
   2521 
   2522     case TX_DATA_SET_AC_QUEUE_INDEX:
   2523         queueIndex = pParamInfo->content.txDataQosParams.acTrfcCtrl.QueueIndex;
   2524 
   2525         pTxData->txDataAcTrfcCtrl[pParamInfo->content.txDataQosParams.acID].QueueIndex = queueIndex;
   2526         /* also set the opposute direction conversion table (queue ID -> ac ID) */
   2527         txData_SetQidToAcTable( hTxData, queueIndex, queueIndex, acID );
   2528         break;
   2529 
   2530     case TX_DATA_SET_MEDIUM_USAGE_THRESHOLD:
   2531        txData_setMediumUsageThresholds (hTxData,
   2532             (UINT8)pParamInfo->content.txDataMediumUsageThreshold.uAC,
   2533             pParamInfo->content.txDataMediumUsageThreshold.uHighThreshold,
   2534             pParamInfo->content.txDataMediumUsageThreshold.uLowThreshold);
   2535        break;
   2536 
   2537     case TX_DATA_GET_MEDIUM_USAGE_THRESHOLD:
   2538         /* SET operation is performed, but actually this is only for AC parameter transfer from Utility Adapter to driver, since copy
   2539           of user supplied block of data (and vice versa) is only performed in SetParam calls, the driver can also modify the supplied
   2540           structure and thus return it to user mode */
   2541         queueIndex = pTxData->txDataAcTrfcCtrl[pParamInfo->content.txDataMediumUsageThreshold.uAC].QueueIndex;
   2542 
   2543         /* get threshold */
   2544         pParamInfo->content.txDataMediumUsageThreshold.uHighThreshold = pTxData->dataMsduListArr[queueIndex]->highMediumUsageThreshold;
   2545         pParamInfo->content.txDataMediumUsageThreshold.uLowThreshold = pTxData->dataMsduListArr[queueIndex]->lowMediumUsageThreshold;
   2546 
   2547         break;
   2548 
   2549     case TX_DATA_POLL_AP_PACKETS_FROM_AC:
   2550 
   2551          queueIndex = pTxData->txDataAcTrfcCtrl[pParamInfo->content.txDataPollApPacketsFromACid].QueueIndex;
   2552 
   2553          if (queueIndex <= QOS_AC_MAX)
   2554             return (txData_sendVadFrame (pTxData, queueIndex));
   2555          else
   2556             return PARAM_VALUE_NOT_VALID;
   2557 
   2558 /*       break; - unreachable */
   2559 
   2560     case TX_DATA_ENCRYPTION_FIELD_SIZE:
   2561         /* set the space to reserve for encrypted frames */
   2562         pTxData->encryptionFieldSize = pParamInfo->content.txDataEncryptionFieldSize;
   2563         break;
   2564 
   2565     case TX_DATA_RESET_COUNTERS_PARAM:
   2566         txData_resetCounters( hTxData );
   2567         break;
   2568 
   2569     case TX_DATA_SET_VAD:
   2570 	{
   2571 	    BOOL bVadTimerEnabled;
   2572 	    UINT16 vadTimerDuration;
   2573 
   2574        	    bVadTimerEnabled = pParamInfo->content.txDataVadTimerParams.vadTimerEnabled;
   2575             vadTimerDuration = pParamInfo->content.txDataVadTimerParams.vadTimerDuration;
   2576    	    WLAN_REPORT_INFORMATION(pTxData->hReport, TX_DATA_MODULE_LOG,
   2577     	    	("txData_setParams: SET_VAD (enable=%d; duration=%d ms)\n",
   2578     	    	  bVadTimerEnabled, vadTimerDuration));
   2579 
   2580     	    txData_setVadTimer(hTxData, bVadTimerEnabled, vadTimerDuration);
   2581 	}
   2582 
   2583     	break;
   2584 
   2585     default:
   2586         return (PARAM_NOT_SUPPORTED);
   2587 /*        WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG,
   2588             (" txData_setParam() : PARAMETER NOT SUPPORTED \n"));
   2589         return NOK;
   2590         break; - unreachable */
   2591     }
   2592 
   2593     return (OK);
   2594 }
   2595 
   2596 
   2597 /***************************************************************************
   2598 *                   txData_convertEthToWlanHeader                          *
   2599 ****************************************************************************
   2600 * DESCRIPTION:  this function convert the msdu header from ethernet format
   2601 *               to the 802.11 header format
   2602 *
   2603 * INPUTS:       hTxData - the object
   2604 *               pMsdu - msdu in ethernet format
   2605 *
   2606 * OUTPUT:       pMsdu - msdu in 802.11 format
   2607 *
   2608 * RETURNS:
   2609 ***************************************************************************/
   2610 static void txData_convertEthToWlanHeader (txData_t *pTxData, mem_MSDU_T *pMsdu)
   2611 {
   2612     EthernetHeader_t    *pEthHeader;
   2613     dot11_header_t      dot11Header;
   2614     Wlan_LlcHeader_T    WlanSnapHeader;
   2615     UINT16              swapedTypeLength;
   2616     bssType_e           currBssType;
   2617     macAddress_t        currBssId;
   2618     UINT8               SNAP_OUI_802_1H[] = SNAP_OUI_802_1H_BYTES;
   2619     UINT8               SNAP_OUI_RFC1042[] = SNAP_OUI_RFC1042_BYTES;
   2620     acTrfcType_e        acIndex;
   2621     char*               pData;
   2622 
   2623     /* initialize the frame header length */
   2624     pMsdu->headerLen = txData_GetWlanHeaderLength( pTxData,
   2625                                                    memMgr_BufData(pMsdu->firstBDPtr) +
   2626                                                    memMgr_BufOffset(pMsdu->firstBDPtr),
   2627                                                    pMsdu->txFlags );
   2628 
   2629     /*
   2630      * Set the Eth pointer to the beginning of the first Bd
   2631         */
   2632        pEthHeader = (EthernetHeader_t*)(memMgr_BufData(pMsdu->firstBDPtr) + memMgr_BufOffset(pMsdu->firstBDPtr));
   2633 
   2634        /*
   2635      * Initialize working copy of the dot11header to zero
   2636         */
   2637     os_memoryZero(pTxData->hOs,&dot11Header,sizeof(dot11_header_t));
   2638 
   2639         /*
   2640          * Convert the header 802.3 ---> 802.11 onto the dot11Header working copy
   2641          */
   2642     /* set Qos control */
   2643     if( pTxData->txDataQosParams.headerConverMode == QOS_CONVERT )
   2644     {
   2645         /* set qos Tag */
   2646         dot11Header.qosControl = ((UINT16)pMsdu->qosTag & QOS_CONTROL_TAG_MASK);
   2647 
   2648         /*
   2649                  * set ac ack policy according to the
   2650                  * Ack policy defined for the particular AC
   2651                  */
   2652         acIndex = (acTrfcType_e)GET_WME_AC_TYPE_FROM_MSDU(pMsdu);
   2653         if(pTxData->txDataAcTrfcCtrl[acIndex].ackPolicy == ACK_POLICY_LEGACY)
   2654         {
   2655             dot11Header.qosControl &= ~DOT11_QOS_CONTROL_DONT_ACK;
   2656         }
   2657         else
   2658         {
   2659             dot11Header.qosControl |= DOT11_QOS_CONTROL_DONT_ACK;
   2660         }
   2661     }
   2662 
   2663     /* receive BssId and Bss Type from control module */
   2664     ctrlData_getCurrBssTypeAndCurrBssId(pTxData->hCtrlData, &currBssId, &currBssType);
   2665 
   2666     if (currBssType == BSS_INDEPENDENT)
   2667     {
   2668         MAC_COPY(pTxData->hOs,(&dot11Header.address1),(&pEthHeader->DstAddr));
   2669         MAC_COPY(pTxData->hOs,(&dot11Header.address2),(&pEthHeader->SrcAddr));
   2670         MAC_COPY(pTxData->hOs,(&dot11Header.address3),(&currBssId));
   2671 
   2672         if( pTxData->txDataQosParams.headerConverMode == QOS_CONVERT )
   2673             dot11Header.fc = DOT11_FC_DATA_QOS;
   2674         else
   2675             dot11Header.fc = DOT11_FC_DATA;
   2676     }
   2677     else /* infrastructure BSS */
   2678     {
   2679         MAC_COPY(pTxData->hOs,(&dot11Header.address1),(&currBssId));
   2680         MAC_COPY(pTxData->hOs,(&dot11Header.address2),(&pEthHeader->SrcAddr));
   2681         MAC_COPY(pTxData->hOs,(&dot11Header.address3),(&pEthHeader->DstAddr));
   2682 
   2683         if( pTxData->txDataQosParams.headerConverMode == QOS_CONVERT )
   2684             dot11Header.fc = DOT11_FC_DATA_QOS | DOT11_FC_TO_DS;
   2685         else
   2686             dot11Header.fc = DOT11_FC_DATA | DOT11_FC_TO_DS;
   2687     }
   2688 
   2689     swapedTypeLength = wlan_htons(pEthHeader->TypeLength);
   2690 
   2691     /* Detect the packet type and decide if to create a     */
   2692     /*          new SNAP or leave the original LLC.         */
   2693     /*------------------------------------------------------*/
   2694     if( swapedTypeLength > ETHERNET_MAX_PAYLOAD_SIZE )
   2695     {
   2696         /* Create the SNAP Header:     */
   2697         /*-----------------------------*/
   2698         /*
   2699          * Make a working copy of the SNAP header
   2700          * initialised to zero
   2701          */
   2702         os_memoryZero(pTxData->hOs,&WlanSnapHeader,sizeof(Wlan_LlcHeader_T));
   2703         WlanSnapHeader.DSAP = SNAP_CHANNEL_ID;
   2704         WlanSnapHeader.SSAP = SNAP_CHANNEL_ID;
   2705         WlanSnapHeader.Control = LLC_CONTROL_UNNUMBERED_INFORMATION;
   2706 
   2707         /* Check to see if the Ethertype matches anything in the translation     */
   2708         /* table (Appletalk AARP or DixII/IPX).  If so, add the 802.1h           */
   2709         /* SNAP.                                                                 */
   2710 
   2711         if(( ETHERTYPE_APPLE_AARP == swapedTypeLength ) ||
   2712            ( ETHERTYPE_DIX_II_IPX == swapedTypeLength ))
   2713         {
   2714             /* Fill out the SNAP Header with 802.1H extention   */
   2715             os_memoryCopy(pTxData->hOs, &WlanSnapHeader.OUI, SNAP_OUI_802_1H,
   2716                             sizeof( WlanSnapHeader.OUI ) );
   2717         }
   2718         else
   2719         {
   2720             /* otherwise, add the RFC1042 SNAP   */
   2721             os_memoryCopy(pTxData->hOs, &WlanSnapHeader.OUI, SNAP_OUI_RFC1042,
   2722                             sizeof( WlanSnapHeader.OUI) );
   2723         }
   2724         /* set type length */
   2725         WlanSnapHeader.Type = pEthHeader->TypeLength;
   2726     }
   2727 
   2728     /*
   2729      * Now - copy wlan header and snap overriding Ethernet header.
   2730      */
   2731 
   2732     /*
   2733        first the wlan header
   2734        the header might not include the qosControl which will be erase
   2735        later by the snap header
   2736      */
   2737     /* pData starts after the reserved place for bus txn and the TxDescriptor */
   2738 
   2739     /* update data offset - bus txn extra space + TxDescriptor */
   2740     memMgr_BufOffset(pMsdu->firstBDPtr) = TX_TOTAL_OFFSET_BEFORE_DATA;
   2741 
   2742     pData = memMgr_BufData(pMsdu->firstBDPtr) + memMgr_BufOffset(pMsdu->firstBDPtr);
   2743     os_memoryCopy(pTxData->hOs,pData,&dot11Header,pMsdu->headerLen);
   2744 
   2745     /* update data length */
   2746     pMsdu->dataLen = pMsdu->dataLen - ETHERNET_HDR_LEN + pMsdu->headerLen;
   2747 
   2748     /* now the snap */
   2749     if( swapedTypeLength > ETHERNET_MAX_PAYLOAD_SIZE )
   2750     {
   2751         pData += (pMsdu->headerLen - sizeof(Wlan_LlcHeader_T));
   2752         os_memoryCopy(pTxData->hOs,pData,&WlanSnapHeader,sizeof(Wlan_LlcHeader_T));
   2753     }
   2754 
   2755     return;
   2756 }
   2757 
   2758 /***************************************************************************
   2759 *                       txData_resetCounters                               *
   2760 ****************************************************************************
   2761 * DESCRIPTION:  Reset the tx data module counters
   2762 *
   2763 * INPUTS:       hTxData - the object
   2764 *
   2765 * OUTPUT:
   2766 *
   2767 * RETURNS:
   2768 ***************************************************************************/
   2769 void txData_resetCounters(TI_HANDLE hTxData)
   2770 {
   2771     txData_t *pTxData = (txData_t *)hTxData;
   2772 
   2773     os_memoryZero(pTxData->hOs, &pTxData->txDataCounters, sizeof(txDataCounters_t) * MAX_NUM_OF_TX_QUEUES);
   2774     pTxData->currentConsecutiveRetryFail = 0;
   2775 }
   2776 
   2777 /***************************************************************************
   2778 *                       txData_resetDbgCounters                            *
   2779 ****************************************************************************
   2780 * DESCRIPTION:  Reset the tx data module debug counters
   2781 *
   2782 * INPUTS:       hTxData - the object
   2783 *
   2784 * OUTPUT:
   2785 *
   2786 * RETURNS:
   2787 ***************************************************************************/
   2788 void txData_resetDbgCounters(TI_HANDLE hTxData)
   2789 {
   2790     txData_t *pTxData = (txData_t *)hTxData;
   2791 
   2792     os_memoryZero(pTxData->hOs, &pTxData->txDataDbgCounters, sizeof(txDataDbgCounters_t));
   2793 }
   2794 
   2795 /***************************************************************************
   2796 *                       txData_DistributorTxEvent                          *
   2797 ****************************************************************************
   2798 * DESCRIPTION:
   2799 *
   2800 *
   2801 * INPUTS:
   2802 *
   2803 *
   2804 *
   2805 * OUTPUT:
   2806 *
   2807 * RETURNS:
   2808 *
   2809 ***************************************************************************/
   2810 static VOID txData_DistributorTxEvent(txData_t *pTxData,UINT16 Mask,int DataLen)
   2811 {
   2812    if(pTxData->TxEventDistributor)
   2813      DistributorMgr_EventCall(pTxData->TxEventDistributor,Mask,DataLen);
   2814 
   2815 }
   2816 
   2817 /***************************************************************************
   2818 *                       txData_RegNotif                                    *
   2819 ****************************************************************************/
   2820 TI_HANDLE txData_RegNotif(TI_HANDLE hTxData,UINT16 EventMask,GeneralEventCall_t CallBack,TI_HANDLE context,UINT32 Cookie)
   2821 {
   2822     txData_t *pTxData = (txData_t *)hTxData;
   2823     if (!hTxData)
   2824         return NULL;
   2825     return DistributorMgr_Reg(pTxData->TxEventDistributor,EventMask,(TI_HANDLE)CallBack,context,Cookie);
   2826 }
   2827 
   2828 
   2829 /***************************************************************************
   2830 *                       txData_AddToNotifMask                              *
   2831 ****************************************************************************/
   2832 TI_STATUS txData_AddToNotifMask(TI_HANDLE hTxData,TI_HANDLE Notifh,UINT16 EventMask)
   2833 {
   2834     txData_t *pTxData = (txData_t *)hTxData;
   2835     if (!hTxData)
   2836         return NOK;
   2837     return DistributorMgr_AddToMask(pTxData->TxEventDistributor,Notifh,EventMask);
   2838 }
   2839 
   2840 
   2841 /***************************************************************************
   2842 *                       TxData_UnRegNotif                                  *
   2843 ****************************************************************************/
   2844 TI_STATUS txData_UnRegNotif(TI_HANDLE hTxData,TI_HANDLE RegEventHandle)
   2845 {
   2846     TI_STATUS status;
   2847     txData_t *pTxData = (txData_t *)hTxData;
   2848 
   2849     if (!hTxData)
   2850         return NOK;
   2851 
   2852     status = DistributorMgr_UnReg(pTxData->TxEventDistributor,RegEventHandle);
   2853     return status;
   2854 }
   2855 
   2856 /****************************************************************************
   2857  *                      txData_SetTxDelayCounters()
   2858  ****************************************************************************
   2859  * DESCRIPTION:          Update transmission path delay counters.
   2860 *
   2861 * INPUTS:       hTxData - the object
   2862 *               txQid - the queue to count delay for
   2863 *               pTxCompleteAttr - struct containing the necessary FW delay data
   2864 *               driverDelay - the time consumed in driver for packet transmission
   2865 *
   2866 * OUTPUT:
   2867 *
   2868 * RETURNS:
   2869  ****************************************************************************/
   2870 static void txData_SetTxDelayCounters( TI_HANDLE hTxData, UINT32 txQid, txCompleteAttr_t *pTxCompleteAttr, UINT32 driverDelay )
   2871 {
   2872     txData_t *pTxData = (txData_t *)hTxData;
   2873     int     rangeIndex;
   2874     UINT32  totalTxDelayMs;
   2875 
   2876     /* Add 1 to the total time so that Total time will always be greater than fwHandlingTime */
   2877     totalTxDelayMs = driverDelay + (pTxCompleteAttr->fwHandlingTime / 1000) + 1;
   2878 
   2879     /* Increment the delay range counter that the current packet Tx delay falls in. */
   2880     for (rangeIndex = TX_DELAY_RANGE_MIN; rangeIndex <= TX_DELAY_RANGE_MAX; rangeIndex++)
   2881     {
   2882         if ( (totalTxDelayMs >= txDelayRangeStart[rangeIndex]) &&
   2883              (totalTxDelayMs <= txDelayRangeEnd  [rangeIndex]) )
   2884         {
   2885             pTxData->txDataCounters[ txQid ].txDelayHistogram[ rangeIndex ]++;
   2886             pTxData->txDataReportedCounters[ txQid ].txDelayHistogram[ rangeIndex ]++;
   2887             break;
   2888         }
   2889     }
   2890 
   2891     /* Update total delay and MAC delay sums and packets number for average delay calculation. */
   2892     if (pTxData->txDataCounters[ txQid ].SumTotalDelayMs < 0x7FFFFFFF) /* verify we are not close to the edge. */
   2893     {
   2894         pTxData->txDataCounters[ txQid ].NumPackets++;
   2895         pTxData->txDataCounters[ txQid ].SumTotalDelayMs += totalTxDelayMs;
   2896         pTxData->txDataCounters[ txQid ].SumFWDelayUs += pTxCompleteAttr->fwHandlingTime;
   2897         pTxData->txDataCounters[ txQid ].SumMacDelayUs += pTxCompleteAttr->mediumDelay;
   2898     }
   2899     else  /* If we get close to overflow, restart average accumulation. */
   2900     {
   2901         pTxData->txDataCounters[ txQid ].NumPackets = 1;
   2902         pTxData->txDataCounters[ txQid ].SumTotalDelayMs = totalTxDelayMs;
   2903         pTxData->txDataCounters[ txQid ].SumFWDelayUs = pTxCompleteAttr->fwHandlingTime;
   2904         pTxData->txDataCounters[ txQid ].SumMacDelayUs = pTxCompleteAttr->mediumDelay;
   2905     }
   2906     pTxData->txDataReportedCounters[ txQid ].NumPackets++;
   2907     pTxData->txDataReportedCounters[ txQid ].SumTotalDelayMs += totalTxDelayMs;
   2908     pTxData->txDataReportedCounters[ txQid ].SumFWDelayUs += pTxCompleteAttr->fwHandlingTime;
   2909     pTxData->txDataReportedCounters[ txQid ].SumMacDelayUs += pTxCompleteAttr->mediumDelay;
   2910 }
   2911 
   2912 /***************************************************************************
   2913 *                       txData_UpdateTxCounters                            *
   2914 ****************************************************************************
   2915 * DESCRIPTION:  free the transmitted msdu
   2916 *
   2917 * INPUTS:       hTxData - the object
   2918 *               pTxCompletAttr - all atributes passed along with the TX
   2919 *                                complete indication
   2920 *
   2921 * OUTPUT:
   2922 *
   2923 * RETURNS:
   2924 ***************************************************************************/
   2925 void txData_UpdateTxCounters( TI_HANDLE hTxData, txCompleteAttr_t *pTxCompleteAttr )
   2926 {
   2927     txData_t *pTxData = (txData_t*)hTxData;
   2928     txPacketIdAttr_t *pPacketId = (txPacketIdAttr_t *)(pTxCompleteAttr->packetId);
   2929     UINT16 EventMask = 0;
   2930     UINT32 dataLen, TxQid = pPacketId->txQid;
   2931     UINT32 retryHistogramIndex;
   2932 
   2933     switch ( pTxCompleteAttr->status )
   2934     {
   2935     case SEND_COMPLETE_SUCCESS:
   2936         /* update the retry histogram */
   2937         retryHistogramIndex = (pTxCompleteAttr->ackFailures >= TX_RETRY_HISTOGRAM_SIZE ?
   2938                                TX_RETRY_HISTOGRAM_SIZE - 1 :
   2939                                pTxCompleteAttr->ackFailures);
   2940         pTxData->txDataCounters[ TxQid ].RetryHistogram[ retryHistogramIndex ]++;
   2941 
   2942         /* update delay histogram */
   2943         txData_SetTxDelayCounters( hTxData, TxQid, pTxCompleteAttr, pPacketId->driverHandlingTime );
   2944 
   2945         if ( (TRUE == pPacketId->bDataMsdu) && (pTxData->txDataQosParams.headerConverMode == QOS_CONVERT) )
   2946         {
   2947             dataLen = pPacketId->msduDataLen - (WLAN_WITH_SNAP_QOS_HEADER_MAX_SIZE - ETHERNET_HDR_LEN);
   2948         }
   2949         else
   2950         {
   2951             dataLen = pPacketId->msduDataLen - (WLAN_WITH_SNAP_HEADER_MAX_SIZE - ETHERNET_HDR_LEN);
   2952         }
   2953 
   2954         if ( IsMacAddressDirected( &(pPacketId->destinationMac) ) )
   2955         {
   2956             /* Directed frame */
   2957             pTxData->txDataCounters[TxQid].DirectedFramesXmit++;
   2958             pTxData->txDataCounters[TxQid].DirectedBytesXmit += dataLen;
   2959             EventMask |= DIRECTED_BYTES_XFER;
   2960             EventMask |= DIRECTED_FRAMES_XFER;
   2961         }
   2962         else if ( IsMacAddressBroadcast( &(pPacketId->destinationMac) ) )
   2963         {
   2964             /* Broadcast frame */
   2965             pTxData->txDataCounters[TxQid].BroadcastFramesXmit++;
   2966             pTxData->txDataCounters[TxQid].BroadcastBytesXmit += dataLen;
   2967             EventMask |= BROADCAST_BYTES_XFER;
   2968             EventMask |= BROADCAST_FRAMES_XFER;
   2969         }
   2970         else
   2971         {
   2972             /* Multicast Address */
   2973             pTxData->txDataCounters[TxQid].MulticastFramesXmit++;
   2974             pTxData->txDataCounters[TxQid].MulticastBytesXmit += dataLen;
   2975             EventMask |= MULTICAST_BYTES_XFER;
   2976             EventMask |= MULTICAST_FRAMES_XFER;
   2977         }
   2978         pTxData->txDataCounters[TxQid].XmitOk++;
   2979         EventMask |= XFER_OK;
   2980 
   2981         /* update the max consecutive retry failures (if needed) */
   2982         if (pTxData->currentConsecutiveRetryFail > pTxData->txDataCounters[ TxQid ].MaxConsecutiveRetryFail)
   2983         {
   2984             pTxData->txDataCounters[TxQid].MaxConsecutiveRetryFail = pTxData->currentConsecutiveRetryFail;
   2985         }
   2986         pTxData->currentConsecutiveRetryFail = 0;
   2987 
   2988         txData_DistributorTxEvent( pTxData, EventMask, dataLen );
   2989         break;
   2990 
   2991     case SEND_COMPLETE_RETRY_EXCEEDED:
   2992 
   2993         pTxData->txDataCounters[ TxQid ].RetryFailCounter++;
   2994         pTxData->currentConsecutiveRetryFail++;
   2995         pTxData->txDataReportedCounters[ TxQid ].OtherFailCounter++;
   2996         break;
   2997 
   2998     case SEND_COMPLETE_LIFETIME_EXCEEDED:
   2999         pTxData->txDataCounters[ TxQid ].TxTimeoutCounter++;
   3000         pTxData->txDataReportedCounters[ TxQid ].OtherFailCounter++;
   3001         break;
   3002 
   3003     case SEND_COMPLETE_NO_LINK:
   3004         pTxData->txDataCounters[ TxQid ].NoLinkCounter++;
   3005         pTxData->txDataReportedCounters[ TxQid ].OtherFailCounter++;
   3006         break;
   3007 
   3008     case SEND_COMPLETE_MAC_CRASHED: /* curently not used */
   3009     default:
   3010         pTxData->txDataCounters[ TxQid ].OtherFailCounter++;
   3011         pTxData->txDataReportedCounters[ TxQid ].OtherFailCounter++;
   3012         break;
   3013     }
   3014 }
   3015 
   3016 static void txData_startVadTimer(TI_HANDLE hTxData, UINT16 voiceDuration)
   3017 {
   3018     txData_t *pTxData = (txData_t*)hTxData;
   3019 
   3020     if (FALSE == pTxData->bVadTimerEnabled)
   3021     {
   3022         WLAN_REPORT_INFORMATION(pTxData->hReport, TX_DATA_MODULE_LOG,
   3023             ("txData_startVadTimer: (voiceDuration is %d) .....................\n", voiceDuration));
   3024 	pTxData->vadTimerDuration = voiceDuration;
   3025 	pTxData->bVadTimerEnabled = TRUE;
   3026 	os_timerStart(pTxData->hOs, pTxData->pVadTimer, voiceDuration, TRUE);
   3027 
   3028     }
   3029     else
   3030     {
   3031         WLAN_REPORT_INFORMATION(pTxData->hReport, TX_DATA_MODULE_LOG,
   3032     	    ("txData_startVadTimer: nothing done. VAD is already started ........\n", voiceDuration));
   3033     }
   3034 }
   3035 
   3036 static void txData_stopVadTimer(TI_HANDLE hTxData)
   3037 {
   3038     txData_t *pTxData = (txData_t*)hTxData;
   3039 
   3040     if (pTxData->bVadTimerEnabled)
   3041     {
   3042     	WLAN_REPORT_INFORMATION(pTxData->hReport, TX_DATA_MODULE_LOG, ("txData_stopVadTimer ...\n"));
   3043 	os_timerStop(pTxData->hOs, pTxData->pVadTimer);
   3044 	pTxData->bVadTimerEnabled = FALSE;
   3045     }
   3046 }
   3047 
   3048 static void txData_setVadTimer(TI_HANDLE hTxData, BOOL vadEnabled, UINT16 duration)
   3049 {
   3050     txData_t *pTxData = (txData_t*)hTxData;
   3051 
   3052     WLAN_REPORT_INFORMATION(pTxData->hReport, TX_DATA_MODULE_LOG, ("txData_setVadTimer (%d, %d)\n", vadEnabled, duration));
   3053     if (vadEnabled)
   3054 	txData_startVadTimer(hTxData, duration);
   3055     else
   3056 	txData_stopVadTimer(hTxData);
   3057 }
   3058 
   3059 static void txData_resetVadTimer(TI_HANDLE hTxData)
   3060 {
   3061     txData_t *pTxData = (txData_t*)hTxData;
   3062 //    UINT32 timeStamp;
   3063 
   3064     if (pTxData->bVadTimerEnabled)
   3065     {
   3066 /*
   3067         timeStamp = os_timeStampMs(pTxData->hOs);
   3068 	printk("resetVadTimer: timestamp = %d\n", timeStamp);
   3069 */
   3070 	os_timerStop(pTxData->hOs, pTxData->pVadTimer);
   3071 	os_timerStart(pTxData->hOs, pTxData->pVadTimer, pTxData->vadTimerDuration, TRUE);
   3072     }
   3073 }
   3074 
   3075 static void txData_vadTimeout(TI_HANDLE hTxData)
   3076 {
   3077     txData_t *pTxData = (txData_t*)hTxData;
   3078 //    UINT32 timeStamp;
   3079 /*
   3080     timeStamp = os_timeStampMs(pTxData->hOs);
   3081     printk("vadTimeout: timestamp = %d\n", timeStamp);
   3082 */
   3083     txData_sendVadFrame (pTxData, QOS_AC_VO);
   3084 }
   3085 
   3086 /***************************************************************************
   3087 *                       txData_startTxSchedulerFromTimer                   *
   3088 ****************************************************************************
   3089 * DESCRIPTION:
   3090 *
   3091 * INPUTS:
   3092 *
   3093 * OUTPUT:
   3094 *
   3095 * RETURNS:
   3096 ***************************************************************************/
   3097 static void txData_startTxSchedulerFromTimer(TI_HANDLE hTxData)
   3098 {
   3099     WLAN_REPORT_DEBUG_TX(((txData_t *)hTxData)->hReport,
   3100         ("in txData_startTxSchedulerFromTimer.....................\n"));
   3101 
   3102     txData_startTxScheduler(hTxData);
   3103 }
   3104 
   3105 /***********************************************************************
   3106  *                        txData_sendNullFrame
   3107  ***********************************************************************
   3108 DESCRIPTION:    Send Null frame Function.
   3109                 The function does the following:
   3110                 -   Builds Null Data Frame with PS bit set to On or Off.
   3111                 -   Allocates MSDU frame.
   3112                 -   Sends the frame.
   3113 
   3114 INPUT:      hTxData         -   Tx Data Pointer.
   3115             powerSaveMode   -   Indicates if to switch the Power Save
   3116                                 mode to On or Off.
   3117             module          -   The calling module.
   3118 
   3119 OUTPUT:     None
   3120 
   3121 RETURN:     OK on success, NOK otherwise
   3122 ************************************************************************/
   3123 TI_STATUS txData_sendNullFrame(TI_HANDLE hTxData,
   3124                                BOOL powerSaveOn,
   3125                                allocatingModule_e module)
   3126 {
   3127     TI_STATUS       status;
   3128     mem_MSDU_T      *pMsdu;
   3129     paramInfo_t     daParam, saParam;
   3130     dot11_header_t  *pFrame; /* Note : there is no body for null frame */
   3131     txData_t        *pTxData = (txData_t *)hTxData;
   3132 
   3133     /* Getting new msdu */
   3134     status = wlan_memMngrAllocMSDU(pTxData->hMemMngr, &pMsdu, WLAN_HDR_LEN + TX_TOTAL_OFFSET_BEFORE_DATA, module);
   3135     if (status != OK)
   3136         return NOK;
   3137 
   3138     pFrame = (dot11_header_t*)(pMsdu->firstBDPtr->data + TX_TOTAL_OFFSET_BEFORE_DATA);
   3139 
   3140     /* Setting the Frame Control with Data frame type and Null frame sub type*/
   3141     pFrame->fc = 0;
   3142     pFrame->fc |= DOT11_FC_DATA_NULL_FUNCTION;
   3143     pFrame->fc |= DOT11_FC_TO_DS;
   3144 
   3145     /* setting the Power Save bit in the Frame control field*/
   3146     if(powerSaveOn == TRUE)
   3147         pFrame->fc |= (0x1 << DOT11_FC_PWR_MGMT_SHIFT);
   3148 
   3149     daParam.paramType = CTRL_DATA_CURRENT_BSSID_PARAM;
   3150     status = ctrlData_getParam(pTxData->hCtrlData, &daParam);
   3151     if (status != OK)
   3152     {
   3153         wlan_memMngrFreeMSDU(pTxData->hMemMngr, pMsdu->handle);
   3154         return NOK;
   3155     }
   3156 
   3157     /* copy destination mac address */
   3158     MAC_COPY(pTxData->hOs, (&pFrame->address3), (&daParam.content.ctrlDataCurrentBSSID));
   3159 
   3160     saParam.paramType = CTRL_DATA_MAC_ADDRESS;
   3161     status = ctrlData_getParam(pTxData->hCtrlData, &saParam);
   3162     if (status != OK)
   3163     {
   3164         wlan_memMngrFreeMSDU(pTxData->hMemMngr, pMsdu->handle);
   3165         return NOK;
   3166     }
   3167 
   3168     /* copy source mac address */
   3169     MAC_COPY(pTxData->hOs, (&pFrame->address2), (&saParam.content.ctrlDataCurrentBSSID));
   3170 
   3171     /* copy BSSID (destination mac address) */
   3172     MAC_COPY(pTxData->hOs, (&pFrame->address1), (&daParam.content.ctrlDataCurrentBSSID));
   3173 
   3174     /* Update MSDU parameters */
   3175     pMsdu->headerLen = pMsdu->dataLen =  WLAN_HDR_LEN;
   3176     pMsdu->firstBDPtr->length = pMsdu->dataLen + TX_TOTAL_OFFSET_BEFORE_DATA;
   3177 
   3178     /* send the packet to the TX */
   3179     pMsdu->qosTag = 0;
   3180     pMsdu->txFlags |= TX_DATA_NULL_MSDU;
   3181 
   3182     status = txData_txSendMsdu(hTxData, pMsdu);
   3183 
   3184     return status;
   3185 }
   3186 
   3187 /***********************************************************************
   3188  *                        txData_sendVadFrame
   3189  ***********************************************************************
   3190 DESCRIPTION:    Send a polling frame to retrieve downlink traffic from
   3191                 the AP. Activated by the voice application when there is
   3192                   no uplink traffic during a voice call.
   3193                 The polling is either PS-Poll (for legacy PS) or QoS-Null
   3194                 (for UPSD).
   3195                 Null frame is currently added after PS-Poll to trigger
   3196                 the triggered-scan which is only triggered by data frames!
   3197                 Note that currently the acID parameter is ignored to insure this
   3198                 function is not activated for other ACs than Voice (to add this
   3199                 flexibility the txData_txSendMsdu() function should be updated.
   3200 
   3201 INPUT:      acID - Currently not used!  Supporting only AC_VO!
   3202 
   3203 OUTPUT:     None
   3204 
   3205 RETURN:     OK on success, NOK otherwise
   3206 ************************************************************************/
   3207 
   3208 TI_STATUS txData_sendVadFrame(TI_HANDLE hTxData, UINT8 acID)
   3209 {
   3210     mem_MSDU_T *pMsdu;
   3211     TI_STATUS  status;
   3212     txData_t   *pTxData = (txData_t *)hTxData;
   3213     paramInfo_t param;
   3214 
   3215     if (pTxData->txDataPortStatus != OPEN)
   3216     {
   3217         WLAN_REPORT_INFORMATION(pTxData->hReport, TX_DATA_MODULE_LOG,
   3218                                 ("txData_sendVadFrame(): While port status is %d\n", pTxData->txDataPortStatus ));
   3219         return NOK;
   3220      }
   3221 
   3222     param.paramType = QOS_MNGR_ACTIVE_PROTOCOL;
   3223     status = qosMngr_getParams(pTxData->hQosMngr, &param);
   3224 
   3225     /* For WME - send QoS-Null-Data. */
   3226     if (param.content.qosSiteProtocol ==  WME)
   3227     {
   3228         /* Send QoS-Null frame to retrieve downlink packets and to trigger the triggered-scan. */
   3229         /* Note: If VO mode is PSPOLL, the txData_txSendMsdu() will add the PS-Poll frame.  */
   3230         if((status = txData_buildQosNullDataFrame(pTxData,&pMsdu,wmeAcToUpIndex[QOS_AC_VO])) == OK)
   3231             status = txData_txSendMsdu(hTxData, pMsdu);
   3232 
   3233         WLAN_REPORT_INFORMATION(pTxData->hReport, TX_DATA_MODULE_LOG,
   3234             ("txData_sendVadFrame(): WME site...Sending QoS-Null frame, Status=%d\n", status));
   3235     }
   3236 
   3237     /* For non-WME - send PS-Poll plus Null-Data. */
   3238     else
   3239     {
   3240         /* Send PS-Poll to retrieve downlink packets. */
   3241         if((status = txData_getPsPollFrame(pTxData,&pMsdu)) == OK)
   3242             status = txData_txSendMsdu(hTxData, pMsdu);
   3243 
   3244         /* Send also a null frame to trigger the triggered-scan in the FW. */
   3245         /* Note: Needed because the scan is triggered only by data frames, so PS-Poll is not enough!. */
   3246         /* Note: The txData_txSendMsdu() won't send another PS-Poll before the null frame since
   3247                  pMsdu->qosTag is set to 0 for null (and not voice). */
   3248         status = txData_sendNullFrame(hTxData, FALSE, TX_MODULE);
   3249 
   3250         WLAN_REPORT_INFORMATION(pTxData->hReport, TX_DATA_MODULE_LOG,
   3251             ("txData_sendVadFrame(): Non-WME site...Sending PS-Poll and Null frame, Status=%d\n", status));
   3252     }
   3253 
   3254     return status;
   3255 }
   3256 
   3257 
   3258 /***********************************************************************
   3259  *                        txData_getPsPollFrame
   3260  ***********************************************************************
   3261 DESCRIPTION:    builds PS POLL frame Function.
   3262                 The function does the following:
   3263                 -   Builds PS POLL Control Frame with PS bit set to On .
   3264                 -   Allocates MSDU frame.
   3265                 -   Sends the frame.
   3266 
   3267 ----------------------------
   3268 PS Poll - 802.11 Mac Header
   3269 ----------------------------
   3270   Version              0
   3271   Type                 %01          (Control)
   3272   Subtype              %1010        (PS Poll)
   3273   Frame Control Flag   %00010000    (Power Management Bit set -> Power Save mode)
   3274   Assoc ID             association ID
   3275   BSSID                MAC addr of BSSID
   3276   Transmitter          MAC addr of sender
   3277 ----------------------------
   3278 
   3279 typedef struct
   3280 {
   3281   UINT16        fc;
   3282   UINT16        AID;
   3283   macAddress_t  BSSID;
   3284   macAddress_t  TA;
   3285 } dot11_PsPollFrameHeader_t;
   3286 
   3287 
   3288 INPUT:
   3289 
   3290 OUTPUT:     None
   3291 
   3292 RETURN:     OK on success, NOK otherwise
   3293 ************************************************************************/
   3294 TI_STATUS txData_getPsPollFrame(TI_HANDLE hTxData,mem_MSDU_T **pMsduPsPoll)
   3295 {
   3296     TI_STATUS       status = OK;
   3297     UINT32          timeStamp ;
   3298     paramInfo_t     daParam, saParam;
   3299     whalParamInfo_t whalParam;
   3300     dot11_PsPollFrameHeader_t   *pFrame; /* Note : there is no body for null frame */
   3301     txData_t *pTxData = (txData_t *)hTxData;
   3302     mem_MSDU_T      *pMsdu;
   3303     /* Getting new msdu */
   3304     status = wlan_memMngrAllocMSDU(pTxData->hMemMngr, &pMsdu, WLAN_HDR_LEN + TX_TOTAL_OFFSET_BEFORE_DATA, TX_MODULE);
   3305     if (status != OK)
   3306     {
   3307         return NOK;
   3308     }
   3309 
   3310 
   3311     pFrame = (dot11_PsPollFrameHeader_t*)(pMsdu->firstBDPtr->data + TX_TOTAL_OFFSET_BEFORE_DATA);
   3312 
   3313     /*
   3314     **   Building the Frame Control word (16 bits)
   3315     ** ---------------------------------------------
   3316     */
   3317     pFrame->fc = 0;
   3318 
   3319     /*
   3320     ** Type = Control
   3321     ** SubType = Power Save (PS) POLL,  */
   3322     pFrame->fc |= DOT11_FC_PS_POLL;
   3323 
   3324     /*
   3325     ** setting the Power Management bit in the Frame control field
   3326     ** to be "Power Save mode"
   3327     */
   3328     pFrame->fc |= (0x1 << DOT11_FC_PWR_MGMT_SHIFT);
   3329 
   3330     /*
   3331     **   Association ID
   3332     ** -----------------
   3333     */
   3334     whalParam.paramType = HAL_CTRL_AID_PARAM;
   3335     status = whalCtrl_GetParam (pTxData->hWhalCtrl, &whalParam) ;
   3336     if (status != OK)
   3337     {
   3338         wlan_memMngrFreeMSDU(pTxData->hMemMngr, pMsdu->handle);
   3339         return NOK;
   3340     }
   3341     /* AID should have its two MSB bit Set to "1"*/
   3342     pFrame->AID = whalParam.content.halCtrlAid | 0xC000;
   3343     WLAN_REPORT_WARNING(pTxData->hReport, TX_DATA_MODULE_LOG,
   3344             (" AID 4 = %d  \n", (whalParam.content.halCtrlAid | 0xC000)));
   3345 
   3346     /*
   3347     **   BSSID
   3348     ** ---------
   3349     */
   3350     daParam.paramType = CTRL_DATA_CURRENT_BSSID_PARAM;
   3351     status = ctrlData_getParam(pTxData->hCtrlData, &daParam);
   3352     if (status != OK)
   3353     {
   3354         wlan_memMngrFreeMSDU(pTxData->hMemMngr, pMsdu->handle);
   3355         return NOK;
   3356     }
   3357     /* copy destination mac address */
   3358     MAC_COPY(pTxData->hOs, (&pFrame->BSSID), (&daParam.content.ctrlDataCurrentBSSID));
   3359 
   3360 
   3361 
   3362 
   3363     /*
   3364     **  TA - Transmiter (MAC) Address
   3365     ** -------------------------------
   3366     */
   3367     saParam.paramType = CTRL_DATA_MAC_ADDRESS;
   3368     status = ctrlData_getParam(pTxData->hCtrlData, &saParam);
   3369     if (status != OK)
   3370     {
   3371         wlan_memMngrFreeMSDU(pTxData->hMemMngr, pMsdu->handle);
   3372         return NOK;
   3373     }
   3374    /* copy source mac address */
   3375     MAC_COPY(pTxData->hOs, (&pFrame->TA), (&saParam.content.ctrlDataCurrentBSSID));
   3376 
   3377     timeStamp = os_timeStampMs(pTxData->hOs);
   3378 
   3379     WLAN_REPORT_INFORMATION(pTxData->hReport, TX_DATA_MODULE_LOG,
   3380             (" txData_sendPsPollFrame() : time = %d insert PS_POLL frame to Driver queue \n", timeStamp));
   3381 
   3382     /* Update MSDU parameters */
   3383     pMsdu->headerLen = pMsdu->dataLen =  sizeof(dot11_PsPollFrameHeader_t);
   3384     pMsdu->firstBDPtr->length = pMsdu->dataLen + TX_TOTAL_OFFSET_BEFORE_DATA;
   3385 
   3386     pMsdu->txFlags |= TX_DATA_PS_POLL;
   3387 
   3388 
   3389     if (status == OK)
   3390         WLAN_REPORT_INFORMATION(pTxData->hReport, TX_DATA_MODULE_LOG,
   3391         ("in txData_sendPsPollFrame: enter PS_POLL to queue\n"));
   3392     else
   3393         WLAN_REPORT_INFORMATION(pTxData->hReport, TX_DATA_MODULE_LOG,
   3394         ("in txData_sendPsPollFrame: didn't enter PS_POLL to queue\n"));
   3395 
   3396     *pMsduPsPoll = pMsdu;
   3397 
   3398     return status;
   3399 }
   3400 
   3401 
   3402 /***********************************************************************
   3403  *                        txData_updateUsedTime
   3404  ***********************************************************************
   3405 DESCRIPTION:    This function is called for every txComplete in order
   3406                 to update the transmisssion time.
   3407 
   3408 INPUT:          hTxData - handale to the ts data object
   3409                 qNum    - the queue that the frame transmitted from
   3410                 usedTime - the time of the transmission (in microseconds)
   3411 
   3412 OUTPUT:     None
   3413 
   3414 RETURN:     OK on success
   3415 ************************************************************************/
   3416 TI_STATUS txData_updateUsedTime(TI_HANDLE hTxData, UINT32 qNum, UINT16 usedTime)
   3417 {
   3418     txData_t *pTxData = (txData_t *)hTxData;
   3419 
   3420     /* addd the used time for the specific queue */
   3421     pTxData->dataMsduListArr[qNum]->totalUsedTime += usedTime;
   3422 
   3423     return OK;
   3424 }
   3425 
   3426 
   3427 /***********************************************************************
   3428  *                        txData_calcCreditFromTimer
   3429  ***********************************************************************
   3430 DESCRIPTION:    This function is called when credit calculation timer
   3431                 is expired. it calculate the credit for the admission ctrl
   3432                 credit algorithm
   3433 
   3434 
   3435 INPUT:          hTxData - handle to the ts data object
   3436 
   3437 OUTPUT:     None
   3438 
   3439 RETURN:     void
   3440 ************************************************************************/
   3441 static void txData_calcCreditFromTimer(TI_HANDLE hTxData)
   3442 {
   3443     UINT32 qNum;
   3444     OS_802_11_THRESHOLD_CROSS_INDICATION_PARAMS mediumTimeCross;
   3445     txData_t *pTxData = (txData_t *)hTxData;
   3446     INT32       prevCredit;
   3447     INT32       highCreditThreshold;
   3448     INT32       lowCreditThreshold;
   3449     MsduList_t  *pMsduList;
   3450     INT32       usageRatio;
   3451     INT32       currUsage;
   3452     INT32       prevUsage;
   3453 
   3454     /* get current time stamp */
   3455     UINT32 currentTimeStamp = os_timeStampMs(pTxData->hOs);
   3456 
   3457 
   3458     for(qNum = 0 ; qNum< MAX_NUM_OF_TX_QUEUES ; qNum++)
   3459     {
   3460         pMsduList = pTxData->dataMsduListArr[qNum];
   3461 
   3462         /* check if this queue is under admission ctrl opration */
   3463         if(pMsduList->mediumTime == 0)
   3464         {
   3465             WLAN_REPORT_INFORMATION(pTxData->hReport, TX_DATA_MODULE_LOG,
   3466                 (" txData_calcCreditFromTimer() :qNum = %d mediumTime = 0 \n",qNum));
   3467 
   3468             continue;
   3469         }
   3470 
   3471         /* in case of wraparound */
   3472         if(currentTimeStamp < pMsduList->lastTimeStamp)
   3473             pMsduList->lastTimeStamp = 0;
   3474 
   3475         /* store prev credit */
   3476         prevCredit = pMsduList->credit;
   3477 
   3478         /* Calculate the medium usage ratio:    totalUsedTime / mediumTime * 1000
   3479            Note that since the totalUsedTime is in usec and not msec we don't multiply by 1000.  */
   3480         usageRatio = pMsduList->totalUsedTime / pMsduList->mediumTime;
   3481 
   3482         /* calculate credit */
   3483         pMsduList->credit = pMsduList->credit + (currentTimeStamp - pMsduList->lastTimeStamp) - usageRatio;
   3484 
   3485         /* update last time stamp */
   3486         pMsduList->lastTimeStamp = currentTimeStamp;
   3487 
   3488         /* check if credit exceeds above mediumTime or below -mediumTime */
   3489         if (pMsduList->credit > (INT32)(pMsduList->mediumTime) )
   3490         {
   3491             /* in case of credit is big than mediumTime -> set credit to medium time */
   3492             pMsduList->credit = pMsduList->mediumTime;
   3493             pMsduList->enableTransmissionTime = 0;
   3494         }
   3495 
   3496         /* If credit is lower than -mediumTime we exceed the admitted time. */
   3497         else if (pMsduList->credit <= (INT32)(0 - pMsduList->mediumTime))
   3498         {
   3499             /* Only delay transmission on this AC if the "delay" registry key is TRUE */
   3500             if(pTxData->admCtrlDelayDueToMediumTimeOverUsage == TRUE)
   3501                 pMsduList->enableTransmissionTime = (0 - pMsduList->credit) - pMsduList->mediumTime;
   3502         }
   3503 
   3504        WLAN_REPORT_INFORMATION(pTxData->hReport, TX_DATA_MODULE_LOG,
   3505           ("credit = %d  | TotalUsedTime = %d  | enableTransmissionTime = %d\n",
   3506           pMsduList->credit, pMsduList->totalUsedTime/1000, pMsduList->enableTransmissionTime));
   3507 
   3508         /* Check medium-usage threshold cross events */
   3509         /*********************************************/
   3510         /*
   3511          * The medium-usage events are defined as follows:
   3512          * The high threshold triggers event only when crossed upward (traffic increased above threshold).
   3513          * The low threshold triggers event only when crossed downward (traffic decreased below threshold).
   3514          * Thus, the two thresholds provide hysteresis and prevent multiple triggering.
   3515          * The high threshold should be greater than the low threshold.
   3516          */
   3517 
   3518         highCreditThreshold = (INT32)((pMsduList->mediumTime)*(pMsduList->highMediumUsageThreshold)/100);
   3519         lowCreditThreshold  = (INT32)((pMsduList->mediumTime)*(pMsduList->lowMediumUsageThreshold)/100);
   3520 
   3521         /* The credit is getting more negative as we get closer to the medium usage limit, so we invert
   3522              it before comparing to the thresholds (lower credit means higher usage). */
   3523         currUsage = -pMsduList->credit;
   3524         prevUsage = -prevCredit;
   3525 
   3526         /* crossing below the low threshold */
   3527         if ( (currUsage < lowCreditThreshold) && (prevUsage >= lowCreditThreshold) )
   3528         {
   3529             /* send event */
   3530             mediumTimeCross.uAC = txData_GetAcIdFromQid( hTxData, qNum );
   3531             mediumTimeCross.uHighOrLowThresholdFlag = (UINT32)LOW_THRESHOLD_CROSS;
   3532             mediumTimeCross.uAboveOrBelowFlag = (UINT32)CROSS_BELOW;
   3533 
   3534             EvHandlerSendEvent(pTxData->hEvHandler, IPC_EVENT_MEDIUM_TIME_CROSS, (UINT8 *)&mediumTimeCross,sizeof(OS_802_11_THRESHOLD_CROSS_INDICATION_PARAMS));
   3535             WLAN_REPORT_INFORMATION(pTxData->hReport, TX_DATA_MODULE_LOG,
   3536                 ("crossed below low threshold !!! prevUsage = %d, currUsage = %d, lowCreditThreshold = %d\n",
   3537                 prevUsage, currUsage, lowCreditThreshold));
   3538         }
   3539 
   3540         /* crossing above the high threshold */
   3541         else if ( (currUsage > highCreditThreshold) && (prevUsage <= highCreditThreshold) )
   3542         {
   3543             /* send event */
   3544             mediumTimeCross.uAC = txData_GetAcIdFromQid( hTxData, qNum );
   3545             mediumTimeCross.uHighOrLowThresholdFlag = (UINT32)HIGH_THRESHOLD_CROSS;
   3546             mediumTimeCross.uAboveOrBelowFlag = (UINT32)CROSS_ABOVE;
   3547 
   3548             EvHandlerSendEvent(pTxData->hEvHandler, IPC_EVENT_MEDIUM_TIME_CROSS, (UINT8 *)&mediumTimeCross,sizeof(OS_802_11_THRESHOLD_CROSS_INDICATION_PARAMS));
   3549             WLAN_REPORT_INFORMATION(pTxData->hReport, TX_DATA_MODULE_LOG,
   3550                 ("crossed above high threshold !!! prevUsage = %d, currUsage = %d, highCreditThreshold = %d\n",
   3551                 prevUsage, currUsage, highCreditThreshold));
   3552         }
   3553 
   3554         /* reset totalUsedTime */
   3555         pMsduList->totalUsedTime = 0;
   3556 
   3557     }
   3558 
   3559 }
   3560 
   3561 
   3562 /***********************************************************************
   3563  *                        txData_setAdmisionCtrlParams
   3564  ***********************************************************************
   3565 DESCRIPTION:    This function is called for add/delete a tspec in order
   3566                 to update parameters.
   3567 
   3568 INPUT:          hTxData - handale to the ts data object
   3569                 acID - the AC of the tspec
   3570                 mediumTime  - tha alocated medium time for this UP
   3571                 minimumPHYRate - the min phy rate to send a packet of this UP
   3572                 admFlag - indicate if the its addition or deletion of tspec
   3573 
   3574 OUTPUT:     None
   3575 
   3576 RETURN:     void
   3577 ************************************************************************/
   3578 TI_STATUS txData_setAdmisionCtrlParams(TI_HANDLE hTxData,
   3579                                        UINT8 acID,
   3580                                        UINT16 mediumTime,
   3581                                        UINT32 minimumPHYRate,
   3582                                        BOOL admFlag)
   3583 {
   3584     UINT8   queueIndex;
   3585     UINT8   i;
   3586     txData_t *pTxData = (txData_t *)hTxData;
   3587     MsduList_t  *pMsduList;
   3588 
   3589     /* find queue from AC */
   3590     queueIndex = pTxData->txDataAcTrfcCtrl[acID].QueueIndex;
   3591 
   3592     pMsduList = pTxData->dataMsduListArr[queueIndex];
   3593 
   3594     if(admFlag == TRUE)
   3595     {
   3596         /* tspaec added */
   3597         pMsduList->mediumTime = mediumTime;
   3598 
   3599         /* in case of medium time>0 set relevant parameters to the credit algo calculation */
   3600         pMsduList->admissionState = AC_ADMITTED;
   3601 
   3602         /* enable admission algo for this queue */
   3603         pMsduList->useAdmissionAlgo = TRUE;
   3604 
   3605         pMsduList->lastTimeStamp = os_timeStampMs(pTxData->hOs);
   3606         pMsduList->enableTransmissionTime = 0;
   3607         pMsduList->credit = mediumTime;
   3608     }
   3609     else
   3610     {
   3611         /* tspaec deleted */
   3612         pMsduList->mediumTime = 0;
   3613 
   3614         /* in case of medium time=0 reset relevant parameters */
   3615         pMsduList->admissionState = AC_NOT_ADMITTED;
   3616 
   3617         pMsduList->useAdmissionAlgo = FALSE;
   3618         pMsduList->lastTimeStamp = 0;
   3619         pMsduList->enableTransmissionTime = 0;
   3620         pMsduList->credit = 0;
   3621 
   3622     }
   3623 
   3624     /* If the timer was not enabled in registry than we will never set it */
   3625     if ( pTxData->bCreditCalcTimerEnabled )
   3626     {
   3627         /* enable disable credit calculation timer */
   3628         for(i = 0 ; i < MAX_NUM_OF_TX_QUEUES ; i++)
   3629         {
   3630             if(pTxData->dataMsduListArr[i]->useAdmissionAlgo == TRUE)
   3631             {
   3632                 if(pTxData->bCreditCalcTimerRunning == FALSE)
   3633                 {
   3634                     pTxData->bCreditCalcTimerRunning = TRUE;
   3635                     os_timerStart(pTxData->hOs, pTxData->pCreditTimer, pTxData->creditCalculationTimeout, TRUE);
   3636                 }
   3637 
   3638                 return OK;
   3639             }
   3640         }
   3641         /* in all queues useAdmissionAlgo is not TRUE */
   3642         if ( pTxData->bCreditCalcTimerRunning )
   3643         {
   3644             os_timerStop(pTxData->hOs, pTxData->pCreditTimer);
   3645             pTxData->bCreditCalcTimerRunning = FALSE;
   3646         }
   3647     }
   3648 
   3649     return OK;
   3650 
   3651 }
   3652 
   3653 
   3654 /***********************************************************************
   3655  *                        txData_setPsVoiceDeliveryMode
   3656  ***********************************************************************
   3657 DESCRIPTION:    This function is called for add/delete a tspec in order
   3658                 to set the PS mode for a specific UP
   3659 
   3660 INPUT:          hTxData - handale to the ts data object
   3661                 userPriority - the user priority of the tspec
   3662                 PsMode  - tha PS mode for the specific UP
   3663 
   3664 OUTPUT:     None
   3665 
   3666 RETURN:     OK on success, NOK otherwise
   3667 ************************************************************************/
   3668 TI_STATUS txData_setPsVoiceDeliveryMode(TI_HANDLE hTxData, PSScheme_e   PsMode)
   3669 {
   3670     txData_t *pTxData = (txData_t *)hTxData;
   3671     pTxData->txDataAcTrfcCtrl[QOS_AC_VO].PsMode = PsMode;
   3672     return OK;
   3673 }
   3674 
   3675 /***********************************************************************
   3676  *                        txData_setMediumUsageThresholds
   3677  ***********************************************************************
   3678 DESCRIPTION:    This function is called in order to set the threshold
   3679                 for the medium time usage
   3680 
   3681 INPUT:          hTxData - handale to the ts data object
   3682                 acID - the AC
   3683                 highMediumUsageThreshold - high threshold
   3684                 lowMediumUsageThreshold - lowhreshold
   3685 
   3686 OUTPUT:     None
   3687 
   3688 RETURN:     OK on success, NOK otherwise
   3689 ************************************************************************/
   3690 TI_STATUS txData_setMediumUsageThresholds(TI_HANDLE     hTxData,
   3691                                       UINT8             acID,
   3692                                       INT32             highMediumUsageThreshold,
   3693                                       INT32             lowMediumUsageThreshold)
   3694 {
   3695     txData_t *pTxData = (txData_t *)hTxData;
   3696 
   3697     UINT8 queueIndex;
   3698 
   3699     /* validate AC */
   3700     if(acID >= MAX_NUM_OF_AC)
   3701         return NOK;
   3702 
   3703     /* find queu from ac */
   3704     queueIndex = pTxData->txDataAcTrfcCtrl[acID].QueueIndex;
   3705 
   3706     /* set threshold */
   3707     pTxData->dataMsduListArr[queueIndex]->lowMediumUsageThreshold = lowMediumUsageThreshold;
   3708     pTxData->dataMsduListArr[queueIndex]->highMediumUsageThreshold = highMediumUsageThreshold;
   3709 
   3710     return OK;
   3711 
   3712 }
   3713 
   3714 /***********************************************************************
   3715  *                        txData_isQueueUseMediumTime
   3716  ***********************************************************************
   3717 DESCRIPTION:
   3718 
   3719 INPUT:          hTxData - handale to the ts data object
   3720 
   3721 OUTPUT:     None
   3722 
   3723 RETURN:     OK on success, NOK otherwise
   3724 ************************************************************************/
   3725 
   3726 BOOL txData_isQueueUseMediumTime(TI_HANDLE hTxData, UINT8 qNum)
   3727 {
   3728     txData_t *pTxData = (txData_t *)hTxData;
   3729 
   3730     if(pTxData->dataMsduListArr[qNum]->mediumTime == 0)
   3731         return FALSE;
   3732     else
   3733         return TRUE;
   3734 
   3735 }
   3736 
   3737 
   3738 
   3739 void Test_HeaderConvertion(TI_HANDLE hTxData, mem_MSDU_T *pMsdu)
   3740 {
   3741     txData_t *pTxData = (txData_t *)hTxData;
   3742 
   3743     print_MsduDataHeader(pTxData->hMemMngr, pMsdu);
   3744 
   3745     txData_convertEthToWlanHeader( pTxData, pMsdu );
   3746 
   3747     print_MsduDataHeader(pTxData->hMemMngr, pMsdu);
   3748 
   3749 }
   3750 
   3751 
   3752 #ifdef TI_DBG
   3753 void txData_printTxBlock(TI_HANDLE hTxData)
   3754 {
   3755     txData_t *pTxData = (txData_t *)hTxData;
   3756     int i;
   3757 
   3758     WLAN_OS_REPORT(("hCtrlData = 0x%X\n", pTxData->hCtrlData));
   3759     WLAN_OS_REPORT(("hTnetwDrv = 0x%X\n", pTxData->hTnetwDrv));
   3760     WLAN_OS_REPORT(("hOs = 0x%X\n", pTxData->hOs));
   3761     WLAN_OS_REPORT(("hReport = 0x%X\n", pTxData->hReport));
   3762     WLAN_OS_REPORT(("hMemMngr = 0x%X\n", pTxData->hMemMngr));
   3763     WLAN_OS_REPORT(("pSchedulerTimer = 0x%X\n", pTxData->pSchedulerTimer));
   3764 
   3765     WLAN_OS_REPORT(("hCriticalSectionProtect = 0x%X\n", pTxData->hCriticalSectionProtect));
   3766 
   3767     WLAN_OS_REPORT(("txDataPortStatus = %d\n", pTxData->txDataPortStatus));
   3768     WLAN_OS_REPORT(("txDataCurrentPrivacyInvokedMode = %d\n", pTxData->txDataCurrentPrivacyInvokedMode));
   3769     WLAN_OS_REPORT(("txDataEapolEncryptionStatus = %d\n", pTxData->txDataEapolEncryptionStatus));
   3770 
   3771     WLAN_OS_REPORT(("txDataIsSchedulerInWork = %d\n", pTxData->txDataIsSchedulerInWork));
   3772 
   3773     WLAN_OS_REPORT(("txDataNumOfQueues = %d\n", pTxData->txDataNumOfQueues));
   3774     WLAN_OS_REPORT(("mngMsduList = 0x%X\n", pTxData->mngMsduList));
   3775     for(i=0 ; i < MAX_NUM_OF_TX_QUEUES; i++ )
   3776     {
   3777         WLAN_OS_REPORT(("dataMsduList %d = 0x%X\n",i, pTxData->dataMsduListArr[i]));
   3778     }
   3779 
   3780 }
   3781 
   3782 
   3783 /*
   3784 void printFullMsduList(MsduList_t *this);
   3785 void printMsduList(MsduList_t *this);
   3786 */
   3787 void txData_printDataMsduList(TI_HANDLE hTxData)
   3788 {
   3789     txData_t *pTxData = (txData_t *)hTxData;
   3790     int i;
   3791 
   3792     for(i=0 ; i < MAX_NUM_OF_TX_QUEUES; i++ )
   3793     {
   3794         WLAN_OS_REPORT(("List : %d \n", i));
   3795         printMsduList(pTxData->dataMsduListArr[i]);
   3796     }
   3797 
   3798 
   3799 }
   3800 
   3801 void txData_fullPrintDataMsduList(TI_HANDLE hTxData)
   3802 {
   3803     txData_t *pTxData = (txData_t *)hTxData;
   3804     int i;
   3805 
   3806     for(i=0 ; i < MAX_NUM_OF_TX_QUEUES; i++ )
   3807     {
   3808         WLAN_OS_REPORT(("List : %d \n", i));
   3809         printFullMsduList(pTxData->dataMsduListArr[i]);
   3810     }
   3811 }
   3812 
   3813 void txData_printMgmtMsduList(TI_HANDLE hTxData)
   3814 {
   3815     txData_t *pTxData = (txData_t *)hTxData;
   3816 
   3817     printMsduList(pTxData->mngMsduList);
   3818 
   3819 
   3820 }
   3821 
   3822 void txData_fullPrintMgmtMsduList(TI_HANDLE hTxData)
   3823 {
   3824     txData_t *pTxData = (txData_t *)hTxData;
   3825 
   3826     printFullMsduList(pTxData->mngMsduList);
   3827 }
   3828 
   3829 
   3830 void txData_printTxCounters(TI_HANDLE hTxData)
   3831 {
   3832     txData_t *pTxData = (txData_t *)hTxData;
   3833     int TxQid;
   3834 
   3835     for (TxQid = 0; TxQid < MAX_NUM_OF_TX_QUEUES; TxQid++)
   3836     {
   3837         WLAN_OS_REPORT(("Tx Queue %d:\n", TxQid));
   3838         WLAN_OS_REPORT(("===========\n"));
   3839         WLAN_OS_REPORT(("XmitOk = %d\n", pTxData->txDataCounters[TxQid].XmitOk));
   3840         WLAN_OS_REPORT(("DirectedBytesXmit = %d\n", pTxData->txDataCounters[TxQid].DirectedBytesXmit));
   3841         WLAN_OS_REPORT(("DirectedFramesXmit = %d\n", pTxData->txDataCounters[TxQid].DirectedFramesXmit));
   3842         WLAN_OS_REPORT(("MulticastBytesXmit = %d\n", pTxData->txDataCounters[TxQid].MulticastBytesXmit));
   3843         WLAN_OS_REPORT(("MulticastFramesXmit = %d\n", pTxData->txDataCounters[TxQid].MulticastFramesXmit));
   3844         WLAN_OS_REPORT(("BroadcastBytesXmit = %d\n", pTxData->txDataCounters[TxQid].BroadcastBytesXmit));
   3845         WLAN_OS_REPORT(("BroadcastFramesXmit = %d\n", pTxData->txDataCounters[TxQid].BroadcastFramesXmit));
   3846     }
   3847 
   3848     /* dbg functions */
   3849     WLAN_OS_REPORT(("\nTx Debug info:\n", TxQid));
   3850     WLAN_OS_REPORT(("==============\n"));
   3851     WLAN_OS_REPORT(("DropedPacketsCounter = %d\n", pTxData->txDataDbgCounters.dbgDropedPacketsCounter));
   3852     WLAN_OS_REPORT(("NumOfNullMsdu (in sendPacketTransfer) = %d\n", pTxData->txDataDbgCounters.dbgNumOfNullMsdu));
   3853 }
   3854 
   3855 
   3856 void txData_printTxQosCounters(TI_HANDLE hTxData)
   3857 {
   3858     txData_t *pTxData = (txData_t *)hTxData;
   3859     int qIndex;
   3860 
   3861     WLAN_OS_REPORT(("-------------- Tx Queues Statistics ---------------\n\n"));
   3862     WLAN_OS_REPORT(("Successed copied = Scheduled - Droped\n"));
   3863     WLAN_OS_REPORT(("Successed copied = Scheduled out - check size failed\n"));
   3864 
   3865     WLAN_OS_REPORT(("-------------- Scheduled To Core queues ---------------\n"));
   3866     for(qIndex = 0; qIndex < MAX_NUM_OF_TX_QUEUES; qIndex++)
   3867     {
   3868         WLAN_OS_REPORT(("Queue %d = %d\n",qIndex, pTxData->txDataDbgCounters.dbgInsertToMsduListPackets[qIndex]));
   3869     }
   3870 
   3871     WLAN_OS_REPORT(("-------------- Droped From Core queues ---------------\n"));
   3872     for(qIndex = 0; qIndex < MAX_NUM_OF_TX_QUEUES; qIndex++)
   3873     {
   3874         WLAN_OS_REPORT(("Queue %d = %d\n",qIndex, pTxData->txDataDbgCounters.dbgDropedFromMsduListPackets[qIndex]));
   3875     }
   3876 
   3877     WLAN_OS_REPORT(("-------------- Scheduled out from Core queues ---------------\n"));
   3878     for(qIndex = 0; qIndex < MAX_NUM_OF_TX_QUEUES; qIndex++)
   3879     {
   3880         WLAN_OS_REPORT(("Queue %d = %d\n",qIndex, pTxData->txDataDbgCounters.dbgScheduledOutPackets[qIndex]));
   3881     }
   3882 
   3883     WLAN_OS_REPORT(("--Dropped due Expiry Time in Core Queues (dropped after %d %% of total time)--\n",pTxData->uFracOfLifeTimeToDrop));
   3884     for(qIndex = 0; qIndex < MAX_NUM_OF_TX_QUEUES; qIndex++)
   3885     {
   3886         WLAN_OS_REPORT(("Queue %d = %d\n",qIndex, pTxData->txDataDbgCounters.dbgDroppedDueExpiryTimePackets[qIndex]));
   3887     }
   3888     WLAN_OS_REPORT(("-------------- Free MSDUs in sendPacketTransfer ---------------\n"));
   3889     for(qIndex = 0; qIndex < MAX_NUM_OF_TX_QUEUES; qIndex++)
   3890     {
   3891         WLAN_OS_REPORT(("Queue %d = %d\n",qIndex, pTxData->txDataDbgCounters.dbgNumOfMsduFreeInTxTransfer[qIndex]));
   3892     }
   3893 
   3894     WLAN_OS_REPORT(("-------------- sendPacketTransfer CB number ---------------\n"));
   3895     for(qIndex = 0; qIndex < MAX_NUM_OF_TX_QUEUES; qIndex++)
   3896     {
   3897         WLAN_OS_REPORT(("Queue %d = %d\n",qIndex, pTxData->txDataDbgCounters.dbgNumOfMsduTxTransferCB[qIndex]));
   3898     }
   3899 
   3900     WLAN_OS_REPORT(("-------------- XFER done in scheduler ---------------\n"));
   3901     for(qIndex = 0; qIndex < MAX_NUM_OF_TX_QUEUES; qIndex++)
   3902     {
   3903         WLAN_OS_REPORT(("Queue %d = %d\n",qIndex, pTxData->txDataDbgCounters.dbgNumOfMsduXferDoneInShceduler[qIndex]));
   3904     }
   3905 
   3906     WLAN_OS_REPORT(("-------------- Success in scheduler ---------------\n"));
   3907     for(qIndex = 0; qIndex < MAX_NUM_OF_TX_QUEUES; qIndex++)
   3908     {
   3909         WLAN_OS_REPORT(("Queue %d = %d\n",qIndex, pTxData->txDataDbgCounters.dbgNumOfMsduSuccessInScheduler[qIndex]));
   3910     }
   3911 
   3912     WLAN_OS_REPORT(("-------------- Pending in scheduler ---------------\n"));
   3913     for(qIndex = 0; qIndex < MAX_NUM_OF_TX_QUEUES; qIndex++)
   3914     {
   3915         WLAN_OS_REPORT(("Queue %d = %d\n",qIndex, pTxData->txDataDbgCounters.dbgNumOfMsduPendingInScheduler[qIndex]));
   3916     }
   3917 
   3918     WLAN_OS_REPORT(("-------------- Busy in scheduler ---------------\n"));
   3919     for(qIndex = 0; qIndex < MAX_NUM_OF_TX_QUEUES; qIndex++)
   3920     {
   3921         WLAN_OS_REPORT(("Queue %d = %d\n",qIndex, pTxData->txDataDbgCounters.dbgNumOfMsduBusyInScheduler[qIndex]));
   3922     }
   3923 
   3924     WLAN_OS_REPORT(("-------------- Error in scheduler ---------------\n"));
   3925     for(qIndex = 0; qIndex < MAX_NUM_OF_TX_QUEUES; qIndex++)
   3926     {
   3927         WLAN_OS_REPORT(("Queue %d = %d\n",qIndex, pTxData->txDataDbgCounters.dbgNumOfMsduErrorInScheduler[qIndex]));
   3928     }
   3929 
   3930     WLAN_OS_REPORT(("-------------- sendPacketComplete ---------------\n"));
   3931     for(qIndex = 0; qIndex < MAX_NUM_OF_TX_QUEUES; qIndex++)
   3932     {
   3933         WLAN_OS_REPORT(("Queue %d = %d\n",qIndex, pTxData->txDataDbgCounters.dbgNumOfsendPacketComplete[qIndex]));
   3934     }
   3935 
   3936     WLAN_OS_REPORT(("-------------- sendPacketComplete Error---------------\n"));
   3937     for(qIndex = 0; qIndex < MAX_NUM_OF_TX_QUEUES; qIndex++)
   3938     {
   3939         WLAN_OS_REPORT(("Queue %d = %d\n",qIndex, pTxData->txDataDbgCounters.dbgTxCmpltError[qIndex]));
   3940     }
   3941 
   3942 
   3943 
   3944     WLAN_OS_REPORT(("-------------- Number of MSDUs successfuly sent to GWSI layer ---------------\n"));
   3945     for(qIndex = 0; qIndex < MAX_NUM_OF_TX_QUEUES; qIndex++)
   3946     {
   3947         WLAN_OS_REPORT(("Queue %d = %d\n",qIndex, pTxData->txDataDbgCounters.dbgSendToGwsiQosPackets[qIndex]));
   3948     }
   3949 
   3950     WLAN_OS_REPORT(("-------------- Current GWSI port status: %s --------------\n",
   3951                     (GWSI_OPEN == pTxData->txDataGwsiInterfaceStatus ? "OPEN" : "PENDING") ));
   3952 
   3953     WLAN_OS_REPORT(("-------------- HW queue available status ---------------\n"));
   3954     for(qIndex = 0; qIndex < MAX_NUM_OF_TX_QUEUES; qIndex++)
   3955     {
   3956         WLAN_OS_REPORT(("Queue %d %s\n",qIndex,
   3957                         (TRUE == pTxData->txDataAvailableQueue[qIndex] ? "Available" : "Not available") ));
   3958     }
   3959 }
   3960 
   3961 
   3962 void txData_printQosParams(TI_HANDLE hTxData)
   3963 {
   3964     UINT8 acID;
   3965     UINT8 qIndex;
   3966     txData_t *pTxData = (txData_t *)hTxData;
   3967 
   3968     for(acID = FIRST_AC_INDEX;acID < MAX_NUM_OF_AC; acID++)
   3969     {
   3970         switch(acID)
   3971         {
   3972         case QOS_AC_BE:
   3973             WLAN_OS_REPORT(("BE Params:\n"));
   3974             break;
   3975         case QOS_AC_BK:
   3976             WLAN_OS_REPORT(("BK params:\n"));
   3977             break;
   3978         case QOS_AC_VI:
   3979             WLAN_OS_REPORT(("VI params:\n"));
   3980             break;
   3981         case QOS_AC_VO:
   3982             WLAN_OS_REPORT(("VO params:\n"));
   3983             break;
   3984         default:
   3985             break;
   3986         }
   3987 
   3988         switch(pTxData->txDataAcTrfcCtrl[acID].PsMode)
   3989         {
   3990         case PS_SCHEME_UPSD_TRIGGER:
   3991             WLAN_OS_REPORT(("PsMode = UPSD\n"));
   3992 
   3993             break;
   3994         case PS_SCHEME_LEGACY_PSPOLL:
   3995             WLAN_OS_REPORT(("PsMode = PS_POLL\n"));
   3996 
   3997             break;
   3998         case PS_SCHEME_LEGACY:
   3999             WLAN_OS_REPORT(("PsMode = PS_SCHEME_REGULAR\n"));
   4000             break;
   4001 
   4002         case PS_SCHEME_SAPSD:
   4003             WLAN_OS_REPORT(("PsMode = S-APSD\n"));
   4004             break;
   4005 
   4006         default:
   4007             WLAN_OS_REPORT(("Error: PsMode = %d\n", pTxData->txDataAcTrfcCtrl[acID].PsMode));
   4008             break;
   4009         }
   4010         WLAN_OS_REPORT(("QueueIndex = %d\n", pTxData->txDataAcTrfcCtrl[acID].QueueIndex));
   4011         WLAN_OS_REPORT(("TxQueueSize = %d\n", pTxData->txDataAcTrfcCtrl[acID].TxQueueSize));
   4012 
   4013         qIndex = GET_QUEUE_INDEX(pTxData, acID);
   4014 
   4015         if(pTxData->dataMsduListArr[qIndex]->admissionState == AC_NOT_ADMITTED)
   4016             WLAN_OS_REPORT(("admissionState = Not Admitted\n\n" ));
   4017         else
   4018             WLAN_OS_REPORT(("admissionState = Admitted\n\n" ));
   4019 
   4020     }
   4021 
   4022     switch(pTxData->txDataQosParams.headerConverMode)
   4023     {
   4024     case NO_CONVERT:
   4025         WLAN_OS_REPORT(("headerConverMode = NO_CONVERT\n"));
   4026         break;
   4027     case QOS_CONVERT:
   4028         WLAN_OS_REPORT(("headerConverMode = QOS_CONVERT\n"));
   4029         break;
   4030     case LEGACY_CONVERT:
   4031         WLAN_OS_REPORT(("headerConverMode = LEGACY_CONVERT\n"));
   4032         break;
   4033     }
   4034 
   4035     WLAN_OS_REPORT(("tag_ToQueueClfrTable = %d, %d, %d, %d, %d, %d, %d, %d\n",
   4036                     pTxData->txDataQosParams.tag_ToAcClsfrTable[0],
   4037                     pTxData->txDataQosParams.tag_ToAcClsfrTable[1],
   4038                     pTxData->txDataQosParams.tag_ToAcClsfrTable[2],
   4039                     pTxData->txDataQosParams.tag_ToAcClsfrTable[3],
   4040                     pTxData->txDataQosParams.tag_ToAcClsfrTable[4],
   4041                     pTxData->txDataQosParams.tag_ToAcClsfrTable[5],
   4042                     pTxData->txDataQosParams.tag_ToAcClsfrTable[6],
   4043                     pTxData->txDataQosParams.tag_ToAcClsfrTable[7]));
   4044 }
   4045 
   4046 void txData_StartTxThroughputTimer(TI_HANDLE hTxData)
   4047 {
   4048     int counterIndex;
   4049 
   4050     txData_t *pTxData = (txData_t *)hTxData;
   4051 
   4052     if(pTxData->txThroughputTimerEnable == FALSE)
   4053     {
   4054         for(counterIndex = 0 ; counterIndex < MAX_NUM_OF_TX_QUEUES ; counterIndex++)
   4055         {
   4056             /* reset throughput counters */
   4057             pTxData->txDataDbgCounters.dbgInsertToMsduListBytes[counterIndex] = 0;
   4058 
   4059 
   4060         }
   4061 
   4062         pTxData->txThroughputTimerEnable = TRUE;
   4063 
   4064         /* start throughput timer */
   4065         os_timerStart(pTxData->hOs, pTxData->pThroughputTimer, THROUGHPUT_TIMER, TRUE);
   4066     }
   4067 }
   4068 
   4069 void txData_StopTxThroughputTimer(TI_HANDLE hTxData)
   4070 {
   4071     txData_t *pTxData = (txData_t *)hTxData;
   4072 
   4073     if(pTxData->txThroughputTimerEnable == TRUE)
   4074     {
   4075         os_timerStop(pTxData->hOs, pTxData->pThroughputTimer);
   4076         pTxData->txThroughputTimerEnable = FALSE;
   4077     }
   4078 }
   4079 
   4080 static void txData_printTxThroughputPerQueue(TI_HANDLE hTxData)
   4081 {
   4082     txData_t *pTxData = (txData_t *)hTxData;
   4083 
   4084     int qIndex;
   4085 
   4086     WLAN_OS_REPORT(("\n"));
   4087     WLAN_OS_REPORT(("\n"));
   4088     WLAN_OS_REPORT(("-------------- Tx Throughput per Queues Statistics ---------------\n"));
   4089     WLAN_OS_REPORT(("-------------- Send To Wlan Per Queue Throughput---------------\n"));
   4090 
   4091     for(qIndex = 0 ; qIndex < MAX_NUM_OF_TX_QUEUES ; qIndex++)
   4092     {
   4093 
   4094         WLAN_OS_REPORT(("Queue %d = %d KBits/sec\n", qIndex,pTxData->txDataDbgCounters.dbgInsertToMsduListBytes[qIndex]*8/1024));
   4095         /* reset throughput counters */
   4096         pTxData->txDataDbgCounters.dbgInsertToMsduListBytes[qIndex] = 0;
   4097     }
   4098 }
   4099 
   4100 void txData_StartTxAirThroughputTimer (TI_HANDLE hTxData)
   4101 {
   4102     unsigned counterIndex;
   4103 
   4104     txData_t *pTxData = (txData_t *)hTxData;
   4105 
   4106     if (!pTxData->txAirThroughputTimerEnable)
   4107     {
   4108         for (counterIndex = 0; counterIndex < MAX_NUM_OF_TX_QUEUES; counterIndex++)
   4109         {
   4110             /* reset throughput counters */
   4111             pTxData->txDataDbgCounters.dbgTxCmpltOkBytes[counterIndex] = 0;
   4112         }
   4113 
   4114         pTxData->txAirThroughputTimerEnable = TRUE;
   4115 
   4116         /* start throughput timer */
   4117         os_timerStart (pTxData->hOs, pTxData->pAirThroughputTimer, THROUGHPUT_TIMER, TRUE);
   4118     }
   4119 }
   4120 
   4121 void txData_StopTxAirThroughputTimer (TI_HANDLE hTxData)
   4122 {
   4123     txData_t *pTxData = (txData_t *)hTxData;
   4124 
   4125     if (pTxData->txAirThroughputTimerEnable)
   4126     {
   4127         os_timerStop (pTxData->hOs, pTxData->pAirThroughputTimer);
   4128         pTxData->txAirThroughputTimerEnable = FALSE;
   4129     }
   4130 }
   4131 
   4132 static void txData_printTxAirThroughputPerQueue (TI_HANDLE hTxData)
   4133 {
   4134     txData_t *pTxData = (txData_t *)hTxData;
   4135 
   4136     int qIndex;
   4137 
   4138     WLAN_OS_REPORT (("\n"));
   4139     WLAN_OS_REPORT (("\n"));
   4140     WLAN_OS_REPORT (("-------------- Tx Air Throughput per Queue Statistics ---------------\n"));
   4141     WLAN_OS_REPORT (("-------------- Send to WLAN per Queue Throughput---------------\n"));
   4142 
   4143     for (qIndex = 0; qIndex < MAX_NUM_OF_TX_QUEUES; qIndex++)
   4144     {
   4145 
   4146         WLAN_OS_REPORT (("Queue %d = %d KBits/sec\n", qIndex, pTxData->txDataDbgCounters.dbgTxCmpltOkBytes[qIndex] * 8 / 1024));
   4147         /* reset throughput counters */
   4148         pTxData->txDataDbgCounters.dbgTxCmpltOkBytes[qIndex] = 0;
   4149     }
   4150 }
   4151 
   4152 void txData_StartJitterTimer (TI_HANDLE hTxData)
   4153 {
   4154     unsigned u_ac;
   4155 
   4156     txData_t *pTxData = (txData_t *)hTxData;
   4157 
   4158     if (!pTxData->txJitterTimerEnable)
   4159     {
   4160         for (u_ac = 0; u_ac < MAX_NUM_OF_TX_QUEUES; u_ac++)
   4161         {
   4162             /* reset jitter intervals */
   4163             pTxData->txJitter[u_ac].jitter.core = 0;
   4164             pTxData->txJitter[u_ac].jitter.xfer = 0;
   4165             pTxData->txJitter[u_ac].jitter.air  = 0;
   4166             pTxData->txJitter[u_ac].jitter.fw   = 0;
   4167 
   4168             pTxData->txJitter[u_ac].delay.core  = 0;
   4169             pTxData->txJitter[u_ac].delay.xfer  = 0;
   4170             pTxData->txJitter[u_ac].delay.wait  = 0;
   4171             pTxData->txJitter[u_ac].delay.fw    = 0;
   4172             pTxData->txJitter[u_ac].delay.air   = 0;
   4173 
   4174             pTxData->txJitter[u_ac].last_delay.core = 0;
   4175             pTxData->txJitter[u_ac].last_delay.xfer = 0;
   4176             pTxData->txJitter[u_ac].last_delay.fw   = 0;
   4177             pTxData->txJitter[u_ac].last_delay.air  = 0;
   4178 
   4179             pTxData->txJitter[u_ac].max_delay.core  = 0;
   4180             pTxData->txJitter[u_ac].max_delay.xfer  = 0;
   4181             pTxData->txJitter[u_ac].max_delay.fw    = 0;
   4182             pTxData->txJitter[u_ac].max_delay.air   = 0;
   4183 
   4184             pTxData->txJitter[u_ac].count.core  = 0;
   4185             pTxData->txJitter[u_ac].count.xfer  = 0;
   4186             pTxData->txJitter[u_ac].count.wait  = 0;
   4187             pTxData->txJitter[u_ac].count.fw =
   4188                 pTxData->txDataDbgCounters.dbgTxCmpltOk[u_ac];
   4189             pTxData->txJitter[u_ac].count.fw_err =
   4190                 pTxData->txDataDbgCounters.dbgTxCmpltError[u_ac];
   4191         }
   4192 
   4193         pTxData->txJitterTimerEnable = TRUE;
   4194 
   4195         /* start throughput timer */
   4196         os_timerStart (pTxData->hOs, pTxData->pJitterTimer, THROUGHPUT_TIMER, TRUE);
   4197     }
   4198 }
   4199 
   4200 void txData_StopJitterTimer (TI_HANDLE hTxData)
   4201 {
   4202     txData_t *pTxData = (txData_t *)hTxData;
   4203 
   4204     if (pTxData->txJitterTimerEnable)
   4205     {
   4206         os_timerStop (pTxData->hOs, pTxData->pJitterTimer);
   4207         pTxData->txJitterTimerEnable = FALSE;
   4208     }
   4209 }
   4210 
   4211 static void txData_printJitter (TI_HANDLE hTxData)
   4212 {
   4213     unsigned  u_ac;
   4214     txData_t *pTxData = (txData_t *)hTxData;
   4215 
   4216     WLAN_OS_REPORT (("\n"));
   4217     WLAN_OS_REPORT (("\n"));
   4218     WLAN_OS_REPORT (("-------------- Tx Jitter per Queue Statistics ---------------\n"));
   4219 
   4220     for (u_ac = 0; u_ac < MAX_NUM_OF_TX_QUEUES; u_ac ++)
   4221     {
   4222         UINT32 u_ok   = pTxData->txDataDbgCounters.dbgTxCmpltOk[u_ac] -
   4223                         pTxData->txJitter[u_ac].count.fw;
   4224         UINT32 u_nok  = pTxData->txDataDbgCounters.dbgTxCmpltError[u_ac] -
   4225                         pTxData->txJitter[u_ac].count.fw_err;
   4226 
   4227         if (u_ok + u_nok)
   4228         {
   4229             WLAN_OS_REPORT (("Queue [%d], drop=%d%%\n", u_ac, u_nok * 100 / (u_ok + u_nok)));
   4230 
   4231             if (pTxData->txJitter[u_ac].count.core)
   4232             {
   4233                 WLAN_OS_REPORT (("  Core: avg.delay=%6d, max.delay=%6d, jitter=%6d\n",
   4234                                  pTxData->txJitter[u_ac].delay.core / pTxData->txJitter[u_ac].count.core,
   4235                                  pTxData->txJitter[u_ac].max_delay.core,
   4236                                  pTxData->txJitter[u_ac].jitter.core / pTxData->txJitter[u_ac].count.core));
   4237             }
   4238             if (pTxData->txJitter[u_ac].count.xfer)
   4239             {
   4240                 WLAN_OS_REPORT (("  Xfer: avg.delay=%6d, max.delay=%6d, jitter=%6d\n",
   4241                                  pTxData->txJitter[u_ac].delay.xfer / pTxData->txJitter[u_ac].count.xfer,
   4242                                  pTxData->txJitter[u_ac].max_delay.xfer,
   4243                                  pTxData->txJitter[u_ac].jitter.xfer / pTxData->txJitter[u_ac].count.xfer));
   4244             }
   4245             if (pTxData->txJitter[u_ac].count.wait)
   4246             {
   4247                 WLAN_OS_REPORT (("  Wait: avg.delay=%6d\n",
   4248                                  pTxData->txJitter[u_ac].delay.wait / pTxData->txJitter[u_ac].count.wait));
   4249             }
   4250             if (u_ok > 0)
   4251             {
   4252                 WLAN_OS_REPORT (("  Fw:   avg.delay=%6d, max.delay=%6d, jitter=%6d\n",
   4253                                  pTxData->txJitter[u_ac].delay.fw / u_ok,
   4254                                  pTxData->txJitter[u_ac].max_delay.fw,
   4255                                  pTxData->txJitter[u_ac].jitter.fw / u_ok));
   4256                 WLAN_OS_REPORT (("  Air:  avg.delay=%6d, max.delay=%6d, jitter=%6d\n",
   4257                                  pTxData->txJitter[u_ac].delay.air / u_ok,
   4258                                  pTxData->txJitter[u_ac].max_delay.air,
   4259                                  pTxData->txJitter[u_ac].jitter.air / u_ok));
   4260             }
   4261         }
   4262 
   4263         /* Update/reset jitter info */
   4264         pTxData->txJitter[u_ac].jitter.core = 0;
   4265         pTxData->txJitter[u_ac].jitter.xfer = 0;
   4266         pTxData->txJitter[u_ac].jitter.fw   = 0;
   4267         pTxData->txJitter[u_ac].jitter.air  = 0;
   4268 
   4269         pTxData->txJitter[u_ac].delay.core  = 0;
   4270         pTxData->txJitter[u_ac].delay.xfer  = 0;
   4271         pTxData->txJitter[u_ac].delay.wait  = 0;
   4272         pTxData->txJitter[u_ac].delay.fw    = 0;
   4273         pTxData->txJitter[u_ac].delay.air   = 0;
   4274 
   4275         pTxData->txJitter[u_ac].max_delay.core  = 0;
   4276         pTxData->txJitter[u_ac].max_delay.xfer  = 0;
   4277         pTxData->txJitter[u_ac].max_delay.fw    = 0;
   4278         pTxData->txJitter[u_ac].max_delay.air   = 0;
   4279 
   4280         pTxData->txJitter[u_ac].count.core  = 0;
   4281         pTxData->txJitter[u_ac].count.xfer  = 0;
   4282         pTxData->txJitter[u_ac].count.wait  = 0;
   4283         pTxData->txJitter[u_ac].count.fw =
   4284             pTxData->txDataDbgCounters.dbgTxCmpltOk[u_ac];
   4285         pTxData->txJitter[u_ac].count.fw_err =
   4286             pTxData->txDataDbgCounters.dbgTxCmpltError[u_ac];
   4287     }
   4288 }
   4289 
   4290 #endif /* TI_BDG */
   4291 
   4292 /***********************************************************************
   4293  *                     txData_buildQosNullDataFrame
   4294  ***********************************************************************
   4295 DESCRIPTION:    builds QOS_NULL_DATA frame.
   4296 
   4297 INPUT:
   4298 
   4299 OUTPUT:     None
   4300 
   4301 RETURN:     OK on success, NOK otherwise
   4302 ************************************************************************/
   4303 TI_STATUS txData_buildQosNullDataFrame(TI_HANDLE hTxData,mem_MSDU_T **pMsduPsPoll, UINT8 userPriority)
   4304 {
   4305     TI_STATUS       status = OK;
   4306     paramInfo_t     daParam, saParam;
   4307     dot11_header_t   *pFrame; /* Note : there is no body for null frame */
   4308 
   4309     txData_t *pTxData = (txData_t *)hTxData;
   4310     mem_MSDU_T      *pMsdu;
   4311 
   4312     status = wlan_memMngrAllocMSDU(pTxData->hMemMngr, &pMsdu, WLAN_QOS_HDR_LEN + TX_TOTAL_OFFSET_BEFORE_DATA, TX_MODULE);
   4313 
   4314     if (status != OK)
   4315     {
   4316         return NOK;
   4317     }
   4318     pFrame = (dot11_header_t*)(pMsdu->firstBDPtr->data+ TX_TOTAL_OFFSET_BEFORE_DATA);
   4319 
   4320     /* Build frame control */
   4321     pFrame->fc = DOT11_FC_DATA_NULL_QOS;
   4322     pFrame->fc |= (0x1 << DOT11_FC_TO_DS_SHIFT);
   4323 
   4324     pFrame->qosControl = (userPriority << QOS_CONTROL_UP_SHIFT);
   4325 
   4326     pFrame->fc = ENDIAN_HANDLE_WORD(pFrame->fc);
   4327 
   4328     /* BSSID */
   4329     daParam.paramType = CTRL_DATA_CURRENT_BSSID_PARAM;
   4330     status = ctrlData_getParam(pTxData->hCtrlData, &daParam);
   4331     if (status != OK)
   4332     {
   4333         wlan_memMngrFreeMSDU(pTxData->hMemMngr, pMsdu->handle);
   4334         return NOK;
   4335     }
   4336     MAC_COPY(pTxData->hOs, (&pFrame->address3), (&daParam.content.ctrlDataCurrentBSSID));
   4337     MAC_COPY(pTxData->hOs, (&pFrame->address1), (&daParam.content.ctrlDataCurrentBSSID));
   4338 
   4339     /* Source MAC address */
   4340     saParam.paramType = CTRL_DATA_MAC_ADDRESS;
   4341     status = ctrlData_getParam(pTxData->hCtrlData, &saParam);
   4342     if (status != OK)
   4343     {
   4344         wlan_memMngrFreeMSDU(pTxData->hMemMngr, pMsdu->handle);
   4345         return NOK;
   4346     }
   4347    /* copy source mac address */
   4348     MAC_COPY(pTxData->hOs, (&pFrame->address2), (&saParam.content.ctrlDataDeviceMacAddress));
   4349 
   4350     /* Update MSDU parameters */
   4351     pMsdu->headerLen = WLAN_QOS_HDR_LEN;
   4352     pMsdu->dataLen = WLAN_QOS_HDR_LEN;
   4353     pMsdu->firstBDPtr->length = WLAN_QOS_HDR_LEN;
   4354 
   4355     pMsdu->qosTag = userPriority;
   4356     pMsdu->txFlags |= TX_DATA_NULL_MSDU;
   4357 
   4358     // all data or mgmt packets built on host must have the correct
   4359     // offset set to point to the start of the mac frame
   4360     memMgr_BufOffset(pMsdu->firstBDPtr) = TX_TOTAL_OFFSET_BEFORE_DATA;
   4361 
   4362 
   4363     *pMsduPsPoll = pMsdu;
   4364 
   4365     return status;
   4366 }
   4367 
   4368 
   4369 /****************************************************************************
   4370  *                      txData_SetQidToAcTable()
   4371  ****************************************************************************
   4372  * DESCRIPTION: set Qid according to Queue ID
   4373  ****************************************************************************/
   4374 void txData_SetQidToAcTable(TI_HANDLE hTxData,UINT8 QidStart, UINT8 QidEnd,UINT8 AcId)
   4375 {
   4376     int i;
   4377     txData_t *pTxData = (txData_t *)hTxData;
   4378 
   4379     for(i = QidStart ; i <= QidEnd; i++)
   4380         pTxData->QidToAcTable[i] = AcId;
   4381 
   4382 }
   4383 
   4384 /****************************************************************************
   4385  *                      txData_GetAcIdFromQid()
   4386  ****************************************************************************
   4387  * DESCRIPTION: Get the Ac Id according to the Queue id
   4388  ****************************************************************************/
   4389 UINT8 txData_GetAcIdFromQid(TI_HANDLE hTxData,UINT8 Qid)
   4390 {
   4391     txData_t *pTxData = (txData_t *)hTxData;
   4392     return (pTxData->QidToAcTable[Qid]);
   4393 }
   4394 
   4395 /****************************************************************************
   4396  *                      txData_GetWlanHeaderLength()
   4397  ****************************************************************************
   4398  * DESCRIPTION: calculates the WLAN header length, according to QoS,
   4399  * current encryption, and packet type
   4400  ****************************************************************************/
   4401 UINT32 txData_GetWlanHeaderLength( TI_HANDLE hTxData, void *pData, UINT32 txFlags )
   4402 {
   4403     txData_t            *pTxData = (txData_t*)hTxData;
   4404     UINT32              wlanHeaderLength = 0;
   4405     EthernetHeader_t    *pEthHeader;
   4406     UINT16              swapedTypeLength;
   4407 
   4408 
   4409     /* management frames never have QoS or encryption padding */
   4410     if ( txFlags & TX_DATA_MGMT_MSDU )
   4411     {
   4412         return WLAN_HDR_LEN;
   4413     }
   4414 
   4415     /*
   4416      * Determine 802.11 header length
   4417      * QoS Header is longer (2 Bytes)
   4418      */
   4419     if ( pTxData->txDataQosParams.headerConverMode == QOS_CONVERT )
   4420     {
   4421         wlanHeaderLength = WLAN_QOS_HDR_LEN;
   4422     }
   4423     else
   4424     {
   4425         wlanHeaderLength = WLAN_HDR_LEN;
   4426     }
   4427 
   4428     if ( txFlags & TX_DATA_EAPOL_MSDU )
   4429     {
   4430         /* EAPOLs should always contain SNAP */
   4431         wlanHeaderLength += WLAN_SNAP_HDR_LEN;
   4432         /* EAPOL encryption is set by the RSN module */
   4433         if ( TRUE == pTxData->txDataEapolEncryptionStatus )
   4434         {
   4435             wlanHeaderLength += pTxData->encryptionFieldSize;
   4436         }
   4437         return wlanHeaderLength;
   4438     }
   4439 
   4440     /* add encryption overhead - 4 bytes for TKIP, 8 for AES. Actual decision was done at RSN */
   4441     if (pTxData->txDataCurrentPrivacyInvokedMode == TRUE)
   4442     {
   4443         wlanHeaderLength += pTxData->encryptionFieldSize;
   4444     }
   4445 
   4446     /*
   4447      * IAPP header should always include SNAP, but this is already included in the frame
   4448      * body itself, so it is not added here
   4449      */
   4450     if ( txFlags & TX_DATA_IAPP_MSDU )
   4451     {
   4452         return wlanHeaderLength;
   4453     }
   4454 
   4455     /* stat frames are checked if they already contain SNAP header or not */
   4456     if ( txFlags & TX_DATA_DATA_MSDU )
   4457     {
   4458         /*
   4459          * Detect the packet type and decide if to create a
   4460          * new SNAP or leave the original LLC.
   4461          */
   4462         pEthHeader = (EthernetHeader_t *)pData;
   4463         swapedTypeLength = wlan_htons(pEthHeader->TypeLength);
   4464 
   4465         /*
   4466          * if the "type" field is greater than 1500 bytes, it means the frame we received has
   4467          * Ethernet II header (destination MAC, source MAC, type, 14 bytes total), and therefore
   4468          * we need to reserve 8 more bytes after the 802.11 header for LLC/SNAP header.
   4469          * If this field is smaller than or equal to 1500, this is not really a "type" field of
   4470          * Ethernet II header, but rather a 802.3 size field. since 802.3 already has 8 bytes
   4471          * LLC/SNAP header (other than the 802.3 14 bytes of destination MAC, source MAC and size),
   4472          * there is no need to reserve 8 more bytes.
   4473          */
   4474         if ( swapedTypeLength > ETHERNET_MAX_PAYLOAD_SIZE )
   4475         {
   4476             return wlanHeaderLength + WLAN_SNAP_HDR_LEN;
   4477         }
   4478         else
   4479         {
   4480             return wlanHeaderLength;
   4481         }
   4482     }
   4483     else
   4484     {
   4485         WLAN_REPORT_ERROR( pTxData->hReport, TX_DATA_MODULE_LOG,
   4486                            (" %s: trying to get header length for packet with txFlags: 0x%x\n", __FUNCTION__, txFlags) );
   4487         return 0;
   4488     }
   4489 }
   4490 
   4491 /****************************************************************************
   4492  *                      txDataMsduTimeExpired()
   4493  ****************************************************************************
   4494  * DESCRIPTION: calculates the time left until MSDU will expire, retunrs the
   4495  * time in TUs, or 0 if the MSDU has already expired.
   4496  ****************************************************************************/
   4497 UINT32 txDataTimeToMsduExpiry (TI_HANDLE hTxData, mem_MSDU_T* pMsdu, UINT8 qID)
   4498 {
   4499     txData_t    *pTxData = (txData_t*)hTxData;
   4500     UINT32       acID, uPassedTime;
   4501 
   4502     /* translate queue ID to AC ID */
   4503     acID = txData_GetAcIdFromQid (hTxData, qID);
   4504 
   4505     /* get time passed since insertion */
   4506     uPassedTime = os_timeStampUs (pTxData->hOs) - pMsdu->insertionTime;
   4507 
   4508     /* if the passed time is smaller than a certain proportion of the MsduLifeTime - it's O.K. */
   4509     if (uPassedTime <
   4510         ((pTxData->uFracOfLifeTimeToDrop * pTxData->txDataAcTrfcCtrl[acID].MsduLifeTime) / 100))
   4511     {
   4512         return (pTxData->txDataAcTrfcCtrl[acID].MsduLifeTime - uPassedTime) >> 10;
   4513     }
   4514 
   4515     /* timer expired, or about to expire --> drop it.*/
   4516     return 0;
   4517 }
   4518 
   4519 
   4520 /****************************************************************************
   4521 *                               txData_startAfterRecovery                                *
   4522 *****************************************************************************
   4523 * DESCRIPTION:  This function start the tx data after recovery.
   4524 *               It uses params that save before recovery.
   4525 *
   4526 * INPUTS:       hTxData - the object
   4527 *
   4528 * OUTPUT:
   4529 *
   4530 * RETURNS:      OK - stop succesfull
   4531 *               NOK - stop unsuccesfull
   4532 ****************************************************************************/
   4533 TI_STATUS txData_startAfterRecovery(TI_HANDLE hTxData)
   4534 {
   4535     txData_t *pTxData = (txData_t *)hTxData;
   4536 
   4537     /* check parameters validity */
   4538     if( pTxData == NULL )
   4539     {
   4540         WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG,
   4541             (" txData_start() : Illegal value for hTxData\n"));
   4542         return NOK;
   4543     }
   4544 
   4545     pTxData->txDataPortStatus = pTxData->savePortStatus;
   4546     pTxData->txDataCurrentPrivacyInvokedMode = pTxData->saveTxDataCurrentPrivacyInvokedMode;
   4547     pTxData->txDataEapolEncryptionStatus = pTxData->saveTxDataEapolEncryptionStatus;
   4548     pTxData->encryptionFieldSize = pTxData->saveEncryptionFieldSize;
   4549 
   4550     /* start scheduler timer */
   4551     os_timerStart(pTxData->hOs, pTxData->pSchedulerTimer, SCHEDULER_TIMER, TRUE);
   4552     pTxData->bSchedulerTimerRunning = TRUE;
   4553 
   4554     return OK;
   4555 }
   4556 
   4557 
   4558