Lines Matching +full:sustainable +full:- +full:power
1 // SPDX-License-Identifier: GPL-2.0
3 * A power allocator to manage temperature
9 #define pr_fmt(fmt) "Power allocator: " fmt
20 #define INVALID_TRIP -1
27 * mul_frac() - multiply two fixed-point numbers
31 * Return: the result of multiplying two fixed-point numbers. The
32 * result is also a fixed-point number.
40 * div_frac() - divide two fixed-point numbers
44 * Return: the result of dividing two fixed-point numbers. The
45 * result is also a fixed-point number.
53 * struct power_allocator_params - parameters for the power allocator governor
66 * @sustainable_power: Sustainable power (heat) that this thermal zone can
79 * estimate_sustainable_power() - Estimate the sustainable power of a thermal zone
84 * power of all the cooling devices as that gives a valid value that
93 struct power_allocator_params *params = tz->governor_data; in estimate_sustainable_power()
95 list_for_each_entry(instance, &tz->thermal_instances, tz_node) { in estimate_sustainable_power()
96 struct thermal_cooling_device *cdev = instance->cdev; in estimate_sustainable_power()
99 if (instance->trip != params->trip_max_desired_temperature) in estimate_sustainable_power()
105 if (cdev->ops->state2power(cdev, instance->upper, &min_power)) in estimate_sustainable_power()
115 * estimate_pid_constants() - Estimate the constants for the PID controller
117 * @sustainable_power: sustainable power for the thermal zone
119 * @control_temp: target temperature for the power allocator governor
133 ret = tz->ops->get_trip_temp(tz, trip_switch_on, &switch_on_temp); in estimate_pid_constants()
137 temperature_threshold = control_temp - switch_on_temp; in estimate_pid_constants()
149 tz->tzp->k_po = int_to_frac(sustainable_power) / in estimate_pid_constants()
152 tz->tzp->k_pu = int_to_frac(2 * sustainable_power) / in estimate_pid_constants()
155 k_i = tz->tzp->k_pu / 10; in estimate_pid_constants()
156 tz->tzp->k_i = k_i > 0 ? k_i : 1; in estimate_pid_constants()
165 * get_sustainable_power() - Get the right sustainable power
167 * @params: parameters for the power allocator governor
168 * @control_temp: target temperature for the power allocator governor
170 * This function is used for getting the proper sustainable power value based
181 if (!tz->tzp->sustainable_power) in get_sustainable_power()
184 sustainable_power = tz->tzp->sustainable_power; in get_sustainable_power()
187 if (sustainable_power != params->sustainable_power) { in get_sustainable_power()
189 params->trip_switch_on, control_temp); in get_sustainable_power()
192 tz->tzp->sustainable_power = sustainable_power; in get_sustainable_power()
193 params->sustainable_power = sustainable_power; in get_sustainable_power()
200 * pid_controller() - PID controller
203 * @max_allocatable_power: maximum allocatable power for this thermal zone
205 * This PID controller increases the available power budget so that the
207 * @control_temp and limits the power if it exceeds it. k_po is the
211 * accumulated error is only valid if the requested power will make
215 * Return: The power budget for the next period.
224 struct power_allocator_params *params = tz->governor_data; in pid_controller()
230 err = control_temp - tz->temperature; in pid_controller()
234 p = mul_frac(err < 0 ? tz->tzp->k_po : tz->tzp->k_pu, err); in pid_controller()
240 * the integral is limited to max power) in pid_controller()
242 i = mul_frac(tz->tzp->k_i, params->err_integral); in pid_controller()
244 if (err < int_to_frac(tz->tzp->integral_cutoff)) { in pid_controller()
245 s64 i_next = i + mul_frac(tz->tzp->k_i, err); in pid_controller()
249 params->err_integral += err; in pid_controller()
256 * We do err - prev_err, so with a positive k_d, a decreasing in pid_controller()
258 * power being applied, slowing down the controller) in pid_controller()
260 d = mul_frac(tz->tzp->k_d, err - params->prev_err); in pid_controller()
261 d = div_frac(d, jiffies_to_msecs(tz->passive_delay_jiffies)); in pid_controller()
262 params->prev_err = err; in pid_controller()
266 /* feed-forward the known sustainable dissipatable power */ in pid_controller()
272 frac_to_int(params->err_integral), in pid_controller()
280 * power_actor_set_power() - limit the maximum power a cooling device consumes
283 * @power: the power in milliwatts
285 * Set the cooling device to consume at most @power milliwatts. The limit is
286 * expected to be a cap at the maximum power consumption.
288 * Return: 0 on success, -EINVAL if the cooling device does not
289 * implement the power actor API or -E* for other failures.
293 struct thermal_instance *instance, u32 power) in power_actor_set_power() argument
298 ret = cdev->ops->power2state(cdev, power, &state); in power_actor_set_power()
302 instance->target = clamp_val(state, instance->lower, instance->upper); in power_actor_set_power()
303 mutex_lock(&cdev->lock); in power_actor_set_power()
305 mutex_unlock(&cdev->lock); in power_actor_set_power()
311 * divvy_up_power() - divvy the allocated power between the actors
312 * @req_power: each actor's requested power
313 * @max_power: each actor's maximum available power
316 * @power_range: total allocated power
317 * @granted_power: output array: each actor's granted power
319 * function as temporary storage of the extra power given
322 * This function divides the total allocated power (@power_range)
324 * share of the @power_range according to how much power it requested
326 * requests power, then it receives all the @power_range. If
330 * If any actor received more than their maximum power, then that
331 * surplus is re-divvied among the actors based on how far they are
334 * Granted power for each actor is written to @granted_power, which
345 * Prevent division by 0 if none of the actors request power. in divvy_up_power()
359 extra_power += granted_power[i] - max_power[i]; in divvy_up_power()
363 extra_actor_power[i] = max_power[i] - granted_power[i]; in divvy_up_power()
371 * Re-divvy the reclaimed extra among actors based on in divvy_up_power()
387 struct power_allocator_params *params = tz->governor_data; in allocate_power()
393 int trip_max_desired_temperature = params->trip_max_desired_temperature; in allocate_power()
397 list_for_each_entry(instance, &tz->thermal_instances, tz_node) { in allocate_power()
398 if ((instance->trip == trip_max_desired_temperature) && in allocate_power()
399 cdev_is_power_actor(instance->cdev)) { in allocate_power()
401 total_weight += instance->weight; in allocate_power()
406 return -ENODEV; in allocate_power()
421 return -ENOMEM; in allocate_power()
433 list_for_each_entry(instance, &tz->thermal_instances, tz_node) { in allocate_power()
435 struct thermal_cooling_device *cdev = instance->cdev; in allocate_power()
437 if (instance->trip != trip_max_desired_temperature) in allocate_power()
443 if (cdev->ops->get_requested_power(cdev, &req_power[i])) in allocate_power()
449 weight = instance->weight; in allocate_power()
453 if (cdev->ops->state2power(cdev, instance->lower, in allocate_power()
472 list_for_each_entry(instance, &tz->thermal_instances, tz_node) { in allocate_power()
473 if (instance->trip != trip_max_desired_temperature) in allocate_power()
476 if (!cdev_is_power_actor(instance->cdev)) in allocate_power()
479 power_actor_set_power(instance->cdev, instance, in allocate_power()
489 max_allocatable_power, tz->temperature, in allocate_power()
490 control_temp - tz->temperature); in allocate_power()
498 * get_governor_trips() - get the number of the two trip points that are key for this governor
502 * The power allocator governor works optimally with two trips points:
522 for (i = 0; i < tz->num_trips; i++) { in get_governor_trips()
526 ret = tz->ops->get_trip_type(tz, i, &type); in get_governor_trips()
528 dev_warn(&tz->device, in get_governor_trips()
536 params->trip_switch_on = i; in get_governor_trips()
549 params->trip_max_desired_temperature = last_passive; in get_governor_trips()
551 params->trip_max_desired_temperature = params->trip_switch_on; in get_governor_trips()
552 params->trip_switch_on = INVALID_TRIP; in get_governor_trips()
554 params->trip_switch_on = INVALID_TRIP; in get_governor_trips()
555 params->trip_max_desired_temperature = last_active; in get_governor_trips()
561 params->err_integral = 0; in reset_pid_controller()
562 params->prev_err = 0; in reset_pid_controller()
568 struct power_allocator_params *params = tz->governor_data; in allow_maximum_power()
571 list_for_each_entry(instance, &tz->thermal_instances, tz_node) { in allow_maximum_power()
572 struct thermal_cooling_device *cdev = instance->cdev; in allow_maximum_power()
574 if ((instance->trip != params->trip_max_desired_temperature) || in allow_maximum_power()
575 (!cdev_is_power_actor(instance->cdev))) in allow_maximum_power()
578 instance->target = 0; in allow_maximum_power()
579 mutex_lock(&instance->cdev->lock); in allow_maximum_power()
585 cdev->ops->get_requested_power(cdev, &req_power); in allow_maximum_power()
588 __thermal_cdev_update(instance->cdev); in allow_maximum_power()
590 mutex_unlock(&instance->cdev->lock); in allow_maximum_power()
595 * check_power_actors() - Check all cooling devices and warn when they are
596 * not power actors
600 * power actor API. The warning should help to investigate the issue, which
603 * Return: 0 on success, -EINVAL if any cooling device does not implement
604 * the power actor API.
611 list_for_each_entry(instance, &tz->thermal_instances, tz_node) { in check_power_actors()
612 if (!cdev_is_power_actor(instance->cdev)) { in check_power_actors()
613 dev_warn(&tz->device, "power_allocator: %s is not a power actor\n", in check_power_actors()
614 instance->cdev->type); in check_power_actors()
615 ret = -EINVAL; in check_power_actors()
623 * power_allocator_bind() - bind the power_allocator governor to a thermal zone
629 * Return: 0 on success, or -ENOMEM if we ran out of memory, or -EINVAL
644 return -ENOMEM; in power_allocator_bind()
646 if (!tz->tzp) { in power_allocator_bind()
647 tz->tzp = kzalloc(sizeof(*tz->tzp), GFP_KERNEL); in power_allocator_bind()
648 if (!tz->tzp) { in power_allocator_bind()
649 ret = -ENOMEM; in power_allocator_bind()
653 params->allocated_tzp = true; in power_allocator_bind()
656 if (!tz->tzp->sustainable_power) in power_allocator_bind()
657 dev_warn(&tz->device, "power_allocator: sustainable_power will be estimated\n"); in power_allocator_bind()
661 if (tz->num_trips > 0) { in power_allocator_bind()
662 ret = tz->ops->get_trip_temp(tz, in power_allocator_bind()
663 params->trip_max_desired_temperature, in power_allocator_bind()
666 estimate_pid_constants(tz, tz->tzp->sustainable_power, in power_allocator_bind()
667 params->trip_switch_on, in power_allocator_bind()
673 tz->governor_data = params; in power_allocator_bind()
685 struct power_allocator_params *params = tz->governor_data; in power_allocator_unbind()
687 dev_dbg(&tz->device, "Unbinding from thermal zone %d\n", tz->id); in power_allocator_unbind()
689 if (params->allocated_tzp) { in power_allocator_unbind()
690 kfree(tz->tzp); in power_allocator_unbind()
691 tz->tzp = NULL; in power_allocator_unbind()
694 kfree(tz->governor_data); in power_allocator_unbind()
695 tz->governor_data = NULL; in power_allocator_unbind()
702 struct power_allocator_params *params = tz->governor_data; in power_allocator_throttle()
705 lockdep_assert_held(&tz->lock); in power_allocator_throttle()
711 if (trip != params->trip_max_desired_temperature) in power_allocator_throttle()
714 ret = tz->ops->get_trip_temp(tz, params->trip_switch_on, in power_allocator_throttle()
716 if (!ret && (tz->temperature < switch_on_temp)) { in power_allocator_throttle()
717 update = (tz->last_temperature >= switch_on_temp); in power_allocator_throttle()
718 tz->passive = 0; in power_allocator_throttle()
724 tz->passive = 1; in power_allocator_throttle()
726 ret = tz->ops->get_trip_temp(tz, params->trip_max_desired_temperature, in power_allocator_throttle()
729 dev_warn(&tz->device, in power_allocator_throttle()