From: "Ilpo Järvinen" <ilpo.jarvinen@linux.intel.com>
To: Rong Zhang <i@rong.moe>
Cc: Derek John Clark <derekjohn.clark@gmail.com>,
Hans de Goede <hansg@kernel.org>,
oe-kbuild-all@lists.linux.dev,
Mark Pearson <mpearson-lenovo@squebb.ca>,
Armin Wolf <W_Armin@gmx.de>, Jonathan Corbet <corbet@lwn.net>,
Kurt Borja <kuurtb@gmail.com>,
platform-driver-x86@vger.kernel.org,
LKML <linux-kernel@vger.kernel.org>,
kernel test robot <lkp@intel.com>,
stable@vger.kernel.org
Subject: Re: [PATCH] platform/x86: lenovo: Decouple lenovo-wmi-gamezone and lenovo-wmi-other
Date: Fri, 27 Mar 2026 13:25:37 +0200 (EET) [thread overview]
Message-ID: <d824bf55-8c1a-1374-04f9-aff9ffdaaa0d@linux.intel.com> (raw)
In-Reply-To: <20260326161724.72186-1-i@rong.moe>
On Fri, 27 Mar 2026, Rong Zhang wrote:
> Currently, lenovo-wmi-gamezone depends on lenovo-wmi-other as the former
> imports symbols from the latter. The imported symbols are just used to
> register a notifier block. However, there is no runtime dependency
> between both drivers, and either of them can run without the other,
> which is the major purpose of using the notifier framework.
>
> Such a link-time dependency is non-optimal. A previous attempt to "fix"
> it made LENOVO_WMI_GAMEZONE select LENOVO_WMI_TUNING, which was
> fundamentally broken and resulted in undefined Kconfig behavior, as
> `select' cannot be used on a symbol with potentially unmet dependencies.
>
> Decouple both drivers by moving the thermal mode notifier chain to
> lenovo-wmi-helpers. Methods for notifier block (un)registration are
> exported for lenovo-wmi-gamezone, while a method for querying the
> current thermal mode are exported for lenovo-wmi-other.
>
> This turns the dependency graph from
>
> +------------ lenovo-wmi-gamezone
> | |
> v |
> lenovo-wmi-helpers |
> ^ |
> | V
> +------------ lenovo-wmi-other
>
> into
>
> +------------ lenovo-wmi-gamezone
> |
> v
> lenovo-wmi-helpers
> ^
> |
> +------------ lenovo-wmi-other
>
> To make it clear, the name of the notifier chain is also renamed from
> `om_chain_head' to `tm_chain_head', indicating that it's used to query
> the current thermal mode.
>
> No functional change intended.
>
> Fixes: 6e38b9fcbfa3 ("platform/x86: lenovo: gamezone needs "other mode"")
> Cc: stable@vger.kernel.org
> Reported-by: kernel test robot <lkp@intel.com>
> Closes: https://lore.kernel.org/oe-kbuild-all/202603252259.gHvJDyh3-lkp@intel.com/
> Closes: https://lore.kernel.org/oe-kbuild-all/202603260302.X0NjQOda-lkp@intel.com/
> Signed-off-by: Rong Zhang <i@rong.moe>
> ---
> drivers/platform/x86/lenovo/Kconfig | 1 -
> drivers/platform/x86/lenovo/wmi-gamezone.c | 4 +-
> drivers/platform/x86/lenovo/wmi-helpers.c | 102 ++++++++++++++++++++
> drivers/platform/x86/lenovo/wmi-helpers.h | 8 ++
> drivers/platform/x86/lenovo/wmi-other.c | 104 +--------------------
> drivers/platform/x86/lenovo/wmi-other.h | 16 ----
> 6 files changed, 113 insertions(+), 122 deletions(-)
> delete mode 100644 drivers/platform/x86/lenovo/wmi-other.h
>
> diff --git a/drivers/platform/x86/lenovo/Kconfig b/drivers/platform/x86/lenovo/Kconfig
> index f885127b007f..09b1b055d2e0 100644
> --- a/drivers/platform/x86/lenovo/Kconfig
> +++ b/drivers/platform/x86/lenovo/Kconfig
> @@ -252,7 +252,6 @@ config LENOVO_WMI_GAMEZONE
> select ACPI_PLATFORM_PROFILE
> select LENOVO_WMI_EVENTS
> select LENOVO_WMI_HELPERS
> - select LENOVO_WMI_TUNING
> help
> Say Y here if you have a WMI aware Lenovo Legion device and would like to use the
> platform-profile firmware interface to manage power usage.
> diff --git a/drivers/platform/x86/lenovo/wmi-gamezone.c b/drivers/platform/x86/lenovo/wmi-gamezone.c
> index c7fe7e3c9f17..92020225db27 100644
> --- a/drivers/platform/x86/lenovo/wmi-gamezone.c
> +++ b/drivers/platform/x86/lenovo/wmi-gamezone.c
> @@ -23,7 +23,6 @@
> #include "wmi-events.h"
> #include "wmi-gamezone.h"
> #include "wmi-helpers.h"
> -#include "wmi-other.h"
>
> #define LENOVO_GAMEZONE_GUID "887B54E3-DDDC-4B2C-8B88-68A26A8835D0"
>
> @@ -383,7 +382,7 @@ static int lwmi_gz_probe(struct wmi_device *wdev, const void *context)
> return ret;
>
> priv->mode_nb.notifier_call = lwmi_gz_mode_call;
> - return devm_lwmi_om_register_notifier(&wdev->dev, &priv->mode_nb);
> + return devm_lwmi_tm_register_notifier(&wdev->dev, &priv->mode_nb);
> }
>
> static const struct wmi_device_id lwmi_gz_id_table[] = {
> @@ -405,7 +404,6 @@ module_wmi_driver(lwmi_gz_driver);
>
> MODULE_IMPORT_NS("LENOVO_WMI_EVENTS");
> MODULE_IMPORT_NS("LENOVO_WMI_HELPERS");
> -MODULE_IMPORT_NS("LENOVO_WMI_OTHER");
> MODULE_DEVICE_TABLE(wmi, lwmi_gz_id_table);
> MODULE_AUTHOR("Derek J. Clark <derekjohn.clark@gmail.com>");
> MODULE_DESCRIPTION("Lenovo GameZone WMI Driver");
> diff --git a/drivers/platform/x86/lenovo/wmi-helpers.c b/drivers/platform/x86/lenovo/wmi-helpers.c
> index 7379defac500..5a88bccb5037 100644
> --- a/drivers/platform/x86/lenovo/wmi-helpers.c
> +++ b/drivers/platform/x86/lenovo/wmi-helpers.c
> @@ -21,11 +21,16 @@
> #include <linux/errno.h>
> #include <linux/export.h>
> #include <linux/module.h>
> +#include <linux/notifier.h>
> #include <linux/unaligned.h>
> #include <linux/wmi.h>
>
> +#include "wmi-gamezone.h"
> #include "wmi-helpers.h"
>
> +/* Thermal mode notifier chain. */
> +static BLOCKING_NOTIFIER_HEAD(tm_chain_head);
> +
> /**
> * lwmi_dev_evaluate_int() - Helper function for calling WMI methods that
> * return an integer.
> @@ -84,6 +89,103 @@ int lwmi_dev_evaluate_int(struct wmi_device *wdev, u8 instance, u32 method_id,
> };
> EXPORT_SYMBOL_NS_GPL(lwmi_dev_evaluate_int, "LENOVO_WMI_HELPERS");
>
> +/**
> + * lwmi_tm_register_notifier() - Add a notifier to the blocking notifier chain
> + * @nb: The notifier_block struct to register
> + *
> + * Call blocking_notifier_chain_register to register the notifier block to the
> + * thermal mode notifier chain.
> + *
> + * Return: 0 on success, %-EEXIST on error.
> + */
> +int lwmi_tm_register_notifier(struct notifier_block *nb)
> +{
> + return blocking_notifier_chain_register(&tm_chain_head, nb);
> +}
> +EXPORT_SYMBOL_NS_GPL(lwmi_tm_register_notifier, "LENOVO_WMI_HELPERS");
> +
> +/**
> + * lwmi_tm_unregister_notifier() - Remove a notifier from the blocking notifier
> + * chain.
> + * @nb: The notifier_block struct to register
> + *
> + * Call blocking_notifier_chain_unregister to unregister the notifier block from the
> + * thermal mode notifier chain.
> + *
> + * Return: 0 on success, %-ENOENT on error.
> + */
> +int lwmi_tm_unregister_notifier(struct notifier_block *nb)
> +{
> + return blocking_notifier_chain_unregister(&tm_chain_head, nb);
> +}
> +EXPORT_SYMBOL_NS_GPL(lwmi_tm_unregister_notifier, "LENOVO_WMI_HELPERS");
> +
> +/**
> + * devm_lwmi_tm_unregister_notifier() - Remove a notifier from the blocking
> + * notifier chain.
> + * @data: Void pointer to the notifier_block struct to register.
> + *
> + * Call lwmi_tm_unregister_notifier to unregister the notifier block from the
> + * thermal mode notifier chain.
> + *
> + * Return: 0 on success, %-ENOENT on error.
> + */
> +static void devm_lwmi_tm_unregister_notifier(void *data)
> +{
> + struct notifier_block *nb = data;
> +
> + lwmi_tm_unregister_notifier(nb);
> +}
> +
> +/**
> + * devm_lwmi_tm_register_notifier() - Add a notifier to the blocking notifier
> + * chain.
> + * @dev: The parent device of the notifier_block struct.
> + * @nb: The notifier_block struct to register
> + *
> + * Call lwmi_tm_register_notifier to register the notifier block to the
> + * thermal mode notifier chain. Then add devm_lwmi_tm_unregister_notifier
> + * as a device managed action to automatically unregister the notifier block
> + * upon parent device removal.
> + *
> + * Return: 0 on success, or an error code.
> + */
> +int devm_lwmi_tm_register_notifier(struct device *dev,
> + struct notifier_block *nb)
> +{
> + int ret;
> +
> + ret = lwmi_tm_register_notifier(nb);
> + if (ret < 0)
> + return ret;
> +
> + return devm_add_action_or_reset(dev, devm_lwmi_tm_unregister_notifier,
> + nb);
> +}
> +EXPORT_SYMBOL_NS_GPL(devm_lwmi_tm_register_notifier, "LENOVO_WMI_HELPERS");
> +
> +/**
> + * lwmi_tm_notifier_call() - Call functions for the notifier call chain.
> + * @mode: Pointer to a thermal mode enum to retrieve the data from.
> + *
> + * Call blocking_notifier_call_chain to retrieve the thermal mode from the
> + * lenovo-wmi-gamezone driver.
> + *
> + * Return: 0 on success, or an error code.
> + */
> +int lwmi_tm_notifier_call(enum thermal_mode *mode)
> +{
> + int ret;
> +
> + ret = blocking_notifier_call_chain(&tm_chain_head,
> + LWMI_GZ_GET_THERMAL_MODE, &mode);
> + if ((ret & ~NOTIFY_STOP_MASK) != NOTIFY_OK)
> + return -EINVAL;
> +
> + return 0;
> +}
> +EXPORT_SYMBOL_NS_GPL(lwmi_tm_notifier_call, "LENOVO_WMI_HELPERS");
> +
> MODULE_AUTHOR("Derek J. Clark <derekjohn.clark@gmail.com>");
> 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
> index 20fd21749803..651a039228ed 100644
> --- a/drivers/platform/x86/lenovo/wmi-helpers.h
> +++ b/drivers/platform/x86/lenovo/wmi-helpers.h
> @@ -7,6 +7,8 @@
>
> #include <linux/types.h>
>
> +struct device;
> +struct notifier_block;
> struct wmi_device;
>
> struct wmi_method_args_32 {
> @@ -17,4 +19,10 @@ struct wmi_method_args_32 {
> int lwmi_dev_evaluate_int(struct wmi_device *wdev, u8 instance, u32 method_id,
> unsigned char *buf, size_t size, u32 *retval);
>
> +int lwmi_tm_register_notifier(struct notifier_block *nb);
> +int lwmi_tm_unregister_notifier(struct notifier_block *nb);
> +int devm_lwmi_tm_register_notifier(struct device *dev,
> + struct notifier_block *nb);
> +int lwmi_tm_notifier_call(enum thermal_mode *mode);
This enum is not introduced earlier within this header?
--
i.
> +
> #endif /* !_LENOVO_WMI_HELPERS_H_ */
> diff --git a/drivers/platform/x86/lenovo/wmi-other.c b/drivers/platform/x86/lenovo/wmi-other.c
> index 6040f45aa2b0..b394cc8168a6 100644
> --- a/drivers/platform/x86/lenovo/wmi-other.c
> +++ b/drivers/platform/x86/lenovo/wmi-other.c
> @@ -40,7 +40,6 @@
> #include <linux/kobject.h>
> #include <linux/limits.h>
> #include <linux/module.h>
> -#include <linux/notifier.h>
> #include <linux/platform_profile.h>
> #include <linux/types.h>
> #include <linux/wmi.h>
> @@ -49,7 +48,6 @@
> #include "wmi-events.h"
> #include "wmi-gamezone.h"
> #include "wmi-helpers.h"
> -#include "wmi-other.h"
> #include "../firmware_attributes_class.h"
>
> #define LENOVO_OTHER_MODE_GUID "DC2A8805-3A8C-41BA-A6F7-092E0089CD3B"
> @@ -81,7 +79,6 @@
> #define LWMI_OM_FW_ATTR_BASE_PATH "lenovo-wmi-other"
> #define LWMI_OM_HWMON_NAME "lenovo_wmi_other"
>
> -static BLOCKING_NOTIFIER_HEAD(om_chain_head);
> static DEFINE_IDA(lwmi_om_ida);
>
> enum attribute_property {
> @@ -109,7 +106,6 @@ struct lwmi_om_priv {
> struct device *hwmon_dev;
> struct device *fw_attr_dev;
> struct kset *fw_attr_kset;
> - struct notifier_block nb;
> struct wmi_device *wdev;
> int ida_id;
>
> @@ -576,102 +572,6 @@ struct capdata01_attr_group {
> struct tunable_attr_01 *tunable_attr;
> };
>
> -/**
> - * lwmi_om_register_notifier() - Add a notifier to the blocking notifier chain
> - * @nb: The notifier_block struct to register
> - *
> - * Call blocking_notifier_chain_register to register the notifier block to the
> - * lenovo-wmi-other driver notifier chain.
> - *
> - * Return: 0 on success, %-EEXIST on error.
> - */
> -int lwmi_om_register_notifier(struct notifier_block *nb)
> -{
> - return blocking_notifier_chain_register(&om_chain_head, nb);
> -}
> -EXPORT_SYMBOL_NS_GPL(lwmi_om_register_notifier, "LENOVO_WMI_OTHER");
> -
> -/**
> - * lwmi_om_unregister_notifier() - Remove a notifier from the blocking notifier
> - * chain.
> - * @nb: The notifier_block struct to register
> - *
> - * Call blocking_notifier_chain_unregister to unregister the notifier block from the
> - * lenovo-wmi-other driver notifier chain.
> - *
> - * Return: 0 on success, %-ENOENT on error.
> - */
> -int lwmi_om_unregister_notifier(struct notifier_block *nb)
> -{
> - return blocking_notifier_chain_unregister(&om_chain_head, nb);
> -}
> -EXPORT_SYMBOL_NS_GPL(lwmi_om_unregister_notifier, "LENOVO_WMI_OTHER");
> -
> -/**
> - * devm_lwmi_om_unregister_notifier() - Remove a notifier from the blocking
> - * notifier chain.
> - * @data: Void pointer to the notifier_block struct to register.
> - *
> - * Call lwmi_om_unregister_notifier to unregister the notifier block from the
> - * lenovo-wmi-other driver notifier chain.
> - *
> - * Return: 0 on success, %-ENOENT on error.
> - */
> -static void devm_lwmi_om_unregister_notifier(void *data)
> -{
> - struct notifier_block *nb = data;
> -
> - lwmi_om_unregister_notifier(nb);
> -}
> -
> -/**
> - * devm_lwmi_om_register_notifier() - Add a notifier to the blocking notifier
> - * chain.
> - * @dev: The parent device of the notifier_block struct.
> - * @nb: The notifier_block struct to register
> - *
> - * Call lwmi_om_register_notifier to register the notifier block to the
> - * lenovo-wmi-other driver notifier chain. Then add devm_lwmi_om_unregister_notifier
> - * as a device managed action to automatically unregister the notifier block
> - * upon parent device removal.
> - *
> - * Return: 0 on success, or an error code.
> - */
> -int devm_lwmi_om_register_notifier(struct device *dev,
> - struct notifier_block *nb)
> -{
> - int ret;
> -
> - ret = lwmi_om_register_notifier(nb);
> - if (ret < 0)
> - return ret;
> -
> - return devm_add_action_or_reset(dev, devm_lwmi_om_unregister_notifier,
> - nb);
> -}
> -EXPORT_SYMBOL_NS_GPL(devm_lwmi_om_register_notifier, "LENOVO_WMI_OTHER");
> -
> -/**
> - * lwmi_om_notifier_call() - Call functions for the notifier call chain.
> - * @mode: Pointer to a thermal mode enum to retrieve the data from.
> - *
> - * Call blocking_notifier_call_chain to retrieve the thermal mode from the
> - * lenovo-wmi-gamezone driver.
> - *
> - * Return: 0 on success, or an error code.
> - */
> -static int lwmi_om_notifier_call(enum thermal_mode *mode)
> -{
> - int ret;
> -
> - ret = blocking_notifier_call_chain(&om_chain_head,
> - LWMI_GZ_GET_THERMAL_MODE, &mode);
> - if ((ret & ~NOTIFY_STOP_MASK) != NOTIFY_OK)
> - return -EINVAL;
> -
> - return 0;
> -}
> -
> /* Attribute Methods */
>
> /**
> @@ -780,7 +680,7 @@ static ssize_t attr_current_value_store(struct kobject *kobj,
> u32 value;
> int ret;
>
> - ret = lwmi_om_notifier_call(&mode);
> + ret = lwmi_tm_notifier_call(&mode);
> if (ret)
> return ret;
>
> @@ -842,7 +742,7 @@ static ssize_t attr_current_value_show(struct kobject *kobj,
> int retval;
> int ret;
>
> - ret = lwmi_om_notifier_call(&mode);
> + ret = lwmi_tm_notifier_call(&mode);
> if (ret)
> return ret;
>
> diff --git a/drivers/platform/x86/lenovo/wmi-other.h b/drivers/platform/x86/lenovo/wmi-other.h
> deleted file mode 100644
> index 8ebf5602bb99..000000000000
> --- a/drivers/platform/x86/lenovo/wmi-other.h
> +++ /dev/null
> @@ -1,16 +0,0 @@
> -/* SPDX-License-Identifier: GPL-2.0-or-later */
> -
> -/* Copyright (C) 2025 Derek J. Clark <derekjohn.clark@gmail.com> */
> -
> -#ifndef _LENOVO_WMI_OTHER_H_
> -#define _LENOVO_WMI_OTHER_H_
> -
> -struct device;
> -struct notifier_block;
> -
> -int lwmi_om_register_notifier(struct notifier_block *nb);
> -int lwmi_om_unregister_notifier(struct notifier_block *nb);
> -int devm_lwmi_om_register_notifier(struct device *dev,
> - struct notifier_block *nb);
> -
> -#endif /* !_LENOVO_WMI_OTHER_H_ */
>
> base-commit: 0138af2472dfdef0d56fc4697416eaa0ff2589bd
>
next prev parent reply other threads:[~2026-03-27 11:25 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <861d0276a759461be446df8e996d196037c9b581.camel@rong.moe>
2026-03-26 16:17 ` [PATCH] platform/x86: lenovo: Decouple lenovo-wmi-gamezone and lenovo-wmi-other Rong Zhang
2026-03-27 11:25 ` Ilpo Järvinen [this message]
2026-03-27 15:16 ` Rong Zhang
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=d824bf55-8c1a-1374-04f9-aff9ffdaaa0d@linux.intel.com \
--to=ilpo.jarvinen@linux.intel.com \
--cc=W_Armin@gmx.de \
--cc=corbet@lwn.net \
--cc=derekjohn.clark@gmail.com \
--cc=hansg@kernel.org \
--cc=i@rong.moe \
--cc=kuurtb@gmail.com \
--cc=linux-kernel@vger.kernel.org \
--cc=lkp@intel.com \
--cc=mpearson-lenovo@squebb.ca \
--cc=oe-kbuild-all@lists.linux.dev \
--cc=platform-driver-x86@vger.kernel.org \
--cc=stable@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox