]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - sys/dev/pms/RefTisa/sallsdk/spc/satimer.c
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / sys / dev / pms / RefTisa / sallsdk / spc / satimer.c
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 }