Neither bootm nor EFI ExitBootServices() stops USB controllers
explicitly. Both only remove devices whose driver sets
DM_FLAG_ACTIVE_DMA or DM_FLAG_OS_PREPARE. xhci-dwc3 sets neither, so a
controller brought up by "usb start", e.g. from preboot for a USB
keyboard, is handed to the OS still running.

Set DM_FLAG_OS_PREPARE so that xhci_dwc3_remove() runs at handoff. This
is the path "usb stop" already takes: the xHCI is reset, its PHYs are
shut down and its clocks and resets are released. Child devices such as
hubs, storage and keyboards are removed first, and a controller already
stopped by "usb stop" is skipped. xhci-pci has done the same since
commit e3bbc1f74e05 ("usb: xhci-pci: Add DM_FLAG_OS_PREPARE flag"), as
have ohci-da8xx and the cdns3 wrappers.

On Apple silicon machines the running controller is user visible: Linux
does not enumerate a USB device attached to a Type-C port at boot until
it is unplugged and plugged back in.

Link: https://github.com/AsahiLinux/linux/issues/554
Signed-off-by: Romain Beauxis <[email protected]>
---
Tested on an M1 Mac mini running Fedora Asahi Remix with Linux 7.1.13,
booting through EFI and GRUB, with a Samsung T7 USB 3 SSD attached to a
Type-C port. U-Boot is v2026.07 plus the Asahi downstream patches.

  U-Boot                                SSD enumerated by Linux
  stock                                 only after a replug, at 83s
  stock, bootcmd "usb stop; <default>"  10.1s, no replug
  stock plus this patch                 10.2s, no replug

In the stock boot, the replug made Linux tear down and re-create the
Type-C xHCI instance, and the SSD appeared right after. In all three
boots a disk on the USB-A ports, which sit behind xhci-pci on the same
machine, enumerated at 6s. The linked issue reports the same failure on
M1 and M2 MacBook Airs with Linux 7.0 and 7.1.

Only the EFI handoff was tested. bootm reaches the same
dm_remove_devices_active() call. No non-Apple xhci-dwc3 board was
tested.

 drivers/usb/host/xhci-dwc3.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/usb/host/xhci-dwc3.c b/drivers/usb/host/xhci-dwc3.c
index 3504a7cf4..92b311d42 100644
--- a/drivers/usb/host/xhci-dwc3.c
+++ b/drivers/usb/host/xhci-dwc3.c
@@ -256,6 +256,6 @@ U_BOOT_DRIVER(xhci_dwc3) = {
        .ops = &xhci_usb_ops,
        .priv_auto      = sizeof(struct xhci_ctrl),
        .plat_auto      = sizeof(struct xhci_dwc3_plat),
-       .flags = DM_FLAG_ALLOC_PRIV_DMA,
+       .flags = DM_FLAG_OS_PREPARE | DM_FLAG_ALLOC_PRIV_DMA,
 };
 #endif
-- 
2.55.0

Reply via email to