From: Michal Pecio <michal.pecio@gmail.com>
To: Mathias Nyman <mathias.nyman@linux.intel.com>
Cc: yiyu@yiyuzhou.io, <linux-usb@vger.kernel.org>,
regressions@lists.linux.dev, diogochaves@me.com,
raoxu@uniontech.com, dennis@dsine.de, gregkh@linuxfoundation.org
Subject: Re: [RFT PATCH 0/2] xhci: clean up endpoint rings after disconnect detect
Date: Wed, 28 Oct 2026 08:07:34 +0100 [thread overview]
Message-ID: <20261028080734.173da0e4.michal.pecio@gmail.com> (raw)
In-Reply-To: <20261027192128.386082-1-mathias.nyman@linux.intel.com>
On Tue, 27 Oct 2026 21:21:25 +0200, Mathias Nyman wrote:
> Yiyu Zhou wrote PATCH 1/2, fixing a regression in USB HID device
> enumeration caused by the endpoint recovery prevention code added in
> v7.3-rc1. Some HID devices that used to enumerate after a brief
> disconnect during enumeration now got stuck until URBs timed out.
>
> PATCH 1/2 gives back the pending URBs right away, which solves most of
> the problem, but it leaves the TRBs of the given back URBs on the ep0
> ring. ep0 survives a brief disconnect during a port reset, so the xHC
> may later process those TRBs during an enumeration retry, writing into
> buffers that were already given back, or ep0 stays halted and the next
> control transfer times out.
>
> PATCH 2/2 cleans up the ep0 ring by resetting ep0 and moving its
> dequeue pointer past the cancelled TDs, even if a disconnect or link
> error is detected. Only Reset Endpoint and Set TR Dequeue Pointer
> commands are issued; ep0 is not restarted while the disconnect is
> pending. The rapid endpoint reset, restart and stop sequence that made
> some xHC hosts fail Stop Endpoint commands is still avoided. Other
> endpoints are still given back without resetting them, but their TRBs
> are turned into no-ops first.
>
> If you have seen the HID enumeration issue, or the xHC Stop Endpoint
> failures with rapid endpoint state changes, testing these two patches
> would be greatly appreciated.
>
> If these patches work, they might be squashed into one before going
> upstream.
Might? :)
1/2 is a possibly dangereous regression and shouldn't be used alone.
Anyway, I think it all can be done with a bit less code, while also
handling disconnection during unlink. Particularly on EP0, multiple
URBs may be submitted by different drivers and/or userspace. Just
because one of them unlinks its URB doesn't mean that the others are
aware of anything being wrong and won't stall for <N> seconds.
This below is a rudimentarily tested RFC but it seems to work. It's
simple enough that hopefully it might even be correct. I will test it
more and write a changelog later today if there are no objections.
I tweaked the logic to return everything with -ESHUTDOWN and not
bother to assign proper status to the URB which halted. Intuition:
we want them to give up, not call clear_halt() or reset_device().
---
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index fa6684746305..b37056cb8576 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -987,14 +987,11 @@ static int xhci_handle_halted_endpoint(struct xhci_hcd *xhci,
int err;
/*
- * Avoid resetting endpoint if link is inactive or device disonnected.
- * Can cause host hang.
- * Device will be reset to recover an inactive link, so don't do anything
+ * Mark endpoints behind disconnected or SS.Inactive root hub ports.
+ * Restarting them is futile and known to triggers HC bugs on USB3.
*/
- if (rhub_port->link_inactive || !rhub_port->connected) {
+ if (rhub_port->link_inactive || !rhub_port->connected)
ep->ep_state |= EP_DROP_PENDING;
- return -ENODEV;
- }
/* add td to cancelled list and let reset ep handler take care of it */
if (reset_type == EP_HARD_RESET) {
@@ -1011,6 +1008,12 @@ static int xhci_handle_halted_endpoint(struct xhci_hcd *xhci,
return 0;
}
+ /* Don't reset lost endpoints, only EP0 can survive device reset */
+ if (ep->ep_state & EP_DROP_PENDING && ep->ep_index) {
+ xhci_process_cancelled_tds(xhci, ep);
+ return 0;
+ }
+
err = xhci_reset_halted_ep(xhci, slot_id, ep->ep_index, reset_type);
if (err)
return err;
@@ -1022,6 +1025,9 @@ static int xhci_handle_halted_endpoint(struct xhci_hcd *xhci,
return 0;
}
+static void xhci_kill_endpoint_urbs(struct xhci_hcd *xhci, int slot_id, int ep_index);
+
+
/*
* Fix up the ep ring first, so HW stops executing cancelled TDs.
* We have the xHCI lock, so nothing can modify this list until we drop it.
@@ -1047,6 +1053,22 @@ static int xhci_invalidate_cancelled_tds(struct xhci_hcd *xhci, struct xhci_virt
if (ep->ep_state & SET_DEQ_PENDING)
return 0;
+ if (ep->ep_state & EP_DROP_PENDING) {
+ xhci_dbg(xhci, "Nuking dead slot %d ep %d\n", ep->vdev->slot_id, ep->ep_index);
+ if (ep->ep_index) {
+ xhci_kill_endpoint_urbs(xhci, ep->vdev->slot_id, ep->ep_index);
+ return 0;
+ }
+ /* EP0 may be reused after device reset, clean up the ring properly */
+ list_for_each_entry(td, &ep->ring->td_list, td_list) {
+ td->status = -ESHUTDOWN;
+ if (list_empty(&td->cancelled_td_list)) {
+ list_add_tail(&td->cancelled_td_list, &ep->cancelled_td_list);
+ td->cancel_status = TD_DIRTY; // for clarity, it's redundant
+ }
+ }
+ }
+
list_for_each_entry_safe(td, tmp_td, &ep->cancelled_td_list, cancelled_td_list) {
xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb,
"Removing canceled TD starting at 0x%llx (dma) in stream %u URB %p",
@@ -1061,12 +1083,6 @@ static int xhci_invalidate_cancelled_tds(struct xhci_hcd *xhci, struct xhci_virt
continue;
}
- /* device disconnected or link error, ep will be dropped */
- if (ep->ep_state & EP_DROP_PENDING) {
- td->cancel_status = TD_CLEARED;
- continue;
- }
-
/*
* If a ring stopped on the TD we need to cancel then we have to
* move the xHC endpoint ring dequeue pointer past this TD.
next prev parent reply other threads:[~2026-10-28 7:07 UTC|newest]
Thread overview: 43+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-24 17:47 [REGRESSION] usbhid -110 timeouts and reset loop for Keychron M5 (3434:d068) at boot since v7.3 Dennis Wissel
2026-10-24 20:34 ` Yiyu Zhou
2026-10-24 20:35 ` Yiyu Zhou
2026-10-24 23:10 ` Dennis Wissel
2026-10-25 8:59 ` Thorsten Leemhuis
2026-10-26 9:28 ` Mathias Nyman
2026-10-26 9:49 ` Thorsten Leemhuis
2026-10-26 10:47 ` Greg KH
2026-10-25 10:14 ` Michal Pecio
2026-10-25 11:11 ` Dennis Wissel
2026-10-26 11:15 ` Michal Pecio
2026-10-26 20:39 ` Yiyu Zhou
2026-10-27 7:29 ` Dennis Wissel
2026-10-27 8:48 ` [PATCH] xhci: keep ep0 blocked after disconnect until Address Device reloads it Yiyu Zhou
2026-10-27 9:10 ` sashiko-bot
2026-10-27 10:36 ` Mathias Nyman
2026-10-27 11:27 ` Michal Pecio
2026-10-27 18:40 ` Yiyu Zhou
2026-10-27 19:21 ` [RFT PATCH 0/2] xhci: clean up endpoint rings after disconnect detect Mathias Nyman
2026-10-27 19:21 ` [RFT PATCH 1/2] xhci: give back all TDs when skipping endpoint reset after disconnect Mathias Nyman
2026-10-27 19:21 ` [RFT PATCH 2/2] xhci: clean up ep0 ring after disconnect instead of leaving stale TRBs Mathias Nyman
2026-10-27 23:05 ` [RFT PATCH 0/2] xhci: clean up endpoint rings after disconnect detect Dennis Wissel
2026-10-29 14:07 ` Mathias Nyman
2026-10-28 7:07 ` Michal Pecio [this message]
2026-10-29 6:54 ` [PATCH 0/4] Fix problems on disconnected devices in 7.3 Michal Pecio
2026-10-29 6:54 ` [PATCH 1/4] usb: xhci: Fix TD invalidation on disconnected endpoints Michal Pecio
2026-10-29 7:12 ` sashiko-bot
2026-10-29 6:55 ` [PATCH 2/4] usb: xhci: Give back stranded URBs " Michal Pecio
2026-10-29 7:23 ` sashiko-bot
2026-10-29 6:56 ` [PATCH 3/4] usb: xhci: Give back URBs on halted " Michal Pecio
2026-10-29 7:19 ` sashiko-bot
2026-10-29 6:57 ` [PATCH 4/4] usb: xhci: Reject URBs to disconnected devices Michal Pecio
2026-10-29 7:24 ` sashiko-bot
2026-10-29 4:18 ` [RFT PATCH 0/2] xhci: clean up endpoint rings after disconnect detect Yiyu Zhou
2026-10-29 13:15 ` Mathias Nyman
2026-10-27 10:58 ` [REGRESSION] usbhid -110 timeouts and reset loop for Keychron M5 (3434:d068) at boot since v7.3 Michal Pecio
2026-10-26 9:18 ` Mathias Nyman
2026-10-26 9:51 ` Michal Pecio
2026-10-26 11:38 ` Michal Pecio
2026-10-26 11:54 ` Mathias Nyman
2026-10-26 18:56 ` Alan Stern
2026-10-26 18:58 ` Alan Stern
2026-10-25 6:28 ` Greg KH
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261028080734.173da0e4.michal.pecio@gmail.com \
--to=michal.pecio@gmail.com \
--cc=dennis@dsine.de \
--cc=diogochaves@me.com \
--cc=gregkh@linuxfoundation.org \
--cc=linux-usb@vger.kernel.org \
--cc=mathias.nyman@linux.intel.com \
--cc=raoxu@uniontech.com \
--cc=regressions@lists.linux.dev \
--cc=yiyu@yiyuzhou.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.