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 249 * 250 * Return: 0 on success, -errno on failure 251 */ 252 static int _aggregate_choices(struct device *dev, void *arg) 253 { 254 unsigned long tmp[BITS_TO_LONGS(PLATFORM_PROFILE_LAST)]; 255 struct aggregate_choices_data *data = arg; 256 struct platform_profile_handler *handler; 257 258 lockdep_assert_held(&profile_lock); 259 handler = to_pprof_handler(dev); 260 bitmap_or(tmp, handler->choices, handler->hidden_choices, PLATFORM_PROFILE_LAST); 261 if (test_bit(PLATFORM_PROFILE_LAST, data->aggregate)) 262 bitmap_copy(data->aggregate, tmp, PLATFORM_PROFILE_LAST); 263 else 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 * @dev: The device 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 device *dev, 299 struct device_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 set_bit(PLATFORM_PROFILE_LAST, data.aggregate); 309 scoped_cond_guard(mutex_intr, return -ERESTARTSYS, &profile_lock) { 310 err = class_for_each_device(&platform_profile_class, NULL, 311 &data, _aggregate_choices); 312 if (err) 313 return err; 314 if (data.count == 1) { 315 err = class_for_each_device(&platform_profile_class, NULL, 316 &data, _remove_hidden_choices); 317 if (err) 318 return err; 319 } 320 } 321 322 /* no profile handler registered any more */ 323 if (bitmap_empty(data.aggregate, PLATFORM_PROFILE_LAST)) 324 return -EINVAL; 325 326 return _commmon_choices_show(data.aggregate, buf); 327 } 328 329 /** 330 * _aggregate_profiles - Aggregate the profiles for legacy sysfs interface 331 * @dev: The device 332 * @data: The profile to return 333 * 334 * Return: 0 on success, -errno on failure 335 */ 336 static int _aggregate_profiles(struct device *dev, void *data) 337 { 338 enum platform_profile_option *profile = data; 339 enum platform_profile_option val; 340 int err; 341 342 err = get_class_profile(dev, &val); 343 if (err) 344 return err; 345 346 if (*profile != PLATFORM_PROFILE_LAST && *profile != val) 347 *profile = PLATFORM_PROFILE_CUSTOM; 348 else 349 *profile = val; 350 351 return 0; 352 } 353 354 /** 355 * _store_and_notify - Store and notify a class from legacy sysfs interface 356 * @dev: The device 357 * @data: The profile to return 358 * 359 * Return: 0 on success, -errno on failure 360 */ 361 static int _store_and_notify(struct device *dev, void *data) 362 { 363 enum platform_profile_option *profile = data; 364 int err; 365 366 err = _store_class_profile(dev, profile); 367 if (err) 368 return err; 369 return _notify_class_profile(dev, NULL); 370 } 371 372 /** 373 * platform_profile_show - Show the current profile for legacy sysfs interface 374 * @dev: The device 375 * @attr: The attribute 376 * @buf: The buffer to write to 377 * 378 * Return: The number of bytes written 379 */ 380 static ssize_t platform_profile_show(struct device *dev, 381 struct device_attribute *attr, 382 char *buf) 383 { 384 enum platform_profile_option profile = PLATFORM_PROFILE_LAST; 385 int err; 386 387 scoped_cond_guard(mutex_intr, return -ERESTARTSYS, &profile_lock) { 388 err = class_for_each_device(&platform_profile_class, NULL, 389 &profile, _aggregate_profiles); 390 if (err) 391 return err; 392 } 393 394 /* no profile handler registered any more */ 395 if (profile == PLATFORM_PROFILE_LAST) 396 return -EINVAL; 397 398 return sysfs_emit(buf, "%s\n", profile_names[profile]); 399 } 400 401 /** 402 * platform_profile_store - Set the profile for legacy sysfs interface 403 * @dev: The device 404 * @attr: The attribute 405 * @buf: The buffer to read from 406 * @count: The number of bytes to read 407 * 408 * Return: The number of bytes read 409 */ 410 static ssize_t platform_profile_store(struct device *dev, 411 struct device_attribute *attr, 412 const char *buf, size_t count) 413 { 414 struct aggregate_choices_data data = { 415 .aggregate = { [0 ... BITS_TO_LONGS(PLATFORM_PROFILE_LAST) - 1] = ~0UL }, 416 .count = 0, 417 }; 418 int ret; 419 int i; 420 421 /* Scan for a matching profile */ 422 i = sysfs_match_string(profile_names, buf); 423 if (i < 0 || i == PLATFORM_PROFILE_CUSTOM) 424 return -EINVAL; 425 set_bit(PLATFORM_PROFILE_LAST, data.aggregate); 426 scoped_cond_guard(mutex_intr, return -ERESTARTSYS, &profile_lock) { 427 ret = class_for_each_device(&platform_profile_class, NULL, 428 &data, _aggregate_choices); 429 if (ret) 430 return ret; 431 if (!test_bit(i, data.aggregate)) 432 return -EOPNOTSUPP; 433 434 ret = class_for_each_device(&platform_profile_class, NULL, &i, 435 _store_and_notify); 436 if (ret) 437 return ret; 438 } 439 440 sysfs_notify(acpi_kobj, NULL, "platform_profile"); 441 442 return count; 443 } 444 445 static DEVICE_ATTR_RO(platform_profile_choices); 446 static DEVICE_ATTR_RW(platform_profile); 447 448 static struct attribute *platform_profile_attrs[] = { 449 &dev_attr_platform_profile_choices.attr, 450 &dev_attr_platform_profile.attr, 451 NULL 452 }; 453 454 static int profile_class_registered(struct device *dev, const void *data) 455 { 456 return 1; 457 } 458 459 static umode_t profile_class_is_visible(struct kobject *kobj, struct attribute *attr, int idx) 460 { 461 struct device *dev; 462 463 dev = class_find_device(&platform_profile_class, NULL, NULL, profile_class_registered); 464 if (!dev) 465 return 0; 466 467 put_device(dev); 468 469 return attr->mode; 470 } 471 472 static const struct attribute_group platform_profile_group = { 473 .attrs = platform_profile_attrs, 474 .is_visible = profile_class_is_visible, 475 }; 476 477 /** 478 * platform_profile_notify - Notify class device and legacy sysfs interface 479 * @dev: The class device 480 */ 481 void platform_profile_notify(struct device *dev) 482 { 483 scoped_cond_guard(mutex_intr, return, &profile_lock) { 484 _notify_class_profile(dev, NULL); 485 } 486 sysfs_notify(acpi_kobj, NULL, "platform_profile"); 487 } 488 EXPORT_SYMBOL_GPL(platform_profile_notify); 489 490 /** 491 * platform_profile_cycle - Cycles profiles available on all registered class devices 492 * 493 * Return: 0 on success, -errno on failure 494 */ 495 int platform_profile_cycle(void) 496 { 497 struct aggregate_choices_data data = { 498 .aggregate = { [0 ... BITS_TO_LONGS(PLATFORM_PROFILE_LAST) - 1] = ~0UL }, 499 .count = 0, 500 }; 501 enum platform_profile_option next = PLATFORM_PROFILE_LAST; 502 enum platform_profile_option profile = PLATFORM_PROFILE_LAST; 503 int err; 504 505 set_bit(PLATFORM_PROFILE_LAST, data.aggregate); 506 scoped_cond_guard(mutex_intr, return -ERESTARTSYS, &profile_lock) { 507 err = class_for_each_device(&platform_profile_class, NULL, 508 &profile, _aggregate_profiles); 509 if (err) 510 return err; 511 512 if (profile == PLATFORM_PROFILE_CUSTOM || 513 profile == PLATFORM_PROFILE_LAST) 514 return -EINVAL; 515 516 err = class_for_each_device(&platform_profile_class, NULL, 517 &data, _aggregate_choices); 518 if (err) 519 return err; 520 521 /* never iterate into a custom if all drivers supported it */ 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 * Return: 0 632 */ 633 int platform_profile_remove(struct device *dev) 634 { 635 struct platform_profile_handler *pprof = to_pprof_handler(dev); 636 int id; 637 guard(mutex)(&profile_lock); 638 639 id = pprof->minor; 640 device_unregister(&pprof->dev); 641 ida_free(&platform_profile_ida, id); 642 643 sysfs_notify(acpi_kobj, NULL, "platform_profile"); 644 645 sysfs_update_group(acpi_kobj, &platform_profile_group); 646 647 return 0; 648 } 649 EXPORT_SYMBOL_GPL(platform_profile_remove); 650 651 static void devm_platform_profile_release(struct device *dev, void *res) 652 { 653 struct device **ppdev = res; 654 655 platform_profile_remove(*ppdev); 656 } 657 658 /** 659 * devm_platform_profile_register - Device managed version of platform_profile_register 660 * @dev: Parent device 661 * @name: Name of the class device 662 * @drvdata: Driver data that will be attached to the class device 663 * @ops: Platform profile's mandatory operations 664 * 665 * Return: pointer to the new class device on success, ERR_PTR on failure 666 */ 667 struct device *devm_platform_profile_register(struct device *dev, const char *name, 668 void *drvdata, 669 const struct platform_profile_ops *ops) 670 { 671 struct device *ppdev; 672 struct device **dr; 673 674 dr = devres_alloc(devm_platform_profile_release, sizeof(*dr), GFP_KERNEL); 675 if (!dr) 676 return ERR_PTR(-ENOMEM); 677 678 ppdev = platform_profile_register(dev, name, drvdata, ops); 679 if (IS_ERR(ppdev)) { 680 devres_free(dr); 681 return ppdev; 682 } 683 684 *dr = ppdev; 685 devres_add(dev, dr); 686 687 return ppdev; 688 } 689 EXPORT_SYMBOL_GPL(devm_platform_profile_register); 690 691 static int __init platform_profile_init(void) 692 { 693 int err; 694 695 err = class_register(&platform_profile_class); 696 if (err) 697 return err; 698 699 err = sysfs_create_group(acpi_kobj, &platform_profile_group); 700 if (err) 701 class_unregister(&platform_profile_class); 702 703 return err; 704 } 705 706 static void __exit platform_profile_exit(void) 707 { 708 sysfs_remove_group(acpi_kobj, &platform_profile_group); 709 class_unregister(&platform_profile_class); 710 } 711 module_init(platform_profile_init); 712 module_exit(platform_profile_exit); 713 714 MODULE_AUTHOR("Mark Pearson <markpearson@lenovo.com>"); 715 MODULE_DESCRIPTION("ACPI platform profile sysfs interface"); 716 MODULE_LICENSE("GPL"); 717