xref: /linux/drivers/acpi/platform_profile.c (revision 86f5536004a61a0c797c14a248fc976f03f55cd5)
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 	if (!class_find_device(&platform_profile_class, NULL, NULL, profile_class_registered))
421 		return 0;
422 	return attr->mode;
423 }
424 
425 static const struct attribute_group platform_profile_group = {
426 	.attrs = platform_profile_attrs,
427 	.is_visible = profile_class_is_visible,
428 };
429 
430 /**
431  * platform_profile_notify - Notify class device and legacy sysfs interface
432  * @dev: The class device
433  */
434 void platform_profile_notify(struct device *dev)
435 {
436 	scoped_cond_guard(mutex_intr, return, &profile_lock) {
437 		_notify_class_profile(dev, NULL);
438 	}
439 	sysfs_notify(acpi_kobj, NULL, "platform_profile");
440 }
441 EXPORT_SYMBOL_GPL(platform_profile_notify);
442 
443 /**
444  * platform_profile_cycle - Cycles profiles available on all registered class devices
445  *
446  * Return: 0 on success, -errno on failure
447  */
448 int platform_profile_cycle(void)
449 {
450 	enum platform_profile_option next = PLATFORM_PROFILE_LAST;
451 	enum platform_profile_option profile = PLATFORM_PROFILE_LAST;
452 	unsigned long choices[BITS_TO_LONGS(PLATFORM_PROFILE_LAST)];
453 	int err;
454 
455 	set_bit(PLATFORM_PROFILE_LAST, choices);
456 	scoped_cond_guard(mutex_intr, return -ERESTARTSYS, &profile_lock) {
457 		err = class_for_each_device(&platform_profile_class, NULL,
458 					    &profile, _aggregate_profiles);
459 		if (err)
460 			return err;
461 
462 		if (profile == PLATFORM_PROFILE_CUSTOM ||
463 		    profile == PLATFORM_PROFILE_LAST)
464 			return -EINVAL;
465 
466 		err = class_for_each_device(&platform_profile_class, NULL,
467 					    choices, _aggregate_choices);
468 		if (err)
469 			return err;
470 
471 		/* never iterate into a custom if all drivers supported it */
472 		clear_bit(PLATFORM_PROFILE_CUSTOM, choices);
473 
474 		next = find_next_bit_wrap(choices,
475 					  PLATFORM_PROFILE_LAST,
476 					  profile + 1);
477 
478 		err = class_for_each_device(&platform_profile_class, NULL, &next,
479 					    _store_and_notify);
480 
481 		if (err)
482 			return err;
483 	}
484 
485 	sysfs_notify(acpi_kobj, NULL, "platform_profile");
486 
487 	return 0;
488 }
489 EXPORT_SYMBOL_GPL(platform_profile_cycle);
490 
491 /**
492  * platform_profile_register - Creates and registers a platform profile class device
493  * @dev: Parent device
494  * @name: Name of the class device
495  * @drvdata: Driver data that will be attached to the class device
496  * @ops: Platform profile's mandatory operations
497  *
498  * Return: pointer to the new class device on success, ERR_PTR on failure
499  */
500 struct device *platform_profile_register(struct device *dev, const char *name,
501 					 void *drvdata,
502 					 const struct platform_profile_ops *ops)
503 {
504 	struct device *ppdev;
505 	int minor;
506 	int err;
507 
508 	/* Sanity check */
509 	if (WARN_ON_ONCE(!dev || !name || !ops || !ops->profile_get ||
510 	    !ops->profile_set || !ops->probe))
511 		return ERR_PTR(-EINVAL);
512 
513 	struct platform_profile_handler *pprof __free(kfree) = kzalloc(
514 		sizeof(*pprof), GFP_KERNEL);
515 	if (!pprof)
516 		return ERR_PTR(-ENOMEM);
517 
518 	err = ops->probe(drvdata, pprof->choices);
519 	if (err) {
520 		dev_err(dev, "platform_profile probe failed\n");
521 		return ERR_PTR(err);
522 	}
523 
524 	if (bitmap_empty(pprof->choices, PLATFORM_PROFILE_LAST)) {
525 		dev_err(dev, "Failed to register platform_profile class device with empty choices\n");
526 		return ERR_PTR(-EINVAL);
527 	}
528 
529 	guard(mutex)(&profile_lock);
530 
531 	/* create class interface for individual handler */
532 	minor = ida_alloc(&platform_profile_ida, GFP_KERNEL);
533 	if (minor < 0)
534 		return ERR_PTR(minor);
535 
536 	pprof->name = name;
537 	pprof->ops = ops;
538 	pprof->minor = minor;
539 	pprof->dev.class = &platform_profile_class;
540 	pprof->dev.parent = dev;
541 	dev_set_drvdata(&pprof->dev, drvdata);
542 	dev_set_name(&pprof->dev, "platform-profile-%d", pprof->minor);
543 	/* device_register() takes ownership of pprof/ppdev */
544 	ppdev = &no_free_ptr(pprof)->dev;
545 	err = device_register(ppdev);
546 	if (err) {
547 		put_device(ppdev);
548 		goto cleanup_ida;
549 	}
550 
551 	sysfs_notify(acpi_kobj, NULL, "platform_profile");
552 
553 	err = sysfs_update_group(acpi_kobj, &platform_profile_group);
554 	if (err)
555 		goto cleanup_cur;
556 
557 	return ppdev;
558 
559 cleanup_cur:
560 	device_unregister(ppdev);
561 
562 cleanup_ida:
563 	ida_free(&platform_profile_ida, minor);
564 
565 	return ERR_PTR(err);
566 }
567 EXPORT_SYMBOL_GPL(platform_profile_register);
568 
569 /**
570  * platform_profile_remove - Unregisters a platform profile class device
571  * @dev: Class device
572  *
573  * Return: 0
574  */
575 int platform_profile_remove(struct device *dev)
576 {
577 	struct platform_profile_handler *pprof = to_pprof_handler(dev);
578 	int id;
579 	guard(mutex)(&profile_lock);
580 
581 	id = pprof->minor;
582 	device_unregister(&pprof->dev);
583 	ida_free(&platform_profile_ida, id);
584 
585 	sysfs_notify(acpi_kobj, NULL, "platform_profile");
586 
587 	sysfs_update_group(acpi_kobj, &platform_profile_group);
588 
589 	return 0;
590 }
591 EXPORT_SYMBOL_GPL(platform_profile_remove);
592 
593 static void devm_platform_profile_release(struct device *dev, void *res)
594 {
595 	struct device **ppdev = res;
596 
597 	platform_profile_remove(*ppdev);
598 }
599 
600 /**
601  * devm_platform_profile_register - Device managed version of platform_profile_register
602  * @dev: Parent device
603  * @name: Name of the class device
604  * @drvdata: Driver data that will be attached to the class device
605  * @ops: Platform profile's mandatory operations
606  *
607  * Return: pointer to the new class device on success, ERR_PTR on failure
608  */
609 struct device *devm_platform_profile_register(struct device *dev, const char *name,
610 					      void *drvdata,
611 					      const struct platform_profile_ops *ops)
612 {
613 	struct device *ppdev;
614 	struct device **dr;
615 
616 	dr = devres_alloc(devm_platform_profile_release, sizeof(*dr), GFP_KERNEL);
617 	if (!dr)
618 		return ERR_PTR(-ENOMEM);
619 
620 	ppdev = platform_profile_register(dev, name, drvdata, ops);
621 	if (IS_ERR(ppdev)) {
622 		devres_free(dr);
623 		return ppdev;
624 	}
625 
626 	*dr = ppdev;
627 	devres_add(dev, dr);
628 
629 	return ppdev;
630 }
631 EXPORT_SYMBOL_GPL(devm_platform_profile_register);
632 
633 static int __init platform_profile_init(void)
634 {
635 	int err;
636 
637 	err = class_register(&platform_profile_class);
638 	if (err)
639 		return err;
640 
641 	err = sysfs_create_group(acpi_kobj, &platform_profile_group);
642 	if (err)
643 		class_unregister(&platform_profile_class);
644 
645 	return err;
646 }
647 
648 static void __exit platform_profile_exit(void)
649 {
650 	sysfs_remove_group(acpi_kobj, &platform_profile_group);
651 	class_unregister(&platform_profile_class);
652 }
653 module_init(platform_profile_init);
654 module_exit(platform_profile_exit);
655 
656 MODULE_AUTHOR("Mark Pearson <markpearson@lenovo.com>");
657 MODULE_DESCRIPTION("ACPI platform profile sysfs interface");
658 MODULE_LICENSE("GPL");
659