[PATCH 4/5] usb: xhci: xhci_bulk_tx: re-fetch ep_ctx after resetting a halted endpoint

Stephano Cetola <[email protected]>
Newsgroups org.infradead.lists.barebox
Message-ID <[email protected]>
xhci_bulk_tx() reads the endpoint's context once at the top of the
function and reuses that same value both to decide whether to call
reset_ep() and, further down, to pass to prepare_ring(). reset_ep()
clears the halt by updating the endpoint's output context via DMA,
but the earlier ep_ctx read is never invalidated or refetched after
that, so prepare_ring() always sees the stale pre-reset
EP_STATE_HALTED value.

prepare_ring() rejects the transfer with -EINVAL, regardless of
whether reset_ep() actually succeeded. The USB keyboard driver's
poller treats any error other than -EAGAIN as fatal. One spurious
rejection is enough to stop it for good, and nothing calls
xhci_bulk_tx() again after that. The keyboard stays dead until the
next boot.

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

diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 522ac7c45f..a3b78052a4 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -705,8 +705,13 @@ int xhci_bulk_tx(struct usb_device *udev, unsigned long pipe,
 	 * the next transfer. It is the responsibility of the upper layer to
 	 * have dealt with whatever caused the error.
 	 */
-	if ((le32_to_cpu(ep_ctx->ep_info) & EP_STATE_MASK) == EP_STATE_HALTED)
+	if ((le32_to_cpu(ep_ctx->ep_info) & EP_STATE_MASK) == EP_STATE_HALTED) {
 		reset_ep(udev, ep_index);
+		/* reset_ep() updates the context via DMA. Re-fetch it here. */
+		xhci_inval_cache((uintptr_t)virt_dev->out_ctx->bytes,
+				 virt_dev->out_ctx->size);
+		ep_ctx = xhci_get_ep_ctx(ctrl, virt_dev->out_ctx, ep_index);
+	}
 
 	ring = virt_dev->eps[ep_index].ring;
 	/*

-- 
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.