From 9b3bb37b44a317626464e79da8b39989b421963f Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Thu, 5 Dec 2024 21:19:00 -0600 Subject: ACPI: platform_profile: Add platform handler argument to platform_profile_remove() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To allow registering and unregistering multiple platform handlers calls to platform_profile_remove() will need to know which handler is to be removed. Add an argument for this. Tested-by: Mark Pearson Tested-by: Matthew Schwartz Reviewed-by: Hans de Goede Reviewed-by: Mark Pearson Reviewed-by: Maximilian Luz Reviewed-by: Ilpo Järvinen Reviewed-by: Armin Wolf Signed-off-by: Mario Limonciello Link: https://lore.kernel.org/r/20241206031918.1537-5-mario.limonciello@amd.com Signed-off-by: Ilpo Järvinen --- drivers/acpi/platform_profile.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/acpi/platform_profile.c') diff --git a/drivers/acpi/platform_profile.c b/drivers/acpi/platform_profile.c index d2f7fd7743a1..c24744da2091 100644 --- a/drivers/acpi/platform_profile.c +++ b/drivers/acpi/platform_profile.c @@ -205,7 +205,7 @@ int platform_profile_register(struct platform_profile_handler *pprof) } EXPORT_SYMBOL_GPL(platform_profile_register); -int platform_profile_remove(void) +int platform_profile_remove(struct platform_profile_handler *pprof) { sysfs_remove_group(acpi_kobj, &platform_profile_group); -- cgit v1.2.3 From 4d5c027bf55661da2621c694ea39908ae2d3a46a Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Thu, 5 Dec 2024 21:19:01 -0600 Subject: ACPI: platform_profile: Pass the profile handler into platform_profile_notify() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The profile handler will be used to notify the appropriate class devices. Reviewed-by: Armin Wolf Reviewed-by: Mark Pearson Signed-off-by: Mario Limonciello Link: https://lore.kernel.org/r/20241206031918.1537-6-mario.limonciello@amd.com Reviewed-by: Ilpo Järvinen Signed-off-by: Ilpo Järvinen --- drivers/acpi/platform_profile.c | 2 +- drivers/platform/x86/acer-wmi.c | 2 +- drivers/platform/x86/asus-wmi.c | 2 +- drivers/platform/x86/ideapad-laptop.c | 2 +- drivers/platform/x86/thinkpad_acpi.c | 14 +++++++------- include/linux/platform_profile.h | 2 +- 6 files changed, 12 insertions(+), 12 deletions(-) (limited to 'drivers/acpi/platform_profile.c') diff --git a/drivers/acpi/platform_profile.c b/drivers/acpi/platform_profile.c index c24744da2091..927a2f7456c9 100644 --- a/drivers/acpi/platform_profile.c +++ b/drivers/acpi/platform_profile.c @@ -128,7 +128,7 @@ static const struct attribute_group platform_profile_group = { .attrs = platform_profile_attrs }; -void platform_profile_notify(void) +void platform_profile_notify(struct platform_profile_handler *pprof) { if (!cur_profile) return; diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c index b12965d9fcdb..001881825807 100644 --- a/drivers/platform/x86/acer-wmi.c +++ b/drivers/platform/x86/acer-wmi.c @@ -1988,7 +1988,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_notify(&platform_profile_handler); } return 0; diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c index 805bce80beef..fdeebab96fc0 100644 --- a/drivers/platform/x86/asus-wmi.c +++ b/drivers/platform/x86/asus-wmi.c @@ -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(); + platform_profile_notify(&asus->platform_profile_handler); return count; } diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c index 95b66ac3ea1d..00b9c0c32239 100644 --- a/drivers/platform/x86/ideapad-laptop.c +++ b/drivers/platform/x86/ideapad-laptop.c @@ -1041,7 +1041,7 @@ static void dytc_profile_refresh(struct ideapad_private *priv) if (profile != priv->dytc->current_profile) { priv->dytc->current_profile = profile; - platform_profile_notify(); + platform_profile_notify(&priv->dytc->pprof); } } diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index 298100d5c535..f51662861738 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -10538,6 +10538,12 @@ unlock: return err; } +static struct platform_profile_handler dytc_profile = { + .name = "thinkpad-acpi", + .profile_get = dytc_profile_get, + .profile_set = dytc_profile_set, +}; + static void dytc_profile_refresh(void) { enum platform_profile_option profile; @@ -10566,16 +10572,10 @@ 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(); + platform_profile_notify(&dytc_profile); } } -static struct platform_profile_handler dytc_profile = { - .name = "thinkpad-acpi", - .profile_get = dytc_profile_get, - .profile_set = dytc_profile_set, -}; - static int tpacpi_dytc_profile_init(struct ibm_init_struct *iibm) { int err, output; diff --git a/include/linux/platform_profile.h b/include/linux/platform_profile.h index bcaf3aa39160..8ec0b8da56db 100644 --- a/include/linux/platform_profile.h +++ b/include/linux/platform_profile.h @@ -39,6 +39,6 @@ struct platform_profile_handler { int platform_profile_register(struct platform_profile_handler *pprof); int platform_profile_remove(struct platform_profile_handler *pprof); int platform_profile_cycle(void); -void platform_profile_notify(void); +void platform_profile_notify(struct platform_profile_handler *pprof); #endif /*_PLATFORM_PROFILE_H_*/ -- cgit v1.2.3 From 585484003dedaa35ffc8d1ead3f3334af021dee7 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Thu, 5 Dec 2024 21:19:02 -0600 Subject: ACPI: platform_profile: Move sanity check out of the mutex MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The sanity check that the platform handler had choices set doesn't need the mutex taken. Move it to earlier in the registration. Tested-by: Mark Pearson Tested-by: Matthew Schwartz Reviewed-by: Ilpo Järvinen Reviewed-by: Mark Pearson Reviewed-by: Armin Wolf Signed-off-by: Mario Limonciello Link: https://lore.kernel.org/r/20241206031918.1537-7-mario.limonciello@amd.com Signed-off-by: Ilpo Järvinen --- drivers/acpi/platform_profile.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers/acpi/platform_profile.c') diff --git a/drivers/acpi/platform_profile.c b/drivers/acpi/platform_profile.c index 927a2f7456c9..4f5623fc27c0 100644 --- a/drivers/acpi/platform_profile.c +++ b/drivers/acpi/platform_profile.c @@ -179,6 +179,13 @@ int platform_profile_register(struct platform_profile_handler *pprof) { int err; + /* Sanity check the profile handler */ + if (!pprof || bitmap_empty(pprof->choices, PLATFORM_PROFILE_LAST) || + !pprof->profile_set || !pprof->profile_get) { + pr_err("platform_profile: handler is invalid\n"); + return -EINVAL; + } + mutex_lock(&profile_lock); /* We can only have one active profile */ if (cur_profile) { @@ -186,13 +193,6 @@ int platform_profile_register(struct platform_profile_handler *pprof) return -EEXIST; } - /* Sanity check the profile handler field are set */ - if (!pprof || bitmap_empty(pprof->choices, PLATFORM_PROFILE_LAST) || - !pprof->profile_set || !pprof->profile_get) { - mutex_unlock(&profile_lock); - return -EINVAL; - } - err = sysfs_create_group(acpi_kobj, &platform_profile_group); if (err) { mutex_unlock(&profile_lock); -- cgit v1.2.3 From ab431a20756a0e755c91a5df78c8c70e0fbecd80 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Thu, 5 Dec 2024 21:19:03 -0600 Subject: ACPI: platform_profile: Move matching string for new profile out of mutex MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Holding the mutex is not necessary while scanning the string passed into platform_profile_store(). Tested-by: Mark Pearson Reviewed-by: Ilpo Järvinen Reviewed-by: Armin Wolf Reviewed-by: Mark Pearson Signed-off-by: Mario Limonciello Link: https://lore.kernel.org/r/20241206031918.1537-8-mario.limonciello@amd.com Signed-off-by: Ilpo Järvinen --- drivers/acpi/platform_profile.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'drivers/acpi/platform_profile.c') diff --git a/drivers/acpi/platform_profile.c b/drivers/acpi/platform_profile.c index 4f5623fc27c0..45ffd85a71dd 100644 --- a/drivers/acpi/platform_profile.c +++ b/drivers/acpi/platform_profile.c @@ -83,6 +83,11 @@ static ssize_t platform_profile_store(struct device *dev, { int err, i; + /* Scan for a matching profile */ + i = sysfs_match_string(profile_names, buf); + if (i < 0) + return -EINVAL; + err = mutex_lock_interruptible(&profile_lock); if (err) return err; @@ -92,13 +97,6 @@ static ssize_t platform_profile_store(struct device *dev, return -ENODEV; } - /* Scan for a matching profile */ - i = sysfs_match_string(profile_names, buf); - if (i < 0) { - mutex_unlock(&profile_lock); - return -EINVAL; - } - /* Check that platform supports this profile choice */ if (!test_bit(i, cur_profile->choices)) { mutex_unlock(&profile_lock); -- cgit v1.2.3 From 55b1e68134bfa041960282fdefef7f3e56add703 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Thu, 5 Dec 2024 21:19:04 -0600 Subject: ACPI: platform_profile: Use guard(mutex) for register/unregister MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit guard(mutex) can be used to automatically release mutexes when going out of scope. Tested-by: Mark Pearson Tested-by: Matthew Schwartz Reviewed-by: Hans de Goede Reviewed-by: Mark Pearson Reviewed-by: Ilpo Järvinen Reviewed-by: Armin Wolf Signed-off-by: Mario Limonciello Link: https://lore.kernel.org/r/20241206031918.1537-9-mario.limonciello@amd.com Signed-off-by: Ilpo Järvinen --- drivers/acpi/platform_profile.c | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) (limited to 'drivers/acpi/platform_profile.c') diff --git a/drivers/acpi/platform_profile.c b/drivers/acpi/platform_profile.c index 45ffd85a71dd..9729543df633 100644 --- a/drivers/acpi/platform_profile.c +++ b/drivers/acpi/platform_profile.c @@ -184,32 +184,26 @@ int platform_profile_register(struct platform_profile_handler *pprof) return -EINVAL; } - mutex_lock(&profile_lock); + guard(mutex)(&profile_lock); /* We can only have one active profile */ - if (cur_profile) { - mutex_unlock(&profile_lock); + if (cur_profile) return -EEXIST; - } err = sysfs_create_group(acpi_kobj, &platform_profile_group); - if (err) { - mutex_unlock(&profile_lock); + if (err) return err; - } cur_profile = pprof; - mutex_unlock(&profile_lock); return 0; } EXPORT_SYMBOL_GPL(platform_profile_register); int platform_profile_remove(struct platform_profile_handler *pprof) { - sysfs_remove_group(acpi_kobj, &platform_profile_group); + guard(mutex)(&profile_lock); - mutex_lock(&profile_lock); + sysfs_remove_group(acpi_kobj, &platform_profile_group); cur_profile = NULL; - mutex_unlock(&profile_lock); return 0; } EXPORT_SYMBOL_GPL(platform_profile_remove); -- cgit v1.2.3 From 1f3ac55c2e65af30a37a460a1a7cc5c7eb74747d Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Thu, 5 Dec 2024 21:19:05 -0600 Subject: ACPI: platform_profile: Use `scoped_cond_guard` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Migrate away from using an interruptible mutex to scoped_cond_guard in all functions. While changing, move the sysfs notification used in platform_profile_store() outside of mutex scope. Reviewed-by: Armin Wolf Tested-by: Mark Pearson Reviewed-by: Mark Pearson Reviewed-by: Ilpo Järvinen Signed-off-by: Mario Limonciello Link: https://lore.kernel.org/r/20241206031918.1537-10-mario.limonciello@amd.com Signed-off-by: Ilpo Järvinen --- drivers/acpi/platform_profile.c | 105 +++++++++++++++------------------------- 1 file changed, 38 insertions(+), 67 deletions(-) (limited to 'drivers/acpi/platform_profile.c') diff --git a/drivers/acpi/platform_profile.c b/drivers/acpi/platform_profile.c index 9729543df633..a1f0378f15e6 100644 --- a/drivers/acpi/platform_profile.c +++ b/drivers/acpi/platform_profile.c @@ -27,25 +27,16 @@ static ssize_t platform_profile_choices_show(struct device *dev, char *buf) { int len = 0; - int err, i; - - err = mutex_lock_interruptible(&profile_lock); - if (err) - return err; + int i; - if (!cur_profile) { - mutex_unlock(&profile_lock); - return -ENODEV; - } - - for_each_set_bit(i, cur_profile->choices, PLATFORM_PROFILE_LAST) { - if (len == 0) - len += sysfs_emit_at(buf, len, "%s", profile_names[i]); - else - len += sysfs_emit_at(buf, len, " %s", profile_names[i]); + scoped_cond_guard(mutex_intr, return -ERESTARTSYS, &profile_lock) { + if (!cur_profile) + return -ENODEV; + for_each_set_bit(i, cur_profile->choices, PLATFORM_PROFILE_LAST) + len += sysfs_emit_at(buf, len, len ? " %s": "%s", profile_names[i]); } len += sysfs_emit_at(buf, len, "\n"); - mutex_unlock(&profile_lock); + return len; } @@ -56,20 +47,15 @@ static ssize_t platform_profile_show(struct device *dev, enum platform_profile_option profile = PLATFORM_PROFILE_BALANCED; int err; - err = mutex_lock_interruptible(&profile_lock); - if (err) - return err; + scoped_cond_guard(mutex_intr, return -ERESTARTSYS, &profile_lock) { + if (!cur_profile) + return -ENODEV; - if (!cur_profile) { - mutex_unlock(&profile_lock); - return -ENODEV; + err = cur_profile->profile_get(cur_profile, &profile); + if (err) + return err; } - err = cur_profile->profile_get(cur_profile, &profile); - mutex_unlock(&profile_lock); - if (err) - return err; - /* Check that profile is valid index */ if (WARN_ON((profile < 0) || (profile >= ARRAY_SIZE(profile_names)))) return -EIO; @@ -88,28 +74,21 @@ static ssize_t platform_profile_store(struct device *dev, if (i < 0) return -EINVAL; - err = mutex_lock_interruptible(&profile_lock); - if (err) - return err; + scoped_cond_guard(mutex_intr, return -ERESTARTSYS, &profile_lock) { + if (!cur_profile) + return -ENODEV; - if (!cur_profile) { - mutex_unlock(&profile_lock); - return -ENODEV; - } + /* Check that platform supports this profile choice */ + if (!test_bit(i, cur_profile->choices)) + return -EOPNOTSUPP; - /* Check that platform supports this profile choice */ - if (!test_bit(i, cur_profile->choices)) { - mutex_unlock(&profile_lock); - return -EOPNOTSUPP; + err = cur_profile->profile_set(cur_profile, i); + if (err) + return err; } - err = cur_profile->profile_set(cur_profile, i); - if (!err) - sysfs_notify(acpi_kobj, NULL, "platform_profile"); + sysfs_notify(acpi_kobj, NULL, "platform_profile"); - mutex_unlock(&profile_lock); - if (err) - return err; return count; } @@ -140,36 +119,28 @@ int platform_profile_cycle(void) enum platform_profile_option next; int err; - err = mutex_lock_interruptible(&profile_lock); - if (err) - return err; + scoped_cond_guard(mutex_intr, return -ERESTARTSYS, &profile_lock) { + if (!cur_profile) + return -ENODEV; - if (!cur_profile) { - mutex_unlock(&profile_lock); - return -ENODEV; - } + err = cur_profile->profile_get(cur_profile, &profile); + if (err) + return err; - err = cur_profile->profile_get(cur_profile, &profile); - if (err) { - mutex_unlock(&profile_lock); - return err; - } + next = find_next_bit_wrap(cur_profile->choices, PLATFORM_PROFILE_LAST, + profile + 1); - next = find_next_bit_wrap(cur_profile->choices, PLATFORM_PROFILE_LAST, - profile + 1); + if (WARN_ON(next == PLATFORM_PROFILE_LAST)) + return -EINVAL; - if (WARN_ON(next == PLATFORM_PROFILE_LAST)) { - mutex_unlock(&profile_lock); - return -EINVAL; + err = cur_profile->profile_set(cur_profile, next); + if (err) + return err; } - err = cur_profile->profile_set(cur_profile, next); - mutex_unlock(&profile_lock); - - if (!err) - sysfs_notify(acpi_kobj, NULL, "platform_profile"); + sysfs_notify(acpi_kobj, NULL, "platform_profile"); - return err; + return 0; } EXPORT_SYMBOL_GPL(platform_profile_cycle); -- cgit v1.2.3 From 77be5cacb2c2d8c3ddd069f0b4e9408f553af1d8 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Thu, 5 Dec 2024 21:19:06 -0600 Subject: ACPI: platform_profile: Create class for ACPI platform profile MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When registering a platform profile handler create a class device that will allow changing a single platform profile handler. The class and sysfs group are no longer needed when the platform profile core is a module and unloaded, so remove them at that time as well. Reviewed-by: Armin Wolf Tested-by: Mark Pearson Reviewed-by: Mark Pearson Reviewed-by: Ilpo Järvinen Signed-off-by: Mario Limonciello Link: https://lore.kernel.org/r/20241206031918.1537-11-mario.limonciello@amd.com Signed-off-by: Ilpo Järvinen --- drivers/acpi/platform_profile.c | 82 +++++++++++++++++++++++++++++++++++++--- include/linux/platform_profile.h | 2 + 2 files changed, 79 insertions(+), 5 deletions(-) (limited to 'drivers/acpi/platform_profile.c') diff --git a/drivers/acpi/platform_profile.c b/drivers/acpi/platform_profile.c index a1f0378f15e6..11eb60b09bac 100644 --- a/drivers/acpi/platform_profile.c +++ b/drivers/acpi/platform_profile.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -22,6 +23,12 @@ static const char * const profile_names[] = { }; static_assert(ARRAY_SIZE(profile_names) == PLATFORM_PROFILE_LAST); +static DEFINE_IDA(platform_profile_ida); + +static const struct class platform_profile_class = { + .name = "platform-profile", +}; + static ssize_t platform_profile_choices_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -101,8 +108,21 @@ static struct attribute *platform_profile_attrs[] = { NULL }; +static int profile_class_registered(struct device *dev, const void *data) +{ + return 1; +} + +static umode_t profile_class_is_visible(struct kobject *kobj, struct attribute *attr, int idx) +{ + if (!class_find_device(&platform_profile_class, NULL, NULL, profile_class_registered)) + return 0; + return attr->mode; +} + static const struct attribute_group platform_profile_group = { - .attrs = platform_profile_attrs + .attrs = platform_profile_attrs, + .is_visible = profile_class_is_visible, }; void platform_profile_notify(struct platform_profile_handler *pprof) @@ -160,25 +180,77 @@ int platform_profile_register(struct platform_profile_handler *pprof) if (cur_profile) return -EEXIST; - err = sysfs_create_group(acpi_kobj, &platform_profile_group); - if (err) - return err; + /* create class interface for individual handler */ + 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); + goto cleanup_ida; + } cur_profile = pprof; + + err = sysfs_update_group(acpi_kobj, &platform_profile_group); + if (err) + goto cleanup_cur; + return 0; + +cleanup_cur: + cur_profile = NULL; + device_unregister(pprof->class_dev); + +cleanup_ida: + ida_free(&platform_profile_ida, pprof->minor); + + return err; } EXPORT_SYMBOL_GPL(platform_profile_register); int platform_profile_remove(struct platform_profile_handler *pprof) { + int id; guard(mutex)(&profile_lock); - sysfs_remove_group(acpi_kobj, &platform_profile_group); cur_profile = NULL; + + id = pprof->minor; + device_unregister(pprof->class_dev); + ida_free(&platform_profile_ida, id); + + sysfs_update_group(acpi_kobj, &platform_profile_group); + return 0; } EXPORT_SYMBOL_GPL(platform_profile_remove); +static int __init platform_profile_init(void) +{ + int err; + + err = class_register(&platform_profile_class); + if (err) + return err; + + err = sysfs_create_group(acpi_kobj, &platform_profile_group); + if (err) + class_unregister(&platform_profile_class); + + return err; +} + +static void __exit platform_profile_exit(void) +{ + sysfs_remove_group(acpi_kobj, &platform_profile_group); + class_unregister(&platform_profile_class); +} +module_init(platform_profile_init); +module_exit(platform_profile_exit); + MODULE_AUTHOR("Mark Pearson "); MODULE_DESCRIPTION("ACPI platform profile sysfs interface"); MODULE_LICENSE("GPL"); diff --git a/include/linux/platform_profile.h b/include/linux/platform_profile.h index 8ec0b8da56db..a888fd085c51 100644 --- a/include/linux/platform_profile.h +++ b/include/linux/platform_profile.h @@ -29,6 +29,8 @@ enum platform_profile_option { 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 platform_profile_handler *pprof, enum platform_profile_option *profile); -- cgit v1.2.3 From 97cab71d712b4066e3807c3e33990d6ed7506c2d Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Thu, 5 Dec 2024 21:19:07 -0600 Subject: ACPI: platform_profile: Add name attribute to class interface MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The name attribute shows the name of the associated platform profile handler. Tested-by: Mark Pearson Reviewed-by: Ilpo Järvinen Reviewed-by: Armin Wolf Reviewed-by: Mark Pearson Signed-off-by: Mario Limonciello Link: https://lore.kernel.org/r/20241206031918.1537-12-mario.limonciello@amd.com Signed-off-by: Ilpo Järvinen --- drivers/acpi/platform_profile.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'drivers/acpi/platform_profile.c') diff --git a/drivers/acpi/platform_profile.c b/drivers/acpi/platform_profile.c index 11eb60b09bac..49a8bd6e97ec 100644 --- a/drivers/acpi/platform_profile.c +++ b/drivers/acpi/platform_profile.c @@ -25,8 +25,31 @@ static_assert(ARRAY_SIZE(profile_names) == PLATFORM_PROFILE_LAST); static DEFINE_IDA(platform_profile_ida); +/** + * name_show - Show the name of the profile handler + * @dev: The device + * @attr: The attribute + * @buf: The buffer to write to + * + * Return: The number of bytes written + */ +static ssize_t name_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct platform_profile_handler *handler = dev_get_drvdata(dev); + + return sysfs_emit(buf, "%s\n", handler->name); +} +static DEVICE_ATTR_RO(name); + +static struct attribute *profile_attrs[] = { + &dev_attr_name.attr, + NULL +}; +ATTRIBUTE_GROUPS(profile); + static const struct class platform_profile_class = { .name = "platform-profile", + .dev_groups = profile_groups, }; static ssize_t platform_profile_choices_show(struct device *dev, -- cgit v1.2.3 From 52a67be8ee274b14984df1a9f7ae157e11bc08ab Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Thu, 5 Dec 2024 21:19:08 -0600 Subject: ACPI: platform_profile: Add choices attribute for class interface MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The `choices` file will show all possible choices that a given platform profile handler can support. Tested-by: Mark Pearson Reviewed-by: Ilpo Järvinen Reviewed-by: Armin Wolf Reviewed-by: Mark Pearson Signed-off-by: Mario Limonciello Link: https://lore.kernel.org/r/20241206031918.1537-13-mario.limonciello@amd.com Signed-off-by: Ilpo Järvinen --- drivers/acpi/platform_profile.c | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) (limited to 'drivers/acpi/platform_profile.c') diff --git a/drivers/acpi/platform_profile.c b/drivers/acpi/platform_profile.c index 49a8bd6e97ec..885f41bca6c2 100644 --- a/drivers/acpi/platform_profile.c +++ b/drivers/acpi/platform_profile.c @@ -25,6 +25,28 @@ static_assert(ARRAY_SIZE(profile_names) == PLATFORM_PROFILE_LAST); static DEFINE_IDA(platform_profile_ida); +/** + * _commmon_choices_show - Show the available profile choices + * @choices: The available profile choices + * @buf: The buffer to write to + * + * Return: The number of bytes written + */ +static ssize_t _commmon_choices_show(unsigned long *choices, char *buf) +{ + int i, len = 0; + + for_each_set_bit(i, choices, PLATFORM_PROFILE_LAST) { + if (len == 0) + len += sysfs_emit_at(buf, len, "%s", profile_names[i]); + else + len += sysfs_emit_at(buf, len, " %s", profile_names[i]); + } + len += sysfs_emit_at(buf, len, "\n"); + + return len; +} + /** * name_show - Show the name of the profile handler * @dev: The device @@ -41,8 +63,27 @@ static ssize_t name_show(struct device *dev, struct device_attribute *attr, char } static DEVICE_ATTR_RO(name); +/** + * choices_show - Show the available profile choices + * @dev: The device + * @attr: The attribute + * @buf: The buffer to write to + * + * Return: The number of bytes written + */ +static ssize_t choices_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct platform_profile_handler *handler = dev_get_drvdata(dev); + + return _commmon_choices_show(handler->choices, buf); +} +static DEVICE_ATTR_RO(choices); + static struct attribute *profile_attrs[] = { &dev_attr_name.attr, + &dev_attr_choices.attr, NULL }; ATTRIBUTE_GROUPS(profile); -- cgit v1.2.3 From d2785e39429a33966b010bcc89b169e93c6597f7 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Thu, 5 Dec 2024 21:19:09 -0600 Subject: ACPI: platform_profile: Add profile attribute for class interface MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reading and writing the `profile` sysfs file will use the callbacks for the platform profile handler to read or set the given profile. Tested-by: Mark Pearson Reviewed-by: Mark Pearson Reviewed-by: Armin Wolf Reviewed-by: Ilpo Järvinen Signed-off-by: Mario Limonciello Link: https://lore.kernel.org/r/20241206031918.1537-14-mario.limonciello@amd.com Signed-off-by: Ilpo Järvinen --- drivers/acpi/platform_profile.c | 105 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) (limited to 'drivers/acpi/platform_profile.c') diff --git a/drivers/acpi/platform_profile.c b/drivers/acpi/platform_profile.c index 885f41bca6c2..d2c83cb25829 100644 --- a/drivers/acpi/platform_profile.c +++ b/drivers/acpi/platform_profile.c @@ -47,6 +47,55 @@ static ssize_t _commmon_choices_show(unsigned long *choices, char *buf) return len; } +/** + * _store_class_profile - Set the profile for a class device + * @dev: The class device + * @data: The profile to set + * + * Return: 0 on success, -errno on failure + */ +static int _store_class_profile(struct device *dev, void *data) +{ + struct platform_profile_handler *handler; + int *bit = (int *)data; + + lockdep_assert_held(&profile_lock); + handler = dev_get_drvdata(dev); + if (!test_bit(*bit, handler->choices)) + return -EOPNOTSUPP; + + return handler->profile_set(handler, *bit); +} + +/** + * get_class_profile - Show the current profile for a class device + * @dev: The class device + * @profile: The profile to return + * + * Return: 0 on success, -errno on failure + */ +static int get_class_profile(struct device *dev, + enum platform_profile_option *profile) +{ + struct platform_profile_handler *handler; + enum platform_profile_option val; + int err; + + lockdep_assert_held(&profile_lock); + handler = dev_get_drvdata(dev); + err = handler->profile_get(handler, &val); + if (err) { + pr_err("Failed to get profile for handler %s\n", handler->name); + return err; + } + + if (WARN_ON(val >= PLATFORM_PROFILE_LAST)) + return -EINVAL; + *profile = val; + + return 0; +} + /** * name_show - Show the name of the profile handler * @dev: The device @@ -81,9 +130,65 @@ static ssize_t choices_show(struct device *dev, } static DEVICE_ATTR_RO(choices); +/** + * profile_show - Show the current profile for a class device + * @dev: The device + * @attr: The attribute + * @buf: The buffer to write to + * + * Return: The number of bytes written + */ +static ssize_t profile_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + enum platform_profile_option profile = PLATFORM_PROFILE_LAST; + int err; + + scoped_cond_guard(mutex_intr, return -ERESTARTSYS, &profile_lock) { + err = get_class_profile(dev, &profile); + if (err) + return err; + } + + return sysfs_emit(buf, "%s\n", profile_names[profile]); +} + +/** + * profile_store - Set the profile for a class device + * @dev: The device + * @attr: The attribute + * @buf: The buffer to read from + * @count: The number of bytes to read + * + * Return: The number of bytes read + */ +static ssize_t profile_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + int index, ret; + + index = sysfs_match_string(profile_names, buf); + if (index < 0) + return -EINVAL; + + scoped_cond_guard(mutex_intr, return -ERESTARTSYS, &profile_lock) { + ret = _store_class_profile(dev, &index); + if (ret) + return ret; + } + + sysfs_notify(acpi_kobj, NULL, "platform_profile"); + + return count; +} +static DEVICE_ATTR_RW(profile); + static struct attribute *profile_attrs[] = { &dev_attr_name.attr, &dev_attr_choices.attr, + &dev_attr_profile.attr, NULL }; ATTRIBUTE_GROUPS(profile); -- cgit v1.2.3 From e5fe5ddc38ffd389433032f9ab121774b6b2980a Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Thu, 5 Dec 2024 21:19:10 -0600 Subject: ACPI: platform_profile: Notify change events on register and unregister MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As multiple platform profile handlers may come and go, send a notification to userspace each time that a platform profile handler is registered or unregistered. Reviewed-by: Armin Wolf Tested-by: Mark Pearson Tested-by: Matthew Schwartz Reviewed-by: Mark Pearson Signed-off-by: Mario Limonciello Link: https://lore.kernel.org/r/20241206031918.1537-15-mario.limonciello@amd.com Signed-off-by: Ilpo Järvinen --- drivers/acpi/platform_profile.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/acpi/platform_profile.c') diff --git a/drivers/acpi/platform_profile.c b/drivers/acpi/platform_profile.c index d2c83cb25829..2a4f067c3c5c 100644 --- a/drivers/acpi/platform_profile.c +++ b/drivers/acpi/platform_profile.c @@ -361,6 +361,8 @@ int platform_profile_register(struct platform_profile_handler *pprof) goto cleanup_ida; } + sysfs_notify(acpi_kobj, NULL, "platform_profile"); + cur_profile = pprof; err = sysfs_update_group(acpi_kobj, &platform_profile_group); @@ -391,6 +393,8 @@ int platform_profile_remove(struct platform_profile_handler *pprof) device_unregister(pprof->class_dev); ida_free(&platform_profile_ida, id); + sysfs_notify(acpi_kobj, NULL, "platform_profile"); + sysfs_update_group(acpi_kobj, &platform_profile_group); return 0; -- cgit v1.2.3 From 06ec24388f1de63a5d9b0dc1994bc2180d7ff6b8 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Thu, 5 Dec 2024 21:19:11 -0600 Subject: ACPI: platform_profile: Only show profiles common for all handlers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If multiple platform profile handlers have been registered, don't allow switching to profiles unique to only one handler. Reviewed-by: Armin Wolf Tested-by: Mark Pearson Tested-by: Matthew Schwartz Reviewed-by: Mark Pearson Reviewed-by: Ilpo Järvinen Signed-off-by: Mario Limonciello Link: https://lore.kernel.org/r/20241206031918.1537-16-mario.limonciello@amd.com Signed-off-by: Ilpo Järvinen --- drivers/acpi/platform_profile.c | 54 +++++++++++++++++++++++++++++++++-------- 1 file changed, 44 insertions(+), 10 deletions(-) (limited to 'drivers/acpi/platform_profile.c') diff --git a/drivers/acpi/platform_profile.c b/drivers/acpi/platform_profile.c index 2a4f067c3c5c..bdf69255ed9c 100644 --- a/drivers/acpi/platform_profile.c +++ b/drivers/acpi/platform_profile.c @@ -198,22 +198,56 @@ static const struct class platform_profile_class = { .dev_groups = profile_groups, }; +/** + * _aggregate_choices - Aggregate the available profile choices + * @dev: The device + * @data: The available profile choices + * + * Return: 0 on success, -errno on failure + */ +static int _aggregate_choices(struct device *dev, void *data) +{ + struct platform_profile_handler *handler; + unsigned long *aggregate = data; + + lockdep_assert_held(&profile_lock); + handler = dev_get_drvdata(dev); + if (test_bit(PLATFORM_PROFILE_LAST, aggregate)) + bitmap_copy(aggregate, handler->choices, PLATFORM_PROFILE_LAST); + else + bitmap_and(aggregate, handler->choices, aggregate, PLATFORM_PROFILE_LAST); + + return 0; +} + +/** + * platform_profile_choices_show - Show the available profile choices for legacy sysfs interface + * @dev: The device + * @attr: The attribute + * @buf: The buffer to write to + * + * Return: The number of bytes written + */ static ssize_t platform_profile_choices_show(struct device *dev, - struct device_attribute *attr, - char *buf) + struct device_attribute *attr, + char *buf) { - int len = 0; - int i; + unsigned long aggregate[BITS_TO_LONGS(PLATFORM_PROFILE_LAST)]; + int err; + set_bit(PLATFORM_PROFILE_LAST, aggregate); scoped_cond_guard(mutex_intr, return -ERESTARTSYS, &profile_lock) { - if (!cur_profile) - return -ENODEV; - for_each_set_bit(i, cur_profile->choices, PLATFORM_PROFILE_LAST) - len += sysfs_emit_at(buf, len, len ? " %s": "%s", profile_names[i]); + err = class_for_each_device(&platform_profile_class, NULL, + aggregate, _aggregate_choices); + if (err) + return err; } - len += sysfs_emit_at(buf, len, "\n"); - return len; + /* no profile handler registered any more */ + if (bitmap_empty(aggregate, PLATFORM_PROFILE_LAST)) + return -EINVAL; + + return _commmon_choices_show(aggregate, buf); } static ssize_t platform_profile_show(struct device *dev, -- cgit v1.2.3 From 494637cf5bf098ac0fe125dd6d23368419fe9da4 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Thu, 5 Dec 2024 21:19:12 -0600 Subject: ACPI: platform_profile: Add concept of a "custom" profile MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When two profile handlers don't agree on the current profile it's ambiguous what to show to the legacy sysfs interface. Add a "custom" profile string that userspace will be able to use the legacy sysfs interface to distinguish this situation.. Additionally drivers can choose to use this to indicate that a user has modified driver settings in a way that the platform profile advertised by a driver is not accurate. Reviewed-by: Armin Wolf Tested-by: Mark Pearson Reviewed-by: Mark Pearson Reviewed-by: Ilpo Järvinen Signed-off-by: Mario Limonciello Link: https://lore.kernel.org/r/20241206031918.1537-17-mario.limonciello@amd.com Signed-off-by: Ilpo Järvinen --- drivers/acpi/platform_profile.c | 1 + include/linux/platform_profile.h | 1 + 2 files changed, 2 insertions(+) (limited to 'drivers/acpi/platform_profile.c') diff --git a/drivers/acpi/platform_profile.c b/drivers/acpi/platform_profile.c index bdf69255ed9c..54483269b883 100644 --- a/drivers/acpi/platform_profile.c +++ b/drivers/acpi/platform_profile.c @@ -20,6 +20,7 @@ static const char * const profile_names[] = { [PLATFORM_PROFILE_BALANCED] = "balanced", [PLATFORM_PROFILE_BALANCED_PERFORMANCE] = "balanced-performance", [PLATFORM_PROFILE_PERFORMANCE] = "performance", + [PLATFORM_PROFILE_CUSTOM] = "custom", }; static_assert(ARRAY_SIZE(profile_names) == PLATFORM_PROFILE_LAST); diff --git a/include/linux/platform_profile.h b/include/linux/platform_profile.h index a888fd085c51..0682bb4c57e5 100644 --- a/include/linux/platform_profile.h +++ b/include/linux/platform_profile.h @@ -23,6 +23,7 @@ enum platform_profile_option { PLATFORM_PROFILE_BALANCED, PLATFORM_PROFILE_BALANCED_PERFORMANCE, PLATFORM_PROFILE_PERFORMANCE, + PLATFORM_PROFILE_CUSTOM, PLATFORM_PROFILE_LAST, /*must always be last */ }; -- cgit v1.2.3 From e836b7dfbabaa9d8a99b58ef0afa586f782d8e01 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Thu, 5 Dec 2024 21:19:13 -0600 Subject: ACPI: platform_profile: Make sure all profile handlers agree on profile MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If for any reason multiple profile handlers don't agree on the profile return the custom profile. Reviewed-by: Armin Wolf Tested-by: Mark Pearson Reviewed-by: Mark Pearson Reviewed-by: Ilpo Järvinen Signed-off-by: Mario Limonciello Link: https://lore.kernel.org/r/20241206031918.1537-18-mario.limonciello@amd.com Signed-off-by: Ilpo Järvinen --- drivers/acpi/platform_profile.c | 125 ++++++++++++++++++++++++++++++++-------- 1 file changed, 102 insertions(+), 23 deletions(-) (limited to 'drivers/acpi/platform_profile.c') diff --git a/drivers/acpi/platform_profile.c b/drivers/acpi/platform_profile.c index 54483269b883..95aff045a1eb 100644 --- a/drivers/acpi/platform_profile.c +++ b/drivers/acpi/platform_profile.c @@ -68,6 +68,24 @@ static int _store_class_profile(struct device *dev, void *data) return handler->profile_set(handler, *bit); } +/** + * _notify_class_profile - Notify the class device of a profile change + * @dev: The class device + * @data: Unused + * + * Return: 0 on success, -errno on failure + */ +static int _notify_class_profile(struct device *dev, void *data) +{ + struct platform_profile_handler *handler = dev_get_drvdata(dev); + + lockdep_assert_held(&profile_lock); + sysfs_notify(&handler->class_dev->kobj, NULL, "profile"); + kobject_uevent(&handler->class_dev->kobj, KOBJ_CHANGE); + + return 0; +} + /** * get_class_profile - Show the current profile for a class device * @dev: The class device @@ -251,51 +269,112 @@ static ssize_t platform_profile_choices_show(struct device *dev, return _commmon_choices_show(aggregate, buf); } +/** + * _aggregate_profiles - Aggregate the profiles for legacy sysfs interface + * @dev: The device + * @data: The profile to return + * + * Return: 0 on success, -errno on failure + */ +static int _aggregate_profiles(struct device *dev, void *data) +{ + enum platform_profile_option *profile = data; + enum platform_profile_option val; + int err; + + err = get_class_profile(dev, &val); + if (err) + return err; + + if (*profile != PLATFORM_PROFILE_LAST && *profile != val) + *profile = PLATFORM_PROFILE_CUSTOM; + else + *profile = val; + + return 0; +} + +/** + * _store_and_notify - Store and notify a class from legacy sysfs interface + * @dev: The device + * @data: The profile to return + * + * Return: 0 on success, -errno on failure + */ +static int _store_and_notify(struct device *dev, void *data) +{ + enum platform_profile_option *profile = data; + int err; + + err = _store_class_profile(dev, profile); + if (err) + return err; + return _notify_class_profile(dev, NULL); +} + +/** + * platform_profile_show - Show the current profile for legacy sysfs interface + * @dev: The device + * @attr: The attribute + * @buf: The buffer to write to + * + * Return: The number of bytes written + */ static ssize_t platform_profile_show(struct device *dev, - struct device_attribute *attr, - char *buf) + struct device_attribute *attr, + char *buf) { - enum platform_profile_option profile = PLATFORM_PROFILE_BALANCED; + enum platform_profile_option profile = PLATFORM_PROFILE_LAST; int err; scoped_cond_guard(mutex_intr, return -ERESTARTSYS, &profile_lock) { - if (!cur_profile) - return -ENODEV; - - err = cur_profile->profile_get(cur_profile, &profile); + err = class_for_each_device(&platform_profile_class, NULL, + &profile, _aggregate_profiles); if (err) return err; } - /* Check that profile is valid index */ - if (WARN_ON((profile < 0) || (profile >= ARRAY_SIZE(profile_names)))) - return -EIO; + /* no profile handler registered any more */ + if (profile == PLATFORM_PROFILE_LAST) + return -EINVAL; return sysfs_emit(buf, "%s\n", profile_names[profile]); } +/** + * platform_profile_store - Set the profile for legacy sysfs interface + * @dev: The device + * @attr: The attribute + * @buf: The buffer to read from + * @count: The number of bytes to read + * + * Return: The number of bytes read + */ static ssize_t platform_profile_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) + struct device_attribute *attr, + const char *buf, size_t count) { - int err, i; + unsigned long choices[BITS_TO_LONGS(PLATFORM_PROFILE_LAST)]; + int ret; + int i; /* Scan for a matching profile */ i = sysfs_match_string(profile_names, buf); - if (i < 0) + if (i < 0 || i == PLATFORM_PROFILE_CUSTOM) return -EINVAL; - + set_bit(PLATFORM_PROFILE_LAST, choices); scoped_cond_guard(mutex_intr, return -ERESTARTSYS, &profile_lock) { - if (!cur_profile) - return -ENODEV; - - /* Check that platform supports this profile choice */ - if (!test_bit(i, cur_profile->choices)) + ret = class_for_each_device(&platform_profile_class, NULL, + choices, _aggregate_choices); + if (ret) + return ret; + if (!test_bit(i, choices)) return -EOPNOTSUPP; - err = cur_profile->profile_set(cur_profile, i); - if (err) - return err; + ret = class_for_each_device(&platform_profile_class, NULL, &i, + _store_and_notify); + if (ret) + return ret; } sysfs_notify(acpi_kobj, NULL, "platform_profile"); -- cgit v1.2.3 From 70246f89c55fb1be0367a584000fd68502a0933f Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Thu, 5 Dec 2024 21:19:14 -0600 Subject: ACPI: platform_profile: Check all profile handler to calculate next MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As multiple platform profile handlers might not all support the same profile, cycling to the next profile could have a different result depending on what handler are registered. Check what is active and supported by all handlers to decide what to do. Reviewed-by: Armin Wolf Tested-by: Mark Pearson Reviewed-by: Mark Pearson Signed-off-by: Mario Limonciello Link: https://lore.kernel.org/r/20241206031918.1537-19-mario.limonciello@amd.com Reviewed-by: Ilpo Järvinen Signed-off-by: Ilpo Järvinen --- drivers/acpi/platform_profile.c | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) (limited to 'drivers/acpi/platform_profile.c') diff --git a/drivers/acpi/platform_profile.c b/drivers/acpi/platform_profile.c index 95aff045a1eb..a1fdc56537ba 100644 --- a/drivers/acpi/platform_profile.c +++ b/drivers/acpi/platform_profile.c @@ -418,25 +418,37 @@ EXPORT_SYMBOL_GPL(platform_profile_notify); int platform_profile_cycle(void) { - enum platform_profile_option profile; - enum platform_profile_option next; + enum platform_profile_option next = PLATFORM_PROFILE_LAST; + enum platform_profile_option profile = PLATFORM_PROFILE_LAST; + unsigned long choices[BITS_TO_LONGS(PLATFORM_PROFILE_LAST)]; int err; + set_bit(PLATFORM_PROFILE_LAST, choices); scoped_cond_guard(mutex_intr, return -ERESTARTSYS, &profile_lock) { - if (!cur_profile) - return -ENODEV; + err = class_for_each_device(&platform_profile_class, NULL, + &profile, _aggregate_profiles); + if (err) + return err; - err = cur_profile->profile_get(cur_profile, &profile); + if (profile == PLATFORM_PROFILE_CUSTOM || + profile == PLATFORM_PROFILE_LAST) + return -EINVAL; + + err = class_for_each_device(&platform_profile_class, NULL, + choices, _aggregate_choices); if (err) return err; - next = find_next_bit_wrap(cur_profile->choices, PLATFORM_PROFILE_LAST, + /* never iterate into a custom if all drivers supported it */ + clear_bit(PLATFORM_PROFILE_CUSTOM, choices); + + next = find_next_bit_wrap(choices, + PLATFORM_PROFILE_LAST, profile + 1); - if (WARN_ON(next == PLATFORM_PROFILE_LAST)) - return -EINVAL; + err = class_for_each_device(&platform_profile_class, NULL, &next, + _store_and_notify); - err = cur_profile->profile_set(cur_profile, next); if (err) return err; } -- cgit v1.2.3 From 37a6853d83f8af1b68346b555a7dd78e2c7f10e5 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Thu, 5 Dec 2024 21:19:15 -0600 Subject: ACPI: platform_profile: Notify class device from platform_profile_notify() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When a driver has called platform_profile_notify() both the legacy sysfs interface and the class device should be notified as userspace may listen to either. Reviewed-by: Armin Wolf Reviewed-by: Mark Pearson Reviewed-by: Ilpo Järvinen Signed-off-by: Mario Limonciello Link: https://lore.kernel.org/r/20241206031918.1537-20-mario.limonciello@amd.com Signed-off-by: Ilpo Järvinen --- drivers/acpi/platform_profile.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/acpi/platform_profile.c') diff --git a/drivers/acpi/platform_profile.c b/drivers/acpi/platform_profile.c index a1fdc56537ba..e105ef48409e 100644 --- a/drivers/acpi/platform_profile.c +++ b/drivers/acpi/platform_profile.c @@ -412,6 +412,9 @@ void platform_profile_notify(struct platform_profile_handler *pprof) { if (!cur_profile) return; + scoped_cond_guard(mutex_intr, return, &profile_lock) { + _notify_class_profile(pprof->class_dev, NULL); + } sysfs_notify(acpi_kobj, NULL, "platform_profile"); } EXPORT_SYMBOL_GPL(platform_profile_notify); -- cgit v1.2.3 From 688834743d672b55ce357e11e34be835c78467e8 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Thu, 5 Dec 2024 21:19:16 -0600 Subject: ACPI: platform_profile: Allow multiple handlers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Multiple drivers may attempt to register platform profile handlers, but only one may be registered and the behavior is non-deterministic for which one wins. It's mostly controlled by probing order. This can be problematic if one driver changes CPU settings and another driver notifies the EC for changing fan curves. Modify the ACPI platform profile handler to let multiple drivers register platform profile handlers and abstract this detail from userspace. To avoid undefined behaviors only offer profiles that are commonly advertised across multiple handlers. If any problems occur when changing profiles for any driver, then the drivers that were already changed remain changed and the legacy sysfs handler will report 'custom'. Tested-by: Mark Pearson Tested-by: Matthew Schwartz Reviewed-by: Mark Pearson Reviewed-by: Armin Wolf Reviewed-by: Ilpo Järvinen Signed-off-by: Mario Limonciello Link: https://lore.kernel.org/r/20241206031918.1537-21-mario.limonciello@amd.com Signed-off-by: Ilpo Järvinen --- drivers/acpi/platform_profile.c | 11 ----------- 1 file changed, 11 deletions(-) (limited to 'drivers/acpi/platform_profile.c') diff --git a/drivers/acpi/platform_profile.c b/drivers/acpi/platform_profile.c index e105ef48409e..75a1415190ac 100644 --- a/drivers/acpi/platform_profile.c +++ b/drivers/acpi/platform_profile.c @@ -10,7 +10,6 @@ #include #include -static struct platform_profile_handler *cur_profile; static DEFINE_MUTEX(profile_lock); static const char * const profile_names[] = { @@ -410,8 +409,6 @@ static const struct attribute_group platform_profile_group = { void platform_profile_notify(struct platform_profile_handler *pprof) { - if (!cur_profile) - return; scoped_cond_guard(mutex_intr, return, &profile_lock) { _notify_class_profile(pprof->class_dev, NULL); } @@ -474,9 +471,6 @@ int platform_profile_register(struct platform_profile_handler *pprof) } guard(mutex)(&profile_lock); - /* We can only have one active profile */ - if (cur_profile) - return -EEXIST; /* create class interface for individual handler */ pprof->minor = ida_alloc(&platform_profile_ida, GFP_KERNEL); @@ -492,8 +486,6 @@ int platform_profile_register(struct platform_profile_handler *pprof) sysfs_notify(acpi_kobj, NULL, "platform_profile"); - cur_profile = pprof; - err = sysfs_update_group(acpi_kobj, &platform_profile_group); if (err) goto cleanup_cur; @@ -501,7 +493,6 @@ int platform_profile_register(struct platform_profile_handler *pprof) return 0; cleanup_cur: - cur_profile = NULL; device_unregister(pprof->class_dev); cleanup_ida: @@ -516,8 +507,6 @@ int platform_profile_remove(struct platform_profile_handler *pprof) int id; guard(mutex)(&profile_lock); - cur_profile = NULL; - id = pprof->minor; device_unregister(pprof->class_dev); ida_free(&platform_profile_ida, id); -- cgit v1.2.3 From b651ea8a44aab69f71c5ebeec7e472b03f1b2ca2 Mon Sep 17 00:00:00 2001 From: Kurt Borja Date: Tue, 24 Dec 2024 09:01:32 -0500 Subject: ACPI: platform_profile: Add devm_platform_profile_register() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Platform profile's lifetime is usually tied to a device's lifetime, therefore add a device managed version of platform_profile_register(). Signed-off-by: Kurt Borja Reviewed-by: Armin Wolf Link: https://lore.kernel.org/r/20241224140131.30362-4-kuurtb@gmail.com Reviewed-by: Ilpo Järvinen Signed-off-by: Ilpo Järvinen --- drivers/acpi/platform_profile.c | 29 +++++++++++++++++++++++++++++ include/linux/platform_profile.h | 1 + 2 files changed, 30 insertions(+) (limited to 'drivers/acpi/platform_profile.c') diff --git a/drivers/acpi/platform_profile.c b/drivers/acpi/platform_profile.c index 75a1415190ac..4c4200a0b1a6 100644 --- a/drivers/acpi/platform_profile.c +++ b/drivers/acpi/platform_profile.c @@ -519,6 +519,35 @@ int platform_profile_remove(struct platform_profile_handler *pprof) } EXPORT_SYMBOL_GPL(platform_profile_remove); +static void devm_platform_profile_release(struct device *dev, void *res) +{ + struct platform_profile_handler **pprof = res; + + platform_profile_remove(*pprof); +} + +int devm_platform_profile_register(struct platform_profile_handler *pprof) +{ + struct platform_profile_handler **dr; + int ret; + + dr = devres_alloc(devm_platform_profile_release, sizeof(*dr), GFP_KERNEL); + if (!dr) + return -ENOMEM; + + ret = platform_profile_register(pprof); + if (ret) { + devres_free(dr); + return ret; + } + + *dr = pprof; + devres_add(pprof->dev, dr); + + return 0; +} +EXPORT_SYMBOL_GPL(devm_platform_profile_register); + static int __init platform_profile_init(void) { int err; diff --git a/include/linux/platform_profile.h b/include/linux/platform_profile.h index 0682bb4c57e5..f1cd4b65e351 100644 --- a/include/linux/platform_profile.h +++ b/include/linux/platform_profile.h @@ -41,6 +41,7 @@ struct platform_profile_handler { int platform_profile_register(struct platform_profile_handler *pprof); int platform_profile_remove(struct platform_profile_handler *pprof); +int devm_platform_profile_register(struct platform_profile_handler *pprof); int platform_profile_cycle(void); void platform_profile_notify(struct platform_profile_handler *pprof); -- cgit v1.2.3 From d960f14800b581d79e1c3df4db524d9d4b3aac9a Mon Sep 17 00:00:00 2001 From: Kurt Borja Date: Wed, 15 Jan 2025 19:27:03 -0500 Subject: ACPI: platform_profile: Replace *class_dev member with class_dev MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Signed-off-by: Kurt Borja Reviewed-by: Mark Pearson Tested-by: Mark Pearson Link: https://lore.kernel.org/r/20250116002721.75592-2-kuurtb@gmail.com Reviewed-by: Ilpo Järvinen Signed-off-by: Ilpo Järvinen --- drivers/acpi/platform_profile.c | 37 ++++++++++++++++++++----------------- include/linux/platform_profile.h | 3 ++- 2 files changed, 22 insertions(+), 18 deletions(-) (limited to 'drivers/acpi/platform_profile.c') diff --git a/drivers/acpi/platform_profile.c b/drivers/acpi/platform_profile.c index 4c4200a0b1a6..15f24adc57d4 100644 --- a/drivers/acpi/platform_profile.c +++ b/drivers/acpi/platform_profile.c @@ -5,11 +5,12 @@ #include #include #include -#include #include #include #include +#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 +61,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 +77,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 +101,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 +125,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 +143,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 +230,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 +411,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 +477,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 +496,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 +511,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 #include /* @@ -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, -- cgit v1.2.3 From 249c576f0f9d0556cb7473b8a437b30239afbd16 Mon Sep 17 00:00:00 2001 From: Kurt Borja Date: Wed, 15 Jan 2025 19:27:04 -0500 Subject: ACPI: platform_profile: Let drivers set drvdata to the class device MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Signed-off-by: Kurt Borja Reviewed-by: Mark Pearson Tested-by: Mark Pearson Link: https://lore.kernel.org/r/20250116002721.75592-3-kuurtb@gmail.com Reviewed-by: Ilpo Järvinen Signed-off-by: Ilpo Järvinen --- 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(-) (limited to 'drivers/acpi/platform_profile.c') diff --git a/drivers/acpi/platform_profile.c b/drivers/acpi/platform_profile.c index 15f24adc57d4..689541d2e66c 100644 --- a/drivers/acpi/platform_profile.c +++ b/drivers/acpi/platform_profile.c @@ -460,7 +460,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; @@ -480,6 +480,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) { @@ -529,7 +530,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; @@ -538,7 +539,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 acf610d59168..1aedf0ef4189 100644 --- a/drivers/platform/x86/acer-wmi.c +++ b/drivers/platform/x86/acer-wmi.c @@ -2073,7 +2073,7 @@ static int acer_platform_profile_setup(struct platform_device *device) ACER_PREDATOR_V4_THERMAL_PROFILE_TURBO; } - 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 6c674de60ec0..f91099792cb9 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 d7f577e0d146..154c417a438c 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 @@ out_free: 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 d99573e7a983..8be3f4e5366d 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -10641,7 +10641,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); -- cgit v1.2.3 From cf3ea098dd3af415f079bc0b999055f213dd4a83 Mon Sep 17 00:00:00 2001 From: Kurt Borja Date: Wed, 15 Jan 2025 19:27:05 -0500 Subject: ACPI: platform_profile: Remove platform_profile_handler from callbacks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Devices can now set drvdata to the class device, thus passing the platform_profile_handler to callbacks is unnecessary. Instead pass the class device. Reviewed-by: Mario Limonciello Signed-off-by: Kurt Borja Reviewed-by: Mark Pearson Tested-by: Mark Pearson Link: https://lore.kernel.org/r/20250116002721.75592-4-kuurtb@gmail.com Reviewed-by: Ilpo Järvinen Signed-off-by: Ilpo Järvinen --- drivers/acpi/platform_profile.c | 4 ++-- drivers/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(-) (limited to 'drivers/acpi/platform_profile.c') diff --git a/drivers/acpi/platform_profile.c b/drivers/acpi/platform_profile.c index 689541d2e66c..bd90aa4e8371 100644 --- a/drivers/acpi/platform_profile.c +++ b/drivers/acpi/platform_profile.c @@ -65,7 +65,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); } /** @@ -102,7 +102,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 1aedf0ef4189..c68c0d744a69 100644 --- a/drivers/platform/x86/acer-wmi.c +++ b/drivers/platform/x86/acer-wmi.c @@ -1950,7 +1950,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; @@ -1984,7 +1984,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 err, 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 f91099792cb9..6b8b30551d36 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 154c417a438c..0346f8e88bf8 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 @@ out_free: * 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 8be3f4e5366d..0abe22228fdb 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -10415,7 +10415,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; @@ -10490,7 +10490,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); -- cgit v1.2.3 From b5ca1a4488a5e6dfb9962e2319c03c7414e50ec3 Mon Sep 17 00:00:00 2001 From: Kurt Borja Date: Wed, 15 Jan 2025 19:27:06 -0500 Subject: ACPI: platform_profile: Add `ops` member to handlers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace *profile_get and *profile_set members with a general *ops member. Reviewed-by: Mario Limonciello Signed-off-by: Kurt Borja Reviewed-by: Mark Pearson Tested-by: Mark Pearson Link: https://lore.kernel.org/r/20250116002721.75592-5-kuurtb@gmail.com Reviewed-by: Ilpo Järvinen Signed-off-by: Ilpo Järvinen --- drivers/acpi/platform_profile.c | 6 +++--- .../platform/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 ++++++-- drivers/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(-) (limited to 'drivers/acpi/platform_profile.c') diff --git a/drivers/acpi/platform_profile.c b/drivers/acpi/platform_profile.c index bd90aa4e8371..161a05d57b0f 100644 --- a/drivers/acpi/platform_profile.c +++ b/drivers/acpi/platform_profile.c @@ -65,7 +65,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); } /** @@ -102,7 +102,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; @@ -466,7 +466,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 c68c0d744a69..63e6bd1fe339 100644 --- a/drivers/platform/x86/acer-wmi.c +++ b/drivers/platform/x86/acer-wmi.c @@ -2019,6 +2019,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) { @@ -2027,10 +2032,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; err = WMID_gaming_get_misc_setting(ACER_WMID_MISC_SETTING_SUPPORTED_PROFILES, (u8 *)&supported_profiles); 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 6b8b30551d36..992956c89d38 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 0346f8e88bf8..b8359b177a0f 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 0abe22228fdb..9e26f5670fc7 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -10539,12 +10539,16 @@ unlock: 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); -- cgit v1.2.3 From 58d5629dc8b8b8d9928fc649d9f2aaa361a8a5c5 Mon Sep 17 00:00:00 2001 From: Kurt Borja Date: Wed, 15 Jan 2025 19:27:07 -0500 Subject: ACPI: platform_profile: Add `probe` to platform_profile_ops MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a `probe` callback to platform_profile_ops, which lets drivers initialize the choices member manually. This is a step towards unexposing the struct platform_profile_handler from the consumer drivers. Reviewed-by: Mario Limonciello Signed-off-by: Kurt Borja Reviewed-by: Mark Pearson Tested-by: Mark Pearson Link: https://lore.kernel.org/r/20250116002721.75592-6-kuurtb@gmail.com Reviewed-by: Ilpo Järvinen Signed-off-by: Ilpo Järvinen --- drivers/acpi/platform_profile.c | 15 +++- .../platform/surface/surface_platform_profile.c | 16 ++-- drivers/platform/x86/acer-wmi.c | 88 +++++++++++----------- 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 ++-- drivers/platform/x86/inspur_platform_profile.c | 14 +++- drivers/platform/x86/thinkpad_acpi.c | 15 ++-- include/linux/platform_profile.h | 1 + 12 files changed, 172 insertions(+), 102 deletions(-) (limited to 'drivers/acpi/platform_profile.c') diff --git a/drivers/acpi/platform_profile.c b/drivers/acpi/platform_profile.c index 161a05d57b0f..120f8402facd 100644 --- a/drivers/acpi/platform_profile.c +++ b/drivers/acpi/platform_profile.c @@ -465,12 +465,23 @@ 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) { + dev_err(pprof->dev, "platform_profile probe failed\n"); + return err; + } + + if (bitmap_empty(pprof->choices, PLATFORM_PROFILE_LAST)) { + dev_err(pprof->dev, "Failed to register a platform_profile class device with empty choices\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 63e6bd1fe339..4d62a61cb241 100644 --- a/drivers/platform/x86/acer-wmi.c +++ b/drivers/platform/x86/acer-wmi.c @@ -2019,7 +2019,53 @@ acer_predator_v4_platform_profile_set(struct device *dev, return 0; } +static int +acer_predator_v4_platform_profile_probe(void *drvdata, unsigned long *choices) +{ + unsigned long supported_profiles; + int err; + + err = WMID_gaming_get_misc_setting(ACER_WMID_MISC_SETTING_SUPPORTED_PROFILES, + (u8 *)&supported_profiles); + if (err) + return err; + + /* Iterate through supported profiles in order of increasing performance */ + if (test_bit(ACER_PREDATOR_V4_THERMAL_PROFILE_ECO, &supported_profiles)) { + set_bit(PLATFORM_PROFILE_LOW_POWER, choices); + acer_predator_v4_max_perf = + ACER_PREDATOR_V4_THERMAL_PROFILE_ECO; + } + + if (test_bit(ACER_PREDATOR_V4_THERMAL_PROFILE_QUIET, &supported_profiles)) { + set_bit(PLATFORM_PROFILE_QUIET, choices); + acer_predator_v4_max_perf = + ACER_PREDATOR_V4_THERMAL_PROFILE_QUIET; + } + + if (test_bit(ACER_PREDATOR_V4_THERMAL_PROFILE_BALANCED, &supported_profiles)) { + set_bit(PLATFORM_PROFILE_BALANCED, choices); + acer_predator_v4_max_perf = + ACER_PREDATOR_V4_THERMAL_PROFILE_BALANCED; + } + + if (test_bit(ACER_PREDATOR_V4_THERMAL_PROFILE_PERFORMANCE, &supported_profiles)) { + set_bit(PLATFORM_PROFILE_BALANCED_PERFORMANCE, choices); + acer_predator_v4_max_perf = + ACER_PREDATOR_V4_THERMAL_PROFILE_PERFORMANCE; + } + + if (test_bit(ACER_PREDATOR_V4_THERMAL_PROFILE_TURBO, &supported_profiles)) { + set_bit(PLATFORM_PROFILE_PERFORMANCE, choices); + acer_predator_v4_max_perf = + ACER_PREDATOR_V4_THERMAL_PROFILE_TURBO; + } + + 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, }; @@ -2027,7 +2073,6 @@ 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) { - unsigned long supported_profiles; int err; platform_profile_handler.name = "acer-wmi"; @@ -2035,47 +2080,6 @@ static int acer_platform_profile_setup(struct platform_device *device) platform_profile_handler.ops = &acer_predator_v4_platform_profile_ops; - err = WMID_gaming_get_misc_setting(ACER_WMID_MISC_SETTING_SUPPORTED_PROFILES, - (u8 *)&supported_profiles); - if (err) - return err; - - /* Iterate through supported profiles in order of increasing performance */ - if (test_bit(ACER_PREDATOR_V4_THERMAL_PROFILE_ECO, &supported_profiles)) { - set_bit(PLATFORM_PROFILE_LOW_POWER, - platform_profile_handler.choices); - acer_predator_v4_max_perf = - ACER_PREDATOR_V4_THERMAL_PROFILE_ECO; - } - - if (test_bit(ACER_PREDATOR_V4_THERMAL_PROFILE_QUIET, &supported_profiles)) { - set_bit(PLATFORM_PROFILE_QUIET, - platform_profile_handler.choices); - acer_predator_v4_max_perf = - ACER_PREDATOR_V4_THERMAL_PROFILE_QUIET; - } - - if (test_bit(ACER_PREDATOR_V4_THERMAL_PROFILE_BALANCED, &supported_profiles)) { - set_bit(PLATFORM_PROFILE_BALANCED, - platform_profile_handler.choices); - acer_predator_v4_max_perf = - ACER_PREDATOR_V4_THERMAL_PROFILE_BALANCED; - } - - if (test_bit(ACER_PREDATOR_V4_THERMAL_PROFILE_PERFORMANCE, &supported_profiles)) { - set_bit(PLATFORM_PROFILE_BALANCED_PERFORMANCE, - platform_profile_handler.choices); - acer_predator_v4_max_perf = - ACER_PREDATOR_V4_THERMAL_PROFILE_PERFORMANCE; - } - - if (test_bit(ACER_PREDATOR_V4_THERMAL_PROFILE_TURBO, &supported_profiles)) { - set_bit(PLATFORM_PROFILE_PERFORMANCE, - platform_profile_handler.choices); - acer_predator_v4_max_perf = - ACER_PREDATOR_V4_THERMAL_PROFILE_TURBO; - } - 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 992956c89d38..e775ec7371ce 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 b8359b177a0f..e7209863e7dc 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 9e26f5670fc7..62b2ddfe7c0a 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -10539,7 +10539,17 @@ unlock: 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, }; @@ -10585,11 +10595,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); }; -- cgit v1.2.3 From 07f531b395db3cd1776ef0f7191abf4b077fcf21 Mon Sep 17 00:00:00 2001 From: Kurt Borja Date: Wed, 15 Jan 2025 19:27:17 -0500 Subject: ACPI: platform_profile: Remove platform_profile_handler from exported symbols MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. Reviewed-by: Mario Limonciello Signed-off-by: Kurt Borja Reviewed-by: Mark Pearson Tested-by: Mark Pearson Link: https://lore.kernel.org/r/20250116002721.75592-16-kuurtb@gmail.com Reviewed-by: Ilpo Järvinen Signed-off-by: Ilpo Järvinen --- drivers/acpi/platform_profile.c | 98 ++++++++++++++-------- .../platform/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 | 15 ++-- drivers/platform/x86/dell/alienware-wmi.c | 10 +-- drivers/platform/x86/dell/dell-pc.c | 21 ++--- drivers/platform/x86/hp/hp-wmi.c | 19 ++--- drivers/platform/x86/ideapad-laptop.c | 15 ++-- drivers/platform/x86/inspur_platform_profile.c | 9 +- drivers/platform/x86/thinkpad_acpi.c | 14 ++-- include/linux/platform_profile.h | 12 ++- 13 files changed, 129 insertions(+), 132 deletions(-) (limited to 'drivers/acpi/platform_profile.c') diff --git a/drivers/acpi/platform_profile.c b/drivers/acpi/platform_profile.c index 120f8402facd..c0701d96c6a9 100644 --- a/drivers/acpi/platform_profile.c +++ b/drivers/acpi/platform_profile.c @@ -4,6 +4,7 @@ #include #include +#include #include #include #include @@ -212,9 +213,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, }; /** @@ -408,10 +417,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"); } @@ -460,42 +469,54 @@ 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) { + struct device *ppdev; + int minor; int err; - /* Sanity check the profile handler */ - if (!pprof || !pprof->ops->profile_set || !pprof->ops->profile_get || - !pprof->ops->probe) { - pr_err("platform_profile: handler is invalid\n"); - return -EINVAL; - } + /* Sanity check */ + if (WARN_ON_ONCE(!dev || !name || !ops || !ops->profile_get || + !ops->profile_set || !ops->probe)) + return ERR_PTR(-EINVAL); + + struct platform_profile_handler *pprof __free(kfree) = kzalloc( + sizeof(*pprof), GFP_KERNEL); + if (!pprof) + return ERR_PTR(-ENOMEM); - err = pprof->ops->probe(drvdata, pprof->choices); + err = ops->probe(drvdata, pprof->choices); if (err) { - dev_err(pprof->dev, "platform_profile probe failed\n"); - return err; + dev_err(dev, "platform_profile probe failed\n"); + return ERR_PTR(err); } if (bitmap_empty(pprof->choices, PLATFORM_PROFILE_LAST)) { - dev_err(pprof->dev, "Failed to register a platform_profile class device with empty choices\n"); - return -EINVAL; + dev_err(dev, "Failed to register platform_profile class device with empty choices\n"); + 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); + /* device_register() takes ownership of pprof/ppdev */ + ppdev = &no_free_ptr(pprof)->class_dev; + err = device_register(ppdev); if (err) { - put_device(&pprof->class_dev); + put_device(ppdev); goto cleanup_ida; } @@ -505,20 +526,21 @@ int platform_profile_register(struct platform_profile_handler *pprof, void *drvd if (err) goto cleanup_cur; - return 0; + return ppdev; cleanup_cur: - device_unregister(&pprof->class_dev); + device_unregister(ppdev); 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); @@ -536,30 +558,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(ppdev)) { 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..0e479e35e66e 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 d201ca0e01d6..ae2a7c93ab72 100644 --- a/drivers/platform/x86/acer-wmi.c +++ b/drivers/platform/x86/acer-wmi.c @@ -784,7 +784,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; /* @@ -2073,16 +2073,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; @@ -2125,7 +2119,7 @@ static int acer_thermal_profile_change(void) if (current_tp != acer_predator_v4_max_perf) last_non_turbo_profile = current_tp; - platform_profile_notify(&platform_profile_handler); + platform_profile_notify(platform_profile_device); } } 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..e6cf0b22dac3 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 7aa837f74fd0..1032c0e84e3d 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 *ppdev; 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->ppdev); return count; } @@ -3891,14 +3891,11 @@ 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; - - err = devm_platform_profile_register(&asus->platform_profile_handler, asus); - if (err) { + asus->ppdev = devm_platform_profile_register(dev, "asus-wmi", asus, + &asus_wmi_platform_profile_ops); + if (IS_ERR(asus->ppdev)) { dev_err(dev, "Failed to register a platform_profile class device\n"); - return err; + return PTR_ERR(asus->ppdev); } asus->platform_profile_support = true; diff --git a/drivers/platform/x86/dell/alienware-wmi.c b/drivers/platform/x86/dell/alienware-wmi.c index e7209863e7dc..63cf016bc912 100644 --- a/drivers/platform/x86/dell/alienware-wmi.c +++ b/drivers/platform/x86/dell/alienware-wmi.c @@ -406,7 +406,6 @@ struct wmax_u32_args { static struct platform_device *platform_device; static struct color_platform colors[4]; -static struct platform_profile_handler pp_handler; static enum wmax_thermal_mode supported_thermal_profiles[PLATFORM_PROFILE_LAST]; static u8 interface; @@ -1135,11 +1134,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..483240bb36e7 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,25 +270,15 @@ 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; + 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_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) - goto cleanup_thermal_handler; return 0; -cleanup_thermal_handler: - thermal_handler = NULL; - cleanup_platform_device: platform_device_unregister(platform_device); diff --git a/drivers/platform/x86/hp/hp-wmi.c b/drivers/platform/x86/hp/hp-wmi.c index 1304dfc65aab..435e3ef2e3e7 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..dfb5d4b8c046 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,16 @@ 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..e02f5a55a6c5 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 c9226e8dc713..56c57cb45a76 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); @@ -10554,11 +10555,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; @@ -10587,7 +10583,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); } } @@ -10648,14 +10644,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_*/ -- cgit v1.2.3 From 6ef33895503583d0741a0d8faf820ca8143b9cf2 Mon Sep 17 00:00:00 2001 From: Kurt Borja Date: Wed, 15 Jan 2025 19:27:18 -0500 Subject: ACPI: platform_profile: Move platform_profile_handler MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit platform_profile_handler is now an internal structure. Move it to platform_profile.c. Reviewed-by: Mario Limonciello Signed-off-by: Kurt Borja Reviewed-by: Mark Pearson Tested-by: Mark Pearson Link: https://lore.kernel.org/r/20250116002721.75592-17-kuurtb@gmail.com Reviewed-by: Ilpo Järvinen Signed-off-by: Ilpo Järvinen --- drivers/acpi/platform_profile.c | 9 +++++++++ include/linux/platform_profile.h | 11 ----------- 2 files changed, 9 insertions(+), 11 deletions(-) (limited to 'drivers/acpi/platform_profile.c') diff --git a/drivers/acpi/platform_profile.c b/drivers/acpi/platform_profile.c index c0701d96c6a9..392ea055cb6e 100644 --- a/drivers/acpi/platform_profile.c +++ b/drivers/acpi/platform_profile.c @@ -14,6 +14,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); -- cgit v1.2.3 From c4f7d255be321d6cb0543174509f2b39f7c763b9 Mon Sep 17 00:00:00 2001 From: Kurt Borja Date: Wed, 15 Jan 2025 19:27:19 -0500 Subject: ACPI: platform_profile: Clean platform_profile_handler MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove parent device *dev from platform_profile_handler, as it's no longer accessed directly. Rename class_dev -> dev. Reviewed-by: Mario Limonciello Signed-off-by: Kurt Borja Reviewed-by: Mark Pearson Tested-by: Mark Pearson Link: https://lore.kernel.org/r/20250116002721.75592-18-kuurtb@gmail.com Reviewed-by: Ilpo Järvinen Signed-off-by: Ilpo Järvinen --- drivers/acpi/platform_profile.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) (limited to 'drivers/acpi/platform_profile.c') diff --git a/drivers/acpi/platform_profile.c b/drivers/acpi/platform_profile.c index 392ea055cb6e..e9a2df337ecc 100644 --- a/drivers/acpi/platform_profile.c +++ b/drivers/acpi/platform_profile.c @@ -10,14 +10,13 @@ #include #include -#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; @@ -90,8 +89,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,12 +516,12 @@ 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); + 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); /* device_register() takes ownership of pprof/ppdev */ - ppdev = &no_free_ptr(pprof)->class_dev; + ppdev = &no_free_ptr(pprof)->dev; err = device_register(ppdev); if (err) { put_device(ppdev); @@ -554,7 +553,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"); -- cgit v1.2.3 From ee7f3e2b4942e3f6d8837780d0d3d5d58de8801a Mon Sep 17 00:00:00 2001 From: Kurt Borja Date: Wed, 15 Jan 2025 19:27:20 -0500 Subject: ACPI: platform_profile: Add documentation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add kerneldoc and sysfs class documentation. Reviewed-by: Mario Limonciello Signed-off-by: Kurt Borja Reviewed-by: Mark Pearson Tested-by: Mark Pearson Link: https://lore.kernel.org/r/20250116002721.75592-19-kuurtb@gmail.com Reviewed-by: Ilpo Järvinen Signed-off-by: Ilpo Järvinen --- .../ABI/testing/sysfs-class-platform-profile | 48 ++++++++++++++++++++++ drivers/acpi/platform_profile.c | 33 +++++++++++++++ include/linux/platform_profile.h | 10 +++++ 3 files changed, 91 insertions(+) create mode 100644 Documentation/ABI/testing/sysfs-class-platform-profile (limited to 'drivers/acpi/platform_profile.c') diff --git a/Documentation/ABI/testing/sysfs-class-platform-profile b/Documentation/ABI/testing/sysfs-class-platform-profile new file mode 100644 index 000000000000..dc72adfb830a --- /dev/null +++ b/Documentation/ABI/testing/sysfs-class-platform-profile @@ -0,0 +1,48 @@ +What: /sys/class/platform-profile/platform-profile-X/name +Date: March 2025 +KernelVersion: 6.14 +Description: Name of the class device given by the driver. + + RO + +What: /sys/class/platform-profile/platform-profile-X/choices +Date: March 2025 +KernelVersion: 6.14 +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: March 2025 +KernelVersion: 6.14 +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 e9a2df337ecc..49af808153a7 100644 --- a/drivers/acpi/platform_profile.c +++ b/drivers/acpi/platform_profile.c @@ -425,6 +425,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) { @@ -434,6 +438,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; @@ -477,6 +486,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) @@ -546,6 +564,12 @@ cleanup_ida: } 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); @@ -571,6 +595,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..8ab5b0e8eb2c 100644 --- a/include/linux/platform_profile.h +++ b/include/linux/platform_profile.h @@ -28,6 +28,16 @@ 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. These + * choices will only be enforced when setting a new profile, not when + * getting the current one. + * @profile_get: Callback that will be called when showing the current platform + * profile in sysfs. + * @profile_set: Callback that will be called when storing a new platform + * profile in sysfs. + */ struct platform_profile_ops { int (*probe)(void *drvdata, unsigned long *choices); int (*profile_get)(struct device *dev, enum platform_profile_option *profile); -- cgit v1.2.3 From 0025d83a3c201d0f1cda1085a3847591af563ec2 Mon Sep 17 00:00:00 2001 From: Kurt Borja Date: Wed, 15 Jan 2025 19:27:21 -0500 Subject: ACPI: platform_profile: Add a prefix to log messages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Declare a pr_fmt prefix. Reviewed-by: Mario Limonciello Signed-off-by: Kurt Borja Reviewed-by: Mark Pearson Tested-by: Mark Pearson Link: https://lore.kernel.org/r/20250116002721.75592-20-kuurtb@gmail.com Reviewed-by: Ilpo Järvinen Signed-off-by: Ilpo Järvinen --- drivers/acpi/platform_profile.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/acpi/platform_profile.c') diff --git a/drivers/acpi/platform_profile.c b/drivers/acpi/platform_profile.c index 49af808153a7..fc92e43d0fe9 100644 --- a/drivers/acpi/platform_profile.c +++ b/drivers/acpi/platform_profile.c @@ -2,6 +2,8 @@ /* Platform profile sysfs interface */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include -- cgit v1.2.3