xref: /wlan-dirver/qca-wifi-host-cmn/qdf/linux/src/i_qdf_defer.h (revision d78dedc9dd8c4ee677ac1649d1d42f2a7c3cc1b7)
1 /*
2  * Copyright (c) 2014-2018 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/version.h>
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 tasklet_struct __qdf_bh_t;
35 typedef struct workqueue_struct __qdf_workqueue_t;
36 
37 #if LINUX_VERSION_CODE  <= KERNEL_VERSION(2, 6, 19)
38 typedef struct work_struct      __qdf_work_t;
39 typedef struct work_struct      __qdf_delayed_work_t;
40 #else
41 
42 /**
43  * __qdf_work_t - wrapper around the real task func
44  * @work: Instance of work
45  * @fn: function pointer to the handler
46  * @arg: pointer to argument
47  */
48 typedef struct {
49 	struct work_struct   work;
50 	qdf_defer_fn_t    fn;
51 	void                 *arg;
52 } __qdf_work_t;
53 
54 /**
55  * __qdf_delayed_work_t - wrapper around the real work func
56  * @dwork: Instance of delayed work
57  * @fn: function pointer to the handler
58  * @arg: pointer to argument
59  */
60 typedef struct {
61 	struct delayed_work  dwork;
62 	qdf_defer_fn_t    fn;
63 	void                 *arg;
64 } __qdf_delayed_work_t;
65 
66 extern void __qdf_defer_func(struct work_struct *work);
67 extern void __qdf_defer_delayed_func(struct work_struct *work);
68 #endif
69 
70 typedef void (*__qdf_bh_fn_t)(unsigned long arg);
71 
72 #if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 19)
73 /**
74  * __qdf_init_work - Initialize a work/task queue, This runs in non-interrupt
75  * context, so can be preempted by H/W & S/W intr
76  * @work: pointer to work
77  * @func: deferred function to run at bottom half non-interrupt context.
78  * @arg: argument for the deferred function
79  * Return: none
80  */
81 static inline QDF_STATUS
82 __qdf_init_work(__qdf_work_t *work, qdf_defer_fn_t func, void *arg)
83 {
84 	/*Initialize func and argument in work struct */
85 	INIT_WORK(&work->work, __qdf_defer_func);
86 	return QDF_STATUS_SUCCESS;
87 }
88 
89 /**
90  * __qdf_init_delayed_work - create a work/task, This runs in non-interrupt
91  * context, so can be preempted by H/W & S/W intr
92  * @work: pointer to work
93  * @func: deferred function to run at bottom half non-interrupt context.
94  * @arg: argument for the deferred function
95  * Return: none
96  */
97 static inline uint32_t __qdf_init_delayed_work(__qdf_delayed_work_t *work,
98 					       qdf_defer_fn_t func,
99 					       void *arg)
100 {
101 	INIT_WORK(work, func, arg);
102 	return QDF_STATUS_SUCCESS;
103 }
104 
105 /**
106  * __qdf_queue_work - Queue the work/task
107  * @wqueue: pointer to workqueue
108  * @work: pointer to work
109  * Return: none
110  */
111 static inline void
112 __qdf_queue_work(__qdf_workqueue_t *wqueue, __qdf_work_t *work)
113 {
114 	queue_work(wqueue, work);
115 }
116 
117 /**
118  * __qdf_queue_delayed_work - Queue the delayed work/task
119  * @wqueue: pointer to workqueue
120  * @work: pointer to work
121  * @delay: delay interval
122  * Return: none
123  */
124 static inline void __qdf_queue_delayed_work(__qdf_workqueue_t *wqueue,
125 					    __qdf_delayed_work_t *work,
126 					    uint32_t delay)
127 {
128 	queue_delayed_work(wqueue, work, msecs_to_jiffies(delay));
129 }
130 
131 /**
132  * __qdf_sched_work - Schedule a deferred task on non-interrupt context
133  * @work: pointer to work
134  * Retrun: none
135  */
136 static inline QDF_STATUS __qdf_sched_work(__qdf_work_t *work)
137 {
138 	schedule_work(work);
139 	return QDF_STATUS_SUCCESS;
140 }
141 
142 /**
143  * __qdf_sched_delayed_work() - Schedule a delayed work
144  * @work: pointer to delayed work
145  * @delay: delay interval
146  * Return: none
147  */
148 static inline QDF_STATUS
149 __qdf_sched_delayed_work(__qdf_delayed_work_t *work, uint32_t delay)
150 {
151 	schedule_delayed_work(work, msecs_to_jiffies(delay));
152 	return QDF_STATUS_SUCCESS;
153 }
154 
155 /**
156  * __qdf_cancel_work() - Cancel a work
157  * @work: pointer to work
158  * Return: true if work was pending, false otherwise
159  */
160 static inline bool __qdf_cancel_work(__qdf_work_t *work)
161 {
162 	return cancel_work_sync(work);
163 }
164 
165 /**
166  * __qdf_cancel_delayed_work() - Cancel a delayed work
167  * @work: pointer to delayed work
168  * Return: true if work was pending, false otherwise
169  */
170 static inline bool __qdf_cancel_delayed_work(__qdf_delayed_work_t *work)
171 {
172 	return cancel_delayed_work_sync(work);
173 }
174 
175 /**
176  * __qdf_flush_work - Flush a deferred task on non-interrupt context
177  * @work: pointer to work
178  * Return: none
179  */
180 static inline uint32_t __qdf_flush_work(__qdf_work_t *work)
181 {
182 	flush_work(work);
183 	return QDF_STATUS_SUCCESS;
184 }
185 
186 /**
187  * __qdf_flush_delayed_work() - Flush a delayed work
188  * @work: pointer to delayed work
189  * Return: none
190  */
191 static inline uint32_t __qdf_flush_delayed_work(__qdf_delayed_work_t *work)
192 {
193 	flush_delayed_work(work);
194 	return QDF_STATUS_SUCCESS;
195 }
196 
197 #else
198 static inline QDF_STATUS
199 __qdf_init_work(__qdf_work_t *work, qdf_defer_fn_t func, void *arg)
200 {
201 	work->fn = func;
202 	work->arg = arg;
203 	INIT_WORK(&work->work, __qdf_defer_func);
204 	return QDF_STATUS_SUCCESS;
205 }
206 
207 static inline uint32_t __qdf_init_delayed_work(__qdf_delayed_work_t *work,
208 					       qdf_defer_fn_t func,
209 					       void *arg)
210 {
211 	/*Initialize func and argument in work struct */
212 	work->fn = func;
213 	work->arg = arg;
214 	INIT_DELAYED_WORK(&work->dwork, __qdf_defer_delayed_func);
215 	return QDF_STATUS_SUCCESS;
216 }
217 
218 static inline void
219 __qdf_queue_work(__qdf_workqueue_t *wqueue, __qdf_work_t *work)
220 {
221 	queue_work(wqueue, &work->work);
222 }
223 
224 static inline void __qdf_queue_delayed_work(__qdf_workqueue_t *wqueue,
225 					    __qdf_delayed_work_t *work,
226 					    uint32_t delay)
227 {
228 	queue_delayed_work(wqueue, &work->dwork, msecs_to_jiffies(delay));
229 }
230 
231 static inline QDF_STATUS __qdf_sched_work(__qdf_work_t *work)
232 {
233 	schedule_work(&work->work);
234 	return QDF_STATUS_SUCCESS;
235 }
236 
237 static inline QDF_STATUS
238 __qdf_sched_delayed_work(__qdf_delayed_work_t *work, uint32_t delay)
239 {
240 	schedule_delayed_work(&work->dwork, msecs_to_jiffies(delay));
241 	return QDF_STATUS_SUCCESS;
242 }
243 
244 static inline bool __qdf_cancel_work(__qdf_work_t *work)
245 {
246 	return cancel_work_sync(&work->work);
247 }
248 
249 static inline bool __qdf_cancel_delayed_work(__qdf_delayed_work_t *work)
250 {
251 	return cancel_delayed_work_sync(&work->dwork);
252 }
253 
254 static inline uint32_t __qdf_flush_work(__qdf_work_t *work)
255 {
256 	flush_work(&work->work);
257 	return QDF_STATUS_SUCCESS;
258 }
259 
260 static inline uint32_t __qdf_flush_delayed_work(__qdf_delayed_work_t *work)
261 {
262 	flush_delayed_work(&work->dwork);
263 	return QDF_STATUS_SUCCESS;
264 }
265 
266 #endif
267 
268 /**
269  * __qdf_create_workqueue - create a workqueue, This runs in non-interrupt
270  * context, so can be preempted by H/W & S/W intr
271  * @name: string
272  * Return: pointer of type qdf_workqueue_t
273  */
274 static inline __qdf_workqueue_t *__qdf_create_workqueue(char *name)
275 {
276 	return create_workqueue(name);
277 }
278 
279 /**
280  * __qdf_create_singlethread_workqueue() - create a single threaded workqueue
281  * @name: string
282  *
283  * This API creates a dedicated work queue with a single worker thread to avoid
284  * wasting unnecessary resources when works which needs to be submitted in this
285  * queue are not very critical and frequent.
286  *
287  * Return: pointer of type qdf_workqueue_t
288  */
289 static inline __qdf_workqueue_t *__qdf_create_singlethread_workqueue(char *name)
290 {
291 	return create_singlethread_workqueue(name);
292 }
293 
294 /**
295  * __qdf_flush_workqueue - flush the workqueue
296  * @wqueue: pointer to workqueue
297  * Return: none
298  */
299 static inline void __qdf_flush_workqueue(__qdf_workqueue_t *wqueue)
300 {
301 	flush_workqueue(wqueue);
302 }
303 
304 /**
305  * __qdf_destroy_workqueue - Destroy the workqueue
306  * @wqueue: pointer to workqueue
307  * Return: none
308  */
309 static inline void __qdf_destroy_workqueue(__qdf_workqueue_t *wqueue)
310 {
311 	destroy_workqueue(wqueue);
312 }
313 
314 /**
315  * __qdf_init_bh - creates the Bottom half deferred handler
316  * @bh: pointer to bottom
317  * @func: deferred function to run at bottom half interrupt context.
318  * @arg: argument for the deferred function
319  * Return: none
320  */
321 static inline QDF_STATUS
322 __qdf_init_bh(struct tasklet_struct *bh, qdf_defer_fn_t func, void *arg)
323 {
324 	tasklet_init(bh, (__qdf_bh_fn_t) func, (unsigned long)arg);
325 	return QDF_STATUS_SUCCESS;
326 }
327 
328 #if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 19)
329 #else
330 #endif
331 
332 /**
333  * __qdf_sched_bh - schedule a bottom half (DPC)
334  * @bh: pointer to bottom
335  * Return: none
336  */
337 static inline QDF_STATUS __qdf_sched_bh(struct tasklet_struct *bh)
338 {
339 	tasklet_schedule(bh);
340 	return QDF_STATUS_SUCCESS;
341 }
342 
343 /**
344  * __qdf_disable_work - disable the deferred task (synchronous)
345  * @work: pointer to work
346  * Return: unsigned int
347  */
348 static inline QDF_STATUS __qdf_disable_work(__qdf_work_t *work)
349 {
350 	if (cancel_work_sync(&work->work))
351 		return QDF_STATUS_E_ALREADY;
352 
353 	return QDF_STATUS_SUCCESS;
354 }
355 
356 /**
357  * __qdf_disable_bh - destroy the bh (synchronous)
358  * @bh: pointer to bottom
359  * Return: none
360  */
361 static inline QDF_STATUS __qdf_disable_bh(struct tasklet_struct *bh)
362 {
363 	tasklet_kill(bh);
364 	return QDF_STATUS_SUCCESS;
365 }
366 
367 #endif /*_I_QDF_DEFER_H*/
368