diff options
author | Durgadoss R <dugardoss.r@intel.com> | 2012-07-24 22:10:59 -0400 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2012-07-24 23:19:26 -0400 |
commit | 27365a6c7d64a3bba22ee62109e4a071bbd7f933 (patch) | |
tree | d8a5c1bf246171e2983b7f801b64a758fa6f62e3 /drivers/thermal | |
parent | c56f5c0342dfee11a1a13d2f5bb7618de5b17590 (diff) |
Thermal: Add Hysteresis attributes
The Linux Thermal Framework does not support hysteresis
attributes. Most thermal sensors, today, have a
hysteresis value associated with trip points.
This patch adds hysteresis attributes on a per-trip-point
basis, to the Thermal Framework. These attributes are
optionally writable.
Signed-off-by: Durgadoss R <durgadoss.r@intel.com>
Signed-off-by: Zhang Rui <rui.zhang@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/thermal')
-rw-r--r-- | drivers/thermal/thermal_sys.c | 88 |
1 files changed, 83 insertions, 5 deletions
diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c index 5feb3353213f..2d7a9fe8f365 100644 --- a/drivers/thermal/thermal_sys.c +++ b/drivers/thermal/thermal_sys.c | |||
@@ -240,6 +240,52 @@ trip_point_temp_show(struct device *dev, struct device_attribute *attr, | |||
240 | } | 240 | } |
241 | 241 | ||
242 | static ssize_t | 242 | static ssize_t |
243 | trip_point_hyst_store(struct device *dev, struct device_attribute *attr, | ||
244 | const char *buf, size_t count) | ||
245 | { | ||
246 | struct thermal_zone_device *tz = to_thermal_zone(dev); | ||
247 | int trip, ret; | ||
248 | unsigned long temperature; | ||
249 | |||
250 | if (!tz->ops->set_trip_hyst) | ||
251 | return -EPERM; | ||
252 | |||
253 | if (!sscanf(attr->attr.name, "trip_point_%d_hyst", &trip)) | ||
254 | return -EINVAL; | ||
255 | |||
256 | if (kstrtoul(buf, 10, &temperature)) | ||
257 | return -EINVAL; | ||
258 | |||
259 | /* | ||
260 | * We are not doing any check on the 'temperature' value | ||
261 | * here. The driver implementing 'set_trip_hyst' has to | ||
262 | * take care of this. | ||
263 | */ | ||
264 | ret = tz->ops->set_trip_hyst(tz, trip, temperature); | ||
265 | |||
266 | return ret ? ret : count; | ||
267 | } | ||
268 | |||
269 | static ssize_t | ||
270 | trip_point_hyst_show(struct device *dev, struct device_attribute *attr, | ||
271 | char *buf) | ||
272 | { | ||
273 | struct thermal_zone_device *tz = to_thermal_zone(dev); | ||
274 | int trip, ret; | ||
275 | unsigned long temperature; | ||
276 | |||
277 | if (!tz->ops->get_trip_hyst) | ||
278 | return -EPERM; | ||
279 | |||
280 | if (!sscanf(attr->attr.name, "trip_point_%d_hyst", &trip)) | ||
281 | return -EINVAL; | ||
282 | |||
283 | ret = tz->ops->get_trip_hyst(tz, trip, &temperature); | ||
284 | |||
285 | return ret ? ret : sprintf(buf, "%ld\n", temperature); | ||
286 | } | ||
287 | |||
288 | static ssize_t | ||
243 | passive_store(struct device *dev, struct device_attribute *attr, | 289 | passive_store(struct device *dev, struct device_attribute *attr, |
244 | const char *buf, size_t count) | 290 | const char *buf, size_t count) |
245 | { | 291 | { |
@@ -1091,21 +1137,29 @@ EXPORT_SYMBOL(thermal_zone_device_update); | |||
1091 | static int create_trip_attrs(struct thermal_zone_device *tz, int mask) | 1137 | static int create_trip_attrs(struct thermal_zone_device *tz, int mask) |
1092 | { | 1138 | { |
1093 | int indx; | 1139 | int indx; |
1140 | int size = sizeof(struct thermal_attr) * tz->trips; | ||
1094 | 1141 | ||
1095 | tz->trip_type_attrs = | 1142 | tz->trip_type_attrs = kzalloc(size, GFP_KERNEL); |
1096 | kzalloc(sizeof(struct thermal_attr) * tz->trips, GFP_KERNEL); | ||
1097 | if (!tz->trip_type_attrs) | 1143 | if (!tz->trip_type_attrs) |
1098 | return -ENOMEM; | 1144 | return -ENOMEM; |
1099 | 1145 | ||
1100 | tz->trip_temp_attrs = | 1146 | tz->trip_temp_attrs = kzalloc(size, GFP_KERNEL); |
1101 | kzalloc(sizeof(struct thermal_attr) * tz->trips, GFP_KERNEL); | ||
1102 | if (!tz->trip_temp_attrs) { | 1147 | if (!tz->trip_temp_attrs) { |
1103 | kfree(tz->trip_type_attrs); | 1148 | kfree(tz->trip_type_attrs); |
1104 | return -ENOMEM; | 1149 | return -ENOMEM; |
1105 | } | 1150 | } |
1106 | 1151 | ||
1107 | for (indx = 0; indx < tz->trips; indx++) { | 1152 | if (tz->ops->get_trip_hyst) { |
1153 | tz->trip_hyst_attrs = kzalloc(size, GFP_KERNEL); | ||
1154 | if (!tz->trip_hyst_attrs) { | ||
1155 | kfree(tz->trip_type_attrs); | ||
1156 | kfree(tz->trip_temp_attrs); | ||
1157 | return -ENOMEM; | ||
1158 | } | ||
1159 | } | ||
1108 | 1160 | ||
1161 | |||
1162 | for (indx = 0; indx < tz->trips; indx++) { | ||
1109 | /* create trip type attribute */ | 1163 | /* create trip type attribute */ |
1110 | snprintf(tz->trip_type_attrs[indx].name, THERMAL_NAME_LENGTH, | 1164 | snprintf(tz->trip_type_attrs[indx].name, THERMAL_NAME_LENGTH, |
1111 | "trip_point_%d_type", indx); | 1165 | "trip_point_%d_type", indx); |
@@ -1136,6 +1190,26 @@ static int create_trip_attrs(struct thermal_zone_device *tz, int mask) | |||
1136 | 1190 | ||
1137 | device_create_file(&tz->device, | 1191 | device_create_file(&tz->device, |
1138 | &tz->trip_temp_attrs[indx].attr); | 1192 | &tz->trip_temp_attrs[indx].attr); |
1193 | |||
1194 | /* create Optional trip hyst attribute */ | ||
1195 | if (!tz->ops->get_trip_hyst) | ||
1196 | continue; | ||
1197 | snprintf(tz->trip_hyst_attrs[indx].name, THERMAL_NAME_LENGTH, | ||
1198 | "trip_point_%d_hyst", indx); | ||
1199 | |||
1200 | sysfs_attr_init(&tz->trip_hyst_attrs[indx].attr.attr); | ||
1201 | tz->trip_hyst_attrs[indx].attr.attr.name = | ||
1202 | tz->trip_hyst_attrs[indx].name; | ||
1203 | tz->trip_hyst_attrs[indx].attr.attr.mode = S_IRUGO; | ||
1204 | tz->trip_hyst_attrs[indx].attr.show = trip_point_hyst_show; | ||
1205 | if (tz->ops->set_trip_hyst) { | ||
1206 | tz->trip_hyst_attrs[indx].attr.attr.mode |= S_IWUSR; | ||
1207 | tz->trip_hyst_attrs[indx].attr.store = | ||
1208 | trip_point_hyst_store; | ||
1209 | } | ||
1210 | |||
1211 | device_create_file(&tz->device, | ||
1212 | &tz->trip_hyst_attrs[indx].attr); | ||
1139 | } | 1213 | } |
1140 | return 0; | 1214 | return 0; |
1141 | } | 1215 | } |
@@ -1149,9 +1223,13 @@ static void remove_trip_attrs(struct thermal_zone_device *tz) | |||
1149 | &tz->trip_type_attrs[indx].attr); | 1223 | &tz->trip_type_attrs[indx].attr); |
1150 | device_remove_file(&tz->device, | 1224 | device_remove_file(&tz->device, |
1151 | &tz->trip_temp_attrs[indx].attr); | 1225 | &tz->trip_temp_attrs[indx].attr); |
1226 | if (tz->ops->get_trip_hyst) | ||
1227 | device_remove_file(&tz->device, | ||
1228 | &tz->trip_hyst_attrs[indx].attr); | ||
1152 | } | 1229 | } |
1153 | kfree(tz->trip_type_attrs); | 1230 | kfree(tz->trip_type_attrs); |
1154 | kfree(tz->trip_temp_attrs); | 1231 | kfree(tz->trip_temp_attrs); |
1232 | kfree(tz->trip_hyst_attrs); | ||
1155 | } | 1233 | } |
1156 | 1234 | ||
1157 | /** | 1235 | /** |