OPP: pstate is only valid for genpd OPP tables
authorViresh Kumar <viresh.kumar@linaro.org>
Wed, 14 Jun 2023 10:27:43 +0000 (15:57 +0530)
committerViresh Kumar <viresh.kumar@linaro.org>
Mon, 19 Jun 2023 04:20:02 +0000 (09:50 +0530)
It is not very clear right now that the `pstate` field is only valid for
genpd OPP tables and not consumer tables. And there is no checking for
the same at various places.

Add checks in place to verify that and make it clear to the reader.

Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
Reviewed-by: Ulf Hansson <ulf.hansson@linaro.org>
Reviewed-by: Bjorn Andersson <quic_bjorande@quicinc.com>
Tested-by: Bjorn Andersson <quic_bjorande@quicinc.com>
drivers/opp/core.c
drivers/opp/debugfs.c
drivers/opp/of.c

index 7290168ec8067b8e67942234f436499e4ba2843b..4c82ee20ceb78b2003d4dbc8accfd6164c407b86 100644 (file)
@@ -227,16 +227,24 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_get_level);
 unsigned int dev_pm_opp_get_required_pstate(struct dev_pm_opp *opp,
                                            unsigned int index)
 {
+       struct opp_table *opp_table = opp->opp_table;
+
        if (IS_ERR_OR_NULL(opp) || !opp->available ||
-           index >= opp->opp_table->required_opp_count) {
+           index >= opp_table->required_opp_count) {
                pr_err("%s: Invalid parameters\n", __func__);
                return 0;
        }
 
        /* required-opps not fully initialized yet */
-       if (lazy_linking_pending(opp->opp_table))
+       if (lazy_linking_pending(opp_table))
                return 0;
 
+       /* The required OPP table must belong to a genpd */
+       if (unlikely(!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]->pstate;
 }
 EXPORT_SYMBOL_GPL(dev_pm_opp_get_required_pstate);
@@ -2696,6 +2704,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;
index 2c7fb683441effcc7ceedc50296c8a53c8b59f14..0cc21e2b42ffea26faa01bffeaf3f9825d8e6b9c 100644 (file)
@@ -152,11 +152,13 @@ void opp_debug_create_one(struct dev_pm_opp *opp, struct opp_table *opp_table)
        debugfs_create_bool("dynamic", S_IRUGO, d, &opp->dynamic);
        debugfs_create_bool("turbo", S_IRUGO, d, &opp->turbo);
        debugfs_create_bool("suspend", S_IRUGO, d, &opp->suspend);
-       debugfs_create_u32("performance_state", S_IRUGO, d, &opp->pstate);
        debugfs_create_u32("level", S_IRUGO, d, &opp->level);
        debugfs_create_ulong("clock_latency_ns", S_IRUGO, d,
                             &opp->clock_latency_ns);
 
+       if (opp_table->is_genpd)
+               debugfs_create_u32("performance_state", S_IRUGO, d, &opp->pstate);
+
        opp->of_name = of_node_full_name(opp->np);
        debugfs_create_str("of_name", S_IRUGO, d, (char **)&opp->of_name);
 
index 943c7fb7402b3e4f0a41d74ff9fd488a927f2c57..e23ce6e78eb6937b3f3a22b8f80456907b29a56b 100644 (file)
@@ -1392,6 +1392,12 @@ int of_get_required_opp_performance_state(struct device_node *np, int index)
                goto put_required_np;
        }
 
+       /* The OPP tables must belong to a genpd */
+       if (unlikely(!opp_table->is_genpd)) {
+               pr_err("%s: Performance state is only valid for genpds.\n", __func__);
+               goto put_required_np;
+       }
+
        opp = _find_opp_of_np(opp_table, required_np);
        if (opp) {
                pstate = opp->pstate;