platform/x86: lenovo-wmi-helpers: Adopt new WMI API

The new WMI API supports multiple ACPI types by converting them into a
unified buffer that satisfies alignment and size requirements.

Adopt it to make our life easier.

Note that the Windows WMI-ACPI driver converts all ACPI objects into a
common buffer format, so adopting the new API intentionally accepts more
ACPI types as a followup of commit 465dc9da8f ("platform/x86:
lenovo-wmi-helpers: Convert returned buffer into u32").

Suggested-by: Armin Wolf <W_Armin@gmx.de>
Link: https://lore.kernel.org/r/f1787927-b655-4321-b9d9-bc12353c72db@gmx.de/
Reviewed-by: Armin Wolf <W_Armin@gmx.de>
Tested-by: Navon John Lukose <navonjohnlukose@gmail.com>
Reviewed-by: Derek J. Clark <derekjohn.clark@gmail.com>
Reviewed-by: Mark Pearson <mpearson-lenovo@squebb.ca>
Signed-off-by: Rong Zhang <i@rong.moe>
Link: https://patch.msgid.link/20261019-lwmi-wmi-new-api-v5-11-71557d28d058@rong.moe
Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
This commit is contained in:
Rong Zhang 2026-10-19 23:02:33 +08:00 committed by Ilpo Järvinen
parent 1e99760fb0
commit 87a7c09a9d
No known key found for this signature in database
GPG Key ID: 59AC4F6153E5CE31

View File

@ -24,9 +24,10 @@
#include <linux/export.h>
#include <linux/module.h>
#include <linux/notifier.h>
#include <linux/unaligned.h>
#include <linux/wmi.h>
#include <asm/byteorder.h>
#include "wmi-helpers.h"
/* Thermal mode notifier chain. */
@ -42,49 +43,33 @@ static BLOCKING_NOTIFIER_HEAD(tm_chain_head);
* @size: Length of the buffer.
* @retval: Pointer for the return value to be assigned.
*
* Calls wmidev_evaluate_method for Lenovo WMI devices that return an ACPI
* integer. Validates the return value type and assigns the value to the
* retval pointer.
* Calls the specified WMI method for Lenovo WMI devices that return a WMI
* integer. Validates the return value and assigns it to @retval when it's not
* NULL, otherwise the return value is not validated.
*
* Return: 0 on success, or an error code.
*/
int lwmi_dev_evaluate_int(struct wmi_device *wdev, u8 instance, u32 method_id,
unsigned char *buf, size_t size, u32 *retval)
{
struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
struct acpi_buffer input = { size, buf };
acpi_status status;
struct wmi_buffer input = {
.length = size,
.data = buf,
};
struct wmi_buffer output;
int ret;
status = wmidev_evaluate_method(wdev, instance, method_id, &input,
&output);
if (ACPI_FAILURE(status))
return -EIO;
if (!retval)
return wmidev_invoke_procedure(wdev, instance, method_id, &input);
union acpi_object *ret_obj __free(kfree) = output.pointer;
ret = wmidev_invoke_method(wdev, instance, method_id, &input,
&output, sizeof(__le32));
if (ret)
return ret;
if (retval) {
if (!ret_obj)
return -ENODATA;
__le32 *valp __free(kfree) = output.data;
switch (ret_obj->type) {
/*
* The ACPI method may simply return a buffer when a u32
* is expected. This is valid on Windows as its WMI-ACPI
* driver converts everything to a common buffer.
*/
case ACPI_TYPE_BUFFER:
if (ret_obj->buffer.length < sizeof(u32))
return -ENXIO;
*retval = get_unaligned_le32(ret_obj->buffer.pointer);
return 0;
case ACPI_TYPE_INTEGER:
*retval = (u32)ret_obj->integer.value;
return 0;
default:
return -ENXIO;
}
}
*retval = le32_to_cpu(*valp);
return 0;
};