[3.5.y.z extended stable] Patch "ARM: OMAP2+: omap_device: maintain sane runtime pm status around" has been added to staging queue

Luis Henriques luis.henriques at canonical.com
Fri Nov 29 14:03:05 UTC 2013

This is a note to let you know that I have just added a patch titled

    ARM: OMAP2+: omap_device: maintain sane runtime pm status around

to the linux-3.5.y-queue branch of the 3.5.y.z extended stable tree 
which can be found at:


If you, or anyone else, feels it should not be added to this tree, please 
reply to this email.

For more information about the 3.5.y.z tree, see



>From d34b5bdf1dbe4daa294255390febb106240a6002 Mon Sep 17 00:00:00 2001
From: Nishanth Menon <nm at ti.com>
Date: Thu, 14 Nov 2013 11:05:16 -0600
Subject: ARM: OMAP2+: omap_device: maintain sane runtime pm status around

commit 3522bf7bfa248b99eafa2f4872190699a808c7d9 upstream.

OMAP device hooks around suspend|resume_noirq ensures that hwmod
devices are forced to idle using omap_device_idle/enable as part of
the last stage of suspend activity.

For a device such as i2c who uses autosuspend, it is possible to enter
the suspend path with dev->power.runtime_status = RPM_ACTIVE.

As part of the suspend flow, the generic runtime logic would increment
it's dev->power.disable_depth to 1. This should prevent further
pm_runtime_get_sync from succeeding once the runtime_status has been

Now, as part of the suspend_noirq handler in omap_device, we force the
following: if the device status is !suspended, we force the device
to idle using omap_device_idle (clocks are cut etc..). This ensures
that from a hardware perspective, the device is "suspended". However,
runtime_status is left to be active.

*if* an operation is attempted after this point to
pm_runtime_get_sync, runtime framework depends on runtime_status to
indicate accurately the device status, and since it sees it to be
ACTIVE, it assumes the module is functional and returns a non-error
value. As a result the user will see pm_runtime_get succeed, however a
register access will crash due to the lack of clocks.

To prevent this from happening, we should ensure that runtime_status
exactly indicates the device status. As a result of this change
any further calls to pm_runtime_get* would return -EACCES (since
disable_depth is 1). On resume, we restore the clocks and runtime
status exactly as we suspended with. These operations are not expected
to fail as we update the states after the core runtime framework has
suspended itself and restore before the core runtime framework has

Reported-by: J Keerthy <j-keerthy at ti.com>
Signed-off-by: Nishanth Menon <nm at ti.com>
Acked-by: Rajendra Nayak <rnayak at ti.com>
Acked-by: Kevin Hilman <khilman at linaro.org>
Reviewed-by: Felipe Balbi <balbi at ti.com>
Signed-off-by: Tony Lindgren <tony at atomide.com>
[ luis: backported to 3.5: adjusted context ]
Signed-off-by: Luis Henriques <luis.henriques at canonical.com>
 arch/arm/plat-omap/omap_device.c | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/arch/arm/plat-omap/omap_device.c b/arch/arm/plat-omap/omap_device.c
index c490240..ccc4536 100644
--- a/arch/arm/plat-omap/omap_device.c
+++ b/arch/arm/plat-omap/omap_device.c
@@ -756,6 +756,7 @@ static int _od_suspend_noirq(struct device *dev)

 	if (!ret && !pm_runtime_status_suspended(dev)) {
 		if (pm_generic_runtime_suspend(dev) == 0) {
+			pm_runtime_set_suspended(dev);
 			if (!(od->flags & OMAP_DEVICE_NO_IDLE_ON_SUSPEND))
 			od->flags |= OMAP_DEVICE_SUSPENDED;
@@ -770,11 +771,19 @@ static int _od_resume_noirq(struct device *dev)
 	struct platform_device *pdev = to_platform_device(dev);
 	struct omap_device *od = to_omap_device(pdev);

-	if ((od->flags & OMAP_DEVICE_SUSPENDED) &&
-	    !pm_runtime_status_suspended(dev)) {
+	if (od->flags & OMAP_DEVICE_SUSPENDED) {
 		od->flags &= ~OMAP_DEVICE_SUSPENDED;
 		if (!(od->flags & OMAP_DEVICE_NO_IDLE_ON_SUSPEND))
+		/*
+		 * XXX: we run before core runtime pm has resumed itself. At
+		 * this point in time, we just restore the runtime pm state and
+		 * considering symmetric operations in resume, we donot expect
+		 * to fail. If we failed, something changed in core runtime_pm
+		 * framework OR some device driver messed things up, hence, WARN
+		 */
+		WARN(pm_runtime_set_active(dev),
+		     "Could not set %s runtime state active\n", dev_name(dev));


More information about the kernel-team mailing list