xref: /wlan-dirver/qca-wifi-host-cmn/qdf/linux/src/qdf_threads.c (revision 4865edfd190c086bbe2c69aae12a8226f877b91e)
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: qdf_threads
21  * QCA driver framework (QDF) thread APIs
22  */
23 
24 /* Include Files */
25 #include <qdf_threads.h>
26 #include <qdf_types.h>
27 #include <qdf_trace.h>
28 #include <linux/jiffies.h>
29 #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0)
30 #include <linux/sched.h>
31 #else
32 #include <linux/sched/signal.h>
33 #endif /* KERNEL_VERSION(4, 11, 0) */
34 #include <linux/delay.h>
35 #include <linux/interrupt.h>
36 #include <linux/kthread.h>
37 #include <linux/stacktrace.h>
38 #include <qdf_defer.h>
39 #include <qdf_module.h>
40 
41 /* Function declarations and documenation */
42 
43 /**
44  *  qdf_sleep() - sleep
45  *  @ms_interval : Number of milliseconds to suspend the current thread.
46  *  A value of 0 may or may not cause the current thread to yield.
47  *
48  *  This function suspends the execution of the current thread
49  *  until the specified time out interval elapses.
50  *
51  *  Return: none
52  */
53 void qdf_sleep(uint32_t ms_interval)
54 {
55 	if (in_interrupt()) {
56 		QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
57 			  "%s cannot be called from interrupt context!!!",
58 			  __func__);
59 		return;
60 	}
61 	msleep_interruptible(ms_interval);
62 }
63 qdf_export_symbol(qdf_sleep);
64 
65 /**
66  *  qdf_sleep_us() - sleep
67  *  @us_interval : Number of microseconds to suspend the current thread.
68  *  A value of 0 may or may not cause the current thread to yield.
69  *
70  *  This function suspends the execution of the current thread
71  *  until the specified time out interval elapses.
72  *
73  *  Return : none
74  */
75 void qdf_sleep_us(uint32_t us_interval)
76 {
77 	unsigned long timeout = usecs_to_jiffies(us_interval) + 1;
78 
79 	if (in_interrupt()) {
80 		QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
81 			  "%s cannot be called from interrupt context!!!",
82 			  __func__);
83 		return;
84 	}
85 
86 	while (timeout && !signal_pending(current))
87 		timeout = schedule_timeout_interruptible(timeout);
88 }
89 qdf_export_symbol(qdf_sleep_us);
90 
91 /**
92  *  qdf_busy_wait() - busy wait
93  *  @us_interval : Number of microseconds to busy wait.
94  *
95  *  This function places the current thread in busy wait until the specified
96  *  time out interval elapses. If the interval is greater than 50us on WM, the
97  *  behaviour is undefined.
98  *
99  *  Return : none
100  */
101 void qdf_busy_wait(uint32_t us_interval)
102 {
103 	udelay(us_interval);
104 }
105 qdf_export_symbol(qdf_busy_wait);
106 
107 void qdf_set_user_nice(qdf_thread_t *thread, long nice)
108 {
109 	set_user_nice(thread, nice);
110 }
111 qdf_export_symbol(qdf_set_user_nice);
112 
113 qdf_thread_t *qdf_create_thread(int (*thread_handler)(void *data), void *data,
114 				const char thread_name[])
115 {
116 	return kthread_create(thread_handler, data, thread_name);
117 }
118 qdf_export_symbol(qdf_create_thread);
119 
120 int qdf_wake_up_process(qdf_thread_t *thread)
121 {
122 	return wake_up_process(thread);
123 }
124 qdf_export_symbol(qdf_wake_up_process);
125 
126 /* save_stack_trace_tsk() is exported for:
127  * 1) non-arm architectures
128  * 2) arm architectures in kernel versions >=4.14
129  * 3) backported kernels defining BACKPORTED_EXPORT_SAVE_STACK_TRACE_TSK_ARM
130  */
131 #if (defined(WLAN_HOST_ARCH_ARM) && !WLAN_HOST_ARCH_ARM) || \
132 	LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) || \
133 	defined(BACKPORTED_EXPORT_SAVE_STACK_TRACE_TSK_ARM)
134 #define QDF_PRINT_TRACE_COUNT 32
135 void qdf_print_thread_trace(qdf_thread_t *thread)
136 {
137 	const int spaces = 4;
138 	struct task_struct *task = thread;
139 	unsigned long entries[QDF_PRINT_TRACE_COUNT] = {0};
140 	struct stack_trace trace = {
141 		.nr_entries = 0,
142 		.skip = 0,
143 		.entries = &entries[0],
144 		.max_entries = QDF_PRINT_TRACE_COUNT,
145 	};
146 
147 	save_stack_trace_tsk(task, &trace);
148 	print_stack_trace(&trace, spaces);
149 }
150 #else
151 void qdf_print_thread_trace(qdf_thread_t *thread) { }
152 #endif /* KERNEL_VERSION(4, 14, 0) */
153 qdf_export_symbol(qdf_print_thread_trace);
154 
155 qdf_thread_t *qdf_get_current_task(void)
156 {
157 	return current;
158 }
159 qdf_export_symbol(qdf_get_current_task);
160