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: 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_bh - 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: false if work was already on a queue, true otherwise 170 */ 171 bool 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 202 /** 203 * qdf_local_bh_disable - Disables softirq and tasklet processing 204 * on the local processor 205 * 206 * Return: none 207 */ 208 void qdf_local_bh_disable(void); 209 210 /** 211 * qdf_local_bh_enable - Disables softirq and tasklet processing 212 * on the local processor 213 * 214 * Return: none 215 */ 216 void qdf_local_bh_enable(void); 217 218 #else 219 /** 220 * qdf_create_bh - creates the bottom half deferred handler 221 * @bh: pointer to bottom 222 * @func: deferred function to run at bottom half interrupt context. 223 * @arg: argument for the deferred function 224 * Return: none 225 */ 226 static inline void qdf_create_bh(qdf_bh_t * bh,qdf_defer_fn_t func,void * arg)227 qdf_create_bh(qdf_bh_t *bh, qdf_defer_fn_t func, void *arg) 228 { 229 __qdf_init_bh(bh, func, arg); 230 } 231 232 /** 233 * qdf_sched_bh - schedule a bottom half (DPC) 234 * @bh: pointer to bottom 235 * Return: none 236 */ qdf_sched_bh(qdf_bh_t * bh)237 static inline void qdf_sched_bh(qdf_bh_t *bh) 238 { 239 __qdf_sched_bh(bh); 240 } 241 242 /** 243 * qdf_destroy_bh - destroy the bh (synchronous) 244 * @bh: pointer to bottom 245 * Return: none 246 */ qdf_destroy_bh(qdf_bh_t * bh)247 static inline void qdf_destroy_bh(qdf_bh_t *bh) 248 { 249 __qdf_disable_bh(bh); 250 } 251 252 /** 253 * qdf_local_bh_disable - Disables softirq and tasklet processing 254 * on the local processor 255 * 256 * Return: none 257 */ qdf_local_bh_disable(void)258 static inline void qdf_local_bh_disable(void) 259 { 260 __qdf_local_bh_disable(); 261 } 262 263 /** 264 * qdf_local_bh_enable - Enables softirq and tasklet processing 265 * on the local processor 266 * 267 * Return: none 268 */ qdf_local_bh_enable(void)269 static inline void qdf_local_bh_enable(void) 270 { 271 __qdf_local_bh_enable(); 272 } 273 274 /*********************Non-Interrupt Context deferred Execution***************/ 275 276 /** 277 * qdf_create_work - create a work/task queue, This runs in non-interrupt 278 * context, so can be preempted by H/W & S/W intr 279 * @hdl: OS handle 280 * @work: pointer to work 281 * @func: deferred function to run at bottom half non-interrupt context. 282 * @arg: argument for the deferred function 283 * 284 * Return: QDF status 285 */ qdf_create_work(qdf_handle_t hdl,qdf_work_t * work,qdf_defer_fn_t func,void * arg)286 static inline QDF_STATUS qdf_create_work(qdf_handle_t hdl, qdf_work_t *work, 287 qdf_defer_fn_t func, void *arg) 288 { 289 return __qdf_init_work(work, func, arg); 290 } 291 292 /** 293 * qdf_create_workqueue - create a workqueue, This runs in non-interrupt 294 * context, so can be preempted by H/W & S/W intr 295 * @name: string 296 * Return: pointer of type qdf_workqueue_t 297 */ qdf_create_workqueue(char * name)298 static inline qdf_workqueue_t *qdf_create_workqueue(char *name) 299 { 300 return __qdf_create_workqueue(name); 301 } 302 303 /** 304 * qdf_create_singlethread_workqueue() - create a single threaded workqueue 305 * @name: string 306 * 307 * This API creates a dedicated work queue with a single worker thread to avoid 308 * wasting unnecessary resources when works which needs to be submitted in this 309 * queue are not very critical and frequent. 310 * 311 * Return: pointer of type qdf_workqueue_t 312 */ qdf_create_singlethread_workqueue(char * name)313 static inline qdf_workqueue_t *qdf_create_singlethread_workqueue(char *name) 314 { 315 return __qdf_create_singlethread_workqueue(name); 316 } 317 318 /** 319 * qdf_alloc_high_prior_ordered_workqueue - alloc high-prior ordered workqueue 320 * @name: string 321 * 322 * Return: pointer of type qdf_workqueue_t 323 */ 324 static inline qdf_alloc_high_prior_ordered_workqueue(char * name)325 qdf_workqueue_t *qdf_alloc_high_prior_ordered_workqueue(char *name) 326 { 327 return __qdf_alloc_high_prior_ordered_workqueue(name); 328 } 329 330 /** 331 * qdf_alloc_unbound_workqueue - allocate an unbound workqueue 332 * @name: string 333 * 334 * Return: pointer of type qdf_workqueue_t 335 */ qdf_alloc_unbound_workqueue(char * name)336 static inline qdf_workqueue_t *qdf_alloc_unbound_workqueue(char *name) 337 { 338 return __qdf_alloc_unbound_workqueue(name); 339 } 340 341 /** 342 * qdf_queue_work - Queue the work/task 343 * @hdl: OS handle 344 * @wqueue: pointer to workqueue 345 * @work: pointer to work 346 * Return: false if work was already on a queue, true otherwise 347 */ 348 static inline bool qdf_queue_work(qdf_handle_t hdl,qdf_workqueue_t * wqueue,qdf_work_t * work)349 qdf_queue_work(qdf_handle_t hdl, qdf_workqueue_t *wqueue, qdf_work_t *work) 350 { 351 return __qdf_queue_work(wqueue, work); 352 } 353 354 /** 355 * qdf_flush_workqueue - flush the workqueue 356 * @hdl: OS handle 357 * @wqueue: pointer to workqueue 358 * Return: none 359 */ qdf_flush_workqueue(qdf_handle_t hdl,qdf_workqueue_t * wqueue)360 static inline void qdf_flush_workqueue(qdf_handle_t hdl, 361 qdf_workqueue_t *wqueue) 362 { 363 return __qdf_flush_workqueue(wqueue); 364 } 365 366 /** 367 * qdf_destroy_workqueue - Destroy the workqueue 368 * @hdl: OS handle 369 * @wqueue: pointer to workqueue 370 * Return: none 371 */ qdf_destroy_workqueue(qdf_handle_t hdl,qdf_workqueue_t * wqueue)372 static inline void qdf_destroy_workqueue(qdf_handle_t hdl, 373 qdf_workqueue_t *wqueue) 374 { 375 return __qdf_destroy_workqueue(wqueue); 376 } 377 378 /** 379 * qdf_sched_work - Schedule a deferred task on non-interrupt context 380 * @hdl: OS handle 381 * @work: pointer to work 382 * 383 * Return: false if work was already on a queue, true otherwise 384 */ qdf_sched_work(qdf_handle_t hdl,qdf_work_t * work)385 static inline bool qdf_sched_work(qdf_handle_t hdl, qdf_work_t *work) 386 { 387 return __qdf_sched_work(work); 388 } 389 390 /** 391 * qdf_cancel_work() - Cancel a work 392 * @work: pointer to work 393 * 394 * Cancel work and wait for its execution to finish. 395 * This function can be used even if the work re-queues 396 * itself or migrates to another workqueue. On return 397 * from this function, work is guaranteed to be not 398 * pending or executing on any CPU. The caller must 399 * ensure that the workqueue on which work was last 400 * queued can't be destroyed before this function returns. 401 * 402 * Return: true if work was pending, false otherwise 403 */ qdf_cancel_work(qdf_work_t * work)404 static inline bool qdf_cancel_work(qdf_work_t *work) 405 { 406 return __qdf_cancel_work(work); 407 } 408 409 /** 410 * qdf_flush_work - Flush a deferred task on non-interrupt context 411 * @work: pointer to work 412 * 413 * Wait until work has finished execution. work is guaranteed to be 414 * idle on return if it hasn't been requeued since flush started. 415 * 416 * Return: none 417 */ qdf_flush_work(qdf_work_t * work)418 static inline void qdf_flush_work(qdf_work_t *work) 419 { 420 __qdf_flush_work(work); 421 } 422 423 /** 424 * qdf_disable_work - disable the deferred task (synchronous) 425 * @work: pointer to work 426 * Return: unsigned int 427 */ qdf_disable_work(qdf_work_t * work)428 static inline uint32_t qdf_disable_work(qdf_work_t *work) 429 { 430 return __qdf_disable_work(work); 431 } 432 433 /** 434 * qdf_destroy_work - destroy the deferred task (synchronous) 435 * @hdl: OS handle 436 * @work: pointer to work 437 * Return: none 438 */ qdf_destroy_work(qdf_handle_t hdl,qdf_work_t * work)439 static inline void qdf_destroy_work(qdf_handle_t hdl, qdf_work_t *work) 440 { 441 __qdf_disable_work(work); 442 } 443 #endif 444 445 #endif /*_QDF_DEFER_H*/ 446