On 23. 06. 25, 15:39, Mathias Nyman wrote:
Hub driver warm-resets ports in SS.Inactive or Compliance mode to recover a possible connected device. The port reset code correctly detects if a connection is lost during reset, but hub driver port_event() fails to take this into account in some cases. port_event() ends up using stale values and assumes there is a connected device, and will try all means to recover it, including power-cycling the port.
Details: This case was triggered when xHC host was suspended with DbC (Debug Capability) enabled and connected. DbC turns one xHC port into a simple usb debug device, allowing debugging a system with an A-to-A USB debug cable.
xhci DbC code disables DbC when xHC is system suspended to D3, and enables it back during resume. We essentially end up with two hosts connected to each other during suspend, and, for a short while during resume, until DbC is enabled back. The suspended xHC host notices some activity on the roothub port, but can't train the link due to being suspended, so xHC hardware sets a CAS (Cold Attach Status) flag for this port to inform xhci host driver that the port needs to be warm reset once xHC resumes.
CAS is xHCI specific, and not part of USB specification, so xhci driver tells usb core that the port has a connection and link is in compliance mode. Recovery from complinace mode is similar to CAS recovery.
xhci CAS driver support that fakes a compliance mode connection was added in commit 8bea2bd37df0 ("usb: Add support for root hub port status CAS")
Once xHCI resumes and DbC is enabled back, all activity on the xHC roothub host side port disappears. The hub driver will anyway think port has a connection and link is in compliance mode, and hub driver will try to recover it.
The port power-cycle during recovery seems to cause issues to the active DbC connection.
Fix this by clearing connect_change flag if hub_port_reset() returns -ENOTCONN, thus avoiding the whole unnecessary port recovery and initialization attempt.
Cc: stable@vger.kernel.org Fixes: 8bea2bd37df0 ("usb: Add support for root hub port status CAS") Tested-by: Ćukasz Bartosik ukaszb@chromium.org Signed-off-by: Mathias Nyman mathias.nyman@linux.intel.com
drivers/usb/core/hub.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 6bb6e92cb0a4..f981e365be36 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -5754,6 +5754,7 @@ static void port_event(struct usb_hub *hub, int port1) struct usb_device *hdev = hub->hdev; u16 portstatus, portchange; int i = 0;
- int err;
connect_change = test_bit(port1, hub->change_bits); clear_bit(port1, hub->event_bits); @@ -5850,8 +5851,11 @@ static void port_event(struct usb_hub *hub, int port1) } else if (!udev || !(portstatus & USB_PORT_STAT_CONNECTION) || udev->state == USB_STATE_NOTATTACHED) { dev_dbg(&port_dev->dev, "do warm reset, port only\n");
if (hub_port_reset(hub, port1, NULL,
HUB_BH_RESET_TIME, true) < 0)
err = hub_port_reset(hub, port1, NULL,
HUB_BH_RESET_TIME, true);
if (!udev && err == -ENOTCONN)
connect_change = 0;
else if (err < 0) hub_port_disable(hub, port1, 1);
This was reported to break the USB on one box:
[Wed Aug 6 16:51:33 2025] [ T355745] usb 1-2: reset full-speed USB device number 12 using xhci_hcd [Wed Aug 6 16:51:34 2025] [ T355745] usb 1-2: device descriptor read/64, error -71 [Wed Aug 6 16:51:34 2025] [ T355745] usb 1-2: device descriptor read/64, error -71 [Wed Aug 6 16:51:34 2025] [ T355745] usb 1-2: reset full-speed USB device number 12 using xhci_hcd [Wed Aug 6 16:51:34 2025] [ T355745] usb 1-2: device descriptor read/64, error -71 [Wed Aug 6 16:51:35 2025] [ T355745] usb 1-2: device descriptor read/64, error -71 [Wed Aug 6 16:51:35 2025] [ T355745] usb 1-2: reset full-speed USB device number 12 using xhci_hcd [Wed Aug 6 16:51:35 2025] [ T355745] usb 1-2: Device not responding to setup address. [Wed Aug 6 16:51:35 2025] [ T355745] usb 1-2: Device not responding to setup address. [Wed Aug 6 16:51:35 2025] [ T355745] usb 1-2: device not accepting address 12, error -71 [Wed Aug 6 16:51:35 2025] [ T355745] usb 1-2: WARN: invalid context state for evaluate context command. [Wed Aug 6 16:51:36 2025] [ T355745] usb 1-2: reset full-speed USB device number 12 using xhci_hcd [Wed Aug 6 16:51:36 2025] [ C10] xhci_hcd 0000:0e:00.0: ERROR unknown event type 2 [Wed Aug 6 16:51:36 2025] [ T355745] usb 1-2: Device not responding to setup address. [Wed Aug 6 16:51:37 2025] [ C10] xhci_hcd 0000:0e:00.0: ERROR unknown event type 2 [Wed Aug 6 16:52:50 2025] [ T362645] xhci_hcd 0000:0e:00.0: Abort failed to stop command ring: -110 [Wed Aug 6 16:52:50 2025] [ T362645] xhci_hcd 0000:0e:00.0: xHCI host controller not responding, assume dead [Wed Aug 6 16:52:50 2025] [ T362645] xhci_hcd 0000:0e:00.0: HC died; cleaning up [Wed Aug 6 16:52:50 2025] [ T359046] usb 1-1: USB disconnect, device number 13 [Wed Aug 6 16:52:50 2025] [ T355745] xhci_hcd 0000:0e:00.0: Timeout while waiting for setup device command [Wed Aug 6 16:52:50 2025] [ T362645] usb 2-3: USB disconnect, device number 2 [Wed Aug 6 16:52:50 2025] [ T362839] cdc_acm 1-5:1.5: acm_port_activate - usb_submit_urb(ctrl irq) failed [Wed Aug 6 16:52:50 2025] [ T355745] usb 1-2: device not accepting address 12, error -62 [Wed Aug 6 16:52:50 2025] [ T359046] usb 1-2: USB disconnect, device number 12 [Wed Aug 6 16:52:50 2025] [ T359046] usb 1-3: USB disconnect, device number 4 [Wed Aug 6 16:52:50 2025] [ T359046] usb 1-3.1: USB disconnect, device number 6 [Wed Aug 6 16:52:50 2025] [ T359046] usb 1-4: USB disconnect, device number 16 [Wed Aug 6 16:52:50 2025] [ T359046] usb 1-5: USB disconnect, device number 15 [Wed Aug 6 16:52:50 2025] [ T359046] usb 1-7: USB disconnect, device number 8
Using 6.16 minus this 2521106fc732b0b makes it works again.
The same happens with 6.15.8 as this was backported there. (6.15.6 is fine).
lsusb --tree
/: Bus 001.Port 001: Dev 001, Class=root_hub, Driver=xhci_hcd/12p, 480M |__ Port 003: Dev 006, If 0, Class=Hub, Driver=hub/4p, 480M |__ Port 001: Dev 008, If 0, Class=Human Interface Device, Driver=usbhid, 12M |__ Port 001: Dev 008, If 1, Class=Human Interface Device, Driver=usbhid, 12M |__ Port 001: Dev 008, If 2, Class=Chip/SmartCard, Driver=usbfs, 12M |__ Port 004: Dev 007, If 0, Class=Audio, Driver=snd-usb-audio, 480M |__ Port 004: Dev 007, If 1, Class=Audio, Driver=snd-usb-audio, 480M |__ Port 004: Dev 007, If 2, Class=Application Specific Interface, Driver=[none], 480M |__ Port 004: Dev 007, If 3, Class=Communications, Driver=cdc_acm, 480M |__ Port 004: Dev 007, If 4, Class=CDC Data, Driver=cdc_acm, 480M |__ Port 005: Dev 009, If 0, Class=Audio, Driver=snd-usb-audio, 480M |__ Port 005: Dev 009, If 1, Class=Audio, Driver=snd-usb-audio, 480M |__ Port 005: Dev 009, If 2, Class=Audio, Driver=snd-usb-audio, 480M |__ Port 005: Dev 009, If 3, Class=Audio, Driver=snd-usb-audio, 480M |__ Port 005: Dev 009, If 4, Class=Audio, Driver=snd-usb-audio, 480M |__ Port 005: Dev 009, If 5, Class=Communications, Driver=cdc_acm, 480M |__ Port 005: Dev 009, If 6, Class=CDC Data, Driver=cdc_acm, 480M |__ Port 007: Dev 010, If 0, Class=Vendor Specific Class, Driver=[none], 12M |__ Port 007: Dev 010, If 2, Class=Human Interface Device, Driver=usbhid, 12M /: Bus 002.Port 001: Dev 001, Class=root_hub, Driver=xhci_hcd/5p, 20000M/x2 |__ Port 003: Dev 002, If 0, Class=Hub, Driver=hub/4p, 5000M /: Bus 003.Port 001: Dev 001, Class=root_hub, Driver=xhci_hcd/12p, 480M |__ Port 003: Dev 002, If 0, Class=Human Interface Device, Driver=usbhid, 12M |__ Port 003: Dev 002, If 1, Class=Human Interface Device, Driver=usbhid, 12M |__ Port 003: Dev 002, If 2, Class=Human Interface Device, Driver=usbhid, 12M /: Bus 004.Port 001: Dev 001, Class=root_hub, Driver=xhci_hcd/5p, 20000M/x2 /: Bus 005.Port 001: Dev 001, Class=root_hub, Driver=xhci_hcd/2p, 480M /: Bus 006.Port 001: Dev 001, Class=root_hub, Driver=xhci_hcd/2p, 10000M /: Bus 007.Port 001: Dev 001, Class=root_hub, Driver=xhci_hcd/2p, 480M |__ Port 002: Dev 002, If 0, Class=Human Interface Device, Driver=usbhid, 480M |__ Port 002: Dev 002, If 1, Class=Human Interface Device, Driver=usbhid, 480M |__ Port 002: Dev 002, If 2, Class=Human Interface Device, Driver=usbhid, 480M /: Bus 008.Port 001: Dev 001, Class=root_hub, Driver=xhci_hcd/2p, 10000M /: Bus 009.Port 001: Dev 001, Class=root_hub, Driver=xhci_hcd/1p, 480M /: Bus 010.Port 001: Dev 001, Class=root_hub, Driver=xhci_hcd/0p, 5000M
Any ideas? What would you need to debug this?
thanks,