@@ -46,6 +46,22 @@ static inline s64 div_frac(s64 x, s64 y)
46
46
return div_s64 (x << FRAC_BITS , y );
47
47
}
48
48
49
+ /**
50
+ * struct power_actor - internal power information for power actor
51
+ * @req_power: requested power value (not weighted)
52
+ * @max_power: max allocatable power for this actor
53
+ * @granted_power: granted power for this actor
54
+ * @extra_actor_power: extra power that this actor can receive
55
+ * @weighted_req_power: weighted requested power as input to IPA
56
+ */
57
+ struct power_actor {
58
+ u32 req_power ;
59
+ u32 max_power ;
60
+ u32 granted_power ;
61
+ u32 extra_actor_power ;
62
+ u32 weighted_req_power ;
63
+ };
64
+
49
65
/**
50
66
* struct power_allocator_params - parameters for the power allocator governor
51
67
* @allocated_tzp: whether we have allocated tzp for this thermal zone and
@@ -61,6 +77,9 @@ static inline s64 div_frac(s64 x, s64 y)
61
77
* @trip_switch_on should be NULL.
62
78
* @trip_max: last passive trip point of the thermal zone. The
63
79
* temperature we are controlling for.
80
+ * @num_actors: number of cooling devices supporting IPA callbacks
81
+ * @buffer_size: internal buffer size, to avoid runtime re-calculation
82
+ * @power: buffer for all power actors internal power information
64
83
*/
65
84
struct power_allocator_params {
66
85
bool allocated_tzp ;
@@ -69,6 +88,9 @@ struct power_allocator_params {
69
88
u32 sustainable_power ;
70
89
const struct thermal_trip * trip_switch_on ;
71
90
const struct thermal_trip * trip_max ;
91
+ unsigned int num_actors ;
92
+ unsigned int buffer_size ;
93
+ struct power_actor * power ;
72
94
};
73
95
74
96
/**
@@ -303,15 +325,10 @@ power_actor_set_power(struct thermal_cooling_device *cdev,
303
325
304
326
/**
305
327
* divvy_up_power() - divvy the allocated power between the actors
306
- * @req_power: each actor's requested power
307
- * @max_power: each actor's maximum available power
308
- * @num_actors: size of the @req_power, @max_power and @granted_power's array
309
- * @total_req_power: sum of @req_power
328
+ * @power: buffer for all power actors internal power information
329
+ * @num_actors: number of power actors in this thermal zone
330
+ * @total_req_power: sum of all weighted requested power for all actors
310
331
* @power_range: total allocated power
311
- * @granted_power: output array: each actor's granted power
312
- * @extra_actor_power: an appropriately sized array to be used in the
313
- * function as temporary storage of the extra power given
314
- * to the actors
315
332
*
316
333
* This function divides the total allocated power (@power_range)
317
334
* fairly between the actors. It first tries to give each actor a
@@ -324,13 +341,9 @@ power_actor_set_power(struct thermal_cooling_device *cdev,
324
341
* If any actor received more than their maximum power, then that
325
342
* surplus is re-divvied among the actors based on how far they are
326
343
* from their respective maximums.
327
- *
328
- * Granted power for each actor is written to @granted_power, which
329
- * should've been allocated by the calling function.
330
344
*/
331
- static void divvy_up_power (u32 * req_power , u32 * max_power , int num_actors ,
332
- u32 total_req_power , u32 power_range ,
333
- u32 * granted_power , u32 * extra_actor_power )
345
+ static void divvy_up_power (struct power_actor * power , int num_actors ,
346
+ u32 total_req_power , u32 power_range )
334
347
{
335
348
u32 capped_extra_power = 0 ;
336
349
u32 extra_power = 0 ;
@@ -343,18 +356,19 @@ static void divvy_up_power(u32 *req_power, u32 *max_power, int num_actors,
343
356
total_req_power = 1 ;
344
357
345
358
for (i = 0 ; i < num_actors ; i ++ ) {
346
- u64 req_range = (u64 )req_power [i ] * power_range ;
359
+ struct power_actor * pa = & power [i ];
360
+ u64 req_range = (u64 )pa -> req_power * power_range ;
347
361
348
- granted_power [ i ] = DIV_ROUND_CLOSEST_ULL (req_range ,
349
- total_req_power );
362
+ pa -> granted_power = DIV_ROUND_CLOSEST_ULL (req_range ,
363
+ total_req_power );
350
364
351
- if (granted_power [ i ] > max_power [ i ] ) {
352
- extra_power += granted_power [ i ] - max_power [ i ] ;
353
- granted_power [ i ] = max_power [ i ] ;
365
+ if (pa -> granted_power > pa -> max_power ) {
366
+ extra_power += pa -> granted_power - pa -> max_power ;
367
+ pa -> granted_power = pa -> max_power ;
354
368
}
355
369
356
- extra_actor_power [ i ] = max_power [ i ] - granted_power [ i ] ;
357
- capped_extra_power += extra_actor_power [ i ] ;
370
+ pa -> extra_actor_power = pa -> max_power - pa -> granted_power ;
371
+ capped_extra_power += pa -> extra_actor_power ;
358
372
}
359
373
360
374
if (!extra_power || !capped_extra_power )
@@ -367,61 +381,44 @@ static void divvy_up_power(u32 *req_power, u32 *max_power, int num_actors,
367
381
extra_power = min (extra_power , capped_extra_power );
368
382
369
383
for (i = 0 ; i < num_actors ; i ++ ) {
370
- u64 extra_range = (u64 )extra_actor_power [i ] * extra_power ;
384
+ struct power_actor * pa = & power [i ];
385
+ u64 extra_range = pa -> extra_actor_power ;
371
386
372
- granted_power [i ] += DIV_ROUND_CLOSEST_ULL (extra_range ,
373
- capped_extra_power );
387
+ extra_range *= extra_power ;
388
+ pa -> granted_power += DIV_ROUND_CLOSEST_ULL (extra_range ,
389
+ capped_extra_power );
374
390
}
375
391
}
376
392
377
393
static int allocate_power (struct thermal_zone_device * tz , int control_temp )
378
394
{
379
- u32 * req_power , * max_power , * granted_power , * extra_actor_power ;
380
395
struct power_allocator_params * params = tz -> governor_data ;
396
+ unsigned int num_actors = params -> num_actors ;
397
+ struct power_actor * power = params -> power ;
381
398
struct thermal_cooling_device * cdev ;
382
399
struct thermal_instance * instance ;
383
400
u32 total_weighted_req_power = 0 ;
384
401
u32 max_allocatable_power = 0 ;
385
402
u32 total_granted_power = 0 ;
386
403
u32 total_req_power = 0 ;
387
- u32 * weighted_req_power ;
388
404
u32 power_range , weight ;
389
405
int total_weight = 0 ;
390
- int num_actors = 0 ;
391
- int i = 0 ;
392
-
393
- list_for_each_entry (instance , & tz -> thermal_instances , tz_node ) {
394
- if ((instance -> trip == params -> trip_max ) &&
395
- cdev_is_power_actor (instance -> cdev )) {
396
- num_actors ++ ;
397
- total_weight += instance -> weight ;
398
- }
399
- }
406
+ int i = 0 , ret ;
400
407
401
408
if (!num_actors )
402
409
return - ENODEV ;
403
410
404
- /*
405
- * We need to allocate five arrays of the same size:
406
- * req_power, max_power, granted_power, extra_actor_power and
407
- * weighted_req_power. They are going to be needed until this
408
- * function returns. Allocate them all in one go to simplify
409
- * the allocation and deallocation logic.
410
- */
411
- BUILD_BUG_ON (sizeof (* req_power ) != sizeof (* max_power ));
412
- BUILD_BUG_ON (sizeof (* req_power ) != sizeof (* granted_power ));
413
- BUILD_BUG_ON (sizeof (* req_power ) != sizeof (* extra_actor_power ));
414
- BUILD_BUG_ON (sizeof (* req_power ) != sizeof (* weighted_req_power ));
415
- req_power = kcalloc (num_actors * 5 , sizeof (* req_power ), GFP_KERNEL );
416
- if (!req_power )
417
- return - ENOMEM ;
411
+ list_for_each_entry (instance , & tz -> thermal_instances , tz_node )
412
+ if ((instance -> trip == params -> trip_max ) &&
413
+ cdev_is_power_actor (instance -> cdev ))
414
+ total_weight += instance -> weight ;
418
415
419
- max_power = & req_power [num_actors ];
420
- granted_power = & req_power [2 * num_actors ];
421
- extra_actor_power = & req_power [3 * num_actors ];
422
- weighted_req_power = & req_power [4 * num_actors ];
416
+ /* Clean all buffers for new power estimations */
417
+ memset (power , 0 , params -> buffer_size );
423
418
424
419
list_for_each_entry (instance , & tz -> thermal_instances , tz_node ) {
420
+ struct power_actor * pa = & power [i ];
421
+
425
422
cdev = instance -> cdev ;
426
423
427
424
if (instance -> trip != params -> trip_max )
@@ -430,47 +427,50 @@ static int allocate_power(struct thermal_zone_device *tz, int control_temp)
430
427
if (!cdev_is_power_actor (cdev ))
431
428
continue ;
432
429
433
- if (cdev -> ops -> get_requested_power (cdev , & req_power [i ]))
430
+ ret = cdev -> ops -> get_requested_power (cdev , & pa -> req_power );
431
+ if (ret )
434
432
continue ;
435
433
436
434
if (!total_weight )
437
435
weight = 1 << FRAC_BITS ;
438
436
else
439
437
weight = instance -> weight ;
440
438
441
- weighted_req_power [ i ] = frac_to_int (weight * req_power [ i ] );
439
+ pa -> weighted_req_power = frac_to_int (weight * pa -> req_power );
442
440
443
- if (cdev -> ops -> state2power (cdev , instance -> lower ,
444
- & max_power [i ]))
441
+ ret = cdev -> ops -> state2power (cdev , instance -> lower ,
442
+ & pa -> max_power );
443
+ if (ret )
445
444
continue ;
446
445
447
- total_req_power += req_power [ i ] ;
448
- max_allocatable_power += max_power [ i ] ;
449
- total_weighted_req_power += weighted_req_power [ i ] ;
446
+ total_req_power += pa -> req_power ;
447
+ max_allocatable_power += pa -> max_power ;
448
+ total_weighted_req_power += pa -> weighted_req_power ;
450
449
451
450
i ++ ;
452
451
}
453
452
454
453
power_range = pid_controller (tz , control_temp , max_allocatable_power );
455
454
456
- divvy_up_power (weighted_req_power , max_power , num_actors ,
457
- total_weighted_req_power , power_range , granted_power ,
458
- extra_actor_power );
455
+ divvy_up_power (power , num_actors , total_weighted_req_power ,
456
+ power_range );
459
457
460
458
i = 0 ;
461
459
list_for_each_entry (instance , & tz -> thermal_instances , tz_node ) {
460
+ struct power_actor * pa = & power [i ];
461
+
462
462
if (instance -> trip != params -> trip_max )
463
463
continue ;
464
464
465
465
if (!cdev_is_power_actor (instance -> cdev ))
466
466
continue ;
467
467
468
468
power_actor_set_power (instance -> cdev , instance ,
469
- granted_power [ i ] );
470
- total_granted_power += granted_power [ i ] ;
469
+ pa -> granted_power );
470
+ total_granted_power += pa -> granted_power ;
471
471
472
- trace_thermal_power_actor (tz , i , req_power [ i ] ,
473
- granted_power [ i ] );
472
+ trace_thermal_power_actor (tz , i , pa -> req_power ,
473
+ pa -> granted_power );
474
474
i ++ ;
475
475
}
476
476
@@ -479,8 +479,6 @@ static int allocate_power(struct thermal_zone_device *tz, int control_temp)
479
479
max_allocatable_power , tz -> temperature ,
480
480
control_temp - tz -> temperature );
481
481
482
- kfree (req_power );
483
-
484
482
return 0 ;
485
483
}
486
484
@@ -607,6 +605,63 @@ static int check_power_actors(struct thermal_zone_device *tz,
607
605
return ret ;
608
606
}
609
607
608
+ static int allocate_actors_buffer (struct power_allocator_params * params ,
609
+ int num_actors )
610
+ {
611
+ int ret ;
612
+
613
+ kfree (params -> power );
614
+
615
+ /* There might be no cooling devices yet. */
616
+ if (!num_actors ) {
617
+ ret = - EINVAL ;
618
+ goto clean_state ;
619
+ }
620
+
621
+ params -> power = kcalloc (num_actors , sizeof (struct power_actor ),
622
+ GFP_KERNEL );
623
+ if (!params -> power ) {
624
+ ret = - ENOMEM ;
625
+ goto clean_state ;
626
+ }
627
+
628
+ params -> num_actors = num_actors ;
629
+ params -> buffer_size = num_actors * sizeof (struct power_actor );
630
+
631
+ return 0 ;
632
+
633
+ clean_state :
634
+ params -> num_actors = 0 ;
635
+ params -> buffer_size = 0 ;
636
+ params -> power = NULL ;
637
+ return ret ;
638
+ }
639
+
640
+ static void power_allocator_update_tz (struct thermal_zone_device * tz ,
641
+ enum thermal_notify_event reason )
642
+ {
643
+ struct power_allocator_params * params = tz -> governor_data ;
644
+ struct thermal_instance * instance ;
645
+ int num_actors = 0 ;
646
+
647
+ switch (reason ) {
648
+ case THERMAL_TZ_BIND_CDEV :
649
+ case THERMAL_TZ_UNBIND_CDEV :
650
+ list_for_each_entry (instance , & tz -> thermal_instances , tz_node )
651
+ if ((instance -> trip == params -> trip_max ) &&
652
+ cdev_is_power_actor (instance -> cdev ))
653
+ num_actors ++ ;
654
+
655
+ if (num_actors == params -> num_actors )
656
+ return ;
657
+
658
+ allocate_actors_buffer (params , num_actors );
659
+ break ;
660
+ default :
661
+ break ;
662
+ }
663
+ }
664
+
610
665
/**
611
666
* power_allocator_bind() - bind the power_allocator governor to a thermal zone
612
667
* @tz: thermal zone to bind it to
@@ -640,6 +695,13 @@ static int power_allocator_bind(struct thermal_zone_device *tz)
640
695
return ret ;
641
696
}
642
697
698
+ ret = allocate_actors_buffer (params , ret );
699
+ if (ret ) {
700
+ dev_warn (& tz -> device , "power_allocator: allocation failed\n" );
701
+ kfree (params );
702
+ return ret ;
703
+ }
704
+
643
705
if (!tz -> tzp ) {
644
706
tz -> tzp = kzalloc (sizeof (* tz -> tzp ), GFP_KERNEL );
645
707
if (!tz -> tzp ) {
@@ -664,6 +726,7 @@ static int power_allocator_bind(struct thermal_zone_device *tz)
664
726
return 0 ;
665
727
666
728
free_params :
729
+ kfree (params -> power );
667
730
kfree (params );
668
731
669
732
return ret ;
@@ -680,6 +743,7 @@ static void power_allocator_unbind(struct thermal_zone_device *tz)
680
743
tz -> tzp = NULL ;
681
744
}
682
745
746
+ kfree (params -> power );
683
747
kfree (tz -> governor_data );
684
748
tz -> governor_data = NULL ;
685
749
}
@@ -718,5 +782,6 @@ static struct thermal_governor thermal_gov_power_allocator = {
718
782
.bind_to_tz = power_allocator_bind ,
719
783
.unbind_from_tz = power_allocator_unbind ,
720
784
.throttle = power_allocator_throttle ,
785
+ .update_tz = power_allocator_update_tz ,
721
786
};
722
787
THERMAL_GOVERNOR_DECLARE (thermal_gov_power_allocator );
0 commit comments