diff options
author | Durgadoss R <durgadoss.r@intel.com> | 2012-09-18 01:34:59 -0400 |
---|---|---|
committer | Zhang Rui <rui.zhang@intel.com> | 2012-11-05 01:00:06 -0500 |
commit | 7e8ee1e9d7561fe640ae8df6c28f10a6a3239592 (patch) | |
tree | 62424e9e873cf857727d6ce9803f2dc73647a561 /drivers/thermal/thermal_sys.c | |
parent | 5a2c090b3327353a78232182f2c7fcd69a46eff0 (diff) |
Thermal: Update binding logic based on platform data
This patch updates the binding logic in thermal_sys.c
It uses the platform layer data to bind a thermal zone
to a cdev for a particular trip point.
* If we do not have platform data and do not have
.bind defined, do not bind.
* If we do not have platform data but .bind is
defined, then use tz->ops->bind.
* If we have platform data, use it to create binding.
The same logic sequence is followed for unbind also.
Signed-off-by: Durgadoss R <durgadoss.r@intel.com>
Signed-off-by: Zhang Rui <rui.zhang@intel.com>
Diffstat (limited to 'drivers/thermal/thermal_sys.c')
-rw-r--r-- | drivers/thermal/thermal_sys.c | 183 |
1 files changed, 157 insertions, 26 deletions
diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c index a6933dad3bab..a32803224e3c 100644 --- a/drivers/thermal/thermal_sys.c +++ b/drivers/thermal/thermal_sys.c | |||
@@ -201,6 +201,111 @@ struct thermal_instance *get_thermal_instance(struct thermal_zone_device *tz, | |||
201 | } | 201 | } |
202 | EXPORT_SYMBOL(get_thermal_instance); | 202 | EXPORT_SYMBOL(get_thermal_instance); |
203 | 203 | ||
204 | static void print_bind_err_msg(struct thermal_zone_device *tz, | ||
205 | struct thermal_cooling_device *cdev, int ret) | ||
206 | { | ||
207 | dev_err(&tz->device, "binding zone %s with cdev %s failed:%d\n", | ||
208 | tz->type, cdev->type, ret); | ||
209 | } | ||
210 | |||
211 | static void __bind(struct thermal_zone_device *tz, int mask, | ||
212 | struct thermal_cooling_device *cdev) | ||
213 | { | ||
214 | int i, ret; | ||
215 | |||
216 | for (i = 0; i < tz->trips; i++) { | ||
217 | if (mask & (1 << i)) { | ||
218 | ret = thermal_zone_bind_cooling_device(tz, i, cdev, | ||
219 | THERMAL_NO_LIMIT, THERMAL_NO_LIMIT); | ||
220 | if (ret) | ||
221 | print_bind_err_msg(tz, cdev, ret); | ||
222 | } | ||
223 | } | ||
224 | } | ||
225 | |||
226 | static void __unbind(struct thermal_zone_device *tz, int mask, | ||
227 | struct thermal_cooling_device *cdev) | ||
228 | { | ||
229 | int i; | ||
230 | |||
231 | for (i = 0; i < tz->trips; i++) | ||
232 | if (mask & (1 << i)) | ||
233 | thermal_zone_unbind_cooling_device(tz, i, cdev); | ||
234 | } | ||
235 | |||
236 | static void bind_cdev(struct thermal_cooling_device *cdev) | ||
237 | { | ||
238 | int i, ret; | ||
239 | const struct thermal_zone_params *tzp; | ||
240 | struct thermal_zone_device *pos = NULL; | ||
241 | |||
242 | mutex_lock(&thermal_list_lock); | ||
243 | |||
244 | list_for_each_entry(pos, &thermal_tz_list, node) { | ||
245 | if (!pos->tzp && !pos->ops->bind) | ||
246 | continue; | ||
247 | |||
248 | if (!pos->tzp && pos->ops->bind) { | ||
249 | ret = pos->ops->bind(pos, cdev); | ||
250 | if (ret) | ||
251 | print_bind_err_msg(pos, cdev, ret); | ||
252 | } | ||
253 | |||
254 | tzp = pos->tzp; | ||
255 | if (!tzp->tbp) | ||
256 | return; | ||
257 | |||
258 | for (i = 0; i < tzp->num_tbps; i++) { | ||
259 | if (tzp->tbp[i].cdev || !tzp->tbp[i].match) | ||
260 | continue; | ||
261 | if (tzp->tbp[i].match(pos, cdev)) | ||
262 | continue; | ||
263 | tzp->tbp[i].cdev = cdev; | ||
264 | __bind(pos, tzp->tbp[i].trip_mask, cdev); | ||
265 | } | ||
266 | } | ||
267 | |||
268 | mutex_unlock(&thermal_list_lock); | ||
269 | } | ||
270 | |||
271 | static void bind_tz(struct thermal_zone_device *tz) | ||
272 | { | ||
273 | int i, ret; | ||
274 | struct thermal_cooling_device *pos = NULL; | ||
275 | const struct thermal_zone_params *tzp = tz->tzp; | ||
276 | |||
277 | if (!tzp && !tz->ops->bind) | ||
278 | return; | ||
279 | |||
280 | mutex_lock(&thermal_list_lock); | ||
281 | |||
282 | /* If there is no platform data, try to use ops->bind */ | ||
283 | if (!tzp && tz->ops->bind) { | ||
284 | list_for_each_entry(pos, &thermal_cdev_list, node) { | ||
285 | ret = tz->ops->bind(tz, pos); | ||
286 | if (ret) | ||
287 | print_bind_err_msg(tz, pos, ret); | ||
288 | } | ||
289 | goto exit; | ||
290 | } | ||
291 | |||
292 | if (!tzp->tbp) | ||
293 | goto exit; | ||
294 | |||
295 | list_for_each_entry(pos, &thermal_cdev_list, node) { | ||
296 | for (i = 0; i < tzp->num_tbps; i++) { | ||
297 | if (tzp->tbp[i].cdev || !tzp->tbp[i].match) | ||
298 | continue; | ||
299 | if (tzp->tbp[i].match(tz, pos)) | ||
300 | continue; | ||
301 | tzp->tbp[i].cdev = pos; | ||
302 | __bind(tz, tzp->tbp[i].trip_mask, pos); | ||
303 | } | ||
304 | } | ||
305 | exit: | ||
306 | mutex_unlock(&thermal_list_lock); | ||
307 | } | ||
308 | |||
204 | /* sys I/F for thermal zone */ | 309 | /* sys I/F for thermal zone */ |
205 | 310 | ||
206 | #define to_thermal_zone(_dev) \ | 311 | #define to_thermal_zone(_dev) \ |
@@ -1026,7 +1131,6 @@ thermal_cooling_device_register(char *type, void *devdata, | |||
1026 | const struct thermal_cooling_device_ops *ops) | 1131 | const struct thermal_cooling_device_ops *ops) |
1027 | { | 1132 | { |
1028 | struct thermal_cooling_device *cdev; | 1133 | struct thermal_cooling_device *cdev; |
1029 | struct thermal_zone_device *pos; | ||
1030 | int result; | 1134 | int result; |
1031 | 1135 | ||
1032 | if (type && strlen(type) >= THERMAL_NAME_LENGTH) | 1136 | if (type && strlen(type) >= THERMAL_NAME_LENGTH) |
@@ -1076,20 +1180,15 @@ thermal_cooling_device_register(char *type, void *devdata, | |||
1076 | if (result) | 1180 | if (result) |
1077 | goto unregister; | 1181 | goto unregister; |
1078 | 1182 | ||
1183 | /* Add 'this' new cdev to the global cdev list */ | ||
1079 | mutex_lock(&thermal_list_lock); | 1184 | mutex_lock(&thermal_list_lock); |
1080 | list_add(&cdev->node, &thermal_cdev_list); | 1185 | list_add(&cdev->node, &thermal_cdev_list); |
1081 | list_for_each_entry(pos, &thermal_tz_list, node) { | ||
1082 | if (!pos->ops->bind) | ||
1083 | continue; | ||
1084 | result = pos->ops->bind(pos, cdev); | ||
1085 | if (result) | ||
1086 | break; | ||
1087 | |||
1088 | } | ||
1089 | mutex_unlock(&thermal_list_lock); | 1186 | mutex_unlock(&thermal_list_lock); |
1090 | 1187 | ||
1091 | if (!result) | 1188 | /* Update binding information for 'this' new cdev */ |
1092 | return cdev; | 1189 | bind_cdev(cdev); |
1190 | |||
1191 | return cdev; | ||
1093 | 1192 | ||
1094 | unregister: | 1193 | unregister: |
1095 | release_idr(&thermal_cdev_idr, &thermal_idr_lock, cdev->id); | 1194 | release_idr(&thermal_cdev_idr, &thermal_idr_lock, cdev->id); |
@@ -1105,10 +1204,10 @@ EXPORT_SYMBOL(thermal_cooling_device_register); | |||
1105 | * thermal_cooling_device_unregister() must be called when the device is no | 1204 | * thermal_cooling_device_unregister() must be called when the device is no |
1106 | * longer needed. | 1205 | * longer needed. |
1107 | */ | 1206 | */ |
1108 | void thermal_cooling_device_unregister(struct | 1207 | void thermal_cooling_device_unregister(struct thermal_cooling_device *cdev) |
1109 | thermal_cooling_device | ||
1110 | *cdev) | ||
1111 | { | 1208 | { |
1209 | int i; | ||
1210 | const struct thermal_zone_params *tzp; | ||
1112 | struct thermal_zone_device *tz; | 1211 | struct thermal_zone_device *tz; |
1113 | struct thermal_cooling_device *pos = NULL; | 1212 | struct thermal_cooling_device *pos = NULL; |
1114 | 1213 | ||
@@ -1125,12 +1224,28 @@ void thermal_cooling_device_unregister(struct | |||
1125 | return; | 1224 | return; |
1126 | } | 1225 | } |
1127 | list_del(&cdev->node); | 1226 | list_del(&cdev->node); |
1227 | |||
1228 | /* Unbind all thermal zones associated with 'this' cdev */ | ||
1128 | list_for_each_entry(tz, &thermal_tz_list, node) { | 1229 | list_for_each_entry(tz, &thermal_tz_list, node) { |
1129 | if (!tz->ops->unbind) | 1230 | if (tz->ops->unbind) { |
1231 | tz->ops->unbind(tz, cdev); | ||
1232 | continue; | ||
1233 | } | ||
1234 | |||
1235 | if (!tz->tzp || !tz->tzp->tbp) | ||
1130 | continue; | 1236 | continue; |
1131 | tz->ops->unbind(tz, cdev); | 1237 | |
1238 | tzp = tz->tzp; | ||
1239 | for (i = 0; i < tzp->num_tbps; i++) { | ||
1240 | if (tzp->tbp[i].cdev == cdev) { | ||
1241 | __unbind(tz, tzp->tbp[i].trip_mask, cdev); | ||
1242 | tzp->tbp[i].cdev = NULL; | ||
1243 | } | ||
1244 | } | ||
1132 | } | 1245 | } |
1246 | |||
1133 | mutex_unlock(&thermal_list_lock); | 1247 | mutex_unlock(&thermal_list_lock); |
1248 | |||
1134 | if (cdev->type[0]) | 1249 | if (cdev->type[0]) |
1135 | device_remove_file(&cdev->device, &dev_attr_cdev_type); | 1250 | device_remove_file(&cdev->device, &dev_attr_cdev_type); |
1136 | device_remove_file(&cdev->device, &dev_attr_max_state); | 1251 | device_remove_file(&cdev->device, &dev_attr_max_state); |
@@ -1468,7 +1583,6 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type, | |||
1468 | int passive_delay, int polling_delay) | 1583 | int passive_delay, int polling_delay) |
1469 | { | 1584 | { |
1470 | struct thermal_zone_device *tz; | 1585 | struct thermal_zone_device *tz; |
1471 | struct thermal_cooling_device *pos; | ||
1472 | enum thermal_trip_type trip_type; | 1586 | enum thermal_trip_type trip_type; |
1473 | int result; | 1587 | int result; |
1474 | int count; | 1588 | int count; |
@@ -1567,14 +1681,11 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type, | |||
1567 | 1681 | ||
1568 | mutex_lock(&thermal_list_lock); | 1682 | mutex_lock(&thermal_list_lock); |
1569 | list_add_tail(&tz->node, &thermal_tz_list); | 1683 | list_add_tail(&tz->node, &thermal_tz_list); |
1570 | if (ops->bind) | ||
1571 | list_for_each_entry(pos, &thermal_cdev_list, node) { | ||
1572 | result = ops->bind(tz, pos); | ||
1573 | if (result) | ||
1574 | break; | ||
1575 | } | ||
1576 | mutex_unlock(&thermal_list_lock); | 1684 | mutex_unlock(&thermal_list_lock); |
1577 | 1685 | ||
1686 | /* Bind cooling devices for this zone */ | ||
1687 | bind_tz(tz); | ||
1688 | |||
1578 | INIT_DELAYED_WORK(&(tz->poll_queue), thermal_zone_device_check); | 1689 | INIT_DELAYED_WORK(&(tz->poll_queue), thermal_zone_device_check); |
1579 | 1690 | ||
1580 | thermal_zone_device_update(tz); | 1691 | thermal_zone_device_update(tz); |
@@ -1595,12 +1706,16 @@ EXPORT_SYMBOL(thermal_zone_device_register); | |||
1595 | */ | 1706 | */ |
1596 | void thermal_zone_device_unregister(struct thermal_zone_device *tz) | 1707 | void thermal_zone_device_unregister(struct thermal_zone_device *tz) |
1597 | { | 1708 | { |
1709 | int i; | ||
1710 | const struct thermal_zone_params *tzp; | ||
1598 | struct thermal_cooling_device *cdev; | 1711 | struct thermal_cooling_device *cdev; |
1599 | struct thermal_zone_device *pos = NULL; | 1712 | struct thermal_zone_device *pos = NULL; |
1600 | 1713 | ||
1601 | if (!tz) | 1714 | if (!tz) |
1602 | return; | 1715 | return; |
1603 | 1716 | ||
1717 | tzp = tz->tzp; | ||
1718 | |||
1604 | mutex_lock(&thermal_list_lock); | 1719 | mutex_lock(&thermal_list_lock); |
1605 | list_for_each_entry(pos, &thermal_tz_list, node) | 1720 | list_for_each_entry(pos, &thermal_tz_list, node) |
1606 | if (pos == tz) | 1721 | if (pos == tz) |
@@ -1611,9 +1726,25 @@ void thermal_zone_device_unregister(struct thermal_zone_device *tz) | |||
1611 | return; | 1726 | return; |
1612 | } | 1727 | } |
1613 | list_del(&tz->node); | 1728 | list_del(&tz->node); |
1614 | if (tz->ops->unbind) | 1729 | |
1615 | list_for_each_entry(cdev, &thermal_cdev_list, node) | 1730 | /* Unbind all cdevs associated with 'this' thermal zone */ |
1616 | tz->ops->unbind(tz, cdev); | 1731 | list_for_each_entry(cdev, &thermal_cdev_list, node) { |
1732 | if (tz->ops->unbind) { | ||
1733 | tz->ops->unbind(tz, cdev); | ||
1734 | continue; | ||
1735 | } | ||
1736 | |||
1737 | if (!tzp || !tzp->tbp) | ||
1738 | break; | ||
1739 | |||
1740 | for (i = 0; i < tzp->num_tbps; i++) { | ||
1741 | if (tzp->tbp[i].cdev == cdev) { | ||
1742 | __unbind(tz, tzp->tbp[i].trip_mask, cdev); | ||
1743 | tzp->tbp[i].cdev = NULL; | ||
1744 | } | ||
1745 | } | ||
1746 | } | ||
1747 | |||
1617 | mutex_unlock(&thermal_list_lock); | 1748 | mutex_unlock(&thermal_list_lock); |
1618 | 1749 | ||
1619 | thermal_zone_device_set_polling(tz, 0); | 1750 | thermal_zone_device_set_polling(tz, 0); |