All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 00/10] clk: implement clock rate protection mechanism
@ 2017-06-12 19:44 ` Jerome Brunet
  0 siblings, 0 replies; 102+ messages in thread
From: Jerome Brunet @ 2017-06-12 19:44 UTC (permalink / raw)
  To: Michael Turquette, Stephen Boyd, linux-clk
  Cc: Jerome Brunet, Kevin Hilman, linux-amlogic, Russell King,
	Linus Walleij, Boris Brezillon, Adriana Reus

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@baylibre.com
[1]: https://lkml.kernel.org/r/148942423440.82235.17188153691656009029@resonance
[2]: https://lkml.kernel.org/r/20170521215958.19743-1-jbrunet@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(-)

-- 
2.9.4

^ permalink raw reply	[flat|nested] 102+ messages in thread

* [PATCH v3 00/10] clk: implement clock rate protection mechanism
@ 2017-06-12 19:44 ` Jerome Brunet
  0 siblings, 0 replies; 102+ messages in thread
From: Jerome Brunet @ 2017-06-12 19:44 UTC (permalink / raw)
  To: linus-amlogic

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(-)

-- 
2.9.4

^ permalink raw reply	[flat|nested] 102+ messages in thread

* [PATCH v3 01/10] clk: take the prepare lock out of clk_core_set_parent
  2017-06-12 19:44 ` Jerome Brunet
@ 2017-06-12 19:44   ` Jerome Brunet
  -1 siblings, 0 replies; 102+ messages in thread
From: Jerome Brunet @ 2017-06-12 19:44 UTC (permalink / raw)
  To: Michael Turquette, Stephen Boyd, linux-clk
  Cc: Jerome Brunet, Kevin Hilman, linux-amlogic, Russell King,
	Linus Walleij, Boris Brezillon

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.

Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
---
 drivers/clk/clk.c | 39 ++++++++++++++++++---------------------
 1 file changed, 18 insertions(+), 21 deletions(-)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index fc58c52a26b4..f5c371532509 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -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);
-- 
2.9.4

^ permalink raw reply related	[flat|nested] 102+ messages in thread

* [PATCH v3 01/10] clk: take the prepare lock out of clk_core_set_parent
@ 2017-06-12 19:44   ` Jerome Brunet
  0 siblings, 0 replies; 102+ messages in thread
From: Jerome Brunet @ 2017-06-12 19:44 UTC (permalink / raw)
  To: linus-amlogic

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.

Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
---
 drivers/clk/clk.c | 39 ++++++++++++++++++---------------------
 1 file changed, 18 insertions(+), 21 deletions(-)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index fc58c52a26b4..f5c371532509 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -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);
-- 
2.9.4

^ permalink raw reply related	[flat|nested] 102+ messages in thread

* [PATCH v3 02/10] clk: add clk_core_set_phase_nolock function
  2017-06-12 19:44 ` Jerome Brunet
@ 2017-06-12 19:44   ` Jerome Brunet
  -1 siblings, 0 replies; 102+ messages in thread
From: Jerome Brunet @ 2017-06-12 19:44 UTC (permalink / raw)
  To: Michael Turquette, Stephen Boyd, linux-clk
  Cc: Jerome Brunet, Kevin Hilman, linux-amlogic, Russell King,
	Linus Walleij, Boris Brezillon

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.

Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
---
 drivers/clk/clk.c | 31 +++++++++++++++++++------------
 1 file changed, 19 insertions(+), 12 deletions(-)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index f5c371532509..dceaf0ff23db 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -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;
-- 
2.9.4

^ permalink raw reply related	[flat|nested] 102+ messages in thread

* [PATCH v3 02/10] clk: add clk_core_set_phase_nolock function
@ 2017-06-12 19:44   ` Jerome Brunet
  0 siblings, 0 replies; 102+ messages in thread
From: Jerome Brunet @ 2017-06-12 19:44 UTC (permalink / raw)
  To: linus-amlogic

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.

Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
---
 drivers/clk/clk.c | 31 +++++++++++++++++++------------
 1 file changed, 19 insertions(+), 12 deletions(-)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index f5c371532509..dceaf0ff23db 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -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;
-- 
2.9.4

^ permalink raw reply related	[flat|nested] 102+ messages in thread

* [PATCH v3 03/10] clk: rework calls to round and determine rate callbacks
  2017-06-12 19:44 ` Jerome Brunet
@ 2017-06-12 19:44   ` Jerome Brunet
  -1 siblings, 0 replies; 102+ messages in thread
From: Jerome Brunet @ 2017-06-12 19:44 UTC (permalink / raw)
  To: Michael Turquette, Stephen Boyd, linux-clk
  Cc: Jerome Brunet, Kevin Hilman, linux-amlogic, Russell King,
	Linus Walleij, Boris Brezillon

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.

Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
---
 drivers/clk/clk.c | 78 +++++++++++++++++++++++++++++++------------------------
 1 file changed, 44 insertions(+), 34 deletions(-)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index dceaf0ff23db..8cc4672414be 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -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;
-- 
2.9.4

^ permalink raw reply related	[flat|nested] 102+ messages in thread

* [PATCH v3 03/10] clk: rework calls to round and determine rate callbacks
@ 2017-06-12 19:44   ` Jerome Brunet
  0 siblings, 0 replies; 102+ messages in thread
From: Jerome Brunet @ 2017-06-12 19:44 UTC (permalink / raw)
  To: linus-amlogic

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.

Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
---
 drivers/clk/clk.c | 78 +++++++++++++++++++++++++++++++------------------------
 1 file changed, 44 insertions(+), 34 deletions(-)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index dceaf0ff23db..8cc4672414be 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -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;
-- 
2.9.4

^ permalink raw reply related	[flat|nested] 102+ messages in thread

* [PATCH v3 04/10] clk: use round rate to bail out early in set_rate
  2017-06-12 19:44 ` Jerome Brunet
@ 2017-06-12 19:44   ` Jerome Brunet
  -1 siblings, 0 replies; 102+ messages in thread
From: Jerome Brunet @ 2017-06-12 19:44 UTC (permalink / raw)
  To: Michael Turquette, Stephen Boyd, linux-clk
  Cc: Jerome Brunet, Kevin Hilman, linux-amlogic, Russell King,
	Linus Walleij, Boris Brezillon

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

Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
---
 drivers/clk/clk.c | 23 +++++++++++++++++++++--
 1 file changed, 21 insertions(+), 2 deletions(-)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 8cc4672414be..163cb9832f10 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -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;
 
-- 
2.9.4

^ permalink raw reply related	[flat|nested] 102+ messages in thread

* [PATCH v3 04/10] clk: use round rate to bail out early in set_rate
@ 2017-06-12 19:44   ` Jerome Brunet
  0 siblings, 0 replies; 102+ messages in thread
From: Jerome Brunet @ 2017-06-12 19:44 UTC (permalink / raw)
  To: linus-amlogic

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

Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
---
 drivers/clk/clk.c | 23 +++++++++++++++++++++--
 1 file changed, 21 insertions(+), 2 deletions(-)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 8cc4672414be..163cb9832f10 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -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;
 
-- 
2.9.4

^ permalink raw reply related	[flat|nested] 102+ messages in thread

* [PATCH v3 05/10] clk: add support for clock protection
  2017-06-12 19:44 ` Jerome Brunet
@ 2017-06-12 19:44   ` Jerome Brunet
  -1 siblings, 0 replies; 102+ messages in thread
From: Jerome Brunet @ 2017-06-12 19:44 UTC (permalink / raw)
  To: Michael Turquette, Stephen Boyd, linux-clk
  Cc: Jerome Brunet, Kevin Hilman, linux-amlogic, Russell King,
	Linus Walleij, Boris Brezillon

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.

Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
---
 drivers/clk/clk.c            | 205 +++++++++++++++++++++++++++++++++++++++++--
 include/linux/clk-provider.h |   1 +
 include/linux/clk.h          |  29 ++++++
 3 files changed, 229 insertions(+), 6 deletions(-)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 163cb9832f10..d688b8f59a59 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -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)
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index a428aec36ace..ebd7df5f375f 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -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);
diff --git a/include/linux/clk.h b/include/linux/clk.h
index 91bd464f4c9b..b60c36f2e6b0 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -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;
-- 
2.9.4

^ permalink raw reply related	[flat|nested] 102+ messages in thread

* [PATCH v3 05/10] clk: add support for clock protection
@ 2017-06-12 19:44   ` Jerome Brunet
  0 siblings, 0 replies; 102+ messages in thread
From: Jerome Brunet @ 2017-06-12 19:44 UTC (permalink / raw)
  To: linus-amlogic

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.

Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
---
 drivers/clk/clk.c            | 205 +++++++++++++++++++++++++++++++++++++++++--
 include/linux/clk-provider.h |   1 +
 include/linux/clk.h          |  29 ++++++
 3 files changed, 229 insertions(+), 6 deletions(-)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 163cb9832f10..d688b8f59a59 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -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)
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index a428aec36ace..ebd7df5f375f 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -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);
diff --git a/include/linux/clk.h b/include/linux/clk.h
index 91bd464f4c9b..b60c36f2e6b0 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -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;
-- 
2.9.4

^ permalink raw reply related	[flat|nested] 102+ messages in thread

* [PATCH v3 06/10] clk: add clk_set_rate_protect
  2017-06-12 19:44 ` Jerome Brunet
@ 2017-06-12 19:44   ` Jerome Brunet
  -1 siblings, 0 replies; 102+ messages in thread
From: Jerome Brunet @ 2017-06-12 19:44 UTC (permalink / raw)
  To: Michael Turquette, Stephen Boyd, linux-clk
  Cc: Jerome Brunet, Kevin Hilman, linux-amlogic, Russell King,
	Linus Walleij, Boris Brezillon

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.

Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
---
 drivers/clk/clk.c   | 45 +++++++++++++++++++++++++++++++++++++++++++++
 include/linux/clk.h | 14 ++++++++++++++
 2 files changed, 59 insertions(+)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index d688b8f59a59..d91236e70a04 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -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
diff --git a/include/linux/clk.h b/include/linux/clk.h
index b60c36f2e6b0..7a01b32f7029 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -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;
-- 
2.9.4

^ permalink raw reply related	[flat|nested] 102+ messages in thread

* [PATCH v3 06/10] clk: add clk_set_rate_protect
@ 2017-06-12 19:44   ` Jerome Brunet
  0 siblings, 0 replies; 102+ messages in thread
From: Jerome Brunet @ 2017-06-12 19:44 UTC (permalink / raw)
  To: linus-amlogic

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.

Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
---
 drivers/clk/clk.c   | 45 +++++++++++++++++++++++++++++++++++++++++++++
 include/linux/clk.h | 14 ++++++++++++++
 2 files changed, 59 insertions(+)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index d688b8f59a59..d91236e70a04 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -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
diff --git a/include/linux/clk.h b/include/linux/clk.h
index b60c36f2e6b0..7a01b32f7029 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -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;
-- 
2.9.4

^ permalink raw reply related	[flat|nested] 102+ messages in thread

* [PATCH v3 07/10] clk: rollback set_rate_range changes on failure
  2017-06-12 19:44 ` Jerome Brunet
@ 2017-06-12 19:44   ` Jerome Brunet
  -1 siblings, 0 replies; 102+ messages in thread
From: Jerome Brunet @ 2017-06-12 19:44 UTC (permalink / raw)
  To: Michael Turquette, Stephen Boyd, linux-clk
  Cc: Jerome Brunet, Kevin Hilman, linux-amlogic, Russell King,
	Linus Walleij, Boris Brezillon

Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
---
 drivers/clk/clk.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index d91236e70a04..253f1d3f0971 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -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)
-- 
2.9.4

^ permalink raw reply related	[flat|nested] 102+ messages in thread

* [PATCH v3 07/10] clk: rollback set_rate_range changes on failure
@ 2017-06-12 19:44   ` Jerome Brunet
  0 siblings, 0 replies; 102+ messages in thread
From: Jerome Brunet @ 2017-06-12 19:44 UTC (permalink / raw)
  To: linus-amlogic

Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
---
 drivers/clk/clk.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index d91236e70a04..253f1d3f0971 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -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)
-- 
2.9.4

^ permalink raw reply related	[flat|nested] 102+ messages in thread

* [PATCH v3 08/10] clk: cosmetic changes to clk_summary debugfs entry
  2017-06-12 19:44 ` Jerome Brunet
@ 2017-06-12 19:44   ` Jerome Brunet
  -1 siblings, 0 replies; 102+ messages in thread
From: Jerome Brunet @ 2017-06-12 19:44 UTC (permalink / raw)
  To: Michael Turquette, Stephen Boyd, linux-clk
  Cc: Jerome Brunet, Kevin Hilman, linux-amlogic, Russell King,
	Linus Walleij, Boris Brezillon

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.

Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
---
 drivers/clk/clk.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 253f1d3f0971..8d57e130c4e0 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -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();
 
-- 
2.9.4

^ permalink raw reply related	[flat|nested] 102+ messages in thread

* [PATCH v3 08/10] clk: cosmetic changes to clk_summary debugfs entry
@ 2017-06-12 19:44   ` Jerome Brunet
  0 siblings, 0 replies; 102+ messages in thread
From: Jerome Brunet @ 2017-06-12 19:44 UTC (permalink / raw)
  To: linus-amlogic

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.

Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
---
 drivers/clk/clk.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 253f1d3f0971..8d57e130c4e0 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -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();
 
-- 
2.9.4

^ permalink raw reply related	[flat|nested] 102+ messages in thread

* [PATCH v3 09/10] clk: fix incorrect usage of ENOSYS
  2017-06-12 19:44 ` Jerome Brunet
@ 2017-06-12 19:44   ` Jerome Brunet
  -1 siblings, 0 replies; 102+ messages in thread
From: Jerome Brunet @ 2017-06-12 19:44 UTC (permalink / raw)
  To: Michael Turquette, Stephen Boyd, linux-clk
  Cc: Jerome Brunet, Kevin Hilman, linux-amlogic, Russell King,
	Linus Walleij, Boris Brezillon

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.

Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
---
 drivers/clk/clk.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 8d57e130c4e0..5d545954c48f 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -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)
-- 
2.9.4

^ permalink raw reply related	[flat|nested] 102+ messages in thread

* [PATCH v3 09/10] clk: fix incorrect usage of ENOSYS
@ 2017-06-12 19:44   ` Jerome Brunet
  0 siblings, 0 replies; 102+ messages in thread
From: Jerome Brunet @ 2017-06-12 19:44 UTC (permalink / raw)
  To: linus-amlogic

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.

Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
---
 drivers/clk/clk.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 8d57e130c4e0..5d545954c48f 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -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)
-- 
2.9.4

^ permalink raw reply related	[flat|nested] 102+ messages in thread

* [PATCH v3 10/10] clk: fix CLK_SET_RATE_GATE with clock rate protection
  2017-06-12 19:44 ` Jerome Brunet
@ 2017-06-12 19:44   ` Jerome Brunet
  -1 siblings, 0 replies; 102+ messages in thread
From: Jerome Brunet @ 2017-06-12 19:44 UTC (permalink / raw)
  To: Michael Turquette, Stephen Boyd, linux-clk
  Cc: Jerome Brunet, Kevin Hilman, linux-amlogic, Russell King,
	Linus Walleij, Boris Brezillon

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

Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
---
 drivers/clk/clk.c | 14 +++++++++++---
 1 file changed, 11 insertions(+), 3 deletions(-)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 5d545954c48f..971f39d4e879 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -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)
-- 
2.9.4

^ permalink raw reply related	[flat|nested] 102+ messages in thread

* [PATCH v3 10/10] clk: fix CLK_SET_RATE_GATE with clock rate protection
@ 2017-06-12 19:44   ` Jerome Brunet
  0 siblings, 0 replies; 102+ messages in thread
From: Jerome Brunet @ 2017-06-12 19:44 UTC (permalink / raw)
  To: linus-amlogic

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

Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
---
 drivers/clk/clk.c | 14 +++++++++++---
 1 file changed, 11 insertions(+), 3 deletions(-)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 5d545954c48f..971f39d4e879 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -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)
-- 
2.9.4

^ permalink raw reply related	[flat|nested] 102+ messages in thread

* Re: [PATCH v3 00/10] clk: implement clock rate protection mechanism
  2017-06-12 19:44 ` Jerome Brunet
@ 2017-06-20  9:07   ` Linus Walleij
  -1 siblings, 0 replies; 102+ messages in thread
From: Linus Walleij @ 2017-06-20  9:07 UTC (permalink / raw)
  To: Jerome Brunet
  Cc: Michael Turquette, Stephen Boyd, linux-clk, Kevin Hilman,
	open list:ARM/Amlogic Meson...,
	Russell King, Boris Brezillon, Adriana Reus

On Mon, Jun 12, 2017 at 9:44 PM, Jerome Brunet <jbrunet@baylibre.com> wrote:

> 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

^ permalink raw reply	[flat|nested] 102+ messages in thread

* [PATCH v3 00/10] clk: implement clock rate protection mechanism
@ 2017-06-20  9:07   ` Linus Walleij
  0 siblings, 0 replies; 102+ messages in thread
From: Linus Walleij @ 2017-06-20  9:07 UTC (permalink / raw)
  To: linus-amlogic

On Mon, Jun 12, 2017 at 9:44 PM, Jerome Brunet <jbrunet@baylibre.com> wrote:

> 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

^ permalink raw reply	[flat|nested] 102+ messages in thread

* Re: [PATCH v3 00/10] clk: implement clock rate protection mechanism
  2017-06-20  9:07   ` Linus Walleij
@ 2017-06-20 10:50     ` Jerome Brunet
  -1 siblings, 0 replies; 102+ messages in thread
From: Jerome Brunet @ 2017-06-20 10:50 UTC (permalink / raw)
  To: Linus Walleij
  Cc: Michael Turquette, Stephen Boyd, linux-clk, Kevin Hilman,
	open list:ARM/Amlogic Meson...,
	Russell King, Boris Brezillon, Adriana Reus

On Tue, 2017-06-20 at 11:07 +0200, Linus Walleij wrote:
> On Mon, Jun 12, 2017 at 9:44 PM, Jerome Brunet <jbrunet@baylibre.com> wrote:
> 
> > 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)

> 
> 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.

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.

> 
> (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.

> 
> Yours,
> Linus Walleij

^ permalink raw reply	[flat|nested] 102+ messages in thread

* [PATCH v3 00/10] clk: implement clock rate protection mechanism
@ 2017-06-20 10:50     ` Jerome Brunet
  0 siblings, 0 replies; 102+ messages in thread
From: Jerome Brunet @ 2017-06-20 10:50 UTC (permalink / raw)
  To: linus-amlogic

On Tue, 2017-06-20 at 11:07 +0200, Linus Walleij wrote:
> On Mon, Jun 12, 2017 at 9:44 PM, Jerome Brunet <jbrunet@baylibre.com> wrote:
> 
> > 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)

> 
> 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.

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.

> 
> (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.

> 
> Yours,
> Linus Walleij

^ permalink raw reply	[flat|nested] 102+ messages in thread

* Re: [PATCH v3 00/10] clk: implement clock rate protection mechanism
  2017-06-20 10:50     ` Jerome Brunet
@ 2017-06-20 11:54       ` Linus Walleij
  -1 siblings, 0 replies; 102+ messages in thread
From: Linus Walleij @ 2017-06-20 11:54 UTC (permalink / raw)
  To: Jerome Brunet
  Cc: Michael Turquette, Stephen Boyd, linux-clk, Kevin Hilman,
	open list:ARM/Amlogic Meson...,
	Russell King, Boris Brezillon, Adriana Reus

On Tue, Jun 20, 2017 at 12:50 PM, Jerome Brunet <jbrunet@baylibre.com> wrote:
> 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!

> 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

^ permalink raw reply	[flat|nested] 102+ messages in thread

* [PATCH v3 00/10] clk: implement clock rate protection mechanism
@ 2017-06-20 11:54       ` Linus Walleij
  0 siblings, 0 replies; 102+ messages in thread
From: Linus Walleij @ 2017-06-20 11:54 UTC (permalink / raw)
  To: linus-amlogic

On Tue, Jun 20, 2017 at 12:50 PM, Jerome Brunet <jbrunet@baylibre.com> wrote:
> 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!

> 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

^ permalink raw reply	[flat|nested] 102+ messages in thread

* Re: [PATCH v3 00/10] clk: implement clock rate protection mechanism
  2017-06-20 11:54       ` Linus Walleij
@ 2017-06-20 12:32         ` Jerome Brunet
  -1 siblings, 0 replies; 102+ messages in thread
From: Jerome Brunet @ 2017-06-20 12:32 UTC (permalink / raw)
  To: Linus Walleij
  Cc: Michael Turquette, Stephen Boyd, linux-clk, Kevin Hilman,
	open list:ARM/Amlogic Meson...,
	Russell King, Boris Brezillon, Adriana Reus

On Tue, 2017-06-20 at 13:54 +0200, Linus Walleij wrote:
> On Tue, Jun 20, 2017 at 12:50 PM, Jerome Brunet <jbrunet@baylibre.com> wrote:
> > 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!
> 
> > 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...

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.

> 
> Yours,
> Linus Walleij

^ permalink raw reply	[flat|nested] 102+ messages in thread

* [PATCH v3 00/10] clk: implement clock rate protection mechanism
@ 2017-06-20 12:32         ` Jerome Brunet
  0 siblings, 0 replies; 102+ messages in thread
From: Jerome Brunet @ 2017-06-20 12:32 UTC (permalink / raw)
  To: linus-amlogic

On Tue, 2017-06-20 at 13:54 +0200, Linus Walleij wrote:
> On Tue, Jun 20, 2017 at 12:50 PM, Jerome Brunet <jbrunet@baylibre.com> wrote:
> > 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!
> 
> > 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...

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.

> 
> Yours,
> Linus Walleij

^ permalink raw reply	[flat|nested] 102+ messages in thread

* Re: [PATCH v3 00/10] clk: implement clock rate protection mechanism
  2017-06-20 12:32         ` Jerome Brunet
@ 2017-06-20 12:47           ` Boris Brezillon
  -1 siblings, 0 replies; 102+ messages in thread
From: Boris Brezillon @ 2017-06-20 12:47 UTC (permalink / raw)
  To: Jerome Brunet
  Cc: Linus Walleij, Michael Turquette, Stephen Boyd, linux-clk,
	Kevin Hilman, open list:ARM/Amlogic Meson...,
	Russell King, Adriana Reus, Quentin Schulz

+Quentin

On Tue, 20 Jun 2017 14:32:30 +0200
Jerome Brunet <jbrunet@baylibre.com> wrote:

> On Tue, 2017-06-20 at 13:54 +0200, Linus Walleij wrote:
> > On Tue, Jun 20, 2017 at 12:50 PM, Jerome Brunet <jbrunet@baylibre.com> wrote:  
> > > 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!
> >   
> > > 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...  
> 
> 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.

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).

> 
> 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/

^ permalink raw reply	[flat|nested] 102+ messages in thread

* [PATCH v3 00/10] clk: implement clock rate protection mechanism
@ 2017-06-20 12:47           ` Boris Brezillon
  0 siblings, 0 replies; 102+ messages in thread
From: Boris Brezillon @ 2017-06-20 12:47 UTC (permalink / raw)
  To: linus-amlogic

+Quentin

On Tue, 20 Jun 2017 14:32:30 +0200
Jerome Brunet <jbrunet@baylibre.com> wrote:

> On Tue, 2017-06-20 at 13:54 +0200, Linus Walleij wrote:
> > On Tue, Jun 20, 2017 at 12:50 PM, Jerome Brunet <jbrunet@baylibre.com> wrote:  
> > > 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!
> >   
> > > 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...  
> 
> 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.

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).

> 
> 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/

^ permalink raw reply	[flat|nested] 102+ messages in thread

* Re: [PATCH v3 00/10] clk: implement clock rate protection mechanism
  2017-06-20 12:32         ` Jerome Brunet
@ 2017-06-20 15:29           ` Linus Walleij
  -1 siblings, 0 replies; 102+ messages in thread
From: Linus Walleij @ 2017-06-20 15:29 UTC (permalink / raw)
  To: Jerome Brunet
  Cc: Michael Turquette, Stephen Boyd, linux-clk, Kevin Hilman,
	open list:ARM/Amlogic Meson...,
	Russell King, Boris Brezillon, Adriana Reus

On Tue, Jun 20, 2017 at 2:32 PM, Jerome Brunet <jbrunet@baylibre.com> wrote:

> 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.

Acked-by: Linus Walleij <linus.walleij@linaro.org>

for the entire series.

Yours,
Linus Walleij

^ permalink raw reply	[flat|nested] 102+ messages in thread

* [PATCH v3 00/10] clk: implement clock rate protection mechanism
@ 2017-06-20 15:29           ` Linus Walleij
  0 siblings, 0 replies; 102+ messages in thread
From: Linus Walleij @ 2017-06-20 15:29 UTC (permalink / raw)
  To: linus-amlogic

On Tue, Jun 20, 2017 at 2:32 PM, Jerome Brunet <jbrunet@baylibre.com> wrote:

> 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.

Acked-by: Linus Walleij <linus.walleij@linaro.org>

for the entire series.

Yours,
Linus Walleij

^ permalink raw reply	[flat|nested] 102+ messages in thread

* Re: [PATCH v3 00/10] clk: implement clock rate protection mechanism
  2017-06-20 12:32         ` Jerome Brunet
@ 2017-06-21 13:15           ` Jerome Brunet
  -1 siblings, 0 replies; 102+ messages in thread
From: Jerome Brunet @ 2017-06-21 13:15 UTC (permalink / raw)
  To: Linus Walleij
  Cc: Michael Turquette, Stephen Boyd, linux-clk, Kevin Hilman,
	open list:ARM/Amlogic Meson...,
	Russell King, Boris Brezillon, Adriana Reus

On Tue, 2017-06-20 at 14:32 +0200, Jerome Brunet wrote:
> On Tue, 2017-06-20 at 13:54 +0200, Linus Walleij wrote:
> > On Tue, Jun 20, 2017 at 12:50 PM, Jerome Brunet <jbrunet@baylibre.com>
> > wrote:
> > > 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!
> > 
> > > 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...
> 
> 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.
> 

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.

> > 
> > Yours,
> > Linus Walleij
> 
> 

^ permalink raw reply	[flat|nested] 102+ messages in thread

* [PATCH v3 00/10] clk: implement clock rate protection mechanism
@ 2017-06-21 13:15           ` Jerome Brunet
  0 siblings, 0 replies; 102+ messages in thread
From: Jerome Brunet @ 2017-06-21 13:15 UTC (permalink / raw)
  To: linus-amlogic

On Tue, 2017-06-20 at 14:32 +0200, Jerome Brunet wrote:
> On Tue, 2017-06-20 at 13:54 +0200, Linus Walleij wrote:
> > On Tue, Jun 20, 2017 at 12:50 PM, Jerome Brunet <jbrunet@baylibre.com>
> > wrote:
> > > 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!
> > 
> > > 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...
> 
> 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.
> 

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.

> > 
> > Yours,
> > Linus Walleij
> 
> 

^ permalink raw reply	[flat|nested] 102+ messages in thread

* Re: [PATCH v3 00/10] clk: implement clock rate protection mechanism
  2017-06-20 12:47           ` Boris Brezillon
@ 2017-06-22  7:07             ` Quentin Schulz
  -1 siblings, 0 replies; 102+ messages in thread
From: Quentin Schulz @ 2017-06-22  7:07 UTC (permalink / raw)
  To: Boris Brezillon, Jerome Brunet
  Cc: Linus Walleij, Michael Turquette, Stephen Boyd, linux-clk,
	Kevin Hilman, open list:ARM/Amlogic Meson...,
	Russell King, Adriana Reus

Hi Jerome,

On 20/06/2017 14:47, Boris Brezillon wrote:
> +Quentin
> 
> On Tue, 20 Jun 2017 14:32:30 +0200
> Jerome Brunet <jbrunet@baylibre.com> wrote:
> 
>> On Tue, 2017-06-20 at 13:54 +0200, Linus Walleij wrote:
>>> On Tue, Jun 20, 2017 at 12:50 PM, Jerome Brunet <jbrunet@baylibre.com> wrote:  
>>>> 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!
>>>   
>>>> 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...  
>>
>> 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.
> 
> 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).
> 
>>
>> 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/
> 

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

Tested-by: Quentin Schulz <quentin.schulz@free-electrons.com>

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

-- 
Quentin Schulz, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com

^ permalink raw reply	[flat|nested] 102+ messages in thread

* [PATCH v3 00/10] clk: implement clock rate protection mechanism
@ 2017-06-22  7:07             ` Quentin Schulz
  0 siblings, 0 replies; 102+ messages in thread
From: Quentin Schulz @ 2017-06-22  7:07 UTC (permalink / raw)
  To: linus-amlogic

Hi Jerome,

On 20/06/2017 14:47, Boris Brezillon wrote:
> +Quentin
> 
> On Tue, 20 Jun 2017 14:32:30 +0200
> Jerome Brunet <jbrunet@baylibre.com> wrote:
> 
>> On Tue, 2017-06-20 at 13:54 +0200, Linus Walleij wrote:
>>> On Tue, Jun 20, 2017 at 12:50 PM, Jerome Brunet <jbrunet@baylibre.com> wrote:  
>>>> 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!
>>>   
>>>> 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...  
>>
>> 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.
> 
> 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).
> 
>>
>> 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/
> 

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

Tested-by: Quentin Schulz <quentin.schulz@free-electrons.com>

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

-- 
Quentin Schulz, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com

^ permalink raw reply	[flat|nested] 102+ messages in thread

* Re: [PATCH v3 00/10] clk: implement clock rate protection mechanism
  2017-06-22  7:07             ` Quentin Schulz
@ 2017-06-22 10:09               ` Jerome Brunet
  -1 siblings, 0 replies; 102+ messages in thread
From: Jerome Brunet @ 2017-06-22 10:09 UTC (permalink / raw)
  To: Quentin Schulz, Boris Brezillon
  Cc: Linus Walleij, Michael Turquette, Stephen Boyd, linux-clk,
	Kevin Hilman, open list:ARM/Amlogic Meson...,
	Russell King, Adriana Reus

On Thu, 2017-06-22 at 09:07 +0200, Quentin Schulz wrote:
> Hi Jerome,
> 
> On 20/06/2017 14:47, Boris Brezillon wrote:
> > +Quentin
> > 
> > On Tue, 20 Jun 2017 14:32:30 +0200
> > Jerome Brunet <jbrunet@baylibre.com> wrote:
> > 
> > > On Tue, 2017-06-20 at 13:54 +0200, Linus Walleij wrote:
> > > > On Tue, Jun 20, 2017 at 12:50 PM, Jerome Brunet <jbrunet@baylibre.com>
> > > > wrote:  
> > > > > 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!
> > > >   
> > > > > 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...  
> > > 
> > > 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.
> > 
> > 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).
> > 
> > > 
> > > 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/
> > 
> 
> I've tested the patch series and it seems good to me.
> 
> Tested-by: Quentin Schulz <quentin.schulz@free-electrons.com>

Thx a lot for taking the time to test this.

> 
> 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. 

> Thanks,
> Quentin
> 

^ permalink raw reply	[flat|nested] 102+ messages in thread

* [PATCH v3 00/10] clk: implement clock rate protection mechanism
@ 2017-06-22 10:09               ` Jerome Brunet
  0 siblings, 0 replies; 102+ messages in thread
From: Jerome Brunet @ 2017-06-22 10:09 UTC (permalink / raw)
  To: linus-amlogic

On Thu, 2017-06-22 at 09:07 +0200, Quentin Schulz wrote:
> Hi Jerome,
> 
> On 20/06/2017 14:47, Boris Brezillon wrote:
> > +Quentin
> > 
> > On Tue, 20 Jun 2017 14:32:30 +0200
> > Jerome Brunet <jbrunet@baylibre.com> wrote:
> > 
> > > On Tue, 2017-06-20 at 13:54 +0200, Linus Walleij wrote:
> > > > On Tue, Jun 20, 2017 at 12:50 PM, Jerome Brunet <jbrunet@baylibre.com>
> > > > wrote:??
> > > > > 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!
> > > > ??
> > > > > 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...??
> > > 
> > > 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.
> > 
> > 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).
> > 
> > > 
> > > 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/
> > 
> 
> I've tested the patch series and it seems good to me.
> 
> Tested-by: Quentin Schulz <quentin.schulz@free-electrons.com>

Thx a lot for taking the time to test this.

> 
> 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. 

> Thanks,
> Quentin
> 

^ permalink raw reply	[flat|nested] 102+ messages in thread

* Re: [PATCH v3 00/10] clk: implement clock rate protection mechanism
  2017-06-12 19:44 ` Jerome Brunet
@ 2017-07-11 21:04   ` Jerome Brunet
  -1 siblings, 0 replies; 102+ messages in thread
From: Jerome Brunet @ 2017-07-11 21:04 UTC (permalink / raw)
  To: Michael Turquette, Stephen Boyd, linux-clk
  Cc: Kevin Hilman, linux-amlogic, Russell King, Linus Walleij,
	Boris Brezillon, Adriana Reus

On Mon, 2017-06-12 at 21:44 +0200, Jerome Brunet wrote:
> 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@baylibre.com
> [1]: https://lkml.kernel.org/r/148942423440.82235.17188153691656009029@resonan
> ce
> [2]: https://lkml.kernel.org/r/20170521215958.19743-1-jbrunet@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


> 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(-)
> 

^ permalink raw reply	[flat|nested] 102+ messages in thread

* [PATCH v3 00/10] clk: implement clock rate protection mechanism
@ 2017-07-11 21:04   ` Jerome Brunet
  0 siblings, 0 replies; 102+ messages in thread
From: Jerome Brunet @ 2017-07-11 21:04 UTC (permalink / raw)
  To: linus-amlogic

On Mon, 2017-06-12 at 21:44 +0200, Jerome Brunet wrote:
> 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 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


> 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(-)
> 

^ permalink raw reply	[flat|nested] 102+ messages in thread

* Re: [PATCH v3 00/10] clk: implement clock rate protection mechanism
  2017-06-21 13:15           ` Jerome Brunet
@ 2017-07-12  1:16             ` Stephen Boyd
  -1 siblings, 0 replies; 102+ messages in thread
From: Stephen Boyd @ 2017-07-12  1:16 UTC (permalink / raw)
  To: Jerome Brunet
  Cc: Linus Walleij, Michael Turquette, linux-clk, Kevin Hilman,
	open list:ARM/Amlogic Meson...,
	Russell King, Boris Brezillon, Adriana Reus

On 06/21, Jerome Brunet wrote:
> 
> 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.
> 

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.

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

^ permalink raw reply	[flat|nested] 102+ messages in thread

* [PATCH v3 00/10] clk: implement clock rate protection mechanism
@ 2017-07-12  1:16             ` Stephen Boyd
  0 siblings, 0 replies; 102+ messages in thread
From: Stephen Boyd @ 2017-07-12  1:16 UTC (permalink / raw)
  To: linus-amlogic

On 06/21, Jerome Brunet wrote:
> 
> 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.
> 

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.

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

^ permalink raw reply	[flat|nested] 102+ messages in thread

* Re: [PATCH v3 01/10] clk: take the prepare lock out of clk_core_set_parent
  2017-06-12 19:44   ` Jerome Brunet
@ 2017-07-12  1:21     ` Stephen Boyd
  -1 siblings, 0 replies; 102+ messages in thread
From: Stephen Boyd @ 2017-07-12  1:21 UTC (permalink / raw)
  To: Jerome Brunet
  Cc: Michael Turquette, linux-clk, Kevin Hilman, linux-amlogic,
	Russell King, Linus Walleij, Boris Brezillon

On 06/12, Jerome Brunet wrote:
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> index fc58c52a26b4..f5c371532509 100644
> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> @@ -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();

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.

> -
>  	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.

> +		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;
>  	}

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

^ permalink raw reply	[flat|nested] 102+ messages in thread

* [PATCH v3 01/10] clk: take the prepare lock out of clk_core_set_parent
@ 2017-07-12  1:21     ` Stephen Boyd
  0 siblings, 0 replies; 102+ messages in thread
From: Stephen Boyd @ 2017-07-12  1:21 UTC (permalink / raw)
  To: linus-amlogic

On 06/12, Jerome Brunet wrote:
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> index fc58c52a26b4..f5c371532509 100644
> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> @@ -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();

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.

> -
>  	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.

> +		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;
>  	}

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

^ permalink raw reply	[flat|nested] 102+ messages in thread

* Re: [PATCH v3 02/10] clk: add clk_core_set_phase_nolock function
  2017-06-12 19:44   ` Jerome Brunet
@ 2017-07-12  1:22     ` Stephen Boyd
  -1 siblings, 0 replies; 102+ messages in thread
From: Stephen Boyd @ 2017-07-12  1:22 UTC (permalink / raw)
  To: Jerome Brunet
  Cc: Michael Turquette, linux-clk, Kevin Hilman, linux-amlogic,
	Russell King, Linus Walleij, Boris Brezillon

On 06/12, Jerome Brunet wrote:
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> index f5c371532509..dceaf0ff23db 100644
> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> @@ -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.

> +
> +	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

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

^ permalink raw reply	[flat|nested] 102+ messages in thread

* [PATCH v3 02/10] clk: add clk_core_set_phase_nolock function
@ 2017-07-12  1:22     ` Stephen Boyd
  0 siblings, 0 replies; 102+ messages in thread
From: Stephen Boyd @ 2017-07-12  1:22 UTC (permalink / raw)
  To: linus-amlogic

On 06/12, Jerome Brunet wrote:
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> index f5c371532509..dceaf0ff23db 100644
> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> @@ -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.

> +
> +	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

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

^ permalink raw reply	[flat|nested] 102+ messages in thread

* Re: [PATCH v3 03/10] clk: rework calls to round and determine rate callbacks
  2017-06-12 19:44   ` Jerome Brunet
@ 2017-07-12  1:49     ` Stephen Boyd
  -1 siblings, 0 replies; 102+ messages in thread
From: Stephen Boyd @ 2017-07-12  1:49 UTC (permalink / raw)
  To: Jerome Brunet
  Cc: Michael Turquette, linux-clk, Kevin Hilman, linux-amlogic,
	Russell King, Linus Walleij, Boris Brezillon

On 06/12, Jerome Brunet wrote:
> 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?

> 
> This rework is done to ease the integration of "protected" clock
> functionality.
> 
> Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
> ---
>  drivers/clk/clk.c | 78 +++++++++++++++++++++++++++++++------------------------
>  1 file changed, 44 insertions(+), 34 deletions(-)
> 
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> index dceaf0ff23db..8cc4672414be 100644
> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> @@ -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);

Best to leave this in place for clk_core_determine_round().

> +	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,

Can core be const?

> +				   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) {

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

>  		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;
> +

Nitpick: Kill this newline.

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

^ permalink raw reply	[flat|nested] 102+ messages in thread

* [PATCH v3 03/10] clk: rework calls to round and determine rate callbacks
@ 2017-07-12  1:49     ` Stephen Boyd
  0 siblings, 0 replies; 102+ messages in thread
From: Stephen Boyd @ 2017-07-12  1:49 UTC (permalink / raw)
  To: linus-amlogic

On 06/12, Jerome Brunet wrote:
> 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?

> 
> This rework is done to ease the integration of "protected" clock
> functionality.
> 
> Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
> ---
>  drivers/clk/clk.c | 78 +++++++++++++++++++++++++++++++------------------------
>  1 file changed, 44 insertions(+), 34 deletions(-)
> 
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> index dceaf0ff23db..8cc4672414be 100644
> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> @@ -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);

Best to leave this in place for clk_core_determine_round().

> +	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,

Can core be const?

> +				   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) {

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

>  		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;
> +

Nitpick: Kill this newline.

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

^ permalink raw reply	[flat|nested] 102+ messages in thread

* Re: [PATCH v3 04/10] clk: use round rate to bail out early in set_rate
  2017-06-12 19:44   ` Jerome Brunet
@ 2017-07-12  2:00     ` Stephen Boyd
  -1 siblings, 0 replies; 102+ messages in thread
From: Stephen Boyd @ 2017-07-12  2:00 UTC (permalink / raw)
  To: Jerome Brunet
  Cc: Michael Turquette, linux-clk, Kevin Hilman, linux-amlogic,
	Russell King, Linus Walleij, Boris Brezillon

On 06/12, Jerome Brunet wrote:
> The current implementation of clk_core_set_rate_nolock bails out early if

Add () to functions please.

> 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/

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

s/rate/the rate/

> 
> 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.

> 
> This is important to prepare the addition of the clock protection
> mechanism
> 
> Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
> ---
>  drivers/clk/clk.c | 23 +++++++++++++++++++++--
>  1 file changed, 21 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> index 8cc4672414be..163cb9832f10 100644
> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> @@ -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;

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

> +
> +	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?

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

^ permalink raw reply	[flat|nested] 102+ messages in thread

* [PATCH v3 04/10] clk: use round rate to bail out early in set_rate
@ 2017-07-12  2:00     ` Stephen Boyd
  0 siblings, 0 replies; 102+ messages in thread
From: Stephen Boyd @ 2017-07-12  2:00 UTC (permalink / raw)
  To: linus-amlogic

On 06/12, Jerome Brunet wrote:
> The current implementation of clk_core_set_rate_nolock bails out early if

Add () to functions please.

> 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/

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

s/rate/the rate/

> 
> 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.

> 
> This is important to prepare the addition of the clock protection
> mechanism
> 
> Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
> ---
>  drivers/clk/clk.c | 23 +++++++++++++++++++++--
>  1 file changed, 21 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> index 8cc4672414be..163cb9832f10 100644
> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> @@ -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;

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

> +
> +	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?

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

^ permalink raw reply	[flat|nested] 102+ messages in thread

* Re: [PATCH v3 07/10] clk: rollback set_rate_range changes on failure
  2017-06-12 19:44   ` Jerome Brunet
@ 2017-07-12  2:02     ` Stephen Boyd
  -1 siblings, 0 replies; 102+ messages in thread
From: Stephen Boyd @ 2017-07-12  2:02 UTC (permalink / raw)
  To: Jerome Brunet
  Cc: Michael Turquette, linux-clk, Kevin Hilman, linux-amlogic,
	Russell King, Linus Walleij, Boris Brezillon

On 06/12, Jerome Brunet wrote:
> Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>

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

> ---
>  drivers/clk/clk.c | 8 ++++++++
>  1 file changed, 8 insertions(+)
> 
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> index d91236e70a04..253f1d3f0971 100644
> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> @@ -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)

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

^ permalink raw reply	[flat|nested] 102+ messages in thread

* [PATCH v3 07/10] clk: rollback set_rate_range changes on failure
@ 2017-07-12  2:02     ` Stephen Boyd
  0 siblings, 0 replies; 102+ messages in thread
From: Stephen Boyd @ 2017-07-12  2:02 UTC (permalink / raw)
  To: linus-amlogic

On 06/12, Jerome Brunet wrote:
> Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>

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

> ---
>  drivers/clk/clk.c | 8 ++++++++
>  1 file changed, 8 insertions(+)
> 
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> index d91236e70a04..253f1d3f0971 100644
> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> @@ -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)

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

^ permalink raw reply	[flat|nested] 102+ messages in thread

* Re: [PATCH v3 08/10] clk: cosmetic changes to clk_summary debugfs entry
  2017-06-12 19:44   ` Jerome Brunet
@ 2017-07-12  2:02     ` Stephen Boyd
  -1 siblings, 0 replies; 102+ messages in thread
From: Stephen Boyd @ 2017-07-12  2:02 UTC (permalink / raw)
  To: Jerome Brunet
  Cc: Michael Turquette, linux-clk, Kevin Hilman, linux-amlogic,
	Russell King, Linus Walleij, Boris Brezillon

On 06/12, Jerome Brunet wrote:
> 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?

> Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
> ---

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

^ permalink raw reply	[flat|nested] 102+ messages in thread

* [PATCH v3 08/10] clk: cosmetic changes to clk_summary debugfs entry
@ 2017-07-12  2:02     ` Stephen Boyd
  0 siblings, 0 replies; 102+ messages in thread
From: Stephen Boyd @ 2017-07-12  2:02 UTC (permalink / raw)
  To: linus-amlogic

On 06/12, Jerome Brunet wrote:
> 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?

> Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
> ---

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

^ permalink raw reply	[flat|nested] 102+ messages in thread

* Re: [PATCH v3 09/10] clk: fix incorrect usage of ENOSYS
  2017-06-12 19:44   ` Jerome Brunet
@ 2017-07-12  2:03     ` Stephen Boyd
  -1 siblings, 0 replies; 102+ messages in thread
From: Stephen Boyd @ 2017-07-12  2:03 UTC (permalink / raw)
  To: Jerome Brunet
  Cc: Michael Turquette, linux-clk, Kevin Hilman, linux-amlogic,
	Russell King, Linus Walleij, Boris Brezillon

On 06/12, Jerome Brunet wrote:
> 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.
> 
> Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>

Could also go earlier in the series.

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

^ permalink raw reply	[flat|nested] 102+ messages in thread

* [PATCH v3 09/10] clk: fix incorrect usage of ENOSYS
@ 2017-07-12  2:03     ` Stephen Boyd
  0 siblings, 0 replies; 102+ messages in thread
From: Stephen Boyd @ 2017-07-12  2:03 UTC (permalink / raw)
  To: linus-amlogic

On 06/12, Jerome Brunet wrote:
> 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.
> 
> Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>

Could also go earlier in the series.

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

^ permalink raw reply	[flat|nested] 102+ messages in thread

* Re: [PATCH v3 05/10] clk: add support for clock protection
  2017-06-12 19:44   ` Jerome Brunet
@ 2017-07-26  0:12     ` Stephen Boyd
  -1 siblings, 0 replies; 102+ messages in thread
From: Stephen Boyd @ 2017-07-26  0:12 UTC (permalink / raw)
  To: Jerome Brunet
  Cc: Michael Turquette, linux-clk, Kevin Hilman, linux-amlogic,
	Russell King, Linus Walleij, Boris Brezillon

On 06/12, Jerome Brunet wrote:
> 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//

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


> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> index 163cb9832f10..d688b8f59a59 100644
> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> +
> +/**
> + * 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);

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.

> +	clk->protect_count--;
> +out:
> +	clk_prepare_unlock();
> +}
> +EXPORT_SYMBOL_GPL(clk_rate_unprotect);
[..]
> +
> @@ -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);

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.

> diff --git a/include/linux/clk.h b/include/linux/clk.h
> index 91bd464f4c9b..b60c36f2e6b0 100644
> --- a/include/linux/clk.h
> +++ b/include/linux/clk.h
> @@ -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);

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.

> +
> +/**
> + * 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

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

Please say clk_rate_protect() and clk_rate_unprotect() here.

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

^ permalink raw reply	[flat|nested] 102+ messages in thread

* [PATCH v3 05/10] clk: add support for clock protection
@ 2017-07-26  0:12     ` Stephen Boyd
  0 siblings, 0 replies; 102+ messages in thread
From: Stephen Boyd @ 2017-07-26  0:12 UTC (permalink / raw)
  To: linus-amlogic

On 06/12, Jerome Brunet wrote:
> 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//

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


> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> index 163cb9832f10..d688b8f59a59 100644
> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> +
> +/**
> + * 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);

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.

> +	clk->protect_count--;
> +out:
> +	clk_prepare_unlock();
> +}
> +EXPORT_SYMBOL_GPL(clk_rate_unprotect);
[..]
> +
> @@ -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);

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.

> diff --git a/include/linux/clk.h b/include/linux/clk.h
> index 91bd464f4c9b..b60c36f2e6b0 100644
> --- a/include/linux/clk.h
> +++ b/include/linux/clk.h
> @@ -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);

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.

> +
> +/**
> + * 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

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

Please say clk_rate_protect() and clk_rate_unprotect() here.

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

^ permalink raw reply	[flat|nested] 102+ messages in thread

* Re: [PATCH v3 06/10] clk: add clk_set_rate_protect
  2017-06-12 19:44   ` Jerome Brunet
@ 2017-07-26  0:59     ` Stephen Boyd
  -1 siblings, 0 replies; 102+ messages in thread
From: Stephen Boyd @ 2017-07-26  0:59 UTC (permalink / raw)
  To: Jerome Brunet
  Cc: Michael Turquette, linux-clk, Kevin Hilman, linux-amlogic,
	Russell King, Linus Walleij, Boris Brezillon

On 06/12, Jerome Brunet wrote:
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> index d688b8f59a59..d91236e70a04 100644
> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> @@ -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()/

> + * a critical section
> + *
> + * This can be used initially to ensure that at least 1 consumers is

s/consumers/consumer/

> + * statisfied when several protecting consummers are competing for the

s/consummers/consumers/

> + * 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,

s/in//

> +	 * so before the consumer code path protect the clock provider
> +	 */
> +
> +	ret = clk_core_set_rate_nolock(clk->core, rate);
> +

Drop newline please.

> +	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

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

^ permalink raw reply	[flat|nested] 102+ messages in thread

* [PATCH v3 06/10] clk: add clk_set_rate_protect
@ 2017-07-26  0:59     ` Stephen Boyd
  0 siblings, 0 replies; 102+ messages in thread
From: Stephen Boyd @ 2017-07-26  0:59 UTC (permalink / raw)
  To: linus-amlogic

On 06/12, Jerome Brunet wrote:
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> index d688b8f59a59..d91236e70a04 100644
> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> @@ -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()/

> + * a critical section
> + *
> + * This can be used initially to ensure that at least 1 consumers is

s/consumers/consumer/

> + * statisfied when several protecting consummers are competing for the

s/consummers/consumers/

> + * 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,

s/in//

> +	 * so before the consumer code path protect the clock provider
> +	 */
> +
> +	ret = clk_core_set_rate_nolock(clk->core, rate);
> +

Drop newline please.

> +	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

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

^ permalink raw reply	[flat|nested] 102+ messages in thread

* Re: [PATCH v3 00/10] clk: implement clock rate protection mechanism
  2017-07-12  1:16             ` Stephen Boyd
@ 2017-07-26 17:05               ` Jerome Brunet
  -1 siblings, 0 replies; 102+ messages in thread
From: Jerome Brunet @ 2017-07-26 17:05 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Linus Walleij, Michael Turquette, linux-clk, Kevin Hilman,
	open list:ARM/Amlogic Meson...,
	Russell King, Boris Brezillon, Adriana Reus

On Tue, 2017-07-11 at 18:16 -0700, Stephen Boyd wrote:
> On 06/21, Jerome Brunet wrote:
> > 
> > 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.
> > 
> 
> 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 ;)

> 
> 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.
> 

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.

^ permalink raw reply	[flat|nested] 102+ messages in thread

* [PATCH v3 00/10] clk: implement clock rate protection mechanism
@ 2017-07-26 17:05               ` Jerome Brunet
  0 siblings, 0 replies; 102+ messages in thread
From: Jerome Brunet @ 2017-07-26 17:05 UTC (permalink / raw)
  To: linus-amlogic

On Tue, 2017-07-11 at 18:16 -0700, Stephen Boyd wrote:
> On 06/21, Jerome Brunet wrote:
> > 
> > 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.
> > 
> 
> 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 ;)

> 
> 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.
> 

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.

^ permalink raw reply	[flat|nested] 102+ messages in thread

* Re: [PATCH v3 04/10] clk: use round rate to bail out early in set_rate
  2017-07-12  2:00     ` Stephen Boyd
@ 2017-07-26 17:13       ` Jerome Brunet
  -1 siblings, 0 replies; 102+ messages in thread
From: Jerome Brunet @ 2017-07-26 17:13 UTC (permalink / raw)
  To: Stephen Boyd, Peter De Schrijver
  Cc: Michael Turquette, linux-clk, Kevin Hilman, linux-amlogic,
	Russell King, Linus Walleij, Boris Brezillon

On Tue, 2017-07-11 at 19:00 -0700, Stephen Boyd wrote:
> On 06/12, Jerome Brunet wrote:
> > The current implementation of clk_core_set_rate_nolock bails out early if
> 
> Add () to functions please.
> 
> > 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/
> 
> > rate is not exactly what is requested, which is fairly common with PLLs.
> 
> s/rate/the rate/
> 
> > 
> > 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.

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@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

> 
> > 
> > This is important to prepare the addition of the clock protection
> > mechanism
> > 
> > Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
> > ---
> >  drivers/clk/clk.c | 23 +++++++++++++++++++++--
> >  1 file changed, 21 insertions(+), 2 deletions(-)
> > 
> > diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> > index 8cc4672414be..163cb9832f10 100644
> > --- a/drivers/clk/clk.c
> > +++ b/drivers/clk/clk.c
> > @@ -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;
> 
> 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 ?

> > +
> > +	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. 


> 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 

> 

^ permalink raw reply	[flat|nested] 102+ messages in thread

* [PATCH v3 04/10] clk: use round rate to bail out early in set_rate
@ 2017-07-26 17:13       ` Jerome Brunet
  0 siblings, 0 replies; 102+ messages in thread
From: Jerome Brunet @ 2017-07-26 17:13 UTC (permalink / raw)
  To: linus-amlogic

On Tue, 2017-07-11 at 19:00 -0700, Stephen Boyd wrote:
> On 06/12, Jerome Brunet wrote:
> > The current implementation of clk_core_set_rate_nolock bails out early if
> 
> Add () to functions please.
> 
> > 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/
> 
> > rate is not exactly what is requested, which is fairly common with PLLs.
> 
> s/rate/the rate/
> 
> > 
> > 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.

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

> 
> > 
> > This is important to prepare the addition of the clock protection
> > mechanism
> > 
> > Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
> > ---
> > ?drivers/clk/clk.c | 23 +++++++++++++++++++++--
> > ?1 file changed, 21 insertions(+), 2 deletions(-)
> > 
> > diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> > index 8cc4672414be..163cb9832f10 100644
> > --- a/drivers/clk/clk.c
> > +++ b/drivers/clk/clk.c
> > @@ -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;
> 
> 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 ?

> > +
> > +	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.?


> 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 

> 

^ permalink raw reply	[flat|nested] 102+ messages in thread

* Re: [PATCH v3 05/10] clk: add support for clock protection
  2017-07-26  0:12     ` Stephen Boyd
@ 2017-07-26 17:18       ` Jerome Brunet
  -1 siblings, 0 replies; 102+ messages in thread
From: Jerome Brunet @ 2017-07-26 17:18 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Michael Turquette, linux-clk, Kevin Hilman, linux-amlogic,
	Russell King, Linus Walleij, Boris Brezillon

On Tue, 2017-07-25 at 17:12 -0700, Stephen Boyd wrote:
> On 06/12, Jerome Brunet wrote:
> > 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//
> 
> > changing the rate or introducing glitches while the clock is protected.
> 
> 
> > diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> > index 163cb9832f10..d688b8f59a59 100644
> > --- a/drivers/clk/clk.c
> > +++ b/drivers/clk/clk.c
> > +
> > +/**
> > + * 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);
> 
> 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.

> 
> > +	clk->protect_count--;
> > +out:
> > +	clk_prepare_unlock();
> > +}
> > +EXPORT_SYMBOL_GPL(clk_rate_unprotect);
> 
> [..]
> > +
> > @@ -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);
> 
> Does this do anything different than:
> 
> 	clk->core->protect_count -= clk->protect_count;
> 	clk->protect_count = 1;

this looks really hacky !

> 	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.

> 
> > diff --git a/include/linux/clk.h b/include/linux/clk.h
> > index 91bd464f4c9b..b60c36f2e6b0 100644
> > --- a/include/linux/clk.h
> > +++ b/include/linux/clk.h
> > @@ -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);
> 
> 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@baylibre.co
[1]: https://github.com/jeromebrunet/linux/commits/amlogic/wip/audio-clk-lock

> 
> 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.

> 
> 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

> > +
> > +/**
> > + * 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
> 
> > + *
> > + * The caller must balance the number of rate_protect and rate_unprotect
> > calls.
> 
> Please say clk_rate_protect() and clk_rate_unprotect() here.
> 

^ permalink raw reply	[flat|nested] 102+ messages in thread

* [PATCH v3 05/10] clk: add support for clock protection
@ 2017-07-26 17:18       ` Jerome Brunet
  0 siblings, 0 replies; 102+ messages in thread
From: Jerome Brunet @ 2017-07-26 17:18 UTC (permalink / raw)
  To: linus-amlogic

On Tue, 2017-07-25 at 17:12 -0700, Stephen Boyd wrote:
> On 06/12, Jerome Brunet wrote:
> > 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//
> 
> > changing the rate or introducing glitches while the clock is protected.
> 
> 
> > diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> > index 163cb9832f10..d688b8f59a59 100644
> > --- a/drivers/clk/clk.c
> > +++ b/drivers/clk/clk.c
> > +
> > +/**
> > + * 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);
> 
> 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.

> 
> > +	clk->protect_count--;
> > +out:
> > +	clk_prepare_unlock();
> > +}
> > +EXPORT_SYMBOL_GPL(clk_rate_unprotect);
> 
> [..]
> > +
> > @@ -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);
> 
> Does this do anything different than:
> 
> 	clk->core->protect_count -= clk->protect_count;
> 	clk->protect_count = 1;

this looks really hacky !

> 	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.

> 
> > diff --git a/include/linux/clk.h b/include/linux/clk.h
> > index 91bd464f4c9b..b60c36f2e6b0 100644
> > --- a/include/linux/clk.h
> > +++ b/include/linux/clk.h
> > @@ -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);
> 
> 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

> 
> 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.

> 
> 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

> > +
> > +/**
> > + * 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
> 
> > + *
> > + * The caller must balance the number of rate_protect and rate_unprotect
> > calls.
> 
> Please say clk_rate_protect() and clk_rate_unprotect() here.
> 

^ permalink raw reply	[flat|nested] 102+ messages in thread

* Re: [PATCH v3 07/10] clk: rollback set_rate_range changes on failure
  2017-07-12  2:02     ` Stephen Boyd
@ 2017-07-26 17:22       ` Jerome Brunet
  -1 siblings, 0 replies; 102+ messages in thread
From: Jerome Brunet @ 2017-07-26 17:22 UTC (permalink / raw)
  To: Stephen Boyd, Peter De Schrijver
  Cc: Michael Turquette, linux-clk, Kevin Hilman, linux-amlogic,
	Russell King, Linus Walleij, Boris Brezillon

On Tue, 2017-07-11 at 19:02 -0700, Stephen Boyd wrote:
> On 06/12, Jerome Brunet wrote:
> > Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
> 
> 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


> 
> > ---
> >  drivers/clk/clk.c | 8 ++++++++
> >  1 file changed, 8 insertions(+)
> > 
> > diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> > index d91236e70a04..253f1d3f0971 100644
> > --- a/drivers/clk/clk.c
> > +++ b/drivers/clk/clk.c
> > @@ -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)
> 
> 

^ permalink raw reply	[flat|nested] 102+ messages in thread

* [PATCH v3 07/10] clk: rollback set_rate_range changes on failure
@ 2017-07-26 17:22       ` Jerome Brunet
  0 siblings, 0 replies; 102+ messages in thread
From: Jerome Brunet @ 2017-07-26 17:22 UTC (permalink / raw)
  To: linus-amlogic

On Tue, 2017-07-11 at 19:02 -0700, Stephen Boyd wrote:
> On 06/12, Jerome Brunet wrote:
> > Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
> 
> 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


> 
> > ---
> > ?drivers/clk/clk.c | 8 ++++++++
> > ?1 file changed, 8 insertions(+)
> > 
> > diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> > index d91236e70a04..253f1d3f0971 100644
> > --- a/drivers/clk/clk.c
> > +++ b/drivers/clk/clk.c
> > @@ -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)
> 
> 

^ permalink raw reply	[flat|nested] 102+ messages in thread

* Re: [PATCH v3 00/10] clk: implement clock rate protection mechanism
  2017-07-26 17:05               ` Jerome Brunet
@ 2017-07-27 22:44                 ` Stephen Boyd
  -1 siblings, 0 replies; 102+ messages in thread
From: Stephen Boyd @ 2017-07-27 22:44 UTC (permalink / raw)
  To: Jerome Brunet
  Cc: Linus Walleij, Michael Turquette, linux-clk, Kevin Hilman,
	open list:ARM/Amlogic Meson...,
	Russell King, Boris Brezillon, Adriana Reus

On 07/26, Jerome Brunet wrote:
> On Tue, 2017-07-11 at 18:16 -0700, Stephen Boyd wrote:
> > On 06/21, Jerome Brunet wrote:
> > > 
> > > 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.
> > > 
> > 
> > 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.

> 
> > 
> > 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.
> > 
> 
> 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.

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

^ permalink raw reply	[flat|nested] 102+ messages in thread

* [PATCH v3 00/10] clk: implement clock rate protection mechanism
@ 2017-07-27 22:44                 ` Stephen Boyd
  0 siblings, 0 replies; 102+ messages in thread
From: Stephen Boyd @ 2017-07-27 22:44 UTC (permalink / raw)
  To: linus-amlogic

On 07/26, Jerome Brunet wrote:
> On Tue, 2017-07-11 at 18:16 -0700, Stephen Boyd wrote:
> > On 06/21, Jerome Brunet wrote:
> > > 
> > > 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.
> > > 
> > 
> > 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.

> 
> > 
> > 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.
> > 
> 
> 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.

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

^ permalink raw reply	[flat|nested] 102+ messages in thread

* Re: [PATCH v3 05/10] clk: add support for clock protection
  2017-07-26 17:18       ` Jerome Brunet
@ 2017-08-04  0:18         ` Stephen Boyd
  -1 siblings, 0 replies; 102+ messages in thread
From: Stephen Boyd @ 2017-08-04  0:18 UTC (permalink / raw)
  To: Jerome Brunet
  Cc: Michael Turquette, linux-clk, Kevin Hilman, linux-amlogic,
	Russell King, Linus Walleij, Boris Brezillon

On 07/26, Jerome Brunet wrote:
> On Tue, 2017-07-25 at 17:12 -0700, Stephen Boyd wrote:
> > On 06/12, Jerome Brunet wrote:
> > > +	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 ?
> 
> 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.

> 
> 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.

> 
> > 
> > > +	clk->protect_count--;
> > > +out:
> > > +	clk_prepare_unlock();
> > > +}
> > > +EXPORT_SYMBOL_GPL(clk_rate_unprotect);
> > 
> > [..]
> > > +
> > > @@ -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);
> > 
> > Does this do anything different than:
> > 
> > 	clk->core->protect_count -= clk->protect_count;
> > 	clk->protect_count = 1;
> 
> this looks really hacky !
> 
> > 	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.

> 
> > 
> > > diff --git a/include/linux/clk.h b/include/linux/clk.h
> > > index 91bd464f4c9b..b60c36f2e6b0 100644
> > > --- a/include/linux/clk.h
> > > +++ b/include/linux/clk.h
> > > @@ -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);
> > 
> > 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@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.

> 
> > 
> > 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.

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.

> 
> 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.

> 
> 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?

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

^ permalink raw reply	[flat|nested] 102+ messages in thread

* [PATCH v3 05/10] clk: add support for clock protection
@ 2017-08-04  0:18         ` Stephen Boyd
  0 siblings, 0 replies; 102+ messages in thread
From: Stephen Boyd @ 2017-08-04  0:18 UTC (permalink / raw)
  To: linus-amlogic

On 07/26, Jerome Brunet wrote:
> On Tue, 2017-07-25 at 17:12 -0700, Stephen Boyd wrote:
> > On 06/12, Jerome Brunet wrote:
> > > +	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 ?
> 
> 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.

> 
> 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.

> 
> > 
> > > +	clk->protect_count--;
> > > +out:
> > > +	clk_prepare_unlock();
> > > +}
> > > +EXPORT_SYMBOL_GPL(clk_rate_unprotect);
> > 
> > [..]
> > > +
> > > @@ -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);
> > 
> > Does this do anything different than:
> > 
> > 	clk->core->protect_count -= clk->protect_count;
> > 	clk->protect_count = 1;
> 
> this looks really hacky !
> 
> > 	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.

> 
> > 
> > > diff --git a/include/linux/clk.h b/include/linux/clk.h
> > > index 91bd464f4c9b..b60c36f2e6b0 100644
> > > --- a/include/linux/clk.h
> > > +++ b/include/linux/clk.h
> > > @@ -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);
> > 
> > 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.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.

> 
> > 
> > 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.

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.

> 
> 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.

> 
> 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?

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

^ permalink raw reply	[flat|nested] 102+ messages in thread

* Re: [PATCH v3 04/10] clk: use round rate to bail out early in set_rate
  2017-07-26 17:13       ` Jerome Brunet
@ 2017-08-04  0:32         ` Stephen Boyd
  -1 siblings, 0 replies; 102+ messages in thread
From: Stephen Boyd @ 2017-08-04  0:32 UTC (permalink / raw)
  To: Jerome Brunet
  Cc: Peter De Schrijver, Michael Turquette, linux-clk, Kevin Hilman,
	linux-amlogic, Russell King, Linus Walleij, Boris Brezillon

On 07/26, Jerome Brunet wrote:
> On Tue, 2017-07-11 at 19:00 -0700, Stephen Boyd wrote:
> > On 06/12, Jerome Brunet wrote:
> > 
> > > 
> > > 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.
> 
> 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@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.

> 
> 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.

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.

> 
> 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.

> 
> [0]: https://github.com/jeromebrunet/linux/commit/235e477f346a9e8d115dda257f9f73
> 834151bd7f
> 
> > 
> > > 
> > > This is important to prepare the addition of the clock protection
> > > mechanism
> > > 
> > > Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
> > > ---
> > >  drivers/clk/clk.c | 23 +++++++++++++++++++++--
> > >  1 file changed, 21 insertions(+), 2 deletions(-)
> > > 
> > > diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> > > index 8cc4672414be..163cb9832f10 100644
> > > --- a/drivers/clk/clk.c
> > > +++ b/drivers/clk/clk.c
> > > @@ -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;
> > 
> > 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 ?

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

> 
> > > +
> > > +	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. 
> 
> 
> > 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 
> 
> > 
> 

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.

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

^ permalink raw reply	[flat|nested] 102+ messages in thread

* [PATCH v3 04/10] clk: use round rate to bail out early in set_rate
@ 2017-08-04  0:32         ` Stephen Boyd
  0 siblings, 0 replies; 102+ messages in thread
From: Stephen Boyd @ 2017-08-04  0:32 UTC (permalink / raw)
  To: linus-amlogic

On 07/26, Jerome Brunet wrote:
> On Tue, 2017-07-11 at 19:00 -0700, Stephen Boyd wrote:
> > On 06/12, Jerome Brunet wrote:
> > 
> > > 
> > > 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.
> 
> 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.

> 
> 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.

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.

> 
> 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.

> 
> [0]: https://github.com/jeromebrunet/linux/commit/235e477f346a9e8d115dda257f9f73
> 834151bd7f
> 
> > 
> > > 
> > > This is important to prepare the addition of the clock protection
> > > mechanism
> > > 
> > > Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
> > > ---
> > > ?drivers/clk/clk.c | 23 +++++++++++++++++++++--
> > > ?1 file changed, 21 insertions(+), 2 deletions(-)
> > > 
> > > diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> > > index 8cc4672414be..163cb9832f10 100644
> > > --- a/drivers/clk/clk.c
> > > +++ b/drivers/clk/clk.c
> > > @@ -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;
> > 
> > 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 ?

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

> 
> > > +
> > > +	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.?
> 
> 
> > 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 
> 
> > 
> 

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.

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

^ permalink raw reply	[flat|nested] 102+ messages in thread

* Re: [PATCH v3 05/10] clk: add support for clock protection
  2017-08-04  0:18         ` Stephen Boyd
@ 2017-08-08 22:37           ` Michael Turquette
  -1 siblings, 0 replies; 102+ messages in thread
From: Michael Turquette @ 2017-08-08 22:37 UTC (permalink / raw)
  To: Stephen Boyd, Jerome Brunet
  Cc: linux-clk, Kevin Hilman, linux-amlogic, Russell King,
	Linus Walleij, Boris Brezillon

Hi Stephen,

Quoting Stephen Boyd (2017-08-03 17:18:36)
> On 07/26, Jerome Brunet wrote:
> > > > +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 R=
FC [0]
> > Here is an example (wip) of usage [1]
> > =

> > [0]: http://lkml.kernel.org/r/20170302173835.18313-1-jbrunet@baylibre.c=
om
> > [1]: https://github.com/jeromebrunet/linux/commits/amlogic/wip/audio-cl=
k-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.

> =

> 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.

> =

> > =

> > > =

> > > 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.
> =

> 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.

> =

> > =

> > 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 someth=
ing
> > 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,

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.

> 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.

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.

> =

> > =

> > Last but not least, it allows consumer to set the rate in a sort of cri=
tical
> > section and have the guarantee that nobody will be able to change the r=
ate
> > 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

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

> 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

> =

> -- =

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

^ permalink raw reply	[flat|nested] 102+ messages in thread

* [PATCH v3 05/10] clk: add support for clock protection
@ 2017-08-08 22:37           ` Michael Turquette
  0 siblings, 0 replies; 102+ messages in thread
From: Michael Turquette @ 2017-08-08 22:37 UTC (permalink / raw)
  To: linus-amlogic

Hi Stephen,

Quoting Stephen Boyd (2017-08-03 17:18:36)
> On 07/26, Jerome Brunet wrote:
> > > > +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.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.

> 
> 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.

> 
> > 
> > > 
> > > 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.
> 
> 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.

> 
> > 
> > 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,

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.

> 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.

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.

> 
> > 
> > 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

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

> 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

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

^ permalink raw reply	[flat|nested] 102+ messages in thread

* Re: [PATCH v3 00/10] clk: implement clock rate protection mechanism
  2017-07-27 22:44                 ` Stephen Boyd
@ 2017-08-08 22:40                   ` Michael Turquette
  -1 siblings, 0 replies; 102+ messages in thread
From: Michael Turquette @ 2017-08-08 22:40 UTC (permalink / raw)
  To: Stephen Boyd, Jerome Brunet
  Cc: Linus Walleij, linux-clk, Kevin Hilman,
	open list:ARM/Amlogic Meson...,
	Russell King, Boris Brezillon, Adriana Reus

Quoting Stephen Boyd (2017-07-27 15:44:59)
> On 07/26, Jerome Brunet wrote:
> > In the following mail, I've only replied where I wanted to discuss a bi=
t more.
> > For everything else, please consider the comments agreed and the modifi=
cations
> > 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

> =

> -- =

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

^ permalink raw reply	[flat|nested] 102+ messages in thread

* [PATCH v3 00/10] clk: implement clock rate protection mechanism
@ 2017-08-08 22:40                   ` Michael Turquette
  0 siblings, 0 replies; 102+ messages in thread
From: Michael Turquette @ 2017-08-08 22:40 UTC (permalink / raw)
  To: linus-amlogic

Quoting Stephen Boyd (2017-07-27 15:44:59)
> On 07/26, Jerome Brunet wrote:
> > 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

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

^ permalink raw reply	[flat|nested] 102+ messages in thread

* Re: [PATCH v3 05/10] clk: add support for clock protection
  2017-08-08 22:37           ` Michael Turquette
@ 2017-08-09  2:19             ` Stephen Boyd
  -1 siblings, 0 replies; 102+ messages in thread
From: Stephen Boyd @ 2017-08-09  2:19 UTC (permalink / raw)
  To: Michael Turquette
  Cc: Jerome Brunet, linux-clk, Kevin Hilman, linux-amlogic,
	Russell King, Linus Walleij, Boris Brezillon

On 08/08, Michael Turquette wrote:
> Hi Stephen,
> 
> Quoting Stephen Boyd (2017-08-03 17:18:36)
> > On 07/26, Jerome Brunet wrote:
> > > > > +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@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.

> 
> > 
> > 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."

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.

> 
> 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.

> 
> > 
> > > 
> > > 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,
> 
> 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.
> 
> > 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.
> 
> 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.

> 
> > 
> > > 
> > > 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
> 
> Right, clk_set_rate_protect does this in the next patch in this series.
> 
> > 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.
> 

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.

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

^ permalink raw reply	[flat|nested] 102+ messages in thread

* [PATCH v3 05/10] clk: add support for clock protection
@ 2017-08-09  2:19             ` Stephen Boyd
  0 siblings, 0 replies; 102+ messages in thread
From: Stephen Boyd @ 2017-08-09  2:19 UTC (permalink / raw)
  To: linus-amlogic

On 08/08, Michael Turquette wrote:
> Hi Stephen,
> 
> Quoting Stephen Boyd (2017-08-03 17:18:36)
> > On 07/26, Jerome Brunet wrote:
> > > > > +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.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.

> 
> > 
> > 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."

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.

> 
> 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.

> 
> > 
> > > 
> > > 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,
> 
> 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.
> 
> > 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.
> 
> 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.

> 
> > 
> > > 
> > > 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
> 
> Right, clk_set_rate_protect does this in the next patch in this series.
> 
> > 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.
> 

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.

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

^ permalink raw reply	[flat|nested] 102+ messages in thread

* Re: [PATCH v3 05/10] clk: add support for clock protection
  2017-08-09  2:19             ` Stephen Boyd
@ 2017-08-09 11:45               ` Russell King - ARM Linux
  -1 siblings, 0 replies; 102+ messages in thread
From: Russell King - ARM Linux @ 2017-08-09 11:45 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Michael Turquette, Jerome Brunet, linux-clk, Kevin Hilman,
	linux-amlogic, Linus Walleij, Boris Brezillon

On Tue, Aug 08, 2017 at 07:19:06PM -0700, Stephen Boyd wrote:
> 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.

-- 
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

^ permalink raw reply	[flat|nested] 102+ messages in thread

* [PATCH v3 05/10] clk: add support for clock protection
@ 2017-08-09 11:45               ` Russell King - ARM Linux
  0 siblings, 0 replies; 102+ messages in thread
From: Russell King - ARM Linux @ 2017-08-09 11:45 UTC (permalink / raw)
  To: linus-amlogic

On Tue, Aug 08, 2017 at 07:19:06PM -0700, Stephen Boyd wrote:
> 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.

-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line in suburbia: sync@8.8Mbps down 630kbps up
According to speedtest.net: 8.21Mbps down 510kbps up

^ permalink raw reply	[flat|nested] 102+ messages in thread

* Re: [PATCH v3 00/10] clk: implement clock rate protection mechanism
  2017-08-08 22:40                   ` Michael Turquette
@ 2017-08-09 12:14                     ` Jerome Brunet
  -1 siblings, 0 replies; 102+ messages in thread
From: Jerome Brunet @ 2017-08-09 12:14 UTC (permalink / raw)
  To: Michael Turquette, Stephen Boyd
  Cc: Linus Walleij, linux-clk, Kevin Hilman,
	open list:ARM/Amlogic Meson...,
	Russell King, Boris Brezillon, Adriana Reus

On Tue, 2017-08-08 at 15:40 -0700, Michael Turquette wrote:
> Quoting Stephen Boyd (2017-07-27 15:44:59)
> > On 07/26, Jerome Brunet wrote:
> > > 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?

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 

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

^ permalink raw reply	[flat|nested] 102+ messages in thread

* [PATCH v3 00/10] clk: implement clock rate protection mechanism
@ 2017-08-09 12:14                     ` Jerome Brunet
  0 siblings, 0 replies; 102+ messages in thread
From: Jerome Brunet @ 2017-08-09 12:14 UTC (permalink / raw)
  To: linus-amlogic

On Tue, 2017-08-08 at 15:40 -0700, Michael Turquette wrote:
> Quoting Stephen Boyd (2017-07-27 15:44:59)
> > On 07/26, Jerome Brunet wrote:
> > > 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?

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 

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

^ permalink raw reply	[flat|nested] 102+ messages in thread

* Re: [PATCH v3 05/10] clk: add support for clock protection
  2017-08-08 22:37           ` Michael Turquette
@ 2017-08-09 12:18             ` Jerome Brunet
  -1 siblings, 0 replies; 102+ messages in thread
From: Jerome Brunet @ 2017-08-09 12:18 UTC (permalink / raw)
  To: Michael Turquette, Stephen Boyd
  Cc: linux-clk, Kevin Hilman, linux-amlogic, Russell King,
	Linus Walleij, Boris Brezillon

On Tue, 2017-08-08 at 15:37 -0700, Michael Turquette wrote:
> Hi Stephen,
> 
> Quoting Stephen Boyd (2017-08-03 17:18:36)
> > On 07/26, Jerome Brunet wrote:
> > > > > +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@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.
> 
> > 
> > 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.
> 
> > 
> > > 
> > > > 
> > > > 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.
> > 
> > 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.
> 
> > 
> > > 
> > > 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,
> 
> 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.
> 
> > 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.
> 
> 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.

> 
> > 
> > > 
> > > 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
> 
> 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.

> 
> > 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
> 
> > 
> > -- 
> > Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
> > a Linux Foundation Collaborative Project

^ permalink raw reply	[flat|nested] 102+ messages in thread

* [PATCH v3 05/10] clk: add support for clock protection
@ 2017-08-09 12:18             ` Jerome Brunet
  0 siblings, 0 replies; 102+ messages in thread
From: Jerome Brunet @ 2017-08-09 12:18 UTC (permalink / raw)
  To: linus-amlogic

On Tue, 2017-08-08 at 15:37 -0700, Michael Turquette wrote:
> Hi Stephen,
> 
> Quoting Stephen Boyd (2017-08-03 17:18:36)
> > On 07/26, Jerome Brunet wrote:
> > > > > +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.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.
> 
> > 
> > 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.
> 
> > 
> > > 
> > > > 
> > > > 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.
> > 
> > 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.
> 
> > 
> > > 
> > > 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,
> 
> 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.
> 
> > 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.
> 
> 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.

> 
> > 
> > > 
> > > 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
> 
> 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.

> 
> > 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
> 
> > 
> > --?
> > Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
> > a Linux Foundation Collaborative Project

^ permalink raw reply	[flat|nested] 102+ messages in thread

* Re: [PATCH v3 05/10] clk: add support for clock protection
  2017-08-09  2:19             ` Stephen Boyd
@ 2017-08-09 13:07               ` Jerome Brunet
  -1 siblings, 0 replies; 102+ messages in thread
From: Jerome Brunet @ 2017-08-09 13:07 UTC (permalink / raw)
  To: Stephen Boyd, Michael Turquette
  Cc: linux-clk, Kevin Hilman, linux-amlogic, Russell King,
	Linus Walleij, Boris Brezillon

On Tue, 2017-08-08 at 19:19 -0700, Stephen Boyd wrote:
> On 08/08, Michael Turquette wrote:
> > Hi Stephen,
> > 
> > Quoting Stephen Boyd (2017-08-03 17:18:36)
> > > On 07/26, Jerome Brunet wrote:
> > > > > > +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@baylibre.co
> > > > m
> > > > [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.
> 
> > 
> > > 
> > > 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."
> 
> 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.

> 
> > 
> > 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.
> 
> > 
> > > 
> > > > 
> > > > 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,
> > 
> > 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.
> > 
> > > 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.
> > 
> > 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.

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.

> 
> > 
> > > 
> > > > 
> > > > 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
> > 
> > Right, clk_set_rate_protect does this in the next patch in this series.
> > 
> > > 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.
> > 
> 
> 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.

> 

^ permalink raw reply	[flat|nested] 102+ messages in thread

* [PATCH v3 05/10] clk: add support for clock protection
@ 2017-08-09 13:07               ` Jerome Brunet
  0 siblings, 0 replies; 102+ messages in thread
From: Jerome Brunet @ 2017-08-09 13:07 UTC (permalink / raw)
  To: linus-amlogic

On Tue, 2017-08-08 at 19:19 -0700, Stephen Boyd wrote:
> On 08/08, Michael Turquette wrote:
> > Hi Stephen,
> > 
> > Quoting Stephen Boyd (2017-08-03 17:18:36)
> > > On 07/26, Jerome Brunet wrote:
> > > > > > +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
> > > > m
> > > > [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.
> 
> > 
> > > 
> > > 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."
> 
> 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.

> 
> > 
> > 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.
> 
> > 
> > > 
> > > > 
> > > > 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,
> > 
> > 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.
> > 
> > > 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.
> > 
> > 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.

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.

> 
> > 
> > > 
> > > > 
> > > > 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
> > 
> > Right, clk_set_rate_protect does this in the next patch in this series.
> > 
> > > 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.
> > 
> 
> 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.

> 

^ permalink raw reply	[flat|nested] 102+ messages in thread

* Re: [PATCH v3 05/10] clk: add support for clock protection
  2017-08-09 11:45               ` Russell King - ARM Linux
@ 2017-08-09 13:34                 ` Jerome Brunet
  -1 siblings, 0 replies; 102+ messages in thread
From: Jerome Brunet @ 2017-08-09 13:34 UTC (permalink / raw)
  To: Russell King - ARM Linux, Stephen Boyd
  Cc: Michael Turquette, linux-clk, Kevin Hilman, linux-amlogic,
	Linus Walleij, Boris Brezillon

On Wed, 2017-08-09 at 12:45 +0100, Russell King - ARM Linux wrote:
> On Tue, Aug 08, 2017 at 07:19:06PM -0700, Stephen Boyd wrote:
> > 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;

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.

> 
> 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.
> 

^ permalink raw reply	[flat|nested] 102+ messages in thread

* [PATCH v3 05/10] clk: add support for clock protection
@ 2017-08-09 13:34                 ` Jerome Brunet
  0 siblings, 0 replies; 102+ messages in thread
From: Jerome Brunet @ 2017-08-09 13:34 UTC (permalink / raw)
  To: linus-amlogic

On Wed, 2017-08-09 at 12:45 +0100, Russell King - ARM Linux wrote:
> On Tue, Aug 08, 2017 at 07:19:06PM -0700, Stephen Boyd wrote:
> > 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;

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.

> 
> 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.
> 

^ permalink raw reply	[flat|nested] 102+ messages in thread

* Re: [PATCH v3 05/10] clk: add support for clock protection
  2017-08-09 13:34                 ` Jerome Brunet
@ 2017-08-09 13:40                   ` Russell King - ARM Linux
  -1 siblings, 0 replies; 102+ messages in thread
From: Russell King - ARM Linux @ 2017-08-09 13:40 UTC (permalink / raw)
  To: Jerome Brunet
  Cc: Stephen Boyd, Michael Turquette, linux-clk, Kevin Hilman,
	linux-amlogic, Linus Walleij, Boris Brezillon

On Wed, Aug 09, 2017 at 03:34:48PM +0200, Jerome Brunet wrote:
> On Wed, 2017-08-09 at 12:45 +0100, Russell King - ARM Linux wrote:
> > On Tue, Aug 08, 2017 at 07:19:06PM -0700, Stephen Boyd wrote:
> > > 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;
> 
> 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);

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.

-- 
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

^ permalink raw reply	[flat|nested] 102+ messages in thread

* [PATCH v3 05/10] clk: add support for clock protection
@ 2017-08-09 13:40                   ` Russell King - ARM Linux
  0 siblings, 0 replies; 102+ messages in thread
From: Russell King - ARM Linux @ 2017-08-09 13:40 UTC (permalink / raw)
  To: linus-amlogic

On Wed, Aug 09, 2017 at 03:34:48PM +0200, Jerome Brunet wrote:
> On Wed, 2017-08-09 at 12:45 +0100, Russell King - ARM Linux wrote:
> > On Tue, Aug 08, 2017 at 07:19:06PM -0700, Stephen Boyd wrote:
> > > 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;
> 
> 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);

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.

-- 
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

^ permalink raw reply	[flat|nested] 102+ messages in thread

* Re: [PATCH v3 05/10] clk: add support for clock protection
  2017-08-09 13:40                   ` Russell King - ARM Linux
@ 2017-08-09 13:45                     ` Jerome Brunet
  -1 siblings, 0 replies; 102+ messages in thread
From: Jerome Brunet @ 2017-08-09 13:45 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: Stephen Boyd, Michael Turquette, linux-clk, Kevin Hilman,
	linux-amlogic, Linus Walleij, Boris Brezillon

On Wed, 2017-08-09 at 14:40 +0100, Russell King - ARM Linux wrote:
> On Wed, Aug 09, 2017 at 03:34:48PM +0200, Jerome Brunet wrote:
> > On Wed, 2017-08-09 at 12:45 +0100, Russell King - ARM Linux wrote:
> > > On Tue, Aug 08, 2017 at 07:19:06PM -0700, Stephen Boyd wrote:
> > > > 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;
> > 
> > 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);
> 
> 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.

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

^ permalink raw reply	[flat|nested] 102+ messages in thread

* [PATCH v3 05/10] clk: add support for clock protection
@ 2017-08-09 13:45                     ` Jerome Brunet
  0 siblings, 0 replies; 102+ messages in thread
From: Jerome Brunet @ 2017-08-09 13:45 UTC (permalink / raw)
  To: linus-amlogic

On Wed, 2017-08-09 at 14:40 +0100, Russell King - ARM Linux wrote:
> On Wed, Aug 09, 2017 at 03:34:48PM +0200, Jerome Brunet wrote:
> > On Wed, 2017-08-09 at 12:45 +0100, Russell King - ARM Linux wrote:
> > > On Tue, Aug 08, 2017 at 07:19:06PM -0700, Stephen Boyd wrote:
> > > > 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;
> > 
> > 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);
> 
> 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.

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

^ permalink raw reply	[flat|nested] 102+ messages in thread

* Re: [PATCH v3 05/10] clk: add support for clock protection
  2017-08-09 11:45               ` Russell King - ARM Linux
@ 2017-08-10 16:46                 ` Michael Turquette
  -1 siblings, 0 replies; 102+ messages in thread
From: Michael Turquette @ 2017-08-10 16:46 UTC (permalink / raw)
  To: Russell King - ARM Linux, Stephen Boyd
  Cc: Jerome Brunet, linux-clk, Kevin Hilman, linux-amlogic,
	Linus Walleij, Boris Brezillon

Hi Russell,

Quoting Russell King - ARM Linux (2017-08-09 04:45:48)
> 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.

> =

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

>                 if (r =3D=3D 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.

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

> =

> -- =

> 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

^ permalink raw reply	[flat|nested] 102+ messages in thread

* [PATCH v3 05/10] clk: add support for clock protection
@ 2017-08-10 16:46                 ` Michael Turquette
  0 siblings, 0 replies; 102+ messages in thread
From: Michael Turquette @ 2017-08-10 16:46 UTC (permalink / raw)
  To: linus-amlogic

Hi Russell,

Quoting Russell King - ARM Linux (2017-08-09 04:45:48)
> 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.

> 
>         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.

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

> 
> -- 
> 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

^ permalink raw reply	[flat|nested] 102+ messages in thread

* Re: [PATCH v3 05/10] clk: add support for clock protection
  2017-08-09 13:40                   ` Russell King - ARM Linux
@ 2017-08-10 16:48                     ` Michael Turquette
  -1 siblings, 0 replies; 102+ messages in thread
From: Michael Turquette @ 2017-08-10 16:48 UTC (permalink / raw)
  To: Russell King - ARM Linux, Jerome Brunet
  Cc: Stephen Boyd, linux-clk, Kevin Hilman, linux-amlogic,
	Linus Walleij, Boris Brezillon

Quoting Russell King - ARM Linux (2017-08-09 06:40:36)
> On Wed, Aug 09, 2017 at 03:34:48PM +0200, Jerome Brunet wrote:
> > On Wed, 2017-08-09 at 12:45 +0100, Russell King - ARM Linux wrote:
> > > On Tue, Aug 08, 2017 at 07:19:06PM -0700, Stephen Boyd wrote:
> > > > 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.=C2=A0=C2=
=A0It is
> > > _not_ supposed to be:
> > > =

> > >     rounded_rate =3D clk_round_rate(clk, requested_rate);
> > > =

> > >     clk_set_rate(clk, rounded_rate);
> > > =

> > > but:
> > > =

> > >     rounded_rate =3D 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 calculatio=
ns
> > > =C2=A0=C2=A0=C2=A0that 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 rat=
e,
> > > that implies we have multiple different threads potentially changing
> > > the rate at any time.=C2=A0=C2=A0If a driver does this:
> > > =

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

> > > what prevents another thread from changing the clock rate between the=
se
> > > two calls?=C2=A0=C2=A0The only way to do this safely would be somethi=
ng like:
> > > =

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

> > >             if (r =3D=3D 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 operatio=
n). This
> > is explained in the cover letter:
> > =

> > """
> > With this series there is 3 use-case:
> > =C2=A0- the provider is not protected: nothing changes
> > =C2=A0- the provider is protected by only 1 consumer (and only once), t=
hen only
> > =C2=A0=C2=A0=C2=A0this consumer will be able to alter the rate of the c=
lock, as it is the
> > =C2=A0=C2=A0=C2=A0only one depending on it.
> > =C2=A0- If the provider is protected more than once, or by the provider=
 itself,
> > =C2=A0=C2=A0=C2=A0the rate is basically locked and protected against re=
parenting.
> > """
> > =

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

> > clk_rate_protect(clk);
> > err =3D 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

> =

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

> -- =

> 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

^ permalink raw reply	[flat|nested] 102+ messages in thread

* [PATCH v3 05/10] clk: add support for clock protection
@ 2017-08-10 16:48                     ` Michael Turquette
  0 siblings, 0 replies; 102+ messages in thread
From: Michael Turquette @ 2017-08-10 16:48 UTC (permalink / raw)
  To: linus-amlogic

Quoting Russell King - ARM Linux (2017-08-09 06:40:36)
> On Wed, Aug 09, 2017 at 03:34:48PM +0200, Jerome Brunet wrote:
> > On Wed, 2017-08-09 at 12:45 +0100, Russell King - ARM Linux wrote:
> > > On Tue, Aug 08, 2017 at 07:19:06PM -0700, Stephen Boyd wrote:
> > > > 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;
> > 
> > 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);
> 
> 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

> 
> Either that or "clk_rate_unprotect" is inappropriately named and doesn't
> do what it says it does.
> 
> -- 
> 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

^ permalink raw reply	[flat|nested] 102+ messages in thread

* Re: [PATCH v3 05/10] clk: add support for clock protection
  2017-08-09 12:18             ` Jerome Brunet
@ 2017-08-10 16:54               ` Michael Turquette
  -1 siblings, 0 replies; 102+ messages in thread
From: Michael Turquette @ 2017-08-10 16:54 UTC (permalink / raw)
  To: Jerome Brunet, Stephen Boyd
  Cc: linux-clk, Kevin Hilman, linux-amlogic, Russell King,
	Linus Walleij, Boris Brezillon

Quoting Jerome Brunet (2017-08-09 05:18:22)
> On Tue, 2017-08-08 at 15:37 -0700, Michael Turquette wrote:
> > Hi Stephen,
> > =

> > Quoting Stephen Boyd (2017-08-03 17:18:36)
> > > On 07/26, Jerome Brunet wrote:
> > > > > > +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 fir=
st RFC
> > > > [0]
> > > > Here is an example (wip) of usage [1]
> > > > =

> > > > [0]: http://lkml.kernel.org/r/20170302173835.18313-1-jbrunet@baylib=
re.com
> > > > [1]: https://github.com/jeromebrunet/linux/commits/amlogic/wip/audi=
o-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.
> > =

> > > =

> > > 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.
> > =

> > > =

> > > > =

> > > > > =

> > > > > 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 w=
ould
> > > > have
> > > > been a lot of complains about CCF by now, it does not prevent glitc=
hes 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.
> > =

> > > =

> > > > =

> > > > If you go over the initial RFC, the point is also for the CCF to fa=
vor
> > > > other
> > > > (unused parent) when several (sometimes with the same capabilities)=
 are
> > > > available. I think this is also a fairly common use case. That's so=
mething
> > > > 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,
> > =

> > 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.
> > =

> > > 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.
> > =

> > 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 i=
t helps
> with sharing issues.
> =

> > =

> > > =

> > > > =

> > > > 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 t=
he rate
> > > > between the clk_set_rate() call and prepare_enable(). That's someth=
ing 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
> > =

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

> Hum, I disagree here.=C2=A0For sure, if you call clk_set_rate() before
> clk_rate_protect() you have not guarantee at all, but you are doing it wr=
ong.
> 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 o=
nly 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.

> =

> This is a good fit for driver which heavily depends on rate being but nee=
d to
> change the rate during during their operations. It is not necessary to un=
protect
> 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

> =

> clk_set_rate_protect() is only introduce to help driver which could get i=
n 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.
> =

> > =

> > > 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
> > =

> > > =

> > > --=C2=A0
> > > Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
> > > a Linux Foundation Collaborative Project
>=20

^ permalink raw reply	[flat|nested] 102+ messages in thread

* [PATCH v3 05/10] clk: add support for clock protection
@ 2017-08-10 16:54               ` Michael Turquette
  0 siblings, 0 replies; 102+ messages in thread
From: Michael Turquette @ 2017-08-10 16:54 UTC (permalink / raw)
  To: linus-amlogic

Quoting Jerome Brunet (2017-08-09 05:18:22)
> On Tue, 2017-08-08 at 15:37 -0700, Michael Turquette wrote:
> > Hi Stephen,
> > 
> > Quoting Stephen Boyd (2017-08-03 17:18:36)
> > > On 07/26, Jerome Brunet wrote:
> > > > > > +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.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.
> > 
> > > 
> > > 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.
> > 
> > > 
> > > > 
> > > > > 
> > > > > 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.
> > > 
> > > 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.
> > 
> > > 
> > > > 
> > > > 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,
> > 
> > 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.
> > 
> > > 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.
> > 
> > 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.
> 
> > 
> > > 
> > > > 
> > > > 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
> > 
> > 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.

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.

> 
> 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

> 
> 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.
> 
> > 
> > > 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
> > 
> > > 
> > > --?
> > > Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
> > > a Linux Foundation Collaborative Project
> 

^ permalink raw reply	[flat|nested] 102+ messages in thread

end of thread, other threads:[~2017-08-10 16:54 UTC | newest]

Thread overview: 102+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-06-12 19:44 [PATCH v3 00/10] clk: implement clock rate protection mechanism Jerome Brunet
2017-06-12 19:44 ` Jerome Brunet
2017-06-12 19:44 ` [PATCH v3 01/10] clk: take the prepare lock out of clk_core_set_parent Jerome Brunet
2017-06-12 19:44   ` Jerome Brunet
2017-07-12  1:21   ` Stephen Boyd
2017-07-12  1:21     ` Stephen Boyd
2017-06-12 19:44 ` [PATCH v3 02/10] clk: add clk_core_set_phase_nolock function Jerome Brunet
2017-06-12 19:44   ` Jerome Brunet
2017-07-12  1:22   ` Stephen Boyd
2017-07-12  1:22     ` Stephen Boyd
2017-06-12 19:44 ` [PATCH v3 03/10] clk: rework calls to round and determine rate callbacks Jerome Brunet
2017-06-12 19:44   ` Jerome Brunet
2017-07-12  1:49   ` Stephen Boyd
2017-07-12  1:49     ` Stephen Boyd
2017-06-12 19:44 ` [PATCH v3 04/10] clk: use round rate to bail out early in set_rate Jerome Brunet
2017-06-12 19:44   ` Jerome Brunet
2017-07-12  2:00   ` Stephen Boyd
2017-07-12  2:00     ` Stephen Boyd
2017-07-26 17:13     ` Jerome Brunet
2017-07-26 17:13       ` Jerome Brunet
2017-08-04  0:32       ` Stephen Boyd
2017-08-04  0:32         ` Stephen Boyd
2017-06-12 19:44 ` [PATCH v3 05/10] clk: add support for clock protection Jerome Brunet
2017-06-12 19:44   ` Jerome Brunet
2017-07-26  0:12   ` Stephen Boyd
2017-07-26  0:12     ` Stephen Boyd
2017-07-26 17:18     ` Jerome Brunet
2017-07-26 17:18       ` Jerome Brunet
2017-08-04  0:18       ` Stephen Boyd
2017-08-04  0:18         ` Stephen Boyd
2017-08-08 22:37         ` Michael Turquette
2017-08-08 22:37           ` Michael Turquette
2017-08-09  2:19           ` Stephen Boyd
2017-08-09  2:19             ` Stephen Boyd
2017-08-09 11:45             ` Russell King - ARM Linux
2017-08-09 11:45               ` Russell King - ARM Linux
2017-08-09 13:34               ` Jerome Brunet
2017-08-09 13:34                 ` Jerome Brunet
2017-08-09 13:40                 ` Russell King - ARM Linux
2017-08-09 13:40                   ` Russell King - ARM Linux
2017-08-09 13:45                   ` Jerome Brunet
2017-08-09 13:45                     ` Jerome Brunet
2017-08-10 16:48                   ` Michael Turquette
2017-08-10 16:48                     ` Michael Turquette
2017-08-10 16:46               ` Michael Turquette
2017-08-10 16:46                 ` Michael Turquette
2017-08-09 13:07             ` Jerome Brunet
2017-08-09 13:07               ` Jerome Brunet
2017-08-09 12:18           ` Jerome Brunet
2017-08-09 12:18             ` Jerome Brunet
2017-08-10 16:54             ` Michael Turquette
2017-08-10 16:54               ` Michael Turquette
2017-06-12 19:44 ` [PATCH v3 06/10] clk: add clk_set_rate_protect Jerome Brunet
2017-06-12 19:44   ` Jerome Brunet
2017-07-26  0:59   ` Stephen Boyd
2017-07-26  0:59     ` Stephen Boyd
2017-06-12 19:44 ` [PATCH v3 07/10] clk: rollback set_rate_range changes on failure Jerome Brunet
2017-06-12 19:44   ` Jerome Brunet
2017-07-12  2:02   ` Stephen Boyd
2017-07-12  2:02     ` Stephen Boyd
2017-07-26 17:22     ` Jerome Brunet
2017-07-26 17:22       ` Jerome Brunet
2017-06-12 19:44 ` [PATCH v3 08/10] clk: cosmetic changes to clk_summary debugfs entry Jerome Brunet
2017-06-12 19:44   ` Jerome Brunet
2017-07-12  2:02   ` Stephen Boyd
2017-07-12  2:02     ` Stephen Boyd
2017-06-12 19:44 ` [PATCH v3 09/10] clk: fix incorrect usage of ENOSYS Jerome Brunet
2017-06-12 19:44   ` Jerome Brunet
2017-07-12  2:03   ` Stephen Boyd
2017-07-12  2:03     ` Stephen Boyd
2017-06-12 19:44 ` [PATCH v3 10/10] clk: fix CLK_SET_RATE_GATE with clock rate protection Jerome Brunet
2017-06-12 19:44   ` Jerome Brunet
2017-06-20  9:07 ` [PATCH v3 00/10] clk: implement clock rate protection mechanism Linus Walleij
2017-06-20  9:07   ` Linus Walleij
2017-06-20 10:50   ` Jerome Brunet
2017-06-20 10:50     ` Jerome Brunet
2017-06-20 11:54     ` Linus Walleij
2017-06-20 11:54       ` Linus Walleij
2017-06-20 12:32       ` Jerome Brunet
2017-06-20 12:32         ` Jerome Brunet
2017-06-20 12:47         ` Boris Brezillon
2017-06-20 12:47           ` Boris Brezillon
2017-06-22  7:07           ` Quentin Schulz
2017-06-22  7:07             ` Quentin Schulz
2017-06-22 10:09             ` Jerome Brunet
2017-06-22 10:09               ` Jerome Brunet
2017-06-20 15:29         ` Linus Walleij
2017-06-20 15:29           ` Linus Walleij
2017-06-21 13:15         ` Jerome Brunet
2017-06-21 13:15           ` Jerome Brunet
2017-07-12  1:16           ` Stephen Boyd
2017-07-12  1:16             ` Stephen Boyd
2017-07-26 17:05             ` Jerome Brunet
2017-07-26 17:05               ` Jerome Brunet
2017-07-27 22:44               ` Stephen Boyd
2017-07-27 22:44                 ` Stephen Boyd
2017-08-08 22:40                 ` Michael Turquette
2017-08-08 22:40                   ` Michael Turquette
2017-08-09 12:14                   ` Jerome Brunet
2017-08-09 12:14                     ` Jerome Brunet
2017-07-11 21:04 ` Jerome Brunet
2017-07-11 21:04   ` Jerome Brunet

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.