Commit 5d113aa6 authored by Rafael J. Wysocki's avatar Rafael J. Wysocki

Merge branches 'pm-opp' and 'powercap'

* pm-opp:
  PM / OPP: _of_add_opp_table_v2(): increment count only if OPP is added
  cpufreq: dt: Try freeing static OPPs only if we have added them
  OPP: Return error on error from dev_pm_opp_get_opp_count()
  OPP: Improve error handling in dev_pm_opp_of_cpumask_add_table()
  OPP: Pass OPP table to _of_add_opp_table_v{1|2}()
  OPP: Prevent creating multiple OPP tables for devices sharing OPP nodes
  OPP: Use a single mechanism to free the OPP table
  OPP: Don't remove dynamic OPPs from _dev_pm_opp_remove_table()
  cpufreq: mvebu: Remove OPPs using dev_pm_opp_remove()
  OPP: Create separate kref for static OPPs list
  OPP: Don't take OPP table's kref for static OPPs
  OPP: Parse OPP table's DT properties from _of_init_opp_table()
  OPP: Pass index to _of_init_opp_table()
  OPP: Protect dev_list with opp_table lock
  OPP: Don't try to remove all OPP tables on failure
  OPP: Free OPP table properly on performance state irregularities

* powercap:
  powercap: RAPL: Get rid of custom RAPL_CPU() macro
...@@ -32,6 +32,7 @@ struct private_data { ...@@ -32,6 +32,7 @@ struct private_data {
struct device *cpu_dev; struct device *cpu_dev;
struct thermal_cooling_device *cdev; struct thermal_cooling_device *cdev;
const char *reg_name; const char *reg_name;
bool have_static_opps;
}; };
static struct freq_attr *cpufreq_dt_attr[] = { static struct freq_attr *cpufreq_dt_attr[] = {
...@@ -204,6 +205,15 @@ static int cpufreq_init(struct cpufreq_policy *policy) ...@@ -204,6 +205,15 @@ static int cpufreq_init(struct cpufreq_policy *policy)
} }
} }
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
if (!priv) {
ret = -ENOMEM;
goto out_put_regulator;
}
priv->reg_name = name;
priv->opp_table = opp_table;
/* /*
* Initialize OPP tables for all policy->cpus. They will be shared by * Initialize OPP tables for all policy->cpus. They will be shared by
* all CPUs which have marked their CPUs shared with OPP bindings. * all CPUs which have marked their CPUs shared with OPP bindings.
...@@ -214,7 +224,8 @@ static int cpufreq_init(struct cpufreq_policy *policy) ...@@ -214,7 +224,8 @@ static int cpufreq_init(struct cpufreq_policy *policy)
* *
* OPPs might be populated at runtime, don't check for error here * OPPs might be populated at runtime, don't check for error here
*/ */
dev_pm_opp_of_cpumask_add_table(policy->cpus); if (!dev_pm_opp_of_cpumask_add_table(policy->cpus))
priv->have_static_opps = true;
/* /*
* But we need OPP table to function so if it is not there let's * But we need OPP table to function so if it is not there let's
...@@ -240,19 +251,10 @@ static int cpufreq_init(struct cpufreq_policy *policy) ...@@ -240,19 +251,10 @@ static int cpufreq_init(struct cpufreq_policy *policy)
__func__, ret); __func__, ret);
} }
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
if (!priv) {
ret = -ENOMEM;
goto out_free_opp;
}
priv->reg_name = name;
priv->opp_table = opp_table;
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;
...@@ -282,10 +284,11 @@ static int cpufreq_init(struct cpufreq_policy *policy) ...@@ -282,10 +284,11 @@ static int cpufreq_init(struct cpufreq_policy *policy)
out_free_cpufreq_table: out_free_cpufreq_table:
dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table); dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table);
out_free_priv:
kfree(priv);
out_free_opp: out_free_opp:
dev_pm_opp_of_cpumask_remove_table(policy->cpus); if (priv->have_static_opps)
dev_pm_opp_of_cpumask_remove_table(policy->cpus);
kfree(priv);
out_put_regulator:
if (name) if (name)
dev_pm_opp_put_regulators(opp_table); dev_pm_opp_put_regulators(opp_table);
out_put_clk: out_put_clk:
...@@ -300,7 +303,8 @@ static int cpufreq_exit(struct cpufreq_policy *policy) ...@@ -300,7 +303,8 @@ static int cpufreq_exit(struct cpufreq_policy *policy)
cpufreq_cooling_unregister(priv->cdev); cpufreq_cooling_unregister(priv->cdev);
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_of_cpumask_remove_table(policy->related_cpus); if (priv->have_static_opps)
dev_pm_opp_of_cpumask_remove_table(policy->related_cpus);
if (priv->reg_name) if (priv->reg_name)
dev_pm_opp_put_regulators(priv->opp_table); dev_pm_opp_put_regulators(priv->opp_table);
......
...@@ -84,9 +84,10 @@ static int __init armada_xp_pmsu_cpufreq_init(void) ...@@ -84,9 +84,10 @@ static int __init armada_xp_pmsu_cpufreq_init(void)
ret = dev_pm_opp_add(cpu_dev, clk_get_rate(clk) / 2, 0); ret = dev_pm_opp_add(cpu_dev, clk_get_rate(clk) / 2, 0);
if (ret) { if (ret) {
dev_pm_opp_remove(cpu_dev, clk_get_rate(clk));
clk_put(clk); clk_put(clk);
dev_err(cpu_dev, "Failed to register OPPs\n"); dev_err(cpu_dev, "Failed to register OPPs\n");
goto opp_register_failed; return ret;
} }
ret = dev_pm_opp_set_sharing_cpus(cpu_dev, ret = dev_pm_opp_set_sharing_cpus(cpu_dev,
...@@ -99,11 +100,5 @@ static int __init armada_xp_pmsu_cpufreq_init(void) ...@@ -99,11 +100,5 @@ static int __init armada_xp_pmsu_cpufreq_init(void)
platform_device_register_simple("cpufreq-dt", -1, NULL, 0); platform_device_register_simple("cpufreq-dt", -1, NULL, 0);
return 0; return 0;
opp_register_failed:
/* As registering has failed remove all the opp for all cpus */
dev_pm_opp_cpumask_remove_table(cpu_possible_mask);
return ret;
} }
device_initcall(armada_xp_pmsu_cpufreq_init); device_initcall(armada_xp_pmsu_cpufreq_init);
...@@ -48,9 +48,14 @@ static struct opp_device *_find_opp_dev(const struct device *dev, ...@@ -48,9 +48,14 @@ static struct opp_device *_find_opp_dev(const struct device *dev,
static struct opp_table *_find_opp_table_unlocked(struct device *dev) static struct opp_table *_find_opp_table_unlocked(struct device *dev)
{ {
struct opp_table *opp_table; struct opp_table *opp_table;
bool found;
list_for_each_entry(opp_table, &opp_tables, node) { list_for_each_entry(opp_table, &opp_tables, node) {
if (_find_opp_dev(dev, opp_table)) { mutex_lock(&opp_table->lock);
found = !!_find_opp_dev(dev, opp_table);
mutex_unlock(&opp_table->lock);
if (found) {
_get_opp_table_kref(opp_table); _get_opp_table_kref(opp_table);
return opp_table; return opp_table;
...@@ -313,7 +318,7 @@ int dev_pm_opp_get_opp_count(struct device *dev) ...@@ -313,7 +318,7 @@ int dev_pm_opp_get_opp_count(struct device *dev)
count = PTR_ERR(opp_table); count = PTR_ERR(opp_table);
dev_dbg(dev, "%s: OPP table not found (%d)\n", dev_dbg(dev, "%s: OPP table not found (%d)\n",
__func__, count); __func__, count);
return 0; return count;
} }
count = _get_opp_count(opp_table); count = _get_opp_count(opp_table);
...@@ -754,8 +759,8 @@ static void _remove_opp_dev(struct opp_device *opp_dev, ...@@ -754,8 +759,8 @@ static void _remove_opp_dev(struct opp_device *opp_dev,
kfree(opp_dev); kfree(opp_dev);
} }
struct opp_device *_add_opp_dev(const struct device *dev, static struct opp_device *_add_opp_dev_unlocked(const struct device *dev,
struct opp_table *opp_table) struct opp_table *opp_table)
{ {
struct opp_device *opp_dev; struct opp_device *opp_dev;
int ret; int ret;
...@@ -766,6 +771,7 @@ struct opp_device *_add_opp_dev(const struct device *dev, ...@@ -766,6 +771,7 @@ struct opp_device *_add_opp_dev(const struct device *dev,
/* Initialize opp-dev */ /* Initialize opp-dev */
opp_dev->dev = dev; opp_dev->dev = dev;
list_add(&opp_dev->node, &opp_table->dev_list); list_add(&opp_dev->node, &opp_table->dev_list);
/* Create debugfs entries for the opp_table */ /* Create debugfs entries for the opp_table */
...@@ -777,7 +783,19 @@ struct opp_device *_add_opp_dev(const struct device *dev, ...@@ -777,7 +783,19 @@ struct opp_device *_add_opp_dev(const struct device *dev,
return opp_dev; return opp_dev;
} }
static struct opp_table *_allocate_opp_table(struct device *dev) struct opp_device *_add_opp_dev(const struct device *dev,
struct opp_table *opp_table)
{
struct opp_device *opp_dev;
mutex_lock(&opp_table->lock);
opp_dev = _add_opp_dev_unlocked(dev, opp_table);
mutex_unlock(&opp_table->lock);
return opp_dev;
}
static struct opp_table *_allocate_opp_table(struct device *dev, int index)
{ {
struct opp_table *opp_table; struct opp_table *opp_table;
struct opp_device *opp_dev; struct opp_device *opp_dev;
...@@ -791,6 +809,7 @@ static struct opp_table *_allocate_opp_table(struct device *dev) ...@@ -791,6 +809,7 @@ static struct opp_table *_allocate_opp_table(struct device *dev)
if (!opp_table) if (!opp_table)
return NULL; return NULL;
mutex_init(&opp_table->lock);
INIT_LIST_HEAD(&opp_table->dev_list); INIT_LIST_HEAD(&opp_table->dev_list);
opp_dev = _add_opp_dev(dev, opp_table); opp_dev = _add_opp_dev(dev, opp_table);
...@@ -799,7 +818,7 @@ static struct opp_table *_allocate_opp_table(struct device *dev) ...@@ -799,7 +818,7 @@ static struct opp_table *_allocate_opp_table(struct device *dev)
return NULL; return NULL;
} }
_of_init_opp_table(opp_table, dev); _of_init_opp_table(opp_table, dev, index);
/* Find clk for the device */ /* Find clk for the device */
opp_table->clk = clk_get(dev, NULL); opp_table->clk = clk_get(dev, NULL);
...@@ -812,7 +831,6 @@ static struct opp_table *_allocate_opp_table(struct device *dev) ...@@ -812,7 +831,6 @@ static struct opp_table *_allocate_opp_table(struct device *dev)
BLOCKING_INIT_NOTIFIER_HEAD(&opp_table->head); BLOCKING_INIT_NOTIFIER_HEAD(&opp_table->head);
INIT_LIST_HEAD(&opp_table->opp_list); INIT_LIST_HEAD(&opp_table->opp_list);
mutex_init(&opp_table->lock);
kref_init(&opp_table->kref); kref_init(&opp_table->kref);
/* Secure the device table modification */ /* Secure the device table modification */
...@@ -825,7 +843,7 @@ void _get_opp_table_kref(struct opp_table *opp_table) ...@@ -825,7 +843,7 @@ void _get_opp_table_kref(struct opp_table *opp_table)
kref_get(&opp_table->kref); kref_get(&opp_table->kref);
} }
struct opp_table *dev_pm_opp_get_opp_table(struct device *dev) static struct opp_table *_opp_get_opp_table(struct device *dev, int index)
{ {
struct opp_table *opp_table; struct opp_table *opp_table;
...@@ -836,31 +854,56 @@ struct opp_table *dev_pm_opp_get_opp_table(struct device *dev) ...@@ -836,31 +854,56 @@ struct opp_table *dev_pm_opp_get_opp_table(struct device *dev)
if (!IS_ERR(opp_table)) if (!IS_ERR(opp_table))
goto unlock; goto unlock;
opp_table = _allocate_opp_table(dev); opp_table = _managed_opp(dev, index);
if (opp_table) {
if (!_add_opp_dev_unlocked(dev, opp_table)) {
dev_pm_opp_put_opp_table(opp_table);
opp_table = NULL;
}
goto unlock;
}
opp_table = _allocate_opp_table(dev, index);
unlock: unlock:
mutex_unlock(&opp_table_lock); mutex_unlock(&opp_table_lock);
return opp_table; return opp_table;
} }
struct opp_table *dev_pm_opp_get_opp_table(struct device *dev)
{
return _opp_get_opp_table(dev, 0);
}
EXPORT_SYMBOL_GPL(dev_pm_opp_get_opp_table); EXPORT_SYMBOL_GPL(dev_pm_opp_get_opp_table);
struct opp_table *dev_pm_opp_get_opp_table_indexed(struct device *dev,
int index)
{
return _opp_get_opp_table(dev, index);
}
static void _opp_table_kref_release(struct kref *kref) static void _opp_table_kref_release(struct kref *kref)
{ {
struct opp_table *opp_table = container_of(kref, struct opp_table, kref); struct opp_table *opp_table = container_of(kref, struct opp_table, kref);
struct opp_device *opp_dev; struct opp_device *opp_dev, *temp;
/* Release clk */ /* Release clk */
if (!IS_ERR(opp_table->clk)) if (!IS_ERR(opp_table->clk))
clk_put(opp_table->clk); clk_put(opp_table->clk);
opp_dev = list_first_entry(&opp_table->dev_list, struct opp_device, WARN_ON(!list_empty(&opp_table->opp_list));
node);
_remove_opp_dev(opp_dev, opp_table); list_for_each_entry_safe(opp_dev, temp, &opp_table->dev_list, node) {
/*
* The OPP table is getting removed, drop the performance state
* constraints.
*/
if (opp_table->genpd_performance_state)
dev_pm_genpd_set_performance_state((struct device *)(opp_dev->dev), 0);
/* dev_list must be empty now */ _remove_opp_dev(opp_dev, opp_table);
WARN_ON(!list_empty(&opp_table->dev_list)); }
mutex_destroy(&opp_table->lock); mutex_destroy(&opp_table->lock);
list_del(&opp_table->node); list_del(&opp_table->node);
...@@ -869,6 +912,33 @@ static void _opp_table_kref_release(struct kref *kref) ...@@ -869,6 +912,33 @@ static void _opp_table_kref_release(struct kref *kref)
mutex_unlock(&opp_table_lock); mutex_unlock(&opp_table_lock);
} }
void _opp_remove_all_static(struct opp_table *opp_table)
{
struct dev_pm_opp *opp, *tmp;
list_for_each_entry_safe(opp, tmp, &opp_table->opp_list, node) {
if (!opp->dynamic)
dev_pm_opp_put(opp);
}
opp_table->parsed_static_opps = false;
}
static void _opp_table_list_kref_release(struct kref *kref)
{
struct opp_table *opp_table = container_of(kref, struct opp_table,
list_kref);
_opp_remove_all_static(opp_table);
mutex_unlock(&opp_table_lock);
}
void _put_opp_list_kref(struct opp_table *opp_table)
{
kref_put_mutex(&opp_table->list_kref, _opp_table_list_kref_release,
&opp_table_lock);
}
void dev_pm_opp_put_opp_table(struct opp_table *opp_table) void dev_pm_opp_put_opp_table(struct opp_table *opp_table)
{ {
kref_put_mutex(&opp_table->kref, _opp_table_kref_release, kref_put_mutex(&opp_table->kref, _opp_table_kref_release,
...@@ -896,7 +966,6 @@ static void _opp_kref_release(struct kref *kref) ...@@ -896,7 +966,6 @@ static void _opp_kref_release(struct kref *kref)
kfree(opp); kfree(opp);
mutex_unlock(&opp_table->lock); mutex_unlock(&opp_table->lock);
dev_pm_opp_put_opp_table(opp_table);
} }
void dev_pm_opp_get(struct dev_pm_opp *opp) void dev_pm_opp_get(struct dev_pm_opp *opp)
...@@ -940,11 +1009,15 @@ void dev_pm_opp_remove(struct device *dev, unsigned long freq) ...@@ -940,11 +1009,15 @@ void dev_pm_opp_remove(struct device *dev, unsigned long freq)
if (found) { if (found) {
dev_pm_opp_put(opp); dev_pm_opp_put(opp);
/* Drop the reference taken by dev_pm_opp_add() */
dev_pm_opp_put_opp_table(opp_table);
} else { } else {
dev_warn(dev, "%s: Couldn't find OPP with freq: %lu\n", dev_warn(dev, "%s: Couldn't find OPP with freq: %lu\n",
__func__, freq); __func__, freq);
} }
/* Drop the reference taken by _find_opp_table() */
dev_pm_opp_put_opp_table(opp_table); dev_pm_opp_put_opp_table(opp_table);
} }
EXPORT_SYMBOL_GPL(dev_pm_opp_remove); EXPORT_SYMBOL_GPL(dev_pm_opp_remove);
...@@ -1062,9 +1135,6 @@ int _opp_add(struct device *dev, struct dev_pm_opp *new_opp, ...@@ -1062,9 +1135,6 @@ int _opp_add(struct device *dev, struct dev_pm_opp *new_opp,
new_opp->opp_table = opp_table; new_opp->opp_table = opp_table;
kref_init(&new_opp->kref); kref_init(&new_opp->kref);
/* Get a reference to the OPP table */
_get_opp_table_kref(opp_table);
ret = opp_debug_create_one(new_opp, opp_table); ret = opp_debug_create_one(new_opp, opp_table);
if (ret) if (ret)
dev_err(dev, "%s: Failed to register opp to debugfs (%d)\n", dev_err(dev, "%s: Failed to register opp to debugfs (%d)\n",
...@@ -1543,8 +1613,9 @@ int dev_pm_opp_add(struct device *dev, unsigned long freq, unsigned long u_volt) ...@@ -1543,8 +1613,9 @@ int dev_pm_opp_add(struct device *dev, unsigned long freq, unsigned long u_volt)
return -ENOMEM; return -ENOMEM;
ret = _opp_add_v1(opp_table, dev, freq, u_volt, true); ret = _opp_add_v1(opp_table, dev, freq, u_volt, true);
if (ret)
dev_pm_opp_put_opp_table(opp_table);
dev_pm_opp_put_opp_table(opp_table);
return ret; return ret;
} }
EXPORT_SYMBOL_GPL(dev_pm_opp_add); EXPORT_SYMBOL_GPL(dev_pm_opp_add);
...@@ -1707,35 +1778,7 @@ int dev_pm_opp_unregister_notifier(struct device *dev, ...@@ -1707,35 +1778,7 @@ int dev_pm_opp_unregister_notifier(struct device *dev,
} }
EXPORT_SYMBOL(dev_pm_opp_unregister_notifier); EXPORT_SYMBOL(dev_pm_opp_unregister_notifier);
/* void _dev_pm_opp_find_and_remove_table(struct device *dev)
* Free OPPs either created using static entries present in DT or even the
* dynamically added entries based on remove_all param.
*/
void _dev_pm_opp_remove_table(struct opp_table *opp_table, struct device *dev,
bool remove_all)
{
struct dev_pm_opp *opp, *tmp;
/* Find if opp_table manages a single device */
if (list_is_singular(&opp_table->dev_list)) {
/* Free static OPPs */
list_for_each_entry_safe(opp, tmp, &opp_table->opp_list, node) {
if (remove_all || !opp->dynamic)
dev_pm_opp_put(opp);
}
/*
* The OPP table is getting removed, drop the performance state
* constraints.
*/
if (opp_table->genpd_performance_state)
dev_pm_genpd_set_performance_state(dev, 0);
} else {
_remove_opp_dev(_find_opp_dev(dev, opp_table), opp_table);
}
}
void _dev_pm_opp_find_and_remove_table(struct device *dev, bool remove_all)
{ {
struct opp_table *opp_table; struct opp_table *opp_table;
...@@ -1752,8 +1795,12 @@ void _dev_pm_opp_find_and_remove_table(struct device *dev, bool remove_all) ...@@ -1752,8 +1795,12 @@ void _dev_pm_opp_find_and_remove_table(struct device *dev, bool remove_all)
return; return;
} }
_dev_pm_opp_remove_table(opp_table, dev, remove_all); _put_opp_list_kref(opp_table);
/* Drop reference taken by _find_opp_table() */
dev_pm_opp_put_opp_table(opp_table);
/* Drop reference taken while the OPP table was added */
dev_pm_opp_put_opp_table(opp_table); dev_pm_opp_put_opp_table(opp_table);
} }
...@@ -1766,6 +1813,6 @@ void _dev_pm_opp_find_and_remove_table(struct device *dev, bool remove_all) ...@@ -1766,6 +1813,6 @@ void _dev_pm_opp_find_and_remove_table(struct device *dev, bool remove_all)
*/ */
void dev_pm_opp_remove_table(struct device *dev) void dev_pm_opp_remove_table(struct device *dev)
{ {
_dev_pm_opp_find_and_remove_table(dev, true); _dev_pm_opp_find_and_remove_table(dev);
} }
EXPORT_SYMBOL_GPL(dev_pm_opp_remove_table); EXPORT_SYMBOL_GPL(dev_pm_opp_remove_table);
...@@ -108,7 +108,8 @@ void dev_pm_opp_free_cpufreq_table(struct device *dev, ...@@ -108,7 +108,8 @@ void dev_pm_opp_free_cpufreq_table(struct device *dev,
EXPORT_SYMBOL_GPL(dev_pm_opp_free_cpufreq_table); EXPORT_SYMBOL_GPL(dev_pm_opp_free_cpufreq_table);
#endif /* CONFIG_CPU_FREQ */ #endif /* CONFIG_CPU_FREQ */
void _dev_pm_opp_cpumask_remove_table(const struct cpumask *cpumask, bool of) void _dev_pm_opp_cpumask_remove_table(const struct cpumask *cpumask,
int last_cpu)
{ {
struct device *cpu_dev; struct device *cpu_dev;
int cpu; int cpu;
...@@ -116,6 +117,9 @@ void _dev_pm_opp_cpumask_remove_table(const struct cpumask *cpumask, bool of) ...@@ -116,6 +117,9 @@ void _dev_pm_opp_cpumask_remove_table(const struct cpumask *cpumask, bool of)
WARN_ON(cpumask_empty(cpumask)); WARN_ON(cpumask_empty(cpumask));
for_each_cpu(cpu, cpumask) { for_each_cpu(cpu, cpumask) {
if (cpu == last_cpu)
break;
cpu_dev = get_cpu_device(cpu); cpu_dev = get_cpu_device(cpu);
if (!cpu_dev) { if (!cpu_dev) {
pr_err("%s: failed to get cpu%d device\n", __func__, pr_err("%s: failed to get cpu%d device\n", __func__,
...@@ -123,10 +127,7 @@ void _dev_pm_opp_cpumask_remove_table(const struct cpumask *cpumask, bool of) ...@@ -123,10 +127,7 @@ void _dev_pm_opp_cpumask_remove_table(const struct cpumask *cpumask, bool of)
continue; continue;
} }
if (of) _dev_pm_opp_find_and_remove_table(cpu_dev);
dev_pm_opp_of_remove_table(cpu_dev);
else
dev_pm_opp_remove_table(cpu_dev);
} }
} }
...@@ -140,7 +141,7 @@ void _dev_pm_opp_cpumask_remove_table(const struct cpumask *cpumask, bool of) ...@@ -140,7 +141,7 @@ void _dev_pm_opp_cpumask_remove_table(const struct cpumask *cpumask, bool of)
*/ */
void dev_pm_opp_cpumask_remove_table(const struct cpumask *cpumask) void dev_pm_opp_cpumask_remove_table(const struct cpumask *cpumask)
{ {
_dev_pm_opp_cpumask_remove_table(cpumask, false); _dev_pm_opp_cpumask_remove_table(cpumask, -1);
} }
EXPORT_SYMBOL_GPL(dev_pm_opp_cpumask_remove_table); EXPORT_SYMBOL_GPL(dev_pm_opp_cpumask_remove_table);
...@@ -222,8 +223,10 @@ int dev_pm_opp_get_sharing_cpus(struct device *cpu_dev, struct cpumask *cpumask) ...@@ -222,8 +223,10 @@ int dev_pm_opp_get_sharing_cpus(struct device *cpu_dev, struct cpumask *cpumask)
cpumask_clear(cpumask); cpumask_clear(cpumask);
if (opp_table->shared_opp == OPP_TABLE_ACCESS_SHARED) { if (opp_table->shared_opp == OPP_TABLE_ACCESS_SHARED) {
mutex_lock(&opp_table->lock);
list_for_each_entry(opp_dev, &opp_table->dev_list, node) list_for_each_entry(opp_dev, &opp_table->dev_list, node)
cpumask_set_cpu(opp_dev->dev->id, cpumask); cpumask_set_cpu(opp_dev->dev->id, cpumask);
mutex_unlock(&opp_table->lock);
} else { } else {
cpumask_set_cpu(cpu_dev->id, cpumask); cpumask_set_cpu(cpu_dev->id, cpumask);
} }
......
This diff is collapsed.
...@@ -126,9 +126,11 @@ enum opp_table_access { ...@@ -126,9 +126,11 @@ enum opp_table_access {
* @dev_list: list of devices that share these OPPs * @dev_list: list of devices that share these OPPs
* @opp_list: table of opps * @opp_list: table of opps
* @kref: for reference count of the table. * @kref: for reference count of the table.
* @lock: mutex protecting the opp_list. * @list_kref: for reference count of the OPP list.
* @lock: mutex protecting the opp_list and dev_list.
* @np: struct device_node pointer for opp's DT node. * @np: struct device_node pointer for opp's DT node.
* @clock_latency_ns_max: Max clock latency in nanoseconds. * @clock_latency_ns_max: Max clock latency in nanoseconds.
* @parsed_static_opps: True if OPPs are initialized from DT.
* @shared_opp: OPP is shared between multiple devices. * @shared_opp: OPP is shared between multiple devices.
* @suspend_opp: Pointer to OPP to be used during device suspend. * @suspend_opp: Pointer to OPP to be used during device suspend.
* @supported_hw: Array of version number to support. * @supported_hw: Array of version number to support.
...@@ -156,6 +158,7 @@ struct opp_table { ...@@ -156,6 +158,7 @@ struct opp_table {
struct list_head dev_list; struct list_head dev_list;
struct list_head opp_list; struct list_head opp_list;
struct kref kref; struct kref kref;
struct kref list_kref;
struct mutex lock; struct mutex lock;
struct device_node *np; struct device_node *np;
...@@ -164,6 +167,7 @@ struct opp_table { ...@@ -164,6 +167,7 @@ struct opp_table {
/* For backward compatibility with v1 bindings */ /* For backward compatibility with v1 bindings */
unsigned int voltage_tolerance_v1; unsigned int voltage_tolerance_v1;
bool parsed_static_opps;
enum opp_table_access shared_opp; enum opp_table_access shared_opp;
struct dev_pm_opp *suspend_opp; struct dev_pm_opp *suspend_opp;
...@@ -186,23 +190,26 @@ struct opp_table { ...@@ -186,23 +190,26 @@ struct opp_table {
/* Routines internal to opp core */ /* Routines internal to opp core */
void dev_pm_opp_get(struct dev_pm_opp *opp); void dev_pm_opp_get(struct dev_pm_opp *opp);
void _opp_remove_all_static(struct opp_table *opp_table);
void _get_opp_table_kref(struct opp_table *opp_table); void _get_opp_table_kref(struct opp_table *opp_table);
int _get_opp_count(struct opp_table *opp_table); int _get_opp_count(struct opp_table *opp_table);
struct opp_table *_find_opp_table(struct device *dev); struct opp_table *_find_opp_table(struct device *dev);
struct opp_device *_add_opp_dev(const struct device *dev, struct opp_table *opp_table); struct opp_device *_add_opp_dev(const struct device *dev, struct opp_table *opp_table);
void _dev_pm_opp_remove_table(struct opp_table *opp_table, struct device *dev, bool remove_all); void _dev_pm_opp_find_and_remove_table(struct device *dev);
void _dev_pm_opp_find_and_remove_table(struct device *dev, bool remove_all);
struct dev_pm_opp *_opp_allocate(struct opp_table *opp_table); struct dev_pm_opp *_opp_allocate(struct opp_table *opp_table);
void _opp_free(struct dev_pm_opp *opp); void _opp_free(struct dev_pm_opp *opp);
int _opp_add(struct device *dev, struct dev_pm_opp *new_opp, struct opp_table *opp_table, bool rate_not_available); int _opp_add(struct device *dev, struct dev_pm_opp *new_opp, struct opp_table *opp_table, bool rate_not_available);
int _opp_add_v1(struct opp_table *opp_table, struct device *dev, unsigned long freq, long u_volt, bool dynamic); int _opp_add_v1(struct opp_table *opp_table, struct device *dev, unsigned long freq, long u_volt, bool dynamic);
void _dev_pm_opp_cpumask_remove_table(const struct cpumask *cpumask, bool of); void _dev_pm_opp_cpumask_remove_table(const struct cpumask *cpumask, int last_cpu);
struct opp_table *_add_opp_table(struct device *dev); struct opp_table *_add_opp_table(struct device *dev);
void _put_opp_list_kref(struct opp_table *opp_table);
#ifdef CONFIG_OF #ifdef CONFIG_OF
void _of_init_opp_table(struct opp_table *opp_table, struct device *dev); void _of_init_opp_table(struct opp_table *opp_table, struct device *dev, int index);
struct opp_table *_managed_opp(struct device *dev, int index);
#else #else
static inline void _of_init_opp_table(struct opp_table *opp_table, struct device *dev) {} static inline void _of_init_opp_table(struct opp_table *opp_table, struct device *dev, int index) {}
static inline struct opp_table *_managed_opp(struct device *dev, int index) { return NULL; }
#endif #endif
#ifdef CONFIG_DEBUG_FS #ifdef CONFIG_DEBUG_FS
......
...@@ -1133,47 +1133,40 @@ static const struct rapl_defaults rapl_defaults_cht = { ...@@ -1133,47 +1133,40 @@ static const struct rapl_defaults rapl_defaults_cht = {
.compute_time_window = rapl_compute_time_window_atom, .compute_time_window = rapl_compute_time_window_atom,
}; };
#define RAPL_CPU(_model, _ops) { \
.vendor = X86_VENDOR_INTEL, \
.family = 6, \
.model = _model, \
.driver_data = (kernel_ulong_t)&_ops, \
}
static const struct x86_cpu_id rapl_ids[] __initconst = { static const struct x86_cpu_id rapl_ids[] __initconst = {
RAPL_CPU(INTEL_FAM6_SANDYBRIDGE, rapl_defaults_core), INTEL_CPU_FAM6(SANDYBRIDGE, rapl_defaults_core),
RAPL_CPU(INTEL_FAM6_SANDYBRIDGE_X, rapl_defaults_core), INTEL_CPU_FAM6(SANDYBRIDGE_X, rapl_defaults_core),
RAPL_CPU(INTEL_FAM6_IVYBRIDGE, rapl_defaults_core), INTEL_CPU_FAM6(IVYBRIDGE, rapl_defaults_core),
RAPL_CPU(INTEL_FAM6_IVYBRIDGE_X, rapl_defaults_core), INTEL_CPU_FAM6(IVYBRIDGE_X, rapl_defaults_core),
RAPL_CPU(INTEL_FAM6_HASWELL_CORE, rapl_defaults_core), INTEL_CPU_FAM6(HASWELL_CORE, rapl_defaults_core),
RAPL_CPU(INTEL_FAM6_HASWELL_ULT, rapl_defaults_core), INTEL_CPU_FAM6(HASWELL_ULT, rapl_defaults_core),
RAPL_CPU(INTEL_FAM6_HASWELL_GT3E, rapl_defaults_core), INTEL_CPU_FAM6(HASWELL_GT3E, rapl_defaults_core),
RAPL_CPU(INTEL_FAM6_HASWELL_X, rapl_defaults_hsw_server), INTEL_CPU_FAM6(HASWELL_X, rapl_defaults_hsw_server),
RAPL_CPU(INTEL_FAM6_BROADWELL_CORE, rapl_defaults_core), INTEL_CPU_FAM6(BROADWELL_CORE, rapl_defaults_core),
RAPL_CPU(INTEL_FAM6_BROADWELL_GT3E, rapl_defaults_core), INTEL_CPU_FAM6(BROADWELL_GT3E, rapl_defaults_core),
RAPL_CPU(INTEL_FAM6_BROADWELL_XEON_D, rapl_defaults_core), INTEL_CPU_FAM6(BROADWELL_XEON_D, rapl_defaults_core),
RAPL_CPU(INTEL_FAM6_BROADWELL_X, rapl_defaults_hsw_server), INTEL_CPU_FAM6(BROADWELL_X, rapl_defaults_hsw_server),
RAPL_CPU(INTEL_FAM6_SKYLAKE_DESKTOP, rapl_defaults_core), INTEL_CPU_FAM6(SKYLAKE_DESKTOP, rapl_defaults_core),
RAPL_CPU(INTEL_FAM6_SKYLAKE_MOBILE, rapl_defaults_core), INTEL_CPU_FAM6(SKYLAKE_MOBILE, rapl_defaults_core),
RAPL_CPU(INTEL_FAM6_SKYLAKE_X, rapl_defaults_hsw_server), INTEL_CPU_FAM6(SKYLAKE_X, rapl_defaults_hsw_server),
RAPL_CPU(INTEL_FAM6_KABYLAKE_MOBILE, rapl_defaults_core), INTEL_CPU_FAM6(KABYLAKE_MOBILE, rapl_defaults_core),
RAPL_CPU(INTEL_FAM6_KABYLAKE_DESKTOP, rapl_defaults_core), INTEL_CPU_FAM6(KABYLAKE_DESKTOP, rapl_defaults_core),
RAPL_CPU(INTEL_FAM6_CANNONLAKE_MOBILE, rapl_defaults_core), INTEL_CPU_FAM6(CANNONLAKE_MOBILE, rapl_defaults_core),
RAPL_CPU(INTEL_FAM6_ATOM_SILVERMONT1, rapl_defaults_byt), INTEL_CPU_FAM6(ATOM_SILVERMONT1, rapl_defaults_byt),
RAPL_CPU(INTEL_FAM6_ATOM_AIRMONT, rapl_defaults_cht), INTEL_CPU_FAM6(ATOM_AIRMONT, rapl_defaults_cht),
RAPL_CPU(INTEL_FAM6_ATOM_MERRIFIELD, rapl_defaults_tng), INTEL_CPU_FAM6(ATOM_MERRIFIELD, rapl_defaults_tng),
RAPL_CPU(INTEL_FAM6_ATOM_MOOREFIELD, rapl_defaults_ann), INTEL_CPU_FAM6(ATOM_MOOREFIELD, rapl_defaults_ann),
RAPL_CPU(INTEL_FAM6_ATOM_GOLDMONT, rapl_defaults_core), INTEL_CPU_FAM6(ATOM_GOLDMONT, rapl_defaults_core),
RAPL_CPU(INTEL_FAM6_ATOM_GEMINI_LAKE, rapl_defaults_core), INTEL_CPU_FAM6(ATOM_GEMINI_LAKE, rapl_defaults_core),
RAPL_CPU(INTEL_FAM6_ATOM_DENVERTON, rapl_defaults_core), INTEL_CPU_FAM6(ATOM_DENVERTON, rapl_defaults_core),
RAPL_CPU(INTEL_FAM6_XEON_PHI_KNL, rapl_defaults_hsw_server), INTEL_CPU_FAM6(XEON_PHI_KNL, rapl_defaults_hsw_server),
RAPL_CPU(INTEL_FAM6_XEON_PHI_KNM, rapl_defaults_hsw_server), INTEL_CPU_FAM6(XEON_PHI_KNM, rapl_defaults_hsw_server),
{} {}
}; };
MODULE_DEVICE_TABLE(x86cpu, rapl_ids); MODULE_DEVICE_TABLE(x86cpu, rapl_ids);
......
...@@ -79,6 +79,7 @@ struct dev_pm_set_opp_data { ...@@ -79,6 +79,7 @@ struct dev_pm_set_opp_data {
#if defined(CONFIG_PM_OPP) #if defined(CONFIG_PM_OPP)
struct opp_table *dev_pm_opp_get_opp_table(struct device *dev); struct opp_table *dev_pm_opp_get_opp_table(struct device *dev);
struct opp_table *dev_pm_opp_get_opp_table_indexed(struct device *dev, int index);
void dev_pm_opp_put_opp_table(struct opp_table *opp_table); void dev_pm_opp_put_opp_table(struct opp_table *opp_table);
unsigned long dev_pm_opp_get_voltage(struct dev_pm_opp *opp); unsigned long dev_pm_opp_get_voltage(struct dev_pm_opp *opp);
...@@ -136,6 +137,11 @@ static inline struct opp_table *dev_pm_opp_get_opp_table(struct device *dev) ...@@ -136,6 +137,11 @@ static inline struct opp_table *dev_pm_opp_get_opp_table(struct device *dev)
return ERR_PTR(-ENOTSUPP); return ERR_PTR(-ENOTSUPP);
} }
static inline struct opp_table *dev_pm_opp_get_opp_table_indexed(struct device *dev, int index)
{
return ERR_PTR(-ENOTSUPP);
}
static inline void dev_pm_opp_put_opp_table(struct opp_table *opp_table) {} static inline void dev_pm_opp_put_opp_table(struct opp_table *opp_table) {}
static inline unsigned long dev_pm_opp_get_voltage(struct dev_pm_opp *opp) static inline unsigned long dev_pm_opp_get_voltage(struct dev_pm_opp *opp)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment