diff options
Diffstat (limited to 'drivers/platform/x86/wmi.c')
-rw-r--r-- | drivers/platform/x86/wmi.c | 375 |
1 files changed, 196 insertions, 179 deletions
diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c index a76313006bdc..c34341f4da76 100644 --- a/drivers/platform/x86/wmi.c +++ b/drivers/platform/x86/wmi.c @@ -17,6 +17,8 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include <linux/acpi.h> +#include <linux/bits.h> +#include <linux/build_bug.h> #include <linux/device.h> #include <linux/init.h> #include <linux/kernel.h> @@ -25,6 +27,7 @@ #include <linux/module.h> #include <linux/platform_device.h> #include <linux/slab.h> +#include <linux/sysfs.h> #include <linux/types.h> #include <linux/uaccess.h> #include <linux/uuid.h> @@ -39,7 +42,7 @@ MODULE_LICENSE("GPL"); static LIST_HEAD(wmi_block_list); struct guid_block { - char guid[16]; + guid_t guid; union { char object_id[2]; struct { @@ -49,7 +52,10 @@ struct guid_block { }; u8 instance_count; u8 flags; -}; +} __packed; +static_assert(sizeof(typeof_member(struct guid_block, guid)) == 16); +static_assert(sizeof(struct guid_block) == 20); +static_assert(__alignof__(struct guid_block) == 1); struct wmi_block { struct wmi_device dev; @@ -70,10 +76,10 @@ struct wmi_block { * If the GUID data block is marked as expensive, we must enable and * explicitily disable data collection. */ -#define ACPI_WMI_EXPENSIVE 0x1 -#define ACPI_WMI_METHOD 0x2 /* GUID is a method */ -#define ACPI_WMI_STRING 0x4 /* GUID takes & returns a string */ -#define ACPI_WMI_EVENT 0x8 /* GUID is an event */ +#define ACPI_WMI_EXPENSIVE BIT(0) +#define ACPI_WMI_METHOD BIT(1) /* GUID is a method */ +#define ACPI_WMI_STRING BIT(2) /* GUID takes & returns a string */ +#define ACPI_WMI_EVENT BIT(3) /* GUID is an event */ static bool debug_event; module_param(debug_event, bool, 0444); @@ -91,7 +97,7 @@ static int acpi_wmi_probe(struct platform_device *device); static const struct acpi_device_id wmi_device_ids[] = { {"PNP0C14", 0}, {"pnp0c14", 0}, - {"", 0}, + { } }; MODULE_DEVICE_TABLE(acpi, wmi_device_ids); @@ -108,43 +114,44 @@ static struct platform_driver acpi_wmi_driver = { * GUID parsing functions */ -static bool find_guid(const char *guid_string, struct wmi_block **out) +static acpi_status find_guid(const char *guid_string, struct wmi_block **out) { guid_t guid_input; struct wmi_block *wblock; - struct guid_block *block; + + if (!guid_string) + return AE_BAD_PARAMETER; if (guid_parse(guid_string, &guid_input)) - return false; + return AE_BAD_PARAMETER; list_for_each_entry(wblock, &wmi_block_list, list) { - block = &wblock->gblock; - - if (memcmp(block->guid, &guid_input, 16) == 0) { + if (guid_equal(&wblock->gblock.guid, &guid_input)) { if (out) *out = wblock; - return true; + + return AE_OK; } } - return false; + + return AE_NOT_FOUND; } static const void *find_guid_context(struct wmi_block *wblock, - struct wmi_driver *wdriver) + struct wmi_driver *wdriver) { const struct wmi_device_id *id; - guid_t guid_input; - if (wblock == NULL || wdriver == NULL) - return NULL; - if (wdriver->id_table == NULL) + id = wdriver->id_table; + if (!id) return NULL; - id = wdriver->id_table; while (*id->guid_string) { + guid_t guid_input; + if (guid_parse(id->guid_string, &guid_input)) continue; - if (!memcmp(wblock->gblock.guid, &guid_input, 16)) + if (guid_equal(&wblock->gblock.guid, &guid_input)) return id->context; id++; } @@ -175,9 +182,9 @@ static int get_subobj_info(acpi_handle handle, const char *pathname, return 0; } -static acpi_status wmi_method_enable(struct wmi_block *wblock, int enable) +static acpi_status wmi_method_enable(struct wmi_block *wblock, bool enable) { - struct guid_block *block = NULL; + struct guid_block *block; char method[5]; acpi_status status; acpi_handle handle; @@ -187,11 +194,50 @@ static acpi_status wmi_method_enable(struct wmi_block *wblock, int enable) snprintf(method, 5, "WE%02X", block->notify_id); status = acpi_execute_simple_method(handle, method, enable); + if (status == AE_NOT_FOUND) + return AE_OK; - if (status != AE_OK && status != AE_NOT_FOUND) - return status; + return status; +} + +#define WMI_ACPI_METHOD_NAME_SIZE 5 + +static inline void get_acpi_method_name(const struct wmi_block *wblock, + const char method, + char buffer[static WMI_ACPI_METHOD_NAME_SIZE]) +{ + static_assert(ARRAY_SIZE(wblock->gblock.object_id) == 2); + static_assert(WMI_ACPI_METHOD_NAME_SIZE >= 5); + + buffer[0] = 'W'; + buffer[1] = method; + buffer[2] = wblock->gblock.object_id[0]; + buffer[3] = wblock->gblock.object_id[1]; + buffer[4] = '\0'; +} + +static inline acpi_object_type get_param_acpi_type(const struct wmi_block *wblock) +{ + if (wblock->gblock.flags & ACPI_WMI_STRING) + return ACPI_TYPE_STRING; else - return AE_OK; + return ACPI_TYPE_BUFFER; +} + +static acpi_status get_event_data(const struct wmi_block *wblock, struct acpi_buffer *out) +{ + union acpi_object param = { + .integer = { + .type = ACPI_TYPE_INTEGER, + .value = wblock->gblock.notify_id, + } + }; + struct acpi_object_list input = { + .count = 1, + .pointer = ¶m, + }; + + return acpi_evaluate_object(wblock->acpi_device->handle, "_WED", &input, out); } /* @@ -226,13 +272,16 @@ EXPORT_SYMBOL_GPL(set_required_buffer_size); * * Call an ACPI-WMI method */ -acpi_status wmi_evaluate_method(const char *guid_string, u8 instance, -u32 method_id, const struct acpi_buffer *in, struct acpi_buffer *out) +acpi_status wmi_evaluate_method(const char *guid_string, u8 instance, u32 method_id, + const struct acpi_buffer *in, struct acpi_buffer *out) { struct wmi_block *wblock = NULL; + acpi_status status; + + status = find_guid(guid_string, &wblock); + if (ACPI_FAILURE(status)) + return status; - if (!find_guid(guid_string, &wblock)) - return AE_ERROR; return wmidev_evaluate_method(&wblock->dev, instance, method_id, in, out); } @@ -248,16 +297,15 @@ EXPORT_SYMBOL_GPL(wmi_evaluate_method); * * Call an ACPI-WMI method */ -acpi_status wmidev_evaluate_method(struct wmi_device *wdev, u8 instance, - u32 method_id, const struct acpi_buffer *in, struct acpi_buffer *out) +acpi_status wmidev_evaluate_method(struct wmi_device *wdev, u8 instance, u32 method_id, + const struct acpi_buffer *in, struct acpi_buffer *out) { - struct guid_block *block = NULL; - struct wmi_block *wblock = NULL; + struct guid_block *block; + struct wmi_block *wblock; acpi_handle handle; - acpi_status status; struct acpi_object_list input; union acpi_object params[3]; - char method[5] = "WM"; + char method[WMI_ACPI_METHOD_NAME_SIZE]; wblock = container_of(wdev, struct wmi_block, dev); block = &wblock->gblock; @@ -279,33 +327,27 @@ acpi_status wmidev_evaluate_method(struct wmi_device *wdev, u8 instance, if (in) { input.count = 3; - if (block->flags & ACPI_WMI_STRING) { - params[2].type = ACPI_TYPE_STRING; - } else { - params[2].type = ACPI_TYPE_BUFFER; - } + params[2].type = get_param_acpi_type(wblock); params[2].buffer.length = in->length; params[2].buffer.pointer = in->pointer; } - strncat(method, block->object_id, 2); + get_acpi_method_name(wblock, 'M', method); - status = acpi_evaluate_object(handle, method, &input, out); - - return status; + return acpi_evaluate_object(handle, method, &input, out); } EXPORT_SYMBOL_GPL(wmidev_evaluate_method); static acpi_status __query_block(struct wmi_block *wblock, u8 instance, struct acpi_buffer *out) { - struct guid_block *block = NULL; + struct guid_block *block; acpi_handle handle; acpi_status status, wc_status = AE_ERROR; struct acpi_object_list input; union acpi_object wq_params[1]; - char method[5]; - char wc_method[5] = "WC"; + char wc_method[WMI_ACPI_METHOD_NAME_SIZE]; + char method[WMI_ACPI_METHOD_NAME_SIZE]; if (!out) return AE_BAD_PARAMETER; @@ -333,7 +375,7 @@ static acpi_status __query_block(struct wmi_block *wblock, u8 instance, * enable collection. */ if (block->flags & ACPI_WMI_EXPENSIVE) { - strncat(wc_method, block->object_id, 2); + get_acpi_method_name(wblock, 'C', wc_method); /* * Some GUIDs break the specification by declaring themselves @@ -343,9 +385,7 @@ static acpi_status __query_block(struct wmi_block *wblock, u8 instance, wc_status = acpi_execute_simple_method(handle, wc_method, 1); } - strcpy(method, "WQ"); - strncat(method, block->object_id, 2); - + get_acpi_method_name(wblock, 'Q', method); status = acpi_evaluate_object(handle, method, &input, out); /* @@ -353,7 +393,14 @@ static acpi_status __query_block(struct wmi_block *wblock, u8 instance, * the WQxx method failed - we should disable collection anyway. */ if ((block->flags & ACPI_WMI_EXPENSIVE) && ACPI_SUCCESS(wc_status)) { - status = acpi_execute_simple_method(handle, wc_method, 0); + /* + * Ignore whether this WCxx call succeeds or not since + * the previously executed WQxx method call might have + * succeeded, and returning the failing status code + * of this call would throw away the result of the WQxx + * call, potentially leaking memory. + */ + acpi_execute_simple_method(handle, wc_method, 0); } return status; @@ -371,12 +418,11 @@ acpi_status wmi_query_block(const char *guid_string, u8 instance, struct acpi_buffer *out) { struct wmi_block *wblock; + acpi_status status; - if (!guid_string) - return AE_BAD_PARAMETER; - - if (!find_guid(guid_string, &wblock)) - return AE_ERROR; + status = find_guid(guid_string, &wblock); + if (ACPI_FAILURE(status)) + return status; return __query_block(wblock, instance, out); } @@ -390,7 +436,7 @@ union acpi_object *wmidev_block_query(struct wmi_device *wdev, u8 instance) if (ACPI_FAILURE(__query_block(wblock, instance, &out))) return NULL; - return (union acpi_object *)out.pointer; + return out.pointer; } EXPORT_SYMBOL_GPL(wmidev_block_query); @@ -405,18 +451,20 @@ EXPORT_SYMBOL_GPL(wmidev_block_query); acpi_status wmi_set_block(const char *guid_string, u8 instance, const struct acpi_buffer *in) { - struct guid_block *block = NULL; struct wmi_block *wblock = NULL; + struct guid_block *block; acpi_handle handle; struct acpi_object_list input; union acpi_object params[2]; - char method[5] = "WS"; + char method[WMI_ACPI_METHOD_NAME_SIZE]; + acpi_status status; - if (!guid_string || !in) + if (!in) return AE_BAD_DATA; - if (!find_guid(guid_string, &wblock)) - return AE_ERROR; + status = find_guid(guid_string, &wblock); + if (ACPI_FAILURE(status)) + return status; block = &wblock->gblock; handle = wblock->acpi_device->handle; @@ -432,16 +480,11 @@ acpi_status wmi_set_block(const char *guid_string, u8 instance, input.pointer = params; params[0].type = ACPI_TYPE_INTEGER; params[0].integer.value = instance; - - if (block->flags & ACPI_WMI_STRING) { - params[1].type = ACPI_TYPE_STRING; - } else { - params[1].type = ACPI_TYPE_BUFFER; - } + params[1].type = get_param_acpi_type(wblock); params[1].buffer.length = in->length; params[1].buffer.pointer = in->pointer; - strncat(method, block->object_id, 2); + get_acpi_method_name(wblock, 'S', method); return acpi_evaluate_object(handle, method, &input, NULL); } @@ -449,7 +492,7 @@ EXPORT_SYMBOL_GPL(wmi_set_block); static void wmi_dump_wdg(const struct guid_block *g) { - pr_info("%pUL:\n", g->guid); + pr_info("%pUL:\n", &g->guid); if (g->flags & ACPI_WMI_EVENT) pr_info("\tnotify_id: 0x%02X\n", g->notify_id); else @@ -482,15 +525,14 @@ static void wmi_notify_debug(u32 value, void *context) return; } - obj = (union acpi_object *)response.pointer; - + obj = response.pointer; if (!obj) return; - pr_info("DEBUG Event "); - switch(obj->type) { + pr_info("DEBUG: event 0x%02X ", value); + switch (obj->type) { case ACPI_TYPE_BUFFER: - pr_cont("BUFFER_TYPE - length %d\n", obj->buffer.length); + pr_cont("BUFFER_TYPE - length %u\n", obj->buffer.length); break; case ACPI_TYPE_STRING: pr_cont("STRING_TYPE - %s\n", obj->string.pointer); @@ -499,7 +541,7 @@ static void wmi_notify_debug(u32 value, void *context) pr_cont("INTEGER_TYPE - %llu\n", obj->integer.value); break; case ACPI_TYPE_PACKAGE: - pr_cont("PACKAGE_TYPE - %d elements\n", obj->package.count); + pr_cont("PACKAGE_TYPE - %u elements\n", obj->package.count); break; default: pr_cont("object type 0x%X\n", obj->type); @@ -516,7 +558,8 @@ static void wmi_notify_debug(u32 value, void *context) * Register a handler for events sent to the ACPI-WMI mapper device. */ acpi_status wmi_install_notify_handler(const char *guid, -wmi_notify_handler handler, void *data) + wmi_notify_handler handler, + void *data) { struct wmi_block *block; acpi_status status = AE_NOT_EXIST; @@ -531,7 +574,7 @@ wmi_notify_handler handler, void *data) list_for_each_entry(block, &wmi_block_list, list) { acpi_status wmi_status; - if (memcmp(block->gblock.guid, &guid_input, 16) == 0) { + if (guid_equal(&block->gblock.guid, &guid_input)) { if (block->handler && block->handler != wmi_notify_debug) return AE_ALREADY_ACQUIRED; @@ -539,7 +582,7 @@ wmi_notify_handler handler, void *data) block->handler = handler; block->handler_data = data; - wmi_status = wmi_method_enable(block, 1); + wmi_status = wmi_method_enable(block, true); if ((wmi_status != AE_OK) || ((wmi_status == AE_OK) && (status == AE_NOT_EXIST))) status = wmi_status; @@ -551,7 +594,7 @@ wmi_notify_handler handler, void *data) EXPORT_SYMBOL_GPL(wmi_install_notify_handler); /** - * wmi_uninstall_notify_handler - Unregister handler for WMI events + * wmi_remove_notify_handler - Unregister handler for WMI events * @guid: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba * * Unregister handler for events sent to the ACPI-WMI mapper device. @@ -571,7 +614,7 @@ acpi_status wmi_remove_notify_handler(const char *guid) list_for_each_entry(block, &wmi_block_list, list) { acpi_status wmi_status; - if (memcmp(block->gblock.guid, &guid_input, 16) == 0) { + if (guid_equal(&block->gblock.guid, &guid_input)) { if (!block->handler || block->handler == wmi_notify_debug) return AE_NULL_ENTRY; @@ -580,7 +623,7 @@ acpi_status wmi_remove_notify_handler(const char *guid) block->handler = wmi_notify_debug; status = AE_OK; } else { - wmi_status = wmi_method_enable(block, 0); + wmi_status = wmi_method_enable(block, false); block->handler = NULL; block->handler_data = NULL; if ((wmi_status != AE_OK) || @@ -605,23 +648,13 @@ EXPORT_SYMBOL_GPL(wmi_remove_notify_handler); */ acpi_status wmi_get_event_data(u32 event, struct acpi_buffer *out) { - struct acpi_object_list input; - union acpi_object params[1]; - struct guid_block *gblock; struct wmi_block *wblock; - input.count = 1; - input.pointer = params; - params[0].type = ACPI_TYPE_INTEGER; - params[0].integer.value = event; - list_for_each_entry(wblock, &wmi_block_list, list) { - gblock = &wblock->gblock; + struct guid_block *gblock = &wblock->gblock; - if ((gblock->flags & ACPI_WMI_EVENT) && - (gblock->notify_id == event)) - return acpi_evaluate_object(wblock->acpi_device->handle, - "_WED", &input, out); + if ((gblock->flags & ACPI_WMI_EVENT) && gblock->notify_id == event) + return get_event_data(wblock, out); } return AE_NOT_FOUND; @@ -636,7 +669,7 @@ EXPORT_SYMBOL_GPL(wmi_get_event_data); */ bool wmi_has_guid(const char *guid_string) { - return find_guid(guid_string, NULL); + return ACPI_SUCCESS(find_guid(guid_string, NULL)); } EXPORT_SYMBOL_GPL(wmi_has_guid); @@ -651,8 +684,10 @@ EXPORT_SYMBOL_GPL(wmi_has_guid); char *wmi_get_acpi_device_uid(const char *guid_string) { struct wmi_block *wblock = NULL; + acpi_status status; - if (!find_guid(guid_string, &wblock)) + status = find_guid(guid_string, &wblock); + if (ACPI_FAILURE(status)) return NULL; return acpi_device_uid(wblock->acpi_device); @@ -669,6 +704,11 @@ static struct wmi_device *dev_to_wdev(struct device *dev) return container_of(dev, struct wmi_device, dev); } +static inline struct wmi_driver *drv_to_wdrv(struct device_driver *drv) +{ + return container_of(drv, struct wmi_driver, driver); +} + /* * sysfs interface */ @@ -677,7 +717,7 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, { struct wmi_block *wblock = dev_to_wblock(dev); - return sprintf(buf, "wmi:%pUL\n", wblock->gblock.guid); + return sysfs_emit(buf, "wmi:%pUL\n", &wblock->gblock.guid); } static DEVICE_ATTR_RO(modalias); @@ -686,7 +726,7 @@ static ssize_t guid_show(struct device *dev, struct device_attribute *attr, { struct wmi_block *wblock = dev_to_wblock(dev); - return sprintf(buf, "%pUL\n", wblock->gblock.guid); + return sysfs_emit(buf, "%pUL\n", &wblock->gblock.guid); } static DEVICE_ATTR_RO(guid); @@ -695,7 +735,7 @@ static ssize_t instance_count_show(struct device *dev, { struct wmi_block *wblock = dev_to_wblock(dev); - return sprintf(buf, "%d\n", (int)wblock->gblock.instance_count); + return sysfs_emit(buf, "%d\n", (int)wblock->gblock.instance_count); } static DEVICE_ATTR_RO(instance_count); @@ -704,8 +744,8 @@ static ssize_t expensive_show(struct device *dev, { struct wmi_block *wblock = dev_to_wblock(dev); - return sprintf(buf, "%d\n", - (wblock->gblock.flags & ACPI_WMI_EXPENSIVE) != 0); + return sysfs_emit(buf, "%d\n", + (wblock->gblock.flags & ACPI_WMI_EXPENSIVE) != 0); } static DEVICE_ATTR_RO(expensive); @@ -714,7 +754,7 @@ static struct attribute *wmi_attrs[] = { &dev_attr_guid.attr, &dev_attr_instance_count.attr, &dev_attr_expensive.attr, - NULL, + NULL }; ATTRIBUTE_GROUPS(wmi); @@ -723,13 +763,13 @@ static ssize_t notify_id_show(struct device *dev, struct device_attribute *attr, { struct wmi_block *wblock = dev_to_wblock(dev); - return sprintf(buf, "%02X\n", (unsigned int)wblock->gblock.notify_id); + return sysfs_emit(buf, "%02X\n", (unsigned int)wblock->gblock.notify_id); } static DEVICE_ATTR_RO(notify_id); static struct attribute *wmi_event_attrs[] = { &dev_attr_notify_id.attr, - NULL, + NULL }; ATTRIBUTE_GROUPS(wmi_event); @@ -738,8 +778,8 @@ static ssize_t object_id_show(struct device *dev, struct device_attribute *attr, { struct wmi_block *wblock = dev_to_wblock(dev); - return sprintf(buf, "%c%c\n", wblock->gblock.object_id[0], - wblock->gblock.object_id[1]); + return sysfs_emit(buf, "%c%c\n", wblock->gblock.object_id[0], + wblock->gblock.object_id[1]); } static DEVICE_ATTR_RO(object_id); @@ -748,20 +788,20 @@ static ssize_t setable_show(struct device *dev, struct device_attribute *attr, { struct wmi_device *wdev = dev_to_wdev(dev); - return sprintf(buf, "%d\n", (int)wdev->setable); + return sysfs_emit(buf, "%d\n", (int)wdev->setable); } static DEVICE_ATTR_RO(setable); static struct attribute *wmi_data_attrs[] = { &dev_attr_object_id.attr, &dev_attr_setable.attr, - NULL, + NULL }; ATTRIBUTE_GROUPS(wmi_data); static struct attribute *wmi_method_attrs[] = { &dev_attr_object_id.attr, - NULL, + NULL }; ATTRIBUTE_GROUPS(wmi_method); @@ -769,10 +809,10 @@ static int wmi_dev_uevent(struct device *dev, struct kobj_uevent_env *env) { struct wmi_block *wblock = dev_to_wblock(dev); - if (add_uevent_var(env, "MODALIAS=wmi:%pUL", wblock->gblock.guid)) + if (add_uevent_var(env, "MODALIAS=wmi:%pUL", &wblock->gblock.guid)) return -ENOMEM; - if (add_uevent_var(env, "WMI_GUID=%pUL", wblock->gblock.guid)) + if (add_uevent_var(env, "WMI_GUID=%pUL", &wblock->gblock.guid)) return -ENOMEM; return 0; @@ -787,8 +827,7 @@ static void wmi_dev_release(struct device *dev) static int wmi_dev_match(struct device *dev, struct device_driver *driver) { - struct wmi_driver *wmi_driver = - container_of(driver, struct wmi_driver, driver); + struct wmi_driver *wmi_driver = drv_to_wdrv(driver); struct wmi_block *wblock = dev_to_wblock(dev); const struct wmi_device_id *id = wmi_driver->id_table; @@ -800,7 +839,7 @@ static int wmi_dev_match(struct device *dev, struct device_driver *driver) if (WARN_ON(guid_parse(id->guid_string, &driver_guid))) continue; - if (!memcmp(&driver_guid, wblock->gblock.guid, 16)) + if (guid_equal(&driver_guid, &wblock->gblock.guid)) return 1; id++; @@ -811,8 +850,8 @@ static int wmi_dev_match(struct device *dev, struct device_driver *driver) static int wmi_char_open(struct inode *inode, struct file *filp) { const char *driver_name = filp->f_path.dentry->d_iname; - struct wmi_block *wblock = NULL; - struct wmi_block *next = NULL; + struct wmi_block *wblock; + struct wmi_block *next; list_for_each_entry_safe(wblock, next, &wmi_block_list, list) { if (!wblock->dev.dev.driver) @@ -830,7 +869,7 @@ static int wmi_char_open(struct inode *inode, struct file *filp) } static ssize_t wmi_char_read(struct file *filp, char __user *buffer, - size_t length, loff_t *offset) + size_t length, loff_t *offset) { struct wmi_block *wblock = filp->private_data; @@ -844,8 +883,8 @@ static long wmi_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) struct wmi_ioctl_buffer __user *input = (struct wmi_ioctl_buffer __user *) arg; struct wmi_block *wblock = filp->private_data; - struct wmi_ioctl_buffer *buf = NULL; - struct wmi_driver *wdriver = NULL; + struct wmi_ioctl_buffer *buf; + struct wmi_driver *wdriver; int ret; if (_IOC_TYPE(cmd) != WMI_IOC) @@ -885,8 +924,7 @@ static long wmi_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) } /* let the driver do any filtering and do the call */ - wdriver = container_of(wblock->dev.dev.driver, - struct wmi_driver, driver); + wdriver = drv_to_wdrv(wblock->dev.dev.driver); if (!try_module_get(wdriver->driver.owner)) { ret = -EBUSY; goto out_ioctl; @@ -919,12 +957,11 @@ static const struct file_operations wmi_fops = { static int wmi_dev_probe(struct device *dev) { struct wmi_block *wblock = dev_to_wblock(dev); - struct wmi_driver *wdriver = - container_of(dev->driver, struct wmi_driver, driver); + struct wmi_driver *wdriver = drv_to_wdrv(dev->driver); int ret = 0; char *buf; - if (ACPI_FAILURE(wmi_method_enable(wblock, 1))) + if (ACPI_FAILURE(wmi_method_enable(wblock, true))) dev_warn(dev, "failed to enable device -- probing anyway\n"); if (wdriver->probe) { @@ -975,7 +1012,7 @@ probe_misc_failure: probe_string_failure: kfree(wblock->handler_data); probe_failure: - if (ACPI_FAILURE(wmi_method_enable(wblock, 0))) + if (ACPI_FAILURE(wmi_method_enable(wblock, false))) dev_warn(dev, "failed to disable device\n"); return ret; } @@ -983,8 +1020,7 @@ probe_failure: static void wmi_dev_remove(struct device *dev) { struct wmi_block *wblock = dev_to_wblock(dev); - struct wmi_driver *wdriver = - container_of(dev->driver, struct wmi_driver, driver); + struct wmi_driver *wdriver = drv_to_wdrv(dev->driver); if (wdriver->filter_callback) { misc_deregister(&wblock->char_dev); @@ -995,7 +1031,7 @@ static void wmi_dev_remove(struct device *dev) if (wdriver->remove) wdriver->remove(dev_to_wdev(dev)); - if (ACPI_FAILURE(wmi_method_enable(wblock, 0))) + if (ACPI_FAILURE(wmi_method_enable(wblock, false))) dev_warn(dev, "failed to disable device\n"); } @@ -1031,20 +1067,19 @@ static const struct device_type wmi_type_data = { }; static int wmi_create_device(struct device *wmi_bus_dev, - const struct guid_block *gblock, struct wmi_block *wblock, struct acpi_device *device) { struct acpi_device_info *info; - char method[5]; + char method[WMI_ACPI_METHOD_NAME_SIZE]; int result; - if (gblock->flags & ACPI_WMI_EVENT) { + if (wblock->gblock.flags & ACPI_WMI_EVENT) { wblock->dev.dev.type = &wmi_type_event; goto out_init; } - if (gblock->flags & ACPI_WMI_METHOD) { + if (wblock->gblock.flags & ACPI_WMI_METHOD) { wblock->dev.dev.type = &wmi_type_method; mutex_init(&wblock->char_mutex); goto out_init; @@ -1055,8 +1090,7 @@ static int wmi_create_device(struct device *wmi_bus_dev, * required per the WMI documentation. If it is not present, * we ignore this data block. */ - strcpy(method, "WQ"); - strncat(method, wblock->gblock.object_id, 2); + get_acpi_method_name(wblock, 'Q', method); result = get_subobj_info(device->handle, method, &info); if (result) { @@ -1083,8 +1117,7 @@ static int wmi_create_device(struct device *wmi_bus_dev, kfree(info); - strcpy(method, "WS"); - strncat(method, wblock->gblock.object_id, 2); + get_acpi_method_name(wblock, 'S', method); result = get_subobj_info(device->handle, method, NULL); if (result == 0) @@ -1094,7 +1127,7 @@ static int wmi_create_device(struct device *wmi_bus_dev, wblock->dev.dev.bus = &wmi_bus_type; wblock->dev.dev.parent = wmi_bus_dev; - dev_set_name(&wblock->dev.dev, "%pUL", gblock->guid); + dev_set_name(&wblock->dev.dev, "%pUL", &wblock->gblock.guid); device_initialize(&wblock->dev.dev); @@ -1114,12 +1147,12 @@ static void wmi_free_devices(struct acpi_device *device) } } -static bool guid_already_parsed(struct acpi_device *device, const u8 *guid) +static bool guid_already_parsed(struct acpi_device *device, const guid_t *guid) { struct wmi_block *wblock; list_for_each_entry(wblock, &wmi_block_list, list) { - if (memcmp(wblock->gblock.guid, guid, 16) == 0) { + if (guid_equal(&wblock->gblock.guid, guid)) { /* * Because we historically didn't track the relationship * between GUIDs and ACPI nodes, we don't know whether @@ -1152,7 +1185,7 @@ static int parse_wdg(struct device *wmi_bus_dev, struct acpi_device *device) if (ACPI_FAILURE(status)) return -ENXIO; - obj = (union acpi_object *) out.pointer; + obj = out.pointer; if (!obj) return -ENXIO; @@ -1174,10 +1207,10 @@ static int parse_wdg(struct device *wmi_bus_dev, struct acpi_device *device) * case yet, so for now, we'll just ignore the duplicate * for device creation. */ - if (guid_already_parsed(device, gblock[i].guid)) + if (guid_already_parsed(device, &gblock[i].guid)) continue; - wblock = kzalloc(sizeof(struct wmi_block), GFP_KERNEL); + wblock = kzalloc(sizeof(*wblock), GFP_KERNEL); if (!wblock) { retval = -ENOMEM; break; @@ -1186,7 +1219,7 @@ static int parse_wdg(struct device *wmi_bus_dev, struct acpi_device *device) wblock->acpi_device = device; wblock->gblock = gblock[i]; - retval = wmi_create_device(wmi_bus_dev, &gblock[i], wblock, device); + retval = wmi_create_device(wmi_bus_dev, wblock, device); if (retval) { kfree(wblock); continue; @@ -1196,7 +1229,7 @@ static int parse_wdg(struct device *wmi_bus_dev, struct acpi_device *device) if (debug_event) { wblock->handler = wmi_notify_debug; - wmi_method_enable(wblock, 1); + wmi_method_enable(wblock, true); } } @@ -1211,9 +1244,9 @@ static int parse_wdg(struct device *wmi_bus_dev, struct acpi_device *device) retval = device_add(&wblock->dev.dev); if (retval) { dev_err(wmi_bus_dev, "failed to register %pUL\n", - wblock->gblock.guid); + &wblock->gblock.guid); if (debug_event) - wmi_method_enable(wblock, 0); + wmi_method_enable(wblock, false); list_del(&wblock->list); put_device(&wblock->dev.dev); } @@ -1230,8 +1263,8 @@ out_free_pointer: */ static acpi_status acpi_wmi_ec_space_handler(u32 function, acpi_physical_address address, - u32 bits, u64 *value, - void *handler_context, void *region_context) + u32 bits, u64 *value, + void *handler_context, void *region_context) { int result = 0, i = 0; u8 temp = 0; @@ -1268,17 +1301,15 @@ acpi_wmi_ec_space_handler(u32 function, acpi_physical_address address, static void acpi_wmi_notify_handler(acpi_handle handle, u32 event, void *context) { - struct guid_block *block; struct wmi_block *wblock; bool found_it = false; list_for_each_entry(wblock, &wmi_block_list, list) { - block = &wblock->gblock; + struct guid_block *block = &wblock->gblock; if (wblock->acpi_device->handle == handle && (block->flags & ACPI_WMI_EVENT) && - (block->notify_id == event)) - { + (block->notify_id == event)) { found_it = true; break; } @@ -1289,31 +1320,18 @@ static void acpi_wmi_notify_handler(acpi_handle handle, u32 event, /* If a driver is bound, then notify the driver. */ if (wblock->dev.dev.driver) { - struct wmi_driver *driver; - struct acpi_object_list input; - union acpi_object params[1]; + struct wmi_driver *driver = drv_to_wdrv(wblock->dev.dev.driver); struct acpi_buffer evdata = { ACPI_ALLOCATE_BUFFER, NULL }; acpi_status status; - driver = container_of(wblock->dev.dev.driver, - struct wmi_driver, driver); - - input.count = 1; - input.pointer = params; - params[0].type = ACPI_TYPE_INTEGER; - params[0].integer.value = event; - - status = acpi_evaluate_object(wblock->acpi_device->handle, - "_WED", &input, &evdata); + status = get_event_data(wblock, &evdata); if (ACPI_FAILURE(status)) { - dev_warn(&wblock->dev.dev, - "failed to get event data\n"); + dev_warn(&wblock->dev.dev, "failed to get event data\n"); return; } if (driver->notify) - driver->notify(&wblock->dev, - (union acpi_object *)evdata.pointer); + driver->notify(&wblock->dev, evdata.pointer); kfree(evdata.pointer); } else if (wblock->handler) { @@ -1322,25 +1340,24 @@ static void acpi_wmi_notify_handler(acpi_handle handle, u32 event, } if (debug_event) - pr_info("DEBUG Event GUID: %pUL\n", wblock->gblock.guid); + pr_info("DEBUG: GUID %pUL event 0x%02X\n", &wblock->gblock.guid, event); acpi_bus_generate_netlink_event( wblock->acpi_device->pnp.device_class, dev_name(&wblock->dev.dev), event, 0); - } static int acpi_wmi_remove(struct platform_device *device) { struct acpi_device *acpi_device = ACPI_COMPANION(&device->dev); - acpi_remove_notify_handler(acpi_device->handle, ACPI_DEVICE_NOTIFY, + acpi_remove_notify_handler(acpi_device->handle, ACPI_ALL_NOTIFY, acpi_wmi_notify_handler); acpi_remove_address_space_handler(acpi_device->handle, ACPI_ADR_SPACE_EC, &acpi_wmi_ec_space_handler); wmi_free_devices(acpi_device); - device_unregister((struct device *)dev_get_drvdata(&device->dev)); + device_unregister(dev_get_drvdata(&device->dev)); return 0; } @@ -1368,7 +1385,7 @@ static int acpi_wmi_probe(struct platform_device *device) } status = acpi_install_notify_handler(acpi_device->handle, - ACPI_DEVICE_NOTIFY, + ACPI_ALL_NOTIFY, acpi_wmi_notify_handler, NULL); if (ACPI_FAILURE(status)) { @@ -1397,7 +1414,7 @@ err_remove_busdev: device_unregister(wmi_bus_dev); err_remove_notify_handler: - acpi_remove_notify_handler(acpi_device->handle, ACPI_DEVICE_NOTIFY, + acpi_remove_notify_handler(acpi_device->handle, ACPI_ALL_NOTIFY, acpi_wmi_notify_handler); err_remove_ec_handler: |