1285809Sscottl/******************************************************************************* 2285809Sscottl*Copyright (c) 2014 PMC-Sierra, Inc. All rights reserved. 3285809Sscottl* 4285809Sscottl*Redistribution and use in source and binary forms, with or without modification, are permitted provided 5285809Sscottl*that the following conditions are met: 6285809Sscottl*1. Redistributions of source code must retain the above copyright notice, this list of conditions and the 7285809Sscottl*following disclaimer. 8285809Sscottl*2. Redistributions in binary form must reproduce the above copyright notice, 9285809Sscottl*this list of conditions and the following disclaimer in the documentation and/or other materials provided 10285809Sscottl*with the distribution. 11285809Sscottl* 12285809Sscottl*THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED 13285809Sscottl*WARRANTIES,INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 14285809Sscottl*FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 15285809Sscottl*FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 16285809Sscottl*NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 17285809Sscottl*BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 18285809Sscottl*LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 19285809Sscottl*SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE 20285809Sscottl 21285809Sscottl********************************************************************************/ 22285809Sscottl/*******************************************************************************/ 23285809Sscottl/*! \file satimer.c 24285809Sscottl * \brief The file implements the timerTick function 25285809Sscottl * 26285809Sscottl */ 27285809Sscottl/******************************************************************************/ 28285809Sscottl#include <sys/cdefs.h> 29285809Sscottl__FBSDID("$FreeBSD$"); 30285809Sscottl#include <dev/pms/config.h> 31285809Sscottl 32285809Sscottl#include <dev/pms/RefTisa/sallsdk/spc/saglobal.h> 33285809Sscottl#ifdef SA_FW_TEST_BUNCH_STARTS 34285809Sscottlvoid mpiMsgProduceBunch( agsaLLRoot_t *saRoot); 35285809Sscottl#endif /* SA_FW_TEST_BUNCH_STARTS */ 36285809Sscottl 37285809Sscottl#ifdef SA_ENABLE_TRACE_FUNCTIONS 38285809Sscottl#ifdef siTraceFileID 39285809Sscottl#undef siTraceFileID 40285809Sscottl#endif 41285809Sscottl#define siTraceFileID 'P' 42285809Sscottl#endif 43285809Sscottl 44285809Sscottl/******************************************************************************/ 45285809Sscottl/*! \brief TimerTick 46285809Sscottl * 47285809Sscottl * TimerTick 48285809Sscottl * 49285809Sscottl * \param agRoot handles for this instance of SAS/SATA hardware 50285809Sscottl * 51285809Sscottl * \return -void- 52285809Sscottl */ 53285809Sscottl/*******************************************************************************/ 54285809SscottlGLOBAL void saTimerTick( 55285809Sscottl agsaRoot_t *agRoot 56285809Sscottl ) 57285809Sscottl{ 58285809Sscottl agsaLLRoot_t *saRoot = (agsaLLRoot_t *)(agRoot->sdkData); 59285809Sscottl agsaTimerDesc_t *pTimer; 60285809Sscottl bit32 Event; 61285809Sscottl void * pParm; 62285809Sscottl 63285809Sscottl if(agNULL == saRoot) 64285809Sscottl { 65285809Sscottl SA_DBG1(("saTimerTick:agNULL == saRoot \n")); 66285809Sscottl return; 67285809Sscottl } 68285809Sscottl 69285809Sscottl /* (1) Acquire timer list lock */ 70285809Sscottl ossaSingleThreadedEnter(agRoot, LL_TIMER_LOCK); 71285809Sscottl 72285809Sscottl /* (2) Find the timers are timeout */ 73285809Sscottl pTimer = (agsaTimerDesc_t *) saLlistGetHead(&(saRoot->validTimers)); 74285809Sscottl while ( agNULL != pTimer ) 75285809Sscottl { 76285809Sscottl /* (2.1) Find the first timer is timeout */ 77285809Sscottl if ( pTimer->timeoutTick == saRoot->timeTick ) 78285809Sscottl { 79285809Sscottl /* (2.1.1) remove the timer from valid timer list */ 80285809Sscottl saLlistRemove(&(saRoot->validTimers), &(pTimer->linkNode)); 81285809Sscottl /* (2.1.2) Invalid timer */ 82285809Sscottl pTimer->valid = agFALSE; 83285809Sscottl /* (2.1.3) Get timer event and param */ 84285809Sscottl Event = pTimer->Event; 85285809Sscottl pParm = pTimer->pParm; 86285809Sscottl /* (2.1.4) Release timer list lock */ 87285809Sscottl ossaSingleThreadedLeave(agRoot, LL_TIMER_LOCK); 88285809Sscottl 89285809Sscottl /* (2.1.5) Timer Callback */ 90285809Sscottl pTimer->pfnTimeout(agRoot, Event, pParm); 91285809Sscottl 92285809Sscottl /* (2.1.6) Acquire timer list lock again */ 93285809Sscottl ossaSingleThreadedEnter(agRoot, LL_TIMER_LOCK); 94285809Sscottl /* (2.1.7) return the timer to free timer list */ 95285809Sscottl saLlistAdd(&(saRoot->freeTimers), &(pTimer->linkNode)); 96285809Sscottl } 97285809Sscottl /* (2.2) the first timer is not timeout */ 98285809Sscottl else 99285809Sscottl { 100285809Sscottl break; 101285809Sscottl } 102285809Sscottl pTimer = (agsaTimerDesc_t *) saLlistGetHead(&(saRoot->validTimers)); 103285809Sscottl } 104285809Sscottl 105285809Sscottl /* (3) increment timeTick */ 106285809Sscottl saRoot->timeTick ++; 107285809Sscottl 108285809Sscottl if( saRoot->ResetFailed ) 109285809Sscottl { 110285809Sscottl SA_DBG1(("saTimerTick: siChipResetV saRoot->ResetFailed\n")); 111285809Sscottl } 112285809Sscottl 113285809Sscottl#ifdef SA_FW_TEST_BUNCH_STARTS 114285809Sscottl if (saRoot->BunchStarts_Enable && 115285809Sscottl saRoot->BunchStarts_Pending) 116285809Sscottl { 117285809Sscottl SA_DBG3(("saTimerTick: mpiMsgProduceBunch\n")); 118285809Sscottl mpiMsgProduceBunch( saRoot); 119285809Sscottl } 120285809Sscottl#endif /* SA_FW_TEST_BUNCH_STARTS */ 121285809Sscottl 122285809Sscottl 123285809Sscottl#ifdef SA_FW_TEST_INTERRUPT_REASSERT 124285809Sscottl 125285809Sscottl if(1) 126285809Sscottl { 127285809Sscottl mpiOCQueue_t *circularQ; 128285809Sscottl int i; 129285809Sscottl SA_DBG4(("saTimerTick:SA_FW_TEST_INTERRUPT_REASSERT\n")); 130285809Sscottl for ( i = 0; i < saRoot->QueueConfig.numOutboundQueues; i++ ) 131285809Sscottl { 132285809Sscottl circularQ = &saRoot->outboundQueue[i]; 133285809Sscottl OSSA_READ_LE_32(circularQ->agRoot, &circularQ->producerIdx, circularQ->piPointer, 0); 134285809Sscottl if(circularQ->producerIdx != circularQ->consumerIdx) 135285809Sscottl { 136285809Sscottl if( saRoot->OldCi[i] == circularQ->consumerIdx && saRoot->OldPi[i] >= circularQ->producerIdx) 137285809Sscottl { 138285809Sscottl agsaEchoCmd_t payload; 139285809Sscottl payload.tag = 0xF0; 140285809Sscottl payload.payload[0]= 0x0; 141285809Sscottl if( ++saRoot->OldFlag[i] > 1 ) 142285809Sscottl { 143285809Sscottl saRoot->CheckAll++; 144285809Sscottl } 145285809Sscottl SA_DBG1(("saTimerTick:Q %d (%d) PI 0x%03x CI 0x%03x (%d) CheckAll %d %d\n",i, 146285809Sscottl saRoot->OldFlag[i], 147285809Sscottl circularQ->producerIdx, 148285809Sscottl circularQ->consumerIdx, 149285809Sscottl (circularQ->producerIdx > circularQ->consumerIdx ? (circularQ->producerIdx - circularQ->consumerIdx) : (circularQ->numElements - circularQ->consumerIdx ) + circularQ->producerIdx), 150285809Sscottl saRoot->CheckAll, 151285809Sscottl saRoot->sysIntsActive )); 152285809Sscottl 153285809Sscottl if(smIS64bInt(agRoot)) 154285809Sscottl { 155285809Sscottl SA_DBG1(("saTimerTick:CheckAll %d ODR 0x%08X%08X ODMR 0x%08X%08X our Int %x\n", 156285809Sscottl saRoot->CheckAll, 157285809Sscottl ossaHwRegReadExt(agRoot, 0, V_Outbound_Doorbell_Set_RegisterU), 158285809Sscottl ossaHwRegReadExt(agRoot, 0, V_Outbound_Doorbell_Set_Register), 159285809Sscottl ossaHwRegReadExt(agRoot, 0, V_Outbound_Doorbell_Mask_Set_RegisterU), 160285809Sscottl ossaHwRegReadExt(agRoot, 0, V_Outbound_Doorbell_Mask_Set_Register), 161285809Sscottl saRoot->OurInterrupt(agRoot,i) 162285809Sscottl )); 163285809Sscottl } 164285809Sscottl else 165285809Sscottl { 166285809Sscottl SA_DBG1(("saTimerTick:CheckAll %d ODR 0x%08X ODMR 0x%08X our Int %x\n", 167285809Sscottl saRoot->CheckAll, 168285809Sscottl siHalRegReadExt(agRoot, GEN_MSGU_ODR, V_Outbound_Doorbell_Set_Register), 169285809Sscottl siHalRegReadExt(agRoot, GEN_MSGU_ODMR, V_Outbound_Doorbell_Mask_Set_Register), 170285809Sscottl saRoot->OurInterrupt(agRoot,i) 171285809Sscottl )); 172285809Sscottl } 173285809Sscottl 174285809Sscottl 175285809Sscottl if( saRoot->CheckAll > 1) 176285809Sscottl { 177285809Sscottl saEchoCommand(agRoot,agNULL, ((i << 16) & 0xFFFF0000 ), (void *)&payload); 178285809Sscottl } 179285809Sscottl 180285809Sscottl } 181285809Sscottl else 182285809Sscottl { 183285809Sscottl saRoot->OldFlag[i] = 0; 184285809Sscottl } 185285809Sscottl 186285809Sscottl saRoot->OldPi[i] = circularQ->producerIdx; 187285809Sscottl saRoot->OldCi[i] = circularQ->consumerIdx; 188285809Sscottl 189285809Sscottl } 190285809Sscottl } 191285809Sscottl } 192285809Sscottl#endif /* SA_FW_TEST_INTERRUPT_REASSERT */ 193285809Sscottl 194285809Sscottl /* (4) Release timer list lock */ 195285809Sscottl ossaSingleThreadedLeave(agRoot, LL_TIMER_LOCK); 196285809Sscottl#ifdef SA_FW_TEST_INTERRUPT_REASSERT 197285809Sscottl if(saRoot->CheckAll ) 198285809Sscottl { 199285809Sscottl int a; 200285809Sscottl for(a=0; a < 32; a++ ) 201285809Sscottl { 202285809Sscottl if (saRoot->interruptVecIndexBitMap[a] & (1 << a)) 203285809Sscottl { 204285809Sscottl SA_DBG1(("saTimerTick DI %d\n",a)); 205285809Sscottl saSystemInterruptsEnable ( agRoot, a ); 206285809Sscottl 207285809Sscottl } 208285809Sscottl } 209285809Sscottl } 210285809Sscottl#endif /* SA_FW_TEST_INTERRUPT_REASSERT */ 211285809Sscottl} 212285809Sscottl 213285809Sscottl/******************************************************************************/ 214285809Sscottl/*! \brief add a timer 215285809Sscottl * 216285809Sscottl * add a timer 217285809Sscottl * 218285809Sscottl * \param agRoot handles for this instance of SAS/SATA hardware 219285809Sscottl * \param pTimer the pointer to the timer being added 220285809Sscottl * \param timeout the timeout ticks from now 221285809Sscottl * \param pfnTimeout callback function when time is out 222285809Sscottl * \param Event the Event code passed to callback function 223285809Sscottl * \param pParm the pointer to parameter passed to callback function 224285809Sscottl * 225285809Sscottl * \return If the timer is added successfully 226285809Sscottl * - \e AGSA_RC_SUCCESS timer is added successfully 227285809Sscottl * - \e AGSA_RC_FAILURE cannot add new timer, run out of resource 228285809Sscottl */ 229285809Sscottl/*******************************************************************************/ 230285809SscottlGLOBAL agsaTimerDesc_t *siTimerAdd( 231285809Sscottl agsaRoot_t *agRoot, 232285809Sscottl bit32 timeout, 233285809Sscottl agsaCallback_t pfnTimeout, 234285809Sscottl bit32 Event, 235285809Sscottl void * pParm 236285809Sscottl ) 237285809Sscottl{ 238285809Sscottl agsaLLRoot_t *saRoot = (agsaLLRoot_t *)(agRoot->sdkData); 239285809Sscottl agsaTimerDesc_t *pTimer; 240285809Sscottl agsaTimerDesc_t *pValidTimer; 241285809Sscottl 242285809Sscottl smTraceFuncEnter(hpDBG_VERY_LOUD, "Ta"); 243285809Sscottl /* (1) Acquire timer list lock */ 244285809Sscottl ossaSingleThreadedEnter(agRoot, LL_TIMER_LOCK); 245285809Sscottl 246285809Sscottl /* (2) Get a free timer */ 247285809Sscottl pTimer = (agsaTimerDesc_t *) saLlistGetHead(&(saRoot->freeTimers)); 248285809Sscottl 249285809Sscottl /* (3) If the timer is availble */ 250285809Sscottl if ( agNULL != pTimer ) 251285809Sscottl { 252285809Sscottl saLlistRemove(&(saRoot->freeTimers), &(pTimer->linkNode)); 253285809Sscottl 254285809Sscottl /* (3.1) Setup timer */ 255285809Sscottl saLlinkInitialize(&(pTimer->linkNode)); 256285809Sscottl /*--------------------------------------** 257285809Sscottl ** the timeout shall greater than 0 ** 258285809Sscottl **--------------------------------------*/ 259285809Sscottl if ( 0 == timeout ) 260285809Sscottl { 261285809Sscottl timeout = timeout + 1; 262285809Sscottl } 263285809Sscottl pTimer->valid = agTRUE; 264285809Sscottl pTimer->timeoutTick = saRoot->timeTick + timeout; 265285809Sscottl pTimer->pfnTimeout = pfnTimeout; 266285809Sscottl pTimer->Event = Event; 267285809Sscottl pTimer->pParm = pParm; 268285809Sscottl 269285809Sscottl /* (3.2) Add timer the timer to valid timer list */ 270285809Sscottl pValidTimer = (agsaTimerDesc_t *) saLlistGetHead(&(saRoot->validTimers)); 271285809Sscottl /* (3.3) for each timer in the valid timer list */ 272285809Sscottl while ( agNULL != pValidTimer ) 273285809Sscottl { 274285809Sscottl /* (3.3.1) If the timeoutTick is not wrapped around */ 275285809Sscottl if ( pTimer->timeoutTick > saRoot->timeTick ) 276285809Sscottl { 277285809Sscottl /* (3.3.1.1) If validTimer wrapped around */ 278285809Sscottl if ( pValidTimer->timeoutTick < saRoot->timeTick ) 279285809Sscottl { 280285809Sscottl saLlistInsert(&(saRoot->validTimers), &(pValidTimer->linkNode), &(pTimer->linkNode)); 281285809Sscottl break; 282285809Sscottl } 283285809Sscottl /* (3.3.1.2) If validTimer is not wrapped around */ 284285809Sscottl else 285285809Sscottl { 286285809Sscottl if ( pValidTimer->timeoutTick > pTimer->timeoutTick ) 287285809Sscottl { 288285809Sscottl saLlistInsert(&(saRoot->validTimers), &(pValidTimer->linkNode), &(pTimer->linkNode)); 289285809Sscottl break; 290285809Sscottl } 291285809Sscottl } 292285809Sscottl } 293285809Sscottl /* (3.3.2) If the timeoutTick is wrapped around */ 294285809Sscottl else 295285809Sscottl { 296285809Sscottl /* (3.3.2.1) If validTimer is wrapped around */ 297285809Sscottl if ( pValidTimer->timeoutTick < saRoot->timeTick ) 298285809Sscottl { 299285809Sscottl if ( pValidTimer->timeoutTick > pTimer->timeoutTick ) 300285809Sscottl { 301285809Sscottl saLlistInsert(&(saRoot->validTimers), &(pValidTimer->linkNode), &(pTimer->linkNode)); 302285809Sscottl break; 303285809Sscottl } 304285809Sscottl } 305285809Sscottl } 306285809Sscottl /* (3.3.3) Continue to the next valid timer */ 307285809Sscottl pValidTimer = (agsaTimerDesc_t *) saLlistGetNext(&(saRoot->validTimers), &(pValidTimer->linkNode)); 308285809Sscottl } 309285809Sscottl 310285809Sscottl /* (3.4) No timers in the validtimer list is greater than this timer */ 311285809Sscottl if ( agNULL == pValidTimer ) 312285809Sscottl { 313285809Sscottl saLlistAdd(&(saRoot->validTimers), &(pTimer->linkNode)); 314285809Sscottl } 315285809Sscottl } 316285809Sscottl 317285809Sscottl /* (4) Release timer list lock */ 318285809Sscottl ossaSingleThreadedLeave(agRoot, LL_TIMER_LOCK); 319285809Sscottl smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "Ta"); 320285809Sscottl 321285809Sscottl return pTimer; 322285809Sscottl} 323285809Sscottl 324285809Sscottl/******************************************************************************/ 325285809Sscottl/*! \brief remove a valid timer 326285809Sscottl * 327285809Sscottl * remove a timer 328285809Sscottl * 329285809Sscottl * \param agRoot handles for this instance of SAS/SATA hardware 330285809Sscottl * \param pTimer the timer to be removed 331285809Sscottl * 332285809Sscottl * \return -void- 333285809Sscottl */ 334285809Sscottl/*******************************************************************************/ 335285809SscottlGLOBAL void siTimerRemove( 336285809Sscottl agsaRoot_t *agRoot, 337285809Sscottl agsaTimerDesc_t *pTimer 338285809Sscottl ) 339285809Sscottl{ 340285809Sscottl agsaLLRoot_t *saRoot = (agsaLLRoot_t *)(agRoot->sdkData); 341285809Sscottl 342285809Sscottl /* (1) Acquire timer list lock */ 343285809Sscottl smTraceFuncEnter(hpDBG_VERY_LOUD,"Tb"); 344285809Sscottl ossaSingleThreadedEnter(agRoot, LL_TIMER_LOCK); 345285809Sscottl 346285809Sscottl /* (2) If the timer is still valid */ 347285809Sscottl if ( agTRUE == pTimer->valid ) 348285809Sscottl { 349285809Sscottl /* (2.1) remove from the valid timer list */ 350285809Sscottl saLlistRemove(&(saRoot->validTimers), &(pTimer->linkNode)); 351285809Sscottl /* (2.2) Invalid the timer */ 352285809Sscottl pTimer->valid = agFALSE; 353285809Sscottl /* (2.3) return the timer to the free timer list */ 354285809Sscottl saLlistAdd(&(saRoot->freeTimers), &(pTimer->linkNode)); 355285809Sscottl } 356285809Sscottl /* (3) Release timer list lock */ 357285809Sscottl ossaSingleThreadedLeave(agRoot, LL_TIMER_LOCK); 358285809Sscottl smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "Tb"); 359285809Sscottl 360285809Sscottl return; 361285809Sscottl} 362285809Sscottl 363285809Sscottl/******************************************************************************/ 364285809Sscottl/*! \brief remove all valid timer 365285809Sscottl * 366285809Sscottl * remove all timer 367285809Sscottl * 368285809Sscottl * \param agRoot handles for this instance of SAS/SATA hardware 369285809Sscottl * 370285809Sscottl * \return -void- 371285809Sscottl */ 372285809Sscottl/*******************************************************************************/ 373285809SscottlGLOBAL void siTimerRemoveAll( 374285809Sscottl agsaRoot_t *agRoot 375285809Sscottl ) 376285809Sscottl{ 377285809Sscottl agsaLLRoot_t *saRoot = (agsaLLRoot_t *)(agRoot->sdkData); 378285809Sscottl agsaTimerDesc_t *pTimer; 379285809Sscottl 380285809Sscottl smTraceFuncEnter(hpDBG_VERY_LOUD,"Tc"); 381285809Sscottl 382285809Sscottl /* (1) Acquire timer list lock */ 383285809Sscottl ossaSingleThreadedEnter(agRoot, LL_TIMER_LOCK); 384285809Sscottl 385285809Sscottl /* (2) Get a valid timer */ 386285809Sscottl pTimer = (agsaTimerDesc_t *) saLlistGetHead(&(saRoot->validTimers)); 387285809Sscottl 388285809Sscottl /* (3) If the timer is valid */ 389285809Sscottl while ( agNULL != pTimer ) 390285809Sscottl { 391285809Sscottl /* (3.1) remove from the valid timer list */ 392285809Sscottl saLlistRemove(&(saRoot->validTimers), &(pTimer->linkNode)); 393285809Sscottl 394285809Sscottl /* (3.2) Invalid timer */ 395285809Sscottl pTimer->valid = agFALSE; 396285809Sscottl 397285809Sscottl /* (3.3) return the timer to the free timer list */ 398285809Sscottl saLlistAdd(&(saRoot->freeTimers), &(pTimer->linkNode)); 399285809Sscottl 400285809Sscottl /* (3.4) get next valid timer */ 401285809Sscottl pTimer = (agsaTimerDesc_t *) saLlistGetHead(&(saRoot->validTimers)); 402285809Sscottl } 403285809Sscottl 404285809Sscottl /* (4) Release timer list lock */ 405285809Sscottl ossaSingleThreadedLeave(agRoot, LL_TIMER_LOCK); 406285809Sscottl 407285809Sscottl smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "Tc"); 408285809Sscottl 409285809Sscottl return; 410285809Sscottl} 411