xref: /wlan-dirver/qca-wifi-host-cmn/qdf/linux/src/i_qdf_hrtimer.h (revision 4865edfd190c086bbe2c69aae12a8226f877b91e)
1 /*
2  * Copyright (c) 2014-2018 The Linux Foundation. All rights reserved.
3  *
4  * Permission to use, copy, modify, and/or distribute this software for
5  * any purpose with or without fee is hereby granted, provided that the
6  * above copyright notice and this permission notice appear in all
7  * copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
12  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
13  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
14  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
15  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16  * PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 /**
20  * DOC: i_qdf_hrtimer
21  * This file provides OS dependent timer API's.
22  */
23 
24 #ifndef _I_QDF_HRTIMER_H
25 #define _I_QDF_HRTIMER_H
26 
27 #include <linux/version.h>
28 #include <linux/delay.h>
29 #include <linux/timer.h>
30 #include <linux/jiffies.h>
31 #include <qdf_types.h>
32 
33 /* hrtimer data type */
34 typedef struct {
35 	union {
36 		struct hrtimer hrtimer;
37 		struct tasklet_hrtimer tasklet_hrtimer;
38 	} u;
39 	enum qdf_context_mode ctx;
40 } __qdf_hrtimer_data_t;
41 
42 /**
43  * __qdf_hrtimer_start() - Starts hrtimer in given context
44  * @timer: pointer to the hrtimer object
45  * @interval: interval to forward as qdf_ktime_t object
46  * @mode: mode of hrtimer
47  *
48  * Starts hrtimer in given context
49  *
50  * Return: void
51  */
52 static inline
53 void __qdf_hrtimer_start(__qdf_hrtimer_data_t *timer, ktime_t interval,
54 			 enum qdf_hrtimer_mode mode)
55 {
56 	if (timer->ctx == QDF_CONTEXT_HARDWARE)
57 		hrtimer_start(&timer->u.hrtimer, interval, mode);
58 	else if (timer->ctx == QDF_CONTEXT_TASKLET)
59 		tasklet_hrtimer_start(&timer->u.tasklet_hrtimer,
60 				      interval, mode);
61 }
62 
63 /**
64  * __qdf_hrtimer_cancel() - cancels hrtimer in given context
65  * @timer: pointer to the hrtimer object
66  *
67  * cancels hrtimer in given context
68  *
69  * Return: void
70  */
71 static inline
72 void __qdf_hrtimer_cancel(__qdf_hrtimer_data_t *timer)
73 {
74 	if (timer->ctx == QDF_CONTEXT_HARDWARE)
75 		hrtimer_cancel(&timer->u.hrtimer);
76 	else if (timer->ctx == QDF_CONTEXT_TASKLET)
77 		hrtimer_cancel(&timer->u.tasklet_hrtimer.timer);
78 }
79 
80 /**
81  * __qdf_hrtimer_init() - init hrtimer in a given context
82  * @timer: pointer to the hrtimer object
83  * @cback: callback function to be fired
84  * @clock: clock id
85  * @hrtimer_mode: mode of hrtimer
86  *
87  * starts hrtimer in a context passed as per the context
88  *
89  * Return: void
90  */
91 static inline void  __qdf_hrtimer_init(__qdf_hrtimer_data_t *timer,
92 				       void *cback,
93 				       enum qdf_clock_id clock,
94 				       enum qdf_hrtimer_mode mode,
95 				       enum qdf_context_mode ctx)
96 {
97 	struct hrtimer *hrtimer = &timer->u.hrtimer;
98 	struct tasklet_hrtimer *tasklet_hrtimer = &timer->u.tasklet_hrtimer;
99 
100 	timer->ctx = ctx;
101 
102 	if (timer->ctx == QDF_CONTEXT_HARDWARE) {
103 		hrtimer_init(hrtimer, clock, mode);
104 		hrtimer->function = cback;
105 	} else if (timer->ctx == QDF_CONTEXT_TASKLET) {
106 		tasklet_hrtimer_init(tasklet_hrtimer, cback, clock, mode);
107 	}
108 }
109 
110 /**
111  * __qdf_hrtimer_kill() - kills hrtimer in given context
112  * @timer: pointer to the hrtimer object
113  *
114  * kills hrtimer in given context
115  *
116  * Return: void
117  */
118 static inline
119 void __qdf_hrtimer_kill(__qdf_hrtimer_data_t *timer)
120 {
121 	if (timer->ctx == QDF_CONTEXT_HARDWARE)
122 		hrtimer_cancel(&timer->u.hrtimer);
123 	else if (timer->ctx == QDF_CONTEXT_TASKLET)
124 		tasklet_hrtimer_cancel(&timer->u.tasklet_hrtimer);
125 }
126 
127 /**
128  * __qdf_hrtimer_get_remaining() - check remaining time in the timer
129  * @timer: pointer to the hrtimer object
130  *
131  * check whether the timer is on one of the queues
132  *
133  * Return: remaining time as ktime object
134  */
135 static inline ktime_t __qdf_hrtimer_get_remaining(__qdf_hrtimer_data_t *timer)
136 {
137 	struct hrtimer *hrtimer = &timer->u.hrtimer;
138 	struct tasklet_hrtimer *tasklet_hrtimer = &timer->u.tasklet_hrtimer;
139 
140 	if (timer->ctx == QDF_CONTEXT_HARDWARE)
141 		return hrtimer_get_remaining(hrtimer);
142 	else
143 		return hrtimer_get_remaining(&tasklet_hrtimer->timer);
144 }
145 
146 /**
147  * __qdf_hrtimer_is_queued() - check whether the timer is on one of the queues
148  * @timer: pointer to the hrtimer object
149  *
150  * check whether the timer is on one of the queues
151  *
152  * Return: false when the timer was not in queue
153  *         true when the timer was in queue
154  */
155 static inline bool __qdf_hrtimer_is_queued(__qdf_hrtimer_data_t *timer)
156 {
157 	struct hrtimer *hrtimer = &timer->u.hrtimer;
158 	struct tasklet_hrtimer *tasklet_hrtimer = &timer->u.tasklet_hrtimer;
159 
160 	if (timer->ctx == QDF_CONTEXT_HARDWARE)
161 		return hrtimer_is_queued(hrtimer);
162 	else
163 		return hrtimer_is_queued(&tasklet_hrtimer->timer);
164 }
165 
166 /**
167  * __qdf_hrtimer_callback_running() - check if callback is running
168  * @timer: pointer to the hrtimer object
169  *
170  * check whether the timer is running the callback function
171  *
172  * Return: false when callback is not running
173  *         true when callback is running
174  */
175 static inline bool __qdf_hrtimer_callback_running(__qdf_hrtimer_data_t *timer)
176 {
177 	struct hrtimer *hrtimer = &timer->u.hrtimer;
178 	struct tasklet_hrtimer *tasklet_hrtimer = &timer->u.tasklet_hrtimer;
179 
180 	if (timer->ctx == QDF_CONTEXT_HARDWARE)
181 		return hrtimer_callback_running(hrtimer);
182 	else
183 		return hrtimer_callback_running(&tasklet_hrtimer->timer);
184 }
185 
186 /**
187  * __qdf_hrtimer_active() - check if timer is active
188  * @timer: pointer to the hrtimer object
189  *
190  * Check if timer is active. A timer is active, when it is enqueued into
191  * the rbtree or the callback function is running.
192  *
193  * Return: false if timer is not active
194  *         true if timer is active
195  */
196 static inline bool __qdf_hrtimer_active(__qdf_hrtimer_data_t *timer)
197 {
198 	struct hrtimer *hrtimer = &timer->u.hrtimer;
199 	struct tasklet_hrtimer *tasklet_hrtimer = &timer->u.tasklet_hrtimer;
200 
201 	if (timer->ctx == QDF_CONTEXT_HARDWARE)
202 		return hrtimer_active(hrtimer);
203 	else
204 		return hrtimer_active(&tasklet_hrtimer->timer);
205 }
206 
207 /**
208  * __qdf_hrtimer_cb_get_time() - get remaining time in callback
209  * @timer: pointer to the hrtimer object
210  *
211  * Get remaining time in the hrtimer callback
212  *
213  * Return: time remaining as ktime object
214  */
215 static inline ktime_t __qdf_hrtimer_cb_get_time(__qdf_hrtimer_data_t *timer)
216 {
217 	struct hrtimer *hrtimer = &timer->u.hrtimer;
218 	struct tasklet_hrtimer *tasklet_hrtimer = &timer->u.tasklet_hrtimer;
219 
220 	if (timer->ctx == QDF_CONTEXT_HARDWARE)
221 		return hrtimer_cb_get_time(hrtimer);
222 	else
223 		return hrtimer_cb_get_time(&tasklet_hrtimer->timer);
224 }
225 
226 /**
227  * __qdf_hrtimer_forward() - forward the hrtimer
228  * @timer: pointer to the hrtimer object
229  * @now: current ktime
230  * @interval: interval to forward as ktime object
231  *
232  * Forward the timer expiry so it will expire in the future
233  *
234  * Return:the number of overruns
235  */
236 static inline uint64_t __qdf_hrtimer_forward(__qdf_hrtimer_data_t *timer,
237 					     ktime_t now,
238 					     ktime_t interval)
239 {
240 	struct hrtimer *hrtimer = &timer->u.hrtimer;
241 	struct tasklet_hrtimer *tasklet_hrtimer = &timer->u.tasklet_hrtimer;
242 
243 	if (timer->ctx == QDF_CONTEXT_HARDWARE)
244 		return hrtimer_forward(hrtimer, now, interval);
245 	else
246 		return hrtimer_forward(&tasklet_hrtimer->timer, now, interval);
247 }
248 
249 #endif /* _I_QDF_HRTIMER_H */
250