]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/acpi/thermal.c
Merge tag 'random_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso...
[karo-tx-linux.git] / 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/slab.h>
39 #include <linux/types.h>
40 #include <linux/jiffies.h>
41 #include <linux/kmod.h>
42 #include <linux/reboot.h>
43 #include <linux/device.h>
44 #include <asm/uaccess.h>
45 #include <linux/thermal.h>
46 #include <acpi/acpi_bus.h>
47 #include <acpi/acpi_drivers.h>
48
49 #define PREFIX "ACPI: "
50
51 #define ACPI_THERMAL_CLASS              "thermal_zone"
52 #define ACPI_THERMAL_DEVICE_NAME        "Thermal Zone"
53 #define ACPI_THERMAL_NOTIFY_TEMPERATURE 0x80
54 #define ACPI_THERMAL_NOTIFY_THRESHOLDS  0x81
55 #define ACPI_THERMAL_NOTIFY_DEVICES     0x82
56 #define ACPI_THERMAL_NOTIFY_CRITICAL    0xF0
57 #define ACPI_THERMAL_NOTIFY_HOT         0xF1
58 #define ACPI_THERMAL_MODE_ACTIVE        0x00
59
60 #define ACPI_THERMAL_MAX_ACTIVE 10
61 #define ACPI_THERMAL_MAX_LIMIT_STR_LEN 65
62
63 #define _COMPONENT              ACPI_THERMAL_COMPONENT
64 ACPI_MODULE_NAME("thermal");
65
66 MODULE_AUTHOR("Paul Diefenbaugh");
67 MODULE_DESCRIPTION("ACPI Thermal Zone Driver");
68 MODULE_LICENSE("GPL");
69
70 static int act;
71 module_param(act, int, 0644);
72 MODULE_PARM_DESC(act, "Disable or override all lowest active trip points.");
73
74 static int crt;
75 module_param(crt, int, 0644);
76 MODULE_PARM_DESC(crt, "Disable or lower all critical trip points.");
77
78 static int tzp;
79 module_param(tzp, int, 0444);
80 MODULE_PARM_DESC(tzp, "Thermal zone polling frequency, in 1/10 seconds.");
81
82 static int nocrt;
83 module_param(nocrt, int, 0);
84 MODULE_PARM_DESC(nocrt, "Set to take no action upon ACPI thermal zone critical trips points.");
85
86 static int off;
87 module_param(off, int, 0);
88 MODULE_PARM_DESC(off, "Set to disable ACPI thermal support.");
89
90 static int psv;
91 module_param(psv, int, 0644);
92 MODULE_PARM_DESC(psv, "Disable or override all passive trip points.");
93
94 static int acpi_thermal_add(struct acpi_device *device);
95 static int acpi_thermal_remove(struct acpi_device *device);
96 static void acpi_thermal_notify(struct acpi_device *device, u32 event);
97
98 static const struct acpi_device_id  thermal_device_ids[] = {
99         {ACPI_THERMAL_HID, 0},
100         {"", 0},
101 };
102 MODULE_DEVICE_TABLE(acpi, thermal_device_ids);
103
104 #ifdef CONFIG_PM_SLEEP
105 static int acpi_thermal_resume(struct device *dev);
106 #endif
107 static SIMPLE_DEV_PM_OPS(acpi_thermal_pm, NULL, acpi_thermal_resume);
108
109 static struct acpi_driver acpi_thermal_driver = {
110         .name = "thermal",
111         .class = ACPI_THERMAL_CLASS,
112         .ids = thermal_device_ids,
113         .ops = {
114                 .add = acpi_thermal_add,
115                 .remove = acpi_thermal_remove,
116                 .notify = acpi_thermal_notify,
117                 },
118         .drv.pm = &acpi_thermal_pm,
119 };
120
121 struct acpi_thermal_state {
122         u8 critical:1;
123         u8 hot:1;
124         u8 passive:1;
125         u8 active:1;
126         u8 reserved:4;
127         int active_index;
128 };
129
130 struct acpi_thermal_state_flags {
131         u8 valid:1;
132         u8 enabled:1;
133         u8 reserved:6;
134 };
135
136 struct acpi_thermal_critical {
137         struct acpi_thermal_state_flags flags;
138         unsigned long temperature;
139 };
140
141 struct acpi_thermal_hot {
142         struct acpi_thermal_state_flags flags;
143         unsigned long temperature;
144 };
145
146 struct acpi_thermal_passive {
147         struct acpi_thermal_state_flags flags;
148         unsigned long temperature;
149         unsigned long tc1;
150         unsigned long tc2;
151         unsigned long tsp;
152         struct acpi_handle_list devices;
153 };
154
155 struct acpi_thermal_active {
156         struct acpi_thermal_state_flags flags;
157         unsigned long temperature;
158         struct acpi_handle_list devices;
159 };
160
161 struct acpi_thermal_trips {
162         struct acpi_thermal_critical critical;
163         struct acpi_thermal_hot hot;
164         struct acpi_thermal_passive passive;
165         struct acpi_thermal_active active[ACPI_THERMAL_MAX_ACTIVE];
166 };
167
168 struct acpi_thermal_flags {
169         u8 cooling_mode:1;      /* _SCP */
170         u8 devices:1;           /* _TZD */
171         u8 reserved:6;
172 };
173
174 struct acpi_thermal {
175         struct acpi_device * device;
176         acpi_bus_id name;
177         unsigned long temperature;
178         unsigned long last_temperature;
179         unsigned long polling_frequency;
180         volatile u8 zombie;
181         struct acpi_thermal_flags flags;
182         struct acpi_thermal_state state;
183         struct acpi_thermal_trips trips;
184         struct acpi_handle_list devices;
185         struct thermal_zone_device *thermal_zone;
186         int tz_enabled;
187         int kelvin_offset;
188 };
189
190 /* --------------------------------------------------------------------------
191                              Thermal Zone Management
192    -------------------------------------------------------------------------- */
193
194 static int acpi_thermal_get_temperature(struct acpi_thermal *tz)
195 {
196         acpi_status status = AE_OK;
197         unsigned long long tmp;
198
199         if (!tz)
200                 return -EINVAL;
201
202         tz->last_temperature = tz->temperature;
203
204         status = acpi_evaluate_integer(tz->device->handle, "_TMP", NULL, &tmp);
205         if (ACPI_FAILURE(status))
206                 return -ENODEV;
207
208         tz->temperature = tmp;
209         ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Temperature is %lu dK\n",
210                           tz->temperature));
211
212         return 0;
213 }
214
215 static int acpi_thermal_get_polling_frequency(struct acpi_thermal *tz)
216 {
217         acpi_status status = AE_OK;
218         unsigned long long tmp;
219
220         if (!tz)
221                 return -EINVAL;
222
223         status = acpi_evaluate_integer(tz->device->handle, "_TZP", NULL, &tmp);
224         if (ACPI_FAILURE(status))
225                 return -ENODEV;
226
227         tz->polling_frequency = tmp;
228         ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Polling frequency is %lu dS\n",
229                           tz->polling_frequency));
230
231         return 0;
232 }
233
234 static int acpi_thermal_set_cooling_mode(struct acpi_thermal *tz, int mode)
235 {
236         if (!tz)
237                 return -EINVAL;
238
239         if (!acpi_has_method(tz->device->handle, "_SCP")) {
240                 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "_SCP not present\n"));
241                 return -ENODEV;
242         } else if (ACPI_FAILURE(acpi_execute_simple_method(tz->device->handle,
243                                                            "_SCP", mode))) {
244                 return -ENODEV;
245         }
246
247         return 0;
248 }
249
250 #define ACPI_TRIPS_CRITICAL     0x01
251 #define ACPI_TRIPS_HOT          0x02
252 #define ACPI_TRIPS_PASSIVE      0x04
253 #define ACPI_TRIPS_ACTIVE       0x08
254 #define ACPI_TRIPS_DEVICES      0x10
255
256 #define ACPI_TRIPS_REFRESH_THRESHOLDS   (ACPI_TRIPS_PASSIVE | ACPI_TRIPS_ACTIVE)
257 #define ACPI_TRIPS_REFRESH_DEVICES      ACPI_TRIPS_DEVICES
258
259 #define ACPI_TRIPS_INIT      (ACPI_TRIPS_CRITICAL | ACPI_TRIPS_HOT |    \
260                               ACPI_TRIPS_PASSIVE | ACPI_TRIPS_ACTIVE |  \
261                               ACPI_TRIPS_DEVICES)
262
263 /*
264  * This exception is thrown out in two cases:
265  * 1.An invalid trip point becomes invalid or a valid trip point becomes invalid
266  *   when re-evaluating the AML code.
267  * 2.TODO: Devices listed in _PSL, _ALx, _TZD may change.
268  *   We need to re-bind the cooling devices of a thermal zone when this occurs.
269  */
270 #define ACPI_THERMAL_TRIPS_EXCEPTION(flags, str)        \
271 do {    \
272         if (flags != ACPI_TRIPS_INIT)   \
273                 ACPI_EXCEPTION((AE_INFO, AE_ERROR,      \
274                 "ACPI thermal trip point %s changed\n"  \
275                 "Please send acpidump to linux-acpi@vger.kernel.org", str)); \
276 } while (0)
277
278 static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
279 {
280         acpi_status status = AE_OK;
281         unsigned long long tmp;
282         struct acpi_handle_list devices;
283         int valid = 0;
284         int i;
285
286         /* Critical Shutdown */
287         if (flag & ACPI_TRIPS_CRITICAL) {
288                 status = acpi_evaluate_integer(tz->device->handle,
289                                 "_CRT", NULL, &tmp);
290                 tz->trips.critical.temperature = tmp;
291                 /*
292                  * Treat freezing temperatures as invalid as well; some
293                  * BIOSes return really low values and cause reboots at startup.
294                  * Below zero (Celsius) values clearly aren't right for sure..
295                  * ... so lets discard those as invalid.
296                  */
297                 if (ACPI_FAILURE(status)) {
298                         tz->trips.critical.flags.valid = 0;
299                         ACPI_DEBUG_PRINT((ACPI_DB_INFO,
300                                           "No critical threshold\n"));
301                 } else if (tmp <= 2732) {
302                         printk(KERN_WARNING FW_BUG "Invalid critical threshold "
303                                "(%llu)\n", tmp);
304                         tz->trips.critical.flags.valid = 0;
305                 } else {
306                         tz->trips.critical.flags.valid = 1;
307                         ACPI_DEBUG_PRINT((ACPI_DB_INFO,
308                                           "Found critical threshold [%lu]\n",
309                                           tz->trips.critical.temperature));
310                 }
311                 if (tz->trips.critical.flags.valid == 1) {
312                         if (crt == -1) {
313                                 tz->trips.critical.flags.valid = 0;
314                         } else if (crt > 0) {
315                                 unsigned long crt_k = CELSIUS_TO_KELVIN(crt);
316                                 /*
317                                  * Allow override critical threshold
318                                  */
319                                 if (crt_k > tz->trips.critical.temperature)
320                                         printk(KERN_WARNING PREFIX
321                                                 "Critical threshold %d C\n", crt);
322                                 tz->trips.critical.temperature = crt_k;
323                         }
324                 }
325         }
326
327         /* Critical Sleep (optional) */
328         if (flag & ACPI_TRIPS_HOT) {
329                 status = acpi_evaluate_integer(tz->device->handle,
330                                 "_HOT", NULL, &tmp);
331                 if (ACPI_FAILURE(status)) {
332                         tz->trips.hot.flags.valid = 0;
333                         ACPI_DEBUG_PRINT((ACPI_DB_INFO,
334                                         "No hot threshold\n"));
335                 } else {
336                         tz->trips.hot.temperature = tmp;
337                         tz->trips.hot.flags.valid = 1;
338                         ACPI_DEBUG_PRINT((ACPI_DB_INFO,
339                                         "Found hot threshold [%lu]\n",
340                                         tz->trips.critical.temperature));
341                 }
342         }
343
344         /* Passive (optional) */
345         if (((flag & ACPI_TRIPS_PASSIVE) && tz->trips.passive.flags.valid) ||
346                 (flag == ACPI_TRIPS_INIT)) {
347                 valid = tz->trips.passive.flags.valid;
348                 if (psv == -1) {
349                         status = AE_SUPPORT;
350                 } else if (psv > 0) {
351                         tmp = CELSIUS_TO_KELVIN(psv);
352                         status = AE_OK;
353                 } else {
354                         status = acpi_evaluate_integer(tz->device->handle,
355                                 "_PSV", NULL, &tmp);
356                 }
357
358                 if (ACPI_FAILURE(status))
359                         tz->trips.passive.flags.valid = 0;
360                 else {
361                         tz->trips.passive.temperature = tmp;
362                         tz->trips.passive.flags.valid = 1;
363                         if (flag == ACPI_TRIPS_INIT) {
364                                 status = acpi_evaluate_integer(
365                                                 tz->device->handle, "_TC1",
366                                                 NULL, &tmp);
367                                 if (ACPI_FAILURE(status))
368                                         tz->trips.passive.flags.valid = 0;
369                                 else
370                                         tz->trips.passive.tc1 = tmp;
371                                 status = acpi_evaluate_integer(
372                                                 tz->device->handle, "_TC2",
373                                                 NULL, &tmp);
374                                 if (ACPI_FAILURE(status))
375                                         tz->trips.passive.flags.valid = 0;
376                                 else
377                                         tz->trips.passive.tc2 = tmp;
378                                 status = acpi_evaluate_integer(
379                                                 tz->device->handle, "_TSP",
380                                                 NULL, &tmp);
381                                 if (ACPI_FAILURE(status))
382                                         tz->trips.passive.flags.valid = 0;
383                                 else
384                                         tz->trips.passive.tsp = tmp;
385                         }
386                 }
387         }
388         if ((flag & ACPI_TRIPS_DEVICES) && tz->trips.passive.flags.valid) {
389                 memset(&devices, 0, sizeof(struct acpi_handle_list));
390                 status = acpi_evaluate_reference(tz->device->handle, "_PSL",
391                                                         NULL, &devices);
392                 if (ACPI_FAILURE(status)) {
393                         printk(KERN_WARNING PREFIX
394                                 "Invalid passive threshold\n");
395                         tz->trips.passive.flags.valid = 0;
396                 }
397                 else
398                         tz->trips.passive.flags.valid = 1;
399
400                 if (memcmp(&tz->trips.passive.devices, &devices,
401                                 sizeof(struct acpi_handle_list))) {
402                         memcpy(&tz->trips.passive.devices, &devices,
403                                 sizeof(struct acpi_handle_list));
404                         ACPI_THERMAL_TRIPS_EXCEPTION(flag, "device");
405                 }
406         }
407         if ((flag & ACPI_TRIPS_PASSIVE) || (flag & ACPI_TRIPS_DEVICES)) {
408                 if (valid != tz->trips.passive.flags.valid)
409                                 ACPI_THERMAL_TRIPS_EXCEPTION(flag, "state");
410         }
411
412         /* Active (optional) */
413         for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
414                 char name[5] = { '_', 'A', 'C', ('0' + i), '\0' };
415                 valid = tz->trips.active[i].flags.valid;
416
417                 if (act == -1)
418                         break; /* disable all active trip points */
419
420                 if ((flag == ACPI_TRIPS_INIT) || ((flag & ACPI_TRIPS_ACTIVE) &&
421                         tz->trips.active[i].flags.valid)) {
422                         status = acpi_evaluate_integer(tz->device->handle,
423                                                         name, NULL, &tmp);
424                         if (ACPI_FAILURE(status)) {
425                                 tz->trips.active[i].flags.valid = 0;
426                                 if (i == 0)
427                                         break;
428                                 if (act <= 0)
429                                         break;
430                                 if (i == 1)
431                                         tz->trips.active[0].temperature =
432                                                 CELSIUS_TO_KELVIN(act);
433                                 else
434                                         /*
435                                          * Don't allow override higher than
436                                          * the next higher trip point
437                                          */
438                                         tz->trips.active[i - 1].temperature =
439                                                 (tz->trips.active[i - 2].temperature <
440                                                 CELSIUS_TO_KELVIN(act) ?
441                                                 tz->trips.active[i - 2].temperature :
442                                                 CELSIUS_TO_KELVIN(act));
443                                 break;
444                         } else {
445                                 tz->trips.active[i].temperature = tmp;
446                                 tz->trips.active[i].flags.valid = 1;
447                         }
448                 }
449
450                 name[2] = 'L';
451                 if ((flag & ACPI_TRIPS_DEVICES) && tz->trips.active[i].flags.valid ) {
452                         memset(&devices, 0, sizeof(struct acpi_handle_list));
453                         status = acpi_evaluate_reference(tz->device->handle,
454                                                 name, NULL, &devices);
455                         if (ACPI_FAILURE(status)) {
456                                 printk(KERN_WARNING PREFIX
457                                         "Invalid active%d threshold\n", i);
458                                 tz->trips.active[i].flags.valid = 0;
459                         }
460                         else
461                                 tz->trips.active[i].flags.valid = 1;
462
463                         if (memcmp(&tz->trips.active[i].devices, &devices,
464                                         sizeof(struct acpi_handle_list))) {
465                                 memcpy(&tz->trips.active[i].devices, &devices,
466                                         sizeof(struct acpi_handle_list));
467                                 ACPI_THERMAL_TRIPS_EXCEPTION(flag, "device");
468                         }
469                 }
470                 if ((flag & ACPI_TRIPS_ACTIVE) || (flag & ACPI_TRIPS_DEVICES))
471                         if (valid != tz->trips.active[i].flags.valid)
472                                 ACPI_THERMAL_TRIPS_EXCEPTION(flag, "state");
473
474                 if (!tz->trips.active[i].flags.valid)
475                         break;
476         }
477
478         if ((flag & ACPI_TRIPS_DEVICES)
479             && acpi_has_method(tz->device->handle, "_TZD")) {
480                 memset(&devices, 0, sizeof(devices));
481                 status = acpi_evaluate_reference(tz->device->handle, "_TZD",
482                                                 NULL, &devices);
483                 if (ACPI_SUCCESS(status)
484                     && memcmp(&tz->devices, &devices, sizeof(devices))) {
485                         tz->devices = devices;
486                         ACPI_THERMAL_TRIPS_EXCEPTION(flag, "device");
487                 }
488         }
489
490         return 0;
491 }
492
493 static int acpi_thermal_get_trip_points(struct acpi_thermal *tz)
494 {
495         int i, valid, ret = acpi_thermal_trips_update(tz, ACPI_TRIPS_INIT);
496
497         if (ret)
498                 return ret;
499
500         valid = tz->trips.critical.flags.valid |
501                 tz->trips.hot.flags.valid |
502                 tz->trips.passive.flags.valid;
503
504         for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++)
505                 valid |= tz->trips.active[i].flags.valid;
506
507         if (!valid) {
508                 printk(KERN_WARNING FW_BUG "No valid trip found\n");
509                 return -ENODEV;
510         }
511         return 0;
512 }
513
514 static void acpi_thermal_check(void *data)
515 {
516         struct acpi_thermal *tz = data;
517
518         if (!tz->tz_enabled) {
519                 pr_warn("thermal zone is disabled \n");
520                 return;
521         }
522         thermal_zone_device_update(tz->thermal_zone);
523 }
524
525 /* sys I/F for generic thermal sysfs support */
526 #define KELVIN_TO_MILLICELSIUS(t, off) (((t) - (off)) * 100)
527
528 static int thermal_get_temp(struct thermal_zone_device *thermal,
529                             unsigned long *temp)
530 {
531         struct acpi_thermal *tz = thermal->devdata;
532         int result;
533
534         if (!tz)
535                 return -EINVAL;
536
537         result = acpi_thermal_get_temperature(tz);
538         if (result)
539                 return result;
540
541         *temp = KELVIN_TO_MILLICELSIUS(tz->temperature, tz->kelvin_offset);
542         return 0;
543 }
544
545 static int thermal_get_mode(struct thermal_zone_device *thermal,
546                                 enum thermal_device_mode *mode)
547 {
548         struct acpi_thermal *tz = thermal->devdata;
549
550         if (!tz)
551                 return -EINVAL;
552
553         *mode = tz->tz_enabled ? THERMAL_DEVICE_ENABLED :
554                 THERMAL_DEVICE_DISABLED;
555
556         return 0;
557 }
558
559 static int thermal_set_mode(struct thermal_zone_device *thermal,
560                                 enum thermal_device_mode mode)
561 {
562         struct acpi_thermal *tz = thermal->devdata;
563         int enable;
564
565         if (!tz)
566                 return -EINVAL;
567
568         /*
569          * enable/disable thermal management from ACPI thermal driver
570          */
571         if (mode == THERMAL_DEVICE_ENABLED)
572                 enable = 1;
573         else if (mode == THERMAL_DEVICE_DISABLED)
574                 enable = 0;
575         else
576                 return -EINVAL;
577
578         if (enable != tz->tz_enabled) {
579                 tz->tz_enabled = enable;
580                 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
581                         "%s kernel ACPI thermal control\n",
582                         tz->tz_enabled ? "Enable" : "Disable"));
583                 acpi_thermal_check(tz);
584         }
585         return 0;
586 }
587
588 static int thermal_get_trip_type(struct thermal_zone_device *thermal,
589                                  int trip, enum thermal_trip_type *type)
590 {
591         struct acpi_thermal *tz = thermal->devdata;
592         int i;
593
594         if (!tz || trip < 0)
595                 return -EINVAL;
596
597         if (tz->trips.critical.flags.valid) {
598                 if (!trip) {
599                         *type = THERMAL_TRIP_CRITICAL;
600                         return 0;
601                 }
602                 trip--;
603         }
604
605         if (tz->trips.hot.flags.valid) {
606                 if (!trip) {
607                         *type = THERMAL_TRIP_HOT;
608                         return 0;
609                 }
610                 trip--;
611         }
612
613         if (tz->trips.passive.flags.valid) {
614                 if (!trip) {
615                         *type = THERMAL_TRIP_PASSIVE;
616                         return 0;
617                 }
618                 trip--;
619         }
620
621         for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE &&
622                 tz->trips.active[i].flags.valid; i++) {
623                 if (!trip) {
624                         *type = THERMAL_TRIP_ACTIVE;
625                         return 0;
626                 }
627                 trip--;
628         }
629
630         return -EINVAL;
631 }
632
633 static int thermal_get_trip_temp(struct thermal_zone_device *thermal,
634                                  int trip, unsigned long *temp)
635 {
636         struct acpi_thermal *tz = thermal->devdata;
637         int i;
638
639         if (!tz || trip < 0)
640                 return -EINVAL;
641
642         if (tz->trips.critical.flags.valid) {
643                 if (!trip) {
644                         *temp = KELVIN_TO_MILLICELSIUS(
645                                 tz->trips.critical.temperature,
646                                 tz->kelvin_offset);
647                         return 0;
648                 }
649                 trip--;
650         }
651
652         if (tz->trips.hot.flags.valid) {
653                 if (!trip) {
654                         *temp = KELVIN_TO_MILLICELSIUS(
655                                 tz->trips.hot.temperature,
656                                 tz->kelvin_offset);
657                         return 0;
658                 }
659                 trip--;
660         }
661
662         if (tz->trips.passive.flags.valid) {
663                 if (!trip) {
664                         *temp = KELVIN_TO_MILLICELSIUS(
665                                 tz->trips.passive.temperature,
666                                 tz->kelvin_offset);
667                         return 0;
668                 }
669                 trip--;
670         }
671
672         for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE &&
673                 tz->trips.active[i].flags.valid; i++) {
674                 if (!trip) {
675                         *temp = KELVIN_TO_MILLICELSIUS(
676                                 tz->trips.active[i].temperature,
677                                 tz->kelvin_offset);
678                         return 0;
679                 }
680                 trip--;
681         }
682
683         return -EINVAL;
684 }
685
686 static int thermal_get_crit_temp(struct thermal_zone_device *thermal,
687                                 unsigned long *temperature) {
688         struct acpi_thermal *tz = thermal->devdata;
689
690         if (tz->trips.critical.flags.valid) {
691                 *temperature = KELVIN_TO_MILLICELSIUS(
692                                 tz->trips.critical.temperature,
693                                 tz->kelvin_offset);
694                 return 0;
695         } else
696                 return -EINVAL;
697 }
698
699 static int thermal_get_trend(struct thermal_zone_device *thermal,
700                                 int trip, enum thermal_trend *trend)
701 {
702         struct acpi_thermal *tz = thermal->devdata;
703         enum thermal_trip_type type;
704         int i;
705
706         if (thermal_get_trip_type(thermal, trip, &type))
707                 return -EINVAL;
708
709         if (type == THERMAL_TRIP_ACTIVE) {
710                 unsigned long trip_temp;
711                 unsigned long temp = KELVIN_TO_MILLICELSIUS(tz->temperature,
712                                                         tz->kelvin_offset);
713                 if (thermal_get_trip_temp(thermal, trip, &trip_temp))
714                         return -EINVAL;
715
716                 if (temp > trip_temp) {
717                         *trend = THERMAL_TREND_RAISING;
718                         return 0;
719                 } else {
720                         /* Fall back on default trend */
721                         return -EINVAL;
722                 }
723         }
724
725         /*
726          * tz->temperature has already been updated by generic thermal layer,
727          * before this callback being invoked
728          */
729         i = (tz->trips.passive.tc1 * (tz->temperature - tz->last_temperature))
730                 + (tz->trips.passive.tc2
731                 * (tz->temperature - tz->trips.passive.temperature));
732
733         if (i > 0)
734                 *trend = THERMAL_TREND_RAISING;
735         else if (i < 0)
736                 *trend = THERMAL_TREND_DROPPING;
737         else
738                 *trend = THERMAL_TREND_STABLE;
739         return 0;
740 }
741
742
743 static int thermal_notify(struct thermal_zone_device *thermal, int trip,
744                            enum thermal_trip_type trip_type)
745 {
746         u8 type = 0;
747         struct acpi_thermal *tz = thermal->devdata;
748
749         if (trip_type == THERMAL_TRIP_CRITICAL)
750                 type = ACPI_THERMAL_NOTIFY_CRITICAL;
751         else if (trip_type == THERMAL_TRIP_HOT)
752                 type = ACPI_THERMAL_NOTIFY_HOT;
753         else
754                 return 0;
755
756         acpi_bus_generate_netlink_event(tz->device->pnp.device_class,
757                                         dev_name(&tz->device->dev), type, 1);
758
759         if (trip_type == THERMAL_TRIP_CRITICAL && nocrt)
760                 return 1;
761
762         return 0;
763 }
764
765 static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal,
766                                         struct thermal_cooling_device *cdev,
767                                         bool bind)
768 {
769         struct acpi_device *device = cdev->devdata;
770         struct acpi_thermal *tz = thermal->devdata;
771         struct acpi_device *dev;
772         acpi_status status;
773         acpi_handle handle;
774         int i;
775         int j;
776         int trip = -1;
777         int result = 0;
778
779         if (tz->trips.critical.flags.valid)
780                 trip++;
781
782         if (tz->trips.hot.flags.valid)
783                 trip++;
784
785         if (tz->trips.passive.flags.valid) {
786                 trip++;
787                 for (i = 0; i < tz->trips.passive.devices.count;
788                     i++) {
789                         handle = tz->trips.passive.devices.handles[i];
790                         status = acpi_bus_get_device(handle, &dev);
791                         if (ACPI_FAILURE(status) || dev != device)
792                                 continue;
793                         if (bind)
794                                 result =
795                                         thermal_zone_bind_cooling_device
796                                         (thermal, trip, cdev,
797                                          THERMAL_NO_LIMIT, THERMAL_NO_LIMIT);
798                         else
799                                 result =
800                                         thermal_zone_unbind_cooling_device
801                                         (thermal, trip, cdev);
802                         if (result)
803                                 goto failed;
804                 }
805         }
806
807         for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
808                 if (!tz->trips.active[i].flags.valid)
809                         break;
810                 trip++;
811                 for (j = 0;
812                     j < tz->trips.active[i].devices.count;
813                     j++) {
814                         handle = tz->trips.active[i].devices.handles[j];
815                         status = acpi_bus_get_device(handle, &dev);
816                         if (ACPI_FAILURE(status) || dev != device)
817                                 continue;
818                         if (bind)
819                                 result = thermal_zone_bind_cooling_device
820                                         (thermal, trip, cdev,
821                                          THERMAL_NO_LIMIT, THERMAL_NO_LIMIT);
822                         else
823                                 result = thermal_zone_unbind_cooling_device
824                                         (thermal, trip, cdev);
825                         if (result)
826                                 goto failed;
827                 }
828         }
829
830         for (i = 0; i < tz->devices.count; i++) {
831                 handle = tz->devices.handles[i];
832                 status = acpi_bus_get_device(handle, &dev);
833                 if (ACPI_SUCCESS(status) && (dev == device)) {
834                         if (bind)
835                                 result = thermal_zone_bind_cooling_device
836                                                 (thermal, THERMAL_TRIPS_NONE,
837                                                  cdev, THERMAL_NO_LIMIT,
838                                                  THERMAL_NO_LIMIT);
839                         else
840                                 result = thermal_zone_unbind_cooling_device
841                                                 (thermal, THERMAL_TRIPS_NONE,
842                                                  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, true);
857 }
858
859 static int
860 acpi_thermal_unbind_cooling_device(struct thermal_zone_device *thermal,
861                                         struct thermal_cooling_device *cdev)
862 {
863         return acpi_thermal_cooling_device_cb(thermal, cdev, false);
864 }
865
866 static const struct thermal_zone_device_ops acpi_thermal_zone_ops = {
867         .bind = acpi_thermal_bind_cooling_device,
868         .unbind = acpi_thermal_unbind_cooling_device,
869         .get_temp = thermal_get_temp,
870         .get_mode = thermal_get_mode,
871         .set_mode = thermal_set_mode,
872         .get_trip_type = thermal_get_trip_type,
873         .get_trip_temp = thermal_get_trip_temp,
874         .get_crit_temp = thermal_get_crit_temp,
875         .get_trend = thermal_get_trend,
876         .notify = thermal_notify,
877 };
878
879 static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz)
880 {
881         int trips = 0;
882         int result;
883         acpi_status status;
884         int i;
885
886         if (tz->trips.critical.flags.valid)
887                 trips++;
888
889         if (tz->trips.hot.flags.valid)
890                 trips++;
891
892         if (tz->trips.passive.flags.valid)
893                 trips++;
894
895         for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE &&
896                         tz->trips.active[i].flags.valid; i++, trips++);
897
898         if (tz->trips.passive.flags.valid)
899                 tz->thermal_zone =
900                         thermal_zone_device_register("acpitz", trips, 0, tz,
901                                                 &acpi_thermal_zone_ops, NULL,
902                                                      tz->trips.passive.tsp*100,
903                                                      tz->polling_frequency*100);
904         else
905                 tz->thermal_zone =
906                         thermal_zone_device_register("acpitz", trips, 0, tz,
907                                                 &acpi_thermal_zone_ops, NULL,
908                                                 0, tz->polling_frequency*100);
909         if (IS_ERR(tz->thermal_zone))
910                 return -ENODEV;
911
912         result = sysfs_create_link(&tz->device->dev.kobj,
913                                    &tz->thermal_zone->device.kobj, "thermal_zone");
914         if (result)
915                 return result;
916
917         result = sysfs_create_link(&tz->thermal_zone->device.kobj,
918                                    &tz->device->dev.kobj, "device");
919         if (result)
920                 return result;
921
922         status = acpi_attach_data(tz->device->handle,
923                                   acpi_bus_private_data_handler,
924                                   tz->thermal_zone);
925         if (ACPI_FAILURE(status)) {
926                 printk(KERN_ERR PREFIX
927                                 "Error attaching device data\n");
928                 return -ENODEV;
929         }
930
931         tz->tz_enabled = 1;
932
933         dev_info(&tz->device->dev, "registered as thermal_zone%d\n",
934                  tz->thermal_zone->id);
935         return 0;
936 }
937
938 static void acpi_thermal_unregister_thermal_zone(struct acpi_thermal *tz)
939 {
940         sysfs_remove_link(&tz->device->dev.kobj, "thermal_zone");
941         sysfs_remove_link(&tz->thermal_zone->device.kobj, "device");
942         thermal_zone_device_unregister(tz->thermal_zone);
943         tz->thermal_zone = NULL;
944         acpi_detach_data(tz->device->handle, acpi_bus_private_data_handler);
945 }
946
947
948 /* --------------------------------------------------------------------------
949                                  Driver Interface
950    -------------------------------------------------------------------------- */
951
952 static void acpi_thermal_notify(struct acpi_device *device, u32 event)
953 {
954         struct acpi_thermal *tz = acpi_driver_data(device);
955
956
957         if (!tz)
958                 return;
959
960         switch (event) {
961         case ACPI_THERMAL_NOTIFY_TEMPERATURE:
962                 acpi_thermal_check(tz);
963                 break;
964         case ACPI_THERMAL_NOTIFY_THRESHOLDS:
965                 acpi_thermal_trips_update(tz, ACPI_TRIPS_REFRESH_THRESHOLDS);
966                 acpi_thermal_check(tz);
967                 acpi_bus_generate_netlink_event(device->pnp.device_class,
968                                                   dev_name(&device->dev), event, 0);
969                 break;
970         case ACPI_THERMAL_NOTIFY_DEVICES:
971                 acpi_thermal_trips_update(tz, ACPI_TRIPS_REFRESH_DEVICES);
972                 acpi_thermal_check(tz);
973                 acpi_bus_generate_netlink_event(device->pnp.device_class,
974                                                   dev_name(&device->dev), event, 0);
975                 break;
976         default:
977                 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
978                                   "Unsupported event [0x%x]\n", event));
979                 break;
980         }
981 }
982
983 /*
984  * On some platforms, the AML code has dependency about
985  * the evaluating order of _TMP and _CRT/_HOT/_PSV/_ACx.
986  * 1. On HP Pavilion G4-1016tx, _TMP must be invoked after
987  *    /_CRT/_HOT/_PSV/_ACx, or else system will be power off.
988  * 2. On HP Compaq 6715b/6715s, the return value of _PSV is 0
989  *    if _TMP has never been evaluated.
990  *
991  * As this dependency is totally transparent to OS, evaluate
992  * all of them once, in the order of _CRT/_HOT/_PSV/_ACx,
993  * _TMP, before they are actually used.
994  */
995 static void acpi_thermal_aml_dependency_fix(struct acpi_thermal *tz)
996 {
997         acpi_handle handle = tz->device->handle;
998         unsigned long long value;
999         int i;
1000
1001         acpi_evaluate_integer(handle, "_CRT", NULL, &value);
1002         acpi_evaluate_integer(handle, "_HOT", NULL, &value);
1003         acpi_evaluate_integer(handle, "_PSV", NULL, &value);
1004         for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
1005                 char name[5] = { '_', 'A', 'C', ('0' + i), '\0' };
1006                 acpi_status status;
1007
1008                 status = acpi_evaluate_integer(handle, name, NULL, &value);
1009                 if (status == AE_NOT_FOUND)
1010                         break;
1011         }
1012         acpi_evaluate_integer(handle, "_TMP", NULL, &value);
1013 }
1014
1015 static int acpi_thermal_get_info(struct acpi_thermal *tz)
1016 {
1017         int result = 0;
1018
1019
1020         if (!tz)
1021                 return -EINVAL;
1022
1023         acpi_thermal_aml_dependency_fix(tz);
1024
1025         /* Get trip points [_CRT, _PSV, etc.] (required) */
1026         result = acpi_thermal_get_trip_points(tz);
1027         if (result)
1028                 return result;
1029
1030         /* Get temperature [_TMP] (required) */
1031         result = acpi_thermal_get_temperature(tz);
1032         if (result)
1033                 return result;
1034
1035         /* Set the cooling mode [_SCP] to active cooling (default) */
1036         result = acpi_thermal_set_cooling_mode(tz, ACPI_THERMAL_MODE_ACTIVE);
1037         if (!result)
1038                 tz->flags.cooling_mode = 1;
1039
1040         /* Get default polling frequency [_TZP] (optional) */
1041         if (tzp)
1042                 tz->polling_frequency = tzp;
1043         else
1044                 acpi_thermal_get_polling_frequency(tz);
1045
1046         return 0;
1047 }
1048
1049 /*
1050  * The exact offset between Kelvin and degree Celsius is 273.15. However ACPI
1051  * handles temperature values with a single decimal place. As a consequence,
1052  * some implementations use an offset of 273.1 and others use an offset of
1053  * 273.2. Try to find out which one is being used, to present the most
1054  * accurate and visually appealing number.
1055  *
1056  * The heuristic below should work for all ACPI thermal zones which have a
1057  * critical trip point with a value being a multiple of 0.5 degree Celsius.
1058  */
1059 static void acpi_thermal_guess_offset(struct acpi_thermal *tz)
1060 {
1061         if (tz->trips.critical.flags.valid &&
1062             (tz->trips.critical.temperature % 5) == 1)
1063                 tz->kelvin_offset = 2731;
1064         else
1065                 tz->kelvin_offset = 2732;
1066 }
1067
1068 static int acpi_thermal_add(struct acpi_device *device)
1069 {
1070         int result = 0;
1071         struct acpi_thermal *tz = NULL;
1072
1073
1074         if (!device)
1075                 return -EINVAL;
1076
1077         tz = kzalloc(sizeof(struct acpi_thermal), GFP_KERNEL);
1078         if (!tz)
1079                 return -ENOMEM;
1080
1081         tz->device = device;
1082         strcpy(tz->name, device->pnp.bus_id);
1083         strcpy(acpi_device_name(device), ACPI_THERMAL_DEVICE_NAME);
1084         strcpy(acpi_device_class(device), ACPI_THERMAL_CLASS);
1085         device->driver_data = tz;
1086
1087         result = acpi_thermal_get_info(tz);
1088         if (result)
1089                 goto free_memory;
1090
1091         acpi_thermal_guess_offset(tz);
1092
1093         result = acpi_thermal_register_thermal_zone(tz);
1094         if (result)
1095                 goto free_memory;
1096
1097         printk(KERN_INFO PREFIX "%s [%s] (%ld C)\n",
1098                acpi_device_name(device), acpi_device_bid(device),
1099                KELVIN_TO_CELSIUS(tz->temperature));
1100         goto end;
1101
1102 free_memory:
1103         kfree(tz);
1104 end:
1105         return result;
1106 }
1107
1108 static int acpi_thermal_remove(struct acpi_device *device)
1109 {
1110         struct acpi_thermal *tz = NULL;
1111
1112         if (!device || !acpi_driver_data(device))
1113                 return -EINVAL;
1114
1115         tz = acpi_driver_data(device);
1116
1117         acpi_thermal_unregister_thermal_zone(tz);
1118         kfree(tz);
1119         return 0;
1120 }
1121
1122 #ifdef CONFIG_PM_SLEEP
1123 static int acpi_thermal_resume(struct device *dev)
1124 {
1125         struct acpi_thermal *tz;
1126         int i, j, power_state, result;
1127
1128         if (!dev)
1129                 return -EINVAL;
1130
1131         tz = acpi_driver_data(to_acpi_device(dev));
1132         if (!tz)
1133                 return -EINVAL;
1134
1135         for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
1136                 if (!(&tz->trips.active[i]))
1137                         break;
1138                 if (!tz->trips.active[i].flags.valid)
1139                         break;
1140                 tz->trips.active[i].flags.enabled = 1;
1141                 for (j = 0; j < tz->trips.active[i].devices.count; j++) {
1142                         result = acpi_bus_update_power(
1143                                         tz->trips.active[i].devices.handles[j],
1144                                         &power_state);
1145                         if (result || (power_state != ACPI_STATE_D0)) {
1146                                 tz->trips.active[i].flags.enabled = 0;
1147                                 break;
1148                         }
1149                 }
1150                 tz->state.active |= tz->trips.active[i].flags.enabled;
1151         }
1152
1153         acpi_thermal_check(tz);
1154
1155         return AE_OK;
1156 }
1157 #endif
1158
1159 static int thermal_act(const struct dmi_system_id *d) {
1160
1161         if (act == 0) {
1162                 printk(KERN_NOTICE "ACPI: %s detected: "
1163                         "disabling all active thermal trip points\n", d->ident);
1164                 act = -1;
1165         }
1166         return 0;
1167 }
1168 static int thermal_nocrt(const struct dmi_system_id *d) {
1169
1170         printk(KERN_NOTICE "ACPI: %s detected: "
1171                 "disabling all critical thermal trip point actions.\n", d->ident);
1172         nocrt = 1;
1173         return 0;
1174 }
1175 static int thermal_tzp(const struct dmi_system_id *d) {
1176
1177         if (tzp == 0) {
1178                 printk(KERN_NOTICE "ACPI: %s detected: "
1179                         "enabling thermal zone polling\n", d->ident);
1180                 tzp = 300;      /* 300 dS = 30 Seconds */
1181         }
1182         return 0;
1183 }
1184 static int thermal_psv(const struct dmi_system_id *d) {
1185
1186         if (psv == 0) {
1187                 printk(KERN_NOTICE "ACPI: %s detected: "
1188                         "disabling all passive thermal trip points\n", d->ident);
1189                 psv = -1;
1190         }
1191         return 0;
1192 }
1193
1194 static struct dmi_system_id thermal_dmi_table[] __initdata = {
1195         /*
1196          * Award BIOS on this AOpen makes thermal control almost worthless.
1197          * http://bugzilla.kernel.org/show_bug.cgi?id=8842
1198          */
1199         {
1200          .callback = thermal_act,
1201          .ident = "AOpen i915GMm-HFS",
1202          .matches = {
1203                 DMI_MATCH(DMI_BOARD_VENDOR, "AOpen"),
1204                 DMI_MATCH(DMI_BOARD_NAME, "i915GMm-HFS"),
1205                 },
1206         },
1207         {
1208          .callback = thermal_psv,
1209          .ident = "AOpen i915GMm-HFS",
1210          .matches = {
1211                 DMI_MATCH(DMI_BOARD_VENDOR, "AOpen"),
1212                 DMI_MATCH(DMI_BOARD_NAME, "i915GMm-HFS"),
1213                 },
1214         },
1215         {
1216          .callback = thermal_tzp,
1217          .ident = "AOpen i915GMm-HFS",
1218          .matches = {
1219                 DMI_MATCH(DMI_BOARD_VENDOR, "AOpen"),
1220                 DMI_MATCH(DMI_BOARD_NAME, "i915GMm-HFS"),
1221                 },
1222         },
1223         {
1224          .callback = thermal_nocrt,
1225          .ident = "Gigabyte GA-7ZX",
1226          .matches = {
1227                 DMI_MATCH(DMI_BOARD_VENDOR, "Gigabyte Technology Co., Ltd."),
1228                 DMI_MATCH(DMI_BOARD_NAME, "7ZX"),
1229                 },
1230         },
1231         {}
1232 };
1233
1234 static int __init acpi_thermal_init(void)
1235 {
1236         int result = 0;
1237
1238         dmi_check_system(thermal_dmi_table);
1239
1240         if (off) {
1241                 printk(KERN_NOTICE "ACPI: thermal control disabled\n");
1242                 return -ENODEV;
1243         }
1244
1245         result = acpi_bus_register_driver(&acpi_thermal_driver);
1246         if (result < 0)
1247                 return -ENODEV;
1248
1249         return 0;
1250 }
1251
1252 static void __exit acpi_thermal_exit(void)
1253 {
1254
1255         acpi_bus_unregister_driver(&acpi_thermal_driver);
1256
1257         return;
1258 }
1259
1260 module_init(acpi_thermal_init);
1261 module_exit(acpi_thermal_exit);