1 /* 2 * Copyright (c) 2014-2021 The Linux Foundation. All rights reserved. 3 * Copyright (c) 2022 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 typedef struct workqueue_struct __qdf_workqueue_t; 35 36 /** 37 * typedef struct __qdf_work_t - wrapper around the real task func 38 * @work: Instance of work 39 * @fn: function pointer to the handler 40 * @arg: pointer to argument 41 */ 42 typedef struct { 43 struct work_struct work; 44 qdf_defer_fn_t fn; 45 void *arg; 46 } __qdf_work_t; 47 48 /** 49 * typedef struct __qdf_bh_t - wrapper around the real task func 50 * @bh: Instance of the bottom half 51 * @fn: function pointer to the handler 52 * @arg: pointer to argument 53 */ 54 typedef struct { 55 struct tasklet_struct bh; 56 qdf_defer_fn_t fn; 57 void *arg; 58 } __qdf_bh_t; 59 60 /** 61 * __qdf_defer_func() - Linux-specific defer work handler 62 * @work: Pointer to defer work 63 * 64 * This function services all Linux-specific deferred work 65 * and dispatches them to the correct handler using the 66 * abstracted functional interface. 67 * 68 * Return: none 69 */ 70 void __qdf_defer_func(struct work_struct *work); 71 72 /** 73 * __qdf_bh_func() - bottom half handler 74 * @arg: Pointer to bottom half abstraction 75 * 76 * This function services all Linux-specific bottom halves 77 * and dispatches them to the correct handler using the 78 * abstracted functional interface. 79 * 80 * Return: none 81 */ 82 void __qdf_bh_func(unsigned long arg); 83 84 /** 85 * __qdf_init_work - Initialize a work/task queue, This runs in non-interrupt 86 * context, so can be preempted by H/W & S/W intr 87 * @work: pointer to work 88 * @func: deferred function to run at bottom half non-interrupt context. 89 * @arg: argument for the deferred function 90 * Return: none 91 */ 92 static inline QDF_STATUS 93 __qdf_init_work(__qdf_work_t *work, qdf_defer_fn_t func, void *arg) 94 { 95 work->fn = func; 96 work->arg = arg; 97 INIT_WORK(&work->work, __qdf_defer_func); 98 return QDF_STATUS_SUCCESS; 99 } 100 101 /** 102 * __qdf_queue_work - Queue the work/task 103 * @wqueue: pointer to workqueue 104 * @work: pointer to work 105 * Return: false if work was already on a queue, true otherwise 106 */ 107 static inline bool 108 __qdf_queue_work(__qdf_workqueue_t *wqueue, __qdf_work_t *work) 109 { 110 return queue_work(wqueue, &work->work); 111 } 112 113 /** 114 * __qdf_sched_work - Schedule a deferred task on non-interrupt context 115 * @work: pointer to work 116 * Return: none 117 */ 118 static inline QDF_STATUS __qdf_sched_work(__qdf_work_t *work) 119 { 120 schedule_work(&work->work); 121 return QDF_STATUS_SUCCESS; 122 } 123 124 /** 125 * __qdf_cancel_work() - Cancel a work 126 * @work: pointer to work 127 * Return: true if work was pending, false otherwise 128 */ 129 static inline bool __qdf_cancel_work(__qdf_work_t *work) 130 { 131 return cancel_work_sync(&work->work); 132 } 133 134 /** 135 * __qdf_flush_work - Flush a deferred task on non-interrupt context 136 * @work: pointer to work 137 * Return: none 138 */ 139 static inline uint32_t __qdf_flush_work(__qdf_work_t *work) 140 { 141 flush_work(&work->work); 142 return QDF_STATUS_SUCCESS; 143 } 144 145 /** 146 * __qdf_create_workqueue - create a workqueue, This runs in non-interrupt 147 * context, so can be preempted by H/W & S/W intr 148 * @name: string 149 * Return: pointer of type qdf_workqueue_t 150 */ 151 static inline __qdf_workqueue_t *__qdf_create_workqueue(char *name) 152 { 153 return create_workqueue(name); 154 } 155 156 /** 157 * __qdf_create_singlethread_workqueue() - create a single threaded workqueue 158 * @name: string 159 * 160 * This API creates a dedicated work queue with a single worker thread to avoid 161 * wasting unnecessary resources when works which needs to be submitted in this 162 * queue are not very critical and frequent. 163 * 164 * Return: pointer of type qdf_workqueue_t 165 */ 166 static inline __qdf_workqueue_t *__qdf_create_singlethread_workqueue(char *name) 167 { 168 return create_singlethread_workqueue(name); 169 } 170 171 /** 172 * __qdf_alloc_high_prior_ordered_workqueue - alloc high-prior ordered workqueue 173 * @name: string 174 * 175 * Return: pointer of type qdf_workqueue_t 176 */ 177 static inline 178 __qdf_workqueue_t *__qdf_alloc_high_prior_ordered_workqueue(char *name) 179 { 180 return alloc_ordered_workqueue(name, WQ_HIGHPRI); 181 } 182 183 /** 184 * __qdf_alloc_unbound_workqueue - alloc an unbound workqueue 185 * @name: string 186 * 187 * Return: pointer of type qdf_workqueue_t 188 */ 189 static inline __qdf_workqueue_t *__qdf_alloc_unbound_workqueue(char *name) 190 { 191 return alloc_workqueue(name, WQ_UNBOUND, 0); 192 } 193 194 /** 195 * __qdf_flush_workqueue - flush the workqueue 196 * @wqueue: pointer to workqueue 197 * Return: none 198 */ 199 static inline void __qdf_flush_workqueue(__qdf_workqueue_t *wqueue) 200 { 201 flush_workqueue(wqueue); 202 } 203 204 /** 205 * __qdf_destroy_workqueue - Destroy the workqueue 206 * @wqueue: pointer to workqueue 207 * Return: none 208 */ 209 static inline void __qdf_destroy_workqueue(__qdf_workqueue_t *wqueue) 210 { 211 destroy_workqueue(wqueue); 212 } 213 214 /** 215 * __qdf_init_bh - creates the Bottom half deferred handler 216 * @bh: pointer to bottom 217 * @func: deferred function to run at bottom half interrupt context. 218 * @arg: argument for the deferred function 219 * 220 * Return: none 221 */ 222 static inline void __qdf_init_bh(__qdf_bh_t *bh, qdf_defer_fn_t func, void *arg) 223 { 224 bh->fn = func; 225 bh->arg = arg; 226 tasklet_init(&bh->bh, __qdf_bh_func, (unsigned long)bh); 227 } 228 229 /** 230 * __qdf_sched_bh - schedule a bottom half (DPC) 231 * @bh: pointer to bottom 232 * 233 * Return: none 234 */ 235 static inline void __qdf_sched_bh(__qdf_bh_t *bh) 236 { 237 tasklet_schedule(&bh->bh); 238 } 239 240 /** 241 * __qdf_disable_work - disable the deferred task (synchronous) 242 * @work: pointer to work 243 * Return: unsigned int 244 */ 245 static inline QDF_STATUS __qdf_disable_work(__qdf_work_t *work) 246 { 247 if (cancel_work_sync(&work->work)) 248 return QDF_STATUS_E_ALREADY; 249 250 return QDF_STATUS_SUCCESS; 251 } 252 253 /** 254 * __qdf_disable_bh - destroy the bh (synchronous) 255 * @bh: pointer to bottom 256 * 257 * Return: none 258 */ 259 static inline void __qdf_disable_bh(__qdf_bh_t *bh) 260 { 261 tasklet_kill(&bh->bh); 262 } 263 264 /** 265 * __qdf_local_bh_disable - disables softirq and tasklet processing 266 * on the local processor 267 * 268 * Return: none 269 */ 270 static inline void __qdf_local_bh_disable(void) 271 { 272 local_bh_disable(); 273 } 274 275 /** 276 * __qdf_local_bh_enable - Enables softirq and tasklet processing 277 * on the local processor 278 * 279 * Return: none 280 */ 281 static inline void __qdf_local_bh_enable(void) 282 { 283 local_bh_enable(); 284 } 285 #endif /*_I_QDF_DEFER_H*/ 286