diff options
-rw-r--r-- | Documentation/thermal/sysfs-api.txt | 6 | ||||
-rw-r--r-- | drivers/thermal/thermal_sys.c | 88 | ||||
-rw-r--r-- | include/linux/thermal.h | 5 |
3 files changed, 94 insertions, 5 deletions
diff --git a/Documentation/thermal/sysfs-api.txt b/Documentation/thermal/sysfs-api.txt index 4c105934c599..2ba4c9bb790a 100644 --- a/Documentation/thermal/sysfs-api.txt +++ b/Documentation/thermal/sysfs-api.txt | |||
@@ -121,6 +121,7 @@ Thermal zone device sys I/F, created once it's registered: | |||
121 | |---mode: Working mode of the thermal zone | 121 | |---mode: Working mode of the thermal zone |
122 | |---trip_point_[0-*]_temp: Trip point temperature | 122 | |---trip_point_[0-*]_temp: Trip point temperature |
123 | |---trip_point_[0-*]_type: Trip point type | 123 | |---trip_point_[0-*]_type: Trip point type |
124 | |---trip_point_[0-*]_hyst: Hysteresis value for this trip point | ||
124 | 125 | ||
125 | Thermal cooling device sys I/F, created once it's registered: | 126 | Thermal cooling device sys I/F, created once it's registered: |
126 | /sys/class/thermal/cooling_device[0-*]: | 127 | /sys/class/thermal/cooling_device[0-*]: |
@@ -190,6 +191,11 @@ trip_point_[0-*]_type | |||
190 | thermal zone. | 191 | thermal zone. |
191 | RO, Optional | 192 | RO, Optional |
192 | 193 | ||
194 | trip_point_[0-*]_hyst | ||
195 | The hysteresis value for a trip point, represented as an integer | ||
196 | Unit: Celsius | ||
197 | RW, Optional | ||
198 | |||
193 | cdev[0-*] | 199 | cdev[0-*] |
194 | Sysfs link to the thermal cooling device node where the sys I/F | 200 | Sysfs link to the thermal cooling device node where the sys I/F |
195 | for cooling device throttling control represents. | 201 | for cooling device throttling control represents. |
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 | /** |
diff --git a/include/linux/thermal.h b/include/linux/thermal.h index 6eaf9146c847..cfc8d908892e 100644 --- a/include/linux/thermal.h +++ b/include/linux/thermal.h | |||
@@ -60,6 +60,10 @@ struct thermal_zone_device_ops { | |||
60 | unsigned long *); | 60 | unsigned long *); |
61 | int (*set_trip_temp) (struct thermal_zone_device *, int, | 61 | int (*set_trip_temp) (struct thermal_zone_device *, int, |
62 | unsigned long); | 62 | unsigned long); |
63 | int (*get_trip_hyst) (struct thermal_zone_device *, int, | ||
64 | unsigned long *); | ||
65 | int (*set_trip_hyst) (struct thermal_zone_device *, int, | ||
66 | unsigned long); | ||
63 | int (*get_crit_temp) (struct thermal_zone_device *, unsigned long *); | 67 | int (*get_crit_temp) (struct thermal_zone_device *, unsigned long *); |
64 | int (*notify) (struct thermal_zone_device *, int, | 68 | int (*notify) (struct thermal_zone_device *, int, |
65 | enum thermal_trip_type); | 69 | enum thermal_trip_type); |
@@ -98,6 +102,7 @@ struct thermal_zone_device { | |||
98 | struct device device; | 102 | struct device device; |
99 | struct thermal_attr *trip_temp_attrs; | 103 | struct thermal_attr *trip_temp_attrs; |
100 | struct thermal_attr *trip_type_attrs; | 104 | struct thermal_attr *trip_type_attrs; |
105 | struct thermal_attr *trip_hyst_attrs; | ||
101 | void *devdata; | 106 | void *devdata; |
102 | int trips; | 107 | int trips; |
103 | int tc1; | 108 | int tc1; |