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