Эх сурвалжийг харах

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>
Rafael J. Wysocki 12 жил өмнө
parent
commit
45f0a85c82

+ 0 - 5
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
 management callbacks provided by the PM core, defined in
 driver/base/power/generic_ops.c:
 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);
   int pm_generic_runtime_suspend(struct device *dev);
     - invoke the ->runtime_suspend() callback provided by the driver of this
     - invoke the ->runtime_suspend() callback provided by the driver of this
       device and return its result, or return -EINVAL if not defined
       device and return its result, or return -EINVAL if not defined

+ 1 - 6
arch/arm/mach-omap2/omap_device.c

@@ -591,11 +591,6 @@ static int _od_runtime_suspend(struct device *dev)
 	return ret;
 	return ret;
 }
 }
 
 
-static int _od_runtime_idle(struct device *dev)
-{
-	return pm_generic_runtime_idle(dev);
-}
-
 static int _od_runtime_resume(struct device *dev)
 static int _od_runtime_resume(struct device *dev)
 {
 {
 	struct platform_device *pdev = to_platform_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 = {
 struct dev_pm_domain omap_device_pm_domain = {
 	.ops = {
 	.ops = {
 		SET_RUNTIME_PM_OPS(_od_runtime_suspend, _od_runtime_resume,
 		SET_RUNTIME_PM_OPS(_od_runtime_suspend, _od_runtime_resume,
-				   _od_runtime_idle)
+				   NULL)
 		USE_PLATFORM_PM_SLEEP_OPS
 		USE_PLATFORM_PM_SLEEP_OPS
 		.suspend_noirq = _od_suspend_noirq,
 		.suspend_noirq = _od_suspend_noirq,
 		.resume_noirq = _od_resume_noirq,
 		.resume_noirq = _od_resume_noirq,

+ 0 - 1
drivers/acpi/device_pm.c

@@ -886,7 +886,6 @@ static struct dev_pm_domain acpi_general_pm_domain = {
 #ifdef CONFIG_PM_RUNTIME
 #ifdef CONFIG_PM_RUNTIME
 		.runtime_suspend = acpi_subsys_runtime_suspend,
 		.runtime_suspend = acpi_subsys_runtime_suspend,
 		.runtime_resume = acpi_subsys_runtime_resume,
 		.runtime_resume = acpi_subsys_runtime_resume,
-		.runtime_idle = pm_generic_runtime_idle,
 #endif
 #endif
 #ifdef CONFIG_PM_SLEEP
 #ifdef CONFIG_PM_SLEEP
 		.prepare = acpi_subsys_prepare,
 		.prepare = acpi_subsys_prepare,

+ 1 - 1
drivers/amba/bus.c

@@ -284,7 +284,7 @@ static const struct dev_pm_ops amba_pm = {
 	SET_RUNTIME_PM_OPS(
 	SET_RUNTIME_PM_OPS(
 		amba_pm_runtime_suspend,
 		amba_pm_runtime_suspend,
 		amba_pm_runtime_resume,
 		amba_pm_runtime_resume,
-		pm_generic_runtime_idle
+		NULL
 	)
 	)
 };
 };
 
 

+ 1 - 1
drivers/ata/libata-core.c

@@ -5430,7 +5430,7 @@ static int ata_port_runtime_idle(struct device *dev)
 				return -EBUSY;
 				return -EBUSY;
 	}
 	}
 
 
-	return pm_runtime_suspend(dev);
+	return 0;
 }
 }
 
 
 static int ata_port_runtime_suspend(struct device *dev)
 static int ata_port_runtime_suspend(struct device *dev)

+ 0 - 1
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 = {
 static const struct dev_pm_ops platform_dev_pm_ops = {
 	.runtime_suspend = pm_generic_runtime_suspend,
 	.runtime_suspend = pm_generic_runtime_suspend,
 	.runtime_resume = pm_generic_runtime_resume,
 	.runtime_resume = pm_generic_runtime_resume,
-	.runtime_idle = pm_generic_runtime_idle,
 	USE_PLATFORM_PM_SLEEP_OPS
 	USE_PLATFORM_PM_SLEEP_OPS
 };
 };
 
 

+ 0 - 1
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->max_off_time_changed = true;
 	genpd->domain.ops.runtime_suspend = pm_genpd_runtime_suspend;
 	genpd->domain.ops.runtime_suspend = pm_genpd_runtime_suspend;
 	genpd->domain.ops.runtime_resume = pm_genpd_runtime_resume;
 	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.prepare = pm_genpd_prepare;
 	genpd->domain.ops.suspend = pm_genpd_suspend;
 	genpd->domain.ops.suspend = pm_genpd_suspend;
 	genpd->domain.ops.suspend_late = pm_genpd_suspend_late;
 	genpd->domain.ops.suspend_late = pm_genpd_suspend_late;

+ 0 - 23
drivers/base/power/generic_ops.c

@@ -11,29 +11,6 @@
 #include <linux/export.h>
 #include <linux/export.h>
 
 
 #ifdef CONFIG_PM_RUNTIME
 #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.
  * pm_generic_runtime_suspend - Generic runtime suspend callback for subsystems.
  * @dev: Device to suspend.
  * @dev: Device to suspend.

+ 5 - 7
drivers/base/power/runtime.c

@@ -293,11 +293,8 @@ static int rpm_idle(struct device *dev, int rpmflags)
 	/* Pending requests need to be canceled. */
 	/* Pending requests need to be canceled. */
 	dev->power.request = RPM_REQ_NONE;
 	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;
 		goto out;
-	}
 
 
 	/* Carry out an asynchronous or a synchronous idle notification. */
 	/* Carry out an asynchronous or a synchronous idle notification. */
 	if (rpmflags & RPM_ASYNC) {
 	if (rpmflags & RPM_ASYNC) {
@@ -306,7 +303,8 @@ static int rpm_idle(struct device *dev, int rpmflags)
 			dev->power.request_pending = true;
 			dev->power.request_pending = true;
 			queue_work(pm_wq, &dev->power.work);
 			queue_work(pm_wq, &dev->power.work);
 		}
 		}
-		goto out;
+		trace_rpm_return_int(dev, _THIS_IP_, 0);
+		return 0;
 	}
 	}
 
 
 	dev->power.idle_notification = true;
 	dev->power.idle_notification = true;
@@ -326,14 +324,14 @@ static int rpm_idle(struct device *dev, int rpmflags)
 		callback = dev->driver->pm->runtime_idle;
 		callback = dev->driver->pm->runtime_idle;
 
 
 	if (callback)
 	if (callback)
-		__rpm_callback(callback, dev);
+		retval = __rpm_callback(callback, dev);
 
 
 	dev->power.idle_notification = false;
 	dev->power.idle_notification = false;
 	wake_up_all(&dev->power.wait_queue);
 	wake_up_all(&dev->power.wait_queue);
 
 
  out:
  out:
 	trace_rpm_return_int(dev, _THIS_IP_, retval);
 	trace_rpm_return_int(dev, _THIS_IP_, retval);
-	return retval;
+	return retval ? retval : rpm_suspend(dev, rpmflags);
 }
 }
 
 
 /**
 /**

+ 1 - 1
drivers/dma/intel_mid_dma.c

@@ -1405,7 +1405,7 @@ static int dma_runtime_idle(struct device *dev)
 			return -EAGAIN;
 			return -EAGAIN;
 	}
 	}
 
 
-	return pm_schedule_suspend(dev, 0);
+	return 0;
 }
 }
 
 
 /******************************************************************************
 /******************************************************************************

+ 1 - 5
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)
 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;
 	return -EBUSY;
 }
 }
 
 

+ 1 - 1
drivers/i2c/i2c-core.c

@@ -435,7 +435,7 @@ static const struct dev_pm_ops i2c_device_pm_ops = {
 	SET_RUNTIME_PM_OPS(
 	SET_RUNTIME_PM_OPS(
 		pm_generic_runtime_suspend,
 		pm_generic_runtime_suspend,
 		pm_generic_runtime_resume,
 		pm_generic_runtime_resume,
-		pm_generic_runtime_idle
+		NULL
 	)
 	)
 };
 };
 
 

+ 1 - 7
drivers/mfd/ab8500-gpadc.c

@@ -886,12 +886,6 @@ static int ab8500_gpadc_runtime_resume(struct device *dev)
 	return ret;
 	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)
 static int ab8500_gpadc_suspend(struct device *dev)
 {
 {
 	struct ab8500_gpadc *gpadc = dev_get_drvdata(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 = {
 static const struct dev_pm_ops ab8500_gpadc_pm_ops = {
 	SET_RUNTIME_PM_OPS(ab8500_gpadc_runtime_suspend,
 	SET_RUNTIME_PM_OPS(ab8500_gpadc_runtime_suspend,
 			   ab8500_gpadc_runtime_resume,
 			   ab8500_gpadc_runtime_resume,
-			   ab8500_gpadc_runtime_idle)
+			   NULL)
 	SET_SYSTEM_SLEEP_PM_OPS(ab8500_gpadc_suspend,
 	SET_SYSTEM_SLEEP_PM_OPS(ab8500_gpadc_suspend,
 				ab8500_gpadc_resume)
 				ab8500_gpadc_resume)
 
 

+ 1 - 1
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)
 static int mmc_runtime_idle(struct device *dev)
 {
 {
-	return pm_runtime_suspend(dev);
+	return 0;
 }
 }
 
 
 #endif /* !CONFIG_PM_RUNTIME */
 #endif /* !CONFIG_PM_RUNTIME */

+ 1 - 1
drivers/mmc/core/sdio_bus.c

@@ -211,7 +211,7 @@ static const struct dev_pm_ops sdio_bus_pm_ops = {
 	SET_RUNTIME_PM_OPS(
 	SET_RUNTIME_PM_OPS(
 		pm_generic_runtime_suspend,
 		pm_generic_runtime_suspend,
 		pm_generic_runtime_resume,
 		pm_generic_runtime_resume,
-		pm_generic_runtime_idle
+		NULL
 	)
 	)
 };
 };
 
 

+ 5 - 9
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);
 	struct pci_dev *pci_dev = to_pci_dev(dev);
 	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
 	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
 	 * If pci_dev->driver is not set (unbound), the device should
 	 * always remain in D0 regardless of the runtime PM status
 	 * always remain in D0 regardless of the runtime PM status
 	 */
 	 */
 	if (!pci_dev->driver)
 	if (!pci_dev->driver)
-		goto out;
+		return 0;
 
 
 	if (!pm)
 	if (!pm)
 		return -ENOSYS;
 		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 */
 #else /* !CONFIG_PM_RUNTIME */

+ 3 - 8
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)
 static int scsi_runtime_idle(struct device *dev)
 {
 {
-	int err;
-
 	dev_dbg(dev, "scsi_runtime_idle\n");
 	dev_dbg(dev, "scsi_runtime_idle\n");
 
 
 	/* Insert hooks here for targets, hosts, and transport classes */
 	/* 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) {
 		if (sdev->request_queue->dev) {
 			pm_runtime_mark_last_busy(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)
 int scsi_autopm_get_device(struct scsi_device *sdev)

+ 1 - 1
drivers/sh/pm_runtime.c

@@ -25,7 +25,7 @@
 static int default_platform_runtime_idle(struct device *dev)
 static int default_platform_runtime_idle(struct device *dev)
 {
 {
 	/* suspend synchronously to disable clocks immediately */
 	/* suspend synchronously to disable clocks immediately */
-	return pm_runtime_suspend(dev);
+	return 0;
 }
 }
 
 
 static struct dev_pm_domain default_pm_domain = {
 static struct dev_pm_domain default_pm_domain = {

+ 1 - 1
drivers/spi/spi.c

@@ -223,7 +223,7 @@ static const struct dev_pm_ops spi_pm = {
 	SET_RUNTIME_PM_OPS(
 	SET_RUNTIME_PM_OPS(
 		pm_generic_runtime_suspend,
 		pm_generic_runtime_suspend,
 		pm_generic_runtime_resume,
 		pm_generic_runtime_resume,
-		pm_generic_runtime_idle
+		NULL
 	)
 	)
 };
 };
 
 

+ 2 - 7
drivers/tty/serial/mfd.c

@@ -1248,13 +1248,8 @@ static int serial_hsu_resume(struct pci_dev *pdev)
 #ifdef CONFIG_PM_RUNTIME
 #ifdef CONFIG_PM_RUNTIME
 static int serial_hsu_runtime_idle(struct device *dev)
 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)
 static int serial_hsu_runtime_suspend(struct device *dev)

+ 2 - 1
drivers/usb/core/driver.c

@@ -1765,7 +1765,8 @@ int usb_runtime_idle(struct device *dev)
 	 */
 	 */
 	if (autosuspend_check(udev) == 0)
 	if (autosuspend_check(udev) == 0)
 		pm_runtime_autosuspend(dev);
 		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)
 int usb_set_usb2_hardware_lpm(struct usb_device *udev, int enable)

+ 0 - 1
drivers/usb/core/port.c

@@ -141,7 +141,6 @@ static const struct dev_pm_ops usb_port_pm_ops = {
 #ifdef CONFIG_PM_RUNTIME
 #ifdef CONFIG_PM_RUNTIME
 	.runtime_suspend =	usb_port_runtime_suspend,
 	.runtime_suspend =	usb_port_runtime_suspend,
 	.runtime_resume =	usb_port_runtime_resume,
 	.runtime_resume =	usb_port_runtime_resume,
-	.runtime_idle =		pm_generic_runtime_idle,
 #endif
 #endif
 };
 };
 
 

+ 0 - 2
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_disable(struct device *dev, bool check_resume);
 extern void pm_runtime_allow(struct device *dev);
 extern void pm_runtime_allow(struct device *dev);
 extern void pm_runtime_forbid(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_suspend(struct device *dev);
 extern int pm_generic_runtime_resume(struct device *dev);
 extern int pm_generic_runtime_resume(struct device *dev);
 extern void pm_runtime_no_callbacks(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_status_suspended(struct device *dev) { return false; }
 static inline bool pm_runtime_enabled(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_suspend(struct device *dev) { return 0; }
 static inline int pm_generic_runtime_resume(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) {}
 static inline void pm_runtime_no_callbacks(struct device *dev) {}