PM / Runtime: let rpm_resume() succeed if RPM_ACTIVE, even when disabled, v2
Kevin Hilman [Fri, 21 Sep 2012 22:47:34 +0000 (22:47 +0000)]
There are several drivers where the return value of
pm_runtime_get_sync() is used to decide whether or not it is safe to
access hardware and that don't provide .suspend() callbacks for system
suspend (but may use late/noirq callbacks.)  If such a driver happens
to call pm_runtime_get_sync() during system suspend, after the core
has disabled runtime PM, it will get the error code and will decide
that the hardware should not be accessed, although this may be a wrong
conclusion, depending on the state of the device when runtime PM was

Drivers might work around this problem by using a test like:

   ret = pm_runtime_get_sync(dev);
   if (!ret || (ret == -EACCES && driver_private_data(dev)->suspended)) {
      /* access hardware */

where driver_private_data(dev)->suspended is a flag set by the
driver's .suspend() method (that would have to be added for this
purpose).  However, that potentially would need to be done by multiple
drivers which means quite a lot of duplicated code and bloat.

To avoid that we can use the observation that the core sets
dev->power.is_suspended before disabling runtime PM and use that
instead of the driver's private flag.  Still, potentially many drivers
would need to repeat that same check in quite a few places, so it's
better to let the core do it.

Then we can be a bit smarter and check whether or not runtime PM was
disabled by the core only (disable_depth == 1) or by someone else in
addition to the core (disable_depth > 1).  In the former case
rpm_resume() can return 1 if the runtime PM status is RPM_ACTIVE,
because it means the device was active when the core disabled runtime
PM.  In the latter case it should still return -EACCES, because it
isn't clear why runtime PM has been disabled.

Tested on AM3730/Beagle-xM where a wakeup IRQ firing during the late
suspend phase triggers runtime PM activity in the I2C driver since the
wakeup IRQ is on an I2C-connected PMIC.

[rjw: Modified whitespace to follow the file's convention.]

Signed-off-by: Kevin Hilman <>
Signed-off-by: Rafael J. Wysocki <>
(cherry picked from commit 6f3c77b040fc24708228607bba504878de5236d1)
Change-Id: Idc33d188f460f6703e2fba147602b7b0a65f27c7
Reviewed-on: http://git-master/r/145855
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Prashant Gaikwad <>
Tested-by: Prashant Gaikwad <>
Reviewed-by: Bharat Nihalani <>


index 44bce74..2ea7621 100644 (file)
@@ -511,6 +511,9 @@ static int rpm_resume(struct device *dev, int rpmflags)
        if (dev->power.runtime_error)
                retval = -EINVAL;
+       else if (dev->power.disable_depth == 1 && dev->power.is_suspended
+           && dev->power.runtime_status == RPM_ACTIVE)
+               retval = 1;
        else if (dev->power.disable_depth > 0)
                retval = -EACCES;
        if (retval)