xref: /wlan-dirver/qca-wifi-host-cmn/qdf/linux/src/i_qdf_hrtimer.h (revision 302a1d9701784af5f4797b1a9fe07ae820b51907)
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: int
70  */
71 static inline
72 int __qdf_hrtimer_cancel(__qdf_hrtimer_data_t *timer)
73 {
74 	if (timer->ctx == QDF_CONTEXT_HARDWARE)
75 		return hrtimer_cancel(&timer->u.hrtimer);
76 	else if (timer->ctx == QDF_CONTEXT_TASKLET)
77 		return hrtimer_cancel(&timer->u.tasklet_hrtimer.timer);
78 
79 	return 0;
80 }
81 
82 /**
83  * __qdf_hrtimer_init() - init hrtimer in a given context
84  * @timer: pointer to the hrtimer object
85  * @cback: callback function to be fired
86  * @clock: clock id
87  * @hrtimer_mode: mode of hrtimer
88  *
89  * starts hrtimer in a context passed as per the context
90  *
91  * Return: void
92  */
93 static inline void  __qdf_hrtimer_init(__qdf_hrtimer_data_t *timer,
94 				       void *cback,
95 				       enum qdf_clock_id clock,
96 				       enum qdf_hrtimer_mode mode,
97 				       enum qdf_context_mode ctx)
98 {
99 	struct hrtimer *hrtimer = &timer->u.hrtimer;
100 	struct tasklet_hrtimer *tasklet_hrtimer = &timer->u.tasklet_hrtimer;
101 
102 	timer->ctx = ctx;
103 
104 	if (timer->ctx == QDF_CONTEXT_HARDWARE) {
105 		hrtimer_init(hrtimer, clock, mode);
106 		hrtimer->function = cback;
107 	} else if (timer->ctx == QDF_CONTEXT_TASKLET) {
108 		tasklet_hrtimer_init(tasklet_hrtimer, cback, clock, mode);
109 	}
110 }
111 
112 /**
113  * __qdf_hrtimer_kill() - kills hrtimer in given context
114  * @timer: pointer to the hrtimer object
115  *
116  * kills hrtimer in given context
117  *
118  * Return: void
119  */
120 static inline
121 void __qdf_hrtimer_kill(__qdf_hrtimer_data_t *timer)
122 {
123 	if (timer->ctx == QDF_CONTEXT_HARDWARE)
124 		hrtimer_cancel(&timer->u.hrtimer);
125 	else if (timer->ctx == QDF_CONTEXT_TASKLET)
126 		tasklet_hrtimer_cancel(&timer->u.tasklet_hrtimer);
127 }
128 
129 /**
130  * __qdf_hrtimer_get_remaining() - check remaining time in the timer
131  * @timer: pointer to the hrtimer object
132  *
133  * check whether the timer is on one of the queues
134  *
135  * Return: remaining time as ktime object
136  */
137 static inline ktime_t __qdf_hrtimer_get_remaining(__qdf_hrtimer_data_t *timer)
138 {
139 	struct hrtimer *hrtimer = &timer->u.hrtimer;
140 	struct tasklet_hrtimer *tasklet_hrtimer = &timer->u.tasklet_hrtimer;
141 
142 	if (timer->ctx == QDF_CONTEXT_HARDWARE)
143 		return hrtimer_get_remaining(hrtimer);
144 	else
145 		return hrtimer_get_remaining(&tasklet_hrtimer->timer);
146 }
147 
148 /**
149  * __qdf_hrtimer_is_queued() - check whether the timer is on one of the queues
150  * @timer: pointer to the hrtimer object
151  *
152  * check whether the timer is on one of the queues
153  *
154  * Return: false when the timer was not in queue
155  *         true when the timer was in queue
156  */
157 static inline bool __qdf_hrtimer_is_queued(__qdf_hrtimer_data_t *timer)
158 {
159 	struct hrtimer *hrtimer = &timer->u.hrtimer;
160 	struct tasklet_hrtimer *tasklet_hrtimer = &timer->u.tasklet_hrtimer;
161 
162 	if (timer->ctx == QDF_CONTEXT_HARDWARE)
163 		return hrtimer_is_queued(hrtimer);
164 	else
165 		return hrtimer_is_queued(&tasklet_hrtimer->timer);
166 }
167 
168 /**
169  * __qdf_hrtimer_callback_running() - check if callback is running
170  * @timer: pointer to the hrtimer object
171  *
172  * check whether the timer is running the callback function
173  *
174  * Return: false when callback is not running
175  *         true when callback is running
176  */
177 static inline bool __qdf_hrtimer_callback_running(__qdf_hrtimer_data_t *timer)
178 {
179 	struct hrtimer *hrtimer = &timer->u.hrtimer;
180 	struct tasklet_hrtimer *tasklet_hrtimer = &timer->u.tasklet_hrtimer;
181 
182 	if (timer->ctx == QDF_CONTEXT_HARDWARE)
183 		return hrtimer_callback_running(hrtimer);
184 	else
185 		return hrtimer_callback_running(&tasklet_hrtimer->timer);
186 }
187 
188 /**
189  * __qdf_hrtimer_active() - check if timer is active
190  * @timer: pointer to the hrtimer object
191  *
192  * Check if timer is active. A timer is active, when it is enqueued into
193  * the rbtree or the callback function is running.
194  *
195  * Return: false if timer is not active
196  *         true if timer is active
197  */
198 static inline bool __qdf_hrtimer_active(__qdf_hrtimer_data_t *timer)
199 {
200 	struct hrtimer *hrtimer = &timer->u.hrtimer;
201 	struct tasklet_hrtimer *tasklet_hrtimer = &timer->u.tasklet_hrtimer;
202 
203 	if (timer->ctx == QDF_CONTEXT_HARDWARE)
204 		return hrtimer_active(hrtimer);
205 	else
206 		return hrtimer_active(&tasklet_hrtimer->timer);
207 }
208 
209 /**
210  * __qdf_hrtimer_cb_get_time() - get remaining time in callback
211  * @timer: pointer to the hrtimer object
212  *
213  * Get remaining time in the hrtimer callback
214  *
215  * Return: time remaining as ktime object
216  */
217 static inline ktime_t __qdf_hrtimer_cb_get_time(__qdf_hrtimer_data_t *timer)
218 {
219 	struct hrtimer *hrtimer = &timer->u.hrtimer;
220 	struct tasklet_hrtimer *tasklet_hrtimer = &timer->u.tasklet_hrtimer;
221 
222 	if (timer->ctx == QDF_CONTEXT_HARDWARE)
223 		return hrtimer_cb_get_time(hrtimer);
224 	else
225 		return hrtimer_cb_get_time(&tasklet_hrtimer->timer);
226 }
227 
228 /**
229  * __qdf_hrtimer_forward() - forward the hrtimer
230  * @timer: pointer to the hrtimer object
231  * @now: current ktime
232  * @interval: interval to forward as ktime object
233  *
234  * Forward the timer expiry so it will expire in the future
235  *
236  * Return:the number of overruns
237  */
238 static inline uint64_t __qdf_hrtimer_forward(__qdf_hrtimer_data_t *timer,
239 					     ktime_t now,
240 					     ktime_t interval)
241 {
242 	struct hrtimer *hrtimer = &timer->u.hrtimer;
243 	struct tasklet_hrtimer *tasklet_hrtimer = &timer->u.tasklet_hrtimer;
244 
245 	if (timer->ctx == QDF_CONTEXT_HARDWARE)
246 		return hrtimer_forward(hrtimer, now, interval);
247 	else
248 		return hrtimer_forward(&tasklet_hrtimer->timer, now, interval);
249 }
250 
251 #endif /* _I_QDF_HRTIMER_H */
252