Skip to content

Commit

Permalink
PM / Domains: Fix genpd to deal with drivers returning 1 from ->prepa…
Browse files Browse the repository at this point in the history
…re()

During system-wide PM, genpd relies on its PM callbacks to be invoked for
all its attached devices, as to deal with powering off/on the PM domain. In
other words, genpd is not compatible with the direct_complete path, if
executed by the PM core for any of its attached devices.

However, when genpd's ->prepare() callback invokes pm_generic_prepare(), it
does not take into account that it may return 1. Instead it treats that as
an error internally and expects the PM core to abort the prepare phase and
roll back. This leads to genpd not properly powering on/off the PM domain,
because its internal counters gets wrongly balanced.

To fix the behaviour, allow drivers to return 1 from their ->prepare()
callbacks, but let's return 0 from genpd's ->prepare() callback in such
case, as that prevents the PM core from running the direct_complete path
for the device.

Signed-off-by: Ulf Hansson <[email protected]>
Signed-off-by: Rafael J. Wysocki <[email protected]>
  • Loading branch information
storulf authored and rafaeljw committed Nov 8, 2017
1 parent 704d2ce commit 5241ab4
Showing 1 changed file with 3 additions and 2 deletions.
5 changes: 3 additions & 2 deletions drivers/base/power/domain.c
Original file line number Diff line number Diff line change
Expand Up @@ -1010,15 +1010,16 @@ static int genpd_prepare(struct device *dev)
genpd_unlock(genpd);

ret = pm_generic_prepare(dev);
if (ret) {
if (ret < 0) {
genpd_lock(genpd);

genpd->prepared_count--;

genpd_unlock(genpd);
}

return ret;
/* Never return 1, as genpd don't cope with the direct_complete path. */
return ret >= 0 ? 0 : ret;
}

/**
Expand Down

0 comments on commit 5241ab4

Please sign in to comment.