From dd42da7131999e5d331d9c20ee7c73c72657f746 Mon Sep 17 00:00:00 2001 From: Sriharsha Allenki Date: Thu, 28 May 2020 17:42:11 +0530 Subject: [PATCH] usb: dwc3: Fix enumeration failure with reset during transfers If the host initiates a BUS reset when SETUP packet is in progress, it is possible that the trb_enqueue is set to 1 and ep0_bounced is set to true in handling the SETUP packet which was interrupted with the BUS reset. With the trb_enqueue set to 1, instead of the first TRB the second TRB is queued but the START_TRANSFER is issued on the first TRB which does not have HWO is set leading to the enumeration failure, since there is no available TRB to handle the SETUP packet from the host. Fix this by resetting the trb_enqueue and ep0_bounced to prevent the enumeration failure. Change-Id: I73a4ca0a970124714acc511ab507d1411d197709 Signed-off-by: Sriharsha Allenki --- drivers/usb/dwc3/gadget.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 04888bb784b2..c9e4bd51d802 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -745,12 +745,13 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep, unsigned int action) reg |= DWC3_DALEPENA_EP(dep->number); dwc3_writel(dwc->regs, DWC3_DALEPENA, reg); + dep->trb_dequeue = 0; + dep->trb_enqueue = 0; + if (usb_endpoint_xfer_control(desc)) goto out; /* Initialize the TRB ring */ - dep->trb_dequeue = 0; - dep->trb_enqueue = 0; memset(dep->trb_pool, 0, sizeof(struct dwc3_trb) * DWC3_TRB_NUM); @@ -2423,6 +2424,7 @@ static int __dwc3_gadget_start(struct dwc3 *dwc) /* begin to receive SETUP packets */ dwc->ep0state = EP0_SETUP_PHASE; + dwc->ep0_bounced = false; dwc->link_state = DWC3_LINK_STATE_SS_DIS; dwc3_ep0_out_start(dwc); @@ -3287,6 +3289,10 @@ static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc) dwc3_ep0_end_control_data(dwc, dwc->eps[dir]); else dwc3_ep0_end_control_data(dwc, dwc->eps[!dir]); + + dwc->eps[0]->trb_enqueue = 0; + dwc->eps[1]->trb_enqueue = 0; + dwc3_ep0_stall_and_restart(dwc); }