From: Armin Wolf <W_Armin@gmx.de>
To: "Mario Limonciello" <mario.limonciello@amd.com>,
"Hans de Goede" <hdegoede@redhat.com>,
"Ilpo Järvinen" <ilpo.jarvinen@linux.intel.com>
Cc: "Rafael J . Wysocki" <rafael@kernel.org>,
"Len Brown" <lenb@kernel.org>,
"Maximilian Luz" <luzmaximilian@gmail.com>,
"Lee Chun-Yi" <jlee@suse.com>,
"Shyam Sundar S K" <Shyam-sundar.S-k@amd.com>,
"Corentin Chary" <corentin.chary@gmail.com>,
"Luke D . Jones" <luke@ljones.dev>,
"Ike Panhc" <ike.pan@canonical.com>,
"Henrique de Moraes Holschuh" <hmh@hmh.eng.br>,
"Alexis Belmonte" <alexbelm48@gmail.com>,
"Uwe Kleine-König" <u.kleine-koenig@pengutronix.de>,
"Ai Chao" <aichao@kylinos.cn>, "Gergo Koteles" <soyer@irl.hu>,
"open list" <linux-kernel@vger.kernel.org>,
"open list:ACPI" <linux-acpi@vger.kernel.org>,
"open list:MICROSOFT SURFACE PLATFORM PROFILE DRIVER"
<platform-driver-x86@vger.kernel.org>,
"open list:THINKPAD ACPI EXTRAS DRIVER"
<ibm-acpi-devel@lists.sourceforge.net>,
"Mark Pearson" <mpearson-lenovo@squebb.ca>,
"Matthew Schwartz" <matthew.schwartz@linux.dev>
Subject: Re: [PATCH v3 20/22] ACPI: platform_profile: Register class device for platform profile handlers
Date: Thu, 31 Oct 2024 21:55:59 +0100 [thread overview]
Message-ID: <9fdcfdb4-bbdd-4f6a-9a69-73dceac7b14b@gmx.de> (raw)
In-Reply-To: <20241031040952.109057-21-mario.limonciello@amd.com>
Am 31.10.24 um 05:09 schrieb Mario Limonciello:
> The "platform_profile" class device has the exact same semantics as the
> platform profile files in /sys/firmware/acpi/ but it reflects values only
> present for a single platform profile handler.
>
> The expectation is that legacy userspace can change the profile for all
> handlers in /sys/firmware/acpi/platform_profile and can change it for
> individual handlers by /sys/class/platform_profile/*.
>
> Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
> ---
> drivers/acpi/platform_profile.c | 93 ++++++++++++++++++++++++++++----
> include/linux/platform_profile.h | 2 +
> 2 files changed, 85 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/acpi/platform_profile.c b/drivers/acpi/platform_profile.c
> index 9b681884ae324..1cc8182930dde 100644
> --- a/drivers/acpi/platform_profile.c
> +++ b/drivers/acpi/platform_profile.c
> @@ -24,13 +24,24 @@ static const char * const profile_names[] = {
> };
> static_assert(ARRAY_SIZE(profile_names) == PLATFORM_PROFILE_LAST);
>
> +static DEFINE_IDR(platform_profile_minor_idr);
> +
> +static const struct class platform_profile_class = {
> + .name = "platform-profile",
> +};
> +
> static bool platform_profile_is_registered(void)
> {
> lockdep_assert_held(&profile_lock);
> return !list_empty(&platform_profile_handler_list);
> }
>
> -static unsigned long platform_profile_get_choices(void)
> +static bool platform_profile_is_class_device(struct device *dev)
> +{
> + return dev && dev->class == &platform_profile_class;
> +}
> +
> +static unsigned long platform_profile_get_choices(struct device *dev)
> {
> struct platform_profile_handler *handler;
> unsigned long aggregate = 0;
> @@ -40,6 +51,9 @@ static unsigned long platform_profile_get_choices(void)
> list_for_each_entry(handler, &platform_profile_handler_list, list) {
> unsigned long individual = 0;
>
> + /* if called from a class attribute then only match that one */
> + if (platform_profile_is_class_device(dev) && handler->dev != dev->parent)
> + continue;
I do not like how the sysfs attributes for the platform-profile class are handled:
1. We should use .dev_groups instead of manually registering the sysfs attributes.
2. Can we name the sysfs attributes for the class a bit differently ("profile_choices" and "profile")
and use separate store/show functions for those?
3. Why do we still need platform_profile_handler_list?
This would allow us to get rid of platform_profile_is_class_device().
> for_each_set_bit(i, handler->choices, PLATFORM_PROFILE_LAST)
> individual |= BIT(i);
> if (!aggregate)
> @@ -51,7 +65,7 @@ static unsigned long platform_profile_get_choices(void)
> return aggregate;
> }
>
> -static int platform_profile_get_active(enum platform_profile_option *profile)
> +static int platform_profile_get_active(struct device *dev, enum platform_profile_option *profile)
> {
> struct platform_profile_handler *handler;
> enum platform_profile_option active = PLATFORM_PROFILE_LAST;
> @@ -60,6 +74,8 @@ static int platform_profile_get_active(enum platform_profile_option *profile)
>
> lockdep_assert_held(&profile_lock);
> list_for_each_entry(handler, &platform_profile_handler_list, list) {
> + if (platform_profile_is_class_device(dev) && handler->dev != dev->parent)
> + continue;
> err = handler->profile_get(handler, &val);
> if (err) {
> pr_err("Failed to get profile for handler %s\n", handler->name);
> @@ -69,6 +85,10 @@ static int platform_profile_get_active(enum platform_profile_option *profile)
> if (WARN_ON(val >= PLATFORM_PROFILE_LAST))
> return -EINVAL;
>
> + /*
> + * If the profiles are different for class devices then this must
> + * show "custom" to legacy sysfs interface
> + */
> if (active != val && active != PLATFORM_PROFILE_LAST) {
> *profile = PLATFORM_PROFILE_CUSTOM;
> return 0;
> @@ -90,7 +110,7 @@ static ssize_t platform_profile_choices_show(struct device *dev,
> int i;
>
> scoped_cond_guard(mutex_intr, return -ERESTARTSYS, &profile_lock)
> - choices = platform_profile_get_choices();
> + choices = platform_profile_get_choices(dev);
>
> for_each_set_bit(i, &choices, PLATFORM_PROFILE_LAST) {
> if (len == 0)
> @@ -113,7 +133,7 @@ static ssize_t platform_profile_show(struct device *dev,
> scoped_cond_guard(mutex_intr, return -ERESTARTSYS, &profile_lock) {
> if (!platform_profile_is_registered())
> return -ENODEV;
> - err = platform_profile_get_active(&profile);
> + err = platform_profile_get_active(dev, &profile);
> if (err)
> return err;
> }
> @@ -138,12 +158,22 @@ static ssize_t platform_profile_store(struct device *dev,
> if (!platform_profile_is_registered())
> return -ENODEV;
>
> - /* Check that all handlers support this profile choice */
> - choices = platform_profile_get_choices();
> + /* don't allow setting custom to legacy sysfs interface */
> + if (!platform_profile_is_class_device(dev) &&
> + i == PLATFORM_PROFILE_CUSTOM) {
> + pr_warn("Custom profile not supported for legacy sysfs interface\n");
> + return -EINVAL;
> + }
> +
> + /* Check that applicable handlers support this profile choice */
> + choices = platform_profile_get_choices(dev);
> if (!test_bit(i, &choices))
> return -EOPNOTSUPP;
>
> list_for_each_entry(handler, &platform_profile_handler_list, list) {
> + if (platform_profile_is_class_device(dev) &&
> + handler->dev != dev->parent)
> + continue;
> err = handler->profile_set(handler, i);
> if (err) {
> pr_err("Failed to set profile for handler %s\n", handler->name);
> @@ -152,6 +182,9 @@ static ssize_t platform_profile_store(struct device *dev,
> }
> if (err) {
> list_for_each_entry_continue_reverse(handler, &platform_profile_handler_list, list) {
> + if (platform_profile_is_class_device(dev) &&
> + handler->dev != dev->parent)
> + continue;
> if (handler->profile_set(handler, PLATFORM_PROFILE_BALANCED))
> pr_err("Failed to revert profile for handler %s\n",
> handler->name);
> @@ -194,11 +227,11 @@ int platform_profile_cycle(void)
> int err;
>
> scoped_cond_guard(mutex_intr, return -ERESTARTSYS, &profile_lock) {
> - err = platform_profile_get_active(&profile);
> + err = platform_profile_get_active(NULL, &profile);
> if (err)
> return err;
>
> - choices = platform_profile_get_choices();
> + choices = platform_profile_get_choices(NULL);
>
> next = find_next_bit_wrap(&choices,
> PLATFORM_PROFILE_LAST,
> @@ -228,6 +261,7 @@ EXPORT_SYMBOL_GPL(platform_profile_cycle);
>
> int platform_profile_register(struct platform_profile_handler *pprof)
> {
> + bool registered;
> int err;
>
> /* Sanity check the profile handler */
> @@ -250,14 +284,49 @@ int platform_profile_register(struct platform_profile_handler *pprof)
> if (cur_profile)
> return -EEXIST;
>
> - err = sysfs_create_group(acpi_kobj, &platform_profile_group);
> + registered = platform_profile_is_registered();
> + if (!registered) {
> + /* class for individual handlers */
> + err = class_register(&platform_profile_class);
> + if (err)
> + return err;
Why do we need to unregister the class here? From my point of view, having a empty class if no
platform profiles are registered is totally fine.
> + /* legacy sysfs files */
> + err = sysfs_create_group(acpi_kobj, &platform_profile_group);
> + if (err)
> + goto cleanup_class;
> +
> + }
> +
> + /* create class interface for individual handler */
> + pprof->minor = idr_alloc(&platform_profile_minor_idr, pprof, 0, 0, GFP_KERNEL);
> + pprof->class_dev = device_create(&platform_profile_class, pprof->dev,
> + MKDEV(0, pprof->minor), NULL, "platform-profile-%s",
> + pprof->name);
I would suggest that the name of the class devices should not contain the platform profile name,
as this would mean that two platform profile handlers cannot have the same name.
Maybe using "platform-profile-<minor>" would be a better solution here? The name can instead be
read using an additional sysfs property.
Thanks,
Armin Wolf
> + if (IS_ERR(pprof->class_dev)) {
> + err = PTR_ERR(pprof->class_dev);
> + goto cleanup_legacy;
> + }
> + err = sysfs_create_group(&pprof->class_dev->kobj, &platform_profile_group);
> if (err)
> - return err;
> + goto cleanup_device;
> +
> list_add_tail(&pprof->list, &platform_profile_handler_list);
> sysfs_notify(acpi_kobj, NULL, "platform_profile");
>
> cur_profile = pprof;
> return 0;
> +
> +cleanup_device:
> + device_destroy(&platform_profile_class, MKDEV(0, pprof->minor));
> +
> +cleanup_legacy:
> + if (!registered)
> + sysfs_remove_group(acpi_kobj, &platform_profile_group);
> +cleanup_class:
> + if (!registered)
> + class_unregister(&platform_profile_class);
> +
> + return err;
> }
> EXPORT_SYMBOL_GPL(platform_profile_register);
>
> @@ -270,6 +339,10 @@ int platform_profile_remove(struct platform_profile_handler *pprof)
> cur_profile = NULL;
>
> sysfs_notify(acpi_kobj, NULL, "platform_profile");
> +
> + sysfs_remove_group(&pprof->class_dev->kobj, &platform_profile_group);
> + device_destroy(&platform_profile_class, MKDEV(0, pprof->minor));
> +
> if (!platform_profile_is_registered())
> sysfs_remove_group(acpi_kobj, &platform_profile_group);
>
> diff --git a/include/linux/platform_profile.h b/include/linux/platform_profile.h
> index da009c8a402c9..764c4812ef759 100644
> --- a/include/linux/platform_profile.h
> +++ b/include/linux/platform_profile.h
> @@ -30,6 +30,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)];
> struct list_head list;
> int (*profile_get)(struct platform_profile_handler *pprof,
next prev parent reply other threads:[~2024-10-31 20:57 UTC|newest]
Thread overview: 51+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-10-31 4:09 [PATCH v3 00/22] Add support for binding ACPI platform profile to multiple drivers Mario Limonciello
2024-10-31 4:09 ` [PATCH v3 01/22] ACPI: platform-profile: Add a name member to handlers Mario Limonciello
2024-10-31 4:09 ` [PATCH v3 02/22] platform/x86/dell: dell-pc: Create platform device Mario Limonciello
2024-10-31 4:09 ` [PATCH v3 03/22] ACPI: platform_profile: Add device pointer into platform profile handler Mario Limonciello
2024-11-02 2:13 ` Mark Pearson
2024-11-02 9:56 ` Maximilian Luz
2024-10-31 4:09 ` [PATCH v3 04/22] ACPI: platform_profile: Add platform handler argument to platform_profile_remove() Mario Limonciello
2024-10-31 4:09 ` [PATCH v3 05/22] ACPI: platform_profile: Add a list to platform profile handler Mario Limonciello
2024-10-31 4:09 ` [PATCH v3 06/22] ACPI: platform_profile: Move sanity check out of the mutex Mario Limonciello
2024-11-02 2:13 ` Mark Pearson
2024-10-31 4:09 ` [PATCH v3 07/22] ACPI: platform_profile: Use guard(mutex) for register/unregister Mario Limonciello
2024-10-31 10:16 ` Ilpo Järvinen
2024-10-31 4:09 ` [PATCH v3 08/22] ACPI: platform_profile: Use `scoped_cond_guard` for platform_profile_choices_show() Mario Limonciello
2024-10-31 4:09 ` [PATCH v3 09/22] ACPI: platform_profile: Use `scoped_cond_guard` for platform_profile_show() Mario Limonciello
2024-10-31 4:09 ` [PATCH v3 10/22] " Mario Limonciello
2024-10-31 10:15 ` Ilpo Järvinen
2024-10-31 13:16 ` Mario Limonciello
2024-10-31 4:09 ` [PATCH v3 11/22] ACPI: platform_profile: Use `scoped_cond_guard` for platform_profile_cycle() Mario Limonciello
2024-11-02 2:14 ` Mark Pearson
2024-10-31 4:09 ` [PATCH v3 12/22] ACPI: platform_profile: Only remove group when no more handler registered Mario Limonciello
2024-10-31 4:09 ` [PATCH v3 13/22] ACPI: platform_profile: Require handlers to support balanced profile Mario Limonciello
2024-10-31 20:39 ` Armin Wolf
2024-10-31 20:43 ` Mario Limonciello
2024-10-31 21:01 ` Armin Wolf
2024-10-31 4:09 ` [PATCH v3 14/22] ACPI: platform_profile: Notify change events on register and unregister Mario Limonciello
2024-11-02 2:14 ` Mark Pearson
2024-10-31 4:09 ` [PATCH v3 15/22] ACPI: platform_profile: Only show profiles common for all handlers Mario Limonciello
2024-11-02 2:15 ` Mark Pearson
2024-10-31 4:09 ` [PATCH v3 16/22] ACPI: platform_profile: Set profile for all registered handlers Mario Limonciello
2024-10-31 10:25 ` Ilpo Järvinen
2024-10-31 13:18 ` Mario Limonciello
2024-10-31 14:37 ` Ilpo Järvinen
2024-10-31 14:40 ` Mario Limonciello
2024-10-31 4:09 ` [PATCH v3 17/22] ACPI: platform_profile: Add concept of a "custom" profile Mario Limonciello
2024-11-02 2:15 ` Mark Pearson
2024-10-31 4:09 ` [PATCH v3 18/22] ACPI: platform_profile: Make sure all profile handlers agree on profile Mario Limonciello
2024-11-02 2:15 ` Mark Pearson
2024-10-31 4:09 ` [PATCH v3 19/22] ACPI: platform_profile: Check all profile handler to calculate next Mario Limonciello
2024-10-31 10:40 ` Ilpo Järvinen
2024-11-02 2:15 ` Mark Pearson
2024-10-31 4:09 ` [PATCH v3 20/22] ACPI: platform_profile: Register class device for platform profile handlers Mario Limonciello
2024-10-31 20:55 ` Armin Wolf [this message]
2024-10-31 21:54 ` Mario Limonciello
2024-11-01 1:54 ` Armin Wolf
2024-11-02 2:13 ` Mark Pearson
2024-11-02 23:46 ` Armin Wolf
2024-11-01 14:22 ` kernel test robot
2024-11-01 15:45 ` kernel test robot
2024-10-31 4:09 ` [PATCH v3 21/22] ACPI: platform_profile: Allow multiple handlers Mario Limonciello
2024-11-02 2:15 ` Mark Pearson
2024-10-31 4:09 ` [PATCH v3 22/22] platform/x86/amd: pmf: Drop all quirks Mario Limonciello
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=9fdcfdb4-bbdd-4f6a-9a69-73dceac7b14b@gmx.de \
--to=w_armin@gmx.de \
--cc=Shyam-sundar.S-k@amd.com \
--cc=aichao@kylinos.cn \
--cc=alexbelm48@gmail.com \
--cc=corentin.chary@gmail.com \
--cc=hdegoede@redhat.com \
--cc=hmh@hmh.eng.br \
--cc=ibm-acpi-devel@lists.sourceforge.net \
--cc=ike.pan@canonical.com \
--cc=ilpo.jarvinen@linux.intel.com \
--cc=jlee@suse.com \
--cc=lenb@kernel.org \
--cc=linux-acpi@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=luke@ljones.dev \
--cc=luzmaximilian@gmail.com \
--cc=mario.limonciello@amd.com \
--cc=matthew.schwartz@linux.dev \
--cc=mpearson-lenovo@squebb.ca \
--cc=platform-driver-x86@vger.kernel.org \
--cc=rafael@kernel.org \
--cc=soyer@irl.hu \
--cc=u.kleine-koenig@pengutronix.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox