diff options
author | Zhang Rui <rui.zhang@intel.com> | 2012-06-26 04:35:57 -0400 |
---|---|---|
committer | Zhang Rui <rui.zhang@intel.com> | 2012-09-24 02:44:36 -0400 |
commit | 9d99842f99d847191ebd0c28469d2c70fcc5bf9e (patch) | |
tree | 211624d5fbc557c1226b6270a96807acc3b383df | |
parent | 74051ba50583a5880d4536c1d9333e2493ddfd76 (diff) |
Thermal: set upper and lower limits
set upper and lower limits when binding
a thermal cooling device to a thermal zone device.
Signed-off-by: Zhang Rui <rui.zhang@intel.com>
Reviewed-by: Rafael J. Wysocki <rjw@sisk.pl>
Reviewed-by: Eduardo Valentin <eduardo.valentin@ti.com>
-rw-r--r-- | Documentation/thermal/sysfs-api.txt | 9 | ||||
-rw-r--r-- | drivers/acpi/thermal.c | 53 | ||||
-rw-r--r-- | drivers/platform/x86/acerhdf.c | 3 | ||||
-rw-r--r-- | drivers/thermal/thermal_sys.c | 23 | ||||
-rw-r--r-- | include/linux/thermal.h | 5 |
5 files changed, 65 insertions, 28 deletions
diff --git a/Documentation/thermal/sysfs-api.txt b/Documentation/thermal/sysfs-api.txt index c087dbcf3535..ca1a1a34970e 100644 --- a/Documentation/thermal/sysfs-api.txt +++ b/Documentation/thermal/sysfs-api.txt | |||
@@ -84,7 +84,8 @@ temperature) and throttle appropriate devices. | |||
84 | 84 | ||
85 | 1.3 interface for binding a thermal zone device with a thermal cooling device | 85 | 1.3 interface for binding a thermal zone device with a thermal cooling device |
86 | 1.3.1 int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz, | 86 | 1.3.1 int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz, |
87 | int trip, struct thermal_cooling_device *cdev); | 87 | int trip, struct thermal_cooling_device *cdev, |
88 | unsigned long upper, unsigned long lower); | ||
88 | 89 | ||
89 | This interface function bind a thermal cooling device to the certain trip | 90 | This interface function bind a thermal cooling device to the certain trip |
90 | point of a thermal zone device. | 91 | point of a thermal zone device. |
@@ -93,6 +94,12 @@ temperature) and throttle appropriate devices. | |||
93 | cdev: thermal cooling device | 94 | cdev: thermal cooling device |
94 | trip: indicates which trip point the cooling devices is associated with | 95 | trip: indicates which trip point the cooling devices is associated with |
95 | in this thermal zone. | 96 | in this thermal zone. |
97 | upper:the Maximum cooling state for this trip point. | ||
98 | THERMAL_NO_LIMIT means no upper limit, | ||
99 | and the cooling device can be in max_state. | ||
100 | lower:the Minimum cooling state can be used for this trip point. | ||
101 | THERMAL_NO_LIMIT means no lower limit, | ||
102 | and the cooling device can be in cooling state 0. | ||
96 | 103 | ||
97 | 1.3.2 int thermal_zone_unbind_cooling_device(struct thermal_zone_device *tz, | 104 | 1.3.2 int thermal_zone_unbind_cooling_device(struct thermal_zone_device *tz, |
98 | int trip, struct thermal_cooling_device *cdev); | 105 | int trip, struct thermal_cooling_device *cdev); |
diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index 9fe90e9fecb5..d7ef69d835f2 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c | |||
@@ -729,11 +729,9 @@ static int thermal_notify(struct thermal_zone_device *thermal, int trip, | |||
729 | return 0; | 729 | return 0; |
730 | } | 730 | } |
731 | 731 | ||
732 | typedef int (*cb)(struct thermal_zone_device *, int, | ||
733 | struct thermal_cooling_device *); | ||
734 | static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal, | 732 | static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal, |
735 | struct thermal_cooling_device *cdev, | 733 | struct thermal_cooling_device *cdev, |
736 | cb action) | 734 | bool bind) |
737 | { | 735 | { |
738 | struct acpi_device *device = cdev->devdata; | 736 | struct acpi_device *device = cdev->devdata; |
739 | struct acpi_thermal *tz = thermal->devdata; | 737 | struct acpi_thermal *tz = thermal->devdata; |
@@ -757,11 +755,19 @@ static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal, | |||
757 | i++) { | 755 | i++) { |
758 | handle = tz->trips.passive.devices.handles[i]; | 756 | handle = tz->trips.passive.devices.handles[i]; |
759 | status = acpi_bus_get_device(handle, &dev); | 757 | status = acpi_bus_get_device(handle, &dev); |
760 | if (ACPI_SUCCESS(status) && (dev == device)) { | 758 | if (ACPI_FAILURE(status) || dev != device) |
761 | result = action(thermal, trip, cdev); | 759 | continue; |
762 | if (result) | 760 | if (bind) |
763 | goto failed; | 761 | result = |
764 | } | 762 | thermal_zone_bind_cooling_device |
763 | (thermal, trip, cdev, | ||
764 | THERMAL_NO_LIMIT, THERMAL_NO_LIMIT); | ||
765 | else | ||
766 | result = | ||
767 | thermal_zone_unbind_cooling_device | ||
768 | (thermal, trip, cdev); | ||
769 | if (result) | ||
770 | goto failed; | ||
765 | } | 771 | } |
766 | } | 772 | } |
767 | 773 | ||
@@ -774,11 +780,17 @@ static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal, | |||
774 | j++) { | 780 | j++) { |
775 | handle = tz->trips.active[i].devices.handles[j]; | 781 | handle = tz->trips.active[i].devices.handles[j]; |
776 | status = acpi_bus_get_device(handle, &dev); | 782 | status = acpi_bus_get_device(handle, &dev); |
777 | if (ACPI_SUCCESS(status) && (dev == device)) { | 783 | if (ACPI_FAILURE(status) || dev != device) |
778 | result = action(thermal, trip, cdev); | 784 | continue; |
779 | if (result) | 785 | if (bind) |
780 | goto failed; | 786 | result = thermal_zone_bind_cooling_device |
781 | } | 787 | (thermal, trip, cdev, |
788 | THERMAL_NO_LIMIT, THERMAL_NO_LIMIT); | ||
789 | else | ||
790 | result = thermal_zone_unbind_cooling_device | ||
791 | (thermal, trip, cdev); | ||
792 | if (result) | ||
793 | goto failed; | ||
782 | } | 794 | } |
783 | } | 795 | } |
784 | 796 | ||
@@ -786,7 +798,14 @@ static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal, | |||
786 | handle = tz->devices.handles[i]; | 798 | handle = tz->devices.handles[i]; |
787 | status = acpi_bus_get_device(handle, &dev); | 799 | status = acpi_bus_get_device(handle, &dev); |
788 | if (ACPI_SUCCESS(status) && (dev == device)) { | 800 | if (ACPI_SUCCESS(status) && (dev == device)) { |
789 | result = action(thermal, -1, cdev); | 801 | if (bind) |
802 | result = thermal_zone_bind_cooling_device | ||
803 | (thermal, -1, cdev, | ||
804 | THERMAL_NO_LIMIT, | ||
805 | THERMAL_NO_LIMIT); | ||
806 | else | ||
807 | result = thermal_zone_unbind_cooling_device | ||
808 | (thermal, -1, cdev); | ||
790 | if (result) | 809 | if (result) |
791 | goto failed; | 810 | goto failed; |
792 | } | 811 | } |
@@ -800,16 +819,14 @@ static int | |||
800 | acpi_thermal_bind_cooling_device(struct thermal_zone_device *thermal, | 819 | acpi_thermal_bind_cooling_device(struct thermal_zone_device *thermal, |
801 | struct thermal_cooling_device *cdev) | 820 | struct thermal_cooling_device *cdev) |
802 | { | 821 | { |
803 | return acpi_thermal_cooling_device_cb(thermal, cdev, | 822 | return acpi_thermal_cooling_device_cb(thermal, cdev, true); |
804 | thermal_zone_bind_cooling_device); | ||
805 | } | 823 | } |
806 | 824 | ||
807 | static int | 825 | static int |
808 | acpi_thermal_unbind_cooling_device(struct thermal_zone_device *thermal, | 826 | acpi_thermal_unbind_cooling_device(struct thermal_zone_device *thermal, |
809 | struct thermal_cooling_device *cdev) | 827 | struct thermal_cooling_device *cdev) |
810 | { | 828 | { |
811 | return acpi_thermal_cooling_device_cb(thermal, cdev, | 829 | return acpi_thermal_cooling_device_cb(thermal, cdev, false); |
812 | thermal_zone_unbind_cooling_device); | ||
813 | } | 830 | } |
814 | 831 | ||
815 | static const struct thermal_zone_device_ops acpi_thermal_zone_ops = { | 832 | static const struct thermal_zone_device_ops acpi_thermal_zone_ops = { |
diff --git a/drivers/platform/x86/acerhdf.c b/drivers/platform/x86/acerhdf.c index 39abb150bdd4..a207466f4ba8 100644 --- a/drivers/platform/x86/acerhdf.c +++ b/drivers/platform/x86/acerhdf.c | |||
@@ -329,7 +329,8 @@ static int acerhdf_bind(struct thermal_zone_device *thermal, | |||
329 | if (cdev != cl_dev) | 329 | if (cdev != cl_dev) |
330 | return 0; | 330 | return 0; |
331 | 331 | ||
332 | if (thermal_zone_bind_cooling_device(thermal, 0, cdev)) { | 332 | if (thermal_zone_bind_cooling_device(thermal, 0, cdev, |
333 | THERMAL_NO_LIMIT, THERMAL_NO_LIMIT)) { | ||
333 | pr_err("error binding cooling dev\n"); | 334 | pr_err("error binding cooling dev\n"); |
334 | return -EINVAL; | 335 | return -EINVAL; |
335 | } | 336 | } |
diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c index d78c6dc6b00a..b04fe2c4b0d5 100644 --- a/drivers/thermal/thermal_sys.c +++ b/drivers/thermal/thermal_sys.c | |||
@@ -315,8 +315,9 @@ passive_store(struct device *dev, struct device_attribute *attr, | |||
315 | if (!strncmp("Processor", cdev->type, | 315 | if (!strncmp("Processor", cdev->type, |
316 | sizeof("Processor"))) | 316 | sizeof("Processor"))) |
317 | thermal_zone_bind_cooling_device(tz, | 317 | thermal_zone_bind_cooling_device(tz, |
318 | THERMAL_TRIPS_NONE, | 318 | THERMAL_TRIPS_NONE, cdev, |
319 | cdev); | 319 | THERMAL_NO_LIMIT, |
320 | THERMAL_NO_LIMIT); | ||
320 | } | 321 | } |
321 | mutex_unlock(&thermal_list_lock); | 322 | mutex_unlock(&thermal_list_lock); |
322 | if (!tz->passive_delay) | 323 | if (!tz->passive_delay) |
@@ -801,7 +802,8 @@ static void thermal_zone_device_check(struct work_struct *work) | |||
801 | */ | 802 | */ |
802 | int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz, | 803 | int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz, |
803 | int trip, | 804 | int trip, |
804 | struct thermal_cooling_device *cdev) | 805 | struct thermal_cooling_device *cdev, |
806 | unsigned long upper, unsigned long lower) | ||
805 | { | 807 | { |
806 | struct thermal_cooling_device_instance *dev; | 808 | struct thermal_cooling_device_instance *dev; |
807 | struct thermal_cooling_device_instance *pos; | 809 | struct thermal_cooling_device_instance *pos; |
@@ -825,6 +827,15 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz, | |||
825 | if (tz != pos1 || cdev != pos2) | 827 | if (tz != pos1 || cdev != pos2) |
826 | return -EINVAL; | 828 | return -EINVAL; |
827 | 829 | ||
830 | cdev->ops->get_max_state(cdev, &max_state); | ||
831 | |||
832 | /* lower default 0, upper default max_state */ | ||
833 | lower = lower == THERMAL_NO_LIMIT ? 0 : lower; | ||
834 | upper = upper == THERMAL_NO_LIMIT ? max_state : upper; | ||
835 | |||
836 | if (lower > upper || upper > max_state) | ||
837 | return -EINVAL; | ||
838 | |||
828 | dev = | 839 | dev = |
829 | kzalloc(sizeof(struct thermal_cooling_device_instance), GFP_KERNEL); | 840 | kzalloc(sizeof(struct thermal_cooling_device_instance), GFP_KERNEL); |
830 | if (!dev) | 841 | if (!dev) |
@@ -832,10 +843,8 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz, | |||
832 | dev->tz = tz; | 843 | dev->tz = tz; |
833 | dev->cdev = cdev; | 844 | dev->cdev = cdev; |
834 | dev->trip = trip; | 845 | dev->trip = trip; |
835 | 846 | dev->upper = upper; | |
836 | cdev->ops->get_max_state(cdev, &max_state); | 847 | dev->lower = lower; |
837 | dev->upper = max_state; | ||
838 | dev->lower = 0; | ||
839 | 848 | ||
840 | result = get_idr(&tz->idr, &tz->lock, &dev->id); | 849 | result = get_idr(&tz->idr, &tz->lock, &dev->id); |
841 | if (result) | 850 | if (result) |
diff --git a/include/linux/thermal.h b/include/linux/thermal.h index 4b94a61955df..5946a3b90bb2 100644 --- a/include/linux/thermal.h +++ b/include/linux/thermal.h | |||
@@ -75,6 +75,8 @@ struct thermal_cooling_device_ops { | |||
75 | int (*set_cur_state) (struct thermal_cooling_device *, unsigned long); | 75 | int (*set_cur_state) (struct thermal_cooling_device *, unsigned long); |
76 | }; | 76 | }; |
77 | 77 | ||
78 | #define THERMAL_NO_LIMIT -1UL /* no upper/lower limit requirement */ | ||
79 | |||
78 | #define THERMAL_TRIPS_NONE -1 | 80 | #define THERMAL_TRIPS_NONE -1 |
79 | #define THERMAL_MAX_TRIPS 12 | 81 | #define THERMAL_MAX_TRIPS 12 |
80 | #define THERMAL_NAME_LENGTH 20 | 82 | #define THERMAL_NAME_LENGTH 20 |
@@ -157,7 +159,8 @@ struct thermal_zone_device *thermal_zone_device_register(const char *, int, int, | |||
157 | void thermal_zone_device_unregister(struct thermal_zone_device *); | 159 | void thermal_zone_device_unregister(struct thermal_zone_device *); |
158 | 160 | ||
159 | int thermal_zone_bind_cooling_device(struct thermal_zone_device *, int, | 161 | int thermal_zone_bind_cooling_device(struct thermal_zone_device *, int, |
160 | struct thermal_cooling_device *); | 162 | struct thermal_cooling_device *, |
163 | unsigned long, unsigned long); | ||
161 | int thermal_zone_unbind_cooling_device(struct thermal_zone_device *, int, | 164 | int thermal_zone_unbind_cooling_device(struct thermal_zone_device *, int, |
162 | struct thermal_cooling_device *); | 165 | struct thermal_cooling_device *); |
163 | void thermal_zone_device_update(struct thermal_zone_device *); | 166 | void thermal_zone_device_update(struct thermal_zone_device *); |