From cf0dba7ad60c98807229dfc81f737dbd0d983375 Mon Sep 17 00:00:00 2001 From: Wesley Cheng Date: Thu, 1 Sep 2022 12:36:25 -0700 Subject: [PATCH] UPSTREAM: usb: dwc3: gadget: Submit endxfer command if delayed during disconnect During a cable disconnect sequence, if ep0state is not in the SETUP phase, then nothing will trigger any pending end transfer commands. Force stopping of any pending SETUP transaction, and move back to the SETUP phase. Change-Id: Icae282b1a47872a262fea9b6bd4e8dea08c5455d Reviewed-by: Thinh Nguyen Signed-off-by: Wesley Cheng Link: https://lore.kernel.org/r/20220901193625.8727-6-quic_wcheng@quicinc.com Signed-off-by: Greg Kroah-Hartman Signed-off-by: Frank Wang (cherry picked from commit 8422b769fa46bd429dc0f324012629a4691f0dd9) --- drivers/usb/dwc3/gadget.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 281e559f5990..8a3248c6d063 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -3978,13 +3978,24 @@ static void dwc3_gadget_disconnect_interrupt(struct dwc3 *dwc) reg &= ~DWC3_DCTL_INITU2ENA; dwc3_gadget_dctl_write_safe(dwc, reg); + dwc->connected = false; + dwc3_disconnect_gadget(dwc); dwc->gadget->speed = USB_SPEED_UNKNOWN; dwc->setup_packet_pending = false; usb_gadget_set_state(dwc->gadget, USB_STATE_NOTATTACHED); - dwc->connected = false; + if (dwc->ep0state != EP0_SETUP_PHASE) { + unsigned int dir; + + dir = !!dwc->ep0_expect_in; + if (dwc->ep0state == EP0_DATA_PHASE) + dwc3_ep0_end_control_data(dwc, dwc->eps[dir]); + else + dwc3_ep0_end_control_data(dwc, dwc->eps[!dir]); + dwc3_ep0_stall_and_restart(dwc); + } } static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc)