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