Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
[safe/jmp/linux-2.6] / drivers / acpi / thermal.c
index d0b44ce..84c795f 100644 (file)
 
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/dmi.h>
 #include <linux/init.h>
 #include <linux/types.h>
 #include <linux/proc_fs.h>
-#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/jiffies.h>
 #include <linux/kmod.h>
 #include <linux/seq_file.h>
+#include <linux/reboot.h>
 #include <asm/uaccess.h>
-
+#include <linux/thermal.h>
 #include <acpi/acpi_bus.h>
 #include <acpi/acpi_drivers.h>
 
 #define ACPI_THERMAL_COMPONENT         0x04000000
 #define ACPI_THERMAL_CLASS             "thermal_zone"
-#define ACPI_THERMAL_DRIVER_NAME       "ACPI Thermal Zone Driver"
 #define ACPI_THERMAL_DEVICE_NAME       "Thermal Zone"
 #define ACPI_THERMAL_FILE_STATE                "state"
 #define ACPI_THERMAL_FILE_TEMPERATURE  "temperature"
 #define ACPI_THERMAL_NOTIFY_CRITICAL   0xF0
 #define ACPI_THERMAL_NOTIFY_HOT                0xF1
 #define ACPI_THERMAL_MODE_ACTIVE       0x00
-#define ACPI_THERMAL_MODE_PASSIVE      0x01
-#define ACPI_THERMAL_MODE_CRITICAL     0xff
-#define ACPI_THERMAL_PATH_POWEROFF     "/sbin/poweroff"
 
 #define ACPI_THERMAL_MAX_ACTIVE        10
 #define ACPI_THERMAL_MAX_LIMIT_STR_LEN 65
 
-#define KELVIN_TO_CELSIUS(t)    (long)(((long)t-2732>=0) ? ((long)t-2732+5)/10 : ((long)t-2732-5)/10)
-#define CELSIUS_TO_KELVIN(t)   ((t+273)*10)
-
 #define _COMPONENT             ACPI_THERMAL_COMPONENT
-ACPI_MODULE_NAME("acpi_thermal")
+ACPI_MODULE_NAME("thermal");
 
 MODULE_AUTHOR("Paul Diefenbaugh");
-MODULE_DESCRIPTION(ACPI_THERMAL_DRIVER_NAME);
+MODULE_DESCRIPTION("ACPI Thermal Zone Driver");
 MODULE_LICENSE("GPL");
 
+static int act;
+module_param(act, int, 0644);
+MODULE_PARM_DESC(act, "Disable or override all lowest active trip points.");
+
+static int crt;
+module_param(crt, int, 0644);
+MODULE_PARM_DESC(crt, "Disable or lower all critical trip points.");
+
 static int tzp;
-module_param(tzp, int, 0);
-MODULE_PARM_DESC(tzp, "Thermal zone polling frequency, in 1/10 seconds.\n");
+module_param(tzp, int, 0444);
+MODULE_PARM_DESC(tzp, "Thermal zone polling frequency, in 1/10 seconds.");
+
+static int nocrt;
+module_param(nocrt, int, 0);
+MODULE_PARM_DESC(nocrt, "Set to take no action upon ACPI thermal zone critical trips points.");
+
+static int off;
+module_param(off, int, 0);
+MODULE_PARM_DESC(off, "Set to disable ACPI thermal support.");
+
+static int psv;
+module_param(psv, int, 0644);
+MODULE_PARM_DESC(psv, "Disable or override all passive trip points.");
 
 static int acpi_thermal_add(struct acpi_device *device);
 static int acpi_thermal_remove(struct acpi_device *device, int type);
+static int acpi_thermal_resume(struct acpi_device *device);
 static int acpi_thermal_state_open_fs(struct inode *inode, struct file *file);
 static int acpi_thermal_temp_open_fs(struct inode *inode, struct file *file);
 static int acpi_thermal_trip_open_fs(struct inode *inode, struct file *file);
-static ssize_t acpi_thermal_write_trip_points(struct file *,
-                                             const char __user *, size_t,
-                                             loff_t *);
 static int acpi_thermal_cooling_open_fs(struct inode *inode, struct file *file);
 static ssize_t acpi_thermal_write_cooling_mode(struct file *,
                                               const char __user *, size_t,
@@ -96,13 +110,20 @@ static int acpi_thermal_polling_open_fs(struct inode *inode, struct file *file);
 static ssize_t acpi_thermal_write_polling(struct file *, const char __user *,
                                          size_t, loff_t *);
 
+static const struct acpi_device_id  thermal_device_ids[] = {
+       {ACPI_THERMAL_HID, 0},
+       {"", 0},
+};
+MODULE_DEVICE_TABLE(acpi, thermal_device_ids);
+
 static struct acpi_driver acpi_thermal_driver = {
-       .name = ACPI_THERMAL_DRIVER_NAME,
+       .name = "thermal",
        .class = ACPI_THERMAL_CLASS,
-       .ids = ACPI_THERMAL_HID,
+       .ids = thermal_device_ids,
        .ops = {
                .add = acpi_thermal_add,
                .remove = acpi_thermal_remove,
+               .resume = acpi_thermal_resume,
                },
 };
 
@@ -160,43 +181,48 @@ struct acpi_thermal_flags {
 };
 
 struct acpi_thermal {
-       acpi_handle handle;
+       struct acpi_device * device;
        acpi_bus_id name;
        unsigned long temperature;
        unsigned long last_temperature;
        unsigned long polling_frequency;
-       u8 cooling_mode;
        volatile u8 zombie;
        struct acpi_thermal_flags flags;
        struct acpi_thermal_state state;
        struct acpi_thermal_trips trips;
        struct acpi_handle_list devices;
        struct timer_list timer;
+       struct thermal_zone_device *thermal_zone;
+       int tz_enabled;
+       struct mutex lock;
 };
 
-static struct file_operations acpi_thermal_state_fops = {
+static const struct file_operations acpi_thermal_state_fops = {
+       .owner = THIS_MODULE,
        .open = acpi_thermal_state_open_fs,
        .read = seq_read,
        .llseek = seq_lseek,
        .release = single_release,
 };
 
-static struct file_operations acpi_thermal_temp_fops = {
+static const struct file_operations acpi_thermal_temp_fops = {
+       .owner = THIS_MODULE,
        .open = acpi_thermal_temp_open_fs,
        .read = seq_read,
        .llseek = seq_lseek,
        .release = single_release,
 };
 
-static struct file_operations acpi_thermal_trip_fops = {
+static const struct file_operations acpi_thermal_trip_fops = {
+       .owner = THIS_MODULE,
        .open = acpi_thermal_trip_open_fs,
        .read = seq_read,
-       .write = acpi_thermal_write_trip_points,
        .llseek = seq_lseek,
        .release = single_release,
 };
 
-static struct file_operations acpi_thermal_cooling_fops = {
+static const struct file_operations acpi_thermal_cooling_fops = {
+       .owner = THIS_MODULE,
        .open = acpi_thermal_cooling_open_fs,
        .read = seq_read,
        .write = acpi_thermal_write_cooling_mode,
@@ -204,7 +230,8 @@ static struct file_operations acpi_thermal_cooling_fops = {
        .release = single_release,
 };
 
-static struct file_operations acpi_thermal_polling_fops = {
+static const struct file_operations acpi_thermal_polling_fops = {
+       .owner = THIS_MODULE,
        .open = acpi_thermal_polling_open_fs,
        .read = seq_read,
        .write = acpi_thermal_write_polling,
@@ -220,59 +247,56 @@ static int acpi_thermal_get_temperature(struct acpi_thermal *tz)
 {
        acpi_status status = AE_OK;
 
-       ACPI_FUNCTION_TRACE("acpi_thermal_get_temperature");
 
        if (!tz)
-               return_VALUE(-EINVAL);
+               return -EINVAL;
 
        tz->last_temperature = tz->temperature;
 
        status =
-           acpi_evaluate_integer(tz->handle, "_TMP", NULL, &tz->temperature);
+           acpi_evaluate_integer(tz->device->handle, "_TMP", NULL, &tz->temperature);
        if (ACPI_FAILURE(status))
-               return_VALUE(-ENODEV);
+               return -ENODEV;
 
        ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Temperature is %lu dK\n",
                          tz->temperature));
 
-       return_VALUE(0);
+       return 0;
 }
 
 static int acpi_thermal_get_polling_frequency(struct acpi_thermal *tz)
 {
        acpi_status status = AE_OK;
 
-       ACPI_FUNCTION_TRACE("acpi_thermal_get_polling_frequency");
 
        if (!tz)
-               return_VALUE(-EINVAL);
+               return -EINVAL;
 
        status =
-           acpi_evaluate_integer(tz->handle, "_TZP", NULL,
+           acpi_evaluate_integer(tz->device->handle, "_TZP", NULL,
                                  &tz->polling_frequency);
        if (ACPI_FAILURE(status))
-               return_VALUE(-ENODEV);
+               return -ENODEV;
 
        ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Polling frequency is %lu dS\n",
                          tz->polling_frequency));
 
-       return_VALUE(0);
+       return 0;
 }
 
 static int acpi_thermal_set_polling(struct acpi_thermal *tz, int seconds)
 {
-       ACPI_FUNCTION_TRACE("acpi_thermal_set_polling");
 
        if (!tz)
-               return_VALUE(-EINVAL);
+               return -EINVAL;
 
        tz->polling_frequency = seconds * 10;   /* Convert value to deci-seconds */
 
        ACPI_DEBUG_PRINT((ACPI_DB_INFO,
                          "Polling frequency set to %lu seconds\n",
-                         tz->polling_frequency));
+                         tz->polling_frequency/10));
 
-       return_VALUE(0);
+       return 0;
 }
 
 static int acpi_thermal_set_cooling_mode(struct acpi_thermal *tz, int mode)
@@ -282,239 +306,299 @@ static int acpi_thermal_set_cooling_mode(struct acpi_thermal *tz, int mode)
        struct acpi_object_list arg_list = { 1, &arg0 };
        acpi_handle handle = NULL;
 
-       ACPI_FUNCTION_TRACE("acpi_thermal_set_cooling_mode");
 
        if (!tz)
-               return_VALUE(-EINVAL);
+               return -EINVAL;
 
-       status = acpi_get_handle(tz->handle, "_SCP", &handle);
+       status = acpi_get_handle(tz->device->handle, "_SCP", &handle);
        if (ACPI_FAILURE(status)) {
                ACPI_DEBUG_PRINT((ACPI_DB_INFO, "_SCP not present\n"));
-               return_VALUE(-ENODEV);
+               return -ENODEV;
        }
 
        arg0.integer.value = mode;
 
        status = acpi_evaluate_object(handle, NULL, &arg_list, NULL);
        if (ACPI_FAILURE(status))
-               return_VALUE(-ENODEV);
+               return -ENODEV;
 
-       tz->cooling_mode = mode;
+       return 0;
+}
 
-       ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Cooling mode [%s]\n",
-                         mode ? "passive" : "active"));
+#define ACPI_TRIPS_CRITICAL    0x01
+#define ACPI_TRIPS_HOT         0x02
+#define ACPI_TRIPS_PASSIVE     0x04
+#define ACPI_TRIPS_ACTIVE      0x08
+#define ACPI_TRIPS_DEVICES     0x10
 
-       return_VALUE(0);
-}
+#define ACPI_TRIPS_REFRESH_THRESHOLDS  (ACPI_TRIPS_PASSIVE | ACPI_TRIPS_ACTIVE)
+#define ACPI_TRIPS_REFRESH_DEVICES     ACPI_TRIPS_DEVICES
 
-static int acpi_thermal_get_trip_points(struct acpi_thermal *tz)
+#define ACPI_TRIPS_INIT      (ACPI_TRIPS_CRITICAL | ACPI_TRIPS_HOT |   \
+                             ACPI_TRIPS_PASSIVE | ACPI_TRIPS_ACTIVE |  \
+                             ACPI_TRIPS_DEVICES)
+
+/*
+ * This exception is thrown out in two cases:
+ * 1.An invalid trip point becomes invalid or a valid trip point becomes invalid
+ *   when re-evaluating the AML code.
+ * 2.TODO: Devices listed in _PSL, _ALx, _TZD may change.
+ *   We need to re-bind the cooling devices of a thermal zone when this occurs.
+ */
+#define ACPI_THERMAL_TRIPS_EXCEPTION(flags, str)       \
+do {   \
+       if (flags != ACPI_TRIPS_INIT)   \
+               ACPI_EXCEPTION((AE_INFO, AE_ERROR,      \
+               "ACPI thermal trip point %s changed\n"  \
+               "Please send acpidump to linux-acpi@vger.kernel.org\n", str)); \
+} while (0)
+
+static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
 {
        acpi_status status = AE_OK;
-       int i = 0;
-
-       ACPI_FUNCTION_TRACE("acpi_thermal_get_trip_points");
-
-       if (!tz)
-               return_VALUE(-EINVAL);
+       struct acpi_handle_list devices;
+       int valid = 0;
+       int i;
 
        /* Critical Shutdown (required) */
-
-       status = acpi_evaluate_integer(tz->handle, "_CRT", NULL,
-                                      &tz->trips.critical.temperature);
-       if (ACPI_FAILURE(status)) {
-               tz->trips.critical.flags.valid = 0;
-               ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "No critical threshold\n"));
-               return_VALUE(-ENODEV);
-       } else {
-               tz->trips.critical.flags.valid = 1;
-               ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-                                 "Found critical threshold [%lu]\n",
-                                 tz->trips.critical.temperature));
+       if (flag & ACPI_TRIPS_CRITICAL) {
+               status = acpi_evaluate_integer(tz->device->handle,
+                               "_CRT", NULL, &tz->trips.critical.temperature);
+               /*
+                * Treat freezing temperatures as invalid as well; some
+                * BIOSes return really low values and cause reboots at startup.
+                * Below zero (Celcius) values clearly aren't right for sure..
+                * ... so lets discard those as invalid.
+                */
+               if (ACPI_FAILURE(status) ||
+                               tz->trips.critical.temperature <= 2732) {
+                       tz->trips.critical.flags.valid = 0;
+                       ACPI_EXCEPTION((AE_INFO, status,
+                                       "No or invalid critical threshold"));
+                       return -ENODEV;
+               } else {
+                       tz->trips.critical.flags.valid = 1;
+                       ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+                                       "Found critical threshold [%lu]\n",
+                                       tz->trips.critical.temperature));
+               }
+               if (tz->trips.critical.flags.valid == 1) {
+                       if (crt == -1) {
+                               tz->trips.critical.flags.valid = 0;
+                       } else if (crt > 0) {
+                               unsigned long crt_k = CELSIUS_TO_KELVIN(crt);
+                               /*
+                                * Allow override to lower critical threshold
+                                */
+                               if (crt_k < tz->trips.critical.temperature)
+                                       tz->trips.critical.temperature = crt_k;
+                       }
+               }
        }
 
        /* Critical Sleep (optional) */
-
-       status =
-           acpi_evaluate_integer(tz->handle, "_HOT", NULL,
-                                 &tz->trips.hot.temperature);
-       if (ACPI_FAILURE(status)) {
-               tz->trips.hot.flags.valid = 0;
-               ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No hot threshold\n"));
-       } else {
-               tz->trips.hot.flags.valid = 1;
-               ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found hot threshold [%lu]\n",
-                                 tz->trips.hot.temperature));
+       if (flag & ACPI_TRIPS_HOT) {
+               status = acpi_evaluate_integer(tz->device->handle,
+                               "_HOT", NULL, &tz->trips.hot.temperature);
+               if (ACPI_FAILURE(status)) {
+                       tz->trips.hot.flags.valid = 0;
+                       ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+                                       "No hot threshold\n"));
+               } else {
+                       tz->trips.hot.flags.valid = 1;
+                       ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+                                       "Found hot threshold [%lu]\n",
+                                       tz->trips.critical.temperature));
+               }
        }
 
-       /* Passive: Processors (optional) */
-
-       status =
-           acpi_evaluate_integer(tz->handle, "_PSV", NULL,
-                                 &tz->trips.passive.temperature);
-       if (ACPI_FAILURE(status)) {
-               tz->trips.passive.flags.valid = 0;
-               ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No passive threshold\n"));
-       } else {
-               tz->trips.passive.flags.valid = 1;
-
-               status =
-                   acpi_evaluate_integer(tz->handle, "_TC1", NULL,
-                                         &tz->trips.passive.tc1);
-               if (ACPI_FAILURE(status))
-                       tz->trips.passive.flags.valid = 0;
-
-               status =
-                   acpi_evaluate_integer(tz->handle, "_TC2", NULL,
-                                         &tz->trips.passive.tc2);
-               if (ACPI_FAILURE(status))
-                       tz->trips.passive.flags.valid = 0;
+       /* Passive (optional) */
+       if (flag & ACPI_TRIPS_PASSIVE) {
+               valid = tz->trips.passive.flags.valid;
+               if (psv == -1) {
+                       status = AE_SUPPORT;
+               } else if (psv > 0) {
+                       tz->trips.passive.temperature = CELSIUS_TO_KELVIN(psv);
+                       status = AE_OK;
+               } else {
+                       status = acpi_evaluate_integer(tz->device->handle,
+                               "_PSV", NULL, &tz->trips.passive.temperature);
+               }
 
-               status =
-                   acpi_evaluate_integer(tz->handle, "_TSP", NULL,
-                                         &tz->trips.passive.tsp);
                if (ACPI_FAILURE(status))
                        tz->trips.passive.flags.valid = 0;
-
-               status =
-                   acpi_evaluate_reference(tz->handle, "_PSL", NULL,
-                                           &tz->trips.passive.devices);
+               else {
+                       tz->trips.passive.flags.valid = 1;
+                       if (flag == ACPI_TRIPS_INIT) {
+                               status = acpi_evaluate_integer(
+                                               tz->device->handle, "_TC1",
+                                               NULL, &tz->trips.passive.tc1);
+                               if (ACPI_FAILURE(status))
+                                       tz->trips.passive.flags.valid = 0;
+                               status = acpi_evaluate_integer(
+                                               tz->device->handle, "_TC2",
+                                               NULL, &tz->trips.passive.tc2);
+                               if (ACPI_FAILURE(status))
+                                       tz->trips.passive.flags.valid = 0;
+                               status = acpi_evaluate_integer(
+                                               tz->device->handle, "_TSP",
+                                               NULL, &tz->trips.passive.tsp);
+                               if (ACPI_FAILURE(status))
+                                       tz->trips.passive.flags.valid = 0;
+                       }
+               }
+       }
+       if ((flag & ACPI_TRIPS_DEVICES) && tz->trips.passive.flags.valid) {
+               memset(&devices, 0, sizeof(struct acpi_handle_list));
+               status = acpi_evaluate_reference(tz->device->handle, "_PSL",
+                                                       NULL, &devices);
                if (ACPI_FAILURE(status))
                        tz->trips.passive.flags.valid = 0;
-
-               if (!tz->trips.passive.flags.valid)
-                       ACPI_DEBUG_PRINT((ACPI_DB_WARN,
-                                         "Invalid passive threshold\n"));
                else
-                       ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-                                         "Found passive threshold [%lu]\n",
-                                         tz->trips.passive.temperature));
-       }
+                       tz->trips.passive.flags.valid = 1;
 
-       /* Active: Fans, etc. (optional) */
+               if (memcmp(&tz->trips.passive.devices, &devices,
+                               sizeof(struct acpi_handle_list))) {
+                       memcpy(&tz->trips.passive.devices, &devices,
+                               sizeof(struct acpi_handle_list));
+                       ACPI_THERMAL_TRIPS_EXCEPTION(flag, "device");
+               }
+       }
+       if ((flag & ACPI_TRIPS_PASSIVE) || (flag & ACPI_TRIPS_DEVICES)) {
+               if (valid != tz->trips.passive.flags.valid)
+                               ACPI_THERMAL_TRIPS_EXCEPTION(flag, "state");
+       }
 
+       /* Active (optional) */
        for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
-
                char name[5] = { '_', 'A', 'C', ('0' + i), '\0' };
-
-               status =
-                   acpi_evaluate_integer(tz->handle, name, NULL,
-                                         &tz->trips.active[i].temperature);
-               if (ACPI_FAILURE(status))
-                       break;
+               valid = tz->trips.active[i].flags.valid;
+
+               if (act == -1)
+                       break; /* disable all active trip points */
+
+               if (flag & ACPI_TRIPS_ACTIVE) {
+                       status = acpi_evaluate_integer(tz->device->handle,
+                               name, NULL, &tz->trips.active[i].temperature);
+                       if (ACPI_FAILURE(status)) {
+                               tz->trips.active[i].flags.valid = 0;
+                               if (i == 0)
+                                       break;
+                               if (act <= 0)
+                                       break;
+                               if (i == 1)
+                                       tz->trips.active[0].temperature =
+                                               CELSIUS_TO_KELVIN(act);
+                               else
+                                       /*
+                                        * Don't allow override higher than
+                                        * the next higher trip point
+                                        */
+                                       tz->trips.active[i - 1].temperature =
+                                               (tz->trips.active[i - 2].temperature <
+                                               CELSIUS_TO_KELVIN(act) ?
+                                               tz->trips.active[i - 2].temperature :
+                                               CELSIUS_TO_KELVIN(act));
+                               break;
+                       } else
+                               tz->trips.active[i].flags.valid = 1;
+               }
 
                name[2] = 'L';
-               status =
-                   acpi_evaluate_reference(tz->handle, name, NULL,
-                                           &tz->trips.active[i].devices);
-               if (ACPI_SUCCESS(status)) {
-                       tz->trips.active[i].flags.valid = 1;
-                       ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-                                         "Found active threshold [%d]:[%lu]\n",
-                                         i, tz->trips.active[i].temperature));
-               } else
-                       ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-                                         "Invalid active threshold [%d]\n",
-                                         i));
-       }
-
-       return_VALUE(0);
-}
-
-static int acpi_thermal_get_devices(struct acpi_thermal *tz)
-{
-       acpi_status status = AE_OK;
+               if ((flag & ACPI_TRIPS_DEVICES) && tz->trips.active[i].flags.valid ) {
+                       memset(&devices, 0, sizeof(struct acpi_handle_list));
+                       status = acpi_evaluate_reference(tz->device->handle,
+                                               name, NULL, &devices);
+                       if (ACPI_FAILURE(status))
+                               tz->trips.active[i].flags.valid = 0;
+                       else
+                               tz->trips.active[i].flags.valid = 1;
 
-       ACPI_FUNCTION_TRACE("acpi_thermal_get_devices");
+                       if (memcmp(&tz->trips.active[i].devices, &devices,
+                                       sizeof(struct acpi_handle_list))) {
+                               memcpy(&tz->trips.active[i].devices, &devices,
+                                       sizeof(struct acpi_handle_list));
+                               ACPI_THERMAL_TRIPS_EXCEPTION(flag, "device");
+                       }
+               }
+               if ((flag & ACPI_TRIPS_ACTIVE) || (flag & ACPI_TRIPS_DEVICES))
+                       if (valid != tz->trips.active[i].flags.valid)
+                               ACPI_THERMAL_TRIPS_EXCEPTION(flag, "state");
 
-       if (!tz)
-               return_VALUE(-EINVAL);
+               if (!tz->trips.active[i].flags.valid)
+                       break;
+       }
 
-       status =
-           acpi_evaluate_reference(tz->handle, "_TZD", NULL, &tz->devices);
-       if (ACPI_FAILURE(status))
-               return_VALUE(-ENODEV);
+       if (flag & ACPI_TRIPS_DEVICES) {
+               memset(&devices, 0, sizeof(struct acpi_handle_list));
+               status = acpi_evaluate_reference(tz->device->handle, "_TZD",
+                                               NULL, &devices);
+               if (memcmp(&tz->devices, &devices,
+                               sizeof(struct acpi_handle_list))) {
+                       memcpy(&tz->devices, &devices,
+                               sizeof(struct acpi_handle_list));
+                       ACPI_THERMAL_TRIPS_EXCEPTION(flag, "device");
+               }
+       }
 
-       return_VALUE(0);
+       return 0;
 }
 
-static int acpi_thermal_call_usermode(char *path)
+static int acpi_thermal_get_trip_points(struct acpi_thermal *tz)
 {
-       char *argv[2] = { NULL, NULL };
-       char *envp[3] = { NULL, NULL, NULL };
-
-       ACPI_FUNCTION_TRACE("acpi_thermal_call_usermode");
-
-       if (!path)
-               return_VALUE(-EINVAL);
-
-       argv[0] = path;
-
-       /* minimal command environment */
-       envp[0] = "HOME=/";
-       envp[1] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
-
-       call_usermodehelper(argv[0], argv, envp, 0);
-
-       return_VALUE(0);
+       return acpi_thermal_trips_update(tz, ACPI_TRIPS_INIT);
 }
 
 static int acpi_thermal_critical(struct acpi_thermal *tz)
 {
-       int result = 0;
-       struct acpi_device *device = NULL;
-
-       ACPI_FUNCTION_TRACE("acpi_thermal_critical");
-
        if (!tz || !tz->trips.critical.flags.valid)
-               return_VALUE(-EINVAL);
+               return -EINVAL;
 
        if (tz->temperature >= tz->trips.critical.temperature) {
-               ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Critical trip point\n"));
+               printk(KERN_WARNING PREFIX "Critical trip point\n");
                tz->trips.critical.flags.enabled = 1;
        } else if (tz->trips.critical.flags.enabled)
                tz->trips.critical.flags.enabled = 0;
 
-       result = acpi_bus_get_device(tz->handle, &device);
-       if (result)
-               return_VALUE(result);
-
-       printk(KERN_EMERG
-              "Critical temperature reached (%ld C), shutting down.\n",
-              KELVIN_TO_CELSIUS(tz->temperature));
-       acpi_bus_generate_event(device, ACPI_THERMAL_NOTIFY_CRITICAL,
+       acpi_bus_generate_proc_event(tz->device, ACPI_THERMAL_NOTIFY_CRITICAL,
                                tz->trips.critical.flags.enabled);
+       acpi_bus_generate_netlink_event(tz->device->pnp.device_class,
+                                         tz->device->dev.bus_id,
+                                         ACPI_THERMAL_NOTIFY_CRITICAL,
+                                         tz->trips.critical.flags.enabled);
+
+       /* take no action if nocrt is set */
+       if(!nocrt) {
+               printk(KERN_EMERG
+                       "Critical temperature reached (%ld C), shutting down.\n",
+                       KELVIN_TO_CELSIUS(tz->temperature));
+               orderly_poweroff(true);
+       }
 
-       acpi_thermal_call_usermode(ACPI_THERMAL_PATH_POWEROFF);
-
-       return_VALUE(0);
+       return 0;
 }
 
 static int acpi_thermal_hot(struct acpi_thermal *tz)
 {
-       int result = 0;
-       struct acpi_device *device = NULL;
-
-       ACPI_FUNCTION_TRACE("acpi_thermal_hot");
-
        if (!tz || !tz->trips.hot.flags.valid)
-               return_VALUE(-EINVAL);
+               return -EINVAL;
 
        if (tz->temperature >= tz->trips.hot.temperature) {
-               ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Hot trip point\n"));
+               printk(KERN_WARNING PREFIX "Hot trip point\n");
                tz->trips.hot.flags.enabled = 1;
        } else if (tz->trips.hot.flags.enabled)
                tz->trips.hot.flags.enabled = 0;
 
-       result = acpi_bus_get_device(tz->handle, &device);
-       if (result)
-               return_VALUE(result);
-
-       acpi_bus_generate_event(device, ACPI_THERMAL_NOTIFY_HOT,
+       acpi_bus_generate_proc_event(tz->device, ACPI_THERMAL_NOTIFY_HOT,
                                tz->trips.hot.flags.enabled);
+       acpi_bus_generate_netlink_event(tz->device->pnp.device_class,
+                                         tz->device->dev.bus_id,
+                                         ACPI_THERMAL_NOTIFY_HOT,
+                                         tz->trips.hot.flags.enabled);
 
-       /* TBD: Call user-mode "sleep(S4)" function */
+       /* TBD: Call user-mode "sleep(S4)" function if nocrt is cleared */
 
-       return_VALUE(0);
+       return 0;
 }
 
 static void acpi_thermal_passive(struct acpi_thermal *tz)
@@ -524,7 +608,6 @@ static void acpi_thermal_passive(struct acpi_thermal *tz)
        int trend = 0;
        int i = 0;
 
-       ACPI_FUNCTION_TRACE("acpi_thermal_passive");
 
        if (!tz || !tz->trips.passive.flags.valid)
                return;
@@ -613,7 +696,6 @@ static void acpi_thermal_active(struct acpi_thermal *tz)
        int j = 0;
        unsigned long maxtemp = 0;
 
-       ACPI_FUNCTION_TRACE("acpi_thermal_active");
 
        if (!tz)
                return;
@@ -640,10 +722,10 @@ static void acpi_thermal_active(struct acpi_thermal *tz)
                                                       handles[j],
                                                       ACPI_STATE_D0);
                                if (result) {
-                                       ACPI_DEBUG_PRINT((ACPI_DB_WARN,
-                                                         "Unable to turn cooling device [%p] 'on'\n",
-                                                         active->devices.
-                                                         handles[j]));
+                                       printk(KERN_WARNING PREFIX
+                                                     "Unable to turn cooling device [%p] 'on'\n",
+                                                     active->devices.
+                                                     handles[j]);
                                        continue;
                                }
                                active->flags.enabled = 1;
@@ -665,9 +747,9 @@ static void acpi_thermal_active(struct acpi_thermal *tz)
                        result = acpi_bus_set_power(active->devices.handles[j],
                                                    ACPI_STATE_D3);
                        if (result) {
-                               ACPI_DEBUG_PRINT((ACPI_DB_WARN,
-                                                 "Unable to turn cooling device [%p] 'off'\n",
-                                                 active->devices.handles[j]));
+                               printk(KERN_WARNING PREFIX
+                                             "Unable to turn cooling device [%p] 'off'\n",
+                                             active->devices.handles[j]);
                                continue;
                        }
                        active->flags.enabled = 0;
@@ -684,30 +766,36 @@ static void acpi_thermal_run(unsigned long data)
 {
        struct acpi_thermal *tz = (struct acpi_thermal *)data;
        if (!tz->zombie)
-               acpi_os_queue_for_execution(OSD_PRIORITY_GPE,
-                                           acpi_thermal_check, (void *)data);
+               acpi_os_execute(OSL_GPE_HANDLER, acpi_thermal_check, (void *)data);
 }
 
 static void acpi_thermal_check(void *data)
 {
        int result = 0;
-       struct acpi_thermal *tz = (struct acpi_thermal *)data;
+       struct acpi_thermal *tz = data;
        unsigned long sleep_time = 0;
+       unsigned long timeout_jiffies = 0;
        int i = 0;
        struct acpi_thermal_state state;
 
-       ACPI_FUNCTION_TRACE("acpi_thermal_check");
 
        if (!tz) {
-               ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid (NULL) context.\n"));
-               return_VOID;
+               printk(KERN_ERR PREFIX "Invalid (NULL) context\n");
+               return;
        }
 
+       /* Check if someone else is already running */
+       if (!mutex_trylock(&tz->lock))
+               return;
+
        state = tz->state;
 
        result = acpi_thermal_get_temperature(tz);
        if (result)
-               return_VOID;
+               goto unlock;
+
+       if (!tz->tz_enabled)
+               goto unlock;
 
        memset(&tz->state, 0, sizeof(tz->state));
 
@@ -770,10 +858,13 @@ static void acpi_thermal_check(void *data)
         * a thermal event occurs).  Note that _TSP and _TZD values are
         * given in 1/10th seconds (we must covert to milliseconds).
         */
-       if (tz->state.passive)
+       if (tz->state.passive) {
                sleep_time = tz->trips.passive.tsp * 100;
-       else if (tz->polling_frequency > 0)
+               timeout_jiffies =  jiffies + (HZ * sleep_time) / 1000;
+       } else if (tz->polling_frequency > 0) {
                sleep_time = tz->polling_frequency * 100;
+               timeout_jiffies =  round_jiffies(jiffies + (HZ * sleep_time) / 1000);
+       }
 
        ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%s: temperature[%lu] sleep[%lu]\n",
                          tz->name, tz->temperature, sleep_time));
@@ -787,18 +878,322 @@ static void acpi_thermal_check(void *data)
                        del_timer(&(tz->timer));
        } else {
                if (timer_pending(&(tz->timer)))
-                       mod_timer(&(tz->timer), (HZ * sleep_time) / 1000);
+                       mod_timer(&(tz->timer), timeout_jiffies);
                else {
                        tz->timer.data = (unsigned long)tz;
                        tz->timer.function = acpi_thermal_run;
-                       tz->timer.expires = jiffies + (HZ * sleep_time) / 1000;
+                       tz->timer.expires = timeout_jiffies;
                        add_timer(&(tz->timer));
                }
        }
+      unlock:
+       mutex_unlock(&tz->lock);
+}
+
+/* sys I/F for generic thermal sysfs support */
+#define KELVIN_TO_MILLICELSIUS(t) (t * 100 - 273200)
+
+static int thermal_get_temp(struct thermal_zone_device *thermal, char *buf)
+{
+       struct acpi_thermal *tz = thermal->devdata;
+       int result;
+
+       if (!tz)
+               return -EINVAL;
+
+       result = acpi_thermal_get_temperature(tz);
+       if (result)
+               return result;
+
+       return sprintf(buf, "%ld\n", KELVIN_TO_MILLICELSIUS(tz->temperature));
+}
+
+static const char enabled[] = "kernel";
+static const char disabled[] = "user";
+static int thermal_get_mode(struct thermal_zone_device *thermal,
+                               char *buf)
+{
+       struct acpi_thermal *tz = thermal->devdata;
+
+       if (!tz)
+               return -EINVAL;
+
+       return sprintf(buf, "%s\n", tz->tz_enabled ?
+                       enabled : disabled);
+}
+
+static int thermal_set_mode(struct thermal_zone_device *thermal,
+                               const char *buf)
+{
+       struct acpi_thermal *tz = thermal->devdata;
+       int enable;
+
+       if (!tz)
+               return -EINVAL;
+
+       /*
+        * enable/disable thermal management from ACPI thermal driver
+        */
+       if (!strncmp(buf, enabled, sizeof enabled - 1))
+               enable = 1;
+       else if (!strncmp(buf, disabled, sizeof disabled - 1))
+               enable = 0;
+       else
+               return -EINVAL;
+
+       if (enable != tz->tz_enabled) {
+               tz->tz_enabled = enable;
+               ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+                       "%s ACPI thermal control\n",
+                       tz->tz_enabled ? enabled : disabled));
+               acpi_thermal_check(tz);
+       }
+       return 0;
+}
+
+static int thermal_get_trip_type(struct thermal_zone_device *thermal,
+                                int trip, char *buf)
+{
+       struct acpi_thermal *tz = thermal->devdata;
+       int i;
+
+       if (!tz || trip < 0)
+               return -EINVAL;
+
+       if (tz->trips.critical.flags.valid) {
+               if (!trip)
+                       return sprintf(buf, "critical\n");
+               trip--;
+       }
+
+       if (tz->trips.hot.flags.valid) {
+               if (!trip)
+                       return sprintf(buf, "hot\n");
+               trip--;
+       }
+
+       if (tz->trips.passive.flags.valid) {
+               if (!trip)
+                       return sprintf(buf, "passive\n");
+               trip--;
+       }
+
+       for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE &&
+               tz->trips.active[i].flags.valid; i++) {
+               if (!trip)
+                       return sprintf(buf, "active%d\n", i);
+               trip--;
+       }
+
+       return -EINVAL;
+}
+
+static int thermal_get_trip_temp(struct thermal_zone_device *thermal,
+                                int trip, char *buf)
+{
+       struct acpi_thermal *tz = thermal->devdata;
+       int i;
+
+       if (!tz || trip < 0)
+               return -EINVAL;
+
+       if (tz->trips.critical.flags.valid) {
+               if (!trip)
+                       return sprintf(buf, "%ld\n", KELVIN_TO_MILLICELSIUS(
+                               tz->trips.critical.temperature));
+               trip--;
+       }
+
+       if (tz->trips.hot.flags.valid) {
+               if (!trip)
+                       return sprintf(buf, "%ld\n", KELVIN_TO_MILLICELSIUS(
+                                       tz->trips.hot.temperature));
+               trip--;
+       }
+
+       if (tz->trips.passive.flags.valid) {
+               if (!trip)
+                       return sprintf(buf, "%ld\n", KELVIN_TO_MILLICELSIUS(
+                                       tz->trips.passive.temperature));
+               trip--;
+       }
+
+       for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE &&
+               tz->trips.active[i].flags.valid; i++) {
+               if (!trip)
+                       return sprintf(buf, "%ld\n", KELVIN_TO_MILLICELSIUS(
+                                       tz->trips.active[i].temperature));
+               trip--;
+       }
+
+       return -EINVAL;
+}
+
+static int thermal_get_crit_temp(struct thermal_zone_device *thermal,
+                               unsigned long *temperature) {
+       struct acpi_thermal *tz = thermal->devdata;
+
+       if (tz->trips.critical.flags.valid) {
+               *temperature = KELVIN_TO_MILLICELSIUS(
+                               tz->trips.critical.temperature);
+               return 0;
+       } else
+               return -EINVAL;
+}
+
+typedef int (*cb)(struct thermal_zone_device *, int,
+                 struct thermal_cooling_device *);
+static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal,
+                                       struct thermal_cooling_device *cdev,
+                                       cb action)
+{
+       struct acpi_device *device = cdev->devdata;
+       struct acpi_thermal *tz = thermal->devdata;
+       struct acpi_device *dev;
+       acpi_status status;
+       acpi_handle handle;
+       int i;
+       int j;
+       int trip = -1;
+       int result = 0;
+
+       if (tz->trips.critical.flags.valid)
+               trip++;
+
+       if (tz->trips.hot.flags.valid)
+               trip++;
+
+       if (tz->trips.passive.flags.valid) {
+               trip++;
+               for (i = 0; i < tz->trips.passive.devices.count;
+                   i++) {
+                       handle = tz->trips.passive.devices.handles[i];
+                       status = acpi_bus_get_device(handle, &dev);
+                       if (ACPI_SUCCESS(status) && (dev == device)) {
+                               result = action(thermal, trip, cdev);
+                               if (result)
+                                       goto failed;
+                       }
+               }
+       }
+
+       for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
+               if (!tz->trips.active[i].flags.valid)
+                       break;
+               trip++;
+               for (j = 0;
+                   j < tz->trips.active[i].devices.count;
+                   j++) {
+                       handle = tz->trips.active[i].devices.handles[j];
+                       status = acpi_bus_get_device(handle, &dev);
+                       if (ACPI_SUCCESS(status) && (dev == device)) {
+                               result = action(thermal, trip, cdev);
+                               if (result)
+                                       goto failed;
+                       }
+               }
+       }
+
+       for (i = 0; i < tz->devices.count; i++) {
+               handle = tz->devices.handles[i];
+               status = acpi_bus_get_device(handle, &dev);
+               if (ACPI_SUCCESS(status) && (dev == device)) {
+                       result = action(thermal, -1, cdev);
+                       if (result)
+                               goto failed;
+               }
+       }
+
+failed:
+       return result;
+}
+
+static int
+acpi_thermal_bind_cooling_device(struct thermal_zone_device *thermal,
+                                       struct thermal_cooling_device *cdev)
+{
+       return acpi_thermal_cooling_device_cb(thermal, cdev,
+                               thermal_zone_bind_cooling_device);
+}
+
+static int
+acpi_thermal_unbind_cooling_device(struct thermal_zone_device *thermal,
+                                       struct thermal_cooling_device *cdev)
+{
+       return acpi_thermal_cooling_device_cb(thermal, cdev,
+                               thermal_zone_unbind_cooling_device);
+}
+
+static struct thermal_zone_device_ops acpi_thermal_zone_ops = {
+       .bind = acpi_thermal_bind_cooling_device,
+       .unbind = acpi_thermal_unbind_cooling_device,
+       .get_temp = thermal_get_temp,
+       .get_mode = thermal_get_mode,
+       .set_mode = thermal_set_mode,
+       .get_trip_type = thermal_get_trip_type,
+       .get_trip_temp = thermal_get_trip_temp,
+       .get_crit_temp = thermal_get_crit_temp,
+};
+
+static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz)
+{
+       int trips = 0;
+       int result;
+       acpi_status status;
+       int i;
+
+       if (tz->trips.critical.flags.valid)
+               trips++;
+
+       if (tz->trips.hot.flags.valid)
+               trips++;
+
+       if (tz->trips.passive.flags.valid)
+               trips++;
+
+       for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE &&
+                       tz->trips.active[i].flags.valid; i++, trips++);
+       tz->thermal_zone = thermal_zone_device_register("acpitz",
+                                       trips, tz, &acpi_thermal_zone_ops);
+       if (IS_ERR(tz->thermal_zone))
+               return -ENODEV;
+
+       result = sysfs_create_link(&tz->device->dev.kobj,
+                                  &tz->thermal_zone->device.kobj, "thermal_zone");
+       if (result)
+               return result;
+
+       result = sysfs_create_link(&tz->thermal_zone->device.kobj,
+                                  &tz->device->dev.kobj, "device");
+       if (result)
+               return result;
+
+       status = acpi_attach_data(tz->device->handle,
+                                 acpi_bus_private_data_handler,
+                                 tz->thermal_zone);
+       if (ACPI_FAILURE(status)) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                               "Error attaching device data\n"));
+               return -ENODEV;
+       }
+
+       tz->tz_enabled = 1;
+
+       printk(KERN_INFO PREFIX "%s is registered as thermal_zone%d\n",
+                       tz->device->dev.bus_id, tz->thermal_zone->id);
+       return 0;
+}
 
-       return_VOID;
+static void acpi_thermal_unregister_thermal_zone(struct acpi_thermal *tz)
+{
+       sysfs_remove_link(&tz->device->dev.kobj, "thermal_zone");
+       sysfs_remove_link(&tz->thermal_zone->device.kobj, "device");
+       thermal_zone_device_unregister(tz->thermal_zone);
+       tz->thermal_zone = NULL;
+       acpi_detach_data(tz->device->handle, acpi_bus_private_data_handler);
 }
 
+
 /* --------------------------------------------------------------------------
                               FS Interface (/proc)
    -------------------------------------------------------------------------- */
@@ -807,9 +1202,8 @@ static struct proc_dir_entry *acpi_thermal_dir;
 
 static int acpi_thermal_state_seq_show(struct seq_file *seq, void *offset)
 {
-       struct acpi_thermal *tz = (struct acpi_thermal *)seq->private;
+       struct acpi_thermal *tz = seq->private;
 
-       ACPI_FUNCTION_TRACE("acpi_thermal_state_seq_show");
 
        if (!tz)
                goto end;
@@ -832,7 +1226,7 @@ static int acpi_thermal_state_seq_show(struct seq_file *seq, void *offset)
        }
 
       end:
-       return_VALUE(0);
+       return 0;
 }
 
 static int acpi_thermal_state_open_fs(struct inode *inode, struct file *file)
@@ -843,9 +1237,8 @@ static int acpi_thermal_state_open_fs(struct inode *inode, struct file *file)
 static int acpi_thermal_temp_seq_show(struct seq_file *seq, void *offset)
 {
        int result = 0;
-       struct acpi_thermal *tz = (struct acpi_thermal *)seq->private;
+       struct acpi_thermal *tz = seq->private;
 
-       ACPI_FUNCTION_TRACE("acpi_thermal_temp_seq_show");
 
        if (!tz)
                goto end;
@@ -858,7 +1251,7 @@ static int acpi_thermal_temp_seq_show(struct seq_file *seq, void *offset)
                   KELVIN_TO_CELSIUS(tz->temperature));
 
       end:
-       return_VALUE(0);
+       return 0;
 }
 
 static int acpi_thermal_temp_open_fs(struct inode *inode, struct file *file)
@@ -868,22 +1261,26 @@ static int acpi_thermal_temp_open_fs(struct inode *inode, struct file *file)
 
 static int acpi_thermal_trip_seq_show(struct seq_file *seq, void *offset)
 {
-       struct acpi_thermal *tz = (struct acpi_thermal *)seq->private;
+       struct acpi_thermal *tz = seq->private;
+       struct acpi_device *device;
+       acpi_status status;
+
        int i = 0;
        int j = 0;
 
-       ACPI_FUNCTION_TRACE("acpi_thermal_trip_seq_show");
 
        if (!tz)
                goto end;
 
        if (tz->trips.critical.flags.valid)
-               seq_printf(seq, "critical (S5):           %ld C\n",
-                          KELVIN_TO_CELSIUS(tz->trips.critical.temperature));
+               seq_printf(seq, "critical (S5):           %ld C%s",
+                          KELVIN_TO_CELSIUS(tz->trips.critical.temperature),
+                          nocrt ? " <disabled>\n" : "\n");
 
        if (tz->trips.hot.flags.valid)
-               seq_printf(seq, "hot (S4):                %ld C\n",
-                          KELVIN_TO_CELSIUS(tz->trips.hot.temperature));
+               seq_printf(seq, "hot (S4):                %ld C%s",
+                          KELVIN_TO_CELSIUS(tz->trips.hot.temperature),
+                          nocrt ? " <disabled>\n" : "\n");
 
        if (tz->trips.passive.flags.valid) {
                seq_printf(seq,
@@ -892,9 +1289,10 @@ static int acpi_thermal_trip_seq_show(struct seq_file *seq, void *offset)
                           tz->trips.passive.tc1, tz->trips.passive.tc2,
                           tz->trips.passive.tsp);
                for (j = 0; j < tz->trips.passive.devices.count; j++) {
-
-                       seq_printf(seq, "0x%p ",
-                                  tz->trips.passive.devices.handles[j]);
+                       status = acpi_bus_get_device(tz->trips.passive.devices.
+                                                    handles[j], &device);
+                       seq_printf(seq, "%4.4s ", status ? "" :
+                                  acpi_device_bid(device));
                }
                seq_puts(seq, "\n");
        }
@@ -905,14 +1303,18 @@ static int acpi_thermal_trip_seq_show(struct seq_file *seq, void *offset)
                seq_printf(seq, "active[%d]:               %ld C: devices=",
                           i,
                           KELVIN_TO_CELSIUS(tz->trips.active[i].temperature));
-               for (j = 0; j < tz->trips.active[i].devices.count; j++)
-                       seq_printf(seq, "0x%p ",
-                                  tz->trips.active[i].devices.handles[j]);
+               for (j = 0; j < tz->trips.active[i].devices.count; j++){
+                       status = acpi_bus_get_device(tz->trips.active[i].
+                                                    devices.handles[j],
+                                                    &device);
+                       seq_printf(seq, "%4.4s ", status ? "" :
+                                  acpi_device_bid(device));
+               }
                seq_puts(seq, "\n");
        }
 
       end:
-       return_VALUE(0);
+       return 0;
 }
 
 static int acpi_thermal_trip_open_fs(struct inode *inode, struct file *file)
@@ -920,94 +1322,21 @@ static int acpi_thermal_trip_open_fs(struct inode *inode, struct file *file)
        return single_open(file, acpi_thermal_trip_seq_show, PDE(inode)->data);
 }
 
-static ssize_t
-acpi_thermal_write_trip_points(struct file *file,
-                              const char __user * buffer,
-                              size_t count, loff_t * ppos)
-{
-       struct seq_file *m = (struct seq_file *)file->private_data;
-       struct acpi_thermal *tz = (struct acpi_thermal *)m->private;
-
-       char *limit_string;
-       int num, critical, hot, passive;
-       int *active;
-       int i = 0;
-
-       ACPI_FUNCTION_TRACE("acpi_thermal_write_trip_points");
-
-       limit_string = kmalloc(ACPI_THERMAL_MAX_LIMIT_STR_LEN, GFP_KERNEL);
-       if (!limit_string)
-               return_VALUE(-ENOMEM);
-
-       memset(limit_string, 0, ACPI_THERMAL_MAX_LIMIT_STR_LEN);
-
-       active = kmalloc(ACPI_THERMAL_MAX_ACTIVE * sizeof(int), GFP_KERNEL);
-       if (!active) {
-               kfree(limit_string);
-               return_VALUE(-ENOMEM);
-       }
-
-       if (!tz || (count > ACPI_THERMAL_MAX_LIMIT_STR_LEN - 1)) {
-               ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid argument\n"));
-               count = -EINVAL;
-               goto end;
-       }
-
-       if (copy_from_user(limit_string, buffer, count)) {
-               ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid data\n"));
-               count = -EFAULT;
-               goto end;
-       }
-
-       limit_string[count] = '\0';
-
-       num = sscanf(limit_string, "%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d",
-                    &critical, &hot, &passive,
-                    &active[0], &active[1], &active[2], &active[3], &active[4],
-                    &active[5], &active[6], &active[7], &active[8],
-                    &active[9]);
-       if (!(num >= 5 && num < (ACPI_THERMAL_MAX_ACTIVE + 3))) {
-               ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid data format\n"));
-               count = -EINVAL;
-               goto end;
-       }
-
-       tz->trips.critical.temperature = CELSIUS_TO_KELVIN(critical);
-       tz->trips.hot.temperature = CELSIUS_TO_KELVIN(hot);
-       tz->trips.passive.temperature = CELSIUS_TO_KELVIN(passive);
-       for (i = 0; i < num - 3; i++) {
-               if (!(tz->trips.active[i].flags.valid))
-                       break;
-               tz->trips.active[i].temperature = CELSIUS_TO_KELVIN(active[i]);
-       }
-
-      end:
-       kfree(active);
-       kfree(limit_string);
-       return_VALUE(count);
-}
-
 static int acpi_thermal_cooling_seq_show(struct seq_file *seq, void *offset)
 {
-       struct acpi_thermal *tz = (struct acpi_thermal *)seq->private;
+       struct acpi_thermal *tz = seq->private;
 
-       ACPI_FUNCTION_TRACE("acpi_thermal_cooling_seq_show");
 
        if (!tz)
                goto end;
 
-       if (!tz->flags.cooling_mode) {
+       if (!tz->flags.cooling_mode)
                seq_puts(seq, "<setting not supported>\n");
-       }
-
-       if (tz->cooling_mode == ACPI_THERMAL_MODE_CRITICAL)
-               seq_printf(seq, "cooling mode:  critical\n");
        else
-               seq_printf(seq, "cooling mode:  %s\n",
-                          tz->cooling_mode ? "passive" : "active");
+               seq_puts(seq, "0 - Active; 1 - Passive\n");
 
       end:
-       return_VALUE(0);
+       return 0;
 }
 
 static int acpi_thermal_cooling_open_fs(struct inode *inode, struct file *file)
@@ -1021,21 +1350,20 @@ acpi_thermal_write_cooling_mode(struct file *file,
                                const char __user * buffer,
                                size_t count, loff_t * ppos)
 {
-       struct seq_file *m = (struct seq_file *)file->private_data;
-       struct acpi_thermal *tz = (struct acpi_thermal *)m->private;
+       struct seq_file *m = file->private_data;
+       struct acpi_thermal *tz = m->private;
        int result = 0;
        char mode_string[12] = { '\0' };
 
-       ACPI_FUNCTION_TRACE("acpi_thermal_write_cooling_mode");
 
        if (!tz || (count > sizeof(mode_string) - 1))
-               return_VALUE(-EINVAL);
+               return -EINVAL;
 
        if (!tz->flags.cooling_mode)
-               return_VALUE(-ENODEV);
+               return -ENODEV;
 
        if (copy_from_user(mode_string, buffer, count))
-               return_VALUE(-EFAULT);
+               return -EFAULT;
 
        mode_string[count] = '\0';
 
@@ -1043,18 +1371,17 @@ acpi_thermal_write_cooling_mode(struct file *file,
                                               simple_strtoul(mode_string, NULL,
                                                              0));
        if (result)
-               return_VALUE(result);
+               return result;
 
        acpi_thermal_check(tz);
 
-       return_VALUE(count);
+       return count;
 }
 
 static int acpi_thermal_polling_seq_show(struct seq_file *seq, void *offset)
 {
-       struct acpi_thermal *tz = (struct acpi_thermal *)seq->private;
+       struct acpi_thermal *tz = seq->private;
 
-       ACPI_FUNCTION_TRACE("acpi_thermal_polling_seq_show");
 
        if (!tz)
                goto end;
@@ -1068,7 +1395,7 @@ static int acpi_thermal_polling_seq_show(struct seq_file *seq, void *offset)
                   (tz->polling_frequency / 10));
 
       end:
-       return_VALUE(0);
+       return 0;
 }
 
 static int acpi_thermal_polling_open_fs(struct inode *inode, struct file *file)
@@ -1082,19 +1409,18 @@ acpi_thermal_write_polling(struct file *file,
                           const char __user * buffer,
                           size_t count, loff_t * ppos)
 {
-       struct seq_file *m = (struct seq_file *)file->private_data;
-       struct acpi_thermal *tz = (struct acpi_thermal *)m->private;
+       struct seq_file *m = file->private_data;
+       struct acpi_thermal *tz = m->private;
        int result = 0;
        char polling_string[12] = { '\0' };
        int seconds = 0;
 
-       ACPI_FUNCTION_TRACE("acpi_thermal_write_polling");
 
        if (!tz || (count > sizeof(polling_string) - 1))
-               return_VALUE(-EINVAL);
+               return -EINVAL;
 
        if (copy_from_user(polling_string, buffer, count))
-               return_VALUE(-EFAULT);
+               return -EFAULT;
 
        polling_string[count] = '\0';
 
@@ -1102,101 +1428,73 @@ acpi_thermal_write_polling(struct file *file,
 
        result = acpi_thermal_set_polling(tz, seconds);
        if (result)
-               return_VALUE(result);
+               return result;
 
        acpi_thermal_check(tz);
 
-       return_VALUE(count);
+       return count;
 }
 
 static int acpi_thermal_add_fs(struct acpi_device *device)
 {
        struct proc_dir_entry *entry = NULL;
 
-       ACPI_FUNCTION_TRACE("acpi_thermal_add_fs");
 
        if (!acpi_device_dir(device)) {
                acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
                                                     acpi_thermal_dir);
                if (!acpi_device_dir(device))
-                       return_VALUE(-ENODEV);
+                       return -ENODEV;
                acpi_device_dir(device)->owner = THIS_MODULE;
        }
 
        /* 'state' [R] */
-       entry = create_proc_entry(ACPI_THERMAL_FILE_STATE,
-                                 S_IRUGO, acpi_device_dir(device));
+       entry = proc_create_data(ACPI_THERMAL_FILE_STATE,
+                                S_IRUGO, acpi_device_dir(device),
+                                &acpi_thermal_state_fops,
+                                acpi_driver_data(device));
        if (!entry)
-               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-                                 "Unable to create '%s' fs entry\n",
-                                 ACPI_THERMAL_FILE_STATE));
-       else {
-               entry->proc_fops = &acpi_thermal_state_fops;
-               entry->data = acpi_driver_data(device);
-               entry->owner = THIS_MODULE;
-       }
+               return -ENODEV;
 
        /* 'temperature' [R] */
-       entry = create_proc_entry(ACPI_THERMAL_FILE_TEMPERATURE,
-                                 S_IRUGO, acpi_device_dir(device));
+       entry = proc_create_data(ACPI_THERMAL_FILE_TEMPERATURE,
+                                S_IRUGO, acpi_device_dir(device),
+                                &acpi_thermal_temp_fops,
+                                acpi_driver_data(device));
        if (!entry)
-               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-                                 "Unable to create '%s' fs entry\n",
-                                 ACPI_THERMAL_FILE_TEMPERATURE));
-       else {
-               entry->proc_fops = &acpi_thermal_temp_fops;
-               entry->data = acpi_driver_data(device);
-               entry->owner = THIS_MODULE;
-       }
-
-       /* 'trip_points' [R/W] */
-       entry = create_proc_entry(ACPI_THERMAL_FILE_TRIP_POINTS,
-                                 S_IFREG | S_IRUGO | S_IWUSR,
-                                 acpi_device_dir(device));
+               return -ENODEV;
+
+       /* 'trip_points' [R] */
+       entry = proc_create_data(ACPI_THERMAL_FILE_TRIP_POINTS,
+                                S_IRUGO,
+                                acpi_device_dir(device),
+                                &acpi_thermal_trip_fops,
+                                acpi_driver_data(device));
        if (!entry)
-               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-                                 "Unable to create '%s' fs entry\n",
-                                 ACPI_THERMAL_FILE_TRIP_POINTS));
-       else {
-               entry->proc_fops = &acpi_thermal_trip_fops;
-               entry->data = acpi_driver_data(device);
-               entry->owner = THIS_MODULE;
-       }
+               return -ENODEV;
 
        /* 'cooling_mode' [R/W] */
-       entry = create_proc_entry(ACPI_THERMAL_FILE_COOLING_MODE,
-                                 S_IFREG | S_IRUGO | S_IWUSR,
-                                 acpi_device_dir(device));
+       entry = proc_create_data(ACPI_THERMAL_FILE_COOLING_MODE,
+                                S_IFREG | S_IRUGO | S_IWUSR,
+                                acpi_device_dir(device),
+                                &acpi_thermal_cooling_fops,
+                                acpi_driver_data(device));
        if (!entry)
-               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-                                 "Unable to create '%s' fs entry\n",
-                                 ACPI_THERMAL_FILE_COOLING_MODE));
-       else {
-               entry->proc_fops = &acpi_thermal_cooling_fops;
-               entry->data = acpi_driver_data(device);
-               entry->owner = THIS_MODULE;
-       }
+               return -ENODEV;
 
        /* 'polling_frequency' [R/W] */
-       entry = create_proc_entry(ACPI_THERMAL_FILE_POLLING_FREQ,
-                                 S_IFREG | S_IRUGO | S_IWUSR,
-                                 acpi_device_dir(device));
+       entry = proc_create_data(ACPI_THERMAL_FILE_POLLING_FREQ,
+                                S_IFREG | S_IRUGO | S_IWUSR,
+                                acpi_device_dir(device),
+                                &acpi_thermal_polling_fops,
+                                acpi_driver_data(device));
        if (!entry)
-               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-                                 "Unable to create '%s' fs entry\n",
-                                 ACPI_THERMAL_FILE_POLLING_FREQ));
-       else {
-               entry->proc_fops = &acpi_thermal_polling_fops;
-               entry->data = acpi_driver_data(device);
-               entry->owner = THIS_MODULE;
-       }
-
-       return_VALUE(0);
+               return -ENODEV;
+       return 0;
 }
 
 static int acpi_thermal_remove_fs(struct acpi_device *device)
 {
-       ACPI_FUNCTION_TRACE("acpi_thermal_remove_fs");
 
        if (acpi_device_dir(device)) {
                remove_proc_entry(ACPI_THERMAL_FILE_POLLING_FREQ,
@@ -1213,7 +1511,7 @@ static int acpi_thermal_remove_fs(struct acpi_device *device)
                acpi_device_dir(device) = NULL;
        }
 
-       return_VALUE(0);
+       return 0;
 }
 
 /* --------------------------------------------------------------------------
@@ -1222,30 +1520,32 @@ static int acpi_thermal_remove_fs(struct acpi_device *device)
 
 static void acpi_thermal_notify(acpi_handle handle, u32 event, void *data)
 {
-       struct acpi_thermal *tz = (struct acpi_thermal *)data;
+       struct acpi_thermal *tz = data;
        struct acpi_device *device = NULL;
 
-       ACPI_FUNCTION_TRACE("acpi_thermal_notify");
 
        if (!tz)
-               return_VOID;
+               return;
 
-       if (acpi_bus_get_device(tz->handle, &device))
-               return_VOID;
+       device = tz->device;
 
        switch (event) {
        case ACPI_THERMAL_NOTIFY_TEMPERATURE:
                acpi_thermal_check(tz);
                break;
        case ACPI_THERMAL_NOTIFY_THRESHOLDS:
-               acpi_thermal_get_trip_points(tz);
+               acpi_thermal_trips_update(tz, ACPI_TRIPS_REFRESH_THRESHOLDS);
                acpi_thermal_check(tz);
-               acpi_bus_generate_event(device, event, 0);
+               acpi_bus_generate_proc_event(device, event, 0);
+               acpi_bus_generate_netlink_event(device->pnp.device_class,
+                                                 device->dev.bus_id, event, 0);
                break;
        case ACPI_THERMAL_NOTIFY_DEVICES:
-               if (tz->flags.devices)
-                       acpi_thermal_get_devices(tz);
-               acpi_bus_generate_event(device, event, 0);
+               acpi_thermal_trips_update(tz, ACPI_TRIPS_REFRESH_DEVICES);
+               acpi_thermal_check(tz);
+               acpi_bus_generate_proc_event(device, event, 0);
+               acpi_bus_generate_netlink_event(device->pnp.device_class,
+                                                 device->dev.bus_id, event, 0);
                break;
        default:
                ACPI_DEBUG_PRINT((ACPI_DB_INFO,
@@ -1253,54 +1553,31 @@ static void acpi_thermal_notify(acpi_handle handle, u32 event, void *data)
                break;
        }
 
-       return_VOID;
+       return;
 }
 
 static int acpi_thermal_get_info(struct acpi_thermal *tz)
 {
        int result = 0;
 
-       ACPI_FUNCTION_TRACE("acpi_thermal_get_info");
 
        if (!tz)
-               return_VALUE(-EINVAL);
+               return -EINVAL;
 
        /* Get temperature [_TMP] (required) */
        result = acpi_thermal_get_temperature(tz);
        if (result)
-               return_VALUE(result);
+               return result;
 
        /* Get trip points [_CRT, _PSV, etc.] (required) */
        result = acpi_thermal_get_trip_points(tz);
        if (result)
-               return_VALUE(result);
+               return result;
 
        /* Set the cooling mode [_SCP] to active cooling (default) */
        result = acpi_thermal_set_cooling_mode(tz, ACPI_THERMAL_MODE_ACTIVE);
        if (!result)
                tz->flags.cooling_mode = 1;
-       else {
-               /* Oh,we have not _SCP method.
-                  Generally show cooling_mode by _ACx, _PSV,spec 12.2 */
-               tz->flags.cooling_mode = 0;
-               if (tz->trips.active[0].flags.valid
-                   && tz->trips.passive.flags.valid) {
-                       if (tz->trips.passive.temperature >
-                           tz->trips.active[0].temperature)
-                               tz->cooling_mode = ACPI_THERMAL_MODE_ACTIVE;
-                       else
-                               tz->cooling_mode = ACPI_THERMAL_MODE_PASSIVE;
-               } else if (!tz->trips.active[0].flags.valid
-                          && tz->trips.passive.flags.valid) {
-                       tz->cooling_mode = ACPI_THERMAL_MODE_PASSIVE;
-               } else if (tz->trips.active[0].flags.valid
-                          && !tz->trips.passive.flags.valid) {
-                       tz->cooling_mode = ACPI_THERMAL_MODE_ACTIVE;
-               } else {
-                       /* _ACx and _PSV are optional, but _CRT is required */
-                       tz->cooling_mode = ACPI_THERMAL_MODE_CRITICAL;
-               }
-       }
 
        /* Get default polling frequency [_TZP] (optional) */
        if (tzp)
@@ -1308,12 +1585,7 @@ static int acpi_thermal_get_info(struct acpi_thermal *tz)
        else
                acpi_thermal_get_polling_frequency(tz);
 
-       /* Get devices in this thermal zone [_TZD] (optional) */
-       result = acpi_thermal_get_devices(tz);
-       if (!result)
-               tz->flags.devices = 1;
-
-       return_VALUE(0);
+       return 0;
 }
 
 static int acpi_thermal_add(struct acpi_device *device)
@@ -1322,55 +1594,59 @@ static int acpi_thermal_add(struct acpi_device *device)
        acpi_status status = AE_OK;
        struct acpi_thermal *tz = NULL;
 
-       ACPI_FUNCTION_TRACE("acpi_thermal_add");
 
        if (!device)
-               return_VALUE(-EINVAL);
+               return -EINVAL;
 
-       tz = kmalloc(sizeof(struct acpi_thermal), GFP_KERNEL);
+       tz = kzalloc(sizeof(struct acpi_thermal), GFP_KERNEL);
        if (!tz)
-               return_VALUE(-ENOMEM);
-       memset(tz, 0, sizeof(struct acpi_thermal));
+               return -ENOMEM;
 
-       tz->handle = device->handle;
+       tz->device = device;
        strcpy(tz->name, device->pnp.bus_id);
        strcpy(acpi_device_name(device), ACPI_THERMAL_DEVICE_NAME);
        strcpy(acpi_device_class(device), ACPI_THERMAL_CLASS);
        acpi_driver_data(device) = tz;
+       mutex_init(&tz->lock);
+
 
        result = acpi_thermal_get_info(tz);
        if (result)
-               goto end;
+               goto free_memory;
+
+       result = acpi_thermal_register_thermal_zone(tz);
+       if (result)
+               goto free_memory;
 
        result = acpi_thermal_add_fs(device);
        if (result)
-               return_VALUE(result);
+               goto unregister_thermal_zone;
 
        init_timer(&tz->timer);
 
        acpi_thermal_check(tz);
 
-       status = acpi_install_notify_handler(tz->handle,
+       status = acpi_install_notify_handler(device->handle,
                                             ACPI_DEVICE_NOTIFY,
                                             acpi_thermal_notify, tz);
        if (ACPI_FAILURE(status)) {
-               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-                                 "Error installing notify handler\n"));
                result = -ENODEV;
-               goto end;
+               goto remove_fs;
        }
 
        printk(KERN_INFO PREFIX "%s [%s] (%ld C)\n",
               acpi_device_name(device), acpi_device_bid(device),
               KELVIN_TO_CELSIUS(tz->temperature));
+       goto end;
 
-      end:
-       if (result) {
-               acpi_thermal_remove_fs(device);
-               kfree(tz);
-       }
-
-       return_VALUE(result);
+remove_fs:
+       acpi_thermal_remove_fs(device);
+unregister_thermal_zone:
+       thermal_zone_device_unregister(tz->thermal_zone);
+free_memory:
+       kfree(tz);
+end:
+       return result;
 }
 
 static int acpi_thermal_remove(struct acpi_device *device, int type)
@@ -1378,12 +1654,11 @@ static int acpi_thermal_remove(struct acpi_device *device, int type)
        acpi_status status = AE_OK;
        struct acpi_thermal *tz = NULL;
 
-       ACPI_FUNCTION_TRACE("acpi_thermal_remove");
 
        if (!device || !acpi_driver_data(device))
-               return_VALUE(-EINVAL);
+               return -EINVAL;
 
-       tz = (struct acpi_thermal *)acpi_driver_data(device);
+       tz = acpi_driver_data(device);
 
        /* avoid timer adding new defer task */
        tz->zombie = 1;
@@ -1394,12 +1669,9 @@ static int acpi_thermal_remove(struct acpi_device *device, int type)
        /* deferred task may reinsert timer */
        del_timer_sync(&(tz->timer));
 
-       status = acpi_remove_notify_handler(tz->handle,
+       status = acpi_remove_notify_handler(device->handle,
                                            ACPI_DEVICE_NOTIFY,
                                            acpi_thermal_notify);
-       if (ACPI_FAILURE(status))
-               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-                                 "Error removing notify handler\n"));
 
        /* Terminate policy */
        if (tz->trips.passive.flags.valid && tz->trips.passive.flags.enabled) {
@@ -1413,40 +1685,152 @@ static int acpi_thermal_remove(struct acpi_device *device, int type)
        }
 
        acpi_thermal_remove_fs(device);
-
+       acpi_thermal_unregister_thermal_zone(tz);
+       mutex_destroy(&tz->lock);
        kfree(tz);
-       return_VALUE(0);
+       return 0;
+}
+
+static int acpi_thermal_resume(struct acpi_device *device)
+{
+       struct acpi_thermal *tz = NULL;
+       int i, j, power_state, result;
+
+
+       if (!device || !acpi_driver_data(device))
+               return -EINVAL;
+
+       tz = acpi_driver_data(device);
+
+       for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
+               if (!(&tz->trips.active[i]))
+                       break;
+               if (!tz->trips.active[i].flags.valid)
+                       break;
+               tz->trips.active[i].flags.enabled = 1;
+               for (j = 0; j < tz->trips.active[i].devices.count; j++) {
+                       result = acpi_bus_get_power(tz->trips.active[i].devices.
+                           handles[j], &power_state);
+                       if (result || (power_state != ACPI_STATE_D0)) {
+                               tz->trips.active[i].flags.enabled = 0;
+                               break;
+                       }
+               }
+               tz->state.active |= tz->trips.active[i].flags.enabled;
+       }
+
+       acpi_thermal_check(tz);
+
+       return AE_OK;
 }
 
+static int thermal_act(const struct dmi_system_id *d) {
+
+       if (act == 0) {
+               printk(KERN_NOTICE "ACPI: %s detected: "
+                       "disabling all active thermal trip points\n", d->ident);
+               act = -1;
+       }
+       return 0;
+}
+static int thermal_nocrt(const struct dmi_system_id *d) {
+
+       printk(KERN_NOTICE "ACPI: %s detected: "
+               "disabling all critical thermal trip point actions.\n", d->ident);
+       nocrt = 1;
+       return 0;
+}
+static int thermal_tzp(const struct dmi_system_id *d) {
+
+       if (tzp == 0) {
+               printk(KERN_NOTICE "ACPI: %s detected: "
+                       "enabling thermal zone polling\n", d->ident);
+               tzp = 300;      /* 300 dS = 30 Seconds */
+       }
+       return 0;
+}
+static int thermal_psv(const struct dmi_system_id *d) {
+
+       if (psv == 0) {
+               printk(KERN_NOTICE "ACPI: %s detected: "
+                       "disabling all passive thermal trip points\n", d->ident);
+               psv = -1;
+       }
+       return 0;
+}
+
+static struct dmi_system_id thermal_dmi_table[] __initdata = {
+       /*
+        * Award BIOS on this AOpen makes thermal control almost worthless.
+        * http://bugzilla.kernel.org/show_bug.cgi?id=8842
+        */
+       {
+        .callback = thermal_act,
+        .ident = "AOpen i915GMm-HFS",
+        .matches = {
+               DMI_MATCH(DMI_BOARD_VENDOR, "AOpen"),
+               DMI_MATCH(DMI_BOARD_NAME, "i915GMm-HFS"),
+               },
+       },
+       {
+        .callback = thermal_psv,
+        .ident = "AOpen i915GMm-HFS",
+        .matches = {
+               DMI_MATCH(DMI_BOARD_VENDOR, "AOpen"),
+               DMI_MATCH(DMI_BOARD_NAME, "i915GMm-HFS"),
+               },
+       },
+       {
+        .callback = thermal_tzp,
+        .ident = "AOpen i915GMm-HFS",
+        .matches = {
+               DMI_MATCH(DMI_BOARD_VENDOR, "AOpen"),
+               DMI_MATCH(DMI_BOARD_NAME, "i915GMm-HFS"),
+               },
+       },
+       {
+        .callback = thermal_nocrt,
+        .ident = "Gigabyte GA-7ZX",
+        .matches = {
+               DMI_MATCH(DMI_BOARD_VENDOR, "Gigabyte Technology Co., Ltd."),
+               DMI_MATCH(DMI_BOARD_NAME, "7ZX"),
+               },
+       },
+       {}
+};
+
 static int __init acpi_thermal_init(void)
 {
        int result = 0;
 
-       ACPI_FUNCTION_TRACE("acpi_thermal_init");
+       dmi_check_system(thermal_dmi_table);
 
+       if (off) {
+               printk(KERN_NOTICE "ACPI: thermal control disabled\n");
+               return -ENODEV;
+       }
        acpi_thermal_dir = proc_mkdir(ACPI_THERMAL_CLASS, acpi_root_dir);
        if (!acpi_thermal_dir)
-               return_VALUE(-ENODEV);
+               return -ENODEV;
        acpi_thermal_dir->owner = THIS_MODULE;
 
        result = acpi_bus_register_driver(&acpi_thermal_driver);
        if (result < 0) {
                remove_proc_entry(ACPI_THERMAL_CLASS, acpi_root_dir);
-               return_VALUE(-ENODEV);
+               return -ENODEV;
        }
 
-       return_VALUE(0);
+       return 0;
 }
 
 static void __exit acpi_thermal_exit(void)
 {
-       ACPI_FUNCTION_TRACE("acpi_thermal_exit");
 
        acpi_bus_unregister_driver(&acpi_thermal_driver);
 
        remove_proc_entry(ACPI_THERMAL_CLASS, acpi_root_dir);
 
-       return_VOID;
+       return;
 }
 
 module_init(acpi_thermal_init);