• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * txDataQueue.c
3  *
4  * Copyright(c) 1998 - 2009 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 /** \file   txDataQueue.c
36  *  \brief  The Tx Data Queues module.
37  *
38  *  \see    txDataQueue.h
39  */
40 
41 
42 #define __FILE_ID__  FILE_ID_60
43 #include "paramOut.h"
44 #include "osApi.h"
45 #include "report.h"
46 #include "queue.h"
47 #include "context.h"
48 #include "Ethernet.h"
49 #include "TWDriver.h"
50 #include "DataCtrl_Api.h"
51 #include "txDataQueue.h"
52 #include "DrvMainModules.h"
53 #include "bmtrace_api.h"
54 
55 
56 /* Internal Functions prototypes */
57 static void txDataQ_RunScheduler (TI_HANDLE hTxDataQ);
58 static void txDataQ_UpdateQueuesBusyState (TTxDataQ *pTxDataQ, TI_UINT32 uTidBitMap);
59 
60 
61 /***************************************************************************
62 *                      PUBLIC  FUNCTIONS  IMPLEMENTATION				   *
63 ****************************************************************************/
64 
65 
66 /**
67  * \fn     txDataQ_Create
68  * \brief  Create the module and its queues
69  *
70  * Create the Tx Data module and its queues.
71  *
72  * \note
73  * \param  hOs - Handle to the Os Abstraction Layer
74  * \return Handle to the allocated Tx Data Queue module (NULL if failed)
75  * \sa
76  */
txDataQ_Create(TI_HANDLE hOs)77 TI_HANDLE txDataQ_Create(TI_HANDLE hOs)
78 {
79     TTxDataQ *pTxDataQ;
80 
81     /* allocate TxDataQueue module */
82     pTxDataQ = os_memoryAlloc (hOs, (sizeof(TTxDataQ)));
83 
84     if (!pTxDataQ)
85 	{
86         WLAN_OS_REPORT(("Error allocating the TxDataQueue Module\n"));
87 		return NULL;
88 	}
89 
90     /* Reset TxDataQueue module */
91     os_memoryZero (hOs, pTxDataQ, (sizeof(TTxDataQ)));
92 
93     return (TI_HANDLE)pTxDataQ;
94 }
95 
96 
97 /**
98  * \fn     txDataQ_Init
99  * \brief  Save required modules handles
100  *
101  * Save other modules handles.
102  *
103  * \note
104  * \param  pStadHandles  - The driver modules handles
105  * \return void
106  * \sa
107  */
txDataQ_Init(TStadHandlesList * pStadHandles)108 void txDataQ_Init (TStadHandlesList *pStadHandles)
109 {
110     TTxDataQ  *pTxDataQ = (TTxDataQ *)(pStadHandles->hTxDataQ);
111     TI_UINT32  uNodeHeaderOffset = TI_FIELD_OFFSET(TTxnStruct, tTxnQNode);
112     TI_UINT8   uQueId;
113 
114     /* save modules handles */
115     pTxDataQ->hContext	= pStadHandles->hContext;
116     pTxDataQ->hTxCtrl	= pStadHandles->hTxCtrl;
117     pTxDataQ->hOs		= pStadHandles->hOs;
118     pTxDataQ->hReport	= pStadHandles->hReport;
119     pTxDataQ->hTxMgmtQ	= pStadHandles->hTxMgmtQ;
120 
121     /* Configures the Port Default status to Close */
122 	pTxDataQ->bDataPortEnable = TI_FALSE;
123 
124 	/* Configures the LastQueId to zero => scheduler will strart from Queue 1*/
125 	pTxDataQ->uLastQueId = 0;
126 
127 	/* init the number of the Data queue to be used */
128 	pTxDataQ->uNumQueues = MAX_NUM_OF_AC;
129 
130 	/* init the max size of the Data queues */
131 	pTxDataQ->aQueueMaxSize[QOS_AC_BE] = DATA_QUEUE_DEPTH_BE;
132 	pTxDataQ->aQueueMaxSize[QOS_AC_BK] = DATA_QUEUE_DEPTH_BK;
133 	pTxDataQ->aQueueMaxSize[QOS_AC_VI] = DATA_QUEUE_DEPTH_VI;
134 	pTxDataQ->aQueueMaxSize[QOS_AC_VO] = DATA_QUEUE_DEPTH_VO;
135 
136     /* Create the tx data queues */
137 	for (uQueId = 0; uQueId < pTxDataQ->uNumQueues; uQueId++)
138     {
139         pTxDataQ->aQueues[uQueId] = que_Create (pTxDataQ->hOs,
140                                                 pTxDataQ->hReport,
141                                                 pTxDataQ->aQueueMaxSize[uQueId],
142                                                 uNodeHeaderOffset);
143 
144 		/* If any Queues' allocation failed, print error, free TxDataQueue module and exit */
145 		if (pTxDataQ->aQueues[uQueId] == NULL)
146 		{
147             TRACE0(pTxDataQ->hReport, REPORT_SEVERITY_CONSOLE , "Failed to create queue\n");
148 			WLAN_OS_REPORT(("Failed to create queue\n"));
149 			os_memoryFree (pTxDataQ->hOs, pTxDataQ, sizeof(TTxDataQ));
150 			return;
151 		}
152 
153 		/* Configure the Queue default Mode to Open (not busy)*/
154 		pTxDataQ->aQueueBusy[uQueId] = TI_FALSE;
155     }
156 
157     /* Register to the context engine and get the client ID */
158     pTxDataQ->uContextId = context_RegisterClient (pTxDataQ->hContext,
159                                                    txDataQ_RunScheduler,
160                                                    (TI_HANDLE)pTxDataQ,
161                                                    TI_TRUE,
162                                                    "TX_DATA",
163                                                    sizeof("TX_DATA"));
164 }
165 
166 
167 /**
168  * \fn     txDataQ_SetDefaults
169  * \brief  Configure module with default settings
170  *
171  * Init the Tx Data queues.
172  * Register as the context-engine client.
173  *
174  * \note
175  * \param  hTxDataQ - The object
176  * \param  Other modules handles
177  * \return TI_OK on success or TI_NOK on failure
178  * \sa
179  */
txDataQ_SetDefaults(TI_HANDLE hTxDataQ,txDataInitParams_t * pTxDataInitParams)180 TI_STATUS txDataQ_SetDefaults (TI_HANDLE  hTxDataQ, txDataInitParams_t *pTxDataInitParams)
181 {
182     TTxDataQ  *pTxDataQ = (TTxDataQ *)hTxDataQ;
183 	TI_STATUS  eStatus;
184 
185     /* configure the classifier sub-module */
186     eStatus = txDataClsfr_Config (hTxDataQ, &pTxDataInitParams->ClsfrInitParam);
187     if (eStatus != TI_OK)
188     {
189         TRACE0(pTxDataQ->hReport, REPORT_SEVERITY_CONSOLE ,"FATAL ERROR: txDataQ_SetDefaults(): txDataClsfr_Config failed - Aborting\n");
190         WLAN_OS_REPORT(("FATAL ERROR: txDataQ_SetDefaults(): txDataClsfr_Config failed - Aborting\n"));
191         return eStatus;
192     }
193 
194 TRACE0(pTxDataQ->hReport, REPORT_SEVERITY_INIT, ".....Tx Data Queue configured successfully\n");
195 
196     return TI_OK;
197 }
198 
199 
200 /**
201  * \fn     txDataQ_Destroy
202  * \brief  Destroy the module and its queues
203  *
204  * Clear and destroy the queues and then destroy the module object.
205  *
206  * \note
207  * \param  hTxDataQ - The object
208  * \return TI_OK - Unload succesfull, TI_NOK - Unload unsuccesfull
209  * \sa
210  */
txDataQ_Destroy(TI_HANDLE hTxDataQ)211 TI_STATUS txDataQ_Destroy (TI_HANDLE hTxDataQ)
212 {
213     TTxDataQ  *pTxDataQ = (TTxDataQ *)hTxDataQ;
214     TI_STATUS  status = TI_OK;
215     TI_UINT32  uQueId;
216 
217     /* Dequeue and free all queued packets */
218     txDataQ_ClearQueues (hTxDataQ);
219 
220     /* Free Data queues */
221     for (uQueId = 0 ; uQueId < pTxDataQ->uNumQueues ; uQueId++)
222     {
223         if (que_Destroy(pTxDataQ->aQueues[uQueId]) != TI_OK)
224 		{
225             TRACE1(pTxDataQ->hReport, REPORT_SEVERITY_ERROR, "txDataQueue_unLoad: fail to free Data Queue number: %d\n",uQueId);
226 			status = TI_NOK;
227 		}
228     }
229 
230     /* Free Tx Data Queue Module */
231     os_memoryFree (pTxDataQ->hOs, pTxDataQ, sizeof(TTxDataQ));
232 
233     return status;
234 }
235 
236 
237 /**
238  * \fn     txDataQ_ClearQueues
239  * \brief  Clear all queues
240  *
241  * Dequeue and free all queued packets.
242  *
243  * \note
244  * \param  hTxDataQ - The object
245  * \return void
246  * \sa
247  */
txDataQ_ClearQueues(TI_HANDLE hTxDataQ)248 void txDataQ_ClearQueues (TI_HANDLE hTxDataQ)
249 {
250     TTxDataQ   *pTxDataQ = (TTxDataQ *)hTxDataQ;
251     TTxCtrlBlk *pPktCtrlBlk;
252     TI_UINT32  uQueId;
253 
254     /* Dequeue and free all queued packets */
255     for (uQueId = 0 ; uQueId < pTxDataQ->uNumQueues ; uQueId++)
256     {
257         do {
258             context_EnterCriticalSection (pTxDataQ->hContext);
259             pPktCtrlBlk = (TTxCtrlBlk *) que_Dequeue(pTxDataQ->aQueues[uQueId]);
260             context_LeaveCriticalSection (pTxDataQ->hContext);
261             if (pPktCtrlBlk != NULL) {
262                 txCtrl_FreePacket (pTxDataQ->hTxCtrl, pPktCtrlBlk, TI_NOK);
263             }
264         } while (pPktCtrlBlk != NULL);
265     }
266 }
267 
268 
269 /**
270  * \fn     txDataQ_InsertPacket
271  * \brief  Insert packet in queue and schedule task
272  *
273  * This function is called by the hard_start_xmit() callback function.
274  * If the packet it an EAPOL, forward it to the Mgmt-Queue.
275  * Otherwise, classify the packet, enqueue it and request
276  *   context switch for handling it in the driver's context.
277  *
278  * \note
279  * \param  hTxDataQ    - The object
280  * \param  pPktCtrlBlk - Pointer to the packet
281  * \param  uPacketDtag - The packet priority optionaly set by the OAL
282  * \return TI_OK - if the packet was queued, TI_NOK - if the packet was dropped.
283  * \sa     txDataQ_Run
284  */
txDataQ_InsertPacket(TI_HANDLE hTxDataQ,TTxCtrlBlk * pPktCtrlBlk,TI_UINT8 uPacketDtag)285 TI_STATUS txDataQ_InsertPacket (TI_HANDLE hTxDataQ, TTxCtrlBlk *pPktCtrlBlk, TI_UINT8 uPacketDtag)
286 {
287     TTxDataQ        *pTxDataQ = (TTxDataQ *)hTxDataQ;
288 	TEthernetHeader *pEthHead = (TEthernetHeader *)(pPktCtrlBlk->tTxnStruct.aBuf[0]);
289 	TI_STATUS        eStatus;
290     TI_UINT32        uQueId;
291     TI_UINT32        uQueSize;
292 	CL_TRACE_START_L3();
293 
294     /* If packet is EAPOL, forward it to the Mgmt-Queue and exit */
295     if (HTOWLANS(pEthHead->type) == ETHERTYPE_EAPOL)
296     {
297 		pPktCtrlBlk->tTxPktParams.uPktType = TX_PKT_TYPE_EAPOL;
298 
299         return txMgmtQ_Xmit (pTxDataQ->hTxMgmtQ, pPktCtrlBlk, TI_TRUE);
300         /* Note: The last parameter indicates that we are running in external context */
301     }
302 
303     pPktCtrlBlk->tTxPktParams.uPktType = TX_PKT_TYPE_ETHER;
304 
305     /* Enter critical section to protect classifier data and queue access */
306     context_EnterCriticalSection (pTxDataQ->hContext);
307 
308 	/* Call the Classify function to set the TID field */
309 	if (txDataClsfr_ClassifyTxPacket (hTxDataQ, pPktCtrlBlk, uPacketDtag) != TI_OK)
310 	{
311 #ifdef TI_DBG
312 		pTxDataQ->uClsfrMismatchCount++;
313 TRACE0(pTxDataQ->hReport, REPORT_SEVERITY_WARNING, "txDataQueue_xmit: No matching classifier found \n");
314 #endif /* TI_DBG */
315 	}
316 
317 	/* Enqueue the packet in the appropriate Queue */
318     uQueId = aTidToQueueTable[pPktCtrlBlk->tTxDescriptor.tid];
319     eStatus = que_Enqueue (pTxDataQ->aQueues[uQueId], (TI_HANDLE)pPktCtrlBlk);
320 
321     /* Get number of packets in current queue */
322     uQueSize = que_Size (pTxDataQ->aQueues[uQueId]);
323 
324     /* Leave critical section */
325     context_LeaveCriticalSection (pTxDataQ->hContext);
326 
327     /* If the queue was empty, request switch to driver context for handling queued packet(s) */
328     if (uQueSize == 1)
329     {
330         context_RequestSchedule (pTxDataQ->hContext, pTxDataQ->uContextId);
331     }
332 
333 	if (eStatus != TI_OK)
334     {
335         /* If the packet can't be queued drop it */
336         txCtrl_FreePacket (pTxDataQ->hTxCtrl, pPktCtrlBlk, TI_NOK);
337       #ifdef TI_DBG
338 		pTxDataQ->aQueueCounters[uQueId].uDroppedPacket++;
339       #endif /* TI_DBG */
340     }
341 	else
342     {
343       #ifdef TI_DBG
344 		pTxDataQ->aQueueCounters[uQueId].uEnqueuePacket++;
345       #endif /* TI_DBG */
346     }
347 
348     CL_TRACE_END_L3 ("tiwlan_drv.ko", "INHERIT", "TX", "");
349 
350     return eStatus;
351 }
352 
353 
354 /**
355  * \fn     txDataQ_StopQueue
356  * \brief  Set queue's busy indication
357  *
358  * This function is called by the txCtrl_xmitData() if the queue's backpressure
359  *   indication is set.
360  * It sets the internal queue's Busy indication.
361  *
362  * \note
363  * \param  hTxDataQ - The object
364  * \param  uTidBitMap   - The changed TIDs busy bitmap
365  * \return void
366  * \sa     txDataQ_UpdateBusyMap
367  */
txDataQ_StopQueue(TI_HANDLE hTxDataQ,TI_UINT32 uTidBitMap)368 void txDataQ_StopQueue (TI_HANDLE hTxDataQ, TI_UINT32 uTidBitMap)
369 {
370 	TTxDataQ *pTxDataQ = (TTxDataQ *)hTxDataQ;
371 
372 	/* Set the relevant queue(s) busy flag */
373 	txDataQ_UpdateQueuesBusyState (pTxDataQ, uTidBitMap);
374 }
375 
376 
377 /**
378  * \fn     txDataQ_UpdateBusyMap
379  * \brief  Set queue's busy indication
380  *
381  * This function is called by the txCtrl if the backpressure map per TID is changed.
382  * This could be as a result of Tx-Complete, admission change or association.
383  * The function modifies the internal queue's Busy indication and calls the scheduler.
384  *
385  * \note
386  * \param  hTxDataQ - The object
387  * \param  uTidBitMap   - The changed TIDs busy bitmap
388  * \return void
389  * \sa     txDataQ_StopQueue
390  */
txDataQ_UpdateBusyMap(TI_HANDLE hTxDataQ,TI_UINT32 tidBitMap)391 void txDataQ_UpdateBusyMap (TI_HANDLE hTxDataQ, TI_UINT32 tidBitMap)
392 {
393 	TTxDataQ *pTxDataQ = (TTxDataQ *)hTxDataQ;
394 
395 	/* Update the Queue(s) mode */
396 	txDataQ_UpdateQueuesBusyState (pTxDataQ, tidBitMap);
397 
398 	/* Run the scheduler */
399 	txDataQ_RunScheduler (hTxDataQ);
400 }
401 
402 
403 /**
404  * \fn     txDataQ_StopAll
405  * \brief  Disable Data-Queue module access to Tx path.
406  *
407  * Called by the Tx-Port when the data-queue module can't access the Tx path.
408  * Sets stop-all-queues indication.
409  *
410  * \note
411  * \param  hTxDataQ - The object
412  * \return void
413  * \sa     txDataQ_WakeAll
414  */
txDataQ_StopAll(TI_HANDLE hTxDataQ)415 void txDataQ_StopAll (TI_HANDLE hTxDataQ)
416 {
417     TTxDataQ *pTxDataQ = (TTxDataQ *)hTxDataQ;
418 
419 	/* Disable the data Tx port */
420 	pTxDataQ->bDataPortEnable = TI_FALSE;
421 }
422 
423 
424 /**
425  * \fn     txDataQ_WakeAll
426  * \brief  Enable Data-Queue module access to Tx path.
427  *
428  * Called by the Tx-Port when the data-queue module can access the Tx path.
429  * Clears the stop-all-queues indication and calls the scheduler.
430  *
431  * \note
432  * \param  hTxDataQ - The object
433  * \return void
434  * \sa     txDataQ_StopAll
435  */
txDataQ_WakeAll(TI_HANDLE hTxDataQ)436 void txDataQ_WakeAll (TI_HANDLE hTxDataQ)
437 {
438     TTxDataQ *pTxDataQ = (TTxDataQ *)hTxDataQ;
439 
440 	/* Enable the data Tx port */
441 	pTxDataQ->bDataPortEnable = TI_TRUE;
442 
443 	/* Run the scheduler */
444 	txDataQ_RunScheduler (hTxDataQ);
445 }
446 
447 
448 /***************************************************************************
449 *                       DEBUG  FUNCTIONS  IMPLEMENTATION			       *
450 ****************************************************************************/
451 
452 #ifdef TI_DBG
453 
454 /**
455  * \fn     txDataQ_PrintModuleParams
456  * \brief  Print Module Parameters
457  *
458  * Print Module Parameters
459  *
460  * \note
461  * \param  hTxDataQ - The object
462  * \return void
463  * \sa
464  */
txDataQ_PrintModuleParams(TI_HANDLE hTxDataQ)465 void txDataQ_PrintModuleParams (TI_HANDLE hTxDataQ)
466 {
467 	TTxDataQ *pTxDataQ = (TTxDataQ *)hTxDataQ;
468 	TI_UINT32      qIndex;
469 
470 	WLAN_OS_REPORT(("--------- txDataQueue_printModuleParams ----------\n\n"));
471 
472 	WLAN_OS_REPORT(("bDataPortEnable = %d\n",pTxDataQ->bDataPortEnable));
473 	WLAN_OS_REPORT(("uNumQueues      = %d\n",pTxDataQ->uNumQueues));
474 	WLAN_OS_REPORT(("uLastQueId      = %d\n",pTxDataQ->uLastQueId));
475 	WLAN_OS_REPORT(("uContextId      = %d\n",pTxDataQ->uContextId));
476 
477 	for (qIndex = 0; qIndex < pTxDataQ->uNumQueues; qIndex++)
478     {
479 		WLAN_OS_REPORT(("aQueueBusy[%d]	   = %d\n", qIndex, pTxDataQ->aQueueBusy[qIndex]));
480         WLAN_OS_REPORT(("aQueueMaxSize[%d] = %d\n", qIndex, pTxDataQ->aQueueMaxSize[qIndex]));
481     }
482 
483 	WLAN_OS_REPORT(("-------------- Queues Info -----------------------\n"));
484 	for (qIndex = 0; qIndex < MAX_NUM_OF_AC; qIndex++)
485     {
486         WLAN_OS_REPORT(("Que %d:\n", qIndex));
487         que_Print (pTxDataQ->aQueues[qIndex]);
488     }
489 
490 	WLAN_OS_REPORT(("--------------------------------------------------\n\n"));
491 }
492 
493 
494 /**
495  * \fn     txDataQ_PrintQueueStatistics
496  * \brief  Print queues statistics
497  *
498  * Print queues statistics
499  *
500  * \note
501  * \param  hTxDataQ - The object
502  * \return void
503  * \sa
504  */
txDataQ_PrintQueueStatistics(TI_HANDLE hTxDataQ)505 void txDataQ_PrintQueueStatistics (TI_HANDLE hTxDataQ)
506 {
507 #ifdef REPORT_LOG
508     TTxDataQ *pTxDataQ = (TTxDataQ *)hTxDataQ;
509     TI_UINT32      qIndex;
510 
511     WLAN_OS_REPORT(("-------------- txDataQueue_printStatistics -------\n\n"));
512 
513     WLAN_OS_REPORT(("-------------- Classifier Mismatches = %d  -------\n",pTxDataQ->uClsfrMismatchCount));
514 
515     WLAN_OS_REPORT(("-------------- Enqueue to queues -----------------\n"));
516     for(qIndex = 0; qIndex < MAX_NUM_OF_AC; qIndex++)
517         WLAN_OS_REPORT(("Que[%d]: = %d\n",qIndex, pTxDataQ->aQueueCounters[qIndex].uEnqueuePacket));
518 
519     WLAN_OS_REPORT(("-------------- Dequeue from queues ---------------\n"));
520     for(qIndex = 0; qIndex < MAX_NUM_OF_AC; qIndex++)
521         WLAN_OS_REPORT(("Que[%d]: = %d\n",qIndex, pTxDataQ->aQueueCounters[qIndex].uDequeuePacket));
522 
523     WLAN_OS_REPORT(("-------------- Requeue to queues -----------------\n"));
524     for(qIndex = 0; qIndex < MAX_NUM_OF_AC; qIndex++)
525         WLAN_OS_REPORT(("Que[%d]: = %d\n",qIndex, pTxDataQ->aQueueCounters[qIndex].uRequeuePacket));
526 
527     WLAN_OS_REPORT(("-------------- Sent to TxCtrl --------------------\n"));
528     for(qIndex = 0; qIndex < MAX_NUM_OF_AC; qIndex++)
529         WLAN_OS_REPORT(("Que[%d]: = %d\n",qIndex, pTxDataQ->aQueueCounters[qIndex].uXmittedPacket));
530 
531     WLAN_OS_REPORT(("-------------- Dropped - Queue Full --------------\n"));
532     for(qIndex = 0; qIndex < MAX_NUM_OF_AC; qIndex++)
533         WLAN_OS_REPORT(("Que[%d]: = %d\n",qIndex, pTxDataQ->aQueueCounters[qIndex].uDroppedPacket));
534 
535     WLAN_OS_REPORT(("--------------------------------------------------\n\n"));
536 #endif
537 }
538 
539 
540 /**
541  * \fn     txDataQ_ResetQueueStatistics
542  * \brief  Reset queues statistics
543  *
544  * Reset queues statistics
545  *
546  * \note
547  * \param  hTxDataQ - The object
548  * \return void
549  * \sa
550  */
txDataQ_ResetQueueStatistics(TI_HANDLE hTxDataQ)551 void txDataQ_ResetQueueStatistics (TI_HANDLE hTxDataQ)
552 {
553 	TTxDataQ *pTxDataQ = (TTxDataQ *)hTxDataQ;
554 
555     os_memoryZero(pTxDataQ->hOs, &pTxDataQ->aQueueCounters, sizeof(pTxDataQ->aQueueCounters));
556 }
557 
558 
559 #endif /* TI_DBG */
560 
561 
562 
563 /***************************************************************************
564 *                      INTERNAL  FUNCTIONS  IMPLEMENTATION				   *
565 ****************************************************************************/
566 
567 
568 /**
569  * \fn     txDataQ_RunScheduler
570  * \brief  The module's Tx scheduler
571  *
572  * This function is the Data-Queue scheduler.
573  * It selects a packet to transmit from the tx queues and sends it to the TxCtrl.
574  * The queues are selected in a round-robin order.
575  * The function is called by one of:
576  *     txDataQ_Run()
577  *     txDataQ_UpdateBusyMap()
578  *     txDataQ_WakeAll()
579  *
580  * \note
581  * \param  hTxDataQ - The object
582  * \return void
583  * \sa
584  */
txDataQ_RunScheduler(TI_HANDLE hTxDataQ)585 static void txDataQ_RunScheduler (TI_HANDLE hTxDataQ)
586 {
587 	TTxDataQ   *pTxDataQ = (TTxDataQ *)hTxDataQ;
588 	TI_UINT32  uIdleIterationsCount = 0;  /* Count iterations without packet transmission (for exit criteria) */
589 	TI_UINT32  uQueId = pTxDataQ->uLastQueId;  /* The last iteration queue */
590 	TI_STATUS  eStatus;  /* The return status of the txCtrl_xmitData function */
591     TTxCtrlBlk *pPktCtrlBlk; /* Pointer to the packet to be dequeued and sent */
592 
593 	while(1)
594 	{
595 		/* check if the Data port is closed or if the scheduler couldn't send packet from
596 		     all queues => no packet can be transferred to the TNET */
597 		if ( !pTxDataQ->bDataPortEnable  ||  (uIdleIterationsCount >= pTxDataQ->uNumQueues) )
598 		{
599 			return;
600 		}
601 
602 		/* Selecting the next queue */
603 		uQueId++;
604 		if (uQueId == pTxDataQ->uNumQueues)
605         {
606 			uQueId = 0;
607         }
608 		pTxDataQ->uLastQueId = uQueId;
609 
610 		/* Increment the idle iterations counter */
611 		uIdleIterationsCount++;
612 
613 		/* If the queue is busy (AC is full), continue to next queue. */
614 		if (pTxDataQ->aQueueBusy[uQueId])
615         {
616 			continue;
617         }
618 
619 		/* Dequeue a packet in a critical section */
620         context_EnterCriticalSection (pTxDataQ->hContext);
621 		pPktCtrlBlk = (TTxCtrlBlk *) que_Dequeue (pTxDataQ->aQueues[uQueId]);
622         context_LeaveCriticalSection (pTxDataQ->hContext);
623 
624 		/* If the queue was empty, continue to the next queue */
625 		if (pPktCtrlBlk == NULL)
626         {
627 			continue;
628         }
629 
630 #ifdef TI_DBG
631 		pTxDataQ->aQueueCounters[uQueId].uDequeuePacket++;
632 #endif /* TI_DBG */
633 
634 		/* Send the packet */
635 		eStatus = txCtrl_XmitData (pTxDataQ->hTxCtrl, pPktCtrlBlk);
636 
637 		/*
638          * If the return status is busy it means that the packet was not sent
639          *   so we need to requeue it for future try.
640          */
641 		if(eStatus == STATUS_XMIT_BUSY)
642 		{
643             /* Requeue the packet in a critical section */
644             context_EnterCriticalSection (pTxDataQ->hContext);
645 			que_Requeue (pTxDataQ->aQueues[uQueId], (TI_HANDLE)pPktCtrlBlk);
646             context_LeaveCriticalSection (pTxDataQ->hContext);
647 
648 #ifdef TI_DBG
649 			pTxDataQ->aQueueCounters[uQueId].uRequeuePacket++;
650 #endif /* TI_DBG */
651 
652 			continue;
653 		}
654 
655 		/* If we reach this point, a packet was sent successfully so reset the idle iterations counter. */
656 		uIdleIterationsCount = 0;
657 
658 #ifdef TI_DBG
659 		pTxDataQ->aQueueCounters[uQueId].uXmittedPacket++;
660 #endif /* TI_DBG */
661 
662 	} /* End of while */
663 
664 	/* Unreachable code */
665 }
666 
667 
668 /**
669  * \fn     txDataQ_UpdateQueuesBusyState
670  * \brief  Update queues' busy state
671  *
672  * Update the Queues Mode to Busy according to the input TidBitMap.
673 *               Each Tid that is set indicates that the related Queue is Busy.
674 *
675  * \note
676  * \param  hTxDataQ - The object
677  * \param  uTidBitMap   - The changed TIDs busy bitmap
678  * \return void
679  * \sa
680  */
txDataQ_UpdateQueuesBusyState(TTxDataQ * pTxDataQ,TI_UINT32 uTidBitMap)681 static void txDataQ_UpdateQueuesBusyState (TTxDataQ *pTxDataQ, TI_UINT32 uTidBitMap)
682 {
683 	TI_UINT32 uTidIdx;
684 
685 	/* Go over the TidBitMap and update the related queue busy state */
686 	for (uTidIdx = 0; uTidIdx < MAX_NUM_OF_802_1d_TAGS; uTidIdx++, uTidBitMap >>= 1)
687 	{
688 		if (uTidBitMap & 0x1) /* this Tid is busy */
689         {
690 			pTxDataQ->aQueueBusy[aTidToQueueTable[uTidIdx]] = TI_TRUE;
691         }
692 		else
693         {
694 			pTxDataQ->aQueueBusy[aTidToQueueTable[uTidIdx]] = TI_FALSE;
695         }
696 	}
697 }
698