Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

usb: acpi: add device link between tunneled USB3 device and USB4 Host Interface

Describe the power management relationship between a tunneled USB3 device
and the tunnel providing USB4 host with a device link as the relationship
between them is not evident from normal device hierarchy.

Tunneling capable ports have an ACPI _DSD object pointing to the USB4
Host Interface that is used to establish USB3 3.x tunnels

Set the link directly between tunneled USB3 devices and USB4 Host
Interface to ensure that the USB4 host can runtime suspend if no tunneled
USB 3.x devices exist.
Current Thunderbolt code sets a link between USB4 Host Interface and USB3
xHCI host which prevents USB4 Host Interface from runtime suspending even
if the USB3 host is only serving native USB devices.

See commit b2be2b05cf3b ("thunderbolt: Create device links from ACPI
description") for details.

As the device link is only set for USB3 devices that are already tunneled
we know that USB4 Host Interface exists and is bound to its driver.

Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
Link: https://lore.kernel.org/r/20240830152630.3943215-4-mathias.nyman@linux.intel.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Mathias Nyman and committed by
Greg Kroah-Hartman
f1bfb4a6 f46a6e16

+53
+53
drivers/usb/core/usb-acpi.c
··· 142 142 } 143 143 EXPORT_SYMBOL_GPL(usb_acpi_set_power_state); 144 144 145 + /** 146 + * usb_acpi_add_usb4_devlink - add device link to USB4 Host Interface for tunneled USB3 devices 147 + * 148 + * @udev: Tunneled USB3 device connected to a roothub. 149 + * 150 + * Adds a device link between a tunneled USB3 device and the USB4 Host Interface 151 + * device to ensure correct runtime PM suspend and resume order. This function 152 + * should only be called for tunneled USB3 devices. 153 + * The USB4 Host Interface this tunneled device depends on is found from the roothub 154 + * port ACPI device specific data _DSD entry. 155 + * 156 + * Return: negative error code on failure, 0 otherwise 157 + */ 158 + static int usb_acpi_add_usb4_devlink(struct usb_device *udev) 159 + { 160 + const struct device_link *link; 161 + struct usb_port *port_dev; 162 + struct usb_hub *hub; 163 + 164 + if (!udev->parent || udev->parent->parent) 165 + return 0; 166 + 167 + hub = usb_hub_to_struct_hub(udev->parent); 168 + port_dev = hub->ports[udev->portnum - 1]; 169 + 170 + struct fwnode_handle *nhi_fwnode __free(fwnode_handle) = 171 + fwnode_find_reference(dev_fwnode(&port_dev->dev), "usb4-host-interface", 0); 172 + 173 + if (IS_ERR(nhi_fwnode)) 174 + return 0; 175 + 176 + link = device_link_add(&port_dev->child->dev, nhi_fwnode->dev, 177 + DL_FLAG_AUTOREMOVE_CONSUMER | 178 + DL_FLAG_RPM_ACTIVE | 179 + DL_FLAG_PM_RUNTIME); 180 + if (!link) { 181 + dev_err(&port_dev->dev, "Failed to created device link from %s to %s\n", 182 + dev_name(&port_dev->child->dev), dev_name(nhi_fwnode->dev)); 183 + return -EINVAL; 184 + } 185 + 186 + dev_dbg(&port_dev->dev, "Created device link from %s to %s\n", 187 + dev_name(&port_dev->child->dev), dev_name(nhi_fwnode->dev)); 188 + 189 + return 0; 190 + } 191 + 145 192 /* 146 193 * Private to usb-acpi, all the core needs to know is that 147 194 * port_dev->location is non-zero when it has been set by the firmware. ··· 308 261 hub = usb_hub_to_struct_hub(udev->parent); 309 262 if (!hub) 310 263 return NULL; 264 + 265 + 266 + /* Tunneled USB3 devices depend on USB4 Host Interface, set device link to it */ 267 + if (udev->speed >= USB_SPEED_SUPER && 268 + udev->tunnel_mode != USB_LINK_NATIVE) 269 + usb_acpi_add_usb4_devlink(udev); 311 270 312 271 /* 313 272 * This is an embedded USB device connected to a port and such