From patchwork Mon Sep 14 16:09:26 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alan Jenkins X-Patchwork-Id: 47329 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 n8EGA0Di013417 for ; Mon, 14 Sep 2009 16:10:00 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755071AbZINQJf (ORCPT ); Mon, 14 Sep 2009 12:09:35 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1756016AbZINQJf (ORCPT ); Mon, 14 Sep 2009 12:09:35 -0400 Received: from mxout-08.mxes.net ([216.86.168.183]:63743 "EHLO mxout-08.mxes.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755071AbZINQJe (ORCPT ); Mon, 14 Sep 2009 12:09:34 -0400 Received: from localhost.localdomain (unknown [86.53.68.233]) by smtp.mxes.net (Postfix) with ESMTPA id D61B5509DE; Mon, 14 Sep 2009 12:09:36 -0400 (EDT) From: Alan Jenkins To: lenb@kernel.org Cc: bjorn.helgaas@hp.com, linux-acpi@vger.kernel.org, Alan Jenkins Subject: [PATCH 1/4] ACPI: Remember to clear acpi_dev->driver after calling ops.remove() Date: Mon, 14 Sep 2009 17:09:26 +0100 Message-Id: <1252944569-29799-2-git-send-email-alan-jenkins@tuffmail.co.uk> X-Mailer: git-send-email 1.6.3.2 In-Reply-To: <1252944569-29799-1-git-send-email-alan-jenkins@tuffmail.co.uk> References: <1252944569-29799-1-git-send-email-alan-jenkins@tuffmail.co.uk> 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 can't be good. Signed-off-by: Alan Jenkins 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;