diff options
author | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2020-09-01 19:44:20 +0200 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2020-09-01 19:44:20 +0200 |
commit | 763700f5e0fc8e66f4279848b150c5d12eb4d421 (patch) | |
tree | c508dabee27ccd6a88141dc70d09968dd9ac72bf /drivers | |
parent | Linux 5.9-rc3 (diff) | |
parent | opp: Don't drop reference for an OPP table that was never parsed (diff) | |
download | linux-763700f5e0fc8e66f4279848b150c5d12eb4d421.tar.xz linux-763700f5e0fc8e66f4279848b150c5d12eb4d421.zip |
Merge branch 'opp/fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/vireshk/pm
Pull operating performance points (OPP) framework fixes for 5.9-rc4 from
Viresh Kumar:
"This fixes reference counting for OPP tables. Few patches are getting
queued (for various subsystems) for 5.10 which depend on this to be
fixed first."
* 'opp/fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/vireshk/pm:
opp: Don't drop reference for an OPP table that was never parsed
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/opp/core.c | 22 | ||||
-rw-r--r-- | drivers/opp/opp.h | 2 |
2 files changed, 17 insertions, 7 deletions
diff --git a/drivers/opp/core.c b/drivers/opp/core.c index 9668ea04cc80..3ca7543142bf 100644 --- a/drivers/opp/core.c +++ b/drivers/opp/core.c @@ -1296,13 +1296,19 @@ void dev_pm_opp_remove(struct device *dev, unsigned long freq) } EXPORT_SYMBOL_GPL(dev_pm_opp_remove); -void _opp_remove_all_static(struct opp_table *opp_table) +bool _opp_remove_all_static(struct opp_table *opp_table) { struct dev_pm_opp *opp, *tmp; + bool ret = true; mutex_lock(&opp_table->lock); - if (!opp_table->parsed_static_opps || --opp_table->parsed_static_opps) + if (!opp_table->parsed_static_opps) { + ret = false; + goto unlock; + } + + if (--opp_table->parsed_static_opps) goto unlock; list_for_each_entry_safe(opp, tmp, &opp_table->opp_list, node) { @@ -1312,6 +1318,8 @@ void _opp_remove_all_static(struct opp_table *opp_table) unlock: mutex_unlock(&opp_table->lock); + + return ret; } /** @@ -2414,13 +2422,15 @@ void _dev_pm_opp_find_and_remove_table(struct device *dev) return; } - _opp_remove_all_static(opp_table); + /* + * Drop the extra reference only if the OPP table was successfully added + * with dev_pm_opp_of_add_table() earlier. + **/ + if (_opp_remove_all_static(opp_table)) + dev_pm_opp_put_opp_table(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); } /** diff --git a/drivers/opp/opp.h b/drivers/opp/opp.h index e51646ff279e..c3fcd571e446 100644 --- a/drivers/opp/opp.h +++ b/drivers/opp/opp.h @@ -212,7 +212,7 @@ struct opp_table { /* Routines internal to opp core */ void dev_pm_opp_get(struct dev_pm_opp *opp); -void _opp_remove_all_static(struct opp_table *opp_table); +bool _opp_remove_all_static(struct opp_table *opp_table); void _get_opp_table_kref(struct opp_table *opp_table); int _get_opp_count(struct opp_table *opp_table); struct opp_table *_find_opp_table(struct device *dev); |