요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.
1. 요약·해설
원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.
2. 영어 원문 전체
번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.
원문 전체 펼치기
=================================
Power allocator governor tunables
=================================
Trip points
-----------
The governor works optimally with the following two passive trip points:
1. "switch on" trip point: temperature above which the governor
control loop starts operating. This is the first passive trip
point of the thermal zone.
2. "desired temperature" trip point: it should be higher than the
"switch on" trip point. This the target temperature the governor
is controlling for. This is the last passive trip point of the
thermal zone.
PID Controller
--------------
The power allocator governor implements a
Proportional-Integral-Derivative controller (PID controller) with
temperature as the control input and power as the controlled output:
P_max = k_p * e + k_i * err_integral + k_d * diff_err + sustainable_power
where
- e = desired_temperature - current_temperature
- err_integral is the sum of previous errors
- diff_err = e - previous_error
It is similar to the one depicted below::
k_d
|
current_temp |
| v
| +----------+ +---+
| +----->| diff_err |-->| X |------+
| | +----------+ +---+ |
| | | tdp actor
| | k_i | | get_requested_power()
| | | | | | |
| | | | | | | ...
v | v v v v v
+---+ | +-------+ +---+ +---+ +---+ +----------+
| S |-----+----->| sum e |----->| X |--->| S |-->| S |-->|power |
+---+ | +-------+ +---+ +---+ +---+ |allocation|
^ | ^ +----------+
| | | | |
| | +---+ | | |
| +------->| X |-------------------+ v v
| +---+ granted performance
desired_temperature ^
|
|
k_po/k_pu
Sustainable power
-----------------
An estimate of the sustainable dissipatable power (in mW) should be
provided while registering the thermal zone. This estimates the
sustained power that can be dissipated at the desired control
temperature. This is the maximum sustained power for allocation at
the desired maximum temperature. The actual sustained power can vary
for a number of reasons. The closed loop controller will take care of
variations such as environmental conditions, and some factors related
to the speed-grade of the silicon. `sustainable_power` is therefore
simply an estimate, and may be tuned to affect the aggressiveness of
the thermal ramp. For reference, the sustainable power of a 4" phone
is typically 2000mW, while on a 10" tablet is around 4500mW (may vary
depending on screen size). It is possible to have the power value
expressed in an abstract scale. The sustained power should be aligned
to the scale used by the related cooling devices.
If you are using device tree, do add it as a property of the
thermal-zone. For example::
thermal-zones {
soc_thermal {
polling-delay = <1000>;
polling-delay-passive = <100>;
sustainable-power = <2500>;
...
Instead, if the thermal zone is registered from the platform code, pass a
`thermal_zone_params` that has a `sustainable_power`. If no
`thermal_zone_params` were being passed, then something like below
will suffice::
static const struct thermal_zone_params tz_params = {
.sustainable_power = 3500,
};
and then pass `tz_params` as the 5th parameter to
`thermal_zone_device_register()`
k_po and k_pu
-------------
The implementation of the PID controller in the power allocator
thermal governor allows the configuration of two proportional term
constants: `k_po` and `k_pu`. `k_po` is the proportional term
constant during temperature overshoot periods (current temperature is
above "desired temperature" trip point). Conversely, `k_pu` is the
proportional term constant during temperature undershoot periods
(current temperature below "desired temperature" trip point).
These controls are intended as the primary mechanism for configuring
the permitted thermal "ramp" of the system. For instance, a lower
`k_pu` value will provide a slower ramp, at the cost of capping
available capacity at a low temperature. On the other hand, a high
value of `k_pu` will result in the governor granting very high power
while temperature is low, and may lead to temperature overshooting.
The default value for `k_pu` is::
2 * sustainable_power / (desired_temperature - switch_on_temp)
This means that at `switch_on_temp` the output of the controller's
proportional term will be 2 * `sustainable_power`. The default value
for `k_po` is::
sustainable_power / (desired_temperature - switch_on_temp)
Focusing on the proportional and feed forward values of the PID
controller equation we have::
P_max = k_p * e + sustainable_power
The proportional term is proportional to the difference between the
desired temperature and the current one. When the current temperature
is the desired one, then the proportional component is zero and
`P_max` = `sustainable_power`. That is, the system should operate in
thermal equilibrium under constant load. `sustainable_power` is only
an estimate, which is the reason for closed-loop control such as this.
Expanding `k_pu` we get::
P_max = 2 * sustainable_power * (T_set - T) / (T_set - T_on) +
sustainable_power
where:
- T_set is the desired temperature
- T is the current temperature
- T_on is the switch on temperature
When the current temperature is the switch_on temperature, the above
formula becomes::
P_max = 2 * sustainable_power * (T_set - T_on) / (T_set - T_on) +
sustainable_power = 2 * sustainable_power + sustainable_power =
3 * sustainable_power
Therefore, the proportional term alone linearly decreases power from
3 * `sustainable_power` to `sustainable_power` as the temperature
rises from the switch on temperature to the desired temperature.
k_i and integral_cutoff
-----------------------
`k_i` configures the PID loop's integral term constant. This term
allows the PID controller to compensate for long term drift and for
the quantized nature of the output control: cooling devices can't set
the exact power that the governor requests. When the temperature
error is below `integral_cutoff`, errors are accumulated in the
integral term. This term is then multiplied by `k_i` and the result
added to the output of the controller. Typically `k_i` is set low (1
or 2) and `integral_cutoff` is 0.
k_d
---
`k_d` configures the PID loop's derivative term constant. It's
recommended to leave it as the default: 0.
Cooling device power API
========================
Cooling devices controlled by this governor must supply the additional
"power" API in their `cooling_device_ops`. It consists on three ops:
1. ::
int get_requested_power(struct thermal_cooling_device *cdev,
struct thermal_zone_device *tz, u32 *power);
@cdev:
The `struct thermal_cooling_device` pointer
@tz:
thermal zone in which we are currently operating
@power:
pointer in which to store the calculated power
`get_requested_power()` calculates the power requested by the device
in milliwatts and stores it in @power . It should return 0 on
success, -E* on failure. This is currently used by the power
allocator governor to calculate how much power to give to each cooling
device.
2. ::
int state2power(struct thermal_cooling_device *cdev, struct
thermal_zone_device *tz, unsigned long state,
u32 *power);
@cdev:
The `struct thermal_cooling_device` pointer
@tz:
thermal zone in which we are currently operating
@state:
A cooling device state
@power:
pointer in which to store the equivalent power
Convert cooling device state @state into power consumption in
milliwatts and store it in @power. It should return 0 on success, -E*
on failure. This is currently used by thermal core to calculate the
maximum power that an actor can consume.
3. ::
int power2state(struct thermal_cooling_device *cdev, u32 power,
unsigned long *state);
@cdev:
The `struct thermal_cooling_device` pointer
@power:
power in milliwatts
@state:
pointer in which to store the resulting state
Calculate a cooling device state that would make the device consume at
most @power mW and store it in @state. It should return 0 on success,
-E* on failure. This is currently used by the thermal core to convert
a given power set by the power allocator governor to a state that the
cooling device can set. It is a function because this conversion may
depend on external factors that may change so this function should the
best conversion given "current circumstances".
Cooling device weights
----------------------
Weights are a mechanism to bias the allocation among cooling
devices. They express the relative power efficiency of different
cooling devices. Higher weight can be used to express higher power
efficiency. Weighting is relative such that if each cooling device
has a weight of one they are considered equal. This is particularly
useful in heterogeneous systems where two cooling devices may perform
the same kind of compute, but with different efficiency. For example,
a system with two different types of processors.
If the thermal zone is registered using
`thermal_zone_device_register()` (i.e., platform code), then weights
are passed as part of the thermal zone's `thermal_bind_parameters`.
If the platform is registered using device tree, then they are passed
as the `contribution` property of each map in the `cooling-maps` node.
Limitations of the power allocator governor
===========================================
The power allocator governor's PID controller works best if there is a
periodic tick. If you have a driver that calls
`thermal_zone_device_update()` (or anything that ends up calling the
governor's `throttle()` function) repetitively, the governor response
won't be very good. Note that this is not particular to this
governor, step-wise will also misbehave if you call its throttle()
faster than the normal thermal framework tick (due to interrupts for
example) as it will overreact.
Energy Model requirements
=========================
Another important thing is the consistent scale of the power values
provided by the cooling devices. All of the cooling devices in a single
thermal zone should have power values reported either in milli-Watts
or scaled to the same 'abstract scale'.
3. 한국어 전문 번역
영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.
Power allocator의 두 passive trip point
1-18Power allocator governor는 두 개의 passive trip point를 사용할 때 최적으로 동작합니다.
첫 passive trip point인 `switch on`은 이 온도를 넘으면 governor control loop가 동작을 시작하는 기준입니다.
마지막 passive trip point인 `desired temperature`는 `switch on`보다 높아야 하며 governor가 맞추려는 target temperature입니다.
=================================
Power allocator governor tunables
=================================
Trip points
-----------
The governor works optimally with the following two passive trip points:
1. "switch on" trip point: temperature above which the governor
control loop starts operating. This is the first passive trip
point of the thermal zone.
2. "desired temperature" trip point: it should be higher than the
"switch on" trip point. This the target temperature the governor
is controlling for. This is the last passive trip point of the
thermal zone.
PID controller와 power allocation 흐름
19-59Power allocator governor는 temperature를 control input으로, power를 controlled output으로 사용하는 Proportional-Integral-Derivative controller(PID controller)를 구현합니다.
출력은 `P_max = k_p * e + k_i * err_integral + k_d * diff_err + sustainable_power`입니다. 여기서 `e = desired_temperature - current_temperature`, `err_integral`은 이전 error의 합, `diff_err = e - previous_error`입니다.
원문의 회로에서 current temperature와 desired temperature의 차이가 error가 됩니다. Error는 proportional 경로, 누적 error의 integral 경로, 이전 error와의 차이를 쓰는 derivative 경로로 나뉘고 `sustainable_power` feed-forward 값과 합쳐집니다.
그 결과인 허용 power는 각 actor가 `get_requested_power()`로 요청한 값과 함께 power allocation에 입력되고, actor별 granted performance를 결정합니다.
원문의 PID ASCII 회로를 같은 신호와 합산 관계로 구조화했습니다.
PID Controller
--------------
The power allocator governor implements a
Proportional-Integral-Derivative controller (PID controller) with
temperature as the control input and power as the controlled output:
P_max = k_p * e + k_i * err_integral + k_d * diff_err + sustainable_power
where
- e = desired_temperature - current_temperature
- err_integral is the sum of previous errors
- diff_err = e - previous_error
It is similar to the one depicted below::
k_d
|
current_temp |
| v
| +----------+ +---+
| +----->| diff_err |-->| X |------+
| | +----------+ +---+ |
| | | tdp actor
| | k_i | | get_requested_power()
| | | | | | |
| | | | | | | ...
v | v v v v v
+---+ | +-------+ +---+ +---+ +---+ +----------+
| S |-----+----->| sum e |----->| X |--->| S |-->| S |-->|power |
+---+ | +-------+ +---+ +---+ +---+ |allocation|
^ | ^ +----------+
| | | | |
| | +---+ | | |
| +------->| X |-------------------+ v v
| +---+ granted performance
desired_temperature ^
|
|
k_po/k_pu
Sustainable power 추정과 등록
60-99Thermal zone을 등록할 때 지속적으로 방출할 수 있는 power의 추정값을 mW 단위로 제공해야 합니다. 이는 desired control temperature에서 방출 가능한 sustained power이자, 원하는 maximum temperature에서 allocation할 수 있는 maximum sustained power입니다.
실제 sustained power는 환경 조건과 silicon speed-grade 같은 요인으로 달라질 수 있으며 closed-loop controller가 이 variation을 보정합니다. 따라서 `sustainable_power`는 추정값일 뿐이고 thermal ramp의 공격성을 조절하도록 tuning할 수 있습니다.
참고로 4-inch phone은 보통 2000mW, 10-inch tablet은 약 4500mW이며 screen size에 따라 달라질 수 있습니다. Power를 abstract scale로 표현해도 되지만 related cooling device가 쓰는 scale과 일치해야 합니다.
Device tree를 사용하면 thermal-zone property로 `sustainable-power = <2500>;`처럼 추가합니다. Platform code에서 thermal zone을 등록하면 `sustainable_power`가 포함된 `thermal_zone_params`를 전달하고, 이 `tz_params`를 `thermal_zone_device_register()`의 다섯 번째 parameter로 넘깁니다.
Sustainable power
-----------------
An estimate of the sustainable dissipatable power (in mW) should be
provided while registering the thermal zone. This estimates the
sustained power that can be dissipated at the desired control
temperature. This is the maximum sustained power for allocation at
the desired maximum temperature. The actual sustained power can vary
for a number of reasons. The closed loop controller will take care of
variations such as environmental conditions, and some factors related
to the speed-grade of the silicon. `sustainable_power` is therefore
simply an estimate, and may be tuned to affect the aggressiveness of
the thermal ramp. For reference, the sustainable power of a 4" phone
is typically 2000mW, while on a 10" tablet is around 4500mW (may vary
depending on screen size). It is possible to have the power value
expressed in an abstract scale. The sustained power should be aligned
to the scale used by the related cooling devices.
If you are using device tree, do add it as a property of the
thermal-zone. For example::
thermal-zones {
soc_thermal {
polling-delay = <1000>;
polling-delay-passive = <100>;
sustainable-power = <2500>;
...
Instead, if the thermal zone is registered from the platform code, pass a
`thermal_zone_params` that has a `sustainable_power`. If no
`thermal_zone_params` were being passed, then something like below
will suffice::
static const struct thermal_zone_params tz_params = {
.sustainable_power = 3500,
};
and then pass `tz_params` as the 5th parameter to
`thermal_zone_device_register()`
비례 상수 k_po와 k_pu
100-161Power allocator의 PID controller는 두 proportional term constant인 `k_po`와 `k_pu`를 설정할 수 있습니다. `k_po`는 current temperature가 desired temperature trip point보다 높은 overshoot 기간에, `k_pu`는 그보다 낮은 undershoot 기간에 사용합니다.
이 값들은 system에서 허용할 thermal ramp를 설정하는 주된 수단입니다. 낮은 `k_pu`는 ramp를 느리게 하지만 낮은 temperature에서도 available capacity를 제한합니다. 높은 `k_pu`는 temperature가 낮을 때 governor가 매우 큰 power를 허용하여 overshoot를 일으킬 수 있습니다.
기본값은 `k_pu = 2 * sustainable_power / (desired_temperature - switch_on_temp)`와 `k_po = sustainable_power / (desired_temperature - switch_on_temp)`입니다. 따라서 `switch_on_temp`에서 proportional term output은 `2 * sustainable_power`입니다.
Proportional과 feed-forward만 보면 `P_max = k_p * e + sustainable_power`입니다. Current temperature가 desired temperature와 같으면 proportional component가 0이므로 `P_max = sustainable_power`가 되어 constant load에서 thermal equilibrium을 이뤄야 합니다. 추정 오차는 closed-loop control이 보정합니다.
`k_pu`를 전개하면 `P_max = 2 * sustainable_power * (T_set - T) / (T_set - T_on) + sustainable_power`입니다. `T_set`은 desired temperature, `T`는 current temperature, `T_on`은 switch on temperature입니다.
Current temperature가 `T_on`이면 `P_max = 3 * sustainable_power`가 됩니다. 그러므로 proportional term만 고려할 때 temperature가 switch on에서 desired temperature로 오르는 동안 power는 `3 * sustainable_power`에서 `sustainable_power`까지 선형으로 감소합니다.
k_po and k_pu
-------------
The implementation of the PID controller in the power allocator
thermal governor allows the configuration of two proportional term
constants: `k_po` and `k_pu`. `k_po` is the proportional term
constant during temperature overshoot periods (current temperature is
above "desired temperature" trip point). Conversely, `k_pu` is the
proportional term constant during temperature undershoot periods
(current temperature below "desired temperature" trip point).
These controls are intended as the primary mechanism for configuring
the permitted thermal "ramp" of the system. For instance, a lower
`k_pu` value will provide a slower ramp, at the cost of capping
available capacity at a low temperature. On the other hand, a high
value of `k_pu` will result in the governor granting very high power
while temperature is low, and may lead to temperature overshooting.
The default value for `k_pu` is::
2 * sustainable_power / (desired_temperature - switch_on_temp)
This means that at `switch_on_temp` the output of the controller's
proportional term will be 2 * `sustainable_power`. The default value
for `k_po` is::
sustainable_power / (desired_temperature - switch_on_temp)
Focusing on the proportional and feed forward values of the PID
controller equation we have::
P_max = k_p * e + sustainable_power
The proportional term is proportional to the difference between the
desired temperature and the current one. When the current temperature
is the desired one, then the proportional component is zero and
`P_max` = `sustainable_power`. That is, the system should operate in
thermal equilibrium under constant load. `sustainable_power` is only
an estimate, which is the reason for closed-loop control such as this.
Expanding `k_pu` we get::
P_max = 2 * sustainable_power * (T_set - T) / (T_set - T_on) +
sustainable_power
where:
- T_set is the desired temperature
- T is the current temperature
- T_on is the switch on temperature
When the current temperature is the switch_on temperature, the above
formula becomes::
P_max = 2 * sustainable_power * (T_set - T_on) / (T_set - T_on) +
sustainable_power = 2 * sustainable_power + sustainable_power =
3 * sustainable_power
Therefore, the proportional term alone linearly decreases power from
3 * `sustainable_power` to `sustainable_power` as the temperature
rises from the switch on temperature to the desired temperature.
k_i, integral_cutoff와 k_d
162-179`k_i`는 PID loop의 integral term constant입니다. Cooling device는 governor가 요청한 정확한 power를 설정하지 못하므로, integral term은 장기 drift와 output control의 양자화 특성을 보정합니다.
Temperature error가 `integral_cutoff`보다 작으면 error를 integral term에 누적합니다. 누적값에 `k_i`를 곱한 결과를 controller output에 더합니다. 보통 `k_i`는 1 또는 2처럼 낮게 설정하고 `integral_cutoff`는 0으로 둡니다.
`k_d`는 derivative term constant이며 기본값 0을 유지하는 것이 권장됩니다.
k_i and integral_cutoff
-----------------------
`k_i` configures the PID loop's integral term constant. This term
allows the PID controller to compensate for long term drift and for
the quantized nature of the output control: cooling devices can't set
the exact power that the governor requests. When the temperature
error is below `integral_cutoff`, errors are accumulated in the
integral term. This term is then multiplied by `k_i` and the result
added to the output of the controller. Typically `k_i` is set low (1
or 2) and `integral_cutoff` is 0.
k_d
---
`k_d` configures the PID loop's derivative term constant. It's
recommended to leave it as the default: 0.
Cooling device power API
180-244이 governor가 제어하는 cooling device는 `cooling_device_ops`에 추가 `power` API 세 개를 제공해야 합니다.
`get_requested_power(struct thermal_cooling_device *cdev, struct thermal_zone_device *tz, u32 *power)`는 device가 요청하는 power를 milliwatt 단위로 계산해 `@power`에 저장합니다. `@cdev`는 cooling device pointer이고 `@tz`는 현재 동작 중인 thermal zone입니다. 성공 시 0, 실패 시 `-E*`를 반환하며 governor가 각 cooling device에 얼마의 power를 줄지 계산할 때 사용합니다.
`state2power(struct thermal_cooling_device *cdev, struct thermal_zone_device *tz, unsigned long state, u32 *power)`는 cooling device의 `@state`를 milliwatt power consumption으로 변환해 `@power`에 저장합니다. 성공 시 0, 실패 시 `-E*`를 반환하며 thermal core가 actor가 소비할 수 있는 maximum power를 계산할 때 사용합니다.
`power2state(struct thermal_cooling_device *cdev, u32 power, unsigned long *state)`는 device가 최대 `@power` mW를 소비하게 할 cooling state를 계산해 `@state`에 저장합니다. 성공 시 0, 실패 시 `-E*`를 반환합니다.
Thermal core는 power allocator가 설정한 power를 cooling device가 적용할 state로 바꾸기 위해 `power2state()`를 사용합니다. 변환은 바뀔 수 있는 외부 요인에 의존하므로 function으로 제공되며 현재 상황에서 가장 적절한 변환을 반환해야 합니다.
Cooling device power API
========================
Cooling devices controlled by this governor must supply the additional
"power" API in their `cooling_device_ops`. It consists on three ops:
1. ::
int get_requested_power(struct thermal_cooling_device *cdev,
struct thermal_zone_device *tz, u32 *power);
@cdev:
The `struct thermal_cooling_device` pointer
@tz:
thermal zone in which we are currently operating
@power:
pointer in which to store the calculated power
`get_requested_power()` calculates the power requested by the device
in milliwatts and stores it in @power . It should return 0 on
success, -E* on failure. This is currently used by the power
allocator governor to calculate how much power to give to each cooling
device.
2. ::
int state2power(struct thermal_cooling_device *cdev, struct
thermal_zone_device *tz, unsigned long state,
u32 *power);
@cdev:
The `struct thermal_cooling_device` pointer
@tz:
thermal zone in which we are currently operating
@state:
A cooling device state
@power:
pointer in which to store the equivalent power
Convert cooling device state @state into power consumption in
milliwatts and store it in @power. It should return 0 on success, -E*
on failure. This is currently used by thermal core to calculate the
maximum power that an actor can consume.
3. ::
int power2state(struct thermal_cooling_device *cdev, u32 power,
unsigned long *state);
@cdev:
The `struct thermal_cooling_device` pointer
@power:
power in milliwatts
@state:
pointer in which to store the resulting state
Calculate a cooling device state that would make the device consume at
most @power mW and store it in @state. It should return 0 on success,
-E* on failure. This is currently used by the thermal core to convert
a given power set by the power allocator governor to a state that the
cooling device can set. It is a function because this conversion may
depend on external factors that may change so this function should the
best conversion given "current circumstances".
Cooling device weight
245-262Weight는 cooling device 사이의 allocation에 bias를 주는 mechanism으로, 서로 다른 cooling device의 상대적인 power efficiency를 표현합니다. 높은 weight는 높은 power efficiency를 나타낼 수 있습니다.
Weight는 상대값이므로 모든 cooling device의 weight가 1이면 서로 동등하게 취급합니다. 같은 종류의 compute를 서로 다른 효율로 수행하는 두 processor 같은 heterogeneous system에서 특히 유용합니다.
Platform code가 `thermal_zone_device_register()`로 thermal zone을 등록하면 weight를 thermal zone의 `thermal_bind_parameters` 일부로 전달합니다. Device tree를 사용하면 `cooling-maps` node의 각 map에 `contribution` property로 전달합니다.
Cooling device weights
----------------------
Weights are a mechanism to bias the allocation among cooling
devices. They express the relative power efficiency of different
cooling devices. Higher weight can be used to express higher power
efficiency. Weighting is relative such that if each cooling device
has a weight of one they are considered equal. This is particularly
useful in heterogeneous systems where two cooling devices may perform
the same kind of compute, but with different efficiency. For example,
a system with two different types of processors.
If the thermal zone is registered using
`thermal_zone_device_register()` (i.e., platform code), then weights
are passed as part of the thermal zone's `thermal_bind_parameters`.
If the platform is registered using device tree, then they are passed
as the `contribution` property of each map in the `cooling-maps` node.
Power allocator governor의 제한
263-274Power allocator의 PID controller는 periodic tick이 있을 때 가장 잘 동작합니다.
Driver가 `thermal_zone_device_update()` 또는 governor의 `throttle()`을 반복적으로 호출하면 governor response가 좋지 않습니다. 정상 thermal framework tick보다 빠르게 호출하면 과잉 반응합니다.
이는 power allocator만의 문제는 아닙니다. Interrupt 등으로 step-wise governor의 `throttle()`을 정상 tick보다 빠르게 호출해도 같은 방식으로 잘못 동작합니다.
Limitations of the power allocator governor
===========================================
The power allocator governor's PID controller works best if there is a
periodic tick. If you have a driver that calls
`thermal_zone_device_update()` (or anything that ends up calling the
governor's `throttle()` function) repetitively, the governor response
won't be very good. Note that this is not particular to this
governor, step-wise will also misbehave if you call its throttle()
faster than the normal thermal framework tick (due to interrupts for
example) as it will overreact.
Energy Model의 power scale 요구사항
275-281Cooling device가 제공하는 power value의 scale은 일관되어야 합니다.
하나의 thermal zone에 속한 모든 cooling device는 power를 모두 milli-Watts 단위로 보고하거나, 모두 같은 `abstract scale`로 변환해 보고해야 합니다.
Energy Model requirements
=========================
Another important thing is the consistent scale of the power values
provided by the cooling devices. All of the cooling devices in a single
thermal zone should have power values reported either in milli-Watts
or scaled to the same 'abstract scale'.
요약·해설
power_allocator.rst:1-281Power allocator는 두 passive trip point 사이에서 PID loop로 thermal power budget을 계산합니다. `sustainable_power`와 P/I/D tunable을 platform 특성에 맞추고, 각 cooling device는 power와 state를 상호 변환하는 API와 일관된 power scale을 제공해야 합니다.