From patchwork Mon Nov 4 13:32:00 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Rafael J. Wysocki" X-Patchwork-Id: 3135831 X-Patchwork-Delegate: bhelgaas@google.com Return-Path: X-Original-To: patchwork-linux-pci@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 4D4439F407 for ; Mon, 4 Nov 2013 13:27:13 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 0E7852054A for ; Mon, 4 Nov 2013 13:27:12 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 98A5320551 for ; Mon, 4 Nov 2013 13:27:09 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753535Ab3KDN0z (ORCPT ); Mon, 4 Nov 2013 08:26:55 -0500 Received: from v094114.home.net.pl ([79.96.170.134]:64423 "HELO v094114.home.net.pl" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with SMTP id S1751807Ab3KDN0D (ORCPT ); Mon, 4 Nov 2013 08:26:03 -0500 Received: from afjm202.neoplus.adsl.tpnet.pl [95.49.246.202] (HELO vostro.rjw.lan) by serwer1319399.home.pl [79.96.170.134] with SMTP (IdeaSmtpServer v0.80) id 17eb41c8a4eeddd6; Mon, 4 Nov 2013 14:26:01 +0100 From: "Rafael J. Wysocki" To: ACPI Devel Maling List Cc: LKML , Linux PCI , Bjorn Helgaas , Toshi Kani , Yinghai Lu Subject: [Update][PATCH 2/6] ACPI / hotplug: Refuse to hot-remove all objects with disabled hotplug Date: Mon, 04 Nov 2013 14:32 +0100 Message-ID: <1842331.UHR0XPv1jo@vostro.rjw.lan> User-Agent: KMail/4.10.5 (Linux/3.12.0-rc6+; KDE/4.10.5; x86_64; ; ) In-Reply-To: <2970389.SeMGM45Qln@vostro.rjw.lan> References: <5839747.7HXXGHmMBd@vostro.rjw.lan> <2970389.SeMGM45Qln@vostro.rjw.lan> MIME-Version: 1.0 Sender: linux-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Rafael J. Wysocki In theory, an ACPI device object may be the parent of another device object whose hotplug is disabled by user space thorugh its scan handler. In that case, the eject operation targeting the parent should fail as though the parent's own hotplug was disabled, but currently this is not the case, because acpi_scan_hot_remove() doesn't check the disable/enable hotplug status of the children of the top-most object passed to it. To fix this, modify acpi_bus_offline_companions() to return an error code if hotplug is disabled for the given device object. [Also change the name of the function to acpi_bus_offline(), because it is not only about companions any more, and change the name of acpi_bus_online_companions() accordingly.] Make acpi_scan_hot_remove() propagate that error to its callers. Signed-off-by: Rafael J. Wysocki --- drivers/acpi/scan.c | 57 ++++++++++++++++++++++++++++++++-------------------- 1 file changed, 36 insertions(+), 21 deletions(-) -- To unsubscribe from this list: send the line "unsubscribe linux-pci" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Index: linux-pm/drivers/acpi/scan.c =================================================================== --- linux-pm.orig/drivers/acpi/scan.c +++ linux-pm/drivers/acpi/scan.c @@ -125,8 +125,8 @@ acpi_device_modalias_show(struct device } static DEVICE_ATTR(modalias, 0444, acpi_device_modalias_show, NULL); -static acpi_status acpi_bus_offline_companions(acpi_handle handle, u32 lvl, - void *data, void **ret_p) +static acpi_status acpi_bus_offline(acpi_handle handle, u32 lvl, void *data, + void **ret_p) { struct acpi_device *device = NULL; struct acpi_device_physical_node *pn; @@ -136,6 +136,11 @@ static acpi_status acpi_bus_offline_comp if (acpi_bus_get_device(handle, &device)) return AE_OK; + if (device->handler && !device->handler->hotplug.enabled) { + *ret_p = &device->dev; + return AE_SUPPORT; + } + mutex_lock(&device->physical_node_lock); list_for_each_entry(pn, &device->physical_node_list, node) { @@ -168,8 +173,8 @@ static acpi_status acpi_bus_offline_comp return status; } -static acpi_status acpi_bus_online_companions(acpi_handle handle, u32 lvl, - void *data, void **ret_p) +static acpi_status acpi_bus_online(acpi_handle handle, u32 lvl, void *data, + void **ret_p) { struct acpi_device *device = NULL; struct acpi_device_physical_node *pn; @@ -214,26 +219,32 @@ static int acpi_scan_hot_remove(struct a * If the first pass is successful, the second one isn't needed, though. */ errdev = NULL; - acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, - NULL, acpi_bus_offline_companions, - (void *)false, (void **)&errdev); - acpi_bus_offline_companions(handle, 0, (void *)false, (void **)&errdev); + status = acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, + NULL, acpi_bus_offline, (void *)false, + (void **)&errdev); + if (status == AE_SUPPORT) { + dev_warn(errdev, "Offline disabled.\n"); + acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, + acpi_bus_online, NULL, NULL, NULL); + put_device(&device->dev); + return -EPERM; + } + acpi_bus_offline(handle, 0, (void *)false, (void **)&errdev); if (errdev) { errdev = NULL; acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX, - NULL, acpi_bus_offline_companions, - (void *)true , (void **)&errdev); + NULL, acpi_bus_offline, (void *)true, + (void **)&errdev); if (!errdev || acpi_force_hot_remove) - acpi_bus_offline_companions(handle, 0, (void *)true, - (void **)&errdev); + acpi_bus_offline(handle, 0, (void *)true, + (void **)&errdev); if (errdev && !acpi_force_hot_remove) { dev_warn(errdev, "Offline failed.\n"); - acpi_bus_online_companions(handle, 0, NULL, NULL); + acpi_bus_online(handle, 0, NULL, NULL); acpi_walk_namespace(ACPI_TYPE_ANY, handle, - ACPI_UINT32_MAX, - acpi_bus_online_companions, NULL, - NULL, NULL); + ACPI_UINT32_MAX, acpi_bus_online, + NULL, NULL, NULL); put_device(&device->dev); return -EBUSY; } @@ -290,10 +301,9 @@ static void acpi_bus_device_eject(void * goto err_out; handler = device->handler; - if (!handler || !handler->hotplug.enabled) { - ost_code = ACPI_OST_SC_EJECT_NOT_SUPPORTED; - goto err_out; - } + if (!handler || !handler->hotplug.enabled) + goto err_support; + acpi_evaluate_hotplug_ost(handle, ACPI_NOTIFY_EJECT_REQUEST, ACPI_OST_SC_EJECT_IN_PROGRESS, NULL); if (handler->hotplug.mode == AHM_CONTAINER) @@ -301,14 +311,19 @@ static void acpi_bus_device_eject(void * get_device(&device->dev); error = acpi_scan_hot_remove(device); - if (error) + if (error == -EPERM) { + goto err_support; + } else if (error) { goto err_out; + } out: mutex_unlock(&acpi_scan_lock); unlock_device_hotplug(); return; + err_support: + ost_code = ACPI_OST_SC_EJECT_NOT_SUPPORTED; err_out: acpi_evaluate_hotplug_ost(handle, ACPI_NOTIFY_EJECT_REQUEST, ost_code, NULL);