1 /* 2 * Copyright (c) 2014-2021 The Linux Foundation. All rights reserved. 3 * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for 6 * any purpose with or without fee is hereby granted, provided that the 7 * above copyright notice and this permission notice appear in all 8 * copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 11 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 13 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 16 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 17 * PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 /** 21 * DOC: i_qdf_defer.h 22 * This file provides OS dependent deferred API's. 23 */ 24 25 #ifndef _I_QDF_DEFER_H 26 #define _I_QDF_DEFER_H 27 28 #include <linux/workqueue.h> 29 #include <linux/interrupt.h> 30 #include <qdf_types.h> 31 #include <qdf_status.h> 32 #include <qdf_trace.h> 33 34 /** 35 * typedef __qdf_workqueue_t - qdf_workqueue_t abstraction 36 */ 37 typedef struct workqueue_struct __qdf_workqueue_t; 38 39 /** 40 * typedef __qdf_work_t - wrapper around the real task func 41 * @work: Instance of work 42 * @fn: function pointer to the handler 43 * @arg: pointer to argument 44 */ 45 typedef struct { 46 struct work_struct work; 47 qdf_defer_fn_t fn; 48 void *arg; 49 } __qdf_work_t; 50 51 /** 52 * typedef __qdf_bh_t - wrapper around the real task func 53 * @bh: Instance of the bottom half 54 * @fn: function pointer to the handler 55 * @arg: pointer to argument 56 */ 57 typedef struct { 58 struct tasklet_struct bh; 59 qdf_defer_fn_t fn; 60 void *arg; 61 } __qdf_bh_t; 62 63 /** 64 * __qdf_defer_func() - Linux-specific defer work handler 65 * @work: Pointer to defer work 66 * 67 * This function services all Linux-specific deferred work 68 * and dispatches them to the correct handler using the 69 * abstracted functional interface. 70 * 71 * Return: none 72 */ 73 void __qdf_defer_func(struct work_struct *work); 74 75 /** 76 * __qdf_bh_func() - bottom half handler 77 * @arg: Pointer to bottom half abstraction 78 * 79 * This function services all Linux-specific bottom halves 80 * and dispatches them to the correct handler using the 81 * abstracted functional interface. 82 * 83 * Return: none 84 */ 85 void __qdf_bh_func(unsigned long arg); 86 87 /** 88 * __qdf_init_work - Initialize a work/task queue, This runs in non-interrupt 89 * context, so can be preempted by H/W & S/W intr 90 * @work: pointer to work 91 * @func: deferred function to run at bottom half non-interrupt context. 92 * @arg: argument for the deferred function 93 * Return: none 94 */ 95 static inline QDF_STATUS 96 __qdf_init_work(__qdf_work_t *work, qdf_defer_fn_t func, void *arg) 97 { 98 work->fn = func; 99 work->arg = arg; 100 INIT_WORK(&work->work, __qdf_defer_func); 101 return QDF_STATUS_SUCCESS; 102 } 103 104 /** 105 * __qdf_queue_work - Queue the work/task 106 * @wqueue: pointer to workqueue 107 * @work: pointer to work 108 * Return: false if work was already on a queue, true otherwise 109 */ 110 static inline bool 111 __qdf_queue_work(__qdf_workqueue_t *wqueue, __qdf_work_t *work) 112 { 113 return queue_work(wqueue, &work->work); 114 } 115 116 /** 117 * __qdf_sched_work - Schedule a deferred task on non-interrupt context 118 * @work: pointer to work 119 * 120 * Return: false if work was already on a global queue, true otherwise 121 */ 122 static inline bool __qdf_sched_work(__qdf_work_t *work) 123 { 124 return schedule_work(&work->work); 125 } 126 127 /** 128 * __qdf_cancel_work() - Cancel a work 129 * @work: pointer to work 130 * Return: true if work was pending, false otherwise 131 */ 132 static inline bool __qdf_cancel_work(__qdf_work_t *work) 133 { 134 return cancel_work_sync(&work->work); 135 } 136 137 /** 138 * __qdf_flush_work - Flush a deferred task on non-interrupt context 139 * @work: pointer to work 140 * Return: none 141 */ 142 static inline uint32_t __qdf_flush_work(__qdf_work_t *work) 143 { 144 flush_work(&work->work); 145 return QDF_STATUS_SUCCESS; 146 } 147 148 /** 149 * __qdf_create_workqueue - create a workqueue, This runs in non-interrupt 150 * context, so can be preempted by H/W & S/W intr 151 * @name: string 152 * Return: pointer of type qdf_workqueue_t 153 */ 154 static inline __qdf_workqueue_t *__qdf_create_workqueue(char *name) 155 { 156 return create_workqueue(name); 157 } 158 159 /** 160 * __qdf_create_singlethread_workqueue() - create a single threaded workqueue 161 * @name: string 162 * 163 * This API creates a dedicated work queue with a single worker thread to avoid 164 * wasting unnecessary resources when works which needs to be submitted in this 165 * queue are not very critical and frequent. 166 * 167 * Return: pointer of type qdf_workqueue_t 168 */ 169 static inline __qdf_workqueue_t *__qdf_create_singlethread_workqueue(char *name) 170 { 171 return create_singlethread_workqueue(name); 172 } 173 174 /** 175 * __qdf_alloc_high_prior_ordered_workqueue - alloc high-prior ordered workqueue 176 * @name: string 177 * 178 * Return: pointer of type qdf_workqueue_t 179 */ 180 static inline 181 __qdf_workqueue_t *__qdf_alloc_high_prior_ordered_workqueue(char *name) 182 { 183 return alloc_ordered_workqueue(name, WQ_HIGHPRI); 184 } 185 186 /** 187 * __qdf_alloc_unbound_workqueue - alloc an unbound workqueue 188 * @name: string 189 * 190 * Return: pointer of type qdf_workqueue_t 191 */ 192 static inline __qdf_workqueue_t *__qdf_alloc_unbound_workqueue(char *name) 193 { 194 return alloc_workqueue(name, WQ_UNBOUND, 0); 195 } 196 197 /** 198 * __qdf_flush_workqueue - flush the workqueue 199 * @wqueue: pointer to workqueue 200 * Return: none 201 */ 202 static inline void __qdf_flush_workqueue(__qdf_workqueue_t *wqueue) 203 { 204 flush_workqueue(wqueue); 205 } 206 207 /** 208 * __qdf_destroy_workqueue - Destroy the workqueue 209 * @wqueue: pointer to workqueue 210 * Return: none 211 */ 212 static inline void __qdf_destroy_workqueue(__qdf_workqueue_t *wqueue) 213 { 214 destroy_workqueue(wqueue); 215 } 216 217 /** 218 * __qdf_init_bh - creates the Bottom half deferred handler 219 * @bh: pointer to bottom 220 * @func: deferred function to run at bottom half interrupt context. 221 * @arg: argument for the deferred function 222 * 223 * Return: none 224 */ 225 static inline void __qdf_init_bh(__qdf_bh_t *bh, qdf_defer_fn_t func, void *arg) 226 { 227 bh->fn = func; 228 bh->arg = arg; 229 tasklet_init(&bh->bh, __qdf_bh_func, (unsigned long)bh); 230 } 231 232 /** 233 * __qdf_sched_bh - schedule a bottom half (DPC) 234 * @bh: pointer to bottom 235 * 236 * Return: none 237 */ 238 static inline void __qdf_sched_bh(__qdf_bh_t *bh) 239 { 240 tasklet_schedule(&bh->bh); 241 } 242 243 /** 244 * __qdf_disable_work - disable the deferred task (synchronous) 245 * @work: pointer to work 246 * Return: unsigned int 247 */ 248 static inline QDF_STATUS __qdf_disable_work(__qdf_work_t *work) 249 { 250 if (cancel_work_sync(&work->work)) 251 return QDF_STATUS_E_ALREADY; 252 253 return QDF_STATUS_SUCCESS; 254 } 255 256 /** 257 * __qdf_disable_bh - destroy the bh (synchronous) 258 * @bh: pointer to bottom 259 * 260 * Return: none 261 */ 262 static inline void __qdf_disable_bh(__qdf_bh_t *bh) 263 { 264 tasklet_kill(&bh->bh); 265 } 266 267 /** 268 * __qdf_local_bh_disable - disables softirq and tasklet processing 269 * on the local processor 270 * 271 * Return: none 272 */ 273 static inline void __qdf_local_bh_disable(void) 274 { 275 local_bh_disable(); 276 } 277 278 /** 279 * __qdf_local_bh_enable - Enables softirq and tasklet processing 280 * on the local processor 281 * 282 * Return: none 283 */ 284 static inline void __qdf_local_bh_enable(void) 285 { 286 local_bh_enable(); 287 } 288 #endif /*_I_QDF_DEFER_H*/ 289