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