Commit 042a3d80 authored by Rafael J. Wysocki's avatar Rafael J. Wysocki

thermal: core: Move passive polling management to the core

Passive polling is enabled by setting the 'passive' field in
struct thermal_zone_device to a positive value so long as the
'passive_delay_jiffies' field is greater than zero.  It causes
the thermal core to actively check the thermal zone temperature
periodically which in theory should be done after crossing a
passive trip point on the way up in order to allow governors to
react more rapidly to temperature changes and adjust mitigation
more precisely.

However, the 'passive' field in struct thermal_zone_device is currently
managed by governors which is quite problematic.  First of all, only
two governors, Step-Wise and Power Allocator, update that field at
all, so the other governors do not benefit from passive polling,
although in principle they should.  Moreover, if the zone governor is
changed from, say, Step-Wise to Fair-Share after 'passive' has been
incremented by the former, it is not going to be reset back to zero by
the latter even if the zone temperature falls down below all passive
trip points.

For this reason, make handle_thermal_trip() increment 'passive'
to enable passive polling for the given thermal zone whenever a
passive trip point is crossed on the way up and decrement it
whenever a passive trip point is crossed on the way down.  Also
remove the 'passive' field updates from governors and additionally
clear it in thermal_zone_device_init() to prevent passive polling
from being enabled after a system resume just beacuse it was enabled
before suspending the system.
Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
Reviewed-by: default avatarLukasz Luba <lukasz.luba@arm.com>
Tested-by: default avatarLukasz Luba <lukasz.luba@arm.com>
parent 202aa0d4
...@@ -66,6 +66,7 @@ struct power_actor { ...@@ -66,6 +66,7 @@ struct power_actor {
* struct power_allocator_params - parameters for the power allocator governor * struct power_allocator_params - parameters for the power allocator governor
* @allocated_tzp: whether we have allocated tzp for this thermal zone and * @allocated_tzp: whether we have allocated tzp for this thermal zone and
* it needs to be freed on unbind * it needs to be freed on unbind
* @update_cdevs: whether or not update cdevs on the next run
* @err_integral: accumulated error in the PID controller. * @err_integral: accumulated error in the PID controller.
* @prev_err: error in the previous iteration of the PID controller. * @prev_err: error in the previous iteration of the PID controller.
* Used to calculate the derivative term. * Used to calculate the derivative term.
...@@ -84,6 +85,7 @@ struct power_actor { ...@@ -84,6 +85,7 @@ struct power_actor {
*/ */
struct power_allocator_params { struct power_allocator_params {
bool allocated_tzp; bool allocated_tzp;
bool update_cdevs;
s64 err_integral; s64 err_integral;
s32 prev_err; s32 prev_err;
u32 sustainable_power; u32 sustainable_power;
...@@ -533,7 +535,7 @@ static void reset_pid_controller(struct power_allocator_params *params) ...@@ -533,7 +535,7 @@ static void reset_pid_controller(struct power_allocator_params *params)
params->prev_err = 0; params->prev_err = 0;
} }
static void allow_maximum_power(struct thermal_zone_device *tz, bool update) static void allow_maximum_power(struct thermal_zone_device *tz)
{ {
struct power_allocator_params *params = tz->governor_data; struct power_allocator_params *params = tz->governor_data;
struct thermal_cooling_device *cdev; struct thermal_cooling_device *cdev;
...@@ -555,7 +557,7 @@ static void allow_maximum_power(struct thermal_zone_device *tz, bool update) ...@@ -555,7 +557,7 @@ static void allow_maximum_power(struct thermal_zone_device *tz, bool update)
*/ */
cdev->ops->get_requested_power(cdev, &req_power); cdev->ops->get_requested_power(cdev, &req_power);
if (update) if (params->update_cdevs)
__thermal_cdev_update(cdev); __thermal_cdev_update(cdev);
mutex_unlock(&cdev->lock); mutex_unlock(&cdev->lock);
...@@ -752,13 +754,13 @@ static void power_allocator_manage(struct thermal_zone_device *tz) ...@@ -752,13 +754,13 @@ static void power_allocator_manage(struct thermal_zone_device *tz)
if (trip && tz->temperature < trip->temperature) { if (trip && tz->temperature < trip->temperature) {
reset_pid_controller(params); reset_pid_controller(params);
allow_maximum_power(tz, tz->passive); allow_maximum_power(tz);
tz->passive = 0; params->update_cdevs = false;
return; return;
} }
allocate_power(tz, params->trip_max->temperature); allocate_power(tz, params->trip_max->temperature);
tz->passive = 1; params->update_cdevs = true;
} }
static struct thermal_governor thermal_gov_power_allocator = { static struct thermal_governor thermal_gov_power_allocator = {
......
...@@ -93,16 +93,6 @@ static void thermal_zone_trip_update(struct thermal_zone_device *tz, ...@@ -93,16 +93,6 @@ static void thermal_zone_trip_update(struct thermal_zone_device *tz,
if (instance->initialized && old_target == instance->target) if (instance->initialized && old_target == instance->target)
continue; continue;
if (trip->type == THERMAL_TRIP_PASSIVE) {
/* If needed, update the status of passive polling. */
if (old_target == THERMAL_NO_TARGET &&
instance->target != THERMAL_NO_TARGET)
tz->passive++;
else if (old_target != THERMAL_NO_TARGET &&
instance->target == THERMAL_NO_TARGET)
tz->passive--;
}
instance->initialized = true; instance->initialized = true;
mutex_lock(&instance->cdev->lock); mutex_lock(&instance->cdev->lock);
......
...@@ -296,7 +296,7 @@ static void monitor_thermal_zone(struct thermal_zone_device *tz) ...@@ -296,7 +296,7 @@ static void monitor_thermal_zone(struct thermal_zone_device *tz)
{ {
if (tz->mode != THERMAL_DEVICE_ENABLED) if (tz->mode != THERMAL_DEVICE_ENABLED)
thermal_zone_device_set_polling(tz, 0); thermal_zone_device_set_polling(tz, 0);
else if (tz->passive) else if (tz->passive > 0)
thermal_zone_device_set_polling(tz, tz->passive_delay_jiffies); thermal_zone_device_set_polling(tz, tz->passive_delay_jiffies);
else if (tz->polling_delay_jiffies) else if (tz->polling_delay_jiffies)
thermal_zone_device_set_polling(tz, tz->polling_delay_jiffies); thermal_zone_device_set_polling(tz, tz->polling_delay_jiffies);
...@@ -389,6 +389,11 @@ static void handle_thermal_trip(struct thermal_zone_device *tz, ...@@ -389,6 +389,11 @@ static void handle_thermal_trip(struct thermal_zone_device *tz,
if (tz->temperature < trip->temperature - trip->hysteresis) { if (tz->temperature < trip->temperature - trip->hysteresis) {
list_add(&td->notify_list_node, way_down_list); list_add(&td->notify_list_node, way_down_list);
td->notify_temp = trip->temperature - trip->hysteresis; td->notify_temp = trip->temperature - trip->hysteresis;
if (trip->type == THERMAL_TRIP_PASSIVE) {
tz->passive--;
WARN_ON(tz->passive < 0);
}
} else { } else {
td->threshold -= trip->hysteresis; td->threshold -= trip->hysteresis;
} }
...@@ -402,8 +407,10 @@ static void handle_thermal_trip(struct thermal_zone_device *tz, ...@@ -402,8 +407,10 @@ static void handle_thermal_trip(struct thermal_zone_device *tz,
td->notify_temp = trip->temperature; td->notify_temp = trip->temperature;
td->threshold -= trip->hysteresis; td->threshold -= trip->hysteresis;
if (trip->type == THERMAL_TRIP_CRITICAL || if (trip->type == THERMAL_TRIP_PASSIVE)
trip->type == THERMAL_TRIP_HOT) tz->passive++;
else if (trip->type == THERMAL_TRIP_CRITICAL ||
trip->type == THERMAL_TRIP_HOT)
handle_critical_trips(tz, trip); handle_critical_trips(tz, trip);
} }
} }
...@@ -444,6 +451,7 @@ static void thermal_zone_device_init(struct thermal_zone_device *tz) ...@@ -444,6 +451,7 @@ static void thermal_zone_device_init(struct thermal_zone_device *tz)
INIT_DELAYED_WORK(&tz->poll_queue, thermal_zone_device_check); INIT_DELAYED_WORK(&tz->poll_queue, thermal_zone_device_check);
tz->temperature = THERMAL_TEMP_INVALID; tz->temperature = THERMAL_TEMP_INVALID;
tz->passive = 0;
tz->prev_low_trip = -INT_MAX; tz->prev_low_trip = -INT_MAX;
tz->prev_high_trip = INT_MAX; tz->prev_high_trip = INT_MAX;
list_for_each_entry(pos, &tz->thermal_instances, tz_node) list_for_each_entry(pos, &tz->thermal_instances, tz_node)
......
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