aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/thermal
diff options
context:
space:
mode:
authorDurgadoss R <dugardoss.r@intel.com>2012-07-24 22:10:59 -0400
committerLen Brown <len.brown@intel.com>2012-07-24 23:19:26 -0400
commit27365a6c7d64a3bba22ee62109e4a071bbd7f933 (patch)
treed8a5c1bf246171e2983b7f801b64a758fa6f62e3 /drivers/thermal
parentc56f5c0342dfee11a1a13d2f5bb7618de5b17590 (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.c88
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
242static ssize_t 242static ssize_t
243trip_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
269static ssize_t
270trip_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
288static ssize_t
243passive_store(struct device *dev, struct device_attribute *attr, 289passive_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);
1091static int create_trip_attrs(struct thermal_zone_device *tz, int mask) 1137static 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/**