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