[PATCH 2/5] usb: xhci: reset_ep: wait for real completion, not the caller's timeout

Stephano Cetola <[email protected]>
Newsgroups org.infradead.lists.barebox
Message-ID <[email protected]>
reset_ep() recovers a halted endpoint by issuing a Reset Endpoint
command followed by a Set TR Dequeue Pointer command, each followed
by a wait for the command's completion event. It waited using the
caller's timeout_ms.

For an interrupt endpoint poll, timeout_ms is 0 (a non-blocking
check for pending data). Passed through to reset_ep(), that same 0ms
value gives the actual recovery commands almost no time to complete.
xhci_wait_for_event() gives up immediately, reset_ep() returns before
the halt is ever cleared, and the endpoint stays halted forever no
matter how many times the caller retries.

Recovering from a halt is a command completion wait, not a data
transfer wait, and should not inherit the transfer's timeout.

Signed-off-by: Stephano Cetola <[email protected]>
---
 drivers/usb/host/xhci-ring.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index bd38f0de91..0b11da88a2 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -506,7 +506,7 @@ union xhci_trb *xhci_wait_for_event(struct xhci_ctrl *ctrl, trb_type expected,
  * Send reset endpoint command for given endpoint. This recovers from a
  * halted endpoint (e.g. due to a stall error).
  */
-static void reset_ep(struct usb_device *udev, int ep_index, unsigned int timeout_ms)
+static void reset_ep(struct usb_device *udev, int ep_index)
 {
 	struct xhci_ctrl *ctrl = xhci_get_ctrl(udev);
 	struct xhci_ring *ring =  ctrl->devs[udev->slot_id]->eps[ep_index].ring;
@@ -517,7 +517,7 @@ static void reset_ep(struct usb_device *udev, int ep_index, unsigned int timeout
 	dev_info(&udev->dev, "Resetting EP %d...\n", ep_index);
 
 	xhci_queue_command(ctrl, 0, udev->slot_id, ep_index, TRB_RESET_EP);
-	event = xhci_wait_for_event(ctrl, TRB_COMPLETION, timeout_ms);
+	event = xhci_wait_for_event(ctrl, TRB_COMPLETION, XHCI_TIMEOUT_DEFAULT);
 	if (!event)
 		return;
 
@@ -528,7 +528,7 @@ static void reset_ep(struct usb_device *udev, int ep_index, unsigned int timeout
 	addr = xhci_trb_virt_to_dma(ring->enq_seg,
 		(void *)((uintptr_t)ring->enqueue | ring->cycle_state));
 	xhci_queue_command(ctrl, addr, udev->slot_id, ep_index, TRB_SET_DEQ);
-	event = xhci_wait_for_event(ctrl, TRB_COMPLETION, timeout_ms);
+	event = xhci_wait_for_event(ctrl, TRB_COMPLETION, XHCI_TIMEOUT_DEFAULT);
 	if (!event)
 		return;
 
@@ -706,7 +706,7 @@ int xhci_bulk_tx(struct usb_device *udev, unsigned long pipe,
 	 * have dealt with whatever caused the error.
 	 */
 	if ((le32_to_cpu(ep_ctx->ep_info) & EP_STATE_MASK) == EP_STATE_HALTED)
-		reset_ep(udev, ep_index, timeout_ms);
+		reset_ep(udev, ep_index);
 
 	ring = virt_dev->eps[ep_index].ring;
 	/*
@@ -1055,7 +1055,7 @@ int xhci_ctrl_tx(struct usb_device *udev, unsigned long pipe,
 		dma_unmap_single(ctrl->host.hw_dev, map, length, direction);
 
 	if (udev->status == USB_ST_STALLED) {
-		reset_ep(udev, ep_index, timeout_ms);
+		reset_ep(udev, ep_index);
 		return -EPIPE;
 	}
 

-- 
2.55.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.