2 * acpi_thermal.c - ACPI Thermal Zone Driver ($Revision: 41 $)
4 * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
5 * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
7 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
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.
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.
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.
23 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25 * This driver fully implements the ACPI thermal policy as described in the
26 * ACPI 2.0 Specification.
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.
34 #include <linux/kernel.h>
35 #include <linux/module.h>
36 #include <linux/dmi.h>
37 #include <linux/init.h>
38 #include <linux/types.h>
39 #include <linux/proc_fs.h>
40 #include <linux/jiffies.h>
41 #include <linux/kmod.h>
42 #include <linux/seq_file.h>
43 #include <linux/reboot.h>
44 #include <linux/device.h>
45 #include <linux/dmi.h>
46 #include <asm/uaccess.h>
47 #include <linux/thermal.h>
48 #include <acpi/acpi_bus.h>
49 #include <acpi/acpi_drivers.h>
51 #define PREFIX "ACPI: "
53 #define ACPI_THERMAL_CLASS "thermal_zone"
54 #define ACPI_THERMAL_DEVICE_NAME "Thermal Zone"
55 #define ACPI_THERMAL_FILE_STATE "state"
56 #define ACPI_THERMAL_FILE_TEMPERATURE "temperature"
57 #define ACPI_THERMAL_FILE_TRIP_POINTS "trip_points"
58 #define ACPI_THERMAL_FILE_COOLING_MODE "cooling_mode"
59 #define ACPI_THERMAL_FILE_POLLING_FREQ "polling_frequency"
60 #define ACPI_THERMAL_NOTIFY_TEMPERATURE 0x80
61 #define ACPI_THERMAL_NOTIFY_THRESHOLDS 0x81
62 #define ACPI_THERMAL_NOTIFY_DEVICES 0x82
63 #define ACPI_THERMAL_NOTIFY_CRITICAL 0xF0
64 #define ACPI_THERMAL_NOTIFY_HOT 0xF1
65 #define ACPI_THERMAL_MODE_ACTIVE 0x00
67 #define ACPI_THERMAL_MAX_ACTIVE 10
68 #define ACPI_THERMAL_MAX_LIMIT_STR_LEN 65
70 #define _COMPONENT ACPI_THERMAL_COMPONENT
71 ACPI_MODULE_NAME("thermal");
73 MODULE_AUTHOR("Paul Diefenbaugh");
74 MODULE_DESCRIPTION("ACPI Thermal Zone Driver");
75 MODULE_LICENSE("GPL");
78 module_param(act, int, 0644);
79 MODULE_PARM_DESC(act, "Disable or override all lowest active trip points.");
82 module_param(crt, int, 0644);
83 MODULE_PARM_DESC(crt, "Disable or lower all critical trip points.");
86 module_param(tzp, int, 0444);
87 MODULE_PARM_DESC(tzp, "Thermal zone polling frequency, in 1/10 seconds.");
90 module_param(nocrt, int, 0);
91 MODULE_PARM_DESC(nocrt, "Set to take no action upon ACPI thermal zone critical trips points.");
94 module_param(off, int, 0);
95 MODULE_PARM_DESC(off, "Set to disable ACPI thermal support.");
98 module_param(psv, int, 0644);
99 MODULE_PARM_DESC(psv, "Disable or override all passive trip points.");
101 static int acpi_thermal_add(struct acpi_device *device);
102 static int acpi_thermal_remove(struct acpi_device *device, int type);
103 static int acpi_thermal_resume(struct acpi_device *device);
104 static void acpi_thermal_notify(struct acpi_device *device, u32 event);
105 static int acpi_thermal_state_open_fs(struct inode *inode, struct file *file);
106 static int acpi_thermal_temp_open_fs(struct inode *inode, struct file *file);
107 static int acpi_thermal_trip_open_fs(struct inode *inode, struct file *file);
108 static int acpi_thermal_cooling_open_fs(struct inode *inode, struct file *file);
109 static ssize_t acpi_thermal_write_cooling_mode(struct file *,
110 const char __user *, size_t,
112 static int acpi_thermal_polling_open_fs(struct inode *inode, struct file *file);
113 static ssize_t acpi_thermal_write_polling(struct file *, const char __user *,
116 static const struct acpi_device_id thermal_device_ids[] = {
117 {ACPI_THERMAL_HID, 0},
120 MODULE_DEVICE_TABLE(acpi, thermal_device_ids);
122 static struct acpi_driver acpi_thermal_driver = {
124 .class = ACPI_THERMAL_CLASS,
125 .ids = thermal_device_ids,
127 .add = acpi_thermal_add,
128 .remove = acpi_thermal_remove,
129 .resume = acpi_thermal_resume,
130 .notify = acpi_thermal_notify,
134 struct acpi_thermal_state {
143 struct acpi_thermal_state_flags {
149 struct acpi_thermal_critical {
150 struct acpi_thermal_state_flags flags;
151 unsigned long temperature;
154 struct acpi_thermal_hot {
155 struct acpi_thermal_state_flags flags;
156 unsigned long temperature;
159 struct acpi_thermal_passive {
160 struct acpi_thermal_state_flags flags;
161 unsigned long temperature;
165 struct acpi_handle_list devices;
168 struct acpi_thermal_active {
169 struct acpi_thermal_state_flags flags;
170 unsigned long temperature;
171 struct acpi_handle_list devices;
174 struct acpi_thermal_trips {
175 struct acpi_thermal_critical critical;
176 struct acpi_thermal_hot hot;
177 struct acpi_thermal_passive passive;
178 struct acpi_thermal_active active[ACPI_THERMAL_MAX_ACTIVE];
181 struct acpi_thermal_flags {
182 u8 cooling_mode:1; /* _SCP */
183 u8 devices:1; /* _TZD */
187 struct acpi_thermal {
188 struct acpi_device * device;
190 unsigned long temperature;
191 unsigned long last_temperature;
192 unsigned long polling_frequency;
194 struct acpi_thermal_flags flags;
195 struct acpi_thermal_state state;
196 struct acpi_thermal_trips trips;
197 struct acpi_handle_list devices;
198 struct thermal_zone_device *thermal_zone;
204 static const struct file_operations acpi_thermal_state_fops = {
205 .owner = THIS_MODULE,
206 .open = acpi_thermal_state_open_fs,
209 .release = single_release,
212 static const struct file_operations acpi_thermal_temp_fops = {
213 .owner = THIS_MODULE,
214 .open = acpi_thermal_temp_open_fs,
217 .release = single_release,
220 static const struct file_operations acpi_thermal_trip_fops = {
221 .owner = THIS_MODULE,
222 .open = acpi_thermal_trip_open_fs,
225 .release = single_release,
228 static const struct file_operations acpi_thermal_cooling_fops = {
229 .owner = THIS_MODULE,
230 .open = acpi_thermal_cooling_open_fs,
232 .write = acpi_thermal_write_cooling_mode,
234 .release = single_release,
237 static const struct file_operations acpi_thermal_polling_fops = {
238 .owner = THIS_MODULE,
239 .open = acpi_thermal_polling_open_fs,
241 .write = acpi_thermal_write_polling,
243 .release = single_release,
246 /* --------------------------------------------------------------------------
247 Thermal Zone Management
248 -------------------------------------------------------------------------- */
250 static int acpi_thermal_get_temperature(struct acpi_thermal *tz)
252 acpi_status status = AE_OK;
253 unsigned long long tmp;
258 tz->last_temperature = tz->temperature;
260 status = acpi_evaluate_integer(tz->device->handle, "_TMP", NULL, &tmp);
261 if (ACPI_FAILURE(status))
264 tz->temperature = tmp;
265 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Temperature is %lu dK\n",
271 static int acpi_thermal_get_polling_frequency(struct acpi_thermal *tz)
273 acpi_status status = AE_OK;
274 unsigned long long tmp;
279 status = acpi_evaluate_integer(tz->device->handle, "_TZP", NULL, &tmp);
280 if (ACPI_FAILURE(status))
283 tz->polling_frequency = tmp;
284 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Polling frequency is %lu dS\n",
285 tz->polling_frequency));
290 static int acpi_thermal_set_polling(struct acpi_thermal *tz, int seconds)
296 tz->polling_frequency = seconds * 10; /* Convert value to deci-seconds */
298 tz->thermal_zone->polling_delay = seconds * 1000;
301 thermal_zone_device_update(tz->thermal_zone);
303 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
304 "Polling frequency set to %lu seconds\n",
305 tz->polling_frequency/10));
310 static int acpi_thermal_set_cooling_mode(struct acpi_thermal *tz, int mode)
312 acpi_status status = AE_OK;
313 union acpi_object arg0 = { ACPI_TYPE_INTEGER };
314 struct acpi_object_list arg_list = { 1, &arg0 };
315 acpi_handle handle = NULL;
321 status = acpi_get_handle(tz->device->handle, "_SCP", &handle);
322 if (ACPI_FAILURE(status)) {
323 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "_SCP not present\n"));
327 arg0.integer.value = mode;
329 status = acpi_evaluate_object(handle, NULL, &arg_list, NULL);
330 if (ACPI_FAILURE(status))
336 #define ACPI_TRIPS_CRITICAL 0x01
337 #define ACPI_TRIPS_HOT 0x02
338 #define ACPI_TRIPS_PASSIVE 0x04
339 #define ACPI_TRIPS_ACTIVE 0x08
340 #define ACPI_TRIPS_DEVICES 0x10
342 #define ACPI_TRIPS_REFRESH_THRESHOLDS (ACPI_TRIPS_PASSIVE | ACPI_TRIPS_ACTIVE)
343 #define ACPI_TRIPS_REFRESH_DEVICES ACPI_TRIPS_DEVICES
345 #define ACPI_TRIPS_INIT (ACPI_TRIPS_CRITICAL | ACPI_TRIPS_HOT | \
346 ACPI_TRIPS_PASSIVE | ACPI_TRIPS_ACTIVE | \
350 * This exception is thrown out in two cases:
351 * 1.An invalid trip point becomes invalid or a valid trip point becomes invalid
352 * when re-evaluating the AML code.
353 * 2.TODO: Devices listed in _PSL, _ALx, _TZD may change.
354 * We need to re-bind the cooling devices of a thermal zone when this occurs.
356 #define ACPI_THERMAL_TRIPS_EXCEPTION(flags, str) \
358 if (flags != ACPI_TRIPS_INIT) \
359 ACPI_EXCEPTION((AE_INFO, AE_ERROR, \
360 "ACPI thermal trip point %s changed\n" \
361 "Please send acpidump to linux-acpi@vger.kernel.org\n", str)); \
364 static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
366 acpi_status status = AE_OK;
367 unsigned long long tmp;
368 struct acpi_handle_list devices;
372 /* Critical Shutdown (required) */
373 if (flag & ACPI_TRIPS_CRITICAL) {
374 status = acpi_evaluate_integer(tz->device->handle,
376 tz->trips.critical.temperature = tmp;
378 * Treat freezing temperatures as invalid as well; some
379 * BIOSes return really low values and cause reboots at startup.
380 * Below zero (Celsius) values clearly aren't right for sure..
381 * ... so lets discard those as invalid.
383 if (ACPI_FAILURE(status) ||
384 tz->trips.critical.temperature <= 2732) {
385 tz->trips.critical.flags.valid = 0;
386 ACPI_EXCEPTION((AE_INFO, status,
387 "No or invalid critical threshold"));
390 tz->trips.critical.flags.valid = 1;
391 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
392 "Found critical threshold [%lu]\n",
393 tz->trips.critical.temperature));
395 if (tz->trips.critical.flags.valid == 1) {
397 tz->trips.critical.flags.valid = 0;
398 } else if (crt > 0) {
399 unsigned long crt_k = CELSIUS_TO_KELVIN(crt);
401 * Allow override critical threshold
403 if (crt_k > tz->trips.critical.temperature)
404 printk(KERN_WARNING PREFIX
405 "Critical threshold %d C\n", crt);
406 tz->trips.critical.temperature = crt_k;
411 /* Critical Sleep (optional) */
412 if (flag & ACPI_TRIPS_HOT) {
413 status = acpi_evaluate_integer(tz->device->handle,
415 if (ACPI_FAILURE(status)) {
416 tz->trips.hot.flags.valid = 0;
417 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
418 "No hot threshold\n"));
420 tz->trips.hot.temperature = tmp;
421 tz->trips.hot.flags.valid = 1;
422 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
423 "Found hot threshold [%lu]\n",
424 tz->trips.critical.temperature));
428 /* Passive (optional) */
429 if (((flag & ACPI_TRIPS_PASSIVE) && tz->trips.passive.flags.valid) ||
430 (flag == ACPI_TRIPS_INIT)) {
431 valid = tz->trips.passive.flags.valid;
434 } else if (psv > 0) {
435 tmp = CELSIUS_TO_KELVIN(psv);
438 status = acpi_evaluate_integer(tz->device->handle,
442 if (ACPI_FAILURE(status))
443 tz->trips.passive.flags.valid = 0;
445 tz->trips.passive.temperature = tmp;
446 tz->trips.passive.flags.valid = 1;
447 if (flag == ACPI_TRIPS_INIT) {
448 status = acpi_evaluate_integer(
449 tz->device->handle, "_TC1",
451 if (ACPI_FAILURE(status))
452 tz->trips.passive.flags.valid = 0;
454 tz->trips.passive.tc1 = tmp;
455 status = acpi_evaluate_integer(
456 tz->device->handle, "_TC2",
458 if (ACPI_FAILURE(status))
459 tz->trips.passive.flags.valid = 0;
461 tz->trips.passive.tc2 = tmp;
462 status = acpi_evaluate_integer(
463 tz->device->handle, "_TSP",
465 if (ACPI_FAILURE(status))
466 tz->trips.passive.flags.valid = 0;
468 tz->trips.passive.tsp = tmp;
472 if ((flag & ACPI_TRIPS_DEVICES) && tz->trips.passive.flags.valid) {
473 memset(&devices, 0, sizeof(struct acpi_handle_list));
474 status = acpi_evaluate_reference(tz->device->handle, "_PSL",
476 if (ACPI_FAILURE(status)) {
477 printk(KERN_WARNING PREFIX
478 "Invalid passive threshold\n");
479 tz->trips.passive.flags.valid = 0;
482 tz->trips.passive.flags.valid = 1;
484 if (memcmp(&tz->trips.passive.devices, &devices,
485 sizeof(struct acpi_handle_list))) {
486 memcpy(&tz->trips.passive.devices, &devices,
487 sizeof(struct acpi_handle_list));
488 ACPI_THERMAL_TRIPS_EXCEPTION(flag, "device");
491 if ((flag & ACPI_TRIPS_PASSIVE) || (flag & ACPI_TRIPS_DEVICES)) {
492 if (valid != tz->trips.passive.flags.valid)
493 ACPI_THERMAL_TRIPS_EXCEPTION(flag, "state");
496 /* Active (optional) */
497 for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
498 char name[5] = { '_', 'A', 'C', ('0' + i), '\0' };
499 valid = tz->trips.active[i].flags.valid;
502 break; /* disable all active trip points */
504 if ((flag == ACPI_TRIPS_INIT) || ((flag & ACPI_TRIPS_ACTIVE) &&
505 tz->trips.active[i].flags.valid)) {
506 status = acpi_evaluate_integer(tz->device->handle,
508 if (ACPI_FAILURE(status)) {
509 tz->trips.active[i].flags.valid = 0;
515 tz->trips.active[0].temperature =
516 CELSIUS_TO_KELVIN(act);
519 * Don't allow override higher than
520 * the next higher trip point
522 tz->trips.active[i - 1].temperature =
523 (tz->trips.active[i - 2].temperature <
524 CELSIUS_TO_KELVIN(act) ?
525 tz->trips.active[i - 2].temperature :
526 CELSIUS_TO_KELVIN(act));
529 tz->trips.active[i].temperature = tmp;
530 tz->trips.active[i].flags.valid = 1;
535 if ((flag & ACPI_TRIPS_DEVICES) && tz->trips.active[i].flags.valid ) {
536 memset(&devices, 0, sizeof(struct acpi_handle_list));
537 status = acpi_evaluate_reference(tz->device->handle,
538 name, NULL, &devices);
539 if (ACPI_FAILURE(status)) {
540 printk(KERN_WARNING PREFIX
541 "Invalid active%d threshold\n", i);
542 tz->trips.active[i].flags.valid = 0;
545 tz->trips.active[i].flags.valid = 1;
547 if (memcmp(&tz->trips.active[i].devices, &devices,
548 sizeof(struct acpi_handle_list))) {
549 memcpy(&tz->trips.active[i].devices, &devices,
550 sizeof(struct acpi_handle_list));
551 ACPI_THERMAL_TRIPS_EXCEPTION(flag, "device");
554 if ((flag & ACPI_TRIPS_ACTIVE) || (flag & ACPI_TRIPS_DEVICES))
555 if (valid != tz->trips.active[i].flags.valid)
556 ACPI_THERMAL_TRIPS_EXCEPTION(flag, "state");
558 if (!tz->trips.active[i].flags.valid)
562 if (flag & ACPI_TRIPS_DEVICES) {
563 memset(&devices, 0, sizeof(struct acpi_handle_list));
564 status = acpi_evaluate_reference(tz->device->handle, "_TZD",
566 if (memcmp(&tz->devices, &devices,
567 sizeof(struct acpi_handle_list))) {
568 memcpy(&tz->devices, &devices,
569 sizeof(struct acpi_handle_list));
570 ACPI_THERMAL_TRIPS_EXCEPTION(flag, "device");
577 static int acpi_thermal_get_trip_points(struct acpi_thermal *tz)
579 return acpi_thermal_trips_update(tz, ACPI_TRIPS_INIT);
582 static void acpi_thermal_check(void *data)
584 struct acpi_thermal *tz = data;
586 thermal_zone_device_update(tz->thermal_zone);
589 /* sys I/F for generic thermal sysfs support */
590 #define KELVIN_TO_MILLICELSIUS(t, off) (((t) - (off)) * 100)
592 static int thermal_get_temp(struct thermal_zone_device *thermal,
595 struct acpi_thermal *tz = thermal->devdata;
601 result = acpi_thermal_get_temperature(tz);
605 *temp = KELVIN_TO_MILLICELSIUS(tz->temperature, tz->kelvin_offset);
609 static const char enabled[] = "kernel";
610 static const char disabled[] = "user";
611 static int thermal_get_mode(struct thermal_zone_device *thermal,
612 enum thermal_device_mode *mode)
614 struct acpi_thermal *tz = thermal->devdata;
619 *mode = tz->tz_enabled ? THERMAL_DEVICE_ENABLED :
620 THERMAL_DEVICE_DISABLED;
625 static int thermal_set_mode(struct thermal_zone_device *thermal,
626 enum thermal_device_mode mode)
628 struct acpi_thermal *tz = thermal->devdata;
635 * enable/disable thermal management from ACPI thermal driver
637 if (mode == THERMAL_DEVICE_ENABLED)
639 else if (mode == THERMAL_DEVICE_DISABLED)
644 if (enable != tz->tz_enabled) {
645 tz->tz_enabled = enable;
646 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
647 "%s ACPI thermal control\n",
648 tz->tz_enabled ? enabled : disabled));
649 acpi_thermal_check(tz);
654 static int thermal_get_trip_type(struct thermal_zone_device *thermal,
655 int trip, enum thermal_trip_type *type)
657 struct acpi_thermal *tz = thermal->devdata;
663 if (tz->trips.critical.flags.valid) {
665 *type = THERMAL_TRIP_CRITICAL;
671 if (tz->trips.hot.flags.valid) {
673 *type = THERMAL_TRIP_HOT;
679 if (tz->trips.passive.flags.valid) {
681 *type = THERMAL_TRIP_PASSIVE;
687 for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE &&
688 tz->trips.active[i].flags.valid; i++) {
690 *type = THERMAL_TRIP_ACTIVE;
699 static int thermal_get_trip_temp(struct thermal_zone_device *thermal,
700 int trip, unsigned long *temp)
702 struct acpi_thermal *tz = thermal->devdata;
708 if (tz->trips.critical.flags.valid) {
710 *temp = KELVIN_TO_MILLICELSIUS(
711 tz->trips.critical.temperature,
718 if (tz->trips.hot.flags.valid) {
720 *temp = KELVIN_TO_MILLICELSIUS(
721 tz->trips.hot.temperature,
728 if (tz->trips.passive.flags.valid) {
730 *temp = KELVIN_TO_MILLICELSIUS(
731 tz->trips.passive.temperature,
738 for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE &&
739 tz->trips.active[i].flags.valid; i++) {
741 *temp = KELVIN_TO_MILLICELSIUS(
742 tz->trips.active[i].temperature,
752 static int thermal_get_crit_temp(struct thermal_zone_device *thermal,
753 unsigned long *temperature) {
754 struct acpi_thermal *tz = thermal->devdata;
756 if (tz->trips.critical.flags.valid) {
757 *temperature = KELVIN_TO_MILLICELSIUS(
758 tz->trips.critical.temperature,
765 static int thermal_notify(struct thermal_zone_device *thermal, int trip,
766 enum thermal_trip_type trip_type)
769 struct acpi_thermal *tz = thermal->devdata;
771 if (trip_type == THERMAL_TRIP_CRITICAL)
772 type = ACPI_THERMAL_NOTIFY_CRITICAL;
773 else if (trip_type == THERMAL_TRIP_HOT)
774 type = ACPI_THERMAL_NOTIFY_HOT;
778 acpi_bus_generate_proc_event(tz->device, type, 1);
779 acpi_bus_generate_netlink_event(tz->device->pnp.device_class,
780 dev_name(&tz->device->dev), type, 1);
782 if (trip_type == THERMAL_TRIP_CRITICAL && nocrt)
788 typedef int (*cb)(struct thermal_zone_device *, int,
789 struct thermal_cooling_device *);
790 static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal,
791 struct thermal_cooling_device *cdev,
794 struct acpi_device *device = cdev->devdata;
795 struct acpi_thermal *tz = thermal->devdata;
796 struct acpi_device *dev;
804 if (tz->trips.critical.flags.valid)
807 if (tz->trips.hot.flags.valid)
810 if (tz->trips.passive.flags.valid) {
812 for (i = 0; i < tz->trips.passive.devices.count;
814 handle = tz->trips.passive.devices.handles[i];
815 status = acpi_bus_get_device(handle, &dev);
816 if (ACPI_SUCCESS(status) && (dev == device)) {
817 result = action(thermal, trip, cdev);
824 for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
825 if (!tz->trips.active[i].flags.valid)
829 j < tz->trips.active[i].devices.count;
831 handle = tz->trips.active[i].devices.handles[j];
832 status = acpi_bus_get_device(handle, &dev);
833 if (ACPI_SUCCESS(status) && (dev == device)) {
834 result = action(thermal, trip, cdev);
841 for (i = 0; i < tz->devices.count; i++) {
842 handle = tz->devices.handles[i];
843 status = acpi_bus_get_device(handle, &dev);
844 if (ACPI_SUCCESS(status) && (dev == device)) {
845 result = action(thermal, -1, cdev);
856 acpi_thermal_bind_cooling_device(struct thermal_zone_device *thermal,
857 struct thermal_cooling_device *cdev)
859 return acpi_thermal_cooling_device_cb(thermal, cdev,
860 thermal_zone_bind_cooling_device);
864 acpi_thermal_unbind_cooling_device(struct thermal_zone_device *thermal,
865 struct thermal_cooling_device *cdev)
867 return acpi_thermal_cooling_device_cb(thermal, cdev,
868 thermal_zone_unbind_cooling_device);
871 static struct thermal_zone_device_ops acpi_thermal_zone_ops = {
872 .bind = acpi_thermal_bind_cooling_device,
873 .unbind = acpi_thermal_unbind_cooling_device,
874 .get_temp = thermal_get_temp,
875 .get_mode = thermal_get_mode,
876 .set_mode = thermal_set_mode,
877 .get_trip_type = thermal_get_trip_type,
878 .get_trip_temp = thermal_get_trip_temp,
879 .get_crit_temp = thermal_get_crit_temp,
880 .notify = thermal_notify,
883 static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz)
890 if (tz->trips.critical.flags.valid)
893 if (tz->trips.hot.flags.valid)
896 if (tz->trips.passive.flags.valid)
899 for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE &&
900 tz->trips.active[i].flags.valid; i++, trips++);
902 if (tz->trips.passive.flags.valid)
904 thermal_zone_device_register("acpitz", trips, tz,
905 &acpi_thermal_zone_ops,
906 tz->trips.passive.tc1,
907 tz->trips.passive.tc2,
908 tz->trips.passive.tsp*100,
909 tz->polling_frequency*100);
912 thermal_zone_device_register("acpitz", trips, tz,
913 &acpi_thermal_zone_ops,
915 tz->polling_frequency*100);
916 if (IS_ERR(tz->thermal_zone))
919 result = sysfs_create_link(&tz->device->dev.kobj,
920 &tz->thermal_zone->device.kobj, "thermal_zone");
924 result = sysfs_create_link(&tz->thermal_zone->device.kobj,
925 &tz->device->dev.kobj, "device");
929 status = acpi_attach_data(tz->device->handle,
930 acpi_bus_private_data_handler,
932 if (ACPI_FAILURE(status)) {
933 printk(KERN_ERR PREFIX
934 "Error attaching device data\n");
940 dev_info(&tz->device->dev, "registered as thermal_zone%d\n",
941 tz->thermal_zone->id);
945 static void acpi_thermal_unregister_thermal_zone(struct acpi_thermal *tz)
947 sysfs_remove_link(&tz->device->dev.kobj, "thermal_zone");
948 sysfs_remove_link(&tz->thermal_zone->device.kobj, "device");
949 thermal_zone_device_unregister(tz->thermal_zone);
950 tz->thermal_zone = NULL;
951 acpi_detach_data(tz->device->handle, acpi_bus_private_data_handler);
955 /* --------------------------------------------------------------------------
957 -------------------------------------------------------------------------- */
959 static struct proc_dir_entry *acpi_thermal_dir;
961 static int acpi_thermal_state_seq_show(struct seq_file *seq, void *offset)
963 struct acpi_thermal *tz = seq->private;
969 seq_puts(seq, "state: ");
971 if (!tz->state.critical && !tz->state.hot && !tz->state.passive
972 && !tz->state.active)
973 seq_puts(seq, "ok\n");
975 if (tz->state.critical)
976 seq_puts(seq, "critical ");
978 seq_puts(seq, "hot ");
979 if (tz->state.passive)
980 seq_puts(seq, "passive ");
981 if (tz->state.active)
982 seq_printf(seq, "active[%d]", tz->state.active_index);
990 static int acpi_thermal_state_open_fs(struct inode *inode, struct file *file)
992 return single_open(file, acpi_thermal_state_seq_show, PDE(inode)->data);
995 static int acpi_thermal_temp_seq_show(struct seq_file *seq, void *offset)
998 struct acpi_thermal *tz = seq->private;
1004 result = acpi_thermal_get_temperature(tz);
1008 seq_printf(seq, "temperature: %ld C\n",
1009 KELVIN_TO_CELSIUS(tz->temperature));
1015 static int acpi_thermal_temp_open_fs(struct inode *inode, struct file *file)
1017 return single_open(file, acpi_thermal_temp_seq_show, PDE(inode)->data);
1020 static int acpi_thermal_trip_seq_show(struct seq_file *seq, void *offset)
1022 struct acpi_thermal *tz = seq->private;
1023 struct acpi_device *device;
1033 if (tz->trips.critical.flags.valid)
1034 seq_printf(seq, "critical (S5): %ld C%s",
1035 KELVIN_TO_CELSIUS(tz->trips.critical.temperature),
1036 nocrt ? " <disabled>\n" : "\n");
1038 if (tz->trips.hot.flags.valid)
1039 seq_printf(seq, "hot (S4): %ld C%s",
1040 KELVIN_TO_CELSIUS(tz->trips.hot.temperature),
1041 nocrt ? " <disabled>\n" : "\n");
1043 if (tz->trips.passive.flags.valid) {
1045 "passive: %ld C: tc1=%lu tc2=%lu tsp=%lu devices=",
1046 KELVIN_TO_CELSIUS(tz->trips.passive.temperature),
1047 tz->trips.passive.tc1, tz->trips.passive.tc2,
1048 tz->trips.passive.tsp);
1049 for (j = 0; j < tz->trips.passive.devices.count; j++) {
1050 status = acpi_bus_get_device(tz->trips.passive.devices.
1051 handles[j], &device);
1052 seq_printf(seq, "%4.4s ", status ? "" :
1053 acpi_device_bid(device));
1055 seq_puts(seq, "\n");
1057 seq_printf(seq, "passive (forced):");
1058 if (tz->thermal_zone->forced_passive)
1059 seq_printf(seq, " %i C\n",
1060 tz->thermal_zone->forced_passive / 1000);
1062 seq_printf(seq, "<not set>\n");
1065 for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
1066 if (!(tz->trips.active[i].flags.valid))
1068 seq_printf(seq, "active[%d]: %ld C: devices=",
1070 KELVIN_TO_CELSIUS(tz->trips.active[i].temperature));
1071 for (j = 0; j < tz->trips.active[i].devices.count; j++){
1072 status = acpi_bus_get_device(tz->trips.active[i].
1075 seq_printf(seq, "%4.4s ", status ? "" :
1076 acpi_device_bid(device));
1078 seq_puts(seq, "\n");
1085 static int acpi_thermal_trip_open_fs(struct inode *inode, struct file *file)
1087 return single_open(file, acpi_thermal_trip_seq_show, PDE(inode)->data);
1090 static int acpi_thermal_cooling_seq_show(struct seq_file *seq, void *offset)
1092 struct acpi_thermal *tz = seq->private;
1098 if (!tz->flags.cooling_mode)
1099 seq_puts(seq, "<setting not supported>\n");
1101 seq_puts(seq, "0 - Active; 1 - Passive\n");
1107 static int acpi_thermal_cooling_open_fs(struct inode *inode, struct file *file)
1109 return single_open(file, acpi_thermal_cooling_seq_show,
1114 acpi_thermal_write_cooling_mode(struct file *file,
1115 const char __user * buffer,
1116 size_t count, loff_t * ppos)
1118 struct seq_file *m = file->private_data;
1119 struct acpi_thermal *tz = m->private;
1121 char mode_string[12] = { '\0' };
1124 if (!tz || (count > sizeof(mode_string) - 1))
1127 if (!tz->flags.cooling_mode)
1130 if (copy_from_user(mode_string, buffer, count))
1133 mode_string[count] = '\0';
1135 result = acpi_thermal_set_cooling_mode(tz,
1136 simple_strtoul(mode_string, NULL,
1141 acpi_thermal_check(tz);
1146 static int acpi_thermal_polling_seq_show(struct seq_file *seq, void *offset)
1148 struct acpi_thermal *tz = seq->private;
1154 if (!tz->thermal_zone->polling_delay) {
1155 seq_puts(seq, "<polling disabled>\n");
1159 seq_printf(seq, "polling frequency: %d seconds\n",
1160 (tz->thermal_zone->polling_delay / 1000));
1166 static int acpi_thermal_polling_open_fs(struct inode *inode, struct file *file)
1168 return single_open(file, acpi_thermal_polling_seq_show,
1173 acpi_thermal_write_polling(struct file *file,
1174 const char __user * buffer,
1175 size_t count, loff_t * ppos)
1177 struct seq_file *m = file->private_data;
1178 struct acpi_thermal *tz = m->private;
1180 char polling_string[12] = { '\0' };
1184 if (!tz || (count > sizeof(polling_string) - 1))
1187 if (copy_from_user(polling_string, buffer, count))
1190 polling_string[count] = '\0';
1192 seconds = simple_strtoul(polling_string, NULL, 0);
1194 result = acpi_thermal_set_polling(tz, seconds);
1198 acpi_thermal_check(tz);
1203 static int acpi_thermal_add_fs(struct acpi_device *device)
1205 struct proc_dir_entry *entry = NULL;
1208 if (!acpi_device_dir(device)) {
1209 acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
1211 if (!acpi_device_dir(device))
1216 entry = proc_create_data(ACPI_THERMAL_FILE_STATE,
1217 S_IRUGO, acpi_device_dir(device),
1218 &acpi_thermal_state_fops,
1219 acpi_driver_data(device));
1223 /* 'temperature' [R] */
1224 entry = proc_create_data(ACPI_THERMAL_FILE_TEMPERATURE,
1225 S_IRUGO, acpi_device_dir(device),
1226 &acpi_thermal_temp_fops,
1227 acpi_driver_data(device));
1231 /* 'trip_points' [R] */
1232 entry = proc_create_data(ACPI_THERMAL_FILE_TRIP_POINTS,
1234 acpi_device_dir(device),
1235 &acpi_thermal_trip_fops,
1236 acpi_driver_data(device));
1240 /* 'cooling_mode' [R/W] */
1241 entry = proc_create_data(ACPI_THERMAL_FILE_COOLING_MODE,
1242 S_IFREG | S_IRUGO | S_IWUSR,
1243 acpi_device_dir(device),
1244 &acpi_thermal_cooling_fops,
1245 acpi_driver_data(device));
1249 /* 'polling_frequency' [R/W] */
1250 entry = proc_create_data(ACPI_THERMAL_FILE_POLLING_FREQ,
1251 S_IFREG | S_IRUGO | S_IWUSR,
1252 acpi_device_dir(device),
1253 &acpi_thermal_polling_fops,
1254 acpi_driver_data(device));
1260 static int acpi_thermal_remove_fs(struct acpi_device *device)
1263 if (acpi_device_dir(device)) {
1264 remove_proc_entry(ACPI_THERMAL_FILE_POLLING_FREQ,
1265 acpi_device_dir(device));
1266 remove_proc_entry(ACPI_THERMAL_FILE_COOLING_MODE,
1267 acpi_device_dir(device));
1268 remove_proc_entry(ACPI_THERMAL_FILE_TRIP_POINTS,
1269 acpi_device_dir(device));
1270 remove_proc_entry(ACPI_THERMAL_FILE_TEMPERATURE,
1271 acpi_device_dir(device));
1272 remove_proc_entry(ACPI_THERMAL_FILE_STATE,
1273 acpi_device_dir(device));
1274 remove_proc_entry(acpi_device_bid(device), acpi_thermal_dir);
1275 acpi_device_dir(device) = NULL;
1281 /* --------------------------------------------------------------------------
1283 -------------------------------------------------------------------------- */
1285 static void acpi_thermal_notify(struct acpi_device *device, u32 event)
1287 struct acpi_thermal *tz = acpi_driver_data(device);
1294 case ACPI_THERMAL_NOTIFY_TEMPERATURE:
1295 acpi_thermal_check(tz);
1297 case ACPI_THERMAL_NOTIFY_THRESHOLDS:
1298 acpi_thermal_trips_update(tz, ACPI_TRIPS_REFRESH_THRESHOLDS);
1299 acpi_thermal_check(tz);
1300 acpi_bus_generate_proc_event(device, event, 0);
1301 acpi_bus_generate_netlink_event(device->pnp.device_class,
1302 dev_name(&device->dev), event, 0);
1304 case ACPI_THERMAL_NOTIFY_DEVICES:
1305 acpi_thermal_trips_update(tz, ACPI_TRIPS_REFRESH_DEVICES);
1306 acpi_thermal_check(tz);
1307 acpi_bus_generate_proc_event(device, event, 0);
1308 acpi_bus_generate_netlink_event(device->pnp.device_class,
1309 dev_name(&device->dev), event, 0);
1312 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
1313 "Unsupported event [0x%x]\n", event));
1318 static int acpi_thermal_get_info(struct acpi_thermal *tz)
1326 /* Get temperature [_TMP] (required) */
1327 result = acpi_thermal_get_temperature(tz);
1331 /* Get trip points [_CRT, _PSV, etc.] (required) */
1332 result = acpi_thermal_get_trip_points(tz);
1336 /* Set the cooling mode [_SCP] to active cooling (default) */
1337 result = acpi_thermal_set_cooling_mode(tz, ACPI_THERMAL_MODE_ACTIVE);
1339 tz->flags.cooling_mode = 1;
1341 /* Get default polling frequency [_TZP] (optional) */
1343 tz->polling_frequency = tzp;
1345 acpi_thermal_get_polling_frequency(tz);
1351 * The exact offset between Kelvin and degree Celsius is 273.15. However ACPI
1352 * handles temperature values with a single decimal place. As a consequence,
1353 * some implementations use an offset of 273.1 and others use an offset of
1354 * 273.2. Try to find out which one is being used, to present the most
1355 * accurate and visually appealing number.
1357 * The heuristic below should work for all ACPI thermal zones which have a
1358 * critical trip point with a value being a multiple of 0.5 degree Celsius.
1360 static void acpi_thermal_guess_offset(struct acpi_thermal *tz)
1362 if (tz->trips.critical.flags.valid &&
1363 (tz->trips.critical.temperature % 5) == 1)
1364 tz->kelvin_offset = 2731;
1366 tz->kelvin_offset = 2732;
1369 static struct dmi_system_id thermal_psv_dmi_table[] = {
1371 .ident = "IBM ThinkPad T41",
1373 DMI_MATCH(DMI_BIOS_VENDOR,"IBM"),
1374 DMI_MATCH(DMI_PRODUCT_VERSION,"ThinkPad T41"),
1378 .ident = "IBM ThinkPad T42",
1380 DMI_MATCH(DMI_BIOS_VENDOR,"IBM"),
1381 DMI_MATCH(DMI_PRODUCT_VERSION,"ThinkPad T42"),
1385 .ident = "IBM ThinkPad T43",
1387 DMI_MATCH(DMI_BIOS_VENDOR,"IBM"),
1388 DMI_MATCH(DMI_PRODUCT_VERSION,"ThinkPad T43"),
1392 .ident = "IBM ThinkPad T41p",
1394 DMI_MATCH(DMI_BIOS_VENDOR,"IBM"),
1395 DMI_MATCH(DMI_PRODUCT_VERSION,"ThinkPad T41p"),
1399 .ident = "IBM ThinkPad T42p",
1401 DMI_MATCH(DMI_BIOS_VENDOR,"IBM"),
1402 DMI_MATCH(DMI_PRODUCT_VERSION,"ThinkPad T42p"),
1406 .ident = "IBM ThinkPad T43p",
1408 DMI_MATCH(DMI_BIOS_VENDOR,"IBM"),
1409 DMI_MATCH(DMI_PRODUCT_VERSION,"ThinkPad T43p"),
1413 .ident = "IBM ThinkPad R40",
1415 DMI_MATCH(DMI_BIOS_VENDOR,"IBM"),
1416 DMI_MATCH(DMI_PRODUCT_VERSION,"ThinkPad R40"),
1420 .ident = "IBM ThinkPad R50p",
1422 DMI_MATCH(DMI_BIOS_VENDOR,"IBM"),
1423 DMI_MATCH(DMI_PRODUCT_VERSION,"ThinkPad R50p"),
1429 static int acpi_thermal_add(struct acpi_device *device)
1432 struct acpi_thermal *tz = NULL;
1438 tz = kzalloc(sizeof(struct acpi_thermal), GFP_KERNEL);
1442 tz->device = device;
1443 strcpy(tz->name, device->pnp.bus_id);
1444 strcpy(acpi_device_name(device), ACPI_THERMAL_DEVICE_NAME);
1445 strcpy(acpi_device_class(device), ACPI_THERMAL_CLASS);
1446 device->driver_data = tz;
1447 mutex_init(&tz->lock);
1450 result = acpi_thermal_get_info(tz);
1454 acpi_thermal_guess_offset(tz);
1456 result = acpi_thermal_register_thermal_zone(tz);
1460 if (dmi_check_system(thermal_psv_dmi_table)) {
1461 if (tz->trips.passive.flags.valid &&
1462 tz->trips.passive.temperature > CELSIUS_TO_KELVIN(85)) {
1463 printk (KERN_INFO "Adjust passive trip point from %lu"
1465 KELVIN_TO_CELSIUS(tz->trips.passive.temperature),
1466 KELVIN_TO_CELSIUS(tz->trips.passive.temperature - 150));
1467 tz->trips.passive.temperature -= 150;
1468 acpi_thermal_set_polling(tz, 5);
1472 result = acpi_thermal_add_fs(device);
1474 goto unregister_thermal_zone;
1476 printk(KERN_INFO PREFIX "%s [%s] (%ld C)\n",
1477 acpi_device_name(device), acpi_device_bid(device),
1478 KELVIN_TO_CELSIUS(tz->temperature));
1481 unregister_thermal_zone:
1482 thermal_zone_device_unregister(tz->thermal_zone);
1489 static int acpi_thermal_remove(struct acpi_device *device, int type)
1491 struct acpi_thermal *tz = NULL;
1493 if (!device || !acpi_driver_data(device))
1496 tz = acpi_driver_data(device);
1498 acpi_thermal_remove_fs(device);
1499 acpi_thermal_unregister_thermal_zone(tz);
1500 mutex_destroy(&tz->lock);
1505 static int acpi_thermal_resume(struct acpi_device *device)
1507 struct acpi_thermal *tz = NULL;
1508 int i, j, power_state, result;
1511 if (!device || !acpi_driver_data(device))
1514 tz = acpi_driver_data(device);
1516 for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
1517 if (!(&tz->trips.active[i]))
1519 if (!tz->trips.active[i].flags.valid)
1521 tz->trips.active[i].flags.enabled = 1;
1522 for (j = 0; j < tz->trips.active[i].devices.count; j++) {
1523 result = acpi_bus_get_power(tz->trips.active[i].devices.
1524 handles[j], &power_state);
1525 if (result || (power_state != ACPI_STATE_D0)) {
1526 tz->trips.active[i].flags.enabled = 0;
1530 tz->state.active |= tz->trips.active[i].flags.enabled;
1533 acpi_thermal_check(tz);
1538 static int thermal_act(const struct dmi_system_id *d) {
1541 printk(KERN_NOTICE "ACPI: %s detected: "
1542 "disabling all active thermal trip points\n", d->ident);
1547 static int thermal_nocrt(const struct dmi_system_id *d) {
1549 printk(KERN_NOTICE "ACPI: %s detected: "
1550 "disabling all critical thermal trip point actions.\n", d->ident);
1554 static int thermal_tzp(const struct dmi_system_id *d) {
1557 printk(KERN_NOTICE "ACPI: %s detected: "
1558 "enabling thermal zone polling\n", d->ident);
1559 tzp = 300; /* 300 dS = 30 Seconds */
1563 static int thermal_psv(const struct dmi_system_id *d) {
1566 printk(KERN_NOTICE "ACPI: %s detected: "
1567 "disabling all passive thermal trip points\n", d->ident);
1573 static struct dmi_system_id thermal_dmi_table[] __initdata = {
1575 * Award BIOS on this AOpen makes thermal control almost worthless.
1576 * http://bugzilla.kernel.org/show_bug.cgi?id=8842
1579 .callback = thermal_act,
1580 .ident = "AOpen i915GMm-HFS",
1582 DMI_MATCH(DMI_BOARD_VENDOR, "AOpen"),
1583 DMI_MATCH(DMI_BOARD_NAME, "i915GMm-HFS"),
1587 .callback = thermal_psv,
1588 .ident = "AOpen i915GMm-HFS",
1590 DMI_MATCH(DMI_BOARD_VENDOR, "AOpen"),
1591 DMI_MATCH(DMI_BOARD_NAME, "i915GMm-HFS"),
1595 .callback = thermal_tzp,
1596 .ident = "AOpen i915GMm-HFS",
1598 DMI_MATCH(DMI_BOARD_VENDOR, "AOpen"),
1599 DMI_MATCH(DMI_BOARD_NAME, "i915GMm-HFS"),
1603 .callback = thermal_nocrt,
1604 .ident = "Gigabyte GA-7ZX",
1606 DMI_MATCH(DMI_BOARD_VENDOR, "Gigabyte Technology Co., Ltd."),
1607 DMI_MATCH(DMI_BOARD_NAME, "7ZX"),
1613 static int __init acpi_thermal_init(void)
1617 dmi_check_system(thermal_dmi_table);
1620 printk(KERN_NOTICE "ACPI: thermal control disabled\n");
1623 acpi_thermal_dir = proc_mkdir(ACPI_THERMAL_CLASS, acpi_root_dir);
1624 if (!acpi_thermal_dir)
1627 result = acpi_bus_register_driver(&acpi_thermal_driver);
1629 remove_proc_entry(ACPI_THERMAL_CLASS, acpi_root_dir);
1636 static void __exit acpi_thermal_exit(void)
1639 acpi_bus_unregister_driver(&acpi_thermal_driver);
1641 remove_proc_entry(ACPI_THERMAL_CLASS, acpi_root_dir);
1646 module_init(acpi_thermal_init);
1647 module_exit(acpi_thermal_exit);