From 8d95e23b2a4fcd41ea90027ea26ee27173eab6a9 Mon Sep 17 00:00:00 2001 From: Wesley Cheng Date: Tue, 22 Mar 2022 15:24:59 -0700 Subject: [PATCH] usb: dwc3: dwc3-msm-core: Reset GSI event buffers after core soft reset Due to a newly added sequence to issue a core soft reset before enabling the pullup, the GSI event buffers also need to be reset as well: commit 0066472de157 ("usb: dwc3: Issue core soft reset before enabling run/stop"). Failure to do so will result in a SMMU fault, showing that the DWC3 controller is attempting to access a FAR=0x0. Add a kretprobe to gadget start, as that is executed before enabling run/stop, so that we can initialize the GSI event buffers properly. Change-Id: I612bfcd24bba54b5c5850950838f5ad53523045a Signed-off-by: Wesley Cheng --- drivers/usb/dwc3/dwc3-msm-core.c | 12 ++++++++++++ drivers/usb/dwc3/dwc3-msm-ops.c | 11 +++++++++++ include/linux/usb/dwc3-msm.h | 1 + 3 files changed, 24 insertions(+) diff --git a/drivers/usb/dwc3/dwc3-msm-core.c b/drivers/usb/dwc3/dwc3-msm-core.c index 8d70fec99959..5d302e872b0f 100644 --- a/drivers/usb/dwc3/dwc3-msm-core.c +++ b/drivers/usb/dwc3/dwc3-msm-core.c @@ -3175,6 +3175,15 @@ static int is_diag_enabled(struct usb_composite_dev *cdev) return 0; } +static int dwc3_device_core_soft_reset(struct dwc3_msm *mdwc) +{ + struct dwc3 *dwc = platform_get_drvdata(mdwc->dwc3); + + dwc3_msm_notify_event(dwc, DWC3_GSI_EVT_BUF_SETUP, 0); + + return 0; +} + static void dwc3_msm_update_imem_pid(struct dwc3 *dwc) { struct usb_composite_dev *cdev = NULL; @@ -3434,6 +3443,9 @@ void dwc3_msm_notify_event(struct dwc3 *dwc, case DWC3_IMEM_UPDATE_PID: dwc3_msm_update_imem_pid(dwc); break; + case DWC3_CONTROLLER_SOFT_RESET: + dwc3_device_core_soft_reset(mdwc); + break; default: dev_dbg(mdwc->dev, "unknown dwc3 event\n"); break; diff --git a/drivers/usb/dwc3/dwc3-msm-ops.c b/drivers/usb/dwc3/dwc3-msm-ops.c index 9ef11bba2554..83da8d91893a 100644 --- a/drivers/usb/dwc3/dwc3-msm-ops.c +++ b/drivers/usb/dwc3/dwc3-msm-ops.c @@ -130,6 +130,16 @@ static int exit_dwc3_gadget_pullup(struct kretprobe_instance *ri, return 0; } +static int entry___dwc3_gadget_start(struct kretprobe_instance *ri, + struct pt_regs *regs) +{ + struct dwc3 *dwc = (struct dwc3 *)regs->regs[0]; + + dwc3_msm_notify_event(dwc, DWC3_CONTROLLER_SOFT_RESET, 0); + + return 0; +} + static int entry_trace_dwc3_ctrl_req(struct kretprobe_instance *ri, struct pt_regs *regs) { @@ -226,6 +236,7 @@ static struct kretprobe dwc3_msm_probes[] = { ENTRY(dwc3_gadget_reset_interrupt), ENTRY_EXIT(dwc3_gadget_conndone_interrupt), ENTRY_EXIT(dwc3_gadget_pullup), + ENTRY(__dwc3_gadget_start), ENTRY(trace_dwc3_ctrl_req), ENTRY(trace_dwc3_ep_queue), ENTRY(trace_dwc3_ep_dequeue), diff --git a/include/linux/usb/dwc3-msm.h b/include/linux/usb/dwc3-msm.h index ee76735f04bb..79046e1ebb9c 100644 --- a/include/linux/usb/dwc3-msm.h +++ b/include/linux/usb/dwc3-msm.h @@ -77,6 +77,7 @@ enum dwc3_notify_event { DWC3_CONTROLLER_NOTIFY_DISABLE_UPDXFER, DWC3_CONTROLLER_PULLUP_ENTER, DWC3_CONTROLLER_PULLUP_EXIT, + DWC3_CONTROLLER_SOFT_RESET, /* USB GSI event buffer related notification */ DWC3_GSI_EVT_BUF_ALLOC,