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, ¶m);
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