===================================================================
@@ -918,7 +918,7 @@ static int device_suspend_noirq(struct d
pm_callback_t callback = NULL;
char *info = NULL;
- if (dev->power.syscore)
+ if (dev->power.syscore || dev->power.no_suspend)
return 0;
if (dev->pm_domain) {
@@ -1006,7 +1006,7 @@ static int device_suspend_late(struct de
__pm_runtime_disable(dev, false);
- if (dev->power.syscore)
+ if (dev->power.syscore || dev->power.no_suspend)
return 0;
if (dev->pm_domain) {
@@ -1143,8 +1143,10 @@ static int __device_suspend(struct devic
* for it, this is equivalent to the device signaling wakeup, so the
* system suspend operation should be aborted.
*/
- if (pm_runtime_barrier(dev) && device_may_wakeup(dev))
+ if (pm_runtime_barrier(dev) && device_may_wakeup(dev)) {
pm_wakeup_event(dev, 0);
+ dev->power.no_suspend = false;
+ }
if (pm_wakeup_pending()) {
async_error = -EBUSY;
@@ -1157,6 +1159,9 @@ static int __device_suspend(struct devic
dpm_watchdog_set(&wd, dev);
device_lock(dev);
+ if (dev->power.no_suspend)
+ goto End;
+
if (dev->pm_domain) {
info = "power domain ";
callback = pm_op(&dev->pm_domain->ops, state);
@@ -1205,9 +1210,13 @@ static int __device_suspend(struct devic
End:
if (!error) {
dev->power.is_suspended = true;
- if (dev->power.wakeup_path
- && dev->parent && !dev->parent->power.ignore_children)
- dev->parent->power.wakeup_path = true;
+ if (dev->parent && !dev->parent->power.ignore_children) {
+ if (dev->power.wakeup_path)
+ dev->parent->power.wakeup_path = true;
+
+ if (!dev->power.no_suspend)
+ dev->parent->power.no_suspend = false;
+ }
}
device_unlock(dev);
@@ -1307,7 +1316,7 @@ static int device_prepare(struct device
{
int (*callback)(struct device *) = NULL;
char *info = NULL;
- int error = 0;
+ int ret = 0;
if (dev->power.syscore)
return 0;
@@ -1323,6 +1332,7 @@ static int device_prepare(struct device
device_lock(dev);
dev->power.wakeup_path = device_may_wakeup(dev);
+ dev->power.no_suspend = false;
if (dev->pm_domain) {
info = "preparing power domain ";
@@ -1344,16 +1354,20 @@ static int device_prepare(struct device
}
if (callback) {
- error = callback(dev);
- suspend_report_result(callback, error);
+ ret = callback(dev);
+ suspend_report_result(callback, ret);
}
device_unlock(dev);
- if (error)
+ if (ret < 0) {
pm_runtime_put(dev);
+ } else if (ret > 0) {
+ dev->power.no_suspend = true;
+ ret = 0;
+ }
- return error;
+ return ret;
}
/**
@@ -1422,7 +1436,7 @@ EXPORT_SYMBOL_GPL(dpm_suspend_start);
void __suspend_report_result(const char *function, void *fn, int ret)
{
- if (ret)
+ if (ret < 0)
printk(KERN_ERR "%s(): %pF returns %d\n", function, fn, ret);
}
EXPORT_SYMBOL_GPL(__suspend_report_result);
===================================================================
@@ -544,6 +544,7 @@ struct dev_pm_info {
bool is_suspended:1; /* Ditto */
bool ignore_children:1;
bool early_init:1; /* Owned by the PM core */
+ bool no_suspend:1;
spinlock_t lock;
#ifdef CONFIG_PM_SLEEP
struct list_head entry;