PM / OPP: Fix shared OPP table support in dev_pm_opp_set_supported_hw()
It should be fine to call dev_pm_opp_set_supported_hw() for all possible CPUs, even if some of them share the OPP table as the caller may not be aware of sharing policy. Lets increment the reference count of the OPP table and return its pointer. The caller need to call dev_pm_opp_put_supported_hw() the same number of times later on to drop all the references. To avoid adding another counter to count how many times dev_pm_opp_set_supported_hw() is called for the same OPP table, dev_pm_opp_put_supported_hw() frees the resources on the very first call made to it, assuming that the caller would be calling it sequentially for all the CPUs. We can revisit that if that assumption is broken in the future. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
This commit is contained in:
parent
6a89e012aa
commit
25419de1b8
|
@ -1157,7 +1157,6 @@ struct opp_table *dev_pm_opp_set_supported_hw(struct device *dev,
|
|||
const u32 *versions, unsigned int count)
|
||||
{
|
||||
struct opp_table *opp_table;
|
||||
int ret;
|
||||
|
||||
opp_table = dev_pm_opp_get_opp_table(dev);
|
||||
if (!opp_table)
|
||||
|
@ -1166,29 +1165,20 @@ struct opp_table *dev_pm_opp_set_supported_hw(struct device *dev,
|
|||
/* Make sure there are no concurrent readers while updating opp_table */
|
||||
WARN_ON(!list_empty(&opp_table->opp_list));
|
||||
|
||||
/* Do we already have a version hierarchy associated with opp_table? */
|
||||
if (opp_table->supported_hw) {
|
||||
dev_err(dev, "%s: Already have supported hardware list\n",
|
||||
__func__);
|
||||
ret = -EBUSY;
|
||||
goto err;
|
||||
}
|
||||
/* Another CPU that shares the OPP table has set the property ? */
|
||||
if (opp_table->supported_hw)
|
||||
return opp_table;
|
||||
|
||||
opp_table->supported_hw = kmemdup(versions, count * sizeof(*versions),
|
||||
GFP_KERNEL);
|
||||
if (!opp_table->supported_hw) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
dev_pm_opp_put_opp_table(opp_table);
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
opp_table->supported_hw_count = count;
|
||||
|
||||
return opp_table;
|
||||
|
||||
err:
|
||||
dev_pm_opp_put_opp_table(opp_table);
|
||||
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dev_pm_opp_set_supported_hw);
|
||||
|
||||
|
@ -1205,12 +1195,6 @@ void dev_pm_opp_put_supported_hw(struct opp_table *opp_table)
|
|||
/* Make sure there are no concurrent readers while updating opp_table */
|
||||
WARN_ON(!list_empty(&opp_table->opp_list));
|
||||
|
||||
if (!opp_table->supported_hw) {
|
||||
pr_err("%s: Doesn't have supported hardware list\n",
|
||||
__func__);
|
||||
return;
|
||||
}
|
||||
|
||||
kfree(opp_table->supported_hw);
|
||||
opp_table->supported_hw = NULL;
|
||||
opp_table->supported_hw_count = 0;
|
||||
|
|
Loading…
Reference in New Issue