From: Derek J. Clark Date: Wed, 2 Jul 2025 03:38:22 +0000 (-0700) Subject: platform/x86: Add lenovo-wmi-helpers X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e521d16e76cd9ea99c585e064f4e7daf657b1451;p=thirdparty%2Fkernel%2Fstable.git platform/x86: Add lenovo-wmi-helpers Adds lenovo-wmi-helpers, which provides a common wrapper function for wmidev_evaluate_method that does data validation and error handling. Reviewed-by: Alok Tiwari Reviewed-by: Armin Wolf Reviewed-by: Mario Limonciello Signed-off-by: Derek J. Clark Link: https://lore.kernel.org/r/20250702033826.1057762-3-derekjohn.clark@gmail.com Reviewed-by: Ilpo Järvinen Signed-off-by: Ilpo Järvinen --- diff --git a/drivers/platform/x86/lenovo/Kconfig b/drivers/platform/x86/lenovo/Kconfig index 05dab29a22f71..abb4888898341 100644 --- a/drivers/platform/x86/lenovo/Kconfig +++ b/drivers/platform/x86/lenovo/Kconfig @@ -232,3 +232,7 @@ config YT2_1380 To compile this driver as a module, choose M here: the module will be called lenovo-yogabook. + +config LENOVO_WMI_HELPERS + tristate + depends on ACPI_WMI diff --git a/drivers/platform/x86/lenovo/Makefile b/drivers/platform/x86/lenovo/Makefile index f1aa2449293b3..a347d657d2358 100644 --- a/drivers/platform/x86/lenovo/Makefile +++ b/drivers/platform/x86/lenovo/Makefile @@ -12,6 +12,7 @@ lenovo-target-$(CONFIG_LENOVO_YMC) += ymc.o lenovo-target-$(CONFIG_YOGABOOK) += yogabook.o lenovo-target-$(CONFIG_YT2_1380) += yoga-tab2-pro-1380-fastcharger.o lenovo-target-$(CONFIG_LENOVO_WMI_CAMERA) += wmi-camera.o +lenovo-target-$(CONFIG_LENOVO_WMI_HELPERS) += wmi-helpers.o # Add 'lenovo' prefix to each module listed in lenovo-target-* define LENOVO_OBJ_TARGET diff --git a/drivers/platform/x86/lenovo/wmi-helpers.c b/drivers/platform/x86/lenovo/wmi-helpers.c new file mode 100644 index 0000000000000..f6fef6296251e --- /dev/null +++ b/drivers/platform/x86/lenovo/wmi-helpers.c @@ -0,0 +1,74 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Lenovo Legion WMI helpers driver. + * + * The Lenovo Legion WMI interface is broken up into multiple GUID interfaces + * that require cross-references between GUID's for some functionality. The + * "Custom Mode" interface is a legacy interface for managing and displaying + * CPU & GPU power and hwmon settings and readings. The "Other Mode" interface + * is a modern interface that replaces or extends the "Custom Mode" interface + * methods. The "Gamezone" interface adds advanced features such as fan + * profiles and overclocking. The "Lighting" interface adds control of various + * status lights related to different hardware components. Each of these + * drivers uses a common procedure to get data from the WMI interface, + * enumerated here. + * + * Copyright (C) 2025 Derek J. Clark + */ + +#include +#include +#include +#include +#include +#include + +#include "wmi-helpers.h" + +/** + * lwmi_dev_evaluate_int() - Helper function for calling WMI methods that + * return an integer. + * @wdev: Pointer to the WMI device to be called. + * @instance: Instance of the called method. + * @method_id: WMI Method ID for the method to be called. + * @buf: Buffer of all arguments for the given method_id. + * @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. + * + * 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 }; + union acpi_object *ret_obj __free(kfree) = NULL; + struct acpi_buffer input = { size, buf }; + acpi_status status; + + status = wmidev_evaluate_method(wdev, instance, method_id, &input, + &output); + if (ACPI_FAILURE(status)) + return -EIO; + + if (retval) { + ret_obj = output.pointer; + if (!ret_obj) + return -ENODATA; + + if (ret_obj->type != ACPI_TYPE_INTEGER) + return -ENXIO; + + *retval = (u32)ret_obj->integer.value; + } + + return 0; +}; +EXPORT_SYMBOL_NS_GPL(lwmi_dev_evaluate_int, "LENOVO_WMI_HELPERS"); + +MODULE_AUTHOR("Derek J. Clark "); +MODULE_DESCRIPTION("Lenovo WMI Helpers Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/platform/x86/lenovo/wmi-helpers.h b/drivers/platform/x86/lenovo/wmi-helpers.h new file mode 100644 index 0000000000000..20fd217498035 --- /dev/null +++ b/drivers/platform/x86/lenovo/wmi-helpers.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +/* Copyright (C) 2025 Derek J. Clark */ + +#ifndef _LENOVO_WMI_HELPERS_H_ +#define _LENOVO_WMI_HELPERS_H_ + +#include + +struct wmi_device; + +struct wmi_method_args_32 { + u32 arg0; + u32 arg1; +}; + +int lwmi_dev_evaluate_int(struct wmi_device *wdev, u8 instance, u32 method_id, + unsigned char *buf, size_t size, u32 *retval); + +#endif /* !_LENOVO_WMI_HELPERS_H_ */