summaryrefslogtreecommitdiffstats
path: root/drivers/opp
diff options
context:
space:
mode:
authorViresh Kumar <viresh.kumar@linaro.org>2018-05-22 07:08:08 -0400
committerViresh Kumar <viresh.kumar@linaro.org>2018-05-22 07:30:10 -0400
commit878ec1a9f0e5a6b344c12fdc349ec7cb036c2a42 (patch)
tree45152b99aa4c6814d244ca9e1de8579ea75869d2 /drivers/opp
parent25419de1b8dda24f3e02478b12b724a9b0cc4e78 (diff)
PM / OPP: Fix shared OPP table support in dev_pm_opp_set_prop_name()
It should be fine to call dev_pm_opp_set_prop_name() 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_prop_name() 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_prop_name() is called for the same OPP table, dev_pm_opp_put_prop_name() 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>
Diffstat (limited to 'drivers/opp')
-rw-r--r--drivers/opp/core.c25
1 files changed, 5 insertions, 20 deletions
diff --git a/drivers/opp/core.c b/drivers/opp/core.c
index 481affb783f3..86e8e2c1905f 100644
--- a/drivers/opp/core.c
+++ b/drivers/opp/core.c
@@ -1216,7 +1216,6 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_put_supported_hw);
1216struct opp_table *dev_pm_opp_set_prop_name(struct device *dev, const char *name) 1216struct opp_table *dev_pm_opp_set_prop_name(struct device *dev, const char *name)
1217{ 1217{
1218 struct opp_table *opp_table; 1218 struct opp_table *opp_table;
1219 int ret;
1220 1219
1221 opp_table = dev_pm_opp_get_opp_table(dev); 1220 opp_table = dev_pm_opp_get_opp_table(dev);
1222 if (!opp_table) 1221 if (!opp_table)
@@ -1225,26 +1224,17 @@ struct opp_table *dev_pm_opp_set_prop_name(struct device *dev, const char *name)
1225 /* Make sure there are no concurrent readers while updating opp_table */ 1224 /* Make sure there are no concurrent readers while updating opp_table */
1226 WARN_ON(!list_empty(&opp_table->opp_list)); 1225 WARN_ON(!list_empty(&opp_table->opp_list));
1227 1226
1228 /* Do we already have a prop-name associated with opp_table? */ 1227 /* Another CPU that shares the OPP table has set the property ? */
1229 if (opp_table->prop_name) { 1228 if (opp_table->prop_name)
1230 dev_err(dev, "%s: Already have prop-name %s\n", __func__, 1229 return opp_table;
1231 opp_table->prop_name);
1232 ret = -EBUSY;
1233 goto err;
1234 }
1235 1230
1236 opp_table->prop_name = kstrdup(name, GFP_KERNEL); 1231 opp_table->prop_name = kstrdup(name, GFP_KERNEL);
1237 if (!opp_table->prop_name) { 1232 if (!opp_table->prop_name) {
1238 ret = -ENOMEM; 1233 dev_pm_opp_put_opp_table(opp_table);
1239 goto err; 1234 return ERR_PTR(-ENOMEM);
1240 } 1235 }
1241 1236
1242 return opp_table; 1237 return opp_table;
1243
1244err:
1245 dev_pm_opp_put_opp_table(opp_table);
1246
1247 return ERR_PTR(ret);
1248} 1238}
1249EXPORT_SYMBOL_GPL(dev_pm_opp_set_prop_name); 1239EXPORT_SYMBOL_GPL(dev_pm_opp_set_prop_name);
1250 1240
@@ -1261,11 +1251,6 @@ void dev_pm_opp_put_prop_name(struct opp_table *opp_table)
1261 /* Make sure there are no concurrent readers while updating opp_table */ 1251 /* Make sure there are no concurrent readers while updating opp_table */
1262 WARN_ON(!list_empty(&opp_table->opp_list)); 1252 WARN_ON(!list_empty(&opp_table->opp_list));
1263 1253
1264 if (!opp_table->prop_name) {
1265 pr_err("%s: Doesn't have a prop-name\n", __func__);
1266 return;
1267 }
1268
1269 kfree(opp_table->prop_name); 1254 kfree(opp_table->prop_name);
1270 opp_table->prop_name = NULL; 1255 opp_table->prop_name = NULL;
1271 1256