2019-05-27 09:55:15 +03:00
// SPDX-License-Identifier: GPL-2.0-only
2012-09-18 09:35:01 +04:00
/*
* fair_share . c - A simple weight based Thermal governor
*
* Copyright ( C ) 2012 Intel Corp
* Copyright ( C ) 2012 Durgadoss R < durgadoss . r @ intel . com >
*
* ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
*
* ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
*/
# include <linux/thermal.h>
2014-07-29 14:50:50 +04:00
# include <trace/events/thermal.h>
2012-09-18 09:35:01 +04:00
# include "thermal_core.h"
/**
* get_trip_level : - obtains the current trip level for a zone
* @ tz : thermal zone device
*/
static int get_trip_level ( struct thermal_zone_device * tz )
{
int count = 0 ;
2015-07-24 09:12:54 +03:00
int trip_temp ;
2014-07-29 14:50:50 +04:00
enum thermal_trip_type trip_type ;
2012-09-18 09:35:01 +04:00
2022-07-22 23:00:04 +03:00
if ( tz - > num_trips = = 0 | | ! tz - > ops - > get_trip_temp )
2012-09-18 09:35:01 +04:00
return 0 ;
2022-07-22 23:00:04 +03:00
for ( count = 0 ; count < tz - > num_trips ; count + + ) {
2012-09-18 09:35:01 +04:00
tz - > ops - > get_trip_temp ( tz , count , & trip_temp ) ;
if ( tz - > temperature < trip_temp )
break ;
}
2014-07-29 14:50:50 +04:00
/*
* count > 0 only if temperature is greater than first trip
* point , in which case , trip_point = count - 1
*/
if ( count > 0 ) {
tz - > ops - > get_trip_type ( tz , count - 1 , & trip_type ) ;
trace_thermal_zone_trip ( tz , count - 1 , trip_type ) ;
}
2012-09-18 09:35:01 +04:00
return count ;
}
static long get_target_state ( struct thermal_zone_device * tz ,
2015-02-18 19:04:25 +03:00
struct thermal_cooling_device * cdev , int percentage , int level )
2012-09-18 09:35:01 +04:00
{
2022-10-17 13:03:01 +03:00
return ( long ) ( percentage * level * cdev - > max_state ) / ( 100 * tz - > num_trips ) ;
2012-09-18 09:35:01 +04:00
}
/**
2015-02-18 19:04:23 +03:00
* fair_share_throttle - throttles devices associated with the given zone
2019-11-20 18:45:12 +03:00
* @ tz : thermal_zone_device
* @ trip : trip point index
2012-09-18 09:35:01 +04:00
*
* Throttling Logic : This uses three parameters to calculate the new
* throttle state of the cooling devices associated with the given zone .
*
* Parameters used for Throttling :
* P1 . max_state : Maximum throttle state exposed by the cooling device .
2015-02-18 19:04:25 +03:00
* P2 . percentage [ i ] / 100 :
2012-09-18 09:35:01 +04:00
* How ' effective ' the ' i ' th device is , in cooling the given zone .
* P3 . cur_trip_level / max_no_of_trips :
* This describes the extent to which the devices should be throttled .
* We do not want to throttle too much when we trip a lower temperature ,
* whereas the throttling is at full swing if we trip critical levels .
* ( Heavily assumes the trip points are in ascending order )
* new_state of cooling device = P3 * P2 * P1
*/
2012-09-27 15:27:53 +04:00
static int fair_share_throttle ( struct thermal_zone_device * tz , int trip )
2012-09-18 09:35:01 +04:00
{
struct thermal_instance * instance ;
2015-02-18 19:04:25 +03:00
int total_weight = 0 ;
int total_instance = 0 ;
2012-09-18 09:35:01 +04:00
int cur_trip_level = get_trip_level ( tz ) ;
2022-08-05 18:38:33 +03:00
lockdep_assert_held ( & tz - > lock ) ;
2021-04-22 18:36:22 +03:00
2015-02-18 19:04:22 +03:00
list_for_each_entry ( instance , & tz - > thermal_instances , tz_node ) {
2015-02-18 19:04:25 +03:00
if ( instance - > trip ! = trip )
continue ;
total_weight + = instance - > weight ;
total_instance + + ;
}
list_for_each_entry ( instance , & tz - > thermal_instances , tz_node ) {
int percentage ;
2015-02-18 19:04:22 +03:00
struct thermal_cooling_device * cdev = instance - > cdev ;
2012-09-18 09:35:01 +04:00
2015-02-18 19:04:22 +03:00
if ( instance - > trip ! = trip )
2012-09-18 09:35:01 +04:00
continue ;
2015-02-18 19:04:25 +03:00
if ( ! total_weight )
percentage = 100 / total_instance ;
else
percentage = ( instance - > weight * 100 ) / total_weight ;
instance - > target = get_target_state ( tz , cdev , percentage ,
cur_trip_level ) ;
2012-09-18 09:35:01 +04:00
2021-04-22 18:36:23 +03:00
mutex_lock ( & cdev - > lock ) ;
__thermal_cdev_update ( cdev ) ;
mutex_unlock ( & cdev - > lock ) ;
2012-09-18 09:35:01 +04:00
}
2021-04-22 18:36:22 +03:00
2012-09-18 09:35:01 +04:00
return 0 ;
}
2012-09-27 15:27:53 +04:00
static struct thermal_governor thermal_gov_fair_share = {
2012-09-18 09:35:01 +04:00
. name = " fair_share " ,
. throttle = fair_share_throttle ,
} ;
2019-06-12 23:13:25 +03:00
THERMAL_GOVERNOR_DECLARE ( thermal_gov_fair_share ) ;