From patchwork Thu Nov 8 18:29:30 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vasilis Liaskovitis X-Patchwork-Id: 1716891 Return-Path: X-Original-To: patchwork-linux-acpi@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by patchwork2.kernel.org (Postfix) with ESMTP id 58E9FE0010 for ; Thu, 8 Nov 2012 18:30:34 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756555Ab2KHSaJ (ORCPT ); Thu, 8 Nov 2012 13:30:09 -0500 Received: from mail-bk0-f46.google.com ([209.85.214.46]:63259 "EHLO mail-bk0-f46.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756610Ab2KHS3l (ORCPT ); Thu, 8 Nov 2012 13:29:41 -0500 Received: by mail-bk0-f46.google.com with SMTP id jk13so1346633bkc.19 for ; Thu, 08 Nov 2012 10:29:41 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references :x-gm-message-state; bh=4X1NyK0ST/ybsJR0NwyfjbOiKUyFowESYbRrn/IvTuc=; b=TdLilI79Xl4vuc/9SwSXvZQfVwxb1II52XDH8Oy5kYmmvj2gHws5FV5sbYk3i2mghp QXC8y9VeJpSA003MPUF+HQOuEgS00PeE9inRDIIG+DRGg6q1S/74dZT3IPZnzaV2/PWp XlKoY9J7VOlbBseGMfCgbWKhvtTN9aGN/pVAyvaE/G3cAZVL6DYu+LGy4NJteMGI/Ku4 fSMH74MjKb1CVdMqCZtyP4uE3f+sXfHlBeME9sFIEzmvbLnybbzEm8IV3L6wTZpL41hU 0ALtv7DzqaXWSyfqoy43RwZRvp4Ns6WSDrswmb0UpTAAcSX8UIgpPsdjVZIPvuj0CSZA FiOQ== Received: by 10.204.12.205 with SMTP id y13mr2660836bky.46.1352399380817; Thu, 08 Nov 2012 10:29:40 -0800 (PST) Received: from dhcp-192-168-178-175.ri.profitbricks.localdomain ([62.217.45.26]) by mx.google.com with ESMTPS id z22sm17670961bkw.2.2012.11.08.10.29.39 (version=TLSv1/SSLv3 cipher=OTHER); Thu, 08 Nov 2012 10:29:40 -0800 (PST) From: Vasilis Liaskovitis To: linux-acpi@vger.kernel.org, isimatu.yasuaki@jp.fujitsu.com Cc: rjw@sisk.pl, wency@cn.fujitsu.com, lenb@kernel.org, linux-kernel@vger.kernel.org, linux-pci@vger.kernel.org, linux-mm@kvack.org, Vasilis Liaskovitis Subject: [RFC PATCH 2/3] acpi: Make acpi_bus_trim handle device removal preparation Date: Thu, 8 Nov 2012 19:29:30 +0100 Message-Id: <1352399371-8015-3-git-send-email-vasilis.liaskovitis@profitbricks.com> X-Mailer: git-send-email 1.7.9 In-Reply-To: <1352399371-8015-1-git-send-email-vasilis.liaskovitis@profitbricks.com> References: <1352399371-8015-1-git-send-email-vasilis.liaskovitis@profitbricks.com> X-Gm-Message-State: ALoCoQnH+0j22CVPZmDiEh4DotN9bz5zYQgghUGiLsEtEYb7t+3sIJkndQrlf7bYvf5EiXidAC3P Sender: linux-acpi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-acpi@vger.kernel.org A new argument is added to acpi_bus_trim, which indicates if we are preparing for removal or performing the actual ACPI removal. This is needed for safe removal of memory devices. The argument change would not be needed if the existing argument rmdevice of acpi_bus_trim could be used instead. What is the role of rmdevice argument? As far as I can tell the rmdevice argument is never used at the moment (acpi_bus_trim is called with rmdevice=1 from all its call sites. It is never called with rmdevice=0) Signed-off-by: Vasilis Liaskovitis --- drivers/acpi/acpi_memhotplug.c | 2 +- drivers/acpi/dock.c | 2 +- drivers/acpi/scan.c | 32 +++++++++++++++++++++++++++++--- drivers/pci/hotplug/acpiphp_glue.c | 4 ++-- drivers/pci/hotplug/sgi_hotplug.c | 2 +- include/acpi/acpi_bus.h | 2 +- 6 files changed, 35 insertions(+), 9 deletions(-) diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c index 92c973a..7fcc844 100644 --- a/drivers/acpi/acpi_memhotplug.c +++ b/drivers/acpi/acpi_memhotplug.c @@ -427,7 +427,7 @@ static void acpi_memory_device_notify(acpi_handle handle, u32 event, void *data) /* * Invoke acpi_bus_trim() to remove memory device */ - acpi_bus_trim(device, 1); + acpi_bus_trim(device, 1, 0); /* _EJ0 succeeded; _OST is not necessary */ return; diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index ae4ebf2..9e37b49 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c @@ -345,7 +345,7 @@ static void dock_remove_acpi_device(acpi_handle handle) int ret; if (!acpi_bus_get_device(handle, &device)) { - ret = acpi_bus_trim(device, 1); + ret = acpi_bus_trim(device, 1, 0); if (ret) pr_debug("error removing bus, %x\n", -ret); } diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 95ff1e8..b1001a4 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -121,7 +121,12 @@ void acpi_bus_hot_remove_device(void *context) ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Hot-removing device %s...\n", dev_name(&device->dev))); - if (acpi_bus_trim(device, 1)) { + if (acpi_bus_trim(device, 1, 1)) { + pr_err("Preparing to removing device failed\n"); + goto err_out; + } + + if (acpi_bus_trim(device, 1, 0)) { printk(KERN_ERR PREFIX "Removing device failed\n"); goto err_out; @@ -1347,6 +1352,19 @@ static int acpi_device_set_context(struct acpi_device *device) return -ENODEV; } +static int acpi_bus_prepare_remove(struct acpi_device *dev) +{ + int ret = 0; + + if (!dev) + return -EINVAL; + + if (dev->driver && dev->driver->ops.prepare_remove) + ret = dev->driver->ops.prepare_remove(dev); + + return ret; +} + static int acpi_bus_remove(struct acpi_device *dev, int rmdevice) { if (!dev) @@ -1640,7 +1658,11 @@ int acpi_bus_start(struct acpi_device *device) } EXPORT_SYMBOL(acpi_bus_start); -int acpi_bus_trim(struct acpi_device *start, int rmdevice) +/* acpi_bus_trim: Remove or prepare to remove a device and its children. + * @device: the device to remove or prepare to remove from. + * @prepare: If 1, prepare for removal. If 0, perform actual removal. + */ +int acpi_bus_trim(struct acpi_device *start, int rmdevice, int prepare) { acpi_status status; struct acpi_device *parent, *child; @@ -1667,7 +1689,11 @@ int acpi_bus_trim(struct acpi_device *start, int rmdevice) child = parent; parent = parent->parent; - if (level == 0) + if (prepare) { + err = acpi_bus_prepare_remove(child); + if (err) + return err; + } else if (level == 0) err = acpi_bus_remove(child, rmdevice); else err = acpi_bus_remove(child, 1); diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 3d6d4fd..bc10b61 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -748,7 +748,7 @@ static int acpiphp_bus_add(struct acpiphp_func *func) /* this shouldn't be in here, so remove * the bus then re-add it... */ - ret_val = acpi_bus_trim(device, 1); + ret_val = acpi_bus_trim(device, 1, 0); dbg("acpi_bus_trim return %x\n", ret_val); } @@ -781,7 +781,7 @@ static int acpiphp_bus_trim(acpi_handle handle) return retval; } - retval = acpi_bus_trim(device, 1); + retval = acpi_bus_trim(device, 1, 0); if (retval) err("cannot remove from acpi list\n"); diff --git a/drivers/pci/hotplug/sgi_hotplug.c b/drivers/pci/hotplug/sgi_hotplug.c index f64ca92..3655de3 100644 --- a/drivers/pci/hotplug/sgi_hotplug.c +++ b/drivers/pci/hotplug/sgi_hotplug.c @@ -539,7 +539,7 @@ static int disable_slot(struct hotplug_slot *bss_hotplug_slot) ret = acpi_bus_get_device(chandle, &device); if (ACPI_SUCCESS(ret)) - acpi_bus_trim(device, 1); + acpi_bus_trim(device, 1, 0); } } diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 6ef1692..063c470 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -359,7 +359,7 @@ void acpi_bus_unregister_driver(struct acpi_driver *driver); int acpi_bus_add(struct acpi_device **child, struct acpi_device *parent, acpi_handle handle, int type); void acpi_bus_hot_remove_device(void *context); -int acpi_bus_trim(struct acpi_device *start, int rmdevice); +int acpi_bus_trim(struct acpi_device *start, int rmdevice, int prepare); int acpi_bus_start(struct acpi_device *device); acpi_status acpi_bus_get_ejd(acpi_handle handle, acpi_handle * ejd); int acpi_match_device_ids(struct acpi_device *device,