From patchwork Sun Nov 4 12:50:13 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiang Liu X-Patchwork-Id: 197031 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 048E12C00AC for ; Sun, 4 Nov 2012 23:52:23 +1100 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754095Ab2KDMwD (ORCPT ); Sun, 4 Nov 2012 07:52:03 -0500 Received: from mail-pb0-f46.google.com ([209.85.160.46]:46858 "EHLO mail-pb0-f46.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754138Ab2KDMv4 (ORCPT ); Sun, 4 Nov 2012 07:51:56 -0500 Received: by mail-pb0-f46.google.com with SMTP id rr4so3339156pbb.19 for ; Sun, 04 Nov 2012 04:51:56 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references; bh=wgpqCFOwIYuZxzOipRcdC8C9fCzRSxwau+NSH1rxWhQ=; b=xcBErPzxJPYGEIFXvua2ResrgBfBcdq1+Fn1oRq6BtW600cdZRbyN+4Eyg19MzUdLE QclIwiKANTJhpGKSk+TrEYXbnvrHqb+wnnjiPvVz+vYHDLqbMkIe7p3jSQXDmla+7DkW bDbM+4smnhVG6gfFou7fC5giGImmq8HqeB97Gekx06ZyJwOzD0HJewUG6lqoJ1Fvdqi+ D1RZN5vkqU02Z3/HDoURyOZbEgINyfLqbYQjFz4bKeKiqczBpNVF5KgX8DF8haIkI2Il BF/ALj09YFzlqrxhPwzDtwrwNOhQxXYbYCQ7ENgXjKXy71wyikGq6DKnnOjfCROwW/vj IB8w== Received: by 10.68.251.130 with SMTP id zk2mr22167013pbc.19.1352033516501; Sun, 04 Nov 2012 04:51:56 -0800 (PST) Received: from localhost.localdomain ([120.196.98.117]) by mx.google.com with ESMTPS id a4sm8922768pax.12.2012.11.04.04.51.48 (version=TLSv1/SSLv3 cipher=OTHER); Sun, 04 Nov 2012 04:51:55 -0800 (PST) From: Jiang Liu To: "Rafael J . Wysocki" , Yinghai Lu , Tony Luck , Yasuaki Ishimatsu , Wen Congyang , Tang Chen , Taku Izumi , Bjorn Helgaas Cc: Jiang Liu , Kenji Kaneshige , Huang Ying , Bob Moore , Len Brown , "Srivatsa S . Bhat" , Yijing Wang , Hanjun Guo , Jiang Liu , linux-kernel@vger.kernel.org, linux-acpi@vger.kernel.org, linux-pci@vger.kernel.org, linux-mm@kvack.org Subject: [ACPIHP PATCH part2 11/13] ACPIHP: block ACPI device driver from unloading when doing hotplug Date: Sun, 4 Nov 2012 20:50:13 +0800 Message-Id: <1352033415-5606-12-git-send-email-jiang.liu@huawei.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1352033415-5606-1-git-send-email-jiang.liu@huawei.com> References: <1352033415-5606-1-git-send-email-jiang.liu@huawei.com> Sender: linux-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org The ACPI hotplug driver depends on ACPI device drivers to configure or unconfigure ACPI devices. The hotplug driver will be confused if ACPI device drivers are unloaded when there are ongoing hotplug operations. So block ACPI device driver unbinding/unloading by holding the device lock when executing hotplug operations. Signed-off-by: Jiang Liu --- drivers/acpi/hotplug/configure.c | 18 ++++++++++++++++-- drivers/acpi/hotplug/device.c | 6 ------ 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/drivers/acpi/hotplug/configure.c b/drivers/acpi/hotplug/configure.c index 3209d14b..9f3ea97 100644 --- a/drivers/acpi/hotplug/configure.c +++ b/drivers/acpi/hotplug/configure.c @@ -37,7 +37,9 @@ enum config_op_code { DRV_OP_POST_RELEASE, DRV_OP_PRE_UNCONFIGURE, DRV_OP_UNCONFIGURE, - DRV_OP_POST_UNCONFIGURE + DRV_OP_POST_UNCONFIGURE, + DRV_OP_LOCK_DEVICE, + DRV_OP_UNLOCK_DEVICE, }; /* All devices will be configured in following order. */ @@ -98,6 +100,12 @@ static int acpihp_drv_invoke_method(enum config_op_code opcode, return acpihp_dev_unconfigure(dev); case DRV_OP_POST_UNCONFIGURE: return acpihp_dev_post_unconfigure(dev); + case DRV_OP_LOCK_DEVICE: + device_lock(&dev->dev); + return 0; + case DRV_OP_UNLOCK_DEVICE: + device_unlock(&dev->dev); + return 0; default: BUG_ON(opcode); return -ENOSYS; @@ -122,7 +130,9 @@ static int acpihp_drv_call_method(enum config_op_code opcode, result = acpihp_drv_invoke_method(opcode, slot, acpi_dev, 0); if (result) break; - acpihp_drv_update_dev_state(np, state); + if (opcode != DRV_OP_LOCK_DEVICE && + opcode != DRV_OP_UNLOCK_DEVICE) + acpihp_drv_update_dev_state(np, state); } klist_iter_exit(&iter); @@ -249,6 +259,7 @@ int acpihp_drv_configure(struct list_head *list) acpihp_slot_change_state(dep->slot, ACPIHP_SLOT_STATE_CONFIGURING); + acpihp_drv_walk_devs(&head, DRV_OP_LOCK_DEVICE, 0, false); result = acpihp_drv_walk_devs(&head, DRV_OP_PRE_CONFIGURE, DEVICE_STATE_PRE_CONFIGURE, false); if (!result) @@ -258,6 +269,7 @@ int acpihp_drv_configure(struct list_head *list) post = ACPIHP_DEV_POST_CMD_ROLLBACK; acpihp_drv_walk_devs_post(&head, DRV_OP_POST_CONFIGURE, DEVICE_STATE_CONNECTED, post, false); + acpihp_drv_walk_devs(&head, DRV_OP_UNLOCK_DEVICE, 0, false); list_for_each_entry(dep, &head, node) acpihp_drv_update_slot_state(dep->slot); @@ -328,9 +340,11 @@ int acpihp_drv_unconfigure(struct list_head *list) acpihp_slot_change_state(dep->slot, ACPIHP_SLOT_STATE_UNCONFIGURING); + acpihp_drv_walk_devs(&head, DRV_OP_LOCK_DEVICE, 0, false); result = acpihp_drv_release(&head); if (!result) __acpihp_drv_unconfigure(&head); + acpihp_drv_walk_devs(&head, DRV_OP_UNLOCK_DEVICE, 0, false); list_for_each_entry(dep, &head, node) acpihp_drv_update_slot_state(dep->slot); diff --git a/drivers/acpi/hotplug/device.c b/drivers/acpi/hotplug/device.c index c9d550f..6d60bb0 100644 --- a/drivers/acpi/hotplug/device.c +++ b/drivers/acpi/hotplug/device.c @@ -62,14 +62,12 @@ int acpihp_dev_##method(struct acpi_device *device, type val) \ { \ int ret; \ BUG_ON(device == NULL); \ - device_lock(&device->dev); \ if (!device->driver || !device->driver->ops.hp_ops) \ ret = (err); \ else if (!device->driver->ops.hp_ops->method) \ ret = (def); \ else \ ret = device->driver->ops.hp_ops->method(device, val); \ - device_unlock(&device->dev); \ return ret; \ } \ EXPORT_SYMBOL_GPL(acpihp_dev_##method) @@ -79,14 +77,12 @@ int acpihp_dev_##method(struct acpi_device *device, type val) \ { \ int ret = 0; \ BUG_ON(device == NULL); \ - device_lock(&device->dev); \ if (!device->driver || !device->driver->ops.hp_ops) \ ret = (err); \ else if (!device->driver->ops.hp_ops->method) \ ret = (def); \ else \ device->driver->ops.hp_ops->method(device, val); \ - device_unlock(&device->dev); \ return ret; \ } \ EXPORT_SYMBOL_GPL(acpihp_dev_##method) @@ -96,14 +92,12 @@ int acpihp_dev_##method(struct acpi_device *device) \ { \ int ret = 0; \ BUG_ON(device == NULL); \ - device_lock(&device->dev); \ if (!device->driver || !device->driver->ops.hp_ops) \ ret = (err); \ else if (!device->driver->ops.hp_ops->method) \ ret = (def); \ else \ device->driver->ops.hp_ops->method(device);\ - device_unlock(&device->dev); \ return ret; \ } \ EXPORT_SYMBOL_GPL(acpihp_dev_##method)