Skip to content

Commit

Permalink
usb: dwc3: ep0: Properly handle setup_packet_pending scenario in data…
Browse files Browse the repository at this point in the history
… 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>
  • Loading branch information
Wesley Cheng authored and Greg Kroah-Hartman committed Jul 14, 2022
1 parent 2d937c6 commit 5e76ee9
Showing 1 changed file with 7 additions and 0 deletions.
7 changes: 7 additions & 0 deletions drivers/usb/dwc3/ep0.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down Expand Up @@ -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) {
Expand Down

0 comments on commit 5e76ee9

Please sign in to comment.