All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Rafael J. Wysocki" <rjw@sisk.pl>
To: ACPI Devel Maling List <linux-acpi@vger.kernel.org>
Cc: Bjorn Helgaas <bhelgaas@google.com>,
	LKML <linux-kernel@vger.kernel.org>,
	Yinghai Lu <yinghai@kernel.org>, Toshi Kani <toshi.kani@hp.com>,
	Yasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com>,
	Jiang Liu <liuj97@gmail.com>
Subject: [PATCH 5/7] ACPI / hotplug: Introduce user space interface for hotplug profiles
Date: Sun, 17 Feb 2013 16:24:47 +0100	[thread overview]
Message-ID: <5060623.RI4NTzcn19@vostro.rjw.lan> (raw)
In-Reply-To: <3260206.bhaAobGhpZ@vostro.rjw.lan>

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

Introduce user space interface for manipulating hotplug profiles
associated with ACPI scan handlers.

The interface consists of sysfs directories under
/sys/firmware/acpi/hotplug/, one for each hotplug profile, containing
attributes allowing user space to manipulate the enabled, uevents,
and autoeject fields of the corresponding profile.  In particular,
switching the enabled attribute from 'unset' to 'set' will cause
the common hotplug notify handler to be installed for all ACPI
namespace objects representing devices matching the scan handler
associated with the given hotplug profile (and analogously for the
converse switch).

Drivers willing to use the new user space interface should add their
ACPI scan handlers with the help of new funtion
acpi_scan_add_handler_with_hotplug().

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@inel.com>
---
 Documentation/ABI/testing/sysfs-firmware-acpi |   42 +++++++++
 drivers/acpi/internal.h                       |    9 +
 drivers/acpi/scan.c                           |   73 +++++++++++++++
 drivers/acpi/sysfs.c                          |  120 ++++++++++++++++++++++++++
 include/acpi/acpi_bus.h                       |    7 +
 5 files changed, 251 insertions(+)

Index: test/drivers/acpi/sysfs.c
===================================================================
--- test.orig/drivers/acpi/sysfs.c
+++ test/drivers/acpi/sysfs.c
@@ -7,6 +7,8 @@
 #include <linux/moduleparam.h>
 #include <acpi/acpi_drivers.h>
 
+#include "internal.h"
+
 #define _COMPONENT		ACPI_SYSTEM_COMPONENT
 ACPI_MODULE_NAME("sysfs");
 
@@ -249,6 +251,7 @@ module_param_call(acpica_version, NULL,
 static LIST_HEAD(acpi_table_attr_list);
 static struct kobject *tables_kobj;
 static struct kobject *dynamic_tables_kobj;
+static struct kobject *hotplug_kobj;
 
 struct acpi_table_attr {
 	struct bin_attribute attr;
@@ -716,6 +719,121 @@ acpi_show_profile(struct device *dev, st
 static const struct device_attribute pm_profile_attr =
 	__ATTR(pm_profile, S_IRUGO, acpi_show_profile, NULL);
 
+static ssize_t hotplug_enabled_show(struct kobject *kobj,
+				    struct kobj_attribute *attr, char *buf)
+{
+	struct acpi_hotplug_profile *hotplug = to_acpi_hotplug_profile(kobj);
+
+	return sprintf(buf, "%d\n", hotplug->enabled);
+}
+
+static ssize_t hotplug_enabled_store(struct kobject *kobj,
+				     struct kobj_attribute *attr,
+				     const char *buf, size_t size)
+{
+	struct acpi_hotplug_profile *hotplug = to_acpi_hotplug_profile(kobj);
+	unsigned int val;
+
+	if (kstrtouint(buf, 10, &val) || val > 1)
+		return -EINVAL;
+
+	acpi_scan_hotplug_enabled(hotplug, val);
+	return size;
+}
+
+static struct kobj_attribute hotplug_enabled_attr =
+	__ATTR(enabled, S_IRUGO | S_IWUSR, hotplug_enabled_show,
+		hotplug_enabled_store);
+
+static ssize_t hotplug_uevents_show(struct kobject *kobj,
+				    struct kobj_attribute *attr, char *buf)
+{
+	struct acpi_hotplug_profile *hotplug = to_acpi_hotplug_profile(kobj);
+
+	return sprintf(buf, "%d\n", hotplug->uevents);
+}
+
+static ssize_t hotplug_uevents_store(struct kobject *kobj,
+				     struct kobj_attribute *attr,
+				     const char *buf, size_t size)
+{
+	struct acpi_hotplug_profile *hotplug = to_acpi_hotplug_profile(kobj);
+	unsigned int val;
+
+	if (kstrtouint(buf, 10, &val) || val > 1)
+		return -EINVAL;
+
+	acpi_scan_hotplug_uevents(hotplug, val);
+	return size;
+}
+
+static struct kobj_attribute hotplug_uevents_attr =
+	__ATTR(uevents, S_IRUGO | S_IWUSR, hotplug_uevents_show,
+		hotplug_uevents_store);
+
+static ssize_t hotplug_autoeject_show(struct kobject *kobj,
+				      struct kobj_attribute *attr, char *buf)
+{
+	struct acpi_hotplug_profile *hotplug = to_acpi_hotplug_profile(kobj);
+
+	return sprintf(buf, "%d\n", hotplug->autoeject);
+}
+
+static ssize_t hotplug_autoeject_store(struct kobject *kobj,
+				       struct kobj_attribute *attr,
+				       const char *buf, size_t size)
+{
+	struct acpi_hotplug_profile *hotplug = to_acpi_hotplug_profile(kobj);
+	unsigned int val;
+
+	if (kstrtouint(buf, 10, &val) || val > 1)
+		return -EINVAL;
+
+	acpi_scan_hotplug_autoeject(hotplug, val);
+	return size;
+}
+
+static struct kobj_attribute hotplug_autoeject_attr =
+	__ATTR(autoeject, S_IRUGO | S_IWUSR, hotplug_autoeject_show,
+		hotplug_autoeject_store);
+
+static struct attribute *hotplug_profile_attrs[] = {
+	&hotplug_enabled_attr.attr,
+	&hotplug_uevents_attr.attr,
+	&hotplug_autoeject_attr.attr,
+	NULL
+};
+
+struct kobj_type acpi_hotplug_profile_ktype = {
+	.sysfs_ops = &kobj_sysfs_ops,
+	.default_attrs = hotplug_profile_attrs,
+};
+
+void acpi_sysfs_add_hotplug_profile(struct acpi_hotplug_profile *hotplug,
+				    const char *name)
+{
+	int error;
+
+	if (!hotplug_kobj)
+		goto err_out;
+
+	kobject_init(&hotplug->kobj, &acpi_hotplug_profile_ktype);
+	error = kobject_set_name(&hotplug->kobj, "%s", name);
+	if (error)
+		goto err_out;
+
+	hotplug->kobj.parent = hotplug_kobj;
+	error = kobject_add(&hotplug->kobj, hotplug_kobj, NULL);
+	if (error)
+		goto err_out;
+
+	kobject_uevent(&hotplug->kobj, KOBJ_ADD);
+	return;
+
+ err_out:
+	pr_err(PREFIX "Unable to add hotplug profile '%s'\n", name);
+}
+
 int __init acpi_sysfs_init(void)
 {
 	int result;
@@ -723,6 +841,8 @@ int __init acpi_sysfs_init(void)
 	result = acpi_tables_sysfs_init();
 	if (result)
 		return result;
+
+	hotplug_kobj = kobject_create_and_add("hotplug", acpi_kobj);
 	result = sysfs_create_file(acpi_kobj, &pm_profile_attr.attr);
 	return result;
 }
Index: test/include/acpi/acpi_bus.h
===================================================================
--- test.orig/include/acpi/acpi_bus.h
+++ test/include/acpi/acpi_bus.h
@@ -89,11 +89,18 @@ struct acpi_device;
  */
 
 struct acpi_hotplug_profile {
+	struct kobject kobj;
 	bool enabled:1;
 	bool uevents:1;
 	bool autoeject:1;
 };
 
+static inline struct acpi_hotplug_profile *to_acpi_hotplug_profile(
+						struct kobject *kobj)
+{
+	return container_of(kobj, struct acpi_hotplug_profile, kobj);
+}
+
 struct acpi_scan_handler {
 	const struct acpi_device_id *ids;
 	struct list_head list_node;
Index: test/drivers/acpi/internal.h
===================================================================
--- test.orig/drivers/acpi/internal.h
+++ test/drivers/acpi/internal.h
@@ -36,6 +36,15 @@ void acpi_container_init(void);
 static inline void acpi_container_init(void) {}
 #endif
 
+void acpi_sysfs_add_hotplug_profile(struct acpi_hotplug_profile *hotplug,
+				    const char *name);
+int acpi_scan_add_handler_with_hotplug(struct acpi_scan_handler *handler,
+				       const char *hotplug_profile_name);
+void acpi_scan_hotplug_enabled(struct acpi_hotplug_profile *hotplug, bool val);
+void acpi_scan_hotplug_uevents(struct acpi_hotplug_profile *hotplug, bool val);
+void acpi_scan_hotplug_autoeject(struct acpi_hotplug_profile *hotplug,
+				 bool val);
+
 #ifdef CONFIG_DEBUG_FS
 extern struct dentry *acpi_debugfs_dir;
 int acpi_debugfs_init(void);
Index: test/drivers/acpi/scan.c
===================================================================
--- test.orig/drivers/acpi/scan.c
+++ test/drivers/acpi/scan.c
@@ -63,6 +63,19 @@ int acpi_scan_add_handler(struct acpi_sc
 	return 0;
 }
 
+int acpi_scan_add_handler_with_hotplug(struct acpi_scan_handler *handler,
+				       const char *hotplug_profile_name)
+{
+	int error;
+
+	error = acpi_scan_add_handler(handler);
+	if (error)
+		return error;
+
+	acpi_sysfs_add_hotplug_profile(&handler->hotplug, hotplug_profile_name);
+	return 0;
+}
+
 /*
  * Creates hid/cid(s) string needed for modalias and uevent
  * e.g. on a device with hid:IBM0001 and cid:ACPI0001 you get:
@@ -1675,6 +1688,66 @@ static bool acpi_scan_handler_matching(s
 	return false;
 }
 
+static acpi_status acpi_scan_hotplug_modify(acpi_handle handle,
+					    u32 lvl_not_used, void *data,
+					    void **ret_not_used)
+{
+	struct acpi_scan_handler *handler = data;
+	struct acpi_device_info *info;
+	bool match = false;
+
+	if (ACPI_FAILURE(acpi_get_object_info(handle, &info)))
+		return AE_OK;
+
+	if (info->valid & ACPI_VALID_HID) {
+		char *idstr = info->hardware_id.string;
+		match = acpi_scan_handler_matching(handler, idstr, NULL);
+	}
+	kfree(info);
+	if (!match)
+		return AE_OK;
+
+	if (handler->hotplug.enabled)
+		acpi_remove_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
+					   acpi_hotplug_notify_cb);
+	else
+		acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
+					    acpi_hotplug_notify_cb, NULL);
+
+	return AE_OK;
+}
+
+void acpi_scan_hotplug_enabled(struct acpi_hotplug_profile *hotplug, bool val)
+{
+	struct acpi_scan_handler *handler;
+
+	if (!!hotplug->enabled == !!val)
+		return;
+
+	mutex_lock(&acpi_scan_lock);
+
+	hotplug->enabled = val;
+	handler = container_of(hotplug, struct acpi_scan_handler, hotplug);
+	acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX,
+			    acpi_scan_hotplug_modify, NULL, handler, NULL);
+
+	mutex_unlock(&acpi_scan_lock);
+}
+
+void acpi_scan_hotplug_uevents(struct acpi_hotplug_profile *hotplug, bool val)
+{
+	mutex_lock(&acpi_scan_lock);
+	hotplug->uevents = val;
+	mutex_unlock(&acpi_scan_lock);
+}
+
+void acpi_scan_hotplug_autoeject(struct acpi_hotplug_profile *hotplug, bool val)
+{
+	mutex_lock(&acpi_scan_lock);
+	hotplug->autoeject = val;
+	mutex_unlock(&acpi_scan_lock);
+}
+
 static struct acpi_scan_handler *acpi_scan_match_handler(char *idstr,
 					const struct acpi_device_id **matchid)
 {
Index: test/Documentation/ABI/testing/sysfs-firmware-acpi
===================================================================
--- test.orig/Documentation/ABI/testing/sysfs-firmware-acpi
+++ test/Documentation/ABI/testing/sysfs-firmware-acpi
@@ -18,6 +18,48 @@ Description:
 		yoffset: The number of pixels between the top of the screen
 			 and the top edge of the image.
 
+What:		/sys/firmware/acpi/hotplug/
+Date:		February 2013
+Contact:	Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Description:
+		There are separate hotplug profiles for different classes of
+		devices supported by ACPI, such as containers, memory modules,
+		processors, PCI root bridges etc.  A hotplug profile for a given
+		class of devices is a collection of settings defining the way
+		that class of devices will be handled by the ACPI core hotplug
+		code.  Those profiles are represented in sysfs as subdirectories
+		of /sys/firmware/acpi/hotplug/.
+
+		The following settings are available for each hotplug profile:
+
+		enabled: If set, the ACPI core will handle notifications of
+			hotplug events associated with the given class of
+			devices and will allow those devices to be ejected with
+			the help of the _EJ0 control method.  Unsetting it
+			effectively disables hotplug for the correspoinding
+			class of devices.
+
+		uevents: If set, the ACPI core will emit a KOBJ_ONLINE uevent
+			after a successful namespace scan for a device of the
+			given class resulting from a "bus check" or "device
+			check" firmware notification.  It also will emit a
+			KOBJ_OFFLINE uevent upon receiving an eject request from
+			the platform firmware for a device node of the given
+			class.  If unset, no uevents related to hotplug will be
+			emitted for devices of the given class.
+
+		autoeject: If set, the ACPI core will automatically carry out
+			a namespace trim operation and will attempt to execute
+			_EJ0 after receiving an eject request from the platform
+			firmware for a device node of the given class.  If
+			unset, user space will have to trigger ejects directly
+			using the 'eject' attributes of the device nodes to be
+			ejected.
+
+		The values of all of the above attributes are integer numbers:
+		1 (set) or 0 (unset).  Attempts to write any other values to
+		them will cause -EINVAL to be returned.
+
 What:		/sys/firmware/acpi/interrupts/
 Date:		February 2008
 Contact:	Len Brown <lenb@kernel.org>

  parent reply	other threads:[~2013-02-17 15:24 UTC|newest]

Thread overview: 69+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-02-17 15:18 [PATCH 0/7] ACPI / hotplug: Common code for ACPI-based hotplug Rafael J. Wysocki
2013-02-17 15:20 ` [PATCH 1/7] ACPI / scan: Introduce acpi_scan_match_handler() Rafael J. Wysocki
2013-02-19  6:48   ` Yasuaki Ishimatsu
2013-02-17 15:21 ` [PATCH 2/7] ACPI / scan: Introduce common code for ACPI-based device hotplug Rafael J. Wysocki
2013-02-19  6:43   ` Yasuaki Ishimatsu
2013-02-19  7:10     ` Yasuaki Ishimatsu
2013-02-20 13:27       ` Rafael J. Wysocki
2013-02-20 13:23     ` Rafael J. Wysocki
2013-02-20 20:23       ` Toshi Kani
2013-02-20 21:17         ` Rafael J. Wysocki
2013-02-20 22:49   ` [Update][PATCH " Rafael J. Wysocki
2013-02-21  1:17     ` Toshi Kani
2013-02-21 15:44       ` Rafael J. Wysocki
2013-02-21 15:52     ` [Update 2][PATCH " Rafael J. Wysocki
2013-02-21 17:39       ` Toshi Kani
2013-02-21 22:57         ` Rafael J. Wysocki
2013-02-21 23:06       ` [Update 3][PATCH " Rafael J. Wysocki
2013-02-22  1:12         ` Toshi Kani
2013-02-22  1:50           ` Rafael J. Wysocki
2013-02-22  8:51             ` Yasuaki Ishimatsu
2013-02-22 12:37               ` Rafael J. Wysocki
2013-02-22 15:54                 ` Toshi Kani
2013-02-22 20:59                   ` Rafael J. Wysocki
2013-02-23 22:38         ` [Update 4][PATCH " Rafael J. Wysocki
2013-02-25 18:07           ` Toshi Kani
2013-02-25 23:39             ` Rafael J. Wysocki
2013-02-25 23:32               ` Toshi Kani
2013-02-26  0:40               ` Yasuaki Ishimatsu
2013-02-26  1:09                 ` Toshi Kani
2013-02-26  2:02                   ` Yasuaki Ishimatsu
2013-02-26  3:11                     ` Rafael J. Wysocki
2013-02-26  3:40                       ` Yasuaki Ishimatsu
2013-02-26  3:50                         ` Rafael J. Wysocki
2013-03-04 13:10               ` Vasilis Liaskovitis
2013-03-14 17:16                 ` Rafael J. Wysocki
2013-03-15 10:47                   ` Vasilis Liaskovitis
2013-03-25 20:45                     ` Toshi Kani
2013-03-25 22:29                       ` Rafael J. Wysocki
2013-03-25 22:57                         ` Toshi Kani
2013-03-26 12:22                           ` Rafael J. Wysocki
2013-03-26 20:10                             ` Toshi Kani
2013-02-17 15:22 ` [PATCH 3/7] ACPI / container: Use common hotplug code Rafael J. Wysocki
2013-02-17 15:23 ` [PATCH 4/7] ACPI / scan: Introduce acpi_scan_handler_matching() Rafael J. Wysocki
2013-02-19  8:05   ` Yasuaki Ishimatsu
2013-02-17 15:24 ` Rafael J. Wysocki [this message]
2013-02-25 18:13   ` [PATCH 5/7] ACPI / hotplug: Introduce user space interface for hotplug profiles Toshi Kani
2013-02-25 23:25     ` Rafael J. Wysocki
2013-02-17 15:25 ` [PATCH 6/7] ACPI / container: Use hotplug profile user space interface Rafael J. Wysocki
2013-02-17 15:27 ` [PATCH 7/7] ACPI / scan: Make memory hotplug driver use struct acpi_scan_handler Rafael J. Wysocki
2013-02-19 18:11   ` Vasilis Liaskovitis
2013-02-20  3:35     ` Yasuaki Ishimatsu
2013-02-20 10:42       ` Vasilis Liaskovitis
2013-02-20 21:50         ` Toshi Kani
2013-02-20 22:29           ` Rafael J. Wysocki
2013-02-20 22:39             ` Toshi Kani
2013-02-21  6:58         ` Yasuaki Ishimatsu
2013-02-26 22:41 ` [PATCH v2, 0/7] ACPI / hotplug: Common code for ACPI-based hotplug Rafael J. Wysocki
2013-02-26 22:44   ` [PATCH v2, 1/7] ACPI / scan: Introduce acpi_scan_match_handler() Rafael J. Wysocki
2013-02-26 22:46   ` [PATCH v2, 2/7] ACPI / scan: Introduce common code for ACPI-based device hotplug Rafael J. Wysocki
2013-02-26 22:46   ` [PATCH v2, 3/7] ACPI / container: Use common hotplug code Rafael J. Wysocki
2013-02-26 23:13     ` Toshi Kani
2013-02-26 23:13       ` Toshi Kani
2013-02-27  0:06       ` Rafael J. Wysocki
2013-02-27  0:09     ` [Update][PATCH " Rafael J. Wysocki
2013-02-26 22:47   ` [PATCH v2, 4/7] ACPI / scan: Introduce acpi_scan_handler_matching() Rafael J. Wysocki
2013-02-26 22:48   ` [PATCH v2, 5/7] ACPI / hotplug: Introduce user space interface for hotplug profiles Rafael J. Wysocki
2013-02-26 22:49   ` [PATCH v2, 6/7] ACPI / container: Use hotplug profile user space interface Rafael J. Wysocki
2013-02-26 22:50   ` [PATCH v2, 7/7] ACPI / scan: Make memory hotplug driver use struct acpi_scan_handler Rafael J. Wysocki
2013-02-27  0:51   ` [PATCH v2, 0/7] ACPI / hotplug: Common code for ACPI-based hotplug Toshi Kani

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=5060623.RI4NTzcn19@vostro.rjw.lan \
    --to=rjw@sisk.pl \
    --cc=bhelgaas@google.com \
    --cc=isimatu.yasuaki@jp.fujitsu.com \
    --cc=linux-acpi@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=liuj97@gmail.com \
    --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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.