mt_wq_debug.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. #define DEBUG 1
  2. #include <asm/uaccess.h>
  3. #include <linux/module.h>
  4. #include <linux/kernel.h>
  5. #include <linux/workqueue.h>
  6. #include <linux/module.h>
  7. #include <linux/proc_fs.h>
  8. struct pool_workqueue;
  9. #include <trace/events/workqueue.h>
  10. #define WQ_VERBOSE_DEBUG 0
  11. #define WQ_DUMP_QUEUE_WORK 0x1
  12. #define WQ_DUMP_ACTIVE_WORK 0x2
  13. #define WQ_DUMP_EXECUTE_WORK 0x4
  14. #include "internal.h"
  15. static int wq_tracing;
  16. static void mttrace_workqueue_execute_work(void *ignore, struct work_struct *work)
  17. {
  18. pr_debug("execute work=%p\n", (void *)work);
  19. }
  20. static void mttrace_workqueue_execute_end(void *ignore, struct work_struct *work)
  21. {
  22. pr_debug("execute end work=%p\n", (void *)work);
  23. }
  24. static void mttrace_workqueue_activate_work(void *ignore, struct work_struct *work)
  25. {
  26. pr_debug("activate work=%p\n", (void *)work);
  27. }
  28. static void mttrace_workqueue_queue_work(void *ignore, unsigned int req_cpu, struct pool_workqueue *pwq,
  29. struct work_struct *work)
  30. {
  31. pr_debug("queue work=%p function=%pf req_cpu=%u\n",
  32. (void *)work, (void *)work->func, req_cpu);
  33. }
  34. static void print_help(struct seq_file *m)
  35. {
  36. if (m != NULL) {
  37. SEQ_printf(m, "\n*** Usage ***\n");
  38. SEQ_printf(m, "commands to enable logs\n");
  39. SEQ_printf(m,
  40. " echo [queue work] [activate work] [execute work] > wq_enable_logs\n");
  41. SEQ_printf(m, " ex. echo 1 1 1 > wq_enable_logs, to enable all logs\n");
  42. SEQ_printf(m,
  43. " ex. echo 1 0 0 > wq_enable_logs, to enable \"queue work\" & \"wq debug\" logs\n");
  44. } else {
  45. pr_err("\n*** Usage ***\n");
  46. pr_err("commands to enable logs\n");
  47. pr_err
  48. (" echo [queue work] [activate work] [execute work] > wq_enable_logs\n");
  49. pr_err(" ex. echo 1 1 1 > wq_enable_logs, to enable all logs\n");
  50. pr_err
  51. (" ex. echo 1 0 0 > wq_enable_logs, to enable \"queue work\" logs\n");
  52. }
  53. }
  54. MT_DEBUG_ENTRY(wq_log);
  55. static int mt_wq_log_show(struct seq_file *m, void *v)
  56. {
  57. if (wq_tracing & WQ_DUMP_QUEUE_WORK)
  58. SEQ_printf(m, "wq: queue work log enabled\n");
  59. if (wq_tracing & WQ_DUMP_ACTIVE_WORK)
  60. SEQ_printf(m, "wq: active work log enabled\n");
  61. if (wq_tracing & WQ_DUMP_EXECUTE_WORK)
  62. SEQ_printf(m, "wq: execute work log enabled\n");
  63. if (wq_tracing == 0)
  64. SEQ_printf(m, "wq: no log enabled\n");
  65. print_help(m);
  66. return 0;
  67. }
  68. static ssize_t mt_wq_log_write(struct file *filp, const char *ubuf, size_t cnt, loff_t *data)
  69. {
  70. int log_queue_work = 0, log_activate_work = 0, log_execute_work = 0;
  71. char buf[64];
  72. if (cnt >= sizeof(buf))
  73. return -EINVAL;
  74. if (copy_from_user(&buf, ubuf, cnt))
  75. return -EFAULT;
  76. buf[cnt] = '\0';
  77. if (sscanf
  78. (buf, "%d %d %d", &log_queue_work, &log_activate_work, &log_execute_work) == 3) {
  79. if (!!log_queue_work ^ ((wq_tracing & WQ_DUMP_QUEUE_WORK) != 0)) {
  80. if (!(wq_tracing & WQ_DUMP_QUEUE_WORK)) {
  81. register_trace_workqueue_queue_work(mttrace_workqueue_queue_work,
  82. NULL);
  83. wq_tracing |= WQ_DUMP_QUEUE_WORK;
  84. } else {
  85. unregister_trace_workqueue_queue_work(mttrace_workqueue_queue_work,
  86. NULL);
  87. wq_tracing &= ~WQ_DUMP_QUEUE_WORK;
  88. }
  89. }
  90. if (!!log_activate_work ^ ((wq_tracing & WQ_DUMP_ACTIVE_WORK) != 0)) {
  91. if (!(wq_tracing & WQ_DUMP_ACTIVE_WORK)) {
  92. register_trace_workqueue_activate_work(mttrace_workqueue_activate_work,
  93. NULL);
  94. wq_tracing |= WQ_DUMP_ACTIVE_WORK;
  95. } else {
  96. unregister_trace_workqueue_activate_work(mttrace_workqueue_activate_work,
  97. NULL);
  98. wq_tracing &= ~WQ_DUMP_ACTIVE_WORK;
  99. }
  100. }
  101. if (!!log_execute_work ^ ((wq_tracing & WQ_DUMP_EXECUTE_WORK) != 0)) {
  102. if (!(wq_tracing & WQ_DUMP_EXECUTE_WORK)) {
  103. register_trace_workqueue_execute_start(mttrace_workqueue_execute_work,
  104. NULL);
  105. register_trace_workqueue_execute_end(mttrace_workqueue_execute_end,
  106. NULL);
  107. wq_tracing |= WQ_DUMP_EXECUTE_WORK;
  108. } else {
  109. unregister_trace_workqueue_execute_start(mttrace_workqueue_execute_work,
  110. NULL);
  111. unregister_trace_workqueue_execute_end(mttrace_workqueue_execute_end,
  112. NULL);
  113. wq_tracing &= ~WQ_DUMP_EXECUTE_WORK;
  114. }
  115. }
  116. } else
  117. print_help(NULL);
  118. return cnt;
  119. }
  120. static int __init init_wq_debug(void)
  121. {
  122. struct proc_dir_entry *pe;
  123. pe = proc_create("mtprof/wq_enable_logs", 0664, NULL, &mt_wq_log_fops);
  124. if (!pe)
  125. return -ENOMEM;
  126. return 0;
  127. }
  128. device_initcall(init_wq_debug);