Commit 94d76d5de38d7502c3e78fcd6bf50da95e3e0361

Authored by Rafael J. Wysocki
1 parent 45c36462ae

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 /**