drivers/thermal/cpufreq_cooling: Use new Energy Model interface

Energy Model framework support modifications at runtime of the power
values. Use the new EM table which is protected with RCU. Align the
code so that this RCU read section is short.

This change is not expected to alter the general functionality.

Reviewed-by: Dietmar Eggemann <dietmar.eggemann@arm.com>
Tested-by: Dietmar Eggemann <dietmar.eggemann@arm.com>
Signed-off-by: Lukasz Luba <lukasz.luba@arm.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
This commit is contained in:
Lukasz Luba 2024-02-08 11:55:52 +00:00 committed by Rafael J. Wysocki
parent 27d2c37e7d
commit 207472b8ef
1 changed files with 37 additions and 8 deletions

View File

@ -91,12 +91,16 @@ struct cpufreq_cooling_device {
static unsigned long get_level(struct cpufreq_cooling_device *cpufreq_cdev,
unsigned int freq)
{
struct em_perf_state *table;
int i;
rcu_read_lock();
table = em_perf_state_from_pd(cpufreq_cdev->em);
for (i = cpufreq_cdev->max_level - 1; i >= 0; i--) {
if (freq > cpufreq_cdev->em->table[i].frequency)
if (freq > table[i].frequency)
break;
}
rcu_read_unlock();
return cpufreq_cdev->max_level - i - 1;
}
@ -104,16 +108,20 @@ static unsigned long get_level(struct cpufreq_cooling_device *cpufreq_cdev,
static u32 cpu_freq_to_power(struct cpufreq_cooling_device *cpufreq_cdev,
u32 freq)
{
struct em_perf_state *table;
unsigned long power_mw;
int i;
rcu_read_lock();
table = em_perf_state_from_pd(cpufreq_cdev->em);
for (i = cpufreq_cdev->max_level - 1; i >= 0; i--) {
if (freq > cpufreq_cdev->em->table[i].frequency)
if (freq > table[i].frequency)
break;
}
power_mw = cpufreq_cdev->em->table[i + 1].power;
power_mw = table[i + 1].power;
power_mw /= MICROWATT_PER_MILLIWATT;
rcu_read_unlock();
return power_mw;
}
@ -121,18 +129,24 @@ static u32 cpu_freq_to_power(struct cpufreq_cooling_device *cpufreq_cdev,
static u32 cpu_power_to_freq(struct cpufreq_cooling_device *cpufreq_cdev,
u32 power)
{
struct em_perf_state *table;
unsigned long em_power_mw;
u32 freq;
int i;
rcu_read_lock();
table = em_perf_state_from_pd(cpufreq_cdev->em);
for (i = cpufreq_cdev->max_level; i > 0; i--) {
/* Convert EM power to milli-Watts to make safe comparison */
em_power_mw = cpufreq_cdev->em->table[i].power;
em_power_mw = table[i].power;
em_power_mw /= MICROWATT_PER_MILLIWATT;
if (power >= em_power_mw)
break;
}
freq = table[i].frequency;
rcu_read_unlock();
return cpufreq_cdev->em->table[i].frequency;
return freq;
}
/**
@ -262,8 +276,9 @@ static int cpufreq_get_requested_power(struct thermal_cooling_device *cdev,
static int cpufreq_state2power(struct thermal_cooling_device *cdev,
unsigned long state, u32 *power)
{
unsigned int freq, num_cpus, idx;
struct cpufreq_cooling_device *cpufreq_cdev = cdev->devdata;
unsigned int freq, num_cpus, idx;
struct em_perf_state *table;
/* Request state should be less than max_level */
if (state > cpufreq_cdev->max_level)
@ -272,7 +287,12 @@ static int cpufreq_state2power(struct thermal_cooling_device *cdev,
num_cpus = cpumask_weight(cpufreq_cdev->policy->cpus);
idx = cpufreq_cdev->max_level - state;
freq = cpufreq_cdev->em->table[idx].frequency;
rcu_read_lock();
table = em_perf_state_from_pd(cpufreq_cdev->em);
freq = table[idx].frequency;
rcu_read_unlock();
*power = cpu_freq_to_power(cpufreq_cdev, freq) * num_cpus;
return 0;
@ -378,8 +398,17 @@ static unsigned int get_state_freq(struct cpufreq_cooling_device *cpufreq_cdev,
#ifdef CONFIG_THERMAL_GOV_POWER_ALLOCATOR
/* Use the Energy Model table if available */
if (cpufreq_cdev->em) {
struct em_perf_state *table;
unsigned int freq;
idx = cpufreq_cdev->max_level - state;
return cpufreq_cdev->em->table[idx].frequency;
rcu_read_lock();
table = em_perf_state_from_pd(cpufreq_cdev->em);
freq = table[idx].frequency;
rcu_read_unlock();
return freq;
}
#endif