kernel: xhci: fix USB3 port events with a single roothub

USB3 port events are dropped whenever the controller has only one roothub.
The check that guards them treats a missing shared hcd as proof the hcd was
removed, which stopped being true with upstream commit 4736ebd7fcaf ("usb:
host: xhci-plat: omit shared hcd if either root hub has no ports"). A
controller whose USB2 root hub has no ports gets a single roothub and never
has a shared one, so every SuperSpeed event is thrown away and nothing
enumerates even though the port reports the device:

  0x006a1203 Powered Connected Enabled Link:U0 PortSpeed:4

Broadcom Northstar is such a controller. USB3 works there up to 5.15 and
stops from 5.19 onwards.

Tested on an Asus RT-N18U with kernel 6.18, seven SuperSpeed enumerations,
USB2 unaffected on both ports.

Link: https://github.com/openwrt/openwrt/issues/19592
Signed-off-by: Semih Baskan <strst.gs@gmail.com>
Link: https://github.com/openwrt/openwrt/pull/24547
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
This commit is contained in:
Semih Baskan authored and Hauke Mehrtens committed 2026-08-14 02:05:25 +02:00
1 parent 5f144a7513
commit f6bc2a3b29
2 files changed
+78

No files matched your search

@@ -0,0 +1,39 @@
From eb8cfe27aef67b30299aaf2a1ac538cf905135f2 Mon Sep 17 00:00:00 2001
From: Semih Baskan <strst.gs@gmail.com>
Date: Mon, 3 Aug 2026 07:08:11 +0300
Subject: [PATCH] usb: xhci: Handle USB3 port events when there is one roothub
handle_port_status() drops every USB3 port event when xhci->shared_hcd is
NULL. The check dates from a time when xhci-plat always created a shared
hcd, so a NULL one could only mean the hcd had been removed.
Since commit 4736ebd7fcaf ("usb: host: xhci-plat: omit shared hcd if
either root hub has no ports") that is no longer true. A controller whose
USB2 root hub has no ports gets a single roothub, the USB3 rhub is served
by the main hcd, and shared_hcd stays NULL for the lifetime of the device.
Every SuperSpeed port event is then thrown away as bogus behind a debug
message, so devices never enumerate even though the port reports them:
0x006a1203 Powered Connected Enabled Link:U0 PortSpeed:4
Broadcom Northstar is such a controller. USB3 works there up to 5.15 and
stops working from 5.19 onwards.
Ask xhci_get_usb3_hcd() instead. It returns the shared hcd when there is
one, the main hcd when the USB2 root hub has no ports, and NULL once the
shared hcd is gone, which keeps the original meaning of the check.
Fixes: 4736ebd7fcaf ("usb: host: xhci-plat: omit shared hcd if either root hub has no ports")
Signed-off-by: Semih Baskan <strst.gs@gmail.com>
---
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -1986,7 +1986,7 @@ static void handle_port_status(struct xh
vdev = xhci->devs[port->slot_id];
/* We might get interrupts after shared_hcd is removed */
- if (port->rhub == &xhci->usb3_rhub && xhci->shared_hcd == NULL) {
+ if (port->rhub == &xhci->usb3_rhub && xhci_get_usb3_hcd(xhci) == NULL) {
xhci_dbg(xhci, "ignore port event for removed USB3 hcd\n");
bogus_port_status = true;
goto cleanup;
@@ -0,0 +1,39 @@
From eb8cfe27aef67b30299aaf2a1ac538cf905135f2 Mon Sep 17 00:00:00 2001
From: Semih Baskan <strst.gs@gmail.com>
Date: Mon, 3 Aug 2026 07:08:11 +0300
Subject: [PATCH] usb: xhci: Handle USB3 port events when there is one roothub
handle_port_status() drops every USB3 port event when xhci->shared_hcd is
NULL. The check dates from a time when xhci-plat always created a shared
hcd, so a NULL one could only mean the hcd had been removed.
Since commit 4736ebd7fcaf ("usb: host: xhci-plat: omit shared hcd if
either root hub has no ports") that is no longer true. A controller whose
USB2 root hub has no ports gets a single roothub, the USB3 rhub is served
by the main hcd, and shared_hcd stays NULL for the lifetime of the device.
Every SuperSpeed port event is then thrown away as bogus behind a debug
message, so devices never enumerate even though the port reports them:
0x006a1203 Powered Connected Enabled Link:U0 PortSpeed:4
Broadcom Northstar is such a controller. USB3 works there up to 5.15 and
stops working from 5.19 onwards.
Ask xhci_get_usb3_hcd() instead. It returns the shared hcd when there is
one, the main hcd when the USB2 root hub has no ports, and NULL once the
shared hcd is gone, which keeps the original meaning of the check.
Fixes: 4736ebd7fcaf ("usb: host: xhci-plat: omit shared hcd if either root hub has no ports")
Signed-off-by: Semih Baskan <strst.gs@gmail.com>
---
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -2026,7 +2026,7 @@ static void handle_port_status(struct xh
vdev = xhci->devs[port->slot_id];
/* We might get interrupts after shared_hcd is removed */
- if (port->rhub == &xhci->usb3_rhub && xhci->shared_hcd == NULL) {
+ if (port->rhub == &xhci->usb3_rhub && xhci_get_usb3_hcd(xhci) == NULL) {
xhci_dbg(xhci, "ignore port event for removed USB3 hcd\n");
bogus_port_status = true;
goto cleanup;