aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/platform/x86/wmi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/platform/x86/wmi.c')
-rw-r--r--drivers/platform/x86/wmi.c375
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 = &param,
+ };
+
+ 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: