xref: /freebsd/sys/dev/pms/RefTisa/sallsdk/spc/satimer.c (revision f126890ac5386406dadf7c4cfa9566cbb56537c5)
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