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