summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-06-03 23:49:52 +0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-06-03 23:49:52 +0400
commit45f0a85c8258741d11bda25c0a5669c06267204a (patch)
treea618cce0583426a5c7f53f56cf19139a6f9733ce
parentcd38ca854de15b26eb91009137cbe157d8a8e773 (diff)
downloadlinux-45f0a85c8258741d11bda25c0a5669c06267204a.tar.xz
PM / Runtime: Rework the "runtime idle" helper routine
The "runtime idle" helper routine, rpm_idle(), currently ignores return values from .runtime_idle() callbacks executed by it. However, it turns out that many subsystems use pm_generic_runtime_idle() which checks the return value of the driver's callback and executes pm_runtime_suspend() for the device unless that value is not 0. If that logic is moved to rpm_idle() instead, pm_generic_runtime_idle() can be dropped and its users will not need any .runtime_idle() callbacks any more. Moreover, the PCI, SCSI, and SATA subsystems' .runtime_idle() routines, pci_pm_runtime_idle(), scsi_runtime_idle(), and ata_port_runtime_idle(), respectively, as well as a few drivers' ones may be simplified if rpm_idle() calls rpm_suspend() after 0 has been returned by the .runtime_idle() callback executed by it. To reduce overall code bloat, make the changes described above. Tested-by: Mika Westerberg <mika.westerberg@linux.intel.com> Tested-by: Kevin Hilman <khilman@linaro.org> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Acked-by: Kevin Hilman <khilman@linaro.org> Reviewed-by: Ulf Hansson <ulf.hansson@linaro.org> Acked-by: Alan Stern <stern@rowland.harvard.edu>
-rw-r--r--Documentation/power/runtime_pm.txt5
-rw-r--r--arch/arm/mach-omap2/omap_device.c7
-rw-r--r--drivers/acpi/device_pm.c1
-rw-r--r--drivers/amba/bus.c2
-rw-r--r--drivers/ata/libata-core.c2
-rw-r--r--drivers/base/platform.c1
-rw-r--r--drivers/base/power/domain.c1
-rw-r--r--drivers/base/power/generic_ops.c23
-rw-r--r--drivers/base/power/runtime.c12
-rw-r--r--drivers/dma/intel_mid_dma.c2
-rw-r--r--drivers/gpio/gpio-langwell.c6
-rw-r--r--drivers/i2c/i2c-core.c2
-rw-r--r--drivers/mfd/ab8500-gpadc.c8
-rw-r--r--drivers/mmc/core/bus.c2
-rw-r--r--drivers/mmc/core/sdio_bus.c2
-rw-r--r--drivers/pci/pci-driver.c14
-rw-r--r--drivers/scsi/scsi_pm.c11
-rw-r--r--drivers/sh/pm_runtime.c2
-rw-r--r--drivers/spi/spi.c2
-rw-r--r--drivers/tty/serial/mfd.c9
-rw-r--r--drivers/usb/core/driver.c3
-rw-r--r--drivers/usb/core/port.c1
-rw-r--r--include/linux/pm_runtime.h2
23 files changed, 28 insertions, 92 deletions
diff --git a/Documentation/power/runtime_pm.txt b/Documentation/power/runtime_pm.txt
index 6c9f5d9aa115..6c470c71ba27 100644
--- a/Documentation/power/runtime_pm.txt
+++ b/Documentation/power/runtime_pm.txt
@@ -660,11 +660,6 @@ Subsystems may wish to conserve code space by using the set of generic power
management callbacks provided by the PM core, defined in
driver/base/power/generic_ops.c:
- int pm_generic_runtime_idle(struct device *dev);
- - invoke the ->runtime_idle() callback provided by the driver of this
- device, if defined, and call pm_runtime_suspend() for this device if the
- return value is 0 or the callback is not defined
-
int pm_generic_runtime_suspend(struct device *dev);
- invoke the ->runtime_suspend() callback provided by the driver of this
device and return its result, or return -EINVAL if not defined
diff --git a/arch/arm/mach-omap2/omap_device.c b/arch/arm/mach-omap2/omap_device.c
index e6d230700b2b..e37feb2f05a3 100644
--- a/arch/arm/mach-omap2/omap_device.c
+++ b/arch/arm/mach-omap2/omap_device.c
@@ -591,11 +591,6 @@ static int _od_runtime_suspend(struct device *dev)
return ret;
}
-static int _od_runtime_idle(struct device *dev)
-{
- return pm_generic_runtime_idle(dev);
-}
-
static int _od_runtime_resume(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
@@ -653,7 +648,7 @@ static int _od_resume_noirq(struct device *dev)
struct dev_pm_domain omap_device_pm_domain = {
.ops = {
SET_RUNTIME_PM_OPS(_od_runtime_suspend, _od_runtime_resume,
- _od_runtime_idle)
+ NULL)
USE_PLATFORM_PM_SLEEP_OPS
.suspend_noirq = _od_suspend_noirq,
.resume_noirq = _od_resume_noirq,
diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c
index bc493aa3af19..1eb8b6258786 100644
--- a/drivers/acpi/device_pm.c
+++ b/drivers/acpi/device_pm.c
@@ -886,7 +886,6 @@ static struct dev_pm_domain acpi_general_pm_domain = {
#ifdef CONFIG_PM_RUNTIME
.runtime_suspend = acpi_subsys_runtime_suspend,
.runtime_resume = acpi_subsys_runtime_resume,
- .runtime_idle = pm_generic_runtime_idle,
#endif
#ifdef CONFIG_PM_SLEEP
.prepare = acpi_subsys_prepare,
diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c
index cdbad3a454a0..c6707278a6bb 100644
--- a/drivers/amba/bus.c
+++ b/drivers/amba/bus.c
@@ -284,7 +284,7 @@ static const struct dev_pm_ops amba_pm = {
SET_RUNTIME_PM_OPS(
amba_pm_runtime_suspend,
amba_pm_runtime_resume,
- pm_generic_runtime_idle
+ NULL
)
};
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 63c743baf920..84e3b62aa368 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -5430,7 +5430,7 @@ static int ata_port_runtime_idle(struct device *dev)
return -EBUSY;
}
- return pm_runtime_suspend(dev);
+ return 0;
}
static int ata_port_runtime_suspend(struct device *dev)
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index 9eda84246ffd..96a930387ebc 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -888,7 +888,6 @@ int platform_pm_restore(struct device *dev)
static const struct dev_pm_ops platform_dev_pm_ops = {
.runtime_suspend = pm_generic_runtime_suspend,
.runtime_resume = pm_generic_runtime_resume,
- .runtime_idle = pm_generic_runtime_idle,
USE_PLATFORM_PM_SLEEP_OPS
};
diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c
index 7072404c8b6d..bfb8955c406c 100644
--- a/drivers/base/power/domain.c
+++ b/drivers/base/power/domain.c
@@ -2143,7 +2143,6 @@ void pm_genpd_init(struct generic_pm_domain *genpd,
genpd->max_off_time_changed = true;
genpd->domain.ops.runtime_suspend = pm_genpd_runtime_suspend;
genpd->domain.ops.runtime_resume = pm_genpd_runtime_resume;
- genpd->domain.ops.runtime_idle = pm_generic_runtime_idle;
genpd->domain.ops.prepare = pm_genpd_prepare;
genpd->domain.ops.suspend = pm_genpd_suspend;
genpd->domain.ops.suspend_late = pm_genpd_suspend_late;
diff --git a/drivers/base/power/generic_ops.c b/drivers/base/power/generic_ops.c
index bfd898b8988e..5ee030a864f9 100644
--- a/drivers/base/power/generic_ops.c
+++ b/drivers/base/power/generic_ops.c
@@ -12,29 +12,6 @@
#ifdef CONFIG_PM_RUNTIME
/**
- * pm_generic_runtime_idle - Generic runtime idle callback for subsystems.
- * @dev: Device to handle.
- *
- * If PM operations are defined for the @dev's driver and they include
- * ->runtime_idle(), execute it and return its error code, if nonzero.
- * Otherwise, execute pm_runtime_suspend() for the device and return 0.
- */
-int pm_generic_runtime_idle(struct device *dev)
-{
- const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
-
- if (pm && pm->runtime_idle) {
- int ret = pm->runtime_idle(dev);
- if (ret)
- return ret;
- }
-
- pm_runtime_suspend(dev);
- return 0;
-}
-EXPORT_SYMBOL_GPL(pm_generic_runtime_idle);
-
-/**
* pm_generic_runtime_suspend - Generic runtime suspend callback for subsystems.
* @dev: Device to suspend.
*
diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
index ef13ad08afb2..268a35097578 100644
--- a/drivers/base/power/runtime.c
+++ b/drivers/base/power/runtime.c
@@ -293,11 +293,8 @@ static int rpm_idle(struct device *dev, int rpmflags)
/* Pending requests need to be canceled. */
dev->power.request = RPM_REQ_NONE;
- if (dev->power.no_callbacks) {
- /* Assume ->runtime_idle() callback would have suspended. */
- retval = rpm_suspend(dev, rpmflags);
+ if (dev->power.no_callbacks)
goto out;
- }
/* Carry out an asynchronous or a synchronous idle notification. */
if (rpmflags & RPM_ASYNC) {
@@ -306,7 +303,8 @@ static int rpm_idle(struct device *dev, int rpmflags)
dev->power.request_pending = true;
queue_work(pm_wq, &dev->power.work);
}
- goto out;
+ trace_rpm_return_int(dev, _THIS_IP_, 0);
+ return 0;
}
dev->power.idle_notification = true;
@@ -326,14 +324,14 @@ static int rpm_idle(struct device *dev, int rpmflags)
callback = dev->driver->pm->runtime_idle;
if (callback)
- __rpm_callback(callback, dev);
+ retval = __rpm_callback(callback, dev);
dev->power.idle_notification = false;
wake_up_all(&dev->power.wait_queue);
out:
trace_rpm_return_int(dev, _THIS_IP_, retval);
- return retval;
+ return retval ? retval : rpm_suspend(dev, rpmflags);
}
/**
diff --git a/drivers/dma/intel_mid_dma.c b/drivers/dma/intel_mid_dma.c
index a0de82e21a7c..a975ebebea8a 100644
--- a/drivers/dma/intel_mid_dma.c
+++ b/drivers/dma/intel_mid_dma.c
@@ -1405,7 +1405,7 @@ static int dma_runtime_idle(struct device *dev)
return -EAGAIN;
}
- return pm_schedule_suspend(dev, 0);
+ return 0;
}
/******************************************************************************
diff --git a/drivers/gpio/gpio-langwell.c b/drivers/gpio/gpio-langwell.c
index 62ef10a641c4..89d0d2a3b1bb 100644
--- a/drivers/gpio/gpio-langwell.c
+++ b/drivers/gpio/gpio-langwell.c
@@ -305,11 +305,7 @@ static const struct irq_domain_ops lnw_gpio_irq_ops = {
static int lnw_gpio_runtime_idle(struct device *dev)
{
- int err = pm_schedule_suspend(dev, 500);
-
- if (!err)
- return 0;
-
+ pm_schedule_suspend(dev, 500);
return -EBUSY;
}
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index 48e31ed69dbf..f32ca293ae0e 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -435,7 +435,7 @@ static const struct dev_pm_ops i2c_device_pm_ops = {
SET_RUNTIME_PM_OPS(
pm_generic_runtime_suspend,
pm_generic_runtime_resume,
- pm_generic_runtime_idle
+ NULL
)
};
diff --git a/drivers/mfd/ab8500-gpadc.c b/drivers/mfd/ab8500-gpadc.c
index 13f7866de46e..3598b0ecf8c7 100644
--- a/drivers/mfd/ab8500-gpadc.c
+++ b/drivers/mfd/ab8500-gpadc.c
@@ -886,12 +886,6 @@ static int ab8500_gpadc_runtime_resume(struct device *dev)
return ret;
}
-static int ab8500_gpadc_runtime_idle(struct device *dev)
-{
- pm_runtime_suspend(dev);
- return 0;
-}
-
static int ab8500_gpadc_suspend(struct device *dev)
{
struct ab8500_gpadc *gpadc = dev_get_drvdata(dev);
@@ -1039,7 +1033,7 @@ static int ab8500_gpadc_remove(struct platform_device *pdev)
static const struct dev_pm_ops ab8500_gpadc_pm_ops = {
SET_RUNTIME_PM_OPS(ab8500_gpadc_runtime_suspend,
ab8500_gpadc_runtime_resume,
- ab8500_gpadc_runtime_idle)
+ NULL)
SET_SYSTEM_SLEEP_PM_OPS(ab8500_gpadc_suspend,
ab8500_gpadc_resume)
diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c
index e219c97a02a4..9d5c71125576 100644
--- a/drivers/mmc/core/bus.c
+++ b/drivers/mmc/core/bus.c
@@ -164,7 +164,7 @@ static int mmc_runtime_resume(struct device *dev)
static int mmc_runtime_idle(struct device *dev)
{
- return pm_runtime_suspend(dev);
+ return 0;
}
#endif /* !CONFIG_PM_RUNTIME */
diff --git a/drivers/mmc/core/sdio_bus.c b/drivers/mmc/core/sdio_bus.c
index 546c67c2bbbf..6d67492a9247 100644
--- a/drivers/mmc/core/sdio_bus.c
+++ b/drivers/mmc/core/sdio_bus.c
@@ -211,7 +211,7 @@ static const struct dev_pm_ops sdio_bus_pm_ops = {
SET_RUNTIME_PM_OPS(
pm_generic_runtime_suspend,
pm_generic_runtime_resume,
- pm_generic_runtime_idle
+ NULL
)
};
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index 79277fb36c6b..e6515e21afa3 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -1050,26 +1050,22 @@ static int pci_pm_runtime_idle(struct device *dev)
{
struct pci_dev *pci_dev = to_pci_dev(dev);
const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
+ int ret = 0;
/*
* If pci_dev->driver is not set (unbound), the device should
* always remain in D0 regardless of the runtime PM status
*/
if (!pci_dev->driver)
- goto out;
+ return 0;
if (!pm)
return -ENOSYS;
- if (pm->runtime_idle) {
- int ret = pm->runtime_idle(dev);
- if (ret)
- return ret;
- }
+ if (pm->runtime_idle)
+ ret = pm->runtime_idle(dev);
-out:
- pm_runtime_suspend(dev);
- return 0;
+ return ret;
}
#else /* !CONFIG_PM_RUNTIME */
diff --git a/drivers/scsi/scsi_pm.c b/drivers/scsi/scsi_pm.c
index 42539ee2cb11..4c5aabe21755 100644
--- a/drivers/scsi/scsi_pm.c
+++ b/drivers/scsi/scsi_pm.c
@@ -229,8 +229,6 @@ static int scsi_runtime_resume(struct device *dev)
static int scsi_runtime_idle(struct device *dev)
{
- int err;
-
dev_dbg(dev, "scsi_runtime_idle\n");
/* Insert hooks here for targets, hosts, and transport classes */
@@ -240,14 +238,11 @@ static int scsi_runtime_idle(struct device *dev)
if (sdev->request_queue->dev) {
pm_runtime_mark_last_busy(dev);
- err = pm_runtime_autosuspend(dev);
- } else {
- err = pm_runtime_suspend(dev);
+ pm_runtime_autosuspend(dev);
+ return -EBUSY;
}
- } else {
- err = pm_runtime_suspend(dev);
}
- return err;
+ return 0;
}
int scsi_autopm_get_device(struct scsi_device *sdev)
diff --git a/drivers/sh/pm_runtime.c b/drivers/sh/pm_runtime.c
index afe9282629b9..8afa5a4589f2 100644
--- a/drivers/sh/pm_runtime.c
+++ b/drivers/sh/pm_runtime.c
@@ -25,7 +25,7 @@
static int default_platform_runtime_idle(struct device *dev)
{
/* suspend synchronously to disable clocks immediately */
- return pm_runtime_suspend(dev);
+ return 0;
}
static struct dev_pm_domain default_pm_domain = {
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 32b7bb111eb6..095cfaded1c0 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -223,7 +223,7 @@ static const struct dev_pm_ops spi_pm = {
SET_RUNTIME_PM_OPS(
pm_generic_runtime_suspend,
pm_generic_runtime_resume,
- pm_generic_runtime_idle
+ NULL
)
};
diff --git a/drivers/tty/serial/mfd.c b/drivers/tty/serial/mfd.c
index 5f4765a7a5c5..5dfcf3bae23a 100644
--- a/drivers/tty/serial/mfd.c
+++ b/drivers/tty/serial/mfd.c
@@ -1248,13 +1248,8 @@ static int serial_hsu_resume(struct pci_dev *pdev)
#ifdef CONFIG_PM_RUNTIME
static int serial_hsu_runtime_idle(struct device *dev)
{
- int err;
-
- err = pm_schedule_suspend(dev, 500);
- if (err)
- return -EBUSY;
-
- return 0;
+ pm_schedule_suspend(dev, 500);
+ return -EBUSY;
}
static int serial_hsu_runtime_suspend(struct device *dev)
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index 6eab440e1542..7609ac4aed1c 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -1765,7 +1765,8 @@ int usb_runtime_idle(struct device *dev)
*/
if (autosuspend_check(udev) == 0)
pm_runtime_autosuspend(dev);
- return 0;
+ /* Tell the core not to suspend it, though. */
+ return -EBUSY;
}
int usb_set_usb2_hardware_lpm(struct usb_device *udev, int enable)
diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c
index b8bad294eeb8..8c1b2c509467 100644
--- a/drivers/usb/core/port.c
+++ b/drivers/usb/core/port.c
@@ -141,7 +141,6 @@ static const struct dev_pm_ops usb_port_pm_ops = {
#ifdef CONFIG_PM_RUNTIME
.runtime_suspend = usb_port_runtime_suspend,
.runtime_resume = usb_port_runtime_resume,
- .runtime_idle = pm_generic_runtime_idle,
#endif
};
diff --git a/include/linux/pm_runtime.h b/include/linux/pm_runtime.h
index 7d7e09efff9b..6fa7cea25da9 100644
--- a/include/linux/pm_runtime.h
+++ b/include/linux/pm_runtime.h
@@ -37,7 +37,6 @@ extern void pm_runtime_enable(struct device *dev);
extern void __pm_runtime_disable(struct device *dev, bool check_resume);
extern void pm_runtime_allow(struct device *dev);
extern void pm_runtime_forbid(struct device *dev);
-extern int pm_generic_runtime_idle(struct device *dev);
extern int pm_generic_runtime_suspend(struct device *dev);
extern int pm_generic_runtime_resume(struct device *dev);
extern void pm_runtime_no_callbacks(struct device *dev);
@@ -143,7 +142,6 @@ static inline bool pm_runtime_active(struct device *dev) { return true; }
static inline bool pm_runtime_status_suspended(struct device *dev) { return false; }
static inline bool pm_runtime_enabled(struct device *dev) { return false; }
-static inline int pm_generic_runtime_idle(struct device *dev) { return 0; }
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 void pm_runtime_no_callbacks(struct device *dev) {}