1 /*
2  * Copyright (c) 2019 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: qdf_periodic_work.h
22  * A simple, periodic work type for repeatedly executing a callback with a
23  * certain frequency.
24  */
25 
26 #ifndef __QDF_PERIODIC_WORK_H
27 #define __QDF_PERIODIC_WORK_H
28 
29 #include "i_qdf_periodic_work.h"
30 #include "qdf_status.h"
31 #include "qdf_types.h"
32 
33 typedef void (*qdf_periodic_work_cb)(void *context);
34 
35 /**
36  * struct qdf_periodic_work - a deferred work type which executes a callback
37  *	periodically until stopped
38  * @dwork: OS-specific delayed work
39  * @callback: the callback to be executed periodically
40  * @context: the context to pass to the callback
41  * @msec: the delay between executions in milliseconds
42  */
43 struct qdf_periodic_work {
44 	struct __qdf_opaque_delayed_work dwork;
45 	qdf_periodic_work_cb callback;
46 	void *context;
47 	uint32_t msec;
48 };
49 
50 /**
51  * qdf_periodic_work_create() - initialized a periodic work @pwork
52  * @pwork: the periodic work to initialize
53  * @callback: the callback to be executed periodically
54  * @context: the context to pass to the callback
55  *
56  * Return: QDF_STATUS
57  */
58 #define qdf_periodic_work_create(pwork, callback, context) \
59 	__qdf_periodic_work_create(pwork, callback, context, __func__, __LINE__)
60 
61 qdf_must_check QDF_STATUS
62 __qdf_periodic_work_create(struct qdf_periodic_work *pwork,
63 			   qdf_periodic_work_cb callback, void *context,
64 			   const char *func, uint32_t line);
65 
66 /**
67  * qdf_periodic_work_destroy() - deinitialize a periodic work @pwork
68  * @pwork: the periodic work to de-initialize
69  *
70  * Return: None
71  */
72 #define qdf_periodic_work_destroy(pwork) \
73 	__qdf_periodic_work_destroy(pwork, __func__, __LINE__)
74 
75 void __qdf_periodic_work_destroy(struct qdf_periodic_work *pwork,
76 				 const char *func, uint32_t line);
77 
78 /**
79  * qdf_periodic_work_start() - begin periodic execution of @pwork callback
80  * @pwork: the periodic work to start
81  * @msec: the delay between executions in milliseconds
82  *
83  * Return: true if started successfully
84  */
85 bool qdf_periodic_work_start(struct qdf_periodic_work *pwork, uint32_t msec);
86 
87 /**
88  * qdf_periodic_work_stop_async() - Asynchronously stop execution of @pwork
89  * @pwork: the periodic work to stop
90  *
91  * When this returns, @pwork is guaranteed to not be queued, *but* its callback
92  * may still be executing.
93  *
94  * This is safe to call from the @pwork callback.
95  *
96  * Return: true if @pwork was previously started
97  */
98 bool qdf_periodic_work_stop_async(struct qdf_periodic_work *pwork);
99 
100 /**
101  * qdf_periodic_work_stop_sync() - Synchronously stop execution of @pwork
102  * @pwork: the periodic work to stop
103  *
104  * When this returns, @pwork is guaranteed to not be queued, and its callback
105  * not executing.
106  *
107  * This will deadlock if called from the @pwork callback.
108  *
109  * Return: true if @pwork was previously started
110  */
111 bool qdf_periodic_work_stop_sync(struct qdf_periodic_work *pwork);
112 
113 #ifdef WLAN_PERIODIC_WORK_DEBUG
114 /**
115  * qdf_periodic_work_check_for_leaks() - assert no periodic work leaks
116  *
117  * Return: None
118  */
119 void qdf_periodic_work_check_for_leaks(void);
120 
121 /**
122  * qdf_periodic_work_feature_init() - global init logic for periodic work
123  *
124  * Return: None
125  */
126 void qdf_periodic_work_feature_init(void);
127 
128 /**
129  * qdf_periodic_work_feature_deinit() - global de-init logic for periodic work
130  *
131  * Return: None
132  */
133 void qdf_periodic_work_feature_deinit(void);
134 #else
qdf_periodic_work_check_for_leaks(void)135 static inline void qdf_periodic_work_check_for_leaks(void) { }
qdf_periodic_work_feature_init(void)136 static inline void qdf_periodic_work_feature_init(void) { }
qdf_periodic_work_feature_deinit(void)137 static inline void qdf_periodic_work_feature_deinit(void) { }
138 #endif /* WLAN_PERIODIC_WORK_DEBUG */
139 
140 #endif /* __QDF_PERIODIC_WORK_H */
141 
142