xref: /wlan-dirver/qca-wifi-host-cmn/qdf/linux/src/i_qdf_defer.h (revision 70a19e16789e308182f63b15c75decec7bf0b342)
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