@@ -46,6 +46,22 @@ static inline s64 div_frac(s64 x, s64 y)
4646 return div_s64 (x << FRAC_BITS , y );
4747}
4848
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+
4965/**
5066 * struct power_allocator_params - parameters for the power allocator governor
5167 * @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)
6177 * @trip_switch_on should be NULL.
6278 * @trip_max: last passive trip point of the thermal zone. The
6379 * 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
6483 */
6584struct power_allocator_params {
6685 bool allocated_tzp ;
@@ -69,6 +88,9 @@ struct power_allocator_params {
6988 u32 sustainable_power ;
7089 const struct thermal_trip * trip_switch_on ;
7190 const struct thermal_trip * trip_max ;
91+ unsigned int num_actors ;
92+ unsigned int buffer_size ;
93+ struct power_actor * power ;
7294};
7395
7496/**
@@ -303,15 +325,10 @@ power_actor_set_power(struct thermal_cooling_device *cdev,
303325
304326/**
305327 * 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
310331 * @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
315332 *
316333 * This function divides the total allocated power (@power_range)
317334 * 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,
324341 * If any actor received more than their maximum power, then that
325342 * surplus is re-divvied among the actors based on how far they are
326343 * 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.
330344 */
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 )
334347{
335348 u32 capped_extra_power = 0 ;
336349 u32 extra_power = 0 ;
@@ -343,18 +356,19 @@ static void divvy_up_power(u32 *req_power, u32 *max_power, int num_actors,
343356 total_req_power = 1 ;
344357
345358 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 ;
347361
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 );
350364
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 ;
354368 }
355369
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 ;
358372 }
359373
360374 if (!extra_power || !capped_extra_power )
@@ -367,61 +381,44 @@ static void divvy_up_power(u32 *req_power, u32 *max_power, int num_actors,
367381 extra_power = min (extra_power , capped_extra_power );
368382
369383 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 ;
371386
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 );
374390 }
375391}
376392
377393static int allocate_power (struct thermal_zone_device * tz , int control_temp )
378394{
379- u32 * req_power , * max_power , * granted_power , * extra_actor_power ;
380395 struct power_allocator_params * params = tz -> governor_data ;
396+ unsigned int num_actors = params -> num_actors ;
397+ struct power_actor * power = params -> power ;
381398 struct thermal_cooling_device * cdev ;
382399 struct thermal_instance * instance ;
383400 u32 total_weighted_req_power = 0 ;
384401 u32 max_allocatable_power = 0 ;
385402 u32 total_granted_power = 0 ;
386403 u32 total_req_power = 0 ;
387- u32 * weighted_req_power ;
388404 u32 power_range , weight ;
389405 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 ;
400407
401408 if (!num_actors )
402409 return - ENODEV ;
403410
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 ;
418415
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 );
423418
424419 list_for_each_entry (instance , & tz -> thermal_instances , tz_node ) {
420+ struct power_actor * pa = & power [i ];
421+
425422 cdev = instance -> cdev ;
426423
427424 if (instance -> trip != params -> trip_max )
@@ -430,47 +427,50 @@ static int allocate_power(struct thermal_zone_device *tz, int control_temp)
430427 if (!cdev_is_power_actor (cdev ))
431428 continue ;
432429
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 )
434432 continue ;
435433
436434 if (!total_weight )
437435 weight = 1 << FRAC_BITS ;
438436 else
439437 weight = instance -> weight ;
440438
441- weighted_req_power [ i ] = frac_to_int (weight * req_power [ i ] );
439+ pa -> weighted_req_power = frac_to_int (weight * pa -> req_power );
442440
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 )
445444 continue ;
446445
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 ;
450449
451450 i ++ ;
452451 }
453452
454453 power_range = pid_controller (tz , control_temp , max_allocatable_power );
455454
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 );
459457
460458 i = 0 ;
461459 list_for_each_entry (instance , & tz -> thermal_instances , tz_node ) {
460+ struct power_actor * pa = & power [i ];
461+
462462 if (instance -> trip != params -> trip_max )
463463 continue ;
464464
465465 if (!cdev_is_power_actor (instance -> cdev ))
466466 continue ;
467467
468468 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 ;
471471
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 );
474474 i ++ ;
475475 }
476476
@@ -479,8 +479,6 @@ static int allocate_power(struct thermal_zone_device *tz, int control_temp)
479479 max_allocatable_power , tz -> temperature ,
480480 control_temp - tz -> temperature );
481481
482- kfree (req_power );
483-
484482 return 0 ;
485483}
486484
@@ -607,6 +605,63 @@ static int check_power_actors(struct thermal_zone_device *tz,
607605 return ret ;
608606}
609607
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+
610665/**
611666 * power_allocator_bind() - bind the power_allocator governor to a thermal zone
612667 * @tz: thermal zone to bind it to
@@ -640,6 +695,13 @@ static int power_allocator_bind(struct thermal_zone_device *tz)
640695 return ret ;
641696 }
642697
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+
643705 if (!tz -> tzp ) {
644706 tz -> tzp = kzalloc (sizeof (* tz -> tzp ), GFP_KERNEL );
645707 if (!tz -> tzp ) {
@@ -664,6 +726,7 @@ static int power_allocator_bind(struct thermal_zone_device *tz)
664726 return 0 ;
665727
666728free_params :
729+ kfree (params -> power );
667730 kfree (params );
668731
669732 return ret ;
@@ -680,6 +743,7 @@ static void power_allocator_unbind(struct thermal_zone_device *tz)
680743 tz -> tzp = NULL ;
681744 }
682745
746+ kfree (params -> power );
683747 kfree (tz -> governor_data );
684748 tz -> governor_data = NULL ;
685749}
@@ -718,5 +782,6 @@ static struct thermal_governor thermal_gov_power_allocator = {
718782 .bind_to_tz = power_allocator_bind ,
719783 .unbind_from_tz = power_allocator_unbind ,
720784 .throttle = power_allocator_throttle ,
785+ .update_tz = power_allocator_update_tz ,
721786};
722787THERMAL_GOVERNOR_DECLARE (thermal_gov_power_allocator );
0 commit comments