diff options
-rw-r--r-- | drivers/thermal/thermal_sys.c | 44 | ||||
-rw-r--r-- | include/linux/thermal.h | 1 |
2 files changed, 42 insertions, 3 deletions
diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c index 70045c12d7df..36ae2f43ee2e 100644 --- a/drivers/thermal/thermal_sys.c +++ b/drivers/thermal/thermal_sys.c | |||
@@ -41,6 +41,7 @@ MODULE_AUTHOR("Zhang Rui"); | |||
41 | MODULE_DESCRIPTION("Generic thermal management sysfs support"); | 41 | MODULE_DESCRIPTION("Generic thermal management sysfs support"); |
42 | MODULE_LICENSE("GPL"); | 42 | MODULE_LICENSE("GPL"); |
43 | 43 | ||
44 | #define THERMAL_NO_TARGET -1UL | ||
44 | /* | 45 | /* |
45 | * This structure is used to describe the behavior of | 46 | * This structure is used to describe the behavior of |
46 | * a certain cooling device on a certain trip point | 47 | * a certain cooling device on a certain trip point |
@@ -54,6 +55,7 @@ struct thermal_instance { | |||
54 | int trip; | 55 | int trip; |
55 | unsigned long upper; /* Highest cooling state for this trip point */ | 56 | unsigned long upper; /* Highest cooling state for this trip point */ |
56 | unsigned long lower; /* Lowest cooling state for this trip point */ | 57 | unsigned long lower; /* Lowest cooling state for this trip point */ |
58 | unsigned long target; /* expected cooling state */ | ||
57 | char attr_name[THERMAL_NAME_LENGTH]; | 59 | char attr_name[THERMAL_NAME_LENGTH]; |
58 | struct device_attribute attr; | 60 | struct device_attribute attr; |
59 | struct list_head tz_node; /* node in tz->thermal_instances */ | 61 | struct list_head tz_node; /* node in tz->thermal_instances */ |
@@ -853,6 +855,7 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz, | |||
853 | dev->trip = trip; | 855 | dev->trip = trip; |
854 | dev->upper = upper; | 856 | dev->upper = upper; |
855 | dev->lower = lower; | 857 | dev->lower = lower; |
858 | dev->target = THERMAL_NO_TARGET; | ||
856 | 859 | ||
857 | result = get_idr(&tz->idr, &tz->lock, &dev->id); | 860 | result = get_idr(&tz->idr, &tz->lock, &dev->id); |
858 | if (result) | 861 | if (result) |
@@ -990,6 +993,7 @@ thermal_cooling_device_register(char *type, void *devdata, | |||
990 | strcpy(cdev->type, type); | 993 | strcpy(cdev->type, type); |
991 | INIT_LIST_HEAD(&cdev->thermal_instances); | 994 | INIT_LIST_HEAD(&cdev->thermal_instances); |
992 | cdev->ops = ops; | 995 | cdev->ops = ops; |
996 | cdev->updated = true; | ||
993 | cdev->device.class = &thermal_class; | 997 | cdev->device.class = &thermal_class; |
994 | cdev->devdata = devdata; | 998 | cdev->devdata = devdata; |
995 | dev_set_name(&cdev->device, "cooling_device%d", cdev->id); | 999 | dev_set_name(&cdev->device, "cooling_device%d", cdev->id); |
@@ -1081,6 +1085,34 @@ void thermal_cooling_device_unregister(struct | |||
1081 | } | 1085 | } |
1082 | EXPORT_SYMBOL(thermal_cooling_device_unregister); | 1086 | EXPORT_SYMBOL(thermal_cooling_device_unregister); |
1083 | 1087 | ||
1088 | static void thermal_cdev_do_update(struct thermal_cooling_device *cdev) | ||
1089 | { | ||
1090 | struct thermal_instance *instance; | ||
1091 | unsigned long target = 0; | ||
1092 | |||
1093 | /* cooling device is updated*/ | ||
1094 | if (cdev->updated) | ||
1095 | return; | ||
1096 | |||
1097 | /* Make sure cdev enters the deepest cooling state */ | ||
1098 | list_for_each_entry(instance, &cdev->thermal_instances, cdev_node) { | ||
1099 | if (instance->target == THERMAL_NO_TARGET) | ||
1100 | continue; | ||
1101 | if (instance->target > target) | ||
1102 | target = instance->target; | ||
1103 | } | ||
1104 | cdev->ops->set_cur_state(cdev, target); | ||
1105 | cdev->updated = true; | ||
1106 | } | ||
1107 | |||
1108 | static void thermal_zone_do_update(struct thermal_zone_device *tz) | ||
1109 | { | ||
1110 | struct thermal_instance *instance; | ||
1111 | |||
1112 | list_for_each_entry(instance, &tz->thermal_instances, tz_node) | ||
1113 | thermal_cdev_do_update(instance->cdev); | ||
1114 | } | ||
1115 | |||
1084 | /* | 1116 | /* |
1085 | * Cooling algorithm for active trip points | 1117 | * Cooling algorithm for active trip points |
1086 | * | 1118 | * |
@@ -1138,19 +1170,24 @@ static void thermal_zone_trip_update(struct thermal_zone_device *tz, | |||
1138 | cur_state = cur_state > instance->lower ? | 1170 | cur_state = cur_state > instance->lower ? |
1139 | (cur_state - 1) : instance->lower; | 1171 | (cur_state - 1) : instance->lower; |
1140 | } | 1172 | } |
1141 | cdev->ops->set_cur_state(cdev, cur_state); | 1173 | instance->target = cur_state; |
1174 | cdev->updated = false; /* cooling device needs update */ | ||
1142 | } | 1175 | } |
1143 | } else { /* below trip */ | 1176 | } else { /* below trip */ |
1144 | list_for_each_entry(instance, &tz->thermal_instances, tz_node) { | 1177 | list_for_each_entry(instance, &tz->thermal_instances, tz_node) { |
1145 | if (instance->trip != trip) | 1178 | if (instance->trip != trip) |
1146 | continue; | 1179 | continue; |
1147 | 1180 | ||
1181 | /* Do not use the inactive thermal instance */ | ||
1182 | if (instance->target == THERMAL_NO_TARGET) | ||
1183 | continue; | ||
1148 | cdev = instance->cdev; | 1184 | cdev = instance->cdev; |
1149 | cdev->ops->get_cur_state(cdev, &cur_state); | 1185 | cdev->ops->get_cur_state(cdev, &cur_state); |
1150 | 1186 | ||
1151 | cur_state = cur_state > instance->lower ? | 1187 | cur_state = cur_state > instance->lower ? |
1152 | (cur_state - 1) : instance->lower; | 1188 | (cur_state - 1) : THERMAL_NO_TARGET; |
1153 | cdev->ops->set_cur_state(cdev, cur_state); | 1189 | instance->target = cur_state; |
1190 | cdev->updated = false; /* cooling device needs update */ | ||
1154 | } | 1191 | } |
1155 | } | 1192 | } |
1156 | 1193 | ||
@@ -1211,6 +1248,7 @@ void thermal_zone_device_update(struct thermal_zone_device *tz) | |||
1211 | } | 1248 | } |
1212 | } | 1249 | } |
1213 | 1250 | ||
1251 | thermal_zone_do_update(tz); | ||
1214 | if (tz->forced_passive) | 1252 | if (tz->forced_passive) |
1215 | thermal_zone_device_passive(tz, temp, tz->forced_passive, | 1253 | thermal_zone_device_passive(tz, temp, tz->forced_passive, |
1216 | THERMAL_TRIPS_NONE); | 1254 | THERMAL_TRIPS_NONE); |
diff --git a/include/linux/thermal.h b/include/linux/thermal.h index 9ae378a4a555..de0515a96f9f 100644 --- a/include/linux/thermal.h +++ b/include/linux/thermal.h | |||
@@ -94,6 +94,7 @@ struct thermal_cooling_device { | |||
94 | struct device device; | 94 | struct device device; |
95 | void *devdata; | 95 | void *devdata; |
96 | const struct thermal_cooling_device_ops *ops; | 96 | const struct thermal_cooling_device_ops *ops; |
97 | bool updated; /* true if the cooling device does not need update */ | ||
97 | struct list_head thermal_instances; | 98 | struct list_head thermal_instances; |
98 | struct list_head node; | 99 | struct list_head node; |
99 | }; | 100 | }; |