xref: /OK3568_Linux_fs/kernel/drivers/thermal/gov_power_allocator.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * A power allocator to manage temperature
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Copyright (C) 2014 ARM Ltd.
6*4882a593Smuzhiyun  *
7*4882a593Smuzhiyun  */
8*4882a593Smuzhiyun 
9*4882a593Smuzhiyun #define pr_fmt(fmt) "Power allocator: " fmt
10*4882a593Smuzhiyun 
11*4882a593Smuzhiyun #include <linux/rculist.h>
12*4882a593Smuzhiyun #include <linux/slab.h>
13*4882a593Smuzhiyun #include <linux/thermal.h>
14*4882a593Smuzhiyun 
15*4882a593Smuzhiyun #define CREATE_TRACE_POINTS
16*4882a593Smuzhiyun #include <trace/events/thermal_power_allocator.h>
17*4882a593Smuzhiyun 
18*4882a593Smuzhiyun #include "thermal_core.h"
19*4882a593Smuzhiyun 
20*4882a593Smuzhiyun #define INVALID_TRIP -1
21*4882a593Smuzhiyun 
22*4882a593Smuzhiyun #define FRAC_BITS 10
23*4882a593Smuzhiyun #define int_to_frac(x) ((x) << FRAC_BITS)
24*4882a593Smuzhiyun #define frac_to_int(x) ((x) >> FRAC_BITS)
25*4882a593Smuzhiyun 
26*4882a593Smuzhiyun /**
27*4882a593Smuzhiyun  * mul_frac() - multiply two fixed-point numbers
28*4882a593Smuzhiyun  * @x:	first multiplicand
29*4882a593Smuzhiyun  * @y:	second multiplicand
30*4882a593Smuzhiyun  *
31*4882a593Smuzhiyun  * Return: the result of multiplying two fixed-point numbers.  The
32*4882a593Smuzhiyun  * result is also a fixed-point number.
33*4882a593Smuzhiyun  */
mul_frac(s64 x,s64 y)34*4882a593Smuzhiyun static inline s64 mul_frac(s64 x, s64 y)
35*4882a593Smuzhiyun {
36*4882a593Smuzhiyun 	return (x * y) >> FRAC_BITS;
37*4882a593Smuzhiyun }
38*4882a593Smuzhiyun 
39*4882a593Smuzhiyun /**
40*4882a593Smuzhiyun  * div_frac() - divide two fixed-point numbers
41*4882a593Smuzhiyun  * @x:	the dividend
42*4882a593Smuzhiyun  * @y:	the divisor
43*4882a593Smuzhiyun  *
44*4882a593Smuzhiyun  * Return: the result of dividing two fixed-point numbers.  The
45*4882a593Smuzhiyun  * result is also a fixed-point number.
46*4882a593Smuzhiyun  */
div_frac(s64 x,s64 y)47*4882a593Smuzhiyun static inline s64 div_frac(s64 x, s64 y)
48*4882a593Smuzhiyun {
49*4882a593Smuzhiyun 	return div_s64(x << FRAC_BITS, y);
50*4882a593Smuzhiyun }
51*4882a593Smuzhiyun 
52*4882a593Smuzhiyun /**
53*4882a593Smuzhiyun  * struct power_allocator_params - parameters for the power allocator governor
54*4882a593Smuzhiyun  * @allocated_tzp:	whether we have allocated tzp for this thermal zone and
55*4882a593Smuzhiyun  *			it needs to be freed on unbind
56*4882a593Smuzhiyun  * @err_integral:	accumulated error in the PID controller.
57*4882a593Smuzhiyun  * @prev_err:	error in the previous iteration of the PID controller.
58*4882a593Smuzhiyun  *		Used to calculate the derivative term.
59*4882a593Smuzhiyun  * @trip_switch_on:	first passive trip point of the thermal zone.  The
60*4882a593Smuzhiyun  *			governor switches on when this trip point is crossed.
61*4882a593Smuzhiyun  *			If the thermal zone only has one passive trip point,
62*4882a593Smuzhiyun  *			@trip_switch_on should be INVALID_TRIP.
63*4882a593Smuzhiyun  * @trip_max_desired_temperature:	last passive trip point of the thermal
64*4882a593Smuzhiyun  *					zone.  The temperature we are
65*4882a593Smuzhiyun  *					controlling for.
66*4882a593Smuzhiyun  */
67*4882a593Smuzhiyun struct power_allocator_params {
68*4882a593Smuzhiyun 	bool allocated_tzp;
69*4882a593Smuzhiyun 	s64 err_integral;
70*4882a593Smuzhiyun 	s32 prev_err;
71*4882a593Smuzhiyun 	int trip_switch_on;
72*4882a593Smuzhiyun 	int trip_max_desired_temperature;
73*4882a593Smuzhiyun };
74*4882a593Smuzhiyun 
75*4882a593Smuzhiyun /**
76*4882a593Smuzhiyun  * estimate_sustainable_power() - Estimate the sustainable power of a thermal zone
77*4882a593Smuzhiyun  * @tz: thermal zone we are operating in
78*4882a593Smuzhiyun  *
79*4882a593Smuzhiyun  * For thermal zones that don't provide a sustainable_power in their
80*4882a593Smuzhiyun  * thermal_zone_params, estimate one.  Calculate it using the minimum
81*4882a593Smuzhiyun  * power of all the cooling devices as that gives a valid value that
82*4882a593Smuzhiyun  * can give some degree of functionality.  For optimal performance of
83*4882a593Smuzhiyun  * this governor, provide a sustainable_power in the thermal zone's
84*4882a593Smuzhiyun  * thermal_zone_params.
85*4882a593Smuzhiyun  */
estimate_sustainable_power(struct thermal_zone_device * tz)86*4882a593Smuzhiyun static u32 estimate_sustainable_power(struct thermal_zone_device *tz)
87*4882a593Smuzhiyun {
88*4882a593Smuzhiyun 	u32 sustainable_power = 0;
89*4882a593Smuzhiyun 	struct thermal_instance *instance;
90*4882a593Smuzhiyun 	struct power_allocator_params *params = tz->governor_data;
91*4882a593Smuzhiyun 
92*4882a593Smuzhiyun 	list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
93*4882a593Smuzhiyun 		struct thermal_cooling_device *cdev = instance->cdev;
94*4882a593Smuzhiyun 		u32 min_power;
95*4882a593Smuzhiyun 
96*4882a593Smuzhiyun 		if (instance->trip != params->trip_max_desired_temperature)
97*4882a593Smuzhiyun 			continue;
98*4882a593Smuzhiyun 
99*4882a593Smuzhiyun 		if (power_actor_get_min_power(cdev, &min_power))
100*4882a593Smuzhiyun 			continue;
101*4882a593Smuzhiyun 
102*4882a593Smuzhiyun 		sustainable_power += min_power;
103*4882a593Smuzhiyun 	}
104*4882a593Smuzhiyun 
105*4882a593Smuzhiyun 	return sustainable_power;
106*4882a593Smuzhiyun }
107*4882a593Smuzhiyun 
108*4882a593Smuzhiyun /**
109*4882a593Smuzhiyun  * estimate_pid_constants() - Estimate the constants for the PID controller
110*4882a593Smuzhiyun  * @tz:		thermal zone for which to estimate the constants
111*4882a593Smuzhiyun  * @sustainable_power:	sustainable power for the thermal zone
112*4882a593Smuzhiyun  * @trip_switch_on:	trip point number for the switch on temperature
113*4882a593Smuzhiyun  * @control_temp:	target temperature for the power allocator governor
114*4882a593Smuzhiyun  * @force:	whether to force the update of the constants
115*4882a593Smuzhiyun  *
116*4882a593Smuzhiyun  * This function is used to update the estimation of the PID
117*4882a593Smuzhiyun  * controller constants in struct thermal_zone_parameters.
118*4882a593Smuzhiyun  * Sustainable power is provided in case it was estimated.  The
119*4882a593Smuzhiyun  * estimated sustainable_power should not be stored in the
120*4882a593Smuzhiyun  * thermal_zone_parameters so it has to be passed explicitly to this
121*4882a593Smuzhiyun  * function.
122*4882a593Smuzhiyun  *
123*4882a593Smuzhiyun  * If @force is not set, the values in the thermal zone's parameters
124*4882a593Smuzhiyun  * are preserved if they are not zero.  If @force is set, the values
125*4882a593Smuzhiyun  * in thermal zone's parameters are overwritten.
126*4882a593Smuzhiyun  */
estimate_pid_constants(struct thermal_zone_device * tz,u32 sustainable_power,int trip_switch_on,int control_temp,bool force)127*4882a593Smuzhiyun static void estimate_pid_constants(struct thermal_zone_device *tz,
128*4882a593Smuzhiyun 				   u32 sustainable_power, int trip_switch_on,
129*4882a593Smuzhiyun 				   int control_temp, bool force)
130*4882a593Smuzhiyun {
131*4882a593Smuzhiyun 	int ret;
132*4882a593Smuzhiyun 	int switch_on_temp;
133*4882a593Smuzhiyun 	u32 temperature_threshold;
134*4882a593Smuzhiyun 
135*4882a593Smuzhiyun 	ret = tz->ops->get_trip_temp(tz, trip_switch_on, &switch_on_temp);
136*4882a593Smuzhiyun 	if (ret)
137*4882a593Smuzhiyun 		switch_on_temp = 0;
138*4882a593Smuzhiyun 
139*4882a593Smuzhiyun 	temperature_threshold = control_temp - switch_on_temp;
140*4882a593Smuzhiyun 	/*
141*4882a593Smuzhiyun 	 * estimate_pid_constants() tries to find appropriate default
142*4882a593Smuzhiyun 	 * values for thermal zones that don't provide them. If a
143*4882a593Smuzhiyun 	 * system integrator has configured a thermal zone with two
144*4882a593Smuzhiyun 	 * passive trip points at the same temperature, that person
145*4882a593Smuzhiyun 	 * hasn't put any effort to set up the thermal zone properly
146*4882a593Smuzhiyun 	 * so just give up.
147*4882a593Smuzhiyun 	 */
148*4882a593Smuzhiyun 	if (!temperature_threshold)
149*4882a593Smuzhiyun 		return;
150*4882a593Smuzhiyun 
151*4882a593Smuzhiyun 	if (!tz->tzp->k_po || force)
152*4882a593Smuzhiyun 		tz->tzp->k_po = int_to_frac(sustainable_power) /
153*4882a593Smuzhiyun 			temperature_threshold;
154*4882a593Smuzhiyun 
155*4882a593Smuzhiyun 	if (!tz->tzp->k_pu || force)
156*4882a593Smuzhiyun 		tz->tzp->k_pu = int_to_frac(2 * sustainable_power) /
157*4882a593Smuzhiyun 			temperature_threshold;
158*4882a593Smuzhiyun 
159*4882a593Smuzhiyun 	if (!tz->tzp->k_i || force)
160*4882a593Smuzhiyun 		tz->tzp->k_i = int_to_frac(10) / 1000;
161*4882a593Smuzhiyun 	/*
162*4882a593Smuzhiyun 	 * The default for k_d and integral_cutoff is 0, so we can
163*4882a593Smuzhiyun 	 * leave them as they are.
164*4882a593Smuzhiyun 	 */
165*4882a593Smuzhiyun }
166*4882a593Smuzhiyun 
167*4882a593Smuzhiyun /**
168*4882a593Smuzhiyun  * pid_controller() - PID controller
169*4882a593Smuzhiyun  * @tz:	thermal zone we are operating in
170*4882a593Smuzhiyun  * @control_temp:	the target temperature in millicelsius
171*4882a593Smuzhiyun  * @max_allocatable_power:	maximum allocatable power for this thermal zone
172*4882a593Smuzhiyun  *
173*4882a593Smuzhiyun  * This PID controller increases the available power budget so that the
174*4882a593Smuzhiyun  * temperature of the thermal zone gets as close as possible to
175*4882a593Smuzhiyun  * @control_temp and limits the power if it exceeds it.  k_po is the
176*4882a593Smuzhiyun  * proportional term when we are overshooting, k_pu is the
177*4882a593Smuzhiyun  * proportional term when we are undershooting.  integral_cutoff is a
178*4882a593Smuzhiyun  * threshold below which we stop accumulating the error.  The
179*4882a593Smuzhiyun  * accumulated error is only valid if the requested power will make
180*4882a593Smuzhiyun  * the system warmer.  If the system is mostly idle, there's no point
181*4882a593Smuzhiyun  * in accumulating positive error.
182*4882a593Smuzhiyun  *
183*4882a593Smuzhiyun  * Return: The power budget for the next period.
184*4882a593Smuzhiyun  */
pid_controller(struct thermal_zone_device * tz,int control_temp,u32 max_allocatable_power)185*4882a593Smuzhiyun static u32 pid_controller(struct thermal_zone_device *tz,
186*4882a593Smuzhiyun 			  int control_temp,
187*4882a593Smuzhiyun 			  u32 max_allocatable_power)
188*4882a593Smuzhiyun {
189*4882a593Smuzhiyun 	s64 p, i, d, power_range;
190*4882a593Smuzhiyun 	s32 err, max_power_frac;
191*4882a593Smuzhiyun 	u32 sustainable_power;
192*4882a593Smuzhiyun 	struct power_allocator_params *params = tz->governor_data;
193*4882a593Smuzhiyun 
194*4882a593Smuzhiyun 	max_power_frac = int_to_frac(max_allocatable_power);
195*4882a593Smuzhiyun 
196*4882a593Smuzhiyun 	if (tz->tzp->sustainable_power) {
197*4882a593Smuzhiyun 		sustainable_power = tz->tzp->sustainable_power;
198*4882a593Smuzhiyun 	} else {
199*4882a593Smuzhiyun 		sustainable_power = estimate_sustainable_power(tz);
200*4882a593Smuzhiyun 		estimate_pid_constants(tz, sustainable_power,
201*4882a593Smuzhiyun 				       params->trip_switch_on, control_temp,
202*4882a593Smuzhiyun 				       true);
203*4882a593Smuzhiyun 	}
204*4882a593Smuzhiyun 
205*4882a593Smuzhiyun 	err = control_temp - tz->temperature;
206*4882a593Smuzhiyun 	err = int_to_frac(err);
207*4882a593Smuzhiyun 
208*4882a593Smuzhiyun 	/* Calculate the proportional term */
209*4882a593Smuzhiyun 	p = mul_frac(err < 0 ? tz->tzp->k_po : tz->tzp->k_pu, err);
210*4882a593Smuzhiyun 
211*4882a593Smuzhiyun 	/*
212*4882a593Smuzhiyun 	 * Calculate the integral term
213*4882a593Smuzhiyun 	 *
214*4882a593Smuzhiyun 	 * if the error is less than cut off allow integration (but
215*4882a593Smuzhiyun 	 * the integral is limited to max power)
216*4882a593Smuzhiyun 	 */
217*4882a593Smuzhiyun 	i = mul_frac(tz->tzp->k_i, params->err_integral);
218*4882a593Smuzhiyun 
219*4882a593Smuzhiyun 	if (err < int_to_frac(tz->tzp->integral_cutoff)) {
220*4882a593Smuzhiyun 		s64 i_next = i + mul_frac(tz->tzp->k_i, err);
221*4882a593Smuzhiyun 
222*4882a593Smuzhiyun 		if (abs(i_next) < max_power_frac) {
223*4882a593Smuzhiyun 			i = i_next;
224*4882a593Smuzhiyun 			params->err_integral += err;
225*4882a593Smuzhiyun 		}
226*4882a593Smuzhiyun 	}
227*4882a593Smuzhiyun 
228*4882a593Smuzhiyun 	/*
229*4882a593Smuzhiyun 	 * Calculate the derivative term
230*4882a593Smuzhiyun 	 *
231*4882a593Smuzhiyun 	 * We do err - prev_err, so with a positive k_d, a decreasing
232*4882a593Smuzhiyun 	 * error (i.e. driving closer to the line) results in less
233*4882a593Smuzhiyun 	 * power being applied, slowing down the controller)
234*4882a593Smuzhiyun 	 */
235*4882a593Smuzhiyun 	d = mul_frac(tz->tzp->k_d, err - params->prev_err);
236*4882a593Smuzhiyun 	d = div_frac(d, tz->passive_delay);
237*4882a593Smuzhiyun 	params->prev_err = err;
238*4882a593Smuzhiyun 
239*4882a593Smuzhiyun 	power_range = p + i + d;
240*4882a593Smuzhiyun 
241*4882a593Smuzhiyun 	/* feed-forward the known sustainable dissipatable power */
242*4882a593Smuzhiyun 	power_range = sustainable_power + frac_to_int(power_range);
243*4882a593Smuzhiyun 
244*4882a593Smuzhiyun 	power_range = clamp(power_range, (s64)0, (s64)max_allocatable_power);
245*4882a593Smuzhiyun 
246*4882a593Smuzhiyun 	trace_thermal_power_allocator_pid(tz, frac_to_int(err),
247*4882a593Smuzhiyun 					  frac_to_int(params->err_integral),
248*4882a593Smuzhiyun 					  frac_to_int(p), frac_to_int(i),
249*4882a593Smuzhiyun 					  frac_to_int(d), power_range);
250*4882a593Smuzhiyun 
251*4882a593Smuzhiyun 	return power_range;
252*4882a593Smuzhiyun }
253*4882a593Smuzhiyun 
254*4882a593Smuzhiyun /**
255*4882a593Smuzhiyun  * divvy_up_power() - divvy the allocated power between the actors
256*4882a593Smuzhiyun  * @req_power:	each actor's requested power
257*4882a593Smuzhiyun  * @max_power:	each actor's maximum available power
258*4882a593Smuzhiyun  * @num_actors:	size of the @req_power, @max_power and @granted_power's array
259*4882a593Smuzhiyun  * @total_req_power: sum of @req_power
260*4882a593Smuzhiyun  * @power_range:	total allocated power
261*4882a593Smuzhiyun  * @granted_power:	output array: each actor's granted power
262*4882a593Smuzhiyun  * @extra_actor_power:	an appropriately sized array to be used in the
263*4882a593Smuzhiyun  *			function as temporary storage of the extra power given
264*4882a593Smuzhiyun  *			to the actors
265*4882a593Smuzhiyun  *
266*4882a593Smuzhiyun  * This function divides the total allocated power (@power_range)
267*4882a593Smuzhiyun  * fairly between the actors.  It first tries to give each actor a
268*4882a593Smuzhiyun  * share of the @power_range according to how much power it requested
269*4882a593Smuzhiyun  * compared to the rest of the actors.  For example, if only one actor
270*4882a593Smuzhiyun  * requests power, then it receives all the @power_range.  If
271*4882a593Smuzhiyun  * three actors each requests 1mW, each receives a third of the
272*4882a593Smuzhiyun  * @power_range.
273*4882a593Smuzhiyun  *
274*4882a593Smuzhiyun  * If any actor received more than their maximum power, then that
275*4882a593Smuzhiyun  * surplus is re-divvied among the actors based on how far they are
276*4882a593Smuzhiyun  * from their respective maximums.
277*4882a593Smuzhiyun  *
278*4882a593Smuzhiyun  * Granted power for each actor is written to @granted_power, which
279*4882a593Smuzhiyun  * should've been allocated by the calling function.
280*4882a593Smuzhiyun  */
divvy_up_power(u32 * req_power,u32 * max_power,int num_actors,u32 total_req_power,u32 power_range,u32 * granted_power,u32 * extra_actor_power)281*4882a593Smuzhiyun static void divvy_up_power(u32 *req_power, u32 *max_power, int num_actors,
282*4882a593Smuzhiyun 			   u32 total_req_power, u32 power_range,
283*4882a593Smuzhiyun 			   u32 *granted_power, u32 *extra_actor_power)
284*4882a593Smuzhiyun {
285*4882a593Smuzhiyun 	u32 extra_power, capped_extra_power;
286*4882a593Smuzhiyun 	int i;
287*4882a593Smuzhiyun 
288*4882a593Smuzhiyun 	/*
289*4882a593Smuzhiyun 	 * Prevent division by 0 if none of the actors request power.
290*4882a593Smuzhiyun 	 */
291*4882a593Smuzhiyun 	if (!total_req_power)
292*4882a593Smuzhiyun 		total_req_power = 1;
293*4882a593Smuzhiyun 
294*4882a593Smuzhiyun 	capped_extra_power = 0;
295*4882a593Smuzhiyun 	extra_power = 0;
296*4882a593Smuzhiyun 	for (i = 0; i < num_actors; i++) {
297*4882a593Smuzhiyun 		u64 req_range = (u64)req_power[i] * power_range;
298*4882a593Smuzhiyun 
299*4882a593Smuzhiyun 		granted_power[i] = DIV_ROUND_CLOSEST_ULL(req_range,
300*4882a593Smuzhiyun 							 total_req_power);
301*4882a593Smuzhiyun 
302*4882a593Smuzhiyun 		if (granted_power[i] > max_power[i]) {
303*4882a593Smuzhiyun 			extra_power += granted_power[i] - max_power[i];
304*4882a593Smuzhiyun 			granted_power[i] = max_power[i];
305*4882a593Smuzhiyun 		}
306*4882a593Smuzhiyun 
307*4882a593Smuzhiyun 		extra_actor_power[i] = max_power[i] - granted_power[i];
308*4882a593Smuzhiyun 		capped_extra_power += extra_actor_power[i];
309*4882a593Smuzhiyun 	}
310*4882a593Smuzhiyun 
311*4882a593Smuzhiyun 	if (!extra_power)
312*4882a593Smuzhiyun 		return;
313*4882a593Smuzhiyun 
314*4882a593Smuzhiyun 	/*
315*4882a593Smuzhiyun 	 * Re-divvy the reclaimed extra among actors based on
316*4882a593Smuzhiyun 	 * how far they are from the max
317*4882a593Smuzhiyun 	 */
318*4882a593Smuzhiyun 	extra_power = min(extra_power, capped_extra_power);
319*4882a593Smuzhiyun 	if (capped_extra_power > 0)
320*4882a593Smuzhiyun 		for (i = 0; i < num_actors; i++)
321*4882a593Smuzhiyun 			granted_power[i] += (extra_actor_power[i] *
322*4882a593Smuzhiyun 					extra_power) / capped_extra_power;
323*4882a593Smuzhiyun }
324*4882a593Smuzhiyun 
allocate_power(struct thermal_zone_device * tz,int control_temp)325*4882a593Smuzhiyun static int allocate_power(struct thermal_zone_device *tz,
326*4882a593Smuzhiyun 			  int control_temp)
327*4882a593Smuzhiyun {
328*4882a593Smuzhiyun 	struct thermal_instance *instance;
329*4882a593Smuzhiyun 	struct power_allocator_params *params = tz->governor_data;
330*4882a593Smuzhiyun 	u32 *req_power, *max_power, *granted_power, *extra_actor_power;
331*4882a593Smuzhiyun 	u32 *weighted_req_power;
332*4882a593Smuzhiyun 	u32 total_req_power, max_allocatable_power, total_weighted_req_power;
333*4882a593Smuzhiyun 	u32 total_granted_power, power_range;
334*4882a593Smuzhiyun 	int i, num_actors, total_weight, ret = 0;
335*4882a593Smuzhiyun 	int trip_max_desired_temperature = params->trip_max_desired_temperature;
336*4882a593Smuzhiyun 
337*4882a593Smuzhiyun 	mutex_lock(&tz->lock);
338*4882a593Smuzhiyun 
339*4882a593Smuzhiyun 	num_actors = 0;
340*4882a593Smuzhiyun 	total_weight = 0;
341*4882a593Smuzhiyun 	list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
342*4882a593Smuzhiyun 		if ((instance->trip == trip_max_desired_temperature) &&
343*4882a593Smuzhiyun 		    cdev_is_power_actor(instance->cdev)) {
344*4882a593Smuzhiyun 			num_actors++;
345*4882a593Smuzhiyun 			total_weight += instance->weight;
346*4882a593Smuzhiyun 		}
347*4882a593Smuzhiyun 	}
348*4882a593Smuzhiyun 
349*4882a593Smuzhiyun 	if (!num_actors) {
350*4882a593Smuzhiyun 		ret = -ENODEV;
351*4882a593Smuzhiyun 		goto unlock;
352*4882a593Smuzhiyun 	}
353*4882a593Smuzhiyun 
354*4882a593Smuzhiyun 	/*
355*4882a593Smuzhiyun 	 * We need to allocate five arrays of the same size:
356*4882a593Smuzhiyun 	 * req_power, max_power, granted_power, extra_actor_power and
357*4882a593Smuzhiyun 	 * weighted_req_power.  They are going to be needed until this
358*4882a593Smuzhiyun 	 * function returns.  Allocate them all in one go to simplify
359*4882a593Smuzhiyun 	 * the allocation and deallocation logic.
360*4882a593Smuzhiyun 	 */
361*4882a593Smuzhiyun 	BUILD_BUG_ON(sizeof(*req_power) != sizeof(*max_power));
362*4882a593Smuzhiyun 	BUILD_BUG_ON(sizeof(*req_power) != sizeof(*granted_power));
363*4882a593Smuzhiyun 	BUILD_BUG_ON(sizeof(*req_power) != sizeof(*extra_actor_power));
364*4882a593Smuzhiyun 	BUILD_BUG_ON(sizeof(*req_power) != sizeof(*weighted_req_power));
365*4882a593Smuzhiyun 	req_power = kcalloc(num_actors * 5, sizeof(*req_power), GFP_KERNEL);
366*4882a593Smuzhiyun 	if (!req_power) {
367*4882a593Smuzhiyun 		ret = -ENOMEM;
368*4882a593Smuzhiyun 		goto unlock;
369*4882a593Smuzhiyun 	}
370*4882a593Smuzhiyun 
371*4882a593Smuzhiyun 	max_power = &req_power[num_actors];
372*4882a593Smuzhiyun 	granted_power = &req_power[2 * num_actors];
373*4882a593Smuzhiyun 	extra_actor_power = &req_power[3 * num_actors];
374*4882a593Smuzhiyun 	weighted_req_power = &req_power[4 * num_actors];
375*4882a593Smuzhiyun 
376*4882a593Smuzhiyun 	i = 0;
377*4882a593Smuzhiyun 	total_weighted_req_power = 0;
378*4882a593Smuzhiyun 	total_req_power = 0;
379*4882a593Smuzhiyun 	max_allocatable_power = 0;
380*4882a593Smuzhiyun 
381*4882a593Smuzhiyun 	list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
382*4882a593Smuzhiyun 		int weight;
383*4882a593Smuzhiyun 		struct thermal_cooling_device *cdev = instance->cdev;
384*4882a593Smuzhiyun 
385*4882a593Smuzhiyun 		if (instance->trip != trip_max_desired_temperature)
386*4882a593Smuzhiyun 			continue;
387*4882a593Smuzhiyun 
388*4882a593Smuzhiyun 		if (!cdev_is_power_actor(cdev))
389*4882a593Smuzhiyun 			continue;
390*4882a593Smuzhiyun 
391*4882a593Smuzhiyun 		if (cdev->ops->get_requested_power(cdev, &req_power[i]))
392*4882a593Smuzhiyun 			continue;
393*4882a593Smuzhiyun 
394*4882a593Smuzhiyun 		if (!total_weight)
395*4882a593Smuzhiyun 			weight = 1 << FRAC_BITS;
396*4882a593Smuzhiyun 		else
397*4882a593Smuzhiyun 			weight = instance->weight;
398*4882a593Smuzhiyun 
399*4882a593Smuzhiyun 		weighted_req_power[i] = frac_to_int(weight * req_power[i]);
400*4882a593Smuzhiyun 
401*4882a593Smuzhiyun 		if (power_actor_get_max_power(cdev, &max_power[i]))
402*4882a593Smuzhiyun 			continue;
403*4882a593Smuzhiyun 
404*4882a593Smuzhiyun 		total_req_power += req_power[i];
405*4882a593Smuzhiyun 		max_allocatable_power += max_power[i];
406*4882a593Smuzhiyun 		total_weighted_req_power += weighted_req_power[i];
407*4882a593Smuzhiyun 
408*4882a593Smuzhiyun 		i++;
409*4882a593Smuzhiyun 	}
410*4882a593Smuzhiyun 
411*4882a593Smuzhiyun 	power_range = pid_controller(tz, control_temp, max_allocatable_power);
412*4882a593Smuzhiyun 
413*4882a593Smuzhiyun 	divvy_up_power(weighted_req_power, max_power, num_actors,
414*4882a593Smuzhiyun 		       total_weighted_req_power, power_range, granted_power,
415*4882a593Smuzhiyun 		       extra_actor_power);
416*4882a593Smuzhiyun 
417*4882a593Smuzhiyun 	total_granted_power = 0;
418*4882a593Smuzhiyun 	i = 0;
419*4882a593Smuzhiyun 	list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
420*4882a593Smuzhiyun 		if (instance->trip != trip_max_desired_temperature)
421*4882a593Smuzhiyun 			continue;
422*4882a593Smuzhiyun 
423*4882a593Smuzhiyun 		if (!cdev_is_power_actor(instance->cdev))
424*4882a593Smuzhiyun 			continue;
425*4882a593Smuzhiyun 
426*4882a593Smuzhiyun 		power_actor_set_power(instance->cdev, instance,
427*4882a593Smuzhiyun 				      granted_power[i]);
428*4882a593Smuzhiyun 		total_granted_power += granted_power[i];
429*4882a593Smuzhiyun 
430*4882a593Smuzhiyun 		i++;
431*4882a593Smuzhiyun 	}
432*4882a593Smuzhiyun 
433*4882a593Smuzhiyun 	trace_thermal_power_allocator(tz, req_power, total_req_power,
434*4882a593Smuzhiyun 				      granted_power, total_granted_power,
435*4882a593Smuzhiyun 				      num_actors, power_range,
436*4882a593Smuzhiyun 				      max_allocatable_power, tz->temperature,
437*4882a593Smuzhiyun 				      control_temp - tz->temperature);
438*4882a593Smuzhiyun 
439*4882a593Smuzhiyun 	kfree(req_power);
440*4882a593Smuzhiyun unlock:
441*4882a593Smuzhiyun 	mutex_unlock(&tz->lock);
442*4882a593Smuzhiyun 
443*4882a593Smuzhiyun 	return ret;
444*4882a593Smuzhiyun }
445*4882a593Smuzhiyun 
446*4882a593Smuzhiyun /**
447*4882a593Smuzhiyun  * get_governor_trips() - get the number of the two trip points that are key for this governor
448*4882a593Smuzhiyun  * @tz:	thermal zone to operate on
449*4882a593Smuzhiyun  * @params:	pointer to private data for this governor
450*4882a593Smuzhiyun  *
451*4882a593Smuzhiyun  * The power allocator governor works optimally with two trips points:
452*4882a593Smuzhiyun  * a "switch on" trip point and a "maximum desired temperature".  These
453*4882a593Smuzhiyun  * are defined as the first and last passive trip points.
454*4882a593Smuzhiyun  *
455*4882a593Smuzhiyun  * If there is only one trip point, then that's considered to be the
456*4882a593Smuzhiyun  * "maximum desired temperature" trip point and the governor is always
457*4882a593Smuzhiyun  * on.  If there are no passive or active trip points, then the
458*4882a593Smuzhiyun  * governor won't do anything.  In fact, its throttle function
459*4882a593Smuzhiyun  * won't be called at all.
460*4882a593Smuzhiyun  */
get_governor_trips(struct thermal_zone_device * tz,struct power_allocator_params * params)461*4882a593Smuzhiyun static void get_governor_trips(struct thermal_zone_device *tz,
462*4882a593Smuzhiyun 			       struct power_allocator_params *params)
463*4882a593Smuzhiyun {
464*4882a593Smuzhiyun 	int i, last_active, last_passive;
465*4882a593Smuzhiyun 	bool found_first_passive;
466*4882a593Smuzhiyun 
467*4882a593Smuzhiyun 	found_first_passive = false;
468*4882a593Smuzhiyun 	last_active = INVALID_TRIP;
469*4882a593Smuzhiyun 	last_passive = INVALID_TRIP;
470*4882a593Smuzhiyun 
471*4882a593Smuzhiyun 	for (i = 0; i < tz->trips; i++) {
472*4882a593Smuzhiyun 		enum thermal_trip_type type;
473*4882a593Smuzhiyun 		int ret;
474*4882a593Smuzhiyun 
475*4882a593Smuzhiyun 		ret = tz->ops->get_trip_type(tz, i, &type);
476*4882a593Smuzhiyun 		if (ret) {
477*4882a593Smuzhiyun 			dev_warn(&tz->device,
478*4882a593Smuzhiyun 				 "Failed to get trip point %d type: %d\n", i,
479*4882a593Smuzhiyun 				 ret);
480*4882a593Smuzhiyun 			continue;
481*4882a593Smuzhiyun 		}
482*4882a593Smuzhiyun 
483*4882a593Smuzhiyun 		if (type == THERMAL_TRIP_PASSIVE) {
484*4882a593Smuzhiyun 			if (!found_first_passive) {
485*4882a593Smuzhiyun 				params->trip_switch_on = i;
486*4882a593Smuzhiyun 				found_first_passive = true;
487*4882a593Smuzhiyun 			} else  {
488*4882a593Smuzhiyun 				last_passive = i;
489*4882a593Smuzhiyun 			}
490*4882a593Smuzhiyun 		} else if (type == THERMAL_TRIP_ACTIVE) {
491*4882a593Smuzhiyun 			last_active = i;
492*4882a593Smuzhiyun 		} else {
493*4882a593Smuzhiyun 			break;
494*4882a593Smuzhiyun 		}
495*4882a593Smuzhiyun 	}
496*4882a593Smuzhiyun 
497*4882a593Smuzhiyun 	if (last_passive != INVALID_TRIP) {
498*4882a593Smuzhiyun 		params->trip_max_desired_temperature = last_passive;
499*4882a593Smuzhiyun 	} else if (found_first_passive) {
500*4882a593Smuzhiyun 		params->trip_max_desired_temperature = params->trip_switch_on;
501*4882a593Smuzhiyun 		params->trip_switch_on = INVALID_TRIP;
502*4882a593Smuzhiyun 	} else {
503*4882a593Smuzhiyun 		params->trip_switch_on = INVALID_TRIP;
504*4882a593Smuzhiyun 		params->trip_max_desired_temperature = last_active;
505*4882a593Smuzhiyun 	}
506*4882a593Smuzhiyun }
507*4882a593Smuzhiyun 
reset_pid_controller(struct power_allocator_params * params)508*4882a593Smuzhiyun static void reset_pid_controller(struct power_allocator_params *params)
509*4882a593Smuzhiyun {
510*4882a593Smuzhiyun 	params->err_integral = 0;
511*4882a593Smuzhiyun 	params->prev_err = 0;
512*4882a593Smuzhiyun }
513*4882a593Smuzhiyun 
allow_maximum_power(struct thermal_zone_device * tz)514*4882a593Smuzhiyun static void allow_maximum_power(struct thermal_zone_device *tz)
515*4882a593Smuzhiyun {
516*4882a593Smuzhiyun 	struct thermal_instance *instance;
517*4882a593Smuzhiyun 	struct power_allocator_params *params = tz->governor_data;
518*4882a593Smuzhiyun 
519*4882a593Smuzhiyun 	mutex_lock(&tz->lock);
520*4882a593Smuzhiyun 	list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
521*4882a593Smuzhiyun 		if ((instance->trip != params->trip_max_desired_temperature) ||
522*4882a593Smuzhiyun 		    (!cdev_is_power_actor(instance->cdev)))
523*4882a593Smuzhiyun 			continue;
524*4882a593Smuzhiyun 
525*4882a593Smuzhiyun 		instance->target = 0;
526*4882a593Smuzhiyun 		mutex_lock(&instance->cdev->lock);
527*4882a593Smuzhiyun 		instance->cdev->updated = false;
528*4882a593Smuzhiyun 		mutex_unlock(&instance->cdev->lock);
529*4882a593Smuzhiyun 		thermal_cdev_update(instance->cdev);
530*4882a593Smuzhiyun 	}
531*4882a593Smuzhiyun 	mutex_unlock(&tz->lock);
532*4882a593Smuzhiyun }
533*4882a593Smuzhiyun 
534*4882a593Smuzhiyun /**
535*4882a593Smuzhiyun  * power_allocator_bind() - bind the power_allocator governor to a thermal zone
536*4882a593Smuzhiyun  * @tz:	thermal zone to bind it to
537*4882a593Smuzhiyun  *
538*4882a593Smuzhiyun  * Initialize the PID controller parameters and bind it to the thermal
539*4882a593Smuzhiyun  * zone.
540*4882a593Smuzhiyun  *
541*4882a593Smuzhiyun  * Return: 0 on success, or -ENOMEM if we ran out of memory.
542*4882a593Smuzhiyun  */
power_allocator_bind(struct thermal_zone_device * tz)543*4882a593Smuzhiyun static int power_allocator_bind(struct thermal_zone_device *tz)
544*4882a593Smuzhiyun {
545*4882a593Smuzhiyun 	int ret;
546*4882a593Smuzhiyun 	struct power_allocator_params *params;
547*4882a593Smuzhiyun 	int control_temp;
548*4882a593Smuzhiyun 
549*4882a593Smuzhiyun 	params = kzalloc(sizeof(*params), GFP_KERNEL);
550*4882a593Smuzhiyun 	if (!params)
551*4882a593Smuzhiyun 		return -ENOMEM;
552*4882a593Smuzhiyun 
553*4882a593Smuzhiyun 	if (!tz->tzp) {
554*4882a593Smuzhiyun 		tz->tzp = kzalloc(sizeof(*tz->tzp), GFP_KERNEL);
555*4882a593Smuzhiyun 		if (!tz->tzp) {
556*4882a593Smuzhiyun 			ret = -ENOMEM;
557*4882a593Smuzhiyun 			goto free_params;
558*4882a593Smuzhiyun 		}
559*4882a593Smuzhiyun 
560*4882a593Smuzhiyun 		params->allocated_tzp = true;
561*4882a593Smuzhiyun 	}
562*4882a593Smuzhiyun 
563*4882a593Smuzhiyun 	if (!tz->tzp->sustainable_power)
564*4882a593Smuzhiyun 		dev_warn(&tz->device, "power_allocator: sustainable_power will be estimated\n");
565*4882a593Smuzhiyun 
566*4882a593Smuzhiyun 	get_governor_trips(tz, params);
567*4882a593Smuzhiyun 
568*4882a593Smuzhiyun 	if (tz->trips > 0) {
569*4882a593Smuzhiyun 		ret = tz->ops->get_trip_temp(tz,
570*4882a593Smuzhiyun 					params->trip_max_desired_temperature,
571*4882a593Smuzhiyun 					&control_temp);
572*4882a593Smuzhiyun 		if (!ret)
573*4882a593Smuzhiyun 			estimate_pid_constants(tz, tz->tzp->sustainable_power,
574*4882a593Smuzhiyun 					       params->trip_switch_on,
575*4882a593Smuzhiyun 					       control_temp, false);
576*4882a593Smuzhiyun 	}
577*4882a593Smuzhiyun 
578*4882a593Smuzhiyun 	reset_pid_controller(params);
579*4882a593Smuzhiyun 
580*4882a593Smuzhiyun 	tz->governor_data = params;
581*4882a593Smuzhiyun 
582*4882a593Smuzhiyun 	return 0;
583*4882a593Smuzhiyun 
584*4882a593Smuzhiyun free_params:
585*4882a593Smuzhiyun 	kfree(params);
586*4882a593Smuzhiyun 
587*4882a593Smuzhiyun 	return ret;
588*4882a593Smuzhiyun }
589*4882a593Smuzhiyun 
power_allocator_unbind(struct thermal_zone_device * tz)590*4882a593Smuzhiyun static void power_allocator_unbind(struct thermal_zone_device *tz)
591*4882a593Smuzhiyun {
592*4882a593Smuzhiyun 	struct power_allocator_params *params = tz->governor_data;
593*4882a593Smuzhiyun 
594*4882a593Smuzhiyun 	dev_dbg(&tz->device, "Unbinding from thermal zone %d\n", tz->id);
595*4882a593Smuzhiyun 
596*4882a593Smuzhiyun 	if (params->allocated_tzp) {
597*4882a593Smuzhiyun 		kfree(tz->tzp);
598*4882a593Smuzhiyun 		tz->tzp = NULL;
599*4882a593Smuzhiyun 	}
600*4882a593Smuzhiyun 
601*4882a593Smuzhiyun 	kfree(tz->governor_data);
602*4882a593Smuzhiyun 	tz->governor_data = NULL;
603*4882a593Smuzhiyun }
604*4882a593Smuzhiyun 
power_allocator_throttle(struct thermal_zone_device * tz,int trip)605*4882a593Smuzhiyun static int power_allocator_throttle(struct thermal_zone_device *tz, int trip)
606*4882a593Smuzhiyun {
607*4882a593Smuzhiyun 	int ret;
608*4882a593Smuzhiyun 	int switch_on_temp, control_temp;
609*4882a593Smuzhiyun 	struct power_allocator_params *params = tz->governor_data;
610*4882a593Smuzhiyun 
611*4882a593Smuzhiyun 	/*
612*4882a593Smuzhiyun 	 * We get called for every trip point but we only need to do
613*4882a593Smuzhiyun 	 * our calculations once
614*4882a593Smuzhiyun 	 */
615*4882a593Smuzhiyun 	if (trip != params->trip_max_desired_temperature)
616*4882a593Smuzhiyun 		return 0;
617*4882a593Smuzhiyun 
618*4882a593Smuzhiyun 	ret = tz->ops->get_trip_temp(tz, params->trip_switch_on,
619*4882a593Smuzhiyun 				     &switch_on_temp);
620*4882a593Smuzhiyun 	if (!ret && (tz->temperature < switch_on_temp)) {
621*4882a593Smuzhiyun 		tz->passive = 0;
622*4882a593Smuzhiyun 		reset_pid_controller(params);
623*4882a593Smuzhiyun 		allow_maximum_power(tz);
624*4882a593Smuzhiyun 		return 0;
625*4882a593Smuzhiyun 	}
626*4882a593Smuzhiyun 
627*4882a593Smuzhiyun 	tz->passive = 1;
628*4882a593Smuzhiyun 
629*4882a593Smuzhiyun 	ret = tz->ops->get_trip_temp(tz, params->trip_max_desired_temperature,
630*4882a593Smuzhiyun 				&control_temp);
631*4882a593Smuzhiyun 	if (ret) {
632*4882a593Smuzhiyun 		dev_warn(&tz->device,
633*4882a593Smuzhiyun 			 "Failed to get the maximum desired temperature: %d\n",
634*4882a593Smuzhiyun 			 ret);
635*4882a593Smuzhiyun 		return ret;
636*4882a593Smuzhiyun 	}
637*4882a593Smuzhiyun 
638*4882a593Smuzhiyun 	return allocate_power(tz, control_temp);
639*4882a593Smuzhiyun }
640*4882a593Smuzhiyun 
641*4882a593Smuzhiyun static struct thermal_governor thermal_gov_power_allocator = {
642*4882a593Smuzhiyun 	.name		= "power_allocator",
643*4882a593Smuzhiyun 	.bind_to_tz	= power_allocator_bind,
644*4882a593Smuzhiyun 	.unbind_from_tz	= power_allocator_unbind,
645*4882a593Smuzhiyun 	.throttle	= power_allocator_throttle,
646*4882a593Smuzhiyun };
647*4882a593Smuzhiyun THERMAL_GOVERNOR_DECLARE(thermal_gov_power_allocator);
648