From patchwork Sun Nov 25 14:58:14 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rafael Wysocki X-Patchwork-Id: 1799411 Return-Path: X-Original-To: patchwork-linux-acpi@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork1.kernel.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by patchwork1.kernel.org (Postfix) with ESMTP id 71B143FC23 for ; Sun, 25 Nov 2012 14:54:26 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753084Ab2KYOyX (ORCPT ); Sun, 25 Nov 2012 09:54:23 -0500 Received: from ogre.sisk.pl ([193.178.161.156]:36418 "EHLO ogre.sisk.pl" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753065Ab2KYOyX (ORCPT ); Sun, 25 Nov 2012 09:54:23 -0500 Received: from localhost (localhost.localdomain [127.0.0.1]) by ogre.sisk.pl (Postfix) with ESMTP id 6528A1DF0C5; Sun, 25 Nov 2012 15:32:03 +0100 (CET) Received: from ogre.sisk.pl ([127.0.0.1]) by localhost (ogre.sisk.pl [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 00922-06; Sun, 25 Nov 2012 15:31:53 +0100 (CET) Received: from vostro.rjw.lan (afer50.neoplus.adsl.tpnet.pl [95.49.121.50]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by ogre.sisk.pl (Postfix) with ESMTP id AC546195B5C; Sun, 25 Nov 2012 15:31:53 +0100 (CET) From: "Rafael J. Wysocki" 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" , Aaron Lu , Grant Likely Subject: [PATCH 2/2] platform / ACPI: Attach/detach ACPI PM during probe/remove/shutdown Date: Sun, 25 Nov 2012 15:58:14 +0100 Message-ID: <6227446.8xPtqi6yHi@vostro.rjw.lan> User-Agent: KMail/4.9.3 (Linux/3.7.0-rc6; KDE/4.9.3; x86_64; ; ) In-Reply-To: <1672179.qgDUs0YdYu@vostro.rjw.lan> References: <1672179.qgDUs0YdYu@vostro.rjw.lan> MIME-Version: 1.0 X-Virus-Scanned: amavisd-new at ogre.sisk.pl using MkS_Vir for Linux Sender: linux-acpi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-acpi@vger.kernel.org From: Rafael J. Wysocki 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 Acked-by: Greg Kroah-Hartman --- 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 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); } /**