xref: /wlan-dirver/qca-wifi-host-cmn/qdf/linux/src/i_qdf_defer.h (revision 6d768494e5ce14eb1603a695c86739d12ecc6ec2)
1 /*
2  * Copyright (c) 2014-2020 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_defer.h
21  * This file provides OS dependent deferred API's.
22  */
23 
24 #ifndef _I_QDF_DEFER_H
25 #define _I_QDF_DEFER_H
26 
27 #include <linux/workqueue.h>
28 #include <linux/interrupt.h>
29 #include <qdf_types.h>
30 #include <qdf_status.h>
31 #include <qdf_trace.h>
32 
33 typedef struct tasklet_struct __qdf_bh_t;
34 typedef struct workqueue_struct __qdf_workqueue_t;
35 
36 /**
37  * __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 extern void __qdf_defer_func(struct work_struct *work);
49 
50 typedef void (*__qdf_bh_fn_t)(unsigned long arg);
51 
52 /**
53  * __qdf_init_work - Initialize a work/task queue, This runs in non-interrupt
54  * context, so can be preempted by H/W & S/W intr
55  * @work: pointer to work
56  * @func: deferred function to run at bottom half non-interrupt context.
57  * @arg: argument for the deferred function
58  * Return: none
59  */
60 static inline QDF_STATUS
61 __qdf_init_work(__qdf_work_t *work, qdf_defer_fn_t func, void *arg)
62 {
63 	work->fn = func;
64 	work->arg = arg;
65 	INIT_WORK(&work->work, __qdf_defer_func);
66 	return QDF_STATUS_SUCCESS;
67 }
68 
69 /**
70  * __qdf_queue_work - Queue the work/task
71  * @wqueue: pointer to workqueue
72  * @work: pointer to work
73  * Return: none
74  */
75 static inline void
76 __qdf_queue_work(__qdf_workqueue_t *wqueue, __qdf_work_t *work)
77 {
78 	queue_work(wqueue, &work->work);
79 }
80 
81 /**
82  * __qdf_sched_work - Schedule a deferred task on non-interrupt context
83  * @work: pointer to work
84  * Retrun: none
85  */
86 static inline QDF_STATUS __qdf_sched_work(__qdf_work_t *work)
87 {
88 	schedule_work(&work->work);
89 	return QDF_STATUS_SUCCESS;
90 }
91 
92 /**
93  * __qdf_cancel_work() - Cancel a work
94  * @work: pointer to work
95  * Return: true if work was pending, false otherwise
96  */
97 static inline bool __qdf_cancel_work(__qdf_work_t *work)
98 {
99 	return cancel_work_sync(&work->work);
100 }
101 
102 /**
103  * __qdf_flush_work - Flush a deferred task on non-interrupt context
104  * @work: pointer to work
105  * Return: none
106  */
107 static inline uint32_t __qdf_flush_work(__qdf_work_t *work)
108 {
109 	flush_work(&work->work);
110 	return QDF_STATUS_SUCCESS;
111 }
112 
113 /**
114  * __qdf_create_workqueue - create a workqueue, This runs in non-interrupt
115  * context, so can be preempted by H/W & S/W intr
116  * @name: string
117  * Return: pointer of type qdf_workqueue_t
118  */
119 static inline __qdf_workqueue_t *__qdf_create_workqueue(char *name)
120 {
121 	return create_workqueue(name);
122 }
123 
124 /**
125  * __qdf_create_singlethread_workqueue() - create a single threaded workqueue
126  * @name: string
127  *
128  * This API creates a dedicated work queue with a single worker thread to avoid
129  * wasting unnecessary resources when works which needs to be submitted in this
130  * queue are not very critical and frequent.
131  *
132  * Return: pointer of type qdf_workqueue_t
133  */
134 static inline __qdf_workqueue_t *__qdf_create_singlethread_workqueue(char *name)
135 {
136 	return create_singlethread_workqueue(name);
137 }
138 
139 /**
140  * __qdf_alloc_high_prior_ordered_workqueue - alloc high-prior ordered workqueue
141  * @name: string
142  *
143  * Return: pointer of type qdf_workqueue_t
144  */
145 static inline
146 __qdf_workqueue_t *__qdf_alloc_high_prior_ordered_workqueue(char *name)
147 {
148 	return  alloc_ordered_workqueue(name, WQ_HIGHPRI);
149 }
150 
151 /**
152  * __qdf_alloc_unbound_workqueue - alloc an unbound workqueue
153  * @name: string
154  *
155  * Return: pointer of type qdf_workqueue_t
156  */
157 static inline __qdf_workqueue_t *__qdf_alloc_unbound_workqueue(char *name)
158 {
159 	return alloc_workqueue(name, WQ_UNBOUND, 0);
160 }
161 
162 /**
163  * __qdf_flush_workqueue - flush the workqueue
164  * @wqueue: pointer to workqueue
165  * Return: none
166  */
167 static inline void __qdf_flush_workqueue(__qdf_workqueue_t *wqueue)
168 {
169 	flush_workqueue(wqueue);
170 }
171 
172 /**
173  * __qdf_destroy_workqueue - Destroy the workqueue
174  * @wqueue: pointer to workqueue
175  * Return: none
176  */
177 static inline void __qdf_destroy_workqueue(__qdf_workqueue_t *wqueue)
178 {
179 	destroy_workqueue(wqueue);
180 }
181 
182 /**
183  * __qdf_init_bh - creates the Bottom half deferred handler
184  * @bh: pointer to bottom
185  * @func: deferred function to run at bottom half interrupt context.
186  * @arg: argument for the deferred function
187  * Return: none
188  */
189 static inline QDF_STATUS
190 __qdf_init_bh(struct tasklet_struct *bh, qdf_defer_fn_t func, void *arg)
191 {
192 	tasklet_init(bh, (__qdf_bh_fn_t) func, (unsigned long)arg);
193 	return QDF_STATUS_SUCCESS;
194 }
195 
196 /**
197  * __qdf_sched_bh - schedule a bottom half (DPC)
198  * @bh: pointer to bottom
199  * Return: none
200  */
201 static inline QDF_STATUS __qdf_sched_bh(struct tasklet_struct *bh)
202 {
203 	tasklet_schedule(bh);
204 	return QDF_STATUS_SUCCESS;
205 }
206 
207 /**
208  * __qdf_disable_work - disable the deferred task (synchronous)
209  * @work: pointer to work
210  * Return: unsigned int
211  */
212 static inline QDF_STATUS __qdf_disable_work(__qdf_work_t *work)
213 {
214 	if (cancel_work_sync(&work->work))
215 		return QDF_STATUS_E_ALREADY;
216 
217 	return QDF_STATUS_SUCCESS;
218 }
219 
220 /**
221  * __qdf_disable_bh - destroy the bh (synchronous)
222  * @bh: pointer to bottom
223  * Return: none
224  */
225 static inline QDF_STATUS __qdf_disable_bh(struct tasklet_struct *bh)
226 {
227 	tasklet_kill(bh);
228 	return QDF_STATUS_SUCCESS;
229 }
230 
231 #endif /*_I_QDF_DEFER_H*/
232