Skip to content

Commit

Permalink
platform / ACPI: Attach/detach ACPI PM during probe/remove/shutdown
Browse files Browse the repository at this point in the history
Drivers usually expect that the devices they are supposed to handle
will be operational when their .probe() routines are called, but that
need not be the case on some ACPI-based systems with ACPI-based
device enumeration where the BIOSes don't put devices into D0 by
default.  To work around this problem it is sufficient to change
bus type .probe() routines to ensure that devices will be powered
on before the drivers' .probe() routines run (and their .remove()
and .shutdown() routines accordingly).

Modify platform_drv_probe() to run acpi_dev_pm_attach() for devices
whose ACPI handles are present, so that ACPI power management is used
to change their power states.  Analogously, modify
platform_drv_remove() and platform_drv_shutdown() to call
acpi_dev_pm_detach() for those devices, so that they are not subject
to ACPI PM any more.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Tested-by: Mika Westerberg <mika.westerberg@linux.intel.com>
  • Loading branch information
Rafael J. Wysocki committed Nov 27, 2012
1 parent 45c3646 commit 94d76d5
Showing 1 changed file with 17 additions and 2 deletions.
19 changes: 17 additions & 2 deletions drivers/base/platform.c
Original file line number Diff line number Diff line change
Expand Up @@ -484,8 +484,16 @@ static int platform_drv_probe(struct device *_dev)
{
struct platform_driver *drv = to_platform_driver(_dev->driver);
struct platform_device *dev = to_platform_device(_dev);
int ret;

return drv->probe(dev);
if (ACPI_HANDLE(_dev))
acpi_dev_pm_attach(_dev, true);

ret = drv->probe(dev);
if (ret && ACPI_HANDLE(_dev))
acpi_dev_pm_detach(_dev, true);

return ret;
}

static int platform_drv_probe_fail(struct device *_dev)
Expand All @@ -497,8 +505,13 @@ static int platform_drv_remove(struct device *_dev)
{
struct platform_driver *drv = to_platform_driver(_dev->driver);
struct platform_device *dev = to_platform_device(_dev);
int ret;

return drv->remove(dev);
ret = drv->remove(dev);
if (ACPI_HANDLE(_dev))
acpi_dev_pm_detach(_dev, true);

return ret;
}

static void platform_drv_shutdown(struct device *_dev)
Expand All @@ -507,6 +520,8 @@ static void platform_drv_shutdown(struct device *_dev)
struct platform_device *dev = to_platform_device(_dev);

drv->shutdown(dev);
if (ACPI_HANDLE(_dev))
acpi_dev_pm_detach(_dev, true);
}

/**
Expand Down

0 comments on commit 94d76d5

Please sign in to comment.