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 ****************************************************************************/ 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 ****************************************************************************/ 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 ****************************************************************************/ 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 ****************************************************************************/ 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 ****************************************************************************/ 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 ****************************************************************************/ 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 ****************************************************************************/ 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 ****************************************************************************/ 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 ****************************************************************************/ 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 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