linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: "Rafael J. Wysocki" <rjw@rjwysocki.net>
To: ACPI Devel Maling List <linux-acpi@vger.kernel.org>
Cc: LKML <linux-kernel@vger.kernel.org>,
	Linux PCI <linux-pci@vger.kernel.org>,
	Bjorn Helgaas <bhelgaas@google.com>,
	Toshi Kani <toshi.kani@hp.com>, Yinghai Lu <yinghai@kernel.org>
Subject: [Update][PATCH 2/6] ACPI / hotplug: Refuse to hot-remove all objects with disabled hotplug
Date: Mon, 04 Nov 2013 14:32 +0100	[thread overview]
Message-ID: <1842331.UHR0XPv1jo@vostro.rjw.lan> (raw)
In-Reply-To: <2970389.SeMGM45Qln@vostro.rjw.lan>

From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

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 <rafael.j.wysocki@intel.com>
---
 drivers/acpi/scan.c |   57 ++++++++++++++++++++++++++++++++--------------------
 1 file changed, 36 insertions(+), 21 deletions(-)

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);


  parent reply	other threads:[~2013-11-04 13:26 UTC|newest]

Thread overview: 29+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-11-04  0:17 [PATCH 0/3] ACPI scan and hotplug fixes for 3.14 Rafael J. Wysocki
2013-11-04  0:18 ` [PATCH 1/3] ACPI / scan: Start matching drivers after trying scan handlers Rafael J. Wysocki
2013-11-04  0:21 ` [PATCH 2/3] ACPI / hotplug: Refuse to hot-remove all objects with disabled hotplug Rafael J. Wysocki
2013-11-04  0:21 ` [PATCH 3/3] ACPI / hotplug: Merge device hot-removal routines Rafael J. Wysocki
2013-11-04  0:41   ` [PATCH on top of 3/3] ACPI / hotplug: Remove unnecessary get_device() and put_device() Rafael J. Wysocki
2013-11-04 13:26   ` [PATCH 3/3] ACPI / hotplug: Merge device hot-removal routines Rafael J. Wysocki
2013-11-04 13:29 ` [Update][PATCH 0/6] ACPI scan and hotplug fixes Rafael J. Wysocki
2013-11-04 13:30   ` [Update][PATCH 1/6] ACPI / scan: Start matching drivers after trying scan handlers Rafael J. Wysocki
2013-11-05 23:27     ` Toshi Kani
2013-11-04 13:32   ` Rafael J. Wysocki [this message]
2013-11-05 23:27     ` [fixup][PATCH 2/6] ACPI / hotplug: Refuse to hot-remove all objects with disabled hotplug Rafael J. Wysocki
2013-11-06  0:39       ` Toshi Kani
2013-11-06  1:35         ` Rafael J. Wysocki
2013-11-06  1:32           ` Toshi Kani
2013-11-04 13:33   ` [Update][PATCH 3/6] ACPI / hotplug: Fix handle_root_bridge_removal() Rafael J. Wysocki
2013-11-06 23:21     ` Toshi Kani
2013-11-04 13:36   ` [Update][PATCH 4/6] ACPI / hotplug: Simplify device ejection routines Rafael J. Wysocki
2013-11-06 23:27     ` Toshi Kani
2013-11-07  0:14       ` Rafael J. Wysocki
2013-11-07  0:17         ` Toshi Kani
2013-11-07  0:35           ` Rafael J. Wysocki
2013-11-04 13:36   ` [Update][PATCH 5/6] ACPI / hotplug: Make acpi_bus_hot_remove_device() internal Rafael J. Wysocki
2013-11-04 13:36   ` [Update][PATCH 6/6] ACPI / hotplug: Merge device hot-removal routines Rafael J. Wysocki
2013-11-05 23:32   ` [PATCH 0/3] More ACPI hotplug updates (was: [Update][PATCH 0/6] ACPI scan and hotplug fixes) Rafael J. Wysocki
2013-11-05 23:34     ` [PATCH 1/3] ACPI / hotplug: Carry out PCI root eject directly Rafael J. Wysocki
2013-11-06  1:42       ` [Update][PATCH " Rafael J. Wysocki
2013-11-05 23:36     ` [PATCH 2/3] ACPI / hotplug: Do not execute "insert in progress" _OST Rafael J. Wysocki
2013-11-05 23:48     ` [PATCH 3/3] ACPI / hotplug: Consolidate deferred execution of ACPI hotplug routines Rafael J. Wysocki
2013-11-06  1:44       ` [Update][PATCH " Rafael J. Wysocki

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1842331.UHR0XPv1jo@vostro.rjw.lan \
    --to=rjw@rjwysocki.net \
    --cc=bhelgaas@google.com \
    --cc=linux-acpi@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pci@vger.kernel.org \
    --cc=toshi.kani@hp.com \
    --cc=yinghai@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).