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_timer 21 * This file provides OS dependent timer API's. 22 */ 23 24 #ifndef _I_QDF_TIMER_H 25 #define _I_QDF_TIMER_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 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) 33 #include <linux/sched/task_stack.h> 34 #endif 35 36 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0) 37 struct __qdf_timer_t { 38 struct timer_list os_timer; 39 qdf_timer_func_t callback; 40 void *context; 41 }; 42 #else 43 typedef struct timer_list __qdf_timer_t; 44 #endif 45 46 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0) 47 48 static inline void __os_timer_shim(struct timer_list *os_timer) 49 { 50 struct __qdf_timer_t *timer = from_timer(timer, os_timer, os_timer); 51 52 timer->callback(timer->context); 53 } 54 55 static inline QDF_STATUS __qdf_timer_init(struct __qdf_timer_t *timer, 56 qdf_timer_func_t func, void *arg, 57 QDF_TIMER_TYPE type) 58 { 59 struct timer_list *os_timer = &timer->os_timer; 60 uint32_t flags = 0; 61 62 timer->callback = func; 63 timer->context = arg; 64 65 if (type == QDF_TIMER_TYPE_SW) 66 flags |= TIMER_DEFERRABLE; 67 68 if (object_is_on_stack(os_timer)) 69 timer_setup_on_stack(os_timer, __os_timer_shim, flags); 70 else 71 timer_setup(os_timer, __os_timer_shim, flags); 72 73 return QDF_STATUS_SUCCESS; 74 } 75 76 static inline void __qdf_timer_start(struct __qdf_timer_t *timer, uint32_t msec) 77 { 78 struct timer_list *os_timer = &timer->os_timer; 79 80 os_timer->expires = jiffies + msecs_to_jiffies(msec); 81 add_timer(os_timer); 82 } 83 84 static inline void __qdf_timer_mod(struct __qdf_timer_t *timer, uint32_t msec) 85 { 86 mod_timer(&timer->os_timer, jiffies + msecs_to_jiffies(msec)); 87 } 88 89 static inline bool __qdf_timer_stop(struct __qdf_timer_t *timer) 90 { 91 return !!del_timer(&timer->os_timer); 92 } 93 94 static inline void __qdf_timer_free(struct __qdf_timer_t *timer) 95 { 96 struct timer_list *os_timer = &timer->os_timer; 97 98 del_timer_sync(os_timer); 99 100 if (object_is_on_stack(os_timer)) 101 destroy_timer_on_stack(os_timer); 102 } 103 104 static inline bool __qdf_timer_sync_cancel(struct __qdf_timer_t *timer) 105 { 106 return del_timer_sync(&timer->os_timer); 107 } 108 #else 109 110 #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 9, 0) 111 #define setup_deferrable_timer(timer, fn, data) \ 112 __setup_timer((timer), (fn), (data), TIMER_DEFERRABLE) 113 #endif 114 115 typedef void (*__legacy_timer_callback_t)(unsigned long arg); 116 117 static inline QDF_STATUS __qdf_timer_init(__qdf_timer_t *os_timer, 118 qdf_timer_func_t func, void *arg, 119 QDF_TIMER_TYPE type) 120 { 121 bool is_on_stack = object_is_on_stack(os_timer); 122 __legacy_timer_callback_t callback = (__legacy_timer_callback_t)func; 123 unsigned long ctx = (unsigned long)arg; 124 125 if (type == QDF_TIMER_TYPE_SW) { 126 if (is_on_stack) 127 setup_deferrable_timer_on_stack(os_timer, callback, 128 ctx); 129 else 130 setup_deferrable_timer(os_timer, callback, ctx); 131 } else { 132 if (is_on_stack) 133 setup_timer_on_stack(os_timer, callback, ctx); 134 else 135 setup_timer(os_timer, callback, ctx); 136 } 137 138 return QDF_STATUS_SUCCESS; 139 } 140 141 static inline void __qdf_timer_start(__qdf_timer_t *timer, uint32_t msec) 142 { 143 timer->expires = jiffies + msecs_to_jiffies(msec); 144 add_timer(timer); 145 } 146 147 static inline void __qdf_timer_mod(__qdf_timer_t *timer, uint32_t msec) 148 { 149 mod_timer(timer, jiffies + msecs_to_jiffies(msec)); 150 } 151 152 static inline bool __qdf_timer_stop(__qdf_timer_t *timer) 153 { 154 return !!del_timer(timer); 155 } 156 157 static inline void __qdf_timer_free(__qdf_timer_t *timer) 158 { 159 del_timer_sync(timer); 160 161 if (object_is_on_stack(timer)) 162 destroy_timer_on_stack(timer); 163 } 164 165 static inline bool __qdf_timer_sync_cancel(__qdf_timer_t *timer) 166 { 167 return del_timer_sync(timer); 168 } 169 170 #endif /* KERNEL_VERSION(4, 15, 0)*/ 171 #endif /* _I_QDF_TIMER_H */ 172