sky2: dont enable PME legacy mode
[safe/jmp/linux-2.6] / drivers / acpi / thermal.c
index 6b95997..9073ada 100644 (file)
@@ -47,6 +47,8 @@
 #include <acpi/acpi_bus.h>
 #include <acpi/acpi_drivers.h>
 
+#define PREFIX "ACPI: "
+
 #define ACPI_THERMAL_CLASS             "thermal_zone"
 #define ACPI_THERMAL_DEVICE_NAME       "Thermal Zone"
 #define ACPI_THERMAL_FILE_STATE                "state"
@@ -98,6 +100,7 @@ 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 void acpi_thermal_notify(struct acpi_device *device, u32 event);
 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);
@@ -123,6 +126,7 @@ static struct acpi_driver acpi_thermal_driver = {
                .add = acpi_thermal_add,
                .remove = acpi_thermal_remove,
                .resume = acpi_thermal_resume,
+               .notify = acpi_thermal_notify,
                },
 };
 
@@ -192,6 +196,7 @@ struct acpi_thermal {
        struct acpi_handle_list devices;
        struct thermal_zone_device *thermal_zone;
        int tz_enabled;
+       int kelvin_offset;
        struct mutex lock;
 };
 
@@ -371,7 +376,7 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
                /*
                 * 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..
+                * Below zero (Celsius) values clearly aren't right for sure..
                 * ... so lets discard those as invalid.
                 */
                if (ACPI_FAILURE(status) ||
@@ -581,7 +586,7 @@ static void acpi_thermal_check(void *data)
 }
 
 /* sys I/F for generic thermal sysfs support */
-#define KELVIN_TO_MILLICELSIUS(t) (t * 100 - 273200)
+#define KELVIN_TO_MILLICELSIUS(t, off) (((t) - (off)) * 100)
 
 static int thermal_get_temp(struct thermal_zone_device *thermal,
                            unsigned long *temp)
@@ -596,7 +601,7 @@ static int thermal_get_temp(struct thermal_zone_device *thermal,
        if (result)
                return result;
 
-       *temp = KELVIN_TO_MILLICELSIUS(tz->temperature);
+       *temp = KELVIN_TO_MILLICELSIUS(tz->temperature, tz->kelvin_offset);
        return 0;
 }
 
@@ -702,7 +707,8 @@ static int thermal_get_trip_temp(struct thermal_zone_device *thermal,
        if (tz->trips.critical.flags.valid) {
                if (!trip) {
                        *temp = KELVIN_TO_MILLICELSIUS(
-                               tz->trips.critical.temperature);
+                               tz->trips.critical.temperature,
+                               tz->kelvin_offset);
                        return 0;
                }
                trip--;
@@ -711,7 +717,8 @@ static int thermal_get_trip_temp(struct thermal_zone_device *thermal,
        if (tz->trips.hot.flags.valid) {
                if (!trip) {
                        *temp = KELVIN_TO_MILLICELSIUS(
-                               tz->trips.hot.temperature);
+                               tz->trips.hot.temperature,
+                               tz->kelvin_offset);
                        return 0;
                }
                trip--;
@@ -720,7 +727,8 @@ static int thermal_get_trip_temp(struct thermal_zone_device *thermal,
        if (tz->trips.passive.flags.valid) {
                if (!trip) {
                        *temp = KELVIN_TO_MILLICELSIUS(
-                               tz->trips.passive.temperature);
+                               tz->trips.passive.temperature,
+                               tz->kelvin_offset);
                        return 0;
                }
                trip--;
@@ -730,7 +738,8 @@ static int thermal_get_trip_temp(struct thermal_zone_device *thermal,
                tz->trips.active[i].flags.valid; i++) {
                if (!trip) {
                        *temp = KELVIN_TO_MILLICELSIUS(
-                               tz->trips.active[i].temperature);
+                               tz->trips.active[i].temperature,
+                               tz->kelvin_offset);
                        return 0;
                }
                trip--;
@@ -745,7 +754,8 @@ static int thermal_get_crit_temp(struct thermal_zone_device *thermal,
 
        if (tz->trips.critical.flags.valid) {
                *temperature = KELVIN_TO_MILLICELSIUS(
-                               tz->trips.critical.temperature);
+                               tz->trips.critical.temperature,
+                               tz->kelvin_offset);
                return 0;
        } else
                return -EINVAL;
@@ -901,7 +911,7 @@ static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz)
                        thermal_zone_device_register("acpitz", trips, tz,
                                                     &acpi_thermal_zone_ops,
                                                     0, 0, 0,
-                                                    tz->polling_frequency);
+                                                    tz->polling_frequency*100);
        if (IS_ERR(tz->thermal_zone))
                return -ENODEV;
 
@@ -1042,6 +1052,13 @@ static int acpi_thermal_trip_seq_show(struct seq_file *seq, void *offset)
                                   acpi_device_bid(device));
                }
                seq_puts(seq, "\n");
+       } else {
+               seq_printf(seq, "passive (forced):");
+               if (tz->thermal_zone->forced_passive)
+                       seq_printf(seq, "        %i C\n",
+                                  tz->thermal_zone->forced_passive / 1000);
+               else
+                       seq_printf(seq, "<not set>\n");
        }
 
        for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
@@ -1192,7 +1209,6 @@ static int acpi_thermal_add_fs(struct acpi_device *device)
                                                     acpi_thermal_dir);
                if (!acpi_device_dir(device))
                        return -ENODEV;
-               acpi_device_dir(device)->owner = THIS_MODULE;
        }
 
        /* 'state' [R] */
@@ -1265,17 +1281,14 @@ static int acpi_thermal_remove_fs(struct acpi_device *device)
                                  Driver Interface
    -------------------------------------------------------------------------- */
 
-static void acpi_thermal_notify(acpi_handle handle, u32 event, void *data)
+static void acpi_thermal_notify(struct acpi_device *device, u32 event)
 {
-       struct acpi_thermal *tz = data;
-       struct acpi_device *device = NULL;
+       struct acpi_thermal *tz = acpi_driver_data(device);
 
 
        if (!tz)
                return;
 
-       device = tz->device;
-
        switch (event) {
        case ACPI_THERMAL_NOTIFY_TEMPERATURE:
                acpi_thermal_check(tz);
@@ -1299,8 +1312,6 @@ static void acpi_thermal_notify(acpi_handle handle, u32 event, void *data)
                                  "Unsupported event [0x%x]\n", event));
                break;
        }
-
-       return;
 }
 
 static int acpi_thermal_get_info(struct acpi_thermal *tz)
@@ -1335,10 +1346,28 @@ static int acpi_thermal_get_info(struct acpi_thermal *tz)
        return 0;
 }
 
+/*
+ * The exact offset between Kelvin and degree Celsius is 273.15. However ACPI
+ * handles temperature values with a single decimal place. As a consequence,
+ * some implementations use an offset of 273.1 and others use an offset of
+ * 273.2. Try to find out which one is being used, to present the most
+ * accurate and visually appealing number.
+ *
+ * The heuristic below should work for all ACPI thermal zones which have a
+ * critical trip point with a value being a multiple of 0.5 degree Celsius.
+ */
+static void acpi_thermal_guess_offset(struct acpi_thermal *tz)
+{
+       if (tz->trips.critical.flags.valid &&
+           (tz->trips.critical.temperature % 5) == 1)
+               tz->kelvin_offset = 2731;
+       else
+               tz->kelvin_offset = 2732;
+}
+
 static int acpi_thermal_add(struct acpi_device *device)
 {
        int result = 0;
-       acpi_status status = AE_OK;
        struct acpi_thermal *tz = NULL;
 
 
@@ -1361,6 +1390,8 @@ static int acpi_thermal_add(struct acpi_device *device)
        if (result)
                goto free_memory;
 
+       acpi_thermal_guess_offset(tz);
+
        result = acpi_thermal_register_thermal_zone(tz);
        if (result)
                goto free_memory;
@@ -1369,21 +1400,11 @@ static int acpi_thermal_add(struct acpi_device *device)
        if (result)
                goto unregister_thermal_zone;
 
-       status = acpi_install_notify_handler(device->handle,
-                                            ACPI_DEVICE_NOTIFY,
-                                            acpi_thermal_notify, tz);
-       if (ACPI_FAILURE(status)) {
-               result = -ENODEV;
-               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;
 
-remove_fs:
-       acpi_thermal_remove_fs(device);
 unregister_thermal_zone:
        thermal_zone_device_unregister(tz->thermal_zone);
 free_memory:
@@ -1394,7 +1415,6 @@ end:
 
 static int acpi_thermal_remove(struct acpi_device *device, int type)
 {
-       acpi_status status = AE_OK;
        struct acpi_thermal *tz = NULL;
 
        if (!device || !acpi_driver_data(device))
@@ -1402,10 +1422,6 @@ static int acpi_thermal_remove(struct acpi_device *device, int type)
 
        tz = acpi_driver_data(device);
 
-       status = acpi_remove_notify_handler(device->handle,
-                                           ACPI_DEVICE_NOTIFY,
-                                           acpi_thermal_notify);
-
        acpi_thermal_remove_fs(device);
        acpi_thermal_unregister_thermal_zone(tz);
        mutex_destroy(&tz->lock);
@@ -1534,7 +1550,6 @@ static int __init acpi_thermal_init(void)
        acpi_thermal_dir = proc_mkdir(ACPI_THERMAL_CLASS, acpi_root_dir);
        if (!acpi_thermal_dir)
                return -ENODEV;
-       acpi_thermal_dir->owner = THIS_MODULE;
 
        result = acpi_bus_register_driver(&acpi_thermal_driver);
        if (result < 0) {