Auto merge with /home/aegl/GIT/linus
[linux-2.6] / drivers / acpi / thermal.c
1 /*
2  *  acpi_thermal.c - ACPI Thermal Zone Driver ($Revision: 41 $)
3  *
4  *  Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
5  *  Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
6  *
7  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
8  *
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.
13  *
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.
18  *
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.
22  *
23  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
24  *
25  *  This driver fully implements the ACPI thermal policy as described in the
26  *  ACPI 2.0 Specification.
27  *
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.
31  *
32  */
33
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>
43
44 #include <acpi/acpi_bus.h>
45 #include <acpi/acpi_drivers.h>
46
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_CRITICAL      0xff
64 #define ACPI_THERMAL_PATH_POWEROFF      "/sbin/poweroff"
65
66 #define ACPI_THERMAL_MAX_ACTIVE 10
67 #define ACPI_THERMAL_MAX_LIMIT_STR_LEN 65
68
69 #define KELVIN_TO_CELSIUS(t)    (long)(((long)t-2732>=0) ? ((long)t-2732+5)/10 : ((long)t-2732-5)/10)
70 #define CELSIUS_TO_KELVIN(t)    ((t+273)*10)
71
72 #define _COMPONENT              ACPI_THERMAL_COMPONENT
73 ACPI_MODULE_NAME                ("acpi_thermal")
74
75 MODULE_AUTHOR("Paul Diefenbaugh");
76 MODULE_DESCRIPTION(ACPI_THERMAL_DRIVER_NAME);
77 MODULE_LICENSE("GPL");
78
79 static int tzp;
80 module_param(tzp, int, 0);
81 MODULE_PARM_DESC(tzp, "Thermal zone polling frequency, in 1/10 seconds.\n");
82
83
84 static int acpi_thermal_add (struct acpi_device *device);
85 static int acpi_thermal_remove (struct acpi_device *device, int type);
86 static int acpi_thermal_state_open_fs(struct inode *inode, struct file *file);
87 static int acpi_thermal_temp_open_fs(struct inode *inode, struct file *file);
88 static int acpi_thermal_trip_open_fs(struct inode *inode, struct file *file);
89 static ssize_t acpi_thermal_write_trip_points (struct file*,const char __user *,size_t,loff_t *);
90 static int acpi_thermal_cooling_open_fs(struct inode *inode, struct file *file);
91 static ssize_t acpi_thermal_write_cooling_mode (struct file*,const char __user *,size_t,loff_t *);
92 static int acpi_thermal_polling_open_fs(struct inode *inode, struct file *file);
93 static ssize_t acpi_thermal_write_polling(struct file*,const char __user *,size_t,loff_t *);
94
95 static struct acpi_driver acpi_thermal_driver = {
96         .name =         ACPI_THERMAL_DRIVER_NAME,
97         .class =        ACPI_THERMAL_CLASS,
98         .ids =          ACPI_THERMAL_HID,
99         .ops =          {
100                                 .add =          acpi_thermal_add,
101                                 .remove =       acpi_thermal_remove,
102                         },
103 };
104
105 struct acpi_thermal_state {
106         u8                      critical:1;
107         u8                      hot:1;
108         u8                      passive:1;
109         u8                      active:1;
110         u8                      reserved:4;
111         int                     active_index;
112 };
113
114 struct acpi_thermal_state_flags {
115         u8                      valid:1;
116         u8                      enabled:1;
117         u8                      reserved:6;
118 };
119
120 struct acpi_thermal_critical {
121         struct acpi_thermal_state_flags flags;
122         unsigned long           temperature;
123 };
124
125 struct acpi_thermal_hot {
126         struct acpi_thermal_state_flags flags;
127         unsigned long           temperature;
128 };
129
130 struct acpi_thermal_passive {
131         struct acpi_thermal_state_flags flags;
132         unsigned long           temperature;
133         unsigned long           tc1;
134         unsigned long           tc2;
135         unsigned long           tsp;
136         struct acpi_handle_list devices;
137 };
138
139 struct acpi_thermal_active {
140         struct acpi_thermal_state_flags flags;
141         unsigned long           temperature;
142         struct acpi_handle_list devices;
143 };
144
145 struct acpi_thermal_trips {
146         struct acpi_thermal_critical critical;
147         struct acpi_thermal_hot hot;
148         struct acpi_thermal_passive passive;
149         struct acpi_thermal_active active[ACPI_THERMAL_MAX_ACTIVE];
150 };
151
152 struct acpi_thermal_flags {
153         u8                      cooling_mode:1;         /* _SCP */
154         u8                      devices:1;              /* _TZD */
155         u8                      reserved:6;
156 };
157
158 struct acpi_thermal {
159         acpi_handle             handle;
160         acpi_bus_id             name;
161         unsigned long           temperature;
162         unsigned long           last_temperature;
163         unsigned long           polling_frequency;
164         u8                      cooling_mode;
165         volatile u8             zombie;
166         struct acpi_thermal_flags flags;
167         struct acpi_thermal_state state;
168         struct acpi_thermal_trips trips;
169         struct acpi_handle_list devices;
170         struct timer_list       timer;
171 };
172
173 static struct file_operations acpi_thermal_state_fops = {
174         .open           = acpi_thermal_state_open_fs,
175         .read           = seq_read,
176         .llseek         = seq_lseek,
177         .release        = single_release,
178 };
179
180 static struct file_operations acpi_thermal_temp_fops = {
181         .open           = acpi_thermal_temp_open_fs,
182         .read           = seq_read,
183         .llseek         = seq_lseek,
184         .release        = single_release,
185 };
186
187 static struct file_operations acpi_thermal_trip_fops = {
188         .open           = acpi_thermal_trip_open_fs,
189         .read           = seq_read,
190         .write          = acpi_thermal_write_trip_points,
191         .llseek         = seq_lseek,
192         .release        = single_release,
193 };
194
195 static struct file_operations acpi_thermal_cooling_fops = {
196         .open           = acpi_thermal_cooling_open_fs,
197         .read           = seq_read,
198         .write          = acpi_thermal_write_cooling_mode,
199         .llseek         = seq_lseek,
200         .release        = single_release,
201 };
202
203 static struct file_operations acpi_thermal_polling_fops = {
204         .open           = acpi_thermal_polling_open_fs,
205         .read           = seq_read,
206         .write          = acpi_thermal_write_polling,
207         .llseek         = seq_lseek,
208         .release        = single_release,
209 };
210
211 /* --------------------------------------------------------------------------
212                              Thermal Zone Management
213    -------------------------------------------------------------------------- */
214
215 static int
216 acpi_thermal_get_temperature (
217         struct acpi_thermal *tz)
218 {
219         acpi_status             status = AE_OK;
220
221         ACPI_FUNCTION_TRACE("acpi_thermal_get_temperature");
222
223         if (!tz)
224                 return_VALUE(-EINVAL);
225
226         tz->last_temperature = tz->temperature;
227
228         status = acpi_evaluate_integer(tz->handle, "_TMP", NULL, &tz->temperature);
229         if (ACPI_FAILURE(status))
230                 return_VALUE(-ENODEV);
231
232         ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Temperature is %lu dK\n", tz->temperature));
233
234         return_VALUE(0);
235 }
236
237
238 static int
239 acpi_thermal_get_polling_frequency (
240         struct acpi_thermal     *tz)
241 {
242         acpi_status             status = AE_OK;
243
244         ACPI_FUNCTION_TRACE("acpi_thermal_get_polling_frequency");
245
246         if (!tz)
247                 return_VALUE(-EINVAL);
248
249         status = acpi_evaluate_integer(tz->handle, "_TZP", NULL, &tz->polling_frequency);
250         if (ACPI_FAILURE(status))
251                 return_VALUE(-ENODEV);
252
253         ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Polling frequency is %lu dS\n", tz->polling_frequency));
254
255         return_VALUE(0);
256 }
257
258
259 static int
260 acpi_thermal_set_polling (
261         struct acpi_thermal     *tz,
262         int                     seconds)
263 {
264         ACPI_FUNCTION_TRACE("acpi_thermal_set_polling");
265
266         if (!tz)
267                 return_VALUE(-EINVAL);
268
269         tz->polling_frequency = seconds * 10;   /* Convert value to deci-seconds */
270
271         ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Polling frequency set to %lu seconds\n", tz->polling_frequency));
272
273         return_VALUE(0);
274 }
275
276
277 static int
278 acpi_thermal_set_cooling_mode (
279         struct acpi_thermal     *tz,
280         int                     mode)
281 {
282         acpi_status             status = AE_OK;
283         union acpi_object       arg0 = {ACPI_TYPE_INTEGER};
284         struct acpi_object_list arg_list = {1, &arg0};
285         acpi_handle             handle = NULL;
286
287         ACPI_FUNCTION_TRACE("acpi_thermal_set_cooling_mode");
288
289         if (!tz)
290                 return_VALUE(-EINVAL);
291
292         status = acpi_get_handle(tz->handle, "_SCP", &handle);
293         if (ACPI_FAILURE(status)) {
294                 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "_SCP not present\n"));
295                 return_VALUE(-ENODEV);
296         }
297
298         arg0.integer.value = mode;
299
300         status = acpi_evaluate_object(handle, NULL, &arg_list, NULL);
301         if (ACPI_FAILURE(status))
302                 return_VALUE(-ENODEV);
303
304         tz->cooling_mode = mode;
305
306         ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Cooling mode [%s]\n", 
307                 mode?"passive":"active"));
308
309         return_VALUE(0);
310 }
311
312
313 static int
314 acpi_thermal_get_trip_points (
315         struct acpi_thermal *tz)
316 {
317         acpi_status             status = AE_OK;
318         int                     i = 0;
319
320         ACPI_FUNCTION_TRACE("acpi_thermal_get_trip_points");
321
322         if (!tz)
323                 return_VALUE(-EINVAL);
324
325         /* Critical Shutdown (required) */
326
327         status = acpi_evaluate_integer(tz->handle, "_CRT", NULL, 
328                 &tz->trips.critical.temperature);
329         if (ACPI_FAILURE(status)) {
330                 tz->trips.critical.flags.valid = 0;
331                 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "No critical threshold\n"));
332                 return_VALUE(-ENODEV);
333         }
334         else {
335                 tz->trips.critical.flags.valid = 1;
336                 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found critical threshold [%lu]\n", tz->trips.critical.temperature));
337         }
338
339         /* Critical Sleep (optional) */
340
341         status = acpi_evaluate_integer(tz->handle, "_HOT", NULL, &tz->trips.hot.temperature);
342         if (ACPI_FAILURE(status)) {
343                 tz->trips.hot.flags.valid = 0;
344                 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No hot threshold\n"));
345         }
346         else {
347                 tz->trips.hot.flags.valid = 1;
348                 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found hot threshold [%lu]\n", tz->trips.hot.temperature));
349         }
350
351         /* Passive: Processors (optional) */
352
353         status = acpi_evaluate_integer(tz->handle, "_PSV", NULL, &tz->trips.passive.temperature);
354         if (ACPI_FAILURE(status)) {
355                 tz->trips.passive.flags.valid = 0;
356                 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No passive threshold\n"));
357         }
358         else {
359                 tz->trips.passive.flags.valid = 1;
360
361                 status = acpi_evaluate_integer(tz->handle, "_TC1", NULL, &tz->trips.passive.tc1);
362                 if (ACPI_FAILURE(status))
363                         tz->trips.passive.flags.valid = 0;
364
365                 status = acpi_evaluate_integer(tz->handle, "_TC2", NULL, &tz->trips.passive.tc2);
366                 if (ACPI_FAILURE(status))
367                         tz->trips.passive.flags.valid = 0;
368
369                 status = acpi_evaluate_integer(tz->handle, "_TSP", NULL, &tz->trips.passive.tsp);
370                 if (ACPI_FAILURE(status))
371                         tz->trips.passive.flags.valid = 0;
372
373                 status = acpi_evaluate_reference(tz->handle, "_PSL", NULL, &tz->trips.passive.devices);
374                 if (ACPI_FAILURE(status))
375                         tz->trips.passive.flags.valid = 0;
376
377                 if (!tz->trips.passive.flags.valid)
378                         ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Invalid passive threshold\n"));
379                 else
380                         ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found passive threshold [%lu]\n", tz->trips.passive.temperature));
381         }
382
383         /* Active: Fans, etc. (optional) */
384
385         for (i=0; i<ACPI_THERMAL_MAX_ACTIVE; i++) {
386
387                 char name[5] = {'_','A','C',('0'+i),'\0'};
388
389                 status = acpi_evaluate_integer(tz->handle, name, NULL, &tz->trips.active[i].temperature);
390                 if (ACPI_FAILURE(status))
391                         break;
392
393                 name[2] = 'L';
394                 status = acpi_evaluate_reference(tz->handle, name, NULL, &tz->trips.active[i].devices);
395                 if (ACPI_SUCCESS(status)) {
396                         tz->trips.active[i].flags.valid = 1;
397                         ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found active threshold [%d]:[%lu]\n", i, tz->trips.active[i].temperature));
398                 }
399                 else
400                         ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid active threshold [%d]\n", i));
401         }
402
403         return_VALUE(0);
404 }
405
406
407 static int
408 acpi_thermal_get_devices (
409         struct acpi_thermal     *tz)
410 {
411         acpi_status             status = AE_OK;
412
413         ACPI_FUNCTION_TRACE("acpi_thermal_get_devices");
414
415         if (!tz)
416                 return_VALUE(-EINVAL);
417
418         status = acpi_evaluate_reference(tz->handle, "_TZD", NULL, &tz->devices);
419         if (ACPI_FAILURE(status))
420                 return_VALUE(-ENODEV);
421
422         return_VALUE(0);
423 }
424
425
426 static int
427 acpi_thermal_call_usermode (
428         char                    *path)
429 {
430         char                    *argv[2] = {NULL, NULL};
431         char                    *envp[3] = {NULL, NULL, NULL};
432
433         ACPI_FUNCTION_TRACE("acpi_thermal_call_usermode");
434
435         if (!path)
436                 return_VALUE(-EINVAL);
437
438         argv[0] = path;
439
440         /* minimal command environment */
441         envp[0] = "HOME=/";
442         envp[1] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
443         
444         call_usermodehelper(argv[0], argv, envp, 0);
445
446         return_VALUE(0);
447 }
448
449
450 static int
451 acpi_thermal_critical (
452         struct acpi_thermal     *tz)
453 {
454         int                     result = 0;
455         struct acpi_device      *device = NULL;
456
457         ACPI_FUNCTION_TRACE("acpi_thermal_critical");
458
459         if (!tz || !tz->trips.critical.flags.valid)
460                 return_VALUE(-EINVAL);
461
462         if (tz->temperature >= tz->trips.critical.temperature) {
463                 ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Critical trip point\n"));
464                 tz->trips.critical.flags.enabled = 1;
465         }
466         else if (tz->trips.critical.flags.enabled)
467                 tz->trips.critical.flags.enabled = 0;
468
469         result = acpi_bus_get_device(tz->handle, &device);
470         if (result)
471                 return_VALUE(result);
472
473         printk(KERN_EMERG "Critical temperature reached (%ld C), shutting down.\n", KELVIN_TO_CELSIUS(tz->temperature));
474         acpi_bus_generate_event(device, ACPI_THERMAL_NOTIFY_CRITICAL, tz->trips.critical.flags.enabled);
475
476         acpi_thermal_call_usermode(ACPI_THERMAL_PATH_POWEROFF);
477
478         return_VALUE(0);
479 }
480
481
482 static int
483 acpi_thermal_hot (
484         struct acpi_thermal     *tz)
485 {
486         int                     result = 0;
487         struct acpi_device      *device = NULL;
488
489         ACPI_FUNCTION_TRACE("acpi_thermal_hot");
490
491         if (!tz || !tz->trips.hot.flags.valid)
492                 return_VALUE(-EINVAL);
493
494         if (tz->temperature >= tz->trips.hot.temperature) {
495                 ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Hot trip point\n"));
496                 tz->trips.hot.flags.enabled = 1;
497         }
498         else if (tz->trips.hot.flags.enabled)
499                 tz->trips.hot.flags.enabled = 0;
500
501         result = acpi_bus_get_device(tz->handle, &device);
502         if (result)
503                 return_VALUE(result);
504
505         acpi_bus_generate_event(device, ACPI_THERMAL_NOTIFY_HOT, tz->trips.hot.flags.enabled);
506
507         /* TBD: Call user-mode "sleep(S4)" function */
508
509         return_VALUE(0);
510 }
511
512
513 static int
514 acpi_thermal_passive (
515         struct acpi_thermal     *tz)
516 {
517         int                     result = 0;
518         struct acpi_thermal_passive *passive = NULL;
519         int                     trend = 0;
520         int                     i = 0;
521
522         ACPI_FUNCTION_TRACE("acpi_thermal_passive");
523
524         if (!tz || !tz->trips.passive.flags.valid)
525                 return_VALUE(-EINVAL);
526
527         passive = &(tz->trips.passive);
528
529         /*
530          * Above Trip?
531          * -----------
532          * Calculate the thermal trend (using the passive cooling equation)
533          * and modify the performance limit for all passive cooling devices
534          * accordingly.  Note that we assume symmetry.
535          */
536         if (tz->temperature >= passive->temperature) {
537                 trend = (passive->tc1 * (tz->temperature - tz->last_temperature)) + (passive->tc2 * (tz->temperature - passive->temperature));
538                 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 
539                         "trend[%d]=(tc1[%lu]*(tmp[%lu]-last[%lu]))+(tc2[%lu]*(tmp[%lu]-psv[%lu]))\n", 
540                         trend, passive->tc1, tz->temperature, 
541                         tz->last_temperature, passive->tc2, 
542                         tz->temperature, passive->temperature));
543                 tz->trips.passive.flags.enabled = 1;
544                 /* Heating up? */
545                 if (trend > 0)
546                         for (i=0; i<passive->devices.count; i++)
547                                 acpi_processor_set_thermal_limit(
548                                         passive->devices.handles[i], 
549                                         ACPI_PROCESSOR_LIMIT_INCREMENT);
550                 /* Cooling off? */
551                 else if (trend < 0)
552                         for (i=0; i<passive->devices.count; i++)
553                                 acpi_processor_set_thermal_limit(
554                                         passive->devices.handles[i], 
555                                         ACPI_PROCESSOR_LIMIT_DECREMENT);
556         }
557
558         /*
559          * Below Trip?
560          * -----------
561          * Implement passive cooling hysteresis to slowly increase performance
562          * and avoid thrashing around the passive trip point.  Note that we
563          * assume symmetry.
564          */
565         else if (tz->trips.passive.flags.enabled) {
566                 for (i=0; i<passive->devices.count; i++)
567                         result = acpi_processor_set_thermal_limit(
568                                 passive->devices.handles[i], 
569                                 ACPI_PROCESSOR_LIMIT_DECREMENT);
570                 if (result == 1) {
571                         tz->trips.passive.flags.enabled = 0;
572                         ACPI_DEBUG_PRINT((ACPI_DB_INFO, 
573                                 "Disabling passive cooling (zone is cool)\n"));
574                 }
575         }
576
577         return_VALUE(0);
578 }
579
580
581 static int
582 acpi_thermal_active (
583         struct acpi_thermal     *tz)
584 {
585         int                     result = 0;
586         struct acpi_thermal_active *active = NULL;
587         int                     i = 0;
588         int                     j = 0;
589         unsigned long           maxtemp = 0;
590
591         ACPI_FUNCTION_TRACE("acpi_thermal_active");
592
593         if (!tz)
594                 return_VALUE(-EINVAL);
595
596         for (i=0; i<ACPI_THERMAL_MAX_ACTIVE; i++) {
597
598                 active = &(tz->trips.active[i]);
599                 if (!active || !active->flags.valid)
600                         break;
601
602                 /*
603                  * Above Threshold?
604                  * ----------------
605                  * If not already enabled, turn ON all cooling devices
606                  * associated with this active threshold.
607                  */
608                 if (tz->temperature >= active->temperature) {
609                         if (active->temperature > maxtemp)
610                                 tz->state.active_index = i, maxtemp = active->temperature;
611                         if (!active->flags.enabled) {
612                                 for (j = 0; j < active->devices.count; j++) {
613                                         result = acpi_bus_set_power(active->devices.handles[j], ACPI_STATE_D0);
614                                         if (result) {
615                                                 ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Unable to turn cooling device [%p] 'on'\n", active->devices.handles[j]));
616                                                 continue;
617                                         }
618                                         active->flags.enabled = 1;
619                                         ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Cooling device [%p] now 'on'\n", active->devices.handles[j]));
620                                 }
621                         }
622                 }
623                 /*
624                  * Below Threshold?
625                  * ----------------
626                  * Turn OFF all cooling devices associated with this
627                  * threshold.
628                  */
629                 else if (active->flags.enabled) {
630                         for (j = 0; j < active->devices.count; j++) {
631                                 result = acpi_bus_set_power(active->devices.handles[j], ACPI_STATE_D3);
632                                 if (result) {
633                                         ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Unable to turn cooling device [%p] 'off'\n", active->devices.handles[j]));
634                                         continue;
635                                 }
636                                 active->flags.enabled = 0;
637                                 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Cooling device [%p] now 'off'\n", active->devices.handles[j]));
638                         }
639                 }
640         }
641
642         return_VALUE(0);
643 }
644
645
646 static void acpi_thermal_check (void *context);
647
648 static void
649 acpi_thermal_run (
650         unsigned long           data)
651 {
652         struct acpi_thermal *tz = (struct acpi_thermal *)data;
653         if (!tz->zombie)
654                 acpi_os_queue_for_execution(OSD_PRIORITY_GPE,  
655                         acpi_thermal_check, (void *) data);
656 }
657
658
659 static void
660 acpi_thermal_check (
661         void                    *data)
662 {
663         int                     result = 0;
664         struct acpi_thermal     *tz = (struct acpi_thermal *) data;
665         unsigned long           sleep_time = 0;
666         int                     i = 0;
667         struct acpi_thermal_state state;
668
669         ACPI_FUNCTION_TRACE("acpi_thermal_check");
670
671         if (!tz) {
672                 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid (NULL) context.\n"));
673                 return_VOID;
674         }
675
676         state = tz->state;
677
678         result = acpi_thermal_get_temperature(tz);
679         if (result)
680                 return_VOID;
681         
682         memset(&tz->state, 0, sizeof(tz->state));
683         
684         /*
685          * Check Trip Points
686          * -----------------
687          * Compare the current temperature to the trip point values to see
688          * if we've entered one of the thermal policy states.  Note that
689          * this function determines when a state is entered, but the 
690          * individual policy decides when it is exited (e.g. hysteresis).
691          */
692         if (tz->trips.critical.flags.valid)
693                 state.critical |= (tz->temperature >= tz->trips.critical.temperature);
694         if (tz->trips.hot.flags.valid)
695                 state.hot |= (tz->temperature >= tz->trips.hot.temperature);
696         if (tz->trips.passive.flags.valid)
697                 state.passive |= (tz->temperature >= tz->trips.passive.temperature);
698         for (i=0; i<ACPI_THERMAL_MAX_ACTIVE; i++)
699                 if (tz->trips.active[i].flags.valid)
700                         state.active |= (tz->temperature >= tz->trips.active[i].temperature);
701
702         /*
703          * Invoke Policy
704          * -------------
705          * Separated from the above check to allow individual policy to 
706          * determine when to exit a given state.
707          */
708         if (state.critical)
709                 acpi_thermal_critical(tz);
710         if (state.hot)
711                 acpi_thermal_hot(tz);
712         if (state.passive)
713                 acpi_thermal_passive(tz);
714         if (state.active)
715                 acpi_thermal_active(tz);
716
717         /*
718          * Calculate State
719          * ---------------
720          * Again, separated from the above two to allow independent policy
721          * decisions.
722          */
723         if (tz->trips.critical.flags.enabled)
724                 tz->state.critical = 1;
725         if (tz->trips.hot.flags.enabled)
726                 tz->state.hot = 1;
727         if (tz->trips.passive.flags.enabled)
728                 tz->state.passive = 1;
729         for (i=0; i<ACPI_THERMAL_MAX_ACTIVE; i++)
730                 if (tz->trips.active[i].flags.enabled)
731                         tz->state.active = 1;
732
733         /*
734          * Calculate Sleep Time
735          * --------------------
736          * If we're in the passive state, use _TSP's value.  Otherwise
737          * use the default polling frequency (e.g. _TZP).  If no polling
738          * frequency is specified then we'll wait forever (at least until
739          * a thermal event occurs).  Note that _TSP and _TZD values are
740          * given in 1/10th seconds (we must covert to milliseconds).
741          */
742         if (tz->state.passive)
743                 sleep_time = tz->trips.passive.tsp * 100;
744         else if (tz->polling_frequency > 0)
745                 sleep_time = tz->polling_frequency * 100;
746
747         ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%s: temperature[%lu] sleep[%lu]\n", 
748                 tz->name, tz->temperature, sleep_time));
749
750         /*
751          * Schedule Next Poll
752          * ------------------
753          */
754         if (!sleep_time) {
755                 if (timer_pending(&(tz->timer)))
756                         del_timer(&(tz->timer));
757         }
758         else {
759                 if (timer_pending(&(tz->timer)))
760                         mod_timer(&(tz->timer), (HZ * sleep_time) / 1000);
761                 else {
762                         tz->timer.data = (unsigned long) tz;
763                         tz->timer.function = acpi_thermal_run;
764                         tz->timer.expires = jiffies + (HZ * sleep_time) / 1000;
765                         add_timer(&(tz->timer));
766                 }
767         }
768
769         return_VOID;
770 }
771
772
773 /* --------------------------------------------------------------------------
774                               FS Interface (/proc)
775    -------------------------------------------------------------------------- */
776
777 static struct proc_dir_entry    *acpi_thermal_dir;
778
779 static int acpi_thermal_state_seq_show(struct seq_file *seq, void *offset)
780 {
781         struct acpi_thermal     *tz = (struct acpi_thermal *)seq->private;
782
783         ACPI_FUNCTION_TRACE("acpi_thermal_state_seq_show");
784
785         if (!tz)
786                 goto end;
787
788         seq_puts(seq, "state:                   ");
789
790         if (!tz->state.critical && !tz->state.hot && !tz->state.passive && !tz->state.active)
791                 seq_puts(seq, "ok\n");
792         else {
793                 if (tz->state.critical)
794                         seq_puts(seq, "critical ");
795                 if (tz->state.hot)
796                         seq_puts(seq, "hot ");
797                 if (tz->state.passive)
798                         seq_puts(seq, "passive ");
799                 if (tz->state.active)
800                         seq_printf(seq, "active[%d]", tz->state.active_index);
801                 seq_puts(seq, "\n");
802         }
803
804 end:
805         return_VALUE(0);
806 }
807
808 static int acpi_thermal_state_open_fs(struct inode *inode, struct file *file)
809 {
810         return single_open(file, acpi_thermal_state_seq_show, PDE(inode)->data);
811 }
812
813
814 static int acpi_thermal_temp_seq_show(struct seq_file *seq, void *offset)
815 {
816         int                     result = 0;
817         struct acpi_thermal     *tz = (struct acpi_thermal *)seq->private;
818
819         ACPI_FUNCTION_TRACE("acpi_thermal_temp_seq_show");
820
821         if (!tz)
822                 goto end;
823
824         result = acpi_thermal_get_temperature(tz);
825         if (result)
826                 goto end;
827
828         seq_printf(seq, "temperature:             %ld C\n", 
829                 KELVIN_TO_CELSIUS(tz->temperature));
830
831 end:
832         return_VALUE(0);
833 }
834
835 static int acpi_thermal_temp_open_fs(struct inode *inode, struct file *file)
836 {
837         return single_open(file, acpi_thermal_temp_seq_show, PDE(inode)->data);
838 }
839
840
841 static int acpi_thermal_trip_seq_show(struct seq_file *seq, void *offset)
842 {
843         struct acpi_thermal     *tz = (struct acpi_thermal *)seq->private;
844         int                     i = 0;
845         int                     j = 0;
846
847         ACPI_FUNCTION_TRACE("acpi_thermal_trip_seq_show");
848
849         if (!tz)
850                 goto end;
851
852         if (tz->trips.critical.flags.valid)
853                 seq_printf(seq, "critical (S5):           %ld C\n",
854                         KELVIN_TO_CELSIUS(tz->trips.critical.temperature));
855
856         if (tz->trips.hot.flags.valid)
857                 seq_printf(seq, "hot (S4):                %ld C\n",
858                         KELVIN_TO_CELSIUS(tz->trips.hot.temperature));
859
860         if (tz->trips.passive.flags.valid) {
861                 seq_printf(seq, "passive:                 %ld C: tc1=%lu tc2=%lu tsp=%lu devices=",
862                         KELVIN_TO_CELSIUS(tz->trips.passive.temperature),
863                         tz->trips.passive.tc1,
864                         tz->trips.passive.tc2, 
865                         tz->trips.passive.tsp);
866                 for (j=0; j<tz->trips.passive.devices.count; j++) {
867
868                         seq_printf(seq, "0x%p ", tz->trips.passive.devices.handles[j]);
869                 }
870                 seq_puts(seq, "\n");
871         }
872
873         for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
874                 if (!(tz->trips.active[i].flags.valid))
875                         break;
876                 seq_printf(seq, "active[%d]:               %ld C: devices=",
877                         i, KELVIN_TO_CELSIUS(tz->trips.active[i].temperature));
878                 for (j = 0; j < tz->trips.active[i].devices.count; j++) 
879                         seq_printf(seq, "0x%p ",
880                                 tz->trips.active[i].devices.handles[j]);
881                 seq_puts(seq, "\n");
882         }
883
884 end:
885         return_VALUE(0);
886 }
887
888 static int acpi_thermal_trip_open_fs(struct inode *inode, struct file *file)
889 {
890         return single_open(file, acpi_thermal_trip_seq_show, PDE(inode)->data);
891 }
892
893 static ssize_t
894 acpi_thermal_write_trip_points (
895         struct file             *file,
896         const char              __user *buffer,
897         size_t                  count,
898         loff_t                  *ppos)
899 {
900         struct seq_file         *m = (struct seq_file *)file->private_data;
901         struct acpi_thermal     *tz = (struct acpi_thermal *)m->private;
902
903         char                    *limit_string; 
904         int                     num, critical, hot, passive;
905         int                     *active; 
906         int                     i = 0;
907
908         ACPI_FUNCTION_TRACE("acpi_thermal_write_trip_points");
909
910         limit_string = kmalloc(ACPI_THERMAL_MAX_LIMIT_STR_LEN, GFP_KERNEL);
911         if(!limit_string)
912                 return_VALUE(-ENOMEM);
913
914         memset(limit_string, 0, ACPI_THERMAL_MAX_LIMIT_STR_LEN);
915
916         active = kmalloc(ACPI_THERMAL_MAX_ACTIVE *sizeof(int), GFP_KERNEL);
917         if(!active)
918                 return_VALUE(-ENOMEM);
919
920         if (!tz || (count > ACPI_THERMAL_MAX_LIMIT_STR_LEN - 1)) {
921                 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid argument\n"));
922                 count = -EINVAL;
923                 goto end;
924         }
925         
926         if (copy_from_user(limit_string, buffer, count)) {
927                 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid data\n"));
928                 count = -EFAULT;
929                 goto end;
930         }
931         
932         limit_string[count] = '\0';
933
934         num = sscanf(limit_string, "%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d",
935                                 &critical, &hot, &passive,
936                                 &active[0], &active[1], &active[2], &active[3], &active[4],
937                                 &active[5], &active[6], &active[7], &active[8], &active[9]);
938         if(!(num >=5 && num < (ACPI_THERMAL_MAX_ACTIVE + 3))) {
939                 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid data format\n"));
940                 count = -EINVAL;
941                 goto end;
942         }
943
944         tz->trips.critical.temperature = CELSIUS_TO_KELVIN(critical);
945         tz->trips.hot.temperature = CELSIUS_TO_KELVIN(hot);
946         tz->trips.passive.temperature = CELSIUS_TO_KELVIN(passive);
947         for (i = 0; i < num - 3; i++) {
948                 if (!(tz->trips.active[i].flags.valid))
949                         break;
950                 tz->trips.active[i].temperature = CELSIUS_TO_KELVIN(active[i]);
951         }
952         
953 end:
954         kfree(active);
955         kfree(limit_string);
956         return_VALUE(count);
957 }
958
959
960 static int acpi_thermal_cooling_seq_show(struct seq_file *seq, void *offset)
961 {
962         struct acpi_thermal     *tz = (struct acpi_thermal *)seq->private;
963
964         ACPI_FUNCTION_TRACE("acpi_thermal_cooling_seq_show");
965
966         if (!tz)
967                 goto end;
968
969         if (!tz->flags.cooling_mode) {
970                 seq_puts(seq, "<setting not supported>\n");
971         }
972
973         if ( tz->cooling_mode == ACPI_THERMAL_MODE_CRITICAL )
974                 seq_printf(seq, "cooling mode:  critical\n");
975         else
976                 seq_printf(seq, "cooling mode:  %s\n",
977                         tz->cooling_mode?"passive":"active");
978
979 end:
980         return_VALUE(0);
981 }
982
983 static int acpi_thermal_cooling_open_fs(struct inode *inode, struct file *file)
984 {
985         return single_open(file, acpi_thermal_cooling_seq_show,
986                                                         PDE(inode)->data);
987 }
988
989 static ssize_t
990 acpi_thermal_write_cooling_mode (
991         struct file             *file,
992         const char              __user *buffer,
993         size_t                  count,
994         loff_t                  *ppos)
995 {
996         struct seq_file         *m = (struct seq_file *)file->private_data;
997         struct acpi_thermal     *tz = (struct acpi_thermal *)m->private;
998         int                     result = 0;
999         char                    mode_string[12] = {'\0'};
1000
1001         ACPI_FUNCTION_TRACE("acpi_thermal_write_cooling_mode");
1002
1003         if (!tz || (count > sizeof(mode_string) - 1))
1004                 return_VALUE(-EINVAL);
1005
1006         if (!tz->flags.cooling_mode)
1007                 return_VALUE(-ENODEV);
1008
1009         if (copy_from_user(mode_string, buffer, count))
1010                 return_VALUE(-EFAULT);
1011         
1012         mode_string[count] = '\0';
1013         
1014         result = acpi_thermal_set_cooling_mode(tz, 
1015                 simple_strtoul(mode_string, NULL, 0));
1016         if (result)
1017                 return_VALUE(result);
1018
1019         acpi_thermal_check(tz);
1020
1021         return_VALUE(count);
1022 }
1023
1024
1025 static int acpi_thermal_polling_seq_show(struct seq_file *seq, void *offset)
1026 {
1027         struct acpi_thermal     *tz = (struct acpi_thermal *)seq->private;
1028
1029         ACPI_FUNCTION_TRACE("acpi_thermal_polling_seq_show");
1030
1031         if (!tz)
1032                 goto end;
1033
1034         if (!tz->polling_frequency) {
1035                 seq_puts(seq, "<polling disabled>\n");
1036                 goto end;
1037         }
1038
1039         seq_printf(seq, "polling frequency:       %lu seconds\n",
1040                 (tz->polling_frequency / 10));
1041
1042 end:
1043         return_VALUE(0);
1044 }
1045
1046 static int acpi_thermal_polling_open_fs(struct inode *inode, struct file *file)
1047 {
1048         return single_open(file, acpi_thermal_polling_seq_show,
1049                                                         PDE(inode)->data);
1050 }
1051
1052 static ssize_t
1053 acpi_thermal_write_polling (
1054         struct file             *file,
1055         const char              __user *buffer,
1056         size_t                  count,
1057         loff_t                  *ppos)
1058 {
1059         struct seq_file         *m = (struct seq_file *)file->private_data;
1060         struct acpi_thermal     *tz = (struct acpi_thermal *)m->private;
1061         int                     result = 0;
1062         char                    polling_string[12] = {'\0'};
1063         int                     seconds = 0;
1064
1065         ACPI_FUNCTION_TRACE("acpi_thermal_write_polling");
1066
1067         if (!tz || (count > sizeof(polling_string) - 1))
1068                 return_VALUE(-EINVAL);
1069         
1070         if (copy_from_user(polling_string, buffer, count))
1071                 return_VALUE(-EFAULT);
1072         
1073         polling_string[count] = '\0';
1074
1075         seconds = simple_strtoul(polling_string, NULL, 0);
1076         
1077         result = acpi_thermal_set_polling(tz, seconds);
1078         if (result)
1079                 return_VALUE(result);
1080
1081         acpi_thermal_check(tz);
1082
1083         return_VALUE(count);
1084 }
1085
1086
1087 static int
1088 acpi_thermal_add_fs (
1089         struct acpi_device      *device)
1090 {
1091         struct proc_dir_entry   *entry = NULL;
1092
1093         ACPI_FUNCTION_TRACE("acpi_thermal_add_fs");
1094
1095         if (!acpi_device_dir(device)) {
1096                 acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
1097                         acpi_thermal_dir);
1098                 if (!acpi_device_dir(device))
1099                         return_VALUE(-ENODEV);
1100                 acpi_device_dir(device)->owner = THIS_MODULE;
1101         }
1102
1103         /* 'state' [R] */
1104         entry = create_proc_entry(ACPI_THERMAL_FILE_STATE,
1105                 S_IRUGO, acpi_device_dir(device));
1106         if (!entry)
1107                 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
1108                         "Unable to create '%s' fs entry\n",
1109                         ACPI_THERMAL_FILE_STATE));
1110         else {
1111                 entry->proc_fops = &acpi_thermal_state_fops;
1112                 entry->data = acpi_driver_data(device);
1113                 entry->owner = THIS_MODULE;
1114         }
1115
1116         /* 'temperature' [R] */
1117         entry = create_proc_entry(ACPI_THERMAL_FILE_TEMPERATURE,
1118                 S_IRUGO, acpi_device_dir(device));
1119         if (!entry)
1120                 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
1121                         "Unable to create '%s' fs entry\n",
1122                         ACPI_THERMAL_FILE_TEMPERATURE));
1123         else {
1124                 entry->proc_fops = &acpi_thermal_temp_fops;
1125                 entry->data = acpi_driver_data(device);
1126                 entry->owner = THIS_MODULE;
1127         }
1128
1129         /* 'trip_points' [R/W] */
1130         entry = create_proc_entry(ACPI_THERMAL_FILE_TRIP_POINTS,
1131                 S_IFREG|S_IRUGO|S_IWUSR, acpi_device_dir(device));
1132         if (!entry)
1133                 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
1134                         "Unable to create '%s' fs entry\n",
1135                         ACPI_THERMAL_FILE_TRIP_POINTS));
1136         else {
1137                 entry->proc_fops = &acpi_thermal_trip_fops;
1138                 entry->data = acpi_driver_data(device);
1139                 entry->owner = THIS_MODULE;
1140         }
1141
1142         /* 'cooling_mode' [R/W] */
1143         entry = create_proc_entry(ACPI_THERMAL_FILE_COOLING_MODE,
1144                 S_IFREG|S_IRUGO|S_IWUSR, acpi_device_dir(device));
1145         if (!entry)
1146                 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
1147                         "Unable to create '%s' fs entry\n",
1148                         ACPI_THERMAL_FILE_COOLING_MODE));
1149         else {
1150                 entry->proc_fops = &acpi_thermal_cooling_fops;
1151                 entry->data = acpi_driver_data(device);
1152                 entry->owner = THIS_MODULE;
1153         }
1154
1155         /* 'polling_frequency' [R/W] */
1156         entry = create_proc_entry(ACPI_THERMAL_FILE_POLLING_FREQ,
1157                 S_IFREG|S_IRUGO|S_IWUSR, acpi_device_dir(device));
1158         if (!entry)
1159                 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
1160                         "Unable to create '%s' fs entry\n",
1161                         ACPI_THERMAL_FILE_POLLING_FREQ));
1162         else {
1163                 entry->proc_fops = &acpi_thermal_polling_fops;
1164                 entry->data = acpi_driver_data(device);
1165                 entry->owner = THIS_MODULE;
1166         }
1167
1168         return_VALUE(0);
1169 }
1170
1171
1172 static int
1173 acpi_thermal_remove_fs (
1174         struct acpi_device      *device)
1175 {
1176         ACPI_FUNCTION_TRACE("acpi_thermal_remove_fs");
1177
1178         if (acpi_device_dir(device)) {
1179                 remove_proc_entry(ACPI_THERMAL_FILE_POLLING_FREQ,
1180                                   acpi_device_dir(device));
1181                 remove_proc_entry(ACPI_THERMAL_FILE_COOLING_MODE,
1182                                   acpi_device_dir(device));
1183                 remove_proc_entry(ACPI_THERMAL_FILE_TRIP_POINTS,
1184                                   acpi_device_dir(device));
1185                 remove_proc_entry(ACPI_THERMAL_FILE_TEMPERATURE,
1186                                   acpi_device_dir(device));
1187                 remove_proc_entry(ACPI_THERMAL_FILE_STATE,
1188                                   acpi_device_dir(device));
1189                 remove_proc_entry(acpi_device_bid(device), acpi_thermal_dir);
1190                 acpi_device_dir(device) = NULL;
1191         }
1192
1193         return_VALUE(0);
1194 }
1195
1196
1197 /* --------------------------------------------------------------------------
1198                                  Driver Interface
1199    -------------------------------------------------------------------------- */
1200
1201 static void
1202 acpi_thermal_notify (
1203         acpi_handle             handle,
1204         u32                     event,
1205         void                    *data)
1206 {
1207         struct acpi_thermal     *tz = (struct acpi_thermal *) data;
1208         struct acpi_device      *device = NULL;
1209
1210         ACPI_FUNCTION_TRACE("acpi_thermal_notify");
1211
1212         if (!tz)
1213                 return_VOID;
1214
1215         if (acpi_bus_get_device(tz->handle, &device))
1216                 return_VOID;
1217
1218         switch (event) {
1219         case ACPI_THERMAL_NOTIFY_TEMPERATURE:
1220                 acpi_thermal_check(tz);
1221                 break;
1222         case ACPI_THERMAL_NOTIFY_THRESHOLDS:
1223                 acpi_thermal_get_trip_points(tz);
1224                 acpi_thermal_check(tz);
1225                 acpi_bus_generate_event(device, event, 0);
1226                 break;
1227         case ACPI_THERMAL_NOTIFY_DEVICES:
1228                 if (tz->flags.devices)
1229                         acpi_thermal_get_devices(tz);
1230                 acpi_bus_generate_event(device, event, 0);
1231                 break;
1232         default:
1233                 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
1234                         "Unsupported event [0x%x]\n", event));
1235                 break;
1236         }
1237
1238         return_VOID;
1239 }
1240
1241
1242 static int
1243 acpi_thermal_get_info (
1244         struct acpi_thermal     *tz)
1245 {
1246         int                     result = 0;
1247
1248         ACPI_FUNCTION_TRACE("acpi_thermal_get_info");
1249
1250         if (!tz)
1251                 return_VALUE(-EINVAL);
1252
1253         /* Get temperature [_TMP] (required) */
1254         result = acpi_thermal_get_temperature(tz);
1255         if (result)
1256                 return_VALUE(result);
1257
1258         /* Get trip points [_CRT, _PSV, etc.] (required) */
1259         result = acpi_thermal_get_trip_points(tz);
1260         if (result)
1261                 return_VALUE(result);
1262
1263         /* Set the cooling mode [_SCP] to active cooling (default) */
1264         result = acpi_thermal_set_cooling_mode(tz, ACPI_THERMAL_MODE_ACTIVE);
1265         if (!result) 
1266                 tz->flags.cooling_mode = 1;
1267         else { 
1268                 /* Oh,we have not _SCP method.
1269                    Generally show cooling_mode by _ACx, _PSV,spec 12.2*/
1270                 tz->flags.cooling_mode = 0;
1271                 if ( tz->trips.active[0].flags.valid && tz->trips.passive.flags.valid ) {
1272                         if ( tz->trips.passive.temperature > tz->trips.active[0].temperature )
1273                                 tz->cooling_mode = ACPI_THERMAL_MODE_ACTIVE;
1274                         else 
1275                                 tz->cooling_mode = ACPI_THERMAL_MODE_PASSIVE;
1276                 } else if ( !tz->trips.active[0].flags.valid && tz->trips.passive.flags.valid ) {
1277                         tz->cooling_mode = ACPI_THERMAL_MODE_PASSIVE;
1278                 } else if ( tz->trips.active[0].flags.valid && !tz->trips.passive.flags.valid ) {
1279                         tz->cooling_mode = ACPI_THERMAL_MODE_ACTIVE;
1280                 } else {
1281                         /* _ACx and _PSV are optional, but _CRT is required */
1282                         tz->cooling_mode = ACPI_THERMAL_MODE_CRITICAL;
1283                 }
1284         }
1285
1286         /* Get default polling frequency [_TZP] (optional) */
1287         if (tzp)
1288                 tz->polling_frequency = tzp;
1289         else
1290                 acpi_thermal_get_polling_frequency(tz);
1291
1292         /* Get devices in this thermal zone [_TZD] (optional) */
1293         result = acpi_thermal_get_devices(tz);
1294         if (!result)
1295                 tz->flags.devices = 1;
1296
1297         return_VALUE(0);
1298 }
1299
1300
1301 static int
1302 acpi_thermal_add (
1303         struct acpi_device              *device)
1304 {
1305         int                     result = 0;
1306         acpi_status             status = AE_OK;
1307         struct acpi_thermal     *tz = NULL;
1308
1309         ACPI_FUNCTION_TRACE("acpi_thermal_add");
1310
1311         if (!device)
1312                 return_VALUE(-EINVAL);
1313
1314         tz = kmalloc(sizeof(struct acpi_thermal), GFP_KERNEL);
1315         if (!tz)
1316                 return_VALUE(-ENOMEM);
1317         memset(tz, 0, sizeof(struct acpi_thermal));
1318
1319         tz->handle = device->handle;
1320         strcpy(tz->name, device->pnp.bus_id);
1321         strcpy(acpi_device_name(device), ACPI_THERMAL_DEVICE_NAME);
1322         strcpy(acpi_device_class(device), ACPI_THERMAL_CLASS);
1323         acpi_driver_data(device) = tz;
1324
1325         result = acpi_thermal_get_info(tz);
1326         if (result)
1327                 goto end;
1328
1329         result = acpi_thermal_add_fs(device);
1330         if (result)
1331                 return_VALUE(result);
1332
1333         init_timer(&tz->timer);
1334
1335         acpi_thermal_check(tz);
1336
1337         status = acpi_install_notify_handler(tz->handle,
1338                 ACPI_DEVICE_NOTIFY, acpi_thermal_notify, tz);
1339         if (ACPI_FAILURE(status)) {
1340                 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
1341                         "Error installing notify handler\n"));
1342                 result = -ENODEV;
1343                 goto end;
1344         }
1345
1346         printk(KERN_INFO PREFIX "%s [%s] (%ld C)\n",
1347                 acpi_device_name(device), acpi_device_bid(device),
1348                 KELVIN_TO_CELSIUS(tz->temperature));
1349
1350 end:
1351         if (result) {
1352                 acpi_thermal_remove_fs(device);
1353                 kfree(tz);
1354         }
1355
1356         return_VALUE(result);
1357 }
1358
1359
1360 static int
1361 acpi_thermal_remove (
1362         struct acpi_device      *device,
1363         int                     type)
1364 {
1365         acpi_status             status = AE_OK;
1366         struct acpi_thermal     *tz = NULL;
1367
1368         ACPI_FUNCTION_TRACE("acpi_thermal_remove");
1369
1370         if (!device || !acpi_driver_data(device))
1371                 return_VALUE(-EINVAL);
1372
1373         tz = (struct acpi_thermal *) acpi_driver_data(device);
1374
1375         /* avoid timer adding new defer task */
1376         tz->zombie = 1;
1377         /* wait for running timer (on other CPUs) finish */
1378         del_timer_sync(&(tz->timer));
1379         /* synchronize deferred task */
1380         acpi_os_wait_events_complete(NULL);
1381         /* deferred task may reinsert timer */
1382         del_timer_sync(&(tz->timer));
1383
1384         status = acpi_remove_notify_handler(tz->handle,
1385                 ACPI_DEVICE_NOTIFY, acpi_thermal_notify);
1386         if (ACPI_FAILURE(status))
1387                 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
1388                         "Error removing notify handler\n"));
1389
1390         /* Terminate policy */
1391         if (tz->trips.passive.flags.valid
1392                 && tz->trips.passive.flags.enabled) {
1393                 tz->trips.passive.flags.enabled = 0;
1394                 acpi_thermal_passive(tz);
1395         }
1396         if (tz->trips.active[0].flags.valid
1397                 && tz->trips.active[0].flags.enabled) {
1398                 tz->trips.active[0].flags.enabled = 0;
1399                 acpi_thermal_active(tz);
1400         }
1401
1402         acpi_thermal_remove_fs(device);
1403
1404         kfree(tz);
1405         return_VALUE(0);
1406 }
1407
1408
1409 static int __init
1410 acpi_thermal_init (void)
1411 {
1412         int                     result = 0;
1413
1414         ACPI_FUNCTION_TRACE("acpi_thermal_init");
1415
1416         acpi_thermal_dir = proc_mkdir(ACPI_THERMAL_CLASS, acpi_root_dir);
1417         if (!acpi_thermal_dir)
1418                 return_VALUE(-ENODEV);
1419         acpi_thermal_dir->owner = THIS_MODULE;
1420
1421         result = acpi_bus_register_driver(&acpi_thermal_driver);
1422         if (result < 0) {
1423                 remove_proc_entry(ACPI_THERMAL_CLASS, acpi_root_dir);
1424                 return_VALUE(-ENODEV);
1425         }
1426
1427         return_VALUE(0);
1428 }
1429
1430
1431 static void __exit
1432 acpi_thermal_exit (void)
1433 {
1434         ACPI_FUNCTION_TRACE("acpi_thermal_exit");
1435
1436         acpi_bus_unregister_driver(&acpi_thermal_driver);
1437
1438         remove_proc_entry(ACPI_THERMAL_CLASS, acpi_root_dir);
1439
1440         return_VOID;
1441 }
1442
1443
1444 module_init(acpi_thermal_init);
1445 module_exit(acpi_thermal_exit);