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/init.h>
37 #include <linux/types.h>
38 #include <linux/proc_fs.h>
39 #include <linux/sched.h>
40 #include <linux/kmod.h>
41 #include <linux/seq_file.h>
42 #include <asm/uaccess.h>
44 #include <acpi/acpi_bus.h>
45 #include <acpi/acpi_drivers.h>
47 #define ACPI_THERMAL_COMPONENT 0x04000000
48 #define ACPI_THERMAL_CLASS "thermal_zone"
49 #define ACPI_THERMAL_DRIVER_NAME "ACPI Thermal Zone Driver"
50 #define ACPI_THERMAL_DEVICE_NAME "Thermal Zone"
51 #define ACPI_THERMAL_FILE_STATE "state"
52 #define ACPI_THERMAL_FILE_TEMPERATURE "temperature"
53 #define ACPI_THERMAL_FILE_TRIP_POINTS "trip_points"
54 #define ACPI_THERMAL_FILE_COOLING_MODE "cooling_mode"
55 #define ACPI_THERMAL_FILE_POLLING_FREQ "polling_frequency"
56 #define ACPI_THERMAL_NOTIFY_TEMPERATURE 0x80
57 #define ACPI_THERMAL_NOTIFY_THRESHOLDS 0x81
58 #define ACPI_THERMAL_NOTIFY_DEVICES 0x82
59 #define ACPI_THERMAL_NOTIFY_CRITICAL 0xF0
60 #define ACPI_THERMAL_NOTIFY_HOT 0xF1
61 #define ACPI_THERMAL_MODE_ACTIVE 0x00
62 #define ACPI_THERMAL_MODE_PASSIVE 0x01
63 #define ACPI_THERMAL_MODE_CRT 0xff
64 #define ACPI_THERMAL_PATH_POWEROFF "/sbin/poweroff"
66 #define ACPI_THERMAL_MAX_ACTIVE 10
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)
71 #define _COMPONENT ACPI_THERMAL_COMPONENT
72 ACPI_MODULE_NAME ("acpi_thermal")
74 MODULE_AUTHOR("Paul Diefenbaugh");
75 MODULE_DESCRIPTION(ACPI_THERMAL_DRIVER_NAME
);
76 MODULE_LICENSE("GPL");
79 MODULE_PARM(tzp
, "i");
80 MODULE_PARM_DESC(tzp
, "Thermal zone polling frequency, in 1/10 seconds.\n");
83 static int acpi_thermal_add (struct acpi_device
*device
);
84 static int acpi_thermal_remove (struct acpi_device
*device
, int type
);
85 static int acpi_thermal_state_open_fs(struct inode
*inode
, struct file
*file
);
86 static int acpi_thermal_temp_open_fs(struct inode
*inode
, struct file
*file
);
87 static int acpi_thermal_trip_open_fs(struct inode
*inode
, struct file
*file
);
88 static ssize_t
acpi_thermal_write_trip_points (struct file
*,const char __user
*,size_t,loff_t
*);
89 static int acpi_thermal_cooling_open_fs(struct inode
*inode
, struct file
*file
);
90 static ssize_t
acpi_thermal_write_cooling_mode (struct file
*,const char __user
*,size_t,loff_t
*);
91 static int acpi_thermal_polling_open_fs(struct inode
*inode
, struct file
*file
);
92 static ssize_t
acpi_thermal_write_polling(struct file
*,const char __user
*,size_t,loff_t
*);
94 static struct acpi_driver acpi_thermal_driver
= {
95 .name
= ACPI_THERMAL_DRIVER_NAME
,
96 .class = ACPI_THERMAL_CLASS
,
97 .ids
= ACPI_THERMAL_HID
,
99 .add
= acpi_thermal_add
,
100 .remove
= acpi_thermal_remove
,
104 struct acpi_thermal_state
{
113 struct acpi_thermal_state_flags
{
119 struct acpi_thermal_critical
{
120 struct acpi_thermal_state_flags flags
;
121 unsigned long temperature
;
124 struct acpi_thermal_hot
{
125 struct acpi_thermal_state_flags flags
;
126 unsigned long temperature
;
129 struct acpi_thermal_passive
{
130 struct acpi_thermal_state_flags flags
;
131 unsigned long temperature
;
135 struct acpi_handle_list devices
;
138 struct acpi_thermal_active
{
139 struct acpi_thermal_state_flags flags
;
140 unsigned long temperature
;
141 struct acpi_handle_list devices
;
144 struct acpi_thermal_trips
{
145 struct acpi_thermal_critical critical
;
146 struct acpi_thermal_hot hot
;
147 struct acpi_thermal_passive passive
;
148 struct acpi_thermal_active active
[ACPI_THERMAL_MAX_ACTIVE
];
151 struct acpi_thermal_flags
{
152 u8 cooling_mode
:1; /* _SCP */
153 u8 devices
:1; /* _TZD */
157 struct acpi_thermal
{
160 unsigned long temperature
;
161 unsigned long last_temperature
;
162 unsigned long polling_frequency
;
165 struct acpi_thermal_flags flags
;
166 struct acpi_thermal_state state
;
167 struct acpi_thermal_trips trips
;
168 struct acpi_handle_list devices
;
169 struct timer_list timer
;
172 static struct file_operations acpi_thermal_state_fops
= {
173 .open
= acpi_thermal_state_open_fs
,
176 .release
= single_release
,
179 static struct file_operations acpi_thermal_temp_fops
= {
180 .open
= acpi_thermal_temp_open_fs
,
183 .release
= single_release
,
186 static struct file_operations acpi_thermal_trip_fops
= {
187 .open
= acpi_thermal_trip_open_fs
,
189 .write
= acpi_thermal_write_trip_points
,
191 .release
= single_release
,
194 static struct file_operations acpi_thermal_cooling_fops
= {
195 .open
= acpi_thermal_cooling_open_fs
,
197 .write
= acpi_thermal_write_cooling_mode
,
199 .release
= single_release
,
202 static struct file_operations acpi_thermal_polling_fops
= {
203 .open
= acpi_thermal_polling_open_fs
,
205 .write
= acpi_thermal_write_polling
,
207 .release
= single_release
,
210 /* --------------------------------------------------------------------------
211 Thermal Zone Management
212 -------------------------------------------------------------------------- */
215 acpi_thermal_get_temperature (
216 struct acpi_thermal
*tz
)
218 acpi_status status
= AE_OK
;
220 ACPI_FUNCTION_TRACE("acpi_thermal_get_temperature");
223 return_VALUE(-EINVAL
);
225 tz
->last_temperature
= tz
->temperature
;
227 status
= acpi_evaluate_integer(tz
->handle
, "_TMP", NULL
, &tz
->temperature
);
228 if (ACPI_FAILURE(status
))
231 ACPI_DEBUG_PRINT((ACPI_DB_INFO
, "Temperature is %lu dK\n", tz
->temperature
));
238 acpi_thermal_get_polling_frequency (
239 struct acpi_thermal
*tz
)
241 acpi_status status
= AE_OK
;
243 ACPI_FUNCTION_TRACE("acpi_thermal_get_polling_frequency");
246 return_VALUE(-EINVAL
);
248 status
= acpi_evaluate_integer(tz
->handle
, "_TZP", NULL
, &tz
->polling_frequency
);
249 if (ACPI_FAILURE(status
))
250 return_VALUE(-ENODEV
);
252 ACPI_DEBUG_PRINT((ACPI_DB_INFO
, "Polling frequency is %lu dS\n", tz
->polling_frequency
));
259 acpi_thermal_set_polling (
260 struct acpi_thermal
*tz
,
263 ACPI_FUNCTION_TRACE("acpi_thermal_set_polling");
266 return_VALUE(-EINVAL
);
268 tz
->polling_frequency
= seconds
* 10; /* Convert value to deci-seconds */
270 ACPI_DEBUG_PRINT((ACPI_DB_INFO
, "Polling frequency set to %lu seconds\n", tz
->polling_frequency
));
277 acpi_thermal_set_cooling_mode (
278 struct acpi_thermal
*tz
,
281 acpi_status status
= AE_OK
;
282 union acpi_object arg0
= {ACPI_TYPE_INTEGER
};
283 struct acpi_object_list arg_list
= {1, &arg0
};
284 acpi_handle handle
= NULL
;
286 ACPI_FUNCTION_TRACE("acpi_thermal_set_cooling_mode");
289 return_VALUE(-EINVAL
);
291 status
= acpi_get_handle(tz
->handle
, "_SCP", &handle
);
292 if (ACPI_FAILURE(status
)) {
293 ACPI_DEBUG_PRINT((ACPI_DB_INFO
, "_SCP not present\n"));
294 return_VALUE(-ENODEV
);
297 arg0
.integer
.value
= mode
;
299 status
= acpi_evaluate_object(handle
, NULL
, &arg_list
, NULL
);
300 if (ACPI_FAILURE(status
))
301 return_VALUE(-ENODEV
);
303 tz
->cooling_mode
= mode
;
305 ACPI_DEBUG_PRINT((ACPI_DB_INFO
, "Cooling mode [%s]\n",
306 mode
?"passive":"active"));
313 acpi_thermal_get_trip_points (
314 struct acpi_thermal
*tz
)
316 acpi_status status
= AE_OK
;
319 ACPI_FUNCTION_TRACE("acpi_thermal_get_trip_points");
322 return_VALUE(-EINVAL
);
324 /* Critical Shutdown (required) */
326 status
= acpi_evaluate_integer(tz
->handle
, "_CRT", NULL
,
327 &tz
->trips
.critical
.temperature
);
328 if (ACPI_FAILURE(status
)) {
329 tz
->trips
.critical
.flags
.valid
= 0;
330 ACPI_DEBUG_PRINT((ACPI_DB_ERROR
, "No critical threshold\n"));
334 tz
->trips
.critical
.flags
.valid
= 1;
335 ACPI_DEBUG_PRINT((ACPI_DB_INFO
, "Found critical threshold [%lu]\n", tz
->trips
.critical
.temperature
));
338 /* Critical Sleep (optional) */
340 status
= acpi_evaluate_integer(tz
->handle
, "_HOT", NULL
, &tz
->trips
.hot
.temperature
);
341 if (ACPI_FAILURE(status
)) {
342 tz
->trips
.hot
.flags
.valid
= 0;
343 ACPI_DEBUG_PRINT((ACPI_DB_INFO
, "No hot threshold\n"));
346 tz
->trips
.hot
.flags
.valid
= 1;
347 ACPI_DEBUG_PRINT((ACPI_DB_INFO
, "Found hot threshold [%lu]\n", tz
->trips
.hot
.temperature
));
350 /* Passive: Processors (optional) */
352 status
= acpi_evaluate_integer(tz
->handle
, "_PSV", NULL
, &tz
->trips
.passive
.temperature
);
353 if (ACPI_FAILURE(status
)) {
354 tz
->trips
.passive
.flags
.valid
= 0;
355 ACPI_DEBUG_PRINT((ACPI_DB_INFO
, "No passive threshold\n"));
358 tz
->trips
.passive
.flags
.valid
= 1;
360 status
= acpi_evaluate_integer(tz
->handle
, "_TC1", NULL
, &tz
->trips
.passive
.tc1
);
361 if (ACPI_FAILURE(status
))
362 tz
->trips
.passive
.flags
.valid
= 0;
364 status
= acpi_evaluate_integer(tz
->handle
, "_TC2", NULL
, &tz
->trips
.passive
.tc2
);
365 if (ACPI_FAILURE(status
))
366 tz
->trips
.passive
.flags
.valid
= 0;
368 status
= acpi_evaluate_integer(tz
->handle
, "_TSP", NULL
, &tz
->trips
.passive
.tsp
);
369 if (ACPI_FAILURE(status
))
370 tz
->trips
.passive
.flags
.valid
= 0;
372 status
= acpi_evaluate_reference(tz
->handle
, "_PSL", NULL
, &tz
->trips
.passive
.devices
);
373 if (ACPI_FAILURE(status
))
374 tz
->trips
.passive
.flags
.valid
= 0;
376 if (!tz
->trips
.passive
.flags
.valid
)
377 ACPI_DEBUG_PRINT((ACPI_DB_WARN
, "Invalid passive threshold\n"));
379 ACPI_DEBUG_PRINT((ACPI_DB_INFO
, "Found passive threshold [%lu]\n", tz
->trips
.passive
.temperature
));
382 /* Active: Fans, etc. (optional) */
384 for (i
=0; i
<ACPI_THERMAL_MAX_ACTIVE
; i
++) {
386 char name
[5] = {'_','A','C',('0'+i
),'\0'};
388 status
= acpi_evaluate_integer(tz
->handle
, name
, NULL
, &tz
->trips
.active
[i
].temperature
);
389 if (ACPI_FAILURE(status
))
393 status
= acpi_evaluate_reference(tz
->handle
, name
, NULL
, &tz
->trips
.active
[i
].devices
);
394 if (ACPI_SUCCESS(status
)) {
395 tz
->trips
.active
[i
].flags
.valid
= 1;
396 ACPI_DEBUG_PRINT((ACPI_DB_INFO
, "Found active threshold [%d]:[%lu]\n", i
, tz
->trips
.active
[i
].temperature
));
399 ACPI_DEBUG_PRINT((ACPI_DB_ERROR
, "Invalid active threshold [%d]\n", i
));
407 acpi_thermal_get_devices (
408 struct acpi_thermal
*tz
)
410 acpi_status status
= AE_OK
;
412 ACPI_FUNCTION_TRACE("acpi_thermal_get_devices");
415 return_VALUE(-EINVAL
);
417 status
= acpi_evaluate_reference(tz
->handle
, "_TZD", NULL
, &tz
->devices
);
418 if (ACPI_FAILURE(status
))
419 return_VALUE(-ENODEV
);
426 acpi_thermal_call_usermode (
429 char *argv
[2] = {NULL
, NULL
};
430 char *envp
[3] = {NULL
, NULL
, NULL
};
432 ACPI_FUNCTION_TRACE("acpi_thermal_call_usermode");
435 return_VALUE(-EINVAL
);
439 /* minimal command environment */
441 envp
[1] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
443 call_usermodehelper(argv
[0], argv
, envp
, 0);
450 acpi_thermal_critical (
451 struct acpi_thermal
*tz
)
454 struct acpi_device
*device
= NULL
;
456 ACPI_FUNCTION_TRACE("acpi_thermal_critical");
458 if (!tz
|| !tz
->trips
.critical
.flags
.valid
)
459 return_VALUE(-EINVAL
);
461 if (tz
->temperature
>= tz
->trips
.critical
.temperature
) {
462 ACPI_DEBUG_PRINT((ACPI_DB_WARN
, "Critical trip point\n"));
463 tz
->trips
.critical
.flags
.enabled
= 1;
465 else if (tz
->trips
.critical
.flags
.enabled
)
466 tz
->trips
.critical
.flags
.enabled
= 0;
468 result
= acpi_bus_get_device(tz
->handle
, &device
);
470 return_VALUE(result
);
472 printk(KERN_EMERG
"Critical temperature reached (%ld C), shutting down.\n", KELVIN_TO_CELSIUS(tz
->temperature
));
473 acpi_bus_generate_event(device
, ACPI_THERMAL_NOTIFY_CRITICAL
, tz
->trips
.critical
.flags
.enabled
);
475 acpi_thermal_call_usermode(ACPI_THERMAL_PATH_POWEROFF
);
483 struct acpi_thermal
*tz
)
486 struct acpi_device
*device
= NULL
;
488 ACPI_FUNCTION_TRACE("acpi_thermal_hot");
490 if (!tz
|| !tz
->trips
.hot
.flags
.valid
)
491 return_VALUE(-EINVAL
);
493 if (tz
->temperature
>= tz
->trips
.hot
.temperature
) {
494 ACPI_DEBUG_PRINT((ACPI_DB_WARN
, "Hot trip point\n"));
495 tz
->trips
.hot
.flags
.enabled
= 1;
497 else if (tz
->trips
.hot
.flags
.enabled
)
498 tz
->trips
.hot
.flags
.enabled
= 0;
500 result
= acpi_bus_get_device(tz
->handle
, &device
);
502 return_VALUE(result
);
504 acpi_bus_generate_event(device
, ACPI_THERMAL_NOTIFY_HOT
, tz
->trips
.hot
.flags
.enabled
);
506 /* TBD: Call user-mode "sleep(S4)" function */
513 acpi_thermal_passive (
514 struct acpi_thermal
*tz
)
517 struct acpi_thermal_passive
*passive
= NULL
;
521 ACPI_FUNCTION_TRACE("acpi_thermal_passive");
523 if (!tz
|| !tz
->trips
.passive
.flags
.valid
)
524 return_VALUE(-EINVAL
);
526 passive
= &(tz
->trips
.passive
);
531 * Calculate the thermal trend (using the passive cooling equation)
532 * and modify the performance limit for all passive cooling devices
533 * accordingly. Note that we assume symmetry.
535 if (tz
->temperature
>= passive
->temperature
) {
536 trend
= (passive
->tc1
* (tz
->temperature
- tz
->last_temperature
)) + (passive
->tc2
* (tz
->temperature
- passive
->temperature
));
537 ACPI_DEBUG_PRINT((ACPI_DB_INFO
,
538 "trend[%d]=(tc1[%lu]*(tmp[%lu]-last[%lu]))+(tc2[%lu]*(tmp[%lu]-psv[%lu]))\n",
539 trend
, passive
->tc1
, tz
->temperature
,
540 tz
->last_temperature
, passive
->tc2
,
541 tz
->temperature
, passive
->temperature
));
542 tz
->trips
.passive
.flags
.enabled
= 1;
545 for (i
=0; i
<passive
->devices
.count
; i
++)
546 acpi_processor_set_thermal_limit(
547 passive
->devices
.handles
[i
],
548 ACPI_PROCESSOR_LIMIT_INCREMENT
);
551 for (i
=0; i
<passive
->devices
.count
; i
++)
552 acpi_processor_set_thermal_limit(
553 passive
->devices
.handles
[i
],
554 ACPI_PROCESSOR_LIMIT_DECREMENT
);
560 * Implement passive cooling hysteresis to slowly increase performance
561 * and avoid thrashing around the passive trip point. Note that we
564 else if (tz
->trips
.passive
.flags
.enabled
) {
565 for (i
=0; i
<passive
->devices
.count
; i
++)
566 result
= acpi_processor_set_thermal_limit(
567 passive
->devices
.handles
[i
],
568 ACPI_PROCESSOR_LIMIT_DECREMENT
);
570 tz
->trips
.passive
.flags
.enabled
= 0;
571 ACPI_DEBUG_PRINT((ACPI_DB_INFO
,
572 "Disabling passive cooling (zone is cool)\n"));
581 acpi_thermal_active (
582 struct acpi_thermal
*tz
)
585 struct acpi_thermal_active
*active
= NULL
;
588 unsigned long maxtemp
= 0;
590 ACPI_FUNCTION_TRACE("acpi_thermal_active");
593 return_VALUE(-EINVAL
);
595 for (i
=0; i
<ACPI_THERMAL_MAX_ACTIVE
; i
++) {
597 active
= &(tz
->trips
.active
[i
]);
598 if (!active
|| !active
->flags
.valid
)
604 * If not already enabled, turn ON all cooling devices
605 * associated with this active threshold.
607 if (tz
->temperature
>= active
->temperature
) {
608 if (active
->temperature
> maxtemp
)
609 tz
->state
.active_index
= i
, maxtemp
= active
->temperature
;
610 if (!active
->flags
.enabled
) {
611 for (j
= 0; j
< active
->devices
.count
; j
++) {
612 result
= acpi_bus_set_power(active
->devices
.handles
[j
], ACPI_STATE_D0
);
614 ACPI_DEBUG_PRINT((ACPI_DB_WARN
, "Unable to turn cooling device [%p] 'on'\n", active
->devices
.handles
[j
]));
617 active
->flags
.enabled
= 1;
618 ACPI_DEBUG_PRINT((ACPI_DB_INFO
, "Cooling device [%p] now 'on'\n", active
->devices
.handles
[j
]));
625 * Turn OFF all cooling devices associated with this
628 else if (active
->flags
.enabled
) {
629 for (j
= 0; j
< active
->devices
.count
; j
++) {
630 result
= acpi_bus_set_power(active
->devices
.handles
[j
], ACPI_STATE_D3
);
632 ACPI_DEBUG_PRINT((ACPI_DB_WARN
, "Unable to turn cooling device [%p] 'off'\n", active
->devices
.handles
[j
]));
635 active
->flags
.enabled
= 0;
636 ACPI_DEBUG_PRINT((ACPI_DB_INFO
, "Cooling device [%p] now 'off'\n", active
->devices
.handles
[j
]));
645 static void acpi_thermal_check (void *context
);
651 struct acpi_thermal
*tz
= (struct acpi_thermal
*)data
;
653 acpi_os_queue_for_execution(OSD_PRIORITY_GPE
,
654 acpi_thermal_check
, (void *) data
);
663 struct acpi_thermal
*tz
= (struct acpi_thermal
*) data
;
664 unsigned long sleep_time
= 0;
666 struct acpi_thermal_state state
;
668 ACPI_FUNCTION_TRACE("acpi_thermal_check");
671 ACPI_DEBUG_PRINT((ACPI_DB_ERROR
, "Invalid (NULL) context.\n"));
677 result
= acpi_thermal_get_temperature(tz
);
681 memset(&tz
->state
, 0, sizeof(tz
->state
));
686 * Compare the current temperature to the trip point values to see
687 * if we've entered one of the thermal policy states. Note that
688 * this function determines when a state is entered, but the
689 * individual policy decides when it is exited (e.g. hysteresis).
691 if (tz
->trips
.critical
.flags
.valid
)
692 state
.critical
|= (tz
->temperature
>= tz
->trips
.critical
.temperature
);
693 if (tz
->trips
.hot
.flags
.valid
)
694 state
.hot
|= (tz
->temperature
>= tz
->trips
.hot
.temperature
);
695 if (tz
->trips
.passive
.flags
.valid
)
696 state
.passive
|= (tz
->temperature
>= tz
->trips
.passive
.temperature
);
697 for (i
=0; i
<ACPI_THERMAL_MAX_ACTIVE
; i
++)
698 if (tz
->trips
.active
[i
].flags
.valid
)
699 state
.active
|= (tz
->temperature
>= tz
->trips
.active
[i
].temperature
);
704 * Separated from the above check to allow individual policy to
705 * determine when to exit a given state.
708 acpi_thermal_critical(tz
);
710 acpi_thermal_hot(tz
);
712 acpi_thermal_passive(tz
);
714 acpi_thermal_active(tz
);
719 * Again, separated from the above two to allow independent policy
722 if (tz
->trips
.critical
.flags
.enabled
)
723 tz
->state
.critical
= 1;
724 if (tz
->trips
.hot
.flags
.enabled
)
726 if (tz
->trips
.passive
.flags
.enabled
)
727 tz
->state
.passive
= 1;
728 for (i
=0; i
<ACPI_THERMAL_MAX_ACTIVE
; i
++)
729 if (tz
->trips
.active
[i
].flags
.enabled
)
730 tz
->state
.active
= 1;
733 * Calculate Sleep Time
734 * --------------------
735 * If we're in the passive state, use _TSP's value. Otherwise
736 * use the default polling frequency (e.g. _TZP). If no polling
737 * frequency is specified then we'll wait forever (at least until
738 * a thermal event occurs). Note that _TSP and _TZD values are
739 * given in 1/10th seconds (we must covert to milliseconds).
741 if (tz
->state
.passive
)
742 sleep_time
= tz
->trips
.passive
.tsp
* 100;
743 else if (tz
->polling_frequency
> 0)
744 sleep_time
= tz
->polling_frequency
* 100;
746 ACPI_DEBUG_PRINT((ACPI_DB_INFO
, "%s: temperature[%lu] sleep[%lu]\n",
747 tz
->name
, tz
->temperature
, sleep_time
));
754 if (timer_pending(&(tz
->timer
)))
755 del_timer(&(tz
->timer
));
758 if (timer_pending(&(tz
->timer
)))
759 mod_timer(&(tz
->timer
), (HZ
* sleep_time
) / 1000);
761 tz
->timer
.data
= (unsigned long) tz
;
762 tz
->timer
.function
= acpi_thermal_run
;
763 tz
->timer
.expires
= jiffies
+ (HZ
* sleep_time
) / 1000;
764 add_timer(&(tz
->timer
));
772 /* --------------------------------------------------------------------------
774 -------------------------------------------------------------------------- */
776 struct proc_dir_entry
*acpi_thermal_dir
;
778 static int acpi_thermal_state_seq_show(struct seq_file
*seq
, void *offset
)
780 struct acpi_thermal
*tz
= (struct acpi_thermal
*)seq
->private;
782 ACPI_FUNCTION_TRACE("acpi_thermal_state_seq_show");
787 seq_puts(seq
, "state: ");
789 if (!tz
->state
.critical
&& !tz
->state
.hot
&& !tz
->state
.passive
&& !tz
->state
.active
)
790 seq_puts(seq
, "ok\n");
792 if (tz
->state
.critical
)
793 seq_puts(seq
, "critical ");
795 seq_puts(seq
, "hot ");
796 if (tz
->state
.passive
)
797 seq_puts(seq
, "passive ");
798 if (tz
->state
.active
)
799 seq_printf(seq
, "active[%d]", tz
->state
.active_index
);
807 static int acpi_thermal_state_open_fs(struct inode
*inode
, struct file
*file
)
809 return single_open(file
, acpi_thermal_state_seq_show
, PDE(inode
)->data
);
813 static int acpi_thermal_temp_seq_show(struct seq_file
*seq
, void *offset
)
816 struct acpi_thermal
*tz
= (struct acpi_thermal
*)seq
->private;
818 ACPI_FUNCTION_TRACE("acpi_thermal_temp_seq_show");
823 result
= acpi_thermal_get_temperature(tz
);
827 seq_printf(seq
, "temperature: %ld C\n",
828 KELVIN_TO_CELSIUS(tz
->temperature
));
834 static int acpi_thermal_temp_open_fs(struct inode
*inode
, struct file
*file
)
836 return single_open(file
, acpi_thermal_temp_seq_show
, PDE(inode
)->data
);
840 static int acpi_thermal_trip_seq_show(struct seq_file
*seq
, void *offset
)
842 struct acpi_thermal
*tz
= (struct acpi_thermal
*)seq
->private;
846 ACPI_FUNCTION_TRACE("acpi_thermal_trip_seq_show");
851 if (tz
->trips
.critical
.flags
.valid
)
852 seq_printf(seq
, "critical (S5): %ld C\n",
853 KELVIN_TO_CELSIUS(tz
->trips
.critical
.temperature
));
855 if (tz
->trips
.hot
.flags
.valid
)
856 seq_printf(seq
, "hot (S4): %ld C\n",
857 KELVIN_TO_CELSIUS(tz
->trips
.hot
.temperature
));
859 if (tz
->trips
.passive
.flags
.valid
) {
860 seq_printf(seq
, "passive: %ld C: tc1=%lu tc2=%lu tsp=%lu devices=",
861 KELVIN_TO_CELSIUS(tz
->trips
.passive
.temperature
),
862 tz
->trips
.passive
.tc1
,
863 tz
->trips
.passive
.tc2
,
864 tz
->trips
.passive
.tsp
);
865 for (j
=0; j
<tz
->trips
.passive
.devices
.count
; j
++) {
867 seq_printf(seq
, "0x%p ", tz
->trips
.passive
.devices
.handles
[j
]);
872 for (i
= 0; i
< ACPI_THERMAL_MAX_ACTIVE
; i
++) {
873 if (!(tz
->trips
.active
[i
].flags
.valid
))
875 seq_printf(seq
, "active[%d]: %ld C: devices=",
876 i
, KELVIN_TO_CELSIUS(tz
->trips
.active
[i
].temperature
));
877 for (j
= 0; j
< tz
->trips
.active
[i
].devices
.count
; j
++)
878 seq_printf(seq
, "0x%p ",
879 tz
->trips
.active
[i
].devices
.handles
[j
]);
887 static int acpi_thermal_trip_open_fs(struct inode
*inode
, struct file
*file
)
889 return single_open(file
, acpi_thermal_trip_seq_show
, PDE(inode
)->data
);
893 acpi_thermal_write_trip_points (
895 const char __user
*buffer
,
899 struct seq_file
*m
= (struct seq_file
*)file
->private_data
;
900 struct acpi_thermal
*tz
= (struct acpi_thermal
*)m
->private;
902 char limit_string
[65] = {'\0'};
903 int num
, critical
, hot
, passive
;
904 int active
[ACPI_THERMAL_MAX_ACTIVE
];
907 ACPI_FUNCTION_TRACE("acpi_thermal_write_trip_points");
909 if (!tz
|| (count
> sizeof(limit_string
) - 1)) {
910 ACPI_DEBUG_PRINT((ACPI_DB_ERROR
, "Invalid argument\n"));
911 return_VALUE(-EINVAL
);
914 if (copy_from_user(limit_string
, buffer
, count
)) {
915 ACPI_DEBUG_PRINT((ACPI_DB_ERROR
, "Invalid data\n"));
916 return_VALUE(-EFAULT
);
919 limit_string
[count
] = '\0';
921 num
= sscanf(limit_string
, "%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d",
922 &critical
, &hot
, &passive
,
923 &active
[0], &active
[1], &active
[2], &active
[3], &active
[4],
924 &active
[5], &active
[6], &active
[7], &active
[8], &active
[9]);
925 if(!(num
>=5 && num
< (ACPI_THERMAL_MAX_ACTIVE
+ 3))) {
926 ACPI_DEBUG_PRINT((ACPI_DB_ERROR
, "Invalid data format\n"));
927 return_VALUE(-EINVAL
);
930 tz
->trips
.critical
.temperature
= CELSIUS_TO_KELVIN(critical
);
931 tz
->trips
.hot
.temperature
= CELSIUS_TO_KELVIN(hot
);
932 tz
->trips
.passive
.temperature
= CELSIUS_TO_KELVIN(passive
);
933 for (i
= 0; i
< num
- 3; i
++) {
934 if (!(tz
->trips
.active
[i
].flags
.valid
))
936 tz
->trips
.active
[i
].temperature
= CELSIUS_TO_KELVIN(active
[i
]);
943 static int acpi_thermal_cooling_seq_show(struct seq_file
*seq
, void *offset
)
945 struct acpi_thermal
*tz
= (struct acpi_thermal
*)seq
->private;
947 ACPI_FUNCTION_TRACE("acpi_thermal_cooling_seq_show");
952 if (!tz
->flags
.cooling_mode
) {
953 seq_puts(seq
, "<setting not supported>\n");
956 if ( tz
->cooling_mode
== ACPI_THERMAL_MODE_CRT
)
957 seq_printf(seq
, "cooling mode: critical\n");
959 seq_printf(seq
, "cooling mode: %s\n",
960 tz
->cooling_mode
?"passive":"active");
966 static int acpi_thermal_cooling_open_fs(struct inode
*inode
, struct file
*file
)
968 return single_open(file
, acpi_thermal_cooling_seq_show
,
973 acpi_thermal_write_cooling_mode (
975 const char __user
*buffer
,
979 struct seq_file
*m
= (struct seq_file
*)file
->private_data
;
980 struct acpi_thermal
*tz
= (struct acpi_thermal
*)m
->private;
982 char mode_string
[12] = {'\0'};
984 ACPI_FUNCTION_TRACE("acpi_thermal_write_cooling_mode");
986 if (!tz
|| (count
> sizeof(mode_string
) - 1))
987 return_VALUE(-EINVAL
);
989 if (!tz
->flags
.cooling_mode
)
990 return_VALUE(-ENODEV
);
992 if (copy_from_user(mode_string
, buffer
, count
))
993 return_VALUE(-EFAULT
);
995 mode_string
[count
] = '\0';
997 result
= acpi_thermal_set_cooling_mode(tz
,
998 simple_strtoul(mode_string
, NULL
, 0));
1000 return_VALUE(result
);
1002 acpi_thermal_check(tz
);
1004 return_VALUE(count
);
1008 static int acpi_thermal_polling_seq_show(struct seq_file
*seq
, void *offset
)
1010 struct acpi_thermal
*tz
= (struct acpi_thermal
*)seq
->private;
1012 ACPI_FUNCTION_TRACE("acpi_thermal_polling_seq_show");
1017 if (!tz
->polling_frequency
) {
1018 seq_puts(seq
, "<polling disabled>\n");
1022 seq_printf(seq
, "polling frequency: %lu seconds\n",
1023 (tz
->polling_frequency
/ 10));
1029 static int acpi_thermal_polling_open_fs(struct inode
*inode
, struct file
*file
)
1031 return single_open(file
, acpi_thermal_polling_seq_show
,
1036 acpi_thermal_write_polling (
1038 const char __user
*buffer
,
1042 struct seq_file
*m
= (struct seq_file
*)file
->private_data
;
1043 struct acpi_thermal
*tz
= (struct acpi_thermal
*)m
->private;
1045 char polling_string
[12] = {'\0'};
1048 ACPI_FUNCTION_TRACE("acpi_thermal_write_polling");
1050 if (!tz
|| (count
> sizeof(polling_string
) - 1))
1051 return_VALUE(-EINVAL
);
1053 if (copy_from_user(polling_string
, buffer
, count
))
1054 return_VALUE(-EFAULT
);
1056 polling_string
[count
] = '\0';
1058 seconds
= simple_strtoul(polling_string
, NULL
, 0);
1060 result
= acpi_thermal_set_polling(tz
, seconds
);
1062 return_VALUE(result
);
1064 acpi_thermal_check(tz
);
1066 return_VALUE(count
);
1071 acpi_thermal_add_fs (
1072 struct acpi_device
*device
)
1074 struct proc_dir_entry
*entry
= NULL
;
1076 ACPI_FUNCTION_TRACE("acpi_thermal_add_fs");
1078 if (!acpi_device_dir(device
)) {
1079 acpi_device_dir(device
) = proc_mkdir(acpi_device_bid(device
),
1081 if (!acpi_device_dir(device
))
1082 return_VALUE(-ENODEV
);
1083 acpi_device_dir(device
)->owner
= THIS_MODULE
;
1087 entry
= create_proc_entry(ACPI_THERMAL_FILE_STATE
,
1088 S_IRUGO
, acpi_device_dir(device
));
1090 ACPI_DEBUG_PRINT((ACPI_DB_ERROR
,
1091 "Unable to create '%s' fs entry\n",
1092 ACPI_THERMAL_FILE_STATE
));
1094 entry
->proc_fops
= &acpi_thermal_state_fops
;
1095 entry
->data
= acpi_driver_data(device
);
1096 entry
->owner
= THIS_MODULE
;
1099 /* 'temperature' [R] */
1100 entry
= create_proc_entry(ACPI_THERMAL_FILE_TEMPERATURE
,
1101 S_IRUGO
, acpi_device_dir(device
));
1103 ACPI_DEBUG_PRINT((ACPI_DB_ERROR
,
1104 "Unable to create '%s' fs entry\n",
1105 ACPI_THERMAL_FILE_TEMPERATURE
));
1107 entry
->proc_fops
= &acpi_thermal_temp_fops
;
1108 entry
->data
= acpi_driver_data(device
);
1109 entry
->owner
= THIS_MODULE
;
1112 /* 'trip_points' [R/W] */
1113 entry
= create_proc_entry(ACPI_THERMAL_FILE_TRIP_POINTS
,
1114 S_IFREG
|S_IRUGO
|S_IWUSR
, acpi_device_dir(device
));
1116 ACPI_DEBUG_PRINT((ACPI_DB_ERROR
,
1117 "Unable to create '%s' fs entry\n",
1118 ACPI_THERMAL_FILE_TRIP_POINTS
));
1120 entry
->proc_fops
= &acpi_thermal_trip_fops
;
1121 entry
->data
= acpi_driver_data(device
);
1122 entry
->owner
= THIS_MODULE
;
1125 /* 'cooling_mode' [R/W] */
1126 entry
= create_proc_entry(ACPI_THERMAL_FILE_COOLING_MODE
,
1127 S_IFREG
|S_IRUGO
|S_IWUSR
, acpi_device_dir(device
));
1129 ACPI_DEBUG_PRINT((ACPI_DB_ERROR
,
1130 "Unable to create '%s' fs entry\n",
1131 ACPI_THERMAL_FILE_COOLING_MODE
));
1133 entry
->proc_fops
= &acpi_thermal_cooling_fops
;
1134 entry
->data
= acpi_driver_data(device
);
1135 entry
->owner
= THIS_MODULE
;
1138 /* 'polling_frequency' [R/W] */
1139 entry
= create_proc_entry(ACPI_THERMAL_FILE_POLLING_FREQ
,
1140 S_IFREG
|S_IRUGO
|S_IWUSR
, acpi_device_dir(device
));
1142 ACPI_DEBUG_PRINT((ACPI_DB_ERROR
,
1143 "Unable to create '%s' fs entry\n",
1144 ACPI_THERMAL_FILE_POLLING_FREQ
));
1146 entry
->proc_fops
= &acpi_thermal_polling_fops
;
1147 entry
->data
= acpi_driver_data(device
);
1148 entry
->owner
= THIS_MODULE
;
1156 acpi_thermal_remove_fs (
1157 struct acpi_device
*device
)
1159 ACPI_FUNCTION_TRACE("acpi_thermal_remove_fs");
1161 if (acpi_device_dir(device
)) {
1162 remove_proc_entry(ACPI_THERMAL_FILE_POLLING_FREQ
,
1163 acpi_device_dir(device
));
1164 remove_proc_entry(ACPI_THERMAL_FILE_COOLING_MODE
,
1165 acpi_device_dir(device
));
1166 remove_proc_entry(ACPI_THERMAL_FILE_TRIP_POINTS
,
1167 acpi_device_dir(device
));
1168 remove_proc_entry(ACPI_THERMAL_FILE_TEMPERATURE
,
1169 acpi_device_dir(device
));
1170 remove_proc_entry(ACPI_THERMAL_FILE_STATE
,
1171 acpi_device_dir(device
));
1172 remove_proc_entry(acpi_device_bid(device
), acpi_thermal_dir
);
1173 acpi_device_dir(device
) = NULL
;
1180 /* --------------------------------------------------------------------------
1182 -------------------------------------------------------------------------- */
1185 acpi_thermal_notify (
1190 struct acpi_thermal
*tz
= (struct acpi_thermal
*) data
;
1191 struct acpi_device
*device
= NULL
;
1193 ACPI_FUNCTION_TRACE("acpi_thermal_notify");
1198 if (acpi_bus_get_device(tz
->handle
, &device
))
1202 case ACPI_THERMAL_NOTIFY_TEMPERATURE
:
1203 acpi_thermal_check(tz
);
1205 case ACPI_THERMAL_NOTIFY_THRESHOLDS
:
1206 acpi_thermal_get_trip_points(tz
);
1207 acpi_thermal_check(tz
);
1208 acpi_bus_generate_event(device
, event
, 0);
1210 case ACPI_THERMAL_NOTIFY_DEVICES
:
1211 if (tz
->flags
.devices
)
1212 acpi_thermal_get_devices(tz
);
1213 acpi_bus_generate_event(device
, event
, 0);
1216 ACPI_DEBUG_PRINT((ACPI_DB_INFO
,
1217 "Unsupported event [0x%x]\n", event
));
1226 acpi_thermal_get_info (
1227 struct acpi_thermal
*tz
)
1231 ACPI_FUNCTION_TRACE("acpi_thermal_get_info");
1234 return_VALUE(-EINVAL
);
1236 /* Get temperature [_TMP] (required) */
1237 result
= acpi_thermal_get_temperature(tz
);
1239 return_VALUE(result
);
1241 /* Get trip points [_CRT, _PSV, etc.] (required) */
1242 result
= acpi_thermal_get_trip_points(tz
);
1244 return_VALUE(result
);
1246 /* Set the cooling mode [_SCP] to active cooling (default) */
1247 result
= acpi_thermal_set_cooling_mode(tz
, ACPI_THERMAL_MODE_ACTIVE
);
1249 tz
->flags
.cooling_mode
= 1;
1251 /* Oh,we have not _SCP method.
1252 Generally show cooling_mode by _ACx, _PSV,spec 12.2*/
1253 tz
->flags
.cooling_mode
= 0;
1254 if ( tz
->trips
.active
[0].flags
.valid
&& tz
->trips
.passive
.flags
.valid
) {
1255 if ( tz
->trips
.passive
.temperature
> tz
->trips
.active
[0].temperature
)
1256 tz
->cooling_mode
= ACPI_THERMAL_MODE_ACTIVE
;
1258 tz
->cooling_mode
= ACPI_THERMAL_MODE_PASSIVE
;
1259 } else if ( !tz
->trips
.active
[0].flags
.valid
&& tz
->trips
.passive
.flags
.valid
) {
1260 tz
->cooling_mode
= ACPI_THERMAL_MODE_PASSIVE
;
1261 } else if ( tz
->trips
.active
[0].flags
.valid
&& !tz
->trips
.passive
.flags
.valid
) {
1262 tz
->cooling_mode
= ACPI_THERMAL_MODE_ACTIVE
;
1264 /* _ACx and _PSV are optional, but _CRT is required */
1265 tz
->cooling_mode
= ACPI_THERMAL_MODE_CRT
;
1269 /* Get default polling frequency [_TZP] (optional) */
1271 tz
->polling_frequency
= tzp
;
1273 acpi_thermal_get_polling_frequency(tz
);
1275 /* Get devices in this thermal zone [_TZD] (optional) */
1276 result
= acpi_thermal_get_devices(tz
);
1278 tz
->flags
.devices
= 1;
1286 struct acpi_device
*device
)
1289 acpi_status status
= AE_OK
;
1290 struct acpi_thermal
*tz
= NULL
;
1292 ACPI_FUNCTION_TRACE("acpi_thermal_add");
1295 return_VALUE(-EINVAL
);
1297 tz
= kmalloc(sizeof(struct acpi_thermal
), GFP_KERNEL
);
1299 return_VALUE(-ENOMEM
);
1300 memset(tz
, 0, sizeof(struct acpi_thermal
));
1302 tz
->handle
= device
->handle
;
1303 strcpy(tz
->name
, device
->pnp
.bus_id
);
1304 strcpy(acpi_device_name(device
), ACPI_THERMAL_DEVICE_NAME
);
1305 strcpy(acpi_device_class(device
), ACPI_THERMAL_CLASS
);
1306 acpi_driver_data(device
) = tz
;
1308 result
= acpi_thermal_get_info(tz
);
1312 result
= acpi_thermal_add_fs(device
);
1314 return_VALUE(result
);
1316 init_timer(&tz
->timer
);
1318 acpi_thermal_check(tz
);
1320 status
= acpi_install_notify_handler(tz
->handle
,
1321 ACPI_DEVICE_NOTIFY
, acpi_thermal_notify
, tz
);
1322 if (ACPI_FAILURE(status
)) {
1323 ACPI_DEBUG_PRINT((ACPI_DB_ERROR
,
1324 "Error installing notify handler\n"));
1329 printk(KERN_INFO PREFIX
"%s [%s] (%ld C)\n",
1330 acpi_device_name(device
), acpi_device_bid(device
),
1331 KELVIN_TO_CELSIUS(tz
->temperature
));
1335 acpi_thermal_remove_fs(device
);
1339 return_VALUE(result
);
1344 acpi_thermal_remove (
1345 struct acpi_device
*device
,
1348 acpi_status status
= AE_OK
;
1349 struct acpi_thermal
*tz
= NULL
;
1351 ACPI_FUNCTION_TRACE("acpi_thermal_remove");
1353 if (!device
|| !acpi_driver_data(device
))
1354 return_VALUE(-EINVAL
);
1356 tz
= (struct acpi_thermal
*) acpi_driver_data(device
);
1358 /* avoid timer adding new defer task */
1360 /* wait for running timer (on other CPUs) finish */
1361 del_timer_sync(&(tz
->timer
));
1362 /* synchronize deferred task */
1363 acpi_os_wait_events_complete(NULL
);
1364 /* deferred task may reinsert timer */
1365 del_timer_sync(&(tz
->timer
));
1367 status
= acpi_remove_notify_handler(tz
->handle
,
1368 ACPI_DEVICE_NOTIFY
, acpi_thermal_notify
);
1369 if (ACPI_FAILURE(status
))
1370 ACPI_DEBUG_PRINT((ACPI_DB_ERROR
,
1371 "Error removing notify handler\n"));
1373 /* Terminate policy */
1374 if (tz
->trips
.passive
.flags
.valid
1375 && tz
->trips
.passive
.flags
.enabled
) {
1376 tz
->trips
.passive
.flags
.enabled
= 0;
1377 acpi_thermal_passive(tz
);
1379 if (tz
->trips
.active
[0].flags
.valid
1380 && tz
->trips
.active
[0].flags
.enabled
) {
1381 tz
->trips
.active
[0].flags
.enabled
= 0;
1382 acpi_thermal_active(tz
);
1385 acpi_thermal_remove_fs(device
);
1393 acpi_thermal_init (void)
1397 ACPI_FUNCTION_TRACE("acpi_thermal_init");
1399 acpi_thermal_dir
= proc_mkdir(ACPI_THERMAL_CLASS
, acpi_root_dir
);
1400 if (!acpi_thermal_dir
)
1401 return_VALUE(-ENODEV
);
1402 acpi_thermal_dir
->owner
= THIS_MODULE
;
1404 result
= acpi_bus_register_driver(&acpi_thermal_driver
);
1406 remove_proc_entry(ACPI_THERMAL_CLASS
, acpi_root_dir
);
1407 return_VALUE(-ENODEV
);
1415 acpi_thermal_exit (void)
1417 ACPI_FUNCTION_TRACE("acpi_thermal_exit");
1419 acpi_bus_unregister_driver(&acpi_thermal_driver
);
1421 remove_proc_entry(ACPI_THERMAL_CLASS
, acpi_root_dir
);
1427 module_init(acpi_thermal_init
);
1428 module_exit(acpi_thermal_exit
);