xref: /wlan-dirver/qca-wifi-host-cmn/qdf/linux/src/i_qdf_timer.h (revision 27d564647e9b50e713c60b0d7e5ea2a9b0a3ae74)
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_timer
21  * This file provides OS dependent timer API's.
22  */
23 
24 #ifndef _I_QDF_TIMER_H
25 #define _I_QDF_TIMER_H
26 
27 #include <linux/version.h>
28 #include <linux/delay.h>
29 #include <linux/timer.h>
30 #include <linux/jiffies.h>
31 #include <qdf_types.h>
32 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0)
33 #include <linux/sched/task_stack.h>
34 #endif
35 
36 #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 9, 0)
37 #define setup_deferrable_timer(timer, fn, data)                                \
38 	__setup_timer((timer), (fn), (data), TIMER_DEFERRABLE)
39 #endif
40 
41 /* timer data type */
42 typedef struct timer_list __qdf_timer_t;
43 
44 typedef void (*__qdf_dummy_timer_func_t)(unsigned long arg);
45 
46 /**
47  * __qdf_timer_init() - initialize a softirq timer
48  * @timer: Pointer to timer object
49  * @func: Function pointer
50  * @arg: Argument
51  * @type: deferrable or non deferrable timer type
52  *
53  * Timer type QDF_TIMER_TYPE_SW means its a deferrable sw timer which will
54  * not cause CPU wake upon expiry
55  * Timer type QDF_TIMER_TYPE_WAKE_APPS means its a non-deferrable timer which
56  * will cause CPU wake up on expiry
57  *
58  * Return: QDF_STATUS
59  */
60 static inline QDF_STATUS __qdf_timer_init(struct timer_list *timer,
61 					  qdf_timer_func_t func, void *arg,
62 					  QDF_TIMER_TYPE type)
63 {
64 	bool is_on_stack = object_is_on_stack(timer);
65 	__qdf_dummy_timer_func_t callback = (__qdf_dummy_timer_func_t)func;
66 	unsigned long ctx = (unsigned long)arg;
67 
68 	if (type == QDF_TIMER_TYPE_SW) {
69 		if (is_on_stack)
70 			setup_deferrable_timer_on_stack(timer, callback, ctx);
71 		else
72 			setup_deferrable_timer(timer, callback, ctx);
73 	} else {
74 		if (is_on_stack)
75 			setup_timer_on_stack(timer, callback, ctx);
76 		else
77 			setup_timer(timer, callback, ctx);
78 	}
79 
80 	return QDF_STATUS_SUCCESS;
81 }
82 
83 /**
84  * __qdf_timer_start() - start a qdf softirq timer
85  * @timer: Pointer to timer object
86  * @delay: Delay in milliseconds
87  *
88  * Return: None
89  */
90 static inline void __qdf_timer_start(struct timer_list *timer, uint32_t delay)
91 {
92 	timer->expires = jiffies + msecs_to_jiffies(delay);
93 	add_timer(timer);
94 }
95 
96 /**
97  * __qdf_timer_mod() - modify a timer
98  * @timer: Pointer to timer object
99  * @delay: Delay in milliseconds
100  *
101  * Return: None
102  */
103 static inline void __qdf_timer_mod(struct timer_list *timer, uint32_t delay)
104 {
105 	mod_timer(timer, jiffies + msecs_to_jiffies(delay));
106 }
107 
108 /**
109  * __qdf_timer_stop() - cancel a timer
110  * @timer: Pointer to timer object
111  *
112  * Return: true if timer was cancelled and deactived,
113  * false if timer was cancelled but already got fired.
114  */
115 static inline bool __qdf_timer_stop(struct timer_list *timer)
116 {
117 	if (likely(del_timer(timer)))
118 		return 1;
119 	else
120 		return 0;
121 }
122 
123 /**
124  * __qdf_timer_free() - free a qdf timer
125  * @timer: Pointer to timer object
126  *
127  * Return: None
128  */
129 static inline void __qdf_timer_free(struct timer_list *timer)
130 {
131 	del_timer_sync(timer);
132 
133 	if (object_is_on_stack(timer))
134 		destroy_timer_on_stack(timer);
135 }
136 
137 /**
138  * __qdf_sostirq_timer_sync_cancel() - Synchronously canel a timer
139  * @timer: Pointer to timer object
140  *
141  * Synchronization Rules:
142  * 1. caller must make sure timer function will not use
143  *    qdf_set_timer to add iteself again.
144  * 2. caller must not hold any lock that timer function
145  *    is likely to hold as well.
146  * 3. It can't be called from interrupt context.
147  *
148  * Return: true if timer was cancelled and deactived,
149  * false if timer was cancelled but already got fired.
150  */
151 static inline bool __qdf_timer_sync_cancel(struct timer_list *timer)
152 {
153 	return del_timer_sync(timer);
154 }
155 
156 #endif /*_QDF_TIMER_PVT_H*/
157