diff options
Diffstat (limited to 'drivers/opp/core.c')
-rw-r--r-- | drivers/opp/core.c | 40 |
1 files changed, 22 insertions, 18 deletions
diff --git a/drivers/opp/core.c b/drivers/opp/core.c index 954c94865cf5..ae359ed6a161 100644 --- a/drivers/opp/core.c +++ b/drivers/opp/core.c @@ -29,9 +29,6 @@ */ LIST_HEAD(opp_tables); -/* OPP tables with uninitialized required OPPs */ -LIST_HEAD(lazy_opp_tables); - /* Lock to allow exclusive modification to the device and opp lists */ DEFINE_MUTEX(opp_table_lock); /* Flag indicating that opp_tables list is being updated at the moment */ @@ -240,7 +237,13 @@ unsigned int dev_pm_opp_get_required_pstate(struct dev_pm_opp *opp, if (lazy_linking_pending(opp->opp_table)) return 0; - return opp->required_opps[index]->pstate; + /* The required OPP table must belong to a genpd */ + if (unlikely(!opp->opp_table->required_opp_tables[index]->is_genpd)) { + pr_err("%s: Performance state is only valid for genpds.\n", __func__); + return 0; + } + + return opp->required_opps[index]->level; } EXPORT_SYMBOL_GPL(dev_pm_opp_get_required_pstate); @@ -938,7 +941,7 @@ static int _set_opp_bw(const struct opp_table *opp_table, static int _set_performance_state(struct device *dev, struct device *pd_dev, struct dev_pm_opp *opp, int i) { - unsigned int pstate = likely(opp) ? opp->required_opps[i]->pstate : 0; + unsigned int pstate = likely(opp) ? opp->required_opps[i]->level: 0; int ret; if (!pd_dev) @@ -1091,7 +1094,7 @@ static int _set_opp(struct device *dev, struct opp_table *opp_table, /* Return early if nothing to do */ if (!forced && old_opp == opp && opp_table->enabled) { - dev_dbg(dev, "%s: OPPs are same, nothing to do\n", __func__); + dev_dbg_ratelimited(dev, "%s: OPPs are same, nothing to do\n", __func__); return 0; } @@ -1358,7 +1361,10 @@ static struct opp_table *_allocate_opp_table(struct device *dev, int index) return opp_table; remove_opp_dev: + _of_clear_opp_table(opp_table); _remove_opp_dev(opp_dev, opp_table); + mutex_destroy(&opp_table->genpd_virt_dev_lock); + mutex_destroy(&opp_table->lock); err: kfree(opp_table); return ERR_PTR(ret); @@ -1522,16 +1528,8 @@ static void _opp_table_kref_release(struct kref *kref) WARN_ON(!list_empty(&opp_table->opp_list)); - list_for_each_entry_safe(opp_dev, temp, &opp_table->dev_list, node) { - /* - * The OPP table is getting removed, drop the performance state - * constraints. - */ - if (opp_table->genpd_performance_state) - dev_pm_genpd_set_performance_state((struct device *)(opp_dev->dev), 0); - + list_for_each_entry_safe(opp_dev, temp, &opp_table->dev_list, node) _remove_opp_dev(opp_dev, opp_table); - } mutex_destroy(&opp_table->genpd_virt_dev_lock); mutex_destroy(&opp_table->lock); @@ -2379,7 +2377,7 @@ static int _opp_attach_genpd(struct opp_table *opp_table, struct device *dev, virt_dev = dev_pm_domain_attach_by_name(dev, *name); if (IS_ERR_OR_NULL(virt_dev)) { - ret = PTR_ERR(virt_dev) ? : -ENODEV; + ret = virt_dev ? PTR_ERR(virt_dev) : -ENODEV; dev_err(dev, "Couldn't attach to pm_domain: %d\n", ret); goto err; } @@ -2704,6 +2702,12 @@ int dev_pm_opp_xlate_performance_state(struct opp_table *src_table, if (!src_table || !src_table->required_opp_count) return pstate; + /* Both OPP tables must belong to genpds */ + if (unlikely(!src_table->is_genpd || !dst_table->is_genpd)) { + pr_err("%s: Performance state is only valid for genpds.\n", __func__); + return -EINVAL; + } + /* required-opps not fully initialized yet */ if (lazy_linking_pending(src_table)) return -EBUSY; @@ -2722,8 +2726,8 @@ int dev_pm_opp_xlate_performance_state(struct opp_table *src_table, mutex_lock(&src_table->lock); list_for_each_entry(opp, &src_table->opp_list, node) { - if (opp->pstate == pstate) { - dest_pstate = opp->required_opps[i]->pstate; + if (opp->level == pstate) { + dest_pstate = opp->required_opps[i]->level; goto unlock; } } |