The ACPI DSDT table includes multiple WMI blocks which emit events with the same notify_id. The wmi_get_event_data() function chooses the wmi_block with the _WED handler to call based on the notify_id. This function may call the wrong _WED event handler based on the order the WMI blocks are parsed. This introduces wmi_get_event_data_with_guid() to diambiguate the _WED call to get metadata for an event. The GUID here is the one of the containing WMI block, not the one of the WMI event itself. Signed-off-by: Philipp Jungkamp <p.jungkamp@xxxxxxx> --- Was separating this change into it's own commit correct? drivers/platform/x86/wmi.c | 30 ++++++++++++++++++++++++++++++ include/linux/acpi.h | 3 +++ 2 files changed, 33 insertions(+) diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c index 223550a10d4d..56b666f4b40b 100644 --- a/drivers/platform/x86/wmi.c +++ b/drivers/platform/x86/wmi.c @@ -659,6 +659,36 @@ acpi_status wmi_get_event_data(u32 event, struct acpi_buffer *out) } EXPORT_SYMBOL_GPL(wmi_get_event_data); +/** + * wmi_get_event_data_with_guid - Get WMI data associated with an event by guid + * + * Consider using this instead of wmi_get_event_data() when the notify_id + * of the WMI event may not be unique among all WMI blocks of a device. + * + * @guid: GUID of the WMI block for this event + * @event: Event to find + * @out: Buffer to hold event data. out->pointer should be freed with kfree() + * + * Returns extra data associated with an event in WMI. + */ +acpi_status wmi_get_event_data_with_guid(const char *guid, u32 event, struct acpi_buffer *out) +{ + struct wmi_block *wblock = NULL; + struct guid_block *gblock; + acpi_status status; + + status = find_guid(guid, &wblock); + if (ACPI_FAILURE(status)) + return AE_NOT_FOUND; + + gblock = &wblock->gblock; + if ((gblock->flags & ACPI_WMI_EVENT) && gblock->notify_id == event) + return get_event_data(wblock, out); + + return AE_NOT_FOUND; +} +EXPORT_SYMBOL_GPL(wmi_get_event_data_with_guid); + /** * wmi_has_guid - Check if a GUID is available * @guid_string: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 3015235d65e3..51ac4d6bcae1 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -423,6 +423,9 @@ extern acpi_status wmi_set_block(const char *guid, u8 instance, extern acpi_status wmi_install_notify_handler(const char *guid, wmi_notify_handler handler, void *data); extern acpi_status wmi_remove_notify_handler(const char *guid); +extern acpi_status wmi_get_event_data_with_guid(const char *guid, + u32 event, + struct acpi_buffer *out); extern acpi_status wmi_get_event_data(u32 event, struct acpi_buffer *out); extern bool wmi_has_guid(const char *guid); extern char *wmi_get_acpi_device_uid(const char *guid); -- 2.38.1