at master 22 kB view raw
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * thermal.c - sysfs interface of thermal devices 4 * 5 * Copyright (C) 2016 Eduardo Valentin <edubezval@gmail.com> 6 * 7 * Highly based on original thermal_core.c 8 * Copyright (C) 2008 Intel Corp 9 * Copyright (C) 2008 Zhang Rui <rui.zhang@intel.com> 10 * Copyright (C) 2008 Sujith Thomas <sujith.thomas@intel.com> 11 */ 12 13#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 14 15#include <linux/container_of.h> 16#include <linux/sysfs.h> 17#include <linux/device.h> 18#include <linux/err.h> 19#include <linux/slab.h> 20#include <linux/string.h> 21#include <linux/jiffies.h> 22 23#include "thermal_core.h" 24 25/* sys I/F for thermal zone */ 26 27static ssize_t 28type_show(struct device *dev, struct device_attribute *attr, char *buf) 29{ 30 struct thermal_zone_device *tz = to_thermal_zone(dev); 31 32 return sprintf(buf, "%s\n", tz->type); 33} 34 35static ssize_t 36temp_show(struct device *dev, struct device_attribute *attr, char *buf) 37{ 38 struct thermal_zone_device *tz = to_thermal_zone(dev); 39 int temperature, ret; 40 41 ret = thermal_zone_get_temp(tz, &temperature); 42 43 if (!ret) 44 return sprintf(buf, "%d\n", temperature); 45 46 if (ret == -EAGAIN) 47 return -ENODATA; 48 49 return ret; 50} 51 52static ssize_t 53mode_show(struct device *dev, struct device_attribute *attr, char *buf) 54{ 55 struct thermal_zone_device *tz = to_thermal_zone(dev); 56 57 guard(thermal_zone)(tz); 58 59 if (tz->mode == THERMAL_DEVICE_ENABLED) 60 return sprintf(buf, "enabled\n"); 61 62 return sprintf(buf, "disabled\n"); 63} 64 65static ssize_t 66mode_store(struct device *dev, struct device_attribute *attr, 67 const char *buf, size_t count) 68{ 69 struct thermal_zone_device *tz = to_thermal_zone(dev); 70 int result; 71 72 if (!strncmp(buf, "enabled", sizeof("enabled") - 1)) 73 result = thermal_zone_device_enable(tz); 74 else if (!strncmp(buf, "disabled", sizeof("disabled") - 1)) 75 result = thermal_zone_device_disable(tz); 76 else 77 result = -EINVAL; 78 79 if (result) 80 return result; 81 82 return count; 83} 84 85#define thermal_trip_of_attr(_ptr_, _attr_) \ 86 ({ \ 87 struct thermal_trip_desc *td; \ 88 \ 89 td = container_of(_ptr_, struct thermal_trip_desc, \ 90 trip_attrs._attr_.attr); \ 91 &td->trip; \ 92 }) 93 94static ssize_t 95trip_point_type_show(struct device *dev, struct device_attribute *attr, 96 char *buf) 97{ 98 struct thermal_trip *trip = thermal_trip_of_attr(attr, type); 99 100 return sprintf(buf, "%s\n", thermal_trip_type_name(trip->type)); 101} 102 103static ssize_t 104trip_point_temp_store(struct device *dev, struct device_attribute *attr, 105 const char *buf, size_t count) 106{ 107 struct thermal_trip *trip = thermal_trip_of_attr(attr, temp); 108 struct thermal_zone_device *tz = to_thermal_zone(dev); 109 int temp; 110 111 if (kstrtoint(buf, 10, &temp)) 112 return -EINVAL; 113 114 guard(thermal_zone)(tz); 115 116 if (temp == trip->temperature) 117 return count; 118 119 /* Arrange the condition to avoid integer overflows. */ 120 if (temp != THERMAL_TEMP_INVALID && 121 temp <= trip->hysteresis + THERMAL_TEMP_INVALID) 122 return -EINVAL; 123 124 if (tz->ops.set_trip_temp) { 125 int ret; 126 127 ret = tz->ops.set_trip_temp(tz, trip, temp); 128 if (ret) 129 return ret; 130 } 131 132 thermal_zone_set_trip_temp(tz, trip, temp); 133 134 __thermal_zone_device_update(tz, THERMAL_TRIP_CHANGED); 135 136 return count; 137} 138 139static ssize_t 140trip_point_temp_show(struct device *dev, struct device_attribute *attr, 141 char *buf) 142{ 143 struct thermal_trip *trip = thermal_trip_of_attr(attr, temp); 144 145 return sprintf(buf, "%d\n", READ_ONCE(trip->temperature)); 146} 147 148static ssize_t 149trip_point_hyst_store(struct device *dev, struct device_attribute *attr, 150 const char *buf, size_t count) 151{ 152 struct thermal_trip *trip = thermal_trip_of_attr(attr, hyst); 153 struct thermal_zone_device *tz = to_thermal_zone(dev); 154 int hyst; 155 156 if (kstrtoint(buf, 10, &hyst) || hyst < 0) 157 return -EINVAL; 158 159 guard(thermal_zone)(tz); 160 161 if (hyst == trip->hysteresis) 162 return count; 163 164 /* 165 * Allow the hysteresis to be updated when the temperature is invalid 166 * to allow user space to avoid having to adjust hysteresis after a 167 * valid temperature has been set, but in that case just change the 168 * value and do nothing else. 169 */ 170 if (trip->temperature == THERMAL_TEMP_INVALID) { 171 WRITE_ONCE(trip->hysteresis, hyst); 172 return count; 173 } 174 175 if (trip->temperature - hyst <= THERMAL_TEMP_INVALID) 176 return -EINVAL; 177 178 thermal_zone_set_trip_hyst(tz, trip, hyst); 179 180 __thermal_zone_device_update(tz, THERMAL_TRIP_CHANGED); 181 182 return count; 183} 184 185static ssize_t 186trip_point_hyst_show(struct device *dev, struct device_attribute *attr, 187 char *buf) 188{ 189 struct thermal_trip *trip = thermal_trip_of_attr(attr, hyst); 190 191 return sprintf(buf, "%d\n", READ_ONCE(trip->hysteresis)); 192} 193 194static ssize_t 195policy_store(struct device *dev, struct device_attribute *attr, 196 const char *buf, size_t count) 197{ 198 struct thermal_zone_device *tz = to_thermal_zone(dev); 199 char name[THERMAL_NAME_LENGTH]; 200 int ret; 201 202 snprintf(name, sizeof(name), "%s", buf); 203 204 ret = thermal_zone_device_set_policy(tz, name); 205 if (!ret) 206 ret = count; 207 208 return ret; 209} 210 211static ssize_t 212policy_show(struct device *dev, struct device_attribute *devattr, char *buf) 213{ 214 struct thermal_zone_device *tz = to_thermal_zone(dev); 215 216 return sprintf(buf, "%s\n", tz->governor->name); 217} 218 219static ssize_t 220available_policies_show(struct device *dev, struct device_attribute *devattr, 221 char *buf) 222{ 223 return thermal_build_list_of_policies(buf); 224} 225 226#if (IS_ENABLED(CONFIG_THERMAL_EMULATION)) 227static ssize_t 228emul_temp_store(struct device *dev, struct device_attribute *attr, 229 const char *buf, size_t count) 230{ 231 struct thermal_zone_device *tz = to_thermal_zone(dev); 232 int temperature; 233 234 if (kstrtoint(buf, 10, &temperature)) 235 return -EINVAL; 236 237 guard(thermal_zone)(tz); 238 239 if (tz->ops.set_emul_temp) { 240 int ret; 241 242 ret = tz->ops.set_emul_temp(tz, temperature); 243 if (ret) 244 return ret; 245 } else { 246 tz->emul_temperature = temperature; 247 } 248 249 __thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED); 250 251 return count; 252} 253static DEVICE_ATTR_WO(emul_temp); 254#endif 255 256static ssize_t 257sustainable_power_show(struct device *dev, struct device_attribute *devattr, 258 char *buf) 259{ 260 struct thermal_zone_device *tz = to_thermal_zone(dev); 261 262 if (tz->tzp) 263 return sprintf(buf, "%u\n", tz->tzp->sustainable_power); 264 else 265 return -EIO; 266} 267 268static ssize_t 269sustainable_power_store(struct device *dev, struct device_attribute *devattr, 270 const char *buf, size_t count) 271{ 272 struct thermal_zone_device *tz = to_thermal_zone(dev); 273 u32 sustainable_power; 274 275 if (!tz->tzp) 276 return -EIO; 277 278 if (kstrtou32(buf, 10, &sustainable_power)) 279 return -EINVAL; 280 281 tz->tzp->sustainable_power = sustainable_power; 282 283 return count; 284} 285 286#define create_s32_tzp_attr(name) \ 287 static ssize_t \ 288 name##_show(struct device *dev, struct device_attribute *devattr, \ 289 char *buf) \ 290 { \ 291 struct thermal_zone_device *tz = to_thermal_zone(dev); \ 292 \ 293 if (tz->tzp) \ 294 return sprintf(buf, "%d\n", tz->tzp->name); \ 295 else \ 296 return -EIO; \ 297 } \ 298 \ 299 static ssize_t \ 300 name##_store(struct device *dev, struct device_attribute *devattr, \ 301 const char *buf, size_t count) \ 302 { \ 303 struct thermal_zone_device *tz = to_thermal_zone(dev); \ 304 s32 value; \ 305 \ 306 if (!tz->tzp) \ 307 return -EIO; \ 308 \ 309 if (kstrtos32(buf, 10, &value)) \ 310 return -EINVAL; \ 311 \ 312 tz->tzp->name = value; \ 313 \ 314 return count; \ 315 } \ 316 static DEVICE_ATTR_RW(name) 317 318create_s32_tzp_attr(k_po); 319create_s32_tzp_attr(k_pu); 320create_s32_tzp_attr(k_i); 321create_s32_tzp_attr(k_d); 322create_s32_tzp_attr(integral_cutoff); 323create_s32_tzp_attr(slope); 324create_s32_tzp_attr(offset); 325#undef create_s32_tzp_attr 326 327/* 328 * These are thermal zone device attributes that will always be present. 329 * All the attributes created for tzp (create_s32_tzp_attr) also are always 330 * present on the sysfs interface. 331 */ 332static DEVICE_ATTR_RO(type); 333static DEVICE_ATTR_RO(temp); 334static DEVICE_ATTR_RW(policy); 335static DEVICE_ATTR_RO(available_policies); 336static DEVICE_ATTR_RW(sustainable_power); 337 338/* These thermal zone device attributes are created based on conditions */ 339static DEVICE_ATTR_RW(mode); 340 341/* These attributes are unconditionally added to a thermal zone */ 342static struct attribute *thermal_zone_dev_attrs[] = { 343 &dev_attr_type.attr, 344 &dev_attr_temp.attr, 345#if (IS_ENABLED(CONFIG_THERMAL_EMULATION)) 346 &dev_attr_emul_temp.attr, 347#endif 348 &dev_attr_policy.attr, 349 &dev_attr_available_policies.attr, 350 &dev_attr_sustainable_power.attr, 351 &dev_attr_k_po.attr, 352 &dev_attr_k_pu.attr, 353 &dev_attr_k_i.attr, 354 &dev_attr_k_d.attr, 355 &dev_attr_integral_cutoff.attr, 356 &dev_attr_slope.attr, 357 &dev_attr_offset.attr, 358 NULL, 359}; 360 361static const struct attribute_group thermal_zone_attribute_group = { 362 .attrs = thermal_zone_dev_attrs, 363}; 364 365static struct attribute *thermal_zone_mode_attrs[] = { 366 &dev_attr_mode.attr, 367 NULL, 368}; 369 370static const struct attribute_group thermal_zone_mode_attribute_group = { 371 .attrs = thermal_zone_mode_attrs, 372}; 373 374static const struct attribute_group *thermal_zone_attribute_groups[] = { 375 &thermal_zone_attribute_group, 376 &thermal_zone_mode_attribute_group, 377 /* This is not NULL terminated as we create the group dynamically */ 378}; 379 380/** 381 * create_trip_attrs() - create attributes for trip points 382 * @tz: the thermal zone device 383 * 384 * helper function to instantiate sysfs entries for every trip 385 * point and its properties of a struct thermal_zone_device. 386 * 387 * Return: 0 on success, the proper error value otherwise. 388 */ 389static int create_trip_attrs(struct thermal_zone_device *tz) 390{ 391 struct thermal_trip_desc *td; 392 struct attribute **attrs; 393 int i; 394 395 attrs = kcalloc(tz->num_trips * 3 + 1, sizeof(*attrs), GFP_KERNEL); 396 if (!attrs) 397 return -ENOMEM; 398 399 i = 0; 400 for_each_trip_desc(tz, td) { 401 struct thermal_trip_attrs *trip_attrs = &td->trip_attrs; 402 403 /* create trip type attribute */ 404 snprintf(trip_attrs->type.name, THERMAL_NAME_LENGTH, 405 "trip_point_%d_type", i); 406 407 sysfs_attr_init(&trip_attrs->type.attr.attr); 408 trip_attrs->type.attr.attr.name = trip_attrs->type.name; 409 trip_attrs->type.attr.attr.mode = S_IRUGO; 410 trip_attrs->type.attr.show = trip_point_type_show; 411 attrs[i] = &trip_attrs->type.attr.attr; 412 413 /* create trip temp attribute */ 414 snprintf(trip_attrs->temp.name, THERMAL_NAME_LENGTH, 415 "trip_point_%d_temp", i); 416 417 sysfs_attr_init(&trip_attrs->temp.attr.attr); 418 trip_attrs->temp.attr.attr.name = trip_attrs->temp.name; 419 trip_attrs->temp.attr.attr.mode = S_IRUGO; 420 trip_attrs->temp.attr.show = trip_point_temp_show; 421 if (td->trip.flags & THERMAL_TRIP_FLAG_RW_TEMP) { 422 trip_attrs->temp.attr.attr.mode |= S_IWUSR; 423 trip_attrs->temp.attr.store = trip_point_temp_store; 424 } 425 attrs[i + tz->num_trips] = &trip_attrs->temp.attr.attr; 426 427 snprintf(trip_attrs->hyst.name, THERMAL_NAME_LENGTH, 428 "trip_point_%d_hyst", i); 429 430 sysfs_attr_init(&trip_attrs->hyst.attr.attr); 431 trip_attrs->hyst.attr.attr.name = trip_attrs->hyst.name; 432 trip_attrs->hyst.attr.attr.mode = S_IRUGO; 433 trip_attrs->hyst.attr.show = trip_point_hyst_show; 434 if (td->trip.flags & THERMAL_TRIP_FLAG_RW_HYST) { 435 trip_attrs->hyst.attr.attr.mode |= S_IWUSR; 436 trip_attrs->hyst.attr.store = trip_point_hyst_store; 437 } 438 attrs[i + 2 * tz->num_trips] = &trip_attrs->hyst.attr.attr; 439 i++; 440 } 441 attrs[tz->num_trips * 3] = NULL; 442 443 tz->trips_attribute_group.attrs = attrs; 444 445 return 0; 446} 447 448/** 449 * destroy_trip_attrs() - destroy attributes for trip points 450 * @tz: the thermal zone device 451 * 452 * helper function to free resources allocated by create_trip_attrs() 453 */ 454static void destroy_trip_attrs(struct thermal_zone_device *tz) 455{ 456 if (tz) 457 kfree(tz->trips_attribute_group.attrs); 458} 459 460int thermal_zone_create_device_groups(struct thermal_zone_device *tz) 461{ 462 const struct attribute_group **groups; 463 int i, size, result; 464 465 /* we need one extra for trips and the NULL to terminate the array */ 466 size = ARRAY_SIZE(thermal_zone_attribute_groups) + 2; 467 /* This also takes care of API requirement to be NULL terminated */ 468 groups = kcalloc(size, sizeof(*groups), GFP_KERNEL); 469 if (!groups) 470 return -ENOMEM; 471 472 for (i = 0; i < size - 2; i++) 473 groups[i] = thermal_zone_attribute_groups[i]; 474 475 if (tz->num_trips) { 476 result = create_trip_attrs(tz); 477 if (result) { 478 kfree(groups); 479 480 return result; 481 } 482 483 groups[size - 2] = &tz->trips_attribute_group; 484 } 485 486 tz->device.groups = groups; 487 488 return 0; 489} 490 491void thermal_zone_destroy_device_groups(struct thermal_zone_device *tz) 492{ 493 if (!tz) 494 return; 495 496 if (tz->num_trips) 497 destroy_trip_attrs(tz); 498 499 kfree(tz->device.groups); 500} 501 502/* sys I/F for cooling device */ 503static ssize_t 504cdev_type_show(struct device *dev, struct device_attribute *attr, char *buf) 505{ 506 struct thermal_cooling_device *cdev = to_cooling_device(dev); 507 508 return sprintf(buf, "%s\n", cdev->type); 509} 510 511static ssize_t max_state_show(struct device *dev, struct device_attribute *attr, 512 char *buf) 513{ 514 struct thermal_cooling_device *cdev = to_cooling_device(dev); 515 516 return sprintf(buf, "%ld\n", cdev->max_state); 517} 518 519static ssize_t cur_state_show(struct device *dev, struct device_attribute *attr, 520 char *buf) 521{ 522 struct thermal_cooling_device *cdev = to_cooling_device(dev); 523 unsigned long state; 524 int ret; 525 526 ret = cdev->ops->get_cur_state(cdev, &state); 527 if (ret) 528 return ret; 529 return sprintf(buf, "%ld\n", state); 530} 531 532static ssize_t 533cur_state_store(struct device *dev, struct device_attribute *attr, 534 const char *buf, size_t count) 535{ 536 struct thermal_cooling_device *cdev = to_cooling_device(dev); 537 unsigned long state; 538 int result; 539 540 if (sscanf(buf, "%ld\n", &state) != 1) 541 return -EINVAL; 542 543 if ((long)state < 0) 544 return -EINVAL; 545 546 /* Requested state should be less than max_state + 1 */ 547 if (state > cdev->max_state) 548 return -EINVAL; 549 550 guard(cooling_dev)(cdev); 551 552 result = cdev->ops->set_cur_state(cdev, state); 553 if (result) 554 return result; 555 556 thermal_cooling_device_stats_update(cdev, state); 557 558 return count; 559} 560 561static struct device_attribute 562dev_attr_cdev_type = __ATTR(type, 0444, cdev_type_show, NULL); 563static DEVICE_ATTR_RO(max_state); 564static DEVICE_ATTR_RW(cur_state); 565 566static struct attribute *cooling_device_attrs[] = { 567 &dev_attr_cdev_type.attr, 568 &dev_attr_max_state.attr, 569 &dev_attr_cur_state.attr, 570 NULL, 571}; 572 573static const struct attribute_group cooling_device_attr_group = { 574 .attrs = cooling_device_attrs, 575}; 576 577static const struct attribute_group *cooling_device_attr_groups[] = { 578 &cooling_device_attr_group, 579 NULL, /* Space allocated for cooling_device_stats_attr_group */ 580 NULL, 581}; 582 583#ifdef CONFIG_THERMAL_STATISTICS 584struct cooling_dev_stats { 585 spinlock_t lock; 586 unsigned int total_trans; 587 unsigned long state; 588 ktime_t last_time; 589 ktime_t *time_in_state; 590 unsigned int *trans_table; 591}; 592 593static void update_time_in_state(struct cooling_dev_stats *stats) 594{ 595 ktime_t now = ktime_get(), delta; 596 597 delta = ktime_sub(now, stats->last_time); 598 stats->time_in_state[stats->state] = 599 ktime_add(stats->time_in_state[stats->state], delta); 600 stats->last_time = now; 601} 602 603void thermal_cooling_device_stats_update(struct thermal_cooling_device *cdev, 604 unsigned long new_state) 605{ 606 struct cooling_dev_stats *stats = cdev->stats; 607 608 lockdep_assert_held(&cdev->lock); 609 610 if (!stats) 611 return; 612 613 spin_lock(&stats->lock); 614 615 if (stats->state == new_state) 616 goto unlock; 617 618 update_time_in_state(stats); 619 stats->trans_table[stats->state * (cdev->max_state + 1) + new_state]++; 620 stats->state = new_state; 621 stats->total_trans++; 622 623unlock: 624 spin_unlock(&stats->lock); 625} 626 627static ssize_t total_trans_show(struct device *dev, 628 struct device_attribute *attr, char *buf) 629{ 630 struct thermal_cooling_device *cdev = to_cooling_device(dev); 631 struct cooling_dev_stats *stats; 632 int ret; 633 634 guard(cooling_dev)(cdev); 635 636 stats = cdev->stats; 637 if (!stats) 638 return 0; 639 640 spin_lock(&stats->lock); 641 ret = sprintf(buf, "%u\n", stats->total_trans); 642 spin_unlock(&stats->lock); 643 644 return ret; 645} 646 647static ssize_t 648time_in_state_ms_show(struct device *dev, struct device_attribute *attr, 649 char *buf) 650{ 651 struct thermal_cooling_device *cdev = to_cooling_device(dev); 652 struct cooling_dev_stats *stats; 653 ssize_t len = 0; 654 int i; 655 656 guard(cooling_dev)(cdev); 657 658 stats = cdev->stats; 659 if (!stats) 660 return 0; 661 662 spin_lock(&stats->lock); 663 664 update_time_in_state(stats); 665 666 for (i = 0; i <= cdev->max_state; i++) { 667 len += sprintf(buf + len, "state%u\t%llu\n", i, 668 ktime_to_ms(stats->time_in_state[i])); 669 } 670 spin_unlock(&stats->lock); 671 672 return len; 673} 674 675static ssize_t 676reset_store(struct device *dev, struct device_attribute *attr, const char *buf, 677 size_t count) 678{ 679 struct thermal_cooling_device *cdev = to_cooling_device(dev); 680 struct cooling_dev_stats *stats; 681 int i, states; 682 683 guard(cooling_dev)(cdev); 684 685 stats = cdev->stats; 686 if (!stats) 687 return count; 688 689 states = cdev->max_state + 1; 690 691 spin_lock(&stats->lock); 692 693 stats->total_trans = 0; 694 stats->last_time = ktime_get(); 695 memset(stats->trans_table, 0, 696 states * states * sizeof(*stats->trans_table)); 697 698 for (i = 0; i < states; i++) 699 stats->time_in_state[i] = ktime_set(0, 0); 700 701 spin_unlock(&stats->lock); 702 703 return count; 704} 705 706static ssize_t trans_table_show(struct device *dev, 707 struct device_attribute *attr, char *buf) 708{ 709 struct thermal_cooling_device *cdev = to_cooling_device(dev); 710 struct cooling_dev_stats *stats; 711 ssize_t len = 0; 712 int i, j; 713 714 guard(cooling_dev)(cdev); 715 716 stats = cdev->stats; 717 if (!stats) 718 return -ENODATA; 719 720 len += snprintf(buf + len, PAGE_SIZE - len, " From : To\n"); 721 len += snprintf(buf + len, PAGE_SIZE - len, " : "); 722 for (i = 0; i <= cdev->max_state; i++) { 723 if (len >= PAGE_SIZE) 724 break; 725 len += snprintf(buf + len, PAGE_SIZE - len, "state%2u ", i); 726 } 727 if (len >= PAGE_SIZE) 728 return PAGE_SIZE; 729 730 len += snprintf(buf + len, PAGE_SIZE - len, "\n"); 731 732 for (i = 0; i <= cdev->max_state; i++) { 733 if (len >= PAGE_SIZE) 734 break; 735 736 len += snprintf(buf + len, PAGE_SIZE - len, "state%2u:", i); 737 738 for (j = 0; j <= cdev->max_state; j++) { 739 if (len >= PAGE_SIZE) 740 break; 741 len += snprintf(buf + len, PAGE_SIZE - len, "%8u ", 742 stats->trans_table[i * (cdev->max_state + 1) + j]); 743 } 744 if (len >= PAGE_SIZE) 745 break; 746 len += snprintf(buf + len, PAGE_SIZE - len, "\n"); 747 } 748 749 if (len >= PAGE_SIZE) { 750 pr_warn_once("Thermal transition table exceeds PAGE_SIZE. Disabling\n"); 751 len = -EFBIG; 752 } 753 754 return len; 755} 756 757static DEVICE_ATTR_RO(total_trans); 758static DEVICE_ATTR_RO(time_in_state_ms); 759static DEVICE_ATTR_WO(reset); 760static DEVICE_ATTR_RO(trans_table); 761 762static struct attribute *cooling_device_stats_attrs[] = { 763 &dev_attr_total_trans.attr, 764 &dev_attr_time_in_state_ms.attr, 765 &dev_attr_reset.attr, 766 &dev_attr_trans_table.attr, 767 NULL 768}; 769 770static const struct attribute_group cooling_device_stats_attr_group = { 771 .attrs = cooling_device_stats_attrs, 772 .name = "stats" 773}; 774 775static void cooling_device_stats_setup(struct thermal_cooling_device *cdev) 776{ 777 const struct attribute_group *stats_attr_group = NULL; 778 struct cooling_dev_stats *stats; 779 /* Total number of states is highest state + 1 */ 780 unsigned long states = cdev->max_state + 1; 781 int var; 782 783 var = sizeof(*stats); 784 var += sizeof(*stats->time_in_state) * states; 785 var += sizeof(*stats->trans_table) * states * states; 786 787 stats = kzalloc(var, GFP_KERNEL); 788 if (!stats) 789 goto out; 790 791 stats->time_in_state = (ktime_t *)(stats + 1); 792 stats->trans_table = (unsigned int *)(stats->time_in_state + states); 793 cdev->stats = stats; 794 stats->last_time = ktime_get(); 795 796 spin_lock_init(&stats->lock); 797 798 stats_attr_group = &cooling_device_stats_attr_group; 799 800out: 801 /* Fill the empty slot left in cooling_device_attr_groups */ 802 var = ARRAY_SIZE(cooling_device_attr_groups) - 2; 803 cooling_device_attr_groups[var] = stats_attr_group; 804} 805 806static void cooling_device_stats_destroy(struct thermal_cooling_device *cdev) 807{ 808 kfree(cdev->stats); 809 cdev->stats = NULL; 810} 811 812#else 813 814static inline void 815cooling_device_stats_setup(struct thermal_cooling_device *cdev) {} 816static inline void 817cooling_device_stats_destroy(struct thermal_cooling_device *cdev) {} 818 819#endif /* CONFIG_THERMAL_STATISTICS */ 820 821void thermal_cooling_device_setup_sysfs(struct thermal_cooling_device *cdev) 822{ 823 cooling_device_stats_setup(cdev); 824 cdev->device.groups = cooling_device_attr_groups; 825} 826 827void thermal_cooling_device_destroy_sysfs(struct thermal_cooling_device *cdev) 828{ 829 cooling_device_stats_destroy(cdev); 830} 831 832void thermal_cooling_device_stats_reinit(struct thermal_cooling_device *cdev) 833{ 834 lockdep_assert_held(&cdev->lock); 835 836 cooling_device_stats_destroy(cdev); 837 cooling_device_stats_setup(cdev); 838} 839 840/* these helper will be used only at the time of bindig */ 841ssize_t 842trip_point_show(struct device *dev, struct device_attribute *attr, char *buf) 843{ 844 struct thermal_zone_device *tz = to_thermal_zone(dev); 845 struct thermal_instance *instance; 846 847 instance = container_of(attr, struct thermal_instance, attr); 848 849 return sprintf(buf, "%d\n", thermal_zone_trip_id(tz, instance->trip)); 850} 851 852ssize_t 853weight_show(struct device *dev, struct device_attribute *attr, char *buf) 854{ 855 struct thermal_instance *instance; 856 857 instance = container_of(attr, struct thermal_instance, weight_attr); 858 859 return sprintf(buf, "%d\n", instance->weight); 860} 861 862ssize_t weight_store(struct device *dev, struct device_attribute *attr, 863 const char *buf, size_t count) 864{ 865 struct thermal_zone_device *tz = to_thermal_zone(dev); 866 struct thermal_instance *instance; 867 int ret, weight; 868 869 ret = kstrtoint(buf, 0, &weight); 870 if (ret) 871 return ret; 872 873 instance = container_of(attr, struct thermal_instance, weight_attr); 874 875 /* Don't race with governors using the 'weight' value */ 876 guard(thermal_zone)(tz); 877 878 instance->weight = weight; 879 880 thermal_governor_update_tz(tz, THERMAL_INSTANCE_WEIGHT_CHANGED); 881 882 return count; 883}