Commit d045c46c authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull thermal control fixes from Rafael Wysocki:
 "These fix a possible NULL pointer dereference in a thermal governor,
  fix up the handling of thermal zones enabled before their temperature
  can be determined and fix list sorting during thermal zone temperature
  updates.

  Specifics:

   - Prevent the Power Allocator thermal governor from dereferencing a
     NULL pointer if it is bound to a tripless thermal zone (Nícolas
     Prado)

   - Prevent thermal zones enabled too early from staying effectively
     dormant forever because their temperature cannot be determined
     initially (Rafael Wysocki)

   - Fix list sorting during thermal zone temperature updates to ensure
     the proper ordering of trip crossing notifications (Rafael
     Wysocki)"

* tag 'thermal-6.10-rc8' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
  thermal: core: Fix list sorting in __thermal_zone_device_update()
  thermal: core: Call monitor_thermal_zone() if zone temperature is invalid
  thermal: gov_power_allocator: Return early in manage if trip_max is NULL
parents 367cbaad 94eacc1c
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -759,6 +759,9 @@ static void power_allocator_manage(struct thermal_zone_device *tz)
		return;
	}

	if (!params->trip_max)
		return;

	allocate_power(tz, params->trip_max->temperature);
	params->update_cdevs = true;
}
+8 −7
Original line number Diff line number Diff line
@@ -300,6 +300,8 @@ static void monitor_thermal_zone(struct thermal_zone_device *tz)
		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);
	else if (tz->temperature == THERMAL_TEMP_INVALID)
		thermal_zone_device_set_polling(tz, msecs_to_jiffies(THERMAL_RECHECK_DELAY_MS));
}

static struct thermal_governor *thermal_get_tz_governor(struct thermal_zone_device *tz)
@@ -482,16 +484,14 @@ static void thermal_trip_crossed(struct thermal_zone_device *tz,
	thermal_governor_trip_crossed(governor, tz, trip, crossed_up);
}

static int thermal_trip_notify_cmp(void *ascending, const struct list_head *a,
static int thermal_trip_notify_cmp(void *not_used, const struct list_head *a,
				   const struct list_head *b)
{
	struct thermal_trip_desc *tda = container_of(a, struct thermal_trip_desc,
						     notify_list_node);
	struct thermal_trip_desc *tdb = container_of(b, struct thermal_trip_desc,
						     notify_list_node);
	int ret = tdb->notify_temp - tda->notify_temp;

	return ascending ? ret : -ret;
	return tda->notify_temp - tdb->notify_temp;
}

void __thermal_zone_device_update(struct thermal_zone_device *tz,
@@ -511,7 +511,7 @@ void __thermal_zone_device_update(struct thermal_zone_device *tz,
	update_temperature(tz);

	if (tz->temperature == THERMAL_TEMP_INVALID)
		return;
		goto monitor;

	__thermal_zone_set_trips(tz);

@@ -520,12 +520,12 @@ void __thermal_zone_device_update(struct thermal_zone_device *tz,
	for_each_trip_desc(tz, td)
		handle_thermal_trip(tz, td, &way_up_list, &way_down_list);

	list_sort(&way_up_list, &way_up_list, thermal_trip_notify_cmp);
	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);

	list_sort(NULL, &way_down_list, thermal_trip_notify_cmp);
	list_for_each_entry(td, &way_down_list, notify_list_node)
	list_for_each_entry_reverse(td, &way_down_list, notify_list_node)
		thermal_trip_crossed(tz, &td->trip, governor, false);

	if (governor->manage)
@@ -533,6 +533,7 @@ void __thermal_zone_device_update(struct thermal_zone_device *tz,

	thermal_debug_update_trip_stats(tz);

monitor:
	monitor_thermal_zone(tz);
}

+6 −0
Original line number Diff line number Diff line
@@ -133,6 +133,12 @@ struct thermal_zone_device {
	struct thermal_trip_desc trips[] __counted_by(num_trips);
};

/*
 * Default delay after a failing thermal zone temperature check before
 * attempting to check it again.
 */
#define THERMAL_RECHECK_DELAY_MS	250

/* Default Thermal Governor */
#if defined(CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE)
#define DEFAULT_THERMAL_GOVERNOR       "step_wise"