Commit 057d51a1 authored by Rafael J. Wysocki's avatar Rafael J. Wysocki

Merge branch 'pm-sleep'

* pm-sleep:
  PM: Prevent runtime suspend during system resume
  PM / Sleep: use resume event when call dpm_resume_early

Conflicts:
	drivers/base/power/main.c (trivial)
parents 071f5827 88d26136
...@@ -570,7 +570,6 @@ static int device_resume(struct device *dev, pm_message_t state, bool async) ...@@ -570,7 +570,6 @@ static int device_resume(struct device *dev, pm_message_t state, bool async)
pm_callback_t callback = NULL; pm_callback_t callback = NULL;
char *info = NULL; char *info = NULL;
int error = 0; int error = 0;
bool put = false;
TRACE_DEVICE(dev); TRACE_DEVICE(dev);
TRACE_RESUME(0); TRACE_RESUME(0);
...@@ -591,7 +590,6 @@ static int device_resume(struct device *dev, pm_message_t state, bool async) ...@@ -591,7 +590,6 @@ static int device_resume(struct device *dev, pm_message_t state, bool async)
goto Unlock; goto Unlock;
pm_runtime_enable(dev); pm_runtime_enable(dev);
put = true;
if (dev->pm_domain) { if (dev->pm_domain) {
info = "power domain "; info = "power domain ";
...@@ -646,9 +644,6 @@ static int device_resume(struct device *dev, pm_message_t state, bool async) ...@@ -646,9 +644,6 @@ static int device_resume(struct device *dev, pm_message_t state, bool async)
TRACE_RESUME(error); TRACE_RESUME(error);
if (put)
pm_runtime_put_sync(dev);
return error; return error;
} }
...@@ -762,6 +757,8 @@ static void device_complete(struct device *dev, pm_message_t state) ...@@ -762,6 +757,8 @@ static void device_complete(struct device *dev, pm_message_t state)
} }
device_unlock(dev); device_unlock(dev);
pm_runtime_put_sync(dev);
} }
/** /**
...@@ -1015,7 +1012,7 @@ int dpm_suspend_end(pm_message_t state) ...@@ -1015,7 +1012,7 @@ int dpm_suspend_end(pm_message_t state)
error = dpm_suspend_noirq(state); error = dpm_suspend_noirq(state);
if (error) { if (error) {
dpm_resume_early(state); dpm_resume_early(resume_event(state));
return error; return error;
} }
...@@ -1062,12 +1059,16 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async) ...@@ -1062,12 +1059,16 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
if (async_error) if (async_error)
goto Complete; goto Complete;
pm_runtime_get_noresume(dev); /*
* If a device configured to wake up the system from sleep states
* has been suspended at run time and there's a resume request pending
* 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); pm_wakeup_event(dev, 0);
if (pm_wakeup_pending()) { if (pm_wakeup_pending()) {
pm_runtime_put_sync(dev);
async_error = -EBUSY; async_error = -EBUSY;
goto Complete; goto Complete;
} }
...@@ -1133,12 +1134,10 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async) ...@@ -1133,12 +1134,10 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
Complete: Complete:
complete_all(&dev->power.completion); complete_all(&dev->power.completion);
if (error) { if (error)
pm_runtime_put_sync(dev);
async_error = error; async_error = error;
} else if (dev->power.is_suspended) { else if (dev->power.is_suspended)
__pm_runtime_disable(dev, false); __pm_runtime_disable(dev, false);
}
return error; return error;
} }
...@@ -1234,6 +1233,14 @@ static int device_prepare(struct device *dev, pm_message_t state) ...@@ -1234,6 +1233,14 @@ static int device_prepare(struct device *dev, pm_message_t state)
if (dev->power.syscore) if (dev->power.syscore)
return 0; return 0;
/*
* If a device's parent goes into runtime suspend at the wrong time,
* it won't be possible to resume the device. To prevent this we
* block runtime suspend here, during the prepare phase, and allow
* it again during the complete phase.
*/
pm_runtime_get_noresume(dev);
device_lock(dev); device_lock(dev);
dev->power.wakeup_path = device_may_wakeup(dev); dev->power.wakeup_path = device_may_wakeup(dev);
......
...@@ -629,21 +629,6 @@ static int pci_pm_prepare(struct device *dev) ...@@ -629,21 +629,6 @@ static int pci_pm_prepare(struct device *dev)
struct device_driver *drv = dev->driver; struct device_driver *drv = dev->driver;
int error = 0; int error = 0;
/*
* If a PCI device configured to wake up the system from sleep states
* has been suspended at run time and there's a resume request pending
* for it, this is equivalent to the device signaling wakeup, so the
* system suspend operation should be aborted.
*/
pm_runtime_get_noresume(dev);
if (pm_runtime_barrier(dev) && device_may_wakeup(dev))
pm_wakeup_event(dev, 0);
if (pm_wakeup_pending()) {
pm_runtime_put_sync(dev);
return -EBUSY;
}
/* /*
* PCI devices suspended at run time need to be resumed at this * PCI devices suspended at run time need to be resumed at this
* point, because in general it is necessary to reconfigure them for * point, because in general it is necessary to reconfigure them for
...@@ -667,8 +652,6 @@ static void pci_pm_complete(struct device *dev) ...@@ -667,8 +652,6 @@ static void pci_pm_complete(struct device *dev)
if (drv && drv->pm && drv->pm->complete) if (drv && drv->pm && drv->pm->complete)
drv->pm->complete(dev); drv->pm->complete(dev);
pm_runtime_put_sync(dev);
} }
#else /* !CONFIG_PM_SLEEP */ #else /* !CONFIG_PM_SLEEP */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment