Skip to contentSkip to conversation

usb: acpi: fix boot hang due to early incorrect 'tunneled' USB3 device links

PATCH In review Mathias Nyman 3 participants 3 messages Oct 24, 2024 USB

lore
Share & tools
lore
#0 lore raw

PATCH v2 1/1 usb: acpi: fix boot hang due to early incorrect 'tunneled' USB3 device links

Fix a boot hang issue triggered when a USB3 device is incorrectly assumed to be tunneled over USB4, thus attempting to create a device link between the USB3 "consumer" device and the USB4 "supplier" Host Interface before the USB4 side is properly bound to a driver.

This could happen if xhci isn't capable of detecting tunneled devices, but ACPI tables contain all info needed to assume device is tunneled. i.e. udev->tunnel_mode == USB_LINK_UNKNOWN.

It turns out that even for actual tunneled USB3 devices it can't be assumed that the thunderbolt driver providing the tunnel is loaded before the tunneled USB3 device is created.
The tunnel can be created by BIOS and remain in use by thunderbolt/USB4 host driver once it loads.

Solve this by making the device link "stateless", which doesn't create a driver presence order dependency between the supplier and consumer drivers.
It still guarantees correct suspend/resume and shutdown ordering.

cc Mario Limonciello <[email protected]>
Fixes f1bfb4a6fed6 ("usb: acpi: add device link between tunneled USB3 device and USB4 Host Interface")

---
v2: Use stateless device link instead of checking if driver is bound

 drivers/usb/core/usb-acpi.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/usb/core/usb-acpi.c +2 -2
index 21585ed89ef8..03c22114214b 100644
@@ -170,11 +170,11 @@ static int usb_acpi_add_usb4_devlink(struct usb_device *udev)
 	struct fwnode_handle *nhi_fwnode __free(fwnode_handle) =
 		fwnode_find_reference(dev_fwnode(&port_dev->dev), "usb4-host-interface", 0);
 
-	if (IS_ERR(nhi_fwnode))
+	if (IS_ERR(nhi_fwnode) || !nhi_fwnode->dev)
 		return 0;
 
 	link = device_link_add(&port_dev->child->dev, nhi_fwnode->dev,
-			       DL_FLAG_AUTOREMOVE_CONSUMER |
+			       DL_FLAG_STATELESS |
 			       DL_FLAG_RPM_ACTIVE |
 			       DL_FLAG_PM_RUNTIME);
 	if (!link) {
Signature · 1 line
2.25.1
Tested-by on v2 1/1
#1 lore raw
Quoted 15 lines · Mathias Nyman

Fix a boot hang issue triggered when a USB3 device is incorrectly assumed to be tunneled over USB4, thus attempting to create a device link between the USB3 "consumer" device and the USB4 "supplier" Host Interface before the USB4 side is properly bound to a driver.

This could happen if xhci isn't capable of detecting tunneled devices, but ACPI tables contain all info needed to assume device is tunneled. i.e. udev->tunnel_mode == USB_LINK_UNKNOWN.

It turns out that even for actual tunneled USB3 devices it can't be assumed that the thunderbolt driver providing the tunnel is loaded before the tunneled USB3 device is created.
The tunnel can be created by BIOS and remain in use by thunderbolt/USB4 host driver once it loads.

Quoted 8 lines

Solve this by making the device link "stateless", which doesn't create a driver presence order dependency between the supplier and consumer drivers.
It still guarantees correct suspend/resume and shutdown ordering.

cc Mario Limonciello <[email protected]>
Fixes f1bfb4a6fed6 ("usb: acpi: add device link between tunneled USB3 device and USB4 Host Interface")
Quoted 25 lines

---
v2: Use stateless device link instead of checking if driver is bound

  drivers/usb/core/usb-acpi.c | 4 ++--
  1 file changed, 2 insertions(+), 2 deletions(-)
drivers/usb/core/usb-acpi.c +2 -2
index 21585ed89ef8..03c22114214b 100644
@@ -170,11 +170,11 @@ static int usb_acpi_add_usb4_devlink(struct usb_device *udev)
  	struct fwnode_handle *nhi_fwnode __free(fwnode_handle) =
  		fwnode_find_reference(dev_fwnode(&port_dev->dev), "usb4-host-interface", 0);
 
-	if (IS_ERR(nhi_fwnode))
+	if (IS_ERR(nhi_fwnode) || !nhi_fwnode->dev)
  		return 0;
 
  	link = device_link_add(&port_dev->child->dev, nhi_fwnode->dev,
-			       DL_FLAG_AUTOREMOVE_CONSUMER |
+			       DL_FLAG_STATELESS |
  			       DL_FLAG_RPM_ACTIVE |
  			       DL_FLAG_PM_RUNTIME);
  	if (!link) {
Reviewed-by on v2 1/1
#2 lore raw
In reply to Mathias Nyman
Quoted 20 lines · Mathias Nyman

Fix a boot hang issue triggered when a USB3 device is incorrectly assumed to be tunneled over USB4, thus attempting to create a device link between the USB3 "consumer" device and the USB4 "supplier" Host Interface before the USB4 side is properly bound to a driver.

This could happen if xhci isn't capable of detecting tunneled devices, but ACPI tables contain all info needed to assume device is tunneled. i.e. udev->tunnel_mode == USB_LINK_UNKNOWN.

It turns out that even for actual tunneled USB3 devices it can't be assumed that the thunderbolt driver providing the tunnel is loaded before the tunneled USB3 device is created.
The tunnel can be created by BIOS and remain in use by thunderbolt/USB4 host driver once it loads.

Solve this by making the device link "stateless", which doesn't create a driver presence order dependency between the supplier and consumer drivers.
It still guarantees correct suspend/resume and shutdown ordering.

Quoted 4 lines
cc Mario Limonciello <[email protected]>
Fixes f1bfb4a6fed6 ("usb: acpi: add device link between tunneled USB3 device and USB4 Host Interface")