PM: EM: Mark inefficient states
authorVincent Donnefort <vincent.donnefort@arm.com>
Wed, 8 Sep 2021 14:05:23 +0000 (15:05 +0100)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Tue, 5 Oct 2021 14:33:05 +0000 (16:33 +0200)
Some SoCs, such as the sd855 have OPPs within the same performance domain,
whose cost is higher than others with a higher frequency. Even though
those OPPs are interesting from a cooling perspective, it makes no sense
to use them when the device can run at full capacity. Those OPPs handicap
the performance domain, when choosing the most energy-efficient CPU and
are wasting energy. They are inefficient.

Hence, add support for such OPPs to the Energy Model. The table can now
be read skipping inefficient performance states (and by extension,
inefficient OPPs).

Signed-off-by: Vincent Donnefort <vincent.donnefort@arm.com>
Reviewed-by: Matthias Kaehlcke <mka@chromium.org>
Reviewed-by: Lukasz Luba <lukasz.luba@arm.com>
Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
include/linux/energy_model.h
kernel/power/energy_model.c

index 39dcadd492b53b23ee93ae604414339fa1420675..3641ca4acf04282779f19bd9d04c1aa6fe3e44c3 100644 (file)
  *             device). It can be a total power: static and dynamic.
  * @cost:      The cost coefficient associated with this level, used during
  *             energy calculation. Equal to: power * max_frequency / frequency
+ * @flags:     see "em_perf_state flags" description below.
  */
 struct em_perf_state {
        unsigned long frequency;
        unsigned long power;
        unsigned long cost;
+       unsigned long flags;
 };
 
+/*
+ * em_perf_state flags:
+ *
+ * EM_PERF_STATE_INEFFICIENT: The performance state is inefficient. There is
+ * in this em_perf_domain, another performance state with a higher frequency
+ * but a lower or equal power cost. Such inefficient states are ignored when
+ * using em_pd_get_efficient_*() functions.
+ */
+#define EM_PERF_STATE_INEFFICIENT BIT(0)
+
 /**
  * struct em_perf_domain - Performance domain
  * @table:             List of performance states, in ascending order
index 97e62469a6b32fc2ceb14c71473270106eca5cf2..6d843834753533681b9b873b263a058e6b013ec1 100644 (file)
@@ -2,7 +2,7 @@
 /*
  * Energy Model of devices
  *
- * Copyright (c) 2018-2020, Arm ltd.
+ * Copyright (c) 2018-2021, Arm ltd.
  * Written by: Quentin Perret, Arm ltd.
  * Improvements provided by: Lukasz Luba, Arm ltd.
  */
@@ -42,6 +42,7 @@ static void em_debug_create_ps(struct em_perf_state *ps, struct dentry *pd)
        debugfs_create_ulong("frequency", 0444, d, &ps->frequency);
        debugfs_create_ulong("power", 0444, d, &ps->power);
        debugfs_create_ulong("cost", 0444, d, &ps->cost);
+       debugfs_create_ulong("inefficient", 0444, d, &ps->flags);
 }
 
 static int em_debug_cpus_show(struct seq_file *s, void *unused)
@@ -162,6 +163,7 @@ static int em_create_perf_table(struct device *dev, struct em_perf_domain *pd,
                table[i].cost = div64_u64(fmax * power_res,
                                          table[i].frequency);
                if (table[i].cost >= prev_cost) {
+                       table[i].flags = EM_PERF_STATE_INEFFICIENT;
                        dev_dbg(dev, "EM: OPP:%lu is inefficient\n",
                                table[i].frequency);
                } else {