Commit 06d55c42 authored by Rafael J. Wysocki's avatar Rafael J. Wysocki
Browse files

Merge branch 'thermal-core'

Merge thermal core changes for v6.11:

 - Fix and clean up several minor shortcomings in thermal debug (Rafael
   Wysocki).

 - Rename __thermal_zone_set_trips() to thermal_zone_set_trips() and
   make it use trip thresholds (Rafael Wysocki).

 - Use READ_ONCE() for lockless access to trip temperature and
   hysteresis (Rafael Wysocki).

 - Drop unnecessary cooling device target state checks from the
   Bang-Bang thermal governor (Rafael Wysocki).

 - Avoid invoking thermal governor .trip_crossed() callback for critical
   and hot trip points (Rafael Wysocki).

* thermal-core:
  thermal: core: Avoid calling .trip_crossed() for critical and hot trips
  thermal: gov_bang_bang: Drop unnecessary cooling device target state checks
  thermal: trip: Use READ_ONCE() for lockless access to trip properties
  thermal: trip: Make thermal_zone_set_trips() use trip thresholds
  thermal: trip: Rename __thermal_zone_set_trips() to thermal_zone_set_trips()
  thermal: trip: Use common set of trip type names
  thermal/debugfs: Move some statements from under thermal_dbg->lock
  thermal/debugfs: Compute maximum temperature for mitigation episode as a whole
  thermal/debugfs: Adjust check for trips without statistics in tze_seq_show()
  thermal/debugfs: Fix up units in "mitigations" files
  thermal/debugfs: Print mitigation timestamp value in milliseconds
  thermal/debugfs: Do not extend mitigation episodes beyond system resume
  thermal/debugfs: Use helper to update trip point overstepping duration
parents 3995904d 72196c20
Loading
Loading
Loading
Loading
+3 −11
Original line number Diff line number Diff line
@@ -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);

+6 −2
Original line number Diff line number Diff line
@@ -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);

+3 −1
Original line number Diff line number Diff line
@@ -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,
+72 −38
Original line number Diff line number Diff line
@@ -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 @@ void thermal_debug_tz_trip_up(struct thermal_zone_device *tz,
	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);
}
+2 −0
Original line number Diff line number Diff line
@@ -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,
Loading