Commit 6b775e87 authored by Javi Merino's avatar Javi Merino Committed by Eduardo Valentin

thermal: introduce the Power Allocator governor

The power allocator governor is a thermal governor that controls system
and device power allocation to control temperature.  Conceptually, the
implementation divides the sustainable power of a thermal zone among
all the heat sources in that zone.

This governor relies on "power actors", entities that represent heat
sources.  They can report current and maximum power consumption and
can set a given maximum power consumption, usually via a cooling

The governor uses a Proportional Integral Derivative (PID) controller
driven by the temperature of the thermal zone.  The output of the
controller is a power budget that is then allocated to each power
actor that can have bearing on the temperature we are trying to
control.  It decides how much power to give each cooling device based
on the performance they are requesting.  The PID controller ensures
that the total power budget does not exceed the control temperature.

Cc: Zhang Rui <>
Cc: Eduardo Valentin <>
Signed-off-by: default avatarPunit Agrawal <>
Signed-off-by: default avatarJavi Merino <>
Signed-off-by: default avatarEduardo Valentin <>
parent c36cf071
This diff is collapsed.
......@@ -71,6 +71,14 @@ config THERMAL_DEFAULT_GOV_USER_SPACE
Select this if you want to let the user space manage the
platform thermals.
bool "power_allocator"
Select this if you want to control temperature based on
system and device power allocation. This governor can only
operate on cooling devices that implement the power API.
......@@ -99,6 +107,13 @@ config THERMAL_GOV_USER_SPACE
Enable this to let the user space manage the platform thermals.
bool "Power allocator thermal governor"
Enable this to manage platform thermals by dynamically
allocating and limiting power to devices.
bool "generic cpu cooling support"
depends on CPU_FREQ
......@@ -14,6 +14,7 @@ thermal_sys-$(CONFIG_THERMAL_GOV_FAIR_SHARE) += fair_share.o
thermal_sys-$(CONFIG_THERMAL_GOV_BANG_BANG) += gov_bang_bang.o
thermal_sys-$(CONFIG_THERMAL_GOV_STEP_WISE) += step_wise.o
thermal_sys-$(CONFIG_THERMAL_GOV_USER_SPACE) += user_space.o
thermal_sys-$(CONFIG_THERMAL_GOV_POWER_ALLOCATOR) += power_allocator.o
# cpufreq cooling
thermal_sys-$(CONFIG_CPU_THERMAL) += cpu_cooling.o
This diff is collapsed.
......@@ -1616,7 +1616,7 @@ static void remove_trip_attrs(struct thermal_zone_device *tz)
struct thermal_zone_device *thermal_zone_device_register(const char *type,
int trips, int mask, void *devdata,
struct thermal_zone_device_ops *ops,
const struct thermal_zone_params *tzp,
struct thermal_zone_params *tzp,
int passive_delay, int polling_delay)
struct thermal_zone_device *tz;
......@@ -1968,7 +1968,11 @@ static int __init thermal_register_governors(void)
if (result)
return result;
return thermal_gov_user_space_register();
result = thermal_gov_user_space_register();
if (result)
return result;
return thermal_gov_power_allocator_register();
static void thermal_unregister_governors(void)
......@@ -1977,6 +1981,7 @@ static void thermal_unregister_governors(void)
static int __init thermal_init(void)
......@@ -88,6 +88,14 @@ static inline int thermal_gov_user_space_register(void) { return 0; }
static inline void thermal_gov_user_space_unregister(void) {}
int thermal_gov_power_allocator_register(void);
void thermal_gov_power_allocator_unregister(void);
static inline int thermal_gov_power_allocator_register(void) { return 0; }
static inline void thermal_gov_power_allocator_unregister(void) {}
/* device tree support */
int of_parse_thermal_zones(void);
......@@ -59,6 +59,8 @@
#define DEFAULT_THERMAL_GOVERNOR "fair_share"
#define DEFAULT_THERMAL_GOVERNOR "user_space"
#define DEFAULT_THERMAL_GOVERNOR "power_allocator"
struct thermal_zone_device;
......@@ -154,8 +156,7 @@ struct thermal_attr {
* @devdata: private pointer for device private data
* @trips: number of trip points the thermal zone supports
* @passive_delay: number of milliseconds to wait between polls when
* performing passive cooling. Currenty only used by the
* step-wise governor
* performing passive cooling.
* @polling_delay: number of milliseconds to wait between polls when
* checking whether trip points have been crossed (0 for
* interrupt driven systems)
......@@ -165,7 +166,6 @@ struct thermal_attr {
* @last_temperature: previous temperature read
* @emul_temperature: emulated temperature when using CONFIG_THERMAL_EMULATION
* @passive: 1 if you've crossed a passive trip point, 0 otherwise.
* Currenty only used by the step-wise governor.
* @forced_passive: If > 0, temperature at which to switch on all ACPI
* processor cooling devices. Currently only used by the
* step-wise governor.
......@@ -197,7 +197,7 @@ struct thermal_zone_device {
int passive;
unsigned int forced_passive;
struct thermal_zone_device_ops *ops;
const struct thermal_zone_params *tzp;
struct thermal_zone_params *tzp;
struct thermal_governor *governor;
void *governor_data;
struct list_head thermal_instances;
......@@ -275,6 +275,33 @@ struct thermal_zone_params {
int num_tbps; /* Number of tbp entries */
struct thermal_bind_params *tbp;
* Sustainable power (heat) that this thermal zone can dissipate in
* mW
u32 sustainable_power;
* Proportional parameter of the PID controller when
* overshooting (i.e., when temperature is below the target)
s32 k_po;
* Proportional parameter of the PID controller when
* undershooting
s32 k_pu;
/* Integral parameter of the PID controller */
s32 k_i;
/* Derivative parameter of the PID controller */
s32 k_d;
/* threshold below which the error is no longer accumulated */
s32 integral_cutoff;
struct thermal_genl_event {
......@@ -350,7 +377,7 @@ int power_actor_set_power(struct thermal_cooling_device *,
struct thermal_instance *, u32);
struct thermal_zone_device *thermal_zone_device_register(const char *, int, int,
void *, struct thermal_zone_device_ops *,
const struct thermal_zone_params *, int, int);
struct thermal_zone_params *, int, int);
void thermal_zone_device_unregister(struct thermal_zone_device *);
int thermal_zone_bind_cooling_device(struct thermal_zone_device *, int,
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment