diff options
-rw-r--r-- | drivers/thermal/thermal_sys.c | 77 | ||||
-rw-r--r-- | include/linux/thermal.h | 1 |
2 files changed, 78 insertions, 0 deletions
diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c index 6378741882f3..d0b093b66adc 100644 --- a/drivers/thermal/thermal_sys.c +++ b/drivers/thermal/thermal_sys.c | |||
@@ -214,9 +214,69 @@ trip_point_temp_show(struct device *dev, struct device_attribute *attr, | |||
214 | return sprintf(buf, "%ld\n", temperature); | 214 | return sprintf(buf, "%ld\n", temperature); |
215 | } | 215 | } |
216 | 216 | ||
217 | static ssize_t | ||
218 | passive_store(struct device *dev, struct device_attribute *attr, | ||
219 | const char *buf, size_t count) | ||
220 | { | ||
221 | struct thermal_zone_device *tz = to_thermal_zone(dev); | ||
222 | struct thermal_cooling_device *cdev = NULL; | ||
223 | int state; | ||
224 | |||
225 | if (!sscanf(buf, "%d\n", &state)) | ||
226 | return -EINVAL; | ||
227 | |||
228 | if (state && !tz->forced_passive) { | ||
229 | mutex_lock(&thermal_list_lock); | ||
230 | list_for_each_entry(cdev, &thermal_cdev_list, node) { | ||
231 | if (!strncmp("Processor", cdev->type, | ||
232 | sizeof("Processor"))) | ||
233 | thermal_zone_bind_cooling_device(tz, | ||
234 | THERMAL_TRIPS_NONE, | ||
235 | cdev); | ||
236 | } | ||
237 | mutex_unlock(&thermal_list_lock); | ||
238 | } else if (!state && tz->forced_passive) { | ||
239 | mutex_lock(&thermal_list_lock); | ||
240 | list_for_each_entry(cdev, &thermal_cdev_list, node) { | ||
241 | if (!strncmp("Processor", cdev->type, | ||
242 | sizeof("Processor"))) | ||
243 | thermal_zone_unbind_cooling_device(tz, | ||
244 | THERMAL_TRIPS_NONE, | ||
245 | cdev); | ||
246 | } | ||
247 | mutex_unlock(&thermal_list_lock); | ||
248 | } | ||
249 | |||
250 | tz->tc1 = 1; | ||
251 | tz->tc2 = 1; | ||
252 | |||
253 | if (!tz->passive_delay) | ||
254 | tz->passive_delay = 1000; | ||
255 | |||
256 | if (!tz->polling_delay) | ||
257 | tz->polling_delay = 10000; | ||
258 | |||
259 | tz->forced_passive = state; | ||
260 | |||
261 | thermal_zone_device_update(tz); | ||
262 | |||
263 | return count; | ||
264 | } | ||
265 | |||
266 | static ssize_t | ||
267 | passive_show(struct device *dev, struct device_attribute *attr, | ||
268 | char *buf) | ||
269 | { | ||
270 | struct thermal_zone_device *tz = to_thermal_zone(dev); | ||
271 | |||
272 | return sprintf(buf, "%d\n", tz->forced_passive); | ||
273 | } | ||
274 | |||
217 | static DEVICE_ATTR(type, 0444, type_show, NULL); | 275 | static DEVICE_ATTR(type, 0444, type_show, NULL); |
218 | static DEVICE_ATTR(temp, 0444, temp_show, NULL); | 276 | static DEVICE_ATTR(temp, 0444, temp_show, NULL); |
219 | static DEVICE_ATTR(mode, 0644, mode_show, mode_store); | 277 | static DEVICE_ATTR(mode, 0644, mode_show, mode_store); |
278 | static DEVICE_ATTR(passive, S_IRUGO | S_IWUSR, passive_show, \ | ||
279 | passive_store); | ||
220 | 280 | ||
221 | static struct device_attribute trip_point_attrs[] = { | 281 | static struct device_attribute trip_point_attrs[] = { |
222 | __ATTR(trip_point_0_type, 0444, trip_point_type_show, NULL), | 282 | __ATTR(trip_point_0_type, 0444, trip_point_type_show, NULL), |
@@ -939,6 +999,11 @@ void thermal_zone_device_update(struct thermal_zone_device *tz) | |||
939 | break; | 999 | break; |
940 | } | 1000 | } |
941 | } | 1001 | } |
1002 | |||
1003 | if (tz->forced_passive) | ||
1004 | thermal_zone_device_passive(tz, temp, tz->forced_passive, | ||
1005 | THERMAL_TRIPS_NONE); | ||
1006 | |||
942 | tz->last_temperature = temp; | 1007 | tz->last_temperature = temp; |
943 | if (tz->passive) | 1008 | if (tz->passive) |
944 | thermal_zone_device_set_polling(tz, tz->passive_delay); | 1009 | thermal_zone_device_set_polling(tz, tz->passive_delay); |
@@ -977,8 +1042,10 @@ struct thermal_zone_device *thermal_zone_device_register(char *type, | |||
977 | { | 1042 | { |
978 | struct thermal_zone_device *tz; | 1043 | struct thermal_zone_device *tz; |
979 | struct thermal_cooling_device *pos; | 1044 | struct thermal_cooling_device *pos; |
1045 | enum thermal_trip_type trip_type; | ||
980 | int result; | 1046 | int result; |
981 | int count; | 1047 | int count; |
1048 | int passive = 0; | ||
982 | 1049 | ||
983 | if (strlen(type) >= THERMAL_NAME_LENGTH) | 1050 | if (strlen(type) >= THERMAL_NAME_LENGTH) |
984 | return ERR_PTR(-EINVAL); | 1051 | return ERR_PTR(-EINVAL); |
@@ -1041,8 +1108,18 @@ struct thermal_zone_device *thermal_zone_device_register(char *type, | |||
1041 | TRIP_POINT_ATTR_ADD(&tz->device, count, result); | 1108 | TRIP_POINT_ATTR_ADD(&tz->device, count, result); |
1042 | if (result) | 1109 | if (result) |
1043 | goto unregister; | 1110 | goto unregister; |
1111 | tz->ops->get_trip_type(tz, count, &trip_type); | ||
1112 | if (trip_type == THERMAL_TRIP_PASSIVE) | ||
1113 | passive = 1; | ||
1044 | } | 1114 | } |
1045 | 1115 | ||
1116 | if (!passive) | ||
1117 | result = device_create_file(&tz->device, | ||
1118 | &dev_attr_passive); | ||
1119 | |||
1120 | if (result) | ||
1121 | goto unregister; | ||
1122 | |||
1046 | result = thermal_add_hwmon_sysfs(tz); | 1123 | result = thermal_add_hwmon_sysfs(tz); |
1047 | if (result) | 1124 | if (result) |
1048 | goto unregister; | 1125 | goto unregister; |
diff --git a/include/linux/thermal.h b/include/linux/thermal.h index a81c61521ba4..1de8b9eb841b 100644 --- a/include/linux/thermal.h +++ b/include/linux/thermal.h | |||
@@ -113,6 +113,7 @@ struct thermal_zone_device { | |||
113 | int polling_delay; | 113 | int polling_delay; |
114 | int last_temperature; | 114 | int last_temperature; |
115 | bool passive; | 115 | bool passive; |
116 | unsigned int forced_passive; | ||
116 | struct thermal_zone_device_ops *ops; | 117 | struct thermal_zone_device_ops *ops; |
117 | struct list_head cooling_devices; | 118 | struct list_head cooling_devices; |
118 | struct idr idr; | 119 | struct idr idr; |