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/*
65This 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 */
205extern UINT8 wmeAcToUpIndex[MAX_NUM_OF_AC];
206
207/* defined in qosMngr.c - used to identify voice packets in NON QOS APs */
208extern 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
217static void txData_convertEthToWlanHeader (txData_t *pTxData, mem_MSDU_T *pMsdu);
218
219static TI_STATUS txData_schedulerSelectQueueToTransmitFrom( TI_HANDLE hTxData, MsduList_t** pMsduListPtr,UINT8 *selectedQueueIndex );
220
221static void txData_startTxSchedulerFromTimer(TI_HANDLE hTxData);
222
223static void txData_calcCreditFromTimer(TI_HANDLE hTxData);
224
225static void txData_UpdateTxCounters( TI_HANDLE hTxData, txCompleteAttr_t *pTxCompleteAttr );
226
227static void txData_SetTxDelayCounters( TI_HANDLE hTxData, UINT32 txQid, txCompleteAttr_t *pTxCompleteAttr, UINT32 driverDelay );
228
229static int txData_selectQueueAndUpdateUserPriority (txData_t *pTxData, mem_MSDU_T *pMsdu, int *selectedQueue, acTrfcType_e *selectedAc);
230
231static int txData_getHighestAdmittedAc(txData_t *pTxData, int startingAcIndex);
232
233static void txData_startVadTimer(TI_HANDLE hTxData, UINT16 voiceDuration);
234static void txData_stopVadTimer(TI_HANDLE hTxData);
235static void txData_setVadTimer(TI_HANDLE hTxData, BOOL vadEnabled, UINT16 duration);
236static void txData_resetVadTimer(TI_HANDLE hTxData);
237static void txData_vadTimeout(TI_HANDLE hTxData);
238#ifdef TI_DBG
239
240static void txData_printTxThroughputPerQueue(TI_HANDLE hTxData);
241
242static void txData_printTxAirThroughputPerQueue(TI_HANDLE hTxData);
243
244static void txData_printJitter(TI_HANDLE hTxData);
245
246#endif
247
248static BOOL txData_acVoPsPollMode(txData_t *pTxData);
249
250static UINT32 txDataTimeToMsduExpiry( TI_HANDLE htxData, mem_MSDU_T* pMsdu, UINT8 Qid);
251
252static UINT8 txData_GetAcIdFromQid(TI_HANDLE hTxData,UINT8 Qid);
253
254TI_STATUS txData_setMediumUsageThresholds(TI_HANDLE     hTxData,
255                                      UINT8             acID,
256                                      INT32             highMediumUsageThreshold,
257                                      INT32             lowMediumUsageThreshold);
258
259static void txData_SetQidToAcTable(TI_HANDLE hTxData,UINT8 QidStart, UINT8 QidEnd,UINT8 AcId);
260
261/* The TX delay histogram ranges start and end in msec. */
262static UINT32 txDelayRangeStart[TX_DELAY_RANGES_NUM] = { 0,  1, 10, 20, 40, 60,  80, 100, 200 };
263static 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*************************************************************************/
276TI_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
485TI_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
594TI_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
661TI_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****************************************************************************/
748TI_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****************************************************************************/
776void 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***************************************************************************/
829TI_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***************************************************************************/
854TI_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
938TI_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
1101TI_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
1291TI_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***************************************************************************/
1725void 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***************************************************************************/
1813TI_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
1910void 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
1964static 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***************************************************************************/
2018static 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
2073static 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***************************************************************************/
2104TI_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***************************************************************************/
2124TI_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
2160static 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***************************************************************************/
2326TI_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***************************************************************************/
2411TI_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***************************************************************************/
2610static 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***************************************************************************/
2769void 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***************************************************************************/
2788void 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***************************************************************************/
2810static 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****************************************************************************/
2820TI_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****************************************************************************/
2832TI_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****************************************************************************/
2844TI_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 ****************************************************************************/
2870static 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***************************************************************************/
2925void 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
3016static 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
3036static 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
3048static 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
3059static 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
3075static 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***************************************************************************/
3097static 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 ***********************************************************************
3108DESCRIPTION:    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
3114INPUT:      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
3119OUTPUT:     None
3120
3121RETURN:     OK on success, NOK otherwise
3122************************************************************************/
3123TI_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 ***********************************************************************
3190DESCRIPTION:    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
3201INPUT:      acID - Currently not used!  Supporting only AC_VO!
3202
3203OUTPUT:     None
3204
3205RETURN:     OK on success, NOK otherwise
3206************************************************************************/
3207
3208TI_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 ***********************************************************************
3261DESCRIPTION:    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----------------------------
3268PS 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
3279typedef struct
3280{
3281  UINT16        fc;
3282  UINT16        AID;
3283  macAddress_t  BSSID;
3284  macAddress_t  TA;
3285} dot11_PsPollFrameHeader_t;
3286
3287
3288INPUT:
3289
3290OUTPUT:     None
3291
3292RETURN:     OK on success, NOK otherwise
3293************************************************************************/
3294TI_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 ***********************************************************************
3405DESCRIPTION:    This function is called for every txComplete in order
3406                to update the transmisssion time.
3407
3408INPUT:          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
3412OUTPUT:     None
3413
3414RETURN:     OK on success
3415************************************************************************/
3416TI_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 ***********************************************************************
3430DESCRIPTION:    This function is called when credit calculation timer
3431                is expired. it calculate the credit for the admission ctrl
3432                credit algorithm
3433
3434
3435INPUT:          hTxData - handle to the ts data object
3436
3437OUTPUT:     None
3438
3439RETURN:     void
3440************************************************************************/
3441static 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 ***********************************************************************
3565DESCRIPTION:    This function is called for add/delete a tspec in order
3566                to update parameters.
3567
3568INPUT:          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
3574OUTPUT:     None
3575
3576RETURN:     void
3577************************************************************************/
3578TI_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 ***********************************************************************
3657DESCRIPTION:    This function is called for add/delete a tspec in order
3658                to set the PS mode for a specific UP
3659
3660INPUT:          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
3664OUTPUT:     None
3665
3666RETURN:     OK on success, NOK otherwise
3667************************************************************************/
3668TI_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 ***********************************************************************
3678DESCRIPTION:    This function is called in order to set the threshold
3679                for the medium time usage
3680
3681INPUT:          hTxData - handale to the ts data object
3682                acID - the AC
3683                highMediumUsageThreshold - high threshold
3684                lowMediumUsageThreshold - lowhreshold
3685
3686OUTPUT:     None
3687
3688RETURN:     OK on success, NOK otherwise
3689************************************************************************/
3690TI_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 ***********************************************************************
3717DESCRIPTION:
3718
3719INPUT:          hTxData - handale to the ts data object
3720
3721OUTPUT:     None
3722
3723RETURN:     OK on success, NOK otherwise
3724************************************************************************/
3725
3726BOOL 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
3739void 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
3753void 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/*
3784void printFullMsduList(MsduList_t *this);
3785void printMsduList(MsduList_t *this);
3786*/
3787void 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
3801void 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
3813void txData_printMgmtMsduList(TI_HANDLE hTxData)
3814{
3815    txData_t *pTxData = (txData_t *)hTxData;
3816
3817    printMsduList(pTxData->mngMsduList);
3818
3819
3820}
3821
3822void txData_fullPrintMgmtMsduList(TI_HANDLE hTxData)
3823{
3824    txData_t *pTxData = (txData_t *)hTxData;
3825
3826    printFullMsduList(pTxData->mngMsduList);
3827}
3828
3829
3830void 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
3856void 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
3962void 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
4046void 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
4069void 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
4080static 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
4100void 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
4121void 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
4132static 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
4152void 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
4200void 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
4211static 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 ***********************************************************************
4295DESCRIPTION:    builds QOS_NULL_DATA frame.
4296
4297INPUT:
4298
4299OUTPUT:     None
4300
4301RETURN:     OK on success, NOK otherwise
4302************************************************************************/
4303TI_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 ****************************************************************************/
4374void 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 ****************************************************************************/
4389UINT8 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 ****************************************************************************/
4401UINT32 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 ****************************************************************************/
4497UINT32 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****************************************************************************/
4533TI_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