summaryrefslogtreecommitdiff
path: root/drivers/acpi/scan.c
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-03-03 22:08:16 (GMT)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-03-04 13:25:32 (GMT)
commit3f8055c3583640ed3e4c81864dd76e06a7faa505 (patch)
treec77ae4121942fc43be57cd603435f1a9dcb78b3d /drivers/acpi/scan.c
parent4b59cc1fd6fd1dac1d4468b4f327ae9f59d1c0aa (diff)
downloadlinux-3f8055c3583640ed3e4c81864dd76e06a7faa505.tar.xz
ACPI / hotplug: Introduce user space interface for hotplug profiles
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 an attribute allowing user space to manipulate the enabled field of the corresponding profile. Namely, switching the enabled attribute from '0' to '1' 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@intel.com> Acked-by: Toshi Kani <toshi.kani@hp.com> Tested-by: Toshi Kani <toshi.kani@hp.com>
Diffstat (limited to 'drivers/acpi/scan.c')
-rw-r--r--drivers/acpi/scan.c59
1 files changed, 59 insertions, 0 deletions
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 45fbe95..5458403 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -63,6 +63,19 @@ int acpi_scan_add_handler(struct acpi_scan_handler *handler)
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:
@@ -1690,6 +1703,52 @@ static bool acpi_scan_handler_matching(struct acpi_scan_handler *handler,
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_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
+ acpi_hotplug_notify_cb, NULL);
+ else
+ acpi_remove_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
+ acpi_hotplug_notify_cb);
+
+ 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);
+}
+
static struct acpi_scan_handler *acpi_scan_match_handler(char *idstr,
const struct acpi_device_id **matchid)
{