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