diff options
author | Durgadoss R <durgadoss.r@intel.com> | 2012-09-18 01:35:04 -0400 |
---|---|---|
committer | Zhang Rui <rui.zhang@intel.com> | 2012-11-05 01:00:08 -0500 |
commit | 0c01ebbfd3caf1dc132e0d93c8e7e9f742839d94 (patch) | |
tree | 13245049a96b852f786e0322a6e91c5f5c90715a /drivers/thermal | |
parent | 1cc807a234cb988d69ba18f6a3a1c68d71e54bed (diff) |
Thermal: Remove throttling logic out of thermal_sys.c
This patch removes the throttling logic out of
thermal_sys.c; also refactors the code into smaller
functions so that are easy to read/maintain.
* Seperates the handling of critical and non-critical trips
* Re-arranges the set_polling and device_check methods, so
that all related functions are arranged in one place.
* Removes the 'do_update' and 'trip_update' method, as part
of moving the throttling logic out of thermal_sys.c
Signed-off-by: Durgadoss R <durgadoss.r@intel.com>
Signed-off-by: Zhang Rui <rui.zhang@intel.com>
Diffstat (limited to 'drivers/thermal')
-rw-r--r-- | drivers/thermal/thermal_sys.c | 307 |
1 files changed, 109 insertions, 198 deletions
diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c index 9d21f82986ee..64f3e9735316 100644 --- a/drivers/thermal/thermal_sys.c +++ b/drivers/thermal/thermal_sys.c | |||
@@ -306,6 +306,115 @@ exit: | |||
306 | mutex_unlock(&thermal_list_lock); | 306 | mutex_unlock(&thermal_list_lock); |
307 | } | 307 | } |
308 | 308 | ||
309 | static void thermal_zone_device_set_polling(struct thermal_zone_device *tz, | ||
310 | int delay) | ||
311 | { | ||
312 | if (delay > 1000) | ||
313 | mod_delayed_work(system_freezable_wq, &tz->poll_queue, | ||
314 | round_jiffies(msecs_to_jiffies(delay))); | ||
315 | else if (delay) | ||
316 | mod_delayed_work(system_freezable_wq, &tz->poll_queue, | ||
317 | msecs_to_jiffies(delay)); | ||
318 | else | ||
319 | cancel_delayed_work(&tz->poll_queue); | ||
320 | } | ||
321 | |||
322 | static void monitor_thermal_zone(struct thermal_zone_device *tz) | ||
323 | { | ||
324 | mutex_lock(&tz->lock); | ||
325 | |||
326 | if (tz->passive) | ||
327 | thermal_zone_device_set_polling(tz, tz->passive_delay); | ||
328 | else if (tz->polling_delay) | ||
329 | thermal_zone_device_set_polling(tz, tz->polling_delay); | ||
330 | else | ||
331 | thermal_zone_device_set_polling(tz, 0); | ||
332 | |||
333 | mutex_unlock(&tz->lock); | ||
334 | } | ||
335 | |||
336 | static void handle_non_critical_trips(struct thermal_zone_device *tz, | ||
337 | int trip, enum thermal_trip_type trip_type) | ||
338 | { | ||
339 | tz->governor->throttle(tz, trip); | ||
340 | } | ||
341 | |||
342 | static void handle_critical_trips(struct thermal_zone_device *tz, | ||
343 | int trip, enum thermal_trip_type trip_type) | ||
344 | { | ||
345 | long trip_temp; | ||
346 | |||
347 | tz->ops->get_trip_temp(tz, trip, &trip_temp); | ||
348 | |||
349 | /* If we have not crossed the trip_temp, we do not care. */ | ||
350 | if (tz->temperature < trip_temp) | ||
351 | return; | ||
352 | |||
353 | if (tz->ops->notify) | ||
354 | tz->ops->notify(tz, trip, trip_type); | ||
355 | |||
356 | if (trip_type == THERMAL_TRIP_CRITICAL) { | ||
357 | pr_emerg("Critical temperature reached(%d C),shutting down\n", | ||
358 | tz->temperature / 1000); | ||
359 | orderly_poweroff(true); | ||
360 | } | ||
361 | } | ||
362 | |||
363 | static void handle_thermal_trip(struct thermal_zone_device *tz, int trip) | ||
364 | { | ||
365 | enum thermal_trip_type type; | ||
366 | |||
367 | tz->ops->get_trip_type(tz, trip, &type); | ||
368 | |||
369 | if (type == THERMAL_TRIP_CRITICAL || type == THERMAL_TRIP_HOT) | ||
370 | handle_critical_trips(tz, trip, type); | ||
371 | else | ||
372 | handle_non_critical_trips(tz, trip, type); | ||
373 | /* | ||
374 | * Alright, we handled this trip successfully. | ||
375 | * So, start monitoring again. | ||
376 | */ | ||
377 | monitor_thermal_zone(tz); | ||
378 | } | ||
379 | |||
380 | static void update_temperature(struct thermal_zone_device *tz) | ||
381 | { | ||
382 | long temp; | ||
383 | int ret; | ||
384 | |||
385 | mutex_lock(&tz->lock); | ||
386 | |||
387 | ret = tz->ops->get_temp(tz, &temp); | ||
388 | if (ret) { | ||
389 | pr_warn("failed to read out thermal zone %d\n", tz->id); | ||
390 | return; | ||
391 | } | ||
392 | |||
393 | tz->last_temperature = tz->temperature; | ||
394 | tz->temperature = temp; | ||
395 | |||
396 | mutex_unlock(&tz->lock); | ||
397 | } | ||
398 | |||
399 | void thermal_zone_device_update(struct thermal_zone_device *tz) | ||
400 | { | ||
401 | int count; | ||
402 | |||
403 | update_temperature(tz); | ||
404 | |||
405 | for (count = 0; count < tz->trips; count++) | ||
406 | handle_thermal_trip(tz, count); | ||
407 | } | ||
408 | EXPORT_SYMBOL(thermal_zone_device_update); | ||
409 | |||
410 | static void thermal_zone_device_check(struct work_struct *work) | ||
411 | { | ||
412 | struct thermal_zone_device *tz = container_of(work, struct | ||
413 | thermal_zone_device, | ||
414 | poll_queue.work); | ||
415 | thermal_zone_device_update(tz); | ||
416 | } | ||
417 | |||
309 | /* sys I/F for thermal zone */ | 418 | /* sys I/F for thermal zone */ |
310 | 419 | ||
311 | #define to_thermal_zone(_dev) \ | 420 | #define to_thermal_zone(_dev) \ |
@@ -936,27 +1045,6 @@ thermal_remove_hwmon_sysfs(struct thermal_zone_device *tz) | |||
936 | } | 1045 | } |
937 | #endif | 1046 | #endif |
938 | 1047 | ||
939 | static void thermal_zone_device_set_polling(struct thermal_zone_device *tz, | ||
940 | int delay) | ||
941 | { | ||
942 | if (delay > 1000) | ||
943 | mod_delayed_work(system_freezable_wq, &tz->poll_queue, | ||
944 | round_jiffies(msecs_to_jiffies(delay))); | ||
945 | else if (delay) | ||
946 | mod_delayed_work(system_freezable_wq, &tz->poll_queue, | ||
947 | msecs_to_jiffies(delay)); | ||
948 | else | ||
949 | cancel_delayed_work(&tz->poll_queue); | ||
950 | } | ||
951 | |||
952 | static void thermal_zone_device_check(struct work_struct *work) | ||
953 | { | ||
954 | struct thermal_zone_device *tz = container_of(work, struct | ||
955 | thermal_zone_device, | ||
956 | poll_queue.work); | ||
957 | thermal_zone_device_update(tz); | ||
958 | } | ||
959 | |||
960 | /** | 1048 | /** |
961 | * thermal_zone_bind_cooling_device - bind a cooling device to a thermal zone | 1049 | * thermal_zone_bind_cooling_device - bind a cooling device to a thermal zone |
962 | * @tz: thermal zone device | 1050 | * @tz: thermal zone device |
@@ -1280,183 +1368,6 @@ void thermal_cdev_update(struct thermal_cooling_device *cdev) | |||
1280 | } | 1368 | } |
1281 | EXPORT_SYMBOL(thermal_cdev_update); | 1369 | EXPORT_SYMBOL(thermal_cdev_update); |
1282 | 1370 | ||
1283 | static void thermal_zone_do_update(struct thermal_zone_device *tz) | ||
1284 | { | ||
1285 | struct thermal_instance *instance; | ||
1286 | |||
1287 | list_for_each_entry(instance, &tz->thermal_instances, tz_node) | ||
1288 | thermal_cdev_update(instance->cdev); | ||
1289 | } | ||
1290 | |||
1291 | /* | ||
1292 | * Cooling algorithm for both active and passive cooling | ||
1293 | * | ||
1294 | * 1. if the temperature is higher than a trip point, | ||
1295 | * a. if the trend is THERMAL_TREND_RAISING, use higher cooling | ||
1296 | * state for this trip point | ||
1297 | * b. if the trend is THERMAL_TREND_DROPPING, use lower cooling | ||
1298 | * state for this trip point | ||
1299 | * | ||
1300 | * 2. if the temperature is lower than a trip point, use lower | ||
1301 | * cooling state for this trip point | ||
1302 | * | ||
1303 | * Note that this behaves the same as the previous passive cooling | ||
1304 | * algorithm. | ||
1305 | */ | ||
1306 | |||
1307 | static void thermal_zone_trip_update(struct thermal_zone_device *tz, | ||
1308 | int trip, long temp) | ||
1309 | { | ||
1310 | struct thermal_instance *instance; | ||
1311 | struct thermal_cooling_device *cdev = NULL; | ||
1312 | unsigned long cur_state, max_state; | ||
1313 | long trip_temp; | ||
1314 | enum thermal_trip_type trip_type; | ||
1315 | enum thermal_trend trend; | ||
1316 | |||
1317 | if (trip == THERMAL_TRIPS_NONE) { | ||
1318 | trip_temp = tz->forced_passive; | ||
1319 | trip_type = THERMAL_TRIPS_NONE; | ||
1320 | } else { | ||
1321 | tz->ops->get_trip_temp(tz, trip, &trip_temp); | ||
1322 | tz->ops->get_trip_type(tz, trip, &trip_type); | ||
1323 | } | ||
1324 | |||
1325 | if (!tz->ops->get_trend || tz->ops->get_trend(tz, trip, &trend)) { | ||
1326 | /* | ||
1327 | * compare the current temperature and previous temperature | ||
1328 | * to get the thermal trend, if no special requirement | ||
1329 | */ | ||
1330 | if (tz->temperature > tz->last_temperature) | ||
1331 | trend = THERMAL_TREND_RAISING; | ||
1332 | else if (tz->temperature < tz->last_temperature) | ||
1333 | trend = THERMAL_TREND_DROPPING; | ||
1334 | else | ||
1335 | trend = THERMAL_TREND_STABLE; | ||
1336 | } | ||
1337 | |||
1338 | if (temp >= trip_temp) { | ||
1339 | list_for_each_entry(instance, &tz->thermal_instances, tz_node) { | ||
1340 | if (instance->trip != trip) | ||
1341 | continue; | ||
1342 | |||
1343 | cdev = instance->cdev; | ||
1344 | |||
1345 | cdev->ops->get_cur_state(cdev, &cur_state); | ||
1346 | cdev->ops->get_max_state(cdev, &max_state); | ||
1347 | |||
1348 | if (trend == THERMAL_TREND_RAISING) { | ||
1349 | cur_state = cur_state < instance->upper ? | ||
1350 | (cur_state + 1) : instance->upper; | ||
1351 | } else if (trend == THERMAL_TREND_DROPPING) { | ||
1352 | cur_state = cur_state > instance->lower ? | ||
1353 | (cur_state - 1) : instance->lower; | ||
1354 | } | ||
1355 | |||
1356 | /* activate a passive thermal instance */ | ||
1357 | if ((trip_type == THERMAL_TRIP_PASSIVE || | ||
1358 | trip_type == THERMAL_TRIPS_NONE) && | ||
1359 | instance->target == THERMAL_NO_TARGET) | ||
1360 | tz->passive++; | ||
1361 | |||
1362 | instance->target = cur_state; | ||
1363 | cdev->updated = false; /* cooling device needs update */ | ||
1364 | } | ||
1365 | } else { /* below trip */ | ||
1366 | list_for_each_entry(instance, &tz->thermal_instances, tz_node) { | ||
1367 | if (instance->trip != trip) | ||
1368 | continue; | ||
1369 | |||
1370 | /* Do not use the inactive thermal instance */ | ||
1371 | if (instance->target == THERMAL_NO_TARGET) | ||
1372 | continue; | ||
1373 | cdev = instance->cdev; | ||
1374 | cdev->ops->get_cur_state(cdev, &cur_state); | ||
1375 | |||
1376 | cur_state = cur_state > instance->lower ? | ||
1377 | (cur_state - 1) : THERMAL_NO_TARGET; | ||
1378 | |||
1379 | /* deactivate a passive thermal instance */ | ||
1380 | if ((trip_type == THERMAL_TRIP_PASSIVE || | ||
1381 | trip_type == THERMAL_TRIPS_NONE) && | ||
1382 | cur_state == THERMAL_NO_TARGET) | ||
1383 | tz->passive--; | ||
1384 | instance->target = cur_state; | ||
1385 | cdev->updated = false; /* cooling device needs update */ | ||
1386 | } | ||
1387 | } | ||
1388 | |||
1389 | return; | ||
1390 | } | ||
1391 | /** | ||
1392 | * thermal_zone_device_update - force an update of a thermal zone's state | ||
1393 | * @ttz: the thermal zone to update | ||
1394 | */ | ||
1395 | |||
1396 | void thermal_zone_device_update(struct thermal_zone_device *tz) | ||
1397 | { | ||
1398 | int count, ret = 0; | ||
1399 | long temp, trip_temp; | ||
1400 | enum thermal_trip_type trip_type; | ||
1401 | |||
1402 | mutex_lock(&tz->lock); | ||
1403 | |||
1404 | if (tz->ops->get_temp(tz, &temp)) { | ||
1405 | /* get_temp failed - retry it later */ | ||
1406 | pr_warn("failed to read out thermal zone %d\n", tz->id); | ||
1407 | goto leave; | ||
1408 | } | ||
1409 | |||
1410 | tz->last_temperature = tz->temperature; | ||
1411 | tz->temperature = temp; | ||
1412 | |||
1413 | for (count = 0; count < tz->trips; count++) { | ||
1414 | tz->ops->get_trip_type(tz, count, &trip_type); | ||
1415 | tz->ops->get_trip_temp(tz, count, &trip_temp); | ||
1416 | |||
1417 | switch (trip_type) { | ||
1418 | case THERMAL_TRIP_CRITICAL: | ||
1419 | if (temp >= trip_temp) { | ||
1420 | if (tz->ops->notify) | ||
1421 | ret = tz->ops->notify(tz, count, | ||
1422 | trip_type); | ||
1423 | if (!ret) { | ||
1424 | pr_emerg("Critical temperature reached (%ld C), shutting down\n", | ||
1425 | temp/1000); | ||
1426 | orderly_poweroff(true); | ||
1427 | } | ||
1428 | } | ||
1429 | break; | ||
1430 | case THERMAL_TRIP_HOT: | ||
1431 | if (temp >= trip_temp) | ||
1432 | if (tz->ops->notify) | ||
1433 | tz->ops->notify(tz, count, trip_type); | ||
1434 | break; | ||
1435 | case THERMAL_TRIP_ACTIVE: | ||
1436 | thermal_zone_trip_update(tz, count, temp); | ||
1437 | break; | ||
1438 | case THERMAL_TRIP_PASSIVE: | ||
1439 | if (temp >= trip_temp || tz->passive) | ||
1440 | thermal_zone_trip_update(tz, count, temp); | ||
1441 | break; | ||
1442 | } | ||
1443 | } | ||
1444 | |||
1445 | if (tz->forced_passive) | ||
1446 | thermal_zone_trip_update(tz, THERMAL_TRIPS_NONE, temp); | ||
1447 | thermal_zone_do_update(tz); | ||
1448 | |||
1449 | leave: | ||
1450 | if (tz->passive) | ||
1451 | thermal_zone_device_set_polling(tz, tz->passive_delay); | ||
1452 | else if (tz->polling_delay) | ||
1453 | thermal_zone_device_set_polling(tz, tz->polling_delay); | ||
1454 | else | ||
1455 | thermal_zone_device_set_polling(tz, 0); | ||
1456 | mutex_unlock(&tz->lock); | ||
1457 | } | ||
1458 | EXPORT_SYMBOL(thermal_zone_device_update); | ||
1459 | |||
1460 | /** | 1371 | /** |
1461 | * create_trip_attrs - create attributes for trip points | 1372 | * create_trip_attrs - create attributes for trip points |
1462 | * @tz: the thermal zone device | 1373 | * @tz: the thermal zone device |