1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16#define pr_fmt(fmt) "Power allocator: " fmt
17
18#include <linux/rculist.h>
19#include <linux/slab.h>
20#include <linux/thermal.h>
21
22#define CREATE_TRACE_POINTS
23#include <trace/events/thermal_power_allocator.h>
24
25#include "thermal_core.h"
26
27#define INVALID_TRIP -1
28
29#define FRAC_BITS 10
30#define int_to_frac(x) ((x) << FRAC_BITS)
31#define frac_to_int(x) ((x) >> FRAC_BITS)
32
33
34
35
36
37
38
39
40
41static inline s64 mul_frac(s64 x, s64 y)
42{
43 return (x * y) >> FRAC_BITS;
44}
45
46
47
48
49
50
51
52
53
54static inline s64 div_frac(s64 x, s64 y)
55{
56 return div_s64(x << FRAC_BITS, y);
57}
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74struct power_allocator_params {
75 bool allocated_tzp;
76 s64 err_integral;
77 s32 prev_err;
78 int trip_switch_on;
79 int trip_max_desired_temperature;
80};
81
82
83
84
85
86
87
88
89
90
91
92
93static u32 estimate_sustainable_power(struct thermal_zone_device *tz)
94{
95 u32 sustainable_power = 0;
96 struct thermal_instance *instance;
97 struct power_allocator_params *params = tz->governor_data;
98
99 list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
100 struct thermal_cooling_device *cdev = instance->cdev;
101 u32 min_power;
102
103 if (instance->trip != params->trip_max_desired_temperature)
104 continue;
105
106 if (power_actor_get_min_power(cdev, tz, &min_power))
107 continue;
108
109 sustainable_power += min_power;
110 }
111
112 return sustainable_power;
113}
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134static void estimate_pid_constants(struct thermal_zone_device *tz,
135 u32 sustainable_power, int trip_switch_on,
136 int control_temp, bool force)
137{
138 int ret;
139 int switch_on_temp;
140 u32 temperature_threshold;
141
142 ret = tz->ops->get_trip_temp(tz, trip_switch_on, &switch_on_temp);
143 if (ret)
144 switch_on_temp = 0;
145
146 temperature_threshold = control_temp - switch_on_temp;
147
148
149
150
151
152
153
154
155 if (!temperature_threshold)
156 return;
157
158 if (!tz->tzp->k_po || force)
159 tz->tzp->k_po = int_to_frac(sustainable_power) /
160 temperature_threshold;
161
162 if (!tz->tzp->k_pu || force)
163 tz->tzp->k_pu = int_to_frac(2 * sustainable_power) /
164 temperature_threshold;
165
166 if (!tz->tzp->k_i || force)
167 tz->tzp->k_i = int_to_frac(10) / 1000;
168
169
170
171
172}
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193static u32 pid_controller(struct thermal_zone_device *tz,
194 int current_temp,
195 int control_temp,
196 u32 max_allocatable_power)
197{
198 s64 p, i, d, power_range;
199 s32 err, max_power_frac;
200 u32 sustainable_power;
201 struct power_allocator_params *params = tz->governor_data;
202
203 max_power_frac = int_to_frac(max_allocatable_power);
204
205 if (tz->tzp->sustainable_power) {
206 sustainable_power = tz->tzp->sustainable_power;
207 } else {
208 sustainable_power = estimate_sustainable_power(tz);
209 estimate_pid_constants(tz, sustainable_power,
210 params->trip_switch_on, control_temp,
211 true);
212 }
213
214 err = control_temp - current_temp;
215 err = int_to_frac(err);
216
217
218 p = mul_frac(err < 0 ? tz->tzp->k_po : tz->tzp->k_pu, err);
219
220
221
222
223
224
225
226 i = mul_frac(tz->tzp->k_i, params->err_integral);
227
228 if (err < int_to_frac(tz->tzp->integral_cutoff)) {
229 s64 i_next = i + mul_frac(tz->tzp->k_i, err);
230
231 if (abs64(i_next) < max_power_frac) {
232 i = i_next;
233 params->err_integral += err;
234 }
235 }
236
237
238
239
240
241
242
243
244 d = mul_frac(tz->tzp->k_d, err - params->prev_err);
245 d = div_frac(d, tz->passive_delay);
246 params->prev_err = err;
247
248 power_range = p + i + d;
249
250
251 power_range = sustainable_power + frac_to_int(power_range);
252
253 power_range = clamp(power_range, (s64)0, (s64)max_allocatable_power);
254
255 trace_thermal_power_allocator_pid(tz, frac_to_int(err),
256 frac_to_int(params->err_integral),
257 frac_to_int(p), frac_to_int(i),
258 frac_to_int(d), power_range);
259
260 return power_range;
261}
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290static void divvy_up_power(u32 *req_power, u32 *max_power, int num_actors,
291 u32 total_req_power, u32 power_range,
292 u32 *granted_power, u32 *extra_actor_power)
293{
294 u32 extra_power, capped_extra_power;
295 int i;
296
297
298
299
300 if (!total_req_power)
301 total_req_power = 1;
302
303 capped_extra_power = 0;
304 extra_power = 0;
305 for (i = 0; i < num_actors; i++) {
306 u64 req_range = req_power[i] * power_range;
307
308 granted_power[i] = DIV_ROUND_CLOSEST_ULL(req_range,
309 total_req_power);
310
311 if (granted_power[i] > max_power[i]) {
312 extra_power += granted_power[i] - max_power[i];
313 granted_power[i] = max_power[i];
314 }
315
316 extra_actor_power[i] = max_power[i] - granted_power[i];
317 capped_extra_power += extra_actor_power[i];
318 }
319
320 if (!extra_power)
321 return;
322
323
324
325
326
327 extra_power = min(extra_power, capped_extra_power);
328 if (capped_extra_power > 0)
329 for (i = 0; i < num_actors; i++)
330 granted_power[i] += (extra_actor_power[i] *
331 extra_power) / capped_extra_power;
332}
333
334static int allocate_power(struct thermal_zone_device *tz,
335 int current_temp,
336 int control_temp)
337{
338 struct thermal_instance *instance;
339 struct power_allocator_params *params = tz->governor_data;
340 u32 *req_power, *max_power, *granted_power, *extra_actor_power;
341 u32 *weighted_req_power;
342 u32 total_req_power, max_allocatable_power, total_weighted_req_power;
343 u32 total_granted_power, power_range;
344 int i, num_actors, total_weight, ret = 0;
345 int trip_max_desired_temperature = params->trip_max_desired_temperature;
346
347 mutex_lock(&tz->lock);
348
349 num_actors = 0;
350 total_weight = 0;
351 list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
352 if ((instance->trip == trip_max_desired_temperature) &&
353 cdev_is_power_actor(instance->cdev)) {
354 num_actors++;
355 total_weight += instance->weight;
356 }
357 }
358
359 if (!num_actors) {
360 ret = -ENODEV;
361 goto unlock;
362 }
363
364
365
366
367
368
369
370
371 BUILD_BUG_ON(sizeof(*req_power) != sizeof(*max_power));
372 BUILD_BUG_ON(sizeof(*req_power) != sizeof(*granted_power));
373 BUILD_BUG_ON(sizeof(*req_power) != sizeof(*extra_actor_power));
374 BUILD_BUG_ON(sizeof(*req_power) != sizeof(*weighted_req_power));
375 req_power = kcalloc(num_actors * 5, sizeof(*req_power), GFP_KERNEL);
376 if (!req_power) {
377 ret = -ENOMEM;
378 goto unlock;
379 }
380
381 max_power = &req_power[num_actors];
382 granted_power = &req_power[2 * num_actors];
383 extra_actor_power = &req_power[3 * num_actors];
384 weighted_req_power = &req_power[4 * num_actors];
385
386 i = 0;
387 total_weighted_req_power = 0;
388 total_req_power = 0;
389 max_allocatable_power = 0;
390
391 list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
392 int weight;
393 struct thermal_cooling_device *cdev = instance->cdev;
394
395 if (instance->trip != trip_max_desired_temperature)
396 continue;
397
398 if (!cdev_is_power_actor(cdev))
399 continue;
400
401 if (cdev->ops->get_requested_power(cdev, tz, &req_power[i]))
402 continue;
403
404 if (!total_weight)
405 weight = 1 << FRAC_BITS;
406 else
407 weight = instance->weight;
408
409 weighted_req_power[i] = frac_to_int(weight * req_power[i]);
410
411 if (power_actor_get_max_power(cdev, tz, &max_power[i]))
412 continue;
413
414 total_req_power += req_power[i];
415 max_allocatable_power += max_power[i];
416 total_weighted_req_power += weighted_req_power[i];
417
418 i++;
419 }
420
421 power_range = pid_controller(tz, current_temp, control_temp,
422 max_allocatable_power);
423
424 divvy_up_power(weighted_req_power, max_power, num_actors,
425 total_weighted_req_power, power_range, granted_power,
426 extra_actor_power);
427
428 total_granted_power = 0;
429 i = 0;
430 list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
431 if (instance->trip != trip_max_desired_temperature)
432 continue;
433
434 if (!cdev_is_power_actor(instance->cdev))
435 continue;
436
437 power_actor_set_power(instance->cdev, instance,
438 granted_power[i]);
439 total_granted_power += granted_power[i];
440
441 i++;
442 }
443
444 trace_thermal_power_allocator(tz, req_power, total_req_power,
445 granted_power, total_granted_power,
446 num_actors, power_range,
447 max_allocatable_power, current_temp,
448 control_temp - current_temp);
449
450 kfree(req_power);
451unlock:
452 mutex_unlock(&tz->lock);
453
454 return ret;
455}
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472static void get_governor_trips(struct thermal_zone_device *tz,
473 struct power_allocator_params *params)
474{
475 int i, last_active, last_passive;
476 bool found_first_passive;
477
478 found_first_passive = false;
479 last_active = INVALID_TRIP;
480 last_passive = INVALID_TRIP;
481
482 for (i = 0; i < tz->trips; i++) {
483 enum thermal_trip_type type;
484 int ret;
485
486 ret = tz->ops->get_trip_type(tz, i, &type);
487 if (ret) {
488 dev_warn(&tz->device,
489 "Failed to get trip point %d type: %d\n", i,
490 ret);
491 continue;
492 }
493
494 if (type == THERMAL_TRIP_PASSIVE) {
495 if (!found_first_passive) {
496 params->trip_switch_on = i;
497 found_first_passive = true;
498 } else {
499 last_passive = i;
500 }
501 } else if (type == THERMAL_TRIP_ACTIVE) {
502 last_active = i;
503 } else {
504 break;
505 }
506 }
507
508 if (last_passive != INVALID_TRIP) {
509 params->trip_max_desired_temperature = last_passive;
510 } else if (found_first_passive) {
511 params->trip_max_desired_temperature = params->trip_switch_on;
512 params->trip_switch_on = INVALID_TRIP;
513 } else {
514 params->trip_switch_on = INVALID_TRIP;
515 params->trip_max_desired_temperature = last_active;
516 }
517}
518
519static void reset_pid_controller(struct power_allocator_params *params)
520{
521 params->err_integral = 0;
522 params->prev_err = 0;
523}
524
525static void allow_maximum_power(struct thermal_zone_device *tz)
526{
527 struct thermal_instance *instance;
528 struct power_allocator_params *params = tz->governor_data;
529
530 list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
531 if ((instance->trip != params->trip_max_desired_temperature) ||
532 (!cdev_is_power_actor(instance->cdev)))
533 continue;
534
535 instance->target = 0;
536 instance->cdev->updated = false;
537 thermal_cdev_update(instance->cdev);
538 }
539}
540
541
542
543
544
545
546
547
548
549
550static int power_allocator_bind(struct thermal_zone_device *tz)
551{
552 int ret;
553 struct power_allocator_params *params;
554 int control_temp;
555
556 params = kzalloc(sizeof(*params), GFP_KERNEL);
557 if (!params)
558 return -ENOMEM;
559
560 if (!tz->tzp) {
561 tz->tzp = kzalloc(sizeof(*tz->tzp), GFP_KERNEL);
562 if (!tz->tzp) {
563 ret = -ENOMEM;
564 goto free_params;
565 }
566
567 params->allocated_tzp = true;
568 }
569
570 if (!tz->tzp->sustainable_power)
571 dev_warn(&tz->device, "power_allocator: sustainable_power will be estimated\n");
572
573 get_governor_trips(tz, params);
574
575 if (tz->trips > 0) {
576 ret = tz->ops->get_trip_temp(tz,
577 params->trip_max_desired_temperature,
578 &control_temp);
579 if (!ret)
580 estimate_pid_constants(tz, tz->tzp->sustainable_power,
581 params->trip_switch_on,
582 control_temp, false);
583 }
584
585 reset_pid_controller(params);
586
587 tz->governor_data = params;
588
589 return 0;
590
591free_params:
592 kfree(params);
593
594 return ret;
595}
596
597static void power_allocator_unbind(struct thermal_zone_device *tz)
598{
599 struct power_allocator_params *params = tz->governor_data;
600
601 dev_dbg(&tz->device, "Unbinding from thermal zone %d\n", tz->id);
602
603 if (params->allocated_tzp) {
604 kfree(tz->tzp);
605 tz->tzp = NULL;
606 }
607
608 kfree(tz->governor_data);
609 tz->governor_data = NULL;
610}
611
612static int power_allocator_throttle(struct thermal_zone_device *tz, int trip)
613{
614 int ret;
615 int switch_on_temp, control_temp, current_temp;
616 struct power_allocator_params *params = tz->governor_data;
617
618
619
620
621
622 if (trip != params->trip_max_desired_temperature)
623 return 0;
624
625 ret = thermal_zone_get_temp(tz, ¤t_temp);
626 if (ret) {
627 dev_warn(&tz->device, "Failed to get temperature: %d\n", ret);
628 return ret;
629 }
630
631 ret = tz->ops->get_trip_temp(tz, params->trip_switch_on,
632 &switch_on_temp);
633 if (!ret && (current_temp < switch_on_temp)) {
634 tz->passive = 0;
635 reset_pid_controller(params);
636 allow_maximum_power(tz);
637 return 0;
638 }
639
640 tz->passive = 1;
641
642 ret = tz->ops->get_trip_temp(tz, params->trip_max_desired_temperature,
643 &control_temp);
644 if (ret) {
645 dev_warn(&tz->device,
646 "Failed to get the maximum desired temperature: %d\n",
647 ret);
648 return ret;
649 }
650
651 return allocate_power(tz, current_temp, control_temp);
652}
653
654static struct thermal_governor thermal_gov_power_allocator = {
655 .name = "power_allocator",
656 .bind_to_tz = power_allocator_bind,
657 .unbind_from_tz = power_allocator_unbind,
658 .throttle = power_allocator_throttle,
659};
660
661int thermal_gov_power_allocator_register(void)
662{
663 return thermal_register_governor(&thermal_gov_power_allocator);
664}
665
666void thermal_gov_power_allocator_unregister(void)
667{
668 thermal_unregister_governor(&thermal_gov_power_allocator);
669}
670