diff mbox

[2/2] platform / ACPI: Attach/detach ACPI PM during probe/remove/shutdown

Message ID 6227446.8xPtqi6yHi@vostro.rjw.lan (mailing list archive)
State Accepted, archived
Headers show

Commit Message

Rafael Wysocki Nov. 25, 2012, 2:58 p.m. UTC
From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

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 and change their power states to D0
before driver probing.  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>
---
 drivers/base/platform.c |   19 +++++++++++++++++--
 1 file changed, 17 insertions(+), 2 deletions(-)


--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Comments

Greg Kroah-Hartman Nov. 25, 2012, 6:42 p.m. UTC | #1
On Sun, Nov 25, 2012 at 03:58:14PM +0100, Rafael J. Wysocki wrote:
> From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> 
> 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 and change their power states to D0
> before driver probing.  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>
--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Rafael Wysocki Nov. 25, 2012, 7:57 p.m. UTC | #2
On Sunday, November 25, 2012 10:42:25 AM Greg Kroah-Hartman wrote:
> On Sun, Nov 25, 2012 at 03:58:14PM +0100, Rafael J. Wysocki wrote:
> > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > 
> > 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 and change their power states to D0
> > before driver probing.  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>

Thanks!
Lv Zheng Nov. 27, 2012, 5:24 a.m. UTC | #3
It looks cleanest unless more abstractions are introduced for other power management providers.

Best regards/Lv Zheng

> -----Original Message-----

> From: Rafael J. Wysocki [mailto:rjw@sisk.pl]

> Sent: Sunday, November 25, 2012 10:58 PM

> To: LKML

> Cc: Greg Kroah-Hartman; Linux PM list; ACPI Devel Maling List; Zhang, Rui;

> Svahn, Kai; Mika Westerberg; Huang, Ying; Lan, Tianyu; Zheng, Lv; Lu, Aaron;

> Grant Likely

> Subject: [PATCH 2/2] platform / ACPI: Attach/detach ACPI PM during

> probe/remove/shutdown

> 

> From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

> 

> 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 and change their power states to D0 before driver probing.

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

> ---

>  drivers/base/platform.c |   19 +++++++++++++++++--

>  1 file changed, 17 insertions(+), 2 deletions(-)

> 

> Index: linux/drivers/base/platform.c

> ================================================================

> ===

> --- linux.orig/drivers/base/platform.c

> +++ linux/drivers/base/platform.c

> @@ -484,8 +484,16 @@ static int platform_drv_probe(struct 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) @@ -497,8 +505,13

> @@ static int platform_drv_remove(struct de  {

>  	struct platform_driver *drv = to_platform_driver(_dev->driver);

>  	struct platform_device *dev = to_platform_device(_dev);

> +	int ret;

> +

> +	ret = drv->remove(dev);

> +	if (ACPI_HANDLE(_dev))

> +		acpi_dev_pm_detach(_dev, true);

> 

> -	return drv->remove(dev);

> +	return ret;

>  }

> 

>  static void platform_drv_shutdown(struct device *_dev) @@ -507,6 +520,8

> @@ static void platform_drv_shutdown(struct

>  	struct platform_device *dev = to_platform_device(_dev);

> 

>  	drv->shutdown(dev);

> +	if (ACPI_HANDLE(_dev))

> +		acpi_dev_pm_detach(_dev, true);

>  }

> 

>  /**
diff mbox

Patch

Index: linux/drivers/base/platform.c
===================================================================
--- linux.orig/drivers/base/platform.c
+++ linux/drivers/base/platform.c
@@ -484,8 +484,16 @@  static int platform_drv_probe(struct 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)
@@ -497,8 +505,13 @@  static int platform_drv_remove(struct de
 {
 	struct platform_driver *drv = to_platform_driver(_dev->driver);
 	struct platform_device *dev = to_platform_device(_dev);
+	int ret;
+
+	ret = drv->remove(dev);
+	if (ACPI_HANDLE(_dev))
+		acpi_dev_pm_detach(_dev, true);
 
-	return drv->remove(dev);
+	return ret;
 }
 
 static void platform_drv_shutdown(struct device *_dev)
@@ -507,6 +520,8 @@  static void platform_drv_shutdown(struct
 	struct platform_device *dev = to_platform_device(_dev);
 
 	drv->shutdown(dev);
+	if (ACPI_HANDLE(_dev))
+		acpi_dev_pm_detach(_dev, true);
 }
 
 /**