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: qdf_defer.h 22 * This file abstracts deferred execution API's. 23 */ 24 25 #ifndef __QDF_DEFER_H 26 #define __QDF_DEFER_H 27 28 #include <qdf_types.h> 29 #include <i_qdf_defer.h> 30 31 /** 32 * TODO This implements work queues (worker threads, kernel threads etc.). 33 * Note that there is no cancel on a scheduled work. You cannot free a work 34 * item if its queued. You cannot know if a work item is queued or not unless 35 * its running, hence you know its not queued. 36 * 37 * so if, say, a module is asked to unload itself, how exactly will it make 38 * sure that the work's not queued, for OS'es that dont provide such a 39 * mechanism?? 40 */ 41 42 /* 43 * Representation of a work queue. 44 */ 45 typedef __qdf_work_t qdf_work_t; 46 typedef __qdf_workqueue_t qdf_workqueue_t; 47 48 /* 49 * Representation of a bottom half. 50 */ 51 typedef __qdf_bh_t qdf_bh_t; 52 53 #ifdef ENHANCED_OS_ABSTRACTION 54 /** 55 * qdf_create_bh - creates the bottom half deferred handler 56 * @bh: pointer to bottom 57 * @func: deferred function to run at bottom half interrupt context. 58 * @arg: argument for the deferred function 59 * Return: none 60 */ 61 void 62 qdf_create_bh(qdf_bh_t *bh, qdf_defer_fn_t func, void *arg); 63 64 /** 65 * qdf_sched - schedule a bottom half (DPC) 66 * @bh: pointer to bottom 67 * Return: none 68 */ 69 void qdf_sched_bh(qdf_bh_t *bh); 70 71 /** 72 * qdf_destroy_bh - destroy the bh (synchronous) 73 * @bh: pointer to bottom 74 * Return: none 75 */ 76 void qdf_destroy_bh(qdf_bh_t *bh); 77 78 /** 79 * qdf_create_workqueue - create a workqueue, This runs in non-interrupt 80 * context, so can be preempted by H/W & S/W intr 81 * @name: string 82 * 83 * Return: pointer of type qdf_workqueue_t 84 */ 85 qdf_workqueue_t *qdf_create_workqueue(char *name); 86 87 /** 88 * qdf_create_singlethread_workqueue() - create a single threaded workqueue 89 * @name: string 90 * 91 * This API creates a dedicated work queue with a single worker thread to avoid 92 * wasting unnecessary resources when works which needs to be submitted in this 93 * queue are not very critical and frequent. 94 * 95 * Return: pointer of type qdf_workqueue_t 96 */ 97 qdf_workqueue_t *qdf_create_singlethread_workqueue(char *name); 98 99 /** 100 * qdf_alloc_unbound_workqueue - allocate an unbound workqueue 101 * @name: string 102 * 103 * Return: pointer of type qdf_workqueue_t 104 */ 105 qdf_workqueue_t *qdf_alloc_unbound_workqueue(char *name); 106 107 /** 108 * qdf_destroy_workqueue - Destroy the workqueue 109 * @hdl: OS handle 110 * @wqueue: pointer to workqueue 111 * 112 * Return: none 113 */ 114 void qdf_destroy_workqueue(qdf_handle_t hdl, qdf_workqueue_t *wqueue); 115 116 /** 117 * qdf_cancel_work() - Cancel a work 118 * @work: pointer to work 119 * 120 * Cancel work and wait for its execution to finish. 121 * This function can be used even if the work re-queues 122 * itself or migrates to another workqueue. On return 123 * from this function, work is guaranteed to be not 124 * pending or executing on any CPU. The caller must 125 * ensure that the workqueue on which work was last 126 * queued can't be destroyed before this function returns. 127 * 128 * Return: true if work was pending, false otherwise 129 */ 130 bool qdf_cancel_work(qdf_work_t *work); 131 132 /** 133 * qdf_disable_work - disable the deferred task (synchronous) 134 * @work: pointer to work 135 * 136 * Return: unsigned int 137 */ 138 uint32_t qdf_disable_work(qdf_work_t *work); 139 140 /** 141 * qdf_flush_work - Flush a deferred task on non-interrupt context 142 * @work: pointer to work 143 * 144 * Wait until work has finished execution. work is guaranteed to be 145 * idle on return if it hasn't been requeued since flush started. 146 * 147 * Return: none 148 */ 149 void qdf_flush_work(qdf_work_t *work); 150 151 /** 152 * qdf_create_work - create a work/task queue, This runs in non-interrupt 153 * context, so can be preempted by H/W & S/W intr 154 * @hdl: OS handle 155 * @work: pointer to work 156 * @func: deferred function to run at bottom half non-interrupt context. 157 * @arg: argument for the deferred function 158 * 159 * Return: QDF status 160 */ 161 QDF_STATUS qdf_create_work(qdf_handle_t hdl, qdf_work_t *work, 162 qdf_defer_fn_t func, void *arg); 163 164 /** 165 * qdf_sched_work - Schedule a deferred task on non-interrupt context 166 * @hdl: OS handle 167 * @work: pointer to work 168 * 169 * Return: none 170 */ 171 void qdf_sched_work(qdf_handle_t hdl, qdf_work_t *work); 172 173 /** 174 * qdf_queue_work - Queue the work/task 175 * @hdl: OS handle 176 * @wqueue: pointer to workqueue 177 * @work: pointer to work 178 * 179 * Return: false if work was already on a queue, true otherwise 180 */ 181 bool 182 qdf_queue_work(qdf_handle_t hdl, qdf_workqueue_t *wqueue, qdf_work_t *work); 183 184 /** 185 * qdf_flush_workqueue - flush the workqueue 186 * @hdl: OS handle 187 * @wqueue: pointer to workqueue 188 * 189 * Return: none 190 */ 191 void qdf_flush_workqueue(qdf_handle_t hdl, qdf_workqueue_t *wqueue); 192 193 /** 194 * qdf_destroy_work - destroy the deferred task (synchronous) 195 * @hdl: OS handle 196 * @work: pointer to work 197 * 198 * Return: none 199 */ 200 void qdf_destroy_work(qdf_handle_t hdl, qdf_work_t *work); 201 #else 202 /** 203 * qdf_create_bh - creates the bottom half deferred handler 204 * @bh: pointer to bottom 205 * @func: deferred function to run at bottom half interrupt context. 206 * @arg: argument for the deferred function 207 * Return: none 208 */ 209 static inline void 210 qdf_create_bh(qdf_bh_t *bh, qdf_defer_fn_t func, void *arg) 211 { 212 __qdf_init_bh(bh, func, arg); 213 } 214 215 /** 216 * qdf_sched - schedule a bottom half (DPC) 217 * @bh: pointer to bottom 218 * Return: none 219 */ 220 static inline void qdf_sched_bh(qdf_bh_t *bh) 221 { 222 __qdf_sched_bh(bh); 223 } 224 225 /** 226 * qdf_destroy_bh - destroy the bh (synchronous) 227 * @bh: pointer to bottom 228 * Return: none 229 */ 230 static inline void qdf_destroy_bh(qdf_bh_t *bh) 231 { 232 __qdf_disable_bh(bh); 233 } 234 235 /*********************Non-Interrupt Context deferred Execution***************/ 236 237 /** 238 * qdf_create_work - create a work/task queue, This runs in non-interrupt 239 * context, so can be preempted by H/W & S/W intr 240 * @hdl: OS handle 241 * @work: pointer to work 242 * @func: deferred function to run at bottom half non-interrupt context. 243 * @arg: argument for the deferred function 244 * 245 * Return: QDF status 246 */ 247 static inline QDF_STATUS qdf_create_work(qdf_handle_t hdl, qdf_work_t *work, 248 qdf_defer_fn_t func, void *arg) 249 { 250 return __qdf_init_work(work, func, arg); 251 } 252 253 /** 254 * qdf_create_workqueue - create a workqueue, This runs in non-interrupt 255 * context, so can be preempted by H/W & S/W intr 256 * @name: string 257 * Return: pointer of type qdf_workqueue_t 258 */ 259 static inline qdf_workqueue_t *qdf_create_workqueue(char *name) 260 { 261 return __qdf_create_workqueue(name); 262 } 263 264 /** 265 * qdf_create_singlethread_workqueue() - create a single threaded workqueue 266 * @name: string 267 * 268 * This API creates a dedicated work queue with a single worker thread to avoid 269 * wasting unnecessary resources when works which needs to be submitted in this 270 * queue are not very critical and frequent. 271 * 272 * Return: pointer of type qdf_workqueue_t 273 */ 274 static inline qdf_workqueue_t *qdf_create_singlethread_workqueue(char *name) 275 { 276 return __qdf_create_singlethread_workqueue(name); 277 } 278 279 /** 280 * qdf_alloc_high_prior_ordered_workqueue - alloc high-prior ordered workqueue 281 * @name: string 282 * 283 * Return: pointer of type qdf_workqueue_t 284 */ 285 static inline 286 qdf_workqueue_t *qdf_alloc_high_prior_ordered_workqueue(char *name) 287 { 288 return __qdf_alloc_high_prior_ordered_workqueue(name); 289 } 290 291 /** 292 * qdf_alloc_unbound_workqueue - allocate an unbound workqueue 293 * @name: string 294 * 295 * Return: pointer of type qdf_workqueue_t 296 */ 297 static inline qdf_workqueue_t *qdf_alloc_unbound_workqueue(char *name) 298 { 299 return __qdf_alloc_unbound_workqueue(name); 300 } 301 302 /** 303 * qdf_queue_work - Queue the work/task 304 * @hdl: OS handle 305 * @wqueue: pointer to workqueue 306 * @work: pointer to work 307 * Return: false if work was already on a queue, true otherwise 308 */ 309 static inline bool 310 qdf_queue_work(qdf_handle_t hdl, qdf_workqueue_t *wqueue, qdf_work_t *work) 311 { 312 return __qdf_queue_work(wqueue, work); 313 } 314 315 /** 316 * qdf_flush_workqueue - flush the workqueue 317 * @hdl: OS handle 318 * @wqueue: pointer to workqueue 319 * Return: none 320 */ 321 static inline void qdf_flush_workqueue(qdf_handle_t hdl, 322 qdf_workqueue_t *wqueue) 323 { 324 return __qdf_flush_workqueue(wqueue); 325 } 326 327 /** 328 * qdf_destroy_workqueue - Destroy the workqueue 329 * @hdl: OS handle 330 * @wqueue: pointer to workqueue 331 * Return: none 332 */ 333 static inline void qdf_destroy_workqueue(qdf_handle_t hdl, 334 qdf_workqueue_t *wqueue) 335 { 336 return __qdf_destroy_workqueue(wqueue); 337 } 338 339 /** 340 * qdf_sched_work - Schedule a deferred task on non-interrupt context 341 * @hdl: OS handle 342 * @work: pointer to work 343 * Return: none 344 */ 345 static inline void qdf_sched_work(qdf_handle_t hdl, qdf_work_t *work) 346 { 347 __qdf_sched_work(work); 348 } 349 350 /** 351 * qdf_cancel_work() - Cancel a work 352 * @work: pointer to work 353 * 354 * Cancel work and wait for its execution to finish. 355 * This function can be used even if the work re-queues 356 * itself or migrates to another workqueue. On return 357 * from this function, work is guaranteed to be not 358 * pending or executing on any CPU. The caller must 359 * ensure that the workqueue on which work was last 360 * queued can't be destroyed before this function returns. 361 * 362 * Return: true if work was pending, false otherwise 363 */ 364 static inline bool qdf_cancel_work(qdf_work_t *work) 365 { 366 return __qdf_cancel_work(work); 367 } 368 369 /** 370 * qdf_flush_work - Flush a deferred task on non-interrupt context 371 * @work: pointer to work 372 * 373 * Wait until work has finished execution. work is guaranteed to be 374 * idle on return if it hasn't been requeued since flush started. 375 * 376 * Return: none 377 */ 378 static inline void qdf_flush_work(qdf_work_t *work) 379 { 380 __qdf_flush_work(work); 381 } 382 383 /** 384 * qdf_disable_work - disable the deferred task (synchronous) 385 * @work: pointer to work 386 * Return: unsigned int 387 */ 388 static inline uint32_t qdf_disable_work(qdf_work_t *work) 389 { 390 return __qdf_disable_work(work); 391 } 392 393 /** 394 * qdf_destroy_work - destroy the deferred task (synchronous) 395 * @hdl: OS handle 396 * @work: pointer to work 397 * Return: none 398 */ 399 static inline void qdf_destroy_work(qdf_handle_t hdl, qdf_work_t *work) 400 { 401 __qdf_disable_work(work); 402 } 403 #endif 404 405 #endif /*_QDF_DEFER_H*/ 406