lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-Id: <20200616055223.119360-1-ikjn@chromium.org>
Date:   Tue, 16 Jun 2020 13:52:23 +0800
From:   Ikjoon Jang <ikjn@...omium.org>
To:     linux-clk@...r.kernel.org
Cc:     Michael Turquette <mturquette@...libre.com>,
        Stephen Boyd <sboyd@...nel.org>, linux-kernel@...r.kernel.org,
        Ikjoon Jang <ikjn@...omium.org>
Subject: [PATCH] clk: Provide future parent in clk notification

Current clk notification handlers cannot know its new parent in
PRE_RATE_CHANGE event. This patch simply adds parent clk to
clk_notifier_data so the child clk is now able to know its future
parent prior to reparenting.

Change-Id: I099a784d5302a93951bdc6254d85f8df8c770462
Signed-off-by: Ikjoon Jang <ikjn@...omium.org>
---
 drivers/clk/clk.c   | 30 +++++++++++++++++-------------
 include/linux/clk.h |  9 ++++++---
 2 files changed, 23 insertions(+), 16 deletions(-)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 3f588ed06ce3..62c4e7b50ae5 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -1458,6 +1458,7 @@ EXPORT_SYMBOL_GPL(clk_round_rate);
 /**
  * __clk_notify - call clk notifier chain
  * @core: clk that is changing rate
+ * @parent: new parent of core
  * @msg: clk notifier type (see include/linux/clk.h)
  * @old_rate: old clk rate
  * @new_rate: new clk rate
@@ -1469,13 +1470,15 @@ EXPORT_SYMBOL_GPL(clk_round_rate);
  * called if all went well, or NOTIFY_STOP or NOTIFY_BAD immediately if
  * a driver returns that.
  */
-static int __clk_notify(struct clk_core *core, unsigned long msg,
-		unsigned long old_rate, unsigned long new_rate)
+static int __clk_notify(struct clk_core *core, struct clk_core *parent,
+			unsigned long msg, unsigned long old_rate,
+			unsigned long new_rate)
 {
 	struct clk_notifier *cn;
 	struct clk_notifier_data cnd;
 	int ret = NOTIFY_DONE;
 
+	cnd.parent = parent ? parent->hw->clk : NULL;
 	cnd.old_rate = old_rate;
 	cnd.new_rate = new_rate;
 
@@ -1597,7 +1600,7 @@ static void __clk_recalc_rates(struct clk_core *core, unsigned long msg)
 	 * & ABORT_RATE_CHANGE notifiers
 	 */
 	if (core->notifier_count && msg)
-		__clk_notify(core, msg, old_rate, core->rate);
+		__clk_notify(core, core->parent, msg, old_rate, core->rate);
 
 	hlist_for_each_entry(child, &core->children, child_node)
 		__clk_recalc_rates(child, msg);
@@ -1834,7 +1837,7 @@ static int __clk_set_parent(struct clk_core *core, struct clk_core *parent,
 /**
  * __clk_speculate_rates
  * @core: first clk in the subtree
- * @parent_rate: the "future" rate of clk's parent
+ * @parent: the "future" parent of core
  *
  * Walks the subtree of clks starting with clk, speculating rates as it
  * goes and firing off PRE_RATE_CHANGE notifications as necessary.
@@ -1846,7 +1849,7 @@ static int __clk_set_parent(struct clk_core *core, struct clk_core *parent,
  * take on the rate of its parent.
  */
 static int __clk_speculate_rates(struct clk_core *core,
-				 unsigned long parent_rate)
+				 struct clk_core *parent)
 {
 	struct clk_core *child;
 	unsigned long new_rate;
@@ -1854,11 +1857,12 @@ static int __clk_speculate_rates(struct clk_core *core,
 
 	lockdep_assert_held(&prepare_lock);
 
-	new_rate = clk_recalc(core, parent_rate);
+	new_rate = clk_recalc(core, parent ? parent->rate : 0);
 
 	/* abort rate change if a driver returns NOTIFY_BAD or NOTIFY_STOP */
 	if (core->notifier_count)
-		ret = __clk_notify(core, PRE_RATE_CHANGE, core->rate, new_rate);
+		ret = __clk_notify(core, parent, PRE_RATE_CHANGE,
+				   core->rate, new_rate);
 
 	if (ret & NOTIFY_STOP_MASK) {
 		pr_debug("%s: clk notifier callback for clock %s aborted with error %d\n",
@@ -1867,7 +1871,7 @@ static int __clk_speculate_rates(struct clk_core *core,
 	}
 
 	hlist_for_each_entry(child, &core->children, child_node) {
-		ret = __clk_speculate_rates(child, new_rate);
+		ret = __clk_speculate_rates(child, core);
 		if (ret & NOTIFY_STOP_MASK)
 			break;
 	}
@@ -1996,7 +2000,8 @@ static struct clk_core *clk_propagate_rate_change(struct clk_core *core,
 		return NULL;
 
 	if (core->notifier_count) {
-		ret = __clk_notify(core, event, core->rate, core->new_rate);
+		ret = __clk_notify(core, core->parent, event,
+				   core->rate, core->new_rate);
 		if (ret & NOTIFY_STOP_MASK)
 			fail_clk = core;
 	}
@@ -2098,7 +2103,8 @@ static void clk_change_rate(struct clk_core *core)
 		clk_core_disable_unprepare(parent);
 
 	if (core->notifier_count && old_rate != core->rate)
-		__clk_notify(core, POST_RATE_CHANGE, old_rate, core->rate);
+		__clk_notify(core, core->parent, POST_RATE_CHANGE,
+			     old_rate, core->rate);
 
 	if (core->flags & CLK_RECALC_NEW_RATES)
 		(void)clk_calc_new_rates(core, core->new_rate);
@@ -2479,7 +2485,6 @@ static int clk_core_set_parent_nolock(struct clk_core *core,
 {
 	int ret = 0;
 	int p_index = 0;
-	unsigned long p_rate = 0;
 
 	lockdep_assert_held(&prepare_lock);
 
@@ -2508,7 +2513,6 @@ static int clk_core_set_parent_nolock(struct clk_core *core,
 					__func__, parent->name, core->name);
 			return p_index;
 		}
-		p_rate = parent->rate;
 	}
 
 	ret = clk_pm_runtime_get(core);
@@ -2516,7 +2520,7 @@ static int clk_core_set_parent_nolock(struct clk_core *core,
 		return ret;
 
 	/* propagate PRE_RATE_CHANGE notifications */
-	ret = __clk_speculate_rates(core, p_rate);
+	ret = __clk_speculate_rates(core, parent);
 
 	/* abort if a driver objects */
 	if (ret & NOTIFY_STOP_MASK)
diff --git a/include/linux/clk.h b/include/linux/clk.h
index 7fd6a1febcf4..e246e160b290 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -60,16 +60,19 @@ struct clk_notifier {
 /**
  * struct clk_notifier_data - rate data to pass to the notifier callback
  * @clk: struct clk * being changed
+ * @parent: new parent of this clk
  * @old_rate: previous rate of this clk
  * @new_rate: new rate of this clk
  *
  * For a pre-notifier, old_rate is the clk's rate before this rate
- * change, and new_rate is what the rate will be in the future.  For a
- * post-notifier, old_rate and new_rate are both set to the clk's
- * current rate (this was done to optimize the implementation).
+ * change, new_rate is what the rate will be in the future, and parent is
+ * new parent of the clk after new_rate is applied, For a post-notifier,
+ * parent, old_rate, and new_rate are all set to the clk's current state.
+ * (this was done to optimize the implementation).
  */
 struct clk_notifier_data {
 	struct clk		*clk;
+	struct clk		*parent;
 	unsigned long		old_rate;
 	unsigned long		new_rate;
 };
-- 
2.27.0.290.gba653c62da-goog

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ