Skip to content

Commit 296c871

Browse files
committed
Merge tag 'thermal-6.11-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
Pull thermal control fix from Rafael Wysocki: "Fix a Bang-bang thermal governor issue causing it to fail to reset the state of cooling devices if they are 'on' to start with, but the thermal zone temperature is always below the corresponding trip point (Rafael Wysocki)" * tag 'thermal-6.11-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: thermal: gov_bang_bang: Use governor_data to reduce overhead thermal: gov_bang_bang: Add .manage() callback thermal: gov_bang_bang: Split bang_bang_control() thermal: gov_bang_bang: Call __thermal_cdev_update() directly
2 parents 64ab5e4 + 6e6f58a commit 296c871

File tree

3 files changed

+69
-18
lines changed

3 files changed

+69
-18
lines changed

drivers/thermal/gov_bang_bang.c

Lines changed: 66 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,28 @@
1313

1414
#include "thermal_core.h"
1515

16+
static void bang_bang_set_instance_target(struct thermal_instance *instance,
17+
unsigned int target)
18+
{
19+
if (instance->target != 0 && instance->target != 1 &&
20+
instance->target != THERMAL_NO_TARGET)
21+
pr_debug("Unexpected state %ld of thermal instance %s in bang-bang\n",
22+
instance->target, instance->name);
23+
24+
/*
25+
* Enable the fan when the trip is crossed on the way up and disable it
26+
* when the trip is crossed on the way down.
27+
*/
28+
instance->target = target;
29+
instance->initialized = true;
30+
31+
dev_dbg(&instance->cdev->device, "target=%ld\n", instance->target);
32+
33+
mutex_lock(&instance->cdev->lock);
34+
__thermal_cdev_update(instance->cdev);
35+
mutex_unlock(&instance->cdev->lock);
36+
}
37+
1638
/**
1739
* bang_bang_control - controls devices associated with the given zone
1840
* @tz: thermal_zone_device
@@ -54,33 +76,60 @@ static void bang_bang_control(struct thermal_zone_device *tz,
5476
tz->temperature, trip->hysteresis);
5577

5678
list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
57-
if (instance->trip != trip)
58-
continue;
79+
if (instance->trip == trip)
80+
bang_bang_set_instance_target(instance, crossed_up);
81+
}
82+
}
83+
84+
static void bang_bang_manage(struct thermal_zone_device *tz)
85+
{
86+
const struct thermal_trip_desc *td;
87+
struct thermal_instance *instance;
5988

60-
if (instance->target != 0 && instance->target != 1 &&
61-
instance->target != THERMAL_NO_TARGET)
62-
pr_debug("Unexpected state %ld of thermal instance %s in bang-bang\n",
63-
instance->target, instance->name);
89+
/* If the code below has run already, nothing needs to be done. */
90+
if (tz->governor_data)
91+
return;
6492

65-
/*
66-
* Enable the fan when the trip is crossed on the way up and
67-
* disable it when the trip is crossed on the way down.
68-
*/
69-
instance->target = crossed_up;
93+
for_each_trip_desc(tz, td) {
94+
const struct thermal_trip *trip = &td->trip;
7095

71-
dev_dbg(&instance->cdev->device, "target=%ld\n", instance->target);
96+
if (tz->temperature >= td->threshold ||
97+
trip->temperature == THERMAL_TEMP_INVALID ||
98+
trip->type == THERMAL_TRIP_CRITICAL ||
99+
trip->type == THERMAL_TRIP_HOT)
100+
continue;
72101

73-
mutex_lock(&instance->cdev->lock);
74-
instance->cdev->updated = false; /* cdev needs update */
75-
mutex_unlock(&instance->cdev->lock);
102+
/*
103+
* If the initial cooling device state is "on", but the zone
104+
* temperature is not above the trip point, the core will not
105+
* call bang_bang_control() until the zone temperature reaches
106+
* the trip point temperature which may be never. In those
107+
* cases, set the initial state of the cooling device to 0.
108+
*/
109+
list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
110+
if (!instance->initialized && instance->trip == trip)
111+
bang_bang_set_instance_target(instance, 0);
112+
}
76113
}
77114

78-
list_for_each_entry(instance, &tz->thermal_instances, tz_node)
79-
thermal_cdev_update(instance->cdev);
115+
tz->governor_data = (void *)true;
116+
}
117+
118+
static void bang_bang_update_tz(struct thermal_zone_device *tz,
119+
enum thermal_notify_event reason)
120+
{
121+
/*
122+
* Let bang_bang_manage() know that it needs to walk trips after binding
123+
* a new cdev and after system resume.
124+
*/
125+
if (reason == THERMAL_TZ_BIND_CDEV || reason == THERMAL_TZ_RESUME)
126+
tz->governor_data = NULL;
80127
}
81128

82129
static struct thermal_governor thermal_gov_bang_bang = {
83130
.name = "bang_bang",
84131
.trip_crossed = bang_bang_control,
132+
.manage = bang_bang_manage,
133+
.update_tz = bang_bang_update_tz,
85134
};
86135
THERMAL_GOVERNOR_DECLARE(thermal_gov_bang_bang);

drivers/thermal/thermal_core.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1728,7 +1728,8 @@ static void thermal_zone_device_resume(struct work_struct *work)
17281728

17291729
thermal_debug_tz_resume(tz);
17301730
thermal_zone_device_init(tz);
1731-
__thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED);
1731+
thermal_governor_update_tz(tz, THERMAL_TZ_RESUME);
1732+
__thermal_zone_device_update(tz, THERMAL_TZ_RESUME);
17321733

17331734
complete(&tz->resume);
17341735
tz->resuming = false;

include/linux/thermal.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ enum thermal_notify_event {
5555
THERMAL_TZ_BIND_CDEV, /* Cooling dev is bind to the thermal zone */
5656
THERMAL_TZ_UNBIND_CDEV, /* Cooling dev is unbind from the thermal zone */
5757
THERMAL_INSTANCE_WEIGHT_CHANGED, /* Thermal instance weight changed */
58+
THERMAL_TZ_RESUME, /* Thermal zone is resuming after system sleep */
5859
};
5960

6061
/**

0 commit comments

Comments
 (0)