All of lore.kernel.org
 help / color / mirror / Atom feed
From: Vincent Donnefort <vincent.donnefort@arm.com>
To: peterz@infradead.org, rjw@rjwysocki.net, viresh.kumar@linaro.org,
	vincent.guittot@linaro.org, qperret@google.com
Cc: linux-pm@vger.kernel.org, ionela.voinescu@arm.com,
	lukasz.luba@arm.com, dietmar.eggemann@arm.com, mka@chromium.org,
	Vincent Donnefort <vincent.donnefort@arm.com>
Subject: [PATCH v4 8/9] cpufreq: Add driver flag CPUFREQ_READ_ENERGY_MODEL
Date: Thu,  8 Jul 2021 11:09:05 +0100	[thread overview]
Message-ID: <1625738946-295849-9-git-send-email-vincent.donnefort@arm.com> (raw)
In-Reply-To: <1625738946-295849-1-git-send-email-vincent.donnefort@arm.com>

The Energy Model has a 1:1 mapping between OPPs and performance states
(em_perf_state). If a CPUFreq driver registers an Energy Model, the
inefficiencies found by the latter can apply to CPUFreq.
CPUFREQ_READ_ENERGY_MODEL allows, during registration, to read those
inefficiencies and mark the freq-table accordingly.

If a driver that set CPUFREQ_READ_ENERGY_MODEL, doesn't use a custom
->target() callback, CPUFreq can handle skipping inefficient frequencies
on its own and will automatically enable the freq-table relation
CPUFREQ_RELATION_E.

If CPUFREQ_RELATION_E is enabled, CPUFreq will let the Energy Model know
inefficiencies shouldn't be taken into account for the energy estimation.

Signed-off-by: Vincent Donnefort <vincent.donnefort@arm.com>

diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index f8d01d083df0..cb8950da4a47 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -19,6 +19,7 @@
 #include <linux/cpu_cooling.h>
 #include <linux/delay.h>
 #include <linux/device.h>
+#include <linux/energy_model.h>
 #include <linux/init.h>
 #include <linux/kernel_stat.h>
 #include <linux/module.h>
@@ -1313,6 +1314,58 @@ static void cpufreq_policy_free(struct cpufreq_policy *policy)
 	kfree(policy);
 }
 
+static inline void
+cpufreq_read_inefficiencies_from_em(struct cpufreq_policy *policy,
+				    struct em_perf_domain *em_pd)
+{
+	struct cpufreq_frequency_table *pos, *table = policy->freq_table;
+	struct em_perf_state *em_table;
+	bool found = false;
+	int i;
+
+	if (!(cpufreq_driver->flags & CPUFREQ_READ_ENERGY_MODEL))
+		return;
+
+	if (!em_pd) {
+		pr_warn("CPUFreq driver wants to read inefficiencies from the Energy Model but none found\n");
+		return;
+	}
+
+	em_table = em_pd->table;
+
+	for (i = 0; i < em_pd->nr_perf_states; i++) {
+		if (!(em_table[i].flags & EM_PERF_STATE_INEFFICIENT))
+			continue;
+
+		cpufreq_for_each_valid_entry(pos, table) {
+			if (pos->frequency == em_table[i].frequency) {
+				pos->flags |= CPUFREQ_INEFFICIENT_FREQ;
+				found = true;
+				break;
+			}
+		}
+	}
+
+	if (!found)
+		return;
+
+	/*
+	 * If the driver does not use a custom ->target() callback, we can
+	 * automatically enable CPUFREQ_RELATION_E, supported by the default
+	 * function cpufreq_frequency_table_target(). Otherwise, the driver
+	 * must set this flag itself.
+	 */
+	if (!cpufreq_driver->target)
+		policy->relation_efficient = true;
+
+	/*
+	 * With CPUFREQ_RELATION_E enabled, inefficient frequencies will be
+	 * skipped. Let know the Energy Model it can skip them too.
+	 */
+	if (policy->relation_efficient)
+		em_pd->flags |= EM_PERF_DOMAIN_SKIP_INEFFICIENCIES;
+}
+
 static int cpufreq_online(unsigned int cpu)
 {
 	struct cpufreq_policy *policy;
@@ -1367,6 +1420,12 @@ static int cpufreq_online(unsigned int cpu)
 			goto out_free_policy;
 		}
 
+		/*
+		 * Sync potential inefficiencies with the Energy Model if the
+		 * driver requested CPUFREQ_READ_ENERGY_MODEL.
+		 */
+		cpufreq_read_inefficiencies_from_em(policy, em_cpu_get(cpu));
+
 		ret = cpufreq_table_validate_and_sort(policy);
 		if (ret)
 			goto out_exit_policy;
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
index 0110408fcf2d..f5e94207094c 100644
--- a/include/linux/cpufreq.h
+++ b/include/linux/cpufreq.h
@@ -440,6 +440,14 @@ struct cpufreq_driver {
  */
 #define CPUFREQ_NO_AUTO_DYNAMIC_SWITCHING	BIT(6)
 
+/*
+ * Set by drivers which register an Energy Model and want to use the latter to
+ * populate the freq-table with inefficiency information. If the same driver
+ * is not implementing the ->target() callback, setting this flag will also
+ * automatically enable CPUFREQ_RELATION_E.
+ */
+#define CPUFREQ_READ_ENERGY_MODEL		BIT(7)
+
 int cpufreq_register_driver(struct cpufreq_driver *driver_data);
 int cpufreq_unregister_driver(struct cpufreq_driver *driver_data);
 
-- 
2.7.4


  parent reply	other threads:[~2021-07-08 10:09 UTC|newest]

Thread overview: 31+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-07-08 10:08 [PATCH v4 0/9] Inefficient OPPs Vincent Donnefort
2021-07-08 10:08 ` [PATCH v4 1/9] PM / EM: Fix inefficient states detection Vincent Donnefort
2021-07-08 10:08 ` [PATCH v4 2/9] PM / EM: Mark inefficient states Vincent Donnefort
2021-07-22  7:25   ` Lukasz Luba
2021-07-08 10:09 ` [PATCH v4 3/9] PM / EM: Extend em_perf_domain with a flag field Vincent Donnefort
2021-07-22  7:27   ` Lukasz Luba
2021-07-08 10:09 ` [PATCH v4 4/9] PM / EM: Allow skipping inefficient states Vincent Donnefort
2021-07-22 13:09   ` Lukasz Luba
2021-07-08 10:09 ` [PATCH v4 5/9] cpufreq: Add an interface to mark inefficient frequencies Vincent Donnefort
2021-07-08 10:09 ` [PATCH v4 6/9] cpufreq: Add a new freq-table relation CPUFREQ_RELATION_E Vincent Donnefort
2021-07-22  8:17   ` Lukasz Luba
2021-07-08 10:09 ` [PATCH v4 7/9] cpufreq: CPUFREQ_RELATION_E in schedutil ondemand and conservative Vincent Donnefort
2021-07-08 10:09 ` Vincent Donnefort [this message]
2021-07-08 10:09 ` [PATCH v4 9/9] cpufreq: dt: Add CPUFREQ_READ_ENERGY_MODEL Vincent Donnefort
2021-08-04 16:21 ` [PATCH v4 0/9] Inefficient OPPs Rafael J. Wysocki
2021-08-10  6:13   ` Viresh Kumar
2021-08-10  7:39     ` Viresh Kumar
2021-08-10 12:28     ` Lukasz Luba
2021-08-10 14:07       ` Quentin Perret
2021-08-10 14:18         ` Lukasz Luba
2021-08-10 15:12           ` Lukasz Luba
2021-08-10 15:47             ` Quentin Perret
2021-08-11  5:03               ` Viresh Kumar
2021-08-11 11:38                 ` Lukasz Luba
2021-08-16 14:35                   ` Rafael J. Wysocki
2021-08-17  7:09                     ` Viresh Kumar
2021-08-11  4:01       ` Viresh Kumar
2021-08-16 14:19     ` Rafael J. Wysocki
2021-08-17  7:06       ` Viresh Kumar
2021-08-17  9:03         ` Lukasz Luba
2021-08-23 17:06           ` Vincent Donnefort

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1625738946-295849-9-git-send-email-vincent.donnefort@arm.com \
    --to=vincent.donnefort@arm.com \
    --cc=dietmar.eggemann@arm.com \
    --cc=ionela.voinescu@arm.com \
    --cc=linux-pm@vger.kernel.org \
    --cc=lukasz.luba@arm.com \
    --cc=mka@chromium.org \
    --cc=peterz@infradead.org \
    --cc=qperret@google.com \
    --cc=rjw@rjwysocki.net \
    --cc=vincent.guittot@linaro.org \
    --cc=viresh.kumar@linaro.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.