Message ID | 20210215075139.30772-3-nicola.mazzucato@arm.com (mailing list archive) |
---|---|
State | New, archived |
Delegated to: | viresh kumar |
Headers | show |
Series | CPUFreq: Add support for opp-sharing cpus | expand |
On 15-02-21, 07:51, Nicola Mazzucato wrote: > + /* > + * Add OPPs only on those CPUs for which we haven't already done so. > + */ > nr_opp = dev_pm_opp_get_opp_count(cpu_dev); Please add a more detailed comment here explaining why you expect OPPs to be present here in advance. i.e. you _may_ have policy per CPU even though OPP core says OPPs are shared.. It is not straight forward to catch otherwise. > if (nr_opp <= 0) { > - dev_err(cpu_dev, "%s: No OPPs for this device: %d\n", > - __func__, ret); > - > - ret = -ENODEV; > - goto out_free_priv; > + ret = handle->perf_ops->device_opps_add(handle, cpu_dev); > + if (ret) { > + dev_warn(cpu_dev, "failed to add opps to the device\n"); > + goto out_free_cpumask; > + } > + > + nr_opp = dev_pm_opp_get_opp_count(cpu_dev); > + if (nr_opp <= 0) { > + dev_err(cpu_dev, "%s: No OPPs for this device: %d\n", > + __func__, ret); > + > + ret = -ENODEV; > + goto out_free_opp; > + } > + > + ret = dev_pm_opp_set_sharing_cpus(cpu_dev, opp_shared_cpus); > + if (ret) { > + dev_err(cpu_dev, "%s: failed to mark OPPs as shared: %d\n", > + __func__, ret); > + > + goto out_free_opp; > + } > + > + power_scale_mw = handle->perf_ops->power_scale_mw_get(handle); > + em_dev_register_perf_domain(cpu_dev, nr_opp, &em_cb, > + opp_shared_cpus, power_scale_mw); > }
Hi Viresh, On 2/18/21 11:00 AM, Viresh Kumar wrote: > On 15-02-21, 07:51, Nicola Mazzucato wrote: >> + /* >> + * Add OPPs only on those CPUs for which we haven't already done so. >> + */ >> nr_opp = dev_pm_opp_get_opp_count(cpu_dev); > > Please add a more detailed comment here explaining why you expect OPPs > to be present here in advance. i.e. you _may_ have policy per CPU even > though OPP core says OPPs are shared.. It is not straight forward to > catch otherwise. Sure, I'll put more details, thanks. > >> if (nr_opp <= 0) { >> - dev_err(cpu_dev, "%s: No OPPs for this device: %d\n", >> - __func__, ret); >> - >> - ret = -ENODEV; >> - goto out_free_priv; >> + ret = handle->perf_ops->device_opps_add(handle, cpu_dev); >> + if (ret) { >> + dev_warn(cpu_dev, "failed to add opps to the device\n"); >> + goto out_free_cpumask; >> + } >> + >> + nr_opp = dev_pm_opp_get_opp_count(cpu_dev); >> + if (nr_opp <= 0) { >> + dev_err(cpu_dev, "%s: No OPPs for this device: %d\n", >> + __func__, ret); >> + >> + ret = -ENODEV; >> + goto out_free_opp; >> + } >> + >> + ret = dev_pm_opp_set_sharing_cpus(cpu_dev, opp_shared_cpus); >> + if (ret) { >> + dev_err(cpu_dev, "%s: failed to mark OPPs as shared: %d\n", >> + __func__, ret); >> + >> + goto out_free_opp; >> + } >> + >> + power_scale_mw = handle->perf_ops->power_scale_mw_get(handle); >> + em_dev_register_perf_domain(cpu_dev, nr_opp, &em_cb, >> + opp_shared_cpus, power_scale_mw); >> } >
diff --git a/drivers/cpufreq/scmi-cpufreq.c b/drivers/cpufreq/scmi-cpufreq.c index 34bf2eb8d465..fc9866511f01 100644 --- a/drivers/cpufreq/scmi-cpufreq.c +++ b/drivers/cpufreq/scmi-cpufreq.c @@ -126,6 +126,7 @@ static int scmi_cpufreq_init(struct cpufreq_policy *policy) struct scmi_data *priv; 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); @@ -134,32 +135,62 @@ static int scmi_cpufreq_init(struct cpufreq_policy *policy) return -ENODEV; } - ret = handle->perf_ops->device_opps_add(handle, cpu_dev); - if (ret) { - dev_warn(cpu_dev, "failed to add opps to the device\n"); - return ret; - } + if (!zalloc_cpumask_var(&opp_shared_cpus, GFP_KERNEL)) + ret = -ENOMEM; + /* Obtain CPUs that share SCMI performance controls */ ret = scmi_get_sharing_cpus(cpu_dev, policy->cpus); if (ret) { dev_warn(cpu_dev, "failed to get sharing cpumask\n"); - return ret; + goto out_free_cpumask; } - ret = dev_pm_opp_set_sharing_cpus(cpu_dev, policy->cpus); - if (ret) { - dev_err(cpu_dev, "%s: failed to mark OPPs as shared: %d\n", - __func__, ret); - return ret; + /* + * Obtain CPUs that share performance levels. + * The OPP 'sharing cpus' info may come from DT through an empty opp + * table and opp-shared. + */ + ret = dev_pm_opp_of_get_sharing_cpus(cpu_dev, opp_shared_cpus); + if (ret || !cpumask_weight(opp_shared_cpus)) { + /* + * Either opp-table is not set or no opp-shared was found. + * Use the CPU mask from SCMI to designate CPUs sharing an OPP + * table. + */ + cpumask_copy(opp_shared_cpus, policy->cpus); } + /* + * Add OPPs only on those CPUs for which we haven't already done so. + */ nr_opp = dev_pm_opp_get_opp_count(cpu_dev); if (nr_opp <= 0) { - dev_err(cpu_dev, "%s: No OPPs for this device: %d\n", - __func__, ret); - - ret = -ENODEV; - goto out_free_priv; + ret = handle->perf_ops->device_opps_add(handle, cpu_dev); + if (ret) { + dev_warn(cpu_dev, "failed to add opps to the device\n"); + goto out_free_cpumask; + } + + nr_opp = dev_pm_opp_get_opp_count(cpu_dev); + if (nr_opp <= 0) { + dev_err(cpu_dev, "%s: No OPPs for this device: %d\n", + __func__, ret); + + ret = -ENODEV; + goto out_free_opp; + } + + ret = dev_pm_opp_set_sharing_cpus(cpu_dev, opp_shared_cpus); + if (ret) { + dev_err(cpu_dev, "%s: failed to mark OPPs as shared: %d\n", + __func__, ret); + + goto out_free_opp; + } + + power_scale_mw = handle->perf_ops->power_scale_mw_get(handle); + em_dev_register_perf_domain(cpu_dev, nr_opp, &em_cb, + opp_shared_cpus, power_scale_mw); } priv = kzalloc(sizeof(*priv), GFP_KERNEL); @@ -192,17 +223,18 @@ static int scmi_cpufreq_init(struct cpufreq_policy *policy) policy->fast_switch_possible = handle->perf_ops->fast_switch_possible(handle, cpu_dev); - power_scale_mw = handle->perf_ops->power_scale_mw_get(handle); - em_dev_register_perf_domain(cpu_dev, nr_opp, &em_cb, policy->cpus, - power_scale_mw); - + free_cpumask_var(opp_shared_cpus); return 0; out_free_priv: kfree(priv); + out_free_opp: dev_pm_opp_remove_all_dynamic(cpu_dev); +out_free_cpumask: + free_cpumask_var(opp_shared_cpus); + return ret; }