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_WO(emul_temp); 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_RO(type); 400 static DEVICE_ATTR_RO(temp); 401 static DEVICE_ATTR_RW(policy); 402 static DEVICE_ATTR_RO(available_policies); 403 static DEVICE_ATTR_RW(sustainable_power); 404 405 /* These thermal zone device attributes are created based on conditions */ 406 static DEVICE_ATTR_RW(mode); 407 static DEVICE_ATTR_RW(passive); 408 409 /* These attributes are unconditionally added to a thermal zone */ 410 static struct attribute *thermal_zone_dev_attrs[] = { 411 &dev_attr_type.attr, 412 &dev_attr_temp.attr, 413 #if (IS_ENABLED(CONFIG_THERMAL_EMULATION)) 414 &dev_attr_emul_temp.attr, 415 #endif 416 &dev_attr_policy.attr, 417 &dev_attr_available_policies.attr, 418 &dev_attr_sustainable_power.attr, 419 &dev_attr_k_po.attr, 420 &dev_attr_k_pu.attr, 421 &dev_attr_k_i.attr, 422 &dev_attr_k_d.attr, 423 &dev_attr_integral_cutoff.attr, 424 &dev_attr_slope.attr, 425 &dev_attr_offset.attr, 426 NULL, 427 }; 428 429 static struct attribute_group thermal_zone_attribute_group = { 430 .attrs = thermal_zone_dev_attrs, 431 }; 432 433 /* We expose mode only if .get_mode is present */ 434 static struct attribute *thermal_zone_mode_attrs[] = { 435 &dev_attr_mode.attr, 436 NULL, 437 }; 438 439 static umode_t thermal_zone_mode_is_visible(struct kobject *kobj, 440 struct attribute *attr, 441 int attrno) 442 { 443 struct device *dev = container_of(kobj, struct device, kobj); 444 struct thermal_zone_device *tz; 445 446 tz = container_of(dev, struct thermal_zone_device, device); 447 448 if (tz->ops->get_mode) 449 return attr->mode; 450 451 return 0; 452 } 453 454 static struct attribute_group thermal_zone_mode_attribute_group = { 455 .attrs = thermal_zone_mode_attrs, 456 .is_visible = thermal_zone_mode_is_visible, 457 }; 458 459 /* We expose passive only if passive trips are present */ 460 static struct attribute *thermal_zone_passive_attrs[] = { 461 &dev_attr_passive.attr, 462 NULL, 463 }; 464 465 static umode_t thermal_zone_passive_is_visible(struct kobject *kobj, 466 struct attribute *attr, 467 int attrno) 468 { 469 struct device *dev = container_of(kobj, struct device, kobj); 470 struct thermal_zone_device *tz; 471 enum thermal_trip_type trip_type; 472 int count, passive = 0; 473 474 tz = container_of(dev, struct thermal_zone_device, device); 475 476 for (count = 0; count < tz->trips && !passive; count++) { 477 tz->ops->get_trip_type(tz, count, &trip_type); 478 479 if (trip_type == THERMAL_TRIP_PASSIVE) 480 passive = 1; 481 } 482 483 if (!passive) 484 return attr->mode; 485 486 return 0; 487 } 488 489 static struct attribute_group thermal_zone_passive_attribute_group = { 490 .attrs = thermal_zone_passive_attrs, 491 .is_visible = thermal_zone_passive_is_visible, 492 }; 493 494 static const struct attribute_group *thermal_zone_attribute_groups[] = { 495 &thermal_zone_attribute_group, 496 &thermal_zone_mode_attribute_group, 497 &thermal_zone_passive_attribute_group, 498 /* This is not NULL terminated as we create the group dynamically */ 499 }; 500 501 /** 502 * create_trip_attrs() - create attributes for trip points 503 * @tz: the thermal zone device 504 * @mask: Writeable trip point bitmap. 505 * 506 * helper function to instantiate sysfs entries for every trip 507 * point and its properties of a struct thermal_zone_device. 508 * 509 * Return: 0 on success, the proper error value otherwise. 510 */ 511 static int create_trip_attrs(struct thermal_zone_device *tz, int mask) 512 { 513 struct attribute **attrs; 514 int indx; 515 516 /* This function works only for zones with at least one trip */ 517 if (tz->trips <= 0) 518 return -EINVAL; 519 520 tz->trip_type_attrs = kcalloc(tz->trips, sizeof(*tz->trip_type_attrs), 521 GFP_KERNEL); 522 if (!tz->trip_type_attrs) 523 return -ENOMEM; 524 525 tz->trip_temp_attrs = kcalloc(tz->trips, sizeof(*tz->trip_temp_attrs), 526 GFP_KERNEL); 527 if (!tz->trip_temp_attrs) { 528 kfree(tz->trip_type_attrs); 529 return -ENOMEM; 530 } 531 532 if (tz->ops->get_trip_hyst) { 533 tz->trip_hyst_attrs = kcalloc(tz->trips, 534 sizeof(*tz->trip_hyst_attrs), 535 GFP_KERNEL); 536 if (!tz->trip_hyst_attrs) { 537 kfree(tz->trip_type_attrs); 538 kfree(tz->trip_temp_attrs); 539 return -ENOMEM; 540 } 541 } 542 543 attrs = kcalloc(tz->trips * 3 + 1, sizeof(*attrs), GFP_KERNEL); 544 if (!attrs) { 545 kfree(tz->trip_type_attrs); 546 kfree(tz->trip_temp_attrs); 547 if (tz->ops->get_trip_hyst) 548 kfree(tz->trip_hyst_attrs); 549 return -ENOMEM; 550 } 551 552 for (indx = 0; indx < tz->trips; indx++) { 553 /* create trip type attribute */ 554 snprintf(tz->trip_type_attrs[indx].name, THERMAL_NAME_LENGTH, 555 "trip_point_%d_type", indx); 556 557 sysfs_attr_init(&tz->trip_type_attrs[indx].attr.attr); 558 tz->trip_type_attrs[indx].attr.attr.name = 559 tz->trip_type_attrs[indx].name; 560 tz->trip_type_attrs[indx].attr.attr.mode = S_IRUGO; 561 tz->trip_type_attrs[indx].attr.show = trip_point_type_show; 562 attrs[indx] = &tz->trip_type_attrs[indx].attr.attr; 563 564 /* create trip temp attribute */ 565 snprintf(tz->trip_temp_attrs[indx].name, THERMAL_NAME_LENGTH, 566 "trip_point_%d_temp", indx); 567 568 sysfs_attr_init(&tz->trip_temp_attrs[indx].attr.attr); 569 tz->trip_temp_attrs[indx].attr.attr.name = 570 tz->trip_temp_attrs[indx].name; 571 tz->trip_temp_attrs[indx].attr.attr.mode = S_IRUGO; 572 tz->trip_temp_attrs[indx].attr.show = trip_point_temp_show; 573 if (IS_ENABLED(CONFIG_THERMAL_WRITABLE_TRIPS) && 574 mask & (1 << indx)) { 575 tz->trip_temp_attrs[indx].attr.attr.mode |= S_IWUSR; 576 tz->trip_temp_attrs[indx].attr.store = 577 trip_point_temp_store; 578 } 579 attrs[indx + tz->trips] = &tz->trip_temp_attrs[indx].attr.attr; 580 581 /* create Optional trip hyst attribute */ 582 if (!tz->ops->get_trip_hyst) 583 continue; 584 snprintf(tz->trip_hyst_attrs[indx].name, THERMAL_NAME_LENGTH, 585 "trip_point_%d_hyst", indx); 586 587 sysfs_attr_init(&tz->trip_hyst_attrs[indx].attr.attr); 588 tz->trip_hyst_attrs[indx].attr.attr.name = 589 tz->trip_hyst_attrs[indx].name; 590 tz->trip_hyst_attrs[indx].attr.attr.mode = S_IRUGO; 591 tz->trip_hyst_attrs[indx].attr.show = trip_point_hyst_show; 592 if (tz->ops->set_trip_hyst) { 593 tz->trip_hyst_attrs[indx].attr.attr.mode |= S_IWUSR; 594 tz->trip_hyst_attrs[indx].attr.store = 595 trip_point_hyst_store; 596 } 597 attrs[indx + tz->trips * 2] = 598 &tz->trip_hyst_attrs[indx].attr.attr; 599 } 600 attrs[tz->trips * 3] = NULL; 601 602 tz->trips_attribute_group.attrs = attrs; 603 604 return 0; 605 } 606 607 /** 608 * destroy_trip_attrs() - destroy attributes for trip points 609 * @tz: the thermal zone device 610 * 611 * helper function to free resources allocated by create_trip_attrs() 612 */ 613 static void destroy_trip_attrs(struct thermal_zone_device *tz) 614 { 615 if (!tz) 616 return; 617 618 kfree(tz->trip_type_attrs); 619 kfree(tz->trip_temp_attrs); 620 if (tz->ops->get_trip_hyst) 621 kfree(tz->trip_hyst_attrs); 622 kfree(tz->trips_attribute_group.attrs); 623 } 624 625 int thermal_zone_create_device_groups(struct thermal_zone_device *tz, 626 int mask) 627 { 628 const struct attribute_group **groups; 629 int i, size, result; 630 631 /* we need one extra for trips and the NULL to terminate the array */ 632 size = ARRAY_SIZE(thermal_zone_attribute_groups) + 2; 633 /* This also takes care of API requirement to be NULL terminated */ 634 groups = kcalloc(size, sizeof(*groups), GFP_KERNEL); 635 if (!groups) 636 return -ENOMEM; 637 638 for (i = 0; i < size - 2; i++) 639 groups[i] = thermal_zone_attribute_groups[i]; 640 641 if (tz->trips) { 642 result = create_trip_attrs(tz, mask); 643 if (result) { 644 kfree(groups); 645 646 return result; 647 } 648 649 groups[size - 2] = &tz->trips_attribute_group; 650 } 651 652 tz->device.groups = groups; 653 654 return 0; 655 } 656 657 void thermal_zone_destroy_device_groups(struct thermal_zone_device *tz) 658 { 659 if (!tz) 660 return; 661 662 if (tz->trips) 663 destroy_trip_attrs(tz); 664 665 kfree(tz->device.groups); 666 } 667 668 /* sys I/F for cooling device */ 669 static ssize_t 670 thermal_cooling_device_type_show(struct device *dev, 671 struct device_attribute *attr, char *buf) 672 { 673 struct thermal_cooling_device *cdev = to_cooling_device(dev); 674 675 return sprintf(buf, "%s\n", cdev->type); 676 } 677 678 static ssize_t 679 thermal_cooling_device_max_state_show(struct device *dev, 680 struct device_attribute *attr, char *buf) 681 { 682 struct thermal_cooling_device *cdev = to_cooling_device(dev); 683 unsigned long state; 684 int ret; 685 686 ret = cdev->ops->get_max_state(cdev, &state); 687 if (ret) 688 return ret; 689 return sprintf(buf, "%ld\n", state); 690 } 691 692 static ssize_t 693 thermal_cooling_device_cur_state_show(struct device *dev, 694 struct device_attribute *attr, char *buf) 695 { 696 struct thermal_cooling_device *cdev = to_cooling_device(dev); 697 unsigned long state; 698 int ret; 699 700 ret = cdev->ops->get_cur_state(cdev, &state); 701 if (ret) 702 return ret; 703 return sprintf(buf, "%ld\n", state); 704 } 705 706 static ssize_t 707 thermal_cooling_device_cur_state_store(struct device *dev, 708 struct device_attribute *attr, 709 const char *buf, size_t count) 710 { 711 struct thermal_cooling_device *cdev = to_cooling_device(dev); 712 unsigned long state; 713 int result; 714 715 if (sscanf(buf, "%ld\n", &state) != 1) 716 return -EINVAL; 717 718 if ((long)state < 0) 719 return -EINVAL; 720 721 result = cdev->ops->set_cur_state(cdev, state); 722 if (result) 723 return result; 724 return count; 725 } 726 727 static struct device_attribute dev_attr_cdev_type = 728 __ATTR(type, 0444, thermal_cooling_device_type_show, NULL); 729 static DEVICE_ATTR(max_state, 0444, 730 thermal_cooling_device_max_state_show, NULL); 731 static DEVICE_ATTR(cur_state, 0644, 732 thermal_cooling_device_cur_state_show, 733 thermal_cooling_device_cur_state_store); 734 735 static struct attribute *cooling_device_attrs[] = { 736 &dev_attr_cdev_type.attr, 737 &dev_attr_max_state.attr, 738 &dev_attr_cur_state.attr, 739 NULL, 740 }; 741 742 static const struct attribute_group cooling_device_attr_group = { 743 .attrs = cooling_device_attrs, 744 }; 745 746 static const struct attribute_group *cooling_device_attr_groups[] = { 747 &cooling_device_attr_group, 748 NULL, 749 }; 750 751 void thermal_cooling_device_setup_sysfs(struct thermal_cooling_device *cdev) 752 { 753 cdev->device.groups = cooling_device_attr_groups; 754 } 755 756 /* these helper will be used only at the time of bindig */ 757 ssize_t 758 thermal_cooling_device_trip_point_show(struct device *dev, 759 struct device_attribute *attr, char *buf) 760 { 761 struct thermal_instance *instance; 762 763 instance = 764 container_of(attr, struct thermal_instance, attr); 765 766 if (instance->trip == THERMAL_TRIPS_NONE) 767 return sprintf(buf, "-1\n"); 768 else 769 return sprintf(buf, "%d\n", instance->trip); 770 } 771 772 ssize_t 773 thermal_cooling_device_weight_show(struct device *dev, 774 struct device_attribute *attr, char *buf) 775 { 776 struct thermal_instance *instance; 777 778 instance = container_of(attr, struct thermal_instance, weight_attr); 779 780 return sprintf(buf, "%d\n", instance->weight); 781 } 782 783 ssize_t 784 thermal_cooling_device_weight_store(struct device *dev, 785 struct device_attribute *attr, 786 const char *buf, size_t count) 787 { 788 struct thermal_instance *instance; 789 int ret, weight; 790 791 ret = kstrtoint(buf, 0, &weight); 792 if (ret) 793 return ret; 794 795 instance = container_of(attr, struct thermal_instance, weight_attr); 796 instance->weight = weight; 797 798 return count; 799 } 800