xref: /wlan-dirver/qca-wifi-host-cmn/qdf/linux/src/i_qdf_hrtimer.h (revision bea437e2293c3d4fb1b5704fcf633aedac996962)
1 /*
2  * Copyright (c) 2014-2019 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 #if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 2, 0))
38 		struct tasklet_hrtimer tasklet_hrtimer;
39 #endif
40 	} u;
41 	enum qdf_context_mode ctx;
42 } __qdf_hrtimer_data_t;
43 
44 /**
45  * __qdf_hrtimer_get_mode() - Get hrtimer_mode with qdf mode
46  * @mode: mode of hrtimer
47  *
48  * Get hrtimer_mode with qdf hrtimer mode
49  *
50  * Return: void
51  */
52 static inline
53 enum hrtimer_mode __qdf_hrtimer_get_mode(enum qdf_hrtimer_mode mode)
54 {
55 	return (enum hrtimer_mode)mode;
56 }
57 
58 /**
59  * __qdf_hrtimer_start() - Starts hrtimer in given context
60  * @timer: pointer to the hrtimer object
61  * @interval: interval to forward as qdf_ktime_t object
62  * @mode: mode of hrtimer
63  *
64  * Starts hrtimer in given context
65  *
66  * Return: void
67  */
68 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0))
69 static inline
70 void __qdf_hrtimer_start(__qdf_hrtimer_data_t *timer, ktime_t interval,
71 			 enum qdf_hrtimer_mode mode)
72 {
73 	enum hrtimer_mode hrt_mode = __qdf_hrtimer_get_mode(mode);
74 
75 	hrtimer_start(&timer->u.hrtimer, interval, hrt_mode);
76 }
77 #else
78 static inline
79 void __qdf_hrtimer_start(__qdf_hrtimer_data_t *timer, ktime_t interval,
80 			 enum qdf_hrtimer_mode mode)
81 {
82 	enum hrtimer_mode hrt_mode = __qdf_hrtimer_get_mode(mode);
83 
84 	if (timer->ctx == QDF_CONTEXT_HARDWARE)
85 		hrtimer_start(&timer->u.hrtimer, interval, hrt_mode);
86 	else if (timer->ctx == QDF_CONTEXT_TASKLET)
87 		tasklet_hrtimer_start(&timer->u.tasklet_hrtimer,
88 				      interval, hrt_mode);
89 }
90 #endif
91 
92 /**
93  * __qdf_hrtimer_cancel() - cancels hrtimer in given context
94  * @timer: pointer to the hrtimer object
95  *
96  * cancels hrtimer in given context
97  *
98  * Return: int
99  */
100 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0))
101 static inline
102 int __qdf_hrtimer_cancel(__qdf_hrtimer_data_t *timer)
103 {
104 	if (timer->ctx == QDF_CONTEXT_HARDWARE)
105 		return hrtimer_cancel(&timer->u.hrtimer);
106 
107 	return 0;
108 }
109 #else
110 static inline
111 int __qdf_hrtimer_cancel(__qdf_hrtimer_data_t *timer)
112 {
113 	if (timer->ctx == QDF_CONTEXT_HARDWARE)
114 		return hrtimer_cancel(&timer->u.hrtimer);
115 	else if (timer->ctx == QDF_CONTEXT_TASKLET)
116 		return hrtimer_cancel(&timer->u.tasklet_hrtimer.timer);
117 
118 	return 0;
119 }
120 #endif
121 
122 /**
123  * __qdf_hrtimer_init() - init hrtimer in a given context
124  * @timer: pointer to the hrtimer object
125  * @cback: callback function to be fired
126  * @clock: clock id
127  * @hrtimer_mode: mode of hrtimer
128  *
129  * starts hrtimer in a context passed as per the context
130  *
131  * Return: void
132  */
133 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0))
134 static inline void  __qdf_hrtimer_init(__qdf_hrtimer_data_t *timer,
135 				       void *cback,
136 				       enum qdf_clock_id clock,
137 				       enum qdf_hrtimer_mode mode,
138 				       enum qdf_context_mode ctx)
139 {
140 	struct hrtimer *hrtimer = &timer->u.hrtimer;
141 	enum hrtimer_mode hrt_mode = __qdf_hrtimer_get_mode(mode);
142 
143 	timer->ctx = ctx;
144 
145 	if (timer->ctx == QDF_CONTEXT_HARDWARE) {
146 		hrtimer_init(hrtimer, clock, hrt_mode);
147 		hrtimer->function = cback;
148 	} else if (timer->ctx == QDF_CONTEXT_TASKLET) {
149 		QDF_BUG(0);
150 	}
151 }
152 #else
153 static inline void  __qdf_hrtimer_init(__qdf_hrtimer_data_t *timer,
154 				       void *cback,
155 				       enum qdf_clock_id clock,
156 				       enum qdf_hrtimer_mode mode,
157 				       enum qdf_context_mode ctx)
158 {
159 	struct hrtimer *hrtimer = &timer->u.hrtimer;
160 	struct tasklet_hrtimer *tasklet_hrtimer = &timer->u.tasklet_hrtimer;
161 	enum hrtimer_mode hrt_mode = __qdf_hrtimer_get_mode(mode);
162 
163 	timer->ctx = ctx;
164 
165 	if (timer->ctx == QDF_CONTEXT_HARDWARE) {
166 		hrtimer_init(hrtimer, clock, hrt_mode);
167 		hrtimer->function = cback;
168 	} else if (timer->ctx == QDF_CONTEXT_TASKLET) {
169 		tasklet_hrtimer_init(tasklet_hrtimer, cback, clock, hrt_mode);
170 	}
171 }
172 #endif
173 
174 /**
175  * __qdf_hrtimer_kill() - kills hrtimer in given context
176  * @timer: pointer to the hrtimer object
177  *
178  * kills hrtimer in given context
179  *
180  * Return: void
181  */
182 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0))
183 static inline
184 void __qdf_hrtimer_kill(__qdf_hrtimer_data_t *timer)
185 {
186 	hrtimer_cancel(&timer->u.hrtimer);
187 }
188 #else
189 static inline
190 void __qdf_hrtimer_kill(__qdf_hrtimer_data_t *timer)
191 {
192 	if (timer->ctx == QDF_CONTEXT_HARDWARE)
193 		hrtimer_cancel(&timer->u.hrtimer);
194 	else if (timer->ctx == QDF_CONTEXT_TASKLET)
195 		tasklet_hrtimer_cancel(&timer->u.tasklet_hrtimer);
196 }
197 #endif
198 
199 /**
200  * __qdf_hrtimer_get_remaining() - check remaining time in the timer
201  * @timer: pointer to the hrtimer object
202  *
203  * check whether the timer is on one of the queues
204  *
205  * Return: remaining time as ktime object
206  */
207 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0))
208 static inline ktime_t __qdf_hrtimer_get_remaining(__qdf_hrtimer_data_t *timer)
209 {
210 	struct hrtimer *hrtimer = &timer->u.hrtimer;
211 
212 	return hrtimer_get_remaining(hrtimer);
213 }
214 #else
215 static inline ktime_t __qdf_hrtimer_get_remaining(__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_get_remaining(hrtimer);
222 	else
223 		return hrtimer_get_remaining(&tasklet_hrtimer->timer);
224 }
225 #endif
226 
227 /**
228  * __qdf_hrtimer_is_queued() - check whether the timer is on one of the queues
229  * @timer: pointer to the hrtimer object
230  *
231  * check whether the timer is on one of the queues
232  *
233  * Return: false when the timer was not in queue
234  *         true when the timer was in queue
235  */
236 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0))
237 static inline bool __qdf_hrtimer_is_queued(__qdf_hrtimer_data_t *timer)
238 {
239 	struct hrtimer *hrtimer = &timer->u.hrtimer;
240 
241 	return hrtimer_is_queued(hrtimer);
242 }
243 #else
244 static inline bool __qdf_hrtimer_is_queued(__qdf_hrtimer_data_t *timer)
245 {
246 	struct hrtimer *hrtimer = &timer->u.hrtimer;
247 	struct tasklet_hrtimer *tasklet_hrtimer = &timer->u.tasklet_hrtimer;
248 
249 	if (timer->ctx == QDF_CONTEXT_HARDWARE)
250 		return hrtimer_is_queued(hrtimer);
251 	else
252 		return hrtimer_is_queued(&tasklet_hrtimer->timer);
253 }
254 #endif
255 
256 /**
257  * __qdf_hrtimer_callback_running() - check if callback is running
258  * @timer: pointer to the hrtimer object
259  *
260  * check whether the timer is running the callback function
261  *
262  * Return: false when callback is not running
263  *         true when callback is running
264  */
265 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0))
266 static inline bool __qdf_hrtimer_callback_running(__qdf_hrtimer_data_t *timer)
267 {
268 	struct hrtimer *hrtimer = &timer->u.hrtimer;
269 
270 	return hrtimer_callback_running(hrtimer);
271 }
272 #else
273 static inline bool __qdf_hrtimer_callback_running(__qdf_hrtimer_data_t *timer)
274 {
275 	struct hrtimer *hrtimer = &timer->u.hrtimer;
276 	struct tasklet_hrtimer *tasklet_hrtimer = &timer->u.tasklet_hrtimer;
277 
278 	if (timer->ctx == QDF_CONTEXT_HARDWARE)
279 		return hrtimer_callback_running(hrtimer);
280 	else
281 		return hrtimer_callback_running(&tasklet_hrtimer->timer);
282 }
283 #endif
284 
285 /**
286  * __qdf_hrtimer_active() - check if timer is active
287  * @timer: pointer to the hrtimer object
288  *
289  * Check if timer is active. A timer is active, when it is enqueued into
290  * the rbtree or the callback function is running.
291  *
292  * Return: false if timer is not active
293  *         true if timer is active
294  */
295 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0))
296 static inline bool __qdf_hrtimer_active(__qdf_hrtimer_data_t *timer)
297 {
298 	struct hrtimer *hrtimer = &timer->u.hrtimer;
299 
300 	return hrtimer_active(hrtimer);
301 }
302 #else
303 static inline bool __qdf_hrtimer_active(__qdf_hrtimer_data_t *timer)
304 {
305 	struct hrtimer *hrtimer = &timer->u.hrtimer;
306 	struct tasklet_hrtimer *tasklet_hrtimer = &timer->u.tasklet_hrtimer;
307 
308 	if (timer->ctx == QDF_CONTEXT_HARDWARE)
309 		return hrtimer_active(hrtimer);
310 	else
311 		return hrtimer_active(&tasklet_hrtimer->timer);
312 }
313 #endif
314 
315 /**
316  * __qdf_hrtimer_cb_get_time() - get remaining time in callback
317  * @timer: pointer to the hrtimer object
318  *
319  * Get remaining time in the hrtimer callback
320  *
321  * Return: time remaining as ktime object
322  */
323 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0))
324 static inline ktime_t __qdf_hrtimer_cb_get_time(__qdf_hrtimer_data_t *timer)
325 {
326 	struct hrtimer *hrtimer = &timer->u.hrtimer;
327 
328 	return hrtimer_cb_get_time(hrtimer);
329 }
330 #else
331 static inline ktime_t __qdf_hrtimer_cb_get_time(__qdf_hrtimer_data_t *timer)
332 {
333 	struct hrtimer *hrtimer = &timer->u.hrtimer;
334 	struct tasklet_hrtimer *tasklet_hrtimer = &timer->u.tasklet_hrtimer;
335 
336 	if (timer->ctx == QDF_CONTEXT_HARDWARE)
337 		return hrtimer_cb_get_time(hrtimer);
338 	else
339 		return hrtimer_cb_get_time(&tasklet_hrtimer->timer);
340 }
341 #endif
342 
343 /**
344  * __qdf_hrtimer_forward() - forward the hrtimer
345  * @timer: pointer to the hrtimer object
346  * @now: current ktime
347  * @interval: interval to forward as ktime object
348  *
349  * Forward the timer expiry so it will expire in the future
350  *
351  * Return:the number of overruns
352  */
353 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0))
354 static inline uint64_t __qdf_hrtimer_forward(__qdf_hrtimer_data_t *timer,
355 					     ktime_t now,
356 					     ktime_t interval)
357 {
358 	struct hrtimer *hrtimer = &timer->u.hrtimer;
359 
360 	return hrtimer_forward(hrtimer, now, interval);
361 }
362 #else
363 static inline uint64_t __qdf_hrtimer_forward(__qdf_hrtimer_data_t *timer,
364 					     ktime_t now,
365 					     ktime_t interval)
366 {
367 	struct hrtimer *hrtimer = &timer->u.hrtimer;
368 	struct tasklet_hrtimer *tasklet_hrtimer = &timer->u.tasklet_hrtimer;
369 
370 	if (timer->ctx == QDF_CONTEXT_HARDWARE)
371 		return hrtimer_forward(hrtimer, now, interval);
372 	else
373 		return hrtimer_forward(&tasklet_hrtimer->timer, now, interval);
374 }
375 #endif
376 
377 #endif /* _I_QDF_HRTIMER_H */
378