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 v2.6.32-rc7 1232 lines 32 kB view raw
1/* 2 * thermal.c - Generic Thermal Management Sysfs support. 3 * 4 * Copyright (C) 2008 Intel Corp 5 * Copyright (C) 2008 Zhang Rui <rui.zhang@intel.com> 6 * Copyright (C) 2008 Sujith Thomas <sujith.thomas@intel.com> 7 * 8 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 9 * 10 * This program is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License as published by 12 * the Free Software Foundation; version 2 of the License. 13 * 14 * This program is distributed in the hope that it will be useful, but 15 * WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 * General Public License for more details. 18 * 19 * You should have received a copy of the GNU General Public License along 20 * with this program; if not, write to the Free Software Foundation, Inc., 21 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. 22 * 23 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 24 */ 25 26#include <linux/module.h> 27#include <linux/device.h> 28#include <linux/err.h> 29#include <linux/kdev_t.h> 30#include <linux/idr.h> 31#include <linux/thermal.h> 32#include <linux/spinlock.h> 33#include <linux/reboot.h> 34 35MODULE_AUTHOR("Zhang Rui"); 36MODULE_DESCRIPTION("Generic thermal management sysfs support"); 37MODULE_LICENSE("GPL"); 38 39#define PREFIX "Thermal: " 40 41struct thermal_cooling_device_instance { 42 int id; 43 char name[THERMAL_NAME_LENGTH]; 44 struct thermal_zone_device *tz; 45 struct thermal_cooling_device *cdev; 46 int trip; 47 char attr_name[THERMAL_NAME_LENGTH]; 48 struct device_attribute attr; 49 struct list_head node; 50}; 51 52static DEFINE_IDR(thermal_tz_idr); 53static DEFINE_IDR(thermal_cdev_idr); 54static DEFINE_MUTEX(thermal_idr_lock); 55 56static LIST_HEAD(thermal_tz_list); 57static LIST_HEAD(thermal_cdev_list); 58static DEFINE_MUTEX(thermal_list_lock); 59 60static int get_idr(struct idr *idr, struct mutex *lock, int *id) 61{ 62 int err; 63 64 again: 65 if (unlikely(idr_pre_get(idr, GFP_KERNEL) == 0)) 66 return -ENOMEM; 67 68 if (lock) 69 mutex_lock(lock); 70 err = idr_get_new(idr, NULL, id); 71 if (lock) 72 mutex_unlock(lock); 73 if (unlikely(err == -EAGAIN)) 74 goto again; 75 else if (unlikely(err)) 76 return err; 77 78 *id = *id & MAX_ID_MASK; 79 return 0; 80} 81 82static void release_idr(struct idr *idr, struct mutex *lock, int id) 83{ 84 if (lock) 85 mutex_lock(lock); 86 idr_remove(idr, id); 87 if (lock) 88 mutex_unlock(lock); 89} 90 91/* sys I/F for thermal zone */ 92 93#define to_thermal_zone(_dev) \ 94 container_of(_dev, struct thermal_zone_device, device) 95 96static ssize_t 97type_show(struct device *dev, struct device_attribute *attr, char *buf) 98{ 99 struct thermal_zone_device *tz = to_thermal_zone(dev); 100 101 return sprintf(buf, "%s\n", tz->type); 102} 103 104static ssize_t 105temp_show(struct device *dev, struct device_attribute *attr, char *buf) 106{ 107 struct thermal_zone_device *tz = to_thermal_zone(dev); 108 long temperature; 109 int ret; 110 111 if (!tz->ops->get_temp) 112 return -EPERM; 113 114 ret = tz->ops->get_temp(tz, &temperature); 115 116 if (ret) 117 return ret; 118 119 return sprintf(buf, "%ld\n", temperature); 120} 121 122static ssize_t 123mode_show(struct device *dev, struct device_attribute *attr, char *buf) 124{ 125 struct thermal_zone_device *tz = to_thermal_zone(dev); 126 enum thermal_device_mode mode; 127 int result; 128 129 if (!tz->ops->get_mode) 130 return -EPERM; 131 132 result = tz->ops->get_mode(tz, &mode); 133 if (result) 134 return result; 135 136 return sprintf(buf, "%s\n", mode == THERMAL_DEVICE_ENABLED ? "enabled" 137 : "disabled"); 138} 139 140static ssize_t 141mode_store(struct device *dev, struct device_attribute *attr, 142 const char *buf, size_t count) 143{ 144 struct thermal_zone_device *tz = to_thermal_zone(dev); 145 int result; 146 147 if (!tz->ops->set_mode) 148 return -EPERM; 149 150 if (!strncmp(buf, "enabled", sizeof("enabled"))) 151 result = tz->ops->set_mode(tz, THERMAL_DEVICE_ENABLED); 152 else if (!strncmp(buf, "disabled", sizeof("disabled"))) 153 result = tz->ops->set_mode(tz, THERMAL_DEVICE_DISABLED); 154 else 155 result = -EINVAL; 156 157 if (result) 158 return result; 159 160 return count; 161} 162 163static ssize_t 164trip_point_type_show(struct device *dev, struct device_attribute *attr, 165 char *buf) 166{ 167 struct thermal_zone_device *tz = to_thermal_zone(dev); 168 enum thermal_trip_type type; 169 int trip, result; 170 171 if (!tz->ops->get_trip_type) 172 return -EPERM; 173 174 if (!sscanf(attr->attr.name, "trip_point_%d_type", &trip)) 175 return -EINVAL; 176 177 result = tz->ops->get_trip_type(tz, trip, &type); 178 if (result) 179 return result; 180 181 switch (type) { 182 case THERMAL_TRIP_CRITICAL: 183 return sprintf(buf, "critical\n"); 184 case THERMAL_TRIP_HOT: 185 return sprintf(buf, "hot\n"); 186 case THERMAL_TRIP_PASSIVE: 187 return sprintf(buf, "passive\n"); 188 case THERMAL_TRIP_ACTIVE: 189 return sprintf(buf, "active\n"); 190 default: 191 return sprintf(buf, "unknown\n"); 192 } 193} 194 195static ssize_t 196trip_point_temp_show(struct device *dev, struct device_attribute *attr, 197 char *buf) 198{ 199 struct thermal_zone_device *tz = to_thermal_zone(dev); 200 int trip, ret; 201 long temperature; 202 203 if (!tz->ops->get_trip_temp) 204 return -EPERM; 205 206 if (!sscanf(attr->attr.name, "trip_point_%d_temp", &trip)) 207 return -EINVAL; 208 209 ret = tz->ops->get_trip_temp(tz, trip, &temperature); 210 211 if (ret) 212 return ret; 213 214 return sprintf(buf, "%ld\n", temperature); 215} 216 217static ssize_t 218passive_store(struct device *dev, struct device_attribute *attr, 219 const char *buf, size_t count) 220{ 221 struct thermal_zone_device *tz = to_thermal_zone(dev); 222 struct thermal_cooling_device *cdev = NULL; 223 int state; 224 225 if (!sscanf(buf, "%d\n", &state)) 226 return -EINVAL; 227 228 if (state && !tz->forced_passive) { 229 mutex_lock(&thermal_list_lock); 230 list_for_each_entry(cdev, &thermal_cdev_list, node) { 231 if (!strncmp("Processor", cdev->type, 232 sizeof("Processor"))) 233 thermal_zone_bind_cooling_device(tz, 234 THERMAL_TRIPS_NONE, 235 cdev); 236 } 237 mutex_unlock(&thermal_list_lock); 238 } else if (!state && tz->forced_passive) { 239 mutex_lock(&thermal_list_lock); 240 list_for_each_entry(cdev, &thermal_cdev_list, node) { 241 if (!strncmp("Processor", cdev->type, 242 sizeof("Processor"))) 243 thermal_zone_unbind_cooling_device(tz, 244 THERMAL_TRIPS_NONE, 245 cdev); 246 } 247 mutex_unlock(&thermal_list_lock); 248 } 249 250 tz->tc1 = 1; 251 tz->tc2 = 1; 252 253 if (!tz->passive_delay) 254 tz->passive_delay = 1000; 255 256 if (!tz->polling_delay) 257 tz->polling_delay = 10000; 258 259 tz->forced_passive = state; 260 261 thermal_zone_device_update(tz); 262 263 return count; 264} 265 266static ssize_t 267passive_show(struct device *dev, struct device_attribute *attr, 268 char *buf) 269{ 270 struct thermal_zone_device *tz = to_thermal_zone(dev); 271 272 return sprintf(buf, "%d\n", tz->forced_passive); 273} 274 275static DEVICE_ATTR(type, 0444, type_show, NULL); 276static DEVICE_ATTR(temp, 0444, temp_show, NULL); 277static DEVICE_ATTR(mode, 0644, mode_show, mode_store); 278static DEVICE_ATTR(passive, S_IRUGO | S_IWUSR, passive_show, \ 279 passive_store); 280 281static struct device_attribute trip_point_attrs[] = { 282 __ATTR(trip_point_0_type, 0444, trip_point_type_show, NULL), 283 __ATTR(trip_point_0_temp, 0444, trip_point_temp_show, NULL), 284 __ATTR(trip_point_1_type, 0444, trip_point_type_show, NULL), 285 __ATTR(trip_point_1_temp, 0444, trip_point_temp_show, NULL), 286 __ATTR(trip_point_2_type, 0444, trip_point_type_show, NULL), 287 __ATTR(trip_point_2_temp, 0444, trip_point_temp_show, NULL), 288 __ATTR(trip_point_3_type, 0444, trip_point_type_show, NULL), 289 __ATTR(trip_point_3_temp, 0444, trip_point_temp_show, NULL), 290 __ATTR(trip_point_4_type, 0444, trip_point_type_show, NULL), 291 __ATTR(trip_point_4_temp, 0444, trip_point_temp_show, NULL), 292 __ATTR(trip_point_5_type, 0444, trip_point_type_show, NULL), 293 __ATTR(trip_point_5_temp, 0444, trip_point_temp_show, NULL), 294 __ATTR(trip_point_6_type, 0444, trip_point_type_show, NULL), 295 __ATTR(trip_point_6_temp, 0444, trip_point_temp_show, NULL), 296 __ATTR(trip_point_7_type, 0444, trip_point_type_show, NULL), 297 __ATTR(trip_point_7_temp, 0444, trip_point_temp_show, NULL), 298 __ATTR(trip_point_8_type, 0444, trip_point_type_show, NULL), 299 __ATTR(trip_point_8_temp, 0444, trip_point_temp_show, NULL), 300 __ATTR(trip_point_9_type, 0444, trip_point_type_show, NULL), 301 __ATTR(trip_point_9_temp, 0444, trip_point_temp_show, NULL), 302 __ATTR(trip_point_10_type, 0444, trip_point_type_show, NULL), 303 __ATTR(trip_point_10_temp, 0444, trip_point_temp_show, NULL), 304 __ATTR(trip_point_11_type, 0444, trip_point_type_show, NULL), 305 __ATTR(trip_point_11_temp, 0444, trip_point_temp_show, NULL), 306}; 307 308#define TRIP_POINT_ATTR_ADD(_dev, _index, result) \ 309do { \ 310 result = device_create_file(_dev, \ 311 &trip_point_attrs[_index * 2]); \ 312 if (result) \ 313 break; \ 314 result = device_create_file(_dev, \ 315 &trip_point_attrs[_index * 2 + 1]); \ 316} while (0) 317 318#define TRIP_POINT_ATTR_REMOVE(_dev, _index) \ 319do { \ 320 device_remove_file(_dev, &trip_point_attrs[_index * 2]); \ 321 device_remove_file(_dev, &trip_point_attrs[_index * 2 + 1]); \ 322} while (0) 323 324/* sys I/F for cooling device */ 325#define to_cooling_device(_dev) \ 326 container_of(_dev, struct thermal_cooling_device, device) 327 328static ssize_t 329thermal_cooling_device_type_show(struct device *dev, 330 struct device_attribute *attr, char *buf) 331{ 332 struct thermal_cooling_device *cdev = to_cooling_device(dev); 333 334 return sprintf(buf, "%s\n", cdev->type); 335} 336 337static ssize_t 338thermal_cooling_device_max_state_show(struct device *dev, 339 struct device_attribute *attr, char *buf) 340{ 341 struct thermal_cooling_device *cdev = to_cooling_device(dev); 342 unsigned long state; 343 int ret; 344 345 ret = cdev->ops->get_max_state(cdev, &state); 346 if (ret) 347 return ret; 348 return sprintf(buf, "%ld\n", state); 349} 350 351static ssize_t 352thermal_cooling_device_cur_state_show(struct device *dev, 353 struct device_attribute *attr, char *buf) 354{ 355 struct thermal_cooling_device *cdev = to_cooling_device(dev); 356 unsigned long state; 357 int ret; 358 359 ret = cdev->ops->get_cur_state(cdev, &state); 360 if (ret) 361 return ret; 362 return sprintf(buf, "%ld\n", state); 363} 364 365static ssize_t 366thermal_cooling_device_cur_state_store(struct device *dev, 367 struct device_attribute *attr, 368 const char *buf, size_t count) 369{ 370 struct thermal_cooling_device *cdev = to_cooling_device(dev); 371 unsigned long state; 372 int result; 373 374 if (!sscanf(buf, "%ld\n", &state)) 375 return -EINVAL; 376 377 if (state < 0) 378 return -EINVAL; 379 380 result = cdev->ops->set_cur_state(cdev, state); 381 if (result) 382 return result; 383 return count; 384} 385 386static struct device_attribute dev_attr_cdev_type = 387__ATTR(type, 0444, thermal_cooling_device_type_show, NULL); 388static DEVICE_ATTR(max_state, 0444, 389 thermal_cooling_device_max_state_show, NULL); 390static DEVICE_ATTR(cur_state, 0644, 391 thermal_cooling_device_cur_state_show, 392 thermal_cooling_device_cur_state_store); 393 394static ssize_t 395thermal_cooling_device_trip_point_show(struct device *dev, 396 struct device_attribute *attr, char *buf) 397{ 398 struct thermal_cooling_device_instance *instance; 399 400 instance = 401 container_of(attr, struct thermal_cooling_device_instance, attr); 402 403 if (instance->trip == THERMAL_TRIPS_NONE) 404 return sprintf(buf, "-1\n"); 405 else 406 return sprintf(buf, "%d\n", instance->trip); 407} 408 409/* Device management */ 410 411#if defined(CONFIG_THERMAL_HWMON) 412 413/* hwmon sys I/F */ 414#include <linux/hwmon.h> 415static LIST_HEAD(thermal_hwmon_list); 416 417static ssize_t 418name_show(struct device *dev, struct device_attribute *attr, char *buf) 419{ 420 struct thermal_hwmon_device *hwmon = dev_get_drvdata(dev); 421 return sprintf(buf, "%s\n", hwmon->type); 422} 423static DEVICE_ATTR(name, 0444, name_show, NULL); 424 425static ssize_t 426temp_input_show(struct device *dev, struct device_attribute *attr, char *buf) 427{ 428 long temperature; 429 int ret; 430 struct thermal_hwmon_attr *hwmon_attr 431 = container_of(attr, struct thermal_hwmon_attr, attr); 432 struct thermal_zone_device *tz 433 = container_of(hwmon_attr, struct thermal_zone_device, 434 temp_input); 435 436 ret = tz->ops->get_temp(tz, &temperature); 437 438 if (ret) 439 return ret; 440 441 return sprintf(buf, "%ld\n", temperature); 442} 443 444static ssize_t 445temp_crit_show(struct device *dev, struct device_attribute *attr, 446 char *buf) 447{ 448 struct thermal_hwmon_attr *hwmon_attr 449 = container_of(attr, struct thermal_hwmon_attr, attr); 450 struct thermal_zone_device *tz 451 = container_of(hwmon_attr, struct thermal_zone_device, 452 temp_crit); 453 long temperature; 454 int ret; 455 456 ret = tz->ops->get_trip_temp(tz, 0, &temperature); 457 if (ret) 458 return ret; 459 460 return sprintf(buf, "%ld\n", temperature); 461} 462 463 464static int 465thermal_add_hwmon_sysfs(struct thermal_zone_device *tz) 466{ 467 struct thermal_hwmon_device *hwmon; 468 int new_hwmon_device = 1; 469 int result; 470 471 mutex_lock(&thermal_list_lock); 472 list_for_each_entry(hwmon, &thermal_hwmon_list, node) 473 if (!strcmp(hwmon->type, tz->type)) { 474 new_hwmon_device = 0; 475 mutex_unlock(&thermal_list_lock); 476 goto register_sys_interface; 477 } 478 mutex_unlock(&thermal_list_lock); 479 480 hwmon = kzalloc(sizeof(struct thermal_hwmon_device), GFP_KERNEL); 481 if (!hwmon) 482 return -ENOMEM; 483 484 INIT_LIST_HEAD(&hwmon->tz_list); 485 strlcpy(hwmon->type, tz->type, THERMAL_NAME_LENGTH); 486 hwmon->device = hwmon_device_register(NULL); 487 if (IS_ERR(hwmon->device)) { 488 result = PTR_ERR(hwmon->device); 489 goto free_mem; 490 } 491 dev_set_drvdata(hwmon->device, hwmon); 492 result = device_create_file(hwmon->device, &dev_attr_name); 493 if (result) 494 goto unregister_hwmon_device; 495 496 register_sys_interface: 497 tz->hwmon = hwmon; 498 hwmon->count++; 499 500 snprintf(tz->temp_input.name, THERMAL_NAME_LENGTH, 501 "temp%d_input", hwmon->count); 502 tz->temp_input.attr.attr.name = tz->temp_input.name; 503 tz->temp_input.attr.attr.mode = 0444; 504 tz->temp_input.attr.show = temp_input_show; 505 result = device_create_file(hwmon->device, &tz->temp_input.attr); 506 if (result) 507 goto unregister_hwmon_device; 508 509 if (tz->ops->get_crit_temp) { 510 unsigned long temperature; 511 if (!tz->ops->get_crit_temp(tz, &temperature)) { 512 snprintf(tz->temp_crit.name, THERMAL_NAME_LENGTH, 513 "temp%d_crit", hwmon->count); 514 tz->temp_crit.attr.attr.name = tz->temp_crit.name; 515 tz->temp_crit.attr.attr.mode = 0444; 516 tz->temp_crit.attr.show = temp_crit_show; 517 result = device_create_file(hwmon->device, 518 &tz->temp_crit.attr); 519 if (result) 520 goto unregister_hwmon_device; 521 } 522 } 523 524 mutex_lock(&thermal_list_lock); 525 if (new_hwmon_device) 526 list_add_tail(&hwmon->node, &thermal_hwmon_list); 527 list_add_tail(&tz->hwmon_node, &hwmon->tz_list); 528 mutex_unlock(&thermal_list_lock); 529 530 return 0; 531 532 unregister_hwmon_device: 533 device_remove_file(hwmon->device, &tz->temp_crit.attr); 534 device_remove_file(hwmon->device, &tz->temp_input.attr); 535 if (new_hwmon_device) { 536 device_remove_file(hwmon->device, &dev_attr_name); 537 hwmon_device_unregister(hwmon->device); 538 } 539 free_mem: 540 if (new_hwmon_device) 541 kfree(hwmon); 542 543 return result; 544} 545 546static void 547thermal_remove_hwmon_sysfs(struct thermal_zone_device *tz) 548{ 549 struct thermal_hwmon_device *hwmon = tz->hwmon; 550 551 tz->hwmon = NULL; 552 device_remove_file(hwmon->device, &tz->temp_input.attr); 553 device_remove_file(hwmon->device, &tz->temp_crit.attr); 554 555 mutex_lock(&thermal_list_lock); 556 list_del(&tz->hwmon_node); 557 if (!list_empty(&hwmon->tz_list)) { 558 mutex_unlock(&thermal_list_lock); 559 return; 560 } 561 list_del(&hwmon->node); 562 mutex_unlock(&thermal_list_lock); 563 564 device_remove_file(hwmon->device, &dev_attr_name); 565 hwmon_device_unregister(hwmon->device); 566 kfree(hwmon); 567} 568#else 569static int 570thermal_add_hwmon_sysfs(struct thermal_zone_device *tz) 571{ 572 return 0; 573} 574 575static void 576thermal_remove_hwmon_sysfs(struct thermal_zone_device *tz) 577{ 578} 579#endif 580 581static void thermal_zone_device_set_polling(struct thermal_zone_device *tz, 582 int delay) 583{ 584 cancel_delayed_work(&(tz->poll_queue)); 585 586 if (!delay) 587 return; 588 589 if (delay > 1000) 590 schedule_delayed_work(&(tz->poll_queue), 591 round_jiffies(msecs_to_jiffies(delay))); 592 else 593 schedule_delayed_work(&(tz->poll_queue), 594 msecs_to_jiffies(delay)); 595} 596 597static void thermal_zone_device_passive(struct thermal_zone_device *tz, 598 int temp, int trip_temp, int trip) 599{ 600 int trend = 0; 601 struct thermal_cooling_device_instance *instance; 602 struct thermal_cooling_device *cdev; 603 long state, max_state; 604 605 /* 606 * Above Trip? 607 * ----------- 608 * Calculate the thermal trend (using the passive cooling equation) 609 * and modify the performance limit for all passive cooling devices 610 * accordingly. Note that we assume symmetry. 611 */ 612 if (temp >= trip_temp) { 613 tz->passive = true; 614 615 trend = (tz->tc1 * (temp - tz->last_temperature)) + 616 (tz->tc2 * (temp - trip_temp)); 617 618 /* Heating up? */ 619 if (trend > 0) { 620 list_for_each_entry(instance, &tz->cooling_devices, 621 node) { 622 if (instance->trip != trip) 623 continue; 624 cdev = instance->cdev; 625 cdev->ops->get_cur_state(cdev, &state); 626 cdev->ops->get_max_state(cdev, &max_state); 627 if (state++ < max_state) 628 cdev->ops->set_cur_state(cdev, state); 629 } 630 } else if (trend < 0) { /* Cooling off? */ 631 list_for_each_entry(instance, &tz->cooling_devices, 632 node) { 633 if (instance->trip != trip) 634 continue; 635 cdev = instance->cdev; 636 cdev->ops->get_cur_state(cdev, &state); 637 cdev->ops->get_max_state(cdev, &max_state); 638 if (state > 0) 639 cdev->ops->set_cur_state(cdev, --state); 640 } 641 } 642 return; 643 } 644 645 /* 646 * Below Trip? 647 * ----------- 648 * Implement passive cooling hysteresis to slowly increase performance 649 * and avoid thrashing around the passive trip point. Note that we 650 * assume symmetry. 651 */ 652 list_for_each_entry(instance, &tz->cooling_devices, node) { 653 if (instance->trip != trip) 654 continue; 655 cdev = instance->cdev; 656 cdev->ops->get_cur_state(cdev, &state); 657 cdev->ops->get_max_state(cdev, &max_state); 658 if (state > 0) 659 cdev->ops->set_cur_state(cdev, --state); 660 if (state == 0) 661 tz->passive = false; 662 } 663} 664 665static void thermal_zone_device_check(struct work_struct *work) 666{ 667 struct thermal_zone_device *tz = container_of(work, struct 668 thermal_zone_device, 669 poll_queue.work); 670 thermal_zone_device_update(tz); 671} 672 673/** 674 * thermal_zone_bind_cooling_device - bind a cooling device to a thermal zone 675 * @tz: thermal zone device 676 * @trip: indicates which trip point the cooling devices is 677 * associated with in this thermal zone. 678 * @cdev: thermal cooling device 679 * 680 * This function is usually called in the thermal zone device .bind callback. 681 */ 682int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz, 683 int trip, 684 struct thermal_cooling_device *cdev) 685{ 686 struct thermal_cooling_device_instance *dev; 687 struct thermal_cooling_device_instance *pos; 688 struct thermal_zone_device *pos1; 689 struct thermal_cooling_device *pos2; 690 int result; 691 692 if (trip >= tz->trips || (trip < 0 && trip != THERMAL_TRIPS_NONE)) 693 return -EINVAL; 694 695 list_for_each_entry(pos1, &thermal_tz_list, node) { 696 if (pos1 == tz) 697 break; 698 } 699 list_for_each_entry(pos2, &thermal_cdev_list, node) { 700 if (pos2 == cdev) 701 break; 702 } 703 704 if (tz != pos1 || cdev != pos2) 705 return -EINVAL; 706 707 dev = 708 kzalloc(sizeof(struct thermal_cooling_device_instance), GFP_KERNEL); 709 if (!dev) 710 return -ENOMEM; 711 dev->tz = tz; 712 dev->cdev = cdev; 713 dev->trip = trip; 714 result = get_idr(&tz->idr, &tz->lock, &dev->id); 715 if (result) 716 goto free_mem; 717 718 sprintf(dev->name, "cdev%d", dev->id); 719 result = 720 sysfs_create_link(&tz->device.kobj, &cdev->device.kobj, dev->name); 721 if (result) 722 goto release_idr; 723 724 sprintf(dev->attr_name, "cdev%d_trip_point", dev->id); 725 dev->attr.attr.name = dev->attr_name; 726 dev->attr.attr.mode = 0444; 727 dev->attr.show = thermal_cooling_device_trip_point_show; 728 result = device_create_file(&tz->device, &dev->attr); 729 if (result) 730 goto remove_symbol_link; 731 732 mutex_lock(&tz->lock); 733 list_for_each_entry(pos, &tz->cooling_devices, node) 734 if (pos->tz == tz && pos->trip == trip && pos->cdev == cdev) { 735 result = -EEXIST; 736 break; 737 } 738 if (!result) 739 list_add_tail(&dev->node, &tz->cooling_devices); 740 mutex_unlock(&tz->lock); 741 742 if (!result) 743 return 0; 744 745 device_remove_file(&tz->device, &dev->attr); 746 remove_symbol_link: 747 sysfs_remove_link(&tz->device.kobj, dev->name); 748 release_idr: 749 release_idr(&tz->idr, &tz->lock, dev->id); 750 free_mem: 751 kfree(dev); 752 return result; 753} 754 755EXPORT_SYMBOL(thermal_zone_bind_cooling_device); 756 757/** 758 * thermal_zone_unbind_cooling_device - unbind a cooling device from a thermal zone 759 * @tz: thermal zone device 760 * @trip: indicates which trip point the cooling devices is 761 * associated with in this thermal zone. 762 * @cdev: thermal cooling device 763 * 764 * This function is usually called in the thermal zone device .unbind callback. 765 */ 766int thermal_zone_unbind_cooling_device(struct thermal_zone_device *tz, 767 int trip, 768 struct thermal_cooling_device *cdev) 769{ 770 struct thermal_cooling_device_instance *pos, *next; 771 772 mutex_lock(&tz->lock); 773 list_for_each_entry_safe(pos, next, &tz->cooling_devices, node) { 774 if (pos->tz == tz && pos->trip == trip && pos->cdev == cdev) { 775 list_del(&pos->node); 776 mutex_unlock(&tz->lock); 777 goto unbind; 778 } 779 } 780 mutex_unlock(&tz->lock); 781 782 return -ENODEV; 783 784 unbind: 785 device_remove_file(&tz->device, &pos->attr); 786 sysfs_remove_link(&tz->device.kobj, pos->name); 787 release_idr(&tz->idr, &tz->lock, pos->id); 788 kfree(pos); 789 return 0; 790} 791 792EXPORT_SYMBOL(thermal_zone_unbind_cooling_device); 793 794static void thermal_release(struct device *dev) 795{ 796 struct thermal_zone_device *tz; 797 struct thermal_cooling_device *cdev; 798 799 if (!strncmp(dev_name(dev), "thermal_zone", sizeof "thermal_zone" - 1)) { 800 tz = to_thermal_zone(dev); 801 kfree(tz); 802 } else { 803 cdev = to_cooling_device(dev); 804 kfree(cdev); 805 } 806} 807 808static struct class thermal_class = { 809 .name = "thermal", 810 .dev_release = thermal_release, 811}; 812 813/** 814 * thermal_cooling_device_register - register a new thermal cooling device 815 * @type: the thermal cooling device type. 816 * @devdata: device private data. 817 * @ops: standard thermal cooling devices callbacks. 818 */ 819struct thermal_cooling_device *thermal_cooling_device_register(char *type, 820 void *devdata, 821 struct 822 thermal_cooling_device_ops 823 *ops) 824{ 825 struct thermal_cooling_device *cdev; 826 struct thermal_zone_device *pos; 827 int result; 828 829 if (strlen(type) >= THERMAL_NAME_LENGTH) 830 return ERR_PTR(-EINVAL); 831 832 if (!ops || !ops->get_max_state || !ops->get_cur_state || 833 !ops->set_cur_state) 834 return ERR_PTR(-EINVAL); 835 836 cdev = kzalloc(sizeof(struct thermal_cooling_device), GFP_KERNEL); 837 if (!cdev) 838 return ERR_PTR(-ENOMEM); 839 840 result = get_idr(&thermal_cdev_idr, &thermal_idr_lock, &cdev->id); 841 if (result) { 842 kfree(cdev); 843 return ERR_PTR(result); 844 } 845 846 strcpy(cdev->type, type); 847 cdev->ops = ops; 848 cdev->device.class = &thermal_class; 849 cdev->devdata = devdata; 850 dev_set_name(&cdev->device, "cooling_device%d", cdev->id); 851 result = device_register(&cdev->device); 852 if (result) { 853 release_idr(&thermal_cdev_idr, &thermal_idr_lock, cdev->id); 854 kfree(cdev); 855 return ERR_PTR(result); 856 } 857 858 /* sys I/F */ 859 if (type) { 860 result = device_create_file(&cdev->device, &dev_attr_cdev_type); 861 if (result) 862 goto unregister; 863 } 864 865 result = device_create_file(&cdev->device, &dev_attr_max_state); 866 if (result) 867 goto unregister; 868 869 result = device_create_file(&cdev->device, &dev_attr_cur_state); 870 if (result) 871 goto unregister; 872 873 mutex_lock(&thermal_list_lock); 874 list_add(&cdev->node, &thermal_cdev_list); 875 list_for_each_entry(pos, &thermal_tz_list, node) { 876 if (!pos->ops->bind) 877 continue; 878 result = pos->ops->bind(pos, cdev); 879 if (result) 880 break; 881 882 } 883 mutex_unlock(&thermal_list_lock); 884 885 if (!result) 886 return cdev; 887 888 unregister: 889 release_idr(&thermal_cdev_idr, &thermal_idr_lock, cdev->id); 890 device_unregister(&cdev->device); 891 return ERR_PTR(result); 892} 893 894EXPORT_SYMBOL(thermal_cooling_device_register); 895 896/** 897 * thermal_cooling_device_unregister - removes the registered thermal cooling device 898 * @cdev: the thermal cooling device to remove. 899 * 900 * thermal_cooling_device_unregister() must be called when the device is no 901 * longer needed. 902 */ 903void thermal_cooling_device_unregister(struct 904 thermal_cooling_device 905 *cdev) 906{ 907 struct thermal_zone_device *tz; 908 struct thermal_cooling_device *pos = NULL; 909 910 if (!cdev) 911 return; 912 913 mutex_lock(&thermal_list_lock); 914 list_for_each_entry(pos, &thermal_cdev_list, node) 915 if (pos == cdev) 916 break; 917 if (pos != cdev) { 918 /* thermal cooling device not found */ 919 mutex_unlock(&thermal_list_lock); 920 return; 921 } 922 list_del(&cdev->node); 923 list_for_each_entry(tz, &thermal_tz_list, node) { 924 if (!tz->ops->unbind) 925 continue; 926 tz->ops->unbind(tz, cdev); 927 } 928 mutex_unlock(&thermal_list_lock); 929 if (cdev->type[0]) 930 device_remove_file(&cdev->device, &dev_attr_cdev_type); 931 device_remove_file(&cdev->device, &dev_attr_max_state); 932 device_remove_file(&cdev->device, &dev_attr_cur_state); 933 934 release_idr(&thermal_cdev_idr, &thermal_idr_lock, cdev->id); 935 device_unregister(&cdev->device); 936 return; 937} 938 939EXPORT_SYMBOL(thermal_cooling_device_unregister); 940 941/** 942 * thermal_zone_device_update - force an update of a thermal zone's state 943 * @ttz: the thermal zone to update 944 */ 945 946void thermal_zone_device_update(struct thermal_zone_device *tz) 947{ 948 int count, ret = 0; 949 long temp, trip_temp; 950 enum thermal_trip_type trip_type; 951 struct thermal_cooling_device_instance *instance; 952 struct thermal_cooling_device *cdev; 953 954 mutex_lock(&tz->lock); 955 956 if (tz->ops->get_temp(tz, &temp)) { 957 /* get_temp failed - retry it later */ 958 printk(KERN_WARNING PREFIX "failed to read out thermal zone " 959 "%d\n", tz->id); 960 goto leave; 961 } 962 963 for (count = 0; count < tz->trips; count++) { 964 tz->ops->get_trip_type(tz, count, &trip_type); 965 tz->ops->get_trip_temp(tz, count, &trip_temp); 966 967 switch (trip_type) { 968 case THERMAL_TRIP_CRITICAL: 969 if (temp >= trip_temp) { 970 if (tz->ops->notify) 971 ret = tz->ops->notify(tz, count, 972 trip_type); 973 if (!ret) { 974 printk(KERN_EMERG 975 "Critical temperature reached (%ld C), shutting down.\n", 976 temp/1000); 977 orderly_poweroff(true); 978 } 979 } 980 break; 981 case THERMAL_TRIP_HOT: 982 if (temp >= trip_temp) 983 if (tz->ops->notify) 984 tz->ops->notify(tz, count, trip_type); 985 break; 986 case THERMAL_TRIP_ACTIVE: 987 list_for_each_entry(instance, &tz->cooling_devices, 988 node) { 989 if (instance->trip != count) 990 continue; 991 992 cdev = instance->cdev; 993 994 if (temp >= trip_temp) 995 cdev->ops->set_cur_state(cdev, 1); 996 else 997 cdev->ops->set_cur_state(cdev, 0); 998 } 999 break; 1000 case THERMAL_TRIP_PASSIVE: 1001 if (temp >= trip_temp || tz->passive) 1002 thermal_zone_device_passive(tz, temp, 1003 trip_temp, count); 1004 break; 1005 } 1006 } 1007 1008 if (tz->forced_passive) 1009 thermal_zone_device_passive(tz, temp, tz->forced_passive, 1010 THERMAL_TRIPS_NONE); 1011 1012 tz->last_temperature = temp; 1013 1014 leave: 1015 if (tz->passive) 1016 thermal_zone_device_set_polling(tz, tz->passive_delay); 1017 else if (tz->polling_delay) 1018 thermal_zone_device_set_polling(tz, tz->polling_delay); 1019 mutex_unlock(&tz->lock); 1020} 1021EXPORT_SYMBOL(thermal_zone_device_update); 1022 1023/** 1024 * thermal_zone_device_register - register a new thermal zone device 1025 * @type: the thermal zone device type 1026 * @trips: the number of trip points the thermal zone support 1027 * @devdata: private device data 1028 * @ops: standard thermal zone device callbacks 1029 * @tc1: thermal coefficient 1 for passive calculations 1030 * @tc2: thermal coefficient 2 for passive calculations 1031 * @passive_delay: number of milliseconds to wait between polls when 1032 * performing passive cooling 1033 * @polling_delay: number of milliseconds to wait between polls when checking 1034 * whether trip points have been crossed (0 for interrupt 1035 * driven systems) 1036 * 1037 * thermal_zone_device_unregister() must be called when the device is no 1038 * longer needed. The passive cooling formula uses tc1 and tc2 as described in 1039 * section 11.1.5.1 of the ACPI specification 3.0. 1040 */ 1041struct thermal_zone_device *thermal_zone_device_register(char *type, 1042 int trips, 1043 void *devdata, struct 1044 thermal_zone_device_ops 1045 *ops, int tc1, int 1046 tc2, 1047 int passive_delay, 1048 int polling_delay) 1049{ 1050 struct thermal_zone_device *tz; 1051 struct thermal_cooling_device *pos; 1052 enum thermal_trip_type trip_type; 1053 int result; 1054 int count; 1055 int passive = 0; 1056 1057 if (strlen(type) >= THERMAL_NAME_LENGTH) 1058 return ERR_PTR(-EINVAL); 1059 1060 if (trips > THERMAL_MAX_TRIPS || trips < 0) 1061 return ERR_PTR(-EINVAL); 1062 1063 if (!ops || !ops->get_temp) 1064 return ERR_PTR(-EINVAL); 1065 1066 tz = kzalloc(sizeof(struct thermal_zone_device), GFP_KERNEL); 1067 if (!tz) 1068 return ERR_PTR(-ENOMEM); 1069 1070 INIT_LIST_HEAD(&tz->cooling_devices); 1071 idr_init(&tz->idr); 1072 mutex_init(&tz->lock); 1073 result = get_idr(&thermal_tz_idr, &thermal_idr_lock, &tz->id); 1074 if (result) { 1075 kfree(tz); 1076 return ERR_PTR(result); 1077 } 1078 1079 strcpy(tz->type, type); 1080 tz->ops = ops; 1081 tz->device.class = &thermal_class; 1082 tz->devdata = devdata; 1083 tz->trips = trips; 1084 tz->tc1 = tc1; 1085 tz->tc2 = tc2; 1086 tz->passive_delay = passive_delay; 1087 tz->polling_delay = polling_delay; 1088 1089 dev_set_name(&tz->device, "thermal_zone%d", tz->id); 1090 result = device_register(&tz->device); 1091 if (result) { 1092 release_idr(&thermal_tz_idr, &thermal_idr_lock, tz->id); 1093 kfree(tz); 1094 return ERR_PTR(result); 1095 } 1096 1097 /* sys I/F */ 1098 if (type) { 1099 result = device_create_file(&tz->device, &dev_attr_type); 1100 if (result) 1101 goto unregister; 1102 } 1103 1104 result = device_create_file(&tz->device, &dev_attr_temp); 1105 if (result) 1106 goto unregister; 1107 1108 if (ops->get_mode) { 1109 result = device_create_file(&tz->device, &dev_attr_mode); 1110 if (result) 1111 goto unregister; 1112 } 1113 1114 for (count = 0; count < trips; count++) { 1115 TRIP_POINT_ATTR_ADD(&tz->device, count, result); 1116 if (result) 1117 goto unregister; 1118 tz->ops->get_trip_type(tz, count, &trip_type); 1119 if (trip_type == THERMAL_TRIP_PASSIVE) 1120 passive = 1; 1121 } 1122 1123 if (!passive) 1124 result = device_create_file(&tz->device, 1125 &dev_attr_passive); 1126 1127 if (result) 1128 goto unregister; 1129 1130 result = thermal_add_hwmon_sysfs(tz); 1131 if (result) 1132 goto unregister; 1133 1134 mutex_lock(&thermal_list_lock); 1135 list_add_tail(&tz->node, &thermal_tz_list); 1136 if (ops->bind) 1137 list_for_each_entry(pos, &thermal_cdev_list, node) { 1138 result = ops->bind(tz, pos); 1139 if (result) 1140 break; 1141 } 1142 mutex_unlock(&thermal_list_lock); 1143 1144 INIT_DELAYED_WORK(&(tz->poll_queue), thermal_zone_device_check); 1145 1146 thermal_zone_device_update(tz); 1147 1148 if (!result) 1149 return tz; 1150 1151 unregister: 1152 release_idr(&thermal_tz_idr, &thermal_idr_lock, tz->id); 1153 device_unregister(&tz->device); 1154 return ERR_PTR(result); 1155} 1156 1157EXPORT_SYMBOL(thermal_zone_device_register); 1158 1159/** 1160 * thermal_device_unregister - removes the registered thermal zone device 1161 * @tz: the thermal zone device to remove 1162 */ 1163void thermal_zone_device_unregister(struct thermal_zone_device *tz) 1164{ 1165 struct thermal_cooling_device *cdev; 1166 struct thermal_zone_device *pos = NULL; 1167 int count; 1168 1169 if (!tz) 1170 return; 1171 1172 mutex_lock(&thermal_list_lock); 1173 list_for_each_entry(pos, &thermal_tz_list, node) 1174 if (pos == tz) 1175 break; 1176 if (pos != tz) { 1177 /* thermal zone device not found */ 1178 mutex_unlock(&thermal_list_lock); 1179 return; 1180 } 1181 list_del(&tz->node); 1182 if (tz->ops->unbind) 1183 list_for_each_entry(cdev, &thermal_cdev_list, node) 1184 tz->ops->unbind(tz, cdev); 1185 mutex_unlock(&thermal_list_lock); 1186 1187 thermal_zone_device_set_polling(tz, 0); 1188 1189 if (tz->type[0]) 1190 device_remove_file(&tz->device, &dev_attr_type); 1191 device_remove_file(&tz->device, &dev_attr_temp); 1192 if (tz->ops->get_mode) 1193 device_remove_file(&tz->device, &dev_attr_mode); 1194 1195 for (count = 0; count < tz->trips; count++) 1196 TRIP_POINT_ATTR_REMOVE(&tz->device, count); 1197 1198 thermal_remove_hwmon_sysfs(tz); 1199 release_idr(&thermal_tz_idr, &thermal_idr_lock, tz->id); 1200 idr_destroy(&tz->idr); 1201 mutex_destroy(&tz->lock); 1202 device_unregister(&tz->device); 1203 return; 1204} 1205 1206EXPORT_SYMBOL(thermal_zone_device_unregister); 1207 1208static int __init thermal_init(void) 1209{ 1210 int result = 0; 1211 1212 result = class_register(&thermal_class); 1213 if (result) { 1214 idr_destroy(&thermal_tz_idr); 1215 idr_destroy(&thermal_cdev_idr); 1216 mutex_destroy(&thermal_idr_lock); 1217 mutex_destroy(&thermal_list_lock); 1218 } 1219 return result; 1220} 1221 1222static void __exit thermal_exit(void) 1223{ 1224 class_unregister(&thermal_class); 1225 idr_destroy(&thermal_tz_idr); 1226 idr_destroy(&thermal_cdev_idr); 1227 mutex_destroy(&thermal_idr_lock); 1228 mutex_destroy(&thermal_list_lock); 1229} 1230 1231subsys_initcall(thermal_init); 1232module_exit(thermal_exit);