From 33be4d8a2c5ecfef9beef6a203e36e7529792b66 Mon Sep 17 00:00:00 2001 From: Wesley Cheng Date: Wed, 17 Aug 2022 11:23:54 -0700 Subject: [PATCH] UPSTREAM: usb: dwc3: gadget: Continue handling EP0 xfercomplete events During soft disconnect, EP0 events are expected to be handled in order to allow the controller to successfully move into the halted state. Since __dwc3_gadget_stop() is executed before polling, EP0 has been disabled, and events are being blocked. Allow xfercomplete events to be handled, so that cached SETUP packets can be read out from the internal controller memory. Without doing so, it will lead to endxfer timeouts, which results to controller halt failures. Change-Id: Ie58a709ee48f8f8e869285414ee2fd93d4d56326 Reviewed-by: Thinh Nguyen Signed-off-by: Wesley Cheng Link: https://lore.kernel.org/r/20220817182359.13550-5-quic_wcheng@quicinc.com Signed-off-by: Greg Kroah-Hartman Signed-off-by: Frank Wang (cherry picked from commit dff981842a0b1c05786c4c0cdea3ac80079ddd57) --- drivers/usb/dwc3/gadget.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 570759088ea3..28115d6672e8 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -2869,6 +2869,7 @@ static int __dwc3_gadget_start(struct dwc3 *dwc) dwc3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(512); dep = dwc->eps[0]; + dep->flags = 0; ret = __dwc3_gadget_ep_enable(dep, DWC3_DEPCFG_ACTION_INIT); if (ret) { dev_err(dwc->dev, "failed to enable %s\n", dep->name); @@ -2876,6 +2877,7 @@ static int __dwc3_gadget_start(struct dwc3 *dwc) } dep = dwc->eps[1]; + dep->flags = 0; ret = __dwc3_gadget_ep_enable(dep, DWC3_DEPCFG_ACTION_INIT); if (ret) { dev_err(dwc->dev, "failed to enable %s\n", dep->name); @@ -3800,11 +3802,12 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc, dep = dwc->eps[epnum]; if (!(dep->flags & DWC3_EP_ENABLED)) { - if (!(dep->flags & DWC3_EP_TRANSFER_STARTED)) + if ((epnum > 1) && !(dep->flags & DWC3_EP_TRANSFER_STARTED)) return; /* Handle only EPCMDCMPLT when EP disabled */ - if (event->endpoint_event != DWC3_DEPEVT_EPCMDCMPLT) + if ((event->endpoint_event != DWC3_DEPEVT_EPCMDCMPLT) && + !(epnum <= 1 && event->endpoint_event == DWC3_DEPEVT_XFERCOMPLETE)) return; }