opp: Free static OPPs on errors while adding them
authorViresh Kumar <viresh.kumar@linaro.org>
Mon, 18 Nov 2019 09:11:07 +0000 (14:41 +0530)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 24 Feb 2020 07:36:34 +0000 (08:36 +0100)
[ Upstream commit ba0033192145cbd4e70ef64552958b13d597eb9e ]

The static OPPs aren't getting freed properly, if errors occur while
adding them. Fix that by calling _put_opp_list_kref() and putting their
reference on failures.

Fixes: 11e1a1648298 ("opp: Don't decrement uninitialized list_kref")
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/opp/of.c

index 1cbb582..1e5fcde 100644 (file)
@@ -678,15 +678,17 @@ static int _of_add_opp_table_v2(struct device *dev, struct opp_table *opp_table)
                        dev_err(dev, "%s: Failed to add OPP, %d\n", __func__,
                                ret);
                        of_node_put(np);
-                       return ret;
+                       goto put_list_kref;
                } else if (opp) {
                        count++;
                }
        }
 
        /* There should be one of more OPP defined */
-       if (WARN_ON(!count))
-               return -ENOENT;
+       if (WARN_ON(!count)) {
+               ret = -ENOENT;
+               goto put_list_kref;
+       }
 
        list_for_each_entry(opp, &opp_table->opp_list, node)
                pstate_count += !!opp->pstate;
@@ -695,7 +697,8 @@ static int _of_add_opp_table_v2(struct device *dev, struct opp_table *opp_table)
        if (pstate_count && pstate_count != count) {
                dev_err(dev, "Not all nodes have performance state set (%d: %d)\n",
                        count, pstate_count);
-               return -ENOENT;
+               ret = -ENOENT;
+               goto put_list_kref;
        }
 
        if (pstate_count)
@@ -704,6 +707,11 @@ static int _of_add_opp_table_v2(struct device *dev, struct opp_table *opp_table)
        opp_table->parsed_static_opps = true;
 
        return 0;
+
+put_list_kref:
+       _put_opp_list_kref(opp_table);
+
+       return ret;
 }
 
 /* Initializes OPP tables based on old-deprecated bindings */
@@ -738,6 +746,7 @@ static int _of_add_opp_table_v1(struct device *dev, struct opp_table *opp_table)
                if (ret) {
                        dev_err(dev, "%s: Failed to add OPP %ld (%d)\n",
                                __func__, freq, ret);
+                       _put_opp_list_kref(opp_table);
                        return ret;
                }
                nr -= 2;