summaryrefslogtreecommitdiffstats
path: root/drivers/opp/of.c
diff options
context:
space:
mode:
authorViresh Kumar <viresh.kumar@linaro.org>2018-09-12 09:05:19 +0200
committerViresh Kumar <viresh.kumar@linaro.org>2018-09-19 23:56:46 +0200
commitcdd6ed90cdb6c2fd982909501f0a109274147fb4 (patch)
tree353be38edd20f6a6045244801cd6597ceb5caf87 /drivers/opp/of.c
parentOPP: Don't remove dynamic OPPs from _dev_pm_opp_remove_table() (diff)
downloadlinux-cdd6ed90cdb6c2fd982909501f0a109274147fb4.tar.xz
linux-cdd6ed90cdb6c2fd982909501f0a109274147fb4.zip
OPP: Use a single mechanism to free the OPP table
Currently there are two separate ways to free the OPP table based on how it is created in the first place. We call _dev_pm_opp_remove_table() to free the static and/or dynamic OPP, OPP list devices, etc. This is done for the case where the OPP table is added while initializing the OPPs, like via the path dev_pm_opp_of_add_table(). We also call dev_pm_opp_put_opp_table() in some cases which eventually frees the OPP table structure once the reference count reaches 0. This is used by the first case as well as other cases like dev_pm_opp_set_regulators() where the OPPs aren't necessarily initialized at this point. This whole thing is a bit unclear and messy and obstruct any further cleanup/fixup of OPP core. This patch tries to streamline this by keeping a single path for OPP table destruction, i.e. dev_pm_opp_put_opp_table(). All the cleanup happens in _opp_table_kref_release() now after the reference count reaches 0. _dev_pm_opp_remove_table() is removed as it isn't required anymore. We don't drop the reference to the OPP table after creating it from _of_add_opp_table_v{1|2}() anymore and the same is dropped only when we try to remove them. Tested-by: Niklas Cassel <niklas.cassel@linaro.org> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
Diffstat (limited to 'drivers/opp/of.c')
-rw-r--r--drivers/opp/of.c32
1 files changed, 18 insertions, 14 deletions
diff --git a/drivers/opp/of.c b/drivers/opp/of.c
index 861cc75de329..ae0436eaa911 100644
--- a/drivers/opp/of.c
+++ b/drivers/opp/of.c
@@ -407,14 +407,17 @@ static int _of_add_opp_table_v2(struct device *dev, struct device_node *opp_np,
opp_table = _managed_opp(opp_np);
if (opp_table) {
/* OPPs are already managed */
- if (!_add_opp_dev(dev, opp_table))
+ if (!_add_opp_dev(dev, opp_table)) {
ret = -ENOMEM;
- else if (!opp_table->parsed_static_opps)
- goto initialize_static_opps;
- else
+ goto put_opp_table;
+ }
+
+ if (opp_table->parsed_static_opps) {
kref_get(&opp_table->list_kref);
+ return 0;
+ }
- goto put_opp_table;
+ goto initialize_static_opps;
}
opp_table = dev_pm_opp_get_opp_table_indexed(dev, index);
@@ -432,17 +435,15 @@ initialize_static_opps:
if (ret) {
dev_err(dev, "%s: Failed to add OPP, %d\n", __func__,
ret);
- _dev_pm_opp_remove_table(opp_table, dev);
of_node_put(np);
- goto put_opp_table;
+ goto put_list_kref;
}
}
/* There should be one of more OPP defined */
if (WARN_ON(!count)) {
ret = -ENOENT;
- _put_opp_list_kref(opp_table);
- goto put_opp_table;
+ goto put_list_kref;
}
list_for_each_entry(opp, &opp_table->opp_list, node)
@@ -453,8 +454,7 @@ initialize_static_opps:
dev_err(dev, "Not all nodes have performance state set (%d: %d)\n",
count, pstate_count);
ret = -ENOENT;
- _dev_pm_opp_remove_table(opp_table, dev);
- goto put_opp_table;
+ goto put_list_kref;
}
if (pstate_count)
@@ -462,6 +462,10 @@ initialize_static_opps:
opp_table->parsed_static_opps = true;
+ return 0;
+
+put_list_kref:
+ _put_opp_list_kref(opp_table);
put_opp_table:
dev_pm_opp_put_opp_table(opp_table);
@@ -507,13 +511,13 @@ static int _of_add_opp_table_v1(struct device *dev)
if (ret) {
dev_err(dev, "%s: Failed to add OPP %ld (%d)\n",
__func__, freq, ret);
- _dev_pm_opp_remove_table(opp_table, dev);
- break;
+ _put_opp_list_kref(opp_table);
+ dev_pm_opp_put_opp_table(opp_table);
+ return ret;
}
nr -= 2;
}
- dev_pm_opp_put_opp_table(opp_table);
return ret;
}