xref: /linux/drivers/acpi/platform_profile.c (revision d1e879ec600f9b3bdd253167533959facfefb17b)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 
3 /* Platform profile sysfs interface */
4 
5 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
6 
7 #include <linux/acpi.h>
8 #include <linux/bits.h>
9 #include <linux/cleanup.h>
10 #include <linux/init.h>
11 #include <linux/mutex.h>
12 #include <linux/platform_profile.h>
13 #include <linux/sysfs.h>
14 
15 #define to_pprof_handler(d)	(container_of(d, struct platform_profile_handler, dev))
16 
17 static DEFINE_MUTEX(profile_lock);
18 
19 struct platform_profile_handler {
20 	const char *name;
21 	struct device dev;
22 	int minor;
23 	unsigned long choices[BITS_TO_LONGS(PLATFORM_PROFILE_LAST)];
24 	const struct platform_profile_ops *ops;
25 };
26 
27 static const char * const profile_names[] = {
28 	[PLATFORM_PROFILE_LOW_POWER] = "low-power",
29 	[PLATFORM_PROFILE_COOL] = "cool",
30 	[PLATFORM_PROFILE_QUIET] = "quiet",
31 	[PLATFORM_PROFILE_BALANCED] = "balanced",
32 	[PLATFORM_PROFILE_BALANCED_PERFORMANCE] = "balanced-performance",
33 	[PLATFORM_PROFILE_PERFORMANCE] = "performance",
34 	[PLATFORM_PROFILE_CUSTOM] = "custom",
35 };
36 static_assert(ARRAY_SIZE(profile_names) == PLATFORM_PROFILE_LAST);
37 
38 static DEFINE_IDA(platform_profile_ida);
39 
40 /**
41  * _commmon_choices_show - Show the available profile choices
42  * @choices: The available profile choices
43  * @buf: The buffer to write to
44  *
45  * Return: The number of bytes written
46  */
47 static ssize_t _commmon_choices_show(unsigned long *choices, char *buf)
48 {
49 	int i, len = 0;
50 
51 	for_each_set_bit(i, choices, PLATFORM_PROFILE_LAST) {
52 		if (len == 0)
53 			len += sysfs_emit_at(buf, len, "%s", profile_names[i]);
54 		else
55 			len += sysfs_emit_at(buf, len, " %s", profile_names[i]);
56 	}
57 	len += sysfs_emit_at(buf, len, "\n");
58 
59 	return len;
60 }
61 
62 /**
63  * _store_class_profile - Set the profile for a class device
64  * @dev: The class device
65  * @data: The profile to set
66  *
67  * Return: 0 on success, -errno on failure
68  */
69 static int _store_class_profile(struct device *dev, void *data)
70 {
71 	struct platform_profile_handler *handler;
72 	int *bit = (int *)data;
73 
74 	lockdep_assert_held(&profile_lock);
75 	handler = to_pprof_handler(dev);
76 	if (!test_bit(*bit, handler->choices))
77 		return -EOPNOTSUPP;
78 
79 	return handler->ops->profile_set(dev, *bit);
80 }
81 
82 /**
83  * _notify_class_profile - Notify the class device of a profile change
84  * @dev: The class device
85  * @data: Unused
86  *
87  * Return: 0 on success, -errno on failure
88  */
89 static int _notify_class_profile(struct device *dev, void *data)
90 {
91 	struct platform_profile_handler *handler = to_pprof_handler(dev);
92 
93 	lockdep_assert_held(&profile_lock);
94 	sysfs_notify(&handler->dev.kobj, NULL, "profile");
95 	kobject_uevent(&handler->dev.kobj, KOBJ_CHANGE);
96 
97 	return 0;
98 }
99 
100 /**
101  * get_class_profile - Show the current profile for a class device
102  * @dev: The class device
103  * @profile: The profile to return
104  *
105  * Return: 0 on success, -errno on failure
106  */
107 static int get_class_profile(struct device *dev,
108 			     enum platform_profile_option *profile)
109 {
110 	struct platform_profile_handler *handler;
111 	enum platform_profile_option val;
112 	int err;
113 
114 	lockdep_assert_held(&profile_lock);
115 	handler = to_pprof_handler(dev);
116 	err = handler->ops->profile_get(dev, &val);
117 	if (err) {
118 		pr_err("Failed to get profile for handler %s\n", handler->name);
119 		return err;
120 	}
121 
122 	if (WARN_ON(val >= PLATFORM_PROFILE_LAST))
123 		return -EINVAL;
124 	*profile = val;
125 
126 	return 0;
127 }
128 
129 /**
130  * name_show - Show the name of the profile handler
131  * @dev: The device
132  * @attr: The attribute
133  * @buf: The buffer to write to
134  *
135  * Return: The number of bytes written
136  */
137 static ssize_t name_show(struct device *dev, struct device_attribute *attr, char *buf)
138 {
139 	struct platform_profile_handler *handler = to_pprof_handler(dev);
140 
141 	return sysfs_emit(buf, "%s\n", handler->name);
142 }
143 static DEVICE_ATTR_RO(name);
144 
145 /**
146  * choices_show - Show the available profile choices
147  * @dev: The device
148  * @attr: The attribute
149  * @buf: The buffer to write to
150  *
151  * Return: The number of bytes written
152  */
153 static ssize_t choices_show(struct device *dev,
154 			    struct device_attribute *attr,
155 			    char *buf)
156 {
157 	struct platform_profile_handler *handler = to_pprof_handler(dev);
158 
159 	return _commmon_choices_show(handler->choices, buf);
160 }
161 static DEVICE_ATTR_RO(choices);
162 
163 /**
164  * profile_show - Show the current profile for a class device
165  * @dev: The device
166  * @attr: The attribute
167  * @buf: The buffer to write to
168  *
169  * Return: The number of bytes written
170  */
171 static ssize_t profile_show(struct device *dev,
172 			    struct device_attribute *attr,
173 			    char *buf)
174 {
175 	enum platform_profile_option profile = PLATFORM_PROFILE_LAST;
176 	int err;
177 
178 	scoped_cond_guard(mutex_intr, return -ERESTARTSYS, &profile_lock) {
179 		err = get_class_profile(dev, &profile);
180 		if (err)
181 			return err;
182 	}
183 
184 	return sysfs_emit(buf, "%s\n", profile_names[profile]);
185 }
186 
187 /**
188  * profile_store - Set the profile for a class device
189  * @dev: The device
190  * @attr: The attribute
191  * @buf: The buffer to read from
192  * @count: The number of bytes to read
193  *
194  * Return: The number of bytes read
195  */
196 static ssize_t profile_store(struct device *dev,
197 			     struct device_attribute *attr,
198 			     const char *buf, size_t count)
199 {
200 	int index, ret;
201 
202 	index = sysfs_match_string(profile_names, buf);
203 	if (index < 0)
204 		return -EINVAL;
205 
206 	scoped_cond_guard(mutex_intr, return -ERESTARTSYS, &profile_lock) {
207 		ret = _store_class_profile(dev, &index);
208 		if (ret)
209 			return ret;
210 	}
211 
212 	sysfs_notify(acpi_kobj, NULL, "platform_profile");
213 
214 	return count;
215 }
216 static DEVICE_ATTR_RW(profile);
217 
218 static struct attribute *profile_attrs[] = {
219 	&dev_attr_name.attr,
220 	&dev_attr_choices.attr,
221 	&dev_attr_profile.attr,
222 	NULL
223 };
224 ATTRIBUTE_GROUPS(profile);
225 
226 static void pprof_device_release(struct device *dev)
227 {
228 	struct platform_profile_handler *pprof = to_pprof_handler(dev);
229 
230 	kfree(pprof);
231 }
232 
233 static const struct class platform_profile_class = {
234 	.name = "platform-profile",
235 	.dev_groups = profile_groups,
236 	.dev_release = pprof_device_release,
237 };
238 
239 /**
240  * _aggregate_choices - Aggregate the available profile choices
241  * @dev: The device
242  * @data: The available profile choices
243  *
244  * Return: 0 on success, -errno on failure
245  */
246 static int _aggregate_choices(struct device *dev, void *data)
247 {
248 	struct platform_profile_handler *handler;
249 	unsigned long *aggregate = data;
250 
251 	lockdep_assert_held(&profile_lock);
252 	handler = to_pprof_handler(dev);
253 	if (test_bit(PLATFORM_PROFILE_LAST, aggregate))
254 		bitmap_copy(aggregate, handler->choices, PLATFORM_PROFILE_LAST);
255 	else
256 		bitmap_and(aggregate, handler->choices, aggregate, PLATFORM_PROFILE_LAST);
257 
258 	return 0;
259 }
260 
261 /**
262  * platform_profile_choices_show - Show the available profile choices for legacy sysfs interface
263  * @dev: The device
264  * @attr: The attribute
265  * @buf: The buffer to write to
266  *
267  * Return: The number of bytes written
268  */
269 static ssize_t platform_profile_choices_show(struct device *dev,
270 					     struct device_attribute *attr,
271 					     char *buf)
272 {
273 	unsigned long aggregate[BITS_TO_LONGS(PLATFORM_PROFILE_LAST)];
274 	int err;
275 
276 	set_bit(PLATFORM_PROFILE_LAST, aggregate);
277 	scoped_cond_guard(mutex_intr, return -ERESTARTSYS, &profile_lock) {
278 		err = class_for_each_device(&platform_profile_class, NULL,
279 					    aggregate, _aggregate_choices);
280 		if (err)
281 			return err;
282 	}
283 
284 	/* no profile handler registered any more */
285 	if (bitmap_empty(aggregate, PLATFORM_PROFILE_LAST))
286 		return -EINVAL;
287 
288 	return _commmon_choices_show(aggregate, buf);
289 }
290 
291 /**
292  * _aggregate_profiles - Aggregate the profiles for legacy sysfs interface
293  * @dev: The device
294  * @data: The profile to return
295  *
296  * Return: 0 on success, -errno on failure
297  */
298 static int _aggregate_profiles(struct device *dev, void *data)
299 {
300 	enum platform_profile_option *profile = data;
301 	enum platform_profile_option val;
302 	int err;
303 
304 	err = get_class_profile(dev, &val);
305 	if (err)
306 		return err;
307 
308 	if (*profile != PLATFORM_PROFILE_LAST && *profile != val)
309 		*profile = PLATFORM_PROFILE_CUSTOM;
310 	else
311 		*profile = val;
312 
313 	return 0;
314 }
315 
316 /**
317  * _store_and_notify - Store and notify a class from legacy sysfs interface
318  * @dev: The device
319  * @data: The profile to return
320  *
321  * Return: 0 on success, -errno on failure
322  */
323 static int _store_and_notify(struct device *dev, void *data)
324 {
325 	enum platform_profile_option *profile = data;
326 	int err;
327 
328 	err = _store_class_profile(dev, profile);
329 	if (err)
330 		return err;
331 	return _notify_class_profile(dev, NULL);
332 }
333 
334 /**
335  * platform_profile_show - Show the current profile for legacy sysfs interface
336  * @dev: The device
337  * @attr: The attribute
338  * @buf: The buffer to write to
339  *
340  * Return: The number of bytes written
341  */
342 static ssize_t platform_profile_show(struct device *dev,
343 				     struct device_attribute *attr,
344 				     char *buf)
345 {
346 	enum platform_profile_option profile = PLATFORM_PROFILE_LAST;
347 	int err;
348 
349 	scoped_cond_guard(mutex_intr, return -ERESTARTSYS, &profile_lock) {
350 		err = class_for_each_device(&platform_profile_class, NULL,
351 					    &profile, _aggregate_profiles);
352 		if (err)
353 			return err;
354 	}
355 
356 	/* no profile handler registered any more */
357 	if (profile == PLATFORM_PROFILE_LAST)
358 		return -EINVAL;
359 
360 	return sysfs_emit(buf, "%s\n", profile_names[profile]);
361 }
362 
363 /**
364  * platform_profile_store - Set the profile for legacy sysfs interface
365  * @dev: The device
366  * @attr: The attribute
367  * @buf: The buffer to read from
368  * @count: The number of bytes to read
369  *
370  * Return: The number of bytes read
371  */
372 static ssize_t platform_profile_store(struct device *dev,
373 				      struct device_attribute *attr,
374 				      const char *buf, size_t count)
375 {
376 	unsigned long choices[BITS_TO_LONGS(PLATFORM_PROFILE_LAST)];
377 	int ret;
378 	int i;
379 
380 	/* Scan for a matching profile */
381 	i = sysfs_match_string(profile_names, buf);
382 	if (i < 0 || i == PLATFORM_PROFILE_CUSTOM)
383 		return -EINVAL;
384 	set_bit(PLATFORM_PROFILE_LAST, choices);
385 	scoped_cond_guard(mutex_intr, return -ERESTARTSYS, &profile_lock) {
386 		ret = class_for_each_device(&platform_profile_class, NULL,
387 					    choices, _aggregate_choices);
388 		if (ret)
389 			return ret;
390 		if (!test_bit(i, choices))
391 			return -EOPNOTSUPP;
392 
393 		ret = class_for_each_device(&platform_profile_class, NULL, &i,
394 					    _store_and_notify);
395 		if (ret)
396 			return ret;
397 	}
398 
399 	sysfs_notify(acpi_kobj, NULL, "platform_profile");
400 
401 	return count;
402 }
403 
404 static DEVICE_ATTR_RO(platform_profile_choices);
405 static DEVICE_ATTR_RW(platform_profile);
406 
407 static struct attribute *platform_profile_attrs[] = {
408 	&dev_attr_platform_profile_choices.attr,
409 	&dev_attr_platform_profile.attr,
410 	NULL
411 };
412 
413 static int profile_class_registered(struct device *dev, const void *data)
414 {
415 	return 1;
416 }
417 
418 static umode_t profile_class_is_visible(struct kobject *kobj, struct attribute *attr, int idx)
419 {
420 	struct device *dev;
421 
422 	dev = class_find_device(&platform_profile_class, NULL, NULL, profile_class_registered);
423 	if (!dev)
424 		return 0;
425 
426 	put_device(dev);
427 
428 	return attr->mode;
429 }
430 
431 static const struct attribute_group platform_profile_group = {
432 	.attrs = platform_profile_attrs,
433 	.is_visible = profile_class_is_visible,
434 };
435 
436 /**
437  * platform_profile_notify - Notify class device and legacy sysfs interface
438  * @dev: The class device
439  */
440 void platform_profile_notify(struct device *dev)
441 {
442 	scoped_cond_guard(mutex_intr, return, &profile_lock) {
443 		_notify_class_profile(dev, NULL);
444 	}
445 	sysfs_notify(acpi_kobj, NULL, "platform_profile");
446 }
447 EXPORT_SYMBOL_GPL(platform_profile_notify);
448 
449 /**
450  * platform_profile_cycle - Cycles profiles available on all registered class devices
451  *
452  * Return: 0 on success, -errno on failure
453  */
454 int platform_profile_cycle(void)
455 {
456 	enum platform_profile_option next = PLATFORM_PROFILE_LAST;
457 	enum platform_profile_option profile = PLATFORM_PROFILE_LAST;
458 	unsigned long choices[BITS_TO_LONGS(PLATFORM_PROFILE_LAST)];
459 	int err;
460 
461 	set_bit(PLATFORM_PROFILE_LAST, choices);
462 	scoped_cond_guard(mutex_intr, return -ERESTARTSYS, &profile_lock) {
463 		err = class_for_each_device(&platform_profile_class, NULL,
464 					    &profile, _aggregate_profiles);
465 		if (err)
466 			return err;
467 
468 		if (profile == PLATFORM_PROFILE_CUSTOM ||
469 		    profile == PLATFORM_PROFILE_LAST)
470 			return -EINVAL;
471 
472 		err = class_for_each_device(&platform_profile_class, NULL,
473 					    choices, _aggregate_choices);
474 		if (err)
475 			return err;
476 
477 		/* never iterate into a custom if all drivers supported it */
478 		clear_bit(PLATFORM_PROFILE_CUSTOM, choices);
479 
480 		next = find_next_bit_wrap(choices,
481 					  PLATFORM_PROFILE_LAST,
482 					  profile + 1);
483 
484 		err = class_for_each_device(&platform_profile_class, NULL, &next,
485 					    _store_and_notify);
486 
487 		if (err)
488 			return err;
489 	}
490 
491 	sysfs_notify(acpi_kobj, NULL, "platform_profile");
492 
493 	return 0;
494 }
495 EXPORT_SYMBOL_GPL(platform_profile_cycle);
496 
497 /**
498  * platform_profile_register - Creates and registers a platform profile class device
499  * @dev: Parent device
500  * @name: Name of the class device
501  * @drvdata: Driver data that will be attached to the class device
502  * @ops: Platform profile's mandatory operations
503  *
504  * Return: pointer to the new class device on success, ERR_PTR on failure
505  */
506 struct device *platform_profile_register(struct device *dev, const char *name,
507 					 void *drvdata,
508 					 const struct platform_profile_ops *ops)
509 {
510 	struct device *ppdev;
511 	int minor;
512 	int err;
513 
514 	/* Sanity check */
515 	if (WARN_ON_ONCE(!dev || !name || !ops || !ops->profile_get ||
516 	    !ops->profile_set || !ops->probe))
517 		return ERR_PTR(-EINVAL);
518 
519 	struct platform_profile_handler *pprof __free(kfree) = kzalloc(
520 		sizeof(*pprof), GFP_KERNEL);
521 	if (!pprof)
522 		return ERR_PTR(-ENOMEM);
523 
524 	err = ops->probe(drvdata, pprof->choices);
525 	if (err) {
526 		dev_err(dev, "platform_profile probe failed\n");
527 		return ERR_PTR(err);
528 	}
529 
530 	if (bitmap_empty(pprof->choices, PLATFORM_PROFILE_LAST)) {
531 		dev_err(dev, "Failed to register platform_profile class device with empty choices\n");
532 		return ERR_PTR(-EINVAL);
533 	}
534 
535 	guard(mutex)(&profile_lock);
536 
537 	/* create class interface for individual handler */
538 	minor = ida_alloc(&platform_profile_ida, GFP_KERNEL);
539 	if (minor < 0)
540 		return ERR_PTR(minor);
541 
542 	pprof->name = name;
543 	pprof->ops = ops;
544 	pprof->minor = minor;
545 	pprof->dev.class = &platform_profile_class;
546 	pprof->dev.parent = dev;
547 	dev_set_drvdata(&pprof->dev, drvdata);
548 	dev_set_name(&pprof->dev, "platform-profile-%d", pprof->minor);
549 	/* device_register() takes ownership of pprof/ppdev */
550 	ppdev = &no_free_ptr(pprof)->dev;
551 	err = device_register(ppdev);
552 	if (err) {
553 		put_device(ppdev);
554 		goto cleanup_ida;
555 	}
556 
557 	sysfs_notify(acpi_kobj, NULL, "platform_profile");
558 
559 	err = sysfs_update_group(acpi_kobj, &platform_profile_group);
560 	if (err)
561 		goto cleanup_cur;
562 
563 	return ppdev;
564 
565 cleanup_cur:
566 	device_unregister(ppdev);
567 
568 cleanup_ida:
569 	ida_free(&platform_profile_ida, minor);
570 
571 	return ERR_PTR(err);
572 }
573 EXPORT_SYMBOL_GPL(platform_profile_register);
574 
575 /**
576  * platform_profile_remove - Unregisters a platform profile class device
577  * @dev: Class device
578  *
579  * Return: 0
580  */
581 int platform_profile_remove(struct device *dev)
582 {
583 	struct platform_profile_handler *pprof = to_pprof_handler(dev);
584 	int id;
585 	guard(mutex)(&profile_lock);
586 
587 	id = pprof->minor;
588 	device_unregister(&pprof->dev);
589 	ida_free(&platform_profile_ida, id);
590 
591 	sysfs_notify(acpi_kobj, NULL, "platform_profile");
592 
593 	sysfs_update_group(acpi_kobj, &platform_profile_group);
594 
595 	return 0;
596 }
597 EXPORT_SYMBOL_GPL(platform_profile_remove);
598 
599 static void devm_platform_profile_release(struct device *dev, void *res)
600 {
601 	struct device **ppdev = res;
602 
603 	platform_profile_remove(*ppdev);
604 }
605 
606 /**
607  * devm_platform_profile_register - Device managed version of platform_profile_register
608  * @dev: Parent device
609  * @name: Name of the class device
610  * @drvdata: Driver data that will be attached to the class device
611  * @ops: Platform profile's mandatory operations
612  *
613  * Return: pointer to the new class device on success, ERR_PTR on failure
614  */
615 struct device *devm_platform_profile_register(struct device *dev, const char *name,
616 					      void *drvdata,
617 					      const struct platform_profile_ops *ops)
618 {
619 	struct device *ppdev;
620 	struct device **dr;
621 
622 	dr = devres_alloc(devm_platform_profile_release, sizeof(*dr), GFP_KERNEL);
623 	if (!dr)
624 		return ERR_PTR(-ENOMEM);
625 
626 	ppdev = platform_profile_register(dev, name, drvdata, ops);
627 	if (IS_ERR(ppdev)) {
628 		devres_free(dr);
629 		return ppdev;
630 	}
631 
632 	*dr = ppdev;
633 	devres_add(dev, dr);
634 
635 	return ppdev;
636 }
637 EXPORT_SYMBOL_GPL(devm_platform_profile_register);
638 
639 static int __init platform_profile_init(void)
640 {
641 	int err;
642 
643 	err = class_register(&platform_profile_class);
644 	if (err)
645 		return err;
646 
647 	err = sysfs_create_group(acpi_kobj, &platform_profile_group);
648 	if (err)
649 		class_unregister(&platform_profile_class);
650 
651 	return err;
652 }
653 
654 static void __exit platform_profile_exit(void)
655 {
656 	sysfs_remove_group(acpi_kobj, &platform_profile_group);
657 	class_unregister(&platform_profile_class);
658 }
659 module_init(platform_profile_init);
660 module_exit(platform_profile_exit);
661 
662 MODULE_AUTHOR("Mark Pearson <markpearson@lenovo.com>");
663 MODULE_DESCRIPTION("ACPI platform profile sysfs interface");
664 MODULE_LICENSE("GPL");
665