aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base/platform.c
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2012-11-26 04:04:53 -0500
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2012-11-27 07:44:45 -0500
commit94d76d5de38d7502c3e78fcd6bf50da95e3e0361 (patch)
tree855aec097310ea4e59ef843d748d8e87e4eeac21 /drivers/base/platform.c
parent45c36462aef0cccadb7755ea4edc78d13334a2be (diff)
platform / ACPI: Attach/detach ACPI PM during probe/remove/shutdown
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>
Diffstat (limited to 'drivers/base/platform.c')
-rw-r--r--drivers/base/platform.c19
1 files changed, 17 insertions, 2 deletions
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index 49fd96e23460..b2ee3bcd5a41 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -484,8 +484,16 @@ static int platform_drv_probe(struct device *_dev)
484{ 484{
485 struct platform_driver *drv = to_platform_driver(_dev->driver); 485 struct platform_driver *drv = to_platform_driver(_dev->driver);
486 struct platform_device *dev = to_platform_device(_dev); 486 struct platform_device *dev = to_platform_device(_dev);
487 int ret;
487 488
488 return drv->probe(dev); 489 if (ACPI_HANDLE(_dev))
490 acpi_dev_pm_attach(_dev, true);
491
492 ret = drv->probe(dev);
493 if (ret && ACPI_HANDLE(_dev))
494 acpi_dev_pm_detach(_dev, true);
495
496 return ret;
489} 497}
490 498
491static int platform_drv_probe_fail(struct device *_dev) 499static int platform_drv_probe_fail(struct device *_dev)
@@ -497,8 +505,13 @@ static int platform_drv_remove(struct device *_dev)
497{ 505{
498 struct platform_driver *drv = to_platform_driver(_dev->driver); 506 struct platform_driver *drv = to_platform_driver(_dev->driver);
499 struct platform_device *dev = to_platform_device(_dev); 507 struct platform_device *dev = to_platform_device(_dev);
508 int ret;
500 509
501 return drv->remove(dev); 510 ret = drv->remove(dev);
511 if (ACPI_HANDLE(_dev))
512 acpi_dev_pm_detach(_dev, true);
513
514 return ret;
502} 515}
503 516
504static void platform_drv_shutdown(struct device *_dev) 517static void platform_drv_shutdown(struct device *_dev)
@@ -507,6 +520,8 @@ static void platform_drv_shutdown(struct device *_dev)
507 struct platform_device *dev = to_platform_device(_dev); 520 struct platform_device *dev = to_platform_device(_dev);
508 521
509 drv->shutdown(dev); 522 drv->shutdown(dev);
523 if (ACPI_HANDLE(_dev))
524 acpi_dev_pm_detach(_dev, true);
510} 525}
511 526
512/** 527/**