Commit 03d38806 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull thermal control fixes from Rafael Wysocki:
 "These fix the processing of DT thermal properties and the Power
  Allocator thermal governor:

   - Fix parsing cooling-maps in DT for trip points with more than one
     cooling device (Rafael Wysocki)

   - Fix granted_power computation in the Power Allocator thermal
     governor and make it update total_weight on configuration changes
     after the thermal zone has been registered (Yu-Che Cheng)"

* tag 'thermal-6.14-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
  thermal: gov_power_allocator: Update total_weight on bind and cdev updates
  thermal/of: Fix cdev lookup in thermal_of_should_bind()
  thermal: gov_power_allocator: Fix incorrect calculation in divvy_up_power()
parents 14ebe690 0cde378a
Loading
Loading
Loading
Loading
+23 −9
Original line number Diff line number Diff line
@@ -370,7 +370,7 @@ static void divvy_up_power(struct power_actor *power, int num_actors,

	for (i = 0; i < num_actors; i++) {
		struct power_actor *pa = &power[i];
		u64 req_range = (u64)pa->req_power * power_range;
		u64 req_range = (u64)pa->weighted_req_power * power_range;

		pa->granted_power = DIV_ROUND_CLOSEST_ULL(req_range,
							  total_req_power);
@@ -641,6 +641,22 @@ static int allocate_actors_buffer(struct power_allocator_params *params,
	return ret;
}

static void power_allocator_update_weight(struct power_allocator_params *params)
{
	const struct thermal_trip_desc *td;
	struct thermal_instance *instance;

	if (!params->trip_max)
		return;

	td = trip_to_trip_desc(params->trip_max);

	params->total_weight = 0;
	list_for_each_entry(instance, &td->thermal_instances, trip_node)
		if (power_actor_is_valid(instance))
			params->total_weight += instance->weight;
}

static void power_allocator_update_tz(struct thermal_zone_device *tz,
				      enum thermal_notify_event reason)
{
@@ -656,16 +672,12 @@ static void power_allocator_update_tz(struct thermal_zone_device *tz,
			if (power_actor_is_valid(instance))
				num_actors++;

		if (num_actors == params->num_actors)
			return;

		if (num_actors != params->num_actors)
			allocate_actors_buffer(params, num_actors);
		break;

		fallthrough;
	case THERMAL_INSTANCE_WEIGHT_CHANGED:
		params->total_weight = 0;
		list_for_each_entry(instance, &td->thermal_instances, trip_node)
			if (power_actor_is_valid(instance))
				params->total_weight += instance->weight;
		power_allocator_update_weight(params);
		break;
	default:
		break;
@@ -731,6 +743,8 @@ static int power_allocator_bind(struct thermal_zone_device *tz)

	tz->governor_data = params;

	power_allocator_update_weight(params);

	return 0;

free_params:
+29 −21
Original line number Diff line number Diff line
@@ -274,25 +274,11 @@ static bool thermal_of_get_cooling_spec(struct device_node *map_np, int index,
	return true;
}

static bool thermal_of_should_bind(struct thermal_zone_device *tz,
static bool thermal_of_cm_lookup(struct device_node *cm_np,
				 const struct thermal_trip *trip,
				 struct thermal_cooling_device *cdev,
				 struct cooling_spec *c)
{
	struct device_node *tz_np, *cm_np;
	bool result = false;

	tz_np = thermal_of_zone_get_by_name(tz);
	if (IS_ERR(tz_np)) {
		pr_err("Failed to get node tz by name\n");
		return false;
	}

	cm_np = of_get_child_by_name(tz_np, "cooling-maps");
	if (!cm_np)
		goto out;

	/* Look up the trip and the cdev in the cooling maps. */
	for_each_child_of_node_scoped(cm_np, child) {
		struct device_node *tr_np;
		int count, i;
@@ -302,19 +288,41 @@ static bool thermal_of_should_bind(struct thermal_zone_device *tz,
			continue;

		/* The trip has been found, look up the cdev. */
		count = of_count_phandle_with_args(child, "cooling-device", "#cooling-cells");
		count = of_count_phandle_with_args(child, "cooling-device",
						   "#cooling-cells");
		if (count <= 0)
			pr_err("Add a cooling_device property with at least one device\n");

		for (i = 0; i < count; i++) {
			result = thermal_of_get_cooling_spec(child, i, cdev, c);
			if (result)
				break;
			if (thermal_of_get_cooling_spec(child, i, cdev, c))
				return true;
		}
	}

	return false;
}

		break;
static bool thermal_of_should_bind(struct thermal_zone_device *tz,
				   const struct thermal_trip *trip,
				   struct thermal_cooling_device *cdev,
				   struct cooling_spec *c)
{
	struct device_node *tz_np, *cm_np;
	bool result = false;

	tz_np = thermal_of_zone_get_by_name(tz);
	if (IS_ERR(tz_np)) {
		pr_err("Failed to get node tz by name\n");
		return false;
	}

	cm_np = of_get_child_by_name(tz_np, "cooling-maps");
	if (!cm_np)
		goto out;

	/* Look up the trip and the cdev in the cooling maps. */
	result = thermal_of_cm_lookup(cm_np, trip, cdev, c);

	of_node_put(cm_np);
out:
	of_node_put(tz_np);