From patchwork Sat Sep 12 15:35:49 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alan Jenkins X-Patchwork-Id: 47086 Received: from vger.kernel.org (vger.kernel.org [209.132.176.167]) by demeter.kernel.org (8.14.2/8.14.2) with ESMTP id n8CFZsOF032432 for ; Sat, 12 Sep 2009 15:35:54 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754680AbZILPfu (ORCPT ); Sat, 12 Sep 2009 11:35:50 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1754745AbZILPfu (ORCPT ); Sat, 12 Sep 2009 11:35:50 -0400 Received: from ey-out-2122.google.com ([74.125.78.24]:54626 "EHLO ey-out-2122.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754680AbZILPft (ORCPT ); Sat, 12 Sep 2009 11:35:49 -0400 Received: by ey-out-2122.google.com with SMTP id 4so220345eyf.5 for ; Sat, 12 Sep 2009 08:35:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=googlemail.com; s=gamma; h=domainkey-signature:received:received:sender:message-id:date:from :user-agent:mime-version:to:cc:subject:content-type :content-transfer-encoding; bh=0ZthYqdNC2BfozS9qMIeCbFD3mpcPWG9/RQ+nUMT924=; b=haaNt+Ln2UIrmD3jnsTB8Si+gLk6ihmsR6RPrzUHHINGdqnjnSZSEJS8/xWZMLfsei iFkVKPtQ1Hbxlcck2iqhuu5/oCKIDhx0a5c6Ousq3CUkc/qof8spB9IfM/G20jg/iLo+ zntaVyOw0Lsn1Vw2pAvRq4JlawXeUUFOx5g7o= DomainKey-Signature: a=rsa-sha1; c=nofws; d=googlemail.com; s=gamma; h=sender:message-id:date:from:user-agent:mime-version:to:cc:subject :content-type:content-transfer-encoding; b=bvqCxDBpa1tGFbxxbxfoHpEos9pdv0MGn67gmvqo2RMxiKn+mQBNmwz4iDIHcCeuCr WC235sSpz0roj8K787TzvfWGMbY/zU/kqWtZFwYE68ytoxxnoC72RzGwV2LgTi6GzyG0 vX3VM/43E4lM5PDTkKhR7l4XcxCPx1uPg/fLo= Received: by 10.210.15.14 with SMTP id 14mr1063164ebo.49.1252769751693; Sat, 12 Sep 2009 08:35:51 -0700 (PDT) Received: from ?192.168.0.5? ([86.53.68.233]) by mx.google.com with ESMTPS id 10sm1187437eyd.23.2009.09.12.08.35.50 (version=SSLv3 cipher=RC4-MD5); Sat, 12 Sep 2009 08:35:50 -0700 (PDT) Message-ID: <4AABBFD5.1000009@tuffmail.co.uk> Date: Sat, 12 Sep 2009 16:35:49 +0100 From: Alan Jenkins User-Agent: Thunderbird 2.0.0.21 (X11/20090318) MIME-Version: 1.0 To: Len Brown CC: Bjorn Helgaas , linux acpi Subject: [PATCH] ACPI: Remember to clear acpi_dev->driver after calling ops.remove() Sender: linux-acpi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-acpi@vger.kernel.org If an error occurs while binding a driver to a device and we call remove(), we should also clear acpi->driver and acpi_dev->driverdata. Otherwise bad things will happen e.g. we will invoke the suspend() driver callback when the system is suspended, even though the driver thinks it has been unbound from the device. Also check the return value of acpi_start_single_object(). I'm not sure what will happen if we claim success despite seeing ops.start() fail and then calling ops.remove(), but it's not a good idea. Signed-off-by: Alan Jenkins CC: Bjorn Helgaas Reviewed-by: Bjorn Helgaas --- drivers/acpi/scan.c | 45 +++++++++++++++++++++++++++------------------ 1 files changed, 27 insertions(+), 18 deletions(-) diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 957620b..cde179e 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -423,26 +423,33 @@ static int acpi_device_probe(struct device * dev) int ret; ret = acpi_bus_driver_init(acpi_dev, acpi_drv); - if (!ret) { - if (acpi_dev->bus_ops.acpi_op_start) - acpi_start_single_object(acpi_dev); - - if (acpi_drv->ops.notify) { - ret = acpi_device_install_notify_handler(acpi_dev); - if (ret) { - if (acpi_drv->ops.remove) - acpi_drv->ops.remove(acpi_dev, - acpi_dev->removal_type); - return ret; - } - } + if (ret) + return ret; - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Found driver [%s] for device [%s]\n", - acpi_drv->name, acpi_dev->pnp.bus_id)); - get_device(dev); + if (acpi_dev->bus_ops.acpi_op_start) { + ret = acpi_start_single_object(acpi_dev); + if (ret) + return ret; } - return ret; + + if (acpi_drv->ops.notify) { + ret = acpi_device_install_notify_handler(acpi_dev); + if (ret) { + if (acpi_drv->ops.remove) + acpi_drv->ops.remove(acpi_dev, + acpi_dev->removal_type); + acpi_dev->driver = NULL; + acpi_dev->driver_data = NULL; + return ret; + } + } + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Found driver [%s] for device [%s]\n", + acpi_drv->name, acpi_dev->pnp.bus_id)); + get_device(dev); + + return 0; } static int acpi_device_remove(struct device * dev) @@ -617,6 +624,8 @@ static int acpi_start_single_object(struct acpi_device *device) result = driver->ops.start(device); if (result && driver->ops.remove) driver->ops.remove(device, ACPI_BUS_REMOVAL_NORMAL); + device->driver = NULL; + device->driver_data = NULL; } return result;