All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v7 0/5] clk: Provide support for always-on clocks
@ 2015-07-22 13:04 ` Lee Jones
  0 siblings, 0 replies; 93+ messages in thread
From: Lee Jones @ 2015-07-22 13:04 UTC (permalink / raw)
  To: linux-arm-kernel, linux-kernel
  Cc: kernel, mturquette, sboyd, devicetree, geert, maxime.ripard,
	s.hauer, Lee Jones

Lots of platforms contain clocks which if turned off would prove fatal.
The only way to recover from these catastrophic failures is to restart
the board(s).  Now, when a clock provider is registered with the
framework it is possible for a list of critical clocks to be supplied
which must be kept ungated.  Each clock mentioned in the newly
introduced 'critical-clock' property will be clk_prepare_enable()d
where the normal references will be taken.  This will prevent the
common clk framework from attempting to gate them during the normal
clk_disable_unused() and disable_clock() procedures.

Note that it will still be possible for knowledgeable drivers to turn
these clocks off using clk_{enable,disable}_critical() calls.

Changelog:
v6 => v7:
  - Introduce API to enable and disable critical clocks
  - Rename 'always-on-clock' to 'critical-clock'

v5 => v6:
  - Use of_clk_get_from_provider() instead of of_clk_get_by_clkspec()
  - Explicitly describe expected DT values
  - Be pedantic with regards to printk() format specifiers

vX => v5:
  Implementations have changed drastically between versions, thus I
  would like for this set to be thought of independently from its
  predecessors.  The only reason for identifying as 'v5' is ease of
  differentiation on the list, which stems from the confusion caused
  by submitting 'v4' as a separate entity.

Lee Jones (5):
  ARM: sti: stih407-family: Supply defines for CLOCKGEN A0
  ARM: sti: stih410-clocks: Identify critical clocks
  clk: Supply the critical clock {init, enable, disable} framework
  clk: Provide critical clock support
  clk: dt: Introduce binding for critical clock support

 .../devicetree/bindings/clock/clock-bindings.txt   | 39 +++++++++++++++++++
 arch/arm/boot/dts/stih410-clock.dtsi               | 10 +++++
 drivers/clk/clk-conf.c                             | 45 +++++++++++++++++++++-
 drivers/clk/clk.c                                  | 45 ++++++++++++++++++++++
 include/dt-bindings/clock/stih407-clks.h           |  4 ++
 include/linux/clk-provider.h                       |  2 +
 include/linux/clk.h                                | 30 +++++++++++++++
 7 files changed, 174 insertions(+), 1 deletion(-)

-- 
1.9.1


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

* [PATCH v7 0/5] clk: Provide support for always-on clocks
@ 2015-07-22 13:04 ` Lee Jones
  0 siblings, 0 replies; 93+ messages in thread
From: Lee Jones @ 2015-07-22 13:04 UTC (permalink / raw)
  To: linux-arm-kernel, linux-kernel
  Cc: devicetree, mturquette, kernel, s.hauer, sboyd, geert,
	maxime.ripard, Lee Jones

Lots of platforms contain clocks which if turned off would prove fatal.
The only way to recover from these catastrophic failures is to restart
the board(s).  Now, when a clock provider is registered with the
framework it is possible for a list of critical clocks to be supplied
which must be kept ungated.  Each clock mentioned in the newly
introduced 'critical-clock' property will be clk_prepare_enable()d
where the normal references will be taken.  This will prevent the
common clk framework from attempting to gate them during the normal
clk_disable_unused() and disable_clock() procedures.

Note that it will still be possible for knowledgeable drivers to turn
these clocks off using clk_{enable,disable}_critical() calls.

Changelog:
v6 => v7:
  - Introduce API to enable and disable critical clocks
  - Rename 'always-on-clock' to 'critical-clock'

v5 => v6:
  - Use of_clk_get_from_provider() instead of of_clk_get_by_clkspec()
  - Explicitly describe expected DT values
  - Be pedantic with regards to printk() format specifiers

vX => v5:
  Implementations have changed drastically between versions, thus I
  would like for this set to be thought of independently from its
  predecessors.  The only reason for identifying as 'v5' is ease of
  differentiation on the list, which stems from the confusion caused
  by submitting 'v4' as a separate entity.

Lee Jones (5):
  ARM: sti: stih407-family: Supply defines for CLOCKGEN A0
  ARM: sti: stih410-clocks: Identify critical clocks
  clk: Supply the critical clock {init, enable, disable} framework
  clk: Provide critical clock support
  clk: dt: Introduce binding for critical clock support

 .../devicetree/bindings/clock/clock-bindings.txt   | 39 +++++++++++++++++++
 arch/arm/boot/dts/stih410-clock.dtsi               | 10 +++++
 drivers/clk/clk-conf.c                             | 45 +++++++++++++++++++++-
 drivers/clk/clk.c                                  | 45 ++++++++++++++++++++++
 include/dt-bindings/clock/stih407-clks.h           |  4 ++
 include/linux/clk-provider.h                       |  2 +
 include/linux/clk.h                                | 30 +++++++++++++++
 7 files changed, 174 insertions(+), 1 deletion(-)

-- 
1.9.1

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

* [PATCH v7 0/5] clk: Provide support for always-on clocks
@ 2015-07-22 13:04 ` Lee Jones
  0 siblings, 0 replies; 93+ messages in thread
From: Lee Jones @ 2015-07-22 13:04 UTC (permalink / raw)
  To: linux-arm-kernel

Lots of platforms contain clocks which if turned off would prove fatal.
The only way to recover from these catastrophic failures is to restart
the board(s).  Now, when a clock provider is registered with the
framework it is possible for a list of critical clocks to be supplied
which must be kept ungated.  Each clock mentioned in the newly
introduced 'critical-clock' property will be clk_prepare_enable()d
where the normal references will be taken.  This will prevent the
common clk framework from attempting to gate them during the normal
clk_disable_unused() and disable_clock() procedures.

Note that it will still be possible for knowledgeable drivers to turn
these clocks off using clk_{enable,disable}_critical() calls.

Changelog:
v6 => v7:
  - Introduce API to enable and disable critical clocks
  - Rename 'always-on-clock' to 'critical-clock'

v5 => v6:
  - Use of_clk_get_from_provider() instead of of_clk_get_by_clkspec()
  - Explicitly describe expected DT values
  - Be pedantic with regards to printk() format specifiers

vX => v5:
  Implementations have changed drastically between versions, thus I
  would like for this set to be thought of independently from its
  predecessors.  The only reason for identifying as 'v5' is ease of
  differentiation on the list, which stems from the confusion caused
  by submitting 'v4' as a separate entity.

Lee Jones (5):
  ARM: sti: stih407-family: Supply defines for CLOCKGEN A0
  ARM: sti: stih410-clocks: Identify critical clocks
  clk: Supply the critical clock {init, enable, disable} framework
  clk: Provide critical clock support
  clk: dt: Introduce binding for critical clock support

 .../devicetree/bindings/clock/clock-bindings.txt   | 39 +++++++++++++++++++
 arch/arm/boot/dts/stih410-clock.dtsi               | 10 +++++
 drivers/clk/clk-conf.c                             | 45 +++++++++++++++++++++-
 drivers/clk/clk.c                                  | 45 ++++++++++++++++++++++
 include/dt-bindings/clock/stih407-clks.h           |  4 ++
 include/linux/clk-provider.h                       |  2 +
 include/linux/clk.h                                | 30 +++++++++++++++
 7 files changed, 174 insertions(+), 1 deletion(-)

-- 
1.9.1

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

* [PATCH v7 1/5] ARM: sti: stih407-family: Supply defines for CLOCKGEN A0
  2015-07-22 13:04 ` Lee Jones
  (?)
@ 2015-07-22 13:04   ` Lee Jones
  -1 siblings, 0 replies; 93+ messages in thread
From: Lee Jones @ 2015-07-22 13:04 UTC (permalink / raw)
  To: linux-arm-kernel, linux-kernel
  Cc: kernel, mturquette, sboyd, devicetree, geert, maxime.ripard,
	s.hauer, Lee Jones

There are 2 LMI clocks generated by CLOCKGEN A0.  We wish to control
them individually and need to use these indexes to do so.

Signed-off-by: Lee Jones <lee.jones@linaro.org>
---
 include/dt-bindings/clock/stih407-clks.h | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/include/dt-bindings/clock/stih407-clks.h b/include/dt-bindings/clock/stih407-clks.h
index 7af2b71..082edd9 100644
--- a/include/dt-bindings/clock/stih407-clks.h
+++ b/include/dt-bindings/clock/stih407-clks.h
@@ -5,6 +5,10 @@
 #ifndef _DT_BINDINGS_CLK_STIH407
 #define _DT_BINDINGS_CLK_STIH407
 
+/* CLOCKGEN A0 */
+#define CLK_IC_LMI0		0
+#define CLK_IC_LMI1		1
+
 /* CLOCKGEN C0 */
 #define CLK_ICN_GPU		0
 #define CLK_FDMA		1
-- 
1.9.1


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

* [PATCH v7 1/5] ARM: sti: stih407-family: Supply defines for CLOCKGEN A0
@ 2015-07-22 13:04   ` Lee Jones
  0 siblings, 0 replies; 93+ messages in thread
From: Lee Jones @ 2015-07-22 13:04 UTC (permalink / raw)
  To: linux-arm-kernel, linux-kernel
  Cc: devicetree, mturquette, kernel, s.hauer, sboyd, geert,
	maxime.ripard, Lee Jones

There are 2 LMI clocks generated by CLOCKGEN A0.  We wish to control
them individually and need to use these indexes to do so.

Signed-off-by: Lee Jones <lee.jones@linaro.org>
---
 include/dt-bindings/clock/stih407-clks.h | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/include/dt-bindings/clock/stih407-clks.h b/include/dt-bindings/clock/stih407-clks.h
index 7af2b71..082edd9 100644
--- a/include/dt-bindings/clock/stih407-clks.h
+++ b/include/dt-bindings/clock/stih407-clks.h
@@ -5,6 +5,10 @@
 #ifndef _DT_BINDINGS_CLK_STIH407
 #define _DT_BINDINGS_CLK_STIH407
 
+/* CLOCKGEN A0 */
+#define CLK_IC_LMI0		0
+#define CLK_IC_LMI1		1
+
 /* CLOCKGEN C0 */
 #define CLK_ICN_GPU		0
 #define CLK_FDMA		1
-- 
1.9.1

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

* [PATCH v7 1/5] ARM: sti: stih407-family: Supply defines for CLOCKGEN A0
@ 2015-07-22 13:04   ` Lee Jones
  0 siblings, 0 replies; 93+ messages in thread
From: Lee Jones @ 2015-07-22 13:04 UTC (permalink / raw)
  To: linux-arm-kernel

There are 2 LMI clocks generated by CLOCKGEN A0.  We wish to control
them individually and need to use these indexes to do so.

Signed-off-by: Lee Jones <lee.jones@linaro.org>
---
 include/dt-bindings/clock/stih407-clks.h | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/include/dt-bindings/clock/stih407-clks.h b/include/dt-bindings/clock/stih407-clks.h
index 7af2b71..082edd9 100644
--- a/include/dt-bindings/clock/stih407-clks.h
+++ b/include/dt-bindings/clock/stih407-clks.h
@@ -5,6 +5,10 @@
 #ifndef _DT_BINDINGS_CLK_STIH407
 #define _DT_BINDINGS_CLK_STIH407
 
+/* CLOCKGEN A0 */
+#define CLK_IC_LMI0		0
+#define CLK_IC_LMI1		1
+
 /* CLOCKGEN C0 */
 #define CLK_ICN_GPU		0
 #define CLK_FDMA		1
-- 
1.9.1

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

* [PATCH v7 2/5] ARM: sti: stih410-clocks: Identify critical clocks
  2015-07-22 13:04 ` Lee Jones
@ 2015-07-22 13:04   ` Lee Jones
  -1 siblings, 0 replies; 93+ messages in thread
From: Lee Jones @ 2015-07-22 13:04 UTC (permalink / raw)
  To: linux-arm-kernel, linux-kernel
  Cc: kernel, mturquette, sboyd, devicetree, geert, maxime.ripard,
	s.hauer, Lee Jones

Lots of platforms contain clocks which if turned off would prove fatal.
The only way to recover is to restart the board(s).  This driver takes
references to clocks which are required to be always-on.  The Common
Clk Framework will then take references to them.  This way they will
not be turned off during the clk_disabled_unused() procedure.

In this patch we are identifying clocks, which if gated would render
the STiH410 development board unserviceable.

Signed-off-by: Lee Jones <lee.jones@linaro.org>
---
 arch/arm/boot/dts/stih410-clock.dtsi | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/arch/arm/boot/dts/stih410-clock.dtsi b/arch/arm/boot/dts/stih410-clock.dtsi
index 6b5803a..0a72c56 100644
--- a/arch/arm/boot/dts/stih410-clock.dtsi
+++ b/arch/arm/boot/dts/stih410-clock.dtsi
@@ -103,6 +103,7 @@
 				clocks = <&clk_sysin>;
 
 				clock-output-names = "clk-s-a0-pll-ofd-0";
+				critical-clock = <0>; /* clk-s-a0-pll-ofd-0 */
 			};
 
 			clk_s_a0_flexgen: clk-s-a0-flexgen {
@@ -115,6 +116,8 @@
 
 				clock-output-names = "clk-ic-lmi0",
 						     "clk-ic-lmi1";
+
+				critical-clock = <CLK_IC_LMI0>;
 			};
 		};
 
@@ -142,6 +145,7 @@
 				clocks = <&clk_sysin>;
 
 				clock-output-names = "clk-s-c0-pll0-odf-0";
+				critical-clock = <0>; /* clk-s-c0-pll0-odf-0 */
 			};
 
 			clk_s_c0_pll1: clk-s-c0-pll1 {
@@ -204,6 +208,12 @@
 						     "clk-clust-hades",
 						     "clk-hwpe-hades",
 						     "clk-fc-hades";
+
+				critical-clock = <CLK_ICN_CPU>,
+						 <CLK_TX_ICN_DMU>,
+						 <CLK_EXT2F_A9>,
+						 <CLK_ICN_LMI>,
+						 <CLK_ICN_SBC>;
 			};
 		};
 
-- 
1.9.1


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

* [PATCH v7 2/5] ARM: sti: stih410-clocks: Identify critical clocks
@ 2015-07-22 13:04   ` Lee Jones
  0 siblings, 0 replies; 93+ messages in thread
From: Lee Jones @ 2015-07-22 13:04 UTC (permalink / raw)
  To: linux-arm-kernel

Lots of platforms contain clocks which if turned off would prove fatal.
The only way to recover is to restart the board(s).  This driver takes
references to clocks which are required to be always-on.  The Common
Clk Framework will then take references to them.  This way they will
not be turned off during the clk_disabled_unused() procedure.

In this patch we are identifying clocks, which if gated would render
the STiH410 development board unserviceable.

Signed-off-by: Lee Jones <lee.jones@linaro.org>
---
 arch/arm/boot/dts/stih410-clock.dtsi | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/arch/arm/boot/dts/stih410-clock.dtsi b/arch/arm/boot/dts/stih410-clock.dtsi
index 6b5803a..0a72c56 100644
--- a/arch/arm/boot/dts/stih410-clock.dtsi
+++ b/arch/arm/boot/dts/stih410-clock.dtsi
@@ -103,6 +103,7 @@
 				clocks = <&clk_sysin>;
 
 				clock-output-names = "clk-s-a0-pll-ofd-0";
+				critical-clock = <0>; /* clk-s-a0-pll-ofd-0 */
 			};
 
 			clk_s_a0_flexgen: clk-s-a0-flexgen {
@@ -115,6 +116,8 @@
 
 				clock-output-names = "clk-ic-lmi0",
 						     "clk-ic-lmi1";
+
+				critical-clock = <CLK_IC_LMI0>;
 			};
 		};
 
@@ -142,6 +145,7 @@
 				clocks = <&clk_sysin>;
 
 				clock-output-names = "clk-s-c0-pll0-odf-0";
+				critical-clock = <0>; /* clk-s-c0-pll0-odf-0 */
 			};
 
 			clk_s_c0_pll1: clk-s-c0-pll1 {
@@ -204,6 +208,12 @@
 						     "clk-clust-hades",
 						     "clk-hwpe-hades",
 						     "clk-fc-hades";
+
+				critical-clock = <CLK_ICN_CPU>,
+						 <CLK_TX_ICN_DMU>,
+						 <CLK_EXT2F_A9>,
+						 <CLK_ICN_LMI>,
+						 <CLK_ICN_SBC>;
 			};
 		};
 
-- 
1.9.1

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

* [PATCH v7 3/5] clk: Supply the critical clock {init, enable, disable} framework
  2015-07-22 13:04 ` Lee Jones
  (?)
@ 2015-07-22 13:04   ` Lee Jones
  -1 siblings, 0 replies; 93+ messages in thread
From: Lee Jones @ 2015-07-22 13:04 UTC (permalink / raw)
  To: linux-arm-kernel, linux-kernel
  Cc: kernel, mturquette, sboyd, devicetree, geert, maxime.ripard,
	s.hauer, Lee Jones

These new API calls will firstly provide a mechanisms to tag a clock as
critical and secondly allow any knowledgeable driver to (un)gate clocks,
even if they are marked as critical.

Suggested-by: Maxime Ripard <maxime.ripard@free-electrons.com>
Signed-off-by: Lee Jones <lee.jones@linaro.org>
---
 drivers/clk/clk.c            | 45 ++++++++++++++++++++++++++++++++++++++++++++
 include/linux/clk-provider.h |  2 ++
 include/linux/clk.h          | 30 +++++++++++++++++++++++++++++
 3 files changed, 77 insertions(+)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 61c3fc5..486b1da 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -46,6 +46,21 @@ static struct clk_core *clk_core_lookup(const char *name);
 
 /***    private data structures    ***/
 
+/**
+ * struct critical -	Provides 'play' over critical clocks.  A clock can be
+ *			marked as critical, meaning that it should not be
+ *			disabled.  However, if a driver which is aware of the
+ *			critical behaviour wants to control it, it can do so
+ *			using clk_enable_critical() and clk_disable_critical().
+ *
+ * @enabled	Is clock critical?  Once set, doesn't change
+ * @leave_on	Self explanatory.  Can be disabled by knowledgeable drivers
+ */
+struct critical {
+	bool enabled;
+	bool leave_on;
+};
+
 struct clk_core {
 	const char		*name;
 	const struct clk_ops	*ops;
@@ -75,6 +90,7 @@ struct clk_core {
 	struct dentry		*dentry;
 #endif
 	struct kref		ref;
+	struct critical		critical;
 };
 
 struct clk {
@@ -995,6 +1011,10 @@ static void clk_core_disable(struct clk_core *clk)
 	if (WARN_ON(clk->enable_count == 0))
 		return;
 
+	/* Refuse to turn off a critical clock */
+	if (clk->enable_count == 1 && clk->critical.leave_on)
+		return;
+
 	if (--clk->enable_count > 0)
 		return;
 
@@ -1037,6 +1057,13 @@ void clk_disable(struct clk *clk)
 }
 EXPORT_SYMBOL_GPL(clk_disable);
 
+void clk_disable_critical(struct clk *clk)
+{
+	clk->core->critical.leave_on = false;
+	clk_disable(clk);
+}
+EXPORT_SYMBOL_GPL(clk_disable_critical);
+
 static int clk_core_enable(struct clk_core *clk)
 {
 	int ret = 0;
@@ -1100,6 +1127,15 @@ int clk_enable(struct clk *clk)
 }
 EXPORT_SYMBOL_GPL(clk_enable);
 
+int clk_enable_critical(struct clk *clk)
+{
+	if (clk->core->critical.enabled)
+		clk->core->critical.leave_on = true;
+
+	return clk_enable(clk);
+}
+EXPORT_SYMBOL_GPL(clk_enable_critical);
+
 static unsigned long clk_core_round_rate_nolock(struct clk_core *clk,
 						unsigned long rate,
 						unsigned long min_rate,
@@ -2482,6 +2518,15 @@ fail_out:
 }
 EXPORT_SYMBOL_GPL(clk_register);
 
+void clk_init_critical(struct clk *clk)
+{
+	struct critical *critical = &clk->core->critical;
+
+	critical->enabled = true;
+	critical->leave_on = true;
+}
+EXPORT_SYMBOL_GPL(clk_init_critical);
+
 /*
  * Free memory allocated for a clock.
  * Caller must hold prepare_lock.
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 5591ea7..15ef8c9 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -563,6 +563,8 @@ struct clk *devm_clk_register(struct device *dev, struct clk_hw *hw);
 void clk_unregister(struct clk *clk);
 void devm_clk_unregister(struct device *dev, struct clk *clk);
 
+void clk_init_critical(struct clk *clk);
+
 /* helper functions */
 const char *__clk_get_name(struct clk *clk);
 struct clk_hw *__clk_get_hw(struct clk *clk);
diff --git a/include/linux/clk.h b/include/linux/clk.h
index 8381bbf..9807f3b 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -231,6 +231,19 @@ struct clk *devm_clk_get(struct device *dev, const char *id);
 int clk_enable(struct clk *clk);
 
 /**
+ * clk_enable_critical - inform the system when the clock source should be
+ * 			 running, even if clock is critical.
+ * @clk: clock source
+ *
+ * If the clock can not be enabled/disabled, this should return success.
+ *
+ * May be called from atomic contexts.
+ *
+ * Returns success (0) or negative errno.
+ */
+int clk_enable_critical(struct clk *clk);
+
+/**
  * clk_disable - inform the system when the clock source is no longer required.
  * @clk: clock source
  *
@@ -247,6 +260,23 @@ int clk_enable(struct clk *clk);
 void clk_disable(struct clk *clk);
 
 /**
+ * clk_disable_critical - inform the system when the clock source is no
+ * 			  longer required, even if clock is critical.
+ * @clk: clock source
+ *
+ * Inform the system that a clock source is no longer required by
+ * a driver and may be shut down.
+ *
+ * May be called from atomic contexts.
+ *
+ * Implementation detail: if the clock source is shared between
+ * multiple drivers, clk_enable_critical() calls must be balanced
+ * by the same number of clk_disable_critical() calls for the clock
+ * source to be disabled.
+ */
+void clk_disable_critical(struct clk *clk);
+
+/**
  * clk_get_rate - obtain the current clock rate (in Hz) for a clock source.
  *		  This is only valid once the clock source has been enabled.
  * @clk: clock source
-- 
1.9.1


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

* [PATCH v7 3/5] clk: Supply the critical clock {init, enable, disable} framework
@ 2015-07-22 13:04   ` Lee Jones
  0 siblings, 0 replies; 93+ messages in thread
From: Lee Jones @ 2015-07-22 13:04 UTC (permalink / raw)
  To: linux-arm-kernel, linux-kernel
  Cc: devicetree, mturquette, kernel, s.hauer, sboyd, geert,
	maxime.ripard, Lee Jones

These new API calls will firstly provide a mechanisms to tag a clock as
critical and secondly allow any knowledgeable driver to (un)gate clocks,
even if they are marked as critical.

Suggested-by: Maxime Ripard <maxime.ripard@free-electrons.com>
Signed-off-by: Lee Jones <lee.jones@linaro.org>
---
 drivers/clk/clk.c            | 45 ++++++++++++++++++++++++++++++++++++++++++++
 include/linux/clk-provider.h |  2 ++
 include/linux/clk.h          | 30 +++++++++++++++++++++++++++++
 3 files changed, 77 insertions(+)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 61c3fc5..486b1da 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -46,6 +46,21 @@ static struct clk_core *clk_core_lookup(const char *name);
 
 /***    private data structures    ***/
 
+/**
+ * struct critical -	Provides 'play' over critical clocks.  A clock can be
+ *			marked as critical, meaning that it should not be
+ *			disabled.  However, if a driver which is aware of the
+ *			critical behaviour wants to control it, it can do so
+ *			using clk_enable_critical() and clk_disable_critical().
+ *
+ * @enabled	Is clock critical?  Once set, doesn't change
+ * @leave_on	Self explanatory.  Can be disabled by knowledgeable drivers
+ */
+struct critical {
+	bool enabled;
+	bool leave_on;
+};
+
 struct clk_core {
 	const char		*name;
 	const struct clk_ops	*ops;
@@ -75,6 +90,7 @@ struct clk_core {
 	struct dentry		*dentry;
 #endif
 	struct kref		ref;
+	struct critical		critical;
 };
 
 struct clk {
@@ -995,6 +1011,10 @@ static void clk_core_disable(struct clk_core *clk)
 	if (WARN_ON(clk->enable_count == 0))
 		return;
 
+	/* Refuse to turn off a critical clock */
+	if (clk->enable_count == 1 && clk->critical.leave_on)
+		return;
+
 	if (--clk->enable_count > 0)
 		return;
 
@@ -1037,6 +1057,13 @@ void clk_disable(struct clk *clk)
 }
 EXPORT_SYMBOL_GPL(clk_disable);
 
+void clk_disable_critical(struct clk *clk)
+{
+	clk->core->critical.leave_on = false;
+	clk_disable(clk);
+}
+EXPORT_SYMBOL_GPL(clk_disable_critical);
+
 static int clk_core_enable(struct clk_core *clk)
 {
 	int ret = 0;
@@ -1100,6 +1127,15 @@ int clk_enable(struct clk *clk)
 }
 EXPORT_SYMBOL_GPL(clk_enable);
 
+int clk_enable_critical(struct clk *clk)
+{
+	if (clk->core->critical.enabled)
+		clk->core->critical.leave_on = true;
+
+	return clk_enable(clk);
+}
+EXPORT_SYMBOL_GPL(clk_enable_critical);
+
 static unsigned long clk_core_round_rate_nolock(struct clk_core *clk,
 						unsigned long rate,
 						unsigned long min_rate,
@@ -2482,6 +2518,15 @@ fail_out:
 }
 EXPORT_SYMBOL_GPL(clk_register);
 
+void clk_init_critical(struct clk *clk)
+{
+	struct critical *critical = &clk->core->critical;
+
+	critical->enabled = true;
+	critical->leave_on = true;
+}
+EXPORT_SYMBOL_GPL(clk_init_critical);
+
 /*
  * Free memory allocated for a clock.
  * Caller must hold prepare_lock.
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 5591ea7..15ef8c9 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -563,6 +563,8 @@ struct clk *devm_clk_register(struct device *dev, struct clk_hw *hw);
 void clk_unregister(struct clk *clk);
 void devm_clk_unregister(struct device *dev, struct clk *clk);
 
+void clk_init_critical(struct clk *clk);
+
 /* helper functions */
 const char *__clk_get_name(struct clk *clk);
 struct clk_hw *__clk_get_hw(struct clk *clk);
diff --git a/include/linux/clk.h b/include/linux/clk.h
index 8381bbf..9807f3b 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -231,6 +231,19 @@ struct clk *devm_clk_get(struct device *dev, const char *id);
 int clk_enable(struct clk *clk);
 
 /**
+ * clk_enable_critical - inform the system when the clock source should be
+ * 			 running, even if clock is critical.
+ * @clk: clock source
+ *
+ * If the clock can not be enabled/disabled, this should return success.
+ *
+ * May be called from atomic contexts.
+ *
+ * Returns success (0) or negative errno.
+ */
+int clk_enable_critical(struct clk *clk);
+
+/**
  * clk_disable - inform the system when the clock source is no longer required.
  * @clk: clock source
  *
@@ -247,6 +260,23 @@ int clk_enable(struct clk *clk);
 void clk_disable(struct clk *clk);
 
 /**
+ * clk_disable_critical - inform the system when the clock source is no
+ * 			  longer required, even if clock is critical.
+ * @clk: clock source
+ *
+ * Inform the system that a clock source is no longer required by
+ * a driver and may be shut down.
+ *
+ * May be called from atomic contexts.
+ *
+ * Implementation detail: if the clock source is shared between
+ * multiple drivers, clk_enable_critical() calls must be balanced
+ * by the same number of clk_disable_critical() calls for the clock
+ * source to be disabled.
+ */
+void clk_disable_critical(struct clk *clk);
+
+/**
  * clk_get_rate - obtain the current clock rate (in Hz) for a clock source.
  *		  This is only valid once the clock source has been enabled.
  * @clk: clock source
-- 
1.9.1

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

* [PATCH v7 3/5] clk: Supply the critical clock {init, enable, disable} framework
@ 2015-07-22 13:04   ` Lee Jones
  0 siblings, 0 replies; 93+ messages in thread
From: Lee Jones @ 2015-07-22 13:04 UTC (permalink / raw)
  To: linux-arm-kernel

These new API calls will firstly provide a mechanisms to tag a clock as
critical and secondly allow any knowledgeable driver to (un)gate clocks,
even if they are marked as critical.

Suggested-by: Maxime Ripard <maxime.ripard@free-electrons.com>
Signed-off-by: Lee Jones <lee.jones@linaro.org>
---
 drivers/clk/clk.c            | 45 ++++++++++++++++++++++++++++++++++++++++++++
 include/linux/clk-provider.h |  2 ++
 include/linux/clk.h          | 30 +++++++++++++++++++++++++++++
 3 files changed, 77 insertions(+)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 61c3fc5..486b1da 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -46,6 +46,21 @@ static struct clk_core *clk_core_lookup(const char *name);
 
 /***    private data structures    ***/
 
+/**
+ * struct critical -	Provides 'play' over critical clocks.  A clock can be
+ *			marked as critical, meaning that it should not be
+ *			disabled.  However, if a driver which is aware of the
+ *			critical behaviour wants to control it, it can do so
+ *			using clk_enable_critical() and clk_disable_critical().
+ *
+ * @enabled	Is clock critical?  Once set, doesn't change
+ * @leave_on	Self explanatory.  Can be disabled by knowledgeable drivers
+ */
+struct critical {
+	bool enabled;
+	bool leave_on;
+};
+
 struct clk_core {
 	const char		*name;
 	const struct clk_ops	*ops;
@@ -75,6 +90,7 @@ struct clk_core {
 	struct dentry		*dentry;
 #endif
 	struct kref		ref;
+	struct critical		critical;
 };
 
 struct clk {
@@ -995,6 +1011,10 @@ static void clk_core_disable(struct clk_core *clk)
 	if (WARN_ON(clk->enable_count == 0))
 		return;
 
+	/* Refuse to turn off a critical clock */
+	if (clk->enable_count == 1 && clk->critical.leave_on)
+		return;
+
 	if (--clk->enable_count > 0)
 		return;
 
@@ -1037,6 +1057,13 @@ void clk_disable(struct clk *clk)
 }
 EXPORT_SYMBOL_GPL(clk_disable);
 
+void clk_disable_critical(struct clk *clk)
+{
+	clk->core->critical.leave_on = false;
+	clk_disable(clk);
+}
+EXPORT_SYMBOL_GPL(clk_disable_critical);
+
 static int clk_core_enable(struct clk_core *clk)
 {
 	int ret = 0;
@@ -1100,6 +1127,15 @@ int clk_enable(struct clk *clk)
 }
 EXPORT_SYMBOL_GPL(clk_enable);
 
+int clk_enable_critical(struct clk *clk)
+{
+	if (clk->core->critical.enabled)
+		clk->core->critical.leave_on = true;
+
+	return clk_enable(clk);
+}
+EXPORT_SYMBOL_GPL(clk_enable_critical);
+
 static unsigned long clk_core_round_rate_nolock(struct clk_core *clk,
 						unsigned long rate,
 						unsigned long min_rate,
@@ -2482,6 +2518,15 @@ fail_out:
 }
 EXPORT_SYMBOL_GPL(clk_register);
 
+void clk_init_critical(struct clk *clk)
+{
+	struct critical *critical = &clk->core->critical;
+
+	critical->enabled = true;
+	critical->leave_on = true;
+}
+EXPORT_SYMBOL_GPL(clk_init_critical);
+
 /*
  * Free memory allocated for a clock.
  * Caller must hold prepare_lock.
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 5591ea7..15ef8c9 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -563,6 +563,8 @@ struct clk *devm_clk_register(struct device *dev, struct clk_hw *hw);
 void clk_unregister(struct clk *clk);
 void devm_clk_unregister(struct device *dev, struct clk *clk);
 
+void clk_init_critical(struct clk *clk);
+
 /* helper functions */
 const char *__clk_get_name(struct clk *clk);
 struct clk_hw *__clk_get_hw(struct clk *clk);
diff --git a/include/linux/clk.h b/include/linux/clk.h
index 8381bbf..9807f3b 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -231,6 +231,19 @@ struct clk *devm_clk_get(struct device *dev, const char *id);
 int clk_enable(struct clk *clk);
 
 /**
+ * clk_enable_critical - inform the system when the clock source should be
+ * 			 running, even if clock is critical.
+ * @clk: clock source
+ *
+ * If the clock can not be enabled/disabled, this should return success.
+ *
+ * May be called from atomic contexts.
+ *
+ * Returns success (0) or negative errno.
+ */
+int clk_enable_critical(struct clk *clk);
+
+/**
  * clk_disable - inform the system when the clock source is no longer required.
  * @clk: clock source
  *
@@ -247,6 +260,23 @@ int clk_enable(struct clk *clk);
 void clk_disable(struct clk *clk);
 
 /**
+ * clk_disable_critical - inform the system when the clock source is no
+ * 			  longer required, even if clock is critical.
+ * @clk: clock source
+ *
+ * Inform the system that a clock source is no longer required by
+ * a driver and may be shut down.
+ *
+ * May be called from atomic contexts.
+ *
+ * Implementation detail: if the clock source is shared between
+ * multiple drivers, clk_enable_critical() calls must be balanced
+ * by the same number of clk_disable_critical() calls for the clock
+ * source to be disabled.
+ */
+void clk_disable_critical(struct clk *clk);
+
+/**
  * clk_get_rate - obtain the current clock rate (in Hz) for a clock source.
  *		  This is only valid once the clock source has been enabled.
  * @clk: clock source
-- 
1.9.1

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

* [PATCH v7 4/5] clk: Provide critical clock support
  2015-07-22 13:04 ` Lee Jones
  (?)
@ 2015-07-22 13:04   ` Lee Jones
  -1 siblings, 0 replies; 93+ messages in thread
From: Lee Jones @ 2015-07-22 13:04 UTC (permalink / raw)
  To: linux-arm-kernel, linux-kernel
  Cc: kernel, mturquette, sboyd, devicetree, geert, maxime.ripard,
	s.hauer, Lee Jones

Lots of platforms contain clocks which if turned off would prove fatal.
The only way to recover from these catastrophic failures is to restart
the board(s).  Now, when a clock provider is registered with the
framework it is possible for a list of critical clocks to be supplied
which must be kept ungated.  Each clock mentioned in the newly
introduced 'critical-clock' property will be clk_prepare_enable()d
where the normal references will be taken.  This will prevent the
common clk framework from attempting to gate them during the normal
clk_disable_unused() and disable_clock() procedures.

Note that it will still be possible for knowledgeable drivers to turn
these clocks off using clk_{enable,disable}_critical() calls.

Signed-off-by: Lee Jones <lee.jones@linaro.org>
---
 drivers/clk/clk-conf.c | 45 ++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 44 insertions(+), 1 deletion(-)

diff --git a/drivers/clk/clk-conf.c b/drivers/clk/clk-conf.c
index aad4796..f83c1c2 100644
--- a/drivers/clk/clk-conf.c
+++ b/drivers/clk/clk-conf.c
@@ -116,6 +116,45 @@ static int __set_clk_rates(struct device_node *node, bool clk_supplier)
 	return 0;
 }
 
+static int __set_critical_clocks(struct device_node *node, bool clk_supplier)
+{
+	struct of_phandle_args clkspec;
+	struct clk *clk;
+	struct property	*prop;
+	const __be32 *cur;
+	uint32_t index;
+	int ret;
+
+	if (!clk_supplier)
+		return 0;
+
+	of_property_for_each_u32(node, "critical-clock", prop, cur, index) {
+		clkspec.np = node;
+		clkspec.args_count = 1;
+		clkspec.args[0] = index;
+
+		clk = of_clk_get_from_provider(&clkspec);
+		if (IS_ERR(clk)) {
+			pr_err("clk: couldn't get clock %u for %s\n",
+				index, node->full_name);
+			return PTR_ERR(clk);
+		}
+
+		clk_init_critical(clk);
+
+		ret = clk_prepare_enable(clk);
+		if (ret) {
+			pr_err("Failed to enable clock %u for %s: %d\n",
+			       index, node->full_name, ret);
+			return ret;
+		}
+
+		pr_debug("Setting clock as critical %pC\n", clk);
+	}
+
+	return 0;
+}
+
 /**
  * of_clk_set_defaults() - parse and set assigned clocks configuration
  * @node: device node to apply clock settings for
@@ -139,6 +178,10 @@ int of_clk_set_defaults(struct device_node *node, bool clk_supplier)
 	if (rc < 0)
 		return rc;
 
-	return __set_clk_rates(node, clk_supplier);
+	rc = __set_clk_rates(node, clk_supplier);
+	if (rc < 0)
+		return rc;
+
+	return __set_critical_clocks(node, clk_supplier);
 }
 EXPORT_SYMBOL_GPL(of_clk_set_defaults);
-- 
1.9.1


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

* [PATCH v7 4/5] clk: Provide critical clock support
@ 2015-07-22 13:04   ` Lee Jones
  0 siblings, 0 replies; 93+ messages in thread
From: Lee Jones @ 2015-07-22 13:04 UTC (permalink / raw)
  To: linux-arm-kernel, linux-kernel
  Cc: devicetree, mturquette, kernel, s.hauer, sboyd, geert,
	maxime.ripard, Lee Jones

Lots of platforms contain clocks which if turned off would prove fatal.
The only way to recover from these catastrophic failures is to restart
the board(s).  Now, when a clock provider is registered with the
framework it is possible for a list of critical clocks to be supplied
which must be kept ungated.  Each clock mentioned in the newly
introduced 'critical-clock' property will be clk_prepare_enable()d
where the normal references will be taken.  This will prevent the
common clk framework from attempting to gate them during the normal
clk_disable_unused() and disable_clock() procedures.

Note that it will still be possible for knowledgeable drivers to turn
these clocks off using clk_{enable,disable}_critical() calls.

Signed-off-by: Lee Jones <lee.jones@linaro.org>
---
 drivers/clk/clk-conf.c | 45 ++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 44 insertions(+), 1 deletion(-)

diff --git a/drivers/clk/clk-conf.c b/drivers/clk/clk-conf.c
index aad4796..f83c1c2 100644
--- a/drivers/clk/clk-conf.c
+++ b/drivers/clk/clk-conf.c
@@ -116,6 +116,45 @@ static int __set_clk_rates(struct device_node *node, bool clk_supplier)
 	return 0;
 }
 
+static int __set_critical_clocks(struct device_node *node, bool clk_supplier)
+{
+	struct of_phandle_args clkspec;
+	struct clk *clk;
+	struct property	*prop;
+	const __be32 *cur;
+	uint32_t index;
+	int ret;
+
+	if (!clk_supplier)
+		return 0;
+
+	of_property_for_each_u32(node, "critical-clock", prop, cur, index) {
+		clkspec.np = node;
+		clkspec.args_count = 1;
+		clkspec.args[0] = index;
+
+		clk = of_clk_get_from_provider(&clkspec);
+		if (IS_ERR(clk)) {
+			pr_err("clk: couldn't get clock %u for %s\n",
+				index, node->full_name);
+			return PTR_ERR(clk);
+		}
+
+		clk_init_critical(clk);
+
+		ret = clk_prepare_enable(clk);
+		if (ret) {
+			pr_err("Failed to enable clock %u for %s: %d\n",
+			       index, node->full_name, ret);
+			return ret;
+		}
+
+		pr_debug("Setting clock as critical %pC\n", clk);
+	}
+
+	return 0;
+}
+
 /**
  * of_clk_set_defaults() - parse and set assigned clocks configuration
  * @node: device node to apply clock settings for
@@ -139,6 +178,10 @@ int of_clk_set_defaults(struct device_node *node, bool clk_supplier)
 	if (rc < 0)
 		return rc;
 
-	return __set_clk_rates(node, clk_supplier);
+	rc = __set_clk_rates(node, clk_supplier);
+	if (rc < 0)
+		return rc;
+
+	return __set_critical_clocks(node, clk_supplier);
 }
 EXPORT_SYMBOL_GPL(of_clk_set_defaults);
-- 
1.9.1

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

* [PATCH v7 4/5] clk: Provide critical clock support
@ 2015-07-22 13:04   ` Lee Jones
  0 siblings, 0 replies; 93+ messages in thread
From: Lee Jones @ 2015-07-22 13:04 UTC (permalink / raw)
  To: linux-arm-kernel

Lots of platforms contain clocks which if turned off would prove fatal.
The only way to recover from these catastrophic failures is to restart
the board(s).  Now, when a clock provider is registered with the
framework it is possible for a list of critical clocks to be supplied
which must be kept ungated.  Each clock mentioned in the newly
introduced 'critical-clock' property will be clk_prepare_enable()d
where the normal references will be taken.  This will prevent the
common clk framework from attempting to gate them during the normal
clk_disable_unused() and disable_clock() procedures.

Note that it will still be possible for knowledgeable drivers to turn
these clocks off using clk_{enable,disable}_critical() calls.

Signed-off-by: Lee Jones <lee.jones@linaro.org>
---
 drivers/clk/clk-conf.c | 45 ++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 44 insertions(+), 1 deletion(-)

diff --git a/drivers/clk/clk-conf.c b/drivers/clk/clk-conf.c
index aad4796..f83c1c2 100644
--- a/drivers/clk/clk-conf.c
+++ b/drivers/clk/clk-conf.c
@@ -116,6 +116,45 @@ static int __set_clk_rates(struct device_node *node, bool clk_supplier)
 	return 0;
 }
 
+static int __set_critical_clocks(struct device_node *node, bool clk_supplier)
+{
+	struct of_phandle_args clkspec;
+	struct clk *clk;
+	struct property	*prop;
+	const __be32 *cur;
+	uint32_t index;
+	int ret;
+
+	if (!clk_supplier)
+		return 0;
+
+	of_property_for_each_u32(node, "critical-clock", prop, cur, index) {
+		clkspec.np = node;
+		clkspec.args_count = 1;
+		clkspec.args[0] = index;
+
+		clk = of_clk_get_from_provider(&clkspec);
+		if (IS_ERR(clk)) {
+			pr_err("clk: couldn't get clock %u for %s\n",
+				index, node->full_name);
+			return PTR_ERR(clk);
+		}
+
+		clk_init_critical(clk);
+
+		ret = clk_prepare_enable(clk);
+		if (ret) {
+			pr_err("Failed to enable clock %u for %s: %d\n",
+			       index, node->full_name, ret);
+			return ret;
+		}
+
+		pr_debug("Setting clock as critical %pC\n", clk);
+	}
+
+	return 0;
+}
+
 /**
  * of_clk_set_defaults() - parse and set assigned clocks configuration
  * @node: device node to apply clock settings for
@@ -139,6 +178,10 @@ int of_clk_set_defaults(struct device_node *node, bool clk_supplier)
 	if (rc < 0)
 		return rc;
 
-	return __set_clk_rates(node, clk_supplier);
+	rc = __set_clk_rates(node, clk_supplier);
+	if (rc < 0)
+		return rc;
+
+	return __set_critical_clocks(node, clk_supplier);
 }
 EXPORT_SYMBOL_GPL(of_clk_set_defaults);
-- 
1.9.1

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

* [PATCH v7 5/5] clk: dt: Introduce binding for critical clock support
  2015-07-22 13:04 ` Lee Jones
  (?)
@ 2015-07-22 13:04   ` Lee Jones
  -1 siblings, 0 replies; 93+ messages in thread
From: Lee Jones @ 2015-07-22 13:04 UTC (permalink / raw)
  To: linux-arm-kernel, linux-kernel
  Cc: kernel, mturquette, sboyd, devicetree, geert, maxime.ripard,
	s.hauer, Lee Jones

Signed-off-by: Lee Jones <lee.jones@linaro.org>
---
 .../devicetree/bindings/clock/clock-bindings.txt   | 39 ++++++++++++++++++++++
 1 file changed, 39 insertions(+)

diff --git a/Documentation/devicetree/bindings/clock/clock-bindings.txt b/Documentation/devicetree/bindings/clock/clock-bindings.txt
index 06fc6d5..4137034 100644
--- a/Documentation/devicetree/bindings/clock/clock-bindings.txt
+++ b/Documentation/devicetree/bindings/clock/clock-bindings.txt
@@ -44,6 +44,45 @@ For example:
   clocks by index. The names should reflect the clock output signal
   names for the device.
 
+critical-clock:	Some hardware contains bunches of clocks which, in normal
+		circumstances, must never be turned off.  If drivers a) fail to
+		obtain a reference to any of these or b) give up a previously
+		obtained reference during suspend, it is possible that some
+		Operating Systems might attempt to disable them to save power.
+		If this happens a platform can fail irrecoverably as a result.
+		Usually the only way to recover from these failures is to
+		reboot.
+
+		To avoid either of these two scenarios from catastrophically
+		disabling an otherwise perfectly healthy running system,
+		clocks can be identified as 'critical' using this property from
+		inside a clocksource's node.
+
+		This property is not to be abused.  It is only to be used to
+		protect platforms from being crippled by gated clocks, NOT as a
+		convenience function to avoid using the framework correctly
+		inside device drivers.
+
+		Expected values are hardware clock indices.  If the
+		clock-indices property (see below) is used, then supplied
+		values must correspond to one of the listed identifiers.
+		Using the clock-indices example below, hardware clock <2>
+		is missing, therefore it is considered invalid to then
+		list clock <2> as a critical clock.
+
+For example:
+
+    oscillator {
+	#clock-cells = <1>;
+	clock-output-names = "ckil", "ckih";
+	critical-clock = <0>, <1>;
+    };
+
+- this node defines a device with two clock outputs, just as in the
+  example above.  The only difference being that 'ckil' and 'ckih'
+  are now identified as an critical clocks, so an OS will know to
+  never attempt to gate them.
+
 clock-indices:	   If the identifying number for the clocks in the node
 		   is not linear from zero, then this allows the mapping of
 		   identifiers into the clock-output-names array.
-- 
1.9.1


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

* [PATCH v7 5/5] clk: dt: Introduce binding for critical clock support
@ 2015-07-22 13:04   ` Lee Jones
  0 siblings, 0 replies; 93+ messages in thread
From: Lee Jones @ 2015-07-22 13:04 UTC (permalink / raw)
  To: linux-arm-kernel, linux-kernel
  Cc: devicetree, mturquette, kernel, s.hauer, sboyd, geert,
	maxime.ripard, Lee Jones

Signed-off-by: Lee Jones <lee.jones@linaro.org>
---
 .../devicetree/bindings/clock/clock-bindings.txt   | 39 ++++++++++++++++++++++
 1 file changed, 39 insertions(+)

diff --git a/Documentation/devicetree/bindings/clock/clock-bindings.txt b/Documentation/devicetree/bindings/clock/clock-bindings.txt
index 06fc6d5..4137034 100644
--- a/Documentation/devicetree/bindings/clock/clock-bindings.txt
+++ b/Documentation/devicetree/bindings/clock/clock-bindings.txt
@@ -44,6 +44,45 @@ For example:
   clocks by index. The names should reflect the clock output signal
   names for the device.
 
+critical-clock:	Some hardware contains bunches of clocks which, in normal
+		circumstances, must never be turned off.  If drivers a) fail to
+		obtain a reference to any of these or b) give up a previously
+		obtained reference during suspend, it is possible that some
+		Operating Systems might attempt to disable them to save power.
+		If this happens a platform can fail irrecoverably as a result.
+		Usually the only way to recover from these failures is to
+		reboot.
+
+		To avoid either of these two scenarios from catastrophically
+		disabling an otherwise perfectly healthy running system,
+		clocks can be identified as 'critical' using this property from
+		inside a clocksource's node.
+
+		This property is not to be abused.  It is only to be used to
+		protect platforms from being crippled by gated clocks, NOT as a
+		convenience function to avoid using the framework correctly
+		inside device drivers.
+
+		Expected values are hardware clock indices.  If the
+		clock-indices property (see below) is used, then supplied
+		values must correspond to one of the listed identifiers.
+		Using the clock-indices example below, hardware clock <2>
+		is missing, therefore it is considered invalid to then
+		list clock <2> as a critical clock.
+
+For example:
+
+    oscillator {
+	#clock-cells = <1>;
+	clock-output-names = "ckil", "ckih";
+	critical-clock = <0>, <1>;
+    };
+
+- this node defines a device with two clock outputs, just as in the
+  example above.  The only difference being that 'ckil' and 'ckih'
+  are now identified as an critical clocks, so an OS will know to
+  never attempt to gate them.
+
 clock-indices:	   If the identifying number for the clocks in the node
 		   is not linear from zero, then this allows the mapping of
 		   identifiers into the clock-output-names array.
-- 
1.9.1

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

* [PATCH v7 5/5] clk: dt: Introduce binding for critical clock support
@ 2015-07-22 13:04   ` Lee Jones
  0 siblings, 0 replies; 93+ messages in thread
From: Lee Jones @ 2015-07-22 13:04 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Lee Jones <lee.jones@linaro.org>
---
 .../devicetree/bindings/clock/clock-bindings.txt   | 39 ++++++++++++++++++++++
 1 file changed, 39 insertions(+)

diff --git a/Documentation/devicetree/bindings/clock/clock-bindings.txt b/Documentation/devicetree/bindings/clock/clock-bindings.txt
index 06fc6d5..4137034 100644
--- a/Documentation/devicetree/bindings/clock/clock-bindings.txt
+++ b/Documentation/devicetree/bindings/clock/clock-bindings.txt
@@ -44,6 +44,45 @@ For example:
   clocks by index. The names should reflect the clock output signal
   names for the device.
 
+critical-clock:	Some hardware contains bunches of clocks which, in normal
+		circumstances, must never be turned off.  If drivers a) fail to
+		obtain a reference to any of these or b) give up a previously
+		obtained reference during suspend, it is possible that some
+		Operating Systems might attempt to disable them to save power.
+		If this happens a platform can fail irrecoverably as a result.
+		Usually the only way to recover from these failures is to
+		reboot.
+
+		To avoid either of these two scenarios from catastrophically
+		disabling an otherwise perfectly healthy running system,
+		clocks can be identified as 'critical' using this property from
+		inside a clocksource's node.
+
+		This property is not to be abused.  It is only to be used to
+		protect platforms from being crippled by gated clocks, NOT as a
+		convenience function to avoid using the framework correctly
+		inside device drivers.
+
+		Expected values are hardware clock indices.  If the
+		clock-indices property (see below) is used, then supplied
+		values must correspond to one of the listed identifiers.
+		Using the clock-indices example below, hardware clock <2>
+		is missing, therefore it is considered invalid to then
+		list clock <2> as a critical clock.
+
+For example:
+
+    oscillator {
+	#clock-cells = <1>;
+	clock-output-names = "ckil", "ckih";
+	critical-clock = <0>, <1>;
+    };
+
+- this node defines a device with two clock outputs, just as in the
+  example above.  The only difference being that 'ckil' and 'ckih'
+  are now identified as an critical clocks, so an OS will know to
+  never attempt to gate them.
+
 clock-indices:	   If the identifying number for the clocks in the node
 		   is not linear from zero, then this allows the mapping of
 		   identifiers into the clock-output-names array.
-- 
1.9.1

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

* Re: [PATCH v7 5/5] clk: dt: Introduce binding for critical clock support
  2015-07-22 13:04   ` Lee Jones
@ 2015-07-27  7:10     ` Maxime Ripard
  -1 siblings, 0 replies; 93+ messages in thread
From: Maxime Ripard @ 2015-07-27  7:10 UTC (permalink / raw)
  To: Lee Jones
  Cc: linux-arm-kernel, linux-kernel, kernel, mturquette, sboyd,
	devicetree, geert, s.hauer

[-- Attachment #1: Type: text/plain, Size: 2447 bytes --]

Hi Lee,

On Wed, Jul 22, 2015 at 02:04:15PM +0100, Lee Jones wrote:
> Signed-off-by: Lee Jones <lee.jones@linaro.org>
> ---
>  .../devicetree/bindings/clock/clock-bindings.txt   | 39 ++++++++++++++++++++++
>  1 file changed, 39 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/clock/clock-bindings.txt b/Documentation/devicetree/bindings/clock/clock-bindings.txt
> index 06fc6d5..4137034 100644
> --- a/Documentation/devicetree/bindings/clock/clock-bindings.txt
> +++ b/Documentation/devicetree/bindings/clock/clock-bindings.txt
> @@ -44,6 +44,45 @@ For example:
>    clocks by index. The names should reflect the clock output signal
>    names for the device.
>  
> +critical-clock:	Some hardware contains bunches of clocks which, in normal
> +		circumstances, must never be turned off.  If drivers a) fail to
> +		obtain a reference to any of these or b) give up a previously
> +		obtained reference during suspend, it is possible that some
> +		Operating Systems might attempt to disable them to save power.
> +		If this happens a platform can fail irrecoverably as a result.
> +		Usually the only way to recover from these failures is to
> +		reboot.
> +
> +		To avoid either of these two scenarios from catastrophically
> +		disabling an otherwise perfectly healthy running system,
> +		clocks can be identified as 'critical' using this property from
> +		inside a clocksource's node.
> +
> +		This property is not to be abused.  It is only to be used to
> +		protect platforms from being crippled by gated clocks, NOT as a
> +		convenience function to avoid using the framework correctly
> +		inside device drivers.
> +
> +		Expected values are hardware clock indices.  If the
> +		clock-indices property (see below) is used, then supplied
> +		values must correspond to one of the listed identifiers.
> +		Using the clock-indices example below, hardware clock <2>
> +		is missing, therefore it is considered invalid to then
> +		list clock <2> as a critical clock.

I think we should also consider having it simply as a boolean. Using
indices for clocks that don't have any (for example because it only
provides a single clock) seem to not really make much sense.

Also, since you can have a bunch of them, using critical-clocks seem
more appropriate.

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

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

* [PATCH v7 5/5] clk: dt: Introduce binding for critical clock support
@ 2015-07-27  7:10     ` Maxime Ripard
  0 siblings, 0 replies; 93+ messages in thread
From: Maxime Ripard @ 2015-07-27  7:10 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Lee,

On Wed, Jul 22, 2015 at 02:04:15PM +0100, Lee Jones wrote:
> Signed-off-by: Lee Jones <lee.jones@linaro.org>
> ---
>  .../devicetree/bindings/clock/clock-bindings.txt   | 39 ++++++++++++++++++++++
>  1 file changed, 39 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/clock/clock-bindings.txt b/Documentation/devicetree/bindings/clock/clock-bindings.txt
> index 06fc6d5..4137034 100644
> --- a/Documentation/devicetree/bindings/clock/clock-bindings.txt
> +++ b/Documentation/devicetree/bindings/clock/clock-bindings.txt
> @@ -44,6 +44,45 @@ For example:
>    clocks by index. The names should reflect the clock output signal
>    names for the device.
>  
> +critical-clock:	Some hardware contains bunches of clocks which, in normal
> +		circumstances, must never be turned off.  If drivers a) fail to
> +		obtain a reference to any of these or b) give up a previously
> +		obtained reference during suspend, it is possible that some
> +		Operating Systems might attempt to disable them to save power.
> +		If this happens a platform can fail irrecoverably as a result.
> +		Usually the only way to recover from these failures is to
> +		reboot.
> +
> +		To avoid either of these two scenarios from catastrophically
> +		disabling an otherwise perfectly healthy running system,
> +		clocks can be identified as 'critical' using this property from
> +		inside a clocksource's node.
> +
> +		This property is not to be abused.  It is only to be used to
> +		protect platforms from being crippled by gated clocks, NOT as a
> +		convenience function to avoid using the framework correctly
> +		inside device drivers.
> +
> +		Expected values are hardware clock indices.  If the
> +		clock-indices property (see below) is used, then supplied
> +		values must correspond to one of the listed identifiers.
> +		Using the clock-indices example below, hardware clock <2>
> +		is missing, therefore it is considered invalid to then
> +		list clock <2> as a critical clock.

I think we should also consider having it simply as a boolean. Using
indices for clocks that don't have any (for example because it only
provides a single clock) seem to not really make much sense.

Also, since you can have a bunch of them, using critical-clocks seem
more appropriate.

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20150727/752ad1cd/attachment.sig>

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

* Re: [PATCH v7 3/5] clk: Supply the critical clock {init, enable, disable} framework
@ 2015-07-27  7:25     ` Maxime Ripard
  0 siblings, 0 replies; 93+ messages in thread
From: Maxime Ripard @ 2015-07-27  7:25 UTC (permalink / raw)
  To: Lee Jones
  Cc: linux-arm-kernel, linux-kernel, kernel, mturquette, sboyd,
	devicetree, geert, s.hauer

[-- Attachment #1: Type: text/plain, Size: 2566 bytes --]

On Wed, Jul 22, 2015 at 02:04:13PM +0100, Lee Jones wrote:
> These new API calls will firstly provide a mechanisms to tag a clock as
> critical and secondly allow any knowledgeable driver to (un)gate clocks,
> even if they are marked as critical.
> 
> Suggested-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> Signed-off-by: Lee Jones <lee.jones@linaro.org>
> ---
>  drivers/clk/clk.c            | 45 ++++++++++++++++++++++++++++++++++++++++++++
>  include/linux/clk-provider.h |  2 ++
>  include/linux/clk.h          | 30 +++++++++++++++++++++++++++++
>  3 files changed, 77 insertions(+)
> 
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> index 61c3fc5..486b1da 100644
> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> @@ -46,6 +46,21 @@ static struct clk_core *clk_core_lookup(const char *name);
>  
>  /***    private data structures    ***/
>  
> +/**
> + * struct critical -	Provides 'play' over critical clocks.  A clock can be
> + *			marked as critical, meaning that it should not be
> + *			disabled.  However, if a driver which is aware of the
> + *			critical behaviour wants to control it, it can do so
> + *			using clk_enable_critical() and clk_disable_critical().
> + *
> + * @enabled	Is clock critical?  Once set, doesn't change
> + * @leave_on	Self explanatory.  Can be disabled by knowledgeable drivers
> + */
> +struct critical {
> +	bool enabled;
> +	bool leave_on;
> +};
> +
>  struct clk_core {
>  	const char		*name;
>  	const struct clk_ops	*ops;
> @@ -75,6 +90,7 @@ struct clk_core {
>  	struct dentry		*dentry;
>  #endif
>  	struct kref		ref;
> +	struct critical		critical;
>  };
>  
>  struct clk {
> @@ -995,6 +1011,10 @@ static void clk_core_disable(struct clk_core *clk)
>  	if (WARN_ON(clk->enable_count == 0))
>  		return;
>  
> +	/* Refuse to turn off a critical clock */
> +	if (clk->enable_count == 1 && clk->critical.leave_on)
> +		return;
> +

I think it should be handled by a separate counting. Otherwise, if you
have two users that marked the clock as critical, and then one of them
disable it...

>  	if (--clk->enable_count > 0)
>  		return;
>  
> @@ -1037,6 +1057,13 @@ void clk_disable(struct clk *clk)
>  }
>  EXPORT_SYMBOL_GPL(clk_disable);
>  
> +void clk_disable_critical(struct clk *clk)
> +{
> +	clk->core->critical.leave_on = false;

.. you just lost the fact that it was critical in the first place.

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

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

* Re: [PATCH v7 3/5] clk: Supply the critical clock {init, enable, disable} framework
@ 2015-07-27  7:25     ` Maxime Ripard
  0 siblings, 0 replies; 93+ messages in thread
From: Maxime Ripard @ 2015-07-27  7:25 UTC (permalink / raw)
  To: Lee Jones
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	kernel-F5mvAk5X5gdBDgjK7y7TUQ, mturquette-QSEj5FYQhm4dnm+yROfE0A,
	sboyd-sgV2jX0FEOL9JmXXK+q4OQ, devicetree-u79uwXL29TY76Z2rM5mHXA,
	geert-Td1EMuHUCqxL1ZNQvxDV9g, s.hauer-bIcnvbaLZ9MEGnE8C9+IrQ

[-- Attachment #1: Type: text/plain, Size: 2626 bytes --]

On Wed, Jul 22, 2015 at 02:04:13PM +0100, Lee Jones wrote:
> These new API calls will firstly provide a mechanisms to tag a clock as
> critical and secondly allow any knowledgeable driver to (un)gate clocks,
> even if they are marked as critical.
> 
> Suggested-by: Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
> Signed-off-by: Lee Jones <lee.jones-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> ---
>  drivers/clk/clk.c            | 45 ++++++++++++++++++++++++++++++++++++++++++++
>  include/linux/clk-provider.h |  2 ++
>  include/linux/clk.h          | 30 +++++++++++++++++++++++++++++
>  3 files changed, 77 insertions(+)
> 
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> index 61c3fc5..486b1da 100644
> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> @@ -46,6 +46,21 @@ static struct clk_core *clk_core_lookup(const char *name);
>  
>  /***    private data structures    ***/
>  
> +/**
> + * struct critical -	Provides 'play' over critical clocks.  A clock can be
> + *			marked as critical, meaning that it should not be
> + *			disabled.  However, if a driver which is aware of the
> + *			critical behaviour wants to control it, it can do so
> + *			using clk_enable_critical() and clk_disable_critical().
> + *
> + * @enabled	Is clock critical?  Once set, doesn't change
> + * @leave_on	Self explanatory.  Can be disabled by knowledgeable drivers
> + */
> +struct critical {
> +	bool enabled;
> +	bool leave_on;
> +};
> +
>  struct clk_core {
>  	const char		*name;
>  	const struct clk_ops	*ops;
> @@ -75,6 +90,7 @@ struct clk_core {
>  	struct dentry		*dentry;
>  #endif
>  	struct kref		ref;
> +	struct critical		critical;
>  };
>  
>  struct clk {
> @@ -995,6 +1011,10 @@ static void clk_core_disable(struct clk_core *clk)
>  	if (WARN_ON(clk->enable_count == 0))
>  		return;
>  
> +	/* Refuse to turn off a critical clock */
> +	if (clk->enable_count == 1 && clk->critical.leave_on)
> +		return;
> +

I think it should be handled by a separate counting. Otherwise, if you
have two users that marked the clock as critical, and then one of them
disable it...

>  	if (--clk->enable_count > 0)
>  		return;
>  
> @@ -1037,6 +1057,13 @@ void clk_disable(struct clk *clk)
>  }
>  EXPORT_SYMBOL_GPL(clk_disable);
>  
> +void clk_disable_critical(struct clk *clk)
> +{
> +	clk->core->critical.leave_on = false;

.. you just lost the fact that it was critical in the first place.

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

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

* [PATCH v7 3/5] clk: Supply the critical clock {init, enable, disable} framework
@ 2015-07-27  7:25     ` Maxime Ripard
  0 siblings, 0 replies; 93+ messages in thread
From: Maxime Ripard @ 2015-07-27  7:25 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Jul 22, 2015 at 02:04:13PM +0100, Lee Jones wrote:
> These new API calls will firstly provide a mechanisms to tag a clock as
> critical and secondly allow any knowledgeable driver to (un)gate clocks,
> even if they are marked as critical.
> 
> Suggested-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> Signed-off-by: Lee Jones <lee.jones@linaro.org>
> ---
>  drivers/clk/clk.c            | 45 ++++++++++++++++++++++++++++++++++++++++++++
>  include/linux/clk-provider.h |  2 ++
>  include/linux/clk.h          | 30 +++++++++++++++++++++++++++++
>  3 files changed, 77 insertions(+)
> 
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> index 61c3fc5..486b1da 100644
> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> @@ -46,6 +46,21 @@ static struct clk_core *clk_core_lookup(const char *name);
>  
>  /***    private data structures    ***/
>  
> +/**
> + * struct critical -	Provides 'play' over critical clocks.  A clock can be
> + *			marked as critical, meaning that it should not be
> + *			disabled.  However, if a driver which is aware of the
> + *			critical behaviour wants to control it, it can do so
> + *			using clk_enable_critical() and clk_disable_critical().
> + *
> + * @enabled	Is clock critical?  Once set, doesn't change
> + * @leave_on	Self explanatory.  Can be disabled by knowledgeable drivers
> + */
> +struct critical {
> +	bool enabled;
> +	bool leave_on;
> +};
> +
>  struct clk_core {
>  	const char		*name;
>  	const struct clk_ops	*ops;
> @@ -75,6 +90,7 @@ struct clk_core {
>  	struct dentry		*dentry;
>  #endif
>  	struct kref		ref;
> +	struct critical		critical;
>  };
>  
>  struct clk {
> @@ -995,6 +1011,10 @@ static void clk_core_disable(struct clk_core *clk)
>  	if (WARN_ON(clk->enable_count == 0))
>  		return;
>  
> +	/* Refuse to turn off a critical clock */
> +	if (clk->enable_count == 1 && clk->critical.leave_on)
> +		return;
> +

I think it should be handled by a separate counting. Otherwise, if you
have two users that marked the clock as critical, and then one of them
disable it...

>  	if (--clk->enable_count > 0)
>  		return;
>  
> @@ -1037,6 +1057,13 @@ void clk_disable(struct clk *clk)
>  }
>  EXPORT_SYMBOL_GPL(clk_disable);
>  
> +void clk_disable_critical(struct clk *clk)
> +{
> +	clk->core->critical.leave_on = false;

.. you just lost the fact that it was critical in the first place.

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20150727/ee6145cd/attachment.sig>

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

* Re: [PATCH v7 5/5] clk: dt: Introduce binding for critical clock support
  2015-07-27  7:10     ` Maxime Ripard
@ 2015-07-27  7:31       ` Lee Jones
  -1 siblings, 0 replies; 93+ messages in thread
From: Lee Jones @ 2015-07-27  7:31 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: linux-arm-kernel, linux-kernel, kernel, mturquette, sboyd,
	devicetree, geert, s.hauer

On Mon, 27 Jul 2015, Maxime Ripard wrote:

> Hi Lee,
> 
> On Wed, Jul 22, 2015 at 02:04:15PM +0100, Lee Jones wrote:
> > Signed-off-by: Lee Jones <lee.jones@linaro.org>
> > ---
> >  .../devicetree/bindings/clock/clock-bindings.txt   | 39 ++++++++++++++++++++++
> >  1 file changed, 39 insertions(+)
> > 
> > diff --git a/Documentation/devicetree/bindings/clock/clock-bindings.txt b/Documentation/devicetree/bindings/clock/clock-bindings.txt
> > index 06fc6d5..4137034 100644
> > --- a/Documentation/devicetree/bindings/clock/clock-bindings.txt
> > +++ b/Documentation/devicetree/bindings/clock/clock-bindings.txt
> > @@ -44,6 +44,45 @@ For example:
> >    clocks by index. The names should reflect the clock output signal
> >    names for the device.
> >  
> > +critical-clock:	Some hardware contains bunches of clocks which, in normal
> > +		circumstances, must never be turned off.  If drivers a) fail to
> > +		obtain a reference to any of these or b) give up a previously
> > +		obtained reference during suspend, it is possible that some
> > +		Operating Systems might attempt to disable them to save power.
> > +		If this happens a platform can fail irrecoverably as a result.
> > +		Usually the only way to recover from these failures is to
> > +		reboot.
> > +
> > +		To avoid either of these two scenarios from catastrophically
> > +		disabling an otherwise perfectly healthy running system,
> > +		clocks can be identified as 'critical' using this property from
> > +		inside a clocksource's node.
> > +
> > +		This property is not to be abused.  It is only to be used to
> > +		protect platforms from being crippled by gated clocks, NOT as a
> > +		convenience function to avoid using the framework correctly
> > +		inside device drivers.
> > +
> > +		Expected values are hardware clock indices.  If the
> > +		clock-indices property (see below) is used, then supplied
> > +		values must correspond to one of the listed identifiers.
> > +		Using the clock-indices example below, hardware clock <2>
> > +		is missing, therefore it is considered invalid to then
> > +		list clock <2> as a critical clock.
> 
> I think we should also consider having it simply as a boolean. Using
> indices for clocks that don't have any (for example because it only
> provides a single clock) seem to not really make much sense.

Then how would you distinguish between the clocks if the provider
provides more than a single clock?

> Also, since you can have a bunch of them, using critical-clocks seem
> more appropriate.

I can change the name to critical-clocks, no problem.

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

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

* [PATCH v7 5/5] clk: dt: Introduce binding for critical clock support
@ 2015-07-27  7:31       ` Lee Jones
  0 siblings, 0 replies; 93+ messages in thread
From: Lee Jones @ 2015-07-27  7:31 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, 27 Jul 2015, Maxime Ripard wrote:

> Hi Lee,
> 
> On Wed, Jul 22, 2015 at 02:04:15PM +0100, Lee Jones wrote:
> > Signed-off-by: Lee Jones <lee.jones@linaro.org>
> > ---
> >  .../devicetree/bindings/clock/clock-bindings.txt   | 39 ++++++++++++++++++++++
> >  1 file changed, 39 insertions(+)
> > 
> > diff --git a/Documentation/devicetree/bindings/clock/clock-bindings.txt b/Documentation/devicetree/bindings/clock/clock-bindings.txt
> > index 06fc6d5..4137034 100644
> > --- a/Documentation/devicetree/bindings/clock/clock-bindings.txt
> > +++ b/Documentation/devicetree/bindings/clock/clock-bindings.txt
> > @@ -44,6 +44,45 @@ For example:
> >    clocks by index. The names should reflect the clock output signal
> >    names for the device.
> >  
> > +critical-clock:	Some hardware contains bunches of clocks which, in normal
> > +		circumstances, must never be turned off.  If drivers a) fail to
> > +		obtain a reference to any of these or b) give up a previously
> > +		obtained reference during suspend, it is possible that some
> > +		Operating Systems might attempt to disable them to save power.
> > +		If this happens a platform can fail irrecoverably as a result.
> > +		Usually the only way to recover from these failures is to
> > +		reboot.
> > +
> > +		To avoid either of these two scenarios from catastrophically
> > +		disabling an otherwise perfectly healthy running system,
> > +		clocks can be identified as 'critical' using this property from
> > +		inside a clocksource's node.
> > +
> > +		This property is not to be abused.  It is only to be used to
> > +		protect platforms from being crippled by gated clocks, NOT as a
> > +		convenience function to avoid using the framework correctly
> > +		inside device drivers.
> > +
> > +		Expected values are hardware clock indices.  If the
> > +		clock-indices property (see below) is used, then supplied
> > +		values must correspond to one of the listed identifiers.
> > +		Using the clock-indices example below, hardware clock <2>
> > +		is missing, therefore it is considered invalid to then
> > +		list clock <2> as a critical clock.
> 
> I think we should also consider having it simply as a boolean. Using
> indices for clocks that don't have any (for example because it only
> provides a single clock) seem to not really make much sense.

Then how would you distinguish between the clocks if the provider
provides more than a single clock?

> Also, since you can have a bunch of them, using critical-clocks seem
> more appropriate.

I can change the name to critical-clocks, no problem.

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org ? Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

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

* Re: [PATCH v7 3/5] clk: Supply the critical clock {init, enable, disable} framework
  2015-07-27  7:25     ` Maxime Ripard
  (?)
@ 2015-07-27  8:53       ` Lee Jones
  -1 siblings, 0 replies; 93+ messages in thread
From: Lee Jones @ 2015-07-27  8:53 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: linux-arm-kernel, linux-kernel, kernel, mturquette, sboyd,
	devicetree, geert, s.hauer

On Mon, 27 Jul 2015, Maxime Ripard wrote:

> On Wed, Jul 22, 2015 at 02:04:13PM +0100, Lee Jones wrote:
> > These new API calls will firstly provide a mechanisms to tag a clock as
> > critical and secondly allow any knowledgeable driver to (un)gate clocks,
> > even if they are marked as critical.
> > 
> > Suggested-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> > Signed-off-by: Lee Jones <lee.jones@linaro.org>
> > ---
> >  drivers/clk/clk.c            | 45 ++++++++++++++++++++++++++++++++++++++++++++
> >  include/linux/clk-provider.h |  2 ++
> >  include/linux/clk.h          | 30 +++++++++++++++++++++++++++++
> >  3 files changed, 77 insertions(+)
> > 
> > diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> > index 61c3fc5..486b1da 100644
> > --- a/drivers/clk/clk.c
> > +++ b/drivers/clk/clk.c
> > @@ -46,6 +46,21 @@ static struct clk_core *clk_core_lookup(const char *name);
> >  
> >  /***    private data structures    ***/
> >  
> > +/**
> > + * struct critical -	Provides 'play' over critical clocks.  A clock can be
> > + *			marked as critical, meaning that it should not be
> > + *			disabled.  However, if a driver which is aware of the
> > + *			critical behaviour wants to control it, it can do so
> > + *			using clk_enable_critical() and clk_disable_critical().
> > + *
> > + * @enabled	Is clock critical?  Once set, doesn't change
> > + * @leave_on	Self explanatory.  Can be disabled by knowledgeable drivers
> > + */
> > +struct critical {
> > +	bool enabled;
> > +	bool leave_on;
> > +};
> > +
> >  struct clk_core {
> >  	const char		*name;
> >  	const struct clk_ops	*ops;
> > @@ -75,6 +90,7 @@ struct clk_core {
> >  	struct dentry		*dentry;
> >  #endif
> >  	struct kref		ref;
> > +	struct critical		critical;
> >  };
> >  
> >  struct clk {
> > @@ -995,6 +1011,10 @@ static void clk_core_disable(struct clk_core *clk)
> >  	if (WARN_ON(clk->enable_count == 0))
> >  		return;
> >  
> > +	/* Refuse to turn off a critical clock */
> > +	if (clk->enable_count == 1 && clk->critical.leave_on)
> > +		return;
> > +
> 
> I think it should be handled by a separate counting. Otherwise, if you
> have two users that marked the clock as critical, and then one of them
> disable it...
> 
> >  	if (--clk->enable_count > 0)
> >  		return;
> >  
> > @@ -1037,6 +1057,13 @@ void clk_disable(struct clk *clk)
> >  }
> >  EXPORT_SYMBOL_GPL(clk_disable);
> >  
> > +void clk_disable_critical(struct clk *clk)
> > +{
> > +	clk->core->critical.leave_on = false;
> 
> .. you just lost the fact that it was critical in the first place.

I thought about both of these points, which is why I came up with this
strategy.

Any device which uses the *_critical() API should a) have knowledge of
what happens when a particular critical clock is gated and b) have
thought about the consequences.  I don't think we can use reference
counting, because we'd need as many critical clock owners as there are
critical clocks.  Cast your mind back to the reasons for this critical
clock API.  One of the most important intentions of this API is the
requirement mitigation for each of the critical clocks to have an owner
(driver).

With regards to your second point, that's what 'critical.enabled'
is for.  Take a look at clk_enable_critical().

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

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

* Re: [PATCH v7 3/5] clk: Supply the critical clock {init, enable, disable} framework
@ 2015-07-27  8:53       ` Lee Jones
  0 siblings, 0 replies; 93+ messages in thread
From: Lee Jones @ 2015-07-27  8:53 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	kernel-F5mvAk5X5gdBDgjK7y7TUQ, mturquette-QSEj5FYQhm4dnm+yROfE0A,
	sboyd-sgV2jX0FEOL9JmXXK+q4OQ, devicetree-u79uwXL29TY76Z2rM5mHXA,
	geert-Td1EMuHUCqxL1ZNQvxDV9g, s.hauer-bIcnvbaLZ9MEGnE8C9+IrQ

On Mon, 27 Jul 2015, Maxime Ripard wrote:

> On Wed, Jul 22, 2015 at 02:04:13PM +0100, Lee Jones wrote:
> > These new API calls will firstly provide a mechanisms to tag a clock as
> > critical and secondly allow any knowledgeable driver to (un)gate clocks,
> > even if they are marked as critical.
> > 
> > Suggested-by: Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
> > Signed-off-by: Lee Jones <lee.jones-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> > ---
> >  drivers/clk/clk.c            | 45 ++++++++++++++++++++++++++++++++++++++++++++
> >  include/linux/clk-provider.h |  2 ++
> >  include/linux/clk.h          | 30 +++++++++++++++++++++++++++++
> >  3 files changed, 77 insertions(+)
> > 
> > diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> > index 61c3fc5..486b1da 100644
> > --- a/drivers/clk/clk.c
> > +++ b/drivers/clk/clk.c
> > @@ -46,6 +46,21 @@ static struct clk_core *clk_core_lookup(const char *name);
> >  
> >  /***    private data structures    ***/
> >  
> > +/**
> > + * struct critical -	Provides 'play' over critical clocks.  A clock can be
> > + *			marked as critical, meaning that it should not be
> > + *			disabled.  However, if a driver which is aware of the
> > + *			critical behaviour wants to control it, it can do so
> > + *			using clk_enable_critical() and clk_disable_critical().
> > + *
> > + * @enabled	Is clock critical?  Once set, doesn't change
> > + * @leave_on	Self explanatory.  Can be disabled by knowledgeable drivers
> > + */
> > +struct critical {
> > +	bool enabled;
> > +	bool leave_on;
> > +};
> > +
> >  struct clk_core {
> >  	const char		*name;
> >  	const struct clk_ops	*ops;
> > @@ -75,6 +90,7 @@ struct clk_core {
> >  	struct dentry		*dentry;
> >  #endif
> >  	struct kref		ref;
> > +	struct critical		critical;
> >  };
> >  
> >  struct clk {
> > @@ -995,6 +1011,10 @@ static void clk_core_disable(struct clk_core *clk)
> >  	if (WARN_ON(clk->enable_count == 0))
> >  		return;
> >  
> > +	/* Refuse to turn off a critical clock */
> > +	if (clk->enable_count == 1 && clk->critical.leave_on)
> > +		return;
> > +
> 
> I think it should be handled by a separate counting. Otherwise, if you
> have two users that marked the clock as critical, and then one of them
> disable it...
> 
> >  	if (--clk->enable_count > 0)
> >  		return;
> >  
> > @@ -1037,6 +1057,13 @@ void clk_disable(struct clk *clk)
> >  }
> >  EXPORT_SYMBOL_GPL(clk_disable);
> >  
> > +void clk_disable_critical(struct clk *clk)
> > +{
> > +	clk->core->critical.leave_on = false;
> 
> .. you just lost the fact that it was critical in the first place.

I thought about both of these points, which is why I came up with this
strategy.

Any device which uses the *_critical() API should a) have knowledge of
what happens when a particular critical clock is gated and b) have
thought about the consequences.  I don't think we can use reference
counting, because we'd need as many critical clock owners as there are
critical clocks.  Cast your mind back to the reasons for this critical
clock API.  One of the most important intentions of this API is the
requirement mitigation for each of the critical clocks to have an owner
(driver).

With regards to your second point, that's what 'critical.enabled'
is for.  Take a look at clk_enable_critical().

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH v7 3/5] clk: Supply the critical clock {init, enable, disable} framework
@ 2015-07-27  8:53       ` Lee Jones
  0 siblings, 0 replies; 93+ messages in thread
From: Lee Jones @ 2015-07-27  8:53 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, 27 Jul 2015, Maxime Ripard wrote:

> On Wed, Jul 22, 2015 at 02:04:13PM +0100, Lee Jones wrote:
> > These new API calls will firstly provide a mechanisms to tag a clock as
> > critical and secondly allow any knowledgeable driver to (un)gate clocks,
> > even if they are marked as critical.
> > 
> > Suggested-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> > Signed-off-by: Lee Jones <lee.jones@linaro.org>
> > ---
> >  drivers/clk/clk.c            | 45 ++++++++++++++++++++++++++++++++++++++++++++
> >  include/linux/clk-provider.h |  2 ++
> >  include/linux/clk.h          | 30 +++++++++++++++++++++++++++++
> >  3 files changed, 77 insertions(+)
> > 
> > diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> > index 61c3fc5..486b1da 100644
> > --- a/drivers/clk/clk.c
> > +++ b/drivers/clk/clk.c
> > @@ -46,6 +46,21 @@ static struct clk_core *clk_core_lookup(const char *name);
> >  
> >  /***    private data structures    ***/
> >  
> > +/**
> > + * struct critical -	Provides 'play' over critical clocks.  A clock can be
> > + *			marked as critical, meaning that it should not be
> > + *			disabled.  However, if a driver which is aware of the
> > + *			critical behaviour wants to control it, it can do so
> > + *			using clk_enable_critical() and clk_disable_critical().
> > + *
> > + * @enabled	Is clock critical?  Once set, doesn't change
> > + * @leave_on	Self explanatory.  Can be disabled by knowledgeable drivers
> > + */
> > +struct critical {
> > +	bool enabled;
> > +	bool leave_on;
> > +};
> > +
> >  struct clk_core {
> >  	const char		*name;
> >  	const struct clk_ops	*ops;
> > @@ -75,6 +90,7 @@ struct clk_core {
> >  	struct dentry		*dentry;
> >  #endif
> >  	struct kref		ref;
> > +	struct critical		critical;
> >  };
> >  
> >  struct clk {
> > @@ -995,6 +1011,10 @@ static void clk_core_disable(struct clk_core *clk)
> >  	if (WARN_ON(clk->enable_count == 0))
> >  		return;
> >  
> > +	/* Refuse to turn off a critical clock */
> > +	if (clk->enable_count == 1 && clk->critical.leave_on)
> > +		return;
> > +
> 
> I think it should be handled by a separate counting. Otherwise, if you
> have two users that marked the clock as critical, and then one of them
> disable it...
> 
> >  	if (--clk->enable_count > 0)
> >  		return;
> >  
> > @@ -1037,6 +1057,13 @@ void clk_disable(struct clk *clk)
> >  }
> >  EXPORT_SYMBOL_GPL(clk_disable);
> >  
> > +void clk_disable_critical(struct clk *clk)
> > +{
> > +	clk->core->critical.leave_on = false;
> 
> .. you just lost the fact that it was critical in the first place.

I thought about both of these points, which is why I came up with this
strategy.

Any device which uses the *_critical() API should a) have knowledge of
what happens when a particular critical clock is gated and b) have
thought about the consequences.  I don't think we can use reference
counting, because we'd need as many critical clock owners as there are
critical clocks.  Cast your mind back to the reasons for this critical
clock API.  One of the most important intentions of this API is the
requirement mitigation for each of the critical clocks to have an owner
(driver).

With regards to your second point, that's what 'critical.enabled'
is for.  Take a look at clk_enable_critical().

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org ? Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

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

* Re: [PATCH v7 5/5] clk: dt: Introduce binding for critical clock support
  2015-07-27  7:31       ` Lee Jones
@ 2015-07-28  9:32         ` Maxime Ripard
  -1 siblings, 0 replies; 93+ messages in thread
From: Maxime Ripard @ 2015-07-28  9:32 UTC (permalink / raw)
  To: Lee Jones
  Cc: linux-arm-kernel, linux-kernel, kernel, mturquette, sboyd,
	devicetree, geert, s.hauer

[-- Attachment #1: Type: text/plain, Size: 3143 bytes --]

On Mon, Jul 27, 2015 at 08:31:49AM +0100, Lee Jones wrote:
> On Mon, 27 Jul 2015, Maxime Ripard wrote:
> 
> > Hi Lee,
> > 
> > On Wed, Jul 22, 2015 at 02:04:15PM +0100, Lee Jones wrote:
> > > Signed-off-by: Lee Jones <lee.jones@linaro.org>
> > > ---
> > >  .../devicetree/bindings/clock/clock-bindings.txt   | 39 ++++++++++++++++++++++
> > >  1 file changed, 39 insertions(+)
> > > 
> > > diff --git a/Documentation/devicetree/bindings/clock/clock-bindings.txt b/Documentation/devicetree/bindings/clock/clock-bindings.txt
> > > index 06fc6d5..4137034 100644
> > > --- a/Documentation/devicetree/bindings/clock/clock-bindings.txt
> > > +++ b/Documentation/devicetree/bindings/clock/clock-bindings.txt
> > > @@ -44,6 +44,45 @@ For example:
> > >    clocks by index. The names should reflect the clock output signal
> > >    names for the device.
> > >  
> > > +critical-clock:	Some hardware contains bunches of clocks which, in normal
> > > +		circumstances, must never be turned off.  If drivers a) fail to
> > > +		obtain a reference to any of these or b) give up a previously
> > > +		obtained reference during suspend, it is possible that some
> > > +		Operating Systems might attempt to disable them to save power.
> > > +		If this happens a platform can fail irrecoverably as a result.
> > > +		Usually the only way to recover from these failures is to
> > > +		reboot.
> > > +
> > > +		To avoid either of these two scenarios from catastrophically
> > > +		disabling an otherwise perfectly healthy running system,
> > > +		clocks can be identified as 'critical' using this property from
> > > +		inside a clocksource's node.
> > > +
> > > +		This property is not to be abused.  It is only to be used to
> > > +		protect platforms from being crippled by gated clocks, NOT as a
> > > +		convenience function to avoid using the framework correctly
> > > +		inside device drivers.
> > > +
> > > +		Expected values are hardware clock indices.  If the
> > > +		clock-indices property (see below) is used, then supplied
> > > +		values must correspond to one of the listed identifiers.
> > > +		Using the clock-indices example below, hardware clock <2>
> > > +		is missing, therefore it is considered invalid to then
> > > +		list clock <2> as a critical clock.
> > 
> > I think we should also consider having it simply as a boolean. Using
> > indices for clocks that don't have any (for example because it only
> > provides a single clock) seem to not really make much sense.
> 
> Then how would you distinguish between the clocks if the provider
> provides more than a single clock?

What I had in mind was that, you would have three cases:

  - critical-clocks is not there: no clocks are made critical

  - critical-clocks is there, but doesn't have any values: all the
    clocks provided are marked critical

  - critical-clocks is there and it has a list of values: only the
    clocks listed are marked critical.

Does that make sense to you?

Thanks,
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

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

* [PATCH v7 5/5] clk: dt: Introduce binding for critical clock support
@ 2015-07-28  9:32         ` Maxime Ripard
  0 siblings, 0 replies; 93+ messages in thread
From: Maxime Ripard @ 2015-07-28  9:32 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Jul 27, 2015 at 08:31:49AM +0100, Lee Jones wrote:
> On Mon, 27 Jul 2015, Maxime Ripard wrote:
> 
> > Hi Lee,
> > 
> > On Wed, Jul 22, 2015 at 02:04:15PM +0100, Lee Jones wrote:
> > > Signed-off-by: Lee Jones <lee.jones@linaro.org>
> > > ---
> > >  .../devicetree/bindings/clock/clock-bindings.txt   | 39 ++++++++++++++++++++++
> > >  1 file changed, 39 insertions(+)
> > > 
> > > diff --git a/Documentation/devicetree/bindings/clock/clock-bindings.txt b/Documentation/devicetree/bindings/clock/clock-bindings.txt
> > > index 06fc6d5..4137034 100644
> > > --- a/Documentation/devicetree/bindings/clock/clock-bindings.txt
> > > +++ b/Documentation/devicetree/bindings/clock/clock-bindings.txt
> > > @@ -44,6 +44,45 @@ For example:
> > >    clocks by index. The names should reflect the clock output signal
> > >    names for the device.
> > >  
> > > +critical-clock:	Some hardware contains bunches of clocks which, in normal
> > > +		circumstances, must never be turned off.  If drivers a) fail to
> > > +		obtain a reference to any of these or b) give up a previously
> > > +		obtained reference during suspend, it is possible that some
> > > +		Operating Systems might attempt to disable them to save power.
> > > +		If this happens a platform can fail irrecoverably as a result.
> > > +		Usually the only way to recover from these failures is to
> > > +		reboot.
> > > +
> > > +		To avoid either of these two scenarios from catastrophically
> > > +		disabling an otherwise perfectly healthy running system,
> > > +		clocks can be identified as 'critical' using this property from
> > > +		inside a clocksource's node.
> > > +
> > > +		This property is not to be abused.  It is only to be used to
> > > +		protect platforms from being crippled by gated clocks, NOT as a
> > > +		convenience function to avoid using the framework correctly
> > > +		inside device drivers.
> > > +
> > > +		Expected values are hardware clock indices.  If the
> > > +		clock-indices property (see below) is used, then supplied
> > > +		values must correspond to one of the listed identifiers.
> > > +		Using the clock-indices example below, hardware clock <2>
> > > +		is missing, therefore it is considered invalid to then
> > > +		list clock <2> as a critical clock.
> > 
> > I think we should also consider having it simply as a boolean. Using
> > indices for clocks that don't have any (for example because it only
> > provides a single clock) seem to not really make much sense.
> 
> Then how would you distinguish between the clocks if the provider
> provides more than a single clock?

What I had in mind was that, you would have three cases:

  - critical-clocks is not there: no clocks are made critical

  - critical-clocks is there, but doesn't have any values: all the
    clocks provided are marked critical

  - critical-clocks is there and it has a list of values: only the
    clocks listed are marked critical.

Does that make sense to you?

Thanks,
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20150728/1de9ebb8/attachment-0001.sig>

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

* Re: [PATCH v7 3/5] clk: Supply the critical clock {init, enable, disable} framework
  2015-07-27  8:53       ` Lee Jones
@ 2015-07-28 11:40         ` Maxime Ripard
  -1 siblings, 0 replies; 93+ messages in thread
From: Maxime Ripard @ 2015-07-28 11:40 UTC (permalink / raw)
  To: Lee Jones
  Cc: linux-arm-kernel, linux-kernel, kernel, mturquette, sboyd,
	devicetree, geert, s.hauer

[-- Attachment #1: Type: text/plain, Size: 4463 bytes --]

On Mon, Jul 27, 2015 at 09:53:38AM +0100, Lee Jones wrote:
> On Mon, 27 Jul 2015, Maxime Ripard wrote:
> 
> > On Wed, Jul 22, 2015 at 02:04:13PM +0100, Lee Jones wrote:
> > > These new API calls will firstly provide a mechanisms to tag a clock as
> > > critical and secondly allow any knowledgeable driver to (un)gate clocks,
> > > even if they are marked as critical.
> > > 
> > > Suggested-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> > > Signed-off-by: Lee Jones <lee.jones@linaro.org>
> > > ---
> > >  drivers/clk/clk.c            | 45 ++++++++++++++++++++++++++++++++++++++++++++
> > >  include/linux/clk-provider.h |  2 ++
> > >  include/linux/clk.h          | 30 +++++++++++++++++++++++++++++
> > >  3 files changed, 77 insertions(+)
> > > 
> > > diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> > > index 61c3fc5..486b1da 100644
> > > --- a/drivers/clk/clk.c
> > > +++ b/drivers/clk/clk.c
> > > @@ -46,6 +46,21 @@ static struct clk_core *clk_core_lookup(const char *name);
> > >  
> > >  /***    private data structures    ***/
> > >  
> > > +/**
> > > + * struct critical -	Provides 'play' over critical clocks.  A clock can be
> > > + *			marked as critical, meaning that it should not be
> > > + *			disabled.  However, if a driver which is aware of the
> > > + *			critical behaviour wants to control it, it can do so
> > > + *			using clk_enable_critical() and clk_disable_critical().
> > > + *
> > > + * @enabled	Is clock critical?  Once set, doesn't change
> > > + * @leave_on	Self explanatory.  Can be disabled by knowledgeable drivers
> > > + */
> > > +struct critical {
> > > +	bool enabled;
> > > +	bool leave_on;
> > > +};
> > > +
> > >  struct clk_core {
> > >  	const char		*name;
> > >  	const struct clk_ops	*ops;
> > > @@ -75,6 +90,7 @@ struct clk_core {
> > >  	struct dentry		*dentry;
> > >  #endif
> > >  	struct kref		ref;
> > > +	struct critical		critical;
> > >  };
> > >  
> > >  struct clk {
> > > @@ -995,6 +1011,10 @@ static void clk_core_disable(struct clk_core *clk)
> > >  	if (WARN_ON(clk->enable_count == 0))
> > >  		return;
> > >  
> > > +	/* Refuse to turn off a critical clock */
> > > +	if (clk->enable_count == 1 && clk->critical.leave_on)
> > > +		return;
> > > +
> > 
> > I think it should be handled by a separate counting. Otherwise, if you
> > have two users that marked the clock as critical, and then one of them
> > disable it...
> > 
> > >  	if (--clk->enable_count > 0)
> > >  		return;
> > >  
> > > @@ -1037,6 +1057,13 @@ void clk_disable(struct clk *clk)
> > >  }
> > >  EXPORT_SYMBOL_GPL(clk_disable);
> > >  
> > > +void clk_disable_critical(struct clk *clk)
> > > +{
> > > +	clk->core->critical.leave_on = false;
> > 
> > .. you just lost the fact that it was critical in the first place.
> 
> I thought about both of these points, which is why I came up with this
> strategy.
> 
> Any device which uses the *_critical() API should a) have knowledge of
> what happens when a particular critical clock is gated and b) have
> thought about the consequences.

Indeed.

> I don't think we can use reference counting, because we'd need as
> many critical clock owners as there are critical clocks.

Which we can have if we replace the call to clk_prepare_enable you add
in your fourth patch in __set_critical_clocks.

> Cast your mind back to the reasons for this critical clock API.  One
> of the most important intentions of this API is the requirement
> mitigation for each of the critical clocks to have an owner
> (driver).
> 
> With regards to your second point, that's what 'critical.enabled'
> is for.  Take a look at clk_enable_critical().

I don't think this addresses the issue, if you just throw more
customers at it, the issue remain with your implementation.

If you have three customers that used the critical API, and if on of
these calls clk_disable_critical, you're losing leave_on.

Which means that if there's one of the two users left that calls
clk_disable on it, the clock will actually be disabled, which is
clearly not what we want to do, as we have still a user that want the
clock to be enabled.

It would be much more robust to have another count for the critical
stuff, initialised to one by the __set_critical_clocks function.

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

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

* [PATCH v7 3/5] clk: Supply the critical clock {init, enable, disable} framework
@ 2015-07-28 11:40         ` Maxime Ripard
  0 siblings, 0 replies; 93+ messages in thread
From: Maxime Ripard @ 2015-07-28 11:40 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Jul 27, 2015 at 09:53:38AM +0100, Lee Jones wrote:
> On Mon, 27 Jul 2015, Maxime Ripard wrote:
> 
> > On Wed, Jul 22, 2015 at 02:04:13PM +0100, Lee Jones wrote:
> > > These new API calls will firstly provide a mechanisms to tag a clock as
> > > critical and secondly allow any knowledgeable driver to (un)gate clocks,
> > > even if they are marked as critical.
> > > 
> > > Suggested-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> > > Signed-off-by: Lee Jones <lee.jones@linaro.org>
> > > ---
> > >  drivers/clk/clk.c            | 45 ++++++++++++++++++++++++++++++++++++++++++++
> > >  include/linux/clk-provider.h |  2 ++
> > >  include/linux/clk.h          | 30 +++++++++++++++++++++++++++++
> > >  3 files changed, 77 insertions(+)
> > > 
> > > diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> > > index 61c3fc5..486b1da 100644
> > > --- a/drivers/clk/clk.c
> > > +++ b/drivers/clk/clk.c
> > > @@ -46,6 +46,21 @@ static struct clk_core *clk_core_lookup(const char *name);
> > >  
> > >  /***    private data structures    ***/
> > >  
> > > +/**
> > > + * struct critical -	Provides 'play' over critical clocks.  A clock can be
> > > + *			marked as critical, meaning that it should not be
> > > + *			disabled.  However, if a driver which is aware of the
> > > + *			critical behaviour wants to control it, it can do so
> > > + *			using clk_enable_critical() and clk_disable_critical().
> > > + *
> > > + * @enabled	Is clock critical?  Once set, doesn't change
> > > + * @leave_on	Self explanatory.  Can be disabled by knowledgeable drivers
> > > + */
> > > +struct critical {
> > > +	bool enabled;
> > > +	bool leave_on;
> > > +};
> > > +
> > >  struct clk_core {
> > >  	const char		*name;
> > >  	const struct clk_ops	*ops;
> > > @@ -75,6 +90,7 @@ struct clk_core {
> > >  	struct dentry		*dentry;
> > >  #endif
> > >  	struct kref		ref;
> > > +	struct critical		critical;
> > >  };
> > >  
> > >  struct clk {
> > > @@ -995,6 +1011,10 @@ static void clk_core_disable(struct clk_core *clk)
> > >  	if (WARN_ON(clk->enable_count == 0))
> > >  		return;
> > >  
> > > +	/* Refuse to turn off a critical clock */
> > > +	if (clk->enable_count == 1 && clk->critical.leave_on)
> > > +		return;
> > > +
> > 
> > I think it should be handled by a separate counting. Otherwise, if you
> > have two users that marked the clock as critical, and then one of them
> > disable it...
> > 
> > >  	if (--clk->enable_count > 0)
> > >  		return;
> > >  
> > > @@ -1037,6 +1057,13 @@ void clk_disable(struct clk *clk)
> > >  }
> > >  EXPORT_SYMBOL_GPL(clk_disable);
> > >  
> > > +void clk_disable_critical(struct clk *clk)
> > > +{
> > > +	clk->core->critical.leave_on = false;
> > 
> > .. you just lost the fact that it was critical in the first place.
> 
> I thought about both of these points, which is why I came up with this
> strategy.
> 
> Any device which uses the *_critical() API should a) have knowledge of
> what happens when a particular critical clock is gated and b) have
> thought about the consequences.

Indeed.

> I don't think we can use reference counting, because we'd need as
> many critical clock owners as there are critical clocks.

Which we can have if we replace the call to clk_prepare_enable you add
in your fourth patch in __set_critical_clocks.

> Cast your mind back to the reasons for this critical clock API.  One
> of the most important intentions of this API is the requirement
> mitigation for each of the critical clocks to have an owner
> (driver).
> 
> With regards to your second point, that's what 'critical.enabled'
> is for.  Take a look at clk_enable_critical().

I don't think this addresses the issue, if you just throw more
customers at it, the issue remain with your implementation.

If you have three customers that used the critical API, and if on of
these calls clk_disable_critical, you're losing leave_on.

Which means that if there's one of the two users left that calls
clk_disable on it, the clock will actually be disabled, which is
clearly not what we want to do, as we have still a user that want the
clock to be enabled.

It would be much more robust to have another count for the critical
stuff, initialised to one by the __set_critical_clocks function.

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20150728/f38b6aaf/attachment-0001.sig>

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

* Re: [PATCH v7 3/5] clk: Supply the critical clock {init, enable, disable} framework
  2015-07-28 11:40         ` Maxime Ripard
  (?)
@ 2015-07-28 13:00           ` Lee Jones
  -1 siblings, 0 replies; 93+ messages in thread
From: Lee Jones @ 2015-07-28 13:00 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: linux-arm-kernel, linux-kernel, kernel, mturquette, sboyd,
	devicetree, geert, s.hauer

On Tue, 28 Jul 2015, Maxime Ripard wrote:

> On Mon, Jul 27, 2015 at 09:53:38AM +0100, Lee Jones wrote:
> > On Mon, 27 Jul 2015, Maxime Ripard wrote:
> > 
> > > On Wed, Jul 22, 2015 at 02:04:13PM +0100, Lee Jones wrote:
> > > > These new API calls will firstly provide a mechanisms to tag a clock as
> > > > critical and secondly allow any knowledgeable driver to (un)gate clocks,
> > > > even if they are marked as critical.
> > > > 
> > > > Suggested-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> > > > Signed-off-by: Lee Jones <lee.jones@linaro.org>
> > > > ---
> > > >  drivers/clk/clk.c            | 45 ++++++++++++++++++++++++++++++++++++++++++++
> > > >  include/linux/clk-provider.h |  2 ++
> > > >  include/linux/clk.h          | 30 +++++++++++++++++++++++++++++
> > > >  3 files changed, 77 insertions(+)
> > > > 
> > > > diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> > > > index 61c3fc5..486b1da 100644
> > > > --- a/drivers/clk/clk.c
> > > > +++ b/drivers/clk/clk.c
> > > > @@ -46,6 +46,21 @@ static struct clk_core *clk_core_lookup(const char *name);
> > > >  
> > > >  /***    private data structures    ***/
> > > >  
> > > > +/**
> > > > + * struct critical -	Provides 'play' over critical clocks.  A clock can be
> > > > + *			marked as critical, meaning that it should not be
> > > > + *			disabled.  However, if a driver which is aware of the
> > > > + *			critical behaviour wants to control it, it can do so
> > > > + *			using clk_enable_critical() and clk_disable_critical().
> > > > + *
> > > > + * @enabled	Is clock critical?  Once set, doesn't change
> > > > + * @leave_on	Self explanatory.  Can be disabled by knowledgeable drivers
> > > > + */
> > > > +struct critical {
> > > > +	bool enabled;
> > > > +	bool leave_on;
> > > > +};
> > > > +
> > > >  struct clk_core {
> > > >  	const char		*name;
> > > >  	const struct clk_ops	*ops;
> > > > @@ -75,6 +90,7 @@ struct clk_core {
> > > >  	struct dentry		*dentry;
> > > >  #endif
> > > >  	struct kref		ref;
> > > > +	struct critical		critical;
> > > >  };
> > > >  
> > > >  struct clk {
> > > > @@ -995,6 +1011,10 @@ static void clk_core_disable(struct clk_core *clk)
> > > >  	if (WARN_ON(clk->enable_count == 0))
> > > >  		return;
> > > >  
> > > > +	/* Refuse to turn off a critical clock */
> > > > +	if (clk->enable_count == 1 && clk->critical.leave_on)
> > > > +		return;
> > > > +
> > > 
> > > I think it should be handled by a separate counting. Otherwise, if you
> > > have two users that marked the clock as critical, and then one of them
> > > disable it...
> > > 
> > > >  	if (--clk->enable_count > 0)
> > > >  		return;
> > > >  
> > > > @@ -1037,6 +1057,13 @@ void clk_disable(struct clk *clk)
> > > >  }
> > > >  EXPORT_SYMBOL_GPL(clk_disable);
> > > >  
> > > > +void clk_disable_critical(struct clk *clk)
> > > > +{
> > > > +	clk->core->critical.leave_on = false;
> > > 
> > > .. you just lost the fact that it was critical in the first place.
> > 
> > I thought about both of these points, which is why I came up with this
> > strategy.
> > 
> > Any device which uses the *_critical() API should a) have knowledge of
> > what happens when a particular critical clock is gated and b) have
> > thought about the consequences.
> 
> Indeed.
> 
> > I don't think we can use reference counting, because we'd need as
> > many critical clock owners as there are critical clocks.
> 
> Which we can have if we replace the call to clk_prepare_enable you add
> in your fourth patch in __set_critical_clocks.

What should it be replaced with?

> > Cast your mind back to the reasons for this critical clock API.  One
> > of the most important intentions of this API is the requirement
> > mitigation for each of the critical clocks to have an owner
> > (driver).
> > 
> > With regards to your second point, that's what 'critical.enabled'
> > is for.  Take a look at clk_enable_critical().
> 
> I don't think this addresses the issue, if you just throw more
> customers at it, the issue remain with your implementation.
> 
> If you have three customers that used the critical API, and if on of
> these calls clk_disable_critical, you're losing leave_on.

That's the idea.  See my point above, the one you replied "Indeed"
to.  So when a driver uses clk_disable_critical() it's saying, "I know
why this clock is a critical clock, and I know that nothing terrible
will happen if I disable it, as I have that covered".  So then if it's
not the last user to call clk_disable(), the last one out the door
will be allowed to finally gate the clock, regardless whether it's
critical aware or not.

Then, when we come to enable the clock again, the critical aware user
then re-marks the clock as leave_on, so not critical un-aware user can
take the final reference and disable the clock.

> Which means that if there's one of the two users left that calls
> clk_disable on it, the clock will actually be disabled, which is
> clearly not what we want to do, as we have still a user that want the
> clock to be enabled.

That's not what happens (at least it shouldn't if I've coded it up
right).  The API _still_ requires all of the users to give-up their
reference.

> It would be much more robust to have another count for the critical
> stuff, initialised to one by the __set_critical_clocks function.

If I understand you correctly, we already have a count.  We use the
original reference count.  No need for one of our own.

Using your RAM Clock (Clock 4) as an example
--------------------------------------------

Early start-up:
  Clock 4 is marked as critical and a reference is taken (ref == 1)

Driver probe:
  SPI enables Clock 4 (ref == 2)
  I2C enables Clock 4 (ref == 3)

Suspend (without RAM driver's permission):
  SPI disables Clock 4 (ref == 2)
  I2C disables Clock 4 (ref == 1)
  /*
   * Clock won't be gated because:
   *   .leave_on is True - can't dec final reference
   */

Suspend (with RAM driver's permission):
  /* Order is unimportant */
  SPI disables Clock 4 (ref == 2)
  RAM disables Clock 4 (ref == 1) /* Won't turn off here (ref > 0)
  I2C disables Clock 4 (ref == 0) /* (.leave_on == False) last ref can be taken */
  /*
   * Clock will be gated because:
   *   .leave_on is False, so (ref == 0)
   */

Resume:
  /* Order is unimportant */
  SPI enables Clock 4 (ref == 1)
  RAM enables Clock 4 and re-enables .leave_on (ref == 2)
  I2C enables Clock 4 (ref == 3)

Hopefully that clears things up.

Please tell me if the code doesn't reflect this strategy, or if you
can see anything wrong with how it operates.

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

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

* Re: [PATCH v7 3/5] clk: Supply the critical clock {init, enable, disable} framework
@ 2015-07-28 13:00           ` Lee Jones
  0 siblings, 0 replies; 93+ messages in thread
From: Lee Jones @ 2015-07-28 13:00 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	kernel-F5mvAk5X5gdBDgjK7y7TUQ, mturquette-QSEj5FYQhm4dnm+yROfE0A,
	sboyd-sgV2jX0FEOL9JmXXK+q4OQ, devicetree-u79uwXL29TY76Z2rM5mHXA,
	geert-Td1EMuHUCqxL1ZNQvxDV9g, s.hauer-bIcnvbaLZ9MEGnE8C9+IrQ

On Tue, 28 Jul 2015, Maxime Ripard wrote:

> On Mon, Jul 27, 2015 at 09:53:38AM +0100, Lee Jones wrote:
> > On Mon, 27 Jul 2015, Maxime Ripard wrote:
> > 
> > > On Wed, Jul 22, 2015 at 02:04:13PM +0100, Lee Jones wrote:
> > > > These new API calls will firstly provide a mechanisms to tag a clock as
> > > > critical and secondly allow any knowledgeable driver to (un)gate clocks,
> > > > even if they are marked as critical.
> > > > 
> > > > Suggested-by: Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
> > > > Signed-off-by: Lee Jones <lee.jones-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> > > > ---
> > > >  drivers/clk/clk.c            | 45 ++++++++++++++++++++++++++++++++++++++++++++
> > > >  include/linux/clk-provider.h |  2 ++
> > > >  include/linux/clk.h          | 30 +++++++++++++++++++++++++++++
> > > >  3 files changed, 77 insertions(+)
> > > > 
> > > > diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> > > > index 61c3fc5..486b1da 100644
> > > > --- a/drivers/clk/clk.c
> > > > +++ b/drivers/clk/clk.c
> > > > @@ -46,6 +46,21 @@ static struct clk_core *clk_core_lookup(const char *name);
> > > >  
> > > >  /***    private data structures    ***/
> > > >  
> > > > +/**
> > > > + * struct critical -	Provides 'play' over critical clocks.  A clock can be
> > > > + *			marked as critical, meaning that it should not be
> > > > + *			disabled.  However, if a driver which is aware of the
> > > > + *			critical behaviour wants to control it, it can do so
> > > > + *			using clk_enable_critical() and clk_disable_critical().
> > > > + *
> > > > + * @enabled	Is clock critical?  Once set, doesn't change
> > > > + * @leave_on	Self explanatory.  Can be disabled by knowledgeable drivers
> > > > + */
> > > > +struct critical {
> > > > +	bool enabled;
> > > > +	bool leave_on;
> > > > +};
> > > > +
> > > >  struct clk_core {
> > > >  	const char		*name;
> > > >  	const struct clk_ops	*ops;
> > > > @@ -75,6 +90,7 @@ struct clk_core {
> > > >  	struct dentry		*dentry;
> > > >  #endif
> > > >  	struct kref		ref;
> > > > +	struct critical		critical;
> > > >  };
> > > >  
> > > >  struct clk {
> > > > @@ -995,6 +1011,10 @@ static void clk_core_disable(struct clk_core *clk)
> > > >  	if (WARN_ON(clk->enable_count == 0))
> > > >  		return;
> > > >  
> > > > +	/* Refuse to turn off a critical clock */
> > > > +	if (clk->enable_count == 1 && clk->critical.leave_on)
> > > > +		return;
> > > > +
> > > 
> > > I think it should be handled by a separate counting. Otherwise, if you
> > > have two users that marked the clock as critical, and then one of them
> > > disable it...
> > > 
> > > >  	if (--clk->enable_count > 0)
> > > >  		return;
> > > >  
> > > > @@ -1037,6 +1057,13 @@ void clk_disable(struct clk *clk)
> > > >  }
> > > >  EXPORT_SYMBOL_GPL(clk_disable);
> > > >  
> > > > +void clk_disable_critical(struct clk *clk)
> > > > +{
> > > > +	clk->core->critical.leave_on = false;
> > > 
> > > .. you just lost the fact that it was critical in the first place.
> > 
> > I thought about both of these points, which is why I came up with this
> > strategy.
> > 
> > Any device which uses the *_critical() API should a) have knowledge of
> > what happens when a particular critical clock is gated and b) have
> > thought about the consequences.
> 
> Indeed.
> 
> > I don't think we can use reference counting, because we'd need as
> > many critical clock owners as there are critical clocks.
> 
> Which we can have if we replace the call to clk_prepare_enable you add
> in your fourth patch in __set_critical_clocks.

What should it be replaced with?

> > Cast your mind back to the reasons for this critical clock API.  One
> > of the most important intentions of this API is the requirement
> > mitigation for each of the critical clocks to have an owner
> > (driver).
> > 
> > With regards to your second point, that's what 'critical.enabled'
> > is for.  Take a look at clk_enable_critical().
> 
> I don't think this addresses the issue, if you just throw more
> customers at it, the issue remain with your implementation.
> 
> If you have three customers that used the critical API, and if on of
> these calls clk_disable_critical, you're losing leave_on.

That's the idea.  See my point above, the one you replied "Indeed"
to.  So when a driver uses clk_disable_critical() it's saying, "I know
why this clock is a critical clock, and I know that nothing terrible
will happen if I disable it, as I have that covered".  So then if it's
not the last user to call clk_disable(), the last one out the door
will be allowed to finally gate the clock, regardless whether it's
critical aware or not.

Then, when we come to enable the clock again, the critical aware user
then re-marks the clock as leave_on, so not critical un-aware user can
take the final reference and disable the clock.

> Which means that if there's one of the two users left that calls
> clk_disable on it, the clock will actually be disabled, which is
> clearly not what we want to do, as we have still a user that want the
> clock to be enabled.

That's not what happens (at least it shouldn't if I've coded it up
right).  The API _still_ requires all of the users to give-up their
reference.

> It would be much more robust to have another count for the critical
> stuff, initialised to one by the __set_critical_clocks function.

If I understand you correctly, we already have a count.  We use the
original reference count.  No need for one of our own.

Using your RAM Clock (Clock 4) as an example
--------------------------------------------

Early start-up:
  Clock 4 is marked as critical and a reference is taken (ref == 1)

Driver probe:
  SPI enables Clock 4 (ref == 2)
  I2C enables Clock 4 (ref == 3)

Suspend (without RAM driver's permission):
  SPI disables Clock 4 (ref == 2)
  I2C disables Clock 4 (ref == 1)
  /*
   * Clock won't be gated because:
   *   .leave_on is True - can't dec final reference
   */

Suspend (with RAM driver's permission):
  /* Order is unimportant */
  SPI disables Clock 4 (ref == 2)
  RAM disables Clock 4 (ref == 1) /* Won't turn off here (ref > 0)
  I2C disables Clock 4 (ref == 0) /* (.leave_on == False) last ref can be taken */
  /*
   * Clock will be gated because:
   *   .leave_on is False, so (ref == 0)
   */

Resume:
  /* Order is unimportant */
  SPI enables Clock 4 (ref == 1)
  RAM enables Clock 4 and re-enables .leave_on (ref == 2)
  I2C enables Clock 4 (ref == 3)

Hopefully that clears things up.

Please tell me if the code doesn't reflect this strategy, or if you
can see anything wrong with how it operates.

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH v7 3/5] clk: Supply the critical clock {init, enable, disable} framework
@ 2015-07-28 13:00           ` Lee Jones
  0 siblings, 0 replies; 93+ messages in thread
From: Lee Jones @ 2015-07-28 13:00 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, 28 Jul 2015, Maxime Ripard wrote:

> On Mon, Jul 27, 2015 at 09:53:38AM +0100, Lee Jones wrote:
> > On Mon, 27 Jul 2015, Maxime Ripard wrote:
> > 
> > > On Wed, Jul 22, 2015 at 02:04:13PM +0100, Lee Jones wrote:
> > > > These new API calls will firstly provide a mechanisms to tag a clock as
> > > > critical and secondly allow any knowledgeable driver to (un)gate clocks,
> > > > even if they are marked as critical.
> > > > 
> > > > Suggested-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> > > > Signed-off-by: Lee Jones <lee.jones@linaro.org>
> > > > ---
> > > >  drivers/clk/clk.c            | 45 ++++++++++++++++++++++++++++++++++++++++++++
> > > >  include/linux/clk-provider.h |  2 ++
> > > >  include/linux/clk.h          | 30 +++++++++++++++++++++++++++++
> > > >  3 files changed, 77 insertions(+)
> > > > 
> > > > diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> > > > index 61c3fc5..486b1da 100644
> > > > --- a/drivers/clk/clk.c
> > > > +++ b/drivers/clk/clk.c
> > > > @@ -46,6 +46,21 @@ static struct clk_core *clk_core_lookup(const char *name);
> > > >  
> > > >  /***    private data structures    ***/
> > > >  
> > > > +/**
> > > > + * struct critical -	Provides 'play' over critical clocks.  A clock can be
> > > > + *			marked as critical, meaning that it should not be
> > > > + *			disabled.  However, if a driver which is aware of the
> > > > + *			critical behaviour wants to control it, it can do so
> > > > + *			using clk_enable_critical() and clk_disable_critical().
> > > > + *
> > > > + * @enabled	Is clock critical?  Once set, doesn't change
> > > > + * @leave_on	Self explanatory.  Can be disabled by knowledgeable drivers
> > > > + */
> > > > +struct critical {
> > > > +	bool enabled;
> > > > +	bool leave_on;
> > > > +};
> > > > +
> > > >  struct clk_core {
> > > >  	const char		*name;
> > > >  	const struct clk_ops	*ops;
> > > > @@ -75,6 +90,7 @@ struct clk_core {
> > > >  	struct dentry		*dentry;
> > > >  #endif
> > > >  	struct kref		ref;
> > > > +	struct critical		critical;
> > > >  };
> > > >  
> > > >  struct clk {
> > > > @@ -995,6 +1011,10 @@ static void clk_core_disable(struct clk_core *clk)
> > > >  	if (WARN_ON(clk->enable_count == 0))
> > > >  		return;
> > > >  
> > > > +	/* Refuse to turn off a critical clock */
> > > > +	if (clk->enable_count == 1 && clk->critical.leave_on)
> > > > +		return;
> > > > +
> > > 
> > > I think it should be handled by a separate counting. Otherwise, if you
> > > have two users that marked the clock as critical, and then one of them
> > > disable it...
> > > 
> > > >  	if (--clk->enable_count > 0)
> > > >  		return;
> > > >  
> > > > @@ -1037,6 +1057,13 @@ void clk_disable(struct clk *clk)
> > > >  }
> > > >  EXPORT_SYMBOL_GPL(clk_disable);
> > > >  
> > > > +void clk_disable_critical(struct clk *clk)
> > > > +{
> > > > +	clk->core->critical.leave_on = false;
> > > 
> > > .. you just lost the fact that it was critical in the first place.
> > 
> > I thought about both of these points, which is why I came up with this
> > strategy.
> > 
> > Any device which uses the *_critical() API should a) have knowledge of
> > what happens when a particular critical clock is gated and b) have
> > thought about the consequences.
> 
> Indeed.
> 
> > I don't think we can use reference counting, because we'd need as
> > many critical clock owners as there are critical clocks.
> 
> Which we can have if we replace the call to clk_prepare_enable you add
> in your fourth patch in __set_critical_clocks.

What should it be replaced with?

> > Cast your mind back to the reasons for this critical clock API.  One
> > of the most important intentions of this API is the requirement
> > mitigation for each of the critical clocks to have an owner
> > (driver).
> > 
> > With regards to your second point, that's what 'critical.enabled'
> > is for.  Take a look at clk_enable_critical().
> 
> I don't think this addresses the issue, if you just throw more
> customers at it, the issue remain with your implementation.
> 
> If you have three customers that used the critical API, and if on of
> these calls clk_disable_critical, you're losing leave_on.

That's the idea.  See my point above, the one you replied "Indeed"
to.  So when a driver uses clk_disable_critical() it's saying, "I know
why this clock is a critical clock, and I know that nothing terrible
will happen if I disable it, as I have that covered".  So then if it's
not the last user to call clk_disable(), the last one out the door
will be allowed to finally gate the clock, regardless whether it's
critical aware or not.

Then, when we come to enable the clock again, the critical aware user
then re-marks the clock as leave_on, so not critical un-aware user can
take the final reference and disable the clock.

> Which means that if there's one of the two users left that calls
> clk_disable on it, the clock will actually be disabled, which is
> clearly not what we want to do, as we have still a user that want the
> clock to be enabled.

That's not what happens (at least it shouldn't if I've coded it up
right).  The API _still_ requires all of the users to give-up their
reference.

> It would be much more robust to have another count for the critical
> stuff, initialised to one by the __set_critical_clocks function.

If I understand you correctly, we already have a count.  We use the
original reference count.  No need for one of our own.

Using your RAM Clock (Clock 4) as an example
--------------------------------------------

Early start-up:
  Clock 4 is marked as critical and a reference is taken (ref == 1)

Driver probe:
  SPI enables Clock 4 (ref == 2)
  I2C enables Clock 4 (ref == 3)

Suspend (without RAM driver's permission):
  SPI disables Clock 4 (ref == 2)
  I2C disables Clock 4 (ref == 1)
  /*
   * Clock won't be gated because:
   *   .leave_on is True - can't dec final reference
   */

Suspend (with RAM driver's permission):
  /* Order is unimportant */
  SPI disables Clock 4 (ref == 2)
  RAM disables Clock 4 (ref == 1) /* Won't turn off here (ref > 0)
  I2C disables Clock 4 (ref == 0) /* (.leave_on == False) last ref can be taken */
  /*
   * Clock will be gated because:
   *   .leave_on is False, so (ref == 0)
   */

Resume:
  /* Order is unimportant */
  SPI enables Clock 4 (ref == 1)
  RAM enables Clock 4 and re-enables .leave_on (ref == 2)
  I2C enables Clock 4 (ref == 3)

Hopefully that clears things up.

Please tell me if the code doesn't reflect this strategy, or if you
can see anything wrong with how it operates.

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org ? Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

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

* Re: [PATCH v7 0/5] clk: Provide support for always-on clocks
  2015-07-22 13:04 ` Lee Jones
  (?)
@ 2015-07-30  0:27   ` Michael Turquette
  -1 siblings, 0 replies; 93+ messages in thread
From: Michael Turquette @ 2015-07-30  0:27 UTC (permalink / raw)
  To: Lee Jones, linux-arm-kernel, linux-kernel
  Cc: kernel, sboyd, devicetree, geert, maxime.ripard, s.hauer, Lee Jones

Quoting Lee Jones (2015-07-22 06:04:10)
> Lots of platforms contain clocks which if turned off would prove fatal.
> The only way to recover from these catastrophic failures is to restart
> the board(s).  Now, when a clock provider is registered with the
> framework it is possible for a list of critical clocks to be supplied
> which must be kept ungated.  Each clock mentioned in the newly
> introduced 'critical-clock' property will be clk_prepare_enable()d
> where the normal references will be taken.  This will prevent the
> common clk framework from attempting to gate them during the normal
> clk_disable_unused() and disable_clock() procedures.
> 
> Note that it will still be possible for knowledgeable drivers to turn
> these clocks off using clk_{enable,disable}_critical() calls.

Hi Lee,

Thanks for submitting the series.

It has been a little while since v6. It would be helpful to remind me of
why a new api is necessary, versus using the existing clk_prepare_unused
call at the time that a clock is enabled.

I'm looking over the patches in detail now, but one question stands out:
besides the DT use case, would a Linux device driver ever call
clk_enable_critical instead of using clk_enable? If so, why?

Thanks,
Mike

> 
> Changelog:
> v6 => v7:
>   - Introduce API to enable and disable critical clocks
>   - Rename 'always-on-clock' to 'critical-clock'
> 
> v5 => v6:
>   - Use of_clk_get_from_provider() instead of of_clk_get_by_clkspec()
>   - Explicitly describe expected DT values
>   - Be pedantic with regards to printk() format specifiers
> 
> vX => v5:
>   Implementations have changed drastically between versions, thus I
>   would like for this set to be thought of independently from its
>   predecessors.  The only reason for identifying as 'v5' is ease of
>   differentiation on the list, which stems from the confusion caused
>   by submitting 'v4' as a separate entity.
> 
> Lee Jones (5):
>   ARM: sti: stih407-family: Supply defines for CLOCKGEN A0
>   ARM: sti: stih410-clocks: Identify critical clocks
>   clk: Supply the critical clock {init, enable, disable} framework
>   clk: Provide critical clock support
>   clk: dt: Introduce binding for critical clock support
> 
>  .../devicetree/bindings/clock/clock-bindings.txt   | 39 +++++++++++++++++++
>  arch/arm/boot/dts/stih410-clock.dtsi               | 10 +++++
>  drivers/clk/clk-conf.c                             | 45 +++++++++++++++++++++-
>  drivers/clk/clk.c                                  | 45 ++++++++++++++++++++++
>  include/dt-bindings/clock/stih407-clks.h           |  4 ++
>  include/linux/clk-provider.h                       |  2 +
>  include/linux/clk.h                                | 30 +++++++++++++++
>  7 files changed, 174 insertions(+), 1 deletion(-)
> 
> -- 
> 1.9.1
> 

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

* Re: [PATCH v7 0/5] clk: Provide support for always-on clocks
@ 2015-07-30  0:27   ` Michael Turquette
  0 siblings, 0 replies; 93+ messages in thread
From: Michael Turquette @ 2015-07-30  0:27 UTC (permalink / raw)
  To: linux-arm-kernel, linux-kernel
  Cc: kernel, sboyd, devicetree, geert, maxime.ripard, s.hauer, Lee Jones

Quoting Lee Jones (2015-07-22 06:04:10)
> Lots of platforms contain clocks which if turned off would prove fatal.
> The only way to recover from these catastrophic failures is to restart
> the board(s).  Now, when a clock provider is registered with the
> framework it is possible for a list of critical clocks to be supplied
> which must be kept ungated.  Each clock mentioned in the newly
> introduced 'critical-clock' property will be clk_prepare_enable()d
> where the normal references will be taken.  This will prevent the
> common clk framework from attempting to gate them during the normal
> clk_disable_unused() and disable_clock() procedures.
> 
> Note that it will still be possible for knowledgeable drivers to turn
> these clocks off using clk_{enable,disable}_critical() calls.

Hi Lee,

Thanks for submitting the series.

It has been a little while since v6. It would be helpful to remind me of
why a new api is necessary, versus using the existing clk_prepare_unused
call at the time that a clock is enabled.

I'm looking over the patches in detail now, but one question stands out:
besides the DT use case, would a Linux device driver ever call
clk_enable_critical instead of using clk_enable? If so, why?

Thanks,
Mike

> 
> Changelog:
> v6 => v7:
>   - Introduce API to enable and disable critical clocks
>   - Rename 'always-on-clock' to 'critical-clock'
> 
> v5 => v6:
>   - Use of_clk_get_from_provider() instead of of_clk_get_by_clkspec()
>   - Explicitly describe expected DT values
>   - Be pedantic with regards to printk() format specifiers
> 
> vX => v5:
>   Implementations have changed drastically between versions, thus I
>   would like for this set to be thought of independently from its
>   predecessors.  The only reason for identifying as 'v5' is ease of
>   differentiation on the list, which stems from the confusion caused
>   by submitting 'v4' as a separate entity.
> 
> Lee Jones (5):
>   ARM: sti: stih407-family: Supply defines for CLOCKGEN A0
>   ARM: sti: stih410-clocks: Identify critical clocks
>   clk: Supply the critical clock {init, enable, disable} framework
>   clk: Provide critical clock support
>   clk: dt: Introduce binding for critical clock support
> 
>  .../devicetree/bindings/clock/clock-bindings.txt   | 39 +++++++++++++++++++
>  arch/arm/boot/dts/stih410-clock.dtsi               | 10 +++++
>  drivers/clk/clk-conf.c                             | 45 +++++++++++++++++++++-
>  drivers/clk/clk.c                                  | 45 ++++++++++++++++++++++
>  include/dt-bindings/clock/stih407-clks.h           |  4 ++
>  include/linux/clk-provider.h                       |  2 +
>  include/linux/clk.h                                | 30 +++++++++++++++
>  7 files changed, 174 insertions(+), 1 deletion(-)
> 
> -- 
> 1.9.1
> 

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

* [PATCH v7 0/5] clk: Provide support for always-on clocks
@ 2015-07-30  0:27   ` Michael Turquette
  0 siblings, 0 replies; 93+ messages in thread
From: Michael Turquette @ 2015-07-30  0:27 UTC (permalink / raw)
  To: linux-arm-kernel

Quoting Lee Jones (2015-07-22 06:04:10)
> Lots of platforms contain clocks which if turned off would prove fatal.
> The only way to recover from these catastrophic failures is to restart
> the board(s).  Now, when a clock provider is registered with the
> framework it is possible for a list of critical clocks to be supplied
> which must be kept ungated.  Each clock mentioned in the newly
> introduced 'critical-clock' property will be clk_prepare_enable()d
> where the normal references will be taken.  This will prevent the
> common clk framework from attempting to gate them during the normal
> clk_disable_unused() and disable_clock() procedures.
> 
> Note that it will still be possible for knowledgeable drivers to turn
> these clocks off using clk_{enable,disable}_critical() calls.

Hi Lee,

Thanks for submitting the series.

It has been a little while since v6. It would be helpful to remind me of
why a new api is necessary, versus using the existing clk_prepare_unused
call at the time that a clock is enabled.

I'm looking over the patches in detail now, but one question stands out:
besides the DT use case, would a Linux device driver ever call
clk_enable_critical instead of using clk_enable? If so, why?

Thanks,
Mike

> 
> Changelog:
> v6 => v7:
>   - Introduce API to enable and disable critical clocks
>   - Rename 'always-on-clock' to 'critical-clock'
> 
> v5 => v6:
>   - Use of_clk_get_from_provider() instead of of_clk_get_by_clkspec()
>   - Explicitly describe expected DT values
>   - Be pedantic with regards to printk() format specifiers
> 
> vX => v5:
>   Implementations have changed drastically between versions, thus I
>   would like for this set to be thought of independently from its
>   predecessors.  The only reason for identifying as 'v5' is ease of
>   differentiation on the list, which stems from the confusion caused
>   by submitting 'v4' as a separate entity.
> 
> Lee Jones (5):
>   ARM: sti: stih407-family: Supply defines for CLOCKGEN A0
>   ARM: sti: stih410-clocks: Identify critical clocks
>   clk: Supply the critical clock {init, enable, disable} framework
>   clk: Provide critical clock support
>   clk: dt: Introduce binding for critical clock support
> 
>  .../devicetree/bindings/clock/clock-bindings.txt   | 39 +++++++++++++++++++
>  arch/arm/boot/dts/stih410-clock.dtsi               | 10 +++++
>  drivers/clk/clk-conf.c                             | 45 +++++++++++++++++++++-
>  drivers/clk/clk.c                                  | 45 ++++++++++++++++++++++
>  include/dt-bindings/clock/stih407-clks.h           |  4 ++
>  include/linux/clk-provider.h                       |  2 +
>  include/linux/clk.h                                | 30 +++++++++++++++
>  7 files changed, 174 insertions(+), 1 deletion(-)
> 
> -- 
> 1.9.1
> 

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

* Re: [PATCH v7 3/5] clk: Supply the critical clock {init, enable, disable} framework
  2015-07-22 13:04   ` Lee Jones
  (?)
@ 2015-07-30  1:02     ` Michael Turquette
  -1 siblings, 0 replies; 93+ messages in thread
From: Michael Turquette @ 2015-07-30  1:02 UTC (permalink / raw)
  To: Lee Jones, linux-arm-kernel, linux-kernel
  Cc: kernel, sboyd, devicetree, geert, maxime.ripard, s.hauer,
	Lee Jones, linux-clk

Hi Lee,

+ linux-clk ml

Quoting Lee Jones (2015-07-22 06:04:13)
> These new API calls will firstly provide a mechanisms to tag a clock as
> critical and secondly allow any knowledgeable driver to (un)gate clocks,
> even if they are marked as critical.
> 
> Suggested-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> Signed-off-by: Lee Jones <lee.jones@linaro.org>
> ---
>  drivers/clk/clk.c            | 45 ++++++++++++++++++++++++++++++++++++++++++++
>  include/linux/clk-provider.h |  2 ++
>  include/linux/clk.h          | 30 +++++++++++++++++++++++++++++
>  3 files changed, 77 insertions(+)
> 
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> index 61c3fc5..486b1da 100644
> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> @@ -46,6 +46,21 @@ static struct clk_core *clk_core_lookup(const char *name);
>  
>  /***    private data structures    ***/
>  
> +/**
> + * struct critical -   Provides 'play' over critical clocks.  A clock can be
> + *                     marked as critical, meaning that it should not be
> + *                     disabled.  However, if a driver which is aware of the
> + *                     critical behaviour wants to control it, it can do so
> + *                     using clk_enable_critical() and clk_disable_critical().
> + *
> + * @enabled    Is clock critical?  Once set, doesn't change
> + * @leave_on   Self explanatory.  Can be disabled by knowledgeable drivers

Not self explanatory. I need this explained to me. What does leave_on
do? Better yet, what would happen if leave_on did not exist?

> + */
> +struct critical {
> +       bool enabled;
> +       bool leave_on;
> +};
> +
>  struct clk_core {
>         const char              *name;
>         const struct clk_ops    *ops;
> @@ -75,6 +90,7 @@ struct clk_core {
>         struct dentry           *dentry;
>  #endif
>         struct kref             ref;
> +       struct critical         critical;
>  };
>  
>  struct clk {
> @@ -995,6 +1011,10 @@ static void clk_core_disable(struct clk_core *clk)
>         if (WARN_ON(clk->enable_count == 0))
>                 return;
>  
> +       /* Refuse to turn off a critical clock */
> +       if (clk->enable_count == 1 && clk->critical.leave_on)
> +               return;

How do we get to this point? clk_enable_critical actually calls
clk_enable, thus incrementing the enable_count. The only time that we
could hit the above case is if,

a) there is an imbalance in clk_enable and clk_disable calls. If this is
the case then the drivers need to be fixed. Or better yet some
infrastructure to catch that, now that we have per-user struct clk
cookies.

b) a driver knowingly calls clk_enable_critical(foo) and then regular,
old clk_disable(foo). But why would a driver do that?

It might be that I am missing the point here, so please feel free to
clue me in.

Regards,
Mike

> +
>         if (--clk->enable_count > 0)
>                 return;
>  
> @@ -1037,6 +1057,13 @@ void clk_disable(struct clk *clk)
>  }
>  EXPORT_SYMBOL_GPL(clk_disable);
>  
> +void clk_disable_critical(struct clk *clk)
> +{
> +       clk->core->critical.leave_on = false;
> +       clk_disable(clk);
> +}
> +EXPORT_SYMBOL_GPL(clk_disable_critical);
> +
>  static int clk_core_enable(struct clk_core *clk)
>  {
>         int ret = 0;
> @@ -1100,6 +1127,15 @@ int clk_enable(struct clk *clk)
>  }
>  EXPORT_SYMBOL_GPL(clk_enable);
>  
> +int clk_enable_critical(struct clk *clk)
> +{
> +       if (clk->core->critical.enabled)
> +               clk->core->critical.leave_on = true;
> +
> +       return clk_enable(clk);
> +}
> +EXPORT_SYMBOL_GPL(clk_enable_critical);
> +
>  static unsigned long clk_core_round_rate_nolock(struct clk_core *clk,
>                                                 unsigned long rate,
>                                                 unsigned long min_rate,
> @@ -2482,6 +2518,15 @@ fail_out:
>  }
>  EXPORT_SYMBOL_GPL(clk_register);
>  
> +void clk_init_critical(struct clk *clk)
> +{
> +       struct critical *critical = &clk->core->critical;
> +
> +       critical->enabled = true;
> +       critical->leave_on = true;
> +}
> +EXPORT_SYMBOL_GPL(clk_init_critical);
> +
>  /*
>   * Free memory allocated for a clock.
>   * Caller must hold prepare_lock.
> diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
> index 5591ea7..15ef8c9 100644
> --- a/include/linux/clk-provider.h
> +++ b/include/linux/clk-provider.h
> @@ -563,6 +563,8 @@ struct clk *devm_clk_register(struct device *dev, struct clk_hw *hw);
>  void clk_unregister(struct clk *clk);
>  void devm_clk_unregister(struct device *dev, struct clk *clk);
>  
> +void clk_init_critical(struct clk *clk);
> +
>  /* helper functions */
>  const char *__clk_get_name(struct clk *clk);
>  struct clk_hw *__clk_get_hw(struct clk *clk);
> diff --git a/include/linux/clk.h b/include/linux/clk.h
> index 8381bbf..9807f3b 100644
> --- a/include/linux/clk.h
> +++ b/include/linux/clk.h
> @@ -231,6 +231,19 @@ struct clk *devm_clk_get(struct device *dev, const char *id);
>  int clk_enable(struct clk *clk);
>  
>  /**
> + * clk_enable_critical - inform the system when the clock source should be
> + *                      running, even if clock is critical.
> + * @clk: clock source
> + *
> + * If the clock can not be enabled/disabled, this should return success.
> + *
> + * May be called from atomic contexts.
> + *
> + * Returns success (0) or negative errno.
> + */
> +int clk_enable_critical(struct clk *clk);
> +
> +/**
>   * clk_disable - inform the system when the clock source is no longer required.
>   * @clk: clock source
>   *
> @@ -247,6 +260,23 @@ int clk_enable(struct clk *clk);
>  void clk_disable(struct clk *clk);
>  
>  /**
> + * clk_disable_critical - inform the system when the clock source is no
> + *                       longer required, even if clock is critical.
> + * @clk: clock source
> + *
> + * Inform the system that a clock source is no longer required by
> + * a driver and may be shut down.
> + *
> + * May be called from atomic contexts.
> + *
> + * Implementation detail: if the clock source is shared between
> + * multiple drivers, clk_enable_critical() calls must be balanced
> + * by the same number of clk_disable_critical() calls for the clock
> + * source to be disabled.
> + */
> +void clk_disable_critical(struct clk *clk);
> +
> +/**
>   * clk_get_rate - obtain the current clock rate (in Hz) for a clock source.
>   *               This is only valid once the clock source has been enabled.
>   * @clk: clock source
> -- 
> 1.9.1
> 

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

* Re: [PATCH v7 3/5] clk: Supply the critical clock {init, enable, disable} framework
@ 2015-07-30  1:02     ` Michael Turquette
  0 siblings, 0 replies; 93+ messages in thread
From: Michael Turquette @ 2015-07-30  1:02 UTC (permalink / raw)
  To: linux-arm-kernel, linux-kernel
  Cc: kernel, sboyd, devicetree, geert, maxime.ripard, s.hauer,
	Lee Jones, linux-clk

Hi Lee,

+ linux-clk ml

Quoting Lee Jones (2015-07-22 06:04:13)
> These new API calls will firstly provide a mechanisms to tag a clock as
> critical and secondly allow any knowledgeable driver to (un)gate clocks,
> even if they are marked as critical.
> 
> Suggested-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> Signed-off-by: Lee Jones <lee.jones@linaro.org>
> ---
>  drivers/clk/clk.c            | 45 ++++++++++++++++++++++++++++++++++++++++++++
>  include/linux/clk-provider.h |  2 ++
>  include/linux/clk.h          | 30 +++++++++++++++++++++++++++++
>  3 files changed, 77 insertions(+)
> 
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> index 61c3fc5..486b1da 100644
> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> @@ -46,6 +46,21 @@ static struct clk_core *clk_core_lookup(const char *name);
>  
>  /***    private data structures    ***/
>  
> +/**
> + * struct critical -   Provides 'play' over critical clocks.  A clock can be
> + *                     marked as critical, meaning that it should not be
> + *                     disabled.  However, if a driver which is aware of the
> + *                     critical behaviour wants to control it, it can do so
> + *                     using clk_enable_critical() and clk_disable_critical().
> + *
> + * @enabled    Is clock critical?  Once set, doesn't change
> + * @leave_on   Self explanatory.  Can be disabled by knowledgeable drivers

Not self explanatory. I need this explained to me. What does leave_on
do? Better yet, what would happen if leave_on did not exist?

> + */
> +struct critical {
> +       bool enabled;
> +       bool leave_on;
> +};
> +
>  struct clk_core {
>         const char              *name;
>         const struct clk_ops    *ops;
> @@ -75,6 +90,7 @@ struct clk_core {
>         struct dentry           *dentry;
>  #endif
>         struct kref             ref;
> +       struct critical         critical;
>  };
>  
>  struct clk {
> @@ -995,6 +1011,10 @@ static void clk_core_disable(struct clk_core *clk)
>         if (WARN_ON(clk->enable_count == 0))
>                 return;
>  
> +       /* Refuse to turn off a critical clock */
> +       if (clk->enable_count == 1 && clk->critical.leave_on)
> +               return;

How do we get to this point? clk_enable_critical actually calls
clk_enable, thus incrementing the enable_count. The only time that we
could hit the above case is if,

a) there is an imbalance in clk_enable and clk_disable calls. If this is
the case then the drivers need to be fixed. Or better yet some
infrastructure to catch that, now that we have per-user struct clk
cookies.

b) a driver knowingly calls clk_enable_critical(foo) and then regular,
old clk_disable(foo). But why would a driver do that?

It might be that I am missing the point here, so please feel free to
clue me in.

Regards,
Mike

> +
>         if (--clk->enable_count > 0)
>                 return;
>  
> @@ -1037,6 +1057,13 @@ void clk_disable(struct clk *clk)
>  }
>  EXPORT_SYMBOL_GPL(clk_disable);
>  
> +void clk_disable_critical(struct clk *clk)
> +{
> +       clk->core->critical.leave_on = false;
> +       clk_disable(clk);
> +}
> +EXPORT_SYMBOL_GPL(clk_disable_critical);
> +
>  static int clk_core_enable(struct clk_core *clk)
>  {
>         int ret = 0;
> @@ -1100,6 +1127,15 @@ int clk_enable(struct clk *clk)
>  }
>  EXPORT_SYMBOL_GPL(clk_enable);
>  
> +int clk_enable_critical(struct clk *clk)
> +{
> +       if (clk->core->critical.enabled)
> +               clk->core->critical.leave_on = true;
> +
> +       return clk_enable(clk);
> +}
> +EXPORT_SYMBOL_GPL(clk_enable_critical);
> +
>  static unsigned long clk_core_round_rate_nolock(struct clk_core *clk,
>                                                 unsigned long rate,
>                                                 unsigned long min_rate,
> @@ -2482,6 +2518,15 @@ fail_out:
>  }
>  EXPORT_SYMBOL_GPL(clk_register);
>  
> +void clk_init_critical(struct clk *clk)
> +{
> +       struct critical *critical = &clk->core->critical;
> +
> +       critical->enabled = true;
> +       critical->leave_on = true;
> +}
> +EXPORT_SYMBOL_GPL(clk_init_critical);
> +
>  /*
>   * Free memory allocated for a clock.
>   * Caller must hold prepare_lock.
> diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
> index 5591ea7..15ef8c9 100644
> --- a/include/linux/clk-provider.h
> +++ b/include/linux/clk-provider.h
> @@ -563,6 +563,8 @@ struct clk *devm_clk_register(struct device *dev, struct clk_hw *hw);
>  void clk_unregister(struct clk *clk);
>  void devm_clk_unregister(struct device *dev, struct clk *clk);
>  
> +void clk_init_critical(struct clk *clk);
> +
>  /* helper functions */
>  const char *__clk_get_name(struct clk *clk);
>  struct clk_hw *__clk_get_hw(struct clk *clk);
> diff --git a/include/linux/clk.h b/include/linux/clk.h
> index 8381bbf..9807f3b 100644
> --- a/include/linux/clk.h
> +++ b/include/linux/clk.h
> @@ -231,6 +231,19 @@ struct clk *devm_clk_get(struct device *dev, const char *id);
>  int clk_enable(struct clk *clk);
>  
>  /**
> + * clk_enable_critical - inform the system when the clock source should be
> + *                      running, even if clock is critical.
> + * @clk: clock source
> + *
> + * If the clock can not be enabled/disabled, this should return success.
> + *
> + * May be called from atomic contexts.
> + *
> + * Returns success (0) or negative errno.
> + */
> +int clk_enable_critical(struct clk *clk);
> +
> +/**
>   * clk_disable - inform the system when the clock source is no longer required.
>   * @clk: clock source
>   *
> @@ -247,6 +260,23 @@ int clk_enable(struct clk *clk);
>  void clk_disable(struct clk *clk);
>  
>  /**
> + * clk_disable_critical - inform the system when the clock source is no
> + *                       longer required, even if clock is critical.
> + * @clk: clock source
> + *
> + * Inform the system that a clock source is no longer required by
> + * a driver and may be shut down.
> + *
> + * May be called from atomic contexts.
> + *
> + * Implementation detail: if the clock source is shared between
> + * multiple drivers, clk_enable_critical() calls must be balanced
> + * by the same number of clk_disable_critical() calls for the clock
> + * source to be disabled.
> + */
> +void clk_disable_critical(struct clk *clk);
> +
> +/**
>   * clk_get_rate - obtain the current clock rate (in Hz) for a clock source.
>   *               This is only valid once the clock source has been enabled.
>   * @clk: clock source
> -- 
> 1.9.1
> 

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

* [PATCH v7 3/5] clk: Supply the critical clock {init, enable, disable} framework
@ 2015-07-30  1:02     ` Michael Turquette
  0 siblings, 0 replies; 93+ messages in thread
From: Michael Turquette @ 2015-07-30  1:02 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Lee,

+ linux-clk ml

Quoting Lee Jones (2015-07-22 06:04:13)
> These new API calls will firstly provide a mechanisms to tag a clock as
> critical and secondly allow any knowledgeable driver to (un)gate clocks,
> even if they are marked as critical.
> 
> Suggested-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> Signed-off-by: Lee Jones <lee.jones@linaro.org>
> ---
>  drivers/clk/clk.c            | 45 ++++++++++++++++++++++++++++++++++++++++++++
>  include/linux/clk-provider.h |  2 ++
>  include/linux/clk.h          | 30 +++++++++++++++++++++++++++++
>  3 files changed, 77 insertions(+)
> 
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> index 61c3fc5..486b1da 100644
> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> @@ -46,6 +46,21 @@ static struct clk_core *clk_core_lookup(const char *name);
>  
>  /***    private data structures    ***/
>  
> +/**
> + * struct critical -   Provides 'play' over critical clocks.  A clock can be
> + *                     marked as critical, meaning that it should not be
> + *                     disabled.  However, if a driver which is aware of the
> + *                     critical behaviour wants to control it, it can do so
> + *                     using clk_enable_critical() and clk_disable_critical().
> + *
> + * @enabled    Is clock critical?  Once set, doesn't change
> + * @leave_on   Self explanatory.  Can be disabled by knowledgeable drivers

Not self explanatory. I need this explained to me. What does leave_on
do? Better yet, what would happen if leave_on did not exist?

> + */
> +struct critical {
> +       bool enabled;
> +       bool leave_on;
> +};
> +
>  struct clk_core {
>         const char              *name;
>         const struct clk_ops    *ops;
> @@ -75,6 +90,7 @@ struct clk_core {
>         struct dentry           *dentry;
>  #endif
>         struct kref             ref;
> +       struct critical         critical;
>  };
>  
>  struct clk {
> @@ -995,6 +1011,10 @@ static void clk_core_disable(struct clk_core *clk)
>         if (WARN_ON(clk->enable_count == 0))
>                 return;
>  
> +       /* Refuse to turn off a critical clock */
> +       if (clk->enable_count == 1 && clk->critical.leave_on)
> +               return;

How do we get to this point? clk_enable_critical actually calls
clk_enable, thus incrementing the enable_count. The only time that we
could hit the above case is if,

a) there is an imbalance in clk_enable and clk_disable calls. If this is
the case then the drivers need to be fixed. Or better yet some
infrastructure to catch that, now that we have per-user struct clk
cookies.

b) a driver knowingly calls clk_enable_critical(foo) and then regular,
old clk_disable(foo). But why would a driver do that?

It might be that I am missing the point here, so please feel free to
clue me in.

Regards,
Mike

> +
>         if (--clk->enable_count > 0)
>                 return;
>  
> @@ -1037,6 +1057,13 @@ void clk_disable(struct clk *clk)
>  }
>  EXPORT_SYMBOL_GPL(clk_disable);
>  
> +void clk_disable_critical(struct clk *clk)
> +{
> +       clk->core->critical.leave_on = false;
> +       clk_disable(clk);
> +}
> +EXPORT_SYMBOL_GPL(clk_disable_critical);
> +
>  static int clk_core_enable(struct clk_core *clk)
>  {
>         int ret = 0;
> @@ -1100,6 +1127,15 @@ int clk_enable(struct clk *clk)
>  }
>  EXPORT_SYMBOL_GPL(clk_enable);
>  
> +int clk_enable_critical(struct clk *clk)
> +{
> +       if (clk->core->critical.enabled)
> +               clk->core->critical.leave_on = true;
> +
> +       return clk_enable(clk);
> +}
> +EXPORT_SYMBOL_GPL(clk_enable_critical);
> +
>  static unsigned long clk_core_round_rate_nolock(struct clk_core *clk,
>                                                 unsigned long rate,
>                                                 unsigned long min_rate,
> @@ -2482,6 +2518,15 @@ fail_out:
>  }
>  EXPORT_SYMBOL_GPL(clk_register);
>  
> +void clk_init_critical(struct clk *clk)
> +{
> +       struct critical *critical = &clk->core->critical;
> +
> +       critical->enabled = true;
> +       critical->leave_on = true;
> +}
> +EXPORT_SYMBOL_GPL(clk_init_critical);
> +
>  /*
>   * Free memory allocated for a clock.
>   * Caller must hold prepare_lock.
> diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
> index 5591ea7..15ef8c9 100644
> --- a/include/linux/clk-provider.h
> +++ b/include/linux/clk-provider.h
> @@ -563,6 +563,8 @@ struct clk *devm_clk_register(struct device *dev, struct clk_hw *hw);
>  void clk_unregister(struct clk *clk);
>  void devm_clk_unregister(struct device *dev, struct clk *clk);
>  
> +void clk_init_critical(struct clk *clk);
> +
>  /* helper functions */
>  const char *__clk_get_name(struct clk *clk);
>  struct clk_hw *__clk_get_hw(struct clk *clk);
> diff --git a/include/linux/clk.h b/include/linux/clk.h
> index 8381bbf..9807f3b 100644
> --- a/include/linux/clk.h
> +++ b/include/linux/clk.h
> @@ -231,6 +231,19 @@ struct clk *devm_clk_get(struct device *dev, const char *id);
>  int clk_enable(struct clk *clk);
>  
>  /**
> + * clk_enable_critical - inform the system when the clock source should be
> + *                      running, even if clock is critical.
> + * @clk: clock source
> + *
> + * If the clock can not be enabled/disabled, this should return success.
> + *
> + * May be called from atomic contexts.
> + *
> + * Returns success (0) or negative errno.
> + */
> +int clk_enable_critical(struct clk *clk);
> +
> +/**
>   * clk_disable - inform the system when the clock source is no longer required.
>   * @clk: clock source
>   *
> @@ -247,6 +260,23 @@ int clk_enable(struct clk *clk);
>  void clk_disable(struct clk *clk);
>  
>  /**
> + * clk_disable_critical - inform the system when the clock source is no
> + *                       longer required, even if clock is critical.
> + * @clk: clock source
> + *
> + * Inform the system that a clock source is no longer required by
> + * a driver and may be shut down.
> + *
> + * May be called from atomic contexts.
> + *
> + * Implementation detail: if the clock source is shared between
> + * multiple drivers, clk_enable_critical() calls must be balanced
> + * by the same number of clk_disable_critical() calls for the clock
> + * source to be disabled.
> + */
> +void clk_disable_critical(struct clk *clk);
> +
> +/**
>   * clk_get_rate - obtain the current clock rate (in Hz) for a clock source.
>   *               This is only valid once the clock source has been enabled.
>   * @clk: clock source
> -- 
> 1.9.1
> 

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

* Re: [PATCH v7 3/5] clk: Supply the critical clock {init, enable, disable} framework
  2015-07-28 13:00           ` Lee Jones
  (?)
@ 2015-07-30  1:19             ` Michael Turquette
  -1 siblings, 0 replies; 93+ messages in thread
From: Michael Turquette @ 2015-07-30  1:19 UTC (permalink / raw)
  To: Lee Jones, Maxime Ripard
  Cc: linux-arm-kernel, linux-kernel, kernel, sboyd, devicetree, geert,
	s.hauer

Quoting Lee Jones (2015-07-28 06:00:55)
> On Tue, 28 Jul 2015, Maxime Ripard wrote:
> 
> > On Mon, Jul 27, 2015 at 09:53:38AM +0100, Lee Jones wrote:
> > > On Mon, 27 Jul 2015, Maxime Ripard wrote:
> > > 
> > > > On Wed, Jul 22, 2015 at 02:04:13PM +0100, Lee Jones wrote:
> > > > > These new API calls will firstly provide a mechanisms to tag a clock as
> > > > > critical and secondly allow any knowledgeable driver to (un)gate clocks,
> > > > > even if they are marked as critical.
> > > > > 
> > > > > Suggested-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> > > > > Signed-off-by: Lee Jones <lee.jones@linaro.org>
> > > > > ---
> > > > >  drivers/clk/clk.c            | 45 ++++++++++++++++++++++++++++++++++++++++++++
> > > > >  include/linux/clk-provider.h |  2 ++
> > > > >  include/linux/clk.h          | 30 +++++++++++++++++++++++++++++
> > > > >  3 files changed, 77 insertions(+)
> > > > > 
> > > > > diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> > > > > index 61c3fc5..486b1da 100644
> > > > > --- a/drivers/clk/clk.c
> > > > > +++ b/drivers/clk/clk.c
> > > > > @@ -46,6 +46,21 @@ static struct clk_core *clk_core_lookup(const char *name);
> > > > >  
> > > > >  /***    private data structures    ***/
> > > > >  
> > > > > +/**
> > > > > + * struct critical -   Provides 'play' over critical clocks.  A clock can be
> > > > > + *                     marked as critical, meaning that it should not be
> > > > > + *                     disabled.  However, if a driver which is aware of the
> > > > > + *                     critical behaviour wants to control it, it can do so
> > > > > + *                     using clk_enable_critical() and clk_disable_critical().
> > > > > + *
> > > > > + * @enabled    Is clock critical?  Once set, doesn't change
> > > > > + * @leave_on   Self explanatory.  Can be disabled by knowledgeable drivers
> > > > > + */
> > > > > +struct critical {
> > > > > +       bool enabled;
> > > > > +       bool leave_on;
> > > > > +};
> > > > > +
> > > > >  struct clk_core {
> > > > >         const char              *name;
> > > > >         const struct clk_ops    *ops;
> > > > > @@ -75,6 +90,7 @@ struct clk_core {
> > > > >         struct dentry           *dentry;
> > > > >  #endif
> > > > >         struct kref             ref;
> > > > > +       struct critical         critical;
> > > > >  };
> > > > >  
> > > > >  struct clk {
> > > > > @@ -995,6 +1011,10 @@ static void clk_core_disable(struct clk_core *clk)
> > > > >         if (WARN_ON(clk->enable_count == 0))
> > > > >                 return;
> > > > >  
> > > > > +       /* Refuse to turn off a critical clock */
> > > > > +       if (clk->enable_count == 1 && clk->critical.leave_on)
> > > > > +               return;
> > > > > +
> > > > 
> > > > I think it should be handled by a separate counting. Otherwise, if you
> > > > have two users that marked the clock as critical, and then one of them
> > > > disable it...
> > > > 
> > > > >         if (--clk->enable_count > 0)
> > > > >                 return;
> > > > >  
> > > > > @@ -1037,6 +1057,13 @@ void clk_disable(struct clk *clk)
> > > > >  }
> > > > >  EXPORT_SYMBOL_GPL(clk_disable);
> > > > >  
> > > > > +void clk_disable_critical(struct clk *clk)
> > > > > +{
> > > > > +       clk->core->critical.leave_on = false;
> > > > 
> > > > .. you just lost the fact that it was critical in the first place.
> > > 
> > > I thought about both of these points, which is why I came up with this
> > > strategy.
> > > 
> > > Any device which uses the *_critical() API should a) have knowledge of
> > > what happens when a particular critical clock is gated and b) have
> > > thought about the consequences.
> > 
> > Indeed.
> > 
> > > I don't think we can use reference counting, because we'd need as
> > > many critical clock owners as there are critical clocks.
> > 
> > Which we can have if we replace the call to clk_prepare_enable you add
> > in your fourth patch in __set_critical_clocks.
> 
> What should it be replaced with?
> 
> > > Cast your mind back to the reasons for this critical clock API.  One
> > > of the most important intentions of this API is the requirement
> > > mitigation for each of the critical clocks to have an owner
> > > (driver).
> > > 
> > > With regards to your second point, that's what 'critical.enabled'
> > > is for.  Take a look at clk_enable_critical().
> > 
> > I don't think this addresses the issue, if you just throw more
> > customers at it, the issue remain with your implementation.
> > 
> > If you have three customers that used the critical API, and if on of
> > these calls clk_disable_critical, you're losing leave_on.
> 
> That's the idea.  See my point above, the one you replied "Indeed"
> to.  So when a driver uses clk_disable_critical() it's saying, "I know
> why this clock is a critical clock, and I know that nothing terrible
> will happen if I disable it, as I have that covered".  So then if it's
> not the last user to call clk_disable(), the last one out the door
> will be allowed to finally gate the clock, regardless whether it's
> critical aware or not.
> 
> Then, when we come to enable the clock again, the critical aware user
> then re-marks the clock as leave_on, so not critical un-aware user can
> take the final reference and disable the clock.
> 
> > Which means that if there's one of the two users left that calls
> > clk_disable on it, the clock will actually be disabled, which is
> > clearly not what we want to do, as we have still a user that want the
> > clock to be enabled.
> 
> That's not what happens (at least it shouldn't if I've coded it up
> right).  The API _still_ requires all of the users to give-up their
> reference.
> 
> > It would be much more robust to have another count for the critical
> > stuff, initialised to one by the __set_critical_clocks function.
> 
> If I understand you correctly, we already have a count.  We use the
> original reference count.  No need for one of our own.
> 
> Using your RAM Clock (Clock 4) as an example
> --------------------------------------------
> 
> Early start-up:
>   Clock 4 is marked as critical and a reference is taken (ref == 1)
> 
> Driver probe:
>   SPI enables Clock 4 (ref == 2)
>   I2C enables Clock 4 (ref == 3)
> 
> Suspend (without RAM driver's permission):
>   SPI disables Clock 4 (ref == 2)
>   I2C disables Clock 4 (ref == 1)
>   /*
>    * Clock won't be gated because:
>    *   .leave_on is True - can't dec final reference

I am clearly missing the point. The clock won't be gated because the
enable_count is still 1! What does .leave_on do here?

>    */
> 
> Suspend (with RAM driver's permission):
>   /* Order is unimportant */
>   SPI disables Clock 4 (ref == 2)
>   RAM disables Clock 4 (ref == 1) /* Won't turn off here (ref > 0)
>   I2C disables Clock 4 (ref == 0) /* (.leave_on == False) last ref can be taken */
>   /*
>    * Clock will be gated because:
>    *   .leave_on is False, so (ref == 0)

Again, .leave_on does nothing new here. We gate the clock because the
reference count is 0.

>    */
> 
> Resume:
>   /* Order is unimportant */
>   SPI enables Clock 4 (ref == 1)
>   RAM enables Clock 4 and re-enables .leave_on (ref == 2)
>   I2C enables Clock 4 (ref == 3)

Same again. As soon as RAM calls clk_enable_critical the ref count goes
up. .leave_on does nothing as far as I can tell. The all works because
of the reference counting, which already exists before this patch
series.

Regards,
Mike

> 
> Hopefully that clears things up.
> 
> Please tell me if the code doesn't reflect this strategy, or if you
> can see anything wrong with how it operates.
> 
> -- 
> Lee Jones
> Linaro STMicroelectronics Landing Team Lead
> Linaro.org │ Open source software for ARM SoCs
> Follow Linaro: Facebook | Twitter | Blog

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

* Re: [PATCH v7 3/5] clk: Supply the critical clock {init, enable, disable} framework
@ 2015-07-30  1:19             ` Michael Turquette
  0 siblings, 0 replies; 93+ messages in thread
From: Michael Turquette @ 2015-07-30  1:19 UTC (permalink / raw)
  To: Lee Jones, Maxime Ripard
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	kernel-F5mvAk5X5gdBDgjK7y7TUQ, sboyd-sgV2jX0FEOL9JmXXK+q4OQ,
	devicetree-u79uwXL29TY76Z2rM5mHXA, geert-Td1EMuHUCqxL1ZNQvxDV9g,
	s.hauer-bIcnvbaLZ9MEGnE8C9+IrQ

Quoting Lee Jones (2015-07-28 06:00:55)
> On Tue, 28 Jul 2015, Maxime Ripard wrote:
> 
> > On Mon, Jul 27, 2015 at 09:53:38AM +0100, Lee Jones wrote:
> > > On Mon, 27 Jul 2015, Maxime Ripard wrote:
> > > 
> > > > On Wed, Jul 22, 2015 at 02:04:13PM +0100, Lee Jones wrote:
> > > > > These new API calls will firstly provide a mechanisms to tag a clock as
> > > > > critical and secondly allow any knowledgeable driver to (un)gate clocks,
> > > > > even if they are marked as critical.
> > > > > 
> > > > > Suggested-by: Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
> > > > > Signed-off-by: Lee Jones <lee.jones-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> > > > > ---
> > > > >  drivers/clk/clk.c            | 45 ++++++++++++++++++++++++++++++++++++++++++++
> > > > >  include/linux/clk-provider.h |  2 ++
> > > > >  include/linux/clk.h          | 30 +++++++++++++++++++++++++++++
> > > > >  3 files changed, 77 insertions(+)
> > > > > 
> > > > > diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> > > > > index 61c3fc5..486b1da 100644
> > > > > --- a/drivers/clk/clk.c
> > > > > +++ b/drivers/clk/clk.c
> > > > > @@ -46,6 +46,21 @@ static struct clk_core *clk_core_lookup(const char *name);
> > > > >  
> > > > >  /***    private data structures    ***/
> > > > >  
> > > > > +/**
> > > > > + * struct critical -   Provides 'play' over critical clocks.  A clock can be
> > > > > + *                     marked as critical, meaning that it should not be
> > > > > + *                     disabled.  However, if a driver which is aware of the
> > > > > + *                     critical behaviour wants to control it, it can do so
> > > > > + *                     using clk_enable_critical() and clk_disable_critical().
> > > > > + *
> > > > > + * @enabled    Is clock critical?  Once set, doesn't change
> > > > > + * @leave_on   Self explanatory.  Can be disabled by knowledgeable drivers
> > > > > + */
> > > > > +struct critical {
> > > > > +       bool enabled;
> > > > > +       bool leave_on;
> > > > > +};
> > > > > +
> > > > >  struct clk_core {
> > > > >         const char              *name;
> > > > >         const struct clk_ops    *ops;
> > > > > @@ -75,6 +90,7 @@ struct clk_core {
> > > > >         struct dentry           *dentry;
> > > > >  #endif
> > > > >         struct kref             ref;
> > > > > +       struct critical         critical;
> > > > >  };
> > > > >  
> > > > >  struct clk {
> > > > > @@ -995,6 +1011,10 @@ static void clk_core_disable(struct clk_core *clk)
> > > > >         if (WARN_ON(clk->enable_count == 0))
> > > > >                 return;
> > > > >  
> > > > > +       /* Refuse to turn off a critical clock */
> > > > > +       if (clk->enable_count == 1 && clk->critical.leave_on)
> > > > > +               return;
> > > > > +
> > > > 
> > > > I think it should be handled by a separate counting. Otherwise, if you
> > > > have two users that marked the clock as critical, and then one of them
> > > > disable it...
> > > > 
> > > > >         if (--clk->enable_count > 0)
> > > > >                 return;
> > > > >  
> > > > > @@ -1037,6 +1057,13 @@ void clk_disable(struct clk *clk)
> > > > >  }
> > > > >  EXPORT_SYMBOL_GPL(clk_disable);
> > > > >  
> > > > > +void clk_disable_critical(struct clk *clk)
> > > > > +{
> > > > > +       clk->core->critical.leave_on = false;
> > > > 
> > > > .. you just lost the fact that it was critical in the first place.
> > > 
> > > I thought about both of these points, which is why I came up with this
> > > strategy.
> > > 
> > > Any device which uses the *_critical() API should a) have knowledge of
> > > what happens when a particular critical clock is gated and b) have
> > > thought about the consequences.
> > 
> > Indeed.
> > 
> > > I don't think we can use reference counting, because we'd need as
> > > many critical clock owners as there are critical clocks.
> > 
> > Which we can have if we replace the call to clk_prepare_enable you add
> > in your fourth patch in __set_critical_clocks.
> 
> What should it be replaced with?
> 
> > > Cast your mind back to the reasons for this critical clock API.  One
> > > of the most important intentions of this API is the requirement
> > > mitigation for each of the critical clocks to have an owner
> > > (driver).
> > > 
> > > With regards to your second point, that's what 'critical.enabled'
> > > is for.  Take a look at clk_enable_critical().
> > 
> > I don't think this addresses the issue, if you just throw more
> > customers at it, the issue remain with your implementation.
> > 
> > If you have three customers that used the critical API, and if on of
> > these calls clk_disable_critical, you're losing leave_on.
> 
> That's the idea.  See my point above, the one you replied "Indeed"
> to.  So when a driver uses clk_disable_critical() it's saying, "I know
> why this clock is a critical clock, and I know that nothing terrible
> will happen if I disable it, as I have that covered".  So then if it's
> not the last user to call clk_disable(), the last one out the door
> will be allowed to finally gate the clock, regardless whether it's
> critical aware or not.
> 
> Then, when we come to enable the clock again, the critical aware user
> then re-marks the clock as leave_on, so not critical un-aware user can
> take the final reference and disable the clock.
> 
> > Which means that if there's one of the two users left that calls
> > clk_disable on it, the clock will actually be disabled, which is
> > clearly not what we want to do, as we have still a user that want the
> > clock to be enabled.
> 
> That's not what happens (at least it shouldn't if I've coded it up
> right).  The API _still_ requires all of the users to give-up their
> reference.
> 
> > It would be much more robust to have another count for the critical
> > stuff, initialised to one by the __set_critical_clocks function.
> 
> If I understand you correctly, we already have a count.  We use the
> original reference count.  No need for one of our own.
> 
> Using your RAM Clock (Clock 4) as an example
> --------------------------------------------
> 
> Early start-up:
>   Clock 4 is marked as critical and a reference is taken (ref == 1)
> 
> Driver probe:
>   SPI enables Clock 4 (ref == 2)
>   I2C enables Clock 4 (ref == 3)
> 
> Suspend (without RAM driver's permission):
>   SPI disables Clock 4 (ref == 2)
>   I2C disables Clock 4 (ref == 1)
>   /*
>    * Clock won't be gated because:
>    *   .leave_on is True - can't dec final reference

I am clearly missing the point. The clock won't be gated because the
enable_count is still 1! What does .leave_on do here?

>    */
> 
> Suspend (with RAM driver's permission):
>   /* Order is unimportant */
>   SPI disables Clock 4 (ref == 2)
>   RAM disables Clock 4 (ref == 1) /* Won't turn off here (ref > 0)
>   I2C disables Clock 4 (ref == 0) /* (.leave_on == False) last ref can be taken */
>   /*
>    * Clock will be gated because:
>    *   .leave_on is False, so (ref == 0)

Again, .leave_on does nothing new here. We gate the clock because the
reference count is 0.

>    */
> 
> Resume:
>   /* Order is unimportant */
>   SPI enables Clock 4 (ref == 1)
>   RAM enables Clock 4 and re-enables .leave_on (ref == 2)
>   I2C enables Clock 4 (ref == 3)

Same again. As soon as RAM calls clk_enable_critical the ref count goes
up. .leave_on does nothing as far as I can tell. The all works because
of the reference counting, which already exists before this patch
series.

Regards,
Mike

> 
> Hopefully that clears things up.
> 
> Please tell me if the code doesn't reflect this strategy, or if you
> can see anything wrong with how it operates.
> 
> -- 
> Lee Jones
> Linaro STMicroelectronics Landing Team Lead
> Linaro.org │ Open source software for ARM SoCs
> Follow Linaro: Facebook | Twitter | Blog
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH v7 3/5] clk: Supply the critical clock {init, enable, disable} framework
@ 2015-07-30  1:19             ` Michael Turquette
  0 siblings, 0 replies; 93+ messages in thread
From: Michael Turquette @ 2015-07-30  1:19 UTC (permalink / raw)
  To: linux-arm-kernel

Quoting Lee Jones (2015-07-28 06:00:55)
> On Tue, 28 Jul 2015, Maxime Ripard wrote:
> 
> > On Mon, Jul 27, 2015 at 09:53:38AM +0100, Lee Jones wrote:
> > > On Mon, 27 Jul 2015, Maxime Ripard wrote:
> > > 
> > > > On Wed, Jul 22, 2015 at 02:04:13PM +0100, Lee Jones wrote:
> > > > > These new API calls will firstly provide a mechanisms to tag a clock as
> > > > > critical and secondly allow any knowledgeable driver to (un)gate clocks,
> > > > > even if they are marked as critical.
> > > > > 
> > > > > Suggested-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> > > > > Signed-off-by: Lee Jones <lee.jones@linaro.org>
> > > > > ---
> > > > >  drivers/clk/clk.c            | 45 ++++++++++++++++++++++++++++++++++++++++++++
> > > > >  include/linux/clk-provider.h |  2 ++
> > > > >  include/linux/clk.h          | 30 +++++++++++++++++++++++++++++
> > > > >  3 files changed, 77 insertions(+)
> > > > > 
> > > > > diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> > > > > index 61c3fc5..486b1da 100644
> > > > > --- a/drivers/clk/clk.c
> > > > > +++ b/drivers/clk/clk.c
> > > > > @@ -46,6 +46,21 @@ static struct clk_core *clk_core_lookup(const char *name);
> > > > >  
> > > > >  /***    private data structures    ***/
> > > > >  
> > > > > +/**
> > > > > + * struct critical -   Provides 'play' over critical clocks.  A clock can be
> > > > > + *                     marked as critical, meaning that it should not be
> > > > > + *                     disabled.  However, if a driver which is aware of the
> > > > > + *                     critical behaviour wants to control it, it can do so
> > > > > + *                     using clk_enable_critical() and clk_disable_critical().
> > > > > + *
> > > > > + * @enabled    Is clock critical?  Once set, doesn't change
> > > > > + * @leave_on   Self explanatory.  Can be disabled by knowledgeable drivers
> > > > > + */
> > > > > +struct critical {
> > > > > +       bool enabled;
> > > > > +       bool leave_on;
> > > > > +};
> > > > > +
> > > > >  struct clk_core {
> > > > >         const char              *name;
> > > > >         const struct clk_ops    *ops;
> > > > > @@ -75,6 +90,7 @@ struct clk_core {
> > > > >         struct dentry           *dentry;
> > > > >  #endif
> > > > >         struct kref             ref;
> > > > > +       struct critical         critical;
> > > > >  };
> > > > >  
> > > > >  struct clk {
> > > > > @@ -995,6 +1011,10 @@ static void clk_core_disable(struct clk_core *clk)
> > > > >         if (WARN_ON(clk->enable_count == 0))
> > > > >                 return;
> > > > >  
> > > > > +       /* Refuse to turn off a critical clock */
> > > > > +       if (clk->enable_count == 1 && clk->critical.leave_on)
> > > > > +               return;
> > > > > +
> > > > 
> > > > I think it should be handled by a separate counting. Otherwise, if you
> > > > have two users that marked the clock as critical, and then one of them
> > > > disable it...
> > > > 
> > > > >         if (--clk->enable_count > 0)
> > > > >                 return;
> > > > >  
> > > > > @@ -1037,6 +1057,13 @@ void clk_disable(struct clk *clk)
> > > > >  }
> > > > >  EXPORT_SYMBOL_GPL(clk_disable);
> > > > >  
> > > > > +void clk_disable_critical(struct clk *clk)
> > > > > +{
> > > > > +       clk->core->critical.leave_on = false;
> > > > 
> > > > .. you just lost the fact that it was critical in the first place.
> > > 
> > > I thought about both of these points, which is why I came up with this
> > > strategy.
> > > 
> > > Any device which uses the *_critical() API should a) have knowledge of
> > > what happens when a particular critical clock is gated and b) have
> > > thought about the consequences.
> > 
> > Indeed.
> > 
> > > I don't think we can use reference counting, because we'd need as
> > > many critical clock owners as there are critical clocks.
> > 
> > Which we can have if we replace the call to clk_prepare_enable you add
> > in your fourth patch in __set_critical_clocks.
> 
> What should it be replaced with?
> 
> > > Cast your mind back to the reasons for this critical clock API.  One
> > > of the most important intentions of this API is the requirement
> > > mitigation for each of the critical clocks to have an owner
> > > (driver).
> > > 
> > > With regards to your second point, that's what 'critical.enabled'
> > > is for.  Take a look at clk_enable_critical().
> > 
> > I don't think this addresses the issue, if you just throw more
> > customers at it, the issue remain with your implementation.
> > 
> > If you have three customers that used the critical API, and if on of
> > these calls clk_disable_critical, you're losing leave_on.
> 
> That's the idea.  See my point above, the one you replied "Indeed"
> to.  So when a driver uses clk_disable_critical() it's saying, "I know
> why this clock is a critical clock, and I know that nothing terrible
> will happen if I disable it, as I have that covered".  So then if it's
> not the last user to call clk_disable(), the last one out the door
> will be allowed to finally gate the clock, regardless whether it's
> critical aware or not.
> 
> Then, when we come to enable the clock again, the critical aware user
> then re-marks the clock as leave_on, so not critical un-aware user can
> take the final reference and disable the clock.
> 
> > Which means that if there's one of the two users left that calls
> > clk_disable on it, the clock will actually be disabled, which is
> > clearly not what we want to do, as we have still a user that want the
> > clock to be enabled.
> 
> That's not what happens (at least it shouldn't if I've coded it up
> right).  The API _still_ requires all of the users to give-up their
> reference.
> 
> > It would be much more robust to have another count for the critical
> > stuff, initialised to one by the __set_critical_clocks function.
> 
> If I understand you correctly, we already have a count.  We use the
> original reference count.  No need for one of our own.
> 
> Using your RAM Clock (Clock 4) as an example
> --------------------------------------------
> 
> Early start-up:
>   Clock 4 is marked as critical and a reference is taken (ref == 1)
> 
> Driver probe:
>   SPI enables Clock 4 (ref == 2)
>   I2C enables Clock 4 (ref == 3)
> 
> Suspend (without RAM driver's permission):
>   SPI disables Clock 4 (ref == 2)
>   I2C disables Clock 4 (ref == 1)
>   /*
>    * Clock won't be gated because:
>    *   .leave_on is True - can't dec final reference

I am clearly missing the point. The clock won't be gated because the
enable_count is still 1! What does .leave_on do here?

>    */
> 
> Suspend (with RAM driver's permission):
>   /* Order is unimportant */
>   SPI disables Clock 4 (ref == 2)
>   RAM disables Clock 4 (ref == 1) /* Won't turn off here (ref > 0)
>   I2C disables Clock 4 (ref == 0) /* (.leave_on == False) last ref can be taken */
>   /*
>    * Clock will be gated because:
>    *   .leave_on is False, so (ref == 0)

Again, .leave_on does nothing new here. We gate the clock because the
reference count is 0.

>    */
> 
> Resume:
>   /* Order is unimportant */
>   SPI enables Clock 4 (ref == 1)
>   RAM enables Clock 4 and re-enables .leave_on (ref == 2)
>   I2C enables Clock 4 (ref == 3)

Same again. As soon as RAM calls clk_enable_critical the ref count goes
up. .leave_on does nothing as far as I can tell. The all works because
of the reference counting, which already exists before this patch
series.

Regards,
Mike

> 
> Hopefully that clears things up.
> 
> Please tell me if the code doesn't reflect this strategy, or if you
> can see anything wrong with how it operates.
> 
> -- 
> Lee Jones
> Linaro STMicroelectronics Landing Team Lead
> Linaro.org ? Open source software for ARM SoCs
> Follow Linaro: Facebook | Twitter | Blog

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

* Re: [PATCH v7 3/5] clk: Supply the critical clock {init, enable, disable} framework
  2015-07-27  8:53       ` Lee Jones
  (?)
@ 2015-07-30  1:21         ` Michael Turquette
  -1 siblings, 0 replies; 93+ messages in thread
From: Michael Turquette @ 2015-07-30  1:21 UTC (permalink / raw)
  To: Lee Jones, Maxime Ripard
  Cc: linux-arm-kernel, linux-kernel, kernel, sboyd, devicetree, geert,
	s.hauer

Quoting Lee Jones (2015-07-27 01:53:38)
> On Mon, 27 Jul 2015, Maxime Ripard wrote:
> 
> > On Wed, Jul 22, 2015 at 02:04:13PM +0100, Lee Jones wrote:
> > > These new API calls will firstly provide a mechanisms to tag a clock as
> > > critical and secondly allow any knowledgeable driver to (un)gate clocks,
> > > even if they are marked as critical.
> > > 
> > > Suggested-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> > > Signed-off-by: Lee Jones <lee.jones@linaro.org>
> > > ---
> > >  drivers/clk/clk.c            | 45 ++++++++++++++++++++++++++++++++++++++++++++
> > >  include/linux/clk-provider.h |  2 ++
> > >  include/linux/clk.h          | 30 +++++++++++++++++++++++++++++
> > >  3 files changed, 77 insertions(+)
> > > 
> > > diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> > > index 61c3fc5..486b1da 100644
> > > --- a/drivers/clk/clk.c
> > > +++ b/drivers/clk/clk.c
> > > @@ -46,6 +46,21 @@ static struct clk_core *clk_core_lookup(const char *name);
> > >  
> > >  /***    private data structures    ***/
> > >  
> > > +/**
> > > + * struct critical -       Provides 'play' over critical clocks.  A clock can be
> > > + *                 marked as critical, meaning that it should not be
> > > + *                 disabled.  However, if a driver which is aware of the
> > > + *                 critical behaviour wants to control it, it can do so
> > > + *                 using clk_enable_critical() and clk_disable_critical().
> > > + *
> > > + * @enabled        Is clock critical?  Once set, doesn't change
> > > + * @leave_on       Self explanatory.  Can be disabled by knowledgeable drivers
> > > + */
> > > +struct critical {
> > > +   bool enabled;
> > > +   bool leave_on;
> > > +};
> > > +
> > >  struct clk_core {
> > >     const char              *name;
> > >     const struct clk_ops    *ops;
> > > @@ -75,6 +90,7 @@ struct clk_core {
> > >     struct dentry           *dentry;
> > >  #endif
> > >     struct kref             ref;
> > > +   struct critical         critical;
> > >  };
> > >  
> > >  struct clk {
> > > @@ -995,6 +1011,10 @@ static void clk_core_disable(struct clk_core *clk)
> > >     if (WARN_ON(clk->enable_count == 0))
> > >             return;
> > >  
> > > +   /* Refuse to turn off a critical clock */
> > > +   if (clk->enable_count == 1 && clk->critical.leave_on)
> > > +           return;
> > > +
> > 
> > I think it should be handled by a separate counting. Otherwise, if you
> > have two users that marked the clock as critical, and then one of them
> > disable it...
> > 
> > >     if (--clk->enable_count > 0)
> > >             return;
> > >  
> > > @@ -1037,6 +1057,13 @@ void clk_disable(struct clk *clk)
> > >  }
> > >  EXPORT_SYMBOL_GPL(clk_disable);
> > >  
> > > +void clk_disable_critical(struct clk *clk)
> > > +{
> > > +   clk->core->critical.leave_on = false;
> > 
> > .. you just lost the fact that it was critical in the first place.
> 
> I thought about both of these points, which is why I came up with this
> strategy.
> 
> Any device which uses the *_critical() API should a) have knowledge of
> what happens when a particular critical clock is gated and b) have
> thought about the consequences.

If this statement above is true then I fail to see the need for a new
api. A driver which has a really great idea of when it is safe or unsafe
to gate a clock should call clk_prepare_enable at probe and then only
call clk_disable_unprepare once it is safe to do so.

The existing bookkeeping in the clock framework will do the rest.

Regards,
Mike

> I don't think we can use reference
> counting, because we'd need as many critical clock owners as there are
> critical clocks.  Cast your mind back to the reasons for this critical
> clock API.  One of the most important intentions of this API is the
> requirement mitigation for each of the critical clocks to have an owner
> (driver).
> 
> With regards to your second point, that's what 'critical.enabled'
> is for.  Take a look at clk_enable_critical().
> 
> -- 
> Lee Jones
> Linaro STMicroelectronics Landing Team Lead
> Linaro.org │ Open source software for ARM SoCs
> Follow Linaro: Facebook | Twitter | Blog

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

* Re: [PATCH v7 3/5] clk: Supply the critical clock {init, enable, disable} framework
@ 2015-07-30  1:21         ` Michael Turquette
  0 siblings, 0 replies; 93+ messages in thread
From: Michael Turquette @ 2015-07-30  1:21 UTC (permalink / raw)
  To: Lee Jones, Maxime Ripard
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	kernel-F5mvAk5X5gdBDgjK7y7TUQ, sboyd-sgV2jX0FEOL9JmXXK+q4OQ,
	devicetree-u79uwXL29TY76Z2rM5mHXA, geert-Td1EMuHUCqxL1ZNQvxDV9g,
	s.hauer-bIcnvbaLZ9MEGnE8C9+IrQ

Quoting Lee Jones (2015-07-27 01:53:38)
> On Mon, 27 Jul 2015, Maxime Ripard wrote:
> 
> > On Wed, Jul 22, 2015 at 02:04:13PM +0100, Lee Jones wrote:
> > > These new API calls will firstly provide a mechanisms to tag a clock as
> > > critical and secondly allow any knowledgeable driver to (un)gate clocks,
> > > even if they are marked as critical.
> > > 
> > > Suggested-by: Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
> > > Signed-off-by: Lee Jones <lee.jones-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> > > ---
> > >  drivers/clk/clk.c            | 45 ++++++++++++++++++++++++++++++++++++++++++++
> > >  include/linux/clk-provider.h |  2 ++
> > >  include/linux/clk.h          | 30 +++++++++++++++++++++++++++++
> > >  3 files changed, 77 insertions(+)
> > > 
> > > diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> > > index 61c3fc5..486b1da 100644
> > > --- a/drivers/clk/clk.c
> > > +++ b/drivers/clk/clk.c
> > > @@ -46,6 +46,21 @@ static struct clk_core *clk_core_lookup(const char *name);
> > >  
> > >  /***    private data structures    ***/
> > >  
> > > +/**
> > > + * struct critical -       Provides 'play' over critical clocks.  A clock can be
> > > + *                 marked as critical, meaning that it should not be
> > > + *                 disabled.  However, if a driver which is aware of the
> > > + *                 critical behaviour wants to control it, it can do so
> > > + *                 using clk_enable_critical() and clk_disable_critical().
> > > + *
> > > + * @enabled        Is clock critical?  Once set, doesn't change
> > > + * @leave_on       Self explanatory.  Can be disabled by knowledgeable drivers
> > > + */
> > > +struct critical {
> > > +   bool enabled;
> > > +   bool leave_on;
> > > +};
> > > +
> > >  struct clk_core {
> > >     const char              *name;
> > >     const struct clk_ops    *ops;
> > > @@ -75,6 +90,7 @@ struct clk_core {
> > >     struct dentry           *dentry;
> > >  #endif
> > >     struct kref             ref;
> > > +   struct critical         critical;
> > >  };
> > >  
> > >  struct clk {
> > > @@ -995,6 +1011,10 @@ static void clk_core_disable(struct clk_core *clk)
> > >     if (WARN_ON(clk->enable_count == 0))
> > >             return;
> > >  
> > > +   /* Refuse to turn off a critical clock */
> > > +   if (clk->enable_count == 1 && clk->critical.leave_on)
> > > +           return;
> > > +
> > 
> > I think it should be handled by a separate counting. Otherwise, if you
> > have two users that marked the clock as critical, and then one of them
> > disable it...
> > 
> > >     if (--clk->enable_count > 0)
> > >             return;
> > >  
> > > @@ -1037,6 +1057,13 @@ void clk_disable(struct clk *clk)
> > >  }
> > >  EXPORT_SYMBOL_GPL(clk_disable);
> > >  
> > > +void clk_disable_critical(struct clk *clk)
> > > +{
> > > +   clk->core->critical.leave_on = false;
> > 
> > .. you just lost the fact that it was critical in the first place.
> 
> I thought about both of these points, which is why I came up with this
> strategy.
> 
> Any device which uses the *_critical() API should a) have knowledge of
> what happens when a particular critical clock is gated and b) have
> thought about the consequences.

If this statement above is true then I fail to see the need for a new
api. A driver which has a really great idea of when it is safe or unsafe
to gate a clock should call clk_prepare_enable at probe and then only
call clk_disable_unprepare once it is safe to do so.

The existing bookkeeping in the clock framework will do the rest.

Regards,
Mike

> I don't think we can use reference
> counting, because we'd need as many critical clock owners as there are
> critical clocks.  Cast your mind back to the reasons for this critical
> clock API.  One of the most important intentions of this API is the
> requirement mitigation for each of the critical clocks to have an owner
> (driver).
> 
> With regards to your second point, that's what 'critical.enabled'
> is for.  Take a look at clk_enable_critical().
> 
> -- 
> Lee Jones
> Linaro STMicroelectronics Landing Team Lead
> Linaro.org │ Open source software for ARM SoCs
> Follow Linaro: Facebook | Twitter | Blog
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH v7 3/5] clk: Supply the critical clock {init, enable, disable} framework
@ 2015-07-30  1:21         ` Michael Turquette
  0 siblings, 0 replies; 93+ messages in thread
From: Michael Turquette @ 2015-07-30  1:21 UTC (permalink / raw)
  To: linux-arm-kernel

Quoting Lee Jones (2015-07-27 01:53:38)
> On Mon, 27 Jul 2015, Maxime Ripard wrote:
> 
> > On Wed, Jul 22, 2015 at 02:04:13PM +0100, Lee Jones wrote:
> > > These new API calls will firstly provide a mechanisms to tag a clock as
> > > critical and secondly allow any knowledgeable driver to (un)gate clocks,
> > > even if they are marked as critical.
> > > 
> > > Suggested-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> > > Signed-off-by: Lee Jones <lee.jones@linaro.org>
> > > ---
> > >  drivers/clk/clk.c            | 45 ++++++++++++++++++++++++++++++++++++++++++++
> > >  include/linux/clk-provider.h |  2 ++
> > >  include/linux/clk.h          | 30 +++++++++++++++++++++++++++++
> > >  3 files changed, 77 insertions(+)
> > > 
> > > diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> > > index 61c3fc5..486b1da 100644
> > > --- a/drivers/clk/clk.c
> > > +++ b/drivers/clk/clk.c
> > > @@ -46,6 +46,21 @@ static struct clk_core *clk_core_lookup(const char *name);
> > >  
> > >  /***    private data structures    ***/
> > >  
> > > +/**
> > > + * struct critical -       Provides 'play' over critical clocks.  A clock can be
> > > + *                 marked as critical, meaning that it should not be
> > > + *                 disabled.  However, if a driver which is aware of the
> > > + *                 critical behaviour wants to control it, it can do so
> > > + *                 using clk_enable_critical() and clk_disable_critical().
> > > + *
> > > + * @enabled        Is clock critical?  Once set, doesn't change
> > > + * @leave_on       Self explanatory.  Can be disabled by knowledgeable drivers
> > > + */
> > > +struct critical {
> > > +   bool enabled;
> > > +   bool leave_on;
> > > +};
> > > +
> > >  struct clk_core {
> > >     const char              *name;
> > >     const struct clk_ops    *ops;
> > > @@ -75,6 +90,7 @@ struct clk_core {
> > >     struct dentry           *dentry;
> > >  #endif
> > >     struct kref             ref;
> > > +   struct critical         critical;
> > >  };
> > >  
> > >  struct clk {
> > > @@ -995,6 +1011,10 @@ static void clk_core_disable(struct clk_core *clk)
> > >     if (WARN_ON(clk->enable_count == 0))
> > >             return;
> > >  
> > > +   /* Refuse to turn off a critical clock */
> > > +   if (clk->enable_count == 1 && clk->critical.leave_on)
> > > +           return;
> > > +
> > 
> > I think it should be handled by a separate counting. Otherwise, if you
> > have two users that marked the clock as critical, and then one of them
> > disable it...
> > 
> > >     if (--clk->enable_count > 0)
> > >             return;
> > >  
> > > @@ -1037,6 +1057,13 @@ void clk_disable(struct clk *clk)
> > >  }
> > >  EXPORT_SYMBOL_GPL(clk_disable);
> > >  
> > > +void clk_disable_critical(struct clk *clk)
> > > +{
> > > +   clk->core->critical.leave_on = false;
> > 
> > .. you just lost the fact that it was critical in the first place.
> 
> I thought about both of these points, which is why I came up with this
> strategy.
> 
> Any device which uses the *_critical() API should a) have knowledge of
> what happens when a particular critical clock is gated and b) have
> thought about the consequences.

If this statement above is true then I fail to see the need for a new
api. A driver which has a really great idea of when it is safe or unsafe
to gate a clock should call clk_prepare_enable at probe and then only
call clk_disable_unprepare once it is safe to do so.

The existing bookkeeping in the clock framework will do the rest.

Regards,
Mike

> I don't think we can use reference
> counting, because we'd need as many critical clock owners as there are
> critical clocks.  Cast your mind back to the reasons for this critical
> clock API.  One of the most important intentions of this API is the
> requirement mitigation for each of the critical clocks to have an owner
> (driver).
> 
> With regards to your second point, that's what 'critical.enabled'
> is for.  Take a look at clk_enable_critical().
> 
> -- 
> Lee Jones
> Linaro STMicroelectronics Landing Team Lead
> Linaro.org ? Open source software for ARM SoCs
> Follow Linaro: Facebook | Twitter | Blog

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

* Re: [PATCH v7 0/5] clk: Provide support for always-on clocks
  2015-07-30  0:27   ` Michael Turquette
@ 2015-07-30  9:09     ` Lee Jones
  -1 siblings, 0 replies; 93+ messages in thread
From: Lee Jones @ 2015-07-30  9:09 UTC (permalink / raw)
  To: Michael Turquette
  Cc: linux-arm-kernel, linux-kernel, kernel, sboyd, devicetree, geert,
	maxime.ripard, s.hauer

On Wed, 29 Jul 2015, Michael Turquette wrote:
> Quoting Lee Jones (2015-07-22 06:04:10)
> > Lots of platforms contain clocks which if turned off would prove fatal.
> > The only way to recover from these catastrophic failures is to restart
> > the board(s).  Now, when a clock provider is registered with the
> > framework it is possible for a list of critical clocks to be supplied
> > which must be kept ungated.  Each clock mentioned in the newly
> > introduced 'critical-clock' property will be clk_prepare_enable()d
> > where the normal references will be taken.  This will prevent the
> > common clk framework from attempting to gate them during the normal
> > clk_disable_unused() and disable_clock() procedures.
> > 
> > Note that it will still be possible for knowledgeable drivers to turn
> > these clocks off using clk_{enable,disable}_critical() calls.
> 
> Hi Lee,
> 
> Thanks for submitting the series.
> 
> It has been a little while since v6. It would be helpful to remind me of
> why a new api is necessary, versus using the existing clk_prepare_unused
> call at the time that a clock is enabled.
> 
> I'm looking over the patches in detail now, but one question stands out:
> besides the DT use case, would a Linux device driver ever call
> clk_enable_critical instead of using clk_enable? If so, why?

Looks like a have a lot of emails to reply to.  Let's start here and
work our way through them, there are good answers to all of your
reasonable questions.

This set only supports the DT way of marking clocks as critical, due
to the fact that that's the way we'll be using the API.  I can spend
more time, once we have the ground work done, writing a similar
generic call (or expand the current one, whatever's deemed the best
approach) which will allow this to be possible from C.

> > Changelog:
> > v6 => v7:
> >   - Introduce API to enable and disable critical clocks
> >   - Rename 'always-on-clock' to 'critical-clock'
> > 
> > v5 => v6:
> >   - Use of_clk_get_from_provider() instead of of_clk_get_by_clkspec()
> >   - Explicitly describe expected DT values
> >   - Be pedantic with regards to printk() format specifiers
> > 
> > vX => v5:
> >   Implementations have changed drastically between versions, thus I
> >   would like for this set to be thought of independently from its
> >   predecessors.  The only reason for identifying as 'v5' is ease of
> >   differentiation on the list, which stems from the confusion caused
> >   by submitting 'v4' as a separate entity.
> > 
> > Lee Jones (5):
> >   ARM: sti: stih407-family: Supply defines for CLOCKGEN A0
> >   ARM: sti: stih410-clocks: Identify critical clocks
> >   clk: Supply the critical clock {init, enable, disable} framework
> >   clk: Provide critical clock support
> >   clk: dt: Introduce binding for critical clock support
> > 
> >  .../devicetree/bindings/clock/clock-bindings.txt   | 39 +++++++++++++++++++
> >  arch/arm/boot/dts/stih410-clock.dtsi               | 10 +++++
> >  drivers/clk/clk-conf.c                             | 45 +++++++++++++++++++++-
> >  drivers/clk/clk.c                                  | 45 ++++++++++++++++++++++
> >  include/dt-bindings/clock/stih407-clks.h           |  4 ++
> >  include/linux/clk-provider.h                       |  2 +
> >  include/linux/clk.h                                | 30 +++++++++++++++
> >  7 files changed, 174 insertions(+), 1 deletion(-)
> > 

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

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

* [PATCH v7 0/5] clk: Provide support for always-on clocks
@ 2015-07-30  9:09     ` Lee Jones
  0 siblings, 0 replies; 93+ messages in thread
From: Lee Jones @ 2015-07-30  9:09 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, 29 Jul 2015, Michael Turquette wrote:
> Quoting Lee Jones (2015-07-22 06:04:10)
> > Lots of platforms contain clocks which if turned off would prove fatal.
> > The only way to recover from these catastrophic failures is to restart
> > the board(s).  Now, when a clock provider is registered with the
> > framework it is possible for a list of critical clocks to be supplied
> > which must be kept ungated.  Each clock mentioned in the newly
> > introduced 'critical-clock' property will be clk_prepare_enable()d
> > where the normal references will be taken.  This will prevent the
> > common clk framework from attempting to gate them during the normal
> > clk_disable_unused() and disable_clock() procedures.
> > 
> > Note that it will still be possible for knowledgeable drivers to turn
> > these clocks off using clk_{enable,disable}_critical() calls.
> 
> Hi Lee,
> 
> Thanks for submitting the series.
> 
> It has been a little while since v6. It would be helpful to remind me of
> why a new api is necessary, versus using the existing clk_prepare_unused
> call at the time that a clock is enabled.
> 
> I'm looking over the patches in detail now, but one question stands out:
> besides the DT use case, would a Linux device driver ever call
> clk_enable_critical instead of using clk_enable? If so, why?

Looks like a have a lot of emails to reply to.  Let's start here and
work our way through them, there are good answers to all of your
reasonable questions.

This set only supports the DT way of marking clocks as critical, due
to the fact that that's the way we'll be using the API.  I can spend
more time, once we have the ground work done, writing a similar
generic call (or expand the current one, whatever's deemed the best
approach) which will allow this to be possible from C.

> > Changelog:
> > v6 => v7:
> >   - Introduce API to enable and disable critical clocks
> >   - Rename 'always-on-clock' to 'critical-clock'
> > 
> > v5 => v6:
> >   - Use of_clk_get_from_provider() instead of of_clk_get_by_clkspec()
> >   - Explicitly describe expected DT values
> >   - Be pedantic with regards to printk() format specifiers
> > 
> > vX => v5:
> >   Implementations have changed drastically between versions, thus I
> >   would like for this set to be thought of independently from its
> >   predecessors.  The only reason for identifying as 'v5' is ease of
> >   differentiation on the list, which stems from the confusion caused
> >   by submitting 'v4' as a separate entity.
> > 
> > Lee Jones (5):
> >   ARM: sti: stih407-family: Supply defines for CLOCKGEN A0
> >   ARM: sti: stih410-clocks: Identify critical clocks
> >   clk: Supply the critical clock {init, enable, disable} framework
> >   clk: Provide critical clock support
> >   clk: dt: Introduce binding for critical clock support
> > 
> >  .../devicetree/bindings/clock/clock-bindings.txt   | 39 +++++++++++++++++++
> >  arch/arm/boot/dts/stih410-clock.dtsi               | 10 +++++
> >  drivers/clk/clk-conf.c                             | 45 +++++++++++++++++++++-
> >  drivers/clk/clk.c                                  | 45 ++++++++++++++++++++++
> >  include/dt-bindings/clock/stih407-clks.h           |  4 ++
> >  include/linux/clk-provider.h                       |  2 +
> >  include/linux/clk.h                                | 30 +++++++++++++++
> >  7 files changed, 174 insertions(+), 1 deletion(-)
> > 

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org ? Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

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

* Re: [PATCH v7 3/5] clk: Supply the critical clock {init, enable, disable} framework
  2015-07-30  1:21         ` Michael Turquette
  (?)
@ 2015-07-30  9:21           ` Lee Jones
  -1 siblings, 0 replies; 93+ messages in thread
From: Lee Jones @ 2015-07-30  9:21 UTC (permalink / raw)
  To: Michael Turquette
  Cc: Maxime Ripard, linux-arm-kernel, linux-kernel, kernel, sboyd,
	devicetree, geert, s.hauer

On Wed, 29 Jul 2015, Michael Turquette wrote:
> Quoting Lee Jones (2015-07-27 01:53:38)
> > On Mon, 27 Jul 2015, Maxime Ripard wrote:
> > 
> > > On Wed, Jul 22, 2015 at 02:04:13PM +0100, Lee Jones wrote:
> > > > These new API calls will firstly provide a mechanisms to tag a clock as
> > > > critical and secondly allow any knowledgeable driver to (un)gate clocks,
> > > > even if they are marked as critical.
> > > > 
> > > > Suggested-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> > > > Signed-off-by: Lee Jones <lee.jones@linaro.org>
> > > > ---
> > > >  drivers/clk/clk.c            | 45 ++++++++++++++++++++++++++++++++++++++++++++
> > > >  include/linux/clk-provider.h |  2 ++
> > > >  include/linux/clk.h          | 30 +++++++++++++++++++++++++++++
> > > >  3 files changed, 77 insertions(+)
> > > > 
> > > > diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> > > > index 61c3fc5..486b1da 100644
> > > > --- a/drivers/clk/clk.c
> > > > +++ b/drivers/clk/clk.c
> > > > @@ -46,6 +46,21 @@ static struct clk_core *clk_core_lookup(const char *name);
> > > >  
> > > >  /***    private data structures    ***/
> > > >  
> > > > +/**
> > > > + * struct critical -       Provides 'play' over critical clocks.  A clock can be
> > > > + *                 marked as critical, meaning that it should not be
> > > > + *                 disabled.  However, if a driver which is aware of the
> > > > + *                 critical behaviour wants to control it, it can do so
> > > > + *                 using clk_enable_critical() and clk_disable_critical().
> > > > + *
> > > > + * @enabled        Is clock critical?  Once set, doesn't change
> > > > + * @leave_on       Self explanatory.  Can be disabled by knowledgeable drivers
> > > > + */
> > > > +struct critical {
> > > > +   bool enabled;
> > > > +   bool leave_on;
> > > > +};
> > > > +
> > > >  struct clk_core {
> > > >     const char              *name;
> > > >     const struct clk_ops    *ops;
> > > > @@ -75,6 +90,7 @@ struct clk_core {
> > > >     struct dentry           *dentry;
> > > >  #endif
> > > >     struct kref             ref;
> > > > +   struct critical         critical;
> > > >  };
> > > >  
> > > >  struct clk {
> > > > @@ -995,6 +1011,10 @@ static void clk_core_disable(struct clk_core *clk)
> > > >     if (WARN_ON(clk->enable_count == 0))
> > > >             return;
> > > >  
> > > > +   /* Refuse to turn off a critical clock */
> > > > +   if (clk->enable_count == 1 && clk->critical.leave_on)
> > > > +           return;
> > > > +
> > > 
> > > I think it should be handled by a separate counting. Otherwise, if you
> > > have two users that marked the clock as critical, and then one of them
> > > disable it...
> > > 
> > > >     if (--clk->enable_count > 0)
> > > >             return;
> > > >  
> > > > @@ -1037,6 +1057,13 @@ void clk_disable(struct clk *clk)
> > > >  }
> > > >  EXPORT_SYMBOL_GPL(clk_disable);
> > > >  
> > > > +void clk_disable_critical(struct clk *clk)
> > > > +{
> > > > +   clk->core->critical.leave_on = false;
> > > 
> > > .. you just lost the fact that it was critical in the first place.
> > 
> > I thought about both of these points, which is why I came up with this
> > strategy.
> > 
> > Any device which uses the *_critical() API should a) have knowledge of
> > what happens when a particular critical clock is gated and b) have
> > thought about the consequences.
> 
> If this statement above is true then I fail to see the need for a new
> api. A driver which has a really great idea of when it is safe or unsafe
> to gate a clock should call clk_prepare_enable at probe and then only
> call clk_disable_unprepare once it is safe to do so.
> 
> The existing bookkeeping in the clock framework will do the rest.

I think you are viewing this particular API back-to-front.  The idea
is to mark all of the critical clocks at start-up by taking a
reference.  Then, if there are no knowledgable drivers who wish to
turn the clock off, the CCF will leave the clock ungated becuase the
reference count will always be >0.

The clk_{disable,enable}_critical() calls are to be used by
knowledgable drivers to say "[disable] I know what I'm doing and it's
okay for this clock to be turned off" and "[enable] right I'm done
with this clock now, let's turn it back on and mark it back as
critical, so no one else can turn it off".

To put things simply, the knowledgable driver will _not_ be enabling
the clock in the first place.  The first interaction it has with it is
to gate it.  Then, once it's done, it will enable it again and mark it
back up as critical.

Still confused ... let's go on another Q in one of your other emails
for another way of putting it.

> > I don't think we can use reference
> > counting, because we'd need as many critical clock owners as there are
> > critical clocks.  Cast your mind back to the reasons for this critical
> > clock API.  One of the most important intentions of this API is the
> > requirement mitigation for each of the critical clocks to have an owner
> > (driver).
> > 
> > With regards to your second point, that's what 'critical.enabled'
> > is for.  Take a look at clk_enable_critical().
> > 

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

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

* Re: [PATCH v7 3/5] clk: Supply the critical clock {init, enable, disable} framework
@ 2015-07-30  9:21           ` Lee Jones
  0 siblings, 0 replies; 93+ messages in thread
From: Lee Jones @ 2015-07-30  9:21 UTC (permalink / raw)
  To: Michael Turquette
  Cc: Maxime Ripard, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	kernel-F5mvAk5X5gdBDgjK7y7TUQ, sboyd-sgV2jX0FEOL9JmXXK+q4OQ,
	devicetree-u79uwXL29TY76Z2rM5mHXA, geert-Td1EMuHUCqxL1ZNQvxDV9g,
	s.hauer-bIcnvbaLZ9MEGnE8C9+IrQ

On Wed, 29 Jul 2015, Michael Turquette wrote:
> Quoting Lee Jones (2015-07-27 01:53:38)
> > On Mon, 27 Jul 2015, Maxime Ripard wrote:
> > 
> > > On Wed, Jul 22, 2015 at 02:04:13PM +0100, Lee Jones wrote:
> > > > These new API calls will firstly provide a mechanisms to tag a clock as
> > > > critical and secondly allow any knowledgeable driver to (un)gate clocks,
> > > > even if they are marked as critical.
> > > > 
> > > > Suggested-by: Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
> > > > Signed-off-by: Lee Jones <lee.jones-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> > > > ---
> > > >  drivers/clk/clk.c            | 45 ++++++++++++++++++++++++++++++++++++++++++++
> > > >  include/linux/clk-provider.h |  2 ++
> > > >  include/linux/clk.h          | 30 +++++++++++++++++++++++++++++
> > > >  3 files changed, 77 insertions(+)
> > > > 
> > > > diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> > > > index 61c3fc5..486b1da 100644
> > > > --- a/drivers/clk/clk.c
> > > > +++ b/drivers/clk/clk.c
> > > > @@ -46,6 +46,21 @@ static struct clk_core *clk_core_lookup(const char *name);
> > > >  
> > > >  /***    private data structures    ***/
> > > >  
> > > > +/**
> > > > + * struct critical -       Provides 'play' over critical clocks.  A clock can be
> > > > + *                 marked as critical, meaning that it should not be
> > > > + *                 disabled.  However, if a driver which is aware of the
> > > > + *                 critical behaviour wants to control it, it can do so
> > > > + *                 using clk_enable_critical() and clk_disable_critical().
> > > > + *
> > > > + * @enabled        Is clock critical?  Once set, doesn't change
> > > > + * @leave_on       Self explanatory.  Can be disabled by knowledgeable drivers
> > > > + */
> > > > +struct critical {
> > > > +   bool enabled;
> > > > +   bool leave_on;
> > > > +};
> > > > +
> > > >  struct clk_core {
> > > >     const char              *name;
> > > >     const struct clk_ops    *ops;
> > > > @@ -75,6 +90,7 @@ struct clk_core {
> > > >     struct dentry           *dentry;
> > > >  #endif
> > > >     struct kref             ref;
> > > > +   struct critical         critical;
> > > >  };
> > > >  
> > > >  struct clk {
> > > > @@ -995,6 +1011,10 @@ static void clk_core_disable(struct clk_core *clk)
> > > >     if (WARN_ON(clk->enable_count == 0))
> > > >             return;
> > > >  
> > > > +   /* Refuse to turn off a critical clock */
> > > > +   if (clk->enable_count == 1 && clk->critical.leave_on)
> > > > +           return;
> > > > +
> > > 
> > > I think it should be handled by a separate counting. Otherwise, if you
> > > have two users that marked the clock as critical, and then one of them
> > > disable it...
> > > 
> > > >     if (--clk->enable_count > 0)
> > > >             return;
> > > >  
> > > > @@ -1037,6 +1057,13 @@ void clk_disable(struct clk *clk)
> > > >  }
> > > >  EXPORT_SYMBOL_GPL(clk_disable);
> > > >  
> > > > +void clk_disable_critical(struct clk *clk)
> > > > +{
> > > > +   clk->core->critical.leave_on = false;
> > > 
> > > .. you just lost the fact that it was critical in the first place.
> > 
> > I thought about both of these points, which is why I came up with this
> > strategy.
> > 
> > Any device which uses the *_critical() API should a) have knowledge of
> > what happens when a particular critical clock is gated and b) have
> > thought about the consequences.
> 
> If this statement above is true then I fail to see the need for a new
> api. A driver which has a really great idea of when it is safe or unsafe
> to gate a clock should call clk_prepare_enable at probe and then only
> call clk_disable_unprepare once it is safe to do so.
> 
> The existing bookkeeping in the clock framework will do the rest.

I think you are viewing this particular API back-to-front.  The idea
is to mark all of the critical clocks at start-up by taking a
reference.  Then, if there are no knowledgable drivers who wish to
turn the clock off, the CCF will leave the clock ungated becuase the
reference count will always be >0.

The clk_{disable,enable}_critical() calls are to be used by
knowledgable drivers to say "[disable] I know what I'm doing and it's
okay for this clock to be turned off" and "[enable] right I'm done
with this clock now, let's turn it back on and mark it back as
critical, so no one else can turn it off".

To put things simply, the knowledgable driver will _not_ be enabling
the clock in the first place.  The first interaction it has with it is
to gate it.  Then, once it's done, it will enable it again and mark it
back up as critical.

Still confused ... let's go on another Q in one of your other emails
for another way of putting it.

> > I don't think we can use reference
> > counting, because we'd need as many critical clock owners as there are
> > critical clocks.  Cast your mind back to the reasons for this critical
> > clock API.  One of the most important intentions of this API is the
> > requirement mitigation for each of the critical clocks to have an owner
> > (driver).
> > 
> > With regards to your second point, that's what 'critical.enabled'
> > is for.  Take a look at clk_enable_critical().
> > 

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH v7 3/5] clk: Supply the critical clock {init, enable, disable} framework
@ 2015-07-30  9:21           ` Lee Jones
  0 siblings, 0 replies; 93+ messages in thread
From: Lee Jones @ 2015-07-30  9:21 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, 29 Jul 2015, Michael Turquette wrote:
> Quoting Lee Jones (2015-07-27 01:53:38)
> > On Mon, 27 Jul 2015, Maxime Ripard wrote:
> > 
> > > On Wed, Jul 22, 2015 at 02:04:13PM +0100, Lee Jones wrote:
> > > > These new API calls will firstly provide a mechanisms to tag a clock as
> > > > critical and secondly allow any knowledgeable driver to (un)gate clocks,
> > > > even if they are marked as critical.
> > > > 
> > > > Suggested-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> > > > Signed-off-by: Lee Jones <lee.jones@linaro.org>
> > > > ---
> > > >  drivers/clk/clk.c            | 45 ++++++++++++++++++++++++++++++++++++++++++++
> > > >  include/linux/clk-provider.h |  2 ++
> > > >  include/linux/clk.h          | 30 +++++++++++++++++++++++++++++
> > > >  3 files changed, 77 insertions(+)
> > > > 
> > > > diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> > > > index 61c3fc5..486b1da 100644
> > > > --- a/drivers/clk/clk.c
> > > > +++ b/drivers/clk/clk.c
> > > > @@ -46,6 +46,21 @@ static struct clk_core *clk_core_lookup(const char *name);
> > > >  
> > > >  /***    private data structures    ***/
> > > >  
> > > > +/**
> > > > + * struct critical -       Provides 'play' over critical clocks.  A clock can be
> > > > + *                 marked as critical, meaning that it should not be
> > > > + *                 disabled.  However, if a driver which is aware of the
> > > > + *                 critical behaviour wants to control it, it can do so
> > > > + *                 using clk_enable_critical() and clk_disable_critical().
> > > > + *
> > > > + * @enabled        Is clock critical?  Once set, doesn't change
> > > > + * @leave_on       Self explanatory.  Can be disabled by knowledgeable drivers
> > > > + */
> > > > +struct critical {
> > > > +   bool enabled;
> > > > +   bool leave_on;
> > > > +};
> > > > +
> > > >  struct clk_core {
> > > >     const char              *name;
> > > >     const struct clk_ops    *ops;
> > > > @@ -75,6 +90,7 @@ struct clk_core {
> > > >     struct dentry           *dentry;
> > > >  #endif
> > > >     struct kref             ref;
> > > > +   struct critical         critical;
> > > >  };
> > > >  
> > > >  struct clk {
> > > > @@ -995,6 +1011,10 @@ static void clk_core_disable(struct clk_core *clk)
> > > >     if (WARN_ON(clk->enable_count == 0))
> > > >             return;
> > > >  
> > > > +   /* Refuse to turn off a critical clock */
> > > > +   if (clk->enable_count == 1 && clk->critical.leave_on)
> > > > +           return;
> > > > +
> > > 
> > > I think it should be handled by a separate counting. Otherwise, if you
> > > have two users that marked the clock as critical, and then one of them
> > > disable it...
> > > 
> > > >     if (--clk->enable_count > 0)
> > > >             return;
> > > >  
> > > > @@ -1037,6 +1057,13 @@ void clk_disable(struct clk *clk)
> > > >  }
> > > >  EXPORT_SYMBOL_GPL(clk_disable);
> > > >  
> > > > +void clk_disable_critical(struct clk *clk)
> > > > +{
> > > > +   clk->core->critical.leave_on = false;
> > > 
> > > .. you just lost the fact that it was critical in the first place.
> > 
> > I thought about both of these points, which is why I came up with this
> > strategy.
> > 
> > Any device which uses the *_critical() API should a) have knowledge of
> > what happens when a particular critical clock is gated and b) have
> > thought about the consequences.
> 
> If this statement above is true then I fail to see the need for a new
> api. A driver which has a really great idea of when it is safe or unsafe
> to gate a clock should call clk_prepare_enable at probe and then only
> call clk_disable_unprepare once it is safe to do so.
> 
> The existing bookkeeping in the clock framework will do the rest.

I think you are viewing this particular API back-to-front.  The idea
is to mark all of the critical clocks at start-up by taking a
reference.  Then, if there are no knowledgable drivers who wish to
turn the clock off, the CCF will leave the clock ungated becuase the
reference count will always be >0.

The clk_{disable,enable}_critical() calls are to be used by
knowledgable drivers to say "[disable] I know what I'm doing and it's
okay for this clock to be turned off" and "[enable] right I'm done
with this clock now, let's turn it back on and mark it back as
critical, so no one else can turn it off".

To put things simply, the knowledgable driver will _not_ be enabling
the clock in the first place.  The first interaction it has with it is
to gate it.  Then, once it's done, it will enable it again and mark it
back up as critical.

Still confused ... let's go on another Q in one of your other emails
for another way of putting it.

> > I don't think we can use reference
> > counting, because we'd need as many critical clock owners as there are
> > critical clocks.  Cast your mind back to the reasons for this critical
> > clock API.  One of the most important intentions of this API is the
> > requirement mitigation for each of the critical clocks to have an owner
> > (driver).
> > 
> > With regards to your second point, that's what 'critical.enabled'
> > is for.  Take a look at clk_enable_critical().
> > 

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org ? Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

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

* Re: [PATCH v7 5/5] clk: dt: Introduce binding for critical clock support
  2015-07-28  9:32         ` Maxime Ripard
@ 2015-07-30  9:23           ` Lee Jones
  -1 siblings, 0 replies; 93+ messages in thread
From: Lee Jones @ 2015-07-30  9:23 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: linux-arm-kernel, linux-kernel, kernel, mturquette, sboyd,
	devicetree, geert, s.hauer

On Tue, 28 Jul 2015, Maxime Ripard wrote:

> On Mon, Jul 27, 2015 at 08:31:49AM +0100, Lee Jones wrote:
> > On Mon, 27 Jul 2015, Maxime Ripard wrote:
> > 
> > > Hi Lee,
> > > 
> > > On Wed, Jul 22, 2015 at 02:04:15PM +0100, Lee Jones wrote:
> > > > Signed-off-by: Lee Jones <lee.jones@linaro.org>
> > > > ---
> > > >  .../devicetree/bindings/clock/clock-bindings.txt   | 39 ++++++++++++++++++++++
> > > >  1 file changed, 39 insertions(+)
> > > > 
> > > > diff --git a/Documentation/devicetree/bindings/clock/clock-bindings.txt b/Documentation/devicetree/bindings/clock/clock-bindings.txt
> > > > index 06fc6d5..4137034 100644
> > > > --- a/Documentation/devicetree/bindings/clock/clock-bindings.txt
> > > > +++ b/Documentation/devicetree/bindings/clock/clock-bindings.txt
> > > > @@ -44,6 +44,45 @@ For example:
> > > >    clocks by index. The names should reflect the clock output signal
> > > >    names for the device.
> > > >  
> > > > +critical-clock:	Some hardware contains bunches of clocks which, in normal
> > > > +		circumstances, must never be turned off.  If drivers a) fail to
> > > > +		obtain a reference to any of these or b) give up a previously
> > > > +		obtained reference during suspend, it is possible that some
> > > > +		Operating Systems might attempt to disable them to save power.
> > > > +		If this happens a platform can fail irrecoverably as a result.
> > > > +		Usually the only way to recover from these failures is to
> > > > +		reboot.
> > > > +
> > > > +		To avoid either of these two scenarios from catastrophically
> > > > +		disabling an otherwise perfectly healthy running system,
> > > > +		clocks can be identified as 'critical' using this property from
> > > > +		inside a clocksource's node.
> > > > +
> > > > +		This property is not to be abused.  It is only to be used to
> > > > +		protect platforms from being crippled by gated clocks, NOT as a
> > > > +		convenience function to avoid using the framework correctly
> > > > +		inside device drivers.
> > > > +
> > > > +		Expected values are hardware clock indices.  If the
> > > > +		clock-indices property (see below) is used, then supplied
> > > > +		values must correspond to one of the listed identifiers.
> > > > +		Using the clock-indices example below, hardware clock <2>
> > > > +		is missing, therefore it is considered invalid to then
> > > > +		list clock <2> as a critical clock.
> > > 
> > > I think we should also consider having it simply as a boolean. Using
> > > indices for clocks that don't have any (for example because it only
> > > provides a single clock) seem to not really make much sense.
> > 
> > Then how would you distinguish between the clocks if the provider
> > provides more than a single clock?
> 
> What I had in mind was that, you would have three cases:
> 
>   - critical-clocks is not there: no clocks are made critical
> 
>   - critical-clocks is there, but doesn't have any values: all the
>     clocks provided are marked critical
> 
>   - critical-clocks is there and it has a list of values: only the
>     clocks listed are marked critical.
> 
> Does that make sense to you?

Yep, sounds good.

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

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

* [PATCH v7 5/5] clk: dt: Introduce binding for critical clock support
@ 2015-07-30  9:23           ` Lee Jones
  0 siblings, 0 replies; 93+ messages in thread
From: Lee Jones @ 2015-07-30  9:23 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, 28 Jul 2015, Maxime Ripard wrote:

> On Mon, Jul 27, 2015 at 08:31:49AM +0100, Lee Jones wrote:
> > On Mon, 27 Jul 2015, Maxime Ripard wrote:
> > 
> > > Hi Lee,
> > > 
> > > On Wed, Jul 22, 2015 at 02:04:15PM +0100, Lee Jones wrote:
> > > > Signed-off-by: Lee Jones <lee.jones@linaro.org>
> > > > ---
> > > >  .../devicetree/bindings/clock/clock-bindings.txt   | 39 ++++++++++++++++++++++
> > > >  1 file changed, 39 insertions(+)
> > > > 
> > > > diff --git a/Documentation/devicetree/bindings/clock/clock-bindings.txt b/Documentation/devicetree/bindings/clock/clock-bindings.txt
> > > > index 06fc6d5..4137034 100644
> > > > --- a/Documentation/devicetree/bindings/clock/clock-bindings.txt
> > > > +++ b/Documentation/devicetree/bindings/clock/clock-bindings.txt
> > > > @@ -44,6 +44,45 @@ For example:
> > > >    clocks by index. The names should reflect the clock output signal
> > > >    names for the device.
> > > >  
> > > > +critical-clock:	Some hardware contains bunches of clocks which, in normal
> > > > +		circumstances, must never be turned off.  If drivers a) fail to
> > > > +		obtain a reference to any of these or b) give up a previously
> > > > +		obtained reference during suspend, it is possible that some
> > > > +		Operating Systems might attempt to disable them to save power.
> > > > +		If this happens a platform can fail irrecoverably as a result.
> > > > +		Usually the only way to recover from these failures is to
> > > > +		reboot.
> > > > +
> > > > +		To avoid either of these two scenarios from catastrophically
> > > > +		disabling an otherwise perfectly healthy running system,
> > > > +		clocks can be identified as 'critical' using this property from
> > > > +		inside a clocksource's node.
> > > > +
> > > > +		This property is not to be abused.  It is only to be used to
> > > > +		protect platforms from being crippled by gated clocks, NOT as a
> > > > +		convenience function to avoid using the framework correctly
> > > > +		inside device drivers.
> > > > +
> > > > +		Expected values are hardware clock indices.  If the
> > > > +		clock-indices property (see below) is used, then supplied
> > > > +		values must correspond to one of the listed identifiers.
> > > > +		Using the clock-indices example below, hardware clock <2>
> > > > +		is missing, therefore it is considered invalid to then
> > > > +		list clock <2> as a critical clock.
> > > 
> > > I think we should also consider having it simply as a boolean. Using
> > > indices for clocks that don't have any (for example because it only
> > > provides a single clock) seem to not really make much sense.
> > 
> > Then how would you distinguish between the clocks if the provider
> > provides more than a single clock?
> 
> What I had in mind was that, you would have three cases:
> 
>   - critical-clocks is not there: no clocks are made critical
> 
>   - critical-clocks is there, but doesn't have any values: all the
>     clocks provided are marked critical
> 
>   - critical-clocks is there and it has a list of values: only the
>     clocks listed are marked critical.
> 
> Does that make sense to you?

Yep, sounds good.

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org ? Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

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

* Re: [PATCH v7 3/5] clk: Supply the critical clock {init, enable, disable} framework
  2015-07-30  1:19             ` Michael Turquette
  (?)
@ 2015-07-30  9:50               ` Lee Jones
  -1 siblings, 0 replies; 93+ messages in thread
From: Lee Jones @ 2015-07-30  9:50 UTC (permalink / raw)
  To: Michael Turquette
  Cc: Maxime Ripard, linux-arm-kernel, linux-kernel, kernel, sboyd,
	devicetree, geert, s.hauer

On Wed, 29 Jul 2015, Michael Turquette wrote:
> Quoting Lee Jones (2015-07-28 06:00:55)
> > On Tue, 28 Jul 2015, Maxime Ripard wrote:
> > 
> > > On Mon, Jul 27, 2015 at 09:53:38AM +0100, Lee Jones wrote:
> > > > On Mon, 27 Jul 2015, Maxime Ripard wrote:
> > > > 
> > > > > On Wed, Jul 22, 2015 at 02:04:13PM +0100, Lee Jones wrote:
> > > > > > These new API calls will firstly provide a mechanisms to tag a clock as
> > > > > > critical and secondly allow any knowledgeable driver to (un)gate clocks,
> > > > > > even if they are marked as critical.
> > > > > > 
> > > > > > Suggested-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> > > > > > Signed-off-by: Lee Jones <lee.jones@linaro.org>
> > > > > > ---
> > > > > >  drivers/clk/clk.c            | 45 ++++++++++++++++++++++++++++++++++++++++++++
> > > > > >  include/linux/clk-provider.h |  2 ++
> > > > > >  include/linux/clk.h          | 30 +++++++++++++++++++++++++++++
> > > > > >  3 files changed, 77 insertions(+)
> > > > > > 
> > > > > > diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> > > > > > index 61c3fc5..486b1da 100644
> > > > > > --- a/drivers/clk/clk.c
> > > > > > +++ b/drivers/clk/clk.c
> > > > > > @@ -46,6 +46,21 @@ static struct clk_core *clk_core_lookup(const char *name);
> > > > > >  
> > > > > >  /***    private data structures    ***/
> > > > > >  
> > > > > > +/**
> > > > > > + * struct critical -   Provides 'play' over critical clocks.  A clock can be
> > > > > > + *                     marked as critical, meaning that it should not be
> > > > > > + *                     disabled.  However, if a driver which is aware of the
> > > > > > + *                     critical behaviour wants to control it, it can do so
> > > > > > + *                     using clk_enable_critical() and clk_disable_critical().
> > > > > > + *
> > > > > > + * @enabled    Is clock critical?  Once set, doesn't change
> > > > > > + * @leave_on   Self explanatory.  Can be disabled by knowledgeable drivers
> > > > > > + */
> > > > > > +struct critical {
> > > > > > +       bool enabled;
> > > > > > +       bool leave_on;
> > > > > > +};
> > > > > > +
> > > > > >  struct clk_core {
> > > > > >         const char              *name;
> > > > > >         const struct clk_ops    *ops;
> > > > > > @@ -75,6 +90,7 @@ struct clk_core {
> > > > > >         struct dentry           *dentry;
> > > > > >  #endif
> > > > > >         struct kref             ref;
> > > > > > +       struct critical         critical;
> > > > > >  };
> > > > > >  
> > > > > >  struct clk {
> > > > > > @@ -995,6 +1011,10 @@ static void clk_core_disable(struct clk_core *clk)
> > > > > >         if (WARN_ON(clk->enable_count == 0))
> > > > > >                 return;
> > > > > >  
> > > > > > +       /* Refuse to turn off a critical clock */
> > > > > > +       if (clk->enable_count == 1 && clk->critical.leave_on)
> > > > > > +               return;
> > > > > > +
> > > > > 
> > > > > I think it should be handled by a separate counting. Otherwise, if you
> > > > > have two users that marked the clock as critical, and then one of them
> > > > > disable it...
> > > > > 
> > > > > >         if (--clk->enable_count > 0)
> > > > > >                 return;
> > > > > >  
> > > > > > @@ -1037,6 +1057,13 @@ void clk_disable(struct clk *clk)
> > > > > >  }
> > > > > >  EXPORT_SYMBOL_GPL(clk_disable);
> > > > > >  
> > > > > > +void clk_disable_critical(struct clk *clk)
> > > > > > +{
> > > > > > +       clk->core->critical.leave_on = false;
> > > > > 
> > > > > .. you just lost the fact that it was critical in the first place.
> > > > 
> > > > I thought about both of these points, which is why I came up with this
> > > > strategy.
> > > > 
> > > > Any device which uses the *_critical() API should a) have knowledge of
> > > > what happens when a particular critical clock is gated and b) have
> > > > thought about the consequences.
> > > 
> > > Indeed.
> > > 
> > > > I don't think we can use reference counting, because we'd need as
> > > > many critical clock owners as there are critical clocks.
> > > 
> > > Which we can have if we replace the call to clk_prepare_enable you add
> > > in your fourth patch in __set_critical_clocks.
> > 
> > What should it be replaced with?
> > 
> > > > Cast your mind back to the reasons for this critical clock API.  One
> > > > of the most important intentions of this API is the requirement
> > > > mitigation for each of the critical clocks to have an owner
> > > > (driver).
> > > > 
> > > > With regards to your second point, that's what 'critical.enabled'
> > > > is for.  Take a look at clk_enable_critical().
> > > 
> > > I don't think this addresses the issue, if you just throw more
> > > customers at it, the issue remain with your implementation.
> > > 
> > > If you have three customers that used the critical API, and if on of
> > > these calls clk_disable_critical, you're losing leave_on.
> > 
> > That's the idea.  See my point above, the one you replied "Indeed"
> > to.  So when a driver uses clk_disable_critical() it's saying, "I know
> > why this clock is a critical clock, and I know that nothing terrible
> > will happen if I disable it, as I have that covered".  So then if it's
> > not the last user to call clk_disable(), the last one out the door
> > will be allowed to finally gate the clock, regardless whether it's
> > critical aware or not.
> > 
> > Then, when we come to enable the clock again, the critical aware user
> > then re-marks the clock as leave_on, so not critical un-aware user can
> > take the final reference and disable the clock.
> > 
> > > Which means that if there's one of the two users left that calls
> > > clk_disable on it, the clock will actually be disabled, which is
> > > clearly not what we want to do, as we have still a user that want the
> > > clock to be enabled.
> > 
> > That's not what happens (at least it shouldn't if I've coded it up
> > right).  The API _still_ requires all of the users to give-up their
> > reference.
> > 
> > > It would be much more robust to have another count for the critical
> > > stuff, initialised to one by the __set_critical_clocks function.
> > 
> > If I understand you correctly, we already have a count.  We use the
> > original reference count.  No need for one of our own.
> > 
> > Using your RAM Clock (Clock 4) as an example
> > --------------------------------------------
> > 
> > Early start-up:
> >   Clock 4 is marked as critical and a reference is taken (ref == 1)
> > 
> > Driver probe:
> >   SPI enables Clock 4 (ref == 2)
> >   I2C enables Clock 4 (ref == 3)
> > 
> > Suspend (without RAM driver's permission):
> >   SPI disables Clock 4 (ref == 2)
> >   I2C disables Clock 4 (ref == 1)
> >   /*
> >    * Clock won't be gated because:
> >    *   .leave_on is True - can't dec final reference
> 
> I am clearly missing the point. The clock won't be gated because the
> enable_count is still 1! What does .leave_on do here?

The point of _this_ (the extended) part of the API is so that the
clock _can_ be turned off.  Without the possibility to disable
.leave_on and the logic with accompanies it (i.e.
clk_disable_critical()) the clock will _never_ be gated.

> >    */
> > 
> > Suspend (with RAM driver's permission):
> >   /* Order is unimportant */
> >   SPI disables Clock 4 (ref == 2)
> >   RAM disables Clock 4 (ref == 1) /* Won't turn off here (ref > 0)
> >   I2C disables Clock 4 (ref == 0) /* (.leave_on == False) last ref can be taken */
> >   /*
> >    * Clock will be gated because:
> >    *   .leave_on is False, so (ref == 0)
> 
> Again, .leave_on does nothing new here. We gate the clock because the
> reference count is 0.

It's the fact that .leave_on has been disabled in
clk_disable_critical() that allows the final reference to be taken.

> >    */
> > 
> > Resume:
> >   /* Order is unimportant */
> >   SPI enables Clock 4 (ref == 1)
> >   RAM enables Clock 4 and re-enables .leave_on (ref == 2)
> >   I2C enables Clock 4 (ref == 3)
> 
> Same again. As soon as RAM calls clk_enable_critical the ref count goes
> up. .leave_on does nothing as far as I can tell. The all works because
> of the reference counting, which already exists before this patch
> series.

So fundamentally you're right in what you say.  All you really need to
disable a critical clock is write a knowledgeable driver, which is
intentionally unbalanced i.e. just calls clk_disable().  All this
extended API really does is makes the process more official and
ensures that an unintentionally unbalanced driver doesn't bugger up
the running platform.  We could also add a new WARN() to say that said
driver is unbalanced, as it just tried to turn off a critical clock.

What do you think is best?

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

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

* Re: [PATCH v7 3/5] clk: Supply the critical clock {init, enable, disable} framework
@ 2015-07-30  9:50               ` Lee Jones
  0 siblings, 0 replies; 93+ messages in thread
From: Lee Jones @ 2015-07-30  9:50 UTC (permalink / raw)
  To: Michael Turquette
  Cc: Maxime Ripard, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	kernel-F5mvAk5X5gdBDgjK7y7TUQ, sboyd-sgV2jX0FEOL9JmXXK+q4OQ,
	devicetree-u79uwXL29TY76Z2rM5mHXA, geert-Td1EMuHUCqxL1ZNQvxDV9g,
	s.hauer-bIcnvbaLZ9MEGnE8C9+IrQ

On Wed, 29 Jul 2015, Michael Turquette wrote:
> Quoting Lee Jones (2015-07-28 06:00:55)
> > On Tue, 28 Jul 2015, Maxime Ripard wrote:
> > 
> > > On Mon, Jul 27, 2015 at 09:53:38AM +0100, Lee Jones wrote:
> > > > On Mon, 27 Jul 2015, Maxime Ripard wrote:
> > > > 
> > > > > On Wed, Jul 22, 2015 at 02:04:13PM +0100, Lee Jones wrote:
> > > > > > These new API calls will firstly provide a mechanisms to tag a clock as
> > > > > > critical and secondly allow any knowledgeable driver to (un)gate clocks,
> > > > > > even if they are marked as critical.
> > > > > > 
> > > > > > Suggested-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> > > > > > Signed-off-by: Lee Jones <lee.jones-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> > > > > > ---
> > > > > >  drivers/clk/clk.c            | 45 ++++++++++++++++++++++++++++++++++++++++++++
> > > > > >  include/linux/clk-provider.h |  2 ++
> > > > > >  include/linux/clk.h          | 30 +++++++++++++++++++++++++++++
> > > > > >  3 files changed, 77 insertions(+)
> > > > > > 
> > > > > > diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> > > > > > index 61c3fc5..486b1da 100644
> > > > > > --- a/drivers/clk/clk.c
> > > > > > +++ b/drivers/clk/clk.c
> > > > > > @@ -46,6 +46,21 @@ static struct clk_core *clk_core_lookup(const char *name);
> > > > > >  
> > > > > >  /***    private data structures    ***/
> > > > > >  
> > > > > > +/**
> > > > > > + * struct critical -   Provides 'play' over critical clocks.  A clock can be
> > > > > > + *                     marked as critical, meaning that it should not be
> > > > > > + *                     disabled.  However, if a driver which is aware of the
> > > > > > + *                     critical behaviour wants to control it, it can do so
> > > > > > + *                     using clk_enable_critical() and clk_disable_critical().
> > > > > > + *
> > > > > > + * @enabled    Is clock critical?  Once set, doesn't change
> > > > > > + * @leave_on   Self explanatory.  Can be disabled by knowledgeable drivers
> > > > > > + */
> > > > > > +struct critical {
> > > > > > +       bool enabled;
> > > > > > +       bool leave_on;
> > > > > > +};
> > > > > > +
> > > > > >  struct clk_core {
> > > > > >         const char              *name;
> > > > > >         const struct clk_ops    *ops;
> > > > > > @@ -75,6 +90,7 @@ struct clk_core {
> > > > > >         struct dentry           *dentry;
> > > > > >  #endif
> > > > > >         struct kref             ref;
> > > > > > +       struct critical         critical;
> > > > > >  };
> > > > > >  
> > > > > >  struct clk {
> > > > > > @@ -995,6 +1011,10 @@ static void clk_core_disable(struct clk_core *clk)
> > > > > >         if (WARN_ON(clk->enable_count == 0))
> > > > > >                 return;
> > > > > >  
> > > > > > +       /* Refuse to turn off a critical clock */
> > > > > > +       if (clk->enable_count == 1 && clk->critical.leave_on)
> > > > > > +               return;
> > > > > > +
> > > > > 
> > > > > I think it should be handled by a separate counting. Otherwise, if you
> > > > > have two users that marked the clock as critical, and then one of them
> > > > > disable it...
> > > > > 
> > > > > >         if (--clk->enable_count > 0)
> > > > > >                 return;
> > > > > >  
> > > > > > @@ -1037,6 +1057,13 @@ void clk_disable(struct clk *clk)
> > > > > >  }
> > > > > >  EXPORT_SYMBOL_GPL(clk_disable);
> > > > > >  
> > > > > > +void clk_disable_critical(struct clk *clk)
> > > > > > +{
> > > > > > +       clk->core->critical.leave_on = false;
> > > > > 
> > > > > .. you just lost the fact that it was critical in the first place.
> > > > 
> > > > I thought about both of these points, which is why I came up with this
> > > > strategy.
> > > > 
> > > > Any device which uses the *_critical() API should a) have knowledge of
> > > > what happens when a particular critical clock is gated and b) have
> > > > thought about the consequences.
> > > 
> > > Indeed.
> > > 
> > > > I don't think we can use reference counting, because we'd need as
> > > > many critical clock owners as there are critical clocks.
> > > 
> > > Which we can have if we replace the call to clk_prepare_enable you add
> > > in your fourth patch in __set_critical_clocks.
> > 
> > What should it be replaced with?
> > 
> > > > Cast your mind back to the reasons for this critical clock API.  One
> > > > of the most important intentions of this API is the requirement
> > > > mitigation for each of the critical clocks to have an owner
> > > > (driver).
> > > > 
> > > > With regards to your second point, that's what 'critical.enabled'
> > > > is for.  Take a look at clk_enable_critical().
> > > 
> > > I don't think this addresses the issue, if you just throw more
> > > customers at it, the issue remain with your implementation.
> > > 
> > > If you have three customers that used the critical API, and if on of
> > > these calls clk_disable_critical, you're losing leave_on.
> > 
> > That's the idea.  See my point above, the one you replied "Indeed"
> > to.  So when a driver uses clk_disable_critical() it's saying, "I know
> > why this clock is a critical clock, and I know that nothing terrible
> > will happen if I disable it, as I have that covered".  So then if it's
> > not the last user to call clk_disable(), the last one out the door
> > will be allowed to finally gate the clock, regardless whether it's
> > critical aware or not.
> > 
> > Then, when we come to enable the clock again, the critical aware user
> > then re-marks the clock as leave_on, so not critical un-aware user can
> > take the final reference and disable the clock.
> > 
> > > Which means that if there's one of the two users left that calls
> > > clk_disable on it, the clock will actually be disabled, which is
> > > clearly not what we want to do, as we have still a user that want the
> > > clock to be enabled.
> > 
> > That's not what happens (at least it shouldn't if I've coded it up
> > right).  The API _still_ requires all of the users to give-up their
> > reference.
> > 
> > > It would be much more robust to have another count for the critical
> > > stuff, initialised to one by the __set_critical_clocks function.
> > 
> > If I understand you correctly, we already have a count.  We use the
> > original reference count.  No need for one of our own.
> > 
> > Using your RAM Clock (Clock 4) as an example
> > --------------------------------------------
> > 
> > Early start-up:
> >   Clock 4 is marked as critical and a reference is taken (ref == 1)
> > 
> > Driver probe:
> >   SPI enables Clock 4 (ref == 2)
> >   I2C enables Clock 4 (ref == 3)
> > 
> > Suspend (without RAM driver's permission):
> >   SPI disables Clock 4 (ref == 2)
> >   I2C disables Clock 4 (ref == 1)
> >   /*
> >    * Clock won't be gated because:
> >    *   .leave_on is True - can't dec final reference
> 
> I am clearly missing the point. The clock won't be gated because the
> enable_count is still 1! What does .leave_on do here?

The point of _this_ (the extended) part of the API is so that the
clock _can_ be turned off.  Without the possibility to disable
.leave_on and the logic with accompanies it (i.e.
clk_disable_critical()) the clock will _never_ be gated.

> >    */
> > 
> > Suspend (with RAM driver's permission):
> >   /* Order is unimportant */
> >   SPI disables Clock 4 (ref == 2)
> >   RAM disables Clock 4 (ref == 1) /* Won't turn off here (ref > 0)
> >   I2C disables Clock 4 (ref == 0) /* (.leave_on == False) last ref can be taken */
> >   /*
> >    * Clock will be gated because:
> >    *   .leave_on is False, so (ref == 0)
> 
> Again, .leave_on does nothing new here. We gate the clock because the
> reference count is 0.

It's the fact that .leave_on has been disabled in
clk_disable_critical() that allows the final reference to be taken.

> >    */
> > 
> > Resume:
> >   /* Order is unimportant */
> >   SPI enables Clock 4 (ref == 1)
> >   RAM enables Clock 4 and re-enables .leave_on (ref == 2)
> >   I2C enables Clock 4 (ref == 3)
> 
> Same again. As soon as RAM calls clk_enable_critical the ref count goes
> up. .leave_on does nothing as far as I can tell. The all works because
> of the reference counting, which already exists before this patch
> series.

So fundamentally you're right in what you say.  All you really need to
disable a critical clock is write a knowledgeable driver, which is
intentionally unbalanced i.e. just calls clk_disable().  All this
extended API really does is makes the process more official and
ensures that an unintentionally unbalanced driver doesn't bugger up
the running platform.  We could also add a new WARN() to say that said
driver is unbalanced, as it just tried to turn off a critical clock.

What do you think is best?

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH v7 3/5] clk: Supply the critical clock {init, enable, disable} framework
@ 2015-07-30  9:50               ` Lee Jones
  0 siblings, 0 replies; 93+ messages in thread
From: Lee Jones @ 2015-07-30  9:50 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, 29 Jul 2015, Michael Turquette wrote:
> Quoting Lee Jones (2015-07-28 06:00:55)
> > On Tue, 28 Jul 2015, Maxime Ripard wrote:
> > 
> > > On Mon, Jul 27, 2015 at 09:53:38AM +0100, Lee Jones wrote:
> > > > On Mon, 27 Jul 2015, Maxime Ripard wrote:
> > > > 
> > > > > On Wed, Jul 22, 2015 at 02:04:13PM +0100, Lee Jones wrote:
> > > > > > These new API calls will firstly provide a mechanisms to tag a clock as
> > > > > > critical and secondly allow any knowledgeable driver to (un)gate clocks,
> > > > > > even if they are marked as critical.
> > > > > > 
> > > > > > Suggested-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> > > > > > Signed-off-by: Lee Jones <lee.jones@linaro.org>
> > > > > > ---
> > > > > >  drivers/clk/clk.c            | 45 ++++++++++++++++++++++++++++++++++++++++++++
> > > > > >  include/linux/clk-provider.h |  2 ++
> > > > > >  include/linux/clk.h          | 30 +++++++++++++++++++++++++++++
> > > > > >  3 files changed, 77 insertions(+)
> > > > > > 
> > > > > > diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> > > > > > index 61c3fc5..486b1da 100644
> > > > > > --- a/drivers/clk/clk.c
> > > > > > +++ b/drivers/clk/clk.c
> > > > > > @@ -46,6 +46,21 @@ static struct clk_core *clk_core_lookup(const char *name);
> > > > > >  
> > > > > >  /***    private data structures    ***/
> > > > > >  
> > > > > > +/**
> > > > > > + * struct critical -   Provides 'play' over critical clocks.  A clock can be
> > > > > > + *                     marked as critical, meaning that it should not be
> > > > > > + *                     disabled.  However, if a driver which is aware of the
> > > > > > + *                     critical behaviour wants to control it, it can do so
> > > > > > + *                     using clk_enable_critical() and clk_disable_critical().
> > > > > > + *
> > > > > > + * @enabled    Is clock critical?  Once set, doesn't change
> > > > > > + * @leave_on   Self explanatory.  Can be disabled by knowledgeable drivers
> > > > > > + */
> > > > > > +struct critical {
> > > > > > +       bool enabled;
> > > > > > +       bool leave_on;
> > > > > > +};
> > > > > > +
> > > > > >  struct clk_core {
> > > > > >         const char              *name;
> > > > > >         const struct clk_ops    *ops;
> > > > > > @@ -75,6 +90,7 @@ struct clk_core {
> > > > > >         struct dentry           *dentry;
> > > > > >  #endif
> > > > > >         struct kref             ref;
> > > > > > +       struct critical         critical;
> > > > > >  };
> > > > > >  
> > > > > >  struct clk {
> > > > > > @@ -995,6 +1011,10 @@ static void clk_core_disable(struct clk_core *clk)
> > > > > >         if (WARN_ON(clk->enable_count == 0))
> > > > > >                 return;
> > > > > >  
> > > > > > +       /* Refuse to turn off a critical clock */
> > > > > > +       if (clk->enable_count == 1 && clk->critical.leave_on)
> > > > > > +               return;
> > > > > > +
> > > > > 
> > > > > I think it should be handled by a separate counting. Otherwise, if you
> > > > > have two users that marked the clock as critical, and then one of them
> > > > > disable it...
> > > > > 
> > > > > >         if (--clk->enable_count > 0)
> > > > > >                 return;
> > > > > >  
> > > > > > @@ -1037,6 +1057,13 @@ void clk_disable(struct clk *clk)
> > > > > >  }
> > > > > >  EXPORT_SYMBOL_GPL(clk_disable);
> > > > > >  
> > > > > > +void clk_disable_critical(struct clk *clk)
> > > > > > +{
> > > > > > +       clk->core->critical.leave_on = false;
> > > > > 
> > > > > .. you just lost the fact that it was critical in the first place.
> > > > 
> > > > I thought about both of these points, which is why I came up with this
> > > > strategy.
> > > > 
> > > > Any device which uses the *_critical() API should a) have knowledge of
> > > > what happens when a particular critical clock is gated and b) have
> > > > thought about the consequences.
> > > 
> > > Indeed.
> > > 
> > > > I don't think we can use reference counting, because we'd need as
> > > > many critical clock owners as there are critical clocks.
> > > 
> > > Which we can have if we replace the call to clk_prepare_enable you add
> > > in your fourth patch in __set_critical_clocks.
> > 
> > What should it be replaced with?
> > 
> > > > Cast your mind back to the reasons for this critical clock API.  One
> > > > of the most important intentions of this API is the requirement
> > > > mitigation for each of the critical clocks to have an owner
> > > > (driver).
> > > > 
> > > > With regards to your second point, that's what 'critical.enabled'
> > > > is for.  Take a look at clk_enable_critical().
> > > 
> > > I don't think this addresses the issue, if you just throw more
> > > customers at it, the issue remain with your implementation.
> > > 
> > > If you have three customers that used the critical API, and if on of
> > > these calls clk_disable_critical, you're losing leave_on.
> > 
> > That's the idea.  See my point above, the one you replied "Indeed"
> > to.  So when a driver uses clk_disable_critical() it's saying, "I know
> > why this clock is a critical clock, and I know that nothing terrible
> > will happen if I disable it, as I have that covered".  So then if it's
> > not the last user to call clk_disable(), the last one out the door
> > will be allowed to finally gate the clock, regardless whether it's
> > critical aware or not.
> > 
> > Then, when we come to enable the clock again, the critical aware user
> > then re-marks the clock as leave_on, so not critical un-aware user can
> > take the final reference and disable the clock.
> > 
> > > Which means that if there's one of the two users left that calls
> > > clk_disable on it, the clock will actually be disabled, which is
> > > clearly not what we want to do, as we have still a user that want the
> > > clock to be enabled.
> > 
> > That's not what happens (at least it shouldn't if I've coded it up
> > right).  The API _still_ requires all of the users to give-up their
> > reference.
> > 
> > > It would be much more robust to have another count for the critical
> > > stuff, initialised to one by the __set_critical_clocks function.
> > 
> > If I understand you correctly, we already have a count.  We use the
> > original reference count.  No need for one of our own.
> > 
> > Using your RAM Clock (Clock 4) as an example
> > --------------------------------------------
> > 
> > Early start-up:
> >   Clock 4 is marked as critical and a reference is taken (ref == 1)
> > 
> > Driver probe:
> >   SPI enables Clock 4 (ref == 2)
> >   I2C enables Clock 4 (ref == 3)
> > 
> > Suspend (without RAM driver's permission):
> >   SPI disables Clock 4 (ref == 2)
> >   I2C disables Clock 4 (ref == 1)
> >   /*
> >    * Clock won't be gated because:
> >    *   .leave_on is True - can't dec final reference
> 
> I am clearly missing the point. The clock won't be gated because the
> enable_count is still 1! What does .leave_on do here?

The point of _this_ (the extended) part of the API is so that the
clock _can_ be turned off.  Without the possibility to disable
.leave_on and the logic with accompanies it (i.e.
clk_disable_critical()) the clock will _never_ be gated.

> >    */
> > 
> > Suspend (with RAM driver's permission):
> >   /* Order is unimportant */
> >   SPI disables Clock 4 (ref == 2)
> >   RAM disables Clock 4 (ref == 1) /* Won't turn off here (ref > 0)
> >   I2C disables Clock 4 (ref == 0) /* (.leave_on == False) last ref can be taken */
> >   /*
> >    * Clock will be gated because:
> >    *   .leave_on is False, so (ref == 0)
> 
> Again, .leave_on does nothing new here. We gate the clock because the
> reference count is 0.

It's the fact that .leave_on has been disabled in
clk_disable_critical() that allows the final reference to be taken.

> >    */
> > 
> > Resume:
> >   /* Order is unimportant */
> >   SPI enables Clock 4 (ref == 1)
> >   RAM enables Clock 4 and re-enables .leave_on (ref == 2)
> >   I2C enables Clock 4 (ref == 3)
> 
> Same again. As soon as RAM calls clk_enable_critical the ref count goes
> up. .leave_on does nothing as far as I can tell. The all works because
> of the reference counting, which already exists before this patch
> series.

So fundamentally you're right in what you say.  All you really need to
disable a critical clock is write a knowledgeable driver, which is
intentionally unbalanced i.e. just calls clk_disable().  All this
extended API really does is makes the process more official and
ensures that an unintentionally unbalanced driver doesn't bugger up
the running platform.  We could also add a new WARN() to say that said
driver is unbalanced, as it just tried to turn off a critical clock.

What do you think is best?

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org ? Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

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

* Re: [PATCH v7 3/5] clk: Supply the critical clock {init, enable, disable} framework
  2015-07-30  1:02     ` Michael Turquette
@ 2015-07-30 11:17       ` Lee Jones
  -1 siblings, 0 replies; 93+ messages in thread
From: Lee Jones @ 2015-07-30 11:17 UTC (permalink / raw)
  To: Michael Turquette
  Cc: linux-arm-kernel, linux-kernel, kernel, sboyd, devicetree, geert,
	maxime.ripard, s.hauer, linux-clk

On Wed, 29 Jul 2015, Michael Turquette wrote:

> Hi Lee,
> 
> + linux-clk ml
> 
> Quoting Lee Jones (2015-07-22 06:04:13)
> > These new API calls will firstly provide a mechanisms to tag a clock as
> > critical and secondly allow any knowledgeable driver to (un)gate clocks,
> > even if they are marked as critical.
> > 
> > Suggested-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> > Signed-off-by: Lee Jones <lee.jones@linaro.org>
> > ---
> >  drivers/clk/clk.c            | 45 ++++++++++++++++++++++++++++++++++++++++++++
> >  include/linux/clk-provider.h |  2 ++
> >  include/linux/clk.h          | 30 +++++++++++++++++++++++++++++
> >  3 files changed, 77 insertions(+)
> > 
> > diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> > index 61c3fc5..486b1da 100644
> > --- a/drivers/clk/clk.c
> > +++ b/drivers/clk/clk.c
> > @@ -46,6 +46,21 @@ static struct clk_core *clk_core_lookup(const char *name);
> >  
> >  /***    private data structures    ***/
> >  
> > +/**
> > + * struct critical -   Provides 'play' over critical clocks.  A clock can be
> > + *                     marked as critical, meaning that it should not be
> > + *                     disabled.  However, if a driver which is aware of the
> > + *                     critical behaviour wants to control it, it can do so
> > + *                     using clk_enable_critical() and clk_disable_critical().
> > + *
> > + * @enabled    Is clock critical?  Once set, doesn't change
> > + * @leave_on   Self explanatory.  Can be disabled by knowledgeable drivers
> 
> Not self explanatory. I need this explained to me. What does leave_on
> do? Better yet, what would happen if leave_on did not exist?
> 
> > + */
> > +struct critical {
> > +       bool enabled;
> > +       bool leave_on;
> > +};
> > +
> >  struct clk_core {
> >         const char              *name;
> >         const struct clk_ops    *ops;
> > @@ -75,6 +90,7 @@ struct clk_core {
> >         struct dentry           *dentry;
> >  #endif
> >         struct kref             ref;
> > +       struct critical         critical;
> >  };
> >  
> >  struct clk {
> > @@ -995,6 +1011,10 @@ static void clk_core_disable(struct clk_core *clk)
> >         if (WARN_ON(clk->enable_count == 0))
> >                 return;
> >  
> > +       /* Refuse to turn off a critical clock */
> > +       if (clk->enable_count == 1 && clk->critical.leave_on)
> > +               return;
> 
> How do we get to this point? clk_enable_critical actually calls
> clk_enable, thus incrementing the enable_count. The only time that we
> could hit the above case is if,
> 
> a) there is an imbalance in clk_enable and clk_disable calls. If this is
> the case then the drivers need to be fixed. Or better yet some
> infrastructure to catch that, now that we have per-user struct clk
> cookies.
> 
> b) a driver knowingly calls clk_enable_critical(foo) and then regular,
> old clk_disable(foo). But why would a driver do that?
> 
> It might be that I am missing the point here, so please feel free to
> clue me in.

This check behaves in a very similar to the WARN() above.  It's more
of a fail-safe.  If all drivers are behaving properly, then it
shouldn't ever be true.  If they're not, it prevents an incorrectly
written driver from irrecoverably crippling the system.

As I said in the other mail.  We can do without these 3 new wrappers.
We _could_ just write a driver which only calls clk_enable() _after_
it calls clk_disable(), a kind of intentional unbalance and it would
do that same thing.  However, what we're trying to do here is provide
a proper API, so we can see at first glance what the 'knowledgeable'
driver is trying to do and not have someone attempt to submit a 'fix'
which calls clk_enable() or something.

> > +
> >         if (--clk->enable_count > 0)
> >                 return;
> >  
> > @@ -1037,6 +1057,13 @@ void clk_disable(struct clk *clk)
> >  }
> >  EXPORT_SYMBOL_GPL(clk_disable);
> >  
> > +void clk_disable_critical(struct clk *clk)
> > +{
> > +       clk->core->critical.leave_on = false;
> > +       clk_disable(clk);
> > +}
> > +EXPORT_SYMBOL_GPL(clk_disable_critical);
> > +
> >  static int clk_core_enable(struct clk_core *clk)
> >  {
> >         int ret = 0;
> > @@ -1100,6 +1127,15 @@ int clk_enable(struct clk *clk)
> >  }
> >  EXPORT_SYMBOL_GPL(clk_enable);
> >  
> > +int clk_enable_critical(struct clk *clk)
> > +{
> > +       if (clk->core->critical.enabled)
> > +               clk->core->critical.leave_on = true;
> > +
> > +       return clk_enable(clk);
> > +}
> > +EXPORT_SYMBOL_GPL(clk_enable_critical);
> > +
> >  static unsigned long clk_core_round_rate_nolock(struct clk_core *clk,
> >                                                 unsigned long rate,
> >                                                 unsigned long min_rate,
> > @@ -2482,6 +2518,15 @@ fail_out:
> >  }
> >  EXPORT_SYMBOL_GPL(clk_register);
> >  
> > +void clk_init_critical(struct clk *clk)
> > +{
> > +       struct critical *critical = &clk->core->critical;
> > +
> > +       critical->enabled = true;
> > +       critical->leave_on = true;
> > +}
> > +EXPORT_SYMBOL_GPL(clk_init_critical);
> > +
> >  /*
> >   * Free memory allocated for a clock.
> >   * Caller must hold prepare_lock.
> > diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
> > index 5591ea7..15ef8c9 100644
> > --- a/include/linux/clk-provider.h
> > +++ b/include/linux/clk-provider.h
> > @@ -563,6 +563,8 @@ struct clk *devm_clk_register(struct device *dev, struct clk_hw *hw);
> >  void clk_unregister(struct clk *clk);
> >  void devm_clk_unregister(struct device *dev, struct clk *clk);
> >  
> > +void clk_init_critical(struct clk *clk);
> > +
> >  /* helper functions */
> >  const char *__clk_get_name(struct clk *clk);
> >  struct clk_hw *__clk_get_hw(struct clk *clk);
> > diff --git a/include/linux/clk.h b/include/linux/clk.h
> > index 8381bbf..9807f3b 100644
> > --- a/include/linux/clk.h
> > +++ b/include/linux/clk.h
> > @@ -231,6 +231,19 @@ struct clk *devm_clk_get(struct device *dev, const char *id);
> >  int clk_enable(struct clk *clk);
> >  
> >  /**
> > + * clk_enable_critical - inform the system when the clock source should be
> > + *                      running, even if clock is critical.
> > + * @clk: clock source
> > + *
> > + * If the clock can not be enabled/disabled, this should return success.
> > + *
> > + * May be called from atomic contexts.
> > + *
> > + * Returns success (0) or negative errno.
> > + */
> > +int clk_enable_critical(struct clk *clk);
> > +
> > +/**
> >   * clk_disable - inform the system when the clock source is no longer required.
> >   * @clk: clock source
> >   *
> > @@ -247,6 +260,23 @@ int clk_enable(struct clk *clk);
> >  void clk_disable(struct clk *clk);
> >  
> >  /**
> > + * clk_disable_critical - inform the system when the clock source is no
> > + *                       longer required, even if clock is critical.
> > + * @clk: clock source
> > + *
> > + * Inform the system that a clock source is no longer required by
> > + * a driver and may be shut down.
> > + *
> > + * May be called from atomic contexts.
> > + *
> > + * Implementation detail: if the clock source is shared between
> > + * multiple drivers, clk_enable_critical() calls must be balanced
> > + * by the same number of clk_disable_critical() calls for the clock
> > + * source to be disabled.
> > + */
> > +void clk_disable_critical(struct clk *clk);
> > +
> > +/**
> >   * clk_get_rate - obtain the current clock rate (in Hz) for a clock source.
> >   *               This is only valid once the clock source has been enabled.
> >   * @clk: clock source

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

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

* [PATCH v7 3/5] clk: Supply the critical clock {init, enable, disable} framework
@ 2015-07-30 11:17       ` Lee Jones
  0 siblings, 0 replies; 93+ messages in thread
From: Lee Jones @ 2015-07-30 11:17 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, 29 Jul 2015, Michael Turquette wrote:

> Hi Lee,
> 
> + linux-clk ml
> 
> Quoting Lee Jones (2015-07-22 06:04:13)
> > These new API calls will firstly provide a mechanisms to tag a clock as
> > critical and secondly allow any knowledgeable driver to (un)gate clocks,
> > even if they are marked as critical.
> > 
> > Suggested-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> > Signed-off-by: Lee Jones <lee.jones@linaro.org>
> > ---
> >  drivers/clk/clk.c            | 45 ++++++++++++++++++++++++++++++++++++++++++++
> >  include/linux/clk-provider.h |  2 ++
> >  include/linux/clk.h          | 30 +++++++++++++++++++++++++++++
> >  3 files changed, 77 insertions(+)
> > 
> > diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> > index 61c3fc5..486b1da 100644
> > --- a/drivers/clk/clk.c
> > +++ b/drivers/clk/clk.c
> > @@ -46,6 +46,21 @@ static struct clk_core *clk_core_lookup(const char *name);
> >  
> >  /***    private data structures    ***/
> >  
> > +/**
> > + * struct critical -   Provides 'play' over critical clocks.  A clock can be
> > + *                     marked as critical, meaning that it should not be
> > + *                     disabled.  However, if a driver which is aware of the
> > + *                     critical behaviour wants to control it, it can do so
> > + *                     using clk_enable_critical() and clk_disable_critical().
> > + *
> > + * @enabled    Is clock critical?  Once set, doesn't change
> > + * @leave_on   Self explanatory.  Can be disabled by knowledgeable drivers
> 
> Not self explanatory. I need this explained to me. What does leave_on
> do? Better yet, what would happen if leave_on did not exist?
> 
> > + */
> > +struct critical {
> > +       bool enabled;
> > +       bool leave_on;
> > +};
> > +
> >  struct clk_core {
> >         const char              *name;
> >         const struct clk_ops    *ops;
> > @@ -75,6 +90,7 @@ struct clk_core {
> >         struct dentry           *dentry;
> >  #endif
> >         struct kref             ref;
> > +       struct critical         critical;
> >  };
> >  
> >  struct clk {
> > @@ -995,6 +1011,10 @@ static void clk_core_disable(struct clk_core *clk)
> >         if (WARN_ON(clk->enable_count == 0))
> >                 return;
> >  
> > +       /* Refuse to turn off a critical clock */
> > +       if (clk->enable_count == 1 && clk->critical.leave_on)
> > +               return;
> 
> How do we get to this point? clk_enable_critical actually calls
> clk_enable, thus incrementing the enable_count. The only time that we
> could hit the above case is if,
> 
> a) there is an imbalance in clk_enable and clk_disable calls. If this is
> the case then the drivers need to be fixed. Or better yet some
> infrastructure to catch that, now that we have per-user struct clk
> cookies.
> 
> b) a driver knowingly calls clk_enable_critical(foo) and then regular,
> old clk_disable(foo). But why would a driver do that?
> 
> It might be that I am missing the point here, so please feel free to
> clue me in.

This check behaves in a very similar to the WARN() above.  It's more
of a fail-safe.  If all drivers are behaving properly, then it
shouldn't ever be true.  If they're not, it prevents an incorrectly
written driver from irrecoverably crippling the system.

As I said in the other mail.  We can do without these 3 new wrappers.
We _could_ just write a driver which only calls clk_enable() _after_
it calls clk_disable(), a kind of intentional unbalance and it would
do that same thing.  However, what we're trying to do here is provide
a proper API, so we can see at first glance what the 'knowledgeable'
driver is trying to do and not have someone attempt to submit a 'fix'
which calls clk_enable() or something.

> > +
> >         if (--clk->enable_count > 0)
> >                 return;
> >  
> > @@ -1037,6 +1057,13 @@ void clk_disable(struct clk *clk)
> >  }
> >  EXPORT_SYMBOL_GPL(clk_disable);
> >  
> > +void clk_disable_critical(struct clk *clk)
> > +{
> > +       clk->core->critical.leave_on = false;
> > +       clk_disable(clk);
> > +}
> > +EXPORT_SYMBOL_GPL(clk_disable_critical);
> > +
> >  static int clk_core_enable(struct clk_core *clk)
> >  {
> >         int ret = 0;
> > @@ -1100,6 +1127,15 @@ int clk_enable(struct clk *clk)
> >  }
> >  EXPORT_SYMBOL_GPL(clk_enable);
> >  
> > +int clk_enable_critical(struct clk *clk)
> > +{
> > +       if (clk->core->critical.enabled)
> > +               clk->core->critical.leave_on = true;
> > +
> > +       return clk_enable(clk);
> > +}
> > +EXPORT_SYMBOL_GPL(clk_enable_critical);
> > +
> >  static unsigned long clk_core_round_rate_nolock(struct clk_core *clk,
> >                                                 unsigned long rate,
> >                                                 unsigned long min_rate,
> > @@ -2482,6 +2518,15 @@ fail_out:
> >  }
> >  EXPORT_SYMBOL_GPL(clk_register);
> >  
> > +void clk_init_critical(struct clk *clk)
> > +{
> > +       struct critical *critical = &clk->core->critical;
> > +
> > +       critical->enabled = true;
> > +       critical->leave_on = true;
> > +}
> > +EXPORT_SYMBOL_GPL(clk_init_critical);
> > +
> >  /*
> >   * Free memory allocated for a clock.
> >   * Caller must hold prepare_lock.
> > diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
> > index 5591ea7..15ef8c9 100644
> > --- a/include/linux/clk-provider.h
> > +++ b/include/linux/clk-provider.h
> > @@ -563,6 +563,8 @@ struct clk *devm_clk_register(struct device *dev, struct clk_hw *hw);
> >  void clk_unregister(struct clk *clk);
> >  void devm_clk_unregister(struct device *dev, struct clk *clk);
> >  
> > +void clk_init_critical(struct clk *clk);
> > +
> >  /* helper functions */
> >  const char *__clk_get_name(struct clk *clk);
> >  struct clk_hw *__clk_get_hw(struct clk *clk);
> > diff --git a/include/linux/clk.h b/include/linux/clk.h
> > index 8381bbf..9807f3b 100644
> > --- a/include/linux/clk.h
> > +++ b/include/linux/clk.h
> > @@ -231,6 +231,19 @@ struct clk *devm_clk_get(struct device *dev, const char *id);
> >  int clk_enable(struct clk *clk);
> >  
> >  /**
> > + * clk_enable_critical - inform the system when the clock source should be
> > + *                      running, even if clock is critical.
> > + * @clk: clock source
> > + *
> > + * If the clock can not be enabled/disabled, this should return success.
> > + *
> > + * May be called from atomic contexts.
> > + *
> > + * Returns success (0) or negative errno.
> > + */
> > +int clk_enable_critical(struct clk *clk);
> > +
> > +/**
> >   * clk_disable - inform the system when the clock source is no longer required.
> >   * @clk: clock source
> >   *
> > @@ -247,6 +260,23 @@ int clk_enable(struct clk *clk);
> >  void clk_disable(struct clk *clk);
> >  
> >  /**
> > + * clk_disable_critical - inform the system when the clock source is no
> > + *                       longer required, even if clock is critical.
> > + * @clk: clock source
> > + *
> > + * Inform the system that a clock source is no longer required by
> > + * a driver and may be shut down.
> > + *
> > + * May be called from atomic contexts.
> > + *
> > + * Implementation detail: if the clock source is shared between
> > + * multiple drivers, clk_enable_critical() calls must be balanced
> > + * by the same number of clk_disable_critical() calls for the clock
> > + * source to be disabled.
> > + */
> > +void clk_disable_critical(struct clk *clk);
> > +
> > +/**
> >   * clk_get_rate - obtain the current clock rate (in Hz) for a clock source.
> >   *               This is only valid once the clock source has been enabled.
> >   * @clk: clock source

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org ? Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

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

* Re: [PATCH v7 3/5] clk: Supply the critical clock {init, enable, disable} framework
  2015-07-30  9:50               ` Lee Jones
@ 2015-07-30 22:47                 ` Michael Turquette
  -1 siblings, 0 replies; 93+ messages in thread
From: Michael Turquette @ 2015-07-30 22:47 UTC (permalink / raw)
  To: Lee Jones
  Cc: devicetree, kernel, s.hauer, sboyd, linux-kernel, geert,
	Maxime Ripard, linux-arm-kernel

Quoting Lee Jones (2015-07-30 02:50:14)
> On Wed, 29 Jul 2015, Michael Turquette wrote:
> > Quoting Lee Jones (2015-07-28 06:00:55)
> > > On Tue, 28 Jul 2015, Maxime Ripard wrote:
> > > 
> > > > On Mon, Jul 27, 2015 at 09:53:38AM +0100, Lee Jones wrote:
> > > > > On Mon, 27 Jul 2015, Maxime Ripard wrote:
> > > > > 
> > > > > > On Wed, Jul 22, 2015 at 02:04:13PM +0100, Lee Jones wrote:
> > > > > > > These new API calls will firstly provide a mechanisms to tag a clock as
> > > > > > > critical and secondly allow any knowledgeable driver to (un)gate clocks,
> > > > > > > even if they are marked as critical.
> > > > > > > 
> > > > > > > Suggested-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> > > > > > > Signed-off-by: Lee Jones <lee.jones@linaro.org>
> > > > > > > ---
> > > > > > >  drivers/clk/clk.c            | 45 ++++++++++++++++++++++++++++++++++++++++++++
> > > > > > >  include/linux/clk-provider.h |  2 ++
> > > > > > >  include/linux/clk.h          | 30 +++++++++++++++++++++++++++++
> > > > > > >  3 files changed, 77 insertions(+)
> > > > > > > 
> > > > > > > diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> > > > > > > index 61c3fc5..486b1da 100644
> > > > > > > --- a/drivers/clk/clk.c
> > > > > > > +++ b/drivers/clk/clk.c
> > > > > > > @@ -46,6 +46,21 @@ static struct clk_core *clk_core_lookup(const char *name);
> > > > > > >  
> > > > > > >  /***    private data structures    ***/
> > > > > > >  
> > > > > > > +/**
> > > > > > > + * struct critical -   Provides 'play' over critical clocks.  A clock can be
> > > > > > > + *                     marked as critical, meaning that it should not be
> > > > > > > + *                     disabled.  However, if a driver which is aware of the
> > > > > > > + *                     critical behaviour wants to control it, it can do so
> > > > > > > + *                     using clk_enable_critical() and clk_disable_critical().
> > > > > > > + *
> > > > > > > + * @enabled    Is clock critical?  Once set, doesn't change
> > > > > > > + * @leave_on   Self explanatory.  Can be disabled by knowledgeable drivers
> > > > > > > + */
> > > > > > > +struct critical {
> > > > > > > +       bool enabled;
> > > > > > > +       bool leave_on;
> > > > > > > +};
> > > > > > > +
> > > > > > >  struct clk_core {
> > > > > > >         const char              *name;
> > > > > > >         const struct clk_ops    *ops;
> > > > > > > @@ -75,6 +90,7 @@ struct clk_core {
> > > > > > >         struct dentry           *dentry;
> > > > > > >  #endif
> > > > > > >         struct kref             ref;
> > > > > > > +       struct critical         critical;
> > > > > > >  };
> > > > > > >  
> > > > > > >  struct clk {
> > > > > > > @@ -995,6 +1011,10 @@ static void clk_core_disable(struct clk_core *clk)
> > > > > > >         if (WARN_ON(clk->enable_count == 0))
> > > > > > >                 return;
> > > > > > >  
> > > > > > > +       /* Refuse to turn off a critical clock */
> > > > > > > +       if (clk->enable_count == 1 && clk->critical.leave_on)
> > > > > > > +               return;
> > > > > > > +
> > > > > > 
> > > > > > I think it should be handled by a separate counting. Otherwise, if you
> > > > > > have two users that marked the clock as critical, and then one of them
> > > > > > disable it...
> > > > > > 
> > > > > > >         if (--clk->enable_count > 0)
> > > > > > >                 return;
> > > > > > >  
> > > > > > > @@ -1037,6 +1057,13 @@ void clk_disable(struct clk *clk)
> > > > > > >  }
> > > > > > >  EXPORT_SYMBOL_GPL(clk_disable);
> > > > > > >  
> > > > > > > +void clk_disable_critical(struct clk *clk)
> > > > > > > +{
> > > > > > > +       clk->core->critical.leave_on = false;
> > > > > > 
> > > > > > .. you just lost the fact that it was critical in the first place.
> > > > > 
> > > > > I thought about both of these points, which is why I came up with this
> > > > > strategy.
> > > > > 
> > > > > Any device which uses the *_critical() API should a) have knowledge of
> > > > > what happens when a particular critical clock is gated and b) have
> > > > > thought about the consequences.
> > > > 
> > > > Indeed.
> > > > 
> > > > > I don't think we can use reference counting, because we'd need as
> > > > > many critical clock owners as there are critical clocks.
> > > > 
> > > > Which we can have if we replace the call to clk_prepare_enable you add
> > > > in your fourth patch in __set_critical_clocks.
> > > 
> > > What should it be replaced with?
> > > 
> > > > > Cast your mind back to the reasons for this critical clock API.  One
> > > > > of the most important intentions of this API is the requirement
> > > > > mitigation for each of the critical clocks to have an owner
> > > > > (driver).
> > > > > 
> > > > > With regards to your second point, that's what 'critical.enabled'
> > > > > is for.  Take a look at clk_enable_critical().
> > > > 
> > > > I don't think this addresses the issue, if you just throw more
> > > > customers at it, the issue remain with your implementation.
> > > > 
> > > > If you have three customers that used the critical API, and if on of
> > > > these calls clk_disable_critical, you're losing leave_on.
> > > 
> > > That's the idea.  See my point above, the one you replied "Indeed"
> > > to.  So when a driver uses clk_disable_critical() it's saying, "I know
> > > why this clock is a critical clock, and I know that nothing terrible
> > > will happen if I disable it, as I have that covered".  So then if it's
> > > not the last user to call clk_disable(), the last one out the door
> > > will be allowed to finally gate the clock, regardless whether it's
> > > critical aware or not.
> > > 
> > > Then, when we come to enable the clock again, the critical aware user
> > > then re-marks the clock as leave_on, so not critical un-aware user can
> > > take the final reference and disable the clock.
> > > 
> > > > Which means that if there's one of the two users left that calls
> > > > clk_disable on it, the clock will actually be disabled, which is
> > > > clearly not what we want to do, as we have still a user that want the
> > > > clock to be enabled.
> > > 
> > > That's not what happens (at least it shouldn't if I've coded it up
> > > right).  The API _still_ requires all of the users to give-up their
> > > reference.
> > > 
> > > > It would be much more robust to have another count for the critical
> > > > stuff, initialised to one by the __set_critical_clocks function.
> > > 
> > > If I understand you correctly, we already have a count.  We use the
> > > original reference count.  No need for one of our own.
> > > 
> > > Using your RAM Clock (Clock 4) as an example
> > > --------------------------------------------
> > > 
> > > Early start-up:
> > >   Clock 4 is marked as critical and a reference is taken (ref == 1)
> > > 
> > > Driver probe:
> > >   SPI enables Clock 4 (ref == 2)
> > >   I2C enables Clock 4 (ref == 3)
> > > 
> > > Suspend (without RAM driver's permission):
> > >   SPI disables Clock 4 (ref == 2)
> > >   I2C disables Clock 4 (ref == 1)
> > >   /*
> > >    * Clock won't be gated because:
> > >    *   .leave_on is True - can't dec final reference
> > 
> > I am clearly missing the point. The clock won't be gated because the
> > enable_count is still 1! What does .leave_on do here?
> 
> The point of _this_ (the extended) part of the API is so that the
> clock _can_ be turned off.  Without the possibility to disable
> .leave_on and the logic with accompanies it (i.e.
> clk_disable_critical()) the clock will _never_ be gated.
> 
> > >    */
> > > 
> > > Suspend (with RAM driver's permission):
> > >   /* Order is unimportant */
> > >   SPI disables Clock 4 (ref == 2)
> > >   RAM disables Clock 4 (ref == 1) /* Won't turn off here (ref > 0)
> > >   I2C disables Clock 4 (ref == 0) /* (.leave_on == False) last ref can be taken */
> > >   /*
> > >    * Clock will be gated because:
> > >    *   .leave_on is False, so (ref == 0)
> > 
> > Again, .leave_on does nothing new here. We gate the clock because the
> > reference count is 0.
> 
> It's the fact that .leave_on has been disabled in
> clk_disable_critical() that allows the final reference to be taken.
> 
> > >    */
> > > 
> > > Resume:
> > >   /* Order is unimportant */
> > >   SPI enables Clock 4 (ref == 1)
> > >   RAM enables Clock 4 and re-enables .leave_on (ref == 2)
> > >   I2C enables Clock 4 (ref == 3)
> > 
> > Same again. As soon as RAM calls clk_enable_critical the ref count goes
> > up. .leave_on does nothing as far as I can tell. The all works because
> > of the reference counting, which already exists before this patch
> > series.
> 
> So fundamentally you're right in what you say.  All you really need to
> disable a critical clock is write a knowledgeable driver, which is
> intentionally unbalanced i.e. just calls clk_disable().  All this

OK, the line above is helpful. What you really want is a formalized
hand-off mechanism, whereby the clock is enabled at registration-time
and it cannot be turned off until the right driver claims it and decides
turning it off is OK (with a priori knowledge that the clock is already
enabled).

Note that I don't think this implementation can really work in the near
future. Today we do not catch unbalanced calls to clk_enable and
clk_disable, but I have a patch that catches this and WARNs loudly in my
private tree. More on that in the next stanza.

What I don't understand is if there is ever a case for a clock consumer
driver to ever call clk_enable_critical... I do not think there is. What
you're trying to protect against is having the clock disabled BEFORE
that "knowledgeable driver" has a chance to enable it.

Let me know if I've got that right. The only user of this function in
your series is the clk-conf.c stuff, which matches my summary above.

> extended API really does is makes the process more official and
> ensures that an unintentionally unbalanced driver doesn't bugger up
> the running platform.  We could also add a new WARN() to say that said
> driver is unbalanced, as it just tried to turn off a critical clock.

As I mentioned up above I am working on this right now. Our per-user
struct clk stuff makes it trivial to track prepare_count and
enable_count values on a per-user basis. Consequently a naive approach
that simply calls clk_disable an extra time will not work once this code
is merged. This is because the struct clk used in clk-conf.c and in your
knowledgeable driver will be two distinct instances.

Regards,
Mike

> 
> What do you think is best?
> 
> -- 
> Lee Jones
> Linaro STMicroelectronics Landing Team Lead
> Linaro.org │ Open source software for ARM SoCs
> Follow Linaro: Facebook | Twitter | Blog

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v7 3/5] clk: Supply the critical clock {init, enable, disable} framework
@ 2015-07-30 22:47                 ` Michael Turquette
  0 siblings, 0 replies; 93+ messages in thread
From: Michael Turquette @ 2015-07-30 22:47 UTC (permalink / raw)
  To: linux-arm-kernel

Quoting Lee Jones (2015-07-30 02:50:14)
> On Wed, 29 Jul 2015, Michael Turquette wrote:
> > Quoting Lee Jones (2015-07-28 06:00:55)
> > > On Tue, 28 Jul 2015, Maxime Ripard wrote:
> > > 
> > > > On Mon, Jul 27, 2015 at 09:53:38AM +0100, Lee Jones wrote:
> > > > > On Mon, 27 Jul 2015, Maxime Ripard wrote:
> > > > > 
> > > > > > On Wed, Jul 22, 2015 at 02:04:13PM +0100, Lee Jones wrote:
> > > > > > > These new API calls will firstly provide a mechanisms to tag a clock as
> > > > > > > critical and secondly allow any knowledgeable driver to (un)gate clocks,
> > > > > > > even if they are marked as critical.
> > > > > > > 
> > > > > > > Suggested-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> > > > > > > Signed-off-by: Lee Jones <lee.jones@linaro.org>
> > > > > > > ---
> > > > > > >  drivers/clk/clk.c            | 45 ++++++++++++++++++++++++++++++++++++++++++++
> > > > > > >  include/linux/clk-provider.h |  2 ++
> > > > > > >  include/linux/clk.h          | 30 +++++++++++++++++++++++++++++
> > > > > > >  3 files changed, 77 insertions(+)
> > > > > > > 
> > > > > > > diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> > > > > > > index 61c3fc5..486b1da 100644
> > > > > > > --- a/drivers/clk/clk.c
> > > > > > > +++ b/drivers/clk/clk.c
> > > > > > > @@ -46,6 +46,21 @@ static struct clk_core *clk_core_lookup(const char *name);
> > > > > > >  
> > > > > > >  /***    private data structures    ***/
> > > > > > >  
> > > > > > > +/**
> > > > > > > + * struct critical -   Provides 'play' over critical clocks.  A clock can be
> > > > > > > + *                     marked as critical, meaning that it should not be
> > > > > > > + *                     disabled.  However, if a driver which is aware of the
> > > > > > > + *                     critical behaviour wants to control it, it can do so
> > > > > > > + *                     using clk_enable_critical() and clk_disable_critical().
> > > > > > > + *
> > > > > > > + * @enabled    Is clock critical?  Once set, doesn't change
> > > > > > > + * @leave_on   Self explanatory.  Can be disabled by knowledgeable drivers
> > > > > > > + */
> > > > > > > +struct critical {
> > > > > > > +       bool enabled;
> > > > > > > +       bool leave_on;
> > > > > > > +};
> > > > > > > +
> > > > > > >  struct clk_core {
> > > > > > >         const char              *name;
> > > > > > >         const struct clk_ops    *ops;
> > > > > > > @@ -75,6 +90,7 @@ struct clk_core {
> > > > > > >         struct dentry           *dentry;
> > > > > > >  #endif
> > > > > > >         struct kref             ref;
> > > > > > > +       struct critical         critical;
> > > > > > >  };
> > > > > > >  
> > > > > > >  struct clk {
> > > > > > > @@ -995,6 +1011,10 @@ static void clk_core_disable(struct clk_core *clk)
> > > > > > >         if (WARN_ON(clk->enable_count == 0))
> > > > > > >                 return;
> > > > > > >  
> > > > > > > +       /* Refuse to turn off a critical clock */
> > > > > > > +       if (clk->enable_count == 1 && clk->critical.leave_on)
> > > > > > > +               return;
> > > > > > > +
> > > > > > 
> > > > > > I think it should be handled by a separate counting. Otherwise, if you
> > > > > > have two users that marked the clock as critical, and then one of them
> > > > > > disable it...
> > > > > > 
> > > > > > >         if (--clk->enable_count > 0)
> > > > > > >                 return;
> > > > > > >  
> > > > > > > @@ -1037,6 +1057,13 @@ void clk_disable(struct clk *clk)
> > > > > > >  }
> > > > > > >  EXPORT_SYMBOL_GPL(clk_disable);
> > > > > > >  
> > > > > > > +void clk_disable_critical(struct clk *clk)
> > > > > > > +{
> > > > > > > +       clk->core->critical.leave_on = false;
> > > > > > 
> > > > > > .. you just lost the fact that it was critical in the first place.
> > > > > 
> > > > > I thought about both of these points, which is why I came up with this
> > > > > strategy.
> > > > > 
> > > > > Any device which uses the *_critical() API should a) have knowledge of
> > > > > what happens when a particular critical clock is gated and b) have
> > > > > thought about the consequences.
> > > > 
> > > > Indeed.
> > > > 
> > > > > I don't think we can use reference counting, because we'd need as
> > > > > many critical clock owners as there are critical clocks.
> > > > 
> > > > Which we can have if we replace the call to clk_prepare_enable you add
> > > > in your fourth patch in __set_critical_clocks.
> > > 
> > > What should it be replaced with?
> > > 
> > > > > Cast your mind back to the reasons for this critical clock API.  One
> > > > > of the most important intentions of this API is the requirement
> > > > > mitigation for each of the critical clocks to have an owner
> > > > > (driver).
> > > > > 
> > > > > With regards to your second point, that's what 'critical.enabled'
> > > > > is for.  Take a look at clk_enable_critical().
> > > > 
> > > > I don't think this addresses the issue, if you just throw more
> > > > customers at it, the issue remain with your implementation.
> > > > 
> > > > If you have three customers that used the critical API, and if on of
> > > > these calls clk_disable_critical, you're losing leave_on.
> > > 
> > > That's the idea.  See my point above, the one you replied "Indeed"
> > > to.  So when a driver uses clk_disable_critical() it's saying, "I know
> > > why this clock is a critical clock, and I know that nothing terrible
> > > will happen if I disable it, as I have that covered".  So then if it's
> > > not the last user to call clk_disable(), the last one out the door
> > > will be allowed to finally gate the clock, regardless whether it's
> > > critical aware or not.
> > > 
> > > Then, when we come to enable the clock again, the critical aware user
> > > then re-marks the clock as leave_on, so not critical un-aware user can
> > > take the final reference and disable the clock.
> > > 
> > > > Which means that if there's one of the two users left that calls
> > > > clk_disable on it, the clock will actually be disabled, which is
> > > > clearly not what we want to do, as we have still a user that want the
> > > > clock to be enabled.
> > > 
> > > That's not what happens (at least it shouldn't if I've coded it up
> > > right).  The API _still_ requires all of the users to give-up their
> > > reference.
> > > 
> > > > It would be much more robust to have another count for the critical
> > > > stuff, initialised to one by the __set_critical_clocks function.
> > > 
> > > If I understand you correctly, we already have a count.  We use the
> > > original reference count.  No need for one of our own.
> > > 
> > > Using your RAM Clock (Clock 4) as an example
> > > --------------------------------------------
> > > 
> > > Early start-up:
> > >   Clock 4 is marked as critical and a reference is taken (ref == 1)
> > > 
> > > Driver probe:
> > >   SPI enables Clock 4 (ref == 2)
> > >   I2C enables Clock 4 (ref == 3)
> > > 
> > > Suspend (without RAM driver's permission):
> > >   SPI disables Clock 4 (ref == 2)
> > >   I2C disables Clock 4 (ref == 1)
> > >   /*
> > >    * Clock won't be gated because:
> > >    *   .leave_on is True - can't dec final reference
> > 
> > I am clearly missing the point. The clock won't be gated because the
> > enable_count is still 1! What does .leave_on do here?
> 
> The point of _this_ (the extended) part of the API is so that the
> clock _can_ be turned off.  Without the possibility to disable
> .leave_on and the logic with accompanies it (i.e.
> clk_disable_critical()) the clock will _never_ be gated.
> 
> > >    */
> > > 
> > > Suspend (with RAM driver's permission):
> > >   /* Order is unimportant */
> > >   SPI disables Clock 4 (ref == 2)
> > >   RAM disables Clock 4 (ref == 1) /* Won't turn off here (ref > 0)
> > >   I2C disables Clock 4 (ref == 0) /* (.leave_on == False) last ref can be taken */
> > >   /*
> > >    * Clock will be gated because:
> > >    *   .leave_on is False, so (ref == 0)
> > 
> > Again, .leave_on does nothing new here. We gate the clock because the
> > reference count is 0.
> 
> It's the fact that .leave_on has been disabled in
> clk_disable_critical() that allows the final reference to be taken.
> 
> > >    */
> > > 
> > > Resume:
> > >   /* Order is unimportant */
> > >   SPI enables Clock 4 (ref == 1)
> > >   RAM enables Clock 4 and re-enables .leave_on (ref == 2)
> > >   I2C enables Clock 4 (ref == 3)
> > 
> > Same again. As soon as RAM calls clk_enable_critical the ref count goes
> > up. .leave_on does nothing as far as I can tell. The all works because
> > of the reference counting, which already exists before this patch
> > series.
> 
> So fundamentally you're right in what you say.  All you really need to
> disable a critical clock is write a knowledgeable driver, which is
> intentionally unbalanced i.e. just calls clk_disable().  All this

OK, the line above is helpful. What you really want is a formalized
hand-off mechanism, whereby the clock is enabled at registration-time
and it cannot be turned off until the right driver claims it and decides
turning it off is OK (with a priori knowledge that the clock is already
enabled).

Note that I don't think this implementation can really work in the near
future. Today we do not catch unbalanced calls to clk_enable and
clk_disable, but I have a patch that catches this and WARNs loudly in my
private tree. More on that in the next stanza.

What I don't understand is if there is ever a case for a clock consumer
driver to ever call clk_enable_critical... I do not think there is. What
you're trying to protect against is having the clock disabled BEFORE
that "knowledgeable driver" has a chance to enable it.

Let me know if I've got that right. The only user of this function in
your series is the clk-conf.c stuff, which matches my summary above.

> extended API really does is makes the process more official and
> ensures that an unintentionally unbalanced driver doesn't bugger up
> the running platform.  We could also add a new WARN() to say that said
> driver is unbalanced, as it just tried to turn off a critical clock.

As I mentioned up above I am working on this right now. Our per-user
struct clk stuff makes it trivial to track prepare_count and
enable_count values on a per-user basis. Consequently a naive approach
that simply calls clk_disable an extra time will not work once this code
is merged. This is because the struct clk used in clk-conf.c and in your
knowledgeable driver will be two distinct instances.

Regards,
Mike

> 
> What do you think is best?
> 
> -- 
> Lee Jones
> Linaro STMicroelectronics Landing Team Lead
> Linaro.org ? Open source software for ARM SoCs
> Follow Linaro: Facebook | Twitter | Blog

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

* Re: [PATCH v7 3/5] clk: Supply the critical clock {init, enable, disable} framework
  2015-07-30  9:21           ` Lee Jones
@ 2015-07-30 22:57             ` Michael Turquette
  -1 siblings, 0 replies; 93+ messages in thread
From: Michael Turquette @ 2015-07-30 22:57 UTC (permalink / raw)
  To: Lee Jones
  Cc: devicetree, kernel, s.hauer, sboyd, linux-kernel, geert,
	Maxime Ripard, linux-arm-kernel

Quoting Lee Jones (2015-07-30 02:21:39)
> On Wed, 29 Jul 2015, Michael Turquette wrote:
> > Quoting Lee Jones (2015-07-27 01:53:38)
> > > On Mon, 27 Jul 2015, Maxime Ripard wrote:
> > > 
> > > > On Wed, Jul 22, 2015 at 02:04:13PM +0100, Lee Jones wrote:
> > > > > These new API calls will firstly provide a mechanisms to tag a clock as
> > > > > critical and secondly allow any knowledgeable driver to (un)gate clocks,
> > > > > even if they are marked as critical.
> > > > > 
> > > > > Suggested-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> > > > > Signed-off-by: Lee Jones <lee.jones@linaro.org>
> > > > > ---
> > > > >  drivers/clk/clk.c            | 45 ++++++++++++++++++++++++++++++++++++++++++++
> > > > >  include/linux/clk-provider.h |  2 ++
> > > > >  include/linux/clk.h          | 30 +++++++++++++++++++++++++++++
> > > > >  3 files changed, 77 insertions(+)
> > > > > 
> > > > > diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> > > > > index 61c3fc5..486b1da 100644
> > > > > --- a/drivers/clk/clk.c
> > > > > +++ b/drivers/clk/clk.c
> > > > > @@ -46,6 +46,21 @@ static struct clk_core *clk_core_lookup(const char *name);
> > > > >  
> > > > >  /***    private data structures    ***/
> > > > >  
> > > > > +/**
> > > > > + * struct critical -       Provides 'play' over critical clocks.  A clock can be
> > > > > + *                 marked as critical, meaning that it should not be
> > > > > + *                 disabled.  However, if a driver which is aware of the
> > > > > + *                 critical behaviour wants to control it, it can do so
> > > > > + *                 using clk_enable_critical() and clk_disable_critical().
> > > > > + *
> > > > > + * @enabled        Is clock critical?  Once set, doesn't change
> > > > > + * @leave_on       Self explanatory.  Can be disabled by knowledgeable drivers
> > > > > + */
> > > > > +struct critical {
> > > > > +   bool enabled;
> > > > > +   bool leave_on;
> > > > > +};
> > > > > +
> > > > >  struct clk_core {
> > > > >     const char              *name;
> > > > >     const struct clk_ops    *ops;
> > > > > @@ -75,6 +90,7 @@ struct clk_core {
> > > > >     struct dentry           *dentry;
> > > > >  #endif
> > > > >     struct kref             ref;
> > > > > +   struct critical         critical;
> > > > >  };
> > > > >  
> > > > >  struct clk {
> > > > > @@ -995,6 +1011,10 @@ static void clk_core_disable(struct clk_core *clk)
> > > > >     if (WARN_ON(clk->enable_count == 0))
> > > > >             return;
> > > > >  
> > > > > +   /* Refuse to turn off a critical clock */
> > > > > +   if (clk->enable_count == 1 && clk->critical.leave_on)
> > > > > +           return;
> > > > > +
> > > > 
> > > > I think it should be handled by a separate counting. Otherwise, if you
> > > > have two users that marked the clock as critical, and then one of them
> > > > disable it...
> > > > 
> > > > >     if (--clk->enable_count > 0)
> > > > >             return;
> > > > >  
> > > > > @@ -1037,6 +1057,13 @@ void clk_disable(struct clk *clk)
> > > > >  }
> > > > >  EXPORT_SYMBOL_GPL(clk_disable);
> > > > >  
> > > > > +void clk_disable_critical(struct clk *clk)
> > > > > +{
> > > > > +   clk->core->critical.leave_on = false;
> > > > 
> > > > .. you just lost the fact that it was critical in the first place.
> > > 
> > > I thought about both of these points, which is why I came up with this
> > > strategy.
> > > 
> > > Any device which uses the *_critical() API should a) have knowledge of
> > > what happens when a particular critical clock is gated and b) have
> > > thought about the consequences.
> > 
> > If this statement above is true then I fail to see the need for a new
> > api. A driver which has a really great idea of when it is safe or unsafe
> > to gate a clock should call clk_prepare_enable at probe and then only
> > call clk_disable_unprepare once it is safe to do so.
> > 
> > The existing bookkeeping in the clock framework will do the rest.
> 
> I think you are viewing this particular API back-to-front.  The idea
> is to mark all of the critical clocks at start-up by taking a
> reference.  Then, if there are no knowledgable drivers who wish to
> turn the clock off, the CCF will leave the clock ungated becuase the
> reference count will always be >0.

Right. So I'll ask the same question here that I asked in the other
patch: is there ever a case where a clock consumer driver would want to
call clk_enable_critical? It seems to me that in you usage of it, that
call would only ever be made by the core framework code (e.g. clk-conf.c
or perhaps somewhere in drivers/clk/clk.c).

> 
> The clk_{disable,enable}_critical() calls are to be used by
> knowledgable drivers to say "[disable] I know what I'm doing and it's
> okay for this clock to be turned off" and "[enable] right I'm done
> with this clock now, let's turn it back on and mark it back as
> critical, so no one else can turn it off".

OK, so this almost answers my question above. You have a driver that may
finish using a clock for a while (ie, rmmod knowledgeable_driver), and
you want it (critically) enabled again. Is this a real use case? Who
would come along and disable this clock later on? If the driver is to be
re-loaded then I would suggest never unloading it in the first place.

(Oh and bear in mind when answering my question above that imbalanced
clk_enable/clk_disable calls will not succeed thanks to the vaporware
patch that I have in my local tree)

If you have a second knowledgeable_driver_2 that shares that clock and
can be trusted to manage it (critically) then I would need to see that
example, as it doesn't feel like a real use to me.

> 
> To put things simply, the knowledgable driver will _not_ be enabling
> the clock in the first place.  The first interaction it has with it is
> to gate it.  Then, once it's done, it will enable it again and mark it
> back up as critical.a

I like the first part. Makes sense and fills a real need. I am fully
on-board with a provider-handoff-to-consumer solution. It is all the
weird stuff that comes after it that I'm unsure of.

Regards,
Mike

> 
> Still confused ... let's go on another Q in one of your other emails
> for another way of putting it.
> 
> > > I don't think we can use reference
> > > counting, because we'd need as many critical clock owners as there are
> > > critical clocks.  Cast your mind back to the reasons for this critical
> > > clock API.  One of the most important intentions of this API is the
> > > requirement mitigation for each of the critical clocks to have an owner
> > > (driver).
> > > 
> > > With regards to your second point, that's what 'critical.enabled'
> > > is for.  Take a look at clk_enable_critical().
> > > 
> 
> -- 
> Lee Jones
> Linaro STMicroelectronics Landing Team Lead
> Linaro.org │ Open source software for ARM SoCs
> Follow Linaro: Facebook | Twitter | Blog

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v7 3/5] clk: Supply the critical clock {init, enable, disable} framework
@ 2015-07-30 22:57             ` Michael Turquette
  0 siblings, 0 replies; 93+ messages in thread
From: Michael Turquette @ 2015-07-30 22:57 UTC (permalink / raw)
  To: linux-arm-kernel

Quoting Lee Jones (2015-07-30 02:21:39)
> On Wed, 29 Jul 2015, Michael Turquette wrote:
> > Quoting Lee Jones (2015-07-27 01:53:38)
> > > On Mon, 27 Jul 2015, Maxime Ripard wrote:
> > > 
> > > > On Wed, Jul 22, 2015 at 02:04:13PM +0100, Lee Jones wrote:
> > > > > These new API calls will firstly provide a mechanisms to tag a clock as
> > > > > critical and secondly allow any knowledgeable driver to (un)gate clocks,
> > > > > even if they are marked as critical.
> > > > > 
> > > > > Suggested-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> > > > > Signed-off-by: Lee Jones <lee.jones@linaro.org>
> > > > > ---
> > > > >  drivers/clk/clk.c            | 45 ++++++++++++++++++++++++++++++++++++++++++++
> > > > >  include/linux/clk-provider.h |  2 ++
> > > > >  include/linux/clk.h          | 30 +++++++++++++++++++++++++++++
> > > > >  3 files changed, 77 insertions(+)
> > > > > 
> > > > > diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> > > > > index 61c3fc5..486b1da 100644
> > > > > --- a/drivers/clk/clk.c
> > > > > +++ b/drivers/clk/clk.c
> > > > > @@ -46,6 +46,21 @@ static struct clk_core *clk_core_lookup(const char *name);
> > > > >  
> > > > >  /***    private data structures    ***/
> > > > >  
> > > > > +/**
> > > > > + * struct critical -       Provides 'play' over critical clocks.  A clock can be
> > > > > + *                 marked as critical, meaning that it should not be
> > > > > + *                 disabled.  However, if a driver which is aware of the
> > > > > + *                 critical behaviour wants to control it, it can do so
> > > > > + *                 using clk_enable_critical() and clk_disable_critical().
> > > > > + *
> > > > > + * @enabled        Is clock critical?  Once set, doesn't change
> > > > > + * @leave_on       Self explanatory.  Can be disabled by knowledgeable drivers
> > > > > + */
> > > > > +struct critical {
> > > > > +   bool enabled;
> > > > > +   bool leave_on;
> > > > > +};
> > > > > +
> > > > >  struct clk_core {
> > > > >     const char              *name;
> > > > >     const struct clk_ops    *ops;
> > > > > @@ -75,6 +90,7 @@ struct clk_core {
> > > > >     struct dentry           *dentry;
> > > > >  #endif
> > > > >     struct kref             ref;
> > > > > +   struct critical         critical;
> > > > >  };
> > > > >  
> > > > >  struct clk {
> > > > > @@ -995,6 +1011,10 @@ static void clk_core_disable(struct clk_core *clk)
> > > > >     if (WARN_ON(clk->enable_count == 0))
> > > > >             return;
> > > > >  
> > > > > +   /* Refuse to turn off a critical clock */
> > > > > +   if (clk->enable_count == 1 && clk->critical.leave_on)
> > > > > +           return;
> > > > > +
> > > > 
> > > > I think it should be handled by a separate counting. Otherwise, if you
> > > > have two users that marked the clock as critical, and then one of them
> > > > disable it...
> > > > 
> > > > >     if (--clk->enable_count > 0)
> > > > >             return;
> > > > >  
> > > > > @@ -1037,6 +1057,13 @@ void clk_disable(struct clk *clk)
> > > > >  }
> > > > >  EXPORT_SYMBOL_GPL(clk_disable);
> > > > >  
> > > > > +void clk_disable_critical(struct clk *clk)
> > > > > +{
> > > > > +   clk->core->critical.leave_on = false;
> > > > 
> > > > .. you just lost the fact that it was critical in the first place.
> > > 
> > > I thought about both of these points, which is why I came up with this
> > > strategy.
> > > 
> > > Any device which uses the *_critical() API should a) have knowledge of
> > > what happens when a particular critical clock is gated and b) have
> > > thought about the consequences.
> > 
> > If this statement above is true then I fail to see the need for a new
> > api. A driver which has a really great idea of when it is safe or unsafe
> > to gate a clock should call clk_prepare_enable at probe and then only
> > call clk_disable_unprepare once it is safe to do so.
> > 
> > The existing bookkeeping in the clock framework will do the rest.
> 
> I think you are viewing this particular API back-to-front.  The idea
> is to mark all of the critical clocks at start-up by taking a
> reference.  Then, if there are no knowledgable drivers who wish to
> turn the clock off, the CCF will leave the clock ungated becuase the
> reference count will always be >0.

Right. So I'll ask the same question here that I asked in the other
patch: is there ever a case where a clock consumer driver would want to
call clk_enable_critical? It seems to me that in you usage of it, that
call would only ever be made by the core framework code (e.g. clk-conf.c
or perhaps somewhere in drivers/clk/clk.c).

> 
> The clk_{disable,enable}_critical() calls are to be used by
> knowledgable drivers to say "[disable] I know what I'm doing and it's
> okay for this clock to be turned off" and "[enable] right I'm done
> with this clock now, let's turn it back on and mark it back as
> critical, so no one else can turn it off".

OK, so this almost answers my question above. You have a driver that may
finish using a clock for a while (ie, rmmod knowledgeable_driver), and
you want it (critically) enabled again. Is this a real use case? Who
would come along and disable this clock later on? If the driver is to be
re-loaded then I would suggest never unloading it in the first place.

(Oh and bear in mind when answering my question above that imbalanced
clk_enable/clk_disable calls will not succeed thanks to the vaporware
patch that I have in my local tree)

If you have a second knowledgeable_driver_2 that shares that clock and
can be trusted to manage it (critically) then I would need to see that
example, as it doesn't feel like a real use to me.

> 
> To put things simply, the knowledgable driver will _not_ be enabling
> the clock in the first place.  The first interaction it has with it is
> to gate it.  Then, once it's done, it will enable it again and mark it
> back up as critical.a

I like the first part. Makes sense and fills a real need. I am fully
on-board with a provider-handoff-to-consumer solution. It is all the
weird stuff that comes after it that I'm unsure of.

Regards,
Mike

> 
> Still confused ... let's go on another Q in one of your other emails
> for another way of putting it.
> 
> > > I don't think we can use reference
> > > counting, because we'd need as many critical clock owners as there are
> > > critical clocks.  Cast your mind back to the reasons for this critical
> > > clock API.  One of the most important intentions of this API is the
> > > requirement mitigation for each of the critical clocks to have an owner
> > > (driver).
> > > 
> > > With regards to your second point, that's what 'critical.enabled'
> > > is for.  Take a look at clk_enable_critical().
> > > 
> 
> -- 
> Lee Jones
> Linaro STMicroelectronics Landing Team Lead
> Linaro.org ? Open source software for ARM SoCs
> Follow Linaro: Facebook | Twitter | Blog

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

* Re: [PATCH v7 3/5] clk: Supply the critical clock {init, enable, disable} framework
  2015-07-30 11:17       ` Lee Jones
  (?)
@ 2015-07-30 23:35         ` Michael Turquette
  -1 siblings, 0 replies; 93+ messages in thread
From: Michael Turquette @ 2015-07-30 23:35 UTC (permalink / raw)
  To: Lee Jones
  Cc: devicetree, kernel, s.hauer, sboyd, linux-kernel, geert,
	maxime.ripard, linux-clk, linux-arm-kernel

Quoting Lee Jones (2015-07-30 04:17:47)
> On Wed, 29 Jul 2015, Michael Turquette wrote:
> 
> > Hi Lee,
> > 
> > + linux-clk ml
> > 
> > Quoting Lee Jones (2015-07-22 06:04:13)
> > > These new API calls will firstly provide a mechanisms to tag a clock as
> > > critical and secondly allow any knowledgeable driver to (un)gate clocks,
> > > even if they are marked as critical.
> > > 
> > > Suggested-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> > > Signed-off-by: Lee Jones <lee.jones@linaro.org>
> > > ---
> > >  drivers/clk/clk.c            | 45 ++++++++++++++++++++++++++++++++++++++++++++
> > >  include/linux/clk-provider.h |  2 ++
> > >  include/linux/clk.h          | 30 +++++++++++++++++++++++++++++
> > >  3 files changed, 77 insertions(+)
> > > 
> > > diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> > > index 61c3fc5..486b1da 100644
> > > --- a/drivers/clk/clk.c
> > > +++ b/drivers/clk/clk.c
> > > @@ -46,6 +46,21 @@ static struct clk_core *clk_core_lookup(const char *name);
> > >  
> > >  /***    private data structures    ***/
> > >  
> > > +/**
> > > + * struct critical -   Provides 'play' over critical clocks.  A clock can be
> > > + *                     marked as critical, meaning that it should not be
> > > + *                     disabled.  However, if a driver which is aware of the
> > > + *                     critical behaviour wants to control it, it can do so
> > > + *                     using clk_enable_critical() and clk_disable_critical().
> > > + *
> > > + * @enabled    Is clock critical?  Once set, doesn't change
> > > + * @leave_on   Self explanatory.  Can be disabled by knowledgeable drivers
> > 
> > Not self explanatory. I need this explained to me. What does leave_on
> > do? Better yet, what would happen if leave_on did not exist?
> > 
> > > + */
> > > +struct critical {
> > > +       bool enabled;
> > > +       bool leave_on;
> > > +};
> > > +
> > >  struct clk_core {
> > >         const char              *name;
> > >         const struct clk_ops    *ops;
> > > @@ -75,6 +90,7 @@ struct clk_core {
> > >         struct dentry           *dentry;
> > >  #endif
> > >         struct kref             ref;
> > > +       struct critical         critical;
> > >  };
> > >  
> > >  struct clk {
> > > @@ -995,6 +1011,10 @@ static void clk_core_disable(struct clk_core *clk)
> > >         if (WARN_ON(clk->enable_count == 0))
> > >                 return;
> > >  
> > > +       /* Refuse to turn off a critical clock */
> > > +       if (clk->enable_count == 1 && clk->critical.leave_on)
> > > +               return;
> > 
> > How do we get to this point? clk_enable_critical actually calls
> > clk_enable, thus incrementing the enable_count. The only time that we
> > could hit the above case is if,
> > 
> > a) there is an imbalance in clk_enable and clk_disable calls. If this is
> > the case then the drivers need to be fixed. Or better yet some
> > infrastructure to catch that, now that we have per-user struct clk
> > cookies.
> > 
> > b) a driver knowingly calls clk_enable_critical(foo) and then regular,
> > old clk_disable(foo). But why would a driver do that?
> > 
> > It might be that I am missing the point here, so please feel free to
> > clue me in.
> 
> This check behaves in a very similar to the WARN() above.  It's more
> of a fail-safe.  If all drivers are behaving properly, then it
> shouldn't ever be true.  If they're not, it prevents an incorrectly
> written driver from irrecoverably crippling the system.

Then this check should be replaced with a generic approach that refuses
to honor imbalances anyways. Below are two patches that probably resolve
the issue of badly behaving drivers that cause enable imbalances.

> 
> As I said in the other mail.  We can do without these 3 new wrappers.
> We _could_ just write a driver which only calls clk_enable() _after_
> it calls clk_disable(), a kind of intentional unbalance and it would
> do that same thing.

This naive approach will not work with per-user imbalance tracking.

> However, what we're trying to do here is provide
> a proper API, so we can see at first glance what the 'knowledgeable'
> driver is trying to do and not have someone attempt to submit a 'fix'
> which calls clk_enable() or something.

We'll need some type of api for sure for the handoff.

Regards,
Mike



>From 3599ed206da9ce770bfafcfd95cbb9a03ac44473 Mon Sep 17 00:00:00 2001
From: Michael Turquette <mturquette@baylibre.com>
Date: Wed, 29 Jul 2015 18:22:45 -0700
Subject: [PATCH 1/2] clk: per-user clk prepare & enable ref counts

This patch adds prepare and enable reference counts for the per-user
handles that clock consumers have for a clock node. This patch warns if
an imbalance occurs while trying to disable or unprepare a clock and
aborts, leaving the hardware unaffected.

Signed-off-by: Michael Turquette <mturquette@baylibre.com>
---
 drivers/clk/clk.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 898052e..72feee9 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -84,6 +84,8 @@ struct clk {
 	unsigned long min_rate;
 	unsigned long max_rate;
 	struct hlist_node clks_node;
+	unsigned int enable_count;
+	unsigned int prepare_count;
 };
 
 /***           locking             ***/
@@ -600,6 +602,9 @@ void clk_unprepare(struct clk *clk)
 		return;
 
 	clk_prepare_lock();
+	if (WARN_ON(clk->prepare_count == 0))
+		return;
+	clk->prepare_count--;
 	clk_core_unprepare(clk->core);
 	clk_prepare_unlock();
 }
@@ -657,6 +662,7 @@ int clk_prepare(struct clk *clk)
 		return 0;
 
 	clk_prepare_lock();
+	clk->prepare_count++;
 	ret = clk_core_prepare(clk->core);
 	clk_prepare_unlock();
 
@@ -707,6 +713,9 @@ void clk_disable(struct clk *clk)
 		return;
 
 	flags = clk_enable_lock();
+	if (WARN_ON(clk->enable_count == 0))
+		return;
+	clk->enable_count--;
 	clk_core_disable(clk->core);
 	clk_enable_unlock(flags);
 }
@@ -769,6 +778,7 @@ int clk_enable(struct clk *clk)
 		return 0;
 
 	flags = clk_enable_lock();
+	clk->enable_count++;
 	ret = clk_core_enable(clk->core);
 	clk_enable_unlock(flags);
 
-- 
1.9.1

>From ace76f6ed634a69c499f8440a98d4b5a54d78368 Mon Sep 17 00:00:00 2001
From: Michael Turquette <mturquette@baylibre.com>
Date: Thu, 30 Jul 2015 12:52:26 -0700
Subject: [PATCH 2/2] clk: clk_put WARNs if user has not disabled clk

>From the clk_put kerneldoc in include/linux/clk.h:

"""
Note: drivers must ensure that all clk_enable calls made on this clock
source are balanced by clk_disable calls prior to calling this function.
"""

The common clock framework implementation of the clk.h api has per-user
reference counts for calls to clk_prepare and clk_disable. As such it
can enforce the requirement to properly call clk_disable and
clk_unprepare before calling clk_put.

Because this requirement is probably violated in many places, this patch
starts with a simple warning. Once offending code has been fixed this
check could additionally release the reference counts automatically.

Signed-off-by: Michael Turquette <mturquette@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 72feee9..6ec0f77 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -2764,6 +2764,14 @@ void __clk_put(struct clk *clk)
 	    clk->max_rate < clk->core->req_rate)
 		clk_core_set_rate_nolock(clk->core, clk->core->req_rate);
 
+	/*
+	 * before calling clk_put, all calls to clk_prepare and clk_enable from
+	 * a given user must be balanced with calls to clk_disable and
+	 * clk_unprepare by that same user
+	 */
+	WARN_ON(clk->prepare_count);
+	WARN_ON(clk->enable_count);
+
 	owner = clk->core->owner;
 	kref_put(&clk->core->ref, __clk_release);
 
-- 
1.9.1

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

* Re: [PATCH v7 3/5] clk: Supply the critical clock {init, enable, disable} framework
@ 2015-07-30 23:35         ` Michael Turquette
  0 siblings, 0 replies; 93+ messages in thread
From: Michael Turquette @ 2015-07-30 23:35 UTC (permalink / raw)
  To: Lee Jones
  Cc: linux-arm-kernel, linux-kernel, kernel, sboyd, devicetree, geert,
	maxime.ripard, s.hauer, linux-clk

Quoting Lee Jones (2015-07-30 04:17:47)
> On Wed, 29 Jul 2015, Michael Turquette wrote:
> =

> > Hi Lee,
> > =

> > + linux-clk ml
> > =

> > Quoting Lee Jones (2015-07-22 06:04:13)
> > > These new API calls will firstly provide a mechanisms to tag a clock =
as
> > > critical and secondly allow any knowledgeable driver to (un)gate cloc=
ks,
> > > even if they are marked as critical.
> > > =

> > > Suggested-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> > > Signed-off-by: Lee Jones <lee.jones@linaro.org>
> > > ---
> > >  drivers/clk/clk.c            | 45 ++++++++++++++++++++++++++++++++++=
++++++++++
> > >  include/linux/clk-provider.h |  2 ++
> > >  include/linux/clk.h          | 30 +++++++++++++++++++++++++++++
> > >  3 files changed, 77 insertions(+)
> > > =

> > > diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> > > index 61c3fc5..486b1da 100644
> > > --- a/drivers/clk/clk.c
> > > +++ b/drivers/clk/clk.c
> > > @@ -46,6 +46,21 @@ static struct clk_core *clk_core_lookup(const char=
 *name);
> > >  =

> > >  /***    private data structures    ***/
> > >  =

> > > +/**
> > > + * struct critical -   Provides 'play' over critical clocks.  A cloc=
k can be
> > > + *                     marked as critical, meaning that it should no=
t be
> > > + *                     disabled.  However, if a driver which is awar=
e of the
> > > + *                     critical behaviour wants to control it, it ca=
n do so
> > > + *                     using clk_enable_critical() and clk_disable_c=
ritical().
> > > + *
> > > + * @enabled    Is clock critical?  Once set, doesn't change
> > > + * @leave_on   Self explanatory.  Can be disabled by knowledgeable d=
rivers
> > =

> > Not self explanatory. I need this explained to me. What does leave_on
> > do? Better yet, what would happen if leave_on did not exist?
> > =

> > > + */
> > > +struct critical {
> > > +       bool enabled;
> > > +       bool leave_on;
> > > +};
> > > +
> > >  struct clk_core {
> > >         const char              *name;
> > >         const struct clk_ops    *ops;
> > > @@ -75,6 +90,7 @@ struct clk_core {
> > >         struct dentry           *dentry;
> > >  #endif
> > >         struct kref             ref;
> > > +       struct critical         critical;
> > >  };
> > >  =

> > >  struct clk {
> > > @@ -995,6 +1011,10 @@ static void clk_core_disable(struct clk_core *c=
lk)
> > >         if (WARN_ON(clk->enable_count =3D=3D 0))
> > >                 return;
> > >  =

> > > +       /* Refuse to turn off a critical clock */
> > > +       if (clk->enable_count =3D=3D 1 && clk->critical.leave_on)
> > > +               return;
> > =

> > How do we get to this point? clk_enable_critical actually calls
> > clk_enable, thus incrementing the enable_count. The only time that we
> > could hit the above case is if,
> > =

> > a) there is an imbalance in clk_enable and clk_disable calls. If this is
> > the case then the drivers need to be fixed. Or better yet some
> > infrastructure to catch that, now that we have per-user struct clk
> > cookies.
> > =

> > b) a driver knowingly calls clk_enable_critical(foo) and then regular,
> > old clk_disable(foo). But why would a driver do that?
> > =

> > It might be that I am missing the point here, so please feel free to
> > clue me in.
> =

> This check behaves in a very similar to the WARN() above.  It's more
> of a fail-safe.  If all drivers are behaving properly, then it
> shouldn't ever be true.  If they're not, it prevents an incorrectly
> written driver from irrecoverably crippling the system.

Then this check should be replaced with a generic approach that refuses
to honor imbalances anyways. Below are two patches that probably resolve
the issue of badly behaving drivers that cause enable imbalances.

> =

> As I said in the other mail.  We can do without these 3 new wrappers.
> We _could_ just write a driver which only calls clk_enable() _after_
> it calls clk_disable(), a kind of intentional unbalance and it would
> do that same thing.

This naive approach will not work with per-user imbalance tracking.

> However, what we're trying to do here is provide
> a proper API, so we can see at first glance what the 'knowledgeable'
> driver is trying to do and not have someone attempt to submit a 'fix'
> which calls clk_enable() or something.

We'll need some type of api for sure for the handoff.

Regards,
Mike



From=203599ed206da9ce770bfafcfd95cbb9a03ac44473 Mon Sep 17 00:00:00 2001
From: Michael Turquette <mturquette@baylibre.com>
Date: Wed, 29 Jul 2015 18:22:45 -0700
Subject: [PATCH 1/2] clk: per-user clk prepare & enable ref counts

This patch adds prepare and enable reference counts for the per-user
handles that clock consumers have for a clock node. This patch warns if
an imbalance occurs while trying to disable or unprepare a clock and
aborts, leaving the hardware unaffected.

Signed-off-by: Michael Turquette <mturquette@baylibre.com>
---
 drivers/clk/clk.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 898052e..72feee9 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -84,6 +84,8 @@ struct clk {
 	unsigned long min_rate;
 	unsigned long max_rate;
 	struct hlist_node clks_node;
+	unsigned int enable_count;
+	unsigned int prepare_count;
 };
 =

 /***           locking             ***/
@@ -600,6 +602,9 @@ void clk_unprepare(struct clk *clk)
 		return;
 =

 	clk_prepare_lock();
+	if (WARN_ON(clk->prepare_count =3D=3D 0))
+		return;
+	clk->prepare_count--;
 	clk_core_unprepare(clk->core);
 	clk_prepare_unlock();
 }
@@ -657,6 +662,7 @@ int clk_prepare(struct clk *clk)
 		return 0;
 =

 	clk_prepare_lock();
+	clk->prepare_count++;
 	ret =3D clk_core_prepare(clk->core);
 	clk_prepare_unlock();
 =

@@ -707,6 +713,9 @@ void clk_disable(struct clk *clk)
 		return;
 =

 	flags =3D clk_enable_lock();
+	if (WARN_ON(clk->enable_count =3D=3D 0))
+		return;
+	clk->enable_count--;
 	clk_core_disable(clk->core);
 	clk_enable_unlock(flags);
 }
@@ -769,6 +778,7 @@ int clk_enable(struct clk *clk)
 		return 0;
 =

 	flags =3D clk_enable_lock();
+	clk->enable_count++;
 	ret =3D clk_core_enable(clk->core);
 	clk_enable_unlock(flags);
 =

-- =

1.9.1

From=20ace76f6ed634a69c499f8440a98d4b5a54d78368 Mon Sep 17 00:00:00 2001
From: Michael Turquette <mturquette@baylibre.com>
Date: Thu, 30 Jul 2015 12:52:26 -0700
Subject: [PATCH 2/2] clk: clk_put WARNs if user has not disabled clk

From=20the clk_put kerneldoc in include/linux/clk.h:

"""
Note: drivers must ensure that all clk_enable calls made on this clock
source are balanced by clk_disable calls prior to calling this function.
"""

The common clock framework implementation of the clk.h api has per-user
reference counts for calls to clk_prepare and clk_disable. As such it
can enforce the requirement to properly call clk_disable and
clk_unprepare before calling clk_put.

Because this requirement is probably violated in many places, this patch
starts with a simple warning. Once offending code has been fixed this
check could additionally release the reference counts automatically.

Signed-off-by: Michael Turquette <mturquette@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 72feee9..6ec0f77 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -2764,6 +2764,14 @@ void __clk_put(struct clk *clk)
 	    clk->max_rate < clk->core->req_rate)
 		clk_core_set_rate_nolock(clk->core, clk->core->req_rate);
 =

+	/*
+	 * before calling clk_put, all calls to clk_prepare and clk_enable from
+	 * a given user must be balanced with calls to clk_disable and
+	 * clk_unprepare by that same user
+	 */
+	WARN_ON(clk->prepare_count);
+	WARN_ON(clk->enable_count);
+
 	owner =3D clk->core->owner;
 	kref_put(&clk->core->ref, __clk_release);
 =

-- =

1.9.1

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

* [PATCH v7 3/5] clk: Supply the critical clock {init, enable, disable} framework
@ 2015-07-30 23:35         ` Michael Turquette
  0 siblings, 0 replies; 93+ messages in thread
From: Michael Turquette @ 2015-07-30 23:35 UTC (permalink / raw)
  To: linux-arm-kernel

Quoting Lee Jones (2015-07-30 04:17:47)
> On Wed, 29 Jul 2015, Michael Turquette wrote:
> 
> > Hi Lee,
> > 
> > + linux-clk ml
> > 
> > Quoting Lee Jones (2015-07-22 06:04:13)
> > > These new API calls will firstly provide a mechanisms to tag a clock as
> > > critical and secondly allow any knowledgeable driver to (un)gate clocks,
> > > even if they are marked as critical.
> > > 
> > > Suggested-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> > > Signed-off-by: Lee Jones <lee.jones@linaro.org>
> > > ---
> > >  drivers/clk/clk.c            | 45 ++++++++++++++++++++++++++++++++++++++++++++
> > >  include/linux/clk-provider.h |  2 ++
> > >  include/linux/clk.h          | 30 +++++++++++++++++++++++++++++
> > >  3 files changed, 77 insertions(+)
> > > 
> > > diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> > > index 61c3fc5..486b1da 100644
> > > --- a/drivers/clk/clk.c
> > > +++ b/drivers/clk/clk.c
> > > @@ -46,6 +46,21 @@ static struct clk_core *clk_core_lookup(const char *name);
> > >  
> > >  /***    private data structures    ***/
> > >  
> > > +/**
> > > + * struct critical -   Provides 'play' over critical clocks.  A clock can be
> > > + *                     marked as critical, meaning that it should not be
> > > + *                     disabled.  However, if a driver which is aware of the
> > > + *                     critical behaviour wants to control it, it can do so
> > > + *                     using clk_enable_critical() and clk_disable_critical().
> > > + *
> > > + * @enabled    Is clock critical?  Once set, doesn't change
> > > + * @leave_on   Self explanatory.  Can be disabled by knowledgeable drivers
> > 
> > Not self explanatory. I need this explained to me. What does leave_on
> > do? Better yet, what would happen if leave_on did not exist?
> > 
> > > + */
> > > +struct critical {
> > > +       bool enabled;
> > > +       bool leave_on;
> > > +};
> > > +
> > >  struct clk_core {
> > >         const char              *name;
> > >         const struct clk_ops    *ops;
> > > @@ -75,6 +90,7 @@ struct clk_core {
> > >         struct dentry           *dentry;
> > >  #endif
> > >         struct kref             ref;
> > > +       struct critical         critical;
> > >  };
> > >  
> > >  struct clk {
> > > @@ -995,6 +1011,10 @@ static void clk_core_disable(struct clk_core *clk)
> > >         if (WARN_ON(clk->enable_count == 0))
> > >                 return;
> > >  
> > > +       /* Refuse to turn off a critical clock */
> > > +       if (clk->enable_count == 1 && clk->critical.leave_on)
> > > +               return;
> > 
> > How do we get to this point? clk_enable_critical actually calls
> > clk_enable, thus incrementing the enable_count. The only time that we
> > could hit the above case is if,
> > 
> > a) there is an imbalance in clk_enable and clk_disable calls. If this is
> > the case then the drivers need to be fixed. Or better yet some
> > infrastructure to catch that, now that we have per-user struct clk
> > cookies.
> > 
> > b) a driver knowingly calls clk_enable_critical(foo) and then regular,
> > old clk_disable(foo). But why would a driver do that?
> > 
> > It might be that I am missing the point here, so please feel free to
> > clue me in.
> 
> This check behaves in a very similar to the WARN() above.  It's more
> of a fail-safe.  If all drivers are behaving properly, then it
> shouldn't ever be true.  If they're not, it prevents an incorrectly
> written driver from irrecoverably crippling the system.

Then this check should be replaced with a generic approach that refuses
to honor imbalances anyways. Below are two patches that probably resolve
the issue of badly behaving drivers that cause enable imbalances.

> 
> As I said in the other mail.  We can do without these 3 new wrappers.
> We _could_ just write a driver which only calls clk_enable() _after_
> it calls clk_disable(), a kind of intentional unbalance and it would
> do that same thing.

This naive approach will not work with per-user imbalance tracking.

> However, what we're trying to do here is provide
> a proper API, so we can see at first glance what the 'knowledgeable'
> driver is trying to do and not have someone attempt to submit a 'fix'
> which calls clk_enable() or something.

We'll need some type of api for sure for the handoff.

Regards,
Mike



>From 3599ed206da9ce770bfafcfd95cbb9a03ac44473 Mon Sep 17 00:00:00 2001
From: Michael Turquette <mturquette@baylibre.com>
Date: Wed, 29 Jul 2015 18:22:45 -0700
Subject: [PATCH 1/2] clk: per-user clk prepare & enable ref counts

This patch adds prepare and enable reference counts for the per-user
handles that clock consumers have for a clock node. This patch warns if
an imbalance occurs while trying to disable or unprepare a clock and
aborts, leaving the hardware unaffected.

Signed-off-by: Michael Turquette <mturquette@baylibre.com>
---
 drivers/clk/clk.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 898052e..72feee9 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -84,6 +84,8 @@ struct clk {
 	unsigned long min_rate;
 	unsigned long max_rate;
 	struct hlist_node clks_node;
+	unsigned int enable_count;
+	unsigned int prepare_count;
 };
 
 /***           locking             ***/
@@ -600,6 +602,9 @@ void clk_unprepare(struct clk *clk)
 		return;
 
 	clk_prepare_lock();
+	if (WARN_ON(clk->prepare_count == 0))
+		return;
+	clk->prepare_count--;
 	clk_core_unprepare(clk->core);
 	clk_prepare_unlock();
 }
@@ -657,6 +662,7 @@ int clk_prepare(struct clk *clk)
 		return 0;
 
 	clk_prepare_lock();
+	clk->prepare_count++;
 	ret = clk_core_prepare(clk->core);
 	clk_prepare_unlock();
 
@@ -707,6 +713,9 @@ void clk_disable(struct clk *clk)
 		return;
 
 	flags = clk_enable_lock();
+	if (WARN_ON(clk->enable_count == 0))
+		return;
+	clk->enable_count--;
 	clk_core_disable(clk->core);
 	clk_enable_unlock(flags);
 }
@@ -769,6 +778,7 @@ int clk_enable(struct clk *clk)
 		return 0;
 
 	flags = clk_enable_lock();
+	clk->enable_count++;
 	ret = clk_core_enable(clk->core);
 	clk_enable_unlock(flags);
 
-- 
1.9.1

>From ace76f6ed634a69c499f8440a98d4b5a54d78368 Mon Sep 17 00:00:00 2001
From: Michael Turquette <mturquette@baylibre.com>
Date: Thu, 30 Jul 2015 12:52:26 -0700
Subject: [PATCH 2/2] clk: clk_put WARNs if user has not disabled clk

>From the clk_put kerneldoc in include/linux/clk.h:

"""
Note: drivers must ensure that all clk_enable calls made on this clock
source are balanced by clk_disable calls prior to calling this function.
"""

The common clock framework implementation of the clk.h api has per-user
reference counts for calls to clk_prepare and clk_disable. As such it
can enforce the requirement to properly call clk_disable and
clk_unprepare before calling clk_put.

Because this requirement is probably violated in many places, this patch
starts with a simple warning. Once offending code has been fixed this
check could additionally release the reference counts automatically.

Signed-off-by: Michael Turquette <mturquette@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 72feee9..6ec0f77 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -2764,6 +2764,14 @@ void __clk_put(struct clk *clk)
 	    clk->max_rate < clk->core->req_rate)
 		clk_core_set_rate_nolock(clk->core, clk->core->req_rate);
 
+	/*
+	 * before calling clk_put, all calls to clk_prepare and clk_enable from
+	 * a given user must be balanced with calls to clk_disable and
+	 * clk_unprepare by that same user
+	 */
+	WARN_ON(clk->prepare_count);
+	WARN_ON(clk->enable_count);
+
 	owner = clk->core->owner;
 	kref_put(&clk->core->ref, __clk_release);
 
-- 
1.9.1

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

* Re: [PATCH v7 3/5] clk: Supply the critical clock {init, enable, disable} framework
  2015-07-28 13:00           ` Lee Jones
  (?)
@ 2015-07-31  7:03             ` Maxime Ripard
  -1 siblings, 0 replies; 93+ messages in thread
From: Maxime Ripard @ 2015-07-31  7:03 UTC (permalink / raw)
  To: Lee Jones
  Cc: linux-arm-kernel, linux-kernel, kernel, mturquette, sboyd,
	devicetree, geert, s.hauer

[-- Attachment #1: Type: text/plain, Size: 5359 bytes --]

On Tue, Jul 28, 2015 at 02:00:55PM +0100, Lee Jones wrote:
> > > I don't think we can use reference counting, because we'd need as
> > > many critical clock owners as there are critical clocks.
> > 
> > Which we can have if we replace the call to clk_prepare_enable you add
> > in your fourth patch in __set_critical_clocks.
> 
> What should it be replaced with?

clk->critical_count++
clk_prepare_enable

?

> 
> > > Cast your mind back to the reasons for this critical clock API.  One
> > > of the most important intentions of this API is the requirement
> > > mitigation for each of the critical clocks to have an owner
> > > (driver).
> > > 
> > > With regards to your second point, that's what 'critical.enabled'
> > > is for.  Take a look at clk_enable_critical().
> > 
> > I don't think this addresses the issue, if you just throw more
> > customers at it, the issue remain with your implementation.
> > 
> > If you have three customers that used the critical API, and if on of
> > these calls clk_disable_critical, you're losing leave_on.
> 
> That's the idea.  See my point above, the one you replied "Indeed"
> to.  So when a driver uses clk_disable_critical() it's saying, "I know
> why this clock is a critical clock, and I know that nothing terrible
> will happen if I disable it, as I have that covered".

We do agree on the semantic of clk_disable_critical :)

> So then if it's not the last user to call clk_disable(), the last
> one out the door will be allowed to finally gate the clock,
> regardless whether it's critical aware or not.

That's right, but what I mean would be a case where you have two users
that are aware that it is a critical clock (A and B), and one which is
not (C).

If I understood correctly your code, if A calls clk_disable_critical,
leave_on is set to false. That means that now, if C calls clk_disable
on that clock, it will actually be shut down, while B still considers
it a critical clock.

> Then, when we come to enable the clock again, the critical aware user
> then re-marks the clock as leave_on, so not critical un-aware user can
> take the final reference and disable the clock.
> 
> > Which means that if there's one of the two users left that calls
> > clk_disable on it, the clock will actually be disabled, which is
> > clearly not what we want to do, as we have still a user that want the
> > clock to be enabled.
> 
> That's not what happens (at least it shouldn't if I've coded it up
> right).  The API _still_ requires all of the users to give-up their
> reference.

Ah, right. So I guess it all boils down to the discussion you're
having with Mike regarding whether critical users should expect to
already have a reference taken or calling clk_prepare / clk_enable
themselves.

> 
> > It would be much more robust to have another count for the critical
> > stuff, initialised to one by the __set_critical_clocks function.
> 
> If I understand you correctly, we already have a count.  We use the
> original reference count.  No need for one of our own.
> 
> Using your RAM Clock (Clock 4) as an example
> --------------------------------------------
> 
> Early start-up:
>   Clock 4 is marked as critical and a reference is taken (ref == 1)
> 
> Driver probe:
>   SPI enables Clock 4 (ref == 2)
>   I2C enables Clock 4 (ref == 3)
> 
> Suspend (without RAM driver's permission):
>   SPI disables Clock 4 (ref == 2)
>   I2C disables Clock 4 (ref == 1)
>   /*
>    * Clock won't be gated because:
>    *   .leave_on is True - can't dec final reference
>    */
> 
> Suspend (with RAM driver's permission):
>   /* Order is unimportant */
>   SPI disables Clock 4 (ref == 2)
>   RAM disables Clock 4 (ref == 1) /* Won't turn off here (ref > 0)
>   I2C disables Clock 4 (ref == 0) /* (.leave_on == False) last ref can be taken */
>   /*
>    * Clock will be gated because:
>    *   .leave_on is False, so (ref == 0)
>    */
> 
> Resume:
>   /* Order is unimportant */
>   SPI enables Clock 4 (ref == 1)
>   RAM enables Clock 4 and re-enables .leave_on (ref == 2)
>   I2C enables Clock 4 (ref == 3)
> 
> Hopefully that clears things up.

It does indeed. I simply forgot to take into account the fact that it
would still need the reference to be set to 0. My bad.

Still, If we take the same kind of scenario:

Early start-up:
  Clock 4 is marked as critical and a reference is taken (ref == 1, leave_on = true)

Driver probe:
  SPI enables Clock 4 (ref == 2)
  I2C enables Clock 4 (ref == 3)
  RAM enables Clock 4 (ref == 4, leave_on = true )
  CPUIdle enables Clock 4 (ref == 5, leave_on = true )

Suspend (with CPUIdle and RAM permissions):
  /* Order is unimportant */
  SPI disables Clock 4 (ref == 4)
  CPUIdle disables Clock 4 (ref == 3, leave_on = false ) 
  RAM disables Clock 4 (ref == 2, leave_on = false )
  I2C disables Clock 4 (ref == 1)

And even though the clock will still be running when CPUIdle calls
clk_disable_critical because of the enable_count, the status of
leave_on is off, as the RAM driver still considers it to be left on
(ie, hasn't called clk_disable_critical yet).

Or at least, that's what I understood of it.

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

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

* Re: [PATCH v7 3/5] clk: Supply the critical clock {init, enable, disable} framework
@ 2015-07-31  7:03             ` Maxime Ripard
  0 siblings, 0 replies; 93+ messages in thread
From: Maxime Ripard @ 2015-07-31  7:03 UTC (permalink / raw)
  To: Lee Jones
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	kernel-F5mvAk5X5gdBDgjK7y7TUQ, mturquette-QSEj5FYQhm4dnm+yROfE0A,
	sboyd-sgV2jX0FEOL9JmXXK+q4OQ, devicetree-u79uwXL29TY76Z2rM5mHXA,
	geert-Td1EMuHUCqxL1ZNQvxDV9g, s.hauer-bIcnvbaLZ9MEGnE8C9+IrQ

[-- Attachment #1: Type: text/plain, Size: 5359 bytes --]

On Tue, Jul 28, 2015 at 02:00:55PM +0100, Lee Jones wrote:
> > > I don't think we can use reference counting, because we'd need as
> > > many critical clock owners as there are critical clocks.
> > 
> > Which we can have if we replace the call to clk_prepare_enable you add
> > in your fourth patch in __set_critical_clocks.
> 
> What should it be replaced with?

clk->critical_count++
clk_prepare_enable

?

> 
> > > Cast your mind back to the reasons for this critical clock API.  One
> > > of the most important intentions of this API is the requirement
> > > mitigation for each of the critical clocks to have an owner
> > > (driver).
> > > 
> > > With regards to your second point, that's what 'critical.enabled'
> > > is for.  Take a look at clk_enable_critical().
> > 
> > I don't think this addresses the issue, if you just throw more
> > customers at it, the issue remain with your implementation.
> > 
> > If you have three customers that used the critical API, and if on of
> > these calls clk_disable_critical, you're losing leave_on.
> 
> That's the idea.  See my point above, the one you replied "Indeed"
> to.  So when a driver uses clk_disable_critical() it's saying, "I know
> why this clock is a critical clock, and I know that nothing terrible
> will happen if I disable it, as I have that covered".

We do agree on the semantic of clk_disable_critical :)

> So then if it's not the last user to call clk_disable(), the last
> one out the door will be allowed to finally gate the clock,
> regardless whether it's critical aware or not.

That's right, but what I mean would be a case where you have two users
that are aware that it is a critical clock (A and B), and one which is
not (C).

If I understood correctly your code, if A calls clk_disable_critical,
leave_on is set to false. That means that now, if C calls clk_disable
on that clock, it will actually be shut down, while B still considers
it a critical clock.

> Then, when we come to enable the clock again, the critical aware user
> then re-marks the clock as leave_on, so not critical un-aware user can
> take the final reference and disable the clock.
> 
> > Which means that if there's one of the two users left that calls
> > clk_disable on it, the clock will actually be disabled, which is
> > clearly not what we want to do, as we have still a user that want the
> > clock to be enabled.
> 
> That's not what happens (at least it shouldn't if I've coded it up
> right).  The API _still_ requires all of the users to give-up their
> reference.

Ah, right. So I guess it all boils down to the discussion you're
having with Mike regarding whether critical users should expect to
already have a reference taken or calling clk_prepare / clk_enable
themselves.

> 
> > It would be much more robust to have another count for the critical
> > stuff, initialised to one by the __set_critical_clocks function.
> 
> If I understand you correctly, we already have a count.  We use the
> original reference count.  No need for one of our own.
> 
> Using your RAM Clock (Clock 4) as an example
> --------------------------------------------
> 
> Early start-up:
>   Clock 4 is marked as critical and a reference is taken (ref == 1)
> 
> Driver probe:
>   SPI enables Clock 4 (ref == 2)
>   I2C enables Clock 4 (ref == 3)
> 
> Suspend (without RAM driver's permission):
>   SPI disables Clock 4 (ref == 2)
>   I2C disables Clock 4 (ref == 1)
>   /*
>    * Clock won't be gated because:
>    *   .leave_on is True - can't dec final reference
>    */
> 
> Suspend (with RAM driver's permission):
>   /* Order is unimportant */
>   SPI disables Clock 4 (ref == 2)
>   RAM disables Clock 4 (ref == 1) /* Won't turn off here (ref > 0)
>   I2C disables Clock 4 (ref == 0) /* (.leave_on == False) last ref can be taken */
>   /*
>    * Clock will be gated because:
>    *   .leave_on is False, so (ref == 0)
>    */
> 
> Resume:
>   /* Order is unimportant */
>   SPI enables Clock 4 (ref == 1)
>   RAM enables Clock 4 and re-enables .leave_on (ref == 2)
>   I2C enables Clock 4 (ref == 3)
> 
> Hopefully that clears things up.

It does indeed. I simply forgot to take into account the fact that it
would still need the reference to be set to 0. My bad.

Still, If we take the same kind of scenario:

Early start-up:
  Clock 4 is marked as critical and a reference is taken (ref == 1, leave_on = true)

Driver probe:
  SPI enables Clock 4 (ref == 2)
  I2C enables Clock 4 (ref == 3)
  RAM enables Clock 4 (ref == 4, leave_on = true )
  CPUIdle enables Clock 4 (ref == 5, leave_on = true )

Suspend (with CPUIdle and RAM permissions):
  /* Order is unimportant */
  SPI disables Clock 4 (ref == 4)
  CPUIdle disables Clock 4 (ref == 3, leave_on = false ) 
  RAM disables Clock 4 (ref == 2, leave_on = false )
  I2C disables Clock 4 (ref == 1)

And even though the clock will still be running when CPUIdle calls
clk_disable_critical because of the enable_count, the status of
leave_on is off, as the RAM driver still considers it to be left on
(ie, hasn't called clk_disable_critical yet).

Or at least, that's what I understood of it.

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

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

* [PATCH v7 3/5] clk: Supply the critical clock {init, enable, disable} framework
@ 2015-07-31  7:03             ` Maxime Ripard
  0 siblings, 0 replies; 93+ messages in thread
From: Maxime Ripard @ 2015-07-31  7:03 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Jul 28, 2015 at 02:00:55PM +0100, Lee Jones wrote:
> > > I don't think we can use reference counting, because we'd need as
> > > many critical clock owners as there are critical clocks.
> > 
> > Which we can have if we replace the call to clk_prepare_enable you add
> > in your fourth patch in __set_critical_clocks.
> 
> What should it be replaced with?

clk->critical_count++
clk_prepare_enable

?

> 
> > > Cast your mind back to the reasons for this critical clock API.  One
> > > of the most important intentions of this API is the requirement
> > > mitigation for each of the critical clocks to have an owner
> > > (driver).
> > > 
> > > With regards to your second point, that's what 'critical.enabled'
> > > is for.  Take a look at clk_enable_critical().
> > 
> > I don't think this addresses the issue, if you just throw more
> > customers at it, the issue remain with your implementation.
> > 
> > If you have three customers that used the critical API, and if on of
> > these calls clk_disable_critical, you're losing leave_on.
> 
> That's the idea.  See my point above, the one you replied "Indeed"
> to.  So when a driver uses clk_disable_critical() it's saying, "I know
> why this clock is a critical clock, and I know that nothing terrible
> will happen if I disable it, as I have that covered".

We do agree on the semantic of clk_disable_critical :)

> So then if it's not the last user to call clk_disable(), the last
> one out the door will be allowed to finally gate the clock,
> regardless whether it's critical aware or not.

That's right, but what I mean would be a case where you have two users
that are aware that it is a critical clock (A and B), and one which is
not (C).

If I understood correctly your code, if A calls clk_disable_critical,
leave_on is set to false. That means that now, if C calls clk_disable
on that clock, it will actually be shut down, while B still considers
it a critical clock.

> Then, when we come to enable the clock again, the critical aware user
> then re-marks the clock as leave_on, so not critical un-aware user can
> take the final reference and disable the clock.
> 
> > Which means that if there's one of the two users left that calls
> > clk_disable on it, the clock will actually be disabled, which is
> > clearly not what we want to do, as we have still a user that want the
> > clock to be enabled.
> 
> That's not what happens (at least it shouldn't if I've coded it up
> right).  The API _still_ requires all of the users to give-up their
> reference.

Ah, right. So I guess it all boils down to the discussion you're
having with Mike regarding whether critical users should expect to
already have a reference taken or calling clk_prepare / clk_enable
themselves.

> 
> > It would be much more robust to have another count for the critical
> > stuff, initialised to one by the __set_critical_clocks function.
> 
> If I understand you correctly, we already have a count.  We use the
> original reference count.  No need for one of our own.
> 
> Using your RAM Clock (Clock 4) as an example
> --------------------------------------------
> 
> Early start-up:
>   Clock 4 is marked as critical and a reference is taken (ref == 1)
> 
> Driver probe:
>   SPI enables Clock 4 (ref == 2)
>   I2C enables Clock 4 (ref == 3)
> 
> Suspend (without RAM driver's permission):
>   SPI disables Clock 4 (ref == 2)
>   I2C disables Clock 4 (ref == 1)
>   /*
>    * Clock won't be gated because:
>    *   .leave_on is True - can't dec final reference
>    */
> 
> Suspend (with RAM driver's permission):
>   /* Order is unimportant */
>   SPI disables Clock 4 (ref == 2)
>   RAM disables Clock 4 (ref == 1) /* Won't turn off here (ref > 0)
>   I2C disables Clock 4 (ref == 0) /* (.leave_on == False) last ref can be taken */
>   /*
>    * Clock will be gated because:
>    *   .leave_on is False, so (ref == 0)
>    */
> 
> Resume:
>   /* Order is unimportant */
>   SPI enables Clock 4 (ref == 1)
>   RAM enables Clock 4 and re-enables .leave_on (ref == 2)
>   I2C enables Clock 4 (ref == 3)
> 
> Hopefully that clears things up.

It does indeed. I simply forgot to take into account the fact that it
would still need the reference to be set to 0. My bad.

Still, If we take the same kind of scenario:

Early start-up:
  Clock 4 is marked as critical and a reference is taken (ref == 1, leave_on = true)

Driver probe:
  SPI enables Clock 4 (ref == 2)
  I2C enables Clock 4 (ref == 3)
  RAM enables Clock 4 (ref == 4, leave_on = true )
  CPUIdle enables Clock 4 (ref == 5, leave_on = true )

Suspend (with CPUIdle and RAM permissions):
  /* Order is unimportant */
  SPI disables Clock 4 (ref == 4)
  CPUIdle disables Clock 4 (ref == 3, leave_on = false ) 
  RAM disables Clock 4 (ref == 2, leave_on = false )
  I2C disables Clock 4 (ref == 1)

And even though the clock will still be running when CPUIdle calls
clk_disable_critical because of the enable_count, the status of
leave_on is off, as the RAM driver still considers it to be left on
(ie, hasn't called clk_disable_critical yet).

Or at least, that's what I understood of it.

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20150731/780c6dca/attachment.sig>

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

* Re: [PATCH v7 3/5] clk: Supply the critical clock {init, enable, disable} framework
  2015-07-30 22:47                 ` Michael Turquette
  (?)
@ 2015-07-31  7:30                   ` Maxime Ripard
  -1 siblings, 0 replies; 93+ messages in thread
From: Maxime Ripard @ 2015-07-31  7:30 UTC (permalink / raw)
  To: Michael Turquette
  Cc: Lee Jones, linux-arm-kernel, linux-kernel, kernel, sboyd,
	devicetree, geert, s.hauer

[-- Attachment #1: Type: text/plain, Size: 3239 bytes --]

On Thu, Jul 30, 2015 at 03:47:20PM -0700, Michael Turquette wrote:
> > > >    */
> > > > 
> > > > Resume:
> > > >   /* Order is unimportant */
> > > >   SPI enables Clock 4 (ref == 1)
> > > >   RAM enables Clock 4 and re-enables .leave_on (ref == 2)
> > > >   I2C enables Clock 4 (ref == 3)
> > > 
> > > Same again. As soon as RAM calls clk_enable_critical the ref count goes
> > > up. .leave_on does nothing as far as I can tell. The all works because
> > > of the reference counting, which already exists before this patch
> > > series.
> > 
> > So fundamentally you're right in what you say.  All you really need to
> > disable a critical clock is write a knowledgeable driver, which is
> > intentionally unbalanced i.e. just calls clk_disable().  All this
> 
> OK, the line above is helpful. What you really want is a formalized
> hand-off mechanism, whereby the clock is enabled at registration-time
> and it cannot be turned off until the right driver claims it and decides
> turning it off is OK (with a priori knowledge that the clock is already
> enabled).

There's two things that should be covered, and are related, yet can be
done in two steps:

  - Have a way to, no matter what (which configuration we have, if we
    have multiple users or not that might reparent or disable their
    clocks, etc.), make sure that a clock will always be running by
    default. This is done through the call in clk-conf, and we
    identify such clocks using critical-clocks in the DT.

  - Now, even though that information is true, some driver who are
    aware of that fact might want to disable those critical
    clocks. This is what the clk_disable_critical and
    clk_enable_critical functions are here for.

> Note that I don't think this implementation can really work in the near
> future. Today we do not catch unbalanced calls to clk_enable and
> clk_disable, but I have a patch that catches this and WARNs loudly in my
> private tree. More on that in the next stanza.
> 
> What I don't understand is if there is ever a case for a clock consumer
> driver to ever call clk_enable_critical... I do not think there is. What
> you're trying to protect against is having the clock disabled BEFORE
> that "knowledgeable driver" has a chance to enable it.

It's really about what we want the API to look like in the second
case.

Do we want such drivers to still call clk_prepare_enable? Some other
function? Should they assume that the clock has already been enabled,
or do we want a handover, or a force disable, or whatever.

I guess we should discuss those questions, before starting to think
about how to implement it.

IMHO, I think that the existing way of doing should be used, or at
least with the same mindset to avoid confusion, errors, and
misinformed reviews.

So I'd expect the drivers to do something like:

probe:
  clk_get
  clk_critical_enable

remove / probe error path:
  clk_critical_disable
  clk_put

and use the clk_critical_enable and clk_critical_disable whenever
needed, and thing would just work as intended.

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

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

* Re: [PATCH v7 3/5] clk: Supply the critical clock {init, enable, disable} framework
@ 2015-07-31  7:30                   ` Maxime Ripard
  0 siblings, 0 replies; 93+ messages in thread
From: Maxime Ripard @ 2015-07-31  7:30 UTC (permalink / raw)
  To: Michael Turquette
  Cc: Lee Jones, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	kernel-F5mvAk5X5gdBDgjK7y7TUQ, sboyd-sgV2jX0FEOL9JmXXK+q4OQ,
	devicetree-u79uwXL29TY76Z2rM5mHXA, geert-Td1EMuHUCqxL1ZNQvxDV9g,
	s.hauer-bIcnvbaLZ9MEGnE8C9+IrQ

[-- Attachment #1: Type: text/plain, Size: 3239 bytes --]

On Thu, Jul 30, 2015 at 03:47:20PM -0700, Michael Turquette wrote:
> > > >    */
> > > > 
> > > > Resume:
> > > >   /* Order is unimportant */
> > > >   SPI enables Clock 4 (ref == 1)
> > > >   RAM enables Clock 4 and re-enables .leave_on (ref == 2)
> > > >   I2C enables Clock 4 (ref == 3)
> > > 
> > > Same again. As soon as RAM calls clk_enable_critical the ref count goes
> > > up. .leave_on does nothing as far as I can tell. The all works because
> > > of the reference counting, which already exists before this patch
> > > series.
> > 
> > So fundamentally you're right in what you say.  All you really need to
> > disable a critical clock is write a knowledgeable driver, which is
> > intentionally unbalanced i.e. just calls clk_disable().  All this
> 
> OK, the line above is helpful. What you really want is a formalized
> hand-off mechanism, whereby the clock is enabled at registration-time
> and it cannot be turned off until the right driver claims it and decides
> turning it off is OK (with a priori knowledge that the clock is already
> enabled).

There's two things that should be covered, and are related, yet can be
done in two steps:

  - Have a way to, no matter what (which configuration we have, if we
    have multiple users or not that might reparent or disable their
    clocks, etc.), make sure that a clock will always be running by
    default. This is done through the call in clk-conf, and we
    identify such clocks using critical-clocks in the DT.

  - Now, even though that information is true, some driver who are
    aware of that fact might want to disable those critical
    clocks. This is what the clk_disable_critical and
    clk_enable_critical functions are here for.

> Note that I don't think this implementation can really work in the near
> future. Today we do not catch unbalanced calls to clk_enable and
> clk_disable, but I have a patch that catches this and WARNs loudly in my
> private tree. More on that in the next stanza.
> 
> What I don't understand is if there is ever a case for a clock consumer
> driver to ever call clk_enable_critical... I do not think there is. What
> you're trying to protect against is having the clock disabled BEFORE
> that "knowledgeable driver" has a chance to enable it.

It's really about what we want the API to look like in the second
case.

Do we want such drivers to still call clk_prepare_enable? Some other
function? Should they assume that the clock has already been enabled,
or do we want a handover, or a force disable, or whatever.

I guess we should discuss those questions, before starting to think
about how to implement it.

IMHO, I think that the existing way of doing should be used, or at
least with the same mindset to avoid confusion, errors, and
misinformed reviews.

So I'd expect the drivers to do something like:

probe:
  clk_get
  clk_critical_enable

remove / probe error path:
  clk_critical_disable
  clk_put

and use the clk_critical_enable and clk_critical_disable whenever
needed, and thing would just work as intended.

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

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

* [PATCH v7 3/5] clk: Supply the critical clock {init, enable, disable} framework
@ 2015-07-31  7:30                   ` Maxime Ripard
  0 siblings, 0 replies; 93+ messages in thread
From: Maxime Ripard @ 2015-07-31  7:30 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Jul 30, 2015 at 03:47:20PM -0700, Michael Turquette wrote:
> > > >    */
> > > > 
> > > > Resume:
> > > >   /* Order is unimportant */
> > > >   SPI enables Clock 4 (ref == 1)
> > > >   RAM enables Clock 4 and re-enables .leave_on (ref == 2)
> > > >   I2C enables Clock 4 (ref == 3)
> > > 
> > > Same again. As soon as RAM calls clk_enable_critical the ref count goes
> > > up. .leave_on does nothing as far as I can tell. The all works because
> > > of the reference counting, which already exists before this patch
> > > series.
> > 
> > So fundamentally you're right in what you say.  All you really need to
> > disable a critical clock is write a knowledgeable driver, which is
> > intentionally unbalanced i.e. just calls clk_disable().  All this
> 
> OK, the line above is helpful. What you really want is a formalized
> hand-off mechanism, whereby the clock is enabled at registration-time
> and it cannot be turned off until the right driver claims it and decides
> turning it off is OK (with a priori knowledge that the clock is already
> enabled).

There's two things that should be covered, and are related, yet can be
done in two steps:

  - Have a way to, no matter what (which configuration we have, if we
    have multiple users or not that might reparent or disable their
    clocks, etc.), make sure that a clock will always be running by
    default. This is done through the call in clk-conf, and we
    identify such clocks using critical-clocks in the DT.

  - Now, even though that information is true, some driver who are
    aware of that fact might want to disable those critical
    clocks. This is what the clk_disable_critical and
    clk_enable_critical functions are here for.

> Note that I don't think this implementation can really work in the near
> future. Today we do not catch unbalanced calls to clk_enable and
> clk_disable, but I have a patch that catches this and WARNs loudly in my
> private tree. More on that in the next stanza.
> 
> What I don't understand is if there is ever a case for a clock consumer
> driver to ever call clk_enable_critical... I do not think there is. What
> you're trying to protect against is having the clock disabled BEFORE
> that "knowledgeable driver" has a chance to enable it.

It's really about what we want the API to look like in the second
case.

Do we want such drivers to still call clk_prepare_enable? Some other
function? Should they assume that the clock has already been enabled,
or do we want a handover, or a force disable, or whatever.

I guess we should discuss those questions, before starting to think
about how to implement it.

IMHO, I think that the existing way of doing should be used, or at
least with the same mindset to avoid confusion, errors, and
misinformed reviews.

So I'd expect the drivers to do something like:

probe:
  clk_get
  clk_critical_enable

remove / probe error path:
  clk_critical_disable
  clk_put

and use the clk_critical_enable and clk_critical_disable whenever
needed, and thing would just work as intended.

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20150731/9e5c7098/attachment.sig>

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

* Re: [PATCH v7 3/5] clk: Supply the critical clock {init, enable, disable} framework
  2015-07-31  7:30                   ` Maxime Ripard
  (?)
@ 2015-07-31  8:32                     ` Lee Jones
  -1 siblings, 0 replies; 93+ messages in thread
From: Lee Jones @ 2015-07-31  8:32 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Michael Turquette, linux-arm-kernel, linux-kernel, kernel, sboyd,
	devicetree, geert, s.hauer

On Fri, 31 Jul 2015, Maxime Ripard wrote:

> On Thu, Jul 30, 2015 at 03:47:20PM -0700, Michael Turquette wrote:
> > > > >    */
> > > > > 
> > > > > Resume:
> > > > >   /* Order is unimportant */
> > > > >   SPI enables Clock 4 (ref == 1)
> > > > >   RAM enables Clock 4 and re-enables .leave_on (ref == 2)
> > > > >   I2C enables Clock 4 (ref == 3)
> > > > 
> > > > Same again. As soon as RAM calls clk_enable_critical the ref count goes
> > > > up. .leave_on does nothing as far as I can tell. The all works because
> > > > of the reference counting, which already exists before this patch
> > > > series.
> > > 
> > > So fundamentally you're right in what you say.  All you really need to
> > > disable a critical clock is write a knowledgeable driver, which is
> > > intentionally unbalanced i.e. just calls clk_disable().  All this
> > 
> > OK, the line above is helpful. What you really want is a formalized
> > hand-off mechanism, whereby the clock is enabled at registration-time
> > and it cannot be turned off until the right driver claims it and decides
> > turning it off is OK (with a priori knowledge that the clock is already
> > enabled).
> 
> There's two things that should be covered, and are related, yet can be
> done in two steps:
> 
>   - Have a way to, no matter what (which configuration we have, if we
>     have multiple users or not that might reparent or disable their
>     clocks, etc.), make sure that a clock will always be running by
>     default. This is done through the call in clk-conf, and we
>     identify such clocks using critical-clocks in the DT.
> 
>   - Now, even though that information is true, some driver who are
>     aware of that fact might want to disable those critical
>     clocks. This is what the clk_disable_critical and
>     clk_enable_critical functions are here for.

+1

> > Note that I don't think this implementation can really work in the near
> > future. Today we do not catch unbalanced calls to clk_enable and
> > clk_disable, but I have a patch that catches this and WARNs loudly in my
> > private tree. More on that in the next stanza.
> > 
> > What I don't understand is if there is ever a case for a clock consumer
> > driver to ever call clk_enable_critical... I do not think there is. What
> > you're trying to protect against is having the clock disabled BEFORE
> > that "knowledgeable driver" has a chance to enable it.

In my mind and in this implementation  clk_disable_critical() will be
used _first_ by the knowledgeable driver, then when the knowledgeable
driver has finished whatever it was doing (shutting down banks of RAM
etc...), it should then call clk_enable_critical() to reset the clock
state back to the way it found it i.e. enabled and marked as critical.

> It's really about what we want the API to look like in the second
> case.
> 
> Do we want such drivers to still call clk_prepare_enable? Some other
> function? Should they assume that the clock has already been enabled,
> or do we want a handover, or a force disable, or whatever.
> 
> I guess we should discuss those questions, before starting to think
> about how to implement it.
> 
> IMHO, I think that the existing way of doing should be used, or at
> least with the same mindset to avoid confusion, errors, and
> misinformed reviews.
> 
> So I'd expect the drivers to do something like:
> 
> probe:
>   clk_get
>   clk_critical_enable

Well becuase the clock has been marked as critical, a reference has
already been taken, so even if there are 0 users the clock now has 2
references attributed to it.

> remove / probe error path:
>   clk_critical_disable
>   clk_put

I think we should assume that the clock is already running in the
knowledgeable driver:

start-up:
  __set_critical_clocks()

probe:
  clk_get()

suspend (or whatever reason the driver wishes to disable the clk):
  clk_disable_critical()

resume (or whatever ...):
  clk_enable_critical()

remove:
  clk_put() /* Or just rely on devm_*() */ 

> and use the clk_critical_enable and clk_critical_disable whenever
> needed, and thing would just work as intended.

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

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

* Re: [PATCH v7 3/5] clk: Supply the critical clock {init, enable, disable} framework
@ 2015-07-31  8:32                     ` Lee Jones
  0 siblings, 0 replies; 93+ messages in thread
From: Lee Jones @ 2015-07-31  8:32 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Michael Turquette,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	kernel-F5mvAk5X5gdBDgjK7y7TUQ, sboyd-sgV2jX0FEOL9JmXXK+q4OQ,
	devicetree-u79uwXL29TY76Z2rM5mHXA, geert-Td1EMuHUCqxL1ZNQvxDV9g,
	s.hauer-bIcnvbaLZ9MEGnE8C9+IrQ

On Fri, 31 Jul 2015, Maxime Ripard wrote:

> On Thu, Jul 30, 2015 at 03:47:20PM -0700, Michael Turquette wrote:
> > > > >    */
> > > > > 
> > > > > Resume:
> > > > >   /* Order is unimportant */
> > > > >   SPI enables Clock 4 (ref == 1)
> > > > >   RAM enables Clock 4 and re-enables .leave_on (ref == 2)
> > > > >   I2C enables Clock 4 (ref == 3)
> > > > 
> > > > Same again. As soon as RAM calls clk_enable_critical the ref count goes
> > > > up. .leave_on does nothing as far as I can tell. The all works because
> > > > of the reference counting, which already exists before this patch
> > > > series.
> > > 
> > > So fundamentally you're right in what you say.  All you really need to
> > > disable a critical clock is write a knowledgeable driver, which is
> > > intentionally unbalanced i.e. just calls clk_disable().  All this
> > 
> > OK, the line above is helpful. What you really want is a formalized
> > hand-off mechanism, whereby the clock is enabled at registration-time
> > and it cannot be turned off until the right driver claims it and decides
> > turning it off is OK (with a priori knowledge that the clock is already
> > enabled).
> 
> There's two things that should be covered, and are related, yet can be
> done in two steps:
> 
>   - Have a way to, no matter what (which configuration we have, if we
>     have multiple users or not that might reparent or disable their
>     clocks, etc.), make sure that a clock will always be running by
>     default. This is done through the call in clk-conf, and we
>     identify such clocks using critical-clocks in the DT.
> 
>   - Now, even though that information is true, some driver who are
>     aware of that fact might want to disable those critical
>     clocks. This is what the clk_disable_critical and
>     clk_enable_critical functions are here for.

+1

> > Note that I don't think this implementation can really work in the near
> > future. Today we do not catch unbalanced calls to clk_enable and
> > clk_disable, but I have a patch that catches this and WARNs loudly in my
> > private tree. More on that in the next stanza.
> > 
> > What I don't understand is if there is ever a case for a clock consumer
> > driver to ever call clk_enable_critical... I do not think there is. What
> > you're trying to protect against is having the clock disabled BEFORE
> > that "knowledgeable driver" has a chance to enable it.

In my mind and in this implementation  clk_disable_critical() will be
used _first_ by the knowledgeable driver, then when the knowledgeable
driver has finished whatever it was doing (shutting down banks of RAM
etc...), it should then call clk_enable_critical() to reset the clock
state back to the way it found it i.e. enabled and marked as critical.

> It's really about what we want the API to look like in the second
> case.
> 
> Do we want such drivers to still call clk_prepare_enable? Some other
> function? Should they assume that the clock has already been enabled,
> or do we want a handover, or a force disable, or whatever.
> 
> I guess we should discuss those questions, before starting to think
> about how to implement it.
> 
> IMHO, I think that the existing way of doing should be used, or at
> least with the same mindset to avoid confusion, errors, and
> misinformed reviews.
> 
> So I'd expect the drivers to do something like:
> 
> probe:
>   clk_get
>   clk_critical_enable

Well becuase the clock has been marked as critical, a reference has
already been taken, so even if there are 0 users the clock now has 2
references attributed to it.

> remove / probe error path:
>   clk_critical_disable
>   clk_put

I think we should assume that the clock is already running in the
knowledgeable driver:

start-up:
  __set_critical_clocks()

probe:
  clk_get()

suspend (or whatever reason the driver wishes to disable the clk):
  clk_disable_critical()

resume (or whatever ...):
  clk_enable_critical()

remove:
  clk_put() /* Or just rely on devm_*() */ 

> and use the clk_critical_enable and clk_critical_disable whenever
> needed, and thing would just work as intended.

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH v7 3/5] clk: Supply the critical clock {init, enable, disable} framework
@ 2015-07-31  8:32                     ` Lee Jones
  0 siblings, 0 replies; 93+ messages in thread
From: Lee Jones @ 2015-07-31  8:32 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, 31 Jul 2015, Maxime Ripard wrote:

> On Thu, Jul 30, 2015 at 03:47:20PM -0700, Michael Turquette wrote:
> > > > >    */
> > > > > 
> > > > > Resume:
> > > > >   /* Order is unimportant */
> > > > >   SPI enables Clock 4 (ref == 1)
> > > > >   RAM enables Clock 4 and re-enables .leave_on (ref == 2)
> > > > >   I2C enables Clock 4 (ref == 3)
> > > > 
> > > > Same again. As soon as RAM calls clk_enable_critical the ref count goes
> > > > up. .leave_on does nothing as far as I can tell. The all works because
> > > > of the reference counting, which already exists before this patch
> > > > series.
> > > 
> > > So fundamentally you're right in what you say.  All you really need to
> > > disable a critical clock is write a knowledgeable driver, which is
> > > intentionally unbalanced i.e. just calls clk_disable().  All this
> > 
> > OK, the line above is helpful. What you really want is a formalized
> > hand-off mechanism, whereby the clock is enabled at registration-time
> > and it cannot be turned off until the right driver claims it and decides
> > turning it off is OK (with a priori knowledge that the clock is already
> > enabled).
> 
> There's two things that should be covered, and are related, yet can be
> done in two steps:
> 
>   - Have a way to, no matter what (which configuration we have, if we
>     have multiple users or not that might reparent or disable their
>     clocks, etc.), make sure that a clock will always be running by
>     default. This is done through the call in clk-conf, and we
>     identify such clocks using critical-clocks in the DT.
> 
>   - Now, even though that information is true, some driver who are
>     aware of that fact might want to disable those critical
>     clocks. This is what the clk_disable_critical and
>     clk_enable_critical functions are here for.

+1

> > Note that I don't think this implementation can really work in the near
> > future. Today we do not catch unbalanced calls to clk_enable and
> > clk_disable, but I have a patch that catches this and WARNs loudly in my
> > private tree. More on that in the next stanza.
> > 
> > What I don't understand is if there is ever a case for a clock consumer
> > driver to ever call clk_enable_critical... I do not think there is. What
> > you're trying to protect against is having the clock disabled BEFORE
> > that "knowledgeable driver" has a chance to enable it.

In my mind and in this implementation  clk_disable_critical() will be
used _first_ by the knowledgeable driver, then when the knowledgeable
driver has finished whatever it was doing (shutting down banks of RAM
etc...), it should then call clk_enable_critical() to reset the clock
state back to the way it found it i.e. enabled and marked as critical.

> It's really about what we want the API to look like in the second
> case.
> 
> Do we want such drivers to still call clk_prepare_enable? Some other
> function? Should they assume that the clock has already been enabled,
> or do we want a handover, or a force disable, or whatever.
> 
> I guess we should discuss those questions, before starting to think
> about how to implement it.
> 
> IMHO, I think that the existing way of doing should be used, or at
> least with the same mindset to avoid confusion, errors, and
> misinformed reviews.
> 
> So I'd expect the drivers to do something like:
> 
> probe:
>   clk_get
>   clk_critical_enable

Well becuase the clock has been marked as critical, a reference has
already been taken, so even if there are 0 users the clock now has 2
references attributed to it.

> remove / probe error path:
>   clk_critical_disable
>   clk_put

I think we should assume that the clock is already running in the
knowledgeable driver:

start-up:
  __set_critical_clocks()

probe:
  clk_get()

suspend (or whatever reason the driver wishes to disable the clk):
  clk_disable_critical()

resume (or whatever ...):
  clk_enable_critical()

remove:
  clk_put() /* Or just rely on devm_*() */ 

> and use the clk_critical_enable and clk_critical_disable whenever
> needed, and thing would just work as intended.

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org ? Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

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

* Re: [PATCH v7 3/5] clk: Supply the critical clock {init, enable, disable} framework
  2015-07-31  7:03             ` Maxime Ripard
@ 2015-07-31  8:48               ` Lee Jones
  -1 siblings, 0 replies; 93+ messages in thread
From: Lee Jones @ 2015-07-31  8:48 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: linux-arm-kernel, linux-kernel, kernel, mturquette, sboyd,
	devicetree, geert, s.hauer

On Fri, 31 Jul 2015, Maxime Ripard wrote:

> On Tue, Jul 28, 2015 at 02:00:55PM +0100, Lee Jones wrote:
> > > > I don't think we can use reference counting, because we'd need as
> > > > many critical clock owners as there are critical clocks.
> > > 
> > > Which we can have if we replace the call to clk_prepare_enable you add
> > > in your fourth patch in __set_critical_clocks.
> > 
> > What should it be replaced with?
> 
> clk->critical_count++
> clk_prepare_enable
> 
> ?

Ah, so not replace it then.  Just add a reference counter.

I'm with you, that's fine.

> > > > Cast your mind back to the reasons for this critical clock API.  One
> > > > of the most important intentions of this API is the requirement
> > > > mitigation for each of the critical clocks to have an owner
> > > > (driver).
> > > > 
> > > > With regards to your second point, that's what 'critical.enabled'
> > > > is for.  Take a look at clk_enable_critical().
> > > 
> > > I don't think this addresses the issue, if you just throw more
> > > customers at it, the issue remain with your implementation.
> > > 
> > > If you have three customers that used the critical API, and if on of
> > > these calls clk_disable_critical, you're losing leave_on.
> > 
> > That's the idea.  See my point above, the one you replied "Indeed"
> > to.  So when a driver uses clk_disable_critical() it's saying, "I know
> > why this clock is a critical clock, and I know that nothing terrible
> > will happen if I disable it, as I have that covered".
> 
> We do agree on the semantic of clk_disable_critical :)
> 
> > So then if it's not the last user to call clk_disable(), the last
> > one out the door will be allowed to finally gate the clock,
> > regardless whether it's critical aware or not.
> 
> That's right, but what I mean would be a case where you have two users
> that are aware that it is a critical clock (A and B), and one which is
> not (C).
> 
> If I understood correctly your code, if A calls clk_disable_critical,
> leave_on is set to false. That means that now, if C calls clk_disable
> on that clock, it will actually be shut down, while B still considers
> it a critical clock.

Hmm... I'd have to think about this.

How would you mark a clock as critical twice?

> > Then, when we come to enable the clock again, the critical aware user
> > then re-marks the clock as leave_on, so not critical un-aware user can
> > take the final reference and disable the clock.
> > 
> > > Which means that if there's one of the two users left that calls
> > > clk_disable on it, the clock will actually be disabled, which is
> > > clearly not what we want to do, as we have still a user that want the
> > > clock to be enabled.
> > 
> > That's not what happens (at least it shouldn't if I've coded it up
> > right).  The API _still_ requires all of the users to give-up their
> > reference.
> 
> Ah, right. So I guess it all boils down to the discussion you're
> having with Mike regarding whether critical users should expect to
> already have a reference taken or calling clk_prepare / clk_enable
> themselves.

Then we'd need a clk_prepare_enable_critical() :)

... which would be aware of the original reference (taken by
__set_critical_clocks).  However, if a second knowledgeable driver
were to call it, then how would it know that whether the original
reference was still present or not?  I guess that's where your
critical clock reference comes in.  If it's the first critical user,
it would decrement the original reference, it it's a subsequent user,
then it won't

> > > It would be much more robust to have another count for the critical
> > > stuff, initialised to one by the __set_critical_clocks function.
> > 
> > If I understand you correctly, we already have a count.  We use the
> > original reference count.  No need for one of our own.
> > 
> > Using your RAM Clock (Clock 4) as an example
> > --------------------------------------------
> > 
> > Early start-up:
> >   Clock 4 is marked as critical and a reference is taken (ref == 1)
> > 
> > Driver probe:
> >   SPI enables Clock 4 (ref == 2)
> >   I2C enables Clock 4 (ref == 3)
> > 
> > Suspend (without RAM driver's permission):
> >   SPI disables Clock 4 (ref == 2)
> >   I2C disables Clock 4 (ref == 1)
> >   /*
> >    * Clock won't be gated because:
> >    *   .leave_on is True - can't dec final reference
> >    */
> > 
> > Suspend (with RAM driver's permission):
> >   /* Order is unimportant */
> >   SPI disables Clock 4 (ref == 2)
> >   RAM disables Clock 4 (ref == 1) /* Won't turn off here (ref > 0)
> >   I2C disables Clock 4 (ref == 0) /* (.leave_on == False) last ref can be taken */
> >   /*
> >    * Clock will be gated because:
> >    *   .leave_on is False, so (ref == 0)
> >    */
> > 
> > Resume:
> >   /* Order is unimportant */
> >   SPI enables Clock 4 (ref == 1)
> >   RAM enables Clock 4 and re-enables .leave_on (ref == 2)
> >   I2C enables Clock 4 (ref == 3)
> > 
> > Hopefully that clears things up.
> 
> It does indeed. I simply forgot to take into account the fact that it
> would still need the reference to be set to 0. My bad.
> 
> Still, If we take the same kind of scenario:
> 
> Early start-up:
>   Clock 4 is marked as critical and a reference is taken (ref == 1, leave_on = true)
> 
> Driver probe:
>   SPI enables Clock 4 (ref == 2)
>   I2C enables Clock 4 (ref == 3)
>   RAM enables Clock 4 (ref == 4, leave_on = true )
>   CPUIdle enables Clock 4 (ref == 5, leave_on = true )
> 
> Suspend (with CPUIdle and RAM permissions):
>   /* Order is unimportant */
>   SPI disables Clock 4 (ref == 4)
>   CPUIdle disables Clock 4 (ref == 3, leave_on = false ) 
>   RAM disables Clock 4 (ref == 2, leave_on = false )
>   I2C disables Clock 4 (ref == 1)
> 
> And even though the clock will still be running when CPUIdle calls
> clk_disable_critical because of the enable_count, the status of
> leave_on is off, as the RAM driver still considers it to be left on
> (ie, hasn't called clk_disable_critical yet).
> 
> Or at least, that's what I understood of it.

Right, I understood this problem when you suggested that two critical
clock users could be using the same clock.  Other than having them
call clock_prepare_enable[_critical](), I'm not sure if that's
possible.

As I mentioned above, we can handle this with reference counting and
I'm happy to code that up.

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

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

* [PATCH v7 3/5] clk: Supply the critical clock {init, enable, disable} framework
@ 2015-07-31  8:48               ` Lee Jones
  0 siblings, 0 replies; 93+ messages in thread
From: Lee Jones @ 2015-07-31  8:48 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, 31 Jul 2015, Maxime Ripard wrote:

> On Tue, Jul 28, 2015 at 02:00:55PM +0100, Lee Jones wrote:
> > > > I don't think we can use reference counting, because we'd need as
> > > > many critical clock owners as there are critical clocks.
> > > 
> > > Which we can have if we replace the call to clk_prepare_enable you add
> > > in your fourth patch in __set_critical_clocks.
> > 
> > What should it be replaced with?
> 
> clk->critical_count++
> clk_prepare_enable
> 
> ?

Ah, so not replace it then.  Just add a reference counter.

I'm with you, that's fine.

> > > > Cast your mind back to the reasons for this critical clock API.  One
> > > > of the most important intentions of this API is the requirement
> > > > mitigation for each of the critical clocks to have an owner
> > > > (driver).
> > > > 
> > > > With regards to your second point, that's what 'critical.enabled'
> > > > is for.  Take a look at clk_enable_critical().
> > > 
> > > I don't think this addresses the issue, if you just throw more
> > > customers at it, the issue remain with your implementation.
> > > 
> > > If you have three customers that used the critical API, and if on of
> > > these calls clk_disable_critical, you're losing leave_on.
> > 
> > That's the idea.  See my point above, the one you replied "Indeed"
> > to.  So when a driver uses clk_disable_critical() it's saying, "I know
> > why this clock is a critical clock, and I know that nothing terrible
> > will happen if I disable it, as I have that covered".
> 
> We do agree on the semantic of clk_disable_critical :)
> 
> > So then if it's not the last user to call clk_disable(), the last
> > one out the door will be allowed to finally gate the clock,
> > regardless whether it's critical aware or not.
> 
> That's right, but what I mean would be a case where you have two users
> that are aware that it is a critical clock (A and B), and one which is
> not (C).
> 
> If I understood correctly your code, if A calls clk_disable_critical,
> leave_on is set to false. That means that now, if C calls clk_disable
> on that clock, it will actually be shut down, while B still considers
> it a critical clock.

Hmm... I'd have to think about this.

How would you mark a clock as critical twice?

> > Then, when we come to enable the clock again, the critical aware user
> > then re-marks the clock as leave_on, so not critical un-aware user can
> > take the final reference and disable the clock.
> > 
> > > Which means that if there's one of the two users left that calls
> > > clk_disable on it, the clock will actually be disabled, which is
> > > clearly not what we want to do, as we have still a user that want the
> > > clock to be enabled.
> > 
> > That's not what happens (at least it shouldn't if I've coded it up
> > right).  The API _still_ requires all of the users to give-up their
> > reference.
> 
> Ah, right. So I guess it all boils down to the discussion you're
> having with Mike regarding whether critical users should expect to
> already have a reference taken or calling clk_prepare / clk_enable
> themselves.

Then we'd need a clk_prepare_enable_critical() :)

... which would be aware of the original reference (taken by
__set_critical_clocks).  However, if a second knowledgeable driver
were to call it, then how would it know that whether the original
reference was still present or not?  I guess that's where your
critical clock reference comes in.  If it's the first critical user,
it would decrement the original reference, it it's a subsequent user,
then it won't

> > > It would be much more robust to have another count for the critical
> > > stuff, initialised to one by the __set_critical_clocks function.
> > 
> > If I understand you correctly, we already have a count.  We use the
> > original reference count.  No need for one of our own.
> > 
> > Using your RAM Clock (Clock 4) as an example
> > --------------------------------------------
> > 
> > Early start-up:
> >   Clock 4 is marked as critical and a reference is taken (ref == 1)
> > 
> > Driver probe:
> >   SPI enables Clock 4 (ref == 2)
> >   I2C enables Clock 4 (ref == 3)
> > 
> > Suspend (without RAM driver's permission):
> >   SPI disables Clock 4 (ref == 2)
> >   I2C disables Clock 4 (ref == 1)
> >   /*
> >    * Clock won't be gated because:
> >    *   .leave_on is True - can't dec final reference
> >    */
> > 
> > Suspend (with RAM driver's permission):
> >   /* Order is unimportant */
> >   SPI disables Clock 4 (ref == 2)
> >   RAM disables Clock 4 (ref == 1) /* Won't turn off here (ref > 0)
> >   I2C disables Clock 4 (ref == 0) /* (.leave_on == False) last ref can be taken */
> >   /*
> >    * Clock will be gated because:
> >    *   .leave_on is False, so (ref == 0)
> >    */
> > 
> > Resume:
> >   /* Order is unimportant */
> >   SPI enables Clock 4 (ref == 1)
> >   RAM enables Clock 4 and re-enables .leave_on (ref == 2)
> >   I2C enables Clock 4 (ref == 3)
> > 
> > Hopefully that clears things up.
> 
> It does indeed. I simply forgot to take into account the fact that it
> would still need the reference to be set to 0. My bad.
> 
> Still, If we take the same kind of scenario:
> 
> Early start-up:
>   Clock 4 is marked as critical and a reference is taken (ref == 1, leave_on = true)
> 
> Driver probe:
>   SPI enables Clock 4 (ref == 2)
>   I2C enables Clock 4 (ref == 3)
>   RAM enables Clock 4 (ref == 4, leave_on = true )
>   CPUIdle enables Clock 4 (ref == 5, leave_on = true )
> 
> Suspend (with CPUIdle and RAM permissions):
>   /* Order is unimportant */
>   SPI disables Clock 4 (ref == 4)
>   CPUIdle disables Clock 4 (ref == 3, leave_on = false ) 
>   RAM disables Clock 4 (ref == 2, leave_on = false )
>   I2C disables Clock 4 (ref == 1)
> 
> And even though the clock will still be running when CPUIdle calls
> clk_disable_critical because of the enable_count, the status of
> leave_on is off, as the RAM driver still considers it to be left on
> (ie, hasn't called clk_disable_critical yet).
> 
> Or at least, that's what I understood of it.

Right, I understood this problem when you suggested that two critical
clock users could be using the same clock.  Other than having them
call clock_prepare_enable[_critical](), I'm not sure if that's
possible.

As I mentioned above, we can handle this with reference counting and
I'm happy to code that up.

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org ? Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

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

* Re: [PATCH v7 3/5] clk: Supply the critical clock {init, enable, disable} framework
  2015-07-30 22:57             ` Michael Turquette
  (?)
@ 2015-07-31  8:56               ` Lee Jones
  -1 siblings, 0 replies; 93+ messages in thread
From: Lee Jones @ 2015-07-31  8:56 UTC (permalink / raw)
  To: Michael Turquette
  Cc: Maxime Ripard, linux-arm-kernel, linux-kernel, kernel, sboyd,
	devicetree, geert, s.hauer

On Thu, 30 Jul 2015, Michael Turquette wrote:

> Quoting Lee Jones (2015-07-30 02:21:39)
> > On Wed, 29 Jul 2015, Michael Turquette wrote:
> > > Quoting Lee Jones (2015-07-27 01:53:38)
> > > > On Mon, 27 Jul 2015, Maxime Ripard wrote:
> > > > 
> > > > > On Wed, Jul 22, 2015 at 02:04:13PM +0100, Lee Jones wrote:
> > > > > > These new API calls will firstly provide a mechanisms to tag a clock as
> > > > > > critical and secondly allow any knowledgeable driver to (un)gate clocks,
> > > > > > even if they are marked as critical.
> > > > > > 
> > > > > > Suggested-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> > > > > > Signed-off-by: Lee Jones <lee.jones@linaro.org>
> > > > > > ---
> > > > > >  drivers/clk/clk.c            | 45 ++++++++++++++++++++++++++++++++++++++++++++
> > > > > >  include/linux/clk-provider.h |  2 ++
> > > > > >  include/linux/clk.h          | 30 +++++++++++++++++++++++++++++
> > > > > >  3 files changed, 77 insertions(+)
> > > > > > 
> > > > > > diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> > > > > > index 61c3fc5..486b1da 100644
> > > > > > --- a/drivers/clk/clk.c
> > > > > > +++ b/drivers/clk/clk.c
> > > > > > @@ -46,6 +46,21 @@ static struct clk_core *clk_core_lookup(const char *name);
> > > > > >  
> > > > > >  /***    private data structures    ***/
> > > > > >  
> > > > > > +/**
> > > > > > + * struct critical -       Provides 'play' over critical clocks.  A clock can be
> > > > > > + *                 marked as critical, meaning that it should not be
> > > > > > + *                 disabled.  However, if a driver which is aware of the
> > > > > > + *                 critical behaviour wants to control it, it can do so
> > > > > > + *                 using clk_enable_critical() and clk_disable_critical().
> > > > > > + *
> > > > > > + * @enabled        Is clock critical?  Once set, doesn't change
> > > > > > + * @leave_on       Self explanatory.  Can be disabled by knowledgeable drivers
> > > > > > + */
> > > > > > +struct critical {
> > > > > > +   bool enabled;
> > > > > > +   bool leave_on;
> > > > > > +};
> > > > > > +
> > > > > >  struct clk_core {
> > > > > >     const char              *name;
> > > > > >     const struct clk_ops    *ops;
> > > > > > @@ -75,6 +90,7 @@ struct clk_core {
> > > > > >     struct dentry           *dentry;
> > > > > >  #endif
> > > > > >     struct kref             ref;
> > > > > > +   struct critical         critical;
> > > > > >  };
> > > > > >  
> > > > > >  struct clk {
> > > > > > @@ -995,6 +1011,10 @@ static void clk_core_disable(struct clk_core *clk)
> > > > > >     if (WARN_ON(clk->enable_count == 0))
> > > > > >             return;
> > > > > >  
> > > > > > +   /* Refuse to turn off a critical clock */
> > > > > > +   if (clk->enable_count == 1 && clk->critical.leave_on)
> > > > > > +           return;
> > > > > > +
> > > > > 
> > > > > I think it should be handled by a separate counting. Otherwise, if you
> > > > > have two users that marked the clock as critical, and then one of them
> > > > > disable it...
> > > > > 
> > > > > >     if (--clk->enable_count > 0)
> > > > > >             return;
> > > > > >  
> > > > > > @@ -1037,6 +1057,13 @@ void clk_disable(struct clk *clk)
> > > > > >  }
> > > > > >  EXPORT_SYMBOL_GPL(clk_disable);
> > > > > >  
> > > > > > +void clk_disable_critical(struct clk *clk)
> > > > > > +{
> > > > > > +   clk->core->critical.leave_on = false;
> > > > > 
> > > > > .. you just lost the fact that it was critical in the first place.
> > > > 
> > > > I thought about both of these points, which is why I came up with this
> > > > strategy.
> > > > 
> > > > Any device which uses the *_critical() API should a) have knowledge of
> > > > what happens when a particular critical clock is gated and b) have
> > > > thought about the consequences.
> > > 
> > > If this statement above is true then I fail to see the need for a new
> > > api. A driver which has a really great idea of when it is safe or unsafe
> > > to gate a clock should call clk_prepare_enable at probe and then only
> > > call clk_disable_unprepare once it is safe to do so.
> > > 
> > > The existing bookkeeping in the clock framework will do the rest.
> > 
> > I think you are viewing this particular API back-to-front.  The idea
> > is to mark all of the critical clocks at start-up by taking a
> > reference.  Then, if there are no knowledgable drivers who wish to
> > turn the clock off, the CCF will leave the clock ungated becuase the
> > reference count will always be >0.
> 
> Right. So I'll ask the same question here that I asked in the other
> patch: is there ever a case where a clock consumer driver would want to
> call clk_enable_critical? It seems to me that in you usage of it, that
> call would only ever be made by the core framework code (e.g. clk-conf.c
> or perhaps somewhere in drivers/clk/clk.c).

Yes, _after_ it has called clk_disable_critical(), when it has
finished fiddling with it.  clk_enable_critical() simply resets the
clock back to an enabled/critical state (how the knowledgeable driver
found it).

> > The clk_{disable,enable}_critical() calls are to be used by
> > knowledgable drivers to say "[disable] I know what I'm doing and it's
> > okay for this clock to be turned off" and "[enable] right I'm done
> > with this clock now, let's turn it back on and mark it back as
> > critical, so no one else can turn it off".
> 
> OK, so this almost answers my question above. You have a driver that may
> finish using a clock for a while (ie, rmmod knowledgeable_driver), and
> you want it (critically) enabled again. Is this a real use case? Who
> would come along and disable this clock later on? If the driver is to be
> re-loaded then I would suggest never unloading it in the first place.

This has nothing to do with modules.  I believe the knowledgeable
consumer should only gate the clock (steal a reference) when the clock
is actually gated.  The rest of the time the framework will have it
marked as critical "do not turn me off".

> (Oh and bear in mind when answering my question above that imbalanced
> clk_enable/clk_disable calls will not succeed thanks to the vaporware
> patch that I have in my local tree)

They won't be imbalanced, because clk_enable() would have been called
first during start-up (__set_critical_clocks()).

> If you have a second knowledgeable_driver_2 that shares that clock and
> can be trusted to manage it (critically) then I would need to see that
> example, as it doesn't feel like a real use to me.

Nor me, that's why this impementation doesn't handle that use-case,
however Maxime thinks it is one, so we can solve that with reference
counting.

> > To put things simply, the knowledgable driver will _not_ be enabling
> > the clock in the first place.  The first interaction it has with it is
> > to gate it.  Then, once it's done, it will enable it again and mark it
> > back up as critical.a
> 
> I like the first part. Makes sense and fills a real need. I am fully
> on-board with a provider-handoff-to-consumer solution. It is all the
> weird stuff that comes after it that I'm unsure of.

I don't think there should be hand-off.  I think the
{enable,disable}_critical() should "momentarily" take the last
reference, then put everything back as it found it when it's finished
disabling the clock.

> > Still confused ... let's go on another Q in one of your other emails
> > for another way of putting it.
> > 
> > > > I don't think we can use reference
> > > > counting, because we'd need as many critical clock owners as there are
> > > > critical clocks.  Cast your mind back to the reasons for this critical
> > > > clock API.  One of the most important intentions of this API is the
> > > > requirement mitigation for each of the critical clocks to have an owner
> > > > (driver).
> > > > 
> > > > With regards to your second point, that's what 'critical.enabled'
> > > > is for.  Take a look at clk_enable_critical().
> > > > 
> > 

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

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

* Re: [PATCH v7 3/5] clk: Supply the critical clock {init, enable, disable} framework
@ 2015-07-31  8:56               ` Lee Jones
  0 siblings, 0 replies; 93+ messages in thread
From: Lee Jones @ 2015-07-31  8:56 UTC (permalink / raw)
  To: Michael Turquette
  Cc: Maxime Ripard, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	kernel-F5mvAk5X5gdBDgjK7y7TUQ, sboyd-sgV2jX0FEOL9JmXXK+q4OQ,
	devicetree-u79uwXL29TY76Z2rM5mHXA, geert-Td1EMuHUCqxL1ZNQvxDV9g,
	s.hauer-bIcnvbaLZ9MEGnE8C9+IrQ

On Thu, 30 Jul 2015, Michael Turquette wrote:

> Quoting Lee Jones (2015-07-30 02:21:39)
> > On Wed, 29 Jul 2015, Michael Turquette wrote:
> > > Quoting Lee Jones (2015-07-27 01:53:38)
> > > > On Mon, 27 Jul 2015, Maxime Ripard wrote:
> > > > 
> > > > > On Wed, Jul 22, 2015 at 02:04:13PM +0100, Lee Jones wrote:
> > > > > > These new API calls will firstly provide a mechanisms to tag a clock as
> > > > > > critical and secondly allow any knowledgeable driver to (un)gate clocks,
> > > > > > even if they are marked as critical.
> > > > > > 
> > > > > > Suggested-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> > > > > > Signed-off-by: Lee Jones <lee.jones-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> > > > > > ---
> > > > > >  drivers/clk/clk.c            | 45 ++++++++++++++++++++++++++++++++++++++++++++
> > > > > >  include/linux/clk-provider.h |  2 ++
> > > > > >  include/linux/clk.h          | 30 +++++++++++++++++++++++++++++
> > > > > >  3 files changed, 77 insertions(+)
> > > > > > 
> > > > > > diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> > > > > > index 61c3fc5..486b1da 100644
> > > > > > --- a/drivers/clk/clk.c
> > > > > > +++ b/drivers/clk/clk.c
> > > > > > @@ -46,6 +46,21 @@ static struct clk_core *clk_core_lookup(const char *name);
> > > > > >  
> > > > > >  /***    private data structures    ***/
> > > > > >  
> > > > > > +/**
> > > > > > + * struct critical -       Provides 'play' over critical clocks.  A clock can be
> > > > > > + *                 marked as critical, meaning that it should not be
> > > > > > + *                 disabled.  However, if a driver which is aware of the
> > > > > > + *                 critical behaviour wants to control it, it can do so
> > > > > > + *                 using clk_enable_critical() and clk_disable_critical().
> > > > > > + *
> > > > > > + * @enabled        Is clock critical?  Once set, doesn't change
> > > > > > + * @leave_on       Self explanatory.  Can be disabled by knowledgeable drivers
> > > > > > + */
> > > > > > +struct critical {
> > > > > > +   bool enabled;
> > > > > > +   bool leave_on;
> > > > > > +};
> > > > > > +
> > > > > >  struct clk_core {
> > > > > >     const char              *name;
> > > > > >     const struct clk_ops    *ops;
> > > > > > @@ -75,6 +90,7 @@ struct clk_core {
> > > > > >     struct dentry           *dentry;
> > > > > >  #endif
> > > > > >     struct kref             ref;
> > > > > > +   struct critical         critical;
> > > > > >  };
> > > > > >  
> > > > > >  struct clk {
> > > > > > @@ -995,6 +1011,10 @@ static void clk_core_disable(struct clk_core *clk)
> > > > > >     if (WARN_ON(clk->enable_count == 0))
> > > > > >             return;
> > > > > >  
> > > > > > +   /* Refuse to turn off a critical clock */
> > > > > > +   if (clk->enable_count == 1 && clk->critical.leave_on)
> > > > > > +           return;
> > > > > > +
> > > > > 
> > > > > I think it should be handled by a separate counting. Otherwise, if you
> > > > > have two users that marked the clock as critical, and then one of them
> > > > > disable it...
> > > > > 
> > > > > >     if (--clk->enable_count > 0)
> > > > > >             return;
> > > > > >  
> > > > > > @@ -1037,6 +1057,13 @@ void clk_disable(struct clk *clk)
> > > > > >  }
> > > > > >  EXPORT_SYMBOL_GPL(clk_disable);
> > > > > >  
> > > > > > +void clk_disable_critical(struct clk *clk)
> > > > > > +{
> > > > > > +   clk->core->critical.leave_on = false;
> > > > > 
> > > > > .. you just lost the fact that it was critical in the first place.
> > > > 
> > > > I thought about both of these points, which is why I came up with this
> > > > strategy.
> > > > 
> > > > Any device which uses the *_critical() API should a) have knowledge of
> > > > what happens when a particular critical clock is gated and b) have
> > > > thought about the consequences.
> > > 
> > > If this statement above is true then I fail to see the need for a new
> > > api. A driver which has a really great idea of when it is safe or unsafe
> > > to gate a clock should call clk_prepare_enable at probe and then only
> > > call clk_disable_unprepare once it is safe to do so.
> > > 
> > > The existing bookkeeping in the clock framework will do the rest.
> > 
> > I think you are viewing this particular API back-to-front.  The idea
> > is to mark all of the critical clocks at start-up by taking a
> > reference.  Then, if there are no knowledgable drivers who wish to
> > turn the clock off, the CCF will leave the clock ungated becuase the
> > reference count will always be >0.
> 
> Right. So I'll ask the same question here that I asked in the other
> patch: is there ever a case where a clock consumer driver would want to
> call clk_enable_critical? It seems to me that in you usage of it, that
> call would only ever be made by the core framework code (e.g. clk-conf.c
> or perhaps somewhere in drivers/clk/clk.c).

Yes, _after_ it has called clk_disable_critical(), when it has
finished fiddling with it.  clk_enable_critical() simply resets the
clock back to an enabled/critical state (how the knowledgeable driver
found it).

> > The clk_{disable,enable}_critical() calls are to be used by
> > knowledgable drivers to say "[disable] I know what I'm doing and it's
> > okay for this clock to be turned off" and "[enable] right I'm done
> > with this clock now, let's turn it back on and mark it back as
> > critical, so no one else can turn it off".
> 
> OK, so this almost answers my question above. You have a driver that may
> finish using a clock for a while (ie, rmmod knowledgeable_driver), and
> you want it (critically) enabled again. Is this a real use case? Who
> would come along and disable this clock later on? If the driver is to be
> re-loaded then I would suggest never unloading it in the first place.

This has nothing to do with modules.  I believe the knowledgeable
consumer should only gate the clock (steal a reference) when the clock
is actually gated.  The rest of the time the framework will have it
marked as critical "do not turn me off".

> (Oh and bear in mind when answering my question above that imbalanced
> clk_enable/clk_disable calls will not succeed thanks to the vaporware
> patch that I have in my local tree)

They won't be imbalanced, because clk_enable() would have been called
first during start-up (__set_critical_clocks()).

> If you have a second knowledgeable_driver_2 that shares that clock and
> can be trusted to manage it (critically) then I would need to see that
> example, as it doesn't feel like a real use to me.

Nor me, that's why this impementation doesn't handle that use-case,
however Maxime thinks it is one, so we can solve that with reference
counting.

> > To put things simply, the knowledgable driver will _not_ be enabling
> > the clock in the first place.  The first interaction it has with it is
> > to gate it.  Then, once it's done, it will enable it again and mark it
> > back up as critical.a
> 
> I like the first part. Makes sense and fills a real need. I am fully
> on-board with a provider-handoff-to-consumer solution. It is all the
> weird stuff that comes after it that I'm unsure of.

I don't think there should be hand-off.  I think the
{enable,disable}_critical() should "momentarily" take the last
reference, then put everything back as it found it when it's finished
disabling the clock.

> > Still confused ... let's go on another Q in one of your other emails
> > for another way of putting it.
> > 
> > > > I don't think we can use reference
> > > > counting, because we'd need as many critical clock owners as there are
> > > > critical clocks.  Cast your mind back to the reasons for this critical
> > > > clock API.  One of the most important intentions of this API is the
> > > > requirement mitigation for each of the critical clocks to have an owner
> > > > (driver).
> > > > 
> > > > With regards to your second point, that's what 'critical.enabled'
> > > > is for.  Take a look at clk_enable_critical().
> > > > 
> > 

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH v7 3/5] clk: Supply the critical clock {init, enable, disable} framework
@ 2015-07-31  8:56               ` Lee Jones
  0 siblings, 0 replies; 93+ messages in thread
From: Lee Jones @ 2015-07-31  8:56 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, 30 Jul 2015, Michael Turquette wrote:

> Quoting Lee Jones (2015-07-30 02:21:39)
> > On Wed, 29 Jul 2015, Michael Turquette wrote:
> > > Quoting Lee Jones (2015-07-27 01:53:38)
> > > > On Mon, 27 Jul 2015, Maxime Ripard wrote:
> > > > 
> > > > > On Wed, Jul 22, 2015 at 02:04:13PM +0100, Lee Jones wrote:
> > > > > > These new API calls will firstly provide a mechanisms to tag a clock as
> > > > > > critical and secondly allow any knowledgeable driver to (un)gate clocks,
> > > > > > even if they are marked as critical.
> > > > > > 
> > > > > > Suggested-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> > > > > > Signed-off-by: Lee Jones <lee.jones@linaro.org>
> > > > > > ---
> > > > > >  drivers/clk/clk.c            | 45 ++++++++++++++++++++++++++++++++++++++++++++
> > > > > >  include/linux/clk-provider.h |  2 ++
> > > > > >  include/linux/clk.h          | 30 +++++++++++++++++++++++++++++
> > > > > >  3 files changed, 77 insertions(+)
> > > > > > 
> > > > > > diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> > > > > > index 61c3fc5..486b1da 100644
> > > > > > --- a/drivers/clk/clk.c
> > > > > > +++ b/drivers/clk/clk.c
> > > > > > @@ -46,6 +46,21 @@ static struct clk_core *clk_core_lookup(const char *name);
> > > > > >  
> > > > > >  /***    private data structures    ***/
> > > > > >  
> > > > > > +/**
> > > > > > + * struct critical -       Provides 'play' over critical clocks.  A clock can be
> > > > > > + *                 marked as critical, meaning that it should not be
> > > > > > + *                 disabled.  However, if a driver which is aware of the
> > > > > > + *                 critical behaviour wants to control it, it can do so
> > > > > > + *                 using clk_enable_critical() and clk_disable_critical().
> > > > > > + *
> > > > > > + * @enabled        Is clock critical?  Once set, doesn't change
> > > > > > + * @leave_on       Self explanatory.  Can be disabled by knowledgeable drivers
> > > > > > + */
> > > > > > +struct critical {
> > > > > > +   bool enabled;
> > > > > > +   bool leave_on;
> > > > > > +};
> > > > > > +
> > > > > >  struct clk_core {
> > > > > >     const char              *name;
> > > > > >     const struct clk_ops    *ops;
> > > > > > @@ -75,6 +90,7 @@ struct clk_core {
> > > > > >     struct dentry           *dentry;
> > > > > >  #endif
> > > > > >     struct kref             ref;
> > > > > > +   struct critical         critical;
> > > > > >  };
> > > > > >  
> > > > > >  struct clk {
> > > > > > @@ -995,6 +1011,10 @@ static void clk_core_disable(struct clk_core *clk)
> > > > > >     if (WARN_ON(clk->enable_count == 0))
> > > > > >             return;
> > > > > >  
> > > > > > +   /* Refuse to turn off a critical clock */
> > > > > > +   if (clk->enable_count == 1 && clk->critical.leave_on)
> > > > > > +           return;
> > > > > > +
> > > > > 
> > > > > I think it should be handled by a separate counting. Otherwise, if you
> > > > > have two users that marked the clock as critical, and then one of them
> > > > > disable it...
> > > > > 
> > > > > >     if (--clk->enable_count > 0)
> > > > > >             return;
> > > > > >  
> > > > > > @@ -1037,6 +1057,13 @@ void clk_disable(struct clk *clk)
> > > > > >  }
> > > > > >  EXPORT_SYMBOL_GPL(clk_disable);
> > > > > >  
> > > > > > +void clk_disable_critical(struct clk *clk)
> > > > > > +{
> > > > > > +   clk->core->critical.leave_on = false;
> > > > > 
> > > > > .. you just lost the fact that it was critical in the first place.
> > > > 
> > > > I thought about both of these points, which is why I came up with this
> > > > strategy.
> > > > 
> > > > Any device which uses the *_critical() API should a) have knowledge of
> > > > what happens when a particular critical clock is gated and b) have
> > > > thought about the consequences.
> > > 
> > > If this statement above is true then I fail to see the need for a new
> > > api. A driver which has a really great idea of when it is safe or unsafe
> > > to gate a clock should call clk_prepare_enable at probe and then only
> > > call clk_disable_unprepare once it is safe to do so.
> > > 
> > > The existing bookkeeping in the clock framework will do the rest.
> > 
> > I think you are viewing this particular API back-to-front.  The idea
> > is to mark all of the critical clocks at start-up by taking a
> > reference.  Then, if there are no knowledgable drivers who wish to
> > turn the clock off, the CCF will leave the clock ungated becuase the
> > reference count will always be >0.
> 
> Right. So I'll ask the same question here that I asked in the other
> patch: is there ever a case where a clock consumer driver would want to
> call clk_enable_critical? It seems to me that in you usage of it, that
> call would only ever be made by the core framework code (e.g. clk-conf.c
> or perhaps somewhere in drivers/clk/clk.c).

Yes, _after_ it has called clk_disable_critical(), when it has
finished fiddling with it.  clk_enable_critical() simply resets the
clock back to an enabled/critical state (how the knowledgeable driver
found it).

> > The clk_{disable,enable}_critical() calls are to be used by
> > knowledgable drivers to say "[disable] I know what I'm doing and it's
> > okay for this clock to be turned off" and "[enable] right I'm done
> > with this clock now, let's turn it back on and mark it back as
> > critical, so no one else can turn it off".
> 
> OK, so this almost answers my question above. You have a driver that may
> finish using a clock for a while (ie, rmmod knowledgeable_driver), and
> you want it (critically) enabled again. Is this a real use case? Who
> would come along and disable this clock later on? If the driver is to be
> re-loaded then I would suggest never unloading it in the first place.

This has nothing to do with modules.  I believe the knowledgeable
consumer should only gate the clock (steal a reference) when the clock
is actually gated.  The rest of the time the framework will have it
marked as critical "do not turn me off".

> (Oh and bear in mind when answering my question above that imbalanced
> clk_enable/clk_disable calls will not succeed thanks to the vaporware
> patch that I have in my local tree)

They won't be imbalanced, because clk_enable() would have been called
first during start-up (__set_critical_clocks()).

> If you have a second knowledgeable_driver_2 that shares that clock and
> can be trusted to manage it (critically) then I would need to see that
> example, as it doesn't feel like a real use to me.

Nor me, that's why this impementation doesn't handle that use-case,
however Maxime thinks it is one, so we can solve that with reference
counting.

> > To put things simply, the knowledgable driver will _not_ be enabling
> > the clock in the first place.  The first interaction it has with it is
> > to gate it.  Then, once it's done, it will enable it again and mark it
> > back up as critical.a
> 
> I like the first part. Makes sense and fills a real need. I am fully
> on-board with a provider-handoff-to-consumer solution. It is all the
> weird stuff that comes after it that I'm unsure of.

I don't think there should be hand-off.  I think the
{enable,disable}_critical() should "momentarily" take the last
reference, then put everything back as it found it when it's finished
disabling the clock.

> > Still confused ... let's go on another Q in one of your other emails
> > for another way of putting it.
> > 
> > > > I don't think we can use reference
> > > > counting, because we'd need as many critical clock owners as there are
> > > > critical clocks.  Cast your mind back to the reasons for this critical
> > > > clock API.  One of the most important intentions of this API is the
> > > > requirement mitigation for each of the critical clocks to have an owner
> > > > (driver).
> > > > 
> > > > With regards to your second point, that's what 'critical.enabled'
> > > > is for.  Take a look at clk_enable_critical().
> > > > 
> > 

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org ? Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

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

* Re: [PATCH v7 3/5] clk: Supply the critical clock {init, enable, disable} framework
  2015-07-30 23:35         ` Michael Turquette
@ 2015-07-31  9:02           ` Lee Jones
  -1 siblings, 0 replies; 93+ messages in thread
From: Lee Jones @ 2015-07-31  9:02 UTC (permalink / raw)
  To: Michael Turquette
  Cc: linux-arm-kernel, linux-kernel, kernel, sboyd, devicetree, geert,
	maxime.ripard, s.hauer, linux-clk

On Thu, 30 Jul 2015, Michael Turquette wrote:

> Quoting Lee Jones (2015-07-30 04:17:47)
> > On Wed, 29 Jul 2015, Michael Turquette wrote:
> > 
> > > Hi Lee,
> > > 
> > > + linux-clk ml
> > > 
> > > Quoting Lee Jones (2015-07-22 06:04:13)
> > > > These new API calls will firstly provide a mechanisms to tag a clock as
> > > > critical and secondly allow any knowledgeable driver to (un)gate clocks,
> > > > even if they are marked as critical.
> > > > 
> > > > Suggested-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> > > > Signed-off-by: Lee Jones <lee.jones@linaro.org>
> > > > ---
> > > >  drivers/clk/clk.c            | 45 ++++++++++++++++++++++++++++++++++++++++++++
> > > >  include/linux/clk-provider.h |  2 ++
> > > >  include/linux/clk.h          | 30 +++++++++++++++++++++++++++++
> > > >  3 files changed, 77 insertions(+)
> > > > 
> > > > diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> > > > index 61c3fc5..486b1da 100644
> > > > --- a/drivers/clk/clk.c
> > > > +++ b/drivers/clk/clk.c
> > > > @@ -46,6 +46,21 @@ static struct clk_core *clk_core_lookup(const char *name);
> > > >  
> > > >  /***    private data structures    ***/
> > > >  
> > > > +/**
> > > > + * struct critical -   Provides 'play' over critical clocks.  A clock can be
> > > > + *                     marked as critical, meaning that it should not be
> > > > + *                     disabled.  However, if a driver which is aware of the
> > > > + *                     critical behaviour wants to control it, it can do so
> > > > + *                     using clk_enable_critical() and clk_disable_critical().
> > > > + *
> > > > + * @enabled    Is clock critical?  Once set, doesn't change
> > > > + * @leave_on   Self explanatory.  Can be disabled by knowledgeable drivers
> > > 
> > > Not self explanatory. I need this explained to me. What does leave_on
> > > do? Better yet, what would happen if leave_on did not exist?
> > > 
> > > > + */
> > > > +struct critical {
> > > > +       bool enabled;
> > > > +       bool leave_on;
> > > > +};
> > > > +
> > > >  struct clk_core {
> > > >         const char              *name;
> > > >         const struct clk_ops    *ops;
> > > > @@ -75,6 +90,7 @@ struct clk_core {
> > > >         struct dentry           *dentry;
> > > >  #endif
> > > >         struct kref             ref;
> > > > +       struct critical         critical;
> > > >  };
> > > >  
> > > >  struct clk {
> > > > @@ -995,6 +1011,10 @@ static void clk_core_disable(struct clk_core *clk)
> > > >         if (WARN_ON(clk->enable_count == 0))
> > > >                 return;
> > > >  
> > > > +       /* Refuse to turn off a critical clock */
> > > > +       if (clk->enable_count == 1 && clk->critical.leave_on)
> > > > +               return;
> > > 
> > > How do we get to this point? clk_enable_critical actually calls
> > > clk_enable, thus incrementing the enable_count. The only time that we
> > > could hit the above case is if,
> > > 
> > > a) there is an imbalance in clk_enable and clk_disable calls. If this is
> > > the case then the drivers need to be fixed. Or better yet some
> > > infrastructure to catch that, now that we have per-user struct clk
> > > cookies.
> > > 
> > > b) a driver knowingly calls clk_enable_critical(foo) and then regular,
> > > old clk_disable(foo). But why would a driver do that?
> > > 
> > > It might be that I am missing the point here, so please feel free to
> > > clue me in.
> > 
> > This check behaves in a very similar to the WARN() above.  It's more
> > of a fail-safe.  If all drivers are behaving properly, then it
> > shouldn't ever be true.  If they're not, it prevents an incorrectly
> > written driver from irrecoverably crippling the system.
> 
> Then this check should be replaced with a generic approach that refuses
> to honor imbalances anyways. Below are two patches that probably resolve
> the issue of badly behaving drivers that cause enable imbalances.

Your patch should make the requirement for this check moot, so it can
probably be removed.

> > As I said in the other mail.  We can do without these 3 new wrappers.
> > We _could_ just write a driver which only calls clk_enable() _after_
> > it calls clk_disable(), a kind of intentional unbalance and it would
> > do that same thing.
> 
> This naive approach will not work with per-user imbalance tracking.

Steady on.  I said we "_could_", that that I think it's a good idea.

I think it's a bad idea, which is why I wrote this set. ;)

> > However, what we're trying to do here is provide
> > a proper API, so we can see at first glance what the 'knowledgeable'
> > driver is trying to do and not have someone attempt to submit a 'fix'
> > which calls clk_enable() or something.
> 
> We'll need some type of api for sure for the handoff.

This set will not trigger your new checks.  The clocks will be in
perfect ballance becuase a reference will be taken at start-up.

Again:

start-up:
  clk_prepare_enable()

knowlegable_driver_probe:
  clk_get()

knowlegable_driver_gate_clk:
  clk_disable_critical()

knowlegable_driver_ungate_clk:
  clk_enable_critical()

knowlegable_driver_remove:
  clk_put()

> From 3599ed206da9ce770bfafcfd95cbb9a03ac44473 Mon Sep 17 00:00:00 2001
> From: Michael Turquette <mturquette@baylibre.com>
> Date: Wed, 29 Jul 2015 18:22:45 -0700
> Subject: [PATCH 1/2] clk: per-user clk prepare & enable ref counts
> 
> This patch adds prepare and enable reference counts for the per-user
> handles that clock consumers have for a clock node. This patch warns if
> an imbalance occurs while trying to disable or unprepare a clock and
> aborts, leaving the hardware unaffected.
> 
> Signed-off-by: Michael Turquette <mturquette@baylibre.com>
> ---
>  drivers/clk/clk.c | 10 ++++++++++
>  1 file changed, 10 insertions(+)
> 
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> index 898052e..72feee9 100644
> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> @@ -84,6 +84,8 @@ struct clk {
>  	unsigned long min_rate;
>  	unsigned long max_rate;
>  	struct hlist_node clks_node;
> +	unsigned int enable_count;
> +	unsigned int prepare_count;
>  };
>  
>  /***           locking             ***/
> @@ -600,6 +602,9 @@ void clk_unprepare(struct clk *clk)
>  		return;
>  
>  	clk_prepare_lock();
> +	if (WARN_ON(clk->prepare_count == 0))
> +		return;
> +	clk->prepare_count--;
>  	clk_core_unprepare(clk->core);
>  	clk_prepare_unlock();
>  }
> @@ -657,6 +662,7 @@ int clk_prepare(struct clk *clk)
>  		return 0;
>  
>  	clk_prepare_lock();
> +	clk->prepare_count++;
>  	ret = clk_core_prepare(clk->core);
>  	clk_prepare_unlock();
>  
> @@ -707,6 +713,9 @@ void clk_disable(struct clk *clk)
>  		return;
>  
>  	flags = clk_enable_lock();
> +	if (WARN_ON(clk->enable_count == 0))
> +		return;
> +	clk->enable_count--;
>  	clk_core_disable(clk->core);
>  	clk_enable_unlock(flags);
>  }
> @@ -769,6 +778,7 @@ int clk_enable(struct clk *clk)
>  		return 0;
>  
>  	flags = clk_enable_lock();
> +	clk->enable_count++;
>  	ret = clk_core_enable(clk->core);
>  	clk_enable_unlock(flags);
>  

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

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

* [PATCH v7 3/5] clk: Supply the critical clock {init, enable, disable} framework
@ 2015-07-31  9:02           ` Lee Jones
  0 siblings, 0 replies; 93+ messages in thread
From: Lee Jones @ 2015-07-31  9:02 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, 30 Jul 2015, Michael Turquette wrote:

> Quoting Lee Jones (2015-07-30 04:17:47)
> > On Wed, 29 Jul 2015, Michael Turquette wrote:
> > 
> > > Hi Lee,
> > > 
> > > + linux-clk ml
> > > 
> > > Quoting Lee Jones (2015-07-22 06:04:13)
> > > > These new API calls will firstly provide a mechanisms to tag a clock as
> > > > critical and secondly allow any knowledgeable driver to (un)gate clocks,
> > > > even if they are marked as critical.
> > > > 
> > > > Suggested-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> > > > Signed-off-by: Lee Jones <lee.jones@linaro.org>
> > > > ---
> > > >  drivers/clk/clk.c            | 45 ++++++++++++++++++++++++++++++++++++++++++++
> > > >  include/linux/clk-provider.h |  2 ++
> > > >  include/linux/clk.h          | 30 +++++++++++++++++++++++++++++
> > > >  3 files changed, 77 insertions(+)
> > > > 
> > > > diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> > > > index 61c3fc5..486b1da 100644
> > > > --- a/drivers/clk/clk.c
> > > > +++ b/drivers/clk/clk.c
> > > > @@ -46,6 +46,21 @@ static struct clk_core *clk_core_lookup(const char *name);
> > > >  
> > > >  /***    private data structures    ***/
> > > >  
> > > > +/**
> > > > + * struct critical -   Provides 'play' over critical clocks.  A clock can be
> > > > + *                     marked as critical, meaning that it should not be
> > > > + *                     disabled.  However, if a driver which is aware of the
> > > > + *                     critical behaviour wants to control it, it can do so
> > > > + *                     using clk_enable_critical() and clk_disable_critical().
> > > > + *
> > > > + * @enabled    Is clock critical?  Once set, doesn't change
> > > > + * @leave_on   Self explanatory.  Can be disabled by knowledgeable drivers
> > > 
> > > Not self explanatory. I need this explained to me. What does leave_on
> > > do? Better yet, what would happen if leave_on did not exist?
> > > 
> > > > + */
> > > > +struct critical {
> > > > +       bool enabled;
> > > > +       bool leave_on;
> > > > +};
> > > > +
> > > >  struct clk_core {
> > > >         const char              *name;
> > > >         const struct clk_ops    *ops;
> > > > @@ -75,6 +90,7 @@ struct clk_core {
> > > >         struct dentry           *dentry;
> > > >  #endif
> > > >         struct kref             ref;
> > > > +       struct critical         critical;
> > > >  };
> > > >  
> > > >  struct clk {
> > > > @@ -995,6 +1011,10 @@ static void clk_core_disable(struct clk_core *clk)
> > > >         if (WARN_ON(clk->enable_count == 0))
> > > >                 return;
> > > >  
> > > > +       /* Refuse to turn off a critical clock */
> > > > +       if (clk->enable_count == 1 && clk->critical.leave_on)
> > > > +               return;
> > > 
> > > How do we get to this point? clk_enable_critical actually calls
> > > clk_enable, thus incrementing the enable_count. The only time that we
> > > could hit the above case is if,
> > > 
> > > a) there is an imbalance in clk_enable and clk_disable calls. If this is
> > > the case then the drivers need to be fixed. Or better yet some
> > > infrastructure to catch that, now that we have per-user struct clk
> > > cookies.
> > > 
> > > b) a driver knowingly calls clk_enable_critical(foo) and then regular,
> > > old clk_disable(foo). But why would a driver do that?
> > > 
> > > It might be that I am missing the point here, so please feel free to
> > > clue me in.
> > 
> > This check behaves in a very similar to the WARN() above.  It's more
> > of a fail-safe.  If all drivers are behaving properly, then it
> > shouldn't ever be true.  If they're not, it prevents an incorrectly
> > written driver from irrecoverably crippling the system.
> 
> Then this check should be replaced with a generic approach that refuses
> to honor imbalances anyways. Below are two patches that probably resolve
> the issue of badly behaving drivers that cause enable imbalances.

Your patch should make the requirement for this check moot, so it can
probably be removed.

> > As I said in the other mail.  We can do without these 3 new wrappers.
> > We _could_ just write a driver which only calls clk_enable() _after_
> > it calls clk_disable(), a kind of intentional unbalance and it would
> > do that same thing.
> 
> This naive approach will not work with per-user imbalance tracking.

Steady on.  I said we "_could_", that that I think it's a good idea.

I think it's a bad idea, which is why I wrote this set. ;)

> > However, what we're trying to do here is provide
> > a proper API, so we can see at first glance what the 'knowledgeable'
> > driver is trying to do and not have someone attempt to submit a 'fix'
> > which calls clk_enable() or something.
> 
> We'll need some type of api for sure for the handoff.

This set will not trigger your new checks.  The clocks will be in
perfect ballance becuase a reference will be taken at start-up.

Again:

start-up:
  clk_prepare_enable()

knowlegable_driver_probe:
  clk_get()

knowlegable_driver_gate_clk:
  clk_disable_critical()

knowlegable_driver_ungate_clk:
  clk_enable_critical()

knowlegable_driver_remove:
  clk_put()

> From 3599ed206da9ce770bfafcfd95cbb9a03ac44473 Mon Sep 17 00:00:00 2001
> From: Michael Turquette <mturquette@baylibre.com>
> Date: Wed, 29 Jul 2015 18:22:45 -0700
> Subject: [PATCH 1/2] clk: per-user clk prepare & enable ref counts
> 
> This patch adds prepare and enable reference counts for the per-user
> handles that clock consumers have for a clock node. This patch warns if
> an imbalance occurs while trying to disable or unprepare a clock and
> aborts, leaving the hardware unaffected.
> 
> Signed-off-by: Michael Turquette <mturquette@baylibre.com>
> ---
>  drivers/clk/clk.c | 10 ++++++++++
>  1 file changed, 10 insertions(+)
> 
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> index 898052e..72feee9 100644
> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> @@ -84,6 +84,8 @@ struct clk {
>  	unsigned long min_rate;
>  	unsigned long max_rate;
>  	struct hlist_node clks_node;
> +	unsigned int enable_count;
> +	unsigned int prepare_count;
>  };
>  
>  /***           locking             ***/
> @@ -600,6 +602,9 @@ void clk_unprepare(struct clk *clk)
>  		return;
>  
>  	clk_prepare_lock();
> +	if (WARN_ON(clk->prepare_count == 0))
> +		return;
> +	clk->prepare_count--;
>  	clk_core_unprepare(clk->core);
>  	clk_prepare_unlock();
>  }
> @@ -657,6 +662,7 @@ int clk_prepare(struct clk *clk)
>  		return 0;
>  
>  	clk_prepare_lock();
> +	clk->prepare_count++;
>  	ret = clk_core_prepare(clk->core);
>  	clk_prepare_unlock();
>  
> @@ -707,6 +713,9 @@ void clk_disable(struct clk *clk)
>  		return;
>  
>  	flags = clk_enable_lock();
> +	if (WARN_ON(clk->enable_count == 0))
> +		return;
> +	clk->enable_count--;
>  	clk_core_disable(clk->core);
>  	clk_enable_unlock(flags);
>  }
> @@ -769,6 +778,7 @@ int clk_enable(struct clk *clk)
>  		return 0;
>  
>  	flags = clk_enable_lock();
> +	clk->enable_count++;
>  	ret = clk_core_enable(clk->core);
>  	clk_enable_unlock(flags);
>  

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org ? Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

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

* Re: [PATCH v7 3/5] clk: Supply the critical clock {init, enable, disable} framework
  2015-07-31  9:02           ` Lee Jones
  (?)
@ 2015-08-01  0:59             ` Michael Turquette
  -1 siblings, 0 replies; 93+ messages in thread
From: Michael Turquette @ 2015-08-01  0:59 UTC (permalink / raw)
  To: Lee Jones
  Cc: devicetree, kernel, s.hauer, sboyd, linux-kernel, geert,
	maxime.ripard, linux-clk, linux-arm-kernel

Quoting Lee Jones (2015-07-31 02:02:19)
> On Thu, 30 Jul 2015, Michael Turquette wrote:
> 
> > Quoting Lee Jones (2015-07-30 04:17:47)
> > > On Wed, 29 Jul 2015, Michael Turquette wrote:
> > > 
> > > > Hi Lee,
> > > > 
> > > > + linux-clk ml
> > > > 
> > > > Quoting Lee Jones (2015-07-22 06:04:13)
> > > > > These new API calls will firstly provide a mechanisms to tag a clock as
> > > > > critical and secondly allow any knowledgeable driver to (un)gate clocks,
> > > > > even if they are marked as critical.
> > > > > 
> > > > > Suggested-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> > > > > Signed-off-by: Lee Jones <lee.jones@linaro.org>
> > > > > ---
> > > > >  drivers/clk/clk.c            | 45 ++++++++++++++++++++++++++++++++++++++++++++
> > > > >  include/linux/clk-provider.h |  2 ++
> > > > >  include/linux/clk.h          | 30 +++++++++++++++++++++++++++++
> > > > >  3 files changed, 77 insertions(+)
> > > > > 
> > > > > diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> > > > > index 61c3fc5..486b1da 100644
> > > > > --- a/drivers/clk/clk.c
> > > > > +++ b/drivers/clk/clk.c
> > > > > @@ -46,6 +46,21 @@ static struct clk_core *clk_core_lookup(const char *name);
> > > > >  
> > > > >  /***    private data structures    ***/
> > > > >  
> > > > > +/**
> > > > > + * struct critical -   Provides 'play' over critical clocks.  A clock can be
> > > > > + *                     marked as critical, meaning that it should not be
> > > > > + *                     disabled.  However, if a driver which is aware of the
> > > > > + *                     critical behaviour wants to control it, it can do so
> > > > > + *                     using clk_enable_critical() and clk_disable_critical().
> > > > > + *
> > > > > + * @enabled    Is clock critical?  Once set, doesn't change
> > > > > + * @leave_on   Self explanatory.  Can be disabled by knowledgeable drivers
> > > > 
> > > > Not self explanatory. I need this explained to me. What does leave_on
> > > > do? Better yet, what would happen if leave_on did not exist?
> > > > 
> > > > > + */
> > > > > +struct critical {
> > > > > +       bool enabled;
> > > > > +       bool leave_on;
> > > > > +};
> > > > > +
> > > > >  struct clk_core {
> > > > >         const char              *name;
> > > > >         const struct clk_ops    *ops;
> > > > > @@ -75,6 +90,7 @@ struct clk_core {
> > > > >         struct dentry           *dentry;
> > > > >  #endif
> > > > >         struct kref             ref;
> > > > > +       struct critical         critical;
> > > > >  };
> > > > >  
> > > > >  struct clk {
> > > > > @@ -995,6 +1011,10 @@ static void clk_core_disable(struct clk_core *clk)
> > > > >         if (WARN_ON(clk->enable_count == 0))
> > > > >                 return;
> > > > >  
> > > > > +       /* Refuse to turn off a critical clock */
> > > > > +       if (clk->enable_count == 1 && clk->critical.leave_on)
> > > > > +               return;
> > > > 
> > > > How do we get to this point? clk_enable_critical actually calls
> > > > clk_enable, thus incrementing the enable_count. The only time that we
> > > > could hit the above case is if,
> > > > 
> > > > a) there is an imbalance in clk_enable and clk_disable calls. If this is
> > > > the case then the drivers need to be fixed. Or better yet some
> > > > infrastructure to catch that, now that we have per-user struct clk
> > > > cookies.
> > > > 
> > > > b) a driver knowingly calls clk_enable_critical(foo) and then regular,
> > > > old clk_disable(foo). But why would a driver do that?
> > > > 
> > > > It might be that I am missing the point here, so please feel free to
> > > > clue me in.
> > > 
> > > This check behaves in a very similar to the WARN() above.  It's more
> > > of a fail-safe.  If all drivers are behaving properly, then it
> > > shouldn't ever be true.  If they're not, it prevents an incorrectly
> > > written driver from irrecoverably crippling the system.
> > 
> > Then this check should be replaced with a generic approach that refuses
> > to honor imbalances anyways. Below are two patches that probably resolve
> > the issue of badly behaving drivers that cause enable imbalances.
> 
> Your patch should make the requirement for this check moot, so it can
> probably be removed.
> 
> > > As I said in the other mail.  We can do without these 3 new wrappers.
> > > We _could_ just write a driver which only calls clk_enable() _after_
> > > it calls clk_disable(), a kind of intentional unbalance and it would
> > > do that same thing.
> > 
> > This naive approach will not work with per-user imbalance tracking.
> 
> Steady on.  I said we "_could_", that that I think it's a good idea.
> 
> I think it's a bad idea, which is why I wrote this set. ;)
> 
> > > However, what we're trying to do here is provide
> > > a proper API, so we can see at first glance what the 'knowledgeable'
> > > driver is trying to do and not have someone attempt to submit a 'fix'
> > > which calls clk_enable() or something.
> > 
> > We'll need some type of api for sure for the handoff.
> 
> This set will not trigger your new checks.  The clocks will be in
> perfect ballance becuase a reference will be taken at start-up.
> 
> Again:
> 
> start-up:
>   clk_prepare_enable()
> 
> knowlegable_driver_probe:
>   clk_get()
> 
> knowlegable_driver_gate_clk:
>   clk_disable_critical()

The call to clk_disable() nested inside clk_disable_critical will fail
with the new checks. This is because the struct clk instance will be
different from one used in your "start-up" section above. clk_get()
creates a unique struct clk every time you call it.

Put another way, a unique user of a clock cannot call clk_disable() when
the per-user enable_count is 0.

Furthermore, there is no way that I will ever be happy with a technique
that requires calling disable prior to an enable within a driver. That
goes against a long-standing api designs and is confusing as hell to
driver authors.

Regards,
Mike

> 
> knowlegable_driver_ungate_clk:
>   clk_enable_critical()
> 
> knowlegable_driver_remove:
>   clk_put()
> 
> > From 3599ed206da9ce770bfafcfd95cbb9a03ac44473 Mon Sep 17 00:00:00 2001
> > From: Michael Turquette <mturquette@baylibre.com>
> > Date: Wed, 29 Jul 2015 18:22:45 -0700
> > Subject: [PATCH 1/2] clk: per-user clk prepare & enable ref counts
> > 
> > This patch adds prepare and enable reference counts for the per-user
> > handles that clock consumers have for a clock node. This patch warns if
> > an imbalance occurs while trying to disable or unprepare a clock and
> > aborts, leaving the hardware unaffected.
> > 
> > Signed-off-by: Michael Turquette <mturquette@baylibre.com>
> > ---
> >  drivers/clk/clk.c | 10 ++++++++++
> >  1 file changed, 10 insertions(+)
> > 
> > diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> > index 898052e..72feee9 100644
> > --- a/drivers/clk/clk.c
> > +++ b/drivers/clk/clk.c
> > @@ -84,6 +84,8 @@ struct clk {
> >       unsigned long min_rate;
> >       unsigned long max_rate;
> >       struct hlist_node clks_node;
> > +     unsigned int enable_count;
> > +     unsigned int prepare_count;
> >  };
> >  
> >  /***           locking             ***/
> > @@ -600,6 +602,9 @@ void clk_unprepare(struct clk *clk)
> >               return;
> >  
> >       clk_prepare_lock();
> > +     if (WARN_ON(clk->prepare_count == 0))
> > +             return;
> > +     clk->prepare_count--;
> >       clk_core_unprepare(clk->core);
> >       clk_prepare_unlock();
> >  }
> > @@ -657,6 +662,7 @@ int clk_prepare(struct clk *clk)
> >               return 0;
> >  
> >       clk_prepare_lock();
> > +     clk->prepare_count++;
> >       ret = clk_core_prepare(clk->core);
> >       clk_prepare_unlock();
> >  
> > @@ -707,6 +713,9 @@ void clk_disable(struct clk *clk)
> >               return;
> >  
> >       flags = clk_enable_lock();
> > +     if (WARN_ON(clk->enable_count == 0))
> > +             return;
> > +     clk->enable_count--;
> >       clk_core_disable(clk->core);
> >       clk_enable_unlock(flags);
> >  }
> > @@ -769,6 +778,7 @@ int clk_enable(struct clk *clk)
> >               return 0;
> >  
> >       flags = clk_enable_lock();
> > +     clk->enable_count++;
> >       ret = clk_core_enable(clk->core);
> >       clk_enable_unlock(flags);
> >  
> 
> -- 
> Lee Jones
> Linaro STMicroelectronics Landing Team Lead
> Linaro.org │ Open source software for ARM SoCs
> Follow Linaro: Facebook | Twitter | Blog
> --
> To unsubscribe from this list: send the line "unsubscribe linux-clk" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v7 3/5] clk: Supply the critical clock {init, enable, disable} framework
@ 2015-08-01  0:59             ` Michael Turquette
  0 siblings, 0 replies; 93+ messages in thread
From: Michael Turquette @ 2015-08-01  0:59 UTC (permalink / raw)
  To: Lee Jones
  Cc: devicetree, kernel, s.hauer, sboyd, linux-kernel, geert,
	maxime.ripard, linux-clk, linux-arm-kernel

UXVvdGluZyBMZWUgSm9uZXMgKDIwMTUtMDctMzEgMDI6MDI6MTkpCj4gT24gVGh1LCAzMCBKdWwg
MjAxNSwgTWljaGFlbCBUdXJxdWV0dGUgd3JvdGU6Cj4gCj4gPiBRdW90aW5nIExlZSBKb25lcyAo
MjAxNS0wNy0zMCAwNDoxNzo0NykKPiA+ID4gT24gV2VkLCAyOSBKdWwgMjAxNSwgTWljaGFlbCBU
dXJxdWV0dGUgd3JvdGU6Cj4gPiA+IAo+ID4gPiA+IEhpIExlZSwKPiA+ID4gPiAKPiA+ID4gPiAr
IGxpbnV4LWNsayBtbAo+ID4gPiA+IAo+ID4gPiA+IFF1b3RpbmcgTGVlIEpvbmVzICgyMDE1LTA3
LTIyIDA2OjA0OjEzKQo+ID4gPiA+ID4gVGhlc2UgbmV3IEFQSSBjYWxscyB3aWxsIGZpcnN0bHkg
cHJvdmlkZSBhIG1lY2hhbmlzbXMgdG8gdGFnIGEgY2xvY2sgYXMKPiA+ID4gPiA+IGNyaXRpY2Fs
IGFuZCBzZWNvbmRseSBhbGxvdyBhbnkga25vd2xlZGdlYWJsZSBkcml2ZXIgdG8gKHVuKWdhdGUg
Y2xvY2tzLAo+ID4gPiA+ID4gZXZlbiBpZiB0aGV5IGFyZSBtYXJrZWQgYXMgY3JpdGljYWwuCj4g
PiA+ID4gPiAKPiA+ID4gPiA+IFN1Z2dlc3RlZC1ieTogTWF4aW1lIFJpcGFyZCA8bWF4aW1lLnJp
cGFyZEBmcmVlLWVsZWN0cm9ucy5jb20+Cj4gPiA+ID4gPiBTaWduZWQtb2ZmLWJ5OiBMZWUgSm9u
ZXMgPGxlZS5qb25lc0BsaW5hcm8ub3JnPgo+ID4gPiA+ID4gLS0tCj4gPiA+ID4gPiAgZHJpdmVy
cy9jbGsvY2xrLmMgICAgICAgICAgICB8IDQ1ICsrKysrKysrKysrKysrKysrKysrKysrKysrKysr
KysrKysrKysrKysrKysrCj4gPiA+ID4gPiAgaW5jbHVkZS9saW51eC9jbGstcHJvdmlkZXIuaCB8
ICAyICsrCj4gPiA+ID4gPiAgaW5jbHVkZS9saW51eC9jbGsuaCAgICAgICAgICB8IDMwICsrKysr
KysrKysrKysrKysrKysrKysrKysrKysrCj4gPiA+ID4gPiAgMyBmaWxlcyBjaGFuZ2VkLCA3NyBp
bnNlcnRpb25zKCspCj4gPiA+ID4gPiAKPiA+ID4gPiA+IGRpZmYgLS1naXQgYS9kcml2ZXJzL2Ns
ay9jbGsuYyBiL2RyaXZlcnMvY2xrL2Nsay5jCj4gPiA+ID4gPiBpbmRleCA2MWMzZmM1Li40ODZi
MWRhIDEwMDY0NAo+ID4gPiA+ID4gLS0tIGEvZHJpdmVycy9jbGsvY2xrLmMKPiA+ID4gPiA+ICsr
KyBiL2RyaXZlcnMvY2xrL2Nsay5jCj4gPiA+ID4gPiBAQCAtNDYsNiArNDYsMjEgQEAgc3RhdGlj
IHN0cnVjdCBjbGtfY29yZSAqY2xrX2NvcmVfbG9va3VwKGNvbnN0IGNoYXIgKm5hbWUpOwo+ID4g
PiA+ID4gIAo+ID4gPiA+ID4gIC8qKiogICAgcHJpdmF0ZSBkYXRhIHN0cnVjdHVyZXMgICAgKioq
Lwo+ID4gPiA+ID4gIAo+ID4gPiA+ID4gKy8qKgo+ID4gPiA+ID4gKyAqIHN0cnVjdCBjcml0aWNh
bCAtICAgUHJvdmlkZXMgJ3BsYXknIG92ZXIgY3JpdGljYWwgY2xvY2tzLiAgQSBjbG9jayBjYW4g
YmUKPiA+ID4gPiA+ICsgKiAgICAgICAgICAgICAgICAgICAgIG1hcmtlZCBhcyBjcml0aWNhbCwg
bWVhbmluZyB0aGF0IGl0IHNob3VsZCBub3QgYmUKPiA+ID4gPiA+ICsgKiAgICAgICAgICAgICAg
ICAgICAgIGRpc2FibGVkLiAgSG93ZXZlciwgaWYgYSBkcml2ZXIgd2hpY2ggaXMgYXdhcmUgb2Yg
dGhlCj4gPiA+ID4gPiArICogICAgICAgICAgICAgICAgICAgICBjcml0aWNhbCBiZWhhdmlvdXIg
d2FudHMgdG8gY29udHJvbCBpdCwgaXQgY2FuIGRvIHNvCj4gPiA+ID4gPiArICogICAgICAgICAg
ICAgICAgICAgICB1c2luZyBjbGtfZW5hYmxlX2NyaXRpY2FsKCkgYW5kIGNsa19kaXNhYmxlX2Ny
aXRpY2FsKCkuCj4gPiA+ID4gPiArICoKPiA+ID4gPiA+ICsgKiBAZW5hYmxlZCAgICBJcyBjbG9j
ayBjcml0aWNhbD8gIE9uY2Ugc2V0LCBkb2Vzbid0IGNoYW5nZQo+ID4gPiA+ID4gKyAqIEBsZWF2
ZV9vbiAgIFNlbGYgZXhwbGFuYXRvcnkuICBDYW4gYmUgZGlzYWJsZWQgYnkga25vd2xlZGdlYWJs
ZSBkcml2ZXJzCj4gPiA+ID4gCj4gPiA+ID4gTm90IHNlbGYgZXhwbGFuYXRvcnkuIEkgbmVlZCB0
aGlzIGV4cGxhaW5lZCB0byBtZS4gV2hhdCBkb2VzIGxlYXZlX29uCj4gPiA+ID4gZG8/IEJldHRl
ciB5ZXQsIHdoYXQgd291bGQgaGFwcGVuIGlmIGxlYXZlX29uIGRpZCBub3QgZXhpc3Q/Cj4gPiA+
ID4gCj4gPiA+ID4gPiArICovCj4gPiA+ID4gPiArc3RydWN0IGNyaXRpY2FsIHsKPiA+ID4gPiA+
ICsgICAgICAgYm9vbCBlbmFibGVkOwo+ID4gPiA+ID4gKyAgICAgICBib29sIGxlYXZlX29uOwo+
ID4gPiA+ID4gK307Cj4gPiA+ID4gPiArCj4gPiA+ID4gPiAgc3RydWN0IGNsa19jb3JlIHsKPiA+
ID4gPiA+ICAgICAgICAgY29uc3QgY2hhciAgICAgICAgICAgICAgKm5hbWU7Cj4gPiA+ID4gPiAg
ICAgICAgIGNvbnN0IHN0cnVjdCBjbGtfb3BzICAgICpvcHM7Cj4gPiA+ID4gPiBAQCAtNzUsNiAr
OTAsNyBAQCBzdHJ1Y3QgY2xrX2NvcmUgewo+ID4gPiA+ID4gICAgICAgICBzdHJ1Y3QgZGVudHJ5
ICAgICAgICAgICAqZGVudHJ5Owo+ID4gPiA+ID4gICNlbmRpZgo+ID4gPiA+ID4gICAgICAgICBz
dHJ1Y3Qga3JlZiAgICAgICAgICAgICByZWY7Cj4gPiA+ID4gPiArICAgICAgIHN0cnVjdCBjcml0
aWNhbCAgICAgICAgIGNyaXRpY2FsOwo+ID4gPiA+ID4gIH07Cj4gPiA+ID4gPiAgCj4gPiA+ID4g
PiAgc3RydWN0IGNsayB7Cj4gPiA+ID4gPiBAQCAtOTk1LDYgKzEwMTEsMTAgQEAgc3RhdGljIHZv
aWQgY2xrX2NvcmVfZGlzYWJsZShzdHJ1Y3QgY2xrX2NvcmUgKmNsaykKPiA+ID4gPiA+ICAgICAg
ICAgaWYgKFdBUk5fT04oY2xrLT5lbmFibGVfY291bnQgPT0gMCkpCj4gPiA+ID4gPiAgICAgICAg
ICAgICAgICAgcmV0dXJuOwo+ID4gPiA+ID4gIAo+ID4gPiA+ID4gKyAgICAgICAvKiBSZWZ1c2Ug
dG8gdHVybiBvZmYgYSBjcml0aWNhbCBjbG9jayAqLwo+ID4gPiA+ID4gKyAgICAgICBpZiAoY2xr
LT5lbmFibGVfY291bnQgPT0gMSAmJiBjbGstPmNyaXRpY2FsLmxlYXZlX29uKQo+ID4gPiA+ID4g
KyAgICAgICAgICAgICAgIHJldHVybjsKPiA+ID4gPiAKPiA+ID4gPiBIb3cgZG8gd2UgZ2V0IHRv
IHRoaXMgcG9pbnQ/IGNsa19lbmFibGVfY3JpdGljYWwgYWN0dWFsbHkgY2FsbHMKPiA+ID4gPiBj
bGtfZW5hYmxlLCB0aHVzIGluY3JlbWVudGluZyB0aGUgZW5hYmxlX2NvdW50LiBUaGUgb25seSB0
aW1lIHRoYXQgd2UKPiA+ID4gPiBjb3VsZCBoaXQgdGhlIGFib3ZlIGNhc2UgaXMgaWYsCj4gPiA+
ID4gCj4gPiA+ID4gYSkgdGhlcmUgaXMgYW4gaW1iYWxhbmNlIGluIGNsa19lbmFibGUgYW5kIGNs
a19kaXNhYmxlIGNhbGxzLiBJZiB0aGlzIGlzCj4gPiA+ID4gdGhlIGNhc2UgdGhlbiB0aGUgZHJp
dmVycyBuZWVkIHRvIGJlIGZpeGVkLiBPciBiZXR0ZXIgeWV0IHNvbWUKPiA+ID4gPiBpbmZyYXN0
cnVjdHVyZSB0byBjYXRjaCB0aGF0LCBub3cgdGhhdCB3ZSBoYXZlIHBlci11c2VyIHN0cnVjdCBj
bGsKPiA+ID4gPiBjb29raWVzLgo+ID4gPiA+IAo+ID4gPiA+IGIpIGEgZHJpdmVyIGtub3dpbmds
eSBjYWxscyBjbGtfZW5hYmxlX2NyaXRpY2FsKGZvbykgYW5kIHRoZW4gcmVndWxhciwKPiA+ID4g
PiBvbGQgY2xrX2Rpc2FibGUoZm9vKS4gQnV0IHdoeSB3b3VsZCBhIGRyaXZlciBkbyB0aGF0Pwo+
ID4gPiA+IAo+ID4gPiA+IEl0IG1pZ2h0IGJlIHRoYXQgSSBhbSBtaXNzaW5nIHRoZSBwb2ludCBo
ZXJlLCBzbyBwbGVhc2UgZmVlbCBmcmVlIHRvCj4gPiA+ID4gY2x1ZSBtZSBpbi4KPiA+ID4gCj4g
PiA+IFRoaXMgY2hlY2sgYmVoYXZlcyBpbiBhIHZlcnkgc2ltaWxhciB0byB0aGUgV0FSTigpIGFi
b3ZlLiAgSXQncyBtb3JlCj4gPiA+IG9mIGEgZmFpbC1zYWZlLiAgSWYgYWxsIGRyaXZlcnMgYXJl
IGJlaGF2aW5nIHByb3Blcmx5LCB0aGVuIGl0Cj4gPiA+IHNob3VsZG4ndCBldmVyIGJlIHRydWUu
ICBJZiB0aGV5J3JlIG5vdCwgaXQgcHJldmVudHMgYW4gaW5jb3JyZWN0bHkKPiA+ID4gd3JpdHRl
biBkcml2ZXIgZnJvbSBpcnJlY292ZXJhYmx5IGNyaXBwbGluZyB0aGUgc3lzdGVtLgo+ID4gCj4g
PiBUaGVuIHRoaXMgY2hlY2sgc2hvdWxkIGJlIHJlcGxhY2VkIHdpdGggYSBnZW5lcmljIGFwcHJv
YWNoIHRoYXQgcmVmdXNlcwo+ID4gdG8gaG9ub3IgaW1iYWxhbmNlcyBhbnl3YXlzLiBCZWxvdyBh
cmUgdHdvIHBhdGNoZXMgdGhhdCBwcm9iYWJseSByZXNvbHZlCj4gPiB0aGUgaXNzdWUgb2YgYmFk
bHkgYmVoYXZpbmcgZHJpdmVycyB0aGF0IGNhdXNlIGVuYWJsZSBpbWJhbGFuY2VzLgo+IAo+IFlv
dXIgcGF0Y2ggc2hvdWxkIG1ha2UgdGhlIHJlcXVpcmVtZW50IGZvciB0aGlzIGNoZWNrIG1vb3Qs
IHNvIGl0IGNhbgo+IHByb2JhYmx5IGJlIHJlbW92ZWQuCj4gCj4gPiA+IEFzIEkgc2FpZCBpbiB0
aGUgb3RoZXIgbWFpbC4gIFdlIGNhbiBkbyB3aXRob3V0IHRoZXNlIDMgbmV3IHdyYXBwZXJzLgo+
ID4gPiBXZSBfY291bGRfIGp1c3Qgd3JpdGUgYSBkcml2ZXIgd2hpY2ggb25seSBjYWxscyBjbGtf
ZW5hYmxlKCkgX2FmdGVyXwo+ID4gPiBpdCBjYWxscyBjbGtfZGlzYWJsZSgpLCBhIGtpbmQgb2Yg
aW50ZW50aW9uYWwgdW5iYWxhbmNlIGFuZCBpdCB3b3VsZAo+ID4gPiBkbyB0aGF0IHNhbWUgdGhp
bmcuCj4gPiAKPiA+IFRoaXMgbmFpdmUgYXBwcm9hY2ggd2lsbCBub3Qgd29yayB3aXRoIHBlci11
c2VyIGltYmFsYW5jZSB0cmFja2luZy4KPiAKPiBTdGVhZHkgb24uICBJIHNhaWQgd2UgIl9jb3Vs
ZF8iLCB0aGF0IHRoYXQgSSB0aGluayBpdCdzIGEgZ29vZCBpZGVhLgo+IAo+IEkgdGhpbmsgaXQn
cyBhIGJhZCBpZGVhLCB3aGljaCBpcyB3aHkgSSB3cm90ZSB0aGlzIHNldC4gOykKPiAKPiA+ID4g
SG93ZXZlciwgd2hhdCB3ZSdyZSB0cnlpbmcgdG8gZG8gaGVyZSBpcyBwcm92aWRlCj4gPiA+IGEg
cHJvcGVyIEFQSSwgc28gd2UgY2FuIHNlZSBhdCBmaXJzdCBnbGFuY2Ugd2hhdCB0aGUgJ2tub3ds
ZWRnZWFibGUnCj4gPiA+IGRyaXZlciBpcyB0cnlpbmcgdG8gZG8gYW5kIG5vdCBoYXZlIHNvbWVv
bmUgYXR0ZW1wdCB0byBzdWJtaXQgYSAnZml4Jwo+ID4gPiB3aGljaCBjYWxscyBjbGtfZW5hYmxl
KCkgb3Igc29tZXRoaW5nLgo+ID4gCj4gPiBXZSdsbCBuZWVkIHNvbWUgdHlwZSBvZiBhcGkgZm9y
IHN1cmUgZm9yIHRoZSBoYW5kb2ZmLgo+IAo+IFRoaXMgc2V0IHdpbGwgbm90IHRyaWdnZXIgeW91
ciBuZXcgY2hlY2tzLiAgVGhlIGNsb2NrcyB3aWxsIGJlIGluCj4gcGVyZmVjdCBiYWxsYW5jZSBi
ZWN1YXNlIGEgcmVmZXJlbmNlIHdpbGwgYmUgdGFrZW4gYXQgc3RhcnQtdXAuCj4gCj4gQWdhaW46
Cj4gCj4gc3RhcnQtdXA6Cj4gICBjbGtfcHJlcGFyZV9lbmFibGUoKQo+IAo+IGtub3dsZWdhYmxl
X2RyaXZlcl9wcm9iZToKPiAgIGNsa19nZXQoKQo+IAo+IGtub3dsZWdhYmxlX2RyaXZlcl9nYXRl
X2NsazoKPiAgIGNsa19kaXNhYmxlX2NyaXRpY2FsKCkKClRoZSBjYWxsIHRvIGNsa19kaXNhYmxl
KCkgbmVzdGVkIGluc2lkZSBjbGtfZGlzYWJsZV9jcml0aWNhbCB3aWxsIGZhaWwKd2l0aCB0aGUg
bmV3IGNoZWNrcy4gVGhpcyBpcyBiZWNhdXNlIHRoZSBzdHJ1Y3QgY2xrIGluc3RhbmNlIHdpbGwg
YmUKZGlmZmVyZW50IGZyb20gb25lIHVzZWQgaW4geW91ciAic3RhcnQtdXAiIHNlY3Rpb24gYWJv
dmUuIGNsa19nZXQoKQpjcmVhdGVzIGEgdW5pcXVlIHN0cnVjdCBjbGsgZXZlcnkgdGltZSB5b3Ug
Y2FsbCBpdC4KClB1dCBhbm90aGVyIHdheSwgYSB1bmlxdWUgdXNlciBvZiBhIGNsb2NrIGNhbm5v
dCBjYWxsIGNsa19kaXNhYmxlKCkgd2hlbgp0aGUgcGVyLXVzZXIgZW5hYmxlX2NvdW50IGlzIDAu
CgpGdXJ0aGVybW9yZSwgdGhlcmUgaXMgbm8gd2F5IHRoYXQgSSB3aWxsIGV2ZXIgYmUgaGFwcHkg
d2l0aCBhIHRlY2huaXF1ZQp0aGF0IHJlcXVpcmVzIGNhbGxpbmcgZGlzYWJsZSBwcmlvciB0byBh
biBlbmFibGUgd2l0aGluIGEgZHJpdmVyLiBUaGF0CmdvZXMgYWdhaW5zdCBhIGxvbmctc3RhbmRp
bmcgYXBpIGRlc2lnbnMgYW5kIGlzIGNvbmZ1c2luZyBhcyBoZWxsIHRvCmRyaXZlciBhdXRob3Jz
LgoKUmVnYXJkcywKTWlrZQoKPiAKPiBrbm93bGVnYWJsZV9kcml2ZXJfdW5nYXRlX2NsazoKPiAg
IGNsa19lbmFibGVfY3JpdGljYWwoKQo+IAo+IGtub3dsZWdhYmxlX2RyaXZlcl9yZW1vdmU6Cj4g
ICBjbGtfcHV0KCkKPiAKPiA+IEZyb20gMzU5OWVkMjA2ZGE5Y2U3NzBiZmFmY2ZkOTVjYmI5YTAz
YWM0NDQ3MyBNb24gU2VwIDE3IDAwOjAwOjAwIDIwMDEKPiA+IEZyb206IE1pY2hhZWwgVHVycXVl
dHRlIDxtdHVycXVldHRlQGJheWxpYnJlLmNvbT4KPiA+IERhdGU6IFdlZCwgMjkgSnVsIDIwMTUg
MTg6MjI6NDUgLTA3MDAKPiA+IFN1YmplY3Q6IFtQQVRDSCAxLzJdIGNsazogcGVyLXVzZXIgY2xr
IHByZXBhcmUgJiBlbmFibGUgcmVmIGNvdW50cwo+ID4gCj4gPiBUaGlzIHBhdGNoIGFkZHMgcHJl
cGFyZSBhbmQgZW5hYmxlIHJlZmVyZW5jZSBjb3VudHMgZm9yIHRoZSBwZXItdXNlcgo+ID4gaGFu
ZGxlcyB0aGF0IGNsb2NrIGNvbnN1bWVycyBoYXZlIGZvciBhIGNsb2NrIG5vZGUuIFRoaXMgcGF0
Y2ggd2FybnMgaWYKPiA+IGFuIGltYmFsYW5jZSBvY2N1cnMgd2hpbGUgdHJ5aW5nIHRvIGRpc2Fi
bGUgb3IgdW5wcmVwYXJlIGEgY2xvY2sgYW5kCj4gPiBhYm9ydHMsIGxlYXZpbmcgdGhlIGhhcmR3
YXJlIHVuYWZmZWN0ZWQuCj4gPiAKPiA+IFNpZ25lZC1vZmYtYnk6IE1pY2hhZWwgVHVycXVldHRl
IDxtdHVycXVldHRlQGJheWxpYnJlLmNvbT4KPiA+IC0tLQo+ID4gIGRyaXZlcnMvY2xrL2Nsay5j
IHwgMTAgKysrKysrKysrKwo+ID4gIDEgZmlsZSBjaGFuZ2VkLCAxMCBpbnNlcnRpb25zKCspCj4g
PiAKPiA+IGRpZmYgLS1naXQgYS9kcml2ZXJzL2Nsay9jbGsuYyBiL2RyaXZlcnMvY2xrL2Nsay5j
Cj4gPiBpbmRleCA4OTgwNTJlLi43MmZlZWU5IDEwMDY0NAo+ID4gLS0tIGEvZHJpdmVycy9jbGsv
Y2xrLmMKPiA+ICsrKyBiL2RyaXZlcnMvY2xrL2Nsay5jCj4gPiBAQCAtODQsNiArODQsOCBAQCBz
dHJ1Y3QgY2xrIHsKPiA+ICAgICAgIHVuc2lnbmVkIGxvbmcgbWluX3JhdGU7Cj4gPiAgICAgICB1
bnNpZ25lZCBsb25nIG1heF9yYXRlOwo+ID4gICAgICAgc3RydWN0IGhsaXN0X25vZGUgY2xrc19u
b2RlOwo+ID4gKyAgICAgdW5zaWduZWQgaW50IGVuYWJsZV9jb3VudDsKPiA+ICsgICAgIHVuc2ln
bmVkIGludCBwcmVwYXJlX2NvdW50Owo+ID4gIH07Cj4gPiAgCj4gPiAgLyoqKiAgICAgICAgICAg
bG9ja2luZyAgICAgICAgICAgICAqKiovCj4gPiBAQCAtNjAwLDYgKzYwMiw5IEBAIHZvaWQgY2xr
X3VucHJlcGFyZShzdHJ1Y3QgY2xrICpjbGspCj4gPiAgICAgICAgICAgICAgIHJldHVybjsKPiA+
ICAKPiA+ICAgICAgIGNsa19wcmVwYXJlX2xvY2soKTsKPiA+ICsgICAgIGlmIChXQVJOX09OKGNs
ay0+cHJlcGFyZV9jb3VudCA9PSAwKSkKPiA+ICsgICAgICAgICAgICAgcmV0dXJuOwo+ID4gKyAg
ICAgY2xrLT5wcmVwYXJlX2NvdW50LS07Cj4gPiAgICAgICBjbGtfY29yZV91bnByZXBhcmUoY2xr
LT5jb3JlKTsKPiA+ICAgICAgIGNsa19wcmVwYXJlX3VubG9jaygpOwo+ID4gIH0KPiA+IEBAIC02
NTcsNiArNjYyLDcgQEAgaW50IGNsa19wcmVwYXJlKHN0cnVjdCBjbGsgKmNsaykKPiA+ICAgICAg
ICAgICAgICAgcmV0dXJuIDA7Cj4gPiAgCj4gPiAgICAgICBjbGtfcHJlcGFyZV9sb2NrKCk7Cj4g
PiArICAgICBjbGstPnByZXBhcmVfY291bnQrKzsKPiA+ICAgICAgIHJldCA9IGNsa19jb3JlX3By
ZXBhcmUoY2xrLT5jb3JlKTsKPiA+ICAgICAgIGNsa19wcmVwYXJlX3VubG9jaygpOwo+ID4gIAo+
ID4gQEAgLTcwNyw2ICs3MTMsOSBAQCB2b2lkIGNsa19kaXNhYmxlKHN0cnVjdCBjbGsgKmNsaykK
PiA+ICAgICAgICAgICAgICAgcmV0dXJuOwo+ID4gIAo+ID4gICAgICAgZmxhZ3MgPSBjbGtfZW5h
YmxlX2xvY2soKTsKPiA+ICsgICAgIGlmIChXQVJOX09OKGNsay0+ZW5hYmxlX2NvdW50ID09IDAp
KQo+ID4gKyAgICAgICAgICAgICByZXR1cm47Cj4gPiArICAgICBjbGstPmVuYWJsZV9jb3VudC0t
Owo+ID4gICAgICAgY2xrX2NvcmVfZGlzYWJsZShjbGstPmNvcmUpOwo+ID4gICAgICAgY2xrX2Vu
YWJsZV91bmxvY2soZmxhZ3MpOwo+ID4gIH0KPiA+IEBAIC03NjksNiArNzc4LDcgQEAgaW50IGNs
a19lbmFibGUoc3RydWN0IGNsayAqY2xrKQo+ID4gICAgICAgICAgICAgICByZXR1cm4gMDsKPiA+
ICAKPiA+ICAgICAgIGZsYWdzID0gY2xrX2VuYWJsZV9sb2NrKCk7Cj4gPiArICAgICBjbGstPmVu
YWJsZV9jb3VudCsrOwo+ID4gICAgICAgcmV0ID0gY2xrX2NvcmVfZW5hYmxlKGNsay0+Y29yZSk7
Cj4gPiAgICAgICBjbGtfZW5hYmxlX3VubG9jayhmbGFncyk7Cj4gPiAgCj4gCj4gLS0gCj4gTGVl
IEpvbmVzCj4gTGluYXJvIFNUTWljcm9lbGVjdHJvbmljcyBMYW5kaW5nIFRlYW0gTGVhZAo+IExp
bmFyby5vcmcg4pSCIE9wZW4gc291cmNlIHNvZnR3YXJlIGZvciBBUk0gU29Dcwo+IEZvbGxvdyBM
aW5hcm86IEZhY2Vib29rIHwgVHdpdHRlciB8IEJsb2cKPiAtLQo+IFRvIHVuc3Vic2NyaWJlIGZy
b20gdGhpcyBsaXN0OiBzZW5kIHRoZSBsaW5lICJ1bnN1YnNjcmliZSBsaW51eC1jbGsiIGluCj4g
dGhlIGJvZHkgb2YgYSBtZXNzYWdlIHRvIG1ham9yZG9tb0B2Z2VyLmtlcm5lbC5vcmcKPiBNb3Jl
IG1ham9yZG9tbyBpbmZvIGF0ICBodHRwOi8vdmdlci5rZXJuZWwub3JnL21ham9yZG9tby1pbmZv
Lmh0bWwKCl9fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fCmxp
bnV4LWFybS1rZXJuZWwgbWFpbGluZyBsaXN0CmxpbnV4LWFybS1rZXJuZWxAbGlzdHMuaW5mcmFk
ZWFkLm9yZwpodHRwOi8vbGlzdHMuaW5mcmFkZWFkLm9yZy9tYWlsbWFuL2xpc3RpbmZvL2xpbnV4
LWFybS1rZXJuZWwK

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

* [PATCH v7 3/5] clk: Supply the critical clock {init, enable, disable} framework
@ 2015-08-01  0:59             ` Michael Turquette
  0 siblings, 0 replies; 93+ messages in thread
From: Michael Turquette @ 2015-08-01  0:59 UTC (permalink / raw)
  To: linux-arm-kernel

Quoting Lee Jones (2015-07-31 02:02:19)
> On Thu, 30 Jul 2015, Michael Turquette wrote:
> 
> > Quoting Lee Jones (2015-07-30 04:17:47)
> > > On Wed, 29 Jul 2015, Michael Turquette wrote:
> > > 
> > > > Hi Lee,
> > > > 
> > > > + linux-clk ml
> > > > 
> > > > Quoting Lee Jones (2015-07-22 06:04:13)
> > > > > These new API calls will firstly provide a mechanisms to tag a clock as
> > > > > critical and secondly allow any knowledgeable driver to (un)gate clocks,
> > > > > even if they are marked as critical.
> > > > > 
> > > > > Suggested-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> > > > > Signed-off-by: Lee Jones <lee.jones@linaro.org>
> > > > > ---
> > > > >  drivers/clk/clk.c            | 45 ++++++++++++++++++++++++++++++++++++++++++++
> > > > >  include/linux/clk-provider.h |  2 ++
> > > > >  include/linux/clk.h          | 30 +++++++++++++++++++++++++++++
> > > > >  3 files changed, 77 insertions(+)
> > > > > 
> > > > > diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> > > > > index 61c3fc5..486b1da 100644
> > > > > --- a/drivers/clk/clk.c
> > > > > +++ b/drivers/clk/clk.c
> > > > > @@ -46,6 +46,21 @@ static struct clk_core *clk_core_lookup(const char *name);
> > > > >  
> > > > >  /***    private data structures    ***/
> > > > >  
> > > > > +/**
> > > > > + * struct critical -   Provides 'play' over critical clocks.  A clock can be
> > > > > + *                     marked as critical, meaning that it should not be
> > > > > + *                     disabled.  However, if a driver which is aware of the
> > > > > + *                     critical behaviour wants to control it, it can do so
> > > > > + *                     using clk_enable_critical() and clk_disable_critical().
> > > > > + *
> > > > > + * @enabled    Is clock critical?  Once set, doesn't change
> > > > > + * @leave_on   Self explanatory.  Can be disabled by knowledgeable drivers
> > > > 
> > > > Not self explanatory. I need this explained to me. What does leave_on
> > > > do? Better yet, what would happen if leave_on did not exist?
> > > > 
> > > > > + */
> > > > > +struct critical {
> > > > > +       bool enabled;
> > > > > +       bool leave_on;
> > > > > +};
> > > > > +
> > > > >  struct clk_core {
> > > > >         const char              *name;
> > > > >         const struct clk_ops    *ops;
> > > > > @@ -75,6 +90,7 @@ struct clk_core {
> > > > >         struct dentry           *dentry;
> > > > >  #endif
> > > > >         struct kref             ref;
> > > > > +       struct critical         critical;
> > > > >  };
> > > > >  
> > > > >  struct clk {
> > > > > @@ -995,6 +1011,10 @@ static void clk_core_disable(struct clk_core *clk)
> > > > >         if (WARN_ON(clk->enable_count == 0))
> > > > >                 return;
> > > > >  
> > > > > +       /* Refuse to turn off a critical clock */
> > > > > +       if (clk->enable_count == 1 && clk->critical.leave_on)
> > > > > +               return;
> > > > 
> > > > How do we get to this point? clk_enable_critical actually calls
> > > > clk_enable, thus incrementing the enable_count. The only time that we
> > > > could hit the above case is if,
> > > > 
> > > > a) there is an imbalance in clk_enable and clk_disable calls. If this is
> > > > the case then the drivers need to be fixed. Or better yet some
> > > > infrastructure to catch that, now that we have per-user struct clk
> > > > cookies.
> > > > 
> > > > b) a driver knowingly calls clk_enable_critical(foo) and then regular,
> > > > old clk_disable(foo). But why would a driver do that?
> > > > 
> > > > It might be that I am missing the point here, so please feel free to
> > > > clue me in.
> > > 
> > > This check behaves in a very similar to the WARN() above.  It's more
> > > of a fail-safe.  If all drivers are behaving properly, then it
> > > shouldn't ever be true.  If they're not, it prevents an incorrectly
> > > written driver from irrecoverably crippling the system.
> > 
> > Then this check should be replaced with a generic approach that refuses
> > to honor imbalances anyways. Below are two patches that probably resolve
> > the issue of badly behaving drivers that cause enable imbalances.
> 
> Your patch should make the requirement for this check moot, so it can
> probably be removed.
> 
> > > As I said in the other mail.  We can do without these 3 new wrappers.
> > > We _could_ just write a driver which only calls clk_enable() _after_
> > > it calls clk_disable(), a kind of intentional unbalance and it would
> > > do that same thing.
> > 
> > This naive approach will not work with per-user imbalance tracking.
> 
> Steady on.  I said we "_could_", that that I think it's a good idea.
> 
> I think it's a bad idea, which is why I wrote this set. ;)
> 
> > > However, what we're trying to do here is provide
> > > a proper API, so we can see at first glance what the 'knowledgeable'
> > > driver is trying to do and not have someone attempt to submit a 'fix'
> > > which calls clk_enable() or something.
> > 
> > We'll need some type of api for sure for the handoff.
> 
> This set will not trigger your new checks.  The clocks will be in
> perfect ballance becuase a reference will be taken at start-up.
> 
> Again:
> 
> start-up:
>   clk_prepare_enable()
> 
> knowlegable_driver_probe:
>   clk_get()
> 
> knowlegable_driver_gate_clk:
>   clk_disable_critical()

The call to clk_disable() nested inside clk_disable_critical will fail
with the new checks. This is because the struct clk instance will be
different from one used in your "start-up" section above. clk_get()
creates a unique struct clk every time you call it.

Put another way, a unique user of a clock cannot call clk_disable() when
the per-user enable_count is 0.

Furthermore, there is no way that I will ever be happy with a technique
that requires calling disable prior to an enable within a driver. That
goes against a long-standing api designs and is confusing as hell to
driver authors.

Regards,
Mike

> 
> knowlegable_driver_ungate_clk:
>   clk_enable_critical()
> 
> knowlegable_driver_remove:
>   clk_put()
> 
> > From 3599ed206da9ce770bfafcfd95cbb9a03ac44473 Mon Sep 17 00:00:00 2001
> > From: Michael Turquette <mturquette@baylibre.com>
> > Date: Wed, 29 Jul 2015 18:22:45 -0700
> > Subject: [PATCH 1/2] clk: per-user clk prepare & enable ref counts
> > 
> > This patch adds prepare and enable reference counts for the per-user
> > handles that clock consumers have for a clock node. This patch warns if
> > an imbalance occurs while trying to disable or unprepare a clock and
> > aborts, leaving the hardware unaffected.
> > 
> > Signed-off-by: Michael Turquette <mturquette@baylibre.com>
> > ---
> >  drivers/clk/clk.c | 10 ++++++++++
> >  1 file changed, 10 insertions(+)
> > 
> > diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> > index 898052e..72feee9 100644
> > --- a/drivers/clk/clk.c
> > +++ b/drivers/clk/clk.c
> > @@ -84,6 +84,8 @@ struct clk {
> >       unsigned long min_rate;
> >       unsigned long max_rate;
> >       struct hlist_node clks_node;
> > +     unsigned int enable_count;
> > +     unsigned int prepare_count;
> >  };
> >  
> >  /***           locking             ***/
> > @@ -600,6 +602,9 @@ void clk_unprepare(struct clk *clk)
> >               return;
> >  
> >       clk_prepare_lock();
> > +     if (WARN_ON(clk->prepare_count == 0))
> > +             return;
> > +     clk->prepare_count--;
> >       clk_core_unprepare(clk->core);
> >       clk_prepare_unlock();
> >  }
> > @@ -657,6 +662,7 @@ int clk_prepare(struct clk *clk)
> >               return 0;
> >  
> >       clk_prepare_lock();
> > +     clk->prepare_count++;
> >       ret = clk_core_prepare(clk->core);
> >       clk_prepare_unlock();
> >  
> > @@ -707,6 +713,9 @@ void clk_disable(struct clk *clk)
> >               return;
> >  
> >       flags = clk_enable_lock();
> > +     if (WARN_ON(clk->enable_count == 0))
> > +             return;
> > +     clk->enable_count--;
> >       clk_core_disable(clk->core);
> >       clk_enable_unlock(flags);
> >  }
> > @@ -769,6 +778,7 @@ int clk_enable(struct clk *clk)
> >               return 0;
> >  
> >       flags = clk_enable_lock();
> > +     clk->enable_count++;
> >       ret = clk_core_enable(clk->core);
> >       clk_enable_unlock(flags);
> >  
> 
> -- 
> Lee Jones
> Linaro STMicroelectronics Landing Team Lead
> Linaro.org ? Open source software for ARM SoCs
> Follow Linaro: Facebook | Twitter | Blog
> --
> To unsubscribe from this list: send the line "unsubscribe linux-clk" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH v7 4/5] clk: Provide critical clock support
@ 2015-08-17  5:43     ` Barry Song
  0 siblings, 0 replies; 93+ messages in thread
From: Barry Song @ 2015-08-17  5:43 UTC (permalink / raw)
  To: Lee Jones
  Cc: linux-arm-kernel, LKML, devicetree, Mike Turquette, kernel,
	Sascha Hauer, Stephen Boyd, Geert Uytterhoeven, Maxime Ripard

2015-07-22 21:04 GMT+08:00 Lee Jones <lee.jones@linaro.org>:
> Lots of platforms contain clocks which if turned off would prove fatal.
> The only way to recover from these catastrophic failures is to restart
> the board(s).  Now, when a clock provider is registered with the
> framework it is possible for a list of critical clocks to be supplied
> which must be kept ungated.  Each clock mentioned in the newly
> introduced 'critical-clock' property will be clk_prepare_enable()d
> where the normal references will be taken.  This will prevent the
> common clk framework from attempting to gate them during the normal
> clk_disable_unused() and disable_clock() procedures.
>
> Note that it will still be possible for knowledgeable drivers to turn
> these clocks off using clk_{enable,disable}_critical() calls.
>
> Signed-off-by: Lee Jones <lee.jones@linaro.org>

hi Lee,
i have another email about this. i am wondering whether
CLK_IGNORE_UNUSE is still useful after your patch. another solution
for your patch might be extending the current CLK_IGNORE_UNUSE to
runtime?


copy the mail here:
currently we can set a CLK_IGNORE_UNUSE flag to  a clock to stop
clk_disable_unused()  from disabling it at the boot stage:

static void clk_disable_unused_subtree(struct clk_core *core)
{
...

if (core->flags & CLK_IGNORE_UNUSED)
goto unlock_out;
}

static int clk_disable_unused(void)
{
...

clk_unprepare_unused_subtree(core);
...
 return 0;
}

late_initcall_sync(clk_disable_unused);

so if there are two clocks A and B, A is the parent of B, and A is
marked as CLK_IGNORE_UNUSED.

in boot stage if there is nobody using A and B, Linux will disable B
due to clk_disable_unused() , but keep A being enabled since A has
CLK_IGNORE_UNUSED.

but in Linux runtime, we might frequently disable /enable B in runtime
power management, this will cause A disabled since Linux will not
check CLK_IGNORE_UNUSED for runtime disabling clk .

 so this makes CLK_IGNORE_UNUSE only work if we don't disable its
sub-clock at runtime. this looks making no sense.

 i am thinking whether we should do some changes to make it have side
affect for runtime clk disable. otherwise, why do we want to stop it
from being disabled during boot stage?

 I am not sure whether i missed something in clk core level support.

-barry

> ---
>  drivers/clk/clk-conf.c | 45 ++++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 44 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/clk/clk-conf.c b/drivers/clk/clk-conf.c
> index aad4796..f83c1c2 100644
> --- a/drivers/clk/clk-conf.c
> +++ b/drivers/clk/clk-conf.c
> @@ -116,6 +116,45 @@ static int __set_clk_rates(struct device_node *node, bool clk_supplier)
>         return 0;
>  }
>
> +static int __set_critical_clocks(struct device_node *node, bool clk_supplier)
> +{
> +       struct of_phandle_args clkspec;
> +       struct clk *clk;
> +       struct property *prop;
> +       const __be32 *cur;
> +       uint32_t index;
> +       int ret;
> +
> +       if (!clk_supplier)
> +               return 0;
> +
> +       of_property_for_each_u32(node, "critical-clock", prop, cur, index) {
> +               clkspec.np = node;
> +               clkspec.args_count = 1;
> +               clkspec.args[0] = index;
> +
> +               clk = of_clk_get_from_provider(&clkspec);
> +               if (IS_ERR(clk)) {
> +                       pr_err("clk: couldn't get clock %u for %s\n",
> +                               index, node->full_name);
> +                       return PTR_ERR(clk);
> +               }
> +
> +               clk_init_critical(clk);
> +
> +               ret = clk_prepare_enable(clk);
> +               if (ret) {
> +                       pr_err("Failed to enable clock %u for %s: %d\n",
> +                              index, node->full_name, ret);
> +                       return ret;
> +               }
> +
> +               pr_debug("Setting clock as critical %pC\n", clk);
> +       }
> +
> +       return 0;
> +}
> +
>  /**
>   * of_clk_set_defaults() - parse and set assigned clocks configuration
>   * @node: device node to apply clock settings for
> @@ -139,6 +178,10 @@ int of_clk_set_defaults(struct device_node *node, bool clk_supplier)
>         if (rc < 0)
>                 return rc;
>
> -       return __set_clk_rates(node, clk_supplier);
> +       rc = __set_clk_rates(node, clk_supplier);
> +       if (rc < 0)
> +               return rc;
> +
> +       return __set_critical_clocks(node, clk_supplier);
>  }
>  EXPORT_SYMBOL_GPL(of_clk_set_defaults);
> --
> 1.9.1

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

* Re: [PATCH v7 4/5] clk: Provide critical clock support
@ 2015-08-17  5:43     ` Barry Song
  0 siblings, 0 replies; 93+ messages in thread
From: Barry Song @ 2015-08-17  5:43 UTC (permalink / raw)
  To: Lee Jones
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, LKML,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Mike Turquette,
	kernel-F5mvAk5X5gdBDgjK7y7TUQ, Sascha Hauer, Stephen Boyd,
	Geert Uytterhoeven, Maxime Ripard

2015-07-22 21:04 GMT+08:00 Lee Jones <lee.jones-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>:
> Lots of platforms contain clocks which if turned off would prove fatal.
> The only way to recover from these catastrophic failures is to restart
> the board(s).  Now, when a clock provider is registered with the
> framework it is possible for a list of critical clocks to be supplied
> which must be kept ungated.  Each clock mentioned in the newly
> introduced 'critical-clock' property will be clk_prepare_enable()d
> where the normal references will be taken.  This will prevent the
> common clk framework from attempting to gate them during the normal
> clk_disable_unused() and disable_clock() procedures.
>
> Note that it will still be possible for knowledgeable drivers to turn
> these clocks off using clk_{enable,disable}_critical() calls.
>
> Signed-off-by: Lee Jones <lee.jones-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>

hi Lee,
i have another email about this. i am wondering whether
CLK_IGNORE_UNUSE is still useful after your patch. another solution
for your patch might be extending the current CLK_IGNORE_UNUSE to
runtime?


copy the mail here:
currently we can set a CLK_IGNORE_UNUSE flag to  a clock to stop
clk_disable_unused()  from disabling it at the boot stage:

static void clk_disable_unused_subtree(struct clk_core *core)
{
...

if (core->flags & CLK_IGNORE_UNUSED)
goto unlock_out;
}

static int clk_disable_unused(void)
{
...

clk_unprepare_unused_subtree(core);
...
 return 0;
}

late_initcall_sync(clk_disable_unused);

so if there are two clocks A and B, A is the parent of B, and A is
marked as CLK_IGNORE_UNUSED.

in boot stage if there is nobody using A and B, Linux will disable B
due to clk_disable_unused() , but keep A being enabled since A has
CLK_IGNORE_UNUSED.

but in Linux runtime, we might frequently disable /enable B in runtime
power management, this will cause A disabled since Linux will not
check CLK_IGNORE_UNUSED for runtime disabling clk .

 so this makes CLK_IGNORE_UNUSE only work if we don't disable its
sub-clock at runtime. this looks making no sense.

 i am thinking whether we should do some changes to make it have side
affect for runtime clk disable. otherwise, why do we want to stop it
from being disabled during boot stage?

 I am not sure whether i missed something in clk core level support.

-barry

> ---
>  drivers/clk/clk-conf.c | 45 ++++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 44 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/clk/clk-conf.c b/drivers/clk/clk-conf.c
> index aad4796..f83c1c2 100644
> --- a/drivers/clk/clk-conf.c
> +++ b/drivers/clk/clk-conf.c
> @@ -116,6 +116,45 @@ static int __set_clk_rates(struct device_node *node, bool clk_supplier)
>         return 0;
>  }
>
> +static int __set_critical_clocks(struct device_node *node, bool clk_supplier)
> +{
> +       struct of_phandle_args clkspec;
> +       struct clk *clk;
> +       struct property *prop;
> +       const __be32 *cur;
> +       uint32_t index;
> +       int ret;
> +
> +       if (!clk_supplier)
> +               return 0;
> +
> +       of_property_for_each_u32(node, "critical-clock", prop, cur, index) {
> +               clkspec.np = node;
> +               clkspec.args_count = 1;
> +               clkspec.args[0] = index;
> +
> +               clk = of_clk_get_from_provider(&clkspec);
> +               if (IS_ERR(clk)) {
> +                       pr_err("clk: couldn't get clock %u for %s\n",
> +                               index, node->full_name);
> +                       return PTR_ERR(clk);
> +               }
> +
> +               clk_init_critical(clk);
> +
> +               ret = clk_prepare_enable(clk);
> +               if (ret) {
> +                       pr_err("Failed to enable clock %u for %s: %d\n",
> +                              index, node->full_name, ret);
> +                       return ret;
> +               }
> +
> +               pr_debug("Setting clock as critical %pC\n", clk);
> +       }
> +
> +       return 0;
> +}
> +
>  /**
>   * of_clk_set_defaults() - parse and set assigned clocks configuration
>   * @node: device node to apply clock settings for
> @@ -139,6 +178,10 @@ int of_clk_set_defaults(struct device_node *node, bool clk_supplier)
>         if (rc < 0)
>                 return rc;
>
> -       return __set_clk_rates(node, clk_supplier);
> +       rc = __set_clk_rates(node, clk_supplier);
> +       if (rc < 0)
> +               return rc;
> +
> +       return __set_critical_clocks(node, clk_supplier);
>  }
>  EXPORT_SYMBOL_GPL(of_clk_set_defaults);
> --
> 1.9.1
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH v7 4/5] clk: Provide critical clock support
@ 2015-08-17  5:43     ` Barry Song
  0 siblings, 0 replies; 93+ messages in thread
From: Barry Song @ 2015-08-17  5:43 UTC (permalink / raw)
  To: linux-arm-kernel

2015-07-22 21:04 GMT+08:00 Lee Jones <lee.jones@linaro.org>:
> Lots of platforms contain clocks which if turned off would prove fatal.
> The only way to recover from these catastrophic failures is to restart
> the board(s).  Now, when a clock provider is registered with the
> framework it is possible for a list of critical clocks to be supplied
> which must be kept ungated.  Each clock mentioned in the newly
> introduced 'critical-clock' property will be clk_prepare_enable()d
> where the normal references will be taken.  This will prevent the
> common clk framework from attempting to gate them during the normal
> clk_disable_unused() and disable_clock() procedures.
>
> Note that it will still be possible for knowledgeable drivers to turn
> these clocks off using clk_{enable,disable}_critical() calls.
>
> Signed-off-by: Lee Jones <lee.jones@linaro.org>

hi Lee,
i have another email about this. i am wondering whether
CLK_IGNORE_UNUSE is still useful after your patch. another solution
for your patch might be extending the current CLK_IGNORE_UNUSE to
runtime?


copy the mail here:
currently we can set a CLK_IGNORE_UNUSE flag to  a clock to stop
clk_disable_unused()  from disabling it at the boot stage:

static void clk_disable_unused_subtree(struct clk_core *core)
{
...

if (core->flags & CLK_IGNORE_UNUSED)
goto unlock_out;
}

static int clk_disable_unused(void)
{
...

clk_unprepare_unused_subtree(core);
...
 return 0;
}

late_initcall_sync(clk_disable_unused);

so if there are two clocks A and B, A is the parent of B, and A is
marked as CLK_IGNORE_UNUSED.

in boot stage if there is nobody using A and B, Linux will disable B
due to clk_disable_unused() , but keep A being enabled since A has
CLK_IGNORE_UNUSED.

but in Linux runtime, we might frequently disable /enable B in runtime
power management, this will cause A disabled since Linux will not
check CLK_IGNORE_UNUSED for runtime disabling clk .

 so this makes CLK_IGNORE_UNUSE only work if we don't disable its
sub-clock at runtime. this looks making no sense.

 i am thinking whether we should do some changes to make it have side
affect for runtime clk disable. otherwise, why do we want to stop it
from being disabled during boot stage?

 I am not sure whether i missed something in clk core level support.

-barry

> ---
>  drivers/clk/clk-conf.c | 45 ++++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 44 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/clk/clk-conf.c b/drivers/clk/clk-conf.c
> index aad4796..f83c1c2 100644
> --- a/drivers/clk/clk-conf.c
> +++ b/drivers/clk/clk-conf.c
> @@ -116,6 +116,45 @@ static int __set_clk_rates(struct device_node *node, bool clk_supplier)
>         return 0;
>  }
>
> +static int __set_critical_clocks(struct device_node *node, bool clk_supplier)
> +{
> +       struct of_phandle_args clkspec;
> +       struct clk *clk;
> +       struct property *prop;
> +       const __be32 *cur;
> +       uint32_t index;
> +       int ret;
> +
> +       if (!clk_supplier)
> +               return 0;
> +
> +       of_property_for_each_u32(node, "critical-clock", prop, cur, index) {
> +               clkspec.np = node;
> +               clkspec.args_count = 1;
> +               clkspec.args[0] = index;
> +
> +               clk = of_clk_get_from_provider(&clkspec);
> +               if (IS_ERR(clk)) {
> +                       pr_err("clk: couldn't get clock %u for %s\n",
> +                               index, node->full_name);
> +                       return PTR_ERR(clk);
> +               }
> +
> +               clk_init_critical(clk);
> +
> +               ret = clk_prepare_enable(clk);
> +               if (ret) {
> +                       pr_err("Failed to enable clock %u for %s: %d\n",
> +                              index, node->full_name, ret);
> +                       return ret;
> +               }
> +
> +               pr_debug("Setting clock as critical %pC\n", clk);
> +       }
> +
> +       return 0;
> +}
> +
>  /**
>   * of_clk_set_defaults() - parse and set assigned clocks configuration
>   * @node: device node to apply clock settings for
> @@ -139,6 +178,10 @@ int of_clk_set_defaults(struct device_node *node, bool clk_supplier)
>         if (rc < 0)
>                 return rc;
>
> -       return __set_clk_rates(node, clk_supplier);
> +       rc = __set_clk_rates(node, clk_supplier);
> +       if (rc < 0)
> +               return rc;
> +
> +       return __set_critical_clocks(node, clk_supplier);
>  }
>  EXPORT_SYMBOL_GPL(of_clk_set_defaults);
> --
> 1.9.1

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

* Re: [PATCH v7 4/5] clk: Provide critical clock support
  2015-08-17  5:43     ` Barry Song
  (?)
@ 2015-08-17  7:42       ` Lee Jones
  -1 siblings, 0 replies; 93+ messages in thread
From: Lee Jones @ 2015-08-17  7:42 UTC (permalink / raw)
  To: Barry Song
  Cc: linux-arm-kernel, LKML, devicetree, Mike Turquette, kernel,
	Sascha Hauer, Stephen Boyd, Geert Uytterhoeven, Maxime Ripard

On Mon, 17 Aug 2015, Barry Song wrote:

> 2015-07-22 21:04 GMT+08:00 Lee Jones <lee.jones@linaro.org>:
> > Lots of platforms contain clocks which if turned off would prove fatal.
> > The only way to recover from these catastrophic failures is to restart
> > the board(s).  Now, when a clock provider is registered with the
> > framework it is possible for a list of critical clocks to be supplied
> > which must be kept ungated.  Each clock mentioned in the newly
> > introduced 'critical-clock' property will be clk_prepare_enable()d
> > where the normal references will be taken.  This will prevent the
> > common clk framework from attempting to gate them during the normal
> > clk_disable_unused() and disable_clock() procedures.
> >
> > Note that it will still be possible for knowledgeable drivers to turn
> > these clocks off using clk_{enable,disable}_critical() calls.
> >
> > Signed-off-by: Lee Jones <lee.jones@linaro.org>
> 
> hi Lee,
> i have another email about this. i am wondering whether
> CLK_IGNORE_UNUSE is still useful after your patch. another solution
> for your patch might be extending the current CLK_IGNORE_UNUSE to
> runtime?
> 
> 
> copy the mail here:
> currently we can set a CLK_IGNORE_UNUSE flag to  a clock to stop
> clk_disable_unused()  from disabling it at the boot stage:
> 
> static void clk_disable_unused_subtree(struct clk_core *core)
> {
> ...
> 
> if (core->flags & CLK_IGNORE_UNUSED)
> goto unlock_out;
> }
> 
> static int clk_disable_unused(void)
> {
> ...
> 
> clk_unprepare_unused_subtree(core);
> ...
>  return 0;
> }
> 
> late_initcall_sync(clk_disable_unused);
> 
> so if there are two clocks A and B, A is the parent of B, and A is
> marked as CLK_IGNORE_UNUSED.
> 
> in boot stage if there is nobody using A and B, Linux will disable B
> due to clk_disable_unused() , but keep A being enabled since A has
> CLK_IGNORE_UNUSED.
> 
> but in Linux runtime, we might frequently disable /enable B in runtime
> power management, this will cause A disabled since Linux will not
> check CLK_IGNORE_UNUSED for runtime disabling clk .
> 
>  so this makes CLK_IGNORE_UNUSE only work if we don't disable its
> sub-clock at runtime. this looks making no sense.
> 
>  i am thinking whether we should do some changes to make it have side
> affect for runtime clk disable. otherwise, why do we want to stop it
> from being disabled during boot stage?

This is one of this problems, along with some others that this set
aims to solve.

Extending CLK_IGNORE_UNUSED is not a good idea.  In fact, if we can
phase it out completely, that will be a good thing.

Since this set Mike has submitted an alternitive solution.

Please see: https://groups.google.com/forum/#!msg/linux.kernel/kX_nWSsWRxU/IZSjhG5Ed4oJ

>  I am not sure whether i missed something in clk core level support.
> 
> -barry
> 
> > ---
> >  drivers/clk/clk-conf.c | 45 ++++++++++++++++++++++++++++++++++++++++++++-
> >  1 file changed, 44 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/clk/clk-conf.c b/drivers/clk/clk-conf.c
> > index aad4796..f83c1c2 100644
> > --- a/drivers/clk/clk-conf.c
> > +++ b/drivers/clk/clk-conf.c
> > @@ -116,6 +116,45 @@ static int __set_clk_rates(struct device_node *node, bool clk_supplier)
> >         return 0;
> >  }
> >
> > +static int __set_critical_clocks(struct device_node *node, bool clk_supplier)
> > +{
> > +       struct of_phandle_args clkspec;
> > +       struct clk *clk;
> > +       struct property *prop;
> > +       const __be32 *cur;
> > +       uint32_t index;
> > +       int ret;
> > +
> > +       if (!clk_supplier)
> > +               return 0;
> > +
> > +       of_property_for_each_u32(node, "critical-clock", prop, cur, index) {
> > +               clkspec.np = node;
> > +               clkspec.args_count = 1;
> > +               clkspec.args[0] = index;
> > +
> > +               clk = of_clk_get_from_provider(&clkspec);
> > +               if (IS_ERR(clk)) {
> > +                       pr_err("clk: couldn't get clock %u for %s\n",
> > +                               index, node->full_name);
> > +                       return PTR_ERR(clk);
> > +               }
> > +
> > +               clk_init_critical(clk);
> > +
> > +               ret = clk_prepare_enable(clk);
> > +               if (ret) {
> > +                       pr_err("Failed to enable clock %u for %s: %d\n",
> > +                              index, node->full_name, ret);
> > +                       return ret;
> > +               }
> > +
> > +               pr_debug("Setting clock as critical %pC\n", clk);
> > +       }
> > +
> > +       return 0;
> > +}
> > +
> >  /**
> >   * of_clk_set_defaults() - parse and set assigned clocks configuration
> >   * @node: device node to apply clock settings for
> > @@ -139,6 +178,10 @@ int of_clk_set_defaults(struct device_node *node, bool clk_supplier)
> >         if (rc < 0)
> >                 return rc;
> >
> > -       return __set_clk_rates(node, clk_supplier);
> > +       rc = __set_clk_rates(node, clk_supplier);
> > +       if (rc < 0)
> > +               return rc;
> > +
> > +       return __set_critical_clocks(node, clk_supplier);
> >  }
> >  EXPORT_SYMBOL_GPL(of_clk_set_defaults);

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

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

* Re: [PATCH v7 4/5] clk: Provide critical clock support
@ 2015-08-17  7:42       ` Lee Jones
  0 siblings, 0 replies; 93+ messages in thread
From: Lee Jones @ 2015-08-17  7:42 UTC (permalink / raw)
  To: Barry Song
  Cc: linux-arm-kernel, LKML, devicetree, Mike Turquette, kernel,
	Sascha Hauer, Stephen Boyd, Geert Uytterhoeven, Maxime Ripard

On Mon, 17 Aug 2015, Barry Song wrote:

> 2015-07-22 21:04 GMT+08:00 Lee Jones <lee.jones@linaro.org>:
> > Lots of platforms contain clocks which if turned off would prove fatal.
> > The only way to recover from these catastrophic failures is to restart
> > the board(s).  Now, when a clock provider is registered with the
> > framework it is possible for a list of critical clocks to be supplied
> > which must be kept ungated.  Each clock mentioned in the newly
> > introduced 'critical-clock' property will be clk_prepare_enable()d
> > where the normal references will be taken.  This will prevent the
> > common clk framework from attempting to gate them during the normal
> > clk_disable_unused() and disable_clock() procedures.
> >
> > Note that it will still be possible for knowledgeable drivers to turn
> > these clocks off using clk_{enable,disable}_critical() calls.
> >
> > Signed-off-by: Lee Jones <lee.jones@linaro.org>
> 
> hi Lee,
> i have another email about this. i am wondering whether
> CLK_IGNORE_UNUSE is still useful after your patch. another solution
> for your patch might be extending the current CLK_IGNORE_UNUSE to
> runtime?
> 
> 
> copy the mail here:
> currently we can set a CLK_IGNORE_UNUSE flag to  a clock to stop
> clk_disable_unused()  from disabling it at the boot stage:
> 
> static void clk_disable_unused_subtree(struct clk_core *core)
> {
> ...
> 
> if (core->flags & CLK_IGNORE_UNUSED)
> goto unlock_out;
> }
> 
> static int clk_disable_unused(void)
> {
> ...
> 
> clk_unprepare_unused_subtree(core);
> ...
>  return 0;
> }
> 
> late_initcall_sync(clk_disable_unused);
> 
> so if there are two clocks A and B, A is the parent of B, and A is
> marked as CLK_IGNORE_UNUSED.
> 
> in boot stage if there is nobody using A and B, Linux will disable B
> due to clk_disable_unused() , but keep A being enabled since A has
> CLK_IGNORE_UNUSED.
> 
> but in Linux runtime, we might frequently disable /enable B in runtime
> power management, this will cause A disabled since Linux will not
> check CLK_IGNORE_UNUSED for runtime disabling clk .
> 
>  so this makes CLK_IGNORE_UNUSE only work if we don't disable its
> sub-clock at runtime. this looks making no sense.
> 
>  i am thinking whether we should do some changes to make it have side
> affect for runtime clk disable. otherwise, why do we want to stop it
> from being disabled during boot stage?

This is one of this problems, along with some others that this set
aims to solve.

Extending CLK_IGNORE_UNUSED is not a good idea.  In fact, if we can
phase it out completely, that will be a good thing.

Since this set Mike has submitted an alternitive solution.

Please see: https://groups.google.com/forum/#!msg/linux.kernel/kX_nWSsWRxU/IZSjhG5Ed4oJ

>  I am not sure whether i missed something in clk core level support.
> 
> -barry
> 
> > ---
> >  drivers/clk/clk-conf.c | 45 ++++++++++++++++++++++++++++++++++++++++++++-
> >  1 file changed, 44 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/clk/clk-conf.c b/drivers/clk/clk-conf.c
> > index aad4796..f83c1c2 100644
> > --- a/drivers/clk/clk-conf.c
> > +++ b/drivers/clk/clk-conf.c
> > @@ -116,6 +116,45 @@ static int __set_clk_rates(struct device_node *node, bool clk_supplier)
> >         return 0;
> >  }
> >
> > +static int __set_critical_clocks(struct device_node *node, bool clk_supplier)
> > +{
> > +       struct of_phandle_args clkspec;
> > +       struct clk *clk;
> > +       struct property *prop;
> > +       const __be32 *cur;
> > +       uint32_t index;
> > +       int ret;
> > +
> > +       if (!clk_supplier)
> > +               return 0;
> > +
> > +       of_property_for_each_u32(node, "critical-clock", prop, cur, index) {
> > +               clkspec.np = node;
> > +               clkspec.args_count = 1;
> > +               clkspec.args[0] = index;
> > +
> > +               clk = of_clk_get_from_provider(&clkspec);
> > +               if (IS_ERR(clk)) {
> > +                       pr_err("clk: couldn't get clock %u for %s\n",
> > +                               index, node->full_name);
> > +                       return PTR_ERR(clk);
> > +               }
> > +
> > +               clk_init_critical(clk);
> > +
> > +               ret = clk_prepare_enable(clk);
> > +               if (ret) {
> > +                       pr_err("Failed to enable clock %u for %s: %d\n",
> > +                              index, node->full_name, ret);
> > +                       return ret;
> > +               }
> > +
> > +               pr_debug("Setting clock as critical %pC\n", clk);
> > +       }
> > +
> > +       return 0;
> > +}
> > +
> >  /**
> >   * of_clk_set_defaults() - parse and set assigned clocks configuration
> >   * @node: device node to apply clock settings for
> > @@ -139,6 +178,10 @@ int of_clk_set_defaults(struct device_node *node, bool clk_supplier)
> >         if (rc < 0)
> >                 return rc;
> >
> > -       return __set_clk_rates(node, clk_supplier);
> > +       rc = __set_clk_rates(node, clk_supplier);
> > +       if (rc < 0)
> > +               return rc;
> > +
> > +       return __set_critical_clocks(node, clk_supplier);
> >  }
> >  EXPORT_SYMBOL_GPL(of_clk_set_defaults);

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

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

* [PATCH v7 4/5] clk: Provide critical clock support
@ 2015-08-17  7:42       ` Lee Jones
  0 siblings, 0 replies; 93+ messages in thread
From: Lee Jones @ 2015-08-17  7:42 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, 17 Aug 2015, Barry Song wrote:

> 2015-07-22 21:04 GMT+08:00 Lee Jones <lee.jones@linaro.org>:
> > Lots of platforms contain clocks which if turned off would prove fatal.
> > The only way to recover from these catastrophic failures is to restart
> > the board(s).  Now, when a clock provider is registered with the
> > framework it is possible for a list of critical clocks to be supplied
> > which must be kept ungated.  Each clock mentioned in the newly
> > introduced 'critical-clock' property will be clk_prepare_enable()d
> > where the normal references will be taken.  This will prevent the
> > common clk framework from attempting to gate them during the normal
> > clk_disable_unused() and disable_clock() procedures.
> >
> > Note that it will still be possible for knowledgeable drivers to turn
> > these clocks off using clk_{enable,disable}_critical() calls.
> >
> > Signed-off-by: Lee Jones <lee.jones@linaro.org>
> 
> hi Lee,
> i have another email about this. i am wondering whether
> CLK_IGNORE_UNUSE is still useful after your patch. another solution
> for your patch might be extending the current CLK_IGNORE_UNUSE to
> runtime?
> 
> 
> copy the mail here:
> currently we can set a CLK_IGNORE_UNUSE flag to  a clock to stop
> clk_disable_unused()  from disabling it at the boot stage:
> 
> static void clk_disable_unused_subtree(struct clk_core *core)
> {
> ...
> 
> if (core->flags & CLK_IGNORE_UNUSED)
> goto unlock_out;
> }
> 
> static int clk_disable_unused(void)
> {
> ...
> 
> clk_unprepare_unused_subtree(core);
> ...
>  return 0;
> }
> 
> late_initcall_sync(clk_disable_unused);
> 
> so if there are two clocks A and B, A is the parent of B, and A is
> marked as CLK_IGNORE_UNUSED.
> 
> in boot stage if there is nobody using A and B, Linux will disable B
> due to clk_disable_unused() , but keep A being enabled since A has
> CLK_IGNORE_UNUSED.
> 
> but in Linux runtime, we might frequently disable /enable B in runtime
> power management, this will cause A disabled since Linux will not
> check CLK_IGNORE_UNUSED for runtime disabling clk .
> 
>  so this makes CLK_IGNORE_UNUSE only work if we don't disable its
> sub-clock at runtime. this looks making no sense.
> 
>  i am thinking whether we should do some changes to make it have side
> affect for runtime clk disable. otherwise, why do we want to stop it
> from being disabled during boot stage?

This is one of this problems, along with some others that this set
aims to solve.

Extending CLK_IGNORE_UNUSED is not a good idea.  In fact, if we can
phase it out completely, that will be a good thing.

Since this set Mike has submitted an alternitive solution.

Please see: https://groups.google.com/forum/#!msg/linux.kernel/kX_nWSsWRxU/IZSjhG5Ed4oJ

>  I am not sure whether i missed something in clk core level support.
> 
> -barry
> 
> > ---
> >  drivers/clk/clk-conf.c | 45 ++++++++++++++++++++++++++++++++++++++++++++-
> >  1 file changed, 44 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/clk/clk-conf.c b/drivers/clk/clk-conf.c
> > index aad4796..f83c1c2 100644
> > --- a/drivers/clk/clk-conf.c
> > +++ b/drivers/clk/clk-conf.c
> > @@ -116,6 +116,45 @@ static int __set_clk_rates(struct device_node *node, bool clk_supplier)
> >         return 0;
> >  }
> >
> > +static int __set_critical_clocks(struct device_node *node, bool clk_supplier)
> > +{
> > +       struct of_phandle_args clkspec;
> > +       struct clk *clk;
> > +       struct property *prop;
> > +       const __be32 *cur;
> > +       uint32_t index;
> > +       int ret;
> > +
> > +       if (!clk_supplier)
> > +               return 0;
> > +
> > +       of_property_for_each_u32(node, "critical-clock", prop, cur, index) {
> > +               clkspec.np = node;
> > +               clkspec.args_count = 1;
> > +               clkspec.args[0] = index;
> > +
> > +               clk = of_clk_get_from_provider(&clkspec);
> > +               if (IS_ERR(clk)) {
> > +                       pr_err("clk: couldn't get clock %u for %s\n",
> > +                               index, node->full_name);
> > +                       return PTR_ERR(clk);
> > +               }
> > +
> > +               clk_init_critical(clk);
> > +
> > +               ret = clk_prepare_enable(clk);
> > +               if (ret) {
> > +                       pr_err("Failed to enable clock %u for %s: %d\n",
> > +                              index, node->full_name, ret);
> > +                       return ret;
> > +               }
> > +
> > +               pr_debug("Setting clock as critical %pC\n", clk);
> > +       }
> > +
> > +       return 0;
> > +}
> > +
> >  /**
> >   * of_clk_set_defaults() - parse and set assigned clocks configuration
> >   * @node: device node to apply clock settings for
> > @@ -139,6 +178,10 @@ int of_clk_set_defaults(struct device_node *node, bool clk_supplier)
> >         if (rc < 0)
> >                 return rc;
> >
> > -       return __set_clk_rates(node, clk_supplier);
> > +       rc = __set_clk_rates(node, clk_supplier);
> > +       if (rc < 0)
> > +               return rc;
> > +
> > +       return __set_critical_clocks(node, clk_supplier);
> >  }
> >  EXPORT_SYMBOL_GPL(of_clk_set_defaults);

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org ? Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

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

* Re: [PATCH v7 4/5] clk: Provide critical clock support
  2015-08-17  7:42       ` Lee Jones
  (?)
@ 2015-08-20 13:23         ` Barry Song
  -1 siblings, 0 replies; 93+ messages in thread
From: Barry Song @ 2015-08-20 13:23 UTC (permalink / raw)
  To: Lee Jones
  Cc: linux-arm-kernel, LKML, devicetree, Mike Turquette, kernel,
	Sascha Hauer, Stephen Boyd, Geert Uytterhoeven, Maxime Ripard,
	shengtao.sheng

2015-08-17 15:42 GMT+08:00 Lee Jones <lee.jones@linaro.org>:
> On Mon, 17 Aug 2015, Barry Song wrote:
>
>> 2015-07-22 21:04 GMT+08:00 Lee Jones <lee.jones@linaro.org>:
>> > Lots of platforms contain clocks which if turned off would prove fatal.
>> > The only way to recover from these catastrophic failures is to restart
>> > the board(s).  Now, when a clock provider is registered with the
>> > framework it is possible for a list of critical clocks to be supplied
>> > which must be kept ungated.  Each clock mentioned in the newly
>> > introduced 'critical-clock' property will be clk_prepare_enable()d
>> > where the normal references will be taken.  This will prevent the
>> > common clk framework from attempting to gate them during the normal
>> > clk_disable_unused() and disable_clock() procedures.
>> >
>> > Note that it will still be possible for knowledgeable drivers to turn
>> > these clocks off using clk_{enable,disable}_critical() calls.
>> >
>> > Signed-off-by: Lee Jones <lee.jones@linaro.org>
>>
>> hi Lee,
>> i have another email about this. i am wondering whether
>> CLK_IGNORE_UNUSE is still useful after your patch. another solution
>> for your patch might be extending the current CLK_IGNORE_UNUSE to
>> runtime?
>>
>>
>> copy the mail here:
>> currently we can set a CLK_IGNORE_UNUSE flag to  a clock to stop
>> clk_disable_unused()  from disabling it at the boot stage:
>>
>> static void clk_disable_unused_subtree(struct clk_core *core)
>> {
>> ...
>>
>> if (core->flags & CLK_IGNORE_UNUSED)
>> goto unlock_out;
>> }
>>
>> static int clk_disable_unused(void)
>> {
>> ...
>>
>> clk_unprepare_unused_subtree(core);
>> ...
>>  return 0;
>> }
>>
>> late_initcall_sync(clk_disable_unused);
>>
>> so if there are two clocks A and B, A is the parent of B, and A is
>> marked as CLK_IGNORE_UNUSED.
>>
>> in boot stage if there is nobody using A and B, Linux will disable B
>> due to clk_disable_unused() , but keep A being enabled since A has
>> CLK_IGNORE_UNUSED.
>>
>> but in Linux runtime, we might frequently disable /enable B in runtime
>> power management, this will cause A disabled since Linux will not
>> check CLK_IGNORE_UNUSED for runtime disabling clk .
>>
>>  so this makes CLK_IGNORE_UNUSE only work if we don't disable its
>> sub-clock at runtime. this looks making no sense.
>>
>>  i am thinking whether we should do some changes to make it have side
>> affect for runtime clk disable. otherwise, why do we want to stop it
>> from being disabled during boot stage?
>
> This is one of this problems, along with some others that this set
> aims to solve.
>
> Extending CLK_IGNORE_UNUSED is not a good idea.  In fact, if we can
> phase it out completely, that will be a good thing.

i would agree it is better we can drop CLK_IGNORE_UNUSED since it is
confusing...


>
> Since this set Mike has submitted an alternitive solution.
>
> Please see: https://groups.google.com/forum/#!msg/linux.kernel/kX_nWSsWRxU/IZSjhG5Ed4oJ
>
>>  I am not sure whether i missed something in clk core level support.
>>
>> -barry
>>
>> > ---
>> >  drivers/clk/clk-conf.c | 45 ++++++++++++++++++++++++++++++++++++++++++++-
>> >  1 file changed, 44 insertions(+), 1 deletion(-)
>> >
>> > diff --git a/drivers/clk/clk-conf.c b/drivers/clk/clk-conf.c
>> > index aad4796..f83c1c2 100644
>> > --- a/drivers/clk/clk-conf.c
>> > +++ b/drivers/clk/clk-conf.c
>> > @@ -116,6 +116,45 @@ static int __set_clk_rates(struct device_node *node, bool clk_supplier)
>> >         return 0;
>> >  }
>> >
>> > +static int __set_critical_clocks(struct device_node *node, bool clk_supplier)
>> > +{
>> > +       struct of_phandle_args clkspec;
>> > +       struct clk *clk;
>> > +       struct property *prop;
>> > +       const __be32 *cur;
>> > +       uint32_t index;
>> > +       int ret;
>> > +
>> > +       if (!clk_supplier)
>> > +               return 0;
>> > +
>> > +       of_property_for_each_u32(node, "critical-clock", prop, cur, index) {
>> > +               clkspec.np = node;
>> > +               clkspec.args_count = 1;
>> > +               clkspec.args[0] = index;
>> > +
>> > +               clk = of_clk_get_from_provider(&clkspec);
>> > +               if (IS_ERR(clk)) {
>> > +                       pr_err("clk: couldn't get clock %u for %s\n",
>> > +                               index, node->full_name);
>> > +                       return PTR_ERR(clk);
>> > +               }
>> > +
>> > +               clk_init_critical(clk);
>> > +
>> > +               ret = clk_prepare_enable(clk);
>> > +               if (ret) {
>> > +                       pr_err("Failed to enable clock %u for %s: %d\n",
>> > +                              index, node->full_name, ret);
>> > +                       return ret;
>> > +               }
>> > +
>> > +               pr_debug("Setting clock as critical %pC\n", clk);
>> > +       }
>> > +
>> > +       return 0;
>> > +}
>> > +
>> >  /**
>> >   * of_clk_set_defaults() - parse and set assigned clocks configuration
>> >   * @node: device node to apply clock settings for
>> > @@ -139,6 +178,10 @@ int of_clk_set_defaults(struct device_node *node, bool clk_supplier)
>> >         if (rc < 0)
>> >                 return rc;
>> >
>> > -       return __set_clk_rates(node, clk_supplier);
>> > +       rc = __set_clk_rates(node, clk_supplier);
>> > +       if (rc < 0)
>> > +               return rc;
>> > +
>> > +       return __set_critical_clocks(node, clk_supplier);
>> >  }
>> >  EXPORT_SYMBOL_GPL(of_clk_set_defaults);
>
> --

-barry

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

* Re: [PATCH v7 4/5] clk: Provide critical clock support
@ 2015-08-20 13:23         ` Barry Song
  0 siblings, 0 replies; 93+ messages in thread
From: Barry Song @ 2015-08-20 13:23 UTC (permalink / raw)
  To: Lee Jones
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, LKML,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Mike Turquette,
	kernel-F5mvAk5X5gdBDgjK7y7TUQ, Sascha Hauer, Stephen Boyd,
	Geert Uytterhoeven, Maxime Ripard, shengtao.sheng-kQvG35nSl+M

2015-08-17 15:42 GMT+08:00 Lee Jones <lee.jones-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>:
> On Mon, 17 Aug 2015, Barry Song wrote:
>
>> 2015-07-22 21:04 GMT+08:00 Lee Jones <lee.jones-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>:
>> > Lots of platforms contain clocks which if turned off would prove fatal.
>> > The only way to recover from these catastrophic failures is to restart
>> > the board(s).  Now, when a clock provider is registered with the
>> > framework it is possible for a list of critical clocks to be supplied
>> > which must be kept ungated.  Each clock mentioned in the newly
>> > introduced 'critical-clock' property will be clk_prepare_enable()d
>> > where the normal references will be taken.  This will prevent the
>> > common clk framework from attempting to gate them during the normal
>> > clk_disable_unused() and disable_clock() procedures.
>> >
>> > Note that it will still be possible for knowledgeable drivers to turn
>> > these clocks off using clk_{enable,disable}_critical() calls.
>> >
>> > Signed-off-by: Lee Jones <lee.jones-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
>>
>> hi Lee,
>> i have another email about this. i am wondering whether
>> CLK_IGNORE_UNUSE is still useful after your patch. another solution
>> for your patch might be extending the current CLK_IGNORE_UNUSE to
>> runtime?
>>
>>
>> copy the mail here:
>> currently we can set a CLK_IGNORE_UNUSE flag to  a clock to stop
>> clk_disable_unused()  from disabling it at the boot stage:
>>
>> static void clk_disable_unused_subtree(struct clk_core *core)
>> {
>> ...
>>
>> if (core->flags & CLK_IGNORE_UNUSED)
>> goto unlock_out;
>> }
>>
>> static int clk_disable_unused(void)
>> {
>> ...
>>
>> clk_unprepare_unused_subtree(core);
>> ...
>>  return 0;
>> }
>>
>> late_initcall_sync(clk_disable_unused);
>>
>> so if there are two clocks A and B, A is the parent of B, and A is
>> marked as CLK_IGNORE_UNUSED.
>>
>> in boot stage if there is nobody using A and B, Linux will disable B
>> due to clk_disable_unused() , but keep A being enabled since A has
>> CLK_IGNORE_UNUSED.
>>
>> but in Linux runtime, we might frequently disable /enable B in runtime
>> power management, this will cause A disabled since Linux will not
>> check CLK_IGNORE_UNUSED for runtime disabling clk .
>>
>>  so this makes CLK_IGNORE_UNUSE only work if we don't disable its
>> sub-clock at runtime. this looks making no sense.
>>
>>  i am thinking whether we should do some changes to make it have side
>> affect for runtime clk disable. otherwise, why do we want to stop it
>> from being disabled during boot stage?
>
> This is one of this problems, along with some others that this set
> aims to solve.
>
> Extending CLK_IGNORE_UNUSED is not a good idea.  In fact, if we can
> phase it out completely, that will be a good thing.

i would agree it is better we can drop CLK_IGNORE_UNUSED since it is
confusing...


>
> Since this set Mike has submitted an alternitive solution.
>
> Please see: https://groups.google.com/forum/#!msg/linux.kernel/kX_nWSsWRxU/IZSjhG5Ed4oJ
>
>>  I am not sure whether i missed something in clk core level support.
>>
>> -barry
>>
>> > ---
>> >  drivers/clk/clk-conf.c | 45 ++++++++++++++++++++++++++++++++++++++++++++-
>> >  1 file changed, 44 insertions(+), 1 deletion(-)
>> >
>> > diff --git a/drivers/clk/clk-conf.c b/drivers/clk/clk-conf.c
>> > index aad4796..f83c1c2 100644
>> > --- a/drivers/clk/clk-conf.c
>> > +++ b/drivers/clk/clk-conf.c
>> > @@ -116,6 +116,45 @@ static int __set_clk_rates(struct device_node *node, bool clk_supplier)
>> >         return 0;
>> >  }
>> >
>> > +static int __set_critical_clocks(struct device_node *node, bool clk_supplier)
>> > +{
>> > +       struct of_phandle_args clkspec;
>> > +       struct clk *clk;
>> > +       struct property *prop;
>> > +       const __be32 *cur;
>> > +       uint32_t index;
>> > +       int ret;
>> > +
>> > +       if (!clk_supplier)
>> > +               return 0;
>> > +
>> > +       of_property_for_each_u32(node, "critical-clock", prop, cur, index) {
>> > +               clkspec.np = node;
>> > +               clkspec.args_count = 1;
>> > +               clkspec.args[0] = index;
>> > +
>> > +               clk = of_clk_get_from_provider(&clkspec);
>> > +               if (IS_ERR(clk)) {
>> > +                       pr_err("clk: couldn't get clock %u for %s\n",
>> > +                               index, node->full_name);
>> > +                       return PTR_ERR(clk);
>> > +               }
>> > +
>> > +               clk_init_critical(clk);
>> > +
>> > +               ret = clk_prepare_enable(clk);
>> > +               if (ret) {
>> > +                       pr_err("Failed to enable clock %u for %s: %d\n",
>> > +                              index, node->full_name, ret);
>> > +                       return ret;
>> > +               }
>> > +
>> > +               pr_debug("Setting clock as critical %pC\n", clk);
>> > +       }
>> > +
>> > +       return 0;
>> > +}
>> > +
>> >  /**
>> >   * of_clk_set_defaults() - parse and set assigned clocks configuration
>> >   * @node: device node to apply clock settings for
>> > @@ -139,6 +178,10 @@ int of_clk_set_defaults(struct device_node *node, bool clk_supplier)
>> >         if (rc < 0)
>> >                 return rc;
>> >
>> > -       return __set_clk_rates(node, clk_supplier);
>> > +       rc = __set_clk_rates(node, clk_supplier);
>> > +       if (rc < 0)
>> > +               return rc;
>> > +
>> > +       return __set_critical_clocks(node, clk_supplier);
>> >  }
>> >  EXPORT_SYMBOL_GPL(of_clk_set_defaults);
>
> --

-barry
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH v7 4/5] clk: Provide critical clock support
@ 2015-08-20 13:23         ` Barry Song
  0 siblings, 0 replies; 93+ messages in thread
From: Barry Song @ 2015-08-20 13:23 UTC (permalink / raw)
  To: linux-arm-kernel

2015-08-17 15:42 GMT+08:00 Lee Jones <lee.jones@linaro.org>:
> On Mon, 17 Aug 2015, Barry Song wrote:
>
>> 2015-07-22 21:04 GMT+08:00 Lee Jones <lee.jones@linaro.org>:
>> > Lots of platforms contain clocks which if turned off would prove fatal.
>> > The only way to recover from these catastrophic failures is to restart
>> > the board(s).  Now, when a clock provider is registered with the
>> > framework it is possible for a list of critical clocks to be supplied
>> > which must be kept ungated.  Each clock mentioned in the newly
>> > introduced 'critical-clock' property will be clk_prepare_enable()d
>> > where the normal references will be taken.  This will prevent the
>> > common clk framework from attempting to gate them during the normal
>> > clk_disable_unused() and disable_clock() procedures.
>> >
>> > Note that it will still be possible for knowledgeable drivers to turn
>> > these clocks off using clk_{enable,disable}_critical() calls.
>> >
>> > Signed-off-by: Lee Jones <lee.jones@linaro.org>
>>
>> hi Lee,
>> i have another email about this. i am wondering whether
>> CLK_IGNORE_UNUSE is still useful after your patch. another solution
>> for your patch might be extending the current CLK_IGNORE_UNUSE to
>> runtime?
>>
>>
>> copy the mail here:
>> currently we can set a CLK_IGNORE_UNUSE flag to  a clock to stop
>> clk_disable_unused()  from disabling it at the boot stage:
>>
>> static void clk_disable_unused_subtree(struct clk_core *core)
>> {
>> ...
>>
>> if (core->flags & CLK_IGNORE_UNUSED)
>> goto unlock_out;
>> }
>>
>> static int clk_disable_unused(void)
>> {
>> ...
>>
>> clk_unprepare_unused_subtree(core);
>> ...
>>  return 0;
>> }
>>
>> late_initcall_sync(clk_disable_unused);
>>
>> so if there are two clocks A and B, A is the parent of B, and A is
>> marked as CLK_IGNORE_UNUSED.
>>
>> in boot stage if there is nobody using A and B, Linux will disable B
>> due to clk_disable_unused() , but keep A being enabled since A has
>> CLK_IGNORE_UNUSED.
>>
>> but in Linux runtime, we might frequently disable /enable B in runtime
>> power management, this will cause A disabled since Linux will not
>> check CLK_IGNORE_UNUSED for runtime disabling clk .
>>
>>  so this makes CLK_IGNORE_UNUSE only work if we don't disable its
>> sub-clock at runtime. this looks making no sense.
>>
>>  i am thinking whether we should do some changes to make it have side
>> affect for runtime clk disable. otherwise, why do we want to stop it
>> from being disabled during boot stage?
>
> This is one of this problems, along with some others that this set
> aims to solve.
>
> Extending CLK_IGNORE_UNUSED is not a good idea.  In fact, if we can
> phase it out completely, that will be a good thing.

i would agree it is better we can drop CLK_IGNORE_UNUSED since it is
confusing...


>
> Since this set Mike has submitted an alternitive solution.
>
> Please see: https://groups.google.com/forum/#!msg/linux.kernel/kX_nWSsWRxU/IZSjhG5Ed4oJ
>
>>  I am not sure whether i missed something in clk core level support.
>>
>> -barry
>>
>> > ---
>> >  drivers/clk/clk-conf.c | 45 ++++++++++++++++++++++++++++++++++++++++++++-
>> >  1 file changed, 44 insertions(+), 1 deletion(-)
>> >
>> > diff --git a/drivers/clk/clk-conf.c b/drivers/clk/clk-conf.c
>> > index aad4796..f83c1c2 100644
>> > --- a/drivers/clk/clk-conf.c
>> > +++ b/drivers/clk/clk-conf.c
>> > @@ -116,6 +116,45 @@ static int __set_clk_rates(struct device_node *node, bool clk_supplier)
>> >         return 0;
>> >  }
>> >
>> > +static int __set_critical_clocks(struct device_node *node, bool clk_supplier)
>> > +{
>> > +       struct of_phandle_args clkspec;
>> > +       struct clk *clk;
>> > +       struct property *prop;
>> > +       const __be32 *cur;
>> > +       uint32_t index;
>> > +       int ret;
>> > +
>> > +       if (!clk_supplier)
>> > +               return 0;
>> > +
>> > +       of_property_for_each_u32(node, "critical-clock", prop, cur, index) {
>> > +               clkspec.np = node;
>> > +               clkspec.args_count = 1;
>> > +               clkspec.args[0] = index;
>> > +
>> > +               clk = of_clk_get_from_provider(&clkspec);
>> > +               if (IS_ERR(clk)) {
>> > +                       pr_err("clk: couldn't get clock %u for %s\n",
>> > +                               index, node->full_name);
>> > +                       return PTR_ERR(clk);
>> > +               }
>> > +
>> > +               clk_init_critical(clk);
>> > +
>> > +               ret = clk_prepare_enable(clk);
>> > +               if (ret) {
>> > +                       pr_err("Failed to enable clock %u for %s: %d\n",
>> > +                              index, node->full_name, ret);
>> > +                       return ret;
>> > +               }
>> > +
>> > +               pr_debug("Setting clock as critical %pC\n", clk);
>> > +       }
>> > +
>> > +       return 0;
>> > +}
>> > +
>> >  /**
>> >   * of_clk_set_defaults() - parse and set assigned clocks configuration
>> >   * @node: device node to apply clock settings for
>> > @@ -139,6 +178,10 @@ int of_clk_set_defaults(struct device_node *node, bool clk_supplier)
>> >         if (rc < 0)
>> >                 return rc;
>> >
>> > -       return __set_clk_rates(node, clk_supplier);
>> > +       rc = __set_clk_rates(node, clk_supplier);
>> > +       if (rc < 0)
>> > +               return rc;
>> > +
>> > +       return __set_critical_clocks(node, clk_supplier);
>> >  }
>> >  EXPORT_SYMBOL_GPL(of_clk_set_defaults);
>
> --

-barry

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

end of thread, other threads:[~2015-08-20 13:23 UTC | newest]

Thread overview: 93+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-07-22 13:04 [PATCH v7 0/5] clk: Provide support for always-on clocks Lee Jones
2015-07-22 13:04 ` Lee Jones
2015-07-22 13:04 ` Lee Jones
2015-07-22 13:04 ` [PATCH v7 1/5] ARM: sti: stih407-family: Supply defines for CLOCKGEN A0 Lee Jones
2015-07-22 13:04   ` Lee Jones
2015-07-22 13:04   ` Lee Jones
2015-07-22 13:04 ` [PATCH v7 2/5] ARM: sti: stih410-clocks: Identify critical clocks Lee Jones
2015-07-22 13:04   ` Lee Jones
2015-07-22 13:04 ` [PATCH v7 3/5] clk: Supply the critical clock {init, enable, disable} framework Lee Jones
2015-07-22 13:04   ` Lee Jones
2015-07-22 13:04   ` Lee Jones
2015-07-27  7:25   ` Maxime Ripard
2015-07-27  7:25     ` Maxime Ripard
2015-07-27  7:25     ` Maxime Ripard
2015-07-27  8:53     ` Lee Jones
2015-07-27  8:53       ` Lee Jones
2015-07-27  8:53       ` Lee Jones
2015-07-28 11:40       ` Maxime Ripard
2015-07-28 11:40         ` Maxime Ripard
2015-07-28 13:00         ` Lee Jones
2015-07-28 13:00           ` Lee Jones
2015-07-28 13:00           ` Lee Jones
2015-07-30  1:19           ` Michael Turquette
2015-07-30  1:19             ` Michael Turquette
2015-07-30  1:19             ` Michael Turquette
2015-07-30  9:50             ` Lee Jones
2015-07-30  9:50               ` Lee Jones
2015-07-30  9:50               ` Lee Jones
2015-07-30 22:47               ` Michael Turquette
2015-07-30 22:47                 ` Michael Turquette
2015-07-31  7:30                 ` Maxime Ripard
2015-07-31  7:30                   ` Maxime Ripard
2015-07-31  7:30                   ` Maxime Ripard
2015-07-31  8:32                   ` Lee Jones
2015-07-31  8:32                     ` Lee Jones
2015-07-31  8:32                     ` Lee Jones
2015-07-31  7:03           ` Maxime Ripard
2015-07-31  7:03             ` Maxime Ripard
2015-07-31  7:03             ` Maxime Ripard
2015-07-31  8:48             ` Lee Jones
2015-07-31  8:48               ` Lee Jones
2015-07-30  1:21       ` Michael Turquette
2015-07-30  1:21         ` Michael Turquette
2015-07-30  1:21         ` Michael Turquette
2015-07-30  9:21         ` Lee Jones
2015-07-30  9:21           ` Lee Jones
2015-07-30  9:21           ` Lee Jones
2015-07-30 22:57           ` Michael Turquette
2015-07-30 22:57             ` Michael Turquette
2015-07-31  8:56             ` Lee Jones
2015-07-31  8:56               ` Lee Jones
2015-07-31  8:56               ` Lee Jones
2015-07-30  1:02   ` Michael Turquette
2015-07-30  1:02     ` Michael Turquette
2015-07-30  1:02     ` Michael Turquette
2015-07-30 11:17     ` Lee Jones
2015-07-30 11:17       ` Lee Jones
2015-07-30 23:35       ` Michael Turquette
2015-07-30 23:35         ` Michael Turquette
2015-07-30 23:35         ` Michael Turquette
2015-07-31  9:02         ` Lee Jones
2015-07-31  9:02           ` Lee Jones
2015-08-01  0:59           ` Michael Turquette
2015-08-01  0:59             ` Michael Turquette
2015-08-01  0:59             ` Michael Turquette
2015-07-22 13:04 ` [PATCH v7 4/5] clk: Provide critical clock support Lee Jones
2015-07-22 13:04   ` Lee Jones
2015-07-22 13:04   ` Lee Jones
2015-08-17  5:43   ` Barry Song
2015-08-17  5:43     ` Barry Song
2015-08-17  5:43     ` Barry Song
2015-08-17  7:42     ` Lee Jones
2015-08-17  7:42       ` Lee Jones
2015-08-17  7:42       ` Lee Jones
2015-08-20 13:23       ` Barry Song
2015-08-20 13:23         ` Barry Song
2015-08-20 13:23         ` Barry Song
2015-07-22 13:04 ` [PATCH v7 5/5] clk: dt: Introduce binding for " Lee Jones
2015-07-22 13:04   ` Lee Jones
2015-07-22 13:04   ` Lee Jones
2015-07-27  7:10   ` Maxime Ripard
2015-07-27  7:10     ` Maxime Ripard
2015-07-27  7:31     ` Lee Jones
2015-07-27  7:31       ` Lee Jones
2015-07-28  9:32       ` Maxime Ripard
2015-07-28  9:32         ` Maxime Ripard
2015-07-30  9:23         ` Lee Jones
2015-07-30  9:23           ` Lee Jones
2015-07-30  0:27 ` [PATCH v7 0/5] clk: Provide support for always-on clocks Michael Turquette
2015-07-30  0:27   ` Michael Turquette
2015-07-30  0:27   ` Michael Turquette
2015-07-30  9:09   ` Lee Jones
2015-07-30  9:09     ` Lee Jones

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.