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 }
Cache object: 6a3a5b5b1912caf1d3b1a2a7bf91e853
|