Skip to content

Commit 9396b2a

Browse files
committed
Merge branch 'thermal-core'
This includes a major rework of thermal governors and part of the thermal core interacting with them as well as some fixes and cleanups of the thermal debug code: - Redesign the thermal governor interface to allow the governors to work in a more straightforward way. - Make thermal governors take the current trip point thresholds into account in their computations which allows trip hysteresis to be observed more accurately. - Clean up thermal governors. - Make the thermal core manage passive polling for thermal zones and remove passive polling management from thermal governors. - Improve the handling of cooling device states and thermal mitigation episodes in progress in the thermal debug code. - Avoid excessive updates of trip point statistics and clean up the printing of thermal mitigation episode information. * thermal-core: (27 commits) thermal: core: Move passive polling management to the core thermal: core: Do not call handle_thermal_trip() if zone temperature is invalid thermal: trip: Add missing empty code line thermal/debugfs: Avoid printing zero duration for mitigation events in progress thermal/debugfs: Pass cooling device state to thermal_debug_cdev_add() thermal/debugfs: Create records for cdev states as they get used thermal: core: Introduce thermal_governor_trip_crossed() thermal/debugfs: Make tze_seq_show() skip invalid trips and trips with no stats thermal/debugfs: Rename thermal_debug_update_temp() to thermal_debug_update_trip_stats() thermal/debugfs: Clean up thermal_debug_update_temp() thermal/debugfs: Avoid excessive updates of trip point statistics thermal: core: Relocate critical and hot trip handling thermal: core: Drop the .throttle() governor callback thermal: gov_user_space: Use .trip_crossed() instead of .throttle() thermal: gov_fair_share: Eliminate unnecessary integer divisions thermal: gov_fair_share: Use trip thresholds instead of trip temperatures thermal: gov_fair_share: Use .manage() callback instead of .throttle() thermal: gov_step_wise: Clean up thermal_zone_trip_update() thermal: gov_step_wise: Use trip thresholds instead of trip temperatures thermal: gov_step_wise: Use .manage() callback instead of .throttle() ...
2 parents 0021102 + 042a3d8 commit 9396b2a

File tree

10 files changed

+268
-216
lines changed

10 files changed

+268
-216
lines changed

drivers/thermal/gov_bang_bang.c

Lines changed: 38 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -13,60 +13,11 @@
1313

1414
#include "thermal_core.h"
1515

16-
static int thermal_zone_trip_update(struct thermal_zone_device *tz,
17-
const struct thermal_trip *trip)
18-
{
19-
int trip_index = thermal_zone_trip_id(tz, trip);
20-
struct thermal_instance *instance;
21-
22-
if (!trip->hysteresis)
23-
dev_info_once(&tz->device,
24-
"Zero hysteresis value for thermal zone %s\n", tz->type);
25-
26-
dev_dbg(&tz->device, "Trip%d[temp=%d]:temp=%d:hyst=%d\n",
27-
trip_index, trip->temperature, tz->temperature,
28-
trip->hysteresis);
29-
30-
list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
31-
if (instance->trip != trip)
32-
continue;
33-
34-
/* in case fan is in initial state, switch the fan off */
35-
if (instance->target == THERMAL_NO_TARGET)
36-
instance->target = 0;
37-
38-
/* in case fan is neither on nor off set the fan to active */
39-
if (instance->target != 0 && instance->target != 1) {
40-
pr_warn("Thermal instance %s controlled by bang-bang has unexpected state: %ld\n",
41-
instance->name, instance->target);
42-
instance->target = 1;
43-
}
44-
45-
/*
46-
* enable fan when temperature exceeds trip_temp and disable
47-
* the fan in case it falls below trip_temp minus hysteresis
48-
*/
49-
if (instance->target == 0 && tz->temperature >= trip->temperature)
50-
instance->target = 1;
51-
else if (instance->target == 1 &&
52-
tz->temperature < trip->temperature - trip->hysteresis)
53-
instance->target = 0;
54-
55-
dev_dbg(&instance->cdev->device, "target=%d\n",
56-
(int)instance->target);
57-
58-
mutex_lock(&instance->cdev->lock);
59-
instance->cdev->updated = false; /* cdev needs update */
60-
mutex_unlock(&instance->cdev->lock);
61-
}
62-
63-
return 0;
64-
}
65-
6616
/**
6717
* bang_bang_control - controls devices associated with the given zone
6818
* @tz: thermal_zone_device
6919
* @trip: the trip point
20+
* @crossed_up: whether or not the trip has been crossed on the way up
7021
*
7122
* Regulation Logic: a two point regulation, deliver cooling state depending
7223
* on the previous state shown in this diagram:
@@ -90,26 +41,54 @@ static int thermal_zone_trip_update(struct thermal_zone_device *tz,
9041
* (trip_temp - hyst) so that the fan gets turned off again.
9142
*
9243
*/
93-
static int bang_bang_control(struct thermal_zone_device *tz,
94-
const struct thermal_trip *trip)
44+
static void bang_bang_control(struct thermal_zone_device *tz,
45+
const struct thermal_trip *trip,
46+
bool crossed_up)
9547
{
9648
struct thermal_instance *instance;
97-
int ret;
9849

9950
lockdep_assert_held(&tz->lock);
10051

101-
ret = thermal_zone_trip_update(tz, trip);
102-
if (ret)
103-
return ret;
52+
dev_dbg(&tz->device, "Trip%d[temp=%d]:temp=%d:hyst=%d\n",
53+
thermal_zone_trip_id(tz, trip), trip->temperature,
54+
tz->temperature, trip->hysteresis);
55+
56+
list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
57+
if (instance->trip != trip)
58+
continue;
59+
60+
if (instance->target == THERMAL_NO_TARGET)
61+
instance->target = 0;
62+
63+
if (instance->target != 0 && instance->target != 1) {
64+
pr_debug("Unexpected state %ld of thermal instance %s in bang-bang\n",
65+
instance->target, instance->name);
66+
67+
instance->target = 1;
68+
}
69+
70+
/*
71+
* Enable the fan when the trip is crossed on the way up and
72+
* disable it when the trip is crossed on the way down.
73+
*/
74+
if (instance->target == 0 && crossed_up)
75+
instance->target = 1;
76+
else if (instance->target == 1 && !crossed_up)
77+
instance->target = 0;
78+
79+
dev_dbg(&instance->cdev->device, "target=%ld\n", instance->target);
80+
81+
mutex_lock(&instance->cdev->lock);
82+
instance->cdev->updated = false; /* cdev needs update */
83+
mutex_unlock(&instance->cdev->lock);
84+
}
10485

10586
list_for_each_entry(instance, &tz->thermal_instances, tz_node)
10687
thermal_cdev_update(instance->cdev);
107-
108-
return 0;
10988
}
11089

11190
static struct thermal_governor thermal_gov_bang_bang = {
11291
.name = "bang_bang",
113-
.throttle = bang_bang_control,
92+
.trip_crossed = bang_bang_control,
11493
};
11594
THERMAL_GOVERNOR_DECLARE(thermal_gov_bang_bang);

drivers/thermal/gov_fair_share.c

Lines changed: 46 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -17,100 +17,111 @@
1717

1818
static int get_trip_level(struct thermal_zone_device *tz)
1919
{
20-
const struct thermal_trip *level_trip = NULL;
20+
const struct thermal_trip_desc *level_td = NULL;
2121
const struct thermal_trip_desc *td;
2222
int trip_level = -1;
2323

2424
for_each_trip_desc(tz, td) {
25-
const struct thermal_trip *trip = &td->trip;
26-
27-
if (trip->temperature >= tz->temperature)
25+
if (td->threshold > tz->temperature)
2826
continue;
2927

3028
trip_level++;
3129

32-
if (!level_trip || trip->temperature > level_trip->temperature)
33-
level_trip = trip;
30+
if (!level_td || td->threshold > level_td->threshold)
31+
level_td = td;
3432
}
3533

3634
/* Bail out if the temperature is not greater than any trips. */
3735
if (trip_level < 0)
3836
return 0;
3937

40-
trace_thermal_zone_trip(tz, thermal_zone_trip_id(tz, level_trip),
41-
level_trip->type);
38+
trace_thermal_zone_trip(tz, thermal_zone_trip_id(tz, &level_td->trip),
39+
level_td->trip.type);
4240

4341
return trip_level;
4442
}
4543

46-
static long get_target_state(struct thermal_zone_device *tz,
47-
struct thermal_cooling_device *cdev, int percentage, int level)
48-
{
49-
return (long)(percentage * level * cdev->max_state) / (100 * tz->num_trips);
50-
}
51-
5244
/**
5345
* fair_share_throttle - throttles devices associated with the given zone
5446
* @tz: thermal_zone_device
5547
* @trip: trip point
48+
* @trip_level: number of trips crossed by the zone temperature
5649
*
5750
* Throttling Logic: This uses three parameters to calculate the new
5851
* throttle state of the cooling devices associated with the given zone.
5952
*
6053
* Parameters used for Throttling:
6154
* P1. max_state: Maximum throttle state exposed by the cooling device.
62-
* P2. percentage[i]/100:
55+
* P2. weight[i]/total_weight:
6356
* How 'effective' the 'i'th device is, in cooling the given zone.
64-
* P3. cur_trip_level/max_no_of_trips:
57+
* P3. trip_level/max_no_of_trips:
6558
* This describes the extent to which the devices should be throttled.
6659
* We do not want to throttle too much when we trip a lower temperature,
6760
* whereas the throttling is at full swing if we trip critical levels.
68-
* (Heavily assumes the trip points are in ascending order)
6961
* new_state of cooling device = P3 * P2 * P1
7062
*/
71-
static int fair_share_throttle(struct thermal_zone_device *tz,
72-
const struct thermal_trip *trip)
63+
static void fair_share_throttle(struct thermal_zone_device *tz,
64+
const struct thermal_trip *trip,
65+
int trip_level)
7366
{
7467
struct thermal_instance *instance;
7568
int total_weight = 0;
76-
int total_instance = 0;
77-
int cur_trip_level = get_trip_level(tz);
78-
79-
lockdep_assert_held(&tz->lock);
69+
int nr_instances = 0;
8070

8171
list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
8272
if (instance->trip != trip)
8373
continue;
8474

8575
total_weight += instance->weight;
86-
total_instance++;
76+
nr_instances++;
8777
}
8878

8979
list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
90-
int percentage;
9180
struct thermal_cooling_device *cdev = instance->cdev;
81+
u64 dividend;
82+
u32 divisor;
9283

9384
if (instance->trip != trip)
9485
continue;
9586

96-
if (!total_weight)
97-
percentage = 100 / total_instance;
98-
else
99-
percentage = (instance->weight * 100) / total_weight;
100-
101-
instance->target = get_target_state(tz, cdev, percentage,
102-
cur_trip_level);
87+
dividend = trip_level;
88+
dividend *= cdev->max_state;
89+
divisor = tz->num_trips;
90+
if (total_weight) {
91+
dividend *= instance->weight;
92+
divisor *= total_weight;
93+
} else {
94+
divisor *= nr_instances;
95+
}
96+
instance->target = div_u64(dividend, divisor);
10397

10498
mutex_lock(&cdev->lock);
10599
__thermal_cdev_update(cdev);
106100
mutex_unlock(&cdev->lock);
107101
}
102+
}
103+
104+
static void fair_share_manage(struct thermal_zone_device *tz)
105+
{
106+
int trip_level = get_trip_level(tz);
107+
const struct thermal_trip_desc *td;
108+
109+
lockdep_assert_held(&tz->lock);
110+
111+
for_each_trip_desc(tz, td) {
112+
const struct thermal_trip *trip = &td->trip;
108113

109-
return 0;
114+
if (trip->temperature == THERMAL_TEMP_INVALID ||
115+
trip->type == THERMAL_TRIP_CRITICAL ||
116+
trip->type == THERMAL_TRIP_HOT)
117+
continue;
118+
119+
fair_share_throttle(tz, trip, trip_level);
120+
}
110121
}
111122

112123
static struct thermal_governor thermal_gov_fair_share = {
113-
.name = "fair_share",
114-
.throttle = fair_share_throttle,
124+
.name = "fair_share",
125+
.manage = fair_share_manage,
115126
};
116127
THERMAL_GOVERNOR_DECLARE(thermal_gov_fair_share);

drivers/thermal/gov_power_allocator.c

Lines changed: 14 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ struct power_actor {
6666
* struct power_allocator_params - parameters for the power allocator governor
6767
* @allocated_tzp: whether we have allocated tzp for this thermal zone and
6868
* it needs to be freed on unbind
69+
* @update_cdevs: whether or not update cdevs on the next run
6970
* @err_integral: accumulated error in the PID controller.
7071
* @prev_err: error in the previous iteration of the PID controller.
7172
* Used to calculate the derivative term.
@@ -84,6 +85,7 @@ struct power_actor {
8485
*/
8586
struct power_allocator_params {
8687
bool allocated_tzp;
88+
bool update_cdevs;
8789
s64 err_integral;
8890
s32 prev_err;
8991
u32 sustainable_power;
@@ -395,7 +397,7 @@ static void divvy_up_power(struct power_actor *power, int num_actors,
395397
}
396398
}
397399

398-
static int allocate_power(struct thermal_zone_device *tz, int control_temp)
400+
static void allocate_power(struct thermal_zone_device *tz, int control_temp)
399401
{
400402
struct power_allocator_params *params = tz->governor_data;
401403
unsigned int num_actors = params->num_actors;
@@ -410,7 +412,7 @@ static int allocate_power(struct thermal_zone_device *tz, int control_temp)
410412
int i = 0, ret;
411413

412414
if (!num_actors)
413-
return -ENODEV;
415+
return;
414416

415417
/* Clean all buffers for new power estimations */
416418
memset(power, 0, params->buffer_size);
@@ -471,8 +473,6 @@ static int allocate_power(struct thermal_zone_device *tz, int control_temp)
471473
num_actors, power_range,
472474
max_allocatable_power, tz->temperature,
473475
control_temp - tz->temperature);
474-
475-
return 0;
476476
}
477477

478478
/**
@@ -535,7 +535,7 @@ static void reset_pid_controller(struct power_allocator_params *params)
535535
params->prev_err = 0;
536536
}
537537

538-
static void allow_maximum_power(struct thermal_zone_device *tz, bool update)
538+
static void allow_maximum_power(struct thermal_zone_device *tz)
539539
{
540540
struct power_allocator_params *params = tz->governor_data;
541541
struct thermal_cooling_device *cdev;
@@ -557,7 +557,7 @@ static void allow_maximum_power(struct thermal_zone_device *tz, bool update)
557557
*/
558558
cdev->ops->get_requested_power(cdev, &req_power);
559559

560-
if (update)
560+
if (params->update_cdevs)
561561
__thermal_cdev_update(cdev);
562562

563563
mutex_unlock(&cdev->lock);
@@ -745,40 +745,29 @@ static void power_allocator_unbind(struct thermal_zone_device *tz)
745745
tz->governor_data = NULL;
746746
}
747747

748-
static int power_allocator_throttle(struct thermal_zone_device *tz,
749-
const struct thermal_trip *trip)
748+
static void power_allocator_manage(struct thermal_zone_device *tz)
750749
{
751750
struct power_allocator_params *params = tz->governor_data;
752-
bool update;
751+
const struct thermal_trip *trip = params->trip_switch_on;
753752

754753
lockdep_assert_held(&tz->lock);
755754

756-
/*
757-
* We get called for every trip point but we only need to do
758-
* our calculations once
759-
*/
760-
if (trip != params->trip_max)
761-
return 0;
762-
763-
trip = params->trip_switch_on;
764755
if (trip && tz->temperature < trip->temperature) {
765-
update = tz->passive;
766-
tz->passive = 0;
767756
reset_pid_controller(params);
768-
allow_maximum_power(tz, update);
769-
return 0;
757+
allow_maximum_power(tz);
758+
params->update_cdevs = false;
759+
return;
770760
}
771761

772-
tz->passive = 1;
773-
774-
return allocate_power(tz, params->trip_max->temperature);
762+
allocate_power(tz, params->trip_max->temperature);
763+
params->update_cdevs = true;
775764
}
776765

777766
static struct thermal_governor thermal_gov_power_allocator = {
778767
.name = "power_allocator",
779768
.bind_to_tz = power_allocator_bind,
780769
.unbind_from_tz = power_allocator_unbind,
781-
.throttle = power_allocator_throttle,
770+
.manage = power_allocator_manage,
782771
.update_tz = power_allocator_update_tz,
783772
};
784773
THERMAL_GOVERNOR_DECLARE(thermal_gov_power_allocator);

0 commit comments

Comments
 (0)