mirror of
https://github.com/torvalds/linux.git
synced 2024-11-13 23:51:39 +00:00
Merge back thermal control material for 6.11.
This commit is contained in:
commit
462be1c353
@ -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);
|
||||
|
||||
|
@ -465,6 +465,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)
|
||||
goto monitor;
|
||||
|
||||
__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(NULL, &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);
|
||||
@ -1650,6 +1653,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);
|
||||
|
||||
|
@ -250,7 +250,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,
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user