xref: /wlan-dirver/qca-wifi-host-cmn/qdf/linux/src/i_qdf_defer.h (revision 92d87f51612f6c3b2285266215edee8911647c2f)
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/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 /**
49  * __qdf_delayed_work_t - wrapper around the real work func
50  * @dwork: Instance of delayed work
51  * @fn: function pointer to the handler
52  * @arg: pointer to argument
53  */
54 typedef struct {
55 	struct delayed_work dwork;
56 	qdf_defer_fn_t fn;
57 	void *arg;
58 } __qdf_delayed_work_t;
59 
60 extern void __qdf_defer_func(struct work_struct *work);
61 extern void __qdf_defer_delayed_func(struct work_struct *work);
62 
63 typedef void (*__qdf_bh_fn_t)(unsigned long arg);
64 
65 /**
66  * __qdf_init_work - Initialize a work/task queue, This runs in non-interrupt
67  * context, so can be preempted by H/W & S/W intr
68  * @work: pointer to work
69  * @func: deferred function to run at bottom half non-interrupt context.
70  * @arg: argument for the deferred function
71  * Return: none
72  */
73 static inline QDF_STATUS
74 __qdf_init_work(__qdf_work_t *work, qdf_defer_fn_t func, void *arg)
75 {
76 	work->fn = func;
77 	work->arg = arg;
78 	INIT_WORK(&work->work, __qdf_defer_func);
79 	return QDF_STATUS_SUCCESS;
80 }
81 
82 /**
83  * __qdf_init_delayed_work - create a work/task, This runs in non-interrupt
84  * context, so can be preempted by H/W & S/W intr
85  * @work: pointer to work
86  * @func: deferred function to run at bottom half non-interrupt context.
87  * @arg: argument for the deferred function
88  * Return: none
89  */
90 static inline uint32_t __qdf_init_delayed_work(__qdf_delayed_work_t *work,
91 					       qdf_defer_fn_t func,
92 					       void *arg)
93 {
94 	/*Initialize func and argument in work struct */
95 	work->fn = func;
96 	work->arg = arg;
97 	INIT_DELAYED_WORK(&work->dwork, __qdf_defer_delayed_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: none
106  */
107 static inline void
108 __qdf_queue_work(__qdf_workqueue_t *wqueue, __qdf_work_t *work)
109 {
110 	queue_work(wqueue, &work->work);
111 }
112 
113 /**
114  * __qdf_queue_delayed_work - Queue the delayed work/task
115  * @wqueue: pointer to workqueue
116  * @work: pointer to work
117  * @delay: delay interval
118  * Return: none
119  */
120 static inline void __qdf_queue_delayed_work(__qdf_workqueue_t *wqueue,
121 					    __qdf_delayed_work_t *work,
122 					    uint32_t delay)
123 {
124 	queue_delayed_work(wqueue, &work->dwork, msecs_to_jiffies(delay));
125 }
126 
127 /**
128  * __qdf_sched_work - Schedule a deferred task on non-interrupt context
129  * @work: pointer to work
130  * Retrun: none
131  */
132 static inline QDF_STATUS __qdf_sched_work(__qdf_work_t *work)
133 {
134 	schedule_work(&work->work);
135 	return QDF_STATUS_SUCCESS;
136 }
137 
138 /**
139  * __qdf_sched_delayed_work() - Schedule a delayed work
140  * @work: pointer to delayed work
141  * @delay: delay interval
142  * Return: none
143  */
144 static inline QDF_STATUS
145 __qdf_sched_delayed_work(__qdf_delayed_work_t *work, uint32_t delay)
146 {
147 	schedule_delayed_work(&work->dwork, msecs_to_jiffies(delay));
148 	return QDF_STATUS_SUCCESS;
149 }
150 
151 /**
152  * __qdf_cancel_work() - Cancel a work
153  * @work: pointer to work
154  * Return: true if work was pending, false otherwise
155  */
156 static inline bool __qdf_cancel_work(__qdf_work_t *work)
157 {
158 	return cancel_work_sync(&work->work);
159 }
160 
161 /**
162  * __qdf_cancel_delayed_work() - Cancel a delayed work
163  * @work: pointer to delayed work
164  * Return: true if work was pending, false otherwise
165  */
166 static inline bool __qdf_cancel_delayed_work(__qdf_delayed_work_t *work)
167 {
168 	return cancel_delayed_work_sync(&work->dwork);
169 }
170 
171 /**
172  * __qdf_flush_work - Flush a deferred task on non-interrupt context
173  * @work: pointer to work
174  * Return: none
175  */
176 static inline uint32_t __qdf_flush_work(__qdf_work_t *work)
177 {
178 	flush_work(&work->work);
179 	return QDF_STATUS_SUCCESS;
180 }
181 
182 /**
183  * __qdf_flush_delayed_work() - Flush a delayed work
184  * @work: pointer to delayed work
185  * Return: none
186  */
187 static inline uint32_t __qdf_flush_delayed_work(__qdf_delayed_work_t *work)
188 {
189 	flush_delayed_work(&work->dwork);
190 	return QDF_STATUS_SUCCESS;
191 }
192 
193 /**
194  * __qdf_create_workqueue - create a workqueue, This runs in non-interrupt
195  * context, so can be preempted by H/W & S/W intr
196  * @name: string
197  * Return: pointer of type qdf_workqueue_t
198  */
199 static inline __qdf_workqueue_t *__qdf_create_workqueue(char *name)
200 {
201 	return create_workqueue(name);
202 }
203 
204 /**
205  * __qdf_create_singlethread_workqueue() - create a single threaded workqueue
206  * @name: string
207  *
208  * This API creates a dedicated work queue with a single worker thread to avoid
209  * wasting unnecessary resources when works which needs to be submitted in this
210  * queue are not very critical and frequent.
211  *
212  * Return: pointer of type qdf_workqueue_t
213  */
214 static inline __qdf_workqueue_t *__qdf_create_singlethread_workqueue(char *name)
215 {
216 	return create_singlethread_workqueue(name);
217 }
218 
219 /**
220  * __qdf_flush_workqueue - flush the workqueue
221  * @wqueue: pointer to workqueue
222  * Return: none
223  */
224 static inline void __qdf_flush_workqueue(__qdf_workqueue_t *wqueue)
225 {
226 	flush_workqueue(wqueue);
227 }
228 
229 /**
230  * __qdf_destroy_workqueue - Destroy the workqueue
231  * @wqueue: pointer to workqueue
232  * Return: none
233  */
234 static inline void __qdf_destroy_workqueue(__qdf_workqueue_t *wqueue)
235 {
236 	destroy_workqueue(wqueue);
237 }
238 
239 /**
240  * __qdf_init_bh - creates the Bottom half deferred handler
241  * @bh: pointer to bottom
242  * @func: deferred function to run at bottom half interrupt context.
243  * @arg: argument for the deferred function
244  * Return: none
245  */
246 static inline QDF_STATUS
247 __qdf_init_bh(struct tasklet_struct *bh, qdf_defer_fn_t func, void *arg)
248 {
249 	tasklet_init(bh, (__qdf_bh_fn_t) func, (unsigned long)arg);
250 	return QDF_STATUS_SUCCESS;
251 }
252 
253 /**
254  * __qdf_sched_bh - schedule a bottom half (DPC)
255  * @bh: pointer to bottom
256  * Return: none
257  */
258 static inline QDF_STATUS __qdf_sched_bh(struct tasklet_struct *bh)
259 {
260 	tasklet_schedule(bh);
261 	return QDF_STATUS_SUCCESS;
262 }
263 
264 /**
265  * __qdf_disable_work - disable the deferred task (synchronous)
266  * @work: pointer to work
267  * Return: unsigned int
268  */
269 static inline QDF_STATUS __qdf_disable_work(__qdf_work_t *work)
270 {
271 	if (cancel_work_sync(&work->work))
272 		return QDF_STATUS_E_ALREADY;
273 
274 	return QDF_STATUS_SUCCESS;
275 }
276 
277 /**
278  * __qdf_disable_bh - destroy the bh (synchronous)
279  * @bh: pointer to bottom
280  * Return: none
281  */
282 static inline QDF_STATUS __qdf_disable_bh(struct tasklet_struct *bh)
283 {
284 	tasklet_kill(bh);
285 	return QDF_STATUS_SUCCESS;
286 }
287 
288 #endif /*_I_QDF_DEFER_H*/
289