Commit | Line | Data |
---|---|---|
6fa3eb70 S |
1 | /* |
2 | ** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/cnm_timer.c#1 $ | |
3 | */ | |
4 | ||
5 | /*! \file "cnm_timer.c" | |
6 | \brief | |
7 | ||
8 | */ | |
9 | ||
10 | ||
11 | ||
12 | /* | |
13 | ** $Log: cnm_timer.c $ | |
14 | * | |
15 | * 12 13 2011 cm.chang | |
16 | * [WCXRP00001136] [All Wi-Fi][Driver] Add wake lock for pending timer | |
17 | * Add wake lock if timer timeout value is smaller than 5 seconds | |
18 | * | |
19 | * 02 24 2011 cp.wu | |
20 | * [WCXRP00000490] [MT6620 Wi-Fi][Driver][Win32] modify kalMsleep() implementation because NdisMSleep() won't sleep long enough for specified interval such as 500ms | |
21 | * modify cnm_timer and hem_mbox APIs to be thread safe to ease invoking restrictions | |
22 | * | |
23 | * 07 08 2010 cp.wu | |
24 | * | |
25 | * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. | |
26 | * | |
27 | * 06 08 2010 cp.wu | |
28 | * [WPD00003833][MT6620 and MT5931] Driver migration | |
29 | * cnm_timer has been migrated. | |
30 | * | |
31 | * 05 28 2010 cm.chang | |
32 | * [BORA00000018]Integrate WIFI part into BORA for the 1st time | |
33 | * Support sleep notification to host | |
34 | * | |
35 | * 05 19 2010 cm.chang | |
36 | * [BORA00000018]Integrate WIFI part into BORA for the 1st time | |
37 | * Add some checking assertions | |
38 | * | |
39 | * 04 24 2010 cm.chang | |
40 | * [BORA00000018]Integrate WIFI part into BORA for the 1st time | |
41 | * Return timer token back to COS when entering wait off state | |
42 | * | |
43 | * 01 11 2010 cm.chang | |
44 | * [BORA00000018]Integrate WIFI part into BORA for the 1st time | |
45 | * Remove compiling warning | |
46 | * | |
47 | * 01 08 2010 cm.chang | |
48 | * [BORA00000018]Integrate WIFI part into BORA for the 1st time | |
49 | * Support longer timeout interval to 45 days from 65secu1rwduu`wvpghlqg|fh+fmdkb | |
50 | * | |
51 | * 01 06 2010 cm.chang | |
52 | * [BORA00000018]Integrate WIFI part into BORA for the 1st time | |
53 | * Fix system time is 32KHz instead of 1ms | |
54 | * | |
55 | * 01 04 2010 tehuang.liu | |
56 | * [BORA00000018]Integrate WIFI part into BORA for the 1st time | |
57 | * For working out the first connection Chariot-verified version | |
58 | * | |
59 | * Dec 3 2009 mtk01461 | |
60 | * [BORA00000018] Integrate WIFI part into BORA for the 1st time | |
61 | * Place rRootTimer.rNextExpiredSysTime = rExpiredSysTime; before set timer | |
62 | * | |
63 | * Oct 30 2009 mtk01104 | |
64 | * [BORA00000018] Integrate WIFI part into BORA for the 1st time | |
65 | * In cnmTimerInitialize(), just stop timer if it was already created. | |
66 | * | |
67 | * Oct 30 2009 mtk01461 | |
68 | * [BORA00000018] Integrate WIFI part into BORA for the 1st time | |
69 | * Move the external reference for Lint to precomp.h | |
70 | * | |
71 | * Oct 30 2009 mtk01461 | |
72 | * [BORA00000018] Integrate WIFI part into BORA for the 1st time | |
73 | * Fix lint warning | |
74 | * | |
75 | * Oct 28 2009 mtk01104 | |
76 | * [BORA00000018] Integrate WIFI part into BORA for the 1st time | |
77 | * | |
78 | ** | |
79 | */ | |
80 | ||
81 | /******************************************************************************* | |
82 | * C O M P I L E R F L A G S | |
83 | ******************************************************************************** | |
84 | */ | |
85 | ||
86 | /******************************************************************************* | |
87 | * E X T E R N A L R E F E R E N C E S | |
88 | ******************************************************************************** | |
89 | */ | |
90 | #include "precomp.h" | |
91 | ||
92 | /******************************************************************************* | |
93 | * C O N S T A N T S | |
94 | ******************************************************************************** | |
95 | */ | |
96 | ||
97 | /******************************************************************************* | |
98 | * D A T A T Y P E S | |
99 | ******************************************************************************** | |
100 | */ | |
101 | ||
102 | /******************************************************************************* | |
103 | * P U B L I C D A T A | |
104 | ******************************************************************************** | |
105 | */ | |
106 | ||
107 | /******************************************************************************* | |
108 | * P R I V A T E D A T A | |
109 | ******************************************************************************** | |
110 | */ | |
111 | ||
112 | /******************************************************************************* | |
113 | * M A C R O S | |
114 | ******************************************************************************** | |
115 | */ | |
116 | ||
117 | /******************************************************************************* | |
118 | * F U N C T I O N D E C L A R A T I O N S | |
119 | ******************************************************************************** | |
120 | */ | |
121 | ||
122 | /******************************************************************************* | |
123 | * F U N C T I O N S | |
124 | ******************************************************************************** | |
125 | */ | |
126 | ||
127 | /*----------------------------------------------------------------------------*/ | |
128 | /*! | |
129 | * \brief This routine is called to set the time to do the time out check. | |
130 | * | |
131 | * \param[in] rTimeout Time out interval from current time. | |
132 | * | |
133 | * \retval TRUE Success. | |
134 | * | |
135 | */ | |
136 | /*----------------------------------------------------------------------------*/ | |
137 | static BOOLEAN cnmTimerSetTimer(IN P_ADAPTER_T prAdapter, IN OS_SYSTIME rTimeout) | |
138 | { | |
139 | P_ROOT_TIMER prRootTimer; | |
140 | BOOLEAN fgNeedWakeLock; | |
141 | ||
142 | ASSERT(prAdapter); | |
143 | ||
144 | prRootTimer = &prAdapter->rRootTimer; | |
145 | ||
146 | kalSetTimer(prAdapter->prGlueInfo, rTimeout); | |
147 | ||
148 | if (rTimeout <= SEC_TO_SYSTIME(WAKE_LOCK_MAX_TIME)) { | |
149 | fgNeedWakeLock = TRUE; | |
150 | ||
151 | if (!prRootTimer->fgWakeLocked) { | |
152 | KAL_WAKE_LOCK(prAdapter, &prRootTimer->rWakeLock); | |
153 | prRootTimer->fgWakeLocked = TRUE; | |
154 | } | |
155 | } else { | |
156 | fgNeedWakeLock = FALSE; | |
157 | } | |
158 | ||
159 | return fgNeedWakeLock; | |
160 | } | |
161 | ||
162 | /*----------------------------------------------------------------------------*/ | |
163 | /*! | |
164 | * \brief This routines is called to initialize a root timer. | |
165 | * | |
166 | * \param[in] prAdapter | |
167 | * | |
168 | * \return (none) | |
169 | */ | |
170 | /*----------------------------------------------------------------------------*/ | |
171 | VOID cnmTimerInitialize(IN P_ADAPTER_T prAdapter) | |
172 | { | |
173 | P_ROOT_TIMER prRootTimer; | |
174 | KAL_SPIN_LOCK_DECLARATION(); | |
175 | ||
176 | ASSERT(prAdapter); | |
177 | ||
178 | prRootTimer = &prAdapter->rRootTimer; | |
179 | ||
180 | /* Note: glue layer have configured timer */ | |
181 | ||
182 | KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER); | |
183 | LINK_INITIALIZE(&prRootTimer->rLinkHead); | |
184 | KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER); | |
185 | ||
186 | KAL_WAKE_LOCK_INIT(prAdapter, &prRootTimer->rWakeLock, "WLAN Timer"); | |
187 | prRootTimer->fgWakeLocked = FALSE; | |
188 | return; | |
189 | } | |
190 | ||
191 | /*----------------------------------------------------------------------------*/ | |
192 | /*! | |
193 | * \brief This routines is called to destroy a root timer. | |
194 | * When WIFI is off, the token shall be returned back to system. | |
195 | * | |
196 | * \param[in] | |
197 | * | |
198 | * \return (none) | |
199 | */ | |
200 | /*----------------------------------------------------------------------------*/ | |
201 | VOID cnmTimerDestroy(IN P_ADAPTER_T prAdapter) | |
202 | { | |
203 | P_ROOT_TIMER prRootTimer; | |
204 | KAL_SPIN_LOCK_DECLARATION(); | |
205 | ||
206 | ASSERT(prAdapter); | |
207 | ||
208 | prRootTimer = &prAdapter->rRootTimer; | |
209 | ||
210 | if (prRootTimer->fgWakeLocked) { | |
211 | KAL_WAKE_UNLOCK(prAdapter, &prRootTimer->rWakeLock); | |
212 | prRootTimer->fgWakeLocked = FALSE; | |
213 | } | |
214 | KAL_WAKE_LOCK_DESTROY(prAdapter, &prRootTimer->rWakeLock); | |
215 | ||
216 | KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER); | |
217 | LINK_INITIALIZE(&prRootTimer->rLinkHead); | |
218 | KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER); | |
219 | ||
220 | /* Note: glue layer will be responsible for timer destruction */ | |
221 | ||
222 | return; | |
223 | } | |
224 | ||
225 | /*----------------------------------------------------------------------------*/ | |
226 | /*! | |
227 | * \brief This routines is called to initialize a timer. | |
228 | * | |
229 | * \param[in] prTimer Pointer to a timer structure. | |
230 | * \param[in] pfnFunc Pointer to the call back function. | |
231 | * \param[in] u4Data Parameter for call back function. | |
232 | * | |
233 | * \return (none) | |
234 | */ | |
235 | /*----------------------------------------------------------------------------*/ | |
236 | VOID | |
237 | cnmTimerInitTimer(IN P_ADAPTER_T prAdapter, | |
238 | IN P_TIMER_T prTimer, IN PFN_MGMT_TIMEOUT_FUNC pfFunc, IN UINT_32 u4Data) | |
239 | { | |
240 | ASSERT(prAdapter); | |
241 | ||
242 | ASSERT(prTimer); | |
243 | ||
244 | #if DBG | |
245 | /* Note: NULL function pointer is permitted for HEM POWER */ | |
246 | if (pfFunc == NULL) { | |
247 | DBGLOG(CNM, WARN, ("Init timer with NULL callback function!\n")); | |
248 | } | |
249 | #endif | |
250 | ||
251 | #if DBG | |
252 | ASSERT(prAdapter->rRootTimer.rLinkHead.prNext); | |
253 | { | |
254 | P_LINK_T prTimerList; | |
255 | P_LINK_ENTRY_T prLinkEntry; | |
256 | P_TIMER_T prPendingTimer; | |
257 | ||
258 | prTimerList = &(prAdapter->rRootTimer.rLinkHead); | |
259 | ||
260 | LINK_FOR_EACH(prLinkEntry, prTimerList) { | |
261 | prPendingTimer = LINK_ENTRY(prLinkEntry, TIMER_T, rLinkEntry); | |
262 | ASSERT(prPendingTimer); | |
263 | ASSERT(prPendingTimer != prTimer); | |
264 | } | |
265 | } | |
266 | #endif | |
267 | ||
268 | LINK_ENTRY_INITIALIZE(&prTimer->rLinkEntry); | |
269 | ||
270 | prTimer->pfMgmtTimeOutFunc = pfFunc; | |
271 | prTimer->u4Data = u4Data; | |
272 | ||
273 | return; | |
274 | } | |
275 | ||
276 | ||
277 | /*----------------------------------------------------------------------------*/ | |
278 | /*! | |
279 | * \brief This routines is called to stop a timer. | |
280 | * | |
281 | * \param[in] prTimer Pointer to a timer structure. | |
282 | * | |
283 | * \return (none) | |
284 | */ | |
285 | /*----------------------------------------------------------------------------*/ | |
286 | static VOID | |
287 | cnmTimerStopTimer_impl(IN P_ADAPTER_T prAdapter, IN P_TIMER_T prTimer, IN BOOLEAN fgAcquireSpinlock) | |
288 | { | |
289 | P_ROOT_TIMER prRootTimer; | |
290 | KAL_SPIN_LOCK_DECLARATION(); | |
291 | ||
292 | ASSERT(prAdapter); | |
293 | ASSERT(prTimer); | |
294 | ||
295 | prRootTimer = &prAdapter->rRootTimer; | |
296 | ||
297 | if (fgAcquireSpinlock) { | |
298 | KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER); | |
299 | } | |
300 | ||
301 | if (timerPendingTimer(prTimer)) { | |
302 | LINK_REMOVE_KNOWN_ENTRY(&prRootTimer->rLinkHead, &prTimer->rLinkEntry); | |
303 | ||
304 | /* Reduce dummy timeout for power saving, especially HIF activity. | |
305 | * If two or more timers exist and being removed timer is smallest, | |
306 | * this dummy timeout will still happen, but it is OK. | |
307 | */ | |
308 | if (LINK_IS_EMPTY(&prRootTimer->rLinkHead)) { | |
309 | kalCancelTimer(prAdapter->prGlueInfo); | |
310 | ||
311 | if (fgAcquireSpinlock && prRootTimer->fgWakeLocked) { | |
312 | KAL_WAKE_UNLOCK(prAdapter, &prRootTimer->rWakeLock); | |
313 | prRootTimer->fgWakeLocked = FALSE; | |
314 | } | |
315 | } | |
316 | } | |
317 | ||
318 | if (fgAcquireSpinlock) { | |
319 | KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER); | |
320 | } | |
321 | } | |
322 | ||
323 | /*----------------------------------------------------------------------------*/ | |
324 | /*! | |
325 | * \brief This routines is called to stop a timer. | |
326 | * | |
327 | * \param[in] prTimer Pointer to a timer structure. | |
328 | * | |
329 | * \return (none) | |
330 | */ | |
331 | /*----------------------------------------------------------------------------*/ | |
332 | VOID cnmTimerStopTimer(IN P_ADAPTER_T prAdapter, IN P_TIMER_T prTimer) | |
333 | { | |
334 | ASSERT(prAdapter); | |
335 | ASSERT(prTimer); | |
336 | ||
337 | cnmTimerStopTimer_impl(prAdapter, prTimer, TRUE); | |
338 | } | |
339 | ||
340 | /*----------------------------------------------------------------------------*/ | |
341 | /*! | |
342 | * \brief This routines is called to start a timer with wake_lock. | |
343 | * | |
344 | * \param[in] prTimer Pointer to a timer structure. | |
345 | * \param[in] u4TimeoutMs Timeout to issue the timer and call back function | |
346 | * (unit: ms). | |
347 | * | |
348 | * \return (none) | |
349 | */ | |
350 | /*----------------------------------------------------------------------------*/ | |
351 | VOID cnmTimerStartTimer(IN P_ADAPTER_T prAdapter, IN P_TIMER_T prTimer, IN UINT_32 u4TimeoutMs) | |
352 | { | |
353 | P_ROOT_TIMER prRootTimer; | |
354 | P_LINK_T prTimerList; | |
355 | OS_SYSTIME rExpiredSysTime, rTimeoutSystime; | |
356 | KAL_SPIN_LOCK_DECLARATION(); | |
357 | ||
358 | ASSERT(prAdapter); | |
359 | ASSERT(prTimer); | |
360 | ||
361 | KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER); | |
362 | ||
363 | prRootTimer = &prAdapter->rRootTimer; | |
364 | prTimerList = &prRootTimer->rLinkHead; | |
365 | ||
366 | /* If timeout interval is larger than 1 minute, the mod value is set | |
367 | * to the timeout value first, then per minutue. | |
368 | */ | |
369 | if (u4TimeoutMs > MSEC_PER_MIN) { | |
370 | ASSERT(u4TimeoutMs <= ((UINT_32) 0xFFFF * MSEC_PER_MIN)); | |
371 | ||
372 | prTimer->u2Minutes = (UINT_16) (u4TimeoutMs / MSEC_PER_MIN); | |
373 | u4TimeoutMs -= (prTimer->u2Minutes * MSEC_PER_MIN); | |
374 | if (u4TimeoutMs == 0) { | |
375 | u4TimeoutMs = MSEC_PER_MIN; | |
376 | prTimer->u2Minutes--; | |
377 | } | |
378 | } else { | |
379 | prTimer->u2Minutes = 0; | |
380 | } | |
381 | ||
382 | /* The assertion check if MSEC_TO_SYSTIME() may be overflow. */ | |
383 | ASSERT(u4TimeoutMs < (((UINT_32) 0x80000000 - MSEC_PER_SEC) / KAL_HZ)); | |
384 | rTimeoutSystime = MSEC_TO_SYSTIME(u4TimeoutMs); | |
385 | rExpiredSysTime = kalGetTimeTick() + rTimeoutSystime; | |
386 | ||
387 | /* If no timer pending or the fast time interval is used. */ | |
388 | if (LINK_IS_EMPTY(prTimerList) || | |
389 | TIME_BEFORE(rExpiredSysTime, prRootTimer->rNextExpiredSysTime)) { | |
390 | ||
391 | prRootTimer->rNextExpiredSysTime = rExpiredSysTime; | |
392 | cnmTimerSetTimer(prAdapter, rTimeoutSystime); | |
393 | } | |
394 | ||
395 | /* Add this timer to checking list */ | |
396 | prTimer->rExpiredSysTime = rExpiredSysTime; | |
397 | ||
398 | if (!timerPendingTimer(prTimer)) { | |
399 | LINK_INSERT_TAIL(prTimerList, &prTimer->rLinkEntry); | |
400 | } | |
401 | ||
402 | KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER); | |
403 | ||
404 | return; | |
405 | } | |
406 | ||
407 | /*----------------------------------------------------------------------------*/ | |
408 | /*! | |
409 | * \brief This routines is called to check the timer list. | |
410 | * | |
411 | * \param[in] | |
412 | * | |
413 | * \return (none) | |
414 | */ | |
415 | /*----------------------------------------------------------------------------*/ | |
416 | VOID cnmTimerDoTimeOutCheck(IN P_ADAPTER_T prAdapter) | |
417 | { | |
418 | P_ROOT_TIMER prRootTimer; | |
419 | P_LINK_T prTimerList; | |
420 | P_LINK_ENTRY_T prLinkEntry; | |
421 | P_TIMER_T prTimer; | |
422 | OS_SYSTIME rCurSysTime; | |
423 | PFN_MGMT_TIMEOUT_FUNC pfMgmtTimeOutFunc; | |
424 | UINT_32 u4TimeoutData; | |
425 | BOOLEAN fgNeedWakeLock; | |
426 | KAL_SPIN_LOCK_DECLARATION(); | |
427 | ||
428 | ASSERT(prAdapter); | |
429 | ||
430 | /* acquire spin lock */ | |
431 | KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER); | |
432 | ||
433 | prRootTimer = &prAdapter->rRootTimer; | |
434 | prTimerList = &prRootTimer->rLinkHead; | |
435 | ||
436 | rCurSysTime = kalGetTimeTick(); | |
437 | ||
438 | /* Set the permitted max timeout value for new one */ | |
439 | prRootTimer->rNextExpiredSysTime = rCurSysTime + MGMT_MAX_TIMEOUT_INTERVAL; | |
440 | ||
441 | LINK_FOR_EACH(prLinkEntry, prTimerList) { | |
442 | prTimer = LINK_ENTRY(prLinkEntry, TIMER_T, rLinkEntry); | |
443 | ASSERT(prTimer); | |
444 | ||
445 | /* Check if this entry is timeout. */ | |
446 | if (!TIME_BEFORE(rCurSysTime, prTimer->rExpiredSysTime)) { | |
447 | cnmTimerStopTimer_impl(prAdapter, prTimer, FALSE); | |
448 | ||
449 | pfMgmtTimeOutFunc = prTimer->pfMgmtTimeOutFunc; | |
450 | u4TimeoutData = prTimer->u4Data; | |
451 | ||
452 | if (prTimer->u2Minutes > 0) { | |
453 | prTimer->u2Minutes--; | |
454 | prTimer->rExpiredSysTime = | |
455 | rCurSysTime + MSEC_TO_SYSTIME(MSEC_PER_MIN); | |
456 | LINK_INSERT_TAIL(prTimerList, &prTimer->rLinkEntry); | |
457 | } else if (pfMgmtTimeOutFunc) { | |
458 | KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER); | |
459 | (pfMgmtTimeOutFunc) (prAdapter, u4TimeoutData); | |
460 | KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER); | |
461 | } | |
462 | ||
463 | /* Search entire list again because of nest del and add timers | |
464 | * and current MGMT_TIMER could be volatile after stopped | |
465 | */ | |
466 | prLinkEntry = (P_LINK_ENTRY_T) prTimerList; | |
467 | ||
468 | prRootTimer->rNextExpiredSysTime = rCurSysTime + MGMT_MAX_TIMEOUT_INTERVAL; | |
469 | } else if (TIME_BEFORE(prTimer->rExpiredSysTime, prRootTimer->rNextExpiredSysTime)) { | |
470 | prRootTimer->rNextExpiredSysTime = prTimer->rExpiredSysTime; | |
471 | } | |
472 | } /* end of for loop */ | |
473 | ||
474 | /* Setup the prNext timeout event. It is possible the timer was already | |
475 | * set in the above timeout callback function. | |
476 | */ | |
477 | fgNeedWakeLock = FALSE; | |
478 | if (!LINK_IS_EMPTY(prTimerList)) { | |
479 | ASSERT(TIME_AFTER(prRootTimer->rNextExpiredSysTime, rCurSysTime)); | |
480 | ||
481 | fgNeedWakeLock = cnmTimerSetTimer(prAdapter, (OS_SYSTIME) | |
482 | ((INT_32) prRootTimer->rNextExpiredSysTime - | |
483 | (INT_32) rCurSysTime)); | |
484 | } | |
485 | ||
486 | if (prRootTimer->fgWakeLocked && !fgNeedWakeLock) { | |
487 | KAL_WAKE_UNLOCK(prAdapter, &prRootTimer->rWakeLock); | |
488 | prRootTimer->fgWakeLocked = FALSE; | |
489 | } | |
490 | ||
491 | /* release spin lock */ | |
492 | KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER); | |
493 | } |