Re: [PATCH] PM: Do not create wakeup sysfs files for devices thatcannot wake up (v2)

From: Minchan Kim
Date: Sun Feb 06 2011 - 10:50:20 EST


On Sun, Feb 6, 2011 at 11:19 PM, Rafael J. Wysocki <rjw@xxxxxxx> wrote:
> Hi,
>
> Below is the next version of the patch changing the PM core to only create
> wakeup sysfs files for devices that are wakeup-capable. ÂIt contains a change
> in drivers/usb/core/hub.c that should avoid the problem described in the thread
> at https://lkml.org/lkml/2011/2/5/108 , but I'm not 100% it's the right
> approach. ÂPlease have a look.
>
> Thanks,
> Rafael
>
>
> ---
> From: Rafael J. Wysocki <rjw@xxxxxxx>
> Subject: PM: Don't create wakeup sysfs files for devices that can't wake up (v2)
>
> Currently, wakeup sysfs attributes are created for all devices,
> regardless of whether or not they are wakeup-capable. ÂThis is
> excessive and complicates wakeup device identification from user
> space (i.e. to identify wakeup-capable devices user space has to read
> /sys/devices/.../power/wakeup for all devices and see if they are not
> empty).
>
> Fix this issue by avoiding to create wakeup sysfs files for devices
> that cannot wake up the system from sleep states (i.e. whose
> power.can_wakeup flags are unset during registration) and modify
> device_set_wakeup_capable() so that it adds (or removes) the relevant
> sysfs attributes if a device's wakeup capability status is changed.
>
> Signed-off-by: Rafael J. Wysocki <rjw@xxxxxxx>
> ---
> ÂDocumentation/ABI/testing/sysfs-devices-power | Â 20 +++---
> ÂDocumentation/power/devices.txt        |  20 +++---
> Âdrivers/base/power/power.h          Â|  21 +++----
> Âdrivers/base/power/sysfs.c          Â|  78 +++++++++++++++++---------
> Âdrivers/base/power/wakeup.c          |  26 ++++++++
> Âdrivers/usb/core/hub.c            Â|  10 ++-
> Âinclude/linux/pm_runtime.h          Â|  Â6 ++
> Âinclude/linux/pm_wakeup.h           |  10 ---
> Â8 files changed, 121 insertions(+), 70 deletions(-)
>
> Index: linux-2.6/drivers/base/power/sysfs.c
> ===================================================================
> --- linux-2.6.orig/drivers/base/power/sysfs.c
> +++ linux-2.6/drivers/base/power/sysfs.c
> @@ -431,26 +431,18 @@ static ssize_t async_store(struct device
> Âstatic DEVICE_ATTR(async, 0644, async_show, async_store);
> Â#endif /* CONFIG_PM_ADVANCED_DEBUG */
>
> -static struct attribute * power_attrs[] = {
> - Â Â Â &dev_attr_wakeup.attr,
> -#ifdef CONFIG_PM_SLEEP
> - Â Â Â &dev_attr_wakeup_count.attr,
> - Â Â Â &dev_attr_wakeup_active_count.attr,
> - Â Â Â &dev_attr_wakeup_hit_count.attr,
> - Â Â Â &dev_attr_wakeup_active.attr,
> - Â Â Â &dev_attr_wakeup_total_time_ms.attr,
> - Â Â Â &dev_attr_wakeup_max_time_ms.attr,
> - Â Â Â &dev_attr_wakeup_last_time_ms.attr,
> -#endif
> +static struct attribute *power_attrs[] = {
> Â#ifdef CONFIG_PM_ADVANCED_DEBUG
> +#ifdef CONFIG_PM_SLEEP
> Â Â Â Â&dev_attr_async.attr,
> +#endif
> Â#ifdef CONFIG_PM_RUNTIME
> Â Â Â Â&dev_attr_runtime_status.attr,
> Â Â Â Â&dev_attr_runtime_usage.attr,
> Â Â Â Â&dev_attr_runtime_active_kids.attr,
> Â Â Â Â&dev_attr_runtime_enabled.attr,
> Â#endif
> -#endif
> +#endif /* CONFIG_PM_ADVANCED_DEBUG */
> Â Â Â ÂNULL,
> Â};
> Âstatic struct attribute_group pm_attr_group = {
> @@ -458,9 +450,26 @@ static struct attribute_group pm_attr_gr
> Â Â Â Â.attrs Â= power_attrs,
> Â};
>
> -#ifdef CONFIG_PM_RUNTIME
> +static struct attribute *wakeup_attrs[] = {
> +#ifdef CONFIG_PM_SLEEP
> + Â Â Â &dev_attr_wakeup.attr,
> + Â Â Â &dev_attr_wakeup_count.attr,
> + Â Â Â &dev_attr_wakeup_active_count.attr,
> + Â Â Â &dev_attr_wakeup_hit_count.attr,
> + Â Â Â &dev_attr_wakeup_active.attr,
> + Â Â Â &dev_attr_wakeup_total_time_ms.attr,
> + Â Â Â &dev_attr_wakeup_max_time_ms.attr,
> + Â Â Â &dev_attr_wakeup_last_time_ms.attr,
> +#endif
> + Â Â Â NULL,
> +};
> +static struct attribute_group pm_wakeup_attr_group = {
> +    .name  = power_group_name,
> + Â Â Â .attrs Â= wakeup_attrs,
> +};
>
> Âstatic struct attribute *runtime_attrs[] = {
> +#ifdef CONFIG_PM_RUNTIME
> Â#ifndef CONFIG_PM_ADVANCED_DEBUG
> Â Â Â Â&dev_attr_runtime_status.attr,
> Â#endif
> @@ -468,6 +477,7 @@ static struct attribute *runtime_attrs[]
> Â Â Â Â&dev_attr_runtime_suspended_time.attr,
> Â Â Â Â&dev_attr_runtime_active_time.attr,
> Â Â Â Â&dev_attr_autosuspend_delay_ms.attr,
> +#endif /* CONFIG_PM_RUNTIME */
> Â Â Â ÂNULL,
> Â};
> Âstatic struct attribute_group pm_runtime_attr_group = {
> @@ -480,35 +490,49 @@ int dpm_sysfs_add(struct device *dev)
> Â Â Â Âint rc;
>
> Â Â Â Ârc = sysfs_create_group(&dev->kobj, &pm_attr_group);
> - Â Â Â if (rc == 0 && !dev->power.no_callbacks) {
> + Â Â Â if (rc)
> + Â Â Â Â Â Â Â return rc;
> +
> + Â Â Â if (pm_runtime_callbacks_present(dev)) {
> Â Â Â Â Â Â Â Ârc = sysfs_merge_group(&dev->kobj, &pm_runtime_attr_group);
> Â Â Â Â Â Â Â Âif (rc)
> - Â Â Â Â Â Â Â Â Â Â Â sysfs_remove_group(&dev->kobj, &pm_attr_group);
> + Â Â Â Â Â Â Â Â Â Â Â goto err_out;
> + Â Â Â }
> +
> + Â Â Â if (device_can_wakeup(dev)) {
> + Â Â Â Â Â Â Â rc = sysfs_merge_group(&dev->kobj, &pm_wakeup_attr_group);
> + Â Â Â Â Â Â Â if (rc) {
> + Â Â Â Â Â Â Â Â Â Â Â if (pm_runtime_callbacks_present(dev))
> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â sysfs_unmerge_group(&dev->kobj,
> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â &pm_runtime_attr_group);
> + Â Â Â Â Â Â Â Â Â Â Â goto err_out;
> + Â Â Â Â Â Â Â }
> Â Â Â Â}
> + Â Â Â return 0;
> +
> + err_out:
> + Â Â Â sysfs_remove_group(&dev->kobj, &pm_attr_group);
> Â Â Â Âreturn rc;
> Â}
>
> -void rpm_sysfs_remove(struct device *dev)
> +int wakeup_sysfs_add(struct device *dev)
> Â{
> - Â Â Â sysfs_unmerge_group(&dev->kobj, &pm_runtime_attr_group);
> + Â Â Â return sysfs_merge_group(&dev->kobj, &pm_wakeup_attr_group);
> Â}
>
> -void dpm_sysfs_remove(struct device *dev)
> +void wakeup_sysfs_remove(struct device *dev)
> Â{
> - Â Â Â rpm_sysfs_remove(dev);
> - Â Â Â sysfs_remove_group(&dev->kobj, &pm_attr_group);
> + Â Â Â sysfs_unmerge_group(&dev->kobj, &pm_wakeup_attr_group);
> Â}
>
> -#else /* CONFIG_PM_RUNTIME */
> -
> -int dpm_sysfs_add(struct device * dev)
> +void rpm_sysfs_remove(struct device *dev)
> Â{
> - Â Â Â return sysfs_create_group(&dev->kobj, &pm_attr_group);
> + Â Â Â sysfs_unmerge_group(&dev->kobj, &pm_runtime_attr_group);
> Â}
>
> -void dpm_sysfs_remove(struct device * dev)
> +void dpm_sysfs_remove(struct device *dev)
> Â{
> + Â Â Â rpm_sysfs_remove(dev);
> + Â Â Â sysfs_unmerge_group(&dev->kobj, &pm_wakeup_attr_group);
> Â Â Â Âsysfs_remove_group(&dev->kobj, &pm_attr_group);
> Â}
> -
> -#endif
> Index: linux-2.6/include/linux/pm_runtime.h
> ===================================================================
> --- linux-2.6.orig/include/linux/pm_runtime.h
> +++ linux-2.6/include/linux/pm_runtime.h
> @@ -87,6 +87,11 @@ static inline bool pm_runtime_enabled(st
> Â Â Â Âreturn !dev->power.disable_depth;
> Â}
>
> +static inline bool pm_runtime_callbacks_present(struct device *dev)
> +{
> + Â Â Â return !dev->power.no_callbacks;
> +}
> +
> Âstatic inline void pm_runtime_mark_last_busy(struct device *dev)
> Â{
> Â Â Â ÂACCESS_ONCE(dev->power.last_busy) = jiffies;
> @@ -133,6 +138,7 @@ static inline int pm_generic_runtime_res
> Âstatic inline void pm_runtime_no_callbacks(struct device *dev) {}
> Âstatic inline void pm_runtime_irq_safe(struct device *dev) {}
>
> +static inline bool pm_runtime_callbacks_present(struct device *dev) { return false; }
> Âstatic inline void pm_runtime_mark_last_busy(struct device *dev) {}
> Âstatic inline void __pm_runtime_use_autosuspend(struct device *dev,
> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Âbool use) {}
> Index: linux-2.6/drivers/base/power/power.h
> ===================================================================
> --- linux-2.6.orig/drivers/base/power/power.h
> +++ linux-2.6/drivers/base/power/power.h
> @@ -58,19 +58,18 @@ static inline void device_pm_move_last(s
> Â* sysfs.c
> Â*/
>
> -extern int dpm_sysfs_add(struct device *);
> -extern void dpm_sysfs_remove(struct device *);
> -extern void rpm_sysfs_remove(struct device *);
> +extern int dpm_sysfs_add(struct device *dev);
> +extern void dpm_sysfs_remove(struct device *dev);
> +extern void rpm_sysfs_remove(struct device *dev);
> +extern int wakeup_sysfs_add(struct device *dev);
> +extern void wakeup_sysfs_remove(struct device *dev);
>
> Â#else /* CONFIG_PM */
>
> -static inline int dpm_sysfs_add(struct device *dev)
> -{
> - Â Â Â return 0;
> -}
> -
> -static inline void dpm_sysfs_remove(struct device *dev)
> -{
> -}
> +static inline int dpm_sysfs_add(struct device *dev) { return 0; }
> +static inline void dpm_sysfs_remove(struct device *dev) {}
> +static inline void rpm_sysfs_remove(struct device *dev) {}
> +static inline int wakeup_sysfs_add(struct device *dev) { return 0; }
> +static inline void wakeup_sysfs_remove(struct device *dev) {}
>
> Â#endif
> Index: linux-2.6/include/linux/pm_wakeup.h
> ===================================================================
> --- linux-2.6.orig/include/linux/pm_wakeup.h
> +++ linux-2.6/include/linux/pm_wakeup.h
> @@ -62,18 +62,11 @@ struct wakeup_source {
> Â* Changes to device_may_wakeup take effect on the next pm state change.
> Â*/
>
> -static inline void device_set_wakeup_capable(struct device *dev, bool capable)
> -{
> - Â Â Â dev->power.can_wakeup = capable;
> -}
> -
> Âstatic inline bool device_can_wakeup(struct device *dev)
> Â{
> Â Â Â Âreturn dev->power.can_wakeup;
> Â}
>
> -
> -
> Âstatic inline bool device_may_wakeup(struct device *dev)
> Â{
> Â Â Â Âreturn dev->power.can_wakeup && !!dev->power.wakeup;
> @@ -88,6 +81,7 @@ extern struct wakeup_source *wakeup_sour
> Âextern void wakeup_source_unregister(struct wakeup_source *ws);
> Âextern int device_wakeup_enable(struct device *dev);
> Âextern int device_wakeup_disable(struct device *dev);
> +extern void device_set_wakeup_capable(struct device *dev, bool capable);
> Âextern int device_init_wakeup(struct device *dev, bool val);
> Âextern int device_set_wakeup_enable(struct device *dev, bool enable);
> Âextern void __pm_stay_awake(struct wakeup_source *ws);
> @@ -144,7 +138,7 @@ static inline int device_wakeup_disable(
>
> Âstatic inline int device_init_wakeup(struct device *dev, bool val)
> Â{
> - Â Â Â dev->power.can_wakeup = val;
> + Â Â Â device_set_wakeup_capable(dev, val);
> Â Â Â Âreturn val ? -EINVAL : 0;
> Â}
>
> Index: linux-2.6/drivers/base/power/wakeup.c
> ===================================================================
> --- linux-2.6.orig/drivers/base/power/wakeup.c
> +++ linux-2.6/drivers/base/power/wakeup.c
> @@ -242,6 +242,32 @@ int device_wakeup_disable(struct device
> ÂEXPORT_SYMBOL_GPL(device_wakeup_disable);
>
> Â/**
> + * device_set_wakeup_capable - Set/reset device wakeup capability flag.
> + * @dev: Device to handle.
> + * @capable: Whether or not @dev is capable of waking up the system from sleep.
> + *
> + * If @capable is set, set the @dev's power.can_wakeup flag and add its
> + * wakeup-related attributes to sysfs. ÂOtherwise, unset the @dev's
> + * power.can_wakeup flag and remove its wakeup-related attributes from sysfs.
> + */
> +void device_set_wakeup_capable(struct device *dev, bool capable)
> +{
> + Â Â Â if (!!dev->power.can_wakeup == !!capable)
> + Â Â Â Â Â Â Â return;
> +
> + Â Â Â if (device_is_registered(dev)) {
> + Â Â Â Â Â Â Â if (capable) {
> + Â Â Â Â Â Â Â Â Â Â Â if (wakeup_sysfs_add(dev))
> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â return;
> + Â Â Â Â Â Â Â } else {
> + Â Â Â Â Â Â Â Â Â Â Â wakeup_sysfs_remove(dev);
> + Â Â Â Â Â Â Â }
> + Â Â Â }
> + Â Â Â dev->power.can_wakeup = capable;
> +}
> +EXPORT_SYMBOL_GPL(device_set_wakeup_capable);
> +
> +/**
> Â* device_init_wakeup - Device wakeup initialization.
> Â* @dev: Device to handle.
> Â* @enable: Whether or not to enable @dev as a wakeup device.
> Index: linux-2.6/Documentation/power/devices.txt
> ===================================================================
> --- linux-2.6.orig/Documentation/power/devices.txt
> +++ linux-2.6/Documentation/power/devices.txt
> @@ -159,18 +159,18 @@ matter, and the kernel is responsible fo
> Âwhether or not a wakeup-capable device should issue wakeup events is a policy
> Âdecision, and it is managed by user space through a sysfs attribute: the
> Âpower/wakeup file. ÂUser space can write the strings "enabled" or "disabled" to
> -set or clear the should_wakeup flag, respectively. ÂReads from the file will
> -return the corresponding string if can_wakeup is true, but if can_wakeup is
> -false then reads will return an empty string, to indicate that the device
> -doesn't support wakeup events. Â(But even though the file appears empty, writes
> -will still affect the should_wakeup flag.)
> +set or clear the "should_wakeup" flag, respectively. ÂThis file is only present
> +for wakeup-capable devices (i.e. devices whose "can_wakeup" flags are set)
> +and is created (or removed) by device_set_wakeup_capable(). ÂReads from the
> +file will return the corresponding string.
>
> ÂThe device_may_wakeup() routine returns true only if both flags are set.
> -Drivers should check this routine when putting devices in a low-power state
> -during a system sleep transition, to see whether or not to enable the devices'
> -wakeup mechanisms. ÂHowever for runtime power management, wakeup events should
> -be enabled whenever the device and driver both support them, regardless of the
> -should_wakeup flag.
> +This information is used by subsystems, like the PCI bus type code, to see
> +whether or not to enable the devices' wakeup mechanisms. ÂIf device wakeup
> +mechanisms are enabled or disabled directly by drivers, they also should use
> +device_may_wakeup() to decide what to do during a system sleep transition.
> +However for runtime power management, wakeup events should be enabled whenever
> +the device and driver both support them, regardless of the should_wakeup flag.
>
>
> Â/sys/devices/.../power/control files
> Index: linux-2.6/Documentation/ABI/testing/sysfs-devices-power
> ===================================================================
> --- linux-2.6.orig/Documentation/ABI/testing/sysfs-devices-power
> +++ linux-2.6/Documentation/ABI/testing/sysfs-devices-power
> @@ -29,9 +29,8 @@ Description:
> Â Â Â Â Â Â Â Â"disabled" to it.
>
> Â Â Â Â Â Â Â ÂFor the devices that are not capable of generating system wakeup
> - Â Â Â Â Â Â Â events this file contains "\n". ÂIn that cases the user space
> - Â Â Â Â Â Â Â cannot modify the contents of this file and the device cannot be
> - Â Â Â Â Â Â Â enabled to wake up the system.
> + Â Â Â Â Â Â Â events this file is not present. ÂIn that case the device cannot
> + Â Â Â Â Â Â Â be enabled to wake up the system from sleep states.
>
> ÂWhat: Â Â Â Â Â/sys/devices/.../power/control
> ÂDate: Â Â Â Â ÂJanuary 2009
> @@ -85,7 +84,7 @@ Description:
> Â Â Â Â Â Â Â ÂThe /sys/devices/.../wakeup_count attribute contains the number
> Â Â Â Â Â Â Â Âof signaled wakeup events associated with the device. ÂThis
> Â Â Â Â Â Â Â Âattribute is read-only. ÂIf the device is not enabled to wake up
> - Â Â Â Â Â Â Â the system from sleep states, this attribute is empty.
> + Â Â Â Â Â Â Â the system from sleep states, this attribute is not present.
>
> ÂWhat: Â Â Â Â Â/sys/devices/.../power/wakeup_active_count
> ÂDate: Â Â Â Â ÂSeptember 2010
> @@ -95,7 +94,7 @@ Description:
> Â Â Â Â Â Â Â Ânumber of times the processing of wakeup events associated with
> Â Â Â Â Â Â Â Âthe device was completed (at the kernel level). ÂThis attribute
> Â Â Â Â Â Â Â Âis read-only. ÂIf the device is not enabled to wake up the
> - Â Â Â Â Â Â Â system from sleep states, this attribute is empty.
> + Â Â Â Â Â Â Â system from sleep states, this attribute is not present.
>
> ÂWhat: Â Â Â Â Â/sys/devices/.../power/wakeup_hit_count
> ÂDate: Â Â Â Â ÂSeptember 2010
> @@ -105,7 +104,8 @@ Description:
> Â Â Â Â Â Â Â Ânumber of times the processing of a wakeup event associated with
> Â Â Â Â Â Â Â Âthe device might prevent the system from entering a sleep state.
> Â Â Â Â Â Â Â ÂThis attribute is read-only. ÂIf the device is not enabled to
> - Â Â Â Â Â Â Â wake up the system from sleep states, this attribute is empty.
> + Â Â Â Â Â Â Â wake up the system from sleep states, this attribute is not
> + Â Â Â Â Â Â Â present.
>
> ÂWhat: Â Â Â Â Â/sys/devices/.../power/wakeup_active
> ÂDate: Â Â Â Â ÂSeptember 2010
> @@ -115,7 +115,7 @@ Description:
> Â Â Â Â Â Â Â Âor 0, depending on whether or not a wakeup event associated with
> Â Â Â Â Â Â Â Âthe device is being processed (1). ÂThis attribute is read-only.
> Â Â Â Â Â Â Â ÂIf the device is not enabled to wake up the system from sleep
> - Â Â Â Â Â Â Â states, this attribute is empty.
> + Â Â Â Â Â Â Â states, this attribute is not present.
>
> ÂWhat: Â Â Â Â Â/sys/devices/.../power/wakeup_total_time_ms
> ÂDate: Â Â Â Â ÂSeptember 2010
> @@ -125,7 +125,7 @@ Description:
> Â Â Â Â Â Â Â Âthe total time of processing wakeup events associated with the
> Â Â Â Â Â Â Â Âdevice, in milliseconds. ÂThis attribute is read-only. ÂIf the
> Â Â Â Â Â Â Â Âdevice is not enabled to wake up the system from sleep states,
> - Â Â Â Â Â Â Â this attribute is empty.
> + Â Â Â Â Â Â Â this attribute is not present.
>
> ÂWhat: Â Â Â Â Â/sys/devices/.../power/wakeup_max_time_ms
> ÂDate: Â Â Â Â ÂSeptember 2010
> @@ -135,7 +135,7 @@ Description:
> Â Â Â Â Â Â Â Âthe maximum time of processing a single wakeup event associated
> Â Â Â Â Â Â Â Âwith the device, in milliseconds. ÂThis attribute is read-only.
> Â Â Â Â Â Â Â ÂIf the device is not enabled to wake up the system from sleep
> - Â Â Â Â Â Â Â states, this attribute is empty.
> + Â Â Â Â Â Â Â states, this attribute is not present.
>
> ÂWhat: Â Â Â Â Â/sys/devices/.../power/wakeup_last_time_ms
> ÂDate: Â Â Â Â ÂSeptember 2010
> @@ -146,7 +146,7 @@ Description:
> Â Â Â Â Â Â Â Âsignaling the last wakeup event associated with the device, in
> Â Â Â Â Â Â Â Âmilliseconds. ÂThis attribute is read-only. ÂIf the device is
> Â Â Â Â Â Â Â Ânot enabled to wake up the system from sleep states, this
> - Â Â Â Â Â Â Â attribute is empty.
> + Â Â Â Â Â Â Â attribute is not present.
>
> ÂWhat: Â Â Â Â Â/sys/devices/.../power/autosuspend_delay_ms
> ÂDate: Â Â Â Â ÂSeptember 2010
> Index: linux-2.6/drivers/usb/core/hub.c
> ===================================================================
> --- linux-2.6.orig/drivers/usb/core/hub.c
> +++ linux-2.6/drivers/usb/core/hub.c
> @@ -1465,6 +1465,7 @@ void usb_set_device_state(struct usb_dev
> Â Â Â Â Â Â Â Âenum usb_device_state new_state)
> Â{
> Â Â Â Âunsigned long flags;
> + Â Â Â int wakeup = -1;
>
> Â Â Â Âspin_lock_irqsave(&device_state_lock, flags);
> Â Â Â Âif (udev->state == USB_STATE_NOTATTACHED)
> @@ -1479,11 +1480,10 @@ void usb_set_device_state(struct usb_dev
> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â|| new_state == USB_STATE_SUSPENDED)
> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â; Â Â Â /* No change to wakeup settings */
> Â Â Â Â Â Â Â Â Â Â Â Âelse if (new_state == USB_STATE_CONFIGURED)
> - Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â device_set_wakeup_capable(&udev->dev,
> - Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â (udev->actconfig->desc.bmAttributes
> - Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â& USB_CONFIG_ATT_WAKEUP));
> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â wakeup = udev->actconfig->desc.bmAttributes
> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â& USB_CONFIG_ATT_WAKEUP;
> Â Â Â Â Â Â Â Â Â Â Â Âelse
> - Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â device_set_wakeup_capable(&udev->dev, 0);
> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â wakeup = 0;
> Â Â Â Â Â Â Â Â}
> Â Â Â Â Â Â Â Âif (udev->state == USB_STATE_SUSPENDED &&
> Â Â Â Â Â Â Â Â Â Â Â Ânew_state != USB_STATE_SUSPENDED)
> @@ -1495,6 +1495,8 @@ void usb_set_device_state(struct usb_dev
> Â Â Â Â} else
> Â Â Â Â Â Â Â Ârecursively_mark_NOTATTACHED(udev);
> Â Â Â Âspin_unlock_irqrestore(&device_state_lock, flags);
> + Â Â Â if (wakeup >= 0)
> + Â Â Â Â Â Â Â device_set_wakeup_capable(&udev->dev, wakeup);
> Â}
> ÂEXPORT_SYMBOL_GPL(usb_set_device_state);
>
>

I can't say the work of usb since I am not a expert about that.
Anyway, the patch works well in my machine.
Just a nitpick.

Please, add a kind comment for new exported device_set_wakeup_capable
to show the function should be called by process context.

Feel free to use below signs.

Reported-by: Minchan Kim <minchan.kim@xxxxxxxxx>
Tested-by: Minchan Kim <minchan.kim@xxxxxxxxx>


--
Kind regards,
Minchan Kim
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/