diff options
-rw-r--r-- | drivers/base/power/main.c | 16 | ||||
-rw-r--r-- | drivers/base/power/runtime.c | 9 | ||||
-rw-r--r-- | include/linux/pm_runtime.h | 4 |
3 files changed, 18 insertions, 11 deletions
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index cc9903065900..a06ef91fbdb9 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -1796,16 +1796,14 @@ static void device_prepare_smart_suspend(struct device *dev) /* * The "smart suspend" feature is enabled for devices whose drivers ask - * for it and for devices without PM callbacks unless runtime PM is - * disabled and enabling it is blocked for them. + * for it and for devices without PM callbacks. * * However, if "smart suspend" is not enabled for the device's parent * or any of its suppliers that take runtime PM into account, it cannot * be enabled for the device either. */ - dev->power.smart_suspend = (dev->power.no_pm_callbacks || - dev_pm_test_driver_flags(dev, DPM_FLAG_SMART_SUSPEND)) && - !pm_runtime_blocked(dev); + dev->power.smart_suspend = dev->power.no_pm_callbacks || + dev_pm_test_driver_flags(dev, DPM_FLAG_SMART_SUSPEND); if (!dev_pm_smart_suspend(dev)) return; @@ -1843,6 +1841,7 @@ static void device_prepare_smart_suspend(struct device *dev) static int device_prepare(struct device *dev, pm_message_t state) { int (*callback)(struct device *) = NULL; + bool no_runtime_pm; int ret = 0; /* @@ -1858,7 +1857,7 @@ static int device_prepare(struct device *dev, pm_message_t state) * suspend-resume cycle is complete, so prepare to trigger a warning on * subsequent attempts to enable it. */ - pm_runtime_block_if_disabled(dev); + no_runtime_pm = pm_runtime_block_if_disabled(dev); if (dev->power.syscore) return 0; @@ -1893,7 +1892,10 @@ unlock: pm_runtime_put(dev); return ret; } - device_prepare_smart_suspend(dev); + /* Do not enable "smart suspend" for devices without runtime PM. */ + if (!no_runtime_pm) + device_prepare_smart_suspend(dev); + /* * A positive return value from ->prepare() means "this device appears * to be runtime-suspended and its state is fine, so if it really is diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c index c0f5a9f89299..e772e45d30f3 100644 --- a/drivers/base/power/runtime.c +++ b/drivers/base/power/runtime.c @@ -1460,14 +1460,19 @@ int pm_runtime_barrier(struct device *dev) } EXPORT_SYMBOL_GPL(pm_runtime_barrier); -void pm_runtime_block_if_disabled(struct device *dev) +bool pm_runtime_block_if_disabled(struct device *dev) { + bool ret; + spin_lock_irq(&dev->power.lock); - if (dev->power.disable_depth && dev->power.last_status == RPM_INVALID) + ret = dev->power.disable_depth && dev->power.last_status == RPM_INVALID; + if (ret) dev->power.last_status = RPM_BLOCKED; spin_unlock_irq(&dev->power.lock); + + return ret; } void pm_runtime_unblock(struct device *dev) diff --git a/include/linux/pm_runtime.h b/include/linux/pm_runtime.h index aea0395c10a1..01ead602aedd 100644 --- a/include/linux/pm_runtime.h +++ b/include/linux/pm_runtime.h @@ -77,7 +77,7 @@ extern int pm_runtime_get_if_in_use(struct device *dev); extern int pm_schedule_suspend(struct device *dev, unsigned int delay); extern int __pm_runtime_set_status(struct device *dev, unsigned int status); extern int pm_runtime_barrier(struct device *dev); -extern void pm_runtime_block_if_disabled(struct device *dev); +extern bool pm_runtime_block_if_disabled(struct device *dev); extern void pm_runtime_unblock(struct device *dev); extern void pm_runtime_enable(struct device *dev); extern void __pm_runtime_disable(struct device *dev, bool check_resume); @@ -274,7 +274,7 @@ static inline int pm_runtime_get_if_active(struct device *dev) static inline int __pm_runtime_set_status(struct device *dev, unsigned int status) { return 0; } static inline int pm_runtime_barrier(struct device *dev) { return 0; } -static inline void pm_runtime_block_if_disabled(struct device *dev) {} +static inline bool pm_runtime_block_if_disabled(struct device *dev) { return true; } static inline void pm_runtime_unblock(struct device *dev) {} static inline void pm_runtime_enable(struct device *dev) {} static inline void __pm_runtime_disable(struct device *dev, bool c) {} |