Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 256957
b: refs/heads/master
c: 1e2ef05
h: refs/heads/master
i:
  256955: f476731
v: v3
  • Loading branch information
Rafael J. Wysocki committed Jul 6, 2011
1 parent 140c256 commit bee74bf
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 13 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: eea3fc0357eb89d0b2d1af37bdfb83eb4076a542
refs/heads/master: 1e2ef05bb8cf851a694d38e9170c89e7ff052741
21 changes: 21 additions & 0 deletions trunk/Documentation/power/runtime_pm.txt
Original file line number Diff line number Diff line change
Expand Up @@ -583,6 +583,13 @@ this is:
pm_runtime_set_active(dev);
pm_runtime_enable(dev);

The PM core always increments the run-time usage counter before calling the
->suspend() callback and decrements it after calling the ->resume() callback.
Hence disabling run-time PM temporarily like this will not cause any runtime
suspend attempts to be permanently lost. If the usage count goes to zero
following the return of the ->resume() callback, the ->runtime_idle() callback
will be invoked as usual.

On some systems, however, system sleep is not entered through a global firmware
or hardware operation. Instead, all hardware components are put into low-power
states directly by the kernel in a coordinated way. Then, the system sleep
Expand All @@ -595,6 +602,20 @@ place (in particular, if the system is not waking up from hibernation), it may
be more efficient to leave the devices that had been suspended before the system
suspend began in the suspended state.

The PM core does its best to reduce the probability of race conditions between
the runtime PM and system suspend/resume (and hibernation) callbacks by carrying
out the following operations:

* During system suspend it calls pm_runtime_get_noresume() and
pm_runtime_barrier() for every device right before executing the
subsystem-level .suspend() callback for it. In addition to that it calls
pm_runtime_disable() for every device right after executing the
subsystem-level .suspend() callback for it.

* During system resume it calls pm_runtime_enable() and pm_runtime_put_sync()
for every device right before and right after executing the subsystem-level
.resume() callback for it, respectively.

7. Generic subsystem callbacks

Subsystems may wish to conserve code space by using the set of generic power
Expand Down
35 changes: 23 additions & 12 deletions trunk/drivers/base/power/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -505,6 +505,7 @@ static int legacy_resume(struct device *dev, int (*cb)(struct device *dev))
static int device_resume(struct device *dev, pm_message_t state, bool async)
{
int error = 0;
bool put = false;

TRACE_DEVICE(dev);
TRACE_RESUME(0);
Expand All @@ -521,6 +522,9 @@ static int device_resume(struct device *dev, pm_message_t state, bool async)
if (!dev->power.is_suspended)
goto Unlock;

pm_runtime_enable(dev);
put = true;

if (dev->pm_domain) {
pm_dev_dbg(dev, state, "power domain ");
error = pm_op(dev, &dev->pm_domain->ops, state);
Expand Down Expand Up @@ -563,6 +567,10 @@ static int device_resume(struct device *dev, pm_message_t state, bool async)
complete_all(&dev->power.completion);

TRACE_RESUME(error);

if (put)
pm_runtime_put_sync(dev);

return error;
}

Expand Down Expand Up @@ -843,16 +851,22 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
int error = 0;

dpm_wait_for_children(dev, async);
device_lock(dev);

if (async_error)
goto Unlock;
return 0;

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);
async_error = -EBUSY;
goto Unlock;
return 0;
}

device_lock(dev);

if (dev->pm_domain) {
pm_dev_dbg(dev, state, "power domain ");
error = pm_op(dev, &dev->pm_domain->ops, state);
Expand Down Expand Up @@ -890,12 +904,15 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
End:
dev->power.is_suspended = !error;

Unlock:
device_unlock(dev);
complete_all(&dev->power.completion);

if (error)
if (error) {
pm_runtime_put_sync(dev);
async_error = error;
} else if (dev->power.is_suspended) {
__pm_runtime_disable(dev, false);
}

return error;
}
Expand Down Expand Up @@ -1035,13 +1052,7 @@ int dpm_prepare(pm_message_t state)
get_device(dev);
mutex_unlock(&dpm_list_mtx);

pm_runtime_get_noresume(dev);
if (pm_runtime_barrier(dev) && device_may_wakeup(dev))
pm_wakeup_event(dev, 0);

pm_runtime_put_sync(dev);
error = pm_wakeup_pending() ?
-EBUSY : device_prepare(dev, state);
error = device_prepare(dev, state);

mutex_lock(&dpm_list_mtx);
if (error) {
Expand Down

0 comments on commit bee74bf

Please sign in to comment.