1
0
Fork 0
mirror of synced 2025-03-06 20:59:54 +01:00

ACPI: platform_profile: Create class for ACPI platform profile

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 <W_Armin@gmx.de>
Tested-by: Mark Pearson <mpearson-lenovo@squebb.ca>
Reviewed-by: Mark Pearson <mpearson-lenovo@squebb.ca>
Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
Link: https://lore.kernel.org/r/20241206031918.1537-11-mario.limonciello@amd.com
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
This commit is contained in:
Mario Limonciello 2024-12-05 21:19:06 -06:00 committed by Ilpo Järvinen
parent 1f3ac55c2e
commit 77be5cacb2
No known key found for this signature in database
GPG key ID: 59AC4F6153E5CE31
2 changed files with 79 additions and 5 deletions

View file

@ -5,6 +5,7 @@
#include <linux/acpi.h>
#include <linux/bits.h>
#include <linux/init.h>
#include <linux/kdev_t.h>
#include <linux/mutex.h>
#include <linux/platform_profile.h>
#include <linux/sysfs.h>
@ -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 <markpearson@lenovo.com>");
MODULE_DESCRIPTION("ACPI platform profile sysfs interface");
MODULE_LICENSE("GPL");

View file

@ -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);