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 <asm/uaccess.h>
46 #include <linux/thermal.h>
47 #include <acpi/acpi_bus.h>
48 #include <acpi/acpi_drivers.h>
50 #define PREFIX "ACPI: "
52 #define ACPI_THERMAL_CLASS "thermal_zone"
53 #define ACPI_THERMAL_DEVICE_NAME "Thermal Zone"
54 #define ACPI_THERMAL_FILE_STATE "state"
55 #define ACPI_THERMAL_FILE_TEMPERATURE "temperature"
56 #define ACPI_THERMAL_FILE_TRIP_POINTS "trip_points"
57 #define ACPI_THERMAL_FILE_COOLING_MODE "cooling_mode"
58 #define ACPI_THERMAL_FILE_POLLING_FREQ "polling_frequency"
59 #define ACPI_THERMAL_NOTIFY_TEMPERATURE 0x80
60 #define ACPI_THERMAL_NOTIFY_THRESHOLDS 0x81
61 #define ACPI_THERMAL_NOTIFY_DEVICES 0x82
62 #define ACPI_THERMAL_NOTIFY_CRITICAL 0xF0
63 #define ACPI_THERMAL_NOTIFY_HOT 0xF1
64 #define ACPI_THERMAL_MODE_ACTIVE 0x00
66 #define ACPI_THERMAL_MAX_ACTIVE 10
67 #define ACPI_THERMAL_MAX_LIMIT_STR_LEN 65
69 #define _COMPONENT ACPI_THERMAL_COMPONENT
70 ACPI_MODULE_NAME("thermal");
72 MODULE_AUTHOR("Paul Diefenbaugh");
73 MODULE_DESCRIPTION("ACPI Thermal Zone Driver");
74 MODULE_LICENSE("GPL");
77 module_param(act
, int, 0644);
78 MODULE_PARM_DESC(act
, "Disable or override all lowest active trip points.");
81 module_param(crt
, int, 0644);
82 MODULE_PARM_DESC(crt
, "Disable or lower all critical trip points.");
85 module_param(tzp
, int, 0444);
86 MODULE_PARM_DESC(tzp
, "Thermal zone polling frequency, in 1/10 seconds.");
89 module_param(nocrt
, int, 0);
90 MODULE_PARM_DESC(nocrt
, "Set to take no action upon ACPI thermal zone critical trips points.");
93 module_param(off
, int, 0);
94 MODULE_PARM_DESC(off
, "Set to disable ACPI thermal support.");
97 module_param(psv
, int, 0644);
98 MODULE_PARM_DESC(psv
, "Disable or override all passive trip points.");
100 static int acpi_thermal_add(struct acpi_device
*device
);
101 static int acpi_thermal_remove(struct acpi_device
*device
, int type
);
102 static int acpi_thermal_resume(struct acpi_device
*device
);
103 static void acpi_thermal_notify(struct acpi_device
*device
, u32 event
);
104 static int acpi_thermal_state_open_fs(struct inode
*inode
, struct file
*file
);
105 static int acpi_thermal_temp_open_fs(struct inode
*inode
, struct file
*file
);
106 static int acpi_thermal_trip_open_fs(struct inode
*inode
, struct file
*file
);
107 static int acpi_thermal_cooling_open_fs(struct inode
*inode
, struct file
*file
);
108 static ssize_t
acpi_thermal_write_cooling_mode(struct file
*,
109 const char __user
*, size_t,
111 static int acpi_thermal_polling_open_fs(struct inode
*inode
, struct file
*file
);
112 static ssize_t
acpi_thermal_write_polling(struct file
*, const char __user
*,
115 static const struct acpi_device_id thermal_device_ids
[] = {
116 {ACPI_THERMAL_HID
, 0},
119 MODULE_DEVICE_TABLE(acpi
, thermal_device_ids
);
121 static struct acpi_driver acpi_thermal_driver
= {
123 .class = ACPI_THERMAL_CLASS
,
124 .ids
= thermal_device_ids
,
126 .add
= acpi_thermal_add
,
127 .remove
= acpi_thermal_remove
,
128 .resume
= acpi_thermal_resume
,
129 .notify
= acpi_thermal_notify
,
133 struct acpi_thermal_state
{
142 struct acpi_thermal_state_flags
{
148 struct acpi_thermal_critical
{
149 struct acpi_thermal_state_flags flags
;
150 unsigned long temperature
;
153 struct acpi_thermal_hot
{
154 struct acpi_thermal_state_flags flags
;
155 unsigned long temperature
;
158 struct acpi_thermal_passive
{
159 struct acpi_thermal_state_flags flags
;
160 unsigned long temperature
;
164 struct acpi_handle_list devices
;
167 struct acpi_thermal_active
{
168 struct acpi_thermal_state_flags flags
;
169 unsigned long temperature
;
170 struct acpi_handle_list devices
;
173 struct acpi_thermal_trips
{
174 struct acpi_thermal_critical critical
;
175 struct acpi_thermal_hot hot
;
176 struct acpi_thermal_passive passive
;
177 struct acpi_thermal_active active
[ACPI_THERMAL_MAX_ACTIVE
];
180 struct acpi_thermal_flags
{
181 u8 cooling_mode
:1; /* _SCP */
182 u8 devices
:1; /* _TZD */
186 struct acpi_thermal
{
187 struct acpi_device
* device
;
189 unsigned long temperature
;
190 unsigned long last_temperature
;
191 unsigned long polling_frequency
;
193 struct acpi_thermal_flags flags
;
194 struct acpi_thermal_state state
;
195 struct acpi_thermal_trips trips
;
196 struct acpi_handle_list devices
;
197 struct thermal_zone_device
*thermal_zone
;
203 static const struct file_operations acpi_thermal_state_fops
= {
204 .owner
= THIS_MODULE
,
205 .open
= acpi_thermal_state_open_fs
,
208 .release
= single_release
,
211 static const struct file_operations acpi_thermal_temp_fops
= {
212 .owner
= THIS_MODULE
,
213 .open
= acpi_thermal_temp_open_fs
,
216 .release
= single_release
,
219 static const struct file_operations acpi_thermal_trip_fops
= {
220 .owner
= THIS_MODULE
,
221 .open
= acpi_thermal_trip_open_fs
,
224 .release
= single_release
,
227 static const struct file_operations acpi_thermal_cooling_fops
= {
228 .owner
= THIS_MODULE
,
229 .open
= acpi_thermal_cooling_open_fs
,
231 .write
= acpi_thermal_write_cooling_mode
,
233 .release
= single_release
,
236 static const struct file_operations acpi_thermal_polling_fops
= {
237 .owner
= THIS_MODULE
,
238 .open
= acpi_thermal_polling_open_fs
,
240 .write
= acpi_thermal_write_polling
,
242 .release
= single_release
,
245 /* --------------------------------------------------------------------------
246 Thermal Zone Management
247 -------------------------------------------------------------------------- */
249 static int acpi_thermal_get_temperature(struct acpi_thermal
*tz
)
251 acpi_status status
= AE_OK
;
252 unsigned long long tmp
;
257 tz
->last_temperature
= tz
->temperature
;
259 status
= acpi_evaluate_integer(tz
->device
->handle
, "_TMP", NULL
, &tmp
);
260 if (ACPI_FAILURE(status
))
263 tz
->temperature
= tmp
;
264 ACPI_DEBUG_PRINT((ACPI_DB_INFO
, "Temperature is %lu dK\n",
270 static int acpi_thermal_get_polling_frequency(struct acpi_thermal
*tz
)
272 acpi_status status
= AE_OK
;
273 unsigned long long tmp
;
278 status
= acpi_evaluate_integer(tz
->device
->handle
, "_TZP", NULL
, &tmp
);
279 if (ACPI_FAILURE(status
))
282 tz
->polling_frequency
= tmp
;
283 ACPI_DEBUG_PRINT((ACPI_DB_INFO
, "Polling frequency is %lu dS\n",
284 tz
->polling_frequency
));
289 static int acpi_thermal_set_polling(struct acpi_thermal
*tz
, int seconds
)
295 tz
->polling_frequency
= seconds
* 10; /* Convert value to deci-seconds */
297 tz
->thermal_zone
->polling_delay
= seconds
* 1000;
300 thermal_zone_device_update(tz
->thermal_zone
);
302 ACPI_DEBUG_PRINT((ACPI_DB_INFO
,
303 "Polling frequency set to %lu seconds\n",
304 tz
->polling_frequency
/10));
309 static int acpi_thermal_set_cooling_mode(struct acpi_thermal
*tz
, int mode
)
311 acpi_status status
= AE_OK
;
312 union acpi_object arg0
= { ACPI_TYPE_INTEGER
};
313 struct acpi_object_list arg_list
= { 1, &arg0
};
314 acpi_handle handle
= NULL
;
320 status
= acpi_get_handle(tz
->device
->handle
, "_SCP", &handle
);
321 if (ACPI_FAILURE(status
)) {
322 ACPI_DEBUG_PRINT((ACPI_DB_INFO
, "_SCP not present\n"));
326 arg0
.integer
.value
= mode
;
328 status
= acpi_evaluate_object(handle
, NULL
, &arg_list
, NULL
);
329 if (ACPI_FAILURE(status
))
335 #define ACPI_TRIPS_CRITICAL 0x01
336 #define ACPI_TRIPS_HOT 0x02
337 #define ACPI_TRIPS_PASSIVE 0x04
338 #define ACPI_TRIPS_ACTIVE 0x08
339 #define ACPI_TRIPS_DEVICES 0x10
341 #define ACPI_TRIPS_REFRESH_THRESHOLDS (ACPI_TRIPS_PASSIVE | ACPI_TRIPS_ACTIVE)
342 #define ACPI_TRIPS_REFRESH_DEVICES ACPI_TRIPS_DEVICES
344 #define ACPI_TRIPS_INIT (ACPI_TRIPS_CRITICAL | ACPI_TRIPS_HOT | \
345 ACPI_TRIPS_PASSIVE | ACPI_TRIPS_ACTIVE | \
349 * This exception is thrown out in two cases:
350 * 1.An invalid trip point becomes invalid or a valid trip point becomes invalid
351 * when re-evaluating the AML code.
352 * 2.TODO: Devices listed in _PSL, _ALx, _TZD may change.
353 * We need to re-bind the cooling devices of a thermal zone when this occurs.
355 #define ACPI_THERMAL_TRIPS_EXCEPTION(flags, str) \
357 if (flags != ACPI_TRIPS_INIT) \
358 ACPI_EXCEPTION((AE_INFO, AE_ERROR, \
359 "ACPI thermal trip point %s changed\n" \
360 "Please send acpidump to linux-acpi@vger.kernel.org\n", str)); \
363 static int acpi_thermal_trips_update(struct acpi_thermal
*tz
, int flag
)
365 acpi_status status
= AE_OK
;
366 unsigned long long tmp
;
367 struct acpi_handle_list devices
;
371 /* Critical Shutdown */
372 if (flag
& ACPI_TRIPS_CRITICAL
) {
373 status
= acpi_evaluate_integer(tz
->device
->handle
,
375 tz
->trips
.critical
.temperature
= tmp
;
377 * Treat freezing temperatures as invalid as well; some
378 * BIOSes return really low values and cause reboots at startup.
379 * Below zero (Celsius) values clearly aren't right for sure..
380 * ... so lets discard those as invalid.
382 if (ACPI_FAILURE(status
)) {
383 tz
->trips
.critical
.flags
.valid
= 0;
384 ACPI_DEBUG_PRINT((ACPI_DB_INFO
,
385 "No critical threshold\n"));
386 } else if (tmp
<= 2732) {
387 printk(KERN_WARNING FW_BUG
"Invalid critical threshold "
389 tz
->trips
.critical
.flags
.valid
= 0;
391 tz
->trips
.critical
.flags
.valid
= 1;
392 ACPI_DEBUG_PRINT((ACPI_DB_INFO
,
393 "Found critical threshold [%lu]\n",
394 tz
->trips
.critical
.temperature
));
396 if (tz
->trips
.critical
.flags
.valid
== 1) {
398 tz
->trips
.critical
.flags
.valid
= 0;
399 } else if (crt
> 0) {
400 unsigned long crt_k
= CELSIUS_TO_KELVIN(crt
);
402 * Allow override critical threshold
404 if (crt_k
> tz
->trips
.critical
.temperature
)
405 printk(KERN_WARNING PREFIX
406 "Critical threshold %d C\n", crt
);
407 tz
->trips
.critical
.temperature
= crt_k
;
412 /* Critical Sleep (optional) */
413 if (flag
& ACPI_TRIPS_HOT
) {
414 status
= acpi_evaluate_integer(tz
->device
->handle
,
416 if (ACPI_FAILURE(status
)) {
417 tz
->trips
.hot
.flags
.valid
= 0;
418 ACPI_DEBUG_PRINT((ACPI_DB_INFO
,
419 "No hot threshold\n"));
421 tz
->trips
.hot
.temperature
= tmp
;
422 tz
->trips
.hot
.flags
.valid
= 1;
423 ACPI_DEBUG_PRINT((ACPI_DB_INFO
,
424 "Found hot threshold [%lu]\n",
425 tz
->trips
.critical
.temperature
));
429 /* Passive (optional) */
430 if (((flag
& ACPI_TRIPS_PASSIVE
) && tz
->trips
.passive
.flags
.valid
) ||
431 (flag
== ACPI_TRIPS_INIT
)) {
432 valid
= tz
->trips
.passive
.flags
.valid
;
435 } else if (psv
> 0) {
436 tmp
= CELSIUS_TO_KELVIN(psv
);
439 status
= acpi_evaluate_integer(tz
->device
->handle
,
443 if (ACPI_FAILURE(status
))
444 tz
->trips
.passive
.flags
.valid
= 0;
446 tz
->trips
.passive
.temperature
= tmp
;
447 tz
->trips
.passive
.flags
.valid
= 1;
448 if (flag
== ACPI_TRIPS_INIT
) {
449 status
= acpi_evaluate_integer(
450 tz
->device
->handle
, "_TC1",
452 if (ACPI_FAILURE(status
))
453 tz
->trips
.passive
.flags
.valid
= 0;
455 tz
->trips
.passive
.tc1
= tmp
;
456 status
= acpi_evaluate_integer(
457 tz
->device
->handle
, "_TC2",
459 if (ACPI_FAILURE(status
))
460 tz
->trips
.passive
.flags
.valid
= 0;
462 tz
->trips
.passive
.tc2
= tmp
;
463 status
= acpi_evaluate_integer(
464 tz
->device
->handle
, "_TSP",
466 if (ACPI_FAILURE(status
))
467 tz
->trips
.passive
.flags
.valid
= 0;
469 tz
->trips
.passive
.tsp
= tmp
;
473 if ((flag
& ACPI_TRIPS_DEVICES
) && tz
->trips
.passive
.flags
.valid
) {
474 memset(&devices
, 0, sizeof(struct acpi_handle_list
));
475 status
= acpi_evaluate_reference(tz
->device
->handle
, "_PSL",
477 if (ACPI_FAILURE(status
)) {
478 printk(KERN_WARNING PREFIX
479 "Invalid passive threshold\n");
480 tz
->trips
.passive
.flags
.valid
= 0;
483 tz
->trips
.passive
.flags
.valid
= 1;
485 if (memcmp(&tz
->trips
.passive
.devices
, &devices
,
486 sizeof(struct acpi_handle_list
))) {
487 memcpy(&tz
->trips
.passive
.devices
, &devices
,
488 sizeof(struct acpi_handle_list
));
489 ACPI_THERMAL_TRIPS_EXCEPTION(flag
, "device");
492 if ((flag
& ACPI_TRIPS_PASSIVE
) || (flag
& ACPI_TRIPS_DEVICES
)) {
493 if (valid
!= tz
->trips
.passive
.flags
.valid
)
494 ACPI_THERMAL_TRIPS_EXCEPTION(flag
, "state");
497 /* Active (optional) */
498 for (i
= 0; i
< ACPI_THERMAL_MAX_ACTIVE
; i
++) {
499 char name
[5] = { '_', 'A', 'C', ('0' + i
), '\0' };
500 valid
= tz
->trips
.active
[i
].flags
.valid
;
503 break; /* disable all active trip points */
505 if ((flag
== ACPI_TRIPS_INIT
) || ((flag
& ACPI_TRIPS_ACTIVE
) &&
506 tz
->trips
.active
[i
].flags
.valid
)) {
507 status
= acpi_evaluate_integer(tz
->device
->handle
,
509 if (ACPI_FAILURE(status
)) {
510 tz
->trips
.active
[i
].flags
.valid
= 0;
516 tz
->trips
.active
[0].temperature
=
517 CELSIUS_TO_KELVIN(act
);
520 * Don't allow override higher than
521 * the next higher trip point
523 tz
->trips
.active
[i
- 1].temperature
=
524 (tz
->trips
.active
[i
- 2].temperature
<
525 CELSIUS_TO_KELVIN(act
) ?
526 tz
->trips
.active
[i
- 2].temperature
:
527 CELSIUS_TO_KELVIN(act
));
530 tz
->trips
.active
[i
].temperature
= tmp
;
531 tz
->trips
.active
[i
].flags
.valid
= 1;
536 if ((flag
& ACPI_TRIPS_DEVICES
) && tz
->trips
.active
[i
].flags
.valid
) {
537 memset(&devices
, 0, sizeof(struct acpi_handle_list
));
538 status
= acpi_evaluate_reference(tz
->device
->handle
,
539 name
, NULL
, &devices
);
540 if (ACPI_FAILURE(status
)) {
541 printk(KERN_WARNING PREFIX
542 "Invalid active%d threshold\n", i
);
543 tz
->trips
.active
[i
].flags
.valid
= 0;
546 tz
->trips
.active
[i
].flags
.valid
= 1;
548 if (memcmp(&tz
->trips
.active
[i
].devices
, &devices
,
549 sizeof(struct acpi_handle_list
))) {
550 memcpy(&tz
->trips
.active
[i
].devices
, &devices
,
551 sizeof(struct acpi_handle_list
));
552 ACPI_THERMAL_TRIPS_EXCEPTION(flag
, "device");
555 if ((flag
& ACPI_TRIPS_ACTIVE
) || (flag
& ACPI_TRIPS_DEVICES
))
556 if (valid
!= tz
->trips
.active
[i
].flags
.valid
)
557 ACPI_THERMAL_TRIPS_EXCEPTION(flag
, "state");
559 if (!tz
->trips
.active
[i
].flags
.valid
)
563 if (flag
& ACPI_TRIPS_DEVICES
) {
564 memset(&devices
, 0, sizeof(struct acpi_handle_list
));
565 status
= acpi_evaluate_reference(tz
->device
->handle
, "_TZD",
567 if (memcmp(&tz
->devices
, &devices
,
568 sizeof(struct acpi_handle_list
))) {
569 memcpy(&tz
->devices
, &devices
,
570 sizeof(struct acpi_handle_list
));
571 ACPI_THERMAL_TRIPS_EXCEPTION(flag
, "device");
578 static int acpi_thermal_get_trip_points(struct acpi_thermal
*tz
)
580 int i
, valid
, ret
= acpi_thermal_trips_update(tz
, ACPI_TRIPS_INIT
);
585 valid
= tz
->trips
.critical
.flags
.valid
|
586 tz
->trips
.hot
.flags
.valid
|
587 tz
->trips
.passive
.flags
.valid
;
589 for (i
= 0; i
< ACPI_THERMAL_MAX_ACTIVE
; i
++)
590 valid
|= tz
->trips
.active
[i
].flags
.valid
;
593 printk(KERN_WARNING FW_BUG
"No valid trip found\n");
599 static void acpi_thermal_check(void *data
)
601 struct acpi_thermal
*tz
= data
;
603 thermal_zone_device_update(tz
->thermal_zone
);
606 /* sys I/F for generic thermal sysfs support */
607 #define KELVIN_TO_MILLICELSIUS(t, off) (((t) - (off)) * 100)
609 static int thermal_get_temp(struct thermal_zone_device
*thermal
,
612 struct acpi_thermal
*tz
= thermal
->devdata
;
618 result
= acpi_thermal_get_temperature(tz
);
622 *temp
= KELVIN_TO_MILLICELSIUS(tz
->temperature
, tz
->kelvin_offset
);
626 static const char enabled
[] = "kernel";
627 static const char disabled
[] = "user";
628 static int thermal_get_mode(struct thermal_zone_device
*thermal
,
629 enum thermal_device_mode
*mode
)
631 struct acpi_thermal
*tz
= thermal
->devdata
;
636 *mode
= tz
->tz_enabled
? THERMAL_DEVICE_ENABLED
:
637 THERMAL_DEVICE_DISABLED
;
642 static int thermal_set_mode(struct thermal_zone_device
*thermal
,
643 enum thermal_device_mode mode
)
645 struct acpi_thermal
*tz
= thermal
->devdata
;
652 * enable/disable thermal management from ACPI thermal driver
654 if (mode
== THERMAL_DEVICE_ENABLED
)
656 else if (mode
== THERMAL_DEVICE_DISABLED
)
661 if (enable
!= tz
->tz_enabled
) {
662 tz
->tz_enabled
= enable
;
663 ACPI_DEBUG_PRINT((ACPI_DB_INFO
,
664 "%s ACPI thermal control\n",
665 tz
->tz_enabled
? enabled
: disabled
));
666 acpi_thermal_check(tz
);
671 static int thermal_get_trip_type(struct thermal_zone_device
*thermal
,
672 int trip
, enum thermal_trip_type
*type
)
674 struct acpi_thermal
*tz
= thermal
->devdata
;
680 if (tz
->trips
.critical
.flags
.valid
) {
682 *type
= THERMAL_TRIP_CRITICAL
;
688 if (tz
->trips
.hot
.flags
.valid
) {
690 *type
= THERMAL_TRIP_HOT
;
696 if (tz
->trips
.passive
.flags
.valid
) {
698 *type
= THERMAL_TRIP_PASSIVE
;
704 for (i
= 0; i
< ACPI_THERMAL_MAX_ACTIVE
&&
705 tz
->trips
.active
[i
].flags
.valid
; i
++) {
707 *type
= THERMAL_TRIP_ACTIVE
;
716 static int thermal_get_trip_temp(struct thermal_zone_device
*thermal
,
717 int trip
, unsigned long *temp
)
719 struct acpi_thermal
*tz
= thermal
->devdata
;
725 if (tz
->trips
.critical
.flags
.valid
) {
727 *temp
= KELVIN_TO_MILLICELSIUS(
728 tz
->trips
.critical
.temperature
,
735 if (tz
->trips
.hot
.flags
.valid
) {
737 *temp
= KELVIN_TO_MILLICELSIUS(
738 tz
->trips
.hot
.temperature
,
745 if (tz
->trips
.passive
.flags
.valid
) {
747 *temp
= KELVIN_TO_MILLICELSIUS(
748 tz
->trips
.passive
.temperature
,
755 for (i
= 0; i
< ACPI_THERMAL_MAX_ACTIVE
&&
756 tz
->trips
.active
[i
].flags
.valid
; i
++) {
758 *temp
= KELVIN_TO_MILLICELSIUS(
759 tz
->trips
.active
[i
].temperature
,
769 static int thermal_get_crit_temp(struct thermal_zone_device
*thermal
,
770 unsigned long *temperature
) {
771 struct acpi_thermal
*tz
= thermal
->devdata
;
773 if (tz
->trips
.critical
.flags
.valid
) {
774 *temperature
= KELVIN_TO_MILLICELSIUS(
775 tz
->trips
.critical
.temperature
,
782 static int thermal_notify(struct thermal_zone_device
*thermal
, int trip
,
783 enum thermal_trip_type trip_type
)
786 struct acpi_thermal
*tz
= thermal
->devdata
;
788 if (trip_type
== THERMAL_TRIP_CRITICAL
)
789 type
= ACPI_THERMAL_NOTIFY_CRITICAL
;
790 else if (trip_type
== THERMAL_TRIP_HOT
)
791 type
= ACPI_THERMAL_NOTIFY_HOT
;
795 acpi_bus_generate_proc_event(tz
->device
, type
, 1);
796 acpi_bus_generate_netlink_event(tz
->device
->pnp
.device_class
,
797 dev_name(&tz
->device
->dev
), type
, 1);
799 if (trip_type
== THERMAL_TRIP_CRITICAL
&& nocrt
)
805 typedef int (*cb
)(struct thermal_zone_device
*, int,
806 struct thermal_cooling_device
*);
807 static int acpi_thermal_cooling_device_cb(struct thermal_zone_device
*thermal
,
808 struct thermal_cooling_device
*cdev
,
811 struct acpi_device
*device
= cdev
->devdata
;
812 struct acpi_thermal
*tz
= thermal
->devdata
;
813 struct acpi_device
*dev
;
821 if (tz
->trips
.critical
.flags
.valid
)
824 if (tz
->trips
.hot
.flags
.valid
)
827 if (tz
->trips
.passive
.flags
.valid
) {
829 for (i
= 0; i
< tz
->trips
.passive
.devices
.count
;
831 handle
= tz
->trips
.passive
.devices
.handles
[i
];
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
< ACPI_THERMAL_MAX_ACTIVE
; i
++) {
842 if (!tz
->trips
.active
[i
].flags
.valid
)
846 j
< tz
->trips
.active
[i
].devices
.count
;
848 handle
= tz
->trips
.active
[i
].devices
.handles
[j
];
849 status
= acpi_bus_get_device(handle
, &dev
);
850 if (ACPI_SUCCESS(status
) && (dev
== device
)) {
851 result
= action(thermal
, trip
, cdev
);
858 for (i
= 0; i
< tz
->devices
.count
; i
++) {
859 handle
= tz
->devices
.handles
[i
];
860 status
= acpi_bus_get_device(handle
, &dev
);
861 if (ACPI_SUCCESS(status
) && (dev
== device
)) {
862 result
= action(thermal
, -1, cdev
);
873 acpi_thermal_bind_cooling_device(struct thermal_zone_device
*thermal
,
874 struct thermal_cooling_device
*cdev
)
876 return acpi_thermal_cooling_device_cb(thermal
, cdev
,
877 thermal_zone_bind_cooling_device
);
881 acpi_thermal_unbind_cooling_device(struct thermal_zone_device
*thermal
,
882 struct thermal_cooling_device
*cdev
)
884 return acpi_thermal_cooling_device_cb(thermal
, cdev
,
885 thermal_zone_unbind_cooling_device
);
888 static struct thermal_zone_device_ops acpi_thermal_zone_ops
= {
889 .bind
= acpi_thermal_bind_cooling_device
,
890 .unbind
= acpi_thermal_unbind_cooling_device
,
891 .get_temp
= thermal_get_temp
,
892 .get_mode
= thermal_get_mode
,
893 .set_mode
= thermal_set_mode
,
894 .get_trip_type
= thermal_get_trip_type
,
895 .get_trip_temp
= thermal_get_trip_temp
,
896 .get_crit_temp
= thermal_get_crit_temp
,
897 .notify
= thermal_notify
,
900 static int acpi_thermal_register_thermal_zone(struct acpi_thermal
*tz
)
907 if (tz
->trips
.critical
.flags
.valid
)
910 if (tz
->trips
.hot
.flags
.valid
)
913 if (tz
->trips
.passive
.flags
.valid
)
916 for (i
= 0; i
< ACPI_THERMAL_MAX_ACTIVE
&&
917 tz
->trips
.active
[i
].flags
.valid
; i
++, trips
++);
919 if (tz
->trips
.passive
.flags
.valid
)
921 thermal_zone_device_register("acpitz", trips
, tz
,
922 &acpi_thermal_zone_ops
,
923 tz
->trips
.passive
.tc1
,
924 tz
->trips
.passive
.tc2
,
925 tz
->trips
.passive
.tsp
*100,
926 tz
->polling_frequency
*100);
929 thermal_zone_device_register("acpitz", trips
, tz
,
930 &acpi_thermal_zone_ops
,
932 tz
->polling_frequency
*100);
933 if (IS_ERR(tz
->thermal_zone
))
936 result
= sysfs_create_link(&tz
->device
->dev
.kobj
,
937 &tz
->thermal_zone
->device
.kobj
, "thermal_zone");
941 result
= sysfs_create_link(&tz
->thermal_zone
->device
.kobj
,
942 &tz
->device
->dev
.kobj
, "device");
946 status
= acpi_attach_data(tz
->device
->handle
,
947 acpi_bus_private_data_handler
,
949 if (ACPI_FAILURE(status
)) {
950 printk(KERN_ERR PREFIX
951 "Error attaching device data\n");
957 dev_info(&tz
->device
->dev
, "registered as thermal_zone%d\n",
958 tz
->thermal_zone
->id
);
962 static void acpi_thermal_unregister_thermal_zone(struct acpi_thermal
*tz
)
964 sysfs_remove_link(&tz
->device
->dev
.kobj
, "thermal_zone");
965 sysfs_remove_link(&tz
->thermal_zone
->device
.kobj
, "device");
966 thermal_zone_device_unregister(tz
->thermal_zone
);
967 tz
->thermal_zone
= NULL
;
968 acpi_detach_data(tz
->device
->handle
, acpi_bus_private_data_handler
);
972 /* --------------------------------------------------------------------------
974 -------------------------------------------------------------------------- */
976 static struct proc_dir_entry
*acpi_thermal_dir
;
978 static int acpi_thermal_state_seq_show(struct seq_file
*seq
, void *offset
)
980 struct acpi_thermal
*tz
= seq
->private;
986 seq_puts(seq
, "state: ");
988 if (!tz
->state
.critical
&& !tz
->state
.hot
&& !tz
->state
.passive
989 && !tz
->state
.active
)
990 seq_puts(seq
, "ok\n");
992 if (tz
->state
.critical
)
993 seq_puts(seq
, "critical ");
995 seq_puts(seq
, "hot ");
996 if (tz
->state
.passive
)
997 seq_puts(seq
, "passive ");
998 if (tz
->state
.active
)
999 seq_printf(seq
, "active[%d]", tz
->state
.active_index
);
1000 seq_puts(seq
, "\n");
1007 static int acpi_thermal_state_open_fs(struct inode
*inode
, struct file
*file
)
1009 return single_open(file
, acpi_thermal_state_seq_show
, PDE(inode
)->data
);
1012 static int acpi_thermal_temp_seq_show(struct seq_file
*seq
, void *offset
)
1015 struct acpi_thermal
*tz
= seq
->private;
1021 result
= acpi_thermal_get_temperature(tz
);
1025 seq_printf(seq
, "temperature: %ld C\n",
1026 KELVIN_TO_CELSIUS(tz
->temperature
));
1032 static int acpi_thermal_temp_open_fs(struct inode
*inode
, struct file
*file
)
1034 return single_open(file
, acpi_thermal_temp_seq_show
, PDE(inode
)->data
);
1037 static int acpi_thermal_trip_seq_show(struct seq_file
*seq
, void *offset
)
1039 struct acpi_thermal
*tz
= seq
->private;
1040 struct acpi_device
*device
;
1050 if (tz
->trips
.critical
.flags
.valid
)
1051 seq_printf(seq
, "critical (S5): %ld C%s",
1052 KELVIN_TO_CELSIUS(tz
->trips
.critical
.temperature
),
1053 nocrt
? " <disabled>\n" : "\n");
1055 if (tz
->trips
.hot
.flags
.valid
)
1056 seq_printf(seq
, "hot (S4): %ld C%s",
1057 KELVIN_TO_CELSIUS(tz
->trips
.hot
.temperature
),
1058 nocrt
? " <disabled>\n" : "\n");
1060 if (tz
->trips
.passive
.flags
.valid
) {
1062 "passive: %ld C: tc1=%lu tc2=%lu tsp=%lu devices=",
1063 KELVIN_TO_CELSIUS(tz
->trips
.passive
.temperature
),
1064 tz
->trips
.passive
.tc1
, tz
->trips
.passive
.tc2
,
1065 tz
->trips
.passive
.tsp
);
1066 for (j
= 0; j
< tz
->trips
.passive
.devices
.count
; j
++) {
1067 status
= acpi_bus_get_device(tz
->trips
.passive
.devices
.
1068 handles
[j
], &device
);
1069 seq_printf(seq
, "%4.4s ", status
? "" :
1070 acpi_device_bid(device
));
1072 seq_puts(seq
, "\n");
1074 seq_printf(seq
, "passive (forced):");
1075 if (tz
->thermal_zone
->forced_passive
)
1076 seq_printf(seq
, " %i C\n",
1077 tz
->thermal_zone
->forced_passive
/ 1000);
1079 seq_printf(seq
, "<not set>\n");
1082 for (i
= 0; i
< ACPI_THERMAL_MAX_ACTIVE
; i
++) {
1083 if (!(tz
->trips
.active
[i
].flags
.valid
))
1085 seq_printf(seq
, "active[%d]: %ld C: devices=",
1087 KELVIN_TO_CELSIUS(tz
->trips
.active
[i
].temperature
));
1088 for (j
= 0; j
< tz
->trips
.active
[i
].devices
.count
; j
++){
1089 status
= acpi_bus_get_device(tz
->trips
.active
[i
].
1092 seq_printf(seq
, "%4.4s ", status
? "" :
1093 acpi_device_bid(device
));
1095 seq_puts(seq
, "\n");
1102 static int acpi_thermal_trip_open_fs(struct inode
*inode
, struct file
*file
)
1104 return single_open(file
, acpi_thermal_trip_seq_show
, PDE(inode
)->data
);
1107 static int acpi_thermal_cooling_seq_show(struct seq_file
*seq
, void *offset
)
1109 struct acpi_thermal
*tz
= seq
->private;
1115 if (!tz
->flags
.cooling_mode
)
1116 seq_puts(seq
, "<setting not supported>\n");
1118 seq_puts(seq
, "0 - Active; 1 - Passive\n");
1124 static int acpi_thermal_cooling_open_fs(struct inode
*inode
, struct file
*file
)
1126 return single_open(file
, acpi_thermal_cooling_seq_show
,
1131 acpi_thermal_write_cooling_mode(struct file
*file
,
1132 const char __user
* buffer
,
1133 size_t count
, loff_t
* ppos
)
1135 struct seq_file
*m
= file
->private_data
;
1136 struct acpi_thermal
*tz
= m
->private;
1138 char mode_string
[12] = { '\0' };
1141 if (!tz
|| (count
> sizeof(mode_string
) - 1))
1144 if (!tz
->flags
.cooling_mode
)
1147 if (copy_from_user(mode_string
, buffer
, count
))
1150 mode_string
[count
] = '\0';
1152 result
= acpi_thermal_set_cooling_mode(tz
,
1153 simple_strtoul(mode_string
, NULL
,
1158 acpi_thermal_check(tz
);
1163 static int acpi_thermal_polling_seq_show(struct seq_file
*seq
, void *offset
)
1165 struct acpi_thermal
*tz
= seq
->private;
1171 if (!tz
->thermal_zone
->polling_delay
) {
1172 seq_puts(seq
, "<polling disabled>\n");
1176 seq_printf(seq
, "polling frequency: %d seconds\n",
1177 (tz
->thermal_zone
->polling_delay
/ 1000));
1183 static int acpi_thermal_polling_open_fs(struct inode
*inode
, struct file
*file
)
1185 return single_open(file
, acpi_thermal_polling_seq_show
,
1190 acpi_thermal_write_polling(struct file
*file
,
1191 const char __user
* buffer
,
1192 size_t count
, loff_t
* ppos
)
1194 struct seq_file
*m
= file
->private_data
;
1195 struct acpi_thermal
*tz
= m
->private;
1197 char polling_string
[12] = { '\0' };
1201 if (!tz
|| (count
> sizeof(polling_string
) - 1))
1204 if (copy_from_user(polling_string
, buffer
, count
))
1207 polling_string
[count
] = '\0';
1209 seconds
= simple_strtoul(polling_string
, NULL
, 0);
1211 result
= acpi_thermal_set_polling(tz
, seconds
);
1215 acpi_thermal_check(tz
);
1220 static int acpi_thermal_add_fs(struct acpi_device
*device
)
1222 struct proc_dir_entry
*entry
= NULL
;
1225 if (!acpi_device_dir(device
)) {
1226 acpi_device_dir(device
) = proc_mkdir(acpi_device_bid(device
),
1228 if (!acpi_device_dir(device
))
1233 entry
= proc_create_data(ACPI_THERMAL_FILE_STATE
,
1234 S_IRUGO
, acpi_device_dir(device
),
1235 &acpi_thermal_state_fops
,
1236 acpi_driver_data(device
));
1240 /* 'temperature' [R] */
1241 entry
= proc_create_data(ACPI_THERMAL_FILE_TEMPERATURE
,
1242 S_IRUGO
, acpi_device_dir(device
),
1243 &acpi_thermal_temp_fops
,
1244 acpi_driver_data(device
));
1248 /* 'trip_points' [R] */
1249 entry
= proc_create_data(ACPI_THERMAL_FILE_TRIP_POINTS
,
1251 acpi_device_dir(device
),
1252 &acpi_thermal_trip_fops
,
1253 acpi_driver_data(device
));
1257 /* 'cooling_mode' [R/W] */
1258 entry
= proc_create_data(ACPI_THERMAL_FILE_COOLING_MODE
,
1259 S_IFREG
| S_IRUGO
| S_IWUSR
,
1260 acpi_device_dir(device
),
1261 &acpi_thermal_cooling_fops
,
1262 acpi_driver_data(device
));
1266 /* 'polling_frequency' [R/W] */
1267 entry
= proc_create_data(ACPI_THERMAL_FILE_POLLING_FREQ
,
1268 S_IFREG
| S_IRUGO
| S_IWUSR
,
1269 acpi_device_dir(device
),
1270 &acpi_thermal_polling_fops
,
1271 acpi_driver_data(device
));
1277 static int acpi_thermal_remove_fs(struct acpi_device
*device
)
1280 if (acpi_device_dir(device
)) {
1281 remove_proc_entry(ACPI_THERMAL_FILE_POLLING_FREQ
,
1282 acpi_device_dir(device
));
1283 remove_proc_entry(ACPI_THERMAL_FILE_COOLING_MODE
,
1284 acpi_device_dir(device
));
1285 remove_proc_entry(ACPI_THERMAL_FILE_TRIP_POINTS
,
1286 acpi_device_dir(device
));
1287 remove_proc_entry(ACPI_THERMAL_FILE_TEMPERATURE
,
1288 acpi_device_dir(device
));
1289 remove_proc_entry(ACPI_THERMAL_FILE_STATE
,
1290 acpi_device_dir(device
));
1291 remove_proc_entry(acpi_device_bid(device
), acpi_thermal_dir
);
1292 acpi_device_dir(device
) = NULL
;
1298 /* --------------------------------------------------------------------------
1300 -------------------------------------------------------------------------- */
1302 static void acpi_thermal_notify(struct acpi_device
*device
, u32 event
)
1304 struct acpi_thermal
*tz
= acpi_driver_data(device
);
1311 case ACPI_THERMAL_NOTIFY_TEMPERATURE
:
1312 acpi_thermal_check(tz
);
1314 case ACPI_THERMAL_NOTIFY_THRESHOLDS
:
1315 acpi_thermal_trips_update(tz
, ACPI_TRIPS_REFRESH_THRESHOLDS
);
1316 acpi_thermal_check(tz
);
1317 acpi_bus_generate_proc_event(device
, event
, 0);
1318 acpi_bus_generate_netlink_event(device
->pnp
.device_class
,
1319 dev_name(&device
->dev
), event
, 0);
1321 case ACPI_THERMAL_NOTIFY_DEVICES
:
1322 acpi_thermal_trips_update(tz
, ACPI_TRIPS_REFRESH_DEVICES
);
1323 acpi_thermal_check(tz
);
1324 acpi_bus_generate_proc_event(device
, event
, 0);
1325 acpi_bus_generate_netlink_event(device
->pnp
.device_class
,
1326 dev_name(&device
->dev
), event
, 0);
1329 ACPI_DEBUG_PRINT((ACPI_DB_INFO
,
1330 "Unsupported event [0x%x]\n", event
));
1335 static int acpi_thermal_get_info(struct acpi_thermal
*tz
)
1343 /* Get temperature [_TMP] (required) */
1344 result
= acpi_thermal_get_temperature(tz
);
1348 /* Get trip points [_CRT, _PSV, etc.] (required) */
1349 result
= acpi_thermal_get_trip_points(tz
);
1353 /* Set the cooling mode [_SCP] to active cooling (default) */
1354 result
= acpi_thermal_set_cooling_mode(tz
, ACPI_THERMAL_MODE_ACTIVE
);
1356 tz
->flags
.cooling_mode
= 1;
1358 /* Get default polling frequency [_TZP] (optional) */
1360 tz
->polling_frequency
= tzp
;
1362 acpi_thermal_get_polling_frequency(tz
);
1368 * The exact offset between Kelvin and degree Celsius is 273.15. However ACPI
1369 * handles temperature values with a single decimal place. As a consequence,
1370 * some implementations use an offset of 273.1 and others use an offset of
1371 * 273.2. Try to find out which one is being used, to present the most
1372 * accurate and visually appealing number.
1374 * The heuristic below should work for all ACPI thermal zones which have a
1375 * critical trip point with a value being a multiple of 0.5 degree Celsius.
1377 static void acpi_thermal_guess_offset(struct acpi_thermal
*tz
)
1379 if (tz
->trips
.critical
.flags
.valid
&&
1380 (tz
->trips
.critical
.temperature
% 5) == 1)
1381 tz
->kelvin_offset
= 2731;
1383 tz
->kelvin_offset
= 2732;
1386 static int acpi_thermal_add(struct acpi_device
*device
)
1389 struct acpi_thermal
*tz
= NULL
;
1395 tz
= kzalloc(sizeof(struct acpi_thermal
), GFP_KERNEL
);
1399 tz
->device
= device
;
1400 strcpy(tz
->name
, device
->pnp
.bus_id
);
1401 strcpy(acpi_device_name(device
), ACPI_THERMAL_DEVICE_NAME
);
1402 strcpy(acpi_device_class(device
), ACPI_THERMAL_CLASS
);
1403 device
->driver_data
= tz
;
1404 mutex_init(&tz
->lock
);
1407 result
= acpi_thermal_get_info(tz
);
1411 acpi_thermal_guess_offset(tz
);
1413 result
= acpi_thermal_register_thermal_zone(tz
);
1417 result
= acpi_thermal_add_fs(device
);
1419 goto unregister_thermal_zone
;
1421 printk(KERN_INFO PREFIX
"%s [%s] (%ld C)\n",
1422 acpi_device_name(device
), acpi_device_bid(device
),
1423 KELVIN_TO_CELSIUS(tz
->temperature
));
1426 unregister_thermal_zone
:
1427 thermal_zone_device_unregister(tz
->thermal_zone
);
1434 static int acpi_thermal_remove(struct acpi_device
*device
, int type
)
1436 struct acpi_thermal
*tz
= NULL
;
1438 if (!device
|| !acpi_driver_data(device
))
1441 tz
= acpi_driver_data(device
);
1443 acpi_thermal_remove_fs(device
);
1444 acpi_thermal_unregister_thermal_zone(tz
);
1445 mutex_destroy(&tz
->lock
);
1450 static int acpi_thermal_resume(struct acpi_device
*device
)
1452 struct acpi_thermal
*tz
= NULL
;
1453 int i
, j
, power_state
, result
;
1456 if (!device
|| !acpi_driver_data(device
))
1459 tz
= acpi_driver_data(device
);
1461 for (i
= 0; i
< ACPI_THERMAL_MAX_ACTIVE
; i
++) {
1462 if (!(&tz
->trips
.active
[i
]))
1464 if (!tz
->trips
.active
[i
].flags
.valid
)
1466 tz
->trips
.active
[i
].flags
.enabled
= 1;
1467 for (j
= 0; j
< tz
->trips
.active
[i
].devices
.count
; j
++) {
1468 result
= acpi_bus_get_power(tz
->trips
.active
[i
].devices
.
1469 handles
[j
], &power_state
);
1470 if (result
|| (power_state
!= ACPI_STATE_D0
)) {
1471 tz
->trips
.active
[i
].flags
.enabled
= 0;
1475 tz
->state
.active
|= tz
->trips
.active
[i
].flags
.enabled
;
1478 acpi_thermal_check(tz
);
1483 static int thermal_act(const struct dmi_system_id
*d
) {
1486 printk(KERN_NOTICE
"ACPI: %s detected: "
1487 "disabling all active thermal trip points\n", d
->ident
);
1492 static int thermal_nocrt(const struct dmi_system_id
*d
) {
1494 printk(KERN_NOTICE
"ACPI: %s detected: "
1495 "disabling all critical thermal trip point actions.\n", d
->ident
);
1499 static int thermal_tzp(const struct dmi_system_id
*d
) {
1502 printk(KERN_NOTICE
"ACPI: %s detected: "
1503 "enabling thermal zone polling\n", d
->ident
);
1504 tzp
= 300; /* 300 dS = 30 Seconds */
1508 static int thermal_psv(const struct dmi_system_id
*d
) {
1511 printk(KERN_NOTICE
"ACPI: %s detected: "
1512 "disabling all passive thermal trip points\n", d
->ident
);
1518 static struct dmi_system_id thermal_dmi_table
[] __initdata
= {
1520 * Award BIOS on this AOpen makes thermal control almost worthless.
1521 * http://bugzilla.kernel.org/show_bug.cgi?id=8842
1524 .callback
= thermal_act
,
1525 .ident
= "AOpen i915GMm-HFS",
1527 DMI_MATCH(DMI_BOARD_VENDOR
, "AOpen"),
1528 DMI_MATCH(DMI_BOARD_NAME
, "i915GMm-HFS"),
1532 .callback
= thermal_psv
,
1533 .ident
= "AOpen i915GMm-HFS",
1535 DMI_MATCH(DMI_BOARD_VENDOR
, "AOpen"),
1536 DMI_MATCH(DMI_BOARD_NAME
, "i915GMm-HFS"),
1540 .callback
= thermal_tzp
,
1541 .ident
= "AOpen i915GMm-HFS",
1543 DMI_MATCH(DMI_BOARD_VENDOR
, "AOpen"),
1544 DMI_MATCH(DMI_BOARD_NAME
, "i915GMm-HFS"),
1548 .callback
= thermal_nocrt
,
1549 .ident
= "Gigabyte GA-7ZX",
1551 DMI_MATCH(DMI_BOARD_VENDOR
, "Gigabyte Technology Co., Ltd."),
1552 DMI_MATCH(DMI_BOARD_NAME
, "7ZX"),
1558 static int __init
acpi_thermal_init(void)
1562 dmi_check_system(thermal_dmi_table
);
1565 printk(KERN_NOTICE
"ACPI: thermal control disabled\n");
1568 acpi_thermal_dir
= proc_mkdir(ACPI_THERMAL_CLASS
, acpi_root_dir
);
1569 if (!acpi_thermal_dir
)
1572 result
= acpi_bus_register_driver(&acpi_thermal_driver
);
1574 remove_proc_entry(ACPI_THERMAL_CLASS
, acpi_root_dir
);
1581 static void __exit
acpi_thermal_exit(void)
1584 acpi_bus_unregister_driver(&acpi_thermal_driver
);
1586 remove_proc_entry(ACPI_THERMAL_CLASS
, acpi_root_dir
);
1591 module_init(acpi_thermal_init
);
1592 module_exit(acpi_thermal_exit
);