Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  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',(''+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 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);
1446 
  This page was automatically generated by the LXR engine.