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: void 70 */ 71 static inline 72 void __qdf_hrtimer_cancel(__qdf_hrtimer_data_t *timer) 73 { 74 if (timer->ctx == QDF_CONTEXT_HARDWARE) 75 hrtimer_cancel(&timer->u.hrtimer); 76 else if (timer->ctx == QDF_CONTEXT_TASKLET) 77 hrtimer_cancel(&timer->u.tasklet_hrtimer.timer); 78 } 79 80 /** 81 * __qdf_hrtimer_init() - init hrtimer in a given context 82 * @timer: pointer to the hrtimer object 83 * @cback: callback function to be fired 84 * @clock: clock id 85 * @hrtimer_mode: mode of hrtimer 86 * 87 * starts hrtimer in a context passed as per the context 88 * 89 * Return: void 90 */ 91 static inline void __qdf_hrtimer_init(__qdf_hrtimer_data_t *timer, 92 void *cback, 93 enum qdf_clock_id clock, 94 enum qdf_hrtimer_mode mode, 95 enum qdf_context_mode ctx) 96 { 97 struct hrtimer *hrtimer = &timer->u.hrtimer; 98 struct tasklet_hrtimer *tasklet_hrtimer = &timer->u.tasklet_hrtimer; 99 100 timer->ctx = ctx; 101 102 if (timer->ctx == QDF_CONTEXT_HARDWARE) { 103 hrtimer_init(hrtimer, clock, mode); 104 hrtimer->function = cback; 105 } else if (timer->ctx == QDF_CONTEXT_TASKLET) { 106 tasklet_hrtimer_init(tasklet_hrtimer, cback, clock, mode); 107 } 108 } 109 110 /** 111 * __qdf_hrtimer_kill() - kills hrtimer in given context 112 * @timer: pointer to the hrtimer object 113 * 114 * kills hrtimer in given context 115 * 116 * Return: void 117 */ 118 static inline 119 void __qdf_hrtimer_kill(__qdf_hrtimer_data_t *timer) 120 { 121 if (timer->ctx == QDF_CONTEXT_HARDWARE) 122 hrtimer_cancel(&timer->u.hrtimer); 123 else if (timer->ctx == QDF_CONTEXT_TASKLET) 124 tasklet_hrtimer_cancel(&timer->u.tasklet_hrtimer); 125 } 126 127 /** 128 * __qdf_hrtimer_get_remaining() - check remaining time in the timer 129 * @timer: pointer to the hrtimer object 130 * 131 * check whether the timer is on one of the queues 132 * 133 * Return: remaining time as ktime object 134 */ 135 static inline ktime_t __qdf_hrtimer_get_remaining(__qdf_hrtimer_data_t *timer) 136 { 137 struct hrtimer *hrtimer = &timer->u.hrtimer; 138 struct tasklet_hrtimer *tasklet_hrtimer = &timer->u.tasklet_hrtimer; 139 140 if (timer->ctx == QDF_CONTEXT_HARDWARE) 141 return hrtimer_get_remaining(hrtimer); 142 else 143 return hrtimer_get_remaining(&tasklet_hrtimer->timer); 144 } 145 146 /** 147 * __qdf_hrtimer_is_queued() - check whether the timer is on one of the queues 148 * @timer: pointer to the hrtimer object 149 * 150 * check whether the timer is on one of the queues 151 * 152 * Return: false when the timer was not in queue 153 * true when the timer was in queue 154 */ 155 static inline bool __qdf_hrtimer_is_queued(__qdf_hrtimer_data_t *timer) 156 { 157 struct hrtimer *hrtimer = &timer->u.hrtimer; 158 struct tasklet_hrtimer *tasklet_hrtimer = &timer->u.tasklet_hrtimer; 159 160 if (timer->ctx == QDF_CONTEXT_HARDWARE) 161 return hrtimer_is_queued(hrtimer); 162 else 163 return hrtimer_is_queued(&tasklet_hrtimer->timer); 164 } 165 166 /** 167 * __qdf_hrtimer_callback_running() - check if callback is running 168 * @timer: pointer to the hrtimer object 169 * 170 * check whether the timer is running the callback function 171 * 172 * Return: false when callback is not running 173 * true when callback is running 174 */ 175 static inline bool __qdf_hrtimer_callback_running(__qdf_hrtimer_data_t *timer) 176 { 177 struct hrtimer *hrtimer = &timer->u.hrtimer; 178 struct tasklet_hrtimer *tasklet_hrtimer = &timer->u.tasklet_hrtimer; 179 180 if (timer->ctx == QDF_CONTEXT_HARDWARE) 181 return hrtimer_callback_running(hrtimer); 182 else 183 return hrtimer_callback_running(&tasklet_hrtimer->timer); 184 } 185 186 /** 187 * __qdf_hrtimer_active() - check if timer is active 188 * @timer: pointer to the hrtimer object 189 * 190 * Check if timer is active. A timer is active, when it is enqueued into 191 * the rbtree or the callback function is running. 192 * 193 * Return: false if timer is not active 194 * true if timer is active 195 */ 196 static inline bool __qdf_hrtimer_active(__qdf_hrtimer_data_t *timer) 197 { 198 struct hrtimer *hrtimer = &timer->u.hrtimer; 199 struct tasklet_hrtimer *tasklet_hrtimer = &timer->u.tasklet_hrtimer; 200 201 if (timer->ctx == QDF_CONTEXT_HARDWARE) 202 return hrtimer_active(hrtimer); 203 else 204 return hrtimer_active(&tasklet_hrtimer->timer); 205 } 206 207 /** 208 * __qdf_hrtimer_cb_get_time() - get remaining time in callback 209 * @timer: pointer to the hrtimer object 210 * 211 * Get remaining time in the hrtimer callback 212 * 213 * Return: time remaining as ktime object 214 */ 215 static inline ktime_t __qdf_hrtimer_cb_get_time(__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_cb_get_time(hrtimer); 222 else 223 return hrtimer_cb_get_time(&tasklet_hrtimer->timer); 224 } 225 226 /** 227 * __qdf_hrtimer_forward() - forward the hrtimer 228 * @timer: pointer to the hrtimer object 229 * @now: current ktime 230 * @interval: interval to forward as ktime object 231 * 232 * Forward the timer expiry so it will expire in the future 233 * 234 * Return:the number of overruns 235 */ 236 static inline uint64_t __qdf_hrtimer_forward(__qdf_hrtimer_data_t *timer, 237 ktime_t now, 238 ktime_t interval) 239 { 240 struct hrtimer *hrtimer = &timer->u.hrtimer; 241 struct tasklet_hrtimer *tasklet_hrtimer = &timer->u.tasklet_hrtimer; 242 243 if (timer->ctx == QDF_CONTEXT_HARDWARE) 244 return hrtimer_forward(hrtimer, now, interval); 245 else 246 return hrtimer_forward(&tasklet_hrtimer->timer, now, interval); 247 } 248 249 #endif /* _I_QDF_HRTIMER_H */ 250