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