gov_step_wise.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * step_wise.c - A step-by-step Thermal throttling governor
  4. *
  5. * Copyright (C) 2012 Intel Corp
  6. * Copyright (C) 2012 Durgadoss R <durgadoss.r@intel.com>
  7. *
  8. * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  9. *
  10. * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  11. */
  12. #include <linux/thermal.h>
  13. #include <linux/minmax.h>
  14. #include "thermal_trace.h"
  15. #include "thermal_core.h"
  16. /*
  17. * If the temperature is higher than a trip point,
  18. * a. if the trend is THERMAL_TREND_RAISING, use higher cooling
  19. * state for this trip point
  20. * b. if the trend is THERMAL_TREND_DROPPING, do nothing
  21. * If the temperature is lower than a trip point,
  22. * a. if the trend is THERMAL_TREND_RAISING, do nothing
  23. * b. if the trend is THERMAL_TREND_DROPPING, use lower cooling
  24. * state for this trip point, if the cooling state already
  25. * equals lower limit, deactivate the thermal instance
  26. */
  27. static unsigned long get_target_state(struct thermal_instance *instance,
  28. enum thermal_trend trend, bool throttle)
  29. {
  30. struct thermal_cooling_device *cdev = instance->cdev;
  31. unsigned long cur_state;
  32. /*
  33. * We keep this instance the way it is by default.
  34. * Otherwise, we use the current state of the
  35. * cdev in use to determine the next_target.
  36. */
  37. cdev->ops->get_cur_state(cdev, &cur_state);
  38. dev_dbg(&cdev->device, "cur_state=%ld\n", cur_state);
  39. if (!instance->initialized) {
  40. if (throttle)
  41. return clamp(cur_state + 1, instance->lower, instance->upper);
  42. return THERMAL_NO_TARGET;
  43. }
  44. if (throttle) {
  45. if (trend == THERMAL_TREND_RAISING)
  46. return clamp(cur_state + 1, instance->lower, instance->upper);
  47. } else if (trend == THERMAL_TREND_DROPPING) {
  48. if (cur_state <= instance->lower)
  49. return THERMAL_NO_TARGET;
  50. /*
  51. * If 'throttle' is false, no mitigation is necessary, so
  52. * request the lower state for this instance.
  53. */
  54. return instance->lower;
  55. }
  56. return instance->target;
  57. }
  58. static void thermal_zone_trip_update(struct thermal_zone_device *tz,
  59. const struct thermal_trip_desc *td,
  60. int trip_threshold)
  61. {
  62. const struct thermal_trip *trip = &td->trip;
  63. enum thermal_trend trend = get_tz_trend(tz, trip);
  64. int trip_id = thermal_zone_trip_id(tz, trip);
  65. struct thermal_instance *instance;
  66. bool throttle = false;
  67. if (tz->temperature >= trip_threshold) {
  68. throttle = true;
  69. trace_thermal_zone_trip(tz, trip_id, trip->type);
  70. }
  71. dev_dbg(&tz->device, "Trip%d[type=%d,temp=%d]:trend=%d,throttle=%d\n",
  72. trip_id, trip->type, trip_threshold, trend, throttle);
  73. list_for_each_entry(instance, &td->thermal_instances, trip_node) {
  74. int old_target;
  75. old_target = instance->target;
  76. instance->target = get_target_state(instance, trend, throttle);
  77. dev_dbg(&instance->cdev->device, "old_target=%d, target=%ld\n",
  78. old_target, instance->target);
  79. if (instance->initialized && old_target == instance->target)
  80. continue;
  81. instance->initialized = true;
  82. mutex_lock(&instance->cdev->lock);
  83. instance->cdev->updated = false; /* cdev needs update */
  84. mutex_unlock(&instance->cdev->lock);
  85. }
  86. }
  87. static void step_wise_manage(struct thermal_zone_device *tz)
  88. {
  89. const struct thermal_trip_desc *td;
  90. struct thermal_instance *instance;
  91. lockdep_assert_held(&tz->lock);
  92. /*
  93. * Throttling Logic: Use the trend of the thermal zone to throttle.
  94. * If the thermal zone is 'heating up', throttle all of the cooling
  95. * devices associated with each trip point by one step. If the zone
  96. * is 'cooling down', it brings back the performance of the devices
  97. * by one step.
  98. */
  99. for_each_trip_desc(tz, td) {
  100. const struct thermal_trip *trip = &td->trip;
  101. if (trip->temperature == THERMAL_TEMP_INVALID ||
  102. trip->type == THERMAL_TRIP_CRITICAL ||
  103. trip->type == THERMAL_TRIP_HOT)
  104. continue;
  105. thermal_zone_trip_update(tz, td, td->threshold);
  106. }
  107. for_each_trip_desc(tz, td) {
  108. list_for_each_entry(instance, &td->thermal_instances, trip_node)
  109. thermal_cdev_update(instance->cdev);
  110. }
  111. }
  112. static struct thermal_governor thermal_gov_step_wise = {
  113. .name = "step_wise",
  114. .manage = step_wise_manage,
  115. };
  116. THERMAL_GOVERNOR_DECLARE(thermal_gov_step_wise);