Commit 94d76d5de38d7502c3e78fcd6bf50da95e3e0361
1 parent
45c36462ae
Exists in
master
and in
20 other branches
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>
Showing 1 changed file with 17 additions and 2 deletions Side-by-side Diff
drivers/base/platform.c
... | ... | @@ -484,8 +484,16 @@ |
484 | 484 | { |
485 | 485 | struct platform_driver *drv = to_platform_driver(_dev->driver); |
486 | 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 | |
491 | 499 | static int platform_drv_probe_fail(struct device *_dev) |
492 | 500 | |
... | ... | @@ -497,8 +505,13 @@ |
497 | 505 | { |
498 | 506 | struct platform_driver *drv = to_platform_driver(_dev->driver); |
499 | 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 | |
504 | 517 | static void platform_drv_shutdown(struct device *_dev) |
... | ... | @@ -507,6 +520,8 @@ |
507 | 520 | struct platform_device *dev = to_platform_device(_dev); |
508 | 521 | |
509 | 522 | drv->shutdown(dev); |
523 | + if (ACPI_HANDLE(_dev)) | |
524 | + acpi_dev_pm_detach(_dev, true); | |
510 | 525 | } |
511 | 526 | |
512 | 527 | /** |