Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

PM / OPP: Add dev_pm_opp_get_sharing_cpus()

OPP core allows a platform to mark OPP table as shared, when the
platform isn't using operating-points-v2 bindings.

And, so there should be a non DT way of finding out if the OPP table is
shared or not.

This patch adds dev_pm_opp_get_sharing_cpus(), which first tries to get
OPP sharing information from the opp-table (in case it is already marked
as shared), otherwise it uses the existing DT way of finding sharing
information.

Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
Acked-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

authored by

Viresh Kumar and committed by
Rafael J. Wysocki
6f707daa dde370b2

+51
+45
drivers/base/power/opp/cpu.c
··· 330 330 return ret; 331 331 } 332 332 EXPORT_SYMBOL_GPL(dev_pm_opp_set_sharing_cpus); 333 + 334 + /** 335 + * dev_pm_opp_get_sharing_cpus() - Get cpumask of CPUs sharing OPPs with @cpu_dev 336 + * @cpu_dev: CPU device for which we do this operation 337 + * @cpumask: cpumask to update with information of sharing CPUs 338 + * 339 + * This updates the @cpumask with CPUs that are sharing OPPs with @cpu_dev. 340 + * 341 + * Returns -ENODEV if OPP table isn't already present. 342 + * 343 + * Locking: The internal opp_table and opp structures are RCU protected. 344 + * Hence this function internally uses RCU updater strategy with mutex locks 345 + * to keep the integrity of the internal data structures. Callers should ensure 346 + * that this function is *NOT* called under RCU protection or in contexts where 347 + * mutex cannot be locked. 348 + */ 349 + int dev_pm_opp_get_sharing_cpus(struct device *cpu_dev, cpumask_var_t cpumask) 350 + { 351 + struct opp_device *opp_dev; 352 + struct opp_table *opp_table; 353 + int ret = 0; 354 + 355 + mutex_lock(&opp_table_lock); 356 + 357 + opp_table = _find_opp_table(cpu_dev); 358 + if (IS_ERR(opp_table)) { 359 + ret = PTR_ERR(opp_table); 360 + goto unlock; 361 + } 362 + 363 + cpumask_clear(cpumask); 364 + 365 + if (opp_table->shared_opp) { 366 + list_for_each_entry(opp_dev, &opp_table->dev_list, node) 367 + cpumask_set_cpu(opp_dev->dev->id, cpumask); 368 + } else { 369 + cpumask_set_cpu(cpu_dev->id, cpumask); 370 + } 371 + 372 + unlock: 373 + mutex_unlock(&opp_table_lock); 374 + 375 + return ret; 376 + } 377 + EXPORT_SYMBOL_GPL(dev_pm_opp_get_sharing_cpus);
+6
include/linux/pm_opp.h
··· 66 66 void dev_pm_opp_put_regulator(struct device *dev); 67 67 int dev_pm_opp_set_rate(struct device *dev, unsigned long target_freq); 68 68 int dev_pm_opp_set_sharing_cpus(struct device *cpu_dev, const cpumask_var_t cpumask); 69 + int dev_pm_opp_get_sharing_cpus(struct device *cpu_dev, cpumask_var_t cpumask); 69 70 #else 70 71 static inline unsigned long dev_pm_opp_get_voltage(struct dev_pm_opp *opp) 71 72 { ··· 183 182 static inline int dev_pm_opp_set_sharing_cpus(struct device *cpu_dev, const cpumask_var_t cpumask) 184 183 { 185 184 return -ENOTSUPP; 185 + } 186 + 187 + static inline int dev_pm_opp_get_sharing_cpus(struct device *cpu_dev, cpumask_var_t cpumask) 188 + { 189 + return -EINVAL; 186 190 } 187 191 188 192 #endif /* CONFIG_PM_OPP */