| 1 | =================================
|
| 2 | Power allocator governor tunables
|
| 3 | =================================
|
| 4 |
|
| 5 | Trip points
|
| 6 | -----------
|
| 7 |
|
| 8 | The governor works optimally with the following two passive trip points:
|
| 9 |
|
| 10 | 1. "switch on" trip point: temperature above which the governor
|
| 11 | control loop starts operating. This is the first passive trip
|
| 12 | point of the thermal zone.
|
| 13 |
|
| 14 | 2. "desired temperature" trip point: it should be higher than the
|
| 15 | "switch on" trip point. This the target temperature the governor
|
| 16 | is controlling for. This is the last passive trip point of the
|
| 17 | thermal zone.
|
| 18 |
|
| 19 | PID Controller
|
| 20 | --------------
|
| 21 |
|
| 22 | The power allocator governor implements a
|
| 23 | Proportional-Integral-Derivative controller (PID controller) with
|
| 24 | temperature as the control input and power as the controlled output:
|
| 25 |
|
| 26 | P_max = k_p * e + k_i * err_integral + k_d * diff_err + sustainable_power
|
| 27 |
|
| 28 | where
|
| 29 | - e = desired_temperature - current_temperature
|
| 30 | - err_integral is the sum of previous errors
|
| 31 | - diff_err = e - previous_error
|
| 32 |
|
| 33 | It is similar to the one depicted below::
|
| 34 |
|
| 35 | k_d
|
| 36 | |
|
| 37 | current_temp |
|
| 38 | | v
|
| 39 | | +----------+ +---+
|
| 40 | | +----->| diff_err |-->| X |------+
|
| 41 | | | +----------+ +---+ |
|
| 42 | | | | tdp actor
|
| 43 | | | k_i | | get_requested_power()
|
| 44 | | | | | | | |
|
| 45 | | | | | | | | ...
|
| 46 | v | v v v v v
|
| 47 | +---+ | +-------+ +---+ +---+ +---+ +----------+
|
| 48 | | S |-----+----->| sum e |----->| X |--->| S |-->| S |-->|power |
|
| 49 | +---+ | +-------+ +---+ +---+ +---+ |allocation|
|
| 50 | ^ | ^ +----------+
|
| 51 | | | | | |
|
| 52 | | | +---+ | | |
|
| 53 | | +------->| X |-------------------+ v v
|
| 54 | | +---+ granted performance
|
| 55 | desired_temperature ^
|
| 56 | |
|
| 57 | |
|
| 58 | k_po/k_pu
|
| 59 |
|
| 60 | Sustainable power
|
| 61 | -----------------
|
| 62 |
|
| 63 | An estimate of the sustainable dissipatable power (in mW) should be
|
| 64 | provided while registering the thermal zone. This estimates the
|
| 65 | sustained power that can be dissipated at the desired control
|
| 66 | temperature. This is the maximum sustained power for allocation at
|
| 67 | the desired maximum temperature. The actual sustained power can vary
|
| 68 | for a number of reasons. The closed loop controller will take care of
|
| 69 | variations such as environmental conditions, and some factors related
|
| 70 | to the speed-grade of the silicon. `sustainable_power` is therefore
|
| 71 | simply an estimate, and may be tuned to affect the aggressiveness of
|
| 72 | the thermal ramp. For reference, the sustainable power of a 4" phone
|
| 73 | is typically 2000mW, while on a 10" tablet is around 4500mW (may vary
|
| 74 | depending on screen size). It is possible to have the power value
|
| 75 | expressed in an abstract scale. The sustained power should be aligned
|
| 76 | to the scale used by the related cooling devices.
|
| 77 |
|
| 78 | If you are using device tree, do add it as a property of the
|
| 79 | thermal-zone. For example::
|
| 80 |
|
| 81 | thermal-zones {
|
| 82 | soc_thermal {
|
| 83 | polling-delay = <1000>;
|
| 84 | polling-delay-passive = <100>;
|
| 85 | sustainable-power = <2500>;
|
| 86 | ...
|
| 87 |
|
| 88 | Instead, if the thermal zone is registered from the platform code, pass a
|
| 89 | `thermal_zone_params` that has a `sustainable_power`. If no
|
| 90 | `thermal_zone_params` were being passed, then something like below
|
| 91 | will suffice::
|
| 92 |
|
| 93 | static const struct thermal_zone_params tz_params = {
|
| 94 | .sustainable_power = 3500,
|
| 95 | };
|
| 96 |
|
| 97 | and then pass `tz_params` as the 5th parameter to
|
| 98 | `thermal_zone_device_register()`
|
| 99 |
|
| 100 | k_po and k_pu
|
| 101 | -------------
|
| 102 |
|
| 103 | The implementation of the PID controller in the power allocator
|
| 104 | thermal governor allows the configuration of two proportional term
|
| 105 | constants: `k_po` and `k_pu`. `k_po` is the proportional term
|
| 106 | constant during temperature overshoot periods (current temperature is
|
| 107 | above "desired temperature" trip point). Conversely, `k_pu` is the
|
| 108 | proportional term constant during temperature undershoot periods
|
| 109 | (current temperature below "desired temperature" trip point).
|
| 110 |
|
| 111 | These controls are intended as the primary mechanism for configuring
|
| 112 | the permitted thermal "ramp" of the system. For instance, a lower
|
| 113 | `k_pu` value will provide a slower ramp, at the cost of capping
|
| 114 | available capacity at a low temperature. On the other hand, a high
|
| 115 | value of `k_pu` will result in the governor granting very high power
|
| 116 | while temperature is low, and may lead to temperature overshooting.
|
| 117 |
|
| 118 | The default value for `k_pu` is::
|
| 119 |
|
| 120 | 2 * sustainable_power / (desired_temperature - switch_on_temp)
|
| 121 |
|
| 122 | This means that at `switch_on_temp` the output of the controller's
|
| 123 | proportional term will be 2 * `sustainable_power`. The default value
|
| 124 | for `k_po` is::
|
| 125 |
|
| 126 | sustainable_power / (desired_temperature - switch_on_temp)
|
| 127 |
|
| 128 | Focusing on the proportional and feed forward values of the PID
|
| 129 | controller equation we have::
|
| 130 |
|
| 131 | P_max = k_p * e + sustainable_power
|
| 132 |
|
| 133 | The proportional term is proportional to the difference between the
|
| 134 | desired temperature and the current one. When the current temperature
|
| 135 | is the desired one, then the proportional component is zero and
|
| 136 | `P_max` = `sustainable_power`. That is, the system should operate in
|
| 137 | thermal equilibrium under constant load. `sustainable_power` is only
|
| 138 | an estimate, which is the reason for closed-loop control such as this.
|
| 139 |
|
| 140 | Expanding `k_pu` we get::
|
| 141 |
|
| 142 | P_max = 2 * sustainable_power * (T_set - T) / (T_set - T_on) +
|
| 143 | sustainable_power
|
| 144 |
|
| 145 | where:
|
| 146 |
|
| 147 | - T_set is the desired temperature
|
| 148 | - T is the current temperature
|
| 149 | - T_on is the switch on temperature
|
| 150 |
|
| 151 | When the current temperature is the switch_on temperature, the above
|
| 152 | formula becomes::
|
| 153 |
|
| 154 | P_max = 2 * sustainable_power * (T_set - T_on) / (T_set - T_on) +
|
| 155 | sustainable_power = 2 * sustainable_power + sustainable_power =
|
| 156 | 3 * sustainable_power
|
| 157 |
|
| 158 | Therefore, the proportional term alone linearly decreases power from
|
| 159 | 3 * `sustainable_power` to `sustainable_power` as the temperature
|
| 160 | rises from the switch on temperature to the desired temperature.
|
| 161 |
|
| 162 | k_i and integral_cutoff
|
| 163 | -----------------------
|
| 164 |
|
| 165 | `k_i` configures the PID loop's integral term constant. This term
|
| 166 | allows the PID controller to compensate for long term drift and for
|
| 167 | the quantized nature of the output control: cooling devices can't set
|
| 168 | the exact power that the governor requests. When the temperature
|
| 169 | error is below `integral_cutoff`, errors are accumulated in the
|
| 170 | integral term. This term is then multiplied by `k_i` and the result
|
| 171 | added to the output of the controller. Typically `k_i` is set low (1
|
| 172 | or 2) and `integral_cutoff` is 0.
|
| 173 |
|
| 174 | k_d
|
| 175 | ---
|
| 176 |
|
| 177 | `k_d` configures the PID loop's derivative term constant. It's
|
| 178 | recommended to leave it as the default: 0.
|
| 179 |
|
| 180 | Cooling device power API
|
| 181 | ========================
|
| 182 |
|
| 183 | Cooling devices controlled by this governor must supply the additional
|
| 184 | "power" API in their `cooling_device_ops`. It consists on three ops:
|
| 185 |
|
| 186 | 1. ::
|
| 187 |
|
| 188 | int get_requested_power(struct thermal_cooling_device *cdev,
|
| 189 | struct thermal_zone_device *tz, u32 *power);
|
| 190 |
|
| 191 |
|
| 192 | @cdev:
|
| 193 | The `struct thermal_cooling_device` pointer
|
| 194 | @tz:
|
| 195 | thermal zone in which we are currently operating
|
| 196 | @power:
|
| 197 | pointer in which to store the calculated power
|
| 198 |
|
| 199 | `get_requested_power()` calculates the power requested by the device
|
| 200 | in milliwatts and stores it in @power . It should return 0 on
|
| 201 | success, -E* on failure. This is currently used by the power
|
| 202 | allocator governor to calculate how much power to give to each cooling
|
| 203 | device.
|
| 204 |
|
| 205 | 2. ::
|
| 206 |
|
| 207 | int state2power(struct thermal_cooling_device *cdev, struct
|
| 208 | thermal_zone_device *tz, unsigned long state,
|
| 209 | u32 *power);
|
| 210 |
|
| 211 | @cdev:
|
| 212 | The `struct thermal_cooling_device` pointer
|
| 213 | @tz:
|
| 214 | thermal zone in which we are currently operating
|
| 215 | @state:
|
| 216 | A cooling device state
|
| 217 | @power:
|
| 218 | pointer in which to store the equivalent power
|
| 219 |
|
| 220 | Convert cooling device state @state into power consumption in
|
| 221 | milliwatts and store it in @power. It should return 0 on success, -E*
|
| 222 | on failure. This is currently used by thermal core to calculate the
|
| 223 | maximum power that an actor can consume.
|
| 224 |
|
| 225 | 3. ::
|
| 226 |
|
| 227 | int power2state(struct thermal_cooling_device *cdev, u32 power,
|
| 228 | unsigned long *state);
|
| 229 |
|
| 230 | @cdev:
|
| 231 | The `struct thermal_cooling_device` pointer
|
| 232 | @power:
|
| 233 | power in milliwatts
|
| 234 | @state:
|
| 235 | pointer in which to store the resulting state
|
| 236 |
|
| 237 | Calculate a cooling device state that would make the device consume at
|
| 238 | most @power mW and store it in @state. It should return 0 on success,
|
| 239 | -E* on failure. This is currently used by the thermal core to convert
|
| 240 | a given power set by the power allocator governor to a state that the
|
| 241 | cooling device can set. It is a function because this conversion may
|
| 242 | depend on external factors that may change so this function should the
|
| 243 | best conversion given "current circumstances".
|
| 244 |
|
| 245 | Cooling device weights
|
| 246 | ----------------------
|
| 247 |
|
| 248 | Weights are a mechanism to bias the allocation among cooling
|
| 249 | devices. They express the relative power efficiency of different
|
| 250 | cooling devices. Higher weight can be used to express higher power
|
| 251 | efficiency. Weighting is relative such that if each cooling device
|
| 252 | has a weight of one they are considered equal. This is particularly
|
| 253 | useful in heterogeneous systems where two cooling devices may perform
|
| 254 | the same kind of compute, but with different efficiency. For example,
|
| 255 | a system with two different types of processors.
|
| 256 |
|
| 257 | If the thermal zone is registered using
|
| 258 | `thermal_zone_device_register()` (i.e., platform code), then weights
|
| 259 | are passed as part of the thermal zone's `thermal_bind_parameters`.
|
| 260 | If the platform is registered using device tree, then they are passed
|
| 261 | as the `contribution` property of each map in the `cooling-maps` node.
|
| 262 |
|
| 263 | Limitations of the power allocator governor
|
| 264 | ===========================================
|
| 265 |
|
| 266 | The power allocator governor's PID controller works best if there is a
|
| 267 | periodic tick. If you have a driver that calls
|
| 268 | `thermal_zone_device_update()` (or anything that ends up calling the
|
| 269 | governor's `throttle()` function) repetitively, the governor response
|
| 270 | won't be very good. Note that this is not particular to this
|
| 271 | governor, step-wise will also misbehave if you call its throttle()
|
| 272 | faster than the normal thermal framework tick (due to interrupts for
|
| 273 | example) as it will overreact.
|
| 274 |
|
| 275 | Energy Model requirements
|
| 276 | =========================
|
| 277 |
|
| 278 | Another important thing is the consistent scale of the power values
|
| 279 | provided by the cooling devices. All of the cooling devices in a single
|
| 280 | thermal zone should have power values reported either in milli-Watts
|
| 281 | or scaled to the same 'abstract scale'.
|