2 ** $Id: //Department/DaVinci/BRANCHES/MT662X_593X_WIFI_DRIVER_V2_3/mgmt/cnm_timer.c#1 $
5 /*! \file "cnm_timer.c"
10 /*******************************************************************************
11 * Copyright (c) 2009 MediaTek Inc.
13 * All rights reserved. Copying, compilation, modification, distribution
14 * or any other use whatsoever of this material is strictly prohibited
15 * except in accordance with a Software License Agreement with
17 ********************************************************************************
20 /*******************************************************************************
23 * BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND
24 * AGREES THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK
25 * SOFTWARE") RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE
26 * PROVIDED TO BUYER ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY
27 * DISCLAIMS ANY AND ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT
28 * LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
29 * PARTICULAR PURPOSE OR NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE
30 * ANY WARRANTY WHATSOEVER WITH RESPECT TO THE SOFTWARE OF ANY THIRD PARTY
31 * WHICH MAY BE USED BY, INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK
32 * SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY
33 * WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE
34 * FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S SPECIFICATION OR TO
35 * CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
37 * BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
38 * LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL
39 * BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT
40 * ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY
41 * BUYER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
43 * THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
44 * WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT
45 * OF LAWS PRINCIPLES. ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING
46 * THEREOF AND RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN
47 * FRANCISCO, CA, UNDER THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE
49 ********************************************************************************
53 ** $Log: cnm_timer.c $
56 * [WCXRP00001136] [All Wi-Fi][Driver] Add wake lock for pending timer
57 * Add wake lock if timer timeout value is smaller than 5 seconds
60 * [WCXRP00000490] [MT6620 Wi-Fi][Driver][Win32] modify kalMsleep() implementation because NdisMSleep() won't sleep long enough for specified interval such as 500ms
61 * modify cnm_timer and hem_mbox APIs to be thread safe to ease invoking restrictions
65 * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository.
68 * [WPD00003833][MT6620 and MT5931] Driver migration
69 * cnm_timer has been migrated.
72 * [BORA00000018]Integrate WIFI part into BORA for the 1st time
73 * Support sleep notification to host
76 * [BORA00000018]Integrate WIFI part into BORA for the 1st time
77 * Add some checking assertions
80 * [BORA00000018]Integrate WIFI part into BORA for the 1st time
81 * Return timer token back to COS when entering wait off state
84 * [BORA00000018]Integrate WIFI part into BORA for the 1st time
85 * Remove compiling warning
88 * [BORA00000018]Integrate WIFI part into BORA for the 1st time
89 * Support longer timeout interval to 45 days from 65secu1rwduu`wvpghlqg|fh+fmdkb
92 * [BORA00000018]Integrate WIFI part into BORA for the 1st time
93 * Fix system time is 32KHz instead of 1ms
95 * 01 04 2010 tehuang.liu
96 * [BORA00000018]Integrate WIFI part into BORA for the 1st time
97 * For working out the first connection Chariot-verified version
100 * [BORA00000018] Integrate WIFI part into BORA for the 1st time
101 * Place rRootTimer.rNextExpiredSysTime = rExpiredSysTime; before set timer
103 * Oct 30 2009 mtk01104
104 * [BORA00000018] Integrate WIFI part into BORA for the 1st time
105 * In cnmTimerInitialize(), just stop timer if it was already created.
107 * Oct 30 2009 mtk01461
108 * [BORA00000018] Integrate WIFI part into BORA for the 1st time
109 * Move the external reference for Lint to precomp.h
111 * Oct 30 2009 mtk01461
112 * [BORA00000018] Integrate WIFI part into BORA for the 1st time
115 * Oct 28 2009 mtk01104
116 * [BORA00000018] Integrate WIFI part into BORA for the 1st time
121 /*******************************************************************************
122 * C O M P I L E R F L A G S
123 ********************************************************************************
126 /*******************************************************************************
127 * E X T E R N A L R E F E R E N C E S
128 ********************************************************************************
132 /*******************************************************************************
134 ********************************************************************************
137 /*******************************************************************************
139 ********************************************************************************
142 /*******************************************************************************
143 * P U B L I C D A T A
144 ********************************************************************************
147 /*******************************************************************************
148 * P R I V A T E D A T A
149 ********************************************************************************
152 /*******************************************************************************
154 ********************************************************************************
157 /*******************************************************************************
158 * F U N C T I O N D E C L A R A T I O N S
159 ********************************************************************************
162 /*******************************************************************************
164 ********************************************************************************
167 /*----------------------------------------------------------------------------*/
169 * \brief This routine is called to set the time to do the time out check.
171 * \param[in] rTimeout Time out interval from current time.
173 * \retval TRUE Success.
176 /*----------------------------------------------------------------------------*/
179 IN P_ADAPTER_T prAdapter,
180 IN OS_SYSTIME rTimeout
183 P_ROOT_TIMER prRootTimer;
184 BOOLEAN fgNeedWakeLock;
188 prRootTimer = &prAdapter->rRootTimer;
190 kalSetTimer(prAdapter->prGlueInfo, rTimeout);
192 if (rTimeout <= SEC_TO_SYSTIME(WAKE_LOCK_MAX_TIME)) {
193 fgNeedWakeLock = TRUE;
195 if (!prRootTimer->fgWakeLocked) {
196 KAL_WAKE_LOCK(prAdapter, &prRootTimer->rWakeLock);
197 prRootTimer->fgWakeLocked = TRUE;
201 fgNeedWakeLock = FALSE;
204 return fgNeedWakeLock;
207 /*----------------------------------------------------------------------------*/
209 * \brief This routines is called to initialize a root timer.
211 * \param[in] prAdapter
215 /*----------------------------------------------------------------------------*/
218 IN P_ADAPTER_T prAdapter
221 P_ROOT_TIMER prRootTimer;
222 KAL_SPIN_LOCK_DECLARATION();
226 prRootTimer = &prAdapter->rRootTimer;
228 /* Note: glue layer have configured timer */
230 KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER);
231 LINK_INITIALIZE(&prRootTimer->rLinkHead);
232 KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER);
234 KAL_WAKE_LOCK_INIT(prAdapter, &prRootTimer->rWakeLock, "WLAN Timer");
235 prRootTimer->fgWakeLocked = FALSE;
239 /*----------------------------------------------------------------------------*/
241 * \brief This routines is called to destroy a root timer.
242 * When WIFI is off, the token shall be returned back to system.
248 /*----------------------------------------------------------------------------*/
251 IN P_ADAPTER_T prAdapter
254 P_ROOT_TIMER prRootTimer;
255 KAL_SPIN_LOCK_DECLARATION();
259 prRootTimer = &prAdapter->rRootTimer;
261 if (prRootTimer->fgWakeLocked) {
262 KAL_WAKE_UNLOCK(prAdapter, &prRootTimer->rWakeLock);
263 prRootTimer->fgWakeLocked = FALSE;
265 KAL_WAKE_LOCK_DESTROY(prAdapter, &prRootTimer->rWakeLock);
267 KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER);
268 LINK_INITIALIZE(&prRootTimer->rLinkHead);
269 KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER);
271 /* Note: glue layer will be responsible for timer destruction */
276 /*----------------------------------------------------------------------------*/
278 * \brief This routines is called to initialize a timer.
280 * \param[in] prTimer Pointer to a timer structure.
281 * \param[in] pfnFunc Pointer to the call back function.
282 * \param[in] u4Data Parameter for call back function.
286 /*----------------------------------------------------------------------------*/
289 IN P_ADAPTER_T prAdapter,
290 IN P_TIMER_T prTimer,
291 IN PFN_MGMT_TIMEOUT_FUNC pfFunc,
300 /* Note: NULL function pointer is permitted for HEM POWER */
301 if (pfFunc == NULL) {
302 DBGLOG(CNM, WARN, ("Init timer with NULL callback function!\n"));
307 ASSERT(prAdapter->rRootTimer.rLinkHead.prNext);
309 P_LINK_T prTimerList;
310 P_LINK_ENTRY_T prLinkEntry;
311 P_TIMER_T prPendingTimer;
313 prTimerList = &(prAdapter->rRootTimer.rLinkHead);
315 LINK_FOR_EACH(prLinkEntry, prTimerList) {
316 prPendingTimer = LINK_ENTRY(prLinkEntry, TIMER_T, rLinkEntry);
317 ASSERT(prPendingTimer);
318 ASSERT(prPendingTimer != prTimer);
323 LINK_ENTRY_INITIALIZE(&prTimer->rLinkEntry);
325 prTimer->pfMgmtTimeOutFunc = pfFunc;
326 prTimer->u4Data = u4Data;
332 /*----------------------------------------------------------------------------*/
334 * \brief This routines is called to stop a timer.
336 * \param[in] prTimer Pointer to a timer structure.
340 /*----------------------------------------------------------------------------*/
342 cnmTimerStopTimer_impl (
343 IN P_ADAPTER_T prAdapter,
344 IN P_TIMER_T prTimer,
345 IN BOOLEAN fgAcquireSpinlock
348 P_ROOT_TIMER prRootTimer;
349 KAL_SPIN_LOCK_DECLARATION();
354 prRootTimer = &prAdapter->rRootTimer;
356 if (fgAcquireSpinlock) {
357 KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER);
360 if (timerPendingTimer(prTimer)) {
361 LINK_REMOVE_KNOWN_ENTRY(&prRootTimer->rLinkHead,
362 &prTimer->rLinkEntry);
364 /* Reduce dummy timeout for power saving, especially HIF activity.
365 * If two or more timers exist and being removed timer is smallest,
366 * this dummy timeout will still happen, but it is OK.
368 if (LINK_IS_EMPTY(&prRootTimer->rLinkHead)) {
369 kalCancelTimer(prAdapter->prGlueInfo);
371 if (fgAcquireSpinlock && prRootTimer->fgWakeLocked) {
372 KAL_WAKE_UNLOCK(prAdapter, &prRootTimer->rWakeLock);
373 prRootTimer->fgWakeLocked = FALSE;
378 if (fgAcquireSpinlock) {
379 KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER);
383 /*----------------------------------------------------------------------------*/
385 * \brief This routines is called to stop a timer.
387 * \param[in] prTimer Pointer to a timer structure.
391 /*----------------------------------------------------------------------------*/
394 IN P_ADAPTER_T prAdapter,
401 cnmTimerStopTimer_impl(prAdapter, prTimer, TRUE);
404 /*----------------------------------------------------------------------------*/
406 * \brief This routines is called to start a timer with wake_lock.
408 * \param[in] prTimer Pointer to a timer structure.
409 * \param[in] u4TimeoutMs Timeout to issue the timer and call back function
414 /*----------------------------------------------------------------------------*/
417 IN P_ADAPTER_T prAdapter,
418 IN P_TIMER_T prTimer,
419 IN UINT_32 u4TimeoutMs
422 P_ROOT_TIMER prRootTimer;
423 P_LINK_T prTimerList;
424 OS_SYSTIME rExpiredSysTime, rTimeoutSystime;
425 KAL_SPIN_LOCK_DECLARATION();
430 KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER);
432 prRootTimer = &prAdapter->rRootTimer;
433 prTimerList= &prRootTimer->rLinkHead;
435 /* If timeout interval is larger than 1 minute, the mod value is set
436 * to the timeout value first, then per minutue.
438 if (u4TimeoutMs > MSEC_PER_MIN) {
439 ASSERT(u4TimeoutMs <= ((UINT_32)0xFFFF * MSEC_PER_MIN));
441 prTimer->u2Minutes = (UINT_16)(u4TimeoutMs / MSEC_PER_MIN);
442 u4TimeoutMs -= (prTimer->u2Minutes * MSEC_PER_MIN);
443 if (u4TimeoutMs == 0) {
444 u4TimeoutMs = MSEC_PER_MIN;
445 prTimer->u2Minutes--;
449 prTimer->u2Minutes = 0;
452 /* The assertion check if MSEC_TO_SYSTIME() may be overflow. */
453 ASSERT(u4TimeoutMs < (((UINT_32)0x80000000 - MSEC_PER_SEC) / KAL_HZ));
454 rTimeoutSystime = MSEC_TO_SYSTIME(u4TimeoutMs);
455 rExpiredSysTime = kalGetTimeTick() + rTimeoutSystime;
457 /* If no timer pending or the fast time interval is used. */
458 if (LINK_IS_EMPTY(prTimerList) ||
459 TIME_BEFORE(rExpiredSysTime, prRootTimer->rNextExpiredSysTime)) {
461 prRootTimer->rNextExpiredSysTime = rExpiredSysTime;
462 cnmTimerSetTimer(prAdapter, rTimeoutSystime);
465 /* Add this timer to checking list */
466 prTimer->rExpiredSysTime = rExpiredSysTime;
468 if (!timerPendingTimer(prTimer)) {
469 LINK_INSERT_TAIL(prTimerList, &prTimer->rLinkEntry);
472 KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER);
477 /*----------------------------------------------------------------------------*/
479 * \brief This routines is called to check the timer list.
485 /*----------------------------------------------------------------------------*/
487 cnmTimerDoTimeOutCheck (
488 IN P_ADAPTER_T prAdapter
491 P_ROOT_TIMER prRootTimer;
492 P_LINK_T prTimerList;
493 P_LINK_ENTRY_T prLinkEntry;
495 OS_SYSTIME rCurSysTime;
496 PFN_MGMT_TIMEOUT_FUNC pfMgmtTimeOutFunc;
497 UINT_32 u4TimeoutData;
498 BOOLEAN fgNeedWakeLock;
499 KAL_SPIN_LOCK_DECLARATION();
503 /* acquire spin lock */
504 KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER);
506 prRootTimer = &prAdapter->rRootTimer;
507 prTimerList= &prRootTimer->rLinkHead;
509 rCurSysTime = kalGetTimeTick();
511 /* Set the permitted max timeout value for new one */
512 prRootTimer->rNextExpiredSysTime = rCurSysTime + MGMT_MAX_TIMEOUT_INTERVAL;
514 LINK_FOR_EACH(prLinkEntry, prTimerList) {
515 prTimer = LINK_ENTRY(prLinkEntry, TIMER_T, rLinkEntry);
518 /* Check if this entry is timeout. */
519 if (!TIME_BEFORE(rCurSysTime, prTimer->rExpiredSysTime)) {
520 cnmTimerStopTimer_impl(prAdapter, prTimer, FALSE);
522 pfMgmtTimeOutFunc = prTimer->pfMgmtTimeOutFunc;
523 u4TimeoutData = prTimer->u4Data;
525 if (prTimer->u2Minutes > 0) {
526 prTimer->u2Minutes--;
527 prTimer->rExpiredSysTime =
528 rCurSysTime + MSEC_TO_SYSTIME(MSEC_PER_MIN);
529 LINK_INSERT_TAIL(prTimerList, &prTimer->rLinkEntry);
531 else if (pfMgmtTimeOutFunc) {
532 KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER);
533 (pfMgmtTimeOutFunc)(prAdapter, u4TimeoutData);
534 KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER);
537 /* Search entire list again because of nest del and add timers
538 * and current MGMT_TIMER could be volatile after stopped
540 prLinkEntry = (P_LINK_ENTRY_T)prTimerList;
542 prRootTimer->rNextExpiredSysTime =
543 rCurSysTime + MGMT_MAX_TIMEOUT_INTERVAL;
545 else if (TIME_BEFORE(prTimer->rExpiredSysTime,
546 prRootTimer->rNextExpiredSysTime)) {
547 prRootTimer->rNextExpiredSysTime = prTimer->rExpiredSysTime;
549 } /* end of for loop */
551 /* Setup the prNext timeout event. It is possible the timer was already
552 * set in the above timeout callback function.
554 fgNeedWakeLock = FALSE;
555 if (!LINK_IS_EMPTY(prTimerList)) {
556 ASSERT(TIME_AFTER(prRootTimer->rNextExpiredSysTime, rCurSysTime));
558 fgNeedWakeLock = cnmTimerSetTimer(prAdapter, (OS_SYSTIME)
559 ((INT_32)prRootTimer->rNextExpiredSysTime - (INT_32)rCurSysTime));
562 if (prRootTimer->fgWakeLocked && !fgNeedWakeLock) {
563 KAL_WAKE_UNLOCK(prAdapter, &prRootTimer->rWakeLock);
564 prRootTimer->fgWakeLocked = FALSE;
567 /* release spin lock */
568 KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER);