summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWesley Cheng <quic_wcheng@quicinc.com>2022-07-11 18:44:03 -0700
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2022-07-14 16:09:43 +0200
commit5e76ee96be8f7bbf9416a5edddc8c064e7e7c6ac (patch)
treec295eadcbfa898f1d6413adc71cdf12baa5a321f
parent2d937c64e8bf3d9b11b1d62d37fbe97b3cd5dc8d (diff)
usb: dwc3: ep0: Properly handle setup_packet_pending scenario in data stage
During a 3 stage SETUP transfer, if the host sends another SETUP token before completing the status phase, it signifies that the host has aborted the current control transfer. Currently, if a setup_packet_pending is received, there are no subsequent calls to dwc3_ep0_out_start() to fetch the new SETUP packet. This leads to a stall on EP0, as host does not expect another STATUS phase as it has aborted the current transfer. Fix this issue by explicitly stalling and restarting EP0, as well as resetting the trb_enqueue indexes. (without this, there is a chance the SETUP TRB is set up on trb_endqueue == 1) Signed-off-by: Wesley Cheng <quic_wcheng@quicinc.com> Link: https://lore.kernel.org/r/20220712014403.2977-1-quic_wcheng@quicinc.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/usb/dwc3/ep0.c7
1 files changed, 7 insertions, 0 deletions
diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
index 2a510e84eef4..197af63f8d05 100644
--- a/drivers/usb/dwc3/ep0.c
+++ b/drivers/usb/dwc3/ep0.c
@@ -239,6 +239,8 @@ void dwc3_ep0_stall_and_restart(struct dwc3 *dwc)
dwc3_gadget_giveback(dep, req, -ECONNRESET);
}
+ dwc->eps[0]->trb_enqueue = 0;
+ dwc->eps[1]->trb_enqueue = 0;
dwc->ep0state = EP0_SETUP_PHASE;
dwc3_ep0_out_start(dwc);
}
@@ -1140,6 +1142,11 @@ static void dwc3_ep0_xfernotready(struct dwc3 *dwc,
if (dwc->ep0_next_event != DWC3_EP0_NRDY_STATUS)
return;
+ if (dwc->setup_packet_pending) {
+ dwc3_ep0_stall_and_restart(dwc);
+ return;
+ }
+
dwc->ep0state = EP0_STATUS_PHASE;
if (dwc->delayed_status) {