drivers: power: report battery voltage in AOSP compatible format
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / misc / mediatek / connectivity / combo / drv_wlan / mt6628 / wlan / mgmt / cnm_timer.c
CommitLineData
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/*----------------------------------------------------------------------------*/
137static 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/*----------------------------------------------------------------------------*/
171VOID 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/*----------------------------------------------------------------------------*/
201VOID 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/*----------------------------------------------------------------------------*/
236VOID
237cnmTimerInitTimer(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/*----------------------------------------------------------------------------*/
286static VOID
287cnmTimerStopTimer_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/*----------------------------------------------------------------------------*/
332VOID 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/*----------------------------------------------------------------------------*/
351VOID 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/*----------------------------------------------------------------------------*/
416VOID 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}