Skip to content

Commit

Permalink
drivers/thermal/devfreq_cooling: Use new Energy Model interface
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Lukasz Luba authored and Rafael J. Wysocki committed Feb 8, 2024
1 parent 207472b commit 9f5fb51
Showing 1 changed file with 40 additions and 9 deletions.
49 changes: 40 additions & 9 deletions drivers/thermal/devfreq_cooling.c
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ static int devfreq_cooling_set_cur_state(struct thermal_cooling_device *cdev,
struct devfreq_cooling_device *dfc = cdev->devdata;
struct devfreq *df = dfc->devfreq;
struct device *dev = df->dev.parent;
struct em_perf_state *table;
unsigned long freq;
int perf_idx;

Expand All @@ -100,7 +101,11 @@ static int devfreq_cooling_set_cur_state(struct thermal_cooling_device *cdev,

if (dfc->em_pd) {
perf_idx = dfc->max_state - state;
freq = dfc->em_pd->table[perf_idx].frequency * 1000;

rcu_read_lock();
table = em_perf_state_from_pd(dfc->em_pd);
freq = table[perf_idx].frequency * 1000;
rcu_read_unlock();
} else {
freq = dfc->freq_table[state];
}
Expand All @@ -123,14 +128,21 @@ static int devfreq_cooling_set_cur_state(struct thermal_cooling_device *cdev,
*/
static int get_perf_idx(struct em_perf_domain *em_pd, unsigned long freq)
{
int i;
struct em_perf_state *table;
int i, idx = -EINVAL;

rcu_read_lock();
table = em_perf_state_from_pd(em_pd);
for (i = 0; i < em_pd->nr_perf_states; i++) {
if (em_pd->table[i].frequency == freq)
return i;
if (table[i].frequency != freq)
continue;

idx = i;
break;
}
rcu_read_unlock();

return -EINVAL;
return idx;
}

static unsigned long get_voltage(struct devfreq *df, unsigned long freq)
Expand Down Expand Up @@ -181,6 +193,7 @@ static int devfreq_cooling_get_requested_power(struct thermal_cooling_device *cd
struct devfreq_cooling_device *dfc = cdev->devdata;
struct devfreq *df = dfc->devfreq;
struct devfreq_dev_status status;
struct em_perf_state *table;
unsigned long state;
unsigned long freq;
unsigned long voltage;
Expand All @@ -204,7 +217,11 @@ static int devfreq_cooling_get_requested_power(struct thermal_cooling_device *cd
state = dfc->capped_state;

/* Convert EM power into milli-Watts first */
dfc->res_util = dfc->em_pd->table[state].power;
rcu_read_lock();
table = em_perf_state_from_pd(dfc->em_pd);
dfc->res_util = table[state].power;
rcu_read_unlock();

dfc->res_util /= MICROWATT_PER_MILLIWATT;

dfc->res_util *= SCALE_ERROR_MITIGATION;
Expand All @@ -225,7 +242,11 @@ static int devfreq_cooling_get_requested_power(struct thermal_cooling_device *cd
_normalize_load(&status);

/* Convert EM power into milli-Watts first */
*power = dfc->em_pd->table[perf_idx].power;
rcu_read_lock();
table = em_perf_state_from_pd(dfc->em_pd);
*power = table[perf_idx].power;
rcu_read_unlock();

*power /= MICROWATT_PER_MILLIWATT;
/* Scale power for utilization */
*power *= status.busy_time;
Expand All @@ -245,13 +266,19 @@ static int devfreq_cooling_state2power(struct thermal_cooling_device *cdev,
unsigned long state, u32 *power)
{
struct devfreq_cooling_device *dfc = cdev->devdata;
struct em_perf_state *table;
int perf_idx;

if (state > dfc->max_state)
return -EINVAL;

perf_idx = dfc->max_state - state;
*power = dfc->em_pd->table[perf_idx].power;

rcu_read_lock();
table = em_perf_state_from_pd(dfc->em_pd);
*power = table[perf_idx].power;
rcu_read_unlock();

*power /= MICROWATT_PER_MILLIWATT;

return 0;
Expand All @@ -264,6 +291,7 @@ static int devfreq_cooling_power2state(struct thermal_cooling_device *cdev,
struct devfreq *df = dfc->devfreq;
struct devfreq_dev_status status;
unsigned long freq, em_power_mw;
struct em_perf_state *table;
s32 est_power;
int i;

Expand All @@ -288,13 +316,16 @@ static int devfreq_cooling_power2state(struct thermal_cooling_device *cdev,
* Find the first cooling state that is within the power
* budget. The EM power table is sorted ascending.
*/
rcu_read_lock();
table = em_perf_state_from_pd(dfc->em_pd);
for (i = dfc->max_state; i > 0; i--) {
/* Convert EM power to milli-Watts to make safe comparison */
em_power_mw = dfc->em_pd->table[i].power;
em_power_mw = table[i].power;
em_power_mw /= MICROWATT_PER_MILLIWATT;
if (est_power >= em_power_mw)
break;
}
rcu_read_unlock();

*state = dfc->max_state - i;
dfc->capped_state = *state;
Expand Down

0 comments on commit 9f5fb51

Please sign in to comment.