aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/thermal
diff options
context:
space:
mode:
authorDurgadoss R <durgadoss.r@intel.com>2012-09-18 01:35:04 -0400
committerZhang Rui <rui.zhang@intel.com>2012-11-05 01:00:08 -0500
commit0c01ebbfd3caf1dc132e0d93c8e7e9f742839d94 (patch)
tree13245049a96b852f786e0322a6e91c5f5c90715a /drivers/thermal
parent1cc807a234cb988d69ba18f6a3a1c68d71e54bed (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.c307
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
309static 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
322static 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
336static 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
342static 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
363static 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
380static 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
399void 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}
408EXPORT_SYMBOL(thermal_zone_device_update);
409
410static 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
939static 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
952static 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}
1281EXPORT_SYMBOL(thermal_cdev_update); 1369EXPORT_SYMBOL(thermal_cdev_update);
1282 1370
1283static 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
1307static 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
1396void 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
1449leave:
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}
1458EXPORT_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