Commit 8354eb9e authored by Vincent Donnefort's avatar Vincent Donnefort Committed by Rafael J. Wysocki

PM: EM: Allow skipping inefficient states

The new performance domain flag EM_PERF_DOMAIN_SKIP_INEFFICIENCIES allows
to not take into account inefficient states when estimating energy
consumption. This intends to let the Energy Model know that CPUFreq itself
will skip inefficiencies and such states don't need to be part of the
estimation anymore.
Signed-off-by: default avatarVincent Donnefort <vincent.donnefort@arm.com>
Reviewed-by: default avatarLukasz Luba <lukasz.luba@arm.com>
Acked-by: default avatarViresh Kumar <viresh.kumar@linaro.org>
Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
parent 88f7a895
...@@ -64,8 +64,12 @@ struct em_perf_domain { ...@@ -64,8 +64,12 @@ struct em_perf_domain {
* *
* EM_PERF_DOMAIN_MILLIWATTS: The power values are in milli-Watts or some * EM_PERF_DOMAIN_MILLIWATTS: The power values are in milli-Watts or some
* other scale. * other scale.
*
* EM_PERF_DOMAIN_SKIP_INEFFICIENCIES: Skip inefficient states when estimating
* energy consumption.
*/ */
#define EM_PERF_DOMAIN_MILLIWATTS BIT(0) #define EM_PERF_DOMAIN_MILLIWATTS BIT(0)
#define EM_PERF_DOMAIN_SKIP_INEFFICIENCIES BIT(1)
#define em_span_cpus(em) (to_cpumask((em)->cpus)) #define em_span_cpus(em) (to_cpumask((em)->cpus))
...@@ -120,6 +124,37 @@ int em_dev_register_perf_domain(struct device *dev, unsigned int nr_states, ...@@ -120,6 +124,37 @@ int em_dev_register_perf_domain(struct device *dev, unsigned int nr_states,
bool milliwatts); bool milliwatts);
void em_dev_unregister_perf_domain(struct device *dev); void em_dev_unregister_perf_domain(struct device *dev);
/**
* em_pd_get_efficient_state() - Get an efficient performance state from the EM
* @pd : Performance domain for which we want an efficient frequency
* @freq : Frequency to map with the EM
*
* It is called from the scheduler code quite frequently and as a consequence
* doesn't implement any check.
*
* Return: An efficient performance state, high enough to meet @freq
* requirement.
*/
static inline
struct em_perf_state *em_pd_get_efficient_state(struct em_perf_domain *pd,
unsigned long freq)
{
struct em_perf_state *ps;
int i;
for (i = 0; i < pd->nr_perf_states; i++) {
ps = &pd->table[i];
if (ps->frequency >= freq) {
if (pd->flags & EM_PERF_DOMAIN_SKIP_INEFFICIENCIES &&
ps->flags & EM_PERF_STATE_INEFFICIENT)
continue;
break;
}
}
return ps;
}
/** /**
* em_cpu_energy() - Estimates the energy consumed by the CPUs of a * em_cpu_energy() - Estimates the energy consumed by the CPUs of a
* performance domain * performance domain
...@@ -142,7 +177,7 @@ static inline unsigned long em_cpu_energy(struct em_perf_domain *pd, ...@@ -142,7 +177,7 @@ static inline unsigned long em_cpu_energy(struct em_perf_domain *pd,
{ {
unsigned long freq, scale_cpu; unsigned long freq, scale_cpu;
struct em_perf_state *ps; struct em_perf_state *ps;
int i, cpu; int cpu;
if (!sum_util) if (!sum_util)
return 0; return 0;
...@@ -167,11 +202,7 @@ static inline unsigned long em_cpu_energy(struct em_perf_domain *pd, ...@@ -167,11 +202,7 @@ static inline unsigned long em_cpu_energy(struct em_perf_domain *pd,
* Find the lowest performance state of the Energy Model above the * Find the lowest performance state of the Energy Model above the
* requested frequency. * requested frequency.
*/ */
for (i = 0; i < pd->nr_perf_states; i++) { ps = em_pd_get_efficient_state(pd, freq);
ps = &pd->table[i];
if (ps->frequency >= freq)
break;
}
/* /*
* The capacity of a CPU in the domain at the performance state (ps) * The capacity of a CPU in the domain at the performance state (ps)
......
...@@ -65,6 +65,17 @@ static int em_debug_units_show(struct seq_file *s, void *unused) ...@@ -65,6 +65,17 @@ static int em_debug_units_show(struct seq_file *s, void *unused)
} }
DEFINE_SHOW_ATTRIBUTE(em_debug_units); DEFINE_SHOW_ATTRIBUTE(em_debug_units);
static int em_debug_skip_inefficiencies_show(struct seq_file *s, void *unused)
{
struct em_perf_domain *pd = s->private;
int enabled = (pd->flags & EM_PERF_DOMAIN_SKIP_INEFFICIENCIES) ? 1 : 0;
seq_printf(s, "%d\n", enabled);
return 0;
}
DEFINE_SHOW_ATTRIBUTE(em_debug_skip_inefficiencies);
static void em_debug_create_pd(struct device *dev) static void em_debug_create_pd(struct device *dev)
{ {
struct dentry *d; struct dentry *d;
...@@ -78,6 +89,8 @@ static void em_debug_create_pd(struct device *dev) ...@@ -78,6 +89,8 @@ static void em_debug_create_pd(struct device *dev)
&em_debug_cpus_fops); &em_debug_cpus_fops);
debugfs_create_file("units", 0444, d, dev->em_pd, &em_debug_units_fops); debugfs_create_file("units", 0444, d, dev->em_pd, &em_debug_units_fops);
debugfs_create_file("skip-inefficiencies", 0444, d, dev->em_pd,
&em_debug_skip_inefficiencies_fops);
/* Create a sub-directory for each performance state */ /* Create a sub-directory for each performance state */
for (i = 0; i < dev->em_pd->nr_perf_states; i++) for (i = 0; i < dev->em_pd->nr_perf_states; i++)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment