1 /*******************************************************************************
2 *Copyright (c) 2014 PMC-Sierra, Inc. All rights reserved.
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
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.
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
21 ********************************************************************************/
22 /*******************************************************************************/
24 * \brief The file implements the timerTick function
27 /******************************************************************************/
28 #include <sys/cdefs.h>
29 __FBSDID("$FreeBSD$");
30 #include <dev/pms/config.h>
32 #include <dev/pms/RefTisa/sallsdk/spc/saglobal.h>
33 #ifdef SA_FW_TEST_BUNCH_STARTS
34 void mpiMsgProduceBunch( agsaLLRoot_t *saRoot);
35 #endif /* SA_FW_TEST_BUNCH_STARTS */
37 #ifdef SA_ENABLE_TRACE_FUNCTIONS
41 #define siTraceFileID 'P'
44 /******************************************************************************/
49 * \param agRoot handles for this instance of SAS/SATA hardware
53 /*******************************************************************************/
54 GLOBAL void saTimerTick(
58 agsaLLRoot_t *saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
59 agsaTimerDesc_t *pTimer;
65 SA_DBG1(("saTimerTick:agNULL == saRoot \n"));
69 /* (1) Acquire timer list lock */
70 ossaSingleThreadedEnter(agRoot, LL_TIMER_LOCK);
72 /* (2) Find the timers are timeout */
73 pTimer = (agsaTimerDesc_t *) saLlistGetHead(&(saRoot->validTimers));
74 while ( agNULL != pTimer )
76 /* (2.1) Find the first timer is timeout */
77 if ( pTimer->timeoutTick == saRoot->timeTick )
79 /* (2.1.1) remove the timer from valid timer list */
80 saLlistRemove(&(saRoot->validTimers), &(pTimer->linkNode));
81 /* (2.1.2) Invalid timer */
82 pTimer->valid = agFALSE;
83 /* (2.1.3) Get timer event and param */
84 Event = pTimer->Event;
85 pParm = pTimer->pParm;
86 /* (2.1.4) Release timer list lock */
87 ossaSingleThreadedLeave(agRoot, LL_TIMER_LOCK);
89 /* (2.1.5) Timer Callback */
90 pTimer->pfnTimeout(agRoot, Event, pParm);
92 /* (2.1.6) Acquire timer list lock again */
93 ossaSingleThreadedEnter(agRoot, LL_TIMER_LOCK);
94 /* (2.1.7) return the timer to free timer list */
95 saLlistAdd(&(saRoot->freeTimers), &(pTimer->linkNode));
97 /* (2.2) the first timer is not timeout */
102 pTimer = (agsaTimerDesc_t *) saLlistGetHead(&(saRoot->validTimers));
105 /* (3) increment timeTick */
108 if( saRoot->ResetFailed )
110 SA_DBG1(("saTimerTick: siChipResetV saRoot->ResetFailed\n"));
113 #ifdef SA_FW_TEST_BUNCH_STARTS
114 if (saRoot->BunchStarts_Enable &&
115 saRoot->BunchStarts_Pending)
117 SA_DBG3(("saTimerTick: mpiMsgProduceBunch\n"));
118 mpiMsgProduceBunch( saRoot);
120 #endif /* SA_FW_TEST_BUNCH_STARTS */
123 #ifdef SA_FW_TEST_INTERRUPT_REASSERT
127 mpiOCQueue_t *circularQ;
129 SA_DBG4(("saTimerTick:SA_FW_TEST_INTERRUPT_REASSERT\n"));
130 for ( i = 0; i < saRoot->QueueConfig.numOutboundQueues; i++ )
132 circularQ = &saRoot->outboundQueue[i];
133 OSSA_READ_LE_32(circularQ->agRoot, &circularQ->producerIdx, circularQ->piPointer, 0);
134 if(circularQ->producerIdx != circularQ->consumerIdx)
136 if( saRoot->OldCi[i] == circularQ->consumerIdx && saRoot->OldPi[i] >= circularQ->producerIdx)
138 agsaEchoCmd_t payload;
140 payload.payload[0]= 0x0;
141 if( ++saRoot->OldFlag[i] > 1 )
145 SA_DBG1(("saTimerTick:Q %d (%d) PI 0x%03x CI 0x%03x (%d) CheckAll %d %d\n",i,
147 circularQ->producerIdx,
148 circularQ->consumerIdx,
149 (circularQ->producerIdx > circularQ->consumerIdx ? (circularQ->producerIdx - circularQ->consumerIdx) : (circularQ->numElements - circularQ->consumerIdx ) + circularQ->producerIdx),
151 saRoot->sysIntsActive ));
153 if(smIS64bInt(agRoot))
155 SA_DBG1(("saTimerTick:CheckAll %d ODR 0x%08X%08X ODMR 0x%08X%08X our Int %x\n",
157 ossaHwRegReadExt(agRoot, 0, V_Outbound_Doorbell_Set_RegisterU),
158 ossaHwRegReadExt(agRoot, 0, V_Outbound_Doorbell_Set_Register),
159 ossaHwRegReadExt(agRoot, 0, V_Outbound_Doorbell_Mask_Set_RegisterU),
160 ossaHwRegReadExt(agRoot, 0, V_Outbound_Doorbell_Mask_Set_Register),
161 saRoot->OurInterrupt(agRoot,i)
166 SA_DBG1(("saTimerTick:CheckAll %d ODR 0x%08X ODMR 0x%08X our Int %x\n",
168 siHalRegReadExt(agRoot, GEN_MSGU_ODR, V_Outbound_Doorbell_Set_Register),
169 siHalRegReadExt(agRoot, GEN_MSGU_ODMR, V_Outbound_Doorbell_Mask_Set_Register),
170 saRoot->OurInterrupt(agRoot,i)
175 if( saRoot->CheckAll > 1)
177 saEchoCommand(agRoot,agNULL, ((i << 16) & 0xFFFF0000 ), (void *)&payload);
183 saRoot->OldFlag[i] = 0;
186 saRoot->OldPi[i] = circularQ->producerIdx;
187 saRoot->OldCi[i] = circularQ->consumerIdx;
192 #endif /* SA_FW_TEST_INTERRUPT_REASSERT */
194 /* (4) Release timer list lock */
195 ossaSingleThreadedLeave(agRoot, LL_TIMER_LOCK);
196 #ifdef SA_FW_TEST_INTERRUPT_REASSERT
197 if(saRoot->CheckAll )
200 for(a=0; a < 32; a++ )
202 if (saRoot->interruptVecIndexBitMap[a] & (1 << a))
204 SA_DBG1(("saTimerTick DI %d\n",a));
205 saSystemInterruptsEnable ( agRoot, a );
210 #endif /* SA_FW_TEST_INTERRUPT_REASSERT */
213 /******************************************************************************/
214 /*! \brief add a timer
218 * \param agRoot handles for this instance of SAS/SATA hardware
219 * \param pTimer the pointer to the timer being added
220 * \param timeout the timeout ticks from now
221 * \param pfnTimeout callback function when time is out
222 * \param Event the Event code passed to callback function
223 * \param pParm the pointer to parameter passed to callback function
225 * \return If the timer is added successfully
226 * - \e AGSA_RC_SUCCESS timer is added successfully
227 * - \e AGSA_RC_FAILURE cannot add new timer, run out of resource
229 /*******************************************************************************/
230 GLOBAL agsaTimerDesc_t *siTimerAdd(
233 agsaCallback_t pfnTimeout,
238 agsaLLRoot_t *saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
239 agsaTimerDesc_t *pTimer;
240 agsaTimerDesc_t *pValidTimer;
242 smTraceFuncEnter(hpDBG_VERY_LOUD, "Ta");
243 /* (1) Acquire timer list lock */
244 ossaSingleThreadedEnter(agRoot, LL_TIMER_LOCK);
246 /* (2) Get a free timer */
247 pTimer = (agsaTimerDesc_t *) saLlistGetHead(&(saRoot->freeTimers));
249 /* (3) If the timer is availble */
250 if ( agNULL != pTimer )
252 saLlistRemove(&(saRoot->freeTimers), &(pTimer->linkNode));
254 /* (3.1) Setup timer */
255 saLlinkInitialize(&(pTimer->linkNode));
256 /*--------------------------------------**
257 ** the timeout shall greater than 0 **
258 **--------------------------------------*/
261 timeout = timeout + 1;
263 pTimer->valid = agTRUE;
264 pTimer->timeoutTick = saRoot->timeTick + timeout;
265 pTimer->pfnTimeout = pfnTimeout;
266 pTimer->Event = Event;
267 pTimer->pParm = pParm;
269 /* (3.2) Add timer the timer to valid timer list */
270 pValidTimer = (agsaTimerDesc_t *) saLlistGetHead(&(saRoot->validTimers));
271 /* (3.3) for each timer in the valid timer list */
272 while ( agNULL != pValidTimer )
274 /* (3.3.1) If the timeoutTick is not wrapped around */
275 if ( pTimer->timeoutTick > saRoot->timeTick )
277 /* (3.3.1.1) If validTimer wrapped around */
278 if ( pValidTimer->timeoutTick < saRoot->timeTick )
280 saLlistInsert(&(saRoot->validTimers), &(pValidTimer->linkNode), &(pTimer->linkNode));
283 /* (3.3.1.2) If validTimer is not wrapped around */
286 if ( pValidTimer->timeoutTick > pTimer->timeoutTick )
288 saLlistInsert(&(saRoot->validTimers), &(pValidTimer->linkNode), &(pTimer->linkNode));
293 /* (3.3.2) If the timeoutTick is wrapped around */
296 /* (3.3.2.1) If validTimer is wrapped around */
297 if ( pValidTimer->timeoutTick < saRoot->timeTick )
299 if ( pValidTimer->timeoutTick > pTimer->timeoutTick )
301 saLlistInsert(&(saRoot->validTimers), &(pValidTimer->linkNode), &(pTimer->linkNode));
306 /* (3.3.3) Continue to the next valid timer */
307 pValidTimer = (agsaTimerDesc_t *) saLlistGetNext(&(saRoot->validTimers), &(pValidTimer->linkNode));
310 /* (3.4) No timers in the validtimer list is greater than this timer */
311 if ( agNULL == pValidTimer )
313 saLlistAdd(&(saRoot->validTimers), &(pTimer->linkNode));
317 /* (4) Release timer list lock */
318 ossaSingleThreadedLeave(agRoot, LL_TIMER_LOCK);
319 smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "Ta");
324 /******************************************************************************/
325 /*! \brief remove a valid timer
329 * \param agRoot handles for this instance of SAS/SATA hardware
330 * \param pTimer the timer to be removed
334 /*******************************************************************************/
335 GLOBAL void siTimerRemove(
337 agsaTimerDesc_t *pTimer
340 agsaLLRoot_t *saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
342 /* (1) Acquire timer list lock */
343 smTraceFuncEnter(hpDBG_VERY_LOUD,"Tb");
344 ossaSingleThreadedEnter(agRoot, LL_TIMER_LOCK);
346 /* (2) If the timer is still valid */
347 if ( agTRUE == pTimer->valid )
349 /* (2.1) remove from the valid timer list */
350 saLlistRemove(&(saRoot->validTimers), &(pTimer->linkNode));
351 /* (2.2) Invalid the timer */
352 pTimer->valid = agFALSE;
353 /* (2.3) return the timer to the free timer list */
354 saLlistAdd(&(saRoot->freeTimers), &(pTimer->linkNode));
356 /* (3) Release timer list lock */
357 ossaSingleThreadedLeave(agRoot, LL_TIMER_LOCK);
358 smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "Tb");
363 /******************************************************************************/
364 /*! \brief remove all valid timer
368 * \param agRoot handles for this instance of SAS/SATA hardware
372 /*******************************************************************************/
373 GLOBAL void siTimerRemoveAll(
377 agsaLLRoot_t *saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
378 agsaTimerDesc_t *pTimer;
380 smTraceFuncEnter(hpDBG_VERY_LOUD,"Tc");
382 /* (1) Acquire timer list lock */
383 ossaSingleThreadedEnter(agRoot, LL_TIMER_LOCK);
385 /* (2) Get a valid timer */
386 pTimer = (agsaTimerDesc_t *) saLlistGetHead(&(saRoot->validTimers));
388 /* (3) If the timer is valid */
389 while ( agNULL != pTimer )
391 /* (3.1) remove from the valid timer list */
392 saLlistRemove(&(saRoot->validTimers), &(pTimer->linkNode));
394 /* (3.2) Invalid timer */
395 pTimer->valid = agFALSE;
397 /* (3.3) return the timer to the free timer list */
398 saLlistAdd(&(saRoot->freeTimers), &(pTimer->linkNode));
400 /* (3.4) get next valid timer */
401 pTimer = (agsaTimerDesc_t *) saLlistGetHead(&(saRoot->validTimers));
404 /* (4) Release timer list lock */
405 ossaSingleThreadedLeave(agRoot, LL_TIMER_LOCK);
407 smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "Tc");