Skip to contentSkip to conversation

PM / Sleep / Runtime: Fixup some driver's system suspend

PATCH Superseded Ulf Hansson 4 participants 20 messages Mar 1, 2014 – Mar 10, 2014

Subsystems (10)
lore
Share & tools
lore
#0 lore raw

v3 cover PM / Sleep / Runtime: Fixup some driver's system suspend

Patch 1 -> 2:
These patches provides two new runtime PM helper functions which intend to be used from system suspend/resume callbacks, to make sure devices are put into low power state during system suspend and brought back to full power at system resume.

The prerequisite is to have all levels of a device's runtime PM callbacks to be defined through the SET_PM_RUNTIME_PM_OPS macro, which means these are available for CONFIG_PM.

By using the new runtime PM helper functions especially the two scenarios below will be addressed.

1) The PM core prevents .runtime_suspend callbacks from being invoked during system suspend. That means even for a runtime PM centric subsystem and driver, the device needs to be put into low power state from a system suspend callback. Otherwise it may very well be left in full power state (runtime resumed) while the system is suspended. By using the new helper functions, we make sure to walk the hierarchy of a device's power domain, subsystem and driver.

2) Subsystems and drivers need to cope with all the combinations of CONFIG_PM_SLEEP and CONFIG_PM_RUNTIME. The two new helper functions smothly addresses this.

Patch 3 -> 4:
Fixup system suspend for spi-pl022 driver, by using the new runtime PM helper functions.

These patches is based upon the latest next-branch for spi-pl022 driver. They will not apply to Rafael's linux-pm tree, but are included in this patchset for reference and to receive comments/acks.

Patch 5:
Fixup system suspend for i2c-nomadik driver, by using the new runtime PM helper functions.

This patch is based upon the latest next-branch for the i2c-nomadik driver. They will not apply to Rafael's linux-pm tree, but are included in this patchset for reference and to receive comments/acks.

Patch 6 -> 8:
Fixup system suspend for mmci driver, by using the new runtime PM helper functions.

A final note, the amba bus has converted to use the SET_PM_RUNTIME_PM_OPS which is needed for these patches to work with only CONFIG_PM_SLEEP and not CONFIG_PM_RUNTIME. Anyway, the patches for the amba bus have recently been applied by Russell and resides in his ARM tree.

Changes in v3:
This is repost of the patchset. Only patch 1 and patch 2 has been updated to v3, the rest are still in v1.

Ulf Hansson (8):
PM / Runtime: Fetch runtime PM callbacks using a macro
PM / Sleep / Runtime: Add pm_runtime_suspend|resume_force functions
spi: pl022: Let runtime PM callbacks be available for CONFIG_PM
spi: pl022: Don't ignore power domain and amba bus at system suspend
i2c: nomadik: Fixup system suspend
mmc: mmci: Mask IRQs for all variants during runtime suspend
mmc: mmci: Let runtime PM callbacks be available for CONFIG_PM
mmc: mmci: Put the device into low power state at system suspend

 drivers/base/power/Makefile      |    3 +-
 drivers/base/power/runtime.c     |  162 +++++++++++++++++++++++++++++---------
 drivers/i2c/busses/i2c-nomadik.c |   14 ++--
 drivers/mmc/host/mmci.c          |   60 ++++----------
 drivers/spi/spi-pl022.c          |   58 +++++---------
 include/linux/pm_runtime.h       |    4 +
 6 files changed, 170 insertions(+), 131 deletions(-)
Signature · 1 line
1.7.9.5
#1 lore raw

PATCH v3 1/8 PM / Runtime: Fetch runtime PM callbacks using a macro

While fetching the proper runtime PM callback, we walk the hierarchy of device's power domains, subsystems and drivers.

This is common for rpm_suspend(), rpm_idle() and rpm_resume(). Let's clean up the code by using a macro that handles this.

Cc Kevin Hilman <[email protected]>
Cc Alan Stern <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Mark Brown <[email protected]>
Cc Russell King <[email protected]>
Cc Linus Walleij <[email protected]>
Cc Wolfram Sang <[email protected]>
Cc Alessandro Rubini <[email protected]>

---

Changes in v3:
Added functions to return the callbacks, which will be the only users of the macro. According to comments from Alan Stern and Kevin Hilman.

Changes in v2:
Updated the macro to return a callback instead. Suggested by Josh Cartwright.

---
 drivers/base/power/runtime.c |   78 +++++++++++++++++++++---------------------
 1 file changed, 39 insertions(+), 39 deletions(-)
drivers/base/power/runtime.c +39 -39
index 72e00e6..ac495b1 100644
@@ -13,6 +13,42 @@
 #include <trace/events/rpm.h>
 #include "power.h"
 
+#define RPM_GET_CALLBACK(dev, cb)				\
+({								\
+	int (*__rpm_cb)(struct device *__d);			\
+								\
+	if (dev->pm_domain)					\
+		__rpm_cb = dev->pm_domain->ops.cb;		\
+	else if (dev->type && dev->type->pm)			\
+		__rpm_cb = dev->type->pm->cb;			\
+	else if (dev->class && dev->class->pm)			\
+		__rpm_cb = dev->class->pm->cb;			\
+	else if (dev->bus && dev->bus->pm)			\
+		__rpm_cb = dev->bus->pm->cb;			\
+	else							\
+		__rpm_cb = NULL;				\
+								\
+	if (!__rpm_cb && dev->driver && dev->driver->pm)	\
+		__rpm_cb = dev->driver->pm->cb;			\
+								\
+	__rpm_cb;						\
+})
+
+static int (*rpm_get_suspend_cb(struct device *dev))(struct device *)
+{
+	return RPM_GET_CALLBACK(dev, runtime_suspend);
+}
+
+static int (*rpm_get_resume_cb(struct device *dev))(struct device *)
+{
+	return RPM_GET_CALLBACK(dev, runtime_resume);
+}
+
+static int (*rpm_get_idle_cb(struct device *dev))(struct device *)
+{
+	return RPM_GET_CALLBACK(dev, runtime_idle);
+}
+
 static int rpm_resume(struct device *dev, int rpmflags);
 static int rpm_suspend(struct device *dev, int rpmflags);
 
@@ -310,19 +346,7 @@ static int rpm_idle(struct device *dev, int rpmflags)
 
 	dev->power.idle_notification = true;
 
-	if (dev->pm_domain)
-		callback = dev->pm_domain->ops.runtime_idle;
-	else if (dev->type && dev->type->pm)
-		callback = dev->type->pm->runtime_idle;
-	else if (dev->class && dev->class->pm)
-		callback = dev->class->pm->runtime_idle;
-	else if (dev->bus && dev->bus->pm)
-		callback = dev->bus->pm->runtime_idle;
-	else
-		callback = NULL;
-
-	if (!callback && dev->driver && dev->driver->pm)
-		callback = dev->driver->pm->runtime_idle;
+	callback = rpm_get_idle_cb(dev);
 
 	if (callback)
 		retval = __rpm_callback(callback, dev);
@@ -492,19 +516,7 @@ static int rpm_suspend(struct device *dev, int rpmflags)
 
 	__update_runtime_status(dev, RPM_SUSPENDING);
 
-	if (dev->pm_domain)
-		callback = dev->pm_domain->ops.runtime_suspend;
-	else if (dev->type && dev->type->pm)
-		callback = dev->type->pm->runtime_suspend;
-	else if (dev->class && dev->class->pm)
-		callback = dev->class->pm->runtime_suspend;
-	else if (dev->bus && dev->bus->pm)
-		callback = dev->bus->pm->runtime_suspend;
-	else
-		callback = NULL;
-
-	if (!callback && dev->driver && dev->driver->pm)
-		callback = dev->driver->pm->runtime_suspend;
+	callback = rpm_get_suspend_cb(dev);
 
 	retval = rpm_callback(callback, dev);
 	if (retval)
@@ -724,19 +736,7 @@ static int rpm_resume(struct device *dev, int rpmflags)
 
 	__update_runtime_status(dev, RPM_RESUMING);
 
-	if (dev->pm_domain)
-		callback = dev->pm_domain->ops.runtime_resume;
-	else if (dev->type && dev->type->pm)
-		callback = dev->type->pm->runtime_resume;
-	else if (dev->class && dev->class->pm)
-		callback = dev->class->pm->runtime_resume;
-	else if (dev->bus && dev->bus->pm)
-		callback = dev->bus->pm->runtime_resume;
-	else
-		callback = NULL;
-
-	if (!callback && dev->driver && dev->driver->pm)
-		callback = dev->driver->pm->runtime_resume;
+	callback = rpm_get_resume_cb(dev);
 
 	retval = rpm_callback(callback, dev);
 	if (retval) {
Signature · 1 line
1.7.9.5
#2 lore raw

PATCH v3 2/8 PM / Sleep / Runtime: Add pm_runtime_suspend|resume_force functions

In reply to Ulf Hansson

This patch provides two new runtime PM helper functions which intend to be used from system suspend/resume callbacks, to make sure devices are put into low power state during system suspend and brought back to full power at system resume.

The prerequisite is to have all levels of a device's runtime PM callbacks to be defined through the SET_PM_RUNTIME_PM_OPS macro, which means these are available for CONFIG_PM.

By using the new runtime PM helper functions especially the two scenarios below will be addressed.

1) The PM core prevents .runtime_suspend callbacks from being invoked during system suspend. That means even for a runtime PM centric subsystem and driver, the device needs to be put into low power state from a system suspend callback. Otherwise it may very well be left in full power state (runtime resumed) while the system is suspended. By using the new helper functions, we make sure to walk the hierarchy of a device's power domain, subsystem and driver.

2) Subsystems and drivers need to cope with all the combinations of CONFIG_PM_SLEEP and CONFIG_PM_RUNTIME. The two new helper functions smothly addresses this.

Cc Kevin Hilman <[email protected]>
Cc Alan Stern <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Mark Brown <[email protected]>
Cc Russell King <[email protected]>
Cc Linus Walleij <[email protected]>
Cc Wolfram Sang <[email protected]>
Cc Alessandro Rubini <[email protected]>

---

Changes in v3:
Use rpm_get_suspend|resume_cb() instead of the macro.

Changes in v2:
Adopt to version 2 of the RPM_GET_CALLBACK macro.

---
 drivers/base/power/Makefile  |    3 +-
 drivers/base/power/runtime.c |   84 ++++++++++++++++++++++++++++++++++++++++++
 include/linux/pm_runtime.h   |    4 ++
 3 files changed, 89 insertions(+), 2 deletions(-)
drivers/base/power/Makefile +1 -2
index 2e58ebb..1cb8544 100644
@@ -1,6 +1,5 @@
-obj-$(CONFIG_PM)	+= sysfs.o generic_ops.o common.o qos.o
+obj-$(CONFIG_PM)	+= sysfs.o generic_ops.o common.o qos.o runtime.o
 obj-$(CONFIG_PM_SLEEP)	+= main.o wakeup.o
-obj-$(CONFIG_PM_RUNTIME)	+= runtime.o
 obj-$(CONFIG_PM_TRACE_RTC)	+= trace.o
 obj-$(CONFIG_PM_OPP)	+= opp.o
 obj-$(CONFIG_PM_GENERIC_DOMAINS)	+=  domain.o domain_governor.o
drivers/base/power/runtime.c +84 -0

93 lines not on this page · raw message

include/linux/pm_runtime.h +4 -0
index 16c9a62..2a5897a 100644
@@ -26,9 +26,13 @@
 #ifdef CONFIG_PM
 extern int pm_generic_runtime_suspend(struct device *dev);
 extern int pm_generic_runtime_resume(struct device *dev);
+extern int pm_runtime_force_suspend(struct device *dev);
+extern int pm_runtime_force_resume(struct device *dev);
 #else
 static inline int pm_generic_runtime_suspend(struct device *dev) { return 0; }
 static inline int pm_generic_runtime_resume(struct device *dev) { return 0; }
+static inline int pm_runtime_force_suspend(struct device *dev) { return 0; }
+static inline int pm_runtime_force_resume(struct device *dev) { return 0; }
 #endif
 
 #ifdef CONFIG_PM_RUNTIME
Signature · 1 line
1.7.9.5
#3 lore raw

PATCH v3 2/8 PM / Sleep / Runtime: Add pm_runtime_suspend|resume_force functions

Quoted 24 lines · Ulf Hansson

This patch provides two new runtime PM helper functions which intend to be used from system suspend/resume callbacks, to make sure devices are put into low power state during system suspend and brought back to full power at system resume.

The prerequisite is to have all levels of a device's runtime PM callbacks to be defined through the SET_PM_RUNTIME_PM_OPS macro, which means these are available for CONFIG_PM.

By using the new runtime PM helper functions especially the two scenarios below will be addressed.

1) The PM core prevents .runtime_suspend callbacks from being invoked during system suspend. That means even for a runtime PM centric subsystem and driver, the device needs to be put into low power state from a system suspend callback. Otherwise it may very well be left in full power state (runtime resumed) while the system is suspended. By using the new helper functions, we make sure to walk the hierarchy of a device's power domain, subsystem and driver.

2) Subsystems and drivers need to cope with all the combinations of CONFIG_PM_SLEEP and CONFIG_PM_RUNTIME. The two new helper functions smothly addresses this.

Quoted 9 lines
Cc Kevin Hilman <[email protected]>
Cc Alan Stern <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Mark Brown <[email protected]>
Cc Russell King <[email protected]>
Cc Linus Walleij <[email protected]>
Cc Wolfram Sang <[email protected]>
Cc Alessandro Rubini <[email protected]>

FWIW

#4 lore raw

PATCH v3 3/8 spi: pl022: Let runtime PM callbacks be available for CONFIG_PM

In reply to Ulf Hansson

Convert to the SET_PM_RUNTIME_PM macro while defining the runtime PM callbacks. This means the callbacks becomes available for both CONFIG_PM_SLEEP and CONFIG_PM_RUNTIME, which is needed to handle the combinations of these scenarios.

---
 drivers/spi/spi-pl022.c |    6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/spi/spi-pl022.c +3 -3
index 74a0729..6dfcabf 100644
@@ -2277,7 +2277,7 @@ pl022_remove(struct amba_device *adev)
 	return 0;
 }
 
-#if defined(CONFIG_SUSPEND) || defined(CONFIG_PM_RUNTIME)
+#ifdef CONFIG_PM
 /*
  * These two functions are used from both suspend/resume and
  * the runtime counterparts to handle external resources like
@@ -2343,7 +2343,7 @@ static int pl022_resume(struct device *dev)
 }
 #endif	/* CONFIG_PM */
 
-#ifdef CONFIG_PM_RUNTIME
+#ifdef CONFIG_PM
 static int pl022_runtime_suspend(struct device *dev)
 {
 	struct pl022 *pl022 = dev_get_drvdata(dev);
@@ -2363,7 +2363,7 @@ static int pl022_runtime_resume(struct device *dev)
 
 static const struct dev_pm_ops pl022_dev_pm_ops = {
 	SET_SYSTEM_SLEEP_PM_OPS(pl022_suspend, pl022_resume)
-	SET_RUNTIME_PM_OPS(pl022_runtime_suspend, pl022_runtime_resume, NULL)
+	SET_PM_RUNTIME_PM_OPS(pl022_runtime_suspend, pl022_runtime_resume, NULL)
 };
 
 static struct vendor_data vendor_arm = {
Signature · 1 line
1.7.9.5
maintainer
#5 lore raw

PATCH v3 3/8 spi: pl022: Let runtime PM callbacks be available for CONFIG_PM

Quoted 4 lines · Ulf Hansson

Convert to the SET_PM_RUNTIME_PM macro while defining the runtime PM callbacks. This means the callbacks becomes available for both CONFIG_PM_SLEEP and CONFIG_PM_RUNTIME, which is needed to handle the combinations of these scenarios.

Applied, thanks.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140306/58aee6a0/attachment-0001.sig>

#6 lore raw

PATCH v3 4/8 spi: pl022: Don't ignore power domain and amba bus at system suspend

In reply to Ulf Hansson

Previously only the resources controlled by the driver were put into low power state at system suspend. Both the amba bus and a potential power domain were ignored.

Moreover, while putting the device into low power state we first brought it back to full power, but for no particular reason.

To handle both issues above, use pm_runtime_force_suspend|resume() from the system suspend|resume callbacks.

---
 drivers/spi/spi-pl022.c |   54 ++++++++++++++++-------------------------------
 1 file changed, 18 insertions(+), 36 deletions(-)
drivers/spi/spi-pl022.c +18 -36
index 6dfcabf..d37e840 100644
@@ -2277,35 +2277,7 @@ pl022_remove(struct amba_device *adev)
 	return 0;
 }
 
-#ifdef CONFIG_PM
-/*
- * These two functions are used from both suspend/resume and
- * the runtime counterparts to handle external resources like
- * clocks, pins and regulators when going to sleep.
- */
-static void pl022_suspend_resources(struct pl022 *pl022, bool runtime)
-{
-	clk_disable_unprepare(pl022->clk);
-
-	if (runtime)
-		pinctrl_pm_select_idle_state(&pl022->adev->dev);
-	else
-		pinctrl_pm_select_sleep_state(&pl022->adev->dev);
-}
-
-static void pl022_resume_resources(struct pl022 *pl022, bool runtime)
-{
-	/* First go to the default state */
-	pinctrl_pm_select_default_state(&pl022->adev->dev);
-	if (!runtime)
-		/* Then let's idle the pins until the next transfer happens */
-		pinctrl_pm_select_idle_state(&pl022->adev->dev);
-
-	clk_prepare_enable(pl022->clk);
-}
-#endif
-
-#ifdef CONFIG_SUSPEND
+#ifdef CONFIG_PM_SLEEP
 static int pl022_suspend(struct device *dev)
 {
 	struct pl022 *pl022 = dev_get_drvdata(dev);
@@ -2317,8 +2289,13 @@ static int pl022_suspend(struct device *dev)
 		return ret;
 	}
 
-	pm_runtime_get_sync(dev);
-	pl022_suspend_resources(pl022, false);
+	ret = pm_runtime_force_suspend(dev);
+	if (ret) {
+		spi_master_resume(pl022->master);
+		return ret;
+	}
+
+	pinctrl_pm_select_sleep_state(dev);
 
 	dev_dbg(dev, "suspended\n");
 	return 0;
@@ -2329,8 +2306,9 @@ static int pl022_resume(struct device *dev)
 	struct pl022 *pl022 = dev_get_drvdata(dev);
 	int ret;
 
-	pl022_resume_resources(pl022, false);
-	pm_runtime_put(dev);
+	ret = pm_runtime_force_resume(dev);
+	if (ret)
+		dev_err(dev, "problem resuming\n");
 
 	/* Start the queue running */
 	ret = spi_master_resume(pl022->master);
@@ -2341,14 +2319,16 @@ static int pl022_resume(struct device *dev)
 
 	return ret;
 }
-#endif	/* CONFIG_PM */
+#endif
 
 #ifdef CONFIG_PM
 static int pl022_runtime_suspend(struct device *dev)
 {
 	struct pl022 *pl022 = dev_get_drvdata(dev);
 
-	pl022_suspend_resources(pl022, true);
+	clk_disable_unprepare(pl022->clk);
+	pinctrl_pm_select_idle_state(dev);
+
 	return 0;
 }
 
@@ -2356,7 +2336,9 @@ static int pl022_runtime_resume(struct device *dev)
 {
 	struct pl022 *pl022 = dev_get_drvdata(dev);
 
-	pl022_resume_resources(pl022, true);
+	pinctrl_pm_select_default_state(dev);
+	clk_prepare_enable(pl022->clk);
+
 	return 0;
 }
 #endif
Signature · 1 line
1.7.9.5
maintainer
#7 lore raw

PATCH v3 4/8 spi: pl022: Don't ignore power domain and amba bus at system suspend

Quoted 3 lines · Ulf Hansson

Previously only the resources controlled by the driver were put into low power state at system suspend. Both the amba bus and a potential power domain were ignored.

Applied, thanks.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140306/0960093d/attachment.sig>

#8 lore raw

PATCH v3 5/8 i2c: nomadik: Fixup system suspend

In reply to Ulf Hansson

For !CONFIG_PM_RUNTIME, the device were never put back into active state while resuming.

For CONFIG_PM_RUNTIME, we blindly trusted the device to be inactive while we were about to handle it at suspend late, which is just too optimistic.

Even if the driver uses pm_runtime_put_sync() after each tranfer to return it's runtime PM resources, there are no guarantees this will actually mean the device will inactivated. The reason is that the PM core will prevent runtime suspend during system suspend, and thus when a transfer occurs during the early phases of system suspend the device will be kept active after the transfer.

To handle both issues above, use pm_runtime_force_suspend|resume() from the system suspend|resume callbacks.

Cc Alessandro Rubini <[email protected]>
Cc Linus Walleij <[email protected]>
Cc Wolfram Sang <[email protected]>
---
 drivers/i2c/busses/i2c-nomadik.c |   14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)
drivers/i2c/busses/i2c-nomadik.c +7 -7
index 8082f5c..519f5b8 100644
@@ -879,19 +879,19 @@ static irqreturn_t i2c_irq_handler(int irq, void *arg)
 #ifdef CONFIG_PM_SLEEP
 static int nmk_i2c_suspend_late(struct device *dev)
 {
-	pinctrl_pm_select_sleep_state(dev);
+	int ret;
 
+	ret = pm_runtime_force_suspend(dev);
+	if (ret)
+		return ret;
+
+	pinctrl_pm_select_sleep_state(dev);
 	return 0;
 }
 
 static int nmk_i2c_resume_early(struct device *dev)
 {
-	/* First go to the default state */
-	pinctrl_pm_select_default_state(dev);
-	/* Then let's idle the pins until the next transfer happens */
-	pinctrl_pm_select_idle_state(dev);
-
-	return 0;
+	return pm_runtime_force_resume(dev);
 }
 #endif
 
Signature · 1 line
1.7.9.5
#9 lore raw

PATCH v3 5/8 i2c: nomadik: Fixup system suspend

Quoted 14 lines · Ulf Hansson

For !CONFIG_PM_RUNTIME, the device were never put back into active state while resuming.

For CONFIG_PM_RUNTIME, we blindly trusted the device to be inactive while we were about to handle it at suspend late, which is just too optimistic.

Even if the driver uses pm_runtime_put_sync() after each tranfer to return it's runtime PM resources, there are no guarantees this will actually mean the device will inactivated. The reason is that the PM core will prevent runtime suspend during system suspend, and thus when a transfer occurs during the early phases of system suspend the device will be kept active after the transfer.

Quoted 7 lines

To handle both issues above, use pm_runtime_force_suspend|resume() from the system suspend|resume callbacks.

Cc Alessandro Rubini <[email protected]>
Cc Linus Walleij <[email protected]>
Cc Wolfram Sang <[email protected]>

Hi Wolfram,

The pm-drivers branch of the linux-pm.git, contains the helper functions this patch depends on.

If you decide to pull that branch to your tree, to be able to apply this patch, please let me know. Otherwise I will repost this patch once 3.15 rc1 is available.

Kind regards
Ulf Hansson

Quoted 38 lines
---
 drivers/i2c/busses/i2c-nomadik.c |   14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)
drivers/i2c/busses/i2c-nomadik.c +7 -8
index 8082f5c..519f5b8 100644
@@ -879,19 +879,19 @@ static irqreturn_t i2c_irq_handler(int irq, void *arg)
 #ifdef CONFIG_PM_SLEEP
 static int nmk_i2c_suspend_late(struct device *dev)
 {
-       pinctrl_pm_select_sleep_state(dev);
+       int ret;
 
+       ret = pm_runtime_force_suspend(dev);
+       if (ret)
+               return ret;
+
+       pinctrl_pm_select_sleep_state(dev);
        return 0;
 }
 
 static int nmk_i2c_resume_early(struct device *dev)
 {
-       /* First go to the default state */
-       pinctrl_pm_select_default_state(dev);
-       /* Then let's idle the pins until the next transfer happens */
-       pinctrl_pm_select_idle_state(dev);
-
-       return 0;
+       return pm_runtime_force_resume(dev);
 }
 #endif
 
--

1.7.9.5

#10 lore raw

PATCH v3 6/8 mmc: mmci: Mask IRQs for all variants during runtime suspend

In reply to Ulf Hansson

In runtime suspended state, we are not expecting IRQs and thus we can safely mask them, not only for pwrreg_nopower variants but for all.

Obviously we then also need to make sure we restore the IRQ mask while becoming runtime resumed.

---
 drivers/mmc/host/mmci.c |   23 +++++++++++------------
 1 file changed, 11 insertions(+), 12 deletions(-)
drivers/mmc/host/mmci.c +11 -12
index b931226..178868a 100644
@@ -1758,35 +1758,34 @@ static void mmci_save(struct mmci_host *host)
 {
 	unsigned long flags;
 
-	if (host->variant->pwrreg_nopower) {
-		spin_lock_irqsave(&host->lock, flags);
+	spin_lock_irqsave(&host->lock, flags);
 
-		writel(0, host->base + MMCIMASK0);
+	writel(0, host->base + MMCIMASK0);
+	if (host->variant->pwrreg_nopower) {
 		writel(0, host->base + MMCIDATACTRL);
 		writel(0, host->base + MMCIPOWER);
 		writel(0, host->base + MMCICLOCK);
-		mmci_reg_delay(host);
-
-		spin_unlock_irqrestore(&host->lock, flags);
 	}
+	mmci_reg_delay(host);
 
+	spin_unlock_irqrestore(&host->lock, flags);
 }
 
 static void mmci_restore(struct mmci_host *host)
 {
 	unsigned long flags;
 
-	if (host->variant->pwrreg_nopower) {
-		spin_lock_irqsave(&host->lock, flags);
+	spin_lock_irqsave(&host->lock, flags);
 
+	if (host->variant->pwrreg_nopower) {
 		writel(host->clk_reg, host->base + MMCICLOCK);
 		writel(host->datactrl_reg, host->base + MMCIDATACTRL);
 		writel(host->pwr_reg, host->base + MMCIPOWER);
-		writel(MCI_IRQENABLE, host->base + MMCIMASK0);
-		mmci_reg_delay(host);
-
-		spin_unlock_irqrestore(&host->lock, flags);
 	}
+	writel(MCI_IRQENABLE, host->base + MMCIMASK0);
+	mmci_reg_delay(host);
+
+	spin_unlock_irqrestore(&host->lock, flags);
 }
 
 static int mmci_runtime_suspend(struct device *dev)
Signature · 1 line
1.7.9.5
#11 lore raw

PATCH v3 6/8 mmc: mmci: Mask IRQs for all variants during runtime suspend

Quoted 8 lines · Ulf Hansson

In runtime suspended state, we are not expecting IRQs and thus we can safely mask them, not only for pwrreg_nopower variants but for all.

Obviously we then also need to make sure we restore the IRQ mask while becoming runtime resumed.

Hi Russell,

I suppose we have discussed and sorted out the concerns you had around this patch!?

It's available in your patch tracker, would be nice to get it merged for 3.15, if that's possible.

Kind regards
Uffe

Quoted 58 lines
---
 drivers/mmc/host/mmci.c |   23 +++++++++++------------
 1 file changed, 11 insertions(+), 12 deletions(-)
drivers/mmc/host/mmci.c +11 -13
index b931226..178868a 100644
@@ -1758,35 +1758,34 @@ static void mmci_save(struct mmci_host *host)
 {
        unsigned long flags;
 
-       if (host->variant->pwrreg_nopower) {
-               spin_lock_irqsave(&host->lock, flags);
+       spin_lock_irqsave(&host->lock, flags);
 
-               writel(0, host->base + MMCIMASK0);
+       writel(0, host->base + MMCIMASK0);
+       if (host->variant->pwrreg_nopower) {
                writel(0, host->base + MMCIDATACTRL);
                writel(0, host->base + MMCIPOWER);
                writel(0, host->base + MMCICLOCK);
-               mmci_reg_delay(host);
-
-               spin_unlock_irqrestore(&host->lock, flags);
        }
+       mmci_reg_delay(host);
 
+       spin_unlock_irqrestore(&host->lock, flags);
 }
 
 static void mmci_restore(struct mmci_host *host)
 {
        unsigned long flags;
 
-       if (host->variant->pwrreg_nopower) {
-               spin_lock_irqsave(&host->lock, flags);
+       spin_lock_irqsave(&host->lock, flags);
 
+       if (host->variant->pwrreg_nopower) {
                writel(host->clk_reg, host->base + MMCICLOCK);
                writel(host->datactrl_reg, host->base + MMCIDATACTRL);
                writel(host->pwr_reg, host->base + MMCIPOWER);
-               writel(MCI_IRQENABLE, host->base + MMCIMASK0);
-               mmci_reg_delay(host);
-
-               spin_unlock_irqrestore(&host->lock, flags);
        }
+       writel(MCI_IRQENABLE, host->base + MMCIMASK0);
+       mmci_reg_delay(host);
+
+       spin_unlock_irqrestore(&host->lock, flags);
 }
 
 static int mmci_runtime_suspend(struct device *dev)
--

1.7.9.5

#12 lore raw

PATCH v3 6/8 mmc: mmci: Mask IRQs for all variants during runtime suspend

Quoted 12 lines · Ulf Hansson
Quoted 8 lines · Ulf Hansson

In runtime suspended state, we are not expecting IRQs and thus we can safely mask them, not only for pwrreg_nopower variants but for all.

Obviously we then also need to make sure we restore the IRQ mask while becoming runtime resumed.

Hi Russell,

Quoted 8 lines

I suppose we have discussed and sorted out the concerns you had around this patch!?

It's available in your patch tracker, would be nice to get it merged for 3.15, if that's possible.

Kind regards
Uffe

Sorry for spamming, this went to the wrong addresses. Let's try again.

Kind regards
Uffe

Quoted 59 lines
Quoted 59 lines
---
 drivers/mmc/host/mmci.c |   23 +++++++++++------------
 1 file changed, 11 insertions(+), 12 deletions(-)
drivers/mmc/host/mmci.c +11 -13
index b931226..178868a 100644
@@ -1758,35 +1758,34 @@ static void mmci_save(struct mmci_host *host)
 {
        unsigned long flags;
 
-       if (host->variant->pwrreg_nopower) {
-               spin_lock_irqsave(&host->lock, flags);
+       spin_lock_irqsave(&host->lock, flags);
 
-               writel(0, host->base + MMCIMASK0);
+       writel(0, host->base + MMCIMASK0);
+       if (host->variant->pwrreg_nopower) {
                writel(0, host->base + MMCIDATACTRL);
                writel(0, host->base + MMCIPOWER);
                writel(0, host->base + MMCICLOCK);
-               mmci_reg_delay(host);
-
-               spin_unlock_irqrestore(&host->lock, flags);
        }
+       mmci_reg_delay(host);
 
+       spin_unlock_irqrestore(&host->lock, flags);
 }
 
 static void mmci_restore(struct mmci_host *host)
 {
        unsigned long flags;
 
-       if (host->variant->pwrreg_nopower) {
-               spin_lock_irqsave(&host->lock, flags);
+       spin_lock_irqsave(&host->lock, flags);
 
+       if (host->variant->pwrreg_nopower) {
                writel(host->clk_reg, host->base + MMCICLOCK);
                writel(host->datactrl_reg, host->base + MMCIDATACTRL);
                writel(host->pwr_reg, host->base + MMCIPOWER);
-               writel(MCI_IRQENABLE, host->base + MMCIMASK0);
-               mmci_reg_delay(host);
-
-               spin_unlock_irqrestore(&host->lock, flags);
        }
+       writel(MCI_IRQENABLE, host->base + MMCIMASK0);
+       mmci_reg_delay(host);
+
+       spin_unlock_irqrestore(&host->lock, flags);
 }
 
 static int mmci_runtime_suspend(struct device *dev)
--

1.7.9.5

#13 lore raw

PATCH v3 7/8 mmc: mmci: Let runtime PM callbacks be available for CONFIG_PM

In reply to Ulf Hansson

Convert to the SET_PM_RUNTIME_PM macro while defining the runtime PM callbacks. This means the callbacks becomes available for both CONFIG_PM_SLEEP and CONFIG_PM_RUNTIME, which is needed to handle the combinations of these scenarios.

---
 drivers/mmc/host/mmci.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/mmc/host/mmci.c +2 -2
index 178868a..c88da1c 100644
@@ -1753,7 +1753,7 @@ static int mmci_resume(struct device *dev)
 }
 #endif
 
-#ifdef CONFIG_PM_RUNTIME
+#ifdef CONFIG_PM
 static void mmci_save(struct mmci_host *host)
 {
 	unsigned long flags;
@@ -1821,7 +1821,7 @@ static int mmci_runtime_resume(struct device *dev)
 
 static const struct dev_pm_ops mmci_dev_pm_ops = {
 	SET_SYSTEM_SLEEP_PM_OPS(mmci_suspend, mmci_resume)
-	SET_RUNTIME_PM_OPS(mmci_runtime_suspend, mmci_runtime_resume, NULL)
+	SET_PM_RUNTIME_PM_OPS(mmci_runtime_suspend, mmci_runtime_resume, NULL)
 };
 
 static struct amba_id mmci_ids[] = {
Signature · 1 line
1.7.9.5
#14 lore raw

PATCH v3 8/8 mmc: mmci: Put the device into low power state at system suspend

In reply to Ulf Hansson

For CONFIG_PM_SLEEP, the device were always left in full power state after system suspend.

We solely relied on a power domain to put it into low power state, which is an unreasonable requirement to put on SOCs to implement. Especially for those SOCs not supporting power domains at all.

Use pm_runtime_force_suspend|resume() as the system suspend callbacks, to resolve the issue.

---
 drivers/mmc/host/mmci.c |   33 ++-------------------------------
 1 file changed, 2 insertions(+), 31 deletions(-)
drivers/mmc/host/mmci.c +2 -31
index c88da1c..1432ae2 100644
@@ -1723,36 +1723,6 @@ static int mmci_remove(struct amba_device *dev)
 	return 0;
 }
 
-#ifdef CONFIG_SUSPEND
-static int mmci_suspend(struct device *dev)
-{
-	struct amba_device *adev = to_amba_device(dev);
-	struct mmc_host *mmc = amba_get_drvdata(adev);
-
-	if (mmc) {
-		struct mmci_host *host = mmc_priv(mmc);
-		pm_runtime_get_sync(dev);
-		writel(0, host->base + MMCIMASK0);
-	}
-
-	return 0;
-}
-
-static int mmci_resume(struct device *dev)
-{
-	struct amba_device *adev = to_amba_device(dev);
-	struct mmc_host *mmc = amba_get_drvdata(adev);
-
-	if (mmc) {
-		struct mmci_host *host = mmc_priv(mmc);
-		writel(MCI_IRQENABLE, host->base + MMCIMASK0);
-		pm_runtime_put(dev);
-	}
-
-	return 0;
-}
-#endif
-
 #ifdef CONFIG_PM
 static void mmci_save(struct mmci_host *host)
 {
@@ -1820,7 +1790,8 @@ static int mmci_runtime_resume(struct device *dev)
 #endif
 
 static const struct dev_pm_ops mmci_dev_pm_ops = {
-	SET_SYSTEM_SLEEP_PM_OPS(mmci_suspend, mmci_resume)
+	SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
+				pm_runtime_force_resume)
 	SET_PM_RUNTIME_PM_OPS(mmci_runtime_suspend, mmci_runtime_resume, NULL)
 };
 
Signature · 1 line
1.7.9.5
#15 lore raw

v3 cover PM / Sleep / Runtime: Fixup some driver's system suspend

In reply to Ulf Hansson
Quoted 20 lines · Ulf Hansson

Patch 1 -> 2:
These patches provides two new runtime PM helper functions which intend to be used from system suspend/resume callbacks, to make sure devices are put into low power state during system suspend and brought back to full power at system resume.

The prerequisite is to have all levels of a device's runtime PM callbacks to be defined through the SET_PM_RUNTIME_PM_OPS macro, which means these are available for CONFIG_PM.

By using the new runtime PM helper functions especially the two scenarios below will be addressed.

1) The PM core prevents .runtime_suspend callbacks from being invoked during system suspend. That means even for a runtime PM centric subsystem and driver, the device needs to be put into low power state from a system suspend callback. Otherwise it may very well be left in full power state (runtime resumed) while the system is suspended. By using the new helper functions, we make sure to walk the hierarchy of a device's power domain, subsystem and driver.

Quoted 3 lines

2) Subsystems and drivers need to cope with all the combinations of CONFIG_PM_SLEEP and CONFIG_PM_RUNTIME. The two new helper functions smothly addresses this.

OK, I've queued up [1-2/8] for 3.15. The rest generally didn't apply for me and I think it'd be better to push them through the respective subsystem trees later anyway.

Thanks!

Signature · 2 lines
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.
#16 lore raw

v3 cover PM / Sleep / Runtime: Fixup some driver's system suspend

Quoted 21 lines · Rafael J. Wysocki
Quoted 20 lines · Ulf Hansson

Patch 1 -> 2:
These patches provides two new runtime PM helper functions which intend to be used from system suspend/resume callbacks, to make sure devices are put into low power state during system suspend and brought back to full power at system resume.

The prerequisite is to have all levels of a device's runtime PM callbacks to be defined through the SET_PM_RUNTIME_PM_OPS macro, which means these are available for CONFIG_PM.

By using the new runtime PM helper functions especially the two scenarios below will be addressed.

1) The PM core prevents .runtime_suspend callbacks from being invoked during system suspend. That means even for a runtime PM centric subsystem and driver, the device needs to be put into low power state from a system suspend callback. Otherwise it may very well be left in full power state (runtime resumed) while the system is suspended. By using the new helper functions, we make sure to walk the hierarchy of a device's power domain, subsystem and driver.

Quoted 7 lines
Quoted 3 lines

2) Subsystems and drivers need to cope with all the combinations of CONFIG_PM_SLEEP and CONFIG_PM_RUNTIME. The two new helper functions smothly addresses this.

OK, I've queued up [1-2/8] for 3.15. The rest generally didn't apply for me and I think it'd be better to push them through the respective subsystem trees later anyway.

Thanks Rafael!

Agree, regarding 3->8, they were at this point mostly included for your reference.

Kind regards
Uffe

Quoted 6 lines

Thanks!

--
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.

maintainer
#17 lore raw

v3 cover PM / Sleep / Runtime: Fixup some driver's system suspend

In reply to Rafael J. Wysocki
Quoted 3 lines · Rafael J. Wysocki

OK, I've queued up [1-2/8] for 3.15. The rest generally didn't apply for me and I think it'd be better to push them through the respective subsystem trees later anyway.

Is there a tag we can pull to get those patches? The driver changes
depend on the new API introduced in patch 2.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140305/b9b21cb4/attachment.sig>

#18 lore raw

v3 cover PM / Sleep / Runtime: Fixup some driver's system suspend

Quoted 8 lines · Mark Brown
Quoted 3 lines · Rafael J. Wysocki

OK, I've queued up [1-2/8] for 3.15. The rest generally didn't apply for me and I think it'd be better to push them through the respective subsystem trees later anyway.

Is there a tag we can pull to get those patches? The driver changes depend on the new API introduced in patch 2.

They are in the pm-drivers branch of linux-pm.git.

Thanks!

Signature · 2 lines
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.
maintainer
#19 lore raw

v3 cover PM / Sleep / Runtime: Fixup some driver's system suspend

Quoted 6 lines · Rafael J. Wysocki
Quoted 2 lines · Mark Brown

Is there a tag we can pull to get those patches? The driver changes depend on the new API introduced in patch 2.

They are in the pm-drivers branch of linux-pm.git.

I've pulled them now, thanks.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140306/545f45c6/attachment-0001.sig>