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