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 24 #include "thermal_core.h" 25 26 /* sys I/F for thermal zone */ 27 28 static ssize_t 29 type_show(struct device *dev, struct device_attribute *attr, char *buf) 30 { 31 struct thermal_zone_device *tz = to_thermal_zone(dev); 32 33 return sprintf(buf, "%s\n", tz->type); 34 } 35 36 static ssize_t 37 temp_show(struct device *dev, struct device_attribute *attr, char *buf) 38 { 39 struct thermal_zone_device *tz = to_thermal_zone(dev); 40 int temperature, ret; 41 42 ret = thermal_zone_get_temp(tz, &temperature); 43 44 if (ret) 45 return ret; 46 47 return sprintf(buf, "%d\n", temperature); 48 } 49 50 static ssize_t 51 mode_show(struct device *dev, struct device_attribute *attr, char *buf) 52 { 53 struct thermal_zone_device *tz = to_thermal_zone(dev); 54 enum thermal_device_mode mode; 55 int result; 56 57 if (!tz->ops->get_mode) 58 return -EPERM; 59 60 result = tz->ops->get_mode(tz, &mode); 61 if (result) 62 return result; 63 64 return sprintf(buf, "%s\n", mode == THERMAL_DEVICE_ENABLED ? "enabled" 65 : "disabled"); 66 } 67 68 static ssize_t 69 mode_store(struct device *dev, struct device_attribute *attr, 70 const char *buf, size_t count) 71 { 72 struct thermal_zone_device *tz = to_thermal_zone(dev); 73 int result; 74 75 if (!tz->ops->set_mode) 76 return -EPERM; 77 78 if (!strncmp(buf, "enabled", sizeof("enabled") - 1)) 79 result = tz->ops->set_mode(tz, THERMAL_DEVICE_ENABLED); 80 else if (!strncmp(buf, "disabled", sizeof("disabled") - 1)) 81 result = tz->ops->set_mode(tz, THERMAL_DEVICE_DISABLED); 82 else 83 result = -EINVAL; 84 85 if (result) 86 return result; 87 88 return count; 89 } 90 91 static ssize_t 92 trip_point_type_show(struct device *dev, struct device_attribute *attr, 93 char *buf) 94 { 95 struct thermal_zone_device *tz = to_thermal_zone(dev); 96 enum thermal_trip_type type; 97 int trip, result; 98 99 if (!tz->ops->get_trip_type) 100 return -EPERM; 101 102 if (sscanf(attr->attr.name, "trip_point_%d_type", &trip) != 1) 103 return -EINVAL; 104 105 result = tz->ops->get_trip_type(tz, trip, &type); 106 if (result) 107 return result; 108 109 switch (type) { 110 case THERMAL_TRIP_CRITICAL: 111 return sprintf(buf, "critical\n"); 112 case THERMAL_TRIP_HOT: 113 return sprintf(buf, "hot\n"); 114 case THERMAL_TRIP_PASSIVE: 115 return sprintf(buf, "passive\n"); 116 case THERMAL_TRIP_ACTIVE: 117 return sprintf(buf, "active\n"); 118 default: 119 return sprintf(buf, "unknown\n"); 120 } 121 } 122 123 static ssize_t 124 trip_point_temp_store(struct device *dev, struct device_attribute *attr, 125 const char *buf, size_t count) 126 { 127 struct thermal_zone_device *tz = to_thermal_zone(dev); 128 int trip, ret; 129 int temperature; 130 131 if (!tz->ops->set_trip_temp) 132 return -EPERM; 133 134 if (sscanf(attr->attr.name, "trip_point_%d_temp", &trip) != 1) 135 return -EINVAL; 136 137 if (kstrtoint(buf, 10, &temperature)) 138 return -EINVAL; 139 140 ret = tz->ops->set_trip_temp(tz, trip, temperature); 141 if (ret) 142 return ret; 143 144 thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED); 145 146 return count; 147 } 148 149 static ssize_t 150 trip_point_temp_show(struct device *dev, struct device_attribute *attr, 151 char *buf) 152 { 153 struct thermal_zone_device *tz = to_thermal_zone(dev); 154 int trip, ret; 155 int temperature; 156 157 if (!tz->ops->get_trip_temp) 158 return -EPERM; 159 160 if (sscanf(attr->attr.name, "trip_point_%d_temp", &trip) != 1) 161 return -EINVAL; 162 163 ret = tz->ops->get_trip_temp(tz, trip, &temperature); 164 165 if (ret) 166 return ret; 167 168 return sprintf(buf, "%d\n", temperature); 169 } 170 171 static ssize_t 172 trip_point_hyst_store(struct device *dev, struct device_attribute *attr, 173 const char *buf, size_t count) 174 { 175 struct thermal_zone_device *tz = to_thermal_zone(dev); 176 int trip, ret; 177 int temperature; 178 179 if (!tz->ops->set_trip_hyst) 180 return -EPERM; 181 182 if (sscanf(attr->attr.name, "trip_point_%d_hyst", &trip) != 1) 183 return -EINVAL; 184 185 if (kstrtoint(buf, 10, &temperature)) 186 return -EINVAL; 187 188 /* 189 * We are not doing any check on the 'temperature' value 190 * here. The driver implementing 'set_trip_hyst' has to 191 * take care of this. 192 */ 193 ret = tz->ops->set_trip_hyst(tz, trip, temperature); 194 195 if (!ret) 196 thermal_zone_set_trips(tz); 197 198 return ret ? ret : count; 199 } 200 201 static ssize_t 202 trip_point_hyst_show(struct device *dev, struct device_attribute *attr, 203 char *buf) 204 { 205 struct thermal_zone_device *tz = to_thermal_zone(dev); 206 int trip, ret; 207 int temperature; 208 209 if (!tz->ops->get_trip_hyst) 210 return -EPERM; 211 212 if (sscanf(attr->attr.name, "trip_point_%d_hyst", &trip) != 1) 213 return -EINVAL; 214 215 ret = tz->ops->get_trip_hyst(tz, trip, &temperature); 216 217 return ret ? ret : sprintf(buf, "%d\n", temperature); 218 } 219 220 static ssize_t 221 passive_store(struct device *dev, struct device_attribute *attr, 222 const char *buf, size_t count) 223 { 224 struct thermal_zone_device *tz = to_thermal_zone(dev); 225 int state; 226 227 if (sscanf(buf, "%d\n", &state) != 1) 228 return -EINVAL; 229 230 /* sanity check: values below 1000 millicelcius don't make sense 231 * and can cause the system to go into a thermal heart attack 232 */ 233 if (state && state < 1000) 234 return -EINVAL; 235 236 if (state && !tz->forced_passive) { 237 if (!tz->passive_delay) 238 tz->passive_delay = 1000; 239 thermal_zone_device_rebind_exception(tz, "Processor", 240 sizeof("Processor")); 241 } else if (!state && tz->forced_passive) { 242 tz->passive_delay = 0; 243 thermal_zone_device_unbind_exception(tz, "Processor", 244 sizeof("Processor")); 245 } 246 247 tz->forced_passive = state; 248 249 thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED); 250 251 return count; 252 } 253 254 static ssize_t 255 passive_show(struct device *dev, struct device_attribute *attr, 256 char *buf) 257 { 258 struct thermal_zone_device *tz = to_thermal_zone(dev); 259 260 return sprintf(buf, "%d\n", tz->forced_passive); 261 } 262 263 static ssize_t 264 policy_store(struct device *dev, struct device_attribute *attr, 265 const char *buf, size_t count) 266 { 267 struct thermal_zone_device *tz = to_thermal_zone(dev); 268 char name[THERMAL_NAME_LENGTH]; 269 int ret; 270 271 snprintf(name, sizeof(name), "%s", buf); 272 273 ret = thermal_zone_device_set_policy(tz, name); 274 if (!ret) 275 ret = count; 276 277 return ret; 278 } 279 280 static ssize_t 281 policy_show(struct device *dev, struct device_attribute *devattr, char *buf) 282 { 283 struct thermal_zone_device *tz = to_thermal_zone(dev); 284 285 return sprintf(buf, "%s\n", tz->governor->name); 286 } 287 288 static ssize_t 289 available_policies_show(struct device *dev, struct device_attribute *devattr, 290 char *buf) 291 { 292 return thermal_build_list_of_policies(buf); 293 } 294 295 #if (IS_ENABLED(CONFIG_THERMAL_EMULATION)) 296 static ssize_t 297 emul_temp_store(struct device *dev, struct device_attribute *attr, 298 const char *buf, size_t count) 299 { 300 struct thermal_zone_device *tz = to_thermal_zone(dev); 301 int ret = 0; 302 int temperature; 303 304 if (kstrtoint(buf, 10, &temperature)) 305 return -EINVAL; 306 307 if (!tz->ops->set_emul_temp) { 308 mutex_lock(&tz->lock); 309 tz->emul_temperature = temperature; 310 mutex_unlock(&tz->lock); 311 } else { 312 ret = tz->ops->set_emul_temp(tz, temperature); 313 } 314 315 if (!ret) 316 thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED); 317 318 return ret ? ret : count; 319 } 320 static DEVICE_ATTR(emul_temp, S_IWUSR, NULL, emul_temp_store); 321 #endif 322 323 static ssize_t 324 sustainable_power_show(struct device *dev, struct device_attribute *devattr, 325 char *buf) 326 { 327 struct thermal_zone_device *tz = to_thermal_zone(dev); 328 329 if (tz->tzp) 330 return sprintf(buf, "%u\n", tz->tzp->sustainable_power); 331 else 332 return -EIO; 333 } 334 335 static ssize_t 336 sustainable_power_store(struct device *dev, struct device_attribute *devattr, 337 const char *buf, size_t count) 338 { 339 struct thermal_zone_device *tz = to_thermal_zone(dev); 340 u32 sustainable_power; 341 342 if (!tz->tzp) 343 return -EIO; 344 345 if (kstrtou32(buf, 10, &sustainable_power)) 346 return -EINVAL; 347 348 tz->tzp->sustainable_power = sustainable_power; 349 350 return count; 351 } 352 353 #define create_s32_tzp_attr(name) \ 354 static ssize_t \ 355 name##_show(struct device *dev, struct device_attribute *devattr, \ 356 char *buf) \ 357 { \ 358 struct thermal_zone_device *tz = to_thermal_zone(dev); \ 359 \ 360 if (tz->tzp) \ 361 return sprintf(buf, "%d\n", tz->tzp->name); \ 362 else \ 363 return -EIO; \ 364 } \ 365 \ 366 static ssize_t \ 367 name##_store(struct device *dev, struct device_attribute *devattr, \ 368 const char *buf, size_t count) \ 369 { \ 370 struct thermal_zone_device *tz = to_thermal_zone(dev); \ 371 s32 value; \ 372 \ 373 if (!tz->tzp) \ 374 return -EIO; \ 375 \ 376 if (kstrtos32(buf, 10, &value)) \ 377 return -EINVAL; \ 378 \ 379 tz->tzp->name = value; \ 380 \ 381 return count; \ 382 } \ 383 static DEVICE_ATTR(name, S_IWUSR | S_IRUGO, name##_show, name##_store) 384 385 create_s32_tzp_attr(k_po); 386 create_s32_tzp_attr(k_pu); 387 create_s32_tzp_attr(k_i); 388 create_s32_tzp_attr(k_d); 389 create_s32_tzp_attr(integral_cutoff); 390 create_s32_tzp_attr(slope); 391 create_s32_tzp_attr(offset); 392 #undef create_s32_tzp_attr 393 394 /* 395 * These are thermal zone device attributes that will always be present. 396 * All the attributes created for tzp (create_s32_tzp_attr) also are always 397 * present on the sysfs interface. 398 */ 399 static DEVICE_ATTR(type, 0444, type_show, NULL); 400 static DEVICE_ATTR(temp, 0444, temp_show, NULL); 401 static DEVICE_ATTR(policy, S_IRUGO | S_IWUSR, policy_show, policy_store); 402 static DEVICE_ATTR(available_policies, S_IRUGO, available_policies_show, NULL); 403 static DEVICE_ATTR(sustainable_power, S_IWUSR | S_IRUGO, sustainable_power_show, 404 sustainable_power_store); 405 406 /* These thermal zone device attributes are created based on conditions */ 407 static DEVICE_ATTR(mode, 0644, mode_show, mode_store); 408 static DEVICE_ATTR(passive, S_IRUGO | S_IWUSR, passive_show, passive_store); 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 int thermal_zone_create_device_groups(struct thermal_zone_device *tz, 609 int mask) 610 { 611 const struct attribute_group **groups; 612 int i, size, result; 613 614 /* we need one extra for trips and the NULL to terminate the array */ 615 size = ARRAY_SIZE(thermal_zone_attribute_groups) + 2; 616 /* This also takes care of API requirement to be NULL terminated */ 617 groups = kcalloc(size, sizeof(*groups), GFP_KERNEL); 618 if (!groups) 619 return -ENOMEM; 620 621 for (i = 0; i < size - 2; i++) 622 groups[i] = thermal_zone_attribute_groups[i]; 623 624 if (tz->trips) { 625 result = create_trip_attrs(tz, mask); 626 if (result) { 627 kfree(groups); 628 629 return result; 630 } 631 632 groups[size - 2] = &tz->trips_attribute_group; 633 } 634 635 tz->device.groups = groups; 636 637 return 0; 638 } 639 640 /* sys I/F for cooling device */ 641 static ssize_t 642 thermal_cooling_device_type_show(struct device *dev, 643 struct device_attribute *attr, char *buf) 644 { 645 struct thermal_cooling_device *cdev = to_cooling_device(dev); 646 647 return sprintf(buf, "%s\n", cdev->type); 648 } 649 650 static ssize_t 651 thermal_cooling_device_max_state_show(struct device *dev, 652 struct device_attribute *attr, char *buf) 653 { 654 struct thermal_cooling_device *cdev = to_cooling_device(dev); 655 unsigned long state; 656 int ret; 657 658 ret = cdev->ops->get_max_state(cdev, &state); 659 if (ret) 660 return ret; 661 return sprintf(buf, "%ld\n", state); 662 } 663 664 static ssize_t 665 thermal_cooling_device_cur_state_show(struct device *dev, 666 struct device_attribute *attr, char *buf) 667 { 668 struct thermal_cooling_device *cdev = to_cooling_device(dev); 669 unsigned long state; 670 int ret; 671 672 ret = cdev->ops->get_cur_state(cdev, &state); 673 if (ret) 674 return ret; 675 return sprintf(buf, "%ld\n", state); 676 } 677 678 static ssize_t 679 thermal_cooling_device_cur_state_store(struct device *dev, 680 struct device_attribute *attr, 681 const char *buf, size_t count) 682 { 683 struct thermal_cooling_device *cdev = to_cooling_device(dev); 684 unsigned long state; 685 int result; 686 687 if (sscanf(buf, "%ld\n", &state) != 1) 688 return -EINVAL; 689 690 if ((long)state < 0) 691 return -EINVAL; 692 693 result = cdev->ops->set_cur_state(cdev, state); 694 if (result) 695 return result; 696 return count; 697 } 698 699 static struct device_attribute dev_attr_cdev_type = 700 __ATTR(type, 0444, thermal_cooling_device_type_show, NULL); 701 static DEVICE_ATTR(max_state, 0444, 702 thermal_cooling_device_max_state_show, NULL); 703 static DEVICE_ATTR(cur_state, 0644, 704 thermal_cooling_device_cur_state_show, 705 thermal_cooling_device_cur_state_store); 706 707 static struct attribute *cooling_device_attrs[] = { 708 &dev_attr_cdev_type.attr, 709 &dev_attr_max_state.attr, 710 &dev_attr_cur_state.attr, 711 NULL, 712 }; 713 714 static const struct attribute_group cooling_device_attr_group = { 715 .attrs = cooling_device_attrs, 716 }; 717 718 static const struct attribute_group *cooling_device_attr_groups[] = { 719 &cooling_device_attr_group, 720 NULL, 721 }; 722 723 void thermal_cooling_device_setup_sysfs(struct thermal_cooling_device *cdev) 724 { 725 cdev->device.groups = cooling_device_attr_groups; 726 } 727 728 /* these helper will be used only at the time of bindig */ 729 ssize_t 730 thermal_cooling_device_trip_point_show(struct device *dev, 731 struct device_attribute *attr, char *buf) 732 { 733 struct thermal_instance *instance; 734 735 instance = 736 container_of(attr, struct thermal_instance, attr); 737 738 if (instance->trip == THERMAL_TRIPS_NONE) 739 return sprintf(buf, "-1\n"); 740 else 741 return sprintf(buf, "%d\n", instance->trip); 742 } 743 744 ssize_t 745 thermal_cooling_device_weight_show(struct device *dev, 746 struct device_attribute *attr, char *buf) 747 { 748 struct thermal_instance *instance; 749 750 instance = container_of(attr, struct thermal_instance, weight_attr); 751 752 return sprintf(buf, "%d\n", instance->weight); 753 } 754 755 ssize_t 756 thermal_cooling_device_weight_store(struct device *dev, 757 struct device_attribute *attr, 758 const char *buf, size_t count) 759 { 760 struct thermal_instance *instance; 761 int ret, weight; 762 763 ret = kstrtoint(buf, 0, &weight); 764 if (ret) 765 return ret; 766 767 instance = container_of(attr, struct thermal_instance, weight_attr); 768 instance->weight = weight; 769 770 return count; 771 } 772