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