Messages in this thread | | | Date | Fri, 13 Oct 2023 09:26:34 +0530 | Subject | Re: [RFC] usb: dwc3: core: Fix RAM interface getting stuck during enumeration | From | Krishna Kurapati PSSNV <> |
| |
On 10/13/2023 12:55 AM, Wesley Cheng wrote: > Hi Krishna, > > On 10/11/2023 3:02 AM, Krishna Kurapati wrote: >> This implementation is to fix RAM interface getting stuck during
>> Synopsys confirmed that the issue is present on all USB3 devices and >> as a workaround, suggested to re-initialize device mode. >> >> Signed-off-by: Krishna Kurapati <quic_kriskura@quicinc.com> >> --- >> drivers/usb/dwc3/core.c | 20 ++++++++++++++++++++ >> drivers/usb/dwc3/core.h | 4 ++++ >> drivers/usb/dwc3/drd.c | 5 +++++ >> drivers/usb/dwc3/gadget.c | 6 ++++-- >> 4 files changed, 33 insertions(+), 2 deletions(-) >> >> diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c >> index 44ee8526dc28..d18b81cccdc5 100644 >> --- a/drivers/usb/dwc3/core.c >> +++ b/drivers/usb/dwc3/core.c >> @@ -122,6 +122,7 @@ static void __dwc3_set_mode(struct work_struct *work) >> unsigned long flags; >> int ret; >> u32 reg; >> + u8 timeout = 100; >> u32 desired_dr_role; >> mutex_lock(&dwc->mutex); >> @@ -137,6 +138,25 @@ static void __dwc3_set_mode(struct work_struct >> *work) >> if (!desired_dr_role) >> goto out; >> + /* >> + * STAR 5001544 - If cable disconnect doesn't generate >> + * disconnect event in device mode, then re-initialize the >> + * controller. >> + */ >> + if ((dwc->cable_disconnected == true) && >> + (dwc->current_dr_role == DWC3_GCTL_PRTCAP_DEVICE)) { >> + while (dwc->connected == true && timeout != 0) { >> + mdelay(10); >> + timeout--; >> + } >> + >> + if (timeout == 0) { >> + dwc3_gadget_soft_disconnect(dwc); >> + udelay(100); >> + dwc3_gadget_soft_connect(dwc); >> + } >> + } >> + >> if (desired_dr_role == dwc->current_dr_role) >> goto out; >> diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h >> index c6c87acbd376..7642330cf608 100644 >> --- a/drivers/usb/dwc3/core.h >> +++ b/drivers/usb/dwc3/core.h >> @@ -1355,6 +1355,7 @@ struct dwc3 { >> int last_fifo_depth; >> int num_ep_resized; >> struct dentry *debug_root; >> + bool cable_disconnected; >> }; >> #define INCRX_BURST_MODE 0 >> @@ -1568,6 +1569,9 @@ void dwc3_event_buffers_cleanup(struct dwc3 *dwc); >> int dwc3_core_soft_reset(struct dwc3 *dwc); >> +int dwc3_gadget_soft_disconnect(struct dwc3 *dwc); >> +int dwc3_gadget_soft_connect(struct dwc3 *dwc); >> + >> #if IS_ENABLED(CONFIG_USB_DWC3_HOST) || >> IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE) >> int dwc3_host_init(struct dwc3 *dwc); >> void dwc3_host_exit(struct dwc3 *dwc); >> diff --git a/drivers/usb/dwc3/drd.c b/drivers/usb/dwc3/drd.c >> index 039bf241769a..593c023fc39a 100644 >> --- a/drivers/usb/dwc3/drd.c >> +++ b/drivers/usb/dwc3/drd.c >> @@ -446,6 +446,8 @@ static int dwc3_usb_role_switch_set(struct >> usb_role_switch *sw, >> struct dwc3 *dwc = usb_role_switch_get_drvdata(sw); >> u32 mode; >> + dwc->cable_disconnected = false; >> + >> switch (role) { >> case USB_ROLE_HOST: >> mode = DWC3_GCTL_PRTCAP_HOST; >> @@ -454,6 +456,9 @@ static int dwc3_usb_role_switch_set(struct >> usb_role_switch *sw, >> mode = DWC3_GCTL_PRTCAP_DEVICE; >> break; >> default: >> + if (role == USB_ROLE_NONE) >> + dwc->cable_disconnected = true; >> + > > How do we handle cases where role switch isn't used? (ie extcon or maybe > no cable connection notification at all) >
Hi Wesley,
Since I was considering fixing it during disconnect, I made it in role switch. So no cable connection notification case has been ruled out in this patch. But yes, extcon is a valid case. Will need to account for it.
Regards, Krishna,
| |