xref: /wlan-driver/qca-wifi-host-cmn/qdf/linux/src/i_qdf_timer.h (revision 5113495b16420b49004c444715d2daae2066e7dc)
1*5113495bSYour Name /*
2*5113495bSYour Name  * Copyright (c) 2014-2021 The Linux Foundation. All rights reserved.
3*5113495bSYour Name  *
4*5113495bSYour Name  * Permission to use, copy, modify, and/or distribute this software for
5*5113495bSYour Name  * any purpose with or without fee is hereby granted, provided that the
6*5113495bSYour Name  * above copyright notice and this permission notice appear in all
7*5113495bSYour Name  * copies.
8*5113495bSYour Name  *
9*5113495bSYour Name  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10*5113495bSYour Name  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11*5113495bSYour Name  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
12*5113495bSYour Name  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
13*5113495bSYour Name  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
14*5113495bSYour Name  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
15*5113495bSYour Name  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16*5113495bSYour Name  * PERFORMANCE OF THIS SOFTWARE.
17*5113495bSYour Name  */
18*5113495bSYour Name 
19*5113495bSYour Name /**
20*5113495bSYour Name  * DOC: i_qdf_timer
21*5113495bSYour Name  * This file provides OS dependent timer API's.
22*5113495bSYour Name  */
23*5113495bSYour Name 
24*5113495bSYour Name #ifndef _I_QDF_TIMER_H
25*5113495bSYour Name #define _I_QDF_TIMER_H
26*5113495bSYour Name 
27*5113495bSYour Name #include <linux/version.h>
28*5113495bSYour Name #include <linux/delay.h>
29*5113495bSYour Name #include <linux/timer.h>
30*5113495bSYour Name #include <linux/jiffies.h>
31*5113495bSYour Name #include "qdf_mc_timer.h"
32*5113495bSYour Name #include <qdf_types.h>
33*5113495bSYour Name #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0)
34*5113495bSYour Name #include <linux/sched/task_stack.h>
35*5113495bSYour Name #endif
36*5113495bSYour Name 
37*5113495bSYour Name typedef void (*qdf_timer_func_t)(void *);
38*5113495bSYour Name 
39*5113495bSYour Name 
40*5113495bSYour Name struct __qdf_timer_t {
41*5113495bSYour Name 	struct timer_list os_timer;
42*5113495bSYour Name 	qdf_timer_func_t callback;
43*5113495bSYour Name 	void *context;
44*5113495bSYour Name };
45*5113495bSYour Name 
46*5113495bSYour Name #define __qdf_scaled_msecs_to_jiffies(msec) \
47*5113495bSYour Name 	(qdf_timer_get_multiplier() * msecs_to_jiffies(msec))
48*5113495bSYour Name 
49*5113495bSYour Name #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)
__os_timer_shim(struct timer_list * os_timer)50*5113495bSYour Name static inline void __os_timer_shim(struct timer_list *os_timer)
51*5113495bSYour Name {
52*5113495bSYour Name 	struct __qdf_timer_t *timer = from_timer(timer, os_timer, os_timer);
53*5113495bSYour Name 
54*5113495bSYour Name 	timer->callback(timer->context);
55*5113495bSYour Name }
56*5113495bSYour Name 
__qdf_timer_init(struct __qdf_timer_t * timer,qdf_timer_func_t func,void * arg,QDF_TIMER_TYPE type)57*5113495bSYour Name static inline QDF_STATUS __qdf_timer_init(struct __qdf_timer_t *timer,
58*5113495bSYour Name 					  qdf_timer_func_t func, void *arg,
59*5113495bSYour Name 					  QDF_TIMER_TYPE type)
60*5113495bSYour Name {
61*5113495bSYour Name 	struct timer_list *os_timer = &timer->os_timer;
62*5113495bSYour Name 	uint32_t flags = 0;
63*5113495bSYour Name 
64*5113495bSYour Name 	timer->callback = func;
65*5113495bSYour Name 	timer->context = arg;
66*5113495bSYour Name 
67*5113495bSYour Name 	if (type == QDF_TIMER_TYPE_SW)
68*5113495bSYour Name 		flags |= TIMER_DEFERRABLE;
69*5113495bSYour Name 	else if (type == QDF_TIMER_TYPE_SW_SPIN)
70*5113495bSYour Name 		flags |= TIMER_DEFERRABLE | TIMER_PINNED;
71*5113495bSYour Name 
72*5113495bSYour Name 	if (object_is_on_stack(os_timer))
73*5113495bSYour Name 		timer_setup_on_stack(os_timer, __os_timer_shim, flags);
74*5113495bSYour Name 	else
75*5113495bSYour Name 		timer_setup(os_timer, __os_timer_shim, flags);
76*5113495bSYour Name 
77*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
78*5113495bSYour Name }
79*5113495bSYour Name #else
80*5113495bSYour Name 
81*5113495bSYour Name #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 9, 0)
82*5113495bSYour Name #define setup_deferrable_timer(timer, fn, data) \
83*5113495bSYour Name 	__setup_timer((timer), (fn), (data), TIMER_DEFERRABLE)
84*5113495bSYour Name #endif
85*5113495bSYour Name 
__os_timer_shim(unsigned long addr)86*5113495bSYour Name static inline void __os_timer_shim(unsigned long addr)
87*5113495bSYour Name {
88*5113495bSYour Name 	struct __qdf_timer_t *timer = (void *)addr;
89*5113495bSYour Name 
90*5113495bSYour Name 	timer->callback(timer->context);
91*5113495bSYour Name }
92*5113495bSYour Name 
__qdf_timer_init(struct __qdf_timer_t * timer,qdf_timer_func_t func,void * arg,QDF_TIMER_TYPE type)93*5113495bSYour Name static inline QDF_STATUS __qdf_timer_init(struct __qdf_timer_t *timer,
94*5113495bSYour Name 					  qdf_timer_func_t func, void *arg,
95*5113495bSYour Name 					  QDF_TIMER_TYPE type)
96*5113495bSYour Name {
97*5113495bSYour Name 	struct timer_list *os_timer = &timer->os_timer;
98*5113495bSYour Name 	bool is_on_stack = object_is_on_stack(os_timer);
99*5113495bSYour Name 	unsigned long addr = (unsigned long)timer;
100*5113495bSYour Name 
101*5113495bSYour Name 	timer->callback = func;
102*5113495bSYour Name 	timer->context = arg;
103*5113495bSYour Name 
104*5113495bSYour Name 	if (type == QDF_TIMER_TYPE_SW) {
105*5113495bSYour Name 		if (is_on_stack)
106*5113495bSYour Name 			setup_deferrable_timer_on_stack(os_timer,
107*5113495bSYour Name 							__os_timer_shim,
108*5113495bSYour Name 							addr);
109*5113495bSYour Name 		else
110*5113495bSYour Name 			setup_deferrable_timer(os_timer, __os_timer_shim, addr);
111*5113495bSYour Name 	} else if (type == QDF_TIMER_TYPE_SW_SPIN) {
112*5113495bSYour Name 		if (is_on_stack)
113*5113495bSYour Name 			__setup_timer_on_stack(os_timer,
114*5113495bSYour Name 					       __os_timer_shim,
115*5113495bSYour Name 					       addr,
116*5113495bSYour Name 					       TIMER_DEFERRABLE | TIMER_PINNED);
117*5113495bSYour Name 		else
118*5113495bSYour Name 			__setup_timer(os_timer,
119*5113495bSYour Name 				      __os_timer_shim,
120*5113495bSYour Name 				      addr,
121*5113495bSYour Name 				      TIMER_DEFERRABLE | TIMER_PINNED);
122*5113495bSYour Name 	} else {
123*5113495bSYour Name 		if (is_on_stack)
124*5113495bSYour Name 			setup_timer_on_stack(os_timer, __os_timer_shim, addr);
125*5113495bSYour Name 		else
126*5113495bSYour Name 			setup_timer(os_timer, __os_timer_shim, addr);
127*5113495bSYour Name 	}
128*5113495bSYour Name 
129*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
130*5113495bSYour Name }
131*5113495bSYour Name #endif /* KERNEL_VERSION(4, 15, 0)*/
132*5113495bSYour Name 
__qdf_timer_start(struct __qdf_timer_t * timer,uint32_t msec)133*5113495bSYour Name static inline void __qdf_timer_start(struct __qdf_timer_t *timer, uint32_t msec)
134*5113495bSYour Name {
135*5113495bSYour Name 	struct timer_list *os_timer = &timer->os_timer;
136*5113495bSYour Name 
137*5113495bSYour Name 	os_timer->expires = jiffies + __qdf_scaled_msecs_to_jiffies(msec);
138*5113495bSYour Name 	add_timer(os_timer);
139*5113495bSYour Name }
140*5113495bSYour Name 
141*5113495bSYour Name static inline
__qdf_timer_start_on(struct __qdf_timer_t * timer,uint32_t msec,int cpu)142*5113495bSYour Name void __qdf_timer_start_on(struct __qdf_timer_t *timer, uint32_t msec,
143*5113495bSYour Name 			  int cpu)
144*5113495bSYour Name {
145*5113495bSYour Name 	struct timer_list *os_timer = &timer->os_timer;
146*5113495bSYour Name 
147*5113495bSYour Name 	os_timer->expires = jiffies + __qdf_scaled_msecs_to_jiffies(msec);
148*5113495bSYour Name 	add_timer_on(os_timer, cpu);
149*5113495bSYour Name }
150*5113495bSYour Name 
__qdf_timer_mod(struct __qdf_timer_t * timer,uint32_t msec)151*5113495bSYour Name static inline bool __qdf_timer_mod(struct __qdf_timer_t *timer, uint32_t msec)
152*5113495bSYour Name {
153*5113495bSYour Name 	return mod_timer(&timer->os_timer,
154*5113495bSYour Name 			 jiffies + __qdf_scaled_msecs_to_jiffies(msec));
155*5113495bSYour Name }
156*5113495bSYour Name 
__qdf_timer_stop(struct __qdf_timer_t * timer)157*5113495bSYour Name static inline bool __qdf_timer_stop(struct __qdf_timer_t *timer)
158*5113495bSYour Name {
159*5113495bSYour Name 	return !!del_timer(&timer->os_timer);
160*5113495bSYour Name }
161*5113495bSYour Name 
__qdf_timer_free(struct __qdf_timer_t * timer)162*5113495bSYour Name static inline void __qdf_timer_free(struct __qdf_timer_t *timer)
163*5113495bSYour Name {
164*5113495bSYour Name 	struct timer_list *os_timer = &timer->os_timer;
165*5113495bSYour Name 
166*5113495bSYour Name 	del_timer_sync(os_timer);
167*5113495bSYour Name 
168*5113495bSYour Name 	if (object_is_on_stack(os_timer))
169*5113495bSYour Name 		destroy_timer_on_stack(os_timer);
170*5113495bSYour Name }
171*5113495bSYour Name 
__qdf_timer_sync_cancel(struct __qdf_timer_t * timer)172*5113495bSYour Name static inline bool __qdf_timer_sync_cancel(struct __qdf_timer_t *timer)
173*5113495bSYour Name {
174*5113495bSYour Name 	return del_timer_sync(&timer->os_timer);
175*5113495bSYour Name }
176*5113495bSYour Name 
177*5113495bSYour Name #endif /* _I_QDF_TIMER_H */
178