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)
{
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. */