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 /*******************************************************************************/
saTimerTick(agsaRoot_t * agRoot)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 /*******************************************************************************/
siTimerAdd(agsaRoot_t * agRoot,bit32 timeout,agsaCallback_t pfnTimeout,bit32 Event,void * pParm)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 /*******************************************************************************/
siTimerRemove(agsaRoot_t * agRoot,agsaTimerDesc_t * pTimer)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 /*******************************************************************************/
siTimerRemoveAll(agsaRoot_t * agRoot)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