add rk3288 pinctrl dts code
[firefly-linux-kernel-4.4.55.git] / drivers / net / wireless / combo_mt66xx / mt6620 / wlan / mgmt / cnm_timer.c
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
138 cnmTimerSetTimer (
139     IN P_ADAPTER_T prAdapter,
140     IN OS_SYSTIME  rTimeout
141     )
142 {
143     P_ROOT_TIMER        prRootTimer;
144     BOOLEAN             fgNeedWakeLock;
145
146     ASSERT(prAdapter);
147
148     prRootTimer = &prAdapter->rRootTimer;
149
150     kalSetTimer(prAdapter->prGlueInfo, rTimeout);
151
152     if (rTimeout <= SEC_TO_SYSTIME(WAKE_LOCK_MAX_TIME)) {
153         fgNeedWakeLock = TRUE;
154
155         if (!prRootTimer->fgWakeLocked) {
156             KAL_WAKE_LOCK(prAdapter, &prRootTimer->rWakeLock);
157             prRootTimer->fgWakeLocked = TRUE;
158         }
159     }
160     else {
161         fgNeedWakeLock = FALSE;
162     }
163
164     return fgNeedWakeLock;
165 }
166
167 /*----------------------------------------------------------------------------*/
168 /*!
169 * \brief This routines is called to initialize a root timer.
170 *
171 * \param[in] prAdapter
172 *
173 * \return (none)
174 */
175 /*----------------------------------------------------------------------------*/
176 VOID
177 cnmTimerInitialize (
178     IN P_ADAPTER_T prAdapter
179     )
180 {
181     P_ROOT_TIMER    prRootTimer;
182     KAL_SPIN_LOCK_DECLARATION();
183
184     ASSERT(prAdapter);
185
186     prRootTimer = &prAdapter->rRootTimer;
187
188     /* Note: glue layer have configured timer */
189
190     KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER);
191     LINK_INITIALIZE(&prRootTimer->rLinkHead);
192     KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER);
193
194     KAL_WAKE_LOCK_INIT(prAdapter, &prRootTimer->rWakeLock, "WLAN Timer");
195     prRootTimer->fgWakeLocked = FALSE;
196     return;
197 }
198
199 /*----------------------------------------------------------------------------*/
200 /*!
201 * \brief This routines is called to destroy a root timer.
202 *        When WIFI is off, the token shall be returned back to system.
203 *
204 * \param[in]
205 *
206 * \return (none)
207 */
208 /*----------------------------------------------------------------------------*/
209 VOID
210 cnmTimerDestroy (
211     IN P_ADAPTER_T prAdapter
212     )
213 {
214     P_ROOT_TIMER    prRootTimer;
215     KAL_SPIN_LOCK_DECLARATION();
216
217     ASSERT(prAdapter);
218
219     prRootTimer = &prAdapter->rRootTimer;
220
221     if (prRootTimer->fgWakeLocked) {
222         KAL_WAKE_UNLOCK(prAdapter, &prRootTimer->rWakeLock);
223         prRootTimer->fgWakeLocked = FALSE;
224     }
225     KAL_WAKE_LOCK_DESTROY(prAdapter, &prRootTimer->rWakeLock);
226
227     KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER);
228     LINK_INITIALIZE(&prRootTimer->rLinkHead);
229     KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER);
230
231     /* Note: glue layer will be responsible for timer destruction */
232
233     return;
234 }
235
236 /*----------------------------------------------------------------------------*/
237 /*!
238 * \brief This routines is called to initialize a timer.
239 *
240 * \param[in] prTimer Pointer to a timer structure.
241 * \param[in] pfnFunc Pointer to the call back function.
242 * \param[in] u4Data Parameter for call back function.
243 *
244 * \return (none)
245 */
246 /*----------------------------------------------------------------------------*/
247 VOID
248 cnmTimerInitTimer (
249     IN P_ADAPTER_T              prAdapter,
250     IN P_TIMER_T                prTimer,
251     IN PFN_MGMT_TIMEOUT_FUNC    pfFunc,
252     IN UINT_32                  u4Data
253     )
254 {
255     ASSERT(prAdapter);
256
257     ASSERT(prTimer);
258
259 #if DBG
260     /* Note: NULL function pointer is permitted for HEM POWER */
261     if (pfFunc == NULL) {
262         DBGLOG(CNM, WARN, ("Init timer with NULL callback function!\n"));
263     }
264 #endif
265
266 #if DBG
267     ASSERT(prAdapter->rRootTimer.rLinkHead.prNext);
268     {
269         P_LINK_T            prTimerList;
270         P_LINK_ENTRY_T      prLinkEntry;
271         P_TIMER_T           prPendingTimer;
272
273         prTimerList = &(prAdapter->rRootTimer.rLinkHead);
274
275         LINK_FOR_EACH(prLinkEntry, prTimerList) {
276             prPendingTimer = LINK_ENTRY(prLinkEntry, TIMER_T, rLinkEntry);
277             ASSERT(prPendingTimer);
278             ASSERT(prPendingTimer != prTimer);
279         }
280     }
281 #endif
282
283     LINK_ENTRY_INITIALIZE(&prTimer->rLinkEntry);
284
285     prTimer->pfMgmtTimeOutFunc  = pfFunc;
286     prTimer->u4Data             = u4Data;
287
288     return;
289 }
290
291
292 /*----------------------------------------------------------------------------*/
293 /*!
294 * \brief This routines is called to stop a timer.
295 *
296 * \param[in] prTimer Pointer to a timer structure.
297 *
298 * \return (none)
299 */
300 /*----------------------------------------------------------------------------*/
301 static VOID
302 cnmTimerStopTimer_impl (
303     IN P_ADAPTER_T              prAdapter,
304     IN P_TIMER_T                prTimer,
305     IN BOOLEAN                  fgAcquireSpinlock
306     )
307 {
308     P_ROOT_TIMER    prRootTimer;
309     KAL_SPIN_LOCK_DECLARATION();
310
311     ASSERT(prAdapter);
312     ASSERT(prTimer);
313
314     prRootTimer = &prAdapter->rRootTimer;
315
316     if (fgAcquireSpinlock) {
317         KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER);
318     }
319
320     if (timerPendingTimer(prTimer)) {
321         LINK_REMOVE_KNOWN_ENTRY(&prRootTimer->rLinkHead,
322                     &prTimer->rLinkEntry);
323
324         /* Reduce dummy timeout for power saving, especially HIF activity.
325          * If two or more timers exist and being removed timer is smallest,
326          * this dummy timeout will still happen, but it is OK.
327          */
328         if (LINK_IS_EMPTY(&prRootTimer->rLinkHead)) {
329             kalCancelTimer(prAdapter->prGlueInfo);
330
331             if (fgAcquireSpinlock && prRootTimer->fgWakeLocked) {
332                 KAL_WAKE_UNLOCK(prAdapter, &prRootTimer->rWakeLock);
333                 prRootTimer->fgWakeLocked = FALSE;
334             }
335         }
336     }
337
338     if (fgAcquireSpinlock) {
339         KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER);
340     }
341 }
342
343 /*----------------------------------------------------------------------------*/
344 /*!
345 * \brief This routines is called to stop a timer.
346 *
347 * \param[in] prTimer Pointer to a timer structure.
348 *
349 * \return (none)
350 */
351 /*----------------------------------------------------------------------------*/
352 VOID
353 cnmTimerStopTimer (
354     IN P_ADAPTER_T              prAdapter,
355     IN P_TIMER_T                prTimer
356     )
357 {
358     ASSERT(prAdapter);
359     ASSERT(prTimer);
360
361     cnmTimerStopTimer_impl(prAdapter, prTimer, TRUE);
362 }
363
364 /*----------------------------------------------------------------------------*/
365 /*!
366 * \brief This routines is called to start a timer with wake_lock.
367 *
368 * \param[in] prTimer Pointer to a timer structure.
369 * \param[in] u4TimeoutMs Timeout to issue the timer and call back function
370 *                        (unit: ms).
371 *
372 * \return (none)
373 */
374 /*----------------------------------------------------------------------------*/
375 VOID
376 cnmTimerStartTimer (
377     IN P_ADAPTER_T      prAdapter,
378     IN P_TIMER_T        prTimer,
379     IN UINT_32          u4TimeoutMs
380     )
381 {
382     P_ROOT_TIMER    prRootTimer;
383     P_LINK_T        prTimerList;
384     OS_SYSTIME      rExpiredSysTime, rTimeoutSystime;
385     KAL_SPIN_LOCK_DECLARATION();
386
387     ASSERT(prAdapter);
388     ASSERT(prTimer);
389
390     KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER);
391
392     prRootTimer = &prAdapter->rRootTimer;
393     prTimerList= &prRootTimer->rLinkHead;
394
395     /* If timeout interval is larger than 1 minute, the mod value is set
396      * to the timeout value first, then per minutue.
397      */
398     if (u4TimeoutMs > MSEC_PER_MIN) {
399         ASSERT(u4TimeoutMs <= ((UINT_32)0xFFFF * MSEC_PER_MIN));
400
401         prTimer->u2Minutes = (UINT_16)(u4TimeoutMs / MSEC_PER_MIN);
402         u4TimeoutMs -= (prTimer->u2Minutes * MSEC_PER_MIN);
403         if (u4TimeoutMs == 0) {
404             u4TimeoutMs = MSEC_PER_MIN;
405             prTimer->u2Minutes--;
406         }
407     }
408     else {
409         prTimer->u2Minutes = 0;
410     }
411
412     /* The assertion check if MSEC_TO_SYSTIME() may be overflow. */
413     ASSERT(u4TimeoutMs < (((UINT_32)0x80000000 - MSEC_PER_SEC) / KAL_HZ));
414     rTimeoutSystime = MSEC_TO_SYSTIME(u4TimeoutMs);
415     rExpiredSysTime = kalGetTimeTick() + rTimeoutSystime;
416
417     /* If no timer pending or the fast time interval is used. */
418     if (LINK_IS_EMPTY(prTimerList) ||
419         TIME_BEFORE(rExpiredSysTime, prRootTimer->rNextExpiredSysTime)) {
420
421         prRootTimer->rNextExpiredSysTime = rExpiredSysTime;
422         cnmTimerSetTimer(prAdapter, rTimeoutSystime);
423     }
424
425     /* Add this timer to checking list */
426     prTimer->rExpiredSysTime = rExpiredSysTime;
427
428     if (!timerPendingTimer(prTimer)) {
429         LINK_INSERT_TAIL(prTimerList, &prTimer->rLinkEntry);
430     }
431
432     KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER);
433
434     return;
435 }
436
437 /*----------------------------------------------------------------------------*/
438 /*!
439 * \brief This routines is called to check the timer list.
440 *
441 * \param[in]
442 *
443 * \return (none)
444 */
445 /*----------------------------------------------------------------------------*/
446 VOID
447 cnmTimerDoTimeOutCheck (
448     IN P_ADAPTER_T      prAdapter
449     )
450 {
451     P_ROOT_TIMER        prRootTimer;
452     P_LINK_T            prTimerList;
453     P_LINK_ENTRY_T      prLinkEntry;
454     P_TIMER_T           prTimer;
455     OS_SYSTIME          rCurSysTime;
456     PFN_MGMT_TIMEOUT_FUNC   pfMgmtTimeOutFunc;
457     UINT_32             u4TimeoutData;
458     BOOLEAN             fgNeedWakeLock;
459     KAL_SPIN_LOCK_DECLARATION();
460
461     ASSERT(prAdapter);
462
463     /* acquire spin lock */
464     KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER);
465
466     prRootTimer = &prAdapter->rRootTimer;
467     prTimerList= &prRootTimer->rLinkHead;
468
469     rCurSysTime = kalGetTimeTick();
470
471     /* Set the permitted max timeout value for new one */
472     prRootTimer->rNextExpiredSysTime = rCurSysTime + MGMT_MAX_TIMEOUT_INTERVAL;
473
474     LINK_FOR_EACH(prLinkEntry, prTimerList) {
475         prTimer = LINK_ENTRY(prLinkEntry, TIMER_T, rLinkEntry);
476         ASSERT(prTimer);
477
478         /* Check if this entry is timeout. */
479         if (!TIME_BEFORE(rCurSysTime, prTimer->rExpiredSysTime)) {
480             cnmTimerStopTimer_impl(prAdapter, prTimer, FALSE);
481
482             pfMgmtTimeOutFunc = prTimer->pfMgmtTimeOutFunc;
483             u4TimeoutData = prTimer->u4Data;
484
485             if (prTimer->u2Minutes > 0) {
486                 prTimer->u2Minutes--;
487                 prTimer->rExpiredSysTime =
488                     rCurSysTime + MSEC_TO_SYSTIME(MSEC_PER_MIN);
489                 LINK_INSERT_TAIL(prTimerList, &prTimer->rLinkEntry);
490             }
491             else if (pfMgmtTimeOutFunc) {
492                 KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER);
493                 (pfMgmtTimeOutFunc)(prAdapter, u4TimeoutData);
494                 KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER);
495             }
496
497             /* Search entire list again because of nest del and add timers
498              * and current MGMT_TIMER could be volatile after stopped
499              */
500             prLinkEntry = (P_LINK_ENTRY_T)prTimerList;
501
502             prRootTimer->rNextExpiredSysTime =
503                     rCurSysTime + MGMT_MAX_TIMEOUT_INTERVAL;
504         }
505         else if (TIME_BEFORE(prTimer->rExpiredSysTime,
506                              prRootTimer->rNextExpiredSysTime)) {
507             prRootTimer->rNextExpiredSysTime = prTimer->rExpiredSysTime;
508         }
509     } /* end of for loop */
510
511     /* Setup the prNext timeout event. It is possible the timer was already
512      * set in the above timeout callback function.
513      */
514     fgNeedWakeLock = FALSE;
515     if (!LINK_IS_EMPTY(prTimerList)) {
516         ASSERT(TIME_AFTER(prRootTimer->rNextExpiredSysTime, rCurSysTime));
517
518         fgNeedWakeLock = cnmTimerSetTimer(prAdapter, (OS_SYSTIME)
519             ((INT_32)prRootTimer->rNextExpiredSysTime - (INT_32)rCurSysTime));
520     }
521
522     if (prRootTimer->fgWakeLocked && !fgNeedWakeLock) {
523         KAL_WAKE_UNLOCK(prAdapter, &prRootTimer->rWakeLock);
524         prRootTimer->fgWakeLocked = FALSE;
525     }
526
527     /* release spin lock */
528     KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER);
529 }
530
531