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.28-rc5 1892 lines 49 kB view raw
1/* 2 * acpi_thermal.c - ACPI Thermal Zone Driver ($Revision: 41 $) 3 * 4 * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com> 5 * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> 6 * 7 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License as published by 11 * the Free Software Foundation; either version 2 of the License, or (at 12 * your option) any later version. 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 * This driver fully implements the ACPI thermal policy as described in the 26 * ACPI 2.0 Specification. 27 * 28 * TBD: 1. Implement passive cooling hysteresis. 29 * 2. Enhance passive cooling (CPU) states/limit interface to support 30 * concepts of 'multiple limiters', upper/lower limits, etc. 31 * 32 */ 33 34#include <linux/kernel.h> 35#include <linux/module.h> 36#include <linux/dmi.h> 37#include <linux/init.h> 38#include <linux/types.h> 39#include <linux/proc_fs.h> 40#include <linux/timer.h> 41#include <linux/jiffies.h> 42#include <linux/kmod.h> 43#include <linux/seq_file.h> 44#include <linux/reboot.h> 45#include <asm/uaccess.h> 46#include <linux/thermal.h> 47#include <acpi/acpi_bus.h> 48#include <acpi/acpi_drivers.h> 49 50#define ACPI_THERMAL_CLASS "thermal_zone" 51#define ACPI_THERMAL_DEVICE_NAME "Thermal Zone" 52#define ACPI_THERMAL_FILE_STATE "state" 53#define ACPI_THERMAL_FILE_TEMPERATURE "temperature" 54#define ACPI_THERMAL_FILE_TRIP_POINTS "trip_points" 55#define ACPI_THERMAL_FILE_COOLING_MODE "cooling_mode" 56#define ACPI_THERMAL_FILE_POLLING_FREQ "polling_frequency" 57#define ACPI_THERMAL_NOTIFY_TEMPERATURE 0x80 58#define ACPI_THERMAL_NOTIFY_THRESHOLDS 0x81 59#define ACPI_THERMAL_NOTIFY_DEVICES 0x82 60#define ACPI_THERMAL_NOTIFY_CRITICAL 0xF0 61#define ACPI_THERMAL_NOTIFY_HOT 0xF1 62#define ACPI_THERMAL_MODE_ACTIVE 0x00 63 64#define ACPI_THERMAL_MAX_ACTIVE 10 65#define ACPI_THERMAL_MAX_LIMIT_STR_LEN 65 66 67#define _COMPONENT ACPI_THERMAL_COMPONENT 68ACPI_MODULE_NAME("thermal"); 69 70MODULE_AUTHOR("Paul Diefenbaugh"); 71MODULE_DESCRIPTION("ACPI Thermal Zone Driver"); 72MODULE_LICENSE("GPL"); 73 74static int act; 75module_param(act, int, 0644); 76MODULE_PARM_DESC(act, "Disable or override all lowest active trip points."); 77 78static int crt; 79module_param(crt, int, 0644); 80MODULE_PARM_DESC(crt, "Disable or lower all critical trip points."); 81 82static int tzp; 83module_param(tzp, int, 0444); 84MODULE_PARM_DESC(tzp, "Thermal zone polling frequency, in 1/10 seconds."); 85 86static int nocrt; 87module_param(nocrt, int, 0); 88MODULE_PARM_DESC(nocrt, "Set to take no action upon ACPI thermal zone critical trips points."); 89 90static int off; 91module_param(off, int, 0); 92MODULE_PARM_DESC(off, "Set to disable ACPI thermal support."); 93 94static int psv; 95module_param(psv, int, 0644); 96MODULE_PARM_DESC(psv, "Disable or override all passive trip points."); 97 98static int acpi_thermal_add(struct acpi_device *device); 99static int acpi_thermal_remove(struct acpi_device *device, int type); 100static int acpi_thermal_resume(struct acpi_device *device); 101static int acpi_thermal_state_open_fs(struct inode *inode, struct file *file); 102static int acpi_thermal_temp_open_fs(struct inode *inode, struct file *file); 103static int acpi_thermal_trip_open_fs(struct inode *inode, struct file *file); 104static int acpi_thermal_cooling_open_fs(struct inode *inode, struct file *file); 105static ssize_t acpi_thermal_write_cooling_mode(struct file *, 106 const char __user *, size_t, 107 loff_t *); 108static int acpi_thermal_polling_open_fs(struct inode *inode, struct file *file); 109static ssize_t acpi_thermal_write_polling(struct file *, const char __user *, 110 size_t, loff_t *); 111 112static const struct acpi_device_id thermal_device_ids[] = { 113 {ACPI_THERMAL_HID, 0}, 114 {"", 0}, 115}; 116MODULE_DEVICE_TABLE(acpi, thermal_device_ids); 117 118static struct acpi_driver acpi_thermal_driver = { 119 .name = "thermal", 120 .class = ACPI_THERMAL_CLASS, 121 .ids = thermal_device_ids, 122 .ops = { 123 .add = acpi_thermal_add, 124 .remove = acpi_thermal_remove, 125 .resume = acpi_thermal_resume, 126 }, 127}; 128 129struct acpi_thermal_state { 130 u8 critical:1; 131 u8 hot:1; 132 u8 passive:1; 133 u8 active:1; 134 u8 reserved:4; 135 int active_index; 136}; 137 138struct acpi_thermal_state_flags { 139 u8 valid:1; 140 u8 enabled:1; 141 u8 reserved:6; 142}; 143 144struct acpi_thermal_critical { 145 struct acpi_thermal_state_flags flags; 146 unsigned long temperature; 147}; 148 149struct acpi_thermal_hot { 150 struct acpi_thermal_state_flags flags; 151 unsigned long temperature; 152}; 153 154struct acpi_thermal_passive { 155 struct acpi_thermal_state_flags flags; 156 unsigned long temperature; 157 unsigned long tc1; 158 unsigned long tc2; 159 unsigned long tsp; 160 struct acpi_handle_list devices; 161}; 162 163struct acpi_thermal_active { 164 struct acpi_thermal_state_flags flags; 165 unsigned long temperature; 166 struct acpi_handle_list devices; 167}; 168 169struct acpi_thermal_trips { 170 struct acpi_thermal_critical critical; 171 struct acpi_thermal_hot hot; 172 struct acpi_thermal_passive passive; 173 struct acpi_thermal_active active[ACPI_THERMAL_MAX_ACTIVE]; 174}; 175 176struct acpi_thermal_flags { 177 u8 cooling_mode:1; /* _SCP */ 178 u8 devices:1; /* _TZD */ 179 u8 reserved:6; 180}; 181 182struct acpi_thermal { 183 struct acpi_device * device; 184 acpi_bus_id name; 185 unsigned long temperature; 186 unsigned long last_temperature; 187 unsigned long polling_frequency; 188 volatile u8 zombie; 189 struct acpi_thermal_flags flags; 190 struct acpi_thermal_state state; 191 struct acpi_thermal_trips trips; 192 struct acpi_handle_list devices; 193 struct timer_list timer; 194 struct thermal_zone_device *thermal_zone; 195 int tz_enabled; 196 struct mutex lock; 197}; 198 199static const struct file_operations acpi_thermal_state_fops = { 200 .owner = THIS_MODULE, 201 .open = acpi_thermal_state_open_fs, 202 .read = seq_read, 203 .llseek = seq_lseek, 204 .release = single_release, 205}; 206 207static const struct file_operations acpi_thermal_temp_fops = { 208 .owner = THIS_MODULE, 209 .open = acpi_thermal_temp_open_fs, 210 .read = seq_read, 211 .llseek = seq_lseek, 212 .release = single_release, 213}; 214 215static const struct file_operations acpi_thermal_trip_fops = { 216 .owner = THIS_MODULE, 217 .open = acpi_thermal_trip_open_fs, 218 .read = seq_read, 219 .llseek = seq_lseek, 220 .release = single_release, 221}; 222 223static const struct file_operations acpi_thermal_cooling_fops = { 224 .owner = THIS_MODULE, 225 .open = acpi_thermal_cooling_open_fs, 226 .read = seq_read, 227 .write = acpi_thermal_write_cooling_mode, 228 .llseek = seq_lseek, 229 .release = single_release, 230}; 231 232static const struct file_operations acpi_thermal_polling_fops = { 233 .owner = THIS_MODULE, 234 .open = acpi_thermal_polling_open_fs, 235 .read = seq_read, 236 .write = acpi_thermal_write_polling, 237 .llseek = seq_lseek, 238 .release = single_release, 239}; 240 241/* -------------------------------------------------------------------------- 242 Thermal Zone Management 243 -------------------------------------------------------------------------- */ 244 245static int acpi_thermal_get_temperature(struct acpi_thermal *tz) 246{ 247 acpi_status status = AE_OK; 248 unsigned long long tmp; 249 250 if (!tz) 251 return -EINVAL; 252 253 tz->last_temperature = tz->temperature; 254 255 status = acpi_evaluate_integer(tz->device->handle, "_TMP", NULL, &tmp); 256 if (ACPI_FAILURE(status)) 257 return -ENODEV; 258 259 tz->temperature = tmp; 260 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Temperature is %lu dK\n", 261 tz->temperature)); 262 263 return 0; 264} 265 266static int acpi_thermal_get_polling_frequency(struct acpi_thermal *tz) 267{ 268 acpi_status status = AE_OK; 269 unsigned long long tmp; 270 271 if (!tz) 272 return -EINVAL; 273 274 status = acpi_evaluate_integer(tz->device->handle, "_TZP", NULL, &tmp); 275 if (ACPI_FAILURE(status)) 276 return -ENODEV; 277 278 tz->polling_frequency = tmp; 279 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Polling frequency is %lu dS\n", 280 tz->polling_frequency)); 281 282 return 0; 283} 284 285static int acpi_thermal_set_polling(struct acpi_thermal *tz, int seconds) 286{ 287 288 if (!tz) 289 return -EINVAL; 290 291 tz->polling_frequency = seconds * 10; /* Convert value to deci-seconds */ 292 293 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 294 "Polling frequency set to %lu seconds\n", 295 tz->polling_frequency/10)); 296 297 return 0; 298} 299 300static int acpi_thermal_set_cooling_mode(struct acpi_thermal *tz, int mode) 301{ 302 acpi_status status = AE_OK; 303 union acpi_object arg0 = { ACPI_TYPE_INTEGER }; 304 struct acpi_object_list arg_list = { 1, &arg0 }; 305 acpi_handle handle = NULL; 306 307 308 if (!tz) 309 return -EINVAL; 310 311 status = acpi_get_handle(tz->device->handle, "_SCP", &handle); 312 if (ACPI_FAILURE(status)) { 313 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "_SCP not present\n")); 314 return -ENODEV; 315 } 316 317 arg0.integer.value = mode; 318 319 status = acpi_evaluate_object(handle, NULL, &arg_list, NULL); 320 if (ACPI_FAILURE(status)) 321 return -ENODEV; 322 323 return 0; 324} 325 326#define ACPI_TRIPS_CRITICAL 0x01 327#define ACPI_TRIPS_HOT 0x02 328#define ACPI_TRIPS_PASSIVE 0x04 329#define ACPI_TRIPS_ACTIVE 0x08 330#define ACPI_TRIPS_DEVICES 0x10 331 332#define ACPI_TRIPS_REFRESH_THRESHOLDS (ACPI_TRIPS_PASSIVE | ACPI_TRIPS_ACTIVE) 333#define ACPI_TRIPS_REFRESH_DEVICES ACPI_TRIPS_DEVICES 334 335#define ACPI_TRIPS_INIT (ACPI_TRIPS_CRITICAL | ACPI_TRIPS_HOT | \ 336 ACPI_TRIPS_PASSIVE | ACPI_TRIPS_ACTIVE | \ 337 ACPI_TRIPS_DEVICES) 338 339/* 340 * This exception is thrown out in two cases: 341 * 1.An invalid trip point becomes invalid or a valid trip point becomes invalid 342 * when re-evaluating the AML code. 343 * 2.TODO: Devices listed in _PSL, _ALx, _TZD may change. 344 * We need to re-bind the cooling devices of a thermal zone when this occurs. 345 */ 346#define ACPI_THERMAL_TRIPS_EXCEPTION(flags, str) \ 347do { \ 348 if (flags != ACPI_TRIPS_INIT) \ 349 ACPI_EXCEPTION((AE_INFO, AE_ERROR, \ 350 "ACPI thermal trip point %s changed\n" \ 351 "Please send acpidump to linux-acpi@vger.kernel.org\n", str)); \ 352} while (0) 353 354static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag) 355{ 356 acpi_status status = AE_OK; 357 unsigned long long tmp; 358 struct acpi_handle_list devices; 359 int valid = 0; 360 int i; 361 362 /* Critical Shutdown (required) */ 363 if (flag & ACPI_TRIPS_CRITICAL) { 364 status = acpi_evaluate_integer(tz->device->handle, 365 "_CRT", NULL, &tmp); 366 tz->trips.critical.temperature = tmp; 367 /* 368 * Treat freezing temperatures as invalid as well; some 369 * BIOSes return really low values and cause reboots at startup. 370 * Below zero (Celcius) values clearly aren't right for sure.. 371 * ... so lets discard those as invalid. 372 */ 373 if (ACPI_FAILURE(status) || 374 tz->trips.critical.temperature <= 2732) { 375 tz->trips.critical.flags.valid = 0; 376 ACPI_EXCEPTION((AE_INFO, status, 377 "No or invalid critical threshold")); 378 return -ENODEV; 379 } else { 380 tz->trips.critical.flags.valid = 1; 381 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 382 "Found critical threshold [%lu]\n", 383 tz->trips.critical.temperature)); 384 } 385 if (tz->trips.critical.flags.valid == 1) { 386 if (crt == -1) { 387 tz->trips.critical.flags.valid = 0; 388 } else if (crt > 0) { 389 unsigned long crt_k = CELSIUS_TO_KELVIN(crt); 390 /* 391 * Allow override critical threshold 392 */ 393 if (crt_k > tz->trips.critical.temperature) 394 printk(KERN_WARNING PREFIX 395 "Critical threshold %d C\n", crt); 396 tz->trips.critical.temperature = crt_k; 397 } 398 } 399 } 400 401 /* Critical Sleep (optional) */ 402 if (flag & ACPI_TRIPS_HOT) { 403 status = acpi_evaluate_integer(tz->device->handle, 404 "_HOT", NULL, &tmp); 405 if (ACPI_FAILURE(status)) { 406 tz->trips.hot.flags.valid = 0; 407 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 408 "No hot threshold\n")); 409 } else { 410 tz->trips.hot.temperature = tmp; 411 tz->trips.hot.flags.valid = 1; 412 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 413 "Found hot threshold [%lu]\n", 414 tz->trips.critical.temperature)); 415 } 416 } 417 418 /* Passive (optional) */ 419 if (flag & ACPI_TRIPS_PASSIVE) { 420 valid = tz->trips.passive.flags.valid; 421 if (psv == -1) { 422 status = AE_SUPPORT; 423 } else if (psv > 0) { 424 tmp = CELSIUS_TO_KELVIN(psv); 425 status = AE_OK; 426 } else { 427 status = acpi_evaluate_integer(tz->device->handle, 428 "_PSV", NULL, &tmp); 429 } 430 431 if (ACPI_FAILURE(status)) 432 tz->trips.passive.flags.valid = 0; 433 else { 434 tz->trips.passive.temperature = tmp; 435 tz->trips.passive.flags.valid = 1; 436 if (flag == ACPI_TRIPS_INIT) { 437 status = acpi_evaluate_integer( 438 tz->device->handle, "_TC1", 439 NULL, &tmp); 440 if (ACPI_FAILURE(status)) 441 tz->trips.passive.flags.valid = 0; 442 else 443 tz->trips.passive.tc1 = tmp; 444 status = acpi_evaluate_integer( 445 tz->device->handle, "_TC2", 446 NULL, &tmp); 447 if (ACPI_FAILURE(status)) 448 tz->trips.passive.flags.valid = 0; 449 else 450 tz->trips.passive.tc2 = tmp; 451 status = acpi_evaluate_integer( 452 tz->device->handle, "_TSP", 453 NULL, &tmp); 454 if (ACPI_FAILURE(status)) 455 tz->trips.passive.flags.valid = 0; 456 else 457 tz->trips.passive.tsp = tmp; 458 } 459 } 460 } 461 if ((flag & ACPI_TRIPS_DEVICES) && tz->trips.passive.flags.valid) { 462 memset(&devices, 0, sizeof(struct acpi_handle_list)); 463 status = acpi_evaluate_reference(tz->device->handle, "_PSL", 464 NULL, &devices); 465 if (ACPI_FAILURE(status)) 466 tz->trips.passive.flags.valid = 0; 467 else 468 tz->trips.passive.flags.valid = 1; 469 470 if (memcmp(&tz->trips.passive.devices, &devices, 471 sizeof(struct acpi_handle_list))) { 472 memcpy(&tz->trips.passive.devices, &devices, 473 sizeof(struct acpi_handle_list)); 474 ACPI_THERMAL_TRIPS_EXCEPTION(flag, "device"); 475 } 476 } 477 if ((flag & ACPI_TRIPS_PASSIVE) || (flag & ACPI_TRIPS_DEVICES)) { 478 if (valid != tz->trips.passive.flags.valid) 479 ACPI_THERMAL_TRIPS_EXCEPTION(flag, "state"); 480 } 481 482 /* Active (optional) */ 483 for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) { 484 char name[5] = { '_', 'A', 'C', ('0' + i), '\0' }; 485 valid = tz->trips.active[i].flags.valid; 486 487 if (act == -1) 488 break; /* disable all active trip points */ 489 490 if (flag & ACPI_TRIPS_ACTIVE) { 491 status = acpi_evaluate_integer(tz->device->handle, 492 name, NULL, &tmp); 493 if (ACPI_FAILURE(status)) { 494 tz->trips.active[i].flags.valid = 0; 495 if (i == 0) 496 break; 497 if (act <= 0) 498 break; 499 if (i == 1) 500 tz->trips.active[0].temperature = 501 CELSIUS_TO_KELVIN(act); 502 else 503 /* 504 * Don't allow override higher than 505 * the next higher trip point 506 */ 507 tz->trips.active[i - 1].temperature = 508 (tz->trips.active[i - 2].temperature < 509 CELSIUS_TO_KELVIN(act) ? 510 tz->trips.active[i - 2].temperature : 511 CELSIUS_TO_KELVIN(act)); 512 break; 513 } else { 514 tz->trips.active[i].temperature = tmp; 515 tz->trips.active[i].flags.valid = 1; 516 } 517 } 518 519 name[2] = 'L'; 520 if ((flag & ACPI_TRIPS_DEVICES) && tz->trips.active[i].flags.valid ) { 521 memset(&devices, 0, sizeof(struct acpi_handle_list)); 522 status = acpi_evaluate_reference(tz->device->handle, 523 name, NULL, &devices); 524 if (ACPI_FAILURE(status)) 525 tz->trips.active[i].flags.valid = 0; 526 else 527 tz->trips.active[i].flags.valid = 1; 528 529 if (memcmp(&tz->trips.active[i].devices, &devices, 530 sizeof(struct acpi_handle_list))) { 531 memcpy(&tz->trips.active[i].devices, &devices, 532 sizeof(struct acpi_handle_list)); 533 ACPI_THERMAL_TRIPS_EXCEPTION(flag, "device"); 534 } 535 } 536 if ((flag & ACPI_TRIPS_ACTIVE) || (flag & ACPI_TRIPS_DEVICES)) 537 if (valid != tz->trips.active[i].flags.valid) 538 ACPI_THERMAL_TRIPS_EXCEPTION(flag, "state"); 539 540 if (!tz->trips.active[i].flags.valid) 541 break; 542 } 543 544 if (flag & ACPI_TRIPS_DEVICES) { 545 memset(&devices, 0, sizeof(struct acpi_handle_list)); 546 status = acpi_evaluate_reference(tz->device->handle, "_TZD", 547 NULL, &devices); 548 if (memcmp(&tz->devices, &devices, 549 sizeof(struct acpi_handle_list))) { 550 memcpy(&tz->devices, &devices, 551 sizeof(struct acpi_handle_list)); 552 ACPI_THERMAL_TRIPS_EXCEPTION(flag, "device"); 553 } 554 } 555 556 return 0; 557} 558 559static int acpi_thermal_get_trip_points(struct acpi_thermal *tz) 560{ 561 return acpi_thermal_trips_update(tz, ACPI_TRIPS_INIT); 562} 563 564static int acpi_thermal_critical(struct acpi_thermal *tz) 565{ 566 if (!tz || !tz->trips.critical.flags.valid) 567 return -EINVAL; 568 569 if (tz->temperature >= tz->trips.critical.temperature) { 570 printk(KERN_WARNING PREFIX "Critical trip point\n"); 571 tz->trips.critical.flags.enabled = 1; 572 } else if (tz->trips.critical.flags.enabled) 573 tz->trips.critical.flags.enabled = 0; 574 575 acpi_bus_generate_proc_event(tz->device, ACPI_THERMAL_NOTIFY_CRITICAL, 576 tz->trips.critical.flags.enabled); 577 acpi_bus_generate_netlink_event(tz->device->pnp.device_class, 578 dev_name(&tz->device->dev), 579 ACPI_THERMAL_NOTIFY_CRITICAL, 580 tz->trips.critical.flags.enabled); 581 582 /* take no action if nocrt is set */ 583 if(!nocrt) { 584 printk(KERN_EMERG 585 "Critical temperature reached (%ld C), shutting down.\n", 586 KELVIN_TO_CELSIUS(tz->temperature)); 587 orderly_poweroff(true); 588 } 589 590 return 0; 591} 592 593static int acpi_thermal_hot(struct acpi_thermal *tz) 594{ 595 if (!tz || !tz->trips.hot.flags.valid) 596 return -EINVAL; 597 598 if (tz->temperature >= tz->trips.hot.temperature) { 599 printk(KERN_WARNING PREFIX "Hot trip point\n"); 600 tz->trips.hot.flags.enabled = 1; 601 } else if (tz->trips.hot.flags.enabled) 602 tz->trips.hot.flags.enabled = 0; 603 604 acpi_bus_generate_proc_event(tz->device, ACPI_THERMAL_NOTIFY_HOT, 605 tz->trips.hot.flags.enabled); 606 acpi_bus_generate_netlink_event(tz->device->pnp.device_class, 607 dev_name(&tz->device->dev), 608 ACPI_THERMAL_NOTIFY_HOT, 609 tz->trips.hot.flags.enabled); 610 611 /* TBD: Call user-mode "sleep(S4)" function if nocrt is cleared */ 612 613 return 0; 614} 615 616static void acpi_thermal_passive(struct acpi_thermal *tz) 617{ 618 int result = 1; 619 struct acpi_thermal_passive *passive = NULL; 620 int trend = 0; 621 int i = 0; 622 623 624 if (!tz || !tz->trips.passive.flags.valid) 625 return; 626 627 passive = &(tz->trips.passive); 628 629 /* 630 * Above Trip? 631 * ----------- 632 * Calculate the thermal trend (using the passive cooling equation) 633 * and modify the performance limit for all passive cooling devices 634 * accordingly. Note that we assume symmetry. 635 */ 636 if (tz->temperature >= passive->temperature) { 637 trend = 638 (passive->tc1 * (tz->temperature - tz->last_temperature)) + 639 (passive->tc2 * (tz->temperature - passive->temperature)); 640 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 641 "trend[%d]=(tc1[%lu]*(tmp[%lu]-last[%lu]))+(tc2[%lu]*(tmp[%lu]-psv[%lu]))\n", 642 trend, passive->tc1, tz->temperature, 643 tz->last_temperature, passive->tc2, 644 tz->temperature, passive->temperature)); 645 passive->flags.enabled = 1; 646 /* Heating up? */ 647 if (trend > 0) 648 for (i = 0; i < passive->devices.count; i++) 649 acpi_processor_set_thermal_limit(passive-> 650 devices. 651 handles[i], 652 ACPI_PROCESSOR_LIMIT_INCREMENT); 653 /* Cooling off? */ 654 else if (trend < 0) { 655 for (i = 0; i < passive->devices.count; i++) 656 /* 657 * assume that we are on highest 658 * freq/lowest thrott and can leave 659 * passive mode, even in error case 660 */ 661 if (!acpi_processor_set_thermal_limit 662 (passive->devices.handles[i], 663 ACPI_PROCESSOR_LIMIT_DECREMENT)) 664 result = 0; 665 /* 666 * Leave cooling mode, even if the temp might 667 * higher than trip point This is because some 668 * machines might have long thermal polling 669 * frequencies (tsp) defined. We will fall back 670 * into passive mode in next cycle (probably quicker) 671 */ 672 if (result) { 673 passive->flags.enabled = 0; 674 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 675 "Disabling passive cooling, still above threshold," 676 " but we are cooling down\n")); 677 } 678 } 679 return; 680 } 681 682 /* 683 * Below Trip? 684 * ----------- 685 * Implement passive cooling hysteresis to slowly increase performance 686 * and avoid thrashing around the passive trip point. Note that we 687 * assume symmetry. 688 */ 689 if (!passive->flags.enabled) 690 return; 691 for (i = 0; i < passive->devices.count; i++) 692 if (!acpi_processor_set_thermal_limit 693 (passive->devices.handles[i], 694 ACPI_PROCESSOR_LIMIT_DECREMENT)) 695 result = 0; 696 if (result) { 697 passive->flags.enabled = 0; 698 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 699 "Disabling passive cooling (zone is cool)\n")); 700 } 701} 702 703static void acpi_thermal_active(struct acpi_thermal *tz) 704{ 705 int result = 0; 706 struct acpi_thermal_active *active = NULL; 707 int i = 0; 708 int j = 0; 709 unsigned long maxtemp = 0; 710 711 712 if (!tz) 713 return; 714 715 for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) { 716 active = &(tz->trips.active[i]); 717 if (!active || !active->flags.valid) 718 break; 719 if (tz->temperature >= active->temperature) { 720 /* 721 * Above Threshold? 722 * ---------------- 723 * If not already enabled, turn ON all cooling devices 724 * associated with this active threshold. 725 */ 726 if (active->temperature > maxtemp) 727 tz->state.active_index = i; 728 maxtemp = active->temperature; 729 if (active->flags.enabled) 730 continue; 731 for (j = 0; j < active->devices.count; j++) { 732 result = 733 acpi_bus_set_power(active->devices. 734 handles[j], 735 ACPI_STATE_D0); 736 if (result) { 737 printk(KERN_WARNING PREFIX 738 "Unable to turn cooling device [%p] 'on'\n", 739 active->devices. 740 handles[j]); 741 continue; 742 } 743 active->flags.enabled = 1; 744 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 745 "Cooling device [%p] now 'on'\n", 746 active->devices.handles[j])); 747 } 748 continue; 749 } 750 if (!active->flags.enabled) 751 continue; 752 /* 753 * Below Threshold? 754 * ---------------- 755 * Turn OFF all cooling devices associated with this 756 * threshold. 757 */ 758 for (j = 0; j < active->devices.count; j++) { 759 result = acpi_bus_set_power(active->devices.handles[j], 760 ACPI_STATE_D3); 761 if (result) { 762 printk(KERN_WARNING PREFIX 763 "Unable to turn cooling device [%p] 'off'\n", 764 active->devices.handles[j]); 765 continue; 766 } 767 active->flags.enabled = 0; 768 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 769 "Cooling device [%p] now 'off'\n", 770 active->devices.handles[j])); 771 } 772 } 773} 774 775static void acpi_thermal_check(void *context); 776 777static void acpi_thermal_run(unsigned long data) 778{ 779 struct acpi_thermal *tz = (struct acpi_thermal *)data; 780 if (!tz->zombie) 781 acpi_os_execute(OSL_GPE_HANDLER, acpi_thermal_check, (void *)data); 782} 783 784static void acpi_thermal_active_off(void *data) 785{ 786 int result = 0; 787 struct acpi_thermal *tz = data; 788 int i = 0; 789 int j = 0; 790 struct acpi_thermal_active *active = NULL; 791 792 if (!tz) { 793 printk(KERN_ERR PREFIX "Invalid (NULL) context\n"); 794 return; 795 } 796 797 result = acpi_thermal_get_temperature(tz); 798 if (result) 799 return; 800 801 for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) { 802 active = &(tz->trips.active[i]); 803 if (!active || !active->flags.valid) 804 break; 805 if (tz->temperature >= active->temperature) { 806 /* 807 * If the thermal temperature is greater than the 808 * active threshod, unnecessary to turn off the 809 * the active cooling device. 810 */ 811 continue; 812 } 813 /* 814 * Below Threshold? 815 * ---------------- 816 * Turn OFF all cooling devices associated with this 817 * threshold. 818 */ 819 for (j = 0; j < active->devices.count; j++) 820 result = acpi_bus_set_power(active->devices.handles[j], 821 ACPI_STATE_D3); 822 } 823} 824 825static void acpi_thermal_check(void *data) 826{ 827 int result = 0; 828 struct acpi_thermal *tz = data; 829 unsigned long sleep_time = 0; 830 unsigned long timeout_jiffies = 0; 831 int i = 0; 832 struct acpi_thermal_state state; 833 834 835 if (!tz) { 836 printk(KERN_ERR PREFIX "Invalid (NULL) context\n"); 837 return; 838 } 839 840 /* Check if someone else is already running */ 841 if (!mutex_trylock(&tz->lock)) 842 return; 843 844 state = tz->state; 845 846 result = acpi_thermal_get_temperature(tz); 847 if (result) 848 goto unlock; 849 850 if (!tz->tz_enabled) 851 goto unlock; 852 853 memset(&tz->state, 0, sizeof(tz->state)); 854 855 /* 856 * Check Trip Points 857 * ----------------- 858 * Compare the current temperature to the trip point values to see 859 * if we've entered one of the thermal policy states. Note that 860 * this function determines when a state is entered, but the 861 * individual policy decides when it is exited (e.g. hysteresis). 862 */ 863 if (tz->trips.critical.flags.valid) 864 state.critical |= 865 (tz->temperature >= tz->trips.critical.temperature); 866 if (tz->trips.hot.flags.valid) 867 state.hot |= (tz->temperature >= tz->trips.hot.temperature); 868 if (tz->trips.passive.flags.valid) 869 state.passive |= 870 (tz->temperature >= tz->trips.passive.temperature); 871 for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) 872 if (tz->trips.active[i].flags.valid) 873 state.active |= 874 (tz->temperature >= 875 tz->trips.active[i].temperature); 876 877 /* 878 * Invoke Policy 879 * ------------- 880 * Separated from the above check to allow individual policy to 881 * determine when to exit a given state. 882 */ 883 if (state.critical) 884 acpi_thermal_critical(tz); 885 if (state.hot) 886 acpi_thermal_hot(tz); 887 if (state.passive) 888 acpi_thermal_passive(tz); 889 if (state.active) 890 acpi_thermal_active(tz); 891 892 /* 893 * Calculate State 894 * --------------- 895 * Again, separated from the above two to allow independent policy 896 * decisions. 897 */ 898 tz->state.critical = tz->trips.critical.flags.enabled; 899 tz->state.hot = tz->trips.hot.flags.enabled; 900 tz->state.passive = tz->trips.passive.flags.enabled; 901 tz->state.active = 0; 902 for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) 903 tz->state.active |= tz->trips.active[i].flags.enabled; 904 905 /* 906 * Calculate Sleep Time 907 * -------------------- 908 * If we're in the passive state, use _TSP's value. Otherwise 909 * use the default polling frequency (e.g. _TZP). If no polling 910 * frequency is specified then we'll wait forever (at least until 911 * a thermal event occurs). Note that _TSP and _TZD values are 912 * given in 1/10th seconds (we must covert to milliseconds). 913 */ 914 if (tz->state.passive) { 915 sleep_time = tz->trips.passive.tsp * 100; 916 timeout_jiffies = jiffies + (HZ * sleep_time) / 1000; 917 } else if (tz->polling_frequency > 0) { 918 sleep_time = tz->polling_frequency * 100; 919 timeout_jiffies = round_jiffies(jiffies + (HZ * sleep_time) / 1000); 920 } 921 922 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%s: temperature[%lu] sleep[%lu]\n", 923 tz->name, tz->temperature, sleep_time)); 924 925 /* 926 * Schedule Next Poll 927 * ------------------ 928 */ 929 if (!sleep_time) { 930 if (timer_pending(&(tz->timer))) 931 del_timer(&(tz->timer)); 932 } else { 933 if (timer_pending(&(tz->timer))) 934 mod_timer(&(tz->timer), timeout_jiffies); 935 else { 936 tz->timer.data = (unsigned long)tz; 937 tz->timer.function = acpi_thermal_run; 938 tz->timer.expires = timeout_jiffies; 939 add_timer(&(tz->timer)); 940 } 941 } 942 unlock: 943 mutex_unlock(&tz->lock); 944} 945 946/* sys I/F for generic thermal sysfs support */ 947#define KELVIN_TO_MILLICELSIUS(t) (t * 100 - 273200) 948 949static int thermal_get_temp(struct thermal_zone_device *thermal, char *buf) 950{ 951 struct acpi_thermal *tz = thermal->devdata; 952 int result; 953 954 if (!tz) 955 return -EINVAL; 956 957 result = acpi_thermal_get_temperature(tz); 958 if (result) 959 return result; 960 961 return sprintf(buf, "%ld\n", KELVIN_TO_MILLICELSIUS(tz->temperature)); 962} 963 964static const char enabled[] = "kernel"; 965static const char disabled[] = "user"; 966static int thermal_get_mode(struct thermal_zone_device *thermal, 967 char *buf) 968{ 969 struct acpi_thermal *tz = thermal->devdata; 970 971 if (!tz) 972 return -EINVAL; 973 974 return sprintf(buf, "%s\n", tz->tz_enabled ? 975 enabled : disabled); 976} 977 978static int thermal_set_mode(struct thermal_zone_device *thermal, 979 const char *buf) 980{ 981 struct acpi_thermal *tz = thermal->devdata; 982 int enable; 983 984 if (!tz) 985 return -EINVAL; 986 987 /* 988 * enable/disable thermal management from ACPI thermal driver 989 */ 990 if (!strncmp(buf, enabled, sizeof enabled - 1)) 991 enable = 1; 992 else if (!strncmp(buf, disabled, sizeof disabled - 1)) 993 enable = 0; 994 else 995 return -EINVAL; 996 997 if (enable != tz->tz_enabled) { 998 tz->tz_enabled = enable; 999 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 1000 "%s ACPI thermal control\n", 1001 tz->tz_enabled ? enabled : disabled)); 1002 acpi_thermal_check(tz); 1003 } 1004 return 0; 1005} 1006 1007static int thermal_get_trip_type(struct thermal_zone_device *thermal, 1008 int trip, char *buf) 1009{ 1010 struct acpi_thermal *tz = thermal->devdata; 1011 int i; 1012 1013 if (!tz || trip < 0) 1014 return -EINVAL; 1015 1016 if (tz->trips.critical.flags.valid) { 1017 if (!trip) 1018 return sprintf(buf, "critical\n"); 1019 trip--; 1020 } 1021 1022 if (tz->trips.hot.flags.valid) { 1023 if (!trip) 1024 return sprintf(buf, "hot\n"); 1025 trip--; 1026 } 1027 1028 if (tz->trips.passive.flags.valid) { 1029 if (!trip) 1030 return sprintf(buf, "passive\n"); 1031 trip--; 1032 } 1033 1034 for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE && 1035 tz->trips.active[i].flags.valid; i++) { 1036 if (!trip) 1037 return sprintf(buf, "active%d\n", i); 1038 trip--; 1039 } 1040 1041 return -EINVAL; 1042} 1043 1044static int thermal_get_trip_temp(struct thermal_zone_device *thermal, 1045 int trip, char *buf) 1046{ 1047 struct acpi_thermal *tz = thermal->devdata; 1048 int i; 1049 1050 if (!tz || trip < 0) 1051 return -EINVAL; 1052 1053 if (tz->trips.critical.flags.valid) { 1054 if (!trip) 1055 return sprintf(buf, "%ld\n", KELVIN_TO_MILLICELSIUS( 1056 tz->trips.critical.temperature)); 1057 trip--; 1058 } 1059 1060 if (tz->trips.hot.flags.valid) { 1061 if (!trip) 1062 return sprintf(buf, "%ld\n", KELVIN_TO_MILLICELSIUS( 1063 tz->trips.hot.temperature)); 1064 trip--; 1065 } 1066 1067 if (tz->trips.passive.flags.valid) { 1068 if (!trip) 1069 return sprintf(buf, "%ld\n", KELVIN_TO_MILLICELSIUS( 1070 tz->trips.passive.temperature)); 1071 trip--; 1072 } 1073 1074 for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE && 1075 tz->trips.active[i].flags.valid; i++) { 1076 if (!trip) 1077 return sprintf(buf, "%ld\n", KELVIN_TO_MILLICELSIUS( 1078 tz->trips.active[i].temperature)); 1079 trip--; 1080 } 1081 1082 return -EINVAL; 1083} 1084 1085static int thermal_get_crit_temp(struct thermal_zone_device *thermal, 1086 unsigned long *temperature) { 1087 struct acpi_thermal *tz = thermal->devdata; 1088 1089 if (tz->trips.critical.flags.valid) { 1090 *temperature = KELVIN_TO_MILLICELSIUS( 1091 tz->trips.critical.temperature); 1092 return 0; 1093 } else 1094 return -EINVAL; 1095} 1096 1097typedef int (*cb)(struct thermal_zone_device *, int, 1098 struct thermal_cooling_device *); 1099static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal, 1100 struct thermal_cooling_device *cdev, 1101 cb action) 1102{ 1103 struct acpi_device *device = cdev->devdata; 1104 struct acpi_thermal *tz = thermal->devdata; 1105 struct acpi_device *dev; 1106 acpi_status status; 1107 acpi_handle handle; 1108 int i; 1109 int j; 1110 int trip = -1; 1111 int result = 0; 1112 1113 if (tz->trips.critical.flags.valid) 1114 trip++; 1115 1116 if (tz->trips.hot.flags.valid) 1117 trip++; 1118 1119 if (tz->trips.passive.flags.valid) { 1120 trip++; 1121 for (i = 0; i < tz->trips.passive.devices.count; 1122 i++) { 1123 handle = tz->trips.passive.devices.handles[i]; 1124 status = acpi_bus_get_device(handle, &dev); 1125 if (ACPI_SUCCESS(status) && (dev == device)) { 1126 result = action(thermal, trip, cdev); 1127 if (result) 1128 goto failed; 1129 } 1130 } 1131 } 1132 1133 for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) { 1134 if (!tz->trips.active[i].flags.valid) 1135 break; 1136 trip++; 1137 for (j = 0; 1138 j < tz->trips.active[i].devices.count; 1139 j++) { 1140 handle = tz->trips.active[i].devices.handles[j]; 1141 status = acpi_bus_get_device(handle, &dev); 1142 if (ACPI_SUCCESS(status) && (dev == device)) { 1143 result = action(thermal, trip, cdev); 1144 if (result) 1145 goto failed; 1146 } 1147 } 1148 } 1149 1150 for (i = 0; i < tz->devices.count; i++) { 1151 handle = tz->devices.handles[i]; 1152 status = acpi_bus_get_device(handle, &dev); 1153 if (ACPI_SUCCESS(status) && (dev == device)) { 1154 result = action(thermal, -1, cdev); 1155 if (result) 1156 goto failed; 1157 } 1158 } 1159 1160failed: 1161 return result; 1162} 1163 1164static int 1165acpi_thermal_bind_cooling_device(struct thermal_zone_device *thermal, 1166 struct thermal_cooling_device *cdev) 1167{ 1168 return acpi_thermal_cooling_device_cb(thermal, cdev, 1169 thermal_zone_bind_cooling_device); 1170} 1171 1172static int 1173acpi_thermal_unbind_cooling_device(struct thermal_zone_device *thermal, 1174 struct thermal_cooling_device *cdev) 1175{ 1176 return acpi_thermal_cooling_device_cb(thermal, cdev, 1177 thermal_zone_unbind_cooling_device); 1178} 1179 1180static struct thermal_zone_device_ops acpi_thermal_zone_ops = { 1181 .bind = acpi_thermal_bind_cooling_device, 1182 .unbind = acpi_thermal_unbind_cooling_device, 1183 .get_temp = thermal_get_temp, 1184 .get_mode = thermal_get_mode, 1185 .set_mode = thermal_set_mode, 1186 .get_trip_type = thermal_get_trip_type, 1187 .get_trip_temp = thermal_get_trip_temp, 1188 .get_crit_temp = thermal_get_crit_temp, 1189}; 1190 1191static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz) 1192{ 1193 int trips = 0; 1194 int result; 1195 acpi_status status; 1196 int i; 1197 1198 if (tz->trips.critical.flags.valid) 1199 trips++; 1200 1201 if (tz->trips.hot.flags.valid) 1202 trips++; 1203 1204 if (tz->trips.passive.flags.valid) 1205 trips++; 1206 1207 for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE && 1208 tz->trips.active[i].flags.valid; i++, trips++); 1209 tz->thermal_zone = thermal_zone_device_register("acpitz", 1210 trips, tz, &acpi_thermal_zone_ops); 1211 if (IS_ERR(tz->thermal_zone)) 1212 return -ENODEV; 1213 1214 result = sysfs_create_link(&tz->device->dev.kobj, 1215 &tz->thermal_zone->device.kobj, "thermal_zone"); 1216 if (result) 1217 return result; 1218 1219 result = sysfs_create_link(&tz->thermal_zone->device.kobj, 1220 &tz->device->dev.kobj, "device"); 1221 if (result) 1222 return result; 1223 1224 status = acpi_attach_data(tz->device->handle, 1225 acpi_bus_private_data_handler, 1226 tz->thermal_zone); 1227 if (ACPI_FAILURE(status)) { 1228 printk(KERN_ERR PREFIX 1229 "Error attaching device data\n"); 1230 return -ENODEV; 1231 } 1232 1233 tz->tz_enabled = 1; 1234 1235 dev_info(&tz->device->dev, "registered as thermal_zone%d\n", 1236 tz->thermal_zone->id); 1237 return 0; 1238} 1239 1240static void acpi_thermal_unregister_thermal_zone(struct acpi_thermal *tz) 1241{ 1242 sysfs_remove_link(&tz->device->dev.kobj, "thermal_zone"); 1243 sysfs_remove_link(&tz->thermal_zone->device.kobj, "device"); 1244 thermal_zone_device_unregister(tz->thermal_zone); 1245 tz->thermal_zone = NULL; 1246 acpi_detach_data(tz->device->handle, acpi_bus_private_data_handler); 1247} 1248 1249 1250/* -------------------------------------------------------------------------- 1251 FS Interface (/proc) 1252 -------------------------------------------------------------------------- */ 1253 1254static struct proc_dir_entry *acpi_thermal_dir; 1255 1256static int acpi_thermal_state_seq_show(struct seq_file *seq, void *offset) 1257{ 1258 struct acpi_thermal *tz = seq->private; 1259 1260 1261 if (!tz) 1262 goto end; 1263 1264 seq_puts(seq, "state: "); 1265 1266 if (!tz->state.critical && !tz->state.hot && !tz->state.passive 1267 && !tz->state.active) 1268 seq_puts(seq, "ok\n"); 1269 else { 1270 if (tz->state.critical) 1271 seq_puts(seq, "critical "); 1272 if (tz->state.hot) 1273 seq_puts(seq, "hot "); 1274 if (tz->state.passive) 1275 seq_puts(seq, "passive "); 1276 if (tz->state.active) 1277 seq_printf(seq, "active[%d]", tz->state.active_index); 1278 seq_puts(seq, "\n"); 1279 } 1280 1281 end: 1282 return 0; 1283} 1284 1285static int acpi_thermal_state_open_fs(struct inode *inode, struct file *file) 1286{ 1287 return single_open(file, acpi_thermal_state_seq_show, PDE(inode)->data); 1288} 1289 1290static int acpi_thermal_temp_seq_show(struct seq_file *seq, void *offset) 1291{ 1292 int result = 0; 1293 struct acpi_thermal *tz = seq->private; 1294 1295 1296 if (!tz) 1297 goto end; 1298 1299 result = acpi_thermal_get_temperature(tz); 1300 if (result) 1301 goto end; 1302 1303 seq_printf(seq, "temperature: %ld C\n", 1304 KELVIN_TO_CELSIUS(tz->temperature)); 1305 1306 end: 1307 return 0; 1308} 1309 1310static int acpi_thermal_temp_open_fs(struct inode *inode, struct file *file) 1311{ 1312 return single_open(file, acpi_thermal_temp_seq_show, PDE(inode)->data); 1313} 1314 1315static int acpi_thermal_trip_seq_show(struct seq_file *seq, void *offset) 1316{ 1317 struct acpi_thermal *tz = seq->private; 1318 struct acpi_device *device; 1319 acpi_status status; 1320 1321 int i = 0; 1322 int j = 0; 1323 1324 1325 if (!tz) 1326 goto end; 1327 1328 if (tz->trips.critical.flags.valid) 1329 seq_printf(seq, "critical (S5): %ld C%s", 1330 KELVIN_TO_CELSIUS(tz->trips.critical.temperature), 1331 nocrt ? " <disabled>\n" : "\n"); 1332 1333 if (tz->trips.hot.flags.valid) 1334 seq_printf(seq, "hot (S4): %ld C%s", 1335 KELVIN_TO_CELSIUS(tz->trips.hot.temperature), 1336 nocrt ? " <disabled>\n" : "\n"); 1337 1338 if (tz->trips.passive.flags.valid) { 1339 seq_printf(seq, 1340 "passive: %ld C: tc1=%lu tc2=%lu tsp=%lu devices=", 1341 KELVIN_TO_CELSIUS(tz->trips.passive.temperature), 1342 tz->trips.passive.tc1, tz->trips.passive.tc2, 1343 tz->trips.passive.tsp); 1344 for (j = 0; j < tz->trips.passive.devices.count; j++) { 1345 status = acpi_bus_get_device(tz->trips.passive.devices. 1346 handles[j], &device); 1347 seq_printf(seq, "%4.4s ", status ? "" : 1348 acpi_device_bid(device)); 1349 } 1350 seq_puts(seq, "\n"); 1351 } 1352 1353 for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) { 1354 if (!(tz->trips.active[i].flags.valid)) 1355 break; 1356 seq_printf(seq, "active[%d]: %ld C: devices=", 1357 i, 1358 KELVIN_TO_CELSIUS(tz->trips.active[i].temperature)); 1359 for (j = 0; j < tz->trips.active[i].devices.count; j++){ 1360 status = acpi_bus_get_device(tz->trips.active[i]. 1361 devices.handles[j], 1362 &device); 1363 seq_printf(seq, "%4.4s ", status ? "" : 1364 acpi_device_bid(device)); 1365 } 1366 seq_puts(seq, "\n"); 1367 } 1368 1369 end: 1370 return 0; 1371} 1372 1373static int acpi_thermal_trip_open_fs(struct inode *inode, struct file *file) 1374{ 1375 return single_open(file, acpi_thermal_trip_seq_show, PDE(inode)->data); 1376} 1377 1378static int acpi_thermal_cooling_seq_show(struct seq_file *seq, void *offset) 1379{ 1380 struct acpi_thermal *tz = seq->private; 1381 1382 1383 if (!tz) 1384 goto end; 1385 1386 if (!tz->flags.cooling_mode) 1387 seq_puts(seq, "<setting not supported>\n"); 1388 else 1389 seq_puts(seq, "0 - Active; 1 - Passive\n"); 1390 1391 end: 1392 return 0; 1393} 1394 1395static int acpi_thermal_cooling_open_fs(struct inode *inode, struct file *file) 1396{ 1397 return single_open(file, acpi_thermal_cooling_seq_show, 1398 PDE(inode)->data); 1399} 1400 1401static ssize_t 1402acpi_thermal_write_cooling_mode(struct file *file, 1403 const char __user * buffer, 1404 size_t count, loff_t * ppos) 1405{ 1406 struct seq_file *m = file->private_data; 1407 struct acpi_thermal *tz = m->private; 1408 int result = 0; 1409 char mode_string[12] = { '\0' }; 1410 1411 1412 if (!tz || (count > sizeof(mode_string) - 1)) 1413 return -EINVAL; 1414 1415 if (!tz->flags.cooling_mode) 1416 return -ENODEV; 1417 1418 if (copy_from_user(mode_string, buffer, count)) 1419 return -EFAULT; 1420 1421 mode_string[count] = '\0'; 1422 1423 result = acpi_thermal_set_cooling_mode(tz, 1424 simple_strtoul(mode_string, NULL, 1425 0)); 1426 if (result) 1427 return result; 1428 1429 acpi_thermal_check(tz); 1430 1431 return count; 1432} 1433 1434static int acpi_thermal_polling_seq_show(struct seq_file *seq, void *offset) 1435{ 1436 struct acpi_thermal *tz = seq->private; 1437 1438 1439 if (!tz) 1440 goto end; 1441 1442 if (!tz->polling_frequency) { 1443 seq_puts(seq, "<polling disabled>\n"); 1444 goto end; 1445 } 1446 1447 seq_printf(seq, "polling frequency: %lu seconds\n", 1448 (tz->polling_frequency / 10)); 1449 1450 end: 1451 return 0; 1452} 1453 1454static int acpi_thermal_polling_open_fs(struct inode *inode, struct file *file) 1455{ 1456 return single_open(file, acpi_thermal_polling_seq_show, 1457 PDE(inode)->data); 1458} 1459 1460static ssize_t 1461acpi_thermal_write_polling(struct file *file, 1462 const char __user * buffer, 1463 size_t count, loff_t * ppos) 1464{ 1465 struct seq_file *m = file->private_data; 1466 struct acpi_thermal *tz = m->private; 1467 int result = 0; 1468 char polling_string[12] = { '\0' }; 1469 int seconds = 0; 1470 1471 1472 if (!tz || (count > sizeof(polling_string) - 1)) 1473 return -EINVAL; 1474 1475 if (copy_from_user(polling_string, buffer, count)) 1476 return -EFAULT; 1477 1478 polling_string[count] = '\0'; 1479 1480 seconds = simple_strtoul(polling_string, NULL, 0); 1481 1482 result = acpi_thermal_set_polling(tz, seconds); 1483 if (result) 1484 return result; 1485 1486 acpi_thermal_check(tz); 1487 1488 return count; 1489} 1490 1491static int acpi_thermal_add_fs(struct acpi_device *device) 1492{ 1493 struct proc_dir_entry *entry = NULL; 1494 1495 1496 if (!acpi_device_dir(device)) { 1497 acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), 1498 acpi_thermal_dir); 1499 if (!acpi_device_dir(device)) 1500 return -ENODEV; 1501 acpi_device_dir(device)->owner = THIS_MODULE; 1502 } 1503 1504 /* 'state' [R] */ 1505 entry = proc_create_data(ACPI_THERMAL_FILE_STATE, 1506 S_IRUGO, acpi_device_dir(device), 1507 &acpi_thermal_state_fops, 1508 acpi_driver_data(device)); 1509 if (!entry) 1510 return -ENODEV; 1511 1512 /* 'temperature' [R] */ 1513 entry = proc_create_data(ACPI_THERMAL_FILE_TEMPERATURE, 1514 S_IRUGO, acpi_device_dir(device), 1515 &acpi_thermal_temp_fops, 1516 acpi_driver_data(device)); 1517 if (!entry) 1518 return -ENODEV; 1519 1520 /* 'trip_points' [R] */ 1521 entry = proc_create_data(ACPI_THERMAL_FILE_TRIP_POINTS, 1522 S_IRUGO, 1523 acpi_device_dir(device), 1524 &acpi_thermal_trip_fops, 1525 acpi_driver_data(device)); 1526 if (!entry) 1527 return -ENODEV; 1528 1529 /* 'cooling_mode' [R/W] */ 1530 entry = proc_create_data(ACPI_THERMAL_FILE_COOLING_MODE, 1531 S_IFREG | S_IRUGO | S_IWUSR, 1532 acpi_device_dir(device), 1533 &acpi_thermal_cooling_fops, 1534 acpi_driver_data(device)); 1535 if (!entry) 1536 return -ENODEV; 1537 1538 /* 'polling_frequency' [R/W] */ 1539 entry = proc_create_data(ACPI_THERMAL_FILE_POLLING_FREQ, 1540 S_IFREG | S_IRUGO | S_IWUSR, 1541 acpi_device_dir(device), 1542 &acpi_thermal_polling_fops, 1543 acpi_driver_data(device)); 1544 if (!entry) 1545 return -ENODEV; 1546 return 0; 1547} 1548 1549static int acpi_thermal_remove_fs(struct acpi_device *device) 1550{ 1551 1552 if (acpi_device_dir(device)) { 1553 remove_proc_entry(ACPI_THERMAL_FILE_POLLING_FREQ, 1554 acpi_device_dir(device)); 1555 remove_proc_entry(ACPI_THERMAL_FILE_COOLING_MODE, 1556 acpi_device_dir(device)); 1557 remove_proc_entry(ACPI_THERMAL_FILE_TRIP_POINTS, 1558 acpi_device_dir(device)); 1559 remove_proc_entry(ACPI_THERMAL_FILE_TEMPERATURE, 1560 acpi_device_dir(device)); 1561 remove_proc_entry(ACPI_THERMAL_FILE_STATE, 1562 acpi_device_dir(device)); 1563 remove_proc_entry(acpi_device_bid(device), acpi_thermal_dir); 1564 acpi_device_dir(device) = NULL; 1565 } 1566 1567 return 0; 1568} 1569 1570/* -------------------------------------------------------------------------- 1571 Driver Interface 1572 -------------------------------------------------------------------------- */ 1573 1574static void acpi_thermal_notify(acpi_handle handle, u32 event, void *data) 1575{ 1576 struct acpi_thermal *tz = data; 1577 struct acpi_device *device = NULL; 1578 1579 1580 if (!tz) 1581 return; 1582 1583 device = tz->device; 1584 1585 switch (event) { 1586 case ACPI_THERMAL_NOTIFY_TEMPERATURE: 1587 acpi_thermal_check(tz); 1588 break; 1589 case ACPI_THERMAL_NOTIFY_THRESHOLDS: 1590 acpi_thermal_trips_update(tz, ACPI_TRIPS_REFRESH_THRESHOLDS); 1591 acpi_thermal_check(tz); 1592 acpi_bus_generate_proc_event(device, event, 0); 1593 acpi_bus_generate_netlink_event(device->pnp.device_class, 1594 dev_name(&device->dev), event, 0); 1595 break; 1596 case ACPI_THERMAL_NOTIFY_DEVICES: 1597 acpi_thermal_trips_update(tz, ACPI_TRIPS_REFRESH_DEVICES); 1598 acpi_thermal_check(tz); 1599 acpi_bus_generate_proc_event(device, event, 0); 1600 acpi_bus_generate_netlink_event(device->pnp.device_class, 1601 dev_name(&device->dev), event, 0); 1602 break; 1603 default: 1604 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 1605 "Unsupported event [0x%x]\n", event)); 1606 break; 1607 } 1608 1609 return; 1610} 1611 1612static int acpi_thermal_get_info(struct acpi_thermal *tz) 1613{ 1614 int result = 0; 1615 1616 1617 if (!tz) 1618 return -EINVAL; 1619 1620 /* Get temperature [_TMP] (required) */ 1621 result = acpi_thermal_get_temperature(tz); 1622 if (result) 1623 return result; 1624 1625 /* Get trip points [_CRT, _PSV, etc.] (required) */ 1626 result = acpi_thermal_get_trip_points(tz); 1627 if (result) 1628 return result; 1629 1630 /* Set the cooling mode [_SCP] to active cooling (default) */ 1631 result = acpi_thermal_set_cooling_mode(tz, ACPI_THERMAL_MODE_ACTIVE); 1632 if (!result) 1633 tz->flags.cooling_mode = 1; 1634 1635 /* Get default polling frequency [_TZP] (optional) */ 1636 if (tzp) 1637 tz->polling_frequency = tzp; 1638 else 1639 acpi_thermal_get_polling_frequency(tz); 1640 1641 return 0; 1642} 1643 1644static int acpi_thermal_add(struct acpi_device *device) 1645{ 1646 int result = 0; 1647 acpi_status status = AE_OK; 1648 struct acpi_thermal *tz = NULL; 1649 1650 1651 if (!device) 1652 return -EINVAL; 1653 1654 tz = kzalloc(sizeof(struct acpi_thermal), GFP_KERNEL); 1655 if (!tz) 1656 return -ENOMEM; 1657 1658 tz->device = device; 1659 strcpy(tz->name, device->pnp.bus_id); 1660 strcpy(acpi_device_name(device), ACPI_THERMAL_DEVICE_NAME); 1661 strcpy(acpi_device_class(device), ACPI_THERMAL_CLASS); 1662 device->driver_data = tz; 1663 mutex_init(&tz->lock); 1664 1665 1666 result = acpi_thermal_get_info(tz); 1667 if (result) 1668 goto free_memory; 1669 1670 result = acpi_thermal_register_thermal_zone(tz); 1671 if (result) 1672 goto free_memory; 1673 1674 result = acpi_thermal_add_fs(device); 1675 if (result) 1676 goto unregister_thermal_zone; 1677 1678 init_timer(&tz->timer); 1679 1680 acpi_thermal_active_off(tz); 1681 1682 acpi_thermal_check(tz); 1683 1684 status = acpi_install_notify_handler(device->handle, 1685 ACPI_DEVICE_NOTIFY, 1686 acpi_thermal_notify, tz); 1687 if (ACPI_FAILURE(status)) { 1688 result = -ENODEV; 1689 goto remove_fs; 1690 } 1691 1692 printk(KERN_INFO PREFIX "%s [%s] (%ld C)\n", 1693 acpi_device_name(device), acpi_device_bid(device), 1694 KELVIN_TO_CELSIUS(tz->temperature)); 1695 goto end; 1696 1697remove_fs: 1698 acpi_thermal_remove_fs(device); 1699unregister_thermal_zone: 1700 thermal_zone_device_unregister(tz->thermal_zone); 1701free_memory: 1702 kfree(tz); 1703end: 1704 return result; 1705} 1706 1707static int acpi_thermal_remove(struct acpi_device *device, int type) 1708{ 1709 acpi_status status = AE_OK; 1710 struct acpi_thermal *tz = NULL; 1711 1712 1713 if (!device || !acpi_driver_data(device)) 1714 return -EINVAL; 1715 1716 tz = acpi_driver_data(device); 1717 1718 /* avoid timer adding new defer task */ 1719 tz->zombie = 1; 1720 /* wait for running timer (on other CPUs) finish */ 1721 del_timer_sync(&(tz->timer)); 1722 /* synchronize deferred task */ 1723 acpi_os_wait_events_complete(NULL); 1724 /* deferred task may reinsert timer */ 1725 del_timer_sync(&(tz->timer)); 1726 1727 status = acpi_remove_notify_handler(device->handle, 1728 ACPI_DEVICE_NOTIFY, 1729 acpi_thermal_notify); 1730 1731 /* Terminate policy */ 1732 if (tz->trips.passive.flags.valid && tz->trips.passive.flags.enabled) { 1733 tz->trips.passive.flags.enabled = 0; 1734 acpi_thermal_passive(tz); 1735 } 1736 if (tz->trips.active[0].flags.valid 1737 && tz->trips.active[0].flags.enabled) { 1738 tz->trips.active[0].flags.enabled = 0; 1739 acpi_thermal_active(tz); 1740 } 1741 1742 acpi_thermal_remove_fs(device); 1743 acpi_thermal_unregister_thermal_zone(tz); 1744 mutex_destroy(&tz->lock); 1745 kfree(tz); 1746 return 0; 1747} 1748 1749static int acpi_thermal_resume(struct acpi_device *device) 1750{ 1751 struct acpi_thermal *tz = NULL; 1752 int i, j, power_state, result; 1753 1754 1755 if (!device || !acpi_driver_data(device)) 1756 return -EINVAL; 1757 1758 tz = acpi_driver_data(device); 1759 1760 for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) { 1761 if (!(&tz->trips.active[i])) 1762 break; 1763 if (!tz->trips.active[i].flags.valid) 1764 break; 1765 tz->trips.active[i].flags.enabled = 1; 1766 for (j = 0; j < tz->trips.active[i].devices.count; j++) { 1767 result = acpi_bus_get_power(tz->trips.active[i].devices. 1768 handles[j], &power_state); 1769 if (result || (power_state != ACPI_STATE_D0)) { 1770 tz->trips.active[i].flags.enabled = 0; 1771 break; 1772 } 1773 } 1774 tz->state.active |= tz->trips.active[i].flags.enabled; 1775 } 1776 1777 acpi_thermal_check(tz); 1778 1779 return AE_OK; 1780} 1781 1782static int thermal_act(const struct dmi_system_id *d) { 1783 1784 if (act == 0) { 1785 printk(KERN_NOTICE "ACPI: %s detected: " 1786 "disabling all active thermal trip points\n", d->ident); 1787 act = -1; 1788 } 1789 return 0; 1790} 1791static int thermal_nocrt(const struct dmi_system_id *d) { 1792 1793 printk(KERN_NOTICE "ACPI: %s detected: " 1794 "disabling all critical thermal trip point actions.\n", d->ident); 1795 nocrt = 1; 1796 return 0; 1797} 1798static int thermal_tzp(const struct dmi_system_id *d) { 1799 1800 if (tzp == 0) { 1801 printk(KERN_NOTICE "ACPI: %s detected: " 1802 "enabling thermal zone polling\n", d->ident); 1803 tzp = 300; /* 300 dS = 30 Seconds */ 1804 } 1805 return 0; 1806} 1807static int thermal_psv(const struct dmi_system_id *d) { 1808 1809 if (psv == 0) { 1810 printk(KERN_NOTICE "ACPI: %s detected: " 1811 "disabling all passive thermal trip points\n", d->ident); 1812 psv = -1; 1813 } 1814 return 0; 1815} 1816 1817static struct dmi_system_id thermal_dmi_table[] __initdata = { 1818 /* 1819 * Award BIOS on this AOpen makes thermal control almost worthless. 1820 * http://bugzilla.kernel.org/show_bug.cgi?id=8842 1821 */ 1822 { 1823 .callback = thermal_act, 1824 .ident = "AOpen i915GMm-HFS", 1825 .matches = { 1826 DMI_MATCH(DMI_BOARD_VENDOR, "AOpen"), 1827 DMI_MATCH(DMI_BOARD_NAME, "i915GMm-HFS"), 1828 }, 1829 }, 1830 { 1831 .callback = thermal_psv, 1832 .ident = "AOpen i915GMm-HFS", 1833 .matches = { 1834 DMI_MATCH(DMI_BOARD_VENDOR, "AOpen"), 1835 DMI_MATCH(DMI_BOARD_NAME, "i915GMm-HFS"), 1836 }, 1837 }, 1838 { 1839 .callback = thermal_tzp, 1840 .ident = "AOpen i915GMm-HFS", 1841 .matches = { 1842 DMI_MATCH(DMI_BOARD_VENDOR, "AOpen"), 1843 DMI_MATCH(DMI_BOARD_NAME, "i915GMm-HFS"), 1844 }, 1845 }, 1846 { 1847 .callback = thermal_nocrt, 1848 .ident = "Gigabyte GA-7ZX", 1849 .matches = { 1850 DMI_MATCH(DMI_BOARD_VENDOR, "Gigabyte Technology Co., Ltd."), 1851 DMI_MATCH(DMI_BOARD_NAME, "7ZX"), 1852 }, 1853 }, 1854 {} 1855}; 1856 1857static int __init acpi_thermal_init(void) 1858{ 1859 int result = 0; 1860 1861 dmi_check_system(thermal_dmi_table); 1862 1863 if (off) { 1864 printk(KERN_NOTICE "ACPI: thermal control disabled\n"); 1865 return -ENODEV; 1866 } 1867 acpi_thermal_dir = proc_mkdir(ACPI_THERMAL_CLASS, acpi_root_dir); 1868 if (!acpi_thermal_dir) 1869 return -ENODEV; 1870 acpi_thermal_dir->owner = THIS_MODULE; 1871 1872 result = acpi_bus_register_driver(&acpi_thermal_driver); 1873 if (result < 0) { 1874 remove_proc_entry(ACPI_THERMAL_CLASS, acpi_root_dir); 1875 return -ENODEV; 1876 } 1877 1878 return 0; 1879} 1880 1881static void __exit acpi_thermal_exit(void) 1882{ 1883 1884 acpi_bus_unregister_driver(&acpi_thermal_driver); 1885 1886 remove_proc_entry(ACPI_THERMAL_CLASS, acpi_root_dir); 1887 1888 return; 1889} 1890 1891module_init(acpi_thermal_init); 1892module_exit(acpi_thermal_exit);