gov_step_wise.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  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 <[email protected]>
  7. *
  8. * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  9. *
  10. * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  11. */
  12. #include <linux/thermal.h>
  13. #include <linux/minmax.h>
  14. #include <trace/events/thermal.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. * c. if the trend is THERMAL_TREND_RAISE_FULL, use upper limit
  22. * for this trip point
  23. * d. if the trend is THERMAL_TREND_DROP_FULL, use lower limit
  24. * for this trip point
  25. * If the temperature is lower than a trip point,
  26. * a. if the trend is THERMAL_TREND_RAISING, do nothing
  27. * b. if the trend is THERMAL_TREND_DROPPING, use lower cooling
  28. * state for this trip point, if the cooling state already
  29. * equals lower limit, deactivate the thermal instance
  30. * c. if the trend is THERMAL_TREND_RAISE_FULL, do nothing
  31. * d. if the trend is THERMAL_TREND_DROP_FULL, use lower limit,
  32. * if the cooling state already equals lower limit,
  33. * deactivate the thermal instance
  34. */
  35. static unsigned long get_target_state(struct thermal_instance *instance,
  36. enum thermal_trend trend, bool throttle)
  37. {
  38. struct thermal_cooling_device *cdev = instance->cdev;
  39. unsigned long cur_state;
  40. unsigned long next_target;
  41. /*
  42. * We keep this instance the way it is by default.
  43. * Otherwise, we use the current state of the
  44. * cdev in use to determine the next_target.
  45. */
  46. cdev->ops->get_cur_state(cdev, &cur_state);
  47. next_target = instance->target;
  48. dev_dbg(&cdev->device, "cur_state=%ld\n", cur_state);
  49. if (!instance->initialized) {
  50. if (throttle) {
  51. next_target = clamp((cur_state + 1), instance->lower, instance->upper);
  52. } else {
  53. next_target = THERMAL_NO_TARGET;
  54. }
  55. return next_target;
  56. }
  57. switch (trend) {
  58. case THERMAL_TREND_RAISING:
  59. if (throttle) {
  60. next_target = clamp((cur_state + 1), instance->lower, instance->upper);
  61. }
  62. break;
  63. case THERMAL_TREND_DROPPING:
  64. if (cur_state <= instance->lower) {
  65. if (!throttle)
  66. next_target = THERMAL_NO_TARGET;
  67. } else {
  68. if (!throttle) {
  69. next_target = clamp((cur_state - 1), instance->lower, instance->upper);
  70. }
  71. }
  72. break;
  73. default:
  74. break;
  75. }
  76. return next_target;
  77. }
  78. static void update_passive_instance(struct thermal_zone_device *tz,
  79. enum thermal_trip_type type, int value)
  80. {
  81. /*
  82. * If value is +1, activate a passive instance.
  83. * If value is -1, deactivate a passive instance.
  84. */
  85. if (type == THERMAL_TRIP_PASSIVE)
  86. tz->passive += value;
  87. }
  88. static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip)
  89. {
  90. int trip_temp;
  91. enum thermal_trip_type trip_type;
  92. enum thermal_trend trend;
  93. struct thermal_instance *instance;
  94. bool throttle = false;
  95. int old_target;
  96. tz->ops->get_trip_temp(tz, trip, &trip_temp);
  97. tz->ops->get_trip_type(tz, trip, &trip_type);
  98. trend = get_tz_trend(tz, trip);
  99. if (tz->temperature >= trip_temp) {
  100. throttle = true;
  101. trace_thermal_zone_trip(tz, trip, trip_type);
  102. }
  103. dev_dbg(&tz->device, "Trip%d[type=%d,temp=%d]:trend=%d,throttle=%d\n",
  104. trip, trip_type, trip_temp, trend, throttle);
  105. list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
  106. if (instance->trip != trip)
  107. continue;
  108. old_target = instance->target;
  109. instance->target = get_target_state(instance, trend, throttle);
  110. dev_dbg(&instance->cdev->device, "old_target=%d, target=%d\n",
  111. old_target, (int)instance->target);
  112. if (instance->initialized && old_target == instance->target)
  113. continue;
  114. /* Activate a passive thermal instance */
  115. if (old_target == THERMAL_NO_TARGET &&
  116. instance->target != THERMAL_NO_TARGET)
  117. update_passive_instance(tz, trip_type, 1);
  118. /* Deactivate a passive thermal instance */
  119. else if (old_target != THERMAL_NO_TARGET &&
  120. instance->target == THERMAL_NO_TARGET)
  121. update_passive_instance(tz, trip_type, -1);
  122. instance->initialized = true;
  123. mutex_lock(&instance->cdev->lock);
  124. instance->cdev->updated = false; /* cdev needs update */
  125. mutex_unlock(&instance->cdev->lock);
  126. }
  127. }
  128. /**
  129. * step_wise_throttle - throttles devices associated with the given zone
  130. * @tz: thermal_zone_device
  131. * @trip: trip point index
  132. *
  133. * Throttling Logic: This uses the trend of the thermal zone to throttle.
  134. * If the thermal zone is 'heating up' this throttles all the cooling
  135. * devices associated with the zone and its particular trip point, by one
  136. * step. If the zone is 'cooling down' it brings back the performance of
  137. * the devices by one step.
  138. */
  139. static int step_wise_throttle(struct thermal_zone_device *tz, int trip)
  140. {
  141. struct thermal_instance *instance;
  142. lockdep_assert_held(&tz->lock);
  143. thermal_zone_trip_update(tz, trip);
  144. list_for_each_entry(instance, &tz->thermal_instances, tz_node)
  145. thermal_cdev_update(instance->cdev);
  146. return 0;
  147. }
  148. static struct thermal_governor thermal_gov_step_wise = {
  149. .name = "step_wise",
  150. .throttle = step_wise_throttle,
  151. };
  152. THERMAL_GOVERNOR_DECLARE(thermal_gov_step_wise);