Skip to content

Commit 77be5ca

Browse files
superm1ij-intel
authored andcommitted
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 <[email protected]> Tested-by: Mark Pearson <[email protected]> Reviewed-by: Mark Pearson <[email protected]> Reviewed-by: Ilpo Järvinen <[email protected]> Signed-off-by: Mario Limonciello <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Ilpo Järvinen <[email protected]>
1 parent 1f3ac55 commit 77be5ca

File tree

2 files changed

+79
-5
lines changed

2 files changed

+79
-5
lines changed

drivers/acpi/platform_profile.c

Lines changed: 77 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include <linux/acpi.h>
66
#include <linux/bits.h>
77
#include <linux/init.h>
8+
#include <linux/kdev_t.h>
89
#include <linux/mutex.h>
910
#include <linux/platform_profile.h>
1011
#include <linux/sysfs.h>
@@ -22,6 +23,12 @@ static const char * const profile_names[] = {
2223
};
2324
static_assert(ARRAY_SIZE(profile_names) == PLATFORM_PROFILE_LAST);
2425

26+
static DEFINE_IDA(platform_profile_ida);
27+
28+
static const struct class platform_profile_class = {
29+
.name = "platform-profile",
30+
};
31+
2532
static ssize_t platform_profile_choices_show(struct device *dev,
2633
struct device_attribute *attr,
2734
char *buf)
@@ -101,8 +108,21 @@ static struct attribute *platform_profile_attrs[] = {
101108
NULL
102109
};
103110

111+
static int profile_class_registered(struct device *dev, const void *data)
112+
{
113+
return 1;
114+
}
115+
116+
static umode_t profile_class_is_visible(struct kobject *kobj, struct attribute *attr, int idx)
117+
{
118+
if (!class_find_device(&platform_profile_class, NULL, NULL, profile_class_registered))
119+
return 0;
120+
return attr->mode;
121+
}
122+
104123
static const struct attribute_group platform_profile_group = {
105-
.attrs = platform_profile_attrs
124+
.attrs = platform_profile_attrs,
125+
.is_visible = profile_class_is_visible,
106126
};
107127

108128
void platform_profile_notify(struct platform_profile_handler *pprof)
@@ -160,25 +180,77 @@ int platform_profile_register(struct platform_profile_handler *pprof)
160180
if (cur_profile)
161181
return -EEXIST;
162182

163-
err = sysfs_create_group(acpi_kobj, &platform_profile_group);
164-
if (err)
165-
return err;
183+
/* create class interface for individual handler */
184+
pprof->minor = ida_alloc(&platform_profile_ida, GFP_KERNEL);
185+
if (pprof->minor < 0)
186+
return pprof->minor;
187+
pprof->class_dev = device_create(&platform_profile_class, pprof->dev,
188+
MKDEV(0, 0), pprof, "platform-profile-%d",
189+
pprof->minor);
190+
if (IS_ERR(pprof->class_dev)) {
191+
err = PTR_ERR(pprof->class_dev);
192+
goto cleanup_ida;
193+
}
166194

167195
cur_profile = pprof;
196+
197+
err = sysfs_update_group(acpi_kobj, &platform_profile_group);
198+
if (err)
199+
goto cleanup_cur;
200+
168201
return 0;
202+
203+
cleanup_cur:
204+
cur_profile = NULL;
205+
device_unregister(pprof->class_dev);
206+
207+
cleanup_ida:
208+
ida_free(&platform_profile_ida, pprof->minor);
209+
210+
return err;
169211
}
170212
EXPORT_SYMBOL_GPL(platform_profile_register);
171213

172214
int platform_profile_remove(struct platform_profile_handler *pprof)
173215
{
216+
int id;
174217
guard(mutex)(&profile_lock);
175218

176-
sysfs_remove_group(acpi_kobj, &platform_profile_group);
177219
cur_profile = NULL;
220+
221+
id = pprof->minor;
222+
device_unregister(pprof->class_dev);
223+
ida_free(&platform_profile_ida, id);
224+
225+
sysfs_update_group(acpi_kobj, &platform_profile_group);
226+
178227
return 0;
179228
}
180229
EXPORT_SYMBOL_GPL(platform_profile_remove);
181230

231+
static int __init platform_profile_init(void)
232+
{
233+
int err;
234+
235+
err = class_register(&platform_profile_class);
236+
if (err)
237+
return err;
238+
239+
err = sysfs_create_group(acpi_kobj, &platform_profile_group);
240+
if (err)
241+
class_unregister(&platform_profile_class);
242+
243+
return err;
244+
}
245+
246+
static void __exit platform_profile_exit(void)
247+
{
248+
sysfs_remove_group(acpi_kobj, &platform_profile_group);
249+
class_unregister(&platform_profile_class);
250+
}
251+
module_init(platform_profile_init);
252+
module_exit(platform_profile_exit);
253+
182254
MODULE_AUTHOR("Mark Pearson <[email protected]>");
183255
MODULE_DESCRIPTION("ACPI platform profile sysfs interface");
184256
MODULE_LICENSE("GPL");

include/linux/platform_profile.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ enum platform_profile_option {
2929
struct platform_profile_handler {
3030
const char *name;
3131
struct device *dev;
32+
struct device *class_dev;
33+
int minor;
3234
unsigned long choices[BITS_TO_LONGS(PLATFORM_PROFILE_LAST)];
3335
int (*profile_get)(struct platform_profile_handler *pprof,
3436
enum platform_profile_option *profile);

0 commit comments

Comments
 (0)