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@xxxxxxx] > 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@xxxxxxxxx> > > 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@xxxxxxxxx> > --- > 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); > } > > /** ��.n��������+%������w��{.n�����{�����ܨ}���Ơz�j:+v�����w����ޙ��&�)ߡ�a����z�ޗ���ݢj��w�f