OPP: Use mutex locking guards

Use mutex locking guard in the OPP core.

No intentional functional impact.

Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
This commit is contained in:
Viresh Kumar 2025-04-24 14:15:53 +05:30
parent 8c5d8c0b9e
commit ff9c512041
3 changed files with 105 additions and 164 deletions

View File

@ -40,17 +40,14 @@ static DEFINE_XARRAY_ALLOC1(opp_configs);
static bool _find_opp_dev(const struct device *dev, struct opp_table *opp_table) static bool _find_opp_dev(const struct device *dev, struct opp_table *opp_table)
{ {
struct opp_device *opp_dev; struct opp_device *opp_dev;
bool found = false;
mutex_lock(&opp_table->lock); guard(mutex)(&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)
if (opp_dev->dev == dev) { if (opp_dev->dev == dev)
found = true; return true;
break;
}
mutex_unlock(&opp_table->lock); return false;
return found;
} }
static struct opp_table *_find_opp_table_unlocked(struct device *dev) static struct opp_table *_find_opp_table_unlocked(struct device *dev)
@ -78,18 +75,13 @@ static struct opp_table *_find_opp_table_unlocked(struct device *dev)
*/ */
struct opp_table *_find_opp_table(struct device *dev) struct opp_table *_find_opp_table(struct device *dev)
{ {
struct opp_table *opp_table;
if (IS_ERR_OR_NULL(dev)) { if (IS_ERR_OR_NULL(dev)) {
pr_err("%s: Invalid parameters\n", __func__); pr_err("%s: Invalid parameters\n", __func__);
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
} }
mutex_lock(&opp_table_lock); guard(mutex)(&opp_table_lock);
opp_table = _find_opp_table_unlocked(dev); return _find_opp_table_unlocked(dev);
mutex_unlock(&opp_table_lock);
return opp_table;
} }
/* /*
@ -359,8 +351,7 @@ unsigned long dev_pm_opp_get_max_volt_latency(struct device *dev)
if (!uV) if (!uV)
return 0; return 0;
mutex_lock(&opp_table->lock); scoped_guard(mutex, &opp_table->lock) {
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
uV[i].min = ~0; uV[i].min = ~0;
uV[i].max = 0; uV[i].max = 0;
@ -375,8 +366,7 @@ unsigned long dev_pm_opp_get_max_volt_latency(struct device *dev)
uV[i].max = opp->supplies[i].u_volt_max; uV[i].max = opp->supplies[i].u_volt_max;
} }
} }
}
mutex_unlock(&opp_table->lock);
/* /*
* The caller needs to ensure that opp_table (and hence the regulator) * The caller needs to ensure that opp_table (and hence the regulator)
@ -438,15 +428,13 @@ int _get_opp_count(struct opp_table *opp_table)
struct dev_pm_opp *opp; struct dev_pm_opp *opp;
int count = 0; int count = 0;
mutex_lock(&opp_table->lock); guard(mutex)(&opp_table->lock);
list_for_each_entry(opp, &opp_table->opp_list, node) { list_for_each_entry(opp, &opp_table->opp_list, node) {
if (opp->available) if (opp->available)
count++; count++;
} }
mutex_unlock(&opp_table->lock);
return count; return count;
} }
@ -535,7 +523,7 @@ static struct dev_pm_opp *_opp_table_find_key(struct opp_table *opp_table,
if (assert && !assert(opp_table, index)) if (assert && !assert(opp_table, index))
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
mutex_lock(&opp_table->lock); guard(mutex)(&opp_table->lock);
list_for_each_entry(temp_opp, &opp_table->opp_list, node) { list_for_each_entry(temp_opp, &opp_table->opp_list, node) {
if (temp_opp->available == available) { if (temp_opp->available == available) {
@ -550,8 +538,6 @@ static struct dev_pm_opp *_opp_table_find_key(struct opp_table *opp_table,
dev_pm_opp_get(opp); dev_pm_opp_get(opp);
} }
mutex_unlock(&opp_table->lock);
return opp; return opp;
} }
@ -1166,10 +1152,9 @@ static void _find_current_opp(struct device *dev, struct opp_table *opp_table)
* make special checks to validate current_opp. * make special checks to validate current_opp.
*/ */
if (IS_ERR(opp)) { if (IS_ERR(opp)) {
mutex_lock(&opp_table->lock); guard(mutex)(&opp_table->lock);
opp = dev_pm_opp_get(list_first_entry(&opp_table->opp_list, opp = dev_pm_opp_get(list_first_entry(&opp_table->opp_list,
struct dev_pm_opp, node)); struct dev_pm_opp, node));
mutex_unlock(&opp_table->lock);
} }
opp_table->current_opp = opp; opp_table->current_opp = opp;
@ -1426,9 +1411,8 @@ struct opp_device *_add_opp_dev(const struct device *dev,
/* Initialize opp-dev */ /* Initialize opp-dev */
opp_dev->dev = dev; opp_dev->dev = dev;
mutex_lock(&opp_table->lock); scoped_guard(mutex, &opp_table->lock)
list_add(&opp_dev->node, &opp_table->dev_list); list_add(&opp_dev->node, &opp_table->dev_list);
mutex_unlock(&opp_table->lock);
/* Create debugfs entries for the opp_table */ /* Create debugfs entries for the opp_table */
opp_debug_register(opp_dev, opp_table); opp_debug_register(opp_dev, opp_table);
@ -1721,16 +1705,14 @@ void dev_pm_opp_remove(struct device *dev, unsigned long freq)
if (!assert_single_clk(opp_table, 0)) if (!assert_single_clk(opp_table, 0))
return; return;
mutex_lock(&opp_table->lock); scoped_guard(mutex, &opp_table->lock) {
list_for_each_entry(iter, &opp_table->opp_list, node) { list_for_each_entry(iter, &opp_table->opp_list, node) {
if (iter->rates[0] == freq) { if (iter->rates[0] == freq) {
opp = iter; opp = iter;
break; break;
} }
} }
}
mutex_unlock(&opp_table->lock);
if (opp) { if (opp) {
dev_pm_opp_put(opp); dev_pm_opp_put(opp);
@ -1747,22 +1729,20 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_remove);
static struct dev_pm_opp *_opp_get_next(struct opp_table *opp_table, static struct dev_pm_opp *_opp_get_next(struct opp_table *opp_table,
bool dynamic) bool dynamic)
{ {
struct dev_pm_opp *opp = NULL, *temp; struct dev_pm_opp *opp;
mutex_lock(&opp_table->lock); guard(mutex)(&opp_table->lock);
list_for_each_entry(temp, &opp_table->opp_list, node) {
list_for_each_entry(opp, &opp_table->opp_list, node) {
/* /*
* Refcount must be dropped only once for each OPP by OPP core, * Refcount must be dropped only once for each OPP by OPP core,
* do that with help of "removed" flag. * do that with help of "removed" flag.
*/ */
if (!temp->removed && dynamic == temp->dynamic) { if (!opp->removed && dynamic == opp->dynamic)
opp = temp; return opp;
break;
}
} }
mutex_unlock(&opp_table->lock); return NULL;
return opp;
} }
/* /*
@ -1786,20 +1766,14 @@ static void _opp_remove_all(struct opp_table *opp_table, bool dynamic)
bool _opp_remove_all_static(struct opp_table *opp_table) bool _opp_remove_all_static(struct opp_table *opp_table)
{ {
mutex_lock(&opp_table->lock); scoped_guard(mutex, &opp_table->lock) {
if (!opp_table->parsed_static_opps)
if (!opp_table->parsed_static_opps) {
mutex_unlock(&opp_table->lock);
return false; return false;
}
if (--opp_table->parsed_static_opps) { if (--opp_table->parsed_static_opps)
mutex_unlock(&opp_table->lock);
return true; return true;
} }
mutex_unlock(&opp_table->lock);
_opp_remove_all(opp_table, false); _opp_remove_all(opp_table, false);
return true; return true;
} }
@ -2003,17 +1977,15 @@ int _opp_add(struct device *dev, struct dev_pm_opp *new_opp,
struct list_head *head; struct list_head *head;
int ret; int ret;
mutex_lock(&opp_table->lock); scoped_guard(mutex, &opp_table->lock) {
head = &opp_table->opp_list; head = &opp_table->opp_list;
ret = _opp_is_duplicate(dev, new_opp, opp_table, &head); ret = _opp_is_duplicate(dev, new_opp, opp_table, &head);
if (ret) { if (ret)
mutex_unlock(&opp_table->lock);
return ret; return ret;
}
list_add(&new_opp->node, head); list_add(&new_opp->node, head);
mutex_unlock(&opp_table->lock); }
new_opp->opp_table = opp_table; new_opp->opp_table = opp_table;
kref_init(&new_opp->kref); kref_init(&new_opp->kref);
@ -2660,17 +2632,16 @@ struct dev_pm_opp *dev_pm_opp_xlate_required_opp(struct opp_table *src_table,
return ERR_PTR(-EBUSY); return ERR_PTR(-EBUSY);
for (i = 0; i < src_table->required_opp_count; i++) { for (i = 0; i < src_table->required_opp_count; i++) {
if (src_table->required_opp_tables[i] == dst_table) { if (src_table->required_opp_tables[i] != dst_table)
mutex_lock(&src_table->lock); continue;
scoped_guard(mutex, &src_table->lock) {
list_for_each_entry(opp, &src_table->opp_list, node) { list_for_each_entry(opp, &src_table->opp_list, node) {
if (opp == src_opp) { if (opp == src_opp) {
dest_opp = dev_pm_opp_get(opp->required_opps[i]); dest_opp = dev_pm_opp_get(opp->required_opps[i]);
break; break;
} }
} }
mutex_unlock(&src_table->lock);
break; break;
} }
} }
@ -2702,7 +2673,6 @@ int dev_pm_opp_xlate_performance_state(struct opp_table *src_table,
unsigned int pstate) unsigned int pstate)
{ {
struct dev_pm_opp *opp; struct dev_pm_opp *opp;
int dest_pstate = -EINVAL;
int i; int i;
/* /*
@ -2736,22 +2706,17 @@ int dev_pm_opp_xlate_performance_state(struct opp_table *src_table,
return -EINVAL; return -EINVAL;
} }
mutex_lock(&src_table->lock); guard(mutex)(&src_table->lock);
list_for_each_entry(opp, &src_table->opp_list, node) { list_for_each_entry(opp, &src_table->opp_list, node) {
if (opp->level == pstate) { if (opp->level == pstate)
dest_pstate = opp->required_opps[i]->level; return opp->required_opps[i]->level;
goto unlock;
}
} }
pr_err("%s: Couldn't find matching OPP (%p: %p)\n", __func__, src_table, pr_err("%s: Couldn't find matching OPP (%p: %p)\n", __func__, src_table,
dst_table); dst_table);
unlock: return -EINVAL;
mutex_unlock(&src_table->lock);
return dest_pstate;
} }
/** /**
@ -2820,25 +2785,21 @@ static int _opp_set_availability(struct device *dev, unsigned long freq,
if (!assert_single_clk(opp_table, 0)) if (!assert_single_clk(opp_table, 0))
return -EINVAL; return -EINVAL;
mutex_lock(&opp_table->lock); scoped_guard(mutex, &opp_table->lock) {
/* Do we have the frequency? */ /* Do we have the frequency? */
list_for_each_entry(tmp_opp, &opp_table->opp_list, node) { list_for_each_entry(tmp_opp, &opp_table->opp_list, node) {
if (tmp_opp->rates[0] == freq) { if (tmp_opp->rates[0] == freq) {
opp = dev_pm_opp_get(tmp_opp); opp = dev_pm_opp_get(tmp_opp);
/* Is update really needed? */ /* Is update really needed? */
if (opp->available == availability_req) { if (opp->available == availability_req)
mutex_unlock(&opp_table->lock);
return 0; return 0;
}
opp->available = availability_req; opp->available = availability_req;
break; break;
} }
} }
}
mutex_unlock(&opp_table->lock);
if (IS_ERR(opp)) if (IS_ERR(opp))
return PTR_ERR(opp); return PTR_ERR(opp);
@ -2886,18 +2847,15 @@ int dev_pm_opp_adjust_voltage(struct device *dev, unsigned long freq,
if (!assert_single_clk(opp_table, 0)) if (!assert_single_clk(opp_table, 0))
return -EINVAL; return -EINVAL;
mutex_lock(&opp_table->lock); scoped_guard(mutex, &opp_table->lock) {
/* Do we have the frequency? */ /* Do we have the frequency? */
list_for_each_entry(tmp_opp, &opp_table->opp_list, node) { list_for_each_entry(tmp_opp, &opp_table->opp_list, node) {
if (tmp_opp->rates[0] == freq) { if (tmp_opp->rates[0] == freq) {
opp = dev_pm_opp_get(tmp_opp); opp = dev_pm_opp_get(tmp_opp);
/* Is update really needed? */ /* Is update really needed? */
if (opp->supplies->u_volt == u_volt) { if (opp->supplies->u_volt == u_volt)
mutex_unlock(&opp_table->lock);
return 0; return 0;
}
opp->supplies->u_volt = u_volt; opp->supplies->u_volt = u_volt;
opp->supplies->u_volt_min = u_volt_min; opp->supplies->u_volt_min = u_volt_min;
@ -2906,8 +2864,7 @@ int dev_pm_opp_adjust_voltage(struct device *dev, unsigned long freq,
break; break;
} }
} }
}
mutex_unlock(&opp_table->lock);
if (IS_ERR(opp)) if (IS_ERR(opp))
return PTR_ERR(opp); return PTR_ERR(opp);

View File

@ -214,10 +214,9 @@ 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); guard(mutex)(&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);
} }

View File

@ -76,17 +76,12 @@ static struct dev_pm_opp *_find_opp_of_np(struct opp_table *opp_table,
{ {
struct dev_pm_opp *opp; struct dev_pm_opp *opp;
mutex_lock(&opp_table->lock); guard(mutex)(&opp_table->lock);
list_for_each_entry(opp, &opp_table->opp_list, node) { list_for_each_entry(opp, &opp_table->opp_list, node) {
if (opp->np == opp_np) { if (opp->np == opp_np)
dev_pm_opp_get(opp); return dev_pm_opp_get(opp);
mutex_unlock(&opp_table->lock);
return opp;
} }
}
mutex_unlock(&opp_table->lock);
return NULL; return NULL;
} }
@ -105,19 +100,15 @@ static struct opp_table *_find_table_of_opp_np(struct device_node *opp_np)
opp_table_np = of_get_parent(opp_np); opp_table_np = of_get_parent(opp_np);
if (!opp_table_np) if (!opp_table_np)
goto err; return ERR_PTR(-ENODEV);
guard(mutex)(&opp_table_lock);
mutex_lock(&opp_table_lock);
list_for_each_entry(opp_table, &opp_tables, node) { list_for_each_entry(opp_table, &opp_tables, node) {
if (opp_table_np == opp_table->np) { if (opp_table_np == opp_table->np)
dev_pm_opp_get_opp_table_ref(opp_table); return dev_pm_opp_get_opp_table_ref(opp_table);
mutex_unlock(&opp_table_lock);
return opp_table;
} }
}
mutex_unlock(&opp_table_lock);
err:
return ERR_PTR(-ENODEV); return ERR_PTR(-ENODEV);
} }
@ -142,9 +133,8 @@ static void _opp_table_free_required_tables(struct opp_table *opp_table)
opp_table->required_opp_count = 0; opp_table->required_opp_count = 0;
opp_table->required_opp_tables = NULL; opp_table->required_opp_tables = NULL;
mutex_lock(&opp_table_lock); guard(mutex)(&opp_table_lock);
list_del(&opp_table->lazy); list_del(&opp_table->lazy);
mutex_unlock(&opp_table_lock);
} }
/* /*
@ -201,9 +191,8 @@ static void _opp_table_alloc_required_tables(struct opp_table *opp_table,
* The OPP table is not held while allocating the table, take it * The OPP table is not held while allocating the table, take it
* now to avoid corruption to the lazy_opp_tables list. * now to avoid corruption to the lazy_opp_tables list.
*/ */
mutex_lock(&opp_table_lock); guard(mutex)(&opp_table_lock);
list_add(&opp_table->lazy, &lazy_opp_tables); list_add(&opp_table->lazy, &lazy_opp_tables);
mutex_unlock(&opp_table_lock);
} }
} }
@ -357,7 +346,7 @@ static void lazy_link_required_opp_table(struct opp_table *new_table)
struct dev_pm_opp *opp; struct dev_pm_opp *opp;
int i, ret; int i, ret;
mutex_lock(&opp_table_lock); guard(mutex)(&opp_table_lock);
list_for_each_entry_safe(opp_table, temp, &lazy_opp_tables, lazy) { list_for_each_entry_safe(opp_table, temp, &lazy_opp_tables, lazy) {
struct device_node *opp_np __free(device_node); struct device_node *opp_np __free(device_node);
@ -408,8 +397,6 @@ static void lazy_link_required_opp_table(struct opp_table *new_table)
_required_opps_available(opp, opp_table->required_opp_count); _required_opps_available(opp, opp_table->required_opp_count);
} }
} }
mutex_unlock(&opp_table_lock);
} }
static int _bandwidth_supported(struct device *dev, struct opp_table *opp_table) static int _bandwidth_supported(struct device *dev, struct opp_table *opp_table)
@ -970,15 +957,14 @@ static int _of_add_opp_table_v2(struct device *dev, struct opp_table *opp_table)
struct dev_pm_opp *opp; struct dev_pm_opp *opp;
/* OPP table is already initialized for the device */ /* OPP table is already initialized for the device */
mutex_lock(&opp_table->lock); scoped_guard(mutex, &opp_table->lock) {
if (opp_table->parsed_static_opps) { if (opp_table->parsed_static_opps) {
opp_table->parsed_static_opps++; opp_table->parsed_static_opps++;
mutex_unlock(&opp_table->lock);
return 0; return 0;
} }
opp_table->parsed_static_opps = 1; opp_table->parsed_static_opps = 1;
mutex_unlock(&opp_table->lock); }
/* We have opp-table node now, iterate over it and add OPPs */ /* We have opp-table node now, iterate over it and add OPPs */
for_each_available_child_of_node(opp_table->np, np) { for_each_available_child_of_node(opp_table->np, np) {
@ -1018,15 +1004,14 @@ static int _of_add_opp_table_v1(struct device *dev, struct opp_table *opp_table)
const __be32 *val; const __be32 *val;
int nr, ret = 0; int nr, ret = 0;
mutex_lock(&opp_table->lock); scoped_guard(mutex, &opp_table->lock) {
if (opp_table->parsed_static_opps) { if (opp_table->parsed_static_opps) {
opp_table->parsed_static_opps++; opp_table->parsed_static_opps++;
mutex_unlock(&opp_table->lock);
return 0; return 0;
} }
opp_table->parsed_static_opps = 1; opp_table->parsed_static_opps = 1;
mutex_unlock(&opp_table->lock); }
prop = of_find_property(dev->of_node, "operating-points", NULL); prop = of_find_property(dev->of_node, "operating-points", NULL);
if (!prop) { if (!prop) {