Merge with Linux 2.5.48.
[linux-2.6/linux-mips.git] / drivers / acpi / thermal.c
blob863f1b0a218d01a0df3a633875cf4e314cb59bd6
1 /*
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/compatmac.h>
39 #include <linux/proc_fs.h>
40 #include <linux/sched.h>
41 #include <linux/kmod.h>
42 #include "acpi_bus.h"
43 #include "acpi_drivers.h"
45 #define ACPI_THERMAL_COMPONENT 0x04000000
46 #define ACPI_THERMAL_CLASS "thermal_zone"
47 #define ACPI_THERMAL_DRIVER_NAME "ACPI Thermal Zone Driver"
48 #define ACPI_THERMAL_DEVICE_NAME "Thermal Zone"
49 #define ACPI_THERMAL_FILE_STATE "state"
50 #define ACPI_THERMAL_FILE_TEMPERATURE "temperature"
51 #define ACPI_THERMAL_FILE_TRIP_POINTS "trip_points"
52 #define ACPI_THERMAL_FILE_COOLING_MODE "cooling_mode"
53 #define ACPI_THERMAL_FILE_POLLING_FREQ "polling_frequency"
54 #define ACPI_THERMAL_NOTIFY_TEMPERATURE 0x80
55 #define ACPI_THERMAL_NOTIFY_THRESHOLDS 0x81
56 #define ACPI_THERMAL_NOTIFY_DEVICES 0x82
57 #define ACPI_THERMAL_NOTIFY_CRITICAL 0xF0
58 #define ACPI_THERMAL_NOTIFY_HOT 0xF1
59 #define ACPI_THERMAL_MODE_ACTIVE 0x00
60 #define ACPI_THERMAL_MODE_PASSIVE 0x01
61 #define ACPI_THERMAL_PATH_POWEROFF "/sbin/poweroff"
63 #define ACPI_THERMAL_MAX_ACTIVE 10
65 #define KELVIN_TO_CELSIUS(t) (long)(((long)t-2732>=0) ? ((long)t-2732+5)/10 : ((long)t-2732-5)/10)
66 #define CELSIUS_TO_KELVIN(t) ((t+273)*10)
68 #define _COMPONENT ACPI_THERMAL_COMPONENT
69 ACPI_MODULE_NAME ("acpi_thermal")
71 MODULE_AUTHOR("Paul Diefenbaugh");
72 MODULE_DESCRIPTION(ACPI_THERMAL_DRIVER_NAME);
73 MODULE_LICENSE("GPL");
75 static int tzp = 0;
76 MODULE_PARM(tzp, "i");
77 MODULE_PARM_DESC(tzp, "Thermal zone polling frequency, in 1/10 seconds.\n");
80 static int acpi_thermal_add (struct acpi_device *device);
81 static int acpi_thermal_remove (struct acpi_device *device, int type);
83 static struct acpi_driver acpi_thermal_driver = {
84 .name = ACPI_THERMAL_DRIVER_NAME,
85 .class = ACPI_THERMAL_CLASS,
86 .ids = ACPI_THERMAL_HID,
87 .ops = {
88 .add = acpi_thermal_add,
89 .remove = acpi_thermal_remove,
93 struct acpi_thermal_state {
94 u8 critical:1;
95 u8 hot:1;
96 u8 passive:1;
97 u8 active:1;
98 u8 reserved:4;
99 int active_index;
102 struct acpi_thermal_state_flags {
103 u8 valid:1;
104 u8 enabled:1;
105 u8 reserved:6;
108 struct acpi_thermal_critical {
109 struct acpi_thermal_state_flags flags;
110 unsigned long temperature;
113 struct acpi_thermal_hot {
114 struct acpi_thermal_state_flags flags;
115 unsigned long temperature;
118 struct acpi_thermal_passive {
119 struct acpi_thermal_state_flags flags;
120 unsigned long temperature;
121 unsigned long tc1;
122 unsigned long tc2;
123 unsigned long tsp;
124 struct acpi_handle_list devices;
127 struct acpi_thermal_active {
128 struct acpi_thermal_state_flags flags;
129 unsigned long temperature;
130 struct acpi_handle_list devices;
133 struct acpi_thermal_trips {
134 struct acpi_thermal_critical critical;
135 struct acpi_thermal_hot hot;
136 struct acpi_thermal_passive passive;
137 struct acpi_thermal_active active[ACPI_THERMAL_MAX_ACTIVE];
140 struct acpi_thermal_flags {
141 u8 cooling_mode:1; /* _SCP */
142 u8 devices:1; /* _TZD */
143 u8 reserved:6;
146 struct acpi_thermal {
147 acpi_handle handle;
148 acpi_bus_id name;
149 unsigned long temperature;
150 unsigned long last_temperature;
151 unsigned long polling_frequency;
152 u8 cooling_mode;
153 struct acpi_thermal_flags flags;
154 struct acpi_thermal_state state;
155 struct acpi_thermal_trips trips;
156 struct acpi_handle_list devices;
157 struct timer_list timer;
161 /* --------------------------------------------------------------------------
162 Thermal Zone Management
163 -------------------------------------------------------------------------- */
165 static int
166 acpi_thermal_get_temperature (
167 struct acpi_thermal *tz)
169 acpi_status status = AE_OK;
171 ACPI_FUNCTION_TRACE("acpi_thermal_get_temperature");
173 if (!tz)
174 return_VALUE(-EINVAL);
176 tz->last_temperature = tz->temperature;
178 status = acpi_evaluate_integer(tz->handle, "_TMP", NULL, &tz->temperature);
179 if (ACPI_FAILURE(status))
180 return -ENODEV;
182 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Temperature is %lu dK\n", tz->temperature));
184 return_VALUE(0);
188 static int
189 acpi_thermal_get_polling_frequency (
190 struct acpi_thermal *tz)
192 acpi_status status = AE_OK;
194 ACPI_FUNCTION_TRACE("acpi_thermal_get_polling_frequency");
196 if (!tz)
197 return_VALUE(-EINVAL);
199 status = acpi_evaluate_integer(tz->handle, "_TZP", NULL, &tz->polling_frequency);
200 if (ACPI_FAILURE(status))
201 return_VALUE(-ENODEV);
203 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Polling frequency is %lu dS\n", tz->polling_frequency));
205 return_VALUE(0);
209 static int
210 acpi_thermal_set_polling (
211 struct acpi_thermal *tz,
212 int seconds)
214 ACPI_FUNCTION_TRACE("acpi_thermal_set_polling");
216 if (!tz)
217 return_VALUE(-EINVAL);
219 tz->polling_frequency = seconds * 10; /* Convert value to deci-seconds */
221 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Polling frequency set to %lu seconds\n", tz->polling_frequency));
223 return_VALUE(0);
227 static int
228 acpi_thermal_set_cooling_mode (
229 struct acpi_thermal *tz,
230 int mode)
232 acpi_status status = AE_OK;
233 acpi_object arg0 = {ACPI_TYPE_INTEGER};
234 acpi_object_list arg_list= {1, &arg0};
235 acpi_handle handle = NULL;
237 ACPI_FUNCTION_TRACE("acpi_thermal_set_cooling_mode");
239 if (!tz)
240 return_VALUE(-EINVAL);
242 status = acpi_get_handle(tz->handle, "_SCP", &handle);
243 if (ACPI_FAILURE(status)) {
244 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "_SCP not present\n"));
245 return_VALUE(-ENODEV);
248 arg0.integer.value = mode;
250 status = acpi_evaluate_object(handle, NULL, &arg_list, NULL);
251 if (ACPI_FAILURE(status))
252 return_VALUE(-ENODEV);
254 tz->cooling_mode = mode;
256 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Cooling mode [%s]\n",
257 mode?"passive":"active"));
259 return_VALUE(0);
263 static int
264 acpi_thermal_get_trip_points (
265 struct acpi_thermal *tz)
267 acpi_status status = AE_OK;
268 int i = 0;
270 ACPI_FUNCTION_TRACE("acpi_thermal_get_trip_points");
272 if (!tz)
273 return_VALUE(-EINVAL);
275 /* Critical Shutdown (required) */
277 status = acpi_evaluate_integer(tz->handle, "_CRT", NULL,
278 &tz->trips.critical.temperature);
279 if (ACPI_FAILURE(status)) {
280 tz->trips.critical.flags.valid = 0;
281 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "No critical threshold\n"));
282 return -ENODEV;
284 else {
285 tz->trips.critical.flags.valid = 1;
286 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found critical threshold [%lu]\n", tz->trips.critical.temperature));
289 /* Critical Sleep (optional) */
291 status = acpi_evaluate_integer(tz->handle, "_HOT", NULL, &tz->trips.hot.temperature);
292 if (ACPI_FAILURE(status)) {
293 tz->trips.hot.flags.valid = 0;
294 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No hot threshold\n"));
296 else {
297 tz->trips.hot.flags.valid = 1;
298 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found hot threshold [%lu]\n", tz->trips.hot.temperature));
301 /* Passive: Processors (optional) */
303 status = acpi_evaluate_integer(tz->handle, "_PSV", NULL, &tz->trips.passive.temperature);
304 if (ACPI_FAILURE(status)) {
305 tz->trips.passive.flags.valid = 0;
306 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No passive threshold\n"));
308 else {
309 tz->trips.passive.flags.valid = 1;
311 status = acpi_evaluate_integer(tz->handle, "_TC1", NULL, &tz->trips.passive.tc1);
312 if (ACPI_FAILURE(status))
313 tz->trips.passive.flags.valid = 0;
315 status = acpi_evaluate_integer(tz->handle, "_TC2", NULL, &tz->trips.passive.tc2);
316 if (ACPI_FAILURE(status))
317 tz->trips.passive.flags.valid = 0;
319 status = acpi_evaluate_integer(tz->handle, "_TSP", NULL, &tz->trips.passive.tsp);
320 if (ACPI_FAILURE(status))
321 tz->trips.passive.flags.valid = 0;
323 status = acpi_evaluate_reference(tz->handle, "_PSL", NULL, &tz->trips.passive.devices);
324 if (ACPI_FAILURE(status))
325 tz->trips.passive.flags.valid = 0;
327 if (!tz->trips.passive.flags.valid)
328 ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Invalid passive threshold\n"));
329 else
330 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found passive threshold [%lu]\n", tz->trips.passive.temperature));
333 /* Active: Fans, etc. (optional) */
335 for (i=0; i<ACPI_THERMAL_MAX_ACTIVE; i++) {
337 char name[5] = {'_','A','C',('0'+i),'\0'};
339 status = acpi_evaluate_integer(tz->handle, name, NULL, &tz->trips.active[i].temperature);
340 if (ACPI_FAILURE(status))
341 break;
343 name[2] = 'L';
344 status = acpi_evaluate_reference(tz->handle, name, NULL, &tz->trips.active[i].devices);
345 if (ACPI_SUCCESS(status)) {
346 tz->trips.active[i].flags.valid = 1;
347 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found active threshold [%d]:[%lu]\n", i, tz->trips.active[i].temperature));
349 else
350 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid active threshold [%d]\n", i));
353 return_VALUE(0);
357 static int
358 acpi_thermal_get_devices (
359 struct acpi_thermal *tz)
361 acpi_status status = AE_OK;
363 ACPI_FUNCTION_TRACE("acpi_thermal_get_devices");
365 if (!tz)
366 return_VALUE(-EINVAL);
368 status = acpi_evaluate_reference(tz->handle, "_TZD", NULL, &tz->devices);
369 if (ACPI_FAILURE(status))
370 return_VALUE(-ENODEV);
372 return_VALUE(0);
376 static int
377 acpi_thermal_call_usermode (
378 char *path)
380 char *argv[2] = {NULL, NULL};
381 char *envp[3] = {NULL, NULL, NULL};
383 ACPI_FUNCTION_TRACE("acpi_thermal_call_usermode");
385 if (!path)
386 return_VALUE(-EINVAL);;
388 argv[0] = path;
390 /* minimal command environment */
391 envp[0] = "HOME=/";
392 envp[1] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
394 call_usermodehelper(argv[0], argv, envp);
396 return_VALUE(0);
400 static int
401 acpi_thermal_critical (
402 struct acpi_thermal *tz)
404 int result = 0;
405 struct acpi_device *device = NULL;
407 ACPI_FUNCTION_TRACE("acpi_thermal_critical");
409 if (!tz || !tz->trips.critical.flags.valid)
410 return_VALUE(-EINVAL);
412 if (tz->temperature >= tz->trips.critical.temperature) {
413 ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Critical trip point\n"));
414 tz->trips.critical.flags.enabled = 1;
416 else if (tz->trips.critical.flags.enabled)
417 tz->trips.critical.flags.enabled = 0;
419 result = acpi_bus_get_device(tz->handle, &device);
420 if (result)
421 return_VALUE(result);
423 acpi_bus_generate_event(device, ACPI_THERMAL_NOTIFY_CRITICAL, tz->trips.critical.flags.enabled);
425 acpi_thermal_call_usermode(ACPI_THERMAL_PATH_POWEROFF);
427 return_VALUE(0);
431 static int
432 acpi_thermal_hot (
433 struct acpi_thermal *tz)
435 int result = 0;
436 struct acpi_device *device = NULL;
438 ACPI_FUNCTION_TRACE("acpi_thermal_hot");
440 if (!tz || !tz->trips.hot.flags.valid)
441 return_VALUE(-EINVAL);
443 if (tz->temperature >= tz->trips.hot.temperature) {
444 ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Hot trip point\n"));
445 tz->trips.hot.flags.enabled = 1;
447 else if (tz->trips.hot.flags.enabled)
448 tz->trips.hot.flags.enabled = 0;
450 result = acpi_bus_get_device(tz->handle, &device);
451 if (result)
452 return_VALUE(result);
454 acpi_bus_generate_event(device, ACPI_THERMAL_NOTIFY_HOT, tz->trips.hot.flags.enabled);
456 /* TBD: Call user-mode "sleep(S4)" function */
458 return_VALUE(0);
462 static int
463 acpi_thermal_passive (
464 struct acpi_thermal *tz)
466 int result = 0;
467 struct acpi_thermal_passive *passive = NULL;
468 int trend = 0;
469 int i = 0;
471 ACPI_FUNCTION_TRACE("acpi_thermal_passive");
473 if (!tz || !tz->trips.passive.flags.valid)
474 return_VALUE(-EINVAL);
476 passive = &(tz->trips.passive);
479 * Above Trip?
480 * -----------
481 * Calculate the thermal trend (using the passive cooling equation)
482 * and modify the performance limit for all passive cooling devices
483 * accordingly. Note that we assume symmetry.
485 if (tz->temperature >= passive->temperature) {
486 trend = (passive->tc1 * (tz->temperature - tz->last_temperature)) + (passive->tc2 * (tz->temperature - passive->temperature));
487 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
488 "trend[%d]=(tc1[%lu]*(tmp[%lu]-last[%lu]))+(tc2[%lu]*(tmp[%lu]-psv[%lu]))\n",
489 trend, passive->tc1, tz->temperature,
490 tz->last_temperature, passive->tc2,
491 tz->temperature, passive->temperature));
492 tz->trips.passive.flags.enabled = 1;
493 /* Heating up? */
494 if (trend > 0)
495 for (i=0; i<passive->devices.count; i++)
496 acpi_processor_set_thermal_limit(
497 passive->devices.handles[i],
498 ACPI_PROCESSOR_LIMIT_INCREMENT);
499 /* Cooling off? */
500 else if (trend < 0)
501 for (i=0; i<passive->devices.count; i++)
502 acpi_processor_set_thermal_limit(
503 passive->devices.handles[i],
504 ACPI_PROCESSOR_LIMIT_DECREMENT);
508 * Below Trip?
509 * -----------
510 * Implement passive cooling hysteresis to slowly increase performance
511 * and avoid thrashing around the passive trip point. Note that we
512 * assume symmetry.
514 else if (tz->trips.passive.flags.enabled) {
515 for (i=0; i<passive->devices.count; i++)
516 result = acpi_processor_set_thermal_limit(
517 passive->devices.handles[i],
518 ACPI_PROCESSOR_LIMIT_DECREMENT);
519 if (result == 1) {
520 tz->trips.passive.flags.enabled = 0;
521 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
522 "Disabling passive cooling (zone is cool)\n"));
526 return_VALUE(0);
530 static int
531 acpi_thermal_active (
532 struct acpi_thermal *tz)
534 int result = 0;
535 struct acpi_thermal_active *active = NULL;
536 int i = 0;
537 int j = 0;
538 unsigned long maxtemp = 0;
540 ACPI_FUNCTION_TRACE("acpi_thermal_active");
542 if (!tz)
543 return_VALUE(-EINVAL);
545 for (i=0; i<ACPI_THERMAL_MAX_ACTIVE; i++) {
547 active = &(tz->trips.active[i]);
548 if (!active || !active->flags.valid)
549 break;
552 * Above Threshold?
553 * ----------------
554 * If not already enabled, turn ON all cooling devices
555 * associated with this active threshold.
557 if (tz->temperature >= active->temperature) {
558 if (active->temperature > maxtemp)
559 tz->state.active_index = i, maxtemp = active->temperature;
560 if (!active->flags.enabled) {
561 for (j = 0; j < active->devices.count; j++) {
562 result = acpi_bus_set_power(active->devices.handles[j], ACPI_STATE_D0);
563 if (result) {
564 ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Unable to turn cooling device [%p] 'on'\n", active->devices.handles[j]));
565 continue;
567 active->flags.enabled = 1;
568 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Cooling device [%p] now 'on'\n", active->devices.handles[j]));
573 * Below Threshold?
574 * ----------------
575 * Turn OFF all cooling devices associated with this
576 * threshold.
578 else if (active->flags.enabled) {
579 for (j = 0; j < active->devices.count; j++) {
580 result = acpi_bus_set_power(active->devices.handles[j], ACPI_STATE_D3);
581 if (result) {
582 ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Unable to turn cooling device [%p] 'off'\n", active->devices.handles[j]));
583 continue;
585 active->flags.enabled = 0;
586 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Cooling device [%p] now 'off'\n", active->devices.handles[j]));
591 return_VALUE(0);
595 static void acpi_thermal_check (void *context);
597 static void
598 acpi_thermal_run (
599 unsigned long data)
601 acpi_os_queue_for_execution(OSD_PRIORITY_GPE, acpi_thermal_check, (void *) data);
605 static void
606 acpi_thermal_check (
607 void *data)
609 int result = 0;
610 struct acpi_thermal *tz = (struct acpi_thermal *) data;
611 unsigned long sleep_time = 0;
612 int i = 0;
613 struct acpi_thermal_state state = tz->state;
615 ACPI_FUNCTION_TRACE("acpi_thermal_check");
617 if (!tz) {
618 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid (NULL) context.\n"));
619 return_VOID;
622 result = acpi_thermal_get_temperature(tz);
623 if (result)
624 return_VOID;
626 memset(&tz->state, 0, sizeof(tz->state));
629 * Check Trip Points
630 * -----------------
631 * Compare the current temperature to the trip point values to see
632 * if we've entered one of the thermal policy states. Note that
633 * this function determines when a state is entered, but the
634 * individual policy decides when it is exited (e.g. hysteresis).
636 if (tz->trips.critical.flags.valid)
637 state.critical |= (tz->temperature >= tz->trips.critical.temperature);
638 if (tz->trips.hot.flags.valid)
639 state.hot |= (tz->temperature >= tz->trips.hot.temperature);
640 if (tz->trips.passive.flags.valid)
641 state.passive |= (tz->temperature >= tz->trips.passive.temperature);
642 for (i=0; i<ACPI_THERMAL_MAX_ACTIVE; i++)
643 if (tz->trips.active[i].flags.valid)
644 state.active |= (tz->temperature >= tz->trips.active[i].temperature);
647 * Invoke Policy
648 * -------------
649 * Separated from the above check to allow individual policy to
650 * determine when to exit a given state.
652 if (state.critical)
653 acpi_thermal_critical(tz);
654 if (state.hot)
655 acpi_thermal_hot(tz);
656 if (state.passive)
657 acpi_thermal_passive(tz);
658 if (state.active)
659 acpi_thermal_active(tz);
662 * Calculate State
663 * ---------------
664 * Again, separated from the above two to allow independent policy
665 * decisions.
667 if (tz->trips.critical.flags.enabled)
668 tz->state.critical = 1;
669 if (tz->trips.hot.flags.enabled)
670 tz->state.hot = 1;
671 if (tz->trips.passive.flags.enabled)
672 tz->state.passive = 1;
673 for (i=0; i<ACPI_THERMAL_MAX_ACTIVE; i++)
674 if (tz->trips.active[i].flags.enabled)
675 tz->state.active = 1;
678 * Calculate Sleep Time
679 * --------------------
680 * If we're in the passive state, use _TSP's value. Otherwise
681 * use the default polling frequency (e.g. _TZP). If no polling
682 * frequency is specified then we'll wait forever (at least until
683 * a thermal event occurs). Note that _TSP and _TZD values are
684 * given in 1/10th seconds (we must covert to milliseconds).
686 if (tz->state.passive)
687 sleep_time = tz->trips.passive.tsp * 100;
688 else if (tz->polling_frequency > 0)
689 sleep_time = tz->polling_frequency * 100;
691 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%s: temperature[%lu] sleep[%lu]\n",
692 tz->name, tz->temperature, sleep_time));
695 * Schedule Next Poll
696 * ------------------
698 if (!sleep_time) {
699 if (timer_pending(&(tz->timer)))
700 del_timer(&(tz->timer));
702 else {
703 if (timer_pending(&(tz->timer)))
704 mod_timer(&(tz->timer), (HZ * sleep_time) / 1000);
705 else {
706 tz->timer.data = (unsigned long) tz;
707 tz->timer.function = acpi_thermal_run;
708 tz->timer.expires = jiffies + (HZ * sleep_time) / 1000;
709 add_timer(&(tz->timer));
713 return_VOID;
717 /* --------------------------------------------------------------------------
718 FS Interface (/proc)
719 -------------------------------------------------------------------------- */
721 struct proc_dir_entry *acpi_thermal_dir = NULL;
724 static int
725 acpi_thermal_read_state (
726 char *page,
727 char **start,
728 off_t off,
729 int count,
730 int *eof,
731 void *data)
733 struct acpi_thermal *tz = (struct acpi_thermal *) data;
734 char *p = page;
735 int len = 0;
737 ACPI_FUNCTION_TRACE("acpi_thermal_read_state");
739 if (!tz || (off != 0))
740 goto end;
742 p += sprintf(p, "state: ");
744 if (!tz->state.critical && !tz->state.hot && !tz->state.passive && !tz->state.active)
745 p += sprintf(p, "ok\n");
746 else {
747 if (tz->state.critical)
748 p += sprintf(p, "critical ");
749 if (tz->state.hot)
750 p += sprintf(p, "hot ");
751 if (tz->state.passive)
752 p += sprintf(p, "passive ");
753 if (tz->state.active)
754 p += sprintf(p, "active[%d]", tz->state.active_index);
755 p += sprintf(p, "\n");
758 end:
759 len = (p - page);
760 if (len <= off+count) *eof = 1;
761 *start = page + off;
762 len -= off;
763 if (len>count) len = count;
764 if (len<0) len = 0;
766 return_VALUE(len);
770 static int
771 acpi_thermal_read_temperature (
772 char *page,
773 char **start,
774 off_t off,
775 int count,
776 int *eof,
777 void *data)
779 int result = 0;
780 struct acpi_thermal *tz = (struct acpi_thermal *) data;
781 char *p = page;
782 int len = 0;
784 ACPI_FUNCTION_TRACE("acpi_thermal_read_temperature");
786 if (!tz || (off != 0))
787 goto end;
789 result = acpi_thermal_get_temperature(tz);
790 if (result)
791 goto end;
793 p += sprintf(p, "temperature: %ld C\n",
794 KELVIN_TO_CELSIUS(tz->temperature));
796 end:
797 len = (p - page);
798 if (len <= off+count) *eof = 1;
799 *start = page + off;
800 len -= off;
801 if (len>count) len = count;
802 if (len<0) len = 0;
804 return_VALUE(len);
808 static int
809 acpi_thermal_read_trip_points (
810 char *page,
811 char **start,
812 off_t off,
813 int count,
814 int *eof,
815 void *data)
817 struct acpi_thermal *tz = (struct acpi_thermal *) data;
818 char *p = page;
819 int len = 0;
820 int i = 0;
821 int j = 0;
823 ACPI_FUNCTION_TRACE("acpi_thermal_read_trip_points");
825 if (!tz || (off != 0))
826 goto end;
828 if (tz->trips.critical.flags.valid)
829 p += sprintf(p, "critical (S5): %ld C\n",
830 KELVIN_TO_CELSIUS(tz->trips.critical.temperature));
832 if (tz->trips.hot.flags.valid)
833 p += sprintf(p, "hot (S4): %ld C\n",
834 KELVIN_TO_CELSIUS(tz->trips.hot.temperature));
836 if (tz->trips.passive.flags.valid) {
837 p += sprintf(p, "passive: %ld C: tc1=%lu tc2=%lu tsp=%lu devices=",
838 KELVIN_TO_CELSIUS(tz->trips.passive.temperature),
839 tz->trips.passive.tc1,
840 tz->trips.passive.tc2,
841 tz->trips.passive.tsp);
842 for (j=0; j<tz->trips.passive.devices.count; j++) {
844 p += sprintf(p, "0x%p ", tz->trips.passive.devices.handles[j]);
846 p += sprintf(p, "\n");
849 for (i=0; i<ACPI_THERMAL_MAX_ACTIVE; i++) {
850 if (!(tz->trips.active[i].flags.valid))
851 break;
852 p += sprintf(p, "active[%d]: %ld C: devices=",
853 i, KELVIN_TO_CELSIUS(tz->trips.active[i].temperature));
854 for (j=0; j<tz->trips.active[i].devices.count; j++)
855 p += sprintf(p, "0x%p ",
856 tz->trips.active[i].devices.handles[j]);
857 p += sprintf(p, "\n");
860 end:
861 len = (p - page);
862 if (len <= off+count) *eof = 1;
863 *start = page + off;
864 len -= off;
865 if (len>count) len = count;
866 if (len<0) len = 0;
868 return_VALUE(len);
872 static int
873 acpi_thermal_write_trip_points (
874 struct file *file,
875 const char *buffer,
876 unsigned long count,
877 void *data)
879 struct acpi_thermal *tz = (struct acpi_thermal *) data;
880 char limit_string[25] = {'\0'};
881 int critical, hot, passive, active0, active1;
883 ACPI_FUNCTION_TRACE("acpi_thermal_write_trip_points");
885 if (!tz || (count > sizeof(limit_string) - 1)) {
886 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid argument\n"));
887 return_VALUE(-EINVAL);
890 if (copy_from_user(limit_string, buffer, count)) {
891 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid data\n"));
892 return_VALUE(-EFAULT);
895 limit_string[count] = '\0';
897 if (sscanf(limit_string, "%d:%d:%d:%d:%d", &critical, &hot, &passive, &active0, &active1) != 5) {
898 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid data format\n"));
899 return_VALUE(-EINVAL);
902 tz->trips.critical.temperature = CELSIUS_TO_KELVIN(critical);
903 tz->trips.hot.temperature = CELSIUS_TO_KELVIN(hot);
904 tz->trips.passive.temperature = CELSIUS_TO_KELVIN(passive);
905 tz->trips.active[0].temperature = CELSIUS_TO_KELVIN(active0);
906 tz->trips.active[1].temperature = CELSIUS_TO_KELVIN(active1);
908 return_VALUE(count);
912 static int
913 acpi_thermal_read_cooling_mode (
914 char *page,
915 char **start,
916 off_t off,
917 int count,
918 int *eof,
919 void *data)
921 struct acpi_thermal *tz = (struct acpi_thermal *) data;
922 char *p = page;
923 int len = 0;
925 ACPI_FUNCTION_TRACE("acpi_thermal_read_cooling_mode");
927 if (!tz || (off != 0))
928 goto end;
930 if (!tz->flags.cooling_mode) {
931 p += sprintf(p, "<not supported>\n");
932 goto end;
935 p += sprintf(p, "cooling mode: %s\n",
936 tz->cooling_mode?"passive":"active");
938 end:
939 len = (p - page);
940 if (len <= off+count) *eof = 1;
941 *start = page + off;
942 len -= off;
943 if (len>count) len = count;
944 if (len<0) len = 0;
946 return_VALUE(len);
950 static int
951 acpi_thermal_write_cooling_mode (
952 struct file *file,
953 const char *buffer,
954 unsigned long count,
955 void *data)
957 int result = 0;
958 struct acpi_thermal *tz = (struct acpi_thermal *) data;
959 char mode_string[12] = {'\0'};
961 ACPI_FUNCTION_TRACE("acpi_thermal_write_cooling_mode");
963 if (!tz || (count > sizeof(mode_string) - 1))
964 return_VALUE(-EINVAL);
966 if (!tz->flags.cooling_mode)
967 return_VALUE(-ENODEV);
969 if (copy_from_user(mode_string, buffer, count))
970 return_VALUE(-EFAULT);
972 mode_string[count] = '\0';
974 result = acpi_thermal_set_cooling_mode(tz,
975 simple_strtoul(mode_string, NULL, 0));
976 if (result)
977 return_VALUE(result);
979 return_VALUE(count);
983 static int
984 acpi_thermal_read_polling (
985 char *page,
986 char **start,
987 off_t off,
988 int count,
989 int *eof,
990 void *data)
992 struct acpi_thermal *tz = (struct acpi_thermal *) data;
993 char *p = page;
994 int len = 0;
996 ACPI_FUNCTION_TRACE("acpi_thermal_read_polling");
998 if (!tz || (off != 0))
999 goto end;
1001 if (!tz->polling_frequency) {
1002 p += sprintf(p, "<polling disabled>\n");
1003 goto end;
1006 p += sprintf(p, "polling frequency: %lu seconds\n",
1007 (tz->polling_frequency / 10));
1009 end:
1010 len = (p - page);
1011 if (len <= off+count) *eof = 1;
1012 *start = page + off;
1013 len -= off;
1014 if (len>count) len = count;
1015 if (len<0) len = 0;
1017 return_VALUE(len);
1021 static int
1022 acpi_thermal_write_polling (
1023 struct file *file,
1024 const char *buffer,
1025 unsigned long count,
1026 void *data)
1028 int result = 0;
1029 struct acpi_thermal *tz = (struct acpi_thermal *) data;
1030 char polling_string[12] = {'\0'};
1031 int seconds = 0;
1033 ACPI_FUNCTION_TRACE("acpi_thermal_write_polling");
1035 if (!tz || (count > sizeof(polling_string) - 1))
1036 return_VALUE(-EINVAL);
1038 if (copy_from_user(polling_string, buffer, count))
1039 return_VALUE(-EFAULT);
1041 polling_string[count] = '\0';
1043 seconds = simple_strtoul(polling_string, NULL, 0);
1045 result = acpi_thermal_set_polling(tz, seconds);
1046 if (result)
1047 return_VALUE(result);
1049 acpi_thermal_check(tz);
1051 return_VALUE(count);
1055 static int
1056 acpi_thermal_add_fs (
1057 struct acpi_device *device)
1059 struct proc_dir_entry *entry = NULL;
1061 ACPI_FUNCTION_TRACE("acpi_thermal_add_fs");
1063 if (!acpi_device_dir(device)) {
1064 acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
1065 acpi_thermal_dir);
1066 if (!acpi_device_dir(device))
1067 return_VALUE(-ENODEV);
1070 /* 'state' [R] */
1071 entry = create_proc_entry(ACPI_THERMAL_FILE_STATE,
1072 S_IRUGO, acpi_device_dir(device));
1073 if (!entry)
1074 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
1075 "Unable to create '%s' fs entry\n",
1076 ACPI_THERMAL_FILE_STATE));
1077 else {
1078 entry->read_proc = acpi_thermal_read_state;
1079 entry->data = acpi_driver_data(device);
1082 /* 'temperature' [R] */
1083 entry = create_proc_entry(ACPI_THERMAL_FILE_TEMPERATURE,
1084 S_IRUGO, acpi_device_dir(device));
1085 if (!entry)
1086 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
1087 "Unable to create '%s' fs entry\n",
1088 ACPI_THERMAL_FILE_TEMPERATURE));
1089 else {
1090 entry->read_proc = acpi_thermal_read_temperature;
1091 entry->data = acpi_driver_data(device);
1094 /* 'trip_points' [R/W] */
1095 entry = create_proc_entry(ACPI_THERMAL_FILE_TRIP_POINTS,
1096 S_IFREG|S_IRUGO|S_IWUSR, acpi_device_dir(device));
1097 if (!entry)
1098 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
1099 "Unable to create '%s' fs entry\n",
1100 ACPI_THERMAL_FILE_POLLING_FREQ));
1101 else {
1102 entry->read_proc = acpi_thermal_read_trip_points;
1103 entry->write_proc = acpi_thermal_write_trip_points;
1104 entry->data = acpi_driver_data(device);
1107 /* 'cooling_mode' [R/W] */
1108 entry = create_proc_entry(ACPI_THERMAL_FILE_COOLING_MODE,
1109 S_IFREG|S_IRUGO|S_IWUSR, acpi_device_dir(device));
1110 if (!entry)
1111 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
1112 "Unable to create '%s' fs entry\n",
1113 ACPI_THERMAL_FILE_COOLING_MODE));
1114 else {
1115 entry->read_proc = acpi_thermal_read_cooling_mode;
1116 entry->write_proc = acpi_thermal_write_cooling_mode;
1117 entry->data = acpi_driver_data(device);
1120 /* 'polling_frequency' [R/W] */
1121 entry = create_proc_entry(ACPI_THERMAL_FILE_POLLING_FREQ,
1122 S_IFREG|S_IRUGO|S_IWUSR, acpi_device_dir(device));
1123 if (!entry)
1124 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
1125 "Unable to create '%s' fs entry\n",
1126 ACPI_THERMAL_FILE_POLLING_FREQ));
1127 else {
1128 entry->read_proc = acpi_thermal_read_polling;
1129 entry->write_proc = acpi_thermal_write_polling;
1130 entry->data = acpi_driver_data(device);
1133 return_VALUE(0);
1137 static int
1138 acpi_thermal_remove_fs (
1139 struct acpi_device *device)
1141 ACPI_FUNCTION_TRACE("acpi_thermal_remove_fs");
1143 if (acpi_device_dir(device))
1144 remove_proc_entry(acpi_device_bid(device), acpi_thermal_dir);
1146 return_VALUE(0);
1150 /* --------------------------------------------------------------------------
1151 Driver Interface
1152 -------------------------------------------------------------------------- */
1154 static void
1155 acpi_thermal_notify (
1156 acpi_handle handle,
1157 u32 event,
1158 void *data)
1160 struct acpi_thermal *tz = (struct acpi_thermal *) data;
1161 struct acpi_device *device = NULL;
1163 ACPI_FUNCTION_TRACE("acpi_thermal_notify");
1165 if (!tz)
1166 return_VOID;
1168 if (acpi_bus_get_device(tz->handle, &device))
1169 return_VOID;
1171 switch (event) {
1172 case ACPI_THERMAL_NOTIFY_TEMPERATURE:
1173 acpi_thermal_check(tz);
1174 break;
1175 case ACPI_THERMAL_NOTIFY_THRESHOLDS:
1176 acpi_thermal_get_trip_points(tz);
1177 acpi_thermal_check(tz);
1178 acpi_bus_generate_event(device, event, 0);
1179 break;
1180 case ACPI_THERMAL_NOTIFY_DEVICES:
1181 if (tz->flags.devices)
1182 acpi_thermal_get_devices(tz);
1183 acpi_bus_generate_event(device, event, 0);
1184 break;
1185 default:
1186 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
1187 "Unsupported event [0x%x]\n", event));
1188 break;
1191 return_VOID;
1195 static int
1196 acpi_thermal_get_info (
1197 struct acpi_thermal *tz)
1199 int result = 0;
1201 ACPI_FUNCTION_TRACE("acpi_thermal_get_info");
1203 if (!tz)
1204 return_VALUE(-EINVAL);
1206 /* Get temperature [_TMP] (required) */
1207 result = acpi_thermal_get_temperature(tz);
1208 if (result)
1209 return_VALUE(result);
1211 /* Set the cooling mode [_SCP] to active cooling (default) */
1212 result = acpi_thermal_set_cooling_mode(tz, ACPI_THERMAL_MODE_ACTIVE);
1213 if (!result)
1214 tz->flags.cooling_mode = 1;
1216 /* Get trip points [_CRT, _PSV, etc.] (required) */
1217 result = acpi_thermal_get_trip_points(tz);
1218 if (result)
1219 return_VALUE(result);
1221 /* Get default polling frequency [_TZP] (optional) */
1222 if (tzp)
1223 tz->polling_frequency = tzp;
1224 else
1225 acpi_thermal_get_polling_frequency(tz);
1227 /* Get devices in this thermal zone [_TZD] (optional) */
1228 result = acpi_thermal_get_devices(tz);
1229 if (!result)
1230 tz->flags.devices = 1;
1232 return_VALUE(0);
1236 static int
1237 acpi_thermal_add (
1238 struct acpi_device *device)
1240 int result = 0;
1241 acpi_status status = AE_OK;
1242 struct acpi_thermal *tz = NULL;
1244 ACPI_FUNCTION_TRACE("acpi_thermal_add");
1246 if (!device)
1247 return_VALUE(-EINVAL);
1249 tz = kmalloc(sizeof(struct acpi_thermal), GFP_KERNEL);
1250 if (!tz)
1251 return_VALUE(-ENOMEM);
1252 memset(tz, 0, sizeof(struct acpi_thermal));
1254 tz->handle = device->handle;
1255 sprintf(tz->name, "%s", device->pnp.bus_id);
1256 sprintf(acpi_device_name(device), "%s", ACPI_THERMAL_DEVICE_NAME);
1257 sprintf(acpi_device_class(device), "%s", ACPI_THERMAL_CLASS);
1258 acpi_driver_data(device) = tz;
1260 result = acpi_thermal_get_info(tz);
1261 if (result)
1262 goto end;
1264 result = acpi_thermal_add_fs(device);
1265 if (result)
1266 return_VALUE(result);
1268 init_timer(&tz->timer);
1270 acpi_thermal_check(tz);
1272 status = acpi_install_notify_handler(tz->handle,
1273 ACPI_DEVICE_NOTIFY, acpi_thermal_notify, tz);
1274 if (ACPI_FAILURE(status)) {
1275 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
1276 "Error installing notify handler\n"));
1277 result = -ENODEV;
1278 goto end;
1281 printk(KERN_INFO PREFIX "%s [%s] (%ld C)\n",
1282 acpi_device_name(device), acpi_device_bid(device),
1283 KELVIN_TO_CELSIUS(tz->temperature));
1285 end:
1286 if (result) {
1287 acpi_thermal_remove_fs(device);
1288 kfree(tz);
1291 return_VALUE(result);
1295 static int
1296 acpi_thermal_remove (
1297 struct acpi_device *device,
1298 int type)
1300 acpi_status status = AE_OK;
1301 struct acpi_thermal *tz = NULL;
1303 ACPI_FUNCTION_TRACE("acpi_thermal_remove");
1305 if (!device || !acpi_driver_data(device))
1306 return_VALUE(-EINVAL);
1308 tz = (struct acpi_thermal *) acpi_driver_data(device);
1310 if (timer_pending(&(tz->timer)))
1311 del_timer(&(tz->timer));
1313 status = acpi_remove_notify_handler(tz->handle,
1314 ACPI_DEVICE_NOTIFY, acpi_thermal_notify);
1315 if (ACPI_FAILURE(status))
1316 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
1317 "Error removing notify handler\n"));
1319 /* Terminate policy */
1320 if (tz->trips.passive.flags.valid
1321 && tz->trips.passive.flags.enabled) {
1322 tz->trips.passive.flags.enabled = 0;
1323 acpi_thermal_passive(tz);
1325 if (tz->trips.active[0].flags.valid
1326 && tz->trips.active[0].flags.enabled) {
1327 tz->trips.active[0].flags.enabled = 0;
1328 acpi_thermal_active(tz);
1331 acpi_thermal_remove_fs(device);
1333 return_VALUE(0);
1337 static int __init
1338 acpi_thermal_init (void)
1340 int result = 0;
1342 ACPI_FUNCTION_TRACE("acpi_thermal_init");
1344 acpi_thermal_dir = proc_mkdir(ACPI_THERMAL_CLASS, acpi_root_dir);
1345 if (!acpi_thermal_dir)
1346 return_VALUE(-ENODEV);
1348 result = acpi_bus_register_driver(&acpi_thermal_driver);
1349 if (result < 0) {
1350 remove_proc_entry(ACPI_THERMAL_CLASS, acpi_root_dir);
1351 return_VALUE(-ENODEV);
1354 return_VALUE(0);
1358 static void __exit
1359 acpi_thermal_exit (void)
1361 ACPI_FUNCTION_TRACE("acpi_thermal_exit");
1363 acpi_bus_unregister_driver(&acpi_thermal_driver);
1365 remove_proc_entry(ACPI_THERMAL_CLASS, acpi_root_dir);
1367 return_VOID;
1371 module_init(acpi_thermal_init);
1372 module_exit(acpi_thermal_exit);