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