xref: /freebsd/sys/dev/pms/RefTisa/sallsdk/spc/satimer.c (revision 8ddb146abcdf061be9f2c0db7e391697dafad85c)
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 __FBSDID("$FreeBSD$");
30 #include <dev/pms/config.h>
31 
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 */
36 
37 #ifdef SA_ENABLE_TRACE_FUNCTIONS
38 #ifdef siTraceFileID
39 #undef siTraceFileID
40 #endif
41 #define siTraceFileID 'P'
42 #endif
43 
44 /******************************************************************************/
45 /*! \brief TimerTick
46  *
47  *  TimerTick
48  *
49  *  \param agRoot handles for this instance of SAS/SATA hardware
50  *
51  *  \return -void-
52  */
53 /*******************************************************************************/
54 GLOBAL void saTimerTick(
55   agsaRoot_t  *agRoot
56   )
57 {
58   agsaLLRoot_t    *saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
59   agsaTimerDesc_t *pTimer;
60   bit32           Event;
61   void *          pParm;
62 
63   if(agNULL ==  saRoot)
64   {
65     SA_DBG1(("saTimerTick:agNULL ==  saRoot \n"));
66     return;
67   }
68 
69   /* (1) Acquire timer list lock */
70   ossaSingleThreadedEnter(agRoot, LL_TIMER_LOCK);
71 
72   /* (2) Find the timers are timeout */
73   pTimer = (agsaTimerDesc_t *) saLlistGetHead(&(saRoot->validTimers));
74   while ( agNULL != pTimer )
75   {
76     /* (2.1) Find the first timer is timeout */
77     if ( pTimer->timeoutTick == saRoot->timeTick )
78     {
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);
88 
89       /* (2.1.5) Timer Callback */
90       pTimer->pfnTimeout(agRoot, Event, pParm);
91 
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));
96     }
97     /* (2.2) the first timer is not timeout */
98     else
99     {
100       break;
101     }
102     pTimer = (agsaTimerDesc_t *) saLlistGetHead(&(saRoot->validTimers));
103   }
104 
105   /* (3) increment timeTick */
106   saRoot->timeTick ++;
107 
108   if( saRoot->ResetFailed )
109   {
110     SA_DBG1(("saTimerTick: siChipResetV saRoot->ResetFailed\n"));
111   }
112 
113 #ifdef SA_FW_TEST_BUNCH_STARTS
114   if (saRoot->BunchStarts_Enable &&
115       saRoot->BunchStarts_Pending)
116   {
117       SA_DBG3(("saTimerTick: mpiMsgProduceBunch\n"));
118       mpiMsgProduceBunch(  saRoot);
119   }
120 #endif /* SA_FW_TEST_BUNCH_STARTS */
121 
122 
123 #ifdef SA_FW_TEST_INTERRUPT_REASSERT
124 
125   if(1)
126   {
127     mpiOCQueue_t         *circularQ;
128     int i;
129     SA_DBG4(("saTimerTick:SA_FW_TEST_INTERRUPT_REASSERT\n"));
130     for ( i = 0; i < saRoot->QueueConfig.numOutboundQueues; i++ )
131     {
132       circularQ = &saRoot->outboundQueue[i];
133       OSSA_READ_LE_32(circularQ->agRoot, &circularQ->producerIdx, circularQ->piPointer, 0);
134       if(circularQ->producerIdx != circularQ->consumerIdx)
135       {
136         if( saRoot->OldCi[i] == circularQ->consumerIdx && saRoot->OldPi[i] >= circularQ->producerIdx)
137         {
138           agsaEchoCmd_t       payload;
139           payload.tag = 0xF0;
140           payload.payload[0]= 0x0;
141           if( ++saRoot->OldFlag[i] > 1 )
142           {
143             saRoot->CheckAll++;
144           }
145           SA_DBG1(("saTimerTick:Q %d (%d) PI 0x%03x CI 0x%03x (%d) CheckAll %d %d\n",i,
146             saRoot->OldFlag[i],
147             circularQ->producerIdx,
148             circularQ->consumerIdx,
149             (circularQ->producerIdx > circularQ->consumerIdx ? (circularQ->producerIdx - circularQ->consumerIdx) :   (circularQ->numElements -  circularQ->consumerIdx ) + circularQ->producerIdx),
150             saRoot->CheckAll,
151             saRoot->sysIntsActive ));
152 
153           if(smIS64bInt(agRoot))
154           {
155             SA_DBG1(("saTimerTick:CheckAll %d ODR 0x%08X%08X ODMR 0x%08X%08X our Int %x\n",
156               saRoot->CheckAll,
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)
162               ));
163           }
164           else
165           {
166             SA_DBG1(("saTimerTick:CheckAll %d ODR 0x%08X ODMR 0x%08X our Int %x\n",
167               saRoot->CheckAll,
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)
171               ));
172           }
173 
174 
175           if( saRoot->CheckAll > 1)
176           {
177             saEchoCommand(agRoot,agNULL, ((i << 16) & 0xFFFF0000 ), (void *)&payload);
178           }
179 
180         }
181         else
182         {
183           saRoot->OldFlag[i] = 0;
184         }
185 
186         saRoot->OldPi[i] = circularQ->producerIdx;
187         saRoot->OldCi[i] = circularQ->consumerIdx;
188 
189       }
190     }
191   }
192 #endif /* SA_FW_TEST_INTERRUPT_REASSERT */
193 
194   /* (4) Release timer list lock */
195   ossaSingleThreadedLeave(agRoot, LL_TIMER_LOCK);
196 #ifdef SA_FW_TEST_INTERRUPT_REASSERT
197   if(saRoot->CheckAll )
198   {
199     int a;
200     for(a=0; a < 32; a++ )
201     {
202       if (saRoot->interruptVecIndexBitMap[a] & (1 << a))
203       {
204         SA_DBG1(("saTimerTick DI %d\n",a));
205         saSystemInterruptsEnable  ( agRoot, a );
206 
207       }
208     }
209   }
210 #endif /* SA_FW_TEST_INTERRUPT_REASSERT */
211 }
212 
213 /******************************************************************************/
214 /*! \brief add a timer
215  *
216  *  add a timer
217  *
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
224  *
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
228  */
229 /*******************************************************************************/
230 GLOBAL agsaTimerDesc_t *siTimerAdd(
231   agsaRoot_t      *agRoot,
232   bit32           timeout,
233   agsaCallback_t  pfnTimeout,
234   bit32           Event,
235   void *          pParm
236   )
237 {
238   agsaLLRoot_t    *saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
239   agsaTimerDesc_t *pTimer;
240   agsaTimerDesc_t *pValidTimer;
241 
242   smTraceFuncEnter(hpDBG_VERY_LOUD, "Ta");
243   /* (1) Acquire timer list lock */
244   ossaSingleThreadedEnter(agRoot, LL_TIMER_LOCK);
245 
246   /* (2) Get a free timer */
247   pTimer = (agsaTimerDesc_t *) saLlistGetHead(&(saRoot->freeTimers));
248 
249   /* (3) If the timer is availble  */
250   if ( agNULL != pTimer )
251   {
252     saLlistRemove(&(saRoot->freeTimers), &(pTimer->linkNode));
253 
254     /* (3.1) Setup timer */
255     saLlinkInitialize(&(pTimer->linkNode));
256     /*--------------------------------------**
257     ** the timeout shall greater than 0 **
258     **--------------------------------------*/
259     if ( 0 == timeout )
260     {
261       timeout = timeout + 1;
262     }
263     pTimer->valid = agTRUE;
264     pTimer->timeoutTick = saRoot->timeTick + timeout;
265     pTimer->pfnTimeout = pfnTimeout;
266     pTimer->Event = Event;
267     pTimer->pParm = pParm;
268 
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 )
273     {
274       /* (3.3.1) If the timeoutTick is not wrapped around */
275       if ( pTimer->timeoutTick > saRoot->timeTick )
276       {
277         /* (3.3.1.1) If validTimer wrapped around */
278         if ( pValidTimer->timeoutTick < saRoot->timeTick )
279         {
280           saLlistInsert(&(saRoot->validTimers), &(pValidTimer->linkNode), &(pTimer->linkNode));
281           break;
282         }
283         /* (3.3.1.2) If validTimer is not wrapped around */
284         else
285         {
286           if ( pValidTimer->timeoutTick > pTimer->timeoutTick )
287           {
288             saLlistInsert(&(saRoot->validTimers), &(pValidTimer->linkNode), &(pTimer->linkNode));
289             break;
290           }
291         }
292       }
293       /* (3.3.2) If the timeoutTick is wrapped around */
294       else
295       {
296         /* (3.3.2.1) If validTimer is wrapped around */
297         if ( pValidTimer->timeoutTick < saRoot->timeTick )
298         {
299           if ( pValidTimer->timeoutTick > pTimer->timeoutTick )
300           {
301             saLlistInsert(&(saRoot->validTimers), &(pValidTimer->linkNode), &(pTimer->linkNode));
302             break;
303           }
304         }
305       }
306       /* (3.3.3) Continue to the next valid timer */
307       pValidTimer = (agsaTimerDesc_t *) saLlistGetNext(&(saRoot->validTimers), &(pValidTimer->linkNode));
308     }
309 
310     /* (3.4) No timers in the validtimer list is greater than this timer */
311     if ( agNULL == pValidTimer )
312     {
313       saLlistAdd(&(saRoot->validTimers), &(pTimer->linkNode));
314     }
315   }
316 
317   /* (4) Release timer list lock */
318   ossaSingleThreadedLeave(agRoot, LL_TIMER_LOCK);
319   smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "Ta");
320 
321   return pTimer;
322 }
323 
324 /******************************************************************************/
325 /*! \brief remove a valid timer
326  *
327  *  remove a timer
328  *
329  *  \param agRoot       handles for this instance of SAS/SATA hardware
330  *  \param pTimer       the timer to be removed
331  *
332  *  \return -void-
333  */
334 /*******************************************************************************/
335 GLOBAL void siTimerRemove(
336   agsaRoot_t      *agRoot,
337   agsaTimerDesc_t *pTimer
338   )
339 {
340   agsaLLRoot_t    *saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
341 
342   /* (1) Acquire timer list lock */
343   smTraceFuncEnter(hpDBG_VERY_LOUD,"Tb");
344   ossaSingleThreadedEnter(agRoot, LL_TIMER_LOCK);
345 
346   /* (2) If the timer is still valid */
347   if ( agTRUE == pTimer->valid )
348   {
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));
355   }
356   /* (3) Release timer list lock */
357   ossaSingleThreadedLeave(agRoot, LL_TIMER_LOCK);
358   smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "Tb");
359 
360   return;
361 }
362 
363 /******************************************************************************/
364 /*! \brief remove all valid timer
365  *
366  *  remove all timer
367  *
368  *  \param agRoot       handles for this instance of SAS/SATA hardware
369  *
370  *  \return -void-
371  */
372 /*******************************************************************************/
373 GLOBAL void siTimerRemoveAll(
374   agsaRoot_t      *agRoot
375   )
376 {
377   agsaLLRoot_t    *saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
378   agsaTimerDesc_t *pTimer;
379 
380   smTraceFuncEnter(hpDBG_VERY_LOUD,"Tc");
381 
382   /* (1) Acquire timer list lock */
383   ossaSingleThreadedEnter(agRoot, LL_TIMER_LOCK);
384 
385   /* (2) Get a valid timer */
386   pTimer = (agsaTimerDesc_t *) saLlistGetHead(&(saRoot->validTimers));
387 
388   /* (3) If the timer is valid  */
389   while ( agNULL != pTimer )
390   {
391     /* (3.1) remove from the valid timer list */
392     saLlistRemove(&(saRoot->validTimers), &(pTimer->linkNode));
393 
394     /* (3.2) Invalid timer */
395     pTimer->valid = agFALSE;
396 
397     /* (3.3) return the timer to the free timer list */
398     saLlistAdd(&(saRoot->freeTimers), &(pTimer->linkNode));
399 
400     /* (3.4) get next valid timer */
401     pTimer = (agsaTimerDesc_t *) saLlistGetHead(&(saRoot->validTimers));
402   }
403 
404   /* (4) Release timer list lock */
405   ossaSingleThreadedLeave(agRoot, LL_TIMER_LOCK);
406 
407   smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "Tc");
408 
409   return;
410 }
411