[PATCH 15/16] firmware: arm_scmi: Extend perf support with OPP from genpd providers

Ulf Hansson ulf.hansson at linaro.org
Wed Jun 7 05:46:27 PDT 2023


To enable a genpd provider to add OPPs for its attached devices,  let's
convert into using the dev_pm_opp_add_dynamic() API, in favor of the
current dev_pm_opp_add() API. This allows us to specify the frequency, the
performance level and the OPP provider type for each OPP that it may be
adding.

Moreover, to let callers of the ->device_opps_add() ops, to specify the OPP
provider let's add a new in-parameter to it.

Signed-off-by: Ulf Hansson <ulf.hansson at linaro.org>
---
 drivers/cpufreq/scmi-cpufreq.c   |  2 +-
 drivers/firmware/arm_scmi/perf.c | 15 ++++++++++-----
 include/linux/scmi_protocol.h    |  2 +-
 3 files changed, 12 insertions(+), 7 deletions(-)

diff --git a/drivers/cpufreq/scmi-cpufreq.c b/drivers/cpufreq/scmi-cpufreq.c
index 78f53e388094..a3f89a4ca899 100644
--- a/drivers/cpufreq/scmi-cpufreq.c
+++ b/drivers/cpufreq/scmi-cpufreq.c
@@ -188,7 +188,7 @@ static int scmi_cpufreq_init(struct cpufreq_policy *policy)
 	  */
 	nr_opp = dev_pm_opp_get_opp_count(cpu_dev);
 	if (nr_opp <= 0) {
-		ret = perf_ops->device_opps_add(ph, cpu_dev, domain);
+		ret = perf_ops->device_opps_add(ph, cpu_dev, domain, false);
 		if (ret) {
 			dev_warn(cpu_dev, "failed to add opps to the device\n");
 			goto out_free_cpumask;
diff --git a/drivers/firmware/arm_scmi/perf.c b/drivers/firmware/arm_scmi/perf.c
index 03a496ccc603..b6cebe45fbc8 100644
--- a/drivers/firmware/arm_scmi/perf.c
+++ b/drivers/firmware/arm_scmi/perf.c
@@ -581,21 +581,26 @@ static void scmi_perf_domain_init_fc(const struct scmi_protocol_handle *ph,
 }
 
 static int scmi_dvfs_device_opps_add(const struct scmi_protocol_handle *ph,
-				     struct device *dev, u32 domain)
+				     struct device *dev, u32 domain, bool genpd)
 {
 	int idx, ret;
-	unsigned long freq;
+	struct dev_pm_opp_data opp_data;
 	struct perf_dom_info *dom;
 	struct scmi_perf_info *pi = ph->get_priv(ph);
 
 	dom = pi->dom_info + domain;
 
 	for (idx = 0; idx < dom->opp_count; idx++) {
-		freq = dom->opp[idx].perf * dom->mult_factor;
+		memset(&opp_data, 0, sizeof(opp_data));
+		opp_data.level = dom->opp[idx].perf;
+		opp_data.freq = dom->opp[idx].perf * dom->mult_factor;
+		opp_data.provider = genpd ? DEV_PM_OPP_TYPE_GENPD :
+					    DEV_PM_OPP_TYPE_NONE;
 
-		ret = dev_pm_opp_add(dev, freq, 0);
+		ret = dev_pm_opp_add_dynamic(dev, &opp_data);
 		if (ret) {
-			dev_warn(dev, "failed to add opp %luHz\n", freq);
+			dev_warn(dev, "failed to add opp %luHz\n",
+				 opp_data.freq);
 			dev_pm_opp_remove_all_dynamic(dev);
 			return ret;
 		}
diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h
index 21aea1b2a355..ec421107f94c 100644
--- a/include/linux/scmi_protocol.h
+++ b/include/linux/scmi_protocol.h
@@ -136,7 +136,7 @@ struct scmi_perf_proto_ops {
 	int (*transition_latency_get)(const struct scmi_protocol_handle *ph,
 				      u32 domain);
 	int (*device_opps_add)(const struct scmi_protocol_handle *ph,
-			       struct device *dev, u32 domain);
+			       struct device *dev, u32 domain, bool genpd);
 	int (*freq_set)(const struct scmi_protocol_handle *ph, u32 domain,
 			unsigned long rate, bool poll);
 	int (*freq_get)(const struct scmi_protocol_handle *ph, u32 domain,
-- 
2.34.1




More information about the linux-arm-kernel mailing list