Skip to content

Commit fe087a8

Browse files
Rongronggg91Naim
authored andcommitted
platform/x86: lenovo: Decouple lenovo-wmi-gamezone and lenovo-wmi-other
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: 6e38b9f ("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>
1 parent e5ff74f commit fe087a8

6 files changed

Lines changed: 112 additions & 122 deletions

File tree

drivers/platform/x86/lenovo/Kconfig

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,6 @@ config LENOVO_WMI_GAMEZONE
252252
select ACPI_PLATFORM_PROFILE
253253
select LENOVO_WMI_EVENTS
254254
select LENOVO_WMI_HELPERS
255-
select LENOVO_WMI_TUNING
256255
help
257256
Say Y here if you have a WMI aware Lenovo Legion device and would like to use the
258257
platform-profile firmware interface to manage power usage.

drivers/platform/x86/lenovo/wmi-gamezone.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
#include "wmi-events.h"
2424
#include "wmi-gamezone.h"
2525
#include "wmi-helpers.h"
26-
#include "wmi-other.h"
2726

2827
#define LENOVO_GAMEZONE_GUID "887B54E3-DDDC-4B2C-8B88-68A26A8835D0"
2928

@@ -385,7 +384,7 @@ static int lwmi_gz_probe(struct wmi_device *wdev, const void *context)
385384
return ret;
386385

387386
priv->mode_nb.notifier_call = lwmi_gz_mode_call;
388-
return devm_lwmi_om_register_notifier(&wdev->dev, &priv->mode_nb);
387+
return devm_lwmi_tm_register_notifier(&wdev->dev, &priv->mode_nb);
389388
}
390389

391390
static const struct wmi_device_id lwmi_gz_id_table[] = {
@@ -407,7 +406,6 @@ module_wmi_driver(lwmi_gz_driver);
407406

408407
MODULE_IMPORT_NS("LENOVO_WMI_EVENTS");
409408
MODULE_IMPORT_NS("LENOVO_WMI_HELPERS");
410-
MODULE_IMPORT_NS("LENOVO_WMI_OTHER");
411409
MODULE_DEVICE_TABLE(wmi, lwmi_gz_id_table);
412410
MODULE_AUTHOR("Derek J. Clark <derekjohn.clark@gmail.com>");
413411
MODULE_DESCRIPTION("Lenovo GameZone WMI Driver");

drivers/platform/x86/lenovo/wmi-helpers.c

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,15 @@
2121
#include <linux/errno.h>
2222
#include <linux/export.h>
2323
#include <linux/module.h>
24+
#include <linux/notifier.h>
2425
#include <linux/unaligned.h>
2526
#include <linux/wmi.h>
2627

2728
#include "wmi-helpers.h"
2829

30+
/* Thermal mode notifier chain. */
31+
static BLOCKING_NOTIFIER_HEAD(tm_chain_head);
32+
2933
/**
3034
* lwmi_dev_evaluate_int() - Helper function for calling WMI methods that
3135
* return an integer.
@@ -85,6 +89,103 @@ int lwmi_dev_evaluate_int(struct wmi_device *wdev, u8 instance, u32 method_id,
8589
};
8690
EXPORT_SYMBOL_NS_GPL(lwmi_dev_evaluate_int, "LENOVO_WMI_HELPERS");
8791

92+
/**
93+
* lwmi_tm_register_notifier() - Add a notifier to the blocking notifier chain
94+
* @nb: The notifier_block struct to register
95+
*
96+
* Call blocking_notifier_chain_register to register the notifier block to the
97+
* thermal mode notifier chain.
98+
*
99+
* Return: 0 on success, %-EEXIST on error.
100+
*/
101+
int lwmi_tm_register_notifier(struct notifier_block *nb)
102+
{
103+
return blocking_notifier_chain_register(&tm_chain_head, nb);
104+
}
105+
EXPORT_SYMBOL_NS_GPL(lwmi_tm_register_notifier, "LENOVO_WMI_HELPERS");
106+
107+
/**
108+
* lwmi_tm_unregister_notifier() - Remove a notifier from the blocking notifier
109+
* chain.
110+
* @nb: The notifier_block struct to register
111+
*
112+
* Call blocking_notifier_chain_unregister to unregister the notifier block from the
113+
* thermal mode notifier chain.
114+
*
115+
* Return: 0 on success, %-ENOENT on error.
116+
*/
117+
int lwmi_tm_unregister_notifier(struct notifier_block *nb)
118+
{
119+
return blocking_notifier_chain_unregister(&tm_chain_head, nb);
120+
}
121+
EXPORT_SYMBOL_NS_GPL(lwmi_tm_unregister_notifier, "LENOVO_WMI_HELPERS");
122+
123+
/**
124+
* devm_lwmi_tm_unregister_notifier() - Remove a notifier from the blocking
125+
* notifier chain.
126+
* @data: Void pointer to the notifier_block struct to register.
127+
*
128+
* Call lwmi_tm_unregister_notifier to unregister the notifier block from the
129+
* thermal mode notifier chain.
130+
*
131+
* Return: 0 on success, %-ENOENT on error.
132+
*/
133+
static void devm_lwmi_tm_unregister_notifier(void *data)
134+
{
135+
struct notifier_block *nb = data;
136+
137+
lwmi_tm_unregister_notifier(nb);
138+
}
139+
140+
/**
141+
* devm_lwmi_tm_register_notifier() - Add a notifier to the blocking notifier
142+
* chain.
143+
* @dev: The parent device of the notifier_block struct.
144+
* @nb: The notifier_block struct to register
145+
*
146+
* Call lwmi_tm_register_notifier to register the notifier block to the
147+
* thermal mode notifier chain. Then add devm_lwmi_tm_unregister_notifier
148+
* as a device managed action to automatically unregister the notifier block
149+
* upon parent device removal.
150+
*
151+
* Return: 0 on success, or an error code.
152+
*/
153+
int devm_lwmi_tm_register_notifier(struct device *dev,
154+
struct notifier_block *nb)
155+
{
156+
int ret;
157+
158+
ret = lwmi_tm_register_notifier(nb);
159+
if (ret < 0)
160+
return ret;
161+
162+
return devm_add_action_or_reset(dev, devm_lwmi_tm_unregister_notifier,
163+
nb);
164+
}
165+
EXPORT_SYMBOL_NS_GPL(devm_lwmi_tm_register_notifier, "LENOVO_WMI_HELPERS");
166+
167+
/**
168+
* lwmi_tm_notifier_call() - Call functions for the notifier call chain.
169+
* @mode: Pointer to a thermal mode enum to retrieve the data from.
170+
*
171+
* Call blocking_notifier_call_chain to retrieve the thermal mode from the
172+
* lenovo-wmi-gamezone driver.
173+
*
174+
* Return: 0 on success, or an error code.
175+
*/
176+
int lwmi_tm_notifier_call(enum thermal_mode *mode)
177+
{
178+
int ret;
179+
180+
ret = blocking_notifier_call_chain(&tm_chain_head,
181+
LWMI_GZ_GET_THERMAL_MODE, &mode);
182+
if ((ret & ~NOTIFY_STOP_MASK) != NOTIFY_OK)
183+
return -EINVAL;
184+
185+
return 0;
186+
}
187+
EXPORT_SYMBOL_NS_GPL(lwmi_tm_notifier_call, "LENOVO_WMI_HELPERS");
188+
88189
MODULE_AUTHOR("Derek J. Clark <derekjohn.clark@gmail.com>");
89190
MODULE_DESCRIPTION("Lenovo WMI Helpers Driver");
90191
MODULE_LICENSE("GPL");

drivers/platform/x86/lenovo/wmi-helpers.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77

88
#include <linux/types.h>
99

10+
struct device;
11+
struct notifier_block;
1012
struct wmi_device;
1113

1214
struct wmi_method_args_32 {
@@ -17,4 +19,10 @@ struct wmi_method_args_32 {
1719
int lwmi_dev_evaluate_int(struct wmi_device *wdev, u8 instance, u32 method_id,
1820
unsigned char *buf, size_t size, u32 *retval);
1921

22+
int lwmi_tm_register_notifier(struct notifier_block *nb);
23+
int lwmi_tm_unregister_notifier(struct notifier_block *nb);
24+
int devm_lwmi_tm_register_notifier(struct device *dev,
25+
struct notifier_block *nb);
26+
int lwmi_tm_notifier_call(enum thermal_mode *mode);
27+
2028
#endif /* !_LENOVO_WMI_HELPERS_H_ */

drivers/platform/x86/lenovo/wmi-other.c

Lines changed: 2 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@
4040
#include <linux/kobject.h>
4141
#include <linux/limits.h>
4242
#include <linux/module.h>
43-
#include <linux/notifier.h>
4443
#include <linux/platform_profile.h>
4544
#include <linux/types.h>
4645
#include <linux/wmi.h>
@@ -49,7 +48,6 @@
4948
#include "wmi-events.h"
5049
#include "wmi-gamezone.h"
5150
#include "wmi-helpers.h"
52-
#include "wmi-other.h"
5351
#include "../firmware_attributes_class.h"
5452

5553
#define LENOVO_OTHER_MODE_GUID "DC2A8805-3A8C-41BA-A6F7-092E0089CD3B"
@@ -81,7 +79,6 @@
8179
#define LWMI_OM_FW_ATTR_BASE_PATH "lenovo-wmi-other"
8280
#define LWMI_OM_HWMON_NAME "lenovo_wmi_other"
8381

84-
static BLOCKING_NOTIFIER_HEAD(om_chain_head);
8582
static DEFINE_IDA(lwmi_om_ida);
8683

8784
enum attribute_property {
@@ -109,7 +106,6 @@ struct lwmi_om_priv {
109106
struct device *hwmon_dev;
110107
struct device *fw_attr_dev;
111108
struct kset *fw_attr_kset;
112-
struct notifier_block nb;
113109
struct wmi_device *wdev;
114110
int ida_id;
115111

@@ -577,102 +573,6 @@ struct capdata01_attr_group {
577573
struct tunable_attr_01 *tunable_attr;
578574
};
579575

580-
/**
581-
* lwmi_om_register_notifier() - Add a notifier to the blocking notifier chain
582-
* @nb: The notifier_block struct to register
583-
*
584-
* Call blocking_notifier_chain_register to register the notifier block to the
585-
* lenovo-wmi-other driver notifier chain.
586-
*
587-
* Return: 0 on success, %-EEXIST on error.
588-
*/
589-
int lwmi_om_register_notifier(struct notifier_block *nb)
590-
{
591-
return blocking_notifier_chain_register(&om_chain_head, nb);
592-
}
593-
EXPORT_SYMBOL_NS_GPL(lwmi_om_register_notifier, "LENOVO_WMI_OTHER");
594-
595-
/**
596-
* lwmi_om_unregister_notifier() - Remove a notifier from the blocking notifier
597-
* chain.
598-
* @nb: The notifier_block struct to register
599-
*
600-
* Call blocking_notifier_chain_unregister to unregister the notifier block from the
601-
* lenovo-wmi-other driver notifier chain.
602-
*
603-
* Return: 0 on success, %-ENOENT on error.
604-
*/
605-
int lwmi_om_unregister_notifier(struct notifier_block *nb)
606-
{
607-
return blocking_notifier_chain_unregister(&om_chain_head, nb);
608-
}
609-
EXPORT_SYMBOL_NS_GPL(lwmi_om_unregister_notifier, "LENOVO_WMI_OTHER");
610-
611-
/**
612-
* devm_lwmi_om_unregister_notifier() - Remove a notifier from the blocking
613-
* notifier chain.
614-
* @data: Void pointer to the notifier_block struct to register.
615-
*
616-
* Call lwmi_om_unregister_notifier to unregister the notifier block from the
617-
* lenovo-wmi-other driver notifier chain.
618-
*
619-
* Return: 0 on success, %-ENOENT on error.
620-
*/
621-
static void devm_lwmi_om_unregister_notifier(void *data)
622-
{
623-
struct notifier_block *nb = data;
624-
625-
lwmi_om_unregister_notifier(nb);
626-
}
627-
628-
/**
629-
* devm_lwmi_om_register_notifier() - Add a notifier to the blocking notifier
630-
* chain.
631-
* @dev: The parent device of the notifier_block struct.
632-
* @nb: The notifier_block struct to register
633-
*
634-
* Call lwmi_om_register_notifier to register the notifier block to the
635-
* lenovo-wmi-other driver notifier chain. Then add devm_lwmi_om_unregister_notifier
636-
* as a device managed action to automatically unregister the notifier block
637-
* upon parent device removal.
638-
*
639-
* Return: 0 on success, or an error code.
640-
*/
641-
int devm_lwmi_om_register_notifier(struct device *dev,
642-
struct notifier_block *nb)
643-
{
644-
int ret;
645-
646-
ret = lwmi_om_register_notifier(nb);
647-
if (ret < 0)
648-
return ret;
649-
650-
return devm_add_action_or_reset(dev, devm_lwmi_om_unregister_notifier,
651-
nb);
652-
}
653-
EXPORT_SYMBOL_NS_GPL(devm_lwmi_om_register_notifier, "LENOVO_WMI_OTHER");
654-
655-
/**
656-
* lwmi_om_notifier_call() - Call functions for the notifier call chain.
657-
* @mode: Pointer to a thermal mode enum to retrieve the data from.
658-
*
659-
* Call blocking_notifier_call_chain to retrieve the thermal mode from the
660-
* lenovo-wmi-gamezone driver.
661-
*
662-
* Return: 0 on success, or an error code.
663-
*/
664-
static int lwmi_om_notifier_call(enum thermal_mode *mode)
665-
{
666-
int ret;
667-
668-
ret = blocking_notifier_call_chain(&om_chain_head,
669-
LWMI_GZ_GET_THERMAL_MODE, &mode);
670-
if ((ret & ~NOTIFY_STOP_MASK) != NOTIFY_OK)
671-
return -EINVAL;
672-
673-
return 0;
674-
}
675-
676576
/* Attribute Methods */
677577

678578
/**
@@ -780,7 +680,7 @@ static ssize_t attr_current_value_store(struct kobject *kobj,
780680
u32 value;
781681
int ret;
782682

783-
ret = lwmi_om_notifier_call(&mode);
683+
ret = lwmi_tm_notifier_call(&mode);
784684
if (ret)
785685
return ret;
786686

@@ -843,7 +743,7 @@ static ssize_t attr_current_value_show(struct kobject *kobj,
843743
int retval;
844744
int ret;
845745

846-
ret = lwmi_om_notifier_call(&mode);
746+
ret = lwmi_tm_notifier_call(&mode);
847747
if (ret)
848748
return ret;
849749

drivers/platform/x86/lenovo/wmi-other.h

Lines changed: 0 additions & 16 deletions
This file was deleted.

0 commit comments

Comments
 (0)