Skip to contentSkip to conversation

clk: implement clock rate protection mechanism

PATCH Superseded Jerome Brunet 7 participants 51 messages Jun 12, 2017 – Aug 10, 2017

Subsystems (3)

v3 of 5 Superseded Latest is v5 →

lore
Share & tools
lore

Jerome Brunet

author reviewer
#0 lore raw

v3 cover clk: implement clock rate protection mechanism

This Patchset is related the RFC [0] and the discussion around CLK_SET_RATE_GATE available here [1]

This patchset is based on clk-next.

The goal of this patchset is to provide a way for consumers to inform the system that they depend on the rate of the clock source and can't tolerate other consumers changing the rate or causing glitches.

With this series there is 3 use-case:
- the provider is not protected: nothing changes
- the provider is protected by only 1 consumer (and only once), then only this consumer will be able to alter the rate of the clock, as it is the only one depending on it.
- If the provider is protected more than once, or by the provider itself, the rate is basically locked and protected against reparenting.

The last patch provide the same functionnality for providers themself, fixing CLK_SET_RATE_GATE flag (enforce clock gating along the tree)

qcom, at91 and ux500 are the heaviest users of this flag. If anybody having one these platform could try this series, it would help build confidence that the platform relying on CLK_SET_RATE_GATE (even if broken) don't get any regression.

Changes since RFC:
- s/clk_protect/clk_rate_protect
- Request rework around core_nolock function
- Add clk_set_rate_protect
- Reword clk_rate_protect and clk_unprotect documentation
- Add few comments to explain the code
- Add 2 last patches to fix users of CLK_SET_RATE_GATE

Changes since v1:
- Add patch 4: Check if the rate would actually change before continuing, a possibly in clk_set_rate.

Changes since v2: [2]
- Fix issues reported by Adriana Reus (Thanks !)
- Dropped patch "clk: move CLK_SET_RATE_GATE protection from prepare to enable". This was broken as the protect count, like the prepare_count should only be accessed under the prepare_lock.
- No change around bail-out code. Mike wanted to ponder a bit more on it.
- Patch 1 still included, could not find the clk-next-protect Mike was referring to.

This was tested with the audio use case mentioned in [1]

[0]: https://lkml.kernel.org/r/20170321183330.26722-1-jbrunet at baylibre.com [1]: https://lkml.kernel.org/r/148942423440.82235.17188153691656009029 at resonance [2]: https://lkml.kernel.org/r/20170521215958.19743-1-jbrunet at baylibre.com

Jerome Brunet (10):
clk: take the prepare lock out of clk_core_set_parent
clk: add clk_core_set_phase_nolock function
clk: rework calls to round and determine rate callbacks
clk: use round rate to bail out early in set_rate
clk: add support for clock protection
clk: add clk_set_rate_protect
clk: rollback set_rate_range changes on failure
clk: cosmetic changes to clk_summary debugfs entry
clk: fix incorrect usage of ENOSYS
clk: fix CLK_SET_RATE_GATE with clock rate protection

 drivers/clk/clk.c            | 428 ++++++++++++++++++++++++++++++++++++-------
 include/linux/clk-provider.h |   1 +
 include/linux/clk.h          |  43 +++++
 3 files changed, 402 insertions(+), 70 deletions(-)
Signature · 1 line
2.9.4
author reviewer
#1 lore raw

PATCH v3 1/10 clk: take the prepare lock out of clk_core_set_parent

Rework set_parent core function so it can be called when the prepare lock is already held by the caller.

This rework is done to ease the integration of the "protected" clock functionality.

---
 drivers/clk/clk.c | 39 ++++++++++++++++++---------------------
 1 file changed, 18 insertions(+), 21 deletions(-)
drivers/clk/clk.c +18 -21
index fc58c52a26b4..f5c371532509 100644
@@ -1787,7 +1787,8 @@ bool clk_has_parent(struct clk *clk, struct clk *parent)
 }
 EXPORT_SYMBOL_GPL(clk_has_parent);
 
-static int clk_core_set_parent(struct clk_core *core, struct clk_core *parent)
+static int clk_core_set_parent_nolock(struct clk_core *core,
+				      struct clk_core *parent)
 {
 	int ret = 0;
 	int p_index = 0;
@@ -1796,23 +1797,16 @@ static int clk_core_set_parent(struct clk_core *core, struct clk_core *parent)
 	if (!core)
 		return 0;
 
-	/* prevent racing with updates to the clock topology */
-	clk_prepare_lock();
-
 	if (core->parent == parent)
-		goto out;
+		return 0;
 
 	/* verify ops for for multi-parent clks */
-	if ((core->num_parents > 1) && (!core->ops->set_parent)) {
-		ret = -ENOSYS;
-		goto out;
-	}
+	if ((core->num_parents > 1) && (!core->ops->set_parent))
+		return -ENOSYS;
 
 	/* check that we are allowed to re-parent if the clock is in use */
-	if ((core->flags & CLK_SET_PARENT_GATE) && core->prepare_count) {
-		ret = -EBUSY;
-		goto out;
-	}
+	if ((core->flags & CLK_SET_PARENT_GATE) && core->prepare_count)
+		return -EBUSY;
 
 	/* try finding the new parent index */
 	if (parent) {
@@ -1820,8 +1814,7 @@ static int clk_core_set_parent(struct clk_core *core, struct clk_core *parent)
 		if (p_index < 0) {
 			pr_debug("%s: clk %s can not be parent of clk %s\n",
 					__func__, parent->name, core->name);
-			ret = p_index;
-			goto out;
+			return p_index;
 		}
 		p_rate = parent->rate;
 	}
@@ -1831,7 +1824,7 @@ static int clk_core_set_parent(struct clk_core *core, struct clk_core *parent)
 
 	/* abort if a driver objects */
 	if (ret & NOTIFY_STOP_MASK)
-		goto out;
+		return ret;
 
 	/* do the re-parent */
 	ret = __clk_set_parent(core, parent, p_index);
@@ -1844,9 +1837,6 @@ static int clk_core_set_parent(struct clk_core *core, struct clk_core *parent)
 		__clk_recalc_accuracies(core);
 	}
 
-out:
-	clk_prepare_unlock();
-
 	return ret;
 }
 
@@ -1869,10 +1859,17 @@ static int clk_core_set_parent(struct clk_core *core, struct clk_core *parent)
  */
 int clk_set_parent(struct clk *clk, struct clk *parent)
 {
+	int ret;
+
 	if (!clk)
 		return 0;
 
-	return clk_core_set_parent(clk->core, parent ? parent->core : NULL);
+	clk_prepare_lock();
+	ret = clk_core_set_parent_nolock(clk->core,
+					 parent ? parent->core : NULL);
+	clk_prepare_unlock();
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(clk_set_parent);
 
@@ -2753,7 +2750,7 @@ void clk_unregister(struct clk *clk)
 		/* Reparent all children to the orphan list. */
 		hlist_for_each_entry_safe(child, t, &clk->core->children,
 					  child_node)
-			clk_core_set_parent(child, NULL);
+			clk_core_set_parent_nolock(child, NULL);
 	}
 
 	hlist_del_init(&clk->core->child_node);
Signature · 1 line
2.9.4
#2 lore raw

PATCH v3 1/10 clk: take the prepare lock out of clk_core_set_parent

Quoted 15 lines · Jerome Brunet
drivers/clk/clk.c +2 -1
index fc58c52a26b4..f5c371532509 100644
@@ -1787,7 +1787,8 @@ bool clk_has_parent(struct clk *clk, struct clk *parent)
 }
 EXPORT_SYMBOL_GPL(clk_has_parent);
 
-static int clk_core_set_parent(struct clk_core *core, struct clk_core *parent)
+static int clk_core_set_parent_nolock(struct clk_core *core,
+				      struct clk_core *parent)
 {
 	int ret = 0;
 	int p_index = 0;

drivers/clk/clk.c static int clk_core_set_parent(struct clk_core *core, struct clk_core *parent) · line 1800

Quoted 5 lines
drivers/clk/clk.c +0 -2
@@ -1796,23 +1797,16 @@ static int clk_core_set_parent(struct clk_core *core, struct clk_core *parent)
 	if (!core)
 		return 0;
 
-	/* prevent racing with updates to the clock topology */
-	clk_prepare_lock();

Please add a lockdep assertion as we have in other places in this file so that callers can't mess up calling the nolock function without the lock held themselves.

drivers/clk/clk.c static int clk_core_set_parent(struct clk_core *core, struct clk_core *parent) · line 1804

Quoted 11 lines
drivers/clk/clk.c +2 -6
-
 	if (core->parent == parent)
-		goto out;
+		return 0;
 
 	/* verify ops for for multi-parent clks */
-	if ((core->num_parents > 1) && (!core->ops->set_parent)) {
-		ret = -ENOSYS;
-		goto out;
-	}
+	if ((core->num_parents > 1) && (!core->ops->set_parent))

Nitpick: drop the extra parenthesis here.

Quoted 22 lines
drivers/clk/clk.c +4 -6
+		return -ENOSYS;
 
 	/* check that we are allowed to re-parent if the clock is in use */
-	if ((core->flags & CLK_SET_PARENT_GATE) && core->prepare_count) {
-		ret = -EBUSY;
-		goto out;
-	}
+	if ((core->flags & CLK_SET_PARENT_GATE) && core->prepare_count)
+		return -EBUSY;
 
 	/* try finding the new parent index */
 	if (parent) {
@@ -1820,8 +1814,7 @@ static int clk_core_set_parent(struct clk_core *core, struct clk_core *parent)
 		if (p_index < 0) {
 			pr_debug("%s: clk %s can not be parent of clk %s\n",
 					__func__, parent->name, core->name);
-			ret = p_index;
-			goto out;
+			return p_index;
 		}
 		p_rate = parent->rate;
 	}
Signature · 2 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
author reviewer
#3 lore raw

PATCH v3 2/10 clk: add clk_core_set_phase_nolock function

In reply to Jerome Brunet

Create a core function for set_phase, as it is done for set_rate and set_parent.

This rework is done to ease the integration of "protected" clock functionality.

---
 drivers/clk/clk.c | 31 +++++++++++++++++++------------
 1 file changed, 19 insertions(+), 12 deletions(-)
drivers/clk/clk.c +19 -12
index f5c371532509..dceaf0ff23db 100644
@@ -1873,6 +1873,23 @@ int clk_set_parent(struct clk *clk, struct clk *parent)
 }
 EXPORT_SYMBOL_GPL(clk_set_parent);
 
+static int clk_core_set_phase_nolock(struct clk_core *core, int degrees)
+{
+	int ret = -EINVAL;
+
+	if (!core)
+		return 0;
+
+	trace_clk_set_phase(core, degrees);
+
+	if (core->ops->set_phase)
+		ret = core->ops->set_phase(core->hw, degrees);
+
+	trace_clk_set_phase_complete(core, degrees);
+
+	return ret;
+}
+
 /**
  * clk_set_phase - adjust the phase shift of a clock signal
  * @clk: clock signal source
@@ -1895,7 +1912,7 @@ EXPORT_SYMBOL_GPL(clk_set_parent);
  */
 int clk_set_phase(struct clk *clk, int degrees)
 {
-	int ret = -EINVAL;
+	int ret;
 
 	if (!clk)
 		return 0;
@@ -1906,17 +1923,7 @@ int clk_set_phase(struct clk *clk, int degrees)
 		degrees += 360;
 
 	clk_prepare_lock();
-
-	trace_clk_set_phase(clk->core, degrees);
-
-	if (clk->core->ops->set_phase)
-		ret = clk->core->ops->set_phase(clk->core->hw, degrees);
-
-	trace_clk_set_phase_complete(clk->core, degrees);
-
-	if (!ret)
-		clk->core->phase = degrees;
-
+	ret = clk_core_set_phase_nolock(clk->core, degrees);
 	clk_prepare_unlock();
 
 	return ret;
Signature · 1 line
2.9.4
#4 lore raw

PATCH v3 2/10 clk: add clk_core_set_phase_nolock function

Quoted 5 lines · Jerome Brunet
drivers/clk/clk.c +0 -0
index f5c371532509..dceaf0ff23db 100644

drivers/clk/clk.c int clk_set_parent(struct clk *clk, struct clk *parent) · line 1881

Quoted 9 lines
drivers/clk/clk.c +6 -0
@@ -1873,6 +1873,23 @@ int clk_set_parent(struct clk *clk, struct clk *parent)
 }
 EXPORT_SYMBOL_GPL(clk_set_parent);
 
+static int clk_core_set_phase_nolock(struct clk_core *core, int degrees)
+{
+	int ret = -EINVAL;
+
+	if (!core)
+		return 0;

Same comment about lockdep assertion applies here.

Quoted 14 lines
drivers/clk/clk.c +11 -0
+
+	trace_clk_set_phase(core, degrees);
+
+	if (core->ops->set_phase)
+		ret = core->ops->set_phase(core->hw, degrees);
+
+	trace_clk_set_phase_complete(core, degrees);
+
+	return ret;
+}
+
 /**
  * clk_set_phase - adjust the phase shift of a clock signal
  * @clk: clock signal source
Signature · 2 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
author reviewer
#5 lore raw

PATCH v3 3/10 clk: rework calls to round and determine rate callbacks

In reply to Jerome Brunet

Rework the way the callbacks round_rate and determine_rate are called. The goal is to do this at a single point and make it easier to add conditions before calling them.

This rework is done to ease the integration of "protected" clock functionality.

---
 drivers/clk/clk.c | 78 +++++++++++++++++++++++++++++++------------------------
 1 file changed, 44 insertions(+), 34 deletions(-)
drivers/clk/clk.c +44 -34
index dceaf0ff23db..8cc4672414be 100644
@@ -833,16 +833,34 @@ static int clk_disable_unused(void)
 }
 late_initcall_sync(clk_disable_unused);
 
-static int clk_core_round_rate_nolock(struct clk_core *core,
-				      struct clk_rate_request *req)
+static int clk_core_determine_round(struct clk_core *core,
+				    struct clk_rate_request *req)
 {
-	struct clk_core *parent;
 	long rate;
 
-	lockdep_assert_held(&prepare_lock);
+	if (core->ops->determine_rate) {
+		return core->ops->determine_rate(core->hw, req);
+	} else if (core->ops->round_rate) {
+		rate = core->ops->round_rate(core->hw, req->rate,
+					     &req->best_parent_rate);
+		if (rate < 0)
+			return rate;
 
-	if (!core)
-		return 0;
+		req->rate = rate;
+	} else {
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static void clk_core_init_rate_req(struct clk_core *core,
+				   struct clk_rate_request *req)
+{
+	struct clk_core *parent;
+
+	if (WARN_ON(!core || !req))
+		return;
 
 	parent = core->parent;
 	if (parent) {
@@ -852,22 +870,24 @@ static int clk_core_round_rate_nolock(struct clk_core *core,
 		req->best_parent_hw = NULL;
 		req->best_parent_rate = 0;
 	}
+}
 
-	if (core->ops->determine_rate) {
-		return core->ops->determine_rate(core->hw, req);
-	} else if (core->ops->round_rate) {
-		rate = core->ops->round_rate(core->hw, req->rate,
-					     &req->best_parent_rate);
-		if (rate < 0)
-			return rate;
+static int clk_core_round_rate_nolock(struct clk_core *core,
+				      struct clk_rate_request *req)
+{
+	lockdep_assert_held(&prepare_lock);
 
-		req->rate = rate;
-	} else if (core->flags & CLK_SET_RATE_PARENT) {
-		return clk_core_round_rate_nolock(parent, req);
-	} else {
-		req->rate = core->rate;
-	}
+	if (!core)
+		return 0;
+
+	clk_core_init_rate_req(core, req);
+
+	if (core->ops->determine_rate || core->ops->round_rate)
+		return clk_core_determine_round(core, req);
+	else if (core->flags & CLK_SET_RATE_PARENT)
+		return clk_core_round_rate_nolock(core->parent, req);
 
+	req->rate = core->rate;
 	return 0;
 }
 
@@ -1356,36 +1376,26 @@ static struct clk_core *clk_calc_new_rates(struct clk_core *core,
 	clk_core_get_boundaries(core, &min_rate, &max_rate);
 
 	/* find the closest rate and parent clk/rate */
-	if (core->ops->determine_rate) {
+	if (core->ops->determine_rate || core->ops->round_rate) {
 		struct clk_rate_request req;
 
 		req.rate = rate;
 		req.min_rate = min_rate;
 		req.max_rate = max_rate;
-		if (parent) {
-			req.best_parent_hw = parent->hw;
-			req.best_parent_rate = parent->rate;
-		} else {
-			req.best_parent_hw = NULL;
-			req.best_parent_rate = 0;
-		}
 
-		ret = core->ops->determine_rate(core->hw, &req);
+		clk_core_init_rate_req(core, &req);
+
+		ret = clk_core_determine_round(core, &req);
 		if (ret < 0)
 			return NULL;
 
 		best_parent_rate = req.best_parent_rate;
 		new_rate = req.rate;
 		parent = req.best_parent_hw ? req.best_parent_hw->core : NULL;
-	} else if (core->ops->round_rate) {
-		ret = core->ops->round_rate(core->hw, rate,
-					    &best_parent_rate);
-		if (ret < 0)
-			return NULL;
 
-		new_rate = ret;
 		if (new_rate < min_rate || new_rate > max_rate)
 			return NULL;
+
 	} else if (!parent || !(core->flags & CLK_SET_RATE_PARENT)) {
 		/* pass-through clock without adjustable parent */
 		core->new_rate = core->rate;
Signature · 1 line
2.9.4
#6 lore raw

PATCH v3 3/10 clk: rework calls to round and determine rate callbacks

Quoted 3 lines · Jerome Brunet

Rework the way the callbacks round_rate and determine_rate are called. The goal is to do this at a single point and make it easier to add conditions before calling them.

This should also say that now we check the rate returned by determine_rate ops against the min/max rates so that we don't exceed the limits?

Quoted 16 lines

This rework is done to ease the integration of "protected" clock functionality.

---
 drivers/clk/clk.c | 78 +++++++++++++++++++++++++++++++------------------------
 1 file changed, 44 insertions(+), 34 deletions(-)
drivers/clk/clk.c +0 -0
index dceaf0ff23db..8cc4672414be 100644
@@ -833,16 +833,34 @@ static int clk_disable_unused(void)
 }
 late_initcall_sync(clk_disable_unused);

drivers/clk/clk.c static int clk_disable_unused(void) · line 842

Quoted 10 lines
drivers/clk/clk.c +2 -4
 
-static int clk_core_round_rate_nolock(struct clk_core *core,
-				      struct clk_rate_request *req)
+static int clk_core_determine_round(struct clk_core *core,
+				    struct clk_rate_request *req)
 {
-	struct clk_core *parent;
 	long rate;
 
-	lockdep_assert_held(&prepare_lock);

Best to leave this in place for clk_core_determine_round().

Quoted 9 lines
drivers/clk/clk.c +7 -1
+	if (core->ops->determine_rate) {
+		return core->ops->determine_rate(core->hw, req);
+	} else if (core->ops->round_rate) {
+		rate = core->ops->round_rate(core->hw, req->rate,
+					     &req->best_parent_rate);
+		if (rate < 0)
+			return rate;
 
-	if (!core)

drivers/clk/clk.c static int clk_disable_unused(void) · line 857

Quoted 10 lines
drivers/clk/clk.c +9 -1
-		return 0;
+		req->rate = rate;
+	} else {
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static void clk_core_init_rate_req(struct clk_core *core,

Can core be const?

Quoted 48 lines
drivers/clk/clk.c +21 -13
+				   struct clk_rate_request *req)
+{
+	struct clk_core *parent;
+
+	if (WARN_ON(!core || !req))
+		return;
 
 	parent = core->parent;
 	if (parent) {
@@ -852,22 +870,24 @@ static int clk_core_round_rate_nolock(struct clk_core *core,
 		req->best_parent_hw = NULL;
 		req->best_parent_rate = 0;
 	}
+}
 
-	if (core->ops->determine_rate) {
-		return core->ops->determine_rate(core->hw, req);
-	} else if (core->ops->round_rate) {
-		rate = core->ops->round_rate(core->hw, req->rate,
-					     &req->best_parent_rate);
-		if (rate < 0)
-			return rate;
+static int clk_core_round_rate_nolock(struct clk_core *core,
+				      struct clk_rate_request *req)
+{
+	lockdep_assert_held(&prepare_lock);
 
-		req->rate = rate;
-	} else if (core->flags & CLK_SET_RATE_PARENT) {
-		return clk_core_round_rate_nolock(parent, req);
-	} else {
-		req->rate = core->rate;
-	}
+	if (!core)
+		return 0;
+
+	clk_core_init_rate_req(core, req);
+
+	if (core->ops->determine_rate || core->ops->round_rate)
+		return clk_core_determine_round(core, req);
+	else if (core->flags & CLK_SET_RATE_PARENT)
+		return clk_core_round_rate_nolock(core->parent, req);
 
+	req->rate = core->rate;
 	return 0;
 }
 

drivers/clk/clk.c static struct clk_core *clk_calc_new_rates(struct clk_core *core, · line 1379

Quoted 5 lines
drivers/clk/clk.c +1 -1
@@ -1356,36 +1376,26 @@ static struct clk_core *clk_calc_new_rates(struct clk_core *core,
 	clk_core_get_boundaries(core, &min_rate, &max_rate);
 
 	/* find the closest rate and parent clk/rate */
-	if (core->ops->determine_rate) {
+	if (core->ops->determine_rate || core->ops->round_rate) {

This is the second time we check this, maybe another function for clk_core_can_round(core) is in order?

Quoted 23 lines
drivers/clk/clk.c +3 -8
 		struct clk_rate_request req;
 
 		req.rate = rate;
 		req.min_rate = min_rate;
 		req.max_rate = max_rate;
-		if (parent) {
-			req.best_parent_hw = parent->hw;
-			req.best_parent_rate = parent->rate;
-		} else {
-			req.best_parent_hw = NULL;
-			req.best_parent_rate = 0;
-		}
 
-		ret = core->ops->determine_rate(core->hw, &req);
+		clk_core_init_rate_req(core, &req);
+
+		ret = clk_core_determine_round(core, &req);
 		if (ret < 0)
 			return NULL;
 
 		best_parent_rate = req.best_parent_rate;
 		new_rate = req.rate;
 		parent = req.best_parent_hw ? req.best_parent_hw->core : NULL;

drivers/clk/clk.c static struct clk_core *clk_calc_new_rates(struct clk_core *core, · line 1398

Quoted 10 lines
drivers/clk/clk.c +1 -6
-	} else if (core->ops->round_rate) {
-		ret = core->ops->round_rate(core->hw, rate,
-					    &best_parent_rate);
-		if (ret < 0)
-			return NULL;
 
-		new_rate = ret;
 		if (new_rate < min_rate || new_rate > max_rate)
 			return NULL;
+

Nitpick: Kill this newline.

Signature · 2 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
author reviewer
#7 lore raw

PATCH v3 4/10 clk: use round rate to bail out early in set_rate

In reply to Jerome Brunet

The current implementation of clk_core_set_rate_nolock bails out early if the requested rate is exactly the same as the one set. It should bail out if the request would not result in rate a change. This important when rate is not exactly what is requested, which is fairly common with PLLs.

Ex: provider able to give any rate with steps of 100Hz
- 1st consumer request 48000Hz and gets it.
- 2nd consumer request 48010Hz as well. If we were to perform the usual mechanism, we would get 48000Hz as well. The clock would not change so there is no point performing any checks to make sure the clock can change, we know it won't.

This is important to prepare the addition of the clock protection mechanism

---
 drivers/clk/clk.c | 23 +++++++++++++++++++++--
 1 file changed, 21 insertions(+), 2 deletions(-)
drivers/clk/clk.c +21 -2
index 8cc4672414be..163cb9832f10 100644
@@ -1570,15 +1570,34 @@ static void clk_change_rate(struct clk_core *core)
 		clk_change_rate(core->new_child);
 }
 
+static unsigned long clk_core_req_round_rate_nolock(struct clk_core *core,
+						     unsigned long req_rate)
+{
+	int ret;
+	struct clk_rate_request req;
+
+	if (!core)
+		return 0;
+
+	clk_core_get_boundaries(core, &req.min_rate, &req.max_rate);
+	req.rate = req_rate;
+
+	ret = clk_core_round_rate_nolock(core, &req);
+
+	return ret ? 0 : req.rate;
+}
+
 static int clk_core_set_rate_nolock(struct clk_core *core,
 				    unsigned long req_rate)
 {
 	struct clk_core *top, *fail_clk;
-	unsigned long rate = req_rate;
+	unsigned long rate;
 
 	if (!core)
 		return 0;
 
+	rate = clk_core_req_round_rate_nolock(core, req_rate);
+
 	/* bail early if nothing to do */
 	if (rate == clk_core_get_rate_nolock(core))
 		return 0;
@@ -1587,7 +1606,7 @@ static int clk_core_set_rate_nolock(struct clk_core *core,
 		return -EBUSY;
 
 	/* calculate new rates and get the topmost changed clock */
-	top = clk_calc_new_rates(core, rate);
+	top = clk_calc_new_rates(core, req_rate);
 	if (!top)
 		return -EINVAL;
 
Signature · 1 line
2.9.4
#8 lore raw

PATCH v3 4/10 clk: use round rate to bail out early in set_rate

Quoted 1 line · Jerome Brunet

The current implementation of clk_core_set_rate_nolock bails out early if

Add () to functions please.

Quoted 2 lines

the requested rate is exactly the same as the one set. It should bail out if the request would not result in rate a change. This important when

s/in rate a change/in a rate change/
s/This important/This is important/

Quoted 1 line

rate is not exactly what is requested, which is fairly common with PLLs.

s/rate/the rate/

Quoted 7 lines

Ex: provider able to give any rate with steps of 100Hz
- 1st consumer request 48000Hz and gets it.
- 2nd consumer request 48010Hz as well. If we were to perform the usual mechanism, we would get 48000Hz as well. The clock would not change so there is no point performing any checks to make sure the clock can change, we know it won't.

I think Peter reported a similar problem as to what you're describing. Can you further explain a problem situation that this patch is fixing based on that thread (I can find the link if needed)? Some of this series if fixing rate constraints actually, so please Cc him on future patch sets.

Quoted 15 lines

This is important to prepare the addition of the clock protection mechanism

---
 drivers/clk/clk.c | 23 +++++++++++++++++++++--
 1 file changed, 21 insertions(+), 2 deletions(-)
drivers/clk/clk.c +0 -0
index 8cc4672414be..163cb9832f10 100644
@@ -1570,15 +1570,34 @@ static void clk_change_rate(struct clk_core *core)
 		clk_change_rate(core->new_child);

drivers/clk/clk.c static void clk_change_rate(struct clk_core *core) · line 1580

Quoted 10 lines
drivers/clk/clk.c +8 -0
 }
 
+static unsigned long clk_core_req_round_rate_nolock(struct clk_core *core,
+						     unsigned long req_rate)
+{
+	int ret;
+	struct clk_rate_request req;
+
+	if (!core)
+		return 0;

This is impossible because the only call site checks for core being NULL already.

drivers/clk/clk.c static void clk_change_rate(struct clk_core *core) · line 1587

Quoted 7 lines
drivers/clk/clk.c +7 -0
+
+	clk_core_get_boundaries(core, &req.min_rate, &req.max_rate);
+	req.rate = req_rate;
+
+	ret = clk_core_round_rate_nolock(core, &req);
+
+	return ret ? 0 : req.rate;

What if the return value is negative? We should bail the set rate call instead of continuing on?

Signature · 2 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
author reviewer
#9 lore raw

PATCH v3 4/10 clk: use round rate to bail out early in set_rate

Quoted 23 lines · Stephen Boyd
Quoted 1 line · Jerome Brunet

The current implementation of clk_core_set_rate_nolock bails out early if

Add () to functions please.

Quoted 2 lines

the requested rate is exactly the same as the one set. It should bail out if the request would not result in rate a change.??This important when

s/in rate a change/in a rate change/
s/This important/This is important/

Quoted 1 line

rate is not exactly what is requested, which is fairly common with PLLs.

s/rate/the rate/

Quoted 7 lines

Ex: provider able to give any rate with steps of 100Hz
?- 1st consumer request 48000Hz and gets it.
?- 2nd consumer request 48010Hz as well. If we were to perform the usual ???mechanism, we would get 48000Hz as well. The clock would not change so ???there is no point performing any checks to make sure the clock can ???change, we know it won't.

Quoted 6 lines

I think Peter reported a similar problem as to what you're describing. Can you further explain a problem situation that this patch is fixing based on that thread (I can find the link if needed)?
Some of this series if fixing rate constraints actually, so please Cc him on future patch sets.

I had not seen the thread you referring to.
I assume Peter is Peter De Schrijver and the thread is:

http://lkml.kernel.org/r/1490103807-21821-1-git-send-email-pdeschrijver at nvidia.c om

Peter is right, There is indeed a problem when the current rate is out of the requested range.

I'm not sure about the proposed solution though. Even the rate set by set_rate_range() should go trough the bail-out mechanism because of the use-case I have explained here.

After spending some time on it, I realized that patch 7 is useless, as the call to clk_core_set_rate_nolock() with core->req_rate is a no-op and will never fail.

We could request the rate to be changed to nearest rate range limit (here is a candidate fix doing that [0]

But then we get to a more fundamental issue of the rate range mechanism.

Take the example of Peter:
* You had 500Mhz and you set a range of [100-300] MHz
* The logical thing to do would be to request the clock rate to change to 300MHz, right ?
* Hw capabilities being what they are, the rate is unfortunately rounded to 301Mhz.
* In the end, you are out of the range and the call fails.

That is when the clock only implement round_rate(). If it implement determine_rate(), it could take the range into account when rounding the rate. However, I doubt many clock drivers are taking care of this corner case, if any.

The clean way to address this would be to have all clock drivers use determine_rate() and make sure they all that the case into account, and delete the round_rate() ... not happening tomorrow.

The consistent way would be to systematically fail if the current rate is out of the requested range ... a bit rude maybe.

The proposed patch [0] does it's best to change the rate, but may fail as explained above ...

For now, I have dropped patch 7 and pushed patch [0] at the end of the queue. Since It is really related to the clock protect mechanism, we should probably discuss this in another thread.

[0]: https://github.com/jeromebrunet/linux/commit/235e477f346a9e8d115dda257f9f73
834151bd7f

Quoted 22 lines
Quoted 22 lines

This is important to prepare the addition of the clock protection mechanism

---
?drivers/clk/clk.c | 23 +++++++++++++++++++++--
?1 file changed, 21 insertions(+), 2 deletions(-)

drivers/clk/clk.c +0 -0
index 8cc4672414be..163cb9832f10 100644
@@ -1570,15 +1570,34 @@ static void clk_change_rate(struct clk_core *core)
 ?		clk_change_rate(core->new_child);
 ?}

?

drivers/clk/clk.c +2 -0
+static unsigned long clk_core_req_round_rate_nolock(struct clk_core *core,
+						?????unsigned long

req_rate)
+{

Quoted 9 lines

drivers/clk/clk.c static void clk_change_rate(struct clk_core *core) · line 1580

Quoted 5 lines
drivers/clk/clk.c +5 -0
+	int ret;
+	struct clk_rate_request req;
+
+	if (!core)
+		return 0;

This is impossible because the only call site checks for core being NULL already.

This more or less like the previous comments on lockdep_assert. Most (should be all) "_no_lock" function check the prepare_lock and the core pointer. Even when it is not strictly necessary, I think we should be consistent
about it.

In the unlikely event this function is used some place else, it would avoid bad surprise

So?if it is OK with you, I would prefer to keep this check and add the check of the prepare lock. Maybe I could go over the other "_nolock" functions in clk.c to verify they are all doing it ? What do you think ?

Quoted 9 lines

drivers/clk/clk.c static void clk_change_rate(struct clk_core *core) · line 1587

Quoted 7 lines
drivers/clk/clk.c +7 -0
+
+	clk_core_get_boundaries(core, &req.min_rate, &req.max_rate);
+	req.rate = req_rate;
+
+	ret = clk_core_round_rate_nolock(core, &req);
+
+	return ret ? 0 : req.rate;

What if the return value is negative?

Here we are trying to return a rate, so unsigned long.
I think (and I remember discussing it with Mike sometimes ago) that a 0 clock rate quite often represent an error.?

Quoted 2 lines

We should bail the set rate
call instead of continuing on?

I don't think this for this particular function to decide. It should try compute what the rate would be. It's up to the calling function to decide what do with this 0 (error)

To answer your question, I think that if we can't figure out the what the rate would be, we should not error right away and just let the regular process happen (no bail-out) ... If there is a problem, it will error anyway

Quoted 1 line
#10 lore raw

PATCH v3 4/10 clk: use round rate to bail out early in set_rate

Quoted 18 lines · Jerome Brunet
Quoted 10 lines · Stephen Boyd
Quoted 7 lines · Jerome Brunet

Ex: provider able to give any rate with steps of 100Hz
?- 1st consumer request 48000Hz and gets it.
?- 2nd consumer request 48010Hz as well. If we were to perform the usual ???mechanism, we would get 48000Hz as well. The clock would not change so ???there is no point performing any checks to make sure the clock can ???change, we know it won't.

Quoted 6 lines

I think Peter reported a similar problem as to what you're describing. Can you further explain a problem situation that this patch is fixing based on that thread (I can find the link if needed)?
Some of this series if fixing rate constraints actually, so please Cc him on future patch sets.

Quoted 8 lines

I had not seen the thread you referring to.
I assume Peter is Peter De Schrijver and the thread is:

http://lkml.kernel.org/r/1490103807-21821-1-git-send-email-pdeschrijver at nvidia.c om

Peter is right, There is indeed a problem when the current rate is out of the requested range.

Yes. Thanks for figuring out my vague statement.

Quoted 22 lines

I'm not sure about the proposed solution though. Even the rate set by set_rate_range() should go trough the bail-out mechanism because of the use-case I have explained here.

After spending some time on it, I realized that patch 7 is useless, as the call to clk_core_set_rate_nolock() with core->req_rate is a no-op and will never fail.

We could request the rate to be changed to nearest rate range limit (here is a candidate fix doing that [0]

But then we get to a more fundamental issue of the rate range mechanism.

Take the example of Peter:
* You had 500Mhz and you set a range of [100-300] MHz
* The logical thing to do would be to request the clock rate to change to 300MHz, right ?
* Hw capabilities being what they are, the rate is unfortunately rounded to 301Mhz.
* In the end, you are out of the range and the call fails.

Quoted 7 lines

That is when the clock only implement round_rate(). If it implement determine_rate(), it could take the range into account when rounding the rate. However, I doubt many clock drivers are taking care of this corner case, if any.

The clean way to address this would be to have all clock drivers use determine_rate() and make sure they all that the case into account, and delete the round_rate() ... not happening tomorrow.

Yes the migration path is to use determine_rate() and have providers handle min/max adjustments themselves. I don't think we really can do anything about the problem you mention though. If someone wants to use rate range setting, then the provider clks need to handle the ranges appropriately. We can't do anything more in the framework if they only implement round_rate() and that returns something out of range.

Quoted 10 lines

The consistent way would be to systematically fail if the current rate is out of the requested range ... a bit rude maybe.

The proposed patch [0] does it's best to change the rate, but may fail as explained above ...

For now, I have dropped patch 7 and pushed patch [0] at the end of the queue. Since It is really related to the clock protect mechanism, we should probably discuss this in another thread.

Ok.

Quoted 41 lines

[0]: https://github.com/jeromebrunet/linux/commit/235e477f346a9e8d115dda257f9f73
834151bd7f

Quoted 22 lines
Quoted 22 lines

This is important to prepare the addition of the clock protection mechanism

---
?drivers/clk/clk.c | 23 +++++++++++++++++++++--
?1 file changed, 21 insertions(+), 2 deletions(-)

drivers/clk/clk.c +0 -0
index 8cc4672414be..163cb9832f10 100644
@@ -1570,15 +1570,34 @@ static void clk_change_rate(struct clk_core *core)
 ?		clk_change_rate(core->new_child);
 ?}

?

drivers/clk/clk.c +2 -0
+static unsigned long clk_core_req_round_rate_nolock(struct clk_core *core,
+						?????unsigned long

req_rate)
+{

Quoted 9 lines

drivers/clk/clk.c static void clk_change_rate(struct clk_core *core) · line 1580

Quoted 5 lines
drivers/clk/clk.c +5 -0
+	int ret;
+	struct clk_rate_request req;
+
+	if (!core)
+		return 0;

This is impossible because the only call site checks for core being NULL already.

This more or less like the previous comments on lockdep_assert. Most (should be all) "_no_lock" function check the prepare_lock and the core pointer. Even when it is not strictly necessary, I think we should be consistent
about it.

Quoted 6 lines

In the unlikely event this function is used some place else, it would avoid bad surprise

So?if it is OK with you, I would prefer to keep this check and add the check of the prepare lock. Maybe I could go over the other "_nolock" functions in clk.c to verify they are all doing it ? What do you think ?

Please don't send a patch to make things consistent. I'm ok with the NULL check here.

Quoted 19 lines
Quoted 10 lines

drivers/clk/clk.c static void clk_change_rate(struct clk_core *core) · line 1587

Quoted 8 lines
drivers/clk/clk.c +7 -0
+
+	clk_core_get_boundaries(core, &req.min_rate, &req.max_rate);
+	req.rate = req_rate;
+
+	ret = clk_core_round_rate_nolock(core, &req);
+
+	return ret ? 0 : req.rate;

What if the return value is negative?

Here we are trying to return a rate, so unsigned long.
I think (and I remember discussing it with Mike sometimes ago) that a 0 clock rate quite often represent an error.?

Quoted 2 lines

We should bail the set rate
call instead of continuing on?

Quoted 10 lines

I don't think this for this particular function to decide. It should try compute what the rate would be. It's up to the calling function to decide what do with this 0 (error)

To answer your question, I think that if we can't figure out the what the rate would be, we should not error right away and just let the regular process happen (no bail-out) ... If there is a problem, it will error anyway

Quoted 1 line

Hmm. Ok. I seem to recall that if set_rate fails in the middle of the tree we won't report it as an error. Maybe I'm misremembering though so if I'm wrong then everything is good.

Signature · 2 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
author reviewer
#11 lore raw

PATCH v3 5/10 clk: add support for clock protection

In reply to Jerome Brunet

The patch adds clk_protect and clk_unprotect to the CCF API. These functions allow a consumer to inform the system that the rate of clock is critical to for its operations and it can't tolerate other consumers changing the rate or introducing glitches while the clock is protected.

---
 drivers/clk/clk.c            | 205 +++++++++++++++++++++++++++++++++++++++++--
 include/linux/clk-provider.h |   1 +
 include/linux/clk.h          |  29 ++++++
 3 files changed, 229 insertions(+), 6 deletions(-)
drivers/clk/clk.c +199 -6
index 163cb9832f10..d688b8f59a59 100644
@@ -60,6 +60,7 @@ struct clk_core {
 	bool			orphan;
 	unsigned int		enable_count;
 	unsigned int		prepare_count;
+	unsigned int		protect_count;
 	unsigned long		min_rate;
 	unsigned long		max_rate;
 	unsigned long		accuracy;
@@ -84,6 +85,7 @@ struct clk {
 	const char *con_id;
 	unsigned long min_rate;
 	unsigned long max_rate;
+	unsigned long protect_count;
 	struct hlist_node clks_node;
 };
 
@@ -148,6 +150,11 @@ static void clk_enable_unlock(unsigned long flags)
 	spin_unlock_irqrestore(&enable_lock, flags);
 }
 
+static bool clk_core_rate_is_protected(struct clk_core *core)
+{
+	return core->protect_count;
+}
+
 static bool clk_core_is_prepared(struct clk_core *core)
 {
 	/*
@@ -328,6 +335,11 @@ bool clk_hw_is_prepared(const struct clk_hw *hw)
 	return clk_core_is_prepared(hw->core);
 }
 
+bool clk_hw_rate_is_protected(const struct clk_hw *hw)
+{
+	return clk_core_rate_is_protected(hw->core);
+}
+
 bool clk_hw_is_enabled(const struct clk_hw *hw)
 {
 	return clk_core_is_enabled(hw->core);
@@ -466,6 +478,102 @@ EXPORT_SYMBOL_GPL(__clk_mux_determine_rate_closest);
 
 /***        clk api        ***/
 
+static void clk_core_rate_unprotect(struct clk_core *core)
+{
+	lockdep_assert_held(&prepare_lock);
+
+	if (!core)
+		return;
+
+	if (WARN_ON(core->protect_count == 0))
+		return;
+
+	if (--core->protect_count > 0)
+		return;
+
+	clk_core_rate_unprotect(core->parent);
+}
+
+/**
+ * clk_rate_unprotect - unprotect the rate of a clock source
+ * @clk: the clk being unprotected
+ *
+ * clk_unprotect completes a critical section during which the clock
+ * consumer cannot tolerate any change to the clock rate. If no other clock
+ * consumers have protected clocks in the parent chain, then calls to this
+ * function will allow the clocks in the parent chain to change rates
+ * freely.
+ *
+ * Unlike the clk_set_rate_range method, which allows the rate to change
+ * within a given range, protected clocks cannot have their rate changed,
+ * either directly or indirectly due to changes further up the parent chain
+ * of clocks.
+ *
+ * Calls to clk_unprotect must be balanced with calls to clk_protect. Calls
+ * to this function may sleep, and do not return error status.
+ */
+void clk_rate_unprotect(struct clk *clk)
+{
+	if (!clk)
+		return;
+
+	clk_prepare_lock();
+
+	/*
+	 * if there is something wrong with this consumer protect count, stop
+	 * here before messing with the provider
+	 */
+	if (WARN_ON(clk->protect_count <= 0))
+		goto out;
+
+	clk_core_rate_unprotect(clk->core);
+	clk->protect_count--;
+out:
+	clk_prepare_unlock();
+}
+EXPORT_SYMBOL_GPL(clk_rate_unprotect);
+
+static void clk_core_rate_protect(struct clk_core *core)
+{
+	lockdep_assert_held(&prepare_lock);
+
+	if (!core)
+		return;
+
+	if (core->protect_count == 0)
+		clk_core_rate_protect(core->parent);
+
+	core->protect_count++;
+}
+
+/**
+ * clk_rate_protect - protect a clock source
+ * @clk: the clk being protected
+ *
+ * clk_protect begins a critical section during which the clock consumer
+ * cannot tolerate any change to the clock rate. This results in all clocks
+ * up the parent chain to also be rate-protected.
+ *
+ * Unlike the clk_set_rate_range method, which allows the rate to change
+ * within a given range, protected clocks cannot have their rate changed,
+ * either directly or indirectly due to changes further up the parent chain
+ * of clocks.
+ *
+ * Calls to clk_protect should be balanced with calls to clk_unprotect.
+ * Calls to this function may sleep, and do not return error status.
+ */
+void clk_rate_protect(struct clk *clk)
+{
+	if (!clk)
+		return;
+
+	clk_prepare_lock();
+	clk_core_rate_protect(clk->core);
+	clk->protect_count++;
+	clk_prepare_unlock();
+}
+EXPORT_SYMBOL_GPL(clk_rate_protect);
+
 static void clk_core_unprepare(struct clk_core *core)
 {
 	lockdep_assert_held(&prepare_lock);
@@ -838,7 +946,15 @@ static int clk_core_determine_round(struct clk_core *core,
 {
 	long rate;
 
-	if (core->ops->determine_rate) {
+	/*
+	 * At this point, core protection will be disabled if
+	 * - if the provider is not protected at all
+	 * - if the calling consumer is the only one protecting the
+	 *   provider (and only once)
+	 */
+	if (clk_core_rate_is_protected(core)) {
+		req->rate = core->rate;
+	} else if (core->ops->determine_rate) {
 		return core->ops->determine_rate(core->hw, req);
 	} else if (core->ops->round_rate) {
 		rate = core->ops->round_rate(core->hw, req->rate,
@@ -944,10 +1060,17 @@ long clk_round_rate(struct clk *clk, unsigned long rate)
 
 	clk_prepare_lock();
 
+	if (clk->protect_count)
+		clk_core_rate_unprotect(clk->core);
+
 	clk_core_get_boundaries(clk->core, &req.min_rate, &req.max_rate);
 	req.rate = rate;
 
 	ret = clk_core_round_rate_nolock(clk->core, &req);
+
+	if (clk->protect_count)
+		clk_core_rate_protect(clk->core);
+
 	clk_prepare_unlock();
 
 	if (ret)
@@ -1575,15 +1698,24 @@ static unsigned long clk_core_req_round_rate_nolock(struct clk_core *core,
 {
 	int ret;
 	struct clk_rate_request req;
+	unsigned int cnt = core->protect_count;
 
 	if (!core)
 		return 0;
 
+	/* simulate what the rate would be if it could be freely set */
+	while (core->protect_count)
+		clk_core_rate_unprotect(core);
+
 	clk_core_get_boundaries(core, &req.min_rate, &req.max_rate);
 	req.rate = req_rate;
 
 	ret = clk_core_round_rate_nolock(core, &req);
 
+	/* restore the protection */
+	while (core->protect_count < cnt)
+		clk_core_rate_protect(core);
+
 	return ret ? 0 : req.rate;
 }
 
@@ -1602,6 +1734,10 @@ static int clk_core_set_rate_nolock(struct clk_core *core,
 	if (rate == clk_core_get_rate_nolock(core))
 		return 0;
 
+	/* fail on a direct rate set of a protected provider */
+	if (clk_core_rate_is_protected(core))
+		return -EBUSY;
+
 	if ((core->flags & CLK_SET_RATE_GATE) && core->prepare_count)
 		return -EBUSY;
 
@@ -1658,8 +1794,14 @@ int clk_set_rate(struct clk *clk, unsigned long rate)
 	/* prevent racing with updates to the clock topology */
 	clk_prepare_lock();
 
+	if (clk->protect_count)
+		clk_core_rate_unprotect(clk->core);
+
 	ret = clk_core_set_rate_nolock(clk->core, rate);
 
+	if (clk->protect_count)
+		clk_core_rate_protect(clk->core);
+
 	clk_prepare_unlock();
 
 	return ret;
@@ -1690,12 +1832,18 @@ int clk_set_rate_range(struct clk *clk, unsigned long min, unsigned long max)
 
 	clk_prepare_lock();
 
+	if (clk->protect_count)
+		clk_core_rate_unprotect(clk->core);
+
 	if (min != clk->min_rate || max != clk->max_rate) {
 		clk->min_rate = min;
 		clk->max_rate = max;
 		ret = clk_core_set_rate_nolock(clk->core, clk->core->req_rate);
 	}
 
+	if (clk->protect_count)
+		clk_core_rate_protect(clk->core);
+
 	clk_prepare_unlock();
 
 	return ret;
@@ -1837,6 +1985,9 @@ static int clk_core_set_parent_nolock(struct clk_core *core,
 	if ((core->flags & CLK_SET_PARENT_GATE) && core->prepare_count)
 		return -EBUSY;
 
+	if (clk_core_rate_is_protected(core))
+		return -EBUSY;
+
 	/* try finding the new parent index */
 	if (parent) {
 		p_index = clk_fetch_parent_index(core, parent);
@@ -1894,8 +2045,16 @@ int clk_set_parent(struct clk *clk, struct clk *parent)
 		return 0;
 
 	clk_prepare_lock();
+
+	if (clk->protect_count)
+		clk_core_rate_unprotect(clk->core);
+
 	ret = clk_core_set_parent_nolock(clk->core,
 					 parent ? parent->core : NULL);
+
+	if (clk->protect_count)
+		clk_core_rate_protect(clk->core);
+
 	clk_prepare_unlock();
 
 	return ret;
@@ -1909,6 +2068,9 @@ static int clk_core_set_phase_nolock(struct clk_core *core, int degrees)
 	if (!core)
 		return 0;
 
+	if (clk_core_rate_is_protected(core))
+		return -EBUSY;
+
 	trace_clk_set_phase(core, degrees);
 
 	if (core->ops->set_phase)
@@ -1952,7 +2114,15 @@ int clk_set_phase(struct clk *clk, int degrees)
 		degrees += 360;
 
 	clk_prepare_lock();
+
+	if (clk->protect_count)
+		clk_core_rate_unprotect(clk->core);
+
 	ret = clk_core_set_phase_nolock(clk->core, degrees);
+
+	if (clk->protect_count)
+		clk_core_rate_protect(clk->core);
+
 	clk_prepare_unlock();
 
 	return ret;
@@ -2039,11 +2209,12 @@ static void clk_summary_show_one(struct seq_file *s, struct clk_core *c,
 	if (!c)
 		return;
 
-	seq_printf(s, "%*s%-*s %11d %12d %11lu %10lu %-3d\n",
+	seq_printf(s, "%*s%-*s %11d %12d %12d %11lu %10lu %-3d\n",
 		   level * 3 + 1, "",
 		   30 - level * 3, c->name,
-		   c->enable_count, c->prepare_count, clk_core_get_rate(c),
-		   clk_core_get_accuracy(c), clk_core_get_phase(c));
+		   c->enable_count, c->prepare_count, c->protect_count,
+		   clk_core_get_rate(c), clk_core_get_accuracy(c),
+		   clk_core_get_phase(c));
 }
 
 static void clk_summary_show_subtree(struct seq_file *s, struct clk_core *c,
@@ -2065,8 +2236,8 @@ static int clk_summary_show(struct seq_file *s, void *data)
 	struct clk_core *c;
 	struct hlist_head **lists = (struct hlist_head **)s->private;
 
-	seq_puts(s, "   clock                         enable_cnt  prepare_cnt        rate   accuracy   phase\n");
-	seq_puts(s, "----------------------------------------------------------------------------------------\n");
+	seq_puts(s, "   clock                         enable_cnt  prepare_cnt  protect_cnt        rate   accuracy   phase\n");
+	seq_puts(s, "----------------------------------------------------------------------------------------------------\n");
 
 	clk_prepare_lock();
 
@@ -2101,6 +2272,7 @@ static void clk_dump_one(struct seq_file *s, struct clk_core *c, int level)
 	seq_printf(s, "\"%s\": { ", c->name);
 	seq_printf(s, "\"enable_count\": %d,", c->enable_count);
 	seq_printf(s, "\"prepare_count\": %d,", c->prepare_count);
+	seq_printf(s, "\"protect_count\": %d,", c->protect_count);
 	seq_printf(s, "\"rate\": %lu,", clk_core_get_rate(c));
 	seq_printf(s, "\"accuracy\": %lu,", clk_core_get_accuracy(c));
 	seq_printf(s, "\"phase\": %d", clk_core_get_phase(c));
@@ -2231,6 +2403,11 @@ static int clk_debug_create_one(struct clk_core *core, struct dentry *pdentry)
 	if (!d)
 		goto err_out;
 
+	d = debugfs_create_u32("clk_protect_count", S_IRUGO, core->dentry,
+			(u32 *)&core->protect_count);
+	if (!d)
+		goto err_out;
+
 	d = debugfs_create_u32("clk_notifier_count", S_IRUGO, core->dentry,
 			(u32 *)&core->notifier_count);
 	if (!d)
@@ -2794,6 +2971,11 @@ void clk_unregister(struct clk *clk)
 	if (clk->core->prepare_count)
 		pr_warn("%s: unregistering prepared clock: %s\n",
 					__func__, clk->core->name);
+
+	if (clk->core->protect_count)
+		pr_warn("%s: unregistering protected clock: %s\n",
+					__func__, clk->core->name);
+
 	kref_put(&clk->core->ref, __clk_release);
 unlock:
 	clk_prepare_unlock();
@@ -2952,6 +3134,17 @@ void __clk_put(struct clk *clk)
 
 	clk_prepare_lock();
 
+	/*
+	 * Before calling clk_put, all calls to clk_rate_protect from a given
+	 * user must be balanced with calls to clk_rate_unprotect and by that
+	 * same user
+	 */
+	WARN_ON(clk->protect_count);
+
+	/* We voiced our concern, let's sanitize the situation */
+	for (; clk->protect_count; clk->protect_count--)
+		clk_core_rate_unprotect(clk->core);
+
 	hlist_del(&clk->clks_node);
 	if (clk->min_rate > clk->core->req_rate ||
 	    clk->max_rate < clk->core->req_rate)
include/linux/clk-provider.h +1 -0
index a428aec36ace..ebd7df5f375f 100644
@@ -739,6 +739,7 @@ unsigned long clk_hw_get_rate(const struct clk_hw *hw);
 unsigned long __clk_get_flags(struct clk *clk);
 unsigned long clk_hw_get_flags(const struct clk_hw *hw);
 bool clk_hw_is_prepared(const struct clk_hw *hw);
+bool clk_hw_rate_is_protected(const struct clk_hw *hw);
 bool clk_hw_is_enabled(const struct clk_hw *hw);
 bool __clk_is_enabled(struct clk *clk);
 struct clk *__clk_lookup(const char *name);
include/linux/clk.h +29 -0
index 91bd464f4c9b..b60c36f2e6b0 100644
@@ -331,6 +331,30 @@ struct clk *devm_clk_get(struct device *dev, const char *id);
  */
 struct clk *devm_get_clk_from_child(struct device *dev,
 				    struct device_node *np, const char *con_id);
+/**
+ * clk_rate_protect - inform the system when the clock rate must be protected.
+ * @clk: clock source
+ *
+ * This function informs the system that the consumer protecting the clock
+ * depends on the rate of the clock source and can't tolerate any glitches
+ * introduced by further clock rate change or re-parenting of the clock source.
+ *
+ * Must not be called from within atomic context.
+ */
+void clk_rate_protect(struct clk *clk);
+
+/**
+ * clk_rate_unprotect - release the protection of the clock source.
+ * @clk: clock source
+ *
+ * This function informs the system that the consumer previously protecting the
+ * clock rate can now deal with other consumer altering the clock source rate
+ *
+ * The caller must balance the number of rate_protect and rate_unprotect calls.
+ *
+ * Must not be called from within atomic context.
+ */
+void clk_rate_unprotect(struct clk *clk);
 
 /**
  * clk_enable - inform the system when the clock source should be running.
@@ -583,6 +607,11 @@ static inline void clk_bulk_put(int num_clks, struct clk_bulk_data *clks) {}
 
 static inline void devm_clk_put(struct device *dev, struct clk *clk) {}
 
+
+static inline void clk_protect(struct clk *clk) {}
+
+static inline void clk_unprotect(struct clk *clk) {}
+
 static inline int clk_enable(struct clk *clk)
 {
 	return 0;
Signature · 1 line
2.9.4
#12 lore raw

PATCH v3 5/10 clk: add support for clock protection

Quoted 3 lines · Jerome Brunet

The patch adds clk_protect and clk_unprotect to the CCF API. These functions allow a consumer to inform the system that the rate of clock is critical to for its operations and it can't tolerate other consumers

s/for//

Quoted 31 lines

changing the rate or introducing glitches while the clock is protected.

drivers/clk/clk.c +24 -0
index 163cb9832f10..d688b8f59a59 100644
+
+/**
+ * clk_rate_unprotect - unprotect the rate of a clock source
+ * @clk: the clk being unprotected
+ *
+ * clk_unprotect completes a critical section during which the clock
+ * consumer cannot tolerate any change to the clock rate. If no other clock
+ * consumers have protected clocks in the parent chain, then calls to this
+ * function will allow the clocks in the parent chain to change rates
+ * freely.
+ *
+ * Unlike the clk_set_rate_range method, which allows the rate to change
+ * within a given range, protected clocks cannot have their rate changed,
+ * either directly or indirectly due to changes further up the parent chain
+ * of clocks.
+ *
+ * Calls to clk_unprotect must be balanced with calls to clk_protect. Calls
+ * to this function may sleep, and do not return error status.
+ */
+void clk_rate_unprotect(struct clk *clk)
+{
+	if (!clk)
+		return;
+

drivers/clk/clk.c EXPORT_SYMBOL_GPL(__clk_mux_determine_rate_closest); · line 529

Quoted 10 lines
drivers/clk/clk.c +10 -0
+	clk_prepare_lock();
+
+	/*
+	 * if there is something wrong with this consumer protect count, stop
+	 * here before messing with the provider
+	 */
+	if (WARN_ON(clk->protect_count <= 0))
+		goto out;
+
+	clk_core_rate_unprotect(clk->core);

Can we make this stuff non-recursive? I know that this is basically a copy paste of prepare/unprepare code and recursion is nice and elegant, but we really don't need to do it when we could have a loop that's the same and doesn't blow up our stack frame usage. I'll send a patch for prepare/enable so you get the idea.

Quoted 5 lines
drivers/clk/clk.c +5 -0
+	clk->protect_count--;
+out:
+	clk_prepare_unlock();
+}
+EXPORT_SYMBOL_GPL(clk_rate_unprotect);

[..]

Quoted 5 lines
drivers/clk/clk.c +1 -0
+
@@ -2952,6 +3134,17 @@ void __clk_put(struct clk *clk)
 
 	clk_prepare_lock();
 

drivers/clk/clk.c void __clk_put(struct clk *clk) · line 3146

Quoted 10 lines
drivers/clk/clk.c +10 -0
+	/*
+	 * Before calling clk_put, all calls to clk_rate_protect from a given
+	 * user must be balanced with calls to clk_rate_unprotect and by that
+	 * same user
+	 */
+	WARN_ON(clk->protect_count);
+
+	/* We voiced our concern, let's sanitize the situation */
+	for (; clk->protect_count; clk->protect_count--)
+		clk_core_rate_unprotect(clk->core);

Does this do anything different than:

	clk->core->protect_count -= clk->protect_count;
	clk->protect_count = 1;
	clk_core_rate_unprotect(clk->core);

Just seems better to not do a loop here.

Quoted 9 lines
include/linux/clk.h +1 -0
index 91bd464f4c9b..b60c36f2e6b0 100644
@@ -331,6 +331,30 @@ struct clk *devm_clk_get(struct device *dev, const char *id);
  */
 struct clk *devm_get_clk_from_child(struct device *dev,
 				    struct device_node *np, const char *con_id);
+/**

include/linux/clk.h struct clk *devm_clk_get(struct device *dev, const char *id); · line 344

Quoted 10 lines
include/linux/clk.h +10 -0
+ * clk_rate_protect - inform the system when the clock rate must be protected.
+ * @clk: clock source
+ *
+ * This function informs the system that the consumer protecting the clock
+ * depends on the rate of the clock source and can't tolerate any glitches
+ * introduced by further clock rate change or re-parenting of the clock source.
+ *
+ * Must not be called from within atomic context.
+ */
+void clk_rate_protect(struct clk *clk);

Is there any plan to use this clk_rate_protect() API? It seems inherently racy for a clk consumer to call clk_set_rate() and then this clk_rate_protect() API after that to lock the rate in. How about we leave this out of the consumer API until a user needs it?

I'm tempted to say that we could do this rate locking stuff with clk_set_rate_range(), but with more thought that doesn't seem possible because there's a subtle difference. The range API is willing to accept a range of frequencies, and calling clk_set_rate_range() with some exact frequency should fail if that exact frequency can't be met. With this API and the subsequent clk_set_rate_protect() API we're willing to accept that the rate we call clk_set_rate_protect() with could be different than the rate we actually get.

Finally, When does a consumer want the rate of a clk to change after they call clk_set_rate() on it? I would guess that very few consumers would be willing to accept that. Which begs the question, if anyone will keep calling clk_set_rate() after this API (and the clk_set_rate_protect() API) is added. It almost seems like we would want it to be opt-out, instead of opt-in, so that consumers would call clk_set_rate() and expect it to be a stable clk rate after that, and they would call clk_set_rate_trample_on_me() or something properly named when they don't care what the rate is after they call the API.

include/linux/clk.h struct clk *devm_clk_get(struct device *dev, const char *id); · line 351

Quoted 7 lines
include/linux/clk.h +7 -0
+
+/**
+ * clk_rate_unprotect - release the protection of the clock source.
+ * @clk: clock source
+ *
+ * This function informs the system that the consumer previously protecting the
+ * clock rate can now deal with other consumer altering the clock source rate

other consumers

include/linux/clk.h struct clk *devm_clk_get(struct device *dev, const char *id); · line 353

Quoted 2 lines
include/linux/clk.h +2 -0
+ *
+ * The caller must balance the number of rate_protect and rate_unprotect calls.

Please say clk_rate_protect() and clk_rate_unprotect() here.

Signature · 2 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
author reviewer
#13 lore raw

PATCH v3 5/10 clk: add support for clock protection

Quoted 47 lines · Stephen Boyd
Quoted 3 lines · Jerome Brunet

The patch adds clk_protect and clk_unprotect to the CCF API. These functions allow a consumer to inform the system that the rate of clock is critical to for its operations and it can't tolerate other consumers

s/for//

Quoted 40 lines

changing the rate or introducing glitches while the clock is protected.

drivers/clk/clk.c +28 -0
index 163cb9832f10..d688b8f59a59 100644
+
+/**
+ * clk_rate_unprotect - unprotect the rate of a clock source
+ * @clk: the clk being unprotected
+ *
+ * clk_unprotect completes a critical section during which the clock
+ * consumer cannot tolerate any change to the clock rate. If no other clock
+ * consumers have protected clocks in the parent chain, then calls to this
+ * function will allow the clocks in the parent chain to change rates
+ * freely.
+ *
+ * Unlike the clk_set_rate_range method, which allows the rate to change
+ * within a given range, protected clocks cannot have their rate changed,
+ * either directly or indirectly due to changes further up the parent chain
+ * of clocks.
+ *
+ * Calls to clk_unprotect must be balanced with calls to clk_protect. Calls
+ * to this function may sleep, and do not return error status.
+ */
+void clk_rate_unprotect(struct clk *clk)
+{
+	if (!clk)
+		return;
+
+	clk_prepare_lock();
+
+	/*
+	?* if there is something wrong with this consumer protect count,

stop

drivers/clk/clk.c +4 -0
+	?* here before messing with the provider
+	?*/
+	if (WARN_ON(clk->protect_count <= 0))
+		goto out;
Quoted 8 lines

drivers/clk/clk.c

Quoted 2 lines
drivers/clk/clk.c +2 -0
+
+	clk_core_rate_unprotect(clk->core);

Can we make this stuff non-recursive? I know that this is basically a copy paste of prepare/unprepare code and recursion is nice and elegant, but we really don't need to do it when we could have a loop that's the same and doesn't blow up our stack frame usage. I'll send a patch for prepare/enable so you get the idea.

I think we should not be doing the same thing differently inside the framework. If enable and disable are recursive, protect should be too. The stack can handle enable and prepare, why would it not handle protect ?

Of course, If your patch to "stack-ify" enable and prepare merges first, I'll copy the mechanism. The important thing for me is keep things consistent.

On a more general note, your idea is no light change ...
Are the trees really that tall that it is becoming a problem ?
I see in your patch comment that there is still a few question to be answered, right ?

Could we take this one step at time and keep the recursion for now? When the whole CCF moves to a stack approach, I'll be happy to help.

Quoted 28 lines
Quoted 6 lines
drivers/clk/clk.c +5 -0
+	clk->protect_count--;
+out:
+	clk_prepare_unlock();
+}
+EXPORT_SYMBOL_GPL(clk_rate_unprotect);

[..]

Quoted 10 lines
drivers/clk/clk.c +1 -0
+
@@ -2952,6 +3134,17 @@ void __clk_put(struct clk *clk)

?
? clk_prepare_lock();
?

drivers/clk/clk.c +2 -0
+	/*
+	?* Before calling clk_put, all calls to clk_rate_protect from a

given

drivers/clk/clk.c +1 -0
+	?* user must be balanced with calls to clk_rate_unprotect and by

that

drivers/clk/clk.c void __clk_put(struct clk *clk) · line 3146

Quoted 7 lines
drivers/clk/clk.c +7 -0
+	?* same user
+	?*/
+	WARN_ON(clk->protect_count);
+
+	/* We voiced our concern, let's sanitize the situation */
+	for (; clk->protect_count; clk->protect_count--)
+		clk_core_rate_unprotect(clk->core);

Does this do anything different than:

Quoted 2 lines
	clk->core->protect_count -= clk->protect_count;
	clk->protect_count = 1;

this looks really hacky !

Quoted 3 lines
	clk_core_rate_unprotect(clk->core);

Just seems better to not do a loop here.

A loop a easy to understand.
This code should actually never run, so readability looks more important to me than optimisation.
If you really insist on this, I'll yield but I'm not a big fan.

Quoted 22 lines
Quoted 22 lines
include/linux/clk.h +0 -0
index 91bd464f4c9b..b60c36f2e6b0 100644
@@ -331,6 +331,30 @@ struct clk *devm_clk_get(struct device *dev, const char
 *id);

? */
?struct clk *devm_get_clk_from_child(struct device *dev,
? ????struct device_node *np, const char
*con_id);
+/**
+ * clk_rate_protect - inform the system when the clock rate must be protected.
+ * @clk: clock source
+ *
+ * This function informs the system that the consumer protecting the clock
+ * depends on the rate of the clock source and can't tolerate any glitches
+ * introduced by further clock rate change or re-parenting of the clock source.
+ *
+ * Must not be called from within atomic context.

Quoted 8 lines
Quoted 2 lines

+ */
+void clk_rate_protect(struct clk *clk);

Is there any plan to use this clk_rate_protect() API? It seems inherently racy for a clk consumer to call clk_set_rate() and then this clk_rate_protect() API after that to lock the rate in. How about we leave this out of the consumer API until a user needs it?

Having this API available is whole reason I've been working on this for so long. By the now, you may have forgot but I explained the use-case in first RFC [0] Here is an example (wip) of usage [1]

[0]: http://lkml.kernel.org/r/20170302173835.18313-1-jbrunet at baylibre.co [1]: https://github.com/jeromebrunet/linux/commits/amlogic/wip/audio-clk-lock

Quoted 10 lines

I'm tempted to say that we could do this rate locking stuff with clk_set_rate_range(), but with more thought that doesn't seem possible because there's a subtle difference. The range API is willing to accept a range of frequencies, and calling clk_set_rate_range() with some exact frequency should fail if that exact frequency can't be met. With this API and the subsequent clk_set_rate_protect() API we're willing to accept that the rate we call clk_set_rate_protect() with could be different than the rate we actually get.

Indeed and this point is important for PLLs which (almost) certainly never meet the exact requested rate.

Also rate_range would give no guarantee regarding gliches and reparenting. Keep audio in mind here, glitches are the enemy.

Say you have 2 clocks fed by a divider (SET_RATE_PARENT of course)

# clock #1 is a PLL locked to 48000kHz
# clock #2 request a new rate

If the clock #1 is protected by rate_range mechanism, the divider could change, provided that PLL is able to relock at 48000kHz ... but we'll get a glitch

This won't happen with clock protect, clock #2 will have to work with what the divider provides at the moment, or reparent to better suited (free) parent clock.

Quoted 12 lines

Finally, When does a consumer want the rate of a clk to change after they call clk_set_rate() on it? I would guess that very few consumers would be willing to accept that. Which begs the question, if anyone will keep calling clk_set_rate() after this API (and the clk_set_rate_protect() API) is added. It almost seems like we would want it to be opt-out, instead of opt-in, so that consumers would call clk_set_rate() and expect it to be a stable clk rate after that, and they would call clk_set_rate_trample_on_me() or something properly named when they don't care what the rate is after they call the API.

Indeed, we generally don't want our rate to change, but:
- This is mostly for leaf clocks, the internal path would generally not care, as long as the leaf are happy.
- Even a leaf may be open (be able to deal with) to small glitches, pll relock, re parenting

Actually, if all the clock could not tolerate any glitches, there would have been a lot of complains about CCF by now, it does not prevent glitches at all.

If you go over the initial RFC, the point is also for the CCF to favor other (unused parent) when several (sometimes with the same capabilities) are available. I think this is also a fairly common use case. That's something rate_range won't do either, as far as I understood.

Last but not least, it allows consumer to set the rate in a sort of critical section and have the guarantee that nobody will be able to change the rate between the clk_set_rate() call and prepare_enable(). That's something we don't have at the moment.

So I think this API bring quite a few things

Quoted 18 lines
Quoted 9 lines
include/linux/clk.h +6 -0
+
+/**
+ * clk_rate_unprotect - release the protection of the clock source.
+ * @clk: clock source
+ *
+ * This function informs the system that the consumer previously protecting

the
+ * clock rate can now deal with other consumer altering the clock source rate

other consumers

Quoted 3 lines

+ *
+ * The caller must balance the number of rate_protect and rate_unprotect calls.

Please say clk_rate_protect() and clk_rate_unprotect() here.

#14 lore raw

PATCH v3 5/10 clk: add support for clock protection

Quoted 17 lines · Jerome Brunet
Quoted 11 lines · Stephen Boyd

drivers/clk/clk.c EXPORT_SYMBOL_GPL(__clk_mux_determine_rate_closest); · line 529

Quoted 4 lines · Jerome Brunet
drivers/clk/clk.c +4 -0
+	if (WARN_ON(clk->protect_count <= 0))
+		goto out;
+
+	clk_core_rate_unprotect(clk->core);

Can we make this stuff non-recursive? I know that this is basically a copy paste of prepare/unprepare code and recursion is nice and elegant, but we really don't need to do it when we could have a loop that's the same and doesn't blow up our stack frame usage. I'll send a patch for prepare/enable so you get the idea.

I think we should not be doing the same thing differently inside the framework. If enable and disable are recursive, protect should be too. The stack can handle enable and prepare, why would it not handle protect ?

Quoted 7 lines

Of course, If your patch to "stack-ify" enable and prepare merges first, I'll copy the mechanism. The important thing for me is keep things consistent.

On a more general note, your idea is no light change ...
Are the trees really that tall that it is becoming a problem ?
I see in your patch comment that there is still a few question to be answered, right ?

I see it more of a problem when set_rate in the middle of recursion needs to call enable/prepare and then goes and stacks a bunch more frames again, and that has already been called deep in a stack by a driver. I admit I haven't seen a problem, but I'd rather not find out later that it was a problem.

Quoted 3 lines

Could we take this one step at time and keep the recursion for now? When the whole CCF moves to a stack approach, I'll be happy to help.

Sounds fine. We can take this up on another thread.

Quoted 34 lines
Quoted 29 lines
Quoted 7 lines
drivers/clk/clk.c +5 -0
+	clk->protect_count--;
+out:
+	clk_prepare_unlock();
+}
+EXPORT_SYMBOL_GPL(clk_rate_unprotect);

[..]

Quoted 10 lines
(quoted diff) +1 -0
+
@@ -2952,6 +3134,17 @@ void __clk_put(struct clk *clk)

?
? clk_prepare_lock();
?

(quoted diff) +2 -0
+	/*
+	?* Before calling clk_put, all calls to clk_rate_protect from a

given

(quoted diff) +1 -0
+	?* user must be balanced with calls to clk_rate_unprotect and by

that

drivers/clk/clk.c void __clk_put(struct clk *clk) · line 3146

Quoted 7 lines
drivers/clk/clk.c +7 -0
+	?* same user
+	?*/
+	WARN_ON(clk->protect_count);
+
+	/* We voiced our concern, let's sanitize the situation */
+	for (; clk->protect_count; clk->protect_count--)
+		clk_core_rate_unprotect(clk->core);

Does this do anything different than:

Quoted 2 lines
	clk->core->protect_count -= clk->protect_count;
	clk->protect_count = 1;

this looks really hacky !

Quoted 8 lines
Quoted 3 lines
	clk_core_rate_unprotect(clk->core);

Just seems better to not do a loop here.

A loop a easy to understand.
This code should actually never run, so readability looks more important to me than optimisation.
If you really insist on this, I'll yield but I'm not a big fan.

Well I'm suggesting this because the same loop looked to be repeated in a couple of other places, and in those cases it was always run, so looping through it all the time to decrement is sort of odd. Maybe it could be a small function?

	int clk_core_rate_unprotect_force(struct clk_core *core)
	{
		int count = core->protect_count;

		if (count) {
			core->protect_count = 1;
			clk_core_rate_unprotect(core);
		}

		return count;
	}

And then call-site would be

	if (clk_core_rate_unprotect_force(clk->core))
		clk->protect_count = 0;

and the other call-site where we temporarily remove it we can have unprotect force and then protect_force restore the value returned.

Quoted 32 lines
Quoted 23 lines
Quoted 23 lines
include/linux/clk.h +0 -0
index 91bd464f4c9b..b60c36f2e6b0 100644
@@ -331,6 +331,30 @@ struct clk *devm_clk_get(struct device *dev, const char
 *id);

? */
?struct clk *devm_get_clk_from_child(struct device *dev,
? ????struct device_node *np, const char
*con_id);
+/**
+ * clk_rate_protect - inform the system when the clock rate must be protected.
+ * @clk: clock source
+ *
+ * This function informs the system that the consumer protecting the clock
+ * depends on the rate of the clock source and can't tolerate any glitches
+ * introduced by further clock rate change or re-parenting of the clock source.
+ *
+ * Must not be called from within atomic context.

Quoted 8 lines
Quoted 2 lines

+ */
+void clk_rate_protect(struct clk *clk);

Is there any plan to use this clk_rate_protect() API? It seems inherently racy for a clk consumer to call clk_set_rate() and then this clk_rate_protect() API after that to lock the rate in. How about we leave this out of the consumer API until a user needs it?

Quoted 6 lines

Having this API available is whole reason I've been working on this for so long. By the now, you may have forgot but I explained the use-case in first RFC [0] Here is an example (wip) of usage [1]

[0]: http://lkml.kernel.org/r/20170302173835.18313-1-jbrunet at baylibre.com [1]: https://github.com/jeromebrunet/linux/commits/amlogic/wip/audio-clk-lock

If we're forgetting why something is introduced then it means the commit text is missing information. Please clearly describe the need for the API in the commit text for the patch that introduces it.

Quoted 14 lines
Quoted 13 lines

Finally, When does a consumer want the rate of a clk to change after they call clk_set_rate() on it? I would guess that very few consumers would be willing to accept that. Which begs the question, if anyone will keep calling clk_set_rate() after this API (and the clk_set_rate_protect() API) is added. It almost seems like we would want it to be opt-out, instead of opt-in, so that consumers would call clk_set_rate() and expect it to be a stable clk rate after that, and they would call clk_set_rate_trample_on_me() or something properly named when they don't care what the rate is after they call the API.

Quoted 8 lines

Indeed, we generally don't want our rate to change, but:
- This is mostly for leaf clocks, the internal path would generally not care, as long as the leaf are happy.
- Even a leaf may be open (be able to deal with) to small glitches, pll relock, re parenting

Actually, if all the clock could not tolerate any glitches, there would have been a lot of complains about CCF by now, it does not prevent glitches at all.

Well some devices handle glitches in the hardware, so the details of glitch free rate changes are hidden from clk consumers, and the software in general, on those devices.

Quoted 5 lines

If you go over the initial RFC, the point is also for the CCF to favor other (unused parent) when several (sometimes with the same capabilities) are available. I think this is also a fairly common use case. That's something rate_range won't do either, as far as I understood.

Fair enough, but why do we want consumers to need to know that there are sometimes unused parents that aren't getting chosen for a particular frequency? I see this as exposing the internals of the clk tree to consumers when they shouldn't need to care. Of course, sometimes clk consumers really do care about internals, for example if some PLL is used for a display controller and it's also routed out of the chip on the display phy pins to encode data or something. Then perhaps we really want to use one particular PLL instead of a generic one that may also be a parent of the display controller clk. Making sure clk_set_rate() doesn't trample on clks deep in the tree seems different than this though.

Going back to your RFC series cover letter though, I see three PLLs (mppl0,1,2) and two users of the PLLs (amclk and mclk_i958). Is anything else using these PLLs in the system? Why are we doing all this stuff instead of hard-coding the parents for these clks to be different PLLs? If we want it to be flexible we could assign parents to the cts_amclk_sel and cts_mclk_i958_sel to be different PLLs in DT via assigned clock parents. Or it could just be hard-coded in the clk driver during probe.

If there's really sharing going on, and you can't hardcode the parents, please indicate why that's the case in the commit text. I don't want to introduce another consumer API just because we didn't want to restrict the available parents for a couple clks.

Quoted 6 lines

Last but not least, it allows consumer to set the rate in a sort of critical section and have the guarantee that nobody will be able to change the rate between the clk_set_rate() call and prepare_enable(). That's something we don't have at the moment.

Right, but clk_rate_protect() doesn't close the critical section between clk_set_rate() and clk_rate_protect() if another consumers changes the frequency, or if that consumer changes the frequency of some parent of the clk. This is why I'm asking what the use of this API is for. Shouldn't we want consumers to use clk_set_rate_protect() so they can be sure they got the rate they wanted, instead of hoping that something else hasn't come in between the set_rate and the protect calls and changed the frequency?

Signature · 2 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
#15 lore raw

PATCH v3 5/10 clk: add support for clock protection

Hi Stephen,

Quoting Stephen Boyd (2017-08-03 17:18:36)

Quoted 9 lines · Jerome Brunet
Quoted 8 lines
Quoted 7 lines
Quoted 1 line

+void clk_rate_protect(struct clk *clk);

Is there any plan to use this clk_rate_protect() API? It seems inherently racy for a clk consumer to call clk_set_rate() and then this clk_rate_protect() API after that to lock the rate in. How about we leave this out of the consumer API until a user needs it?

Quoted 6 lines
Quoted 6 lines

Having this API available is whole reason I've been working on this for so long. By the now, you may have forgot but I explained the use-case in first RFC [0] Here is an example (wip) of usage [1]

[0]: http://lkml.kernel.org/r/20170302173835.18313-1-jbrunet at baylibre.com [1]: https://github.com/jeromebrunet/linux/commits/amlogic/wip/audio-clk-lock

Indeed, something like rate protection or "lock rate" has been discussed since the birth of CCF. I remember a whiteboarding session between you, Paul W. and myself about it probably in 2012. Peter might have been there too.

Quoted 5 lines

If we're forgetting why something is introduced then it means the commit text is missing information. Please clearly describe the need for the API in the commit text for the patch that introduces it.

My $0.02 is that the "pick an unused PLL" thing is a benefit of this new api that is internal to the clock controller driver, and is not the driving force behind the series. If a simple, easy to understand justification for this patch series is needed, might I suggest something like the following for the next commit log/coverletter:

"Some clock consumers require that a clock rate must not deviate from its selected frequency. There can be several reasons for this, not least of which is that some hardware may not be able to handle or recover from a glitch caused by changing the clock rate while the hardware is in operation. The ability to lock a clock's rate, and release that lock, is a fundamental clock rate control primitive. It's absence is a bug that is fixed by this patch series."

That's the short and sweet version. If more verbosity is needed as to why rate_range doesn't need this, there are some good reasons:

1) simplicity: some consumers don't care about their rate, but do care that they rate doesn't change. clk_rate_{un}protect is much simpler than forcing those consumers to call clk_get_rate, then cache that value for future use and then call clk_set_rate_range.

2) expressiveness / debug: trying to find out why a clock rate is locked searching through every use of clk_set_rate_range is sort of lame, especially if variables are used to pass in min/max instead of hard-coded values. It's way way easier to just grep for clk_rate_protect.

Quoted 21 lines
Quoted 21 lines
Quoted 14 lines

Finally, When does a consumer want the rate of a clk to change after they call clk_set_rate() on it? I would guess that very few consumers would be willing to accept that. Which begs the question, if anyone will keep calling clk_set_rate() after this API (and the clk_set_rate_protect() API) is added. It almost seems like we would want it to be opt-out, instead of opt-in, so that consumers would call clk_set_rate() and expect it to be a stable clk rate after that, and they would call clk_set_rate_trample_on_me() or something properly named when they don't care what the rate is after they call the API.

Indeed, we generally don't want our rate to change, but:
- This is mostly for leaf clocks, the internal path would generally not care, as long as the leaf are happy.
- Even a leaf may be open (be able to deal with) to small glitches, pll relock, re parenting

Quoted 6 lines
Quoted 2 lines

Actually, if all the clock could not tolerate any glitches, there would have been a lot of complains about CCF by now, it does not prevent glitches at all.

Well some devices handle glitches in the hardware, so the details of glitch free rate changes are hidden from clk consumers, and the software in general, on those devices.

On the hardware that I am familiar with, the problem of glitches lies not in the clock hardware, but with the downstream peripheral logic / ip block that consumes that clock signal. So it seems to me that having a consumer api for locking the rate makes perfect sense.

Quoted 7 lines
Quoted 6 lines

If you go over the initial RFC, the point is also for the CCF to favor other (unused parent) when several (sometimes with the same capabilities) are available. I think this is also a fairly common use case. That's something rate_range won't do either, as far as I understood.

Quoted 5 lines

Fair enough, but why do we want consumers to need to know that there are sometimes unused parents that aren't getting chosen for a particular frequency? I see this as exposing the internals of the clk tree to consumers when they shouldn't need to care. Of course, sometimes clk consumers really do care about internals,

Right, sometimes they do, and we need to strike a balance. I think that this api has been needed for some time. It very likely could have been included in the initial version of the CCF that was merged years back if I hadn't been trying very hard to stick only to the existing clk.h.

clk_set_rate has always been a "last write wins" api, across a shared resource, and we've always known that this is not a great situation. This patch series does a good job of solving that issue, in conjunction with the existing range stuff.

Quoted 17 lines

for example if some PLL is used for a display controller and it's also routed out of the chip on the display phy pins to encode data or something. Then perhaps we really want to use one particular PLL instead of a generic one that may also be a parent of the display controller clk. Making sure clk_set_rate() doesn't trample on clks deep in the tree seems different than this though.

Going back to your RFC series cover letter though, I see three PLLs (mppl0,1,2) and two users of the PLLs (amclk and mclk_i958). Is anything else using these PLLs in the system? Why are we doing all this stuff instead of hard-coding the parents for these clks to be different PLLs? If we want it to be flexible we could assign parents to the cts_amclk_sel and cts_mclk_i958_sel to be different PLLs in DT via assigned clock parents. Or it could just be hard-coded in the clk driver during probe.

Quoted 4 lines

If there's really sharing going on, and you can't hardcode the parents, please indicate why that's the case in the commit text. I don't want to introduce another consumer API just because we didn't want to restrict the available parents for a couple clks.

I think the PLL sharing thing is a big distraction. Giving consumers the ability to guarantee that their rates are locked in using a simple critical section call just makes sense to me. If it helps with other cases then yay.

Quoted 8 lines
Quoted 7 lines

Last but not least, it allows consumer to set the rate in a sort of critical section and have the guarantee that nobody will be able to change the rate between the clk_set_rate() call and prepare_enable(). That's something we don't have at the moment.

Quoted 4 lines

Right, but clk_rate_protect() doesn't close the critical section between clk_set_rate() and clk_rate_protect() if another consumers changes the frequency, or if that consumer changes the frequency of some parent of the clk. This is why I'm asking what

Right, clk_set_rate_protect does this in the next patch in this series.

Quoted 5 lines

the use of this API is for. Shouldn't we want consumers to use clk_set_rate_protect() so they can be sure they got the rate they wanted, instead of hoping that something else hasn't come in between the set_rate and the protect calls and changed the frequency?

We can remove clk_rate_protect if you really want, but there is always the case that a consumer driver does not set the rate, but needs to guarantee that the rate will not change during operation.

Any driver that must both set the rate AND guarantee it will not change must use clk_set_rate_protect.

Regards,
Mike

Quoted 4 lines
Signature · 3 lines
-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
#16 lore raw

PATCH v3 5/10 clk: add support for clock protection

Quoted 16 lines · Michael Turquette

Hi Stephen,

Quoting Stephen Boyd (2017-08-03 17:18:36)

Quoted 13 lines · Jerome Brunet
Quoted 12 lines
Quoted 7 lines
Quoted 1 line

+void clk_rate_protect(struct clk *clk);

Is there any plan to use this clk_rate_protect() API? It seems inherently racy for a clk consumer to call clk_set_rate() and then this clk_rate_protect() API after that to lock the rate in. How about we leave this out of the consumer API until a user needs it?

Having this API available is whole reason I've been working on this for so long. By the now, you may have forgot but I explained the use-case in first RFC [0] Here is an example (wip) of usage [1]

Quoted 7 lines
Quoted 2 lines
Quoted 2 lines

[0]: http://lkml.kernel.org/r/20170302173835.18313-1-jbrunet at baylibre.com [1]: https://github.com/jeromebrunet/linux/commits/amlogic/wip/audio-clk-lock

Indeed, something like rate protection or "lock rate" has been discussed since the birth of CCF. I remember a whiteboarding session between you, Paul W. and myself about it probably in 2012. Peter might have been there too.

I seem to recall this being about something with how OMAP could change rates only high up in the tree and that would trickle down to multiple different clks that all had to use that rate and then divide it themselves to achieve the rate they actually wanted. Is that right? I also vaguely remember Paul saying that clk_round_rate() could return something and then clk_set_rate() after that would fail because what was calculated during the rate speculation/rounding phase would be different if some other consumer goes and changes some rate high up in the tree.

Quoted 13 lines
Quoted 6 lines

If we're forgetting why something is introduced then it means the commit text is missing information. Please clearly describe the need for the API in the commit text for the patch that introduces it.

My $0.02 is that the "pick an unused PLL" thing is a benefit of this new api that is internal to the clock controller driver, and is not the driving force behind the series. If a simple, easy to understand justification for this patch series is needed, might I suggest something like the following for the next commit log/coverletter:

Quoted 7 lines

"Some clock consumers require that a clock rate must not deviate from its selected frequency. There can be several reasons for this, not least of which is that some hardware may not be able to handle or recover from a glitch caused by changing the clock rate while the hardware is in operation. The ability to lock a clock's rate, and release that lock, is a fundamental clock rate control primitive. It's absence is a bug that is fixed by this patch series."

This sounds like we're fixing the CLK_SET_RATE_GATE flag. I'd prefer we also describe how adding that flag to some clk doesn't solve the problem. I'm all more commit text when introducing this API. Please don't go super verbose, but at least describe the real problem.

Quoted 3 lines

That's the short and sweet version. If more verbosity is needed as to why rate_range doesn't need this, there are some good reasons:

I'm not really concerned about rate range handling this problem here. Let's try to untangle the two in this discussion please.

Quoted 46 lines
Quoted 8 lines
Quoted 7 lines

If you go over the initial RFC, the point is also for the CCF to favor other (unused parent) when several (sometimes with the same capabilities) are available. I think this is also a fairly common use case. That's something rate_range won't do either, as far as I understood.

Quoted 5 lines

Fair enough, but why do we want consumers to need to know that there are sometimes unused parents that aren't getting chosen for a particular frequency? I see this as exposing the internals of the clk tree to consumers when they shouldn't need to care. Of course, sometimes clk consumers really do care about internals,

Right, sometimes they do, and we need to strike a balance. I think that this api has been needed for some time. It very likely could have been included in the initial version of the CCF that was merged years back if I hadn't been trying very hard to stick only to the existing clk.h.

clk_set_rate has always been a "last write wins" api, across a shared resource, and we've always known that this is not a great situation. This patch series does a good job of solving that issue, in conjunction with the existing range stuff.

Quoted 17 lines

for example if some PLL is used for a display controller and it's also routed out of the chip on the display phy pins to encode data or something. Then perhaps we really want to use one particular PLL instead of a generic one that may also be a parent of the display controller clk. Making sure clk_set_rate() doesn't trample on clks deep in the tree seems different than this though.

Going back to your RFC series cover letter though, I see three PLLs (mppl0,1,2) and two users of the PLLs (amclk and mclk_i958). Is anything else using these PLLs in the system? Why are we doing all this stuff instead of hard-coding the parents for these clks to be different PLLs? If we want it to be flexible we could assign parents to the cts_amclk_sel and cts_mclk_i958_sel to be different PLLs in DT via assigned clock parents. Or it could just be hard-coded in the clk driver during probe.

Quoted 4 lines

If there's really sharing going on, and you can't hardcode the parents, please indicate why that's the case in the commit text. I don't want to introduce another consumer API just because we didn't want to restrict the available parents for a couple clks.

Quoted 4 lines

I think the PLL sharing thing is a big distraction. Giving consumers the ability to guarantee that their rates are locked in using a simple critical section call just makes sense to me. If it helps with other cases then yay.

Ok. Can we get details on where we can't fix it in the provider layer? I'm fine to ignore the PLL sharing thing, if we can clearly describe a real situation where a clk consumer needs to lock in a rate, and that isn't the only consumer of a clk that is changing that rate or causing a glitch by changing some other rate up the tree. So far we haven't come across this case, presumably because clk providers are working around the problem by hardcoding parents that can change rate during determine_rate(), or blocking rate changes going up the tree for certain clks, or the hardware isn't designed in a way that something is shared while two devices are active, or maybe nobody has complained (likely!).

I'm all for consumers locking in rates in a critical section, just that I haven't seen a need for it so far. I've mostly seen that hardware doesn't design it this way, or that there's some sort of hardware plan to make sure that desired frequencies can be achieved when there's some shared resource. And the glitching thing hasn't been a problem because consumers are the only ones causing the glitch when they call clk_set_rate() and so far they have only called clk_set_rate() when their hardware is able to handle the glitch that comes down (e.g. audio turns off speaker output, or device is held in reset).

TL;DR: Please distract me from the PLL sharing thing with the real problem that's being solved.

Quoted 22 lines
Quoted 9 lines
Quoted 8 lines

Last but not least, it allows consumer to set the rate in a sort of critical section and have the guarantee that nobody will be able to change the rate between the clk_set_rate() call and prepare_enable(). That's something we don't have at the moment.

Quoted 4 lines

Right, but clk_rate_protect() doesn't close the critical section between clk_set_rate() and clk_rate_protect() if another consumers changes the frequency, or if that consumer changes the frequency of some parent of the clk. This is why I'm asking what

Right, clk_set_rate_protect does this in the next patch in this series.

Quoted 5 lines

the use of this API is for. Shouldn't we want consumers to use clk_set_rate_protect() so they can be sure they got the rate they wanted, instead of hoping that something else hasn't come in between the set_rate and the protect calls and changed the frequency?

Quoted 7 lines

We can remove clk_rate_protect if you really want, but there is always the case that a consumer driver does not set the rate, but needs to guarantee that the rate will not change during operation.

Any driver that must both set the rate AND guarantee it will not change must use clk_set_rate_protect.

No need to remove the API. This is a good description of a case where a consumer would just call clk_rate_protect() (or perhaps clk_dont_glitch()) without caring what the rate is. I was missing this part of the argument because I got hung up on the critical section part. Maybe this can be added to the function documentation so we don't forget that some consumers don't set a rate but still care to make sure it doesn't glitch for them.

Signature · 2 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
#17 lore raw

PATCH v3 5/10 clk: add support for clock protection

Quoted 5 lines · Stephen Boyd

I also vaguely remember Paul saying that clk_round_rate() could return something and then clk_set_rate() after that would fail because what was calculated during the rate speculation/rounding phase would be different if some other consumer goes and changes some rate high up in the tree.

That's probably because people tend to get this stuff wrong. It is _not_ supposed to be:

	rounded_rate = clk_round_rate(clk, requested_rate);

	clk_set_rate(clk, rounded_rate);

but:

	rounded_rate = clk_round_rate(clk, requested_rate);

	clk_set_rate(clk, requested_rate);

The former is wrong for two reasons:

1. it's completely wasteful of CPU resources to do all the calculations that need to be done within clk_set_rate().

2. it's racy - there is no guarantee that you'll end up with "rounded_rate"

The API definition of clk_round_rate() explicitly mentions that it is equivalent to clk_set_rate() followed by clk_get_rate() with the exception that it doesn't affect the hardware.

I'm not sure that the clock rate protection API is really the right solution - if we're trying to stop others from changing the clock rate, that implies we have multiple different threads potentially changing the rate at any time. If a driver does this:

	clk_set_rate(clk, foo);
	clk_rate_protect(clk);

what prevents another thread from changing the clock rate between these two calls? The only way to do this safely would be something like:

	r = clk_round_rate(clk, foo);
	while (1) {
		err = clk_set_rate(clk, foo);
		clk_rate_protect(clk);
		if (err < 0)
			break;

		if (r == clk_get_rate(clk)) /* success */
			break;

		clk_rate_unprotect(clk);
	}

	if (err)
		failed;

That's rather a lot of code to add to every driver, and given the number of times I've seen people get the clk_round_rate() vs clk_set_rate() thing wrong, I've zero confidence that folk will get this right either.

So, I'd suggest _not_ adding this clk_rate_protect() thing, but instead an API that simultaneously sets and protects the rate, so driver authors don't have to get involved in details like the above.

Signature · 3 lines
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line in suburbia: [email protected] down 630kbps up
According to speedtest.net: 8.21Mbps down 510kbps up
author reviewer
#18 lore raw

PATCH v3 5/10 clk: add support for clock protection

Quoted 42 lines · Russell King - ARM Linux
Quoted 5 lines · Stephen Boyd

I also vaguely remember Paul saying that clk_round_rate() could return something and then clk_set_rate() after that would fail because what was calculated during the rate speculation/rounding phase would be different if some other consumer goes and changes some rate high up in the tree.

That's probably because people tend to get this stuff wrong.??It is _not_ supposed to be:

	rounded_rate = clk_round_rate(clk, requested_rate);

	clk_set_rate(clk, rounded_rate);

but:

	rounded_rate = clk_round_rate(clk, requested_rate);

	clk_set_rate(clk, requested_rate);

The former is wrong for two reasons:

1. it's completely wasteful of CPU resources to do all the calculations ???that need to be done within clk_set_rate().

2. it's racy - there is no guarantee that you'll end up with "rounded_rate"

The API definition of clk_round_rate() explicitly mentions that it is equivalent to clk_set_rate() followed by clk_get_rate() with the exception that it doesn't affect the hardware.

I'm not sure that the clock rate protection API is really the right solution - if we're trying to stop others from changing the clock rate, that implies we have multiple different threads potentially changing the rate at any time.??If a driver does this:

	clk_set_rate(clk, foo);
	clk_rate_protect(clk);

what prevents another thread from changing the clock rate between these two calls???The only way to do this safely would be something like:

Quoted 15 lines
	r = clk_round_rate(clk, foo);
	while (1) {
		err = clk_set_rate(clk, foo);
		clk_rate_protect(clk);
		if (err < 0)
			break;

		if (r == clk_get_rate(clk)) /* success */
			break;

		clk_rate_unprotect(clk);
	}

	if (err)
		failed;

Russell,
I think you have missed one subtle thing, when trying any clock altering operation, if the consumer is protecting the clock, it will temporarily release the protection once, under the prepare_lock (to guarantee safe operation). This is explained in the cover letter:

"""
With this series there is 3 use-case:
?- the provider is not protected: nothing changes
?- the provider is protected by only 1 consumer (and only once), then only ???this consumer will be able to alter the rate of the clock, as it is the ???only one depending on it.
?- If the provider is protected more than once, or by the provider itself, ???the rate is basically locked and protected against reparenting. """

So what you should do if you have to protect the clock is:

clk_rate_protect(clk);
err = clk_set_rate(clk, foo);

[...]
clk_rate_unprotect(clk);

If the clock rate could be changed (protected only once) err = 0; If the clock rate could not be changed: err = -EBUSY;

if you wish to combine clk_rate_protect() and clk_set_rate(), you may use clk_set_rate_protect() which is added in another patch of this series.

Quoted 10 lines

That's rather a lot of code to add to every driver, and given the number of times I've seen people get the clk_round_rate() vs clk_set_rate() thing wrong, I've zero confidence that folk will get this right either.

So, I'd suggest _not_ adding this clk_rate_protect() thing, but instead an API that simultaneously sets and protects the rate, so driver authors don't have to get involved in details like the above.

#19 lore raw

PATCH v3 5/10 clk: add support for clock protection

Quoted 75 lines · Jerome Brunet
Quoted 42 lines · Russell King - ARM Linux
Quoted 5 lines · Stephen Boyd

I also vaguely remember Paul saying that clk_round_rate() could return something and then clk_set_rate() after that would fail because what was calculated during the rate speculation/rounding phase would be different if some other consumer goes and changes some rate high up in the tree.

That's probably because people tend to get this stuff wrong.??It is _not_ supposed to be:

	rounded_rate = clk_round_rate(clk, requested_rate);

	clk_set_rate(clk, rounded_rate);

but:

	rounded_rate = clk_round_rate(clk, requested_rate);

	clk_set_rate(clk, requested_rate);

The former is wrong for two reasons:

1. it's completely wasteful of CPU resources to do all the calculations ???that need to be done within clk_set_rate().

2. it's racy - there is no guarantee that you'll end up with "rounded_rate"

The API definition of clk_round_rate() explicitly mentions that it is equivalent to clk_set_rate() followed by clk_get_rate() with the exception that it doesn't affect the hardware.

I'm not sure that the clock rate protection API is really the right solution - if we're trying to stop others from changing the clock rate, that implies we have multiple different threads potentially changing the rate at any time.??If a driver does this:

	clk_set_rate(clk, foo);
	clk_rate_protect(clk);

what prevents another thread from changing the clock rate between these two calls???The only way to do this safely would be something like:

Quoted 15 lines
	r = clk_round_rate(clk, foo);
	while (1) {
		err = clk_set_rate(clk, foo);
		clk_rate_protect(clk);
		if (err < 0)
			break;

		if (r == clk_get_rate(clk)) /* success */
			break;

		clk_rate_unprotect(clk);
	}

	if (err)
		failed;

Russell,
I think you have missed one subtle thing, when trying any clock altering operation, if the consumer is protecting the clock, it will temporarily release the protection once, under the prepare_lock (to guarantee safe operation). This is explained in the cover letter:

"""
With this series there is 3 use-case:
?- the provider is not protected: nothing changes
?- the provider is protected by only 1 consumer (and only once), then only ???this consumer will be able to alter the rate of the clock, as it is the ???only one depending on it.
?- If the provider is protected more than once, or by the provider itself, ???the rate is basically locked and protected against reparenting. """

Quoted 7 lines

So what you should do if you have to protect the clock is:

clk_rate_protect(clk);
err = clk_set_rate(clk, foo);

[...]
clk_rate_unprotect(clk);

So here you drop the protection, which means anyone can alter the clock again.

Either that or "clk_rate_unprotect" is inappropriately named and doesn't do what it says it does.

Signature · 3 lines
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line in suburbia: sync at 8.8Mbps down 630kbps up
According to speedtest.net: 8.21Mbps down 510kbps up
author reviewer
#20 lore raw

PATCH v3 5/10 clk: add support for clock protection

Quoted 81 lines · Russell King - ARM Linux
Quoted 80 lines · Jerome Brunet
Quoted 43 lines · Russell King - ARM Linux
Quoted 5 lines · Stephen Boyd

I also vaguely remember Paul saying that clk_round_rate() could return something and then clk_set_rate() after that would fail because what was calculated during the rate speculation/rounding phase would be different if some other consumer goes and changes some rate high up in the tree.

That's probably because people tend to get this stuff wrong.??It is _not_ supposed to be:

	rounded_rate = clk_round_rate(clk, requested_rate);

	clk_set_rate(clk, rounded_rate);

but:

	rounded_rate = clk_round_rate(clk, requested_rate);

	clk_set_rate(clk, requested_rate);

The former is wrong for two reasons:

1. it's completely wasteful of CPU resources to do all the calculations ???that need to be done within clk_set_rate().

2. it's racy - there is no guarantee that you'll end up with "rounded_rate"

The API definition of clk_round_rate() explicitly mentions that it is equivalent to clk_set_rate() followed by clk_get_rate() with the exception that it doesn't affect the hardware.

I'm not sure that the clock rate protection API is really the right solution - if we're trying to stop others from changing the clock rate, that implies we have multiple different threads potentially changing the rate at any time.??If a driver does this:

	clk_set_rate(clk, foo);
	clk_rate_protect(clk);

what prevents another thread from changing the clock rate between these two calls???The only way to do this safely would be something like:

Quoted 15 lines
	r = clk_round_rate(clk, foo);
	while (1) {
		err = clk_set_rate(clk, foo);
		clk_rate_protect(clk);
		if (err < 0)
			break;

		if (r == clk_get_rate(clk)) /* success */
			break;

		clk_rate_unprotect(clk);
	}

	if (err)
		failed;

Russell,
I think you have missed one subtle thing, when trying any clock altering operation, if the consumer is protecting the clock, it will temporarily release?
the protection once, under the prepare_lock (to guarantee safe operation). This
is explained in the cover letter:

"""
With this series there is 3 use-case:
?- the provider is not protected: nothing changes
?- the provider is protected by only 1 consumer (and only once), then only ???this consumer will be able to alter the rate of the clock, as it is the ???only one depending on it.
?- If the provider is protected more than once, or by the provider itself, ???the rate is basically locked and protected against reparenting. """

So what you should do if you have to protect the clock is:

Quoted 9 lines
Quoted 5 lines

clk_rate_protect(clk);
err = clk_set_rate(clk, foo);

[...]
clk_rate_unprotect(clk);

So here you drop the protection, which means anyone can alter the clock again.

That's just an example. The rate is set after clk_set_rate() if no other consumer depends on the clock.

I just added clk_rate_unprotect() here to illustrate that the calls should be balanced, as documented.

Quoted 3 lines

Either that or "clk_rate_unprotect" is inappropriately named and doesn't do what it says it does.

#21 lore raw

PATCH v3 5/10 clk: add support for clock protection

In reply to Russell King - ARM Linux

Quoting Russell King - ARM Linux (2017-08-09 06:40:36)

Quoted 78 lines · Jerome Brunet
Quoted 77 lines · Russell King - ARM Linux
Quoted 42 lines · Stephen Boyd
Quoted 5 lines

I also vaguely remember Paul saying that clk_round_rate() could return something and then clk_set_rate() after that would fail because what was calculated during the rate speculation/rounding phase would be different if some other consumer goes and changes some rate high up in the tree.

That's probably because people tend to get this stuff wrong.??It is _not_ supposed to be:

    rounded_rate = clk_round_rate(clk, requested_rate);

    clk_set_rate(clk, rounded_rate);

but:

    rounded_rate = clk_round_rate(clk, requested_rate);

    clk_set_rate(clk, requested_rate);

The former is wrong for two reasons:

1. it's completely wasteful of CPU resources to do all the calculations ???that need to be done within clk_set_rate().

2. it's racy - there is no guarantee that you'll end up with "rounded_rate"

The API definition of clk_round_rate() explicitly mentions that it is equivalent to clk_set_rate() followed by clk_get_rate() with the exception that it doesn't affect the hardware.

I'm not sure that the clock rate protection API is really the right solution - if we're trying to stop others from changing the clock rate, that implies we have multiple different threads potentially changing the rate at any time.??If a driver does this:

    clk_set_rate(clk, foo);
    clk_rate_protect(clk);

what prevents another thread from changing the clock rate between these two calls???The only way to do this safely would be something like:

Quoted 15 lines
    r = clk_round_rate(clk, foo);
    while (1) {
            err = clk_set_rate(clk, foo);
            clk_rate_protect(clk);
            if (err < 0)
                    break;

            if (r == clk_get_rate(clk)) /* success */
                    break;

            clk_rate_unprotect(clk);
    }

    if (err)
            failed;

Russell,
I think you have missed one subtle thing, when trying any clock altering operation, if the consumer is protecting the clock, it will temporarily release the protection once, under the prepare_lock (to guarantee safe operation). This is explained in the cover letter:

"""
With this series there is 3 use-case:
?- the provider is not protected: nothing changes
?- the provider is protected by only 1 consumer (and only once), then only ???this consumer will be able to alter the rate of the clock, as it is the ???only one depending on it.
?- If the provider is protected more than once, or by the provider itself, ???the rate is basically locked and protected against reparenting. """

So what you should do if you have to protect the clock is:

Quoted 8 lines
Quoted 5 lines

clk_rate_protect(clk);
err = clk_set_rate(clk, foo);

[...]
clk_rate_unprotect(clk);

So here you drop the protection, which means anyone can alter the clock again.

Correct. It would be appropriate to use clk_rate_unprotect in two ways:

1) module unload
2) when a clk consumer driver completes a critical section of work and no longer cares about clk rate. I would expect this same consumer driver to call clk_disable_unprepare as well.

Regards,
Mike

Quoted 8 lines

Either that or "clk_rate_unprotect" is inappropriately named and doesn't do what it says it does.

Signature · 3 lines
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line in suburbia: sync at 8.8Mbps down 630kbps up
According to speedtest.net: 8.21Mbps down 510kbps up
#22 lore raw

PATCH v3 5/10 clk: add support for clock protection

In reply to Russell King - ARM Linux

Hi Russell,

Quoting Russell King - ARM Linux (2017-08-09 04:45:48)

Quoted 10 lines

I'm not sure that the clock rate protection API is really the right solution - if we're trying to stop others from changing the clock rate, that implies we have multiple different threads potentially changing the rate at any time. If a driver does this:

        clk_set_rate(clk, foo);
        clk_rate_protect(clk);

what prevents another thread from changing the clock rate between these two calls? The only way to do this safely would be something like:

I agree that ordering the calls in your example above is racy. It is an incorrect use of this new api. The two correct ways to use this api are:

1) Use clk_set_rate_protect, introduced in patch #6 of this series

2) Call clk_rate_protect() first, and if that call succeeds then call clk_set_rate(). Thanks to per-consumer struct clk objects, we can know that *this* consumer is the exclusive owner of the clk rate, and is allowed to change the rate within the critical section.

I think this subtlety is not well described in the commitlog nor the kerneldoc, since most reviewing including myself have missed it: the consumer that successfully protects the clk can change the rate within the critical section, by design.

Quoted 17 lines
        r = clk_round_rate(clk, foo);
        while (1) {
                err = clk_set_rate(clk, foo);
                clk_rate_protect(clk);
                if (err < 0)
                        break;

                if (r == clk_get_rate(clk)) /* success */
                        break;

                clk_rate_unprotect(clk);
        }

        if (err)
                failed;
Quoted 8 lines

That's rather a lot of code to add to every driver, and given the number of times I've seen people get the clk_round_rate() vs clk_set_rate() thing wrong, I've zero confidence that folk will get this right either.

So, I'd suggest _not_ adding this clk_rate_protect() thing, but instead an API that simultaneously sets and protects the rate, so driver authors don't have to get involved in details like the above.

As mentioned above, patch #6 does exactly this. Furthermore if you simply flip your use of clk_set_rate and clk_rate_protect, then things Just Work.

Thanks,
Mike

Quoted 5 lines
Signature · 4 lines
-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line in suburbia: sync at 8.8Mbps down 630kbps up
According to speedtest.net: 8.21Mbps down 510kbps up
author reviewer
#23 lore raw

PATCH v3 5/10 clk: add support for clock protection

In reply to Stephen Boyd
Quoted 60 lines · Stephen Boyd
Quoted 23 lines · Michael Turquette

Hi Stephen,

Quoting Stephen Boyd (2017-08-03 17:18:36)

Quoted 15 lines · Jerome Brunet
Quoted 14 lines
Quoted 7 lines
Quoted 1 line

+void clk_rate_protect(struct clk *clk);

Is there any plan to use this clk_rate_protect() API? It seems inherently racy for a clk consumer to call clk_set_rate() and then this clk_rate_protect() API after that to lock the rate in. How about we leave this out of the consumer API until a user needs it?

Having this API available is whole reason I've been working on this for so long.
By the now, you may have forgot but I explained the use-case in first RFC [0]
Here is an example (wip) of usage [1]

Quoted 4 lines
Quoted 4 lines

[0]: http://lkml.kernel.org/r/20170302173835.18313-1-jbrunet at baylibre.co m
[1]: https://github.com/jeromebrunet/linux/commits/amlogic/wip/audio-clk
-lock

Quoted 4 lines

Indeed, something like rate protection or "lock rate" has been discussed since the birth of CCF. I remember a whiteboarding session between you, Paul W. and myself about it probably in 2012. Peter might have been there too.

I seem to recall this being about something with how OMAP could change rates only high up in the tree and that would trickle down to multiple different clks that all had to use that rate and then divide it themselves to achieve the rate they actually wanted. Is that right? I also vaguely remember Paul saying that clk_round_rate() could return something and then clk_set_rate() after that would fail because what was calculated during the rate speculation/rounding phase would be different if some other consumer goes and changes some rate high up in the tree.

Quoted 13 lines
Quoted 6 lines

If we're forgetting why something is introduced then it means the commit text is missing information. Please clearly describe the need for the API in the commit text for the patch that introduces it.

My $0.02 is that the "pick an unused PLL" thing is a benefit of this new api that is internal to the clock controller driver, and is not the driving force behind the series. If a simple, easy to understand justification for this patch series is needed, might I suggest something like the following for the next commit log/coverletter:

Quoted 7 lines

"Some clock consumers require that a clock rate must not deviate from its selected frequency. There can be several reasons for this, not least of which is that some hardware may not be able to handle or recover from a glitch caused by changing the clock rate while the hardware is in operation. The ability to lock a clock's rate, and release that lock, is a fundamental clock rate control primitive. It's absence is a bug that is fixed by this patch series."

Quoted 5 lines

This sounds like we're fixing the CLK_SET_RATE_GATE flag. I'd prefer we also describe how adding that flag to some clk doesn't solve the problem. I'm all more commit text when introducing this API. Please don't go super verbose, but at least describe the real problem.

Yes we are, with another patch later in this series. CLK_SET_RATE_GATE is a particular case of clock protection, where the clock rate is protected by provider (kind of the clock protecting itself) instead of being protected by the consumer.

Quoted 85 lines
Quoted 4 lines

That's the short and sweet version. If more verbosity is needed as to why rate_range doesn't need this, there are some good reasons:

I'm not really concerned about rate range handling this problem here. Let's try to untangle the two in this discussion please.

Quoted 48 lines
Quoted 10 lines
Quoted 9 lines

If you go over the initial RFC, the point is also for the CCF to favor other
(unused parent) when several (sometimes with the same capabilities) are available. I think this is also a fairly common use case. That's something
rate_range won't do either, as far as I understood.

Quoted 5 lines

Fair enough, but why do we want consumers to need to know that there are sometimes unused parents that aren't getting chosen for a particular frequency? I see this as exposing the internals of the clk tree to consumers when they shouldn't need to care. Of course, sometimes clk consumers really do care about internals,

Right, sometimes they do, and we need to strike a balance. I think that this api has been needed for some time. It very likely could have been included in the initial version of the CCF that was merged years back if I hadn't been trying very hard to stick only to the existing clk.h.

clk_set_rate has always been a "last write wins" api, across a shared resource, and we've always known that this is not a great situation. This patch series does a good job of solving that issue, in conjunction with the existing range stuff.

Quoted 17 lines

for example if some PLL is used for a display controller and it's also routed out of the chip on the display phy pins to encode data or something. Then perhaps we really want to use one particular PLL instead of a generic one that may also be a parent of the display controller clk. Making sure clk_set_rate() doesn't trample on clks deep in the tree seems different than this though.

Going back to your RFC series cover letter though, I see three PLLs (mppl0,1,2) and two users of the PLLs (amclk and mclk_i958). Is anything else using these PLLs in the system? Why are we doing all this stuff instead of hard-coding the parents for these clks to be different PLLs? If we want it to be flexible we could assign parents to the cts_amclk_sel and cts_mclk_i958_sel to be different PLLs in DT via assigned clock parents. Or it could just be hard-coded in the clk driver during probe.

Quoted 4 lines

If there's really sharing going on, and you can't hardcode the parents, please indicate why that's the case in the commit text. I don't want to introduce another consumer API just because we didn't want to restrict the available parents for a couple clks.

Quoted 4 lines

I think the PLL sharing thing is a big distraction. Giving consumers the ability to guarantee that their rates are locked in using a simple critical section call just makes sense to me. If it helps with other cases then yay.

Ok. Can we get details on where we can't fix it in the provider layer? I'm fine to ignore the PLL sharing thing, if we can clearly describe a real situation where a clk consumer needs to lock in a rate, and that isn't the only consumer of a clk that is changing that rate or causing a glitch by changing some other rate up the tree. So far we haven't come across this case, presumably because clk providers are working around the problem by hardcoding parents that can change rate during determine_rate(), or blocking rate changes going up the tree for certain clks, or the hardware isn't designed in a way that something is shared while two devices are active, or maybe nobody has complained (likely!).

I'm all for consumers locking in rates in a critical section, just that I haven't seen a need for it so far. I've mostly seen that hardware doesn't design it this way, or that there's some sort of hardware plan to make sure that desired frequencies can be achieved when there's some shared resource. And the glitching thing hasn't been a problem because consumers are the only ones causing the glitch when they call clk_set_rate() and so far they have only called clk_set_rate() when their hardware is able to handle the glitch that comes down (e.g. audio turns off speaker output, or device is held in reset).

Quoted 2 lines

TL;DR: Please distract me from the PLL sharing thing with the real problem that's being solved.

Well, the problem is not sharing "per-se" but constraints resolution. When walking the tree, CCF check what each clock can provide and decide what the best setting is to provide the clock down the line.

The fact the several clocks may share/depend on the same parent is another constraint in the tree. When clock can't change or glitch, it adds constraints along the tree. This is what clock_protect() does.

A use-case of this, without "clock sharing" is the one I already explained is this thread:

Say you have 2 clocks fed by a divider (SET_RATE_PARENT of course)

# clock #1 is a PLL locked to 48000kHz
# clock #2 is another clock (whatever)

clock #2 request a new rate which may change the parent divider...

With the current CCF code, the divider would change and just screw up the PLL (which would end up with another rate)
Say, we could automatically relock the PLL at the initial rate (with clk_range for example), we would still get a glitch.
This would not happen with clock protect, clock #2 would have to work with what the divider provides at the moment ... or "determine" a better suited parent if available.

So what it solves is quite simple:?
* Once consumer protect a clock it has the guarantee from CCF that no-one will be messing with what comes out of the said clock.
* For CCF, it provides a more accurate view of the clock tree constraints when trying to determine a new clock rate.

Quoted 34 lines
Quoted 26 lines
Quoted 13 lines
Quoted 4 lines
Quoted 8 lines

Last but not least, it allows consumer to set the rate in a sort of critical
section and have the guarantee that nobody will be able to change the rate
between the clk_set_rate() call and prepare_enable(). That's something we don't
have at the moment.

Quoted 4 lines

Right, but clk_rate_protect() doesn't close the critical section between clk_set_rate() and clk_rate_protect() if another consumers changes the frequency, or if that consumer changes the frequency of some parent of the clk. This is why I'm asking what

Right, clk_set_rate_protect does this in the next patch in this series.

Quoted 5 lines

the use of this API is for. Shouldn't we want consumers to use clk_set_rate_protect() so they can be sure they got the rate they wanted, instead of hoping that something else hasn't come in between the set_rate and the protect calls and changed the frequency?

Quoted 7 lines

We can remove clk_rate_protect if you really want, but there is always the case that a consumer driver does not set the rate, but needs to guarantee that the rate will not change during operation.

Any driver that must both set the rate AND guarantee it will not change must use clk_set_rate_protect.

Quoted 7 lines

No need to remove the API. This is a good description of a case where a consumer would just call clk_rate_protect() (or perhaps clk_dont_glitch()) without caring what the rate is. I was missing this part of the argument because I got hung up on the critical section part. Maybe this can be added to the function documentation so we don't forget that some consumers don't set a rate but still care to make sure it doesn't glitch for them.

Sure, no problem.

Quoted 1 line
author reviewer
#24 lore raw

PATCH v3 5/10 clk: add support for clock protection

In reply to Michael Turquette
Quoted 144 lines · Michael Turquette

Hi Stephen,

Quoting Stephen Boyd (2017-08-03 17:18:36)

Quoted 15 lines · Jerome Brunet
Quoted 14 lines
Quoted 7 lines
Quoted 1 line

+void clk_rate_protect(struct clk *clk);

Is there any plan to use this clk_rate_protect() API? It seems inherently racy for a clk consumer to call clk_set_rate() and then this clk_rate_protect() API after that to lock the rate in. How about we leave this out of the consumer API until a user needs it?

Having this API available is whole reason I've been working on this for so long.
By the now, you may have forgot but I explained the use-case in first RFC
[0]
Here is an example (wip) of usage [1]

Quoted 3 lines
Quoted 3 lines

[0]: http://lkml.kernel.org/r/20170302173835.18313-1-jbrunet at baylibre.com [1]: https://github.com/jeromebrunet/linux/commits/amlogic/wip/audio-clk-l
ock

Indeed, something like rate protection or "lock rate" has been discussed since the birth of CCF. I remember a whiteboarding session between you, Paul W. and myself about it probably in 2012. Peter might have been there too.

Quoted 5 lines

If we're forgetting why something is introduced then it means the commit text is missing information. Please clearly describe the need for the API in the commit text for the patch that introduces it.

My $0.02 is that the "pick an unused PLL" thing is a benefit of this new api that is internal to the clock controller driver, and is not the driving force behind the series. If a simple, easy to understand justification for this patch series is needed, might I suggest something like the following for the next commit log/coverletter:

"Some clock consumers require that a clock rate must not deviate from its selected frequency. There can be several reasons for this, not least of which is that some hardware may not be able to handle or recover from a glitch caused by changing the clock rate while the hardware is in operation. The ability to lock a clock's rate, and release that lock, is a fundamental clock rate control primitive. It's absence is a bug that is fixed by this patch series."

That's the short and sweet version. If more verbosity is needed as to why rate_range doesn't need this, there are some good reasons:

1) simplicity: some consumers don't care about their rate, but do care that they rate doesn't change. clk_rate_{un}protect is much simpler than forcing those consumers to call clk_get_rate, then cache that value for future use and then call clk_set_rate_range.

2) expressiveness / debug: trying to find out why a clock rate is locked searching through every use of clk_set_rate_range is sort of lame, especially if variables are used to pass in min/max instead of hard-coded values. It's way way easier to just grep for clk_rate_protect.

Quoted 23 lines
Quoted 23 lines
Quoted 14 lines

Finally, When does a consumer want the rate of a clk to change after they call clk_set_rate() on it? I would guess that very few consumers would be willing to accept that. Which begs the question, if anyone will keep calling clk_set_rate() after this API (and the clk_set_rate_protect() API) is added. It almost seems like we would want it to be opt-out, instead of opt-in, so that consumers would call clk_set_rate() and expect it to be a stable clk rate after that, and they would call clk_set_rate_trample_on_me() or something properly named when they don't care what the rate is after they call the API.

Indeed, we generally don't want our rate to change, but:
- This is mostly for leaf clocks, the internal path would generally not care, as
long as the leaf are happy.
- Even a leaf may be open (be able to deal with) to small glitches, pll relock,
re parenting

Quoted 8 lines
Quoted 4 lines

Actually, if all the clock could not tolerate any glitches, there would have
been a lot of complains about CCF by now, it does not prevent glitches at all.

Well some devices handle glitches in the hardware, so the details of glitch free rate changes are hidden from clk consumers, and the software in general, on those devices.

On the hardware that I am familiar with, the problem of glitches lies not in the clock hardware, but with the downstream peripheral logic / ip block that consumes that clock signal. So it seems to me that having a consumer api for locking the rate makes perfect sense.

Quoted 8 lines
Quoted 7 lines

If you go over the initial RFC, the point is also for the CCF to favor other
(unused parent) when several (sometimes with the same capabilities) are available. I think this is also a fairly common use case. That's something rate_range won't do either, as far as I understood.

Quoted 5 lines

Fair enough, but why do we want consumers to need to know that there are sometimes unused parents that aren't getting chosen for a particular frequency? I see this as exposing the internals of the clk tree to consumers when they shouldn't need to care. Of course, sometimes clk consumers really do care about internals,

Right, sometimes they do, and we need to strike a balance. I think that this api has been needed for some time. It very likely could have been included in the initial version of the CCF that was merged years back if I hadn't been trying very hard to stick only to the existing clk.h.

clk_set_rate has always been a "last write wins" api, across a shared resource, and we've always known that this is not a great situation. This patch series does a good job of solving that issue, in conjunction with the existing range stuff.

Quoted 17 lines

for example if some PLL is used for a display controller and it's also routed out of the chip on the display phy pins to encode data or something. Then perhaps we really want to use one particular PLL instead of a generic one that may also be a parent of the display controller clk. Making sure clk_set_rate() doesn't trample on clks deep in the tree seems different than this though.

Going back to your RFC series cover letter though, I see three PLLs (mppl0,1,2) and two users of the PLLs (amclk and mclk_i958). Is anything else using these PLLs in the system? Why are we doing all this stuff instead of hard-coding the parents for these clks to be different PLLs? If we want it to be flexible we could assign parents to the cts_amclk_sel and cts_mclk_i958_sel to be different PLLs in DT via assigned clock parents. Or it could just be hard-coded in the clk driver during probe.

Quoted 4 lines

If there's really sharing going on, and you can't hardcode the parents, please indicate why that's the case in the commit text. I don't want to introduce another consumer API just because we didn't want to restrict the available parents for a couple clks.

Quoted 4 lines

I think the PLL sharing thing is a big distraction. Giving consumers the ability to guarantee that their rates are locked in using a simple critical section call just makes sense to me. If it helps with other cases then yay.

It guarantee that what is being protected, won't be broken ... for sure it helps with sharing issues.

Quoted 11 lines
Quoted 11 lines
Quoted 10 lines

Last but not least, it allows consumer to set the rate in a sort of critical
section and have the guarantee that nobody will be able to change the rate between the clk_set_rate() call and prepare_enable(). That's something we don't
have at the moment.

Quoted 6 lines
Quoted 4 lines

Right, but clk_rate_protect() doesn't close the critical section between clk_set_rate() and clk_rate_protect() if another consumers changes the frequency, or if that consumer changes the frequency of some parent of the clk. This is why I'm asking what

Right, clk_set_rate_protect does this in the next patch in this series.

Hum, I disagree here.?For sure, if you call clk_set_rate() before clk_rate_protect() you have not guarantee at all, but you are doing it wrong. The way to use this it to call clk_rate_protect() then clk_set_rate().

As explained earlier, as long as the clock is protected only once, the protecting consumer is still able to change the rate, because it is the only one depending on clock.

This is a good fit for driver which heavily depends on rate being but need to change the rate during during their operations. It is not necessary to unprotect the clock before calling clk_set_rate().

clk_set_rate_protect() is only introduce to help driver which could get in the situation where 2 consumers protect the clock w/o getting a chance to set the rate, exhausting the ressources. To re-set the rate, clk_rate_unprotect() must be called before calling clk_set_rate_protect() again.

Quoted 21 lines
Quoted 6 lines

the use of this API is for. Shouldn't we want consumers to use clk_set_rate_protect() so they can be sure they got the rate they wanted, instead of hoping that something else hasn't come in between the set_rate and the protect calls and changed the frequency?

We can remove clk_rate_protect if you really want, but there is always the case that a consumer driver does not set the rate, but needs to guarantee that the rate will not change during operation.

Any driver that must both set the rate AND guarantee it will not change must use clk_set_rate_protect.

Regards,
Mike

Quoted 4 lines

--?
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project

#25 lore raw

PATCH v3 5/10 clk: add support for clock protection

Quoting Jerome Brunet (2017-08-09 05:18:22)

Quoted 171 lines · Michael Turquette
Quoted 144 lines

Hi Stephen,

Quoting Stephen Boyd (2017-08-03 17:18:36)

Quoted 15 lines · Jerome Brunet
Quoted 14 lines
Quoted 7 lines
Quoted 1 line

+void clk_rate_protect(struct clk *clk);

Is there any plan to use this clk_rate_protect() API? It seems inherently racy for a clk consumer to call clk_set_rate() and then this clk_rate_protect() API after that to lock the rate in. How about we leave this out of the consumer API until a user needs it?

Having this API available is whole reason I've been working on this for so long.
By the now, you may have forgot but I explained the use-case in first RFC
[0]
Here is an example (wip) of usage [1]

Quoted 3 lines
Quoted 3 lines

[0]: http://lkml.kernel.org/r/20170302173835.18313-1-jbrunet at baylibre.com [1]: https://github.com/jeromebrunet/linux/commits/amlogic/wip/audio-clk-l
ock

Indeed, something like rate protection or "lock rate" has been discussed since the birth of CCF. I remember a whiteboarding session between you, Paul W. and myself about it probably in 2012. Peter might have been there too.

Quoted 5 lines

If we're forgetting why something is introduced then it means the commit text is missing information. Please clearly describe the need for the API in the commit text for the patch that introduces it.

My $0.02 is that the "pick an unused PLL" thing is a benefit of this new api that is internal to the clock controller driver, and is not the driving force behind the series. If a simple, easy to understand justification for this patch series is needed, might I suggest something like the following for the next commit log/coverletter:

"Some clock consumers require that a clock rate must not deviate from its selected frequency. There can be several reasons for this, not least of which is that some hardware may not be able to handle or recover from a glitch caused by changing the clock rate while the hardware is in operation. The ability to lock a clock's rate, and release that lock, is a fundamental clock rate control primitive. It's absence is a bug that is fixed by this patch series."

That's the short and sweet version. If more verbosity is needed as to why rate_range doesn't need this, there are some good reasons:

1) simplicity: some consumers don't care about their rate, but do care that they rate doesn't change. clk_rate_{un}protect is much simpler than forcing those consumers to call clk_get_rate, then cache that value for future use and then call clk_set_rate_range.

2) expressiveness / debug: trying to find out why a clock rate is locked searching through every use of clk_set_rate_range is sort of lame, especially if variables are used to pass in min/max instead of hard-coded values. It's way way easier to just grep for clk_rate_protect.

Quoted 23 lines
Quoted 23 lines
Quoted 14 lines

Finally, When does a consumer want the rate of a clk to change after they call clk_set_rate() on it? I would guess that very few consumers would be willing to accept that. Which begs the question, if anyone will keep calling clk_set_rate() after this API (and the clk_set_rate_protect() API) is added. It almost seems like we would want it to be opt-out, instead of opt-in, so that consumers would call clk_set_rate() and expect it to be a stable clk rate after that, and they would call clk_set_rate_trample_on_me() or something properly named when they don't care what the rate is after they call the API.

Indeed, we generally don't want our rate to change, but:
- This is mostly for leaf clocks, the internal path would generally not care, as
long as the leaf are happy.
- Even a leaf may be open (be able to deal with) to small glitches, pll relock,
re parenting

Quoted 8 lines
Quoted 4 lines

Actually, if all the clock could not tolerate any glitches, there would have
been a lot of complains about CCF by now, it does not prevent glitches at all.

Well some devices handle glitches in the hardware, so the details of glitch free rate changes are hidden from clk consumers, and the software in general, on those devices.

On the hardware that I am familiar with, the problem of glitches lies not in the clock hardware, but with the downstream peripheral logic / ip block that consumes that clock signal. So it seems to me that having a consumer api for locking the rate makes perfect sense.

Quoted 8 lines
Quoted 7 lines

If you go over the initial RFC, the point is also for the CCF to favor other
(unused parent) when several (sometimes with the same capabilities) are available. I think this is also a fairly common use case. That's something rate_range won't do either, as far as I understood.

Quoted 5 lines

Fair enough, but why do we want consumers to need to know that there are sometimes unused parents that aren't getting chosen for a particular frequency? I see this as exposing the internals of the clk tree to consumers when they shouldn't need to care. Of course, sometimes clk consumers really do care about internals,

Right, sometimes they do, and we need to strike a balance. I think that this api has been needed for some time. It very likely could have been included in the initial version of the CCF that was merged years back if I hadn't been trying very hard to stick only to the existing clk.h.

clk_set_rate has always been a "last write wins" api, across a shared resource, and we've always known that this is not a great situation. This patch series does a good job of solving that issue, in conjunction with the existing range stuff.

Quoted 17 lines

for example if some PLL is used for a display controller and it's also routed out of the chip on the display phy pins to encode data or something. Then perhaps we really want to use one particular PLL instead of a generic one that may also be a parent of the display controller clk. Making sure clk_set_rate() doesn't trample on clks deep in the tree seems different than this though.

Going back to your RFC series cover letter though, I see three PLLs (mppl0,1,2) and two users of the PLLs (amclk and mclk_i958). Is anything else using these PLLs in the system? Why are we doing all this stuff instead of hard-coding the parents for these clks to be different PLLs? If we want it to be flexible we could assign parents to the cts_amclk_sel and cts_mclk_i958_sel to be different PLLs in DT via assigned clock parents. Or it could just be hard-coded in the clk driver during probe.

Quoted 4 lines

If there's really sharing going on, and you can't hardcode the parents, please indicate why that's the case in the commit text. I don't want to introduce another consumer API just because we didn't want to restrict the available parents for a couple clks.

Quoted 4 lines

I think the PLL sharing thing is a big distraction. Giving consumers the ability to guarantee that their rates are locked in using a simple critical section call just makes sense to me. If it helps with other cases then yay.

It guarantee that what is being protected, won't be broken ... for sure it helps with sharing issues.

Quoted 11 lines
Quoted 11 lines
Quoted 10 lines

Last but not least, it allows consumer to set the rate in a sort of critical
section and have the guarantee that nobody will be able to change the rate between the clk_set_rate() call and prepare_enable(). That's something we don't
have at the moment.

Quoted 6 lines
Quoted 4 lines

Right, but clk_rate_protect() doesn't close the critical section between clk_set_rate() and clk_rate_protect() if another consumers changes the frequency, or if that consumer changes the frequency of some parent of the clk. This is why I'm asking what

Right, clk_set_rate_protect does this in the next patch in this series.

Quoted 7 lines

Hum, I disagree here.?For sure, if you call clk_set_rate() before clk_rate_protect() you have not guarantee at all, but you are doing it wrong. The way to use this it to call clk_rate_protect() then clk_set_rate().

As explained earlier, as long as the clock is protected only once, the protecting consumer is still able to change the rate, because it is the only one depending on clock.

I honestly do not see the difference between calling clk_set_rate_protect() versus calling clk_rate_protect() followed by clk_set_rate() within the rate-protected critical section.

Yes, you can always call clk_set_rate() later on, but I'm really surprised that calling clk_set_rate_protect() is somehow *wrong*. I'm quite sure that if this api gets merged that users will think of clk_set_rate_protect() in the same way that they think of using clk_prepare_enable() ... it's a useful helper that becomes the default choice of driver authors.

Quoted 4 lines

This is a good fit for driver which heavily depends on rate being but need to change the rate during during their operations. It is not necessary to unprotect the clock before calling clk_set_rate().

Sure, and drivers can aggressively call clk_{en,dis}able within the clk_prepare critical section, but very few do that in practice. From experience, driver authors will not micro-optimize this stuff.

Regarding my comment below to remove clk_rate_protect(), I rescind that statement. We definitely need the api, but it's also clear to me that most users will just opt-in to use clk_set_rate_protect() by default.

Regards,
Mike

Quoted 28 lines

clk_set_rate_protect() is only introduce to help driver which could get in the situation where 2 consumers protect the clock w/o getting a chance to set the rate, exhausting the ressources. To re-set the rate, clk_rate_unprotect() must be called before calling clk_set_rate_protect() again.

Quoted 21 lines
Quoted 6 lines

the use of this API is for. Shouldn't we want consumers to use clk_set_rate_protect() so they can be sure they got the rate they wanted, instead of hoping that something else hasn't come in between the set_rate and the protect calls and changed the frequency?

We can remove clk_rate_protect if you really want, but there is always the case that a consumer driver does not set the rate, but needs to guarantee that the rate will not change during operation.

Any driver that must both set the rate AND guarantee it will not change must use clk_set_rate_protect.

Regards,
Mike

Quoted 4 lines

--?
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project

author reviewer
#26 lore raw

PATCH v3 6/10 clk: add clk_set_rate_protect

In reply to Jerome Brunet

clk_set_rate_protect is a combination of clk_set_rate and clk_rate_protect within a critical section. In case where several protecting consumers compete to set the rate of the same provider, it provides a way to make sure that at least one of them will be satisfied before the resource is locked.

This is to avoid the unlikely situation where several consumers protect a clock provider and none actually get a rate it can work with.

---
 drivers/clk/clk.c   | 45 +++++++++++++++++++++++++++++++++++++++++++++
 include/linux/clk.h | 14 ++++++++++++++
 2 files changed, 59 insertions(+)
drivers/clk/clk.c +45 -0
index d688b8f59a59..d91236e70a04 100644
@@ -1809,6 +1809,51 @@ int clk_set_rate(struct clk *clk, unsigned long rate)
 EXPORT_SYMBOL_GPL(clk_set_rate);
 
 /**
+ * clk_set_rate_protect - specify a new rate and protect it
+ * @clk: the clk whose rate is being changed
+ * @rate: the new rate for clk
+ *
+ * This is a combination of clk_set_rate and clk_rate_protect within
+ * a critical section
+ *
+ * This can be used initially to ensure that at least 1 consumers is
+ * statisfied when several protecting consummers are competing for the
+ * same clock provider.
+ *
+ * The protection is not applied if setting the rate failed.
+ *
+ * Returns 0 on success, -EERROR otherwise.
+ */
+int clk_set_rate_protect(struct clk *clk, unsigned long rate)
+{
+	int ret;
+
+	if (!clk)
+		return 0;
+
+	/* prevent racing with updates to the clock topology */
+	clk_prepare_lock();
+
+	/*
+	 * The temporary protection removal is not here, on purpose
+	 * This function is meant to be used in instead of clk_rate_protect,
+	 * so before the consumer code path protect the clock provider
+	 */
+
+	ret = clk_core_set_rate_nolock(clk->core, rate);
+
+	if (!ret) {
+		clk_core_rate_protect(clk->core);
+		clk->protect_count++;
+	}
+
+	clk_prepare_unlock();
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(clk_set_rate_protect);
+
+/**
  * clk_set_rate_range - set a rate range for a clock source
  * @clk: clock source
  * @min: desired minimum clock rate in Hz, inclusive
include/linux/clk.h +14 -0
index b60c36f2e6b0..7a01b32f7029 100644
@@ -497,6 +497,15 @@ long clk_round_rate(struct clk *clk, unsigned long rate);
 int clk_set_rate(struct clk *clk, unsigned long rate);
 
 /**
+ * clk_set_rate_protect - set and protect the clock rate for a clock source
+ * @clk: clock source
+ * @rate: desired clock rate in Hz
+ *
+ * Returns success (0) or negative errno.
+ */
+int clk_set_rate_protect(struct clk *clk, unsigned long rate);
+
+/**
  * clk_has_parent - check if a clock is a possible parent for another
  * @clk: clock source
  * @parent: parent clock source
@@ -638,6 +647,11 @@ static inline int clk_set_rate(struct clk *clk, unsigned long rate)
 	return 0;
 }
 
+static inline int clk_set_rate_protect(struct clk *clk, unsigned long rate)
+{
+	return 0;
+}
+
 static inline long clk_round_rate(struct clk *clk, unsigned long rate)
 {
 	return 0;
Signature · 1 line
2.9.4
#27 lore raw

PATCH v3 6/10 clk: add clk_set_rate_protect

drivers/clk/clk.c int clk_set_rate(struct clk *clk, unsigned long rate) · line 1816

Quoted 13 lines · Jerome Brunet
drivers/clk/clk.c +5 -0
index d688b8f59a59..d91236e70a04 100644
@@ -1809,6 +1809,51 @@ int clk_set_rate(struct clk *clk, unsigned long rate)
 EXPORT_SYMBOL_GPL(clk_set_rate);
 
 /**
+ * clk_set_rate_protect - specify a new rate and protect it
+ * @clk: the clk whose rate is being changed
+ * @rate: the new rate for clk
+ *
+ * This is a combination of clk_set_rate and clk_rate_protect within

s/clk_set_rate/clk_set_rate()/
s/clk_rate_protect/clk_rate_protect()/

drivers/clk/clk.c int clk_set_rate(struct clk *clk, unsigned long rate) · line 1819

Quoted 3 lines
drivers/clk/clk.c +3 -0
+ * a critical section
+ *
+ * This can be used initially to ensure that at least 1 consumers is

s/consumers/consumer/

drivers/clk/clk.c int clk_set_rate(struct clk *clk, unsigned long rate) · line 1820

Quoted 1 line
drivers/clk/clk.c +1 -0
+ * statisfied when several protecting consummers are competing for the

s/consummers/consumers/

Quoted 9 lines
drivers/clk/clk.c +9 -0
+ * same clock provider.
+ *
+ * The protection is not applied if setting the rate failed.
+ *
+ * Returns 0 on success, -EERROR otherwise.
+ */
+int clk_set_rate_protect(struct clk *clk, unsigned long rate)
+{
+	int ret;

drivers/clk/clk.c int clk_set_rate(struct clk *clk, unsigned long rate) · line 1839

Quoted 10 lines
drivers/clk/clk.c +10 -0
+
+	if (!clk)
+		return 0;
+
+	/* prevent racing with updates to the clock topology */
+	clk_prepare_lock();
+
+	/*
+	 * The temporary protection removal is not here, on purpose
+	 * This function is meant to be used in instead of clk_rate_protect,

s/in//

drivers/clk/clk.c int clk_set_rate(struct clk *clk, unsigned long rate) · line 1844

Quoted 5 lines
drivers/clk/clk.c +5 -0
+	 * so before the consumer code path protect the clock provider
+	 */
+
+	ret = clk_core_set_rate_nolock(clk->core, rate);
+

Drop newline please.

Quoted 15 lines
drivers/clk/clk.c +12 -0
+	if (!ret) {
+		clk_core_rate_protect(clk->core);
+		clk->protect_count++;
+	}
+
+	clk_prepare_unlock();
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(clk_set_rate_protect);
+
+/**
  * clk_set_rate_range - set a rate range for a clock source
  * @clk: clock source
  * @min: desired minimum clock rate in Hz, inclusive
Signature · 2 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
author reviewer
#28 lore raw

PATCH v3 7/10 clk: rollback set_rate_range changes on failure

In reply to Jerome Brunet
---
 drivers/clk/clk.c | 8 ++++++++
 1 file changed, 8 insertions(+)
drivers/clk/clk.c +8 -0
index d91236e70a04..253f1d3f0971 100644
@@ -1864,6 +1864,7 @@ EXPORT_SYMBOL_GPL(clk_set_rate_protect);
 int clk_set_rate_range(struct clk *clk, unsigned long min, unsigned long max)
 {
 	int ret = 0;
+	unsigned int old_min, old_max;
 
 	if (!clk)
 		return 0;
@@ -1881,9 +1882,16 @@ int clk_set_rate_range(struct clk *clk, unsigned long min, unsigned long max)
 		clk_core_rate_unprotect(clk->core);
 
 	if (min != clk->min_rate || max != clk->max_rate) {
+		old_min = clk->min_rate;
+		old_max = clk->max_rate;
 		clk->min_rate = min;
 		clk->max_rate = max;
 		ret = clk_core_set_rate_nolock(clk->core, clk->core->req_rate);
+		if (ret) {
+			/* undo changes */
+			clk->min_rate = old_min;
+			clk->max_rate = old_max;
+		}
 	}
 
 	if (clk->protect_count)
Signature · 1 line
2.9.4
#29 lore raw

PATCH v3 7/10 clk: rollback set_rate_range changes on failure

Quoted 1 line · Jerome Brunet

There should be some commit text here describing the problem. Also a Fixes: tag and please put this earlier in the series.

Quoted 33 lines
---
 drivers/clk/clk.c | 8 ++++++++
 1 file changed, 8 insertions(+)
drivers/clk/clk.c +8 -0
index d91236e70a04..253f1d3f0971 100644
@@ -1864,6 +1864,7 @@ EXPORT_SYMBOL_GPL(clk_set_rate_protect);
 int clk_set_rate_range(struct clk *clk, unsigned long min, unsigned long max)
 {
 	int ret = 0;
+	unsigned int old_min, old_max;
 
 	if (!clk)
 		return 0;
@@ -1881,9 +1882,16 @@ int clk_set_rate_range(struct clk *clk, unsigned long min, unsigned long max)
 		clk_core_rate_unprotect(clk->core);
 
 	if (min != clk->min_rate || max != clk->max_rate) {
+		old_min = clk->min_rate;
+		old_max = clk->max_rate;
 		clk->min_rate = min;
 		clk->max_rate = max;
 		ret = clk_core_set_rate_nolock(clk->core, clk->core->req_rate);
+		if (ret) {
+			/* undo changes */
+			clk->min_rate = old_min;
+			clk->max_rate = old_max;
+		}
 	}
 
 	if (clk->protect_count)
Signature · 2 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
author reviewer
#30 lore raw

PATCH v3 7/10 clk: rollback set_rate_range changes on failure

Quoted 5 lines · Stephen Boyd
Quoted 1 line · Jerome Brunet

There should be some commit text here describing the problem. Also a Fixes: tag and please put this earlier in the series.

Fixes added but as explained, I dropped this patch after thinking about Peter's observations.

The new candidate patch would be [0]. I suggest we discuss this out of the clock
protect thread to avoid mixing issues.

[0]: https://github.com/jeromebrunet/linux/commit/235e477f346a9e8d115dda257f9f73
834151bd7f

Quoted 39 lines
Quoted 37 lines

---
?drivers/clk/clk.c | 8 ++++++++
?1 file changed, 8 insertions(+)

drivers/clk/clk.c +0 -0
index d91236e70a04..253f1d3f0971 100644
@@ -1864,6 +1864,7 @@ EXPORT_SYMBOL_GPL(clk_set_rate_protect);

?int clk_set_rate_range(struct clk *clk, unsigned long min, unsigned long max)
?{
? int ret = 0;

drivers/clk/clk.c +1 -0
+	unsigned int old_min, old_max;

?
? if (!clk)
? return 0;

drivers/clk/clk.c +0 -0
@@ -1881,9 +1882,16 @@ int clk_set_rate_range(struct clk *clk, unsigned long
 min, unsigned long max)
 ?		clk_core_rate_unprotect(clk->core);

?
? if (min != clk->min_rate || max != clk->max_rate) {

drivers/clk/clk.c +2 -0
+		old_min = clk->min_rate;
+		old_max = clk->max_rate;

? clk->min_rate = min;
? clk->max_rate = max;
? ret = clk_core_set_rate_nolock(clk->core, clk->core-

Quoted 1 line

req_rate);

drivers/clk/clk.c +5 -0
+		if (ret) {
+			/* undo changes */
+			clk->min_rate = old_min;
+			clk->max_rate = old_max;
+		}

? }
?
? if (clk->protect_count)

author reviewer
#31 lore raw

PATCH v3 8/10 clk: cosmetic changes to clk_summary debugfs entry

In reply to Jerome Brunet

clk_summary debugfs entry was already well over the traditional 80 characters per line limit but it grew even larger with the addition of clock protection.

---
 drivers/clk/clk.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)
drivers/clk/clk.c +4 -3
index 253f1d3f0971..8d57e130c4e0 100644
@@ -2262,7 +2262,7 @@ static void clk_summary_show_one(struct seq_file *s, struct clk_core *c,
 	if (!c)
 		return;
 
-	seq_printf(s, "%*s%-*s %11d %12d %12d %11lu %10lu %-3d\n",
+	seq_printf(s, "%*s%-*s %7d %8d %8d %11lu %10lu %-3d\n",
 		   level * 3 + 1, "",
 		   30 - level * 3, c->name,
 		   c->enable_count, c->prepare_count, c->protect_count,
@@ -2289,8 +2289,9 @@ static int clk_summary_show(struct seq_file *s, void *data)
 	struct clk_core *c;
 	struct hlist_head **lists = (struct hlist_head **)s->private;
 
-	seq_puts(s, "   clock                         enable_cnt  prepare_cnt  protect_cnt        rate   accuracy   phase\n");
-	seq_puts(s, "----------------------------------------------------------------------------------------------------\n");
+	seq_puts(s, "                                 enable  prepare  protect                               \n");
+	seq_puts(s, "   clock                          count    count    count        rate   accuracy   phase\n");
+	seq_puts(s, "----------------------------------------------------------------------------------------\n");
 
 	clk_prepare_lock();
 
Signature · 1 line
2.9.4
#32 lore raw

PATCH v3 8/10 clk: cosmetic changes to clk_summary debugfs entry

Quoted 4 lines · Jerome Brunet

clk_summary debugfs entry was already well over the traditional 80 characters per line limit but it grew even larger with the addition of clock protection.

Before/after example output perhaps?

Quoted 2 lines

---

Signature · 2 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
author reviewer
#33 lore raw

PATCH v3 9/10 clk: fix incorrect usage of ENOSYS

In reply to Jerome Brunet

ENOSYS is special and should only be used for incorrect syscall number. It does not seem to be the case here.

Reported by checkpatch.pl while working on clock protection.

---
 drivers/clk/clk.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/clk/clk.c +1 -1
index 8d57e130c4e0..5d545954c48f 100644
@@ -2032,7 +2032,7 @@ static int clk_core_set_parent_nolock(struct clk_core *core,
 
 	/* verify ops for for multi-parent clks */
 	if ((core->num_parents > 1) && (!core->ops->set_parent))
-		return -ENOSYS;
+		return -EPERM;
 
 	/* check that we are allowed to re-parent if the clock is in use */
 	if ((core->flags & CLK_SET_PARENT_GATE) && core->prepare_count)
Signature · 1 line
2.9.4
#34 lore raw

PATCH v3 9/10 clk: fix incorrect usage of ENOSYS

Quoted 6 lines · Jerome Brunet

ENOSYS is special and should only be used for incorrect syscall number. It does not seem to be the case here.

Reported by checkpatch.pl while working on clock protection.

Could also go earlier in the series.

Signature · 2 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
author reviewer
#35 lore raw

PATCH v3 10/10 clk: fix CLK_SET_RATE_GATE with clock rate protection

In reply to Jerome Brunet

Using clock rate protection, we can now enforce CLK_SET_RATE_GATE along the clock tree

---
 drivers/clk/clk.c | 14 +++++++++++---
 1 file changed, 11 insertions(+), 3 deletions(-)
drivers/clk/clk.c +11 -3
index 5d545954c48f..971f39d4e879 100644
@@ -587,6 +587,9 @@ static void clk_core_unprepare(struct clk_core *core)
 	if (WARN_ON(core->prepare_count == 1 && core->flags & CLK_IS_CRITICAL))
 		return;
 
+	if (core->flags & CLK_SET_RATE_GATE)
+		clk_core_rate_unprotect(core);
+
 	if (--core->prepare_count > 0)
 		return;
 
@@ -657,6 +660,14 @@ static int clk_core_prepare(struct clk_core *core)
 
 	core->prepare_count++;
 
+	/*
+	 * CLK_SET_RATE_GATE is a special case of clock protection
+	 * Instead of a consumer protection, the provider is protecting
+	 * itself when prepared
+	 */
+	if (core->flags & CLK_SET_RATE_GATE)
+		clk_core_rate_protect(core);
+
 	return 0;
 }
 
@@ -1738,9 +1749,6 @@ static int clk_core_set_rate_nolock(struct clk_core *core,
 	if (clk_core_rate_is_protected(core))
 		return -EBUSY;
 
-	if ((core->flags & CLK_SET_RATE_GATE) && core->prepare_count)
-		return -EBUSY;
-
 	/* calculate new rates and get the topmost changed clock */
 	top = clk_calc_new_rates(core, req_rate);
 	if (!top)
Signature · 1 line
2.9.4
#36 lore raw

v3 cover clk: implement clock rate protection mechanism

In reply to Jerome Brunet
Quoted 3 lines · Jerome Brunet

The goal of this patchset is to provide a way for consumers to inform the system that they depend on the rate of the clock source and can't tolerate other consumers changing the rate or causing glitches.

Just for context: chat kind of consumers are these?

i.e. the consumers that can't tolerate a clock rate change?

I understand it if it is a hardware limitation (like the block would crash if it glitches or changes rate).

On the other hand, in the kernel we have things like in arch/arm/kernel/smp_twd.c we use a notifier to deal with a changing clock rate.

Just want to be sure that you're not working around something that can be dealt with using rate change notifiers.

(OK maybe a stupid question, I assume this is not the case, but anyways, had to ask.)

Yours,
Linus Walleij

author reviewer
#37 lore raw

v3 cover clk: implement clock rate protection mechanism

Quoted 7 lines · Linus Walleij
Quoted 3 lines · Jerome Brunet

The goal of this patchset is to provide a way for consumers to inform the system that they depend on the rate of the clock source and can't tolerate other consumers changing the rate or causing glitches.

Just for context: chat kind of consumers are these?

When the rate is critical to perform a particular task. My example is the audio and i2s output. You can't tolerate glitches during the playback, the end user would complain (longer description in the original RFC)

Quoted 6 lines

i.e. the consumers that can't tolerate a clock rate change?

I understand it if it is a hardware limitation (like the block would crash if it glitches or changes rate).

Quoted 6 lines

On the other hand, in the kernel we have things like in arch/arm/kernel/smp_twd.c we use a notifier to deal with a changing clock rate.

Just want to be sure that you're not working around something that can be dealt with using rate change notifiers.

As far as I can tell, there was no way to enforce this along the tree. You could "block" a clock, but one could simply change the rate of the parent which change the rate of your blocked clock ... game over.

With notifiers you can block a rate change. but this is happening too late.?

Here, it is expressed as constraint along the clock tree which is used in the determine_rate callback.?If you have a ip block which can be fed by multiple parent clock, this will allow the determine_rate to favor another parent depending on the rate requested

It also fixes the behavior of CLK_SET_RATE_GATE flag, which is why I put you in CC.

ux500 uses this flag several time, I'd like make sure people are not relying on its broken implementation.

Quoted 3 lines

(OK maybe a stupid question, I assume this is not the case, but anyways, had to ask.)

Not at all :)
Happy to answer your question. Not sure this was clear though. Feel free to tell me if it is not.

Quoted 3 lines

Yours,
Linus Walleij

#38 lore raw

v3 cover clk: implement clock rate protection mechanism

Quoted 5 lines · Jerome Brunet

On Tue, 2017-06-20 at 11:07 +0200, Linus Walleij wrote:

When the rate is critical to perform a particular task. My example is the audio and i2s output. You can't tolerate glitches during the playback, the end user would complain (longer description in the original RFC)

I see. Thanks for your detailed explanation!

Quoted 5 lines

It also fixes the behavior of CLK_SET_RATE_GATE flag, which is why I put you in CC.

ux500 uses this flag several time, I'd like make sure people are not relying on its broken implementation.

Ux500 audio is broken, but I'm fixing it a little at a time...

Yours,
Linus Walleij

author reviewer
#39 lore raw

v3 cover clk: implement clock rate protection mechanism

Quoted 14 lines · Linus Walleij
Quoted 6 lines · Jerome Brunet

On Tue, 2017-06-20 at 11:07 +0200, Linus Walleij wrote:
When the rate is critical to perform a particular task. My example is the audio
and i2s output. You can't tolerate glitches during the playback, the end user
would complain (longer description in the original RFC)

I see. Thanks for your detailed explanation!

Quoted 4 lines

It also fixes the behavior of CLK_SET_RATE_GATE flag, which is why I put you in
CC.

Quoted 5 lines
Quoted 3 lines

ux500 uses this flag several time, I'd like make sure people are not relying on
its broken implementation.

Ux500 audio is broken, but I'm fixing it a little at a time...

No problem with Ux500 audio, don't worry :)
Audio is just one application among others.

The concern regarding ux500 is that the clock controller declares clocks using the CLK_SET_RATE_GATE flag (like qcom, at91 and several other)

here is the definition:
#define CLK_SET_RATE_GATE BIT(0) /* must be gated across rate change */

My interpretation it that, as long as clock is enabled, rate can't change.

The implementation of this flag is currently broken:
* If you call set_rate on directly on the clock while it is enabled, you will get -EBUSY, as expected
* If you call set_rate on its parent, rate will change, changing the rate of the child clock as well ...

With this patchset applied, calling set_rate on the parent would also return -EBUSY, enforcing the "rate can't change while enabled" property.

To build confidence that this won't be causing regression, I'd like to check that platform using this flag are no relying on the broken behavior.

I've included the clock maintainers of at91, qcom, and ux500 (you) in this thread because they are the heaviest users of this flag, so the more likely to report a problem.

If you could apply this series and just do things as usual, It'd be awesome !

I'll also seek the help of the kci guys, see if it is possible to give the series spin on it.

Quoted 3 lines

Yours,
Linus Walleij

#40 lore raw

v3 cover clk: implement clock rate protection mechanism

+Quentin

Quoted 41 lines · On Tue, 20 Jun 2017 14:32:30 +0200 Jerome Brunet <[email protected]> wrote:
Quoted 14 lines · Linus Walleij
Quoted 6 lines · Jerome Brunet

On Tue, 2017-06-20 at 11:07 +0200, Linus Walleij wrote:
When the rate is critical to perform a particular task. My example is the audio
and i2s output. You can't tolerate glitches during the playback, the end user
would complain (longer description in the original RFC)

I see. Thanks for your detailed explanation!

Quoted 4 lines

It also fixes the behavior of CLK_SET_RATE_GATE flag, which is why I put you in
CC.

Quoted 5 lines
Quoted 3 lines

ux500 uses this flag several time, I'd like make sure people are not relying on
its broken implementation.

Ux500 audio is broken, but I'm fixing it a little at a time...

No problem with Ux500 audio, don't worry :)
Audio is just one application among others.

The concern regarding ux500 is that the clock controller declares clocks using the CLK_SET_RATE_GATE flag (like qcom, at91 and several other)

here is the definition:
#define CLK_SET_RATE_GATE BIT(0) /* must be gated across rate change */

My interpretation it that, as long as clock is enabled, rate can't change.

The implementation of this flag is currently broken:
* If you call set_rate on directly on the clock while it is enabled, you will get -EBUSY, as expected
* If you call set_rate on its parent, rate will change, changing the rate of the child clock as well ...

With this patchset applied, calling set_rate on the parent would also return -EBUSY, enforcing the "rate can't change while enabled" property.

Quoted 6 lines

To build confidence that this won't be causing regression, I'd like to check that platform using this flag are no relying on the broken behavior.

I've included the clock maintainers of at91, qcom, and ux500 (you) in this thread because they are the heaviest users of this flag, so the more likely to report a problem.

This flag in at91 clk drivers really means that rate cannot be changed while the clk is enabled. We have other clock where this is not a problem (at least, nothing in mentioned in the datasheet).

Quoted 2 lines

If you could apply this series and just do things as usual, It'd be awesome !

Actually, this is a feature I was pushing for a while back [1], because I had the same problem (one user messing up with a PLL while others were relying on its rate). I'm glad someone finally had time to provide a solution for this problem.

Quentin tested the series, and I guess he'll soon add his Tested-by. Note that this series does not address all problems. For example, when several drivers are setting a rate on different clks that take the same parent, the first one to set the rate and enable the clk wins.

He has an hack-ish solution for our audio-pll case preventing non audio users to mess up with the audio PLL. It'd be great to have a generic solution, though I don't know how this can be solved without advanced description of the clk-rate setting policy.

[1]https://patchwork.kernel.org/patch/6204221/

#41 lore raw

v3 cover clk: implement clock rate protection mechanism

Hi Jerome,

Quoted 70 lines · Boris Brezillon

+Quentin

Quoted 41 lines · On Tue, 20 Jun 2017 14:32:30 +0200 Jerome Brunet <[email protected]> wrote:
Quoted 14 lines · Linus Walleij
Quoted 6 lines · Jerome Brunet

On Tue, 2017-06-20 at 11:07 +0200, Linus Walleij wrote:
When the rate is critical to perform a particular task. My example is the audio
and i2s output. You can't tolerate glitches during the playback, the end user
would complain (longer description in the original RFC)

I see. Thanks for your detailed explanation!

Quoted 4 lines

It also fixes the behavior of CLK_SET_RATE_GATE flag, which is why I put you in
CC.

Quoted 5 lines
Quoted 3 lines

ux500 uses this flag several time, I'd like make sure people are not relying on
its broken implementation.

Ux500 audio is broken, but I'm fixing it a little at a time...

No problem with Ux500 audio, don't worry :)
Audio is just one application among others.

The concern regarding ux500 is that the clock controller declares clocks using the CLK_SET_RATE_GATE flag (like qcom, at91 and several other)

here is the definition:
#define CLK_SET_RATE_GATE BIT(0) /* must be gated across rate change */

My interpretation it that, as long as clock is enabled, rate can't change.

The implementation of this flag is currently broken:
* If you call set_rate on directly on the clock while it is enabled, you will get -EBUSY, as expected
* If you call set_rate on its parent, rate will change, changing the rate of the child clock as well ...

With this patchset applied, calling set_rate on the parent would also return -EBUSY, enforcing the "rate can't change while enabled" property.

Quoted 6 lines

To build confidence that this won't be causing regression, I'd like to check that platform using this flag are no relying on the broken behavior.

I've included the clock maintainers of at91, qcom, and ux500 (you) in this thread because they are the heaviest users of this flag, so the more likely to report a problem.

This flag in at91 clk drivers really means that rate cannot be changed while the clk is enabled. We have other clock where this is not a problem (at least, nothing in mentioned in the datasheet).

Quoted 2 lines

If you could apply this series and just do things as usual, It'd be awesome !

Actually, this is a feature I was pushing for a while back [1], because I had the same problem (one user messing up with a PLL while others were relying on its rate). I'm glad someone finally had time to provide a solution for this problem.

Quentin tested the series, and I guess he'll soon add his Tested-by. Note that this series does not address all problems. For example, when several drivers are setting a rate on different clks that take the same parent, the first one to set the rate and enable the clk wins.

Quoted 7 lines

He has an hack-ish solution for our audio-pll case preventing non audio users to mess up with the audio PLL. It'd be great to have a generic solution, though I don't know how this can be solved without advanced description of the clk-rate setting policy.

[1]https://patchwork.kernel.org/patch/6204221/

I've tested the patch series and it seems good to me.

Our hackish solution for the moment is to deny clock children to take the audio-pll clock as parent except if it's classd (the audio IP). That way, we take care of the driver probing "order" (i.e., the first driver to enable the clock will lock the rate, but maybe that rate isn't the one we want for a more critical driver) but it is definitely not a neat solution.

Thanks,
Quentin

Signature · 3 lines
Quentin Schulz, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
author reviewer
#42 lore raw

v3 cover clk: implement clock rate protection mechanism

Quoted 91 lines · Quentin Schulz

Hi Jerome,

Quoted 88 lines · Boris Brezillon

+Quentin

Quoted 51 lines · On Tue, 20 Jun 2017 14:32:30 +0200 Jerome Brunet <[email protected]> wrote:
Quoted 18 lines · Linus Walleij

On Tue, Jun 20, 2017 at 12:50 PM, Jerome Brunet <[email protected]> wrote:??

Quoted 8 lines · Linus Walleij

When the rate is critical to perform a particular task. My example is the
audio
and i2s output. You can't tolerate glitches during the playback, the end
user
would complain (longer description in the original RFC)??

I see. Thanks for your detailed explanation!
??

Quoted 5 lines

It also fixes the behavior of CLK_SET_RATE_GATE flag, which is why I put you
in
CC.

Quoted 6 lines
Quoted 4 lines

ux500 uses this flag several time, I'd like make sure people are not relying
on
its broken implementation.??

Ux500 audio is broken, but I'm fixing it a little at a time...??

No problem with Ux500 audio, don't worry :)
Audio is just one application among others.

The concern regarding ux500 is that the clock controller declares clocks using
the CLK_SET_RATE_GATE flag (like qcom, at91 and several other)

here is the definition:
#define CLK_SET_RATE_GATE BIT(0) /* must be gated across rate
change */

My interpretation it that, as long as clock is enabled, rate can't change.

The implementation of this flag is currently broken:
* If you call set_rate on directly on the clock while it is enabled, you will
get -EBUSY, as expected
* If you call set_rate on its parent, rate will change, changing the rate of the
child clock as well ...

With this patchset applied, calling set_rate on the parent would also return
-EBUSY, enforcing the "rate can't change while enabled" property.

Quoted 8 lines

To build confidence that this won't be causing regression, I'd like to check
that platform using this flag are no relying on the broken behavior.

I've included the clock maintainers of at91, qcom, and ux500 (you) in this thread because they are the heaviest users of this flag, so the more likely to
report a problem.

This flag in at91 clk drivers really means that rate cannot be changed while the clk is enabled. We have other clock where this is not a problem (at least, nothing in mentioned in the datasheet).

Quoted 3 lines

If you could apply this series and just do things as usual, It'd be awesome !

Actually, this is a feature I was pushing for a while back [1], because I had the same problem (one user messing up with a PLL while others were relying on its rate). I'm glad someone finally had time to provide a solution for this problem.

Quentin tested the series, and I guess he'll soon add his Tested-by. Note that this series does not address all problems. For example, when several drivers are setting a rate on different clks that take the same parent, the first one to set the rate and enable the clk wins.

He has an hack-ish solution for our audio-pll case preventing non audio users to mess up with the audio PLL. It'd be great to have a generic solution, though I don't know how this can be solved without advanced description of the clk-rate setting policy.

Quoted 6 lines
Quoted 2 lines

[1]https://patchwork.kernel.org/patch/6204221/

I've tested the patch series and it seems good to me.

Thx a lot for taking the time to test this.

Quoted 8 lines

Our hackish solution for the moment is to deny clock children to take the audio-pll clock as parent except if it's classd (the audio IP). That way, we take care of the driver probing "order" (i.e., the first driver to enable the clock will lock the rate, but maybe that rate isn't the one we want for a more critical driver) but it is definitely not a neat solution.

For sure, there is still a lot of thing to be done :)
Ressource allocation and management is a never ending story I suppose.
If you have an idea to improve things, maybe you should post an RFC to kick offthe discussion.

Quoted 3 lines

Thanks,
Quentin

#43 lore raw

v3 cover clk: implement clock rate protection mechanism

In reply to Jerome Brunet
Quoted 6 lines · Jerome Brunet

To build confidence that this won't be causing regression, I'd like to check that platform using this flag are no relying on the broken behavior.

I've included the clock maintainers of at91, qcom, and ux500 (you) in this thread because they are the heaviest users of this flag, so the more likely to report a problem.

OK I'm pretty sure this will not impact the ux500 in a negative way, we don't play around much with the clocks in that way.

for the entire series.

Yours,
Linus Walleij

author reviewer
#44 lore raw

v3 cover clk: implement clock rate protection mechanism

In reply to Jerome Brunet
Quoted 48 lines · Jerome Brunet
Quoted 16 lines · Linus Walleij
Quoted 6 lines · Jerome Brunet

On Tue, 2017-06-20 at 11:07 +0200, Linus Walleij wrote:
When the rate is critical to perform a particular task. My example is the audio
and i2s output. You can't tolerate glitches during the playback, the end user
would complain (longer description in the original RFC)

I see. Thanks for your detailed explanation!

Quoted 5 lines

It also fixes the behavior of CLK_SET_RATE_GATE flag, which is why I put you
in
CC.

Quoted 6 lines
Quoted 4 lines

ux500 uses this flag several time, I'd like make sure people are not relying
on
its broken implementation.

Ux500 audio is broken, but I'm fixing it a little at a time...

No problem with Ux500 audio, don't worry :)
Audio is just one application among others.

The concern regarding ux500 is that the clock controller declares clocks using the CLK_SET_RATE_GATE flag (like qcom, at91 and several other)

here is the definition:
#define CLK_SET_RATE_GATE BIT(0) /* must be gated across rate change */

My interpretation it that, as long as clock is enabled, rate can't change.

The implementation of this flag is currently broken:
* If you call set_rate on directly on the clock while it is enabled, you will get -EBUSY, as expected
* If you call set_rate on its parent, rate will change, changing the rate of the
child clock as well ...

With this patchset applied, calling set_rate on the parent would also return -EBUSY, enforcing the "rate can't change while enabled" property.

To build confidence that this won't be causing regression, I'd like to check that platform using this flag are no relying on the broken behavior.

Quoted 9 lines

I've included the clock maintainers of at91, qcom, and ux500 (you) in this thread because they are the heaviest users of this flag, so the more likely to report a problem.

If you could apply this series and just do things as usual, It'd be awesome !

I'll also seek the help of the kci guys, see if it is possible to give the series spin on it.

I managed to have a run on kci - based on v4.12-rc6:
https://kernelci.org/boot/all/job/khilman/branch/to-build/kernel/v4.12-rc6-10-ge
a373ddef830/

There was no build regression but kci did find one boot regression on qcom platforms:
* qcom-apq8064-cm-qs600
* qcom-apq8064-ifc6410

it seems the problem is coming from the clock used by the mmc driver (drivers/mmc/host/mmci.c)

the driver does following sequence:
* get_clk
* prepare_enable
* get_rate
* set_rate
* ...

with clock SDCx_clk (qcom_apq8064.dtsi:1037). This clock has CLK_SET_RATE_PARENT flag so it will transmit the request to its parent.
The parent of this clock is SDCx_src which has the CLK_SET_RATE_GATE flag.

This can't work with sequence above. The flag was clearly bypassed before, so I think it would be best to remove CLK_SET_RATE_GATE from the SDCx_src clocks

Stephen, would you agree ?

There was an issue with the chip board as well but this particular board has not been very reliable in this lab lately. It has failed on several other job.

Quoted 5 lines
Quoted 3 lines

Yours,
Linus Walleij

#45 lore raw

v3 cover clk: implement clock rate protection mechanism

Quoted 24 lines · Jerome Brunet

I managed to have a run on kci - based on v4.12-rc6:
https://kernelci.org/boot/all/job/khilman/branch/to-build/kernel/v4.12-rc6-10-ge
a373ddef830/

There was no build regression but kci did find one boot regression on qcom platforms:
* qcom-apq8064-cm-qs600
* qcom-apq8064-ifc6410

it seems the problem is coming from the clock used by the mmc driver (drivers/mmc/host/mmci.c)

the driver does following sequence:
* get_clk
* prepare_enable
* get_rate
* set_rate
* ...

with clock SDCx_clk (qcom_apq8064.dtsi:1037). This clock has CLK_SET_RATE_PARENT flag so it will transmit the request to its parent.
The parent of this clock is SDCx_src which has the CLK_SET_RATE_GATE flag.

Quoted 8 lines

This can't work with sequence above. The flag was clearly bypassed before, so I think it would be best to remove CLK_SET_RATE_GATE from the SDCx_src clocks

Stephen, would you agree ?

There was an issue with the chip board as well but this particular board has not been very reliable in this lab lately. It has failed on several other job.

Yes the flag was never working before and we've been ignoring the subtle problems that it causes to change the rate while the clk is enabled. On these older SoCs, all the clks marked with CLK_SET_RATE_GATE need to implement something to forcibly disable all child clks across the rate change. That is the hardware recommended procedure.

So something like

get_clk
prepare_enable
get_rate
set_rate
call ->set_rate() op
forcibly disable children of rcgs actually change the rate of rcg forcibly enable all children that were disabled

and have that happen under one big spinlock local to the qcom driver I suppose so that enable/disable can't leak into the rate change. Fun! I'll make an attempt at implementing the right solution tomorrow/tonight. Of course, we can remove the flag from qcom drivers if it's blocking this series.

Signature · 2 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
author reviewer
#46 lore raw

v3 cover clk: implement clock rate protection mechanism

Quoted 38 lines · Stephen Boyd
Quoted 30 lines · Jerome Brunet

I managed to have a run on kci - based on v4.12-rc6:
https://kernelci.org/boot/all/job/khilman/branch/to-build/kernel/v4.12-rc6-1
0-ge
a373ddef830/

There was no build regression but kci did find one boot regression on qcom platforms:
* qcom-apq8064-cm-qs600
* qcom-apq8064-ifc6410

it seems the problem is coming from the clock used by the mmc driver (drivers/mmc/host/mmci.c)

the driver does following sequence:
* get_clk
* prepare_enable
* get_rate
* set_rate
* ...

with clock SDCx_clk (qcom_apq8064.dtsi:1037). This clock has CLK_SET_RATE_PARENT
flag so it will transmit the request to its parent.
The parent of this clock is SDCx_src which has the CLK_SET_RATE_GATE flag.

This can't work with sequence above. The flag was clearly bypassed before, so I
think it would be best to remove CLK_SET_RATE_GATE from the SDCx_src clocks

Quoted 6 lines

Stephen, would you agree ?

There was an issue with the chip board as well but this particular board has not
been very reliable in this lab lately. It has failed on several other job.

Quoted 6 lines

Yes the flag was never working before and we've been ignoring the subtle problems that it causes to change the rate while the clk is enabled. On these older SoCs, all the clks marked with CLK_SET_RATE_GATE need to implement something to forcibly disable all child clks across the rate change. That is the hardware recommended procedure.

Seems that HW has been doing fine w/o recommended procedure so far ;)

Quoted 12 lines

So something like

get_clk
prepare_enable
get_rate
set_rate
call ->set_rate() op
forcibly disable children of rcgs actually change the rate of rcg forcibly enable all children that were disabled

Quoted 6 lines

and have that happen under one big spinlock local to the qcom driver I suppose so that enable/disable can't leak into the rate change. Fun! I'll make an attempt at implementing the right solution tomorrow/tonight. Of course, we can remove the flag from qcom drivers if it's blocking this series.

Yeah, it is probably blocking the series.

In the following mail, I've only replied where I wanted to discuss a bit more. For everything else, please consider the comments agreed and the modifications done as requested.

#47 lore raw

v3 cover clk: implement clock rate protection mechanism

Quoted 39 lines · Jerome Brunet
Quoted 38 lines · Stephen Boyd
Quoted 36 lines · Jerome Brunet

I managed to have a run on kci - based on v4.12-rc6:
https://kernelci.org/boot/all/job/khilman/branch/to-build/kernel/v4.12-rc6-1
0-ge
a373ddef830/

There was no build regression but kci did find one boot regression on qcom platforms:
* qcom-apq8064-cm-qs600
* qcom-apq8064-ifc6410

it seems the problem is coming from the clock used by the mmc driver (drivers/mmc/host/mmci.c)

the driver does following sequence:
* get_clk
* prepare_enable
* get_rate
* set_rate
* ...

with clock SDCx_clk (qcom_apq8064.dtsi:1037). This clock has CLK_SET_RATE_PARENT
flag so it will transmit the request to its parent.
The parent of this clock is SDCx_src which has the CLK_SET_RATE_GATE flag.

This can't work with sequence above. The flag was clearly bypassed before, so I
think it would be best to remove CLK_SET_RATE_GATE from the SDCx_src clocks

Stephen, would you agree ?

There was an issue with the chip board as well but this particular board has not
been very reliable in this lab lately. It has failed on several other job.

Quoted 8 lines
Quoted 6 lines

Yes the flag was never working before and we've been ignoring the subtle problems that it causes to change the rate while the clk is enabled. On these older SoCs, all the clks marked with CLK_SET_RATE_GATE need to implement something to forcibly disable all child clks across the rate change. That is the hardware recommended procedure.

Seems that HW has been doing fine w/o recommended procedure so far ;)

Dubious at best. There's only light testing with upstream kernels on these SoCs, and probably "doing fine" is more like "nobody has reported a problem" in this case.

Quoted 20 lines
Quoted 13 lines

So something like

get_clk
prepare_enable
get_rate
set_rate
call ->set_rate() op
forcibly disable children of rcgs actually change the rate of rcg forcibly enable all children that were disabled

Quoted 6 lines

and have that happen under one big spinlock local to the qcom driver I suppose so that enable/disable can't leak into the rate change. Fun! I'll make an attempt at implementing the right solution tomorrow/tonight. Of course, we can remove the flag from qcom drivers if it's blocking this series.

Quoted 6 lines

Yeah, it is probably blocking the series.

In the following mail, I've only replied where I wanted to discuss a bit more. For everything else, please consider the comments agreed and the modifications done as requested.

Ok. Good that we can move forward in some way so this is not a blocker. I've almost completed writing the qcom code to force clks on and off so it will be resolved one way or the other soon.

Signature · 2 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
#48 lore raw

v3 cover clk: implement clock rate protection mechanism

Quoting Stephen Boyd (2017-07-27 15:44:59)

Quoted 9 lines · Jerome Brunet
Quoted 4 lines

In the following mail, I've only replied where I wanted to discuss a bit more. For everything else, please consider the comments agreed and the modifications done as requested.

Ok. Good that we can move forward in some way so this is not a blocker. I've almost completed writing the qcom code to force clks on and off so it will be resolved one way or the other soon.

Stephen, are all of the existential issues are sufficiently resolved?

Jerome, are you going to submit a v4?

Thanks,
Mike

Quoted 4 lines
Signature · 3 lines
-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
author reviewer
#49 lore raw

v3 cover clk: implement clock rate protection mechanism

Quoted 9 lines · Michael Turquette

Quoting Stephen Boyd (2017-07-27 15:44:59)

Quoted 8 lines · Jerome Brunet
Quoted 6 lines

In the following mail, I've only replied where I wanted to discuss a bit more.
For everything else, please consider the comments agreed and the modifications
done as requested.

Quoted 7 lines
Quoted 3 lines

Ok. Good that we can move forward in some way so this is not a blocker. I've almost completed writing the qcom code to force clks on and off so it will be resolved one way or the other soon.

Stephen, are all of the existential issues are sufficiently resolved?

Jerome, are you going to submit a v4?

Once the current discussion reaches an agreement, yes for sure. If it helps, I could send it right now, with the points being discussed addressed

Quoted 8 lines

Thanks,
Mike

Quoted 4 lines

--?
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project

author reviewer
#50 lore raw

v3 cover clk: implement clock rate protection mechanism

In reply to Jerome Brunet
Quoted 46 lines · Jerome Brunet

This Patchset is related the RFC [0] and the discussion around CLK_SET_RATE_GATE available here [1]

This patchset is based on clk-next.

The goal of this patchset is to provide a way for consumers to inform the system that they depend on the rate of the clock source and can't tolerate other consumers changing the rate or causing glitches.

With this series there is 3 use-case:
?- the provider is not protected: nothing changes
?- the provider is protected by only 1 consumer (and only once), then only ???this consumer will be able to alter the rate of the clock, as it is the ???only one depending on it.
?- If the provider is protected more than once, or by the provider itself, ???the rate is basically locked and protected against reparenting.

The last patch provide the same functionnality for providers themself, fixing CLK_SET_RATE_GATE flag (enforce clock gating along the tree)

qcom, at91 and ux500 are the heaviest users of this flag. If anybody having one these platform could try this series, it would help build confidence that the platform relying on CLK_SET_RATE_GATE (even if broken) don't get any regression.

Changes since RFC:
?- s/clk_protect/clk_rate_protect
?- Request rework around core_nolock function
?- Add clk_set_rate_protect
?- Reword clk_rate_protect and clk_unprotect documentation ?- Add few comments to explain the code
?- Add 2 last patches to fix users of CLK_SET_RATE_GATE

Changes since v1:
?- Add patch 4: Check if the rate would actually change before continuing, a ???possibly in clk_set_rate.

Changes since v2: [2]
?- Fix issues reported by Adriana Reus (Thanks !)
?- Dropped patch "clk: move CLK_SET_RATE_GATE protection from prepare ???to enable". This was broken as the protect count, like the prepare_count ???should only be accessed under the prepare_lock.
?- No change around bail-out code. Mike wanted to ponder a bit more on it. ?- Patch 1 still included, could not find the clk-next-protect Mike was ???referring to.

Quoted 8 lines

This was tested with the audio use case mentioned in [1]

[0]: https://lkml.kernel.org/r/20170321183330.26722-1-jbrunet at baylibre.com [1]: https://lkml.kernel.org/r/148942423440.82235.17188153691656009029 at resonan ce
[2]: https://lkml.kernel.org/r/20170521215958.19743-1-jbrunet at baylibre.com

Mike, Stephen,

Gentle Ping: I bet you are busy but this v3 was posted 1 month ago. So far, We've add the ack of Linus (ux500).
Quentin (at91) and KCi (some other stuff ;) ) tested the series.

If we could add tests on qcom (and the fix i suggested after the kci run), we would have tested the heaviest users of CLK_SET_RATE_GATE.

Please, could you let me know how to progress on this topic ? Thx

Regards
Jerome

Quoted 18 lines

Jerome Brunet (10):
? clk: take the prepare lock out of clk_core_set_parent ? clk: add clk_core_set_phase_nolock function
? clk: rework calls to round and determine rate callbacks ? clk: use round rate to bail out early in set_rate ? clk: add support for clock protection
? clk: add clk_set_rate_protect
? clk: rollback set_rate_range changes on failure ? clk: cosmetic changes to clk_summary debugfs entry ? clk: fix incorrect usage of ENOSYS
? clk: fix CLK_SET_RATE_GATE with clock rate protection

?drivers/clk/clk.c????????????| 428 ++++++++++++++++++++++++++++++++++++----
---
?include/linux/clk-provider.h |???1 + ?include/linux/clk.h??????????|??43 +++++
?3 files changed, 402 insertions(+), 70 deletions(-)