Commit e04e2b76 authored by Armin Wolf's avatar Armin Wolf Committed by Hans de Goede
Browse files

platform/x86: wmi: Pass event data directly to legacy notify handlers



The current legacy WMI handlers are susceptible to picking up wrong
WMI event data on systems where different WMI devices share some
notification IDs.

Prevent this by letting the WMI driver core taking care of retrieving
the event data. This also simplifies the legacy WMI handlers and their
implementation inside the WMI driver core.

Reviewed-by: default avatarIlpo Järvinen <ilpo.jarvinen@linux.intel.com>
Reviewed-by: default avatarHans de Goede <hdegoede@redhat.com>
Signed-off-by: default avatarArmin Wolf <W_Armin@gmx.de>
Link: https://lore.kernel.org/r/20240901031055.3030-3-W_Armin@gmx.de


Signed-off-by: default avatarHans de Goede <hdegoede@redhat.com>
parent 56d8b784
Loading
Loading
Loading
Loading
+6 −16
Original line number Diff line number Diff line
@@ -1597,15 +1597,13 @@ static void hp_wmi_devm_notify_remove(void *ignored)
}

/* hp_wmi_notify - WMI event notification handler */
static void hp_wmi_notify(u32 value, void *context)
static void hp_wmi_notify(union acpi_object *wobj, void *context)
{
	struct hp_wmi_info *temp_info[HP_WMI_MAX_INSTANCES] = {};
	struct acpi_buffer out = { ACPI_ALLOCATE_BUFFER, NULL };
	struct hp_wmi_sensors *state = context;
	struct device *dev = &state->wdev->dev;
	struct hp_wmi_event event = {};
	struct hp_wmi_info *fan_info;
	union acpi_object *wobj;
	acpi_status err;
	int event_type;
	u8 count;
@@ -1630,20 +1628,15 @@ static void hp_wmi_notify(u32 value, void *context)
	 * HPBIOS_BIOSEvent instance.
	 */

	mutex_lock(&state->lock);

	err = wmi_get_event_data(value, &out);
	if (ACPI_FAILURE(err))
		goto out_unlock;

	wobj = out.pointer;
	if (!wobj)
		goto out_unlock;
		return;

	mutex_lock(&state->lock);

	err = populate_event_from_wobj(dev, &event, wobj);
	if (err) {
		dev_warn(dev, "Bad event data (ACPI type %d)\n", wobj->type);
		goto out_free_wobj;
		goto out_free;
	}

	event_type = classify_event(event.name, event.category);
@@ -1668,13 +1661,10 @@ static void hp_wmi_notify(u32 value, void *context)
		break;
	}

out_free_wobj:
	kfree(wobj);

out_free:
	devm_kfree(dev, event.name);
	devm_kfree(dev, event.description);

out_unlock:
	mutex_unlock(&state->lock);
}

+1 −15
Original line number Diff line number Diff line
@@ -2223,39 +2223,25 @@ static void acer_rfkill_exit(void)
	}
}

static void acer_wmi_notify(u32 value, void *context)
static void acer_wmi_notify(union acpi_object *obj, void *context)
{
	struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL };
	union acpi_object *obj;
	struct event_return_value return_value;
	acpi_status status;
	u16 device_state;
	const struct key_entry *key;
	u32 scancode;

	status = wmi_get_event_data(value, &response);
	if (status != AE_OK) {
		pr_warn("bad event status 0x%x\n", status);
		return;
	}

	obj = (union acpi_object *)response.pointer;

	if (!obj)
		return;
	if (obj->type != ACPI_TYPE_BUFFER) {
		pr_warn("Unknown response received %d\n", obj->type);
		kfree(obj);
		return;
	}
	if (obj->buffer.length != 8) {
		pr_warn("Unknown buffer length %d\n", obj->buffer.length);
		kfree(obj);
		return;
	}

	return_value = *((struct event_return_value *)obj->buffer.pointer);
	kfree(obj);

	switch (return_value.function) {
	case WMID_HOTKEY_EVENT:
+3 −16
Original line number Diff line number Diff line
@@ -4201,28 +4201,15 @@ static void asus_wmi_fnlock_update(struct asus_wmi *asus)

/* WMI events *****************************************************************/

static int asus_wmi_get_event_code(u32 value)
static int asus_wmi_get_event_code(union acpi_object *obj)
{
	struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL };
	union acpi_object *obj;
	acpi_status status;
	int code;

	status = wmi_get_event_data(value, &response);
	if (ACPI_FAILURE(status)) {
		pr_warn("Failed to get WMI notify code: %s\n",
				acpi_format_exception(status));
		return -EIO;
	}

	obj = (union acpi_object *)response.pointer;

	if (obj && obj->type == ACPI_TYPE_INTEGER)
		code = (int)(obj->integer.value & WMI_EVENT_MASK);
	else
		code = -EIO;

	kfree(obj);
	return code;
}

@@ -4288,10 +4275,10 @@ static void asus_wmi_handle_event_code(int code, struct asus_wmi *asus)
		pr_info("Unknown key code 0x%x\n", code);
}

static void asus_wmi_notify(u32 value, void *context)
static void asus_wmi_notify(union acpi_object *obj, void *context)
{
	struct asus_wmi *asus = context;
	int code = asus_wmi_get_event_code(value);
	int code = asus_wmi_get_event_code(obj);

	if (code < 0) {
		pr_warn("Failed to get notify code: %d\n", code);
+1 −12
Original line number Diff line number Diff line
@@ -70,20 +70,10 @@ static bool dell_wmi_aio_event_check(u8 *buffer, int length)
	return false;
}

static void dell_wmi_aio_notify(u32 value, void *context)
static void dell_wmi_aio_notify(union acpi_object *obj, void *context)
{
	struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL };
	union acpi_object *obj;
	struct dell_wmi_event *event;
	acpi_status status;

	status = wmi_get_event_data(value, &response);
	if (status != AE_OK) {
		pr_info("bad event status 0x%x\n", status);
		return;
	}

	obj = (union acpi_object *)response.pointer;
	if (obj) {
		unsigned int scancode = 0;

@@ -114,7 +104,6 @@ static void dell_wmi_aio_notify(u32 value, void *context)
			break;
		}
	}
	kfree(obj);
}

static int __init dell_wmi_aio_input_setup(void)
+1 −15
Original line number Diff line number Diff line
@@ -834,28 +834,16 @@ static struct attribute *hp_wmi_attrs[] = {
};
ATTRIBUTE_GROUPS(hp_wmi);

static void hp_wmi_notify(u32 value, void *context)
static void hp_wmi_notify(union acpi_object *obj, void *context)
{
	struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL };
	u32 event_id, event_data;
	union acpi_object *obj;
	acpi_status status;
	u32 *location;
	int key_code;

	status = wmi_get_event_data(value, &response);
	if (status != AE_OK) {
		pr_info("bad event status 0x%x\n", status);
		return;
	}

	obj = (union acpi_object *)response.pointer;

	if (!obj)
		return;
	if (obj->type != ACPI_TYPE_BUFFER) {
		pr_info("Unknown response received %d\n", obj->type);
		kfree(obj);
		return;
	}

@@ -872,10 +860,8 @@ static void hp_wmi_notify(u32 value, void *context)
		event_data = *(location + 2);
	} else {
		pr_info("Unknown buffer length %d\n", obj->buffer.length);
		kfree(obj);
		return;
	}
	kfree(obj);

	switch (event_id) {
	case HPWMI_DOCK_EVENT:
Loading