1 /******************************************************************************* 2 *Copyright (c) 2014 PMC-Sierra, Inc. All rights reserved. 3 * 4 *Redistribution and use in source and binary forms, with or without modification, are permitted provided 5 *that the following conditions are met: 6 *1. Redistributions of source code must retain the above copyright notice, this list of conditions and the 7 *following disclaimer. 8 *2. Redistributions in binary form must reproduce the above copyright notice, 9 *this list of conditions and the following disclaimer in the documentation and/or other materials provided 10 *with the distribution. 11 * 12 *THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED 13 *WARRANTIES,INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 14 *FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 15 *FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 16 *NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 17 *BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 18 *LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 19 *SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE 20 21 ********************************************************************************/ 22 /*******************************************************************************/ 23 /*! \file satimer.c 24 * \brief The file implements the timerTick function 25 * 26 */ 27 /******************************************************************************/ 28 #include <sys/cdefs.h> 29 #include <dev/pms/config.h> 30 31 #include <dev/pms/RefTisa/sallsdk/spc/saglobal.h> 32 #ifdef SA_FW_TEST_BUNCH_STARTS 33 void mpiMsgProduceBunch( agsaLLRoot_t *saRoot); 34 #endif /* SA_FW_TEST_BUNCH_STARTS */ 35 36 #ifdef SA_ENABLE_TRACE_FUNCTIONS 37 #ifdef siTraceFileID 38 #undef siTraceFileID 39 #endif 40 #define siTraceFileID 'P' 41 #endif 42 43 /******************************************************************************/ 44 /*! \brief TimerTick 45 * 46 * TimerTick 47 * 48 * \param agRoot handles for this instance of SAS/SATA hardware 49 * 50 * \return -void- 51 */ 52 /*******************************************************************************/ 53 GLOBAL void saTimerTick( 54 agsaRoot_t *agRoot 55 ) 56 { 57 agsaLLRoot_t *saRoot = (agsaLLRoot_t *)(agRoot->sdkData); 58 agsaTimerDesc_t *pTimer; 59 bit32 Event; 60 void * pParm; 61 62 if(agNULL == saRoot) 63 { 64 SA_DBG1(("saTimerTick:agNULL == saRoot \n")); 65 return; 66 } 67 68 /* (1) Acquire timer list lock */ 69 ossaSingleThreadedEnter(agRoot, LL_TIMER_LOCK); 70 71 /* (2) Find the timers are timeout */ 72 pTimer = (agsaTimerDesc_t *) saLlistGetHead(&(saRoot->validTimers)); 73 while ( agNULL != pTimer ) 74 { 75 /* (2.1) Find the first timer is timeout */ 76 if ( pTimer->timeoutTick == saRoot->timeTick ) 77 { 78 /* (2.1.1) remove the timer from valid timer list */ 79 saLlistRemove(&(saRoot->validTimers), &(pTimer->linkNode)); 80 /* (2.1.2) Invalid timer */ 81 pTimer->valid = agFALSE; 82 /* (2.1.3) Get timer event and param */ 83 Event = pTimer->Event; 84 pParm = pTimer->pParm; 85 /* (2.1.4) Release timer list lock */ 86 ossaSingleThreadedLeave(agRoot, LL_TIMER_LOCK); 87 88 /* (2.1.5) Timer Callback */ 89 pTimer->pfnTimeout(agRoot, Event, pParm); 90 91 /* (2.1.6) Acquire timer list lock again */ 92 ossaSingleThreadedEnter(agRoot, LL_TIMER_LOCK); 93 /* (2.1.7) return the timer to free timer list */ 94 saLlistAdd(&(saRoot->freeTimers), &(pTimer->linkNode)); 95 } 96 /* (2.2) the first timer is not timeout */ 97 else 98 { 99 break; 100 } 101 pTimer = (agsaTimerDesc_t *) saLlistGetHead(&(saRoot->validTimers)); 102 } 103 104 /* (3) increment timeTick */ 105 saRoot->timeTick ++; 106 107 if( saRoot->ResetFailed ) 108 { 109 SA_DBG1(("saTimerTick: siChipResetV saRoot->ResetFailed\n")); 110 } 111 112 #ifdef SA_FW_TEST_BUNCH_STARTS 113 if (saRoot->BunchStarts_Enable && 114 saRoot->BunchStarts_Pending) 115 { 116 SA_DBG3(("saTimerTick: mpiMsgProduceBunch\n")); 117 mpiMsgProduceBunch( saRoot); 118 } 119 #endif /* SA_FW_TEST_BUNCH_STARTS */ 120 121 122 #ifdef SA_FW_TEST_INTERRUPT_REASSERT 123 124 if(1) 125 { 126 mpiOCQueue_t *circularQ; 127 int i; 128 SA_DBG4(("saTimerTick:SA_FW_TEST_INTERRUPT_REASSERT\n")); 129 for ( i = 0; i < saRoot->QueueConfig.numOutboundQueues; i++ ) 130 { 131 circularQ = &saRoot->outboundQueue[i]; 132 OSSA_READ_LE_32(circularQ->agRoot, &circularQ->producerIdx, circularQ->piPointer, 0); 133 if(circularQ->producerIdx != circularQ->consumerIdx) 134 { 135 if( saRoot->OldCi[i] == circularQ->consumerIdx && saRoot->OldPi[i] >= circularQ->producerIdx) 136 { 137 agsaEchoCmd_t payload; 138 payload.tag = 0xF0; 139 payload.payload[0]= 0x0; 140 if( ++saRoot->OldFlag[i] > 1 ) 141 { 142 saRoot->CheckAll++; 143 } 144 SA_DBG1(("saTimerTick:Q %d (%d) PI 0x%03x CI 0x%03x (%d) CheckAll %d %d\n",i, 145 saRoot->OldFlag[i], 146 circularQ->producerIdx, 147 circularQ->consumerIdx, 148 (circularQ->producerIdx > circularQ->consumerIdx ? (circularQ->producerIdx - circularQ->consumerIdx) : (circularQ->numElements - circularQ->consumerIdx ) + circularQ->producerIdx), 149 saRoot->CheckAll, 150 saRoot->sysIntsActive )); 151 152 if(smIS64bInt(agRoot)) 153 { 154 SA_DBG1(("saTimerTick:CheckAll %d ODR 0x%08X%08X ODMR 0x%08X%08X our Int %x\n", 155 saRoot->CheckAll, 156 ossaHwRegReadExt(agRoot, 0, V_Outbound_Doorbell_Set_RegisterU), 157 ossaHwRegReadExt(agRoot, 0, V_Outbound_Doorbell_Set_Register), 158 ossaHwRegReadExt(agRoot, 0, V_Outbound_Doorbell_Mask_Set_RegisterU), 159 ossaHwRegReadExt(agRoot, 0, V_Outbound_Doorbell_Mask_Set_Register), 160 saRoot->OurInterrupt(agRoot,i) 161 )); 162 } 163 else 164 { 165 SA_DBG1(("saTimerTick:CheckAll %d ODR 0x%08X ODMR 0x%08X our Int %x\n", 166 saRoot->CheckAll, 167 siHalRegReadExt(agRoot, GEN_MSGU_ODR, V_Outbound_Doorbell_Set_Register), 168 siHalRegReadExt(agRoot, GEN_MSGU_ODMR, V_Outbound_Doorbell_Mask_Set_Register), 169 saRoot->OurInterrupt(agRoot,i) 170 )); 171 } 172 173 174 if( saRoot->CheckAll > 1) 175 { 176 saEchoCommand(agRoot,agNULL, ((i << 16) & 0xFFFF0000 ), (void *)&payload); 177 } 178 179 } 180 else 181 { 182 saRoot->OldFlag[i] = 0; 183 } 184 185 saRoot->OldPi[i] = circularQ->producerIdx; 186 saRoot->OldCi[i] = circularQ->consumerIdx; 187 188 } 189 } 190 } 191 #endif /* SA_FW_TEST_INTERRUPT_REASSERT */ 192 193 /* (4) Release timer list lock */ 194 ossaSingleThreadedLeave(agRoot, LL_TIMER_LOCK); 195 #ifdef SA_FW_TEST_INTERRUPT_REASSERT 196 if(saRoot->CheckAll ) 197 { 198 int a; 199 for(a=0; a < 32; a++ ) 200 { 201 if (saRoot->interruptVecIndexBitMap[a] & (1 << a)) 202 { 203 SA_DBG1(("saTimerTick DI %d\n",a)); 204 saSystemInterruptsEnable ( agRoot, a ); 205 206 } 207 } 208 } 209 #endif /* SA_FW_TEST_INTERRUPT_REASSERT */ 210 } 211 212 /******************************************************************************/ 213 /*! \brief add a timer 214 * 215 * add a timer 216 * 217 * \param agRoot handles for this instance of SAS/SATA hardware 218 * \param pTimer the pointer to the timer being added 219 * \param timeout the timeout ticks from now 220 * \param pfnTimeout callback function when time is out 221 * \param Event the Event code passed to callback function 222 * \param pParm the pointer to parameter passed to callback function 223 * 224 * \return If the timer is added successfully 225 * - \e AGSA_RC_SUCCESS timer is added successfully 226 * - \e AGSA_RC_FAILURE cannot add new timer, run out of resource 227 */ 228 /*******************************************************************************/ 229 GLOBAL agsaTimerDesc_t *siTimerAdd( 230 agsaRoot_t *agRoot, 231 bit32 timeout, 232 agsaCallback_t pfnTimeout, 233 bit32 Event, 234 void * pParm 235 ) 236 { 237 agsaLLRoot_t *saRoot = (agsaLLRoot_t *)(agRoot->sdkData); 238 agsaTimerDesc_t *pTimer; 239 agsaTimerDesc_t *pValidTimer; 240 241 smTraceFuncEnter(hpDBG_VERY_LOUD, "Ta"); 242 /* (1) Acquire timer list lock */ 243 ossaSingleThreadedEnter(agRoot, LL_TIMER_LOCK); 244 245 /* (2) Get a free timer */ 246 pTimer = (agsaTimerDesc_t *) saLlistGetHead(&(saRoot->freeTimers)); 247 248 /* (3) If the timer is availble */ 249 if ( agNULL != pTimer ) 250 { 251 saLlistRemove(&(saRoot->freeTimers), &(pTimer->linkNode)); 252 253 /* (3.1) Setup timer */ 254 saLlinkInitialize(&(pTimer->linkNode)); 255 /*--------------------------------------** 256 ** the timeout shall greater than 0 ** 257 **--------------------------------------*/ 258 if ( 0 == timeout ) 259 { 260 timeout = timeout + 1; 261 } 262 pTimer->valid = agTRUE; 263 pTimer->timeoutTick = saRoot->timeTick + timeout; 264 pTimer->pfnTimeout = pfnTimeout; 265 pTimer->Event = Event; 266 pTimer->pParm = pParm; 267 268 /* (3.2) Add timer the timer to valid timer list */ 269 pValidTimer = (agsaTimerDesc_t *) saLlistGetHead(&(saRoot->validTimers)); 270 /* (3.3) for each timer in the valid timer list */ 271 while ( agNULL != pValidTimer ) 272 { 273 /* (3.3.1) If the timeoutTick is not wrapped around */ 274 if ( pTimer->timeoutTick > saRoot->timeTick ) 275 { 276 /* (3.3.1.1) If validTimer wrapped around */ 277 if ( pValidTimer->timeoutTick < saRoot->timeTick ) 278 { 279 saLlistInsert(&(saRoot->validTimers), &(pValidTimer->linkNode), &(pTimer->linkNode)); 280 break; 281 } 282 /* (3.3.1.2) If validTimer is not wrapped around */ 283 else 284 { 285 if ( pValidTimer->timeoutTick > pTimer->timeoutTick ) 286 { 287 saLlistInsert(&(saRoot->validTimers), &(pValidTimer->linkNode), &(pTimer->linkNode)); 288 break; 289 } 290 } 291 } 292 /* (3.3.2) If the timeoutTick is wrapped around */ 293 else 294 { 295 /* (3.3.2.1) If validTimer is wrapped around */ 296 if ( pValidTimer->timeoutTick < saRoot->timeTick ) 297 { 298 if ( pValidTimer->timeoutTick > pTimer->timeoutTick ) 299 { 300 saLlistInsert(&(saRoot->validTimers), &(pValidTimer->linkNode), &(pTimer->linkNode)); 301 break; 302 } 303 } 304 } 305 /* (3.3.3) Continue to the next valid timer */ 306 pValidTimer = (agsaTimerDesc_t *) saLlistGetNext(&(saRoot->validTimers), &(pValidTimer->linkNode)); 307 } 308 309 /* (3.4) No timers in the validtimer list is greater than this timer */ 310 if ( agNULL == pValidTimer ) 311 { 312 saLlistAdd(&(saRoot->validTimers), &(pTimer->linkNode)); 313 } 314 } 315 316 /* (4) Release timer list lock */ 317 ossaSingleThreadedLeave(agRoot, LL_TIMER_LOCK); 318 smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "Ta"); 319 320 return pTimer; 321 } 322 323 /******************************************************************************/ 324 /*! \brief remove a valid timer 325 * 326 * remove a timer 327 * 328 * \param agRoot handles for this instance of SAS/SATA hardware 329 * \param pTimer the timer to be removed 330 * 331 * \return -void- 332 */ 333 /*******************************************************************************/ 334 GLOBAL void siTimerRemove( 335 agsaRoot_t *agRoot, 336 agsaTimerDesc_t *pTimer 337 ) 338 { 339 agsaLLRoot_t *saRoot = (agsaLLRoot_t *)(agRoot->sdkData); 340 341 /* (1) Acquire timer list lock */ 342 smTraceFuncEnter(hpDBG_VERY_LOUD,"Tb"); 343 ossaSingleThreadedEnter(agRoot, LL_TIMER_LOCK); 344 345 /* (2) If the timer is still valid */ 346 if ( agTRUE == pTimer->valid ) 347 { 348 /* (2.1) remove from the valid timer list */ 349 saLlistRemove(&(saRoot->validTimers), &(pTimer->linkNode)); 350 /* (2.2) Invalid the timer */ 351 pTimer->valid = agFALSE; 352 /* (2.3) return the timer to the free timer list */ 353 saLlistAdd(&(saRoot->freeTimers), &(pTimer->linkNode)); 354 } 355 /* (3) Release timer list lock */ 356 ossaSingleThreadedLeave(agRoot, LL_TIMER_LOCK); 357 smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "Tb"); 358 359 return; 360 } 361 362 /******************************************************************************/ 363 /*! \brief remove all valid timer 364 * 365 * remove all timer 366 * 367 * \param agRoot handles for this instance of SAS/SATA hardware 368 * 369 * \return -void- 370 */ 371 /*******************************************************************************/ 372 GLOBAL void siTimerRemoveAll( 373 agsaRoot_t *agRoot 374 ) 375 { 376 agsaLLRoot_t *saRoot = (agsaLLRoot_t *)(agRoot->sdkData); 377 agsaTimerDesc_t *pTimer; 378 379 smTraceFuncEnter(hpDBG_VERY_LOUD,"Tc"); 380 381 /* (1) Acquire timer list lock */ 382 ossaSingleThreadedEnter(agRoot, LL_TIMER_LOCK); 383 384 /* (2) Get a valid timer */ 385 pTimer = (agsaTimerDesc_t *) saLlistGetHead(&(saRoot->validTimers)); 386 387 /* (3) If the timer is valid */ 388 while ( agNULL != pTimer ) 389 { 390 /* (3.1) remove from the valid timer list */ 391 saLlistRemove(&(saRoot->validTimers), &(pTimer->linkNode)); 392 393 /* (3.2) Invalid timer */ 394 pTimer->valid = agFALSE; 395 396 /* (3.3) return the timer to the free timer list */ 397 saLlistAdd(&(saRoot->freeTimers), &(pTimer->linkNode)); 398 399 /* (3.4) get next valid timer */ 400 pTimer = (agsaTimerDesc_t *) saLlistGetHead(&(saRoot->validTimers)); 401 } 402 403 /* (4) Release timer list lock */ 404 ossaSingleThreadedLeave(agRoot, LL_TIMER_LOCK); 405 406 smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "Tc"); 407 408 return; 409 } 410