On Tuesday, November 13, 2012 04:00:05 PM Lan Tianyu wrote: > Some usb devices can't be resumed correctly after power off. This > patch is to add pm qos flags request to change NO_POWER_OFF and > provide usb_device_allow_power_off() for device drivers to allow or > prohibit usb core to power off the device. > > Signed-off-by: Lan Tianyu <tianyu.lan@xxxxxxxxx> This looks reasonable to me. From the PM perspective: Acked-by: Rafael J. Wysocki <rafael.j.wysocki@xxxxxxxxx> > --- > drivers/usb/core/hub.c | 36 ++++++++++++++++++++++++++++++++++++ > drivers/usb/core/port.c | 12 ++++++++++++ > include/linux/usb.h | 3 +++ > 3 files changed, 51 insertions(+) > > diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c > index 267e9d7..7aaac720 100644 > --- a/drivers/usb/core/hub.c > +++ b/drivers/usb/core/hub.c > @@ -189,6 +189,42 @@ static struct usb_hub *hdev_to_hub(struct usb_device *hdev) > return usb_get_intfdata(hdev->actconfig->interface[0]); > } > > +/** > + * usb_device_allow_power_off - Allow or prohibit power off device. > + * @udev: target usb device > + * @set: choice of allow or prohibit > + * > + * Clearing or setting usb port's pm qos flag PM_QOS_FLAG_NO_POWER_OFF > + * to allow or prohibit target usb device to be power off. > + */ > +int usb_device_allow_power_off(struct usb_device *udev, bool set) > +{ > + struct usb_port *port_dev; > + struct dev_pm_qos_request *pm_qos; > + s32 value; > + int ret; > + > + if (!udev->parent) > + return -EINVAL; > + > + port_dev = > + hdev_to_hub(udev->parent)->ports[udev->portnum - 1]; > + pm_qos = &port_dev->pm_qos; > + value = pm_qos->data.flr.flags; > + > + if (set) > + value &= ~PM_QOS_FLAG_NO_POWER_OFF; > + else > + value |= PM_QOS_FLAG_NO_POWER_OFF; > + > + pm_runtime_get_sync(&port_dev->dev); > + ret = dev_pm_qos_update_request(pm_qos, value); > + pm_runtime_put(&port_dev->dev); > + > + return ret; > +} > +EXPORT_SYMBOL_GPL(usb_device_allow_power_off); > + > static int usb_device_supports_lpm(struct usb_device *udev) > { > /* USB 2.1 (and greater) devices indicate LPM support through > diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c > index 5a7a833..077a494 100644 > --- a/drivers/usb/core/port.c > +++ b/drivers/usb/core/port.c > @@ -49,6 +49,11 @@ static const struct attribute_group *port_dev_group[] = { > static void usb_port_device_release(struct device *dev) > { > struct usb_port *port_dev = to_usb_port(dev); > + > + pm_runtime_get_sync(dev); > + dev_pm_qos_remove_request(&port_dev->pm_qos); > + pm_runtime_put(dev); > + > dev_pm_qos_hide_flags(dev); > usb_acpi_unregister_power_resources(dev); > kfree(port_dev); > @@ -116,12 +121,19 @@ int usb_hub_create_port_device(struct device *intfdev, > if (retval) > goto error_expose_pm_qos; > > + retval = dev_pm_qos_add_request(&port_dev->dev, &port_dev->pm_qos, > + DEV_PM_QOS_FLAGS, 0); > + if (retval) > + goto error_add_qos_request; > + > pm_runtime_set_active(&port_dev->dev); > pm_runtime_enable(&port_dev->dev); > usb_acpi_register_power_resources(&port_dev->dev); > > return 0; > > +error_add_qos_request: > + pm_runtime_put(&port_dev->dev); > error_expose_pm_qos: > device_del(&port_dev->dev); > error_register: > diff --git a/include/linux/usb.h b/include/linux/usb.h > index 8002640..aa201bd 100644 > --- a/include/linux/usb.h > +++ b/include/linux/usb.h > @@ -21,6 +21,7 @@ > #include <linux/sched.h> /* for current && schedule_timeout */ > #include <linux/mutex.h> /* for struct mutex */ > #include <linux/pm_runtime.h> /* for runtime PM */ > +#include <linux/pm_qos.h> /* for PM Qos */ > > struct usb_device; > struct usb_driver; > @@ -577,6 +578,7 @@ struct usb_device { > * @child: usb device attatched to the port > * @dev: generic device interface > * @port_owner: port's owner > + * @pm_qos: port's pm qos flags request > * @connect_type: port's connect type > * @portnum: port index num based one > * @power_on: port's power state > @@ -585,6 +587,7 @@ struct usb_port { > struct usb_device *child; > struct device dev; > struct dev_state *port_owner; > + struct dev_pm_qos_request pm_qos; > enum usb_port_connect_type connect_type; > u8 portnum; > bool power_on; > -- I speak only for myself. Rafael J. Wysocki, Intel Open Source Technology Center. -- 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