Merge branch 'bugzilla-12249' into release
[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/dmi.h>
37 #include <linux/init.h>
38 #include <linux/types.h>
39 #include <linux/proc_fs.h>
40 #include <linux/jiffies.h>
41 #include <linux/kmod.h>
42 #include <linux/seq_file.h>
43 #include <linux/reboot.h>
44 #include <linux/device.h>
45 #include <asm/uaccess.h>
46 #include <linux/thermal.h>
47 #include <acpi/acpi_bus.h>
48 #include <acpi/acpi_drivers.h>
49
50 #define ACPI_THERMAL_CLASS              "thermal_zone"
51 #define ACPI_THERMAL_DEVICE_NAME        "Thermal Zone"
52 #define ACPI_THERMAL_FILE_STATE         "state"
53 #define ACPI_THERMAL_FILE_TEMPERATURE   "temperature"
54 #define ACPI_THERMAL_FILE_TRIP_POINTS   "trip_points"
55 #define ACPI_THERMAL_FILE_COOLING_MODE  "cooling_mode"
56 #define ACPI_THERMAL_FILE_POLLING_FREQ  "polling_frequency"
57 #define ACPI_THERMAL_NOTIFY_TEMPERATURE 0x80
58 #define ACPI_THERMAL_NOTIFY_THRESHOLDS  0x81
59 #define ACPI_THERMAL_NOTIFY_DEVICES     0x82
60 #define ACPI_THERMAL_NOTIFY_CRITICAL    0xF0
61 #define ACPI_THERMAL_NOTIFY_HOT         0xF1
62 #define ACPI_THERMAL_MODE_ACTIVE        0x00
63
64 #define ACPI_THERMAL_MAX_ACTIVE 10
65 #define ACPI_THERMAL_MAX_LIMIT_STR_LEN 65
66
67 #define _COMPONENT              ACPI_THERMAL_COMPONENT
68 ACPI_MODULE_NAME("thermal");
69
70 MODULE_AUTHOR("Paul Diefenbaugh");
71 MODULE_DESCRIPTION("ACPI Thermal Zone Driver");
72 MODULE_LICENSE("GPL");
73
74 static int act;
75 module_param(act, int, 0644);
76 MODULE_PARM_DESC(act, "Disable or override all lowest active trip points.");
77
78 static int crt;
79 module_param(crt, int, 0644);
80 MODULE_PARM_DESC(crt, "Disable or lower all critical trip points.");
81
82 static int tzp;
83 module_param(tzp, int, 0444);
84 MODULE_PARM_DESC(tzp, "Thermal zone polling frequency, in 1/10 seconds.");
85
86 static int nocrt;
87 module_param(nocrt, int, 0);
88 MODULE_PARM_DESC(nocrt, "Set to take no action upon ACPI thermal zone critical trips points.");
89
90 static int off;
91 module_param(off, int, 0);
92 MODULE_PARM_DESC(off, "Set to disable ACPI thermal support.");
93
94 static int psv;
95 module_param(psv, int, 0644);
96 MODULE_PARM_DESC(psv, "Disable or override all passive trip points.");
97
98 static int acpi_thermal_add(struct acpi_device *device);
99 static int acpi_thermal_remove(struct acpi_device *device, int type);
100 static int acpi_thermal_resume(struct acpi_device *device);
101 static void acpi_thermal_notify(struct acpi_device *device, u32 event);
102 static int acpi_thermal_state_open_fs(struct inode *inode, struct file *file);
103 static int acpi_thermal_temp_open_fs(struct inode *inode, struct file *file);
104 static int acpi_thermal_trip_open_fs(struct inode *inode, struct file *file);
105 static int acpi_thermal_cooling_open_fs(struct inode *inode, struct file *file);
106 static ssize_t acpi_thermal_write_cooling_mode(struct file *,
107                                                const char __user *, size_t,
108                                                loff_t *);
109 static int acpi_thermal_polling_open_fs(struct inode *inode, struct file *file);
110 static ssize_t acpi_thermal_write_polling(struct file *, const char __user *,
111                                           size_t, loff_t *);
112
113 static const struct acpi_device_id  thermal_device_ids[] = {
114         {ACPI_THERMAL_HID, 0},
115         {"", 0},
116 };
117 MODULE_DEVICE_TABLE(acpi, thermal_device_ids);
118
119 static struct acpi_driver acpi_thermal_driver = {
120         .name = "thermal",
121         .class = ACPI_THERMAL_CLASS,
122         .ids = thermal_device_ids,
123         .ops = {
124                 .add = acpi_thermal_add,
125                 .remove = acpi_thermal_remove,
126                 .resume = acpi_thermal_resume,
127                 .notify = acpi_thermal_notify,
128                 },
129 };
130
131 struct acpi_thermal_state {
132         u8 critical:1;
133         u8 hot:1;
134         u8 passive:1;
135         u8 active:1;
136         u8 reserved:4;
137         int active_index;
138 };
139
140 struct acpi_thermal_state_flags {
141         u8 valid:1;
142         u8 enabled:1;
143         u8 reserved:6;
144 };
145
146 struct acpi_thermal_critical {
147         struct acpi_thermal_state_flags flags;
148         unsigned long temperature;
149 };
150
151 struct acpi_thermal_hot {
152         struct acpi_thermal_state_flags flags;
153         unsigned long temperature;
154 };
155
156 struct acpi_thermal_passive {
157         struct acpi_thermal_state_flags flags;
158         unsigned long temperature;
159         unsigned long tc1;
160         unsigned long tc2;
161         unsigned long tsp;
162         struct acpi_handle_list devices;
163 };
164
165 struct acpi_thermal_active {
166         struct acpi_thermal_state_flags flags;
167         unsigned long temperature;
168         struct acpi_handle_list devices;
169 };
170
171 struct acpi_thermal_trips {
172         struct acpi_thermal_critical critical;
173         struct acpi_thermal_hot hot;
174         struct acpi_thermal_passive passive;
175         struct acpi_thermal_active active[ACPI_THERMAL_MAX_ACTIVE];
176 };
177
178 struct acpi_thermal_flags {
179         u8 cooling_mode:1;      /* _SCP */
180         u8 devices:1;           /* _TZD */
181         u8 reserved:6;
182 };
183
184 struct acpi_thermal {
185         struct acpi_device * device;
186         acpi_bus_id name;
187         unsigned long temperature;
188         unsigned long last_temperature;
189         unsigned long polling_frequency;
190         volatile u8 zombie;
191         struct acpi_thermal_flags flags;
192         struct acpi_thermal_state state;
193         struct acpi_thermal_trips trips;
194         struct acpi_handle_list devices;
195         struct thermal_zone_device *thermal_zone;
196         int tz_enabled;
197         int kelvin_offset;
198         struct mutex lock;
199 };
200
201 static const struct file_operations acpi_thermal_state_fops = {
202         .owner = THIS_MODULE,
203         .open = acpi_thermal_state_open_fs,
204         .read = seq_read,
205         .llseek = seq_lseek,
206         .release = single_release,
207 };
208
209 static const struct file_operations acpi_thermal_temp_fops = {
210         .owner = THIS_MODULE,
211         .open = acpi_thermal_temp_open_fs,
212         .read = seq_read,
213         .llseek = seq_lseek,
214         .release = single_release,
215 };
216
217 static const struct file_operations acpi_thermal_trip_fops = {
218         .owner = THIS_MODULE,
219         .open = acpi_thermal_trip_open_fs,
220         .read = seq_read,
221         .llseek = seq_lseek,
222         .release = single_release,
223 };
224
225 static const struct file_operations acpi_thermal_cooling_fops = {
226         .owner = THIS_MODULE,
227         .open = acpi_thermal_cooling_open_fs,
228         .read = seq_read,
229         .write = acpi_thermal_write_cooling_mode,
230         .llseek = seq_lseek,
231         .release = single_release,
232 };
233
234 static const struct file_operations acpi_thermal_polling_fops = {
235         .owner = THIS_MODULE,
236         .open = acpi_thermal_polling_open_fs,
237         .read = seq_read,
238         .write = acpi_thermal_write_polling,
239         .llseek = seq_lseek,
240         .release = single_release,
241 };
242
243 /* --------------------------------------------------------------------------
244                              Thermal Zone Management
245    -------------------------------------------------------------------------- */
246
247 static int acpi_thermal_get_temperature(struct acpi_thermal *tz)
248 {
249         acpi_status status = AE_OK;
250         unsigned long long tmp;
251
252         if (!tz)
253                 return -EINVAL;
254
255         tz->last_temperature = tz->temperature;
256
257         status = acpi_evaluate_integer(tz->device->handle, "_TMP", NULL, &tmp);
258         if (ACPI_FAILURE(status))
259                 return -ENODEV;
260
261         tz->temperature = tmp;
262         ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Temperature is %lu dK\n",
263                           tz->temperature));
264
265         return 0;
266 }
267
268 static int acpi_thermal_get_polling_frequency(struct acpi_thermal *tz)
269 {
270         acpi_status status = AE_OK;
271         unsigned long long tmp;
272
273         if (!tz)
274                 return -EINVAL;
275
276         status = acpi_evaluate_integer(tz->device->handle, "_TZP", NULL, &tmp);
277         if (ACPI_FAILURE(status))
278                 return -ENODEV;
279
280         tz->polling_frequency = tmp;
281         ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Polling frequency is %lu dS\n",
282                           tz->polling_frequency));
283
284         return 0;
285 }
286
287 static int acpi_thermal_set_polling(struct acpi_thermal *tz, int seconds)
288 {
289
290         if (!tz)
291                 return -EINVAL;
292
293         tz->polling_frequency = seconds * 10;   /* Convert value to deci-seconds */
294
295         tz->thermal_zone->polling_delay = seconds * 1000;
296
297         if (tz->tz_enabled)
298                 thermal_zone_device_update(tz->thermal_zone);
299
300         ACPI_DEBUG_PRINT((ACPI_DB_INFO,
301                           "Polling frequency set to %lu seconds\n",
302                           tz->polling_frequency/10));
303
304         return 0;
305 }
306
307 static int acpi_thermal_set_cooling_mode(struct acpi_thermal *tz, int mode)
308 {
309         acpi_status status = AE_OK;
310         union acpi_object arg0 = { ACPI_TYPE_INTEGER };
311         struct acpi_object_list arg_list = { 1, &arg0 };
312         acpi_handle handle = NULL;
313
314
315         if (!tz)
316                 return -EINVAL;
317
318         status = acpi_get_handle(tz->device->handle, "_SCP", &handle);
319         if (ACPI_FAILURE(status)) {
320                 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "_SCP not present\n"));
321                 return -ENODEV;
322         }
323
324         arg0.integer.value = mode;
325
326         status = acpi_evaluate_object(handle, NULL, &arg_list, NULL);
327         if (ACPI_FAILURE(status))
328                 return -ENODEV;
329
330         return 0;
331 }
332
333 #define ACPI_TRIPS_CRITICAL     0x01
334 #define ACPI_TRIPS_HOT          0x02
335 #define ACPI_TRIPS_PASSIVE      0x04
336 #define ACPI_TRIPS_ACTIVE       0x08
337 #define ACPI_TRIPS_DEVICES      0x10
338
339 #define ACPI_TRIPS_REFRESH_THRESHOLDS   (ACPI_TRIPS_PASSIVE | ACPI_TRIPS_ACTIVE)
340 #define ACPI_TRIPS_REFRESH_DEVICES      ACPI_TRIPS_DEVICES
341
342 #define ACPI_TRIPS_INIT      (ACPI_TRIPS_CRITICAL | ACPI_TRIPS_HOT |    \
343                               ACPI_TRIPS_PASSIVE | ACPI_TRIPS_ACTIVE |  \
344                               ACPI_TRIPS_DEVICES)
345
346 /*
347  * This exception is thrown out in two cases:
348  * 1.An invalid trip point becomes invalid or a valid trip point becomes invalid
349  *   when re-evaluating the AML code.
350  * 2.TODO: Devices listed in _PSL, _ALx, _TZD may change.
351  *   We need to re-bind the cooling devices of a thermal zone when this occurs.
352  */
353 #define ACPI_THERMAL_TRIPS_EXCEPTION(flags, str)        \
354 do {    \
355         if (flags != ACPI_TRIPS_INIT)   \
356                 ACPI_EXCEPTION((AE_INFO, AE_ERROR,      \
357                 "ACPI thermal trip point %s changed\n"  \
358                 "Please send acpidump to linux-acpi@vger.kernel.org\n", str)); \
359 } while (0)
360
361 static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
362 {
363         acpi_status status = AE_OK;
364         unsigned long long tmp;
365         struct acpi_handle_list devices;
366         int valid = 0;
367         int i;
368
369         /* Critical Shutdown (required) */
370         if (flag & ACPI_TRIPS_CRITICAL) {
371                 status = acpi_evaluate_integer(tz->device->handle,
372                                 "_CRT", NULL, &tmp);
373                 tz->trips.critical.temperature = tmp;
374                 /*
375                  * Treat freezing temperatures as invalid as well; some
376                  * BIOSes return really low values and cause reboots at startup.
377                  * Below zero (Celsius) values clearly aren't right for sure..
378                  * ... so lets discard those as invalid.
379                  */
380                 if (ACPI_FAILURE(status) ||
381                                 tz->trips.critical.temperature <= 2732) {
382                         tz->trips.critical.flags.valid = 0;
383                         ACPI_EXCEPTION((AE_INFO, status,
384                                         "No or invalid critical threshold"));
385                         return -ENODEV;
386                 } else {
387                         tz->trips.critical.flags.valid = 1;
388                         ACPI_DEBUG_PRINT((ACPI_DB_INFO,
389                                         "Found critical threshold [%lu]\n",
390                                         tz->trips.critical.temperature));
391                 }
392                 if (tz->trips.critical.flags.valid == 1) {
393                         if (crt == -1) {
394                                 tz->trips.critical.flags.valid = 0;
395                         } else if (crt > 0) {
396                                 unsigned long crt_k = CELSIUS_TO_KELVIN(crt);
397                                 /*
398                                  * Allow override critical threshold
399                                  */
400                                 if (crt_k > tz->trips.critical.temperature)
401                                         printk(KERN_WARNING PREFIX
402                                                 "Critical threshold %d C\n", crt);
403                                 tz->trips.critical.temperature = crt_k;
404                         }
405                 }
406         }
407
408         /* Critical Sleep (optional) */
409         if (flag & ACPI_TRIPS_HOT) {
410                 status = acpi_evaluate_integer(tz->device->handle,
411                                 "_HOT", NULL, &tmp);
412                 if (ACPI_FAILURE(status)) {
413                         tz->trips.hot.flags.valid = 0;
414                         ACPI_DEBUG_PRINT((ACPI_DB_INFO,
415                                         "No hot threshold\n"));
416                 } else {
417                         tz->trips.hot.temperature = tmp;
418                         tz->trips.hot.flags.valid = 1;
419                         ACPI_DEBUG_PRINT((ACPI_DB_INFO,
420                                         "Found hot threshold [%lu]\n",
421                                         tz->trips.critical.temperature));
422                 }
423         }
424
425         /* Passive (optional) */
426         if (((flag & ACPI_TRIPS_PASSIVE) && tz->trips.passive.flags.valid) ||
427                 (flag == ACPI_TRIPS_INIT)) {
428                 valid = tz->trips.passive.flags.valid;
429                 if (psv == -1) {
430                         status = AE_SUPPORT;
431                 } else if (psv > 0) {
432                         tmp = CELSIUS_TO_KELVIN(psv);
433                         status = AE_OK;
434                 } else {
435                         status = acpi_evaluate_integer(tz->device->handle,
436                                 "_PSV", NULL, &tmp);
437                 }
438
439                 if (ACPI_FAILURE(status))
440                         tz->trips.passive.flags.valid = 0;
441                 else {
442                         tz->trips.passive.temperature = tmp;
443                         tz->trips.passive.flags.valid = 1;
444                         if (flag == ACPI_TRIPS_INIT) {
445                                 status = acpi_evaluate_integer(
446                                                 tz->device->handle, "_TC1",
447                                                 NULL, &tmp);
448                                 if (ACPI_FAILURE(status))
449                                         tz->trips.passive.flags.valid = 0;
450                                 else
451                                         tz->trips.passive.tc1 = tmp;
452                                 status = acpi_evaluate_integer(
453                                                 tz->device->handle, "_TC2",
454                                                 NULL, &tmp);
455                                 if (ACPI_FAILURE(status))
456                                         tz->trips.passive.flags.valid = 0;
457                                 else
458                                         tz->trips.passive.tc2 = tmp;
459                                 status = acpi_evaluate_integer(
460                                                 tz->device->handle, "_TSP",
461                                                 NULL, &tmp);
462                                 if (ACPI_FAILURE(status))
463                                         tz->trips.passive.flags.valid = 0;
464                                 else
465                                         tz->trips.passive.tsp = tmp;
466                         }
467                 }
468         }
469         if ((flag & ACPI_TRIPS_DEVICES) && tz->trips.passive.flags.valid) {
470                 memset(&devices, 0, sizeof(struct acpi_handle_list));
471                 status = acpi_evaluate_reference(tz->device->handle, "_PSL",
472                                                         NULL, &devices);
473                 if (ACPI_FAILURE(status)) {
474                         printk(KERN_WARNING PREFIX
475                                 "Invalid passive threshold\n");
476                         tz->trips.passive.flags.valid = 0;
477                 }
478                 else
479                         tz->trips.passive.flags.valid = 1;
480
481                 if (memcmp(&tz->trips.passive.devices, &devices,
482                                 sizeof(struct acpi_handle_list))) {
483                         memcpy(&tz->trips.passive.devices, &devices,
484                                 sizeof(struct acpi_handle_list));
485                         ACPI_THERMAL_TRIPS_EXCEPTION(flag, "device");
486                 }
487         }
488         if ((flag & ACPI_TRIPS_PASSIVE) || (flag & ACPI_TRIPS_DEVICES)) {
489                 if (valid != tz->trips.passive.flags.valid)
490                                 ACPI_THERMAL_TRIPS_EXCEPTION(flag, "state");
491         }
492
493         /* Active (optional) */
494         for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
495                 char name[5] = { '_', 'A', 'C', ('0' + i), '\0' };
496                 valid = tz->trips.active[i].flags.valid;
497
498                 if (act == -1)
499                         break; /* disable all active trip points */
500
501                 if ((flag == ACPI_TRIPS_INIT) || ((flag & ACPI_TRIPS_ACTIVE) &&
502                         tz->trips.active[i].flags.valid)) {
503                         status = acpi_evaluate_integer(tz->device->handle,
504                                                         name, NULL, &tmp);
505                         if (ACPI_FAILURE(status)) {
506                                 tz->trips.active[i].flags.valid = 0;
507                                 if (i == 0)
508                                         break;
509                                 if (act <= 0)
510                                         break;
511                                 if (i == 1)
512                                         tz->trips.active[0].temperature =
513                                                 CELSIUS_TO_KELVIN(act);
514                                 else
515                                         /*
516                                          * Don't allow override higher than
517                                          * the next higher trip point
518                                          */
519                                         tz->trips.active[i - 1].temperature =
520                                                 (tz->trips.active[i - 2].temperature <
521                                                 CELSIUS_TO_KELVIN(act) ?
522                                                 tz->trips.active[i - 2].temperature :
523                                                 CELSIUS_TO_KELVIN(act));
524                                 break;
525                         } else {
526                                 tz->trips.active[i].temperature = tmp;
527                                 tz->trips.active[i].flags.valid = 1;
528                         }
529                 }
530
531                 name[2] = 'L';
532                 if ((flag & ACPI_TRIPS_DEVICES) && tz->trips.active[i].flags.valid ) {
533                         memset(&devices, 0, sizeof(struct acpi_handle_list));
534                         status = acpi_evaluate_reference(tz->device->handle,
535                                                 name, NULL, &devices);
536                         if (ACPI_FAILURE(status)) {
537                                 printk(KERN_WARNING PREFIX
538                                         "Invalid active%d threshold\n", i);
539                                 tz->trips.active[i].flags.valid = 0;
540                         }
541                         else
542                                 tz->trips.active[i].flags.valid = 1;
543
544                         if (memcmp(&tz->trips.active[i].devices, &devices,
545                                         sizeof(struct acpi_handle_list))) {
546                                 memcpy(&tz->trips.active[i].devices, &devices,
547                                         sizeof(struct acpi_handle_list));
548                                 ACPI_THERMAL_TRIPS_EXCEPTION(flag, "device");
549                         }
550                 }
551                 if ((flag & ACPI_TRIPS_ACTIVE) || (flag & ACPI_TRIPS_DEVICES))
552                         if (valid != tz->trips.active[i].flags.valid)
553                                 ACPI_THERMAL_TRIPS_EXCEPTION(flag, "state");
554
555                 if (!tz->trips.active[i].flags.valid)
556                         break;
557         }
558
559         if (flag & ACPI_TRIPS_DEVICES) {
560                 memset(&devices, 0, sizeof(struct acpi_handle_list));
561                 status = acpi_evaluate_reference(tz->device->handle, "_TZD",
562                                                 NULL, &devices);
563                 if (memcmp(&tz->devices, &devices,
564                                 sizeof(struct acpi_handle_list))) {
565                         memcpy(&tz->devices, &devices,
566                                 sizeof(struct acpi_handle_list));
567                         ACPI_THERMAL_TRIPS_EXCEPTION(flag, "device");
568                 }
569         }
570
571         return 0;
572 }
573
574 static int acpi_thermal_get_trip_points(struct acpi_thermal *tz)
575 {
576         return acpi_thermal_trips_update(tz, ACPI_TRIPS_INIT);
577 }
578
579 static void acpi_thermal_check(void *data)
580 {
581         struct acpi_thermal *tz = data;
582
583         thermal_zone_device_update(tz->thermal_zone);
584 }
585
586 /* sys I/F for generic thermal sysfs support */
587 #define KELVIN_TO_MILLICELSIUS(t, off) (((t) - (off)) * 100)
588
589 static int thermal_get_temp(struct thermal_zone_device *thermal,
590                             unsigned long *temp)
591 {
592         struct acpi_thermal *tz = thermal->devdata;
593         int result;
594
595         if (!tz)
596                 return -EINVAL;
597
598         result = acpi_thermal_get_temperature(tz);
599         if (result)
600                 return result;
601
602         *temp = KELVIN_TO_MILLICELSIUS(tz->temperature, tz->kelvin_offset);
603         return 0;
604 }
605
606 static const char enabled[] = "kernel";
607 static const char disabled[] = "user";
608 static int thermal_get_mode(struct thermal_zone_device *thermal,
609                                 enum thermal_device_mode *mode)
610 {
611         struct acpi_thermal *tz = thermal->devdata;
612
613         if (!tz)
614                 return -EINVAL;
615
616         *mode = tz->tz_enabled ? THERMAL_DEVICE_ENABLED :
617                 THERMAL_DEVICE_DISABLED;
618
619         return 0;
620 }
621
622 static int thermal_set_mode(struct thermal_zone_device *thermal,
623                                 enum thermal_device_mode mode)
624 {
625         struct acpi_thermal *tz = thermal->devdata;
626         int enable;
627
628         if (!tz)
629                 return -EINVAL;
630
631         /*
632          * enable/disable thermal management from ACPI thermal driver
633          */
634         if (mode == THERMAL_DEVICE_ENABLED)
635                 enable = 1;
636         else if (mode == THERMAL_DEVICE_DISABLED)
637                 enable = 0;
638         else
639                 return -EINVAL;
640
641         if (enable != tz->tz_enabled) {
642                 tz->tz_enabled = enable;
643                 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
644                         "%s ACPI thermal control\n",
645                         tz->tz_enabled ? enabled : disabled));
646                 acpi_thermal_check(tz);
647         }
648         return 0;
649 }
650
651 static int thermal_get_trip_type(struct thermal_zone_device *thermal,
652                                  int trip, enum thermal_trip_type *type)
653 {
654         struct acpi_thermal *tz = thermal->devdata;
655         int i;
656
657         if (!tz || trip < 0)
658                 return -EINVAL;
659
660         if (tz->trips.critical.flags.valid) {
661                 if (!trip) {
662                         *type = THERMAL_TRIP_CRITICAL;
663                         return 0;
664                 }
665                 trip--;
666         }
667
668         if (tz->trips.hot.flags.valid) {
669                 if (!trip) {
670                         *type = THERMAL_TRIP_HOT;
671                         return 0;
672                 }
673                 trip--;
674         }
675
676         if (tz->trips.passive.flags.valid) {
677                 if (!trip) {
678                         *type = THERMAL_TRIP_PASSIVE;
679                         return 0;
680                 }
681                 trip--;
682         }
683
684         for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE &&
685                 tz->trips.active[i].flags.valid; i++) {
686                 if (!trip) {
687                         *type = THERMAL_TRIP_ACTIVE;
688                         return 0;
689                 }
690                 trip--;
691         }
692
693         return -EINVAL;
694 }
695
696 static int thermal_get_trip_temp(struct thermal_zone_device *thermal,
697                                  int trip, unsigned long *temp)
698 {
699         struct acpi_thermal *tz = thermal->devdata;
700         int i;
701
702         if (!tz || trip < 0)
703                 return -EINVAL;
704
705         if (tz->trips.critical.flags.valid) {
706                 if (!trip) {
707                         *temp = KELVIN_TO_MILLICELSIUS(
708                                 tz->trips.critical.temperature,
709                                 tz->kelvin_offset);
710                         return 0;
711                 }
712                 trip--;
713         }
714
715         if (tz->trips.hot.flags.valid) {
716                 if (!trip) {
717                         *temp = KELVIN_TO_MILLICELSIUS(
718                                 tz->trips.hot.temperature,
719                                 tz->kelvin_offset);
720                         return 0;
721                 }
722                 trip--;
723         }
724
725         if (tz->trips.passive.flags.valid) {
726                 if (!trip) {
727                         *temp = KELVIN_TO_MILLICELSIUS(
728                                 tz->trips.passive.temperature,
729                                 tz->kelvin_offset);
730                         return 0;
731                 }
732                 trip--;
733         }
734
735         for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE &&
736                 tz->trips.active[i].flags.valid; i++) {
737                 if (!trip) {
738                         *temp = KELVIN_TO_MILLICELSIUS(
739                                 tz->trips.active[i].temperature,
740                                 tz->kelvin_offset);
741                         return 0;
742                 }
743                 trip--;
744         }
745
746         return -EINVAL;
747 }
748
749 static int thermal_get_crit_temp(struct thermal_zone_device *thermal,
750                                 unsigned long *temperature) {
751         struct acpi_thermal *tz = thermal->devdata;
752
753         if (tz->trips.critical.flags.valid) {
754                 *temperature = KELVIN_TO_MILLICELSIUS(
755                                 tz->trips.critical.temperature,
756                                 tz->kelvin_offset);
757                 return 0;
758         } else
759                 return -EINVAL;
760 }
761
762 static int thermal_notify(struct thermal_zone_device *thermal, int trip,
763                            enum thermal_trip_type trip_type)
764 {
765         u8 type = 0;
766         struct acpi_thermal *tz = thermal->devdata;
767
768         if (trip_type == THERMAL_TRIP_CRITICAL)
769                 type = ACPI_THERMAL_NOTIFY_CRITICAL;
770         else if (trip_type == THERMAL_TRIP_HOT)
771                 type = ACPI_THERMAL_NOTIFY_HOT;
772         else
773                 return 0;
774
775         acpi_bus_generate_proc_event(tz->device, type, 1);
776         acpi_bus_generate_netlink_event(tz->device->pnp.device_class,
777                                         dev_name(&tz->device->dev), type, 1);
778
779         if (trip_type == THERMAL_TRIP_CRITICAL && nocrt)
780                 return 1;
781
782         return 0;
783 }
784
785 typedef int (*cb)(struct thermal_zone_device *, int,
786                   struct thermal_cooling_device *);
787 static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal,
788                                         struct thermal_cooling_device *cdev,
789                                         cb action)
790 {
791         struct acpi_device *device = cdev->devdata;
792         struct acpi_thermal *tz = thermal->devdata;
793         struct acpi_device *dev;
794         acpi_status status;
795         acpi_handle handle;
796         int i;
797         int j;
798         int trip = -1;
799         int result = 0;
800
801         if (tz->trips.critical.flags.valid)
802                 trip++;
803
804         if (tz->trips.hot.flags.valid)
805                 trip++;
806
807         if (tz->trips.passive.flags.valid) {
808                 trip++;
809                 for (i = 0; i < tz->trips.passive.devices.count;
810                     i++) {
811                         handle = tz->trips.passive.devices.handles[i];
812                         status = acpi_bus_get_device(handle, &dev);
813                         if (ACPI_SUCCESS(status) && (dev == device)) {
814                                 result = action(thermal, trip, cdev);
815                                 if (result)
816                                         goto failed;
817                         }
818                 }
819         }
820
821         for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
822                 if (!tz->trips.active[i].flags.valid)
823                         break;
824                 trip++;
825                 for (j = 0;
826                     j < tz->trips.active[i].devices.count;
827                     j++) {
828                         handle = tz->trips.active[i].devices.handles[j];
829                         status = acpi_bus_get_device(handle, &dev);
830                         if (ACPI_SUCCESS(status) && (dev == device)) {
831                                 result = action(thermal, trip, cdev);
832                                 if (result)
833                                         goto failed;
834                         }
835                 }
836         }
837
838         for (i = 0; i < tz->devices.count; i++) {
839                 handle = tz->devices.handles[i];
840                 status = acpi_bus_get_device(handle, &dev);
841                 if (ACPI_SUCCESS(status) && (dev == device)) {
842                         result = action(thermal, -1, cdev);
843                         if (result)
844                                 goto failed;
845                 }
846         }
847
848 failed:
849         return result;
850 }
851
852 static int
853 acpi_thermal_bind_cooling_device(struct thermal_zone_device *thermal,
854                                         struct thermal_cooling_device *cdev)
855 {
856         return acpi_thermal_cooling_device_cb(thermal, cdev,
857                                 thermal_zone_bind_cooling_device);
858 }
859
860 static int
861 acpi_thermal_unbind_cooling_device(struct thermal_zone_device *thermal,
862                                         struct thermal_cooling_device *cdev)
863 {
864         return acpi_thermal_cooling_device_cb(thermal, cdev,
865                                 thermal_zone_unbind_cooling_device);
866 }
867
868 static struct thermal_zone_device_ops acpi_thermal_zone_ops = {
869         .bind = acpi_thermal_bind_cooling_device,
870         .unbind = acpi_thermal_unbind_cooling_device,
871         .get_temp = thermal_get_temp,
872         .get_mode = thermal_get_mode,
873         .set_mode = thermal_set_mode,
874         .get_trip_type = thermal_get_trip_type,
875         .get_trip_temp = thermal_get_trip_temp,
876         .get_crit_temp = thermal_get_crit_temp,
877         .notify = thermal_notify,
878 };
879
880 static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz)
881 {
882         int trips = 0;
883         int result;
884         acpi_status status;
885         int i;
886
887         if (tz->trips.critical.flags.valid)
888                 trips++;
889
890         if (tz->trips.hot.flags.valid)
891                 trips++;
892
893         if (tz->trips.passive.flags.valid)
894                 trips++;
895
896         for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE &&
897                         tz->trips.active[i].flags.valid; i++, trips++);
898
899         if (tz->trips.passive.flags.valid)
900                 tz->thermal_zone =
901                         thermal_zone_device_register("acpitz", trips, tz,
902                                                      &acpi_thermal_zone_ops,
903                                                      tz->trips.passive.tc1,
904                                                      tz->trips.passive.tc2,
905                                                      tz->trips.passive.tsp*100,
906                                                      tz->polling_frequency*100);
907         else
908                 tz->thermal_zone =
909                         thermal_zone_device_register("acpitz", trips, tz,
910                                                      &acpi_thermal_zone_ops,
911                                                      0, 0, 0,
912                                                      tz->polling_frequency*100);
913         if (IS_ERR(tz->thermal_zone))
914                 return -ENODEV;
915
916         result = sysfs_create_link(&tz->device->dev.kobj,
917                                    &tz->thermal_zone->device.kobj, "thermal_zone");
918         if (result)
919                 return result;
920
921         result = sysfs_create_link(&tz->thermal_zone->device.kobj,
922                                    &tz->device->dev.kobj, "device");
923         if (result)
924                 return result;
925
926         status = acpi_attach_data(tz->device->handle,
927                                   acpi_bus_private_data_handler,
928                                   tz->thermal_zone);
929         if (ACPI_FAILURE(status)) {
930                 printk(KERN_ERR PREFIX
931                                 "Error attaching device data\n");
932                 return -ENODEV;
933         }
934
935         tz->tz_enabled = 1;
936
937         dev_info(&tz->device->dev, "registered as thermal_zone%d\n",
938                  tz->thermal_zone->id);
939         return 0;
940 }
941
942 static void acpi_thermal_unregister_thermal_zone(struct acpi_thermal *tz)
943 {
944         sysfs_remove_link(&tz->device->dev.kobj, "thermal_zone");
945         sysfs_remove_link(&tz->thermal_zone->device.kobj, "device");
946         thermal_zone_device_unregister(tz->thermal_zone);
947         tz->thermal_zone = NULL;
948         acpi_detach_data(tz->device->handle, acpi_bus_private_data_handler);
949 }
950
951
952 /* --------------------------------------------------------------------------
953                               FS Interface (/proc)
954    -------------------------------------------------------------------------- */
955
956 static struct proc_dir_entry *acpi_thermal_dir;
957
958 static int acpi_thermal_state_seq_show(struct seq_file *seq, void *offset)
959 {
960         struct acpi_thermal *tz = seq->private;
961
962
963         if (!tz)
964                 goto end;
965
966         seq_puts(seq, "state:                   ");
967
968         if (!tz->state.critical && !tz->state.hot && !tz->state.passive
969             && !tz->state.active)
970                 seq_puts(seq, "ok\n");
971         else {
972                 if (tz->state.critical)
973                         seq_puts(seq, "critical ");
974                 if (tz->state.hot)
975                         seq_puts(seq, "hot ");
976                 if (tz->state.passive)
977                         seq_puts(seq, "passive ");
978                 if (tz->state.active)
979                         seq_printf(seq, "active[%d]", tz->state.active_index);
980                 seq_puts(seq, "\n");
981         }
982
983       end:
984         return 0;
985 }
986
987 static int acpi_thermal_state_open_fs(struct inode *inode, struct file *file)
988 {
989         return single_open(file, acpi_thermal_state_seq_show, PDE(inode)->data);
990 }
991
992 static int acpi_thermal_temp_seq_show(struct seq_file *seq, void *offset)
993 {
994         int result = 0;
995         struct acpi_thermal *tz = seq->private;
996
997
998         if (!tz)
999                 goto end;
1000
1001         result = acpi_thermal_get_temperature(tz);
1002         if (result)
1003                 goto end;
1004
1005         seq_printf(seq, "temperature:             %ld C\n",
1006                    KELVIN_TO_CELSIUS(tz->temperature));
1007
1008       end:
1009         return 0;
1010 }
1011
1012 static int acpi_thermal_temp_open_fs(struct inode *inode, struct file *file)
1013 {
1014         return single_open(file, acpi_thermal_temp_seq_show, PDE(inode)->data);
1015 }
1016
1017 static int acpi_thermal_trip_seq_show(struct seq_file *seq, void *offset)
1018 {
1019         struct acpi_thermal *tz = seq->private;
1020         struct acpi_device *device;
1021         acpi_status status;
1022
1023         int i = 0;
1024         int j = 0;
1025
1026
1027         if (!tz)
1028                 goto end;
1029
1030         if (tz->trips.critical.flags.valid)
1031                 seq_printf(seq, "critical (S5):           %ld C%s",
1032                            KELVIN_TO_CELSIUS(tz->trips.critical.temperature),
1033                            nocrt ? " <disabled>\n" : "\n");
1034
1035         if (tz->trips.hot.flags.valid)
1036                 seq_printf(seq, "hot (S4):                %ld C%s",
1037                            KELVIN_TO_CELSIUS(tz->trips.hot.temperature),
1038                            nocrt ? " <disabled>\n" : "\n");
1039
1040         if (tz->trips.passive.flags.valid) {
1041                 seq_printf(seq,
1042                            "passive:                 %ld C: tc1=%lu tc2=%lu tsp=%lu devices=",
1043                            KELVIN_TO_CELSIUS(tz->trips.passive.temperature),
1044                            tz->trips.passive.tc1, tz->trips.passive.tc2,
1045                            tz->trips.passive.tsp);
1046                 for (j = 0; j < tz->trips.passive.devices.count; j++) {
1047                         status = acpi_bus_get_device(tz->trips.passive.devices.
1048                                                      handles[j], &device);
1049                         seq_printf(seq, "%4.4s ", status ? "" :
1050                                    acpi_device_bid(device));
1051                 }
1052                 seq_puts(seq, "\n");
1053         }
1054
1055         for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
1056                 if (!(tz->trips.active[i].flags.valid))
1057                         break;
1058                 seq_printf(seq, "active[%d]:               %ld C: devices=",
1059                            i,
1060                            KELVIN_TO_CELSIUS(tz->trips.active[i].temperature));
1061                 for (j = 0; j < tz->trips.active[i].devices.count; j++){
1062                         status = acpi_bus_get_device(tz->trips.active[i].
1063                                                      devices.handles[j],
1064                                                      &device);
1065                         seq_printf(seq, "%4.4s ", status ? "" :
1066                                    acpi_device_bid(device));
1067                 }
1068                 seq_puts(seq, "\n");
1069         }
1070
1071       end:
1072         return 0;
1073 }
1074
1075 static int acpi_thermal_trip_open_fs(struct inode *inode, struct file *file)
1076 {
1077         return single_open(file, acpi_thermal_trip_seq_show, PDE(inode)->data);
1078 }
1079
1080 static int acpi_thermal_cooling_seq_show(struct seq_file *seq, void *offset)
1081 {
1082         struct acpi_thermal *tz = seq->private;
1083
1084
1085         if (!tz)
1086                 goto end;
1087
1088         if (!tz->flags.cooling_mode)
1089                 seq_puts(seq, "<setting not supported>\n");
1090         else
1091                 seq_puts(seq, "0 - Active; 1 - Passive\n");
1092
1093       end:
1094         return 0;
1095 }
1096
1097 static int acpi_thermal_cooling_open_fs(struct inode *inode, struct file *file)
1098 {
1099         return single_open(file, acpi_thermal_cooling_seq_show,
1100                            PDE(inode)->data);
1101 }
1102
1103 static ssize_t
1104 acpi_thermal_write_cooling_mode(struct file *file,
1105                                 const char __user * buffer,
1106                                 size_t count, loff_t * ppos)
1107 {
1108         struct seq_file *m = file->private_data;
1109         struct acpi_thermal *tz = m->private;
1110         int result = 0;
1111         char mode_string[12] = { '\0' };
1112
1113
1114         if (!tz || (count > sizeof(mode_string) - 1))
1115                 return -EINVAL;
1116
1117         if (!tz->flags.cooling_mode)
1118                 return -ENODEV;
1119
1120         if (copy_from_user(mode_string, buffer, count))
1121                 return -EFAULT;
1122
1123         mode_string[count] = '\0';
1124
1125         result = acpi_thermal_set_cooling_mode(tz,
1126                                                simple_strtoul(mode_string, NULL,
1127                                                               0));
1128         if (result)
1129                 return result;
1130
1131         acpi_thermal_check(tz);
1132
1133         return count;
1134 }
1135
1136 static int acpi_thermal_polling_seq_show(struct seq_file *seq, void *offset)
1137 {
1138         struct acpi_thermal *tz = seq->private;
1139
1140
1141         if (!tz)
1142                 goto end;
1143
1144         if (!tz->thermal_zone->polling_delay) {
1145                 seq_puts(seq, "<polling disabled>\n");
1146                 goto end;
1147         }
1148
1149         seq_printf(seq, "polling frequency:       %d seconds\n",
1150                    (tz->thermal_zone->polling_delay / 1000));
1151
1152       end:
1153         return 0;
1154 }
1155
1156 static int acpi_thermal_polling_open_fs(struct inode *inode, struct file *file)
1157 {
1158         return single_open(file, acpi_thermal_polling_seq_show,
1159                            PDE(inode)->data);
1160 }
1161
1162 static ssize_t
1163 acpi_thermal_write_polling(struct file *file,
1164                            const char __user * buffer,
1165                            size_t count, loff_t * ppos)
1166 {
1167         struct seq_file *m = file->private_data;
1168         struct acpi_thermal *tz = m->private;
1169         int result = 0;
1170         char polling_string[12] = { '\0' };
1171         int seconds = 0;
1172
1173
1174         if (!tz || (count > sizeof(polling_string) - 1))
1175                 return -EINVAL;
1176
1177         if (copy_from_user(polling_string, buffer, count))
1178                 return -EFAULT;
1179
1180         polling_string[count] = '\0';
1181
1182         seconds = simple_strtoul(polling_string, NULL, 0);
1183
1184         result = acpi_thermal_set_polling(tz, seconds);
1185         if (result)
1186                 return result;
1187
1188         acpi_thermal_check(tz);
1189
1190         return count;
1191 }
1192
1193 static int acpi_thermal_add_fs(struct acpi_device *device)
1194 {
1195         struct proc_dir_entry *entry = NULL;
1196
1197
1198         if (!acpi_device_dir(device)) {
1199                 acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
1200                                                      acpi_thermal_dir);
1201                 if (!acpi_device_dir(device))
1202                         return -ENODEV;
1203         }
1204
1205         /* 'state' [R] */
1206         entry = proc_create_data(ACPI_THERMAL_FILE_STATE,
1207                                  S_IRUGO, acpi_device_dir(device),
1208                                  &acpi_thermal_state_fops,
1209                                  acpi_driver_data(device));
1210         if (!entry)
1211                 return -ENODEV;
1212
1213         /* 'temperature' [R] */
1214         entry = proc_create_data(ACPI_THERMAL_FILE_TEMPERATURE,
1215                                  S_IRUGO, acpi_device_dir(device),
1216                                  &acpi_thermal_temp_fops,
1217                                  acpi_driver_data(device));
1218         if (!entry)
1219                 return -ENODEV;
1220
1221         /* 'trip_points' [R] */
1222         entry = proc_create_data(ACPI_THERMAL_FILE_TRIP_POINTS,
1223                                  S_IRUGO,
1224                                  acpi_device_dir(device),
1225                                  &acpi_thermal_trip_fops,
1226                                  acpi_driver_data(device));
1227         if (!entry)
1228                 return -ENODEV;
1229
1230         /* 'cooling_mode' [R/W] */
1231         entry = proc_create_data(ACPI_THERMAL_FILE_COOLING_MODE,
1232                                  S_IFREG | S_IRUGO | S_IWUSR,
1233                                  acpi_device_dir(device),
1234                                  &acpi_thermal_cooling_fops,
1235                                  acpi_driver_data(device));
1236         if (!entry)
1237                 return -ENODEV;
1238
1239         /* 'polling_frequency' [R/W] */
1240         entry = proc_create_data(ACPI_THERMAL_FILE_POLLING_FREQ,
1241                                  S_IFREG | S_IRUGO | S_IWUSR,
1242                                  acpi_device_dir(device),
1243                                  &acpi_thermal_polling_fops,
1244                                  acpi_driver_data(device));
1245         if (!entry)
1246                 return -ENODEV;
1247         return 0;
1248 }
1249
1250 static int acpi_thermal_remove_fs(struct acpi_device *device)
1251 {
1252
1253         if (acpi_device_dir(device)) {
1254                 remove_proc_entry(ACPI_THERMAL_FILE_POLLING_FREQ,
1255                                   acpi_device_dir(device));
1256                 remove_proc_entry(ACPI_THERMAL_FILE_COOLING_MODE,
1257                                   acpi_device_dir(device));
1258                 remove_proc_entry(ACPI_THERMAL_FILE_TRIP_POINTS,
1259                                   acpi_device_dir(device));
1260                 remove_proc_entry(ACPI_THERMAL_FILE_TEMPERATURE,
1261                                   acpi_device_dir(device));
1262                 remove_proc_entry(ACPI_THERMAL_FILE_STATE,
1263                                   acpi_device_dir(device));
1264                 remove_proc_entry(acpi_device_bid(device), acpi_thermal_dir);
1265                 acpi_device_dir(device) = NULL;
1266         }
1267
1268         return 0;
1269 }
1270
1271 /* --------------------------------------------------------------------------
1272                                  Driver Interface
1273    -------------------------------------------------------------------------- */
1274
1275 static void acpi_thermal_notify(struct acpi_device *device, u32 event)
1276 {
1277         struct acpi_thermal *tz = acpi_driver_data(device);
1278
1279
1280         if (!tz)
1281                 return;
1282
1283         switch (event) {
1284         case ACPI_THERMAL_NOTIFY_TEMPERATURE:
1285                 acpi_thermal_check(tz);
1286                 break;
1287         case ACPI_THERMAL_NOTIFY_THRESHOLDS:
1288                 acpi_thermal_trips_update(tz, ACPI_TRIPS_REFRESH_THRESHOLDS);
1289                 acpi_thermal_check(tz);
1290                 acpi_bus_generate_proc_event(device, event, 0);
1291                 acpi_bus_generate_netlink_event(device->pnp.device_class,
1292                                                   dev_name(&device->dev), event, 0);
1293                 break;
1294         case ACPI_THERMAL_NOTIFY_DEVICES:
1295                 acpi_thermal_trips_update(tz, ACPI_TRIPS_REFRESH_DEVICES);
1296                 acpi_thermal_check(tz);
1297                 acpi_bus_generate_proc_event(device, event, 0);
1298                 acpi_bus_generate_netlink_event(device->pnp.device_class,
1299                                                   dev_name(&device->dev), event, 0);
1300                 break;
1301         default:
1302                 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
1303                                   "Unsupported event [0x%x]\n", event));
1304                 break;
1305         }
1306 }
1307
1308 static int acpi_thermal_get_info(struct acpi_thermal *tz)
1309 {
1310         int result = 0;
1311
1312
1313         if (!tz)
1314                 return -EINVAL;
1315
1316         /* Get temperature [_TMP] (required) */
1317         result = acpi_thermal_get_temperature(tz);
1318         if (result)
1319                 return result;
1320
1321         /* Get trip points [_CRT, _PSV, etc.] (required) */
1322         result = acpi_thermal_get_trip_points(tz);
1323         if (result)
1324                 return result;
1325
1326         /* Set the cooling mode [_SCP] to active cooling (default) */
1327         result = acpi_thermal_set_cooling_mode(tz, ACPI_THERMAL_MODE_ACTIVE);
1328         if (!result)
1329                 tz->flags.cooling_mode = 1;
1330
1331         /* Get default polling frequency [_TZP] (optional) */
1332         if (tzp)
1333                 tz->polling_frequency = tzp;
1334         else
1335                 acpi_thermal_get_polling_frequency(tz);
1336
1337         return 0;
1338 }
1339
1340 /*
1341  * The exact offset between Kelvin and degree Celsius is 273.15. However ACPI
1342  * handles temperature values with a single decimal place. As a consequence,
1343  * some implementations use an offset of 273.1 and others use an offset of
1344  * 273.2. Try to find out which one is being used, to present the most
1345  * accurate and visually appealing number.
1346  *
1347  * The heuristic below should work for all ACPI thermal zones which have a
1348  * critical trip point with a value being a multiple of 0.5 degree Celsius.
1349  */
1350 static void acpi_thermal_guess_offset(struct acpi_thermal *tz)
1351 {
1352         if (tz->trips.critical.flags.valid &&
1353             (tz->trips.critical.temperature % 5) == 1)
1354                 tz->kelvin_offset = 2731;
1355         else
1356                 tz->kelvin_offset = 2732;
1357 }
1358
1359 static int acpi_thermal_add(struct acpi_device *device)
1360 {
1361         int result = 0;
1362         struct acpi_thermal *tz = NULL;
1363
1364
1365         if (!device)
1366                 return -EINVAL;
1367
1368         tz = kzalloc(sizeof(struct acpi_thermal), GFP_KERNEL);
1369         if (!tz)
1370                 return -ENOMEM;
1371
1372         tz->device = device;
1373         strcpy(tz->name, device->pnp.bus_id);
1374         strcpy(acpi_device_name(device), ACPI_THERMAL_DEVICE_NAME);
1375         strcpy(acpi_device_class(device), ACPI_THERMAL_CLASS);
1376         device->driver_data = tz;
1377         mutex_init(&tz->lock);
1378
1379
1380         result = acpi_thermal_get_info(tz);
1381         if (result)
1382                 goto free_memory;
1383
1384         acpi_thermal_guess_offset(tz);
1385
1386         result = acpi_thermal_register_thermal_zone(tz);
1387         if (result)
1388                 goto free_memory;
1389
1390         result = acpi_thermal_add_fs(device);
1391         if (result)
1392                 goto unregister_thermal_zone;
1393
1394         printk(KERN_INFO PREFIX "%s [%s] (%ld C)\n",
1395                acpi_device_name(device), acpi_device_bid(device),
1396                KELVIN_TO_CELSIUS(tz->temperature));
1397         goto end;
1398
1399 unregister_thermal_zone:
1400         thermal_zone_device_unregister(tz->thermal_zone);
1401 free_memory:
1402         kfree(tz);
1403 end:
1404         return result;
1405 }
1406
1407 static int acpi_thermal_remove(struct acpi_device *device, int type)
1408 {
1409         struct acpi_thermal *tz = NULL;
1410
1411         if (!device || !acpi_driver_data(device))
1412                 return -EINVAL;
1413
1414         tz = acpi_driver_data(device);
1415
1416         acpi_thermal_remove_fs(device);
1417         acpi_thermal_unregister_thermal_zone(tz);
1418         mutex_destroy(&tz->lock);
1419         kfree(tz);
1420         return 0;
1421 }
1422
1423 static int acpi_thermal_resume(struct acpi_device *device)
1424 {
1425         struct acpi_thermal *tz = NULL;
1426         int i, j, power_state, result;
1427
1428
1429         if (!device || !acpi_driver_data(device))
1430                 return -EINVAL;
1431
1432         tz = acpi_driver_data(device);
1433
1434         for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
1435                 if (!(&tz->trips.active[i]))
1436                         break;
1437                 if (!tz->trips.active[i].flags.valid)
1438                         break;
1439                 tz->trips.active[i].flags.enabled = 1;
1440                 for (j = 0; j < tz->trips.active[i].devices.count; j++) {
1441                         result = acpi_bus_get_power(tz->trips.active[i].devices.
1442                             handles[j], &power_state);
1443                         if (result || (power_state != ACPI_STATE_D0)) {
1444                                 tz->trips.active[i].flags.enabled = 0;
1445                                 break;
1446                         }
1447                 }
1448                 tz->state.active |= tz->trips.active[i].flags.enabled;
1449         }
1450
1451         acpi_thermal_check(tz);
1452
1453         return AE_OK;
1454 }
1455
1456 static int thermal_act(const struct dmi_system_id *d) {
1457
1458         if (act == 0) {
1459                 printk(KERN_NOTICE "ACPI: %s detected: "
1460                         "disabling all active thermal trip points\n", d->ident);
1461                 act = -1;
1462         }
1463         return 0;
1464 }
1465 static int thermal_nocrt(const struct dmi_system_id *d) {
1466
1467         printk(KERN_NOTICE "ACPI: %s detected: "
1468                 "disabling all critical thermal trip point actions.\n", d->ident);
1469         nocrt = 1;
1470         return 0;
1471 }
1472 static int thermal_tzp(const struct dmi_system_id *d) {
1473
1474         if (tzp == 0) {
1475                 printk(KERN_NOTICE "ACPI: %s detected: "
1476                         "enabling thermal zone polling\n", d->ident);
1477                 tzp = 300;      /* 300 dS = 30 Seconds */
1478         }
1479         return 0;
1480 }
1481 static int thermal_psv(const struct dmi_system_id *d) {
1482
1483         if (psv == 0) {
1484                 printk(KERN_NOTICE "ACPI: %s detected: "
1485                         "disabling all passive thermal trip points\n", d->ident);
1486                 psv = -1;
1487         }
1488         return 0;
1489 }
1490
1491 static struct dmi_system_id thermal_dmi_table[] __initdata = {
1492         /*
1493          * Award BIOS on this AOpen makes thermal control almost worthless.
1494          * http://bugzilla.kernel.org/show_bug.cgi?id=8842
1495          */
1496         {
1497          .callback = thermal_act,
1498          .ident = "AOpen i915GMm-HFS",
1499          .matches = {
1500                 DMI_MATCH(DMI_BOARD_VENDOR, "AOpen"),
1501                 DMI_MATCH(DMI_BOARD_NAME, "i915GMm-HFS"),
1502                 },
1503         },
1504         {
1505          .callback = thermal_psv,
1506          .ident = "AOpen i915GMm-HFS",
1507          .matches = {
1508                 DMI_MATCH(DMI_BOARD_VENDOR, "AOpen"),
1509                 DMI_MATCH(DMI_BOARD_NAME, "i915GMm-HFS"),
1510                 },
1511         },
1512         {
1513          .callback = thermal_tzp,
1514          .ident = "AOpen i915GMm-HFS",
1515          .matches = {
1516                 DMI_MATCH(DMI_BOARD_VENDOR, "AOpen"),
1517                 DMI_MATCH(DMI_BOARD_NAME, "i915GMm-HFS"),
1518                 },
1519         },
1520         {
1521          .callback = thermal_nocrt,
1522          .ident = "Gigabyte GA-7ZX",
1523          .matches = {
1524                 DMI_MATCH(DMI_BOARD_VENDOR, "Gigabyte Technology Co., Ltd."),
1525                 DMI_MATCH(DMI_BOARD_NAME, "7ZX"),
1526                 },
1527         },
1528         {}
1529 };
1530
1531 static int __init acpi_thermal_init(void)
1532 {
1533         int result = 0;
1534
1535         dmi_check_system(thermal_dmi_table);
1536
1537         if (off) {
1538                 printk(KERN_NOTICE "ACPI: thermal control disabled\n");
1539                 return -ENODEV;
1540         }
1541         acpi_thermal_dir = proc_mkdir(ACPI_THERMAL_CLASS, acpi_root_dir);
1542         if (!acpi_thermal_dir)
1543                 return -ENODEV;
1544
1545         result = acpi_bus_register_driver(&acpi_thermal_driver);
1546         if (result < 0) {
1547                 remove_proc_entry(ACPI_THERMAL_CLASS, acpi_root_dir);
1548                 return -ENODEV;
1549         }
1550
1551         return 0;
1552 }
1553
1554 static void __exit acpi_thermal_exit(void)
1555 {
1556
1557         acpi_bus_unregister_driver(&acpi_thermal_driver);
1558
1559         remove_proc_entry(ACPI_THERMAL_CLASS, acpi_root_dir);
1560
1561         return;
1562 }
1563
1564 module_init(acpi_thermal_init);
1565 module_exit(acpi_thermal_exit);