Commit 37f18831 authored by Viresh Kumar's avatar Viresh Kumar
Browse files

cpufreq: scmi: Use .register_em() to register with energy model



Set the newly added .register_em() callback to register with the EM
after the cpufreq policy is properly initialized.

Acked-by: default avatarSudeep Holla <sudeep.holla@arm.com>
Signed-off-by: default avatarViresh Kumar <viresh.kumar@linaro.org>
parent 3fd23111
Loading
Loading
Loading
Loading
+42 −23
Original line number Original line Diff line number Diff line
@@ -22,7 +22,9 @@


struct scmi_data {
struct scmi_data {
	int domain_id;
	int domain_id;
	int nr_opp;
	struct device *cpu_dev;
	struct device *cpu_dev;
	cpumask_var_t opp_shared_cpus;
};
};


static struct scmi_protocol_handle *ph;
static struct scmi_protocol_handle *ph;
@@ -123,9 +125,6 @@ static int scmi_cpufreq_init(struct cpufreq_policy *policy)
	struct device *cpu_dev;
	struct device *cpu_dev;
	struct scmi_data *priv;
	struct scmi_data *priv;
	struct cpufreq_frequency_table *freq_table;
	struct cpufreq_frequency_table *freq_table;
	struct em_data_callback em_cb = EM_DATA_CB(scmi_get_cpu_power);
	cpumask_var_t opp_shared_cpus;
	bool power_scale_mw;


	cpu_dev = get_cpu_device(policy->cpu);
	cpu_dev = get_cpu_device(policy->cpu);
	if (!cpu_dev) {
	if (!cpu_dev) {
@@ -133,9 +132,15 @@ static int scmi_cpufreq_init(struct cpufreq_policy *policy)
		return -ENODEV;
		return -ENODEV;
	}
	}


	if (!zalloc_cpumask_var(&opp_shared_cpus, GFP_KERNEL))
	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
	if (!priv)
		return -ENOMEM;
		return -ENOMEM;


	if (!zalloc_cpumask_var(&priv->opp_shared_cpus, GFP_KERNEL)) {
		ret = -ENOMEM;
		goto out_free_priv;
	}

	/* Obtain CPUs that share SCMI performance controls */
	/* Obtain CPUs that share SCMI performance controls */
	ret = scmi_get_sharing_cpus(cpu_dev, policy->cpus);
	ret = scmi_get_sharing_cpus(cpu_dev, policy->cpus);
	if (ret) {
	if (ret) {
@@ -148,14 +153,14 @@ static int scmi_cpufreq_init(struct cpufreq_policy *policy)
	 * The OPP 'sharing cpus' info may come from DT through an empty opp
	 * The OPP 'sharing cpus' info may come from DT through an empty opp
	 * table and opp-shared.
	 * table and opp-shared.
	 */
	 */
	ret = dev_pm_opp_of_get_sharing_cpus(cpu_dev, opp_shared_cpus);
	ret = dev_pm_opp_of_get_sharing_cpus(cpu_dev, priv->opp_shared_cpus);
	if (ret || !cpumask_weight(opp_shared_cpus)) {
	if (ret || !cpumask_weight(priv->opp_shared_cpus)) {
		/*
		/*
		 * Either opp-table is not set or no opp-shared was found.
		 * Either opp-table is not set or no opp-shared was found.
		 * Use the CPU mask from SCMI to designate CPUs sharing an OPP
		 * Use the CPU mask from SCMI to designate CPUs sharing an OPP
		 * table.
		 * table.
		 */
		 */
		cpumask_copy(opp_shared_cpus, policy->cpus);
		cpumask_copy(priv->opp_shared_cpus, policy->cpus);
	}
	}


	 /*
	 /*
@@ -180,7 +185,7 @@ static int scmi_cpufreq_init(struct cpufreq_policy *policy)
			goto out_free_opp;
			goto out_free_opp;
		}
		}


		ret = dev_pm_opp_set_sharing_cpus(cpu_dev, opp_shared_cpus);
		ret = dev_pm_opp_set_sharing_cpus(cpu_dev, priv->opp_shared_cpus);
		if (ret) {
		if (ret) {
			dev_err(cpu_dev, "%s: failed to mark OPPs as shared: %d\n",
			dev_err(cpu_dev, "%s: failed to mark OPPs as shared: %d\n",
				__func__, ret);
				__func__, ret);
@@ -188,21 +193,13 @@ static int scmi_cpufreq_init(struct cpufreq_policy *policy)
			goto out_free_opp;
			goto out_free_opp;
		}
		}


		power_scale_mw = perf_ops->power_scale_mw_get(ph);
		priv->nr_opp = nr_opp;
		em_dev_register_perf_domain(cpu_dev, nr_opp, &em_cb,
					    opp_shared_cpus, power_scale_mw);
	}

	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
	if (!priv) {
		ret = -ENOMEM;
		goto out_free_opp;
	}
	}


	ret = dev_pm_opp_init_cpufreq_table(cpu_dev, &freq_table);
	ret = dev_pm_opp_init_cpufreq_table(cpu_dev, &freq_table);
	if (ret) {
	if (ret) {
		dev_err(cpu_dev, "failed to init cpufreq table: %d\n", ret);
		dev_err(cpu_dev, "failed to init cpufreq table: %d\n", ret);
		goto out_free_priv;
		goto out_free_opp;
	}
	}


	priv->cpu_dev = cpu_dev;
	priv->cpu_dev = cpu_dev;
@@ -223,17 +220,16 @@ static int scmi_cpufreq_init(struct cpufreq_policy *policy)
	policy->fast_switch_possible =
	policy->fast_switch_possible =
		perf_ops->fast_switch_possible(ph, cpu_dev);
		perf_ops->fast_switch_possible(ph, cpu_dev);


	free_cpumask_var(opp_shared_cpus);
	return 0;
	return 0;


out_free_priv:
	kfree(priv);

out_free_opp:
out_free_opp:
	dev_pm_opp_remove_all_dynamic(cpu_dev);
	dev_pm_opp_remove_all_dynamic(cpu_dev);


out_free_cpumask:
out_free_cpumask:
	free_cpumask_var(opp_shared_cpus);
	free_cpumask_var(priv->opp_shared_cpus);

out_free_priv:
	kfree(priv);


	return ret;
	return ret;
}
}
@@ -244,11 +240,33 @@ static int scmi_cpufreq_exit(struct cpufreq_policy *policy)


	dev_pm_opp_free_cpufreq_table(priv->cpu_dev, &policy->freq_table);
	dev_pm_opp_free_cpufreq_table(priv->cpu_dev, &policy->freq_table);
	dev_pm_opp_remove_all_dynamic(priv->cpu_dev);
	dev_pm_opp_remove_all_dynamic(priv->cpu_dev);
	free_cpumask_var(priv->opp_shared_cpus);
	kfree(priv);
	kfree(priv);


	return 0;
	return 0;
}
}


static void scmi_cpufreq_register_em(struct cpufreq_policy *policy)
{
	struct em_data_callback em_cb = EM_DATA_CB(scmi_get_cpu_power);
	bool power_scale_mw = perf_ops->power_scale_mw_get(ph);
	struct scmi_data *priv = policy->driver_data;

	/*
	 * This callback will be called for each policy, but we don't need to
	 * register with EM every time. Despite not being part of the same
	 * policy, some CPUs may still share their perf-domains, and a CPU from
	 * another policy may already have registered with EM on behalf of CPUs
	 * of this policy.
	 */
	if (!priv->nr_opp)
		return;

	em_dev_register_perf_domain(get_cpu_device(policy->cpu), priv->nr_opp,
				    &em_cb, priv->opp_shared_cpus,
				    power_scale_mw);
}

static struct cpufreq_driver scmi_cpufreq_driver = {
static struct cpufreq_driver scmi_cpufreq_driver = {
	.name	= "scmi",
	.name	= "scmi",
	.flags	= CPUFREQ_HAVE_GOVERNOR_PER_POLICY |
	.flags	= CPUFREQ_HAVE_GOVERNOR_PER_POLICY |
@@ -261,6 +279,7 @@ static struct cpufreq_driver scmi_cpufreq_driver = {
	.get	= scmi_cpufreq_get_rate,
	.get	= scmi_cpufreq_get_rate,
	.init	= scmi_cpufreq_init,
	.init	= scmi_cpufreq_init,
	.exit	= scmi_cpufreq_exit,
	.exit	= scmi_cpufreq_exit,
	.register_em	= scmi_cpufreq_register_em,
};
};


static int scmi_cpufreq_probe(struct scmi_device *sdev)
static int scmi_cpufreq_probe(struct scmi_device *sdev)