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