qdf_threads.c 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367
  1. /*
  2. * Copyright (c) 2014-2021 The Linux Foundation. All rights reserved.
  3. * Copyright (c) 2022-2023 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. * DOC: qdf_threads
  21. * QCA driver framework (QDF) thread APIs
  22. */
  23. /* Include Files */
  24. #include <qdf_threads.h>
  25. #include <qdf_types.h>
  26. #include <qdf_trace.h>
  27. #include <linux/jiffies.h>
  28. #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0)
  29. #include <linux/sched.h>
  30. #else
  31. #include <linux/sched/signal.h>
  32. #endif /* KERNEL_VERSION(4, 11, 0) */
  33. /* Test against msm kernel version */
  34. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0)) && \
  35. IS_ENABLED(CONFIG_SCHED_WALT)
  36. #include <linux/sched/walt.h>
  37. #endif
  38. #include <linux/delay.h>
  39. #include <linux/interrupt.h>
  40. #include <linux/kthread.h>
  41. #include <linux/stacktrace.h>
  42. #include <qdf_defer.h>
  43. #include <qdf_module.h>
  44. #include <linux/cpumask.h>
  45. /* Function declarations and documentation */
  46. typedef int (*qdf_thread_os_func)(void *data);
  47. /**
  48. * qdf_sleep() - sleep
  49. * @ms_interval : Number of milliseconds to suspend the current thread.
  50. * A value of 0 may or may not cause the current thread to yield.
  51. *
  52. * This function suspends the execution of the current thread
  53. * until the specified time out interval elapses.
  54. *
  55. * Return: none
  56. */
  57. void qdf_sleep(uint32_t ms_interval)
  58. {
  59. if (in_interrupt()) {
  60. QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
  61. "%s cannot be called from interrupt context!!!",
  62. __func__);
  63. return;
  64. }
  65. msleep_interruptible(ms_interval);
  66. }
  67. qdf_export_symbol(qdf_sleep);
  68. /**
  69. * qdf_sleep_us() - sleep
  70. * @us_interval : Number of microseconds to suspend the current thread.
  71. * A value of 0 may or may not cause the current thread to yield.
  72. *
  73. * This function suspends the execution of the current thread
  74. * until the specified time out interval elapses.
  75. *
  76. * Return : none
  77. */
  78. void qdf_sleep_us(uint32_t us_interval)
  79. {
  80. unsigned long timeout = usecs_to_jiffies(us_interval) + 1;
  81. if (in_interrupt()) {
  82. QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
  83. "%s cannot be called from interrupt context!!!",
  84. __func__);
  85. return;
  86. }
  87. while (timeout && !signal_pending(current))
  88. timeout = schedule_timeout_interruptible(timeout);
  89. }
  90. qdf_export_symbol(qdf_sleep_us);
  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. #if defined(PF_WAKE_UP_IDLE) || IS_ENABLED(CONFIG_SCHED_WALT)
  107. void qdf_set_wake_up_idle(bool idle)
  108. {
  109. set_wake_up_idle(idle);
  110. }
  111. #else
  112. void qdf_set_wake_up_idle(bool idle)
  113. {
  114. }
  115. #endif /* PF_WAKE_UP_IDLE */
  116. qdf_export_symbol(qdf_set_wake_up_idle);
  117. void qdf_set_user_nice(qdf_thread_t *thread, long nice)
  118. {
  119. set_user_nice(thread, nice);
  120. }
  121. qdf_export_symbol(qdf_set_user_nice);
  122. qdf_thread_t *qdf_create_thread(int (*thread_handler)(void *data), void *data,
  123. const char thread_name[])
  124. {
  125. struct task_struct *task;
  126. task = kthread_create(thread_handler, data, thread_name);
  127. if (IS_ERR(task))
  128. return NULL;
  129. return task;
  130. }
  131. qdf_export_symbol(qdf_create_thread);
  132. static uint16_t qdf_thread_id;
  133. qdf_thread_t *qdf_thread_run(qdf_thread_func callback, void *context)
  134. {
  135. struct task_struct *thread;
  136. thread = kthread_create((qdf_thread_os_func)callback, context,
  137. "qdf %u", qdf_thread_id++);
  138. if (IS_ERR(thread))
  139. return NULL;
  140. get_task_struct(thread);
  141. wake_up_process(thread);
  142. return thread;
  143. }
  144. qdf_export_symbol(qdf_thread_run);
  145. QDF_STATUS qdf_thread_join(qdf_thread_t *thread)
  146. {
  147. QDF_STATUS status;
  148. QDF_BUG(thread);
  149. status = (QDF_STATUS)kthread_stop(thread);
  150. put_task_struct(thread);
  151. return status;
  152. }
  153. qdf_export_symbol(qdf_thread_join);
  154. bool qdf_thread_should_stop(void)
  155. {
  156. return kthread_should_stop();
  157. }
  158. qdf_export_symbol(qdf_thread_should_stop);
  159. int qdf_wake_up_process(qdf_thread_t *thread)
  160. {
  161. return wake_up_process(thread);
  162. }
  163. qdf_export_symbol(qdf_wake_up_process);
  164. /* save_stack_trace_tsk() is exported for:
  165. * 1) non-arm architectures
  166. * 2) arm architectures in kernel versions >=4.14
  167. * 3) backported kernels defining BACKPORTED_EXPORT_SAVE_STACK_TRACE_TSK_ARM
  168. */
  169. #if ((defined(WLAN_HOST_ARCH_ARM) && !WLAN_HOST_ARCH_ARM) || \
  170. LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) || \
  171. defined(BACKPORTED_EXPORT_SAVE_STACK_TRACE_TSK_ARM)) && \
  172. defined(CONFIG_STACKTRACE) && !defined(CONFIG_ARCH_STACKWALK)
  173. #define QDF_PRINT_TRACE_COUNT 32
  174. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0))
  175. void qdf_print_thread_trace(qdf_thread_t *thread)
  176. {
  177. const int spaces = 4;
  178. struct task_struct *task = thread;
  179. unsigned long entries[QDF_PRINT_TRACE_COUNT] = {0};
  180. struct stack_trace trace = {
  181. .nr_entries = 0,
  182. .skip = 0,
  183. .entries = &entries[0],
  184. .max_entries = QDF_PRINT_TRACE_COUNT,
  185. };
  186. save_stack_trace_tsk(task, &trace);
  187. stack_trace_print(entries, trace.nr_entries, spaces);
  188. }
  189. #else
  190. void qdf_print_thread_trace(qdf_thread_t *thread)
  191. {
  192. const int spaces = 4;
  193. struct task_struct *task = thread;
  194. unsigned long entries[QDF_PRINT_TRACE_COUNT] = {0};
  195. struct stack_trace trace = {
  196. .nr_entries = 0,
  197. .skip = 0,
  198. .entries = &entries[0],
  199. .max_entries = QDF_PRINT_TRACE_COUNT,
  200. };
  201. save_stack_trace_tsk(task, &trace);
  202. print_stack_trace(&trace, spaces);
  203. }
  204. #endif
  205. #else
  206. void qdf_print_thread_trace(qdf_thread_t *thread) { }
  207. #endif /* KERNEL_VERSION(4, 14, 0) */
  208. qdf_export_symbol(qdf_print_thread_trace);
  209. qdf_thread_t *qdf_get_current_task(void)
  210. {
  211. return current;
  212. }
  213. qdf_export_symbol(qdf_get_current_task);
  214. int qdf_get_current_pid(void)
  215. {
  216. return current->pid;
  217. }
  218. qdf_export_symbol(qdf_get_current_pid);
  219. const char *qdf_get_current_comm(void)
  220. {
  221. return current->comm;
  222. }
  223. qdf_export_symbol(qdf_get_current_comm);
  224. void
  225. qdf_thread_set_cpus_allowed_mask(qdf_thread_t *thread, qdf_cpu_mask *new_mask)
  226. {
  227. set_cpus_allowed_ptr(thread, new_mask);
  228. }
  229. qdf_export_symbol(qdf_thread_set_cpus_allowed_mask);
  230. void qdf_cpumask_clear(qdf_cpu_mask *dstp)
  231. {
  232. cpumask_clear(dstp);
  233. }
  234. qdf_export_symbol(qdf_cpumask_clear);
  235. void qdf_cpumask_set_cpu(unsigned int cpu, qdf_cpu_mask *dstp)
  236. {
  237. cpumask_set_cpu(cpu, dstp);
  238. }
  239. qdf_export_symbol(qdf_cpumask_set_cpu);
  240. void qdf_cpumask_clear_cpu(unsigned int cpu, qdf_cpu_mask *dstp)
  241. {
  242. cpumask_clear_cpu(cpu, dstp);
  243. }
  244. qdf_export_symbol(qdf_cpumask_clear_cpu);
  245. void qdf_cpumask_setall(qdf_cpu_mask *dstp)
  246. {
  247. cpumask_setall(dstp);
  248. }
  249. qdf_export_symbol(qdf_cpumask_setall);
  250. bool qdf_cpumask_empty(const qdf_cpu_mask *srcp)
  251. {
  252. return cpumask_empty(srcp);
  253. }
  254. qdf_export_symbol(qdf_cpumask_empty);
  255. void qdf_cpumask_copy(qdf_cpu_mask *dstp,
  256. const qdf_cpu_mask *srcp)
  257. {
  258. return cpumask_copy(dstp, srcp);
  259. }
  260. qdf_export_symbol(qdf_cpumask_copy);
  261. void qdf_cpumask_or(qdf_cpu_mask *dstp, qdf_cpu_mask *src1p,
  262. qdf_cpu_mask *src2p)
  263. {
  264. cpumask_or(dstp, src1p, src2p);
  265. }
  266. qdf_export_symbol(qdf_cpumask_or);
  267. void
  268. qdf_thread_cpumap_print_to_pagebuf(bool list, char *new_mask_str,
  269. qdf_cpu_mask *new_mask)
  270. {
  271. cpumap_print_to_pagebuf(list, new_mask_str, new_mask);
  272. }
  273. qdf_export_symbol(qdf_thread_cpumap_print_to_pagebuf);
  274. bool
  275. qdf_cpumask_and(qdf_cpu_mask *dstp, const qdf_cpu_mask *src1p,
  276. const qdf_cpu_mask *src2p)
  277. {
  278. return cpumask_and(dstp, src1p, src2p);
  279. }
  280. qdf_export_symbol(qdf_cpumask_and);
  281. bool
  282. qdf_cpumask_andnot(qdf_cpu_mask *dstp, const qdf_cpu_mask *src1p,
  283. const qdf_cpu_mask *src2p)
  284. {
  285. return cpumask_andnot(dstp, src1p, src2p);
  286. }
  287. qdf_export_symbol(qdf_cpumask_andnot);
  288. bool
  289. qdf_cpumask_equal(const qdf_cpu_mask *src1p, const qdf_cpu_mask *src2p)
  290. {
  291. return cpumask_equal(src1p, src2p);
  292. }
  293. qdf_export_symbol(qdf_cpumask_equal);
  294. void
  295. qdf_cpumask_complement(qdf_cpu_mask *dstp, const qdf_cpu_mask *srcp)
  296. {
  297. cpumask_complement(dstp, srcp);
  298. }
  299. qdf_export_symbol(qdf_cpumask_complement);
  300. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0))
  301. qdf_cpu_mask qdf_walt_get_cpus_taken(void)
  302. {
  303. return walt_get_cpus_taken();
  304. }
  305. qdf_export_symbol(qdf_walt_get_cpus_taken);
  306. #endif