summaryrefslogtreecommitdiffstats
path: root/drivers/acpi
diff options
context:
space:
mode:
authorRafael J. Wysocki <rjw@sisk.pl>2012-06-27 23:25:59 +0200
committerRafael J. Wysocki <rjw@sisk.pl>2012-07-01 13:30:59 +0200
commit67699c5f0c68f5dc49e92b172d372c99cdd2bf09 (patch)
tree91be1b7151671a8066cabba083ec68b4832d164f /drivers/acpi
parentACPI / PM: Make acpi_bus_type use struct dev_pm_ops for PM handling (diff)
downloadlinux-67699c5f0c68f5dc49e92b172d372c99cdd2bf09.tar.xz
linux-67699c5f0c68f5dc49e92b172d372c99cdd2bf09.zip
ACPI / PM: Make acpi_bus_type use driver struct dev_pm_ops callbacks
Modify acpi_bus_type so that it executes PM callbacks provided by drivers through their struct dev_pm_ops objects, if present, while still allowing the legacy ACPI PM callbacks to take precedence. This will make it possible to convert ACPI drivers one by one to handling PM through struct dev_pm_ops instead of the legacy way. The code added by this change is temporary and will be removed when all of the drivers in question have been switched over to the PM handling based on struct dev_pm_ops. Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Diffstat (limited to 'drivers/acpi')
-rw-r--r--drivers/acpi/scan.c60
1 files changed, 47 insertions, 13 deletions
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 7c37be53334d..af924ba85148 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -290,27 +290,61 @@ static void acpi_device_release(struct device *dev)
kfree(acpi_dev);
}
-static int acpi_device_suspend(struct device *dev)
+#define ACPI_DEV_PM_CALLBACK(dev, callback, legacy_cb) \
+({ \
+ struct acpi_device *__acpi_dev = to_acpi_device(dev); \
+ struct acpi_driver *__acpi_drv = __acpi_dev->driver; \
+ struct device_driver *__drv = dev->driver; \
+ int __ret; \
+ \
+ if (__acpi_drv && __acpi_drv->ops.legacy_cb) \
+ __ret = __acpi_drv->ops.legacy_cb(__acpi_dev); \
+ else if (__drv && __drv->pm && __drv->pm->callback) \
+ __ret = __drv->pm->callback(dev); \
+ else \
+ __ret = 0; \
+ \
+ __ret; \
+})
+
+static int acpi_pm_suspend(struct device *dev)
{
- struct acpi_device *acpi_dev = to_acpi_device(dev);
- struct acpi_driver *acpi_drv = acpi_dev->driver;
+ return ACPI_DEV_PM_CALLBACK(dev, suspend, suspend);
+}
- if (acpi_drv && acpi_drv->ops.suspend)
- return acpi_drv->ops.suspend(acpi_dev);
- return 0;
+static int acpi_pm_resume(struct device *dev)
+{
+ return ACPI_DEV_PM_CALLBACK(dev, resume, resume);
}
-static int acpi_device_resume(struct device *dev)
+static int acpi_pm_freeze(struct device *dev)
{
- struct acpi_device *acpi_dev = to_acpi_device(dev);
- struct acpi_driver *acpi_drv = acpi_dev->driver;
+ return ACPI_DEV_PM_CALLBACK(dev, freeze, suspend);
+}
- if (acpi_drv && acpi_drv->ops.resume)
- return acpi_drv->ops.resume(acpi_dev);
- return 0;
+static int acpi_pm_thaw(struct device *dev)
+{
+ return ACPI_DEV_PM_CALLBACK(dev, thaw, resume);
+}
+
+static int acpi_pm_poweroff(struct device *dev)
+{
+ return ACPI_DEV_PM_CALLBACK(dev, poweroff, suspend);
}
-static SIMPLE_DEV_PM_OPS(acpi_bus_pm, acpi_device_suspend, acpi_device_resume);
+static int acpi_pm_restore(struct device *dev)
+{
+ return ACPI_DEV_PM_CALLBACK(dev, restore, resume);
+}
+
+static const struct dev_pm_ops acpi_bus_pm = {
+ .suspend = acpi_pm_suspend,
+ .resume = acpi_pm_resume,
+ .freeze = acpi_pm_freeze,
+ .thaw = acpi_pm_thaw,
+ .poweroff = acpi_pm_poweroff,
+ .restore = acpi_pm_restore,
+};
static int acpi_bus_match(struct device *dev, struct device_driver *drv)
{