1*5113495bSYour Name /*
2*5113495bSYour Name * Copyright (c) 2014-2021 The Linux Foundation. All rights reserved.
3*5113495bSYour Name *
4*5113495bSYour Name * Permission to use, copy, modify, and/or distribute this software for
5*5113495bSYour Name * any purpose with or without fee is hereby granted, provided that the
6*5113495bSYour Name * above copyright notice and this permission notice appear in all
7*5113495bSYour Name * copies.
8*5113495bSYour Name *
9*5113495bSYour Name * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10*5113495bSYour Name * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11*5113495bSYour Name * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
12*5113495bSYour Name * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
13*5113495bSYour Name * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
14*5113495bSYour Name * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
15*5113495bSYour Name * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16*5113495bSYour Name * PERFORMANCE OF THIS SOFTWARE.
17*5113495bSYour Name */
18*5113495bSYour Name
19*5113495bSYour Name /**
20*5113495bSYour Name * DOC: i_qdf_timer
21*5113495bSYour Name * This file provides OS dependent timer API's.
22*5113495bSYour Name */
23*5113495bSYour Name
24*5113495bSYour Name #ifndef _I_QDF_TIMER_H
25*5113495bSYour Name #define _I_QDF_TIMER_H
26*5113495bSYour Name
27*5113495bSYour Name #include <linux/version.h>
28*5113495bSYour Name #include <linux/delay.h>
29*5113495bSYour Name #include <linux/timer.h>
30*5113495bSYour Name #include <linux/jiffies.h>
31*5113495bSYour Name #include "qdf_mc_timer.h"
32*5113495bSYour Name #include <qdf_types.h>
33*5113495bSYour Name #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0)
34*5113495bSYour Name #include <linux/sched/task_stack.h>
35*5113495bSYour Name #endif
36*5113495bSYour Name
37*5113495bSYour Name typedef void (*qdf_timer_func_t)(void *);
38*5113495bSYour Name
39*5113495bSYour Name
40*5113495bSYour Name struct __qdf_timer_t {
41*5113495bSYour Name struct timer_list os_timer;
42*5113495bSYour Name qdf_timer_func_t callback;
43*5113495bSYour Name void *context;
44*5113495bSYour Name };
45*5113495bSYour Name
46*5113495bSYour Name #define __qdf_scaled_msecs_to_jiffies(msec) \
47*5113495bSYour Name (qdf_timer_get_multiplier() * msecs_to_jiffies(msec))
48*5113495bSYour Name
49*5113495bSYour Name #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)
__os_timer_shim(struct timer_list * os_timer)50*5113495bSYour Name static inline void __os_timer_shim(struct timer_list *os_timer)
51*5113495bSYour Name {
52*5113495bSYour Name struct __qdf_timer_t *timer = from_timer(timer, os_timer, os_timer);
53*5113495bSYour Name
54*5113495bSYour Name timer->callback(timer->context);
55*5113495bSYour Name }
56*5113495bSYour Name
__qdf_timer_init(struct __qdf_timer_t * timer,qdf_timer_func_t func,void * arg,QDF_TIMER_TYPE type)57*5113495bSYour Name static inline QDF_STATUS __qdf_timer_init(struct __qdf_timer_t *timer,
58*5113495bSYour Name qdf_timer_func_t func, void *arg,
59*5113495bSYour Name QDF_TIMER_TYPE type)
60*5113495bSYour Name {
61*5113495bSYour Name struct timer_list *os_timer = &timer->os_timer;
62*5113495bSYour Name uint32_t flags = 0;
63*5113495bSYour Name
64*5113495bSYour Name timer->callback = func;
65*5113495bSYour Name timer->context = arg;
66*5113495bSYour Name
67*5113495bSYour Name if (type == QDF_TIMER_TYPE_SW)
68*5113495bSYour Name flags |= TIMER_DEFERRABLE;
69*5113495bSYour Name else if (type == QDF_TIMER_TYPE_SW_SPIN)
70*5113495bSYour Name flags |= TIMER_DEFERRABLE | TIMER_PINNED;
71*5113495bSYour Name
72*5113495bSYour Name if (object_is_on_stack(os_timer))
73*5113495bSYour Name timer_setup_on_stack(os_timer, __os_timer_shim, flags);
74*5113495bSYour Name else
75*5113495bSYour Name timer_setup(os_timer, __os_timer_shim, flags);
76*5113495bSYour Name
77*5113495bSYour Name return QDF_STATUS_SUCCESS;
78*5113495bSYour Name }
79*5113495bSYour Name #else
80*5113495bSYour Name
81*5113495bSYour Name #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 9, 0)
82*5113495bSYour Name #define setup_deferrable_timer(timer, fn, data) \
83*5113495bSYour Name __setup_timer((timer), (fn), (data), TIMER_DEFERRABLE)
84*5113495bSYour Name #endif
85*5113495bSYour Name
__os_timer_shim(unsigned long addr)86*5113495bSYour Name static inline void __os_timer_shim(unsigned long addr)
87*5113495bSYour Name {
88*5113495bSYour Name struct __qdf_timer_t *timer = (void *)addr;
89*5113495bSYour Name
90*5113495bSYour Name timer->callback(timer->context);
91*5113495bSYour Name }
92*5113495bSYour Name
__qdf_timer_init(struct __qdf_timer_t * timer,qdf_timer_func_t func,void * arg,QDF_TIMER_TYPE type)93*5113495bSYour Name static inline QDF_STATUS __qdf_timer_init(struct __qdf_timer_t *timer,
94*5113495bSYour Name qdf_timer_func_t func, void *arg,
95*5113495bSYour Name QDF_TIMER_TYPE type)
96*5113495bSYour Name {
97*5113495bSYour Name struct timer_list *os_timer = &timer->os_timer;
98*5113495bSYour Name bool is_on_stack = object_is_on_stack(os_timer);
99*5113495bSYour Name unsigned long addr = (unsigned long)timer;
100*5113495bSYour Name
101*5113495bSYour Name timer->callback = func;
102*5113495bSYour Name timer->context = arg;
103*5113495bSYour Name
104*5113495bSYour Name if (type == QDF_TIMER_TYPE_SW) {
105*5113495bSYour Name if (is_on_stack)
106*5113495bSYour Name setup_deferrable_timer_on_stack(os_timer,
107*5113495bSYour Name __os_timer_shim,
108*5113495bSYour Name addr);
109*5113495bSYour Name else
110*5113495bSYour Name setup_deferrable_timer(os_timer, __os_timer_shim, addr);
111*5113495bSYour Name } else if (type == QDF_TIMER_TYPE_SW_SPIN) {
112*5113495bSYour Name if (is_on_stack)
113*5113495bSYour Name __setup_timer_on_stack(os_timer,
114*5113495bSYour Name __os_timer_shim,
115*5113495bSYour Name addr,
116*5113495bSYour Name TIMER_DEFERRABLE | TIMER_PINNED);
117*5113495bSYour Name else
118*5113495bSYour Name __setup_timer(os_timer,
119*5113495bSYour Name __os_timer_shim,
120*5113495bSYour Name addr,
121*5113495bSYour Name TIMER_DEFERRABLE | TIMER_PINNED);
122*5113495bSYour Name } else {
123*5113495bSYour Name if (is_on_stack)
124*5113495bSYour Name setup_timer_on_stack(os_timer, __os_timer_shim, addr);
125*5113495bSYour Name else
126*5113495bSYour Name setup_timer(os_timer, __os_timer_shim, addr);
127*5113495bSYour Name }
128*5113495bSYour Name
129*5113495bSYour Name return QDF_STATUS_SUCCESS;
130*5113495bSYour Name }
131*5113495bSYour Name #endif /* KERNEL_VERSION(4, 15, 0)*/
132*5113495bSYour Name
__qdf_timer_start(struct __qdf_timer_t * timer,uint32_t msec)133*5113495bSYour Name static inline void __qdf_timer_start(struct __qdf_timer_t *timer, uint32_t msec)
134*5113495bSYour Name {
135*5113495bSYour Name struct timer_list *os_timer = &timer->os_timer;
136*5113495bSYour Name
137*5113495bSYour Name os_timer->expires = jiffies + __qdf_scaled_msecs_to_jiffies(msec);
138*5113495bSYour Name add_timer(os_timer);
139*5113495bSYour Name }
140*5113495bSYour Name
141*5113495bSYour Name static inline
__qdf_timer_start_on(struct __qdf_timer_t * timer,uint32_t msec,int cpu)142*5113495bSYour Name void __qdf_timer_start_on(struct __qdf_timer_t *timer, uint32_t msec,
143*5113495bSYour Name int cpu)
144*5113495bSYour Name {
145*5113495bSYour Name struct timer_list *os_timer = &timer->os_timer;
146*5113495bSYour Name
147*5113495bSYour Name os_timer->expires = jiffies + __qdf_scaled_msecs_to_jiffies(msec);
148*5113495bSYour Name add_timer_on(os_timer, cpu);
149*5113495bSYour Name }
150*5113495bSYour Name
__qdf_timer_mod(struct __qdf_timer_t * timer,uint32_t msec)151*5113495bSYour Name static inline bool __qdf_timer_mod(struct __qdf_timer_t *timer, uint32_t msec)
152*5113495bSYour Name {
153*5113495bSYour Name return mod_timer(&timer->os_timer,
154*5113495bSYour Name jiffies + __qdf_scaled_msecs_to_jiffies(msec));
155*5113495bSYour Name }
156*5113495bSYour Name
__qdf_timer_stop(struct __qdf_timer_t * timer)157*5113495bSYour Name static inline bool __qdf_timer_stop(struct __qdf_timer_t *timer)
158*5113495bSYour Name {
159*5113495bSYour Name return !!del_timer(&timer->os_timer);
160*5113495bSYour Name }
161*5113495bSYour Name
__qdf_timer_free(struct __qdf_timer_t * timer)162*5113495bSYour Name static inline void __qdf_timer_free(struct __qdf_timer_t *timer)
163*5113495bSYour Name {
164*5113495bSYour Name struct timer_list *os_timer = &timer->os_timer;
165*5113495bSYour Name
166*5113495bSYour Name del_timer_sync(os_timer);
167*5113495bSYour Name
168*5113495bSYour Name if (object_is_on_stack(os_timer))
169*5113495bSYour Name destroy_timer_on_stack(os_timer);
170*5113495bSYour Name }
171*5113495bSYour Name
__qdf_timer_sync_cancel(struct __qdf_timer_t * timer)172*5113495bSYour Name static inline bool __qdf_timer_sync_cancel(struct __qdf_timer_t *timer)
173*5113495bSYour Name {
174*5113495bSYour Name return del_timer_sync(&timer->os_timer);
175*5113495bSYour Name }
176*5113495bSYour Name
177*5113495bSYour Name #endif /* _I_QDF_TIMER_H */
178