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/init.h> 37 #include <linux/types.h> 38 #include <linux/proc_fs.h> 39 #include <linux/sched.h> 40 #include <linux/kmod.h> 41 #include <linux/seq_file.h> 42 #include <asm/uaccess.h> 43 44 #include <acpi/acpi_bus.h> 45 #include <acpi/acpi_drivers.h> 46 47 #define ACPI_THERMAL_COMPONENT 0x04000000 48 #define ACPI_THERMAL_CLASS "thermal_zone" 49 #define ACPI_THERMAL_DRIVER_NAME "ACPI Thermal Zone Driver" 50 #define ACPI_THERMAL_DEVICE_NAME "Thermal Zone" 51 #define ACPI_THERMAL_FILE_STATE "state" 52 #define ACPI_THERMAL_FILE_TEMPERATURE "temperature" 53 #define ACPI_THERMAL_FILE_TRIP_POINTS "trip_points" 54 #define ACPI_THERMAL_FILE_COOLING_MODE "cooling_mode" 55 #define ACPI_THERMAL_FILE_POLLING_FREQ "polling_frequency" 56 #define ACPI_THERMAL_NOTIFY_TEMPERATURE 0x80 57 #define ACPI_THERMAL_NOTIFY_THRESHOLDS 0x81 58 #define ACPI_THERMAL_NOTIFY_DEVICES 0x82 59 #define ACPI_THERMAL_NOTIFY_CRITICAL 0xF0 60 #define ACPI_THERMAL_NOTIFY_HOT 0xF1 61 #define ACPI_THERMAL_MODE_ACTIVE 0x00 62 #define ACPI_THERMAL_MODE_PASSIVE 0x01 63 #define ACPI_THERMAL_MODE_CRITICAL 0xff 64 #define ACPI_THERMAL_PATH_POWEROFF "/sbin/poweroff" 65 66 #define ACPI_THERMAL_MAX_ACTIVE 10 67 #define ACPI_THERMAL_MAX_LIMIT_STR_LEN 65 68 69 #define KELVIN_TO_CELSIUS(t) (long)(((long)t-2732>=0) ? ((long)t-2732+5)/10 : ((long)t-2732-5)/10) 70 #define CELSIUS_TO_KELVIN(t) ((t+273)*10) 71 72 #define _COMPONENT ACPI_THERMAL_COMPONENT 73 ACPI_MODULE_NAME("acpi_thermal") 74 75 MODULE_AUTHOR("Paul Diefenbaugh"); 76 MODULE_DESCRIPTION(ACPI_THERMAL_DRIVER_NAME); 77 MODULE_LICENSE("GPL"); 78 79 static int tzp; 80 module_param(tzp, int, 0); 81 MODULE_PARM_DESC(tzp, "Thermal zone polling frequency, in 1/10 seconds.\n"); 82 83 static int acpi_thermal_add(struct acpi_device *device); 84 static int acpi_thermal_remove(struct acpi_device *device, int type); 85 static int acpi_thermal_state_open_fs(struct inode *inode, struct file *file); 86 static int acpi_thermal_temp_open_fs(struct inode *inode, struct file *file); 87 static int acpi_thermal_trip_open_fs(struct inode *inode, struct file *file); 88 static ssize_t acpi_thermal_write_trip_points(struct file *, 89 const char __user *, size_t, 90 loff_t *); 91 static int acpi_thermal_cooling_open_fs(struct inode *inode, struct file *file); 92 static ssize_t acpi_thermal_write_cooling_mode(struct file *, 93 const char __user *, size_t, 94 loff_t *); 95 static int acpi_thermal_polling_open_fs(struct inode *inode, struct file *file); 96 static ssize_t acpi_thermal_write_polling(struct file *, const char __user *, 97 size_t, loff_t *); 98 99 static struct acpi_driver acpi_thermal_driver = { 100 .name = ACPI_THERMAL_DRIVER_NAME, 101 .class = ACPI_THERMAL_CLASS, 102 .ids = ACPI_THERMAL_HID, 103 .ops = { 104 .add = acpi_thermal_add, 105 .remove = acpi_thermal_remove, 106 }, 107 }; 108 109 struct acpi_thermal_state { 110 u8 critical:1; 111 u8 hot:1; 112 u8 passive:1; 113 u8 active:1; 114 u8 reserved:4; 115 int active_index; 116 }; 117 118 struct acpi_thermal_state_flags { 119 u8 valid:1; 120 u8 enabled:1; 121 u8 reserved:6; 122 }; 123 124 struct acpi_thermal_critical { 125 struct acpi_thermal_state_flags flags; 126 unsigned long temperature; 127 }; 128 129 struct acpi_thermal_hot { 130 struct acpi_thermal_state_flags flags; 131 unsigned long temperature; 132 }; 133 134 struct acpi_thermal_passive { 135 struct acpi_thermal_state_flags flags; 136 unsigned long temperature; 137 unsigned long tc1; 138 unsigned long tc2; 139 unsigned long tsp; 140 struct acpi_handle_list devices; 141 }; 142 143 struct acpi_thermal_active { 144 struct acpi_thermal_state_flags flags; 145 unsigned long temperature; 146 struct acpi_handle_list devices; 147 }; 148 149 struct acpi_thermal_trips { 150 struct acpi_thermal_critical critical; 151 struct acpi_thermal_hot hot; 152 struct acpi_thermal_passive passive; 153 struct acpi_thermal_active active[ACPI_THERMAL_MAX_ACTIVE]; 154 }; 155 156 struct acpi_thermal_flags { 157 u8 cooling_mode:1; /* _SCP */ 158 u8 devices:1; /* _TZD */ 159 u8 reserved:6; 160 }; 161 162 struct acpi_thermal { 163 acpi_handle handle; 164 acpi_bus_id name; 165 unsigned long temperature; 166 unsigned long last_temperature; 167 unsigned long polling_frequency; 168 u8 cooling_mode; 169 volatile u8 zombie; 170 struct acpi_thermal_flags flags; 171 struct acpi_thermal_state state; 172 struct acpi_thermal_trips trips; 173 struct acpi_handle_list devices; 174 struct timer_list timer; 175 }; 176 177 static struct file_operations acpi_thermal_state_fops = { 178 .open = acpi_thermal_state_open_fs, 179 .read = seq_read, 180 .llseek = seq_lseek, 181 .release = single_release, 182 }; 183 184 static struct file_operations acpi_thermal_temp_fops = { 185 .open = acpi_thermal_temp_open_fs, 186 .read = seq_read, 187 .llseek = seq_lseek, 188 .release = single_release, 189 }; 190 191 static struct file_operations acpi_thermal_trip_fops = { 192 .open = acpi_thermal_trip_open_fs, 193 .read = seq_read, 194 .write = acpi_thermal_write_trip_points, 195 .llseek = seq_lseek, 196 .release = single_release, 197 }; 198 199 static struct file_operations acpi_thermal_cooling_fops = { 200 .open = acpi_thermal_cooling_open_fs, 201 .read = seq_read, 202 .write = acpi_thermal_write_cooling_mode, 203 .llseek = seq_lseek, 204 .release = single_release, 205 }; 206 207 static struct file_operations acpi_thermal_polling_fops = { 208 .open = acpi_thermal_polling_open_fs, 209 .read = seq_read, 210 .write = acpi_thermal_write_polling, 211 .llseek = seq_lseek, 212 .release = single_release, 213 }; 214 215 /* -------------------------------------------------------------------------- 216 Thermal Zone Management 217 -------------------------------------------------------------------------- */ 218 219 static int acpi_thermal_get_temperature(struct acpi_thermal *tz) 220 { 221 acpi_status status = AE_OK; 222 223 ACPI_FUNCTION_TRACE("acpi_thermal_get_temperature"); 224 225 if (!tz) 226 return_VALUE(-EINVAL); 227 228 tz->last_temperature = tz->temperature; 229 230 status = 231 acpi_evaluate_integer(tz->handle, "_TMP", NULL, &tz->temperature); 232 if (ACPI_FAILURE(status)) 233 return_VALUE(-ENODEV); 234 235 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Temperature is %lu dK\n", 236 tz->temperature)); 237 238 return_VALUE(0); 239 } 240 241 static int acpi_thermal_get_polling_frequency(struct acpi_thermal *tz) 242 { 243 acpi_status status = AE_OK; 244 245 ACPI_FUNCTION_TRACE("acpi_thermal_get_polling_frequency"); 246 247 if (!tz) 248 return_VALUE(-EINVAL); 249 250 status = 251 acpi_evaluate_integer(tz->handle, "_TZP", NULL, 252 &tz->polling_frequency); 253 if (ACPI_FAILURE(status)) 254 return_VALUE(-ENODEV); 255 256 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Polling frequency is %lu dS\n", 257 tz->polling_frequency)); 258 259 return_VALUE(0); 260 } 261 262 static int acpi_thermal_set_polling(struct acpi_thermal *tz, int seconds) 263 { 264 ACPI_FUNCTION_TRACE("acpi_thermal_set_polling"); 265 266 if (!tz) 267 return_VALUE(-EINVAL); 268 269 tz->polling_frequency = seconds * 10; /* Convert value to deci-seconds */ 270 271 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 272 "Polling frequency set to %lu seconds\n", 273 tz->polling_frequency)); 274 275 return_VALUE(0); 276 } 277 278 static int acpi_thermal_set_cooling_mode(struct acpi_thermal *tz, int mode) 279 { 280 acpi_status status = AE_OK; 281 union acpi_object arg0 = { ACPI_TYPE_INTEGER }; 282 struct acpi_object_list arg_list = { 1, &arg0 }; 283 acpi_handle handle = NULL; 284 285 ACPI_FUNCTION_TRACE("acpi_thermal_set_cooling_mode"); 286 287 if (!tz) 288 return_VALUE(-EINVAL); 289 290 status = acpi_get_handle(tz->handle, "_SCP", &handle); 291 if (ACPI_FAILURE(status)) { 292 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "_SCP not present\n")); 293 return_VALUE(-ENODEV); 294 } 295 296 arg0.integer.value = mode; 297 298 status = acpi_evaluate_object(handle, NULL, &arg_list, NULL); 299 if (ACPI_FAILURE(status)) 300 return_VALUE(-ENODEV); 301 302 tz->cooling_mode = mode; 303 304 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Cooling mode [%s]\n", 305 mode ? "passive" : "active")); 306 307 return_VALUE(0); 308 } 309 310 static int acpi_thermal_get_trip_points(struct acpi_thermal *tz) 311 { 312 acpi_status status = AE_OK; 313 int i = 0; 314 315 ACPI_FUNCTION_TRACE("acpi_thermal_get_trip_points"); 316 317 if (!tz) 318 return_VALUE(-EINVAL); 319 320 /* Critical Shutdown (required) */ 321 322 status = acpi_evaluate_integer(tz->handle, "_CRT", NULL, 323 &tz->trips.critical.temperature); 324 if (ACPI_FAILURE(status)) { 325 tz->trips.critical.flags.valid = 0; 326 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "No critical threshold\n")); 327 return_VALUE(-ENODEV); 328 } else { 329 tz->trips.critical.flags.valid = 1; 330 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 331 "Found critical threshold [%lu]\n", 332 tz->trips.critical.temperature)); 333 } 334 335 /* Critical Sleep (optional) */ 336 337 status = 338 acpi_evaluate_integer(tz->handle, "_HOT", NULL, 339 &tz->trips.hot.temperature); 340 if (ACPI_FAILURE(status)) { 341 tz->trips.hot.flags.valid = 0; 342 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No hot threshold\n")); 343 } else { 344 tz->trips.hot.flags.valid = 1; 345 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found hot threshold [%lu]\n", 346 tz->trips.hot.temperature)); 347 } 348 349 /* Passive: Processors (optional) */ 350 351 status = 352 acpi_evaluate_integer(tz->handle, "_PSV", NULL, 353 &tz->trips.passive.temperature); 354 if (ACPI_FAILURE(status)) { 355 tz->trips.passive.flags.valid = 0; 356 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No passive threshold\n")); 357 } else { 358 tz->trips.passive.flags.valid = 1; 359 360 status = 361 acpi_evaluate_integer(tz->handle, "_TC1", NULL, 362 &tz->trips.passive.tc1); 363 if (ACPI_FAILURE(status)) 364 tz->trips.passive.flags.valid = 0; 365 366 status = 367 acpi_evaluate_integer(tz->handle, "_TC2", NULL, 368 &tz->trips.passive.tc2); 369 if (ACPI_FAILURE(status)) 370 tz->trips.passive.flags.valid = 0; 371 372 status = 373 acpi_evaluate_integer(tz->handle, "_TSP", NULL, 374 &tz->trips.passive.tsp); 375 if (ACPI_FAILURE(status)) 376 tz->trips.passive.flags.valid = 0; 377 378 status = 379 acpi_evaluate_reference(tz->handle, "_PSL", NULL, 380 &tz->trips.passive.devices); 381 if (ACPI_FAILURE(status)) 382 tz->trips.passive.flags.valid = 0; 383 384 if (!tz->trips.passive.flags.valid) 385 ACPI_DEBUG_PRINT((ACPI_DB_WARN, 386 "Invalid passive threshold\n")); 387 else 388 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 389 "Found passive threshold [%lu]\n", 390 tz->trips.passive.temperature)); 391 } 392 393 /* Active: Fans, etc. (optional) */ 394 395 for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) { 396 397 char name[5] = { '_', 'A', 'C', ('0' + i), '\0' }; 398 399 status = 400 acpi_evaluate_integer(tz->handle, name, NULL, 401 &tz->trips.active[i].temperature); 402 if (ACPI_FAILURE(status)) 403 break; 404 405 name[2] = 'L'; 406 status = 407 acpi_evaluate_reference(tz->handle, name, NULL, 408 &tz->trips.active[i].devices); 409 if (ACPI_SUCCESS(status)) { 410 tz->trips.active[i].flags.valid = 1; 411 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 412 "Found active threshold [%d]:[%lu]\n", 413 i, tz->trips.active[i].temperature)); 414 } else 415 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 416 "Invalid active threshold [%d]\n", 417 i)); 418 } 419 420 return_VALUE(0); 421 } 422 423 static int acpi_thermal_get_devices(struct acpi_thermal *tz) 424 { 425 acpi_status status = AE_OK; 426 427 ACPI_FUNCTION_TRACE("acpi_thermal_get_devices"); 428 429 if (!tz) 430 return_VALUE(-EINVAL); 431 432 status = 433 acpi_evaluate_reference(tz->handle, "_TZD", NULL, &tz->devices); 434 if (ACPI_FAILURE(status)) 435 return_VALUE(-ENODEV); 436 437 return_VALUE(0); 438 } 439 440 static int acpi_thermal_call_usermode(char *path) 441 { 442 char *argv[2] = { NULL, NULL }; 443 char *envp[3] = { NULL, NULL, NULL }; 444 445 ACPI_FUNCTION_TRACE("acpi_thermal_call_usermode"); 446 447 if (!path) 448 return_VALUE(-EINVAL); 449 450 argv[0] = path; 451 452 /* minimal command environment */ 453 envp[0] = "HOME=/"; 454 envp[1] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin"; 455 456 call_usermodehelper(argv[0], argv, envp, 0); 457 458 return_VALUE(0); 459 } 460 461 static int acpi_thermal_critical(struct acpi_thermal *tz) 462 { 463 int result = 0; 464 struct acpi_device *device = NULL; 465 466 ACPI_FUNCTION_TRACE("acpi_thermal_critical"); 467 468 if (!tz || !tz->trips.critical.flags.valid) 469 return_VALUE(-EINVAL); 470 471 if (tz->temperature >= tz->trips.critical.temperature) { 472 ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Critical trip point\n")); 473 tz->trips.critical.flags.enabled = 1; 474 } else if (tz->trips.critical.flags.enabled) 475 tz->trips.critical.flags.enabled = 0; 476 477 result = acpi_bus_get_device(tz->handle, &device); 478 if (result) 479 return_VALUE(result); 480 481 printk(KERN_EMERG 482 "Critical temperature reached (%ld C), shutting down.\n", 483 KELVIN_TO_CELSIUS(tz->temperature)); 484 acpi_bus_generate_event(device, ACPI_THERMAL_NOTIFY_CRITICAL, 485 tz->trips.critical.flags.enabled); 486 487 acpi_thermal_call_usermode(ACPI_THERMAL_PATH_POWEROFF); 488 489 return_VALUE(0); 490 } 491 492 static int acpi_thermal_hot(struct acpi_thermal *tz) 493 { 494 int result = 0; 495 struct acpi_device *device = NULL; 496 497 ACPI_FUNCTION_TRACE("acpi_thermal_hot"); 498 499 if (!tz || !tz->trips.hot.flags.valid) 500 return_VALUE(-EINVAL); 501 502 if (tz->temperature >= tz->trips.hot.temperature) { 503 ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Hot trip point\n")); 504 tz->trips.hot.flags.enabled = 1; 505 } else if (tz->trips.hot.flags.enabled) 506 tz->trips.hot.flags.enabled = 0; 507 508 result = acpi_bus_get_device(tz->handle, &device); 509 if (result) 510 return_VALUE(result); 511 512 acpi_bus_generate_event(device, ACPI_THERMAL_NOTIFY_HOT, 513 tz->trips.hot.flags.enabled); 514 515 /* TBD: Call user-mode "sleep(S4)" function */ 516 517 return_VALUE(0); 518 } 519 520 static int acpi_thermal_passive(struct acpi_thermal *tz) 521 { 522 int result = 0; 523 struct acpi_thermal_passive *passive = NULL; 524 int trend = 0; 525 int i = 0; 526 527 ACPI_FUNCTION_TRACE("acpi_thermal_passive"); 528 529 if (!tz || !tz->trips.passive.flags.valid) 530 return_VALUE(-EINVAL); 531 532 passive = &(tz->trips.passive); 533 534 /* 535 * Above Trip? 536 * ----------- 537 * Calculate the thermal trend (using the passive cooling equation) 538 * and modify the performance limit for all passive cooling devices 539 * accordingly. Note that we assume symmetry. 540 */ 541 if (tz->temperature >= passive->temperature) { 542 trend = 543 (passive->tc1 * (tz->temperature - tz->last_temperature)) + 544 (passive->tc2 * (tz->temperature - passive->temperature)); 545 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 546 "trend[%d]=(tc1[%lu]*(tmp[%lu]-last[%lu]))+(tc2[%lu]*(tmp[%lu]-psv[%lu]))\n", 547 trend, passive->tc1, tz->temperature, 548 tz->last_temperature, passive->tc2, 549 tz->temperature, passive->temperature)); 550 tz->trips.passive.flags.enabled = 1; 551 /* Heating up? */ 552 if (trend > 0) 553 for (i = 0; i < passive->devices.count; i++) 554 acpi_processor_set_thermal_limit(passive-> 555 devices. 556 handles[i], 557 ACPI_PROCESSOR_LIMIT_INCREMENT); 558 /* Cooling off? */ 559 else if (trend < 0) 560 for (i = 0; i < passive->devices.count; i++) 561 acpi_processor_set_thermal_limit(passive-> 562 devices. 563 handles[i], 564 ACPI_PROCESSOR_LIMIT_DECREMENT); 565 } 566 567 /* 568 * Below Trip? 569 * ----------- 570 * Implement passive cooling hysteresis to slowly increase performance 571 * and avoid thrashing around the passive trip point. Note that we 572 * assume symmetry. 573 */ 574 else if (tz->trips.passive.flags.enabled) { 575 for (i = 0; i < passive->devices.count; i++) 576 result = 577 acpi_processor_set_thermal_limit(passive->devices. 578 handles[i], 579 ACPI_PROCESSOR_LIMIT_DECREMENT); 580 if (result == 1) { 581 tz->trips.passive.flags.enabled = 0; 582 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 583 "Disabling passive cooling (zone is cool)\n")); 584 } 585 } 586 587 return_VALUE(0); 588 } 589 590 static int acpi_thermal_active(struct acpi_thermal *tz) 591 { 592 int result = 0; 593 struct acpi_thermal_active *active = NULL; 594 int i = 0; 595 int j = 0; 596 unsigned long maxtemp = 0; 597 598 ACPI_FUNCTION_TRACE("acpi_thermal_active"); 599 600 if (!tz) 601 return_VALUE(-EINVAL); 602 603 for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) { 604 605 active = &(tz->trips.active[i]); 606 if (!active || !active->flags.valid) 607 break; 608 609 /* 610 * Above Threshold? 611 * ---------------- 612 * If not already enabled, turn ON all cooling devices 613 * associated with this active threshold. 614 */ 615 if (tz->temperature >= active->temperature) { 616 if (active->temperature > maxtemp) 617 tz->state.active_index = i, maxtemp = 618 active->temperature; 619 if (!active->flags.enabled) { 620 for (j = 0; j < active->devices.count; j++) { 621 result = 622 acpi_bus_set_power(active->devices. 623 handles[j], 624 ACPI_STATE_D0); 625 if (result) { 626 ACPI_DEBUG_PRINT((ACPI_DB_WARN, 627 "Unable to turn cooling device [%p] 'on'\n", 628 active-> 629 devices. 630 handles[j])); 631 continue; 632 } 633 active->flags.enabled = 1; 634 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 635 "Cooling device [%p] now 'on'\n", 636 active->devices. 637 handles[j])); 638 } 639 } 640 } 641 /* 642 * Below Threshold? 643 * ---------------- 644 * Turn OFF all cooling devices associated with this 645 * threshold. 646 */ 647 else if (active->flags.enabled) { 648 for (j = 0; j < active->devices.count; j++) { 649 result = 650 acpi_bus_set_power(active->devices. 651 handles[j], 652 ACPI_STATE_D3); 653 if (result) { 654 ACPI_DEBUG_PRINT((ACPI_DB_WARN, 655 "Unable to turn cooling device [%p] 'off'\n", 656 active->devices. 657 handles[j])); 658 continue; 659 } 660 active->flags.enabled = 0; 661 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 662 "Cooling device [%p] now 'off'\n", 663 active->devices.handles[j])); 664 } 665 } 666 } 667 668 return_VALUE(0); 669 } 670 671 static void acpi_thermal_check(void *context); 672 673 static void acpi_thermal_run(unsigned long data) 674 { 675 struct acpi_thermal *tz = (struct acpi_thermal *)data; 676 if (!tz->zombie) 677 acpi_os_queue_for_execution(OSD_PRIORITY_GPE, 678 acpi_thermal_check, (void *)data); 679 } 680 681 static void acpi_thermal_check(void *data) 682 { 683 int result = 0; 684 struct acpi_thermal *tz = (struct acpi_thermal *)data; 685 unsigned long sleep_time = 0; 686 int i = 0; 687 struct acpi_thermal_state state; 688 689 ACPI_FUNCTION_TRACE("acpi_thermal_check"); 690 691 if (!tz) { 692 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid (NULL) context.\n")); 693 return_VOID; 694 } 695 696 state = tz->state; 697 698 result = acpi_thermal_get_temperature(tz); 699 if (result) 700 return_VOID; 701 702 memset(&tz->state, 0, sizeof(tz->state)); 703 704 /* 705 * Check Trip Points 706 * ----------------- 707 * Compare the current temperature to the trip point values to see 708 * if we've entered one of the thermal policy states. Note that 709 * this function determines when a state is entered, but the 710 * individual policy decides when it is exited (e.g. hysteresis). 711 */ 712 if (tz->trips.critical.flags.valid) 713 state.critical |= 714 (tz->temperature >= tz->trips.critical.temperature); 715 if (tz->trips.hot.flags.valid) 716 state.hot |= (tz->temperature >= tz->trips.hot.temperature); 717 if (tz->trips.passive.flags.valid) 718 state.passive |= 719 (tz->temperature >= tz->trips.passive.temperature); 720 for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) 721 if (tz->trips.active[i].flags.valid) 722 state.active |= 723 (tz->temperature >= 724 tz->trips.active[i].temperature); 725 726 /* 727 * Invoke Policy 728 * ------------- 729 * Separated from the above check to allow individual policy to 730 * determine when to exit a given state. 731 */ 732 if (state.critical) 733 acpi_thermal_critical(tz); 734 if (state.hot) 735 acpi_thermal_hot(tz); 736 if (state.passive) 737 acpi_thermal_passive(tz); 738 if (state.active) 739 acpi_thermal_active(tz); 740 741 /* 742 * Calculate State 743 * --------------- 744 * Again, separated from the above two to allow independent policy 745 * decisions. 746 */ 747 if (tz->trips.critical.flags.enabled) 748 tz->state.critical = 1; 749 if (tz->trips.hot.flags.enabled) 750 tz->state.hot = 1; 751 if (tz->trips.passive.flags.enabled) 752 tz->state.passive = 1; 753 for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) 754 if (tz->trips.active[i].flags.enabled) 755 tz->state.active = 1; 756 757 /* 758 * Calculate Sleep Time 759 * -------------------- 760 * If we're in the passive state, use _TSP's value. Otherwise 761 * use the default polling frequency (e.g. _TZP). If no polling 762 * frequency is specified then we'll wait forever (at least until 763 * a thermal event occurs). Note that _TSP and _TZD values are 764 * given in 1/10th seconds (we must covert to milliseconds). 765 */ 766 if (tz->state.passive) 767 sleep_time = tz->trips.passive.tsp * 100; 768 else if (tz->polling_frequency > 0) 769 sleep_time = tz->polling_frequency * 100; 770 771 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%s: temperature[%lu] sleep[%lu]\n", 772 tz->name, tz->temperature, sleep_time)); 773 774 /* 775 * Schedule Next Poll 776 * ------------------ 777 */ 778 if (!sleep_time) { 779 if (timer_pending(&(tz->timer))) 780 del_timer(&(tz->timer)); 781 } else { 782 if (timer_pending(&(tz->timer))) 783 mod_timer(&(tz->timer), (HZ * sleep_time) / 1000); 784 else { 785 tz->timer.data = (unsigned long)tz; 786 tz->timer.function = acpi_thermal_run; 787 tz->timer.expires = jiffies + (HZ * sleep_time) / 1000; 788 add_timer(&(tz->timer)); 789 } 790 } 791 792 return_VOID; 793 } 794 795 /* -------------------------------------------------------------------------- 796 FS Interface (/proc) 797 -------------------------------------------------------------------------- */ 798 799 static struct proc_dir_entry *acpi_thermal_dir; 800 801 static int acpi_thermal_state_seq_show(struct seq_file *seq, void *offset) 802 { 803 struct acpi_thermal *tz = (struct acpi_thermal *)seq->private; 804 805 ACPI_FUNCTION_TRACE("acpi_thermal_state_seq_show"); 806 807 if (!tz) 808 goto end; 809 810 seq_puts(seq, "state: "); 811 812 if (!tz->state.critical && !tz->state.hot && !tz->state.passive 813 && !tz->state.active) 814 seq_puts(seq, "ok\n"); 815 else { 816 if (tz->state.critical) 817 seq_puts(seq, "critical "); 818 if (tz->state.hot) 819 seq_puts(seq, "hot "); 820 if (tz->state.passive) 821 seq_puts(seq, "passive "); 822 if (tz->state.active) 823 seq_printf(seq, "active[%d]", tz->state.active_index); 824 seq_puts(seq, "\n"); 825 } 826 827 end: 828 return_VALUE(0); 829 } 830 831 static int acpi_thermal_state_open_fs(struct inode *inode, struct file *file) 832 { 833 return single_open(file, acpi_thermal_state_seq_show, PDE(inode)->data); 834 } 835 836 static int acpi_thermal_temp_seq_show(struct seq_file *seq, void *offset) 837 { 838 int result = 0; 839 struct acpi_thermal *tz = (struct acpi_thermal *)seq->private; 840 841 ACPI_FUNCTION_TRACE("acpi_thermal_temp_seq_show"); 842 843 if (!tz) 844 goto end; 845 846 result = acpi_thermal_get_temperature(tz); 847 if (result) 848 goto end; 849 850 seq_printf(seq, "temperature: %ld C\n", 851 KELVIN_TO_CELSIUS(tz->temperature)); 852 853 end: 854 return_VALUE(0); 855 } 856 857 static int acpi_thermal_temp_open_fs(struct inode *inode, struct file *file) 858 { 859 return single_open(file, acpi_thermal_temp_seq_show, PDE(inode)->data); 860 } 861 862 static int acpi_thermal_trip_seq_show(struct seq_file *seq, void *offset) 863 { 864 struct acpi_thermal *tz = (struct acpi_thermal *)seq->private; 865 int i = 0; 866 int j = 0; 867 868 ACPI_FUNCTION_TRACE("acpi_thermal_trip_seq_show"); 869 870 if (!tz) 871 goto end; 872 873 if (tz->trips.critical.flags.valid) 874 seq_printf(seq, "critical (S5): %ld C\n", 875 KELVIN_TO_CELSIUS(tz->trips.critical.temperature)); 876 877 if (tz->trips.hot.flags.valid) 878 seq_printf(seq, "hot (S4): %ld C\n", 879 KELVIN_TO_CELSIUS(tz->trips.hot.temperature)); 880 881 if (tz->trips.passive.flags.valid) { 882 seq_printf(seq, 883 "passive: %ld C: tc1=%lu tc2=%lu tsp=%lu devices=", 884 KELVIN_TO_CELSIUS(tz->trips.passive.temperature), 885 tz->trips.passive.tc1, tz->trips.passive.tc2, 886 tz->trips.passive.tsp); 887 for (j = 0; j < tz->trips.passive.devices.count; j++) { 888 889 seq_printf(seq, "0x%p ", 890 tz->trips.passive.devices.handles[j]); 891 } 892 seq_puts(seq, "\n"); 893 } 894 895 for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) { 896 if (!(tz->trips.active[i].flags.valid)) 897 break; 898 seq_printf(seq, "active[%d]: %ld C: devices=", 899 i, 900 KELVIN_TO_CELSIUS(tz->trips.active[i].temperature)); 901 for (j = 0; j < tz->trips.active[i].devices.count; j++) 902 seq_printf(seq, "0x%p ", 903 tz->trips.active[i].devices.handles[j]); 904 seq_puts(seq, "\n"); 905 } 906 907 end: 908 return_VALUE(0); 909 } 910 911 static int acpi_thermal_trip_open_fs(struct inode *inode, struct file *file) 912 { 913 return single_open(file, acpi_thermal_trip_seq_show, PDE(inode)->data); 914 } 915 916 static ssize_t 917 acpi_thermal_write_trip_points(struct file *file, 918 const char __user * buffer, 919 size_t count, loff_t * ppos) 920 { 921 struct seq_file *m = (struct seq_file *)file->private_data; 922 struct acpi_thermal *tz = (struct acpi_thermal *)m->private; 923 924 char *limit_string; 925 int num, critical, hot, passive; 926 int *active; 927 int i = 0; 928 929 ACPI_FUNCTION_TRACE("acpi_thermal_write_trip_points"); 930 931 limit_string = kmalloc(ACPI_THERMAL_MAX_LIMIT_STR_LEN, GFP_KERNEL); 932 if (!limit_string) 933 return_VALUE(-ENOMEM); 934 935 memset(limit_string, 0, ACPI_THERMAL_MAX_LIMIT_STR_LEN); 936 937 active = kmalloc(ACPI_THERMAL_MAX_ACTIVE * sizeof(int), GFP_KERNEL); 938 if (!active) 939 return_VALUE(-ENOMEM); 940 941 if (!tz || (count > ACPI_THERMAL_MAX_LIMIT_STR_LEN - 1)) { 942 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid argument\n")); 943 count = -EINVAL; 944 goto end; 945 } 946 947 if (copy_from_user(limit_string, buffer, count)) { 948 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid data\n")); 949 count = -EFAULT; 950 goto end; 951 } 952 953 limit_string[count] = '\0'; 954 955 num = sscanf(limit_string, "%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d", 956 &critical, &hot, &passive, 957 &active[0], &active[1], &active[2], &active[3], &active[4], 958 &active[5], &active[6], &active[7], &active[8], 959 &active[9]); 960 if (!(num >= 5 && num < (ACPI_THERMAL_MAX_ACTIVE + 3))) { 961 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid data format\n")); 962 count = -EINVAL; 963 goto end; 964 } 965 966 tz->trips.critical.temperature = CELSIUS_TO_KELVIN(critical); 967 tz->trips.hot.temperature = CELSIUS_TO_KELVIN(hot); 968 tz->trips.passive.temperature = CELSIUS_TO_KELVIN(passive); 969 for (i = 0; i < num - 3; i++) { 970 if (!(tz->trips.active[i].flags.valid)) 971 break; 972 tz->trips.active[i].temperature = CELSIUS_TO_KELVIN(active[i]); 973 } 974 975 end: 976 kfree(active); 977 kfree(limit_string); 978 return_VALUE(count); 979 } 980 981 static int acpi_thermal_cooling_seq_show(struct seq_file *seq, void *offset) 982 { 983 struct acpi_thermal *tz = (struct acpi_thermal *)seq->private; 984 985 ACPI_FUNCTION_TRACE("acpi_thermal_cooling_seq_show"); 986 987 if (!tz) 988 goto end; 989 990 if (!tz->flags.cooling_mode) { 991 seq_puts(seq, "<setting not supported>\n"); 992 } 993 994 if (tz->cooling_mode == ACPI_THERMAL_MODE_CRITICAL) 995 seq_printf(seq, "cooling mode: critical\n"); 996 else 997 seq_printf(seq, "cooling mode: %s\n", 998 tz->cooling_mode ? "passive" : "active"); 999 1000 end: 1001 return_VALUE(0); 1002 } 1003 1004 static int acpi_thermal_cooling_open_fs(struct inode *inode, struct file *file) 1005 { 1006 return single_open(file, acpi_thermal_cooling_seq_show, 1007 PDE(inode)->data); 1008 } 1009 1010 static ssize_t 1011 acpi_thermal_write_cooling_mode(struct file *file, 1012 const char __user * buffer, 1013 size_t count, loff_t * ppos) 1014 { 1015 struct seq_file *m = (struct seq_file *)file->private_data; 1016 struct acpi_thermal *tz = (struct acpi_thermal *)m->private; 1017 int result = 0; 1018 char mode_string[12] = { '\0' }; 1019 1020 ACPI_FUNCTION_TRACE("acpi_thermal_write_cooling_mode"); 1021 1022 if (!tz || (count > sizeof(mode_string) - 1)) 1023 return_VALUE(-EINVAL); 1024 1025 if (!tz->flags.cooling_mode) 1026 return_VALUE(-ENODEV); 1027 1028 if (copy_from_user(mode_string, buffer, count)) 1029 return_VALUE(-EFAULT); 1030 1031 mode_string[count] = '\0'; 1032 1033 result = acpi_thermal_set_cooling_mode(tz, 1034 simple_strtoul(mode_string, NULL, 1035 0)); 1036 if (result) 1037 return_VALUE(result); 1038 1039 acpi_thermal_check(tz); 1040 1041 return_VALUE(count); 1042 } 1043 1044 static int acpi_thermal_polling_seq_show(struct seq_file *seq, void *offset) 1045 { 1046 struct acpi_thermal *tz = (struct acpi_thermal *)seq->private; 1047 1048 ACPI_FUNCTION_TRACE("acpi_thermal_polling_seq_show"); 1049 1050 if (!tz) 1051 goto end; 1052 1053 if (!tz->polling_frequency) { 1054 seq_puts(seq, "<polling disabled>\n"); 1055 goto end; 1056 } 1057 1058 seq_printf(seq, "polling frequency: %lu seconds\n", 1059 (tz->polling_frequency / 10)); 1060 1061 end: 1062 return_VALUE(0); 1063 } 1064 1065 static int acpi_thermal_polling_open_fs(struct inode *inode, struct file *file) 1066 { 1067 return single_open(file, acpi_thermal_polling_seq_show, 1068 PDE(inode)->data); 1069 } 1070 1071 static ssize_t 1072 acpi_thermal_write_polling(struct file *file, 1073 const char __user * buffer, 1074 size_t count, loff_t * ppos) 1075 { 1076 struct seq_file *m = (struct seq_file *)file->private_data; 1077 struct acpi_thermal *tz = (struct acpi_thermal *)m->private; 1078 int result = 0; 1079 char polling_string[12] = { '\0' }; 1080 int seconds = 0; 1081 1082 ACPI_FUNCTION_TRACE("acpi_thermal_write_polling"); 1083 1084 if (!tz || (count > sizeof(polling_string) - 1)) 1085 return_VALUE(-EINVAL); 1086 1087 if (copy_from_user(polling_string, buffer, count)) 1088 return_VALUE(-EFAULT); 1089 1090 polling_string[count] = '\0'; 1091 1092 seconds = simple_strtoul(polling_string, NULL, 0); 1093 1094 result = acpi_thermal_set_polling(tz, seconds); 1095 if (result) 1096 return_VALUE(result); 1097 1098 acpi_thermal_check(tz); 1099 1100 return_VALUE(count); 1101 } 1102 1103 static int acpi_thermal_add_fs(struct acpi_device *device) 1104 { 1105 struct proc_dir_entry *entry = NULL; 1106 1107 ACPI_FUNCTION_TRACE("acpi_thermal_add_fs"); 1108 1109 if (!acpi_device_dir(device)) { 1110 acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), 1111 acpi_thermal_dir); 1112 if (!acpi_device_dir(device)) 1113 return_VALUE(-ENODEV); 1114 acpi_device_dir(device)->owner = THIS_MODULE; 1115 } 1116 1117 /* 'state' [R] */ 1118 entry = create_proc_entry(ACPI_THERMAL_FILE_STATE, 1119 S_IRUGO, acpi_device_dir(device)); 1120 if (!entry) 1121 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 1122 "Unable to create '%s' fs entry\n", 1123 ACPI_THERMAL_FILE_STATE)); 1124 else { 1125 entry->proc_fops = &acpi_thermal_state_fops; 1126 entry->data = acpi_driver_data(device); 1127 entry->owner = THIS_MODULE; 1128 } 1129 1130 /* 'temperature' [R] */ 1131 entry = create_proc_entry(ACPI_THERMAL_FILE_TEMPERATURE, 1132 S_IRUGO, acpi_device_dir(device)); 1133 if (!entry) 1134 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 1135 "Unable to create '%s' fs entry\n", 1136 ACPI_THERMAL_FILE_TEMPERATURE)); 1137 else { 1138 entry->proc_fops = &acpi_thermal_temp_fops; 1139 entry->data = acpi_driver_data(device); 1140 entry->owner = THIS_MODULE; 1141 } 1142 1143 /* 'trip_points' [R/W] */ 1144 entry = create_proc_entry(ACPI_THERMAL_FILE_TRIP_POINTS, 1145 S_IFREG | S_IRUGO | S_IWUSR, 1146 acpi_device_dir(device)); 1147 if (!entry) 1148 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 1149 "Unable to create '%s' fs entry\n", 1150 ACPI_THERMAL_FILE_TRIP_POINTS)); 1151 else { 1152 entry->proc_fops = &acpi_thermal_trip_fops; 1153 entry->data = acpi_driver_data(device); 1154 entry->owner = THIS_MODULE; 1155 } 1156 1157 /* 'cooling_mode' [R/W] */ 1158 entry = create_proc_entry(ACPI_THERMAL_FILE_COOLING_MODE, 1159 S_IFREG | S_IRUGO | S_IWUSR, 1160 acpi_device_dir(device)); 1161 if (!entry) 1162 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 1163 "Unable to create '%s' fs entry\n", 1164 ACPI_THERMAL_FILE_COOLING_MODE)); 1165 else { 1166 entry->proc_fops = &acpi_thermal_cooling_fops; 1167 entry->data = acpi_driver_data(device); 1168 entry->owner = THIS_MODULE; 1169 } 1170 1171 /* 'polling_frequency' [R/W] */ 1172 entry = create_proc_entry(ACPI_THERMAL_FILE_POLLING_FREQ, 1173 S_IFREG | S_IRUGO | S_IWUSR, 1174 acpi_device_dir(device)); 1175 if (!entry) 1176 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 1177 "Unable to create '%s' fs entry\n", 1178 ACPI_THERMAL_FILE_POLLING_FREQ)); 1179 else { 1180 entry->proc_fops = &acpi_thermal_polling_fops; 1181 entry->data = acpi_driver_data(device); 1182 entry->owner = THIS_MODULE; 1183 } 1184 1185 return_VALUE(0); 1186 } 1187 1188 static int acpi_thermal_remove_fs(struct acpi_device *device) 1189 { 1190 ACPI_FUNCTION_TRACE("acpi_thermal_remove_fs"); 1191 1192 if (acpi_device_dir(device)) { 1193 remove_proc_entry(ACPI_THERMAL_FILE_POLLING_FREQ, 1194 acpi_device_dir(device)); 1195 remove_proc_entry(ACPI_THERMAL_FILE_COOLING_MODE, 1196 acpi_device_dir(device)); 1197 remove_proc_entry(ACPI_THERMAL_FILE_TRIP_POINTS, 1198 acpi_device_dir(device)); 1199 remove_proc_entry(ACPI_THERMAL_FILE_TEMPERATURE, 1200 acpi_device_dir(device)); 1201 remove_proc_entry(ACPI_THERMAL_FILE_STATE, 1202 acpi_device_dir(device)); 1203 remove_proc_entry(acpi_device_bid(device), acpi_thermal_dir); 1204 acpi_device_dir(device) = NULL; 1205 } 1206 1207 return_VALUE(0); 1208 } 1209 1210 /* -------------------------------------------------------------------------- 1211 Driver Interface 1212 -------------------------------------------------------------------------- */ 1213 1214 static void acpi_thermal_notify(acpi_handle handle, u32 event, void *data) 1215 { 1216 struct acpi_thermal *tz = (struct acpi_thermal *)data; 1217 struct acpi_device *device = NULL; 1218 1219 ACPI_FUNCTION_TRACE("acpi_thermal_notify"); 1220 1221 if (!tz) 1222 return_VOID; 1223 1224 if (acpi_bus_get_device(tz->handle, &device)) 1225 return_VOID; 1226 1227 switch (event) { 1228 case ACPI_THERMAL_NOTIFY_TEMPERATURE: 1229 acpi_thermal_check(tz); 1230 break; 1231 case ACPI_THERMAL_NOTIFY_THRESHOLDS: 1232 acpi_thermal_get_trip_points(tz); 1233 acpi_thermal_check(tz); 1234 acpi_bus_generate_event(device, event, 0); 1235 break; 1236 case ACPI_THERMAL_NOTIFY_DEVICES: 1237 if (tz->flags.devices) 1238 acpi_thermal_get_devices(tz); 1239 acpi_bus_generate_event(device, event, 0); 1240 break; 1241 default: 1242 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 1243 "Unsupported event [0x%x]\n", event)); 1244 break; 1245 } 1246 1247 return_VOID; 1248 } 1249 1250 static int acpi_thermal_get_info(struct acpi_thermal *tz) 1251 { 1252 int result = 0; 1253 1254 ACPI_FUNCTION_TRACE("acpi_thermal_get_info"); 1255 1256 if (!tz) 1257 return_VALUE(-EINVAL); 1258 1259 /* Get temperature [_TMP] (required) */ 1260 result = acpi_thermal_get_temperature(tz); 1261 if (result) 1262 return_VALUE(result); 1263 1264 /* Get trip points [_CRT, _PSV, etc.] (required) */ 1265 result = acpi_thermal_get_trip_points(tz); 1266 if (result) 1267 return_VALUE(result); 1268 1269 /* Set the cooling mode [_SCP] to active cooling (default) */ 1270 result = acpi_thermal_set_cooling_mode(tz, ACPI_THERMAL_MODE_ACTIVE); 1271 if (!result) 1272 tz->flags.cooling_mode = 1; 1273 else { 1274 /* Oh,we have not _SCP method. 1275 Generally show cooling_mode by _ACx, _PSV,spec 12.2 */ 1276 tz->flags.cooling_mode = 0; 1277 if (tz->trips.active[0].flags.valid 1278 && tz->trips.passive.flags.valid) { 1279 if (tz->trips.passive.temperature > 1280 tz->trips.active[0].temperature) 1281 tz->cooling_mode = ACPI_THERMAL_MODE_ACTIVE; 1282 else 1283 tz->cooling_mode = ACPI_THERMAL_MODE_PASSIVE; 1284 } else if (!tz->trips.active[0].flags.valid 1285 && tz->trips.passive.flags.valid) { 1286 tz->cooling_mode = ACPI_THERMAL_MODE_PASSIVE; 1287 } else if (tz->trips.active[0].flags.valid 1288 && !tz->trips.passive.flags.valid) { 1289 tz->cooling_mode = ACPI_THERMAL_MODE_ACTIVE; 1290 } else { 1291 /* _ACx and _PSV are optional, but _CRT is required */ 1292 tz->cooling_mode = ACPI_THERMAL_MODE_CRITICAL; 1293 } 1294 } 1295 1296 /* Get default polling frequency [_TZP] (optional) */ 1297 if (tzp) 1298 tz->polling_frequency = tzp; 1299 else 1300 acpi_thermal_get_polling_frequency(tz); 1301 1302 /* Get devices in this thermal zone [_TZD] (optional) */ 1303 result = acpi_thermal_get_devices(tz); 1304 if (!result) 1305 tz->flags.devices = 1; 1306 1307 return_VALUE(0); 1308 } 1309 1310 static int acpi_thermal_add(struct acpi_device *device) 1311 { 1312 int result = 0; 1313 acpi_status status = AE_OK; 1314 struct acpi_thermal *tz = NULL; 1315 1316 ACPI_FUNCTION_TRACE("acpi_thermal_add"); 1317 1318 if (!device) 1319 return_VALUE(-EINVAL); 1320 1321 tz = kmalloc(sizeof(struct acpi_thermal), GFP_KERNEL); 1322 if (!tz) 1323 return_VALUE(-ENOMEM); 1324 memset(tz, 0, sizeof(struct acpi_thermal)); 1325 1326 tz->handle = device->handle; 1327 strcpy(tz->name, device->pnp.bus_id); 1328 strcpy(acpi_device_name(device), ACPI_THERMAL_DEVICE_NAME); 1329 strcpy(acpi_device_class(device), ACPI_THERMAL_CLASS); 1330 acpi_driver_data(device) = tz; 1331 1332 result = acpi_thermal_get_info(tz); 1333 if (result) 1334 goto end; 1335 1336 result = acpi_thermal_add_fs(device); 1337 if (result) 1338 return_VALUE(result); 1339 1340 init_timer(&tz->timer); 1341 1342 acpi_thermal_check(tz); 1343 1344 status = acpi_install_notify_handler(tz->handle, 1345 ACPI_DEVICE_NOTIFY, 1346 acpi_thermal_notify, tz); 1347 if (ACPI_FAILURE(status)) { 1348 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 1349 "Error installing notify handler\n")); 1350 result = -ENODEV; 1351 goto end; 1352 } 1353 1354 printk(KERN_INFO PREFIX "%s [%s] (%ld C)\n", 1355 acpi_device_name(device), acpi_device_bid(device), 1356 KELVIN_TO_CELSIUS(tz->temperature)); 1357 1358 end: 1359 if (result) { 1360 acpi_thermal_remove_fs(device); 1361 kfree(tz); 1362 } 1363 1364 return_VALUE(result); 1365 } 1366 1367 static int acpi_thermal_remove(struct acpi_device *device, int type) 1368 { 1369 acpi_status status = AE_OK; 1370 struct acpi_thermal *tz = NULL; 1371 1372 ACPI_FUNCTION_TRACE("acpi_thermal_remove"); 1373 1374 if (!device || !acpi_driver_data(device)) 1375 return_VALUE(-EINVAL); 1376 1377 tz = (struct acpi_thermal *)acpi_driver_data(device); 1378 1379 /* avoid timer adding new defer task */ 1380 tz->zombie = 1; 1381 /* wait for running timer (on other CPUs) finish */ 1382 del_timer_sync(&(tz->timer)); 1383 /* synchronize deferred task */ 1384 acpi_os_wait_events_complete(NULL); 1385 /* deferred task may reinsert timer */ 1386 del_timer_sync(&(tz->timer)); 1387 1388 status = acpi_remove_notify_handler(tz->handle, 1389 ACPI_DEVICE_NOTIFY, 1390 acpi_thermal_notify); 1391 if (ACPI_FAILURE(status)) 1392 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 1393 "Error removing notify handler\n")); 1394 1395 /* Terminate policy */ 1396 if (tz->trips.passive.flags.valid && tz->trips.passive.flags.enabled) { 1397 tz->trips.passive.flags.enabled = 0; 1398 acpi_thermal_passive(tz); 1399 } 1400 if (tz->trips.active[0].flags.valid 1401 && tz->trips.active[0].flags.enabled) { 1402 tz->trips.active[0].flags.enabled = 0; 1403 acpi_thermal_active(tz); 1404 } 1405 1406 acpi_thermal_remove_fs(device); 1407 1408 kfree(tz); 1409 return_VALUE(0); 1410 } 1411 1412 static int __init acpi_thermal_init(void) 1413 { 1414 int result = 0; 1415 1416 ACPI_FUNCTION_TRACE("acpi_thermal_init"); 1417 1418 acpi_thermal_dir = proc_mkdir(ACPI_THERMAL_CLASS, acpi_root_dir); 1419 if (!acpi_thermal_dir) 1420 return_VALUE(-ENODEV); 1421 acpi_thermal_dir->owner = THIS_MODULE; 1422 1423 result = acpi_bus_register_driver(&acpi_thermal_driver); 1424 if (result < 0) { 1425 remove_proc_entry(ACPI_THERMAL_CLASS, acpi_root_dir); 1426 return_VALUE(-ENODEV); 1427 } 1428 1429 return_VALUE(0); 1430 } 1431 1432 static void __exit acpi_thermal_exit(void) 1433 { 1434 ACPI_FUNCTION_TRACE("acpi_thermal_exit"); 1435 1436 acpi_bus_unregister_driver(&acpi_thermal_driver); 1437 1438 remove_proc_entry(ACPI_THERMAL_CLASS, acpi_root_dir); 1439 1440 return_VOID; 1441 } 1442 1443 module_init(acpi_thermal_init); 1444 module_exit(acpi_thermal_exit); 1445