1

Merge back thermal control material for v6.11.

This commit is contained in:
Rafael J. Wysocki 2024-06-27 21:22:15 +02:00
commit efde8bfdc1
7 changed files with 112 additions and 80 deletions

View File

@ -57,24 +57,16 @@ static void bang_bang_control(struct thermal_zone_device *tz,
if (instance->trip != trip)
continue;
if (instance->target == THERMAL_NO_TARGET)
instance->target = 0;
if (instance->target != 0 && instance->target != 1) {
if (instance->target != 0 && instance->target != 1 &&
instance->target != THERMAL_NO_TARGET)
pr_debug("Unexpected state %ld of thermal instance %s in bang-bang\n",
instance->target, instance->name);
instance->target = 1;
}
/*
* Enable the fan when the trip is crossed on the way up and
* disable it when the trip is crossed on the way down.
*/
if (instance->target == 0 && crossed_up)
instance->target = 1;
else if (instance->target == 1 && !crossed_up)
instance->target = 0;
instance->target = crossed_up;
dev_dbg(&instance->cdev->device, "target=%ld\n", instance->target);

View File

@ -463,6 +463,9 @@ static void thermal_governor_trip_crossed(struct thermal_governor *governor,
const struct thermal_trip *trip,
bool crossed_up)
{
if (trip->type == THERMAL_TRIP_HOT || trip->type == THERMAL_TRIP_CRITICAL)
return;
if (governor->trip_crossed)
governor->trip_crossed(tz, trip, crossed_up);
}
@ -513,13 +516,13 @@ void __thermal_zone_device_update(struct thermal_zone_device *tz,
if (tz->temperature == THERMAL_TEMP_INVALID)
return;
__thermal_zone_set_trips(tz);
tz->notify_event = event;
for_each_trip_desc(tz, td)
handle_thermal_trip(tz, td, &way_up_list, &way_down_list);
thermal_zone_set_trips(tz);
list_sort(&way_up_list, &way_up_list, thermal_trip_notify_cmp);
list_for_each_entry(td, &way_up_list, notify_list_node)
thermal_trip_crossed(tz, &td->trip, governor, true);
@ -1649,6 +1652,7 @@ static void thermal_zone_device_resume(struct work_struct *work)
tz->suspended = false;
thermal_debug_tz_resume(tz);
thermal_zone_device_init(tz);
__thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED);

View File

@ -244,7 +244,9 @@ void thermal_governor_update_tz(struct thermal_zone_device *tz,
#define trip_to_trip_desc(__trip) \
container_of(__trip, struct thermal_trip_desc, trip)
void __thermal_zone_set_trips(struct thermal_zone_device *tz);
const char *thermal_trip_type_name(enum thermal_trip_type trip_type);
void thermal_zone_set_trips(struct thermal_zone_device *tz);
int thermal_zone_trip_id(const struct thermal_zone_device *tz,
const struct thermal_trip *trip);
void thermal_zone_trip_updated(struct thermal_zone_device *tz,

View File

@ -94,7 +94,6 @@ struct cdev_record {
* @trip_temp: trip temperature at mitigation start
* @trip_hyst: trip hysteresis at mitigation start
* @count: the number of times the zone temperature was above the trip point
* @max: maximum recorded temperature above the trip point
* @min: minimum recorded temperature above the trip point
* @avg: average temperature above the trip point
*/
@ -104,7 +103,6 @@ struct trip_stats {
int trip_temp;
int trip_hyst;
int count;
int max;
int min;
int avg;
};
@ -122,12 +120,14 @@ struct trip_stats {
* @timestamp: first trip point crossed the way up
* @duration: total duration of the mitigation episode
* @node: a list element to be added to the list of tz events
* @max_temp: maximum zone temperature during this episode
* @trip_stats: per trip point statistics, flexible array
*/
struct tz_episode {
ktime_t timestamp;
ktime_t duration;
struct list_head node;
int max_temp;
struct trip_stats trip_stats[];
};
@ -561,10 +561,11 @@ static struct tz_episode *thermal_debugfs_tz_event_alloc(struct thermal_zone_dev
INIT_LIST_HEAD(&tze->node);
tze->timestamp = now;
tze->duration = KTIME_MIN;
tze->max_temp = INT_MIN;
for (i = 0; i < tz->num_trips; i++) {
tze->trip_stats[i].trip_temp = THERMAL_TEMP_INVALID;
tze->trip_stats[i].min = INT_MAX;
tze->trip_stats[i].max = INT_MIN;
}
return tze;
@ -573,20 +574,20 @@ static struct tz_episode *thermal_debugfs_tz_event_alloc(struct thermal_zone_dev
void thermal_debug_tz_trip_up(struct thermal_zone_device *tz,
const struct thermal_trip *trip)
{
struct tz_episode *tze;
struct tz_debugfs *tz_dbg;
struct thermal_debugfs *thermal_dbg = tz->debugfs;
int trip_id = thermal_zone_trip_id(tz, trip);
ktime_t now = ktime_get();
struct trip_stats *trip_stats;
struct tz_debugfs *tz_dbg;
struct tz_episode *tze;
if (!thermal_dbg)
return;
mutex_lock(&thermal_dbg->lock);
tz_dbg = &thermal_dbg->tz_dbg;
mutex_lock(&thermal_dbg->lock);
/*
* The mitigation is starting. A mitigation can contain
* several episodes where each of them is related to a
@ -653,23 +654,33 @@ unlock:
mutex_unlock(&thermal_dbg->lock);
}
static void tz_episode_close_trip(struct tz_episode *tze, int trip_id, ktime_t now)
{
struct trip_stats *trip_stats = &tze->trip_stats[trip_id];
ktime_t delta = ktime_sub(now, trip_stats->timestamp);
trip_stats->duration = ktime_add(delta, trip_stats->duration);
/* Mark the end of mitigation for this trip point. */
trip_stats->timestamp = KTIME_MAX;
}
void thermal_debug_tz_trip_down(struct thermal_zone_device *tz,
const struct thermal_trip *trip)
{
struct thermal_debugfs *thermal_dbg = tz->debugfs;
int trip_id = thermal_zone_trip_id(tz, trip);
ktime_t now = ktime_get();
struct tz_episode *tze;
struct tz_debugfs *tz_dbg;
ktime_t delta, now = ktime_get();
int trip_id = thermal_zone_trip_id(tz, trip);
int i;
if (!thermal_dbg)
return;
mutex_lock(&thermal_dbg->lock);
tz_dbg = &thermal_dbg->tz_dbg;
mutex_lock(&thermal_dbg->lock);
/*
* The temperature crosses the way down but there was not
* mitigation detected before. That may happen when the
@ -695,13 +706,7 @@ void thermal_debug_tz_trip_down(struct thermal_zone_device *tz,
tze = list_first_entry(&tz_dbg->tz_episodes, struct tz_episode, node);
delta = ktime_sub(now, tze->trip_stats[trip_id].timestamp);
tze->trip_stats[trip_id].duration =
ktime_add(delta, tze->trip_stats[trip_id].duration);
/* Mark the end of mitigation for this trip point. */
tze->trip_stats[trip_id].timestamp = KTIME_MAX;
tz_episode_close_trip(tze, trip_id, now);
/*
* This event closes the mitigation as we are crossing the
@ -724,20 +729,22 @@ void thermal_debug_update_trip_stats(struct thermal_zone_device *tz)
if (!thermal_dbg)
return;
mutex_lock(&thermal_dbg->lock);
tz_dbg = &thermal_dbg->tz_dbg;
mutex_lock(&thermal_dbg->lock);
if (!tz_dbg->nr_trips)
goto out;
tze = list_first_entry(&tz_dbg->tz_episodes, struct tz_episode, node);
if (tz->temperature > tze->max_temp)
tze->max_temp = tz->temperature;
for (i = 0; i < tz_dbg->nr_trips; i++) {
int trip_id = tz_dbg->trips_crossed[i];
struct trip_stats *trip_stats = &tze->trip_stats[trip_id];
trip_stats->max = max(trip_stats->max, tz->temperature);
trip_stats->min = min(trip_stats->min, tz->temperature);
trip_stats->avg += (tz->temperature - trip_stats->avg) /
++trip_stats->count;
@ -777,7 +784,6 @@ static int tze_seq_show(struct seq_file *s, void *v)
struct thermal_zone_device *tz = thermal_dbg->tz_dbg.tz;
struct thermal_trip_desc *td;
struct tz_episode *tze;
const char *type;
u64 duration_ms;
int trip_id;
char c;
@ -793,10 +799,10 @@ static int tze_seq_show(struct seq_file *s, void *v)
c = '=';
}
seq_printf(s, ",-Mitigation at %lluus, duration%c%llums\n",
ktime_to_us(tze->timestamp), c, duration_ms);
seq_printf(s, ",-Mitigation at %llums, duration%c%llums, max. temp=%dm°C\n",
ktime_to_ms(tze->timestamp), c, duration_ms, tze->max_temp);
seq_printf(s, "| trip | type | temp(°mC) | hyst(°mC) | duration | avg(°mC) | min(°mC) | max(°mC) |\n");
seq_printf(s, "| trip | type | temp(m°C) | hyst(m°C) | duration(ms) | avg(m°C) | min(m°C) |\n");
for_each_trip_desc(tz, td) {
const struct thermal_trip *trip = &td->trip;
@ -814,16 +820,9 @@ static int tze_seq_show(struct seq_file *s, void *v)
trip_stats = &tze->trip_stats[trip_id];
/* Skip trips without any stats. */
if (trip_stats->min > trip_stats->max)
if (trip_stats->trip_temp == THERMAL_TEMP_INVALID)
continue;
if (trip->type == THERMAL_TRIP_PASSIVE)
type = "passive";
else if (trip->type == THERMAL_TRIP_ACTIVE)
type = "active";
else
type = "hot";
if (trip_stats->timestamp != KTIME_MAX) {
/* Mitigation in progress. */
ktime_t delta = ktime_sub(ktime_get(),
@ -837,15 +836,14 @@ static int tze_seq_show(struct seq_file *s, void *v)
c = ' ';
}
seq_printf(s, "| %*d | %*s | %*d | %*d | %c%*lld | %*d | %*d | %*d |\n",
seq_printf(s, "| %*d | %*s | %*d | %*d | %c%*lld | %*d | %*d |\n",
4 , trip_id,
8, type,
8, thermal_trip_type_name(trip->type),
9, trip_stats->trip_temp,
9, trip_stats->trip_hyst,
c, 10, duration_ms,
c, 11, duration_ms,
9, trip_stats->avg,
9, trip_stats->min,
9, trip_stats->max);
9, trip_stats->min);
}
return 0;
@ -922,3 +920,39 @@ void thermal_debug_tz_remove(struct thermal_zone_device *tz)
thermal_debugfs_remove_id(thermal_dbg);
kfree(trips_crossed);
}
void thermal_debug_tz_resume(struct thermal_zone_device *tz)
{
struct thermal_debugfs *thermal_dbg = tz->debugfs;
ktime_t now = ktime_get();
struct tz_debugfs *tz_dbg;
struct tz_episode *tze;
int i;
if (!thermal_dbg)
return;
mutex_lock(&thermal_dbg->lock);
tz_dbg = &thermal_dbg->tz_dbg;
if (!tz_dbg->nr_trips)
goto out;
/*
* A mitigation episode was in progress before the preceding system
* suspend transition, so close it because the zone handling is starting
* over from scratch.
*/
tze = list_first_entry(&tz_dbg->tz_episodes, struct tz_episode, node);
for (i = 0; i < tz_dbg->nr_trips; i++)
tz_episode_close_trip(tze, tz_dbg->trips_crossed[i], now);
tze->duration = ktime_sub(now, tze->timestamp);
tz_dbg->nr_trips = 0;
out:
mutex_unlock(&thermal_dbg->lock);
}

View File

@ -7,6 +7,7 @@ void thermal_debug_cdev_remove(struct thermal_cooling_device *cdev);
void thermal_debug_cdev_state_update(const struct thermal_cooling_device *cdev, int state);
void thermal_debug_tz_add(struct thermal_zone_device *tz);
void thermal_debug_tz_remove(struct thermal_zone_device *tz);
void thermal_debug_tz_resume(struct thermal_zone_device *tz);
void thermal_debug_tz_trip_up(struct thermal_zone_device *tz,
const struct thermal_trip *trip);
void thermal_debug_tz_trip_down(struct thermal_zone_device *tz,
@ -20,6 +21,7 @@ static inline void thermal_debug_cdev_state_update(const struct thermal_cooling_
int state) {}
static inline void thermal_debug_tz_add(struct thermal_zone_device *tz) {}
static inline void thermal_debug_tz_remove(struct thermal_zone_device *tz) {}
static inline void thermal_debug_tz_resume(struct thermal_zone_device *tz) {}
static inline void thermal_debug_tz_trip_up(struct thermal_zone_device *tz,
const struct thermal_trip *trip) {};
static inline void thermal_debug_tz_trip_down(struct thermal_zone_device *tz,

View File

@ -88,18 +88,7 @@ trip_point_type_show(struct device *dev, struct device_attribute *attr,
if (sscanf(attr->attr.name, "trip_point_%d_type", &trip_id) != 1)
return -EINVAL;
switch (tz->trips[trip_id].trip.type) {
case THERMAL_TRIP_CRITICAL:
return sprintf(buf, "critical\n");
case THERMAL_TRIP_HOT:
return sprintf(buf, "hot\n");
case THERMAL_TRIP_PASSIVE:
return sprintf(buf, "passive\n");
case THERMAL_TRIP_ACTIVE:
return sprintf(buf, "active\n");
default:
return sprintf(buf, "unknown\n");
}
return sprintf(buf, "%s\n", thermal_trip_type_name(tz->trips[trip_id].trip.type));
}
static ssize_t
@ -150,7 +139,7 @@ trip_point_temp_show(struct device *dev, struct device_attribute *attr,
if (sscanf(attr->attr.name, "trip_point_%d_temp", &trip_id) != 1)
return -EINVAL;
return sprintf(buf, "%d\n", tz->trips[trip_id].trip.temperature);
return sprintf(buf, "%d\n", READ_ONCE(tz->trips[trip_id].trip.temperature));
}
static ssize_t
@ -174,7 +163,7 @@ trip_point_hyst_store(struct device *dev, struct device_attribute *attr,
trip = &tz->trips[trip_id].trip;
if (hyst != trip->hysteresis) {
trip->hysteresis = hyst;
WRITE_ONCE(trip->hysteresis, hyst);
thermal_zone_trip_updated(tz, trip);
}
@ -194,7 +183,7 @@ trip_point_hyst_show(struct device *dev, struct device_attribute *attr,
if (sscanf(attr->attr.name, "trip_point_%d_hyst", &trip_id) != 1)
return -EINVAL;
return sprintf(buf, "%d\n", tz->trips[trip_id].trip.hysteresis);
return sprintf(buf, "%d\n", READ_ONCE(tz->trips[trip_id].trip.hysteresis));
}
static ssize_t

View File

@ -9,6 +9,21 @@
*/
#include "thermal_core.h"
static const char *trip_type_names[] = {
[THERMAL_TRIP_ACTIVE] = "active",
[THERMAL_TRIP_PASSIVE] = "passive",
[THERMAL_TRIP_HOT] = "hot",
[THERMAL_TRIP_CRITICAL] = "critical",
};
const char *thermal_trip_type_name(enum thermal_trip_type trip_type)
{
if (trip_type < THERMAL_TRIP_ACTIVE || trip_type > THERMAL_TRIP_CRITICAL)
return "unknown";
return trip_type_names[trip_type];
}
int for_each_thermal_trip(struct thermal_zone_device *tz,
int (*cb)(struct thermal_trip *, void *),
void *data)
@ -47,7 +62,7 @@ int thermal_zone_get_num_trips(struct thermal_zone_device *tz)
EXPORT_SYMBOL_GPL(thermal_zone_get_num_trips);
/**
* __thermal_zone_set_trips - Computes the next trip points for the driver
* thermal_zone_set_trips - Computes the next trip points for the driver
* @tz: a pointer to a thermal zone device structure
*
* The function computes the next temperature boundaries by browsing
@ -61,7 +76,7 @@ EXPORT_SYMBOL_GPL(thermal_zone_get_num_trips);
*
* It does not return a value
*/
void __thermal_zone_set_trips(struct thermal_zone_device *tz)
void thermal_zone_set_trips(struct thermal_zone_device *tz)
{
const struct thermal_trip_desc *td;
int low = -INT_MAX, high = INT_MAX;
@ -73,17 +88,11 @@ void __thermal_zone_set_trips(struct thermal_zone_device *tz)
return;
for_each_trip_desc(tz, td) {
const struct thermal_trip *trip = &td->trip;
int trip_low;
if (td->threshold < tz->temperature && td->threshold > low)
low = td->threshold;
trip_low = trip->temperature - trip->hysteresis;
if (trip_low < tz->temperature && trip_low > low)
low = trip_low;
if (trip->temperature > tz->temperature &&
trip->temperature < high)
high = trip->temperature;
if (td->threshold > tz->temperature && td->threshold < high)
high = td->threshold;
}
/* No need to change trip points */
@ -152,7 +161,7 @@ void thermal_zone_set_trip_temp(struct thermal_zone_device *tz,
if (trip->temperature == temp)
return;
trip->temperature = temp;
WRITE_ONCE(trip->temperature, temp);
thermal_notify_tz_trip_change(tz, trip);
if (temp == THERMAL_TEMP_INVALID) {