1 /* 2 * healthMonitor.c 3 * 4 * Copyright(c) 1998 - 2010 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 /** \file healthMonitor.c 35 * \brief Firmware Recovery Mechanism 36 */ 37 38 /** \file healthMonitor.c 39 * \brief The health monitor module. Gets failures indications and handle them. 40 * 41 * For periodic check, use HW watchdog mechanizem instead of local periodic timer check 42 * 43 * \see healthMonitor.h 44 */ 45 46 #define __FILE_ID__ FILE_ID_66 47 #include "healthMonitor.h" 48 #include "osApi.h" 49 #include "timer.h" 50 #include "report.h" 51 #include "siteMgrApi.h" 52 #include "PowerMgr_API.h" 53 #include "currBss.h" 54 #include "DataCtrl_Api.h" 55 #include "TWDriver.h" 56 #include "SoftGeminiApi.h" 57 #include "currBss.h" 58 #include "rsnApi.h" 59 #include "DrvMain.h" 60 #include "DrvMainModules.h" 61 #include "TWDriverInternal.h" 62 63 64 typedef struct 65 { 66 /* handles to other modules */ 67 TI_HANDLE hOs; /* handle to the OS object */ 68 TI_HANDLE hReport; /* handle to the report object */ 69 TI_HANDLE hTWD; /* handle to the TWD object */ 70 TI_HANDLE hSiteMgr; /* handle to the site manager object */ 71 TI_HANDLE hScr; /* handle to the SCR object */ 72 TI_HANDLE hSoftGemini; /* handle to the Soft Gemini object */ 73 TI_HANDLE hDrvMain; /* handle to the Recovery Mgr object */ 74 TI_HANDLE hTxCtrl; /* handle to the TX Ctrl object */ 75 TI_HANDLE hCurrBss; /* handle to the currBss object */ 76 TI_HANDLE hRsn; /* handle to the RSN */ 77 TI_HANDLE hTimer; /* handle to the Timer module object */ 78 TI_HANDLE hContext; /* handle to the context-engine object */ 79 80 /* Timers handles */ 81 TI_HANDLE hFailTimer; /* failure event timer */ 82 83 /* Management variables */ 84 TI_UINT32 numOfHealthTests; /* number of health tests performed counter */ 85 healthMonitorState_e state; /* health monitor state */ 86 TI_BOOL bFullRecoveryEnable; /* full recovery enable flag */ 87 TI_BOOL recoveryTriggerEnabled [MAX_FAILURE_EVENTS]; 88 /* recovery enable flags per trigger type */ 89 TI_UINT32 failureEvent; /* current recovery trigger */ 90 TI_UINT32 keepAliveIntervals; /* number of health monitor timer intervals at which keep alive should be sent */ 91 TI_UINT32 currentKeepAliveCounter;/* counting how many timer intervals had passed w/o a keep alive */ 92 93 /* Recoveries Statistics */ 94 TI_UINT32 recoveryTriggersNumber [MAX_FAILURE_EVENTS]; 95 /* Number of times each recovery trigger occured */ 96 TI_UINT32 numOfRecoveryPerformed; /* number of recoveries performed */ 97 98 } THealthMonitor; 99 100 101 static void healthMonitor_proccessFailureEvent (TI_HANDLE hHealthMonitor, TI_BOOL bTwdInitOccured); 102 103 104 #ifdef REPORT_LOG 105 106 static char* sRecoveryTriggersNames [MAX_FAILURE_EVENTS] = 107 { 108 "NO_SCAN_COMPLETE_FAILURE", 109 "MBOX_FAILURE", 110 "HW_AWAKE_FAILURE", 111 "TX_STUCK", 112 "DISCONNECT_TIMEOUT", 113 "POWER_SAVE_FAILURE", 114 "MEASUREMENT_FAILURE", 115 "BUS_FAILURE", 116 "HW_WD_EXPIRE", 117 "RX_XFER_FAILURE" 118 }; 119 #endif 120 121 122 /** 123 * \fn healthMonitor_create 124 * \brief Create module object 125 * 126 * Create module object. 127 * 128 * \note 129 * \param hOs - The OS adaptation handle 130 * \return The created module handle 131 * \sa 132 */ 133 TI_HANDLE healthMonitor_create (TI_HANDLE hOs) 134 { 135 THealthMonitor *pHealthMonitor; 136 137 /* Allocate memory for the health monitor object and nullify it */ 138 pHealthMonitor = (THealthMonitor*)os_memoryAlloc (hOs, sizeof(THealthMonitor)); 139 if (pHealthMonitor == NULL) 140 { 141 return NULL; 142 } 143 os_memoryZero (hOs, pHealthMonitor, sizeof(THealthMonitor)); 144 145 /* Store OS object handle */ 146 pHealthMonitor->hOs = hOs; 147 148 return (TI_HANDLE)pHealthMonitor; 149 } 150 151 152 /** 153 * \fn healthMonitor_init 154 * \brief Init module handles and variables 155 * 156 * Init module handles and variables. 157 * 158 * \note 159 * \param pStadHandles - The driver modules handles 160 * \return void 161 * \sa 162 */ 163 void healthMonitor_init (TStadHandlesList *pStadHandles) 164 { 165 THealthMonitor *pHealthMonitor = (THealthMonitor *)(pStadHandles->hHealthMonitor); 166 167 pHealthMonitor->hReport = pStadHandles->hReport; 168 pHealthMonitor->hTWD = pStadHandles->hTWD; 169 pHealthMonitor->hSiteMgr = pStadHandles->hSiteMgr; 170 pHealthMonitor->hScr = pStadHandles->hSCR; 171 pHealthMonitor->hSoftGemini = pStadHandles->hSoftGemini; 172 pHealthMonitor->hDrvMain = pStadHandles->hDrvMain; 173 pHealthMonitor->hTxCtrl = pStadHandles->hTxCtrl; 174 pHealthMonitor->hCurrBss = pStadHandles->hCurrBss; 175 pHealthMonitor->hRsn = pStadHandles->hRsn; 176 pHealthMonitor->hTimer = pStadHandles->hTimer; 177 pHealthMonitor->hContext = pStadHandles->hContext; 178 179 pHealthMonitor->state = HEALTH_MONITOR_STATE_DISCONNECTED; 180 pHealthMonitor->failureEvent = (TI_UINT32)NO_FAILURE; 181 182 /* Register the failure event callback */ 183 TWD_RegisterCb (pHealthMonitor->hTWD, 184 TWD_EVENT_FAILURE, 185 (void *)healthMonitor_sendFailureEvent, 186 (void *)pHealthMonitor); 187 } 188 189 190 /** 191 * \fn healthMonitor_SetDefaults 192 * \brief Set module defaults and create timers 193 * 194 * Set module defaults from Ini-file and create timers. 195 * 196 * \note 197 * \param hHealthMonitor - The module's handle 198 * \param healthMonitorInitParams - The module's parameters default values (from Ini-file). 199 * \return void 200 * \sa 201 */ 202 TI_STATUS healthMonitor_SetDefaults (TI_HANDLE hHealthMonitor, healthMonitorInitParams_t *healthMonitorInitParams) 203 { 204 THealthMonitor *pHealthMonitor = hHealthMonitor; 205 int i; 206 207 /* Registry configuration */ 208 pHealthMonitor->bFullRecoveryEnable = healthMonitorInitParams->FullRecoveryEnable; 209 210 for (i = 0; i < MAX_FAILURE_EVENTS; i++) 211 { 212 pHealthMonitor->recoveryTriggerEnabled[i] = healthMonitorInitParams->recoveryTriggerEnabled[i]; 213 } 214 215 /* Create recovery request timer */ 216 pHealthMonitor->hFailTimer = tmr_CreateTimer (pHealthMonitor->hTimer); 217 if (pHealthMonitor->hFailTimer == NULL) 218 { 219 TRACE0(pHealthMonitor->hReport, REPORT_SEVERITY_ERROR, "healthMonitor_SetDefaults(): Failed to create hFailTimer!\n"); 220 return TI_NOK; 221 } 222 223 return TI_OK; 224 } 225 226 227 /*********************************************************************** 228 * healthMonitor_unload 229 *********************************************************************** 230 DESCRIPTION: 231 232 INPUT: 233 234 OUTPUT: 235 236 RETURN: 237 238 ************************************************************************/ 239 TI_STATUS healthMonitor_unload (TI_HANDLE hHealthMonitor) 240 { 241 THealthMonitor *pHealthMonitor; 242 243 pHealthMonitor = (THealthMonitor*)hHealthMonitor; 244 245 if (pHealthMonitor != NULL) 246 { 247 if (NULL != pHealthMonitor->hFailTimer) 248 { 249 /* Release the timer */ 250 tmr_DestroyTimer (pHealthMonitor->hFailTimer); 251 } 252 253 /* Freeing the object should be called last !!!!!!!!!!!! */ 254 os_memoryFree (pHealthMonitor->hOs, pHealthMonitor, sizeof(THealthMonitor)); 255 } 256 257 return TI_OK; 258 } 259 260 261 /*********************************************************************** 262 * healthMonitor_setState 263 *********************************************************************** 264 DESCRIPTION: 265 266 267 INPUT: 268 269 OUTPUT: 270 271 RETURN: 272 273 ************************************************************************/ 274 void healthMonitor_setState (TI_HANDLE hHealthMonitor, healthMonitorState_e state) 275 { 276 THealthMonitor *pHealthMonitor = (THealthMonitor*)hHealthMonitor; 277 278 pHealthMonitor->state = state; 279 } 280 281 282 /*********************************************************************** 283 * healthMonitor_PerformTest 284 *********************************************************************** 285 DESCRIPTION: Called periodically by timer every few seconds (depends on connection state), 286 or optionally by external application. 287 288 INPUT: hHealthMonitor - Module handle. 289 bTwdInitOccured - Indicates if TWDriver recovery occured since timer started 290 291 OUTPUT: 292 293 RETURN: 294 295 ************************************************************************/ 296 void healthMonitor_PerformTest (TI_HANDLE hHealthMonitor, TI_BOOL bTwdInitOccured) 297 { 298 THealthMonitor *pHealthMonitor = (THealthMonitor*)hHealthMonitor; 299 300 pHealthMonitor->numOfHealthTests++; 301 302 /* Send health-check command to FW, just to ensure command complete is accepted */ 303 TWD_CmdHealthCheck (pHealthMonitor->hTWD); 304 } 305 306 307 /*********************************************************************** 308 * healthMonitor_sendFailureEvent 309 *********************************************************************** 310 DESCRIPTION: Entry point for all low level modules to send a failure evrnt 311 312 INPUT: handle - health monitor handle 313 failureEvent - the error 314 315 OUTPUT: 316 317 RETURN: 318 319 ************************************************************************/ 320 void healthMonitor_sendFailureEvent (TI_HANDLE hHealthMonitor, EFailureEvent failureEvent) 321 { 322 THealthMonitor *pHealthMonitor = (THealthMonitor*)hHealthMonitor; 323 324 /* Check the recovery process is already running */ 325 if (pHealthMonitor->failureEvent < MAX_FAILURE_EVENTS) 326 { 327 TRACE0(pHealthMonitor->hReport, REPORT_SEVERITY_WARNING , ": recovery process is already handling , new trigger is \n"); 328 } 329 330 /* Recovery is performed only if this trigger is enabled in the .INI file */ 331 else if (pHealthMonitor->recoveryTriggerEnabled[failureEvent]) 332 { 333 pHealthMonitor->failureEvent = failureEvent; 334 /* 335 * NOTE: start timer with minimum expiry (1 msec) for recovery will start 336 * from the top of the stack 337 */ 338 tmr_StartTimer (pHealthMonitor->hFailTimer, 339 healthMonitor_proccessFailureEvent, 340 (TI_HANDLE)pHealthMonitor, 341 1, 342 TI_FALSE); 343 } 344 else 345 { 346 TRACE0(pHealthMonitor->hReport, REPORT_SEVERITY_ERROR , ": Recovery trigger is disabled!\n"); 347 } 348 } 349 350 351 /*********************************************************************** 352 * healthMonitor_proccessFailureEvent 353 *********************************************************************** 354 DESCRIPTION: this is the central error function - will be passed as call back 355 to the TnetWDriver modules. it will parse the error and dispatch the 356 relevant action (recovery or not) 357 358 INPUT: hHealthMonitor - health monitor handle 359 bTwdInitOccured - Indicates if TWDriver recovery occured since timer started 360 361 OUTPUT: 362 363 RETURN: 364 365 ************************************************************************/ 366 void healthMonitor_proccessFailureEvent (TI_HANDLE hHealthMonitor, TI_BOOL bTwdInitOccured) 367 { 368 THealthMonitor *pHealthMonitor = (THealthMonitor*)hHealthMonitor; 369 370 /* Check failure event validity */ 371 if (pHealthMonitor->failureEvent < MAX_FAILURE_EVENTS) 372 { 373 pHealthMonitor->recoveryTriggersNumber[pHealthMonitor->failureEvent] ++; 374 375 TRACE2(pHealthMonitor->hReport, REPORT_SEVERITY_CONSOLE, "***** recovery trigger: failureEvent =%d *****, ts=%d\n", pHealthMonitor->failureEvent, os_timeStampMs(pHealthMonitor->hOs)); 376 WLAN_OS_REPORT (("***** recovery trigger: %s *****, ts=%d\n", sRecoveryTriggersNames[pHealthMonitor->failureEvent], os_timeStampMs(pHealthMonitor->hOs))); 377 378 if (TWD_RecoveryEnabled (pHealthMonitor->hTWD)) 379 { 380 pHealthMonitor->numOfRecoveryPerformed ++; 381 drvMain_Recovery (pHealthMonitor->hDrvMain); 382 } 383 else 384 { 385 TRACE0(pHealthMonitor->hReport, REPORT_SEVERITY_CONSOLE, "healthMonitor_proccessFailureEvent: Recovery is disabled in tiwlan.ini, abort recovery process\n"); 386 WLAN_OS_REPORT(("healthMonitor_proccessFailureEvent: Recovery is disabled in tiwlan.ini, abort recovery process\n")); 387 } 388 389 pHealthMonitor->failureEvent = (TI_UINT32)NO_FAILURE; 390 } 391 else 392 { 393 TRACE1(pHealthMonitor->hReport, REPORT_SEVERITY_ERROR , "unsupported failure event = %d\n", pHealthMonitor->failureEvent); 394 } 395 } 396 397 398 /*********************************************************************** 399 * healthMonitor_printFailureEvents 400 *********************************************************************** 401 DESCRIPTION: 402 403 INPUT: 404 405 OUTPUT: 406 407 RETURN: 408 ************************************************************************/ 409 void healthMonitor_printFailureEvents(TI_HANDLE hHealthMonitor) 410 { 411 #ifdef TI_DBG 412 #ifdef REPORT_LOG 413 THealthMonitor *pHealthMonitor = (THealthMonitor*)hHealthMonitor; 414 int i; 415 416 WLAN_OS_REPORT(("-------------- STA Health Failure Statistics ---------------\n")); 417 WLAN_OS_REPORT(("FULL RECOVERY PERFORMED = %d\n", pHealthMonitor->numOfRecoveryPerformed)); 418 for (i = 0; i < MAX_FAILURE_EVENTS; i++) 419 { 420 WLAN_OS_REPORT(("%27s= %d\n", sRecoveryTriggersNames[ i ], pHealthMonitor->recoveryTriggersNumber[ i ])); 421 } 422 WLAN_OS_REPORT(("Maximum number of commands in mailbox queue = %u\n", TWD_GetMaxNumberOfCommandsInQueue(pHealthMonitor->hTWD))); 423 WLAN_OS_REPORT(("Health Test Performed = %d\n", pHealthMonitor->numOfHealthTests)); 424 WLAN_OS_REPORT(("\n")); 425 #endif 426 #endif /* TI_DBG */ 427 } 428 429 430 /*********************************************************************** 431 * healthMonitor_SetParam 432 *********************************************************************** 433 DESCRIPTION: Set module parameters from the external command interface 434 435 INPUT: hHealthMonitor - module handle. 436 pParam - Pointer to the parameter 437 438 OUTPUT: 439 440 RETURN: TI_OK on success, TI_NOK otherwise 441 ************************************************************************/ 442 TI_STATUS healthMonitor_SetParam (TI_HANDLE hHealthMonitor, paramInfo_t *pParam) 443 { 444 THealthMonitor *pHealthMonitor = (THealthMonitor*)hHealthMonitor; 445 TI_STATUS eStatus = TI_OK; 446 447 TRACE1(pHealthMonitor->hReport, REPORT_SEVERITY_INFORMATION, "healthMonitor_SetParam() - %d\n", pParam->paramType); 448 449 switch(pParam->paramType) 450 { 451 452 case HEALTH_MONITOR_CHECK_DEVICE: 453 /* Send health check command to FW if we are not disconnceted */ 454 if (pHealthMonitor->state != HEALTH_MONITOR_STATE_DISCONNECTED) 455 { 456 healthMonitor_PerformTest (hHealthMonitor, TI_FALSE); 457 } 458 break; 459 460 default: 461 TRACE1(pHealthMonitor->hReport, REPORT_SEVERITY_ERROR, "healthMonitor_SetParam(): Params is not supported, %d\n", pParam->paramType); 462 } 463 464 return eStatus; 465 } 466 467 468 /*********************************************************************** 469 * healthMonitor_GetParam 470 *********************************************************************** 471 DESCRIPTION: Get module parameters from the external command interface 472 473 INPUT: hHealthMonitor - module handle. 474 pParam - Pointer to the parameter 475 476 OUTPUT: 477 478 RETURN: TI_OK on success, TI_NOK otherwise 479 ************************************************************************/ 480 TI_STATUS healthMonitor_GetParam (TI_HANDLE hHealthMonitor, paramInfo_t *pParam) 481 { 482 return TI_OK; 483 } 484 485 486 487 488