]> git.itanic.dy.fi Git - linux-stable/commitdiff
OPP: Don't drop opp->np reference while it is still in use
authorLiang He <windhl@126.com>
Mon, 18 Jul 2022 13:36:32 +0000 (21:36 +0800)
committerViresh Kumar <viresh.kumar@linaro.org>
Tue, 19 Jul 2022 05:37:02 +0000 (11:07 +0530)
The struct dev_pm_opp contains a reference of the DT node, opp->np,
throughout its lifetime. We should increase the refcount for the same
from _opp_add_static_v2(), and drop it while removing the OPP finally.

Signed-off-by: Liang He <windhl@126.com>
[ Viresh: Updated subject / commit log, create _of_clear_opp() and drop
  reference from it]
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
drivers/opp/core.c
drivers/opp/of.c
drivers/opp/opp.h

index 4f4a285886fa72c7e595fec93bc6f45b9a981724..77d1ba3a4154f93ca7a1fe46de791d9e54dd0cce 100644 (file)
@@ -1553,7 +1553,7 @@ static void _opp_kref_release(struct kref *kref)
         * frequency/voltage list.
         */
        blocking_notifier_call_chain(&opp_table->head, OPP_EVENT_REMOVE, opp);
-       _of_opp_free_required_opps(opp_table, opp);
+       _of_clear_opp(opp_table, opp);
        opp_debug_remove_one(opp);
        kfree(opp);
 }
index e4002b0754224882c6cffa2bb0a7bbe8cb3f1ce7..7fa8263e38cb86c5ea4c98b8f1f6aeeed0e8565a 100644 (file)
@@ -254,8 +254,8 @@ void _of_clear_opp_table(struct opp_table *opp_table)
  * Release all resources previously acquired with a call to
  * _of_opp_alloc_required_opps().
  */
-void _of_opp_free_required_opps(struct opp_table *opp_table,
-                               struct dev_pm_opp *opp)
+static void _of_opp_free_required_opps(struct opp_table *opp_table,
+                                      struct dev_pm_opp *opp)
 {
        struct dev_pm_opp **required_opps = opp->required_opps;
        int i;
@@ -275,6 +275,12 @@ void _of_opp_free_required_opps(struct opp_table *opp_table,
        kfree(required_opps);
 }
 
+void _of_clear_opp(struct opp_table *opp_table, struct dev_pm_opp *opp)
+{
+       _of_opp_free_required_opps(opp_table, opp);
+       of_node_put(opp->np);
+}
+
 /* Populate all required OPPs which are part of "required-opps" list */
 static int _of_opp_alloc_required_opps(struct opp_table *opp_table,
                                       struct dev_pm_opp *opp)
@@ -938,7 +944,7 @@ static struct dev_pm_opp *_opp_add_static_v2(struct opp_table *opp_table,
 
        new_opp->turbo = of_property_read_bool(np, "turbo-mode");
 
-       new_opp->np = np;
+       new_opp->np = of_node_get(np);
        new_opp->dynamic = false;
        new_opp->available = true;
 
index 816009eaafee224d3a4f0d953daaaeaa9f43f7ad..3a6e077df3866b8389457afb06925f9c8ada87ca 100644 (file)
@@ -267,14 +267,12 @@ static inline bool lazy_linking_pending(struct opp_table *opp_table)
 void _of_init_opp_table(struct opp_table *opp_table, struct device *dev, int index);
 void _of_clear_opp_table(struct opp_table *opp_table);
 struct opp_table *_managed_opp(struct device *dev, int index);
-void _of_opp_free_required_opps(struct opp_table *opp_table,
-                               struct dev_pm_opp *opp);
+void _of_clear_opp(struct opp_table *opp_table, struct dev_pm_opp *opp);
 #else
 static inline void _of_init_opp_table(struct opp_table *opp_table, struct device *dev, int index) {}
 static inline void _of_clear_opp_table(struct opp_table *opp_table) {}
 static inline struct opp_table *_managed_opp(struct device *dev, int index) { return NULL; }
-static inline void _of_opp_free_required_opps(struct opp_table *opp_table,
-                                             struct dev_pm_opp *opp) {}
+static inline void _of_clear_opp(struct opp_table *opp_table, struct dev_pm_opp *opp) {}
 #endif
 
 #ifdef CONFIG_DEBUG_FS