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