From: Michal Pecio <michal.pecio@gmail.com>
To: Henry Tseng <henrytseng@qnap.com>
Cc: Mathias Nyman <mathias.nyman@intel.com>,
Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
linux-usb@vger.kernel.org
Subject: Re: [PATCH 0/2] xhci: handshake timeout overrun and configure endpoint hang on device disconnect
Date: Fri, 9 Oct 2026 17:35:16 +0200 [thread overview]
Message-ID: <20261009173516.681681a6.michal.pecio@gmail.com> (raw)
In-Reply-To: <20261008102522.109308-1-henrytseng@qnap.com>
[-- Attachment #1: Type: text/plain, Size: 2991 bytes --]
On Thu, 8 Oct 2026 18:25:20 +0800, Henry Tseng wrote:
> > Does it help to blacklist "uas" driver before connecting the whole
> > tree? My guess at this point: probably not, it's not a streams bug.
> >
>
> No, the host still dies.
> Deconfiguring 2-1.3 completes fine:
>
> [ 87.929570] xhci_hcd 0000:0c:00.3: Cancel URB 0000000064a1e51d, dev 1.3, ep 0x83, starting at offset 0xfff49000
> [ 87.929675] xhci_hcd 0000:0c:00.3: Stopped on Transfer TRB for slot 4 ep 6
> [ 87.929756] xhci_hcd 0000:0c:00.3: Successful Set TR Deq Ptr cmd, deq = @fff49010
> [ 87.930564] xhci_hcd 0000:0c:00.3: drop ep 0x83, slot id 4, new drop flags = 0x80, new add flags = 0x0
> [ 87.937756] xhci_hcd 0000:0c:00.3: Successful Endpoint Configure command
>
> The host still dies on disconnection, but the stuck command is now the
> configure endpoint dropping 0x83 of the 2-1.4 hub (slot 6):
>
> [ 164.793408] usb 2-1: USB disconnect, device number 2
> [ 164.793419] usb 2-1.3: USB disconnect, device number 3
> ...
> [ 164.803390] usb 2-1.4: USB disconnect, device number 4
> ...
> [ 164.834173] xhci_hcd 0000:0c:00.3: Cancel URB 000000009ac4b95a, dev 1.4, ep 0x83, starting at offset 0xfff15010
> [ 164.834219] xhci_hcd 0000:0c:00.3: Stopped on Transfer TRB for slot 6 ep 6
> [ 164.834819] xhci_hcd 0000:0c:00.3: drop ep 0x83, slot id 6, new drop flags = 0x80, new add flags = 0x0
> [ 170.058142] xhci_hcd 0000:0c:00.3: Command timeout, USBSTS: 0x00000010 PCD
> [ 185.909602] xhci_hcd 0000:0c:00.3: Abort failed to stop command ring: -110
> [ 185.921446] xhci_hcd 0000:0c:00.3: xHCI host controller not responding, assume dead
But 2-1.4.4 deconfigured successfully before 2-1.4 failed?
Looks like there is something special about those hubs...
The kernel doesn't seem to be doing anything wrong, just stops
these endpoints (which don't even seem to be doing much) and
tries to disable them. I'm only unsure why 2-1.3 seems not to
be suspended despite having no children?
Set TR Deq is omitted in the failing case above, but this isn't
supposed to matter and kernels before 7.3 didn't omit it.
One thing coming to my mind is that the HW might expect the
"deconfigure" flag to be set in the Configure Endpoint command
under such circumstances. If you don't mind spending a few minutes
more, please try the attached patch, and also before unplugging,
echo 0 > /sys/bus/usb/devices/1-1/bConfigurationValue
echo 2-1.3:1.0 >/sys/bus/usb/drivers/hub/unbind
But it's starting to look like your patch may be the only option.
It's not out of spec and I've tested it on some HW today, none of
it had any issues with disabling slots with enabled endpoints.
This only works for disconnection from the root hub. Do you have
any external (ideally at least USB 3.1 10gbps) hub to check if HC
still hangs when you disconnect the same device from a hub?
Maybe it helps to re-connect the device before abort begins?
This worked with Renesas :)
Regards,
Michal
[-- Attachment #2: xhci-deconf.patch --]
[-- Type: text/x-patch, Size: 2931 bytes --]
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 2ea1c7dc1574..35679e445a39 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -4421,11 +4421,11 @@ int xhci_queue_reset_device(struct xhci_hcd *xhci, struct xhci_command *cmd,
/* Queue a configure endpoint command TRB */
int xhci_queue_configure_endpoint(struct xhci_hcd *xhci,
struct xhci_command *cmd, dma_addr_t in_ctx_ptr,
- u32 slot_id, bool command_must_succeed)
+ u32 slot_id, bool dc, bool command_must_succeed)
{
return queue_command(xhci, cmd, lower_32_bits(in_ctx_ptr),
upper_32_bits(in_ctx_ptr), 0,
- TRB_TYPE(TRB_CONFIG_EP) | SLOT_ID_FOR_TRB(slot_id),
+ TRB_TYPE(TRB_CONFIG_EP) | (dc ? TRB_DC : 0) | SLOT_ID_FOR_TRB(slot_id),
command_must_succeed);
}
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 34f342d2c7d7..035885903807 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -3052,11 +3052,25 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci,
trace_xhci_configure_endpoint_ctrl_ctx(ctrl_ctx);
trace_xhci_configure_endpoint(slot_ctx);
- if (!ctx_change)
+ if (!ctx_change) {
+ bool dc = true;
+ u32 add = le32_to_cpu(ctrl_ctx->add_flags) >> 2;
+ u32 drop = le32_to_cpu(ctrl_ctx->drop_flags) >> 2;
+
+ for (int i = 1; i <= 30; i++) {
+ if (add & 1 || !(drop & 1 || EP_STATE_DISABLED ==
+ GET_EP_CTX_STATE(xhci_get_ep_ctx(xhci, virt_dev->out_ctx, i))))
+ dc = false;
+ add >>= 1;
+ drop >>= 1;
+ }
+ if (dc)
+ xhci_err(xhci, "deconfigure slot %d\n", udev->slot_id);
+
ret = xhci_queue_configure_endpoint(xhci, command,
command->in_ctx->dma,
- udev->slot_id, must_succeed);
- else
+ udev->slot_id, dc, must_succeed);
+ } else
ret = xhci_queue_evaluate_context(xhci, command,
command->in_ctx->dma,
udev->slot_id, must_succeed);
@@ -3486,7 +3500,7 @@ static void xhci_endpoint_reset(struct usb_hcd *hcd,
xhci_endpoint_copy(xhci, cfg_cmd->in_ctx, vdev->out_ctx, ep_index);
err = xhci_queue_configure_endpoint(xhci, cfg_cmd, cfg_cmd->in_ctx->dma,
- udev->slot_id, false);
+ udev->slot_id, false, false);
if (err < 0) {
spin_unlock_irqrestore(&xhci->lock, flags);
xhci_free_command(xhci, cfg_cmd);
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 3de22e4928b4..c6d771a399a7 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -1929,7 +1929,7 @@ int xhci_queue_isoc_tx_prepare(struct xhci_hcd *xhci, gfp_t mem_flags,
struct urb *urb, int slot_id, unsigned int ep_index);
int xhci_queue_configure_endpoint(struct xhci_hcd *xhci,
struct xhci_command *cmd, dma_addr_t in_ctx_ptr, u32 slot_id,
- bool command_must_succeed);
+ bool dc, bool command_must_succeed);
int xhci_queue_get_port_bw(struct xhci_hcd *xhci,
struct xhci_command *cmd, dma_addr_t in_ctx_ptr,
u8 dev_speed, bool command_must_succeed);
prev parent reply other threads:[~2026-10-09 15:35 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-30 10:17 [PATCH 0/2] xhci: handshake timeout overrun and configure endpoint hang on device disconnect Henry Tseng
2026-09-30 10:17 ` [PATCH 1/2] xhci: make xhci_handshake() timeout wall-clock based again Henry Tseng
2026-09-30 10:17 ` [PATCH 2/2] xhci: skip configure endpoint when dropping endpoints of a disconnected device Henry Tseng
2026-10-02 9:30 ` [PATCH 0/2] xhci: handshake timeout overrun and configure endpoint hang on device disconnect Michal Pecio
2026-10-07 9:52 ` Henry Tseng
2026-10-08 9:06 ` Michal Pecio
2026-10-08 9:13 ` Michal Pecio
2026-10-08 10:25 ` Henry Tseng
2026-10-09 15:35 ` Michal Pecio [this message]
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=20261009173516.681681a6.michal.pecio@gmail.com \
--to=michal.pecio@gmail.com \
--cc=gregkh@linuxfoundation.org \
--cc=henrytseng@qnap.com \
--cc=linux-usb@vger.kernel.org \
--cc=mathias.nyman@intel.com \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox