Commit 8b7b390f authored by Javi Merino's avatar Javi Merino Committed by Eduardo Valentin

thermal: power_allocator: relax the requirement of two passive trip points

The power allocator governor currently requires that the thermal zone
has at least two passive trip points.  If there aren't, the governor
refuses to bind to the thermal zone.

This commit relaxes that requirement.  Now the governor will bind to all
thermal zones regardless of how many trip points they have.

Cc: Zhang Rui <rui.zhang@intel.com>
Cc: Eduardo Valentin <edubezval@gmail.com>
Reviewed-by: default avatarDaniel Kurtz <djkurtz@chromium.org>
Signed-off-by: default avatarJavi Merino <javi.merino@arm.com>
Signed-off-by: default avatarEduardo Valentin <edubezval@gmail.com>
parent e055bb0f
...@@ -4,7 +4,7 @@ Power allocator governor tunables ...@@ -4,7 +4,7 @@ Power allocator governor tunables
Trip points Trip points
----------- -----------
The governor requires the following two passive trip points: The governor works optimally with the following two passive trip points:
1. "switch on" trip point: temperature above which the governor 1. "switch on" trip point: temperature above which the governor
control loop starts operating. This is the first passive trip control loop starts operating. This is the first passive trip
......
...@@ -24,6 +24,8 @@ ...@@ -24,6 +24,8 @@
#include "thermal_core.h" #include "thermal_core.h"
#define INVALID_TRIP -1
#define FRAC_BITS 10 #define FRAC_BITS 10
#define int_to_frac(x) ((x) << FRAC_BITS) #define int_to_frac(x) ((x) << FRAC_BITS)
#define frac_to_int(x) ((x) >> FRAC_BITS) #define frac_to_int(x) ((x) >> FRAC_BITS)
...@@ -61,6 +63,8 @@ static inline s64 div_frac(s64 x, s64 y) ...@@ -61,6 +63,8 @@ static inline s64 div_frac(s64 x, s64 y)
* Used to calculate the derivative term. * Used to calculate the derivative term.
* @trip_switch_on: first passive trip point of the thermal zone. The * @trip_switch_on: first passive trip point of the thermal zone. The
* governor switches on when this trip point is crossed. * governor switches on when this trip point is crossed.
* If the thermal zone only has one passive trip point,
* @trip_switch_on should be INVALID_TRIP.
* @trip_max_desired_temperature: last passive trip point of the thermal * @trip_max_desired_temperature: last passive trip point of the thermal
* zone. The temperature we are * zone. The temperature we are
* controlling for. * controlling for.
...@@ -432,43 +436,66 @@ static int allocate_power(struct thermal_zone_device *tz, ...@@ -432,43 +436,66 @@ static int allocate_power(struct thermal_zone_device *tz,
return ret; return ret;
} }
static int get_governor_trips(struct thermal_zone_device *tz, /**
* get_governor_trips() - get the number of the two trip points that are key for this governor
* @tz: thermal zone to operate on
* @params: pointer to private data for this governor
*
* The power allocator governor works optimally with two trips points:
* a "switch on" trip point and a "maximum desired temperature". These
* are defined as the first and last passive trip points.
*
* If there is only one trip point, then that's considered to be the
* "maximum desired temperature" trip point and the governor is always
* on. If there are no passive or active trip points, then the
* governor won't do anything. In fact, its throttle function
* won't be called at all.
*/
static void get_governor_trips(struct thermal_zone_device *tz,
struct power_allocator_params *params) struct power_allocator_params *params)
{ {
int i, ret, last_passive; int i, last_active, last_passive;
bool found_first_passive; bool found_first_passive;
found_first_passive = false; found_first_passive = false;
last_passive = -1; last_active = INVALID_TRIP;
ret = -EINVAL; last_passive = INVALID_TRIP;
for (i = 0; i < tz->trips; i++) { for (i = 0; i < tz->trips; i++) {
enum thermal_trip_type type; enum thermal_trip_type type;
int ret;
ret = tz->ops->get_trip_type(tz, i, &type); ret = tz->ops->get_trip_type(tz, i, &type);
if (ret) if (ret) {
return ret; dev_warn(&tz->device,
"Failed to get trip point %d type: %d\n", i,
ret);
continue;
}
if (!found_first_passive) {
if (type == THERMAL_TRIP_PASSIVE) { if (type == THERMAL_TRIP_PASSIVE) {
if (!found_first_passive) {
params->trip_switch_on = i; params->trip_switch_on = i;
found_first_passive = true; found_first_passive = true;
} } else {
} else if (type == THERMAL_TRIP_PASSIVE) {
last_passive = i; last_passive = i;
}
} else if (type == THERMAL_TRIP_ACTIVE) {
last_active = i;
} else { } else {
break; break;
} }
} }
if (last_passive != -1) { if (last_passive != INVALID_TRIP) {
params->trip_max_desired_temperature = last_passive; params->trip_max_desired_temperature = last_passive;
ret = 0; } else if (found_first_passive) {
params->trip_max_desired_temperature = params->trip_switch_on;
params->trip_switch_on = INVALID_TRIP;
} else { } else {
ret = -EINVAL; params->trip_switch_on = INVALID_TRIP;
params->trip_max_desired_temperature = last_active;
} }
return ret;
} }
static void reset_pid_controller(struct power_allocator_params *params) static void reset_pid_controller(struct power_allocator_params *params)
...@@ -497,11 +524,10 @@ static void allow_maximum_power(struct thermal_zone_device *tz) ...@@ -497,11 +524,10 @@ static void allow_maximum_power(struct thermal_zone_device *tz)
* power_allocator_bind() - bind the power_allocator governor to a thermal zone * power_allocator_bind() - bind the power_allocator governor to a thermal zone
* @tz: thermal zone to bind it to * @tz: thermal zone to bind it to
* *
* Check that the thermal zone is valid for this governor, that is, it * Initialize the PID controller parameters and bind it to the thermal
* has two thermal trips. If so, initialize the PID controller * zone.
* parameters and bind it to the thermal zone.
* *
* Return: 0 on success, -EINVAL if the trips were invalid or -ENOMEM * Return: 0 on success, -EINVAL if the thermal zone doesn't have tzp or -ENOMEM
* if we ran out of memory. * if we ran out of memory.
*/ */
static int power_allocator_bind(struct thermal_zone_device *tz) static int power_allocator_bind(struct thermal_zone_device *tz)
...@@ -520,30 +546,23 @@ static int power_allocator_bind(struct thermal_zone_device *tz) ...@@ -520,30 +546,23 @@ static int power_allocator_bind(struct thermal_zone_device *tz)
if (!tz->tzp->sustainable_power) if (!tz->tzp->sustainable_power)
dev_warn(&tz->device, "power_allocator: sustainable_power will be estimated\n"); dev_warn(&tz->device, "power_allocator: sustainable_power will be estimated\n");
ret = get_governor_trips(tz, params); get_governor_trips(tz, params);
if (ret) {
dev_err(&tz->device,
"thermal zone %s has wrong trip setup for power allocator\n",
tz->type);
goto free;
}
ret = tz->ops->get_trip_temp(tz, params->trip_max_desired_temperature, if (tz->trips > 0) {
ret = tz->ops->get_trip_temp(tz,
params->trip_max_desired_temperature,
&control_temp); &control_temp);
if (ret) if (!ret)
goto free;
estimate_pid_constants(tz, tz->tzp->sustainable_power, estimate_pid_constants(tz, tz->tzp->sustainable_power,
params->trip_switch_on, control_temp, false); params->trip_switch_on,
control_temp, false);
}
reset_pid_controller(params); reset_pid_controller(params);
tz->governor_data = params; tz->governor_data = params;
return 0; return 0;
free:
kfree(params);
return ret;
} }
static void power_allocator_unbind(struct thermal_zone_device *tz) static void power_allocator_unbind(struct thermal_zone_device *tz)
...@@ -574,13 +593,7 @@ static int power_allocator_throttle(struct thermal_zone_device *tz, int trip) ...@@ -574,13 +593,7 @@ static int power_allocator_throttle(struct thermal_zone_device *tz, int trip)
ret = tz->ops->get_trip_temp(tz, params->trip_switch_on, ret = tz->ops->get_trip_temp(tz, params->trip_switch_on,
&switch_on_temp); &switch_on_temp);
if (ret) { if (!ret && (current_temp < switch_on_temp)) {
dev_warn(&tz->device,
"Failed to get switch on temperature: %d\n", ret);
return ret;
}
if (current_temp < switch_on_temp) {
tz->passive = 0; tz->passive = 0;
reset_pid_controller(params); reset_pid_controller(params);
allow_maximum_power(tz); allow_maximum_power(tz);
......
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