dwc3-msm-ops.c 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2012-2021, The Linux Foundation. All rights reserved.
  4. * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
  5. */
  6. #include <linux/kernel.h>
  7. #include <linux/module.h>
  8. #include <linux/kprobes.h>
  9. #include <linux/irq.h>
  10. #include <linux/irqdesc.h>
  11. #include <linux/sched.h>
  12. #include <linux/usb/dwc3-msm.h>
  13. #include <linux/usb/composite.h>
  14. #include "core.h"
  15. #include "debug-ipc.h"
  16. #include "gadget.h"
  17. #if IS_ENABLED(CONFIG_USB_NOTIFY_LAYER)
  18. #include <linux/usb_notify.h>
  19. #endif
  20. #if IS_ENABLED(CONFIG_USB_CONFIGFS_F_SS_MON_GADGET)
  21. #include <linux/usb/f_ss_mon_gadget.h>
  22. #endif
  23. struct kprobe_data {
  24. struct dwc3 *dwc;
  25. int xi0;
  26. };
  27. static int entry_usb_ep_set_maxpacket_limit(struct kretprobe_instance *ri,
  28. struct pt_regs *regs)
  29. {
  30. struct usb_ep *ep = (struct usb_ep *)regs->regs[0];
  31. struct dwc3_ep *dep;
  32. struct dwc3 *dwc;
  33. struct kprobe_data *data = (struct kprobe_data *)ri->data;
  34. dep = to_dwc3_ep(ep);
  35. dwc = dep->dwc;
  36. data->dwc = dwc;
  37. data->xi0 = dep->number;
  38. return 0;
  39. }
  40. static int exit_usb_ep_set_maxpacket_limit(struct kretprobe_instance *ri,
  41. struct pt_regs *regs)
  42. {
  43. struct kprobe_data *data = (struct kprobe_data *)ri->data;
  44. struct dwc3 *dwc = data->dwc;
  45. u8 epnum = data->xi0;
  46. struct dwc3_ep *dep = dwc->eps[epnum];
  47. struct usb_ep *ep = &dep->endpoint;
  48. if (epnum >= 2) {
  49. ep->maxpacket_limit = 1024;
  50. ep->maxpacket = 1024;
  51. }
  52. return 0;
  53. }
  54. static int entry_dwc3_gadget_run_stop(struct kretprobe_instance *ri,
  55. struct pt_regs *regs)
  56. {
  57. #if IS_ENABLED(CONFIG_USB_CONFIGFS_F_SS_MON_GADGET)
  58. struct kprobe_data *data = (struct kprobe_data *)ri->data;
  59. #endif
  60. struct dwc3 *dwc = (struct dwc3 *)regs->regs[0];
  61. int is_on = (int)regs->regs[1];
  62. #if IS_ENABLED(CONFIG_USB_CONFIGFS_F_SS_MON_GADGET)
  63. data->dwc = dwc;
  64. data->xi0 = is_on;
  65. #endif
  66. if (is_on) {
  67. /*
  68. * DWC3 gadget IRQ uses a threaded handler which normally runs
  69. * at SCHED_FIFO priority. If it gets busy processing a high
  70. * volume of events (usually EP events due to heavy traffic) it
  71. * can potentially starve non-RT taks from running and trigger
  72. * RT throttling in the scheduler; on some build configs this
  73. * will panic. So lower the thread's priority to run as non-RT
  74. * (with a nice value equivalent to a high-priority workqueue).
  75. * It has been found to not have noticeable performance impact.
  76. */
  77. struct irq_desc *irq_desc = irq_to_desc(dwc->irq_gadget);
  78. struct irqaction *action = irq_desc ? irq_desc->action : NULL;
  79. for ( ; action != NULL; action = action->next) {
  80. if (action->thread) {
  81. dev_info(dwc->dev, "Set IRQ thread:%s pid:%d to SCHED_NORMAL prio\n",
  82. action->thread->comm, action->thread->pid);
  83. sched_set_normal(action->thread, MIN_NICE);
  84. break;
  85. }
  86. }
  87. } else {
  88. dwc3_core_stop_hw_active_transfers(dwc);
  89. dwc3_msm_notify_event(dwc, DWC3_GSI_EVT_BUF_CLEAR, 0);
  90. dwc3_msm_notify_event(dwc, DWC3_CONTROLLER_NOTIFY_CLEAR_DB, 0);
  91. }
  92. return 0;
  93. }
  94. #if IS_ENABLED(CONFIG_USB_CONFIGFS_F_SS_MON_GADGET)
  95. static int exit_dwc3_gadget_run_stop(struct kretprobe_instance *ri,
  96. struct pt_regs *regs)
  97. {
  98. unsigned long long retval = regs_return_value(regs);
  99. struct kprobe_data *data = (struct kprobe_data *)ri->data;
  100. struct dwc3 *dwc = data->dwc;
  101. int is_on;
  102. is_on = data->xi0;
  103. vbus_session_notify(dwc->gadget, is_on, retval);
  104. if (retval) {
  105. pr_info("usb: dwc3_gadget_run_stop : dwc3_gadget %s failed (%d)\n",
  106. is_on ? "ON" : "OFF", retval);
  107. }
  108. return 0;
  109. }
  110. #endif
  111. static int entry_dwc3_send_gadget_ep_cmd(struct kretprobe_instance *ri,
  112. struct pt_regs *regs)
  113. {
  114. struct dwc3_ep *dep = (struct dwc3_ep *)regs->regs[0];
  115. unsigned int cmd = (unsigned int)regs->regs[1];
  116. struct dwc3 *dwc = dep->dwc;
  117. if (cmd == DWC3_DEPCMD_ENDTRANSFER)
  118. dwc3_msm_notify_event(dwc,
  119. DWC3_CONTROLLER_NOTIFY_DISABLE_UPDXFER,
  120. dep->number);
  121. return 0;
  122. }
  123. static int entry___dwc3_gadget_ep_enable(struct kretprobe_instance *ri,
  124. struct pt_regs *regs)
  125. {
  126. struct dwc3_ep *dep = (struct dwc3_ep *)regs->regs[0];
  127. unsigned int action = (unsigned int)regs->regs[1];
  128. /* DWC3_DEPCFG_ACTION_MODIFY is only done during CONNDONE */
  129. if (action == DWC3_DEPCFG_ACTION_MODIFY && dep->number == 1)
  130. dwc3_msm_notify_event(dep->dwc, DWC3_CONTROLLER_CONNDONE_EVENT, 0);
  131. return 0;
  132. }
  133. static int entry_dwc3_gadget_reset_interrupt(struct kretprobe_instance *ri,
  134. struct pt_regs *regs)
  135. {
  136. struct dwc3 *dwc = (struct dwc3 *)regs->regs[0];
  137. dwc3_msm_notify_event(dwc, DWC3_CONTROLLER_NOTIFY_CLEAR_DB, 0);
  138. #if IS_ENABLED(CONFIG_USB_CONFIGFS_F_SS_MON_GADGET)
  139. usb_reset_notify(dwc->gadget);
  140. #endif
  141. return 0;
  142. }
  143. static int entry_dwc3_gadget_conndone_interrupt(struct kretprobe_instance *ri,
  144. struct pt_regs *regs)
  145. {
  146. struct kprobe_data *data = (struct kprobe_data *)ri->data;
  147. data->dwc = (struct dwc3 *)regs->regs[0];
  148. return 0;
  149. }
  150. static int exit_dwc3_gadget_conndone_interrupt(struct kretprobe_instance *ri,
  151. struct pt_regs *regs)
  152. {
  153. struct kprobe_data *data = (struct kprobe_data *)ri->data;
  154. dwc3_msm_notify_event(data->dwc, DWC3_CONTROLLER_CONNDONE_EVENT, 0);
  155. #if defined(CONFIG_USB_NOTIFY_PROC_LOG)
  156. switch (data->dwc->speed) {
  157. case DWC3_DSTS_SUPERSPEED_PLUS:
  158. store_usblog_notify(NOTIFY_USBSTATE,
  159. (void *)"USB_STATE=ENUM:CONNDONE:PSS", NULL);
  160. break;
  161. case DWC3_DSTS_SUPERSPEED:
  162. store_usblog_notify(NOTIFY_USBSTATE,
  163. (void *)"USB_STATE=ENUM:CONNDONE:SS", NULL);
  164. break;
  165. case DWC3_DSTS_HIGHSPEED:
  166. store_usblog_notify(NOTIFY_USBSTATE,
  167. (void *)"USB_STATE=ENUM:CONNDONE:HS", NULL);
  168. break;
  169. case DWC3_DSTS_FULLSPEED:
  170. store_usblog_notify(NOTIFY_USBSTATE,
  171. (void *)"USB_STATE=ENUM:CONNDONE:FS", NULL);
  172. break;
  173. }
  174. #endif
  175. return 0;
  176. }
  177. static int entry_dwc3_gadget_pullup(struct kretprobe_instance *ri,
  178. struct pt_regs *regs)
  179. {
  180. struct kprobe_data *data = (struct kprobe_data *)ri->data;
  181. struct usb_gadget *g = (struct usb_gadget *)regs->regs[0];
  182. data->dwc = gadget_to_dwc(g);
  183. data->xi0 = (int)regs->regs[1];
  184. dwc3_msm_notify_event(data->dwc, DWC3_CONTROLLER_PULLUP_ENTER,
  185. data->xi0);
  186. /* Only write PID to IMEM if pullup is being enabled */
  187. if (data->xi0)
  188. dwc3_msm_notify_event(data->dwc, DWC3_IMEM_UPDATE_PID, 0);
  189. return 0;
  190. }
  191. static int exit_dwc3_gadget_pullup(struct kretprobe_instance *ri,
  192. struct pt_regs *regs)
  193. {
  194. struct kprobe_data *data = (struct kprobe_data *)ri->data;
  195. dwc3_msm_notify_event(data->dwc, DWC3_CONTROLLER_PULLUP_EXIT,
  196. data->xi0);
  197. return 0;
  198. }
  199. static int entry___dwc3_gadget_start(struct kretprobe_instance *ri,
  200. struct pt_regs *regs)
  201. {
  202. struct dwc3 *dwc = (struct dwc3 *)regs->regs[0];
  203. /*
  204. * Setup USB GSI event buffer as controller soft reset has cleared
  205. * configured event buffer.
  206. */
  207. dwc3_msm_notify_event(dwc, DWC3_GSI_EVT_BUF_SETUP, 0);
  208. return 0;
  209. }
  210. static int entry_trace_event_raw_event_dwc3_log_request(struct kretprobe_instance *ri,
  211. struct pt_regs *regs)
  212. {
  213. struct dwc3_request *req = (struct dwc3_request *)regs->regs[1];
  214. dbg_trace_ep_queue(req);
  215. return 0;
  216. }
  217. static int entry_trace_event_raw_event_dwc3_log_gadget_ep_cmd(struct kretprobe_instance *ri,
  218. struct pt_regs *regs)
  219. {
  220. struct dwc3_ep *dep = (struct dwc3_ep *)regs->regs[1];
  221. unsigned int cmd = regs->regs[2];
  222. struct dwc3_gadget_ep_cmd_params *param = (struct dwc3_gadget_ep_cmd_params *)regs->regs[3];
  223. int cmd_status = regs->regs[4];
  224. dbg_trace_gadget_ep_cmd(dep, cmd, param, cmd_status);
  225. return 0;
  226. }
  227. static int entry_trace_event_raw_event_dwc3_log_trb(struct kretprobe_instance *ri,
  228. struct pt_regs *regs)
  229. {
  230. struct dwc3_ep *dep = (struct dwc3_ep *)regs->regs[1];
  231. struct dwc3_trb *trb = (struct dwc3_trb *)regs->regs[2];
  232. dbg_trace_trb_prepare(dep, trb);
  233. return 0;
  234. }
  235. static int entry_trace_event_raw_event_dwc3_log_event(struct kretprobe_instance *ri,
  236. struct pt_regs *regs)
  237. {
  238. u32 event = regs->regs[1];
  239. struct dwc3 *dwc = (struct dwc3 *)regs->regs[2];
  240. dbg_trace_event(event, dwc);
  241. return 0;
  242. }
  243. static int entry_trace_event_raw_event_dwc3_log_ep(struct kretprobe_instance *ri,
  244. struct pt_regs *regs)
  245. {
  246. struct dwc3_ep *dep = (struct dwc3_ep *)regs->regs[1];
  247. dbg_trace_ep(dep);
  248. return 0;
  249. }
  250. static int entry_dwc3_gadget_vbus_draw(struct kretprobe_instance *ri,
  251. struct pt_regs *regs)
  252. {
  253. unsigned int mA = (unsigned int)regs->regs[1];
  254. switch (mA) {
  255. case 2:
  256. pr_info("[USB] dwc3_gadget_vbus_draw: suspend -log only-\n");
  257. break;
  258. case 100:
  259. break;
  260. case 500:
  261. break;
  262. case 900:
  263. break;
  264. default:
  265. break;
  266. }
  267. return 0;
  268. }
  269. #define ENTRY_EXIT(name) {\
  270. .handler = exit_##name,\
  271. .entry_handler = entry_##name,\
  272. .data_size = sizeof(struct kprobe_data),\
  273. .maxactive = 8,\
  274. .kp.symbol_name = #name,\
  275. }
  276. #define ENTRY(name) {\
  277. .entry_handler = entry_##name,\
  278. .data_size = sizeof(struct kprobe_data),\
  279. .maxactive = 8,\
  280. .kp.symbol_name = #name,\
  281. }
  282. static struct kretprobe dwc3_msm_probes[] = {
  283. #if IS_ENABLED(CONFIG_USB_CONFIGFS_F_SS_MON_GADGET)
  284. ENTRY_EXIT(dwc3_gadget_run_stop),
  285. #else
  286. ENTRY(dwc3_gadget_run_stop),
  287. #endif
  288. ENTRY(dwc3_send_gadget_ep_cmd),
  289. ENTRY(dwc3_gadget_reset_interrupt),
  290. ENTRY(__dwc3_gadget_ep_enable),
  291. ENTRY_EXIT(dwc3_gadget_conndone_interrupt),
  292. ENTRY_EXIT(dwc3_gadget_pullup),
  293. ENTRY(__dwc3_gadget_start),
  294. ENTRY_EXIT(usb_ep_set_maxpacket_limit),
  295. ENTRY(trace_event_raw_event_dwc3_log_request),
  296. ENTRY(trace_event_raw_event_dwc3_log_gadget_ep_cmd),
  297. ENTRY(trace_event_raw_event_dwc3_log_trb),
  298. ENTRY(trace_event_raw_event_dwc3_log_event),
  299. ENTRY(trace_event_raw_event_dwc3_log_ep),
  300. ENTRY(dwc3_gadget_vbus_draw),
  301. };
  302. int dwc3_msm_kretprobe_init(void)
  303. {
  304. int ret;
  305. int i;
  306. for (i = 0; i < ARRAY_SIZE(dwc3_msm_probes) ; i++) {
  307. ret = register_kretprobe(&dwc3_msm_probes[i]);
  308. if (ret < 0)
  309. pr_err("register_kretprobe failed for %s, returned %d\n",
  310. dwc3_msm_probes[i].kp.symbol_name, ret);
  311. }
  312. return 0;
  313. }
  314. void dwc3_msm_kretprobe_exit(void)
  315. {
  316. int i;
  317. for (i = 0; i < ARRAY_SIZE(dwc3_msm_probes); i++)
  318. unregister_kretprobe(&dwc3_msm_probes[i]);
  319. }