in gov_power_allocator.c [383:503]
static int allocate_power(struct thermal_zone_device *tz,
int control_temp)
{
struct thermal_instance *instance;
struct power_allocator_params *params = tz->governor_data;
u32 *req_power, *max_power, *granted_power, *extra_actor_power;
u32 *weighted_req_power;
u32 total_req_power, max_allocatable_power, total_weighted_req_power;
u32 total_granted_power, power_range;
int i, num_actors, total_weight, ret = 0;
int trip_max_desired_temperature = params->trip_max_desired_temperature;
mutex_lock(&tz->lock);
num_actors = 0;
total_weight = 0;
list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
if ((instance->trip == trip_max_desired_temperature) &&
cdev_is_power_actor(instance->cdev)) {
num_actors++;
total_weight += instance->weight;
}
}
if (!num_actors) {
ret = -ENODEV;
goto unlock;
}
/*
* We need to allocate five arrays of the same size:
* req_power, max_power, granted_power, extra_actor_power and
* weighted_req_power. They are going to be needed until this
* function returns. Allocate them all in one go to simplify
* the allocation and deallocation logic.
*/
BUILD_BUG_ON(sizeof(*req_power) != sizeof(*max_power));
BUILD_BUG_ON(sizeof(*req_power) != sizeof(*granted_power));
BUILD_BUG_ON(sizeof(*req_power) != sizeof(*extra_actor_power));
BUILD_BUG_ON(sizeof(*req_power) != sizeof(*weighted_req_power));
req_power = kcalloc(num_actors * 5, sizeof(*req_power), GFP_KERNEL);
if (!req_power) {
ret = -ENOMEM;
goto unlock;
}
max_power = &req_power[num_actors];
granted_power = &req_power[2 * num_actors];
extra_actor_power = &req_power[3 * num_actors];
weighted_req_power = &req_power[4 * num_actors];
i = 0;
total_weighted_req_power = 0;
total_req_power = 0;
max_allocatable_power = 0;
list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
int weight;
struct thermal_cooling_device *cdev = instance->cdev;
if (instance->trip != trip_max_desired_temperature)
continue;
if (!cdev_is_power_actor(cdev))
continue;
if (cdev->ops->get_requested_power(cdev, &req_power[i]))
continue;
if (!total_weight)
weight = 1 << FRAC_BITS;
else
weight = instance->weight;
weighted_req_power[i] = frac_to_int(weight * req_power[i]);
if (cdev->ops->state2power(cdev, instance->lower,
&max_power[i]))
continue;
total_req_power += req_power[i];
max_allocatable_power += max_power[i];
total_weighted_req_power += weighted_req_power[i];
i++;
}
power_range = pid_controller(tz, control_temp, max_allocatable_power);
divvy_up_power(weighted_req_power, max_power, num_actors,
total_weighted_req_power, power_range, granted_power,
extra_actor_power);
total_granted_power = 0;
i = 0;
list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
if (instance->trip != trip_max_desired_temperature)
continue;
if (!cdev_is_power_actor(instance->cdev))
continue;
power_actor_set_power(instance->cdev, instance,
granted_power[i]);
total_granted_power += granted_power[i];
i++;
}
trace_thermal_power_allocator(tz, req_power, total_req_power,
granted_power, total_granted_power,
num_actors, power_range,
max_allocatable_power, tz->temperature,
control_temp - tz->temperature);
kfree(req_power);
unlock:
mutex_unlock(&tz->lock);
return ret;
}