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....@intel.com>

This looks reasonable to me.  From the PM perspective:

Acked-by: Rafael J. Wysocki <rafael.j.wyso...@intel.com>

> ---
>  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 majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to