]> Pileus Git - ~andy/linux/blobdiff - drivers/acpi/thermal.c
Merge branch 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux...
[~andy/linux] / drivers / acpi / thermal.c
index edda74a43406b5232c01a65ac030303abab830f4..804204d41999d0af951086f25b37a2f7ee783a90 100644 (file)
@@ -708,6 +708,40 @@ static int thermal_get_crit_temp(struct thermal_zone_device *thermal,
                return -EINVAL;
 }
 
+static int thermal_get_trend(struct thermal_zone_device *thermal,
+                               int trip, enum thermal_trend *trend)
+{
+       struct acpi_thermal *tz = thermal->devdata;
+       enum thermal_trip_type type;
+       int i;
+
+       if (thermal_get_trip_type(thermal, trip, &type))
+               return -EINVAL;
+
+       if (type == THERMAL_TRIP_ACTIVE) {
+               /* aggressive active cooling */
+               *trend = THERMAL_TREND_RAISING;
+               return 0;
+       }
+
+       /*
+        * tz->temperature has already been updated by generic thermal layer,
+        * before this callback being invoked
+        */
+       i = (tz->trips.passive.tc1 * (tz->temperature - tz->last_temperature))
+               + (tz->trips.passive.tc2
+               * (tz->temperature - tz->trips.passive.temperature));
+
+       if (i > 0)
+               *trend = THERMAL_TREND_RAISING;
+       else if (i < 0)
+               *trend = THERMAL_TREND_DROPPING;
+       else
+               *trend = THERMAL_TREND_STABLE;
+       return 0;
+}
+
+
 static int thermal_notify(struct thermal_zone_device *thermal, int trip,
                           enum thermal_trip_type trip_type)
 {
@@ -731,11 +765,9 @@ static int thermal_notify(struct thermal_zone_device *thermal, int trip,
        return 0;
 }
 
-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)
+                                       bool bind)
 {
        struct acpi_device *device = cdev->devdata;
        struct acpi_thermal *tz = thermal->devdata;
@@ -759,11 +791,19 @@ static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal,
                    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;
-                       }
+                       if (ACPI_FAILURE(status) || dev != device)
+                               continue;
+                       if (bind)
+                               result =
+                                       thermal_zone_bind_cooling_device
+                                       (thermal, trip, cdev,
+                                        THERMAL_NO_LIMIT, THERMAL_NO_LIMIT);
+                       else
+                               result =
+                                       thermal_zone_unbind_cooling_device
+                                       (thermal, trip, cdev);
+                       if (result)
+                               goto failed;
                }
        }
 
@@ -776,11 +816,17 @@ static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal,
                    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;
-                       }
+                       if (ACPI_FAILURE(status) || dev != device)
+                               continue;
+                       if (bind)
+                               result = thermal_zone_bind_cooling_device
+                                       (thermal, trip, cdev,
+                                        THERMAL_NO_LIMIT, THERMAL_NO_LIMIT);
+                       else
+                               result = thermal_zone_unbind_cooling_device
+                                       (thermal, trip, cdev);
+                       if (result)
+                               goto failed;
                }
        }
 
@@ -788,7 +834,14 @@ static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal,
                handle = tz->devices.handles[i];
                status = acpi_bus_get_device(handle, &dev);
                if (ACPI_SUCCESS(status) && (dev == device)) {
-                       result = action(thermal, -1, cdev);
+                       if (bind)
+                               result = thermal_zone_bind_cooling_device
+                                               (thermal, -1, cdev,
+                                                THERMAL_NO_LIMIT,
+                                                THERMAL_NO_LIMIT);
+                       else
+                               result = thermal_zone_unbind_cooling_device
+                                               (thermal, -1, cdev);
                        if (result)
                                goto failed;
                }
@@ -802,16 +855,14 @@ 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);
+       return acpi_thermal_cooling_device_cb(thermal, cdev, true);
 }
 
 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);
+       return acpi_thermal_cooling_device_cb(thermal, cdev, false);
 }
 
 static const struct thermal_zone_device_ops acpi_thermal_zone_ops = {
@@ -823,6 +874,7 @@ static const struct thermal_zone_device_ops acpi_thermal_zone_ops = {
        .get_trip_type = thermal_get_trip_type,
        .get_trip_temp = thermal_get_trip_temp,
        .get_crit_temp = thermal_get_crit_temp,
+       .get_trend = thermal_get_trend,
        .notify = thermal_notify,
 };
 
@@ -849,15 +901,12 @@ static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz)
                tz->thermal_zone =
                        thermal_zone_device_register("acpitz", trips, 0, tz,
                                                     &acpi_thermal_zone_ops,
-                                                    tz->trips.passive.tc1,
-                                                    tz->trips.passive.tc2,
                                                     tz->trips.passive.tsp*100,
                                                     tz->polling_frequency*100);
        else
                tz->thermal_zone =
                        thermal_zone_device_register("acpitz", trips, 0, tz,
-                                                    &acpi_thermal_zone_ops,
-                                                    0, 0, 0,
+                                                    &acpi_thermal_zone_ops, 0,
                                                     tz->polling_frequency*100);
        if (IS_ERR(tz->thermal_zone))
                return -ENODEV;