summaryrefslogtreecommitdiff
path: root/drivers/thermal
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2024-09-09 18:18:49 +0200
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2024-09-09 18:18:49 +0200
commite3ee4ab0fd6ef257fc8b8d49166aef056d55c938 (patch)
tree11b3d1030621079b0869303d8b8ce35998386899 /drivers/thermal
parentf5c05974349c8e3d80e125b71bd80695807d8528 (diff)
parent54fccad63ec88924db828df6fc0648930bccf345 (diff)
Merge branch 'thermal-core'
Merge thermal core fixes and cleanups for 6.12: - Refuse to accept trip point temperature or hysteresis that would lead to an invalid threshold value when setting them via sysfs (Rafael Wysocki). - Adjust states of all uninitialized instances in the .manage() callback of the Bang-bang thermal governor (Rafael Wysocki). - Drop a couple of redundant checks along with the code depending on them from the thermal core (Rafael Wysocki). - Rearrange the thermal core to avoid redundant checks and simplify control flow in a couple of code paths (Rafael Wysocki). * thermal-core: thermal: core: Drop thermal_zone_device_is_enabled() thermal: core: Check passive delay in monitor_thermal_zone() thermal: core: Drop dead code from monitor_thermal_zone() thermal: core: Drop redundant lockdep_assert_held() thermal: gov_bang_bang: Adjust states of all uninitialized instances thermal: sysfs: Add sanity checks for trip temperature and hysteresis
Diffstat (limited to 'drivers/thermal')
-rw-r--r--drivers/thermal/gov_bang_bang.c14
-rw-r--r--drivers/thermal/thermal_core.c32
-rw-r--r--drivers/thermal/thermal_core.h3
-rw-r--r--drivers/thermal/thermal_sysfs.c52
4 files changed, 49 insertions, 52 deletions
diff --git a/drivers/thermal/gov_bang_bang.c b/drivers/thermal/gov_bang_bang.c
index daed67d19efb..863e7a4272e6 100644
--- a/drivers/thermal/gov_bang_bang.c
+++ b/drivers/thermal/gov_bang_bang.c
@@ -92,23 +92,21 @@ static void bang_bang_manage(struct thermal_zone_device *tz)
for_each_trip_desc(tz, td) {
const struct thermal_trip *trip = &td->trip;
+ bool turn_on;
- if (tz->temperature >= td->threshold ||
- trip->temperature == THERMAL_TEMP_INVALID ||
+ if (trip->temperature == THERMAL_TEMP_INVALID ||
trip->type == THERMAL_TRIP_CRITICAL ||
trip->type == THERMAL_TRIP_HOT)
continue;
/*
- * If the initial cooling device state is "on", but the zone
- * temperature is not above the trip point, the core will not
- * call bang_bang_control() until the zone temperature reaches
- * the trip point temperature which may be never. In those
- * cases, set the initial state of the cooling device to 0.
+ * Adjust the target states for uninitialized thermal instances
+ * to the thermal zone temperature and the trip point threshold.
*/
+ turn_on = tz->temperature >= td->threshold;
list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
if (!instance->initialized && instance->trip == trip)
- bang_bang_set_instance_target(instance, 0);
+ bang_bang_set_instance_target(instance, turn_on);
}
}
diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index 4187f207bce9..073d02e21352 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -323,11 +323,6 @@ static void thermal_zone_broken_disable(struct thermal_zone_device *tz)
static void thermal_zone_device_set_polling(struct thermal_zone_device *tz,
unsigned long delay)
{
- if (!delay) {
- cancel_delayed_work(&tz->poll_queue);
- return;
- }
-
if (delay > HZ)
delay = round_jiffies_relative(delay);
@@ -364,9 +359,7 @@ static void thermal_zone_recheck(struct thermal_zone_device *tz, int error)
static void monitor_thermal_zone(struct thermal_zone_device *tz)
{
- if (tz->mode != THERMAL_DEVICE_ENABLED)
- thermal_zone_device_set_polling(tz, 0);
- else if (tz->passive > 0)
+ if (tz->passive > 0 && tz->passive_delay_jiffies)
thermal_zone_device_set_polling(tz, tz->passive_delay_jiffies);
else if (tz->polling_delay_jiffies)
thermal_zone_device_set_polling(tz, tz->polling_delay_jiffies);
@@ -554,10 +547,7 @@ void __thermal_zone_device_update(struct thermal_zone_device *tz,
int low = -INT_MAX, high = INT_MAX;
int temp, ret;
- if (tz->suspended)
- return;
-
- if (!thermal_zone_device_is_enabled(tz))
+ if (tz->suspended || tz->mode != THERMAL_DEVICE_ENABLED)
return;
ret = __thermal_zone_get_temp(tz, &temp);
@@ -659,13 +649,6 @@ int thermal_zone_device_disable(struct thermal_zone_device *tz)
}
EXPORT_SYMBOL_GPL(thermal_zone_device_disable);
-int thermal_zone_device_is_enabled(struct thermal_zone_device *tz)
-{
- lockdep_assert_held(&tz->lock);
-
- return tz->mode == THERMAL_DEVICE_ENABLED;
-}
-
static bool thermal_zone_is_present(struct thermal_zone_device *tz)
{
return !list_empty(&tz->node);
@@ -891,8 +874,6 @@ static void thermal_unbind_cdev_from_trip(struct thermal_zone_device *tz,
{
struct thermal_instance *pos, *next;
- lockdep_assert_held(&tz->lock);
-
mutex_lock(&cdev->lock);
list_for_each_entry_safe(pos, next, &tz->thermal_instances, tz_node) {
if (pos->trip == trip && pos->cdev == cdev) {
@@ -1415,13 +1396,8 @@ thermal_zone_device_register_with_trips(const char *type,
if (num_trips > 0 && !trips)
return ERR_PTR(-EINVAL);
- if (polling_delay) {
- if (passive_delay > polling_delay)
- return ERR_PTR(-EINVAL);
-
- if (!passive_delay)
- passive_delay = polling_delay;
- }
+ if (polling_delay && passive_delay > polling_delay)
+ return ERR_PTR(-EINVAL);
if (!thermal_class)
return ERR_PTR(-ENODEV);
diff --git a/drivers/thermal/thermal_core.h b/drivers/thermal/thermal_core.h
index 9b19b614a1bc..50b858aa173a 100644
--- a/drivers/thermal/thermal_core.h
+++ b/drivers/thermal/thermal_core.h
@@ -284,7 +284,4 @@ thermal_cooling_device_stats_update(struct thermal_cooling_device *cdev,
unsigned long new_state) {}
#endif /* CONFIG_THERMAL_STATISTICS */
-/* device tree support */
-int thermal_zone_device_is_enabled(struct thermal_zone_device *tz);
-
#endif /* __THERMAL_CORE_H__ */
diff --git a/drivers/thermal/thermal_sysfs.c b/drivers/thermal/thermal_sysfs.c
index b740b60032ee..1838aa729bb5 100644
--- a/drivers/thermal/thermal_sysfs.c
+++ b/drivers/thermal/thermal_sysfs.c
@@ -53,7 +53,7 @@ mode_show(struct device *dev, struct device_attribute *attr, char *buf)
int enabled;
mutex_lock(&tz->lock);
- enabled = thermal_zone_device_is_enabled(tz);
+ enabled = tz->mode == THERMAL_DEVICE_ENABLED;
mutex_unlock(&tz->lock);
return sprintf(buf, "%s\n", enabled ? "enabled" : "disabled");
@@ -111,18 +111,26 @@ trip_point_temp_store(struct device *dev, struct device_attribute *attr,
mutex_lock(&tz->lock);
- if (temp != trip->temperature) {
- if (tz->ops.set_trip_temp) {
- ret = tz->ops.set_trip_temp(tz, trip, temp);
- if (ret)
- goto unlock;
- }
+ if (temp == trip->temperature)
+ goto unlock;
- thermal_zone_set_trip_temp(tz, trip, temp);
+ /* Arrange the condition to avoid integer overflows. */
+ if (temp != THERMAL_TEMP_INVALID &&
+ temp <= trip->hysteresis + THERMAL_TEMP_INVALID) {
+ ret = -EINVAL;
+ goto unlock;
+ }
- __thermal_zone_device_update(tz, THERMAL_TRIP_CHANGED);
+ if (tz->ops.set_trip_temp) {
+ ret = tz->ops.set_trip_temp(tz, trip, temp);
+ if (ret)
+ goto unlock;
}
+ thermal_zone_set_trip_temp(tz, trip, temp);
+
+ __thermal_zone_device_update(tz, THERMAL_TRIP_CHANGED);
+
unlock:
mutex_unlock(&tz->lock);
@@ -152,15 +160,33 @@ trip_point_hyst_store(struct device *dev, struct device_attribute *attr,
mutex_lock(&tz->lock);
- if (hyst != trip->hysteresis) {
- thermal_zone_set_trip_hyst(tz, trip, hyst);
+ if (hyst == trip->hysteresis)
+ goto unlock;
+
+ /*
+ * Allow the hysteresis to be updated when the temperature is invalid
+ * to allow user space to avoid having to adjust hysteresis after a
+ * valid temperature has been set, but in that case just change the
+ * value and do nothing else.
+ */
+ if (trip->temperature == THERMAL_TEMP_INVALID) {
+ WRITE_ONCE(trip->hysteresis, hyst);
+ goto unlock;
+ }
- __thermal_zone_device_update(tz, THERMAL_TRIP_CHANGED);
+ if (trip->temperature - hyst <= THERMAL_TEMP_INVALID) {
+ ret = -EINVAL;
+ goto unlock;
}
+ thermal_zone_set_trip_hyst(tz, trip, hyst);
+
+ __thermal_zone_device_update(tz, THERMAL_TRIP_CHANGED);
+
+unlock:
mutex_unlock(&tz->lock);
- return count;
+ return ret ? ret : count;
}
static ssize_t