1 /*
2 * txPort.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 /****************************************************************************
36 *
37 * MODULE: txPort.c
38 *
39 * PURPOSE: Multiplexes between the management and data queues.
40 *
41 * DESCRIPTION:
42 * ============
43 * The Tx port state machine multiplexes between the management and data queues
44 * according to the management queues requests.
45 *
46 ****************************************************************************/
47
48 #define __FILE_ID__ FILE_ID_62
49 #include "commonTypes.h"
50 #include "tidef.h"
51 #include "osApi.h"
52 #include "report.h"
53 #include "DataCtrl_Api.h"
54 #include "DrvMainModules.h"
55
56
57 typedef enum
58 {
59 MUX_MGMT_QUEUES, /* The management queues have access to the Tx path. */
60 MUX_DATA_QUEUES /* The data queues have access to the Tx path. */
61 } EQueuesMuxState;
62
63 typedef enum
64 {
65 QUEUE_ACTION_NONE,
66 QUEUE_ACTION_STOP,
67 QUEUE_ACTION_WAKE
68 } EQueueAction;
69
70 /* The txPort module object. */
71 typedef struct
72 {
73 TI_HANDLE hOs;
74 TI_HANDLE hReport;
75 TI_HANDLE hTxDataQ;
76 TI_HANDLE hTxMgmtQ;
77
78 EQueuesMuxState queuesMuxState;
79 TI_BOOL txSuspended;
80 TI_BOOL mgmtQueueEnabled;
81 TI_BOOL dataQueueEnabled;
82 } TTxPortObj;
83
84 /*
85 * The txPort local functions:
86 */
87 static void updateQueuesStates(TTxPortObj *pTxPort);
88 #ifdef TI_DBG
89 static char *txPortMuxStateNameStr(EQueuesMuxState queuesMuxState);
90 static char *txPortActionNameStr(EQueueAction queueAction);
91 #endif
92
93
94
95 /****************************************************************************
96 * txPort_Create()
97 ****************************************************************************
98 * DESCRIPTION: Create the txPort module object
99 *
100 * INPUTS: None
101 *
102 * OUTPUT: None
103 *
104 * RETURNS: The Created object
105 ****************************************************************************/
txPort_create(TI_HANDLE hOs)106 TI_HANDLE txPort_create(TI_HANDLE hOs)
107 {
108 TTxPortObj *pTxPort;
109
110 pTxPort = os_memoryAlloc(hOs, sizeof(TTxPortObj));
111 if (pTxPort == NULL)
112 return NULL;
113
114 os_memoryZero(hOs, pTxPort, sizeof(TTxPortObj));
115
116 pTxPort->hOs = hOs;
117
118 return( (TI_HANDLE)pTxPort );
119 }
120
121
122 /****************************************************************************
123 * txPort_unLoad()
124 ****************************************************************************
125 * DESCRIPTION: Unload the txPort module object
126 *
127 * INPUTS: hTxPort - The object to free
128 *
129 * OUTPUT: None
130 *
131 * RETURNS: TI_OK
132 ****************************************************************************/
txPort_unLoad(TI_HANDLE hTxPort)133 TI_STATUS txPort_unLoad(TI_HANDLE hTxPort)
134 {
135 TTxPortObj *pTxPort = (TTxPortObj *)hTxPort;
136
137 if (pTxPort)
138 os_memoryFree(pTxPort->hOs, pTxPort, sizeof(TTxPortObj));
139
140 return TI_OK;
141 }
142
143
144 /****************************************************************************
145 * txPort_init()
146 ****************************************************************************
147 * DESCRIPTION: Configure the txPort module object
148 *
149 * INPUTS: The needed TI handles
150 *
151 * OUTPUT: None
152 *
153 * RETURNS: void
154 ****************************************************************************/
txPort_init(TStadHandlesList * pStadHandles)155 void txPort_init (TStadHandlesList *pStadHandles)
156 {
157 TTxPortObj *pTxPort = (TTxPortObj *)(pStadHandles->hTxPort);
158
159 pTxPort->hReport = pStadHandles->hReport;
160 pTxPort->hTxDataQ = pStadHandles->hTxDataQ;
161 pTxPort->hTxMgmtQ = pStadHandles->hTxMgmtQ;
162
163 pTxPort->queuesMuxState = MUX_MGMT_QUEUES;
164 pTxPort->txSuspended = TI_FALSE;
165 pTxPort->mgmtQueueEnabled = TI_TRUE;
166 pTxPort->dataQueueEnabled = TI_FALSE;
167 }
168
169
170 /****************************************************************************
171 * txPort_enableData()
172 ****************************************************************************
173 * DESCRIPTION: Called by the txMgmtQueue SM when the Tx path CAN be used by the
174 * data-queues (i.e. it's not needed for mgmt). Update the queues accordingly.
175 ****************************************************************************/
txPort_enableData(TI_HANDLE hTxPort)176 void txPort_enableData(TI_HANDLE hTxPort)
177 {
178 TTxPortObj *pTxPort = (TTxPortObj *)hTxPort;
179
180 pTxPort->queuesMuxState = MUX_DATA_QUEUES;
181 updateQueuesStates(pTxPort);
182 }
183
184
185 /****************************************************************************
186 * txPort_enableMgmt()
187 ****************************************************************************
188 * DESCRIPTION: Called by the txMgmtQueue SM when the Tx path CAN'T be used by the
189 * data-queues (i.e. it's needed for mgmt). Update the queues accordingly.
190 ****************************************************************************/
txPort_enableMgmt(TI_HANDLE hTxPort)191 void txPort_enableMgmt(TI_HANDLE hTxPort)
192 {
193 TTxPortObj *pTxPort = (TTxPortObj *)hTxPort;
194
195 pTxPort->queuesMuxState = MUX_MGMT_QUEUES;
196 updateQueuesStates(pTxPort);
197 }
198
199
200 /****************************************************************************
201 * txPort_suspendTx()
202 ****************************************************************************
203 * DESCRIPTION: Used by STAD applications (e.g. recovery) to temporarily suspend the Tx path.
204 ****************************************************************************/
txPort_suspendTx(TI_HANDLE hTxPort)205 void txPort_suspendTx(TI_HANDLE hTxPort)
206 {
207 TTxPortObj *pTxPort = (TTxPortObj *)hTxPort;
208
209 pTxPort->txSuspended = TI_TRUE;
210 updateQueuesStates(pTxPort);
211 }
212
213
214 /****************************************************************************
215 * txPort_resumeTx()
216 ****************************************************************************
217 * DESCRIPTION: Used by STAD applications (e.g. recovery) to resume Tx path after suspended.
218 ****************************************************************************/
txPort_resumeTx(TI_HANDLE hTxPort)219 void txPort_resumeTx(TI_HANDLE hTxPort)
220 {
221 TTxPortObj *pTxPort = (TTxPortObj *)hTxPort;
222
223 pTxPort->txSuspended = TI_FALSE;
224 updateQueuesStates(pTxPort);
225 }
226
227
228 /****************************************************************************
229 * updateQueuesStates()
230 ****************************************************************************
231 * DESCRIPTION: Switch the Data-Queue and Mgmt-Queue Tx on/off (stop/wake)
232 * according to the current port conditions.
233 ****************************************************************************/
updateQueuesStates(TTxPortObj * pTxPort)234 static void updateQueuesStates (TTxPortObj *pTxPort)
235 {
236 EQueueAction mgmtQueueAction = QUEUE_ACTION_NONE;
237 EQueueAction dataQueueAction = QUEUE_ACTION_NONE;
238 #ifdef TI_DBG
239 char *pMuxStateNameStr;
240 char *pPortActionNameStr;
241 #endif
242
243 /*
244 * If the Tx path is not suspended:
245 */
246 if (!pTxPort->txSuspended)
247 {
248 /* If mgmt-queues should be enabled, set required actions (awake mgmt and stop data if needed). */
249 if (pTxPort->queuesMuxState == MUX_MGMT_QUEUES)
250 {
251 if ( !pTxPort->mgmtQueueEnabled )
252 mgmtQueueAction = QUEUE_ACTION_WAKE;
253 if ( pTxPort->dataQueueEnabled )
254 dataQueueAction = QUEUE_ACTION_STOP;
255 }
256
257 /* If data-queues should be enabled, set required actions (stop mgmt and awake data if needed). */
258 else
259 {
260 if ( pTxPort->mgmtQueueEnabled )
261 mgmtQueueAction = QUEUE_ACTION_STOP;
262 if ( !pTxPort->dataQueueEnabled )
263 dataQueueAction = QUEUE_ACTION_WAKE;
264 }
265 }
266
267 /*
268 * If the Tx path is not available (Xfer is busy or suspension is requested),
269 * set required actions (stop mgmt and data if needed).
270 */
271 else
272 {
273 if ( pTxPort->mgmtQueueEnabled )
274 mgmtQueueAction = QUEUE_ACTION_STOP;
275 if ( pTxPort->dataQueueEnabled )
276 dataQueueAction = QUEUE_ACTION_STOP;
277 }
278
279
280 #ifdef TI_DBG
281 pMuxStateNameStr = txPortMuxStateNameStr(pTxPort->queuesMuxState);
282 TRACE1(pTxPort->hReport, REPORT_SEVERITY_INFORMATION, ": queuesMuxState = , TxSuspend = %d\n", pTxPort->txSuspended);
283
284 pPortActionNameStr = txPortActionNameStr (mgmtQueueAction);
285 TRACE2(pTxPort->hReport, REPORT_SEVERITY_INFORMATION, ": PrevMgmtEnabled = %d, PrevDataEnabled = %d, MgmtAction = , DataAction = \n", pTxPort->mgmtQueueEnabled, pTxPort->dataQueueEnabled);
286 #endif /* TI_DBG */
287
288 /*
289 * Execute the required actions.
290 * Note: This is done at the end of this function because it may start a sequence that will call it again!!
291 * Always do WAKE action after STOP action, since WAKE may lead to more activities!!
292 */
293 if (mgmtQueueAction == QUEUE_ACTION_STOP)
294 {
295 pTxPort->mgmtQueueEnabled = TI_FALSE;
296 txMgmtQ_StopAll (pTxPort->hTxMgmtQ);
297 }
298 if (dataQueueAction == QUEUE_ACTION_STOP)
299 {
300 pTxPort->dataQueueEnabled = TI_FALSE;
301 txDataQ_StopAll (pTxPort->hTxDataQ);
302 }
303 if (mgmtQueueAction == QUEUE_ACTION_WAKE)
304 {
305 pTxPort->mgmtQueueEnabled = TI_TRUE;
306 txMgmtQ_WakeAll (pTxPort->hTxMgmtQ);
307 }
308 if (dataQueueAction == QUEUE_ACTION_WAKE)
309 {
310 pTxPort->dataQueueEnabled = TI_TRUE;
311 txDataQ_WakeAll (pTxPort->hTxDataQ);
312 }
313 }
314
315
316
317 #ifdef TI_DBG
318
319 /****************************************************************************
320 * Debug functions: txPortMuxStateNameStr()
321 * txPortActionNameStr()
322 ****************************************************************************/
txPortMuxStateNameStr(EQueuesMuxState queuesMuxState)323 static char *txPortMuxStateNameStr(EQueuesMuxState queuesMuxState)
324 {
325 switch (queuesMuxState)
326 {
327 case MUX_MGMT_QUEUES: return "MUX_MGMT_QUEUES";
328 case MUX_DATA_QUEUES: return "MUX_DATA_QUEUES";
329 default: return "UNKNOWN STATE";
330 }
331 }
332
txPortActionNameStr(EQueueAction queueAction)333 static char *txPortActionNameStr(EQueueAction queueAction)
334 {
335 switch (queueAction)
336 {
337 case QUEUE_ACTION_NONE: return "QUEUE_ACTION_NONE";
338 case QUEUE_ACTION_STOP: return "QUEUE_ACTION_STOP";
339 case QUEUE_ACTION_WAKE: return "QUEUE_ACTION_WAKE";
340 default: return "UNKNOWN ACTION";
341 }
342 }
343
344 #endif /* TI_DBG */
345
346
347