aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/thermal.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi/thermal.c')
-rw-r--r--drivers/acpi/thermal.c646
1 files changed, 492 insertions, 154 deletions
diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
index 3a0af9a8cd27..8d4b79b4f933 100644
--- a/drivers/acpi/thermal.c
+++ b/drivers/acpi/thermal.c
@@ -43,7 +43,7 @@
43#include <linux/seq_file.h> 43#include <linux/seq_file.h>
44#include <linux/reboot.h> 44#include <linux/reboot.h>
45#include <asm/uaccess.h> 45#include <asm/uaccess.h>
46 46#include <linux/thermal.h>
47#include <acpi/acpi_bus.h> 47#include <acpi/acpi_bus.h>
48#include <acpi/acpi_drivers.h> 48#include <acpi/acpi_drivers.h>
49 49
@@ -65,9 +65,6 @@
65#define ACPI_THERMAL_MAX_ACTIVE 10 65#define ACPI_THERMAL_MAX_ACTIVE 10
66#define ACPI_THERMAL_MAX_LIMIT_STR_LEN 65 66#define ACPI_THERMAL_MAX_LIMIT_STR_LEN 65
67 67
68#define KELVIN_TO_CELSIUS(t) (long)(((long)t-2732>=0) ? ((long)t-2732+5)/10 : ((long)t-2732-5)/10)
69#define CELSIUS_TO_KELVIN(t) ((t+273)*10)
70
71#define _COMPONENT ACPI_THERMAL_COMPONENT 68#define _COMPONENT ACPI_THERMAL_COMPONENT
72ACPI_MODULE_NAME("thermal"); 69ACPI_MODULE_NAME("thermal");
73 70
@@ -195,6 +192,8 @@ struct acpi_thermal {
195 struct acpi_thermal_trips trips; 192 struct acpi_thermal_trips trips;
196 struct acpi_handle_list devices; 193 struct acpi_handle_list devices;
197 struct timer_list timer; 194 struct timer_list timer;
195 struct thermal_zone_device *thermal_zone;
196 int tz_enabled;
198 struct mutex lock; 197 struct mutex lock;
199}; 198};
200 199
@@ -321,173 +320,221 @@ static int acpi_thermal_set_cooling_mode(struct acpi_thermal *tz, int mode)
321 return 0; 320 return 0;
322} 321}
323 322
324static int acpi_thermal_get_trip_points(struct acpi_thermal *tz) 323#define ACPI_TRIPS_CRITICAL 0x01
325{ 324#define ACPI_TRIPS_HOT 0x02
326 acpi_status status = AE_OK; 325#define ACPI_TRIPS_PASSIVE 0x04
327 int i = 0; 326#define ACPI_TRIPS_ACTIVE 0x08
327#define ACPI_TRIPS_DEVICES 0x10
328 328
329#define ACPI_TRIPS_REFRESH_THRESHOLDS (ACPI_TRIPS_PASSIVE | ACPI_TRIPS_ACTIVE)
330#define ACPI_TRIPS_REFRESH_DEVICES ACPI_TRIPS_DEVICES
329 331
330 if (!tz) 332#define ACPI_TRIPS_INIT (ACPI_TRIPS_CRITICAL | ACPI_TRIPS_HOT | \
331 return -EINVAL; 333 ACPI_TRIPS_PASSIVE | ACPI_TRIPS_ACTIVE | \
334 ACPI_TRIPS_DEVICES)
332 335
333 /* Critical Shutdown (required) */ 336/*
334 337 * This exception is thrown out in two cases:
335 status = acpi_evaluate_integer(tz->device->handle, "_CRT", NULL, 338 * 1.An invalid trip point becomes invalid or a valid trip point becomes invalid
336 &tz->trips.critical.temperature); 339 * when re-evaluating the AML code.
337 if (ACPI_FAILURE(status)) { 340 * 2.TODO: Devices listed in _PSL, _ALx, _TZD may change.
338 tz->trips.critical.flags.valid = 0; 341 * We need to re-bind the cooling devices of a thermal zone when this occurs.
339 ACPI_EXCEPTION((AE_INFO, status, "No critical threshold")); 342 */
340 return -ENODEV; 343#define ACPI_THERMAL_TRIPS_EXCEPTION(flags, str) \
341 } else { 344do { \
342 tz->trips.critical.flags.valid = 1; 345 if (flags != ACPI_TRIPS_INIT) \
343 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 346 ACPI_EXCEPTION((AE_INFO, AE_ERROR, \
344 "Found critical threshold [%lu]\n", 347 "ACPI thermal trip point %s changed\n" \
345 tz->trips.critical.temperature)); 348 "Please send acpidump to linux-acpi@vger.kernel.org\n", str)); \
346 } 349} while (0)
350
351static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
352{
353 acpi_status status = AE_OK;
354 struct acpi_handle_list devices;
355 int valid = 0;
356 int i;
347 357
348 if (tz->trips.critical.flags.valid == 1) { 358 /* Critical Shutdown (required) */
349 if (crt == -1) { 359 if (flag & ACPI_TRIPS_CRITICAL) {
360 status = acpi_evaluate_integer(tz->device->handle,
361 "_CRT", NULL, &tz->trips.critical.temperature);
362 if (ACPI_FAILURE(status)) {
350 tz->trips.critical.flags.valid = 0; 363 tz->trips.critical.flags.valid = 0;
351 } else if (crt > 0) { 364 ACPI_EXCEPTION((AE_INFO, status,
352 unsigned long crt_k = CELSIUS_TO_KELVIN(crt); 365 "No critical threshold"));
353 366 return -ENODEV;
354 /* 367 } else {
355 * Allow override to lower critical threshold 368 tz->trips.critical.flags.valid = 1;
356 */ 369 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
357 if (crt_k < tz->trips.critical.temperature) 370 "Found critical threshold [%lu]\n",
358 tz->trips.critical.temperature = crt_k; 371 tz->trips.critical.temperature));
372 }
373 if (tz->trips.critical.flags.valid == 1) {
374 if (crt == -1) {
375 tz->trips.critical.flags.valid = 0;
376 } else if (crt > 0) {
377 unsigned long crt_k = CELSIUS_TO_KELVIN(crt);
378 /*
379 * Allow override to lower critical threshold
380 */
381 if (crt_k < tz->trips.critical.temperature)
382 tz->trips.critical.temperature = crt_k;
383 }
359 } 384 }
360 } 385 }
361 386
362 /* Critical Sleep (optional) */ 387 /* Critical Sleep (optional) */
363 388 if (flag & ACPI_TRIPS_HOT) {
364 status =
365 acpi_evaluate_integer(tz->device->handle, "_HOT", NULL,
366 &tz->trips.hot.temperature);
367 if (ACPI_FAILURE(status)) {
368 tz->trips.hot.flags.valid = 0;
369 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No hot threshold\n"));
370 } else {
371 tz->trips.hot.flags.valid = 1;
372 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found hot threshold [%lu]\n",
373 tz->trips.hot.temperature));
374 }
375
376 /* Passive: Processors (optional) */
377
378 if (psv == -1) {
379 status = AE_SUPPORT;
380 } else if (psv > 0) {
381 tz->trips.passive.temperature = CELSIUS_TO_KELVIN(psv);
382 status = AE_OK;
383 } else {
384 status = acpi_evaluate_integer(tz->device->handle, 389 status = acpi_evaluate_integer(tz->device->handle,
385 "_PSV", NULL, &tz->trips.passive.temperature); 390 "_HOT", NULL, &tz->trips.hot.temperature);
391 if (ACPI_FAILURE(status)) {
392 tz->trips.hot.flags.valid = 0;
393 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
394 "No hot threshold\n"));
395 } else {
396 tz->trips.hot.flags.valid = 1;
397 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
398 "Found hot threshold [%lu]\n",
399 tz->trips.critical.temperature));
400 }
386 } 401 }
387 402
388 if (ACPI_FAILURE(status)) { 403 /* Passive (optional) */
389 tz->trips.passive.flags.valid = 0; 404 if (flag & ACPI_TRIPS_PASSIVE) {
390 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No passive threshold\n")); 405 valid = tz->trips.passive.flags.valid;
391 } else { 406 if (psv == -1) {
392 tz->trips.passive.flags.valid = 1; 407 status = AE_SUPPORT;
393 408 } else if (psv > 0) {
394 status = 409 tz->trips.passive.temperature = CELSIUS_TO_KELVIN(psv);
395 acpi_evaluate_integer(tz->device->handle, "_TC1", NULL, 410 status = AE_OK;
396 &tz->trips.passive.tc1); 411 } else {
397 if (ACPI_FAILURE(status)) 412 status = acpi_evaluate_integer(tz->device->handle,
398 tz->trips.passive.flags.valid = 0; 413 "_PSV", NULL, &tz->trips.passive.temperature);
399 414 }
400 status =
401 acpi_evaluate_integer(tz->device->handle, "_TC2", NULL,
402 &tz->trips.passive.tc2);
403 if (ACPI_FAILURE(status))
404 tz->trips.passive.flags.valid = 0;
405 415
406 status =
407 acpi_evaluate_integer(tz->device->handle, "_TSP", NULL,
408 &tz->trips.passive.tsp);
409 if (ACPI_FAILURE(status)) 416 if (ACPI_FAILURE(status))
410 tz->trips.passive.flags.valid = 0; 417 tz->trips.passive.flags.valid = 0;
411 418 else {
412 status = 419 tz->trips.passive.flags.valid = 1;
413 acpi_evaluate_reference(tz->device->handle, "_PSL", NULL, 420 if (flag == ACPI_TRIPS_INIT) {
414 &tz->trips.passive.devices); 421 status = acpi_evaluate_integer(
422 tz->device->handle, "_TC1",
423 NULL, &tz->trips.passive.tc1);
424 if (ACPI_FAILURE(status))
425 tz->trips.passive.flags.valid = 0;
426 status = acpi_evaluate_integer(
427 tz->device->handle, "_TC2",
428 NULL, &tz->trips.passive.tc2);
429 if (ACPI_FAILURE(status))
430 tz->trips.passive.flags.valid = 0;
431 status = acpi_evaluate_integer(
432 tz->device->handle, "_TSP",
433 NULL, &tz->trips.passive.tsp);
434 if (ACPI_FAILURE(status))
435 tz->trips.passive.flags.valid = 0;
436 }
437 }
438 }
439 if ((flag & ACPI_TRIPS_DEVICES) && tz->trips.passive.flags.valid) {
440 memset(&devices, 0, sizeof(struct acpi_handle_list));
441 status = acpi_evaluate_reference(tz->device->handle, "_PSL",
442 NULL, &devices);
415 if (ACPI_FAILURE(status)) 443 if (ACPI_FAILURE(status))
416 tz->trips.passive.flags.valid = 0; 444 tz->trips.passive.flags.valid = 0;
417
418 if (!tz->trips.passive.flags.valid)
419 printk(KERN_WARNING PREFIX "Invalid passive threshold\n");
420 else 445 else
421 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 446 tz->trips.passive.flags.valid = 1;
422 "Found passive threshold [%lu]\n",
423 tz->trips.passive.temperature));
424 }
425 447
426 /* Active: Fans, etc. (optional) */ 448 if (memcmp(&tz->trips.passive.devices, &devices,
449 sizeof(struct acpi_handle_list))) {
450 memcpy(&tz->trips.passive.devices, &devices,
451 sizeof(struct acpi_handle_list));
452 ACPI_THERMAL_TRIPS_EXCEPTION(flag, "device");
453 }
454 }
455 if ((flag & ACPI_TRIPS_PASSIVE) || (flag & ACPI_TRIPS_DEVICES)) {
456 if (valid != tz->trips.passive.flags.valid)
457 ACPI_THERMAL_TRIPS_EXCEPTION(flag, "state");
458 }
427 459
460 /* Active (optional) */
428 for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) { 461 for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
429
430 char name[5] = { '_', 'A', 'C', ('0' + i), '\0' }; 462 char name[5] = { '_', 'A', 'C', ('0' + i), '\0' };
463 valid = tz->trips.active[i].flags.valid;
431 464
432 if (act == -1) 465 if (act == -1)
433 break; /* disable all active trip points */ 466 break; /* disable all active trip points */
434 467
435 status = acpi_evaluate_integer(tz->device->handle, 468 if (flag & ACPI_TRIPS_ACTIVE) {
436 name, NULL, &tz->trips.active[i].temperature); 469 status = acpi_evaluate_integer(tz->device->handle,
437 470 name, NULL, &tz->trips.active[i].temperature);
438 if (ACPI_FAILURE(status)) { 471 if (ACPI_FAILURE(status)) {
439 if (i == 0) /* no active trip points */ 472 tz->trips.active[i].flags.valid = 0;
473 if (i == 0)
474 break;
475 if (act <= 0)
476 break;
477 if (i == 1)
478 tz->trips.active[0].temperature =
479 CELSIUS_TO_KELVIN(act);
480 else
481 /*
482 * Don't allow override higher than
483 * the next higher trip point
484 */
485 tz->trips.active[i - 1].temperature =
486 (tz->trips.active[i - 2].temperature <
487 CELSIUS_TO_KELVIN(act) ?
488 tz->trips.active[i - 2].temperature :
489 CELSIUS_TO_KELVIN(act));
440 break; 490 break;
441 if (act <= 0) /* no override requested */ 491 } else
442 break; 492 tz->trips.active[i].flags.valid = 1;
443 if (i == 1) { /* 1 trip point */
444 tz->trips.active[0].temperature =
445 CELSIUS_TO_KELVIN(act);
446 } else { /* multiple trips */
447 /*
448 * Don't allow override higher than
449 * the next higher trip point
450 */
451 tz->trips.active[i - 1].temperature =
452 (tz->trips.active[i - 2].temperature <
453 CELSIUS_TO_KELVIN(act) ?
454 tz->trips.active[i - 2].temperature :
455 CELSIUS_TO_KELVIN(act));
456 }
457 break;
458 } 493 }
459 494
460 name[2] = 'L'; 495 name[2] = 'L';
461 status = 496 if ((flag & ACPI_TRIPS_DEVICES) && tz->trips.active[i].flags.valid ) {
462 acpi_evaluate_reference(tz->device->handle, name, NULL, 497 memset(&devices, 0, sizeof(struct acpi_handle_list));
463 &tz->trips.active[i].devices); 498 status = acpi_evaluate_reference(tz->device->handle,
464 if (ACPI_SUCCESS(status)) { 499 name, NULL, &devices);
465 tz->trips.active[i].flags.valid = 1; 500 if (ACPI_FAILURE(status))
466 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 501 tz->trips.active[i].flags.valid = 0;
467 "Found active threshold [%d]:[%lu]\n", 502 else
468 i, tz->trips.active[i].temperature)); 503 tz->trips.active[i].flags.valid = 1;
469 } else 504
470 ACPI_EXCEPTION((AE_INFO, status, 505 if (memcmp(&tz->trips.active[i].devices, &devices,
471 "Invalid active threshold [%d]", i)); 506 sizeof(struct acpi_handle_list))) {
507 memcpy(&tz->trips.active[i].devices, &devices,
508 sizeof(struct acpi_handle_list));
509 ACPI_THERMAL_TRIPS_EXCEPTION(flag, "device");
510 }
511 }
512 if ((flag & ACPI_TRIPS_ACTIVE) || (flag & ACPI_TRIPS_DEVICES))
513 if (valid != tz->trips.active[i].flags.valid)
514 ACPI_THERMAL_TRIPS_EXCEPTION(flag, "state");
515
516 if (!tz->trips.active[i].flags.valid)
517 break;
518 }
519
520 if (flag & ACPI_TRIPS_DEVICES) {
521 memset(&devices, 0, sizeof(struct acpi_handle_list));
522 status = acpi_evaluate_reference(tz->device->handle, "_TZD",
523 NULL, &devices);
524 if (memcmp(&tz->devices, &devices,
525 sizeof(struct acpi_handle_list))) {
526 memcpy(&tz->devices, &devices,
527 sizeof(struct acpi_handle_list));
528 ACPI_THERMAL_TRIPS_EXCEPTION(flag, "device");
529 }
472 } 530 }
473 531
474 return 0; 532 return 0;
475} 533}
476 534
477static int acpi_thermal_get_devices(struct acpi_thermal *tz) 535static int acpi_thermal_get_trip_points(struct acpi_thermal *tz)
478{ 536{
479 acpi_status status = AE_OK; 537 return acpi_thermal_trips_update(tz, ACPI_TRIPS_INIT);
480
481
482 if (!tz)
483 return -EINVAL;
484
485 status =
486 acpi_evaluate_reference(tz->device->handle, "_TZD", NULL, &tz->devices);
487 if (ACPI_FAILURE(status))
488 return -ENODEV;
489
490 return 0;
491} 538}
492 539
493static int acpi_thermal_critical(struct acpi_thermal *tz) 540static int acpi_thermal_critical(struct acpi_thermal *tz)
@@ -735,6 +782,9 @@ static void acpi_thermal_check(void *data)
735 if (result) 782 if (result)
736 goto unlock; 783 goto unlock;
737 784
785 if (!tz->tz_enabled)
786 goto unlock;
787
738 memset(&tz->state, 0, sizeof(tz->state)); 788 memset(&tz->state, 0, sizeof(tz->state));
739 789
740 /* 790 /*
@@ -828,6 +878,290 @@ static void acpi_thermal_check(void *data)
828 mutex_unlock(&tz->lock); 878 mutex_unlock(&tz->lock);
829} 879}
830 880
881/* sys I/F for generic thermal sysfs support */
882static int thermal_get_temp(struct thermal_zone_device *thermal, char *buf)
883{
884 struct acpi_thermal *tz = thermal->devdata;
885
886 if (!tz)
887 return -EINVAL;
888
889 return sprintf(buf, "%ld\n", KELVIN_TO_CELSIUS(tz->temperature));
890}
891
892static const char enabled[] = "kernel";
893static const char disabled[] = "user";
894static int thermal_get_mode(struct thermal_zone_device *thermal,
895 char *buf)
896{
897 struct acpi_thermal *tz = thermal->devdata;
898
899 if (!tz)
900 return -EINVAL;
901
902 return sprintf(buf, "%s\n", tz->tz_enabled ?
903 enabled : disabled);
904}
905
906static int thermal_set_mode(struct thermal_zone_device *thermal,
907 const char *buf)
908{
909 struct acpi_thermal *tz = thermal->devdata;
910 int enable;
911
912 if (!tz)
913 return -EINVAL;
914
915 /*
916 * enable/disable thermal management from ACPI thermal driver
917 */
918 if (!strncmp(buf, enabled, sizeof enabled - 1))
919 enable = 1;
920 else if (!strncmp(buf, disabled, sizeof disabled - 1))
921 enable = 0;
922 else
923 return -EINVAL;
924
925 if (enable != tz->tz_enabled) {
926 tz->tz_enabled = enable;
927 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
928 "%s ACPI thermal control\n",
929 tz->tz_enabled ? enabled : disabled));
930 acpi_thermal_check(tz);
931 }
932 return 0;
933}
934
935static int thermal_get_trip_type(struct thermal_zone_device *thermal,
936 int trip, char *buf)
937{
938 struct acpi_thermal *tz = thermal->devdata;
939 int i;
940
941 if (!tz || trip < 0)
942 return -EINVAL;
943
944 if (tz->trips.critical.flags.valid) {
945 if (!trip)
946 return sprintf(buf, "critical\n");
947 trip--;
948 }
949
950 if (tz->trips.hot.flags.valid) {
951 if (!trip)
952 return sprintf(buf, "hot\n");
953 trip--;
954 }
955
956 if (tz->trips.passive.flags.valid) {
957 if (!trip)
958 return sprintf(buf, "passive\n");
959 trip--;
960 }
961
962 for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE &&
963 tz->trips.active[i].flags.valid; i++) {
964 if (!trip)
965 return sprintf(buf, "active%d\n", i);
966 trip--;
967 }
968
969 return -EINVAL;
970}
971
972static int thermal_get_trip_temp(struct thermal_zone_device *thermal,
973 int trip, char *buf)
974{
975 struct acpi_thermal *tz = thermal->devdata;
976 int i;
977
978 if (!tz || trip < 0)
979 return -EINVAL;
980
981 if (tz->trips.critical.flags.valid) {
982 if (!trip)
983 return sprintf(buf, "%ld\n", KELVIN_TO_CELSIUS(
984 tz->trips.critical.temperature));
985 trip--;
986 }
987
988 if (tz->trips.hot.flags.valid) {
989 if (!trip)
990 return sprintf(buf, "%ld\n", KELVIN_TO_CELSIUS(
991 tz->trips.hot.temperature));
992 trip--;
993 }
994
995 if (tz->trips.passive.flags.valid) {
996 if (!trip)
997 return sprintf(buf, "%ld\n", KELVIN_TO_CELSIUS(
998 tz->trips.passive.temperature));
999 trip--;
1000 }
1001
1002 for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE &&
1003 tz->trips.active[i].flags.valid; i++) {
1004 if (!trip)
1005 return sprintf(buf, "%ld\n", KELVIN_TO_CELSIUS(
1006 tz->trips.active[i].temperature));
1007 trip--;
1008 }
1009
1010 return -EINVAL;
1011}
1012
1013typedef int (*cb)(struct thermal_zone_device *, int,
1014 struct thermal_cooling_device *);
1015static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal,
1016 struct thermal_cooling_device *cdev,
1017 cb action)
1018{
1019 struct acpi_device *device = cdev->devdata;
1020 struct acpi_thermal *tz = thermal->devdata;
1021 struct acpi_device *dev;
1022 acpi_status status;
1023 acpi_handle handle;
1024 int i;
1025 int j;
1026 int trip = -1;
1027 int result = 0;
1028
1029 if (tz->trips.critical.flags.valid)
1030 trip++;
1031
1032 if (tz->trips.hot.flags.valid)
1033 trip++;
1034
1035 if (tz->trips.passive.flags.valid) {
1036 trip++;
1037 for (i = 0; i < tz->trips.passive.devices.count;
1038 i++) {
1039 handle = tz->trips.passive.devices.handles[i];
1040 status = acpi_bus_get_device(handle, &dev);
1041 if (ACPI_SUCCESS(status) && (dev == device)) {
1042 result = action(thermal, trip, cdev);
1043 if (result)
1044 goto failed;
1045 }
1046 }
1047 }
1048
1049 for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
1050 if (!tz->trips.active[i].flags.valid)
1051 break;
1052 trip++;
1053 for (j = 0;
1054 j < tz->trips.active[i].devices.count;
1055 j++) {
1056 handle = tz->trips.active[i].devices.handles[j];
1057 status = acpi_bus_get_device(handle, &dev);
1058 if (ACPI_SUCCESS(status) && (dev == device)) {
1059 result = action(thermal, trip, cdev);
1060 if (result)
1061 goto failed;
1062 }
1063 }
1064 }
1065
1066 for (i = 0; i < tz->devices.count; i++) {
1067 handle = tz->devices.handles[i];
1068 status = acpi_bus_get_device(handle, &dev);
1069 if (ACPI_SUCCESS(status) && (dev == device)) {
1070 result = action(thermal, -1, cdev);
1071 if (result)
1072 goto failed;
1073 }
1074 }
1075
1076failed:
1077 return result;
1078}
1079
1080static int
1081acpi_thermal_bind_cooling_device(struct thermal_zone_device *thermal,
1082 struct thermal_cooling_device *cdev)
1083{
1084 return acpi_thermal_cooling_device_cb(thermal, cdev,
1085 thermal_zone_bind_cooling_device);
1086}
1087
1088static int
1089acpi_thermal_unbind_cooling_device(struct thermal_zone_device *thermal,
1090 struct thermal_cooling_device *cdev)
1091{
1092 return acpi_thermal_cooling_device_cb(thermal, cdev,
1093 thermal_zone_unbind_cooling_device);
1094}
1095
1096static struct thermal_zone_device_ops acpi_thermal_zone_ops = {
1097 .bind = acpi_thermal_bind_cooling_device,
1098 .unbind = acpi_thermal_unbind_cooling_device,
1099 .get_temp = thermal_get_temp,
1100 .get_mode = thermal_get_mode,
1101 .set_mode = thermal_set_mode,
1102 .get_trip_type = thermal_get_trip_type,
1103 .get_trip_temp = thermal_get_trip_temp,
1104};
1105
1106static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz)
1107{
1108 int trips = 0;
1109 int result;
1110 acpi_status status;
1111 int i;
1112
1113 if (tz->trips.critical.flags.valid)
1114 trips++;
1115
1116 if (tz->trips.hot.flags.valid)
1117 trips++;
1118
1119 if (tz->trips.passive.flags.valid)
1120 trips++;
1121
1122 for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE &&
1123 tz->trips.active[i].flags.valid; i++, trips++);
1124 tz->thermal_zone = thermal_zone_device_register("ACPI thermal zone",
1125 trips, tz, &acpi_thermal_zone_ops);
1126 if (!tz->thermal_zone)
1127 return -ENODEV;
1128
1129 result = sysfs_create_link(&tz->device->dev.kobj,
1130 &tz->thermal_zone->device.kobj, "thermal_zone");
1131 if (result)
1132 return result;
1133
1134 result = sysfs_create_link(&tz->thermal_zone->device.kobj,
1135 &tz->device->dev.kobj, "device");
1136 if (result)
1137 return result;
1138
1139 status = acpi_attach_data(tz->device->handle,
1140 acpi_bus_private_data_handler,
1141 tz->thermal_zone);
1142 if (ACPI_FAILURE(status)) {
1143 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
1144 "Error attaching device data\n"));
1145 return -ENODEV;
1146 }
1147
1148 tz->tz_enabled = 1;
1149
1150 printk(KERN_INFO PREFIX "%s is registered as thermal_zone%d\n",
1151 tz->device->dev.bus_id, tz->thermal_zone->id);
1152 return 0;
1153}
1154
1155static void acpi_thermal_unregister_thermal_zone(struct acpi_thermal *tz)
1156{
1157 sysfs_remove_link(&tz->device->dev.kobj, "thermal_zone");
1158 sysfs_remove_link(&tz->thermal_zone->device.kobj, "device");
1159 thermal_zone_device_unregister(tz->thermal_zone);
1160 tz->thermal_zone = NULL;
1161 acpi_detach_data(tz->device->handle, acpi_bus_private_data_handler);
1162}
1163
1164
831/* -------------------------------------------------------------------------- 1165/* --------------------------------------------------------------------------
832 FS Interface (/proc) 1166 FS Interface (/proc)
833 -------------------------------------------------------------------------- */ 1167 -------------------------------------------------------------------------- */
@@ -1184,15 +1518,15 @@ static void acpi_thermal_notify(acpi_handle handle, u32 event, void *data)
1184 acpi_thermal_check(tz); 1518 acpi_thermal_check(tz);
1185 break; 1519 break;
1186 case ACPI_THERMAL_NOTIFY_THRESHOLDS: 1520 case ACPI_THERMAL_NOTIFY_THRESHOLDS:
1187 acpi_thermal_get_trip_points(tz); 1521 acpi_thermal_trips_update(tz, ACPI_TRIPS_REFRESH_THRESHOLDS);
1188 acpi_thermal_check(tz); 1522 acpi_thermal_check(tz);
1189 acpi_bus_generate_proc_event(device, event, 0); 1523 acpi_bus_generate_proc_event(device, event, 0);
1190 acpi_bus_generate_netlink_event(device->pnp.device_class, 1524 acpi_bus_generate_netlink_event(device->pnp.device_class,
1191 device->dev.bus_id, event, 0); 1525 device->dev.bus_id, event, 0);
1192 break; 1526 break;
1193 case ACPI_THERMAL_NOTIFY_DEVICES: 1527 case ACPI_THERMAL_NOTIFY_DEVICES:
1194 if (tz->flags.devices) 1528 acpi_thermal_trips_update(tz, ACPI_TRIPS_REFRESH_DEVICES);
1195 acpi_thermal_get_devices(tz); 1529 acpi_thermal_check(tz);
1196 acpi_bus_generate_proc_event(device, event, 0); 1530 acpi_bus_generate_proc_event(device, event, 0);
1197 acpi_bus_generate_netlink_event(device->pnp.device_class, 1531 acpi_bus_generate_netlink_event(device->pnp.device_class,
1198 device->dev.bus_id, event, 0); 1532 device->dev.bus_id, event, 0);
@@ -1235,11 +1569,6 @@ static int acpi_thermal_get_info(struct acpi_thermal *tz)
1235 else 1569 else
1236 acpi_thermal_get_polling_frequency(tz); 1570 acpi_thermal_get_polling_frequency(tz);
1237 1571
1238 /* Get devices in this thermal zone [_TZD] (optional) */
1239 result = acpi_thermal_get_devices(tz);
1240 if (!result)
1241 tz->flags.devices = 1;
1242
1243 return 0; 1572 return 0;
1244} 1573}
1245 1574
@@ -1263,13 +1592,19 @@ static int acpi_thermal_add(struct acpi_device *device)
1263 strcpy(acpi_device_class(device), ACPI_THERMAL_CLASS); 1592 strcpy(acpi_device_class(device), ACPI_THERMAL_CLASS);
1264 acpi_driver_data(device) = tz; 1593 acpi_driver_data(device) = tz;
1265 mutex_init(&tz->lock); 1594 mutex_init(&tz->lock);
1595
1596
1266 result = acpi_thermal_get_info(tz); 1597 result = acpi_thermal_get_info(tz);
1267 if (result) 1598 if (result)
1268 goto end; 1599 goto free_memory;
1600
1601 result = acpi_thermal_register_thermal_zone(tz);
1602 if (result)
1603 goto free_memory;
1269 1604
1270 result = acpi_thermal_add_fs(device); 1605 result = acpi_thermal_add_fs(device);
1271 if (result) 1606 if (result)
1272 goto end; 1607 goto unregister_thermal_zone;
1273 1608
1274 init_timer(&tz->timer); 1609 init_timer(&tz->timer);
1275 1610
@@ -1280,19 +1615,21 @@ static int acpi_thermal_add(struct acpi_device *device)
1280 acpi_thermal_notify, tz); 1615 acpi_thermal_notify, tz);
1281 if (ACPI_FAILURE(status)) { 1616 if (ACPI_FAILURE(status)) {
1282 result = -ENODEV; 1617 result = -ENODEV;
1283 goto end; 1618 goto remove_fs;
1284 } 1619 }
1285 1620
1286 printk(KERN_INFO PREFIX "%s [%s] (%ld C)\n", 1621 printk(KERN_INFO PREFIX "%s [%s] (%ld C)\n",
1287 acpi_device_name(device), acpi_device_bid(device), 1622 acpi_device_name(device), acpi_device_bid(device),
1288 KELVIN_TO_CELSIUS(tz->temperature)); 1623 KELVIN_TO_CELSIUS(tz->temperature));
1624 goto end;
1289 1625
1290 end: 1626remove_fs:
1291 if (result) { 1627 acpi_thermal_remove_fs(device);
1292 acpi_thermal_remove_fs(device); 1628unregister_thermal_zone:
1293 kfree(tz); 1629 thermal_zone_device_unregister(tz->thermal_zone);
1294 } 1630free_memory:
1295 1631 kfree(tz);
1632end:
1296 return result; 1633 return result;
1297} 1634}
1298 1635
@@ -1332,6 +1669,7 @@ static int acpi_thermal_remove(struct acpi_device *device, int type)
1332 } 1669 }
1333 1670
1334 acpi_thermal_remove_fs(device); 1671 acpi_thermal_remove_fs(device);
1672 acpi_thermal_unregister_thermal_zone(tz);
1335 mutex_destroy(&tz->lock); 1673 mutex_destroy(&tz->lock);
1336 kfree(tz); 1674 kfree(tz);
1337 return 0; 1675 return 0;