Merge git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-rc-fixes-2.6
[linux-2.6.git] / drivers / thermal / thermal_sys.c
index 0a69672..13c72c6 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/module.h>
 #include <linux/device.h>
 #include <linux/err.h>
+#include <linux/slab.h>
 #include <linux/kdev_t.h>
 #include <linux/idr.h>
 #include <linux/thermal.h>
@@ -180,15 +181,15 @@ trip_point_type_show(struct device *dev, struct device_attribute *attr,
 
        switch (type) {
        case THERMAL_TRIP_CRITICAL:
-               return sprintf(buf, "critical");
+               return sprintf(buf, "critical\n");
        case THERMAL_TRIP_HOT:
-               return sprintf(buf, "hot");
+               return sprintf(buf, "hot\n");
        case THERMAL_TRIP_PASSIVE:
-               return sprintf(buf, "passive");
+               return sprintf(buf, "passive\n");
        case THERMAL_TRIP_ACTIVE:
-               return sprintf(buf, "active");
+               return sprintf(buf, "active\n");
        default:
-               return sprintf(buf, "unknown");
+               return sprintf(buf, "unknown\n");
        }
 }
 
@@ -225,6 +226,12 @@ passive_store(struct device *dev, struct device_attribute *attr,
        if (!sscanf(buf, "%d\n", &state))
                return -EINVAL;
 
+       /* sanity check: values below 1000 millicelcius don't make sense
+        * and can cause the system to go into a thermal heart attack
+        */
+       if (state && state < 1000)
+               return -EINVAL;
+
        if (state && !tz->forced_passive) {
                mutex_lock(&thermal_list_lock);
                list_for_each_entry(cdev, &thermal_cdev_list, node) {
@@ -235,6 +242,8 @@ passive_store(struct device *dev, struct device_attribute *attr,
                                                                 cdev);
                }
                mutex_unlock(&thermal_list_lock);
+               if (!tz->passive_delay)
+                       tz->passive_delay = 1000;
        } else if (!state && tz->forced_passive) {
                mutex_lock(&thermal_list_lock);
                list_for_each_entry(cdev, &thermal_cdev_list, node) {
@@ -245,17 +254,12 @@ passive_store(struct device *dev, struct device_attribute *attr,
                                                                   cdev);
                }
                mutex_unlock(&thermal_list_lock);
+               tz->passive_delay = 0;
        }
 
        tz->tc1 = 1;
        tz->tc2 = 1;
 
-       if (!tz->passive_delay)
-               tz->passive_delay = 1000;
-
-       if (!tz->polling_delay)
-               tz->polling_delay = 10000;
-
        tz->forced_passive = state;
 
        thermal_zone_device_update(tz);
@@ -374,7 +378,7 @@ thermal_cooling_device_cur_state_store(struct device *dev,
        if (!sscanf(buf, "%ld\n", &state))
                return -EINVAL;
 
-       if (state < 0)
+       if ((long)state < 0)
                return -EINVAL;
 
        result = cdev->ops->set_cur_state(cdev, state);
@@ -502,6 +506,7 @@ thermal_add_hwmon_sysfs(struct thermal_zone_device *tz)
        tz->temp_input.attr.attr.name = tz->temp_input.name;
        tz->temp_input.attr.attr.mode = 0444;
        tz->temp_input.attr.show = temp_input_show;
+       sysfs_attr_init(&tz->temp_input.attr.attr);
        result = device_create_file(hwmon->device, &tz->temp_input.attr);
        if (result)
                goto unregister_hwmon_device;
@@ -514,6 +519,7 @@ thermal_add_hwmon_sysfs(struct thermal_zone_device *tz)
                        tz->temp_crit.attr.attr.name = tz->temp_crit.name;
                        tz->temp_crit.attr.attr.mode = 0444;
                        tz->temp_crit.attr.show = temp_crit_show;
+                       sysfs_attr_init(&tz->temp_crit.attr.attr);
                        result = device_create_file(hwmon->device,
                                                    &tz->temp_crit.attr);
                        if (result)
@@ -722,6 +728,7 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz,
                goto release_idr;
 
        sprintf(dev->attr_name, "cdev%d_trip_point", dev->id);
+       sysfs_attr_init(&dev->attr.attr);
        dev->attr.attr.name = dev->attr_name;
        dev->attr.attr.mode = 0444;
        dev->attr.show = thermal_cooling_device_trip_point_show;
@@ -953,7 +960,12 @@ void thermal_zone_device_update(struct thermal_zone_device *tz)
 
        mutex_lock(&tz->lock);
 
-       tz->ops->get_temp(tz, &temp);
+       if (tz->ops->get_temp(tz, &temp)) {
+               /* get_temp failed - retry it later */
+               printk(KERN_WARNING PREFIX "failed to read out thermal zone "
+                      "%d\n", tz->id);
+               goto leave;
+       }
 
        for (count = 0; count < tz->trips; count++) {
                tz->ops->get_trip_type(tz, count, &trip_type);
@@ -1005,10 +1017,14 @@ void thermal_zone_device_update(struct thermal_zone_device *tz)
                                            THERMAL_TRIPS_NONE);
 
        tz->last_temperature = temp;
+
+      leave:
        if (tz->passive)
                thermal_zone_device_set_polling(tz, tz->passive_delay);
        else if (tz->polling_delay)
                thermal_zone_device_set_polling(tz, tz->polling_delay);
+       else
+               thermal_zone_device_set_polling(tz, 0);
        mutex_unlock(&tz->lock);
 }
 EXPORT_SYMBOL(thermal_zone_device_update);