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