* [PATCH v2 00/18] Hide platform_profile_handler from consumers
@ 2025-01-14 15:37 Kurt Borja
2025-01-14 15:37 ` [PATCH v2 01/18] ACPI: platform_profile: Replace *class_dev member with class_dev Kurt Borja
` (18 more replies)
0 siblings, 19 replies; 33+ messages in thread
From: Kurt Borja @ 2025-01-14 15:37 UTC (permalink / raw)
To: platform-driver-x86
Cc: Rafael J. Wysocki, Len Brown, linux-acpi, linux-kernel,
Mario Limonciello, Armin Wolf, Joshua Grisham, Derek J. Clark,
Ilpo Järvinen, Hans de Goede, Kurt Borja, Maximilian Luz,
Lee, Chun-Yi, Shyam Sundar S K, Corentin Chary, Luke D. Jones,
Lyndon Sanche, Ike Panhc, Henrique de Moraes Holschuh,
Mark Pearson, Alexis Belmonte, Ai Chao, Gergo Koteles,
Dell.Client.Kernel, ibm-acpi-devel
Hello,
As suggested by Mario, I moved patch 15/18 to position 3/18. This indeed
simplified all diffs. Full reordering bellow.
Series based on top of pdx86/for-next branch.
~ Kurt
---
v1 -> v2:
01 -> 04
02 -> 05
03 -> 01
04 -> 02
05 -> 06
06 -> 07
07 -> 08
08 -> 09
09 -> 10
10 -> 11
11 -> 12
12 -> 13
13 -> 14
14 -> 15
15 -> 03
[1/18]
- Call put_device() if device_register() fails
[2/18]
- Set and use drvdata for every driver in these series, instead of
patches 6-14
[4/18]
- Renamed the `choices` callback to `probe`
[15/18]
- Improve error handling in amd/pmf
- Improve error handling in asus-wmi
[18/18]
- Fix typo
- Added documentation to platform_profile_ops
v1: https://lore.kernel.org/platform-driver-x86/20250109150731.110799-1-kuurtb@gmail.com/
Kurt Borja (18):
ACPI: platform_profile: Replace *class_dev member with class_dev
ACPI: platform_profile: Let drivers set drvdata to the class device
ACPI: platform_profile: Remove platform_profile_handler from callbacks
ACPI: platform_profile: Add `ops` member to handlers
ACPI: platform_profile: Add `probe` to platform_profile_ops
platform/surface: surface_platform_profile: Use
devm_platform_profile_register()
platform/x86: acer-wmi: Use devm_platform_profile_register()
platform/x86: amd: pmf: sps: Use devm_platform_profile_register()
platform/x86: asus-wmi: Use devm_platform_profile_register()
platform/x86: dell-pc: Use devm_platform_profile_register()
platform/x86: ideapad-laptop: Use devm_platform_profile_register()
platform/x86: hp-wmi: Use devm_platform_profile_register()
platform/x86: inspur_platform_profile: Use
devm_platform_profile_register()
platform/x86: thinkpad_acpi: Use devm_platform_profile_register()
ACPI: platform_profile: Remove platform_profile_handler from exported
symbols
ACPI: platform_profile: Move platform_profile_handler
ACPI: platform_profile: Clean platform_profile_handler
ACPI: platform_profile: Add documentation
.../ABI/testing/sysfs-class-platform-profile | 44 +++++
drivers/acpi/platform_profile.c | 164 +++++++++++++-----
.../surface/surface_platform_profile.c | 48 ++---
drivers/platform/x86/acer-wmi.c | 58 +++----
drivers/platform/x86/amd/pmf/core.c | 1 -
drivers/platform/x86/amd/pmf/pmf.h | 3 +-
drivers/platform/x86/amd/pmf/sps.c | 51 +++---
drivers/platform/x86/asus-wmi.c | 55 +++---
drivers/platform/x86/dell/alienware-wmi.c | 33 ++--
drivers/platform/x86/dell/dell-pc.c | 60 ++++---
drivers/platform/x86/hp/hp-wmi.c | 83 +++++----
drivers/platform/x86/ideapad-laptop.c | 44 +++--
.../platform/x86/inspur_platform_profile.c | 48 +++--
drivers/platform/x86/thinkpad_acpi.c | 37 ++--
include/linux/platform_profile.h | 51 ++++--
15 files changed, 474 insertions(+), 306 deletions(-)
create mode 100644 Documentation/ABI/testing/sysfs-class-platform-profile
base-commit: 58126788aa7726c0e91de6b25e6e332fa06089ab
--
2.47.1
^ permalink raw reply [flat|nested] 33+ messages in thread
* [PATCH v2 01/18] ACPI: platform_profile: Replace *class_dev member with class_dev
2025-01-14 15:37 [PATCH v2 00/18] Hide platform_profile_handler from consumers Kurt Borja
@ 2025-01-14 15:37 ` Kurt Borja
2025-01-14 15:37 ` [PATCH v2 02/18] ACPI: platform_profile: Let drivers set drvdata to the class device Kurt Borja
` (17 subsequent siblings)
18 siblings, 0 replies; 33+ messages in thread
From: Kurt Borja @ 2025-01-14 15:37 UTC (permalink / raw)
To: platform-driver-x86
Cc: Rafael J. Wysocki, Len Brown, linux-acpi, linux-kernel,
Mario Limonciello, Armin Wolf, Joshua Grisham, Derek J. Clark,
Ilpo Järvinen, Hans de Goede, Kurt Borja, Maximilian Luz,
Lee, Chun-Yi, Shyam Sundar S K, Corentin Chary, Luke D. Jones,
Lyndon Sanche, Ike Panhc, Henrique de Moraes Holschuh,
Mark Pearson, Alexis Belmonte, Ai Chao, Gergo Koteles,
Dell.Client.Kernel, ibm-acpi-devel
Instead of holding a reference to the class device, embed it the
platform_profile_handler. This involves manually creating and
registering the device and replacing dev_get_drvdata() with the newly
created to_pprof_handler() macro.
Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
Signed-off-by: Kurt Borja <kuurtb@gmail.com>
---
drivers/acpi/platform_profile.c | 36 ++++++++++++++++++--------------
include/linux/platform_profile.h | 3 ++-
2 files changed, 22 insertions(+), 17 deletions(-)
diff --git a/drivers/acpi/platform_profile.c b/drivers/acpi/platform_profile.c
index 4c4200a0b1a6..a89f64f13e44 100644
--- a/drivers/acpi/platform_profile.c
+++ b/drivers/acpi/platform_profile.c
@@ -10,6 +10,8 @@
#include <linux/platform_profile.h>
#include <linux/sysfs.h>
+#define to_pprof_handler(d) (container_of(d, struct platform_profile_handler, class_dev))
+
static DEFINE_MUTEX(profile_lock);
static const char * const profile_names[] = {
@@ -60,7 +62,7 @@ static int _store_class_profile(struct device *dev, void *data)
int *bit = (int *)data;
lockdep_assert_held(&profile_lock);
- handler = dev_get_drvdata(dev);
+ handler = to_pprof_handler(dev);
if (!test_bit(*bit, handler->choices))
return -EOPNOTSUPP;
@@ -76,11 +78,11 @@ static int _store_class_profile(struct device *dev, void *data)
*/
static int _notify_class_profile(struct device *dev, void *data)
{
- struct platform_profile_handler *handler = dev_get_drvdata(dev);
+ struct platform_profile_handler *handler = to_pprof_handler(dev);
lockdep_assert_held(&profile_lock);
- sysfs_notify(&handler->class_dev->kobj, NULL, "profile");
- kobject_uevent(&handler->class_dev->kobj, KOBJ_CHANGE);
+ sysfs_notify(&handler->class_dev.kobj, NULL, "profile");
+ kobject_uevent(&handler->class_dev.kobj, KOBJ_CHANGE);
return 0;
}
@@ -100,7 +102,7 @@ static int get_class_profile(struct device *dev,
int err;
lockdep_assert_held(&profile_lock);
- handler = dev_get_drvdata(dev);
+ handler = to_pprof_handler(dev);
err = handler->profile_get(handler, &val);
if (err) {
pr_err("Failed to get profile for handler %s\n", handler->name);
@@ -124,7 +126,7 @@ static int get_class_profile(struct device *dev,
*/
static ssize_t name_show(struct device *dev, struct device_attribute *attr, char *buf)
{
- struct platform_profile_handler *handler = dev_get_drvdata(dev);
+ struct platform_profile_handler *handler = to_pprof_handler(dev);
return sysfs_emit(buf, "%s\n", handler->name);
}
@@ -142,7 +144,7 @@ static ssize_t choices_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct platform_profile_handler *handler = dev_get_drvdata(dev);
+ struct platform_profile_handler *handler = to_pprof_handler(dev);
return _commmon_choices_show(handler->choices, buf);
}
@@ -229,7 +231,7 @@ static int _aggregate_choices(struct device *dev, void *data)
unsigned long *aggregate = data;
lockdep_assert_held(&profile_lock);
- handler = dev_get_drvdata(dev);
+ handler = to_pprof_handler(dev);
if (test_bit(PLATFORM_PROFILE_LAST, aggregate))
bitmap_copy(aggregate, handler->choices, PLATFORM_PROFILE_LAST);
else
@@ -410,7 +412,7 @@ static const struct attribute_group platform_profile_group = {
void platform_profile_notify(struct platform_profile_handler *pprof)
{
scoped_cond_guard(mutex_intr, return, &profile_lock) {
- _notify_class_profile(pprof->class_dev, NULL);
+ _notify_class_profile(&pprof->class_dev, NULL);
}
sysfs_notify(acpi_kobj, NULL, "platform_profile");
}
@@ -476,11 +478,13 @@ int platform_profile_register(struct platform_profile_handler *pprof)
pprof->minor = ida_alloc(&platform_profile_ida, GFP_KERNEL);
if (pprof->minor < 0)
return pprof->minor;
- pprof->class_dev = device_create(&platform_profile_class, pprof->dev,
- MKDEV(0, 0), pprof, "platform-profile-%d",
- pprof->minor);
- if (IS_ERR(pprof->class_dev)) {
- err = PTR_ERR(pprof->class_dev);
+
+ pprof->class_dev.class = &platform_profile_class;
+ pprof->class_dev.parent = pprof->dev;
+ dev_set_name(&pprof->class_dev, "platform-profile-%d", pprof->minor);
+ err = device_register(&pprof->class_dev);
+ if (err) {
+ put_device(&pprof->class_dev);
goto cleanup_ida;
}
@@ -493,7 +497,7 @@ int platform_profile_register(struct platform_profile_handler *pprof)
return 0;
cleanup_cur:
- device_unregister(pprof->class_dev);
+ device_unregister(&pprof->class_dev);
cleanup_ida:
ida_free(&platform_profile_ida, pprof->minor);
@@ -508,7 +512,7 @@ int platform_profile_remove(struct platform_profile_handler *pprof)
guard(mutex)(&profile_lock);
id = pprof->minor;
- device_unregister(pprof->class_dev);
+ device_unregister(&pprof->class_dev);
ida_free(&platform_profile_ida, id);
sysfs_notify(acpi_kobj, NULL, "platform_profile");
diff --git a/include/linux/platform_profile.h b/include/linux/platform_profile.h
index f1cd4b65e351..8a9b8754f9ac 100644
--- a/include/linux/platform_profile.h
+++ b/include/linux/platform_profile.h
@@ -9,6 +9,7 @@
#ifndef _PLATFORM_PROFILE_H_
#define _PLATFORM_PROFILE_H_
+#include <linux/device.h>
#include <linux/bitops.h>
/*
@@ -30,7 +31,7 @@ enum platform_profile_option {
struct platform_profile_handler {
const char *name;
struct device *dev;
- struct device *class_dev;
+ struct device class_dev;
int minor;
unsigned long choices[BITS_TO_LONGS(PLATFORM_PROFILE_LAST)];
int (*profile_get)(struct platform_profile_handler *pprof,
--
2.47.1
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH v2 02/18] ACPI: platform_profile: Let drivers set drvdata to the class device
2025-01-14 15:37 [PATCH v2 00/18] Hide platform_profile_handler from consumers Kurt Borja
2025-01-14 15:37 ` [PATCH v2 01/18] ACPI: platform_profile: Replace *class_dev member with class_dev Kurt Borja
@ 2025-01-14 15:37 ` Kurt Borja
2025-01-14 15:37 ` [PATCH v2 03/18] ACPI: platform_profile: Remove platform_profile_handler from callbacks Kurt Borja
` (16 subsequent siblings)
18 siblings, 0 replies; 33+ messages in thread
From: Kurt Borja @ 2025-01-14 15:37 UTC (permalink / raw)
To: platform-driver-x86
Cc: Rafael J. Wysocki, Len Brown, linux-acpi, linux-kernel,
Mario Limonciello, Armin Wolf, Joshua Grisham, Derek J. Clark,
Ilpo Järvinen, Hans de Goede, Kurt Borja, Maximilian Luz,
Lee, Chun-Yi, Shyam Sundar S K, Corentin Chary, Luke D. Jones,
Lyndon Sanche, Ike Panhc, Henrique de Moraes Holschuh,
Mark Pearson, Alexis Belmonte, Ai Chao, Gergo Koteles,
Dell.Client.Kernel, ibm-acpi-devel
Add *drvdata to platform_profile_register() signature and assign it to
the class device.
While at it, pass specific driver state as drvdata to replace uses of
container_of() with dev_get_drvdata().
Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
Signed-off-by: Kurt Borja <kuurtb@gmail.com>
---
drivers/acpi/platform_profile.c | 7 ++++---
drivers/platform/surface/surface_platform_profile.c | 6 +++---
drivers/platform/x86/acer-wmi.c | 2 +-
drivers/platform/x86/amd/pmf/sps.c | 6 +++---
drivers/platform/x86/asus-wmi.c | 6 +++---
drivers/platform/x86/dell/alienware-wmi.c | 2 +-
drivers/platform/x86/dell/dell-pc.c | 2 +-
drivers/platform/x86/hp/hp-wmi.c | 2 +-
drivers/platform/x86/ideapad-laptop.c | 6 +++---
drivers/platform/x86/inspur_platform_profile.c | 8 +++-----
drivers/platform/x86/thinkpad_acpi.c | 2 +-
include/linux/platform_profile.h | 4 ++--
12 files changed, 26 insertions(+), 27 deletions(-)
diff --git a/drivers/acpi/platform_profile.c b/drivers/acpi/platform_profile.c
index a89f64f13e44..f8741201deea 100644
--- a/drivers/acpi/platform_profile.c
+++ b/drivers/acpi/platform_profile.c
@@ -461,7 +461,7 @@ int platform_profile_cycle(void)
}
EXPORT_SYMBOL_GPL(platform_profile_cycle);
-int platform_profile_register(struct platform_profile_handler *pprof)
+int platform_profile_register(struct platform_profile_handler *pprof, void *drvdata)
{
int err;
@@ -481,6 +481,7 @@ int platform_profile_register(struct platform_profile_handler *pprof)
pprof->class_dev.class = &platform_profile_class;
pprof->class_dev.parent = pprof->dev;
+ dev_set_drvdata(&pprof->class_dev, drvdata);
dev_set_name(&pprof->class_dev, "platform-profile-%d", pprof->minor);
err = device_register(&pprof->class_dev);
if (err) {
@@ -530,7 +531,7 @@ static void devm_platform_profile_release(struct device *dev, void *res)
platform_profile_remove(*pprof);
}
-int devm_platform_profile_register(struct platform_profile_handler *pprof)
+int devm_platform_profile_register(struct platform_profile_handler *pprof, void *drvdata)
{
struct platform_profile_handler **dr;
int ret;
@@ -539,7 +540,7 @@ int devm_platform_profile_register(struct platform_profile_handler *pprof)
if (!dr)
return -ENOMEM;
- ret = platform_profile_register(pprof);
+ ret = platform_profile_register(pprof, drvdata);
if (ret) {
devres_free(dr);
return ret;
diff --git a/drivers/platform/surface/surface_platform_profile.c b/drivers/platform/surface/surface_platform_profile.c
index 6c87e982bfc8..edb9362003a4 100644
--- a/drivers/platform/surface/surface_platform_profile.c
+++ b/drivers/platform/surface/surface_platform_profile.c
@@ -161,7 +161,7 @@ static int ssam_platform_profile_get(struct platform_profile_handler *pprof,
enum ssam_tmp_profile tp;
int status;
- tpd = container_of(pprof, struct ssam_platform_profile_device, handler);
+ tpd = dev_get_drvdata(&pprof->class_dev);
status = ssam_tmp_profile_get(tpd->sdev, &tp);
if (status)
@@ -181,7 +181,7 @@ static int ssam_platform_profile_set(struct platform_profile_handler *pprof,
struct ssam_platform_profile_device *tpd;
int tp;
- tpd = container_of(pprof, struct ssam_platform_profile_device, handler);
+ tpd = dev_get_drvdata(&pprof->class_dev);
tp = convert_profile_to_ssam_tmp(tpd->sdev, profile);
if (tp < 0)
@@ -224,7 +224,7 @@ static int surface_platform_profile_probe(struct ssam_device *sdev)
set_bit(PLATFORM_PROFILE_BALANCED_PERFORMANCE, tpd->handler.choices);
set_bit(PLATFORM_PROFILE_PERFORMANCE, tpd->handler.choices);
- return platform_profile_register(&tpd->handler);
+ return platform_profile_register(&tpd->handler, tpd);
}
static void surface_platform_profile_remove(struct ssam_device *sdev)
diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c
index 57d6b680f5b9..4594beb4b9d7 100644
--- a/drivers/platform/x86/acer-wmi.c
+++ b/drivers/platform/x86/acer-wmi.c
@@ -1939,7 +1939,7 @@ static int acer_platform_profile_setup(struct platform_device *device)
set_bit(PLATFORM_PROFILE_LOW_POWER,
platform_profile_handler.choices);
- err = platform_profile_register(&platform_profile_handler);
+ err = platform_profile_register(&platform_profile_handler, NULL);
if (err)
return err;
diff --git a/drivers/platform/x86/amd/pmf/sps.c b/drivers/platform/x86/amd/pmf/sps.c
index bd2bd6cfc39a..259a598acd3e 100644
--- a/drivers/platform/x86/amd/pmf/sps.c
+++ b/drivers/platform/x86/amd/pmf/sps.c
@@ -285,7 +285,7 @@ bool is_pprof_balanced(struct amd_pmf_dev *pmf)
static int amd_pmf_profile_get(struct platform_profile_handler *pprof,
enum platform_profile_option *profile)
{
- struct amd_pmf_dev *pmf = container_of(pprof, struct amd_pmf_dev, pprof);
+ struct amd_pmf_dev *pmf = dev_get_drvdata(&pprof->class_dev);
*profile = pmf->current_profile;
return 0;
@@ -366,7 +366,7 @@ int amd_pmf_power_slider_update_event(struct amd_pmf_dev *dev)
static int amd_pmf_profile_set(struct platform_profile_handler *pprof,
enum platform_profile_option profile)
{
- struct amd_pmf_dev *pmf = container_of(pprof, struct amd_pmf_dev, pprof);
+ struct amd_pmf_dev *pmf = dev_get_drvdata(&pprof->class_dev);
int ret = 0;
pmf->current_profile = profile;
@@ -416,7 +416,7 @@ int amd_pmf_init_sps(struct amd_pmf_dev *dev)
set_bit(PLATFORM_PROFILE_PERFORMANCE, dev->pprof.choices);
/* Create platform_profile structure and register */
- err = platform_profile_register(&dev->pprof);
+ err = platform_profile_register(&dev->pprof, dev);
if (err)
dev_err(dev->dev, "Failed to register SPS support, this is most likely an SBIOS bug: %d\n",
err);
diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
index fdeebab96fc0..0c68635a0aa3 100644
--- a/drivers/platform/x86/asus-wmi.c
+++ b/drivers/platform/x86/asus-wmi.c
@@ -3806,7 +3806,7 @@ static int asus_wmi_platform_profile_get(struct platform_profile_handler *pprof,
struct asus_wmi *asus;
int tp;
- asus = container_of(pprof, struct asus_wmi, platform_profile_handler);
+ asus = dev_get_drvdata(&pprof->class_dev);
tp = asus->throttle_thermal_policy_mode;
switch (tp) {
@@ -3832,7 +3832,7 @@ static int asus_wmi_platform_profile_set(struct platform_profile_handler *pprof,
struct asus_wmi *asus;
int tp;
- asus = container_of(pprof, struct asus_wmi, platform_profile_handler);
+ asus = dev_get_drvdata(&pprof->class_dev);
switch (profile) {
case PLATFORM_PROFILE_PERFORMANCE:
@@ -3887,7 +3887,7 @@ static int platform_profile_setup(struct asus_wmi *asus)
set_bit(PLATFORM_PROFILE_PERFORMANCE,
asus->platform_profile_handler.choices);
- err = platform_profile_register(&asus->platform_profile_handler);
+ err = platform_profile_register(&asus->platform_profile_handler, asus);
if (err == -EEXIST) {
pr_warn("%s, a platform_profile handler is already registered\n", __func__);
return 0;
diff --git a/drivers/platform/x86/dell/alienware-wmi.c b/drivers/platform/x86/dell/alienware-wmi.c
index b4b43f3e3fd9..28c39e25228e 100644
--- a/drivers/platform/x86/dell/alienware-wmi.c
+++ b/drivers/platform/x86/dell/alienware-wmi.c
@@ -1129,7 +1129,7 @@ static int create_thermal_profile(struct platform_device *platform_device)
pp_handler.name = "alienware-wmi";
pp_handler.dev = &platform_device->dev;
- return devm_platform_profile_register(&pp_handler);
+ return devm_platform_profile_register(&pp_handler, NULL);
}
/*
diff --git a/drivers/platform/x86/dell/dell-pc.c b/drivers/platform/x86/dell/dell-pc.c
index 3797a5721dbd..1a0a721d706f 100644
--- a/drivers/platform/x86/dell/dell-pc.c
+++ b/drivers/platform/x86/dell/dell-pc.c
@@ -271,7 +271,7 @@ static int thermal_init(void)
set_bit(PLATFORM_PROFILE_PERFORMANCE, thermal_handler->choices);
/* Clean up if failed */
- ret = platform_profile_register(thermal_handler);
+ ret = platform_profile_register(thermal_handler, NULL);
if (ret)
goto cleanup_thermal_handler;
diff --git a/drivers/platform/x86/hp/hp-wmi.c b/drivers/platform/x86/hp/hp-wmi.c
index 6d6e13a0c6e2..8e5e1422e024 100644
--- a/drivers/platform/x86/hp/hp-wmi.c
+++ b/drivers/platform/x86/hp/hp-wmi.c
@@ -1629,7 +1629,7 @@ static int thermal_profile_setup(struct platform_device *device)
set_bit(PLATFORM_PROFILE_BALANCED, platform_profile_handler.choices);
set_bit(PLATFORM_PROFILE_PERFORMANCE, platform_profile_handler.choices);
- err = platform_profile_register(&platform_profile_handler);
+ err = platform_profile_register(&platform_profile_handler, NULL);
if (err)
return err;
diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c
index dc98f862a06d..ed0d880a07a9 100644
--- a/drivers/platform/x86/ideapad-laptop.c
+++ b/drivers/platform/x86/ideapad-laptop.c
@@ -936,7 +936,7 @@ static int convert_profile_to_dytc(enum platform_profile_option profile, int *pe
static int dytc_profile_get(struct platform_profile_handler *pprof,
enum platform_profile_option *profile)
{
- struct ideapad_dytc_priv *dytc = container_of(pprof, struct ideapad_dytc_priv, pprof);
+ struct ideapad_dytc_priv *dytc = dev_get_drvdata(&pprof->class_dev);
*profile = dytc->current_profile;
return 0;
@@ -989,7 +989,7 @@ static int dytc_cql_command(struct ideapad_private *priv, unsigned long cmd,
static int dytc_profile_set(struct platform_profile_handler *pprof,
enum platform_profile_option profile)
{
- struct ideapad_dytc_priv *dytc = container_of(pprof, struct ideapad_dytc_priv, pprof);
+ struct ideapad_dytc_priv *dytc = dev_get_drvdata(&pprof->class_dev);
struct ideapad_private *priv = dytc->priv;
unsigned long output;
int err;
@@ -1114,7 +1114,7 @@ static int ideapad_dytc_profile_init(struct ideapad_private *priv)
set_bit(PLATFORM_PROFILE_PERFORMANCE, priv->dytc->pprof.choices);
/* Create platform_profile structure and register */
- err = platform_profile_register(&priv->dytc->pprof);
+ err = platform_profile_register(&priv->dytc->pprof, &priv->dytc);
if (err)
goto pp_reg_failed;
diff --git a/drivers/platform/x86/inspur_platform_profile.c b/drivers/platform/x86/inspur_platform_profile.c
index 53af73a7fbf7..471fca50d1c9 100644
--- a/drivers/platform/x86/inspur_platform_profile.c
+++ b/drivers/platform/x86/inspur_platform_profile.c
@@ -87,8 +87,7 @@ static int inspur_wmi_perform_query(struct wmi_device *wdev,
static int inspur_platform_profile_set(struct platform_profile_handler *pprof,
enum platform_profile_option profile)
{
- struct inspur_wmi_priv *priv = container_of(pprof, struct inspur_wmi_priv,
- handler);
+ struct inspur_wmi_priv *priv = dev_get_drvdata(&pprof->class_dev);
u8 ret_code[4] = {0, 0, 0, 0};
int ret;
@@ -135,8 +134,7 @@ static int inspur_platform_profile_set(struct platform_profile_handler *pprof,
static int inspur_platform_profile_get(struct platform_profile_handler *pprof,
enum platform_profile_option *profile)
{
- struct inspur_wmi_priv *priv = container_of(pprof, struct inspur_wmi_priv,
- handler);
+ struct inspur_wmi_priv *priv = dev_get_drvdata(&pprof->class_dev);
u8 ret_code[4] = {0, 0, 0, 0};
int ret;
@@ -186,7 +184,7 @@ static int inspur_wmi_probe(struct wmi_device *wdev, const void *context)
set_bit(PLATFORM_PROFILE_BALANCED, priv->handler.choices);
set_bit(PLATFORM_PROFILE_PERFORMANCE, priv->handler.choices);
- return platform_profile_register(&priv->handler);
+ return platform_profile_register(&priv->handler, priv);
}
static void inspur_wmi_remove(struct wmi_device *wdev)
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
index 22f871e9f53c..fe37c26891d8 100644
--- a/drivers/platform/x86/thinkpad_acpi.c
+++ b/drivers/platform/x86/thinkpad_acpi.c
@@ -10640,7 +10640,7 @@ static int tpacpi_dytc_profile_init(struct ibm_init_struct *iibm)
dytc_profile.dev = &tpacpi_pdev->dev;
/* Create platform_profile structure and register */
- err = platform_profile_register(&dytc_profile);
+ err = platform_profile_register(&dytc_profile, NULL);
/*
* If for some reason platform_profiles aren't enabled
* don't quit terminally.
diff --git a/include/linux/platform_profile.h b/include/linux/platform_profile.h
index 8a9b8754f9ac..1c8fdda51eaa 100644
--- a/include/linux/platform_profile.h
+++ b/include/linux/platform_profile.h
@@ -40,9 +40,9 @@ struct platform_profile_handler {
enum platform_profile_option profile);
};
-int platform_profile_register(struct platform_profile_handler *pprof);
+int platform_profile_register(struct platform_profile_handler *pprof, void *drvdata);
int platform_profile_remove(struct platform_profile_handler *pprof);
-int devm_platform_profile_register(struct platform_profile_handler *pprof);
+int devm_platform_profile_register(struct platform_profile_handler *pprof, void *drvdata);
int platform_profile_cycle(void);
void platform_profile_notify(struct platform_profile_handler *pprof);
--
2.47.1
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH v2 03/18] ACPI: platform_profile: Remove platform_profile_handler from callbacks
2025-01-14 15:37 [PATCH v2 00/18] Hide platform_profile_handler from consumers Kurt Borja
2025-01-14 15:37 ` [PATCH v2 01/18] ACPI: platform_profile: Replace *class_dev member with class_dev Kurt Borja
2025-01-14 15:37 ` [PATCH v2 02/18] ACPI: platform_profile: Let drivers set drvdata to the class device Kurt Borja
@ 2025-01-14 15:37 ` Kurt Borja
2025-01-14 15:59 ` Mario Limonciello
2025-01-14 15:37 ` [PATCH v2 04/18] ACPI: platform_profile: Add `ops` member to handlers Kurt Borja
` (15 subsequent siblings)
18 siblings, 1 reply; 33+ messages in thread
From: Kurt Borja @ 2025-01-14 15:37 UTC (permalink / raw)
To: platform-driver-x86
Cc: Rafael J. Wysocki, Len Brown, linux-acpi, linux-kernel,
Mario Limonciello, Armin Wolf, Joshua Grisham, Derek J. Clark,
Ilpo Järvinen, Hans de Goede, Kurt Borja, Maximilian Luz,
Lee, Chun-Yi, Shyam Sundar S K, Corentin Chary, Luke D. Jones,
Lyndon Sanche, Ike Panhc, Henrique de Moraes Holschuh,
Mark Pearson, Alexis Belmonte, Ai Chao, Gergo Koteles,
Dell.Client.Kernel, ibm-acpi-devel
Devices can now set drvdata to the class device, thus passing the
platform_profile_handler to callbacks is unnecessary. Instead pass the
class device.
Signed-off-by: Kurt Borja <kuurtb@gmail.com>
---
drivers/acpi/platform_profile.c | 4 ++--
.../platform/surface/surface_platform_profile.c | 8 ++++----
drivers/platform/x86/acer-wmi.c | 4 ++--
drivers/platform/x86/amd/pmf/sps.c | 8 ++++----
drivers/platform/x86/asus-wmi.c | 8 ++++----
drivers/platform/x86/dell/alienware-wmi.c | 4 ++--
drivers/platform/x86/dell/dell-pc.c | 4 ++--
drivers/platform/x86/hp/hp-wmi.c | 14 +++++++-------
drivers/platform/x86/ideapad-laptop.c | 8 ++++----
drivers/platform/x86/inspur_platform_profile.c | 8 ++++----
drivers/platform/x86/thinkpad_acpi.c | 4 ++--
include/linux/platform_profile.h | 6 ++----
12 files changed, 39 insertions(+), 41 deletions(-)
diff --git a/drivers/acpi/platform_profile.c b/drivers/acpi/platform_profile.c
index f8741201deea..66170fe436f0 100644
--- a/drivers/acpi/platform_profile.c
+++ b/drivers/acpi/platform_profile.c
@@ -66,7 +66,7 @@ static int _store_class_profile(struct device *dev, void *data)
if (!test_bit(*bit, handler->choices))
return -EOPNOTSUPP;
- return handler->profile_set(handler, *bit);
+ return handler->profile_set(dev, *bit);
}
/**
@@ -103,7 +103,7 @@ static int get_class_profile(struct device *dev,
lockdep_assert_held(&profile_lock);
handler = to_pprof_handler(dev);
- err = handler->profile_get(handler, &val);
+ err = handler->profile_get(dev, &val);
if (err) {
pr_err("Failed to get profile for handler %s\n", handler->name);
return err;
diff --git a/drivers/platform/surface/surface_platform_profile.c b/drivers/platform/surface/surface_platform_profile.c
index edb9362003a4..26c1230e75df 100644
--- a/drivers/platform/surface/surface_platform_profile.c
+++ b/drivers/platform/surface/surface_platform_profile.c
@@ -154,14 +154,14 @@ static int convert_profile_to_ssam_fan(struct ssam_device *sdev, enum platform_p
}
}
-static int ssam_platform_profile_get(struct platform_profile_handler *pprof,
+static int ssam_platform_profile_get(struct device *dev,
enum platform_profile_option *profile)
{
struct ssam_platform_profile_device *tpd;
enum ssam_tmp_profile tp;
int status;
- tpd = dev_get_drvdata(&pprof->class_dev);
+ tpd = dev_get_drvdata(dev);
status = ssam_tmp_profile_get(tpd->sdev, &tp);
if (status)
@@ -175,13 +175,13 @@ static int ssam_platform_profile_get(struct platform_profile_handler *pprof,
return 0;
}
-static int ssam_platform_profile_set(struct platform_profile_handler *pprof,
+static int ssam_platform_profile_set(struct device *dev,
enum platform_profile_option profile)
{
struct ssam_platform_profile_device *tpd;
int tp;
- tpd = dev_get_drvdata(&pprof->class_dev);
+ tpd = dev_get_drvdata(dev);
tp = convert_profile_to_ssam_tmp(tpd->sdev, profile);
if (tp < 0)
diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c
index 4594beb4b9d7..d609bd105db3 100644
--- a/drivers/platform/x86/acer-wmi.c
+++ b/drivers/platform/x86/acer-wmi.c
@@ -1843,7 +1843,7 @@ static int acer_toggle_turbo(void)
}
static int
-acer_predator_v4_platform_profile_get(struct platform_profile_handler *pprof,
+acer_predator_v4_platform_profile_get(struct device *dev,
enum platform_profile_option *profile)
{
u8 tp;
@@ -1878,7 +1878,7 @@ acer_predator_v4_platform_profile_get(struct platform_profile_handler *pprof,
}
static int
-acer_predator_v4_platform_profile_set(struct platform_profile_handler *pprof,
+acer_predator_v4_platform_profile_set(struct device *dev,
enum platform_profile_option profile)
{
int tp;
diff --git a/drivers/platform/x86/amd/pmf/sps.c b/drivers/platform/x86/amd/pmf/sps.c
index 259a598acd3e..cf2e51f67787 100644
--- a/drivers/platform/x86/amd/pmf/sps.c
+++ b/drivers/platform/x86/amd/pmf/sps.c
@@ -282,10 +282,10 @@ bool is_pprof_balanced(struct amd_pmf_dev *pmf)
return (pmf->current_profile == PLATFORM_PROFILE_BALANCED) ? true : false;
}
-static int amd_pmf_profile_get(struct platform_profile_handler *pprof,
+static int amd_pmf_profile_get(struct device *dev,
enum platform_profile_option *profile)
{
- struct amd_pmf_dev *pmf = dev_get_drvdata(&pprof->class_dev);
+ struct amd_pmf_dev *pmf = dev_get_drvdata(dev);
*profile = pmf->current_profile;
return 0;
@@ -363,10 +363,10 @@ int amd_pmf_power_slider_update_event(struct amd_pmf_dev *dev)
return 0;
}
-static int amd_pmf_profile_set(struct platform_profile_handler *pprof,
+static int amd_pmf_profile_set(struct device *dev,
enum platform_profile_option profile)
{
- struct amd_pmf_dev *pmf = dev_get_drvdata(&pprof->class_dev);
+ struct amd_pmf_dev *pmf = dev_get_drvdata(dev);
int ret = 0;
pmf->current_profile = profile;
diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
index 0c68635a0aa3..9bed170abb92 100644
--- a/drivers/platform/x86/asus-wmi.c
+++ b/drivers/platform/x86/asus-wmi.c
@@ -3800,13 +3800,13 @@ static ssize_t throttle_thermal_policy_store(struct device *dev,
static DEVICE_ATTR_RW(throttle_thermal_policy);
/* Platform profile ***********************************************************/
-static int asus_wmi_platform_profile_get(struct platform_profile_handler *pprof,
+static int asus_wmi_platform_profile_get(struct device *dev,
enum platform_profile_option *profile)
{
struct asus_wmi *asus;
int tp;
- asus = dev_get_drvdata(&pprof->class_dev);
+ asus = dev_get_drvdata(dev);
tp = asus->throttle_thermal_policy_mode;
switch (tp) {
@@ -3826,13 +3826,13 @@ static int asus_wmi_platform_profile_get(struct platform_profile_handler *pprof,
return 0;
}
-static int asus_wmi_platform_profile_set(struct platform_profile_handler *pprof,
+static int asus_wmi_platform_profile_set(struct device *dev,
enum platform_profile_option profile)
{
struct asus_wmi *asus;
int tp;
- asus = dev_get_drvdata(&pprof->class_dev);
+ asus = dev_get_drvdata(dev);
switch (profile) {
case PLATFORM_PROFILE_PERFORMANCE:
diff --git a/drivers/platform/x86/dell/alienware-wmi.c b/drivers/platform/x86/dell/alienware-wmi.c
index 28c39e25228e..b8131b803368 100644
--- a/drivers/platform/x86/dell/alienware-wmi.c
+++ b/drivers/platform/x86/dell/alienware-wmi.c
@@ -1026,7 +1026,7 @@ static int wmax_game_shift_status(u8 operation, u32 *out_data)
return 0;
}
-static int thermal_profile_get(struct platform_profile_handler *pprof,
+static int thermal_profile_get(struct device *dev,
enum platform_profile_option *profile)
{
u32 out_data;
@@ -1052,7 +1052,7 @@ static int thermal_profile_get(struct platform_profile_handler *pprof,
return 0;
}
-static int thermal_profile_set(struct platform_profile_handler *pprof,
+static int thermal_profile_set(struct device *dev,
enum platform_profile_option profile)
{
if (quirks->gmode) {
diff --git a/drivers/platform/x86/dell/dell-pc.c b/drivers/platform/x86/dell/dell-pc.c
index 1a0a721d706f..c86b05b5a1cb 100644
--- a/drivers/platform/x86/dell/dell-pc.c
+++ b/drivers/platform/x86/dell/dell-pc.c
@@ -185,7 +185,7 @@ static int thermal_set_mode(enum thermal_mode_bits state)
return dell_send_request(&buffer, CLASS_INFO, SELECT_THERMAL_MANAGEMENT);
}
-static int thermal_platform_profile_set(struct platform_profile_handler *pprof,
+static int thermal_platform_profile_set(struct device *dev,
enum platform_profile_option profile)
{
switch (profile) {
@@ -202,7 +202,7 @@ static int thermal_platform_profile_set(struct platform_profile_handler *pprof,
}
}
-static int thermal_platform_profile_get(struct platform_profile_handler *pprof,
+static int thermal_platform_profile_get(struct device *dev,
enum platform_profile_option *profile)
{
int ret;
diff --git a/drivers/platform/x86/hp/hp-wmi.c b/drivers/platform/x86/hp/hp-wmi.c
index 8e5e1422e024..b8e62dc9cecd 100644
--- a/drivers/platform/x86/hp/hp-wmi.c
+++ b/drivers/platform/x86/hp/hp-wmi.c
@@ -1221,7 +1221,7 @@ static int platform_profile_omen_get_ec(enum platform_profile_option *profile)
return 0;
}
-static int platform_profile_omen_get(struct platform_profile_handler *pprof,
+static int platform_profile_omen_get(struct device *dev,
enum platform_profile_option *profile)
{
/*
@@ -1318,7 +1318,7 @@ static int platform_profile_omen_set_ec(enum platform_profile_option profile)
return 0;
}
-static int platform_profile_omen_set(struct platform_profile_handler *pprof,
+static int platform_profile_omen_set(struct device *dev,
enum platform_profile_option profile)
{
int err;
@@ -1345,7 +1345,7 @@ static int thermal_profile_set(int thermal_profile)
sizeof(thermal_profile), 0);
}
-static int hp_wmi_platform_profile_get(struct platform_profile_handler *pprof,
+static int hp_wmi_platform_profile_get(struct device *dev,
enum platform_profile_option *profile)
{
int tp;
@@ -1374,7 +1374,7 @@ static int hp_wmi_platform_profile_get(struct platform_profile_handler *pprof,
return 0;
}
-static int hp_wmi_platform_profile_set(struct platform_profile_handler *pprof,
+static int hp_wmi_platform_profile_set(struct device *dev,
enum platform_profile_option profile)
{
int err, tp;
@@ -1440,11 +1440,11 @@ static int platform_profile_victus_get_ec(enum platform_profile_option *profile)
return 0;
}
-static int platform_profile_victus_get(struct platform_profile_handler *pprof,
+static int platform_profile_victus_get(struct device *dev,
enum platform_profile_option *profile)
{
/* Same behaviour as platform_profile_omen_get */
- return platform_profile_omen_get(pprof, profile);
+ return platform_profile_omen_get(dev, profile);
}
static int platform_profile_victus_set_ec(enum platform_profile_option profile)
@@ -1472,7 +1472,7 @@ static int platform_profile_victus_set_ec(enum platform_profile_option profile)
return 0;
}
-static int platform_profile_victus_set(struct platform_profile_handler *pprof,
+static int platform_profile_victus_set(struct device *dev,
enum platform_profile_option profile)
{
int err;
diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c
index ed0d880a07a9..fc317f42bb82 100644
--- a/drivers/platform/x86/ideapad-laptop.c
+++ b/drivers/platform/x86/ideapad-laptop.c
@@ -933,10 +933,10 @@ static int convert_profile_to_dytc(enum platform_profile_option profile, int *pe
* dytc_profile_get: Function to register with platform_profile
* handler. Returns current platform profile.
*/
-static int dytc_profile_get(struct platform_profile_handler *pprof,
+static int dytc_profile_get(struct device *dev,
enum platform_profile_option *profile)
{
- struct ideapad_dytc_priv *dytc = dev_get_drvdata(&pprof->class_dev);
+ struct ideapad_dytc_priv *dytc = dev_get_drvdata(dev);
*profile = dytc->current_profile;
return 0;
@@ -986,10 +986,10 @@ static int dytc_cql_command(struct ideapad_private *priv, unsigned long cmd,
* dytc_profile_set: Function to register with platform_profile
* handler. Sets current platform profile.
*/
-static int dytc_profile_set(struct platform_profile_handler *pprof,
+static int dytc_profile_set(struct device *dev,
enum platform_profile_option profile)
{
- struct ideapad_dytc_priv *dytc = dev_get_drvdata(&pprof->class_dev);
+ struct ideapad_dytc_priv *dytc = dev_get_drvdata(dev);
struct ideapad_private *priv = dytc->priv;
unsigned long output;
int err;
diff --git a/drivers/platform/x86/inspur_platform_profile.c b/drivers/platform/x86/inspur_platform_profile.c
index 471fca50d1c9..47d2dbbf3392 100644
--- a/drivers/platform/x86/inspur_platform_profile.c
+++ b/drivers/platform/x86/inspur_platform_profile.c
@@ -84,10 +84,10 @@ static int inspur_wmi_perform_query(struct wmi_device *wdev,
* 0x0: No Error
* 0x1: Error
*/
-static int inspur_platform_profile_set(struct platform_profile_handler *pprof,
+static int inspur_platform_profile_set(struct device *dev,
enum platform_profile_option profile)
{
- struct inspur_wmi_priv *priv = dev_get_drvdata(&pprof->class_dev);
+ struct inspur_wmi_priv *priv = dev_get_drvdata(dev);
u8 ret_code[4] = {0, 0, 0, 0};
int ret;
@@ -131,10 +131,10 @@ static int inspur_platform_profile_set(struct platform_profile_handler *pprof,
* 0x1: Performance Mode
* 0x2: Power Saver Mode
*/
-static int inspur_platform_profile_get(struct platform_profile_handler *pprof,
+static int inspur_platform_profile_get(struct device *dev,
enum platform_profile_option *profile)
{
- struct inspur_wmi_priv *priv = dev_get_drvdata(&pprof->class_dev);
+ struct inspur_wmi_priv *priv = dev_get_drvdata(dev);
u8 ret_code[4] = {0, 0, 0, 0};
int ret;
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
index fe37c26891d8..47f87bb213a9 100644
--- a/drivers/platform/x86/thinkpad_acpi.c
+++ b/drivers/platform/x86/thinkpad_acpi.c
@@ -10414,7 +10414,7 @@ static int convert_profile_to_dytc(enum platform_profile_option profile, int *pe
* dytc_profile_get: Function to register with platform_profile
* handler. Returns current platform profile.
*/
-static int dytc_profile_get(struct platform_profile_handler *pprof,
+static int dytc_profile_get(struct device *dev,
enum platform_profile_option *profile)
{
*profile = dytc_current_profile;
@@ -10489,7 +10489,7 @@ static int dytc_cql_command(int command, int *output)
* dytc_profile_set: Function to register with platform_profile
* handler. Sets current platform profile.
*/
-static int dytc_profile_set(struct platform_profile_handler *pprof,
+static int dytc_profile_set(struct device *dev,
enum platform_profile_option profile)
{
int perfmode;
diff --git a/include/linux/platform_profile.h b/include/linux/platform_profile.h
index 1c8fdda51eaa..5296d886c243 100644
--- a/include/linux/platform_profile.h
+++ b/include/linux/platform_profile.h
@@ -34,10 +34,8 @@ struct platform_profile_handler {
struct device class_dev;
int minor;
unsigned long choices[BITS_TO_LONGS(PLATFORM_PROFILE_LAST)];
- int (*profile_get)(struct platform_profile_handler *pprof,
- enum platform_profile_option *profile);
- int (*profile_set)(struct platform_profile_handler *pprof,
- enum platform_profile_option profile);
+ int (*profile_get)(struct device *dev, enum platform_profile_option *profile);
+ int (*profile_set)(struct device *dev, enum platform_profile_option profile);
};
int platform_profile_register(struct platform_profile_handler *pprof, void *drvdata);
--
2.47.1
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH v2 04/18] ACPI: platform_profile: Add `ops` member to handlers
2025-01-14 15:37 [PATCH v2 00/18] Hide platform_profile_handler from consumers Kurt Borja
` (2 preceding siblings ...)
2025-01-14 15:37 ` [PATCH v2 03/18] ACPI: platform_profile: Remove platform_profile_handler from callbacks Kurt Borja
@ 2025-01-14 15:37 ` Kurt Borja
2025-01-14 15:37 ` [PATCH v2 05/18] ACPI: platform_profile: Add `probe` to platform_profile_ops Kurt Borja
` (14 subsequent siblings)
18 siblings, 0 replies; 33+ messages in thread
From: Kurt Borja @ 2025-01-14 15:37 UTC (permalink / raw)
To: platform-driver-x86
Cc: Rafael J. Wysocki, Len Brown, linux-acpi, linux-kernel,
Mario Limonciello, Armin Wolf, Joshua Grisham, Derek J. Clark,
Ilpo Järvinen, Hans de Goede, Kurt Borja, Maximilian Luz,
Lee, Chun-Yi, Shyam Sundar S K, Corentin Chary, Luke D. Jones,
Lyndon Sanche, Ike Panhc, Henrique de Moraes Holschuh,
Mark Pearson, Alexis Belmonte, Ai Chao, Gergo Koteles,
Dell.Client.Kernel, ibm-acpi-devel
Replace *profile_get and *profile_set members with a general *ops
member.
Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
Signed-off-by: Kurt Borja <kuurtb@gmail.com>
---
drivers/acpi/platform_profile.c | 6 ++---
.../surface/surface_platform_profile.c | 8 +++++--
drivers/platform/x86/acer-wmi.c | 11 +++++----
drivers/platform/x86/amd/pmf/sps.c | 8 +++++--
drivers/platform/x86/asus-wmi.c | 8 +++++--
drivers/platform/x86/dell/alienware-wmi.c | 8 +++++--
drivers/platform/x86/dell/dell-pc.c | 8 +++++--
drivers/platform/x86/hp/hp-wmi.c | 24 ++++++++++++++-----
drivers/platform/x86/ideapad-laptop.c | 8 +++++--
.../platform/x86/inspur_platform_profile.c | 8 +++++--
drivers/platform/x86/thinkpad_acpi.c | 8 +++++--
include/linux/platform_profile.h | 10 ++++++--
12 files changed, 84 insertions(+), 31 deletions(-)
diff --git a/drivers/acpi/platform_profile.c b/drivers/acpi/platform_profile.c
index 66170fe436f0..440654e21620 100644
--- a/drivers/acpi/platform_profile.c
+++ b/drivers/acpi/platform_profile.c
@@ -66,7 +66,7 @@ static int _store_class_profile(struct device *dev, void *data)
if (!test_bit(*bit, handler->choices))
return -EOPNOTSUPP;
- return handler->profile_set(dev, *bit);
+ return handler->ops->profile_set(dev, *bit);
}
/**
@@ -103,7 +103,7 @@ static int get_class_profile(struct device *dev,
lockdep_assert_held(&profile_lock);
handler = to_pprof_handler(dev);
- err = handler->profile_get(dev, &val);
+ err = handler->ops->profile_get(dev, &val);
if (err) {
pr_err("Failed to get profile for handler %s\n", handler->name);
return err;
@@ -467,7 +467,7 @@ int platform_profile_register(struct platform_profile_handler *pprof, void *drvd
/* Sanity check the profile handler */
if (!pprof || bitmap_empty(pprof->choices, PLATFORM_PROFILE_LAST) ||
- !pprof->profile_set || !pprof->profile_get) {
+ !pprof->ops->profile_set || !pprof->ops->profile_get) {
pr_err("platform_profile: handler is invalid\n");
return -EINVAL;
}
diff --git a/drivers/platform/surface/surface_platform_profile.c b/drivers/platform/surface/surface_platform_profile.c
index 26c1230e75df..76967bfeeef8 100644
--- a/drivers/platform/surface/surface_platform_profile.c
+++ b/drivers/platform/surface/surface_platform_profile.c
@@ -201,6 +201,11 @@ static int ssam_platform_profile_set(struct device *dev,
return tp;
}
+static const struct platform_profile_ops ssam_platform_profile_ops = {
+ .profile_get = ssam_platform_profile_get,
+ .profile_set = ssam_platform_profile_set,
+};
+
static int surface_platform_profile_probe(struct ssam_device *sdev)
{
struct ssam_platform_profile_device *tpd;
@@ -214,8 +219,7 @@ static int surface_platform_profile_probe(struct ssam_device *sdev)
tpd->handler.name = "Surface Platform Profile";
tpd->handler.dev = &sdev->dev;
- tpd->handler.profile_get = ssam_platform_profile_get;
- tpd->handler.profile_set = ssam_platform_profile_set;
+ tpd->handler.ops = &ssam_platform_profile_ops;
tpd->has_fan = device_property_read_bool(&sdev->dev, "has_fan");
diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c
index d609bd105db3..91ae48adf6cf 100644
--- a/drivers/platform/x86/acer-wmi.c
+++ b/drivers/platform/x86/acer-wmi.c
@@ -1916,6 +1916,11 @@ acer_predator_v4_platform_profile_set(struct device *dev,
return 0;
}
+static const struct platform_profile_ops acer_predator_v4_platform_profile_ops = {
+ .profile_get = acer_predator_v4_platform_profile_get,
+ .profile_set = acer_predator_v4_platform_profile_set,
+};
+
static int acer_platform_profile_setup(struct platform_device *device)
{
if (quirks->predator_v4) {
@@ -1923,10 +1928,8 @@ static int acer_platform_profile_setup(struct platform_device *device)
platform_profile_handler.name = "acer-wmi";
platform_profile_handler.dev = &device->dev;
- platform_profile_handler.profile_get =
- acer_predator_v4_platform_profile_get;
- platform_profile_handler.profile_set =
- acer_predator_v4_platform_profile_set;
+ platform_profile_handler.ops =
+ &acer_predator_v4_platform_profile_ops;
set_bit(PLATFORM_PROFILE_PERFORMANCE,
platform_profile_handler.choices);
diff --git a/drivers/platform/x86/amd/pmf/sps.c b/drivers/platform/x86/amd/pmf/sps.c
index cf2e51f67787..6ae82ae86d22 100644
--- a/drivers/platform/x86/amd/pmf/sps.c
+++ b/drivers/platform/x86/amd/pmf/sps.c
@@ -387,6 +387,11 @@ static int amd_pmf_profile_set(struct device *dev,
return 0;
}
+static const struct platform_profile_ops amd_pmf_profile_ops = {
+ .profile_get = amd_pmf_profile_get,
+ .profile_set = amd_pmf_profile_set,
+};
+
int amd_pmf_init_sps(struct amd_pmf_dev *dev)
{
int err;
@@ -407,8 +412,7 @@ int amd_pmf_init_sps(struct amd_pmf_dev *dev)
dev->pprof.name = "amd-pmf";
dev->pprof.dev = dev->dev;
- dev->pprof.profile_get = amd_pmf_profile_get;
- dev->pprof.profile_set = amd_pmf_profile_set;
+ dev->pprof.ops = &amd_pmf_profile_ops;
/* Setup supported modes */
set_bit(PLATFORM_PROFILE_LOW_POWER, dev->pprof.choices);
diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
index 9bed170abb92..d88860dd028b 100644
--- a/drivers/platform/x86/asus-wmi.c
+++ b/drivers/platform/x86/asus-wmi.c
@@ -3852,6 +3852,11 @@ static int asus_wmi_platform_profile_set(struct device *dev,
return throttle_thermal_policy_write(asus);
}
+static const struct platform_profile_ops asus_wmi_platform_profile_ops = {
+ .profile_get = asus_wmi_platform_profile_get,
+ .profile_set = asus_wmi_platform_profile_set,
+};
+
static int platform_profile_setup(struct asus_wmi *asus)
{
struct device *dev = &asus->platform_device->dev;
@@ -3878,8 +3883,7 @@ static int platform_profile_setup(struct asus_wmi *asus)
asus->platform_profile_handler.name = "asus-wmi";
asus->platform_profile_handler.dev = dev;
- asus->platform_profile_handler.profile_get = asus_wmi_platform_profile_get;
- asus->platform_profile_handler.profile_set = asus_wmi_platform_profile_set;
+ asus->platform_profile_handler.ops = &asus_wmi_platform_profile_ops;
set_bit(PLATFORM_PROFILE_QUIET, asus->platform_profile_handler.choices);
set_bit(PLATFORM_PROFILE_BALANCED,
diff --git a/drivers/platform/x86/dell/alienware-wmi.c b/drivers/platform/x86/dell/alienware-wmi.c
index b8131b803368..f7a854d40575 100644
--- a/drivers/platform/x86/dell/alienware-wmi.c
+++ b/drivers/platform/x86/dell/alienware-wmi.c
@@ -1078,6 +1078,11 @@ static int thermal_profile_set(struct device *dev,
return wmax_thermal_control(supported_thermal_profiles[profile]);
}
+static const struct platform_profile_ops awcc_platform_profile_ops = {
+ .profile_get = thermal_profile_get,
+ .profile_set = thermal_profile_set,
+};
+
static int create_thermal_profile(struct platform_device *platform_device)
{
enum platform_profile_option profile;
@@ -1124,10 +1129,9 @@ static int create_thermal_profile(struct platform_device *platform_device)
set_bit(PLATFORM_PROFILE_PERFORMANCE, pp_handler.choices);
}
- pp_handler.profile_get = thermal_profile_get;
- pp_handler.profile_set = thermal_profile_set;
pp_handler.name = "alienware-wmi";
pp_handler.dev = &platform_device->dev;
+ pp_handler.ops = &awcc_platform_profile_ops;
return devm_platform_profile_register(&pp_handler, NULL);
}
diff --git a/drivers/platform/x86/dell/dell-pc.c b/drivers/platform/x86/dell/dell-pc.c
index c86b05b5a1cb..9010a231f209 100644
--- a/drivers/platform/x86/dell/dell-pc.c
+++ b/drivers/platform/x86/dell/dell-pc.c
@@ -231,6 +231,11 @@ static int thermal_platform_profile_get(struct device *dev,
return 0;
}
+static const struct platform_profile_ops dell_pc_platform_profile_ops = {
+ .profile_get = thermal_platform_profile_get,
+ .profile_set = thermal_platform_profile_set,
+};
+
static int thermal_init(void)
{
int ret;
@@ -258,8 +263,7 @@ static int thermal_init(void)
}
thermal_handler->name = "dell-pc";
thermal_handler->dev = &platform_device->dev;
- thermal_handler->profile_get = thermal_platform_profile_get;
- thermal_handler->profile_set = thermal_platform_profile_set;
+ thermal_handler->ops = &dell_pc_platform_profile_ops;
if (supported_modes & DELL_QUIET)
set_bit(PLATFORM_PROFILE_QUIET, thermal_handler->choices);
diff --git a/drivers/platform/x86/hp/hp-wmi.c b/drivers/platform/x86/hp/hp-wmi.c
index b8e62dc9cecd..60328b35be74 100644
--- a/drivers/platform/x86/hp/hp-wmi.c
+++ b/drivers/platform/x86/hp/hp-wmi.c
@@ -1565,6 +1565,21 @@ static inline void omen_unregister_powersource_event_handler(void)
unregister_acpi_notifier(&platform_power_source_nb);
}
+static const struct platform_profile_ops platform_profile_omen_ops = {
+ .profile_get = platform_profile_omen_get,
+ .profile_set = platform_profile_omen_set,
+};
+
+static const struct platform_profile_ops platform_profile_victus_ops = {
+ .profile_get = platform_profile_victus_get,
+ .profile_set = platform_profile_victus_set,
+};
+
+static const struct platform_profile_ops hp_wmi_platform_profile_ops = {
+ .profile_get = hp_wmi_platform_profile_get,
+ .profile_set = hp_wmi_platform_profile_set,
+};
+
static int thermal_profile_setup(struct platform_device *device)
{
int err, tp;
@@ -1582,8 +1597,7 @@ static int thermal_profile_setup(struct platform_device *device)
if (err < 0)
return err;
- platform_profile_handler.profile_get = platform_profile_omen_get;
- platform_profile_handler.profile_set = platform_profile_omen_set;
+ platform_profile_handler.ops = &platform_profile_omen_ops;
set_bit(PLATFORM_PROFILE_COOL, platform_profile_handler.choices);
} else if (is_victus_thermal_profile()) {
@@ -1599,8 +1613,7 @@ static int thermal_profile_setup(struct platform_device *device)
if (err < 0)
return err;
- platform_profile_handler.profile_get = platform_profile_victus_get;
- platform_profile_handler.profile_set = platform_profile_victus_set;
+ platform_profile_handler.ops = &platform_profile_victus_ops;
set_bit(PLATFORM_PROFILE_QUIET, platform_profile_handler.choices);
} else {
@@ -1617,8 +1630,7 @@ static int thermal_profile_setup(struct platform_device *device)
if (err)
return err;
- platform_profile_handler.profile_get = hp_wmi_platform_profile_get;
- platform_profile_handler.profile_set = hp_wmi_platform_profile_set;
+ platform_profile_handler.ops = &hp_wmi_platform_profile_ops;
set_bit(PLATFORM_PROFILE_QUIET, platform_profile_handler.choices);
set_bit(PLATFORM_PROFILE_COOL, platform_profile_handler.choices);
diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c
index fc317f42bb82..96e99513b0b5 100644
--- a/drivers/platform/x86/ideapad-laptop.c
+++ b/drivers/platform/x86/ideapad-laptop.c
@@ -1063,6 +1063,11 @@ static const struct dmi_system_id ideapad_dytc_v4_allow_table[] = {
{}
};
+static const struct platform_profile_ops dytc_profile_ops = {
+ .profile_get = dytc_profile_get,
+ .profile_set = dytc_profile_set,
+};
+
static int ideapad_dytc_profile_init(struct ideapad_private *priv)
{
int err, dytc_version;
@@ -1105,8 +1110,7 @@ static int ideapad_dytc_profile_init(struct ideapad_private *priv)
priv->dytc->pprof.name = "ideapad-laptop";
priv->dytc->pprof.dev = &priv->platform_device->dev;
priv->dytc->priv = priv;
- priv->dytc->pprof.profile_get = dytc_profile_get;
- priv->dytc->pprof.profile_set = dytc_profile_set;
+ priv->dytc->pprof.ops = &dytc_profile_ops;
/* Setup supported modes */
set_bit(PLATFORM_PROFILE_LOW_POWER, priv->dytc->pprof.choices);
diff --git a/drivers/platform/x86/inspur_platform_profile.c b/drivers/platform/x86/inspur_platform_profile.c
index 47d2dbbf3392..d0a8e4eebffa 100644
--- a/drivers/platform/x86/inspur_platform_profile.c
+++ b/drivers/platform/x86/inspur_platform_profile.c
@@ -164,6 +164,11 @@ static int inspur_platform_profile_get(struct device *dev,
return 0;
}
+static const struct platform_profile_ops inspur_platform_profile_ops = {
+ .profile_get = inspur_platform_profile_get,
+ .profile_set = inspur_platform_profile_set,
+};
+
static int inspur_wmi_probe(struct wmi_device *wdev, const void *context)
{
struct inspur_wmi_priv *priv;
@@ -177,8 +182,7 @@ static int inspur_wmi_probe(struct wmi_device *wdev, const void *context)
priv->handler.name = "inspur-wmi";
priv->handler.dev = &wdev->dev;
- priv->handler.profile_get = inspur_platform_profile_get;
- priv->handler.profile_set = inspur_platform_profile_set;
+ priv->handler.ops = &inspur_platform_profile_ops;
set_bit(PLATFORM_PROFILE_LOW_POWER, priv->handler.choices);
set_bit(PLATFORM_PROFILE_BALANCED, priv->handler.choices);
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
index 47f87bb213a9..9978fd36a3d1 100644
--- a/drivers/platform/x86/thinkpad_acpi.c
+++ b/drivers/platform/x86/thinkpad_acpi.c
@@ -10538,12 +10538,16 @@ static int dytc_profile_set(struct device *dev,
return err;
}
-static struct platform_profile_handler dytc_profile = {
- .name = "thinkpad-acpi",
+static const struct platform_profile_ops dytc_profile_ops = {
.profile_get = dytc_profile_get,
.profile_set = dytc_profile_set,
};
+static struct platform_profile_handler dytc_profile = {
+ .name = "thinkpad-acpi",
+ .ops = &dytc_profile_ops,
+};
+
static void dytc_profile_refresh(void)
{
enum platform_profile_option profile;
diff --git a/include/linux/platform_profile.h b/include/linux/platform_profile.h
index 5296d886c243..6013c05d7b86 100644
--- a/include/linux/platform_profile.h
+++ b/include/linux/platform_profile.h
@@ -28,14 +28,20 @@ enum platform_profile_option {
PLATFORM_PROFILE_LAST, /*must always be last */
};
+struct platform_profile_handler;
+
+struct platform_profile_ops {
+ int (*profile_get)(struct device *dev, enum platform_profile_option *profile);
+ int (*profile_set)(struct device *dev, enum platform_profile_option profile);
+};
+
struct platform_profile_handler {
const char *name;
struct device *dev;
struct device class_dev;
int minor;
unsigned long choices[BITS_TO_LONGS(PLATFORM_PROFILE_LAST)];
- int (*profile_get)(struct device *dev, enum platform_profile_option *profile);
- int (*profile_set)(struct device *dev, enum platform_profile_option profile);
+ const struct platform_profile_ops *ops;
};
int platform_profile_register(struct platform_profile_handler *pprof, void *drvdata);
--
2.47.1
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH v2 05/18] ACPI: platform_profile: Add `probe` to platform_profile_ops
2025-01-14 15:37 [PATCH v2 00/18] Hide platform_profile_handler from consumers Kurt Borja
` (3 preceding siblings ...)
2025-01-14 15:37 ` [PATCH v2 04/18] ACPI: platform_profile: Add `ops` member to handlers Kurt Borja
@ 2025-01-14 15:37 ` Kurt Borja
2025-01-14 16:20 ` Mario Limonciello
2025-01-14 15:37 ` [PATCH v2 06/18] platform/surface: surface_platform_profile: Use devm_platform_profile_register() Kurt Borja
` (13 subsequent siblings)
18 siblings, 1 reply; 33+ messages in thread
From: Kurt Borja @ 2025-01-14 15:37 UTC (permalink / raw)
To: platform-driver-x86
Cc: Rafael J. Wysocki, Len Brown, linux-acpi, linux-kernel,
Mario Limonciello, Armin Wolf, Joshua Grisham, Derek J. Clark,
Ilpo Järvinen, Hans de Goede, Kurt Borja, Maximilian Luz,
Lee, Chun-Yi, Shyam Sundar S K, Corentin Chary, Luke D. Jones,
Lyndon Sanche, Ike Panhc, Henrique de Moraes Holschuh,
Mark Pearson, Alexis Belmonte, Ai Chao, Gergo Koteles,
Dell.Client.Kernel, ibm-acpi-devel
Add a `probe` callback to platform_profile_ops, which lets drivers
initialize the choices member manually.
Signed-off-by: Kurt Borja <kuurtb@gmail.com>
---
drivers/acpi/platform_profile.c | 13 +++++++--
.../surface/surface_platform_profile.c | 16 ++++++----
drivers/platform/x86/acer-wmi.c | 24 ++++++++-------
drivers/platform/x86/amd/pmf/sps.c | 15 ++++++----
drivers/platform/x86/asus-wmi.c | 16 ++++++----
drivers/platform/x86/dell/alienware-wmi.c | 24 +++++++++------
drivers/platform/x86/dell/dell-pc.c | 26 ++++++++++-------
drivers/platform/x86/hp/hp-wmi.c | 29 +++++++++++++------
drivers/platform/x86/ideapad-laptop.c | 15 ++++++----
.../platform/x86/inspur_platform_profile.c | 14 ++++++---
drivers/platform/x86/thinkpad_acpi.c | 15 ++++++----
include/linux/platform_profile.h | 1 +
12 files changed, 137 insertions(+), 71 deletions(-)
diff --git a/drivers/acpi/platform_profile.c b/drivers/acpi/platform_profile.c
index 440654e21620..34e22b006ccc 100644
--- a/drivers/acpi/platform_profile.c
+++ b/drivers/acpi/platform_profile.c
@@ -466,12 +466,21 @@ int platform_profile_register(struct platform_profile_handler *pprof, void *drvd
int err;
/* Sanity check the profile handler */
- if (!pprof || bitmap_empty(pprof->choices, PLATFORM_PROFILE_LAST) ||
- !pprof->ops->profile_set || !pprof->ops->profile_get) {
+ if (!pprof || !pprof->ops->profile_set || !pprof->ops->profile_get ||
+ !pprof->ops->probe) {
pr_err("platform_profile: handler is invalid\n");
return -EINVAL;
}
+ err = pprof->ops->probe(drvdata, pprof->choices);
+ if (err < 0)
+ return err;
+
+ if (bitmap_empty(pprof->choices, PLATFORM_PROFILE_LAST)) {
+ pr_err("platform_profile: no available profiles\n");
+ return -EINVAL;
+ }
+
guard(mutex)(&profile_lock);
/* create class interface for individual handler */
diff --git a/drivers/platform/surface/surface_platform_profile.c b/drivers/platform/surface/surface_platform_profile.c
index 76967bfeeef8..48cfe9cb89c8 100644
--- a/drivers/platform/surface/surface_platform_profile.c
+++ b/drivers/platform/surface/surface_platform_profile.c
@@ -201,7 +201,18 @@ static int ssam_platform_profile_set(struct device *dev,
return tp;
}
+static int ssam_platform_profile_probe(void *drvdata, unsigned long *choices)
+{
+ set_bit(PLATFORM_PROFILE_LOW_POWER, choices);
+ set_bit(PLATFORM_PROFILE_BALANCED, choices);
+ set_bit(PLATFORM_PROFILE_BALANCED_PERFORMANCE, choices);
+ set_bit(PLATFORM_PROFILE_PERFORMANCE, choices);
+
+ return 0;
+}
+
static const struct platform_profile_ops ssam_platform_profile_ops = {
+ .probe = ssam_platform_profile_probe,
.profile_get = ssam_platform_profile_get,
.profile_set = ssam_platform_profile_set,
};
@@ -223,11 +234,6 @@ static int surface_platform_profile_probe(struct ssam_device *sdev)
tpd->has_fan = device_property_read_bool(&sdev->dev, "has_fan");
- set_bit(PLATFORM_PROFILE_LOW_POWER, tpd->handler.choices);
- set_bit(PLATFORM_PROFILE_BALANCED, tpd->handler.choices);
- set_bit(PLATFORM_PROFILE_BALANCED_PERFORMANCE, tpd->handler.choices);
- set_bit(PLATFORM_PROFILE_PERFORMANCE, tpd->handler.choices);
-
return platform_profile_register(&tpd->handler, tpd);
}
diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c
index 91ae48adf6cf..6953e36dbfde 100644
--- a/drivers/platform/x86/acer-wmi.c
+++ b/drivers/platform/x86/acer-wmi.c
@@ -1916,7 +1916,20 @@ acer_predator_v4_platform_profile_set(struct device *dev,
return 0;
}
+static int
+acer_predator_v4_platform_profile_probe(void *drvdata, unsigned long *choices)
+{
+ set_bit(PLATFORM_PROFILE_PERFORMANCE, choices);
+ set_bit(PLATFORM_PROFILE_BALANCED_PERFORMANCE, choices);
+ set_bit(PLATFORM_PROFILE_BALANCED, choices);
+ set_bit(PLATFORM_PROFILE_QUIET, choices);
+ set_bit(PLATFORM_PROFILE_LOW_POWER, choices);
+
+ return 0;
+}
+
static const struct platform_profile_ops acer_predator_v4_platform_profile_ops = {
+ .probe = acer_predator_v4_platform_profile_probe,
.profile_get = acer_predator_v4_platform_profile_get,
.profile_set = acer_predator_v4_platform_profile_set,
};
@@ -1931,17 +1944,6 @@ static int acer_platform_profile_setup(struct platform_device *device)
platform_profile_handler.ops =
&acer_predator_v4_platform_profile_ops;
- set_bit(PLATFORM_PROFILE_PERFORMANCE,
- platform_profile_handler.choices);
- set_bit(PLATFORM_PROFILE_BALANCED_PERFORMANCE,
- platform_profile_handler.choices);
- set_bit(PLATFORM_PROFILE_BALANCED,
- platform_profile_handler.choices);
- set_bit(PLATFORM_PROFILE_QUIET,
- platform_profile_handler.choices);
- set_bit(PLATFORM_PROFILE_LOW_POWER,
- platform_profile_handler.choices);
-
err = platform_profile_register(&platform_profile_handler, NULL);
if (err)
return err;
diff --git a/drivers/platform/x86/amd/pmf/sps.c b/drivers/platform/x86/amd/pmf/sps.c
index 6ae82ae86d22..e710405b581f 100644
--- a/drivers/platform/x86/amd/pmf/sps.c
+++ b/drivers/platform/x86/amd/pmf/sps.c
@@ -387,7 +387,17 @@ static int amd_pmf_profile_set(struct device *dev,
return 0;
}
+static int amd_pmf_profile_probe(void *drvdata, unsigned long *choices)
+{
+ set_bit(PLATFORM_PROFILE_LOW_POWER, choices);
+ set_bit(PLATFORM_PROFILE_BALANCED, choices);
+ set_bit(PLATFORM_PROFILE_PERFORMANCE, choices);
+
+ return 0;
+}
+
static const struct platform_profile_ops amd_pmf_profile_ops = {
+ .probe = amd_pmf_profile_probe,
.profile_get = amd_pmf_profile_get,
.profile_set = amd_pmf_profile_set,
};
@@ -414,11 +424,6 @@ int amd_pmf_init_sps(struct amd_pmf_dev *dev)
dev->pprof.dev = dev->dev;
dev->pprof.ops = &amd_pmf_profile_ops;
- /* Setup supported modes */
- set_bit(PLATFORM_PROFILE_LOW_POWER, dev->pprof.choices);
- set_bit(PLATFORM_PROFILE_BALANCED, dev->pprof.choices);
- set_bit(PLATFORM_PROFILE_PERFORMANCE, dev->pprof.choices);
-
/* Create platform_profile structure and register */
err = platform_profile_register(&dev->pprof, dev);
if (err)
diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
index d88860dd028b..3d77f7454953 100644
--- a/drivers/platform/x86/asus-wmi.c
+++ b/drivers/platform/x86/asus-wmi.c
@@ -3852,7 +3852,17 @@ static int asus_wmi_platform_profile_set(struct device *dev,
return throttle_thermal_policy_write(asus);
}
+static int asus_wmi_platform_profile_probe(void *drvdata, unsigned long *choices)
+{
+ set_bit(PLATFORM_PROFILE_QUIET, choices);
+ set_bit(PLATFORM_PROFILE_BALANCED, choices);
+ set_bit(PLATFORM_PROFILE_PERFORMANCE, choices);
+
+ return 0;
+}
+
static const struct platform_profile_ops asus_wmi_platform_profile_ops = {
+ .probe = asus_wmi_platform_profile_probe,
.profile_get = asus_wmi_platform_profile_get,
.profile_set = asus_wmi_platform_profile_set,
};
@@ -3885,12 +3895,6 @@ static int platform_profile_setup(struct asus_wmi *asus)
asus->platform_profile_handler.dev = dev;
asus->platform_profile_handler.ops = &asus_wmi_platform_profile_ops;
- set_bit(PLATFORM_PROFILE_QUIET, asus->platform_profile_handler.choices);
- set_bit(PLATFORM_PROFILE_BALANCED,
- asus->platform_profile_handler.choices);
- set_bit(PLATFORM_PROFILE_PERFORMANCE,
- asus->platform_profile_handler.choices);
-
err = platform_profile_register(&asus->platform_profile_handler, asus);
if (err == -EEXIST) {
pr_warn("%s, a platform_profile handler is already registered\n", __func__);
diff --git a/drivers/platform/x86/dell/alienware-wmi.c b/drivers/platform/x86/dell/alienware-wmi.c
index f7a854d40575..0146d2f93be6 100644
--- a/drivers/platform/x86/dell/alienware-wmi.c
+++ b/drivers/platform/x86/dell/alienware-wmi.c
@@ -1078,12 +1078,7 @@ static int thermal_profile_set(struct device *dev,
return wmax_thermal_control(supported_thermal_profiles[profile]);
}
-static const struct platform_profile_ops awcc_platform_profile_ops = {
- .profile_get = thermal_profile_get,
- .profile_set = thermal_profile_set,
-};
-
-static int create_thermal_profile(struct platform_device *platform_device)
+static int thermal_profile_probe(void *drvdata, unsigned long *choices)
{
enum platform_profile_option profile;
enum wmax_thermal_mode mode;
@@ -1116,19 +1111,30 @@ static int create_thermal_profile(struct platform_device *platform_device)
profile = wmax_mode_to_platform_profile[mode];
supported_thermal_profiles[profile] = out_data;
- set_bit(profile, pp_handler.choices);
+ set_bit(profile, choices);
}
- if (bitmap_empty(pp_handler.choices, PLATFORM_PROFILE_LAST))
+ if (bitmap_empty(choices, PLATFORM_PROFILE_LAST))
return -ENODEV;
if (quirks->gmode) {
supported_thermal_profiles[PLATFORM_PROFILE_PERFORMANCE] =
WMAX_THERMAL_MODE_GMODE;
- set_bit(PLATFORM_PROFILE_PERFORMANCE, pp_handler.choices);
+ set_bit(PLATFORM_PROFILE_PERFORMANCE, choices);
}
+ return 0;
+}
+
+static const struct platform_profile_ops awcc_platform_profile_ops = {
+ .probe = thermal_profile_probe,
+ .profile_get = thermal_profile_get,
+ .profile_set = thermal_profile_set,
+};
+
+static int create_thermal_profile(struct platform_device *platform_device)
+{
pp_handler.name = "alienware-wmi";
pp_handler.dev = &platform_device->dev;
pp_handler.ops = &awcc_platform_profile_ops;
diff --git a/drivers/platform/x86/dell/dell-pc.c b/drivers/platform/x86/dell/dell-pc.c
index 9010a231f209..32b3be0723f8 100644
--- a/drivers/platform/x86/dell/dell-pc.c
+++ b/drivers/platform/x86/dell/dell-pc.c
@@ -24,6 +24,7 @@
#include "dell-smbios.h"
static struct platform_device *platform_device;
+static int supported_modes;
static const struct dmi_system_id dell_device_table[] __initconst = {
{
@@ -231,7 +232,22 @@ static int thermal_platform_profile_get(struct device *dev,
return 0;
}
+static int thermal_platform_profile_probe(void *drvdata, unsigned long *choices)
+{
+ if (supported_modes & DELL_QUIET)
+ set_bit(PLATFORM_PROFILE_QUIET, choices);
+ if (supported_modes & DELL_COOL_BOTTOM)
+ set_bit(PLATFORM_PROFILE_COOL, choices);
+ if (supported_modes & DELL_BALANCED)
+ set_bit(PLATFORM_PROFILE_BALANCED, choices);
+ if (supported_modes & DELL_PERFORMANCE)
+ set_bit(PLATFORM_PROFILE_PERFORMANCE, choices);
+
+ return 0;
+}
+
static const struct platform_profile_ops dell_pc_platform_profile_ops = {
+ .probe = thermal_platform_profile_probe,
.profile_get = thermal_platform_profile_get,
.profile_set = thermal_platform_profile_set,
};
@@ -239,7 +255,6 @@ static const struct platform_profile_ops dell_pc_platform_profile_ops = {
static int thermal_init(void)
{
int ret;
- int supported_modes;
/* If thermal commands are not supported, exit without error */
if (!dell_smbios_class_is_supported(CLASS_INFO))
@@ -265,15 +280,6 @@ static int thermal_init(void)
thermal_handler->dev = &platform_device->dev;
thermal_handler->ops = &dell_pc_platform_profile_ops;
- if (supported_modes & DELL_QUIET)
- set_bit(PLATFORM_PROFILE_QUIET, thermal_handler->choices);
- if (supported_modes & DELL_COOL_BOTTOM)
- set_bit(PLATFORM_PROFILE_COOL, thermal_handler->choices);
- if (supported_modes & DELL_BALANCED)
- set_bit(PLATFORM_PROFILE_BALANCED, thermal_handler->choices);
- if (supported_modes & DELL_PERFORMANCE)
- set_bit(PLATFORM_PROFILE_PERFORMANCE, thermal_handler->choices);
-
/* Clean up if failed */
ret = platform_profile_register(thermal_handler, NULL);
if (ret)
diff --git a/drivers/platform/x86/hp/hp-wmi.c b/drivers/platform/x86/hp/hp-wmi.c
index 60328b35be74..75bcd8460e7c 100644
--- a/drivers/platform/x86/hp/hp-wmi.c
+++ b/drivers/platform/x86/hp/hp-wmi.c
@@ -1488,6 +1488,23 @@ static int platform_profile_victus_set(struct device *dev,
return 0;
}
+static int hp_wmi_platform_profile_probe(void *drvdata, unsigned long *choices)
+{
+ if (is_omen_thermal_profile()) {
+ set_bit(PLATFORM_PROFILE_COOL, choices);
+ } else if (is_victus_thermal_profile()) {
+ set_bit(PLATFORM_PROFILE_QUIET, choices);
+ } else {
+ set_bit(PLATFORM_PROFILE_QUIET, choices);
+ set_bit(PLATFORM_PROFILE_COOL, choices);
+ }
+
+ set_bit(PLATFORM_PROFILE_BALANCED, choices);
+ set_bit(PLATFORM_PROFILE_PERFORMANCE, choices);
+
+ return 0;
+}
+
static int omen_powersource_event(struct notifier_block *nb,
unsigned long value,
void *data)
@@ -1566,16 +1583,19 @@ static inline void omen_unregister_powersource_event_handler(void)
}
static const struct platform_profile_ops platform_profile_omen_ops = {
+ .probe = hp_wmi_platform_profile_probe,
.profile_get = platform_profile_omen_get,
.profile_set = platform_profile_omen_set,
};
static const struct platform_profile_ops platform_profile_victus_ops = {
+ .probe = hp_wmi_platform_profile_probe,
.profile_get = platform_profile_victus_get,
.profile_set = platform_profile_victus_set,
};
static const struct platform_profile_ops hp_wmi_platform_profile_ops = {
+ .probe = hp_wmi_platform_profile_probe,
.profile_get = hp_wmi_platform_profile_get,
.profile_set = hp_wmi_platform_profile_set,
};
@@ -1598,8 +1618,6 @@ static int thermal_profile_setup(struct platform_device *device)
return err;
platform_profile_handler.ops = &platform_profile_omen_ops;
-
- set_bit(PLATFORM_PROFILE_COOL, platform_profile_handler.choices);
} else if (is_victus_thermal_profile()) {
err = platform_profile_victus_get_ec(&active_platform_profile);
if (err < 0)
@@ -1614,8 +1632,6 @@ static int thermal_profile_setup(struct platform_device *device)
return err;
platform_profile_handler.ops = &platform_profile_victus_ops;
-
- set_bit(PLATFORM_PROFILE_QUIET, platform_profile_handler.choices);
} else {
tp = thermal_profile_get();
@@ -1631,15 +1647,10 @@ static int thermal_profile_setup(struct platform_device *device)
return err;
platform_profile_handler.ops = &hp_wmi_platform_profile_ops;
-
- set_bit(PLATFORM_PROFILE_QUIET, platform_profile_handler.choices);
- set_bit(PLATFORM_PROFILE_COOL, platform_profile_handler.choices);
}
platform_profile_handler.name = "hp-wmi";
platform_profile_handler.dev = &device->dev;
- set_bit(PLATFORM_PROFILE_BALANCED, platform_profile_handler.choices);
- set_bit(PLATFORM_PROFILE_PERFORMANCE, platform_profile_handler.choices);
err = platform_profile_register(&platform_profile_handler, NULL);
if (err)
diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c
index 96e99513b0b5..050919a28d2b 100644
--- a/drivers/platform/x86/ideapad-laptop.c
+++ b/drivers/platform/x86/ideapad-laptop.c
@@ -1023,6 +1023,15 @@ static int dytc_profile_set(struct device *dev,
return -EINTR;
}
+static int dytc_profile_probe(void *drvdata, unsigned long *choices)
+{
+ set_bit(PLATFORM_PROFILE_LOW_POWER, choices);
+ set_bit(PLATFORM_PROFILE_BALANCED, choices);
+ set_bit(PLATFORM_PROFILE_PERFORMANCE, choices);
+
+ return 0;
+}
+
static void dytc_profile_refresh(struct ideapad_private *priv)
{
enum platform_profile_option profile;
@@ -1064,6 +1073,7 @@ static const struct dmi_system_id ideapad_dytc_v4_allow_table[] = {
};
static const struct platform_profile_ops dytc_profile_ops = {
+ .probe = dytc_profile_probe,
.profile_get = dytc_profile_get,
.profile_set = dytc_profile_set,
};
@@ -1112,11 +1122,6 @@ static int ideapad_dytc_profile_init(struct ideapad_private *priv)
priv->dytc->priv = priv;
priv->dytc->pprof.ops = &dytc_profile_ops;
- /* Setup supported modes */
- set_bit(PLATFORM_PROFILE_LOW_POWER, priv->dytc->pprof.choices);
- set_bit(PLATFORM_PROFILE_BALANCED, priv->dytc->pprof.choices);
- set_bit(PLATFORM_PROFILE_PERFORMANCE, priv->dytc->pprof.choices);
-
/* Create platform_profile structure and register */
err = platform_profile_register(&priv->dytc->pprof, &priv->dytc);
if (err)
diff --git a/drivers/platform/x86/inspur_platform_profile.c b/drivers/platform/x86/inspur_platform_profile.c
index d0a8e4eebffa..06df3aae9a56 100644
--- a/drivers/platform/x86/inspur_platform_profile.c
+++ b/drivers/platform/x86/inspur_platform_profile.c
@@ -164,7 +164,17 @@ static int inspur_platform_profile_get(struct device *dev,
return 0;
}
+static int inspur_platform_profile_probe(void *drvdata, unsigned long *choices)
+{
+ set_bit(PLATFORM_PROFILE_LOW_POWER, choices);
+ set_bit(PLATFORM_PROFILE_BALANCED, choices);
+ set_bit(PLATFORM_PROFILE_PERFORMANCE, choices);
+
+ return 0;
+}
+
static const struct platform_profile_ops inspur_platform_profile_ops = {
+ .probe = inspur_platform_profile_probe,
.profile_get = inspur_platform_profile_get,
.profile_set = inspur_platform_profile_set,
};
@@ -184,10 +194,6 @@ static int inspur_wmi_probe(struct wmi_device *wdev, const void *context)
priv->handler.dev = &wdev->dev;
priv->handler.ops = &inspur_platform_profile_ops;
- set_bit(PLATFORM_PROFILE_LOW_POWER, priv->handler.choices);
- set_bit(PLATFORM_PROFILE_BALANCED, priv->handler.choices);
- set_bit(PLATFORM_PROFILE_PERFORMANCE, priv->handler.choices);
-
return platform_profile_register(&priv->handler, priv);
}
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
index 9978fd36a3d1..5c250867678f 100644
--- a/drivers/platform/x86/thinkpad_acpi.c
+++ b/drivers/platform/x86/thinkpad_acpi.c
@@ -10538,7 +10538,17 @@ static int dytc_profile_set(struct device *dev,
return err;
}
+static int dytc_profile_probe(void *drvdata, unsigned long *choices)
+{
+ set_bit(PLATFORM_PROFILE_LOW_POWER, choices);
+ set_bit(PLATFORM_PROFILE_BALANCED, choices);
+ set_bit(PLATFORM_PROFILE_PERFORMANCE, choices);
+
+ return 0;
+}
+
static const struct platform_profile_ops dytc_profile_ops = {
+ .probe = dytc_profile_probe,
.profile_get = dytc_profile_get,
.profile_set = dytc_profile_set,
};
@@ -10584,11 +10594,6 @@ static int tpacpi_dytc_profile_init(struct ibm_init_struct *iibm)
{
int err, output;
- /* Setup supported modes */
- set_bit(PLATFORM_PROFILE_LOW_POWER, dytc_profile.choices);
- set_bit(PLATFORM_PROFILE_BALANCED, dytc_profile.choices);
- set_bit(PLATFORM_PROFILE_PERFORMANCE, dytc_profile.choices);
-
err = dytc_command(DYTC_CMD_QUERY, &output);
if (err)
return err;
diff --git a/include/linux/platform_profile.h b/include/linux/platform_profile.h
index 6013c05d7b86..5ad1ab7b75e4 100644
--- a/include/linux/platform_profile.h
+++ b/include/linux/platform_profile.h
@@ -31,6 +31,7 @@ enum platform_profile_option {
struct platform_profile_handler;
struct platform_profile_ops {
+ int (*probe)(void *drvdata, unsigned long *choices);
int (*profile_get)(struct device *dev, enum platform_profile_option *profile);
int (*profile_set)(struct device *dev, enum platform_profile_option profile);
};
--
2.47.1
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH v2 06/18] platform/surface: surface_platform_profile: Use devm_platform_profile_register()
2025-01-14 15:37 [PATCH v2 00/18] Hide platform_profile_handler from consumers Kurt Borja
` (4 preceding siblings ...)
2025-01-14 15:37 ` [PATCH v2 05/18] ACPI: platform_profile: Add `probe` to platform_profile_ops Kurt Borja
@ 2025-01-14 15:37 ` Kurt Borja
2025-01-14 15:37 ` [PATCH v2 07/18] platform/x86: acer-wmi: " Kurt Borja
` (12 subsequent siblings)
18 siblings, 0 replies; 33+ messages in thread
From: Kurt Borja @ 2025-01-14 15:37 UTC (permalink / raw)
To: platform-driver-x86
Cc: Rafael J. Wysocki, Len Brown, linux-acpi, linux-kernel,
Mario Limonciello, Armin Wolf, Joshua Grisham, Derek J. Clark,
Ilpo Järvinen, Hans de Goede, Kurt Borja, Maximilian Luz,
Lee, Chun-Yi, Shyam Sundar S K, Corentin Chary, Luke D. Jones,
Lyndon Sanche, Ike Panhc, Henrique de Moraes Holschuh,
Mark Pearson, Alexis Belmonte, Ai Chao, Gergo Koteles,
Dell.Client.Kernel, ibm-acpi-devel
Replace platform_profile_register() with it's device managed version.
Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
Signed-off-by: Kurt Borja <kuurtb@gmail.com>
---
drivers/platform/surface/surface_platform_profile.c | 11 +----------
1 file changed, 1 insertion(+), 10 deletions(-)
diff --git a/drivers/platform/surface/surface_platform_profile.c b/drivers/platform/surface/surface_platform_profile.c
index 48cfe9cb89c8..bbdc873cb788 100644
--- a/drivers/platform/surface/surface_platform_profile.c
+++ b/drivers/platform/surface/surface_platform_profile.c
@@ -234,15 +234,7 @@ static int surface_platform_profile_probe(struct ssam_device *sdev)
tpd->has_fan = device_property_read_bool(&sdev->dev, "has_fan");
- return platform_profile_register(&tpd->handler, tpd);
-}
-
-static void surface_platform_profile_remove(struct ssam_device *sdev)
-{
- struct ssam_platform_profile_device *tpd;
-
- tpd = ssam_device_get_drvdata(sdev);
- platform_profile_remove(&tpd->handler);
+ return devm_platform_profile_register(&tpd->handler, tpd);
}
static const struct ssam_device_id ssam_platform_profile_match[] = {
@@ -253,7 +245,6 @@ MODULE_DEVICE_TABLE(ssam, ssam_platform_profile_match);
static struct ssam_device_driver surface_platform_profile = {
.probe = surface_platform_profile_probe,
- .remove = surface_platform_profile_remove,
.match_table = ssam_platform_profile_match,
.driver = {
.name = "surface_platform_profile",
--
2.47.1
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH v2 07/18] platform/x86: acer-wmi: Use devm_platform_profile_register()
2025-01-14 15:37 [PATCH v2 00/18] Hide platform_profile_handler from consumers Kurt Borja
` (5 preceding siblings ...)
2025-01-14 15:37 ` [PATCH v2 06/18] platform/surface: surface_platform_profile: Use devm_platform_profile_register() Kurt Borja
@ 2025-01-14 15:37 ` Kurt Borja
2025-01-14 15:37 ` [PATCH v2 08/18] platform/x86: amd: pmf: sps: " Kurt Borja
` (11 subsequent siblings)
18 siblings, 0 replies; 33+ messages in thread
From: Kurt Borja @ 2025-01-14 15:37 UTC (permalink / raw)
To: platform-driver-x86
Cc: Rafael J. Wysocki, Len Brown, linux-acpi, linux-kernel,
Mario Limonciello, Armin Wolf, Joshua Grisham, Derek J. Clark,
Ilpo Järvinen, Hans de Goede, Kurt Borja, Maximilian Luz,
Lee, Chun-Yi, Shyam Sundar S K, Corentin Chary, Luke D. Jones,
Lyndon Sanche, Ike Panhc, Henrique de Moraes Holschuh,
Mark Pearson, Alexis Belmonte, Ai Chao, Gergo Koteles,
Dell.Client.Kernel, ibm-acpi-devel
Replace platform_profile_register() with it's device managed version.
Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
Signed-off-by: Kurt Borja <kuurtb@gmail.com>
---
drivers/platform/x86/acer-wmi.c | 7 +------
1 file changed, 1 insertion(+), 6 deletions(-)
diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c
index 6953e36dbfde..39ec236b7cdb 100644
--- a/drivers/platform/x86/acer-wmi.c
+++ b/drivers/platform/x86/acer-wmi.c
@@ -1944,7 +1944,7 @@ static int acer_platform_profile_setup(struct platform_device *device)
platform_profile_handler.ops =
&acer_predator_v4_platform_profile_ops;
- err = platform_profile_register(&platform_profile_handler, NULL);
+ err = devm_platform_profile_register(&platform_profile_handler, NULL);
if (err)
return err;
@@ -2591,8 +2591,6 @@ static int acer_platform_probe(struct platform_device *device)
return 0;
error_hwmon:
- if (platform_profile_support)
- platform_profile_remove(&platform_profile_handler);
error_platform_profile:
acer_rfkill_exit();
error_rfkill:
@@ -2613,9 +2611,6 @@ static void acer_platform_remove(struct platform_device *device)
acer_backlight_exit();
acer_rfkill_exit();
-
- if (platform_profile_support)
- platform_profile_remove(&platform_profile_handler);
}
#ifdef CONFIG_PM_SLEEP
--
2.47.1
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH v2 08/18] platform/x86: amd: pmf: sps: Use devm_platform_profile_register()
2025-01-14 15:37 [PATCH v2 00/18] Hide platform_profile_handler from consumers Kurt Borja
` (6 preceding siblings ...)
2025-01-14 15:37 ` [PATCH v2 07/18] platform/x86: acer-wmi: " Kurt Borja
@ 2025-01-14 15:37 ` Kurt Borja
2025-01-14 15:37 ` [PATCH v2 09/18] platform/x86: asus-wmi: " Kurt Borja
` (10 subsequent siblings)
18 siblings, 0 replies; 33+ messages in thread
From: Kurt Borja @ 2025-01-14 15:37 UTC (permalink / raw)
To: platform-driver-x86
Cc: Rafael J. Wysocki, Len Brown, linux-acpi, linux-kernel,
Mario Limonciello, Armin Wolf, Joshua Grisham, Derek J. Clark,
Ilpo Järvinen, Hans de Goede, Kurt Borja, Maximilian Luz,
Lee, Chun-Yi, Shyam Sundar S K, Corentin Chary, Luke D. Jones,
Lyndon Sanche, Ike Panhc, Henrique de Moraes Holschuh,
Mark Pearson, Alexis Belmonte, Ai Chao, Gergo Koteles,
Dell.Client.Kernel, ibm-acpi-devel
Replace platform_profile_register() with it's device managed version.
Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
Signed-off-by: Kurt Borja <kuurtb@gmail.com>
---
drivers/platform/x86/amd/pmf/core.c | 1 -
drivers/platform/x86/amd/pmf/pmf.h | 1 -
drivers/platform/x86/amd/pmf/sps.c | 7 +------
3 files changed, 1 insertion(+), 8 deletions(-)
diff --git a/drivers/platform/x86/amd/pmf/core.c b/drivers/platform/x86/amd/pmf/core.c
index 57ee95a327be..1211a753fee8 100644
--- a/drivers/platform/x86/amd/pmf/core.c
+++ b/drivers/platform/x86/amd/pmf/core.c
@@ -371,7 +371,6 @@ static void amd_pmf_deinit_features(struct amd_pmf_dev *dev)
if (is_apmf_func_supported(dev, APMF_FUNC_STATIC_SLIDER_GRANULAR) ||
is_apmf_func_supported(dev, APMF_FUNC_OS_POWER_SLIDER_UPDATE)) {
power_supply_unreg_notifier(&dev->pwr_src_notifier);
- amd_pmf_deinit_sps(dev);
}
if (dev->smart_pc_enabled) {
diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/x86/amd/pmf/pmf.h
index 080818dd173b..d99b3556205b 100644
--- a/drivers/platform/x86/amd/pmf/pmf.h
+++ b/drivers/platform/x86/amd/pmf/pmf.h
@@ -780,7 +780,6 @@ int amd_pmf_get_pprof_modes(struct amd_pmf_dev *pmf);
void amd_pmf_update_slider(struct amd_pmf_dev *dev, bool op, int idx,
struct amd_pmf_static_slider_granular *table);
int amd_pmf_init_sps(struct amd_pmf_dev *dev);
-void amd_pmf_deinit_sps(struct amd_pmf_dev *dev);
int apmf_get_static_slider_granular(struct amd_pmf_dev *pdev,
struct apmf_static_slider_granular_output *output);
bool is_pprof_balanced(struct amd_pmf_dev *pmf);
diff --git a/drivers/platform/x86/amd/pmf/sps.c b/drivers/platform/x86/amd/pmf/sps.c
index e710405b581f..7c7ed2b9de01 100644
--- a/drivers/platform/x86/amd/pmf/sps.c
+++ b/drivers/platform/x86/amd/pmf/sps.c
@@ -425,15 +425,10 @@ int amd_pmf_init_sps(struct amd_pmf_dev *dev)
dev->pprof.ops = &amd_pmf_profile_ops;
/* Create platform_profile structure and register */
- err = platform_profile_register(&dev->pprof, dev);
+ err = devm_platform_profile_register(&dev->pprof, dev);
if (err)
dev_err(dev->dev, "Failed to register SPS support, this is most likely an SBIOS bug: %d\n",
err);
return err;
}
-
-void amd_pmf_deinit_sps(struct amd_pmf_dev *dev)
-{
- platform_profile_remove(&dev->pprof);
-}
--
2.47.1
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH v2 09/18] platform/x86: asus-wmi: Use devm_platform_profile_register()
2025-01-14 15:37 [PATCH v2 00/18] Hide platform_profile_handler from consumers Kurt Borja
` (7 preceding siblings ...)
2025-01-14 15:37 ` [PATCH v2 08/18] platform/x86: amd: pmf: sps: " Kurt Borja
@ 2025-01-14 15:37 ` Kurt Borja
2025-01-14 15:37 ` [PATCH v2 10/18] platform/x86: dell-pc: " Kurt Borja
` (9 subsequent siblings)
18 siblings, 0 replies; 33+ messages in thread
From: Kurt Borja @ 2025-01-14 15:37 UTC (permalink / raw)
To: platform-driver-x86
Cc: Rafael J. Wysocki, Len Brown, linux-acpi, linux-kernel,
Mario Limonciello, Armin Wolf, Joshua Grisham, Derek J. Clark,
Ilpo Järvinen, Hans de Goede, Kurt Borja, Maximilian Luz,
Lee, Chun-Yi, Shyam Sundar S K, Corentin Chary, Luke D. Jones,
Lyndon Sanche, Ike Panhc, Henrique de Moraes Holschuh,
Mark Pearson, Alexis Belmonte, Ai Chao, Gergo Koteles,
Dell.Client.Kernel, ibm-acpi-devel
Replace platform_profile_register() with it's device managed version.
Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
Signed-off-by: Kurt Borja <kuurtb@gmail.com>
---
drivers/platform/x86/asus-wmi.c | 9 ++-------
1 file changed, 2 insertions(+), 7 deletions(-)
diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
index 3d77f7454953..f8437cff66df 100644
--- a/drivers/platform/x86/asus-wmi.c
+++ b/drivers/platform/x86/asus-wmi.c
@@ -3895,12 +3895,12 @@ static int platform_profile_setup(struct asus_wmi *asus)
asus->platform_profile_handler.dev = dev;
asus->platform_profile_handler.ops = &asus_wmi_platform_profile_ops;
- err = platform_profile_register(&asus->platform_profile_handler, asus);
+ err = devm_platform_profile_register(&asus->platform_profile_handler, asus);
if (err == -EEXIST) {
pr_warn("%s, a platform_profile handler is already registered\n", __func__);
return 0;
} else if (err) {
- pr_err("%s, failed at platform_profile_register: %d\n", __func__, err);
+ pr_err("%s, failed at devm_platform_profile_register: %d\n", __func__, err);
return err;
}
@@ -4859,8 +4859,6 @@ static int asus_wmi_add(struct platform_device *pdev)
fail_sysfs:
fail_custom_fan_curve:
fail_platform_profile_setup:
- if (asus->platform_profile_support)
- platform_profile_remove(&asus->platform_profile_handler);
fail_fan_boost_mode:
fail_platform:
kfree(asus);
@@ -4886,9 +4884,6 @@ static void asus_wmi_remove(struct platform_device *device)
throttle_thermal_policy_set_default(asus);
asus_wmi_battery_exit(asus);
- if (asus->platform_profile_support)
- platform_profile_remove(&asus->platform_profile_handler);
-
kfree(asus);
}
--
2.47.1
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH v2 10/18] platform/x86: dell-pc: Use devm_platform_profile_register()
2025-01-14 15:37 [PATCH v2 00/18] Hide platform_profile_handler from consumers Kurt Borja
` (8 preceding siblings ...)
2025-01-14 15:37 ` [PATCH v2 09/18] platform/x86: asus-wmi: " Kurt Borja
@ 2025-01-14 15:37 ` Kurt Borja
2025-01-14 15:37 ` [PATCH v2 11/18] platform/x86: ideapad-laptop: " Kurt Borja
` (8 subsequent siblings)
18 siblings, 0 replies; 33+ messages in thread
From: Kurt Borja @ 2025-01-14 15:37 UTC (permalink / raw)
To: platform-driver-x86
Cc: Rafael J. Wysocki, Len Brown, linux-acpi, linux-kernel,
Mario Limonciello, Armin Wolf, Joshua Grisham, Derek J. Clark,
Ilpo Järvinen, Hans de Goede, Kurt Borja, Maximilian Luz,
Lee, Chun-Yi, Shyam Sundar S K, Corentin Chary, Luke D. Jones,
Lyndon Sanche, Ike Panhc, Henrique de Moraes Holschuh,
Mark Pearson, Alexis Belmonte, Ai Chao, Gergo Koteles,
Dell.Client.Kernel, ibm-acpi-devel
Replace platform_profile_register() with it's device managed version.
Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
Signed-off-by: Kurt Borja <kuurtb@gmail.com>
---
drivers/platform/x86/dell/dell-pc.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/drivers/platform/x86/dell/dell-pc.c b/drivers/platform/x86/dell/dell-pc.c
index 32b3be0723f8..2759bb608b1a 100644
--- a/drivers/platform/x86/dell/dell-pc.c
+++ b/drivers/platform/x86/dell/dell-pc.c
@@ -281,7 +281,7 @@ static int thermal_init(void)
thermal_handler->ops = &dell_pc_platform_profile_ops;
/* Clean up if failed */
- ret = platform_profile_register(thermal_handler, NULL);
+ ret = devm_platform_profile_register(thermal_handler, NULL);
if (ret)
goto cleanup_thermal_handler;
@@ -298,8 +298,6 @@ static int thermal_init(void)
static void thermal_cleanup(void)
{
- if (thermal_handler)
- platform_profile_remove(thermal_handler);
platform_device_unregister(platform_device);
}
--
2.47.1
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH v2 11/18] platform/x86: ideapad-laptop: Use devm_platform_profile_register()
2025-01-14 15:37 [PATCH v2 00/18] Hide platform_profile_handler from consumers Kurt Borja
` (9 preceding siblings ...)
2025-01-14 15:37 ` [PATCH v2 10/18] platform/x86: dell-pc: " Kurt Borja
@ 2025-01-14 15:37 ` Kurt Borja
2025-01-14 15:37 ` [PATCH v2 12/18] platform/x86: hp-wmi: " Kurt Borja
` (7 subsequent siblings)
18 siblings, 0 replies; 33+ messages in thread
From: Kurt Borja @ 2025-01-14 15:37 UTC (permalink / raw)
To: platform-driver-x86
Cc: Rafael J. Wysocki, Len Brown, linux-acpi, linux-kernel,
Mario Limonciello, Armin Wolf, Joshua Grisham, Derek J. Clark,
Ilpo Järvinen, Hans de Goede, Kurt Borja, Maximilian Luz,
Lee, Chun-Yi, Shyam Sundar S K, Corentin Chary, Luke D. Jones,
Lyndon Sanche, Ike Panhc, Henrique de Moraes Holschuh,
Mark Pearson, Alexis Belmonte, Ai Chao, Gergo Koteles,
Dell.Client.Kernel, ibm-acpi-devel
Replace platform_profile_register() with it's device managed version.
Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
Signed-off-by: Kurt Borja <kuurtb@gmail.com>
---
drivers/platform/x86/ideapad-laptop.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c
index 050919a28d2b..87c1e087770a 100644
--- a/drivers/platform/x86/ideapad-laptop.c
+++ b/drivers/platform/x86/ideapad-laptop.c
@@ -1123,7 +1123,7 @@ static int ideapad_dytc_profile_init(struct ideapad_private *priv)
priv->dytc->pprof.ops = &dytc_profile_ops;
/* Create platform_profile structure and register */
- err = platform_profile_register(&priv->dytc->pprof, &priv->dytc);
+ err = devm_platform_profile_register(&priv->dytc->pprof, &priv->dytc);
if (err)
goto pp_reg_failed;
@@ -1145,7 +1145,6 @@ static void ideapad_dytc_profile_exit(struct ideapad_private *priv)
if (!priv->dytc)
return;
- platform_profile_remove(&priv->dytc->pprof);
mutex_destroy(&priv->dytc->mutex);
kfree(priv->dytc);
--
2.47.1
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH v2 12/18] platform/x86: hp-wmi: Use devm_platform_profile_register()
2025-01-14 15:37 [PATCH v2 00/18] Hide platform_profile_handler from consumers Kurt Borja
` (10 preceding siblings ...)
2025-01-14 15:37 ` [PATCH v2 11/18] platform/x86: ideapad-laptop: " Kurt Borja
@ 2025-01-14 15:37 ` Kurt Borja
2025-01-14 15:37 ` [PATCH v2 13/18] platform/x86: inspur_platform_profile: " Kurt Borja
` (6 subsequent siblings)
18 siblings, 0 replies; 33+ messages in thread
From: Kurt Borja @ 2025-01-14 15:37 UTC (permalink / raw)
To: platform-driver-x86
Cc: Rafael J. Wysocki, Len Brown, linux-acpi, linux-kernel,
Mario Limonciello, Armin Wolf, Joshua Grisham, Derek J. Clark,
Ilpo Järvinen, Hans de Goede, Kurt Borja, Maximilian Luz,
Lee, Chun-Yi, Shyam Sundar S K, Corentin Chary, Luke D. Jones,
Lyndon Sanche, Ike Panhc, Henrique de Moraes Holschuh,
Mark Pearson, Alexis Belmonte, Ai Chao, Gergo Koteles,
Dell.Client.Kernel, ibm-acpi-devel
Replace platform_profile_register() with it's device managed version.
Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
Signed-off-by: Kurt Borja <kuurtb@gmail.com>
---
drivers/platform/x86/hp/hp-wmi.c | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/drivers/platform/x86/hp/hp-wmi.c b/drivers/platform/x86/hp/hp-wmi.c
index 75bcd8460e7c..1304dfc65aab 100644
--- a/drivers/platform/x86/hp/hp-wmi.c
+++ b/drivers/platform/x86/hp/hp-wmi.c
@@ -1652,7 +1652,7 @@ static int thermal_profile_setup(struct platform_device *device)
platform_profile_handler.name = "hp-wmi";
platform_profile_handler.dev = &device->dev;
- err = platform_profile_register(&platform_profile_handler, NULL);
+ err = devm_platform_profile_register(&platform_profile_handler, NULL);
if (err)
return err;
@@ -1714,9 +1714,6 @@ static void __exit hp_wmi_bios_remove(struct platform_device *device)
rfkill_unregister(wwan_rfkill);
rfkill_destroy(wwan_rfkill);
}
-
- if (platform_profile_support)
- platform_profile_remove(&platform_profile_handler);
}
static int hp_wmi_resume_handler(struct device *device)
--
2.47.1
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH v2 13/18] platform/x86: inspur_platform_profile: Use devm_platform_profile_register()
2025-01-14 15:37 [PATCH v2 00/18] Hide platform_profile_handler from consumers Kurt Borja
` (11 preceding siblings ...)
2025-01-14 15:37 ` [PATCH v2 12/18] platform/x86: hp-wmi: " Kurt Borja
@ 2025-01-14 15:37 ` Kurt Borja
2025-01-14 15:37 ` [PATCH v2 14/18] platform/x86: thinkpad_acpi: " Kurt Borja
` (5 subsequent siblings)
18 siblings, 0 replies; 33+ messages in thread
From: Kurt Borja @ 2025-01-14 15:37 UTC (permalink / raw)
To: platform-driver-x86
Cc: Rafael J. Wysocki, Len Brown, linux-acpi, linux-kernel,
Mario Limonciello, Armin Wolf, Joshua Grisham, Derek J. Clark,
Ilpo Järvinen, Hans de Goede, Kurt Borja, Maximilian Luz,
Lee, Chun-Yi, Shyam Sundar S K, Corentin Chary, Luke D. Jones,
Lyndon Sanche, Ike Panhc, Henrique de Moraes Holschuh,
Mark Pearson, Alexis Belmonte, Ai Chao, Gergo Koteles,
Dell.Client.Kernel, ibm-acpi-devel
Replace platform_profile_register() with it's device managed version.
While at it, pass inspur_wmi_priv to the class device as drvdata and
replace uses of container_of() with dev_get_drvdata().
Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
Signed-off-by: Kurt Borja <kuurtb@gmail.com>
---
drivers/platform/x86/inspur_platform_profile.c | 11 +----------
1 file changed, 1 insertion(+), 10 deletions(-)
diff --git a/drivers/platform/x86/inspur_platform_profile.c b/drivers/platform/x86/inspur_platform_profile.c
index 06df3aae9a56..e1631de6ad86 100644
--- a/drivers/platform/x86/inspur_platform_profile.c
+++ b/drivers/platform/x86/inspur_platform_profile.c
@@ -194,15 +194,7 @@ static int inspur_wmi_probe(struct wmi_device *wdev, const void *context)
priv->handler.dev = &wdev->dev;
priv->handler.ops = &inspur_platform_profile_ops;
- return platform_profile_register(&priv->handler, priv);
-}
-
-static void inspur_wmi_remove(struct wmi_device *wdev)
-{
- struct inspur_wmi_priv *priv;
-
- priv = dev_get_drvdata(&wdev->dev);
- platform_profile_remove(&priv->handler);
+ return devm_platform_profile_register(&priv->handler, priv);
}
static const struct wmi_device_id inspur_wmi_id_table[] = {
@@ -219,7 +211,6 @@ static struct wmi_driver inspur_wmi_driver = {
},
.id_table = inspur_wmi_id_table,
.probe = inspur_wmi_probe,
- .remove = inspur_wmi_remove,
.no_singleton = true,
};
--
2.47.1
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH v2 14/18] platform/x86: thinkpad_acpi: Use devm_platform_profile_register()
2025-01-14 15:37 [PATCH v2 00/18] Hide platform_profile_handler from consumers Kurt Borja
` (12 preceding siblings ...)
2025-01-14 15:37 ` [PATCH v2 13/18] platform/x86: inspur_platform_profile: " Kurt Borja
@ 2025-01-14 15:37 ` Kurt Borja
2025-01-14 15:37 ` [PATCH v2 15/18] ACPI: platform_profile: Remove platform_profile_handler from exported symbols Kurt Borja
` (4 subsequent siblings)
18 siblings, 0 replies; 33+ messages in thread
From: Kurt Borja @ 2025-01-14 15:37 UTC (permalink / raw)
To: platform-driver-x86
Cc: Rafael J. Wysocki, Len Brown, linux-acpi, linux-kernel,
Mario Limonciello, Armin Wolf, Joshua Grisham, Derek J. Clark,
Ilpo Järvinen, Hans de Goede, Kurt Borja, Maximilian Luz,
Lee, Chun-Yi, Shyam Sundar S K, Corentin Chary, Luke D. Jones,
Lyndon Sanche, Ike Panhc, Henrique de Moraes Holschuh,
Mark Pearson, Alexis Belmonte, Ai Chao, Gergo Koteles,
Dell.Client.Kernel, ibm-acpi-devel
Replace platform_profile_register() with it's device managed version.
Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
Signed-off-by: Kurt Borja <kuurtb@gmail.com>
---
drivers/platform/x86/thinkpad_acpi.c | 8 +-------
1 file changed, 1 insertion(+), 7 deletions(-)
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
index 5c250867678f..54ff3e6b8b1a 100644
--- a/drivers/platform/x86/thinkpad_acpi.c
+++ b/drivers/platform/x86/thinkpad_acpi.c
@@ -10649,7 +10649,7 @@ static int tpacpi_dytc_profile_init(struct ibm_init_struct *iibm)
dytc_profile.dev = &tpacpi_pdev->dev;
/* Create platform_profile structure and register */
- err = platform_profile_register(&dytc_profile, NULL);
+ err = devm_platform_profile_register(&dytc_profile, NULL);
/*
* If for some reason platform_profiles aren't enabled
* don't quit terminally.
@@ -10667,14 +10667,8 @@ static int tpacpi_dytc_profile_init(struct ibm_init_struct *iibm)
return 0;
}
-static void dytc_profile_exit(void)
-{
- platform_profile_remove(&dytc_profile);
-}
-
static struct ibm_struct dytc_profile_driver_data = {
.name = "dytc-profile",
- .exit = dytc_profile_exit,
};
/*************************************************************************
--
2.47.1
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH v2 15/18] ACPI: platform_profile: Remove platform_profile_handler from exported symbols
2025-01-14 15:37 [PATCH v2 00/18] Hide platform_profile_handler from consumers Kurt Borja
` (13 preceding siblings ...)
2025-01-14 15:37 ` [PATCH v2 14/18] platform/x86: thinkpad_acpi: " Kurt Borja
@ 2025-01-14 15:37 ` Kurt Borja
2025-01-14 16:22 ` Mario Limonciello
2025-01-14 16:55 ` Ilpo Järvinen
2025-01-14 15:37 ` [PATCH v2 16/18] ACPI: platform_profile: Move platform_profile_handler Kurt Borja
` (3 subsequent siblings)
18 siblings, 2 replies; 33+ messages in thread
From: Kurt Borja @ 2025-01-14 15:37 UTC (permalink / raw)
To: platform-driver-x86
Cc: Rafael J. Wysocki, Len Brown, linux-acpi, linux-kernel,
Mario Limonciello, Armin Wolf, Joshua Grisham, Derek J. Clark,
Ilpo Järvinen, Hans de Goede, Kurt Borja, Maximilian Luz,
Lee, Chun-Yi, Shyam Sundar S K, Corentin Chary, Luke D. Jones,
Lyndon Sanche, Ike Panhc, Henrique de Moraes Holschuh,
Mark Pearson, Alexis Belmonte, Ai Chao, Gergo Koteles,
Dell.Client.Kernel, ibm-acpi-devel
In order to protect the platform_profile_handler from API consumers,
allocate it in platform_profile_register() and modify it's signature
accordingly.
Remove the platform_profile_handler from all consumer drivers and
replace them with a pointer to the class device, which is
now returned from platform_profile_register().
Replace *pprof with a pointer to the class device in the rest of
exported symbols.
Signed-off-by: Kurt Borja <kuurtb@gmail.com>
---
drivers/acpi/platform_profile.c | 87 ++++++++++++-------
.../surface/surface_platform_profile.c | 11 ++-
drivers/platform/x86/acer-wmi.c | 18 ++--
drivers/platform/x86/amd/pmf/pmf.h | 2 +-
drivers/platform/x86/amd/pmf/sps.c | 17 ++--
drivers/platform/x86/asus-wmi.c | 20 ++---
drivers/platform/x86/dell/alienware-wmi.c | 9 +-
drivers/platform/x86/dell/dell-pc.c | 22 ++---
drivers/platform/x86/hp/hp-wmi.c | 19 ++--
drivers/platform/x86/ideapad-laptop.c | 14 +--
.../platform/x86/inspur_platform_profile.c | 9 +-
drivers/platform/x86/thinkpad_acpi.c | 14 ++-
include/linux/platform_profile.h | 12 ++-
13 files changed, 125 insertions(+), 129 deletions(-)
diff --git a/drivers/acpi/platform_profile.c b/drivers/acpi/platform_profile.c
index 34e22b006ccc..2fae5e2fc962 100644
--- a/drivers/acpi/platform_profile.c
+++ b/drivers/acpi/platform_profile.c
@@ -4,6 +4,7 @@
#include <linux/acpi.h>
#include <linux/bits.h>
+#include <linux/cleanup.h>
#include <linux/init.h>
#include <linux/kdev_t.h>
#include <linux/mutex.h>
@@ -213,9 +214,17 @@ static struct attribute *profile_attrs[] = {
};
ATTRIBUTE_GROUPS(profile);
+static void pprof_device_release(struct device *dev)
+{
+ struct platform_profile_handler *pprof = to_pprof_handler(dev);
+
+ kfree(pprof);
+}
+
static const struct class platform_profile_class = {
.name = "platform-profile",
.dev_groups = profile_groups,
+ .dev_release = pprof_device_release,
};
/**
@@ -409,10 +418,10 @@ static const struct attribute_group platform_profile_group = {
.is_visible = profile_class_is_visible,
};
-void platform_profile_notify(struct platform_profile_handler *pprof)
+void platform_profile_notify(struct device *dev)
{
scoped_cond_guard(mutex_intr, return, &profile_lock) {
- _notify_class_profile(&pprof->class_dev, NULL);
+ _notify_class_profile(dev, NULL);
}
sysfs_notify(acpi_kobj, NULL, "platform_profile");
}
@@ -461,40 +470,51 @@ int platform_profile_cycle(void)
}
EXPORT_SYMBOL_GPL(platform_profile_cycle);
-int platform_profile_register(struct platform_profile_handler *pprof, void *drvdata)
+struct device *platform_profile_register(struct device *dev, const char *name,
+ void *drvdata,
+ const struct platform_profile_ops *ops)
{
+ int minor;
int err;
- /* Sanity check the profile handler */
- if (!pprof || !pprof->ops->profile_set || !pprof->ops->profile_get ||
- !pprof->ops->probe) {
+ /* Sanity check */
+ if (!dev || !name || !ops || !ops->profile_get ||
+ !ops->profile_set || !ops->probe) {
pr_err("platform_profile: handler is invalid\n");
- return -EINVAL;
+ return ERR_PTR(-EINVAL);
}
- err = pprof->ops->probe(drvdata, pprof->choices);
+ struct platform_profile_handler *pprof __free(kfree) = kzalloc(
+ sizeof(*pprof), GFP_KERNEL);
+ if (!pprof)
+ return ERR_PTR(-ENOMEM);
+
+ err = ops->probe(drvdata, pprof->choices);
if (err < 0)
- return err;
+ return ERR_PTR(err);
if (bitmap_empty(pprof->choices, PLATFORM_PROFILE_LAST)) {
pr_err("platform_profile: no available profiles\n");
- return -EINVAL;
+ return ERR_PTR(-EINVAL);
}
guard(mutex)(&profile_lock);
/* create class interface for individual handler */
- pprof->minor = ida_alloc(&platform_profile_ida, GFP_KERNEL);
- if (pprof->minor < 0)
- return pprof->minor;
+ minor = ida_alloc(&platform_profile_ida, GFP_KERNEL);
+ if (minor < 0)
+ return ERR_PTR(minor);
+ pprof->name = name;
+ pprof->ops = ops;
+ pprof->minor = minor;
pprof->class_dev.class = &platform_profile_class;
- pprof->class_dev.parent = pprof->dev;
+ pprof->class_dev.parent = dev;
dev_set_drvdata(&pprof->class_dev, drvdata);
dev_set_name(&pprof->class_dev, "platform-profile-%d", pprof->minor);
err = device_register(&pprof->class_dev);
if (err) {
- put_device(&pprof->class_dev);
+ put_device(&no_free_ptr(pprof)->class_dev);
goto cleanup_ida;
}
@@ -504,20 +524,21 @@ int platform_profile_register(struct platform_profile_handler *pprof, void *drvd
if (err)
goto cleanup_cur;
- return 0;
+ return &no_free_ptr(pprof)->class_dev;
cleanup_cur:
- device_unregister(&pprof->class_dev);
+ device_unregister(&no_free_ptr(pprof)->class_dev);
cleanup_ida:
- ida_free(&platform_profile_ida, pprof->minor);
+ ida_free(&platform_profile_ida, minor);
- return err;
+ return ERR_PTR(err);
}
EXPORT_SYMBOL_GPL(platform_profile_register);
-int platform_profile_remove(struct platform_profile_handler *pprof)
+int platform_profile_remove(struct device *dev)
{
+ struct platform_profile_handler *pprof = to_pprof_handler(dev);
int id;
guard(mutex)(&profile_lock);
@@ -535,30 +556,32 @@ EXPORT_SYMBOL_GPL(platform_profile_remove);
static void devm_platform_profile_release(struct device *dev, void *res)
{
- struct platform_profile_handler **pprof = res;
+ struct device **ppdev = res;
- platform_profile_remove(*pprof);
+ platform_profile_remove(*ppdev);
}
-int devm_platform_profile_register(struct platform_profile_handler *pprof, void *drvdata)
+struct device *devm_platform_profile_register(struct device *dev, const char *name,
+ void *drvdata,
+ const struct platform_profile_ops *ops)
{
- struct platform_profile_handler **dr;
- int ret;
+ struct device *ppdev;
+ struct device **dr;
dr = devres_alloc(devm_platform_profile_release, sizeof(*dr), GFP_KERNEL);
if (!dr)
- return -ENOMEM;
+ return ERR_PTR(-ENOMEM);
- ret = platform_profile_register(pprof, drvdata);
- if (ret) {
+ ppdev = platform_profile_register(dev, name, drvdata, ops);
+ if (IS_ERR(dev)) {
devres_free(dr);
- return ret;
+ return ppdev;
}
- *dr = pprof;
- devres_add(pprof->dev, dr);
+ *dr = ppdev;
+ devres_add(dev, dr);
- return 0;
+ return ppdev;
}
EXPORT_SYMBOL_GPL(devm_platform_profile_register);
diff --git a/drivers/platform/surface/surface_platform_profile.c b/drivers/platform/surface/surface_platform_profile.c
index bbdc873cb788..275269a6efc1 100644
--- a/drivers/platform/surface/surface_platform_profile.c
+++ b/drivers/platform/surface/surface_platform_profile.c
@@ -40,7 +40,7 @@ struct ssam_tmp_profile_info {
struct ssam_platform_profile_device {
struct ssam_device *sdev;
- struct platform_profile_handler handler;
+ struct device *ppdev;
bool has_fan;
};
@@ -228,13 +228,12 @@ static int surface_platform_profile_probe(struct ssam_device *sdev)
tpd->sdev = sdev;
ssam_device_set_drvdata(sdev, tpd);
- tpd->handler.name = "Surface Platform Profile";
- tpd->handler.dev = &sdev->dev;
- tpd->handler.ops = &ssam_platform_profile_ops;
-
tpd->has_fan = device_property_read_bool(&sdev->dev, "has_fan");
- return devm_platform_profile_register(&tpd->handler, tpd);
+ tpd->ppdev = devm_platform_profile_register(
+ &sdev->dev, "Surface Platform Profile", tpd, &ssam_platform_profile_ops);
+
+ return PTR_ERR_OR_ZERO(tpd->ppdev);
}
static const struct ssam_device_id ssam_platform_profile_match[] = {
diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c
index 39ec236b7cdb..3e39465b3783 100644
--- a/drivers/platform/x86/acer-wmi.c
+++ b/drivers/platform/x86/acer-wmi.c
@@ -758,7 +758,7 @@ static const struct dmi_system_id non_acer_quirks[] __initconst = {
{}
};
-static struct platform_profile_handler platform_profile_handler;
+static struct device *platform_profile_device;
static bool platform_profile_support;
/*
@@ -1937,16 +1937,10 @@ static const struct platform_profile_ops acer_predator_v4_platform_profile_ops =
static int acer_platform_profile_setup(struct platform_device *device)
{
if (quirks->predator_v4) {
- int err;
-
- platform_profile_handler.name = "acer-wmi";
- platform_profile_handler.dev = &device->dev;
- platform_profile_handler.ops =
- &acer_predator_v4_platform_profile_ops;
-
- err = devm_platform_profile_register(&platform_profile_handler, NULL);
- if (err)
- return err;
+ platform_profile_device = devm_platform_profile_register(
+ &device->dev, "acer-wmi", NULL, &acer_predator_v4_platform_profile_ops);
+ if (IS_ERR(platform_profile_device))
+ return PTR_ERR(platform_profile_device);
platform_profile_support = true;
@@ -2033,7 +2027,7 @@ static int acer_thermal_profile_change(void)
if (tp != ACER_PREDATOR_V4_THERMAL_PROFILE_TURBO_WMI)
last_non_turbo_profile = tp;
- platform_profile_notify(&platform_profile_handler);
+ platform_profile_notify(platform_profile_device);
}
return 0;
diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/x86/amd/pmf/pmf.h
index d99b3556205b..41b2b91b8fdc 100644
--- a/drivers/platform/x86/amd/pmf/pmf.h
+++ b/drivers/platform/x86/amd/pmf/pmf.h
@@ -338,7 +338,7 @@ struct amd_pmf_dev {
struct mutex lock; /* protects the PMF interface */
u32 supported_func;
enum platform_profile_option current_profile;
- struct platform_profile_handler pprof;
+ struct device *ppdev; /* platform profile class device */
struct dentry *dbgfs_dir;
int hb_interval; /* SBIOS heartbeat interval */
struct delayed_work heart_beat;
diff --git a/drivers/platform/x86/amd/pmf/sps.c b/drivers/platform/x86/amd/pmf/sps.c
index 7c7ed2b9de01..a96fc6887cf0 100644
--- a/drivers/platform/x86/amd/pmf/sps.c
+++ b/drivers/platform/x86/amd/pmf/sps.c
@@ -404,8 +404,6 @@ static const struct platform_profile_ops amd_pmf_profile_ops = {
int amd_pmf_init_sps(struct amd_pmf_dev *dev)
{
- int err;
-
dev->current_profile = PLATFORM_PROFILE_BALANCED;
if (is_apmf_func_supported(dev, APMF_FUNC_STATIC_SLIDER_GRANULAR)) {
@@ -420,15 +418,12 @@ int amd_pmf_init_sps(struct amd_pmf_dev *dev)
amd_pmf_set_sps_power_limits(dev);
}
- dev->pprof.name = "amd-pmf";
- dev->pprof.dev = dev->dev;
- dev->pprof.ops = &amd_pmf_profile_ops;
-
/* Create platform_profile structure and register */
- err = devm_platform_profile_register(&dev->pprof, dev);
- if (err)
- dev_err(dev->dev, "Failed to register SPS support, this is most likely an SBIOS bug: %d\n",
- err);
+ dev->ppdev = devm_platform_profile_register(
+ dev->dev, "amd-pmf", dev, &amd_pmf_profile_ops);
+ if (IS_ERR(dev->ppdev))
+ dev_err(dev->dev, "Failed to register SPS support, this is most likely an SBIOS bug: %ld\n",
+ PTR_ERR(dev->ppdev));
- return err;
+ return PTR_ERR_OR_ZERO(dev->ppdev);
}
diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
index f8437cff66df..4ad99cf9df1a 100644
--- a/drivers/platform/x86/asus-wmi.c
+++ b/drivers/platform/x86/asus-wmi.c
@@ -313,7 +313,7 @@ struct asus_wmi {
bool mid_fan_curve_available;
struct fan_curve_data custom_fan_curves[3];
- struct platform_profile_handler platform_profile_handler;
+ struct device *platform_profile_device;
bool platform_profile_support;
// The RSOC controls the maximum charging percentage.
@@ -3789,7 +3789,7 @@ static ssize_t throttle_thermal_policy_store(struct device *dev,
* Ensure that platform_profile updates userspace with the change to ensure
* that platform_profile and throttle_thermal_policy_mode are in sync.
*/
- platform_profile_notify(&asus->platform_profile_handler);
+ platform_profile_notify(asus->platform_profile_device);
return count;
}
@@ -3891,17 +3891,13 @@ static int platform_profile_setup(struct asus_wmi *asus)
dev_info(dev, "Using throttle_thermal_policy for platform_profile support\n");
- asus->platform_profile_handler.name = "asus-wmi";
- asus->platform_profile_handler.dev = dev;
- asus->platform_profile_handler.ops = &asus_wmi_platform_profile_ops;
+ asus->platform_profile_device = devm_platform_profile_register(
+ dev, "asus-wmi", asus, &asus_wmi_platform_profile_ops);
+ if (IS_ERR(asus->platform_profile_device)) {
+ pr_err("%s, failed at devm_platform_profile_register: %ld\n",
+ __func__, PTR_ERR(asus->platform_profile_device));
- err = devm_platform_profile_register(&asus->platform_profile_handler, asus);
- if (err == -EEXIST) {
- pr_warn("%s, a platform_profile handler is already registered\n", __func__);
- return 0;
- } else if (err) {
- pr_err("%s, failed at devm_platform_profile_register: %d\n", __func__, err);
- return err;
+ return PTR_ERR(asus->platform_profile_device);
}
asus->platform_profile_support = true;
diff --git a/drivers/platform/x86/dell/alienware-wmi.c b/drivers/platform/x86/dell/alienware-wmi.c
index 0146d2f93be6..99db93846a63 100644
--- a/drivers/platform/x86/dell/alienware-wmi.c
+++ b/drivers/platform/x86/dell/alienware-wmi.c
@@ -1135,11 +1135,12 @@ static const struct platform_profile_ops awcc_platform_profile_ops = {
static int create_thermal_profile(struct platform_device *platform_device)
{
- pp_handler.name = "alienware-wmi";
- pp_handler.dev = &platform_device->dev;
- pp_handler.ops = &awcc_platform_profile_ops;
+ struct device *ppdev;
- return devm_platform_profile_register(&pp_handler, NULL);
+ ppdev = devm_platform_profile_register(
+ &platform_device->dev, "alienware-wmi", NULL, &awcc_platform_profile_ops);
+
+ return PTR_ERR_OR_ZERO(ppdev);
}
/*
diff --git a/drivers/platform/x86/dell/dell-pc.c b/drivers/platform/x86/dell/dell-pc.c
index 2759bb608b1a..8d60e1b223de 100644
--- a/drivers/platform/x86/dell/dell-pc.c
+++ b/drivers/platform/x86/dell/dell-pc.c
@@ -109,8 +109,6 @@ MODULE_DEVICE_TABLE(dmi, dell_device_table);
#define DELL_ACC_SET_FIELD GENMASK(11, 8)
#define DELL_THERMAL_SUPPORTED GENMASK(3, 0)
-static struct platform_profile_handler *thermal_handler;
-
enum thermal_mode_bits {
DELL_BALANCED = BIT(0),
DELL_COOL_BOTTOM = BIT(1),
@@ -254,6 +252,7 @@ static const struct platform_profile_ops dell_pc_platform_profile_ops = {
static int thermal_init(void)
{
+ struct device *ppdev;
int ret;
/* If thermal commands are not supported, exit without error */
@@ -271,26 +270,17 @@ static int thermal_init(void)
if (IS_ERR(platform_device))
return PTR_ERR(platform_device);
- thermal_handler = devm_kzalloc(&platform_device->dev, sizeof(*thermal_handler), GFP_KERNEL);
- if (!thermal_handler) {
- ret = -ENOMEM;
- goto cleanup_platform_device;
- }
- thermal_handler->name = "dell-pc";
- thermal_handler->dev = &platform_device->dev;
- thermal_handler->ops = &dell_pc_platform_profile_ops;
-
/* Clean up if failed */
- ret = devm_platform_profile_register(thermal_handler, NULL);
- if (ret)
+ ppdev = devm_platform_profile_register(
+ &platform_device->dev, "dell-pc", NULL, &dell_pc_platform_profile_ops);
+ if (IS_ERR(ppdev)) {
+ ret = PTR_ERR(ppdev);
goto cleanup_thermal_handler;
+ }
return 0;
cleanup_thermal_handler:
- thermal_handler = NULL;
-
-cleanup_platform_device:
platform_device_unregister(platform_device);
return ret;
diff --git a/drivers/platform/x86/hp/hp-wmi.c b/drivers/platform/x86/hp/hp-wmi.c
index 1304dfc65aab..d1f9bd287986 100644
--- a/drivers/platform/x86/hp/hp-wmi.c
+++ b/drivers/platform/x86/hp/hp-wmi.c
@@ -273,7 +273,7 @@ static DEFINE_MUTEX(active_platform_profile_lock);
static struct input_dev *hp_wmi_input_dev;
static struct input_dev *camera_shutter_input_dev;
static struct platform_device *hp_wmi_platform_dev;
-static struct platform_profile_handler platform_profile_handler;
+static struct device *platform_profile_device;
static struct notifier_block platform_power_source_nb;
static enum platform_profile_option active_platform_profile;
static bool platform_profile_support;
@@ -1602,6 +1602,7 @@ static const struct platform_profile_ops hp_wmi_platform_profile_ops = {
static int thermal_profile_setup(struct platform_device *device)
{
+ const struct platform_profile_ops *ops;
int err, tp;
if (is_omen_thermal_profile()) {
@@ -1617,7 +1618,7 @@ static int thermal_profile_setup(struct platform_device *device)
if (err < 0)
return err;
- platform_profile_handler.ops = &platform_profile_omen_ops;
+ ops = &platform_profile_omen_ops;
} else if (is_victus_thermal_profile()) {
err = platform_profile_victus_get_ec(&active_platform_profile);
if (err < 0)
@@ -1631,7 +1632,7 @@ static int thermal_profile_setup(struct platform_device *device)
if (err < 0)
return err;
- platform_profile_handler.ops = &platform_profile_victus_ops;
+ ops = &platform_profile_victus_ops;
} else {
tp = thermal_profile_get();
@@ -1646,15 +1647,13 @@ static int thermal_profile_setup(struct platform_device *device)
if (err)
return err;
- platform_profile_handler.ops = &hp_wmi_platform_profile_ops;
+ ops = &hp_wmi_platform_profile_ops;
}
- platform_profile_handler.name = "hp-wmi";
- platform_profile_handler.dev = &device->dev;
-
- err = devm_platform_profile_register(&platform_profile_handler, NULL);
- if (err)
- return err;
+ platform_profile_device = devm_platform_profile_register(
+ &device->dev, "hp-wmi", NULL, ops);
+ if (IS_ERR(platform_profile_device))
+ return PTR_ERR(platform_profile_device);
platform_profile_support = true;
diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c
index 87c1e087770a..6065a7421a02 100644
--- a/drivers/platform/x86/ideapad-laptop.c
+++ b/drivers/platform/x86/ideapad-laptop.c
@@ -142,7 +142,7 @@ enum {
struct ideapad_dytc_priv {
enum platform_profile_option current_profile;
- struct platform_profile_handler pprof;
+ struct device *ppdev; /* platform profile device */
struct mutex mutex; /* protects the DYTC interface */
struct ideapad_private *priv;
};
@@ -1050,7 +1050,7 @@ static void dytc_profile_refresh(struct ideapad_private *priv)
if (profile != priv->dytc->current_profile) {
priv->dytc->current_profile = profile;
- platform_profile_notify(&priv->dytc->pprof);
+ platform_profile_notify(priv->dytc->ppdev);
}
}
@@ -1117,15 +1117,15 @@ static int ideapad_dytc_profile_init(struct ideapad_private *priv)
mutex_init(&priv->dytc->mutex);
- priv->dytc->pprof.name = "ideapad-laptop";
- priv->dytc->pprof.dev = &priv->platform_device->dev;
priv->dytc->priv = priv;
- priv->dytc->pprof.ops = &dytc_profile_ops;
/* Create platform_profile structure and register */
- err = devm_platform_profile_register(&priv->dytc->pprof, &priv->dytc);
- if (err)
+ priv->dytc->ppdev = devm_platform_profile_register(
+ &priv->platform_device->dev, "ideapad-laptop", &priv->dytc, &dytc_profile_ops);
+ if (IS_ERR(priv->dytc->ppdev)) {
+ err = PTR_ERR(priv->dytc->ppdev);
goto pp_reg_failed;
+ }
/* Ensure initial values are correct */
dytc_profile_refresh(priv);
diff --git a/drivers/platform/x86/inspur_platform_profile.c b/drivers/platform/x86/inspur_platform_profile.c
index e1631de6ad86..8b71c4242939 100644
--- a/drivers/platform/x86/inspur_platform_profile.c
+++ b/drivers/platform/x86/inspur_platform_profile.c
@@ -32,7 +32,7 @@ enum inspur_tmp_profile {
struct inspur_wmi_priv {
struct wmi_device *wdev;
- struct platform_profile_handler handler;
+ struct device *ppdev;
};
static int inspur_wmi_perform_query(struct wmi_device *wdev,
@@ -190,11 +190,10 @@ static int inspur_wmi_probe(struct wmi_device *wdev, const void *context)
priv->wdev = wdev;
dev_set_drvdata(&wdev->dev, priv);
- priv->handler.name = "inspur-wmi";
- priv->handler.dev = &wdev->dev;
- priv->handler.ops = &inspur_platform_profile_ops;
+ priv->ppdev = devm_platform_profile_register(
+ &wdev->dev, "inspur-wmi", priv, &inspur_platform_profile_ops);
- return devm_platform_profile_register(&priv->handler, priv);
+ return PTR_ERR_OR_ZERO(priv->ppdev);
}
static const struct wmi_device_id inspur_wmi_id_table[] = {
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
index 54ff3e6b8b1a..2a3dd0d149a1 100644
--- a/drivers/platform/x86/thinkpad_acpi.c
+++ b/drivers/platform/x86/thinkpad_acpi.c
@@ -962,6 +962,7 @@ static const struct proc_ops dispatch_proc_ops = {
static struct platform_device *tpacpi_pdev;
static struct platform_device *tpacpi_sensors_pdev;
static struct device *tpacpi_hwmon;
+static struct device *tpacpi_pprof;
static struct input_dev *tpacpi_inputdev;
static struct mutex tpacpi_inputdev_send_mutex;
static LIST_HEAD(tpacpi_all_drivers);
@@ -10553,11 +10554,6 @@ static const struct platform_profile_ops dytc_profile_ops = {
.profile_set = dytc_profile_set,
};
-static struct platform_profile_handler dytc_profile = {
- .name = "thinkpad-acpi",
- .ops = &dytc_profile_ops,
-};
-
static void dytc_profile_refresh(void)
{
enum platform_profile_option profile;
@@ -10586,7 +10582,7 @@ static void dytc_profile_refresh(void)
err = convert_dytc_to_profile(funcmode, perfmode, &profile);
if (!err && profile != dytc_current_profile) {
dytc_current_profile = profile;
- platform_profile_notify(&dytc_profile);
+ platform_profile_notify(tpacpi_pprof);
}
}
@@ -10647,14 +10643,14 @@ static int tpacpi_dytc_profile_init(struct ibm_init_struct *iibm)
dbg_printk(TPACPI_DBG_INIT,
"DYTC version %d: thermal mode available\n", dytc_version);
- dytc_profile.dev = &tpacpi_pdev->dev;
/* Create platform_profile structure and register */
- err = devm_platform_profile_register(&dytc_profile, NULL);
+ tpacpi_pprof = devm_platform_profile_register(
+ &tpacpi_pdev->dev, "thinkpad-acpi", NULL, &dytc_profile_ops);
/*
* If for some reason platform_profiles aren't enabled
* don't quit terminally.
*/
- if (err)
+ if (IS_ERR(tpacpi_pprof))
return -ENODEV;
/* Ensure initial values are correct */
diff --git a/include/linux/platform_profile.h b/include/linux/platform_profile.h
index 5ad1ab7b75e4..778d4c661c3c 100644
--- a/include/linux/platform_profile.h
+++ b/include/linux/platform_profile.h
@@ -45,10 +45,14 @@ struct platform_profile_handler {
const struct platform_profile_ops *ops;
};
-int platform_profile_register(struct platform_profile_handler *pprof, void *drvdata);
-int platform_profile_remove(struct platform_profile_handler *pprof);
-int devm_platform_profile_register(struct platform_profile_handler *pprof, void *drvdata);
+struct device *platform_profile_register(struct device *dev, const char *name,
+ void *drvdata,
+ const struct platform_profile_ops *ops);
+int platform_profile_remove(struct device *dev);
+struct device *devm_platform_profile_register(struct device *dev, const char *name,
+ void *drvdata,
+ const struct platform_profile_ops *ops);
int platform_profile_cycle(void);
-void platform_profile_notify(struct platform_profile_handler *pprof);
+void platform_profile_notify(struct device *dev);
#endif /*_PLATFORM_PROFILE_H_*/
--
2.47.1
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH v2 16/18] ACPI: platform_profile: Move platform_profile_handler
2025-01-14 15:37 [PATCH v2 00/18] Hide platform_profile_handler from consumers Kurt Borja
` (14 preceding siblings ...)
2025-01-14 15:37 ` [PATCH v2 15/18] ACPI: platform_profile: Remove platform_profile_handler from exported symbols Kurt Borja
@ 2025-01-14 15:37 ` Kurt Borja
2025-01-14 15:37 ` [PATCH v2 17/18] ACPI: platform_profile: Clean platform_profile_handler Kurt Borja
` (2 subsequent siblings)
18 siblings, 0 replies; 33+ messages in thread
From: Kurt Borja @ 2025-01-14 15:37 UTC (permalink / raw)
To: platform-driver-x86
Cc: Rafael J. Wysocki, Len Brown, linux-acpi, linux-kernel,
Mario Limonciello, Armin Wolf, Joshua Grisham, Derek J. Clark,
Ilpo Järvinen, Hans de Goede, Kurt Borja, Maximilian Luz,
Lee, Chun-Yi, Shyam Sundar S K, Corentin Chary, Luke D. Jones,
Lyndon Sanche, Ike Panhc, Henrique de Moraes Holschuh,
Mark Pearson, Alexis Belmonte, Ai Chao, Gergo Koteles,
Dell.Client.Kernel, ibm-acpi-devel
platform_profile_handler is now an internal structure. Move it to
platform_profile.c.
Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
Signed-off-by: Kurt Borja <kuurtb@gmail.com>
---
drivers/acpi/platform_profile.c | 9 +++++++++
include/linux/platform_profile.h | 11 -----------
2 files changed, 9 insertions(+), 11 deletions(-)
diff --git a/drivers/acpi/platform_profile.c b/drivers/acpi/platform_profile.c
index 2fae5e2fc962..f1749eb7b21b 100644
--- a/drivers/acpi/platform_profile.c
+++ b/drivers/acpi/platform_profile.c
@@ -15,6 +15,15 @@
static DEFINE_MUTEX(profile_lock);
+struct platform_profile_handler {
+ const char *name;
+ struct device *dev;
+ struct device class_dev;
+ int minor;
+ unsigned long choices[BITS_TO_LONGS(PLATFORM_PROFILE_LAST)];
+ const struct platform_profile_ops *ops;
+};
+
static const char * const profile_names[] = {
[PLATFORM_PROFILE_LOW_POWER] = "low-power",
[PLATFORM_PROFILE_COOL] = "cool",
diff --git a/include/linux/platform_profile.h b/include/linux/platform_profile.h
index 778d4c661c3c..eea1daf85616 100644
--- a/include/linux/platform_profile.h
+++ b/include/linux/platform_profile.h
@@ -28,23 +28,12 @@ enum platform_profile_option {
PLATFORM_PROFILE_LAST, /*must always be last */
};
-struct platform_profile_handler;
-
struct platform_profile_ops {
int (*probe)(void *drvdata, unsigned long *choices);
int (*profile_get)(struct device *dev, enum platform_profile_option *profile);
int (*profile_set)(struct device *dev, enum platform_profile_option profile);
};
-struct platform_profile_handler {
- const char *name;
- struct device *dev;
- struct device class_dev;
- int minor;
- unsigned long choices[BITS_TO_LONGS(PLATFORM_PROFILE_LAST)];
- const struct platform_profile_ops *ops;
-};
-
struct device *platform_profile_register(struct device *dev, const char *name,
void *drvdata,
const struct platform_profile_ops *ops);
--
2.47.1
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH v2 17/18] ACPI: platform_profile: Clean platform_profile_handler
2025-01-14 15:37 [PATCH v2 00/18] Hide platform_profile_handler from consumers Kurt Borja
` (15 preceding siblings ...)
2025-01-14 15:37 ` [PATCH v2 16/18] ACPI: platform_profile: Move platform_profile_handler Kurt Borja
@ 2025-01-14 15:37 ` Kurt Borja
2025-01-14 15:37 ` [PATCH v2 18/18] ACPI: platform_profile: Add documentation Kurt Borja
2025-01-14 17:15 ` [PATCH v2 00/18] Hide platform_profile_handler from consumers Rafael J. Wysocki
18 siblings, 0 replies; 33+ messages in thread
From: Kurt Borja @ 2025-01-14 15:37 UTC (permalink / raw)
To: platform-driver-x86
Cc: Rafael J. Wysocki, Len Brown, linux-acpi, linux-kernel,
Mario Limonciello, Armin Wolf, Joshua Grisham, Derek J. Clark,
Ilpo Järvinen, Hans de Goede, Kurt Borja, Maximilian Luz,
Lee, Chun-Yi, Shyam Sundar S K, Corentin Chary, Luke D. Jones,
Lyndon Sanche, Ike Panhc, Henrique de Moraes Holschuh,
Mark Pearson, Alexis Belmonte, Ai Chao, Gergo Koteles,
Dell.Client.Kernel, ibm-acpi-devel
Remove parent device *dev from platform_profile_handler, as it's no
longer accessed directly. Rename class_dev -> dev.
Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
Signed-off-by: Kurt Borja <kuurtb@gmail.com>
---
drivers/acpi/platform_profile.c | 27 +++++++++++++--------------
1 file changed, 13 insertions(+), 14 deletions(-)
diff --git a/drivers/acpi/platform_profile.c b/drivers/acpi/platform_profile.c
index f1749eb7b21b..c44989801f8e 100644
--- a/drivers/acpi/platform_profile.c
+++ b/drivers/acpi/platform_profile.c
@@ -11,14 +11,13 @@
#include <linux/platform_profile.h>
#include <linux/sysfs.h>
-#define to_pprof_handler(d) (container_of(d, struct platform_profile_handler, class_dev))
+#define to_pprof_handler(d) (container_of(d, struct platform_profile_handler, dev))
static DEFINE_MUTEX(profile_lock);
struct platform_profile_handler {
const char *name;
- struct device *dev;
- struct device class_dev;
+ struct device dev;
int minor;
unsigned long choices[BITS_TO_LONGS(PLATFORM_PROFILE_LAST)];
const struct platform_profile_ops *ops;
@@ -91,8 +90,8 @@ static int _notify_class_profile(struct device *dev, void *data)
struct platform_profile_handler *handler = to_pprof_handler(dev);
lockdep_assert_held(&profile_lock);
- sysfs_notify(&handler->class_dev.kobj, NULL, "profile");
- kobject_uevent(&handler->class_dev.kobj, KOBJ_CHANGE);
+ sysfs_notify(&handler->dev.kobj, NULL, "profile");
+ kobject_uevent(&handler->dev.kobj, KOBJ_CHANGE);
return 0;
}
@@ -517,13 +516,13 @@ struct device *platform_profile_register(struct device *dev, const char *name,
pprof->name = name;
pprof->ops = ops;
pprof->minor = minor;
- pprof->class_dev.class = &platform_profile_class;
- pprof->class_dev.parent = dev;
- dev_set_drvdata(&pprof->class_dev, drvdata);
- dev_set_name(&pprof->class_dev, "platform-profile-%d", pprof->minor);
- err = device_register(&pprof->class_dev);
+ pprof->dev.class = &platform_profile_class;
+ pprof->dev.parent = dev;
+ dev_set_drvdata(&pprof->dev, drvdata);
+ dev_set_name(&pprof->dev, "platform-profile-%d", pprof->minor);
+ err = device_register(&pprof->dev);
if (err) {
- put_device(&no_free_ptr(pprof)->class_dev);
+ put_device(&no_free_ptr(pprof)->dev);
goto cleanup_ida;
}
@@ -533,10 +532,10 @@ struct device *platform_profile_register(struct device *dev, const char *name,
if (err)
goto cleanup_cur;
- return &no_free_ptr(pprof)->class_dev;
+ return &no_free_ptr(pprof)->dev;
cleanup_cur:
- device_unregister(&no_free_ptr(pprof)->class_dev);
+ device_unregister(&no_free_ptr(pprof)->dev);
cleanup_ida:
ida_free(&platform_profile_ida, minor);
@@ -552,7 +551,7 @@ int platform_profile_remove(struct device *dev)
guard(mutex)(&profile_lock);
id = pprof->minor;
- device_unregister(&pprof->class_dev);
+ device_unregister(&pprof->dev);
ida_free(&platform_profile_ida, id);
sysfs_notify(acpi_kobj, NULL, "platform_profile");
--
2.47.1
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [PATCH v2 18/18] ACPI: platform_profile: Add documentation
2025-01-14 15:37 [PATCH v2 00/18] Hide platform_profile_handler from consumers Kurt Borja
` (16 preceding siblings ...)
2025-01-14 15:37 ` [PATCH v2 17/18] ACPI: platform_profile: Clean platform_profile_handler Kurt Borja
@ 2025-01-14 15:37 ` Kurt Borja
2025-01-14 16:24 ` Mario Limonciello
2025-01-14 16:57 ` Ilpo Järvinen
2025-01-14 17:15 ` [PATCH v2 00/18] Hide platform_profile_handler from consumers Rafael J. Wysocki
18 siblings, 2 replies; 33+ messages in thread
From: Kurt Borja @ 2025-01-14 15:37 UTC (permalink / raw)
To: platform-driver-x86
Cc: Rafael J. Wysocki, Len Brown, linux-acpi, linux-kernel,
Mario Limonciello, Armin Wolf, Joshua Grisham, Derek J. Clark,
Ilpo Järvinen, Hans de Goede, Kurt Borja, Maximilian Luz,
Lee, Chun-Yi, Shyam Sundar S K, Corentin Chary, Luke D. Jones,
Lyndon Sanche, Ike Panhc, Henrique de Moraes Holschuh,
Mark Pearson, Alexis Belmonte, Ai Chao, Gergo Koteles,
Dell.Client.Kernel, ibm-acpi-devel
Add kerneldoc and sysfs class documentation.
Signed-off-by: Kurt Borja <kuurtb@gmail.com>
---
.../ABI/testing/sysfs-class-platform-profile | 44 +++++++++++++++++++
drivers/acpi/platform_profile.c | 33 ++++++++++++++
include/linux/platform_profile.h | 24 ++++++++++
3 files changed, 101 insertions(+)
create mode 100644 Documentation/ABI/testing/sysfs-class-platform-profile
diff --git a/Documentation/ABI/testing/sysfs-class-platform-profile b/Documentation/ABI/testing/sysfs-class-platform-profile
new file mode 100644
index 000000000000..b5a3600080bc
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-class-platform-profile
@@ -0,0 +1,44 @@
+What: /sys/class/platform-profile/platform-profile-X/name
+Date: January 2025
+Description: Name of the class device given by the driver.
+
+ RO
+
+What: /sys/class/platform-profile/platform-profile-X/choices
+Date: January 2025
+Description: This file contains a space-separated list of profiles supported for this device.
+
+ Drivers must use the following standard profile-names:
+
+ ==================== ========================================
+ low-power Low power consumption
+ cool Cooler operation
+ quiet Quieter operation
+ balanced Balance between low power consumption
+ and performance
+ balanced-performance Balance between performance and low
+ power consumption with a slight bias
+ towards performance
+ performance High performance operation
+ custom Driver defined custom profile
+ ==================== ========================================
+
+ RO
+
+What: /sys/class/platform-profile/platform-profile-X/profile
+Date: January 2025
+Description: Reading this file gives the current selected profile for this
+ device. Writing this file with one of the strings from
+ platform_profile_choices changes the profile to the new value.
+
+ This file can be monitored for changes by polling for POLLPRI,
+ POLLPRI will be signaled on any changes, independent of those
+ changes coming from a userspace write; or coming from another
+ source such as e.g. a hotkey triggered profile change handled
+ either directly by the embedded-controller or fully handled
+ inside the kernel.
+
+ This file may also emit the string 'custom' to indicate
+ that the driver is using a driver defined custom profile.
+
+ RW
diff --git a/drivers/acpi/platform_profile.c b/drivers/acpi/platform_profile.c
index c44989801f8e..9caddac695b8 100644
--- a/drivers/acpi/platform_profile.c
+++ b/drivers/acpi/platform_profile.c
@@ -426,6 +426,10 @@ static const struct attribute_group platform_profile_group = {
.is_visible = profile_class_is_visible,
};
+/**
+ * platform_profile_notify - Notify class device and legacy sysfs interface
+ * @dev: The class device
+ */
void platform_profile_notify(struct device *dev)
{
scoped_cond_guard(mutex_intr, return, &profile_lock) {
@@ -435,6 +439,11 @@ void platform_profile_notify(struct device *dev)
}
EXPORT_SYMBOL_GPL(platform_profile_notify);
+/**
+ * platform_profile_cycle - Cycles profiles available on all registered class devices
+ *
+ * Return: 0 on success, -errno on failure
+ */
int platform_profile_cycle(void)
{
enum platform_profile_option next = PLATFORM_PROFILE_LAST;
@@ -478,6 +487,15 @@ int platform_profile_cycle(void)
}
EXPORT_SYMBOL_GPL(platform_profile_cycle);
+/**
+ * platform_profile_register - Creates and registers a platform profile class device
+ * @dev: Parent device
+ * @name: Name of the class device
+ * @drvdata: Driver data that will be attached to the class device
+ * @ops: Platform profile's mandatory operations
+ *
+ * Return: pointer to the new class device on success, ERR_PTR on failure
+ */
struct device *platform_profile_register(struct device *dev, const char *name,
void *drvdata,
const struct platform_profile_ops *ops)
@@ -544,6 +562,12 @@ struct device *platform_profile_register(struct device *dev, const char *name,
}
EXPORT_SYMBOL_GPL(platform_profile_register);
+/**
+ * platform_profile_remove - Unregisters a platform profile class device
+ * @dev: Class device
+ *
+ * Return: 0
+ */
int platform_profile_remove(struct device *dev)
{
struct platform_profile_handler *pprof = to_pprof_handler(dev);
@@ -569,6 +593,15 @@ static void devm_platform_profile_release(struct device *dev, void *res)
platform_profile_remove(*ppdev);
}
+/**
+ * devm_platform_profile_register - Device managed version of platform_profile_register
+ * @dev: Parent device
+ * @name: Name of the class device
+ * @drvdata: Driver data that will be attached to the class device
+ * @ops: Platform profile's mandatory operations
+ *
+ * Return: pointer to the new class device on success, ERR_PTR on failure
+ */
struct device *devm_platform_profile_register(struct device *dev, const char *name,
void *drvdata,
const struct platform_profile_ops *ops)
diff --git a/include/linux/platform_profile.h b/include/linux/platform_profile.h
index eea1daf85616..eb4dc85dc18c 100644
--- a/include/linux/platform_profile.h
+++ b/include/linux/platform_profile.h
@@ -28,6 +28,30 @@ enum platform_profile_option {
PLATFORM_PROFILE_LAST, /*must always be last */
};
+/**
+ * struct platform_profile_ops - platform profile operations
+ * @probe: Callback to setup choices available to the new class device.
+ * Parameters are:
+ * @drvdata: drvdata pointer passed to platform_profile_register.
+ * @choices: Empty choices bitmap which the driver has to manually
+ * setup, by using set_bit() in bits corresponding to
+ * platform_profile_option values. These values will only
+ * be enforced when a new profile is selected from
+ * user-space.
+ * @profile_get: Callback that will be called when showing the current platform
+ * profile.
+ * Parameters are:
+ * @dev: Class device.
+ * @profile: Pointer to the profile which will be read from
+ * user-space. Selected choices are not enforced when
+ * modifying this value.
+ * @profile_set: Callback that will be called when storing the new platform
+ * profile.
+ * Parameters are:
+ * @dev: Class device.
+ * @profile: New platform profile to be set. Guaranteed to be a
+ * value selected in the @probe callback.
+ */
struct platform_profile_ops {
int (*probe)(void *drvdata, unsigned long *choices);
int (*profile_get)(struct device *dev, enum platform_profile_option *profile);
--
2.47.1
^ permalink raw reply related [flat|nested] 33+ messages in thread
* Re: [PATCH v2 03/18] ACPI: platform_profile: Remove platform_profile_handler from callbacks
2025-01-14 15:37 ` [PATCH v2 03/18] ACPI: platform_profile: Remove platform_profile_handler from callbacks Kurt Borja
@ 2025-01-14 15:59 ` Mario Limonciello
0 siblings, 0 replies; 33+ messages in thread
From: Mario Limonciello @ 2025-01-14 15:59 UTC (permalink / raw)
To: Kurt Borja, platform-driver-x86
Cc: Rafael J. Wysocki, Len Brown, linux-acpi, linux-kernel,
Armin Wolf, Joshua Grisham, Derek J. Clark, Ilpo Järvinen,
Hans de Goede, Maximilian Luz, Lee, Chun-Yi, Shyam Sundar S K,
Corentin Chary, Luke D. Jones, Lyndon Sanche, Ike Panhc,
Henrique de Moraes Holschuh, Mark Pearson, Alexis Belmonte,
Ai Chao, Gergo Koteles, Dell.Client.Kernel, ibm-acpi-devel
On 1/14/2025 09:37, Kurt Borja wrote:
> Devices can now set drvdata to the class device, thus passing the
> platform_profile_handler to callbacks is unnecessary. Instead pass the
> class device.
>
> Signed-off-by: Kurt Borja <kuurtb@gmail.com>
Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
> ---
> drivers/acpi/platform_profile.c | 4 ++--
> .../platform/surface/surface_platform_profile.c | 8 ++++----
> drivers/platform/x86/acer-wmi.c | 4 ++--
> drivers/platform/x86/amd/pmf/sps.c | 8 ++++----
> drivers/platform/x86/asus-wmi.c | 8 ++++----
> drivers/platform/x86/dell/alienware-wmi.c | 4 ++--
> drivers/platform/x86/dell/dell-pc.c | 4 ++--
> drivers/platform/x86/hp/hp-wmi.c | 14 +++++++-------
> drivers/platform/x86/ideapad-laptop.c | 8 ++++----
> drivers/platform/x86/inspur_platform_profile.c | 8 ++++----
> drivers/platform/x86/thinkpad_acpi.c | 4 ++--
> include/linux/platform_profile.h | 6 ++----
> 12 files changed, 39 insertions(+), 41 deletions(-)
>
> diff --git a/drivers/acpi/platform_profile.c b/drivers/acpi/platform_profile.c
> index f8741201deea..66170fe436f0 100644
> --- a/drivers/acpi/platform_profile.c
> +++ b/drivers/acpi/platform_profile.c
> @@ -66,7 +66,7 @@ static int _store_class_profile(struct device *dev, void *data)
> if (!test_bit(*bit, handler->choices))
> return -EOPNOTSUPP;
>
> - return handler->profile_set(handler, *bit);
> + return handler->profile_set(dev, *bit);
> }
>
> /**
> @@ -103,7 +103,7 @@ static int get_class_profile(struct device *dev,
>
> lockdep_assert_held(&profile_lock);
> handler = to_pprof_handler(dev);
> - err = handler->profile_get(handler, &val);
> + err = handler->profile_get(dev, &val);
> if (err) {
> pr_err("Failed to get profile for handler %s\n", handler->name);
> return err;
> diff --git a/drivers/platform/surface/surface_platform_profile.c b/drivers/platform/surface/surface_platform_profile.c
> index edb9362003a4..26c1230e75df 100644
> --- a/drivers/platform/surface/surface_platform_profile.c
> +++ b/drivers/platform/surface/surface_platform_profile.c
> @@ -154,14 +154,14 @@ static int convert_profile_to_ssam_fan(struct ssam_device *sdev, enum platform_p
> }
> }
>
> -static int ssam_platform_profile_get(struct platform_profile_handler *pprof,
> +static int ssam_platform_profile_get(struct device *dev,
> enum platform_profile_option *profile)
> {
> struct ssam_platform_profile_device *tpd;
> enum ssam_tmp_profile tp;
> int status;
>
> - tpd = dev_get_drvdata(&pprof->class_dev);
> + tpd = dev_get_drvdata(dev);
>
> status = ssam_tmp_profile_get(tpd->sdev, &tp);
> if (status)
> @@ -175,13 +175,13 @@ static int ssam_platform_profile_get(struct platform_profile_handler *pprof,
> return 0;
> }
>
> -static int ssam_platform_profile_set(struct platform_profile_handler *pprof,
> +static int ssam_platform_profile_set(struct device *dev,
> enum platform_profile_option profile)
> {
> struct ssam_platform_profile_device *tpd;
> int tp;
>
> - tpd = dev_get_drvdata(&pprof->class_dev);
> + tpd = dev_get_drvdata(dev);
>
> tp = convert_profile_to_ssam_tmp(tpd->sdev, profile);
> if (tp < 0)
> diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c
> index 4594beb4b9d7..d609bd105db3 100644
> --- a/drivers/platform/x86/acer-wmi.c
> +++ b/drivers/platform/x86/acer-wmi.c
> @@ -1843,7 +1843,7 @@ static int acer_toggle_turbo(void)
> }
>
> static int
> -acer_predator_v4_platform_profile_get(struct platform_profile_handler *pprof,
> +acer_predator_v4_platform_profile_get(struct device *dev,
> enum platform_profile_option *profile)
> {
> u8 tp;
> @@ -1878,7 +1878,7 @@ acer_predator_v4_platform_profile_get(struct platform_profile_handler *pprof,
> }
>
> static int
> -acer_predator_v4_platform_profile_set(struct platform_profile_handler *pprof,
> +acer_predator_v4_platform_profile_set(struct device *dev,
> enum platform_profile_option profile)
> {
> int tp;
> diff --git a/drivers/platform/x86/amd/pmf/sps.c b/drivers/platform/x86/amd/pmf/sps.c
> index 259a598acd3e..cf2e51f67787 100644
> --- a/drivers/platform/x86/amd/pmf/sps.c
> +++ b/drivers/platform/x86/amd/pmf/sps.c
> @@ -282,10 +282,10 @@ bool is_pprof_balanced(struct amd_pmf_dev *pmf)
> return (pmf->current_profile == PLATFORM_PROFILE_BALANCED) ? true : false;
> }
>
> -static int amd_pmf_profile_get(struct platform_profile_handler *pprof,
> +static int amd_pmf_profile_get(struct device *dev,
> enum platform_profile_option *profile)
> {
> - struct amd_pmf_dev *pmf = dev_get_drvdata(&pprof->class_dev);
> + struct amd_pmf_dev *pmf = dev_get_drvdata(dev);
>
> *profile = pmf->current_profile;
> return 0;
> @@ -363,10 +363,10 @@ int amd_pmf_power_slider_update_event(struct amd_pmf_dev *dev)
> return 0;
> }
>
> -static int amd_pmf_profile_set(struct platform_profile_handler *pprof,
> +static int amd_pmf_profile_set(struct device *dev,
> enum platform_profile_option profile)
> {
> - struct amd_pmf_dev *pmf = dev_get_drvdata(&pprof->class_dev);
> + struct amd_pmf_dev *pmf = dev_get_drvdata(dev);
> int ret = 0;
>
> pmf->current_profile = profile;
> diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
> index 0c68635a0aa3..9bed170abb92 100644
> --- a/drivers/platform/x86/asus-wmi.c
> +++ b/drivers/platform/x86/asus-wmi.c
> @@ -3800,13 +3800,13 @@ static ssize_t throttle_thermal_policy_store(struct device *dev,
> static DEVICE_ATTR_RW(throttle_thermal_policy);
>
> /* Platform profile ***********************************************************/
> -static int asus_wmi_platform_profile_get(struct platform_profile_handler *pprof,
> +static int asus_wmi_platform_profile_get(struct device *dev,
> enum platform_profile_option *profile)
> {
> struct asus_wmi *asus;
> int tp;
>
> - asus = dev_get_drvdata(&pprof->class_dev);
> + asus = dev_get_drvdata(dev);
> tp = asus->throttle_thermal_policy_mode;
>
> switch (tp) {
> @@ -3826,13 +3826,13 @@ static int asus_wmi_platform_profile_get(struct platform_profile_handler *pprof,
> return 0;
> }
>
> -static int asus_wmi_platform_profile_set(struct platform_profile_handler *pprof,
> +static int asus_wmi_platform_profile_set(struct device *dev,
> enum platform_profile_option profile)
> {
> struct asus_wmi *asus;
> int tp;
>
> - asus = dev_get_drvdata(&pprof->class_dev);
> + asus = dev_get_drvdata(dev);
>
> switch (profile) {
> case PLATFORM_PROFILE_PERFORMANCE:
> diff --git a/drivers/platform/x86/dell/alienware-wmi.c b/drivers/platform/x86/dell/alienware-wmi.c
> index 28c39e25228e..b8131b803368 100644
> --- a/drivers/platform/x86/dell/alienware-wmi.c
> +++ b/drivers/platform/x86/dell/alienware-wmi.c
> @@ -1026,7 +1026,7 @@ static int wmax_game_shift_status(u8 operation, u32 *out_data)
> return 0;
> }
>
> -static int thermal_profile_get(struct platform_profile_handler *pprof,
> +static int thermal_profile_get(struct device *dev,
> enum platform_profile_option *profile)
> {
> u32 out_data;
> @@ -1052,7 +1052,7 @@ static int thermal_profile_get(struct platform_profile_handler *pprof,
> return 0;
> }
>
> -static int thermal_profile_set(struct platform_profile_handler *pprof,
> +static int thermal_profile_set(struct device *dev,
> enum platform_profile_option profile)
> {
> if (quirks->gmode) {
> diff --git a/drivers/platform/x86/dell/dell-pc.c b/drivers/platform/x86/dell/dell-pc.c
> index 1a0a721d706f..c86b05b5a1cb 100644
> --- a/drivers/platform/x86/dell/dell-pc.c
> +++ b/drivers/platform/x86/dell/dell-pc.c
> @@ -185,7 +185,7 @@ static int thermal_set_mode(enum thermal_mode_bits state)
> return dell_send_request(&buffer, CLASS_INFO, SELECT_THERMAL_MANAGEMENT);
> }
>
> -static int thermal_platform_profile_set(struct platform_profile_handler *pprof,
> +static int thermal_platform_profile_set(struct device *dev,
> enum platform_profile_option profile)
> {
> switch (profile) {
> @@ -202,7 +202,7 @@ static int thermal_platform_profile_set(struct platform_profile_handler *pprof,
> }
> }
>
> -static int thermal_platform_profile_get(struct platform_profile_handler *pprof,
> +static int thermal_platform_profile_get(struct device *dev,
> enum platform_profile_option *profile)
> {
> int ret;
> diff --git a/drivers/platform/x86/hp/hp-wmi.c b/drivers/platform/x86/hp/hp-wmi.c
> index 8e5e1422e024..b8e62dc9cecd 100644
> --- a/drivers/platform/x86/hp/hp-wmi.c
> +++ b/drivers/platform/x86/hp/hp-wmi.c
> @@ -1221,7 +1221,7 @@ static int platform_profile_omen_get_ec(enum platform_profile_option *profile)
> return 0;
> }
>
> -static int platform_profile_omen_get(struct platform_profile_handler *pprof,
> +static int platform_profile_omen_get(struct device *dev,
> enum platform_profile_option *profile)
> {
> /*
> @@ -1318,7 +1318,7 @@ static int platform_profile_omen_set_ec(enum platform_profile_option profile)
> return 0;
> }
>
> -static int platform_profile_omen_set(struct platform_profile_handler *pprof,
> +static int platform_profile_omen_set(struct device *dev,
> enum platform_profile_option profile)
> {
> int err;
> @@ -1345,7 +1345,7 @@ static int thermal_profile_set(int thermal_profile)
> sizeof(thermal_profile), 0);
> }
>
> -static int hp_wmi_platform_profile_get(struct platform_profile_handler *pprof,
> +static int hp_wmi_platform_profile_get(struct device *dev,
> enum platform_profile_option *profile)
> {
> int tp;
> @@ -1374,7 +1374,7 @@ static int hp_wmi_platform_profile_get(struct platform_profile_handler *pprof,
> return 0;
> }
>
> -static int hp_wmi_platform_profile_set(struct platform_profile_handler *pprof,
> +static int hp_wmi_platform_profile_set(struct device *dev,
> enum platform_profile_option profile)
> {
> int err, tp;
> @@ -1440,11 +1440,11 @@ static int platform_profile_victus_get_ec(enum platform_profile_option *profile)
> return 0;
> }
>
> -static int platform_profile_victus_get(struct platform_profile_handler *pprof,
> +static int platform_profile_victus_get(struct device *dev,
> enum platform_profile_option *profile)
> {
> /* Same behaviour as platform_profile_omen_get */
> - return platform_profile_omen_get(pprof, profile);
> + return platform_profile_omen_get(dev, profile);
> }
>
> static int platform_profile_victus_set_ec(enum platform_profile_option profile)
> @@ -1472,7 +1472,7 @@ static int platform_profile_victus_set_ec(enum platform_profile_option profile)
> return 0;
> }
>
> -static int platform_profile_victus_set(struct platform_profile_handler *pprof,
> +static int platform_profile_victus_set(struct device *dev,
> enum platform_profile_option profile)
> {
> int err;
> diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c
> index ed0d880a07a9..fc317f42bb82 100644
> --- a/drivers/platform/x86/ideapad-laptop.c
> +++ b/drivers/platform/x86/ideapad-laptop.c
> @@ -933,10 +933,10 @@ static int convert_profile_to_dytc(enum platform_profile_option profile, int *pe
> * dytc_profile_get: Function to register with platform_profile
> * handler. Returns current platform profile.
> */
> -static int dytc_profile_get(struct platform_profile_handler *pprof,
> +static int dytc_profile_get(struct device *dev,
> enum platform_profile_option *profile)
> {
> - struct ideapad_dytc_priv *dytc = dev_get_drvdata(&pprof->class_dev);
> + struct ideapad_dytc_priv *dytc = dev_get_drvdata(dev);
>
> *profile = dytc->current_profile;
> return 0;
> @@ -986,10 +986,10 @@ static int dytc_cql_command(struct ideapad_private *priv, unsigned long cmd,
> * dytc_profile_set: Function to register with platform_profile
> * handler. Sets current platform profile.
> */
> -static int dytc_profile_set(struct platform_profile_handler *pprof,
> +static int dytc_profile_set(struct device *dev,
> enum platform_profile_option profile)
> {
> - struct ideapad_dytc_priv *dytc = dev_get_drvdata(&pprof->class_dev);
> + struct ideapad_dytc_priv *dytc = dev_get_drvdata(dev);
> struct ideapad_private *priv = dytc->priv;
> unsigned long output;
> int err;
> diff --git a/drivers/platform/x86/inspur_platform_profile.c b/drivers/platform/x86/inspur_platform_profile.c
> index 471fca50d1c9..47d2dbbf3392 100644
> --- a/drivers/platform/x86/inspur_platform_profile.c
> +++ b/drivers/platform/x86/inspur_platform_profile.c
> @@ -84,10 +84,10 @@ static int inspur_wmi_perform_query(struct wmi_device *wdev,
> * 0x0: No Error
> * 0x1: Error
> */
> -static int inspur_platform_profile_set(struct platform_profile_handler *pprof,
> +static int inspur_platform_profile_set(struct device *dev,
> enum platform_profile_option profile)
> {
> - struct inspur_wmi_priv *priv = dev_get_drvdata(&pprof->class_dev);
> + struct inspur_wmi_priv *priv = dev_get_drvdata(dev);
> u8 ret_code[4] = {0, 0, 0, 0};
> int ret;
>
> @@ -131,10 +131,10 @@ static int inspur_platform_profile_set(struct platform_profile_handler *pprof,
> * 0x1: Performance Mode
> * 0x2: Power Saver Mode
> */
> -static int inspur_platform_profile_get(struct platform_profile_handler *pprof,
> +static int inspur_platform_profile_get(struct device *dev,
> enum platform_profile_option *profile)
> {
> - struct inspur_wmi_priv *priv = dev_get_drvdata(&pprof->class_dev);
> + struct inspur_wmi_priv *priv = dev_get_drvdata(dev);
> u8 ret_code[4] = {0, 0, 0, 0};
> int ret;
>
> diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
> index fe37c26891d8..47f87bb213a9 100644
> --- a/drivers/platform/x86/thinkpad_acpi.c
> +++ b/drivers/platform/x86/thinkpad_acpi.c
> @@ -10414,7 +10414,7 @@ static int convert_profile_to_dytc(enum platform_profile_option profile, int *pe
> * dytc_profile_get: Function to register with platform_profile
> * handler. Returns current platform profile.
> */
> -static int dytc_profile_get(struct platform_profile_handler *pprof,
> +static int dytc_profile_get(struct device *dev,
> enum platform_profile_option *profile)
> {
> *profile = dytc_current_profile;
> @@ -10489,7 +10489,7 @@ static int dytc_cql_command(int command, int *output)
> * dytc_profile_set: Function to register with platform_profile
> * handler. Sets current platform profile.
> */
> -static int dytc_profile_set(struct platform_profile_handler *pprof,
> +static int dytc_profile_set(struct device *dev,
> enum platform_profile_option profile)
> {
> int perfmode;
> diff --git a/include/linux/platform_profile.h b/include/linux/platform_profile.h
> index 1c8fdda51eaa..5296d886c243 100644
> --- a/include/linux/platform_profile.h
> +++ b/include/linux/platform_profile.h
> @@ -34,10 +34,8 @@ struct platform_profile_handler {
> struct device class_dev;
> int minor;
> unsigned long choices[BITS_TO_LONGS(PLATFORM_PROFILE_LAST)];
> - int (*profile_get)(struct platform_profile_handler *pprof,
> - enum platform_profile_option *profile);
> - int (*profile_set)(struct platform_profile_handler *pprof,
> - enum platform_profile_option profile);
> + int (*profile_get)(struct device *dev, enum platform_profile_option *profile);
> + int (*profile_set)(struct device *dev, enum platform_profile_option profile);
> };
>
> int platform_profile_register(struct platform_profile_handler *pprof, void *drvdata);
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH v2 05/18] ACPI: platform_profile: Add `probe` to platform_profile_ops
2025-01-14 15:37 ` [PATCH v2 05/18] ACPI: platform_profile: Add `probe` to platform_profile_ops Kurt Borja
@ 2025-01-14 16:20 ` Mario Limonciello
2025-01-14 16:31 ` Kurt Borja
0 siblings, 1 reply; 33+ messages in thread
From: Mario Limonciello @ 2025-01-14 16:20 UTC (permalink / raw)
To: Kurt Borja, platform-driver-x86
Cc: Rafael J. Wysocki, Len Brown, linux-acpi, linux-kernel,
Armin Wolf, Joshua Grisham, Derek J. Clark, Ilpo Järvinen,
Hans de Goede, Maximilian Luz, Lee, Chun-Yi, Shyam Sundar S K,
Corentin Chary, Luke D. Jones, Lyndon Sanche, Ike Panhc,
Henrique de Moraes Holschuh, Mark Pearson, Alexis Belmonte,
Ai Chao, Gergo Koteles, Dell.Client.Kernel, ibm-acpi-devel
On 1/14/2025 09:37, Kurt Borja wrote:
> Add a `probe` callback to platform_profile_ops, which lets drivers
> initialize the choices member manually.
>
> Signed-off-by: Kurt Borja <kuurtb@gmail.com>
> ---
> drivers/acpi/platform_profile.c | 13 +++++++--
> .../surface/surface_platform_profile.c | 16 ++++++----
> drivers/platform/x86/acer-wmi.c | 24 ++++++++-------
> drivers/platform/x86/amd/pmf/sps.c | 15 ++++++----
> drivers/platform/x86/asus-wmi.c | 16 ++++++----
> drivers/platform/x86/dell/alienware-wmi.c | 24 +++++++++------
> drivers/platform/x86/dell/dell-pc.c | 26 ++++++++++-------
> drivers/platform/x86/hp/hp-wmi.c | 29 +++++++++++++------
> drivers/platform/x86/ideapad-laptop.c | 15 ++++++----
> .../platform/x86/inspur_platform_profile.c | 14 ++++++---
> drivers/platform/x86/thinkpad_acpi.c | 15 ++++++----
> include/linux/platform_profile.h | 1 +
> 12 files changed, 137 insertions(+), 71 deletions(-)
>
> diff --git a/drivers/acpi/platform_profile.c b/drivers/acpi/platform_profile.c
> index 440654e21620..34e22b006ccc 100644
> --- a/drivers/acpi/platform_profile.c
> +++ b/drivers/acpi/platform_profile.c
> @@ -466,12 +466,21 @@ int platform_profile_register(struct platform_profile_handler *pprof, void *drvd
> int err;
>
> /* Sanity check the profile handler */
> - if (!pprof || bitmap_empty(pprof->choices, PLATFORM_PROFILE_LAST) ||
> - !pprof->ops->profile_set || !pprof->ops->profile_get) {
> + if (!pprof || !pprof->ops->profile_set || !pprof->ops->profile_get ||
> + !pprof->ops->probe) {
> pr_err("platform_profile: handler is invalid\n");
> return -EINVAL;
> }
>
> + err = pprof->ops->probe(drvdata, pprof->choices);
> + if (err < 0)
Any particular reason to specifically look for less than zero? Did you
want to have the probe() return something positive in some circumstances?
If not I think this should be fine:
if (err)
> + return err;
> +
> + if (bitmap_empty(pprof->choices, PLATFORM_PROFILE_LAST)) {
> + pr_err("platform_profile: no available profiles\n");
Doesn't pr_fmt handle the prefix?
> + return -EINVAL;
> + }
> +
> guard(mutex)(&profile_lock);
>
> /* create class interface for individual handler */
> diff --git a/drivers/platform/surface/surface_platform_profile.c b/drivers/platform/surface/surface_platform_profile.c
> index 76967bfeeef8..48cfe9cb89c8 100644
> --- a/drivers/platform/surface/surface_platform_profile.c
> +++ b/drivers/platform/surface/surface_platform_profile.c
> @@ -201,7 +201,18 @@ static int ssam_platform_profile_set(struct device *dev,
> return tp;
> }
>
> +static int ssam_platform_profile_probe(void *drvdata, unsigned long *choices)
> +{
> + set_bit(PLATFORM_PROFILE_LOW_POWER, choices);
> + set_bit(PLATFORM_PROFILE_BALANCED, choices);
> + set_bit(PLATFORM_PROFILE_BALANCED_PERFORMANCE, choices);
> + set_bit(PLATFORM_PROFILE_PERFORMANCE, choices);
> +
> + return 0;
> +}
> +
> static const struct platform_profile_ops ssam_platform_profile_ops = {
> + .probe = ssam_platform_profile_probe,
> .profile_get = ssam_platform_profile_get,
> .profile_set = ssam_platform_profile_set,
> };
> @@ -223,11 +234,6 @@ static int surface_platform_profile_probe(struct ssam_device *sdev)
>
> tpd->has_fan = device_property_read_bool(&sdev->dev, "has_fan");
>
> - set_bit(PLATFORM_PROFILE_LOW_POWER, tpd->handler.choices);
> - set_bit(PLATFORM_PROFILE_BALANCED, tpd->handler.choices);
> - set_bit(PLATFORM_PROFILE_BALANCED_PERFORMANCE, tpd->handler.choices);
> - set_bit(PLATFORM_PROFILE_PERFORMANCE, tpd->handler.choices);
> -
> return platform_profile_register(&tpd->handler, tpd);
> }
>
> diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c
> index 91ae48adf6cf..6953e36dbfde 100644
> --- a/drivers/platform/x86/acer-wmi.c
> +++ b/drivers/platform/x86/acer-wmi.c
> @@ -1916,7 +1916,20 @@ acer_predator_v4_platform_profile_set(struct device *dev,
> return 0;
> }
>
> +static int
> +acer_predator_v4_platform_profile_probe(void *drvdata, unsigned long *choices)
> +{
> + set_bit(PLATFORM_PROFILE_PERFORMANCE, choices);
> + set_bit(PLATFORM_PROFILE_BALANCED_PERFORMANCE, choices);
> + set_bit(PLATFORM_PROFILE_BALANCED, choices);
> + set_bit(PLATFORM_PROFILE_QUIET, choices);
> + set_bit(PLATFORM_PROFILE_LOW_POWER, choices);
> +
> + return 0;
> +}
> +
> static const struct platform_profile_ops acer_predator_v4_platform_profile_ops = {
> + .probe = acer_predator_v4_platform_profile_probe,
> .profile_get = acer_predator_v4_platform_profile_get,
> .profile_set = acer_predator_v4_platform_profile_set,
> };
> @@ -1931,17 +1944,6 @@ static int acer_platform_profile_setup(struct platform_device *device)
> platform_profile_handler.ops =
> &acer_predator_v4_platform_profile_ops;
>
> - set_bit(PLATFORM_PROFILE_PERFORMANCE,
> - platform_profile_handler.choices);
> - set_bit(PLATFORM_PROFILE_BALANCED_PERFORMANCE,
> - platform_profile_handler.choices);
> - set_bit(PLATFORM_PROFILE_BALANCED,
> - platform_profile_handler.choices);
> - set_bit(PLATFORM_PROFILE_QUIET,
> - platform_profile_handler.choices);
> - set_bit(PLATFORM_PROFILE_LOW_POWER,
> - platform_profile_handler.choices);
> -
> err = platform_profile_register(&platform_profile_handler, NULL);
> if (err)
> return err;
> diff --git a/drivers/platform/x86/amd/pmf/sps.c b/drivers/platform/x86/amd/pmf/sps.c
> index 6ae82ae86d22..e710405b581f 100644
> --- a/drivers/platform/x86/amd/pmf/sps.c
> +++ b/drivers/platform/x86/amd/pmf/sps.c
> @@ -387,7 +387,17 @@ static int amd_pmf_profile_set(struct device *dev,
> return 0;
> }
>
> +static int amd_pmf_profile_probe(void *drvdata, unsigned long *choices)
> +{
> + set_bit(PLATFORM_PROFILE_LOW_POWER, choices);
> + set_bit(PLATFORM_PROFILE_BALANCED, choices);
> + set_bit(PLATFORM_PROFILE_PERFORMANCE, choices);
> +
> + return 0;
> +}
> +
> static const struct platform_profile_ops amd_pmf_profile_ops = {
> + .probe = amd_pmf_profile_probe,
> .profile_get = amd_pmf_profile_get,
> .profile_set = amd_pmf_profile_set,
> };
> @@ -414,11 +424,6 @@ int amd_pmf_init_sps(struct amd_pmf_dev *dev)
> dev->pprof.dev = dev->dev;
> dev->pprof.ops = &amd_pmf_profile_ops;
>
> - /* Setup supported modes */
> - set_bit(PLATFORM_PROFILE_LOW_POWER, dev->pprof.choices);
> - set_bit(PLATFORM_PROFILE_BALANCED, dev->pprof.choices);
> - set_bit(PLATFORM_PROFILE_PERFORMANCE, dev->pprof.choices);
> -
> /* Create platform_profile structure and register */
> err = platform_profile_register(&dev->pprof, dev);
> if (err)
> diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
> index d88860dd028b..3d77f7454953 100644
> --- a/drivers/platform/x86/asus-wmi.c
> +++ b/drivers/platform/x86/asus-wmi.c
> @@ -3852,7 +3852,17 @@ static int asus_wmi_platform_profile_set(struct device *dev,
> return throttle_thermal_policy_write(asus);
> }
>
> +static int asus_wmi_platform_profile_probe(void *drvdata, unsigned long *choices)
> +{
> + set_bit(PLATFORM_PROFILE_QUIET, choices);
> + set_bit(PLATFORM_PROFILE_BALANCED, choices);
> + set_bit(PLATFORM_PROFILE_PERFORMANCE, choices);
> +
> + return 0;
> +}
> +
> static const struct platform_profile_ops asus_wmi_platform_profile_ops = {
> + .probe = asus_wmi_platform_profile_probe,
> .profile_get = asus_wmi_platform_profile_get,
> .profile_set = asus_wmi_platform_profile_set,
> };
> @@ -3885,12 +3895,6 @@ static int platform_profile_setup(struct asus_wmi *asus)
> asus->platform_profile_handler.dev = dev;
> asus->platform_profile_handler.ops = &asus_wmi_platform_profile_ops;
>
> - set_bit(PLATFORM_PROFILE_QUIET, asus->platform_profile_handler.choices);
> - set_bit(PLATFORM_PROFILE_BALANCED,
> - asus->platform_profile_handler.choices);
> - set_bit(PLATFORM_PROFILE_PERFORMANCE,
> - asus->platform_profile_handler.choices);
> -
> err = platform_profile_register(&asus->platform_profile_handler, asus);
> if (err == -EEXIST) {
> pr_warn("%s, a platform_profile handler is already registered\n", __func__);
> diff --git a/drivers/platform/x86/dell/alienware-wmi.c b/drivers/platform/x86/dell/alienware-wmi.c
> index f7a854d40575..0146d2f93be6 100644
> --- a/drivers/platform/x86/dell/alienware-wmi.c
> +++ b/drivers/platform/x86/dell/alienware-wmi.c
> @@ -1078,12 +1078,7 @@ static int thermal_profile_set(struct device *dev,
> return wmax_thermal_control(supported_thermal_profiles[profile]);
> }
>
> -static const struct platform_profile_ops awcc_platform_profile_ops = {
> - .profile_get = thermal_profile_get,
> - .profile_set = thermal_profile_set,
> -};
> -
> -static int create_thermal_profile(struct platform_device *platform_device)
> +static int thermal_profile_probe(void *drvdata, unsigned long *choices)
> {
> enum platform_profile_option profile;
> enum wmax_thermal_mode mode;
> @@ -1116,19 +1111,30 @@ static int create_thermal_profile(struct platform_device *platform_device)
> profile = wmax_mode_to_platform_profile[mode];
> supported_thermal_profiles[profile] = out_data;
>
> - set_bit(profile, pp_handler.choices);
> + set_bit(profile, choices);
> }
>
> - if (bitmap_empty(pp_handler.choices, PLATFORM_PROFILE_LAST))
> + if (bitmap_empty(choices, PLATFORM_PROFILE_LAST))
> return -ENODEV;
>
> if (quirks->gmode) {
> supported_thermal_profiles[PLATFORM_PROFILE_PERFORMANCE] =
> WMAX_THERMAL_MODE_GMODE;
>
> - set_bit(PLATFORM_PROFILE_PERFORMANCE, pp_handler.choices);
> + set_bit(PLATFORM_PROFILE_PERFORMANCE, choices);
> }
>
> + return 0;
> +}
> +
> +static const struct platform_profile_ops awcc_platform_profile_ops = {
> + .probe = thermal_profile_probe,
> + .profile_get = thermal_profile_get,
> + .profile_set = thermal_profile_set,
> +};
> +
> +static int create_thermal_profile(struct platform_device *platform_device)
> +{
> pp_handler.name = "alienware-wmi";
> pp_handler.dev = &platform_device->dev;
> pp_handler.ops = &awcc_platform_profile_ops;
> diff --git a/drivers/platform/x86/dell/dell-pc.c b/drivers/platform/x86/dell/dell-pc.c
> index 9010a231f209..32b3be0723f8 100644
> --- a/drivers/platform/x86/dell/dell-pc.c
> +++ b/drivers/platform/x86/dell/dell-pc.c
> @@ -24,6 +24,7 @@
> #include "dell-smbios.h"
>
> static struct platform_device *platform_device;
> +static int supported_modes;
>
> static const struct dmi_system_id dell_device_table[] __initconst = {
> {
> @@ -231,7 +232,22 @@ static int thermal_platform_profile_get(struct device *dev,
> return 0;
> }
>
> +static int thermal_platform_profile_probe(void *drvdata, unsigned long *choices)
> +{
> + if (supported_modes & DELL_QUIET)
> + set_bit(PLATFORM_PROFILE_QUIET, choices);
> + if (supported_modes & DELL_COOL_BOTTOM)
> + set_bit(PLATFORM_PROFILE_COOL, choices);
> + if (supported_modes & DELL_BALANCED)
> + set_bit(PLATFORM_PROFILE_BALANCED, choices);
> + if (supported_modes & DELL_PERFORMANCE)
> + set_bit(PLATFORM_PROFILE_PERFORMANCE, choices);
> +
> + return 0;
> +}
> +
> static const struct platform_profile_ops dell_pc_platform_profile_ops = {
> + .probe = thermal_platform_profile_probe,
> .profile_get = thermal_platform_profile_get,
> .profile_set = thermal_platform_profile_set,
> };
> @@ -239,7 +255,6 @@ static const struct platform_profile_ops dell_pc_platform_profile_ops = {
> static int thermal_init(void)
> {
> int ret;
> - int supported_modes;
>
> /* If thermal commands are not supported, exit without error */
> if (!dell_smbios_class_is_supported(CLASS_INFO))
> @@ -265,15 +280,6 @@ static int thermal_init(void)
> thermal_handler->dev = &platform_device->dev;
> thermal_handler->ops = &dell_pc_platform_profile_ops;
>
> - if (supported_modes & DELL_QUIET)
> - set_bit(PLATFORM_PROFILE_QUIET, thermal_handler->choices);
> - if (supported_modes & DELL_COOL_BOTTOM)
> - set_bit(PLATFORM_PROFILE_COOL, thermal_handler->choices);
> - if (supported_modes & DELL_BALANCED)
> - set_bit(PLATFORM_PROFILE_BALANCED, thermal_handler->choices);
> - if (supported_modes & DELL_PERFORMANCE)
> - set_bit(PLATFORM_PROFILE_PERFORMANCE, thermal_handler->choices);
> -
> /* Clean up if failed */
> ret = platform_profile_register(thermal_handler, NULL);
> if (ret)
> diff --git a/drivers/platform/x86/hp/hp-wmi.c b/drivers/platform/x86/hp/hp-wmi.c
> index 60328b35be74..75bcd8460e7c 100644
> --- a/drivers/platform/x86/hp/hp-wmi.c
> +++ b/drivers/platform/x86/hp/hp-wmi.c
> @@ -1488,6 +1488,23 @@ static int platform_profile_victus_set(struct device *dev,
> return 0;
> }
>
> +static int hp_wmi_platform_profile_probe(void *drvdata, unsigned long *choices)
> +{
> + if (is_omen_thermal_profile()) {
> + set_bit(PLATFORM_PROFILE_COOL, choices);
> + } else if (is_victus_thermal_profile()) {
> + set_bit(PLATFORM_PROFILE_QUIET, choices);
> + } else {
> + set_bit(PLATFORM_PROFILE_QUIET, choices);
> + set_bit(PLATFORM_PROFILE_COOL, choices);
> + }
> +
> + set_bit(PLATFORM_PROFILE_BALANCED, choices);
> + set_bit(PLATFORM_PROFILE_PERFORMANCE, choices);
> +
> + return 0;
> +}
> +
> static int omen_powersource_event(struct notifier_block *nb,
> unsigned long value,
> void *data)
> @@ -1566,16 +1583,19 @@ static inline void omen_unregister_powersource_event_handler(void)
> }
>
> static const struct platform_profile_ops platform_profile_omen_ops = {
> + .probe = hp_wmi_platform_profile_probe,
> .profile_get = platform_profile_omen_get,
> .profile_set = platform_profile_omen_set,
> };
>
> static const struct platform_profile_ops platform_profile_victus_ops = {
> + .probe = hp_wmi_platform_profile_probe,
> .profile_get = platform_profile_victus_get,
> .profile_set = platform_profile_victus_set,
> };
>
> static const struct platform_profile_ops hp_wmi_platform_profile_ops = {
> + .probe = hp_wmi_platform_profile_probe,
> .profile_get = hp_wmi_platform_profile_get,
> .profile_set = hp_wmi_platform_profile_set,
> };
> @@ -1598,8 +1618,6 @@ static int thermal_profile_setup(struct platform_device *device)
> return err;
>
> platform_profile_handler.ops = &platform_profile_omen_ops;
> -
> - set_bit(PLATFORM_PROFILE_COOL, platform_profile_handler.choices);
> } else if (is_victus_thermal_profile()) {
> err = platform_profile_victus_get_ec(&active_platform_profile);
> if (err < 0)
> @@ -1614,8 +1632,6 @@ static int thermal_profile_setup(struct platform_device *device)
> return err;
>
> platform_profile_handler.ops = &platform_profile_victus_ops;
> -
> - set_bit(PLATFORM_PROFILE_QUIET, platform_profile_handler.choices);
> } else {
> tp = thermal_profile_get();
>
> @@ -1631,15 +1647,10 @@ static int thermal_profile_setup(struct platform_device *device)
> return err;
>
> platform_profile_handler.ops = &hp_wmi_platform_profile_ops;
> -
> - set_bit(PLATFORM_PROFILE_QUIET, platform_profile_handler.choices);
> - set_bit(PLATFORM_PROFILE_COOL, platform_profile_handler.choices);
> }
>
> platform_profile_handler.name = "hp-wmi";
> platform_profile_handler.dev = &device->dev;
> - set_bit(PLATFORM_PROFILE_BALANCED, platform_profile_handler.choices);
> - set_bit(PLATFORM_PROFILE_PERFORMANCE, platform_profile_handler.choices);
>
> err = platform_profile_register(&platform_profile_handler, NULL);
> if (err)
> diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c
> index 96e99513b0b5..050919a28d2b 100644
> --- a/drivers/platform/x86/ideapad-laptop.c
> +++ b/drivers/platform/x86/ideapad-laptop.c
> @@ -1023,6 +1023,15 @@ static int dytc_profile_set(struct device *dev,
> return -EINTR;
> }
>
> +static int dytc_profile_probe(void *drvdata, unsigned long *choices)
> +{
> + set_bit(PLATFORM_PROFILE_LOW_POWER, choices);
> + set_bit(PLATFORM_PROFILE_BALANCED, choices);
> + set_bit(PLATFORM_PROFILE_PERFORMANCE, choices);
> +
> + return 0;
> +}
> +
> static void dytc_profile_refresh(struct ideapad_private *priv)
> {
> enum platform_profile_option profile;
> @@ -1064,6 +1073,7 @@ static const struct dmi_system_id ideapad_dytc_v4_allow_table[] = {
> };
>
> static const struct platform_profile_ops dytc_profile_ops = {
> + .probe = dytc_profile_probe,
> .profile_get = dytc_profile_get,
> .profile_set = dytc_profile_set,
> };
> @@ -1112,11 +1122,6 @@ static int ideapad_dytc_profile_init(struct ideapad_private *priv)
> priv->dytc->priv = priv;
> priv->dytc->pprof.ops = &dytc_profile_ops;
>
> - /* Setup supported modes */
> - set_bit(PLATFORM_PROFILE_LOW_POWER, priv->dytc->pprof.choices);
> - set_bit(PLATFORM_PROFILE_BALANCED, priv->dytc->pprof.choices);
> - set_bit(PLATFORM_PROFILE_PERFORMANCE, priv->dytc->pprof.choices);
> -
> /* Create platform_profile structure and register */
> err = platform_profile_register(&priv->dytc->pprof, &priv->dytc);
> if (err)
> diff --git a/drivers/platform/x86/inspur_platform_profile.c b/drivers/platform/x86/inspur_platform_profile.c
> index d0a8e4eebffa..06df3aae9a56 100644
> --- a/drivers/platform/x86/inspur_platform_profile.c
> +++ b/drivers/platform/x86/inspur_platform_profile.c
> @@ -164,7 +164,17 @@ static int inspur_platform_profile_get(struct device *dev,
> return 0;
> }
>
> +static int inspur_platform_profile_probe(void *drvdata, unsigned long *choices)
> +{
> + set_bit(PLATFORM_PROFILE_LOW_POWER, choices);
> + set_bit(PLATFORM_PROFILE_BALANCED, choices);
> + set_bit(PLATFORM_PROFILE_PERFORMANCE, choices);
> +
> + return 0;
> +}
> +
> static const struct platform_profile_ops inspur_platform_profile_ops = {
> + .probe = inspur_platform_profile_probe,
> .profile_get = inspur_platform_profile_get,
> .profile_set = inspur_platform_profile_set,
> };
> @@ -184,10 +194,6 @@ static int inspur_wmi_probe(struct wmi_device *wdev, const void *context)
> priv->handler.dev = &wdev->dev;
> priv->handler.ops = &inspur_platform_profile_ops;
>
> - set_bit(PLATFORM_PROFILE_LOW_POWER, priv->handler.choices);
> - set_bit(PLATFORM_PROFILE_BALANCED, priv->handler.choices);
> - set_bit(PLATFORM_PROFILE_PERFORMANCE, priv->handler.choices);
> -
> return platform_profile_register(&priv->handler, priv);
> }
>
> diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
> index 9978fd36a3d1..5c250867678f 100644
> --- a/drivers/platform/x86/thinkpad_acpi.c
> +++ b/drivers/platform/x86/thinkpad_acpi.c
> @@ -10538,7 +10538,17 @@ static int dytc_profile_set(struct device *dev,
> return err;
> }
>
> +static int dytc_profile_probe(void *drvdata, unsigned long *choices)
> +{
> + set_bit(PLATFORM_PROFILE_LOW_POWER, choices);
> + set_bit(PLATFORM_PROFILE_BALANCED, choices);
> + set_bit(PLATFORM_PROFILE_PERFORMANCE, choices);
> +
> + return 0;
> +}
> +
> static const struct platform_profile_ops dytc_profile_ops = {
> + .probe = dytc_profile_probe,
> .profile_get = dytc_profile_get,
> .profile_set = dytc_profile_set,
> };
> @@ -10584,11 +10594,6 @@ static int tpacpi_dytc_profile_init(struct ibm_init_struct *iibm)
> {
> int err, output;
>
> - /* Setup supported modes */
> - set_bit(PLATFORM_PROFILE_LOW_POWER, dytc_profile.choices);
> - set_bit(PLATFORM_PROFILE_BALANCED, dytc_profile.choices);
> - set_bit(PLATFORM_PROFILE_PERFORMANCE, dytc_profile.choices);
> -
> err = dytc_command(DYTC_CMD_QUERY, &output);
> if (err)
> return err;
> diff --git a/include/linux/platform_profile.h b/include/linux/platform_profile.h
> index 6013c05d7b86..5ad1ab7b75e4 100644
> --- a/include/linux/platform_profile.h
> +++ b/include/linux/platform_profile.h
> @@ -31,6 +31,7 @@ enum platform_profile_option {
> struct platform_profile_handler;
>
> struct platform_profile_ops {
> + int (*probe)(void *drvdata, unsigned long *choices);
> int (*profile_get)(struct device *dev, enum platform_profile_option *profile);
> int (*profile_set)(struct device *dev, enum platform_profile_option profile);
> };
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH v2 15/18] ACPI: platform_profile: Remove platform_profile_handler from exported symbols
2025-01-14 15:37 ` [PATCH v2 15/18] ACPI: platform_profile: Remove platform_profile_handler from exported symbols Kurt Borja
@ 2025-01-14 16:22 ` Mario Limonciello
2025-01-14 16:55 ` Ilpo Järvinen
1 sibling, 0 replies; 33+ messages in thread
From: Mario Limonciello @ 2025-01-14 16:22 UTC (permalink / raw)
To: Kurt Borja, platform-driver-x86
Cc: Rafael J. Wysocki, Len Brown, linux-acpi, linux-kernel,
Armin Wolf, Joshua Grisham, Derek J. Clark, Ilpo Järvinen,
Hans de Goede, Maximilian Luz, Lee, Chun-Yi, Shyam Sundar S K,
Corentin Chary, Luke D. Jones, Lyndon Sanche, Ike Panhc,
Henrique de Moraes Holschuh, Mark Pearson, Alexis Belmonte,
Ai Chao, Gergo Koteles, Dell.Client.Kernel, ibm-acpi-devel
On 1/14/2025 09:37, Kurt Borja wrote:
> In order to protect the platform_profile_handler from API consumers,
> allocate it in platform_profile_register() and modify it's signature
> accordingly.
>
> Remove the platform_profile_handler from all consumer drivers and
> replace them with a pointer to the class device, which is
> now returned from platform_profile_register().
>
> Replace *pprof with a pointer to the class device in the rest of
> exported symbols.
>
> Signed-off-by: Kurt Borja <kuurtb@gmail.com>
Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
> ---
> drivers/acpi/platform_profile.c | 87 ++++++++++++-------
> .../surface/surface_platform_profile.c | 11 ++-
> drivers/platform/x86/acer-wmi.c | 18 ++--
> drivers/platform/x86/amd/pmf/pmf.h | 2 +-
> drivers/platform/x86/amd/pmf/sps.c | 17 ++--
> drivers/platform/x86/asus-wmi.c | 20 ++---
> drivers/platform/x86/dell/alienware-wmi.c | 9 +-
> drivers/platform/x86/dell/dell-pc.c | 22 ++---
> drivers/platform/x86/hp/hp-wmi.c | 19 ++--
> drivers/platform/x86/ideapad-laptop.c | 14 +--
> .../platform/x86/inspur_platform_profile.c | 9 +-
> drivers/platform/x86/thinkpad_acpi.c | 14 ++-
> include/linux/platform_profile.h | 12 ++-
> 13 files changed, 125 insertions(+), 129 deletions(-)
>
> diff --git a/drivers/acpi/platform_profile.c b/drivers/acpi/platform_profile.c
> index 34e22b006ccc..2fae5e2fc962 100644
> --- a/drivers/acpi/platform_profile.c
> +++ b/drivers/acpi/platform_profile.c
> @@ -4,6 +4,7 @@
>
> #include <linux/acpi.h>
> #include <linux/bits.h>
> +#include <linux/cleanup.h>
> #include <linux/init.h>
> #include <linux/kdev_t.h>
> #include <linux/mutex.h>
> @@ -213,9 +214,17 @@ static struct attribute *profile_attrs[] = {
> };
> ATTRIBUTE_GROUPS(profile);
>
> +static void pprof_device_release(struct device *dev)
> +{
> + struct platform_profile_handler *pprof = to_pprof_handler(dev);
> +
> + kfree(pprof);
> +}
> +
> static const struct class platform_profile_class = {
> .name = "platform-profile",
> .dev_groups = profile_groups,
> + .dev_release = pprof_device_release,
> };
>
> /**
> @@ -409,10 +418,10 @@ static const struct attribute_group platform_profile_group = {
> .is_visible = profile_class_is_visible,
> };
>
> -void platform_profile_notify(struct platform_profile_handler *pprof)
> +void platform_profile_notify(struct device *dev)
> {
> scoped_cond_guard(mutex_intr, return, &profile_lock) {
> - _notify_class_profile(&pprof->class_dev, NULL);
> + _notify_class_profile(dev, NULL);
> }
> sysfs_notify(acpi_kobj, NULL, "platform_profile");
> }
> @@ -461,40 +470,51 @@ int platform_profile_cycle(void)
> }
> EXPORT_SYMBOL_GPL(platform_profile_cycle);
>
> -int platform_profile_register(struct platform_profile_handler *pprof, void *drvdata)
> +struct device *platform_profile_register(struct device *dev, const char *name,
> + void *drvdata,
> + const struct platform_profile_ops *ops)
> {
> + int minor;
> int err;
>
> - /* Sanity check the profile handler */
> - if (!pprof || !pprof->ops->profile_set || !pprof->ops->profile_get ||
> - !pprof->ops->probe) {
> + /* Sanity check */
> + if (!dev || !name || !ops || !ops->profile_get ||
> + !ops->profile_set || !ops->probe) {
> pr_err("platform_profile: handler is invalid\n");
> - return -EINVAL;
> + return ERR_PTR(-EINVAL);
> }
>
> - err = pprof->ops->probe(drvdata, pprof->choices);
> + struct platform_profile_handler *pprof __free(kfree) = kzalloc(
> + sizeof(*pprof), GFP_KERNEL);
> + if (!pprof)
> + return ERR_PTR(-ENOMEM);
> +
> + err = ops->probe(drvdata, pprof->choices);
> if (err < 0)
> - return err;
> + return ERR_PTR(err);
>
> if (bitmap_empty(pprof->choices, PLATFORM_PROFILE_LAST)) {
> pr_err("platform_profile: no available profiles\n");
> - return -EINVAL;
> + return ERR_PTR(-EINVAL);
> }
>
> guard(mutex)(&profile_lock);
>
> /* create class interface for individual handler */
> - pprof->minor = ida_alloc(&platform_profile_ida, GFP_KERNEL);
> - if (pprof->minor < 0)
> - return pprof->minor;
> + minor = ida_alloc(&platform_profile_ida, GFP_KERNEL);
> + if (minor < 0)
> + return ERR_PTR(minor);
>
> + pprof->name = name;
> + pprof->ops = ops;
> + pprof->minor = minor;
> pprof->class_dev.class = &platform_profile_class;
> - pprof->class_dev.parent = pprof->dev;
> + pprof->class_dev.parent = dev;
> dev_set_drvdata(&pprof->class_dev, drvdata);
> dev_set_name(&pprof->class_dev, "platform-profile-%d", pprof->minor);
> err = device_register(&pprof->class_dev);
> if (err) {
> - put_device(&pprof->class_dev);
> + put_device(&no_free_ptr(pprof)->class_dev);
> goto cleanup_ida;
> }
>
> @@ -504,20 +524,21 @@ int platform_profile_register(struct platform_profile_handler *pprof, void *drvd
> if (err)
> goto cleanup_cur;
>
> - return 0;
> + return &no_free_ptr(pprof)->class_dev;
>
> cleanup_cur:
> - device_unregister(&pprof->class_dev);
> + device_unregister(&no_free_ptr(pprof)->class_dev);
>
> cleanup_ida:
> - ida_free(&platform_profile_ida, pprof->minor);
> + ida_free(&platform_profile_ida, minor);
>
> - return err;
> + return ERR_PTR(err);
> }
> EXPORT_SYMBOL_GPL(platform_profile_register);
>
> -int platform_profile_remove(struct platform_profile_handler *pprof)
> +int platform_profile_remove(struct device *dev)
> {
> + struct platform_profile_handler *pprof = to_pprof_handler(dev);
> int id;
> guard(mutex)(&profile_lock);
>
> @@ -535,30 +556,32 @@ EXPORT_SYMBOL_GPL(platform_profile_remove);
>
> static void devm_platform_profile_release(struct device *dev, void *res)
> {
> - struct platform_profile_handler **pprof = res;
> + struct device **ppdev = res;
>
> - platform_profile_remove(*pprof);
> + platform_profile_remove(*ppdev);
> }
>
> -int devm_platform_profile_register(struct platform_profile_handler *pprof, void *drvdata)
> +struct device *devm_platform_profile_register(struct device *dev, const char *name,
> + void *drvdata,
> + const struct platform_profile_ops *ops)
> {
> - struct platform_profile_handler **dr;
> - int ret;
> + struct device *ppdev;
> + struct device **dr;
>
> dr = devres_alloc(devm_platform_profile_release, sizeof(*dr), GFP_KERNEL);
> if (!dr)
> - return -ENOMEM;
> + return ERR_PTR(-ENOMEM);
>
> - ret = platform_profile_register(pprof, drvdata);
> - if (ret) {
> + ppdev = platform_profile_register(dev, name, drvdata, ops);
> + if (IS_ERR(dev)) {
> devres_free(dr);
> - return ret;
> + return ppdev;
> }
>
> - *dr = pprof;
> - devres_add(pprof->dev, dr);
> + *dr = ppdev;
> + devres_add(dev, dr);
>
> - return 0;
> + return ppdev;
> }
> EXPORT_SYMBOL_GPL(devm_platform_profile_register);
>
> diff --git a/drivers/platform/surface/surface_platform_profile.c b/drivers/platform/surface/surface_platform_profile.c
> index bbdc873cb788..275269a6efc1 100644
> --- a/drivers/platform/surface/surface_platform_profile.c
> +++ b/drivers/platform/surface/surface_platform_profile.c
> @@ -40,7 +40,7 @@ struct ssam_tmp_profile_info {
>
> struct ssam_platform_profile_device {
> struct ssam_device *sdev;
> - struct platform_profile_handler handler;
> + struct device *ppdev;
> bool has_fan;
> };
>
> @@ -228,13 +228,12 @@ static int surface_platform_profile_probe(struct ssam_device *sdev)
> tpd->sdev = sdev;
> ssam_device_set_drvdata(sdev, tpd);
>
> - tpd->handler.name = "Surface Platform Profile";
> - tpd->handler.dev = &sdev->dev;
> - tpd->handler.ops = &ssam_platform_profile_ops;
> -
> tpd->has_fan = device_property_read_bool(&sdev->dev, "has_fan");
>
> - return devm_platform_profile_register(&tpd->handler, tpd);
> + tpd->ppdev = devm_platform_profile_register(
> + &sdev->dev, "Surface Platform Profile", tpd, &ssam_platform_profile_ops);
> +
> + return PTR_ERR_OR_ZERO(tpd->ppdev);
> }
>
> static const struct ssam_device_id ssam_platform_profile_match[] = {
> diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c
> index 39ec236b7cdb..3e39465b3783 100644
> --- a/drivers/platform/x86/acer-wmi.c
> +++ b/drivers/platform/x86/acer-wmi.c
> @@ -758,7 +758,7 @@ static const struct dmi_system_id non_acer_quirks[] __initconst = {
> {}
> };
>
> -static struct platform_profile_handler platform_profile_handler;
> +static struct device *platform_profile_device;
> static bool platform_profile_support;
>
> /*
> @@ -1937,16 +1937,10 @@ static const struct platform_profile_ops acer_predator_v4_platform_profile_ops =
> static int acer_platform_profile_setup(struct platform_device *device)
> {
> if (quirks->predator_v4) {
> - int err;
> -
> - platform_profile_handler.name = "acer-wmi";
> - platform_profile_handler.dev = &device->dev;
> - platform_profile_handler.ops =
> - &acer_predator_v4_platform_profile_ops;
> -
> - err = devm_platform_profile_register(&platform_profile_handler, NULL);
> - if (err)
> - return err;
> + platform_profile_device = devm_platform_profile_register(
> + &device->dev, "acer-wmi", NULL, &acer_predator_v4_platform_profile_ops);
> + if (IS_ERR(platform_profile_device))
> + return PTR_ERR(platform_profile_device);
>
> platform_profile_support = true;
>
> @@ -2033,7 +2027,7 @@ static int acer_thermal_profile_change(void)
> if (tp != ACER_PREDATOR_V4_THERMAL_PROFILE_TURBO_WMI)
> last_non_turbo_profile = tp;
>
> - platform_profile_notify(&platform_profile_handler);
> + platform_profile_notify(platform_profile_device);
> }
>
> return 0;
> diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/x86/amd/pmf/pmf.h
> index d99b3556205b..41b2b91b8fdc 100644
> --- a/drivers/platform/x86/amd/pmf/pmf.h
> +++ b/drivers/platform/x86/amd/pmf/pmf.h
> @@ -338,7 +338,7 @@ struct amd_pmf_dev {
> struct mutex lock; /* protects the PMF interface */
> u32 supported_func;
> enum platform_profile_option current_profile;
> - struct platform_profile_handler pprof;
> + struct device *ppdev; /* platform profile class device */
> struct dentry *dbgfs_dir;
> int hb_interval; /* SBIOS heartbeat interval */
> struct delayed_work heart_beat;
> diff --git a/drivers/platform/x86/amd/pmf/sps.c b/drivers/platform/x86/amd/pmf/sps.c
> index 7c7ed2b9de01..a96fc6887cf0 100644
> --- a/drivers/platform/x86/amd/pmf/sps.c
> +++ b/drivers/platform/x86/amd/pmf/sps.c
> @@ -404,8 +404,6 @@ static const struct platform_profile_ops amd_pmf_profile_ops = {
>
> int amd_pmf_init_sps(struct amd_pmf_dev *dev)
> {
> - int err;
> -
> dev->current_profile = PLATFORM_PROFILE_BALANCED;
>
> if (is_apmf_func_supported(dev, APMF_FUNC_STATIC_SLIDER_GRANULAR)) {
> @@ -420,15 +418,12 @@ int amd_pmf_init_sps(struct amd_pmf_dev *dev)
> amd_pmf_set_sps_power_limits(dev);
> }
>
> - dev->pprof.name = "amd-pmf";
> - dev->pprof.dev = dev->dev;
> - dev->pprof.ops = &amd_pmf_profile_ops;
> -
> /* Create platform_profile structure and register */
> - err = devm_platform_profile_register(&dev->pprof, dev);
> - if (err)
> - dev_err(dev->dev, "Failed to register SPS support, this is most likely an SBIOS bug: %d\n",
> - err);
> + dev->ppdev = devm_platform_profile_register(
> + dev->dev, "amd-pmf", dev, &amd_pmf_profile_ops);
> + if (IS_ERR(dev->ppdev))
> + dev_err(dev->dev, "Failed to register SPS support, this is most likely an SBIOS bug: %ld\n",
> + PTR_ERR(dev->ppdev));
>
> - return err;
> + return PTR_ERR_OR_ZERO(dev->ppdev);
> }
> diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
> index f8437cff66df..4ad99cf9df1a 100644
> --- a/drivers/platform/x86/asus-wmi.c
> +++ b/drivers/platform/x86/asus-wmi.c
> @@ -313,7 +313,7 @@ struct asus_wmi {
> bool mid_fan_curve_available;
> struct fan_curve_data custom_fan_curves[3];
>
> - struct platform_profile_handler platform_profile_handler;
> + struct device *platform_profile_device;
> bool platform_profile_support;
>
> // The RSOC controls the maximum charging percentage.
> @@ -3789,7 +3789,7 @@ static ssize_t throttle_thermal_policy_store(struct device *dev,
> * Ensure that platform_profile updates userspace with the change to ensure
> * that platform_profile and throttle_thermal_policy_mode are in sync.
> */
> - platform_profile_notify(&asus->platform_profile_handler);
> + platform_profile_notify(asus->platform_profile_device);
>
> return count;
> }
> @@ -3891,17 +3891,13 @@ static int platform_profile_setup(struct asus_wmi *asus)
>
> dev_info(dev, "Using throttle_thermal_policy for platform_profile support\n");
>
> - asus->platform_profile_handler.name = "asus-wmi";
> - asus->platform_profile_handler.dev = dev;
> - asus->platform_profile_handler.ops = &asus_wmi_platform_profile_ops;
> + asus->platform_profile_device = devm_platform_profile_register(
> + dev, "asus-wmi", asus, &asus_wmi_platform_profile_ops);
> + if (IS_ERR(asus->platform_profile_device)) {
> + pr_err("%s, failed at devm_platform_profile_register: %ld\n",
> + __func__, PTR_ERR(asus->platform_profile_device));
>
> - err = devm_platform_profile_register(&asus->platform_profile_handler, asus);
> - if (err == -EEXIST) {
> - pr_warn("%s, a platform_profile handler is already registered\n", __func__);
> - return 0;
> - } else if (err) {
> - pr_err("%s, failed at devm_platform_profile_register: %d\n", __func__, err);
> - return err;
> + return PTR_ERR(asus->platform_profile_device);
> }
>
> asus->platform_profile_support = true;
> diff --git a/drivers/platform/x86/dell/alienware-wmi.c b/drivers/platform/x86/dell/alienware-wmi.c
> index 0146d2f93be6..99db93846a63 100644
> --- a/drivers/platform/x86/dell/alienware-wmi.c
> +++ b/drivers/platform/x86/dell/alienware-wmi.c
> @@ -1135,11 +1135,12 @@ static const struct platform_profile_ops awcc_platform_profile_ops = {
>
> static int create_thermal_profile(struct platform_device *platform_device)
> {
> - pp_handler.name = "alienware-wmi";
> - pp_handler.dev = &platform_device->dev;
> - pp_handler.ops = &awcc_platform_profile_ops;
> + struct device *ppdev;
>
> - return devm_platform_profile_register(&pp_handler, NULL);
> + ppdev = devm_platform_profile_register(
> + &platform_device->dev, "alienware-wmi", NULL, &awcc_platform_profile_ops);
> +
> + return PTR_ERR_OR_ZERO(ppdev);
> }
>
> /*
> diff --git a/drivers/platform/x86/dell/dell-pc.c b/drivers/platform/x86/dell/dell-pc.c
> index 2759bb608b1a..8d60e1b223de 100644
> --- a/drivers/platform/x86/dell/dell-pc.c
> +++ b/drivers/platform/x86/dell/dell-pc.c
> @@ -109,8 +109,6 @@ MODULE_DEVICE_TABLE(dmi, dell_device_table);
> #define DELL_ACC_SET_FIELD GENMASK(11, 8)
> #define DELL_THERMAL_SUPPORTED GENMASK(3, 0)
>
> -static struct platform_profile_handler *thermal_handler;
> -
> enum thermal_mode_bits {
> DELL_BALANCED = BIT(0),
> DELL_COOL_BOTTOM = BIT(1),
> @@ -254,6 +252,7 @@ static const struct platform_profile_ops dell_pc_platform_profile_ops = {
>
> static int thermal_init(void)
> {
> + struct device *ppdev;
> int ret;
>
> /* If thermal commands are not supported, exit without error */
> @@ -271,26 +270,17 @@ static int thermal_init(void)
> if (IS_ERR(platform_device))
> return PTR_ERR(platform_device);
>
> - thermal_handler = devm_kzalloc(&platform_device->dev, sizeof(*thermal_handler), GFP_KERNEL);
> - if (!thermal_handler) {
> - ret = -ENOMEM;
> - goto cleanup_platform_device;
> - }
> - thermal_handler->name = "dell-pc";
> - thermal_handler->dev = &platform_device->dev;
> - thermal_handler->ops = &dell_pc_platform_profile_ops;
> -
> /* Clean up if failed */
> - ret = devm_platform_profile_register(thermal_handler, NULL);
> - if (ret)
> + ppdev = devm_platform_profile_register(
> + &platform_device->dev, "dell-pc", NULL, &dell_pc_platform_profile_ops);
> + if (IS_ERR(ppdev)) {
> + ret = PTR_ERR(ppdev);
> goto cleanup_thermal_handler;
> + }
>
> return 0;
>
> cleanup_thermal_handler:
> - thermal_handler = NULL;
> -
> -cleanup_platform_device:
> platform_device_unregister(platform_device);
>
> return ret;
> diff --git a/drivers/platform/x86/hp/hp-wmi.c b/drivers/platform/x86/hp/hp-wmi.c
> index 1304dfc65aab..d1f9bd287986 100644
> --- a/drivers/platform/x86/hp/hp-wmi.c
> +++ b/drivers/platform/x86/hp/hp-wmi.c
> @@ -273,7 +273,7 @@ static DEFINE_MUTEX(active_platform_profile_lock);
> static struct input_dev *hp_wmi_input_dev;
> static struct input_dev *camera_shutter_input_dev;
> static struct platform_device *hp_wmi_platform_dev;
> -static struct platform_profile_handler platform_profile_handler;
> +static struct device *platform_profile_device;
> static struct notifier_block platform_power_source_nb;
> static enum platform_profile_option active_platform_profile;
> static bool platform_profile_support;
> @@ -1602,6 +1602,7 @@ static const struct platform_profile_ops hp_wmi_platform_profile_ops = {
>
> static int thermal_profile_setup(struct platform_device *device)
> {
> + const struct platform_profile_ops *ops;
> int err, tp;
>
> if (is_omen_thermal_profile()) {
> @@ -1617,7 +1618,7 @@ static int thermal_profile_setup(struct platform_device *device)
> if (err < 0)
> return err;
>
> - platform_profile_handler.ops = &platform_profile_omen_ops;
> + ops = &platform_profile_omen_ops;
> } else if (is_victus_thermal_profile()) {
> err = platform_profile_victus_get_ec(&active_platform_profile);
> if (err < 0)
> @@ -1631,7 +1632,7 @@ static int thermal_profile_setup(struct platform_device *device)
> if (err < 0)
> return err;
>
> - platform_profile_handler.ops = &platform_profile_victus_ops;
> + ops = &platform_profile_victus_ops;
> } else {
> tp = thermal_profile_get();
>
> @@ -1646,15 +1647,13 @@ static int thermal_profile_setup(struct platform_device *device)
> if (err)
> return err;
>
> - platform_profile_handler.ops = &hp_wmi_platform_profile_ops;
> + ops = &hp_wmi_platform_profile_ops;
> }
>
> - platform_profile_handler.name = "hp-wmi";
> - platform_profile_handler.dev = &device->dev;
> -
> - err = devm_platform_profile_register(&platform_profile_handler, NULL);
> - if (err)
> - return err;
> + platform_profile_device = devm_platform_profile_register(
> + &device->dev, "hp-wmi", NULL, ops);
> + if (IS_ERR(platform_profile_device))
> + return PTR_ERR(platform_profile_device);
>
> platform_profile_support = true;
>
> diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c
> index 87c1e087770a..6065a7421a02 100644
> --- a/drivers/platform/x86/ideapad-laptop.c
> +++ b/drivers/platform/x86/ideapad-laptop.c
> @@ -142,7 +142,7 @@ enum {
>
> struct ideapad_dytc_priv {
> enum platform_profile_option current_profile;
> - struct platform_profile_handler pprof;
> + struct device *ppdev; /* platform profile device */
> struct mutex mutex; /* protects the DYTC interface */
> struct ideapad_private *priv;
> };
> @@ -1050,7 +1050,7 @@ static void dytc_profile_refresh(struct ideapad_private *priv)
>
> if (profile != priv->dytc->current_profile) {
> priv->dytc->current_profile = profile;
> - platform_profile_notify(&priv->dytc->pprof);
> + platform_profile_notify(priv->dytc->ppdev);
> }
> }
>
> @@ -1117,15 +1117,15 @@ static int ideapad_dytc_profile_init(struct ideapad_private *priv)
>
> mutex_init(&priv->dytc->mutex);
>
> - priv->dytc->pprof.name = "ideapad-laptop";
> - priv->dytc->pprof.dev = &priv->platform_device->dev;
> priv->dytc->priv = priv;
> - priv->dytc->pprof.ops = &dytc_profile_ops;
>
> /* Create platform_profile structure and register */
> - err = devm_platform_profile_register(&priv->dytc->pprof, &priv->dytc);
> - if (err)
> + priv->dytc->ppdev = devm_platform_profile_register(
> + &priv->platform_device->dev, "ideapad-laptop", &priv->dytc, &dytc_profile_ops);
> + if (IS_ERR(priv->dytc->ppdev)) {
> + err = PTR_ERR(priv->dytc->ppdev);
> goto pp_reg_failed;
> + }
>
> /* Ensure initial values are correct */
> dytc_profile_refresh(priv);
> diff --git a/drivers/platform/x86/inspur_platform_profile.c b/drivers/platform/x86/inspur_platform_profile.c
> index e1631de6ad86..8b71c4242939 100644
> --- a/drivers/platform/x86/inspur_platform_profile.c
> +++ b/drivers/platform/x86/inspur_platform_profile.c
> @@ -32,7 +32,7 @@ enum inspur_tmp_profile {
>
> struct inspur_wmi_priv {
> struct wmi_device *wdev;
> - struct platform_profile_handler handler;
> + struct device *ppdev;
> };
>
> static int inspur_wmi_perform_query(struct wmi_device *wdev,
> @@ -190,11 +190,10 @@ static int inspur_wmi_probe(struct wmi_device *wdev, const void *context)
> priv->wdev = wdev;
> dev_set_drvdata(&wdev->dev, priv);
>
> - priv->handler.name = "inspur-wmi";
> - priv->handler.dev = &wdev->dev;
> - priv->handler.ops = &inspur_platform_profile_ops;
> + priv->ppdev = devm_platform_profile_register(
> + &wdev->dev, "inspur-wmi", priv, &inspur_platform_profile_ops);
>
> - return devm_platform_profile_register(&priv->handler, priv);
> + return PTR_ERR_OR_ZERO(priv->ppdev);
> }
>
> static const struct wmi_device_id inspur_wmi_id_table[] = {
> diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
> index 54ff3e6b8b1a..2a3dd0d149a1 100644
> --- a/drivers/platform/x86/thinkpad_acpi.c
> +++ b/drivers/platform/x86/thinkpad_acpi.c
> @@ -962,6 +962,7 @@ static const struct proc_ops dispatch_proc_ops = {
> static struct platform_device *tpacpi_pdev;
> static struct platform_device *tpacpi_sensors_pdev;
> static struct device *tpacpi_hwmon;
> +static struct device *tpacpi_pprof;
> static struct input_dev *tpacpi_inputdev;
> static struct mutex tpacpi_inputdev_send_mutex;
> static LIST_HEAD(tpacpi_all_drivers);
> @@ -10553,11 +10554,6 @@ static const struct platform_profile_ops dytc_profile_ops = {
> .profile_set = dytc_profile_set,
> };
>
> -static struct platform_profile_handler dytc_profile = {
> - .name = "thinkpad-acpi",
> - .ops = &dytc_profile_ops,
> -};
> -
> static void dytc_profile_refresh(void)
> {
> enum platform_profile_option profile;
> @@ -10586,7 +10582,7 @@ static void dytc_profile_refresh(void)
> err = convert_dytc_to_profile(funcmode, perfmode, &profile);
> if (!err && profile != dytc_current_profile) {
> dytc_current_profile = profile;
> - platform_profile_notify(&dytc_profile);
> + platform_profile_notify(tpacpi_pprof);
> }
> }
>
> @@ -10647,14 +10643,14 @@ static int tpacpi_dytc_profile_init(struct ibm_init_struct *iibm)
> dbg_printk(TPACPI_DBG_INIT,
> "DYTC version %d: thermal mode available\n", dytc_version);
>
> - dytc_profile.dev = &tpacpi_pdev->dev;
> /* Create platform_profile structure and register */
> - err = devm_platform_profile_register(&dytc_profile, NULL);
> + tpacpi_pprof = devm_platform_profile_register(
> + &tpacpi_pdev->dev, "thinkpad-acpi", NULL, &dytc_profile_ops);
> /*
> * If for some reason platform_profiles aren't enabled
> * don't quit terminally.
> */
> - if (err)
> + if (IS_ERR(tpacpi_pprof))
> return -ENODEV;
>
> /* Ensure initial values are correct */
> diff --git a/include/linux/platform_profile.h b/include/linux/platform_profile.h
> index 5ad1ab7b75e4..778d4c661c3c 100644
> --- a/include/linux/platform_profile.h
> +++ b/include/linux/platform_profile.h
> @@ -45,10 +45,14 @@ struct platform_profile_handler {
> const struct platform_profile_ops *ops;
> };
>
> -int platform_profile_register(struct platform_profile_handler *pprof, void *drvdata);
> -int platform_profile_remove(struct platform_profile_handler *pprof);
> -int devm_platform_profile_register(struct platform_profile_handler *pprof, void *drvdata);
> +struct device *platform_profile_register(struct device *dev, const char *name,
> + void *drvdata,
> + const struct platform_profile_ops *ops);
> +int platform_profile_remove(struct device *dev);
> +struct device *devm_platform_profile_register(struct device *dev, const char *name,
> + void *drvdata,
> + const struct platform_profile_ops *ops);
> int platform_profile_cycle(void);
> -void platform_profile_notify(struct platform_profile_handler *pprof);
> +void platform_profile_notify(struct device *dev);
>
> #endif /*_PLATFORM_PROFILE_H_*/
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH v2 18/18] ACPI: platform_profile: Add documentation
2025-01-14 15:37 ` [PATCH v2 18/18] ACPI: platform_profile: Add documentation Kurt Borja
@ 2025-01-14 16:24 ` Mario Limonciello
2025-01-14 16:57 ` Ilpo Järvinen
1 sibling, 0 replies; 33+ messages in thread
From: Mario Limonciello @ 2025-01-14 16:24 UTC (permalink / raw)
To: Kurt Borja, platform-driver-x86
Cc: Rafael J. Wysocki, Len Brown, linux-acpi, linux-kernel,
Armin Wolf, Joshua Grisham, Derek J. Clark, Ilpo Järvinen,
Hans de Goede, Maximilian Luz, Lee, Chun-Yi, Shyam Sundar S K,
Corentin Chary, Luke D. Jones, Lyndon Sanche, Ike Panhc,
Henrique de Moraes Holschuh, Mark Pearson, Alexis Belmonte,
Ai Chao, Gergo Koteles, Dell.Client.Kernel, ibm-acpi-devel
On 1/14/2025 09:37, Kurt Borja wrote:
> Add kerneldoc and sysfs class documentation.
>
> Signed-off-by: Kurt Borja <kuurtb@gmail.com>
Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
> ---
> .../ABI/testing/sysfs-class-platform-profile | 44 +++++++++++++++++++
> drivers/acpi/platform_profile.c | 33 ++++++++++++++
> include/linux/platform_profile.h | 24 ++++++++++
> 3 files changed, 101 insertions(+)
> create mode 100644 Documentation/ABI/testing/sysfs-class-platform-profile
>
> diff --git a/Documentation/ABI/testing/sysfs-class-platform-profile b/Documentation/ABI/testing/sysfs-class-platform-profile
> new file mode 100644
> index 000000000000..b5a3600080bc
> --- /dev/null
> +++ b/Documentation/ABI/testing/sysfs-class-platform-profile
> @@ -0,0 +1,44 @@
> +What: /sys/class/platform-profile/platform-profile-X/name
> +Date: January 2025
> +Description: Name of the class device given by the driver.
> +
> + RO
> +
> +What: /sys/class/platform-profile/platform-profile-X/choices
> +Date: January 2025
> +Description: This file contains a space-separated list of profiles supported for this device.
> +
> + Drivers must use the following standard profile-names:
> +
> + ==================== ========================================
> + low-power Low power consumption
> + cool Cooler operation
> + quiet Quieter operation
> + balanced Balance between low power consumption
> + and performance
> + balanced-performance Balance between performance and low
> + power consumption with a slight bias
> + towards performance
> + performance High performance operation
> + custom Driver defined custom profile
> + ==================== ========================================
> +
> + RO
> +
> +What: /sys/class/platform-profile/platform-profile-X/profile
> +Date: January 2025
> +Description: Reading this file gives the current selected profile for this
> + device. Writing this file with one of the strings from
> + platform_profile_choices changes the profile to the new value.
> +
> + This file can be monitored for changes by polling for POLLPRI,
> + POLLPRI will be signaled on any changes, independent of those
> + changes coming from a userspace write; or coming from another
> + source such as e.g. a hotkey triggered profile change handled
> + either directly by the embedded-controller or fully handled
> + inside the kernel.
> +
> + This file may also emit the string 'custom' to indicate
> + that the driver is using a driver defined custom profile.
> +
> + RW
> diff --git a/drivers/acpi/platform_profile.c b/drivers/acpi/platform_profile.c
> index c44989801f8e..9caddac695b8 100644
> --- a/drivers/acpi/platform_profile.c
> +++ b/drivers/acpi/platform_profile.c
> @@ -426,6 +426,10 @@ static const struct attribute_group platform_profile_group = {
> .is_visible = profile_class_is_visible,
> };
>
> +/**
> + * platform_profile_notify - Notify class device and legacy sysfs interface
> + * @dev: The class device
> + */
> void platform_profile_notify(struct device *dev)
> {
> scoped_cond_guard(mutex_intr, return, &profile_lock) {
> @@ -435,6 +439,11 @@ void platform_profile_notify(struct device *dev)
> }
> EXPORT_SYMBOL_GPL(platform_profile_notify);
>
> +/**
> + * platform_profile_cycle - Cycles profiles available on all registered class devices
> + *
> + * Return: 0 on success, -errno on failure
> + */
> int platform_profile_cycle(void)
> {
> enum platform_profile_option next = PLATFORM_PROFILE_LAST;
> @@ -478,6 +487,15 @@ int platform_profile_cycle(void)
> }
> EXPORT_SYMBOL_GPL(platform_profile_cycle);
>
> +/**
> + * platform_profile_register - Creates and registers a platform profile class device
> + * @dev: Parent device
> + * @name: Name of the class device
> + * @drvdata: Driver data that will be attached to the class device
> + * @ops: Platform profile's mandatory operations
> + *
> + * Return: pointer to the new class device on success, ERR_PTR on failure
> + */
> struct device *platform_profile_register(struct device *dev, const char *name,
> void *drvdata,
> const struct platform_profile_ops *ops)
> @@ -544,6 +562,12 @@ struct device *platform_profile_register(struct device *dev, const char *name,
> }
> EXPORT_SYMBOL_GPL(platform_profile_register);
>
> +/**
> + * platform_profile_remove - Unregisters a platform profile class device
> + * @dev: Class device
> + *
> + * Return: 0
> + */
> int platform_profile_remove(struct device *dev)
> {
> struct platform_profile_handler *pprof = to_pprof_handler(dev);
> @@ -569,6 +593,15 @@ static void devm_platform_profile_release(struct device *dev, void *res)
> platform_profile_remove(*ppdev);
> }
>
> +/**
> + * devm_platform_profile_register - Device managed version of platform_profile_register
> + * @dev: Parent device
> + * @name: Name of the class device
> + * @drvdata: Driver data that will be attached to the class device
> + * @ops: Platform profile's mandatory operations
> + *
> + * Return: pointer to the new class device on success, ERR_PTR on failure
> + */
> struct device *devm_platform_profile_register(struct device *dev, const char *name,
> void *drvdata,
> const struct platform_profile_ops *ops)
> diff --git a/include/linux/platform_profile.h b/include/linux/platform_profile.h
> index eea1daf85616..eb4dc85dc18c 100644
> --- a/include/linux/platform_profile.h
> +++ b/include/linux/platform_profile.h
> @@ -28,6 +28,30 @@ enum platform_profile_option {
> PLATFORM_PROFILE_LAST, /*must always be last */
> };
>
> +/**
> + * struct platform_profile_ops - platform profile operations
> + * @probe: Callback to setup choices available to the new class device.
> + * Parameters are:
> + * @drvdata: drvdata pointer passed to platform_profile_register.
> + * @choices: Empty choices bitmap which the driver has to manually
> + * setup, by using set_bit() in bits corresponding to
> + * platform_profile_option values. These values will only
> + * be enforced when a new profile is selected from
> + * user-space.
> + * @profile_get: Callback that will be called when showing the current platform
> + * profile.
> + * Parameters are:
> + * @dev: Class device.
> + * @profile: Pointer to the profile which will be read from
> + * user-space. Selected choices are not enforced when
> + * modifying this value.
> + * @profile_set: Callback that will be called when storing the new platform
> + * profile.
> + * Parameters are:
> + * @dev: Class device.
> + * @profile: New platform profile to be set. Guaranteed to be a
> + * value selected in the @probe callback.
> + */
> struct platform_profile_ops {
> int (*probe)(void *drvdata, unsigned long *choices);
> int (*profile_get)(struct device *dev, enum platform_profile_option *profile);
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH v2 05/18] ACPI: platform_profile: Add `probe` to platform_profile_ops
2025-01-14 16:20 ` Mario Limonciello
@ 2025-01-14 16:31 ` Kurt Borja
2025-01-14 16:36 ` Mario Limonciello
0 siblings, 1 reply; 33+ messages in thread
From: Kurt Borja @ 2025-01-14 16:31 UTC (permalink / raw)
To: Mario Limonciello
Cc: platform-driver-x86, Rafael J. Wysocki, Len Brown, linux-acpi,
linux-kernel, Armin Wolf, Joshua Grisham, Derek J. Clark,
Ilpo Järvinen, Hans de Goede, Maximilian Luz, Lee, Chun-Yi,
Shyam Sundar S K, Corentin Chary, Luke D. Jones, Lyndon Sanche,
Ike Panhc, Henrique de Moraes Holschuh, Mark Pearson,
Alexis Belmonte, Ai Chao, Gergo Koteles, Dell.Client.Kernel,
ibm-acpi-devel
Hi Mario,
On Tue, Jan 14, 2025 at 10:20:15AM -0600, Mario Limonciello wrote:
> On 1/14/2025 09:37, Kurt Borja wrote:
> > Add a `probe` callback to platform_profile_ops, which lets drivers
> > initialize the choices member manually.
> >
> > Signed-off-by: Kurt Borja <kuurtb@gmail.com>
> > ---
> > drivers/acpi/platform_profile.c | 13 +++++++--
> > .../surface/surface_platform_profile.c | 16 ++++++----
> > drivers/platform/x86/acer-wmi.c | 24 ++++++++-------
> > drivers/platform/x86/amd/pmf/sps.c | 15 ++++++----
> > drivers/platform/x86/asus-wmi.c | 16 ++++++----
> > drivers/platform/x86/dell/alienware-wmi.c | 24 +++++++++------
> > drivers/platform/x86/dell/dell-pc.c | 26 ++++++++++-------
> > drivers/platform/x86/hp/hp-wmi.c | 29 +++++++++++++------
> > drivers/platform/x86/ideapad-laptop.c | 15 ++++++----
> > .../platform/x86/inspur_platform_profile.c | 14 ++++++---
> > drivers/platform/x86/thinkpad_acpi.c | 15 ++++++----
> > include/linux/platform_profile.h | 1 +
> > 12 files changed, 137 insertions(+), 71 deletions(-)
> >
> > diff --git a/drivers/acpi/platform_profile.c b/drivers/acpi/platform_profile.c
> > index 440654e21620..34e22b006ccc 100644
> > --- a/drivers/acpi/platform_profile.c
> > +++ b/drivers/acpi/platform_profile.c
> > @@ -466,12 +466,21 @@ int platform_profile_register(struct platform_profile_handler *pprof, void *drvd
> > int err;
> > /* Sanity check the profile handler */
> > - if (!pprof || bitmap_empty(pprof->choices, PLATFORM_PROFILE_LAST) ||
> > - !pprof->ops->profile_set || !pprof->ops->profile_get) {
> > + if (!pprof || !pprof->ops->profile_set || !pprof->ops->profile_get ||
> > + !pprof->ops->probe) {
> > pr_err("platform_profile: handler is invalid\n");
> > return -EINVAL;
> > }
> > + err = pprof->ops->probe(drvdata, pprof->choices);
> > + if (err < 0)
>
> Any particular reason to specifically look for less than zero? Did you want
> to have the probe() return something positive in some circumstances?
>
> If not I think this should be fine:
>
> if (err)
Ack.
I did it out of habit.
>
> > + return err;
> > +
> > + if (bitmap_empty(pprof->choices, PLATFORM_PROFILE_LAST)) {
> > + pr_err("platform_profile: no available profiles\n");
>
> Doesn't pr_fmt handle the prefix?
This file doesn't have pr_fmt :( I'll log it with dev_err and add a
pr_fmt in a separate patch.
Thank you again for reviewing this!
If Ilpo doesn't have any comments I'll send a v3 right away.
~ Kurt
>
> > + return -EINVAL;
> > + }
> > +
> > guard(mutex)(&profile_lock);
> > /* create class interface for individual handler */
> > diff --git a/drivers/platform/surface/surface_platform_profile.c b/drivers/platform/surface/surface_platform_profile.c
> > index 76967bfeeef8..48cfe9cb89c8 100644
> > --- a/drivers/platform/surface/surface_platform_profile.c
> > +++ b/drivers/platform/surface/surface_platform_profile.c
> > @@ -201,7 +201,18 @@ static int ssam_platform_profile_set(struct device *dev,
> > return tp;
> > }
> > +static int ssam_platform_profile_probe(void *drvdata, unsigned long *choices)
> > +{
> > + set_bit(PLATFORM_PROFILE_LOW_POWER, choices);
> > + set_bit(PLATFORM_PROFILE_BALANCED, choices);
> > + set_bit(PLATFORM_PROFILE_BALANCED_PERFORMANCE, choices);
> > + set_bit(PLATFORM_PROFILE_PERFORMANCE, choices);
> > +
> > + return 0;
> > +}
> > +
> > static const struct platform_profile_ops ssam_platform_profile_ops = {
> > + .probe = ssam_platform_profile_probe,
> > .profile_get = ssam_platform_profile_get,
> > .profile_set = ssam_platform_profile_set,
> > };
> > @@ -223,11 +234,6 @@ static int surface_platform_profile_probe(struct ssam_device *sdev)
> > tpd->has_fan = device_property_read_bool(&sdev->dev, "has_fan");
> > - set_bit(PLATFORM_PROFILE_LOW_POWER, tpd->handler.choices);
> > - set_bit(PLATFORM_PROFILE_BALANCED, tpd->handler.choices);
> > - set_bit(PLATFORM_PROFILE_BALANCED_PERFORMANCE, tpd->handler.choices);
> > - set_bit(PLATFORM_PROFILE_PERFORMANCE, tpd->handler.choices);
> > -
> > return platform_profile_register(&tpd->handler, tpd);
> > }
> > diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c
> > index 91ae48adf6cf..6953e36dbfde 100644
> > --- a/drivers/platform/x86/acer-wmi.c
> > +++ b/drivers/platform/x86/acer-wmi.c
> > @@ -1916,7 +1916,20 @@ acer_predator_v4_platform_profile_set(struct device *dev,
> > return 0;
> > }
> > +static int
> > +acer_predator_v4_platform_profile_probe(void *drvdata, unsigned long *choices)
> > +{
> > + set_bit(PLATFORM_PROFILE_PERFORMANCE, choices);
> > + set_bit(PLATFORM_PROFILE_BALANCED_PERFORMANCE, choices);
> > + set_bit(PLATFORM_PROFILE_BALANCED, choices);
> > + set_bit(PLATFORM_PROFILE_QUIET, choices);
> > + set_bit(PLATFORM_PROFILE_LOW_POWER, choices);
> > +
> > + return 0;
> > +}
> > +
> > static const struct platform_profile_ops acer_predator_v4_platform_profile_ops = {
> > + .probe = acer_predator_v4_platform_profile_probe,
> > .profile_get = acer_predator_v4_platform_profile_get,
> > .profile_set = acer_predator_v4_platform_profile_set,
> > };
> > @@ -1931,17 +1944,6 @@ static int acer_platform_profile_setup(struct platform_device *device)
> > platform_profile_handler.ops =
> > &acer_predator_v4_platform_profile_ops;
> > - set_bit(PLATFORM_PROFILE_PERFORMANCE,
> > - platform_profile_handler.choices);
> > - set_bit(PLATFORM_PROFILE_BALANCED_PERFORMANCE,
> > - platform_profile_handler.choices);
> > - set_bit(PLATFORM_PROFILE_BALANCED,
> > - platform_profile_handler.choices);
> > - set_bit(PLATFORM_PROFILE_QUIET,
> > - platform_profile_handler.choices);
> > - set_bit(PLATFORM_PROFILE_LOW_POWER,
> > - platform_profile_handler.choices);
> > -
> > err = platform_profile_register(&platform_profile_handler, NULL);
> > if (err)
> > return err;
> > diff --git a/drivers/platform/x86/amd/pmf/sps.c b/drivers/platform/x86/amd/pmf/sps.c
> > index 6ae82ae86d22..e710405b581f 100644
> > --- a/drivers/platform/x86/amd/pmf/sps.c
> > +++ b/drivers/platform/x86/amd/pmf/sps.c
> > @@ -387,7 +387,17 @@ static int amd_pmf_profile_set(struct device *dev,
> > return 0;
> > }
> > +static int amd_pmf_profile_probe(void *drvdata, unsigned long *choices)
> > +{
> > + set_bit(PLATFORM_PROFILE_LOW_POWER, choices);
> > + set_bit(PLATFORM_PROFILE_BALANCED, choices);
> > + set_bit(PLATFORM_PROFILE_PERFORMANCE, choices);
> > +
> > + return 0;
> > +}
> > +
> > static const struct platform_profile_ops amd_pmf_profile_ops = {
> > + .probe = amd_pmf_profile_probe,
> > .profile_get = amd_pmf_profile_get,
> > .profile_set = amd_pmf_profile_set,
> > };
> > @@ -414,11 +424,6 @@ int amd_pmf_init_sps(struct amd_pmf_dev *dev)
> > dev->pprof.dev = dev->dev;
> > dev->pprof.ops = &amd_pmf_profile_ops;
> > - /* Setup supported modes */
> > - set_bit(PLATFORM_PROFILE_LOW_POWER, dev->pprof.choices);
> > - set_bit(PLATFORM_PROFILE_BALANCED, dev->pprof.choices);
> > - set_bit(PLATFORM_PROFILE_PERFORMANCE, dev->pprof.choices);
> > -
> > /* Create platform_profile structure and register */
> > err = platform_profile_register(&dev->pprof, dev);
> > if (err)
> > diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
> > index d88860dd028b..3d77f7454953 100644
> > --- a/drivers/platform/x86/asus-wmi.c
> > +++ b/drivers/platform/x86/asus-wmi.c
> > @@ -3852,7 +3852,17 @@ static int asus_wmi_platform_profile_set(struct device *dev,
> > return throttle_thermal_policy_write(asus);
> > }
> > +static int asus_wmi_platform_profile_probe(void *drvdata, unsigned long *choices)
> > +{
> > + set_bit(PLATFORM_PROFILE_QUIET, choices);
> > + set_bit(PLATFORM_PROFILE_BALANCED, choices);
> > + set_bit(PLATFORM_PROFILE_PERFORMANCE, choices);
> > +
> > + return 0;
> > +}
> > +
> > static const struct platform_profile_ops asus_wmi_platform_profile_ops = {
> > + .probe = asus_wmi_platform_profile_probe,
> > .profile_get = asus_wmi_platform_profile_get,
> > .profile_set = asus_wmi_platform_profile_set,
> > };
> > @@ -3885,12 +3895,6 @@ static int platform_profile_setup(struct asus_wmi *asus)
> > asus->platform_profile_handler.dev = dev;
> > asus->platform_profile_handler.ops = &asus_wmi_platform_profile_ops;
> > - set_bit(PLATFORM_PROFILE_QUIET, asus->platform_profile_handler.choices);
> > - set_bit(PLATFORM_PROFILE_BALANCED,
> > - asus->platform_profile_handler.choices);
> > - set_bit(PLATFORM_PROFILE_PERFORMANCE,
> > - asus->platform_profile_handler.choices);
> > -
> > err = platform_profile_register(&asus->platform_profile_handler, asus);
> > if (err == -EEXIST) {
> > pr_warn("%s, a platform_profile handler is already registered\n", __func__);
> > diff --git a/drivers/platform/x86/dell/alienware-wmi.c b/drivers/platform/x86/dell/alienware-wmi.c
> > index f7a854d40575..0146d2f93be6 100644
> > --- a/drivers/platform/x86/dell/alienware-wmi.c
> > +++ b/drivers/platform/x86/dell/alienware-wmi.c
> > @@ -1078,12 +1078,7 @@ static int thermal_profile_set(struct device *dev,
> > return wmax_thermal_control(supported_thermal_profiles[profile]);
> > }
> > -static const struct platform_profile_ops awcc_platform_profile_ops = {
> > - .profile_get = thermal_profile_get,
> > - .profile_set = thermal_profile_set,
> > -};
> > -
> > -static int create_thermal_profile(struct platform_device *platform_device)
> > +static int thermal_profile_probe(void *drvdata, unsigned long *choices)
> > {
> > enum platform_profile_option profile;
> > enum wmax_thermal_mode mode;
> > @@ -1116,19 +1111,30 @@ static int create_thermal_profile(struct platform_device *platform_device)
> > profile = wmax_mode_to_platform_profile[mode];
> > supported_thermal_profiles[profile] = out_data;
> > - set_bit(profile, pp_handler.choices);
> > + set_bit(profile, choices);
> > }
> > - if (bitmap_empty(pp_handler.choices, PLATFORM_PROFILE_LAST))
> > + if (bitmap_empty(choices, PLATFORM_PROFILE_LAST))
> > return -ENODEV;
> > if (quirks->gmode) {
> > supported_thermal_profiles[PLATFORM_PROFILE_PERFORMANCE] =
> > WMAX_THERMAL_MODE_GMODE;
> > - set_bit(PLATFORM_PROFILE_PERFORMANCE, pp_handler.choices);
> > + set_bit(PLATFORM_PROFILE_PERFORMANCE, choices);
> > }
> > + return 0;
> > +}
> > +
> > +static const struct platform_profile_ops awcc_platform_profile_ops = {
> > + .probe = thermal_profile_probe,
> > + .profile_get = thermal_profile_get,
> > + .profile_set = thermal_profile_set,
> > +};
> > +
> > +static int create_thermal_profile(struct platform_device *platform_device)
> > +{
> > pp_handler.name = "alienware-wmi";
> > pp_handler.dev = &platform_device->dev;
> > pp_handler.ops = &awcc_platform_profile_ops;
> > diff --git a/drivers/platform/x86/dell/dell-pc.c b/drivers/platform/x86/dell/dell-pc.c
> > index 9010a231f209..32b3be0723f8 100644
> > --- a/drivers/platform/x86/dell/dell-pc.c
> > +++ b/drivers/platform/x86/dell/dell-pc.c
> > @@ -24,6 +24,7 @@
> > #include "dell-smbios.h"
> > static struct platform_device *platform_device;
> > +static int supported_modes;
> > static const struct dmi_system_id dell_device_table[] __initconst = {
> > {
> > @@ -231,7 +232,22 @@ static int thermal_platform_profile_get(struct device *dev,
> > return 0;
> > }
> > +static int thermal_platform_profile_probe(void *drvdata, unsigned long *choices)
> > +{
> > + if (supported_modes & DELL_QUIET)
> > + set_bit(PLATFORM_PROFILE_QUIET, choices);
> > + if (supported_modes & DELL_COOL_BOTTOM)
> > + set_bit(PLATFORM_PROFILE_COOL, choices);
> > + if (supported_modes & DELL_BALANCED)
> > + set_bit(PLATFORM_PROFILE_BALANCED, choices);
> > + if (supported_modes & DELL_PERFORMANCE)
> > + set_bit(PLATFORM_PROFILE_PERFORMANCE, choices);
> > +
> > + return 0;
> > +}
> > +
> > static const struct platform_profile_ops dell_pc_platform_profile_ops = {
> > + .probe = thermal_platform_profile_probe,
> > .profile_get = thermal_platform_profile_get,
> > .profile_set = thermal_platform_profile_set,
> > };
> > @@ -239,7 +255,6 @@ static const struct platform_profile_ops dell_pc_platform_profile_ops = {
> > static int thermal_init(void)
> > {
> > int ret;
> > - int supported_modes;
> > /* If thermal commands are not supported, exit without error */
> > if (!dell_smbios_class_is_supported(CLASS_INFO))
> > @@ -265,15 +280,6 @@ static int thermal_init(void)
> > thermal_handler->dev = &platform_device->dev;
> > thermal_handler->ops = &dell_pc_platform_profile_ops;
> > - if (supported_modes & DELL_QUIET)
> > - set_bit(PLATFORM_PROFILE_QUIET, thermal_handler->choices);
> > - if (supported_modes & DELL_COOL_BOTTOM)
> > - set_bit(PLATFORM_PROFILE_COOL, thermal_handler->choices);
> > - if (supported_modes & DELL_BALANCED)
> > - set_bit(PLATFORM_PROFILE_BALANCED, thermal_handler->choices);
> > - if (supported_modes & DELL_PERFORMANCE)
> > - set_bit(PLATFORM_PROFILE_PERFORMANCE, thermal_handler->choices);
> > -
> > /* Clean up if failed */
> > ret = platform_profile_register(thermal_handler, NULL);
> > if (ret)
> > diff --git a/drivers/platform/x86/hp/hp-wmi.c b/drivers/platform/x86/hp/hp-wmi.c
> > index 60328b35be74..75bcd8460e7c 100644
> > --- a/drivers/platform/x86/hp/hp-wmi.c
> > +++ b/drivers/platform/x86/hp/hp-wmi.c
> > @@ -1488,6 +1488,23 @@ static int platform_profile_victus_set(struct device *dev,
> > return 0;
> > }
> > +static int hp_wmi_platform_profile_probe(void *drvdata, unsigned long *choices)
> > +{
> > + if (is_omen_thermal_profile()) {
> > + set_bit(PLATFORM_PROFILE_COOL, choices);
> > + } else if (is_victus_thermal_profile()) {
> > + set_bit(PLATFORM_PROFILE_QUIET, choices);
> > + } else {
> > + set_bit(PLATFORM_PROFILE_QUIET, choices);
> > + set_bit(PLATFORM_PROFILE_COOL, choices);
> > + }
> > +
> > + set_bit(PLATFORM_PROFILE_BALANCED, choices);
> > + set_bit(PLATFORM_PROFILE_PERFORMANCE, choices);
> > +
> > + return 0;
> > +}
> > +
> > static int omen_powersource_event(struct notifier_block *nb,
> > unsigned long value,
> > void *data)
> > @@ -1566,16 +1583,19 @@ static inline void omen_unregister_powersource_event_handler(void)
> > }
> > static const struct platform_profile_ops platform_profile_omen_ops = {
> > + .probe = hp_wmi_platform_profile_probe,
> > .profile_get = platform_profile_omen_get,
> > .profile_set = platform_profile_omen_set,
> > };
> > static const struct platform_profile_ops platform_profile_victus_ops = {
> > + .probe = hp_wmi_platform_profile_probe,
> > .profile_get = platform_profile_victus_get,
> > .profile_set = platform_profile_victus_set,
> > };
> > static const struct platform_profile_ops hp_wmi_platform_profile_ops = {
> > + .probe = hp_wmi_platform_profile_probe,
> > .profile_get = hp_wmi_platform_profile_get,
> > .profile_set = hp_wmi_platform_profile_set,
> > };
> > @@ -1598,8 +1618,6 @@ static int thermal_profile_setup(struct platform_device *device)
> > return err;
> > platform_profile_handler.ops = &platform_profile_omen_ops;
> > -
> > - set_bit(PLATFORM_PROFILE_COOL, platform_profile_handler.choices);
> > } else if (is_victus_thermal_profile()) {
> > err = platform_profile_victus_get_ec(&active_platform_profile);
> > if (err < 0)
> > @@ -1614,8 +1632,6 @@ static int thermal_profile_setup(struct platform_device *device)
> > return err;
> > platform_profile_handler.ops = &platform_profile_victus_ops;
> > -
> > - set_bit(PLATFORM_PROFILE_QUIET, platform_profile_handler.choices);
> > } else {
> > tp = thermal_profile_get();
> > @@ -1631,15 +1647,10 @@ static int thermal_profile_setup(struct platform_device *device)
> > return err;
> > platform_profile_handler.ops = &hp_wmi_platform_profile_ops;
> > -
> > - set_bit(PLATFORM_PROFILE_QUIET, platform_profile_handler.choices);
> > - set_bit(PLATFORM_PROFILE_COOL, platform_profile_handler.choices);
> > }
> > platform_profile_handler.name = "hp-wmi";
> > platform_profile_handler.dev = &device->dev;
> > - set_bit(PLATFORM_PROFILE_BALANCED, platform_profile_handler.choices);
> > - set_bit(PLATFORM_PROFILE_PERFORMANCE, platform_profile_handler.choices);
> > err = platform_profile_register(&platform_profile_handler, NULL);
> > if (err)
> > diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c
> > index 96e99513b0b5..050919a28d2b 100644
> > --- a/drivers/platform/x86/ideapad-laptop.c
> > +++ b/drivers/platform/x86/ideapad-laptop.c
> > @@ -1023,6 +1023,15 @@ static int dytc_profile_set(struct device *dev,
> > return -EINTR;
> > }
> > +static int dytc_profile_probe(void *drvdata, unsigned long *choices)
> > +{
> > + set_bit(PLATFORM_PROFILE_LOW_POWER, choices);
> > + set_bit(PLATFORM_PROFILE_BALANCED, choices);
> > + set_bit(PLATFORM_PROFILE_PERFORMANCE, choices);
> > +
> > + return 0;
> > +}
> > +
> > static void dytc_profile_refresh(struct ideapad_private *priv)
> > {
> > enum platform_profile_option profile;
> > @@ -1064,6 +1073,7 @@ static const struct dmi_system_id ideapad_dytc_v4_allow_table[] = {
> > };
> > static const struct platform_profile_ops dytc_profile_ops = {
> > + .probe = dytc_profile_probe,
> > .profile_get = dytc_profile_get,
> > .profile_set = dytc_profile_set,
> > };
> > @@ -1112,11 +1122,6 @@ static int ideapad_dytc_profile_init(struct ideapad_private *priv)
> > priv->dytc->priv = priv;
> > priv->dytc->pprof.ops = &dytc_profile_ops;
> > - /* Setup supported modes */
> > - set_bit(PLATFORM_PROFILE_LOW_POWER, priv->dytc->pprof.choices);
> > - set_bit(PLATFORM_PROFILE_BALANCED, priv->dytc->pprof.choices);
> > - set_bit(PLATFORM_PROFILE_PERFORMANCE, priv->dytc->pprof.choices);
> > -
> > /* Create platform_profile structure and register */
> > err = platform_profile_register(&priv->dytc->pprof, &priv->dytc);
> > if (err)
> > diff --git a/drivers/platform/x86/inspur_platform_profile.c b/drivers/platform/x86/inspur_platform_profile.c
> > index d0a8e4eebffa..06df3aae9a56 100644
> > --- a/drivers/platform/x86/inspur_platform_profile.c
> > +++ b/drivers/platform/x86/inspur_platform_profile.c
> > @@ -164,7 +164,17 @@ static int inspur_platform_profile_get(struct device *dev,
> > return 0;
> > }
> > +static int inspur_platform_profile_probe(void *drvdata, unsigned long *choices)
> > +{
> > + set_bit(PLATFORM_PROFILE_LOW_POWER, choices);
> > + set_bit(PLATFORM_PROFILE_BALANCED, choices);
> > + set_bit(PLATFORM_PROFILE_PERFORMANCE, choices);
> > +
> > + return 0;
> > +}
> > +
> > static const struct platform_profile_ops inspur_platform_profile_ops = {
> > + .probe = inspur_platform_profile_probe,
> > .profile_get = inspur_platform_profile_get,
> > .profile_set = inspur_platform_profile_set,
> > };
> > @@ -184,10 +194,6 @@ static int inspur_wmi_probe(struct wmi_device *wdev, const void *context)
> > priv->handler.dev = &wdev->dev;
> > priv->handler.ops = &inspur_platform_profile_ops;
> > - set_bit(PLATFORM_PROFILE_LOW_POWER, priv->handler.choices);
> > - set_bit(PLATFORM_PROFILE_BALANCED, priv->handler.choices);
> > - set_bit(PLATFORM_PROFILE_PERFORMANCE, priv->handler.choices);
> > -
> > return platform_profile_register(&priv->handler, priv);
> > }
> > diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
> > index 9978fd36a3d1..5c250867678f 100644
> > --- a/drivers/platform/x86/thinkpad_acpi.c
> > +++ b/drivers/platform/x86/thinkpad_acpi.c
> > @@ -10538,7 +10538,17 @@ static int dytc_profile_set(struct device *dev,
> > return err;
> > }
> > +static int dytc_profile_probe(void *drvdata, unsigned long *choices)
> > +{
> > + set_bit(PLATFORM_PROFILE_LOW_POWER, choices);
> > + set_bit(PLATFORM_PROFILE_BALANCED, choices);
> > + set_bit(PLATFORM_PROFILE_PERFORMANCE, choices);
> > +
> > + return 0;
> > +}
> > +
> > static const struct platform_profile_ops dytc_profile_ops = {
> > + .probe = dytc_profile_probe,
> > .profile_get = dytc_profile_get,
> > .profile_set = dytc_profile_set,
> > };
> > @@ -10584,11 +10594,6 @@ static int tpacpi_dytc_profile_init(struct ibm_init_struct *iibm)
> > {
> > int err, output;
> > - /* Setup supported modes */
> > - set_bit(PLATFORM_PROFILE_LOW_POWER, dytc_profile.choices);
> > - set_bit(PLATFORM_PROFILE_BALANCED, dytc_profile.choices);
> > - set_bit(PLATFORM_PROFILE_PERFORMANCE, dytc_profile.choices);
> > -
> > err = dytc_command(DYTC_CMD_QUERY, &output);
> > if (err)
> > return err;
> > diff --git a/include/linux/platform_profile.h b/include/linux/platform_profile.h
> > index 6013c05d7b86..5ad1ab7b75e4 100644
> > --- a/include/linux/platform_profile.h
> > +++ b/include/linux/platform_profile.h
> > @@ -31,6 +31,7 @@ enum platform_profile_option {
> > struct platform_profile_handler;
> > struct platform_profile_ops {
> > + int (*probe)(void *drvdata, unsigned long *choices);
> > int (*profile_get)(struct device *dev, enum platform_profile_option *profile);
> > int (*profile_set)(struct device *dev, enum platform_profile_option profile);
> > };
>
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH v2 05/18] ACPI: platform_profile: Add `probe` to platform_profile_ops
2025-01-14 16:31 ` Kurt Borja
@ 2025-01-14 16:36 ` Mario Limonciello
0 siblings, 0 replies; 33+ messages in thread
From: Mario Limonciello @ 2025-01-14 16:36 UTC (permalink / raw)
To: Kurt Borja
Cc: platform-driver-x86, Rafael J. Wysocki, Len Brown, linux-acpi,
linux-kernel, Armin Wolf, Joshua Grisham, Derek J. Clark,
Ilpo Järvinen, Hans de Goede, Maximilian Luz, Lee, Chun-Yi,
Shyam Sundar S K, Corentin Chary, Luke D. Jones, Lyndon Sanche,
Ike Panhc, Henrique de Moraes Holschuh, Mark Pearson,
Alexis Belmonte, Ai Chao, Gergo Koteles, Dell.Client.Kernel,
ibm-acpi-devel
On 1/14/2025 10:31, Kurt Borja wrote:
> Hi Mario,
>
> On Tue, Jan 14, 2025 at 10:20:15AM -0600, Mario Limonciello wrote:
>> On 1/14/2025 09:37, Kurt Borja wrote:
>>> Add a `probe` callback to platform_profile_ops, which lets drivers
>>> initialize the choices member manually.
>>>
>>> Signed-off-by: Kurt Borja <kuurtb@gmail.com>
>>> ---
>>> drivers/acpi/platform_profile.c | 13 +++++++--
>>> .../surface/surface_platform_profile.c | 16 ++++++----
>>> drivers/platform/x86/acer-wmi.c | 24 ++++++++-------
>>> drivers/platform/x86/amd/pmf/sps.c | 15 ++++++----
>>> drivers/platform/x86/asus-wmi.c | 16 ++++++----
>>> drivers/platform/x86/dell/alienware-wmi.c | 24 +++++++++------
>>> drivers/platform/x86/dell/dell-pc.c | 26 ++++++++++-------
>>> drivers/platform/x86/hp/hp-wmi.c | 29 +++++++++++++------
>>> drivers/platform/x86/ideapad-laptop.c | 15 ++++++----
>>> .../platform/x86/inspur_platform_profile.c | 14 ++++++---
>>> drivers/platform/x86/thinkpad_acpi.c | 15 ++++++----
>>> include/linux/platform_profile.h | 1 +
>>> 12 files changed, 137 insertions(+), 71 deletions(-)
>>>
>>> diff --git a/drivers/acpi/platform_profile.c b/drivers/acpi/platform_profile.c
>>> index 440654e21620..34e22b006ccc 100644
>>> --- a/drivers/acpi/platform_profile.c
>>> +++ b/drivers/acpi/platform_profile.c
>>> @@ -466,12 +466,21 @@ int platform_profile_register(struct platform_profile_handler *pprof, void *drvd
>>> int err;
>>> /* Sanity check the profile handler */
>>> - if (!pprof || bitmap_empty(pprof->choices, PLATFORM_PROFILE_LAST) ||
>>> - !pprof->ops->profile_set || !pprof->ops->profile_get) {
>>> + if (!pprof || !pprof->ops->profile_set || !pprof->ops->profile_get ||
>>> + !pprof->ops->probe) {
>>> pr_err("platform_profile: handler is invalid\n");
>>> return -EINVAL;
>>> }
>>> + err = pprof->ops->probe(drvdata, pprof->choices);
>>> + if (err < 0)
>>
>> Any particular reason to specifically look for less than zero? Did you want
>> to have the probe() return something positive in some circumstances?
>>
>> If not I think this should be fine:
>>
>> if (err)
>
> Ack.
>
> I did it out of habit.
>
>>
>>> + return err;
>>> +
>>> + if (bitmap_empty(pprof->choices, PLATFORM_PROFILE_LAST)) {
>>> + pr_err("platform_profile: no available profiles\n");
>>
>> Doesn't pr_fmt handle the prefix?
>
> This file doesn't have pr_fmt :( I'll log it with dev_err and add a
> pr_fmt in a separate patch.
>
Ooph! There might be some other cases the prefix needs to be fixed then
too. I noticed it in use from some existing code too.
> Thank you again for reviewing this!
Sure!
>
> If Ilpo doesn't have any comments I'll send a v3 right away.
>
> ~ Kurt
>
>>
>>> + return -EINVAL;
>>> + }
>>> +
>>> guard(mutex)(&profile_lock);
>>> /* create class interface for individual handler */
>>> diff --git a/drivers/platform/surface/surface_platform_profile.c b/drivers/platform/surface/surface_platform_profile.c
>>> index 76967bfeeef8..48cfe9cb89c8 100644
>>> --- a/drivers/platform/surface/surface_platform_profile.c
>>> +++ b/drivers/platform/surface/surface_platform_profile.c
>>> @@ -201,7 +201,18 @@ static int ssam_platform_profile_set(struct device *dev,
>>> return tp;
>>> }
>>> +static int ssam_platform_profile_probe(void *drvdata, unsigned long *choices)
>>> +{
>>> + set_bit(PLATFORM_PROFILE_LOW_POWER, choices);
>>> + set_bit(PLATFORM_PROFILE_BALANCED, choices);
>>> + set_bit(PLATFORM_PROFILE_BALANCED_PERFORMANCE, choices);
>>> + set_bit(PLATFORM_PROFILE_PERFORMANCE, choices);
>>> +
>>> + return 0;
>>> +}
>>> +
>>> static const struct platform_profile_ops ssam_platform_profile_ops = {
>>> + .probe = ssam_platform_profile_probe,
>>> .profile_get = ssam_platform_profile_get,
>>> .profile_set = ssam_platform_profile_set,
>>> };
>>> @@ -223,11 +234,6 @@ static int surface_platform_profile_probe(struct ssam_device *sdev)
>>> tpd->has_fan = device_property_read_bool(&sdev->dev, "has_fan");
>>> - set_bit(PLATFORM_PROFILE_LOW_POWER, tpd->handler.choices);
>>> - set_bit(PLATFORM_PROFILE_BALANCED, tpd->handler.choices);
>>> - set_bit(PLATFORM_PROFILE_BALANCED_PERFORMANCE, tpd->handler.choices);
>>> - set_bit(PLATFORM_PROFILE_PERFORMANCE, tpd->handler.choices);
>>> -
>>> return platform_profile_register(&tpd->handler, tpd);
>>> }
>>> diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c
>>> index 91ae48adf6cf..6953e36dbfde 100644
>>> --- a/drivers/platform/x86/acer-wmi.c
>>> +++ b/drivers/platform/x86/acer-wmi.c
>>> @@ -1916,7 +1916,20 @@ acer_predator_v4_platform_profile_set(struct device *dev,
>>> return 0;
>>> }
>>> +static int
>>> +acer_predator_v4_platform_profile_probe(void *drvdata, unsigned long *choices)
>>> +{
>>> + set_bit(PLATFORM_PROFILE_PERFORMANCE, choices);
>>> + set_bit(PLATFORM_PROFILE_BALANCED_PERFORMANCE, choices);
>>> + set_bit(PLATFORM_PROFILE_BALANCED, choices);
>>> + set_bit(PLATFORM_PROFILE_QUIET, choices);
>>> + set_bit(PLATFORM_PROFILE_LOW_POWER, choices);
>>> +
>>> + return 0;
>>> +}
>>> +
>>> static const struct platform_profile_ops acer_predator_v4_platform_profile_ops = {
>>> + .probe = acer_predator_v4_platform_profile_probe,
>>> .profile_get = acer_predator_v4_platform_profile_get,
>>> .profile_set = acer_predator_v4_platform_profile_set,
>>> };
>>> @@ -1931,17 +1944,6 @@ static int acer_platform_profile_setup(struct platform_device *device)
>>> platform_profile_handler.ops =
>>> &acer_predator_v4_platform_profile_ops;
>>> - set_bit(PLATFORM_PROFILE_PERFORMANCE,
>>> - platform_profile_handler.choices);
>>> - set_bit(PLATFORM_PROFILE_BALANCED_PERFORMANCE,
>>> - platform_profile_handler.choices);
>>> - set_bit(PLATFORM_PROFILE_BALANCED,
>>> - platform_profile_handler.choices);
>>> - set_bit(PLATFORM_PROFILE_QUIET,
>>> - platform_profile_handler.choices);
>>> - set_bit(PLATFORM_PROFILE_LOW_POWER,
>>> - platform_profile_handler.choices);
>>> -
>>> err = platform_profile_register(&platform_profile_handler, NULL);
>>> if (err)
>>> return err;
>>> diff --git a/drivers/platform/x86/amd/pmf/sps.c b/drivers/platform/x86/amd/pmf/sps.c
>>> index 6ae82ae86d22..e710405b581f 100644
>>> --- a/drivers/platform/x86/amd/pmf/sps.c
>>> +++ b/drivers/platform/x86/amd/pmf/sps.c
>>> @@ -387,7 +387,17 @@ static int amd_pmf_profile_set(struct device *dev,
>>> return 0;
>>> }
>>> +static int amd_pmf_profile_probe(void *drvdata, unsigned long *choices)
>>> +{
>>> + set_bit(PLATFORM_PROFILE_LOW_POWER, choices);
>>> + set_bit(PLATFORM_PROFILE_BALANCED, choices);
>>> + set_bit(PLATFORM_PROFILE_PERFORMANCE, choices);
>>> +
>>> + return 0;
>>> +}
>>> +
>>> static const struct platform_profile_ops amd_pmf_profile_ops = {
>>> + .probe = amd_pmf_profile_probe,
>>> .profile_get = amd_pmf_profile_get,
>>> .profile_set = amd_pmf_profile_set,
>>> };
>>> @@ -414,11 +424,6 @@ int amd_pmf_init_sps(struct amd_pmf_dev *dev)
>>> dev->pprof.dev = dev->dev;
>>> dev->pprof.ops = &amd_pmf_profile_ops;
>>> - /* Setup supported modes */
>>> - set_bit(PLATFORM_PROFILE_LOW_POWER, dev->pprof.choices);
>>> - set_bit(PLATFORM_PROFILE_BALANCED, dev->pprof.choices);
>>> - set_bit(PLATFORM_PROFILE_PERFORMANCE, dev->pprof.choices);
>>> -
>>> /* Create platform_profile structure and register */
>>> err = platform_profile_register(&dev->pprof, dev);
>>> if (err)
>>> diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
>>> index d88860dd028b..3d77f7454953 100644
>>> --- a/drivers/platform/x86/asus-wmi.c
>>> +++ b/drivers/platform/x86/asus-wmi.c
>>> @@ -3852,7 +3852,17 @@ static int asus_wmi_platform_profile_set(struct device *dev,
>>> return throttle_thermal_policy_write(asus);
>>> }
>>> +static int asus_wmi_platform_profile_probe(void *drvdata, unsigned long *choices)
>>> +{
>>> + set_bit(PLATFORM_PROFILE_QUIET, choices);
>>> + set_bit(PLATFORM_PROFILE_BALANCED, choices);
>>> + set_bit(PLATFORM_PROFILE_PERFORMANCE, choices);
>>> +
>>> + return 0;
>>> +}
>>> +
>>> static const struct platform_profile_ops asus_wmi_platform_profile_ops = {
>>> + .probe = asus_wmi_platform_profile_probe,
>>> .profile_get = asus_wmi_platform_profile_get,
>>> .profile_set = asus_wmi_platform_profile_set,
>>> };
>>> @@ -3885,12 +3895,6 @@ static int platform_profile_setup(struct asus_wmi *asus)
>>> asus->platform_profile_handler.dev = dev;
>>> asus->platform_profile_handler.ops = &asus_wmi_platform_profile_ops;
>>> - set_bit(PLATFORM_PROFILE_QUIET, asus->platform_profile_handler.choices);
>>> - set_bit(PLATFORM_PROFILE_BALANCED,
>>> - asus->platform_profile_handler.choices);
>>> - set_bit(PLATFORM_PROFILE_PERFORMANCE,
>>> - asus->platform_profile_handler.choices);
>>> -
>>> err = platform_profile_register(&asus->platform_profile_handler, asus);
>>> if (err == -EEXIST) {
>>> pr_warn("%s, a platform_profile handler is already registered\n", __func__);
>>> diff --git a/drivers/platform/x86/dell/alienware-wmi.c b/drivers/platform/x86/dell/alienware-wmi.c
>>> index f7a854d40575..0146d2f93be6 100644
>>> --- a/drivers/platform/x86/dell/alienware-wmi.c
>>> +++ b/drivers/platform/x86/dell/alienware-wmi.c
>>> @@ -1078,12 +1078,7 @@ static int thermal_profile_set(struct device *dev,
>>> return wmax_thermal_control(supported_thermal_profiles[profile]);
>>> }
>>> -static const struct platform_profile_ops awcc_platform_profile_ops = {
>>> - .profile_get = thermal_profile_get,
>>> - .profile_set = thermal_profile_set,
>>> -};
>>> -
>>> -static int create_thermal_profile(struct platform_device *platform_device)
>>> +static int thermal_profile_probe(void *drvdata, unsigned long *choices)
>>> {
>>> enum platform_profile_option profile;
>>> enum wmax_thermal_mode mode;
>>> @@ -1116,19 +1111,30 @@ static int create_thermal_profile(struct platform_device *platform_device)
>>> profile = wmax_mode_to_platform_profile[mode];
>>> supported_thermal_profiles[profile] = out_data;
>>> - set_bit(profile, pp_handler.choices);
>>> + set_bit(profile, choices);
>>> }
>>> - if (bitmap_empty(pp_handler.choices, PLATFORM_PROFILE_LAST))
>>> + if (bitmap_empty(choices, PLATFORM_PROFILE_LAST))
>>> return -ENODEV;
>>> if (quirks->gmode) {
>>> supported_thermal_profiles[PLATFORM_PROFILE_PERFORMANCE] =
>>> WMAX_THERMAL_MODE_GMODE;
>>> - set_bit(PLATFORM_PROFILE_PERFORMANCE, pp_handler.choices);
>>> + set_bit(PLATFORM_PROFILE_PERFORMANCE, choices);
>>> }
>>> + return 0;
>>> +}
>>> +
>>> +static const struct platform_profile_ops awcc_platform_profile_ops = {
>>> + .probe = thermal_profile_probe,
>>> + .profile_get = thermal_profile_get,
>>> + .profile_set = thermal_profile_set,
>>> +};
>>> +
>>> +static int create_thermal_profile(struct platform_device *platform_device)
>>> +{
>>> pp_handler.name = "alienware-wmi";
>>> pp_handler.dev = &platform_device->dev;
>>> pp_handler.ops = &awcc_platform_profile_ops;
>>> diff --git a/drivers/platform/x86/dell/dell-pc.c b/drivers/platform/x86/dell/dell-pc.c
>>> index 9010a231f209..32b3be0723f8 100644
>>> --- a/drivers/platform/x86/dell/dell-pc.c
>>> +++ b/drivers/platform/x86/dell/dell-pc.c
>>> @@ -24,6 +24,7 @@
>>> #include "dell-smbios.h"
>>> static struct platform_device *platform_device;
>>> +static int supported_modes;
>>> static const struct dmi_system_id dell_device_table[] __initconst = {
>>> {
>>> @@ -231,7 +232,22 @@ static int thermal_platform_profile_get(struct device *dev,
>>> return 0;
>>> }
>>> +static int thermal_platform_profile_probe(void *drvdata, unsigned long *choices)
>>> +{
>>> + if (supported_modes & DELL_QUIET)
>>> + set_bit(PLATFORM_PROFILE_QUIET, choices);
>>> + if (supported_modes & DELL_COOL_BOTTOM)
>>> + set_bit(PLATFORM_PROFILE_COOL, choices);
>>> + if (supported_modes & DELL_BALANCED)
>>> + set_bit(PLATFORM_PROFILE_BALANCED, choices);
>>> + if (supported_modes & DELL_PERFORMANCE)
>>> + set_bit(PLATFORM_PROFILE_PERFORMANCE, choices);
>>> +
>>> + return 0;
>>> +}
>>> +
>>> static const struct platform_profile_ops dell_pc_platform_profile_ops = {
>>> + .probe = thermal_platform_profile_probe,
>>> .profile_get = thermal_platform_profile_get,
>>> .profile_set = thermal_platform_profile_set,
>>> };
>>> @@ -239,7 +255,6 @@ static const struct platform_profile_ops dell_pc_platform_profile_ops = {
>>> static int thermal_init(void)
>>> {
>>> int ret;
>>> - int supported_modes;
>>> /* If thermal commands are not supported, exit without error */
>>> if (!dell_smbios_class_is_supported(CLASS_INFO))
>>> @@ -265,15 +280,6 @@ static int thermal_init(void)
>>> thermal_handler->dev = &platform_device->dev;
>>> thermal_handler->ops = &dell_pc_platform_profile_ops;
>>> - if (supported_modes & DELL_QUIET)
>>> - set_bit(PLATFORM_PROFILE_QUIET, thermal_handler->choices);
>>> - if (supported_modes & DELL_COOL_BOTTOM)
>>> - set_bit(PLATFORM_PROFILE_COOL, thermal_handler->choices);
>>> - if (supported_modes & DELL_BALANCED)
>>> - set_bit(PLATFORM_PROFILE_BALANCED, thermal_handler->choices);
>>> - if (supported_modes & DELL_PERFORMANCE)
>>> - set_bit(PLATFORM_PROFILE_PERFORMANCE, thermal_handler->choices);
>>> -
>>> /* Clean up if failed */
>>> ret = platform_profile_register(thermal_handler, NULL);
>>> if (ret)
>>> diff --git a/drivers/platform/x86/hp/hp-wmi.c b/drivers/platform/x86/hp/hp-wmi.c
>>> index 60328b35be74..75bcd8460e7c 100644
>>> --- a/drivers/platform/x86/hp/hp-wmi.c
>>> +++ b/drivers/platform/x86/hp/hp-wmi.c
>>> @@ -1488,6 +1488,23 @@ static int platform_profile_victus_set(struct device *dev,
>>> return 0;
>>> }
>>> +static int hp_wmi_platform_profile_probe(void *drvdata, unsigned long *choices)
>>> +{
>>> + if (is_omen_thermal_profile()) {
>>> + set_bit(PLATFORM_PROFILE_COOL, choices);
>>> + } else if (is_victus_thermal_profile()) {
>>> + set_bit(PLATFORM_PROFILE_QUIET, choices);
>>> + } else {
>>> + set_bit(PLATFORM_PROFILE_QUIET, choices);
>>> + set_bit(PLATFORM_PROFILE_COOL, choices);
>>> + }
>>> +
>>> + set_bit(PLATFORM_PROFILE_BALANCED, choices);
>>> + set_bit(PLATFORM_PROFILE_PERFORMANCE, choices);
>>> +
>>> + return 0;
>>> +}
>>> +
>>> static int omen_powersource_event(struct notifier_block *nb,
>>> unsigned long value,
>>> void *data)
>>> @@ -1566,16 +1583,19 @@ static inline void omen_unregister_powersource_event_handler(void)
>>> }
>>> static const struct platform_profile_ops platform_profile_omen_ops = {
>>> + .probe = hp_wmi_platform_profile_probe,
>>> .profile_get = platform_profile_omen_get,
>>> .profile_set = platform_profile_omen_set,
>>> };
>>> static const struct platform_profile_ops platform_profile_victus_ops = {
>>> + .probe = hp_wmi_platform_profile_probe,
>>> .profile_get = platform_profile_victus_get,
>>> .profile_set = platform_profile_victus_set,
>>> };
>>> static const struct platform_profile_ops hp_wmi_platform_profile_ops = {
>>> + .probe = hp_wmi_platform_profile_probe,
>>> .profile_get = hp_wmi_platform_profile_get,
>>> .profile_set = hp_wmi_platform_profile_set,
>>> };
>>> @@ -1598,8 +1618,6 @@ static int thermal_profile_setup(struct platform_device *device)
>>> return err;
>>> platform_profile_handler.ops = &platform_profile_omen_ops;
>>> -
>>> - set_bit(PLATFORM_PROFILE_COOL, platform_profile_handler.choices);
>>> } else if (is_victus_thermal_profile()) {
>>> err = platform_profile_victus_get_ec(&active_platform_profile);
>>> if (err < 0)
>>> @@ -1614,8 +1632,6 @@ static int thermal_profile_setup(struct platform_device *device)
>>> return err;
>>> platform_profile_handler.ops = &platform_profile_victus_ops;
>>> -
>>> - set_bit(PLATFORM_PROFILE_QUIET, platform_profile_handler.choices);
>>> } else {
>>> tp = thermal_profile_get();
>>> @@ -1631,15 +1647,10 @@ static int thermal_profile_setup(struct platform_device *device)
>>> return err;
>>> platform_profile_handler.ops = &hp_wmi_platform_profile_ops;
>>> -
>>> - set_bit(PLATFORM_PROFILE_QUIET, platform_profile_handler.choices);
>>> - set_bit(PLATFORM_PROFILE_COOL, platform_profile_handler.choices);
>>> }
>>> platform_profile_handler.name = "hp-wmi";
>>> platform_profile_handler.dev = &device->dev;
>>> - set_bit(PLATFORM_PROFILE_BALANCED, platform_profile_handler.choices);
>>> - set_bit(PLATFORM_PROFILE_PERFORMANCE, platform_profile_handler.choices);
>>> err = platform_profile_register(&platform_profile_handler, NULL);
>>> if (err)
>>> diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c
>>> index 96e99513b0b5..050919a28d2b 100644
>>> --- a/drivers/platform/x86/ideapad-laptop.c
>>> +++ b/drivers/platform/x86/ideapad-laptop.c
>>> @@ -1023,6 +1023,15 @@ static int dytc_profile_set(struct device *dev,
>>> return -EINTR;
>>> }
>>> +static int dytc_profile_probe(void *drvdata, unsigned long *choices)
>>> +{
>>> + set_bit(PLATFORM_PROFILE_LOW_POWER, choices);
>>> + set_bit(PLATFORM_PROFILE_BALANCED, choices);
>>> + set_bit(PLATFORM_PROFILE_PERFORMANCE, choices);
>>> +
>>> + return 0;
>>> +}
>>> +
>>> static void dytc_profile_refresh(struct ideapad_private *priv)
>>> {
>>> enum platform_profile_option profile;
>>> @@ -1064,6 +1073,7 @@ static const struct dmi_system_id ideapad_dytc_v4_allow_table[] = {
>>> };
>>> static const struct platform_profile_ops dytc_profile_ops = {
>>> + .probe = dytc_profile_probe,
>>> .profile_get = dytc_profile_get,
>>> .profile_set = dytc_profile_set,
>>> };
>>> @@ -1112,11 +1122,6 @@ static int ideapad_dytc_profile_init(struct ideapad_private *priv)
>>> priv->dytc->priv = priv;
>>> priv->dytc->pprof.ops = &dytc_profile_ops;
>>> - /* Setup supported modes */
>>> - set_bit(PLATFORM_PROFILE_LOW_POWER, priv->dytc->pprof.choices);
>>> - set_bit(PLATFORM_PROFILE_BALANCED, priv->dytc->pprof.choices);
>>> - set_bit(PLATFORM_PROFILE_PERFORMANCE, priv->dytc->pprof.choices);
>>> -
>>> /* Create platform_profile structure and register */
>>> err = platform_profile_register(&priv->dytc->pprof, &priv->dytc);
>>> if (err)
>>> diff --git a/drivers/platform/x86/inspur_platform_profile.c b/drivers/platform/x86/inspur_platform_profile.c
>>> index d0a8e4eebffa..06df3aae9a56 100644
>>> --- a/drivers/platform/x86/inspur_platform_profile.c
>>> +++ b/drivers/platform/x86/inspur_platform_profile.c
>>> @@ -164,7 +164,17 @@ static int inspur_platform_profile_get(struct device *dev,
>>> return 0;
>>> }
>>> +static int inspur_platform_profile_probe(void *drvdata, unsigned long *choices)
>>> +{
>>> + set_bit(PLATFORM_PROFILE_LOW_POWER, choices);
>>> + set_bit(PLATFORM_PROFILE_BALANCED, choices);
>>> + set_bit(PLATFORM_PROFILE_PERFORMANCE, choices);
>>> +
>>> + return 0;
>>> +}
>>> +
>>> static const struct platform_profile_ops inspur_platform_profile_ops = {
>>> + .probe = inspur_platform_profile_probe,
>>> .profile_get = inspur_platform_profile_get,
>>> .profile_set = inspur_platform_profile_set,
>>> };
>>> @@ -184,10 +194,6 @@ static int inspur_wmi_probe(struct wmi_device *wdev, const void *context)
>>> priv->handler.dev = &wdev->dev;
>>> priv->handler.ops = &inspur_platform_profile_ops;
>>> - set_bit(PLATFORM_PROFILE_LOW_POWER, priv->handler.choices);
>>> - set_bit(PLATFORM_PROFILE_BALANCED, priv->handler.choices);
>>> - set_bit(PLATFORM_PROFILE_PERFORMANCE, priv->handler.choices);
>>> -
>>> return platform_profile_register(&priv->handler, priv);
>>> }
>>> diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
>>> index 9978fd36a3d1..5c250867678f 100644
>>> --- a/drivers/platform/x86/thinkpad_acpi.c
>>> +++ b/drivers/platform/x86/thinkpad_acpi.c
>>> @@ -10538,7 +10538,17 @@ static int dytc_profile_set(struct device *dev,
>>> return err;
>>> }
>>> +static int dytc_profile_probe(void *drvdata, unsigned long *choices)
>>> +{
>>> + set_bit(PLATFORM_PROFILE_LOW_POWER, choices);
>>> + set_bit(PLATFORM_PROFILE_BALANCED, choices);
>>> + set_bit(PLATFORM_PROFILE_PERFORMANCE, choices);
>>> +
>>> + return 0;
>>> +}
>>> +
>>> static const struct platform_profile_ops dytc_profile_ops = {
>>> + .probe = dytc_profile_probe,
>>> .profile_get = dytc_profile_get,
>>> .profile_set = dytc_profile_set,
>>> };
>>> @@ -10584,11 +10594,6 @@ static int tpacpi_dytc_profile_init(struct ibm_init_struct *iibm)
>>> {
>>> int err, output;
>>> - /* Setup supported modes */
>>> - set_bit(PLATFORM_PROFILE_LOW_POWER, dytc_profile.choices);
>>> - set_bit(PLATFORM_PROFILE_BALANCED, dytc_profile.choices);
>>> - set_bit(PLATFORM_PROFILE_PERFORMANCE, dytc_profile.choices);
>>> -
>>> err = dytc_command(DYTC_CMD_QUERY, &output);
>>> if (err)
>>> return err;
>>> diff --git a/include/linux/platform_profile.h b/include/linux/platform_profile.h
>>> index 6013c05d7b86..5ad1ab7b75e4 100644
>>> --- a/include/linux/platform_profile.h
>>> +++ b/include/linux/platform_profile.h
>>> @@ -31,6 +31,7 @@ enum platform_profile_option {
>>> struct platform_profile_handler;
>>> struct platform_profile_ops {
>>> + int (*probe)(void *drvdata, unsigned long *choices);
>>> int (*profile_get)(struct device *dev, enum platform_profile_option *profile);
>>> int (*profile_set)(struct device *dev, enum platform_profile_option profile);
>>> };
>>
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH v2 15/18] ACPI: platform_profile: Remove platform_profile_handler from exported symbols
2025-01-14 15:37 ` [PATCH v2 15/18] ACPI: platform_profile: Remove platform_profile_handler from exported symbols Kurt Borja
2025-01-14 16:22 ` Mario Limonciello
@ 2025-01-14 16:55 ` Ilpo Järvinen
2025-01-14 17:13 ` Rafael J. Wysocki
2025-01-14 17:26 ` Kurt Borja
1 sibling, 2 replies; 33+ messages in thread
From: Ilpo Järvinen @ 2025-01-14 16:55 UTC (permalink / raw)
To: Kurt Borja
Cc: platform-driver-x86, Rafael J. Wysocki, Len Brown, linux-acpi,
LKML, Mario Limonciello, Armin Wolf, Joshua Grisham,
Derek J. Clark, Hans de Goede, Maximilian Luz, Lee, Chun-Yi,
Shyam Sundar S K, Corentin Chary, Luke D. Jones, Lyndon Sanche,
Ike Panhc, Henrique de Moraes Holschuh, Mark Pearson,
Alexis Belmonte, Ai Chao, Gergo Koteles, Dell.Client.Kernel,
ibm-acpi-devel
On Tue, 14 Jan 2025, Kurt Borja wrote:
> In order to protect the platform_profile_handler from API consumers,
> allocate it in platform_profile_register() and modify it's signature
> accordingly.
>
> Remove the platform_profile_handler from all consumer drivers and
> replace them with a pointer to the class device, which is
> now returned from platform_profile_register().
>
> Replace *pprof with a pointer to the class device in the rest of
> exported symbols.
>
> Signed-off-by: Kurt Borja <kuurtb@gmail.com>
> ---
> drivers/acpi/platform_profile.c | 87 ++++++++++++-------
> .../surface/surface_platform_profile.c | 11 ++-
> drivers/platform/x86/acer-wmi.c | 18 ++--
> drivers/platform/x86/amd/pmf/pmf.h | 2 +-
> drivers/platform/x86/amd/pmf/sps.c | 17 ++--
> drivers/platform/x86/asus-wmi.c | 20 ++---
> drivers/platform/x86/dell/alienware-wmi.c | 9 +-
> drivers/platform/x86/dell/dell-pc.c | 22 ++---
> drivers/platform/x86/hp/hp-wmi.c | 19 ++--
> drivers/platform/x86/ideapad-laptop.c | 14 +--
> .../platform/x86/inspur_platform_profile.c | 9 +-
> drivers/platform/x86/thinkpad_acpi.c | 14 ++-
> include/linux/platform_profile.h | 12 ++-
> 13 files changed, 125 insertions(+), 129 deletions(-)
>
> diff --git a/drivers/acpi/platform_profile.c b/drivers/acpi/platform_profile.c
> index 34e22b006ccc..2fae5e2fc962 100644
> --- a/drivers/acpi/platform_profile.c
> +++ b/drivers/acpi/platform_profile.c
> @@ -4,6 +4,7 @@
>
> #include <linux/acpi.h>
> #include <linux/bits.h>
> +#include <linux/cleanup.h>
> #include <linux/init.h>
> #include <linux/kdev_t.h>
> #include <linux/mutex.h>
> @@ -213,9 +214,17 @@ static struct attribute *profile_attrs[] = {
> };
> ATTRIBUTE_GROUPS(profile);
>
> +static void pprof_device_release(struct device *dev)
> +{
> + struct platform_profile_handler *pprof = to_pprof_handler(dev);
> +
> + kfree(pprof);
> +}
> +
> static const struct class platform_profile_class = {
> .name = "platform-profile",
> .dev_groups = profile_groups,
> + .dev_release = pprof_device_release,
> };
>
> /**
> @@ -409,10 +418,10 @@ static const struct attribute_group platform_profile_group = {
> .is_visible = profile_class_is_visible,
> };
>
> -void platform_profile_notify(struct platform_profile_handler *pprof)
> +void platform_profile_notify(struct device *dev)
> {
> scoped_cond_guard(mutex_intr, return, &profile_lock) {
> - _notify_class_profile(&pprof->class_dev, NULL);
> + _notify_class_profile(dev, NULL);
> }
> sysfs_notify(acpi_kobj, NULL, "platform_profile");
> }
> @@ -461,40 +470,51 @@ int platform_profile_cycle(void)
> }
> EXPORT_SYMBOL_GPL(platform_profile_cycle);
>
> -int platform_profile_register(struct platform_profile_handler *pprof, void *drvdata)
> +struct device *platform_profile_register(struct device *dev, const char *name,
> + void *drvdata,
> + const struct platform_profile_ops *ops)
> {
> + int minor;
> int err;
>
> - /* Sanity check the profile handler */
> - if (!pprof || !pprof->ops->profile_set || !pprof->ops->profile_get ||
> - !pprof->ops->probe) {
> + /* Sanity check */
> + if (!dev || !name || !ops || !ops->profile_get ||
> + !ops->profile_set || !ops->probe) {
> pr_err("platform_profile: handler is invalid\n");
> - return -EINVAL;
> + return ERR_PTR(-EINVAL);
> }
>
> - err = pprof->ops->probe(drvdata, pprof->choices);
> + struct platform_profile_handler *pprof __free(kfree) = kzalloc(
> + sizeof(*pprof), GFP_KERNEL);
> + if (!pprof)
> + return ERR_PTR(-ENOMEM);
> +
> + err = ops->probe(drvdata, pprof->choices);
> if (err < 0)
> - return err;
> + return ERR_PTR(err);
>
> if (bitmap_empty(pprof->choices, PLATFORM_PROFILE_LAST)) {
> pr_err("platform_profile: no available profiles\n");
> - return -EINVAL;
> + return ERR_PTR(-EINVAL);
> }
>
> guard(mutex)(&profile_lock);
>
> /* create class interface for individual handler */
> - pprof->minor = ida_alloc(&platform_profile_ida, GFP_KERNEL);
> - if (pprof->minor < 0)
> - return pprof->minor;
> + minor = ida_alloc(&platform_profile_ida, GFP_KERNEL);
> + if (minor < 0)
> + return ERR_PTR(minor);
>
> + pprof->name = name;
> + pprof->ops = ops;
> + pprof->minor = minor;
> pprof->class_dev.class = &platform_profile_class;
> - pprof->class_dev.parent = pprof->dev;
> + pprof->class_dev.parent = dev;
> dev_set_drvdata(&pprof->class_dev, drvdata);
> dev_set_name(&pprof->class_dev, "platform-profile-%d", pprof->minor);
> err = device_register(&pprof->class_dev);
> if (err) {
> - put_device(&pprof->class_dev);
> + put_device(&no_free_ptr(pprof)->class_dev);
> goto cleanup_ida;
> }
>
> @@ -504,20 +524,21 @@ int platform_profile_register(struct platform_profile_handler *pprof, void *drvd
> if (err)
> goto cleanup_cur;
>
> - return 0;
> + return &no_free_ptr(pprof)->class_dev;
>
> cleanup_cur:
> - device_unregister(&pprof->class_dev);
> + device_unregister(&no_free_ptr(pprof)->class_dev);
I don't like how this is architected.
IMO, no_free_ptr() should not appear on error/rollback paths. The pointer
is going to be freed despite the code just told it's not going to be
freed, which sends conflicting signals. Obviously, it is because this
function has relinquished its ownership of the pointer but as is it seems
a dangerous/confusing pattern.
> cleanup_ida:
> - ida_free(&platform_profile_ida, pprof->minor);
> + ida_free(&platform_profile_ida, minor);
>
> - return err;
> + return ERR_PTR(err);
> }
> EXPORT_SYMBOL_GPL(platform_profile_register);
>
> -int platform_profile_remove(struct platform_profile_handler *pprof)
> +int platform_profile_remove(struct device *dev)
> {
> + struct platform_profile_handler *pprof = to_pprof_handler(dev);
> int id;
> guard(mutex)(&profile_lock);
>
> @@ -535,30 +556,32 @@ EXPORT_SYMBOL_GPL(platform_profile_remove);
>
> static void devm_platform_profile_release(struct device *dev, void *res)
> {
> - struct platform_profile_handler **pprof = res;
> + struct device **ppdev = res;
>
> - platform_profile_remove(*pprof);
> + platform_profile_remove(*ppdev);
> }
>
> -int devm_platform_profile_register(struct platform_profile_handler *pprof, void *drvdata)
> +struct device *devm_platform_profile_register(struct device *dev, const char *name,
> + void *drvdata,
> + const struct platform_profile_ops *ops)
> {
> - struct platform_profile_handler **dr;
> - int ret;
> + struct device *ppdev;
> + struct device **dr;
>
> dr = devres_alloc(devm_platform_profile_release, sizeof(*dr), GFP_KERNEL);
> if (!dr)
> - return -ENOMEM;
> + return ERR_PTR(-ENOMEM);
>
> - ret = platform_profile_register(pprof, drvdata);
> - if (ret) {
> + ppdev = platform_profile_register(dev, name, drvdata, ops);
> + if (IS_ERR(dev)) {
> devres_free(dr);
> - return ret;
> + return ppdev;
> }
>
> - *dr = pprof;
> - devres_add(pprof->dev, dr);
> + *dr = ppdev;
> + devres_add(dev, dr);
>
> - return 0;
> + return ppdev;
> }
> EXPORT_SYMBOL_GPL(devm_platform_profile_register);
>
> diff --git a/drivers/platform/surface/surface_platform_profile.c b/drivers/platform/surface/surface_platform_profile.c
> index bbdc873cb788..275269a6efc1 100644
> --- a/drivers/platform/surface/surface_platform_profile.c
> +++ b/drivers/platform/surface/surface_platform_profile.c
> @@ -40,7 +40,7 @@ struct ssam_tmp_profile_info {
>
> struct ssam_platform_profile_device {
> struct ssam_device *sdev;
> - struct platform_profile_handler handler;
> + struct device *ppdev;
> bool has_fan;
> };
>
> @@ -228,13 +228,12 @@ static int surface_platform_profile_probe(struct ssam_device *sdev)
> tpd->sdev = sdev;
> ssam_device_set_drvdata(sdev, tpd);
>
> - tpd->handler.name = "Surface Platform Profile";
> - tpd->handler.dev = &sdev->dev;
> - tpd->handler.ops = &ssam_platform_profile_ops;
> -
> tpd->has_fan = device_property_read_bool(&sdev->dev, "has_fan");
>
> - return devm_platform_profile_register(&tpd->handler, tpd);
> + tpd->ppdev = devm_platform_profile_register(
Extra space.
> + &sdev->dev, "Surface Platform Profile", tpd, &ssam_platform_profile_ops);
Could you try to split the line differently.
> +
> + return PTR_ERR_OR_ZERO(tpd->ppdev);
> }
>
> static const struct ssam_device_id ssam_platform_profile_match[] = {
> diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c
> index 39ec236b7cdb..3e39465b3783 100644
> --- a/drivers/platform/x86/acer-wmi.c
> +++ b/drivers/platform/x86/acer-wmi.c
> @@ -758,7 +758,7 @@ static const struct dmi_system_id non_acer_quirks[] __initconst = {
> {}
> };
>
> -static struct platform_profile_handler platform_profile_handler;
> +static struct device *platform_profile_device;
> static bool platform_profile_support;
>
> /*
> @@ -1937,16 +1937,10 @@ static const struct platform_profile_ops acer_predator_v4_platform_profile_ops =
> static int acer_platform_profile_setup(struct platform_device *device)
> {
> if (quirks->predator_v4) {
> - int err;
> -
> - platform_profile_handler.name = "acer-wmi";
> - platform_profile_handler.dev = &device->dev;
> - platform_profile_handler.ops =
> - &acer_predator_v4_platform_profile_ops;
> -
> - err = devm_platform_profile_register(&platform_profile_handler, NULL);
> - if (err)
> - return err;
> + platform_profile_device = devm_platform_profile_register(
> + &device->dev, "acer-wmi", NULL, &acer_predator_v4_platform_profile_ops);
> + if (IS_ERR(platform_profile_device))
> + return PTR_ERR(platform_profile_device);
>
> platform_profile_support = true;
>
> @@ -2033,7 +2027,7 @@ static int acer_thermal_profile_change(void)
> if (tp != ACER_PREDATOR_V4_THERMAL_PROFILE_TURBO_WMI)
> last_non_turbo_profile = tp;
>
> - platform_profile_notify(&platform_profile_handler);
> + platform_profile_notify(platform_profile_device);
> }
>
> return 0;
> diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/x86/amd/pmf/pmf.h
> index d99b3556205b..41b2b91b8fdc 100644
> --- a/drivers/platform/x86/amd/pmf/pmf.h
> +++ b/drivers/platform/x86/amd/pmf/pmf.h
> @@ -338,7 +338,7 @@ struct amd_pmf_dev {
> struct mutex lock; /* protects the PMF interface */
> u32 supported_func;
> enum platform_profile_option current_profile;
> - struct platform_profile_handler pprof;
> + struct device *ppdev; /* platform profile class device */
> struct dentry *dbgfs_dir;
> int hb_interval; /* SBIOS heartbeat interval */
> struct delayed_work heart_beat;
> diff --git a/drivers/platform/x86/amd/pmf/sps.c b/drivers/platform/x86/amd/pmf/sps.c
> index 7c7ed2b9de01..a96fc6887cf0 100644
> --- a/drivers/platform/x86/amd/pmf/sps.c
> +++ b/drivers/platform/x86/amd/pmf/sps.c
> @@ -404,8 +404,6 @@ static const struct platform_profile_ops amd_pmf_profile_ops = {
>
> int amd_pmf_init_sps(struct amd_pmf_dev *dev)
> {
> - int err;
> -
> dev->current_profile = PLATFORM_PROFILE_BALANCED;
>
> if (is_apmf_func_supported(dev, APMF_FUNC_STATIC_SLIDER_GRANULAR)) {
> @@ -420,15 +418,12 @@ int amd_pmf_init_sps(struct amd_pmf_dev *dev)
> amd_pmf_set_sps_power_limits(dev);
> }
>
> - dev->pprof.name = "amd-pmf";
> - dev->pprof.dev = dev->dev;
> - dev->pprof.ops = &amd_pmf_profile_ops;
> -
> /* Create platform_profile structure and register */
> - err = devm_platform_profile_register(&dev->pprof, dev);
> - if (err)
> - dev_err(dev->dev, "Failed to register SPS support, this is most likely an SBIOS bug: %d\n",
> - err);
> + dev->ppdev = devm_platform_profile_register(
> + dev->dev, "amd-pmf", dev, &amd_pmf_profile_ops);
> + if (IS_ERR(dev->ppdev))
> + dev_err(dev->dev, "Failed to register SPS support, this is most likely an SBIOS bug: %ld\n",
> + PTR_ERR(dev->ppdev));
>
> - return err;
> + return PTR_ERR_OR_ZERO(dev->ppdev);
> }
> diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
> index f8437cff66df..4ad99cf9df1a 100644
> --- a/drivers/platform/x86/asus-wmi.c
> +++ b/drivers/platform/x86/asus-wmi.c
> @@ -313,7 +313,7 @@ struct asus_wmi {
> bool mid_fan_curve_available;
> struct fan_curve_data custom_fan_curves[3];
>
> - struct platform_profile_handler platform_profile_handler;
> + struct device *platform_profile_device;
Using both ppdev vs platform_profile_device for the same thing seems
inconsistent. The long name also caused a few line split issues for you.
> bool platform_profile_support;
>
> // The RSOC controls the maximum charging percentage.
> @@ -3789,7 +3789,7 @@ static ssize_t throttle_thermal_policy_store(struct device *dev,
> * Ensure that platform_profile updates userspace with the change to ensure
> * that platform_profile and throttle_thermal_policy_mode are in sync.
> */
> - platform_profile_notify(&asus->platform_profile_handler);
> + platform_profile_notify(asus->platform_profile_device);
>
> return count;
> }
> @@ -3891,17 +3891,13 @@ static int platform_profile_setup(struct asus_wmi *asus)
>
> dev_info(dev, "Using throttle_thermal_policy for platform_profile support\n");
>
> - asus->platform_profile_handler.name = "asus-wmi";
> - asus->platform_profile_handler.dev = dev;
> - asus->platform_profile_handler.ops = &asus_wmi_platform_profile_ops;
> + asus->platform_profile_device = devm_platform_profile_register(
> + dev, "asus-wmi", asus, &asus_wmi_platform_profile_ops);
> + if (IS_ERR(asus->platform_profile_device)) {
> + pr_err("%s, failed at devm_platform_profile_register: %ld\n",
> + __func__, PTR_ERR(asus->platform_profile_device));
>
> - err = devm_platform_profile_register(&asus->platform_profile_handler, asus);
> - if (err == -EEXIST) {
> - pr_warn("%s, a platform_profile handler is already registered\n", __func__);
> - return 0;
> - } else if (err) {
> - pr_err("%s, failed at devm_platform_profile_register: %d\n", __func__, err);
> - return err;
> + return PTR_ERR(asus->platform_profile_device);
> }
>
> asus->platform_profile_support = true;
> diff --git a/drivers/platform/x86/dell/alienware-wmi.c b/drivers/platform/x86/dell/alienware-wmi.c
> index 0146d2f93be6..99db93846a63 100644
> --- a/drivers/platform/x86/dell/alienware-wmi.c
> +++ b/drivers/platform/x86/dell/alienware-wmi.c
> @@ -1135,11 +1135,12 @@ static const struct platform_profile_ops awcc_platform_profile_ops = {
>
> static int create_thermal_profile(struct platform_device *platform_device)
> {
> - pp_handler.name = "alienware-wmi";
> - pp_handler.dev = &platform_device->dev;
> - pp_handler.ops = &awcc_platform_profile_ops;
> + struct device *ppdev;
>
> - return devm_platform_profile_register(&pp_handler, NULL);
> + ppdev = devm_platform_profile_register(
> + &platform_device->dev, "alienware-wmi", NULL, &awcc_platform_profile_ops);
Not a good linesplit (there are other similar problems).
> +
> + return PTR_ERR_OR_ZERO(ppdev);
> }
>
> /*
> diff --git a/drivers/platform/x86/dell/dell-pc.c b/drivers/platform/x86/dell/dell-pc.c
> index 2759bb608b1a..8d60e1b223de 100644
> --- a/drivers/platform/x86/dell/dell-pc.c
> +++ b/drivers/platform/x86/dell/dell-pc.c
> @@ -109,8 +109,6 @@ MODULE_DEVICE_TABLE(dmi, dell_device_table);
> #define DELL_ACC_SET_FIELD GENMASK(11, 8)
> #define DELL_THERMAL_SUPPORTED GENMASK(3, 0)
>
> -static struct platform_profile_handler *thermal_handler;
> -
> enum thermal_mode_bits {
> DELL_BALANCED = BIT(0),
> DELL_COOL_BOTTOM = BIT(1),
> @@ -254,6 +252,7 @@ static const struct platform_profile_ops dell_pc_platform_profile_ops = {
>
> static int thermal_init(void)
> {
> + struct device *ppdev;
> int ret;
>
> /* If thermal commands are not supported, exit without error */
> @@ -271,26 +270,17 @@ static int thermal_init(void)
> if (IS_ERR(platform_device))
> return PTR_ERR(platform_device);
>
> - thermal_handler = devm_kzalloc(&platform_device->dev, sizeof(*thermal_handler), GFP_KERNEL);
> - if (!thermal_handler) {
> - ret = -ENOMEM;
> - goto cleanup_platform_device;
> - }
> - thermal_handler->name = "dell-pc";
> - thermal_handler->dev = &platform_device->dev;
> - thermal_handler->ops = &dell_pc_platform_profile_ops;
> -
> /* Clean up if failed */
> - ret = devm_platform_profile_register(thermal_handler, NULL);
> - if (ret)
> + ppdev = devm_platform_profile_register(
> + &platform_device->dev, "dell-pc", NULL, &dell_pc_platform_profile_ops);
> + if (IS_ERR(ppdev)) {
> + ret = PTR_ERR(ppdev);
> goto cleanup_thermal_handler;
> + }
>
> return 0;
>
> cleanup_thermal_handler:
> - thermal_handler = NULL;
> -
> -cleanup_platform_device:
> platform_device_unregister(platform_device);
>
> return ret;
> diff --git a/drivers/platform/x86/hp/hp-wmi.c b/drivers/platform/x86/hp/hp-wmi.c
> index 1304dfc65aab..d1f9bd287986 100644
> --- a/drivers/platform/x86/hp/hp-wmi.c
> +++ b/drivers/platform/x86/hp/hp-wmi.c
> @@ -273,7 +273,7 @@ static DEFINE_MUTEX(active_platform_profile_lock);
> static struct input_dev *hp_wmi_input_dev;
> static struct input_dev *camera_shutter_input_dev;
> static struct platform_device *hp_wmi_platform_dev;
> -static struct platform_profile_handler platform_profile_handler;
> +static struct device *platform_profile_device;
> static struct notifier_block platform_power_source_nb;
> static enum platform_profile_option active_platform_profile;
> static bool platform_profile_support;
> @@ -1602,6 +1602,7 @@ static const struct platform_profile_ops hp_wmi_platform_profile_ops = {
>
> static int thermal_profile_setup(struct platform_device *device)
> {
> + const struct platform_profile_ops *ops;
> int err, tp;
>
> if (is_omen_thermal_profile()) {
> @@ -1617,7 +1618,7 @@ static int thermal_profile_setup(struct platform_device *device)
> if (err < 0)
> return err;
>
> - platform_profile_handler.ops = &platform_profile_omen_ops;
> + ops = &platform_profile_omen_ops;
> } else if (is_victus_thermal_profile()) {
> err = platform_profile_victus_get_ec(&active_platform_profile);
> if (err < 0)
> @@ -1631,7 +1632,7 @@ static int thermal_profile_setup(struct platform_device *device)
> if (err < 0)
> return err;
>
> - platform_profile_handler.ops = &platform_profile_victus_ops;
> + ops = &platform_profile_victus_ops;
> } else {
> tp = thermal_profile_get();
>
> @@ -1646,15 +1647,13 @@ static int thermal_profile_setup(struct platform_device *device)
> if (err)
> return err;
>
> - platform_profile_handler.ops = &hp_wmi_platform_profile_ops;
> + ops = &hp_wmi_platform_profile_ops;
> }
>
> - platform_profile_handler.name = "hp-wmi";
> - platform_profile_handler.dev = &device->dev;
> -
> - err = devm_platform_profile_register(&platform_profile_handler, NULL);
> - if (err)
> - return err;
> + platform_profile_device = devm_platform_profile_register(
> + &device->dev, "hp-wmi", NULL, ops);
> + if (IS_ERR(platform_profile_device))
> + return PTR_ERR(platform_profile_device);
>
> platform_profile_support = true;
>
> diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c
> index 87c1e087770a..6065a7421a02 100644
> --- a/drivers/platform/x86/ideapad-laptop.c
> +++ b/drivers/platform/x86/ideapad-laptop.c
> @@ -142,7 +142,7 @@ enum {
>
> struct ideapad_dytc_priv {
> enum platform_profile_option current_profile;
> - struct platform_profile_handler pprof;
> + struct device *ppdev; /* platform profile device */
> struct mutex mutex; /* protects the DYTC interface */
> struct ideapad_private *priv;
> };
> @@ -1050,7 +1050,7 @@ static void dytc_profile_refresh(struct ideapad_private *priv)
>
> if (profile != priv->dytc->current_profile) {
> priv->dytc->current_profile = profile;
> - platform_profile_notify(&priv->dytc->pprof);
> + platform_profile_notify(priv->dytc->ppdev);
> }
> }
>
> @@ -1117,15 +1117,15 @@ static int ideapad_dytc_profile_init(struct ideapad_private *priv)
>
> mutex_init(&priv->dytc->mutex);
>
> - priv->dytc->pprof.name = "ideapad-laptop";
> - priv->dytc->pprof.dev = &priv->platform_device->dev;
> priv->dytc->priv = priv;
> - priv->dytc->pprof.ops = &dytc_profile_ops;
>
> /* Create platform_profile structure and register */
> - err = devm_platform_profile_register(&priv->dytc->pprof, &priv->dytc);
> - if (err)
> + priv->dytc->ppdev = devm_platform_profile_register(
> + &priv->platform_device->dev, "ideapad-laptop", &priv->dytc, &dytc_profile_ops);
> + if (IS_ERR(priv->dytc->ppdev)) {
> + err = PTR_ERR(priv->dytc->ppdev);
> goto pp_reg_failed;
> + }
>
> /* Ensure initial values are correct */
> dytc_profile_refresh(priv);
> diff --git a/drivers/platform/x86/inspur_platform_profile.c b/drivers/platform/x86/inspur_platform_profile.c
> index e1631de6ad86..8b71c4242939 100644
> --- a/drivers/platform/x86/inspur_platform_profile.c
> +++ b/drivers/platform/x86/inspur_platform_profile.c
> @@ -32,7 +32,7 @@ enum inspur_tmp_profile {
>
> struct inspur_wmi_priv {
> struct wmi_device *wdev;
> - struct platform_profile_handler handler;
> + struct device *ppdev;
> };
>
> static int inspur_wmi_perform_query(struct wmi_device *wdev,
> @@ -190,11 +190,10 @@ static int inspur_wmi_probe(struct wmi_device *wdev, const void *context)
> priv->wdev = wdev;
> dev_set_drvdata(&wdev->dev, priv);
>
> - priv->handler.name = "inspur-wmi";
> - priv->handler.dev = &wdev->dev;
> - priv->handler.ops = &inspur_platform_profile_ops;
> + priv->ppdev = devm_platform_profile_register(
> + &wdev->dev, "inspur-wmi", priv, &inspur_platform_profile_ops);
>
> - return devm_platform_profile_register(&priv->handler, priv);
> + return PTR_ERR_OR_ZERO(priv->ppdev);
> }
>
> static const struct wmi_device_id inspur_wmi_id_table[] = {
> diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
> index 54ff3e6b8b1a..2a3dd0d149a1 100644
> --- a/drivers/platform/x86/thinkpad_acpi.c
> +++ b/drivers/platform/x86/thinkpad_acpi.c
> @@ -962,6 +962,7 @@ static const struct proc_ops dispatch_proc_ops = {
> static struct platform_device *tpacpi_pdev;
> static struct platform_device *tpacpi_sensors_pdev;
> static struct device *tpacpi_hwmon;
> +static struct device *tpacpi_pprof;
> static struct input_dev *tpacpi_inputdev;
> static struct mutex tpacpi_inputdev_send_mutex;
> static LIST_HEAD(tpacpi_all_drivers);
> @@ -10553,11 +10554,6 @@ static const struct platform_profile_ops dytc_profile_ops = {
> .profile_set = dytc_profile_set,
> };
>
> -static struct platform_profile_handler dytc_profile = {
> - .name = "thinkpad-acpi",
> - .ops = &dytc_profile_ops,
> -};
> -
> static void dytc_profile_refresh(void)
> {
> enum platform_profile_option profile;
> @@ -10586,7 +10582,7 @@ static void dytc_profile_refresh(void)
> err = convert_dytc_to_profile(funcmode, perfmode, &profile);
> if (!err && profile != dytc_current_profile) {
> dytc_current_profile = profile;
> - platform_profile_notify(&dytc_profile);
> + platform_profile_notify(tpacpi_pprof);
> }
> }
>
> @@ -10647,14 +10643,14 @@ static int tpacpi_dytc_profile_init(struct ibm_init_struct *iibm)
> dbg_printk(TPACPI_DBG_INIT,
> "DYTC version %d: thermal mode available\n", dytc_version);
>
> - dytc_profile.dev = &tpacpi_pdev->dev;
> /* Create platform_profile structure and register */
> - err = devm_platform_profile_register(&dytc_profile, NULL);
> + tpacpi_pprof = devm_platform_profile_register(
> + &tpacpi_pdev->dev, "thinkpad-acpi", NULL, &dytc_profile_ops);
> /*
> * If for some reason platform_profiles aren't enabled
> * don't quit terminally.
> */
> - if (err)
> + if (IS_ERR(tpacpi_pprof))
> return -ENODEV;
>
> /* Ensure initial values are correct */
> diff --git a/include/linux/platform_profile.h b/include/linux/platform_profile.h
> index 5ad1ab7b75e4..778d4c661c3c 100644
> --- a/include/linux/platform_profile.h
> +++ b/include/linux/platform_profile.h
> @@ -45,10 +45,14 @@ struct platform_profile_handler {
> const struct platform_profile_ops *ops;
> };
>
> -int platform_profile_register(struct platform_profile_handler *pprof, void *drvdata);
> -int platform_profile_remove(struct platform_profile_handler *pprof);
> -int devm_platform_profile_register(struct platform_profile_handler *pprof, void *drvdata);
> +struct device *platform_profile_register(struct device *dev, const char *name,
> + void *drvdata,
> + const struct platform_profile_ops *ops);
> +int platform_profile_remove(struct device *dev);
> +struct device *devm_platform_profile_register(struct device *dev, const char *name,
> + void *drvdata,
> + const struct platform_profile_ops *ops);
> int platform_profile_cycle(void);
> -void platform_profile_notify(struct platform_profile_handler *pprof);
> +void platform_profile_notify(struct device *dev);
>
> #endif /*_PLATFORM_PROFILE_H_*/
>
--
i.
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH v2 18/18] ACPI: platform_profile: Add documentation
2025-01-14 15:37 ` [PATCH v2 18/18] ACPI: platform_profile: Add documentation Kurt Borja
2025-01-14 16:24 ` Mario Limonciello
@ 2025-01-14 16:57 ` Ilpo Järvinen
2025-01-14 17:27 ` Kurt Borja
1 sibling, 1 reply; 33+ messages in thread
From: Ilpo Järvinen @ 2025-01-14 16:57 UTC (permalink / raw)
To: Kurt Borja
Cc: platform-driver-x86, Rafael J. Wysocki, Len Brown, linux-acpi,
LKML, Mario Limonciello, Armin Wolf, Joshua Grisham,
Derek J. Clark, Hans de Goede, Maximilian Luz, Lee, Chun-Yi,
Shyam Sundar S K, Corentin Chary, Luke D. Jones, Lyndon Sanche,
Ike Panhc, Henrique de Moraes Holschuh, Mark Pearson,
Alexis Belmonte, Ai Chao, Gergo Koteles, Dell.Client.Kernel,
ibm-acpi-devel
On Tue, 14 Jan 2025, Kurt Borja wrote:
> Add kerneldoc and sysfs class documentation.
>
> Signed-off-by: Kurt Borja <kuurtb@gmail.com>
> ---
> .../ABI/testing/sysfs-class-platform-profile | 44 +++++++++++++++++++
> drivers/acpi/platform_profile.c | 33 ++++++++++++++
> include/linux/platform_profile.h | 24 ++++++++++
> 3 files changed, 101 insertions(+)
> create mode 100644 Documentation/ABI/testing/sysfs-class-platform-profile
>
> diff --git a/Documentation/ABI/testing/sysfs-class-platform-profile b/Documentation/ABI/testing/sysfs-class-platform-profile
> new file mode 100644
> index 000000000000..b5a3600080bc
> --- /dev/null
> +++ b/Documentation/ABI/testing/sysfs-class-platform-profile
> @@ -0,0 +1,44 @@
> +What: /sys/class/platform-profile/platform-profile-X/name
> +Date: January 2025
> +Description: Name of the class device given by the driver.
> +
> + RO
> +
> +What: /sys/class/platform-profile/platform-profile-X/choices
> +Date: January 2025
> +Description: This file contains a space-separated list of profiles supported for this device.
> +
> + Drivers must use the following standard profile-names:
> +
> + ==================== ========================================
> + low-power Low power consumption
> + cool Cooler operation
> + quiet Quieter operation
> + balanced Balance between low power consumption
> + and performance
> + balanced-performance Balance between performance and low
> + power consumption with a slight bias
> + towards performance
> + performance High performance operation
> + custom Driver defined custom profile
> + ==================== ========================================
> +
> + RO
> +
> +What: /sys/class/platform-profile/platform-profile-X/profile
> +Date: January 2025
> +Description: Reading this file gives the current selected profile for this
> + device. Writing this file with one of the strings from
> + platform_profile_choices changes the profile to the new value.
> +
> + This file can be monitored for changes by polling for POLLPRI,
> + POLLPRI will be signaled on any changes, independent of those
> + changes coming from a userspace write; or coming from another
> + source such as e.g. a hotkey triggered profile change handled
> + either directly by the embedded-controller or fully handled
> + inside the kernel.
> +
> + This file may also emit the string 'custom' to indicate
> + that the driver is using a driver defined custom profile.
> +
> + RW
> diff --git a/drivers/acpi/platform_profile.c b/drivers/acpi/platform_profile.c
> index c44989801f8e..9caddac695b8 100644
> --- a/drivers/acpi/platform_profile.c
> +++ b/drivers/acpi/platform_profile.c
> @@ -426,6 +426,10 @@ static const struct attribute_group platform_profile_group = {
> .is_visible = profile_class_is_visible,
> };
>
> +/**
> + * platform_profile_notify - Notify class device and legacy sysfs interface
> + * @dev: The class device
> + */
> void platform_profile_notify(struct device *dev)
> {
> scoped_cond_guard(mutex_intr, return, &profile_lock) {
> @@ -435,6 +439,11 @@ void platform_profile_notify(struct device *dev)
> }
> EXPORT_SYMBOL_GPL(platform_profile_notify);
>
> +/**
> + * platform_profile_cycle - Cycles profiles available on all registered class devices
> + *
> + * Return: 0 on success, -errno on failure
> + */
> int platform_profile_cycle(void)
> {
> enum platform_profile_option next = PLATFORM_PROFILE_LAST;
> @@ -478,6 +487,15 @@ int platform_profile_cycle(void)
> }
> EXPORT_SYMBOL_GPL(platform_profile_cycle);
>
> +/**
> + * platform_profile_register - Creates and registers a platform profile class device
> + * @dev: Parent device
> + * @name: Name of the class device
> + * @drvdata: Driver data that will be attached to the class device
> + * @ops: Platform profile's mandatory operations
> + *
> + * Return: pointer to the new class device on success, ERR_PTR on failure
> + */
> struct device *platform_profile_register(struct device *dev, const char *name,
> void *drvdata,
> const struct platform_profile_ops *ops)
> @@ -544,6 +562,12 @@ struct device *platform_profile_register(struct device *dev, const char *name,
> }
> EXPORT_SYMBOL_GPL(platform_profile_register);
>
> +/**
> + * platform_profile_remove - Unregisters a platform profile class device
> + * @dev: Class device
> + *
> + * Return: 0
> + */
> int platform_profile_remove(struct device *dev)
> {
> struct platform_profile_handler *pprof = to_pprof_handler(dev);
> @@ -569,6 +593,15 @@ static void devm_platform_profile_release(struct device *dev, void *res)
> platform_profile_remove(*ppdev);
> }
>
> +/**
> + * devm_platform_profile_register - Device managed version of platform_profile_register
> + * @dev: Parent device
> + * @name: Name of the class device
> + * @drvdata: Driver data that will be attached to the class device
> + * @ops: Platform profile's mandatory operations
> + *
> + * Return: pointer to the new class device on success, ERR_PTR on failure
> + */
> struct device *devm_platform_profile_register(struct device *dev, const char *name,
> void *drvdata,
> const struct platform_profile_ops *ops)
> diff --git a/include/linux/platform_profile.h b/include/linux/platform_profile.h
> index eea1daf85616..eb4dc85dc18c 100644
> --- a/include/linux/platform_profile.h
> +++ b/include/linux/platform_profile.h
> @@ -28,6 +28,30 @@ enum platform_profile_option {
> PLATFORM_PROFILE_LAST, /*must always be last */
> };
>
> +/**
> + * struct platform_profile_ops - platform profile operations
> + * @probe: Callback to setup choices available to the new class device.
> + * Parameters are:
> + * @drvdata: drvdata pointer passed to platform_profile_register.
> + * @choices: Empty choices bitmap which the driver has to manually
> + * setup, by using set_bit() in bits corresponding to
> + * platform_profile_option values. These values will only
> + * be enforced when a new profile is selected from
> + * user-space.
> + * @profile_get: Callback that will be called when showing the current platform
> + * profile.
> + * Parameters are:
> + * @dev: Class device.
> + * @profile: Pointer to the profile which will be read from
> + * user-space. Selected choices are not enforced when
> + * modifying this value.
> + * @profile_set: Callback that will be called when storing the new platform
> + * profile.
> + * Parameters are:
> + * @dev: Class device.
> + * @profile: New platform profile to be set. Guaranteed to be a
> + * value selected in the @probe callback.
Does kerneldoc render this sensibly?
> + */
> struct platform_profile_ops {
> int (*probe)(void *drvdata, unsigned long *choices);
> int (*profile_get)(struct device *dev, enum platform_profile_option *profile);
>
--
i.
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH v2 15/18] ACPI: platform_profile: Remove platform_profile_handler from exported symbols
2025-01-14 16:55 ` Ilpo Järvinen
@ 2025-01-14 17:13 ` Rafael J. Wysocki
2025-01-14 17:26 ` Kurt Borja
1 sibling, 0 replies; 33+ messages in thread
From: Rafael J. Wysocki @ 2025-01-14 17:13 UTC (permalink / raw)
To: Ilpo Järvinen
Cc: Kurt Borja, platform-driver-x86, Rafael J. Wysocki, Len Brown,
linux-acpi, LKML, Mario Limonciello, Armin Wolf, Joshua Grisham,
Derek J. Clark, Hans de Goede, Maximilian Luz, Lee, Chun-Yi,
Shyam Sundar S K, Corentin Chary, Luke D. Jones, Lyndon Sanche,
Ike Panhc, Henrique de Moraes Holschuh, Mark Pearson,
Alexis Belmonte, Ai Chao, Gergo Koteles, Dell.Client.Kernel,
ibm-acpi-devel
On Tue, Jan 14, 2025 at 5:55 PM Ilpo Järvinen
<ilpo.jarvinen@linux.intel.com> wrote:
>
> On Tue, 14 Jan 2025, Kurt Borja wrote:
>
> > In order to protect the platform_profile_handler from API consumers,
> > allocate it in platform_profile_register() and modify it's signature
> > accordingly.
> >
> > Remove the platform_profile_handler from all consumer drivers and
> > replace them with a pointer to the class device, which is
> > now returned from platform_profile_register().
> >
> > Replace *pprof with a pointer to the class device in the rest of
> > exported symbols.
> >
> > Signed-off-by: Kurt Borja <kuurtb@gmail.com>
> > ---
> > drivers/acpi/platform_profile.c | 87 ++++++++++++-------
> > .../surface/surface_platform_profile.c | 11 ++-
> > drivers/platform/x86/acer-wmi.c | 18 ++--
> > drivers/platform/x86/amd/pmf/pmf.h | 2 +-
> > drivers/platform/x86/amd/pmf/sps.c | 17 ++--
> > drivers/platform/x86/asus-wmi.c | 20 ++---
> > drivers/platform/x86/dell/alienware-wmi.c | 9 +-
> > drivers/platform/x86/dell/dell-pc.c | 22 ++---
> > drivers/platform/x86/hp/hp-wmi.c | 19 ++--
> > drivers/platform/x86/ideapad-laptop.c | 14 +--
> > .../platform/x86/inspur_platform_profile.c | 9 +-
> > drivers/platform/x86/thinkpad_acpi.c | 14 ++-
> > include/linux/platform_profile.h | 12 ++-
> > 13 files changed, 125 insertions(+), 129 deletions(-)
> >
> > diff --git a/drivers/acpi/platform_profile.c b/drivers/acpi/platform_profile.c
> > index 34e22b006ccc..2fae5e2fc962 100644
> > --- a/drivers/acpi/platform_profile.c
> > +++ b/drivers/acpi/platform_profile.c
> > @@ -4,6 +4,7 @@
> >
> > #include <linux/acpi.h>
> > #include <linux/bits.h>
> > +#include <linux/cleanup.h>
> > #include <linux/init.h>
> > #include <linux/kdev_t.h>
> > #include <linux/mutex.h>
> > @@ -213,9 +214,17 @@ static struct attribute *profile_attrs[] = {
> > };
> > ATTRIBUTE_GROUPS(profile);
> >
> > +static void pprof_device_release(struct device *dev)
> > +{
> > + struct platform_profile_handler *pprof = to_pprof_handler(dev);
> > +
> > + kfree(pprof);
> > +}
> > +
> > static const struct class platform_profile_class = {
> > .name = "platform-profile",
> > .dev_groups = profile_groups,
> > + .dev_release = pprof_device_release,
> > };
> >
> > /**
> > @@ -409,10 +418,10 @@ static const struct attribute_group platform_profile_group = {
> > .is_visible = profile_class_is_visible,
> > };
> >
> > -void platform_profile_notify(struct platform_profile_handler *pprof)
> > +void platform_profile_notify(struct device *dev)
> > {
> > scoped_cond_guard(mutex_intr, return, &profile_lock) {
> > - _notify_class_profile(&pprof->class_dev, NULL);
> > + _notify_class_profile(dev, NULL);
> > }
> > sysfs_notify(acpi_kobj, NULL, "platform_profile");
> > }
> > @@ -461,40 +470,51 @@ int platform_profile_cycle(void)
> > }
> > EXPORT_SYMBOL_GPL(platform_profile_cycle);
> >
> > -int platform_profile_register(struct platform_profile_handler *pprof, void *drvdata)
> > +struct device *platform_profile_register(struct device *dev, const char *name,
> > + void *drvdata,
> > + const struct platform_profile_ops *ops)
> > {
> > + int minor;
> > int err;
> >
> > - /* Sanity check the profile handler */
> > - if (!pprof || !pprof->ops->profile_set || !pprof->ops->profile_get ||
> > - !pprof->ops->probe) {
> > + /* Sanity check */
> > + if (!dev || !name || !ops || !ops->profile_get ||
> > + !ops->profile_set || !ops->probe) {
> > pr_err("platform_profile: handler is invalid\n");
> > - return -EINVAL;
> > + return ERR_PTR(-EINVAL);
> > }
> >
> > - err = pprof->ops->probe(drvdata, pprof->choices);
> > + struct platform_profile_handler *pprof __free(kfree) = kzalloc(
> > + sizeof(*pprof), GFP_KERNEL);
> > + if (!pprof)
> > + return ERR_PTR(-ENOMEM);
> > +
> > + err = ops->probe(drvdata, pprof->choices);
> > if (err < 0)
> > - return err;
> > + return ERR_PTR(err);
> >
> > if (bitmap_empty(pprof->choices, PLATFORM_PROFILE_LAST)) {
> > pr_err("platform_profile: no available profiles\n");
> > - return -EINVAL;
> > + return ERR_PTR(-EINVAL);
> > }
> >
> > guard(mutex)(&profile_lock);
> >
> > /* create class interface for individual handler */
> > - pprof->minor = ida_alloc(&platform_profile_ida, GFP_KERNEL);
> > - if (pprof->minor < 0)
> > - return pprof->minor;
> > + minor = ida_alloc(&platform_profile_ida, GFP_KERNEL);
> > + if (minor < 0)
> > + return ERR_PTR(minor);
> >
> > + pprof->name = name;
> > + pprof->ops = ops;
> > + pprof->minor = minor;
> > pprof->class_dev.class = &platform_profile_class;
> > - pprof->class_dev.parent = pprof->dev;
> > + pprof->class_dev.parent = dev;
> > dev_set_drvdata(&pprof->class_dev, drvdata);
> > dev_set_name(&pprof->class_dev, "platform-profile-%d", pprof->minor);
> > err = device_register(&pprof->class_dev);
> > if (err) {
> > - put_device(&pprof->class_dev);
> > + put_device(&no_free_ptr(pprof)->class_dev);
> > goto cleanup_ida;
> > }
> >
> > @@ -504,20 +524,21 @@ int platform_profile_register(struct platform_profile_handler *pprof, void *drvd
> > if (err)
> > goto cleanup_cur;
> >
> > - return 0;
> > + return &no_free_ptr(pprof)->class_dev;
> >
> > cleanup_cur:
> > - device_unregister(&pprof->class_dev);
> > + device_unregister(&no_free_ptr(pprof)->class_dev);
>
> I don't like how this is architected.
>
> IMO, no_free_ptr() should not appear on error/rollback paths. The pointer
> is going to be freed despite the code just told it's not going to be
> freed, which sends conflicting signals. Obviously, it is because this
> function has relinquished its ownership of the pointer but as is it seems
> a dangerous/confusing pattern.
I agree.
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH v2 00/18] Hide platform_profile_handler from consumers
2025-01-14 15:37 [PATCH v2 00/18] Hide platform_profile_handler from consumers Kurt Borja
` (17 preceding siblings ...)
2025-01-14 15:37 ` [PATCH v2 18/18] ACPI: platform_profile: Add documentation Kurt Borja
@ 2025-01-14 17:15 ` Rafael J. Wysocki
18 siblings, 0 replies; 33+ messages in thread
From: Rafael J. Wysocki @ 2025-01-14 17:15 UTC (permalink / raw)
To: Kurt Borja, Ilpo Järvinen
Cc: platform-driver-x86, Len Brown, linux-acpi, linux-kernel,
Mario Limonciello, Armin Wolf, Joshua Grisham, Derek J. Clark,
Hans de Goede, Maximilian Luz, Lee, Chun-Yi, Shyam Sundar S K,
Corentin Chary, Luke D. Jones, Lyndon Sanche, Ike Panhc,
Henrique de Moraes Holschuh, Mark Pearson, Alexis Belmonte,
Ai Chao, Gergo Koteles, Dell.Client.Kernel, ibm-acpi-devel
On Tue, Jan 14, 2025 at 4:38 PM Kurt Borja <kuurtb@gmail.com> wrote:
>
> Hello,
>
> As suggested by Mario, I moved patch 15/18 to position 3/18. This indeed
> simplified all diffs. Full reordering bellow.
>
> Series based on top of pdx86/for-next branch.
>
> ~ Kurt
> ---
> v1 -> v2:
>
> 01 -> 04
> 02 -> 05
> 03 -> 01
> 04 -> 02
> 05 -> 06
> 06 -> 07
> 07 -> 08
> 08 -> 09
> 09 -> 10
> 10 -> 11
> 11 -> 12
> 12 -> 13
> 13 -> 14
> 14 -> 15
> 15 -> 03
>
> [1/18]
> - Call put_device() if device_register() fails
>
> [2/18]
> - Set and use drvdata for every driver in these series, instead of
> patches 6-14
>
> [4/18]
> - Renamed the `choices` callback to `probe`
>
> [15/18]
> - Improve error handling in amd/pmf
> - Improve error handling in asus-wmi
>
> [18/18]
> - Fix typo
> - Added documentation to platform_profile_ops
>
> v1: https://lore.kernel.org/platform-driver-x86/20250109150731.110799-1-kuurtb@gmail.com/
>
> Kurt Borja (18):
> ACPI: platform_profile: Replace *class_dev member with class_dev
> ACPI: platform_profile: Let drivers set drvdata to the class device
> ACPI: platform_profile: Remove platform_profile_handler from callbacks
> ACPI: platform_profile: Add `ops` member to handlers
> ACPI: platform_profile: Add `probe` to platform_profile_ops
> platform/surface: surface_platform_profile: Use
> devm_platform_profile_register()
> platform/x86: acer-wmi: Use devm_platform_profile_register()
> platform/x86: amd: pmf: sps: Use devm_platform_profile_register()
> platform/x86: asus-wmi: Use devm_platform_profile_register()
> platform/x86: dell-pc: Use devm_platform_profile_register()
> platform/x86: ideapad-laptop: Use devm_platform_profile_register()
> platform/x86: hp-wmi: Use devm_platform_profile_register()
> platform/x86: inspur_platform_profile: Use
> devm_platform_profile_register()
> platform/x86: thinkpad_acpi: Use devm_platform_profile_register()
> ACPI: platform_profile: Remove platform_profile_handler from exported
> symbols
> ACPI: platform_profile: Move platform_profile_handler
> ACPI: platform_profile: Clean platform_profile_handler
> ACPI: platform_profile: Add documentation
>
> .../ABI/testing/sysfs-class-platform-profile | 44 +++++
> drivers/acpi/platform_profile.c | 164 +++++++++++++-----
> .../surface/surface_platform_profile.c | 48 ++---
> drivers/platform/x86/acer-wmi.c | 58 +++----
> drivers/platform/x86/amd/pmf/core.c | 1 -
> drivers/platform/x86/amd/pmf/pmf.h | 3 +-
> drivers/platform/x86/amd/pmf/sps.c | 51 +++---
> drivers/platform/x86/asus-wmi.c | 55 +++---
> drivers/platform/x86/dell/alienware-wmi.c | 33 ++--
> drivers/platform/x86/dell/dell-pc.c | 60 ++++---
> drivers/platform/x86/hp/hp-wmi.c | 83 +++++----
> drivers/platform/x86/ideapad-laptop.c | 44 +++--
> .../platform/x86/inspur_platform_profile.c | 48 +++--
> drivers/platform/x86/thinkpad_acpi.c | 37 ++--
> include/linux/platform_profile.h | 51 ++++--
> 15 files changed, 474 insertions(+), 306 deletions(-)
> create mode 100644 Documentation/ABI/testing/sysfs-class-platform-profile
>
>
> base-commit: 58126788aa7726c0e91de6b25e6e332fa06089ab
> --
Ilpo,
If you need any specific input from me on any patches in this series,
please let me know.
Otherwise, please feel free to route them all through platform/x86 when ready.
Thanks!
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH v2 15/18] ACPI: platform_profile: Remove platform_profile_handler from exported symbols
2025-01-14 16:55 ` Ilpo Järvinen
2025-01-14 17:13 ` Rafael J. Wysocki
@ 2025-01-14 17:26 ` Kurt Borja
2025-01-14 17:55 ` Ilpo Järvinen
1 sibling, 1 reply; 33+ messages in thread
From: Kurt Borja @ 2025-01-14 17:26 UTC (permalink / raw)
To: Ilpo Järvinen
Cc: platform-driver-x86, Rafael J. Wysocki, Len Brown, linux-acpi,
LKML, Mario Limonciello, Armin Wolf, Joshua Grisham,
Derek J. Clark, Hans de Goede, Maximilian Luz, Lee, Chun-Yi,
Shyam Sundar S K, Corentin Chary, Luke D. Jones, Lyndon Sanche,
Ike Panhc, Henrique de Moraes Holschuh, Mark Pearson,
Alexis Belmonte, Ai Chao, Gergo Koteles, Dell.Client.Kernel,
ibm-acpi-devel
Hi Ilpo,
On Tue, Jan 14, 2025 at 06:55:34PM +0200, Ilpo Järvinen wrote:
> On Tue, 14 Jan 2025, Kurt Borja wrote:
>
> > In order to protect the platform_profile_handler from API consumers,
> > allocate it in platform_profile_register() and modify it's signature
> > accordingly.
> >
> > Remove the platform_profile_handler from all consumer drivers and
> > replace them with a pointer to the class device, which is
> > now returned from platform_profile_register().
> >
> > Replace *pprof with a pointer to the class device in the rest of
> > exported symbols.
> >
> > Signed-off-by: Kurt Borja <kuurtb@gmail.com>
> > ---
> > drivers/acpi/platform_profile.c | 87 ++++++++++++-------
> > .../surface/surface_platform_profile.c | 11 ++-
> > drivers/platform/x86/acer-wmi.c | 18 ++--
> > drivers/platform/x86/amd/pmf/pmf.h | 2 +-
> > drivers/platform/x86/amd/pmf/sps.c | 17 ++--
> > drivers/platform/x86/asus-wmi.c | 20 ++---
> > drivers/platform/x86/dell/alienware-wmi.c | 9 +-
> > drivers/platform/x86/dell/dell-pc.c | 22 ++---
> > drivers/platform/x86/hp/hp-wmi.c | 19 ++--
> > drivers/platform/x86/ideapad-laptop.c | 14 +--
> > .../platform/x86/inspur_platform_profile.c | 9 +-
> > drivers/platform/x86/thinkpad_acpi.c | 14 ++-
> > include/linux/platform_profile.h | 12 ++-
> > 13 files changed, 125 insertions(+), 129 deletions(-)
> >
> > diff --git a/drivers/acpi/platform_profile.c b/drivers/acpi/platform_profile.c
> > index 34e22b006ccc..2fae5e2fc962 100644
> > --- a/drivers/acpi/platform_profile.c
> > +++ b/drivers/acpi/platform_profile.c
> > @@ -4,6 +4,7 @@
> >
> > #include <linux/acpi.h>
> > #include <linux/bits.h>
> > +#include <linux/cleanup.h>
> > #include <linux/init.h>
> > #include <linux/kdev_t.h>
> > #include <linux/mutex.h>
> > @@ -213,9 +214,17 @@ static struct attribute *profile_attrs[] = {
> > };
> > ATTRIBUTE_GROUPS(profile);
> >
> > +static void pprof_device_release(struct device *dev)
> > +{
> > + struct platform_profile_handler *pprof = to_pprof_handler(dev);
> > +
> > + kfree(pprof);
> > +}
> > +
> > static const struct class platform_profile_class = {
> > .name = "platform-profile",
> > .dev_groups = profile_groups,
> > + .dev_release = pprof_device_release,
> > };
> >
> > /**
> > @@ -409,10 +418,10 @@ static const struct attribute_group platform_profile_group = {
> > .is_visible = profile_class_is_visible,
> > };
> >
> > -void platform_profile_notify(struct platform_profile_handler *pprof)
> > +void platform_profile_notify(struct device *dev)
> > {
> > scoped_cond_guard(mutex_intr, return, &profile_lock) {
> > - _notify_class_profile(&pprof->class_dev, NULL);
> > + _notify_class_profile(dev, NULL);
> > }
> > sysfs_notify(acpi_kobj, NULL, "platform_profile");
> > }
> > @@ -461,40 +470,51 @@ int platform_profile_cycle(void)
> > }
> > EXPORT_SYMBOL_GPL(platform_profile_cycle);
> >
> > -int platform_profile_register(struct platform_profile_handler *pprof, void *drvdata)
> > +struct device *platform_profile_register(struct device *dev, const char *name,
> > + void *drvdata,
> > + const struct platform_profile_ops *ops)
> > {
> > + int minor;
> > int err;
> >
> > - /* Sanity check the profile handler */
> > - if (!pprof || !pprof->ops->profile_set || !pprof->ops->profile_get ||
> > - !pprof->ops->probe) {
> > + /* Sanity check */
> > + if (!dev || !name || !ops || !ops->profile_get ||
> > + !ops->profile_set || !ops->probe) {
> > pr_err("platform_profile: handler is invalid\n");
> > - return -EINVAL;
> > + return ERR_PTR(-EINVAL);
> > }
> >
> > - err = pprof->ops->probe(drvdata, pprof->choices);
> > + struct platform_profile_handler *pprof __free(kfree) = kzalloc(
> > + sizeof(*pprof), GFP_KERNEL);
> > + if (!pprof)
> > + return ERR_PTR(-ENOMEM);
> > +
> > + err = ops->probe(drvdata, pprof->choices);
> > if (err < 0)
> > - return err;
> > + return ERR_PTR(err);
> >
> > if (bitmap_empty(pprof->choices, PLATFORM_PROFILE_LAST)) {
> > pr_err("platform_profile: no available profiles\n");
> > - return -EINVAL;
> > + return ERR_PTR(-EINVAL);
> > }
> >
> > guard(mutex)(&profile_lock);
> >
> > /* create class interface for individual handler */
> > - pprof->minor = ida_alloc(&platform_profile_ida, GFP_KERNEL);
> > - if (pprof->minor < 0)
> > - return pprof->minor;
> > + minor = ida_alloc(&platform_profile_ida, GFP_KERNEL);
> > + if (minor < 0)
> > + return ERR_PTR(minor);
> >
> > + pprof->name = name;
> > + pprof->ops = ops;
> > + pprof->minor = minor;
> > pprof->class_dev.class = &platform_profile_class;
> > - pprof->class_dev.parent = pprof->dev;
> > + pprof->class_dev.parent = dev;
> > dev_set_drvdata(&pprof->class_dev, drvdata);
> > dev_set_name(&pprof->class_dev, "platform-profile-%d", pprof->minor);
> > err = device_register(&pprof->class_dev);
> > if (err) {
> > - put_device(&pprof->class_dev);
> > + put_device(&no_free_ptr(pprof)->class_dev);
> > goto cleanup_ida;
> > }
> >
> > @@ -504,20 +524,21 @@ int platform_profile_register(struct platform_profile_handler *pprof, void *drvd
> > if (err)
> > goto cleanup_cur;
> >
> > - return 0;
> > + return &no_free_ptr(pprof)->class_dev;
> >
> > cleanup_cur:
> > - device_unregister(&pprof->class_dev);
> > + device_unregister(&no_free_ptr(pprof)->class_dev);
>
> I don't like how this is architected.
>
> IMO, no_free_ptr() should not appear on error/rollback paths. The pointer
> is going to be freed despite the code just told it's not going to be
> freed, which sends conflicting signals. Obviously, it is because this
> function has relinquished its ownership of the pointer but as is it seems
> a dangerous/confusing pattern.
Makes sense.
Quick fix would be to replace `goto cleanup_cur` with
device_unregister(&no_free_ptr(pprof)->class_dev);
goto cleanup_ida;
and add a comment about ownership. Similar to the put_device() call
above. Is this ok? If not I will think of a better way of writing this.
>
> > cleanup_ida:
> > - ida_free(&platform_profile_ida, pprof->minor);
> > + ida_free(&platform_profile_ida, minor);
> >
> > - return err;
> > + return ERR_PTR(err);
> > }
> > EXPORT_SYMBOL_GPL(platform_profile_register);
> >
> > -int platform_profile_remove(struct platform_profile_handler *pprof)
> > +int platform_profile_remove(struct device *dev)
> > {
> > + struct platform_profile_handler *pprof = to_pprof_handler(dev);
> > int id;
> > guard(mutex)(&profile_lock);
> >
> > @@ -535,30 +556,32 @@ EXPORT_SYMBOL_GPL(platform_profile_remove);
> >
> > static void devm_platform_profile_release(struct device *dev, void *res)
> > {
> > - struct platform_profile_handler **pprof = res;
> > + struct device **ppdev = res;
> >
> > - platform_profile_remove(*pprof);
> > + platform_profile_remove(*ppdev);
> > }
> >
> > -int devm_platform_profile_register(struct platform_profile_handler *pprof, void *drvdata)
> > +struct device *devm_platform_profile_register(struct device *dev, const char *name,
> > + void *drvdata,
> > + const struct platform_profile_ops *ops)
> > {
> > - struct platform_profile_handler **dr;
> > - int ret;
> > + struct device *ppdev;
> > + struct device **dr;
> >
> > dr = devres_alloc(devm_platform_profile_release, sizeof(*dr), GFP_KERNEL);
> > if (!dr)
> > - return -ENOMEM;
> > + return ERR_PTR(-ENOMEM);
> >
> > - ret = platform_profile_register(pprof, drvdata);
> > - if (ret) {
> > + ppdev = platform_profile_register(dev, name, drvdata, ops);
> > + if (IS_ERR(dev)) {
> > devres_free(dr);
> > - return ret;
> > + return ppdev;
> > }
> >
> > - *dr = pprof;
> > - devres_add(pprof->dev, dr);
> > + *dr = ppdev;
> > + devres_add(dev, dr);
> >
> > - return 0;
> > + return ppdev;
> > }
> > EXPORT_SYMBOL_GPL(devm_platform_profile_register);
> >
> > diff --git a/drivers/platform/surface/surface_platform_profile.c b/drivers/platform/surface/surface_platform_profile.c
> > index bbdc873cb788..275269a6efc1 100644
> > --- a/drivers/platform/surface/surface_platform_profile.c
> > +++ b/drivers/platform/surface/surface_platform_profile.c
> > @@ -40,7 +40,7 @@ struct ssam_tmp_profile_info {
> >
> > struct ssam_platform_profile_device {
> > struct ssam_device *sdev;
> > - struct platform_profile_handler handler;
> > + struct device *ppdev;
> > bool has_fan;
> > };
> >
> > @@ -228,13 +228,12 @@ static int surface_platform_profile_probe(struct ssam_device *sdev)
> > tpd->sdev = sdev;
> > ssam_device_set_drvdata(sdev, tpd);
> >
> > - tpd->handler.name = "Surface Platform Profile";
> > - tpd->handler.dev = &sdev->dev;
> > - tpd->handler.ops = &ssam_platform_profile_ops;
> > -
> > tpd->has_fan = device_property_read_bool(&sdev->dev, "has_fan");
> >
> > - return devm_platform_profile_register(&tpd->handler, tpd);
> > + tpd->ppdev = devm_platform_profile_register(
>
> Extra space.
>
> > + &sdev->dev, "Surface Platform Profile", tpd, &ssam_platform_profile_ops);
>
> Could you try to split the line differently.
I will, for all of these files.
>
> > +
> > + return PTR_ERR_OR_ZERO(tpd->ppdev);
> > }
> >
> > static const struct ssam_device_id ssam_platform_profile_match[] = {
> > diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c
> > index 39ec236b7cdb..3e39465b3783 100644
> > --- a/drivers/platform/x86/acer-wmi.c
> > +++ b/drivers/platform/x86/acer-wmi.c
> > @@ -758,7 +758,7 @@ static const struct dmi_system_id non_acer_quirks[] __initconst = {
> > {}
> > };
> >
> > -static struct platform_profile_handler platform_profile_handler;
> > +static struct device *platform_profile_device;
> > static bool platform_profile_support;
> >
> > /*
> > @@ -1937,16 +1937,10 @@ static const struct platform_profile_ops acer_predator_v4_platform_profile_ops =
> > static int acer_platform_profile_setup(struct platform_device *device)
> > {
> > if (quirks->predator_v4) {
> > - int err;
> > -
> > - platform_profile_handler.name = "acer-wmi";
> > - platform_profile_handler.dev = &device->dev;
> > - platform_profile_handler.ops =
> > - &acer_predator_v4_platform_profile_ops;
> > -
> > - err = devm_platform_profile_register(&platform_profile_handler, NULL);
> > - if (err)
> > - return err;
> > + platform_profile_device = devm_platform_profile_register(
> > + &device->dev, "acer-wmi", NULL, &acer_predator_v4_platform_profile_ops);
> > + if (IS_ERR(platform_profile_device))
> > + return PTR_ERR(platform_profile_device);
> >
> > platform_profile_support = true;
> >
> > @@ -2033,7 +2027,7 @@ static int acer_thermal_profile_change(void)
> > if (tp != ACER_PREDATOR_V4_THERMAL_PROFILE_TURBO_WMI)
> > last_non_turbo_profile = tp;
> >
> > - platform_profile_notify(&platform_profile_handler);
> > + platform_profile_notify(platform_profile_device);
> > }
> >
> > return 0;
> > diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/x86/amd/pmf/pmf.h
> > index d99b3556205b..41b2b91b8fdc 100644
> > --- a/drivers/platform/x86/amd/pmf/pmf.h
> > +++ b/drivers/platform/x86/amd/pmf/pmf.h
> > @@ -338,7 +338,7 @@ struct amd_pmf_dev {
> > struct mutex lock; /* protects the PMF interface */
> > u32 supported_func;
> > enum platform_profile_option current_profile;
> > - struct platform_profile_handler pprof;
> > + struct device *ppdev; /* platform profile class device */
> > struct dentry *dbgfs_dir;
> > int hb_interval; /* SBIOS heartbeat interval */
> > struct delayed_work heart_beat;
> > diff --git a/drivers/platform/x86/amd/pmf/sps.c b/drivers/platform/x86/amd/pmf/sps.c
> > index 7c7ed2b9de01..a96fc6887cf0 100644
> > --- a/drivers/platform/x86/amd/pmf/sps.c
> > +++ b/drivers/platform/x86/amd/pmf/sps.c
> > @@ -404,8 +404,6 @@ static const struct platform_profile_ops amd_pmf_profile_ops = {
> >
> > int amd_pmf_init_sps(struct amd_pmf_dev *dev)
> > {
> > - int err;
> > -
> > dev->current_profile = PLATFORM_PROFILE_BALANCED;
> >
> > if (is_apmf_func_supported(dev, APMF_FUNC_STATIC_SLIDER_GRANULAR)) {
> > @@ -420,15 +418,12 @@ int amd_pmf_init_sps(struct amd_pmf_dev *dev)
> > amd_pmf_set_sps_power_limits(dev);
> > }
> >
> > - dev->pprof.name = "amd-pmf";
> > - dev->pprof.dev = dev->dev;
> > - dev->pprof.ops = &amd_pmf_profile_ops;
> > -
> > /* Create platform_profile structure and register */
> > - err = devm_platform_profile_register(&dev->pprof, dev);
> > - if (err)
> > - dev_err(dev->dev, "Failed to register SPS support, this is most likely an SBIOS bug: %d\n",
> > - err);
> > + dev->ppdev = devm_platform_profile_register(
> > + dev->dev, "amd-pmf", dev, &amd_pmf_profile_ops);
> > + if (IS_ERR(dev->ppdev))
> > + dev_err(dev->dev, "Failed to register SPS support, this is most likely an SBIOS bug: %ld\n",
> > + PTR_ERR(dev->ppdev));
> >
> > - return err;
> > + return PTR_ERR_OR_ZERO(dev->ppdev);
> > }
> > diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
> > index f8437cff66df..4ad99cf9df1a 100644
> > --- a/drivers/platform/x86/asus-wmi.c
> > +++ b/drivers/platform/x86/asus-wmi.c
> > @@ -313,7 +313,7 @@ struct asus_wmi {
> > bool mid_fan_curve_available;
> > struct fan_curve_data custom_fan_curves[3];
> >
> > - struct platform_profile_handler platform_profile_handler;
> > + struct device *platform_profile_device;
>
> Using both ppdev vs platform_profile_device for the same thing seems
> inconsistent. The long name also caused a few line split issues for you.
Ack.
I will rename all to ppdev.
Thank you very much for your feedback!
~ Kurt
>
> > bool platform_profile_support;
> >
> > // The RSOC controls the maximum charging percentage.
> > @@ -3789,7 +3789,7 @@ static ssize_t throttle_thermal_policy_store(struct device *dev,
> > * Ensure that platform_profile updates userspace with the change to ensure
> > * that platform_profile and throttle_thermal_policy_mode are in sync.
> > */
> > - platform_profile_notify(&asus->platform_profile_handler);
> > + platform_profile_notify(asus->platform_profile_device);
> >
> > return count;
> > }
> > @@ -3891,17 +3891,13 @@ static int platform_profile_setup(struct asus_wmi *asus)
> >
> > dev_info(dev, "Using throttle_thermal_policy for platform_profile support\n");
> >
> > - asus->platform_profile_handler.name = "asus-wmi";
> > - asus->platform_profile_handler.dev = dev;
> > - asus->platform_profile_handler.ops = &asus_wmi_platform_profile_ops;
> > + asus->platform_profile_device = devm_platform_profile_register(
> > + dev, "asus-wmi", asus, &asus_wmi_platform_profile_ops);
> > + if (IS_ERR(asus->platform_profile_device)) {
> > + pr_err("%s, failed at devm_platform_profile_register: %ld\n",
> > + __func__, PTR_ERR(asus->platform_profile_device));
> >
> > - err = devm_platform_profile_register(&asus->platform_profile_handler, asus);
> > - if (err == -EEXIST) {
> > - pr_warn("%s, a platform_profile handler is already registered\n", __func__);
> > - return 0;
> > - } else if (err) {
> > - pr_err("%s, failed at devm_platform_profile_register: %d\n", __func__, err);
> > - return err;
> > + return PTR_ERR(asus->platform_profile_device);
> > }
> >
> > asus->platform_profile_support = true;
> > diff --git a/drivers/platform/x86/dell/alienware-wmi.c b/drivers/platform/x86/dell/alienware-wmi.c
> > index 0146d2f93be6..99db93846a63 100644
> > --- a/drivers/platform/x86/dell/alienware-wmi.c
> > +++ b/drivers/platform/x86/dell/alienware-wmi.c
> > @@ -1135,11 +1135,12 @@ static const struct platform_profile_ops awcc_platform_profile_ops = {
> >
> > static int create_thermal_profile(struct platform_device *platform_device)
> > {
> > - pp_handler.name = "alienware-wmi";
> > - pp_handler.dev = &platform_device->dev;
> > - pp_handler.ops = &awcc_platform_profile_ops;
> > + struct device *ppdev;
> >
> > - return devm_platform_profile_register(&pp_handler, NULL);
> > + ppdev = devm_platform_profile_register(
> > + &platform_device->dev, "alienware-wmi", NULL, &awcc_platform_profile_ops);
>
> Not a good linesplit (there are other similar problems).
>
> > +
> > + return PTR_ERR_OR_ZERO(ppdev);
> > }
> >
> > /*
> > diff --git a/drivers/platform/x86/dell/dell-pc.c b/drivers/platform/x86/dell/dell-pc.c
> > index 2759bb608b1a..8d60e1b223de 100644
> > --- a/drivers/platform/x86/dell/dell-pc.c
> > +++ b/drivers/platform/x86/dell/dell-pc.c
> > @@ -109,8 +109,6 @@ MODULE_DEVICE_TABLE(dmi, dell_device_table);
> > #define DELL_ACC_SET_FIELD GENMASK(11, 8)
> > #define DELL_THERMAL_SUPPORTED GENMASK(3, 0)
> >
> > -static struct platform_profile_handler *thermal_handler;
> > -
> > enum thermal_mode_bits {
> > DELL_BALANCED = BIT(0),
> > DELL_COOL_BOTTOM = BIT(1),
> > @@ -254,6 +252,7 @@ static const struct platform_profile_ops dell_pc_platform_profile_ops = {
> >
> > static int thermal_init(void)
> > {
> > + struct device *ppdev;
> > int ret;
> >
> > /* If thermal commands are not supported, exit without error */
> > @@ -271,26 +270,17 @@ static int thermal_init(void)
> > if (IS_ERR(platform_device))
> > return PTR_ERR(platform_device);
> >
> > - thermal_handler = devm_kzalloc(&platform_device->dev, sizeof(*thermal_handler), GFP_KERNEL);
> > - if (!thermal_handler) {
> > - ret = -ENOMEM;
> > - goto cleanup_platform_device;
> > - }
> > - thermal_handler->name = "dell-pc";
> > - thermal_handler->dev = &platform_device->dev;
> > - thermal_handler->ops = &dell_pc_platform_profile_ops;
> > -
> > /* Clean up if failed */
> > - ret = devm_platform_profile_register(thermal_handler, NULL);
> > - if (ret)
> > + ppdev = devm_platform_profile_register(
> > + &platform_device->dev, "dell-pc", NULL, &dell_pc_platform_profile_ops);
> > + if (IS_ERR(ppdev)) {
> > + ret = PTR_ERR(ppdev);
> > goto cleanup_thermal_handler;
> > + }
> >
> > return 0;
> >
> > cleanup_thermal_handler:
> > - thermal_handler = NULL;
> > -
> > -cleanup_platform_device:
> > platform_device_unregister(platform_device);
> >
> > return ret;
> > diff --git a/drivers/platform/x86/hp/hp-wmi.c b/drivers/platform/x86/hp/hp-wmi.c
> > index 1304dfc65aab..d1f9bd287986 100644
> > --- a/drivers/platform/x86/hp/hp-wmi.c
> > +++ b/drivers/platform/x86/hp/hp-wmi.c
> > @@ -273,7 +273,7 @@ static DEFINE_MUTEX(active_platform_profile_lock);
> > static struct input_dev *hp_wmi_input_dev;
> > static struct input_dev *camera_shutter_input_dev;
> > static struct platform_device *hp_wmi_platform_dev;
> > -static struct platform_profile_handler platform_profile_handler;
> > +static struct device *platform_profile_device;
> > static struct notifier_block platform_power_source_nb;
> > static enum platform_profile_option active_platform_profile;
> > static bool platform_profile_support;
> > @@ -1602,6 +1602,7 @@ static const struct platform_profile_ops hp_wmi_platform_profile_ops = {
> >
> > static int thermal_profile_setup(struct platform_device *device)
> > {
> > + const struct platform_profile_ops *ops;
> > int err, tp;
> >
> > if (is_omen_thermal_profile()) {
> > @@ -1617,7 +1618,7 @@ static int thermal_profile_setup(struct platform_device *device)
> > if (err < 0)
> > return err;
> >
> > - platform_profile_handler.ops = &platform_profile_omen_ops;
> > + ops = &platform_profile_omen_ops;
> > } else if (is_victus_thermal_profile()) {
> > err = platform_profile_victus_get_ec(&active_platform_profile);
> > if (err < 0)
> > @@ -1631,7 +1632,7 @@ static int thermal_profile_setup(struct platform_device *device)
> > if (err < 0)
> > return err;
> >
> > - platform_profile_handler.ops = &platform_profile_victus_ops;
> > + ops = &platform_profile_victus_ops;
> > } else {
> > tp = thermal_profile_get();
> >
> > @@ -1646,15 +1647,13 @@ static int thermal_profile_setup(struct platform_device *device)
> > if (err)
> > return err;
> >
> > - platform_profile_handler.ops = &hp_wmi_platform_profile_ops;
> > + ops = &hp_wmi_platform_profile_ops;
> > }
> >
> > - platform_profile_handler.name = "hp-wmi";
> > - platform_profile_handler.dev = &device->dev;
> > -
> > - err = devm_platform_profile_register(&platform_profile_handler, NULL);
> > - if (err)
> > - return err;
> > + platform_profile_device = devm_platform_profile_register(
> > + &device->dev, "hp-wmi", NULL, ops);
> > + if (IS_ERR(platform_profile_device))
> > + return PTR_ERR(platform_profile_device);
> >
> > platform_profile_support = true;
> >
> > diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c
> > index 87c1e087770a..6065a7421a02 100644
> > --- a/drivers/platform/x86/ideapad-laptop.c
> > +++ b/drivers/platform/x86/ideapad-laptop.c
> > @@ -142,7 +142,7 @@ enum {
> >
> > struct ideapad_dytc_priv {
> > enum platform_profile_option current_profile;
> > - struct platform_profile_handler pprof;
> > + struct device *ppdev; /* platform profile device */
> > struct mutex mutex; /* protects the DYTC interface */
> > struct ideapad_private *priv;
> > };
> > @@ -1050,7 +1050,7 @@ static void dytc_profile_refresh(struct ideapad_private *priv)
> >
> > if (profile != priv->dytc->current_profile) {
> > priv->dytc->current_profile = profile;
> > - platform_profile_notify(&priv->dytc->pprof);
> > + platform_profile_notify(priv->dytc->ppdev);
> > }
> > }
> >
> > @@ -1117,15 +1117,15 @@ static int ideapad_dytc_profile_init(struct ideapad_private *priv)
> >
> > mutex_init(&priv->dytc->mutex);
> >
> > - priv->dytc->pprof.name = "ideapad-laptop";
> > - priv->dytc->pprof.dev = &priv->platform_device->dev;
> > priv->dytc->priv = priv;
> > - priv->dytc->pprof.ops = &dytc_profile_ops;
> >
> > /* Create platform_profile structure and register */
> > - err = devm_platform_profile_register(&priv->dytc->pprof, &priv->dytc);
> > - if (err)
> > + priv->dytc->ppdev = devm_platform_profile_register(
> > + &priv->platform_device->dev, "ideapad-laptop", &priv->dytc, &dytc_profile_ops);
> > + if (IS_ERR(priv->dytc->ppdev)) {
> > + err = PTR_ERR(priv->dytc->ppdev);
> > goto pp_reg_failed;
> > + }
> >
> > /* Ensure initial values are correct */
> > dytc_profile_refresh(priv);
> > diff --git a/drivers/platform/x86/inspur_platform_profile.c b/drivers/platform/x86/inspur_platform_profile.c
> > index e1631de6ad86..8b71c4242939 100644
> > --- a/drivers/platform/x86/inspur_platform_profile.c
> > +++ b/drivers/platform/x86/inspur_platform_profile.c
> > @@ -32,7 +32,7 @@ enum inspur_tmp_profile {
> >
> > struct inspur_wmi_priv {
> > struct wmi_device *wdev;
> > - struct platform_profile_handler handler;
> > + struct device *ppdev;
> > };
> >
> > static int inspur_wmi_perform_query(struct wmi_device *wdev,
> > @@ -190,11 +190,10 @@ static int inspur_wmi_probe(struct wmi_device *wdev, const void *context)
> > priv->wdev = wdev;
> > dev_set_drvdata(&wdev->dev, priv);
> >
> > - priv->handler.name = "inspur-wmi";
> > - priv->handler.dev = &wdev->dev;
> > - priv->handler.ops = &inspur_platform_profile_ops;
> > + priv->ppdev = devm_platform_profile_register(
> > + &wdev->dev, "inspur-wmi", priv, &inspur_platform_profile_ops);
> >
> > - return devm_platform_profile_register(&priv->handler, priv);
> > + return PTR_ERR_OR_ZERO(priv->ppdev);
> > }
> >
> > static const struct wmi_device_id inspur_wmi_id_table[] = {
> > diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
> > index 54ff3e6b8b1a..2a3dd0d149a1 100644
> > --- a/drivers/platform/x86/thinkpad_acpi.c
> > +++ b/drivers/platform/x86/thinkpad_acpi.c
> > @@ -962,6 +962,7 @@ static const struct proc_ops dispatch_proc_ops = {
> > static struct platform_device *tpacpi_pdev;
> > static struct platform_device *tpacpi_sensors_pdev;
> > static struct device *tpacpi_hwmon;
> > +static struct device *tpacpi_pprof;
> > static struct input_dev *tpacpi_inputdev;
> > static struct mutex tpacpi_inputdev_send_mutex;
> > static LIST_HEAD(tpacpi_all_drivers);
> > @@ -10553,11 +10554,6 @@ static const struct platform_profile_ops dytc_profile_ops = {
> > .profile_set = dytc_profile_set,
> > };
> >
> > -static struct platform_profile_handler dytc_profile = {
> > - .name = "thinkpad-acpi",
> > - .ops = &dytc_profile_ops,
> > -};
> > -
> > static void dytc_profile_refresh(void)
> > {
> > enum platform_profile_option profile;
> > @@ -10586,7 +10582,7 @@ static void dytc_profile_refresh(void)
> > err = convert_dytc_to_profile(funcmode, perfmode, &profile);
> > if (!err && profile != dytc_current_profile) {
> > dytc_current_profile = profile;
> > - platform_profile_notify(&dytc_profile);
> > + platform_profile_notify(tpacpi_pprof);
> > }
> > }
> >
> > @@ -10647,14 +10643,14 @@ static int tpacpi_dytc_profile_init(struct ibm_init_struct *iibm)
> > dbg_printk(TPACPI_DBG_INIT,
> > "DYTC version %d: thermal mode available\n", dytc_version);
> >
> > - dytc_profile.dev = &tpacpi_pdev->dev;
> > /* Create platform_profile structure and register */
> > - err = devm_platform_profile_register(&dytc_profile, NULL);
> > + tpacpi_pprof = devm_platform_profile_register(
> > + &tpacpi_pdev->dev, "thinkpad-acpi", NULL, &dytc_profile_ops);
> > /*
> > * If for some reason platform_profiles aren't enabled
> > * don't quit terminally.
> > */
> > - if (err)
> > + if (IS_ERR(tpacpi_pprof))
> > return -ENODEV;
> >
> > /* Ensure initial values are correct */
> > diff --git a/include/linux/platform_profile.h b/include/linux/platform_profile.h
> > index 5ad1ab7b75e4..778d4c661c3c 100644
> > --- a/include/linux/platform_profile.h
> > +++ b/include/linux/platform_profile.h
> > @@ -45,10 +45,14 @@ struct platform_profile_handler {
> > const struct platform_profile_ops *ops;
> > };
> >
> > -int platform_profile_register(struct platform_profile_handler *pprof, void *drvdata);
> > -int platform_profile_remove(struct platform_profile_handler *pprof);
> > -int devm_platform_profile_register(struct platform_profile_handler *pprof, void *drvdata);
> > +struct device *platform_profile_register(struct device *dev, const char *name,
> > + void *drvdata,
> > + const struct platform_profile_ops *ops);
> > +int platform_profile_remove(struct device *dev);
> > +struct device *devm_platform_profile_register(struct device *dev, const char *name,
> > + void *drvdata,
> > + const struct platform_profile_ops *ops);
> > int platform_profile_cycle(void);
> > -void platform_profile_notify(struct platform_profile_handler *pprof);
> > +void platform_profile_notify(struct device *dev);
> >
> > #endif /*_PLATFORM_PROFILE_H_*/
> >
>
> --
> i.
>
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH v2 18/18] ACPI: platform_profile: Add documentation
2025-01-14 16:57 ` Ilpo Järvinen
@ 2025-01-14 17:27 ` Kurt Borja
0 siblings, 0 replies; 33+ messages in thread
From: Kurt Borja @ 2025-01-14 17:27 UTC (permalink / raw)
To: Ilpo Järvinen
Cc: platform-driver-x86, Rafael J. Wysocki, Len Brown, linux-acpi,
LKML, Mario Limonciello, Armin Wolf, Joshua Grisham,
Derek J. Clark, Hans de Goede, Maximilian Luz, Lee, Chun-Yi,
Shyam Sundar S K, Corentin Chary, Luke D. Jones, Lyndon Sanche,
Ike Panhc, Henrique de Moraes Holschuh, Mark Pearson,
Alexis Belmonte, Ai Chao, Gergo Koteles, Dell.Client.Kernel,
ibm-acpi-devel
On Tue, Jan 14, 2025 at 06:57:11PM +0200, Ilpo Järvinen wrote:
> On Tue, 14 Jan 2025, Kurt Borja wrote:
>
> > Add kerneldoc and sysfs class documentation.
> >
> > Signed-off-by: Kurt Borja <kuurtb@gmail.com>
> > ---
> > .../ABI/testing/sysfs-class-platform-profile | 44 +++++++++++++++++++
> > drivers/acpi/platform_profile.c | 33 ++++++++++++++
> > include/linux/platform_profile.h | 24 ++++++++++
> > 3 files changed, 101 insertions(+)
> > create mode 100644 Documentation/ABI/testing/sysfs-class-platform-profile
> >
> > diff --git a/Documentation/ABI/testing/sysfs-class-platform-profile b/Documentation/ABI/testing/sysfs-class-platform-profile
> > new file mode 100644
> > index 000000000000..b5a3600080bc
> > --- /dev/null
> > +++ b/Documentation/ABI/testing/sysfs-class-platform-profile
> > @@ -0,0 +1,44 @@
> > +What: /sys/class/platform-profile/platform-profile-X/name
> > +Date: January 2025
> > +Description: Name of the class device given by the driver.
> > +
> > + RO
> > +
> > +What: /sys/class/platform-profile/platform-profile-X/choices
> > +Date: January 2025
> > +Description: This file contains a space-separated list of profiles supported for this device.
> > +
> > + Drivers must use the following standard profile-names:
> > +
> > + ==================== ========================================
> > + low-power Low power consumption
> > + cool Cooler operation
> > + quiet Quieter operation
> > + balanced Balance between low power consumption
> > + and performance
> > + balanced-performance Balance between performance and low
> > + power consumption with a slight bias
> > + towards performance
> > + performance High performance operation
> > + custom Driver defined custom profile
> > + ==================== ========================================
> > +
> > + RO
> > +
> > +What: /sys/class/platform-profile/platform-profile-X/profile
> > +Date: January 2025
> > +Description: Reading this file gives the current selected profile for this
> > + device. Writing this file with one of the strings from
> > + platform_profile_choices changes the profile to the new value.
> > +
> > + This file can be monitored for changes by polling for POLLPRI,
> > + POLLPRI will be signaled on any changes, independent of those
> > + changes coming from a userspace write; or coming from another
> > + source such as e.g. a hotkey triggered profile change handled
> > + either directly by the embedded-controller or fully handled
> > + inside the kernel.
> > +
> > + This file may also emit the string 'custom' to indicate
> > + that the driver is using a driver defined custom profile.
> > +
> > + RW
> > diff --git a/drivers/acpi/platform_profile.c b/drivers/acpi/platform_profile.c
> > index c44989801f8e..9caddac695b8 100644
> > --- a/drivers/acpi/platform_profile.c
> > +++ b/drivers/acpi/platform_profile.c
> > @@ -426,6 +426,10 @@ static const struct attribute_group platform_profile_group = {
> > .is_visible = profile_class_is_visible,
> > };
> >
> > +/**
> > + * platform_profile_notify - Notify class device and legacy sysfs interface
> > + * @dev: The class device
> > + */
> > void platform_profile_notify(struct device *dev)
> > {
> > scoped_cond_guard(mutex_intr, return, &profile_lock) {
> > @@ -435,6 +439,11 @@ void platform_profile_notify(struct device *dev)
> > }
> > EXPORT_SYMBOL_GPL(platform_profile_notify);
> >
> > +/**
> > + * platform_profile_cycle - Cycles profiles available on all registered class devices
> > + *
> > + * Return: 0 on success, -errno on failure
> > + */
> > int platform_profile_cycle(void)
> > {
> > enum platform_profile_option next = PLATFORM_PROFILE_LAST;
> > @@ -478,6 +487,15 @@ int platform_profile_cycle(void)
> > }
> > EXPORT_SYMBOL_GPL(platform_profile_cycle);
> >
> > +/**
> > + * platform_profile_register - Creates and registers a platform profile class device
> > + * @dev: Parent device
> > + * @name: Name of the class device
> > + * @drvdata: Driver data that will be attached to the class device
> > + * @ops: Platform profile's mandatory operations
> > + *
> > + * Return: pointer to the new class device on success, ERR_PTR on failure
> > + */
> > struct device *platform_profile_register(struct device *dev, const char *name,
> > void *drvdata,
> > const struct platform_profile_ops *ops)
> > @@ -544,6 +562,12 @@ struct device *platform_profile_register(struct device *dev, const char *name,
> > }
> > EXPORT_SYMBOL_GPL(platform_profile_register);
> >
> > +/**
> > + * platform_profile_remove - Unregisters a platform profile class device
> > + * @dev: Class device
> > + *
> > + * Return: 0
> > + */
> > int platform_profile_remove(struct device *dev)
> > {
> > struct platform_profile_handler *pprof = to_pprof_handler(dev);
> > @@ -569,6 +593,15 @@ static void devm_platform_profile_release(struct device *dev, void *res)
> > platform_profile_remove(*ppdev);
> > }
> >
> > +/**
> > + * devm_platform_profile_register - Device managed version of platform_profile_register
> > + * @dev: Parent device
> > + * @name: Name of the class device
> > + * @drvdata: Driver data that will be attached to the class device
> > + * @ops: Platform profile's mandatory operations
> > + *
> > + * Return: pointer to the new class device on success, ERR_PTR on failure
> > + */
> > struct device *devm_platform_profile_register(struct device *dev, const char *name,
> > void *drvdata,
> > const struct platform_profile_ops *ops)
> > diff --git a/include/linux/platform_profile.h b/include/linux/platform_profile.h
> > index eea1daf85616..eb4dc85dc18c 100644
> > --- a/include/linux/platform_profile.h
> > +++ b/include/linux/platform_profile.h
> > @@ -28,6 +28,30 @@ enum platform_profile_option {
> > PLATFORM_PROFILE_LAST, /*must always be last */
> > };
> >
> > +/**
> > + * struct platform_profile_ops - platform profile operations
> > + * @probe: Callback to setup choices available to the new class device.
> > + * Parameters are:
> > + * @drvdata: drvdata pointer passed to platform_profile_register.
> > + * @choices: Empty choices bitmap which the driver has to manually
> > + * setup, by using set_bit() in bits corresponding to
> > + * platform_profile_option values. These values will only
> > + * be enforced when a new profile is selected from
> > + * user-space.
> > + * @profile_get: Callback that will be called when showing the current platform
> > + * profile.
> > + * Parameters are:
> > + * @dev: Class device.
> > + * @profile: Pointer to the profile which will be read from
> > + * user-space. Selected choices are not enforced when
> > + * modifying this value.
> > + * @profile_set: Callback that will be called when storing the new platform
> > + * profile.
> > + * Parameters are:
> > + * @dev: Class device.
> > + * @profile: New platform profile to be set. Guaranteed to be a
> > + * value selected in the @probe callback.
>
> Does kerneldoc render this sensibly?
It does not!
That's my bad, I copied the pattern from hwmon.h which also does not
render correctly.
I'll fix it.
~ Kurt
>
> > + */
> > struct platform_profile_ops {
> > int (*probe)(void *drvdata, unsigned long *choices);
> > int (*profile_get)(struct device *dev, enum platform_profile_option *profile);
> >
>
> --
> i.
>
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH v2 15/18] ACPI: platform_profile: Remove platform_profile_handler from exported symbols
2025-01-14 17:26 ` Kurt Borja
@ 2025-01-14 17:55 ` Ilpo Järvinen
2025-01-15 2:45 ` Kurt Borja
0 siblings, 1 reply; 33+ messages in thread
From: Ilpo Järvinen @ 2025-01-14 17:55 UTC (permalink / raw)
To: Kurt Borja
Cc: platform-driver-x86, Rafael J. Wysocki, Len Brown, linux-acpi,
LKML, Mario Limonciello, Armin Wolf, Joshua Grisham,
Derek J. Clark, Hans de Goede, Maximilian Luz, Lee, Chun-Yi,
Shyam Sundar S K, Corentin Chary, Luke D. Jones, Lyndon Sanche,
Ike Panhc, Henrique de Moraes Holschuh, Mark Pearson,
Alexis Belmonte, Ai Chao, Gergo Koteles, Dell.Client.Kernel,
ibm-acpi-devel
[-- Attachment #1: Type: text/plain, Size: 5174 bytes --]
On Tue, 14 Jan 2025, Kurt Borja wrote:
> On Tue, Jan 14, 2025 at 06:55:34PM +0200, Ilpo Järvinen wrote:
> > On Tue, 14 Jan 2025, Kurt Borja wrote:
> >
> > > In order to protect the platform_profile_handler from API consumers,
> > > allocate it in platform_profile_register() and modify it's signature
> > > accordingly.
> > >
> > > Remove the platform_profile_handler from all consumer drivers and
> > > replace them with a pointer to the class device, which is
> > > now returned from platform_profile_register().
> > >
> > > Replace *pprof with a pointer to the class device in the rest of
> > > exported symbols.
> > >
> > > Signed-off-by: Kurt Borja <kuurtb@gmail.com>
> > > ---
> > > -int platform_profile_register(struct platform_profile_handler *pprof, void *drvdata)
> > > +struct device *platform_profile_register(struct device *dev, const char *name,
> > > + void *drvdata,
> > > + const struct platform_profile_ops *ops)
> > > {
> > > + int minor;
> > > int err;
> > >
> > > - /* Sanity check the profile handler */
> > > - if (!pprof || !pprof->ops->profile_set || !pprof->ops->profile_get ||
> > > - !pprof->ops->probe) {
> > > + /* Sanity check */
> > > + if (!dev || !name || !ops || !ops->profile_get ||
> > > + !ops->profile_set || !ops->probe) {
> > > pr_err("platform_profile: handler is invalid\n");
> > > - return -EINVAL;
> > > + return ERR_PTR(-EINVAL);
> > > }
> > >
> > > - err = pprof->ops->probe(drvdata, pprof->choices);
> > > + struct platform_profile_handler *pprof __free(kfree) = kzalloc(
> > > + sizeof(*pprof), GFP_KERNEL);
> > > + if (!pprof)
> > > + return ERR_PTR(-ENOMEM);
> > > +
> > > + err = ops->probe(drvdata, pprof->choices);
> > > if (err < 0)
> > > - return err;
> > > + return ERR_PTR(err);
> > >
> > > if (bitmap_empty(pprof->choices, PLATFORM_PROFILE_LAST)) {
> > > pr_err("platform_profile: no available profiles\n");
> > > - return -EINVAL;
> > > + return ERR_PTR(-EINVAL);
> > > }
> > >
> > > guard(mutex)(&profile_lock);
> > >
> > > /* create class interface for individual handler */
> > > - pprof->minor = ida_alloc(&platform_profile_ida, GFP_KERNEL);
> > > - if (pprof->minor < 0)
> > > - return pprof->minor;
> > > + minor = ida_alloc(&platform_profile_ida, GFP_KERNEL);
> > > + if (minor < 0)
> > > + return ERR_PTR(minor);
> > >
> > > + pprof->name = name;
> > > + pprof->ops = ops;
> > > + pprof->minor = minor;
> > > pprof->class_dev.class = &platform_profile_class;
> > > - pprof->class_dev.parent = pprof->dev;
> > > + pprof->class_dev.parent = dev;
> > > dev_set_drvdata(&pprof->class_dev, drvdata);
> > > dev_set_name(&pprof->class_dev, "platform-profile-%d", pprof->minor);
> > > err = device_register(&pprof->class_dev);
> > > if (err) {
> > > - put_device(&pprof->class_dev);
> > > + put_device(&no_free_ptr(pprof)->class_dev);
> > > goto cleanup_ida;
> > > }
> > >
> > > @@ -504,20 +524,21 @@ int platform_profile_register(struct platform_profile_handler *pprof, void *drvd
> > > if (err)
> > > goto cleanup_cur;
> > >
> > > - return 0;
> > > + return &no_free_ptr(pprof)->class_dev;
> > >
> > > cleanup_cur:
> > > - device_unregister(&pprof->class_dev);
> > > + device_unregister(&no_free_ptr(pprof)->class_dev);
> >
> > I don't like how this is architected.
> >
> > IMO, no_free_ptr() should not appear on error/rollback paths. The pointer
> > is going to be freed despite the code just told it's not going to be
> > freed, which sends conflicting signals. Obviously, it is because this
> > function has relinquished its ownership of the pointer but as is it seems
> > a dangerous/confusing pattern.
>
> Makes sense.
>
> Quick fix would be to replace `goto cleanup_cur` with
>
> device_unregister(&no_free_ptr(pprof)->class_dev);
> goto cleanup_ida;
>
> and add a comment about ownership. Similar to the put_device() call
> above. Is this ok? If not I will think of a better way of writing this.
I think it would still be on the error path which is undesirable. While a
comment would make it understandable, it would be more logical to call
no_free_ptr() near device_register() which is when the ownership
gets transferred.
The trouble with that approach then is that no_free_ptr(pprof) will set
the pprof to NULL because of how the internal cleanup magic prevents
automatic freeing of pprof (Don't ask me how I know about that trap :-D).
I suppose you could take pointer of the pprof->class_dev into a local
variable before making the device_register() call since that is all you
need after that point?
So my suggestion is along the lines of:
/* device_register() takes the ownership of the pointer */
class_dev = &no_free_ptr(pprof)->class_dev;
err = device_register(class_dev);
...
> > > cleanup_ida:
> > > - ida_free(&platform_profile_ida, pprof->minor);
> > > + ida_free(&platform_profile_ida, minor);
> > >
> > > - return err;
> > > + return ERR_PTR(err);
> > > }
> > > EXPORT_SYMBOL_GPL(platform_profile_register);
--
i.
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH v2 15/18] ACPI: platform_profile: Remove platform_profile_handler from exported symbols
2025-01-14 17:55 ` Ilpo Järvinen
@ 2025-01-15 2:45 ` Kurt Borja
0 siblings, 0 replies; 33+ messages in thread
From: Kurt Borja @ 2025-01-15 2:45 UTC (permalink / raw)
To: Ilpo Järvinen
Cc: platform-driver-x86, Rafael J. Wysocki, Len Brown, linux-acpi,
LKML, Mario Limonciello, Armin Wolf, Joshua Grisham,
Derek J. Clark, Hans de Goede, Maximilian Luz, Lee, Chun-Yi,
Shyam Sundar S K, Corentin Chary, Luke D. Jones, Lyndon Sanche,
Ike Panhc, Henrique de Moraes Holschuh, Mark Pearson,
Alexis Belmonte, Ai Chao, Gergo Koteles, Dell.Client.Kernel,
ibm-acpi-devel
On Tue, Jan 14, 2025 at 07:55:53PM +0200, Ilpo Järvinen wrote:
> On Tue, 14 Jan 2025, Kurt Borja wrote:
> > On Tue, Jan 14, 2025 at 06:55:34PM +0200, Ilpo Järvinen wrote:
> > > On Tue, 14 Jan 2025, Kurt Borja wrote:
> > >
> > > > In order to protect the platform_profile_handler from API consumers,
> > > > allocate it in platform_profile_register() and modify it's signature
> > > > accordingly.
> > > >
> > > > Remove the platform_profile_handler from all consumer drivers and
> > > > replace them with a pointer to the class device, which is
> > > > now returned from platform_profile_register().
> > > >
> > > > Replace *pprof with a pointer to the class device in the rest of
> > > > exported symbols.
> > > >
> > > > Signed-off-by: Kurt Borja <kuurtb@gmail.com>
> > > > ---
>
> > > > -int platform_profile_register(struct platform_profile_handler *pprof, void *drvdata)
> > > > +struct device *platform_profile_register(struct device *dev, const char *name,
> > > > + void *drvdata,
> > > > + const struct platform_profile_ops *ops)
> > > > {
> > > > + int minor;
> > > > int err;
> > > >
> > > > - /* Sanity check the profile handler */
> > > > - if (!pprof || !pprof->ops->profile_set || !pprof->ops->profile_get ||
> > > > - !pprof->ops->probe) {
> > > > + /* Sanity check */
> > > > + if (!dev || !name || !ops || !ops->profile_get ||
> > > > + !ops->profile_set || !ops->probe) {
> > > > pr_err("platform_profile: handler is invalid\n");
> > > > - return -EINVAL;
> > > > + return ERR_PTR(-EINVAL);
> > > > }
> > > >
> > > > - err = pprof->ops->probe(drvdata, pprof->choices);
> > > > + struct platform_profile_handler *pprof __free(kfree) = kzalloc(
> > > > + sizeof(*pprof), GFP_KERNEL);
> > > > + if (!pprof)
> > > > + return ERR_PTR(-ENOMEM);
> > > > +
> > > > + err = ops->probe(drvdata, pprof->choices);
> > > > if (err < 0)
> > > > - return err;
> > > > + return ERR_PTR(err);
> > > >
> > > > if (bitmap_empty(pprof->choices, PLATFORM_PROFILE_LAST)) {
> > > > pr_err("platform_profile: no available profiles\n");
> > > > - return -EINVAL;
> > > > + return ERR_PTR(-EINVAL);
> > > > }
> > > >
> > > > guard(mutex)(&profile_lock);
> > > >
> > > > /* create class interface for individual handler */
> > > > - pprof->minor = ida_alloc(&platform_profile_ida, GFP_KERNEL);
> > > > - if (pprof->minor < 0)
> > > > - return pprof->minor;
> > > > + minor = ida_alloc(&platform_profile_ida, GFP_KERNEL);
> > > > + if (minor < 0)
> > > > + return ERR_PTR(minor);
> > > >
> > > > + pprof->name = name;
> > > > + pprof->ops = ops;
> > > > + pprof->minor = minor;
> > > > pprof->class_dev.class = &platform_profile_class;
> > > > - pprof->class_dev.parent = pprof->dev;
> > > > + pprof->class_dev.parent = dev;
> > > > dev_set_drvdata(&pprof->class_dev, drvdata);
> > > > dev_set_name(&pprof->class_dev, "platform-profile-%d", pprof->minor);
> > > > err = device_register(&pprof->class_dev);
> > > > if (err) {
> > > > - put_device(&pprof->class_dev);
> > > > + put_device(&no_free_ptr(pprof)->class_dev);
> > > > goto cleanup_ida;
> > > > }
> > > >
> > > > @@ -504,20 +524,21 @@ int platform_profile_register(struct platform_profile_handler *pprof, void *drvd
> > > > if (err)
> > > > goto cleanup_cur;
> > > >
> > > > - return 0;
> > > > + return &no_free_ptr(pprof)->class_dev;
> > > >
> > > > cleanup_cur:
> > > > - device_unregister(&pprof->class_dev);
> > > > + device_unregister(&no_free_ptr(pprof)->class_dev);
> > >
> > > I don't like how this is architected.
> > >
> > > IMO, no_free_ptr() should not appear on error/rollback paths. The pointer
> > > is going to be freed despite the code just told it's not going to be
> > > freed, which sends conflicting signals. Obviously, it is because this
> > > function has relinquished its ownership of the pointer but as is it seems
> > > a dangerous/confusing pattern.
> >
> > Makes sense.
> >
> > Quick fix would be to replace `goto cleanup_cur` with
> >
> > device_unregister(&no_free_ptr(pprof)->class_dev);
> > goto cleanup_ida;
> >
> > and add a comment about ownership. Similar to the put_device() call
> > above. Is this ok? If not I will think of a better way of writing this.
>
> I think it would still be on the error path which is undesirable. While a
> comment would make it understandable, it would be more logical to call
> no_free_ptr() near device_register() which is when the ownership
> gets transferred.
>
> The trouble with that approach then is that no_free_ptr(pprof) will set
> the pprof to NULL because of how the internal cleanup magic prevents
> automatic freeing of pprof (Don't ask me how I know about that trap :-D).
:')
>
> I suppose you could take pointer of the pprof->class_dev into a local
> variable before making the device_register() call since that is all you
> need after that point?
>
> So my suggestion is along the lines of:
>
> /* device_register() takes the ownership of the pointer */
> class_dev = &no_free_ptr(pprof)->class_dev;
> err = device_register(class_dev);
> ...
Yes, this makes a lot of sense. I will do it this way.
Thanks Ilpo.
~ Kurt
>
>
> > > > cleanup_ida:
> > > > - ida_free(&platform_profile_ida, pprof->minor);
> > > > + ida_free(&platform_profile_ida, minor);
> > > >
> > > > - return err;
> > > > + return ERR_PTR(err);
> > > > }
> > > > EXPORT_SYMBOL_GPL(platform_profile_register);
>
> --
> i.
>
^ permalink raw reply [flat|nested] 33+ messages in thread
end of thread, other threads:[~2025-01-15 2:45 UTC | newest]
Thread overview: 33+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-01-14 15:37 [PATCH v2 00/18] Hide platform_profile_handler from consumers Kurt Borja
2025-01-14 15:37 ` [PATCH v2 01/18] ACPI: platform_profile: Replace *class_dev member with class_dev Kurt Borja
2025-01-14 15:37 ` [PATCH v2 02/18] ACPI: platform_profile: Let drivers set drvdata to the class device Kurt Borja
2025-01-14 15:37 ` [PATCH v2 03/18] ACPI: platform_profile: Remove platform_profile_handler from callbacks Kurt Borja
2025-01-14 15:59 ` Mario Limonciello
2025-01-14 15:37 ` [PATCH v2 04/18] ACPI: platform_profile: Add `ops` member to handlers Kurt Borja
2025-01-14 15:37 ` [PATCH v2 05/18] ACPI: platform_profile: Add `probe` to platform_profile_ops Kurt Borja
2025-01-14 16:20 ` Mario Limonciello
2025-01-14 16:31 ` Kurt Borja
2025-01-14 16:36 ` Mario Limonciello
2025-01-14 15:37 ` [PATCH v2 06/18] platform/surface: surface_platform_profile: Use devm_platform_profile_register() Kurt Borja
2025-01-14 15:37 ` [PATCH v2 07/18] platform/x86: acer-wmi: " Kurt Borja
2025-01-14 15:37 ` [PATCH v2 08/18] platform/x86: amd: pmf: sps: " Kurt Borja
2025-01-14 15:37 ` [PATCH v2 09/18] platform/x86: asus-wmi: " Kurt Borja
2025-01-14 15:37 ` [PATCH v2 10/18] platform/x86: dell-pc: " Kurt Borja
2025-01-14 15:37 ` [PATCH v2 11/18] platform/x86: ideapad-laptop: " Kurt Borja
2025-01-14 15:37 ` [PATCH v2 12/18] platform/x86: hp-wmi: " Kurt Borja
2025-01-14 15:37 ` [PATCH v2 13/18] platform/x86: inspur_platform_profile: " Kurt Borja
2025-01-14 15:37 ` [PATCH v2 14/18] platform/x86: thinkpad_acpi: " Kurt Borja
2025-01-14 15:37 ` [PATCH v2 15/18] ACPI: platform_profile: Remove platform_profile_handler from exported symbols Kurt Borja
2025-01-14 16:22 ` Mario Limonciello
2025-01-14 16:55 ` Ilpo Järvinen
2025-01-14 17:13 ` Rafael J. Wysocki
2025-01-14 17:26 ` Kurt Borja
2025-01-14 17:55 ` Ilpo Järvinen
2025-01-15 2:45 ` Kurt Borja
2025-01-14 15:37 ` [PATCH v2 16/18] ACPI: platform_profile: Move platform_profile_handler Kurt Borja
2025-01-14 15:37 ` [PATCH v2 17/18] ACPI: platform_profile: Clean platform_profile_handler Kurt Borja
2025-01-14 15:37 ` [PATCH v2 18/18] ACPI: platform_profile: Add documentation Kurt Borja
2025-01-14 16:24 ` Mario Limonciello
2025-01-14 16:57 ` Ilpo Järvinen
2025-01-14 17:27 ` Kurt Borja
2025-01-14 17:15 ` [PATCH v2 00/18] Hide platform_profile_handler from consumers Rafael J. Wysocki
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox