When pm qos flags is changing, the pm core will keep device not in RPM_SUSPEND via pm_runtime_get_sync/put(dev). When the flags are changed, this will affect usb device status. If NO_POWER_OFF flag was set when the device was power off, it would need to be resumed and suspended again without power off. If NO_POWER_OFF flag was cleared when the device was suspended without power off, it would need to be resumed and suspended again with power off inorder to save more power. This patch is to add runtime pm callback for usb port device. In the callback, usb device attached to the port will be resumed and suspended. Signed-off-by: Lan Tianyu <tianyu.lan@xxxxxxxxx> --- drivers/usb/core/hub.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index f0e1b29..3ba6a96 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -1264,9 +1264,55 @@ static void usb_hub_remove_port_device(struct usb_hub *hub, device_unregister(&hub->ports[port1 - 1]->dev); } +static int usb_port_runtime_suspend(struct device *dev) +{ + struct usb_port *port_dev = to_usb_port(dev); + int ret; + + if (!port_dev->child) + return 0; + + ret = pm_runtime_suspend(&port_dev->child->dev); + if (ret == 1 || ret == 0 || ret == -EBUSY) + return 0; + else + return ret; +} + +static int usb_port_runtime_resume(struct device *dev) +{ + struct usb_port *port_dev = to_usb_port(dev); + int ret; + + if (!port_dev->child) + return 0; + + ret = pm_runtime_resume(&port_dev->child->dev); + if (ret == 1 || ret == 0) + return 0; + else + return ret; +} + +static int usb_port_runtime_idle(struct device *dev) +{ + struct usb_port *port_dev = to_usb_port(dev); + + return pm_runtime_suspend(&port_dev->dev); +} + +static const struct dev_pm_ops usb_port_pm_ops = { +#ifdef CONFIG_USB_SUSPEND +.runtime_suspend = usb_port_runtime_suspend, +.runtime_resume = usb_port_runtime_resume, +.runtime_idle = usb_port_runtime_idle, +#endif +}; + struct device_type usb_port_device_type = { .name = "usb_port", .release = usb_port_device_release, + .pm = &usb_port_pm_ops, }; static int usb_hub_create_port_device(struct usb_hub *hub, @@ -1291,6 +1337,8 @@ static int usb_hub_create_port_device(struct usb_hub *hub, if (retval) goto error_register; + pm_runtime_enable(&port_dev->dev); + retval = dev_pm_qos_expose_flags(&port_dev->dev, PM_QOS_FLAG_NO_POWER_OFF); if (retval) -- 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html