From: Sean Rhodes Date: Sun, 15 Mar 2026 22:34:33 +0000 (+0000) Subject: usb: core: allow ACPI-managed hard-wired ports to power off X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=8020c41b39f514941d93f3322b598afdce487064;p=thirdparty%2Fkernel%2Flinux.git usb: core: allow ACPI-managed hard-wired ports to power off USB core only relaxes the default PM_QOS_FLAG_NO_POWER_OFF policy when an upstream hub reports switchable port power. That misses internal ports whose power is managed by platform firmware instead of the USB hub descriptor. Allow the port-poweroff policy to be exposed for hard-wired ports with an ACPI-managed power resource. The existing runtime PM path still requires the child usage count to drop and remote wakeup to be clear before it will power the port down. This lets internal devices such as CNVi Bluetooth use the existing USB ACPI runtime power path even when the root hub reports no USB-standard port power switching. Signed-off-by: Sean Rhodes Link: https://patch.msgid.link/20260315223433.23452-1-sean@starlabs.systems Signed-off-by: Greg Kroah-Hartman --- diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c index 44e38f922bc5..b6cdea7e9521 100644 --- a/drivers/usb/core/port.c +++ b/drivers/usb/core/port.c @@ -21,6 +21,20 @@ static int usb_port_block_power_off; static const struct attribute_group *port_dev_group[]; +static bool usb_port_allow_power_off(struct usb_device *hdev, + struct usb_hub *hub, + struct usb_port *port_dev) +{ + if (hub_is_port_power_switchable(hub)) + return true; + + if (!IS_ENABLED(CONFIG_ACPI)) + return false; + + return port_dev->connect_type == USB_PORT_CONNECT_TYPE_HARD_WIRED && + usb_acpi_power_manageable(hdev, port_dev->portnum - 1); +} + static ssize_t early_stop_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -805,10 +819,10 @@ int usb_hub_create_port_device(struct usb_hub *hub, int port1) device_enable_async_suspend(&port_dev->dev); /* - * Keep hidden the ability to enable port-poweroff if the hub - * does not support power switching. + * Keep hidden the ability to enable port-poweroff if neither the + * USB hub nor platform firmware can manage downstream port power. */ - if (!hub_is_port_power_switchable(hub)) + if (!usb_port_allow_power_off(hdev, hub, port_dev)) return 0; /* Attempt to let userspace take over the policy. */