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