xref: /wlan-driver/qca-wifi-host-cmn/qdf/linux/src/qdf_mc_timer.c (revision 5113495b16420b49004c444715d2daae2066e7dc)
1*5113495bSYour Name /*
2*5113495bSYour Name  * Copyright (c) 2014-2021 The Linux Foundation. All rights reserved.
3*5113495bSYour Name  * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
4*5113495bSYour Name  *
5*5113495bSYour Name  * Permission to use, copy, modify, and/or distribute this software for
6*5113495bSYour Name  * any purpose with or without fee is hereby granted, provided that the
7*5113495bSYour Name  * above copyright notice and this permission notice appear in all
8*5113495bSYour Name  * copies.
9*5113495bSYour Name  *
10*5113495bSYour Name  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11*5113495bSYour Name  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12*5113495bSYour Name  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13*5113495bSYour Name  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14*5113495bSYour Name  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15*5113495bSYour Name  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16*5113495bSYour Name  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17*5113495bSYour Name  * PERFORMANCE OF THIS SOFTWARE.
18*5113495bSYour Name  */
19*5113495bSYour Name 
20*5113495bSYour Name /**
21*5113495bSYour Name  * DOC: qdf_mc_timer
22*5113495bSYour Name  * QCA driver framework timer APIs serialized to MC thread
23*5113495bSYour Name  */
24*5113495bSYour Name 
25*5113495bSYour Name /* Include Files */
26*5113495bSYour Name #include <qdf_debug_domain.h>
27*5113495bSYour Name #include <qdf_mc_timer.h>
28*5113495bSYour Name #include <qdf_lock.h>
29*5113495bSYour Name #include "qdf_lock.h"
30*5113495bSYour Name #include "qdf_list.h"
31*5113495bSYour Name #include "qdf_mem.h"
32*5113495bSYour Name #include <qdf_module.h>
33*5113495bSYour Name #include "qdf_timer.h"
34*5113495bSYour Name #include <linux/time64.h>
35*5113495bSYour Name 
36*5113495bSYour Name /* Preprocessor definitions and constants */
37*5113495bSYour Name #define LINUX_TIMER_COOKIE 0x12341234
38*5113495bSYour Name #define LINUX_INVALID_TIMER_COOKIE 0xfeedface
39*5113495bSYour Name #define TMR_INVALID_ID (0)
40*5113495bSYour Name 
41*5113495bSYour Name #ifdef QDF_TIMER_MULTIPLIER_FRAC
42*5113495bSYour Name static uint32_t g_qdf_timer_multiplier = QDF_TIMER_MULTIPLIER_FRAC;
43*5113495bSYour Name #else
44*5113495bSYour Name static uint32_t g_qdf_timer_multiplier = 1;
45*5113495bSYour Name #endif
46*5113495bSYour Name 
qdf_timer_set_multiplier(uint32_t multiplier)47*5113495bSYour Name inline void qdf_timer_set_multiplier(uint32_t multiplier)
48*5113495bSYour Name {
49*5113495bSYour Name 	g_qdf_timer_multiplier = multiplier;
50*5113495bSYour Name }
51*5113495bSYour Name qdf_export_symbol(qdf_timer_set_multiplier);
52*5113495bSYour Name 
qdf_timer_get_multiplier(void)53*5113495bSYour Name inline uint32_t qdf_timer_get_multiplier(void)
54*5113495bSYour Name {
55*5113495bSYour Name 	return g_qdf_timer_multiplier;
56*5113495bSYour Name }
57*5113495bSYour Name qdf_export_symbol(qdf_timer_get_multiplier);
58*5113495bSYour Name 
59*5113495bSYour Name /* Type declarations */
60*5113495bSYour Name 
61*5113495bSYour Name /* Static Variable Definitions */
62*5113495bSYour Name static unsigned int persistent_timer_count;
63*5113495bSYour Name static qdf_mutex_t persistent_timer_count_lock;
64*5113495bSYour Name 
65*5113495bSYour Name static void (*scheduler_timer_callback)(qdf_mc_timer_t *);
qdf_register_mc_timer_callback(void (* callback)(qdf_mc_timer_t *))66*5113495bSYour Name void qdf_register_mc_timer_callback(void (*callback) (qdf_mc_timer_t *))
67*5113495bSYour Name {
68*5113495bSYour Name 	scheduler_timer_callback = callback;
69*5113495bSYour Name }
70*5113495bSYour Name 
71*5113495bSYour Name qdf_export_symbol(qdf_register_mc_timer_callback);
72*5113495bSYour Name 
73*5113495bSYour Name /* Function declarations and documentation */
74*5113495bSYour Name 
qdf_try_allowing_sleep(QDF_TIMER_TYPE type)75*5113495bSYour Name void qdf_try_allowing_sleep(QDF_TIMER_TYPE type)
76*5113495bSYour Name {
77*5113495bSYour Name 	if (QDF_TIMER_TYPE_WAKE_APPS == type) {
78*5113495bSYour Name 
79*5113495bSYour Name 		persistent_timer_count--;
80*5113495bSYour Name 		if (0 == persistent_timer_count) {
81*5113495bSYour Name 			/* since the number of persistent timers has
82*5113495bSYour Name 			 * decreased from 1 to 0, the timer should allow
83*5113495bSYour Name 			 * sleep
84*5113495bSYour Name 			 */
85*5113495bSYour Name 		}
86*5113495bSYour Name 	}
87*5113495bSYour Name }
88*5113495bSYour Name qdf_export_symbol(qdf_try_allowing_sleep);
89*5113495bSYour Name 
qdf_mc_timer_get_current_state(qdf_mc_timer_t * timer)90*5113495bSYour Name QDF_TIMER_STATE qdf_mc_timer_get_current_state(qdf_mc_timer_t *timer)
91*5113495bSYour Name {
92*5113495bSYour Name 	QDF_TIMER_STATE timer_state = QDF_TIMER_STATE_UNUSED;
93*5113495bSYour Name 
94*5113495bSYour Name 	if (!timer) {
95*5113495bSYour Name 		QDF_ASSERT(0);
96*5113495bSYour Name 		return timer_state;
97*5113495bSYour Name 	}
98*5113495bSYour Name 
99*5113495bSYour Name 	qdf_spin_lock_irqsave(&timer->platform_info.spinlock);
100*5113495bSYour Name 
101*5113495bSYour Name 	switch (timer->state) {
102*5113495bSYour Name 	case QDF_TIMER_STATE_STOPPED:
103*5113495bSYour Name 	case QDF_TIMER_STATE_STARTING:
104*5113495bSYour Name 	case QDF_TIMER_STATE_RUNNING:
105*5113495bSYour Name 	case QDF_TIMER_STATE_UNUSED:
106*5113495bSYour Name 		timer_state = timer->state;
107*5113495bSYour Name 		break;
108*5113495bSYour Name 	default:
109*5113495bSYour Name 		QDF_ASSERT(0);
110*5113495bSYour Name 	}
111*5113495bSYour Name 	qdf_spin_unlock_irqrestore(&timer->platform_info.spinlock);
112*5113495bSYour Name 	return timer_state;
113*5113495bSYour Name }
114*5113495bSYour Name qdf_export_symbol(qdf_mc_timer_get_current_state);
115*5113495bSYour Name 
qdf_timer_module_init(void)116*5113495bSYour Name void qdf_timer_module_init(void)
117*5113495bSYour Name {
118*5113495bSYour Name 	QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_INFO_HIGH,
119*5113495bSYour Name 		  "Initializing the QDF MC timer module");
120*5113495bSYour Name 	qdf_mutex_create(&persistent_timer_count_lock);
121*5113495bSYour Name }
122*5113495bSYour Name qdf_export_symbol(qdf_timer_module_init);
123*5113495bSYour Name 
124*5113495bSYour Name #ifdef TIMER_MANAGER
125*5113495bSYour Name 
126*5113495bSYour Name static qdf_list_t qdf_timer_domains[QDF_DEBUG_DOMAIN_COUNT];
127*5113495bSYour Name static qdf_spinlock_t qdf_timer_list_lock;
128*5113495bSYour Name 
qdf_timer_list_get(enum qdf_debug_domain domain)129*5113495bSYour Name static inline qdf_list_t *qdf_timer_list_get(enum qdf_debug_domain domain)
130*5113495bSYour Name {
131*5113495bSYour Name 	return &qdf_timer_domains[domain];
132*5113495bSYour Name }
133*5113495bSYour Name 
qdf_mc_timer_manager_init(void)134*5113495bSYour Name void qdf_mc_timer_manager_init(void)
135*5113495bSYour Name {
136*5113495bSYour Name 	int i;
137*5113495bSYour Name 
138*5113495bSYour Name 	for (i = 0; i < QDF_DEBUG_DOMAIN_COUNT; ++i)
139*5113495bSYour Name 		qdf_list_create(&qdf_timer_domains[i], 1000);
140*5113495bSYour Name 	qdf_spinlock_create(&qdf_timer_list_lock);
141*5113495bSYour Name }
142*5113495bSYour Name qdf_export_symbol(qdf_mc_timer_manager_init);
143*5113495bSYour Name 
qdf_mc_timer_print_list(qdf_list_t * timers)144*5113495bSYour Name static void qdf_mc_timer_print_list(qdf_list_t *timers)
145*5113495bSYour Name {
146*5113495bSYour Name 	QDF_STATUS status;
147*5113495bSYour Name 	qdf_list_node_t *node;
148*5113495bSYour Name 
149*5113495bSYour Name 	qdf_spin_lock_irqsave(&qdf_timer_list_lock);
150*5113495bSYour Name 	status = qdf_list_peek_front(timers, &node);
151*5113495bSYour Name 	while (QDF_IS_STATUS_SUCCESS(status)) {
152*5113495bSYour Name 		qdf_mc_timer_node_t *timer_node = (qdf_mc_timer_node_t *)node;
153*5113495bSYour Name 		const char *filename = kbasename(timer_node->file_name);
154*5113495bSYour Name 		uint32_t line = timer_node->line_num;
155*5113495bSYour Name 
156*5113495bSYour Name 		qdf_spin_unlock_irqrestore(&qdf_timer_list_lock);
157*5113495bSYour Name 		qdf_err("timer Leak@ File %s, @Line %u", filename, line);
158*5113495bSYour Name 		qdf_spin_lock_irqsave(&qdf_timer_list_lock);
159*5113495bSYour Name 
160*5113495bSYour Name 		status = qdf_list_peek_next(timers, node, &node);
161*5113495bSYour Name 	}
162*5113495bSYour Name 	qdf_spin_unlock_irqrestore(&qdf_timer_list_lock);
163*5113495bSYour Name }
164*5113495bSYour Name 
qdf_mc_timer_check_for_leaks(void)165*5113495bSYour Name void qdf_mc_timer_check_for_leaks(void)
166*5113495bSYour Name {
167*5113495bSYour Name 	enum qdf_debug_domain current_domain = qdf_debug_domain_get();
168*5113495bSYour Name 	qdf_list_t *timers = qdf_timer_list_get(current_domain);
169*5113495bSYour Name 
170*5113495bSYour Name 	if (qdf_list_empty(timers))
171*5113495bSYour Name 		return;
172*5113495bSYour Name 
173*5113495bSYour Name 	qdf_err("Timer leaks detected in %s domain!",
174*5113495bSYour Name 		qdf_debug_domain_name(current_domain));
175*5113495bSYour Name 	qdf_mc_timer_print_list(timers);
176*5113495bSYour Name 	QDF_DEBUG_PANIC("Previously reported timer leaks detected");
177*5113495bSYour Name }
178*5113495bSYour Name 
qdf_mc_timer_free_leaked_timers(qdf_list_t * timers)179*5113495bSYour Name static void qdf_mc_timer_free_leaked_timers(qdf_list_t *timers)
180*5113495bSYour Name {
181*5113495bSYour Name 	QDF_STATUS status;
182*5113495bSYour Name 	qdf_list_node_t *node;
183*5113495bSYour Name 
184*5113495bSYour Name 	qdf_spin_lock_irqsave(&qdf_timer_list_lock);
185*5113495bSYour Name 	status = qdf_list_remove_front(timers, &node);
186*5113495bSYour Name 	while (QDF_IS_STATUS_SUCCESS(status)) {
187*5113495bSYour Name 		qdf_mem_free(node);
188*5113495bSYour Name 		status = qdf_list_remove_front(timers, &node);
189*5113495bSYour Name 	}
190*5113495bSYour Name 	qdf_spin_unlock_irqrestore(&qdf_timer_list_lock);
191*5113495bSYour Name }
192*5113495bSYour Name 
193*5113495bSYour Name /**
194*5113495bSYour Name  * qdf_timer_clean() - clean up QDF timer debug functionality
195*5113495bSYour Name  *
196*5113495bSYour Name  * This API cleans up QDF timer debug functionality and prints which QDF timers
197*5113495bSYour Name  * are leaked. This is called during driver unload.
198*5113495bSYour Name  *
199*5113495bSYour Name  * Return: none
200*5113495bSYour Name  */
qdf_timer_clean(void)201*5113495bSYour Name static void qdf_timer_clean(void)
202*5113495bSYour Name {
203*5113495bSYour Name 	bool leaks_detected = false;
204*5113495bSYour Name 	int i;
205*5113495bSYour Name 
206*5113495bSYour Name 	/* detect and print leaks */
207*5113495bSYour Name 	for (i = 0; i < QDF_DEBUG_DOMAIN_COUNT; ++i) {
208*5113495bSYour Name 		qdf_list_t *timers = &qdf_timer_domains[i];
209*5113495bSYour Name 
210*5113495bSYour Name 		if (qdf_list_empty(timers))
211*5113495bSYour Name 			continue;
212*5113495bSYour Name 
213*5113495bSYour Name 		leaks_detected = true;
214*5113495bSYour Name 
215*5113495bSYour Name 		qdf_err("\nTimer leaks detected in the %s (Id %d) domain!",
216*5113495bSYour Name 			qdf_debug_domain_name(i), i);
217*5113495bSYour Name 		qdf_mc_timer_print_list(timers);
218*5113495bSYour Name 	}
219*5113495bSYour Name 
220*5113495bSYour Name 	/* we're done if there were no leaks */
221*5113495bSYour Name 	if (!leaks_detected)
222*5113495bSYour Name 		return;
223*5113495bSYour Name 
224*5113495bSYour Name 	/* panic, if enabled */
225*5113495bSYour Name 	QDF_DEBUG_PANIC("Previously reported timer leaks detected");
226*5113495bSYour Name 
227*5113495bSYour Name 	/* if we didn't crash, release the leaked timers */
228*5113495bSYour Name 	for (i = 0; i < QDF_DEBUG_DOMAIN_COUNT; ++i)
229*5113495bSYour Name 		qdf_mc_timer_free_leaked_timers(&qdf_timer_domains[i]);
230*5113495bSYour Name }
231*5113495bSYour Name 
qdf_mc_timer_manager_exit(void)232*5113495bSYour Name void qdf_mc_timer_manager_exit(void)
233*5113495bSYour Name {
234*5113495bSYour Name 	int i;
235*5113495bSYour Name 
236*5113495bSYour Name 	qdf_timer_clean();
237*5113495bSYour Name 
238*5113495bSYour Name 	for (i = 0; i < QDF_DEBUG_DOMAIN_COUNT; ++i)
239*5113495bSYour Name 		qdf_list_destroy(&qdf_timer_domains[i]);
240*5113495bSYour Name 
241*5113495bSYour Name 	qdf_spinlock_destroy(&qdf_timer_list_lock);
242*5113495bSYour Name }
243*5113495bSYour Name qdf_export_symbol(qdf_mc_timer_manager_exit);
244*5113495bSYour Name #endif
245*5113495bSYour Name 
246*5113495bSYour Name #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)
__os_mc_timer_shim(struct timer_list * os_timer)247*5113495bSYour Name static void __os_mc_timer_shim(struct timer_list *os_timer)
248*5113495bSYour Name {
249*5113495bSYour Name 	qdf_mc_timer_platform_t *platform_info_ptr =
250*5113495bSYour Name 				qdf_container_of(os_timer,
251*5113495bSYour Name 						 qdf_mc_timer_platform_t,
252*5113495bSYour Name 						 timer);
253*5113495bSYour Name 	qdf_mc_timer_t *timer = qdf_container_of(platform_info_ptr,
254*5113495bSYour Name 						 qdf_mc_timer_t,
255*5113495bSYour Name 						 platform_info);
256*5113495bSYour Name 
257*5113495bSYour Name 	scheduler_timer_callback(timer);
258*5113495bSYour Name }
259*5113495bSYour Name 
qdf_mc_timer_setup(qdf_mc_timer_t * timer,QDF_TIMER_TYPE timer_type)260*5113495bSYour Name static void qdf_mc_timer_setup(qdf_mc_timer_t *timer,
261*5113495bSYour Name 			       QDF_TIMER_TYPE timer_type)
262*5113495bSYour Name {
263*5113495bSYour Name 	uint32_t flags = 0;
264*5113495bSYour Name 
265*5113495bSYour Name 	if (QDF_TIMER_TYPE_SW == timer_type)
266*5113495bSYour Name 		flags |= TIMER_DEFERRABLE;
267*5113495bSYour Name 
268*5113495bSYour Name 	timer_setup(&timer->platform_info.timer,
269*5113495bSYour Name 		    __os_mc_timer_shim, flags);
270*5113495bSYour Name }
271*5113495bSYour Name #else
__os_mc_timer_shim(unsigned long data)272*5113495bSYour Name static void __os_mc_timer_shim(unsigned long data)
273*5113495bSYour Name {
274*5113495bSYour Name 	qdf_mc_timer_t *timer = (qdf_mc_timer_t *)data;
275*5113495bSYour Name 
276*5113495bSYour Name 	scheduler_timer_callback(timer);
277*5113495bSYour Name }
278*5113495bSYour Name 
qdf_mc_timer_setup(qdf_mc_timer_t * timer,QDF_TIMER_TYPE timer_type)279*5113495bSYour Name static void qdf_mc_timer_setup(qdf_mc_timer_t *timer,
280*5113495bSYour Name 			       QDF_TIMER_TYPE timer_type)
281*5113495bSYour Name {
282*5113495bSYour Name 	if (QDF_TIMER_TYPE_SW == timer_type)
283*5113495bSYour Name 		init_timer_deferrable(&timer->platform_info.timer);
284*5113495bSYour Name 	else
285*5113495bSYour Name 		init_timer(&timer->platform_info.timer);
286*5113495bSYour Name 
287*5113495bSYour Name 	timer->platform_info.timer.function = __os_mc_timer_shim;
288*5113495bSYour Name 	timer->platform_info.timer.data = (unsigned long)timer;
289*5113495bSYour Name }
290*5113495bSYour Name #endif
291*5113495bSYour Name #ifdef TIMER_MANAGER
qdf_mc_timer_init_debug(qdf_mc_timer_t * timer,QDF_TIMER_TYPE timer_type,qdf_mc_timer_callback_t callback,void * user_data,char * file_name,uint32_t line_num)292*5113495bSYour Name QDF_STATUS qdf_mc_timer_init_debug(qdf_mc_timer_t *timer,
293*5113495bSYour Name 				   QDF_TIMER_TYPE timer_type,
294*5113495bSYour Name 				   qdf_mc_timer_callback_t callback,
295*5113495bSYour Name 				   void *user_data, char *file_name,
296*5113495bSYour Name 				   uint32_t line_num)
297*5113495bSYour Name {
298*5113495bSYour Name 	enum qdf_debug_domain current_domain = qdf_debug_domain_get();
299*5113495bSYour Name 	qdf_list_t *active_timers = qdf_timer_list_get(current_domain);
300*5113495bSYour Name 	QDF_STATUS qdf_status;
301*5113495bSYour Name 
302*5113495bSYour Name 	/* check for invalid pointer */
303*5113495bSYour Name 	if ((!timer) || (!callback)) {
304*5113495bSYour Name 		QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
305*5113495bSYour Name 			  "%s: Null params being passed", __func__);
306*5113495bSYour Name 		QDF_ASSERT(0);
307*5113495bSYour Name 		return QDF_STATUS_E_FAULT;
308*5113495bSYour Name 	}
309*5113495bSYour Name 
310*5113495bSYour Name 	timer->timer_node = qdf_mem_malloc(sizeof(qdf_mc_timer_node_t));
311*5113495bSYour Name 
312*5113495bSYour Name 	if (!timer->timer_node) {
313*5113495bSYour Name 		QDF_ASSERT(0);
314*5113495bSYour Name 		return QDF_STATUS_E_NOMEM;
315*5113495bSYour Name 	}
316*5113495bSYour Name 
317*5113495bSYour Name 	timer->timer_node->file_name = file_name;
318*5113495bSYour Name 	timer->timer_node->line_num = line_num;
319*5113495bSYour Name 	timer->timer_node->qdf_timer = timer;
320*5113495bSYour Name 
321*5113495bSYour Name 	qdf_spin_lock_irqsave(&qdf_timer_list_lock);
322*5113495bSYour Name 	qdf_status = qdf_list_insert_front(active_timers,
323*5113495bSYour Name 					   &timer->timer_node->node);
324*5113495bSYour Name 	qdf_spin_unlock_irqrestore(&qdf_timer_list_lock);
325*5113495bSYour Name 	if (QDF_STATUS_SUCCESS != qdf_status) {
326*5113495bSYour Name 		QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
327*5113495bSYour Name 			  "%s: Unable to insert node into List qdf_status %d",
328*5113495bSYour Name 			  __func__, qdf_status);
329*5113495bSYour Name 	}
330*5113495bSYour Name 
331*5113495bSYour Name 	/* set the various members of the timer structure
332*5113495bSYour Name 	 * with arguments passed or with default values
333*5113495bSYour Name 	 */
334*5113495bSYour Name 	qdf_spinlock_create(&timer->platform_info.spinlock);
335*5113495bSYour Name 	qdf_mc_timer_setup(timer, timer_type);
336*5113495bSYour Name 	timer->callback = callback;
337*5113495bSYour Name 	timer->user_data = user_data;
338*5113495bSYour Name 	timer->type = timer_type;
339*5113495bSYour Name 	timer->platform_info.cookie = LINUX_TIMER_COOKIE;
340*5113495bSYour Name 	timer->platform_info.thread_id = 0;
341*5113495bSYour Name 	timer->state = QDF_TIMER_STATE_STOPPED;
342*5113495bSYour Name 
343*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
344*5113495bSYour Name }
345*5113495bSYour Name qdf_export_symbol(qdf_mc_timer_init_debug);
346*5113495bSYour Name #else
qdf_mc_timer_init(qdf_mc_timer_t * timer,QDF_TIMER_TYPE timer_type,qdf_mc_timer_callback_t callback,void * user_data)347*5113495bSYour Name QDF_STATUS qdf_mc_timer_init(qdf_mc_timer_t *timer, QDF_TIMER_TYPE timer_type,
348*5113495bSYour Name 			     qdf_mc_timer_callback_t callback,
349*5113495bSYour Name 			     void *user_data)
350*5113495bSYour Name {
351*5113495bSYour Name 	/* check for invalid pointer */
352*5113495bSYour Name 	if ((!timer) || (!callback)) {
353*5113495bSYour Name 		QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
354*5113495bSYour Name 			  "%s: Null params being passed", __func__);
355*5113495bSYour Name 		QDF_ASSERT(0);
356*5113495bSYour Name 		return QDF_STATUS_E_FAULT;
357*5113495bSYour Name 	}
358*5113495bSYour Name 
359*5113495bSYour Name 	/* set the various members of the timer structure
360*5113495bSYour Name 	 * with arguments passed or with default values
361*5113495bSYour Name 	 */
362*5113495bSYour Name 	qdf_spinlock_create(&timer->platform_info.spinlock);
363*5113495bSYour Name 	qdf_mc_timer_setup(timer, timer_type);
364*5113495bSYour Name 	timer->callback = callback;
365*5113495bSYour Name 	timer->user_data = user_data;
366*5113495bSYour Name 	timer->type = timer_type;
367*5113495bSYour Name 	timer->platform_info.cookie = LINUX_TIMER_COOKIE;
368*5113495bSYour Name 	timer->platform_info.thread_id = 0;
369*5113495bSYour Name 	timer->state = QDF_TIMER_STATE_STOPPED;
370*5113495bSYour Name 
371*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
372*5113495bSYour Name }
373*5113495bSYour Name qdf_export_symbol(qdf_mc_timer_init);
374*5113495bSYour Name #endif
375*5113495bSYour Name 
376*5113495bSYour Name #ifdef TIMER_MANAGER
qdf_mc_timer_destroy(qdf_mc_timer_t * timer)377*5113495bSYour Name QDF_STATUS qdf_mc_timer_destroy(qdf_mc_timer_t *timer)
378*5113495bSYour Name {
379*5113495bSYour Name 	enum qdf_debug_domain current_domain = qdf_debug_domain_get();
380*5113495bSYour Name 	qdf_list_t *active_timers = qdf_timer_list_get(current_domain);
381*5113495bSYour Name 	QDF_STATUS v_status = QDF_STATUS_SUCCESS;
382*5113495bSYour Name 
383*5113495bSYour Name 	/* check for invalid pointer */
384*5113495bSYour Name 	if (!timer) {
385*5113495bSYour Name 		QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
386*5113495bSYour Name 			  "%s: Null timer pointer being passed", __func__);
387*5113495bSYour Name 		QDF_ASSERT(0);
388*5113495bSYour Name 		return QDF_STATUS_E_FAULT;
389*5113495bSYour Name 	}
390*5113495bSYour Name 
391*5113495bSYour Name 	/* Check if timer refers to an uninitialized object */
392*5113495bSYour Name 	if (LINUX_TIMER_COOKIE != timer->platform_info.cookie) {
393*5113495bSYour Name 		QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
394*5113495bSYour Name 			  "%s: Cannot destroy uninitialized timer", __func__);
395*5113495bSYour Name 		QDF_ASSERT(0);
396*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
397*5113495bSYour Name 	}
398*5113495bSYour Name 
399*5113495bSYour Name 	qdf_spin_lock_irqsave(&qdf_timer_list_lock);
400*5113495bSYour Name 	v_status = qdf_list_remove_node(active_timers,
401*5113495bSYour Name 					&timer->timer_node->node);
402*5113495bSYour Name 	qdf_spin_unlock_irqrestore(&qdf_timer_list_lock);
403*5113495bSYour Name 	if (v_status != QDF_STATUS_SUCCESS) {
404*5113495bSYour Name 		QDF_ASSERT(0);
405*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
406*5113495bSYour Name 	}
407*5113495bSYour Name 	qdf_mem_free(timer->timer_node);
408*5113495bSYour Name 
409*5113495bSYour Name 	qdf_spin_lock_irqsave(&timer->platform_info.spinlock);
410*5113495bSYour Name 
411*5113495bSYour Name 	switch (timer->state) {
412*5113495bSYour Name 
413*5113495bSYour Name 	case QDF_TIMER_STATE_STARTING:
414*5113495bSYour Name 		v_status = QDF_STATUS_E_BUSY;
415*5113495bSYour Name 		break;
416*5113495bSYour Name 
417*5113495bSYour Name 	case QDF_TIMER_STATE_RUNNING:
418*5113495bSYour Name 		/* Stop the timer first */
419*5113495bSYour Name 		del_timer(&(timer->platform_info.timer));
420*5113495bSYour Name 		v_status = QDF_STATUS_SUCCESS;
421*5113495bSYour Name 		break;
422*5113495bSYour Name 	case QDF_TIMER_STATE_STOPPED:
423*5113495bSYour Name 		v_status = QDF_STATUS_SUCCESS;
424*5113495bSYour Name 		break;
425*5113495bSYour Name 
426*5113495bSYour Name 	case QDF_TIMER_STATE_UNUSED:
427*5113495bSYour Name 		v_status = QDF_STATUS_E_ALREADY;
428*5113495bSYour Name 		break;
429*5113495bSYour Name 
430*5113495bSYour Name 	default:
431*5113495bSYour Name 		v_status = QDF_STATUS_E_FAULT;
432*5113495bSYour Name 		break;
433*5113495bSYour Name 	}
434*5113495bSYour Name 
435*5113495bSYour Name 	if (QDF_STATUS_SUCCESS == v_status) {
436*5113495bSYour Name 		timer->platform_info.cookie = LINUX_INVALID_TIMER_COOKIE;
437*5113495bSYour Name 		timer->state = QDF_TIMER_STATE_UNUSED;
438*5113495bSYour Name 		qdf_spin_unlock_irqrestore(&timer->platform_info.spinlock);
439*5113495bSYour Name 		qdf_spinlock_destroy(&timer->platform_info.spinlock);
440*5113495bSYour Name 		return v_status;
441*5113495bSYour Name 	}
442*5113495bSYour Name 
443*5113495bSYour Name 	qdf_spin_unlock_irqrestore(&timer->platform_info.spinlock);
444*5113495bSYour Name 
445*5113495bSYour Name 	QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_INFO_HIGH,
446*5113495bSYour Name 		  "%s: Cannot destroy timer in state = %d", __func__,
447*5113495bSYour Name 		  timer->state);
448*5113495bSYour Name 	QDF_ASSERT(0);
449*5113495bSYour Name 
450*5113495bSYour Name 	return v_status;
451*5113495bSYour Name }
452*5113495bSYour Name qdf_export_symbol(qdf_mc_timer_destroy);
453*5113495bSYour Name 
454*5113495bSYour Name #else
455*5113495bSYour Name 
qdf_mc_timer_destroy(qdf_mc_timer_t * timer)456*5113495bSYour Name QDF_STATUS qdf_mc_timer_destroy(qdf_mc_timer_t *timer)
457*5113495bSYour Name {
458*5113495bSYour Name 	QDF_STATUS v_status = QDF_STATUS_SUCCESS;
459*5113495bSYour Name 
460*5113495bSYour Name 	/* check for invalid pointer */
461*5113495bSYour Name 	if (!timer) {
462*5113495bSYour Name 		QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
463*5113495bSYour Name 			  "%s: Null timer pointer being passed", __func__);
464*5113495bSYour Name 		QDF_ASSERT(0);
465*5113495bSYour Name 		return QDF_STATUS_E_FAULT;
466*5113495bSYour Name 	}
467*5113495bSYour Name 
468*5113495bSYour Name 	/* check if timer refers to an uninitialized object */
469*5113495bSYour Name 	if (LINUX_TIMER_COOKIE != timer->platform_info.cookie) {
470*5113495bSYour Name 		QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
471*5113495bSYour Name 			  "%s: Cannot destroy uninitialized timer", __func__);
472*5113495bSYour Name 		QDF_ASSERT(0);
473*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
474*5113495bSYour Name 	}
475*5113495bSYour Name 	qdf_spin_lock_irqsave(&timer->platform_info.spinlock);
476*5113495bSYour Name 
477*5113495bSYour Name 	switch (timer->state) {
478*5113495bSYour Name 
479*5113495bSYour Name 	case QDF_TIMER_STATE_STARTING:
480*5113495bSYour Name 		v_status = QDF_STATUS_E_BUSY;
481*5113495bSYour Name 		break;
482*5113495bSYour Name 
483*5113495bSYour Name 	case QDF_TIMER_STATE_RUNNING:
484*5113495bSYour Name 		/* Stop the timer first */
485*5113495bSYour Name 		del_timer(&(timer->platform_info.timer));
486*5113495bSYour Name 		v_status = QDF_STATUS_SUCCESS;
487*5113495bSYour Name 		break;
488*5113495bSYour Name 
489*5113495bSYour Name 	case QDF_TIMER_STATE_STOPPED:
490*5113495bSYour Name 		v_status = QDF_STATUS_SUCCESS;
491*5113495bSYour Name 		break;
492*5113495bSYour Name 
493*5113495bSYour Name 	case QDF_TIMER_STATE_UNUSED:
494*5113495bSYour Name 		v_status = QDF_STATUS_E_ALREADY;
495*5113495bSYour Name 		break;
496*5113495bSYour Name 
497*5113495bSYour Name 	default:
498*5113495bSYour Name 		v_status = QDF_STATUS_E_FAULT;
499*5113495bSYour Name 		break;
500*5113495bSYour Name 	}
501*5113495bSYour Name 
502*5113495bSYour Name 	if (QDF_STATUS_SUCCESS == v_status) {
503*5113495bSYour Name 		timer->platform_info.cookie = LINUX_INVALID_TIMER_COOKIE;
504*5113495bSYour Name 		timer->state = QDF_TIMER_STATE_UNUSED;
505*5113495bSYour Name 		qdf_spin_unlock_irqrestore(&timer->platform_info.spinlock);
506*5113495bSYour Name 		return v_status;
507*5113495bSYour Name 	}
508*5113495bSYour Name 
509*5113495bSYour Name 	qdf_spin_unlock_irqrestore(&timer->platform_info.spinlock);
510*5113495bSYour Name 
511*5113495bSYour Name 	QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_INFO_HIGH,
512*5113495bSYour Name 		  "%s: Cannot destroy timer in state = %d", __func__,
513*5113495bSYour Name 		  timer->state);
514*5113495bSYour Name 	QDF_ASSERT(0);
515*5113495bSYour Name 
516*5113495bSYour Name 	return v_status;
517*5113495bSYour Name }
518*5113495bSYour Name qdf_export_symbol(qdf_mc_timer_destroy);
519*5113495bSYour Name #endif
520*5113495bSYour Name 
qdf_mc_timer_start(qdf_mc_timer_t * timer,uint32_t expiration_time)521*5113495bSYour Name QDF_STATUS qdf_mc_timer_start(qdf_mc_timer_t *timer, uint32_t expiration_time)
522*5113495bSYour Name {
523*5113495bSYour Name 	/* check for invalid pointer */
524*5113495bSYour Name 	if (!timer) {
525*5113495bSYour Name 		QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
526*5113495bSYour Name 			  "%s Null timer pointer being passed", __func__);
527*5113495bSYour Name 		QDF_ASSERT(0);
528*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
529*5113495bSYour Name 	}
530*5113495bSYour Name 
531*5113495bSYour Name 	/* check if timer refers to an uninitialized object */
532*5113495bSYour Name 	if (LINUX_TIMER_COOKIE != timer->platform_info.cookie) {
533*5113495bSYour Name 		QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
534*5113495bSYour Name 			  "%s: Cannot start uninitialized timer", __func__);
535*5113495bSYour Name 		QDF_ASSERT(0);
536*5113495bSYour Name 
537*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
538*5113495bSYour Name 	}
539*5113495bSYour Name 
540*5113495bSYour Name 	/* check if timer has expiration time less than 10 ms */
541*5113495bSYour Name 	if (expiration_time < 10) {
542*5113495bSYour Name 		QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
543*5113495bSYour Name 			  "%s: Cannot start a timer with expiration less than 10 ms",
544*5113495bSYour Name 			  __func__);
545*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
546*5113495bSYour Name 	}
547*5113495bSYour Name 
548*5113495bSYour Name 	/* make sure the remainder of the logic isn't interrupted */
549*5113495bSYour Name 	qdf_spin_lock_irqsave(&timer->platform_info.spinlock);
550*5113495bSYour Name 
551*5113495bSYour Name 	/* ensure if the timer can be started */
552*5113495bSYour Name 	if (QDF_TIMER_STATE_STOPPED != timer->state) {
553*5113495bSYour Name 		qdf_spin_unlock_irqrestore(&timer->platform_info.spinlock);
554*5113495bSYour Name 		QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
555*5113495bSYour Name 			  "%s: Cannot start timer in state = %d %ps",
556*5113495bSYour Name 			  __func__, timer->state, (void *)timer->callback);
557*5113495bSYour Name 		return QDF_STATUS_E_ALREADY;
558*5113495bSYour Name 	}
559*5113495bSYour Name 
560*5113495bSYour Name 	/* start the timer */
561*5113495bSYour Name 	mod_timer(&(timer->platform_info.timer),
562*5113495bSYour Name 		  jiffies + __qdf_scaled_msecs_to_jiffies(expiration_time));
563*5113495bSYour Name 
564*5113495bSYour Name 	timer->state = QDF_TIMER_STATE_RUNNING;
565*5113495bSYour Name 
566*5113495bSYour Name 	/* Save the jiffies value in a per-timer context in qdf_mc_timer_t
567*5113495bSYour Name 	 * It will help the debugger to know the exact time at which the host
568*5113495bSYour Name 	 * starts the QDF timer.
569*5113495bSYour Name 	 */
570*5113495bSYour Name 	timer->timer_start_jiffies = jiffies;
571*5113495bSYour Name 
572*5113495bSYour Name 	/* get the thread ID on which the timer is being started */
573*5113495bSYour Name 	timer->platform_info.thread_id = current->pid;
574*5113495bSYour Name 
575*5113495bSYour Name 	if (QDF_TIMER_TYPE_WAKE_APPS == timer->type) {
576*5113495bSYour Name 		persistent_timer_count++;
577*5113495bSYour Name 		if (1 == persistent_timer_count) {
578*5113495bSYour Name 			/* since we now have one persistent timer,
579*5113495bSYour Name 			 * we need to disallow sleep
580*5113495bSYour Name 			 * sleep_negate_okts(sleep_client_handle);
581*5113495bSYour Name 			 */
582*5113495bSYour Name 		}
583*5113495bSYour Name 	}
584*5113495bSYour Name 
585*5113495bSYour Name 	qdf_spin_unlock_irqrestore(&timer->platform_info.spinlock);
586*5113495bSYour Name 
587*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
588*5113495bSYour Name }
589*5113495bSYour Name qdf_export_symbol(qdf_mc_timer_start);
590*5113495bSYour Name 
qdf_mc_timer_stop(qdf_mc_timer_t * timer)591*5113495bSYour Name QDF_STATUS qdf_mc_timer_stop(qdf_mc_timer_t *timer)
592*5113495bSYour Name {
593*5113495bSYour Name 	/* check for invalid pointer */
594*5113495bSYour Name 	if (!timer) {
595*5113495bSYour Name 		QDF_TRACE_DEBUG_RL(QDF_MODULE_ID_QDF,
596*5113495bSYour Name 				   "%s Null timer pointer", __func__);
597*5113495bSYour Name 		QDF_ASSERT(0);
598*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
599*5113495bSYour Name 	}
600*5113495bSYour Name 
601*5113495bSYour Name 	/* check if timer refers to an uninitialized object */
602*5113495bSYour Name 	if (LINUX_TIMER_COOKIE != timer->platform_info.cookie) {
603*5113495bSYour Name 		QDF_TRACE_DEBUG_RL(QDF_MODULE_ID_QDF,
604*5113495bSYour Name 				   "%s: Cannot stop uninit timer", __func__);
605*5113495bSYour Name 		QDF_ASSERT(0);
606*5113495bSYour Name 
607*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
608*5113495bSYour Name 	}
609*5113495bSYour Name 
610*5113495bSYour Name 	/* ensure the timer state is correct */
611*5113495bSYour Name 	qdf_spin_lock_irqsave(&timer->platform_info.spinlock);
612*5113495bSYour Name 
613*5113495bSYour Name 	if (QDF_TIMER_STATE_RUNNING != timer->state) {
614*5113495bSYour Name 		qdf_spin_unlock_irqrestore(&timer->platform_info.spinlock);
615*5113495bSYour Name 		return QDF_STATUS_SUCCESS;
616*5113495bSYour Name 	}
617*5113495bSYour Name 
618*5113495bSYour Name 	qdf_spin_unlock_irqrestore(&timer->platform_info.spinlock);
619*5113495bSYour Name 
620*5113495bSYour Name 	del_timer(&(timer->platform_info.timer));
621*5113495bSYour Name 
622*5113495bSYour Name 	qdf_spin_lock_irqsave(&timer->platform_info.spinlock);
623*5113495bSYour Name 	timer->state = QDF_TIMER_STATE_STOPPED;
624*5113495bSYour Name 	qdf_spin_unlock_irqrestore(&timer->platform_info.spinlock);
625*5113495bSYour Name 
626*5113495bSYour Name 	qdf_try_allowing_sleep(timer->type);
627*5113495bSYour Name 
628*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
629*5113495bSYour Name }
630*5113495bSYour Name qdf_export_symbol(qdf_mc_timer_stop);
631*5113495bSYour Name 
qdf_mc_timer_stop_sync(qdf_mc_timer_t * timer)632*5113495bSYour Name QDF_STATUS qdf_mc_timer_stop_sync(qdf_mc_timer_t *timer)
633*5113495bSYour Name {
634*5113495bSYour Name 	/* check for invalid pointer */
635*5113495bSYour Name 	if (!timer) {
636*5113495bSYour Name 		QDF_TRACE_DEBUG_RL(QDF_MODULE_ID_QDF,
637*5113495bSYour Name 				   "%s Null timer pointer", __func__);
638*5113495bSYour Name 		QDF_ASSERT(0);
639*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
640*5113495bSYour Name 	}
641*5113495bSYour Name 
642*5113495bSYour Name 	/* check if timer refers to an uninitialized object */
643*5113495bSYour Name 	if (LINUX_TIMER_COOKIE != timer->platform_info.cookie) {
644*5113495bSYour Name 		QDF_TRACE_DEBUG_RL(QDF_MODULE_ID_QDF,
645*5113495bSYour Name 				   "%s: Cannot stop uninit timer", __func__);
646*5113495bSYour Name 		QDF_ASSERT(0);
647*5113495bSYour Name 
648*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
649*5113495bSYour Name 	}
650*5113495bSYour Name 
651*5113495bSYour Name 	/* ensure the timer state is correct */
652*5113495bSYour Name 	qdf_spin_lock_irqsave(&timer->platform_info.spinlock);
653*5113495bSYour Name 
654*5113495bSYour Name 	if (QDF_TIMER_STATE_RUNNING != timer->state) {
655*5113495bSYour Name 		qdf_spin_unlock_irqrestore(&timer->platform_info.spinlock);
656*5113495bSYour Name 		return QDF_STATUS_SUCCESS;
657*5113495bSYour Name 	}
658*5113495bSYour Name 
659*5113495bSYour Name 	timer->state = QDF_TIMER_STATE_STOPPED;
660*5113495bSYour Name 
661*5113495bSYour Name 	qdf_spin_unlock_irqrestore(&timer->platform_info.spinlock);
662*5113495bSYour Name 	del_timer_sync(&(timer->platform_info.timer));
663*5113495bSYour Name 
664*5113495bSYour Name 	qdf_try_allowing_sleep(timer->type);
665*5113495bSYour Name 
666*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
667*5113495bSYour Name }
668*5113495bSYour Name qdf_export_symbol(qdf_mc_timer_stop_sync);
669*5113495bSYour Name 
qdf_mc_timer_get_system_ticks(void)670*5113495bSYour Name unsigned long qdf_mc_timer_get_system_ticks(void)
671*5113495bSYour Name {
672*5113495bSYour Name 	return jiffies_to_msecs(jiffies) / 10;
673*5113495bSYour Name }
674*5113495bSYour Name qdf_export_symbol(qdf_mc_timer_get_system_ticks);
675*5113495bSYour Name 
676*5113495bSYour Name #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0))
qdf_mc_timer_get_system_time(void)677*5113495bSYour Name unsigned long qdf_mc_timer_get_system_time(void)
678*5113495bSYour Name {
679*5113495bSYour Name 	struct timespec64 tv;
680*5113495bSYour Name 
681*5113495bSYour Name 	ktime_get_real_ts64(&tv);
682*5113495bSYour Name 	return tv.tv_sec * 1000 + tv.tv_nsec / 1000000;
683*5113495bSYour Name }
684*5113495bSYour Name qdf_export_symbol(qdf_mc_timer_get_system_time);
685*5113495bSYour Name 
686*5113495bSYour Name #else
qdf_mc_timer_get_system_time(void)687*5113495bSYour Name unsigned long qdf_mc_timer_get_system_time(void)
688*5113495bSYour Name {
689*5113495bSYour Name 	struct timeval tv;
690*5113495bSYour Name 
691*5113495bSYour Name 	do_gettimeofday(&tv);
692*5113495bSYour Name 	return tv.tv_sec * 1000 + tv.tv_usec / 1000;
693*5113495bSYour Name }
694*5113495bSYour Name qdf_export_symbol(qdf_mc_timer_get_system_time);
695*5113495bSYour Name #endif
696*5113495bSYour Name 
qdf_get_monotonic_boottime_ns(void)697*5113495bSYour Name s64 qdf_get_monotonic_boottime_ns(void)
698*5113495bSYour Name {
699*5113495bSYour Name 	return ktime_to_ns(ktime_get_boottime());
700*5113495bSYour Name }
701*5113495bSYour Name qdf_export_symbol(qdf_get_monotonic_boottime_ns);
702*5113495bSYour Name 
qdf_timer_module_deinit(void)703*5113495bSYour Name void qdf_timer_module_deinit(void)
704*5113495bSYour Name {
705*5113495bSYour Name 	QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_INFO_HIGH,
706*5113495bSYour Name 		  "De-Initializing the QDF MC timer module");
707*5113495bSYour Name 	qdf_mutex_destroy(&persistent_timer_count_lock);
708*5113495bSYour Name }
709*5113495bSYour Name qdf_export_symbol(qdf_timer_module_deinit);
710*5113495bSYour Name 
711*5113495bSYour Name #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0))
qdf_get_time_of_the_day_in_hr_min_sec_usec(char * tbuf,int len)712*5113495bSYour Name void qdf_get_time_of_the_day_in_hr_min_sec_usec(char *tbuf, int len)
713*5113495bSYour Name {
714*5113495bSYour Name 	struct timespec64 tv;
715*5113495bSYour Name 	struct rtc_time tm;
716*5113495bSYour Name 	unsigned long local_time;
717*5113495bSYour Name 
718*5113495bSYour Name 	/* Format the Log time R#: [hr:min:sec.microsec] */
719*5113495bSYour Name 	ktime_get_real_ts64(&tv);
720*5113495bSYour Name 	/* Convert rtc to local time */
721*5113495bSYour Name 	local_time = (u32)(tv.tv_sec - (sys_tz.tz_minuteswest * 60));
722*5113495bSYour Name 	rtc_time64_to_tm(local_time, &tm);
723*5113495bSYour Name 	scnprintf(tbuf, len,
724*5113495bSYour Name 		  "[%02d:%02d:%02d.%06lu]",
725*5113495bSYour Name 		  tm.tm_hour, tm.tm_min, tm.tm_sec, tv.tv_nsec / 1000);
726*5113495bSYour Name }
727*5113495bSYour Name 
728*5113495bSYour Name qdf_export_symbol(qdf_get_time_of_the_day_in_hr_min_sec_usec);
729*5113495bSYour Name 
qdf_get_time_of_the_day_us(void)730*5113495bSYour Name uint64_t qdf_get_time_of_the_day_us(void)
731*5113495bSYour Name {
732*5113495bSYour Name 	struct timespec64 tv;
733*5113495bSYour Name 	struct rtc_time tm;
734*5113495bSYour Name 	unsigned long local_time;
735*5113495bSYour Name 	uint64_t time_of_day_us = 0;
736*5113495bSYour Name 
737*5113495bSYour Name 	ktime_get_real_ts64(&tv);
738*5113495bSYour Name 	/* Convert rtc to local time */
739*5113495bSYour Name 	local_time = (u32)(tv.tv_sec - (sys_tz.tz_minuteswest * 60));
740*5113495bSYour Name 	rtc_time64_to_tm(local_time, &tm);
741*5113495bSYour Name 
742*5113495bSYour Name 	time_of_day_us += (uint64_t)tm.tm_hour * 60 * 60 * 1000 * 1000;
743*5113495bSYour Name 	time_of_day_us += (uint64_t)tm.tm_min * 60 * 1000 * 1000;
744*5113495bSYour Name 	time_of_day_us += (uint64_t)tm.tm_sec * 1000 * 1000;
745*5113495bSYour Name 	time_of_day_us += qdf_do_div((uint64_t)tv.tv_nsec,  1000);
746*5113495bSYour Name 
747*5113495bSYour Name 	return time_of_day_us;
748*5113495bSYour Name }
749*5113495bSYour Name 
750*5113495bSYour Name qdf_export_symbol(qdf_get_time_of_the_day_us);
751*5113495bSYour Name #else
qdf_get_time_of_the_day_in_hr_min_sec_usec(char * tbuf,int len)752*5113495bSYour Name void qdf_get_time_of_the_day_in_hr_min_sec_usec(char *tbuf, int len)
753*5113495bSYour Name {
754*5113495bSYour Name 	struct timeval tv;
755*5113495bSYour Name 	struct rtc_time tm;
756*5113495bSYour Name 	unsigned long local_time;
757*5113495bSYour Name 
758*5113495bSYour Name 	/* Format the Log time R#: [hr:min:sec.microsec] */
759*5113495bSYour Name 	do_gettimeofday(&tv);
760*5113495bSYour Name 	/* Convert rtc to local time */
761*5113495bSYour Name 	local_time = (u32)(tv.tv_sec - (sys_tz.tz_minuteswest * 60));
762*5113495bSYour Name 	rtc_time_to_tm(local_time, &tm);
763*5113495bSYour Name 	scnprintf(tbuf, len,
764*5113495bSYour Name 		"[%02d:%02d:%02d.%06lu]",
765*5113495bSYour Name 		tm.tm_hour, tm.tm_min, tm.tm_sec, tv.tv_usec);
766*5113495bSYour Name }
767*5113495bSYour Name qdf_export_symbol(qdf_get_time_of_the_day_in_hr_min_sec_usec);
768*5113495bSYour Name 
qdf_get_time_of_the_day_us(void)769*5113495bSYour Name uint64_t qdf_get_time_of_the_day_us(void)
770*5113495bSYour Name {
771*5113495bSYour Name 	struct timeval tv;
772*5113495bSYour Name 	struct rtc_time tm;
773*5113495bSYour Name 	unsigned long local_time;
774*5113495bSYour Name 	uint64_t time_of_day_us = 0;
775*5113495bSYour Name 
776*5113495bSYour Name 	do_gettimeofday(&tv);
777*5113495bSYour Name 	/* Convert rtc to local time */
778*5113495bSYour Name 	local_time = (u32)(tv.tv_sec - (sys_tz.tz_minuteswest * 60));
779*5113495bSYour Name 	rtc_time_to_tm(local_time, &tm);
780*5113495bSYour Name 
781*5113495bSYour Name 	time_of_day_us += (uint64_t)tm.tm_hour * 60 * 60 * 1000 * 1000;
782*5113495bSYour Name 	time_of_day_us += (uint64_t)tm.tm_min * 60 * 1000 * 1000;
783*5113495bSYour Name 	time_of_day_us += (uint64_t)tm.tm_sec * 1000 * 1000;
784*5113495bSYour Name 	time_of_day_us += (uint64_t)tv.tv_usec;
785*5113495bSYour Name 
786*5113495bSYour Name 	return time_of_day_us;
787*5113495bSYour Name }
788*5113495bSYour Name 
789*5113495bSYour Name qdf_export_symbol(qdf_get_time_of_the_day_us);
790*5113495bSYour Name #endif
791*5113495bSYour Name 
qdf_get_time_of_the_day_ms(void)792*5113495bSYour Name qdf_time_t qdf_get_time_of_the_day_ms(void)
793*5113495bSYour Name {
794*5113495bSYour Name 	qdf_time_t time_of_the_day_ms;
795*5113495bSYour Name 
796*5113495bSYour Name 	time_of_the_day_ms = qdf_do_div(qdf_get_time_of_the_day_us(), 1000);
797*5113495bSYour Name 
798*5113495bSYour Name 	return time_of_the_day_ms;
799*5113495bSYour Name }
800*5113495bSYour Name 
801*5113495bSYour Name qdf_export_symbol(qdf_get_time_of_the_day_ms);
802