Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v4.11-rc5 771 lines 20 kB view raw
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 28static ssize_t 29type_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 36static ssize_t 37temp_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 50static ssize_t 51mode_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 68static ssize_t 69mode_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 91static ssize_t 92trip_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 123static ssize_t 124trip_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 149static ssize_t 150trip_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 171static ssize_t 172trip_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 201static ssize_t 202trip_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 220static ssize_t 221passive_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 254static ssize_t 255passive_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 263static ssize_t 264policy_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 280static ssize_t 281policy_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 288static ssize_t 289available_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)) 296static ssize_t 297emul_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} 320static DEVICE_ATTR(emul_temp, S_IWUSR, NULL, emul_temp_store); 321#endif 322 323static ssize_t 324sustainable_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 335static ssize_t 336sustainable_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 385create_s32_tzp_attr(k_po); 386create_s32_tzp_attr(k_pu); 387create_s32_tzp_attr(k_i); 388create_s32_tzp_attr(k_d); 389create_s32_tzp_attr(integral_cutoff); 390create_s32_tzp_attr(slope); 391create_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 */ 399static DEVICE_ATTR(type, 0444, type_show, NULL); 400static DEVICE_ATTR(temp, 0444, temp_show, NULL); 401static DEVICE_ATTR(policy, S_IRUGO | S_IWUSR, policy_show, policy_store); 402static DEVICE_ATTR(available_policies, S_IRUGO, available_policies_show, NULL); 403static 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 */ 407static DEVICE_ATTR(mode, 0644, mode_show, mode_store); 408static DEVICE_ATTR(passive, S_IRUGO | S_IWUSR, passive_show, passive_store); 409 410/* These attributes are unconditionally added to a thermal zone */ 411static 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 430static 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 */ 435static struct attribute *thermal_zone_mode_attrs[] = { 436 &dev_attr_mode.attr, 437 NULL, 438}; 439 440static 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 455static 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 */ 461static struct attribute *thermal_zone_passive_attrs[] = { 462 &dev_attr_passive.attr, 463 NULL, 464}; 465 466static 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 490static struct attribute_group thermal_zone_passive_attribute_group = { 491 .attrs = thermal_zone_passive_attrs, 492 .is_visible = thermal_zone_passive_is_visible, 493}; 494 495static 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 */ 512static 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 608int 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 */ 641static ssize_t 642thermal_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 650static ssize_t 651thermal_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 664static ssize_t 665thermal_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 678static ssize_t 679thermal_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 699static struct device_attribute dev_attr_cdev_type = 700__ATTR(type, 0444, thermal_cooling_device_type_show, NULL); 701static DEVICE_ATTR(max_state, 0444, 702 thermal_cooling_device_max_state_show, NULL); 703static DEVICE_ATTR(cur_state, 0644, 704 thermal_cooling_device_cur_state_show, 705 thermal_cooling_device_cur_state_store); 706 707static 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 714static const struct attribute_group cooling_device_attr_group = { 715 .attrs = cooling_device_attrs, 716}; 717 718static const struct attribute_group *cooling_device_attr_groups[] = { 719 &cooling_device_attr_group, 720 NULL, 721}; 722 723void 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 */ 729ssize_t 730thermal_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 744ssize_t 745thermal_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 755ssize_t 756thermal_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}