All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v13 0/6] Per-user clock constraints
@ 2015-01-23 11:03 Tomeu Vizoso
  2015-01-23 11:03 ` [PATCH v13 1/6] clk: Remove unneeded NULL checks Tomeu Vizoso
                   ` (6 more replies)
  0 siblings, 7 replies; 186+ messages in thread
From: Tomeu Vizoso @ 2015-01-23 11:03 UTC (permalink / raw)
  To: linux-kernel, Mike Turquette, Stephen Boyd
  Cc: Javier Martinez Canillas, Tomeu Vizoso

Hi,

in this v13 I have:

* added the latest R-b tags from Stephen,

* split some lines that went over the 80-char limit,

* made explicit in the docs that the range limits are inclusive, and

* removed an ifdef in clkdev.c by adding a dev_id param to __of_clk_get_by_name.

The first patch just removes some unneeded NULL checks.

The second removes __clk_register.

The third patch actually moves the per-clock data that was stored in struct
clk to a new struct clk_core and adds references to it from both struct clk and
struct clk_hw. struct clk is now ready to contain information that is specific
to a given clk consumer.

The fourth patch adds API for setting floor and ceiling constraints and stores
that information on the per-user struct clk, which is iterable from struct
clk_core. The constraints are made available to clock implementations in the
determine_rate callback.

The fifth patch exports clk_register_clkdev so that clk-test.ko can be built as a module.

The sixth patch adds a module that can be used to unit-test the CCF. It's very rough right now, but I hope to have time soon to polish it a bit. It has been quite useful during development of this series though.

http://cgit.collabora.com/git/user/tomeu/linux.git/log/?h=per-user-clk-constraints-v13

Thanks,

Tomeu

Tomeu Vizoso (6):
  clk: Remove unneeded NULL checks
  clk: Remove __clk_register
  clk: Make clk API return per-user struct clk instances
  clk: Add rate constraints to clocks
  clkdev: Export clk_register_clkdev
  clk: Add module for unit tests

 Documentation/clk.txt                   |   2 +
 arch/arm/mach-omap2/cclock3xxx_data.c   | 111 +++--
 arch/arm/mach-omap2/clock.h             |  11 +-
 arch/arm/mach-omap2/clock_common_data.c |   5 +-
 arch/arm/mach-omap2/dpll3xxx.c          |   2 +
 arch/arm/mach-omap2/dpll44xx.c          |   2 +
 arch/mips/alchemy/common/clock.c        |   8 +
 drivers/clk/Kconfig                     |   1 +
 drivers/clk/Kconfig.debug               |   6 +
 drivers/clk/Makefile                    |   1 +
 drivers/clk/at91/clk-programmable.c     |   2 +
 drivers/clk/bcm/clk-kona.c              |   2 +
 drivers/clk/clk-composite.c             |   9 +-
 drivers/clk/clk-test.c                  | 326 ++++++++++++
 drivers/clk/clk.c                       | 851 +++++++++++++++++++++-----------
 drivers/clk/clk.h                       |   5 +
 drivers/clk/clkdev.c                    |  85 +++-
 drivers/clk/hisilicon/clk-hi3620.c      |   2 +
 drivers/clk/mmp/clk-mix.c               |   2 +
 drivers/clk/qcom/clk-pll.c              |   1 +
 drivers/clk/qcom/clk-rcg.c              |  10 +-
 drivers/clk/qcom/clk-rcg2.c             |   6 +
 drivers/clk/sunxi/clk-factors.c         |   2 +
 drivers/clk/sunxi/clk-sun6i-ar100.c     |   2 +
 include/linux/clk-private.h             |  43 +-
 include/linux/clk-provider.h            |  27 +-
 include/linux/clk.h                     |  28 ++
 include/linux/clk/ti.h                  |   4 +
 28 files changed, 1187 insertions(+), 369 deletions(-)
 create mode 100644 drivers/clk/Kconfig.debug
 create mode 100644 drivers/clk/clk-test.c

-- 
1.9.3


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

* [PATCH v13 1/6] clk: Remove unneeded NULL checks
  2015-01-23 11:03 [PATCH v13 0/6] Per-user clock constraints Tomeu Vizoso
@ 2015-01-23 11:03 ` Tomeu Vizoso
  2015-01-23 11:03 ` [PATCH v13 2/6] clk: Remove __clk_register Tomeu Vizoso
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 186+ messages in thread
From: Tomeu Vizoso @ 2015-01-23 11:03 UTC (permalink / raw)
  To: linux-kernel, Mike Turquette, Stephen Boyd
  Cc: Javier Martinez Canillas, Tomeu Vizoso

As clk_unprepare_unused_subtree and clk_disable_unused_subtree are
always called with a valid struct clk.

Signed-off-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
Reviewed-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/clk.c | 9 ---------
 1 file changed, 9 deletions(-)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index f4963b7..97f3425 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -432,9 +432,6 @@ static void clk_unprepare_unused_subtree(struct clk *clk)
 {
 	struct clk *child;
 
-	if (!clk)
-		return;
-
 	hlist_for_each_entry(child, &clk->children, child_node)
 		clk_unprepare_unused_subtree(child);
 
@@ -458,9 +455,6 @@ static void clk_disable_unused_subtree(struct clk *clk)
 	struct clk *child;
 	unsigned long flags;
 
-	if (!clk)
-		goto out;
-
 	hlist_for_each_entry(child, &clk->children, child_node)
 		clk_disable_unused_subtree(child);
 
@@ -486,9 +480,6 @@ static void clk_disable_unused_subtree(struct clk *clk)
 
 unlock_out:
 	clk_enable_unlock(flags);
-
-out:
-	return;
 }
 
 static bool clk_ignore_unused;
-- 
1.9.3


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

* [PATCH v13 2/6] clk: Remove __clk_register
  2015-01-23 11:03 [PATCH v13 0/6] Per-user clock constraints Tomeu Vizoso
  2015-01-23 11:03 ` [PATCH v13 1/6] clk: Remove unneeded NULL checks Tomeu Vizoso
@ 2015-01-23 11:03 ` Tomeu Vizoso
  2015-01-23 11:03   ` Tomeu Vizoso
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 186+ messages in thread
From: Tomeu Vizoso @ 2015-01-23 11:03 UTC (permalink / raw)
  To: linux-kernel, Mike Turquette, Stephen Boyd
  Cc: Javier Martinez Canillas, Tomeu Vizoso

As it has never been used.

Signed-off-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
Reviewed-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/clk.c           | 42 ------------------------------------------
 include/linux/clk-private.h |  2 --
 2 files changed, 44 deletions(-)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 97f3425..fd3d671 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -1975,48 +1975,6 @@ out:
 }
 
 /**
- * __clk_register - register a clock and return a cookie.
- *
- * Same as clk_register, except that the .clk field inside hw shall point to a
- * preallocated (generally statically allocated) struct clk. None of the fields
- * of the struct clk need to be initialized.
- *
- * The data pointed to by .init and .clk field shall NOT be marked as init
- * data.
- *
- * __clk_register is only exposed via clk-private.h and is intended for use with
- * very large numbers of clocks that need to be statically initialized.  It is
- * a layering violation to include clk-private.h from any code which implements
- * a clock's .ops; as such any statically initialized clock data MUST be in a
- * separate C file from the logic that implements its operations.  Returns 0
- * on success, otherwise an error code.
- */
-struct clk *__clk_register(struct device *dev, struct clk_hw *hw)
-{
-	int ret;
-	struct clk *clk;
-
-	clk = hw->clk;
-	clk->name = hw->init->name;
-	clk->ops = hw->init->ops;
-	clk->hw = hw;
-	clk->flags = hw->init->flags;
-	clk->parent_names = hw->init->parent_names;
-	clk->num_parents = hw->init->num_parents;
-	if (dev && dev->driver)
-		clk->owner = dev->driver->owner;
-	else
-		clk->owner = NULL;
-
-	ret = __clk_init(dev, clk);
-	if (ret)
-		return ERR_PTR(ret);
-
-	return clk;
-}
-EXPORT_SYMBOL_GPL(__clk_register);
-
-/**
  * clk_register - allocate a new clock, register it and return an opaque cookie
  * @dev: device that is registering this clock
  * @hw: link to hardware-specific clock data
diff --git a/include/linux/clk-private.h b/include/linux/clk-private.h
index 0ca5f60..c5f40d0 100644
--- a/include/linux/clk-private.h
+++ b/include/linux/clk-private.h
@@ -214,7 +214,5 @@ struct clk {
  */
 int __clk_init(struct device *dev, struct clk *clk);
 
-struct clk *__clk_register(struct device *dev, struct clk_hw *hw);
-
 #endif /* CONFIG_COMMON_CLK */
 #endif /* CLK_PRIVATE_H */
-- 
1.9.3


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

* [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
  2015-01-23 11:03 [PATCH v13 0/6] Per-user clock constraints Tomeu Vizoso
@ 2015-01-23 11:03   ` Tomeu Vizoso
  2015-01-23 11:03 ` [PATCH v13 2/6] clk: Remove __clk_register Tomeu Vizoso
                     ` (5 subsequent siblings)
  6 siblings, 0 replies; 186+ messages in thread
From: Tomeu Vizoso @ 2015-01-23 11:03 UTC (permalink / raw)
  To: linux-kernel, Mike Turquette, Stephen Boyd
  Cc: Javier Martinez Canillas, Tomeu Vizoso, Paul Walmsley,
	Tony Lindgren, Russell King, linux-omap, linux-arm-kernel

Moves clock state to struct clk_core, but takes care to change as little API as
possible.

struct clk_hw still has a pointer to a struct clk, which is the
implementation's per-user clk instance, for backwards compatibility.

The struct clk that clk_get_parent() returns isn't owned by the caller, but by
the clock implementation, so the former shouldn't call clk_put() on it.

Because some boards in mach-omap2 still register clocks statically, their clock
registration had to be updated to take into account that the clock information
is stored in struct clk_core now.

Signed-off-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
Reviewed-by: Stephen Boyd <sboyd@codeaurora.org>

---
v13:	* Split some lines to 80 columns
	* Add dev_id parameter to __of_clk_get_by_name so it can be
	called by clk_get without losing information

v12:	* Move __clk_create_clk so it's later next to __clk_free_clk
	* NULLify a just-free'd pointer
	* Check the value returned by __clk_create_clk in clk_register

v11:	* Allow for clk_set_parent to be called with a NULL parent

v10:	* Add more missing NULL checks
	* Remove __clk_reparent as it's now unused
	* Remove clk_core_round_rate as it's now unused
	* Call nolock variants from __clk_mux_determine_rate

v9:	* Add missing NULL checks
	* Remove __clk_prepare and __clk_unprepare as they are unused
	  now

v7:	* Add stub for __of_clk_get_by_name to fix builds without OF

v6:	* Guard against NULL pointer

v4:	* Remove unused function __clk_core_to_clk
	* Use "core" more often as the name for struct clk_core* variables
	* Make sure we don't lose information about the caller in of_clk_get_*

v3:	* Rebase on top of linux-next 20141009

v2:	* Remove exported functions that aren't really used outside clk.c
	* Rename new internal functions to clk_core_ prefix
	* Remove redundant checks for error pointers in *_get_parent
	* Change __clk_create_clk to take a struct clk_hw instead
	* Match the original error behavior in clk_get_sys
---
 arch/arm/mach-omap2/cclock3xxx_data.c   | 111 ++++--
 arch/arm/mach-omap2/clock.h             |  11 +-
 arch/arm/mach-omap2/clock_common_data.c |   5 +-
 drivers/clk/clk.c                       | 621 ++++++++++++++++++++------------
 drivers/clk/clk.h                       |   5 +
 drivers/clk/clkdev.c                    |  84 ++++-
 include/linux/clk-private.h             |  35 +-
 include/linux/clk-provider.h            |  12 +-
 8 files changed, 589 insertions(+), 295 deletions(-)

diff --git a/arch/arm/mach-omap2/cclock3xxx_data.c b/arch/arm/mach-omap2/cclock3xxx_data.c
index 644ff32..adb4e64 100644
--- a/arch/arm/mach-omap2/cclock3xxx_data.c
+++ b/arch/arm/mach-omap2/cclock3xxx_data.c
@@ -82,7 +82,7 @@ DEFINE_CLK_MUX(osc_sys_ck, osc_sys_ck_parent_names, NULL, 0x0,
 	       OMAP3430_PRM_CLKSEL, OMAP3430_SYS_CLKIN_SEL_SHIFT,
 	       OMAP3430_SYS_CLKIN_SEL_WIDTH, 0x0, NULL);
 
-DEFINE_CLK_DIVIDER(sys_ck, "osc_sys_ck", &osc_sys_ck, 0x0,
+DEFINE_CLK_DIVIDER(sys_ck, "osc_sys_ck", &osc_sys_ck_core, 0x0,
 		   OMAP3430_PRM_CLKSRC_CTRL, OMAP_SYSCLKDIV_SHIFT,
 		   OMAP_SYSCLKDIV_WIDTH, CLK_DIVIDER_ONE_BASED, NULL);
 
@@ -132,7 +132,7 @@ static struct clk_hw_omap dpll3_ck_hw = {
 
 DEFINE_STRUCT_CLK(dpll3_ck, dpll3_ck_parent_names, dpll3_ck_ops);
 
-DEFINE_CLK_DIVIDER(dpll3_m2_ck, "dpll3_ck", &dpll3_ck, 0x0,
+DEFINE_CLK_DIVIDER(dpll3_m2_ck, "dpll3_ck", &dpll3_ck_core, 0x0,
 		   OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
 		   OMAP3430_CORE_DPLL_CLKOUT_DIV_SHIFT,
 		   OMAP3430_CORE_DPLL_CLKOUT_DIV_WIDTH,
@@ -149,12 +149,12 @@ static const struct clk_ops core_ck_ops = {};
 DEFINE_STRUCT_CLK_HW_OMAP(core_ck, NULL);
 DEFINE_STRUCT_CLK(core_ck, core_ck_parent_names, core_ck_ops);
 
-DEFINE_CLK_DIVIDER(l3_ick, "core_ck", &core_ck, 0x0,
+DEFINE_CLK_DIVIDER(l3_ick, "core_ck", &core_ck_core, 0x0,
 		   OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL),
 		   OMAP3430_CLKSEL_L3_SHIFT, OMAP3430_CLKSEL_L3_WIDTH,
 		   CLK_DIVIDER_ONE_BASED, NULL);
 
-DEFINE_CLK_DIVIDER(l4_ick, "l3_ick", &l3_ick, 0x0,
+DEFINE_CLK_DIVIDER(l4_ick, "l3_ick", &l3_ick_core, 0x0,
 		   OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL),
 		   OMAP3430_CLKSEL_L4_SHIFT, OMAP3430_CLKSEL_L4_WIDTH,
 		   CLK_DIVIDER_ONE_BASED, NULL);
@@ -275,9 +275,9 @@ static struct clk_hw_omap dpll1_ck_hw = {
 
 DEFINE_STRUCT_CLK(dpll1_ck, dpll3_ck_parent_names, dpll1_ck_ops);
 
-DEFINE_CLK_FIXED_FACTOR(dpll1_x2_ck, "dpll1_ck", &dpll1_ck, 0x0, 2, 1);
+DEFINE_CLK_FIXED_FACTOR(dpll1_x2_ck, "dpll1_ck", &dpll1_ck_core, 0x0, 2, 1);
 
-DEFINE_CLK_DIVIDER(dpll1_x2m2_ck, "dpll1_x2_ck", &dpll1_x2_ck, 0x0,
+DEFINE_CLK_DIVIDER(dpll1_x2m2_ck, "dpll1_x2_ck", &dpll1_x2_ck_core, 0x0,
 		   OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_CLKSEL2_PLL),
 		   OMAP3430_MPU_DPLL_CLKOUT_DIV_SHIFT,
 		   OMAP3430_MPU_DPLL_CLKOUT_DIV_WIDTH,
@@ -292,7 +292,7 @@ static const char *mpu_ck_parent_names[] = {
 DEFINE_STRUCT_CLK_HW_OMAP(mpu_ck, "mpu_clkdm");
 DEFINE_STRUCT_CLK(mpu_ck, mpu_ck_parent_names, core_l4_ick_ops);
 
-DEFINE_CLK_DIVIDER(arm_fck, "mpu_ck", &mpu_ck, 0x0,
+DEFINE_CLK_DIVIDER(arm_fck, "mpu_ck", &mpu_ck_core, 0x0,
 		   OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_IDLEST_PLL),
 		   OMAP3430_ST_MPU_CLK_SHIFT, OMAP3430_ST_MPU_CLK_WIDTH,
 		   0x0, NULL);
@@ -424,7 +424,7 @@ static const struct clk_div_table dpll4_mx_ck_div_table[] = {
 	{ .div = 0 },
 };
 
-DEFINE_CLK_DIVIDER(dpll4_m5_ck, "dpll4_ck", &dpll4_ck, 0x0,
+DEFINE_CLK_DIVIDER(dpll4_m5_ck, "dpll4_ck", &dpll4_ck_core, 0x0,
 		   OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_CLKSEL),
 		   OMAP3430_CLKSEL_CAM_SHIFT, OMAP3630_CLKSEL_CAM_WIDTH,
 		   CLK_DIVIDER_ONE_BASED, NULL);
@@ -466,7 +466,7 @@ static struct clk_hw_omap dpll4_m5x2_ck_hw = {
 DEFINE_STRUCT_CLK_FLAGS(dpll4_m5x2_ck, dpll4_m5x2_ck_parent_names,
 			dpll4_m5x2_ck_ops, CLK_SET_RATE_PARENT);
 
-static struct clk dpll4_m5x2_ck_3630 = {
+static struct clk_core dpll4_m5x2_ck_3630_core = {
 	.name		= "dpll4_m5x2_ck",
 	.hw		= &dpll4_m5x2_ck_hw.hw,
 	.parent_names	= dpll4_m5x2_ck_parent_names,
@@ -475,6 +475,10 @@ static struct clk dpll4_m5x2_ck_3630 = {
 	.flags		= CLK_SET_RATE_PARENT,
 };
 
+static struct clk dpll4_m5x2_ck_3630 = {
+	.core = &dpll4_m5x2_ck_3630_core,
+};
+
 static struct clk cam_mclk;
 
 static const char *cam_mclk_parent_names[] = {
@@ -490,7 +494,7 @@ static struct clk_hw_omap cam_mclk_hw = {
 	.clkdm_name	= "cam_clkdm",
 };
 
-static struct clk cam_mclk = {
+static struct clk_core cam_mclk_core = {
 	.name		= "cam_mclk",
 	.hw		= &cam_mclk_hw.hw,
 	.parent_names	= cam_mclk_parent_names,
@@ -499,6 +503,10 @@ static struct clk cam_mclk = {
 	.flags		= CLK_SET_RATE_PARENT,
 };
 
+static struct clk cam_mclk = {
+	.core = &cam_mclk_core,
+};
+
 static const struct clksel_rate clkout2_src_core_rates[] = {
 	{ .div = 1, .val = 0, .flags = RATE_IN_3XXX },
 	{ .div = 0 }
@@ -514,7 +522,7 @@ static const struct clksel_rate clkout2_src_96m_rates[] = {
 	{ .div = 0 }
 };
 
-DEFINE_CLK_DIVIDER(dpll4_m2_ck, "dpll4_ck", &dpll4_ck, 0x0,
+DEFINE_CLK_DIVIDER(dpll4_m2_ck, "dpll4_ck", &dpll4_ck_core, 0x0,
 		   OMAP_CM_REGADDR(PLL_MOD, OMAP3430_CM_CLKSEL3),
 		   OMAP3430_DIV_96M_SHIFT, OMAP3630_DIV_96M_WIDTH,
 		   CLK_DIVIDER_ONE_BASED, NULL);
@@ -538,7 +546,7 @@ static struct clk_hw_omap dpll4_m2x2_ck_hw = {
 
 DEFINE_STRUCT_CLK(dpll4_m2x2_ck, dpll4_m2x2_ck_parent_names, dpll4_m5x2_ck_ops);
 
-static struct clk dpll4_m2x2_ck_3630 = {
+static struct clk_core dpll4_m2x2_ck_3630_core = {
 	.name		= "dpll4_m2x2_ck",
 	.hw		= &dpll4_m2x2_ck_hw.hw,
 	.parent_names	= dpll4_m2x2_ck_parent_names,
@@ -546,6 +554,10 @@ static struct clk dpll4_m2x2_ck_3630 = {
 	.ops		= &dpll4_m5x2_ck_3630_ops,
 };
 
+static struct clk dpll4_m2x2_ck_3630 = {
+	.core = &dpll4_m2x2_ck_3630_core,
+};
+
 static struct clk omap_96m_alwon_fck;
 
 static const char *omap_96m_alwon_fck_parent_names[] = {
@@ -570,7 +582,7 @@ static const struct clksel_rate clkout2_src_54m_rates[] = {
 	{ .div = 0 }
 };
 
-DEFINE_CLK_DIVIDER_TABLE(dpll4_m3_ck, "dpll4_ck", &dpll4_ck, 0x0,
+DEFINE_CLK_DIVIDER_TABLE(dpll4_m3_ck, "dpll4_ck", &dpll4_ck_core, 0x0,
 		   OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_CLKSEL),
 		   OMAP3430_CLKSEL_TV_SHIFT, OMAP3630_CLKSEL_TV_WIDTH,
 		   0, dpll4_mx_ck_div_table, NULL);
@@ -594,7 +606,7 @@ static struct clk_hw_omap dpll4_m3x2_ck_hw = {
 
 DEFINE_STRUCT_CLK(dpll4_m3x2_ck, dpll4_m3x2_ck_parent_names, dpll4_m5x2_ck_ops);
 
-static struct clk dpll4_m3x2_ck_3630 = {
+static struct clk_core dpll4_m3x2_ck_3630_core = {
 	.name		= "dpll4_m3x2_ck",
 	.hw		= &dpll4_m3x2_ck_hw.hw,
 	.parent_names	= dpll4_m3x2_ck_parent_names,
@@ -602,6 +614,10 @@ static struct clk dpll4_m3x2_ck_3630 = {
 	.ops		= &dpll4_m5x2_ck_3630_ops,
 };
 
+static struct clk dpll4_m3x2_ck_3630 = {
+	.core = &dpll4_m3x2_ck_3630_core,
+};
+
 static const char *omap_54m_fck_parent_names[] = {
 	"dpll4_m3x2_ck", "sys_altclk",
 };
@@ -677,7 +693,8 @@ static struct clk_hw_omap omap_48m_fck_hw = {
 
 DEFINE_STRUCT_CLK(omap_48m_fck, omap_48m_fck_parent_names, omap_48m_fck_ops);
 
-DEFINE_CLK_FIXED_FACTOR(omap_12m_fck, "omap_48m_fck", &omap_48m_fck, 0x0, 1, 4);
+DEFINE_CLK_FIXED_FACTOR(omap_12m_fck, "omap_48m_fck", &omap_48m_fck_core, 0x0,
+			1, 4);
 
 static struct clk core_12m_fck;
 
@@ -723,7 +740,8 @@ static const char *core_l3_ick_parent_names[] = {
 DEFINE_STRUCT_CLK_HW_OMAP(core_l3_ick, "core_l3_clkdm");
 DEFINE_STRUCT_CLK(core_l3_ick, core_l3_ick_parent_names, core_l4_ick_ops);
 
-DEFINE_CLK_FIXED_FACTOR(dpll3_m2x2_ck, "dpll3_m2_ck", &dpll3_m2_ck, 0x0, 2, 1);
+DEFINE_CLK_FIXED_FACTOR(dpll3_m2x2_ck, "dpll3_m2_ck", &dpll3_m2_ck_core, 0x0,
+			2, 1);
 
 static struct clk corex2_fck;
 
@@ -809,7 +827,7 @@ static struct clk_hw_omap des2_ick_hw = {
 
 DEFINE_STRUCT_CLK(des2_ick, aes2_ick_parent_names, aes2_ick_ops);
 
-DEFINE_CLK_DIVIDER(dpll1_fck, "core_ck", &core_ck, 0x0,
+DEFINE_CLK_DIVIDER(dpll1_fck, "core_ck", &core_ck_core, 0x0,
 		   OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_CLKSEL1_PLL),
 		   OMAP3430_MPU_CLK_SRC_SHIFT, OMAP3430_MPU_CLK_SRC_WIDTH,
 		   CLK_DIVIDER_ONE_BASED, NULL);
@@ -852,18 +870,18 @@ static struct clk_hw_omap dpll2_ck_hw = {
 
 DEFINE_STRUCT_CLK(dpll2_ck, dpll3_ck_parent_names, dpll1_ck_ops);
 
-DEFINE_CLK_DIVIDER(dpll2_fck, "core_ck", &core_ck, 0x0,
+DEFINE_CLK_DIVIDER(dpll2_fck, "core_ck", &core_ck_core, 0x0,
 		   OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, OMAP3430_CM_CLKSEL1_PLL),
 		   OMAP3430_IVA2_CLK_SRC_SHIFT, OMAP3430_IVA2_CLK_SRC_WIDTH,
 		   CLK_DIVIDER_ONE_BASED, NULL);
 
-DEFINE_CLK_DIVIDER(dpll2_m2_ck, "dpll2_ck", &dpll2_ck, 0x0,
+DEFINE_CLK_DIVIDER(dpll2_m2_ck, "dpll2_ck", &dpll2_ck_core, 0x0,
 		   OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, OMAP3430_CM_CLKSEL2_PLL),
 		   OMAP3430_IVA2_DPLL_CLKOUT_DIV_SHIFT,
 		   OMAP3430_IVA2_DPLL_CLKOUT_DIV_WIDTH,
 		   CLK_DIVIDER_ONE_BASED, NULL);
 
-DEFINE_CLK_DIVIDER(dpll3_m3_ck, "dpll3_ck", &dpll3_ck, 0x0,
+DEFINE_CLK_DIVIDER(dpll3_m3_ck, "dpll3_ck", &dpll3_ck_core, 0x0,
 		   OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1),
 		   OMAP3430_DIV_DPLL3_SHIFT, OMAP3430_DIV_DPLL3_WIDTH,
 		   CLK_DIVIDER_ONE_BASED, NULL);
@@ -887,7 +905,7 @@ static struct clk_hw_omap dpll3_m3x2_ck_hw = {
 
 DEFINE_STRUCT_CLK(dpll3_m3x2_ck, dpll3_m3x2_ck_parent_names, dpll4_m5x2_ck_ops);
 
-static struct clk dpll3_m3x2_ck_3630 = {
+static struct clk_core dpll3_m3x2_ck_3630_core = {
 	.name		= "dpll3_m3x2_ck",
 	.hw		= &dpll3_m3x2_ck_hw.hw,
 	.parent_names	= dpll3_m3x2_ck_parent_names,
@@ -895,9 +913,13 @@ static struct clk dpll3_m3x2_ck_3630 = {
 	.ops		= &dpll4_m5x2_ck_3630_ops,
 };
 
-DEFINE_CLK_FIXED_FACTOR(dpll3_x2_ck, "dpll3_ck", &dpll3_ck, 0x0, 2, 1);
+static struct clk dpll3_m3x2_ck_3630 = {
+	.core = &dpll3_m3x2_ck_3630_core,
+};
+
+DEFINE_CLK_FIXED_FACTOR(dpll3_x2_ck, "dpll3_ck", &dpll3_ck_core, 0x0, 2, 1);
 
-DEFINE_CLK_DIVIDER_TABLE(dpll4_m4_ck, "dpll4_ck", &dpll4_ck, 0x0,
+DEFINE_CLK_DIVIDER_TABLE(dpll4_m4_ck, "dpll4_ck", &dpll4_ck_core, 0x0,
 		   OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_CLKSEL),
 		   OMAP3430_CLKSEL_DSS1_SHIFT, OMAP3630_CLKSEL_DSS1_WIDTH,
 		   0, dpll4_mx_ck_div_table, NULL);
@@ -922,7 +944,7 @@ static struct clk_hw_omap dpll4_m4x2_ck_hw = {
 DEFINE_STRUCT_CLK_FLAGS(dpll4_m4x2_ck, dpll4_m4x2_ck_parent_names,
 		dpll4_m5x2_ck_ops, CLK_SET_RATE_PARENT);
 
-static struct clk dpll4_m4x2_ck_3630 = {
+static struct clk_core dpll4_m4x2_ck_3630_core = {
 	.name		= "dpll4_m4x2_ck",
 	.hw		= &dpll4_m4x2_ck_hw.hw,
 	.parent_names	= dpll4_m4x2_ck_parent_names,
@@ -931,7 +953,11 @@ static struct clk dpll4_m4x2_ck_3630 = {
 	.flags		= CLK_SET_RATE_PARENT,
 };
 
-DEFINE_CLK_DIVIDER(dpll4_m6_ck, "dpll4_ck", &dpll4_ck, 0x0,
+static struct clk dpll4_m4x2_ck_3630 = {
+	.core = &dpll4_m4x2_ck_3630_core,
+};
+
+DEFINE_CLK_DIVIDER(dpll4_m6_ck, "dpll4_ck", &dpll4_ck_core, 0x0,
 		   OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1),
 		   OMAP3430_DIV_DPLL4_SHIFT, OMAP3630_DIV_DPLL4_WIDTH,
 		   CLK_DIVIDER_ONE_BASED, NULL);
@@ -955,7 +981,7 @@ static struct clk_hw_omap dpll4_m6x2_ck_hw = {
 
 DEFINE_STRUCT_CLK(dpll4_m6x2_ck, dpll4_m6x2_ck_parent_names, dpll4_m5x2_ck_ops);
 
-static struct clk dpll4_m6x2_ck_3630 = {
+static struct clk_core dpll4_m6x2_ck_3630_core = {
 	.name		= "dpll4_m6x2_ck",
 	.hw		= &dpll4_m6x2_ck_hw.hw,
 	.parent_names	= dpll4_m6x2_ck_parent_names,
@@ -963,7 +989,11 @@ static struct clk dpll4_m6x2_ck_3630 = {
 	.ops		= &dpll4_m5x2_ck_3630_ops,
 };
 
-DEFINE_CLK_FIXED_FACTOR(dpll4_x2_ck, "dpll4_ck", &dpll4_ck, 0x0, 2, 1);
+static struct clk dpll4_m6x2_ck_3630 = {
+	.core = &dpll4_m6x2_ck_3630_core,
+};
+
+DEFINE_CLK_FIXED_FACTOR(dpll4_x2_ck, "dpll4_ck", &dpll4_ck_core, 0x0, 2, 1);
 
 static struct dpll_data dpll5_dd = {
 	.mult_div1_reg	= OMAP_CM_REGADDR(PLL_MOD, OMAP3430ES2_CM_CLKSEL4),
@@ -1000,7 +1030,7 @@ static struct clk_hw_omap dpll5_ck_hw = {
 
 DEFINE_STRUCT_CLK(dpll5_ck, dpll3_ck_parent_names, dpll1_ck_ops);
 
-DEFINE_CLK_DIVIDER(dpll5_m2_ck, "dpll5_ck", &dpll5_ck, 0x0,
+DEFINE_CLK_DIVIDER(dpll5_m2_ck, "dpll5_ck", &dpll5_ck_core, 0x0,
 		   OMAP_CM_REGADDR(PLL_MOD, OMAP3430ES2_CM_CLKSEL5),
 		   OMAP3430ES2_DIV_120M_SHIFT, OMAP3430ES2_DIV_120M_WIDTH,
 		   CLK_DIVIDER_ONE_BASED, NULL);
@@ -1247,7 +1277,7 @@ static struct clk_hw_omap emu_src_ck_hw = {
 
 DEFINE_STRUCT_CLK(emu_src_ck, emu_src_ck_parent_names, emu_src_ck_ops);
 
-DEFINE_CLK_DIVIDER(atclk_fck, "emu_src_ck", &emu_src_ck, 0x0,
+DEFINE_CLK_DIVIDER(atclk_fck, "emu_src_ck", &emu_src_ck_core, 0x0,
 		   OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1),
 		   OMAP3430_CLKSEL_ATCLK_SHIFT, OMAP3430_CLKSEL_ATCLK_WIDTH,
 		   CLK_DIVIDER_ONE_BASED, NULL);
@@ -1298,7 +1328,7 @@ static struct clk_hw_omap gfx_l3_ck_hw = {
 
 DEFINE_STRUCT_CLK(gfx_l3_ck, core_l3_ick_parent_names, aes1_ick_ops);
 
-DEFINE_CLK_DIVIDER(gfx_l3_fck, "l3_ick", &l3_ick, 0x0,
+DEFINE_CLK_DIVIDER(gfx_l3_fck, "l3_ick", &l3_ick_core, 0x0,
 		   OMAP_CM_REGADDR(GFX_MOD, CM_CLKSEL),
 		   OMAP_CLKSEL_GFX_SHIFT, OMAP_CLKSEL_GFX_WIDTH,
 		   CLK_DIVIDER_ONE_BASED, NULL);
@@ -2498,7 +2528,7 @@ static struct clk_hw_omap omap_96m_alwon_fck_3630_hw = {
 	.clksel_mask	= OMAP3630_CLKSEL_96M_MASK,
 };
 
-static struct clk omap_96m_alwon_fck_3630 = {
+static struct clk_core omap_96m_alwon_fck_3630_core = {
 	.name	= "omap_96m_alwon_fck",
 	.hw	= &omap_96m_alwon_fck_3630_hw.hw,
 	.parent_names	= omap_96m_alwon_fck_3630_parent_names,
@@ -2506,6 +2536,10 @@ static struct clk omap_96m_alwon_fck_3630 = {
 	.ops	= &omap_96m_alwon_fck_3630_ops,
 };
 
+static struct clk omap_96m_alwon_fck_3630 = {
+	.core = &omap_96m_alwon_fck_3630_core,
+};
+
 static struct clk omapctrl_ick;
 
 static struct clk_hw_omap omapctrl_ick_hw = {
@@ -2521,12 +2555,12 @@ static struct clk_hw_omap omapctrl_ick_hw = {
 
 DEFINE_STRUCT_CLK(omapctrl_ick, aes2_ick_parent_names, aes2_ick_ops);
 
-DEFINE_CLK_DIVIDER(pclk_fck, "emu_src_ck", &emu_src_ck, 0x0,
+DEFINE_CLK_DIVIDER(pclk_fck, "emu_src_ck", &emu_src_ck_core, 0x0,
 		   OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1),
 		   OMAP3430_CLKSEL_PCLK_SHIFT, OMAP3430_CLKSEL_PCLK_WIDTH,
 		   CLK_DIVIDER_ONE_BASED, NULL);
 
-DEFINE_CLK_DIVIDER(pclkx2_fck, "emu_src_ck", &emu_src_ck, 0x0,
+DEFINE_CLK_DIVIDER(pclkx2_fck, "emu_src_ck", &emu_src_ck_core, 0x0,
 		   OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1),
 		   OMAP3430_CLKSEL_PCLKX2_SHIFT, OMAP3430_CLKSEL_PCLKX2_WIDTH,
 		   CLK_DIVIDER_ONE_BASED, NULL);
@@ -2558,7 +2592,7 @@ static struct clk_hw_omap pka_ick_hw = {
 
 DEFINE_STRUCT_CLK(pka_ick, pka_ick_parent_names, aes1_ick_ops);
 
-DEFINE_CLK_DIVIDER(rm_ick, "l4_ick", &l4_ick, 0x0,
+DEFINE_CLK_DIVIDER(rm_ick, "l4_ick", &l4_ick_core, 0x0,
 		   OMAP_CM_REGADDR(WKUP_MOD, CM_CLKSEL),
 		   OMAP3430_CLKSEL_RM_SHIFT, OMAP3430_CLKSEL_RM_WIDTH,
 		   CLK_DIVIDER_ONE_BASED, NULL);
@@ -2819,10 +2853,10 @@ DEFINE_CLK_OMAP_MUX_GATE(ssi_ssr_fck_3430es2, "core_l4_clkdm",
 			 ssi_ssr_fck_3430es1_ops);
 
 DEFINE_CLK_FIXED_FACTOR(ssi_sst_fck_3430es1, "ssi_ssr_fck_3430es1",
-			&ssi_ssr_fck_3430es1, 0x0, 1, 2);
+			&ssi_ssr_fck_3430es1_core, 0x0, 1, 2);
 
 DEFINE_CLK_FIXED_FACTOR(ssi_sst_fck_3430es2, "ssi_ssr_fck_3430es2",
-			&ssi_ssr_fck_3430es2, 0x0, 1, 2);
+			&ssi_ssr_fck_3430es2_core, 0x0, 1, 2);
 
 static struct clk sys_clkout1;
 
@@ -2840,7 +2874,7 @@ static struct clk_hw_omap sys_clkout1_hw = {
 
 DEFINE_STRUCT_CLK(sys_clkout1, sys_clkout1_parent_names, aes1_ick_ops);
 
-DEFINE_CLK_DIVIDER(sys_clkout2, "clkout2_src_ck", &clkout2_src_ck, 0x0,
+DEFINE_CLK_DIVIDER(sys_clkout2, "clkout2_src_ck", &clkout2_src_ck_core, 0x0,
 		   OMAP3430_CM_CLKOUT_CTRL, OMAP3430_CLKOUT2_DIV_SHIFT,
 		   OMAP3430_CLKOUT2_DIV_WIDTH, CLK_DIVIDER_POWER_OF_TWO, NULL);
 
@@ -2849,7 +2883,8 @@ DEFINE_CLK_MUX(traceclk_src_fck, emu_src_ck_parent_names, NULL, 0x0,
 	       OMAP3430_TRACE_MUX_CTRL_SHIFT, OMAP3430_TRACE_MUX_CTRL_WIDTH,
 	       0x0, NULL);
 
-DEFINE_CLK_DIVIDER(traceclk_fck, "traceclk_src_fck", &traceclk_src_fck, 0x0,
+DEFINE_CLK_DIVIDER(traceclk_fck, "traceclk_src_fck", &traceclk_src_fck_core,
+		   0x0,
 		   OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1),
 		   OMAP3430_CLKSEL_TRACECLK_SHIFT,
 		   OMAP3430_CLKSEL_TRACECLK_WIDTH, CLK_DIVIDER_ONE_BASED, NULL);
diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h
index a4282e7..c5b3a7f 100644
--- a/arch/arm/mach-omap2/clock.h
+++ b/arch/arm/mach-omap2/clock.h
@@ -40,23 +40,29 @@ struct omap_clk {
 struct clockdomain;
 
 #define DEFINE_STRUCT_CLK(_name, _parent_array_name, _clkops_name)	\
-	static struct clk _name = {				\
+	static struct clk_core _name##_core = {			\
 		.name = #_name,					\
 		.hw = &_name##_hw.hw,				\
 		.parent_names = _parent_array_name,		\
 		.num_parents = ARRAY_SIZE(_parent_array_name),	\
 		.ops = &_clkops_name,				\
+	};							\
+	static struct clk _name = {				\
+		.core = &_name##_core,				\
 	};
 
 #define DEFINE_STRUCT_CLK_FLAGS(_name, _parent_array_name,	\
 				_clkops_name, _flags)		\
-	static struct clk _name = {				\
+	static struct clk_core _name##_core = {			\
 		.name = #_name,					\
 		.hw = &_name##_hw.hw,				\
 		.parent_names = _parent_array_name,		\
 		.num_parents = ARRAY_SIZE(_parent_array_name),	\
 		.ops = &_clkops_name,				\
 		.flags = _flags,				\
+	};							\
+	static struct clk _name = {				\
+		.core = &_name##_core,				\
 	};
 
 #define DEFINE_STRUCT_CLK_HW_OMAP(_name, _clkdm_name)		\
@@ -248,6 +254,7 @@ extern const struct clksel_rate gpt_32k_rates[];
 extern const struct clksel_rate gpt_sys_rates[];
 extern const struct clksel_rate gfx_l3_rates[];
 extern const struct clksel_rate dsp_ick_rates[];
+extern struct clk_core dummy_ck_core;
 extern struct clk dummy_ck;
 
 extern const struct clk_hw_omap_ops clkhwops_iclk_wait;
diff --git a/arch/arm/mach-omap2/clock_common_data.c b/arch/arm/mach-omap2/clock_common_data.c
index ef4d21b..febd0a2 100644
--- a/arch/arm/mach-omap2/clock_common_data.c
+++ b/arch/arm/mach-omap2/clock_common_data.c
@@ -119,8 +119,11 @@ const struct clksel_rate div31_1to31_rates[] = {
 
 static struct clk_ops dummy_ck_ops = {};
 
-struct clk dummy_ck = {
+struct clk_core dummy_ck_core = {
 	.name = "dummy_clk",
 	.ops = &dummy_ck_ops,
 	.flags = CLK_IS_BASIC,
 };
+struct clk dummy_ck = {
+	.core = &dummy_ck_core,
+};
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index fd3d671..0b7091c 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -37,6 +37,15 @@ static HLIST_HEAD(clk_root_list);
 static HLIST_HEAD(clk_orphan_list);
 static LIST_HEAD(clk_notifier_list);
 
+static long clk_core_get_accuracy(struct clk_core *clk);
+static unsigned long clk_core_get_rate(struct clk_core *clk);
+static int clk_core_get_phase(struct clk_core *clk);
+static bool clk_core_is_prepared(struct clk_core *clk);
+static bool clk_core_is_enabled(struct clk_core *clk);
+static unsigned long clk_core_round_rate_nolock(struct clk_core *clk,
+						unsigned long rate);
+static struct clk_core *clk_core_lookup(const char *name);
+
 /***           locking             ***/
 static void clk_prepare_lock(void)
 {
@@ -114,7 +123,8 @@ static struct hlist_head *orphan_list[] = {
 	NULL,
 };
 
-static void clk_summary_show_one(struct seq_file *s, struct clk *c, int level)
+static void clk_summary_show_one(struct seq_file *s, struct clk_core *c,
+				 int level)
 {
 	if (!c)
 		return;
@@ -122,14 +132,14 @@ static void clk_summary_show_one(struct seq_file *s, struct clk *c, int level)
 	seq_printf(s, "%*s%-*s %11d %12d %11lu %10lu %-3d\n",
 		   level * 3 + 1, "",
 		   30 - level * 3, c->name,
-		   c->enable_count, c->prepare_count, clk_get_rate(c),
-		   clk_get_accuracy(c), clk_get_phase(c));
+		   c->enable_count, c->prepare_count, clk_core_get_rate(c),
+		   clk_core_get_accuracy(c), clk_core_get_phase(c));
 }
 
-static void clk_summary_show_subtree(struct seq_file *s, struct clk *c,
+static void clk_summary_show_subtree(struct seq_file *s, struct clk_core *c,
 				     int level)
 {
-	struct clk *child;
+	struct clk_core *child;
 
 	if (!c)
 		return;
@@ -142,7 +152,7 @@ static void clk_summary_show_subtree(struct seq_file *s, struct clk *c,
 
 static int clk_summary_show(struct seq_file *s, void *data)
 {
-	struct clk *c;
+	struct clk_core *c;
 	struct hlist_head **lists = (struct hlist_head **)s->private;
 
 	seq_puts(s, "   clock                         enable_cnt  prepare_cnt        rate   accuracy   phase\n");
@@ -172,7 +182,7 @@ static const struct file_operations clk_summary_fops = {
 	.release	= single_release,
 };
 
-static void clk_dump_one(struct seq_file *s, struct clk *c, int level)
+static void clk_dump_one(struct seq_file *s, struct clk_core *c, int level)
 {
 	if (!c)
 		return;
@@ -180,14 +190,14 @@ static void clk_dump_one(struct seq_file *s, struct clk *c, int level)
 	seq_printf(s, "\"%s\": { ", c->name);
 	seq_printf(s, "\"enable_count\": %d,", c->enable_count);
 	seq_printf(s, "\"prepare_count\": %d,", c->prepare_count);
-	seq_printf(s, "\"rate\": %lu", clk_get_rate(c));
-	seq_printf(s, "\"accuracy\": %lu", clk_get_accuracy(c));
-	seq_printf(s, "\"phase\": %d", clk_get_phase(c));
+	seq_printf(s, "\"rate\": %lu", clk_core_get_rate(c));
+	seq_printf(s, "\"accuracy\": %lu", clk_core_get_accuracy(c));
+	seq_printf(s, "\"phase\": %d", clk_core_get_phase(c));
 }
 
-static void clk_dump_subtree(struct seq_file *s, struct clk *c, int level)
+static void clk_dump_subtree(struct seq_file *s, struct clk_core *c, int level)
 {
-	struct clk *child;
+	struct clk_core *child;
 
 	if (!c)
 		return;
@@ -204,7 +214,7 @@ static void clk_dump_subtree(struct seq_file *s, struct clk *c, int level)
 
 static int clk_dump(struct seq_file *s, void *data)
 {
-	struct clk *c;
+	struct clk_core *c;
 	bool first_node = true;
 	struct hlist_head **lists = (struct hlist_head **)s->private;
 
@@ -240,7 +250,7 @@ static const struct file_operations clk_dump_fops = {
 	.release	= single_release,
 };
 
-static int clk_debug_create_one(struct clk *clk, struct dentry *pdentry)
+static int clk_debug_create_one(struct clk_core *clk, struct dentry *pdentry)
 {
 	struct dentry *d;
 	int ret = -ENOMEM;
@@ -315,7 +325,7 @@ out:
  * initialized.  Otherwise it bails out early since the debugfs clk tree
  * will be created lazily by clk_debug_init as part of a late_initcall.
  */
-static int clk_debug_register(struct clk *clk)
+static int clk_debug_register(struct clk_core *clk)
 {
 	int ret = 0;
 
@@ -340,7 +350,7 @@ unlock:
  * debugfs clk tree if clk->dentry points to debugfs created by
  * clk_debug_register in __clk_init.
  */
-static void clk_debug_unregister(struct clk *clk)
+static void clk_debug_unregister(struct clk_core *clk)
 {
 	mutex_lock(&clk_debug_lock);
 	if (!clk->dentry)
@@ -358,8 +368,9 @@ struct dentry *clk_debugfs_add_file(struct clk_hw *hw, char *name, umode_t mode,
 {
 	struct dentry *d = NULL;
 
-	if (hw->clk->dentry)
-		d = debugfs_create_file(name, mode, hw->clk->dentry, data, fops);
+	if (hw->core->dentry)
+		d = debugfs_create_file(name, mode, hw->core->dentry, data,
+					fops);
 
 	return d;
 }
@@ -379,7 +390,7 @@ EXPORT_SYMBOL_GPL(clk_debugfs_add_file);
  */
 static int __init clk_debug_init(void)
 {
-	struct clk *clk;
+	struct clk_core *clk;
 	struct dentry *d;
 
 	rootdir = debugfs_create_dir("clk", NULL);
@@ -418,19 +429,20 @@ static int __init clk_debug_init(void)
 }
 late_initcall(clk_debug_init);
 #else
-static inline int clk_debug_register(struct clk *clk) { return 0; }
-static inline void clk_debug_reparent(struct clk *clk, struct clk *new_parent)
+static inline int clk_debug_register(struct clk_core *clk) { return 0; }
+static inline void clk_debug_reparent(struct clk_core *clk,
+				      struct clk_core *new_parent)
 {
 }
-static inline void clk_debug_unregister(struct clk *clk)
+static inline void clk_debug_unregister(struct clk_core *clk)
 {
 }
 #endif
 
 /* caller must hold prepare_lock */
-static void clk_unprepare_unused_subtree(struct clk *clk)
+static void clk_unprepare_unused_subtree(struct clk_core *clk)
 {
-	struct clk *child;
+	struct clk_core *child;
 
 	hlist_for_each_entry(child, &clk->children, child_node)
 		clk_unprepare_unused_subtree(child);
@@ -441,7 +453,7 @@ static void clk_unprepare_unused_subtree(struct clk *clk)
 	if (clk->flags & CLK_IGNORE_UNUSED)
 		return;
 
-	if (__clk_is_prepared(clk)) {
+	if (clk_core_is_prepared(clk)) {
 		if (clk->ops->unprepare_unused)
 			clk->ops->unprepare_unused(clk->hw);
 		else if (clk->ops->unprepare)
@@ -450,9 +462,9 @@ static void clk_unprepare_unused_subtree(struct clk *clk)
 }
 
 /* caller must hold prepare_lock */
-static void clk_disable_unused_subtree(struct clk *clk)
+static void clk_disable_unused_subtree(struct clk_core *clk)
 {
-	struct clk *child;
+	struct clk_core *child;
 	unsigned long flags;
 
 	hlist_for_each_entry(child, &clk->children, child_node)
@@ -471,7 +483,7 @@ static void clk_disable_unused_subtree(struct clk *clk)
 	 * sequence.  call .disable_unused if available, otherwise fall
 	 * back to .disable
 	 */
-	if (__clk_is_enabled(clk)) {
+	if (clk_core_is_enabled(clk)) {
 		if (clk->ops->disable_unused)
 			clk->ops->disable_unused(clk->hw);
 		else if (clk->ops->disable)
@@ -492,7 +504,7 @@ __setup("clk_ignore_unused", clk_ignore_unused_setup);
 
 static int clk_disable_unused(void)
 {
-	struct clk *clk;
+	struct clk_core *clk;
 
 	if (clk_ignore_unused) {
 		pr_warn("clk: Not disabling unused clocks\n");
@@ -523,48 +535,65 @@ late_initcall_sync(clk_disable_unused);
 
 const char *__clk_get_name(struct clk *clk)
 {
-	return !clk ? NULL : clk->name;
+	return !clk ? NULL : clk->core->name;
 }
 EXPORT_SYMBOL_GPL(__clk_get_name);
 
 struct clk_hw *__clk_get_hw(struct clk *clk)
 {
-	return !clk ? NULL : clk->hw;
+	return !clk ? NULL : clk->core->hw;
 }
 EXPORT_SYMBOL_GPL(__clk_get_hw);
 
 u8 __clk_get_num_parents(struct clk *clk)
 {
-	return !clk ? 0 : clk->num_parents;
+	return !clk ? 0 : clk->core->num_parents;
 }
 EXPORT_SYMBOL_GPL(__clk_get_num_parents);
 
 struct clk *__clk_get_parent(struct clk *clk)
 {
-	return !clk ? NULL : clk->parent;
+	if (!clk)
+		return NULL;
+
+	/* TODO: Create a per-user clk and change callers to call clk_put */
+	return !clk->core->parent ? NULL : clk->core->parent->hw->clk;
 }
 EXPORT_SYMBOL_GPL(__clk_get_parent);
 
-struct clk *clk_get_parent_by_index(struct clk *clk, u8 index)
+static struct clk_core *clk_core_get_parent_by_index(struct clk_core *clk,
+							 u8 index)
 {
 	if (!clk || index >= clk->num_parents)
 		return NULL;
 	else if (!clk->parents)
-		return __clk_lookup(clk->parent_names[index]);
+		return clk_core_lookup(clk->parent_names[index]);
 	else if (!clk->parents[index])
 		return clk->parents[index] =
-			__clk_lookup(clk->parent_names[index]);
+			clk_core_lookup(clk->parent_names[index]);
 	else
 		return clk->parents[index];
 }
+
+struct clk *clk_get_parent_by_index(struct clk *clk, u8 index)
+{
+	struct clk_core *parent;
+
+	if (!clk)
+		return NULL;
+
+	parent = clk_core_get_parent_by_index(clk->core, index);
+
+	return !parent ? NULL : parent->hw->clk;
+}
 EXPORT_SYMBOL_GPL(clk_get_parent_by_index);
 
 unsigned int __clk_get_enable_count(struct clk *clk)
 {
-	return !clk ? 0 : clk->enable_count;
+	return !clk ? 0 : clk->core->enable_count;
 }
 
-unsigned long __clk_get_rate(struct clk *clk)
+static unsigned long clk_core_get_rate_nolock(struct clk_core *clk)
 {
 	unsigned long ret;
 
@@ -584,9 +613,17 @@ unsigned long __clk_get_rate(struct clk *clk)
 out:
 	return ret;
 }
+
+unsigned long __clk_get_rate(struct clk *clk)
+{
+	if (!clk)
+		return 0;
+
+	return clk_core_get_rate_nolock(clk->core);
+}
 EXPORT_SYMBOL_GPL(__clk_get_rate);
 
-static unsigned long __clk_get_accuracy(struct clk *clk)
+static unsigned long __clk_get_accuracy(struct clk_core *clk)
 {
 	if (!clk)
 		return 0;
@@ -596,11 +633,11 @@ static unsigned long __clk_get_accuracy(struct clk *clk)
 
 unsigned long __clk_get_flags(struct clk *clk)
 {
-	return !clk ? 0 : clk->flags;
+	return !clk ? 0 : clk->core->flags;
 }
 EXPORT_SYMBOL_GPL(__clk_get_flags);
 
-bool __clk_is_prepared(struct clk *clk)
+static bool clk_core_is_prepared(struct clk_core *clk)
 {
 	int ret;
 
@@ -621,7 +658,15 @@ out:
 	return !!ret;
 }
 
-bool __clk_is_enabled(struct clk *clk)
+bool __clk_is_prepared(struct clk *clk)
+{
+	if (!clk)
+		return false;
+
+	return clk_core_is_prepared(clk->core);
+}
+
+static bool clk_core_is_enabled(struct clk_core *clk)
 {
 	int ret;
 
@@ -641,12 +686,21 @@ bool __clk_is_enabled(struct clk *clk)
 out:
 	return !!ret;
 }
+
+bool __clk_is_enabled(struct clk *clk)
+{
+	if (!clk)
+		return false;
+
+	return clk_core_is_enabled(clk->core);
+}
 EXPORT_SYMBOL_GPL(__clk_is_enabled);
 
-static struct clk *__clk_lookup_subtree(const char *name, struct clk *clk)
+static struct clk_core *__clk_lookup_subtree(const char *name,
+					     struct clk_core *clk)
 {
-	struct clk *child;
-	struct clk *ret;
+	struct clk_core *child;
+	struct clk_core *ret;
 
 	if (!strcmp(clk->name, name))
 		return clk;
@@ -660,10 +714,10 @@ static struct clk *__clk_lookup_subtree(const char *name, struct clk *clk)
 	return NULL;
 }
 
-struct clk *__clk_lookup(const char *name)
+static struct clk_core *clk_core_lookup(const char *name)
 {
-	struct clk *root_clk;
-	struct clk *ret;
+	struct clk_core *root_clk;
+	struct clk_core *ret;
 
 	if (!name)
 		return NULL;
@@ -685,6 +739,13 @@ struct clk *__clk_lookup(const char *name)
 	return NULL;
 }
 
+struct clk *__clk_lookup(const char *name)
+{
+	struct clk_core *core = clk_core_lookup(name);
+
+	return !core ? NULL : core->hw->clk;
+}
+
 /*
  * Helper for finding best parent to provide a given frequency. This can be used
  * directly as a determine_rate callback (e.g. for a mux), or from a more
@@ -694,32 +755,32 @@ long __clk_mux_determine_rate(struct clk_hw *hw, unsigned long rate,
 			      unsigned long *best_parent_rate,
 			      struct clk_hw **best_parent_p)
 {
-	struct clk *clk = hw->clk, *parent, *best_parent = NULL;
+	struct clk_core *core = hw->core, *parent, *best_parent = NULL;
 	int i, num_parents;
 	unsigned long parent_rate, best = 0;
 
 	/* if NO_REPARENT flag set, pass through to current parent */
-	if (clk->flags & CLK_SET_RATE_NO_REPARENT) {
-		parent = clk->parent;
-		if (clk->flags & CLK_SET_RATE_PARENT)
-			best = __clk_round_rate(parent, rate);
+	if (core->flags & CLK_SET_RATE_NO_REPARENT) {
+		parent = core->parent;
+		if (core->flags & CLK_SET_RATE_PARENT)
+			best = clk_core_round_rate_nolock(parent, rate);
 		else if (parent)
-			best = __clk_get_rate(parent);
+			best = clk_core_get_rate_nolock(parent);
 		else
-			best = __clk_get_rate(clk);
+			best = clk_core_get_rate_nolock(core);
 		goto out;
 	}
 
 	/* find the parent that can provide the fastest rate <= rate */
-	num_parents = clk->num_parents;
+	num_parents = core->num_parents;
 	for (i = 0; i < num_parents; i++) {
-		parent = clk_get_parent_by_index(clk, i);
+		parent = clk_core_get_parent_by_index(core, i);
 		if (!parent)
 			continue;
-		if (clk->flags & CLK_SET_RATE_PARENT)
-			parent_rate = __clk_round_rate(parent, rate);
+		if (core->flags & CLK_SET_RATE_PARENT)
+			parent_rate = clk_core_round_rate_nolock(parent, rate);
 		else
-			parent_rate = __clk_get_rate(parent);
+			parent_rate = clk_core_get_rate_nolock(parent);
 		if (parent_rate <= rate && parent_rate > best) {
 			best_parent = parent;
 			best = parent_rate;
@@ -737,7 +798,7 @@ EXPORT_SYMBOL_GPL(__clk_mux_determine_rate);
 
 /***        clk api        ***/
 
-void __clk_unprepare(struct clk *clk)
+static void clk_core_unprepare(struct clk_core *clk)
 {
 	if (!clk)
 		return;
@@ -753,7 +814,7 @@ void __clk_unprepare(struct clk *clk)
 	if (clk->ops->unprepare)
 		clk->ops->unprepare(clk->hw);
 
-	__clk_unprepare(clk->parent);
+	clk_core_unprepare(clk->parent);
 }
 
 /**
@@ -773,12 +834,12 @@ void clk_unprepare(struct clk *clk)
 		return;
 
 	clk_prepare_lock();
-	__clk_unprepare(clk);
+	clk_core_unprepare(clk->core);
 	clk_prepare_unlock();
 }
 EXPORT_SYMBOL_GPL(clk_unprepare);
 
-int __clk_prepare(struct clk *clk)
+static int clk_core_prepare(struct clk_core *clk)
 {
 	int ret = 0;
 
@@ -786,14 +847,14 @@ int __clk_prepare(struct clk *clk)
 		return 0;
 
 	if (clk->prepare_count == 0) {
-		ret = __clk_prepare(clk->parent);
+		ret = clk_core_prepare(clk->parent);
 		if (ret)
 			return ret;
 
 		if (clk->ops->prepare) {
 			ret = clk->ops->prepare(clk->hw);
 			if (ret) {
-				__clk_unprepare(clk->parent);
+				clk_core_unprepare(clk->parent);
 				return ret;
 			}
 		}
@@ -820,15 +881,18 @@ int clk_prepare(struct clk *clk)
 {
 	int ret;
 
+	if (!clk)
+		return 0;
+
 	clk_prepare_lock();
-	ret = __clk_prepare(clk);
+	ret = clk_core_prepare(clk->core);
 	clk_prepare_unlock();
 
 	return ret;
 }
 EXPORT_SYMBOL_GPL(clk_prepare);
 
-static void __clk_disable(struct clk *clk)
+static void clk_core_disable(struct clk_core *clk)
 {
 	if (!clk)
 		return;
@@ -842,7 +906,15 @@ static void __clk_disable(struct clk *clk)
 	if (clk->ops->disable)
 		clk->ops->disable(clk->hw);
 
-	__clk_disable(clk->parent);
+	clk_core_disable(clk->parent);
+}
+
+static void __clk_disable(struct clk *clk)
+{
+	if (!clk)
+		return;
+
+	clk_core_disable(clk->core);
 }
 
 /**
@@ -870,7 +942,7 @@ void clk_disable(struct clk *clk)
 }
 EXPORT_SYMBOL_GPL(clk_disable);
 
-static int __clk_enable(struct clk *clk)
+static int clk_core_enable(struct clk_core *clk)
 {
 	int ret = 0;
 
@@ -881,7 +953,7 @@ static int __clk_enable(struct clk *clk)
 		return -ESHUTDOWN;
 
 	if (clk->enable_count == 0) {
-		ret = __clk_enable(clk->parent);
+		ret = clk_core_enable(clk->parent);
 
 		if (ret)
 			return ret;
@@ -889,7 +961,7 @@ static int __clk_enable(struct clk *clk)
 		if (clk->ops->enable) {
 			ret = clk->ops->enable(clk->hw);
 			if (ret) {
-				__clk_disable(clk->parent);
+				clk_core_disable(clk->parent);
 				return ret;
 			}
 		}
@@ -899,6 +971,14 @@ static int __clk_enable(struct clk *clk)
 	return 0;
 }
 
+static int __clk_enable(struct clk *clk)
+{
+	if (!clk)
+		return 0;
+
+	return clk_core_enable(clk->core);
+}
+
 /**
  * clk_enable - ungate a clock
  * @clk: the clk being ungated
@@ -925,17 +1005,11 @@ int clk_enable(struct clk *clk)
 }
 EXPORT_SYMBOL_GPL(clk_enable);
 
-/**
- * __clk_round_rate - round the given rate for a clk
- * @clk: round the rate of this clock
- * @rate: the rate which is to be rounded
- *
- * Caller must hold prepare_lock.  Useful for clk_ops such as .set_rate
- */
-unsigned long __clk_round_rate(struct clk *clk, unsigned long rate)
+static unsigned long clk_core_round_rate_nolock(struct clk_core *clk,
+						unsigned long rate)
 {
 	unsigned long parent_rate = 0;
-	struct clk *parent;
+	struct clk_core *parent;
 	struct clk_hw *parent_hw;
 
 	if (!clk)
@@ -952,10 +1026,25 @@ unsigned long __clk_round_rate(struct clk *clk, unsigned long rate)
 	} else if (clk->ops->round_rate)
 		return clk->ops->round_rate(clk->hw, rate, &parent_rate);
 	else if (clk->flags & CLK_SET_RATE_PARENT)
-		return __clk_round_rate(clk->parent, rate);
+		return clk_core_round_rate_nolock(clk->parent, rate);
 	else
 		return clk->rate;
 }
+
+/**
+ * __clk_round_rate - round the given rate for a clk
+ * @clk: round the rate of this clock
+ * @rate: the rate which is to be rounded
+ *
+ * Caller must hold prepare_lock.  Useful for clk_ops such as .set_rate
+ */
+unsigned long __clk_round_rate(struct clk *clk, unsigned long rate)
+{
+	if (!clk)
+		return 0;
+
+	return clk_core_round_rate_nolock(clk->core, rate);
+}
 EXPORT_SYMBOL_GPL(__clk_round_rate);
 
 /**
@@ -971,8 +1060,11 @@ long clk_round_rate(struct clk *clk, unsigned long rate)
 {
 	unsigned long ret;
 
+	if (!clk)
+		return 0;
+
 	clk_prepare_lock();
-	ret = __clk_round_rate(clk, rate);
+	ret = clk_core_round_rate_nolock(clk->core, rate);
 	clk_prepare_unlock();
 
 	return ret;
@@ -993,22 +1085,21 @@ EXPORT_SYMBOL_GPL(clk_round_rate);
  * called if all went well, or NOTIFY_STOP or NOTIFY_BAD immediately if
  * a driver returns that.
  */
-static int __clk_notify(struct clk *clk, unsigned long msg,
+static int __clk_notify(struct clk_core *clk, unsigned long msg,
 		unsigned long old_rate, unsigned long new_rate)
 {
 	struct clk_notifier *cn;
 	struct clk_notifier_data cnd;
 	int ret = NOTIFY_DONE;
 
-	cnd.clk = clk;
 	cnd.old_rate = old_rate;
 	cnd.new_rate = new_rate;
 
 	list_for_each_entry(cn, &clk_notifier_list, node) {
-		if (cn->clk == clk) {
+		if (cn->clk->core == clk) {
+			cnd.clk = cn->clk;
 			ret = srcu_notifier_call_chain(&cn->notifier_head, msg,
 					&cnd);
-			break;
 		}
 	}
 
@@ -1026,10 +1117,10 @@ static int __clk_notify(struct clk *clk, unsigned long msg,
  *
  * Caller must hold prepare_lock.
  */
-static void __clk_recalc_accuracies(struct clk *clk)
+static void __clk_recalc_accuracies(struct clk_core *clk)
 {
 	unsigned long parent_accuracy = 0;
-	struct clk *child;
+	struct clk_core *child;
 
 	if (clk->parent)
 		parent_accuracy = clk->parent->accuracy;
@@ -1044,6 +1135,20 @@ static void __clk_recalc_accuracies(struct clk *clk)
 		__clk_recalc_accuracies(child);
 }
 
+static long clk_core_get_accuracy(struct clk_core *clk)
+{
+	unsigned long accuracy;
+
+	clk_prepare_lock();
+	if (clk && (clk->flags & CLK_GET_ACCURACY_NOCACHE))
+		__clk_recalc_accuracies(clk);
+
+	accuracy = __clk_get_accuracy(clk);
+	clk_prepare_unlock();
+
+	return accuracy;
+}
+
 /**
  * clk_get_accuracy - return the accuracy of clk
  * @clk: the clk whose accuracy is being returned
@@ -1055,20 +1160,15 @@ static void __clk_recalc_accuracies(struct clk *clk)
  */
 long clk_get_accuracy(struct clk *clk)
 {
-	unsigned long accuracy;
-
-	clk_prepare_lock();
-	if (clk && (clk->flags & CLK_GET_ACCURACY_NOCACHE))
-		__clk_recalc_accuracies(clk);
-
-	accuracy = __clk_get_accuracy(clk);
-	clk_prepare_unlock();
+	if (!clk)
+		return 0;
 
-	return accuracy;
+	return clk_core_get_accuracy(clk->core);
 }
 EXPORT_SYMBOL_GPL(clk_get_accuracy);
 
-static unsigned long clk_recalc(struct clk *clk, unsigned long parent_rate)
+static unsigned long clk_recalc(struct clk_core *clk,
+				unsigned long parent_rate)
 {
 	if (clk->ops->recalc_rate)
 		return clk->ops->recalc_rate(clk->hw, parent_rate);
@@ -1089,11 +1189,11 @@ static unsigned long clk_recalc(struct clk *clk, unsigned long parent_rate)
  *
  * Caller must hold prepare_lock.
  */
-static void __clk_recalc_rates(struct clk *clk, unsigned long msg)
+static void __clk_recalc_rates(struct clk_core *clk, unsigned long msg)
 {
 	unsigned long old_rate;
 	unsigned long parent_rate = 0;
-	struct clk *child;
+	struct clk_core *child;
 
 	old_rate = clk->rate;
 
@@ -1113,15 +1213,7 @@ static void __clk_recalc_rates(struct clk *clk, unsigned long msg)
 		__clk_recalc_rates(child, msg);
 }
 
-/**
- * clk_get_rate - return the rate of clk
- * @clk: the clk whose rate is being returned
- *
- * Simply returns the cached rate of the clk, unless CLK_GET_RATE_NOCACHE flag
- * is set, which means a recalc_rate will be issued.
- * If clk is NULL then returns 0.
- */
-unsigned long clk_get_rate(struct clk *clk)
+static unsigned long clk_core_get_rate(struct clk_core *clk)
 {
 	unsigned long rate;
 
@@ -1130,14 +1222,32 @@ unsigned long clk_get_rate(struct clk *clk)
 	if (clk && (clk->flags & CLK_GET_RATE_NOCACHE))
 		__clk_recalc_rates(clk, 0);
 
-	rate = __clk_get_rate(clk);
+	rate = clk_core_get_rate_nolock(clk);
 	clk_prepare_unlock();
 
 	return rate;
 }
+EXPORT_SYMBOL_GPL(clk_core_get_rate);
+
+/**
+ * clk_get_rate - return the rate of clk
+ * @clk: the clk whose rate is being returned
+ *
+ * Simply returns the cached rate of the clk, unless CLK_GET_RATE_NOCACHE flag
+ * is set, which means a recalc_rate will be issued.
+ * If clk is NULL then returns 0.
+ */
+unsigned long clk_get_rate(struct clk *clk)
+{
+	if (!clk)
+		return 0;
+
+	return clk_core_get_rate(clk->core);
+}
 EXPORT_SYMBOL_GPL(clk_get_rate);
 
-static int clk_fetch_parent_index(struct clk *clk, struct clk *parent)
+static int clk_fetch_parent_index(struct clk_core *clk,
+				  struct clk_core *parent)
 {
 	int i;
 
@@ -1151,7 +1261,7 @@ static int clk_fetch_parent_index(struct clk *clk, struct clk *parent)
 	/*
 	 * find index of new parent clock using cached parent ptrs,
 	 * or if not yet cached, use string name comparison and cache
-	 * them now to avoid future calls to __clk_lookup.
+	 * them now to avoid future calls to clk_core_lookup.
 	 */
 	for (i = 0; i < clk->num_parents; i++) {
 		if (clk->parents[i] == parent)
@@ -1161,7 +1271,7 @@ static int clk_fetch_parent_index(struct clk *clk, struct clk *parent)
 			continue;
 
 		if (!strcmp(clk->parent_names[i], parent->name)) {
-			clk->parents[i] = __clk_lookup(parent->name);
+			clk->parents[i] = clk_core_lookup(parent->name);
 			return i;
 		}
 	}
@@ -1169,7 +1279,7 @@ static int clk_fetch_parent_index(struct clk *clk, struct clk *parent)
 	return -EINVAL;
 }
 
-static void clk_reparent(struct clk *clk, struct clk *new_parent)
+static void clk_reparent(struct clk_core *clk, struct clk_core *new_parent)
 {
 	hlist_del(&clk->child_node);
 
@@ -1186,10 +1296,11 @@ static void clk_reparent(struct clk *clk, struct clk *new_parent)
 	clk->parent = new_parent;
 }
 
-static struct clk *__clk_set_parent_before(struct clk *clk, struct clk *parent)
+static struct clk_core *__clk_set_parent_before(struct clk_core *clk,
+					   struct clk_core *parent)
 {
 	unsigned long flags;
-	struct clk *old_parent = clk->parent;
+	struct clk_core *old_parent = clk->parent;
 
 	/*
 	 * Migrate prepare state between parents and prevent race with
@@ -1209,9 +1320,9 @@ static struct clk *__clk_set_parent_before(struct clk *clk, struct clk *parent)
 	 * See also: Comment for clk_set_parent() below.
 	 */
 	if (clk->prepare_count) {
-		__clk_prepare(parent);
-		clk_enable(parent);
-		clk_enable(clk);
+		clk_core_prepare(parent);
+		clk_core_enable(parent);
+		clk_core_enable(clk);
 	}
 
 	/* update the clk tree topology */
@@ -1222,25 +1333,27 @@ static struct clk *__clk_set_parent_before(struct clk *clk, struct clk *parent)
 	return old_parent;
 }
 
-static void __clk_set_parent_after(struct clk *clk, struct clk *parent,
-		struct clk *old_parent)
+static void __clk_set_parent_after(struct clk_core *core,
+				   struct clk_core *parent,
+				   struct clk_core *old_parent)
 {
 	/*
 	 * Finish the migration of prepare state and undo the changes done
 	 * for preventing a race with clk_enable().
 	 */
-	if (clk->prepare_count) {
-		clk_disable(clk);
-		clk_disable(old_parent);
-		__clk_unprepare(old_parent);
+	if (core->prepare_count) {
+		clk_core_disable(core);
+		clk_core_disable(old_parent);
+		clk_core_unprepare(old_parent);
 	}
 }
 
-static int __clk_set_parent(struct clk *clk, struct clk *parent, u8 p_index)
+static int __clk_set_parent(struct clk_core *clk, struct clk_core *parent,
+			    u8 p_index)
 {
 	unsigned long flags;
 	int ret = 0;
-	struct clk *old_parent;
+	struct clk_core *old_parent;
 
 	old_parent = __clk_set_parent_before(clk, parent);
 
@@ -1254,9 +1367,9 @@ static int __clk_set_parent(struct clk *clk, struct clk *parent, u8 p_index)
 		clk_enable_unlock(flags);
 
 		if (clk->prepare_count) {
-			clk_disable(clk);
-			clk_disable(parent);
-			__clk_unprepare(parent);
+			clk_core_disable(clk);
+			clk_core_disable(parent);
+			clk_core_unprepare(parent);
 		}
 		return ret;
 	}
@@ -1282,9 +1395,10 @@ static int __clk_set_parent(struct clk *clk, struct clk *parent, u8 p_index)
  *
  * Caller must hold prepare_lock.
  */
-static int __clk_speculate_rates(struct clk *clk, unsigned long parent_rate)
+static int __clk_speculate_rates(struct clk_core *clk,
+				 unsigned long parent_rate)
 {
-	struct clk *child;
+	struct clk_core *child;
 	unsigned long new_rate;
 	int ret = NOTIFY_DONE;
 
@@ -1310,10 +1424,10 @@ out:
 	return ret;
 }
 
-static void clk_calc_subtree(struct clk *clk, unsigned long new_rate,
-			     struct clk *new_parent, u8 p_index)
+static void clk_calc_subtree(struct clk_core *clk, unsigned long new_rate,
+			     struct clk_core *new_parent, u8 p_index)
 {
-	struct clk *child;
+	struct clk_core *child;
 
 	clk->new_rate = new_rate;
 	clk->new_parent = new_parent;
@@ -1333,10 +1447,11 @@ static void clk_calc_subtree(struct clk *clk, unsigned long new_rate,
  * calculate the new rates returning the topmost clock that has to be
  * changed.
  */
-static struct clk *clk_calc_new_rates(struct clk *clk, unsigned long rate)
+static struct clk_core *clk_calc_new_rates(struct clk_core *clk,
+					   unsigned long rate)
 {
-	struct clk *top = clk;
-	struct clk *old_parent, *parent;
+	struct clk_core *top = clk;
+	struct clk_core *old_parent, *parent;
 	struct clk_hw *parent_hw;
 	unsigned long best_parent_rate = 0;
 	unsigned long new_rate;
@@ -1357,7 +1472,7 @@ static struct clk *clk_calc_new_rates(struct clk *clk, unsigned long rate)
 		new_rate = clk->ops->determine_rate(clk->hw, rate,
 						    &best_parent_rate,
 						    &parent_hw);
-		parent = parent_hw->clk;
+		parent = parent_hw ? parent_hw->core : NULL;
 	} else if (clk->ops->round_rate) {
 		new_rate = clk->ops->round_rate(clk->hw, rate,
 						&best_parent_rate);
@@ -1405,9 +1520,10 @@ out:
  * so that in case of an error we can walk down the whole tree again and
  * abort the change.
  */
-static struct clk *clk_propagate_rate_change(struct clk *clk, unsigned long event)
+static struct clk_core *clk_propagate_rate_change(struct clk_core *clk,
+						  unsigned long event)
 {
-	struct clk *child, *tmp_clk, *fail_clk = NULL;
+	struct clk_core *child, *tmp_clk, *fail_clk = NULL;
 	int ret = NOTIFY_DONE;
 
 	if (clk->rate == clk->new_rate)
@@ -1442,14 +1558,14 @@ static struct clk *clk_propagate_rate_change(struct clk *clk, unsigned long even
  * walk down a subtree and set the new rates notifying the rate
  * change on the way
  */
-static void clk_change_rate(struct clk *clk)
+static void clk_change_rate(struct clk_core *clk)
 {
-	struct clk *child;
+	struct clk_core *child;
 	struct hlist_node *tmp;
 	unsigned long old_rate;
 	unsigned long best_parent_rate = 0;
 	bool skip_set_rate = false;
-	struct clk *old_parent;
+	struct clk_core *old_parent;
 
 	old_rate = clk->rate;
 
@@ -1520,7 +1636,7 @@ static void clk_change_rate(struct clk *clk)
  */
 int clk_set_rate(struct clk *clk, unsigned long rate)
 {
-	struct clk *top, *fail_clk;
+	struct clk_core *top, *fail_clk;
 	int ret = 0;
 
 	if (!clk)
@@ -1533,13 +1649,14 @@ int clk_set_rate(struct clk *clk, unsigned long rate)
 	if (rate == clk_get_rate(clk))
 		goto out;
 
-	if ((clk->flags & CLK_SET_RATE_GATE) && clk->prepare_count) {
+	if ((clk->core->flags & CLK_SET_RATE_GATE) &&
+	    clk->core->prepare_count) {
 		ret = -EBUSY;
 		goto out;
 	}
 
 	/* calculate new rates and get the topmost changed clock */
-	top = clk_calc_new_rates(clk, rate);
+	top = clk_calc_new_rates(clk->core, rate);
 	if (!top) {
 		ret = -EINVAL;
 		goto out;
@@ -1590,11 +1707,11 @@ EXPORT_SYMBOL_GPL(clk_get_parent);
  *
  * For single-parent clocks without .get_parent, first check to see if the
  * .parents array exists, and if so use it to avoid an expensive tree
- * traversal.  If .parents does not exist then walk the tree with __clk_lookup.
+ * traversal.  If .parents does not exist then walk the tree.
  */
-static struct clk *__clk_init_parent(struct clk *clk)
+static struct clk_core *__clk_init_parent(struct clk_core *clk)
 {
-	struct clk *ret = NULL;
+	struct clk_core *ret = NULL;
 	u8 index;
 
 	/* handle the trivial cases */
@@ -1604,7 +1721,7 @@ static struct clk *__clk_init_parent(struct clk *clk)
 
 	if (clk->num_parents == 1) {
 		if (IS_ERR_OR_NULL(clk->parent))
-			clk->parent = __clk_lookup(clk->parent_names[0]);
+			clk->parent = clk_core_lookup(clk->parent_names[0]);
 		ret = clk->parent;
 		goto out;
 	}
@@ -1618,8 +1735,8 @@ static struct clk *__clk_init_parent(struct clk *clk)
 
 	/*
 	 * Do our best to cache parent clocks in clk->parents.  This prevents
-	 * unnecessary and expensive calls to __clk_lookup.  We don't set
-	 * clk->parent here; that is done by the calling function
+	 * unnecessary and expensive lookups.  We don't set clk->parent here;
+	 * that is done by the calling function.
 	 */
 
 	index = clk->ops->get_parent(clk->hw);
@@ -1629,37 +1746,21 @@ static struct clk *__clk_init_parent(struct clk *clk)
 			kcalloc(clk->num_parents, sizeof(struct clk *),
 					GFP_KERNEL);
 
-	ret = clk_get_parent_by_index(clk, index);
+	ret = clk_core_get_parent_by_index(clk, index);
 
 out:
 	return ret;
 }
 
-void __clk_reparent(struct clk *clk, struct clk *new_parent)
+static void clk_core_reparent(struct clk_core *clk,
+				  struct clk_core *new_parent)
 {
 	clk_reparent(clk, new_parent);
 	__clk_recalc_accuracies(clk);
 	__clk_recalc_rates(clk, POST_RATE_CHANGE);
 }
 
-/**
- * clk_set_parent - switch the parent of a mux clk
- * @clk: the mux clk whose input we are switching
- * @parent: the new input to clk
- *
- * Re-parent clk to use parent as its new input source.  If clk is in
- * prepared state, the clk will get enabled for the duration of this call. If
- * that's not acceptable for a specific clk (Eg: the consumer can't handle
- * that, the reparenting is glitchy in hardware, etc), use the
- * CLK_SET_PARENT_GATE flag to allow reparenting only when clk is unprepared.
- *
- * After successfully changing clk's parent clk_set_parent will update the
- * clk topology, sysfs topology and propagate rate recalculation via
- * __clk_recalc_rates.
- *
- * Returns 0 on success, -EERROR otherwise.
- */
-int clk_set_parent(struct clk *clk, struct clk *parent)
+static int clk_core_set_parent(struct clk_core *clk, struct clk_core *parent)
 {
 	int ret = 0;
 	int p_index = 0;
@@ -1719,6 +1820,31 @@ out:
 
 	return ret;
 }
+
+/**
+ * clk_set_parent - switch the parent of a mux clk
+ * @clk: the mux clk whose input we are switching
+ * @parent: the new input to clk
+ *
+ * Re-parent clk to use parent as its new input source.  If clk is in
+ * prepared state, the clk will get enabled for the duration of this call. If
+ * that's not acceptable for a specific clk (Eg: the consumer can't handle
+ * that, the reparenting is glitchy in hardware, etc), use the
+ * CLK_SET_PARENT_GATE flag to allow reparenting only when clk is unprepared.
+ *
+ * After successfully changing clk's parent clk_set_parent will update the
+ * clk topology, sysfs topology and propagate rate recalculation via
+ * __clk_recalc_rates.
+ *
+ * Returns 0 on success, -EERROR otherwise.
+ */
+int clk_set_parent(struct clk *clk, struct clk *parent)
+{
+	if (!clk)
+		return 0;
+
+	return clk_core_set_parent(clk->core, parent ? parent->core : NULL);
+}
 EXPORT_SYMBOL_GPL(clk_set_parent);
 
 /**
@@ -1755,13 +1881,13 @@ int clk_set_phase(struct clk *clk, int degrees)
 
 	clk_prepare_lock();
 
-	if (!clk->ops->set_phase)
+	if (!clk->core->ops->set_phase)
 		goto out_unlock;
 
-	ret = clk->ops->set_phase(clk->hw, degrees);
+	ret = clk->core->ops->set_phase(clk->core->hw, degrees);
 
 	if (!ret)
-		clk->phase = degrees;
+		clk->core->phase = degrees;
 
 out_unlock:
 	clk_prepare_unlock();
@@ -1770,14 +1896,7 @@ out:
 	return ret;
 }
 
-/**
- * clk_get_phase - return the phase shift of a clock signal
- * @clk: clock signal source
- *
- * Returns the phase shift of a clock node in degrees, otherwise returns
- * -EERROR.
- */
-int clk_get_phase(struct clk *clk)
+static int clk_core_get_phase(struct clk_core *clk)
 {
 	int ret = 0;
 
@@ -1793,26 +1912,44 @@ out:
 }
 
 /**
+ * clk_get_phase - return the phase shift of a clock signal
+ * @clk: clock signal source
+ *
+ * Returns the phase shift of a clock node in degrees, otherwise returns
+ * -EERROR.
+ */
+int clk_get_phase(struct clk *clk)
+{
+	if (!clk)
+		return 0;
+
+	return clk_core_get_phase(clk->core);
+}
+
+/**
  * __clk_init - initialize the data structures in a struct clk
  * @dev:	device initializing this clk, placeholder for now
  * @clk:	clk being initialized
  *
- * Initializes the lists in struct clk, queries the hardware for the
+ * Initializes the lists in struct clk_core, queries the hardware for the
  * parent and rate and sets them both.
  */
-int __clk_init(struct device *dev, struct clk *clk)
+int __clk_init(struct device *dev, struct clk *clk_user)
 {
 	int i, ret = 0;
-	struct clk *orphan;
+	struct clk_core *orphan;
 	struct hlist_node *tmp2;
+	struct clk_core *clk;
 
-	if (!clk)
+	if (!clk_user)
 		return -EINVAL;
 
+	clk = clk_user->core;
+
 	clk_prepare_lock();
 
 	/* check to see if a clock with this name is already registered */
-	if (__clk_lookup(clk->name)) {
+	if (clk_core_lookup(clk->name)) {
 		pr_debug("%s: clk %s already initialized\n",
 				__func__, clk->name);
 		ret = -EEXIST;
@@ -1864,7 +2001,7 @@ int __clk_init(struct device *dev, struct clk *clk)
 		clk->parents = kcalloc(clk->num_parents, sizeof(struct clk *),
 					GFP_KERNEL);
 		/*
-		 * __clk_lookup returns NULL for parents that have not been
+		 * clk_core_lookup returns NULL for parents that have not been
 		 * clk_init'd; thus any access to clk->parents[] must check
 		 * for a NULL pointer.  We can always perform lazy lookups for
 		 * missing parents later on.
@@ -1872,7 +2009,7 @@ int __clk_init(struct device *dev, struct clk *clk)
 		if (clk->parents)
 			for (i = 0; i < clk->num_parents; i++)
 				clk->parents[i] =
-					__clk_lookup(clk->parent_names[i]);
+					clk_core_lookup(clk->parent_names[i]);
 	}
 
 	clk->parent = __clk_init_parent(clk);
@@ -1928,7 +2065,7 @@ int __clk_init(struct device *dev, struct clk *clk)
 	 */
 	if (clk->ops->recalc_rate)
 		clk->rate = clk->ops->recalc_rate(clk->hw,
-				__clk_get_rate(clk->parent));
+				clk_core_get_rate_nolock(clk->parent));
 	else if (clk->parent)
 		clk->rate = clk->parent->rate;
 	else
@@ -1942,13 +2079,13 @@ int __clk_init(struct device *dev, struct clk *clk)
 		if (orphan->num_parents && orphan->ops->get_parent) {
 			i = orphan->ops->get_parent(orphan->hw);
 			if (!strcmp(clk->name, orphan->parent_names[i]))
-				__clk_reparent(orphan, clk);
+				clk_core_reparent(orphan, clk);
 			continue;
 		}
 
 		for (i = 0; i < orphan->num_parents; i++)
 			if (!strcmp(clk->name, orphan->parent_names[i])) {
-				__clk_reparent(orphan, clk);
+				clk_core_reparent(orphan, clk);
 				break;
 			}
 	 }
@@ -1974,6 +2111,26 @@ out:
 	return ret;
 }
 
+struct clk *__clk_create_clk(struct clk_hw *hw, const char *dev_id,
+			     const char *con_id)
+{
+	struct clk *clk;
+
+	/* This is to allow this function to be chained to others */
+	if (!hw || IS_ERR(hw))
+		return (struct clk *) hw;
+
+	clk = kzalloc(sizeof(*clk), GFP_KERNEL);
+	if (!clk)
+		return ERR_PTR(-ENOMEM);
+
+	clk->core = hw->core;
+	clk->dev_id = dev_id;
+	clk->con_id = con_id;
+
+	return clk;
+}
+
 /**
  * clk_register - allocate a new clock, register it and return an opaque cookie
  * @dev: device that is registering this clock
@@ -1988,7 +2145,7 @@ out:
 struct clk *clk_register(struct device *dev, struct clk_hw *hw)
 {
 	int i, ret;
-	struct clk *clk;
+	struct clk_core *clk;
 
 	clk = kzalloc(sizeof(*clk), GFP_KERNEL);
 	if (!clk) {
@@ -2009,7 +2166,7 @@ struct clk *clk_register(struct device *dev, struct clk_hw *hw)
 	clk->hw = hw;
 	clk->flags = hw->init->flags;
 	clk->num_parents = hw->init->num_parents;
-	hw->clk = clk;
+	hw->core = clk;
 
 	/* allocate local copy in case parent_names is __initdata */
 	clk->parent_names = kcalloc(clk->num_parents, sizeof(char *),
@@ -2033,10 +2190,19 @@ struct clk *clk_register(struct device *dev, struct clk_hw *hw)
 		}
 	}
 
-	ret = __clk_init(dev, clk);
+	hw->clk = __clk_create_clk(hw, NULL, NULL);
+	if (IS_ERR(hw->clk)) {
+		pr_err("%s: could not allocate per-user clk\n", __func__);
+		ret = PTR_ERR(hw->clk);
+		goto fail_parent_names_copy;
+	}
+
+	ret = __clk_init(dev, hw->clk);
 	if (!ret)
-		return clk;
+		return hw->clk;
 
+	kfree(hw->clk);
+	hw->clk = NULL;
 fail_parent_names_copy:
 	while (--i >= 0)
 		kfree(clk->parent_names[i]);
@@ -2056,7 +2222,7 @@ EXPORT_SYMBOL_GPL(clk_register);
  */
 static void __clk_release(struct kref *ref)
 {
-	struct clk *clk = container_of(ref, struct clk, ref);
+	struct clk_core *clk = container_of(ref, struct clk_core, ref);
 	int i = clk->num_parents;
 
 	kfree(clk->parents);
@@ -2114,12 +2280,13 @@ void clk_unregister(struct clk *clk)
 	if (!clk || WARN_ON_ONCE(IS_ERR(clk)))
 		return;
 
-	clk_debug_unregister(clk);
+	clk_debug_unregister(clk->core);
 
 	clk_prepare_lock();
 
-	if (clk->ops == &clk_nodrv_ops) {
-		pr_err("%s: unregistered clock: %s\n", __func__, clk->name);
+	if (clk->core->ops == &clk_nodrv_ops) {
+		pr_err("%s: unregistered clock: %s\n", __func__,
+		       clk->core->name);
 		return;
 	}
 	/*
@@ -2127,24 +2294,25 @@ void clk_unregister(struct clk *clk)
 	 * a reference to this clock.
 	 */
 	flags = clk_enable_lock();
-	clk->ops = &clk_nodrv_ops;
+	clk->core->ops = &clk_nodrv_ops;
 	clk_enable_unlock(flags);
 
-	if (!hlist_empty(&clk->children)) {
-		struct clk *child;
+	if (!hlist_empty(&clk->core->children)) {
+		struct clk_core *child;
 		struct hlist_node *t;
 
 		/* Reparent all children to the orphan list. */
-		hlist_for_each_entry_safe(child, t, &clk->children, child_node)
-			clk_set_parent(child, NULL);
+		hlist_for_each_entry_safe(child, t, &clk->core->children,
+					  child_node)
+			clk_core_set_parent(child, NULL);
 	}
 
-	hlist_del_init(&clk->child_node);
+	hlist_del_init(&clk->core->child_node);
 
-	if (clk->prepare_count)
+	if (clk->core->prepare_count)
 		pr_warn("%s: unregistering prepared clock: %s\n",
-					__func__, clk->name);
-	kref_put(&clk->ref, __clk_release);
+					__func__, clk->core->name);
+	kref_put(&clk->core->ref, __clk_release);
 
 	clk_prepare_unlock();
 }
@@ -2212,30 +2380,39 @@ EXPORT_SYMBOL_GPL(devm_clk_unregister);
  */
 int __clk_get(struct clk *clk)
 {
-	if (clk) {
-		if (!try_module_get(clk->owner))
+	struct clk_core *core = !clk ? NULL : clk->core;
+
+	if (core) {
+		if (!try_module_get(core->owner))
 			return 0;
 
-		kref_get(&clk->ref);
+		kref_get(&core->ref);
 	}
 	return 1;
 }
 
-void __clk_put(struct clk *clk)
+static void clk_core_put(struct clk_core *core)
 {
 	struct module *owner;
 
-	if (!clk || WARN_ON_ONCE(IS_ERR(clk)))
-		return;
+	owner = core->owner;
 
 	clk_prepare_lock();
-	owner = clk->owner;
-	kref_put(&clk->ref, __clk_release);
+	kref_put(&core->ref, __clk_release);
 	clk_prepare_unlock();
 
 	module_put(owner);
 }
 
+void __clk_put(struct clk *clk)
+{
+	if (!clk || WARN_ON_ONCE(IS_ERR(clk)))
+		return;
+
+	clk_core_put(clk->core);
+	kfree(clk);
+}
+
 /***        clk rate change notifiers        ***/
 
 /**
@@ -2288,7 +2465,7 @@ int clk_notifier_register(struct clk *clk, struct notifier_block *nb)
 
 	ret = srcu_notifier_chain_register(&cn->notifier_head, nb);
 
-	clk->notifier_count++;
+	clk->core->notifier_count++;
 
 out:
 	clk_prepare_unlock();
@@ -2325,7 +2502,7 @@ int clk_notifier_unregister(struct clk *clk, struct notifier_block *nb)
 	if (cn->clk == clk) {
 		ret = srcu_notifier_chain_unregister(&cn->notifier_head, nb);
 
-		clk->notifier_count--;
+		clk->core->notifier_count--;
 
 		/* XXX the notifier code should handle this better */
 		if (!cn->notifier_head.head) {
diff --git a/drivers/clk/clk.h b/drivers/clk/clk.h
index c798138..23c44e5 100644
--- a/drivers/clk/clk.h
+++ b/drivers/clk/clk.h
@@ -9,9 +9,14 @@
  * published by the Free Software Foundation.
  */
 
+struct clk_hw;
+
 #if defined(CONFIG_OF) && defined(CONFIG_COMMON_CLK)
 struct clk *of_clk_get_by_clkspec(struct of_phandle_args *clkspec);
 struct clk *__of_clk_get_from_provider(struct of_phandle_args *clkspec);
 void of_clk_lock(void);
 void of_clk_unlock(void);
 #endif
+
+struct clk *__clk_create_clk(struct clk_hw *hw, const char *dev_id,
+			     const char *con_id);
diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c
index da4bda8..901d242 100644
--- a/drivers/clk/clkdev.c
+++ b/drivers/clk/clkdev.c
@@ -19,6 +19,7 @@
 #include <linux/mutex.h>
 #include <linux/clk.h>
 #include <linux/clkdev.h>
+#include <linux/clk-provider.h>
 #include <linux/of.h>
 
 #include "clk.h"
@@ -53,7 +54,7 @@ struct clk *of_clk_get_by_clkspec(struct of_phandle_args *clkspec)
 	return clk;
 }
 
-struct clk *of_clk_get(struct device_node *np, int index)
+static struct clk *__of_clk_get(struct device_node *np, int index)
 {
 	struct of_phandle_args clkspec;
 	struct clk *clk;
@@ -69,20 +70,24 @@ struct clk *of_clk_get(struct device_node *np, int index)
 
 	clk = of_clk_get_by_clkspec(&clkspec);
 	of_node_put(clkspec.np);
+
+	return clk;
+}
+
+struct clk *of_clk_get(struct device_node *np, int index)
+{
+	struct clk *clk = __of_clk_get(np, index);
+
+	if (!IS_ERR(clk))
+		clk = __clk_create_clk(__clk_get_hw(clk), np->full_name, NULL);
+
 	return clk;
 }
 EXPORT_SYMBOL(of_clk_get);
 
-/**
- * of_clk_get_by_name() - Parse and lookup a clock referenced by a device node
- * @np: pointer to clock consumer node
- * @name: name of consumer's clock input, or NULL for the first clock reference
- *
- * This function parses the clocks and clock-names properties,
- * and uses them to look up the struct clk from the registered list of clock
- * providers.
- */
-struct clk *of_clk_get_by_name(struct device_node *np, const char *name)
+static struct clk *__of_clk_get_by_name(struct device_node *np,
+					const char *dev_id,
+					const char *name)
 {
 	struct clk *clk = ERR_PTR(-ENOENT);
 
@@ -97,9 +102,11 @@ struct clk *of_clk_get_by_name(struct device_node *np, const char *name)
 		 */
 		if (name)
 			index = of_property_match_string(np, "clock-names", name);
-		clk = of_clk_get(np, index);
-		if (!IS_ERR(clk))
+		clk = __of_clk_get(np, index);
+		if (!IS_ERR(clk)) {
+			clk = __clk_create_clk(__clk_get_hw(clk), dev_id, name);
 			break;
+		}
 		else if (name && index >= 0) {
 			if (PTR_ERR(clk) != -EPROBE_DEFER)
 				pr_err("ERROR: could not get clock %s:%s(%i)\n",
@@ -119,7 +126,33 @@ struct clk *of_clk_get_by_name(struct device_node *np, const char *name)
 
 	return clk;
 }
+
+/**
+ * of_clk_get_by_name() - Parse and lookup a clock referenced by a device node
+ * @np: pointer to clock consumer node
+ * @name: name of consumer's clock input, or NULL for the first clock reference
+ *
+ * This function parses the clocks and clock-names properties,
+ * and uses them to look up the struct clk from the registered list of clock
+ * providers.
+ */
+struct clk *of_clk_get_by_name(struct device_node *np, const char *name)
+{
+	if (!np)
+		return ERR_PTR(-ENOENT);
+
+	return __of_clk_get_by_name(np, np->full_name, name);
+}
 EXPORT_SYMBOL(of_clk_get_by_name);
+
+#else /* defined(CONFIG_OF) && defined(CONFIG_COMMON_CLK) */
+
+static struct clk *__of_clk_get_by_name(struct device_node *np,
+					const char *dev_id,
+					const char *name)
+{
+	return ERR_PTR(-ENOENT);
+}
 #endif
 
 /*
@@ -168,14 +201,29 @@ static struct clk_lookup *clk_find(const char *dev_id, const char *con_id)
 struct clk *clk_get_sys(const char *dev_id, const char *con_id)
 {
 	struct clk_lookup *cl;
+	struct clk *clk = NULL;
 
 	mutex_lock(&clocks_mutex);
+
 	cl = clk_find(dev_id, con_id);
-	if (cl && !__clk_get(cl->clk))
+	if (!cl)
+		goto out;
+
+	if (!__clk_get(cl->clk)) {
 		cl = NULL;
+		goto out;
+	}
+
+#if defined(CONFIG_COMMON_CLK)
+	clk = __clk_create_clk(__clk_get_hw(cl->clk), dev_id, con_id);
+#else
+	clk = cl->clk;
+#endif
+
+out:
 	mutex_unlock(&clocks_mutex);
 
-	return cl ? cl->clk : ERR_PTR(-ENOENT);
+	return cl ? clk : ERR_PTR(-ENOENT);
 }
 EXPORT_SYMBOL(clk_get_sys);
 
@@ -185,10 +233,8 @@ struct clk *clk_get(struct device *dev, const char *con_id)
 	struct clk *clk;
 
 	if (dev) {
-		clk = of_clk_get_by_name(dev->of_node, con_id);
-		if (!IS_ERR(clk))
-			return clk;
-		if (PTR_ERR(clk) == -EPROBE_DEFER)
+		clk = __of_clk_get_by_name(dev->of_node, dev_id, con_id);
+		if (!IS_ERR(clk) || PTR_ERR(clk) == -EPROBE_DEFER)
 			return clk;
 	}
 
diff --git a/include/linux/clk-private.h b/include/linux/clk-private.h
index c5f40d0..ae55d99 100644
--- a/include/linux/clk-private.h
+++ b/include/linux/clk-private.h
@@ -28,20 +28,20 @@
 
 struct module;
 
-struct clk {
+struct clk_core {
 	const char		*name;
 	const struct clk_ops	*ops;
 	struct clk_hw		*hw;
 	struct module		*owner;
-	struct clk		*parent;
+	struct clk_core		*parent;
 	const char		**parent_names;
-	struct clk		**parents;
+	struct clk_core		**parents;
 	u8			num_parents;
 	u8			new_parent_index;
 	unsigned long		rate;
 	unsigned long		new_rate;
-	struct clk		*new_parent;
-	struct clk		*new_child;
+	struct clk_core		*new_parent;
+	struct clk_core		*new_child;
 	unsigned long		flags;
 	unsigned int		enable_count;
 	unsigned int		prepare_count;
@@ -57,6 +57,12 @@ struct clk {
 	struct kref		ref;
 };
 
+struct clk {
+	struct clk_core	*core;
+	const char *dev_id;
+	const char *con_id;
+};
+
 /*
  * DOC: Basic clock implementations common to many platforms
  *
@@ -69,6 +75,9 @@ struct clk {
 #define DEFINE_CLK(_name, _ops, _flags, _parent_names,		\
 		_parents)					\
 	static struct clk _name = {				\
+		.core = &_name##_core				\
+	};							\
+	static struct clk_core _name##_core = {			\
 		.name = #_name,					\
 		.ops = &_ops,					\
 		.hw = &_name##_hw.hw,				\
@@ -81,9 +90,11 @@ struct clk {
 #define DEFINE_CLK_FIXED_RATE(_name, _flags, _rate,		\
 				_fixed_rate_flags)		\
 	static struct clk _name;				\
+	static struct clk_core _name##_core;			\
 	static const char *_name##_parent_names[] = {};		\
 	static struct clk_fixed_rate _name##_hw = {		\
 		.hw = {						\
+			.core = &_name##_core,			\
 			.clk = &_name,				\
 		},						\
 		.fixed_rate = _rate,				\
@@ -96,14 +107,16 @@ struct clk {
 				_flags, _reg, _bit_idx,		\
 				_gate_flags, _lock)		\
 	static struct clk _name;				\
+	static struct clk_core _name##_core;			\
 	static const char *_name##_parent_names[] = {		\
 		_parent_name,					\
 	};							\
-	static struct clk *_name##_parents[] = {		\
+	static struct clk_core *_name##_parents[] = {		\
 		_parent_ptr,					\
 	};							\
 	static struct clk_gate _name##_hw = {			\
 		.hw = {						\
+			.core = &_name##_core,			\
 			.clk = &_name,				\
 		},						\
 		.reg = _reg,					\
@@ -118,14 +131,16 @@ struct clk {
 				_flags, _reg, _shift, _width,	\
 				_divider_flags, _table, _lock)	\
 	static struct clk _name;				\
+	static struct clk_core _name##_core;			\
 	static const char *_name##_parent_names[] = {		\
 		_parent_name,					\
 	};							\
-	static struct clk *_name##_parents[] = {		\
+	static struct clk_core *_name##_parents[] = {		\
 		_parent_ptr,					\
 	};							\
 	static struct clk_divider _name##_hw = {		\
 		.hw = {						\
+			.core = &_name##_core,			\
 			.clk = &_name,				\
 		},						\
 		.reg = _reg,					\
@@ -157,8 +172,10 @@ struct clk {
 				_reg, _shift, _width,		\
 				_mux_flags, _lock)		\
 	static struct clk _name;				\
+	static struct clk_core _name##_core;			\
 	static struct clk_mux _name##_hw = {			\
 		.hw = {						\
+			.core = &_name##_core,			\
 			.clk = &_name,				\
 		},						\
 		.reg = _reg,					\
@@ -174,14 +191,16 @@ struct clk {
 				_parent_ptr, _flags,		\
 				_mult, _div)			\
 	static struct clk _name;				\
+	static struct clk_core _name##_core;			\
 	static const char *_name##_parent_names[] = {		\
 		_parent_name,					\
 	};							\
-	static struct clk *_name##_parents[] = {		\
+	static struct clk_core *_name##_parents[] = {		\
 		_parent_ptr,					\
 	};							\
 	static struct clk_fixed_factor _name##_hw = {		\
 		.hw = {						\
+			.core = &_name##_core,			\
 			.clk = &_name,				\
 		},						\
 		.mult = _mult,					\
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index d936409..9afd438 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -33,6 +33,7 @@
 #define CLK_GET_ACCURACY_NOCACHE BIT(8) /* do not use the cached clk accuracy */
 
 struct clk_hw;
+struct clk_core;
 struct dentry;
 
 /**
@@ -216,13 +217,17 @@ struct clk_init_data {
  * clk_foo and then referenced by the struct clk instance that uses struct
  * clk_foo's clk_ops
  *
- * @clk: pointer to the struct clk instance that points back to this struct
- * clk_hw instance
+ * @core: pointer to the struct clk_core instance that points back to this
+ * struct clk_hw instance
+ *
+ * @clk: pointer to the per-user struct clk instance that can be used to call
+ * into the clk API
  *
  * @init: pointer to struct clk_init_data that contains the init data shared
  * with the common clock framework.
  */
 struct clk_hw {
+	struct clk_core *core;
 	struct clk *clk;
 	const struct clk_init_data *init;
 };
@@ -556,9 +561,6 @@ long __clk_mux_determine_rate(struct clk_hw *hw, unsigned long rate,
 /*
  * FIXME clock api without lock protection
  */
-int __clk_prepare(struct clk *clk);
-void __clk_unprepare(struct clk *clk);
-void __clk_reparent(struct clk *clk, struct clk *new_parent);
 unsigned long __clk_round_rate(struct clk *clk, unsigned long rate);
 
 struct of_device_id;
-- 
1.9.3


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

* [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
@ 2015-01-23 11:03   ` Tomeu Vizoso
  0 siblings, 0 replies; 186+ messages in thread
From: Tomeu Vizoso @ 2015-01-23 11:03 UTC (permalink / raw)
  To: linux-arm-kernel

Moves clock state to struct clk_core, but takes care to change as little API as
possible.

struct clk_hw still has a pointer to a struct clk, which is the
implementation's per-user clk instance, for backwards compatibility.

The struct clk that clk_get_parent() returns isn't owned by the caller, but by
the clock implementation, so the former shouldn't call clk_put() on it.

Because some boards in mach-omap2 still register clocks statically, their clock
registration had to be updated to take into account that the clock information
is stored in struct clk_core now.

Signed-off-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
Reviewed-by: Stephen Boyd <sboyd@codeaurora.org>

---
v13:	* Split some lines to 80 columns
	* Add dev_id parameter to __of_clk_get_by_name so it can be
	called by clk_get without losing information

v12:	* Move __clk_create_clk so it's later next to __clk_free_clk
	* NULLify a just-free'd pointer
	* Check the value returned by __clk_create_clk in clk_register

v11:	* Allow for clk_set_parent to be called with a NULL parent

v10:	* Add more missing NULL checks
	* Remove __clk_reparent as it's now unused
	* Remove clk_core_round_rate as it's now unused
	* Call nolock variants from __clk_mux_determine_rate

v9:	* Add missing NULL checks
	* Remove __clk_prepare and __clk_unprepare as they are unused
	  now

v7:	* Add stub for __of_clk_get_by_name to fix builds without OF

v6:	* Guard against NULL pointer

v4:	* Remove unused function __clk_core_to_clk
	* Use "core" more often as the name for struct clk_core* variables
	* Make sure we don't lose information about the caller in of_clk_get_*

v3:	* Rebase on top of linux-next 20141009

v2:	* Remove exported functions that aren't really used outside clk.c
	* Rename new internal functions to clk_core_ prefix
	* Remove redundant checks for error pointers in *_get_parent
	* Change __clk_create_clk to take a struct clk_hw instead
	* Match the original error behavior in clk_get_sys
---
 arch/arm/mach-omap2/cclock3xxx_data.c   | 111 ++++--
 arch/arm/mach-omap2/clock.h             |  11 +-
 arch/arm/mach-omap2/clock_common_data.c |   5 +-
 drivers/clk/clk.c                       | 621 ++++++++++++++++++++------------
 drivers/clk/clk.h                       |   5 +
 drivers/clk/clkdev.c                    |  84 ++++-
 include/linux/clk-private.h             |  35 +-
 include/linux/clk-provider.h            |  12 +-
 8 files changed, 589 insertions(+), 295 deletions(-)

diff --git a/arch/arm/mach-omap2/cclock3xxx_data.c b/arch/arm/mach-omap2/cclock3xxx_data.c
index 644ff32..adb4e64 100644
--- a/arch/arm/mach-omap2/cclock3xxx_data.c
+++ b/arch/arm/mach-omap2/cclock3xxx_data.c
@@ -82,7 +82,7 @@ DEFINE_CLK_MUX(osc_sys_ck, osc_sys_ck_parent_names, NULL, 0x0,
 	       OMAP3430_PRM_CLKSEL, OMAP3430_SYS_CLKIN_SEL_SHIFT,
 	       OMAP3430_SYS_CLKIN_SEL_WIDTH, 0x0, NULL);
 
-DEFINE_CLK_DIVIDER(sys_ck, "osc_sys_ck", &osc_sys_ck, 0x0,
+DEFINE_CLK_DIVIDER(sys_ck, "osc_sys_ck", &osc_sys_ck_core, 0x0,
 		   OMAP3430_PRM_CLKSRC_CTRL, OMAP_SYSCLKDIV_SHIFT,
 		   OMAP_SYSCLKDIV_WIDTH, CLK_DIVIDER_ONE_BASED, NULL);
 
@@ -132,7 +132,7 @@ static struct clk_hw_omap dpll3_ck_hw = {
 
 DEFINE_STRUCT_CLK(dpll3_ck, dpll3_ck_parent_names, dpll3_ck_ops);
 
-DEFINE_CLK_DIVIDER(dpll3_m2_ck, "dpll3_ck", &dpll3_ck, 0x0,
+DEFINE_CLK_DIVIDER(dpll3_m2_ck, "dpll3_ck", &dpll3_ck_core, 0x0,
 		   OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
 		   OMAP3430_CORE_DPLL_CLKOUT_DIV_SHIFT,
 		   OMAP3430_CORE_DPLL_CLKOUT_DIV_WIDTH,
@@ -149,12 +149,12 @@ static const struct clk_ops core_ck_ops = {};
 DEFINE_STRUCT_CLK_HW_OMAP(core_ck, NULL);
 DEFINE_STRUCT_CLK(core_ck, core_ck_parent_names, core_ck_ops);
 
-DEFINE_CLK_DIVIDER(l3_ick, "core_ck", &core_ck, 0x0,
+DEFINE_CLK_DIVIDER(l3_ick, "core_ck", &core_ck_core, 0x0,
 		   OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL),
 		   OMAP3430_CLKSEL_L3_SHIFT, OMAP3430_CLKSEL_L3_WIDTH,
 		   CLK_DIVIDER_ONE_BASED, NULL);
 
-DEFINE_CLK_DIVIDER(l4_ick, "l3_ick", &l3_ick, 0x0,
+DEFINE_CLK_DIVIDER(l4_ick, "l3_ick", &l3_ick_core, 0x0,
 		   OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL),
 		   OMAP3430_CLKSEL_L4_SHIFT, OMAP3430_CLKSEL_L4_WIDTH,
 		   CLK_DIVIDER_ONE_BASED, NULL);
@@ -275,9 +275,9 @@ static struct clk_hw_omap dpll1_ck_hw = {
 
 DEFINE_STRUCT_CLK(dpll1_ck, dpll3_ck_parent_names, dpll1_ck_ops);
 
-DEFINE_CLK_FIXED_FACTOR(dpll1_x2_ck, "dpll1_ck", &dpll1_ck, 0x0, 2, 1);
+DEFINE_CLK_FIXED_FACTOR(dpll1_x2_ck, "dpll1_ck", &dpll1_ck_core, 0x0, 2, 1);
 
-DEFINE_CLK_DIVIDER(dpll1_x2m2_ck, "dpll1_x2_ck", &dpll1_x2_ck, 0x0,
+DEFINE_CLK_DIVIDER(dpll1_x2m2_ck, "dpll1_x2_ck", &dpll1_x2_ck_core, 0x0,
 		   OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_CLKSEL2_PLL),
 		   OMAP3430_MPU_DPLL_CLKOUT_DIV_SHIFT,
 		   OMAP3430_MPU_DPLL_CLKOUT_DIV_WIDTH,
@@ -292,7 +292,7 @@ static const char *mpu_ck_parent_names[] = {
 DEFINE_STRUCT_CLK_HW_OMAP(mpu_ck, "mpu_clkdm");
 DEFINE_STRUCT_CLK(mpu_ck, mpu_ck_parent_names, core_l4_ick_ops);
 
-DEFINE_CLK_DIVIDER(arm_fck, "mpu_ck", &mpu_ck, 0x0,
+DEFINE_CLK_DIVIDER(arm_fck, "mpu_ck", &mpu_ck_core, 0x0,
 		   OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_IDLEST_PLL),
 		   OMAP3430_ST_MPU_CLK_SHIFT, OMAP3430_ST_MPU_CLK_WIDTH,
 		   0x0, NULL);
@@ -424,7 +424,7 @@ static const struct clk_div_table dpll4_mx_ck_div_table[] = {
 	{ .div = 0 },
 };
 
-DEFINE_CLK_DIVIDER(dpll4_m5_ck, "dpll4_ck", &dpll4_ck, 0x0,
+DEFINE_CLK_DIVIDER(dpll4_m5_ck, "dpll4_ck", &dpll4_ck_core, 0x0,
 		   OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_CLKSEL),
 		   OMAP3430_CLKSEL_CAM_SHIFT, OMAP3630_CLKSEL_CAM_WIDTH,
 		   CLK_DIVIDER_ONE_BASED, NULL);
@@ -466,7 +466,7 @@ static struct clk_hw_omap dpll4_m5x2_ck_hw = {
 DEFINE_STRUCT_CLK_FLAGS(dpll4_m5x2_ck, dpll4_m5x2_ck_parent_names,
 			dpll4_m5x2_ck_ops, CLK_SET_RATE_PARENT);
 
-static struct clk dpll4_m5x2_ck_3630 = {
+static struct clk_core dpll4_m5x2_ck_3630_core = {
 	.name		= "dpll4_m5x2_ck",
 	.hw		= &dpll4_m5x2_ck_hw.hw,
 	.parent_names	= dpll4_m5x2_ck_parent_names,
@@ -475,6 +475,10 @@ static struct clk dpll4_m5x2_ck_3630 = {
 	.flags		= CLK_SET_RATE_PARENT,
 };
 
+static struct clk dpll4_m5x2_ck_3630 = {
+	.core = &dpll4_m5x2_ck_3630_core,
+};
+
 static struct clk cam_mclk;
 
 static const char *cam_mclk_parent_names[] = {
@@ -490,7 +494,7 @@ static struct clk_hw_omap cam_mclk_hw = {
 	.clkdm_name	= "cam_clkdm",
 };
 
-static struct clk cam_mclk = {
+static struct clk_core cam_mclk_core = {
 	.name		= "cam_mclk",
 	.hw		= &cam_mclk_hw.hw,
 	.parent_names	= cam_mclk_parent_names,
@@ -499,6 +503,10 @@ static struct clk cam_mclk = {
 	.flags		= CLK_SET_RATE_PARENT,
 };
 
+static struct clk cam_mclk = {
+	.core = &cam_mclk_core,
+};
+
 static const struct clksel_rate clkout2_src_core_rates[] = {
 	{ .div = 1, .val = 0, .flags = RATE_IN_3XXX },
 	{ .div = 0 }
@@ -514,7 +522,7 @@ static const struct clksel_rate clkout2_src_96m_rates[] = {
 	{ .div = 0 }
 };
 
-DEFINE_CLK_DIVIDER(dpll4_m2_ck, "dpll4_ck", &dpll4_ck, 0x0,
+DEFINE_CLK_DIVIDER(dpll4_m2_ck, "dpll4_ck", &dpll4_ck_core, 0x0,
 		   OMAP_CM_REGADDR(PLL_MOD, OMAP3430_CM_CLKSEL3),
 		   OMAP3430_DIV_96M_SHIFT, OMAP3630_DIV_96M_WIDTH,
 		   CLK_DIVIDER_ONE_BASED, NULL);
@@ -538,7 +546,7 @@ static struct clk_hw_omap dpll4_m2x2_ck_hw = {
 
 DEFINE_STRUCT_CLK(dpll4_m2x2_ck, dpll4_m2x2_ck_parent_names, dpll4_m5x2_ck_ops);
 
-static struct clk dpll4_m2x2_ck_3630 = {
+static struct clk_core dpll4_m2x2_ck_3630_core = {
 	.name		= "dpll4_m2x2_ck",
 	.hw		= &dpll4_m2x2_ck_hw.hw,
 	.parent_names	= dpll4_m2x2_ck_parent_names,
@@ -546,6 +554,10 @@ static struct clk dpll4_m2x2_ck_3630 = {
 	.ops		= &dpll4_m5x2_ck_3630_ops,
 };
 
+static struct clk dpll4_m2x2_ck_3630 = {
+	.core = &dpll4_m2x2_ck_3630_core,
+};
+
 static struct clk omap_96m_alwon_fck;
 
 static const char *omap_96m_alwon_fck_parent_names[] = {
@@ -570,7 +582,7 @@ static const struct clksel_rate clkout2_src_54m_rates[] = {
 	{ .div = 0 }
 };
 
-DEFINE_CLK_DIVIDER_TABLE(dpll4_m3_ck, "dpll4_ck", &dpll4_ck, 0x0,
+DEFINE_CLK_DIVIDER_TABLE(dpll4_m3_ck, "dpll4_ck", &dpll4_ck_core, 0x0,
 		   OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_CLKSEL),
 		   OMAP3430_CLKSEL_TV_SHIFT, OMAP3630_CLKSEL_TV_WIDTH,
 		   0, dpll4_mx_ck_div_table, NULL);
@@ -594,7 +606,7 @@ static struct clk_hw_omap dpll4_m3x2_ck_hw = {
 
 DEFINE_STRUCT_CLK(dpll4_m3x2_ck, dpll4_m3x2_ck_parent_names, dpll4_m5x2_ck_ops);
 
-static struct clk dpll4_m3x2_ck_3630 = {
+static struct clk_core dpll4_m3x2_ck_3630_core = {
 	.name		= "dpll4_m3x2_ck",
 	.hw		= &dpll4_m3x2_ck_hw.hw,
 	.parent_names	= dpll4_m3x2_ck_parent_names,
@@ -602,6 +614,10 @@ static struct clk dpll4_m3x2_ck_3630 = {
 	.ops		= &dpll4_m5x2_ck_3630_ops,
 };
 
+static struct clk dpll4_m3x2_ck_3630 = {
+	.core = &dpll4_m3x2_ck_3630_core,
+};
+
 static const char *omap_54m_fck_parent_names[] = {
 	"dpll4_m3x2_ck", "sys_altclk",
 };
@@ -677,7 +693,8 @@ static struct clk_hw_omap omap_48m_fck_hw = {
 
 DEFINE_STRUCT_CLK(omap_48m_fck, omap_48m_fck_parent_names, omap_48m_fck_ops);
 
-DEFINE_CLK_FIXED_FACTOR(omap_12m_fck, "omap_48m_fck", &omap_48m_fck, 0x0, 1, 4);
+DEFINE_CLK_FIXED_FACTOR(omap_12m_fck, "omap_48m_fck", &omap_48m_fck_core, 0x0,
+			1, 4);
 
 static struct clk core_12m_fck;
 
@@ -723,7 +740,8 @@ static const char *core_l3_ick_parent_names[] = {
 DEFINE_STRUCT_CLK_HW_OMAP(core_l3_ick, "core_l3_clkdm");
 DEFINE_STRUCT_CLK(core_l3_ick, core_l3_ick_parent_names, core_l4_ick_ops);
 
-DEFINE_CLK_FIXED_FACTOR(dpll3_m2x2_ck, "dpll3_m2_ck", &dpll3_m2_ck, 0x0, 2, 1);
+DEFINE_CLK_FIXED_FACTOR(dpll3_m2x2_ck, "dpll3_m2_ck", &dpll3_m2_ck_core, 0x0,
+			2, 1);
 
 static struct clk corex2_fck;
 
@@ -809,7 +827,7 @@ static struct clk_hw_omap des2_ick_hw = {
 
 DEFINE_STRUCT_CLK(des2_ick, aes2_ick_parent_names, aes2_ick_ops);
 
-DEFINE_CLK_DIVIDER(dpll1_fck, "core_ck", &core_ck, 0x0,
+DEFINE_CLK_DIVIDER(dpll1_fck, "core_ck", &core_ck_core, 0x0,
 		   OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_CLKSEL1_PLL),
 		   OMAP3430_MPU_CLK_SRC_SHIFT, OMAP3430_MPU_CLK_SRC_WIDTH,
 		   CLK_DIVIDER_ONE_BASED, NULL);
@@ -852,18 +870,18 @@ static struct clk_hw_omap dpll2_ck_hw = {
 
 DEFINE_STRUCT_CLK(dpll2_ck, dpll3_ck_parent_names, dpll1_ck_ops);
 
-DEFINE_CLK_DIVIDER(dpll2_fck, "core_ck", &core_ck, 0x0,
+DEFINE_CLK_DIVIDER(dpll2_fck, "core_ck", &core_ck_core, 0x0,
 		   OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, OMAP3430_CM_CLKSEL1_PLL),
 		   OMAP3430_IVA2_CLK_SRC_SHIFT, OMAP3430_IVA2_CLK_SRC_WIDTH,
 		   CLK_DIVIDER_ONE_BASED, NULL);
 
-DEFINE_CLK_DIVIDER(dpll2_m2_ck, "dpll2_ck", &dpll2_ck, 0x0,
+DEFINE_CLK_DIVIDER(dpll2_m2_ck, "dpll2_ck", &dpll2_ck_core, 0x0,
 		   OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, OMAP3430_CM_CLKSEL2_PLL),
 		   OMAP3430_IVA2_DPLL_CLKOUT_DIV_SHIFT,
 		   OMAP3430_IVA2_DPLL_CLKOUT_DIV_WIDTH,
 		   CLK_DIVIDER_ONE_BASED, NULL);
 
-DEFINE_CLK_DIVIDER(dpll3_m3_ck, "dpll3_ck", &dpll3_ck, 0x0,
+DEFINE_CLK_DIVIDER(dpll3_m3_ck, "dpll3_ck", &dpll3_ck_core, 0x0,
 		   OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1),
 		   OMAP3430_DIV_DPLL3_SHIFT, OMAP3430_DIV_DPLL3_WIDTH,
 		   CLK_DIVIDER_ONE_BASED, NULL);
@@ -887,7 +905,7 @@ static struct clk_hw_omap dpll3_m3x2_ck_hw = {
 
 DEFINE_STRUCT_CLK(dpll3_m3x2_ck, dpll3_m3x2_ck_parent_names, dpll4_m5x2_ck_ops);
 
-static struct clk dpll3_m3x2_ck_3630 = {
+static struct clk_core dpll3_m3x2_ck_3630_core = {
 	.name		= "dpll3_m3x2_ck",
 	.hw		= &dpll3_m3x2_ck_hw.hw,
 	.parent_names	= dpll3_m3x2_ck_parent_names,
@@ -895,9 +913,13 @@ static struct clk dpll3_m3x2_ck_3630 = {
 	.ops		= &dpll4_m5x2_ck_3630_ops,
 };
 
-DEFINE_CLK_FIXED_FACTOR(dpll3_x2_ck, "dpll3_ck", &dpll3_ck, 0x0, 2, 1);
+static struct clk dpll3_m3x2_ck_3630 = {
+	.core = &dpll3_m3x2_ck_3630_core,
+};
+
+DEFINE_CLK_FIXED_FACTOR(dpll3_x2_ck, "dpll3_ck", &dpll3_ck_core, 0x0, 2, 1);
 
-DEFINE_CLK_DIVIDER_TABLE(dpll4_m4_ck, "dpll4_ck", &dpll4_ck, 0x0,
+DEFINE_CLK_DIVIDER_TABLE(dpll4_m4_ck, "dpll4_ck", &dpll4_ck_core, 0x0,
 		   OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_CLKSEL),
 		   OMAP3430_CLKSEL_DSS1_SHIFT, OMAP3630_CLKSEL_DSS1_WIDTH,
 		   0, dpll4_mx_ck_div_table, NULL);
@@ -922,7 +944,7 @@ static struct clk_hw_omap dpll4_m4x2_ck_hw = {
 DEFINE_STRUCT_CLK_FLAGS(dpll4_m4x2_ck, dpll4_m4x2_ck_parent_names,
 		dpll4_m5x2_ck_ops, CLK_SET_RATE_PARENT);
 
-static struct clk dpll4_m4x2_ck_3630 = {
+static struct clk_core dpll4_m4x2_ck_3630_core = {
 	.name		= "dpll4_m4x2_ck",
 	.hw		= &dpll4_m4x2_ck_hw.hw,
 	.parent_names	= dpll4_m4x2_ck_parent_names,
@@ -931,7 +953,11 @@ static struct clk dpll4_m4x2_ck_3630 = {
 	.flags		= CLK_SET_RATE_PARENT,
 };
 
-DEFINE_CLK_DIVIDER(dpll4_m6_ck, "dpll4_ck", &dpll4_ck, 0x0,
+static struct clk dpll4_m4x2_ck_3630 = {
+	.core = &dpll4_m4x2_ck_3630_core,
+};
+
+DEFINE_CLK_DIVIDER(dpll4_m6_ck, "dpll4_ck", &dpll4_ck_core, 0x0,
 		   OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1),
 		   OMAP3430_DIV_DPLL4_SHIFT, OMAP3630_DIV_DPLL4_WIDTH,
 		   CLK_DIVIDER_ONE_BASED, NULL);
@@ -955,7 +981,7 @@ static struct clk_hw_omap dpll4_m6x2_ck_hw = {
 
 DEFINE_STRUCT_CLK(dpll4_m6x2_ck, dpll4_m6x2_ck_parent_names, dpll4_m5x2_ck_ops);
 
-static struct clk dpll4_m6x2_ck_3630 = {
+static struct clk_core dpll4_m6x2_ck_3630_core = {
 	.name		= "dpll4_m6x2_ck",
 	.hw		= &dpll4_m6x2_ck_hw.hw,
 	.parent_names	= dpll4_m6x2_ck_parent_names,
@@ -963,7 +989,11 @@ static struct clk dpll4_m6x2_ck_3630 = {
 	.ops		= &dpll4_m5x2_ck_3630_ops,
 };
 
-DEFINE_CLK_FIXED_FACTOR(dpll4_x2_ck, "dpll4_ck", &dpll4_ck, 0x0, 2, 1);
+static struct clk dpll4_m6x2_ck_3630 = {
+	.core = &dpll4_m6x2_ck_3630_core,
+};
+
+DEFINE_CLK_FIXED_FACTOR(dpll4_x2_ck, "dpll4_ck", &dpll4_ck_core, 0x0, 2, 1);
 
 static struct dpll_data dpll5_dd = {
 	.mult_div1_reg	= OMAP_CM_REGADDR(PLL_MOD, OMAP3430ES2_CM_CLKSEL4),
@@ -1000,7 +1030,7 @@ static struct clk_hw_omap dpll5_ck_hw = {
 
 DEFINE_STRUCT_CLK(dpll5_ck, dpll3_ck_parent_names, dpll1_ck_ops);
 
-DEFINE_CLK_DIVIDER(dpll5_m2_ck, "dpll5_ck", &dpll5_ck, 0x0,
+DEFINE_CLK_DIVIDER(dpll5_m2_ck, "dpll5_ck", &dpll5_ck_core, 0x0,
 		   OMAP_CM_REGADDR(PLL_MOD, OMAP3430ES2_CM_CLKSEL5),
 		   OMAP3430ES2_DIV_120M_SHIFT, OMAP3430ES2_DIV_120M_WIDTH,
 		   CLK_DIVIDER_ONE_BASED, NULL);
@@ -1247,7 +1277,7 @@ static struct clk_hw_omap emu_src_ck_hw = {
 
 DEFINE_STRUCT_CLK(emu_src_ck, emu_src_ck_parent_names, emu_src_ck_ops);
 
-DEFINE_CLK_DIVIDER(atclk_fck, "emu_src_ck", &emu_src_ck, 0x0,
+DEFINE_CLK_DIVIDER(atclk_fck, "emu_src_ck", &emu_src_ck_core, 0x0,
 		   OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1),
 		   OMAP3430_CLKSEL_ATCLK_SHIFT, OMAP3430_CLKSEL_ATCLK_WIDTH,
 		   CLK_DIVIDER_ONE_BASED, NULL);
@@ -1298,7 +1328,7 @@ static struct clk_hw_omap gfx_l3_ck_hw = {
 
 DEFINE_STRUCT_CLK(gfx_l3_ck, core_l3_ick_parent_names, aes1_ick_ops);
 
-DEFINE_CLK_DIVIDER(gfx_l3_fck, "l3_ick", &l3_ick, 0x0,
+DEFINE_CLK_DIVIDER(gfx_l3_fck, "l3_ick", &l3_ick_core, 0x0,
 		   OMAP_CM_REGADDR(GFX_MOD, CM_CLKSEL),
 		   OMAP_CLKSEL_GFX_SHIFT, OMAP_CLKSEL_GFX_WIDTH,
 		   CLK_DIVIDER_ONE_BASED, NULL);
@@ -2498,7 +2528,7 @@ static struct clk_hw_omap omap_96m_alwon_fck_3630_hw = {
 	.clksel_mask	= OMAP3630_CLKSEL_96M_MASK,
 };
 
-static struct clk omap_96m_alwon_fck_3630 = {
+static struct clk_core omap_96m_alwon_fck_3630_core = {
 	.name	= "omap_96m_alwon_fck",
 	.hw	= &omap_96m_alwon_fck_3630_hw.hw,
 	.parent_names	= omap_96m_alwon_fck_3630_parent_names,
@@ -2506,6 +2536,10 @@ static struct clk omap_96m_alwon_fck_3630 = {
 	.ops	= &omap_96m_alwon_fck_3630_ops,
 };
 
+static struct clk omap_96m_alwon_fck_3630 = {
+	.core = &omap_96m_alwon_fck_3630_core,
+};
+
 static struct clk omapctrl_ick;
 
 static struct clk_hw_omap omapctrl_ick_hw = {
@@ -2521,12 +2555,12 @@ static struct clk_hw_omap omapctrl_ick_hw = {
 
 DEFINE_STRUCT_CLK(omapctrl_ick, aes2_ick_parent_names, aes2_ick_ops);
 
-DEFINE_CLK_DIVIDER(pclk_fck, "emu_src_ck", &emu_src_ck, 0x0,
+DEFINE_CLK_DIVIDER(pclk_fck, "emu_src_ck", &emu_src_ck_core, 0x0,
 		   OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1),
 		   OMAP3430_CLKSEL_PCLK_SHIFT, OMAP3430_CLKSEL_PCLK_WIDTH,
 		   CLK_DIVIDER_ONE_BASED, NULL);
 
-DEFINE_CLK_DIVIDER(pclkx2_fck, "emu_src_ck", &emu_src_ck, 0x0,
+DEFINE_CLK_DIVIDER(pclkx2_fck, "emu_src_ck", &emu_src_ck_core, 0x0,
 		   OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1),
 		   OMAP3430_CLKSEL_PCLKX2_SHIFT, OMAP3430_CLKSEL_PCLKX2_WIDTH,
 		   CLK_DIVIDER_ONE_BASED, NULL);
@@ -2558,7 +2592,7 @@ static struct clk_hw_omap pka_ick_hw = {
 
 DEFINE_STRUCT_CLK(pka_ick, pka_ick_parent_names, aes1_ick_ops);
 
-DEFINE_CLK_DIVIDER(rm_ick, "l4_ick", &l4_ick, 0x0,
+DEFINE_CLK_DIVIDER(rm_ick, "l4_ick", &l4_ick_core, 0x0,
 		   OMAP_CM_REGADDR(WKUP_MOD, CM_CLKSEL),
 		   OMAP3430_CLKSEL_RM_SHIFT, OMAP3430_CLKSEL_RM_WIDTH,
 		   CLK_DIVIDER_ONE_BASED, NULL);
@@ -2819,10 +2853,10 @@ DEFINE_CLK_OMAP_MUX_GATE(ssi_ssr_fck_3430es2, "core_l4_clkdm",
 			 ssi_ssr_fck_3430es1_ops);
 
 DEFINE_CLK_FIXED_FACTOR(ssi_sst_fck_3430es1, "ssi_ssr_fck_3430es1",
-			&ssi_ssr_fck_3430es1, 0x0, 1, 2);
+			&ssi_ssr_fck_3430es1_core, 0x0, 1, 2);
 
 DEFINE_CLK_FIXED_FACTOR(ssi_sst_fck_3430es2, "ssi_ssr_fck_3430es2",
-			&ssi_ssr_fck_3430es2, 0x0, 1, 2);
+			&ssi_ssr_fck_3430es2_core, 0x0, 1, 2);
 
 static struct clk sys_clkout1;
 
@@ -2840,7 +2874,7 @@ static struct clk_hw_omap sys_clkout1_hw = {
 
 DEFINE_STRUCT_CLK(sys_clkout1, sys_clkout1_parent_names, aes1_ick_ops);
 
-DEFINE_CLK_DIVIDER(sys_clkout2, "clkout2_src_ck", &clkout2_src_ck, 0x0,
+DEFINE_CLK_DIVIDER(sys_clkout2, "clkout2_src_ck", &clkout2_src_ck_core, 0x0,
 		   OMAP3430_CM_CLKOUT_CTRL, OMAP3430_CLKOUT2_DIV_SHIFT,
 		   OMAP3430_CLKOUT2_DIV_WIDTH, CLK_DIVIDER_POWER_OF_TWO, NULL);
 
@@ -2849,7 +2883,8 @@ DEFINE_CLK_MUX(traceclk_src_fck, emu_src_ck_parent_names, NULL, 0x0,
 	       OMAP3430_TRACE_MUX_CTRL_SHIFT, OMAP3430_TRACE_MUX_CTRL_WIDTH,
 	       0x0, NULL);
 
-DEFINE_CLK_DIVIDER(traceclk_fck, "traceclk_src_fck", &traceclk_src_fck, 0x0,
+DEFINE_CLK_DIVIDER(traceclk_fck, "traceclk_src_fck", &traceclk_src_fck_core,
+		   0x0,
 		   OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1),
 		   OMAP3430_CLKSEL_TRACECLK_SHIFT,
 		   OMAP3430_CLKSEL_TRACECLK_WIDTH, CLK_DIVIDER_ONE_BASED, NULL);
diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h
index a4282e7..c5b3a7f 100644
--- a/arch/arm/mach-omap2/clock.h
+++ b/arch/arm/mach-omap2/clock.h
@@ -40,23 +40,29 @@ struct omap_clk {
 struct clockdomain;
 
 #define DEFINE_STRUCT_CLK(_name, _parent_array_name, _clkops_name)	\
-	static struct clk _name = {				\
+	static struct clk_core _name##_core = {			\
 		.name = #_name,					\
 		.hw = &_name##_hw.hw,				\
 		.parent_names = _parent_array_name,		\
 		.num_parents = ARRAY_SIZE(_parent_array_name),	\
 		.ops = &_clkops_name,				\
+	};							\
+	static struct clk _name = {				\
+		.core = &_name##_core,				\
 	};
 
 #define DEFINE_STRUCT_CLK_FLAGS(_name, _parent_array_name,	\
 				_clkops_name, _flags)		\
-	static struct clk _name = {				\
+	static struct clk_core _name##_core = {			\
 		.name = #_name,					\
 		.hw = &_name##_hw.hw,				\
 		.parent_names = _parent_array_name,		\
 		.num_parents = ARRAY_SIZE(_parent_array_name),	\
 		.ops = &_clkops_name,				\
 		.flags = _flags,				\
+	};							\
+	static struct clk _name = {				\
+		.core = &_name##_core,				\
 	};
 
 #define DEFINE_STRUCT_CLK_HW_OMAP(_name, _clkdm_name)		\
@@ -248,6 +254,7 @@ extern const struct clksel_rate gpt_32k_rates[];
 extern const struct clksel_rate gpt_sys_rates[];
 extern const struct clksel_rate gfx_l3_rates[];
 extern const struct clksel_rate dsp_ick_rates[];
+extern struct clk_core dummy_ck_core;
 extern struct clk dummy_ck;
 
 extern const struct clk_hw_omap_ops clkhwops_iclk_wait;
diff --git a/arch/arm/mach-omap2/clock_common_data.c b/arch/arm/mach-omap2/clock_common_data.c
index ef4d21b..febd0a2 100644
--- a/arch/arm/mach-omap2/clock_common_data.c
+++ b/arch/arm/mach-omap2/clock_common_data.c
@@ -119,8 +119,11 @@ const struct clksel_rate div31_1to31_rates[] = {
 
 static struct clk_ops dummy_ck_ops = {};
 
-struct clk dummy_ck = {
+struct clk_core dummy_ck_core = {
 	.name = "dummy_clk",
 	.ops = &dummy_ck_ops,
 	.flags = CLK_IS_BASIC,
 };
+struct clk dummy_ck = {
+	.core = &dummy_ck_core,
+};
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index fd3d671..0b7091c 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -37,6 +37,15 @@ static HLIST_HEAD(clk_root_list);
 static HLIST_HEAD(clk_orphan_list);
 static LIST_HEAD(clk_notifier_list);
 
+static long clk_core_get_accuracy(struct clk_core *clk);
+static unsigned long clk_core_get_rate(struct clk_core *clk);
+static int clk_core_get_phase(struct clk_core *clk);
+static bool clk_core_is_prepared(struct clk_core *clk);
+static bool clk_core_is_enabled(struct clk_core *clk);
+static unsigned long clk_core_round_rate_nolock(struct clk_core *clk,
+						unsigned long rate);
+static struct clk_core *clk_core_lookup(const char *name);
+
 /***           locking             ***/
 static void clk_prepare_lock(void)
 {
@@ -114,7 +123,8 @@ static struct hlist_head *orphan_list[] = {
 	NULL,
 };
 
-static void clk_summary_show_one(struct seq_file *s, struct clk *c, int level)
+static void clk_summary_show_one(struct seq_file *s, struct clk_core *c,
+				 int level)
 {
 	if (!c)
 		return;
@@ -122,14 +132,14 @@ static void clk_summary_show_one(struct seq_file *s, struct clk *c, int level)
 	seq_printf(s, "%*s%-*s %11d %12d %11lu %10lu %-3d\n",
 		   level * 3 + 1, "",
 		   30 - level * 3, c->name,
-		   c->enable_count, c->prepare_count, clk_get_rate(c),
-		   clk_get_accuracy(c), clk_get_phase(c));
+		   c->enable_count, c->prepare_count, clk_core_get_rate(c),
+		   clk_core_get_accuracy(c), clk_core_get_phase(c));
 }
 
-static void clk_summary_show_subtree(struct seq_file *s, struct clk *c,
+static void clk_summary_show_subtree(struct seq_file *s, struct clk_core *c,
 				     int level)
 {
-	struct clk *child;
+	struct clk_core *child;
 
 	if (!c)
 		return;
@@ -142,7 +152,7 @@ static void clk_summary_show_subtree(struct seq_file *s, struct clk *c,
 
 static int clk_summary_show(struct seq_file *s, void *data)
 {
-	struct clk *c;
+	struct clk_core *c;
 	struct hlist_head **lists = (struct hlist_head **)s->private;
 
 	seq_puts(s, "   clock                         enable_cnt  prepare_cnt        rate   accuracy   phase\n");
@@ -172,7 +182,7 @@ static const struct file_operations clk_summary_fops = {
 	.release	= single_release,
 };
 
-static void clk_dump_one(struct seq_file *s, struct clk *c, int level)
+static void clk_dump_one(struct seq_file *s, struct clk_core *c, int level)
 {
 	if (!c)
 		return;
@@ -180,14 +190,14 @@ static void clk_dump_one(struct seq_file *s, struct clk *c, int level)
 	seq_printf(s, "\"%s\": { ", c->name);
 	seq_printf(s, "\"enable_count\": %d,", c->enable_count);
 	seq_printf(s, "\"prepare_count\": %d,", c->prepare_count);
-	seq_printf(s, "\"rate\": %lu", clk_get_rate(c));
-	seq_printf(s, "\"accuracy\": %lu", clk_get_accuracy(c));
-	seq_printf(s, "\"phase\": %d", clk_get_phase(c));
+	seq_printf(s, "\"rate\": %lu", clk_core_get_rate(c));
+	seq_printf(s, "\"accuracy\": %lu", clk_core_get_accuracy(c));
+	seq_printf(s, "\"phase\": %d", clk_core_get_phase(c));
 }
 
-static void clk_dump_subtree(struct seq_file *s, struct clk *c, int level)
+static void clk_dump_subtree(struct seq_file *s, struct clk_core *c, int level)
 {
-	struct clk *child;
+	struct clk_core *child;
 
 	if (!c)
 		return;
@@ -204,7 +214,7 @@ static void clk_dump_subtree(struct seq_file *s, struct clk *c, int level)
 
 static int clk_dump(struct seq_file *s, void *data)
 {
-	struct clk *c;
+	struct clk_core *c;
 	bool first_node = true;
 	struct hlist_head **lists = (struct hlist_head **)s->private;
 
@@ -240,7 +250,7 @@ static const struct file_operations clk_dump_fops = {
 	.release	= single_release,
 };
 
-static int clk_debug_create_one(struct clk *clk, struct dentry *pdentry)
+static int clk_debug_create_one(struct clk_core *clk, struct dentry *pdentry)
 {
 	struct dentry *d;
 	int ret = -ENOMEM;
@@ -315,7 +325,7 @@ out:
  * initialized.  Otherwise it bails out early since the debugfs clk tree
  * will be created lazily by clk_debug_init as part of a late_initcall.
  */
-static int clk_debug_register(struct clk *clk)
+static int clk_debug_register(struct clk_core *clk)
 {
 	int ret = 0;
 
@@ -340,7 +350,7 @@ unlock:
  * debugfs clk tree if clk->dentry points to debugfs created by
  * clk_debug_register in __clk_init.
  */
-static void clk_debug_unregister(struct clk *clk)
+static void clk_debug_unregister(struct clk_core *clk)
 {
 	mutex_lock(&clk_debug_lock);
 	if (!clk->dentry)
@@ -358,8 +368,9 @@ struct dentry *clk_debugfs_add_file(struct clk_hw *hw, char *name, umode_t mode,
 {
 	struct dentry *d = NULL;
 
-	if (hw->clk->dentry)
-		d = debugfs_create_file(name, mode, hw->clk->dentry, data, fops);
+	if (hw->core->dentry)
+		d = debugfs_create_file(name, mode, hw->core->dentry, data,
+					fops);
 
 	return d;
 }
@@ -379,7 +390,7 @@ EXPORT_SYMBOL_GPL(clk_debugfs_add_file);
  */
 static int __init clk_debug_init(void)
 {
-	struct clk *clk;
+	struct clk_core *clk;
 	struct dentry *d;
 
 	rootdir = debugfs_create_dir("clk", NULL);
@@ -418,19 +429,20 @@ static int __init clk_debug_init(void)
 }
 late_initcall(clk_debug_init);
 #else
-static inline int clk_debug_register(struct clk *clk) { return 0; }
-static inline void clk_debug_reparent(struct clk *clk, struct clk *new_parent)
+static inline int clk_debug_register(struct clk_core *clk) { return 0; }
+static inline void clk_debug_reparent(struct clk_core *clk,
+				      struct clk_core *new_parent)
 {
 }
-static inline void clk_debug_unregister(struct clk *clk)
+static inline void clk_debug_unregister(struct clk_core *clk)
 {
 }
 #endif
 
 /* caller must hold prepare_lock */
-static void clk_unprepare_unused_subtree(struct clk *clk)
+static void clk_unprepare_unused_subtree(struct clk_core *clk)
 {
-	struct clk *child;
+	struct clk_core *child;
 
 	hlist_for_each_entry(child, &clk->children, child_node)
 		clk_unprepare_unused_subtree(child);
@@ -441,7 +453,7 @@ static void clk_unprepare_unused_subtree(struct clk *clk)
 	if (clk->flags & CLK_IGNORE_UNUSED)
 		return;
 
-	if (__clk_is_prepared(clk)) {
+	if (clk_core_is_prepared(clk)) {
 		if (clk->ops->unprepare_unused)
 			clk->ops->unprepare_unused(clk->hw);
 		else if (clk->ops->unprepare)
@@ -450,9 +462,9 @@ static void clk_unprepare_unused_subtree(struct clk *clk)
 }
 
 /* caller must hold prepare_lock */
-static void clk_disable_unused_subtree(struct clk *clk)
+static void clk_disable_unused_subtree(struct clk_core *clk)
 {
-	struct clk *child;
+	struct clk_core *child;
 	unsigned long flags;
 
 	hlist_for_each_entry(child, &clk->children, child_node)
@@ -471,7 +483,7 @@ static void clk_disable_unused_subtree(struct clk *clk)
 	 * sequence.  call .disable_unused if available, otherwise fall
 	 * back to .disable
 	 */
-	if (__clk_is_enabled(clk)) {
+	if (clk_core_is_enabled(clk)) {
 		if (clk->ops->disable_unused)
 			clk->ops->disable_unused(clk->hw);
 		else if (clk->ops->disable)
@@ -492,7 +504,7 @@ __setup("clk_ignore_unused", clk_ignore_unused_setup);
 
 static int clk_disable_unused(void)
 {
-	struct clk *clk;
+	struct clk_core *clk;
 
 	if (clk_ignore_unused) {
 		pr_warn("clk: Not disabling unused clocks\n");
@@ -523,48 +535,65 @@ late_initcall_sync(clk_disable_unused);
 
 const char *__clk_get_name(struct clk *clk)
 {
-	return !clk ? NULL : clk->name;
+	return !clk ? NULL : clk->core->name;
 }
 EXPORT_SYMBOL_GPL(__clk_get_name);
 
 struct clk_hw *__clk_get_hw(struct clk *clk)
 {
-	return !clk ? NULL : clk->hw;
+	return !clk ? NULL : clk->core->hw;
 }
 EXPORT_SYMBOL_GPL(__clk_get_hw);
 
 u8 __clk_get_num_parents(struct clk *clk)
 {
-	return !clk ? 0 : clk->num_parents;
+	return !clk ? 0 : clk->core->num_parents;
 }
 EXPORT_SYMBOL_GPL(__clk_get_num_parents);
 
 struct clk *__clk_get_parent(struct clk *clk)
 {
-	return !clk ? NULL : clk->parent;
+	if (!clk)
+		return NULL;
+
+	/* TODO: Create a per-user clk and change callers to call clk_put */
+	return !clk->core->parent ? NULL : clk->core->parent->hw->clk;
 }
 EXPORT_SYMBOL_GPL(__clk_get_parent);
 
-struct clk *clk_get_parent_by_index(struct clk *clk, u8 index)
+static struct clk_core *clk_core_get_parent_by_index(struct clk_core *clk,
+							 u8 index)
 {
 	if (!clk || index >= clk->num_parents)
 		return NULL;
 	else if (!clk->parents)
-		return __clk_lookup(clk->parent_names[index]);
+		return clk_core_lookup(clk->parent_names[index]);
 	else if (!clk->parents[index])
 		return clk->parents[index] =
-			__clk_lookup(clk->parent_names[index]);
+			clk_core_lookup(clk->parent_names[index]);
 	else
 		return clk->parents[index];
 }
+
+struct clk *clk_get_parent_by_index(struct clk *clk, u8 index)
+{
+	struct clk_core *parent;
+
+	if (!clk)
+		return NULL;
+
+	parent = clk_core_get_parent_by_index(clk->core, index);
+
+	return !parent ? NULL : parent->hw->clk;
+}
 EXPORT_SYMBOL_GPL(clk_get_parent_by_index);
 
 unsigned int __clk_get_enable_count(struct clk *clk)
 {
-	return !clk ? 0 : clk->enable_count;
+	return !clk ? 0 : clk->core->enable_count;
 }
 
-unsigned long __clk_get_rate(struct clk *clk)
+static unsigned long clk_core_get_rate_nolock(struct clk_core *clk)
 {
 	unsigned long ret;
 
@@ -584,9 +613,17 @@ unsigned long __clk_get_rate(struct clk *clk)
 out:
 	return ret;
 }
+
+unsigned long __clk_get_rate(struct clk *clk)
+{
+	if (!clk)
+		return 0;
+
+	return clk_core_get_rate_nolock(clk->core);
+}
 EXPORT_SYMBOL_GPL(__clk_get_rate);
 
-static unsigned long __clk_get_accuracy(struct clk *clk)
+static unsigned long __clk_get_accuracy(struct clk_core *clk)
 {
 	if (!clk)
 		return 0;
@@ -596,11 +633,11 @@ static unsigned long __clk_get_accuracy(struct clk *clk)
 
 unsigned long __clk_get_flags(struct clk *clk)
 {
-	return !clk ? 0 : clk->flags;
+	return !clk ? 0 : clk->core->flags;
 }
 EXPORT_SYMBOL_GPL(__clk_get_flags);
 
-bool __clk_is_prepared(struct clk *clk)
+static bool clk_core_is_prepared(struct clk_core *clk)
 {
 	int ret;
 
@@ -621,7 +658,15 @@ out:
 	return !!ret;
 }
 
-bool __clk_is_enabled(struct clk *clk)
+bool __clk_is_prepared(struct clk *clk)
+{
+	if (!clk)
+		return false;
+
+	return clk_core_is_prepared(clk->core);
+}
+
+static bool clk_core_is_enabled(struct clk_core *clk)
 {
 	int ret;
 
@@ -641,12 +686,21 @@ bool __clk_is_enabled(struct clk *clk)
 out:
 	return !!ret;
 }
+
+bool __clk_is_enabled(struct clk *clk)
+{
+	if (!clk)
+		return false;
+
+	return clk_core_is_enabled(clk->core);
+}
 EXPORT_SYMBOL_GPL(__clk_is_enabled);
 
-static struct clk *__clk_lookup_subtree(const char *name, struct clk *clk)
+static struct clk_core *__clk_lookup_subtree(const char *name,
+					     struct clk_core *clk)
 {
-	struct clk *child;
-	struct clk *ret;
+	struct clk_core *child;
+	struct clk_core *ret;
 
 	if (!strcmp(clk->name, name))
 		return clk;
@@ -660,10 +714,10 @@ static struct clk *__clk_lookup_subtree(const char *name, struct clk *clk)
 	return NULL;
 }
 
-struct clk *__clk_lookup(const char *name)
+static struct clk_core *clk_core_lookup(const char *name)
 {
-	struct clk *root_clk;
-	struct clk *ret;
+	struct clk_core *root_clk;
+	struct clk_core *ret;
 
 	if (!name)
 		return NULL;
@@ -685,6 +739,13 @@ struct clk *__clk_lookup(const char *name)
 	return NULL;
 }
 
+struct clk *__clk_lookup(const char *name)
+{
+	struct clk_core *core = clk_core_lookup(name);
+
+	return !core ? NULL : core->hw->clk;
+}
+
 /*
  * Helper for finding best parent to provide a given frequency. This can be used
  * directly as a determine_rate callback (e.g. for a mux), or from a more
@@ -694,32 +755,32 @@ long __clk_mux_determine_rate(struct clk_hw *hw, unsigned long rate,
 			      unsigned long *best_parent_rate,
 			      struct clk_hw **best_parent_p)
 {
-	struct clk *clk = hw->clk, *parent, *best_parent = NULL;
+	struct clk_core *core = hw->core, *parent, *best_parent = NULL;
 	int i, num_parents;
 	unsigned long parent_rate, best = 0;
 
 	/* if NO_REPARENT flag set, pass through to current parent */
-	if (clk->flags & CLK_SET_RATE_NO_REPARENT) {
-		parent = clk->parent;
-		if (clk->flags & CLK_SET_RATE_PARENT)
-			best = __clk_round_rate(parent, rate);
+	if (core->flags & CLK_SET_RATE_NO_REPARENT) {
+		parent = core->parent;
+		if (core->flags & CLK_SET_RATE_PARENT)
+			best = clk_core_round_rate_nolock(parent, rate);
 		else if (parent)
-			best = __clk_get_rate(parent);
+			best = clk_core_get_rate_nolock(parent);
 		else
-			best = __clk_get_rate(clk);
+			best = clk_core_get_rate_nolock(core);
 		goto out;
 	}
 
 	/* find the parent that can provide the fastest rate <= rate */
-	num_parents = clk->num_parents;
+	num_parents = core->num_parents;
 	for (i = 0; i < num_parents; i++) {
-		parent = clk_get_parent_by_index(clk, i);
+		parent = clk_core_get_parent_by_index(core, i);
 		if (!parent)
 			continue;
-		if (clk->flags & CLK_SET_RATE_PARENT)
-			parent_rate = __clk_round_rate(parent, rate);
+		if (core->flags & CLK_SET_RATE_PARENT)
+			parent_rate = clk_core_round_rate_nolock(parent, rate);
 		else
-			parent_rate = __clk_get_rate(parent);
+			parent_rate = clk_core_get_rate_nolock(parent);
 		if (parent_rate <= rate && parent_rate > best) {
 			best_parent = parent;
 			best = parent_rate;
@@ -737,7 +798,7 @@ EXPORT_SYMBOL_GPL(__clk_mux_determine_rate);
 
 /***        clk api        ***/
 
-void __clk_unprepare(struct clk *clk)
+static void clk_core_unprepare(struct clk_core *clk)
 {
 	if (!clk)
 		return;
@@ -753,7 +814,7 @@ void __clk_unprepare(struct clk *clk)
 	if (clk->ops->unprepare)
 		clk->ops->unprepare(clk->hw);
 
-	__clk_unprepare(clk->parent);
+	clk_core_unprepare(clk->parent);
 }
 
 /**
@@ -773,12 +834,12 @@ void clk_unprepare(struct clk *clk)
 		return;
 
 	clk_prepare_lock();
-	__clk_unprepare(clk);
+	clk_core_unprepare(clk->core);
 	clk_prepare_unlock();
 }
 EXPORT_SYMBOL_GPL(clk_unprepare);
 
-int __clk_prepare(struct clk *clk)
+static int clk_core_prepare(struct clk_core *clk)
 {
 	int ret = 0;
 
@@ -786,14 +847,14 @@ int __clk_prepare(struct clk *clk)
 		return 0;
 
 	if (clk->prepare_count == 0) {
-		ret = __clk_prepare(clk->parent);
+		ret = clk_core_prepare(clk->parent);
 		if (ret)
 			return ret;
 
 		if (clk->ops->prepare) {
 			ret = clk->ops->prepare(clk->hw);
 			if (ret) {
-				__clk_unprepare(clk->parent);
+				clk_core_unprepare(clk->parent);
 				return ret;
 			}
 		}
@@ -820,15 +881,18 @@ int clk_prepare(struct clk *clk)
 {
 	int ret;
 
+	if (!clk)
+		return 0;
+
 	clk_prepare_lock();
-	ret = __clk_prepare(clk);
+	ret = clk_core_prepare(clk->core);
 	clk_prepare_unlock();
 
 	return ret;
 }
 EXPORT_SYMBOL_GPL(clk_prepare);
 
-static void __clk_disable(struct clk *clk)
+static void clk_core_disable(struct clk_core *clk)
 {
 	if (!clk)
 		return;
@@ -842,7 +906,15 @@ static void __clk_disable(struct clk *clk)
 	if (clk->ops->disable)
 		clk->ops->disable(clk->hw);
 
-	__clk_disable(clk->parent);
+	clk_core_disable(clk->parent);
+}
+
+static void __clk_disable(struct clk *clk)
+{
+	if (!clk)
+		return;
+
+	clk_core_disable(clk->core);
 }
 
 /**
@@ -870,7 +942,7 @@ void clk_disable(struct clk *clk)
 }
 EXPORT_SYMBOL_GPL(clk_disable);
 
-static int __clk_enable(struct clk *clk)
+static int clk_core_enable(struct clk_core *clk)
 {
 	int ret = 0;
 
@@ -881,7 +953,7 @@ static int __clk_enable(struct clk *clk)
 		return -ESHUTDOWN;
 
 	if (clk->enable_count == 0) {
-		ret = __clk_enable(clk->parent);
+		ret = clk_core_enable(clk->parent);
 
 		if (ret)
 			return ret;
@@ -889,7 +961,7 @@ static int __clk_enable(struct clk *clk)
 		if (clk->ops->enable) {
 			ret = clk->ops->enable(clk->hw);
 			if (ret) {
-				__clk_disable(clk->parent);
+				clk_core_disable(clk->parent);
 				return ret;
 			}
 		}
@@ -899,6 +971,14 @@ static int __clk_enable(struct clk *clk)
 	return 0;
 }
 
+static int __clk_enable(struct clk *clk)
+{
+	if (!clk)
+		return 0;
+
+	return clk_core_enable(clk->core);
+}
+
 /**
  * clk_enable - ungate a clock
  * @clk: the clk being ungated
@@ -925,17 +1005,11 @@ int clk_enable(struct clk *clk)
 }
 EXPORT_SYMBOL_GPL(clk_enable);
 
-/**
- * __clk_round_rate - round the given rate for a clk
- * @clk: round the rate of this clock
- * @rate: the rate which is to be rounded
- *
- * Caller must hold prepare_lock.  Useful for clk_ops such as .set_rate
- */
-unsigned long __clk_round_rate(struct clk *clk, unsigned long rate)
+static unsigned long clk_core_round_rate_nolock(struct clk_core *clk,
+						unsigned long rate)
 {
 	unsigned long parent_rate = 0;
-	struct clk *parent;
+	struct clk_core *parent;
 	struct clk_hw *parent_hw;
 
 	if (!clk)
@@ -952,10 +1026,25 @@ unsigned long __clk_round_rate(struct clk *clk, unsigned long rate)
 	} else if (clk->ops->round_rate)
 		return clk->ops->round_rate(clk->hw, rate, &parent_rate);
 	else if (clk->flags & CLK_SET_RATE_PARENT)
-		return __clk_round_rate(clk->parent, rate);
+		return clk_core_round_rate_nolock(clk->parent, rate);
 	else
 		return clk->rate;
 }
+
+/**
+ * __clk_round_rate - round the given rate for a clk
+ * @clk: round the rate of this clock
+ * @rate: the rate which is to be rounded
+ *
+ * Caller must hold prepare_lock.  Useful for clk_ops such as .set_rate
+ */
+unsigned long __clk_round_rate(struct clk *clk, unsigned long rate)
+{
+	if (!clk)
+		return 0;
+
+	return clk_core_round_rate_nolock(clk->core, rate);
+}
 EXPORT_SYMBOL_GPL(__clk_round_rate);
 
 /**
@@ -971,8 +1060,11 @@ long clk_round_rate(struct clk *clk, unsigned long rate)
 {
 	unsigned long ret;
 
+	if (!clk)
+		return 0;
+
 	clk_prepare_lock();
-	ret = __clk_round_rate(clk, rate);
+	ret = clk_core_round_rate_nolock(clk->core, rate);
 	clk_prepare_unlock();
 
 	return ret;
@@ -993,22 +1085,21 @@ EXPORT_SYMBOL_GPL(clk_round_rate);
  * called if all went well, or NOTIFY_STOP or NOTIFY_BAD immediately if
  * a driver returns that.
  */
-static int __clk_notify(struct clk *clk, unsigned long msg,
+static int __clk_notify(struct clk_core *clk, unsigned long msg,
 		unsigned long old_rate, unsigned long new_rate)
 {
 	struct clk_notifier *cn;
 	struct clk_notifier_data cnd;
 	int ret = NOTIFY_DONE;
 
-	cnd.clk = clk;
 	cnd.old_rate = old_rate;
 	cnd.new_rate = new_rate;
 
 	list_for_each_entry(cn, &clk_notifier_list, node) {
-		if (cn->clk == clk) {
+		if (cn->clk->core == clk) {
+			cnd.clk = cn->clk;
 			ret = srcu_notifier_call_chain(&cn->notifier_head, msg,
 					&cnd);
-			break;
 		}
 	}
 
@@ -1026,10 +1117,10 @@ static int __clk_notify(struct clk *clk, unsigned long msg,
  *
  * Caller must hold prepare_lock.
  */
-static void __clk_recalc_accuracies(struct clk *clk)
+static void __clk_recalc_accuracies(struct clk_core *clk)
 {
 	unsigned long parent_accuracy = 0;
-	struct clk *child;
+	struct clk_core *child;
 
 	if (clk->parent)
 		parent_accuracy = clk->parent->accuracy;
@@ -1044,6 +1135,20 @@ static void __clk_recalc_accuracies(struct clk *clk)
 		__clk_recalc_accuracies(child);
 }
 
+static long clk_core_get_accuracy(struct clk_core *clk)
+{
+	unsigned long accuracy;
+
+	clk_prepare_lock();
+	if (clk && (clk->flags & CLK_GET_ACCURACY_NOCACHE))
+		__clk_recalc_accuracies(clk);
+
+	accuracy = __clk_get_accuracy(clk);
+	clk_prepare_unlock();
+
+	return accuracy;
+}
+
 /**
  * clk_get_accuracy - return the accuracy of clk
  * @clk: the clk whose accuracy is being returned
@@ -1055,20 +1160,15 @@ static void __clk_recalc_accuracies(struct clk *clk)
  */
 long clk_get_accuracy(struct clk *clk)
 {
-	unsigned long accuracy;
-
-	clk_prepare_lock();
-	if (clk && (clk->flags & CLK_GET_ACCURACY_NOCACHE))
-		__clk_recalc_accuracies(clk);
-
-	accuracy = __clk_get_accuracy(clk);
-	clk_prepare_unlock();
+	if (!clk)
+		return 0;
 
-	return accuracy;
+	return clk_core_get_accuracy(clk->core);
 }
 EXPORT_SYMBOL_GPL(clk_get_accuracy);
 
-static unsigned long clk_recalc(struct clk *clk, unsigned long parent_rate)
+static unsigned long clk_recalc(struct clk_core *clk,
+				unsigned long parent_rate)
 {
 	if (clk->ops->recalc_rate)
 		return clk->ops->recalc_rate(clk->hw, parent_rate);
@@ -1089,11 +1189,11 @@ static unsigned long clk_recalc(struct clk *clk, unsigned long parent_rate)
  *
  * Caller must hold prepare_lock.
  */
-static void __clk_recalc_rates(struct clk *clk, unsigned long msg)
+static void __clk_recalc_rates(struct clk_core *clk, unsigned long msg)
 {
 	unsigned long old_rate;
 	unsigned long parent_rate = 0;
-	struct clk *child;
+	struct clk_core *child;
 
 	old_rate = clk->rate;
 
@@ -1113,15 +1213,7 @@ static void __clk_recalc_rates(struct clk *clk, unsigned long msg)
 		__clk_recalc_rates(child, msg);
 }
 
-/**
- * clk_get_rate - return the rate of clk
- * @clk: the clk whose rate is being returned
- *
- * Simply returns the cached rate of the clk, unless CLK_GET_RATE_NOCACHE flag
- * is set, which means a recalc_rate will be issued.
- * If clk is NULL then returns 0.
- */
-unsigned long clk_get_rate(struct clk *clk)
+static unsigned long clk_core_get_rate(struct clk_core *clk)
 {
 	unsigned long rate;
 
@@ -1130,14 +1222,32 @@ unsigned long clk_get_rate(struct clk *clk)
 	if (clk && (clk->flags & CLK_GET_RATE_NOCACHE))
 		__clk_recalc_rates(clk, 0);
 
-	rate = __clk_get_rate(clk);
+	rate = clk_core_get_rate_nolock(clk);
 	clk_prepare_unlock();
 
 	return rate;
 }
+EXPORT_SYMBOL_GPL(clk_core_get_rate);
+
+/**
+ * clk_get_rate - return the rate of clk
+ * @clk: the clk whose rate is being returned
+ *
+ * Simply returns the cached rate of the clk, unless CLK_GET_RATE_NOCACHE flag
+ * is set, which means a recalc_rate will be issued.
+ * If clk is NULL then returns 0.
+ */
+unsigned long clk_get_rate(struct clk *clk)
+{
+	if (!clk)
+		return 0;
+
+	return clk_core_get_rate(clk->core);
+}
 EXPORT_SYMBOL_GPL(clk_get_rate);
 
-static int clk_fetch_parent_index(struct clk *clk, struct clk *parent)
+static int clk_fetch_parent_index(struct clk_core *clk,
+				  struct clk_core *parent)
 {
 	int i;
 
@@ -1151,7 +1261,7 @@ static int clk_fetch_parent_index(struct clk *clk, struct clk *parent)
 	/*
 	 * find index of new parent clock using cached parent ptrs,
 	 * or if not yet cached, use string name comparison and cache
-	 * them now to avoid future calls to __clk_lookup.
+	 * them now to avoid future calls to clk_core_lookup.
 	 */
 	for (i = 0; i < clk->num_parents; i++) {
 		if (clk->parents[i] == parent)
@@ -1161,7 +1271,7 @@ static int clk_fetch_parent_index(struct clk *clk, struct clk *parent)
 			continue;
 
 		if (!strcmp(clk->parent_names[i], parent->name)) {
-			clk->parents[i] = __clk_lookup(parent->name);
+			clk->parents[i] = clk_core_lookup(parent->name);
 			return i;
 		}
 	}
@@ -1169,7 +1279,7 @@ static int clk_fetch_parent_index(struct clk *clk, struct clk *parent)
 	return -EINVAL;
 }
 
-static void clk_reparent(struct clk *clk, struct clk *new_parent)
+static void clk_reparent(struct clk_core *clk, struct clk_core *new_parent)
 {
 	hlist_del(&clk->child_node);
 
@@ -1186,10 +1296,11 @@ static void clk_reparent(struct clk *clk, struct clk *new_parent)
 	clk->parent = new_parent;
 }
 
-static struct clk *__clk_set_parent_before(struct clk *clk, struct clk *parent)
+static struct clk_core *__clk_set_parent_before(struct clk_core *clk,
+					   struct clk_core *parent)
 {
 	unsigned long flags;
-	struct clk *old_parent = clk->parent;
+	struct clk_core *old_parent = clk->parent;
 
 	/*
 	 * Migrate prepare state between parents and prevent race with
@@ -1209,9 +1320,9 @@ static struct clk *__clk_set_parent_before(struct clk *clk, struct clk *parent)
 	 * See also: Comment for clk_set_parent() below.
 	 */
 	if (clk->prepare_count) {
-		__clk_prepare(parent);
-		clk_enable(parent);
-		clk_enable(clk);
+		clk_core_prepare(parent);
+		clk_core_enable(parent);
+		clk_core_enable(clk);
 	}
 
 	/* update the clk tree topology */
@@ -1222,25 +1333,27 @@ static struct clk *__clk_set_parent_before(struct clk *clk, struct clk *parent)
 	return old_parent;
 }
 
-static void __clk_set_parent_after(struct clk *clk, struct clk *parent,
-		struct clk *old_parent)
+static void __clk_set_parent_after(struct clk_core *core,
+				   struct clk_core *parent,
+				   struct clk_core *old_parent)
 {
 	/*
 	 * Finish the migration of prepare state and undo the changes done
 	 * for preventing a race with clk_enable().
 	 */
-	if (clk->prepare_count) {
-		clk_disable(clk);
-		clk_disable(old_parent);
-		__clk_unprepare(old_parent);
+	if (core->prepare_count) {
+		clk_core_disable(core);
+		clk_core_disable(old_parent);
+		clk_core_unprepare(old_parent);
 	}
 }
 
-static int __clk_set_parent(struct clk *clk, struct clk *parent, u8 p_index)
+static int __clk_set_parent(struct clk_core *clk, struct clk_core *parent,
+			    u8 p_index)
 {
 	unsigned long flags;
 	int ret = 0;
-	struct clk *old_parent;
+	struct clk_core *old_parent;
 
 	old_parent = __clk_set_parent_before(clk, parent);
 
@@ -1254,9 +1367,9 @@ static int __clk_set_parent(struct clk *clk, struct clk *parent, u8 p_index)
 		clk_enable_unlock(flags);
 
 		if (clk->prepare_count) {
-			clk_disable(clk);
-			clk_disable(parent);
-			__clk_unprepare(parent);
+			clk_core_disable(clk);
+			clk_core_disable(parent);
+			clk_core_unprepare(parent);
 		}
 		return ret;
 	}
@@ -1282,9 +1395,10 @@ static int __clk_set_parent(struct clk *clk, struct clk *parent, u8 p_index)
  *
  * Caller must hold prepare_lock.
  */
-static int __clk_speculate_rates(struct clk *clk, unsigned long parent_rate)
+static int __clk_speculate_rates(struct clk_core *clk,
+				 unsigned long parent_rate)
 {
-	struct clk *child;
+	struct clk_core *child;
 	unsigned long new_rate;
 	int ret = NOTIFY_DONE;
 
@@ -1310,10 +1424,10 @@ out:
 	return ret;
 }
 
-static void clk_calc_subtree(struct clk *clk, unsigned long new_rate,
-			     struct clk *new_parent, u8 p_index)
+static void clk_calc_subtree(struct clk_core *clk, unsigned long new_rate,
+			     struct clk_core *new_parent, u8 p_index)
 {
-	struct clk *child;
+	struct clk_core *child;
 
 	clk->new_rate = new_rate;
 	clk->new_parent = new_parent;
@@ -1333,10 +1447,11 @@ static void clk_calc_subtree(struct clk *clk, unsigned long new_rate,
  * calculate the new rates returning the topmost clock that has to be
  * changed.
  */
-static struct clk *clk_calc_new_rates(struct clk *clk, unsigned long rate)
+static struct clk_core *clk_calc_new_rates(struct clk_core *clk,
+					   unsigned long rate)
 {
-	struct clk *top = clk;
-	struct clk *old_parent, *parent;
+	struct clk_core *top = clk;
+	struct clk_core *old_parent, *parent;
 	struct clk_hw *parent_hw;
 	unsigned long best_parent_rate = 0;
 	unsigned long new_rate;
@@ -1357,7 +1472,7 @@ static struct clk *clk_calc_new_rates(struct clk *clk, unsigned long rate)
 		new_rate = clk->ops->determine_rate(clk->hw, rate,
 						    &best_parent_rate,
 						    &parent_hw);
-		parent = parent_hw->clk;
+		parent = parent_hw ? parent_hw->core : NULL;
 	} else if (clk->ops->round_rate) {
 		new_rate = clk->ops->round_rate(clk->hw, rate,
 						&best_parent_rate);
@@ -1405,9 +1520,10 @@ out:
  * so that in case of an error we can walk down the whole tree again and
  * abort the change.
  */
-static struct clk *clk_propagate_rate_change(struct clk *clk, unsigned long event)
+static struct clk_core *clk_propagate_rate_change(struct clk_core *clk,
+						  unsigned long event)
 {
-	struct clk *child, *tmp_clk, *fail_clk = NULL;
+	struct clk_core *child, *tmp_clk, *fail_clk = NULL;
 	int ret = NOTIFY_DONE;
 
 	if (clk->rate == clk->new_rate)
@@ -1442,14 +1558,14 @@ static struct clk *clk_propagate_rate_change(struct clk *clk, unsigned long even
  * walk down a subtree and set the new rates notifying the rate
  * change on the way
  */
-static void clk_change_rate(struct clk *clk)
+static void clk_change_rate(struct clk_core *clk)
 {
-	struct clk *child;
+	struct clk_core *child;
 	struct hlist_node *tmp;
 	unsigned long old_rate;
 	unsigned long best_parent_rate = 0;
 	bool skip_set_rate = false;
-	struct clk *old_parent;
+	struct clk_core *old_parent;
 
 	old_rate = clk->rate;
 
@@ -1520,7 +1636,7 @@ static void clk_change_rate(struct clk *clk)
  */
 int clk_set_rate(struct clk *clk, unsigned long rate)
 {
-	struct clk *top, *fail_clk;
+	struct clk_core *top, *fail_clk;
 	int ret = 0;
 
 	if (!clk)
@@ -1533,13 +1649,14 @@ int clk_set_rate(struct clk *clk, unsigned long rate)
 	if (rate == clk_get_rate(clk))
 		goto out;
 
-	if ((clk->flags & CLK_SET_RATE_GATE) && clk->prepare_count) {
+	if ((clk->core->flags & CLK_SET_RATE_GATE) &&
+	    clk->core->prepare_count) {
 		ret = -EBUSY;
 		goto out;
 	}
 
 	/* calculate new rates and get the topmost changed clock */
-	top = clk_calc_new_rates(clk, rate);
+	top = clk_calc_new_rates(clk->core, rate);
 	if (!top) {
 		ret = -EINVAL;
 		goto out;
@@ -1590,11 +1707,11 @@ EXPORT_SYMBOL_GPL(clk_get_parent);
  *
  * For single-parent clocks without .get_parent, first check to see if the
  * .parents array exists, and if so use it to avoid an expensive tree
- * traversal.  If .parents does not exist then walk the tree with __clk_lookup.
+ * traversal.  If .parents does not exist then walk the tree.
  */
-static struct clk *__clk_init_parent(struct clk *clk)
+static struct clk_core *__clk_init_parent(struct clk_core *clk)
 {
-	struct clk *ret = NULL;
+	struct clk_core *ret = NULL;
 	u8 index;
 
 	/* handle the trivial cases */
@@ -1604,7 +1721,7 @@ static struct clk *__clk_init_parent(struct clk *clk)
 
 	if (clk->num_parents == 1) {
 		if (IS_ERR_OR_NULL(clk->parent))
-			clk->parent = __clk_lookup(clk->parent_names[0]);
+			clk->parent = clk_core_lookup(clk->parent_names[0]);
 		ret = clk->parent;
 		goto out;
 	}
@@ -1618,8 +1735,8 @@ static struct clk *__clk_init_parent(struct clk *clk)
 
 	/*
 	 * Do our best to cache parent clocks in clk->parents.  This prevents
-	 * unnecessary and expensive calls to __clk_lookup.  We don't set
-	 * clk->parent here; that is done by the calling function
+	 * unnecessary and expensive lookups.  We don't set clk->parent here;
+	 * that is done by the calling function.
 	 */
 
 	index = clk->ops->get_parent(clk->hw);
@@ -1629,37 +1746,21 @@ static struct clk *__clk_init_parent(struct clk *clk)
 			kcalloc(clk->num_parents, sizeof(struct clk *),
 					GFP_KERNEL);
 
-	ret = clk_get_parent_by_index(clk, index);
+	ret = clk_core_get_parent_by_index(clk, index);
 
 out:
 	return ret;
 }
 
-void __clk_reparent(struct clk *clk, struct clk *new_parent)
+static void clk_core_reparent(struct clk_core *clk,
+				  struct clk_core *new_parent)
 {
 	clk_reparent(clk, new_parent);
 	__clk_recalc_accuracies(clk);
 	__clk_recalc_rates(clk, POST_RATE_CHANGE);
 }
 
-/**
- * clk_set_parent - switch the parent of a mux clk
- * @clk: the mux clk whose input we are switching
- * @parent: the new input to clk
- *
- * Re-parent clk to use parent as its new input source.  If clk is in
- * prepared state, the clk will get enabled for the duration of this call. If
- * that's not acceptable for a specific clk (Eg: the consumer can't handle
- * that, the reparenting is glitchy in hardware, etc), use the
- * CLK_SET_PARENT_GATE flag to allow reparenting only when clk is unprepared.
- *
- * After successfully changing clk's parent clk_set_parent will update the
- * clk topology, sysfs topology and propagate rate recalculation via
- * __clk_recalc_rates.
- *
- * Returns 0 on success, -EERROR otherwise.
- */
-int clk_set_parent(struct clk *clk, struct clk *parent)
+static int clk_core_set_parent(struct clk_core *clk, struct clk_core *parent)
 {
 	int ret = 0;
 	int p_index = 0;
@@ -1719,6 +1820,31 @@ out:
 
 	return ret;
 }
+
+/**
+ * clk_set_parent - switch the parent of a mux clk
+ * @clk: the mux clk whose input we are switching
+ * @parent: the new input to clk
+ *
+ * Re-parent clk to use parent as its new input source.  If clk is in
+ * prepared state, the clk will get enabled for the duration of this call. If
+ * that's not acceptable for a specific clk (Eg: the consumer can't handle
+ * that, the reparenting is glitchy in hardware, etc), use the
+ * CLK_SET_PARENT_GATE flag to allow reparenting only when clk is unprepared.
+ *
+ * After successfully changing clk's parent clk_set_parent will update the
+ * clk topology, sysfs topology and propagate rate recalculation via
+ * __clk_recalc_rates.
+ *
+ * Returns 0 on success, -EERROR otherwise.
+ */
+int clk_set_parent(struct clk *clk, struct clk *parent)
+{
+	if (!clk)
+		return 0;
+
+	return clk_core_set_parent(clk->core, parent ? parent->core : NULL);
+}
 EXPORT_SYMBOL_GPL(clk_set_parent);
 
 /**
@@ -1755,13 +1881,13 @@ int clk_set_phase(struct clk *clk, int degrees)
 
 	clk_prepare_lock();
 
-	if (!clk->ops->set_phase)
+	if (!clk->core->ops->set_phase)
 		goto out_unlock;
 
-	ret = clk->ops->set_phase(clk->hw, degrees);
+	ret = clk->core->ops->set_phase(clk->core->hw, degrees);
 
 	if (!ret)
-		clk->phase = degrees;
+		clk->core->phase = degrees;
 
 out_unlock:
 	clk_prepare_unlock();
@@ -1770,14 +1896,7 @@ out:
 	return ret;
 }
 
-/**
- * clk_get_phase - return the phase shift of a clock signal
- * @clk: clock signal source
- *
- * Returns the phase shift of a clock node in degrees, otherwise returns
- * -EERROR.
- */
-int clk_get_phase(struct clk *clk)
+static int clk_core_get_phase(struct clk_core *clk)
 {
 	int ret = 0;
 
@@ -1793,26 +1912,44 @@ out:
 }
 
 /**
+ * clk_get_phase - return the phase shift of a clock signal
+ * @clk: clock signal source
+ *
+ * Returns the phase shift of a clock node in degrees, otherwise returns
+ * -EERROR.
+ */
+int clk_get_phase(struct clk *clk)
+{
+	if (!clk)
+		return 0;
+
+	return clk_core_get_phase(clk->core);
+}
+
+/**
  * __clk_init - initialize the data structures in a struct clk
  * @dev:	device initializing this clk, placeholder for now
  * @clk:	clk being initialized
  *
- * Initializes the lists in struct clk, queries the hardware for the
+ * Initializes the lists in struct clk_core, queries the hardware for the
  * parent and rate and sets them both.
  */
-int __clk_init(struct device *dev, struct clk *clk)
+int __clk_init(struct device *dev, struct clk *clk_user)
 {
 	int i, ret = 0;
-	struct clk *orphan;
+	struct clk_core *orphan;
 	struct hlist_node *tmp2;
+	struct clk_core *clk;
 
-	if (!clk)
+	if (!clk_user)
 		return -EINVAL;
 
+	clk = clk_user->core;
+
 	clk_prepare_lock();
 
 	/* check to see if a clock with this name is already registered */
-	if (__clk_lookup(clk->name)) {
+	if (clk_core_lookup(clk->name)) {
 		pr_debug("%s: clk %s already initialized\n",
 				__func__, clk->name);
 		ret = -EEXIST;
@@ -1864,7 +2001,7 @@ int __clk_init(struct device *dev, struct clk *clk)
 		clk->parents = kcalloc(clk->num_parents, sizeof(struct clk *),
 					GFP_KERNEL);
 		/*
-		 * __clk_lookup returns NULL for parents that have not been
+		 * clk_core_lookup returns NULL for parents that have not been
 		 * clk_init'd; thus any access to clk->parents[] must check
 		 * for a NULL pointer.  We can always perform lazy lookups for
 		 * missing parents later on.
@@ -1872,7 +2009,7 @@ int __clk_init(struct device *dev, struct clk *clk)
 		if (clk->parents)
 			for (i = 0; i < clk->num_parents; i++)
 				clk->parents[i] =
-					__clk_lookup(clk->parent_names[i]);
+					clk_core_lookup(clk->parent_names[i]);
 	}
 
 	clk->parent = __clk_init_parent(clk);
@@ -1928,7 +2065,7 @@ int __clk_init(struct device *dev, struct clk *clk)
 	 */
 	if (clk->ops->recalc_rate)
 		clk->rate = clk->ops->recalc_rate(clk->hw,
-				__clk_get_rate(clk->parent));
+				clk_core_get_rate_nolock(clk->parent));
 	else if (clk->parent)
 		clk->rate = clk->parent->rate;
 	else
@@ -1942,13 +2079,13 @@ int __clk_init(struct device *dev, struct clk *clk)
 		if (orphan->num_parents && orphan->ops->get_parent) {
 			i = orphan->ops->get_parent(orphan->hw);
 			if (!strcmp(clk->name, orphan->parent_names[i]))
-				__clk_reparent(orphan, clk);
+				clk_core_reparent(orphan, clk);
 			continue;
 		}
 
 		for (i = 0; i < orphan->num_parents; i++)
 			if (!strcmp(clk->name, orphan->parent_names[i])) {
-				__clk_reparent(orphan, clk);
+				clk_core_reparent(orphan, clk);
 				break;
 			}
 	 }
@@ -1974,6 +2111,26 @@ out:
 	return ret;
 }
 
+struct clk *__clk_create_clk(struct clk_hw *hw, const char *dev_id,
+			     const char *con_id)
+{
+	struct clk *clk;
+
+	/* This is to allow this function to be chained to others */
+	if (!hw || IS_ERR(hw))
+		return (struct clk *) hw;
+
+	clk = kzalloc(sizeof(*clk), GFP_KERNEL);
+	if (!clk)
+		return ERR_PTR(-ENOMEM);
+
+	clk->core = hw->core;
+	clk->dev_id = dev_id;
+	clk->con_id = con_id;
+
+	return clk;
+}
+
 /**
  * clk_register - allocate a new clock, register it and return an opaque cookie
  * @dev: device that is registering this clock
@@ -1988,7 +2145,7 @@ out:
 struct clk *clk_register(struct device *dev, struct clk_hw *hw)
 {
 	int i, ret;
-	struct clk *clk;
+	struct clk_core *clk;
 
 	clk = kzalloc(sizeof(*clk), GFP_KERNEL);
 	if (!clk) {
@@ -2009,7 +2166,7 @@ struct clk *clk_register(struct device *dev, struct clk_hw *hw)
 	clk->hw = hw;
 	clk->flags = hw->init->flags;
 	clk->num_parents = hw->init->num_parents;
-	hw->clk = clk;
+	hw->core = clk;
 
 	/* allocate local copy in case parent_names is __initdata */
 	clk->parent_names = kcalloc(clk->num_parents, sizeof(char *),
@@ -2033,10 +2190,19 @@ struct clk *clk_register(struct device *dev, struct clk_hw *hw)
 		}
 	}
 
-	ret = __clk_init(dev, clk);
+	hw->clk = __clk_create_clk(hw, NULL, NULL);
+	if (IS_ERR(hw->clk)) {
+		pr_err("%s: could not allocate per-user clk\n", __func__);
+		ret = PTR_ERR(hw->clk);
+		goto fail_parent_names_copy;
+	}
+
+	ret = __clk_init(dev, hw->clk);
 	if (!ret)
-		return clk;
+		return hw->clk;
 
+	kfree(hw->clk);
+	hw->clk = NULL;
 fail_parent_names_copy:
 	while (--i >= 0)
 		kfree(clk->parent_names[i]);
@@ -2056,7 +2222,7 @@ EXPORT_SYMBOL_GPL(clk_register);
  */
 static void __clk_release(struct kref *ref)
 {
-	struct clk *clk = container_of(ref, struct clk, ref);
+	struct clk_core *clk = container_of(ref, struct clk_core, ref);
 	int i = clk->num_parents;
 
 	kfree(clk->parents);
@@ -2114,12 +2280,13 @@ void clk_unregister(struct clk *clk)
 	if (!clk || WARN_ON_ONCE(IS_ERR(clk)))
 		return;
 
-	clk_debug_unregister(clk);
+	clk_debug_unregister(clk->core);
 
 	clk_prepare_lock();
 
-	if (clk->ops == &clk_nodrv_ops) {
-		pr_err("%s: unregistered clock: %s\n", __func__, clk->name);
+	if (clk->core->ops == &clk_nodrv_ops) {
+		pr_err("%s: unregistered clock: %s\n", __func__,
+		       clk->core->name);
 		return;
 	}
 	/*
@@ -2127,24 +2294,25 @@ void clk_unregister(struct clk *clk)
 	 * a reference to this clock.
 	 */
 	flags = clk_enable_lock();
-	clk->ops = &clk_nodrv_ops;
+	clk->core->ops = &clk_nodrv_ops;
 	clk_enable_unlock(flags);
 
-	if (!hlist_empty(&clk->children)) {
-		struct clk *child;
+	if (!hlist_empty(&clk->core->children)) {
+		struct clk_core *child;
 		struct hlist_node *t;
 
 		/* Reparent all children to the orphan list. */
-		hlist_for_each_entry_safe(child, t, &clk->children, child_node)
-			clk_set_parent(child, NULL);
+		hlist_for_each_entry_safe(child, t, &clk->core->children,
+					  child_node)
+			clk_core_set_parent(child, NULL);
 	}
 
-	hlist_del_init(&clk->child_node);
+	hlist_del_init(&clk->core->child_node);
 
-	if (clk->prepare_count)
+	if (clk->core->prepare_count)
 		pr_warn("%s: unregistering prepared clock: %s\n",
-					__func__, clk->name);
-	kref_put(&clk->ref, __clk_release);
+					__func__, clk->core->name);
+	kref_put(&clk->core->ref, __clk_release);
 
 	clk_prepare_unlock();
 }
@@ -2212,30 +2380,39 @@ EXPORT_SYMBOL_GPL(devm_clk_unregister);
  */
 int __clk_get(struct clk *clk)
 {
-	if (clk) {
-		if (!try_module_get(clk->owner))
+	struct clk_core *core = !clk ? NULL : clk->core;
+
+	if (core) {
+		if (!try_module_get(core->owner))
 			return 0;
 
-		kref_get(&clk->ref);
+		kref_get(&core->ref);
 	}
 	return 1;
 }
 
-void __clk_put(struct clk *clk)
+static void clk_core_put(struct clk_core *core)
 {
 	struct module *owner;
 
-	if (!clk || WARN_ON_ONCE(IS_ERR(clk)))
-		return;
+	owner = core->owner;
 
 	clk_prepare_lock();
-	owner = clk->owner;
-	kref_put(&clk->ref, __clk_release);
+	kref_put(&core->ref, __clk_release);
 	clk_prepare_unlock();
 
 	module_put(owner);
 }
 
+void __clk_put(struct clk *clk)
+{
+	if (!clk || WARN_ON_ONCE(IS_ERR(clk)))
+		return;
+
+	clk_core_put(clk->core);
+	kfree(clk);
+}
+
 /***        clk rate change notifiers        ***/
 
 /**
@@ -2288,7 +2465,7 @@ int clk_notifier_register(struct clk *clk, struct notifier_block *nb)
 
 	ret = srcu_notifier_chain_register(&cn->notifier_head, nb);
 
-	clk->notifier_count++;
+	clk->core->notifier_count++;
 
 out:
 	clk_prepare_unlock();
@@ -2325,7 +2502,7 @@ int clk_notifier_unregister(struct clk *clk, struct notifier_block *nb)
 	if (cn->clk == clk) {
 		ret = srcu_notifier_chain_unregister(&cn->notifier_head, nb);
 
-		clk->notifier_count--;
+		clk->core->notifier_count--;
 
 		/* XXX the notifier code should handle this better */
 		if (!cn->notifier_head.head) {
diff --git a/drivers/clk/clk.h b/drivers/clk/clk.h
index c798138..23c44e5 100644
--- a/drivers/clk/clk.h
+++ b/drivers/clk/clk.h
@@ -9,9 +9,14 @@
  * published by the Free Software Foundation.
  */
 
+struct clk_hw;
+
 #if defined(CONFIG_OF) && defined(CONFIG_COMMON_CLK)
 struct clk *of_clk_get_by_clkspec(struct of_phandle_args *clkspec);
 struct clk *__of_clk_get_from_provider(struct of_phandle_args *clkspec);
 void of_clk_lock(void);
 void of_clk_unlock(void);
 #endif
+
+struct clk *__clk_create_clk(struct clk_hw *hw, const char *dev_id,
+			     const char *con_id);
diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c
index da4bda8..901d242 100644
--- a/drivers/clk/clkdev.c
+++ b/drivers/clk/clkdev.c
@@ -19,6 +19,7 @@
 #include <linux/mutex.h>
 #include <linux/clk.h>
 #include <linux/clkdev.h>
+#include <linux/clk-provider.h>
 #include <linux/of.h>
 
 #include "clk.h"
@@ -53,7 +54,7 @@ struct clk *of_clk_get_by_clkspec(struct of_phandle_args *clkspec)
 	return clk;
 }
 
-struct clk *of_clk_get(struct device_node *np, int index)
+static struct clk *__of_clk_get(struct device_node *np, int index)
 {
 	struct of_phandle_args clkspec;
 	struct clk *clk;
@@ -69,20 +70,24 @@ struct clk *of_clk_get(struct device_node *np, int index)
 
 	clk = of_clk_get_by_clkspec(&clkspec);
 	of_node_put(clkspec.np);
+
+	return clk;
+}
+
+struct clk *of_clk_get(struct device_node *np, int index)
+{
+	struct clk *clk = __of_clk_get(np, index);
+
+	if (!IS_ERR(clk))
+		clk = __clk_create_clk(__clk_get_hw(clk), np->full_name, NULL);
+
 	return clk;
 }
 EXPORT_SYMBOL(of_clk_get);
 
-/**
- * of_clk_get_by_name() - Parse and lookup a clock referenced by a device node
- * @np: pointer to clock consumer node
- * @name: name of consumer's clock input, or NULL for the first clock reference
- *
- * This function parses the clocks and clock-names properties,
- * and uses them to look up the struct clk from the registered list of clock
- * providers.
- */
-struct clk *of_clk_get_by_name(struct device_node *np, const char *name)
+static struct clk *__of_clk_get_by_name(struct device_node *np,
+					const char *dev_id,
+					const char *name)
 {
 	struct clk *clk = ERR_PTR(-ENOENT);
 
@@ -97,9 +102,11 @@ struct clk *of_clk_get_by_name(struct device_node *np, const char *name)
 		 */
 		if (name)
 			index = of_property_match_string(np, "clock-names", name);
-		clk = of_clk_get(np, index);
-		if (!IS_ERR(clk))
+		clk = __of_clk_get(np, index);
+		if (!IS_ERR(clk)) {
+			clk = __clk_create_clk(__clk_get_hw(clk), dev_id, name);
 			break;
+		}
 		else if (name && index >= 0) {
 			if (PTR_ERR(clk) != -EPROBE_DEFER)
 				pr_err("ERROR: could not get clock %s:%s(%i)\n",
@@ -119,7 +126,33 @@ struct clk *of_clk_get_by_name(struct device_node *np, const char *name)
 
 	return clk;
 }
+
+/**
+ * of_clk_get_by_name() - Parse and lookup a clock referenced by a device node
+ * @np: pointer to clock consumer node
+ * @name: name of consumer's clock input, or NULL for the first clock reference
+ *
+ * This function parses the clocks and clock-names properties,
+ * and uses them to look up the struct clk from the registered list of clock
+ * providers.
+ */
+struct clk *of_clk_get_by_name(struct device_node *np, const char *name)
+{
+	if (!np)
+		return ERR_PTR(-ENOENT);
+
+	return __of_clk_get_by_name(np, np->full_name, name);
+}
 EXPORT_SYMBOL(of_clk_get_by_name);
+
+#else /* defined(CONFIG_OF) && defined(CONFIG_COMMON_CLK) */
+
+static struct clk *__of_clk_get_by_name(struct device_node *np,
+					const char *dev_id,
+					const char *name)
+{
+	return ERR_PTR(-ENOENT);
+}
 #endif
 
 /*
@@ -168,14 +201,29 @@ static struct clk_lookup *clk_find(const char *dev_id, const char *con_id)
 struct clk *clk_get_sys(const char *dev_id, const char *con_id)
 {
 	struct clk_lookup *cl;
+	struct clk *clk = NULL;
 
 	mutex_lock(&clocks_mutex);
+
 	cl = clk_find(dev_id, con_id);
-	if (cl && !__clk_get(cl->clk))
+	if (!cl)
+		goto out;
+
+	if (!__clk_get(cl->clk)) {
 		cl = NULL;
+		goto out;
+	}
+
+#if defined(CONFIG_COMMON_CLK)
+	clk = __clk_create_clk(__clk_get_hw(cl->clk), dev_id, con_id);
+#else
+	clk = cl->clk;
+#endif
+
+out:
 	mutex_unlock(&clocks_mutex);
 
-	return cl ? cl->clk : ERR_PTR(-ENOENT);
+	return cl ? clk : ERR_PTR(-ENOENT);
 }
 EXPORT_SYMBOL(clk_get_sys);
 
@@ -185,10 +233,8 @@ struct clk *clk_get(struct device *dev, const char *con_id)
 	struct clk *clk;
 
 	if (dev) {
-		clk = of_clk_get_by_name(dev->of_node, con_id);
-		if (!IS_ERR(clk))
-			return clk;
-		if (PTR_ERR(clk) == -EPROBE_DEFER)
+		clk = __of_clk_get_by_name(dev->of_node, dev_id, con_id);
+		if (!IS_ERR(clk) || PTR_ERR(clk) == -EPROBE_DEFER)
 			return clk;
 	}
 
diff --git a/include/linux/clk-private.h b/include/linux/clk-private.h
index c5f40d0..ae55d99 100644
--- a/include/linux/clk-private.h
+++ b/include/linux/clk-private.h
@@ -28,20 +28,20 @@
 
 struct module;
 
-struct clk {
+struct clk_core {
 	const char		*name;
 	const struct clk_ops	*ops;
 	struct clk_hw		*hw;
 	struct module		*owner;
-	struct clk		*parent;
+	struct clk_core		*parent;
 	const char		**parent_names;
-	struct clk		**parents;
+	struct clk_core		**parents;
 	u8			num_parents;
 	u8			new_parent_index;
 	unsigned long		rate;
 	unsigned long		new_rate;
-	struct clk		*new_parent;
-	struct clk		*new_child;
+	struct clk_core		*new_parent;
+	struct clk_core		*new_child;
 	unsigned long		flags;
 	unsigned int		enable_count;
 	unsigned int		prepare_count;
@@ -57,6 +57,12 @@ struct clk {
 	struct kref		ref;
 };
 
+struct clk {
+	struct clk_core	*core;
+	const char *dev_id;
+	const char *con_id;
+};
+
 /*
  * DOC: Basic clock implementations common to many platforms
  *
@@ -69,6 +75,9 @@ struct clk {
 #define DEFINE_CLK(_name, _ops, _flags, _parent_names,		\
 		_parents)					\
 	static struct clk _name = {				\
+		.core = &_name##_core				\
+	};							\
+	static struct clk_core _name##_core = {			\
 		.name = #_name,					\
 		.ops = &_ops,					\
 		.hw = &_name##_hw.hw,				\
@@ -81,9 +90,11 @@ struct clk {
 #define DEFINE_CLK_FIXED_RATE(_name, _flags, _rate,		\
 				_fixed_rate_flags)		\
 	static struct clk _name;				\
+	static struct clk_core _name##_core;			\
 	static const char *_name##_parent_names[] = {};		\
 	static struct clk_fixed_rate _name##_hw = {		\
 		.hw = {						\
+			.core = &_name##_core,			\
 			.clk = &_name,				\
 		},						\
 		.fixed_rate = _rate,				\
@@ -96,14 +107,16 @@ struct clk {
 				_flags, _reg, _bit_idx,		\
 				_gate_flags, _lock)		\
 	static struct clk _name;				\
+	static struct clk_core _name##_core;			\
 	static const char *_name##_parent_names[] = {		\
 		_parent_name,					\
 	};							\
-	static struct clk *_name##_parents[] = {		\
+	static struct clk_core *_name##_parents[] = {		\
 		_parent_ptr,					\
 	};							\
 	static struct clk_gate _name##_hw = {			\
 		.hw = {						\
+			.core = &_name##_core,			\
 			.clk = &_name,				\
 		},						\
 		.reg = _reg,					\
@@ -118,14 +131,16 @@ struct clk {
 				_flags, _reg, _shift, _width,	\
 				_divider_flags, _table, _lock)	\
 	static struct clk _name;				\
+	static struct clk_core _name##_core;			\
 	static const char *_name##_parent_names[] = {		\
 		_parent_name,					\
 	};							\
-	static struct clk *_name##_parents[] = {		\
+	static struct clk_core *_name##_parents[] = {		\
 		_parent_ptr,					\
 	};							\
 	static struct clk_divider _name##_hw = {		\
 		.hw = {						\
+			.core = &_name##_core,			\
 			.clk = &_name,				\
 		},						\
 		.reg = _reg,					\
@@ -157,8 +172,10 @@ struct clk {
 				_reg, _shift, _width,		\
 				_mux_flags, _lock)		\
 	static struct clk _name;				\
+	static struct clk_core _name##_core;			\
 	static struct clk_mux _name##_hw = {			\
 		.hw = {						\
+			.core = &_name##_core,			\
 			.clk = &_name,				\
 		},						\
 		.reg = _reg,					\
@@ -174,14 +191,16 @@ struct clk {
 				_parent_ptr, _flags,		\
 				_mult, _div)			\
 	static struct clk _name;				\
+	static struct clk_core _name##_core;			\
 	static const char *_name##_parent_names[] = {		\
 		_parent_name,					\
 	};							\
-	static struct clk *_name##_parents[] = {		\
+	static struct clk_core *_name##_parents[] = {		\
 		_parent_ptr,					\
 	};							\
 	static struct clk_fixed_factor _name##_hw = {		\
 		.hw = {						\
+			.core = &_name##_core,			\
 			.clk = &_name,				\
 		},						\
 		.mult = _mult,					\
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index d936409..9afd438 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -33,6 +33,7 @@
 #define CLK_GET_ACCURACY_NOCACHE BIT(8) /* do not use the cached clk accuracy */
 
 struct clk_hw;
+struct clk_core;
 struct dentry;
 
 /**
@@ -216,13 +217,17 @@ struct clk_init_data {
  * clk_foo and then referenced by the struct clk instance that uses struct
  * clk_foo's clk_ops
  *
- * @clk: pointer to the struct clk instance that points back to this struct
- * clk_hw instance
+ * @core: pointer to the struct clk_core instance that points back to this
+ * struct clk_hw instance
+ *
+ * @clk: pointer to the per-user struct clk instance that can be used to call
+ * into the clk API
  *
  * @init: pointer to struct clk_init_data that contains the init data shared
  * with the common clock framework.
  */
 struct clk_hw {
+	struct clk_core *core;
 	struct clk *clk;
 	const struct clk_init_data *init;
 };
@@ -556,9 +561,6 @@ long __clk_mux_determine_rate(struct clk_hw *hw, unsigned long rate,
 /*
  * FIXME clock api without lock protection
  */
-int __clk_prepare(struct clk *clk);
-void __clk_unprepare(struct clk *clk);
-void __clk_reparent(struct clk *clk, struct clk *new_parent);
 unsigned long __clk_round_rate(struct clk *clk, unsigned long rate);
 
 struct of_device_id;
-- 
1.9.3

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

* [PATCH v13 4/6] clk: Add rate constraints to clocks
  2015-01-23 11:03 [PATCH v13 0/6] Per-user clock constraints Tomeu Vizoso
  2015-01-23 11:03 ` [PATCH v13 1/6] clk: Remove unneeded NULL checks Tomeu Vizoso
@ 2015-01-23 11:03   ` Tomeu Vizoso
  2015-01-23 11:03   ` Tomeu Vizoso
                     ` (4 subsequent siblings)
  6 siblings, 0 replies; 186+ messages in thread
From: Tomeu Vizoso @ 2015-01-23 11:03 UTC (permalink / raw)
  To: linux-kernel, Mike Turquette, Stephen Boyd
  Cc: Javier Martinez Canillas, Tomeu Vizoso, Jonathan Corbet,
	Tony Lindgren, Russell King, Ralf Baechle, Boris Brezillon,
	Emilio López, Maxime Ripard, Tero Kristo, Manuel Lauss,
	Alex Elder, Matt Porter, Haojian Zhuang, Zhangfei Gao,
	Bintian Wang, Chao Xie, linux-doc, linux-omap, linux-arm-kernel,
	linux-mips

Adds a way for clock consumers to set maximum and minimum rates. This
can be used for thermal drivers to set minimum rates, or by misc.
drivers to set maximum rates to assure a minimum performance level.

Changes the signature of the determine_rate callback by adding the
parameters min_rate and max_rate.

Signed-off-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
Reviewed-by: Stephen Boyd <sboyd@codeaurora.org>

---
v13:	* Cut one line to the 80-column limit
	* Make clear in the docs that the ranges are inclusive

v12:	* Refactor locking so that __clk_put takes the lock only once

v11:	* Recalculate the rate before putting the reference to clk_core
	* Don't recalculate the rate when freeing the per-user clock
	in the initialization error paths
	* Move __clk_create_clk to be next to __clk_free_clk for more
	comfortable reading

v10:	* Refactor __clk_determine_rate to share code with
	clk_round_rate.
	* Remove clk_core_round_rate_nolock as it's unused now

v9:	* s/floor/min and s/ceiling/max
	* Add a bunch of NULL checks
	* Propagate our rate range when querying our parent for the rate
	* Take constraints into account in clk_round_rate
	* Add __clk_determine_rate() for clk providers to ask their
	parents for a rate within their range
	* Make sure that what ops->round_rate returns when changing
	rates is within the range

v7:	* Update a few more instances in new code

v6:	* Take the prepare lock before removing a per-user clk
	* Init per-user clks list before adding the first clk
	* Pass the constraints to determine_rate and let clk
	  implementations deal with constraints
	* Add clk_set_rate_range

v5:	* Initialize clk.ceiling_constraint to ULONG_MAX
	* Warn about inconsistent constraints

v4:	* Copy function docs from header
	* Move WARN out of critical section
	* Refresh rate after removing a per-user clk
	* Rename clk_core.per_user_clks to clk_core.clks
	* Store requested rate and re-apply it when constraints are updated
---
 Documentation/clk.txt               |   2 +
 arch/arm/mach-omap2/dpll3xxx.c      |   2 +
 arch/arm/mach-omap2/dpll44xx.c      |   2 +
 arch/mips/alchemy/common/clock.c    |   8 ++
 drivers/clk/at91/clk-programmable.c |   2 +
 drivers/clk/bcm/clk-kona.c          |   2 +
 drivers/clk/clk-composite.c         |   9 +-
 drivers/clk/clk.c                   | 249 +++++++++++++++++++++++++++++-------
 drivers/clk/hisilicon/clk-hi3620.c  |   2 +
 drivers/clk/mmp/clk-mix.c           |   2 +
 drivers/clk/qcom/clk-pll.c          |   1 +
 drivers/clk/qcom/clk-rcg.c          |  10 +-
 drivers/clk/qcom/clk-rcg2.c         |   6 +
 drivers/clk/sunxi/clk-factors.c     |   2 +
 drivers/clk/sunxi/clk-sun6i-ar100.c |   2 +
 include/linux/clk-private.h         |   6 +
 include/linux/clk-provider.h        |  15 ++-
 include/linux/clk.h                 |  28 ++++
 include/linux/clk/ti.h              |   4 +
 19 files changed, 298 insertions(+), 56 deletions(-)

diff --git a/Documentation/clk.txt b/Documentation/clk.txt
index 4ff8462..0e4f90a 100644
--- a/Documentation/clk.txt
+++ b/Documentation/clk.txt
@@ -73,6 +73,8 @@ the operations defined in clk.h:
 						unsigned long *parent_rate);
 		long		(*determine_rate)(struct clk_hw *hw,
 						unsigned long rate,
+						unsigned long min_rate,
+						unsigned long max_rate,
 						unsigned long *best_parent_rate,
 						struct clk_hw **best_parent_clk);
 		int		(*set_parent)(struct clk_hw *hw, u8 index);
diff --git a/arch/arm/mach-omap2/dpll3xxx.c b/arch/arm/mach-omap2/dpll3xxx.c
index c2da2a0..ac3fb11 100644
--- a/arch/arm/mach-omap2/dpll3xxx.c
+++ b/arch/arm/mach-omap2/dpll3xxx.c
@@ -473,6 +473,8 @@ void omap3_noncore_dpll_disable(struct clk_hw *hw)
  * in failure.
  */
 long omap3_noncore_dpll_determine_rate(struct clk_hw *hw, unsigned long rate,
+				       unsigned long min_rate,
+				       unsigned long max_rate,
 				       unsigned long *best_parent_rate,
 				       struct clk_hw **best_parent_clk)
 {
diff --git a/arch/arm/mach-omap2/dpll44xx.c b/arch/arm/mach-omap2/dpll44xx.c
index 0e58e5a..acacb90 100644
--- a/arch/arm/mach-omap2/dpll44xx.c
+++ b/arch/arm/mach-omap2/dpll44xx.c
@@ -222,6 +222,8 @@ out:
  * in failure.
  */
 long omap4_dpll_regm4xen_determine_rate(struct clk_hw *hw, unsigned long rate,
+					unsigned long min_rate,
+					unsigned long max_rate,
 					unsigned long *best_parent_rate,
 					struct clk_hw **best_parent_clk)
 {
diff --git a/arch/mips/alchemy/common/clock.c b/arch/mips/alchemy/common/clock.c
index 48a9dfc..4e65404 100644
--- a/arch/mips/alchemy/common/clock.c
+++ b/arch/mips/alchemy/common/clock.c
@@ -373,6 +373,8 @@ static long alchemy_calc_div(unsigned long rate, unsigned long prate,
 }
 
 static long alchemy_clk_fgcs_detr(struct clk_hw *hw, unsigned long rate,
+					unsigned long min_rate,
+					unsigned long max_rate,
 					unsigned long *best_parent_rate,
 					struct clk_hw **best_parent_clk,
 					int scale, int maxdiv)
@@ -546,6 +548,8 @@ static unsigned long alchemy_clk_fgv1_recalc(struct clk_hw *hw,
 }
 
 static long alchemy_clk_fgv1_detr(struct clk_hw *hw, unsigned long rate,
+					unsigned long min_rate,
+					unsigned long max_rate,
 					unsigned long *best_parent_rate,
 					struct clk_hw **best_parent_clk)
 {
@@ -678,6 +682,8 @@ static unsigned long alchemy_clk_fgv2_recalc(struct clk_hw *hw,
 }
 
 static long alchemy_clk_fgv2_detr(struct clk_hw *hw, unsigned long rate,
+					unsigned long min_rate,
+					unsigned long max_rate,
 					unsigned long *best_parent_rate,
 					struct clk_hw **best_parent_clk)
 {
@@ -897,6 +903,8 @@ static int alchemy_clk_csrc_setr(struct clk_hw *hw, unsigned long rate,
 }
 
 static long alchemy_clk_csrc_detr(struct clk_hw *hw, unsigned long rate,
+					unsigned long min_rate,
+					unsigned long max_rate,
 					unsigned long *best_parent_rate,
 					struct clk_hw **best_parent_clk)
 {
diff --git a/drivers/clk/at91/clk-programmable.c b/drivers/clk/at91/clk-programmable.c
index bbdb1b9..86c8a07 100644
--- a/drivers/clk/at91/clk-programmable.c
+++ b/drivers/clk/at91/clk-programmable.c
@@ -56,6 +56,8 @@ static unsigned long clk_programmable_recalc_rate(struct clk_hw *hw,
 
 static long clk_programmable_determine_rate(struct clk_hw *hw,
 					    unsigned long rate,
+					    unsigned long min_rate,
+					    unsigned long max_rate,
 					    unsigned long *best_parent_rate,
 					    struct clk_hw **best_parent_hw)
 {
diff --git a/drivers/clk/bcm/clk-kona.c b/drivers/clk/bcm/clk-kona.c
index 1c06f6f..05abae8 100644
--- a/drivers/clk/bcm/clk-kona.c
+++ b/drivers/clk/bcm/clk-kona.c
@@ -1032,6 +1032,8 @@ static long kona_peri_clk_round_rate(struct clk_hw *hw, unsigned long rate,
 }
 
 static long kona_peri_clk_determine_rate(struct clk_hw *hw, unsigned long rate,
+		unsigned long min_rate,
+		unsigned long max_rate,
 		unsigned long *best_parent_rate, struct clk_hw **best_parent)
 {
 	struct kona_clk *bcm_clk = to_kona_clk(hw);
diff --git a/drivers/clk/clk-composite.c b/drivers/clk/clk-composite.c
index 4386697..dee81b8 100644
--- a/drivers/clk/clk-composite.c
+++ b/drivers/clk/clk-composite.c
@@ -56,6 +56,8 @@ static unsigned long clk_composite_recalc_rate(struct clk_hw *hw,
 }
 
 static long clk_composite_determine_rate(struct clk_hw *hw, unsigned long rate,
+					unsigned long min_rate,
+					unsigned long max_rate,
 					unsigned long *best_parent_rate,
 					struct clk_hw **best_parent_p)
 {
@@ -73,7 +75,9 @@ static long clk_composite_determine_rate(struct clk_hw *hw, unsigned long rate,
 
 	if (rate_hw && rate_ops && rate_ops->determine_rate) {
 		rate_hw->clk = hw->clk;
-		return rate_ops->determine_rate(rate_hw, rate, best_parent_rate,
+		return rate_ops->determine_rate(rate_hw, rate, min_rate,
+						max_rate,
+						best_parent_rate,
 						best_parent_p);
 	} else if (rate_hw && rate_ops && rate_ops->round_rate &&
 		   mux_hw && mux_ops && mux_ops->set_parent) {
@@ -117,7 +121,8 @@ static long clk_composite_determine_rate(struct clk_hw *hw, unsigned long rate,
 		return best_rate;
 	} else if (mux_hw && mux_ops && mux_ops->determine_rate) {
 		mux_hw->clk = hw->clk;
-		return mux_ops->determine_rate(mux_hw, rate, best_parent_rate,
+		return mux_ops->determine_rate(mux_hw, rate, min_rate,
+					       max_rate, best_parent_rate,
 					       best_parent_p);
 	} else {
 		pr_err("clk: clk_composite_determine_rate function called, but no mux or rate callback set!\n");
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 0b7091c..ec51978 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -42,8 +42,6 @@ static unsigned long clk_core_get_rate(struct clk_core *clk);
 static int clk_core_get_phase(struct clk_core *clk);
 static bool clk_core_is_prepared(struct clk_core *clk);
 static bool clk_core_is_enabled(struct clk_core *clk);
-static unsigned long clk_core_round_rate_nolock(struct clk_core *clk,
-						unsigned long rate);
 static struct clk_core *clk_core_lookup(const char *name);
 
 /***           locking             ***/
@@ -746,12 +744,30 @@ struct clk *__clk_lookup(const char *name)
 	return !core ? NULL : core->hw->clk;
 }
 
+static void clk_core_get_boundaries(struct clk_core *clk,
+				    unsigned long *min_rate,
+				    unsigned long *max_rate)
+{
+	struct clk *clk_user;
+
+	*min_rate = 0;
+	*max_rate = ULONG_MAX;
+
+	hlist_for_each_entry(clk_user, &clk->clks, child_node)
+		*min_rate = max(*min_rate, clk_user->min_rate);
+
+	hlist_for_each_entry(clk_user, &clk->clks, child_node)
+		*max_rate = min(*max_rate, clk_user->max_rate);
+}
+
 /*
  * Helper for finding best parent to provide a given frequency. This can be used
  * directly as a determine_rate callback (e.g. for a mux), or from a more
  * complex clock that may combine a mux with other operations.
  */
 long __clk_mux_determine_rate(struct clk_hw *hw, unsigned long rate,
+			      unsigned long min_rate,
+			      unsigned long max_rate,
 			      unsigned long *best_parent_rate,
 			      struct clk_hw **best_parent_p)
 {
@@ -763,7 +779,8 @@ long __clk_mux_determine_rate(struct clk_hw *hw, unsigned long rate,
 	if (core->flags & CLK_SET_RATE_NO_REPARENT) {
 		parent = core->parent;
 		if (core->flags & CLK_SET_RATE_PARENT)
-			best = clk_core_round_rate_nolock(parent, rate);
+			best = __clk_determine_rate(parent->hw, rate,
+						    min_rate, max_rate);
 		else if (parent)
 			best = clk_core_get_rate_nolock(parent);
 		else
@@ -778,7 +795,9 @@ long __clk_mux_determine_rate(struct clk_hw *hw, unsigned long rate,
 		if (!parent)
 			continue;
 		if (core->flags & CLK_SET_RATE_PARENT)
-			parent_rate = clk_core_round_rate_nolock(parent, rate);
+			parent_rate = __clk_determine_rate(parent->hw, rate,
+							   min_rate,
+							   max_rate);
 		else
 			parent_rate = clk_core_get_rate_nolock(parent);
 		if (parent_rate <= rate && parent_rate > best) {
@@ -1006,7 +1025,9 @@ int clk_enable(struct clk *clk)
 EXPORT_SYMBOL_GPL(clk_enable);
 
 static unsigned long clk_core_round_rate_nolock(struct clk_core *clk,
-						unsigned long rate)
+						unsigned long rate,
+						unsigned long min_rate,
+						unsigned long max_rate)
 {
 	unsigned long parent_rate = 0;
 	struct clk_core *parent;
@@ -1021,17 +1042,41 @@ static unsigned long clk_core_round_rate_nolock(struct clk_core *clk,
 
 	if (clk->ops->determine_rate) {
 		parent_hw = parent ? parent->hw : NULL;
-		return clk->ops->determine_rate(clk->hw, rate, &parent_rate,
-						&parent_hw);
+		return clk->ops->determine_rate(clk->hw, rate,
+						min_rate, max_rate,
+						&parent_rate, &parent_hw);
 	} else if (clk->ops->round_rate)
 		return clk->ops->round_rate(clk->hw, rate, &parent_rate);
 	else if (clk->flags & CLK_SET_RATE_PARENT)
-		return clk_core_round_rate_nolock(clk->parent, rate);
+		return clk_core_round_rate_nolock(clk->parent, rate, min_rate,
+						  max_rate);
 	else
 		return clk->rate;
 }
 
 /**
+ * __clk_determine_rate - get the closest rate actually supported by a clock
+ * @hw: determine the rate of this clock
+ * @rate: target rate
+ * @min_rate: returned rate must be greater than this rate
+ * @max_rate: returned rate must be less than this rate
+ *
+ * Caller must hold prepare_lock.  Useful for clk_ops such as .set_rate and
+ * .determine_rate.
+ */
+unsigned long __clk_determine_rate(struct clk_hw *hw,
+				   unsigned long rate,
+				   unsigned long min_rate,
+				   unsigned long max_rate)
+{
+	if (!hw)
+		return 0;
+
+	return clk_core_round_rate_nolock(hw->core, rate, min_rate, max_rate);
+}
+EXPORT_SYMBOL_GPL(__clk_determine_rate);
+
+/**
  * __clk_round_rate - round the given rate for a clk
  * @clk: round the rate of this clock
  * @rate: the rate which is to be rounded
@@ -1040,10 +1085,15 @@ static unsigned long clk_core_round_rate_nolock(struct clk_core *clk,
  */
 unsigned long __clk_round_rate(struct clk *clk, unsigned long rate)
 {
+	unsigned long min_rate;
+	unsigned long max_rate;
+
 	if (!clk)
 		return 0;
 
-	return clk_core_round_rate_nolock(clk->core, rate);
+	clk_core_get_boundaries(clk->core, &min_rate, &max_rate);
+
+	return clk_core_round_rate_nolock(clk->core, rate, min_rate, max_rate);
 }
 EXPORT_SYMBOL_GPL(__clk_round_rate);
 
@@ -1064,7 +1114,7 @@ long clk_round_rate(struct clk *clk, unsigned long rate)
 		return 0;
 
 	clk_prepare_lock();
-	ret = clk_core_round_rate_nolock(clk->core, rate);
+	ret = __clk_round_rate(clk, rate);
 	clk_prepare_unlock();
 
 	return ret;
@@ -1455,6 +1505,8 @@ static struct clk_core *clk_calc_new_rates(struct clk_core *clk,
 	struct clk_hw *parent_hw;
 	unsigned long best_parent_rate = 0;
 	unsigned long new_rate;
+	unsigned long min_rate;
+	unsigned long max_rate;
 	int p_index = 0;
 
 	/* sanity */
@@ -1466,16 +1518,22 @@ static struct clk_core *clk_calc_new_rates(struct clk_core *clk,
 	if (parent)
 		best_parent_rate = parent->rate;
 
+	clk_core_get_boundaries(clk, &min_rate, &max_rate);
+
 	/* find the closest rate and parent clk/rate */
 	if (clk->ops->determine_rate) {
 		parent_hw = parent ? parent->hw : NULL;
 		new_rate = clk->ops->determine_rate(clk->hw, rate,
+						    min_rate,
+						    max_rate,
 						    &best_parent_rate,
 						    &parent_hw);
 		parent = parent_hw ? parent_hw->core : NULL;
 	} else if (clk->ops->round_rate) {
 		new_rate = clk->ops->round_rate(clk->hw, rate,
 						&best_parent_rate);
+		if (new_rate < min_rate || new_rate > max_rate)
+			return NULL;
 	} else if (!parent || !(clk->flags & CLK_SET_RATE_PARENT)) {
 		/* pass-through clock without adjustable parent */
 		clk->new_rate = clk->rate;
@@ -1613,6 +1671,45 @@ static void clk_change_rate(struct clk_core *clk)
 		clk_change_rate(clk->new_child);
 }
 
+static int clk_core_set_rate_nolock(struct clk_core *clk,
+				    unsigned long req_rate)
+{
+	struct clk_core *top, *fail_clk;
+	unsigned long rate = req_rate;
+	int ret = 0;
+
+	if (!clk)
+		return 0;
+
+	/* bail early if nothing to do */
+	if (rate == clk_core_get_rate_nolock(clk))
+		return 0;
+
+	if ((clk->flags & CLK_SET_RATE_GATE) && clk->prepare_count)
+		return -EBUSY;
+
+	/* calculate new rates and get the topmost changed clock */
+	top = clk_calc_new_rates(clk, rate);
+	if (!top)
+		return -EINVAL;
+
+	/* notify that we are about to change rates */
+	fail_clk = clk_propagate_rate_change(top, PRE_RATE_CHANGE);
+	if (fail_clk) {
+		pr_debug("%s: failed to set %s rate\n", __func__,
+				fail_clk->name);
+		clk_propagate_rate_change(top, ABORT_RATE_CHANGE);
+		return -EBUSY;
+	}
+
+	/* change the rates */
+	clk_change_rate(top);
+
+	clk->req_rate = req_rate;
+
+	return ret;
+}
+
 /**
  * clk_set_rate - specify a new rate for clk
  * @clk: the clk whose rate is being changed
@@ -1636,8 +1733,7 @@ static void clk_change_rate(struct clk_core *clk)
  */
 int clk_set_rate(struct clk *clk, unsigned long rate)
 {
-	struct clk_core *top, *fail_clk;
-	int ret = 0;
+	int ret;
 
 	if (!clk)
 		return 0;
@@ -1645,42 +1741,81 @@ int clk_set_rate(struct clk *clk, unsigned long rate)
 	/* prevent racing with updates to the clock topology */
 	clk_prepare_lock();
 
-	/* bail early if nothing to do */
-	if (rate == clk_get_rate(clk))
-		goto out;
+	ret = clk_core_set_rate_nolock(clk->core, rate);
 
-	if ((clk->core->flags & CLK_SET_RATE_GATE) &&
-	    clk->core->prepare_count) {
-		ret = -EBUSY;
-		goto out;
-	}
+	clk_prepare_unlock();
 
-	/* calculate new rates and get the topmost changed clock */
-	top = clk_calc_new_rates(clk->core, rate);
-	if (!top) {
-		ret = -EINVAL;
-		goto out;
-	}
+	return ret;
+}
+EXPORT_SYMBOL_GPL(clk_set_rate);
 
-	/* notify that we are about to change rates */
-	fail_clk = clk_propagate_rate_change(top, PRE_RATE_CHANGE);
-	if (fail_clk) {
-		pr_debug("%s: failed to set %s rate\n", __func__,
-				fail_clk->name);
-		clk_propagate_rate_change(top, ABORT_RATE_CHANGE);
-		ret = -EBUSY;
-		goto out;
+/**
+ * clk_set_rate_range - set a rate range for a clock source
+ * @clk: clock source
+ * @min: desired minimum clock rate in Hz, inclusive
+ * @max: desired maximum clock rate in Hz, inclusive
+ *
+ * Returns success (0) or negative errno.
+ */
+int clk_set_rate_range(struct clk *clk, unsigned long min, unsigned long max)
+{
+	int ret = 0;
+
+	if (!clk)
+		return 0;
+
+	if (min > max) {
+		pr_err("%s: clk %s dev %s con %s: invalid range [%lu, %lu]\n",
+		       __func__, clk->core->name, clk->dev_id, clk->con_id,
+		       min, max);
+		return -EINVAL;
 	}
 
-	/* change the rates */
-	clk_change_rate(top);
+	clk_prepare_lock();
+
+	if (min != clk->min_rate || max != clk->max_rate) {
+		clk->min_rate = min;
+		clk->max_rate = max;
+		ret = clk_core_set_rate_nolock(clk->core, clk->core->req_rate);
+	}
 
-out:
 	clk_prepare_unlock();
 
 	return ret;
 }
-EXPORT_SYMBOL_GPL(clk_set_rate);
+EXPORT_SYMBOL_GPL(clk_set_rate_range);
+
+/**
+ * clk_set_min_rate - set a minimum clock rate for a clock source
+ * @clk: clock source
+ * @rate: desired minimum clock rate in Hz, inclusive
+ *
+ * Returns success (0) or negative errno.
+ */
+int clk_set_min_rate(struct clk *clk, unsigned long rate)
+{
+	if (!clk)
+		return 0;
+
+	return clk_set_rate_range(clk, rate, clk->max_rate);
+}
+EXPORT_SYMBOL_GPL(clk_set_min_rate);
+
+/**
+ * clk_set_max_rate - set a maximum clock rate for a clock source
+ * @clk: clock source
+ * @rate: desired maximum clock rate in Hz, inclusive
+ *
+ * Returns success (0) or negative errno.
+ */
+int clk_set_max_rate(struct clk *clk, unsigned long rate)
+{
+	if (!clk)
+		return 0;
+
+	return clk_set_rate_range(clk, clk->min_rate, rate);
+}
+EXPORT_SYMBOL_GPL(clk_set_max_rate);
 
 /**
  * clk_get_parent - return the parent of a clk
@@ -2127,10 +2262,24 @@ struct clk *__clk_create_clk(struct clk_hw *hw, const char *dev_id,
 	clk->core = hw->core;
 	clk->dev_id = dev_id;
 	clk->con_id = con_id;
+	clk->max_rate = ULONG_MAX;
+
+	clk_prepare_lock();
+	hlist_add_head(&clk->child_node, &hw->core->clks);
+	clk_prepare_unlock();
 
 	return clk;
 }
 
+static void __clk_free_clk(struct clk *clk)
+{
+	clk_prepare_lock();
+	hlist_del(&clk->child_node);
+	clk_prepare_unlock();
+
+	kfree(clk);
+}
+
 /**
  * clk_register - allocate a new clock, register it and return an opaque cookie
  * @dev: device that is registering this clock
@@ -2190,6 +2339,8 @@ struct clk *clk_register(struct device *dev, struct clk_hw *hw)
 		}
 	}
 
+	INIT_HLIST_HEAD(&clk->clks);
+
 	hw->clk = __clk_create_clk(hw, NULL, NULL);
 	if (IS_ERR(hw->clk)) {
 		pr_err("%s: could not allocate per-user clk\n", __func__);
@@ -2201,8 +2352,9 @@ struct clk *clk_register(struct device *dev, struct clk_hw *hw)
 	if (!ret)
 		return hw->clk;
 
-	kfree(hw->clk);
+	__clk_free_clk(hw->clk);
 	hw->clk = NULL;
+
 fail_parent_names_copy:
 	while (--i >= 0)
 		kfree(clk->parent_names[i]);
@@ -2391,25 +2543,24 @@ int __clk_get(struct clk *clk)
 	return 1;
 }
 
-static void clk_core_put(struct clk_core *core)
+void __clk_put(struct clk *clk)
 {
 	struct module *owner;
 
-	owner = core->owner;
+	if (!clk || WARN_ON_ONCE(IS_ERR(clk)))
+		return;
 
 	clk_prepare_lock();
-	kref_put(&core->ref, __clk_release);
+
+	hlist_del(&clk->child_node);
+	clk_core_set_rate_nolock(clk->core, clk->core->req_rate);
+	owner = clk->core->owner;
+	kref_put(&clk->core->ref, __clk_release);
+
 	clk_prepare_unlock();
 
 	module_put(owner);
-}
-
-void __clk_put(struct clk *clk)
-{
-	if (!clk || WARN_ON_ONCE(IS_ERR(clk)))
-		return;
 
-	clk_core_put(clk->core);
 	kfree(clk);
 }
 
diff --git a/drivers/clk/hisilicon/clk-hi3620.c b/drivers/clk/hisilicon/clk-hi3620.c
index 007144f..2e4f6d4 100644
--- a/drivers/clk/hisilicon/clk-hi3620.c
+++ b/drivers/clk/hisilicon/clk-hi3620.c
@@ -295,6 +295,8 @@ static unsigned long mmc_clk_recalc_rate(struct clk_hw *hw,
 }
 
 static long mmc_clk_determine_rate(struct clk_hw *hw, unsigned long rate,
+			      unsigned long min_rate,
+			      unsigned long max_rate,
 			      unsigned long *best_parent_rate,
 			      struct clk_hw **best_parent_p)
 {
diff --git a/drivers/clk/mmp/clk-mix.c b/drivers/clk/mmp/clk-mix.c
index 48fa53c..de6a873 100644
--- a/drivers/clk/mmp/clk-mix.c
+++ b/drivers/clk/mmp/clk-mix.c
@@ -202,6 +202,8 @@ error:
 }
 
 static long mmp_clk_mix_determine_rate(struct clk_hw *hw, unsigned long rate,
+					unsigned long min_rate,
+					unsigned long max_rate,
 					unsigned long *best_parent_rate,
 					struct clk_hw **best_parent_clk)
 {
diff --git a/drivers/clk/qcom/clk-pll.c b/drivers/clk/qcom/clk-pll.c
index 60873a7..b4325f6 100644
--- a/drivers/clk/qcom/clk-pll.c
+++ b/drivers/clk/qcom/clk-pll.c
@@ -141,6 +141,7 @@ struct pll_freq_tbl *find_freq(const struct pll_freq_tbl *f, unsigned long rate)
 
 static long
 clk_pll_determine_rate(struct clk_hw *hw, unsigned long rate,
+		       unsigned long min_rate, unsigned long max_rate,
 		       unsigned long *p_rate, struct clk_hw **p)
 {
 	struct clk_pll *pll = to_clk_pll(hw);
diff --git a/drivers/clk/qcom/clk-rcg.c b/drivers/clk/qcom/clk-rcg.c
index 0b93972..0039bd7 100644
--- a/drivers/clk/qcom/clk-rcg.c
+++ b/drivers/clk/qcom/clk-rcg.c
@@ -368,6 +368,7 @@ clk_dyn_rcg_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
 
 static long _freq_tbl_determine_rate(struct clk_hw *hw,
 		const struct freq_tbl *f, unsigned long rate,
+		unsigned long min_rate, unsigned long max_rate,
 		unsigned long *p_rate, struct clk_hw **p_hw)
 {
 	unsigned long clk_flags;
@@ -397,22 +398,27 @@ static long _freq_tbl_determine_rate(struct clk_hw *hw,
 }
 
 static long clk_rcg_determine_rate(struct clk_hw *hw, unsigned long rate,
+		unsigned long min_rate, unsigned long max_rate,
 		unsigned long *p_rate, struct clk_hw **p)
 {
 	struct clk_rcg *rcg = to_clk_rcg(hw);
 
-	return _freq_tbl_determine_rate(hw, rcg->freq_tbl, rate, p_rate, p);
+	return _freq_tbl_determine_rate(hw, rcg->freq_tbl, rate, min_rate,
+			max_rate, p_rate, p);
 }
 
 static long clk_dyn_rcg_determine_rate(struct clk_hw *hw, unsigned long rate,
+		unsigned long min_rate, unsigned long max_rate,
 		unsigned long *p_rate, struct clk_hw **p)
 {
 	struct clk_dyn_rcg *rcg = to_clk_dyn_rcg(hw);
 
-	return _freq_tbl_determine_rate(hw, rcg->freq_tbl, rate, p_rate, p);
+	return _freq_tbl_determine_rate(hw, rcg->freq_tbl, rate, min_rate,
+			max_rate, p_rate, p);
 }
 
 static long clk_rcg_bypass_determine_rate(struct clk_hw *hw, unsigned long rate,
+		unsigned long min_rate, unsigned long max_rate,
 		unsigned long *p_rate, struct clk_hw **p_hw)
 {
 	struct clk_rcg *rcg = to_clk_rcg(hw);
diff --git a/drivers/clk/qcom/clk-rcg2.c b/drivers/clk/qcom/clk-rcg2.c
index 08b8b37..742acfa 100644
--- a/drivers/clk/qcom/clk-rcg2.c
+++ b/drivers/clk/qcom/clk-rcg2.c
@@ -208,6 +208,7 @@ static long _freq_tbl_determine_rate(struct clk_hw *hw,
 }
 
 static long clk_rcg2_determine_rate(struct clk_hw *hw, unsigned long rate,
+		unsigned long min_rate, unsigned long max_rate,
 		unsigned long *p_rate, struct clk_hw **p)
 {
 	struct clk_rcg2 *rcg = to_clk_rcg2(hw);
@@ -361,6 +362,8 @@ static int clk_edp_pixel_set_rate_and_parent(struct clk_hw *hw,
 }
 
 static long clk_edp_pixel_determine_rate(struct clk_hw *hw, unsigned long rate,
+				 unsigned long min_rate,
+				 unsigned long max_rate,
 				 unsigned long *p_rate, struct clk_hw **p)
 {
 	struct clk_rcg2 *rcg = to_clk_rcg2(hw);
@@ -412,6 +415,7 @@ const struct clk_ops clk_edp_pixel_ops = {
 EXPORT_SYMBOL_GPL(clk_edp_pixel_ops);
 
 static long clk_byte_determine_rate(struct clk_hw *hw, unsigned long rate,
+			 unsigned long min_rate, unsigned long max_rate,
 			 unsigned long *p_rate, struct clk_hw **p_hw)
 {
 	struct clk_rcg2 *rcg = to_clk_rcg2(hw);
@@ -476,6 +480,8 @@ static const struct frac_entry frac_table_pixel[] = {
 };
 
 static long clk_pixel_determine_rate(struct clk_hw *hw, unsigned long rate,
+				 unsigned long min_rate,
+				 unsigned long max_rate,
 				 unsigned long *p_rate, struct clk_hw **p)
 {
 	struct clk_rcg2 *rcg = to_clk_rcg2(hw);
diff --git a/drivers/clk/sunxi/clk-factors.c b/drivers/clk/sunxi/clk-factors.c
index 62e08fb..761029b 100644
--- a/drivers/clk/sunxi/clk-factors.c
+++ b/drivers/clk/sunxi/clk-factors.c
@@ -80,6 +80,8 @@ static long clk_factors_round_rate(struct clk_hw *hw, unsigned long rate,
 }
 
 static long clk_factors_determine_rate(struct clk_hw *hw, unsigned long rate,
+				       unsigned long min_rate,
+				       unsigned long max_rate,
 				       unsigned long *best_parent_rate,
 				       struct clk_hw **best_parent_p)
 {
diff --git a/drivers/clk/sunxi/clk-sun6i-ar100.c b/drivers/clk/sunxi/clk-sun6i-ar100.c
index 3d282fb..63cf149 100644
--- a/drivers/clk/sunxi/clk-sun6i-ar100.c
+++ b/drivers/clk/sunxi/clk-sun6i-ar100.c
@@ -45,6 +45,8 @@ static unsigned long ar100_recalc_rate(struct clk_hw *hw,
 }
 
 static long ar100_determine_rate(struct clk_hw *hw, unsigned long rate,
+				 unsigned long min_rate,
+				 unsigned long max_rate,
 				 unsigned long *best_parent_rate,
 				 struct clk_hw **best_parent_clk)
 {
diff --git a/include/linux/clk-private.h b/include/linux/clk-private.h
index ae55d99..5136b30 100644
--- a/include/linux/clk-private.h
+++ b/include/linux/clk-private.h
@@ -39,6 +39,7 @@ struct clk_core {
 	u8			num_parents;
 	u8			new_parent_index;
 	unsigned long		rate;
+	unsigned long		req_rate;
 	unsigned long		new_rate;
 	struct clk_core		*new_parent;
 	struct clk_core		*new_child;
@@ -50,6 +51,7 @@ struct clk_core {
 	struct hlist_head	children;
 	struct hlist_node	child_node;
 	struct hlist_node	debug_node;
+	struct hlist_head	clks;
 	unsigned int		notifier_count;
 #ifdef CONFIG_DEBUG_FS
 	struct dentry		*dentry;
@@ -61,6 +63,10 @@ struct clk {
 	struct clk_core	*core;
 	const char *dev_id;
 	const char *con_id;
+
+	unsigned long min_rate;
+	unsigned long max_rate;
+	struct hlist_node child_node;
 };
 
 /*
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 9afd438..2416026 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -175,9 +175,12 @@ struct clk_ops {
 					unsigned long parent_rate);
 	long		(*round_rate)(struct clk_hw *hw, unsigned long rate,
 					unsigned long *parent_rate);
-	long		(*determine_rate)(struct clk_hw *hw, unsigned long rate,
-					unsigned long *best_parent_rate,
-					struct clk_hw **best_parent_hw);
+	long		(*determine_rate)(struct clk_hw *hw,
+					  unsigned long rate,
+					  unsigned long min_rate,
+					  unsigned long max_rate,
+					  unsigned long *best_parent_rate,
+					  struct clk_hw **best_parent_hw);
 	int		(*set_parent)(struct clk_hw *hw, u8 index);
 	u8		(*get_parent)(struct clk_hw *hw);
 	int		(*set_rate)(struct clk_hw *hw, unsigned long rate,
@@ -555,8 +558,14 @@ bool __clk_is_prepared(struct clk *clk);
 bool __clk_is_enabled(struct clk *clk);
 struct clk *__clk_lookup(const char *name);
 long __clk_mux_determine_rate(struct clk_hw *hw, unsigned long rate,
+			      unsigned long min_rate,
+			      unsigned long max_rate,
 			      unsigned long *best_parent_rate,
 			      struct clk_hw **best_parent_p);
+unsigned long __clk_determine_rate(struct clk_hw *core,
+				   unsigned long rate,
+				   unsigned long min_rate,
+				   unsigned long max_rate);
 
 /*
  * FIXME clock api without lock protection
diff --git a/include/linux/clk.h b/include/linux/clk.h
index c7f258a..a891e21 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -302,6 +302,34 @@ long clk_round_rate(struct clk *clk, unsigned long rate);
 int clk_set_rate(struct clk *clk, unsigned long rate);
 
 /**
+ * clk_set_rate_range - set a rate range for a clock source
+ * @clk: clock source
+ * @min: desired minimum clock rate in Hz, inclusive
+ * @max: desired maximum clock rate in Hz, inclusive
+ *
+ * Returns success (0) or negative errno.
+ */
+int clk_set_rate_range(struct clk *clk, unsigned long min, unsigned long max);
+
+/**
+ * clk_set_min_rate - set a minimum clock rate for a clock source
+ * @clk: clock source
+ * @rate: desired minimum clock rate in Hz, inclusive
+ *
+ * Returns success (0) or negative errno.
+ */
+int clk_set_min_rate(struct clk *clk, unsigned long rate);
+
+/**
+ * clk_set_max_rate - set a maximum clock rate for a clock source
+ * @clk: clock source
+ * @rate: desired maximum clock rate in Hz, inclusive
+ *
+ * Returns success (0) or negative errno.
+ */
+int clk_set_max_rate(struct clk *clk, unsigned long rate);
+
+/**
  * clk_set_parent - set the parent clock source for this clock
  * @clk: clock source
  * @parent: parent clock source
diff --git a/include/linux/clk/ti.h b/include/linux/clk/ti.h
index 55ef529..cfb9e55 100644
--- a/include/linux/clk/ti.h
+++ b/include/linux/clk/ti.h
@@ -263,6 +263,8 @@ int omap3_noncore_dpll_set_rate_and_parent(struct clk_hw *hw,
 					   u8 index);
 long omap3_noncore_dpll_determine_rate(struct clk_hw *hw,
 				       unsigned long rate,
+				       unsigned long min_rate,
+				       unsigned long max_rate,
 				       unsigned long *best_parent_rate,
 				       struct clk_hw **best_parent_clk);
 unsigned long omap4_dpll_regm4xen_recalc(struct clk_hw *hw,
@@ -272,6 +274,8 @@ long omap4_dpll_regm4xen_round_rate(struct clk_hw *hw,
 				    unsigned long *parent_rate);
 long omap4_dpll_regm4xen_determine_rate(struct clk_hw *hw,
 					unsigned long rate,
+					unsigned long min_rate,
+					unsigned long max_rate,
 					unsigned long *best_parent_rate,
 					struct clk_hw **best_parent_clk);
 u8 omap2_init_dpll_parent(struct clk_hw *hw);
-- 
1.9.3


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

* [PATCH v13 4/6] clk: Add rate constraints to clocks
@ 2015-01-23 11:03   ` Tomeu Vizoso
  0 siblings, 0 replies; 186+ messages in thread
From: Tomeu Vizoso @ 2015-01-23 11:03 UTC (permalink / raw)
  To: linux-kernel, Mike Turquette, Stephen Boyd
  Cc: Javier Martinez Canillas, Tomeu Vizoso, Jonathan Corbet,
	Tony Lindgren, Russell King, Ralf Baechle, Boris Brezillon,
	Emilio López, Maxime Ripard, Tero Kristo, Manuel Lauss,
	Alex Elder, Matt Porter, Haojian Zhuang, Zhangfei Gao,
	Bintian Wang, Chao Xie, linux-doc, linux-omap

Adds a way for clock consumers to set maximum and minimum rates. This
can be used for thermal drivers to set minimum rates, or by misc.
drivers to set maximum rates to assure a minimum performance level.

Changes the signature of the determine_rate callback by adding the
parameters min_rate and max_rate.

Signed-off-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
Reviewed-by: Stephen Boyd <sboyd@codeaurora.org>

---
v13:	* Cut one line to the 80-column limit
	* Make clear in the docs that the ranges are inclusive

v12:	* Refactor locking so that __clk_put takes the lock only once

v11:	* Recalculate the rate before putting the reference to clk_core
	* Don't recalculate the rate when freeing the per-user clock
	in the initialization error paths
	* Move __clk_create_clk to be next to __clk_free_clk for more
	comfortable reading

v10:	* Refactor __clk_determine_rate to share code with
	clk_round_rate.
	* Remove clk_core_round_rate_nolock as it's unused now

v9:	* s/floor/min and s/ceiling/max
	* Add a bunch of NULL checks
	* Propagate our rate range when querying our parent for the rate
	* Take constraints into account in clk_round_rate
	* Add __clk_determine_rate() for clk providers to ask their
	parents for a rate within their range
	* Make sure that what ops->round_rate returns when changing
	rates is within the range

v7:	* Update a few more instances in new code

v6:	* Take the prepare lock before removing a per-user clk
	* Init per-user clks list before adding the first clk
	* Pass the constraints to determine_rate and let clk
	  implementations deal with constraints
	* Add clk_set_rate_range

v5:	* Initialize clk.ceiling_constraint to ULONG_MAX
	* Warn about inconsistent constraints

v4:	* Copy function docs from header
	* Move WARN out of critical section
	* Refresh rate after removing a per-user clk
	* Rename clk_core.per_user_clks to clk_core.clks
	* Store requested rate and re-apply it when constraints are updated
---
 Documentation/clk.txt               |   2 +
 arch/arm/mach-omap2/dpll3xxx.c      |   2 +
 arch/arm/mach-omap2/dpll44xx.c      |   2 +
 arch/mips/alchemy/common/clock.c    |   8 ++
 drivers/clk/at91/clk-programmable.c |   2 +
 drivers/clk/bcm/clk-kona.c          |   2 +
 drivers/clk/clk-composite.c         |   9 +-
 drivers/clk/clk.c                   | 249 +++++++++++++++++++++++++++++-------
 drivers/clk/hisilicon/clk-hi3620.c  |   2 +
 drivers/clk/mmp/clk-mix.c           |   2 +
 drivers/clk/qcom/clk-pll.c          |   1 +
 drivers/clk/qcom/clk-rcg.c          |  10 +-
 drivers/clk/qcom/clk-rcg2.c         |   6 +
 drivers/clk/sunxi/clk-factors.c     |   2 +
 drivers/clk/sunxi/clk-sun6i-ar100.c |   2 +
 include/linux/clk-private.h         |   6 +
 include/linux/clk-provider.h        |  15 ++-
 include/linux/clk.h                 |  28 ++++
 include/linux/clk/ti.h              |   4 +
 19 files changed, 298 insertions(+), 56 deletions(-)

diff --git a/Documentation/clk.txt b/Documentation/clk.txt
index 4ff8462..0e4f90a 100644
--- a/Documentation/clk.txt
+++ b/Documentation/clk.txt
@@ -73,6 +73,8 @@ the operations defined in clk.h:
 						unsigned long *parent_rate);
 		long		(*determine_rate)(struct clk_hw *hw,
 						unsigned long rate,
+						unsigned long min_rate,
+						unsigned long max_rate,
 						unsigned long *best_parent_rate,
 						struct clk_hw **best_parent_clk);
 		int		(*set_parent)(struct clk_hw *hw, u8 index);
diff --git a/arch/arm/mach-omap2/dpll3xxx.c b/arch/arm/mach-omap2/dpll3xxx.c
index c2da2a0..ac3fb11 100644
--- a/arch/arm/mach-omap2/dpll3xxx.c
+++ b/arch/arm/mach-omap2/dpll3xxx.c
@@ -473,6 +473,8 @@ void omap3_noncore_dpll_disable(struct clk_hw *hw)
  * in failure.
  */
 long omap3_noncore_dpll_determine_rate(struct clk_hw *hw, unsigned long rate,
+				       unsigned long min_rate,
+				       unsigned long max_rate,
 				       unsigned long *best_parent_rate,
 				       struct clk_hw **best_parent_clk)
 {
diff --git a/arch/arm/mach-omap2/dpll44xx.c b/arch/arm/mach-omap2/dpll44xx.c
index 0e58e5a..acacb90 100644
--- a/arch/arm/mach-omap2/dpll44xx.c
+++ b/arch/arm/mach-omap2/dpll44xx.c
@@ -222,6 +222,8 @@ out:
  * in failure.
  */
 long omap4_dpll_regm4xen_determine_rate(struct clk_hw *hw, unsigned long rate,
+					unsigned long min_rate,
+					unsigned long max_rate,
 					unsigned long *best_parent_rate,
 					struct clk_hw **best_parent_clk)
 {
diff --git a/arch/mips/alchemy/common/clock.c b/arch/mips/alchemy/common/clock.c
index 48a9dfc..4e65404 100644
--- a/arch/mips/alchemy/common/clock.c
+++ b/arch/mips/alchemy/common/clock.c
@@ -373,6 +373,8 @@ static long alchemy_calc_div(unsigned long rate, unsigned long prate,
 }
 
 static long alchemy_clk_fgcs_detr(struct clk_hw *hw, unsigned long rate,
+					unsigned long min_rate,
+					unsigned long max_rate,
 					unsigned long *best_parent_rate,
 					struct clk_hw **best_parent_clk,
 					int scale, int maxdiv)
@@ -546,6 +548,8 @@ static unsigned long alchemy_clk_fgv1_recalc(struct clk_hw *hw,
 }
 
 static long alchemy_clk_fgv1_detr(struct clk_hw *hw, unsigned long rate,
+					unsigned long min_rate,
+					unsigned long max_rate,
 					unsigned long *best_parent_rate,
 					struct clk_hw **best_parent_clk)
 {
@@ -678,6 +682,8 @@ static unsigned long alchemy_clk_fgv2_recalc(struct clk_hw *hw,
 }
 
 static long alchemy_clk_fgv2_detr(struct clk_hw *hw, unsigned long rate,
+					unsigned long min_rate,
+					unsigned long max_rate,
 					unsigned long *best_parent_rate,
 					struct clk_hw **best_parent_clk)
 {
@@ -897,6 +903,8 @@ static int alchemy_clk_csrc_setr(struct clk_hw *hw, unsigned long rate,
 }
 
 static long alchemy_clk_csrc_detr(struct clk_hw *hw, unsigned long rate,
+					unsigned long min_rate,
+					unsigned long max_rate,
 					unsigned long *best_parent_rate,
 					struct clk_hw **best_parent_clk)
 {
diff --git a/drivers/clk/at91/clk-programmable.c b/drivers/clk/at91/clk-programmable.c
index bbdb1b9..86c8a07 100644
--- a/drivers/clk/at91/clk-programmable.c
+++ b/drivers/clk/at91/clk-programmable.c
@@ -56,6 +56,8 @@ static unsigned long clk_programmable_recalc_rate(struct clk_hw *hw,
 
 static long clk_programmable_determine_rate(struct clk_hw *hw,
 					    unsigned long rate,
+					    unsigned long min_rate,
+					    unsigned long max_rate,
 					    unsigned long *best_parent_rate,
 					    struct clk_hw **best_parent_hw)
 {
diff --git a/drivers/clk/bcm/clk-kona.c b/drivers/clk/bcm/clk-kona.c
index 1c06f6f..05abae8 100644
--- a/drivers/clk/bcm/clk-kona.c
+++ b/drivers/clk/bcm/clk-kona.c
@@ -1032,6 +1032,8 @@ static long kona_peri_clk_round_rate(struct clk_hw *hw, unsigned long rate,
 }
 
 static long kona_peri_clk_determine_rate(struct clk_hw *hw, unsigned long rate,
+		unsigned long min_rate,
+		unsigned long max_rate,
 		unsigned long *best_parent_rate, struct clk_hw **best_parent)
 {
 	struct kona_clk *bcm_clk = to_kona_clk(hw);
diff --git a/drivers/clk/clk-composite.c b/drivers/clk/clk-composite.c
index 4386697..dee81b8 100644
--- a/drivers/clk/clk-composite.c
+++ b/drivers/clk/clk-composite.c
@@ -56,6 +56,8 @@ static unsigned long clk_composite_recalc_rate(struct clk_hw *hw,
 }
 
 static long clk_composite_determine_rate(struct clk_hw *hw, unsigned long rate,
+					unsigned long min_rate,
+					unsigned long max_rate,
 					unsigned long *best_parent_rate,
 					struct clk_hw **best_parent_p)
 {
@@ -73,7 +75,9 @@ static long clk_composite_determine_rate(struct clk_hw *hw, unsigned long rate,
 
 	if (rate_hw && rate_ops && rate_ops->determine_rate) {
 		rate_hw->clk = hw->clk;
-		return rate_ops->determine_rate(rate_hw, rate, best_parent_rate,
+		return rate_ops->determine_rate(rate_hw, rate, min_rate,
+						max_rate,
+						best_parent_rate,
 						best_parent_p);
 	} else if (rate_hw && rate_ops && rate_ops->round_rate &&
 		   mux_hw && mux_ops && mux_ops->set_parent) {
@@ -117,7 +121,8 @@ static long clk_composite_determine_rate(struct clk_hw *hw, unsigned long rate,
 		return best_rate;
 	} else if (mux_hw && mux_ops && mux_ops->determine_rate) {
 		mux_hw->clk = hw->clk;
-		return mux_ops->determine_rate(mux_hw, rate, best_parent_rate,
+		return mux_ops->determine_rate(mux_hw, rate, min_rate,
+					       max_rate, best_parent_rate,
 					       best_parent_p);
 	} else {
 		pr_err("clk: clk_composite_determine_rate function called, but no mux or rate callback set!\n");
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 0b7091c..ec51978 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -42,8 +42,6 @@ static unsigned long clk_core_get_rate(struct clk_core *clk);
 static int clk_core_get_phase(struct clk_core *clk);
 static bool clk_core_is_prepared(struct clk_core *clk);
 static bool clk_core_is_enabled(struct clk_core *clk);
-static unsigned long clk_core_round_rate_nolock(struct clk_core *clk,
-						unsigned long rate);
 static struct clk_core *clk_core_lookup(const char *name);
 
 /***           locking             ***/
@@ -746,12 +744,30 @@ struct clk *__clk_lookup(const char *name)
 	return !core ? NULL : core->hw->clk;
 }
 
+static void clk_core_get_boundaries(struct clk_core *clk,
+				    unsigned long *min_rate,
+				    unsigned long *max_rate)
+{
+	struct clk *clk_user;
+
+	*min_rate = 0;
+	*max_rate = ULONG_MAX;
+
+	hlist_for_each_entry(clk_user, &clk->clks, child_node)
+		*min_rate = max(*min_rate, clk_user->min_rate);
+
+	hlist_for_each_entry(clk_user, &clk->clks, child_node)
+		*max_rate = min(*max_rate, clk_user->max_rate);
+}
+
 /*
  * Helper for finding best parent to provide a given frequency. This can be used
  * directly as a determine_rate callback (e.g. for a mux), or from a more
  * complex clock that may combine a mux with other operations.
  */
 long __clk_mux_determine_rate(struct clk_hw *hw, unsigned long rate,
+			      unsigned long min_rate,
+			      unsigned long max_rate,
 			      unsigned long *best_parent_rate,
 			      struct clk_hw **best_parent_p)
 {
@@ -763,7 +779,8 @@ long __clk_mux_determine_rate(struct clk_hw *hw, unsigned long rate,
 	if (core->flags & CLK_SET_RATE_NO_REPARENT) {
 		parent = core->parent;
 		if (core->flags & CLK_SET_RATE_PARENT)
-			best = clk_core_round_rate_nolock(parent, rate);
+			best = __clk_determine_rate(parent->hw, rate,
+						    min_rate, max_rate);
 		else if (parent)
 			best = clk_core_get_rate_nolock(parent);
 		else
@@ -778,7 +795,9 @@ long __clk_mux_determine_rate(struct clk_hw *hw, unsigned long rate,
 		if (!parent)
 			continue;
 		if (core->flags & CLK_SET_RATE_PARENT)
-			parent_rate = clk_core_round_rate_nolock(parent, rate);
+			parent_rate = __clk_determine_rate(parent->hw, rate,
+							   min_rate,
+							   max_rate);
 		else
 			parent_rate = clk_core_get_rate_nolock(parent);
 		if (parent_rate <= rate && parent_rate > best) {
@@ -1006,7 +1025,9 @@ int clk_enable(struct clk *clk)
 EXPORT_SYMBOL_GPL(clk_enable);
 
 static unsigned long clk_core_round_rate_nolock(struct clk_core *clk,
-						unsigned long rate)
+						unsigned long rate,
+						unsigned long min_rate,
+						unsigned long max_rate)
 {
 	unsigned long parent_rate = 0;
 	struct clk_core *parent;
@@ -1021,17 +1042,41 @@ static unsigned long clk_core_round_rate_nolock(struct clk_core *clk,
 
 	if (clk->ops->determine_rate) {
 		parent_hw = parent ? parent->hw : NULL;
-		return clk->ops->determine_rate(clk->hw, rate, &parent_rate,
-						&parent_hw);
+		return clk->ops->determine_rate(clk->hw, rate,
+						min_rate, max_rate,
+						&parent_rate, &parent_hw);
 	} else if (clk->ops->round_rate)
 		return clk->ops->round_rate(clk->hw, rate, &parent_rate);
 	else if (clk->flags & CLK_SET_RATE_PARENT)
-		return clk_core_round_rate_nolock(clk->parent, rate);
+		return clk_core_round_rate_nolock(clk->parent, rate, min_rate,
+						  max_rate);
 	else
 		return clk->rate;
 }
 
 /**
+ * __clk_determine_rate - get the closest rate actually supported by a clock
+ * @hw: determine the rate of this clock
+ * @rate: target rate
+ * @min_rate: returned rate must be greater than this rate
+ * @max_rate: returned rate must be less than this rate
+ *
+ * Caller must hold prepare_lock.  Useful for clk_ops such as .set_rate and
+ * .determine_rate.
+ */
+unsigned long __clk_determine_rate(struct clk_hw *hw,
+				   unsigned long rate,
+				   unsigned long min_rate,
+				   unsigned long max_rate)
+{
+	if (!hw)
+		return 0;
+
+	return clk_core_round_rate_nolock(hw->core, rate, min_rate, max_rate);
+}
+EXPORT_SYMBOL_GPL(__clk_determine_rate);
+
+/**
  * __clk_round_rate - round the given rate for a clk
  * @clk: round the rate of this clock
  * @rate: the rate which is to be rounded
@@ -1040,10 +1085,15 @@ static unsigned long clk_core_round_rate_nolock(struct clk_core *clk,
  */
 unsigned long __clk_round_rate(struct clk *clk, unsigned long rate)
 {
+	unsigned long min_rate;
+	unsigned long max_rate;
+
 	if (!clk)
 		return 0;
 
-	return clk_core_round_rate_nolock(clk->core, rate);
+	clk_core_get_boundaries(clk->core, &min_rate, &max_rate);
+
+	return clk_core_round_rate_nolock(clk->core, rate, min_rate, max_rate);
 }
 EXPORT_SYMBOL_GPL(__clk_round_rate);
 
@@ -1064,7 +1114,7 @@ long clk_round_rate(struct clk *clk, unsigned long rate)
 		return 0;
 
 	clk_prepare_lock();
-	ret = clk_core_round_rate_nolock(clk->core, rate);
+	ret = __clk_round_rate(clk, rate);
 	clk_prepare_unlock();
 
 	return ret;
@@ -1455,6 +1505,8 @@ static struct clk_core *clk_calc_new_rates(struct clk_core *clk,
 	struct clk_hw *parent_hw;
 	unsigned long best_parent_rate = 0;
 	unsigned long new_rate;
+	unsigned long min_rate;
+	unsigned long max_rate;
 	int p_index = 0;
 
 	/* sanity */
@@ -1466,16 +1518,22 @@ static struct clk_core *clk_calc_new_rates(struct clk_core *clk,
 	if (parent)
 		best_parent_rate = parent->rate;
 
+	clk_core_get_boundaries(clk, &min_rate, &max_rate);
+
 	/* find the closest rate and parent clk/rate */
 	if (clk->ops->determine_rate) {
 		parent_hw = parent ? parent->hw : NULL;
 		new_rate = clk->ops->determine_rate(clk->hw, rate,
+						    min_rate,
+						    max_rate,
 						    &best_parent_rate,
 						    &parent_hw);
 		parent = parent_hw ? parent_hw->core : NULL;
 	} else if (clk->ops->round_rate) {
 		new_rate = clk->ops->round_rate(clk->hw, rate,
 						&best_parent_rate);
+		if (new_rate < min_rate || new_rate > max_rate)
+			return NULL;
 	} else if (!parent || !(clk->flags & CLK_SET_RATE_PARENT)) {
 		/* pass-through clock without adjustable parent */
 		clk->new_rate = clk->rate;
@@ -1613,6 +1671,45 @@ static void clk_change_rate(struct clk_core *clk)
 		clk_change_rate(clk->new_child);
 }
 
+static int clk_core_set_rate_nolock(struct clk_core *clk,
+				    unsigned long req_rate)
+{
+	struct clk_core *top, *fail_clk;
+	unsigned long rate = req_rate;
+	int ret = 0;
+
+	if (!clk)
+		return 0;
+
+	/* bail early if nothing to do */
+	if (rate == clk_core_get_rate_nolock(clk))
+		return 0;
+
+	if ((clk->flags & CLK_SET_RATE_GATE) && clk->prepare_count)
+		return -EBUSY;
+
+	/* calculate new rates and get the topmost changed clock */
+	top = clk_calc_new_rates(clk, rate);
+	if (!top)
+		return -EINVAL;
+
+	/* notify that we are about to change rates */
+	fail_clk = clk_propagate_rate_change(top, PRE_RATE_CHANGE);
+	if (fail_clk) {
+		pr_debug("%s: failed to set %s rate\n", __func__,
+				fail_clk->name);
+		clk_propagate_rate_change(top, ABORT_RATE_CHANGE);
+		return -EBUSY;
+	}
+
+	/* change the rates */
+	clk_change_rate(top);
+
+	clk->req_rate = req_rate;
+
+	return ret;
+}
+
 /**
  * clk_set_rate - specify a new rate for clk
  * @clk: the clk whose rate is being changed
@@ -1636,8 +1733,7 @@ static void clk_change_rate(struct clk_core *clk)
  */
 int clk_set_rate(struct clk *clk, unsigned long rate)
 {
-	struct clk_core *top, *fail_clk;
-	int ret = 0;
+	int ret;
 
 	if (!clk)
 		return 0;
@@ -1645,42 +1741,81 @@ int clk_set_rate(struct clk *clk, unsigned long rate)
 	/* prevent racing with updates to the clock topology */
 	clk_prepare_lock();
 
-	/* bail early if nothing to do */
-	if (rate == clk_get_rate(clk))
-		goto out;
+	ret = clk_core_set_rate_nolock(clk->core, rate);
 
-	if ((clk->core->flags & CLK_SET_RATE_GATE) &&
-	    clk->core->prepare_count) {
-		ret = -EBUSY;
-		goto out;
-	}
+	clk_prepare_unlock();
 
-	/* calculate new rates and get the topmost changed clock */
-	top = clk_calc_new_rates(clk->core, rate);
-	if (!top) {
-		ret = -EINVAL;
-		goto out;
-	}
+	return ret;
+}
+EXPORT_SYMBOL_GPL(clk_set_rate);
 
-	/* notify that we are about to change rates */
-	fail_clk = clk_propagate_rate_change(top, PRE_RATE_CHANGE);
-	if (fail_clk) {
-		pr_debug("%s: failed to set %s rate\n", __func__,
-				fail_clk->name);
-		clk_propagate_rate_change(top, ABORT_RATE_CHANGE);
-		ret = -EBUSY;
-		goto out;
+/**
+ * clk_set_rate_range - set a rate range for a clock source
+ * @clk: clock source
+ * @min: desired minimum clock rate in Hz, inclusive
+ * @max: desired maximum clock rate in Hz, inclusive
+ *
+ * Returns success (0) or negative errno.
+ */
+int clk_set_rate_range(struct clk *clk, unsigned long min, unsigned long max)
+{
+	int ret = 0;
+
+	if (!clk)
+		return 0;
+
+	if (min > max) {
+		pr_err("%s: clk %s dev %s con %s: invalid range [%lu, %lu]\n",
+		       __func__, clk->core->name, clk->dev_id, clk->con_id,
+		       min, max);
+		return -EINVAL;
 	}
 
-	/* change the rates */
-	clk_change_rate(top);
+	clk_prepare_lock();
+
+	if (min != clk->min_rate || max != clk->max_rate) {
+		clk->min_rate = min;
+		clk->max_rate = max;
+		ret = clk_core_set_rate_nolock(clk->core, clk->core->req_rate);
+	}
 
-out:
 	clk_prepare_unlock();
 
 	return ret;
 }
-EXPORT_SYMBOL_GPL(clk_set_rate);
+EXPORT_SYMBOL_GPL(clk_set_rate_range);
+
+/**
+ * clk_set_min_rate - set a minimum clock rate for a clock source
+ * @clk: clock source
+ * @rate: desired minimum clock rate in Hz, inclusive
+ *
+ * Returns success (0) or negative errno.
+ */
+int clk_set_min_rate(struct clk *clk, unsigned long rate)
+{
+	if (!clk)
+		return 0;
+
+	return clk_set_rate_range(clk, rate, clk->max_rate);
+}
+EXPORT_SYMBOL_GPL(clk_set_min_rate);
+
+/**
+ * clk_set_max_rate - set a maximum clock rate for a clock source
+ * @clk: clock source
+ * @rate: desired maximum clock rate in Hz, inclusive
+ *
+ * Returns success (0) or negative errno.
+ */
+int clk_set_max_rate(struct clk *clk, unsigned long rate)
+{
+	if (!clk)
+		return 0;
+
+	return clk_set_rate_range(clk, clk->min_rate, rate);
+}
+EXPORT_SYMBOL_GPL(clk_set_max_rate);
 
 /**
  * clk_get_parent - return the parent of a clk
@@ -2127,10 +2262,24 @@ struct clk *__clk_create_clk(struct clk_hw *hw, const char *dev_id,
 	clk->core = hw->core;
 	clk->dev_id = dev_id;
 	clk->con_id = con_id;
+	clk->max_rate = ULONG_MAX;
+
+	clk_prepare_lock();
+	hlist_add_head(&clk->child_node, &hw->core->clks);
+	clk_prepare_unlock();
 
 	return clk;
 }
 
+static void __clk_free_clk(struct clk *clk)
+{
+	clk_prepare_lock();
+	hlist_del(&clk->child_node);
+	clk_prepare_unlock();
+
+	kfree(clk);
+}
+
 /**
  * clk_register - allocate a new clock, register it and return an opaque cookie
  * @dev: device that is registering this clock
@@ -2190,6 +2339,8 @@ struct clk *clk_register(struct device *dev, struct clk_hw *hw)
 		}
 	}
 
+	INIT_HLIST_HEAD(&clk->clks);
+
 	hw->clk = __clk_create_clk(hw, NULL, NULL);
 	if (IS_ERR(hw->clk)) {
 		pr_err("%s: could not allocate per-user clk\n", __func__);
@@ -2201,8 +2352,9 @@ struct clk *clk_register(struct device *dev, struct clk_hw *hw)
 	if (!ret)
 		return hw->clk;
 
-	kfree(hw->clk);
+	__clk_free_clk(hw->clk);
 	hw->clk = NULL;
+
 fail_parent_names_copy:
 	while (--i >= 0)
 		kfree(clk->parent_names[i]);
@@ -2391,25 +2543,24 @@ int __clk_get(struct clk *clk)
 	return 1;
 }
 
-static void clk_core_put(struct clk_core *core)
+void __clk_put(struct clk *clk)
 {
 	struct module *owner;
 
-	owner = core->owner;
+	if (!clk || WARN_ON_ONCE(IS_ERR(clk)))
+		return;
 
 	clk_prepare_lock();
-	kref_put(&core->ref, __clk_release);
+
+	hlist_del(&clk->child_node);
+	clk_core_set_rate_nolock(clk->core, clk->core->req_rate);
+	owner = clk->core->owner;
+	kref_put(&clk->core->ref, __clk_release);
+
 	clk_prepare_unlock();
 
 	module_put(owner);
-}
-
-void __clk_put(struct clk *clk)
-{
-	if (!clk || WARN_ON_ONCE(IS_ERR(clk)))
-		return;
 
-	clk_core_put(clk->core);
 	kfree(clk);
 }
 
diff --git a/drivers/clk/hisilicon/clk-hi3620.c b/drivers/clk/hisilicon/clk-hi3620.c
index 007144f..2e4f6d4 100644
--- a/drivers/clk/hisilicon/clk-hi3620.c
+++ b/drivers/clk/hisilicon/clk-hi3620.c
@@ -295,6 +295,8 @@ static unsigned long mmc_clk_recalc_rate(struct clk_hw *hw,
 }
 
 static long mmc_clk_determine_rate(struct clk_hw *hw, unsigned long rate,
+			      unsigned long min_rate,
+			      unsigned long max_rate,
 			      unsigned long *best_parent_rate,
 			      struct clk_hw **best_parent_p)
 {
diff --git a/drivers/clk/mmp/clk-mix.c b/drivers/clk/mmp/clk-mix.c
index 48fa53c..de6a873 100644
--- a/drivers/clk/mmp/clk-mix.c
+++ b/drivers/clk/mmp/clk-mix.c
@@ -202,6 +202,8 @@ error:
 }
 
 static long mmp_clk_mix_determine_rate(struct clk_hw *hw, unsigned long rate,
+					unsigned long min_rate,
+					unsigned long max_rate,
 					unsigned long *best_parent_rate,
 					struct clk_hw **best_parent_clk)
 {
diff --git a/drivers/clk/qcom/clk-pll.c b/drivers/clk/qcom/clk-pll.c
index 60873a7..b4325f6 100644
--- a/drivers/clk/qcom/clk-pll.c
+++ b/drivers/clk/qcom/clk-pll.c
@@ -141,6 +141,7 @@ struct pll_freq_tbl *find_freq(const struct pll_freq_tbl *f, unsigned long rate)
 
 static long
 clk_pll_determine_rate(struct clk_hw *hw, unsigned long rate,
+		       unsigned long min_rate, unsigned long max_rate,
 		       unsigned long *p_rate, struct clk_hw **p)
 {
 	struct clk_pll *pll = to_clk_pll(hw);
diff --git a/drivers/clk/qcom/clk-rcg.c b/drivers/clk/qcom/clk-rcg.c
index 0b93972..0039bd7 100644
--- a/drivers/clk/qcom/clk-rcg.c
+++ b/drivers/clk/qcom/clk-rcg.c
@@ -368,6 +368,7 @@ clk_dyn_rcg_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
 
 static long _freq_tbl_determine_rate(struct clk_hw *hw,
 		const struct freq_tbl *f, unsigned long rate,
+		unsigned long min_rate, unsigned long max_rate,
 		unsigned long *p_rate, struct clk_hw **p_hw)
 {
 	unsigned long clk_flags;
@@ -397,22 +398,27 @@ static long _freq_tbl_determine_rate(struct clk_hw *hw,
 }
 
 static long clk_rcg_determine_rate(struct clk_hw *hw, unsigned long rate,
+		unsigned long min_rate, unsigned long max_rate,
 		unsigned long *p_rate, struct clk_hw **p)
 {
 	struct clk_rcg *rcg = to_clk_rcg(hw);
 
-	return _freq_tbl_determine_rate(hw, rcg->freq_tbl, rate, p_rate, p);
+	return _freq_tbl_determine_rate(hw, rcg->freq_tbl, rate, min_rate,
+			max_rate, p_rate, p);
 }
 
 static long clk_dyn_rcg_determine_rate(struct clk_hw *hw, unsigned long rate,
+		unsigned long min_rate, unsigned long max_rate,
 		unsigned long *p_rate, struct clk_hw **p)
 {
 	struct clk_dyn_rcg *rcg = to_clk_dyn_rcg(hw);
 
-	return _freq_tbl_determine_rate(hw, rcg->freq_tbl, rate, p_rate, p);
+	return _freq_tbl_determine_rate(hw, rcg->freq_tbl, rate, min_rate,
+			max_rate, p_rate, p);
 }
 
 static long clk_rcg_bypass_determine_rate(struct clk_hw *hw, unsigned long rate,
+		unsigned long min_rate, unsigned long max_rate,
 		unsigned long *p_rate, struct clk_hw **p_hw)
 {
 	struct clk_rcg *rcg = to_clk_rcg(hw);
diff --git a/drivers/clk/qcom/clk-rcg2.c b/drivers/clk/qcom/clk-rcg2.c
index 08b8b37..742acfa 100644
--- a/drivers/clk/qcom/clk-rcg2.c
+++ b/drivers/clk/qcom/clk-rcg2.c
@@ -208,6 +208,7 @@ static long _freq_tbl_determine_rate(struct clk_hw *hw,
 }
 
 static long clk_rcg2_determine_rate(struct clk_hw *hw, unsigned long rate,
+		unsigned long min_rate, unsigned long max_rate,
 		unsigned long *p_rate, struct clk_hw **p)
 {
 	struct clk_rcg2 *rcg = to_clk_rcg2(hw);
@@ -361,6 +362,8 @@ static int clk_edp_pixel_set_rate_and_parent(struct clk_hw *hw,
 }
 
 static long clk_edp_pixel_determine_rate(struct clk_hw *hw, unsigned long rate,
+				 unsigned long min_rate,
+				 unsigned long max_rate,
 				 unsigned long *p_rate, struct clk_hw **p)
 {
 	struct clk_rcg2 *rcg = to_clk_rcg2(hw);
@@ -412,6 +415,7 @@ const struct clk_ops clk_edp_pixel_ops = {
 EXPORT_SYMBOL_GPL(clk_edp_pixel_ops);
 
 static long clk_byte_determine_rate(struct clk_hw *hw, unsigned long rate,
+			 unsigned long min_rate, unsigned long max_rate,
 			 unsigned long *p_rate, struct clk_hw **p_hw)
 {
 	struct clk_rcg2 *rcg = to_clk_rcg2(hw);
@@ -476,6 +480,8 @@ static const struct frac_entry frac_table_pixel[] = {
 };
 
 static long clk_pixel_determine_rate(struct clk_hw *hw, unsigned long rate,
+				 unsigned long min_rate,
+				 unsigned long max_rate,
 				 unsigned long *p_rate, struct clk_hw **p)
 {
 	struct clk_rcg2 *rcg = to_clk_rcg2(hw);
diff --git a/drivers/clk/sunxi/clk-factors.c b/drivers/clk/sunxi/clk-factors.c
index 62e08fb..761029b 100644
--- a/drivers/clk/sunxi/clk-factors.c
+++ b/drivers/clk/sunxi/clk-factors.c
@@ -80,6 +80,8 @@ static long clk_factors_round_rate(struct clk_hw *hw, unsigned long rate,
 }
 
 static long clk_factors_determine_rate(struct clk_hw *hw, unsigned long rate,
+				       unsigned long min_rate,
+				       unsigned long max_rate,
 				       unsigned long *best_parent_rate,
 				       struct clk_hw **best_parent_p)
 {
diff --git a/drivers/clk/sunxi/clk-sun6i-ar100.c b/drivers/clk/sunxi/clk-sun6i-ar100.c
index 3d282fb..63cf149 100644
--- a/drivers/clk/sunxi/clk-sun6i-ar100.c
+++ b/drivers/clk/sunxi/clk-sun6i-ar100.c
@@ -45,6 +45,8 @@ static unsigned long ar100_recalc_rate(struct clk_hw *hw,
 }
 
 static long ar100_determine_rate(struct clk_hw *hw, unsigned long rate,
+				 unsigned long min_rate,
+				 unsigned long max_rate,
 				 unsigned long *best_parent_rate,
 				 struct clk_hw **best_parent_clk)
 {
diff --git a/include/linux/clk-private.h b/include/linux/clk-private.h
index ae55d99..5136b30 100644
--- a/include/linux/clk-private.h
+++ b/include/linux/clk-private.h
@@ -39,6 +39,7 @@ struct clk_core {
 	u8			num_parents;
 	u8			new_parent_index;
 	unsigned long		rate;
+	unsigned long		req_rate;
 	unsigned long		new_rate;
 	struct clk_core		*new_parent;
 	struct clk_core		*new_child;
@@ -50,6 +51,7 @@ struct clk_core {
 	struct hlist_head	children;
 	struct hlist_node	child_node;
 	struct hlist_node	debug_node;
+	struct hlist_head	clks;
 	unsigned int		notifier_count;
 #ifdef CONFIG_DEBUG_FS
 	struct dentry		*dentry;
@@ -61,6 +63,10 @@ struct clk {
 	struct clk_core	*core;
 	const char *dev_id;
 	const char *con_id;
+
+	unsigned long min_rate;
+	unsigned long max_rate;
+	struct hlist_node child_node;
 };
 
 /*
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 9afd438..2416026 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -175,9 +175,12 @@ struct clk_ops {
 					unsigned long parent_rate);
 	long		(*round_rate)(struct clk_hw *hw, unsigned long rate,
 					unsigned long *parent_rate);
-	long		(*determine_rate)(struct clk_hw *hw, unsigned long rate,
-					unsigned long *best_parent_rate,
-					struct clk_hw **best_parent_hw);
+	long		(*determine_rate)(struct clk_hw *hw,
+					  unsigned long rate,
+					  unsigned long min_rate,
+					  unsigned long max_rate,
+					  unsigned long *best_parent_rate,
+					  struct clk_hw **best_parent_hw);
 	int		(*set_parent)(struct clk_hw *hw, u8 index);
 	u8		(*get_parent)(struct clk_hw *hw);
 	int		(*set_rate)(struct clk_hw *hw, unsigned long rate,
@@ -555,8 +558,14 @@ bool __clk_is_prepared(struct clk *clk);
 bool __clk_is_enabled(struct clk *clk);
 struct clk *__clk_lookup(const char *name);
 long __clk_mux_determine_rate(struct clk_hw *hw, unsigned long rate,
+			      unsigned long min_rate,
+			      unsigned long max_rate,
 			      unsigned long *best_parent_rate,
 			      struct clk_hw **best_parent_p);
+unsigned long __clk_determine_rate(struct clk_hw *core,
+				   unsigned long rate,
+				   unsigned long min_rate,
+				   unsigned long max_rate);
 
 /*
  * FIXME clock api without lock protection
diff --git a/include/linux/clk.h b/include/linux/clk.h
index c7f258a..a891e21 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -302,6 +302,34 @@ long clk_round_rate(struct clk *clk, unsigned long rate);
 int clk_set_rate(struct clk *clk, unsigned long rate);
 
 /**
+ * clk_set_rate_range - set a rate range for a clock source
+ * @clk: clock source
+ * @min: desired minimum clock rate in Hz, inclusive
+ * @max: desired maximum clock rate in Hz, inclusive
+ *
+ * Returns success (0) or negative errno.
+ */
+int clk_set_rate_range(struct clk *clk, unsigned long min, unsigned long max);
+
+/**
+ * clk_set_min_rate - set a minimum clock rate for a clock source
+ * @clk: clock source
+ * @rate: desired minimum clock rate in Hz, inclusive
+ *
+ * Returns success (0) or negative errno.
+ */
+int clk_set_min_rate(struct clk *clk, unsigned long rate);
+
+/**
+ * clk_set_max_rate - set a maximum clock rate for a clock source
+ * @clk: clock source
+ * @rate: desired maximum clock rate in Hz, inclusive
+ *
+ * Returns success (0) or negative errno.
+ */
+int clk_set_max_rate(struct clk *clk, unsigned long rate);
+
+/**
  * clk_set_parent - set the parent clock source for this clock
  * @clk: clock source
  * @parent: parent clock source
diff --git a/include/linux/clk/ti.h b/include/linux/clk/ti.h
index 55ef529..cfb9e55 100644
--- a/include/linux/clk/ti.h
+++ b/include/linux/clk/ti.h
@@ -263,6 +263,8 @@ int omap3_noncore_dpll_set_rate_and_parent(struct clk_hw *hw,
 					   u8 index);
 long omap3_noncore_dpll_determine_rate(struct clk_hw *hw,
 				       unsigned long rate,
+				       unsigned long min_rate,
+				       unsigned long max_rate,
 				       unsigned long *best_parent_rate,
 				       struct clk_hw **best_parent_clk);
 unsigned long omap4_dpll_regm4xen_recalc(struct clk_hw *hw,
@@ -272,6 +274,8 @@ long omap4_dpll_regm4xen_round_rate(struct clk_hw *hw,
 				    unsigned long *parent_rate);
 long omap4_dpll_regm4xen_determine_rate(struct clk_hw *hw,
 					unsigned long rate,
+					unsigned long min_rate,
+					unsigned long max_rate,
 					unsigned long *best_parent_rate,
 					struct clk_hw **best_parent_clk);
 u8 omap2_init_dpll_parent(struct clk_hw *hw);
-- 
1.9.3

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

* [PATCH v13 4/6] clk: Add rate constraints to clocks
@ 2015-01-23 11:03   ` Tomeu Vizoso
  0 siblings, 0 replies; 186+ messages in thread
From: Tomeu Vizoso @ 2015-01-23 11:03 UTC (permalink / raw)
  To: linux-arm-kernel

Adds a way for clock consumers to set maximum and minimum rates. This
can be used for thermal drivers to set minimum rates, or by misc.
drivers to set maximum rates to assure a minimum performance level.

Changes the signature of the determine_rate callback by adding the
parameters min_rate and max_rate.

Signed-off-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
Reviewed-by: Stephen Boyd <sboyd@codeaurora.org>

---
v13:	* Cut one line to the 80-column limit
	* Make clear in the docs that the ranges are inclusive

v12:	* Refactor locking so that __clk_put takes the lock only once

v11:	* Recalculate the rate before putting the reference to clk_core
	* Don't recalculate the rate when freeing the per-user clock
	in the initialization error paths
	* Move __clk_create_clk to be next to __clk_free_clk for more
	comfortable reading

v10:	* Refactor __clk_determine_rate to share code with
	clk_round_rate.
	* Remove clk_core_round_rate_nolock as it's unused now

v9:	* s/floor/min and s/ceiling/max
	* Add a bunch of NULL checks
	* Propagate our rate range when querying our parent for the rate
	* Take constraints into account in clk_round_rate
	* Add __clk_determine_rate() for clk providers to ask their
	parents for a rate within their range
	* Make sure that what ops->round_rate returns when changing
	rates is within the range

v7:	* Update a few more instances in new code

v6:	* Take the prepare lock before removing a per-user clk
	* Init per-user clks list before adding the first clk
	* Pass the constraints to determine_rate and let clk
	  implementations deal with constraints
	* Add clk_set_rate_range

v5:	* Initialize clk.ceiling_constraint to ULONG_MAX
	* Warn about inconsistent constraints

v4:	* Copy function docs from header
	* Move WARN out of critical section
	* Refresh rate after removing a per-user clk
	* Rename clk_core.per_user_clks to clk_core.clks
	* Store requested rate and re-apply it when constraints are updated
---
 Documentation/clk.txt               |   2 +
 arch/arm/mach-omap2/dpll3xxx.c      |   2 +
 arch/arm/mach-omap2/dpll44xx.c      |   2 +
 arch/mips/alchemy/common/clock.c    |   8 ++
 drivers/clk/at91/clk-programmable.c |   2 +
 drivers/clk/bcm/clk-kona.c          |   2 +
 drivers/clk/clk-composite.c         |   9 +-
 drivers/clk/clk.c                   | 249 +++++++++++++++++++++++++++++-------
 drivers/clk/hisilicon/clk-hi3620.c  |   2 +
 drivers/clk/mmp/clk-mix.c           |   2 +
 drivers/clk/qcom/clk-pll.c          |   1 +
 drivers/clk/qcom/clk-rcg.c          |  10 +-
 drivers/clk/qcom/clk-rcg2.c         |   6 +
 drivers/clk/sunxi/clk-factors.c     |   2 +
 drivers/clk/sunxi/clk-sun6i-ar100.c |   2 +
 include/linux/clk-private.h         |   6 +
 include/linux/clk-provider.h        |  15 ++-
 include/linux/clk.h                 |  28 ++++
 include/linux/clk/ti.h              |   4 +
 19 files changed, 298 insertions(+), 56 deletions(-)

diff --git a/Documentation/clk.txt b/Documentation/clk.txt
index 4ff8462..0e4f90a 100644
--- a/Documentation/clk.txt
+++ b/Documentation/clk.txt
@@ -73,6 +73,8 @@ the operations defined in clk.h:
 						unsigned long *parent_rate);
 		long		(*determine_rate)(struct clk_hw *hw,
 						unsigned long rate,
+						unsigned long min_rate,
+						unsigned long max_rate,
 						unsigned long *best_parent_rate,
 						struct clk_hw **best_parent_clk);
 		int		(*set_parent)(struct clk_hw *hw, u8 index);
diff --git a/arch/arm/mach-omap2/dpll3xxx.c b/arch/arm/mach-omap2/dpll3xxx.c
index c2da2a0..ac3fb11 100644
--- a/arch/arm/mach-omap2/dpll3xxx.c
+++ b/arch/arm/mach-omap2/dpll3xxx.c
@@ -473,6 +473,8 @@ void omap3_noncore_dpll_disable(struct clk_hw *hw)
  * in failure.
  */
 long omap3_noncore_dpll_determine_rate(struct clk_hw *hw, unsigned long rate,
+				       unsigned long min_rate,
+				       unsigned long max_rate,
 				       unsigned long *best_parent_rate,
 				       struct clk_hw **best_parent_clk)
 {
diff --git a/arch/arm/mach-omap2/dpll44xx.c b/arch/arm/mach-omap2/dpll44xx.c
index 0e58e5a..acacb90 100644
--- a/arch/arm/mach-omap2/dpll44xx.c
+++ b/arch/arm/mach-omap2/dpll44xx.c
@@ -222,6 +222,8 @@ out:
  * in failure.
  */
 long omap4_dpll_regm4xen_determine_rate(struct clk_hw *hw, unsigned long rate,
+					unsigned long min_rate,
+					unsigned long max_rate,
 					unsigned long *best_parent_rate,
 					struct clk_hw **best_parent_clk)
 {
diff --git a/arch/mips/alchemy/common/clock.c b/arch/mips/alchemy/common/clock.c
index 48a9dfc..4e65404 100644
--- a/arch/mips/alchemy/common/clock.c
+++ b/arch/mips/alchemy/common/clock.c
@@ -373,6 +373,8 @@ static long alchemy_calc_div(unsigned long rate, unsigned long prate,
 }
 
 static long alchemy_clk_fgcs_detr(struct clk_hw *hw, unsigned long rate,
+					unsigned long min_rate,
+					unsigned long max_rate,
 					unsigned long *best_parent_rate,
 					struct clk_hw **best_parent_clk,
 					int scale, int maxdiv)
@@ -546,6 +548,8 @@ static unsigned long alchemy_clk_fgv1_recalc(struct clk_hw *hw,
 }
 
 static long alchemy_clk_fgv1_detr(struct clk_hw *hw, unsigned long rate,
+					unsigned long min_rate,
+					unsigned long max_rate,
 					unsigned long *best_parent_rate,
 					struct clk_hw **best_parent_clk)
 {
@@ -678,6 +682,8 @@ static unsigned long alchemy_clk_fgv2_recalc(struct clk_hw *hw,
 }
 
 static long alchemy_clk_fgv2_detr(struct clk_hw *hw, unsigned long rate,
+					unsigned long min_rate,
+					unsigned long max_rate,
 					unsigned long *best_parent_rate,
 					struct clk_hw **best_parent_clk)
 {
@@ -897,6 +903,8 @@ static int alchemy_clk_csrc_setr(struct clk_hw *hw, unsigned long rate,
 }
 
 static long alchemy_clk_csrc_detr(struct clk_hw *hw, unsigned long rate,
+					unsigned long min_rate,
+					unsigned long max_rate,
 					unsigned long *best_parent_rate,
 					struct clk_hw **best_parent_clk)
 {
diff --git a/drivers/clk/at91/clk-programmable.c b/drivers/clk/at91/clk-programmable.c
index bbdb1b9..86c8a07 100644
--- a/drivers/clk/at91/clk-programmable.c
+++ b/drivers/clk/at91/clk-programmable.c
@@ -56,6 +56,8 @@ static unsigned long clk_programmable_recalc_rate(struct clk_hw *hw,
 
 static long clk_programmable_determine_rate(struct clk_hw *hw,
 					    unsigned long rate,
+					    unsigned long min_rate,
+					    unsigned long max_rate,
 					    unsigned long *best_parent_rate,
 					    struct clk_hw **best_parent_hw)
 {
diff --git a/drivers/clk/bcm/clk-kona.c b/drivers/clk/bcm/clk-kona.c
index 1c06f6f..05abae8 100644
--- a/drivers/clk/bcm/clk-kona.c
+++ b/drivers/clk/bcm/clk-kona.c
@@ -1032,6 +1032,8 @@ static long kona_peri_clk_round_rate(struct clk_hw *hw, unsigned long rate,
 }
 
 static long kona_peri_clk_determine_rate(struct clk_hw *hw, unsigned long rate,
+		unsigned long min_rate,
+		unsigned long max_rate,
 		unsigned long *best_parent_rate, struct clk_hw **best_parent)
 {
 	struct kona_clk *bcm_clk = to_kona_clk(hw);
diff --git a/drivers/clk/clk-composite.c b/drivers/clk/clk-composite.c
index 4386697..dee81b8 100644
--- a/drivers/clk/clk-composite.c
+++ b/drivers/clk/clk-composite.c
@@ -56,6 +56,8 @@ static unsigned long clk_composite_recalc_rate(struct clk_hw *hw,
 }
 
 static long clk_composite_determine_rate(struct clk_hw *hw, unsigned long rate,
+					unsigned long min_rate,
+					unsigned long max_rate,
 					unsigned long *best_parent_rate,
 					struct clk_hw **best_parent_p)
 {
@@ -73,7 +75,9 @@ static long clk_composite_determine_rate(struct clk_hw *hw, unsigned long rate,
 
 	if (rate_hw && rate_ops && rate_ops->determine_rate) {
 		rate_hw->clk = hw->clk;
-		return rate_ops->determine_rate(rate_hw, rate, best_parent_rate,
+		return rate_ops->determine_rate(rate_hw, rate, min_rate,
+						max_rate,
+						best_parent_rate,
 						best_parent_p);
 	} else if (rate_hw && rate_ops && rate_ops->round_rate &&
 		   mux_hw && mux_ops && mux_ops->set_parent) {
@@ -117,7 +121,8 @@ static long clk_composite_determine_rate(struct clk_hw *hw, unsigned long rate,
 		return best_rate;
 	} else if (mux_hw && mux_ops && mux_ops->determine_rate) {
 		mux_hw->clk = hw->clk;
-		return mux_ops->determine_rate(mux_hw, rate, best_parent_rate,
+		return mux_ops->determine_rate(mux_hw, rate, min_rate,
+					       max_rate, best_parent_rate,
 					       best_parent_p);
 	} else {
 		pr_err("clk: clk_composite_determine_rate function called, but no mux or rate callback set!\n");
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 0b7091c..ec51978 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -42,8 +42,6 @@ static unsigned long clk_core_get_rate(struct clk_core *clk);
 static int clk_core_get_phase(struct clk_core *clk);
 static bool clk_core_is_prepared(struct clk_core *clk);
 static bool clk_core_is_enabled(struct clk_core *clk);
-static unsigned long clk_core_round_rate_nolock(struct clk_core *clk,
-						unsigned long rate);
 static struct clk_core *clk_core_lookup(const char *name);
 
 /***           locking             ***/
@@ -746,12 +744,30 @@ struct clk *__clk_lookup(const char *name)
 	return !core ? NULL : core->hw->clk;
 }
 
+static void clk_core_get_boundaries(struct clk_core *clk,
+				    unsigned long *min_rate,
+				    unsigned long *max_rate)
+{
+	struct clk *clk_user;
+
+	*min_rate = 0;
+	*max_rate = ULONG_MAX;
+
+	hlist_for_each_entry(clk_user, &clk->clks, child_node)
+		*min_rate = max(*min_rate, clk_user->min_rate);
+
+	hlist_for_each_entry(clk_user, &clk->clks, child_node)
+		*max_rate = min(*max_rate, clk_user->max_rate);
+}
+
 /*
  * Helper for finding best parent to provide a given frequency. This can be used
  * directly as a determine_rate callback (e.g. for a mux), or from a more
  * complex clock that may combine a mux with other operations.
  */
 long __clk_mux_determine_rate(struct clk_hw *hw, unsigned long rate,
+			      unsigned long min_rate,
+			      unsigned long max_rate,
 			      unsigned long *best_parent_rate,
 			      struct clk_hw **best_parent_p)
 {
@@ -763,7 +779,8 @@ long __clk_mux_determine_rate(struct clk_hw *hw, unsigned long rate,
 	if (core->flags & CLK_SET_RATE_NO_REPARENT) {
 		parent = core->parent;
 		if (core->flags & CLK_SET_RATE_PARENT)
-			best = clk_core_round_rate_nolock(parent, rate);
+			best = __clk_determine_rate(parent->hw, rate,
+						    min_rate, max_rate);
 		else if (parent)
 			best = clk_core_get_rate_nolock(parent);
 		else
@@ -778,7 +795,9 @@ long __clk_mux_determine_rate(struct clk_hw *hw, unsigned long rate,
 		if (!parent)
 			continue;
 		if (core->flags & CLK_SET_RATE_PARENT)
-			parent_rate = clk_core_round_rate_nolock(parent, rate);
+			parent_rate = __clk_determine_rate(parent->hw, rate,
+							   min_rate,
+							   max_rate);
 		else
 			parent_rate = clk_core_get_rate_nolock(parent);
 		if (parent_rate <= rate && parent_rate > best) {
@@ -1006,7 +1025,9 @@ int clk_enable(struct clk *clk)
 EXPORT_SYMBOL_GPL(clk_enable);
 
 static unsigned long clk_core_round_rate_nolock(struct clk_core *clk,
-						unsigned long rate)
+						unsigned long rate,
+						unsigned long min_rate,
+						unsigned long max_rate)
 {
 	unsigned long parent_rate = 0;
 	struct clk_core *parent;
@@ -1021,17 +1042,41 @@ static unsigned long clk_core_round_rate_nolock(struct clk_core *clk,
 
 	if (clk->ops->determine_rate) {
 		parent_hw = parent ? parent->hw : NULL;
-		return clk->ops->determine_rate(clk->hw, rate, &parent_rate,
-						&parent_hw);
+		return clk->ops->determine_rate(clk->hw, rate,
+						min_rate, max_rate,
+						&parent_rate, &parent_hw);
 	} else if (clk->ops->round_rate)
 		return clk->ops->round_rate(clk->hw, rate, &parent_rate);
 	else if (clk->flags & CLK_SET_RATE_PARENT)
-		return clk_core_round_rate_nolock(clk->parent, rate);
+		return clk_core_round_rate_nolock(clk->parent, rate, min_rate,
+						  max_rate);
 	else
 		return clk->rate;
 }
 
 /**
+ * __clk_determine_rate - get the closest rate actually supported by a clock
+ * @hw: determine the rate of this clock
+ * @rate: target rate
+ * @min_rate: returned rate must be greater than this rate
+ * @max_rate: returned rate must be less than this rate
+ *
+ * Caller must hold prepare_lock.  Useful for clk_ops such as .set_rate and
+ * .determine_rate.
+ */
+unsigned long __clk_determine_rate(struct clk_hw *hw,
+				   unsigned long rate,
+				   unsigned long min_rate,
+				   unsigned long max_rate)
+{
+	if (!hw)
+		return 0;
+
+	return clk_core_round_rate_nolock(hw->core, rate, min_rate, max_rate);
+}
+EXPORT_SYMBOL_GPL(__clk_determine_rate);
+
+/**
  * __clk_round_rate - round the given rate for a clk
  * @clk: round the rate of this clock
  * @rate: the rate which is to be rounded
@@ -1040,10 +1085,15 @@ static unsigned long clk_core_round_rate_nolock(struct clk_core *clk,
  */
 unsigned long __clk_round_rate(struct clk *clk, unsigned long rate)
 {
+	unsigned long min_rate;
+	unsigned long max_rate;
+
 	if (!clk)
 		return 0;
 
-	return clk_core_round_rate_nolock(clk->core, rate);
+	clk_core_get_boundaries(clk->core, &min_rate, &max_rate);
+
+	return clk_core_round_rate_nolock(clk->core, rate, min_rate, max_rate);
 }
 EXPORT_SYMBOL_GPL(__clk_round_rate);
 
@@ -1064,7 +1114,7 @@ long clk_round_rate(struct clk *clk, unsigned long rate)
 		return 0;
 
 	clk_prepare_lock();
-	ret = clk_core_round_rate_nolock(clk->core, rate);
+	ret = __clk_round_rate(clk, rate);
 	clk_prepare_unlock();
 
 	return ret;
@@ -1455,6 +1505,8 @@ static struct clk_core *clk_calc_new_rates(struct clk_core *clk,
 	struct clk_hw *parent_hw;
 	unsigned long best_parent_rate = 0;
 	unsigned long new_rate;
+	unsigned long min_rate;
+	unsigned long max_rate;
 	int p_index = 0;
 
 	/* sanity */
@@ -1466,16 +1518,22 @@ static struct clk_core *clk_calc_new_rates(struct clk_core *clk,
 	if (parent)
 		best_parent_rate = parent->rate;
 
+	clk_core_get_boundaries(clk, &min_rate, &max_rate);
+
 	/* find the closest rate and parent clk/rate */
 	if (clk->ops->determine_rate) {
 		parent_hw = parent ? parent->hw : NULL;
 		new_rate = clk->ops->determine_rate(clk->hw, rate,
+						    min_rate,
+						    max_rate,
 						    &best_parent_rate,
 						    &parent_hw);
 		parent = parent_hw ? parent_hw->core : NULL;
 	} else if (clk->ops->round_rate) {
 		new_rate = clk->ops->round_rate(clk->hw, rate,
 						&best_parent_rate);
+		if (new_rate < min_rate || new_rate > max_rate)
+			return NULL;
 	} else if (!parent || !(clk->flags & CLK_SET_RATE_PARENT)) {
 		/* pass-through clock without adjustable parent */
 		clk->new_rate = clk->rate;
@@ -1613,6 +1671,45 @@ static void clk_change_rate(struct clk_core *clk)
 		clk_change_rate(clk->new_child);
 }
 
+static int clk_core_set_rate_nolock(struct clk_core *clk,
+				    unsigned long req_rate)
+{
+	struct clk_core *top, *fail_clk;
+	unsigned long rate = req_rate;
+	int ret = 0;
+
+	if (!clk)
+		return 0;
+
+	/* bail early if nothing to do */
+	if (rate == clk_core_get_rate_nolock(clk))
+		return 0;
+
+	if ((clk->flags & CLK_SET_RATE_GATE) && clk->prepare_count)
+		return -EBUSY;
+
+	/* calculate new rates and get the topmost changed clock */
+	top = clk_calc_new_rates(clk, rate);
+	if (!top)
+		return -EINVAL;
+
+	/* notify that we are about to change rates */
+	fail_clk = clk_propagate_rate_change(top, PRE_RATE_CHANGE);
+	if (fail_clk) {
+		pr_debug("%s: failed to set %s rate\n", __func__,
+				fail_clk->name);
+		clk_propagate_rate_change(top, ABORT_RATE_CHANGE);
+		return -EBUSY;
+	}
+
+	/* change the rates */
+	clk_change_rate(top);
+
+	clk->req_rate = req_rate;
+
+	return ret;
+}
+
 /**
  * clk_set_rate - specify a new rate for clk
  * @clk: the clk whose rate is being changed
@@ -1636,8 +1733,7 @@ static void clk_change_rate(struct clk_core *clk)
  */
 int clk_set_rate(struct clk *clk, unsigned long rate)
 {
-	struct clk_core *top, *fail_clk;
-	int ret = 0;
+	int ret;
 
 	if (!clk)
 		return 0;
@@ -1645,42 +1741,81 @@ int clk_set_rate(struct clk *clk, unsigned long rate)
 	/* prevent racing with updates to the clock topology */
 	clk_prepare_lock();
 
-	/* bail early if nothing to do */
-	if (rate == clk_get_rate(clk))
-		goto out;
+	ret = clk_core_set_rate_nolock(clk->core, rate);
 
-	if ((clk->core->flags & CLK_SET_RATE_GATE) &&
-	    clk->core->prepare_count) {
-		ret = -EBUSY;
-		goto out;
-	}
+	clk_prepare_unlock();
 
-	/* calculate new rates and get the topmost changed clock */
-	top = clk_calc_new_rates(clk->core, rate);
-	if (!top) {
-		ret = -EINVAL;
-		goto out;
-	}
+	return ret;
+}
+EXPORT_SYMBOL_GPL(clk_set_rate);
 
-	/* notify that we are about to change rates */
-	fail_clk = clk_propagate_rate_change(top, PRE_RATE_CHANGE);
-	if (fail_clk) {
-		pr_debug("%s: failed to set %s rate\n", __func__,
-				fail_clk->name);
-		clk_propagate_rate_change(top, ABORT_RATE_CHANGE);
-		ret = -EBUSY;
-		goto out;
+/**
+ * clk_set_rate_range - set a rate range for a clock source
+ * @clk: clock source
+ * @min: desired minimum clock rate in Hz, inclusive
+ * @max: desired maximum clock rate in Hz, inclusive
+ *
+ * Returns success (0) or negative errno.
+ */
+int clk_set_rate_range(struct clk *clk, unsigned long min, unsigned long max)
+{
+	int ret = 0;
+
+	if (!clk)
+		return 0;
+
+	if (min > max) {
+		pr_err("%s: clk %s dev %s con %s: invalid range [%lu, %lu]\n",
+		       __func__, clk->core->name, clk->dev_id, clk->con_id,
+		       min, max);
+		return -EINVAL;
 	}
 
-	/* change the rates */
-	clk_change_rate(top);
+	clk_prepare_lock();
+
+	if (min != clk->min_rate || max != clk->max_rate) {
+		clk->min_rate = min;
+		clk->max_rate = max;
+		ret = clk_core_set_rate_nolock(clk->core, clk->core->req_rate);
+	}
 
-out:
 	clk_prepare_unlock();
 
 	return ret;
 }
-EXPORT_SYMBOL_GPL(clk_set_rate);
+EXPORT_SYMBOL_GPL(clk_set_rate_range);
+
+/**
+ * clk_set_min_rate - set a minimum clock rate for a clock source
+ * @clk: clock source
+ * @rate: desired minimum clock rate in Hz, inclusive
+ *
+ * Returns success (0) or negative errno.
+ */
+int clk_set_min_rate(struct clk *clk, unsigned long rate)
+{
+	if (!clk)
+		return 0;
+
+	return clk_set_rate_range(clk, rate, clk->max_rate);
+}
+EXPORT_SYMBOL_GPL(clk_set_min_rate);
+
+/**
+ * clk_set_max_rate - set a maximum clock rate for a clock source
+ * @clk: clock source
+ * @rate: desired maximum clock rate in Hz, inclusive
+ *
+ * Returns success (0) or negative errno.
+ */
+int clk_set_max_rate(struct clk *clk, unsigned long rate)
+{
+	if (!clk)
+		return 0;
+
+	return clk_set_rate_range(clk, clk->min_rate, rate);
+}
+EXPORT_SYMBOL_GPL(clk_set_max_rate);
 
 /**
  * clk_get_parent - return the parent of a clk
@@ -2127,10 +2262,24 @@ struct clk *__clk_create_clk(struct clk_hw *hw, const char *dev_id,
 	clk->core = hw->core;
 	clk->dev_id = dev_id;
 	clk->con_id = con_id;
+	clk->max_rate = ULONG_MAX;
+
+	clk_prepare_lock();
+	hlist_add_head(&clk->child_node, &hw->core->clks);
+	clk_prepare_unlock();
 
 	return clk;
 }
 
+static void __clk_free_clk(struct clk *clk)
+{
+	clk_prepare_lock();
+	hlist_del(&clk->child_node);
+	clk_prepare_unlock();
+
+	kfree(clk);
+}
+
 /**
  * clk_register - allocate a new clock, register it and return an opaque cookie
  * @dev: device that is registering this clock
@@ -2190,6 +2339,8 @@ struct clk *clk_register(struct device *dev, struct clk_hw *hw)
 		}
 	}
 
+	INIT_HLIST_HEAD(&clk->clks);
+
 	hw->clk = __clk_create_clk(hw, NULL, NULL);
 	if (IS_ERR(hw->clk)) {
 		pr_err("%s: could not allocate per-user clk\n", __func__);
@@ -2201,8 +2352,9 @@ struct clk *clk_register(struct device *dev, struct clk_hw *hw)
 	if (!ret)
 		return hw->clk;
 
-	kfree(hw->clk);
+	__clk_free_clk(hw->clk);
 	hw->clk = NULL;
+
 fail_parent_names_copy:
 	while (--i >= 0)
 		kfree(clk->parent_names[i]);
@@ -2391,25 +2543,24 @@ int __clk_get(struct clk *clk)
 	return 1;
 }
 
-static void clk_core_put(struct clk_core *core)
+void __clk_put(struct clk *clk)
 {
 	struct module *owner;
 
-	owner = core->owner;
+	if (!clk || WARN_ON_ONCE(IS_ERR(clk)))
+		return;
 
 	clk_prepare_lock();
-	kref_put(&core->ref, __clk_release);
+
+	hlist_del(&clk->child_node);
+	clk_core_set_rate_nolock(clk->core, clk->core->req_rate);
+	owner = clk->core->owner;
+	kref_put(&clk->core->ref, __clk_release);
+
 	clk_prepare_unlock();
 
 	module_put(owner);
-}
-
-void __clk_put(struct clk *clk)
-{
-	if (!clk || WARN_ON_ONCE(IS_ERR(clk)))
-		return;
 
-	clk_core_put(clk->core);
 	kfree(clk);
 }
 
diff --git a/drivers/clk/hisilicon/clk-hi3620.c b/drivers/clk/hisilicon/clk-hi3620.c
index 007144f..2e4f6d4 100644
--- a/drivers/clk/hisilicon/clk-hi3620.c
+++ b/drivers/clk/hisilicon/clk-hi3620.c
@@ -295,6 +295,8 @@ static unsigned long mmc_clk_recalc_rate(struct clk_hw *hw,
 }
 
 static long mmc_clk_determine_rate(struct clk_hw *hw, unsigned long rate,
+			      unsigned long min_rate,
+			      unsigned long max_rate,
 			      unsigned long *best_parent_rate,
 			      struct clk_hw **best_parent_p)
 {
diff --git a/drivers/clk/mmp/clk-mix.c b/drivers/clk/mmp/clk-mix.c
index 48fa53c..de6a873 100644
--- a/drivers/clk/mmp/clk-mix.c
+++ b/drivers/clk/mmp/clk-mix.c
@@ -202,6 +202,8 @@ error:
 }
 
 static long mmp_clk_mix_determine_rate(struct clk_hw *hw, unsigned long rate,
+					unsigned long min_rate,
+					unsigned long max_rate,
 					unsigned long *best_parent_rate,
 					struct clk_hw **best_parent_clk)
 {
diff --git a/drivers/clk/qcom/clk-pll.c b/drivers/clk/qcom/clk-pll.c
index 60873a7..b4325f6 100644
--- a/drivers/clk/qcom/clk-pll.c
+++ b/drivers/clk/qcom/clk-pll.c
@@ -141,6 +141,7 @@ struct pll_freq_tbl *find_freq(const struct pll_freq_tbl *f, unsigned long rate)
 
 static long
 clk_pll_determine_rate(struct clk_hw *hw, unsigned long rate,
+		       unsigned long min_rate, unsigned long max_rate,
 		       unsigned long *p_rate, struct clk_hw **p)
 {
 	struct clk_pll *pll = to_clk_pll(hw);
diff --git a/drivers/clk/qcom/clk-rcg.c b/drivers/clk/qcom/clk-rcg.c
index 0b93972..0039bd7 100644
--- a/drivers/clk/qcom/clk-rcg.c
+++ b/drivers/clk/qcom/clk-rcg.c
@@ -368,6 +368,7 @@ clk_dyn_rcg_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
 
 static long _freq_tbl_determine_rate(struct clk_hw *hw,
 		const struct freq_tbl *f, unsigned long rate,
+		unsigned long min_rate, unsigned long max_rate,
 		unsigned long *p_rate, struct clk_hw **p_hw)
 {
 	unsigned long clk_flags;
@@ -397,22 +398,27 @@ static long _freq_tbl_determine_rate(struct clk_hw *hw,
 }
 
 static long clk_rcg_determine_rate(struct clk_hw *hw, unsigned long rate,
+		unsigned long min_rate, unsigned long max_rate,
 		unsigned long *p_rate, struct clk_hw **p)
 {
 	struct clk_rcg *rcg = to_clk_rcg(hw);
 
-	return _freq_tbl_determine_rate(hw, rcg->freq_tbl, rate, p_rate, p);
+	return _freq_tbl_determine_rate(hw, rcg->freq_tbl, rate, min_rate,
+			max_rate, p_rate, p);
 }
 
 static long clk_dyn_rcg_determine_rate(struct clk_hw *hw, unsigned long rate,
+		unsigned long min_rate, unsigned long max_rate,
 		unsigned long *p_rate, struct clk_hw **p)
 {
 	struct clk_dyn_rcg *rcg = to_clk_dyn_rcg(hw);
 
-	return _freq_tbl_determine_rate(hw, rcg->freq_tbl, rate, p_rate, p);
+	return _freq_tbl_determine_rate(hw, rcg->freq_tbl, rate, min_rate,
+			max_rate, p_rate, p);
 }
 
 static long clk_rcg_bypass_determine_rate(struct clk_hw *hw, unsigned long rate,
+		unsigned long min_rate, unsigned long max_rate,
 		unsigned long *p_rate, struct clk_hw **p_hw)
 {
 	struct clk_rcg *rcg = to_clk_rcg(hw);
diff --git a/drivers/clk/qcom/clk-rcg2.c b/drivers/clk/qcom/clk-rcg2.c
index 08b8b37..742acfa 100644
--- a/drivers/clk/qcom/clk-rcg2.c
+++ b/drivers/clk/qcom/clk-rcg2.c
@@ -208,6 +208,7 @@ static long _freq_tbl_determine_rate(struct clk_hw *hw,
 }
 
 static long clk_rcg2_determine_rate(struct clk_hw *hw, unsigned long rate,
+		unsigned long min_rate, unsigned long max_rate,
 		unsigned long *p_rate, struct clk_hw **p)
 {
 	struct clk_rcg2 *rcg = to_clk_rcg2(hw);
@@ -361,6 +362,8 @@ static int clk_edp_pixel_set_rate_and_parent(struct clk_hw *hw,
 }
 
 static long clk_edp_pixel_determine_rate(struct clk_hw *hw, unsigned long rate,
+				 unsigned long min_rate,
+				 unsigned long max_rate,
 				 unsigned long *p_rate, struct clk_hw **p)
 {
 	struct clk_rcg2 *rcg = to_clk_rcg2(hw);
@@ -412,6 +415,7 @@ const struct clk_ops clk_edp_pixel_ops = {
 EXPORT_SYMBOL_GPL(clk_edp_pixel_ops);
 
 static long clk_byte_determine_rate(struct clk_hw *hw, unsigned long rate,
+			 unsigned long min_rate, unsigned long max_rate,
 			 unsigned long *p_rate, struct clk_hw **p_hw)
 {
 	struct clk_rcg2 *rcg = to_clk_rcg2(hw);
@@ -476,6 +480,8 @@ static const struct frac_entry frac_table_pixel[] = {
 };
 
 static long clk_pixel_determine_rate(struct clk_hw *hw, unsigned long rate,
+				 unsigned long min_rate,
+				 unsigned long max_rate,
 				 unsigned long *p_rate, struct clk_hw **p)
 {
 	struct clk_rcg2 *rcg = to_clk_rcg2(hw);
diff --git a/drivers/clk/sunxi/clk-factors.c b/drivers/clk/sunxi/clk-factors.c
index 62e08fb..761029b 100644
--- a/drivers/clk/sunxi/clk-factors.c
+++ b/drivers/clk/sunxi/clk-factors.c
@@ -80,6 +80,8 @@ static long clk_factors_round_rate(struct clk_hw *hw, unsigned long rate,
 }
 
 static long clk_factors_determine_rate(struct clk_hw *hw, unsigned long rate,
+				       unsigned long min_rate,
+				       unsigned long max_rate,
 				       unsigned long *best_parent_rate,
 				       struct clk_hw **best_parent_p)
 {
diff --git a/drivers/clk/sunxi/clk-sun6i-ar100.c b/drivers/clk/sunxi/clk-sun6i-ar100.c
index 3d282fb..63cf149 100644
--- a/drivers/clk/sunxi/clk-sun6i-ar100.c
+++ b/drivers/clk/sunxi/clk-sun6i-ar100.c
@@ -45,6 +45,8 @@ static unsigned long ar100_recalc_rate(struct clk_hw *hw,
 }
 
 static long ar100_determine_rate(struct clk_hw *hw, unsigned long rate,
+				 unsigned long min_rate,
+				 unsigned long max_rate,
 				 unsigned long *best_parent_rate,
 				 struct clk_hw **best_parent_clk)
 {
diff --git a/include/linux/clk-private.h b/include/linux/clk-private.h
index ae55d99..5136b30 100644
--- a/include/linux/clk-private.h
+++ b/include/linux/clk-private.h
@@ -39,6 +39,7 @@ struct clk_core {
 	u8			num_parents;
 	u8			new_parent_index;
 	unsigned long		rate;
+	unsigned long		req_rate;
 	unsigned long		new_rate;
 	struct clk_core		*new_parent;
 	struct clk_core		*new_child;
@@ -50,6 +51,7 @@ struct clk_core {
 	struct hlist_head	children;
 	struct hlist_node	child_node;
 	struct hlist_node	debug_node;
+	struct hlist_head	clks;
 	unsigned int		notifier_count;
 #ifdef CONFIG_DEBUG_FS
 	struct dentry		*dentry;
@@ -61,6 +63,10 @@ struct clk {
 	struct clk_core	*core;
 	const char *dev_id;
 	const char *con_id;
+
+	unsigned long min_rate;
+	unsigned long max_rate;
+	struct hlist_node child_node;
 };
 
 /*
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 9afd438..2416026 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -175,9 +175,12 @@ struct clk_ops {
 					unsigned long parent_rate);
 	long		(*round_rate)(struct clk_hw *hw, unsigned long rate,
 					unsigned long *parent_rate);
-	long		(*determine_rate)(struct clk_hw *hw, unsigned long rate,
-					unsigned long *best_parent_rate,
-					struct clk_hw **best_parent_hw);
+	long		(*determine_rate)(struct clk_hw *hw,
+					  unsigned long rate,
+					  unsigned long min_rate,
+					  unsigned long max_rate,
+					  unsigned long *best_parent_rate,
+					  struct clk_hw **best_parent_hw);
 	int		(*set_parent)(struct clk_hw *hw, u8 index);
 	u8		(*get_parent)(struct clk_hw *hw);
 	int		(*set_rate)(struct clk_hw *hw, unsigned long rate,
@@ -555,8 +558,14 @@ bool __clk_is_prepared(struct clk *clk);
 bool __clk_is_enabled(struct clk *clk);
 struct clk *__clk_lookup(const char *name);
 long __clk_mux_determine_rate(struct clk_hw *hw, unsigned long rate,
+			      unsigned long min_rate,
+			      unsigned long max_rate,
 			      unsigned long *best_parent_rate,
 			      struct clk_hw **best_parent_p);
+unsigned long __clk_determine_rate(struct clk_hw *core,
+				   unsigned long rate,
+				   unsigned long min_rate,
+				   unsigned long max_rate);
 
 /*
  * FIXME clock api without lock protection
diff --git a/include/linux/clk.h b/include/linux/clk.h
index c7f258a..a891e21 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -302,6 +302,34 @@ long clk_round_rate(struct clk *clk, unsigned long rate);
 int clk_set_rate(struct clk *clk, unsigned long rate);
 
 /**
+ * clk_set_rate_range - set a rate range for a clock source
+ * @clk: clock source
+ * @min: desired minimum clock rate in Hz, inclusive
+ * @max: desired maximum clock rate in Hz, inclusive
+ *
+ * Returns success (0) or negative errno.
+ */
+int clk_set_rate_range(struct clk *clk, unsigned long min, unsigned long max);
+
+/**
+ * clk_set_min_rate - set a minimum clock rate for a clock source
+ * @clk: clock source
+ * @rate: desired minimum clock rate in Hz, inclusive
+ *
+ * Returns success (0) or negative errno.
+ */
+int clk_set_min_rate(struct clk *clk, unsigned long rate);
+
+/**
+ * clk_set_max_rate - set a maximum clock rate for a clock source
+ * @clk: clock source
+ * @rate: desired maximum clock rate in Hz, inclusive
+ *
+ * Returns success (0) or negative errno.
+ */
+int clk_set_max_rate(struct clk *clk, unsigned long rate);
+
+/**
  * clk_set_parent - set the parent clock source for this clock
  * @clk: clock source
  * @parent: parent clock source
diff --git a/include/linux/clk/ti.h b/include/linux/clk/ti.h
index 55ef529..cfb9e55 100644
--- a/include/linux/clk/ti.h
+++ b/include/linux/clk/ti.h
@@ -263,6 +263,8 @@ int omap3_noncore_dpll_set_rate_and_parent(struct clk_hw *hw,
 					   u8 index);
 long omap3_noncore_dpll_determine_rate(struct clk_hw *hw,
 				       unsigned long rate,
+				       unsigned long min_rate,
+				       unsigned long max_rate,
 				       unsigned long *best_parent_rate,
 				       struct clk_hw **best_parent_clk);
 unsigned long omap4_dpll_regm4xen_recalc(struct clk_hw *hw,
@@ -272,6 +274,8 @@ long omap4_dpll_regm4xen_round_rate(struct clk_hw *hw,
 				    unsigned long *parent_rate);
 long omap4_dpll_regm4xen_determine_rate(struct clk_hw *hw,
 					unsigned long rate,
+					unsigned long min_rate,
+					unsigned long max_rate,
 					unsigned long *best_parent_rate,
 					struct clk_hw **best_parent_clk);
 u8 omap2_init_dpll_parent(struct clk_hw *hw);
-- 
1.9.3

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

* [PATCH v13 5/6] clkdev: Export clk_register_clkdev
  2015-01-23 11:03 [PATCH v13 0/6] Per-user clock constraints Tomeu Vizoso
@ 2015-01-23 11:03   ` Tomeu Vizoso
  2015-01-23 11:03 ` [PATCH v13 2/6] clk: Remove __clk_register Tomeu Vizoso
                     ` (5 subsequent siblings)
  6 siblings, 0 replies; 186+ messages in thread
From: Tomeu Vizoso @ 2015-01-23 11:03 UTC (permalink / raw)
  To: linux-kernel, Mike Turquette, Stephen Boyd
  Cc: Javier Martinez Canillas, Tomeu Vizoso, Russell King, linux-arm-kernel

So it can be used from modules such as clk-test.ko.

Signed-off-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
Reviewed-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/clkdev.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c
index 901d242..29a1ab7 100644
--- a/drivers/clk/clkdev.c
+++ b/drivers/clk/clkdev.c
@@ -377,6 +377,7 @@ int clk_register_clkdev(struct clk *clk, const char *con_id,
 
 	return 0;
 }
+EXPORT_SYMBOL(clk_register_clkdev);
 
 /**
  * clk_register_clkdevs - register a set of clk_lookup for a struct clk
-- 
1.9.3


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

* [PATCH v13 5/6] clkdev: Export clk_register_clkdev
@ 2015-01-23 11:03   ` Tomeu Vizoso
  0 siblings, 0 replies; 186+ messages in thread
From: Tomeu Vizoso @ 2015-01-23 11:03 UTC (permalink / raw)
  To: linux-arm-kernel

So it can be used from modules such as clk-test.ko.

Signed-off-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
Reviewed-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/clkdev.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c
index 901d242..29a1ab7 100644
--- a/drivers/clk/clkdev.c
+++ b/drivers/clk/clkdev.c
@@ -377,6 +377,7 @@ int clk_register_clkdev(struct clk *clk, const char *con_id,
 
 	return 0;
 }
+EXPORT_SYMBOL(clk_register_clkdev);
 
 /**
  * clk_register_clkdevs - register a set of clk_lookup for a struct clk
-- 
1.9.3

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

* [PATCH v13 6/6] clk: Add module for unit tests
  2015-01-23 11:03 [PATCH v13 0/6] Per-user clock constraints Tomeu Vizoso
                   ` (4 preceding siblings ...)
  2015-01-23 11:03   ` Tomeu Vizoso
@ 2015-01-23 11:03 ` Tomeu Vizoso
  2015-01-27  0:55 ` [PATCH v13 0/6] Per-user clock constraints Stephen Boyd
  6 siblings, 0 replies; 186+ messages in thread
From: Tomeu Vizoso @ 2015-01-23 11:03 UTC (permalink / raw)
  To: linux-kernel, Mike Turquette, Stephen Boyd
  Cc: Javier Martinez Canillas, Tomeu Vizoso

This module registers a clock hierarchy and performs several operations
against them checking that the result is expected.

Signed-off-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
---
 drivers/clk/Kconfig       |   1 +
 drivers/clk/Kconfig.debug |   6 +
 drivers/clk/Makefile      |   1 +
 drivers/clk/clk-test.c    | 326 ++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 334 insertions(+)
 create mode 100644 drivers/clk/Kconfig.debug
 create mode 100644 drivers/clk/clk-test.c

diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 3f44f29..03c500f 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -135,6 +135,7 @@ config COMMON_CLK_PXA
 	  Sypport for the Marvell PXA SoC.
 
 source "drivers/clk/qcom/Kconfig"
+source "drivers/clk/Kconfig.debug"
 
 endmenu
 
diff --git a/drivers/clk/Kconfig.debug b/drivers/clk/Kconfig.debug
new file mode 100644
index 0000000..840b790
--- /dev/null
+++ b/drivers/clk/Kconfig.debug
@@ -0,0 +1,6 @@
+config COMMON_CLK_TEST
+	tristate "Unit tests for the Common Clock Framework"
+	default n
+	---help---
+	  This driver runs several tests on the Common Clock Framework.
+
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index d5fba5b..4ee1475 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -68,3 +68,4 @@ obj-$(CONFIG_ARCH_U8500)		+= ux500/
 obj-$(CONFIG_COMMON_CLK_VERSATILE)	+= versatile/
 obj-$(CONFIG_X86)			+= x86/
 obj-$(CONFIG_ARCH_ZYNQ)			+= zynq/
+obj-$(CONFIG_COMMON_CLK_TEST)		+= clk-test.o
diff --git a/drivers/clk/clk-test.c b/drivers/clk/clk-test.c
new file mode 100644
index 0000000..e1032f2a
--- /dev/null
+++ b/drivers/clk/clk-test.c
@@ -0,0 +1,326 @@
+/*
+ * Copyright (C) 2015 Google, Inc
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Unit tests for the Common Clock Framework
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/printk.h>
+#include <linux/slab.h>
+
+/* Assumed to be sorted */
+static const unsigned long allowed_rates[] = { 0, 100, 200, 300, 400, 500 };
+
+struct test_clk {
+	struct clk_hw hw;
+	unsigned long rate;
+};
+
+static inline struct test_clk *to_test_clk(struct clk_hw *hw)
+{
+	return container_of(hw, struct test_clk, hw);
+}
+
+static long test_clk_determine_rate(struct clk_hw *hw,
+				    unsigned long rate,
+				    unsigned long min_rate,
+				    unsigned long max_rate,
+				    unsigned long *best_parent_rate,
+				    struct clk_hw **best_parent)
+{
+	struct clk *parent;
+	unsigned long target_rate = 0;
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(allowed_rates); i++) {
+
+		if (allowed_rates[i] > max_rate) {
+			if (i > 0)
+				target_rate = allowed_rates[i - 1];
+			else
+				target_rate = 0;
+			break;
+		}
+
+		if (allowed_rates[i] < min_rate)
+			continue;
+
+		if (allowed_rates[i] >= rate) {
+			target_rate = allowed_rates[i];
+			break;
+		}
+	}
+
+	parent = clk_get_parent(hw->clk);
+	if (parent) {
+		*best_parent = __clk_get_hw(parent);
+		*best_parent_rate = __clk_determine_rate(__clk_get_hw(parent),
+							 target_rate / 2,
+							 min_rate,
+							 max_rate);
+	}
+
+	return target_rate;
+}
+
+static unsigned long test_clk_recalc_rate(struct clk_hw *hw,
+					  unsigned long parent_rate)
+{
+	struct test_clk *test_clk = to_test_clk(hw);
+
+	return test_clk->rate;
+}
+
+static int test_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+			     unsigned long parent_rate)
+{
+	struct test_clk *test_clk = to_test_clk(hw);
+
+	test_clk->rate = rate;
+
+	return 0;
+}
+
+static const struct clk_ops test_clk_ops = {
+	.determine_rate = test_clk_determine_rate,
+	.recalc_rate = test_clk_recalc_rate,
+	.set_rate = test_clk_set_rate,
+};
+
+static struct clk *init_test_clk(const char *name, const char *parent_name)
+{
+	struct test_clk *test_clk;
+	struct clk *clk;
+	struct clk_init_data init;
+	int err;
+
+	test_clk = kzalloc(sizeof(*test_clk), GFP_KERNEL);
+	if (!test_clk)
+		return ERR_PTR(-ENOMEM);
+
+	test_clk->rate = 0;
+
+	init.name = name;
+	init.ops = &test_clk_ops;
+
+	if (parent_name) {
+		init.parent_names = &parent_name;
+		init.num_parents = 1;
+		init.flags = CLK_SET_RATE_PARENT;
+	} else {
+		init.parent_names = NULL;
+		init.num_parents = 0;
+		init.flags = CLK_IS_ROOT;
+	}
+
+	test_clk->hw.init = &init;
+
+	clk = clk_register(NULL, &test_clk->hw);
+	if (IS_ERR(clk)) {
+		printk("%s: error registering clk: %ld\n", __func__,
+		       PTR_ERR(clk));
+		return clk;
+	}
+
+	err = clk_register_clkdev(clk, name, NULL);
+	if (err)
+		printk("%s: error registering alias: %d\n", __func__, err);
+
+	return clk;
+}
+
+static void test_ceiling(struct clk *clk)
+{
+	unsigned long rate;
+	int ret;
+
+	ret = clk_set_max_rate(clk, 399);
+	if (ret)
+		printk("%s: error setting ceiling: %d\n", __func__, ret);
+
+	rate = clk_round_rate(clk, 400);
+	if (rate != 300)
+		printk("%s: unexpected rounded rate: %lu != 300\n", __func__, rate);
+
+	ret = clk_set_rate(clk, 400);
+	if (ret)
+		printk("%s: error setting rate: %d\n", __func__, ret);
+
+	rate = clk_get_rate(clk);
+	if (rate != 300)
+		printk("%s: unexpected rate: %lu != 300\n", __func__, rate);
+
+	ret = clk_set_max_rate(clk, ULONG_MAX);
+	if (ret)
+		printk("%s: error setting ceiling: %d\n", __func__, ret);
+}
+
+static void test_floor(struct clk *clk)
+{
+	unsigned long rate;
+	int ret;
+
+	ret = clk_set_min_rate(clk, 199);
+	if (ret)
+		printk("%s: error setting floor: %d\n", __func__, ret);
+
+	rate = clk_round_rate(clk, 90);
+	if (rate != 200)
+		printk("%s: unexpected rounded rate: %lu != 200\n", __func__, rate);
+
+	ret = clk_set_rate(clk, 90);
+	if (ret)
+		printk("%s: error setting rate: %d\n", __func__, ret);
+
+	rate = clk_get_rate(clk);
+	if (rate != 200)
+		printk("%s: unexpected rate: %lu != 200\n", __func__, rate);
+
+	ret = clk_set_min_rate(clk, 0);
+	if (ret)
+		printk("%s: error setting floor: %d\n", __func__, ret);
+}
+
+static void test_unsatisfiable(struct clk *clk)
+{
+	struct clk *clk2 = clk_get_sys(NULL, "clk");
+	unsigned long rate;
+	int ret;
+
+	if (IS_ERR(clk2))
+		printk("%s: error getting clk: %ld\n", __func__,
+		       PTR_ERR(clk2));
+
+	ret = clk_set_min_rate(clk, 99);
+	if (ret)
+		printk("%s: error setting floor: %d\n", __func__, ret);
+
+	ret = clk_set_max_rate(clk, 199);
+	if (ret)
+		printk("%s: error setting ceiling: %d\n", __func__, ret);
+
+	ret = clk_set_min_rate(clk2, 399);
+	if (ret)
+		printk("%s: error setting floor: %d\n", __func__, ret);
+
+	ret = clk_set_max_rate(clk2, 499);
+	if (ret)
+		printk("%s: error setting ceiling: %d\n", __func__, ret);
+
+	ret = clk_set_rate(clk, 90);
+	if (ret)
+		printk("%s: error setting rate: %d\n", __func__, ret);
+
+	/*
+	 * It's expected that the rate is the highest rate that is still
+	 * below the smallest ceiling
+	 */
+	rate = clk_get_rate(clk);
+	if (rate != 100)
+		printk("%s: unexpected rate: %lu != 100\n", __func__, rate);
+
+	clk_put(clk2);
+
+	ret = clk_set_min_rate(clk, 0);
+	if (ret)
+		printk("%s: error setting floor: %d\n", __func__, ret);
+
+	ret = clk_set_max_rate(clk, ULONG_MAX);
+	if (ret)
+		printk("%s: error setting ceiling: %d\n", __func__, ret);
+}
+
+static void test_constrained_parent(struct clk *clk, struct clk *parent)
+{
+	unsigned long rate;
+	int ret;
+
+	ret = clk_set_max_rate(parent, 199);
+	if (ret)
+		printk("%s: error setting ceiling: %d\n", __func__, ret);
+
+	ret = clk_set_rate(clk, 200);
+	if (ret)
+		printk("%s: error setting rate: %d\n", __func__, ret);
+
+	rate = clk_get_rate(clk);
+	if (rate != 200)
+		printk("%s: unexpected rate: %lu != 200\n", __func__, rate);
+
+	rate = clk_get_rate(parent);
+	if (rate != 100)
+		printk("%s: unexpected parent rate: %lu != 100\n", __func__, rate);
+
+	ret = clk_set_max_rate(parent, ULONG_MAX);
+	if (ret)
+		printk("%s: error setting ceiling: %d\n", __func__, ret);
+}
+
+static void test_constraint_with_parent(struct clk *clk, struct clk *parent)
+{
+	unsigned long rate;
+	int ret;
+
+	ret = clk_set_min_rate(clk, 201);
+	if (ret)
+		printk("%s: error setting ceiling: %d\n", __func__, ret);
+
+	ret = clk_set_rate(clk, 300);
+	if (ret)
+		printk("%s: error setting rate: %d\n", __func__, ret);
+
+	rate = clk_get_rate(clk);
+	if (rate != 300)
+		printk("%s: unexpected rate: %lu != 300\n", __func__, rate);
+
+	rate = clk_get_rate(parent);
+	if (rate != 300)
+		printk("%s: unexpected parent rate: %lu != 300\n", __func__, rate);
+
+	ret = clk_set_max_rate(parent, ULONG_MAX);
+	if (ret)
+		printk("%s: error setting ceiling: %d\n", __func__, ret);
+}
+
+static int __init clk_test_init(void)
+{
+	struct clk *parent, *clk;
+
+	printk("---------- Common Clock Framework test results ----------\n");
+
+	parent = init_test_clk("parent", NULL);
+	if (IS_ERR(parent)) {
+		printk("%s: error registering parent: %ld\n", __func__,
+		       PTR_ERR(parent));
+		return PTR_ERR(parent);
+	}
+
+	clk = init_test_clk("clk", "parent");
+	if (IS_ERR(clk)) {
+		printk("%s: error registering clk: %ld\n", __func__,
+		       PTR_ERR(clk));
+		return PTR_ERR(clk);
+	}
+
+	test_ceiling(clk);
+	test_floor(clk);
+	test_unsatisfiable(clk);
+	test_constrained_parent(clk, parent);
+	test_constraint_with_parent(clk, parent);
+
+	printk("---------------------------------------------------------\n");
+
+	return 0;
+}
+
+module_init(clk_test_init);
+
+MODULE_LICENSE("GPL");
-- 
1.9.3


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

* Re: [PATCH v13 0/6] Per-user clock constraints
  2015-01-23 11:03 [PATCH v13 0/6] Per-user clock constraints Tomeu Vizoso
                   ` (5 preceding siblings ...)
  2015-01-23 11:03 ` [PATCH v13 6/6] clk: Add module for unit tests Tomeu Vizoso
@ 2015-01-27  0:55 ` Stephen Boyd
  2015-01-27  6:29   ` Tomeu Vizoso
  2015-01-28  6:59   ` Tomeu Vizoso
  6 siblings, 2 replies; 186+ messages in thread
From: Stephen Boyd @ 2015-01-27  0:55 UTC (permalink / raw)
  To: Tomeu Vizoso, linux-kernel, Mike Turquette; +Cc: Javier Martinez Canillas

On 01/23/15 03:03, Tomeu Vizoso wrote:
> Hi,
>
> in this v13 I have:
>
> * added the latest R-b tags from Stephen,
>
> * split some lines that went over the 80-char limit,
>
> * made explicit in the docs that the range limits are inclusive, and
>
> * removed an ifdef in clkdev.c by adding a dev_id param to __of_clk_get_by_name.
>

I think this patch series is ready to go except for the last one? Do you
plan on polishing that one some more?

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


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

* Re: [PATCH v13 0/6] Per-user clock constraints
  2015-01-27  0:55 ` [PATCH v13 0/6] Per-user clock constraints Stephen Boyd
@ 2015-01-27  6:29   ` Tomeu Vizoso
  2015-01-28  6:59   ` Tomeu Vizoso
  1 sibling, 0 replies; 186+ messages in thread
From: Tomeu Vizoso @ 2015-01-27  6:29 UTC (permalink / raw)
  To: Stephen Boyd, linux-kernel, Mike Turquette; +Cc: Javier Martinez Canillas

On 01/27/2015 01:55 AM, Stephen Boyd wrote:
> On 01/23/15 03:03, Tomeu Vizoso wrote:
>> Hi,
>>
>> in this v13 I have:
>>
>> * added the latest R-b tags from Stephen,
>>
>> * split some lines that went over the 80-char limit,
>>
>> * made explicit in the docs that the range limits are inclusive, and
>>
>> * removed an ifdef in clkdev.c by adding a dev_id param to __of_clk_get_by_name.
>>
> 
> I think this patch series is ready to go except for the last one? Do you
> plan on polishing that one some more?

Not in time for 3.20, I'm afraid. Want to spin first each of my other
series, then I will go back to it.

Regards,

Tomeu


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

* Re: [PATCH v13 0/6] Per-user clock constraints
  2015-01-27  0:55 ` [PATCH v13 0/6] Per-user clock constraints Stephen Boyd
  2015-01-27  6:29   ` Tomeu Vizoso
@ 2015-01-28  6:59   ` Tomeu Vizoso
       [not found]     ` <20150129022633.22722.78592@quantum>
  1 sibling, 1 reply; 186+ messages in thread
From: Tomeu Vizoso @ 2015-01-28  6:59 UTC (permalink / raw)
  To: Mike Turquette; +Cc: Stephen Boyd, linux-kernel, Javier Martinez Canillas

On 01/27/2015 01:55 AM, Stephen Boyd wrote:
> On 01/23/15 03:03, Tomeu Vizoso wrote:
>> Hi,
>>
>> in this v13 I have:
>>
>> * added the latest R-b tags from Stephen,
>>
>> * split some lines that went over the 80-char limit,
>>
>> * made explicit in the docs that the range limits are inclusive, and
>>
>> * removed an ifdef in clkdev.c by adding a dev_id param to __of_clk_get_by_name.
>>
> 
> I think this patch series is ready to go except for the last one? Do you
> plan on polishing that one some more?

Hi Mike,

do you plan to merge this for 3.20?

Thanks,

Tomeu


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

* Re: [PATCH v13 0/6] Per-user clock constraints
       [not found]     ` <20150129022633.22722.78592@quantum>
@ 2015-01-29  6:41       ` Tomeu Vizoso
  2015-01-29 14:29         ` Mike Turquette
  0 siblings, 1 reply; 186+ messages in thread
From: Tomeu Vizoso @ 2015-01-29  6:41 UTC (permalink / raw)
  To: Mike Turquette; +Cc: Stephen Boyd, linux-kernel, Javier Martinez Canillas

On 01/29/2015 03:26 AM, Mike Turquette wrote:
> Quoting Tomeu Vizoso (2015-01-27 22:59:59)
>> On 01/27/2015 01:55 AM, Stephen Boyd wrote:
>>> On 01/23/15 03:03, Tomeu Vizoso wrote:
>>>> Hi,
>>>>
>>>> in this v13 I have:
>>>>
>>>> * added the latest R-b tags from Stephen,
>>>>
>>>> * split some lines that went over the 80-char limit,
>>>>
>>>> * made explicit in the docs that the range limits are inclusive, and
>>>>
>>>> * removed an ifdef in clkdev.c by adding a dev_id param to __of_clk_get_by_name.
>>>>
>>>
>>> I think this patch series is ready to go except for the last one? Do you
>>> plan on polishing that one some more?
>>
>> Hi Mike,
>>
>> do you plan to merge this for 3.20?
> 
> Tomeu,
> 
> Yes. I have taken patches 1-5.
> 
> I edited patch #3 to adapt clk_has_parent for struct clk_core.
> 
> https://git.kernel.org/cgit/linux/kernel/git/clk/linux.git/commit/?h=clk-next&id=59cf3fcf9bafe8fdb6183f13dafb81fc8213a8f9
> 
> Patch #4 need an update to convert sun6i_ahb1_clk_determine_rate to have
> min/max rates.
> 
> https://git.kernel.org/cgit/linux/kernel/git/clk/linux.git/commit/?h=clk-next&id=cb75a8fcd14e71c115decc416dd8d223e7c8b2e0
> 
> Can you look it over and make sure I didn't screw anything up?

Yup, they look good to me. I have also done some testing here.

Thanks,

Tomeu


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

* Re: [PATCH v13 4/6] clk: Add rate constraints to clocks
  2015-01-23 11:03   ` Tomeu Vizoso
  (?)
  (?)
@ 2015-01-29 13:31     ` Geert Uytterhoeven
  -1 siblings, 0 replies; 186+ messages in thread
From: Geert Uytterhoeven @ 2015-01-29 13:31 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Tomeu, Mike,

On Fri, Jan 23, 2015 at 12:03 PM, Tomeu Vizoso
<tomeu.vizoso@collabora.com> wrote:
> Adds a way for clock consumers to set maximum and minimum rates. This
> can be used for thermal drivers to set minimum rates, or by misc.
> drivers to set maximum rates to assure a minimum performance level.
>
> Changes the signature of the determine_rate callback by adding the
> parameters min_rate and max_rate.
>
> Signed-off-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
> Reviewed-by: Stephen Boyd <sboyd@codeaurora.org>

This is now in clk-next, and causes division by zeroes on all shmobile
platforms that use renesas,cpg-div6-clock (verified on r8a73a4, r8a7740,
r8a7791, sh73a0):

Division by zero in kernel.
CPU: 0 PID: 0 Comm: swapper/0 Not tainted
3.19.0-rc6-koelsch-04360-g48d797d57c5932c8-dirty #792
Hardware name: Generic R8A7791 (Flattened Device Tree)
Backtrace:
[<c001216c>] (dump_backtrace) from [<c001238c>] (show_stack+0x18/0x1c)
 r6:c051b124 r5:00000000 r4:00000000 r3:00200000
[<c0012374>] (show_stack) from [<c03955d0>] (dump_stack+0x78/0x94)
[<c0395558>] (dump_stack) from [<c00122f4>] (__div0+0x18/0x20)
 r4:2e7ddb00 r3:c05093c8
[<c00122dc>] (__div0) from [<c01bdc9c>] (Ldiv0+0x8/0x10)
[<c02d8efc>] (cpg_div6_clock_round_rate) from [<c02d56a0>]
(clk_calc_new_rates+0xc8/0x1d4)
 r4:eec14e00 r3:c03cb52c
[<c02d55d8>] (clk_calc_new_rates) from [<c02d57f4>]
(clk_core_set_rate_nolock+0x48/0x90)
 r9:eec02f40 r8:00000001 r7:c051b0b8 r6:c051b124 r5:00000000 r4:eec14e00
[<c02d57ac>] (clk_core_set_rate_nolock) from [<c02d6848>] (__clk_put+0x78/0xdc)
 r7:c051b0b8 r6:c051b124 r5:eec08100 r4:eec029c0
[<c02d67d0>] (__clk_put) from [<c02d3238>] (clk_put+0x10/0x14)
 r5:eec08100 r4:00000000
[<c02d3228>] (clk_put) from [<c04db4d0>] (of_clk_init+0x144/0x178)
[<c04db38c>] (of_clk_init) from [<c04dbd34>] (rcar_gen2_clocks_init+0x1c/0x24)
 r10:c04ed098 r9:c05023c0 r8:ffffffff r7:19432124 r6:c0502404 r5:00989680
 r4:f0006000
[<c04dbd18>] (rcar_gen2_clocks_init) from [<c04c6a3c>]
(rcar_gen2_timer_init+0x130/0x14c)
[<c04c690c>] (rcar_gen2_timer_init) from [<c04c15b4>] (time_init+0x24/0x38)
 r7:00000000 r6:c0520c80 r5:00000000 r4:ef7fcbc0
[<c04c1590>] (time_init) from [<c04bdb84>] (start_kernel+0x248/0x3bc)
[<c04bd93c>] (start_kernel) from [<40008084>] (0x40008084)
 r10:00000000 r9:413fc0f2 r8:40007000 r7:c0505870 r6:c04ed094 r5:c0502440
 r4:c0521054


> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c

> @@ -2391,25 +2543,24 @@ int __clk_get(struct clk *clk)
>         return 1;
>  }
>
> -static void clk_core_put(struct clk_core *core)
> +void __clk_put(struct clk *clk)
>  {
>         struct module *owner;
>
> -       owner = core->owner;
> +       if (!clk || WARN_ON_ONCE(IS_ERR(clk)))
> +               return;
>
>         clk_prepare_lock();
> -       kref_put(&core->ref, __clk_release);
> +
> +       hlist_del(&clk->child_node);
> +       clk_core_set_rate_nolock(clk->core, clk->core->req_rate);

At this point, clk->core->req_rate is still zero, causing
cpg_div6_clock_round_rate() to be called with a zero "rate" parameter,
e.g. on r8a7791:

cpg_div6_clock_round_rate: clock sd2 rate 0 parent_rate 780000000 div 1
cpg_div6_clock_round_rate: clock sd1 rate 0 parent_rate 780000000 div 1
cpg_div6_clock_round_rate: clock mmc0 rate 0 parent_rate 780000000 div 1
cpg_div6_clock_round_rate: clock sd1 rate 0 parent_rate 780000000 div 1
cpg_div6_clock_round_rate: clock sd1 rate 0 parent_rate 780000000 div 1
cpg_div6_clock_round_rate: clock sd2 rate 0 parent_rate 780000000 div 1
cpg_div6_clock_round_rate: clock sd2 rate 0 parent_rate 780000000 div 1

and cpg_div6_clock_calc_div() is called to calculate

        div = DIV_ROUND_CLOSEST(parent_rate, rate);

Why was this call to clk_core_set_rate_nolock() in __clk_put() added?
Before, there was no rate setting done at this point, and
cpg_div6_clock_round_rate() was not called.

Have the semantics changed? Should .round_rate() be ready to
accept a "zero" rate, and use e.g. the current rate instead?

> +       owner = clk->core->owner;
> +       kref_put(&clk->core->ref, __clk_release);
> +
>         clk_prepare_unlock();
>
>         module_put(owner);
> -}
> -
> -void __clk_put(struct clk *clk)
> -{
> -       if (!clk || WARN_ON_ONCE(IS_ERR(clk)))
> -               return;
>
> -       clk_core_put(clk->core);
>         kfree(clk);
>  }

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

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

* Re: [PATCH v13 4/6] clk: Add rate constraints to clocks
@ 2015-01-29 13:31     ` Geert Uytterhoeven
  0 siblings, 0 replies; 186+ messages in thread
From: Geert Uytterhoeven @ 2015-01-29 13:31 UTC (permalink / raw)
  To: Tomeu Vizoso, Mike Turquette
  Cc: linux-kernel, Stephen Boyd, Javier Martinez Canillas,
	Jonathan Corbet, Tony Lindgren, Russell King, Ralf Baechle,
	Boris Brezillon, Emilio López, Maxime Ripard, Tero Kristo,
	Manuel Lauss, Alex Elder, Matt Porter, Haojian Zhuang,
	Zhangfei Gao, Bintian Wang, Chao Xie, linux-doc, linux-omap,
	linux-arm-kernel, Linux MIPS Mailing List, Linux-sh list

Hi Tomeu, Mike,

On Fri, Jan 23, 2015 at 12:03 PM, Tomeu Vizoso
<tomeu.vizoso@collabora.com> wrote:
> Adds a way for clock consumers to set maximum and minimum rates. This
> can be used for thermal drivers to set minimum rates, or by misc.
> drivers to set maximum rates to assure a minimum performance level.
>
> Changes the signature of the determine_rate callback by adding the
> parameters min_rate and max_rate.
>
> Signed-off-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
> Reviewed-by: Stephen Boyd <sboyd@codeaurora.org>

This is now in clk-next, and causes division by zeroes on all shmobile
platforms that use renesas,cpg-div6-clock (verified on r8a73a4, r8a7740,
r8a7791, sh73a0):

Division by zero in kernel.
CPU: 0 PID: 0 Comm: swapper/0 Not tainted
3.19.0-rc6-koelsch-04360-g48d797d57c5932c8-dirty #792
Hardware name: Generic R8A7791 (Flattened Device Tree)
Backtrace:
[<c001216c>] (dump_backtrace) from [<c001238c>] (show_stack+0x18/0x1c)
 r6:c051b124 r5:00000000 r4:00000000 r3:00200000
[<c0012374>] (show_stack) from [<c03955d0>] (dump_stack+0x78/0x94)
[<c0395558>] (dump_stack) from [<c00122f4>] (__div0+0x18/0x20)
 r4:2e7ddb00 r3:c05093c8
[<c00122dc>] (__div0) from [<c01bdc9c>] (Ldiv0+0x8/0x10)
[<c02d8efc>] (cpg_div6_clock_round_rate) from [<c02d56a0>]
(clk_calc_new_rates+0xc8/0x1d4)
 r4:eec14e00 r3:c03cb52c
[<c02d55d8>] (clk_calc_new_rates) from [<c02d57f4>]
(clk_core_set_rate_nolock+0x48/0x90)
 r9:eec02f40 r8:00000001 r7:c051b0b8 r6:c051b124 r5:00000000 r4:eec14e00
[<c02d57ac>] (clk_core_set_rate_nolock) from [<c02d6848>] (__clk_put+0x78/0xdc)
 r7:c051b0b8 r6:c051b124 r5:eec08100 r4:eec029c0
[<c02d67d0>] (__clk_put) from [<c02d3238>] (clk_put+0x10/0x14)
 r5:eec08100 r4:00000000
[<c02d3228>] (clk_put) from [<c04db4d0>] (of_clk_init+0x144/0x178)
[<c04db38c>] (of_clk_init) from [<c04dbd34>] (rcar_gen2_clocks_init+0x1c/0x24)
 r10:c04ed098 r9:c05023c0 r8:ffffffff r7:19432124 r6:c0502404 r5:00989680
 r4:f0006000
[<c04dbd18>] (rcar_gen2_clocks_init) from [<c04c6a3c>]
(rcar_gen2_timer_init+0x130/0x14c)
[<c04c690c>] (rcar_gen2_timer_init) from [<c04c15b4>] (time_init+0x24/0x38)
 r7:00000000 r6:c0520c80 r5:00000000 r4:ef7fcbc0
[<c04c1590>] (time_init) from [<c04bdb84>] (start_kernel+0x248/0x3bc)
[<c04bd93c>] (start_kernel) from [<40008084>] (0x40008084)
 r10:00000000 r9:413fc0f2 r8:40007000 r7:c0505870 r6:c04ed094 r5:c0502440
 r4:c0521054


> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c

> @@ -2391,25 +2543,24 @@ int __clk_get(struct clk *clk)
>         return 1;
>  }
>
> -static void clk_core_put(struct clk_core *core)
> +void __clk_put(struct clk *clk)
>  {
>         struct module *owner;
>
> -       owner = core->owner;
> +       if (!clk || WARN_ON_ONCE(IS_ERR(clk)))
> +               return;
>
>         clk_prepare_lock();
> -       kref_put(&core->ref, __clk_release);
> +
> +       hlist_del(&clk->child_node);
> +       clk_core_set_rate_nolock(clk->core, clk->core->req_rate);

At this point, clk->core->req_rate is still zero, causing
cpg_div6_clock_round_rate() to be called with a zero "rate" parameter,
e.g. on r8a7791:

cpg_div6_clock_round_rate: clock sd2 rate 0 parent_rate 780000000 div 1
cpg_div6_clock_round_rate: clock sd1 rate 0 parent_rate 780000000 div 1
cpg_div6_clock_round_rate: clock mmc0 rate 0 parent_rate 780000000 div 1
cpg_div6_clock_round_rate: clock sd1 rate 0 parent_rate 780000000 div 1
cpg_div6_clock_round_rate: clock sd1 rate 0 parent_rate 780000000 div 1
cpg_div6_clock_round_rate: clock sd2 rate 0 parent_rate 780000000 div 1
cpg_div6_clock_round_rate: clock sd2 rate 0 parent_rate 780000000 div 1

and cpg_div6_clock_calc_div() is called to calculate

        div = DIV_ROUND_CLOSEST(parent_rate, rate);

Why was this call to clk_core_set_rate_nolock() in __clk_put() added?
Before, there was no rate setting done at this point, and
cpg_div6_clock_round_rate() was not called.

Have the semantics changed? Should .round_rate() be ready to
accept a "zero" rate, and use e.g. the current rate instead?

> +       owner = clk->core->owner;
> +       kref_put(&clk->core->ref, __clk_release);
> +
>         clk_prepare_unlock();
>
>         module_put(owner);
> -}
> -
> -void __clk_put(struct clk *clk)
> -{
> -       if (!clk || WARN_ON_ONCE(IS_ERR(clk)))
> -               return;
>
> -       clk_core_put(clk->core);
>         kfree(clk);
>  }

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

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

* Re: [PATCH v13 4/6] clk: Add rate constraints to clocks
@ 2015-01-29 13:31     ` Geert Uytterhoeven
  0 siblings, 0 replies; 186+ messages in thread
From: Geert Uytterhoeven @ 2015-01-29 13:31 UTC (permalink / raw)
  To: Tomeu Vizoso, Mike Turquette
  Cc: linux-kernel, Stephen Boyd, Javier Martinez Canillas,
	Jonathan Corbet, Tony Lindgren, Russell King, Ralf Baechle,
	Boris Brezillon, Emilio López, Maxime Ripard, Tero Kristo,
	Manuel Lauss, Alex Elder, Matt Porter, Haojian Zhuang,
	Zhangfei Gao, Bintian Wang, Chao Xie, linux-doc, linux-omap

Hi Tomeu, Mike,

On Fri, Jan 23, 2015 at 12:03 PM, Tomeu Vizoso
<tomeu.vizoso@collabora.com> wrote:
> Adds a way for clock consumers to set maximum and minimum rates. This
> can be used for thermal drivers to set minimum rates, or by misc.
> drivers to set maximum rates to assure a minimum performance level.
>
> Changes the signature of the determine_rate callback by adding the
> parameters min_rate and max_rate.
>
> Signed-off-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
> Reviewed-by: Stephen Boyd <sboyd@codeaurora.org>

This is now in clk-next, and causes division by zeroes on all shmobile
platforms that use renesas,cpg-div6-clock (verified on r8a73a4, r8a7740,
r8a7791, sh73a0):

Division by zero in kernel.
CPU: 0 PID: 0 Comm: swapper/0 Not tainted
3.19.0-rc6-koelsch-04360-g48d797d57c5932c8-dirty #792
Hardware name: Generic R8A7791 (Flattened Device Tree)
Backtrace:
[<c001216c>] (dump_backtrace) from [<c001238c>] (show_stack+0x18/0x1c)
 r6:c051b124 r5:00000000 r4:00000000 r3:00200000
[<c0012374>] (show_stack) from [<c03955d0>] (dump_stack+0x78/0x94)
[<c0395558>] (dump_stack) from [<c00122f4>] (__div0+0x18/0x20)
 r4:2e7ddb00 r3:c05093c8
[<c00122dc>] (__div0) from [<c01bdc9c>] (Ldiv0+0x8/0x10)
[<c02d8efc>] (cpg_div6_clock_round_rate) from [<c02d56a0>]
(clk_calc_new_rates+0xc8/0x1d4)
 r4:eec14e00 r3:c03cb52c
[<c02d55d8>] (clk_calc_new_rates) from [<c02d57f4>]
(clk_core_set_rate_nolock+0x48/0x90)
 r9:eec02f40 r8:00000001 r7:c051b0b8 r6:c051b124 r5:00000000 r4:eec14e00
[<c02d57ac>] (clk_core_set_rate_nolock) from [<c02d6848>] (__clk_put+0x78/0xdc)
 r7:c051b0b8 r6:c051b124 r5:eec08100 r4:eec029c0
[<c02d67d0>] (__clk_put) from [<c02d3238>] (clk_put+0x10/0x14)
 r5:eec08100 r4:00000000
[<c02d3228>] (clk_put) from [<c04db4d0>] (of_clk_init+0x144/0x178)
[<c04db38c>] (of_clk_init) from [<c04dbd34>] (rcar_gen2_clocks_init+0x1c/0x24)
 r10:c04ed098 r9:c05023c0 r8:ffffffff r7:19432124 r6:c0502404 r5:00989680
 r4:f0006000
[<c04dbd18>] (rcar_gen2_clocks_init) from [<c04c6a3c>]
(rcar_gen2_timer_init+0x130/0x14c)
[<c04c690c>] (rcar_gen2_timer_init) from [<c04c15b4>] (time_init+0x24/0x38)
 r7:00000000 r6:c0520c80 r5:00000000 r4:ef7fcbc0
[<c04c1590>] (time_init) from [<c04bdb84>] (start_kernel+0x248/0x3bc)
[<c04bd93c>] (start_kernel) from [<40008084>] (0x40008084)
 r10:00000000 r9:413fc0f2 r8:40007000 r7:c0505870 r6:c04ed094 r5:c0502440
 r4:c0521054


> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c

> @@ -2391,25 +2543,24 @@ int __clk_get(struct clk *clk)
>         return 1;
>  }
>
> -static void clk_core_put(struct clk_core *core)
> +void __clk_put(struct clk *clk)
>  {
>         struct module *owner;
>
> -       owner = core->owner;
> +       if (!clk || WARN_ON_ONCE(IS_ERR(clk)))
> +               return;
>
>         clk_prepare_lock();
> -       kref_put(&core->ref, __clk_release);
> +
> +       hlist_del(&clk->child_node);
> +       clk_core_set_rate_nolock(clk->core, clk->core->req_rate);

At this point, clk->core->req_rate is still zero, causing
cpg_div6_clock_round_rate() to be called with a zero "rate" parameter,
e.g. on r8a7791:

cpg_div6_clock_round_rate: clock sd2 rate 0 parent_rate 780000000 div 1
cpg_div6_clock_round_rate: clock sd1 rate 0 parent_rate 780000000 div 1
cpg_div6_clock_round_rate: clock mmc0 rate 0 parent_rate 780000000 div 1
cpg_div6_clock_round_rate: clock sd1 rate 0 parent_rate 780000000 div 1
cpg_div6_clock_round_rate: clock sd1 rate 0 parent_rate 780000000 div 1
cpg_div6_clock_round_rate: clock sd2 rate 0 parent_rate 780000000 div 1
cpg_div6_clock_round_rate: clock sd2 rate 0 parent_rate 780000000 div 1

and cpg_div6_clock_calc_div() is called to calculate

        div = DIV_ROUND_CLOSEST(parent_rate, rate);

Why was this call to clk_core_set_rate_nolock() in __clk_put() added?
Before, there was no rate setting done at this point, and
cpg_div6_clock_round_rate() was not called.

Have the semantics changed? Should .round_rate() be ready to
accept a "zero" rate, and use e.g. the current rate instead?

> +       owner = clk->core->owner;
> +       kref_put(&clk->core->ref, __clk_release);
> +
>         clk_prepare_unlock();
>
>         module_put(owner);
> -}
> -
> -void __clk_put(struct clk *clk)
> -{
> -       if (!clk || WARN_ON_ONCE(IS_ERR(clk)))
> -               return;
>
> -       clk_core_put(clk->core);
>         kfree(clk);
>  }

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

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

* [PATCH v13 4/6] clk: Add rate constraints to clocks
@ 2015-01-29 13:31     ` Geert Uytterhoeven
  0 siblings, 0 replies; 186+ messages in thread
From: Geert Uytterhoeven @ 2015-01-29 13:31 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Tomeu, Mike,

On Fri, Jan 23, 2015 at 12:03 PM, Tomeu Vizoso
<tomeu.vizoso@collabora.com> wrote:
> Adds a way for clock consumers to set maximum and minimum rates. This
> can be used for thermal drivers to set minimum rates, or by misc.
> drivers to set maximum rates to assure a minimum performance level.
>
> Changes the signature of the determine_rate callback by adding the
> parameters min_rate and max_rate.
>
> Signed-off-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
> Reviewed-by: Stephen Boyd <sboyd@codeaurora.org>

This is now in clk-next, and causes division by zeroes on all shmobile
platforms that use renesas,cpg-div6-clock (verified on r8a73a4, r8a7740,
r8a7791, sh73a0):

Division by zero in kernel.
CPU: 0 PID: 0 Comm: swapper/0 Not tainted
3.19.0-rc6-koelsch-04360-g48d797d57c5932c8-dirty #792
Hardware name: Generic R8A7791 (Flattened Device Tree)
Backtrace:
[<c001216c>] (dump_backtrace) from [<c001238c>] (show_stack+0x18/0x1c)
 r6:c051b124 r5:00000000 r4:00000000 r3:00200000
[<c0012374>] (show_stack) from [<c03955d0>] (dump_stack+0x78/0x94)
[<c0395558>] (dump_stack) from [<c00122f4>] (__div0+0x18/0x20)
 r4:2e7ddb00 r3:c05093c8
[<c00122dc>] (__div0) from [<c01bdc9c>] (Ldiv0+0x8/0x10)
[<c02d8efc>] (cpg_div6_clock_round_rate) from [<c02d56a0>]
(clk_calc_new_rates+0xc8/0x1d4)
 r4:eec14e00 r3:c03cb52c
[<c02d55d8>] (clk_calc_new_rates) from [<c02d57f4>]
(clk_core_set_rate_nolock+0x48/0x90)
 r9:eec02f40 r8:00000001 r7:c051b0b8 r6:c051b124 r5:00000000 r4:eec14e00
[<c02d57ac>] (clk_core_set_rate_nolock) from [<c02d6848>] (__clk_put+0x78/0xdc)
 r7:c051b0b8 r6:c051b124 r5:eec08100 r4:eec029c0
[<c02d67d0>] (__clk_put) from [<c02d3238>] (clk_put+0x10/0x14)
 r5:eec08100 r4:00000000
[<c02d3228>] (clk_put) from [<c04db4d0>] (of_clk_init+0x144/0x178)
[<c04db38c>] (of_clk_init) from [<c04dbd34>] (rcar_gen2_clocks_init+0x1c/0x24)
 r10:c04ed098 r9:c05023c0 r8:ffffffff r7:19432124 r6:c0502404 r5:00989680
 r4:f0006000
[<c04dbd18>] (rcar_gen2_clocks_init) from [<c04c6a3c>]
(rcar_gen2_timer_init+0x130/0x14c)
[<c04c690c>] (rcar_gen2_timer_init) from [<c04c15b4>] (time_init+0x24/0x38)
 r7:00000000 r6:c0520c80 r5:00000000 r4:ef7fcbc0
[<c04c1590>] (time_init) from [<c04bdb84>] (start_kernel+0x248/0x3bc)
[<c04bd93c>] (start_kernel) from [<40008084>] (0x40008084)
 r10:00000000 r9:413fc0f2 r8:40007000 r7:c0505870 r6:c04ed094 r5:c0502440
 r4:c0521054


> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c

> @@ -2391,25 +2543,24 @@ int __clk_get(struct clk *clk)
>         return 1;
>  }
>
> -static void clk_core_put(struct clk_core *core)
> +void __clk_put(struct clk *clk)
>  {
>         struct module *owner;
>
> -       owner = core->owner;
> +       if (!clk || WARN_ON_ONCE(IS_ERR(clk)))
> +               return;
>
>         clk_prepare_lock();
> -       kref_put(&core->ref, __clk_release);
> +
> +       hlist_del(&clk->child_node);
> +       clk_core_set_rate_nolock(clk->core, clk->core->req_rate);

At this point, clk->core->req_rate is still zero, causing
cpg_div6_clock_round_rate() to be called with a zero "rate" parameter,
e.g. on r8a7791:

cpg_div6_clock_round_rate: clock sd2 rate 0 parent_rate 780000000 div 1
cpg_div6_clock_round_rate: clock sd1 rate 0 parent_rate 780000000 div 1
cpg_div6_clock_round_rate: clock mmc0 rate 0 parent_rate 780000000 div 1
cpg_div6_clock_round_rate: clock sd1 rate 0 parent_rate 780000000 div 1
cpg_div6_clock_round_rate: clock sd1 rate 0 parent_rate 780000000 div 1
cpg_div6_clock_round_rate: clock sd2 rate 0 parent_rate 780000000 div 1
cpg_div6_clock_round_rate: clock sd2 rate 0 parent_rate 780000000 div 1

and cpg_div6_clock_calc_div() is called to calculate

        div = DIV_ROUND_CLOSEST(parent_rate, rate);

Why was this call to clk_core_set_rate_nolock() in __clk_put() added?
Before, there was no rate setting done at this point, and
cpg_div6_clock_round_rate() was not called.

Have the semantics changed? Should .round_rate() be ready to
accept a "zero" rate, and use e.g. the current rate instead?

> +       owner = clk->core->owner;
> +       kref_put(&clk->core->ref, __clk_release);
> +
>         clk_prepare_unlock();
>
>         module_put(owner);
> -}
> -
> -void __clk_put(struct clk *clk)
> -{
> -       if (!clk || WARN_ON_ONCE(IS_ERR(clk)))
> -               return;
>
> -       clk_core_put(clk->core);
>         kfree(clk);
>  }

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert at linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

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

* Re: [PATCH v13 0/6] Per-user clock constraints
  2015-01-29  6:41       ` Tomeu Vizoso
@ 2015-01-29 14:29         ` Mike Turquette
  0 siblings, 0 replies; 186+ messages in thread
From: Mike Turquette @ 2015-01-29 14:29 UTC (permalink / raw)
  To: Tomeu Vizoso; +Cc: Stephen Boyd, linux-kernel, Javier Martinez Canillas

On Wed, Jan 28, 2015 at 10:41 PM, Tomeu Vizoso
<tomeu.vizoso@collabora.com> wrote:
> On 01/29/2015 03:26 AM, Mike Turquette wrote:
>> Quoting Tomeu Vizoso (2015-01-27 22:59:59)
>>> On 01/27/2015 01:55 AM, Stephen Boyd wrote:
>>>> On 01/23/15 03:03, Tomeu Vizoso wrote:
>>>>> Hi,
>>>>>
>>>>> in this v13 I have:
>>>>>
>>>>> * added the latest R-b tags from Stephen,
>>>>>
>>>>> * split some lines that went over the 80-char limit,
>>>>>
>>>>> * made explicit in the docs that the range limits are inclusive, and
>>>>>
>>>>> * removed an ifdef in clkdev.c by adding a dev_id param to __of_clk_get_by_name.
>>>>>
>>>>
>>>> I think this patch series is ready to go except for the last one? Do you
>>>> plan on polishing that one some more?
>>>
>>> Hi Mike,
>>>
>>> do you plan to merge this for 3.20?
>>
>> Tomeu,
>>
>> Yes. I have taken patches 1-5.
>>
>> I edited patch #3 to adapt clk_has_parent for struct clk_core.
>>
>> https://git.kernel.org/cgit/linux/kernel/git/clk/linux.git/commit/?h=clk-next&id=59cf3fcf9bafe8fdb6183f13dafb81fc8213a8f9
>>
>> Patch #4 need an update to convert sun6i_ahb1_clk_determine_rate to have
>> min/max rates.
>>
>> https://git.kernel.org/cgit/linux/kernel/git/clk/linux.git/commit/?h=clk-next&id=cb75a8fcd14e71c115decc416dd8d223e7c8b2e0
>>
>> Can you look it over and make sure I didn't screw anything up?
>
> Yup, they look good to me. I have also done some testing here.

Great! Thanks again for your hard work on this series.

Regards,
Mike

>
> Thanks,
>
> Tomeu
>

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

* Re: [PATCH v13 4/6] clk: Add rate constraints to clocks
  2015-01-29 13:31     ` Geert Uytterhoeven
  (?)
  (?)
@ 2015-01-29 19:13       ` Stephen Boyd
  -1 siblings, 0 replies; 186+ messages in thread
From: Stephen Boyd @ 2015-01-29 19:13 UTC (permalink / raw)
  To: linux-arm-kernel

On 01/29/15 05:31, Geert Uytterhoeven wrote:
> Hi Tomeu, Mike,
>
> On Fri, Jan 23, 2015 at 12:03 PM, Tomeu Vizoso
> <tomeu.vizoso@collabora.com> wrote:
>> --- a/drivers/clk/clk.c
>> +++ b/drivers/clk/clk.c
>> @@ -2391,25 +2543,24 @@ int __clk_get(struct clk *clk)
>>         return 1;
>>  }
>>
>> -static void clk_core_put(struct clk_core *core)
>> +void __clk_put(struct clk *clk)
>>  {
>>         struct module *owner;
>>
>> -       owner = core->owner;
>> +       if (!clk || WARN_ON_ONCE(IS_ERR(clk)))
>> +               return;
>>
>>         clk_prepare_lock();
>> -       kref_put(&core->ref, __clk_release);
>> +
>> +       hlist_del(&clk->child_node);
>> +       clk_core_set_rate_nolock(clk->core, clk->core->req_rate);
> At this point, clk->core->req_rate is still zero, causing
> cpg_div6_clock_round_rate() to be called with a zero "rate" parameter,
> e.g. on r8a7791:

Hmm.. I wonder if we should assign core->req_rate to be the same as
core->rate during __clk_init()? That would make this call to
clk_core_set_rate_nolock() a nop in this case.

>
> cpg_div6_clock_round_rate: clock sd2 rate 0 parent_rate 780000000 div 1
> cpg_div6_clock_round_rate: clock sd1 rate 0 parent_rate 780000000 div 1
> cpg_div6_clock_round_rate: clock mmc0 rate 0 parent_rate 780000000 div 1
> cpg_div6_clock_round_rate: clock sd1 rate 0 parent_rate 780000000 div 1
> cpg_div6_clock_round_rate: clock sd1 rate 0 parent_rate 780000000 div 1
> cpg_div6_clock_round_rate: clock sd2 rate 0 parent_rate 780000000 div 1
> cpg_div6_clock_round_rate: clock sd2 rate 0 parent_rate 780000000 div 1
>
> and cpg_div6_clock_calc_div() is called to calculate
>
>         div = DIV_ROUND_CLOSEST(parent_rate, rate);
>
> Why was this call to clk_core_set_rate_nolock() in __clk_put() added?
> Before, there was no rate setting done at this point, and
> cpg_div6_clock_round_rate() was not called.

We need to call clk_core_set_rate_nolock() here to drop any min/max rate
request that this consumer has.

>
> Have the semantics changed? Should .round_rate() be ready to
> accept a "zero" rate, and use e.g. the current rate instead?

It seems like we've also exposed a bug in cpg_div6_clock_calc_div().
Technically any driver could have called clk_round_rate() with a zero
rate before this change and that would have caused the same division by
zero.

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


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

* Re: [PATCH v13 4/6] clk: Add rate constraints to clocks
@ 2015-01-29 19:13       ` Stephen Boyd
  0 siblings, 0 replies; 186+ messages in thread
From: Stephen Boyd @ 2015-01-29 19:13 UTC (permalink / raw)
  To: Geert Uytterhoeven, Tomeu Vizoso, Mike Turquette
  Cc: linux-kernel, Javier Martinez Canillas, Jonathan Corbet,
	Tony Lindgren, Russell King, Ralf Baechle, Boris Brezillon,
	Emilio López, Maxime Ripard, Tero Kristo, Manuel Lauss,
	Alex Elder, Matt Porter, Haojian Zhuang, Zhangfei Gao,
	Bintian Wang, Chao Xie, linux-doc, linux-omap, linux-arm-kernel,
	Linux MIPS Mailing List, Linux-sh list

On 01/29/15 05:31, Geert Uytterhoeven wrote:
> Hi Tomeu, Mike,
>
> On Fri, Jan 23, 2015 at 12:03 PM, Tomeu Vizoso
> <tomeu.vizoso@collabora.com> wrote:
>> --- a/drivers/clk/clk.c
>> +++ b/drivers/clk/clk.c
>> @@ -2391,25 +2543,24 @@ int __clk_get(struct clk *clk)
>>         return 1;
>>  }
>>
>> -static void clk_core_put(struct clk_core *core)
>> +void __clk_put(struct clk *clk)
>>  {
>>         struct module *owner;
>>
>> -       owner = core->owner;
>> +       if (!clk || WARN_ON_ONCE(IS_ERR(clk)))
>> +               return;
>>
>>         clk_prepare_lock();
>> -       kref_put(&core->ref, __clk_release);
>> +
>> +       hlist_del(&clk->child_node);
>> +       clk_core_set_rate_nolock(clk->core, clk->core->req_rate);
> At this point, clk->core->req_rate is still zero, causing
> cpg_div6_clock_round_rate() to be called with a zero "rate" parameter,
> e.g. on r8a7791:

Hmm.. I wonder if we should assign core->req_rate to be the same as
core->rate during __clk_init()? That would make this call to
clk_core_set_rate_nolock() a nop in this case.

>
> cpg_div6_clock_round_rate: clock sd2 rate 0 parent_rate 780000000 div 1
> cpg_div6_clock_round_rate: clock sd1 rate 0 parent_rate 780000000 div 1
> cpg_div6_clock_round_rate: clock mmc0 rate 0 parent_rate 780000000 div 1
> cpg_div6_clock_round_rate: clock sd1 rate 0 parent_rate 780000000 div 1
> cpg_div6_clock_round_rate: clock sd1 rate 0 parent_rate 780000000 div 1
> cpg_div6_clock_round_rate: clock sd2 rate 0 parent_rate 780000000 div 1
> cpg_div6_clock_round_rate: clock sd2 rate 0 parent_rate 780000000 div 1
>
> and cpg_div6_clock_calc_div() is called to calculate
>
>         div = DIV_ROUND_CLOSEST(parent_rate, rate);
>
> Why was this call to clk_core_set_rate_nolock() in __clk_put() added?
> Before, there was no rate setting done at this point, and
> cpg_div6_clock_round_rate() was not called.

We need to call clk_core_set_rate_nolock() here to drop any min/max rate
request that this consumer has.

>
> Have the semantics changed? Should .round_rate() be ready to
> accept a "zero" rate, and use e.g. the current rate instead?

It seems like we've also exposed a bug in cpg_div6_clock_calc_div().
Technically any driver could have called clk_round_rate() with a zero
rate before this change and that would have caused the same division by
zero.

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


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

* Re: [PATCH v13 4/6] clk: Add rate constraints to clocks
@ 2015-01-29 19:13       ` Stephen Boyd
  0 siblings, 0 replies; 186+ messages in thread
From: Stephen Boyd @ 2015-01-29 19:13 UTC (permalink / raw)
  To: Geert Uytterhoeven, Tomeu Vizoso, Mike Turquette
  Cc: linux-kernel, Javier Martinez Canillas, Jonathan Corbet,
	Tony Lindgren, Russell King, Ralf Baechle, Boris Brezillon,
	Emilio López, Maxime Ripard, Tero Kristo, Manuel Lauss,
	Alex Elder, Matt Porter, Haojian Zhuang, Zhangfei Gao,
	Bintian Wang, Chao Xie, linux-doc, linux-omap

On 01/29/15 05:31, Geert Uytterhoeven wrote:
> Hi Tomeu, Mike,
>
> On Fri, Jan 23, 2015 at 12:03 PM, Tomeu Vizoso
> <tomeu.vizoso@collabora.com> wrote:
>> --- a/drivers/clk/clk.c
>> +++ b/drivers/clk/clk.c
>> @@ -2391,25 +2543,24 @@ int __clk_get(struct clk *clk)
>>         return 1;
>>  }
>>
>> -static void clk_core_put(struct clk_core *core)
>> +void __clk_put(struct clk *clk)
>>  {
>>         struct module *owner;
>>
>> -       owner = core->owner;
>> +       if (!clk || WARN_ON_ONCE(IS_ERR(clk)))
>> +               return;
>>
>>         clk_prepare_lock();
>> -       kref_put(&core->ref, __clk_release);
>> +
>> +       hlist_del(&clk->child_node);
>> +       clk_core_set_rate_nolock(clk->core, clk->core->req_rate);
> At this point, clk->core->req_rate is still zero, causing
> cpg_div6_clock_round_rate() to be called with a zero "rate" parameter,
> e.g. on r8a7791:

Hmm.. I wonder if we should assign core->req_rate to be the same as
core->rate during __clk_init()? That would make this call to
clk_core_set_rate_nolock() a nop in this case.

>
> cpg_div6_clock_round_rate: clock sd2 rate 0 parent_rate 780000000 div 1
> cpg_div6_clock_round_rate: clock sd1 rate 0 parent_rate 780000000 div 1
> cpg_div6_clock_round_rate: clock mmc0 rate 0 parent_rate 780000000 div 1
> cpg_div6_clock_round_rate: clock sd1 rate 0 parent_rate 780000000 div 1
> cpg_div6_clock_round_rate: clock sd1 rate 0 parent_rate 780000000 div 1
> cpg_div6_clock_round_rate: clock sd2 rate 0 parent_rate 780000000 div 1
> cpg_div6_clock_round_rate: clock sd2 rate 0 parent_rate 780000000 div 1
>
> and cpg_div6_clock_calc_div() is called to calculate
>
>         div = DIV_ROUND_CLOSEST(parent_rate, rate);
>
> Why was this call to clk_core_set_rate_nolock() in __clk_put() added?
> Before, there was no rate setting done at this point, and
> cpg_div6_clock_round_rate() was not called.

We need to call clk_core_set_rate_nolock() here to drop any min/max rate
request that this consumer has.

>
> Have the semantics changed? Should .round_rate() be ready to
> accept a "zero" rate, and use e.g. the current rate instead?

It seems like we've also exposed a bug in cpg_div6_clock_calc_div().
Technically any driver could have called clk_round_rate() with a zero
rate before this change and that would have caused the same division by
zero.

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


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

* [PATCH v13 4/6] clk: Add rate constraints to clocks
@ 2015-01-29 19:13       ` Stephen Boyd
  0 siblings, 0 replies; 186+ messages in thread
From: Stephen Boyd @ 2015-01-29 19:13 UTC (permalink / raw)
  To: linux-arm-kernel

On 01/29/15 05:31, Geert Uytterhoeven wrote:
> Hi Tomeu, Mike,
>
> On Fri, Jan 23, 2015 at 12:03 PM, Tomeu Vizoso
> <tomeu.vizoso@collabora.com> wrote:
>> --- a/drivers/clk/clk.c
>> +++ b/drivers/clk/clk.c
>> @@ -2391,25 +2543,24 @@ int __clk_get(struct clk *clk)
>>         return 1;
>>  }
>>
>> -static void clk_core_put(struct clk_core *core)
>> +void __clk_put(struct clk *clk)
>>  {
>>         struct module *owner;
>>
>> -       owner = core->owner;
>> +       if (!clk || WARN_ON_ONCE(IS_ERR(clk)))
>> +               return;
>>
>>         clk_prepare_lock();
>> -       kref_put(&core->ref, __clk_release);
>> +
>> +       hlist_del(&clk->child_node);
>> +       clk_core_set_rate_nolock(clk->core, clk->core->req_rate);
> At this point, clk->core->req_rate is still zero, causing
> cpg_div6_clock_round_rate() to be called with a zero "rate" parameter,
> e.g. on r8a7791:

Hmm.. I wonder if we should assign core->req_rate to be the same as
core->rate during __clk_init()? That would make this call to
clk_core_set_rate_nolock() a nop in this case.

>
> cpg_div6_clock_round_rate: clock sd2 rate 0 parent_rate 780000000 div 1
> cpg_div6_clock_round_rate: clock sd1 rate 0 parent_rate 780000000 div 1
> cpg_div6_clock_round_rate: clock mmc0 rate 0 parent_rate 780000000 div 1
> cpg_div6_clock_round_rate: clock sd1 rate 0 parent_rate 780000000 div 1
> cpg_div6_clock_round_rate: clock sd1 rate 0 parent_rate 780000000 div 1
> cpg_div6_clock_round_rate: clock sd2 rate 0 parent_rate 780000000 div 1
> cpg_div6_clock_round_rate: clock sd2 rate 0 parent_rate 780000000 div 1
>
> and cpg_div6_clock_calc_div() is called to calculate
>
>         div = DIV_ROUND_CLOSEST(parent_rate, rate);
>
> Why was this call to clk_core_set_rate_nolock() in __clk_put() added?
> Before, there was no rate setting done at this point, and
> cpg_div6_clock_round_rate() was not called.

We need to call clk_core_set_rate_nolock() here to drop any min/max rate
request that this consumer has.

>
> Have the semantics changed? Should .round_rate() be ready to
> accept a "zero" rate, and use e.g. the current rate instead?

It seems like we've also exposed a bug in cpg_div6_clock_calc_div().
Technically any driver could have called clk_round_rate() with a zero
rate before this change and that would have caused the same division by
zero.

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

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

* Re: [PATCH v13 4/6] clk: Add rate constraints to clocks
  2015-01-29 19:13       ` Stephen Boyd
                           ` (2 preceding siblings ...)
  (?)
@ 2015-01-31  1:31         ` Stephen Boyd
  -1 siblings, 0 replies; 186+ messages in thread
From: Stephen Boyd @ 2015-01-31  1:31 UTC (permalink / raw)
  To: linux-arm-kernel

On 01/29, Stephen Boyd wrote:
> On 01/29/15 05:31, Geert Uytterhoeven wrote:
> > Hi Tomeu, Mike,
> >
> > On Fri, Jan 23, 2015 at 12:03 PM, Tomeu Vizoso
> > <tomeu.vizoso@collabora.com> wrote:
> >> --- a/drivers/clk/clk.c
> >> +++ b/drivers/clk/clk.c
> >> @@ -2391,25 +2543,24 @@ int __clk_get(struct clk *clk)
> >>         return 1;
> >>  }
> >>
> >> -static void clk_core_put(struct clk_core *core)
> >> +void __clk_put(struct clk *clk)
> >>  {
> >>         struct module *owner;
> >>
> >> -       owner = core->owner;
> >> +       if (!clk || WARN_ON_ONCE(IS_ERR(clk)))
> >> +               return;
> >>
> >>         clk_prepare_lock();
> >> -       kref_put(&core->ref, __clk_release);
> >> +
> >> +       hlist_del(&clk->child_node);
> >> +       clk_core_set_rate_nolock(clk->core, clk->core->req_rate);
> > At this point, clk->core->req_rate is still zero, causing
> > cpg_div6_clock_round_rate() to be called with a zero "rate" parameter,
> > e.g. on r8a7791:
> 
> Hmm.. I wonder if we should assign core->req_rate to be the same as
> core->rate during __clk_init()? That would make this call to
> clk_core_set_rate_nolock() a nop in this case.
> 

Here's a patch to do this

---8<----
From: Stephen Boyd <sboyd@codeaurora.org>
Subject: [PATCH] clk: Assign a requested rate by default

We need to assign a requested rate here so that we avoid
requesting a rate of 0 on clocks when we remove clock consumers.

Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/clk.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index a29daf9edea4..8416ed1c40be 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -2142,6 +2142,7 @@ int __clk_init(struct device *dev, struct clk *clk_user)
 	struct clk_core *orphan;
 	struct hlist_node *tmp2;
 	struct clk_core *clk;
+	unsigned long rate;
 
 	if (!clk_user)
 		return -EINVAL;
@@ -2266,12 +2267,13 @@ int __clk_init(struct device *dev, struct clk *clk_user)
 	 * then rate is set to zero.
 	 */
 	if (clk->ops->recalc_rate)
-		clk->rate = clk->ops->recalc_rate(clk->hw,
+		rate = clk->ops->recalc_rate(clk->hw,
 				clk_core_get_rate_nolock(clk->parent));
 	else if (clk->parent)
-		clk->rate = clk->parent->rate;
+		rate = clk->parent->rate;
 	else
-		clk->rate = 0;
+		rate = 0;
+	clk->rate = clk->req_rate = rate;
 
 	/*
 	 * walk the list of orphan clocks and reparent any that are children of
-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

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

* Re: [PATCH v13 4/6] clk: Add rate constraints to clocks
@ 2015-01-31  1:31         ` Stephen Boyd
  0 siblings, 0 replies; 186+ messages in thread
From: Stephen Boyd @ 2015-01-31  1:31 UTC (permalink / raw)
  To: Geert Uytterhoeven, Tomeu Vizoso, Mike Turquette
  Cc: Linux MIPS Mailing List, linux-doc, Tony Lindgren, Chao Xie,
	Haojian Zhuang, Boris Brezillon, Russell King, Jonathan Corbet,
	Emilio L??pez, Linux-sh list, Alex Elder, Zhangfei Gao,
	Bintian Wang, Matt Porter, linux-omap, linux-arm-kernel,
	linux-kernel, Ralf Baechle, Tero Kristo, Manuel Lauss,
	Maxime Ripard, Javier Martinez Canillas

On 01/29, Stephen Boyd wrote:
> On 01/29/15 05:31, Geert Uytterhoeven wrote:
> > Hi Tomeu, Mike,
> >
> > On Fri, Jan 23, 2015 at 12:03 PM, Tomeu Vizoso
> > <tomeu.vizoso@collabora.com> wrote:
> >> --- a/drivers/clk/clk.c
> >> +++ b/drivers/clk/clk.c
> >> @@ -2391,25 +2543,24 @@ int __clk_get(struct clk *clk)
> >>         return 1;
> >>  }
> >>
> >> -static void clk_core_put(struct clk_core *core)
> >> +void __clk_put(struct clk *clk)
> >>  {
> >>         struct module *owner;
> >>
> >> -       owner = core->owner;
> >> +       if (!clk || WARN_ON_ONCE(IS_ERR(clk)))
> >> +               return;
> >>
> >>         clk_prepare_lock();
> >> -       kref_put(&core->ref, __clk_release);
> >> +
> >> +       hlist_del(&clk->child_node);
> >> +       clk_core_set_rate_nolock(clk->core, clk->core->req_rate);
> > At this point, clk->core->req_rate is still zero, causing
> > cpg_div6_clock_round_rate() to be called with a zero "rate" parameter,
> > e.g. on r8a7791:
> 
> Hmm.. I wonder if we should assign core->req_rate to be the same as
> core->rate during __clk_init()? That would make this call to
> clk_core_set_rate_nolock() a nop in this case.
> 

Here's a patch to do this

---8<----
From: Stephen Boyd <sboyd@codeaurora.org>
Subject: [PATCH] clk: Assign a requested rate by default

We need to assign a requested rate here so that we avoid
requesting a rate of 0 on clocks when we remove clock consumers.

Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/clk.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index a29daf9edea4..8416ed1c40be 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -2142,6 +2142,7 @@ int __clk_init(struct device *dev, struct clk *clk_user)
 	struct clk_core *orphan;
 	struct hlist_node *tmp2;
 	struct clk_core *clk;
+	unsigned long rate;
 
 	if (!clk_user)
 		return -EINVAL;
@@ -2266,12 +2267,13 @@ int __clk_init(struct device *dev, struct clk *clk_user)
 	 * then rate is set to zero.
 	 */
 	if (clk->ops->recalc_rate)
-		clk->rate = clk->ops->recalc_rate(clk->hw,
+		rate = clk->ops->recalc_rate(clk->hw,
 				clk_core_get_rate_nolock(clk->parent));
 	else if (clk->parent)
-		clk->rate = clk->parent->rate;
+		rate = clk->parent->rate;
 	else
-		clk->rate = 0;
+		rate = 0;
+	clk->rate = clk->req_rate = rate;
 
 	/*
 	 * walk the list of orphan clocks and reparent any that are children of
-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

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

* Re: [PATCH v13 4/6] clk: Add rate constraints to clocks
@ 2015-01-31  1:31         ` Stephen Boyd
  0 siblings, 0 replies; 186+ messages in thread
From: Stephen Boyd @ 2015-01-31  1:31 UTC (permalink / raw)
  To: Geert Uytterhoeven, Tomeu Vizoso, Mike Turquette
  Cc: Linux MIPS Mailing List, linux-doc, Tony Lindgren, Chao Xie,
	Haojian Zhuang, Boris Brezillon, Russell King, Jonathan Corbet,
	Emilio L??pez, Linux-sh list, Alex Elder, Zhangfei Gao,
	Bintian Wang, Matt Porter, linux-omap, linux-arm-kernel,
	linux-kernel, Ralf Baechle, Tero Kristo, Manuel Lauss,
	Maxime Ripard, Javier Martinez Canillas

On 01/29, Stephen Boyd wrote:
> On 01/29/15 05:31, Geert Uytterhoeven wrote:
> > Hi Tomeu, Mike,
> >
> > On Fri, Jan 23, 2015 at 12:03 PM, Tomeu Vizoso
> > <tomeu.vizoso@collabora.com> wrote:
> >> --- a/drivers/clk/clk.c
> >> +++ b/drivers/clk/clk.c
> >> @@ -2391,25 +2543,24 @@ int __clk_get(struct clk *clk)
> >>         return 1;
> >>  }
> >>
> >> -static void clk_core_put(struct clk_core *core)
> >> +void __clk_put(struct clk *clk)
> >>  {
> >>         struct module *owner;
> >>
> >> -       owner = core->owner;
> >> +       if (!clk || WARN_ON_ONCE(IS_ERR(clk)))
> >> +               return;
> >>
> >>         clk_prepare_lock();
> >> -       kref_put(&core->ref, __clk_release);
> >> +
> >> +       hlist_del(&clk->child_node);
> >> +       clk_core_set_rate_nolock(clk->core, clk->core->req_rate);
> > At this point, clk->core->req_rate is still zero, causing
> > cpg_div6_clock_round_rate() to be called with a zero "rate" parameter,
> > e.g. on r8a7791:
> 
> Hmm.. I wonder if we should assign core->req_rate to be the same as
> core->rate during __clk_init()? That would make this call to
> clk_core_set_rate_nolock() a nop in this case.
> 

Here's a patch to do this

---8<----
From: Stephen Boyd <sboyd@codeaurora.org>
Subject: [PATCH] clk: Assign a requested rate by default

We need to assign a requested rate here so that we avoid
requesting a rate of 0 on clocks when we remove clock consumers.

Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/clk.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index a29daf9edea4..8416ed1c40be 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -2142,6 +2142,7 @@ int __clk_init(struct device *dev, struct clk *clk_user)
 	struct clk_core *orphan;
 	struct hlist_node *tmp2;
 	struct clk_core *clk;
+	unsigned long rate;
 
 	if (!clk_user)
 		return -EINVAL;
@@ -2266,12 +2267,13 @@ int __clk_init(struct device *dev, struct clk *clk_user)
 	 * then rate is set to zero.
 	 */
 	if (clk->ops->recalc_rate)
-		clk->rate = clk->ops->recalc_rate(clk->hw,
+		rate = clk->ops->recalc_rate(clk->hw,
 				clk_core_get_rate_nolock(clk->parent));
 	else if (clk->parent)
-		clk->rate = clk->parent->rate;
+		rate = clk->parent->rate;
 	else
-		clk->rate = 0;
+		rate = 0;
+	clk->rate = clk->req_rate = rate;
 
 	/*
 	 * walk the list of orphan clocks and reparent any that are children of
-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

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

* Re: [PATCH v13 4/6] clk: Add rate constraints to clocks
@ 2015-01-31  1:31         ` Stephen Boyd
  0 siblings, 0 replies; 186+ messages in thread
From: Stephen Boyd @ 2015-01-31  1:31 UTC (permalink / raw)
  To: Geert Uytterhoeven, Tomeu Vizoso, Mike Turquette
  Cc: Linux MIPS Mailing List, linux-doc, Tony Lindgren, Chao Xie,
	Haojian Zhuang, Boris Brezillon, Russell King, Jonathan Corbet,
	Emilio L??pez, Linux-sh list, Alex Elder, Zhangfei Gao,
	Bintian Wang, Matt Porter, linux-omap, linux-arm-kernel,
	linux-kernel, Ralf Baechle, Tero Kristo, Manuel Lauss

On 01/29, Stephen Boyd wrote:
> On 01/29/15 05:31, Geert Uytterhoeven wrote:
> > Hi Tomeu, Mike,
> >
> > On Fri, Jan 23, 2015 at 12:03 PM, Tomeu Vizoso
> > <tomeu.vizoso@collabora.com> wrote:
> >> --- a/drivers/clk/clk.c
> >> +++ b/drivers/clk/clk.c
> >> @@ -2391,25 +2543,24 @@ int __clk_get(struct clk *clk)
> >>         return 1;
> >>  }
> >>
> >> -static void clk_core_put(struct clk_core *core)
> >> +void __clk_put(struct clk *clk)
> >>  {
> >>         struct module *owner;
> >>
> >> -       owner = core->owner;
> >> +       if (!clk || WARN_ON_ONCE(IS_ERR(clk)))
> >> +               return;
> >>
> >>         clk_prepare_lock();
> >> -       kref_put(&core->ref, __clk_release);
> >> +
> >> +       hlist_del(&clk->child_node);
> >> +       clk_core_set_rate_nolock(clk->core, clk->core->req_rate);
> > At this point, clk->core->req_rate is still zero, causing
> > cpg_div6_clock_round_rate() to be called with a zero "rate" parameter,
> > e.g. on r8a7791:
> 
> Hmm.. I wonder if we should assign core->req_rate to be the same as
> core->rate during __clk_init()? That would make this call to
> clk_core_set_rate_nolock() a nop in this case.
> 

Here's a patch to do this

---8<----
From: Stephen Boyd <sboyd@codeaurora.org>
Subject: [PATCH] clk: Assign a requested rate by default

We need to assign a requested rate here so that we avoid
requesting a rate of 0 on clocks when we remove clock consumers.

Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/clk.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index a29daf9edea4..8416ed1c40be 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -2142,6 +2142,7 @@ int __clk_init(struct device *dev, struct clk *clk_user)
 	struct clk_core *orphan;
 	struct hlist_node *tmp2;
 	struct clk_core *clk;
+	unsigned long rate;
 
 	if (!clk_user)
 		return -EINVAL;
@@ -2266,12 +2267,13 @@ int __clk_init(struct device *dev, struct clk *clk_user)
 	 * then rate is set to zero.
 	 */
 	if (clk->ops->recalc_rate)
-		clk->rate = clk->ops->recalc_rate(clk->hw,
+		rate = clk->ops->recalc_rate(clk->hw,
 				clk_core_get_rate_nolock(clk->parent));
 	else if (clk->parent)
-		clk->rate = clk->parent->rate;
+		rate = clk->parent->rate;
 	else
-		clk->rate = 0;
+		rate = 0;
+	clk->rate = clk->req_rate = rate;
 
 	/*
 	 * walk the list of orphan clocks and reparent any that are children of
-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

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

* [PATCH v13 4/6] clk: Add rate constraints to clocks
@ 2015-01-31  1:31         ` Stephen Boyd
  0 siblings, 0 replies; 186+ messages in thread
From: Stephen Boyd @ 2015-01-31  1:31 UTC (permalink / raw)
  To: linux-arm-kernel

On 01/29, Stephen Boyd wrote:
> On 01/29/15 05:31, Geert Uytterhoeven wrote:
> > Hi Tomeu, Mike,
> >
> > On Fri, Jan 23, 2015 at 12:03 PM, Tomeu Vizoso
> > <tomeu.vizoso@collabora.com> wrote:
> >> --- a/drivers/clk/clk.c
> >> +++ b/drivers/clk/clk.c
> >> @@ -2391,25 +2543,24 @@ int __clk_get(struct clk *clk)
> >>         return 1;
> >>  }
> >>
> >> -static void clk_core_put(struct clk_core *core)
> >> +void __clk_put(struct clk *clk)
> >>  {
> >>         struct module *owner;
> >>
> >> -       owner = core->owner;
> >> +       if (!clk || WARN_ON_ONCE(IS_ERR(clk)))
> >> +               return;
> >>
> >>         clk_prepare_lock();
> >> -       kref_put(&core->ref, __clk_release);
> >> +
> >> +       hlist_del(&clk->child_node);
> >> +       clk_core_set_rate_nolock(clk->core, clk->core->req_rate);
> > At this point, clk->core->req_rate is still zero, causing
> > cpg_div6_clock_round_rate() to be called with a zero "rate" parameter,
> > e.g. on r8a7791:
> 
> Hmm.. I wonder if we should assign core->req_rate to be the same as
> core->rate during __clk_init()? That would make this call to
> clk_core_set_rate_nolock() a nop in this case.
> 

Here's a patch to do this

---8<----
From: Stephen Boyd <sboyd@codeaurora.org>
Subject: [PATCH] clk: Assign a requested rate by default

We need to assign a requested rate here so that we avoid
requesting a rate of 0 on clocks when we remove clock consumers.

Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/clk.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index a29daf9edea4..8416ed1c40be 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -2142,6 +2142,7 @@ int __clk_init(struct device *dev, struct clk *clk_user)
 	struct clk_core *orphan;
 	struct hlist_node *tmp2;
 	struct clk_core *clk;
+	unsigned long rate;
 
 	if (!clk_user)
 		return -EINVAL;
@@ -2266,12 +2267,13 @@ int __clk_init(struct device *dev, struct clk *clk_user)
 	 * then rate is set to zero.
 	 */
 	if (clk->ops->recalc_rate)
-		clk->rate = clk->ops->recalc_rate(clk->hw,
+		rate = clk->ops->recalc_rate(clk->hw,
 				clk_core_get_rate_nolock(clk->parent));
 	else if (clk->parent)
-		clk->rate = clk->parent->rate;
+		rate = clk->parent->rate;
 	else
-		clk->rate = 0;
+		rate = 0;
+	clk->rate = clk->req_rate = rate;
 
 	/*
 	 * walk the list of orphan clocks and reparent any that are children of
-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

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

* Re: [PATCH v13 4/6] clk: Add rate constraints to clocks
  2015-01-31  1:31         ` Stephen Boyd
                             ` (2 preceding siblings ...)
  (?)
@ 2015-01-31 18:36           ` Tomeu Vizoso
  -1 siblings, 0 replies; 186+ messages in thread
From: Tomeu Vizoso @ 2015-01-31 18:36 UTC (permalink / raw)
  To: linux-arm-kernel

On 31 January 2015 at 02:31, Stephen Boyd <sboyd@codeaurora.org> wrote:
> On 01/29, Stephen Boyd wrote:
>> On 01/29/15 05:31, Geert Uytterhoeven wrote:
>> > Hi Tomeu, Mike,
>> >
>> > On Fri, Jan 23, 2015 at 12:03 PM, Tomeu Vizoso
>> > <tomeu.vizoso@collabora.com> wrote:
>> >> --- a/drivers/clk/clk.c
>> >> +++ b/drivers/clk/clk.c
>> >> @@ -2391,25 +2543,24 @@ int __clk_get(struct clk *clk)
>> >>         return 1;
>> >>  }
>> >>
>> >> -static void clk_core_put(struct clk_core *core)
>> >> +void __clk_put(struct clk *clk)
>> >>  {
>> >>         struct module *owner;
>> >>
>> >> -       owner = core->owner;
>> >> +       if (!clk || WARN_ON_ONCE(IS_ERR(clk)))
>> >> +               return;
>> >>
>> >>         clk_prepare_lock();
>> >> -       kref_put(&core->ref, __clk_release);
>> >> +
>> >> +       hlist_del(&clk->child_node);
>> >> +       clk_core_set_rate_nolock(clk->core, clk->core->req_rate);
>> > At this point, clk->core->req_rate is still zero, causing
>> > cpg_div6_clock_round_rate() to be called with a zero "rate" parameter,
>> > e.g. on r8a7791:
>>
>> Hmm.. I wonder if we should assign core->req_rate to be the same as
>> core->rate during __clk_init()? That would make this call to
>> clk_core_set_rate_nolock() a nop in this case.
>>
>
> Here's a patch to do this
>
> ---8<----
> From: Stephen Boyd <sboyd@codeaurora.org>
> Subject: [PATCH] clk: Assign a requested rate by default
>
> We need to assign a requested rate here so that we avoid
> requesting a rate of 0 on clocks when we remove clock consumers.

Hi, this looks good to me.

Reviewed-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>

Thanks,

Tomeu

> Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
> ---
>  drivers/clk/clk.c | 8 +++++---
>  1 file changed, 5 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> index a29daf9edea4..8416ed1c40be 100644
> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> @@ -2142,6 +2142,7 @@ int __clk_init(struct device *dev, struct clk *clk_user)
>         struct clk_core *orphan;
>         struct hlist_node *tmp2;
>         struct clk_core *clk;
> +       unsigned long rate;
>
>         if (!clk_user)
>                 return -EINVAL;
> @@ -2266,12 +2267,13 @@ int __clk_init(struct device *dev, struct clk *clk_user)
>          * then rate is set to zero.
>          */
>         if (clk->ops->recalc_rate)
> -               clk->rate = clk->ops->recalc_rate(clk->hw,
> +               rate = clk->ops->recalc_rate(clk->hw,
>                                 clk_core_get_rate_nolock(clk->parent));
>         else if (clk->parent)
> -               clk->rate = clk->parent->rate;
> +               rate = clk->parent->rate;
>         else
> -               clk->rate = 0;
> +               rate = 0;
> +       clk->rate = clk->req_rate = rate;
>
>         /*
>          * walk the list of orphan clocks and reparent any that are children of
> --
> Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
> a Linux Foundation Collaborative Project
>
> _______________________________________________
> 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] 186+ messages in thread

* Re: [PATCH v13 4/6] clk: Add rate constraints to clocks
@ 2015-01-31 18:36           ` Tomeu Vizoso
  0 siblings, 0 replies; 186+ messages in thread
From: Tomeu Vizoso @ 2015-01-31 18:36 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Geert Uytterhoeven, Mike Turquette, Linux MIPS Mailing List,
	linux-doc, Tony Lindgren, Chao Xie, Haojian Zhuang,
	Boris Brezillon, Russell King, Jonathan Corbet, Emilio L??pez,
	Linux-sh list, Alex Elder, Zhangfei Gao, Bintian Wang,
	Matt Porter, linux-omap, linux-arm-kernel, linux-kernel,
	Ralf Baechle, Tero Kristo, Manuel Lauss, Maxime Ripard,
	Javier Martinez Canillas

On 31 January 2015 at 02:31, Stephen Boyd <sboyd@codeaurora.org> wrote:
> On 01/29, Stephen Boyd wrote:
>> On 01/29/15 05:31, Geert Uytterhoeven wrote:
>> > Hi Tomeu, Mike,
>> >
>> > On Fri, Jan 23, 2015 at 12:03 PM, Tomeu Vizoso
>> > <tomeu.vizoso@collabora.com> wrote:
>> >> --- a/drivers/clk/clk.c
>> >> +++ b/drivers/clk/clk.c
>> >> @@ -2391,25 +2543,24 @@ int __clk_get(struct clk *clk)
>> >>         return 1;
>> >>  }
>> >>
>> >> -static void clk_core_put(struct clk_core *core)
>> >> +void __clk_put(struct clk *clk)
>> >>  {
>> >>         struct module *owner;
>> >>
>> >> -       owner = core->owner;
>> >> +       if (!clk || WARN_ON_ONCE(IS_ERR(clk)))
>> >> +               return;
>> >>
>> >>         clk_prepare_lock();
>> >> -       kref_put(&core->ref, __clk_release);
>> >> +
>> >> +       hlist_del(&clk->child_node);
>> >> +       clk_core_set_rate_nolock(clk->core, clk->core->req_rate);
>> > At this point, clk->core->req_rate is still zero, causing
>> > cpg_div6_clock_round_rate() to be called with a zero "rate" parameter,
>> > e.g. on r8a7791:
>>
>> Hmm.. I wonder if we should assign core->req_rate to be the same as
>> core->rate during __clk_init()? That would make this call to
>> clk_core_set_rate_nolock() a nop in this case.
>>
>
> Here's a patch to do this
>
> ---8<----
> From: Stephen Boyd <sboyd@codeaurora.org>
> Subject: [PATCH] clk: Assign a requested rate by default
>
> We need to assign a requested rate here so that we avoid
> requesting a rate of 0 on clocks when we remove clock consumers.

Hi, this looks good to me.

Reviewed-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>

Thanks,

Tomeu

> Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
> ---
>  drivers/clk/clk.c | 8 +++++---
>  1 file changed, 5 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> index a29daf9edea4..8416ed1c40be 100644
> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> @@ -2142,6 +2142,7 @@ int __clk_init(struct device *dev, struct clk *clk_user)
>         struct clk_core *orphan;
>         struct hlist_node *tmp2;
>         struct clk_core *clk;
> +       unsigned long rate;
>
>         if (!clk_user)
>                 return -EINVAL;
> @@ -2266,12 +2267,13 @@ int __clk_init(struct device *dev, struct clk *clk_user)
>          * then rate is set to zero.
>          */
>         if (clk->ops->recalc_rate)
> -               clk->rate = clk->ops->recalc_rate(clk->hw,
> +               rate = clk->ops->recalc_rate(clk->hw,
>                                 clk_core_get_rate_nolock(clk->parent));
>         else if (clk->parent)
> -               clk->rate = clk->parent->rate;
> +               rate = clk->parent->rate;
>         else
> -               clk->rate = 0;
> +               rate = 0;
> +       clk->rate = clk->req_rate = rate;
>
>         /*
>          * walk the list of orphan clocks and reparent any that are children of
> --
> Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
> a Linux Foundation Collaborative Project
>
> _______________________________________________
> 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] 186+ messages in thread

* Re: [PATCH v13 4/6] clk: Add rate constraints to clocks
@ 2015-01-31 18:36           ` Tomeu Vizoso
  0 siblings, 0 replies; 186+ messages in thread
From: Tomeu Vizoso @ 2015-01-31 18:36 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Geert Uytterhoeven, Mike Turquette, Linux MIPS Mailing List,
	linux-doc, Tony Lindgren, Chao Xie, Haojian Zhuang,
	Boris Brezillon, Russell King, Jonathan Corbet, Emilio L??pez,
	Linux-sh list, Alex Elder, Zhangfei Gao, Bintian Wang,
	Matt Porter, linux-omap, linux-arm-kernel, linux-kernel,
	Ralf Baechle, Tero Kristo, Manuel Lauss, Maxime Ripard,
	Javier Martinez Canillas

On 31 January 2015 at 02:31, Stephen Boyd <sboyd@codeaurora.org> wrote:
> On 01/29, Stephen Boyd wrote:
>> On 01/29/15 05:31, Geert Uytterhoeven wrote:
>> > Hi Tomeu, Mike,
>> >
>> > On Fri, Jan 23, 2015 at 12:03 PM, Tomeu Vizoso
>> > <tomeu.vizoso@collabora.com> wrote:
>> >> --- a/drivers/clk/clk.c
>> >> +++ b/drivers/clk/clk.c
>> >> @@ -2391,25 +2543,24 @@ int __clk_get(struct clk *clk)
>> >>         return 1;
>> >>  }
>> >>
>> >> -static void clk_core_put(struct clk_core *core)
>> >> +void __clk_put(struct clk *clk)
>> >>  {
>> >>         struct module *owner;
>> >>
>> >> -       owner = core->owner;
>> >> +       if (!clk || WARN_ON_ONCE(IS_ERR(clk)))
>> >> +               return;
>> >>
>> >>         clk_prepare_lock();
>> >> -       kref_put(&core->ref, __clk_release);
>> >> +
>> >> +       hlist_del(&clk->child_node);
>> >> +       clk_core_set_rate_nolock(clk->core, clk->core->req_rate);
>> > At this point, clk->core->req_rate is still zero, causing
>> > cpg_div6_clock_round_rate() to be called with a zero "rate" parameter,
>> > e.g. on r8a7791:
>>
>> Hmm.. I wonder if we should assign core->req_rate to be the same as
>> core->rate during __clk_init()? That would make this call to
>> clk_core_set_rate_nolock() a nop in this case.
>>
>
> Here's a patch to do this
>
> ---8<----
> From: Stephen Boyd <sboyd@codeaurora.org>
> Subject: [PATCH] clk: Assign a requested rate by default
>
> We need to assign a requested rate here so that we avoid
> requesting a rate of 0 on clocks when we remove clock consumers.

Hi, this looks good to me.

Reviewed-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>

Thanks,

Tomeu

> Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
> ---
>  drivers/clk/clk.c | 8 +++++---
>  1 file changed, 5 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> index a29daf9edea4..8416ed1c40be 100644
> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> @@ -2142,6 +2142,7 @@ int __clk_init(struct device *dev, struct clk *clk_user)
>         struct clk_core *orphan;
>         struct hlist_node *tmp2;
>         struct clk_core *clk;
> +       unsigned long rate;
>
>         if (!clk_user)
>                 return -EINVAL;
> @@ -2266,12 +2267,13 @@ int __clk_init(struct device *dev, struct clk *clk_user)
>          * then rate is set to zero.
>          */
>         if (clk->ops->recalc_rate)
> -               clk->rate = clk->ops->recalc_rate(clk->hw,
> +               rate = clk->ops->recalc_rate(clk->hw,
>                                 clk_core_get_rate_nolock(clk->parent));
>         else if (clk->parent)
> -               clk->rate = clk->parent->rate;
> +               rate = clk->parent->rate;
>         else
> -               clk->rate = 0;
> +               rate = 0;
> +       clk->rate = clk->req_rate = rate;
>
>         /*
>          * walk the list of orphan clocks and reparent any that are children of
> --
> Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
> a Linux Foundation Collaborative Project
>
> _______________________________________________
> 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] 186+ messages in thread

* Re: [PATCH v13 4/6] clk: Add rate constraints to clocks
@ 2015-01-31 18:36           ` Tomeu Vizoso
  0 siblings, 0 replies; 186+ messages in thread
From: Tomeu Vizoso @ 2015-01-31 18:36 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Geert Uytterhoeven, Mike Turquette, Linux MIPS Mailing List,
	linux-doc, Tony Lindgren, Chao Xie, Haojian Zhuang,
	Boris Brezillon, Russell King, Jonathan Corbet, Emilio L??pez,
	Linux-sh list, Alex Elder, Zhangfei Gao, Bintian Wang,
	Matt Porter, linux-omap, linux-arm-kernel, linux-kernel

On 31 January 2015 at 02:31, Stephen Boyd <sboyd@codeaurora.org> wrote:
> On 01/29, Stephen Boyd wrote:
>> On 01/29/15 05:31, Geert Uytterhoeven wrote:
>> > Hi Tomeu, Mike,
>> >
>> > On Fri, Jan 23, 2015 at 12:03 PM, Tomeu Vizoso
>> > <tomeu.vizoso@collabora.com> wrote:
>> >> --- a/drivers/clk/clk.c
>> >> +++ b/drivers/clk/clk.c
>> >> @@ -2391,25 +2543,24 @@ int __clk_get(struct clk *clk)
>> >>         return 1;
>> >>  }
>> >>
>> >> -static void clk_core_put(struct clk_core *core)
>> >> +void __clk_put(struct clk *clk)
>> >>  {
>> >>         struct module *owner;
>> >>
>> >> -       owner = core->owner;
>> >> +       if (!clk || WARN_ON_ONCE(IS_ERR(clk)))
>> >> +               return;
>> >>
>> >>         clk_prepare_lock();
>> >> -       kref_put(&core->ref, __clk_release);
>> >> +
>> >> +       hlist_del(&clk->child_node);
>> >> +       clk_core_set_rate_nolock(clk->core, clk->core->req_rate);
>> > At this point, clk->core->req_rate is still zero, causing
>> > cpg_div6_clock_round_rate() to be called with a zero "rate" parameter,
>> > e.g. on r8a7791:
>>
>> Hmm.. I wonder if we should assign core->req_rate to be the same as
>> core->rate during __clk_init()? That would make this call to
>> clk_core_set_rate_nolock() a nop in this case.
>>
>
> Here's a patch to do this
>
> ---8<----
> From: Stephen Boyd <sboyd@codeaurora.org>
> Subject: [PATCH] clk: Assign a requested rate by default
>
> We need to assign a requested rate here so that we avoid
> requesting a rate of 0 on clocks when we remove clock consumers.

Hi, this looks good to me.

Reviewed-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>

Thanks,

Tomeu

> Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
> ---
>  drivers/clk/clk.c | 8 +++++---
>  1 file changed, 5 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> index a29daf9edea4..8416ed1c40be 100644
> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> @@ -2142,6 +2142,7 @@ int __clk_init(struct device *dev, struct clk *clk_user)
>         struct clk_core *orphan;
>         struct hlist_node *tmp2;
>         struct clk_core *clk;
> +       unsigned long rate;
>
>         if (!clk_user)
>                 return -EINVAL;
> @@ -2266,12 +2267,13 @@ int __clk_init(struct device *dev, struct clk *clk_user)
>          * then rate is set to zero.
>          */
>         if (clk->ops->recalc_rate)
> -               clk->rate = clk->ops->recalc_rate(clk->hw,
> +               rate = clk->ops->recalc_rate(clk->hw,
>                                 clk_core_get_rate_nolock(clk->parent));
>         else if (clk->parent)
> -               clk->rate = clk->parent->rate;
> +               rate = clk->parent->rate;
>         else
> -               clk->rate = 0;
> +               rate = 0;
> +       clk->rate = clk->req_rate = rate;
>
>         /*
>          * walk the list of orphan clocks and reparent any that are children of
> --
> Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
> a Linux Foundation Collaborative Project
>
> _______________________________________________
> 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] 186+ messages in thread

* [PATCH v13 4/6] clk: Add rate constraints to clocks
@ 2015-01-31 18:36           ` Tomeu Vizoso
  0 siblings, 0 replies; 186+ messages in thread
From: Tomeu Vizoso @ 2015-01-31 18:36 UTC (permalink / raw)
  To: linux-arm-kernel

On 31 January 2015 at 02:31, Stephen Boyd <sboyd@codeaurora.org> wrote:
> On 01/29, Stephen Boyd wrote:
>> On 01/29/15 05:31, Geert Uytterhoeven wrote:
>> > Hi Tomeu, Mike,
>> >
>> > On Fri, Jan 23, 2015 at 12:03 PM, Tomeu Vizoso
>> > <tomeu.vizoso@collabora.com> wrote:
>> >> --- a/drivers/clk/clk.c
>> >> +++ b/drivers/clk/clk.c
>> >> @@ -2391,25 +2543,24 @@ int __clk_get(struct clk *clk)
>> >>         return 1;
>> >>  }
>> >>
>> >> -static void clk_core_put(struct clk_core *core)
>> >> +void __clk_put(struct clk *clk)
>> >>  {
>> >>         struct module *owner;
>> >>
>> >> -       owner = core->owner;
>> >> +       if (!clk || WARN_ON_ONCE(IS_ERR(clk)))
>> >> +               return;
>> >>
>> >>         clk_prepare_lock();
>> >> -       kref_put(&core->ref, __clk_release);
>> >> +
>> >> +       hlist_del(&clk->child_node);
>> >> +       clk_core_set_rate_nolock(clk->core, clk->core->req_rate);
>> > At this point, clk->core->req_rate is still zero, causing
>> > cpg_div6_clock_round_rate() to be called with a zero "rate" parameter,
>> > e.g. on r8a7791:
>>
>> Hmm.. I wonder if we should assign core->req_rate to be the same as
>> core->rate during __clk_init()? That would make this call to
>> clk_core_set_rate_nolock() a nop in this case.
>>
>
> Here's a patch to do this
>
> ---8<----
> From: Stephen Boyd <sboyd@codeaurora.org>
> Subject: [PATCH] clk: Assign a requested rate by default
>
> We need to assign a requested rate here so that we avoid
> requesting a rate of 0 on clocks when we remove clock consumers.

Hi, this looks good to me.

Reviewed-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>

Thanks,

Tomeu

> Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
> ---
>  drivers/clk/clk.c | 8 +++++---
>  1 file changed, 5 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> index a29daf9edea4..8416ed1c40be 100644
> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> @@ -2142,6 +2142,7 @@ int __clk_init(struct device *dev, struct clk *clk_user)
>         struct clk_core *orphan;
>         struct hlist_node *tmp2;
>         struct clk_core *clk;
> +       unsigned long rate;
>
>         if (!clk_user)
>                 return -EINVAL;
> @@ -2266,12 +2267,13 @@ int __clk_init(struct device *dev, struct clk *clk_user)
>          * then rate is set to zero.
>          */
>         if (clk->ops->recalc_rate)
> -               clk->rate = clk->ops->recalc_rate(clk->hw,
> +               rate = clk->ops->recalc_rate(clk->hw,
>                                 clk_core_get_rate_nolock(clk->parent));
>         else if (clk->parent)
> -               clk->rate = clk->parent->rate;
> +               rate = clk->parent->rate;
>         else
> -               clk->rate = 0;
> +               rate = 0;
> +       clk->rate = clk->req_rate = rate;
>
>         /*
>          * walk the list of orphan clocks and reparent any that are children of
> --
> Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
> a Linux Foundation Collaborative Project
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
  2015-01-23 11:03   ` Tomeu Vizoso
  (?)
@ 2015-02-01 21:24     ` Mike Turquette
  -1 siblings, 0 replies; 186+ messages in thread
From: Mike Turquette @ 2015-02-01 21:24 UTC (permalink / raw)
  To: Tomeu Vizoso, linux-kernel, Stephen Boyd
  Cc: Tomeu Vizoso, Paul Walmsley, Tony Lindgren, linux-omap,
	linux-arm-kernel, t-kristo

Quoting Tomeu Vizoso (2015-01-23 03:03:30)
> Moves clock state to struct clk_core, but takes care to change as little API as
> possible.
> 
> struct clk_hw still has a pointer to a struct clk, which is the
> implementation's per-user clk instance, for backwards compatibility.
> 
> The struct clk that clk_get_parent() returns isn't owned by the caller, but by
> the clock implementation, so the former shouldn't call clk_put() on it.
> 
> Because some boards in mach-omap2 still register clocks statically, their clock
> registration had to be updated to take into account that the clock information
> is stored in struct clk_core now.

Tero, Paul & Tony,

Tomeu's patch unveils a problem with omap3_noncore_dpll_enable and
struct dpll_data, namely this snippet from
arch/arm/mach-omap2/dpll3xxx.c:

        parent = __clk_get_parent(hw->clk);

        if (__clk_get_rate(hw->clk) == __clk_get_rate(dd->clk_bypass)) {
                WARN(parent != dd->clk_bypass,
                                "here0, parent name is %s, bypass name is %s\n",
                                __clk_get_name(parent), __clk_get_name(dd->clk_bypass));
                r = _omap3_noncore_dpll_bypass(clk);
        } else {
                WARN(parent != dd->clk_ref,
                                "here1, parent name is %s, ref name is %s\n",
                                __clk_get_name(parent), __clk_get_name(dd->clk_ref));
                r = _omap3_noncore_dpll_lock(clk);
        }

struct dpll_data has members clk_ref and clk_bypass which are struct clk
pointers. This was always a bit of a violation of the clk.h contract
since drivers are not supposed to deref struct clk pointers. Now that we
generate unique pointers for each call to clk_get (clk_ref & clk_bypass
are populated by of_clk_get in ti_clk_register_dpll) then the pointer
comparisons above will never be equal (even if they resolve down to the
same struct clk_core). I added the verbose traces to the WARNs above to
illustrate the point: the names are always the same but the pointers
differ.

AFAICT this doesn't break anything, but booting on OMAP3+ results in
noisy WARNs.

I think the correct fix is to replace clk_bypass and clk_ref pointers
with a simple integer parent_index. In fact we already have this index.
See how the pointers are populated in ti_clk_register_dpll:


        dd->clk_ref = of_clk_get(node, 0);
        dd->clk_bypass = of_clk_get(node, 1);

Tony, the same problem affects the FAPLL code which copy/pastes some of
the DPLL code.

Thoughts?

Regards,
Mike

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

* Re: [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
@ 2015-02-01 21:24     ` Mike Turquette
  0 siblings, 0 replies; 186+ messages in thread
From: Mike Turquette @ 2015-02-01 21:24 UTC (permalink / raw)
  To: linux-kernel, Stephen Boyd
  Cc: Tomeu Vizoso, Paul Walmsley, Tony Lindgren, linux-omap,
	linux-arm-kernel, t-kristo

Quoting Tomeu Vizoso (2015-01-23 03:03:30)
> Moves clock state to struct clk_core, but takes care to change as little API as
> possible.
> 
> struct clk_hw still has a pointer to a struct clk, which is the
> implementation's per-user clk instance, for backwards compatibility.
> 
> The struct clk that clk_get_parent() returns isn't owned by the caller, but by
> the clock implementation, so the former shouldn't call clk_put() on it.
> 
> Because some boards in mach-omap2 still register clocks statically, their clock
> registration had to be updated to take into account that the clock information
> is stored in struct clk_core now.

Tero, Paul & Tony,

Tomeu's patch unveils a problem with omap3_noncore_dpll_enable and
struct dpll_data, namely this snippet from
arch/arm/mach-omap2/dpll3xxx.c:

        parent = __clk_get_parent(hw->clk);

        if (__clk_get_rate(hw->clk) == __clk_get_rate(dd->clk_bypass)) {
                WARN(parent != dd->clk_bypass,
                                "here0, parent name is %s, bypass name is %s\n",
                                __clk_get_name(parent), __clk_get_name(dd->clk_bypass));
                r = _omap3_noncore_dpll_bypass(clk);
        } else {
                WARN(parent != dd->clk_ref,
                                "here1, parent name is %s, ref name is %s\n",
                                __clk_get_name(parent), __clk_get_name(dd->clk_ref));
                r = _omap3_noncore_dpll_lock(clk);
        }

struct dpll_data has members clk_ref and clk_bypass which are struct clk
pointers. This was always a bit of a violation of the clk.h contract
since drivers are not supposed to deref struct clk pointers. Now that we
generate unique pointers for each call to clk_get (clk_ref & clk_bypass
are populated by of_clk_get in ti_clk_register_dpll) then the pointer
comparisons above will never be equal (even if they resolve down to the
same struct clk_core). I added the verbose traces to the WARNs above to
illustrate the point: the names are always the same but the pointers
differ.

AFAICT this doesn't break anything, but booting on OMAP3+ results in
noisy WARNs.

I think the correct fix is to replace clk_bypass and clk_ref pointers
with a simple integer parent_index. In fact we already have this index.
See how the pointers are populated in ti_clk_register_dpll:


        dd->clk_ref = of_clk_get(node, 0);
        dd->clk_bypass = of_clk_get(node, 1);

Tony, the same problem affects the FAPLL code which copy/pastes some of
the DPLL code.

Thoughts?

Regards,
Mike

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

* [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
@ 2015-02-01 21:24     ` Mike Turquette
  0 siblings, 0 replies; 186+ messages in thread
From: Mike Turquette @ 2015-02-01 21:24 UTC (permalink / raw)
  To: linux-arm-kernel

Quoting Tomeu Vizoso (2015-01-23 03:03:30)
> Moves clock state to struct clk_core, but takes care to change as little API as
> possible.
> 
> struct clk_hw still has a pointer to a struct clk, which is the
> implementation's per-user clk instance, for backwards compatibility.
> 
> The struct clk that clk_get_parent() returns isn't owned by the caller, but by
> the clock implementation, so the former shouldn't call clk_put() on it.
> 
> Because some boards in mach-omap2 still register clocks statically, their clock
> registration had to be updated to take into account that the clock information
> is stored in struct clk_core now.

Tero, Paul & Tony,

Tomeu's patch unveils a problem with omap3_noncore_dpll_enable and
struct dpll_data, namely this snippet from
arch/arm/mach-omap2/dpll3xxx.c:

        parent = __clk_get_parent(hw->clk);

        if (__clk_get_rate(hw->clk) == __clk_get_rate(dd->clk_bypass)) {
                WARN(parent != dd->clk_bypass,
                                "here0, parent name is %s, bypass name is %s\n",
                                __clk_get_name(parent), __clk_get_name(dd->clk_bypass));
                r = _omap3_noncore_dpll_bypass(clk);
        } else {
                WARN(parent != dd->clk_ref,
                                "here1, parent name is %s, ref name is %s\n",
                                __clk_get_name(parent), __clk_get_name(dd->clk_ref));
                r = _omap3_noncore_dpll_lock(clk);
        }

struct dpll_data has members clk_ref and clk_bypass which are struct clk
pointers. This was always a bit of a violation of the clk.h contract
since drivers are not supposed to deref struct clk pointers. Now that we
generate unique pointers for each call to clk_get (clk_ref & clk_bypass
are populated by of_clk_get in ti_clk_register_dpll) then the pointer
comparisons above will never be equal (even if they resolve down to the
same struct clk_core). I added the verbose traces to the WARNs above to
illustrate the point: the names are always the same but the pointers
differ.

AFAICT this doesn't break anything, but booting on OMAP3+ results in
noisy WARNs.

I think the correct fix is to replace clk_bypass and clk_ref pointers
with a simple integer parent_index. In fact we already have this index.
See how the pointers are populated in ti_clk_register_dpll:


        dd->clk_ref = of_clk_get(node, 0);
        dd->clk_bypass = of_clk_get(node, 1);

Tony, the same problem affects the FAPLL code which copy/pastes some of
the DPLL code.

Thoughts?

Regards,
Mike

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

* Re: [PATCH v13 4/6] clk: Add rate constraints to clocks
  2015-01-31 18:36           ` Tomeu Vizoso
                               ` (2 preceding siblings ...)
  (?)
@ 2015-02-01 22:18             ` Mike Turquette
  -1 siblings, 0 replies; 186+ messages in thread
From: Mike Turquette @ 2015-02-01 22:18 UTC (permalink / raw)
  To: linux-arm-kernel

Quoting Tomeu Vizoso (2015-01-31 10:36:22)
> On 31 January 2015 at 02:31, Stephen Boyd <sboyd@codeaurora.org> wrote:
> > On 01/29, Stephen Boyd wrote:
> >> On 01/29/15 05:31, Geert Uytterhoeven wrote:
> >> > Hi Tomeu, Mike,
> >> >
> >> > On Fri, Jan 23, 2015 at 12:03 PM, Tomeu Vizoso
> >> > <tomeu.vizoso@collabora.com> wrote:
> >> >> --- a/drivers/clk/clk.c
> >> >> +++ b/drivers/clk/clk.c
> >> >> @@ -2391,25 +2543,24 @@ int __clk_get(struct clk *clk)
> >> >>         return 1;
> >> >>  }
> >> >>
> >> >> -static void clk_core_put(struct clk_core *core)
> >> >> +void __clk_put(struct clk *clk)
> >> >>  {
> >> >>         struct module *owner;
> >> >>
> >> >> -       owner = core->owner;
> >> >> +       if (!clk || WARN_ON_ONCE(IS_ERR(clk)))
> >> >> +               return;
> >> >>
> >> >>         clk_prepare_lock();
> >> >> -       kref_put(&core->ref, __clk_release);
> >> >> +
> >> >> +       hlist_del(&clk->child_node);
> >> >> +       clk_core_set_rate_nolock(clk->core, clk->core->req_rate);
> >> > At this point, clk->core->req_rate is still zero, causing
> >> > cpg_div6_clock_round_rate() to be called with a zero "rate" parameter,
> >> > e.g. on r8a7791:
> >>
> >> Hmm.. I wonder if we should assign core->req_rate to be the same as
> >> core->rate during __clk_init()? That would make this call to
> >> clk_core_set_rate_nolock() a nop in this case.
> >>
> >
> > Here's a patch to do this
> >
> > ---8<----
> > From: Stephen Boyd <sboyd@codeaurora.org>
> > Subject: [PATCH] clk: Assign a requested rate by default
> >
> > We need to assign a requested rate here so that we avoid
> > requesting a rate of 0 on clocks when we remove clock consumers.
> 
> Hi, this looks good to me.
> 
> Reviewed-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>

It seems to fix the total boot failure on OMAPs, and hopefully does the
same for SH Mobile and others. I've squashed this into Tomeu's rate
constraints patch to maintain bisect.

Regards,
Mike

> 
> Thanks,
> 
> Tomeu
> 
> > Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
> > ---
> >  drivers/clk/clk.c | 8 +++++---
> >  1 file changed, 5 insertions(+), 3 deletions(-)
> >
> > diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> > index a29daf9edea4..8416ed1c40be 100644
> > --- a/drivers/clk/clk.c
> > +++ b/drivers/clk/clk.c
> > @@ -2142,6 +2142,7 @@ int __clk_init(struct device *dev, struct clk *clk_user)
> >         struct clk_core *orphan;
> >         struct hlist_node *tmp2;
> >         struct clk_core *clk;
> > +       unsigned long rate;
> >
> >         if (!clk_user)
> >                 return -EINVAL;
> > @@ -2266,12 +2267,13 @@ int __clk_init(struct device *dev, struct clk *clk_user)
> >          * then rate is set to zero.
> >          */
> >         if (clk->ops->recalc_rate)
> > -               clk->rate = clk->ops->recalc_rate(clk->hw,
> > +               rate = clk->ops->recalc_rate(clk->hw,
> >                                 clk_core_get_rate_nolock(clk->parent));
> >         else if (clk->parent)
> > -               clk->rate = clk->parent->rate;
> > +               rate = clk->parent->rate;
> >         else
> > -               clk->rate = 0;
> > +               rate = 0;
> > +       clk->rate = clk->req_rate = rate;
> >
> >         /*
> >          * walk the list of orphan clocks and reparent any that are children of
> > --
> > Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
> > a Linux Foundation Collaborative Project
> >
> > _______________________________________________
> > 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] 186+ messages in thread

* Re: [PATCH v13 4/6] clk: Add rate constraints to clocks
@ 2015-02-01 22:18             ` Mike Turquette
  0 siblings, 0 replies; 186+ messages in thread
From: Mike Turquette @ 2015-02-01 22:18 UTC (permalink / raw)
  To: Tomeu Vizoso, Stephen Boyd
  Cc: Geert Uytterhoeven, Linux MIPS Mailing List, linux-doc,
	Tony Lindgren, Chao Xie, Haojian Zhuang, Boris Brezillon,
	Russell King, Jonathan Corbet, Emilio L??pez, Linux-sh list,
	Alex Elder, Zhangfei Gao, Bintian Wang, Matt Porter, linux-omap,
	linux-arm-kernel, linux-kernel, Ralf Baechle, Tero Kristo,
	Manuel Lauss, Maxime Ripard, Javier Martinez Canillas

Quoting Tomeu Vizoso (2015-01-31 10:36:22)
> On 31 January 2015 at 02:31, Stephen Boyd <sboyd@codeaurora.org> wrote:
> > On 01/29, Stephen Boyd wrote:
> >> On 01/29/15 05:31, Geert Uytterhoeven wrote:
> >> > Hi Tomeu, Mike,
> >> >
> >> > On Fri, Jan 23, 2015 at 12:03 PM, Tomeu Vizoso
> >> > <tomeu.vizoso@collabora.com> wrote:
> >> >> --- a/drivers/clk/clk.c
> >> >> +++ b/drivers/clk/clk.c
> >> >> @@ -2391,25 +2543,24 @@ int __clk_get(struct clk *clk)
> >> >>         return 1;
> >> >>  }
> >> >>
> >> >> -static void clk_core_put(struct clk_core *core)
> >> >> +void __clk_put(struct clk *clk)
> >> >>  {
> >> >>         struct module *owner;
> >> >>
> >> >> -       owner = core->owner;
> >> >> +       if (!clk || WARN_ON_ONCE(IS_ERR(clk)))
> >> >> +               return;
> >> >>
> >> >>         clk_prepare_lock();
> >> >> -       kref_put(&core->ref, __clk_release);
> >> >> +
> >> >> +       hlist_del(&clk->child_node);
> >> >> +       clk_core_set_rate_nolock(clk->core, clk->core->req_rate);
> >> > At this point, clk->core->req_rate is still zero, causing
> >> > cpg_div6_clock_round_rate() to be called with a zero "rate" parameter,
> >> > e.g. on r8a7791:
> >>
> >> Hmm.. I wonder if we should assign core->req_rate to be the same as
> >> core->rate during __clk_init()? That would make this call to
> >> clk_core_set_rate_nolock() a nop in this case.
> >>
> >
> > Here's a patch to do this
> >
> > ---8<----
> > From: Stephen Boyd <sboyd@codeaurora.org>
> > Subject: [PATCH] clk: Assign a requested rate by default
> >
> > We need to assign a requested rate here so that we avoid
> > requesting a rate of 0 on clocks when we remove clock consumers.
> 
> Hi, this looks good to me.
> 
> Reviewed-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>

It seems to fix the total boot failure on OMAPs, and hopefully does the
same for SH Mobile and others. I've squashed this into Tomeu's rate
constraints patch to maintain bisect.

Regards,
Mike

> 
> Thanks,
> 
> Tomeu
> 
> > Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
> > ---
> >  drivers/clk/clk.c | 8 +++++---
> >  1 file changed, 5 insertions(+), 3 deletions(-)
> >
> > diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> > index a29daf9edea4..8416ed1c40be 100644
> > --- a/drivers/clk/clk.c
> > +++ b/drivers/clk/clk.c
> > @@ -2142,6 +2142,7 @@ int __clk_init(struct device *dev, struct clk *clk_user)
> >         struct clk_core *orphan;
> >         struct hlist_node *tmp2;
> >         struct clk_core *clk;
> > +       unsigned long rate;
> >
> >         if (!clk_user)
> >                 return -EINVAL;
> > @@ -2266,12 +2267,13 @@ int __clk_init(struct device *dev, struct clk *clk_user)
> >          * then rate is set to zero.
> >          */
> >         if (clk->ops->recalc_rate)
> > -               clk->rate = clk->ops->recalc_rate(clk->hw,
> > +               rate = clk->ops->recalc_rate(clk->hw,
> >                                 clk_core_get_rate_nolock(clk->parent));
> >         else if (clk->parent)
> > -               clk->rate = clk->parent->rate;
> > +               rate = clk->parent->rate;
> >         else
> > -               clk->rate = 0;
> > +               rate = 0;
> > +       clk->rate = clk->req_rate = rate;
> >
> >         /*
> >          * walk the list of orphan clocks and reparent any that are children of
> > --
> > Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
> > a Linux Foundation Collaborative Project
> >
> > _______________________________________________
> > 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] 186+ messages in thread

* Re: [PATCH v13 4/6] clk: Add rate constraints to clocks
@ 2015-02-01 22:18             ` Mike Turquette
  0 siblings, 0 replies; 186+ messages in thread
From: Mike Turquette @ 2015-02-01 22:18 UTC (permalink / raw)
  To: Tomeu Vizoso, Stephen Boyd
  Cc: Geert Uytterhoeven, Linux MIPS Mailing List, linux-doc,
	Tony Lindgren, Chao Xie, Haojian Zhuang, Boris Brezillon,
	Russell King, Jonathan Corbet, Emilio L??pez, Linux-sh list,
	Alex Elder, Zhangfei Gao, Bintian Wang, Matt Porter, linux-omap,
	linux-arm-kernel, linux-kernel, Ralf Baechle, Tero Kristo,
	Manuel Lauss, Maxime Ripard, Javier Martinez Canillas

Quoting Tomeu Vizoso (2015-01-31 10:36:22)
> On 31 January 2015 at 02:31, Stephen Boyd <sboyd@codeaurora.org> wrote:
> > On 01/29, Stephen Boyd wrote:
> >> On 01/29/15 05:31, Geert Uytterhoeven wrote:
> >> > Hi Tomeu, Mike,
> >> >
> >> > On Fri, Jan 23, 2015 at 12:03 PM, Tomeu Vizoso
> >> > <tomeu.vizoso@collabora.com> wrote:
> >> >> --- a/drivers/clk/clk.c
> >> >> +++ b/drivers/clk/clk.c
> >> >> @@ -2391,25 +2543,24 @@ int __clk_get(struct clk *clk)
> >> >>         return 1;
> >> >>  }
> >> >>
> >> >> -static void clk_core_put(struct clk_core *core)
> >> >> +void __clk_put(struct clk *clk)
> >> >>  {
> >> >>         struct module *owner;
> >> >>
> >> >> -       owner = core->owner;
> >> >> +       if (!clk || WARN_ON_ONCE(IS_ERR(clk)))
> >> >> +               return;
> >> >>
> >> >>         clk_prepare_lock();
> >> >> -       kref_put(&core->ref, __clk_release);
> >> >> +
> >> >> +       hlist_del(&clk->child_node);
> >> >> +       clk_core_set_rate_nolock(clk->core, clk->core->req_rate);
> >> > At this point, clk->core->req_rate is still zero, causing
> >> > cpg_div6_clock_round_rate() to be called with a zero "rate" parameter,
> >> > e.g. on r8a7791:
> >>
> >> Hmm.. I wonder if we should assign core->req_rate to be the same as
> >> core->rate during __clk_init()? That would make this call to
> >> clk_core_set_rate_nolock() a nop in this case.
> >>
> >
> > Here's a patch to do this
> >
> > ---8<----
> > From: Stephen Boyd <sboyd@codeaurora.org>
> > Subject: [PATCH] clk: Assign a requested rate by default
> >
> > We need to assign a requested rate here so that we avoid
> > requesting a rate of 0 on clocks when we remove clock consumers.
> 
> Hi, this looks good to me.
> 
> Reviewed-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>

It seems to fix the total boot failure on OMAPs, and hopefully does the
same for SH Mobile and others. I've squashed this into Tomeu's rate
constraints patch to maintain bisect.

Regards,
Mike

> 
> Thanks,
> 
> Tomeu
> 
> > Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
> > ---
> >  drivers/clk/clk.c | 8 +++++---
> >  1 file changed, 5 insertions(+), 3 deletions(-)
> >
> > diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> > index a29daf9edea4..8416ed1c40be 100644
> > --- a/drivers/clk/clk.c
> > +++ b/drivers/clk/clk.c
> > @@ -2142,6 +2142,7 @@ int __clk_init(struct device *dev, struct clk *clk_user)
> >         struct clk_core *orphan;
> >         struct hlist_node *tmp2;
> >         struct clk_core *clk;
> > +       unsigned long rate;
> >
> >         if (!clk_user)
> >                 return -EINVAL;
> > @@ -2266,12 +2267,13 @@ int __clk_init(struct device *dev, struct clk *clk_user)
> >          * then rate is set to zero.
> >          */
> >         if (clk->ops->recalc_rate)
> > -               clk->rate = clk->ops->recalc_rate(clk->hw,
> > +               rate = clk->ops->recalc_rate(clk->hw,
> >                                 clk_core_get_rate_nolock(clk->parent));
> >         else if (clk->parent)
> > -               clk->rate = clk->parent->rate;
> > +               rate = clk->parent->rate;
> >         else
> > -               clk->rate = 0;
> > +               rate = 0;
> > +       clk->rate = clk->req_rate = rate;
> >
> >         /*
> >          * walk the list of orphan clocks and reparent any that are children of
> > --
> > Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
> > a Linux Foundation Collaborative Project
> >
> > _______________________________________________
> > 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] 186+ messages in thread

* Re: [PATCH v13 4/6] clk: Add rate constraints to clocks
@ 2015-02-01 22:18             ` Mike Turquette
  0 siblings, 0 replies; 186+ messages in thread
From: Mike Turquette @ 2015-02-01 22:18 UTC (permalink / raw)
  To: Tomeu Vizoso, Stephen Boyd
  Cc: Geert Uytterhoeven, Linux MIPS Mailing List, linux-doc,
	Tony Lindgren, Chao Xie, Haojian Zhuang, Boris Brezillon,
	Russell King, Jonathan Corbet, Emilio L??pez, Linux-sh list,
	Alex Elder, Zhangfei Gao, Bintian Wang, Matt Porter, linux-omap,
	linux-arm-kernel, linux-kernel, Ralf Baechle

Quoting Tomeu Vizoso (2015-01-31 10:36:22)
> On 31 January 2015 at 02:31, Stephen Boyd <sboyd@codeaurora.org> wrote:
> > On 01/29, Stephen Boyd wrote:
> >> On 01/29/15 05:31, Geert Uytterhoeven wrote:
> >> > Hi Tomeu, Mike,
> >> >
> >> > On Fri, Jan 23, 2015 at 12:03 PM, Tomeu Vizoso
> >> > <tomeu.vizoso@collabora.com> wrote:
> >> >> --- a/drivers/clk/clk.c
> >> >> +++ b/drivers/clk/clk.c
> >> >> @@ -2391,25 +2543,24 @@ int __clk_get(struct clk *clk)
> >> >>         return 1;
> >> >>  }
> >> >>
> >> >> -static void clk_core_put(struct clk_core *core)
> >> >> +void __clk_put(struct clk *clk)
> >> >>  {
> >> >>         struct module *owner;
> >> >>
> >> >> -       owner = core->owner;
> >> >> +       if (!clk || WARN_ON_ONCE(IS_ERR(clk)))
> >> >> +               return;
> >> >>
> >> >>         clk_prepare_lock();
> >> >> -       kref_put(&core->ref, __clk_release);
> >> >> +
> >> >> +       hlist_del(&clk->child_node);
> >> >> +       clk_core_set_rate_nolock(clk->core, clk->core->req_rate);
> >> > At this point, clk->core->req_rate is still zero, causing
> >> > cpg_div6_clock_round_rate() to be called with a zero "rate" parameter,
> >> > e.g. on r8a7791:
> >>
> >> Hmm.. I wonder if we should assign core->req_rate to be the same as
> >> core->rate during __clk_init()? That would make this call to
> >> clk_core_set_rate_nolock() a nop in this case.
> >>
> >
> > Here's a patch to do this
> >
> > ---8<----
> > From: Stephen Boyd <sboyd@codeaurora.org>
> > Subject: [PATCH] clk: Assign a requested rate by default
> >
> > We need to assign a requested rate here so that we avoid
> > requesting a rate of 0 on clocks when we remove clock consumers.
> 
> Hi, this looks good to me.
> 
> Reviewed-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>

It seems to fix the total boot failure on OMAPs, and hopefully does the
same for SH Mobile and others. I've squashed this into Tomeu's rate
constraints patch to maintain bisect.

Regards,
Mike

> 
> Thanks,
> 
> Tomeu
> 
> > Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
> > ---
> >  drivers/clk/clk.c | 8 +++++---
> >  1 file changed, 5 insertions(+), 3 deletions(-)
> >
> > diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> > index a29daf9edea4..8416ed1c40be 100644
> > --- a/drivers/clk/clk.c
> > +++ b/drivers/clk/clk.c
> > @@ -2142,6 +2142,7 @@ int __clk_init(struct device *dev, struct clk *clk_user)
> >         struct clk_core *orphan;
> >         struct hlist_node *tmp2;
> >         struct clk_core *clk;
> > +       unsigned long rate;
> >
> >         if (!clk_user)
> >                 return -EINVAL;
> > @@ -2266,12 +2267,13 @@ int __clk_init(struct device *dev, struct clk *clk_user)
> >          * then rate is set to zero.
> >          */
> >         if (clk->ops->recalc_rate)
> > -               clk->rate = clk->ops->recalc_rate(clk->hw,
> > +               rate = clk->ops->recalc_rate(clk->hw,
> >                                 clk_core_get_rate_nolock(clk->parent));
> >         else if (clk->parent)
> > -               clk->rate = clk->parent->rate;
> > +               rate = clk->parent->rate;
> >         else
> > -               clk->rate = 0;
> > +               rate = 0;
> > +       clk->rate = clk->req_rate = rate;
> >
> >         /*
> >          * walk the list of orphan clocks and reparent any that are children of
> > --
> > Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
> > a Linux Foundation Collaborative Project
> >
> > _______________________________________________
> > 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] 186+ messages in thread

* [PATCH v13 4/6] clk: Add rate constraints to clocks
@ 2015-02-01 22:18             ` Mike Turquette
  0 siblings, 0 replies; 186+ messages in thread
From: Mike Turquette @ 2015-02-01 22:18 UTC (permalink / raw)
  To: linux-arm-kernel

Quoting Tomeu Vizoso (2015-01-31 10:36:22)
> On 31 January 2015 at 02:31, Stephen Boyd <sboyd@codeaurora.org> wrote:
> > On 01/29, Stephen Boyd wrote:
> >> On 01/29/15 05:31, Geert Uytterhoeven wrote:
> >> > Hi Tomeu, Mike,
> >> >
> >> > On Fri, Jan 23, 2015 at 12:03 PM, Tomeu Vizoso
> >> > <tomeu.vizoso@collabora.com> wrote:
> >> >> --- a/drivers/clk/clk.c
> >> >> +++ b/drivers/clk/clk.c
> >> >> @@ -2391,25 +2543,24 @@ int __clk_get(struct clk *clk)
> >> >>         return 1;
> >> >>  }
> >> >>
> >> >> -static void clk_core_put(struct clk_core *core)
> >> >> +void __clk_put(struct clk *clk)
> >> >>  {
> >> >>         struct module *owner;
> >> >>
> >> >> -       owner = core->owner;
> >> >> +       if (!clk || WARN_ON_ONCE(IS_ERR(clk)))
> >> >> +               return;
> >> >>
> >> >>         clk_prepare_lock();
> >> >> -       kref_put(&core->ref, __clk_release);
> >> >> +
> >> >> +       hlist_del(&clk->child_node);
> >> >> +       clk_core_set_rate_nolock(clk->core, clk->core->req_rate);
> >> > At this point, clk->core->req_rate is still zero, causing
> >> > cpg_div6_clock_round_rate() to be called with a zero "rate" parameter,
> >> > e.g. on r8a7791:
> >>
> >> Hmm.. I wonder if we should assign core->req_rate to be the same as
> >> core->rate during __clk_init()? That would make this call to
> >> clk_core_set_rate_nolock() a nop in this case.
> >>
> >
> > Here's a patch to do this
> >
> > ---8<----
> > From: Stephen Boyd <sboyd@codeaurora.org>
> > Subject: [PATCH] clk: Assign a requested rate by default
> >
> > We need to assign a requested rate here so that we avoid
> > requesting a rate of 0 on clocks when we remove clock consumers.
> 
> Hi, this looks good to me.
> 
> Reviewed-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>

It seems to fix the total boot failure on OMAPs, and hopefully does the
same for SH Mobile and others. I've squashed this into Tomeu's rate
constraints patch to maintain bisect.

Regards,
Mike

> 
> Thanks,
> 
> Tomeu
> 
> > Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
> > ---
> >  drivers/clk/clk.c | 8 +++++---
> >  1 file changed, 5 insertions(+), 3 deletions(-)
> >
> > diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> > index a29daf9edea4..8416ed1c40be 100644
> > --- a/drivers/clk/clk.c
> > +++ b/drivers/clk/clk.c
> > @@ -2142,6 +2142,7 @@ int __clk_init(struct device *dev, struct clk *clk_user)
> >         struct clk_core *orphan;
> >         struct hlist_node *tmp2;
> >         struct clk_core *clk;
> > +       unsigned long rate;
> >
> >         if (!clk_user)
> >                 return -EINVAL;
> > @@ -2266,12 +2267,13 @@ int __clk_init(struct device *dev, struct clk *clk_user)
> >          * then rate is set to zero.
> >          */
> >         if (clk->ops->recalc_rate)
> > -               clk->rate = clk->ops->recalc_rate(clk->hw,
> > +               rate = clk->ops->recalc_rate(clk->hw,
> >                                 clk_core_get_rate_nolock(clk->parent));
> >         else if (clk->parent)
> > -               clk->rate = clk->parent->rate;
> > +               rate = clk->parent->rate;
> >         else
> > -               clk->rate = 0;
> > +               rate = 0;
> > +       clk->rate = clk->req_rate = rate;
> >
> >         /*
> >          * walk the list of orphan clocks and reparent any that are children of
> > --
> > Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
> > a Linux Foundation Collaborative Project
> >
> > _______________________________________________
> > linux-arm-kernel mailing list
> > linux-arm-kernel at lists.infradead.org
> > http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v13 4/6] clk: Add rate constraints to clocks
  2015-02-01 22:18             ` Mike Turquette
                                 ` (2 preceding siblings ...)
  (?)
@ 2015-02-02  7:59               ` Geert Uytterhoeven
  -1 siblings, 0 replies; 186+ messages in thread
From: Geert Uytterhoeven @ 2015-02-02  7:59 UTC (permalink / raw)
  To: linux-arm-kernel

On Sun, Feb 1, 2015 at 11:18 PM, Mike Turquette <mturquette@linaro.org> wrote:
> Quoting Tomeu Vizoso (2015-01-31 10:36:22)
>> On 31 January 2015 at 02:31, Stephen Boyd <sboyd@codeaurora.org> wrote:
>> > On 01/29, Stephen Boyd wrote:
>> >> On 01/29/15 05:31, Geert Uytterhoeven wrote:
>> >> > Hi Tomeu, Mike,
>> >> >
>> >> > On Fri, Jan 23, 2015 at 12:03 PM, Tomeu Vizoso
>> >> > <tomeu.vizoso@collabora.com> wrote:
>> >> >> --- a/drivers/clk/clk.c
>> >> >> +++ b/drivers/clk/clk.c
>> >> >> @@ -2391,25 +2543,24 @@ int __clk_get(struct clk *clk)
>> >> >>         return 1;
>> >> >>  }
>> >> >>
>> >> >> -static void clk_core_put(struct clk_core *core)
>> >> >> +void __clk_put(struct clk *clk)
>> >> >>  {
>> >> >>         struct module *owner;
>> >> >>
>> >> >> -       owner = core->owner;
>> >> >> +       if (!clk || WARN_ON_ONCE(IS_ERR(clk)))
>> >> >> +               return;
>> >> >>
>> >> >>         clk_prepare_lock();
>> >> >> -       kref_put(&core->ref, __clk_release);
>> >> >> +
>> >> >> +       hlist_del(&clk->child_node);
>> >> >> +       clk_core_set_rate_nolock(clk->core, clk->core->req_rate);
>> >> > At this point, clk->core->req_rate is still zero, causing
>> >> > cpg_div6_clock_round_rate() to be called with a zero "rate" parameter,
>> >> > e.g. on r8a7791:
>> >>
>> >> Hmm.. I wonder if we should assign core->req_rate to be the same as
>> >> core->rate during __clk_init()? That would make this call to
>> >> clk_core_set_rate_nolock() a nop in this case.
>> >>
>> >
>> > Here's a patch to do this
>> >
>> > ---8<----
>> > From: Stephen Boyd <sboyd@codeaurora.org>
>> > Subject: [PATCH] clk: Assign a requested rate by default
>> >
>> > We need to assign a requested rate here so that we avoid
>> > requesting a rate of 0 on clocks when we remove clock consumers.
>>
>> Hi, this looks good to me.
>>
>> Reviewed-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
>
> It seems to fix the total boot failure on OMAPs, and hopefully does the
> same for SH Mobile and others. I've squashed this into Tomeu's rate
> constraints patch to maintain bisect.

Yes, it fixes shmobile. .round_rate() is now called with a sane value of rate.

Thanks!

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

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

* Re: [PATCH v13 4/6] clk: Add rate constraints to clocks
@ 2015-02-02  7:59               ` Geert Uytterhoeven
  0 siblings, 0 replies; 186+ messages in thread
From: Geert Uytterhoeven @ 2015-02-02  7:59 UTC (permalink / raw)
  To: Mike Turquette
  Cc: Tomeu Vizoso, Stephen Boyd, Linux MIPS Mailing List, linux-doc,
	Tony Lindgren, Chao Xie, Haojian Zhuang, Boris Brezillon,
	Russell King, Jonathan Corbet, Emilio L??pez, Linux-sh list,
	Alex Elder, Zhangfei Gao, Bintian Wang, Matt Porter, linux-omap,
	linux-arm-kernel, linux-kernel, Ralf Baechle, Tero Kristo,
	Manuel Lauss, Maxime Ripard, Javier Martinez Canillas

On Sun, Feb 1, 2015 at 11:18 PM, Mike Turquette <mturquette@linaro.org> wrote:
> Quoting Tomeu Vizoso (2015-01-31 10:36:22)
>> On 31 January 2015 at 02:31, Stephen Boyd <sboyd@codeaurora.org> wrote:
>> > On 01/29, Stephen Boyd wrote:
>> >> On 01/29/15 05:31, Geert Uytterhoeven wrote:
>> >> > Hi Tomeu, Mike,
>> >> >
>> >> > On Fri, Jan 23, 2015 at 12:03 PM, Tomeu Vizoso
>> >> > <tomeu.vizoso@collabora.com> wrote:
>> >> >> --- a/drivers/clk/clk.c
>> >> >> +++ b/drivers/clk/clk.c
>> >> >> @@ -2391,25 +2543,24 @@ int __clk_get(struct clk *clk)
>> >> >>         return 1;
>> >> >>  }
>> >> >>
>> >> >> -static void clk_core_put(struct clk_core *core)
>> >> >> +void __clk_put(struct clk *clk)
>> >> >>  {
>> >> >>         struct module *owner;
>> >> >>
>> >> >> -       owner = core->owner;
>> >> >> +       if (!clk || WARN_ON_ONCE(IS_ERR(clk)))
>> >> >> +               return;
>> >> >>
>> >> >>         clk_prepare_lock();
>> >> >> -       kref_put(&core->ref, __clk_release);
>> >> >> +
>> >> >> +       hlist_del(&clk->child_node);
>> >> >> +       clk_core_set_rate_nolock(clk->core, clk->core->req_rate);
>> >> > At this point, clk->core->req_rate is still zero, causing
>> >> > cpg_div6_clock_round_rate() to be called with a zero "rate" parameter,
>> >> > e.g. on r8a7791:
>> >>
>> >> Hmm.. I wonder if we should assign core->req_rate to be the same as
>> >> core->rate during __clk_init()? That would make this call to
>> >> clk_core_set_rate_nolock() a nop in this case.
>> >>
>> >
>> > Here's a patch to do this
>> >
>> > ---8<----
>> > From: Stephen Boyd <sboyd@codeaurora.org>
>> > Subject: [PATCH] clk: Assign a requested rate by default
>> >
>> > We need to assign a requested rate here so that we avoid
>> > requesting a rate of 0 on clocks when we remove clock consumers.
>>
>> Hi, this looks good to me.
>>
>> Reviewed-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
>
> It seems to fix the total boot failure on OMAPs, and hopefully does the
> same for SH Mobile and others. I've squashed this into Tomeu's rate
> constraints patch to maintain bisect.

Yes, it fixes shmobile. .round_rate() is now called with a sane value of rate.

Thanks!

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

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

* Re: [PATCH v13 4/6] clk: Add rate constraints to clocks
@ 2015-02-02  7:59               ` Geert Uytterhoeven
  0 siblings, 0 replies; 186+ messages in thread
From: Geert Uytterhoeven @ 2015-02-02  7:59 UTC (permalink / raw)
  To: Mike Turquette
  Cc: Tomeu Vizoso, Stephen Boyd, Linux MIPS Mailing List, linux-doc,
	Tony Lindgren, Chao Xie, Haojian Zhuang, Boris Brezillon,
	Russell King, Jonathan Corbet, Emilio L??pez, Linux-sh list,
	Alex Elder, Zhangfei Gao, Bintian Wang, Matt Porter, linux-omap,
	linux-arm-kernel, linux-kernel, Ralf Baechle, Tero Kristo,
	Manuel Lauss, Maxime Ripard, Javier Martinez Canillas

On Sun, Feb 1, 2015 at 11:18 PM, Mike Turquette <mturquette@linaro.org> wrote:
> Quoting Tomeu Vizoso (2015-01-31 10:36:22)
>> On 31 January 2015 at 02:31, Stephen Boyd <sboyd@codeaurora.org> wrote:
>> > On 01/29, Stephen Boyd wrote:
>> >> On 01/29/15 05:31, Geert Uytterhoeven wrote:
>> >> > Hi Tomeu, Mike,
>> >> >
>> >> > On Fri, Jan 23, 2015 at 12:03 PM, Tomeu Vizoso
>> >> > <tomeu.vizoso@collabora.com> wrote:
>> >> >> --- a/drivers/clk/clk.c
>> >> >> +++ b/drivers/clk/clk.c
>> >> >> @@ -2391,25 +2543,24 @@ int __clk_get(struct clk *clk)
>> >> >>         return 1;
>> >> >>  }
>> >> >>
>> >> >> -static void clk_core_put(struct clk_core *core)
>> >> >> +void __clk_put(struct clk *clk)
>> >> >>  {
>> >> >>         struct module *owner;
>> >> >>
>> >> >> -       owner = core->owner;
>> >> >> +       if (!clk || WARN_ON_ONCE(IS_ERR(clk)))
>> >> >> +               return;
>> >> >>
>> >> >>         clk_prepare_lock();
>> >> >> -       kref_put(&core->ref, __clk_release);
>> >> >> +
>> >> >> +       hlist_del(&clk->child_node);
>> >> >> +       clk_core_set_rate_nolock(clk->core, clk->core->req_rate);
>> >> > At this point, clk->core->req_rate is still zero, causing
>> >> > cpg_div6_clock_round_rate() to be called with a zero "rate" parameter,
>> >> > e.g. on r8a7791:
>> >>
>> >> Hmm.. I wonder if we should assign core->req_rate to be the same as
>> >> core->rate during __clk_init()? That would make this call to
>> >> clk_core_set_rate_nolock() a nop in this case.
>> >>
>> >
>> > Here's a patch to do this
>> >
>> > ---8<----
>> > From: Stephen Boyd <sboyd@codeaurora.org>
>> > Subject: [PATCH] clk: Assign a requested rate by default
>> >
>> > We need to assign a requested rate here so that we avoid
>> > requesting a rate of 0 on clocks when we remove clock consumers.
>>
>> Hi, this looks good to me.
>>
>> Reviewed-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
>
> It seems to fix the total boot failure on OMAPs, and hopefully does the
> same for SH Mobile and others. I've squashed this into Tomeu's rate
> constraints patch to maintain bisect.

Yes, it fixes shmobile. .round_rate() is now called with a sane value of rate.

Thanks!

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

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

* Re: [PATCH v13 4/6] clk: Add rate constraints to clocks
@ 2015-02-02  7:59               ` Geert Uytterhoeven
  0 siblings, 0 replies; 186+ messages in thread
From: Geert Uytterhoeven @ 2015-02-02  7:59 UTC (permalink / raw)
  To: Mike Turquette
  Cc: Tomeu Vizoso, Stephen Boyd, Linux MIPS Mailing List, linux-doc,
	Tony Lindgren, Chao Xie, Haojian Zhuang, Boris Brezillon,
	Russell King, Jonathan Corbet, Emilio L??pez, Linux-sh list,
	Alex Elder, Zhangfei Gao, Bintian Wang, Matt Porter, linux-omap,
	linux-arm-kernel, linux-kernel, Ralf Baechle

On Sun, Feb 1, 2015 at 11:18 PM, Mike Turquette <mturquette@linaro.org> wrote:
> Quoting Tomeu Vizoso (2015-01-31 10:36:22)
>> On 31 January 2015 at 02:31, Stephen Boyd <sboyd@codeaurora.org> wrote:
>> > On 01/29, Stephen Boyd wrote:
>> >> On 01/29/15 05:31, Geert Uytterhoeven wrote:
>> >> > Hi Tomeu, Mike,
>> >> >
>> >> > On Fri, Jan 23, 2015 at 12:03 PM, Tomeu Vizoso
>> >> > <tomeu.vizoso@collabora.com> wrote:
>> >> >> --- a/drivers/clk/clk.c
>> >> >> +++ b/drivers/clk/clk.c
>> >> >> @@ -2391,25 +2543,24 @@ int __clk_get(struct clk *clk)
>> >> >>         return 1;
>> >> >>  }
>> >> >>
>> >> >> -static void clk_core_put(struct clk_core *core)
>> >> >> +void __clk_put(struct clk *clk)
>> >> >>  {
>> >> >>         struct module *owner;
>> >> >>
>> >> >> -       owner = core->owner;
>> >> >> +       if (!clk || WARN_ON_ONCE(IS_ERR(clk)))
>> >> >> +               return;
>> >> >>
>> >> >>         clk_prepare_lock();
>> >> >> -       kref_put(&core->ref, __clk_release);
>> >> >> +
>> >> >> +       hlist_del(&clk->child_node);
>> >> >> +       clk_core_set_rate_nolock(clk->core, clk->core->req_rate);
>> >> > At this point, clk->core->req_rate is still zero, causing
>> >> > cpg_div6_clock_round_rate() to be called with a zero "rate" parameter,
>> >> > e.g. on r8a7791:
>> >>
>> >> Hmm.. I wonder if we should assign core->req_rate to be the same as
>> >> core->rate during __clk_init()? That would make this call to
>> >> clk_core_set_rate_nolock() a nop in this case.
>> >>
>> >
>> > Here's a patch to do this
>> >
>> > ---8<----
>> > From: Stephen Boyd <sboyd@codeaurora.org>
>> > Subject: [PATCH] clk: Assign a requested rate by default
>> >
>> > We need to assign a requested rate here so that we avoid
>> > requesting a rate of 0 on clocks when we remove clock consumers.
>>
>> Hi, this looks good to me.
>>
>> Reviewed-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
>
> It seems to fix the total boot failure on OMAPs, and hopefully does the
> same for SH Mobile and others. I've squashed this into Tomeu's rate
> constraints patch to maintain bisect.

Yes, it fixes shmobile. .round_rate() is now called with a sane value of rate.

Thanks!

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

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

* [PATCH v13 4/6] clk: Add rate constraints to clocks
@ 2015-02-02  7:59               ` Geert Uytterhoeven
  0 siblings, 0 replies; 186+ messages in thread
From: Geert Uytterhoeven @ 2015-02-02  7:59 UTC (permalink / raw)
  To: linux-arm-kernel

On Sun, Feb 1, 2015 at 11:18 PM, Mike Turquette <mturquette@linaro.org> wrote:
> Quoting Tomeu Vizoso (2015-01-31 10:36:22)
>> On 31 January 2015 at 02:31, Stephen Boyd <sboyd@codeaurora.org> wrote:
>> > On 01/29, Stephen Boyd wrote:
>> >> On 01/29/15 05:31, Geert Uytterhoeven wrote:
>> >> > Hi Tomeu, Mike,
>> >> >
>> >> > On Fri, Jan 23, 2015 at 12:03 PM, Tomeu Vizoso
>> >> > <tomeu.vizoso@collabora.com> wrote:
>> >> >> --- a/drivers/clk/clk.c
>> >> >> +++ b/drivers/clk/clk.c
>> >> >> @@ -2391,25 +2543,24 @@ int __clk_get(struct clk *clk)
>> >> >>         return 1;
>> >> >>  }
>> >> >>
>> >> >> -static void clk_core_put(struct clk_core *core)
>> >> >> +void __clk_put(struct clk *clk)
>> >> >>  {
>> >> >>         struct module *owner;
>> >> >>
>> >> >> -       owner = core->owner;
>> >> >> +       if (!clk || WARN_ON_ONCE(IS_ERR(clk)))
>> >> >> +               return;
>> >> >>
>> >> >>         clk_prepare_lock();
>> >> >> -       kref_put(&core->ref, __clk_release);
>> >> >> +
>> >> >> +       hlist_del(&clk->child_node);
>> >> >> +       clk_core_set_rate_nolock(clk->core, clk->core->req_rate);
>> >> > At this point, clk->core->req_rate is still zero, causing
>> >> > cpg_div6_clock_round_rate() to be called with a zero "rate" parameter,
>> >> > e.g. on r8a7791:
>> >>
>> >> Hmm.. I wonder if we should assign core->req_rate to be the same as
>> >> core->rate during __clk_init()? That would make this call to
>> >> clk_core_set_rate_nolock() a nop in this case.
>> >>
>> >
>> > Here's a patch to do this
>> >
>> > ---8<----
>> > From: Stephen Boyd <sboyd@codeaurora.org>
>> > Subject: [PATCH] clk: Assign a requested rate by default
>> >
>> > We need to assign a requested rate here so that we avoid
>> > requesting a rate of 0 on clocks when we remove clock consumers.
>>
>> Hi, this looks good to me.
>>
>> Reviewed-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
>
> It seems to fix the total boot failure on OMAPs, and hopefully does the
> same for SH Mobile and others. I've squashed this into Tomeu's rate
> constraints patch to maintain bisect.

Yes, it fixes shmobile. .round_rate() is now called with a sane value of rate.

Thanks!

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert at linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

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

* Re: [PATCH v13 4/6] clk: Add rate constraints to clocks
  2015-02-02  7:59               ` Geert Uytterhoeven
                                   ` (2 preceding siblings ...)
  (?)
@ 2015-02-02 16:12                 ` Tony Lindgren
  -1 siblings, 0 replies; 186+ messages in thread
From: Tony Lindgren @ 2015-02-02 16:12 UTC (permalink / raw)
  To: linux-arm-kernel

* Geert Uytterhoeven <geert@linux-m68k.org> [150202 00:03]:
> On Sun, Feb 1, 2015 at 11:18 PM, Mike Turquette <mturquette@linaro.org> wrote:
> > Quoting Tomeu Vizoso (2015-01-31 10:36:22)
> >> On 31 January 2015 at 02:31, Stephen Boyd <sboyd@codeaurora.org> wrote:
> >> > On 01/29, Stephen Boyd wrote:
> >> >> On 01/29/15 05:31, Geert Uytterhoeven wrote:
> >> >> > Hi Tomeu, Mike,
> >> >> >
> >> >> > On Fri, Jan 23, 2015 at 12:03 PM, Tomeu Vizoso
> >> >> > <tomeu.vizoso@collabora.com> wrote:
> >> >> >> --- a/drivers/clk/clk.c
> >> >> >> +++ b/drivers/clk/clk.c
> >> >> >> @@ -2391,25 +2543,24 @@ int __clk_get(struct clk *clk)
> >> >> >>         return 1;
> >> >> >>  }
> >> >> >>
> >> >> >> -static void clk_core_put(struct clk_core *core)
> >> >> >> +void __clk_put(struct clk *clk)
> >> >> >>  {
> >> >> >>         struct module *owner;
> >> >> >>
> >> >> >> -       owner = core->owner;
> >> >> >> +       if (!clk || WARN_ON_ONCE(IS_ERR(clk)))
> >> >> >> +               return;
> >> >> >>
> >> >> >>         clk_prepare_lock();
> >> >> >> -       kref_put(&core->ref, __clk_release);
> >> >> >> +
> >> >> >> +       hlist_del(&clk->child_node);
> >> >> >> +       clk_core_set_rate_nolock(clk->core, clk->core->req_rate);
> >> >> > At this point, clk->core->req_rate is still zero, causing
> >> >> > cpg_div6_clock_round_rate() to be called with a zero "rate" parameter,
> >> >> > e.g. on r8a7791:
> >> >>
> >> >> Hmm.. I wonder if we should assign core->req_rate to be the same as
> >> >> core->rate during __clk_init()? That would make this call to
> >> >> clk_core_set_rate_nolock() a nop in this case.
> >> >>
> >> >
> >> > Here's a patch to do this
> >> >
> >> > ---8<----
> >> > From: Stephen Boyd <sboyd@codeaurora.org>
> >> > Subject: [PATCH] clk: Assign a requested rate by default
> >> >
> >> > We need to assign a requested rate here so that we avoid
> >> > requesting a rate of 0 on clocks when we remove clock consumers.
> >>
> >> Hi, this looks good to me.
> >>
> >> Reviewed-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
> >
> > It seems to fix the total boot failure on OMAPs, and hopefully does the
> > same for SH Mobile and others. I've squashed this into Tomeu's rate
> > constraints patch to maintain bisect.
> 
> Yes, it fixes shmobile. .round_rate() is now called with a sane value of rate.

Looks like next-20150202 now produces tons of the following errors,
these from omap4:

[   10.568206] ------------[ cut here ]------------
[   10.568206] WARNING: CPU: 0 PID: 1 at drivers/clk/clk.c:925 clk_disable+0x28/0x34()
[   10.568237] Modules linked in:
[   10.568237] CPU: 0 PID: 1 Comm: swapper/0 Tainted: G        W       3.19.0-rc6-next-20150202 #2037
[   10.568237] Hardware name: Generic OMAP4 (Flattened Device Tree)
[   10.568267] [<c0015bdc>] (unwind_backtrace) from [<c001222c>] (show_stack+0x10/0x14)
[   10.568267] [<c001222c>] (show_stack) from [<c05d2014>] (dump_stack+0x84/0x9c)
[   10.568267] [<c05d2014>] (dump_stack) from [<c003ea90>] (warn_slowpath_common+0x7c/0xb8)
[   10.568298] [<c003ea90>] (warn_slowpath_common) from [<c003eb68>] (warn_slowpath_null+0x1c/0x24)
[   10.568298] [<c003eb68>] (warn_slowpath_null) from [<c04c1ffc>] (clk_disable+0x28/0x34)
[   10.568328] [<c04c1ffc>] (clk_disable) from [<c0025b3c>] (_disable_clocks+0x18/0x68)
[   10.568328] [<c0025b3c>] (_disable_clocks) from [<c0026f14>] (_idle+0x10c/0x214)
[   10.568328] [<c0026f14>] (_idle) from [<c0855fac>] (_setup+0x338/0x410)
[   10.568359] [<c0855fac>] (_setup) from [<c0027360>] (omap_hwmod_for_each+0x34/0x60)
[   10.568359] [<c0027360>] (omap_hwmod_for_each) from [<c08563c4>] (__omap_hwmod_setup_all+0x30/0x40)
[   10.568389] [<c08563c4>] (__omap_hwmod_setup_all) from [<c0008a04>] (do_one_initcall+0x80/0x1dc)
[   10.568389] [<c0008a04>] (do_one_initcall) from [<c0848ea0>] (kernel_init_freeable+0x204/0x2d0)
[   10.568420] [<c0848ea0>] (kernel_init_freeable) from [<c05cdab8>] (kernel_init+0x8/0xec)
[   10.568420] [<c05cdab8>] (kernel_init) from [<c000e790>] (ret_from_fork+0x14/0x24)
[   10.568420] ---[ end trace cb88537fdc8fa211 ]---


[   10.568450] ------------[ cut here ]------------
[   10.568450] WARNING: CPU: 0 PID: 1 at arch/arm/mach-omap2/dpll3xxx.c:436 omap3_noncore_dpll_enable+0xdc/0
x10c()
[   10.568450] Modules linked in:
[   10.568481] CPU: 0 PID: 1 Comm: swapper/0 Tainted: G        W       3.19.0-rc6-next-20150202 #2037
[   10.568481] Hardware name: Generic OMAP4 (Flattened Device Tree)
[   10.568481] [<c0015bdc>] (unwind_backtrace) from [<c001222c>] (show_stack+0x10/0x14)
[   10.568511] [<c001222c>] (show_stack) from [<c05d2014>] (dump_stack+0x84/0x9c)
[   10.568511] [<c05d2014>] (dump_stack) from [<c003ea90>] (warn_slowpath_common+0x7c/0xb8)
[   10.568511] [<c003ea90>] (warn_slowpath_common) from [<c003eb68>] (warn_slowpath_null+0x1c/0x24)
[   10.568542] [<c003eb68>] (warn_slowpath_null) from [<c0035800>] (omap3_noncore_dpll_enable+0xdc/0x10c)
[   10.568542] [<c0035800>] (omap3_noncore_dpll_enable) from [<c04c0a10>] (clk_core_enable+0x60/0x9c)
[   10.568572] [<c04c0a10>] (clk_core_enable) from [<c04c09f0>] (clk_core_enable+0x40/0x9c)
[   10.568572] ---[ end trace cb88537fdc8fa212 ]---
...

Regards,

Tony

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

* Re: [PATCH v13 4/6] clk: Add rate constraints to clocks
@ 2015-02-02 16:12                 ` Tony Lindgren
  0 siblings, 0 replies; 186+ messages in thread
From: Tony Lindgren @ 2015-02-02 16:12 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Mike Turquette, Tomeu Vizoso, Stephen Boyd,
	Linux MIPS Mailing List, linux-doc, Chao Xie, Haojian Zhuang,
	Boris Brezillon, Russell King, Jonathan Corbet, Emilio L??pez,
	Linux-sh list, Alex Elder, Zhangfei Gao, Bintian Wang,
	Matt Porter, linux-omap, linux-arm-kernel, linux-kernel,
	Ralf Baechle, Tero Kristo, Manuel Lauss, Maxime Ripard,
	Javier Martinez Canillas

* Geert Uytterhoeven <geert@linux-m68k.org> [150202 00:03]:
> On Sun, Feb 1, 2015 at 11:18 PM, Mike Turquette <mturquette@linaro.org> wrote:
> > Quoting Tomeu Vizoso (2015-01-31 10:36:22)
> >> On 31 January 2015 at 02:31, Stephen Boyd <sboyd@codeaurora.org> wrote:
> >> > On 01/29, Stephen Boyd wrote:
> >> >> On 01/29/15 05:31, Geert Uytterhoeven wrote:
> >> >> > Hi Tomeu, Mike,
> >> >> >
> >> >> > On Fri, Jan 23, 2015 at 12:03 PM, Tomeu Vizoso
> >> >> > <tomeu.vizoso@collabora.com> wrote:
> >> >> >> --- a/drivers/clk/clk.c
> >> >> >> +++ b/drivers/clk/clk.c
> >> >> >> @@ -2391,25 +2543,24 @@ int __clk_get(struct clk *clk)
> >> >> >>         return 1;
> >> >> >>  }
> >> >> >>
> >> >> >> -static void clk_core_put(struct clk_core *core)
> >> >> >> +void __clk_put(struct clk *clk)
> >> >> >>  {
> >> >> >>         struct module *owner;
> >> >> >>
> >> >> >> -       owner = core->owner;
> >> >> >> +       if (!clk || WARN_ON_ONCE(IS_ERR(clk)))
> >> >> >> +               return;
> >> >> >>
> >> >> >>         clk_prepare_lock();
> >> >> >> -       kref_put(&core->ref, __clk_release);
> >> >> >> +
> >> >> >> +       hlist_del(&clk->child_node);
> >> >> >> +       clk_core_set_rate_nolock(clk->core, clk->core->req_rate);
> >> >> > At this point, clk->core->req_rate is still zero, causing
> >> >> > cpg_div6_clock_round_rate() to be called with a zero "rate" parameter,
> >> >> > e.g. on r8a7791:
> >> >>
> >> >> Hmm.. I wonder if we should assign core->req_rate to be the same as
> >> >> core->rate during __clk_init()? That would make this call to
> >> >> clk_core_set_rate_nolock() a nop in this case.
> >> >>
> >> >
> >> > Here's a patch to do this
> >> >
> >> > ---8<----
> >> > From: Stephen Boyd <sboyd@codeaurora.org>
> >> > Subject: [PATCH] clk: Assign a requested rate by default
> >> >
> >> > We need to assign a requested rate here so that we avoid
> >> > requesting a rate of 0 on clocks when we remove clock consumers.
> >>
> >> Hi, this looks good to me.
> >>
> >> Reviewed-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
> >
> > It seems to fix the total boot failure on OMAPs, and hopefully does the
> > same for SH Mobile and others. I've squashed this into Tomeu's rate
> > constraints patch to maintain bisect.
> 
> Yes, it fixes shmobile. .round_rate() is now called with a sane value of rate.

Looks like next-20150202 now produces tons of the following errors,
these from omap4:

[   10.568206] ------------[ cut here ]------------
[   10.568206] WARNING: CPU: 0 PID: 1 at drivers/clk/clk.c:925 clk_disable+0x28/0x34()
[   10.568237] Modules linked in:
[   10.568237] CPU: 0 PID: 1 Comm: swapper/0 Tainted: G        W       3.19.0-rc6-next-20150202 #2037
[   10.568237] Hardware name: Generic OMAP4 (Flattened Device Tree)
[   10.568267] [<c0015bdc>] (unwind_backtrace) from [<c001222c>] (show_stack+0x10/0x14)
[   10.568267] [<c001222c>] (show_stack) from [<c05d2014>] (dump_stack+0x84/0x9c)
[   10.568267] [<c05d2014>] (dump_stack) from [<c003ea90>] (warn_slowpath_common+0x7c/0xb8)
[   10.568298] [<c003ea90>] (warn_slowpath_common) from [<c003eb68>] (warn_slowpath_null+0x1c/0x24)
[   10.568298] [<c003eb68>] (warn_slowpath_null) from [<c04c1ffc>] (clk_disable+0x28/0x34)
[   10.568328] [<c04c1ffc>] (clk_disable) from [<c0025b3c>] (_disable_clocks+0x18/0x68)
[   10.568328] [<c0025b3c>] (_disable_clocks) from [<c0026f14>] (_idle+0x10c/0x214)
[   10.568328] [<c0026f14>] (_idle) from [<c0855fac>] (_setup+0x338/0x410)
[   10.568359] [<c0855fac>] (_setup) from [<c0027360>] (omap_hwmod_for_each+0x34/0x60)
[   10.568359] [<c0027360>] (omap_hwmod_for_each) from [<c08563c4>] (__omap_hwmod_setup_all+0x30/0x40)
[   10.568389] [<c08563c4>] (__omap_hwmod_setup_all) from [<c0008a04>] (do_one_initcall+0x80/0x1dc)
[   10.568389] [<c0008a04>] (do_one_initcall) from [<c0848ea0>] (kernel_init_freeable+0x204/0x2d0)
[   10.568420] [<c0848ea0>] (kernel_init_freeable) from [<c05cdab8>] (kernel_init+0x8/0xec)
[   10.568420] [<c05cdab8>] (kernel_init) from [<c000e790>] (ret_from_fork+0x14/0x24)
[   10.568420] ---[ end trace cb88537fdc8fa211 ]---


[   10.568450] ------------[ cut here ]------------
[   10.568450] WARNING: CPU: 0 PID: 1 at arch/arm/mach-omap2/dpll3xxx.c:436 omap3_noncore_dpll_enable+0xdc/0
x10c()
[   10.568450] Modules linked in:
[   10.568481] CPU: 0 PID: 1 Comm: swapper/0 Tainted: G        W       3.19.0-rc6-next-20150202 #2037
[   10.568481] Hardware name: Generic OMAP4 (Flattened Device Tree)
[   10.568481] [<c0015bdc>] (unwind_backtrace) from [<c001222c>] (show_stack+0x10/0x14)
[   10.568511] [<c001222c>] (show_stack) from [<c05d2014>] (dump_stack+0x84/0x9c)
[   10.568511] [<c05d2014>] (dump_stack) from [<c003ea90>] (warn_slowpath_common+0x7c/0xb8)
[   10.568511] [<c003ea90>] (warn_slowpath_common) from [<c003eb68>] (warn_slowpath_null+0x1c/0x24)
[   10.568542] [<c003eb68>] (warn_slowpath_null) from [<c0035800>] (omap3_noncore_dpll_enable+0xdc/0x10c)
[   10.568542] [<c0035800>] (omap3_noncore_dpll_enable) from [<c04c0a10>] (clk_core_enable+0x60/0x9c)
[   10.568572] [<c04c0a10>] (clk_core_enable) from [<c04c09f0>] (clk_core_enable+0x40/0x9c)
[   10.568572] ---[ end trace cb88537fdc8fa212 ]---
...

Regards,

Tony

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

* Re: [PATCH v13 4/6] clk: Add rate constraints to clocks
@ 2015-02-02 16:12                 ` Tony Lindgren
  0 siblings, 0 replies; 186+ messages in thread
From: Tony Lindgren @ 2015-02-02 16:12 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Mike Turquette, Tomeu Vizoso, Stephen Boyd,
	Linux MIPS Mailing List, linux-doc, Chao Xie, Haojian Zhuang,
	Boris Brezillon, Russell King, Jonathan Corbet, Emilio L??pez,
	Linux-sh list, Alex Elder, Zhangfei Gao, Bintian Wang,
	Matt Porter, linux-omap, linux-arm-kernel, linux-kernel,
	Ralf Baechle, Tero Kristo, Manuel Lauss, Maxime Ripard,
	Javier Martinez Canillas

* Geert Uytterhoeven <geert@linux-m68k.org> [150202 00:03]:
> On Sun, Feb 1, 2015 at 11:18 PM, Mike Turquette <mturquette@linaro.org> wrote:
> > Quoting Tomeu Vizoso (2015-01-31 10:36:22)
> >> On 31 January 2015 at 02:31, Stephen Boyd <sboyd@codeaurora.org> wrote:
> >> > On 01/29, Stephen Boyd wrote:
> >> >> On 01/29/15 05:31, Geert Uytterhoeven wrote:
> >> >> > Hi Tomeu, Mike,
> >> >> >
> >> >> > On Fri, Jan 23, 2015 at 12:03 PM, Tomeu Vizoso
> >> >> > <tomeu.vizoso@collabora.com> wrote:
> >> >> >> --- a/drivers/clk/clk.c
> >> >> >> +++ b/drivers/clk/clk.c
> >> >> >> @@ -2391,25 +2543,24 @@ int __clk_get(struct clk *clk)
> >> >> >>         return 1;
> >> >> >>  }
> >> >> >>
> >> >> >> -static void clk_core_put(struct clk_core *core)
> >> >> >> +void __clk_put(struct clk *clk)
> >> >> >>  {
> >> >> >>         struct module *owner;
> >> >> >>
> >> >> >> -       owner = core->owner;
> >> >> >> +       if (!clk || WARN_ON_ONCE(IS_ERR(clk)))
> >> >> >> +               return;
> >> >> >>
> >> >> >>         clk_prepare_lock();
> >> >> >> -       kref_put(&core->ref, __clk_release);
> >> >> >> +
> >> >> >> +       hlist_del(&clk->child_node);
> >> >> >> +       clk_core_set_rate_nolock(clk->core, clk->core->req_rate);
> >> >> > At this point, clk->core->req_rate is still zero, causing
> >> >> > cpg_div6_clock_round_rate() to be called with a zero "rate" parameter,
> >> >> > e.g. on r8a7791:
> >> >>
> >> >> Hmm.. I wonder if we should assign core->req_rate to be the same as
> >> >> core->rate during __clk_init()? That would make this call to
> >> >> clk_core_set_rate_nolock() a nop in this case.
> >> >>
> >> >
> >> > Here's a patch to do this
> >> >
> >> > ---8<----
> >> > From: Stephen Boyd <sboyd@codeaurora.org>
> >> > Subject: [PATCH] clk: Assign a requested rate by default
> >> >
> >> > We need to assign a requested rate here so that we avoid
> >> > requesting a rate of 0 on clocks when we remove clock consumers.
> >>
> >> Hi, this looks good to me.
> >>
> >> Reviewed-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
> >
> > It seems to fix the total boot failure on OMAPs, and hopefully does the
> > same for SH Mobile and others. I've squashed this into Tomeu's rate
> > constraints patch to maintain bisect.
> 
> Yes, it fixes shmobile. .round_rate() is now called with a sane value of rate.

Looks like next-20150202 now produces tons of the following errors,
these from omap4:

[   10.568206] ------------[ cut here ]------------
[   10.568206] WARNING: CPU: 0 PID: 1 at drivers/clk/clk.c:925 clk_disable+0x28/0x34()
[   10.568237] Modules linked in:
[   10.568237] CPU: 0 PID: 1 Comm: swapper/0 Tainted: G        W       3.19.0-rc6-next-20150202 #2037
[   10.568237] Hardware name: Generic OMAP4 (Flattened Device Tree)
[   10.568267] [<c0015bdc>] (unwind_backtrace) from [<c001222c>] (show_stack+0x10/0x14)
[   10.568267] [<c001222c>] (show_stack) from [<c05d2014>] (dump_stack+0x84/0x9c)
[   10.568267] [<c05d2014>] (dump_stack) from [<c003ea90>] (warn_slowpath_common+0x7c/0xb8)
[   10.568298] [<c003ea90>] (warn_slowpath_common) from [<c003eb68>] (warn_slowpath_null+0x1c/0x24)
[   10.568298] [<c003eb68>] (warn_slowpath_null) from [<c04c1ffc>] (clk_disable+0x28/0x34)
[   10.568328] [<c04c1ffc>] (clk_disable) from [<c0025b3c>] (_disable_clocks+0x18/0x68)
[   10.568328] [<c0025b3c>] (_disable_clocks) from [<c0026f14>] (_idle+0x10c/0x214)
[   10.568328] [<c0026f14>] (_idle) from [<c0855fac>] (_setup+0x338/0x410)
[   10.568359] [<c0855fac>] (_setup) from [<c0027360>] (omap_hwmod_for_each+0x34/0x60)
[   10.568359] [<c0027360>] (omap_hwmod_for_each) from [<c08563c4>] (__omap_hwmod_setup_all+0x30/0x40)
[   10.568389] [<c08563c4>] (__omap_hwmod_setup_all) from [<c0008a04>] (do_one_initcall+0x80/0x1dc)
[   10.568389] [<c0008a04>] (do_one_initcall) from [<c0848ea0>] (kernel_init_freeable+0x204/0x2d0)
[   10.568420] [<c0848ea0>] (kernel_init_freeable) from [<c05cdab8>] (kernel_init+0x8/0xec)
[   10.568420] [<c05cdab8>] (kernel_init) from [<c000e790>] (ret_from_fork+0x14/0x24)
[   10.568420] ---[ end trace cb88537fdc8fa211 ]---


[   10.568450] ------------[ cut here ]------------
[   10.568450] WARNING: CPU: 0 PID: 1 at arch/arm/mach-omap2/dpll3xxx.c:436 omap3_noncore_dpll_enable+0xdc/0
x10c()
[   10.568450] Modules linked in:
[   10.568481] CPU: 0 PID: 1 Comm: swapper/0 Tainted: G        W       3.19.0-rc6-next-20150202 #2037
[   10.568481] Hardware name: Generic OMAP4 (Flattened Device Tree)
[   10.568481] [<c0015bdc>] (unwind_backtrace) from [<c001222c>] (show_stack+0x10/0x14)
[   10.568511] [<c001222c>] (show_stack) from [<c05d2014>] (dump_stack+0x84/0x9c)
[   10.568511] [<c05d2014>] (dump_stack) from [<c003ea90>] (warn_slowpath_common+0x7c/0xb8)
[   10.568511] [<c003ea90>] (warn_slowpath_common) from [<c003eb68>] (warn_slowpath_null+0x1c/0x24)
[   10.568542] [<c003eb68>] (warn_slowpath_null) from [<c0035800>] (omap3_noncore_dpll_enable+0xdc/0x10c)
[   10.568542] [<c0035800>] (omap3_noncore_dpll_enable) from [<c04c0a10>] (clk_core_enable+0x60/0x9c)
[   10.568572] [<c04c0a10>] (clk_core_enable) from [<c04c09f0>] (clk_core_enable+0x40/0x9c)
[   10.568572] ---[ end trace cb88537fdc8fa212 ]---
...

Regards,

Tony

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

* Re: [PATCH v13 4/6] clk: Add rate constraints to clocks
@ 2015-02-02 16:12                 ` Tony Lindgren
  0 siblings, 0 replies; 186+ messages in thread
From: Tony Lindgren @ 2015-02-02 16:12 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Mike Turquette, Tomeu Vizoso, Stephen Boyd,
	Linux MIPS Mailing List, linux-doc, Chao Xie, Haojian Zhuang,
	Boris Brezillon, Russell King, Jonathan Corbet, Emilio L??pez,
	Linux-sh list, Alex Elder, Zhangfei Gao, Bintian Wang,
	Matt Porter, linux-omap, linux-arm-kernel, linux-kernel

* Geert Uytterhoeven <geert@linux-m68k.org> [150202 00:03]:
> On Sun, Feb 1, 2015 at 11:18 PM, Mike Turquette <mturquette@linaro.org> wrote:
> > Quoting Tomeu Vizoso (2015-01-31 10:36:22)
> >> On 31 January 2015 at 02:31, Stephen Boyd <sboyd@codeaurora.org> wrote:
> >> > On 01/29, Stephen Boyd wrote:
> >> >> On 01/29/15 05:31, Geert Uytterhoeven wrote:
> >> >> > Hi Tomeu, Mike,
> >> >> >
> >> >> > On Fri, Jan 23, 2015 at 12:03 PM, Tomeu Vizoso
> >> >> > <tomeu.vizoso@collabora.com> wrote:
> >> >> >> --- a/drivers/clk/clk.c
> >> >> >> +++ b/drivers/clk/clk.c
> >> >> >> @@ -2391,25 +2543,24 @@ int __clk_get(struct clk *clk)
> >> >> >>         return 1;
> >> >> >>  }
> >> >> >>
> >> >> >> -static void clk_core_put(struct clk_core *core)
> >> >> >> +void __clk_put(struct clk *clk)
> >> >> >>  {
> >> >> >>         struct module *owner;
> >> >> >>
> >> >> >> -       owner = core->owner;
> >> >> >> +       if (!clk || WARN_ON_ONCE(IS_ERR(clk)))
> >> >> >> +               return;
> >> >> >>
> >> >> >>         clk_prepare_lock();
> >> >> >> -       kref_put(&core->ref, __clk_release);
> >> >> >> +
> >> >> >> +       hlist_del(&clk->child_node);
> >> >> >> +       clk_core_set_rate_nolock(clk->core, clk->core->req_rate);
> >> >> > At this point, clk->core->req_rate is still zero, causing
> >> >> > cpg_div6_clock_round_rate() to be called with a zero "rate" parameter,
> >> >> > e.g. on r8a7791:
> >> >>
> >> >> Hmm.. I wonder if we should assign core->req_rate to be the same as
> >> >> core->rate during __clk_init()? That would make this call to
> >> >> clk_core_set_rate_nolock() a nop in this case.
> >> >>
> >> >
> >> > Here's a patch to do this
> >> >
> >> > ---8<----
> >> > From: Stephen Boyd <sboyd@codeaurora.org>
> >> > Subject: [PATCH] clk: Assign a requested rate by default
> >> >
> >> > We need to assign a requested rate here so that we avoid
> >> > requesting a rate of 0 on clocks when we remove clock consumers.
> >>
> >> Hi, this looks good to me.
> >>
> >> Reviewed-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
> >
> > It seems to fix the total boot failure on OMAPs, and hopefully does the
> > same for SH Mobile and others. I've squashed this into Tomeu's rate
> > constraints patch to maintain bisect.
> 
> Yes, it fixes shmobile. .round_rate() is now called with a sane value of rate.

Looks like next-20150202 now produces tons of the following errors,
these from omap4:

[   10.568206] ------------[ cut here ]------------
[   10.568206] WARNING: CPU: 0 PID: 1 at drivers/clk/clk.c:925 clk_disable+0x28/0x34()
[   10.568237] Modules linked in:
[   10.568237] CPU: 0 PID: 1 Comm: swapper/0 Tainted: G        W       3.19.0-rc6-next-20150202 #2037
[   10.568237] Hardware name: Generic OMAP4 (Flattened Device Tree)
[   10.568267] [<c0015bdc>] (unwind_backtrace) from [<c001222c>] (show_stack+0x10/0x14)
[   10.568267] [<c001222c>] (show_stack) from [<c05d2014>] (dump_stack+0x84/0x9c)
[   10.568267] [<c05d2014>] (dump_stack) from [<c003ea90>] (warn_slowpath_common+0x7c/0xb8)
[   10.568298] [<c003ea90>] (warn_slowpath_common) from [<c003eb68>] (warn_slowpath_null+0x1c/0x24)
[   10.568298] [<c003eb68>] (warn_slowpath_null) from [<c04c1ffc>] (clk_disable+0x28/0x34)
[   10.568328] [<c04c1ffc>] (clk_disable) from [<c0025b3c>] (_disable_clocks+0x18/0x68)
[   10.568328] [<c0025b3c>] (_disable_clocks) from [<c0026f14>] (_idle+0x10c/0x214)
[   10.568328] [<c0026f14>] (_idle) from [<c0855fac>] (_setup+0x338/0x410)
[   10.568359] [<c0855fac>] (_setup) from [<c0027360>] (omap_hwmod_for_each+0x34/0x60)
[   10.568359] [<c0027360>] (omap_hwmod_for_each) from [<c08563c4>] (__omap_hwmod_setup_all+0x30/0x40)
[   10.568389] [<c08563c4>] (__omap_hwmod_setup_all) from [<c0008a04>] (do_one_initcall+0x80/0x1dc)
[   10.568389] [<c0008a04>] (do_one_initcall) from [<c0848ea0>] (kernel_init_freeable+0x204/0x2d0)
[   10.568420] [<c0848ea0>] (kernel_init_freeable) from [<c05cdab8>] (kernel_init+0x8/0xec)
[   10.568420] [<c05cdab8>] (kernel_init) from [<c000e790>] (ret_from_fork+0x14/0x24)
[   10.568420] ---[ end trace cb88537fdc8fa211 ]---


[   10.568450] ------------[ cut here ]------------
[   10.568450] WARNING: CPU: 0 PID: 1 at arch/arm/mach-omap2/dpll3xxx.c:436 omap3_noncore_dpll_enable+0xdc/0
x10c()
[   10.568450] Modules linked in:
[   10.568481] CPU: 0 PID: 1 Comm: swapper/0 Tainted: G        W       3.19.0-rc6-next-20150202 #2037
[   10.568481] Hardware name: Generic OMAP4 (Flattened Device Tree)
[   10.568481] [<c0015bdc>] (unwind_backtrace) from [<c001222c>] (show_stack+0x10/0x14)
[   10.568511] [<c001222c>] (show_stack) from [<c05d2014>] (dump_stack+0x84/0x9c)
[   10.568511] [<c05d2014>] (dump_stack) from [<c003ea90>] (warn_slowpath_common+0x7c/0xb8)
[   10.568511] [<c003ea90>] (warn_slowpath_common) from [<c003eb68>] (warn_slowpath_null+0x1c/0x24)
[   10.568542] [<c003eb68>] (warn_slowpath_null) from [<c0035800>] (omap3_noncore_dpll_enable+0xdc/0x10c)
[   10.568542] [<c0035800>] (omap3_noncore_dpll_enable) from [<c04c0a10>] (clk_core_enable+0x60/0x9c)
[   10.568572] [<c04c0a10>] (clk_core_enable) from [<c04c09f0>] (clk_core_enable+0x40/0x9c)
[   10.568572] ---[ end trace cb88537fdc8fa212 ]---
...

Regards,

Tony

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

* [PATCH v13 4/6] clk: Add rate constraints to clocks
@ 2015-02-02 16:12                 ` Tony Lindgren
  0 siblings, 0 replies; 186+ messages in thread
From: Tony Lindgren @ 2015-02-02 16:12 UTC (permalink / raw)
  To: linux-arm-kernel

* Geert Uytterhoeven <geert@linux-m68k.org> [150202 00:03]:
> On Sun, Feb 1, 2015 at 11:18 PM, Mike Turquette <mturquette@linaro.org> wrote:
> > Quoting Tomeu Vizoso (2015-01-31 10:36:22)
> >> On 31 January 2015 at 02:31, Stephen Boyd <sboyd@codeaurora.org> wrote:
> >> > On 01/29, Stephen Boyd wrote:
> >> >> On 01/29/15 05:31, Geert Uytterhoeven wrote:
> >> >> > Hi Tomeu, Mike,
> >> >> >
> >> >> > On Fri, Jan 23, 2015 at 12:03 PM, Tomeu Vizoso
> >> >> > <tomeu.vizoso@collabora.com> wrote:
> >> >> >> --- a/drivers/clk/clk.c
> >> >> >> +++ b/drivers/clk/clk.c
> >> >> >> @@ -2391,25 +2543,24 @@ int __clk_get(struct clk *clk)
> >> >> >>         return 1;
> >> >> >>  }
> >> >> >>
> >> >> >> -static void clk_core_put(struct clk_core *core)
> >> >> >> +void __clk_put(struct clk *clk)
> >> >> >>  {
> >> >> >>         struct module *owner;
> >> >> >>
> >> >> >> -       owner = core->owner;
> >> >> >> +       if (!clk || WARN_ON_ONCE(IS_ERR(clk)))
> >> >> >> +               return;
> >> >> >>
> >> >> >>         clk_prepare_lock();
> >> >> >> -       kref_put(&core->ref, __clk_release);
> >> >> >> +
> >> >> >> +       hlist_del(&clk->child_node);
> >> >> >> +       clk_core_set_rate_nolock(clk->core, clk->core->req_rate);
> >> >> > At this point, clk->core->req_rate is still zero, causing
> >> >> > cpg_div6_clock_round_rate() to be called with a zero "rate" parameter,
> >> >> > e.g. on r8a7791:
> >> >>
> >> >> Hmm.. I wonder if we should assign core->req_rate to be the same as
> >> >> core->rate during __clk_init()? That would make this call to
> >> >> clk_core_set_rate_nolock() a nop in this case.
> >> >>
> >> >
> >> > Here's a patch to do this
> >> >
> >> > ---8<----
> >> > From: Stephen Boyd <sboyd@codeaurora.org>
> >> > Subject: [PATCH] clk: Assign a requested rate by default
> >> >
> >> > We need to assign a requested rate here so that we avoid
> >> > requesting a rate of 0 on clocks when we remove clock consumers.
> >>
> >> Hi, this looks good to me.
> >>
> >> Reviewed-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
> >
> > It seems to fix the total boot failure on OMAPs, and hopefully does the
> > same for SH Mobile and others. I've squashed this into Tomeu's rate
> > constraints patch to maintain bisect.
> 
> Yes, it fixes shmobile. .round_rate() is now called with a sane value of rate.

Looks like next-20150202 now produces tons of the following errors,
these from omap4:

[   10.568206] ------------[ cut here ]------------
[   10.568206] WARNING: CPU: 0 PID: 1 at drivers/clk/clk.c:925 clk_disable+0x28/0x34()
[   10.568237] Modules linked in:
[   10.568237] CPU: 0 PID: 1 Comm: swapper/0 Tainted: G        W       3.19.0-rc6-next-20150202 #2037
[   10.568237] Hardware name: Generic OMAP4 (Flattened Device Tree)
[   10.568267] [<c0015bdc>] (unwind_backtrace) from [<c001222c>] (show_stack+0x10/0x14)
[   10.568267] [<c001222c>] (show_stack) from [<c05d2014>] (dump_stack+0x84/0x9c)
[   10.568267] [<c05d2014>] (dump_stack) from [<c003ea90>] (warn_slowpath_common+0x7c/0xb8)
[   10.568298] [<c003ea90>] (warn_slowpath_common) from [<c003eb68>] (warn_slowpath_null+0x1c/0x24)
[   10.568298] [<c003eb68>] (warn_slowpath_null) from [<c04c1ffc>] (clk_disable+0x28/0x34)
[   10.568328] [<c04c1ffc>] (clk_disable) from [<c0025b3c>] (_disable_clocks+0x18/0x68)
[   10.568328] [<c0025b3c>] (_disable_clocks) from [<c0026f14>] (_idle+0x10c/0x214)
[   10.568328] [<c0026f14>] (_idle) from [<c0855fac>] (_setup+0x338/0x410)
[   10.568359] [<c0855fac>] (_setup) from [<c0027360>] (omap_hwmod_for_each+0x34/0x60)
[   10.568359] [<c0027360>] (omap_hwmod_for_each) from [<c08563c4>] (__omap_hwmod_setup_all+0x30/0x40)
[   10.568389] [<c08563c4>] (__omap_hwmod_setup_all) from [<c0008a04>] (do_one_initcall+0x80/0x1dc)
[   10.568389] [<c0008a04>] (do_one_initcall) from [<c0848ea0>] (kernel_init_freeable+0x204/0x2d0)
[   10.568420] [<c0848ea0>] (kernel_init_freeable) from [<c05cdab8>] (kernel_init+0x8/0xec)
[   10.568420] [<c05cdab8>] (kernel_init) from [<c000e790>] (ret_from_fork+0x14/0x24)
[   10.568420] ---[ end trace cb88537fdc8fa211 ]---


[   10.568450] ------------[ cut here ]------------
[   10.568450] WARNING: CPU: 0 PID: 1 at arch/arm/mach-omap2/dpll3xxx.c:436 omap3_noncore_dpll_enable+0xdc/0
x10c()
[   10.568450] Modules linked in:
[   10.568481] CPU: 0 PID: 1 Comm: swapper/0 Tainted: G        W       3.19.0-rc6-next-20150202 #2037
[   10.568481] Hardware name: Generic OMAP4 (Flattened Device Tree)
[   10.568481] [<c0015bdc>] (unwind_backtrace) from [<c001222c>] (show_stack+0x10/0x14)
[   10.568511] [<c001222c>] (show_stack) from [<c05d2014>] (dump_stack+0x84/0x9c)
[   10.568511] [<c05d2014>] (dump_stack) from [<c003ea90>] (warn_slowpath_common+0x7c/0xb8)
[   10.568511] [<c003ea90>] (warn_slowpath_common) from [<c003eb68>] (warn_slowpath_null+0x1c/0x24)
[   10.568542] [<c003eb68>] (warn_slowpath_null) from [<c0035800>] (omap3_noncore_dpll_enable+0xdc/0x10c)
[   10.568542] [<c0035800>] (omap3_noncore_dpll_enable) from [<c04c0a10>] (clk_core_enable+0x60/0x9c)
[   10.568572] [<c04c0a10>] (clk_core_enable) from [<c04c09f0>] (clk_core_enable+0x40/0x9c)
[   10.568572] ---[ end trace cb88537fdc8fa212 ]---
...

Regards,

Tony

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

* Re: [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
  2015-02-01 21:24     ` Mike Turquette
@ 2015-02-02 17:04       ` Tony Lindgren
  -1 siblings, 0 replies; 186+ messages in thread
From: Tony Lindgren @ 2015-02-02 17:04 UTC (permalink / raw)
  To: Mike Turquette
  Cc: Tomeu Vizoso, linux-kernel, Stephen Boyd, Paul Walmsley,
	linux-omap, linux-arm-kernel, t-kristo

* Mike Turquette <mturquette@linaro.org> [150201 13:27]:
> Quoting Tomeu Vizoso (2015-01-23 03:03:30)
> > Moves clock state to struct clk_core, but takes care to change as little API as
> > possible.
> > 
> > struct clk_hw still has a pointer to a struct clk, which is the
> > implementation's per-user clk instance, for backwards compatibility.
> > 
> > The struct clk that clk_get_parent() returns isn't owned by the caller, but by
> > the clock implementation, so the former shouldn't call clk_put() on it.
> > 
> > Because some boards in mach-omap2 still register clocks statically, their clock
> > registration had to be updated to take into account that the clock information
> > is stored in struct clk_core now.
> 
> Tero, Paul & Tony,
> 
> Tomeu's patch unveils a problem with omap3_noncore_dpll_enable and
> struct dpll_data, namely this snippet from
> arch/arm/mach-omap2/dpll3xxx.c:
> 
>         parent = __clk_get_parent(hw->clk);
> 
>         if (__clk_get_rate(hw->clk) == __clk_get_rate(dd->clk_bypass)) {
>                 WARN(parent != dd->clk_bypass,
>                                 "here0, parent name is %s, bypass name is %s\n",
>                                 __clk_get_name(parent), __clk_get_name(dd->clk_bypass));
>                 r = _omap3_noncore_dpll_bypass(clk);
>         } else {
>                 WARN(parent != dd->clk_ref,
>                                 "here1, parent name is %s, ref name is %s\n",
>                                 __clk_get_name(parent), __clk_get_name(dd->clk_ref));
>                 r = _omap3_noncore_dpll_lock(clk);
>         }
> 
> struct dpll_data has members clk_ref and clk_bypass which are struct clk
> pointers. This was always a bit of a violation of the clk.h contract
> since drivers are not supposed to deref struct clk pointers. Now that we
> generate unique pointers for each call to clk_get (clk_ref & clk_bypass
> are populated by of_clk_get in ti_clk_register_dpll) then the pointer
> comparisons above will never be equal (even if they resolve down to the
> same struct clk_core). I added the verbose traces to the WARNs above to
> illustrate the point: the names are always the same but the pointers
> differ.
> 
> AFAICT this doesn't break anything, but booting on OMAP3+ results in
> noisy WARNs.

Also on at least omap4 like I posted. So sounds like the check for
WARN is wrong but harmless. Paul & Tero, what do you want to do
about that?
 
> I think the correct fix is to replace clk_bypass and clk_ref pointers
> with a simple integer parent_index. In fact we already have this index.
> See how the pointers are populated in ti_clk_register_dpll:
> 
> 
>         dd->clk_ref = of_clk_get(node, 0);
>         dd->clk_bypass = of_clk_get(node, 1);
> 
> Tony, the same problem affects the FAPLL code which copy/pastes some of
> the DPLL code.
> 
> Thoughts?

Not seeing these warnings with dm186x as fapll.c does not use
dpll3xxx.c. This is because of the way the PLL's child synthesizers
need to also access the PLL registers for power and bypass mode.

Not related to the $subject bug, but to me it seems that we could
possibly have Linux generic PLL code if we add support for
parent_in_bypass_mode in addition to the parent_rate. This is because
the PLL can in theory generate the same rate both in bypass mode and
regular mode so parent_rate is not enough to tell it to the child
synthesizers. Not sure how the PLL registers enabling and disabling
it's children should be handled, maybe regmap would work there.

Regards,

Tony

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

* [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
@ 2015-02-02 17:04       ` Tony Lindgren
  0 siblings, 0 replies; 186+ messages in thread
From: Tony Lindgren @ 2015-02-02 17:04 UTC (permalink / raw)
  To: linux-arm-kernel

* Mike Turquette <mturquette@linaro.org> [150201 13:27]:
> Quoting Tomeu Vizoso (2015-01-23 03:03:30)
> > Moves clock state to struct clk_core, but takes care to change as little API as
> > possible.
> > 
> > struct clk_hw still has a pointer to a struct clk, which is the
> > implementation's per-user clk instance, for backwards compatibility.
> > 
> > The struct clk that clk_get_parent() returns isn't owned by the caller, but by
> > the clock implementation, so the former shouldn't call clk_put() on it.
> > 
> > Because some boards in mach-omap2 still register clocks statically, their clock
> > registration had to be updated to take into account that the clock information
> > is stored in struct clk_core now.
> 
> Tero, Paul & Tony,
> 
> Tomeu's patch unveils a problem with omap3_noncore_dpll_enable and
> struct dpll_data, namely this snippet from
> arch/arm/mach-omap2/dpll3xxx.c:
> 
>         parent = __clk_get_parent(hw->clk);
> 
>         if (__clk_get_rate(hw->clk) == __clk_get_rate(dd->clk_bypass)) {
>                 WARN(parent != dd->clk_bypass,
>                                 "here0, parent name is %s, bypass name is %s\n",
>                                 __clk_get_name(parent), __clk_get_name(dd->clk_bypass));
>                 r = _omap3_noncore_dpll_bypass(clk);
>         } else {
>                 WARN(parent != dd->clk_ref,
>                                 "here1, parent name is %s, ref name is %s\n",
>                                 __clk_get_name(parent), __clk_get_name(dd->clk_ref));
>                 r = _omap3_noncore_dpll_lock(clk);
>         }
> 
> struct dpll_data has members clk_ref and clk_bypass which are struct clk
> pointers. This was always a bit of a violation of the clk.h contract
> since drivers are not supposed to deref struct clk pointers. Now that we
> generate unique pointers for each call to clk_get (clk_ref & clk_bypass
> are populated by of_clk_get in ti_clk_register_dpll) then the pointer
> comparisons above will never be equal (even if they resolve down to the
> same struct clk_core). I added the verbose traces to the WARNs above to
> illustrate the point: the names are always the same but the pointers
> differ.
> 
> AFAICT this doesn't break anything, but booting on OMAP3+ results in
> noisy WARNs.

Also on at least omap4 like I posted. So sounds like the check for
WARN is wrong but harmless. Paul & Tero, what do you want to do
about that?
 
> I think the correct fix is to replace clk_bypass and clk_ref pointers
> with a simple integer parent_index. In fact we already have this index.
> See how the pointers are populated in ti_clk_register_dpll:
> 
> 
>         dd->clk_ref = of_clk_get(node, 0);
>         dd->clk_bypass = of_clk_get(node, 1);
> 
> Tony, the same problem affects the FAPLL code which copy/pastes some of
> the DPLL code.
> 
> Thoughts?

Not seeing these warnings with dm186x as fapll.c does not use
dpll3xxx.c. This is because of the way the PLL's child synthesizers
need to also access the PLL registers for power and bypass mode.

Not related to the $subject bug, but to me it seems that we could
possibly have Linux generic PLL code if we add support for
parent_in_bypass_mode in addition to the parent_rate. This is because
the PLL can in theory generate the same rate both in bypass mode and
regular mode so parent_rate is not enough to tell it to the child
synthesizers. Not sure how the PLL registers enabling and disabling
it's children should be handled, maybe regmap would work there.

Regards,

Tony

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

* Re: [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
  2015-02-02 17:04       ` Tony Lindgren
@ 2015-02-02 17:32         ` Mike Turquette
  -1 siblings, 0 replies; 186+ messages in thread
From: Mike Turquette @ 2015-02-02 17:32 UTC (permalink / raw)
  To: Tony Lindgren
  Cc: Paul Walmsley, Tomeu Vizoso, Stephen Boyd, linux-kernel,
	t-kristo, linux-omap, linux-arm-kernel

Quoting Tony Lindgren (2015-02-02 09:04:59)
> * Mike Turquette <mturquette@linaro.org> [150201 13:27]:
> > Quoting Tomeu Vizoso (2015-01-23 03:03:30)
> > > Moves clock state to struct clk_core, but takes care to change as little API as
> > > possible.
> > > 
> > > struct clk_hw still has a pointer to a struct clk, which is the
> > > implementation's per-user clk instance, for backwards compatibility.
> > > 
> > > The struct clk that clk_get_parent() returns isn't owned by the caller, but by
> > > the clock implementation, so the former shouldn't call clk_put() on it.
> > > 
> > > Because some boards in mach-omap2 still register clocks statically, their clock
> > > registration had to be updated to take into account that the clock information
> > > is stored in struct clk_core now.
> > 
> > Tero, Paul & Tony,
> > 
> > Tomeu's patch unveils a problem with omap3_noncore_dpll_enable and
> > struct dpll_data, namely this snippet from
> > arch/arm/mach-omap2/dpll3xxx.c:
> > 
> >         parent = __clk_get_parent(hw->clk);
> > 
> >         if (__clk_get_rate(hw->clk) == __clk_get_rate(dd->clk_bypass)) {
> >                 WARN(parent != dd->clk_bypass,
> >                                 "here0, parent name is %s, bypass name is %s\n",
> >                                 __clk_get_name(parent), __clk_get_name(dd->clk_bypass));
> >                 r = _omap3_noncore_dpll_bypass(clk);
> >         } else {
> >                 WARN(parent != dd->clk_ref,
> >                                 "here1, parent name is %s, ref name is %s\n",
> >                                 __clk_get_name(parent), __clk_get_name(dd->clk_ref));
> >                 r = _omap3_noncore_dpll_lock(clk);
> >         }
> > 
> > struct dpll_data has members clk_ref and clk_bypass which are struct clk
> > pointers. This was always a bit of a violation of the clk.h contract
> > since drivers are not supposed to deref struct clk pointers. Now that we
> > generate unique pointers for each call to clk_get (clk_ref & clk_bypass
> > are populated by of_clk_get in ti_clk_register_dpll) then the pointer
> > comparisons above will never be equal (even if they resolve down to the
> > same struct clk_core). I added the verbose traces to the WARNs above to
> > illustrate the point: the names are always the same but the pointers
> > differ.
> > 
> > AFAICT this doesn't break anything, but booting on OMAP3+ results in
> > noisy WARNs.
> 
> Also on at least omap4 like I posted.

Right, hence the + after OMAP3 ;-)

> So sounds like the check for
> WARN is wrong but harmless. Paul & Tero, what do you want to do
> about that?

I would be fine to simply silence the WARNs since we're so closed to the
merge window and then revisit it with a proper fix. Of course the ideal
solution would be to convert the pointer comparison scheme to one using
parent_index.

Regards,
Mike

>  
> > I think the correct fix is to replace clk_bypass and clk_ref pointers
> > with a simple integer parent_index. In fact we already have this index.
> > See how the pointers are populated in ti_clk_register_dpll:
> > 
> > 
> >         dd->clk_ref = of_clk_get(node, 0);
> >         dd->clk_bypass = of_clk_get(node, 1);
> > 
> > Tony, the same problem affects the FAPLL code which copy/pastes some of
> > the DPLL code.
> > 
> > Thoughts?
> 
> Not seeing these warnings with dm186x as fapll.c does not use
> dpll3xxx.c. This is because of the way the PLL's child synthesizers
> need to also access the PLL registers for power and bypass mode.
> 
> Not related to the $subject bug, but to me it seems that we could
> possibly have Linux generic PLL code if we add support for
> parent_in_bypass_mode in addition to the parent_rate. This is because
> the PLL can in theory generate the same rate both in bypass mode and
> regular mode so parent_rate is not enough to tell it to the child
> synthesizers. Not sure how the PLL registers enabling and disabling
> it's children should be handled, maybe regmap would work there.
> 
> Regards,
> 
> Tony

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

* [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
@ 2015-02-02 17:32         ` Mike Turquette
  0 siblings, 0 replies; 186+ messages in thread
From: Mike Turquette @ 2015-02-02 17:32 UTC (permalink / raw)
  To: linux-arm-kernel

Quoting Tony Lindgren (2015-02-02 09:04:59)
> * Mike Turquette <mturquette@linaro.org> [150201 13:27]:
> > Quoting Tomeu Vizoso (2015-01-23 03:03:30)
> > > Moves clock state to struct clk_core, but takes care to change as little API as
> > > possible.
> > > 
> > > struct clk_hw still has a pointer to a struct clk, which is the
> > > implementation's per-user clk instance, for backwards compatibility.
> > > 
> > > The struct clk that clk_get_parent() returns isn't owned by the caller, but by
> > > the clock implementation, so the former shouldn't call clk_put() on it.
> > > 
> > > Because some boards in mach-omap2 still register clocks statically, their clock
> > > registration had to be updated to take into account that the clock information
> > > is stored in struct clk_core now.
> > 
> > Tero, Paul & Tony,
> > 
> > Tomeu's patch unveils a problem with omap3_noncore_dpll_enable and
> > struct dpll_data, namely this snippet from
> > arch/arm/mach-omap2/dpll3xxx.c:
> > 
> >         parent = __clk_get_parent(hw->clk);
> > 
> >         if (__clk_get_rate(hw->clk) == __clk_get_rate(dd->clk_bypass)) {
> >                 WARN(parent != dd->clk_bypass,
> >                                 "here0, parent name is %s, bypass name is %s\n",
> >                                 __clk_get_name(parent), __clk_get_name(dd->clk_bypass));
> >                 r = _omap3_noncore_dpll_bypass(clk);
> >         } else {
> >                 WARN(parent != dd->clk_ref,
> >                                 "here1, parent name is %s, ref name is %s\n",
> >                                 __clk_get_name(parent), __clk_get_name(dd->clk_ref));
> >                 r = _omap3_noncore_dpll_lock(clk);
> >         }
> > 
> > struct dpll_data has members clk_ref and clk_bypass which are struct clk
> > pointers. This was always a bit of a violation of the clk.h contract
> > since drivers are not supposed to deref struct clk pointers. Now that we
> > generate unique pointers for each call to clk_get (clk_ref & clk_bypass
> > are populated by of_clk_get in ti_clk_register_dpll) then the pointer
> > comparisons above will never be equal (even if they resolve down to the
> > same struct clk_core). I added the verbose traces to the WARNs above to
> > illustrate the point: the names are always the same but the pointers
> > differ.
> > 
> > AFAICT this doesn't break anything, but booting on OMAP3+ results in
> > noisy WARNs.
> 
> Also on at least omap4 like I posted.

Right, hence the + after OMAP3 ;-)

> So sounds like the check for
> WARN is wrong but harmless. Paul & Tero, what do you want to do
> about that?

I would be fine to simply silence the WARNs since we're so closed to the
merge window and then revisit it with a proper fix. Of course the ideal
solution would be to convert the pointer comparison scheme to one using
parent_index.

Regards,
Mike

>  
> > I think the correct fix is to replace clk_bypass and clk_ref pointers
> > with a simple integer parent_index. In fact we already have this index.
> > See how the pointers are populated in ti_clk_register_dpll:
> > 
> > 
> >         dd->clk_ref = of_clk_get(node, 0);
> >         dd->clk_bypass = of_clk_get(node, 1);
> > 
> > Tony, the same problem affects the FAPLL code which copy/pastes some of
> > the DPLL code.
> > 
> > Thoughts?
> 
> Not seeing these warnings with dm186x as fapll.c does not use
> dpll3xxx.c. This is because of the way the PLL's child synthesizers
> need to also access the PLL registers for power and bypass mode.
> 
> Not related to the $subject bug, but to me it seems that we could
> possibly have Linux generic PLL code if we add support for
> parent_in_bypass_mode in addition to the parent_rate. This is because
> the PLL can in theory generate the same rate both in bypass mode and
> regular mode so parent_rate is not enough to tell it to the child
> synthesizers. Not sure how the PLL registers enabling and disabling
> it's children should be handled, maybe regmap would work there.
> 
> Regards,
> 
> Tony

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

* Re: [PATCH v13 4/6] clk: Add rate constraints to clocks
  2015-02-02 16:12                 ` Tony Lindgren
                                     ` (2 preceding siblings ...)
  (?)
@ 2015-02-02 17:46                   ` Mike Turquette
  -1 siblings, 0 replies; 186+ messages in thread
From: Mike Turquette @ 2015-02-02 17:46 UTC (permalink / raw)
  To: linux-arm-kernel

Quoting Tony Lindgren (2015-02-02 08:12:37)
> * Geert Uytterhoeven <geert@linux-m68k.org> [150202 00:03]:
> > On Sun, Feb 1, 2015 at 11:18 PM, Mike Turquette <mturquette@linaro.org> wrote:
> > > Quoting Tomeu Vizoso (2015-01-31 10:36:22)
> > >> On 31 January 2015 at 02:31, Stephen Boyd <sboyd@codeaurora.org> wrote:
> > >> > On 01/29, Stephen Boyd wrote:
> > >> >> On 01/29/15 05:31, Geert Uytterhoeven wrote:
> > >> >> > Hi Tomeu, Mike,
> > >> >> >
> > >> >> > On Fri, Jan 23, 2015 at 12:03 PM, Tomeu Vizoso
> > >> >> > <tomeu.vizoso@collabora.com> wrote:
> > >> >> >> --- a/drivers/clk/clk.c
> > >> >> >> +++ b/drivers/clk/clk.c
> > >> >> >> @@ -2391,25 +2543,24 @@ int __clk_get(struct clk *clk)
> > >> >> >>         return 1;
> > >> >> >>  }
> > >> >> >>
> > >> >> >> -static void clk_core_put(struct clk_core *core)
> > >> >> >> +void __clk_put(struct clk *clk)
> > >> >> >>  {
> > >> >> >>         struct module *owner;
> > >> >> >>
> > >> >> >> -       owner = core->owner;
> > >> >> >> +       if (!clk || WARN_ON_ONCE(IS_ERR(clk)))
> > >> >> >> +               return;
> > >> >> >>
> > >> >> >>         clk_prepare_lock();
> > >> >> >> -       kref_put(&core->ref, __clk_release);
> > >> >> >> +
> > >> >> >> +       hlist_del(&clk->child_node);
> > >> >> >> +       clk_core_set_rate_nolock(clk->core, clk->core->req_rate);
> > >> >> > At this point, clk->core->req_rate is still zero, causing
> > >> >> > cpg_div6_clock_round_rate() to be called with a zero "rate" parameter,
> > >> >> > e.g. on r8a7791:
> > >> >>
> > >> >> Hmm.. I wonder if we should assign core->req_rate to be the same as
> > >> >> core->rate during __clk_init()? That would make this call to
> > >> >> clk_core_set_rate_nolock() a nop in this case.
> > >> >>
> > >> >
> > >> > Here's a patch to do this
> > >> >
> > >> > ---8<----
> > >> > From: Stephen Boyd <sboyd@codeaurora.org>
> > >> > Subject: [PATCH] clk: Assign a requested rate by default
> > >> >
> > >> > We need to assign a requested rate here so that we avoid
> > >> > requesting a rate of 0 on clocks when we remove clock consumers.
> > >>
> > >> Hi, this looks good to me.
> > >>
> > >> Reviewed-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
> > >
> > > It seems to fix the total boot failure on OMAPs, and hopefully does the
> > > same for SH Mobile and others. I've squashed this into Tomeu's rate
> > > constraints patch to maintain bisect.
> > 
> > Yes, it fixes shmobile. .round_rate() is now called with a sane value of rate.
> 
> Looks like next-20150202 now produces tons of the following errors,
> these from omap4:

next-20150202 is the rolled-back changes from last Friday. I removed the
clock constraints patch and in doing so also rolled back the TI clock
driver migration and clk-private.h removal patches. Those are all back
in clk-next as of last night and it looks as though they missed being
pulled into todays linux-next by a matter of minutes :-/

> 
> [   10.568206] ------------[ cut here ]------------
> [   10.568206] WARNING: CPU: 0 PID: 1 at drivers/clk/clk.c:925 clk_disable+0x28/0x34()
> [   10.568237] Modules linked in:
> [   10.568237] CPU: 0 PID: 1 Comm: swapper/0 Tainted: G        W       3.19.0-rc6-next-20150202 #2037
> [   10.568237] Hardware name: Generic OMAP4 (Flattened Device Tree)
> [   10.568267] [<c0015bdc>] (unwind_backtrace) from [<c001222c>] (show_stack+0x10/0x14)
> [   10.568267] [<c001222c>] (show_stack) from [<c05d2014>] (dump_stack+0x84/0x9c)
> [   10.568267] [<c05d2014>] (dump_stack) from [<c003ea90>] (warn_slowpath_common+0x7c/0xb8)
> [   10.568298] [<c003ea90>] (warn_slowpath_common) from [<c003eb68>] (warn_slowpath_null+0x1c/0x24)
> [   10.568298] [<c003eb68>] (warn_slowpath_null) from [<c04c1ffc>] (clk_disable+0x28/0x34)
> [   10.568328] [<c04c1ffc>] (clk_disable) from [<c0025b3c>] (_disable_clocks+0x18/0x68)
> [   10.568328] [<c0025b3c>] (_disable_clocks) from [<c0026f14>] (_idle+0x10c/0x214)
> [   10.568328] [<c0026f14>] (_idle) from [<c0855fac>] (_setup+0x338/0x410)
> [   10.568359] [<c0855fac>] (_setup) from [<c0027360>] (omap_hwmod_for_each+0x34/0x60)
> [   10.568359] [<c0027360>] (omap_hwmod_for_each) from [<c08563c4>] (__omap_hwmod_setup_all+0x30/0x40)
> [   10.568389] [<c08563c4>] (__omap_hwmod_setup_all) from [<c0008a04>] (do_one_initcall+0x80/0x1dc)
> [   10.568389] [<c0008a04>] (do_one_initcall) from [<c0848ea0>] (kernel_init_freeable+0x204/0x2d0)
> [   10.568420] [<c0848ea0>] (kernel_init_freeable) from [<c05cdab8>] (kernel_init+0x8/0xec)
> [   10.568420] [<c05cdab8>] (kernel_init) from [<c000e790>] (ret_from_fork+0x14/0x24)
> [   10.568420] ---[ end trace cb88537fdc8fa211 ]---

This looks like mis-matched enable/disable calls. We now have unique
struct clk pointers for every call to clk_get. I haven't yet looked
through the hwmod code but I have a feeling that we're doing something
like this:

	/* enable clock */
	my_clk = clk_get(...);
	clk_prepare_enable(my_clk);
	clk_put(my_clk);

	/* do some work */
	do_work();

	/* disable clock */
	my_clk = clk_get(...);
	clk_disable_unprepare(my_clk);
	clk_put(my_clk);

The above pattern no longer works since my_clk will be two different
unique pointers, but it really should be one stable pointer across the
whole usage of the clk. E.g:

	/* enable clock */
	my_clk = clk_get(...);
	clk_prepare_enable(my_clk);

	/* do some work */
	do_work();

	/* disable clock */
	clk_disable_unprepare(my_clk);
	clk_put(my_clk);

Again, I haven't looked through the code, so the above is just an
educated guess.

Anyways I am testing with an OMAP4460 Panda ES and I didn't see the
above. Is there a test you are running to get this?

> 
> 
> [   10.568450] ------------[ cut here ]------------
> [   10.568450] WARNING: CPU: 0 PID: 1 at arch/arm/mach-omap2/dpll3xxx.c:436 omap3_noncore_dpll_enable+0xdc/0
> x10c()
> [   10.568450] Modules linked in:
> [   10.568481] CPU: 0 PID: 1 Comm: swapper/0 Tainted: G        W       3.19.0-rc6-next-20150202 #2037
> [   10.568481] Hardware name: Generic OMAP4 (Flattened Device Tree)
> [   10.568481] [<c0015bdc>] (unwind_backtrace) from [<c001222c>] (show_stack+0x10/0x14)
> [   10.568511] [<c001222c>] (show_stack) from [<c05d2014>] (dump_stack+0x84/0x9c)
> [   10.568511] [<c05d2014>] (dump_stack) from [<c003ea90>] (warn_slowpath_common+0x7c/0xb8)
> [   10.568511] [<c003ea90>] (warn_slowpath_common) from [<c003eb68>] (warn_slowpath_null+0x1c/0x24)
> [   10.568542] [<c003eb68>] (warn_slowpath_null) from [<c0035800>] (omap3_noncore_dpll_enable+0xdc/0x10c)
> [   10.568542] [<c0035800>] (omap3_noncore_dpll_enable) from [<c04c0a10>] (clk_core_enable+0x60/0x9c)
> [   10.568572] [<c04c0a10>] (clk_core_enable) from [<c04c09f0>] (clk_core_enable+0x40/0x9c)
> [   10.568572] ---[ end trace cb88537fdc8fa212 ]---
> ...

This is the same issue discussed already in this thread[0]. Feedback
from Tero & Paul on how to handle it would be nice.

Please let me know if anything else breaks for you.

Regards,
Mike

> 
> Regards,
> 
> Tony

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

* Re: [PATCH v13 4/6] clk: Add rate constraints to clocks
@ 2015-02-02 17:46                   ` Mike Turquette
  0 siblings, 0 replies; 186+ messages in thread
From: Mike Turquette @ 2015-02-02 17:46 UTC (permalink / raw)
  To: Tony Lindgren, Geert Uytterhoeven
  Cc: Tomeu Vizoso, Stephen Boyd, Linux MIPS Mailing List, linux-doc,
	Chao Xie, Haojian Zhuang, Boris Brezillon, Russell King,
	Jonathan Corbet, Emilio L??pez, Linux-sh list, Alex Elder,
	Zhangfei Gao, Bintian Wang, Matt Porter, linux-omap,
	linux-arm-kernel, linux-kernel, Ralf Baechle, Tero Kristo,
	Manuel Lauss, Maxime Ripard, Javier Martinez Canillas

Quoting Tony Lindgren (2015-02-02 08:12:37)
> * Geert Uytterhoeven <geert@linux-m68k.org> [150202 00:03]:
> > On Sun, Feb 1, 2015 at 11:18 PM, Mike Turquette <mturquette@linaro.org> wrote:
> > > Quoting Tomeu Vizoso (2015-01-31 10:36:22)
> > >> On 31 January 2015 at 02:31, Stephen Boyd <sboyd@codeaurora.org> wrote:
> > >> > On 01/29, Stephen Boyd wrote:
> > >> >> On 01/29/15 05:31, Geert Uytterhoeven wrote:
> > >> >> > Hi Tomeu, Mike,
> > >> >> >
> > >> >> > On Fri, Jan 23, 2015 at 12:03 PM, Tomeu Vizoso
> > >> >> > <tomeu.vizoso@collabora.com> wrote:
> > >> >> >> --- a/drivers/clk/clk.c
> > >> >> >> +++ b/drivers/clk/clk.c
> > >> >> >> @@ -2391,25 +2543,24 @@ int __clk_get(struct clk *clk)
> > >> >> >>         return 1;
> > >> >> >>  }
> > >> >> >>
> > >> >> >> -static void clk_core_put(struct clk_core *core)
> > >> >> >> +void __clk_put(struct clk *clk)
> > >> >> >>  {
> > >> >> >>         struct module *owner;
> > >> >> >>
> > >> >> >> -       owner = core->owner;
> > >> >> >> +       if (!clk || WARN_ON_ONCE(IS_ERR(clk)))
> > >> >> >> +               return;
> > >> >> >>
> > >> >> >>         clk_prepare_lock();
> > >> >> >> -       kref_put(&core->ref, __clk_release);
> > >> >> >> +
> > >> >> >> +       hlist_del(&clk->child_node);
> > >> >> >> +       clk_core_set_rate_nolock(clk->core, clk->core->req_rate);
> > >> >> > At this point, clk->core->req_rate is still zero, causing
> > >> >> > cpg_div6_clock_round_rate() to be called with a zero "rate" parameter,
> > >> >> > e.g. on r8a7791:
> > >> >>
> > >> >> Hmm.. I wonder if we should assign core->req_rate to be the same as
> > >> >> core->rate during __clk_init()? That would make this call to
> > >> >> clk_core_set_rate_nolock() a nop in this case.
> > >> >>
> > >> >
> > >> > Here's a patch to do this
> > >> >
> > >> > ---8<----
> > >> > From: Stephen Boyd <sboyd@codeaurora.org>
> > >> > Subject: [PATCH] clk: Assign a requested rate by default
> > >> >
> > >> > We need to assign a requested rate here so that we avoid
> > >> > requesting a rate of 0 on clocks when we remove clock consumers.
> > >>
> > >> Hi, this looks good to me.
> > >>
> > >> Reviewed-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
> > >
> > > It seems to fix the total boot failure on OMAPs, and hopefully does the
> > > same for SH Mobile and others. I've squashed this into Tomeu's rate
> > > constraints patch to maintain bisect.
> > 
> > Yes, it fixes shmobile. .round_rate() is now called with a sane value of rate.
> 
> Looks like next-20150202 now produces tons of the following errors,
> these from omap4:

next-20150202 is the rolled-back changes from last Friday. I removed the
clock constraints patch and in doing so also rolled back the TI clock
driver migration and clk-private.h removal patches. Those are all back
in clk-next as of last night and it looks as though they missed being
pulled into todays linux-next by a matter of minutes :-/

> 
> [   10.568206] ------------[ cut here ]------------
> [   10.568206] WARNING: CPU: 0 PID: 1 at drivers/clk/clk.c:925 clk_disable+0x28/0x34()
> [   10.568237] Modules linked in:
> [   10.568237] CPU: 0 PID: 1 Comm: swapper/0 Tainted: G        W       3.19.0-rc6-next-20150202 #2037
> [   10.568237] Hardware name: Generic OMAP4 (Flattened Device Tree)
> [   10.568267] [<c0015bdc>] (unwind_backtrace) from [<c001222c>] (show_stack+0x10/0x14)
> [   10.568267] [<c001222c>] (show_stack) from [<c05d2014>] (dump_stack+0x84/0x9c)
> [   10.568267] [<c05d2014>] (dump_stack) from [<c003ea90>] (warn_slowpath_common+0x7c/0xb8)
> [   10.568298] [<c003ea90>] (warn_slowpath_common) from [<c003eb68>] (warn_slowpath_null+0x1c/0x24)
> [   10.568298] [<c003eb68>] (warn_slowpath_null) from [<c04c1ffc>] (clk_disable+0x28/0x34)
> [   10.568328] [<c04c1ffc>] (clk_disable) from [<c0025b3c>] (_disable_clocks+0x18/0x68)
> [   10.568328] [<c0025b3c>] (_disable_clocks) from [<c0026f14>] (_idle+0x10c/0x214)
> [   10.568328] [<c0026f14>] (_idle) from [<c0855fac>] (_setup+0x338/0x410)
> [   10.568359] [<c0855fac>] (_setup) from [<c0027360>] (omap_hwmod_for_each+0x34/0x60)
> [   10.568359] [<c0027360>] (omap_hwmod_for_each) from [<c08563c4>] (__omap_hwmod_setup_all+0x30/0x40)
> [   10.568389] [<c08563c4>] (__omap_hwmod_setup_all) from [<c0008a04>] (do_one_initcall+0x80/0x1dc)
> [   10.568389] [<c0008a04>] (do_one_initcall) from [<c0848ea0>] (kernel_init_freeable+0x204/0x2d0)
> [   10.568420] [<c0848ea0>] (kernel_init_freeable) from [<c05cdab8>] (kernel_init+0x8/0xec)
> [   10.568420] [<c05cdab8>] (kernel_init) from [<c000e790>] (ret_from_fork+0x14/0x24)
> [   10.568420] ---[ end trace cb88537fdc8fa211 ]---

This looks like mis-matched enable/disable calls. We now have unique
struct clk pointers for every call to clk_get. I haven't yet looked
through the hwmod code but I have a feeling that we're doing something
like this:

	/* enable clock */
	my_clk = clk_get(...);
	clk_prepare_enable(my_clk);
	clk_put(my_clk);

	/* do some work */
	do_work();

	/* disable clock */
	my_clk = clk_get(...);
	clk_disable_unprepare(my_clk);
	clk_put(my_clk);

The above pattern no longer works since my_clk will be two different
unique pointers, but it really should be one stable pointer across the
whole usage of the clk. E.g:

	/* enable clock */
	my_clk = clk_get(...);
	clk_prepare_enable(my_clk);

	/* do some work */
	do_work();

	/* disable clock */
	clk_disable_unprepare(my_clk);
	clk_put(my_clk);

Again, I haven't looked through the code, so the above is just an
educated guess.

Anyways I am testing with an OMAP4460 Panda ES and I didn't see the
above. Is there a test you are running to get this?

> 
> 
> [   10.568450] ------------[ cut here ]------------
> [   10.568450] WARNING: CPU: 0 PID: 1 at arch/arm/mach-omap2/dpll3xxx.c:436 omap3_noncore_dpll_enable+0xdc/0
> x10c()
> [   10.568450] Modules linked in:
> [   10.568481] CPU: 0 PID: 1 Comm: swapper/0 Tainted: G        W       3.19.0-rc6-next-20150202 #2037
> [   10.568481] Hardware name: Generic OMAP4 (Flattened Device Tree)
> [   10.568481] [<c0015bdc>] (unwind_backtrace) from [<c001222c>] (show_stack+0x10/0x14)
> [   10.568511] [<c001222c>] (show_stack) from [<c05d2014>] (dump_stack+0x84/0x9c)
> [   10.568511] [<c05d2014>] (dump_stack) from [<c003ea90>] (warn_slowpath_common+0x7c/0xb8)
> [   10.568511] [<c003ea90>] (warn_slowpath_common) from [<c003eb68>] (warn_slowpath_null+0x1c/0x24)
> [   10.568542] [<c003eb68>] (warn_slowpath_null) from [<c0035800>] (omap3_noncore_dpll_enable+0xdc/0x10c)
> [   10.568542] [<c0035800>] (omap3_noncore_dpll_enable) from [<c04c0a10>] (clk_core_enable+0x60/0x9c)
> [   10.568572] [<c04c0a10>] (clk_core_enable) from [<c04c09f0>] (clk_core_enable+0x40/0x9c)
> [   10.568572] ---[ end trace cb88537fdc8fa212 ]---
> ...

This is the same issue discussed already in this thread[0]. Feedback
from Tero & Paul on how to handle it would be nice.

Please let me know if anything else breaks for you.

Regards,
Mike

> 
> Regards,
> 
> Tony

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

* Re: [PATCH v13 4/6] clk: Add rate constraints to clocks
@ 2015-02-02 17:46                   ` Mike Turquette
  0 siblings, 0 replies; 186+ messages in thread
From: Mike Turquette @ 2015-02-02 17:46 UTC (permalink / raw)
  To: Tony Lindgren, Geert Uytterhoeven
  Cc: Tomeu Vizoso, Stephen Boyd, Linux MIPS Mailing List, linux-doc,
	Chao Xie, Haojian Zhuang, Boris Brezillon, Russell King,
	Jonathan Corbet, Emilio L??pez, Linux-sh list, Alex Elder,
	Zhangfei Gao, Bintian Wang, Matt Porter, linux-omap,
	linux-arm-kernel, linux-kernel, Ralf Baechle, Tero Kristo,
	Manuel Lauss, Maxime Ripard, Javier Martinez Canillas

Quoting Tony Lindgren (2015-02-02 08:12:37)
> * Geert Uytterhoeven <geert@linux-m68k.org> [150202 00:03]:
> > On Sun, Feb 1, 2015 at 11:18 PM, Mike Turquette <mturquette@linaro.org> wrote:
> > > Quoting Tomeu Vizoso (2015-01-31 10:36:22)
> > >> On 31 January 2015 at 02:31, Stephen Boyd <sboyd@codeaurora.org> wrote:
> > >> > On 01/29, Stephen Boyd wrote:
> > >> >> On 01/29/15 05:31, Geert Uytterhoeven wrote:
> > >> >> > Hi Tomeu, Mike,
> > >> >> >
> > >> >> > On Fri, Jan 23, 2015 at 12:03 PM, Tomeu Vizoso
> > >> >> > <tomeu.vizoso@collabora.com> wrote:
> > >> >> >> --- a/drivers/clk/clk.c
> > >> >> >> +++ b/drivers/clk/clk.c
> > >> >> >> @@ -2391,25 +2543,24 @@ int __clk_get(struct clk *clk)
> > >> >> >>         return 1;
> > >> >> >>  }
> > >> >> >>
> > >> >> >> -static void clk_core_put(struct clk_core *core)
> > >> >> >> +void __clk_put(struct clk *clk)
> > >> >> >>  {
> > >> >> >>         struct module *owner;
> > >> >> >>
> > >> >> >> -       owner = core->owner;
> > >> >> >> +       if (!clk || WARN_ON_ONCE(IS_ERR(clk)))
> > >> >> >> +               return;
> > >> >> >>
> > >> >> >>         clk_prepare_lock();
> > >> >> >> -       kref_put(&core->ref, __clk_release);
> > >> >> >> +
> > >> >> >> +       hlist_del(&clk->child_node);
> > >> >> >> +       clk_core_set_rate_nolock(clk->core, clk->core->req_rate);
> > >> >> > At this point, clk->core->req_rate is still zero, causing
> > >> >> > cpg_div6_clock_round_rate() to be called with a zero "rate" parameter,
> > >> >> > e.g. on r8a7791:
> > >> >>
> > >> >> Hmm.. I wonder if we should assign core->req_rate to be the same as
> > >> >> core->rate during __clk_init()? That would make this call to
> > >> >> clk_core_set_rate_nolock() a nop in this case.
> > >> >>
> > >> >
> > >> > Here's a patch to do this
> > >> >
> > >> > ---8<----
> > >> > From: Stephen Boyd <sboyd@codeaurora.org>
> > >> > Subject: [PATCH] clk: Assign a requested rate by default
> > >> >
> > >> > We need to assign a requested rate here so that we avoid
> > >> > requesting a rate of 0 on clocks when we remove clock consumers.
> > >>
> > >> Hi, this looks good to me.
> > >>
> > >> Reviewed-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
> > >
> > > It seems to fix the total boot failure on OMAPs, and hopefully does the
> > > same for SH Mobile and others. I've squashed this into Tomeu's rate
> > > constraints patch to maintain bisect.
> > 
> > Yes, it fixes shmobile. .round_rate() is now called with a sane value of rate.
> 
> Looks like next-20150202 now produces tons of the following errors,
> these from omap4:

next-20150202 is the rolled-back changes from last Friday. I removed the
clock constraints patch and in doing so also rolled back the TI clock
driver migration and clk-private.h removal patches. Those are all back
in clk-next as of last night and it looks as though they missed being
pulled into todays linux-next by a matter of minutes :-/

> 
> [   10.568206] ------------[ cut here ]------------
> [   10.568206] WARNING: CPU: 0 PID: 1 at drivers/clk/clk.c:925 clk_disable+0x28/0x34()
> [   10.568237] Modules linked in:
> [   10.568237] CPU: 0 PID: 1 Comm: swapper/0 Tainted: G        W       3.19.0-rc6-next-20150202 #2037
> [   10.568237] Hardware name: Generic OMAP4 (Flattened Device Tree)
> [   10.568267] [<c0015bdc>] (unwind_backtrace) from [<c001222c>] (show_stack+0x10/0x14)
> [   10.568267] [<c001222c>] (show_stack) from [<c05d2014>] (dump_stack+0x84/0x9c)
> [   10.568267] [<c05d2014>] (dump_stack) from [<c003ea90>] (warn_slowpath_common+0x7c/0xb8)
> [   10.568298] [<c003ea90>] (warn_slowpath_common) from [<c003eb68>] (warn_slowpath_null+0x1c/0x24)
> [   10.568298] [<c003eb68>] (warn_slowpath_null) from [<c04c1ffc>] (clk_disable+0x28/0x34)
> [   10.568328] [<c04c1ffc>] (clk_disable) from [<c0025b3c>] (_disable_clocks+0x18/0x68)
> [   10.568328] [<c0025b3c>] (_disable_clocks) from [<c0026f14>] (_idle+0x10c/0x214)
> [   10.568328] [<c0026f14>] (_idle) from [<c0855fac>] (_setup+0x338/0x410)
> [   10.568359] [<c0855fac>] (_setup) from [<c0027360>] (omap_hwmod_for_each+0x34/0x60)
> [   10.568359] [<c0027360>] (omap_hwmod_for_each) from [<c08563c4>] (__omap_hwmod_setup_all+0x30/0x40)
> [   10.568389] [<c08563c4>] (__omap_hwmod_setup_all) from [<c0008a04>] (do_one_initcall+0x80/0x1dc)
> [   10.568389] [<c0008a04>] (do_one_initcall) from [<c0848ea0>] (kernel_init_freeable+0x204/0x2d0)
> [   10.568420] [<c0848ea0>] (kernel_init_freeable) from [<c05cdab8>] (kernel_init+0x8/0xec)
> [   10.568420] [<c05cdab8>] (kernel_init) from [<c000e790>] (ret_from_fork+0x14/0x24)
> [   10.568420] ---[ end trace cb88537fdc8fa211 ]---

This looks like mis-matched enable/disable calls. We now have unique
struct clk pointers for every call to clk_get. I haven't yet looked
through the hwmod code but I have a feeling that we're doing something
like this:

	/* enable clock */
	my_clk = clk_get(...);
	clk_prepare_enable(my_clk);
	clk_put(my_clk);

	/* do some work */
	do_work();

	/* disable clock */
	my_clk = clk_get(...);
	clk_disable_unprepare(my_clk);
	clk_put(my_clk);

The above pattern no longer works since my_clk will be two different
unique pointers, but it really should be one stable pointer across the
whole usage of the clk. E.g:

	/* enable clock */
	my_clk = clk_get(...);
	clk_prepare_enable(my_clk);

	/* do some work */
	do_work();

	/* disable clock */
	clk_disable_unprepare(my_clk);
	clk_put(my_clk);

Again, I haven't looked through the code, so the above is just an
educated guess.

Anyways I am testing with an OMAP4460 Panda ES and I didn't see the
above. Is there a test you are running to get this?

> 
> 
> [   10.568450] ------------[ cut here ]------------
> [   10.568450] WARNING: CPU: 0 PID: 1 at arch/arm/mach-omap2/dpll3xxx.c:436 omap3_noncore_dpll_enable+0xdc/0
> x10c()
> [   10.568450] Modules linked in:
> [   10.568481] CPU: 0 PID: 1 Comm: swapper/0 Tainted: G        W       3.19.0-rc6-next-20150202 #2037
> [   10.568481] Hardware name: Generic OMAP4 (Flattened Device Tree)
> [   10.568481] [<c0015bdc>] (unwind_backtrace) from [<c001222c>] (show_stack+0x10/0x14)
> [   10.568511] [<c001222c>] (show_stack) from [<c05d2014>] (dump_stack+0x84/0x9c)
> [   10.568511] [<c05d2014>] (dump_stack) from [<c003ea90>] (warn_slowpath_common+0x7c/0xb8)
> [   10.568511] [<c003ea90>] (warn_slowpath_common) from [<c003eb68>] (warn_slowpath_null+0x1c/0x24)
> [   10.568542] [<c003eb68>] (warn_slowpath_null) from [<c0035800>] (omap3_noncore_dpll_enable+0xdc/0x10c)
> [   10.568542] [<c0035800>] (omap3_noncore_dpll_enable) from [<c04c0a10>] (clk_core_enable+0x60/0x9c)
> [   10.568572] [<c04c0a10>] (clk_core_enable) from [<c04c09f0>] (clk_core_enable+0x40/0x9c)
> [   10.568572] ---[ end trace cb88537fdc8fa212 ]---
> ...

This is the same issue discussed already in this thread[0]. Feedback
from Tero & Paul on how to handle it would be nice.

Please let me know if anything else breaks for you.

Regards,
Mike

> 
> Regards,
> 
> Tony

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

* Re: [PATCH v13 4/6] clk: Add rate constraints to clocks
@ 2015-02-02 17:46                   ` Mike Turquette
  0 siblings, 0 replies; 186+ messages in thread
From: Mike Turquette @ 2015-02-02 17:46 UTC (permalink / raw)
  To: Tony Lindgren, Geert Uytterhoeven
  Cc: Tomeu Vizoso, Stephen Boyd, Linux MIPS Mailing List, linux-doc,
	Chao Xie, Haojian Zhuang, Boris Brezillon, Russell King,
	Jonathan Corbet, Emilio L??pez, Linux-sh list, Alex Elder,
	Zhangfei Gao, Bintian Wang, Matt Porter, linux-omap,
	linux-arm-kernel, linux-kernel, Ralf Baechle

Quoting Tony Lindgren (2015-02-02 08:12:37)
> * Geert Uytterhoeven <geert@linux-m68k.org> [150202 00:03]:
> > On Sun, Feb 1, 2015 at 11:18 PM, Mike Turquette <mturquette@linaro.org> wrote:
> > > Quoting Tomeu Vizoso (2015-01-31 10:36:22)
> > >> On 31 January 2015 at 02:31, Stephen Boyd <sboyd@codeaurora.org> wrote:
> > >> > On 01/29, Stephen Boyd wrote:
> > >> >> On 01/29/15 05:31, Geert Uytterhoeven wrote:
> > >> >> > Hi Tomeu, Mike,
> > >> >> >
> > >> >> > On Fri, Jan 23, 2015 at 12:03 PM, Tomeu Vizoso
> > >> >> > <tomeu.vizoso@collabora.com> wrote:
> > >> >> >> --- a/drivers/clk/clk.c
> > >> >> >> +++ b/drivers/clk/clk.c
> > >> >> >> @@ -2391,25 +2543,24 @@ int __clk_get(struct clk *clk)
> > >> >> >>         return 1;
> > >> >> >>  }
> > >> >> >>
> > >> >> >> -static void clk_core_put(struct clk_core *core)
> > >> >> >> +void __clk_put(struct clk *clk)
> > >> >> >>  {
> > >> >> >>         struct module *owner;
> > >> >> >>
> > >> >> >> -       owner = core->owner;
> > >> >> >> +       if (!clk || WARN_ON_ONCE(IS_ERR(clk)))
> > >> >> >> +               return;
> > >> >> >>
> > >> >> >>         clk_prepare_lock();
> > >> >> >> -       kref_put(&core->ref, __clk_release);
> > >> >> >> +
> > >> >> >> +       hlist_del(&clk->child_node);
> > >> >> >> +       clk_core_set_rate_nolock(clk->core, clk->core->req_rate);
> > >> >> > At this point, clk->core->req_rate is still zero, causing
> > >> >> > cpg_div6_clock_round_rate() to be called with a zero "rate" parameter,
> > >> >> > e.g. on r8a7791:
> > >> >>
> > >> >> Hmm.. I wonder if we should assign core->req_rate to be the same as
> > >> >> core->rate during __clk_init()? That would make this call to
> > >> >> clk_core_set_rate_nolock() a nop in this case.
> > >> >>
> > >> >
> > >> > Here's a patch to do this
> > >> >
> > >> > ---8<----
> > >> > From: Stephen Boyd <sboyd@codeaurora.org>
> > >> > Subject: [PATCH] clk: Assign a requested rate by default
> > >> >
> > >> > We need to assign a requested rate here so that we avoid
> > >> > requesting a rate of 0 on clocks when we remove clock consumers.
> > >>
> > >> Hi, this looks good to me.
> > >>
> > >> Reviewed-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
> > >
> > > It seems to fix the total boot failure on OMAPs, and hopefully does the
> > > same for SH Mobile and others. I've squashed this into Tomeu's rate
> > > constraints patch to maintain bisect.
> > 
> > Yes, it fixes shmobile. .round_rate() is now called with a sane value of rate.
> 
> Looks like next-20150202 now produces tons of the following errors,
> these from omap4:

next-20150202 is the rolled-back changes from last Friday. I removed the
clock constraints patch and in doing so also rolled back the TI clock
driver migration and clk-private.h removal patches. Those are all back
in clk-next as of last night and it looks as though they missed being
pulled into todays linux-next by a matter of minutes :-/

> 
> [   10.568206] ------------[ cut here ]------------
> [   10.568206] WARNING: CPU: 0 PID: 1 at drivers/clk/clk.c:925 clk_disable+0x28/0x34()
> [   10.568237] Modules linked in:
> [   10.568237] CPU: 0 PID: 1 Comm: swapper/0 Tainted: G        W       3.19.0-rc6-next-20150202 #2037
> [   10.568237] Hardware name: Generic OMAP4 (Flattened Device Tree)
> [   10.568267] [<c0015bdc>] (unwind_backtrace) from [<c001222c>] (show_stack+0x10/0x14)
> [   10.568267] [<c001222c>] (show_stack) from [<c05d2014>] (dump_stack+0x84/0x9c)
> [   10.568267] [<c05d2014>] (dump_stack) from [<c003ea90>] (warn_slowpath_common+0x7c/0xb8)
> [   10.568298] [<c003ea90>] (warn_slowpath_common) from [<c003eb68>] (warn_slowpath_null+0x1c/0x24)
> [   10.568298] [<c003eb68>] (warn_slowpath_null) from [<c04c1ffc>] (clk_disable+0x28/0x34)
> [   10.568328] [<c04c1ffc>] (clk_disable) from [<c0025b3c>] (_disable_clocks+0x18/0x68)
> [   10.568328] [<c0025b3c>] (_disable_clocks) from [<c0026f14>] (_idle+0x10c/0x214)
> [   10.568328] [<c0026f14>] (_idle) from [<c0855fac>] (_setup+0x338/0x410)
> [   10.568359] [<c0855fac>] (_setup) from [<c0027360>] (omap_hwmod_for_each+0x34/0x60)
> [   10.568359] [<c0027360>] (omap_hwmod_for_each) from [<c08563c4>] (__omap_hwmod_setup_all+0x30/0x40)
> [   10.568389] [<c08563c4>] (__omap_hwmod_setup_all) from [<c0008a04>] (do_one_initcall+0x80/0x1dc)
> [   10.568389] [<c0008a04>] (do_one_initcall) from [<c0848ea0>] (kernel_init_freeable+0x204/0x2d0)
> [   10.568420] [<c0848ea0>] (kernel_init_freeable) from [<c05cdab8>] (kernel_init+0x8/0xec)
> [   10.568420] [<c05cdab8>] (kernel_init) from [<c000e790>] (ret_from_fork+0x14/0x24)
> [   10.568420] ---[ end trace cb88537fdc8fa211 ]---

This looks like mis-matched enable/disable calls. We now have unique
struct clk pointers for every call to clk_get. I haven't yet looked
through the hwmod code but I have a feeling that we're doing something
like this:

	/* enable clock */
	my_clk = clk_get(...);
	clk_prepare_enable(my_clk);
	clk_put(my_clk);

	/* do some work */
	do_work();

	/* disable clock */
	my_clk = clk_get(...);
	clk_disable_unprepare(my_clk);
	clk_put(my_clk);

The above pattern no longer works since my_clk will be two different
unique pointers, but it really should be one stable pointer across the
whole usage of the clk. E.g:

	/* enable clock */
	my_clk = clk_get(...);
	clk_prepare_enable(my_clk);

	/* do some work */
	do_work();

	/* disable clock */
	clk_disable_unprepare(my_clk);
	clk_put(my_clk);

Again, I haven't looked through the code, so the above is just an
educated guess.

Anyways I am testing with an OMAP4460 Panda ES and I didn't see the
above. Is there a test you are running to get this?

> 
> 
> [   10.568450] ------------[ cut here ]------------
> [   10.568450] WARNING: CPU: 0 PID: 1 at arch/arm/mach-omap2/dpll3xxx.c:436 omap3_noncore_dpll_enable+0xdc/0
> x10c()
> [   10.568450] Modules linked in:
> [   10.568481] CPU: 0 PID: 1 Comm: swapper/0 Tainted: G        W       3.19.0-rc6-next-20150202 #2037
> [   10.568481] Hardware name: Generic OMAP4 (Flattened Device Tree)
> [   10.568481] [<c0015bdc>] (unwind_backtrace) from [<c001222c>] (show_stack+0x10/0x14)
> [   10.568511] [<c001222c>] (show_stack) from [<c05d2014>] (dump_stack+0x84/0x9c)
> [   10.568511] [<c05d2014>] (dump_stack) from [<c003ea90>] (warn_slowpath_common+0x7c/0xb8)
> [   10.568511] [<c003ea90>] (warn_slowpath_common) from [<c003eb68>] (warn_slowpath_null+0x1c/0x24)
> [   10.568542] [<c003eb68>] (warn_slowpath_null) from [<c0035800>] (omap3_noncore_dpll_enable+0xdc/0x10c)
> [   10.568542] [<c0035800>] (omap3_noncore_dpll_enable) from [<c04c0a10>] (clk_core_enable+0x60/0x9c)
> [   10.568572] [<c04c0a10>] (clk_core_enable) from [<c04c09f0>] (clk_core_enable+0x40/0x9c)
> [   10.568572] ---[ end trace cb88537fdc8fa212 ]---
> ...

This is the same issue discussed already in this thread[0]. Feedback
from Tero & Paul on how to handle it would be nice.

Please let me know if anything else breaks for you.

Regards,
Mike

> 
> Regards,
> 
> Tony

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

* [PATCH v13 4/6] clk: Add rate constraints to clocks
@ 2015-02-02 17:46                   ` Mike Turquette
  0 siblings, 0 replies; 186+ messages in thread
From: Mike Turquette @ 2015-02-02 17:46 UTC (permalink / raw)
  To: linux-arm-kernel

Quoting Tony Lindgren (2015-02-02 08:12:37)
> * Geert Uytterhoeven <geert@linux-m68k.org> [150202 00:03]:
> > On Sun, Feb 1, 2015 at 11:18 PM, Mike Turquette <mturquette@linaro.org> wrote:
> > > Quoting Tomeu Vizoso (2015-01-31 10:36:22)
> > >> On 31 January 2015 at 02:31, Stephen Boyd <sboyd@codeaurora.org> wrote:
> > >> > On 01/29, Stephen Boyd wrote:
> > >> >> On 01/29/15 05:31, Geert Uytterhoeven wrote:
> > >> >> > Hi Tomeu, Mike,
> > >> >> >
> > >> >> > On Fri, Jan 23, 2015 at 12:03 PM, Tomeu Vizoso
> > >> >> > <tomeu.vizoso@collabora.com> wrote:
> > >> >> >> --- a/drivers/clk/clk.c
> > >> >> >> +++ b/drivers/clk/clk.c
> > >> >> >> @@ -2391,25 +2543,24 @@ int __clk_get(struct clk *clk)
> > >> >> >>         return 1;
> > >> >> >>  }
> > >> >> >>
> > >> >> >> -static void clk_core_put(struct clk_core *core)
> > >> >> >> +void __clk_put(struct clk *clk)
> > >> >> >>  {
> > >> >> >>         struct module *owner;
> > >> >> >>
> > >> >> >> -       owner = core->owner;
> > >> >> >> +       if (!clk || WARN_ON_ONCE(IS_ERR(clk)))
> > >> >> >> +               return;
> > >> >> >>
> > >> >> >>         clk_prepare_lock();
> > >> >> >> -       kref_put(&core->ref, __clk_release);
> > >> >> >> +
> > >> >> >> +       hlist_del(&clk->child_node);
> > >> >> >> +       clk_core_set_rate_nolock(clk->core, clk->core->req_rate);
> > >> >> > At this point, clk->core->req_rate is still zero, causing
> > >> >> > cpg_div6_clock_round_rate() to be called with a zero "rate" parameter,
> > >> >> > e.g. on r8a7791:
> > >> >>
> > >> >> Hmm.. I wonder if we should assign core->req_rate to be the same as
> > >> >> core->rate during __clk_init()? That would make this call to
> > >> >> clk_core_set_rate_nolock() a nop in this case.
> > >> >>
> > >> >
> > >> > Here's a patch to do this
> > >> >
> > >> > ---8<----
> > >> > From: Stephen Boyd <sboyd@codeaurora.org>
> > >> > Subject: [PATCH] clk: Assign a requested rate by default
> > >> >
> > >> > We need to assign a requested rate here so that we avoid
> > >> > requesting a rate of 0 on clocks when we remove clock consumers.
> > >>
> > >> Hi, this looks good to me.
> > >>
> > >> Reviewed-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
> > >
> > > It seems to fix the total boot failure on OMAPs, and hopefully does the
> > > same for SH Mobile and others. I've squashed this into Tomeu's rate
> > > constraints patch to maintain bisect.
> > 
> > Yes, it fixes shmobile. .round_rate() is now called with a sane value of rate.
> 
> Looks like next-20150202 now produces tons of the following errors,
> these from omap4:

next-20150202 is the rolled-back changes from last Friday. I removed the
clock constraints patch and in doing so also rolled back the TI clock
driver migration and clk-private.h removal patches. Those are all back
in clk-next as of last night and it looks as though they missed being
pulled into todays linux-next by a matter of minutes :-/

> 
> [   10.568206] ------------[ cut here ]------------
> [   10.568206] WARNING: CPU: 0 PID: 1 at drivers/clk/clk.c:925 clk_disable+0x28/0x34()
> [   10.568237] Modules linked in:
> [   10.568237] CPU: 0 PID: 1 Comm: swapper/0 Tainted: G        W       3.19.0-rc6-next-20150202 #2037
> [   10.568237] Hardware name: Generic OMAP4 (Flattened Device Tree)
> [   10.568267] [<c0015bdc>] (unwind_backtrace) from [<c001222c>] (show_stack+0x10/0x14)
> [   10.568267] [<c001222c>] (show_stack) from [<c05d2014>] (dump_stack+0x84/0x9c)
> [   10.568267] [<c05d2014>] (dump_stack) from [<c003ea90>] (warn_slowpath_common+0x7c/0xb8)
> [   10.568298] [<c003ea90>] (warn_slowpath_common) from [<c003eb68>] (warn_slowpath_null+0x1c/0x24)
> [   10.568298] [<c003eb68>] (warn_slowpath_null) from [<c04c1ffc>] (clk_disable+0x28/0x34)
> [   10.568328] [<c04c1ffc>] (clk_disable) from [<c0025b3c>] (_disable_clocks+0x18/0x68)
> [   10.568328] [<c0025b3c>] (_disable_clocks) from [<c0026f14>] (_idle+0x10c/0x214)
> [   10.568328] [<c0026f14>] (_idle) from [<c0855fac>] (_setup+0x338/0x410)
> [   10.568359] [<c0855fac>] (_setup) from [<c0027360>] (omap_hwmod_for_each+0x34/0x60)
> [   10.568359] [<c0027360>] (omap_hwmod_for_each) from [<c08563c4>] (__omap_hwmod_setup_all+0x30/0x40)
> [   10.568389] [<c08563c4>] (__omap_hwmod_setup_all) from [<c0008a04>] (do_one_initcall+0x80/0x1dc)
> [   10.568389] [<c0008a04>] (do_one_initcall) from [<c0848ea0>] (kernel_init_freeable+0x204/0x2d0)
> [   10.568420] [<c0848ea0>] (kernel_init_freeable) from [<c05cdab8>] (kernel_init+0x8/0xec)
> [   10.568420] [<c05cdab8>] (kernel_init) from [<c000e790>] (ret_from_fork+0x14/0x24)
> [   10.568420] ---[ end trace cb88537fdc8fa211 ]---

This looks like mis-matched enable/disable calls. We now have unique
struct clk pointers for every call to clk_get. I haven't yet looked
through the hwmod code but I have a feeling that we're doing something
like this:

	/* enable clock */
	my_clk = clk_get(...);
	clk_prepare_enable(my_clk);
	clk_put(my_clk);

	/* do some work */
	do_work();

	/* disable clock */
	my_clk = clk_get(...);
	clk_disable_unprepare(my_clk);
	clk_put(my_clk);

The above pattern no longer works since my_clk will be two different
unique pointers, but it really should be one stable pointer across the
whole usage of the clk. E.g:

	/* enable clock */
	my_clk = clk_get(...);
	clk_prepare_enable(my_clk);

	/* do some work */
	do_work();

	/* disable clock */
	clk_disable_unprepare(my_clk);
	clk_put(my_clk);

Again, I haven't looked through the code, so the above is just an
educated guess.

Anyways I am testing with an OMAP4460 Panda ES and I didn't see the
above. Is there a test you are running to get this?

> 
> 
> [   10.568450] ------------[ cut here ]------------
> [   10.568450] WARNING: CPU: 0 PID: 1 at arch/arm/mach-omap2/dpll3xxx.c:436 omap3_noncore_dpll_enable+0xdc/0
> x10c()
> [   10.568450] Modules linked in:
> [   10.568481] CPU: 0 PID: 1 Comm: swapper/0 Tainted: G        W       3.19.0-rc6-next-20150202 #2037
> [   10.568481] Hardware name: Generic OMAP4 (Flattened Device Tree)
> [   10.568481] [<c0015bdc>] (unwind_backtrace) from [<c001222c>] (show_stack+0x10/0x14)
> [   10.568511] [<c001222c>] (show_stack) from [<c05d2014>] (dump_stack+0x84/0x9c)
> [   10.568511] [<c05d2014>] (dump_stack) from [<c003ea90>] (warn_slowpath_common+0x7c/0xb8)
> [   10.568511] [<c003ea90>] (warn_slowpath_common) from [<c003eb68>] (warn_slowpath_null+0x1c/0x24)
> [   10.568542] [<c003eb68>] (warn_slowpath_null) from [<c0035800>] (omap3_noncore_dpll_enable+0xdc/0x10c)
> [   10.568542] [<c0035800>] (omap3_noncore_dpll_enable) from [<c04c0a10>] (clk_core_enable+0x60/0x9c)
> [   10.568572] [<c04c0a10>] (clk_core_enable) from [<c04c09f0>] (clk_core_enable+0x40/0x9c)
> [   10.568572] ---[ end trace cb88537fdc8fa212 ]---
> ...

This is the same issue discussed already in this thread[0]. Feedback
from Tero & Paul on how to handle it would be nice.

Please let me know if anything else breaks for you.

Regards,
Mike

> 
> Regards,
> 
> Tony

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

* Re: [PATCH v13 4/6] clk: Add rate constraints to clocks
  2015-02-02 17:46                   ` Mike Turquette
                                       ` (2 preceding siblings ...)
  (?)
@ 2015-02-02 17:49                     ` Russell King - ARM Linux
  -1 siblings, 0 replies; 186+ messages in thread
From: Russell King - ARM Linux @ 2015-02-02 17:49 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Feb 02, 2015 at 09:46:46AM -0800, Mike Turquette wrote:
> This looks like mis-matched enable/disable calls. We now have unique
> struct clk pointers for every call to clk_get. I haven't yet looked
> through the hwmod code but I have a feeling that we're doing something
> like this:
> 
> 	/* enable clock */
> 	my_clk = clk_get(...);
> 	clk_prepare_enable(my_clk);
> 	clk_put(my_clk);
> 
> 	/* do some work */
> 	do_work();
> 
> 	/* disable clock */
> 	my_clk = clk_get(...);
> 	clk_disable_unprepare(my_clk);
> 	clk_put(my_clk);
> 
> The above pattern no longer works since my_clk will be two different
> unique pointers, but it really should be one stable pointer across the
> whole usage of the clk. E.g:

Yes, it has always been documented that shall be the case.  Anyone doing
the above is basically broken.

-- 
FTTC broadband for 0.8mile line: currently at 10.5Mbps down 400kbps up
according to speedtest.net.

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

* Re: [PATCH v13 4/6] clk: Add rate constraints to clocks
@ 2015-02-02 17:49                     ` Russell King - ARM Linux
  0 siblings, 0 replies; 186+ messages in thread
From: Russell King - ARM Linux @ 2015-02-02 17:49 UTC (permalink / raw)
  To: Mike Turquette
  Cc: Tony Lindgren, Geert Uytterhoeven, Tomeu Vizoso, Stephen Boyd,
	Linux MIPS Mailing List, linux-doc, Chao Xie, Haojian Zhuang,
	Boris Brezillon, Jonathan Corbet, Emilio L??pez, Linux-sh list,
	Alex Elder, Zhangfei Gao, Bintian Wang, Matt Porter, linux-omap,
	linux-arm-kernel, linux-kernel, Ralf Baechle, Tero Kristo,
	Manuel Lauss, Maxime Ripard, Javier Martinez Canillas

On Mon, Feb 02, 2015 at 09:46:46AM -0800, Mike Turquette wrote:
> This looks like mis-matched enable/disable calls. We now have unique
> struct clk pointers for every call to clk_get. I haven't yet looked
> through the hwmod code but I have a feeling that we're doing something
> like this:
> 
> 	/* enable clock */
> 	my_clk = clk_get(...);
> 	clk_prepare_enable(my_clk);
> 	clk_put(my_clk);
> 
> 	/* do some work */
> 	do_work();
> 
> 	/* disable clock */
> 	my_clk = clk_get(...);
> 	clk_disable_unprepare(my_clk);
> 	clk_put(my_clk);
> 
> The above pattern no longer works since my_clk will be two different
> unique pointers, but it really should be one stable pointer across the
> whole usage of the clk. E.g:

Yes, it has always been documented that shall be the case.  Anyone doing
the above is basically broken.

-- 
FTTC broadband for 0.8mile line: currently at 10.5Mbps down 400kbps up
according to speedtest.net.

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

* Re: [PATCH v13 4/6] clk: Add rate constraints to clocks
@ 2015-02-02 17:49                     ` Russell King - ARM Linux
  0 siblings, 0 replies; 186+ messages in thread
From: Russell King - ARM Linux @ 2015-02-02 17:49 UTC (permalink / raw)
  To: Mike Turquette
  Cc: Tony Lindgren, Geert Uytterhoeven, Tomeu Vizoso, Stephen Boyd,
	Linux MIPS Mailing List, linux-doc, Chao Xie, Haojian Zhuang,
	Boris Brezillon, Jonathan Corbet, Emilio L??pez, Linux-sh list,
	Alex Elder, Zhangfei Gao, Bintian Wang, Matt Porter, linux-omap,
	linux-arm-kernel, linux-kernel, Ralf Baechle, Tero Kristo,
	Manuel Lauss, Maxime Ripard, Javier Martinez Canillas

On Mon, Feb 02, 2015 at 09:46:46AM -0800, Mike Turquette wrote:
> This looks like mis-matched enable/disable calls. We now have unique
> struct clk pointers for every call to clk_get. I haven't yet looked
> through the hwmod code but I have a feeling that we're doing something
> like this:
> 
> 	/* enable clock */
> 	my_clk = clk_get(...);
> 	clk_prepare_enable(my_clk);
> 	clk_put(my_clk);
> 
> 	/* do some work */
> 	do_work();
> 
> 	/* disable clock */
> 	my_clk = clk_get(...);
> 	clk_disable_unprepare(my_clk);
> 	clk_put(my_clk);
> 
> The above pattern no longer works since my_clk will be two different
> unique pointers, but it really should be one stable pointer across the
> whole usage of the clk. E.g:

Yes, it has always been documented that shall be the case.  Anyone doing
the above is basically broken.

-- 
FTTC broadband for 0.8mile line: currently at 10.5Mbps down 400kbps up
according to speedtest.net.

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

* Re: [PATCH v13 4/6] clk: Add rate constraints to clocks
@ 2015-02-02 17:49                     ` Russell King - ARM Linux
  0 siblings, 0 replies; 186+ messages in thread
From: Russell King - ARM Linux @ 2015-02-02 17:49 UTC (permalink / raw)
  To: Mike Turquette
  Cc: Tony Lindgren, Geert Uytterhoeven, Tomeu Vizoso, Stephen Boyd,
	Linux MIPS Mailing List, linux-doc, Chao Xie, Haojian Zhuang,
	Boris Brezillon, Jonathan Corbet, Emilio L??pez, Linux-sh list,
	Alex Elder, Zhangfei Gao, Bintian Wang, Matt Porter, linux-omap,
	linux-arm-kernel, linux-kernel, Ralf Baechle

On Mon, Feb 02, 2015 at 09:46:46AM -0800, Mike Turquette wrote:
> This looks like mis-matched enable/disable calls. We now have unique
> struct clk pointers for every call to clk_get. I haven't yet looked
> through the hwmod code but I have a feeling that we're doing something
> like this:
> 
> 	/* enable clock */
> 	my_clk = clk_get(...);
> 	clk_prepare_enable(my_clk);
> 	clk_put(my_clk);
> 
> 	/* do some work */
> 	do_work();
> 
> 	/* disable clock */
> 	my_clk = clk_get(...);
> 	clk_disable_unprepare(my_clk);
> 	clk_put(my_clk);
> 
> The above pattern no longer works since my_clk will be two different
> unique pointers, but it really should be one stable pointer across the
> whole usage of the clk. E.g:

Yes, it has always been documented that shall be the case.  Anyone doing
the above is basically broken.

-- 
FTTC broadband for 0.8mile line: currently at 10.5Mbps down 400kbps up
according to speedtest.net.

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

* [PATCH v13 4/6] clk: Add rate constraints to clocks
@ 2015-02-02 17:49                     ` Russell King - ARM Linux
  0 siblings, 0 replies; 186+ messages in thread
From: Russell King - ARM Linux @ 2015-02-02 17:49 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Feb 02, 2015 at 09:46:46AM -0800, Mike Turquette wrote:
> This looks like mis-matched enable/disable calls. We now have unique
> struct clk pointers for every call to clk_get. I haven't yet looked
> through the hwmod code but I have a feeling that we're doing something
> like this:
> 
> 	/* enable clock */
> 	my_clk = clk_get(...);
> 	clk_prepare_enable(my_clk);
> 	clk_put(my_clk);
> 
> 	/* do some work */
> 	do_work();
> 
> 	/* disable clock */
> 	my_clk = clk_get(...);
> 	clk_disable_unprepare(my_clk);
> 	clk_put(my_clk);
> 
> The above pattern no longer works since my_clk will be two different
> unique pointers, but it really should be one stable pointer across the
> whole usage of the clk. E.g:

Yes, it has always been documented that shall be the case.  Anyone doing
the above is basically broken.

-- 
FTTC broadband for 0.8mile line: currently at 10.5Mbps down 400kbps up
according to speedtest.net.

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

* Re: [PATCH v13 4/6] clk: Add rate constraints to clocks
  2015-02-02 17:46                   ` Mike Turquette
                                       ` (2 preceding siblings ...)
  (?)
@ 2015-02-02 19:21                     ` Tony Lindgren
  -1 siblings, 0 replies; 186+ messages in thread
From: Tony Lindgren @ 2015-02-02 19:21 UTC (permalink / raw)
  To: linux-arm-kernel

* Mike Turquette <mturquette@linaro.org> [150202 09:50]:
> Quoting Tony Lindgren (2015-02-02 08:12:37)
> > 
> > [   10.568206] ------------[ cut here ]------------
> > [   10.568206] WARNING: CPU: 0 PID: 1 at drivers/clk/clk.c:925 clk_disable+0x28/0x34()
> > [   10.568237] Modules linked in:
> > [   10.568237] CPU: 0 PID: 1 Comm: swapper/0 Tainted: G        W       3.19.0-rc6-next-20150202 #2037
> > [   10.568237] Hardware name: Generic OMAP4 (Flattened Device Tree)
> > [   10.568267] [<c0015bdc>] (unwind_backtrace) from [<c001222c>] (show_stack+0x10/0x14)
> > [   10.568267] [<c001222c>] (show_stack) from [<c05d2014>] (dump_stack+0x84/0x9c)
> > [   10.568267] [<c05d2014>] (dump_stack) from [<c003ea90>] (warn_slowpath_common+0x7c/0xb8)
> > [   10.568298] [<c003ea90>] (warn_slowpath_common) from [<c003eb68>] (warn_slowpath_null+0x1c/0x24)
> > [   10.568298] [<c003eb68>] (warn_slowpath_null) from [<c04c1ffc>] (clk_disable+0x28/0x34)
> > [   10.568328] [<c04c1ffc>] (clk_disable) from [<c0025b3c>] (_disable_clocks+0x18/0x68)
> > [   10.568328] [<c0025b3c>] (_disable_clocks) from [<c0026f14>] (_idle+0x10c/0x214)
> > [   10.568328] [<c0026f14>] (_idle) from [<c0855fac>] (_setup+0x338/0x410)
> > [   10.568359] [<c0855fac>] (_setup) from [<c0027360>] (omap_hwmod_for_each+0x34/0x60)
> > [   10.568359] [<c0027360>] (omap_hwmod_for_each) from [<c08563c4>] (__omap_hwmod_setup_all+0x30/0x40)
> > [   10.568389] [<c08563c4>] (__omap_hwmod_setup_all) from [<c0008a04>] (do_one_initcall+0x80/0x1dc)
> > [   10.568389] [<c0008a04>] (do_one_initcall) from [<c0848ea0>] (kernel_init_freeable+0x204/0x2d0)
> > [   10.568420] [<c0848ea0>] (kernel_init_freeable) from [<c05cdab8>] (kernel_init+0x8/0xec)
> > [   10.568420] [<c05cdab8>] (kernel_init) from [<c000e790>] (ret_from_fork+0x14/0x24)
> > [   10.568420] ---[ end trace cb88537fdc8fa211 ]---

For reference, the above is line 992 in clk-next.

> This looks like mis-matched enable/disable calls. We now have unique
> struct clk pointers for every call to clk_get. I haven't yet looked
> through the hwmod code but I have a feeling that we're doing something
> like this:
> 
> 	/* enable clock */
> 	my_clk = clk_get(...);
> 	clk_prepare_enable(my_clk);
> 	clk_put(my_clk);
> 
> 	/* do some work */
> 	do_work();
> 
> 	/* disable clock */
> 	my_clk = clk_get(...);
> 	clk_disable_unprepare(my_clk);
> 	clk_put(my_clk);
> 
> The above pattern no longer works since my_clk will be two different
> unique pointers, but it really should be one stable pointer across the
> whole usage of the clk. E.g:
> 
> 	/* enable clock */
> 	my_clk = clk_get(...);
> 	clk_prepare_enable(my_clk);
> 
> 	/* do some work */
> 	do_work();
> 
> 	/* disable clock */
> 	clk_disable_unprepare(my_clk);
> 	clk_put(my_clk);
> 
> Again, I haven't looked through the code, so the above is just an
> educated guess.
> 
> Anyways I am testing with an OMAP4460 Panda ES and I didn't see the
> above. Is there a test you are running to get this?

Just booting 4430-sdp with omap2plus_defconfig. And git bisect
points to 59cf3fcf9baf ("clk: Make clk API return per-user struct
clk instances") as you already guessed.
 
> > [   10.568450] ------------[ cut here ]------------
> > [   10.568450] WARNING: CPU: 0 PID: 1 at arch/arm/mach-omap2/dpll3xxx.c:436 omap3_noncore_dpll_enable+0xdc/0
> > x10c()
> > [   10.568450] Modules linked in:
> > [   10.568481] CPU: 0 PID: 1 Comm: swapper/0 Tainted: G        W       3.19.0-rc6-next-20150202 #2037
> > [   10.568481] Hardware name: Generic OMAP4 (Flattened Device Tree)
> > [   10.568481] [<c0015bdc>] (unwind_backtrace) from [<c001222c>] (show_stack+0x10/0x14)
> > [   10.568511] [<c001222c>] (show_stack) from [<c05d2014>] (dump_stack+0x84/0x9c)
> > [   10.568511] [<c05d2014>] (dump_stack) from [<c003ea90>] (warn_slowpath_common+0x7c/0xb8)
> > [   10.568511] [<c003ea90>] (warn_slowpath_common) from [<c003eb68>] (warn_slowpath_null+0x1c/0x24)
> > [   10.568542] [<c003eb68>] (warn_slowpath_null) from [<c0035800>] (omap3_noncore_dpll_enable+0xdc/0x10c)
> > [   10.568542] [<c0035800>] (omap3_noncore_dpll_enable) from [<c04c0a10>] (clk_core_enable+0x60/0x9c)
> > [   10.568572] [<c04c0a10>] (clk_core_enable) from [<c04c09f0>] (clk_core_enable+0x40/0x9c)
> > [   10.568572] ---[ end trace cb88537fdc8fa212 ]---
> > ...
> 
> This is the same issue discussed already in this thread[0]. Feedback
> from Tero & Paul on how to handle it would be nice.

Yes that one is a separate issue.
 
> Please let me know if anything else breaks for you.

Also off-idle on omap3 seems to be broken by commit 59cf3fcf9baf.

Regards,

Tony

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

* Re: [PATCH v13 4/6] clk: Add rate constraints to clocks
@ 2015-02-02 19:21                     ` Tony Lindgren
  0 siblings, 0 replies; 186+ messages in thread
From: Tony Lindgren @ 2015-02-02 19:21 UTC (permalink / raw)
  To: Mike Turquette
  Cc: Geert Uytterhoeven, Tomeu Vizoso, Stephen Boyd,
	Linux MIPS Mailing List, linux-doc, Chao Xie, Haojian Zhuang,
	Boris Brezillon, Russell King, Jonathan Corbet, Emilio L??pez,
	Linux-sh list, Alex Elder, Zhangfei Gao, Bintian Wang,
	Matt Porter, linux-omap, linux-arm-kernel, linux-kernel,
	Ralf Baechle, Tero Kristo, Manuel Lauss, Maxime Ripard,
	Javier Martinez Canillas, Paul Walmsley

* Mike Turquette <mturquette@linaro.org> [150202 09:50]:
> Quoting Tony Lindgren (2015-02-02 08:12:37)
> > 
> > [   10.568206] ------------[ cut here ]------------
> > [   10.568206] WARNING: CPU: 0 PID: 1 at drivers/clk/clk.c:925 clk_disable+0x28/0x34()
> > [   10.568237] Modules linked in:
> > [   10.568237] CPU: 0 PID: 1 Comm: swapper/0 Tainted: G        W       3.19.0-rc6-next-20150202 #2037
> > [   10.568237] Hardware name: Generic OMAP4 (Flattened Device Tree)
> > [   10.568267] [<c0015bdc>] (unwind_backtrace) from [<c001222c>] (show_stack+0x10/0x14)
> > [   10.568267] [<c001222c>] (show_stack) from [<c05d2014>] (dump_stack+0x84/0x9c)
> > [   10.568267] [<c05d2014>] (dump_stack) from [<c003ea90>] (warn_slowpath_common+0x7c/0xb8)
> > [   10.568298] [<c003ea90>] (warn_slowpath_common) from [<c003eb68>] (warn_slowpath_null+0x1c/0x24)
> > [   10.568298] [<c003eb68>] (warn_slowpath_null) from [<c04c1ffc>] (clk_disable+0x28/0x34)
> > [   10.568328] [<c04c1ffc>] (clk_disable) from [<c0025b3c>] (_disable_clocks+0x18/0x68)
> > [   10.568328] [<c0025b3c>] (_disable_clocks) from [<c0026f14>] (_idle+0x10c/0x214)
> > [   10.568328] [<c0026f14>] (_idle) from [<c0855fac>] (_setup+0x338/0x410)
> > [   10.568359] [<c0855fac>] (_setup) from [<c0027360>] (omap_hwmod_for_each+0x34/0x60)
> > [   10.568359] [<c0027360>] (omap_hwmod_for_each) from [<c08563c4>] (__omap_hwmod_setup_all+0x30/0x40)
> > [   10.568389] [<c08563c4>] (__omap_hwmod_setup_all) from [<c0008a04>] (do_one_initcall+0x80/0x1dc)
> > [   10.568389] [<c0008a04>] (do_one_initcall) from [<c0848ea0>] (kernel_init_freeable+0x204/0x2d0)
> > [   10.568420] [<c0848ea0>] (kernel_init_freeable) from [<c05cdab8>] (kernel_init+0x8/0xec)
> > [   10.568420] [<c05cdab8>] (kernel_init) from [<c000e790>] (ret_from_fork+0x14/0x24)
> > [   10.568420] ---[ end trace cb88537fdc8fa211 ]---

For reference, the above is line 992 in clk-next.

> This looks like mis-matched enable/disable calls. We now have unique
> struct clk pointers for every call to clk_get. I haven't yet looked
> through the hwmod code but I have a feeling that we're doing something
> like this:
> 
> 	/* enable clock */
> 	my_clk = clk_get(...);
> 	clk_prepare_enable(my_clk);
> 	clk_put(my_clk);
> 
> 	/* do some work */
> 	do_work();
> 
> 	/* disable clock */
> 	my_clk = clk_get(...);
> 	clk_disable_unprepare(my_clk);
> 	clk_put(my_clk);
> 
> The above pattern no longer works since my_clk will be two different
> unique pointers, but it really should be one stable pointer across the
> whole usage of the clk. E.g:
> 
> 	/* enable clock */
> 	my_clk = clk_get(...);
> 	clk_prepare_enable(my_clk);
> 
> 	/* do some work */
> 	do_work();
> 
> 	/* disable clock */
> 	clk_disable_unprepare(my_clk);
> 	clk_put(my_clk);
> 
> Again, I haven't looked through the code, so the above is just an
> educated guess.
> 
> Anyways I am testing with an OMAP4460 Panda ES and I didn't see the
> above. Is there a test you are running to get this?

Just booting 4430-sdp with omap2plus_defconfig. And git bisect
points to 59cf3fcf9baf ("clk: Make clk API return per-user struct
clk instances") as you already guessed.
 
> > [   10.568450] ------------[ cut here ]------------
> > [   10.568450] WARNING: CPU: 0 PID: 1 at arch/arm/mach-omap2/dpll3xxx.c:436 omap3_noncore_dpll_enable+0xdc/0
> > x10c()
> > [   10.568450] Modules linked in:
> > [   10.568481] CPU: 0 PID: 1 Comm: swapper/0 Tainted: G        W       3.19.0-rc6-next-20150202 #2037
> > [   10.568481] Hardware name: Generic OMAP4 (Flattened Device Tree)
> > [   10.568481] [<c0015bdc>] (unwind_backtrace) from [<c001222c>] (show_stack+0x10/0x14)
> > [   10.568511] [<c001222c>] (show_stack) from [<c05d2014>] (dump_stack+0x84/0x9c)
> > [   10.568511] [<c05d2014>] (dump_stack) from [<c003ea90>] (warn_slowpath_common+0x7c/0xb8)
> > [   10.568511] [<c003ea90>] (warn_slowpath_common) from [<c003eb68>] (warn_slowpath_null+0x1c/0x24)
> > [   10.568542] [<c003eb68>] (warn_slowpath_null) from [<c0035800>] (omap3_noncore_dpll_enable+0xdc/0x10c)
> > [   10.568542] [<c0035800>] (omap3_noncore_dpll_enable) from [<c04c0a10>] (clk_core_enable+0x60/0x9c)
> > [   10.568572] [<c04c0a10>] (clk_core_enable) from [<c04c09f0>] (clk_core_enable+0x40/0x9c)
> > [   10.568572] ---[ end trace cb88537fdc8fa212 ]---
> > ...
> 
> This is the same issue discussed already in this thread[0]. Feedback
> from Tero & Paul on how to handle it would be nice.

Yes that one is a separate issue.
 
> Please let me know if anything else breaks for you.

Also off-idle on omap3 seems to be broken by commit 59cf3fcf9baf.

Regards,

Tony

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

* Re: [PATCH v13 4/6] clk: Add rate constraints to clocks
@ 2015-02-02 19:21                     ` Tony Lindgren
  0 siblings, 0 replies; 186+ messages in thread
From: Tony Lindgren @ 2015-02-02 19:21 UTC (permalink / raw)
  To: Mike Turquette
  Cc: Geert Uytterhoeven, Tomeu Vizoso, Stephen Boyd,
	Linux MIPS Mailing List, linux-doc, Chao Xie, Haojian Zhuang,
	Boris Brezillon, Russell King, Jonathan Corbet, Emilio L??pez,
	Linux-sh list, Alex Elder, Zhangfei Gao, Bintian Wang,
	Matt Porter, linux-omap, linux-arm-kernel, linux-kernel,
	Ralf Baechle, Tero Kristo, Manuel Lauss, Maxime Ripard,
	Javier Martinez Canillas, Paul Walmsley

* Mike Turquette <mturquette@linaro.org> [150202 09:50]:
> Quoting Tony Lindgren (2015-02-02 08:12:37)
> > 
> > [   10.568206] ------------[ cut here ]------------
> > [   10.568206] WARNING: CPU: 0 PID: 1 at drivers/clk/clk.c:925 clk_disable+0x28/0x34()
> > [   10.568237] Modules linked in:
> > [   10.568237] CPU: 0 PID: 1 Comm: swapper/0 Tainted: G        W       3.19.0-rc6-next-20150202 #2037
> > [   10.568237] Hardware name: Generic OMAP4 (Flattened Device Tree)
> > [   10.568267] [<c0015bdc>] (unwind_backtrace) from [<c001222c>] (show_stack+0x10/0x14)
> > [   10.568267] [<c001222c>] (show_stack) from [<c05d2014>] (dump_stack+0x84/0x9c)
> > [   10.568267] [<c05d2014>] (dump_stack) from [<c003ea90>] (warn_slowpath_common+0x7c/0xb8)
> > [   10.568298] [<c003ea90>] (warn_slowpath_common) from [<c003eb68>] (warn_slowpath_null+0x1c/0x24)
> > [   10.568298] [<c003eb68>] (warn_slowpath_null) from [<c04c1ffc>] (clk_disable+0x28/0x34)
> > [   10.568328] [<c04c1ffc>] (clk_disable) from [<c0025b3c>] (_disable_clocks+0x18/0x68)
> > [   10.568328] [<c0025b3c>] (_disable_clocks) from [<c0026f14>] (_idle+0x10c/0x214)
> > [   10.568328] [<c0026f14>] (_idle) from [<c0855fac>] (_setup+0x338/0x410)
> > [   10.568359] [<c0855fac>] (_setup) from [<c0027360>] (omap_hwmod_for_each+0x34/0x60)
> > [   10.568359] [<c0027360>] (omap_hwmod_for_each) from [<c08563c4>] (__omap_hwmod_setup_all+0x30/0x40)
> > [   10.568389] [<c08563c4>] (__omap_hwmod_setup_all) from [<c0008a04>] (do_one_initcall+0x80/0x1dc)
> > [   10.568389] [<c0008a04>] (do_one_initcall) from [<c0848ea0>] (kernel_init_freeable+0x204/0x2d0)
> > [   10.568420] [<c0848ea0>] (kernel_init_freeable) from [<c05cdab8>] (kernel_init+0x8/0xec)
> > [   10.568420] [<c05cdab8>] (kernel_init) from [<c000e790>] (ret_from_fork+0x14/0x24)
> > [   10.568420] ---[ end trace cb88537fdc8fa211 ]---

For reference, the above is line 992 in clk-next.

> This looks like mis-matched enable/disable calls. We now have unique
> struct clk pointers for every call to clk_get. I haven't yet looked
> through the hwmod code but I have a feeling that we're doing something
> like this:
> 
> 	/* enable clock */
> 	my_clk = clk_get(...);
> 	clk_prepare_enable(my_clk);
> 	clk_put(my_clk);
> 
> 	/* do some work */
> 	do_work();
> 
> 	/* disable clock */
> 	my_clk = clk_get(...);
> 	clk_disable_unprepare(my_clk);
> 	clk_put(my_clk);
> 
> The above pattern no longer works since my_clk will be two different
> unique pointers, but it really should be one stable pointer across the
> whole usage of the clk. E.g:
> 
> 	/* enable clock */
> 	my_clk = clk_get(...);
> 	clk_prepare_enable(my_clk);
> 
> 	/* do some work */
> 	do_work();
> 
> 	/* disable clock */
> 	clk_disable_unprepare(my_clk);
> 	clk_put(my_clk);
> 
> Again, I haven't looked through the code, so the above is just an
> educated guess.
> 
> Anyways I am testing with an OMAP4460 Panda ES and I didn't see the
> above. Is there a test you are running to get this?

Just booting 4430-sdp with omap2plus_defconfig. And git bisect
points to 59cf3fcf9baf ("clk: Make clk API return per-user struct
clk instances") as you already guessed.
 
> > [   10.568450] ------------[ cut here ]------------
> > [   10.568450] WARNING: CPU: 0 PID: 1 at arch/arm/mach-omap2/dpll3xxx.c:436 omap3_noncore_dpll_enable+0xdc/0
> > x10c()
> > [   10.568450] Modules linked in:
> > [   10.568481] CPU: 0 PID: 1 Comm: swapper/0 Tainted: G        W       3.19.0-rc6-next-20150202 #2037
> > [   10.568481] Hardware name: Generic OMAP4 (Flattened Device Tree)
> > [   10.568481] [<c0015bdc>] (unwind_backtrace) from [<c001222c>] (show_stack+0x10/0x14)
> > [   10.568511] [<c001222c>] (show_stack) from [<c05d2014>] (dump_stack+0x84/0x9c)
> > [   10.568511] [<c05d2014>] (dump_stack) from [<c003ea90>] (warn_slowpath_common+0x7c/0xb8)
> > [   10.568511] [<c003ea90>] (warn_slowpath_common) from [<c003eb68>] (warn_slowpath_null+0x1c/0x24)
> > [   10.568542] [<c003eb68>] (warn_slowpath_null) from [<c0035800>] (omap3_noncore_dpll_enable+0xdc/0x10c)
> > [   10.568542] [<c0035800>] (omap3_noncore_dpll_enable) from [<c04c0a10>] (clk_core_enable+0x60/0x9c)
> > [   10.568572] [<c04c0a10>] (clk_core_enable) from [<c04c09f0>] (clk_core_enable+0x40/0x9c)
> > [   10.568572] ---[ end trace cb88537fdc8fa212 ]---
> > ...
> 
> This is the same issue discussed already in this thread[0]. Feedback
> from Tero & Paul on how to handle it would be nice.

Yes that one is a separate issue.
 
> Please let me know if anything else breaks for you.

Also off-idle on omap3 seems to be broken by commit 59cf3fcf9baf.

Regards,

Tony

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

* Re: [PATCH v13 4/6] clk: Add rate constraints to clocks
@ 2015-02-02 19:21                     ` Tony Lindgren
  0 siblings, 0 replies; 186+ messages in thread
From: Tony Lindgren @ 2015-02-02 19:21 UTC (permalink / raw)
  To: Mike Turquette
  Cc: Geert Uytterhoeven, Tomeu Vizoso, Stephen Boyd,
	Linux MIPS Mailing List, linux-doc, Chao Xie, Haojian Zhuang,
	Boris Brezillon, Russell King, Jonathan Corbet, Emilio L??pez,
	Linux-sh list, Alex Elder, Zhangfei Gao, Bintian Wang,
	Matt Porter, linux-omap, linux-arm-kernel, linux-kernel, Ralf

* Mike Turquette <mturquette@linaro.org> [150202 09:50]:
> Quoting Tony Lindgren (2015-02-02 08:12:37)
> > 
> > [   10.568206] ------------[ cut here ]------------
> > [   10.568206] WARNING: CPU: 0 PID: 1 at drivers/clk/clk.c:925 clk_disable+0x28/0x34()
> > [   10.568237] Modules linked in:
> > [   10.568237] CPU: 0 PID: 1 Comm: swapper/0 Tainted: G        W       3.19.0-rc6-next-20150202 #2037
> > [   10.568237] Hardware name: Generic OMAP4 (Flattened Device Tree)
> > [   10.568267] [<c0015bdc>] (unwind_backtrace) from [<c001222c>] (show_stack+0x10/0x14)
> > [   10.568267] [<c001222c>] (show_stack) from [<c05d2014>] (dump_stack+0x84/0x9c)
> > [   10.568267] [<c05d2014>] (dump_stack) from [<c003ea90>] (warn_slowpath_common+0x7c/0xb8)
> > [   10.568298] [<c003ea90>] (warn_slowpath_common) from [<c003eb68>] (warn_slowpath_null+0x1c/0x24)
> > [   10.568298] [<c003eb68>] (warn_slowpath_null) from [<c04c1ffc>] (clk_disable+0x28/0x34)
> > [   10.568328] [<c04c1ffc>] (clk_disable) from [<c0025b3c>] (_disable_clocks+0x18/0x68)
> > [   10.568328] [<c0025b3c>] (_disable_clocks) from [<c0026f14>] (_idle+0x10c/0x214)
> > [   10.568328] [<c0026f14>] (_idle) from [<c0855fac>] (_setup+0x338/0x410)
> > [   10.568359] [<c0855fac>] (_setup) from [<c0027360>] (omap_hwmod_for_each+0x34/0x60)
> > [   10.568359] [<c0027360>] (omap_hwmod_for_each) from [<c08563c4>] (__omap_hwmod_setup_all+0x30/0x40)
> > [   10.568389] [<c08563c4>] (__omap_hwmod_setup_all) from [<c0008a04>] (do_one_initcall+0x80/0x1dc)
> > [   10.568389] [<c0008a04>] (do_one_initcall) from [<c0848ea0>] (kernel_init_freeable+0x204/0x2d0)
> > [   10.568420] [<c0848ea0>] (kernel_init_freeable) from [<c05cdab8>] (kernel_init+0x8/0xec)
> > [   10.568420] [<c05cdab8>] (kernel_init) from [<c000e790>] (ret_from_fork+0x14/0x24)
> > [   10.568420] ---[ end trace cb88537fdc8fa211 ]---

For reference, the above is line 992 in clk-next.

> This looks like mis-matched enable/disable calls. We now have unique
> struct clk pointers for every call to clk_get. I haven't yet looked
> through the hwmod code but I have a feeling that we're doing something
> like this:
> 
> 	/* enable clock */
> 	my_clk = clk_get(...);
> 	clk_prepare_enable(my_clk);
> 	clk_put(my_clk);
> 
> 	/* do some work */
> 	do_work();
> 
> 	/* disable clock */
> 	my_clk = clk_get(...);
> 	clk_disable_unprepare(my_clk);
> 	clk_put(my_clk);
> 
> The above pattern no longer works since my_clk will be two different
> unique pointers, but it really should be one stable pointer across the
> whole usage of the clk. E.g:
> 
> 	/* enable clock */
> 	my_clk = clk_get(...);
> 	clk_prepare_enable(my_clk);
> 
> 	/* do some work */
> 	do_work();
> 
> 	/* disable clock */
> 	clk_disable_unprepare(my_clk);
> 	clk_put(my_clk);
> 
> Again, I haven't looked through the code, so the above is just an
> educated guess.
> 
> Anyways I am testing with an OMAP4460 Panda ES and I didn't see the
> above. Is there a test you are running to get this?

Just booting 4430-sdp with omap2plus_defconfig. And git bisect
points to 59cf3fcf9baf ("clk: Make clk API return per-user struct
clk instances") as you already guessed.
 
> > [   10.568450] ------------[ cut here ]------------
> > [   10.568450] WARNING: CPU: 0 PID: 1 at arch/arm/mach-omap2/dpll3xxx.c:436 omap3_noncore_dpll_enable+0xdc/0
> > x10c()
> > [   10.568450] Modules linked in:
> > [   10.568481] CPU: 0 PID: 1 Comm: swapper/0 Tainted: G        W       3.19.0-rc6-next-20150202 #2037
> > [   10.568481] Hardware name: Generic OMAP4 (Flattened Device Tree)
> > [   10.568481] [<c0015bdc>] (unwind_backtrace) from [<c001222c>] (show_stack+0x10/0x14)
> > [   10.568511] [<c001222c>] (show_stack) from [<c05d2014>] (dump_stack+0x84/0x9c)
> > [   10.568511] [<c05d2014>] (dump_stack) from [<c003ea90>] (warn_slowpath_common+0x7c/0xb8)
> > [   10.568511] [<c003ea90>] (warn_slowpath_common) from [<c003eb68>] (warn_slowpath_null+0x1c/0x24)
> > [   10.568542] [<c003eb68>] (warn_slowpath_null) from [<c0035800>] (omap3_noncore_dpll_enable+0xdc/0x10c)
> > [   10.568542] [<c0035800>] (omap3_noncore_dpll_enable) from [<c04c0a10>] (clk_core_enable+0x60/0x9c)
> > [   10.568572] [<c04c0a10>] (clk_core_enable) from [<c04c09f0>] (clk_core_enable+0x40/0x9c)
> > [   10.568572] ---[ end trace cb88537fdc8fa212 ]---
> > ...
> 
> This is the same issue discussed already in this thread[0]. Feedback
> from Tero & Paul on how to handle it would be nice.

Yes that one is a separate issue.
 
> Please let me know if anything else breaks for you.

Also off-idle on omap3 seems to be broken by commit 59cf3fcf9baf.

Regards,

Tony

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

* [PATCH v13 4/6] clk: Add rate constraints to clocks
@ 2015-02-02 19:21                     ` Tony Lindgren
  0 siblings, 0 replies; 186+ messages in thread
From: Tony Lindgren @ 2015-02-02 19:21 UTC (permalink / raw)
  To: linux-arm-kernel

* Mike Turquette <mturquette@linaro.org> [150202 09:50]:
> Quoting Tony Lindgren (2015-02-02 08:12:37)
> > 
> > [   10.568206] ------------[ cut here ]------------
> > [   10.568206] WARNING: CPU: 0 PID: 1 at drivers/clk/clk.c:925 clk_disable+0x28/0x34()
> > [   10.568237] Modules linked in:
> > [   10.568237] CPU: 0 PID: 1 Comm: swapper/0 Tainted: G        W       3.19.0-rc6-next-20150202 #2037
> > [   10.568237] Hardware name: Generic OMAP4 (Flattened Device Tree)
> > [   10.568267] [<c0015bdc>] (unwind_backtrace) from [<c001222c>] (show_stack+0x10/0x14)
> > [   10.568267] [<c001222c>] (show_stack) from [<c05d2014>] (dump_stack+0x84/0x9c)
> > [   10.568267] [<c05d2014>] (dump_stack) from [<c003ea90>] (warn_slowpath_common+0x7c/0xb8)
> > [   10.568298] [<c003ea90>] (warn_slowpath_common) from [<c003eb68>] (warn_slowpath_null+0x1c/0x24)
> > [   10.568298] [<c003eb68>] (warn_slowpath_null) from [<c04c1ffc>] (clk_disable+0x28/0x34)
> > [   10.568328] [<c04c1ffc>] (clk_disable) from [<c0025b3c>] (_disable_clocks+0x18/0x68)
> > [   10.568328] [<c0025b3c>] (_disable_clocks) from [<c0026f14>] (_idle+0x10c/0x214)
> > [   10.568328] [<c0026f14>] (_idle) from [<c0855fac>] (_setup+0x338/0x410)
> > [   10.568359] [<c0855fac>] (_setup) from [<c0027360>] (omap_hwmod_for_each+0x34/0x60)
> > [   10.568359] [<c0027360>] (omap_hwmod_for_each) from [<c08563c4>] (__omap_hwmod_setup_all+0x30/0x40)
> > [   10.568389] [<c08563c4>] (__omap_hwmod_setup_all) from [<c0008a04>] (do_one_initcall+0x80/0x1dc)
> > [   10.568389] [<c0008a04>] (do_one_initcall) from [<c0848ea0>] (kernel_init_freeable+0x204/0x2d0)
> > [   10.568420] [<c0848ea0>] (kernel_init_freeable) from [<c05cdab8>] (kernel_init+0x8/0xec)
> > [   10.568420] [<c05cdab8>] (kernel_init) from [<c000e790>] (ret_from_fork+0x14/0x24)
> > [   10.568420] ---[ end trace cb88537fdc8fa211 ]---

For reference, the above is line 992 in clk-next.

> This looks like mis-matched enable/disable calls. We now have unique
> struct clk pointers for every call to clk_get. I haven't yet looked
> through the hwmod code but I have a feeling that we're doing something
> like this:
> 
> 	/* enable clock */
> 	my_clk = clk_get(...);
> 	clk_prepare_enable(my_clk);
> 	clk_put(my_clk);
> 
> 	/* do some work */
> 	do_work();
> 
> 	/* disable clock */
> 	my_clk = clk_get(...);
> 	clk_disable_unprepare(my_clk);
> 	clk_put(my_clk);
> 
> The above pattern no longer works since my_clk will be two different
> unique pointers, but it really should be one stable pointer across the
> whole usage of the clk. E.g:
> 
> 	/* enable clock */
> 	my_clk = clk_get(...);
> 	clk_prepare_enable(my_clk);
> 
> 	/* do some work */
> 	do_work();
> 
> 	/* disable clock */
> 	clk_disable_unprepare(my_clk);
> 	clk_put(my_clk);
> 
> Again, I haven't looked through the code, so the above is just an
> educated guess.
> 
> Anyways I am testing with an OMAP4460 Panda ES and I didn't see the
> above. Is there a test you are running to get this?

Just booting 4430-sdp with omap2plus_defconfig. And git bisect
points to 59cf3fcf9baf ("clk: Make clk API return per-user struct
clk instances") as you already guessed.
 
> > [   10.568450] ------------[ cut here ]------------
> > [   10.568450] WARNING: CPU: 0 PID: 1 at arch/arm/mach-omap2/dpll3xxx.c:436 omap3_noncore_dpll_enable+0xdc/0
> > x10c()
> > [   10.568450] Modules linked in:
> > [   10.568481] CPU: 0 PID: 1 Comm: swapper/0 Tainted: G        W       3.19.0-rc6-next-20150202 #2037
> > [   10.568481] Hardware name: Generic OMAP4 (Flattened Device Tree)
> > [   10.568481] [<c0015bdc>] (unwind_backtrace) from [<c001222c>] (show_stack+0x10/0x14)
> > [   10.568511] [<c001222c>] (show_stack) from [<c05d2014>] (dump_stack+0x84/0x9c)
> > [   10.568511] [<c05d2014>] (dump_stack) from [<c003ea90>] (warn_slowpath_common+0x7c/0xb8)
> > [   10.568511] [<c003ea90>] (warn_slowpath_common) from [<c003eb68>] (warn_slowpath_null+0x1c/0x24)
> > [   10.568542] [<c003eb68>] (warn_slowpath_null) from [<c0035800>] (omap3_noncore_dpll_enable+0xdc/0x10c)
> > [   10.568542] [<c0035800>] (omap3_noncore_dpll_enable) from [<c04c0a10>] (clk_core_enable+0x60/0x9c)
> > [   10.568572] [<c04c0a10>] (clk_core_enable) from [<c04c09f0>] (clk_core_enable+0x40/0x9c)
> > [   10.568572] ---[ end trace cb88537fdc8fa212 ]---
> > ...
> 
> This is the same issue discussed already in this thread[0]. Feedback
> from Tero & Paul on how to handle it would be nice.

Yes that one is a separate issue.
 
> Please let me know if anything else breaks for you.

Also off-idle on omap3 seems to be broken by commit 59cf3fcf9baf.

Regards,

Tony

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

* Re: [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
  2015-02-01 21:24     ` Mike Turquette
  (?)
@ 2015-02-02 19:32       ` Tero Kristo
  -1 siblings, 0 replies; 186+ messages in thread
From: Tero Kristo @ 2015-02-02 19:32 UTC (permalink / raw)
  To: Mike Turquette, Tomeu Vizoso, linux-kernel, Stephen Boyd
  Cc: Paul Walmsley, Tony Lindgren, linux-omap, linux-arm-kernel

On 02/01/2015 11:24 PM, Mike Turquette wrote:
> Quoting Tomeu Vizoso (2015-01-23 03:03:30)
>> Moves clock state to struct clk_core, but takes care to change as little API as
>> possible.
>>
>> struct clk_hw still has a pointer to a struct clk, which is the
>> implementation's per-user clk instance, for backwards compatibility.
>>
>> The struct clk that clk_get_parent() returns isn't owned by the caller, but by
>> the clock implementation, so the former shouldn't call clk_put() on it.
>>
>> Because some boards in mach-omap2 still register clocks statically, their clock
>> registration had to be updated to take into account that the clock information
>> is stored in struct clk_core now.
>
> Tero, Paul & Tony,
>
> Tomeu's patch unveils a problem with omap3_noncore_dpll_enable and
> struct dpll_data, namely this snippet from
> arch/arm/mach-omap2/dpll3xxx.c:
>
>          parent = __clk_get_parent(hw->clk);
>
>          if (__clk_get_rate(hw->clk) == __clk_get_rate(dd->clk_bypass)) {
>                  WARN(parent != dd->clk_bypass,
>                                  "here0, parent name is %s, bypass name is %s\n",
>                                  __clk_get_name(parent), __clk_get_name(dd->clk_bypass));
>                  r = _omap3_noncore_dpll_bypass(clk);
>          } else {
>                  WARN(parent != dd->clk_ref,
>                                  "here1, parent name is %s, ref name is %s\n",
>                                  __clk_get_name(parent), __clk_get_name(dd->clk_ref));
>                  r = _omap3_noncore_dpll_lock(clk);
>          }
>
> struct dpll_data has members clk_ref and clk_bypass which are struct clk
> pointers. This was always a bit of a violation of the clk.h contract
> since drivers are not supposed to deref struct clk pointers. Now that we
> generate unique pointers for each call to clk_get (clk_ref & clk_bypass
> are populated by of_clk_get in ti_clk_register_dpll) then the pointer
> comparisons above will never be equal (even if they resolve down to the
> same struct clk_core). I added the verbose traces to the WARNs above to
> illustrate the point: the names are always the same but the pointers
> differ.
>
> AFAICT this doesn't break anything, but booting on OMAP3+ results in
> noisy WARNs.
>
> I think the correct fix is to replace clk_bypass and clk_ref pointers
> with a simple integer parent_index. In fact we already have this index.
> See how the pointers are populated in ti_clk_register_dpll:

The problem is we still need to be able to get runtime parent clock 
rates (the parent rate may change also), so simple index value is not 
sufficient. We need a handle of some sort to the bypass/ref clocks. The 
DPLL code generally requires knowledge of the bypass + reference clock 
rates to work properly, as it calculates the M/N values based on these.

Shall I change the DPLL code to check against clk_hw pointers or what is 
the preferred approach here? The patch at the end does this and fixes 
the dpll related warnings.

Btw, the rate constraints patch broke boot for me completely, but sounds 
like you reverted it already.

-Tero

--------------------

Author: Tero Kristo <t-kristo@ti.com>
Date:   Mon Feb 2 17:19:17 2015 +0200

     ARM: OMAP3+: clock: dpll: fix logic for comparing parent clocks

     DPLL code uses reference and bypass clock pointers for determining 
runtime
     properties for these clocks, like parent clock rates.

     As clock API now returns per-user clock structs, using a global handle
     in the clock driver code does not work properly anymore. Fix this by
     using the clk_hw instead, and comparing this against the parents.

     Signed-off-by: Tero Kristo <t-kristo@ti.com>
     Fixes: 59cf3fcf9baf ("clk: Make clk API return per-user struct clk 
instances")

diff --git a/arch/arm/mach-omap2/dpll3xxx.c b/arch/arm/mach-omap2/dpll3xxx.c
index c2da2a0..49752d7 100644
--- a/arch/arm/mach-omap2/dpll3xxx.c
+++ b/arch/arm/mach-omap2/dpll3xxx.c
@@ -410,7 +410,7 @@ int omap3_noncore_dpll_enable(struct clk_hw *hw)
  	struct clk_hw_omap *clk = to_clk_hw_omap(hw);
  	int r;
  	struct dpll_data *dd;
-	struct clk *parent;
+	struct clk_hw *parent;

  	dd = clk->dpll_data;
  	if (!dd)
@@ -427,13 +427,13 @@ int omap3_noncore_dpll_enable(struct clk_hw *hw)
  		}
  	}

-	parent = __clk_get_parent(hw->clk);
+	parent = __clk_get_hw(__clk_get_parent(hw->clk));

  	if (__clk_get_rate(hw->clk) == __clk_get_rate(dd->clk_bypass)) {
-		WARN_ON(parent != dd->clk_bypass);
+		WARN_ON(parent != __clk_get_hw(dd->clk_bypass));
  		r = _omap3_noncore_dpll_bypass(clk);
  	} else {
-		WARN_ON(parent != dd->clk_ref);
+		WARN_ON(parent != __clk_get_hw(dd->clk_ref));
  		r = _omap3_noncore_dpll_lock(clk);
  	}

@@ -549,7 +549,8 @@ int omap3_noncore_dpll_set_rate(struct clk_hw *hw, 
unsigned long rate,
  	if (!dd)
  		return -EINVAL;

-	if (__clk_get_parent(hw->clk) != dd->clk_ref)
+	if (__clk_get_hw(__clk_get_parent(hw->clk)) !=
+	    __clk_get_hw(dd->clk_ref))
  		return -EINVAL;

  	if (dd->last_rounded_rate == 0)



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

* Re: [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
@ 2015-02-02 19:32       ` Tero Kristo
  0 siblings, 0 replies; 186+ messages in thread
From: Tero Kristo @ 2015-02-02 19:32 UTC (permalink / raw)
  To: Mike Turquette, Tomeu Vizoso, linux-kernel, Stephen Boyd
  Cc: Paul Walmsley, Tony Lindgren, linux-omap, linux-arm-kernel

On 02/01/2015 11:24 PM, Mike Turquette wrote:
> Quoting Tomeu Vizoso (2015-01-23 03:03:30)
>> Moves clock state to struct clk_core, but takes care to change as little API as
>> possible.
>>
>> struct clk_hw still has a pointer to a struct clk, which is the
>> implementation's per-user clk instance, for backwards compatibility.
>>
>> The struct clk that clk_get_parent() returns isn't owned by the caller, but by
>> the clock implementation, so the former shouldn't call clk_put() on it.
>>
>> Because some boards in mach-omap2 still register clocks statically, their clock
>> registration had to be updated to take into account that the clock information
>> is stored in struct clk_core now.
>
> Tero, Paul & Tony,
>
> Tomeu's patch unveils a problem with omap3_noncore_dpll_enable and
> struct dpll_data, namely this snippet from
> arch/arm/mach-omap2/dpll3xxx.c:
>
>          parent = __clk_get_parent(hw->clk);
>
>          if (__clk_get_rate(hw->clk) == __clk_get_rate(dd->clk_bypass)) {
>                  WARN(parent != dd->clk_bypass,
>                                  "here0, parent name is %s, bypass name is %s\n",
>                                  __clk_get_name(parent), __clk_get_name(dd->clk_bypass));
>                  r = _omap3_noncore_dpll_bypass(clk);
>          } else {
>                  WARN(parent != dd->clk_ref,
>                                  "here1, parent name is %s, ref name is %s\n",
>                                  __clk_get_name(parent), __clk_get_name(dd->clk_ref));
>                  r = _omap3_noncore_dpll_lock(clk);
>          }
>
> struct dpll_data has members clk_ref and clk_bypass which are struct clk
> pointers. This was always a bit of a violation of the clk.h contract
> since drivers are not supposed to deref struct clk pointers. Now that we
> generate unique pointers for each call to clk_get (clk_ref & clk_bypass
> are populated by of_clk_get in ti_clk_register_dpll) then the pointer
> comparisons above will never be equal (even if they resolve down to the
> same struct clk_core). I added the verbose traces to the WARNs above to
> illustrate the point: the names are always the same but the pointers
> differ.
>
> AFAICT this doesn't break anything, but booting on OMAP3+ results in
> noisy WARNs.
>
> I think the correct fix is to replace clk_bypass and clk_ref pointers
> with a simple integer parent_index. In fact we already have this index.
> See how the pointers are populated in ti_clk_register_dpll:

The problem is we still need to be able to get runtime parent clock 
rates (the parent rate may change also), so simple index value is not 
sufficient. We need a handle of some sort to the bypass/ref clocks. The 
DPLL code generally requires knowledge of the bypass + reference clock 
rates to work properly, as it calculates the M/N values based on these.

Shall I change the DPLL code to check against clk_hw pointers or what is 
the preferred approach here? The patch at the end does this and fixes 
the dpll related warnings.

Btw, the rate constraints patch broke boot for me completely, but sounds 
like you reverted it already.

-Tero

--------------------

Author: Tero Kristo <t-kristo@ti.com>
Date:   Mon Feb 2 17:19:17 2015 +0200

     ARM: OMAP3+: clock: dpll: fix logic for comparing parent clocks

     DPLL code uses reference and bypass clock pointers for determining 
runtime
     properties for these clocks, like parent clock rates.

     As clock API now returns per-user clock structs, using a global handle
     in the clock driver code does not work properly anymore. Fix this by
     using the clk_hw instead, and comparing this against the parents.

     Signed-off-by: Tero Kristo <t-kristo@ti.com>
     Fixes: 59cf3fcf9baf ("clk: Make clk API return per-user struct clk 
instances")

diff --git a/arch/arm/mach-omap2/dpll3xxx.c b/arch/arm/mach-omap2/dpll3xxx.c
index c2da2a0..49752d7 100644
--- a/arch/arm/mach-omap2/dpll3xxx.c
+++ b/arch/arm/mach-omap2/dpll3xxx.c
@@ -410,7 +410,7 @@ int omap3_noncore_dpll_enable(struct clk_hw *hw)
  	struct clk_hw_omap *clk = to_clk_hw_omap(hw);
  	int r;
  	struct dpll_data *dd;
-	struct clk *parent;
+	struct clk_hw *parent;

  	dd = clk->dpll_data;
  	if (!dd)
@@ -427,13 +427,13 @@ int omap3_noncore_dpll_enable(struct clk_hw *hw)
  		}
  	}

-	parent = __clk_get_parent(hw->clk);
+	parent = __clk_get_hw(__clk_get_parent(hw->clk));

  	if (__clk_get_rate(hw->clk) == __clk_get_rate(dd->clk_bypass)) {
-		WARN_ON(parent != dd->clk_bypass);
+		WARN_ON(parent != __clk_get_hw(dd->clk_bypass));
  		r = _omap3_noncore_dpll_bypass(clk);
  	} else {
-		WARN_ON(parent != dd->clk_ref);
+		WARN_ON(parent != __clk_get_hw(dd->clk_ref));
  		r = _omap3_noncore_dpll_lock(clk);
  	}

@@ -549,7 +549,8 @@ int omap3_noncore_dpll_set_rate(struct clk_hw *hw, 
unsigned long rate,
  	if (!dd)
  		return -EINVAL;

-	if (__clk_get_parent(hw->clk) != dd->clk_ref)
+	if (__clk_get_hw(__clk_get_parent(hw->clk)) !=
+	    __clk_get_hw(dd->clk_ref))
  		return -EINVAL;

  	if (dd->last_rounded_rate == 0)



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

* [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
@ 2015-02-02 19:32       ` Tero Kristo
  0 siblings, 0 replies; 186+ messages in thread
From: Tero Kristo @ 2015-02-02 19:32 UTC (permalink / raw)
  To: linux-arm-kernel

On 02/01/2015 11:24 PM, Mike Turquette wrote:
> Quoting Tomeu Vizoso (2015-01-23 03:03:30)
>> Moves clock state to struct clk_core, but takes care to change as little API as
>> possible.
>>
>> struct clk_hw still has a pointer to a struct clk, which is the
>> implementation's per-user clk instance, for backwards compatibility.
>>
>> The struct clk that clk_get_parent() returns isn't owned by the caller, but by
>> the clock implementation, so the former shouldn't call clk_put() on it.
>>
>> Because some boards in mach-omap2 still register clocks statically, their clock
>> registration had to be updated to take into account that the clock information
>> is stored in struct clk_core now.
>
> Tero, Paul & Tony,
>
> Tomeu's patch unveils a problem with omap3_noncore_dpll_enable and
> struct dpll_data, namely this snippet from
> arch/arm/mach-omap2/dpll3xxx.c:
>
>          parent = __clk_get_parent(hw->clk);
>
>          if (__clk_get_rate(hw->clk) == __clk_get_rate(dd->clk_bypass)) {
>                  WARN(parent != dd->clk_bypass,
>                                  "here0, parent name is %s, bypass name is %s\n",
>                                  __clk_get_name(parent), __clk_get_name(dd->clk_bypass));
>                  r = _omap3_noncore_dpll_bypass(clk);
>          } else {
>                  WARN(parent != dd->clk_ref,
>                                  "here1, parent name is %s, ref name is %s\n",
>                                  __clk_get_name(parent), __clk_get_name(dd->clk_ref));
>                  r = _omap3_noncore_dpll_lock(clk);
>          }
>
> struct dpll_data has members clk_ref and clk_bypass which are struct clk
> pointers. This was always a bit of a violation of the clk.h contract
> since drivers are not supposed to deref struct clk pointers. Now that we
> generate unique pointers for each call to clk_get (clk_ref & clk_bypass
> are populated by of_clk_get in ti_clk_register_dpll) then the pointer
> comparisons above will never be equal (even if they resolve down to the
> same struct clk_core). I added the verbose traces to the WARNs above to
> illustrate the point: the names are always the same but the pointers
> differ.
>
> AFAICT this doesn't break anything, but booting on OMAP3+ results in
> noisy WARNs.
>
> I think the correct fix is to replace clk_bypass and clk_ref pointers
> with a simple integer parent_index. In fact we already have this index.
> See how the pointers are populated in ti_clk_register_dpll:

The problem is we still need to be able to get runtime parent clock 
rates (the parent rate may change also), so simple index value is not 
sufficient. We need a handle of some sort to the bypass/ref clocks. The 
DPLL code generally requires knowledge of the bypass + reference clock 
rates to work properly, as it calculates the M/N values based on these.

Shall I change the DPLL code to check against clk_hw pointers or what is 
the preferred approach here? The patch at the end does this and fixes 
the dpll related warnings.

Btw, the rate constraints patch broke boot for me completely, but sounds 
like you reverted it already.

-Tero

--------------------

Author: Tero Kristo <t-kristo@ti.com>
Date:   Mon Feb 2 17:19:17 2015 +0200

     ARM: OMAP3+: clock: dpll: fix logic for comparing parent clocks

     DPLL code uses reference and bypass clock pointers for determining 
runtime
     properties for these clocks, like parent clock rates.

     As clock API now returns per-user clock structs, using a global handle
     in the clock driver code does not work properly anymore. Fix this by
     using the clk_hw instead, and comparing this against the parents.

     Signed-off-by: Tero Kristo <t-kristo@ti.com>
     Fixes: 59cf3fcf9baf ("clk: Make clk API return per-user struct clk 
instances")

diff --git a/arch/arm/mach-omap2/dpll3xxx.c b/arch/arm/mach-omap2/dpll3xxx.c
index c2da2a0..49752d7 100644
--- a/arch/arm/mach-omap2/dpll3xxx.c
+++ b/arch/arm/mach-omap2/dpll3xxx.c
@@ -410,7 +410,7 @@ int omap3_noncore_dpll_enable(struct clk_hw *hw)
  	struct clk_hw_omap *clk = to_clk_hw_omap(hw);
  	int r;
  	struct dpll_data *dd;
-	struct clk *parent;
+	struct clk_hw *parent;

  	dd = clk->dpll_data;
  	if (!dd)
@@ -427,13 +427,13 @@ int omap3_noncore_dpll_enable(struct clk_hw *hw)
  		}
  	}

-	parent = __clk_get_parent(hw->clk);
+	parent = __clk_get_hw(__clk_get_parent(hw->clk));

  	if (__clk_get_rate(hw->clk) == __clk_get_rate(dd->clk_bypass)) {
-		WARN_ON(parent != dd->clk_bypass);
+		WARN_ON(parent != __clk_get_hw(dd->clk_bypass));
  		r = _omap3_noncore_dpll_bypass(clk);
  	} else {
-		WARN_ON(parent != dd->clk_ref);
+		WARN_ON(parent != __clk_get_hw(dd->clk_ref));
  		r = _omap3_noncore_dpll_lock(clk);
  	}

@@ -549,7 +549,8 @@ int omap3_noncore_dpll_set_rate(struct clk_hw *hw, 
unsigned long rate,
  	if (!dd)
  		return -EINVAL;

-	if (__clk_get_parent(hw->clk) != dd->clk_ref)
+	if (__clk_get_hw(__clk_get_parent(hw->clk)) !=
+	    __clk_get_hw(dd->clk_ref))
  		return -EINVAL;

  	if (dd->last_rounded_rate == 0)

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

* Re: [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
  2015-02-02 19:32       ` Tero Kristo
@ 2015-02-02 20:44         ` Tony Lindgren
  -1 siblings, 0 replies; 186+ messages in thread
From: Tony Lindgren @ 2015-02-02 20:44 UTC (permalink / raw)
  To: Tero Kristo
  Cc: Mike Turquette, Tomeu Vizoso, linux-kernel, Stephen Boyd,
	Paul Walmsley, linux-omap, linux-arm-kernel

* Tero Kristo <t-kristo@ti.com> [150202 11:35]:
> On 02/01/2015 11:24 PM, Mike Turquette wrote:
> >Quoting Tomeu Vizoso (2015-01-23 03:03:30)
> >
> >AFAICT this doesn't break anything, but booting on OMAP3+ results in
> >noisy WARNs.
> >
> >I think the correct fix is to replace clk_bypass and clk_ref pointers
> >with a simple integer parent_index. In fact we already have this index.
> >See how the pointers are populated in ti_clk_register_dpll:
> 
> The problem is we still need to be able to get runtime parent clock rates
> (the parent rate may change also), so simple index value is not sufficient.
> We need a handle of some sort to the bypass/ref clocks. The DPLL code
> generally requires knowledge of the bypass + reference clock rates to work
> properly, as it calculates the M/N values based on these.
> 
> Shall I change the DPLL code to check against clk_hw pointers or what is the
> preferred approach here? The patch at the end does this and fixes the dpll
> related warnings.
> 
> Btw, the rate constraints patch broke boot for me completely, but sounds
> like you reverted it already.

Thanks Tero, looks like your fix fixes all the issues I'm seeing with
commit 59cf3fcf9baf. That is noisy dmesg, dpll_abe_ck not locking
on 4430sdp, and off-idle not working for omap3.

I could not get the patch to apply, below is what I applied manually.

Mike, If possible, maybe fold this into 59cf3fcf9baf? It applies with
some fuzz on that too. And inn that case, please feel also to add the
following for Tomeu's patch:

Tested-by: Tony Lindgren <tony@atomide.com>

8<------------
From: Tero Kristo <t-kristo@ti.com>
Date: Mon, 2 Feb 2015 12:17:00 -0800
Subject: [PATCH] ARM: OMAP3+: clock: dpll: fix logic for comparing parent clocks

DPLL code uses reference and bypass clock pointers for determining runtime
properties for these clocks, like parent clock rates.
As clock API now returns per-user clock structs, using a global handle
in the clock driver code does not work properly anymore. Fix this by
using the clk_hw instead, and comparing this against the parents.

Fixes: 59cf3fcf9baf ("clk: Make clk API return per-user struct clk instances")
Signed-off-by: Tero Kristo <t-kristo@ti.com>
[tony@atomide.com: updated to apply]
Signed-off-by: Tony Lindgren <tony@atomide.com>

--- a/arch/arm/mach-omap2/dpll3xxx.c
+++ b/arch/arm/mach-omap2/dpll3xxx.c
@@ -410,7 +410,7 @@ int omap3_noncore_dpll_enable(struct clk_hw *hw)
 	struct clk_hw_omap *clk = to_clk_hw_omap(hw);
 	int r;
 	struct dpll_data *dd;
-	struct clk *parent;
+	struct clk_hw *parent;
 
 	dd = clk->dpll_data;
 	if (!dd)
@@ -427,13 +427,13 @@ int omap3_noncore_dpll_enable(struct clk_hw *hw)
 		}
 	}
 
-	parent = __clk_get_parent(hw->clk);
+	parent = __clk_get_hw(__clk_get_parent(hw->clk));
 
 	if (__clk_get_rate(hw->clk) == __clk_get_rate(dd->clk_bypass)) {
-		WARN_ON(parent != dd->clk_bypass);
+		WARN_ON(parent != __clk_get_hw(dd->clk_bypass));
 		r = _omap3_noncore_dpll_bypass(clk);
 	} else {
-		WARN_ON(parent != dd->clk_ref);
+		WARN_ON(parent != __clk_get_hw(dd->clk_ref));
 		r = _omap3_noncore_dpll_lock(clk);
 	}
 
@@ -549,7 +549,8 @@ int omap3_noncore_dpll_set_rate(struct clk_hw *hw, unsigned long rate,
 	if (!dd)
 		return -EINVAL;
 
-	if (__clk_get_parent(hw->clk) != dd->clk_ref)
+	if (__clk_get_hw(__clk_get_parent(hw->clk)) !=
+	    __clk_get_hw(dd->clk_ref))
 		return -EINVAL;
 
 	if (dd->last_rounded_rate == 0)

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

* [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
@ 2015-02-02 20:44         ` Tony Lindgren
  0 siblings, 0 replies; 186+ messages in thread
From: Tony Lindgren @ 2015-02-02 20:44 UTC (permalink / raw)
  To: linux-arm-kernel

* Tero Kristo <t-kristo@ti.com> [150202 11:35]:
> On 02/01/2015 11:24 PM, Mike Turquette wrote:
> >Quoting Tomeu Vizoso (2015-01-23 03:03:30)
> >
> >AFAICT this doesn't break anything, but booting on OMAP3+ results in
> >noisy WARNs.
> >
> >I think the correct fix is to replace clk_bypass and clk_ref pointers
> >with a simple integer parent_index. In fact we already have this index.
> >See how the pointers are populated in ti_clk_register_dpll:
> 
> The problem is we still need to be able to get runtime parent clock rates
> (the parent rate may change also), so simple index value is not sufficient.
> We need a handle of some sort to the bypass/ref clocks. The DPLL code
> generally requires knowledge of the bypass + reference clock rates to work
> properly, as it calculates the M/N values based on these.
> 
> Shall I change the DPLL code to check against clk_hw pointers or what is the
> preferred approach here? The patch at the end does this and fixes the dpll
> related warnings.
> 
> Btw, the rate constraints patch broke boot for me completely, but sounds
> like you reverted it already.

Thanks Tero, looks like your fix fixes all the issues I'm seeing with
commit 59cf3fcf9baf. That is noisy dmesg, dpll_abe_ck not locking
on 4430sdp, and off-idle not working for omap3.

I could not get the patch to apply, below is what I applied manually.

Mike, If possible, maybe fold this into 59cf3fcf9baf? It applies with
some fuzz on that too. And inn that case, please feel also to add the
following for Tomeu's patch:

Tested-by: Tony Lindgren <tony@atomide.com>

8<------------
From: Tero Kristo <t-kristo@ti.com>
Date: Mon, 2 Feb 2015 12:17:00 -0800
Subject: [PATCH] ARM: OMAP3+: clock: dpll: fix logic for comparing parent clocks

DPLL code uses reference and bypass clock pointers for determining runtime
properties for these clocks, like parent clock rates.
As clock API now returns per-user clock structs, using a global handle
in the clock driver code does not work properly anymore. Fix this by
using the clk_hw instead, and comparing this against the parents.

Fixes: 59cf3fcf9baf ("clk: Make clk API return per-user struct clk instances")
Signed-off-by: Tero Kristo <t-kristo@ti.com>
[tony at atomide.com: updated to apply]
Signed-off-by: Tony Lindgren <tony@atomide.com>

--- a/arch/arm/mach-omap2/dpll3xxx.c
+++ b/arch/arm/mach-omap2/dpll3xxx.c
@@ -410,7 +410,7 @@ int omap3_noncore_dpll_enable(struct clk_hw *hw)
 	struct clk_hw_omap *clk = to_clk_hw_omap(hw);
 	int r;
 	struct dpll_data *dd;
-	struct clk *parent;
+	struct clk_hw *parent;
 
 	dd = clk->dpll_data;
 	if (!dd)
@@ -427,13 +427,13 @@ int omap3_noncore_dpll_enable(struct clk_hw *hw)
 		}
 	}
 
-	parent = __clk_get_parent(hw->clk);
+	parent = __clk_get_hw(__clk_get_parent(hw->clk));
 
 	if (__clk_get_rate(hw->clk) == __clk_get_rate(dd->clk_bypass)) {
-		WARN_ON(parent != dd->clk_bypass);
+		WARN_ON(parent != __clk_get_hw(dd->clk_bypass));
 		r = _omap3_noncore_dpll_bypass(clk);
 	} else {
-		WARN_ON(parent != dd->clk_ref);
+		WARN_ON(parent != __clk_get_hw(dd->clk_ref));
 		r = _omap3_noncore_dpll_lock(clk);
 	}
 
@@ -549,7 +549,8 @@ int omap3_noncore_dpll_set_rate(struct clk_hw *hw, unsigned long rate,
 	if (!dd)
 		return -EINVAL;
 
-	if (__clk_get_parent(hw->clk) != dd->clk_ref)
+	if (__clk_get_hw(__clk_get_parent(hw->clk)) !=
+	    __clk_get_hw(dd->clk_ref))
 		return -EINVAL;
 
 	if (dd->last_rounded_rate == 0)

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

* Re: [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
  2015-02-01 21:24     ` Mike Turquette
  (?)
@ 2015-02-02 20:45       ` Stephen Boyd
  -1 siblings, 0 replies; 186+ messages in thread
From: Stephen Boyd @ 2015-02-02 20:45 UTC (permalink / raw)
  To: Julia Lawall
  Cc: Mike Turquette, Tomeu Vizoso, linux-kernel, Paul Walmsley,
	Tony Lindgren, linux-omap, linux-arm-kernel, t-kristo, cocci

On 02/01/15 13:24, Mike Turquette wrote:
> Quoting Tomeu Vizoso (2015-01-23 03:03:30)
>> Moves clock state to struct clk_core, but takes care to change as little API as
>> possible.
>>
>> struct clk_hw still has a pointer to a struct clk, which is the
>> implementation's per-user clk instance, for backwards compatibility.
>>
>> The struct clk that clk_get_parent() returns isn't owned by the caller, but by
>> the clock implementation, so the former shouldn't call clk_put() on it.
>>
>> Because some boards in mach-omap2 still register clocks statically, their clock
>> registration had to be updated to take into account that the clock information
>> is stored in struct clk_core now.
> Tero, Paul & Tony,
>
> Tomeu's patch unveils a problem with omap3_noncore_dpll_enable and
> struct dpll_data, namely this snippet from
> arch/arm/mach-omap2/dpll3xxx.c:
>
>         parent = __clk_get_parent(hw->clk);
>
>         if (__clk_get_rate(hw->clk) == __clk_get_rate(dd->clk_bypass)) {
>                 WARN(parent != dd->clk_bypass,
>                                 "here0, parent name is %s, bypass name is %s\n",
>                                 __clk_get_name(parent), __clk_get_name(dd->clk_bypass));
>                 r = _omap3_noncore_dpll_bypass(clk);
>         } else {
>                 WARN(parent != dd->clk_ref,
>                                 "here1, parent name is %s, ref name is %s\n",
>                                 __clk_get_name(parent), __clk_get_name(dd->clk_ref));
>                 r = _omap3_noncore_dpll_lock(clk);
>         }
>
> struct dpll_data has members clk_ref and clk_bypass which are struct clk
> pointers. This was always a bit of a violation of the clk.h contract
> since drivers are not supposed to deref struct clk pointers. 

Julia,

Is there a way we can write a coccinelle script to check for this? The
goal being to find all drivers that are comparing struct clk pointers or
attempting to dereference them. There are probably other frameworks that
could use the same type of check (regulator, gpiod, reset, pwm, etc.).
Probably anything that has a get/put API.

-Stephen

> Now that we
> generate unique pointers for each call to clk_get (clk_ref & clk_bypass
> are populated by of_clk_get in ti_clk_register_dpll) then the pointer
> comparisons above will never be equal (even if they resolve down to the
> same struct clk_core). I added the verbose traces to the WARNs above to
> illustrate the point: the names are always the same but the pointers
> differ.
>
> AFAICT this doesn't break anything, but booting on OMAP3+ results in
> noisy WARNs.
>
> I think the correct fix is to replace clk_bypass and clk_ref pointers
> with a simple integer parent_index. In fact we already have this index.
> See how the pointers are populated in ti_clk_register_dpll:
>
>
>         dd->clk_ref = of_clk_get(node, 0);
>         dd->clk_bypass = of_clk_get(node, 1);
>
> Tony, the same problem affects the FAPLL code which copy/pastes some of
> the DPLL code.
>
> Thoughts?
>
-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project


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

* [Cocci] [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
@ 2015-02-02 20:45       ` Stephen Boyd
  0 siblings, 0 replies; 186+ messages in thread
From: Stephen Boyd @ 2015-02-02 20:45 UTC (permalink / raw)
  To: cocci

On 02/01/15 13:24, Mike Turquette wrote:
> Quoting Tomeu Vizoso (2015-01-23 03:03:30)
>> Moves clock state to struct clk_core, but takes care to change as little API as
>> possible.
>>
>> struct clk_hw still has a pointer to a struct clk, which is the
>> implementation's per-user clk instance, for backwards compatibility.
>>
>> The struct clk that clk_get_parent() returns isn't owned by the caller, but by
>> the clock implementation, so the former shouldn't call clk_put() on it.
>>
>> Because some boards in mach-omap2 still register clocks statically, their clock
>> registration had to be updated to take into account that the clock information
>> is stored in struct clk_core now.
> Tero, Paul & Tony,
>
> Tomeu's patch unveils a problem with omap3_noncore_dpll_enable and
> struct dpll_data, namely this snippet from
> arch/arm/mach-omap2/dpll3xxx.c:
>
>         parent = __clk_get_parent(hw->clk);
>
>         if (__clk_get_rate(hw->clk) == __clk_get_rate(dd->clk_bypass)) {
>                 WARN(parent != dd->clk_bypass,
>                                 "here0, parent name is %s, bypass name is %s\n",
>                                 __clk_get_name(parent), __clk_get_name(dd->clk_bypass));
>                 r = _omap3_noncore_dpll_bypass(clk);
>         } else {
>                 WARN(parent != dd->clk_ref,
>                                 "here1, parent name is %s, ref name is %s\n",
>                                 __clk_get_name(parent), __clk_get_name(dd->clk_ref));
>                 r = _omap3_noncore_dpll_lock(clk);
>         }
>
> struct dpll_data has members clk_ref and clk_bypass which are struct clk
> pointers. This was always a bit of a violation of the clk.h contract
> since drivers are not supposed to deref struct clk pointers. 

Julia,

Is there a way we can write a coccinelle script to check for this? The
goal being to find all drivers that are comparing struct clk pointers or
attempting to dereference them. There are probably other frameworks that
could use the same type of check (regulator, gpiod, reset, pwm, etc.).
Probably anything that has a get/put API.

-Stephen

> Now that we
> generate unique pointers for each call to clk_get (clk_ref & clk_bypass
> are populated by of_clk_get in ti_clk_register_dpll) then the pointer
> comparisons above will never be equal (even if they resolve down to the
> same struct clk_core). I added the verbose traces to the WARNs above to
> illustrate the point: the names are always the same but the pointers
> differ.
>
> AFAICT this doesn't break anything, but booting on OMAP3+ results in
> noisy WARNs.
>
> I think the correct fix is to replace clk_bypass and clk_ref pointers
> with a simple integer parent_index. In fact we already have this index.
> See how the pointers are populated in ti_clk_register_dpll:
>
>
>         dd->clk_ref = of_clk_get(node, 0);
>         dd->clk_bypass = of_clk_get(node, 1);
>
> Tony, the same problem affects the FAPLL code which copy/pastes some of
> the DPLL code.
>
> Thoughts?
>
-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

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

* [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
@ 2015-02-02 20:45       ` Stephen Boyd
  0 siblings, 0 replies; 186+ messages in thread
From: Stephen Boyd @ 2015-02-02 20:45 UTC (permalink / raw)
  To: linux-arm-kernel

On 02/01/15 13:24, Mike Turquette wrote:
> Quoting Tomeu Vizoso (2015-01-23 03:03:30)
>> Moves clock state to struct clk_core, but takes care to change as little API as
>> possible.
>>
>> struct clk_hw still has a pointer to a struct clk, which is the
>> implementation's per-user clk instance, for backwards compatibility.
>>
>> The struct clk that clk_get_parent() returns isn't owned by the caller, but by
>> the clock implementation, so the former shouldn't call clk_put() on it.
>>
>> Because some boards in mach-omap2 still register clocks statically, their clock
>> registration had to be updated to take into account that the clock information
>> is stored in struct clk_core now.
> Tero, Paul & Tony,
>
> Tomeu's patch unveils a problem with omap3_noncore_dpll_enable and
> struct dpll_data, namely this snippet from
> arch/arm/mach-omap2/dpll3xxx.c:
>
>         parent = __clk_get_parent(hw->clk);
>
>         if (__clk_get_rate(hw->clk) == __clk_get_rate(dd->clk_bypass)) {
>                 WARN(parent != dd->clk_bypass,
>                                 "here0, parent name is %s, bypass name is %s\n",
>                                 __clk_get_name(parent), __clk_get_name(dd->clk_bypass));
>                 r = _omap3_noncore_dpll_bypass(clk);
>         } else {
>                 WARN(parent != dd->clk_ref,
>                                 "here1, parent name is %s, ref name is %s\n",
>                                 __clk_get_name(parent), __clk_get_name(dd->clk_ref));
>                 r = _omap3_noncore_dpll_lock(clk);
>         }
>
> struct dpll_data has members clk_ref and clk_bypass which are struct clk
> pointers. This was always a bit of a violation of the clk.h contract
> since drivers are not supposed to deref struct clk pointers. 

Julia,

Is there a way we can write a coccinelle script to check for this? The
goal being to find all drivers that are comparing struct clk pointers or
attempting to dereference them. There are probably other frameworks that
could use the same type of check (regulator, gpiod, reset, pwm, etc.).
Probably anything that has a get/put API.

-Stephen

> Now that we
> generate unique pointers for each call to clk_get (clk_ref & clk_bypass
> are populated by of_clk_get in ti_clk_register_dpll) then the pointer
> comparisons above will never be equal (even if they resolve down to the
> same struct clk_core). I added the verbose traces to the WARNs above to
> illustrate the point: the names are always the same but the pointers
> differ.
>
> AFAICT this doesn't break anything, but booting on OMAP3+ results in
> noisy WARNs.
>
> I think the correct fix is to replace clk_bypass and clk_ref pointers
> with a simple integer parent_index. In fact we already have this index.
> See how the pointers are populated in ti_clk_register_dpll:
>
>
>         dd->clk_ref = of_clk_get(node, 0);
>         dd->clk_bypass = of_clk_get(node, 1);
>
> Tony, the same problem affects the FAPLL code which copy/pastes some of
> the DPLL code.
>
> Thoughts?
>
-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

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

* Re: [PATCH v13 4/6] clk: Add rate constraints to clocks
  2015-02-02 19:21                     ` Tony Lindgren
                                         ` (2 preceding siblings ...)
  (?)
@ 2015-02-02 20:47                       ` Tony Lindgren
  -1 siblings, 0 replies; 186+ messages in thread
From: Tony Lindgren @ 2015-02-02 20:47 UTC (permalink / raw)
  To: linux-arm-kernel

* Tony Lindgren <tony@atomide.com> [150202 11:28]:
> * Mike Turquette <mturquette@linaro.org> [150202 09:50]:
> > Quoting Tony Lindgren (2015-02-02 08:12:37)
> > > 
> > > [   10.568206] ------------[ cut here ]------------
> > > [   10.568206] WARNING: CPU: 0 PID: 1 at drivers/clk/clk.c:925 clk_disable+0x28/0x34()
> > > [   10.568237] Modules linked in:
> > > [   10.568237] CPU: 0 PID: 1 Comm: swapper/0 Tainted: G        W       3.19.0-rc6-next-20150202 #2037
> > > [   10.568237] Hardware name: Generic OMAP4 (Flattened Device Tree)
> > > [   10.568267] [<c0015bdc>] (unwind_backtrace) from [<c001222c>] (show_stack+0x10/0x14)
> > > [   10.568267] [<c001222c>] (show_stack) from [<c05d2014>] (dump_stack+0x84/0x9c)
> > > [   10.568267] [<c05d2014>] (dump_stack) from [<c003ea90>] (warn_slowpath_common+0x7c/0xb8)
> > > [   10.568298] [<c003ea90>] (warn_slowpath_common) from [<c003eb68>] (warn_slowpath_null+0x1c/0x24)
> > > [   10.568298] [<c003eb68>] (warn_slowpath_null) from [<c04c1ffc>] (clk_disable+0x28/0x34)
> > > [   10.568328] [<c04c1ffc>] (clk_disable) from [<c0025b3c>] (_disable_clocks+0x18/0x68)
> > > [   10.568328] [<c0025b3c>] (_disable_clocks) from [<c0026f14>] (_idle+0x10c/0x214)
> > > [   10.568328] [<c0026f14>] (_idle) from [<c0855fac>] (_setup+0x338/0x410)
> > > [   10.568359] [<c0855fac>] (_setup) from [<c0027360>] (omap_hwmod_for_each+0x34/0x60)
> > > [   10.568359] [<c0027360>] (omap_hwmod_for_each) from [<c08563c4>] (__omap_hwmod_setup_all+0x30/0x40)
> > > [   10.568389] [<c08563c4>] (__omap_hwmod_setup_all) from [<c0008a04>] (do_one_initcall+0x80/0x1dc)
> > > [   10.568389] [<c0008a04>] (do_one_initcall) from [<c0848ea0>] (kernel_init_freeable+0x204/0x2d0)
> > > [   10.568420] [<c0848ea0>] (kernel_init_freeable) from [<c05cdab8>] (kernel_init+0x8/0xec)
> > > [   10.568420] [<c05cdab8>] (kernel_init) from [<c000e790>] (ret_from_fork+0x14/0x24)
> > > [   10.568420] ---[ end trace cb88537fdc8fa211 ]---
> 
> For reference, the above is line 992 in clk-next.
...
 
> Just booting 4430-sdp with omap2plus_defconfig. And git bisect
> points to 59cf3fcf9baf ("clk: Make clk API return per-user struct
> clk instances") as you already guessed.
>  
> > > [   10.568450] ------------[ cut here ]------------
> > > [   10.568450] WARNING: CPU: 0 PID: 1 at arch/arm/mach-omap2/dpll3xxx.c:436 omap3_noncore_dpll_enable+0xdc/0
> > > x10c()
> > > [   10.568450] Modules linked in:
> > > [   10.568481] CPU: 0 PID: 1 Comm: swapper/0 Tainted: G        W       3.19.0-rc6-next-20150202 #2037
> > > [   10.568481] Hardware name: Generic OMAP4 (Flattened Device Tree)
> > > [   10.568481] [<c0015bdc>] (unwind_backtrace) from [<c001222c>] (show_stack+0x10/0x14)
> > > [   10.568511] [<c001222c>] (show_stack) from [<c05d2014>] (dump_stack+0x84/0x9c)
> > > [   10.568511] [<c05d2014>] (dump_stack) from [<c003ea90>] (warn_slowpath_common+0x7c/0xb8)
> > > [   10.568511] [<c003ea90>] (warn_slowpath_common) from [<c003eb68>] (warn_slowpath_null+0x1c/0x24)
> > > [   10.568542] [<c003eb68>] (warn_slowpath_null) from [<c0035800>] (omap3_noncore_dpll_enable+0xdc/0x10c)
> > > [   10.568542] [<c0035800>] (omap3_noncore_dpll_enable) from [<c04c0a10>] (clk_core_enable+0x60/0x9c)
> > > [   10.568572] [<c04c0a10>] (clk_core_enable) from [<c04c09f0>] (clk_core_enable+0x40/0x9c)
> > > [   10.568572] ---[ end trace cb88537fdc8fa212 ]---
> > > ...
> > 
> > This is the same issue discussed already in this thread[0]. Feedback
> > from Tero & Paul on how to handle it would be nice.
> 
> Yes that one is a separate issue.
>  
> > Please let me know if anything else breaks for you.
> 
> Also off-idle on omap3 seems to be broken by commit 59cf3fcf9baf.

Actually the two warnigns above are all caused by the same issue.
And the patch Tero just posted fixes both of the issue. It's the thread 
"[PATCH v13 3/6] clk: Make clk API return per-user struct clk instances"
for reference.

Regards,

Tony


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

* Re: [PATCH v13 4/6] clk: Add rate constraints to clocks
@ 2015-02-02 20:47                       ` Tony Lindgren
  0 siblings, 0 replies; 186+ messages in thread
From: Tony Lindgren @ 2015-02-02 20:47 UTC (permalink / raw)
  To: Mike Turquette
  Cc: Geert Uytterhoeven, Tomeu Vizoso, Stephen Boyd,
	Linux MIPS Mailing List, linux-doc, Chao Xie, Haojian Zhuang,
	Boris Brezillon, Russell King, Jonathan Corbet, Emilio L??pez,
	Linux-sh list, Alex Elder, Zhangfei Gao, Bintian Wang,
	Matt Porter, linux-omap, linux-arm-kernel, linux-kernel,
	Ralf Baechle, Tero Kristo, Manuel Lauss, Maxime Ripard,
	Javier Martinez Canillas, Paul Walmsley

* Tony Lindgren <tony@atomide.com> [150202 11:28]:
> * Mike Turquette <mturquette@linaro.org> [150202 09:50]:
> > Quoting Tony Lindgren (2015-02-02 08:12:37)
> > > 
> > > [   10.568206] ------------[ cut here ]------------
> > > [   10.568206] WARNING: CPU: 0 PID: 1 at drivers/clk/clk.c:925 clk_disable+0x28/0x34()
> > > [   10.568237] Modules linked in:
> > > [   10.568237] CPU: 0 PID: 1 Comm: swapper/0 Tainted: G        W       3.19.0-rc6-next-20150202 #2037
> > > [   10.568237] Hardware name: Generic OMAP4 (Flattened Device Tree)
> > > [   10.568267] [<c0015bdc>] (unwind_backtrace) from [<c001222c>] (show_stack+0x10/0x14)
> > > [   10.568267] [<c001222c>] (show_stack) from [<c05d2014>] (dump_stack+0x84/0x9c)
> > > [   10.568267] [<c05d2014>] (dump_stack) from [<c003ea90>] (warn_slowpath_common+0x7c/0xb8)
> > > [   10.568298] [<c003ea90>] (warn_slowpath_common) from [<c003eb68>] (warn_slowpath_null+0x1c/0x24)
> > > [   10.568298] [<c003eb68>] (warn_slowpath_null) from [<c04c1ffc>] (clk_disable+0x28/0x34)
> > > [   10.568328] [<c04c1ffc>] (clk_disable) from [<c0025b3c>] (_disable_clocks+0x18/0x68)
> > > [   10.568328] [<c0025b3c>] (_disable_clocks) from [<c0026f14>] (_idle+0x10c/0x214)
> > > [   10.568328] [<c0026f14>] (_idle) from [<c0855fac>] (_setup+0x338/0x410)
> > > [   10.568359] [<c0855fac>] (_setup) from [<c0027360>] (omap_hwmod_for_each+0x34/0x60)
> > > [   10.568359] [<c0027360>] (omap_hwmod_for_each) from [<c08563c4>] (__omap_hwmod_setup_all+0x30/0x40)
> > > [   10.568389] [<c08563c4>] (__omap_hwmod_setup_all) from [<c0008a04>] (do_one_initcall+0x80/0x1dc)
> > > [   10.568389] [<c0008a04>] (do_one_initcall) from [<c0848ea0>] (kernel_init_freeable+0x204/0x2d0)
> > > [   10.568420] [<c0848ea0>] (kernel_init_freeable) from [<c05cdab8>] (kernel_init+0x8/0xec)
> > > [   10.568420] [<c05cdab8>] (kernel_init) from [<c000e790>] (ret_from_fork+0x14/0x24)
> > > [   10.568420] ---[ end trace cb88537fdc8fa211 ]---
> 
> For reference, the above is line 992 in clk-next.
...
 
> Just booting 4430-sdp with omap2plus_defconfig. And git bisect
> points to 59cf3fcf9baf ("clk: Make clk API return per-user struct
> clk instances") as you already guessed.
>  
> > > [   10.568450] ------------[ cut here ]------------
> > > [   10.568450] WARNING: CPU: 0 PID: 1 at arch/arm/mach-omap2/dpll3xxx.c:436 omap3_noncore_dpll_enable+0xdc/0
> > > x10c()
> > > [   10.568450] Modules linked in:
> > > [   10.568481] CPU: 0 PID: 1 Comm: swapper/0 Tainted: G        W       3.19.0-rc6-next-20150202 #2037
> > > [   10.568481] Hardware name: Generic OMAP4 (Flattened Device Tree)
> > > [   10.568481] [<c0015bdc>] (unwind_backtrace) from [<c001222c>] (show_stack+0x10/0x14)
> > > [   10.568511] [<c001222c>] (show_stack) from [<c05d2014>] (dump_stack+0x84/0x9c)
> > > [   10.568511] [<c05d2014>] (dump_stack) from [<c003ea90>] (warn_slowpath_common+0x7c/0xb8)
> > > [   10.568511] [<c003ea90>] (warn_slowpath_common) from [<c003eb68>] (warn_slowpath_null+0x1c/0x24)
> > > [   10.568542] [<c003eb68>] (warn_slowpath_null) from [<c0035800>] (omap3_noncore_dpll_enable+0xdc/0x10c)
> > > [   10.568542] [<c0035800>] (omap3_noncore_dpll_enable) from [<c04c0a10>] (clk_core_enable+0x60/0x9c)
> > > [   10.568572] [<c04c0a10>] (clk_core_enable) from [<c04c09f0>] (clk_core_enable+0x40/0x9c)
> > > [   10.568572] ---[ end trace cb88537fdc8fa212 ]---
> > > ...
> > 
> > This is the same issue discussed already in this thread[0]. Feedback
> > from Tero & Paul on how to handle it would be nice.
> 
> Yes that one is a separate issue.
>  
> > Please let me know if anything else breaks for you.
> 
> Also off-idle on omap3 seems to be broken by commit 59cf3fcf9baf.

Actually the two warnigns above are all caused by the same issue.
And the patch Tero just posted fixes both of the issue. It's the thread 
"[PATCH v13 3/6] clk: Make clk API return per-user struct clk instances"
for reference.

Regards,

Tony


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

* Re: [PATCH v13 4/6] clk: Add rate constraints to clocks
@ 2015-02-02 20:47                       ` Tony Lindgren
  0 siblings, 0 replies; 186+ messages in thread
From: Tony Lindgren @ 2015-02-02 20:47 UTC (permalink / raw)
  To: Mike Turquette
  Cc: Geert Uytterhoeven, Tomeu Vizoso, Stephen Boyd,
	Linux MIPS Mailing List, linux-doc, Chao Xie, Haojian Zhuang,
	Boris Brezillon, Russell King, Jonathan Corbet, Emilio L??pez,
	Linux-sh list, Alex Elder, Zhangfei Gao, Bintian Wang,
	Matt Porter, linux-omap, linux-arm-kernel, linux-kernel,
	Ralf Baechle, Tero Kristo, Manuel Lauss, Maxime Ripard,
	Javier Martinez Canillas, Paul Walmsley

* Tony Lindgren <tony@atomide.com> [150202 11:28]:
> * Mike Turquette <mturquette@linaro.org> [150202 09:50]:
> > Quoting Tony Lindgren (2015-02-02 08:12:37)
> > > 
> > > [   10.568206] ------------[ cut here ]------------
> > > [   10.568206] WARNING: CPU: 0 PID: 1 at drivers/clk/clk.c:925 clk_disable+0x28/0x34()
> > > [   10.568237] Modules linked in:
> > > [   10.568237] CPU: 0 PID: 1 Comm: swapper/0 Tainted: G        W       3.19.0-rc6-next-20150202 #2037
> > > [   10.568237] Hardware name: Generic OMAP4 (Flattened Device Tree)
> > > [   10.568267] [<c0015bdc>] (unwind_backtrace) from [<c001222c>] (show_stack+0x10/0x14)
> > > [   10.568267] [<c001222c>] (show_stack) from [<c05d2014>] (dump_stack+0x84/0x9c)
> > > [   10.568267] [<c05d2014>] (dump_stack) from [<c003ea90>] (warn_slowpath_common+0x7c/0xb8)
> > > [   10.568298] [<c003ea90>] (warn_slowpath_common) from [<c003eb68>] (warn_slowpath_null+0x1c/0x24)
> > > [   10.568298] [<c003eb68>] (warn_slowpath_null) from [<c04c1ffc>] (clk_disable+0x28/0x34)
> > > [   10.568328] [<c04c1ffc>] (clk_disable) from [<c0025b3c>] (_disable_clocks+0x18/0x68)
> > > [   10.568328] [<c0025b3c>] (_disable_clocks) from [<c0026f14>] (_idle+0x10c/0x214)
> > > [   10.568328] [<c0026f14>] (_idle) from [<c0855fac>] (_setup+0x338/0x410)
> > > [   10.568359] [<c0855fac>] (_setup) from [<c0027360>] (omap_hwmod_for_each+0x34/0x60)
> > > [   10.568359] [<c0027360>] (omap_hwmod_for_each) from [<c08563c4>] (__omap_hwmod_setup_all+0x30/0x40)
> > > [   10.568389] [<c08563c4>] (__omap_hwmod_setup_all) from [<c0008a04>] (do_one_initcall+0x80/0x1dc)
> > > [   10.568389] [<c0008a04>] (do_one_initcall) from [<c0848ea0>] (kernel_init_freeable+0x204/0x2d0)
> > > [   10.568420] [<c0848ea0>] (kernel_init_freeable) from [<c05cdab8>] (kernel_init+0x8/0xec)
> > > [   10.568420] [<c05cdab8>] (kernel_init) from [<c000e790>] (ret_from_fork+0x14/0x24)
> > > [   10.568420] ---[ end trace cb88537fdc8fa211 ]---
> 
> For reference, the above is line 992 in clk-next.
...
 
> Just booting 4430-sdp with omap2plus_defconfig. And git bisect
> points to 59cf3fcf9baf ("clk: Make clk API return per-user struct
> clk instances") as you already guessed.
>  
> > > [   10.568450] ------------[ cut here ]------------
> > > [   10.568450] WARNING: CPU: 0 PID: 1 at arch/arm/mach-omap2/dpll3xxx.c:436 omap3_noncore_dpll_enable+0xdc/0
> > > x10c()
> > > [   10.568450] Modules linked in:
> > > [   10.568481] CPU: 0 PID: 1 Comm: swapper/0 Tainted: G        W       3.19.0-rc6-next-20150202 #2037
> > > [   10.568481] Hardware name: Generic OMAP4 (Flattened Device Tree)
> > > [   10.568481] [<c0015bdc>] (unwind_backtrace) from [<c001222c>] (show_stack+0x10/0x14)
> > > [   10.568511] [<c001222c>] (show_stack) from [<c05d2014>] (dump_stack+0x84/0x9c)
> > > [   10.568511] [<c05d2014>] (dump_stack) from [<c003ea90>] (warn_slowpath_common+0x7c/0xb8)
> > > [   10.568511] [<c003ea90>] (warn_slowpath_common) from [<c003eb68>] (warn_slowpath_null+0x1c/0x24)
> > > [   10.568542] [<c003eb68>] (warn_slowpath_null) from [<c0035800>] (omap3_noncore_dpll_enable+0xdc/0x10c)
> > > [   10.568542] [<c0035800>] (omap3_noncore_dpll_enable) from [<c04c0a10>] (clk_core_enable+0x60/0x9c)
> > > [   10.568572] [<c04c0a10>] (clk_core_enable) from [<c04c09f0>] (clk_core_enable+0x40/0x9c)
> > > [   10.568572] ---[ end trace cb88537fdc8fa212 ]---
> > > ...
> > 
> > This is the same issue discussed already in this thread[0]. Feedback
> > from Tero & Paul on how to handle it would be nice.
> 
> Yes that one is a separate issue.
>  
> > Please let me know if anything else breaks for you.
> 
> Also off-idle on omap3 seems to be broken by commit 59cf3fcf9baf.

Actually the two warnigns above are all caused by the same issue.
And the patch Tero just posted fixes both of the issue. It's the thread 
"[PATCH v13 3/6] clk: Make clk API return per-user struct clk instances"
for reference.

Regards,

Tony

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

* Re: [PATCH v13 4/6] clk: Add rate constraints to clocks
@ 2015-02-02 20:47                       ` Tony Lindgren
  0 siblings, 0 replies; 186+ messages in thread
From: Tony Lindgren @ 2015-02-02 20:47 UTC (permalink / raw)
  To: Mike Turquette
  Cc: Geert Uytterhoeven, Tomeu Vizoso, Stephen Boyd,
	Linux MIPS Mailing List, linux-doc, Chao Xie, Haojian Zhuang,
	Boris Brezillon, Russell King, Jonathan Corbet, Emilio L??pez,
	Linux-sh list, Alex Elder, Zhangfei Gao, Bintian Wang,
	Matt Porter, linux-omap, linux-arm-kernel, linux-kernel, Ralf

* Tony Lindgren <tony@atomide.com> [150202 11:28]:
> * Mike Turquette <mturquette@linaro.org> [150202 09:50]:
> > Quoting Tony Lindgren (2015-02-02 08:12:37)
> > > 
> > > [   10.568206] ------------[ cut here ]------------
> > > [   10.568206] WARNING: CPU: 0 PID: 1 at drivers/clk/clk.c:925 clk_disable+0x28/0x34()
> > > [   10.568237] Modules linked in:
> > > [   10.568237] CPU: 0 PID: 1 Comm: swapper/0 Tainted: G        W       3.19.0-rc6-next-20150202 #2037
> > > [   10.568237] Hardware name: Generic OMAP4 (Flattened Device Tree)
> > > [   10.568267] [<c0015bdc>] (unwind_backtrace) from [<c001222c>] (show_stack+0x10/0x14)
> > > [   10.568267] [<c001222c>] (show_stack) from [<c05d2014>] (dump_stack+0x84/0x9c)
> > > [   10.568267] [<c05d2014>] (dump_stack) from [<c003ea90>] (warn_slowpath_common+0x7c/0xb8)
> > > [   10.568298] [<c003ea90>] (warn_slowpath_common) from [<c003eb68>] (warn_slowpath_null+0x1c/0x24)
> > > [   10.568298] [<c003eb68>] (warn_slowpath_null) from [<c04c1ffc>] (clk_disable+0x28/0x34)
> > > [   10.568328] [<c04c1ffc>] (clk_disable) from [<c0025b3c>] (_disable_clocks+0x18/0x68)
> > > [   10.568328] [<c0025b3c>] (_disable_clocks) from [<c0026f14>] (_idle+0x10c/0x214)
> > > [   10.568328] [<c0026f14>] (_idle) from [<c0855fac>] (_setup+0x338/0x410)
> > > [   10.568359] [<c0855fac>] (_setup) from [<c0027360>] (omap_hwmod_for_each+0x34/0x60)
> > > [   10.568359] [<c0027360>] (omap_hwmod_for_each) from [<c08563c4>] (__omap_hwmod_setup_all+0x30/0x40)
> > > [   10.568389] [<c08563c4>] (__omap_hwmod_setup_all) from [<c0008a04>] (do_one_initcall+0x80/0x1dc)
> > > [   10.568389] [<c0008a04>] (do_one_initcall) from [<c0848ea0>] (kernel_init_freeable+0x204/0x2d0)
> > > [   10.568420] [<c0848ea0>] (kernel_init_freeable) from [<c05cdab8>] (kernel_init+0x8/0xec)
> > > [   10.568420] [<c05cdab8>] (kernel_init) from [<c000e790>] (ret_from_fork+0x14/0x24)
> > > [   10.568420] ---[ end trace cb88537fdc8fa211 ]---
> 
> For reference, the above is line 992 in clk-next.
...
 
> Just booting 4430-sdp with omap2plus_defconfig. And git bisect
> points to 59cf3fcf9baf ("clk: Make clk API return per-user struct
> clk instances") as you already guessed.
>  
> > > [   10.568450] ------------[ cut here ]------------
> > > [   10.568450] WARNING: CPU: 0 PID: 1 at arch/arm/mach-omap2/dpll3xxx.c:436 omap3_noncore_dpll_enable+0xdc/0
> > > x10c()
> > > [   10.568450] Modules linked in:
> > > [   10.568481] CPU: 0 PID: 1 Comm: swapper/0 Tainted: G        W       3.19.0-rc6-next-20150202 #2037
> > > [   10.568481] Hardware name: Generic OMAP4 (Flattened Device Tree)
> > > [   10.568481] [<c0015bdc>] (unwind_backtrace) from [<c001222c>] (show_stack+0x10/0x14)
> > > [   10.568511] [<c001222c>] (show_stack) from [<c05d2014>] (dump_stack+0x84/0x9c)
> > > [   10.568511] [<c05d2014>] (dump_stack) from [<c003ea90>] (warn_slowpath_common+0x7c/0xb8)
> > > [   10.568511] [<c003ea90>] (warn_slowpath_common) from [<c003eb68>] (warn_slowpath_null+0x1c/0x24)
> > > [   10.568542] [<c003eb68>] (warn_slowpath_null) from [<c0035800>] (omap3_noncore_dpll_enable+0xdc/0x10c)
> > > [   10.568542] [<c0035800>] (omap3_noncore_dpll_enable) from [<c04c0a10>] (clk_core_enable+0x60/0x9c)
> > > [   10.568572] [<c04c0a10>] (clk_core_enable) from [<c04c09f0>] (clk_core_enable+0x40/0x9c)
> > > [   10.568572] ---[ end trace cb88537fdc8fa212 ]---
> > > ...
> > 
> > This is the same issue discussed already in this thread[0]. Feedback
> > from Tero & Paul on how to handle it would be nice.
> 
> Yes that one is a separate issue.
>  
> > Please let me know if anything else breaks for you.
> 
> Also off-idle on omap3 seems to be broken by commit 59cf3fcf9baf.

Actually the two warnigns above are all caused by the same issue.
And the patch Tero just posted fixes both of the issue. It's the thread 
"[PATCH v13 3/6] clk: Make clk API return per-user struct clk instances"
for reference.

Regards,

Tony

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

* [PATCH v13 4/6] clk: Add rate constraints to clocks
@ 2015-02-02 20:47                       ` Tony Lindgren
  0 siblings, 0 replies; 186+ messages in thread
From: Tony Lindgren @ 2015-02-02 20:47 UTC (permalink / raw)
  To: linux-arm-kernel

* Tony Lindgren <tony@atomide.com> [150202 11:28]:
> * Mike Turquette <mturquette@linaro.org> [150202 09:50]:
> > Quoting Tony Lindgren (2015-02-02 08:12:37)
> > > 
> > > [   10.568206] ------------[ cut here ]------------
> > > [   10.568206] WARNING: CPU: 0 PID: 1 at drivers/clk/clk.c:925 clk_disable+0x28/0x34()
> > > [   10.568237] Modules linked in:
> > > [   10.568237] CPU: 0 PID: 1 Comm: swapper/0 Tainted: G        W       3.19.0-rc6-next-20150202 #2037
> > > [   10.568237] Hardware name: Generic OMAP4 (Flattened Device Tree)
> > > [   10.568267] [<c0015bdc>] (unwind_backtrace) from [<c001222c>] (show_stack+0x10/0x14)
> > > [   10.568267] [<c001222c>] (show_stack) from [<c05d2014>] (dump_stack+0x84/0x9c)
> > > [   10.568267] [<c05d2014>] (dump_stack) from [<c003ea90>] (warn_slowpath_common+0x7c/0xb8)
> > > [   10.568298] [<c003ea90>] (warn_slowpath_common) from [<c003eb68>] (warn_slowpath_null+0x1c/0x24)
> > > [   10.568298] [<c003eb68>] (warn_slowpath_null) from [<c04c1ffc>] (clk_disable+0x28/0x34)
> > > [   10.568328] [<c04c1ffc>] (clk_disable) from [<c0025b3c>] (_disable_clocks+0x18/0x68)
> > > [   10.568328] [<c0025b3c>] (_disable_clocks) from [<c0026f14>] (_idle+0x10c/0x214)
> > > [   10.568328] [<c0026f14>] (_idle) from [<c0855fac>] (_setup+0x338/0x410)
> > > [   10.568359] [<c0855fac>] (_setup) from [<c0027360>] (omap_hwmod_for_each+0x34/0x60)
> > > [   10.568359] [<c0027360>] (omap_hwmod_for_each) from [<c08563c4>] (__omap_hwmod_setup_all+0x30/0x40)
> > > [   10.568389] [<c08563c4>] (__omap_hwmod_setup_all) from [<c0008a04>] (do_one_initcall+0x80/0x1dc)
> > > [   10.568389] [<c0008a04>] (do_one_initcall) from [<c0848ea0>] (kernel_init_freeable+0x204/0x2d0)
> > > [   10.568420] [<c0848ea0>] (kernel_init_freeable) from [<c05cdab8>] (kernel_init+0x8/0xec)
> > > [   10.568420] [<c05cdab8>] (kernel_init) from [<c000e790>] (ret_from_fork+0x14/0x24)
> > > [   10.568420] ---[ end trace cb88537fdc8fa211 ]---
> 
> For reference, the above is line 992 in clk-next.
...
 
> Just booting 4430-sdp with omap2plus_defconfig. And git bisect
> points to 59cf3fcf9baf ("clk: Make clk API return per-user struct
> clk instances") as you already guessed.
>  
> > > [   10.568450] ------------[ cut here ]------------
> > > [   10.568450] WARNING: CPU: 0 PID: 1 at arch/arm/mach-omap2/dpll3xxx.c:436 omap3_noncore_dpll_enable+0xdc/0
> > > x10c()
> > > [   10.568450] Modules linked in:
> > > [   10.568481] CPU: 0 PID: 1 Comm: swapper/0 Tainted: G        W       3.19.0-rc6-next-20150202 #2037
> > > [   10.568481] Hardware name: Generic OMAP4 (Flattened Device Tree)
> > > [   10.568481] [<c0015bdc>] (unwind_backtrace) from [<c001222c>] (show_stack+0x10/0x14)
> > > [   10.568511] [<c001222c>] (show_stack) from [<c05d2014>] (dump_stack+0x84/0x9c)
> > > [   10.568511] [<c05d2014>] (dump_stack) from [<c003ea90>] (warn_slowpath_common+0x7c/0xb8)
> > > [   10.568511] [<c003ea90>] (warn_slowpath_common) from [<c003eb68>] (warn_slowpath_null+0x1c/0x24)
> > > [   10.568542] [<c003eb68>] (warn_slowpath_null) from [<c0035800>] (omap3_noncore_dpll_enable+0xdc/0x10c)
> > > [   10.568542] [<c0035800>] (omap3_noncore_dpll_enable) from [<c04c0a10>] (clk_core_enable+0x60/0x9c)
> > > [   10.568572] [<c04c0a10>] (clk_core_enable) from [<c04c09f0>] (clk_core_enable+0x40/0x9c)
> > > [   10.568572] ---[ end trace cb88537fdc8fa212 ]---
> > > ...
> > 
> > This is the same issue discussed already in this thread[0]. Feedback
> > from Tero & Paul on how to handle it would be nice.
> 
> Yes that one is a separate issue.
>  
> > Please let me know if anything else breaks for you.
> 
> Also off-idle on omap3 seems to be broken by commit 59cf3fcf9baf.

Actually the two warnigns above are all caused by the same issue.
And the patch Tero just posted fixes both of the issue. It's the thread 
"[PATCH v13 3/6] clk: Make clk API return per-user struct clk instances"
for reference.

Regards,

Tony

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

* Re: [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
  2015-02-02 20:45       ` [Cocci] " Stephen Boyd
  (?)
@ 2015-02-02 21:31         ` Julia Lawall
  -1 siblings, 0 replies; 186+ messages in thread
From: Julia Lawall @ 2015-02-02 21:31 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Julia Lawall, Mike Turquette, Tomeu Vizoso, linux-kernel,
	Paul Walmsley, Tony Lindgren, linux-omap, linux-arm-kernel,
	t-kristo, cocci



On Mon, 2 Feb 2015, Stephen Boyd wrote:

> On 02/01/15 13:24, Mike Turquette wrote:
> > Quoting Tomeu Vizoso (2015-01-23 03:03:30)
> >> Moves clock state to struct clk_core, but takes care to change as little API as
> >> possible.
> >>
> >> struct clk_hw still has a pointer to a struct clk, which is the
> >> implementation's per-user clk instance, for backwards compatibility.
> >>
> >> The struct clk that clk_get_parent() returns isn't owned by the caller, but by
> >> the clock implementation, so the former shouldn't call clk_put() on it.
> >>
> >> Because some boards in mach-omap2 still register clocks statically, their clock
> >> registration had to be updated to take into account that the clock information
> >> is stored in struct clk_core now.
> > Tero, Paul & Tony,
> >
> > Tomeu's patch unveils a problem with omap3_noncore_dpll_enable and
> > struct dpll_data, namely this snippet from
> > arch/arm/mach-omap2/dpll3xxx.c:
> >
> >         parent = __clk_get_parent(hw->clk);
> >
> >         if (__clk_get_rate(hw->clk) == __clk_get_rate(dd->clk_bypass)) {
> >                 WARN(parent != dd->clk_bypass,
> >                                 "here0, parent name is %s, bypass name is %s\n",
> >                                 __clk_get_name(parent), __clk_get_name(dd->clk_bypass));
> >                 r = _omap3_noncore_dpll_bypass(clk);
> >         } else {
> >                 WARN(parent != dd->clk_ref,
> >                                 "here1, parent name is %s, ref name is %s\n",
> >                                 __clk_get_name(parent), __clk_get_name(dd->clk_ref));
> >                 r = _omap3_noncore_dpll_lock(clk);
> >         }
> >
> > struct dpll_data has members clk_ref and clk_bypass which are struct clk
> > pointers. This was always a bit of a violation of the clk.h contract
> > since drivers are not supposed to deref struct clk pointers. 
> 
> Julia,
> 
> Is there a way we can write a coccinelle script to check for this? The
> goal being to find all drivers that are comparing struct clk pointers or
> attempting to dereference them. There are probably other frameworks that
> could use the same type of check (regulator, gpiod, reset, pwm, etc.).
> Probably anything that has a get/put API.

Comparing or dereferencing pointers of a particular type should be 
straightforward to check for.  Is there an example of how to use the 
parent_index value to fix the problem?

julia


> 
> -Stephen
> 
> > Now that we
> > generate unique pointers for each call to clk_get (clk_ref & clk_bypass
> > are populated by of_clk_get in ti_clk_register_dpll) then the pointer
> > comparisons above will never be equal (even if they resolve down to the
> > same struct clk_core). I added the verbose traces to the WARNs above to
> > illustrate the point: the names are always the same but the pointers
> > differ.
> >
> > AFAICT this doesn't break anything, but booting on OMAP3+ results in
> > noisy WARNs.
> >
> > I think the correct fix is to replace clk_bypass and clk_ref pointers
> > with a simple integer parent_index. In fact we already have this index.
> > See how the pointers are populated in ti_clk_register_dpll:
> >
> >
> >         dd->clk_ref = of_clk_get(node, 0);
> >         dd->clk_bypass = of_clk_get(node, 1);
> >
> > Tony, the same problem affects the FAPLL code which copy/pastes some of
> > the DPLL code.
> >
> > Thoughts?
> >
> -- 
> Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
> a Linux Foundation Collaborative Project
> 
> 

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

* [Cocci] [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
@ 2015-02-02 21:31         ` Julia Lawall
  0 siblings, 0 replies; 186+ messages in thread
From: Julia Lawall @ 2015-02-02 21:31 UTC (permalink / raw)
  To: cocci



On Mon, 2 Feb 2015, Stephen Boyd wrote:

> On 02/01/15 13:24, Mike Turquette wrote:
> > Quoting Tomeu Vizoso (2015-01-23 03:03:30)
> >> Moves clock state to struct clk_core, but takes care to change as little API as
> >> possible.
> >>
> >> struct clk_hw still has a pointer to a struct clk, which is the
> >> implementation's per-user clk instance, for backwards compatibility.
> >>
> >> The struct clk that clk_get_parent() returns isn't owned by the caller, but by
> >> the clock implementation, so the former shouldn't call clk_put() on it.
> >>
> >> Because some boards in mach-omap2 still register clocks statically, their clock
> >> registration had to be updated to take into account that the clock information
> >> is stored in struct clk_core now.
> > Tero, Paul & Tony,
> >
> > Tomeu's patch unveils a problem with omap3_noncore_dpll_enable and
> > struct dpll_data, namely this snippet from
> > arch/arm/mach-omap2/dpll3xxx.c:
> >
> >         parent = __clk_get_parent(hw->clk);
> >
> >         if (__clk_get_rate(hw->clk) == __clk_get_rate(dd->clk_bypass)) {
> >                 WARN(parent != dd->clk_bypass,
> >                                 "here0, parent name is %s, bypass name is %s\n",
> >                                 __clk_get_name(parent), __clk_get_name(dd->clk_bypass));
> >                 r = _omap3_noncore_dpll_bypass(clk);
> >         } else {
> >                 WARN(parent != dd->clk_ref,
> >                                 "here1, parent name is %s, ref name is %s\n",
> >                                 __clk_get_name(parent), __clk_get_name(dd->clk_ref));
> >                 r = _omap3_noncore_dpll_lock(clk);
> >         }
> >
> > struct dpll_data has members clk_ref and clk_bypass which are struct clk
> > pointers. This was always a bit of a violation of the clk.h contract
> > since drivers are not supposed to deref struct clk pointers. 
> 
> Julia,
> 
> Is there a way we can write a coccinelle script to check for this? The
> goal being to find all drivers that are comparing struct clk pointers or
> attempting to dereference them. There are probably other frameworks that
> could use the same type of check (regulator, gpiod, reset, pwm, etc.).
> Probably anything that has a get/put API.

Comparing or dereferencing pointers of a particular type should be 
straightforward to check for.  Is there an example of how to use the 
parent_index value to fix the problem?

julia


> 
> -Stephen
> 
> > Now that we
> > generate unique pointers for each call to clk_get (clk_ref & clk_bypass
> > are populated by of_clk_get in ti_clk_register_dpll) then the pointer
> > comparisons above will never be equal (even if they resolve down to the
> > same struct clk_core). I added the verbose traces to the WARNs above to
> > illustrate the point: the names are always the same but the pointers
> > differ.
> >
> > AFAICT this doesn't break anything, but booting on OMAP3+ results in
> > noisy WARNs.
> >
> > I think the correct fix is to replace clk_bypass and clk_ref pointers
> > with a simple integer parent_index. In fact we already have this index.
> > See how the pointers are populated in ti_clk_register_dpll:
> >
> >
> >         dd->clk_ref = of_clk_get(node, 0);
> >         dd->clk_bypass = of_clk_get(node, 1);
> >
> > Tony, the same problem affects the FAPLL code which copy/pastes some of
> > the DPLL code.
> >
> > Thoughts?
> >
> -- 
> Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
> a Linux Foundation Collaborative Project
> 
> 

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

* [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
@ 2015-02-02 21:31         ` Julia Lawall
  0 siblings, 0 replies; 186+ messages in thread
From: Julia Lawall @ 2015-02-02 21:31 UTC (permalink / raw)
  To: linux-arm-kernel



On Mon, 2 Feb 2015, Stephen Boyd wrote:

> On 02/01/15 13:24, Mike Turquette wrote:
> > Quoting Tomeu Vizoso (2015-01-23 03:03:30)
> >> Moves clock state to struct clk_core, but takes care to change as little API as
> >> possible.
> >>
> >> struct clk_hw still has a pointer to a struct clk, which is the
> >> implementation's per-user clk instance, for backwards compatibility.
> >>
> >> The struct clk that clk_get_parent() returns isn't owned by the caller, but by
> >> the clock implementation, so the former shouldn't call clk_put() on it.
> >>
> >> Because some boards in mach-omap2 still register clocks statically, their clock
> >> registration had to be updated to take into account that the clock information
> >> is stored in struct clk_core now.
> > Tero, Paul & Tony,
> >
> > Tomeu's patch unveils a problem with omap3_noncore_dpll_enable and
> > struct dpll_data, namely this snippet from
> > arch/arm/mach-omap2/dpll3xxx.c:
> >
> >         parent = __clk_get_parent(hw->clk);
> >
> >         if (__clk_get_rate(hw->clk) == __clk_get_rate(dd->clk_bypass)) {
> >                 WARN(parent != dd->clk_bypass,
> >                                 "here0, parent name is %s, bypass name is %s\n",
> >                                 __clk_get_name(parent), __clk_get_name(dd->clk_bypass));
> >                 r = _omap3_noncore_dpll_bypass(clk);
> >         } else {
> >                 WARN(parent != dd->clk_ref,
> >                                 "here1, parent name is %s, ref name is %s\n",
> >                                 __clk_get_name(parent), __clk_get_name(dd->clk_ref));
> >                 r = _omap3_noncore_dpll_lock(clk);
> >         }
> >
> > struct dpll_data has members clk_ref and clk_bypass which are struct clk
> > pointers. This was always a bit of a violation of the clk.h contract
> > since drivers are not supposed to deref struct clk pointers. 
> 
> Julia,
> 
> Is there a way we can write a coccinelle script to check for this? The
> goal being to find all drivers that are comparing struct clk pointers or
> attempting to dereference them. There are probably other frameworks that
> could use the same type of check (regulator, gpiod, reset, pwm, etc.).
> Probably anything that has a get/put API.

Comparing or dereferencing pointers of a particular type should be 
straightforward to check for.  Is there an example of how to use the 
parent_index value to fix the problem?

julia


> 
> -Stephen
> 
> > Now that we
> > generate unique pointers for each call to clk_get (clk_ref & clk_bypass
> > are populated by of_clk_get in ti_clk_register_dpll) then the pointer
> > comparisons above will never be equal (even if they resolve down to the
> > same struct clk_core). I added the verbose traces to the WARNs above to
> > illustrate the point: the names are always the same but the pointers
> > differ.
> >
> > AFAICT this doesn't break anything, but booting on OMAP3+ results in
> > noisy WARNs.
> >
> > I think the correct fix is to replace clk_bypass and clk_ref pointers
> > with a simple integer parent_index. In fact we already have this index.
> > See how the pointers are populated in ti_clk_register_dpll:
> >
> >
> >         dd->clk_ref = of_clk_get(node, 0);
> >         dd->clk_bypass = of_clk_get(node, 1);
> >
> > Tony, the same problem affects the FAPLL code which copy/pastes some of
> > the DPLL code.
> >
> > Thoughts?
> >
> -- 
> Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
> a Linux Foundation Collaborative Project
> 
> 

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

* Re: [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
  2015-02-02 21:31         ` [Cocci] " Julia Lawall
  (?)
@ 2015-02-02 22:35           ` Stephen Boyd
  -1 siblings, 0 replies; 186+ messages in thread
From: Stephen Boyd @ 2015-02-02 22:35 UTC (permalink / raw)
  To: Julia Lawall
  Cc: Mike Turquette, Tomeu Vizoso, linux-kernel, Paul Walmsley,
	Tony Lindgren, linux-omap, linux-arm-kernel, t-kristo, cocci

On 02/02/15 13:31, Julia Lawall wrote:
>
> On Mon, 2 Feb 2015, Stephen Boyd wrote:
>
>> Julia,
>>
>> Is there a way we can write a coccinelle script to check for this? The
>> goal being to find all drivers that are comparing struct clk pointers or
>> attempting to dereference them. There are probably other frameworks that
>> could use the same type of check (regulator, gpiod, reset, pwm, etc.).
>> Probably anything that has a get/put API.
> Comparing or dereferencing pointers of a particular type should be 
> straightforward to check for.  Is there an example of how to use the 
> parent_index value to fix the problem?
>

I'm not sure how to fix this case with parent_index values generically.
I imagine it would be highly specific to the surrounding code to the
point where we couldn't fix it automatically. For example, if it's a clk
consumer (not provider like in this case) using an index wouldn't be the
right fix. We would need some sort of clk API that we don't currently
have and I would wonder why clock consumers even care to compare such
pointers in the first place.

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


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

* [Cocci] [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
@ 2015-02-02 22:35           ` Stephen Boyd
  0 siblings, 0 replies; 186+ messages in thread
From: Stephen Boyd @ 2015-02-02 22:35 UTC (permalink / raw)
  To: cocci

On 02/02/15 13:31, Julia Lawall wrote:
>
> On Mon, 2 Feb 2015, Stephen Boyd wrote:
>
>> Julia,
>>
>> Is there a way we can write a coccinelle script to check for this? The
>> goal being to find all drivers that are comparing struct clk pointers or
>> attempting to dereference them. There are probably other frameworks that
>> could use the same type of check (regulator, gpiod, reset, pwm, etc.).
>> Probably anything that has a get/put API.
> Comparing or dereferencing pointers of a particular type should be 
> straightforward to check for.  Is there an example of how to use the 
> parent_index value to fix the problem?
>

I'm not sure how to fix this case with parent_index values generically.
I imagine it would be highly specific to the surrounding code to the
point where we couldn't fix it automatically. For example, if it's a clk
consumer (not provider like in this case) using an index wouldn't be the
right fix. We would need some sort of clk API that we don't currently
have and I would wonder why clock consumers even care to compare such
pointers in the first place.

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

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

* [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
@ 2015-02-02 22:35           ` Stephen Boyd
  0 siblings, 0 replies; 186+ messages in thread
From: Stephen Boyd @ 2015-02-02 22:35 UTC (permalink / raw)
  To: linux-arm-kernel

On 02/02/15 13:31, Julia Lawall wrote:
>
> On Mon, 2 Feb 2015, Stephen Boyd wrote:
>
>> Julia,
>>
>> Is there a way we can write a coccinelle script to check for this? The
>> goal being to find all drivers that are comparing struct clk pointers or
>> attempting to dereference them. There are probably other frameworks that
>> could use the same type of check (regulator, gpiod, reset, pwm, etc.).
>> Probably anything that has a get/put API.
> Comparing or dereferencing pointers of a particular type should be 
> straightforward to check for.  Is there an example of how to use the 
> parent_index value to fix the problem?
>

I'm not sure how to fix this case with parent_index values generically.
I imagine it would be highly specific to the surrounding code to the
point where we couldn't fix it automatically. For example, if it's a clk
consumer (not provider like in this case) using an index wouldn't be the
right fix. We would need some sort of clk API that we don't currently
have and I would wonder why clock consumers even care to compare such
pointers in the first place.

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

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

* Re: [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
  2015-02-02 19:32       ` Tero Kristo
@ 2015-02-02 22:41         ` Mike Turquette
  -1 siblings, 0 replies; 186+ messages in thread
From: Mike Turquette @ 2015-02-02 22:41 UTC (permalink / raw)
  To: Tero Kristo, Tomeu Vizoso, linux-kernel, Stephen Boyd
  Cc: Paul Walmsley, Tony Lindgren, linux-omap, linux-arm-kernel

Quoting Tero Kristo (2015-02-02 11:32:01)
> On 02/01/2015 11:24 PM, Mike Turquette wrote:
> > Quoting Tomeu Vizoso (2015-01-23 03:03:30)
> >> Moves clock state to struct clk_core, but takes care to change as little API as
> >> possible.
> >>
> >> struct clk_hw still has a pointer to a struct clk, which is the
> >> implementation's per-user clk instance, for backwards compatibility.
> >>
> >> The struct clk that clk_get_parent() returns isn't owned by the caller, but by
> >> the clock implementation, so the former shouldn't call clk_put() on it.
> >>
> >> Because some boards in mach-omap2 still register clocks statically, their clock
> >> registration had to be updated to take into account that the clock information
> >> is stored in struct clk_core now.
> >
> > Tero, Paul & Tony,
> >
> > Tomeu's patch unveils a problem with omap3_noncore_dpll_enable and
> > struct dpll_data, namely this snippet from
> > arch/arm/mach-omap2/dpll3xxx.c:
> >
> >          parent = __clk_get_parent(hw->clk);
> >
> >          if (__clk_get_rate(hw->clk) == __clk_get_rate(dd->clk_bypass)) {
> >                  WARN(parent != dd->clk_bypass,
> >                                  "here0, parent name is %s, bypass name is %s\n",
> >                                  __clk_get_name(parent), __clk_get_name(dd->clk_bypass));
> >                  r = _omap3_noncore_dpll_bypass(clk);
> >          } else {
> >                  WARN(parent != dd->clk_ref,
> >                                  "here1, parent name is %s, ref name is %s\n",
> >                                  __clk_get_name(parent), __clk_get_name(dd->clk_ref));
> >                  r = _omap3_noncore_dpll_lock(clk);
> >          }
> >
> > struct dpll_data has members clk_ref and clk_bypass which are struct clk
> > pointers. This was always a bit of a violation of the clk.h contract
> > since drivers are not supposed to deref struct clk pointers. Now that we
> > generate unique pointers for each call to clk_get (clk_ref & clk_bypass
> > are populated by of_clk_get in ti_clk_register_dpll) then the pointer
> > comparisons above will never be equal (even if they resolve down to the
> > same struct clk_core). I added the verbose traces to the WARNs above to
> > illustrate the point: the names are always the same but the pointers
> > differ.
> >
> > AFAICT this doesn't break anything, but booting on OMAP3+ results in
> > noisy WARNs.
> >
> > I think the correct fix is to replace clk_bypass and clk_ref pointers
> > with a simple integer parent_index. In fact we already have this index.
> > See how the pointers are populated in ti_clk_register_dpll:
> 
> The problem is we still need to be able to get runtime parent clock 
> rates (the parent rate may change also), so simple index value is not 
> sufficient. We need a handle of some sort to the bypass/ref clocks. The 
> DPLL code generally requires knowledge of the bypass + reference clock 
> rates to work properly, as it calculates the M/N values based on these.

We can maybe introduce something like of_clk_get_parent_rate, as we have
analogous stuff for getting parent names and indexes. Without
introducing a new helper you could probably just do:

	clk_ref = clk_get_parent_by_index(dpll_clk, 0);
	ref_rate = clk_get_rate(clk_ref);

	clk_bypass = clk_get_parent_by_index(dpll_clk, 1);
	bypass_rate = clk_get_rate(clk_bypass);

Currently the semantics around this call are weird. It seems like it
would create a new struct clk pointer but it does not. So don't call
clk_put on clk_ref and clk_bypass yet. That might change in the future
as we iron out this brave new world that we all live in. Probably best
to leave a FIXME in there.

Stephen & Tomeu, let me know if I got any of that wrong.

> 
> Shall I change the DPLL code to check against clk_hw pointers or what is 
> the preferred approach here? The patch at the end does this and fixes 
> the dpll related warnings.

Yes, for now that is fine, but feels a bit hacky to me. I don't know
honestly, let me sleep on it. Anyways for 3.20 that is perfectly fine
but we might want to switch to something like the scheme above.

> 
> Btw, the rate constraints patch broke boot for me completely, but sounds 
> like you reverted it already.

Fixed with Stephen's patch from last week. Thanks for dealing with all
the breakage so promptly. It has helped a lot!

Regards,
Mike

> 
> -Tero
> 
> --------------------
> 
> Author: Tero Kristo <t-kristo@ti.com>
> Date:   Mon Feb 2 17:19:17 2015 +0200
> 
>      ARM: OMAP3+: clock: dpll: fix logic for comparing parent clocks
> 
>      DPLL code uses reference and bypass clock pointers for determining 
> runtime
>      properties for these clocks, like parent clock rates.
> 
>      As clock API now returns per-user clock structs, using a global handle
>      in the clock driver code does not work properly anymore. Fix this by
>      using the clk_hw instead, and comparing this against the parents.
> 
>      Signed-off-by: Tero Kristo <t-kristo@ti.com>
>      Fixes: 59cf3fcf9baf ("clk: Make clk API return per-user struct clk 
> instances")
> 
> diff --git a/arch/arm/mach-omap2/dpll3xxx.c b/arch/arm/mach-omap2/dpll3xxx.c
> index c2da2a0..49752d7 100644
> --- a/arch/arm/mach-omap2/dpll3xxx.c
> +++ b/arch/arm/mach-omap2/dpll3xxx.c
> @@ -410,7 +410,7 @@ int omap3_noncore_dpll_enable(struct clk_hw *hw)
>         struct clk_hw_omap *clk = to_clk_hw_omap(hw);
>         int r;
>         struct dpll_data *dd;
> -       struct clk *parent;
> +       struct clk_hw *parent;
> 
>         dd = clk->dpll_data;
>         if (!dd)
> @@ -427,13 +427,13 @@ int omap3_noncore_dpll_enable(struct clk_hw *hw)
>                 }
>         }
> 
> -       parent = __clk_get_parent(hw->clk);
> +       parent = __clk_get_hw(__clk_get_parent(hw->clk));
> 
>         if (__clk_get_rate(hw->clk) == __clk_get_rate(dd->clk_bypass)) {
> -               WARN_ON(parent != dd->clk_bypass);
> +               WARN_ON(parent != __clk_get_hw(dd->clk_bypass));
>                 r = _omap3_noncore_dpll_bypass(clk);
>         } else {
> -               WARN_ON(parent != dd->clk_ref);
> +               WARN_ON(parent != __clk_get_hw(dd->clk_ref));
>                 r = _omap3_noncore_dpll_lock(clk);
>         }
> 
> @@ -549,7 +549,8 @@ int omap3_noncore_dpll_set_rate(struct clk_hw *hw, 
> unsigned long rate,
>         if (!dd)
>                 return -EINVAL;
> 
> -       if (__clk_get_parent(hw->clk) != dd->clk_ref)
> +       if (__clk_get_hw(__clk_get_parent(hw->clk)) !=
> +           __clk_get_hw(dd->clk_ref))
>                 return -EINVAL;
> 
>         if (dd->last_rounded_rate == 0)
> 
> 

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

* [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
@ 2015-02-02 22:41         ` Mike Turquette
  0 siblings, 0 replies; 186+ messages in thread
From: Mike Turquette @ 2015-02-02 22:41 UTC (permalink / raw)
  To: linux-arm-kernel

Quoting Tero Kristo (2015-02-02 11:32:01)
> On 02/01/2015 11:24 PM, Mike Turquette wrote:
> > Quoting Tomeu Vizoso (2015-01-23 03:03:30)
> >> Moves clock state to struct clk_core, but takes care to change as little API as
> >> possible.
> >>
> >> struct clk_hw still has a pointer to a struct clk, which is the
> >> implementation's per-user clk instance, for backwards compatibility.
> >>
> >> The struct clk that clk_get_parent() returns isn't owned by the caller, but by
> >> the clock implementation, so the former shouldn't call clk_put() on it.
> >>
> >> Because some boards in mach-omap2 still register clocks statically, their clock
> >> registration had to be updated to take into account that the clock information
> >> is stored in struct clk_core now.
> >
> > Tero, Paul & Tony,
> >
> > Tomeu's patch unveils a problem with omap3_noncore_dpll_enable and
> > struct dpll_data, namely this snippet from
> > arch/arm/mach-omap2/dpll3xxx.c:
> >
> >          parent = __clk_get_parent(hw->clk);
> >
> >          if (__clk_get_rate(hw->clk) == __clk_get_rate(dd->clk_bypass)) {
> >                  WARN(parent != dd->clk_bypass,
> >                                  "here0, parent name is %s, bypass name is %s\n",
> >                                  __clk_get_name(parent), __clk_get_name(dd->clk_bypass));
> >                  r = _omap3_noncore_dpll_bypass(clk);
> >          } else {
> >                  WARN(parent != dd->clk_ref,
> >                                  "here1, parent name is %s, ref name is %s\n",
> >                                  __clk_get_name(parent), __clk_get_name(dd->clk_ref));
> >                  r = _omap3_noncore_dpll_lock(clk);
> >          }
> >
> > struct dpll_data has members clk_ref and clk_bypass which are struct clk
> > pointers. This was always a bit of a violation of the clk.h contract
> > since drivers are not supposed to deref struct clk pointers. Now that we
> > generate unique pointers for each call to clk_get (clk_ref & clk_bypass
> > are populated by of_clk_get in ti_clk_register_dpll) then the pointer
> > comparisons above will never be equal (even if they resolve down to the
> > same struct clk_core). I added the verbose traces to the WARNs above to
> > illustrate the point: the names are always the same but the pointers
> > differ.
> >
> > AFAICT this doesn't break anything, but booting on OMAP3+ results in
> > noisy WARNs.
> >
> > I think the correct fix is to replace clk_bypass and clk_ref pointers
> > with a simple integer parent_index. In fact we already have this index.
> > See how the pointers are populated in ti_clk_register_dpll:
> 
> The problem is we still need to be able to get runtime parent clock 
> rates (the parent rate may change also), so simple index value is not 
> sufficient. We need a handle of some sort to the bypass/ref clocks. The 
> DPLL code generally requires knowledge of the bypass + reference clock 
> rates to work properly, as it calculates the M/N values based on these.

We can maybe introduce something like of_clk_get_parent_rate, as we have
analogous stuff for getting parent names and indexes. Without
introducing a new helper you could probably just do:

	clk_ref = clk_get_parent_by_index(dpll_clk, 0);
	ref_rate = clk_get_rate(clk_ref);

	clk_bypass = clk_get_parent_by_index(dpll_clk, 1);
	bypass_rate = clk_get_rate(clk_bypass);

Currently the semantics around this call are weird. It seems like it
would create a new struct clk pointer but it does not. So don't call
clk_put on clk_ref and clk_bypass yet. That might change in the future
as we iron out this brave new world that we all live in. Probably best
to leave a FIXME in there.

Stephen & Tomeu, let me know if I got any of that wrong.

> 
> Shall I change the DPLL code to check against clk_hw pointers or what is 
> the preferred approach here? The patch at the end does this and fixes 
> the dpll related warnings.

Yes, for now that is fine, but feels a bit hacky to me. I don't know
honestly, let me sleep on it. Anyways for 3.20 that is perfectly fine
but we might want to switch to something like the scheme above.

> 
> Btw, the rate constraints patch broke boot for me completely, but sounds 
> like you reverted it already.

Fixed with Stephen's patch from last week. Thanks for dealing with all
the breakage so promptly. It has helped a lot!

Regards,
Mike

> 
> -Tero
> 
> --------------------
> 
> Author: Tero Kristo <t-kristo@ti.com>
> Date:   Mon Feb 2 17:19:17 2015 +0200
> 
>      ARM: OMAP3+: clock: dpll: fix logic for comparing parent clocks
> 
>      DPLL code uses reference and bypass clock pointers for determining 
> runtime
>      properties for these clocks, like parent clock rates.
> 
>      As clock API now returns per-user clock structs, using a global handle
>      in the clock driver code does not work properly anymore. Fix this by
>      using the clk_hw instead, and comparing this against the parents.
> 
>      Signed-off-by: Tero Kristo <t-kristo@ti.com>
>      Fixes: 59cf3fcf9baf ("clk: Make clk API return per-user struct clk 
> instances")
> 
> diff --git a/arch/arm/mach-omap2/dpll3xxx.c b/arch/arm/mach-omap2/dpll3xxx.c
> index c2da2a0..49752d7 100644
> --- a/arch/arm/mach-omap2/dpll3xxx.c
> +++ b/arch/arm/mach-omap2/dpll3xxx.c
> @@ -410,7 +410,7 @@ int omap3_noncore_dpll_enable(struct clk_hw *hw)
>         struct clk_hw_omap *clk = to_clk_hw_omap(hw);
>         int r;
>         struct dpll_data *dd;
> -       struct clk *parent;
> +       struct clk_hw *parent;
> 
>         dd = clk->dpll_data;
>         if (!dd)
> @@ -427,13 +427,13 @@ int omap3_noncore_dpll_enable(struct clk_hw *hw)
>                 }
>         }
> 
> -       parent = __clk_get_parent(hw->clk);
> +       parent = __clk_get_hw(__clk_get_parent(hw->clk));
> 
>         if (__clk_get_rate(hw->clk) == __clk_get_rate(dd->clk_bypass)) {
> -               WARN_ON(parent != dd->clk_bypass);
> +               WARN_ON(parent != __clk_get_hw(dd->clk_bypass));
>                 r = _omap3_noncore_dpll_bypass(clk);
>         } else {
> -               WARN_ON(parent != dd->clk_ref);
> +               WARN_ON(parent != __clk_get_hw(dd->clk_ref));
>                 r = _omap3_noncore_dpll_lock(clk);
>         }
> 
> @@ -549,7 +549,8 @@ int omap3_noncore_dpll_set_rate(struct clk_hw *hw, 
> unsigned long rate,
>         if (!dd)
>                 return -EINVAL;
> 
> -       if (__clk_get_parent(hw->clk) != dd->clk_ref)
> +       if (__clk_get_hw(__clk_get_parent(hw->clk)) !=
> +           __clk_get_hw(dd->clk_ref))
>                 return -EINVAL;
> 
>         if (dd->last_rounded_rate == 0)
> 
> 

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

* Re: [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
  2015-02-02 20:44         ` Tony Lindgren
@ 2015-02-02 22:48           ` Mike Turquette
  -1 siblings, 0 replies; 186+ messages in thread
From: Mike Turquette @ 2015-02-02 22:48 UTC (permalink / raw)
  To: Tony Lindgren, Tero Kristo
  Cc: Tomeu Vizoso, linux-kernel, Stephen Boyd, Paul Walmsley,
	linux-omap, linux-arm-kernel

Quoting Tony Lindgren (2015-02-02 12:44:02)
> * Tero Kristo <t-kristo@ti.com> [150202 11:35]:
> > On 02/01/2015 11:24 PM, Mike Turquette wrote:
> > >Quoting Tomeu Vizoso (2015-01-23 03:03:30)
> > >
> > >AFAICT this doesn't break anything, but booting on OMAP3+ results in
> > >noisy WARNs.
> > >
> > >I think the correct fix is to replace clk_bypass and clk_ref pointers
> > >with a simple integer parent_index. In fact we already have this index.
> > >See how the pointers are populated in ti_clk_register_dpll:
> > 
> > The problem is we still need to be able to get runtime parent clock rates
> > (the parent rate may change also), so simple index value is not sufficient.
> > We need a handle of some sort to the bypass/ref clocks. The DPLL code
> > generally requires knowledge of the bypass + reference clock rates to work
> > properly, as it calculates the M/N values based on these.
> > 
> > Shall I change the DPLL code to check against clk_hw pointers or what is the
> > preferred approach here? The patch at the end does this and fixes the dpll
> > related warnings.
> > 
> > Btw, the rate constraints patch broke boot for me completely, but sounds
> > like you reverted it already.
> 
> Thanks Tero, looks like your fix fixes all the issues I'm seeing with
> commit 59cf3fcf9baf. That is noisy dmesg, dpll_abe_ck not locking
> on 4430sdp, and off-idle not working for omap3.
> 
> I could not get the patch to apply, below is what I applied manually.
> 
> Mike, If possible, maybe fold this into 59cf3fcf9baf? It applies with
> some fuzz on that too. And inn that case, please feel also to add the
> following for Tomeu's patch:
> 
> Tested-by: Tony Lindgren <tony@atomide.com>

Done and done. Things look good in my testing. I've pushed another
branch out to the mirrors and hopefully the autobuild/autoboot testing
will give us the green light.

This implementation can be revisited probably after 3.19 comes out if
Tero doesn't like using clk_hw directly, or if we provide a better
interface.

Thanks,
Mike

> 
> 8<------------
> From: Tero Kristo <t-kristo@ti.com>
> Date: Mon, 2 Feb 2015 12:17:00 -0800
> Subject: [PATCH] ARM: OMAP3+: clock: dpll: fix logic for comparing parent clocks
> 
> DPLL code uses reference and bypass clock pointers for determining runtime
> properties for these clocks, like parent clock rates.
> As clock API now returns per-user clock structs, using a global handle
> in the clock driver code does not work properly anymore. Fix this by
> using the clk_hw instead, and comparing this against the parents.
> 
> Fixes: 59cf3fcf9baf ("clk: Make clk API return per-user struct clk instances")
> Signed-off-by: Tero Kristo <t-kristo@ti.com>
> [tony@atomide.com: updated to apply]
> Signed-off-by: Tony Lindgren <tony@atomide.com>
> 
> --- a/arch/arm/mach-omap2/dpll3xxx.c
> +++ b/arch/arm/mach-omap2/dpll3xxx.c
> @@ -410,7 +410,7 @@ int omap3_noncore_dpll_enable(struct clk_hw *hw)
>         struct clk_hw_omap *clk = to_clk_hw_omap(hw);
>         int r;
>         struct dpll_data *dd;
> -       struct clk *parent;
> +       struct clk_hw *parent;
>  
>         dd = clk->dpll_data;
>         if (!dd)
> @@ -427,13 +427,13 @@ int omap3_noncore_dpll_enable(struct clk_hw *hw)
>                 }
>         }
>  
> -       parent = __clk_get_parent(hw->clk);
> +       parent = __clk_get_hw(__clk_get_parent(hw->clk));
>  
>         if (__clk_get_rate(hw->clk) == __clk_get_rate(dd->clk_bypass)) {
> -               WARN_ON(parent != dd->clk_bypass);
> +               WARN_ON(parent != __clk_get_hw(dd->clk_bypass));
>                 r = _omap3_noncore_dpll_bypass(clk);
>         } else {
> -               WARN_ON(parent != dd->clk_ref);
> +               WARN_ON(parent != __clk_get_hw(dd->clk_ref));
>                 r = _omap3_noncore_dpll_lock(clk);
>         }
>  
> @@ -549,7 +549,8 @@ int omap3_noncore_dpll_set_rate(struct clk_hw *hw, unsigned long rate,
>         if (!dd)
>                 return -EINVAL;
>  
> -       if (__clk_get_parent(hw->clk) != dd->clk_ref)
> +       if (__clk_get_hw(__clk_get_parent(hw->clk)) !=
> +           __clk_get_hw(dd->clk_ref))
>                 return -EINVAL;
>  
>         if (dd->last_rounded_rate == 0)

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

* [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
@ 2015-02-02 22:48           ` Mike Turquette
  0 siblings, 0 replies; 186+ messages in thread
From: Mike Turquette @ 2015-02-02 22:48 UTC (permalink / raw)
  To: linux-arm-kernel

Quoting Tony Lindgren (2015-02-02 12:44:02)
> * Tero Kristo <t-kristo@ti.com> [150202 11:35]:
> > On 02/01/2015 11:24 PM, Mike Turquette wrote:
> > >Quoting Tomeu Vizoso (2015-01-23 03:03:30)
> > >
> > >AFAICT this doesn't break anything, but booting on OMAP3+ results in
> > >noisy WARNs.
> > >
> > >I think the correct fix is to replace clk_bypass and clk_ref pointers
> > >with a simple integer parent_index. In fact we already have this index.
> > >See how the pointers are populated in ti_clk_register_dpll:
> > 
> > The problem is we still need to be able to get runtime parent clock rates
> > (the parent rate may change also), so simple index value is not sufficient.
> > We need a handle of some sort to the bypass/ref clocks. The DPLL code
> > generally requires knowledge of the bypass + reference clock rates to work
> > properly, as it calculates the M/N values based on these.
> > 
> > Shall I change the DPLL code to check against clk_hw pointers or what is the
> > preferred approach here? The patch at the end does this and fixes the dpll
> > related warnings.
> > 
> > Btw, the rate constraints patch broke boot for me completely, but sounds
> > like you reverted it already.
> 
> Thanks Tero, looks like your fix fixes all the issues I'm seeing with
> commit 59cf3fcf9baf. That is noisy dmesg, dpll_abe_ck not locking
> on 4430sdp, and off-idle not working for omap3.
> 
> I could not get the patch to apply, below is what I applied manually.
> 
> Mike, If possible, maybe fold this into 59cf3fcf9baf? It applies with
> some fuzz on that too. And inn that case, please feel also to add the
> following for Tomeu's patch:
> 
> Tested-by: Tony Lindgren <tony@atomide.com>

Done and done. Things look good in my testing. I've pushed another
branch out to the mirrors and hopefully the autobuild/autoboot testing
will give us the green light.

This implementation can be revisited probably after 3.19 comes out if
Tero doesn't like using clk_hw directly, or if we provide a better
interface.

Thanks,
Mike

> 
> 8<------------
> From: Tero Kristo <t-kristo@ti.com>
> Date: Mon, 2 Feb 2015 12:17:00 -0800
> Subject: [PATCH] ARM: OMAP3+: clock: dpll: fix logic for comparing parent clocks
> 
> DPLL code uses reference and bypass clock pointers for determining runtime
> properties for these clocks, like parent clock rates.
> As clock API now returns per-user clock structs, using a global handle
> in the clock driver code does not work properly anymore. Fix this by
> using the clk_hw instead, and comparing this against the parents.
> 
> Fixes: 59cf3fcf9baf ("clk: Make clk API return per-user struct clk instances")
> Signed-off-by: Tero Kristo <t-kristo@ti.com>
> [tony at atomide.com: updated to apply]
> Signed-off-by: Tony Lindgren <tony@atomide.com>
> 
> --- a/arch/arm/mach-omap2/dpll3xxx.c
> +++ b/arch/arm/mach-omap2/dpll3xxx.c
> @@ -410,7 +410,7 @@ int omap3_noncore_dpll_enable(struct clk_hw *hw)
>         struct clk_hw_omap *clk = to_clk_hw_omap(hw);
>         int r;
>         struct dpll_data *dd;
> -       struct clk *parent;
> +       struct clk_hw *parent;
>  
>         dd = clk->dpll_data;
>         if (!dd)
> @@ -427,13 +427,13 @@ int omap3_noncore_dpll_enable(struct clk_hw *hw)
>                 }
>         }
>  
> -       parent = __clk_get_parent(hw->clk);
> +       parent = __clk_get_hw(__clk_get_parent(hw->clk));
>  
>         if (__clk_get_rate(hw->clk) == __clk_get_rate(dd->clk_bypass)) {
> -               WARN_ON(parent != dd->clk_bypass);
> +               WARN_ON(parent != __clk_get_hw(dd->clk_bypass));
>                 r = _omap3_noncore_dpll_bypass(clk);
>         } else {
> -               WARN_ON(parent != dd->clk_ref);
> +               WARN_ON(parent != __clk_get_hw(dd->clk_ref));
>                 r = _omap3_noncore_dpll_lock(clk);
>         }
>  
> @@ -549,7 +549,8 @@ int omap3_noncore_dpll_set_rate(struct clk_hw *hw, unsigned long rate,
>         if (!dd)
>                 return -EINVAL;
>  
> -       if (__clk_get_parent(hw->clk) != dd->clk_ref)
> +       if (__clk_get_hw(__clk_get_parent(hw->clk)) !=
> +           __clk_get_hw(dd->clk_ref))
>                 return -EINVAL;
>  
>         if (dd->last_rounded_rate == 0)

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

* Re: [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
  2015-02-02 22:35           ` [Cocci] " Stephen Boyd
  (?)
@ 2015-02-02 22:50             ` Mike Turquette
  -1 siblings, 0 replies; 186+ messages in thread
From: Mike Turquette @ 2015-02-02 22:50 UTC (permalink / raw)
  To: Stephen Boyd, Julia Lawall
  Cc: Tomeu Vizoso, linux-kernel, Paul Walmsley, Tony Lindgren,
	linux-omap, linux-arm-kernel, t-kristo, cocci

Quoting Stephen Boyd (2015-02-02 14:35:59)
> On 02/02/15 13:31, Julia Lawall wrote:
> >
> > On Mon, 2 Feb 2015, Stephen Boyd wrote:
> >
> >> Julia,
> >>
> >> Is there a way we can write a coccinelle script to check for this? The
> >> goal being to find all drivers that are comparing struct clk pointers or
> >> attempting to dereference them. There are probably other frameworks that
> >> could use the same type of check (regulator, gpiod, reset, pwm, etc.).
> >> Probably anything that has a get/put API.
> > Comparing or dereferencing pointers of a particular type should be 
> > straightforward to check for.  Is there an example of how to use the 
> > parent_index value to fix the problem?
> >
> 
> I'm not sure how to fix this case with parent_index values generically.
> I imagine it would be highly specific to the surrounding code to the
> point where we couldn't fix it automatically. For example, if it's a clk
> consumer (not provider like in this case) using an index wouldn't be the
> right fix. We would need some sort of clk API that we don't currently
> have and I would wonder why clock consumers even care to compare such
> pointers in the first place.

Ack. Is there precedent for a "Don't do that" kind of response?

Regards,
Mike

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

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

* [Cocci] [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
@ 2015-02-02 22:50             ` Mike Turquette
  0 siblings, 0 replies; 186+ messages in thread
From: Mike Turquette @ 2015-02-02 22:50 UTC (permalink / raw)
  To: cocci

Quoting Stephen Boyd (2015-02-02 14:35:59)
> On 02/02/15 13:31, Julia Lawall wrote:
> >
> > On Mon, 2 Feb 2015, Stephen Boyd wrote:
> >
> >> Julia,
> >>
> >> Is there a way we can write a coccinelle script to check for this? The
> >> goal being to find all drivers that are comparing struct clk pointers or
> >> attempting to dereference them. There are probably other frameworks that
> >> could use the same type of check (regulator, gpiod, reset, pwm, etc.).
> >> Probably anything that has a get/put API.
> > Comparing or dereferencing pointers of a particular type should be 
> > straightforward to check for.  Is there an example of how to use the 
> > parent_index value to fix the problem?
> >
> 
> I'm not sure how to fix this case with parent_index values generically.
> I imagine it would be highly specific to the surrounding code to the
> point where we couldn't fix it automatically. For example, if it's a clk
> consumer (not provider like in this case) using an index wouldn't be the
> right fix. We would need some sort of clk API that we don't currently
> have and I would wonder why clock consumers even care to compare such
> pointers in the first place.

Ack. Is there precedent for a "Don't do that" kind of response?

Regards,
Mike

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

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

* [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
@ 2015-02-02 22:50             ` Mike Turquette
  0 siblings, 0 replies; 186+ messages in thread
From: Mike Turquette @ 2015-02-02 22:50 UTC (permalink / raw)
  To: linux-arm-kernel

Quoting Stephen Boyd (2015-02-02 14:35:59)
> On 02/02/15 13:31, Julia Lawall wrote:
> >
> > On Mon, 2 Feb 2015, Stephen Boyd wrote:
> >
> >> Julia,
> >>
> >> Is there a way we can write a coccinelle script to check for this? The
> >> goal being to find all drivers that are comparing struct clk pointers or
> >> attempting to dereference them. There are probably other frameworks that
> >> could use the same type of check (regulator, gpiod, reset, pwm, etc.).
> >> Probably anything that has a get/put API.
> > Comparing or dereferencing pointers of a particular type should be 
> > straightforward to check for.  Is there an example of how to use the 
> > parent_index value to fix the problem?
> >
> 
> I'm not sure how to fix this case with parent_index values generically.
> I imagine it would be highly specific to the surrounding code to the
> point where we couldn't fix it automatically. For example, if it's a clk
> consumer (not provider like in this case) using an index wouldn't be the
> right fix. We would need some sort of clk API that we don't currently
> have and I would wonder why clock consumers even care to compare such
> pointers in the first place.

Ack. Is there precedent for a "Don't do that" kind of response?

Regards,
Mike

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

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

* Re: [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
  2015-02-02 22:41         ` Mike Turquette
@ 2015-02-02 22:52           ` Stephen Boyd
  -1 siblings, 0 replies; 186+ messages in thread
From: Stephen Boyd @ 2015-02-02 22:52 UTC (permalink / raw)
  To: Mike Turquette, Tero Kristo, Tomeu Vizoso, linux-kernel
  Cc: Paul Walmsley, Tony Lindgren, linux-omap, linux-arm-kernel

On 02/02/15 14:41, Mike Turquette wrote:
> Quoting Tero Kristo (2015-02-02 11:32:01)
>> On 02/01/2015 11:24 PM, Mike Turquette wrote:
>>>
>>> AFAICT this doesn't break anything, but booting on OMAP3+ results in
>>> noisy WARNs.
>>>
>>> I think the correct fix is to replace clk_bypass and clk_ref pointers
>>> with a simple integer parent_index. In fact we already have this index.
>>> See how the pointers are populated in ti_clk_register_dpll:
>> The problem is we still need to be able to get runtime parent clock 
>> rates (the parent rate may change also), so simple index value is not 
>> sufficient. We need a handle of some sort to the bypass/ref clocks. The 
>> DPLL code generally requires knowledge of the bypass + reference clock 
>> rates to work properly, as it calculates the M/N values based on these.
> We can maybe introduce something like of_clk_get_parent_rate, as we have
> analogous stuff for getting parent names and indexes. Without
> introducing a new helper you could probably just do:
>
> 	clk_ref = clk_get_parent_by_index(dpll_clk, 0);
> 	ref_rate = clk_get_rate(clk_ref);
>
> 	clk_bypass = clk_get_parent_by_index(dpll_clk, 1);
> 	bypass_rate = clk_get_rate(clk_bypass);
>
> Currently the semantics around this call are weird. It seems like it
> would create a new struct clk pointer but it does not. So don't call
> clk_put on clk_ref and clk_bypass yet. That might change in the future
> as we iron out this brave new world that we all live in. Probably best
> to leave a FIXME in there.
>
> Stephen & Tomeu, let me know if I got any of that wrong.

The plan is to make clk_get_parent_by_index() return a clk_hw pointer
instead of a clk pointer (probably with a new
clk_get_parent_hw_by_index() API). Then drivers that are clk providers
can deal in struct clk_hw and clk consumers can deal in struct clk,
nicely splitting the API between consumers and providers on the
structures they use to interact with the framework.

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


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

* [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
@ 2015-02-02 22:52           ` Stephen Boyd
  0 siblings, 0 replies; 186+ messages in thread
From: Stephen Boyd @ 2015-02-02 22:52 UTC (permalink / raw)
  To: linux-arm-kernel

On 02/02/15 14:41, Mike Turquette wrote:
> Quoting Tero Kristo (2015-02-02 11:32:01)
>> On 02/01/2015 11:24 PM, Mike Turquette wrote:
>>>
>>> AFAICT this doesn't break anything, but booting on OMAP3+ results in
>>> noisy WARNs.
>>>
>>> I think the correct fix is to replace clk_bypass and clk_ref pointers
>>> with a simple integer parent_index. In fact we already have this index.
>>> See how the pointers are populated in ti_clk_register_dpll:
>> The problem is we still need to be able to get runtime parent clock 
>> rates (the parent rate may change also), so simple index value is not 
>> sufficient. We need a handle of some sort to the bypass/ref clocks. The 
>> DPLL code generally requires knowledge of the bypass + reference clock 
>> rates to work properly, as it calculates the M/N values based on these.
> We can maybe introduce something like of_clk_get_parent_rate, as we have
> analogous stuff for getting parent names and indexes. Without
> introducing a new helper you could probably just do:
>
> 	clk_ref = clk_get_parent_by_index(dpll_clk, 0);
> 	ref_rate = clk_get_rate(clk_ref);
>
> 	clk_bypass = clk_get_parent_by_index(dpll_clk, 1);
> 	bypass_rate = clk_get_rate(clk_bypass);
>
> Currently the semantics around this call are weird. It seems like it
> would create a new struct clk pointer but it does not. So don't call
> clk_put on clk_ref and clk_bypass yet. That might change in the future
> as we iron out this brave new world that we all live in. Probably best
> to leave a FIXME in there.
>
> Stephen & Tomeu, let me know if I got any of that wrong.

The plan is to make clk_get_parent_by_index() return a clk_hw pointer
instead of a clk pointer (probably with a new
clk_get_parent_hw_by_index() API). Then drivers that are clk providers
can deal in struct clk_hw and clk consumers can deal in struct clk,
nicely splitting the API between consumers and providers on the
structures they use to interact with the framework.

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

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

* Re: [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
  2015-02-02 22:48           ` Mike Turquette
@ 2015-02-02 23:11             ` Tony Lindgren
  -1 siblings, 0 replies; 186+ messages in thread
From: Tony Lindgren @ 2015-02-02 23:11 UTC (permalink / raw)
  To: Mike Turquette
  Cc: Tero Kristo, Tomeu Vizoso, linux-kernel, Stephen Boyd,
	Paul Walmsley, linux-omap, linux-arm-kernel

* Mike Turquette <mturquette@linaro.org> [150202 14:51]:
> Quoting Tony Lindgren (2015-02-02 12:44:02)
> > 
> > Thanks Tero, looks like your fix fixes all the issues I'm seeing with
> > commit 59cf3fcf9baf. That is noisy dmesg, dpll_abe_ck not locking
> > on 4430sdp, and off-idle not working for omap3.
> > 
> > I could not get the patch to apply, below is what I applied manually.
> > 
> > Mike, If possible, maybe fold this into 59cf3fcf9baf? It applies with
> > some fuzz on that too. And inn that case, please feel also to add the
> > following for Tomeu's patch:
> > 
> > Tested-by: Tony Lindgren <tony@atomide.com>
> 
> Done and done. Things look good in my testing. I've pushed another
> branch out to the mirrors and hopefully the autobuild/autoboot testing
> will give us the green light.

Thanks I just checked that your updated branch works for me now.
 
> This implementation can be revisited probably after 3.19 comes out if
> Tero doesn't like using clk_hw directly, or if we provide a better
> interface.

Sounds like what Tero is saying also relates to knowing if the parent
clock is in bypass mode or not in addition to the parent rate.

Regards,

Tony

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

* [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
@ 2015-02-02 23:11             ` Tony Lindgren
  0 siblings, 0 replies; 186+ messages in thread
From: Tony Lindgren @ 2015-02-02 23:11 UTC (permalink / raw)
  To: linux-arm-kernel

* Mike Turquette <mturquette@linaro.org> [150202 14:51]:
> Quoting Tony Lindgren (2015-02-02 12:44:02)
> > 
> > Thanks Tero, looks like your fix fixes all the issues I'm seeing with
> > commit 59cf3fcf9baf. That is noisy dmesg, dpll_abe_ck not locking
> > on 4430sdp, and off-idle not working for omap3.
> > 
> > I could not get the patch to apply, below is what I applied manually.
> > 
> > Mike, If possible, maybe fold this into 59cf3fcf9baf? It applies with
> > some fuzz on that too. And inn that case, please feel also to add the
> > following for Tomeu's patch:
> > 
> > Tested-by: Tony Lindgren <tony@atomide.com>
> 
> Done and done. Things look good in my testing. I've pushed another
> branch out to the mirrors and hopefully the autobuild/autoboot testing
> will give us the green light.

Thanks I just checked that your updated branch works for me now.
 
> This implementation can be revisited probably after 3.19 comes out if
> Tero doesn't like using clk_hw directly, or if we provide a better
> interface.

Sounds like what Tero is saying also relates to knowing if the parent
clock is in bypass mode or not in addition to the parent rate.

Regards,

Tony

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

* Re: [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
  2015-02-02 22:41         ` Mike Turquette
@ 2015-02-03  7:03           ` Tomeu Vizoso
  -1 siblings, 0 replies; 186+ messages in thread
From: Tomeu Vizoso @ 2015-02-03  7:03 UTC (permalink / raw)
  To: Mike Turquette, Tero Kristo, linux-kernel, Stephen Boyd
  Cc: Paul Walmsley, Tony Lindgren, linux-omap, linux-arm-kernel

On 02/02/2015 11:41 PM, Mike Turquette wrote:
> Quoting Tero Kristo (2015-02-02 11:32:01)
>> On 02/01/2015 11:24 PM, Mike Turquette wrote:
>>> Quoting Tomeu Vizoso (2015-01-23 03:03:30)
>>>> Moves clock state to struct clk_core, but takes care to change as little API as
>>>> possible.
>>>>
>>>> struct clk_hw still has a pointer to a struct clk, which is the
>>>> implementation's per-user clk instance, for backwards compatibility.
>>>>
>>>> The struct clk that clk_get_parent() returns isn't owned by the caller, but by
>>>> the clock implementation, so the former shouldn't call clk_put() on it.
>>>>
>>>> Because some boards in mach-omap2 still register clocks statically, their clock
>>>> registration had to be updated to take into account that the clock information
>>>> is stored in struct clk_core now.
>>>
>>> Tero, Paul & Tony,
>>>
>>> Tomeu's patch unveils a problem with omap3_noncore_dpll_enable and
>>> struct dpll_data, namely this snippet from
>>> arch/arm/mach-omap2/dpll3xxx.c:
>>>
>>>          parent = __clk_get_parent(hw->clk);
>>>
>>>          if (__clk_get_rate(hw->clk) == __clk_get_rate(dd->clk_bypass)) {
>>>                  WARN(parent != dd->clk_bypass,
>>>                                  "here0, parent name is %s, bypass name is %s\n",
>>>                                  __clk_get_name(parent), __clk_get_name(dd->clk_bypass));
>>>                  r = _omap3_noncore_dpll_bypass(clk);
>>>          } else {
>>>                  WARN(parent != dd->clk_ref,
>>>                                  "here1, parent name is %s, ref name is %s\n",
>>>                                  __clk_get_name(parent), __clk_get_name(dd->clk_ref));
>>>                  r = _omap3_noncore_dpll_lock(clk);
>>>          }
>>>
>>> struct dpll_data has members clk_ref and clk_bypass which are struct clk
>>> pointers. This was always a bit of a violation of the clk.h contract
>>> since drivers are not supposed to deref struct clk pointers. Now that we
>>> generate unique pointers for each call to clk_get (clk_ref & clk_bypass
>>> are populated by of_clk_get in ti_clk_register_dpll) then the pointer
>>> comparisons above will never be equal (even if they resolve down to the
>>> same struct clk_core). I added the verbose traces to the WARNs above to
>>> illustrate the point: the names are always the same but the pointers
>>> differ.
>>>
>>> AFAICT this doesn't break anything, but booting on OMAP3+ results in
>>> noisy WARNs.
>>>
>>> I think the correct fix is to replace clk_bypass and clk_ref pointers
>>> with a simple integer parent_index. In fact we already have this index.
>>> See how the pointers are populated in ti_clk_register_dpll:
>>
>> The problem is we still need to be able to get runtime parent clock 
>> rates (the parent rate may change also), so simple index value is not 
>> sufficient. We need a handle of some sort to the bypass/ref clocks. The 
>> DPLL code generally requires knowledge of the bypass + reference clock 
>> rates to work properly, as it calculates the M/N values based on these.
> 
> We can maybe introduce something like of_clk_get_parent_rate, as we have
> analogous stuff for getting parent names and indexes. Without
> introducing a new helper you could probably just do:
> 
> 	clk_ref = clk_get_parent_by_index(dpll_clk, 0);
> 	ref_rate = clk_get_rate(clk_ref);
> 
> 	clk_bypass = clk_get_parent_by_index(dpll_clk, 1);
> 	bypass_rate = clk_get_rate(clk_bypass);
> 
> Currently the semantics around this call are weird. It seems like it
> would create a new struct clk pointer but it does not. So don't call
> clk_put on clk_ref and clk_bypass yet. That might change in the future
> as we iron out this brave new world that we all live in. Probably best
> to leave a FIXME in there.
> 
> Stephen & Tomeu, let me know if I got any of that wrong.

I think you got it right, just wanted to mention that we can and
probably should make the clk_get_parent_* calls in the consumer API to
return per-user clk instances but that we need to make sure first that
callers call clk_put afterwards.

This should also allow us to remove the reference to struct clk from
clk_hw, which is at best awkward.

Regards,

Tomeu

>>
>> Shall I change the DPLL code to check against clk_hw pointers or what is 
>> the preferred approach here? The patch at the end does this and fixes 
>> the dpll related warnings.
> 
> Yes, for now that is fine, but feels a bit hacky to me. I don't know
> honestly, let me sleep on it. Anyways for 3.20 that is perfectly fine
> but we might want to switch to something like the scheme above.
> 
>>
>> Btw, the rate constraints patch broke boot for me completely, but sounds 
>> like you reverted it already.
> 
> Fixed with Stephen's patch from last week. Thanks for dealing with all
> the breakage so promptly. It has helped a lot!
> 
> Regards,
> Mike
> 
>>
>> -Tero
>>
>> --------------------
>>
>> Author: Tero Kristo <t-kristo@ti.com>
>> Date:   Mon Feb 2 17:19:17 2015 +0200
>>
>>      ARM: OMAP3+: clock: dpll: fix logic for comparing parent clocks
>>
>>      DPLL code uses reference and bypass clock pointers for determining 
>> runtime
>>      properties for these clocks, like parent clock rates.
>>
>>      As clock API now returns per-user clock structs, using a global handle
>>      in the clock driver code does not work properly anymore. Fix this by
>>      using the clk_hw instead, and comparing this against the parents.
>>
>>      Signed-off-by: Tero Kristo <t-kristo@ti.com>
>>      Fixes: 59cf3fcf9baf ("clk: Make clk API return per-user struct clk 
>> instances")
>>
>> diff --git a/arch/arm/mach-omap2/dpll3xxx.c b/arch/arm/mach-omap2/dpll3xxx.c
>> index c2da2a0..49752d7 100644
>> --- a/arch/arm/mach-omap2/dpll3xxx.c
>> +++ b/arch/arm/mach-omap2/dpll3xxx.c
>> @@ -410,7 +410,7 @@ int omap3_noncore_dpll_enable(struct clk_hw *hw)
>>         struct clk_hw_omap *clk = to_clk_hw_omap(hw);
>>         int r;
>>         struct dpll_data *dd;
>> -       struct clk *parent;
>> +       struct clk_hw *parent;
>>
>>         dd = clk->dpll_data;
>>         if (!dd)
>> @@ -427,13 +427,13 @@ int omap3_noncore_dpll_enable(struct clk_hw *hw)
>>                 }
>>         }
>>
>> -       parent = __clk_get_parent(hw->clk);
>> +       parent = __clk_get_hw(__clk_get_parent(hw->clk));
>>
>>         if (__clk_get_rate(hw->clk) == __clk_get_rate(dd->clk_bypass)) {
>> -               WARN_ON(parent != dd->clk_bypass);
>> +               WARN_ON(parent != __clk_get_hw(dd->clk_bypass));
>>                 r = _omap3_noncore_dpll_bypass(clk);
>>         } else {
>> -               WARN_ON(parent != dd->clk_ref);
>> +               WARN_ON(parent != __clk_get_hw(dd->clk_ref));
>>                 r = _omap3_noncore_dpll_lock(clk);
>>         }
>>
>> @@ -549,7 +549,8 @@ int omap3_noncore_dpll_set_rate(struct clk_hw *hw, 
>> unsigned long rate,
>>         if (!dd)
>>                 return -EINVAL;
>>
>> -       if (__clk_get_parent(hw->clk) != dd->clk_ref)
>> +       if (__clk_get_hw(__clk_get_parent(hw->clk)) !=
>> +           __clk_get_hw(dd->clk_ref))
>>                 return -EINVAL;
>>
>>         if (dd->last_rounded_rate == 0)
>>
>>


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

* [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
@ 2015-02-03  7:03           ` Tomeu Vizoso
  0 siblings, 0 replies; 186+ messages in thread
From: Tomeu Vizoso @ 2015-02-03  7:03 UTC (permalink / raw)
  To: linux-arm-kernel

On 02/02/2015 11:41 PM, Mike Turquette wrote:
> Quoting Tero Kristo (2015-02-02 11:32:01)
>> On 02/01/2015 11:24 PM, Mike Turquette wrote:
>>> Quoting Tomeu Vizoso (2015-01-23 03:03:30)
>>>> Moves clock state to struct clk_core, but takes care to change as little API as
>>>> possible.
>>>>
>>>> struct clk_hw still has a pointer to a struct clk, which is the
>>>> implementation's per-user clk instance, for backwards compatibility.
>>>>
>>>> The struct clk that clk_get_parent() returns isn't owned by the caller, but by
>>>> the clock implementation, so the former shouldn't call clk_put() on it.
>>>>
>>>> Because some boards in mach-omap2 still register clocks statically, their clock
>>>> registration had to be updated to take into account that the clock information
>>>> is stored in struct clk_core now.
>>>
>>> Tero, Paul & Tony,
>>>
>>> Tomeu's patch unveils a problem with omap3_noncore_dpll_enable and
>>> struct dpll_data, namely this snippet from
>>> arch/arm/mach-omap2/dpll3xxx.c:
>>>
>>>          parent = __clk_get_parent(hw->clk);
>>>
>>>          if (__clk_get_rate(hw->clk) == __clk_get_rate(dd->clk_bypass)) {
>>>                  WARN(parent != dd->clk_bypass,
>>>                                  "here0, parent name is %s, bypass name is %s\n",
>>>                                  __clk_get_name(parent), __clk_get_name(dd->clk_bypass));
>>>                  r = _omap3_noncore_dpll_bypass(clk);
>>>          } else {
>>>                  WARN(parent != dd->clk_ref,
>>>                                  "here1, parent name is %s, ref name is %s\n",
>>>                                  __clk_get_name(parent), __clk_get_name(dd->clk_ref));
>>>                  r = _omap3_noncore_dpll_lock(clk);
>>>          }
>>>
>>> struct dpll_data has members clk_ref and clk_bypass which are struct clk
>>> pointers. This was always a bit of a violation of the clk.h contract
>>> since drivers are not supposed to deref struct clk pointers. Now that we
>>> generate unique pointers for each call to clk_get (clk_ref & clk_bypass
>>> are populated by of_clk_get in ti_clk_register_dpll) then the pointer
>>> comparisons above will never be equal (even if they resolve down to the
>>> same struct clk_core). I added the verbose traces to the WARNs above to
>>> illustrate the point: the names are always the same but the pointers
>>> differ.
>>>
>>> AFAICT this doesn't break anything, but booting on OMAP3+ results in
>>> noisy WARNs.
>>>
>>> I think the correct fix is to replace clk_bypass and clk_ref pointers
>>> with a simple integer parent_index. In fact we already have this index.
>>> See how the pointers are populated in ti_clk_register_dpll:
>>
>> The problem is we still need to be able to get runtime parent clock 
>> rates (the parent rate may change also), so simple index value is not 
>> sufficient. We need a handle of some sort to the bypass/ref clocks. The 
>> DPLL code generally requires knowledge of the bypass + reference clock 
>> rates to work properly, as it calculates the M/N values based on these.
> 
> We can maybe introduce something like of_clk_get_parent_rate, as we have
> analogous stuff for getting parent names and indexes. Without
> introducing a new helper you could probably just do:
> 
> 	clk_ref = clk_get_parent_by_index(dpll_clk, 0);
> 	ref_rate = clk_get_rate(clk_ref);
> 
> 	clk_bypass = clk_get_parent_by_index(dpll_clk, 1);
> 	bypass_rate = clk_get_rate(clk_bypass);
> 
> Currently the semantics around this call are weird. It seems like it
> would create a new struct clk pointer but it does not. So don't call
> clk_put on clk_ref and clk_bypass yet. That might change in the future
> as we iron out this brave new world that we all live in. Probably best
> to leave a FIXME in there.
> 
> Stephen & Tomeu, let me know if I got any of that wrong.

I think you got it right, just wanted to mention that we can and
probably should make the clk_get_parent_* calls in the consumer API to
return per-user clk instances but that we need to make sure first that
callers call clk_put afterwards.

This should also allow us to remove the reference to struct clk from
clk_hw, which is at best awkward.

Regards,

Tomeu

>>
>> Shall I change the DPLL code to check against clk_hw pointers or what is 
>> the preferred approach here? The patch at the end does this and fixes 
>> the dpll related warnings.
> 
> Yes, for now that is fine, but feels a bit hacky to me. I don't know
> honestly, let me sleep on it. Anyways for 3.20 that is perfectly fine
> but we might want to switch to something like the scheme above.
> 
>>
>> Btw, the rate constraints patch broke boot for me completely, but sounds 
>> like you reverted it already.
> 
> Fixed with Stephen's patch from last week. Thanks for dealing with all
> the breakage so promptly. It has helped a lot!
> 
> Regards,
> Mike
> 
>>
>> -Tero
>>
>> --------------------
>>
>> Author: Tero Kristo <t-kristo@ti.com>
>> Date:   Mon Feb 2 17:19:17 2015 +0200
>>
>>      ARM: OMAP3+: clock: dpll: fix logic for comparing parent clocks
>>
>>      DPLL code uses reference and bypass clock pointers for determining 
>> runtime
>>      properties for these clocks, like parent clock rates.
>>
>>      As clock API now returns per-user clock structs, using a global handle
>>      in the clock driver code does not work properly anymore. Fix this by
>>      using the clk_hw instead, and comparing this against the parents.
>>
>>      Signed-off-by: Tero Kristo <t-kristo@ti.com>
>>      Fixes: 59cf3fcf9baf ("clk: Make clk API return per-user struct clk 
>> instances")
>>
>> diff --git a/arch/arm/mach-omap2/dpll3xxx.c b/arch/arm/mach-omap2/dpll3xxx.c
>> index c2da2a0..49752d7 100644
>> --- a/arch/arm/mach-omap2/dpll3xxx.c
>> +++ b/arch/arm/mach-omap2/dpll3xxx.c
>> @@ -410,7 +410,7 @@ int omap3_noncore_dpll_enable(struct clk_hw *hw)
>>         struct clk_hw_omap *clk = to_clk_hw_omap(hw);
>>         int r;
>>         struct dpll_data *dd;
>> -       struct clk *parent;
>> +       struct clk_hw *parent;
>>
>>         dd = clk->dpll_data;
>>         if (!dd)
>> @@ -427,13 +427,13 @@ int omap3_noncore_dpll_enable(struct clk_hw *hw)
>>                 }
>>         }
>>
>> -       parent = __clk_get_parent(hw->clk);
>> +       parent = __clk_get_hw(__clk_get_parent(hw->clk));
>>
>>         if (__clk_get_rate(hw->clk) == __clk_get_rate(dd->clk_bypass)) {
>> -               WARN_ON(parent != dd->clk_bypass);
>> +               WARN_ON(parent != __clk_get_hw(dd->clk_bypass));
>>                 r = _omap3_noncore_dpll_bypass(clk);
>>         } else {
>> -               WARN_ON(parent != dd->clk_ref);
>> +               WARN_ON(parent != __clk_get_hw(dd->clk_ref));
>>                 r = _omap3_noncore_dpll_lock(clk);
>>         }
>>
>> @@ -549,7 +549,8 @@ int omap3_noncore_dpll_set_rate(struct clk_hw *hw, 
>> unsigned long rate,
>>         if (!dd)
>>                 return -EINVAL;
>>
>> -       if (__clk_get_parent(hw->clk) != dd->clk_ref)
>> +       if (__clk_get_hw(__clk_get_parent(hw->clk)) !=
>> +           __clk_get_hw(dd->clk_ref))
>>                 return -EINVAL;
>>
>>         if (dd->last_rounded_rate == 0)
>>
>>

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

* Re: [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
  2015-02-03  7:03           ` Tomeu Vizoso
  (?)
@ 2015-02-03  8:46             ` Tero Kristo
  -1 siblings, 0 replies; 186+ messages in thread
From: Tero Kristo @ 2015-02-03  8:46 UTC (permalink / raw)
  To: Tomeu Vizoso, Mike Turquette, linux-kernel, Stephen Boyd
  Cc: Paul Walmsley, Tony Lindgren, linux-omap, linux-arm-kernel

On 02/03/2015 09:03 AM, Tomeu Vizoso wrote:
> On 02/02/2015 11:41 PM, Mike Turquette wrote:
>> Quoting Tero Kristo (2015-02-02 11:32:01)
>>> On 02/01/2015 11:24 PM, Mike Turquette wrote:
>>>> Quoting Tomeu Vizoso (2015-01-23 03:03:30)
>>>>> Moves clock state to struct clk_core, but takes care to change as little API as
>>>>> possible.
>>>>>
>>>>> struct clk_hw still has a pointer to a struct clk, which is the
>>>>> implementation's per-user clk instance, for backwards compatibility.
>>>>>
>>>>> The struct clk that clk_get_parent() returns isn't owned by the caller, but by
>>>>> the clock implementation, so the former shouldn't call clk_put() on it.
>>>>>
>>>>> Because some boards in mach-omap2 still register clocks statically, their clock
>>>>> registration had to be updated to take into account that the clock information
>>>>> is stored in struct clk_core now.
>>>>
>>>> Tero, Paul & Tony,
>>>>
>>>> Tomeu's patch unveils a problem with omap3_noncore_dpll_enable and
>>>> struct dpll_data, namely this snippet from
>>>> arch/arm/mach-omap2/dpll3xxx.c:
>>>>
>>>>           parent = __clk_get_parent(hw->clk);
>>>>
>>>>           if (__clk_get_rate(hw->clk) == __clk_get_rate(dd->clk_bypass)) {
>>>>                   WARN(parent != dd->clk_bypass,
>>>>                                   "here0, parent name is %s, bypass name is %s\n",
>>>>                                   __clk_get_name(parent), __clk_get_name(dd->clk_bypass));
>>>>                   r = _omap3_noncore_dpll_bypass(clk);
>>>>           } else {
>>>>                   WARN(parent != dd->clk_ref,
>>>>                                   "here1, parent name is %s, ref name is %s\n",
>>>>                                   __clk_get_name(parent), __clk_get_name(dd->clk_ref));
>>>>                   r = _omap3_noncore_dpll_lock(clk);
>>>>           }
>>>>
>>>> struct dpll_data has members clk_ref and clk_bypass which are struct clk
>>>> pointers. This was always a bit of a violation of the clk.h contract
>>>> since drivers are not supposed to deref struct clk pointers. Now that we
>>>> generate unique pointers for each call to clk_get (clk_ref & clk_bypass
>>>> are populated by of_clk_get in ti_clk_register_dpll) then the pointer
>>>> comparisons above will never be equal (even if they resolve down to the
>>>> same struct clk_core). I added the verbose traces to the WARNs above to
>>>> illustrate the point: the names are always the same but the pointers
>>>> differ.
>>>>
>>>> AFAICT this doesn't break anything, but booting on OMAP3+ results in
>>>> noisy WARNs.
>>>>
>>>> I think the correct fix is to replace clk_bypass and clk_ref pointers
>>>> with a simple integer parent_index. In fact we already have this index.
>>>> See how the pointers are populated in ti_clk_register_dpll:
>>>
>>> The problem is we still need to be able to get runtime parent clock
>>> rates (the parent rate may change also), so simple index value is not
>>> sufficient. We need a handle of some sort to the bypass/ref clocks. The
>>> DPLL code generally requires knowledge of the bypass + reference clock
>>> rates to work properly, as it calculates the M/N values based on these.
>>
>> We can maybe introduce something like of_clk_get_parent_rate, as we have
>> analogous stuff for getting parent names and indexes. Without
>> introducing a new helper you could probably just do:
>>
>> 	clk_ref = clk_get_parent_by_index(dpll_clk, 0);
>> 	ref_rate = clk_get_rate(clk_ref);
>>
>> 	clk_bypass = clk_get_parent_by_index(dpll_clk, 1);
>> 	bypass_rate = clk_get_rate(clk_bypass);
>>
>> Currently the semantics around this call are weird. It seems like it
>> would create a new struct clk pointer but it does not. So don't call
>> clk_put on clk_ref and clk_bypass yet. That might change in the future
>> as we iron out this brave new world that we all live in. Probably best
>> to leave a FIXME in there.
>>
>> Stephen & Tomeu, let me know if I got any of that wrong.
>
> I think you got it right, just wanted to mention that we can and
> probably should make the clk_get_parent_* calls in the consumer API to
> return per-user clk instances but that we need to make sure first that
> callers call clk_put afterwards.
>
> This should also allow us to remove the reference to struct clk from
> clk_hw, which is at best awkward.
>
> Regards,

For the DPLL code it should just be fine to be able to get the current 
parent index (not parent clock handle), and read a parent clock rate 
based on an arbitrary index (not just the current one.) I don't think 
there is any other need for having the clk_ref / clk_bypass clock 
handles around.

-Tero

>
> Tomeu
>
>>>
>>> Shall I change the DPLL code to check against clk_hw pointers or what is
>>> the preferred approach here? The patch at the end does this and fixes
>>> the dpll related warnings.
>>
>> Yes, for now that is fine, but feels a bit hacky to me. I don't know
>> honestly, let me sleep on it. Anyways for 3.20 that is perfectly fine
>> but we might want to switch to something like the scheme above.
>>
>>>
>>> Btw, the rate constraints patch broke boot for me completely, but sounds
>>> like you reverted it already.
>>
>> Fixed with Stephen's patch from last week. Thanks for dealing with all
>> the breakage so promptly. It has helped a lot!
>>
>> Regards,
>> Mike
>>
>>>
>>> -Tero
>>>
>>> --------------------
>>>
>>> Author: Tero Kristo <t-kristo@ti.com>
>>> Date:   Mon Feb 2 17:19:17 2015 +0200
>>>
>>>       ARM: OMAP3+: clock: dpll: fix logic for comparing parent clocks
>>>
>>>       DPLL code uses reference and bypass clock pointers for determining
>>> runtime
>>>       properties for these clocks, like parent clock rates.
>>>
>>>       As clock API now returns per-user clock structs, using a global handle
>>>       in the clock driver code does not work properly anymore. Fix this by
>>>       using the clk_hw instead, and comparing this against the parents.
>>>
>>>       Signed-off-by: Tero Kristo <t-kristo@ti.com>
>>>       Fixes: 59cf3fcf9baf ("clk: Make clk API return per-user struct clk
>>> instances")
>>>
>>> diff --git a/arch/arm/mach-omap2/dpll3xxx.c b/arch/arm/mach-omap2/dpll3xxx.c
>>> index c2da2a0..49752d7 100644
>>> --- a/arch/arm/mach-omap2/dpll3xxx.c
>>> +++ b/arch/arm/mach-omap2/dpll3xxx.c
>>> @@ -410,7 +410,7 @@ int omap3_noncore_dpll_enable(struct clk_hw *hw)
>>>          struct clk_hw_omap *clk = to_clk_hw_omap(hw);
>>>          int r;
>>>          struct dpll_data *dd;
>>> -       struct clk *parent;
>>> +       struct clk_hw *parent;
>>>
>>>          dd = clk->dpll_data;
>>>          if (!dd)
>>> @@ -427,13 +427,13 @@ int omap3_noncore_dpll_enable(struct clk_hw *hw)
>>>                  }
>>>          }
>>>
>>> -       parent = __clk_get_parent(hw->clk);
>>> +       parent = __clk_get_hw(__clk_get_parent(hw->clk));
>>>
>>>          if (__clk_get_rate(hw->clk) == __clk_get_rate(dd->clk_bypass)) {
>>> -               WARN_ON(parent != dd->clk_bypass);
>>> +               WARN_ON(parent != __clk_get_hw(dd->clk_bypass));
>>>                  r = _omap3_noncore_dpll_bypass(clk);
>>>          } else {
>>> -               WARN_ON(parent != dd->clk_ref);
>>> +               WARN_ON(parent != __clk_get_hw(dd->clk_ref));
>>>                  r = _omap3_noncore_dpll_lock(clk);
>>>          }
>>>
>>> @@ -549,7 +549,8 @@ int omap3_noncore_dpll_set_rate(struct clk_hw *hw,
>>> unsigned long rate,
>>>          if (!dd)
>>>                  return -EINVAL;
>>>
>>> -       if (__clk_get_parent(hw->clk) != dd->clk_ref)
>>> +       if (__clk_get_hw(__clk_get_parent(hw->clk)) !=
>>> +           __clk_get_hw(dd->clk_ref))
>>>                  return -EINVAL;
>>>
>>>          if (dd->last_rounded_rate == 0)
>>>
>>>
>


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

* Re: [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
@ 2015-02-03  8:46             ` Tero Kristo
  0 siblings, 0 replies; 186+ messages in thread
From: Tero Kristo @ 2015-02-03  8:46 UTC (permalink / raw)
  To: Tomeu Vizoso, Mike Turquette, linux-kernel, Stephen Boyd
  Cc: Paul Walmsley, Tony Lindgren, linux-omap, linux-arm-kernel

On 02/03/2015 09:03 AM, Tomeu Vizoso wrote:
> On 02/02/2015 11:41 PM, Mike Turquette wrote:
>> Quoting Tero Kristo (2015-02-02 11:32:01)
>>> On 02/01/2015 11:24 PM, Mike Turquette wrote:
>>>> Quoting Tomeu Vizoso (2015-01-23 03:03:30)
>>>>> Moves clock state to struct clk_core, but takes care to change as little API as
>>>>> possible.
>>>>>
>>>>> struct clk_hw still has a pointer to a struct clk, which is the
>>>>> implementation's per-user clk instance, for backwards compatibility.
>>>>>
>>>>> The struct clk that clk_get_parent() returns isn't owned by the caller, but by
>>>>> the clock implementation, so the former shouldn't call clk_put() on it.
>>>>>
>>>>> Because some boards in mach-omap2 still register clocks statically, their clock
>>>>> registration had to be updated to take into account that the clock information
>>>>> is stored in struct clk_core now.
>>>>
>>>> Tero, Paul & Tony,
>>>>
>>>> Tomeu's patch unveils a problem with omap3_noncore_dpll_enable and
>>>> struct dpll_data, namely this snippet from
>>>> arch/arm/mach-omap2/dpll3xxx.c:
>>>>
>>>>           parent = __clk_get_parent(hw->clk);
>>>>
>>>>           if (__clk_get_rate(hw->clk) == __clk_get_rate(dd->clk_bypass)) {
>>>>                   WARN(parent != dd->clk_bypass,
>>>>                                   "here0, parent name is %s, bypass name is %s\n",
>>>>                                   __clk_get_name(parent), __clk_get_name(dd->clk_bypass));
>>>>                   r = _omap3_noncore_dpll_bypass(clk);
>>>>           } else {
>>>>                   WARN(parent != dd->clk_ref,
>>>>                                   "here1, parent name is %s, ref name is %s\n",
>>>>                                   __clk_get_name(parent), __clk_get_name(dd->clk_ref));
>>>>                   r = _omap3_noncore_dpll_lock(clk);
>>>>           }
>>>>
>>>> struct dpll_data has members clk_ref and clk_bypass which are struct clk
>>>> pointers. This was always a bit of a violation of the clk.h contract
>>>> since drivers are not supposed to deref struct clk pointers. Now that we
>>>> generate unique pointers for each call to clk_get (clk_ref & clk_bypass
>>>> are populated by of_clk_get in ti_clk_register_dpll) then the pointer
>>>> comparisons above will never be equal (even if they resolve down to the
>>>> same struct clk_core). I added the verbose traces to the WARNs above to
>>>> illustrate the point: the names are always the same but the pointers
>>>> differ.
>>>>
>>>> AFAICT this doesn't break anything, but booting on OMAP3+ results in
>>>> noisy WARNs.
>>>>
>>>> I think the correct fix is to replace clk_bypass and clk_ref pointers
>>>> with a simple integer parent_index. In fact we already have this index.
>>>> See how the pointers are populated in ti_clk_register_dpll:
>>>
>>> The problem is we still need to be able to get runtime parent clock
>>> rates (the parent rate may change also), so simple index value is not
>>> sufficient. We need a handle of some sort to the bypass/ref clocks. The
>>> DPLL code generally requires knowledge of the bypass + reference clock
>>> rates to work properly, as it calculates the M/N values based on these.
>>
>> We can maybe introduce something like of_clk_get_parent_rate, as we have
>> analogous stuff for getting parent names and indexes. Without
>> introducing a new helper you could probably just do:
>>
>> 	clk_ref = clk_get_parent_by_index(dpll_clk, 0);
>> 	ref_rate = clk_get_rate(clk_ref);
>>
>> 	clk_bypass = clk_get_parent_by_index(dpll_clk, 1);
>> 	bypass_rate = clk_get_rate(clk_bypass);
>>
>> Currently the semantics around this call are weird. It seems like it
>> would create a new struct clk pointer but it does not. So don't call
>> clk_put on clk_ref and clk_bypass yet. That might change in the future
>> as we iron out this brave new world that we all live in. Probably best
>> to leave a FIXME in there.
>>
>> Stephen & Tomeu, let me know if I got any of that wrong.
>
> I think you got it right, just wanted to mention that we can and
> probably should make the clk_get_parent_* calls in the consumer API to
> return per-user clk instances but that we need to make sure first that
> callers call clk_put afterwards.
>
> This should also allow us to remove the reference to struct clk from
> clk_hw, which is at best awkward.
>
> Regards,

For the DPLL code it should just be fine to be able to get the current 
parent index (not parent clock handle), and read a parent clock rate 
based on an arbitrary index (not just the current one.) I don't think 
there is any other need for having the clk_ref / clk_bypass clock 
handles around.

-Tero

>
> Tomeu
>
>>>
>>> Shall I change the DPLL code to check against clk_hw pointers or what is
>>> the preferred approach here? The patch at the end does this and fixes
>>> the dpll related warnings.
>>
>> Yes, for now that is fine, but feels a bit hacky to me. I don't know
>> honestly, let me sleep on it. Anyways for 3.20 that is perfectly fine
>> but we might want to switch to something like the scheme above.
>>
>>>
>>> Btw, the rate constraints patch broke boot for me completely, but sounds
>>> like you reverted it already.
>>
>> Fixed with Stephen's patch from last week. Thanks for dealing with all
>> the breakage so promptly. It has helped a lot!
>>
>> Regards,
>> Mike
>>
>>>
>>> -Tero
>>>
>>> --------------------
>>>
>>> Author: Tero Kristo <t-kristo@ti.com>
>>> Date:   Mon Feb 2 17:19:17 2015 +0200
>>>
>>>       ARM: OMAP3+: clock: dpll: fix logic for comparing parent clocks
>>>
>>>       DPLL code uses reference and bypass clock pointers for determining
>>> runtime
>>>       properties for these clocks, like parent clock rates.
>>>
>>>       As clock API now returns per-user clock structs, using a global handle
>>>       in the clock driver code does not work properly anymore. Fix this by
>>>       using the clk_hw instead, and comparing this against the parents.
>>>
>>>       Signed-off-by: Tero Kristo <t-kristo@ti.com>
>>>       Fixes: 59cf3fcf9baf ("clk: Make clk API return per-user struct clk
>>> instances")
>>>
>>> diff --git a/arch/arm/mach-omap2/dpll3xxx.c b/arch/arm/mach-omap2/dpll3xxx.c
>>> index c2da2a0..49752d7 100644
>>> --- a/arch/arm/mach-omap2/dpll3xxx.c
>>> +++ b/arch/arm/mach-omap2/dpll3xxx.c
>>> @@ -410,7 +410,7 @@ int omap3_noncore_dpll_enable(struct clk_hw *hw)
>>>          struct clk_hw_omap *clk = to_clk_hw_omap(hw);
>>>          int r;
>>>          struct dpll_data *dd;
>>> -       struct clk *parent;
>>> +       struct clk_hw *parent;
>>>
>>>          dd = clk->dpll_data;
>>>          if (!dd)
>>> @@ -427,13 +427,13 @@ int omap3_noncore_dpll_enable(struct clk_hw *hw)
>>>                  }
>>>          }
>>>
>>> -       parent = __clk_get_parent(hw->clk);
>>> +       parent = __clk_get_hw(__clk_get_parent(hw->clk));
>>>
>>>          if (__clk_get_rate(hw->clk) == __clk_get_rate(dd->clk_bypass)) {
>>> -               WARN_ON(parent != dd->clk_bypass);
>>> +               WARN_ON(parent != __clk_get_hw(dd->clk_bypass));
>>>                  r = _omap3_noncore_dpll_bypass(clk);
>>>          } else {
>>> -               WARN_ON(parent != dd->clk_ref);
>>> +               WARN_ON(parent != __clk_get_hw(dd->clk_ref));
>>>                  r = _omap3_noncore_dpll_lock(clk);
>>>          }
>>>
>>> @@ -549,7 +549,8 @@ int omap3_noncore_dpll_set_rate(struct clk_hw *hw,
>>> unsigned long rate,
>>>          if (!dd)
>>>                  return -EINVAL;
>>>
>>> -       if (__clk_get_parent(hw->clk) != dd->clk_ref)
>>> +       if (__clk_get_hw(__clk_get_parent(hw->clk)) !=
>>> +           __clk_get_hw(dd->clk_ref))
>>>                  return -EINVAL;
>>>
>>>          if (dd->last_rounded_rate == 0)
>>>
>>>
>


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

* [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
@ 2015-02-03  8:46             ` Tero Kristo
  0 siblings, 0 replies; 186+ messages in thread
From: Tero Kristo @ 2015-02-03  8:46 UTC (permalink / raw)
  To: linux-arm-kernel

On 02/03/2015 09:03 AM, Tomeu Vizoso wrote:
> On 02/02/2015 11:41 PM, Mike Turquette wrote:
>> Quoting Tero Kristo (2015-02-02 11:32:01)
>>> On 02/01/2015 11:24 PM, Mike Turquette wrote:
>>>> Quoting Tomeu Vizoso (2015-01-23 03:03:30)
>>>>> Moves clock state to struct clk_core, but takes care to change as little API as
>>>>> possible.
>>>>>
>>>>> struct clk_hw still has a pointer to a struct clk, which is the
>>>>> implementation's per-user clk instance, for backwards compatibility.
>>>>>
>>>>> The struct clk that clk_get_parent() returns isn't owned by the caller, but by
>>>>> the clock implementation, so the former shouldn't call clk_put() on it.
>>>>>
>>>>> Because some boards in mach-omap2 still register clocks statically, their clock
>>>>> registration had to be updated to take into account that the clock information
>>>>> is stored in struct clk_core now.
>>>>
>>>> Tero, Paul & Tony,
>>>>
>>>> Tomeu's patch unveils a problem with omap3_noncore_dpll_enable and
>>>> struct dpll_data, namely this snippet from
>>>> arch/arm/mach-omap2/dpll3xxx.c:
>>>>
>>>>           parent = __clk_get_parent(hw->clk);
>>>>
>>>>           if (__clk_get_rate(hw->clk) == __clk_get_rate(dd->clk_bypass)) {
>>>>                   WARN(parent != dd->clk_bypass,
>>>>                                   "here0, parent name is %s, bypass name is %s\n",
>>>>                                   __clk_get_name(parent), __clk_get_name(dd->clk_bypass));
>>>>                   r = _omap3_noncore_dpll_bypass(clk);
>>>>           } else {
>>>>                   WARN(parent != dd->clk_ref,
>>>>                                   "here1, parent name is %s, ref name is %s\n",
>>>>                                   __clk_get_name(parent), __clk_get_name(dd->clk_ref));
>>>>                   r = _omap3_noncore_dpll_lock(clk);
>>>>           }
>>>>
>>>> struct dpll_data has members clk_ref and clk_bypass which are struct clk
>>>> pointers. This was always a bit of a violation of the clk.h contract
>>>> since drivers are not supposed to deref struct clk pointers. Now that we
>>>> generate unique pointers for each call to clk_get (clk_ref & clk_bypass
>>>> are populated by of_clk_get in ti_clk_register_dpll) then the pointer
>>>> comparisons above will never be equal (even if they resolve down to the
>>>> same struct clk_core). I added the verbose traces to the WARNs above to
>>>> illustrate the point: the names are always the same but the pointers
>>>> differ.
>>>>
>>>> AFAICT this doesn't break anything, but booting on OMAP3+ results in
>>>> noisy WARNs.
>>>>
>>>> I think the correct fix is to replace clk_bypass and clk_ref pointers
>>>> with a simple integer parent_index. In fact we already have this index.
>>>> See how the pointers are populated in ti_clk_register_dpll:
>>>
>>> The problem is we still need to be able to get runtime parent clock
>>> rates (the parent rate may change also), so simple index value is not
>>> sufficient. We need a handle of some sort to the bypass/ref clocks. The
>>> DPLL code generally requires knowledge of the bypass + reference clock
>>> rates to work properly, as it calculates the M/N values based on these.
>>
>> We can maybe introduce something like of_clk_get_parent_rate, as we have
>> analogous stuff for getting parent names and indexes. Without
>> introducing a new helper you could probably just do:
>>
>> 	clk_ref = clk_get_parent_by_index(dpll_clk, 0);
>> 	ref_rate = clk_get_rate(clk_ref);
>>
>> 	clk_bypass = clk_get_parent_by_index(dpll_clk, 1);
>> 	bypass_rate = clk_get_rate(clk_bypass);
>>
>> Currently the semantics around this call are weird. It seems like it
>> would create a new struct clk pointer but it does not. So don't call
>> clk_put on clk_ref and clk_bypass yet. That might change in the future
>> as we iron out this brave new world that we all live in. Probably best
>> to leave a FIXME in there.
>>
>> Stephen & Tomeu, let me know if I got any of that wrong.
>
> I think you got it right, just wanted to mention that we can and
> probably should make the clk_get_parent_* calls in the consumer API to
> return per-user clk instances but that we need to make sure first that
> callers call clk_put afterwards.
>
> This should also allow us to remove the reference to struct clk from
> clk_hw, which is at best awkward.
>
> Regards,

For the DPLL code it should just be fine to be able to get the current 
parent index (not parent clock handle), and read a parent clock rate 
based on an arbitrary index (not just the current one.) I don't think 
there is any other need for having the clk_ref / clk_bypass clock 
handles around.

-Tero

>
> Tomeu
>
>>>
>>> Shall I change the DPLL code to check against clk_hw pointers or what is
>>> the preferred approach here? The patch at the end does this and fixes
>>> the dpll related warnings.
>>
>> Yes, for now that is fine, but feels a bit hacky to me. I don't know
>> honestly, let me sleep on it. Anyways for 3.20 that is perfectly fine
>> but we might want to switch to something like the scheme above.
>>
>>>
>>> Btw, the rate constraints patch broke boot for me completely, but sounds
>>> like you reverted it already.
>>
>> Fixed with Stephen's patch from last week. Thanks for dealing with all
>> the breakage so promptly. It has helped a lot!
>>
>> Regards,
>> Mike
>>
>>>
>>> -Tero
>>>
>>> --------------------
>>>
>>> Author: Tero Kristo <t-kristo@ti.com>
>>> Date:   Mon Feb 2 17:19:17 2015 +0200
>>>
>>>       ARM: OMAP3+: clock: dpll: fix logic for comparing parent clocks
>>>
>>>       DPLL code uses reference and bypass clock pointers for determining
>>> runtime
>>>       properties for these clocks, like parent clock rates.
>>>
>>>       As clock API now returns per-user clock structs, using a global handle
>>>       in the clock driver code does not work properly anymore. Fix this by
>>>       using the clk_hw instead, and comparing this against the parents.
>>>
>>>       Signed-off-by: Tero Kristo <t-kristo@ti.com>
>>>       Fixes: 59cf3fcf9baf ("clk: Make clk API return per-user struct clk
>>> instances")
>>>
>>> diff --git a/arch/arm/mach-omap2/dpll3xxx.c b/arch/arm/mach-omap2/dpll3xxx.c
>>> index c2da2a0..49752d7 100644
>>> --- a/arch/arm/mach-omap2/dpll3xxx.c
>>> +++ b/arch/arm/mach-omap2/dpll3xxx.c
>>> @@ -410,7 +410,7 @@ int omap3_noncore_dpll_enable(struct clk_hw *hw)
>>>          struct clk_hw_omap *clk = to_clk_hw_omap(hw);
>>>          int r;
>>>          struct dpll_data *dd;
>>> -       struct clk *parent;
>>> +       struct clk_hw *parent;
>>>
>>>          dd = clk->dpll_data;
>>>          if (!dd)
>>> @@ -427,13 +427,13 @@ int omap3_noncore_dpll_enable(struct clk_hw *hw)
>>>                  }
>>>          }
>>>
>>> -       parent = __clk_get_parent(hw->clk);
>>> +       parent = __clk_get_hw(__clk_get_parent(hw->clk));
>>>
>>>          if (__clk_get_rate(hw->clk) == __clk_get_rate(dd->clk_bypass)) {
>>> -               WARN_ON(parent != dd->clk_bypass);
>>> +               WARN_ON(parent != __clk_get_hw(dd->clk_bypass));
>>>                  r = _omap3_noncore_dpll_bypass(clk);
>>>          } else {
>>> -               WARN_ON(parent != dd->clk_ref);
>>> +               WARN_ON(parent != __clk_get_hw(dd->clk_ref));
>>>                  r = _omap3_noncore_dpll_lock(clk);
>>>          }
>>>
>>> @@ -549,7 +549,8 @@ int omap3_noncore_dpll_set_rate(struct clk_hw *hw,
>>> unsigned long rate,
>>>          if (!dd)
>>>                  return -EINVAL;
>>>
>>> -       if (__clk_get_parent(hw->clk) != dd->clk_ref)
>>> +       if (__clk_get_hw(__clk_get_parent(hw->clk)) !=
>>> +           __clk_get_hw(dd->clk_ref))
>>>                  return -EINVAL;
>>>
>>>          if (dd->last_rounded_rate == 0)
>>>
>>>
>

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

* Re: [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
  2015-02-03  8:46             ` Tero Kristo
@ 2015-02-03 15:22               ` Tony Lindgren
  -1 siblings, 0 replies; 186+ messages in thread
From: Tony Lindgren @ 2015-02-03 15:22 UTC (permalink / raw)
  To: Tero Kristo
  Cc: Tomeu Vizoso, Mike Turquette, linux-kernel, Stephen Boyd,
	Paul Walmsley, linux-omap, linux-arm-kernel

* Tero Kristo <t-kristo@ti.com> [150203 00:49]:
> On 02/03/2015 09:03 AM, Tomeu Vizoso wrote:
> >
> >I think you got it right, just wanted to mention that we can and
> >probably should make the clk_get_parent_* calls in the consumer API to
> >return per-user clk instances but that we need to make sure first that
> >callers call clk_put afterwards.
> >
> >This should also allow us to remove the reference to struct clk from
> >clk_hw, which is at best awkward.
> 
> For the DPLL code it should just be fine to be able to get the current
> parent index (not parent clock handle), and read a parent clock rate based
> on an arbitrary index (not just the current one.) I don't think there is any
> other need for having the clk_ref / clk_bypass clock handles around.

I'd like to avoid the situation where the children have know that
certain parent index and parent rate means bypass mode for both
parent and children. 

Maybe we can hide that knowledge into some Linux generic PLL code so
the children can get the PLL output as a mux clock. For a PLL, there
can be three mux clock outputs: refclk*multi/div, bypass clock, or no
output.

Regards,

Tony

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

* [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
@ 2015-02-03 15:22               ` Tony Lindgren
  0 siblings, 0 replies; 186+ messages in thread
From: Tony Lindgren @ 2015-02-03 15:22 UTC (permalink / raw)
  To: linux-arm-kernel

* Tero Kristo <t-kristo@ti.com> [150203 00:49]:
> On 02/03/2015 09:03 AM, Tomeu Vizoso wrote:
> >
> >I think you got it right, just wanted to mention that we can and
> >probably should make the clk_get_parent_* calls in the consumer API to
> >return per-user clk instances but that we need to make sure first that
> >callers call clk_put afterwards.
> >
> >This should also allow us to remove the reference to struct clk from
> >clk_hw, which is at best awkward.
> 
> For the DPLL code it should just be fine to be able to get the current
> parent index (not parent clock handle), and read a parent clock rate based
> on an arbitrary index (not just the current one.) I don't think there is any
> other need for having the clk_ref / clk_bypass clock handles around.

I'd like to avoid the situation where the children have know that
certain parent index and parent rate means bypass mode for both
parent and children. 

Maybe we can hide that knowledge into some Linux generic PLL code so
the children can get the PLL output as a mux clock. For a PLL, there
can be three mux clock outputs: refclk*multi/div, bypass clock, or no
output.

Regards,

Tony

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

* Re: [Cocci] [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
  2015-02-02 22:50             ` [Cocci] " Mike Turquette
  (?)
@ 2015-02-03 16:04               ` Quentin Lambert
  -1 siblings, 0 replies; 186+ messages in thread
From: Quentin Lambert @ 2015-02-03 16:04 UTC (permalink / raw)
  To: Mike Turquette, Stephen Boyd, Julia Lawall
  Cc: Paul Walmsley, Tomeu Vizoso, Tony Lindgren, linux-kernel,
	t-kristo, linux-omap, cocci, linux-arm-kernel

Hello,
Julia asked me to have a look and see if I can help.

On 02/02/2015 23:50, Mike Turquette wrote:
> Quoting Stephen Boyd (2015-02-02 14:35:59)
>> On 02/02/15 13:31, Julia Lawall wrote:
>>> On Mon, 2 Feb 2015, Stephen Boyd wrote:
>>>
>>>> Julia,
>>>>
>>>> Is there a way we can write a coccinelle script to check for this? The
>>>> goal being to find all drivers that are comparing struct clk pointers or
>>>> attempting to dereference them. There are probably other frameworks that
>>>> could use the same type of check (regulator, gpiod, reset, pwm, etc.).
>>>> Probably anything that has a get/put API.
>>> Comparing or dereferencing pointers of a particular type should be
>>> straightforward to check for.  Is there an example of how to use the
>>> parent_index value to fix the problem?
>>>
>> I'm not sure how to fix this case with parent_index values generically.
>> I imagine it would be highly specific to the surrounding code to the
>> point where we couldn't fix it automatically. For example, if it's a clk
>> consumer (not provider like in this case) using an index wouldn't be the
>> right fix. We would need some sort of clk API that we don't currently
>> have and I would wonder why clock consumers even care to compare such
>> pointers in the first place.
> Ack. Is there precedent for a "Don't do that" kind of response?
>
> Regards,
> Mike
>
>> -- 
>> Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
>> a Linux Foundation Collaborative Project
>>
> _______________________________________________
> Cocci mailing list
> Cocci@systeme.lip6.fr
> https://systeme.lip6.fr/mailman/listinfo/cocci
I have found these three cases using Coccinnelle in the mach-omap2
directory.



./arch/arm/mach-omap2/clkt_clksel.c
@@ -67,7 +67,6 @@ static const struct clksel *_get_clksel_
                 return NULL;

         for (clks = clk->clksel; clks->parent; clks++)
                 if (clks->parent == src_clk)
                         break; /* Found the requested parent */

         if (!clks->parent) {
./arch/arm/mach-omap2/dpll3xxx.c
@@ -551,7 +549,6 @@ int omap3_noncore_dpll_set_rate(struct c
         if (!dd)
                 return -EINVAL;

         if (__clk_get_parent(hw->clk) != dd->clk_ref)
                 return -EINVAL;

         if (dd->last_rounded_rate == 0)
./arch/arm/mach-omap2/timer.c
@@ -298,7 +298,6 @@ static int __init omap_dm_timer_init_one
         if (IS_ERR(src))
                 return PTR_ERR(src);

         if (clk_get_parent(timer->fclk) != src) {
                 r = clk_set_parent(timer->fclk, src);
                 if (r < 0) {
                         pr_warn("%s: %s cannot set source\n", __func__,


Are they instances of your issue?
Do you have any suggestion on how to fix them?
If you want me to I can enlarge the search to other directories.


Quentin

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

* [Cocci] [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
@ 2015-02-03 16:04               ` Quentin Lambert
  0 siblings, 0 replies; 186+ messages in thread
From: Quentin Lambert @ 2015-02-03 16:04 UTC (permalink / raw)
  To: cocci

Hello,
Julia asked me to have a look and see if I can help.

On 02/02/2015 23:50, Mike Turquette wrote:
> Quoting Stephen Boyd (2015-02-02 14:35:59)
>> On 02/02/15 13:31, Julia Lawall wrote:
>>> On Mon, 2 Feb 2015, Stephen Boyd wrote:
>>>
>>>> Julia,
>>>>
>>>> Is there a way we can write a coccinelle script to check for this? The
>>>> goal being to find all drivers that are comparing struct clk pointers or
>>>> attempting to dereference them. There are probably other frameworks that
>>>> could use the same type of check (regulator, gpiod, reset, pwm, etc.).
>>>> Probably anything that has a get/put API.
>>> Comparing or dereferencing pointers of a particular type should be
>>> straightforward to check for.  Is there an example of how to use the
>>> parent_index value to fix the problem?
>>>
>> I'm not sure how to fix this case with parent_index values generically.
>> I imagine it would be highly specific to the surrounding code to the
>> point where we couldn't fix it automatically. For example, if it's a clk
>> consumer (not provider like in this case) using an index wouldn't be the
>> right fix. We would need some sort of clk API that we don't currently
>> have and I would wonder why clock consumers even care to compare such
>> pointers in the first place.
> Ack. Is there precedent for a "Don't do that" kind of response?
>
> Regards,
> Mike
>
>> -- 
>> Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
>> a Linux Foundation Collaborative Project
>>
> _______________________________________________
> Cocci mailing list
> Cocci at systeme.lip6.fr
> https://systeme.lip6.fr/mailman/listinfo/cocci
I have found these three cases using Coccinnelle in the mach-omap2
directory.



./arch/arm/mach-omap2/clkt_clksel.c
@@ -67,7 +67,6 @@ static const struct clksel *_get_clksel_
                 return NULL;

         for (clks = clk->clksel; clks->parent; clks++)
                 if (clks->parent == src_clk)
                         break; /* Found the requested parent */

         if (!clks->parent) {
./arch/arm/mach-omap2/dpll3xxx.c
@@ -551,7 +549,6 @@ int omap3_noncore_dpll_set_rate(struct c
         if (!dd)
                 return -EINVAL;

         if (__clk_get_parent(hw->clk) != dd->clk_ref)
                 return -EINVAL;

         if (dd->last_rounded_rate == 0)
./arch/arm/mach-omap2/timer.c
@@ -298,7 +298,6 @@ static int __init omap_dm_timer_init_one
         if (IS_ERR(src))
                 return PTR_ERR(src);

         if (clk_get_parent(timer->fclk) != src) {
                 r = clk_set_parent(timer->fclk, src);
                 if (r < 0) {
                         pr_warn("%s: %s cannot set source\n", __func__,


Are they instances of your issue?
Do you have any suggestion on how to fix them?
If you want me to I can enlarge the search to other directories.


Quentin

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

* [Cocci] [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
@ 2015-02-03 16:04               ` Quentin Lambert
  0 siblings, 0 replies; 186+ messages in thread
From: Quentin Lambert @ 2015-02-03 16:04 UTC (permalink / raw)
  To: linux-arm-kernel

Hello,
Julia asked me to have a look and see if I can help.

On 02/02/2015 23:50, Mike Turquette wrote:
> Quoting Stephen Boyd (2015-02-02 14:35:59)
>> On 02/02/15 13:31, Julia Lawall wrote:
>>> On Mon, 2 Feb 2015, Stephen Boyd wrote:
>>>
>>>> Julia,
>>>>
>>>> Is there a way we can write a coccinelle script to check for this? The
>>>> goal being to find all drivers that are comparing struct clk pointers or
>>>> attempting to dereference them. There are probably other frameworks that
>>>> could use the same type of check (regulator, gpiod, reset, pwm, etc.).
>>>> Probably anything that has a get/put API.
>>> Comparing or dereferencing pointers of a particular type should be
>>> straightforward to check for.  Is there an example of how to use the
>>> parent_index value to fix the problem?
>>>
>> I'm not sure how to fix this case with parent_index values generically.
>> I imagine it would be highly specific to the surrounding code to the
>> point where we couldn't fix it automatically. For example, if it's a clk
>> consumer (not provider like in this case) using an index wouldn't be the
>> right fix. We would need some sort of clk API that we don't currently
>> have and I would wonder why clock consumers even care to compare such
>> pointers in the first place.
> Ack. Is there precedent for a "Don't do that" kind of response?
>
> Regards,
> Mike
>
>> -- 
>> Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
>> a Linux Foundation Collaborative Project
>>
> _______________________________________________
> Cocci mailing list
> Cocci at systeme.lip6.fr
> https://systeme.lip6.fr/mailman/listinfo/cocci
I have found these three cases using Coccinnelle in the mach-omap2
directory.



./arch/arm/mach-omap2/clkt_clksel.c
@@ -67,7 +67,6 @@ static const struct clksel *_get_clksel_
                 return NULL;

         for (clks = clk->clksel; clks->parent; clks++)
                 if (clks->parent == src_clk)
                         break; /* Found the requested parent */

         if (!clks->parent) {
./arch/arm/mach-omap2/dpll3xxx.c
@@ -551,7 +549,6 @@ int omap3_noncore_dpll_set_rate(struct c
         if (!dd)
                 return -EINVAL;

         if (__clk_get_parent(hw->clk) != dd->clk_ref)
                 return -EINVAL;

         if (dd->last_rounded_rate == 0)
./arch/arm/mach-omap2/timer.c
@@ -298,7 +298,6 @@ static int __init omap_dm_timer_init_one
         if (IS_ERR(src))
                 return PTR_ERR(src);

         if (clk_get_parent(timer->fclk) != src) {
                 r = clk_set_parent(timer->fclk, src);
                 if (r < 0) {
                         pr_warn("%s: %s cannot set source\n", __func__,


Are they instances of your issue?
Do you have any suggestion on how to fix them?
If you want me to I can enlarge the search to other directories.


Quentin

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

* Re: [PATCH v13 5/6] clkdev: Export clk_register_clkdev
  2015-01-23 11:03   ` Tomeu Vizoso
@ 2015-02-03 17:35     ` Andy Shevchenko
  -1 siblings, 0 replies; 186+ messages in thread
From: Andy Shevchenko @ 2015-02-03 17:35 UTC (permalink / raw)
  To: Tomeu Vizoso
  Cc: linux-kernel, Mike Turquette, Stephen Boyd,
	Javier Martinez Canillas, Russell King, linux-arm Mailing List

On Fri, Jan 23, 2015 at 1:03 PM, Tomeu Vizoso
<tomeu.vizoso@collabora.com> wrote:
> So it can be used from modules such as clk-test.ko.
>
> Signed-off-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
> Reviewed-by: Stephen Boyd <sboyd@codeaurora.org>

Sorry for late answer, but this is useless.

We have to provide the way how to get the allocated clk_lookup.
Otherwise you have no way but memory leak at the ->remove() stage.

(By the way I used to have the exact patch locally, that's why
discovered the change in upsteam)

> ---
>  drivers/clk/clkdev.c | 1 +
>  1 file changed, 1 insertion(+)
>
> diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c
> index 901d242..29a1ab7 100644
> --- a/drivers/clk/clkdev.c
> +++ b/drivers/clk/clkdev.c
> @@ -377,6 +377,7 @@ int clk_register_clkdev(struct clk *clk, const char *con_id,
>
>         return 0;
>  }
> +EXPORT_SYMBOL(clk_register_clkdev);
>
>  /**
>   * clk_register_clkdevs - register a set of clk_lookup for a struct clk
> --
> 1.9.3
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/



-- 
With Best Regards,
Andy Shevchenko

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

* [PATCH v13 5/6] clkdev: Export clk_register_clkdev
@ 2015-02-03 17:35     ` Andy Shevchenko
  0 siblings, 0 replies; 186+ messages in thread
From: Andy Shevchenko @ 2015-02-03 17:35 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Jan 23, 2015 at 1:03 PM, Tomeu Vizoso
<tomeu.vizoso@collabora.com> wrote:
> So it can be used from modules such as clk-test.ko.
>
> Signed-off-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
> Reviewed-by: Stephen Boyd <sboyd@codeaurora.org>

Sorry for late answer, but this is useless.

We have to provide the way how to get the allocated clk_lookup.
Otherwise you have no way but memory leak at the ->remove() stage.

(By the way I used to have the exact patch locally, that's why
discovered the change in upsteam)

> ---
>  drivers/clk/clkdev.c | 1 +
>  1 file changed, 1 insertion(+)
>
> diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c
> index 901d242..29a1ab7 100644
> --- a/drivers/clk/clkdev.c
> +++ b/drivers/clk/clkdev.c
> @@ -377,6 +377,7 @@ int clk_register_clkdev(struct clk *clk, const char *con_id,
>
>         return 0;
>  }
> +EXPORT_SYMBOL(clk_register_clkdev);
>
>  /**
>   * clk_register_clkdevs - register a set of clk_lookup for a struct clk
> --
> 1.9.3
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/



-- 
With Best Regards,
Andy Shevchenko

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

* Re: [PATCH v13 5/6] clkdev: Export clk_register_clkdev
  2015-02-03 17:35     ` Andy Shevchenko
@ 2015-02-03 17:43       ` Andy Shevchenko
  -1 siblings, 0 replies; 186+ messages in thread
From: Andy Shevchenko @ 2015-02-03 17:43 UTC (permalink / raw)
  To: Tomeu Vizoso
  Cc: linux-kernel, Mike Turquette, Stephen Boyd,
	Javier Martinez Canillas, Russell King, linux-arm Mailing List

On Tue, Feb 3, 2015 at 7:35 PM, Andy Shevchenko
<andy.shevchenko@gmail.com> wrote:
> On Fri, Jan 23, 2015 at 1:03 PM, Tomeu Vizoso
> <tomeu.vizoso@collabora.com> wrote:
>> So it can be used from modules such as clk-test.ko.
>>
>> Signed-off-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
>> Reviewed-by: Stephen Boyd <sboyd@codeaurora.org>
>
> Sorry for late answer, but this is useless.
>
> We have to provide the way how to get the allocated clk_lookup.
> Otherwise you have no way but memory leak at the ->remove() stage.
>
> (By the way I used to have the exact patch locally, that's why
> discovered the change in upsteam)
>

Will send a patch soon to fix this.

>> ---
>>  drivers/clk/clkdev.c | 1 +
>>  1 file changed, 1 insertion(+)
>>
>> diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c
>> index 901d242..29a1ab7 100644
>> --- a/drivers/clk/clkdev.c
>> +++ b/drivers/clk/clkdev.c
>> @@ -377,6 +377,7 @@ int clk_register_clkdev(struct clk *clk, const char *con_id,
>>
>>         return 0;
>>  }
>> +EXPORT_SYMBOL(clk_register_clkdev);
>>
>>  /**
>>   * clk_register_clkdevs - register a set of clk_lookup for a struct clk
>> --
>> 1.9.3
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>> Please read the FAQ at  http://www.tux.org/lkml/
>
>
>
> --
> With Best Regards,
> Andy Shevchenko



-- 
With Best Regards,
Andy Shevchenko

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

* [PATCH v13 5/6] clkdev: Export clk_register_clkdev
@ 2015-02-03 17:43       ` Andy Shevchenko
  0 siblings, 0 replies; 186+ messages in thread
From: Andy Shevchenko @ 2015-02-03 17:43 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Feb 3, 2015 at 7:35 PM, Andy Shevchenko
<andy.shevchenko@gmail.com> wrote:
> On Fri, Jan 23, 2015 at 1:03 PM, Tomeu Vizoso
> <tomeu.vizoso@collabora.com> wrote:
>> So it can be used from modules such as clk-test.ko.
>>
>> Signed-off-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
>> Reviewed-by: Stephen Boyd <sboyd@codeaurora.org>
>
> Sorry for late answer, but this is useless.
>
> We have to provide the way how to get the allocated clk_lookup.
> Otherwise you have no way but memory leak at the ->remove() stage.
>
> (By the way I used to have the exact patch locally, that's why
> discovered the change in upsteam)
>

Will send a patch soon to fix this.

>> ---
>>  drivers/clk/clkdev.c | 1 +
>>  1 file changed, 1 insertion(+)
>>
>> diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c
>> index 901d242..29a1ab7 100644
>> --- a/drivers/clk/clkdev.c
>> +++ b/drivers/clk/clkdev.c
>> @@ -377,6 +377,7 @@ int clk_register_clkdev(struct clk *clk, const char *con_id,
>>
>>         return 0;
>>  }
>> +EXPORT_SYMBOL(clk_register_clkdev);
>>
>>  /**
>>   * clk_register_clkdevs - register a set of clk_lookup for a struct clk
>> --
>> 1.9.3
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
>> the body of a message to majordomo at vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>> Please read the FAQ at  http://www.tux.org/lkml/
>
>
>
> --
> With Best Regards,
> Andy Shevchenko



-- 
With Best Regards,
Andy Shevchenko

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

* Re: [Cocci] [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
  2015-02-03 16:04               ` Quentin Lambert
  (?)
@ 2015-02-04 23:26                 ` Stephen Boyd
  -1 siblings, 0 replies; 186+ messages in thread
From: Stephen Boyd @ 2015-02-04 23:26 UTC (permalink / raw)
  To: Quentin Lambert, Mike Turquette, Julia Lawall
  Cc: Paul Walmsley, Tomeu Vizoso, Tony Lindgren, linux-kernel,
	t-kristo, linux-omap, cocci, linux-arm-kernel

On 02/03/15 08:04, Quentin Lambert wrote:
> Hello,
> Julia asked me to have a look and see if I can help.
>
> I have found these three cases using Coccinnelle in the mach-omap2
> directory.
>
>
>
> ./arch/arm/mach-omap2/clkt_clksel.c
> @@ -67,7 +67,6 @@ static const struct clksel *_get_clksel_
>                 return NULL;
>
>         for (clks = clk->clksel; clks->parent; clks++)
>                 if (clks->parent == src_clk)

This probably needs to compare hw pointers again given that it's in the
clk-provider code. It would be nice if we could use indices instead though.

>                         break; /* Found the requested parent */
>
>         if (!clks->parent) {
> ./arch/arm/mach-omap2/dpll3xxx.c
> @@ -551,7 +549,6 @@ int omap3_noncore_dpll_set_rate(struct c
>         if (!dd)
>                 return -EINVAL;
>
>         if (__clk_get_parent(hw->clk) != dd->clk_ref)

This one is what this thread has started on about. Comparing hw pointers
is ok for now...

>                 return -EINVAL;
>
>         if (dd->last_rounded_rate == 0)
> ./arch/arm/mach-omap2/timer.c
> @@ -298,7 +298,6 @@ static int __init omap_dm_timer_init_one
>         if (IS_ERR(src))
>                 return PTR_ERR(src);
>
>         if (clk_get_parent(timer->fclk) != src) {

This one looks like an optimization. We can just always try to set the
parent and if it's already the current parent then the core should bail
out early without an error. So the fix would be to just remove the if
condition.

>                 r = clk_set_parent(timer->fclk, src);
>                 if (r < 0) {
>                         pr_warn("%s: %s cannot set source\n", __func__,
>
>
> Are they instances of your issue?

Yes these all look like instances of the problem.

> If you want me to I can enlarge the search to other directories.

Yes please do. And if you could share the coccinelle patch that would be
great. Thanks.

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


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

* [Cocci] [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
@ 2015-02-04 23:26                 ` Stephen Boyd
  0 siblings, 0 replies; 186+ messages in thread
From: Stephen Boyd @ 2015-02-04 23:26 UTC (permalink / raw)
  To: cocci

On 02/03/15 08:04, Quentin Lambert wrote:
> Hello,
> Julia asked me to have a look and see if I can help.
>
> I have found these three cases using Coccinnelle in the mach-omap2
> directory.
>
>
>
> ./arch/arm/mach-omap2/clkt_clksel.c
> @@ -67,7 +67,6 @@ static const struct clksel *_get_clksel_
>                 return NULL;
>
>         for (clks = clk->clksel; clks->parent; clks++)
>                 if (clks->parent == src_clk)

This probably needs to compare hw pointers again given that it's in the
clk-provider code. It would be nice if we could use indices instead though.

>                         break; /* Found the requested parent */
>
>         if (!clks->parent) {
> ./arch/arm/mach-omap2/dpll3xxx.c
> @@ -551,7 +549,6 @@ int omap3_noncore_dpll_set_rate(struct c
>         if (!dd)
>                 return -EINVAL;
>
>         if (__clk_get_parent(hw->clk) != dd->clk_ref)

This one is what this thread has started on about. Comparing hw pointers
is ok for now...

>                 return -EINVAL;
>
>         if (dd->last_rounded_rate == 0)
> ./arch/arm/mach-omap2/timer.c
> @@ -298,7 +298,6 @@ static int __init omap_dm_timer_init_one
>         if (IS_ERR(src))
>                 return PTR_ERR(src);
>
>         if (clk_get_parent(timer->fclk) != src) {

This one looks like an optimization. We can just always try to set the
parent and if it's already the current parent then the core should bail
out early without an error. So the fix would be to just remove the if
condition.

>                 r = clk_set_parent(timer->fclk, src);
>                 if (r < 0) {
>                         pr_warn("%s: %s cannot set source\n", __func__,
>
>
> Are they instances of your issue?

Yes these all look like instances of the problem.

> If you want me to I can enlarge the search to other directories.

Yes please do. And if you could share the coccinelle patch that would be
great. Thanks.

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

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

* [Cocci] [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
@ 2015-02-04 23:26                 ` Stephen Boyd
  0 siblings, 0 replies; 186+ messages in thread
From: Stephen Boyd @ 2015-02-04 23:26 UTC (permalink / raw)
  To: linux-arm-kernel

On 02/03/15 08:04, Quentin Lambert wrote:
> Hello,
> Julia asked me to have a look and see if I can help.
>
> I have found these three cases using Coccinnelle in the mach-omap2
> directory.
>
>
>
> ./arch/arm/mach-omap2/clkt_clksel.c
> @@ -67,7 +67,6 @@ static const struct clksel *_get_clksel_
>                 return NULL;
>
>         for (clks = clk->clksel; clks->parent; clks++)
>                 if (clks->parent == src_clk)

This probably needs to compare hw pointers again given that it's in the
clk-provider code. It would be nice if we could use indices instead though.

>                         break; /* Found the requested parent */
>
>         if (!clks->parent) {
> ./arch/arm/mach-omap2/dpll3xxx.c
> @@ -551,7 +549,6 @@ int omap3_noncore_dpll_set_rate(struct c
>         if (!dd)
>                 return -EINVAL;
>
>         if (__clk_get_parent(hw->clk) != dd->clk_ref)

This one is what this thread has started on about. Comparing hw pointers
is ok for now...

>                 return -EINVAL;
>
>         if (dd->last_rounded_rate == 0)
> ./arch/arm/mach-omap2/timer.c
> @@ -298,7 +298,6 @@ static int __init omap_dm_timer_init_one
>         if (IS_ERR(src))
>                 return PTR_ERR(src);
>
>         if (clk_get_parent(timer->fclk) != src) {

This one looks like an optimization. We can just always try to set the
parent and if it's already the current parent then the core should bail
out early without an error. So the fix would be to just remove the if
condition.

>                 r = clk_set_parent(timer->fclk, src);
>                 if (r < 0) {
>                         pr_warn("%s: %s cannot set source\n", __func__,
>
>
> Are they instances of your issue?

Yes these all look like instances of the problem.

> If you want me to I can enlarge the search to other directories.

Yes please do. And if you could share the coccinelle patch that would be
great. Thanks.

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

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

* Re: [Cocci] [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
  2015-02-04 23:26                 ` Stephen Boyd
  (?)
@ 2015-02-05 15:45                   ` Quentin Lambert
  -1 siblings, 0 replies; 186+ messages in thread
From: Quentin Lambert @ 2015-02-05 15:45 UTC (permalink / raw)
  To: Stephen Boyd, Mike Turquette, Julia Lawall
  Cc: Paul Walmsley, Tomeu Vizoso, Tony Lindgren, linux-kernel,
	t-kristo, linux-omap, cocci, linux-arm-kernel

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


On 05/02/2015 00:26, Stephen Boyd wrote:
>> If you want me to I can enlarge the search to other directories.
> Yes please do. And if you could share the coccinelle patch that would be
> great. Thanks.
>
structclk.cocci is the coccinelle patch
structclk-arm.patch is the result I got when applying it to the arch/arm 
directory

Is there anything else I can do to help?



[-- Attachment #2: structclk-arm.patch --]
[-- Type: text/x-patch, Size: 2512 bytes --]

diff -u -p ./arch/arm/mach-imx/mach-imx6q.c /tmp/nothing/mach-imx/mach-imx6q.c
--- ./arch/arm/mach-imx/mach-imx6q.c
+++ /tmp/nothing/mach-imx/mach-imx6q.c
@@ -211,7 +211,6 @@ static void __init imx6q_1588_init(void)
 	 * set bit IOMUXC_GPR1[21].  Or the PTP clock must be from pad
 	 * (external OSC), and we need to clear the bit.
 	 */
-	clksel = ptp_clk == enet_ref ? IMX6Q_GPR1_ENET_CLK_SEL_ANATOP :
 				       IMX6Q_GPR1_ENET_CLK_SEL_PAD;
 	gpr = syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
 	if (!IS_ERR(gpr))
diff -u -p ./arch/arm/mach-shmobile/clock-r8a73a4.c /tmp/nothing/mach-shmobile/clock-r8a73a4.c
--- ./arch/arm/mach-shmobile/clock-r8a73a4.c
+++ /tmp/nothing/mach-shmobile/clock-r8a73a4.c
@@ -139,7 +139,6 @@ static int pll_set_parent(struct clk *cl
 
 	/* Search the parent */
 	for (i = 0; i < clk->parent_num; i++)
-		if (clk->parent_table[i] == parent)
 			break;
 
 	if (i == clk->parent_num)
diff -u -p ./arch/arm/mach-shmobile/clock-sh7372.c /tmp/nothing/mach-shmobile/clock-sh7372.c
--- ./arch/arm/mach-shmobile/clock-sh7372.c
+++ /tmp/nothing/mach-shmobile/clock-sh7372.c
@@ -223,7 +223,6 @@ static int pllc2_set_parent(struct clk *
 
 	/* Search the parent */
 	for (i = 0; i < clk->parent_num; i++)
-		if (clk->parent_table[i] == parent)
 			break;
 
 	if (i == clk->parent_num)
diff -u -p ./arch/arm/mach-shmobile/clock-r8a7740.c /tmp/nothing/mach-shmobile/clock-r8a7740.c
--- ./arch/arm/mach-shmobile/clock-r8a7740.c
+++ /tmp/nothing/mach-shmobile/clock-r8a7740.c
@@ -195,7 +195,6 @@ static int usb24s_set_parent(struct clk
 
 	/* Search the parent */
 	for (i = 0; i < clk->parent_num; i++)
-		if (clk->parent_table[i] == parent)
 			break;
 
 	if (i == clk->parent_num)
diff -u -p ./arch/arm/mach-omap2/clkt_clksel.c /tmp/nothing/mach-omap2/clkt_clksel.c
--- ./arch/arm/mach-omap2/clkt_clksel.c
+++ /tmp/nothing/mach-omap2/clkt_clksel.c
@@ -67,7 +67,6 @@ static const struct clksel *_get_clksel_
 		return NULL;
 
 	for (clks = clk->clksel; clks->parent; clks++)
-		if (clks->parent == src_clk)
 			break; /* Found the requested parent */
 
 	if (!clks->parent) {
diff -u -p ./arch/arm/mach-omap2/timer.c /tmp/nothing/mach-omap2/timer.c
--- ./arch/arm/mach-omap2/timer.c
+++ /tmp/nothing/mach-omap2/timer.c
@@ -298,7 +298,6 @@ static int __init omap_dm_timer_init_one
 	if (IS_ERR(src))
 		return PTR_ERR(src);
 
-	if (clk_get_parent(timer->fclk) != src) {
 		r = clk_set_parent(timer->fclk, src);
 		if (r < 0) {
 			pr_warn("%s: %s cannot set source\n", __func__,

[-- Attachment #3: structclk.cocci --]
[-- Type: text/plain, Size: 1129 bytes --]

/// Find any attempt to compare or dereference struct clk pointers.
///
// Confidence: High
// Copyright: (C) 2015 Quentin Lambert, INRIA/LiP6. GPLv2
// URL: http://coccinelle.lip6.fr/
// Options: --recursive-includes --relax-include-path
// Options: --include-headers-for-types

virtual context
virtual org
virtual report


// ----------------------------------------------------------------------------

@comparison_dereference depends on context || org || report@
struct clk *x1, x2;
position j0;
@@

(
*  x1@j0 == x2
|
*  x1@j0 != x2
|
*  *x1@j0
)

// ----------------------------------------------------------------------------

@script:python comparison_dereference_org depends on org@
j0 << comparison_dereference.j0;
@@

msg = "WARNING trying to compare or dereference struct clk pointers."
coccilib.org.print_todo(j0[0], msg)

// ----------------------------------------------------------------------------

@script:python comparison_dereference_report depends on report@
j0 << comparison_dereference.j0;
@@

msg = "WARNING trying to compare or dereference struct clk pointers."
coccilib.report.print_report(j0[0], msg)

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

* [Cocci] [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
@ 2015-02-05 15:45                   ` Quentin Lambert
  0 siblings, 0 replies; 186+ messages in thread
From: Quentin Lambert @ 2015-02-05 15:45 UTC (permalink / raw)
  To: cocci


On 05/02/2015 00:26, Stephen Boyd wrote:
>> If you want me to I can enlarge the search to other directories.
> Yes please do. And if you could share the coccinelle patch that would be
> great. Thanks.
>
structclk.cocci is the coccinelle patch
structclk-arm.patch is the result I got when applying it to the arch/arm 
directory

Is there anything else I can do to help?


-------------- next part --------------
A non-text attachment was scrubbed...
Name: structclk-arm.patch
Type: text/x-patch
Size: 2512 bytes
Desc: not available
URL: <https://systeme.lip6.fr/pipermail/cocci/attachments/20150205/7f8a2e33/attachment.bin>
-------------- next part --------------
/// Find any attempt to compare or dereference struct clk pointers.
///
// Confidence: High
// Copyright: (C) 2015 Quentin Lambert, INRIA/LiP6. GPLv2
// URL: http://coccinelle.lip6.fr/
// Options: --recursive-includes --relax-include-path
// Options: --include-headers-for-types

virtual context
virtual org
virtual report


// ----------------------------------------------------------------------------

@comparison_dereference depends on context || org || report@
struct clk *x1, x2;
position j0;
@@

(
*  x1 at j0 == x2
|
*  x1 at j0 != x2
|
*  *x1 at j0
)

// ----------------------------------------------------------------------------

@script:python comparison_dereference_org depends on org@
j0 << comparison_dereference.j0;
@@

msg = "WARNING trying to compare or dereference struct clk pointers."
coccilib.org.print_todo(j0[0], msg)

// ----------------------------------------------------------------------------

@script:python comparison_dereference_report depends on report@
j0 << comparison_dereference.j0;
@@

msg = "WARNING trying to compare or dereference struct clk pointers."
coccilib.report.print_report(j0[0], msg)

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

* [Cocci] [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
@ 2015-02-05 15:45                   ` Quentin Lambert
  0 siblings, 0 replies; 186+ messages in thread
From: Quentin Lambert @ 2015-02-05 15:45 UTC (permalink / raw)
  To: linux-arm-kernel


On 05/02/2015 00:26, Stephen Boyd wrote:
>> If you want me to I can enlarge the search to other directories.
> Yes please do. And if you could share the coccinelle patch that would be
> great. Thanks.
>
structclk.cocci is the coccinelle patch
structclk-arm.patch is the result I got when applying it to the arch/arm 
directory

Is there anything else I can do to help?


-------------- next part --------------
A non-text attachment was scrubbed...
Name: structclk-arm.patch
Type: text/x-patch
Size: 2512 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20150205/7f8a2e33/attachment.bin>
-------------- next part --------------
/// Find any attempt to compare or dereference struct clk pointers.
///
// Confidence: High
// Copyright: (C) 2015 Quentin Lambert, INRIA/LiP6. GPLv2
// URL: http://coccinelle.lip6.fr/
// Options: --recursive-includes --relax-include-path
// Options: --include-headers-for-types

virtual context
virtual org
virtual report


// ----------------------------------------------------------------------------

@comparison_dereference depends on context || org || report@
struct clk *x1, x2;
position j0;
@@

(
*  x1 at j0 == x2
|
*  x1 at j0 != x2
|
*  *x1 at j0
)

// ----------------------------------------------------------------------------

@script:python comparison_dereference_org depends on org@
j0 << comparison_dereference.j0;
@@

msg = "WARNING trying to compare or dereference struct clk pointers."
coccilib.org.print_todo(j0[0], msg)

// ----------------------------------------------------------------------------

@script:python comparison_dereference_report depends on report@
j0 << comparison_dereference.j0;
@@

msg = "WARNING trying to compare or dereference struct clk pointers."
coccilib.report.print_report(j0[0], msg)

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

* Re: [Cocci] [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
  2015-02-05 15:45                   ` Quentin Lambert
  (?)
@ 2015-02-05 16:02                     ` Quentin Lambert
  -1 siblings, 0 replies; 186+ messages in thread
From: Quentin Lambert @ 2015-02-05 16:02 UTC (permalink / raw)
  To: Stephen Boyd, Mike Turquette, Julia Lawall
  Cc: Paul Walmsley, Tomeu Vizoso, Tony Lindgren, linux-kernel,
	t-kristo, linux-omap, cocci, linux-arm-kernel

Sorry let me do that properly.

On 05/02/2015 16:45, Quentin Lambert wrote:
>
> On 05/02/2015 00:26, Stephen Boyd wrote:
>>> If you want me to I can enlarge the search to other directories.
>> Yes please do. And if you could share the coccinelle patch that would be
>> great. Thanks.
>>
> structclk.cocci is the coccinelle patch
> structclk-arm.patch is the result I got when applying it to the 
> arch/arm directory
>
> Is there anything else I can do to help?
>
>

These are the new instances I found by applying the patch to arch/arm 
directory:

./arch/arm/mach-imx/mach-imx6q.c
@@ -211,7 +211,6 @@ static void __init imx6q_1588_init(void)
       * set bit IOMUXC_GPR1[21].  Or the PTP clock must be from pad
       * (external OSC), and we need to clear the bit.
       */
      clksel = ptp_clk == enet_ref ? IMX6Q_GPR1_ENET_CLK_SEL_ANATOP :
                         IMX6Q_GPR1_ENET_CLK_SEL_PAD;
      gpr = syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
      if (!IS_ERR(gpr))

./arch/arm/mach-shmobile/clock-r8a73a4.c
@@ -139,7 +139,6 @@ static int pll_set_parent(struct clk *cl

      /* Search the parent */
      for (i = 0; i < clk->parent_num; i++)
          if (clk->parent_table[i] == parent)
              break;

      if (i == clk->parent_num)

./arch/arm/mach-shmobile/clock-sh7372.c
@@ -223,7 +223,6 @@ static int pllc2_set_parent(struct clk *

      /* Search the parent */
      for (i = 0; i < clk->parent_num; i++)
          if (clk->parent_table[i] == parent)
              break;

      if (i == clk->parent_num)

./arch/arm/mach-shmobile/clock-r8a7740.c
@@ -195,7 +195,6 @@ static int usb24s_set_parent(struct clk

      /* Search the parent */
      for (i = 0; i < clk->parent_num; i++)
          if (clk->parent_table[i] == parent)
              break;

      if (i == clk->parent_num)




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

* [Cocci] [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
@ 2015-02-05 16:02                     ` Quentin Lambert
  0 siblings, 0 replies; 186+ messages in thread
From: Quentin Lambert @ 2015-02-05 16:02 UTC (permalink / raw)
  To: cocci

Sorry let me do that properly.

On 05/02/2015 16:45, Quentin Lambert wrote:
>
> On 05/02/2015 00:26, Stephen Boyd wrote:
>>> If you want me to I can enlarge the search to other directories.
>> Yes please do. And if you could share the coccinelle patch that would be
>> great. Thanks.
>>
> structclk.cocci is the coccinelle patch
> structclk-arm.patch is the result I got when applying it to the 
> arch/arm directory
>
> Is there anything else I can do to help?
>
>

These are the new instances I found by applying the patch to arch/arm 
directory:

./arch/arm/mach-imx/mach-imx6q.c
@@ -211,7 +211,6 @@ static void __init imx6q_1588_init(void)
       * set bit IOMUXC_GPR1[21].  Or the PTP clock must be from pad
       * (external OSC), and we need to clear the bit.
       */
      clksel = ptp_clk == enet_ref ? IMX6Q_GPR1_ENET_CLK_SEL_ANATOP :
                         IMX6Q_GPR1_ENET_CLK_SEL_PAD;
      gpr = syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
      if (!IS_ERR(gpr))

./arch/arm/mach-shmobile/clock-r8a73a4.c
@@ -139,7 +139,6 @@ static int pll_set_parent(struct clk *cl

      /* Search the parent */
      for (i = 0; i < clk->parent_num; i++)
          if (clk->parent_table[i] == parent)
              break;

      if (i == clk->parent_num)

./arch/arm/mach-shmobile/clock-sh7372.c
@@ -223,7 +223,6 @@ static int pllc2_set_parent(struct clk *

      /* Search the parent */
      for (i = 0; i < clk->parent_num; i++)
          if (clk->parent_table[i] == parent)
              break;

      if (i == clk->parent_num)

./arch/arm/mach-shmobile/clock-r8a7740.c
@@ -195,7 +195,6 @@ static int usb24s_set_parent(struct clk

      /* Search the parent */
      for (i = 0; i < clk->parent_num; i++)
          if (clk->parent_table[i] == parent)
              break;

      if (i == clk->parent_num)

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

* [Cocci] [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
@ 2015-02-05 16:02                     ` Quentin Lambert
  0 siblings, 0 replies; 186+ messages in thread
From: Quentin Lambert @ 2015-02-05 16:02 UTC (permalink / raw)
  To: linux-arm-kernel

Sorry let me do that properly.

On 05/02/2015 16:45, Quentin Lambert wrote:
>
> On 05/02/2015 00:26, Stephen Boyd wrote:
>>> If you want me to I can enlarge the search to other directories.
>> Yes please do. And if you could share the coccinelle patch that would be
>> great. Thanks.
>>
> structclk.cocci is the coccinelle patch
> structclk-arm.patch is the result I got when applying it to the 
> arch/arm directory
>
> Is there anything else I can do to help?
>
>

These are the new instances I found by applying the patch to arch/arm 
directory:

./arch/arm/mach-imx/mach-imx6q.c
@@ -211,7 +211,6 @@ static void __init imx6q_1588_init(void)
       * set bit IOMUXC_GPR1[21].  Or the PTP clock must be from pad
       * (external OSC), and we need to clear the bit.
       */
      clksel = ptp_clk == enet_ref ? IMX6Q_GPR1_ENET_CLK_SEL_ANATOP :
                         IMX6Q_GPR1_ENET_CLK_SEL_PAD;
      gpr = syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
      if (!IS_ERR(gpr))

./arch/arm/mach-shmobile/clock-r8a73a4.c
@@ -139,7 +139,6 @@ static int pll_set_parent(struct clk *cl

      /* Search the parent */
      for (i = 0; i < clk->parent_num; i++)
          if (clk->parent_table[i] == parent)
              break;

      if (i == clk->parent_num)

./arch/arm/mach-shmobile/clock-sh7372.c
@@ -223,7 +223,6 @@ static int pllc2_set_parent(struct clk *

      /* Search the parent */
      for (i = 0; i < clk->parent_num; i++)
          if (clk->parent_table[i] == parent)
              break;

      if (i == clk->parent_num)

./arch/arm/mach-shmobile/clock-r8a7740.c
@@ -195,7 +195,6 @@ static int usb24s_set_parent(struct clk

      /* Search the parent */
      for (i = 0; i < clk->parent_num; i++)
          if (clk->parent_table[i] == parent)
              break;

      if (i == clk->parent_num)

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

* Re: [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
  2015-01-23 11:03   ` Tomeu Vizoso
@ 2015-02-05 19:44     ` Sylwester Nawrocki
  -1 siblings, 0 replies; 186+ messages in thread
From: Sylwester Nawrocki @ 2015-02-05 19:44 UTC (permalink / raw)
  To: Tomeu Vizoso
  Cc: linux-kernel, Mike Turquette, Stephen Boyd,
	Javier Martinez Canillas, Paul Walmsley, Tony Lindgren,
	Russell King, linux-omap, linux-arm-kernel

Hi Tomeu,

On 23/01/15 12:03, Tomeu Vizoso wrote:
>  int __clk_get(struct clk *clk)
>  {
> -	if (clk) {
> -		if (!try_module_get(clk->owner))
> +	struct clk_core *core = !clk ? NULL : clk->core;
> +
> +	if (core) {
> +		if (!try_module_get(core->owner))
>  			return 0;
>  
> -		kref_get(&clk->ref);
> +		kref_get(&core->ref);
>  	}
>  	return 1;
>  }
>  
> -void __clk_put(struct clk *clk)
> +static void clk_core_put(struct clk_core *core)
>  {
>  	struct module *owner;
>  
> -	if (!clk || WARN_ON_ONCE(IS_ERR(clk)))
> -		return;
> +	owner = core->owner;
>  
>  	clk_prepare_lock();
> -	owner = clk->owner;
> -	kref_put(&clk->ref, __clk_release);
> +	kref_put(&core->ref, __clk_release);
>  	clk_prepare_unlock();
>  
>  	module_put(owner);
>  }
>  
> +void __clk_put(struct clk *clk)
> +{
> +	if (!clk || WARN_ON_ONCE(IS_ERR(clk)))
> +		return;
> +
> +	clk_core_put(clk->core);
> +	kfree(clk);

Why do we have kfree() here? clk_get() doesn't allocate the data structure 
being freed here. What happens if we do clk_get(), clk_put(), clk_get() 
on same clock?

I suspect __clk_free_clk() should be called in __clk_release() callback
instead, but then there is an issue of safely getting reference to
struct clk from struct clk_core pointer.

I tested linux-next on Odroid U3 and booting fails with oopses as below.
There is no problems when the above kfree() is commented out.

> +}

[    1.345850] Unable to handle kernel paging request at virtual address 00200200
[    1.349319] pgd = c0004000
[    1.352072] [00200200] *pgd=00000000
[    1.355574] Internal error: Oops: 805 [#1] PREEMPT SMP ARM
[    1.361035] Modules linked in:
[    1.364078] CPU: 0 PID: 1 Comm: swapper/0 Not tainted 3.19.0-rc1-00104-ga251361a-dirty #992
[    1.372405] Hardware name: SAMSUNG EXYNOS (Flattened Device Tree)
[    1.378483] task: ee00b000 ti: ee088000 task.ti: ee088000
[    1.383879] PC is at __clk_put+0x24/0xd0
[    1.387773] LR is at clk_prepare_lock+0xc/0xec
[    1.392198] pc : [<c03eef38>]    lr : [<c03ec1f4>]    psr: 20000153
[    1.392198] sp : ee089de8  ip : 00000000  fp : 00000000
[    1.403653] r10: ee02f480  r9 : 00000001  r8 : 00000000
[    1.408862] r7 : ee031cc0  r6 : ee089e08  r5 : 00000000  r4 : ee02f480
[    1.415373] r3 : 00100100  r2 : 00200200  r1 : 0000091e  r0 : 00000001
[    1.421884] Flags: nzCv  IRQs on  FIQs off  Mode SVC_32  ISA ARM  Segment kernel
[    1.429261] Control: 10c5387d  Table: 4000404a  DAC: 00000015
[    1.434989] Process swapper/0 (pid: 1, stack limit = 0xee088238)
[    1.440978] Stack: (0xee089de8 to 0xee08a000)
[    1.445321] 9de0:                   ee7c8f14 c03f0ec8 ee089e08 00000000 c0718dc8 00000001
[    1.453480] 9e00: 00000000 c04ee0f0 ee7e0844 00000001 00000181 c04edb58 ee2bd320 00000000
[    1.461639] 9e20: 00000000 c011dc5c ee16a1e0 00000000 00000000 c0718dc8 ee16a1e0 ee2bd1e0
[    1.469798] 9e40: c0641740 ee16a1e0 00000000 ee2bd320 c0718dc8 ee1d3e10 ee1d3e10 00000000
[    1.477957] 9e60: c0769a88 00000000 c0718dc8 00000000 00000000 c02c3124 c02c310c ee1d3e10
[    1.486117] 9e80: c07b4eec 00000000 c0769a88 c02c1d0c ee1d3e10 c0769a88 ee1d3e44 00000000
[    1.494276] 9ea0: c07091dc c02c1eb8 00000000 c0769a88 c02c1e2c c02c0544 ee005478 ee1676c0
[    1.502435] 9ec0: c0769a88 ee3a4e80 c0760ce8 c02c150c c0669b90 c0769a88 c0746cd8 c0769a88
[    1.510594] 9ee0: c0746cd8 ee2bc4c0 c0778c00 c02c24e0 00000000 c0746cd8 c0746cd8 c07091f0
[    1.518753] 9f00: 00000000 c0008944 c04f405c 00000025 ee00b000 60000153 c074ab00 00000000
[    1.526913] 9f20: 00000000 c074ab90 60000153 00000000 ef7fca5d c050860c 000000b6 c0036b88
[    1.535071] 9f40: c065ecc4 c06bc728 00000006 00000006 c074ab30 ef7fca40 c0739bdc 00000006
[    1.543231] 9f60: c0718dbc c0778c00 000000b6 c0718dc8 c06ed598 c06edd64 00000006 00000006
[    1.551390] 9f80: c06ed598 c003b438 00000000 c04e64f4 00000000 00000000 00000000 00000000
[    1.559549] 9fa0: 00000000 c04e64fc 00000000 c000e838 00000000 00000000 00000000 00000000
[    1.567708] 9fc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[    1.575867] 9fe0: 00000000 00000000 00000000 00000000 00000013 00000000 c0c0c0c0 c0c0c0c0
[    1.584045] [<c03eef38>] (__clk_put) from [<c03f0ec8>] (of_clk_set_defaults+0xe0/0x2c0)
[    1.592024] [<c03f0ec8>] (of_clk_set_defaults) from [<c02c3124>] (platform_drv_probe+0x18/0xa4)
[    1.600698] [<c02c3124>] (platform_drv_probe) from [<c02c1d0c>] (driver_probe_device+0x10c/0x22c)
[    1.609549] [<c02c1d0c>] (driver_probe_device) from [<c02c1eb8>] (__driver_attach+0x8c/0x90)
[    1.617968] [<c02c1eb8>] (__driver_attach) from [<c02c0544>] (bus_for_each_dev+0x54/0x88)
[    1.626128] [<c02c0544>] (bus_for_each_dev) from [<c02c150c>] (bus_add_driver+0xd4/0x1d0)
[    1.634286] [<c02c150c>] (bus_add_driver) from [<c02c24e0>] (driver_register+0x78/0xf4)
[    1.642275] [<c02c24e0>] (driver_register) from [<c07091f0>] (fimc_md_init+0x14/0x30)
[    1.650089] [<c07091f0>] (fimc_md_init) from [<c0008944>] (do_one_initcall+0x80/0x1d0)
[    1.657989] [<c0008944>] (do_one_initcall) from [<c06edd64>] (kernel_init_freeable+0x108/0x1d4)
[    1.666675] [<c06edd64>] (kernel_init_freeable) from [<c04e64fc>] (kernel_init+0x8/0xec)
[    1.674743] [<c04e64fc>] (kernel_init) from [<c000e838>] (ret_from_fork+0x14/0x3c)
[    1.682287] Code: ebfff4ae e5943014 e5942018 e3530000 (e5823000) 
[    1.688606] ---[ end trace bb367704ce3168e1 ]---

-- 
Regards,
Sylwester

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

* [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
@ 2015-02-05 19:44     ` Sylwester Nawrocki
  0 siblings, 0 replies; 186+ messages in thread
From: Sylwester Nawrocki @ 2015-02-05 19:44 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Tomeu,

On 23/01/15 12:03, Tomeu Vizoso wrote:
>  int __clk_get(struct clk *clk)
>  {
> -	if (clk) {
> -		if (!try_module_get(clk->owner))
> +	struct clk_core *core = !clk ? NULL : clk->core;
> +
> +	if (core) {
> +		if (!try_module_get(core->owner))
>  			return 0;
>  
> -		kref_get(&clk->ref);
> +		kref_get(&core->ref);
>  	}
>  	return 1;
>  }
>  
> -void __clk_put(struct clk *clk)
> +static void clk_core_put(struct clk_core *core)
>  {
>  	struct module *owner;
>  
> -	if (!clk || WARN_ON_ONCE(IS_ERR(clk)))
> -		return;
> +	owner = core->owner;
>  
>  	clk_prepare_lock();
> -	owner = clk->owner;
> -	kref_put(&clk->ref, __clk_release);
> +	kref_put(&core->ref, __clk_release);
>  	clk_prepare_unlock();
>  
>  	module_put(owner);
>  }
>  
> +void __clk_put(struct clk *clk)
> +{
> +	if (!clk || WARN_ON_ONCE(IS_ERR(clk)))
> +		return;
> +
> +	clk_core_put(clk->core);
> +	kfree(clk);

Why do we have kfree() here? clk_get() doesn't allocate the data structure 
being freed here. What happens if we do clk_get(), clk_put(), clk_get() 
on same clock?

I suspect __clk_free_clk() should be called in __clk_release() callback
instead, but then there is an issue of safely getting reference to
struct clk from struct clk_core pointer.

I tested linux-next on Odroid U3 and booting fails with oopses as below.
There is no problems when the above kfree() is commented out.

> +}

[    1.345850] Unable to handle kernel paging request at virtual address 00200200
[    1.349319] pgd = c0004000
[    1.352072] [00200200] *pgd=00000000
[    1.355574] Internal error: Oops: 805 [#1] PREEMPT SMP ARM
[    1.361035] Modules linked in:
[    1.364078] CPU: 0 PID: 1 Comm: swapper/0 Not tainted 3.19.0-rc1-00104-ga251361a-dirty #992
[    1.372405] Hardware name: SAMSUNG EXYNOS (Flattened Device Tree)
[    1.378483] task: ee00b000 ti: ee088000 task.ti: ee088000
[    1.383879] PC is at __clk_put+0x24/0xd0
[    1.387773] LR is at clk_prepare_lock+0xc/0xec
[    1.392198] pc : [<c03eef38>]    lr : [<c03ec1f4>]    psr: 20000153
[    1.392198] sp : ee089de8  ip : 00000000  fp : 00000000
[    1.403653] r10: ee02f480  r9 : 00000001  r8 : 00000000
[    1.408862] r7 : ee031cc0  r6 : ee089e08  r5 : 00000000  r4 : ee02f480
[    1.415373] r3 : 00100100  r2 : 00200200  r1 : 0000091e  r0 : 00000001
[    1.421884] Flags: nzCv  IRQs on  FIQs off  Mode SVC_32  ISA ARM  Segment kernel
[    1.429261] Control: 10c5387d  Table: 4000404a  DAC: 00000015
[    1.434989] Process swapper/0 (pid: 1, stack limit = 0xee088238)
[    1.440978] Stack: (0xee089de8 to 0xee08a000)
[    1.445321] 9de0:                   ee7c8f14 c03f0ec8 ee089e08 00000000 c0718dc8 00000001
[    1.453480] 9e00: 00000000 c04ee0f0 ee7e0844 00000001 00000181 c04edb58 ee2bd320 00000000
[    1.461639] 9e20: 00000000 c011dc5c ee16a1e0 00000000 00000000 c0718dc8 ee16a1e0 ee2bd1e0
[    1.469798] 9e40: c0641740 ee16a1e0 00000000 ee2bd320 c0718dc8 ee1d3e10 ee1d3e10 00000000
[    1.477957] 9e60: c0769a88 00000000 c0718dc8 00000000 00000000 c02c3124 c02c310c ee1d3e10
[    1.486117] 9e80: c07b4eec 00000000 c0769a88 c02c1d0c ee1d3e10 c0769a88 ee1d3e44 00000000
[    1.494276] 9ea0: c07091dc c02c1eb8 00000000 c0769a88 c02c1e2c c02c0544 ee005478 ee1676c0
[    1.502435] 9ec0: c0769a88 ee3a4e80 c0760ce8 c02c150c c0669b90 c0769a88 c0746cd8 c0769a88
[    1.510594] 9ee0: c0746cd8 ee2bc4c0 c0778c00 c02c24e0 00000000 c0746cd8 c0746cd8 c07091f0
[    1.518753] 9f00: 00000000 c0008944 c04f405c 00000025 ee00b000 60000153 c074ab00 00000000
[    1.526913] 9f20: 00000000 c074ab90 60000153 00000000 ef7fca5d c050860c 000000b6 c0036b88
[    1.535071] 9f40: c065ecc4 c06bc728 00000006 00000006 c074ab30 ef7fca40 c0739bdc 00000006
[    1.543231] 9f60: c0718dbc c0778c00 000000b6 c0718dc8 c06ed598 c06edd64 00000006 00000006
[    1.551390] 9f80: c06ed598 c003b438 00000000 c04e64f4 00000000 00000000 00000000 00000000
[    1.559549] 9fa0: 00000000 c04e64fc 00000000 c000e838 00000000 00000000 00000000 00000000
[    1.567708] 9fc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[    1.575867] 9fe0: 00000000 00000000 00000000 00000000 00000013 00000000 c0c0c0c0 c0c0c0c0
[    1.584045] [<c03eef38>] (__clk_put) from [<c03f0ec8>] (of_clk_set_defaults+0xe0/0x2c0)
[    1.592024] [<c03f0ec8>] (of_clk_set_defaults) from [<c02c3124>] (platform_drv_probe+0x18/0xa4)
[    1.600698] [<c02c3124>] (platform_drv_probe) from [<c02c1d0c>] (driver_probe_device+0x10c/0x22c)
[    1.609549] [<c02c1d0c>] (driver_probe_device) from [<c02c1eb8>] (__driver_attach+0x8c/0x90)
[    1.617968] [<c02c1eb8>] (__driver_attach) from [<c02c0544>] (bus_for_each_dev+0x54/0x88)
[    1.626128] [<c02c0544>] (bus_for_each_dev) from [<c02c150c>] (bus_add_driver+0xd4/0x1d0)
[    1.634286] [<c02c150c>] (bus_add_driver) from [<c02c24e0>] (driver_register+0x78/0xf4)
[    1.642275] [<c02c24e0>] (driver_register) from [<c07091f0>] (fimc_md_init+0x14/0x30)
[    1.650089] [<c07091f0>] (fimc_md_init) from [<c0008944>] (do_one_initcall+0x80/0x1d0)
[    1.657989] [<c0008944>] (do_one_initcall) from [<c06edd64>] (kernel_init_freeable+0x108/0x1d4)
[    1.666675] [<c06edd64>] (kernel_init_freeable) from [<c04e64fc>] (kernel_init+0x8/0xec)
[    1.674743] [<c04e64fc>] (kernel_init) from [<c000e838>] (ret_from_fork+0x14/0x3c)
[    1.682287] Code: ebfff4ae e5943014 e5942018 e3530000 (e5823000) 
[    1.688606] ---[ end trace bb367704ce3168e1 ]---

-- 
Regards,
Sylwester

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

* Re: [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
  2015-02-05 19:44     ` Sylwester Nawrocki
@ 2015-02-05 20:06       ` Sylwester Nawrocki
  -1 siblings, 0 replies; 186+ messages in thread
From: Sylwester Nawrocki @ 2015-02-05 20:06 UTC (permalink / raw)
  To: Tomeu Vizoso
  Cc: linux-kernel, Mike Turquette, Stephen Boyd,
	Javier Martinez Canillas, Paul Walmsley, Tony Lindgren,
	Russell King, linux-omap, linux-arm-kernel

On 05/02/15 20:44, Sylwester Nawrocki wrote:
>> +void __clk_put(struct clk *clk)
>> > +{
>> > +	if (!clk || WARN_ON_ONCE(IS_ERR(clk)))
>> > +		return;
>> > +
>> > +	clk_core_put(clk->core);
>> > +	kfree(clk);
>
> Why do we have kfree() here? clk_get() doesn't allocate the data structure 
> being freed here. What happens if we do clk_get(), clk_put(), clk_get() 
> on same clock?
> 
> I suspect __clk_free_clk() should be called in __clk_release() callback
> instead, but then there is an issue of safely getting reference to
> struct clk from struct clk_core pointer.

Please ignore this comment, I missed __clk_create_clk() calls in clkdev.c
Anyway, in current -next I'm seeing random pointer dereferences while
booting Odroid U3, I'll get back to debugging this tomorrow morning.

-- 
Regards,
Sylwester

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

* [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
@ 2015-02-05 20:06       ` Sylwester Nawrocki
  0 siblings, 0 replies; 186+ messages in thread
From: Sylwester Nawrocki @ 2015-02-05 20:06 UTC (permalink / raw)
  To: linux-arm-kernel

On 05/02/15 20:44, Sylwester Nawrocki wrote:
>> +void __clk_put(struct clk *clk)
>> > +{
>> > +	if (!clk || WARN_ON_ONCE(IS_ERR(clk)))
>> > +		return;
>> > +
>> > +	clk_core_put(clk->core);
>> > +	kfree(clk);
>
> Why do we have kfree() here? clk_get() doesn't allocate the data structure 
> being freed here. What happens if we do clk_get(), clk_put(), clk_get() 
> on same clock?
> 
> I suspect __clk_free_clk() should be called in __clk_release() callback
> instead, but then there is an issue of safely getting reference to
> struct clk from struct clk_core pointer.

Please ignore this comment, I missed __clk_create_clk() calls in clkdev.c
Anyway, in current -next I'm seeing random pointer dereferences while
booting Odroid U3, I'll get back to debugging this tomorrow morning.

-- 
Regards,
Sylwester

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

* Re: [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
  2015-02-05 19:44     ` Sylwester Nawrocki
@ 2015-02-05 20:07       ` Stephen Boyd
  -1 siblings, 0 replies; 186+ messages in thread
From: Stephen Boyd @ 2015-02-05 20:07 UTC (permalink / raw)
  To: Sylwester Nawrocki, Tomeu Vizoso
  Cc: linux-kernel, Mike Turquette, Javier Martinez Canillas,
	Paul Walmsley, Tony Lindgren, Russell King, linux-omap,
	linux-arm-kernel

On 02/05/15 11:44, Sylwester Nawrocki wrote:
> Hi Tomeu,
>
> On 23/01/15 12:03, Tomeu Vizoso wrote:
>>  int __clk_get(struct clk *clk)
>>  {
>> -	if (clk) {
>> -		if (!try_module_get(clk->owner))
>> +	struct clk_core *core = !clk ? NULL : clk->core;
>> +
>> +	if (core) {
>> +		if (!try_module_get(core->owner))
>>  			return 0;
>>  
>> -		kref_get(&clk->ref);
>> +		kref_get(&core->ref);
>>  	}
>>  	return 1;
>>  }
>>  
>> -void __clk_put(struct clk *clk)
>> +static void clk_core_put(struct clk_core *core)
>>  {
>>  	struct module *owner;
>>  
>> -	if (!clk || WARN_ON_ONCE(IS_ERR(clk)))
>> -		return;
>> +	owner = core->owner;
>>  
>>  	clk_prepare_lock();
>> -	owner = clk->owner;
>> -	kref_put(&clk->ref, __clk_release);
>> +	kref_put(&core->ref, __clk_release);
>>  	clk_prepare_unlock();
>>  
>>  	module_put(owner);
>>  }
>>  
>> +void __clk_put(struct clk *clk)
>> +{
>> +	if (!clk || WARN_ON_ONCE(IS_ERR(clk)))
>> +		return;
>> +
>> +	clk_core_put(clk->core);
>> +	kfree(clk);
> Why do we have kfree() here? clk_get() doesn't allocate the data structure 
> being freed here. What happens if we do clk_get(), clk_put(), clk_get() 
> on same clock?
>
> I suspect __clk_free_clk() should be called in __clk_release() callback
> instead, but then there is an issue of safely getting reference to
> struct clk from struct clk_core pointer.
>
> I tested linux-next on Odroid U3 and booting fails with oopses as below.
> There is no problems when the above kfree() is commented out.
>
>

Ah now I get it. You meant to say that of_clk_get_by_clkspec() doesn't
return an allocated clk pointer. Let's fix that.

----8<----

From: Stephen Boyd <sboyd@codeaurora.org>
Subject: [PATCH] clkdev: Always allocate a struct clk in OF functions

of_clk_get_by_clkspec() returns a struct clk pointer but it
doesn't create a new handle for the consumers. Instead it just
returns whatever the OF clk provider hands out. Let's create a
per-user handle here so that clk_put() can properly unlink it and
free it when the consumer is done.

Fixes: 035a61c314eb "clk: Make clk API return per-user struct clk instances"
Reported-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/clkdev.c | 44 +++++++++++++++++++++++---------------------
 1 file changed, 23 insertions(+), 21 deletions(-)

diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c
index 29a1ab7af4b8..00d747d09b2a 100644
--- a/drivers/clk/clkdev.c
+++ b/drivers/clk/clkdev.c
@@ -29,15 +29,8 @@ static DEFINE_MUTEX(clocks_mutex);
 
 #if defined(CONFIG_OF) && defined(CONFIG_COMMON_CLK)
 
-/**
- * of_clk_get_by_clkspec() - Lookup a clock form a clock provider
- * @clkspec: pointer to a clock specifier data structure
- *
- * This function looks up a struct clk from the registered list of clock
- * providers, an input is a clock specifier data structure as returned
- * from the of_parse_phandle_with_args() function call.
- */
-struct clk *of_clk_get_by_clkspec(struct of_phandle_args *clkspec)
+static struct clk *__of_clk_get_by_clkspec(struct of_phandle_args *clkspec,
+					 const char *dev_id, const char *con_id)
 {
 	struct clk *clk;
 
@@ -47,6 +40,8 @@ struct clk *of_clk_get_by_clkspec(struct of_phandle_args *clkspec)
 	of_clk_lock();
 	clk = __of_clk_get_from_provider(clkspec);
 
+	if (!IS_ERR(clk))
+		clk = __clk_create_clk(__clk_get_hw(clk), dev_id, con_id);
 	if (!IS_ERR(clk) && !__clk_get(clk))
 		clk = ERR_PTR(-ENOENT);
 
@@ -54,7 +49,21 @@ struct clk *of_clk_get_by_clkspec(struct of_phandle_args *clkspec)
 	return clk;
 }
 
-static struct clk *__of_clk_get(struct device_node *np, int index)
+/**
+ * of_clk_get_by_clkspec() - Lookup a clock form a clock provider
+ * @clkspec: pointer to a clock specifier data structure
+ *
+ * This function looks up a struct clk from the registered list of clock
+ * providers, an input is a clock specifier data structure as returned
+ * from the of_parse_phandle_with_args() function call.
+ */
+struct clk *of_clk_get_by_clkspec(struct of_phandle_args *clkspec)
+{
+	return __of_clk_get_by_clkspec(clkspec, NULL, __func__);
+}
+
+static struct clk *__of_clk_get(struct device_node *np, int index,
+			       const char *dev_id, const char *con_id)
 {
 	struct of_phandle_args clkspec;
 	struct clk *clk;
@@ -68,7 +77,7 @@ static struct clk *__of_clk_get(struct device_node *np, int index)
 	if (rc)
 		return ERR_PTR(rc);
 
-	clk = of_clk_get_by_clkspec(&clkspec);
+	clk = __of_clk_get_by_clkspec(&clkspec, dev_id, con_id);
 	of_node_put(clkspec.np);
 
 	return clk;
@@ -76,12 +85,7 @@ static struct clk *__of_clk_get(struct device_node *np, int index)
 
 struct clk *of_clk_get(struct device_node *np, int index)
 {
-	struct clk *clk = __of_clk_get(np, index);
-
-	if (!IS_ERR(clk))
-		clk = __clk_create_clk(__clk_get_hw(clk), np->full_name, NULL);
-
-	return clk;
+	return __of_clk_get(np, index, np->full_name, NULL);
 }
 EXPORT_SYMBOL(of_clk_get);
 
@@ -102,12 +106,10 @@ static struct clk *__of_clk_get_by_name(struct device_node *np,
 		 */
 		if (name)
 			index = of_property_match_string(np, "clock-names", name);
-		clk = __of_clk_get(np, index);
+		clk = __of_clk_get(np, index, dev_id, name);
 		if (!IS_ERR(clk)) {
-			clk = __clk_create_clk(__clk_get_hw(clk), dev_id, name);
 			break;
-		}
-		else if (name && index >= 0) {
+		} else if (name && index >= 0) {
 			if (PTR_ERR(clk) != -EPROBE_DEFER)
 				pr_err("ERROR: could not get clock %s:%s(%i)\n",
 					np->full_name, name ? name : "", index);


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


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

* [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
@ 2015-02-05 20:07       ` Stephen Boyd
  0 siblings, 0 replies; 186+ messages in thread
From: Stephen Boyd @ 2015-02-05 20:07 UTC (permalink / raw)
  To: linux-arm-kernel

On 02/05/15 11:44, Sylwester Nawrocki wrote:
> Hi Tomeu,
>
> On 23/01/15 12:03, Tomeu Vizoso wrote:
>>  int __clk_get(struct clk *clk)
>>  {
>> -	if (clk) {
>> -		if (!try_module_get(clk->owner))
>> +	struct clk_core *core = !clk ? NULL : clk->core;
>> +
>> +	if (core) {
>> +		if (!try_module_get(core->owner))
>>  			return 0;
>>  
>> -		kref_get(&clk->ref);
>> +		kref_get(&core->ref);
>>  	}
>>  	return 1;
>>  }
>>  
>> -void __clk_put(struct clk *clk)
>> +static void clk_core_put(struct clk_core *core)
>>  {
>>  	struct module *owner;
>>  
>> -	if (!clk || WARN_ON_ONCE(IS_ERR(clk)))
>> -		return;
>> +	owner = core->owner;
>>  
>>  	clk_prepare_lock();
>> -	owner = clk->owner;
>> -	kref_put(&clk->ref, __clk_release);
>> +	kref_put(&core->ref, __clk_release);
>>  	clk_prepare_unlock();
>>  
>>  	module_put(owner);
>>  }
>>  
>> +void __clk_put(struct clk *clk)
>> +{
>> +	if (!clk || WARN_ON_ONCE(IS_ERR(clk)))
>> +		return;
>> +
>> +	clk_core_put(clk->core);
>> +	kfree(clk);
> Why do we have kfree() here? clk_get() doesn't allocate the data structure 
> being freed here. What happens if we do clk_get(), clk_put(), clk_get() 
> on same clock?
>
> I suspect __clk_free_clk() should be called in __clk_release() callback
> instead, but then there is an issue of safely getting reference to
> struct clk from struct clk_core pointer.
>
> I tested linux-next on Odroid U3 and booting fails with oopses as below.
> There is no problems when the above kfree() is commented out.
>
>

Ah now I get it. You meant to say that of_clk_get_by_clkspec() doesn't
return an allocated clk pointer. Let's fix that.

----8<----

From: Stephen Boyd <sboyd@codeaurora.org>
Subject: [PATCH] clkdev: Always allocate a struct clk in OF functions

of_clk_get_by_clkspec() returns a struct clk pointer but it
doesn't create a new handle for the consumers. Instead it just
returns whatever the OF clk provider hands out. Let's create a
per-user handle here so that clk_put() can properly unlink it and
free it when the consumer is done.

Fixes: 035a61c314eb "clk: Make clk API return per-user struct clk instances"
Reported-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/clkdev.c | 44 +++++++++++++++++++++++---------------------
 1 file changed, 23 insertions(+), 21 deletions(-)

diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c
index 29a1ab7af4b8..00d747d09b2a 100644
--- a/drivers/clk/clkdev.c
+++ b/drivers/clk/clkdev.c
@@ -29,15 +29,8 @@ static DEFINE_MUTEX(clocks_mutex);
 
 #if defined(CONFIG_OF) && defined(CONFIG_COMMON_CLK)
 
-/**
- * of_clk_get_by_clkspec() - Lookup a clock form a clock provider
- * @clkspec: pointer to a clock specifier data structure
- *
- * This function looks up a struct clk from the registered list of clock
- * providers, an input is a clock specifier data structure as returned
- * from the of_parse_phandle_with_args() function call.
- */
-struct clk *of_clk_get_by_clkspec(struct of_phandle_args *clkspec)
+static struct clk *__of_clk_get_by_clkspec(struct of_phandle_args *clkspec,
+					 const char *dev_id, const char *con_id)
 {
 	struct clk *clk;
 
@@ -47,6 +40,8 @@ struct clk *of_clk_get_by_clkspec(struct of_phandle_args *clkspec)
 	of_clk_lock();
 	clk = __of_clk_get_from_provider(clkspec);
 
+	if (!IS_ERR(clk))
+		clk = __clk_create_clk(__clk_get_hw(clk), dev_id, con_id);
 	if (!IS_ERR(clk) && !__clk_get(clk))
 		clk = ERR_PTR(-ENOENT);
 
@@ -54,7 +49,21 @@ struct clk *of_clk_get_by_clkspec(struct of_phandle_args *clkspec)
 	return clk;
 }
 
-static struct clk *__of_clk_get(struct device_node *np, int index)
+/**
+ * of_clk_get_by_clkspec() - Lookup a clock form a clock provider
+ * @clkspec: pointer to a clock specifier data structure
+ *
+ * This function looks up a struct clk from the registered list of clock
+ * providers, an input is a clock specifier data structure as returned
+ * from the of_parse_phandle_with_args() function call.
+ */
+struct clk *of_clk_get_by_clkspec(struct of_phandle_args *clkspec)
+{
+	return __of_clk_get_by_clkspec(clkspec, NULL, __func__);
+}
+
+static struct clk *__of_clk_get(struct device_node *np, int index,
+			       const char *dev_id, const char *con_id)
 {
 	struct of_phandle_args clkspec;
 	struct clk *clk;
@@ -68,7 +77,7 @@ static struct clk *__of_clk_get(struct device_node *np, int index)
 	if (rc)
 		return ERR_PTR(rc);
 
-	clk = of_clk_get_by_clkspec(&clkspec);
+	clk = __of_clk_get_by_clkspec(&clkspec, dev_id, con_id);
 	of_node_put(clkspec.np);
 
 	return clk;
@@ -76,12 +85,7 @@ static struct clk *__of_clk_get(struct device_node *np, int index)
 
 struct clk *of_clk_get(struct device_node *np, int index)
 {
-	struct clk *clk = __of_clk_get(np, index);
-
-	if (!IS_ERR(clk))
-		clk = __clk_create_clk(__clk_get_hw(clk), np->full_name, NULL);
-
-	return clk;
+	return __of_clk_get(np, index, np->full_name, NULL);
 }
 EXPORT_SYMBOL(of_clk_get);
 
@@ -102,12 +106,10 @@ static struct clk *__of_clk_get_by_name(struct device_node *np,
 		 */
 		if (name)
 			index = of_property_match_string(np, "clock-names", name);
-		clk = __of_clk_get(np, index);
+		clk = __of_clk_get(np, index, dev_id, name);
 		if (!IS_ERR(clk)) {
-			clk = __clk_create_clk(__clk_get_hw(clk), dev_id, name);
 			break;
-		}
-		else if (name && index >= 0) {
+		} else if (name && index >= 0) {
 			if (PTR_ERR(clk) != -EPROBE_DEFER)
 				pr_err("ERROR: could not get clock %s:%s(%i)\n",
 					np->full_name, name ? name : "", index);


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

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

* Re: [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
  2015-02-05 20:07       ` Stephen Boyd
@ 2015-02-05 22:14         ` Stephen Boyd
  -1 siblings, 0 replies; 186+ messages in thread
From: Stephen Boyd @ 2015-02-05 22:14 UTC (permalink / raw)
  To: Sylwester Nawrocki, Tomeu Vizoso
  Cc: Paul Walmsley, Russell King, Tony Lindgren, linux-kernel,
	Mike Turquette, linux-omap, Javier Martinez Canillas,
	linux-arm-kernel

On 02/05/15 12:07, Stephen Boyd wrote:
> On 02/05/15 11:44, Sylwester Nawrocki wrote:
>> Hi Tomeu,
>>
>> On 23/01/15 12:03, Tomeu Vizoso wrote:
>>>  int __clk_get(struct clk *clk)
>>>  {
>>> -	if (clk) {
>>> -		if (!try_module_get(clk->owner))
>>> +	struct clk_core *core = !clk ? NULL : clk->core;
>>> +
>>> +	if (core) {
>>> +		if (!try_module_get(core->owner))
>>>  			return 0;
>>>  
>>> -		kref_get(&clk->ref);
>>> +		kref_get(&core->ref);
>>>  	}
>>>  	return 1;
>>>  }
>>>  
>>> -void __clk_put(struct clk *clk)
>>> +static void clk_core_put(struct clk_core *core)
>>>  {
>>>  	struct module *owner;
>>>  
>>> -	if (!clk || WARN_ON_ONCE(IS_ERR(clk)))
>>> -		return;
>>> +	owner = core->owner;
>>>  
>>>  	clk_prepare_lock();
>>> -	owner = clk->owner;
>>> -	kref_put(&clk->ref, __clk_release);
>>> +	kref_put(&core->ref, __clk_release);
>>>  	clk_prepare_unlock();
>>>  
>>>  	module_put(owner);
>>>  }
>>>  
>>> +void __clk_put(struct clk *clk)
>>> +{
>>> +	if (!clk || WARN_ON_ONCE(IS_ERR(clk)))
>>> +		return;
>>> +
>>> +	clk_core_put(clk->core);
>>> +	kfree(clk);
>> Why do we have kfree() here? clk_get() doesn't allocate the data structure 
>> being freed here. What happens if we do clk_get(), clk_put(), clk_get() 
>> on same clock?
>>
>> I suspect __clk_free_clk() should be called in __clk_release() callback
>> instead, but then there is an issue of safely getting reference to
>> struct clk from struct clk_core pointer.
>>
>> I tested linux-next on Odroid U3 and booting fails with oopses as below.
>> There is no problems when the above kfree() is commented out.
>>
>>
> Ah now I get it. You meant to say that of_clk_get_by_clkspec() doesn't
> return an allocated clk pointer. Let's fix that.
>
> ----8<----
>
> From: Stephen Boyd <sboyd@codeaurora.org>
> Subject: [PATCH] clkdev: Always allocate a struct clk in OF functions
>
> of_clk_get_by_clkspec() returns a struct clk pointer but it
> doesn't create a new handle for the consumers. Instead it just
> returns whatever the OF clk provider hands out. Let's create a
> per-user handle here so that clk_put() can properly unlink it and
> free it when the consumer is done.
>
> Fixes: 035a61c314eb "clk: Make clk API return per-user struct clk instances"
> Reported-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
> Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
> ---
>  drivers/clk/clkdev.c | 44 +++++++++++++++++++++++---------------------
>  1 file changed, 23 insertions(+), 21 deletions(-)
>
> diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c
> index 29a1ab7af4b8..00d747d09b2a 100644
> --- a/drivers/clk/clkdev.c
> +++ b/drivers/clk/clkdev.c
> @@ -29,15 +29,8 @@ static DEFINE_MUTEX(clocks_mutex);
>  
>  #if defined(CONFIG_OF) && defined(CONFIG_COMMON_CLK)
>  
> -/**
> - * of_clk_get_by_clkspec() - Lookup a clock form a clock provider
> - * @clkspec: pointer to a clock specifier data structure
> - *
> - * This function looks up a struct clk from the registered list of clock
> - * providers, an input is a clock specifier data structure as returned
> - * from the of_parse_phandle_with_args() function call.
> - */
> -struct clk *of_clk_get_by_clkspec(struct of_phandle_args *clkspec)
> +static struct clk *__of_clk_get_by_clkspec(struct of_phandle_args *clkspec,
> +					 const char *dev_id, const char *con_id)
>  {
>  	struct clk *clk;
>  
> @@ -47,6 +40,8 @@ struct clk *of_clk_get_by_clkspec(struct of_phandle_args *clkspec)
>  	of_clk_lock();
>  	clk = __of_clk_get_from_provider(clkspec);
>  
> +	if (!IS_ERR(clk))
> +		clk = __clk_create_clk(__clk_get_hw(clk), dev_id, con_id);
>  	if (!IS_ERR(clk) && !__clk_get(clk))
>  		clk = ERR_PTR(-ENOENT);
>

Actually we can bury the __clk_create_clk() inside
__of_clk_get_from_provider(). We should also move __clk_get() into there
because right now we have a hole where whoever calls
of_clk_get_from_provider() never calls __clk_get() on the clk, leading
to possible badness. v2 coming soon.

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


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

* [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
@ 2015-02-05 22:14         ` Stephen Boyd
  0 siblings, 0 replies; 186+ messages in thread
From: Stephen Boyd @ 2015-02-05 22:14 UTC (permalink / raw)
  To: linux-arm-kernel

On 02/05/15 12:07, Stephen Boyd wrote:
> On 02/05/15 11:44, Sylwester Nawrocki wrote:
>> Hi Tomeu,
>>
>> On 23/01/15 12:03, Tomeu Vizoso wrote:
>>>  int __clk_get(struct clk *clk)
>>>  {
>>> -	if (clk) {
>>> -		if (!try_module_get(clk->owner))
>>> +	struct clk_core *core = !clk ? NULL : clk->core;
>>> +
>>> +	if (core) {
>>> +		if (!try_module_get(core->owner))
>>>  			return 0;
>>>  
>>> -		kref_get(&clk->ref);
>>> +		kref_get(&core->ref);
>>>  	}
>>>  	return 1;
>>>  }
>>>  
>>> -void __clk_put(struct clk *clk)
>>> +static void clk_core_put(struct clk_core *core)
>>>  {
>>>  	struct module *owner;
>>>  
>>> -	if (!clk || WARN_ON_ONCE(IS_ERR(clk)))
>>> -		return;
>>> +	owner = core->owner;
>>>  
>>>  	clk_prepare_lock();
>>> -	owner = clk->owner;
>>> -	kref_put(&clk->ref, __clk_release);
>>> +	kref_put(&core->ref, __clk_release);
>>>  	clk_prepare_unlock();
>>>  
>>>  	module_put(owner);
>>>  }
>>>  
>>> +void __clk_put(struct clk *clk)
>>> +{
>>> +	if (!clk || WARN_ON_ONCE(IS_ERR(clk)))
>>> +		return;
>>> +
>>> +	clk_core_put(clk->core);
>>> +	kfree(clk);
>> Why do we have kfree() here? clk_get() doesn't allocate the data structure 
>> being freed here. What happens if we do clk_get(), clk_put(), clk_get() 
>> on same clock?
>>
>> I suspect __clk_free_clk() should be called in __clk_release() callback
>> instead, but then there is an issue of safely getting reference to
>> struct clk from struct clk_core pointer.
>>
>> I tested linux-next on Odroid U3 and booting fails with oopses as below.
>> There is no problems when the above kfree() is commented out.
>>
>>
> Ah now I get it. You meant to say that of_clk_get_by_clkspec() doesn't
> return an allocated clk pointer. Let's fix that.
>
> ----8<----
>
> From: Stephen Boyd <sboyd@codeaurora.org>
> Subject: [PATCH] clkdev: Always allocate a struct clk in OF functions
>
> of_clk_get_by_clkspec() returns a struct clk pointer but it
> doesn't create a new handle for the consumers. Instead it just
> returns whatever the OF clk provider hands out. Let's create a
> per-user handle here so that clk_put() can properly unlink it and
> free it when the consumer is done.
>
> Fixes: 035a61c314eb "clk: Make clk API return per-user struct clk instances"
> Reported-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
> Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
> ---
>  drivers/clk/clkdev.c | 44 +++++++++++++++++++++++---------------------
>  1 file changed, 23 insertions(+), 21 deletions(-)
>
> diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c
> index 29a1ab7af4b8..00d747d09b2a 100644
> --- a/drivers/clk/clkdev.c
> +++ b/drivers/clk/clkdev.c
> @@ -29,15 +29,8 @@ static DEFINE_MUTEX(clocks_mutex);
>  
>  #if defined(CONFIG_OF) && defined(CONFIG_COMMON_CLK)
>  
> -/**
> - * of_clk_get_by_clkspec() - Lookup a clock form a clock provider
> - * @clkspec: pointer to a clock specifier data structure
> - *
> - * This function looks up a struct clk from the registered list of clock
> - * providers, an input is a clock specifier data structure as returned
> - * from the of_parse_phandle_with_args() function call.
> - */
> -struct clk *of_clk_get_by_clkspec(struct of_phandle_args *clkspec)
> +static struct clk *__of_clk_get_by_clkspec(struct of_phandle_args *clkspec,
> +					 const char *dev_id, const char *con_id)
>  {
>  	struct clk *clk;
>  
> @@ -47,6 +40,8 @@ struct clk *of_clk_get_by_clkspec(struct of_phandle_args *clkspec)
>  	of_clk_lock();
>  	clk = __of_clk_get_from_provider(clkspec);
>  
> +	if (!IS_ERR(clk))
> +		clk = __clk_create_clk(__clk_get_hw(clk), dev_id, con_id);
>  	if (!IS_ERR(clk) && !__clk_get(clk))
>  		clk = ERR_PTR(-ENOENT);
>

Actually we can bury the __clk_create_clk() inside
__of_clk_get_from_provider(). We should also move __clk_get() into there
because right now we have a hole where whoever calls
of_clk_get_from_provider() never calls __clk_get() on the clk, leading
to possible badness. v2 coming soon.

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

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

* Re: [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
  2015-02-05 22:14         ` Stephen Boyd
@ 2015-02-06  0:42           ` Russell King - ARM Linux
  -1 siblings, 0 replies; 186+ messages in thread
From: Russell King - ARM Linux @ 2015-02-06  0:42 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Sylwester Nawrocki, Tomeu Vizoso, Paul Walmsley, Tony Lindgren,
	linux-kernel, Mike Turquette, linux-omap,
	Javier Martinez Canillas, linux-arm-kernel

On Thu, Feb 05, 2015 at 02:14:01PM -0800, Stephen Boyd wrote:
> Actually we can bury the __clk_create_clk() inside
> __of_clk_get_from_provider(). We should also move __clk_get() into there
> because right now we have a hole where whoever calls
> of_clk_get_from_provider() never calls __clk_get() on the clk, leading
> to possible badness. v2 coming soon.

There's some other issues here too...

sound/soc/kirkwood/kirkwood-i2s.c:

        priv->clk = devm_clk_get(&pdev->dev, np ? "internal" : NULL);
...
        priv->extclk = devm_clk_get(&pdev->dev, "extclk");
        if (IS_ERR(priv->extclk)) {
...
	} else {
                if (priv->extclk == priv->clk) {
                        devm_clk_put(&pdev->dev, priv->extclk);
                        priv->extclk = ERR_PTR(-EINVAL);
                } else {
                        dev_info(&pdev->dev, "found external clock\n");
                        clk_prepare_enable(priv->extclk);
                        soc_dai = kirkwood_i2s_dai_extclk;
                }

It should be fine provided your "trick" is only done for DT clocks,
but not for legacy - with legacy, a NULL in the clkdev tables will
match both these requests, hence the need to compare the clk_get()
return value to tell whether we get the same clock.

-- 
FTTC broadband for 0.8mile line: currently at 10.5Mbps down 400kbps up
according to speedtest.net.

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

* [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
@ 2015-02-06  0:42           ` Russell King - ARM Linux
  0 siblings, 0 replies; 186+ messages in thread
From: Russell King - ARM Linux @ 2015-02-06  0:42 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Feb 05, 2015 at 02:14:01PM -0800, Stephen Boyd wrote:
> Actually we can bury the __clk_create_clk() inside
> __of_clk_get_from_provider(). We should also move __clk_get() into there
> because right now we have a hole where whoever calls
> of_clk_get_from_provider() never calls __clk_get() on the clk, leading
> to possible badness. v2 coming soon.

There's some other issues here too...

sound/soc/kirkwood/kirkwood-i2s.c:

        priv->clk = devm_clk_get(&pdev->dev, np ? "internal" : NULL);
...
        priv->extclk = devm_clk_get(&pdev->dev, "extclk");
        if (IS_ERR(priv->extclk)) {
...
	} else {
                if (priv->extclk == priv->clk) {
                        devm_clk_put(&pdev->dev, priv->extclk);
                        priv->extclk = ERR_PTR(-EINVAL);
                } else {
                        dev_info(&pdev->dev, "found external clock\n");
                        clk_prepare_enable(priv->extclk);
                        soc_dai = kirkwood_i2s_dai_extclk;
                }

It should be fine provided your "trick" is only done for DT clocks,
but not for legacy - with legacy, a NULL in the clkdev tables will
match both these requests, hence the need to compare the clk_get()
return value to tell whether we get the same clock.

-- 
FTTC broadband for 0.8mile line: currently at 10.5Mbps down 400kbps up
according to speedtest.net.

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

* Re: [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
  2015-02-06  0:42           ` Russell King - ARM Linux
@ 2015-02-06  1:35             ` Stephen Boyd
  -1 siblings, 0 replies; 186+ messages in thread
From: Stephen Boyd @ 2015-02-06  1:35 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: Sylwester Nawrocki, Tomeu Vizoso, Paul Walmsley, Tony Lindgren,
	linux-kernel, Mike Turquette, linux-omap,
	Javier Martinez Canillas, linux-arm-kernel

On 02/05/15 16:42, Russell King - ARM Linux wrote:
> On Thu, Feb 05, 2015 at 02:14:01PM -0800, Stephen Boyd wrote:
>> Actually we can bury the __clk_create_clk() inside
>> __of_clk_get_from_provider(). We should also move __clk_get() into there
>> because right now we have a hole where whoever calls
>> of_clk_get_from_provider() never calls __clk_get() on the clk, leading
>> to possible badness. v2 coming soon.
> There's some other issues here too...
>
> sound/soc/kirkwood/kirkwood-i2s.c:
>
>         priv->clk = devm_clk_get(&pdev->dev, np ? "internal" : NULL);
> ...
>         priv->extclk = devm_clk_get(&pdev->dev, "extclk");
>         if (IS_ERR(priv->extclk)) {
> ...
> 	} else {
>                 if (priv->extclk == priv->clk) {
>                         devm_clk_put(&pdev->dev, priv->extclk);
>                         priv->extclk = ERR_PTR(-EINVAL);
>                 } else {
>                         dev_info(&pdev->dev, "found external clock\n");
>                         clk_prepare_enable(priv->extclk);
>                         soc_dai = kirkwood_i2s_dai_extclk;
>                 }
>
> It should be fine provided your "trick" is only done for DT clocks,
> but not for legacy - with legacy, a NULL in the clkdev tables will
> match both these requests, hence the need to compare the clk_get()
> return value to tell whether we get the same clock.
>

Are we still talking about of_clk_get_from_provider()? Or are we talking
about comparing struct clk pointers? From what I can tell this code is
now broken because we made all clk getting functions (there's quite a
few...) return unique pointers every time they're called. It seems that
the driver wants to know if extclk and clk are the same so it can do
something differently in kirkwood_set_rate(). Do we need some sort of
clk_equal(struct clk *a, struct clk *b) function for drivers like this?

Also, even on DT this could fail if the DT author made internal and
extclk map to the same clock provider and cell.

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


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

* [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
@ 2015-02-06  1:35             ` Stephen Boyd
  0 siblings, 0 replies; 186+ messages in thread
From: Stephen Boyd @ 2015-02-06  1:35 UTC (permalink / raw)
  To: linux-arm-kernel

On 02/05/15 16:42, Russell King - ARM Linux wrote:
> On Thu, Feb 05, 2015 at 02:14:01PM -0800, Stephen Boyd wrote:
>> Actually we can bury the __clk_create_clk() inside
>> __of_clk_get_from_provider(). We should also move __clk_get() into there
>> because right now we have a hole where whoever calls
>> of_clk_get_from_provider() never calls __clk_get() on the clk, leading
>> to possible badness. v2 coming soon.
> There's some other issues here too...
>
> sound/soc/kirkwood/kirkwood-i2s.c:
>
>         priv->clk = devm_clk_get(&pdev->dev, np ? "internal" : NULL);
> ...
>         priv->extclk = devm_clk_get(&pdev->dev, "extclk");
>         if (IS_ERR(priv->extclk)) {
> ...
> 	} else {
>                 if (priv->extclk == priv->clk) {
>                         devm_clk_put(&pdev->dev, priv->extclk);
>                         priv->extclk = ERR_PTR(-EINVAL);
>                 } else {
>                         dev_info(&pdev->dev, "found external clock\n");
>                         clk_prepare_enable(priv->extclk);
>                         soc_dai = kirkwood_i2s_dai_extclk;
>                 }
>
> It should be fine provided your "trick" is only done for DT clocks,
> but not for legacy - with legacy, a NULL in the clkdev tables will
> match both these requests, hence the need to compare the clk_get()
> return value to tell whether we get the same clock.
>

Are we still talking about of_clk_get_from_provider()? Or are we talking
about comparing struct clk pointers? From what I can tell this code is
now broken because we made all clk getting functions (there's quite a
few...) return unique pointers every time they're called. It seems that
the driver wants to know if extclk and clk are the same so it can do
something differently in kirkwood_set_rate(). Do we need some sort of
clk_equal(struct clk *a, struct clk *b) function for drivers like this?

Also, even on DT this could fail if the DT author made internal and
extclk map to the same clock provider and cell.

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

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

* Re: [Cocci] [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
  2015-02-05 16:02                     ` Quentin Lambert
  (?)
@ 2015-02-06  1:49                       ` Stephen Boyd
  -1 siblings, 0 replies; 186+ messages in thread
From: Stephen Boyd @ 2015-02-06  1:49 UTC (permalink / raw)
  To: Quentin Lambert, Mike Turquette, Julia Lawall
  Cc: Paul Walmsley, Tomeu Vizoso, Tony Lindgren, linux-kernel,
	t-kristo, linux-omap, cocci, linux-arm-kernel

On 02/05/15 08:02, Quentin Lambert wrote:
> Sorry let me do that properly.
>
> On 05/02/2015 16:45, Quentin Lambert wrote:
>>
>> On 05/02/2015 00:26, Stephen Boyd wrote:
>>>> If you want me to I can enlarge the search to other directories.
>>> Yes please do. And if you could share the coccinelle patch that
>>> would be
>>> great. Thanks.
>>>
>> structclk.cocci is the coccinelle patch
>> structclk-arm.patch is the result I got when applying it to the
>> arch/arm directory
>>
>> Is there anything else I can do to help?
>>
>>
>
> These are the new instances I found by applying the patch to arch/arm
> directory:
>
> ./arch/arm/mach-imx/mach-imx6q.c
> @@ -211,7 +211,6 @@ static void __init imx6q_1588_init(void)
>       * set bit IOMUXC_GPR1[21].  Or the PTP clock must be from pad
>       * (external OSC), and we need to clear the bit.
>       */
>      clksel = ptp_clk == enet_ref ? IMX6Q_GPR1_ENET_CLK_SEL_ANATOP :
>                         IMX6Q_GPR1_ENET_CLK_SEL_PAD;
>      gpr = syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
>      if (!IS_ERR(gpr))

This one looks like a real problem and it could probably use a
clk_equal(struct clk *a, struct clk *b) function.

>
> ./arch/arm/mach-shmobile/clock-r8a73a4.c
> @@ -139,7 +139,6 @@ static int pll_set_parent(struct clk *cl
>
>      /* Search the parent */
>      for (i = 0; i < clk->parent_num; i++)
>          if (clk->parent_table[i] == parent)
>              break;
>
>      if (i == clk->parent_num)
>
> ./arch/arm/mach-shmobile/clock-sh7372.c
> @@ -223,7 +223,6 @@ static int pllc2_set_parent(struct clk *
>
>      /* Search the parent */
>      for (i = 0; i < clk->parent_num; i++)
>          if (clk->parent_table[i] == parent)
>              break;
>
>      if (i == clk->parent_num)
>
> ./arch/arm/mach-shmobile/clock-r8a7740.c
> @@ -195,7 +195,6 @@ static int usb24s_set_parent(struct clk
>
>      /* Search the parent */
>      for (i = 0; i < clk->parent_num; i++)
>          if (clk->parent_table[i] == parent)
>              break;
>
>      if (i == clk->parent_num)
>
>
>

I don't think shmobile uses the CCF so this should be safe, but we
should probably fix them up to also use a clk_equal() function that just
does pointer comparisons.

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


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

* [Cocci] [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
@ 2015-02-06  1:49                       ` Stephen Boyd
  0 siblings, 0 replies; 186+ messages in thread
From: Stephen Boyd @ 2015-02-06  1:49 UTC (permalink / raw)
  To: cocci

On 02/05/15 08:02, Quentin Lambert wrote:
> Sorry let me do that properly.
>
> On 05/02/2015 16:45, Quentin Lambert wrote:
>>
>> On 05/02/2015 00:26, Stephen Boyd wrote:
>>>> If you want me to I can enlarge the search to other directories.
>>> Yes please do. And if you could share the coccinelle patch that
>>> would be
>>> great. Thanks.
>>>
>> structclk.cocci is the coccinelle patch
>> structclk-arm.patch is the result I got when applying it to the
>> arch/arm directory
>>
>> Is there anything else I can do to help?
>>
>>
>
> These are the new instances I found by applying the patch to arch/arm
> directory:
>
> ./arch/arm/mach-imx/mach-imx6q.c
> @@ -211,7 +211,6 @@ static void __init imx6q_1588_init(void)
>       * set bit IOMUXC_GPR1[21].  Or the PTP clock must be from pad
>       * (external OSC), and we need to clear the bit.
>       */
>      clksel = ptp_clk == enet_ref ? IMX6Q_GPR1_ENET_CLK_SEL_ANATOP :
>                         IMX6Q_GPR1_ENET_CLK_SEL_PAD;
>      gpr = syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
>      if (!IS_ERR(gpr))

This one looks like a real problem and it could probably use a
clk_equal(struct clk *a, struct clk *b) function.

>
> ./arch/arm/mach-shmobile/clock-r8a73a4.c
> @@ -139,7 +139,6 @@ static int pll_set_parent(struct clk *cl
>
>      /* Search the parent */
>      for (i = 0; i < clk->parent_num; i++)
>          if (clk->parent_table[i] == parent)
>              break;
>
>      if (i == clk->parent_num)
>
> ./arch/arm/mach-shmobile/clock-sh7372.c
> @@ -223,7 +223,6 @@ static int pllc2_set_parent(struct clk *
>
>      /* Search the parent */
>      for (i = 0; i < clk->parent_num; i++)
>          if (clk->parent_table[i] == parent)
>              break;
>
>      if (i == clk->parent_num)
>
> ./arch/arm/mach-shmobile/clock-r8a7740.c
> @@ -195,7 +195,6 @@ static int usb24s_set_parent(struct clk
>
>      /* Search the parent */
>      for (i = 0; i < clk->parent_num; i++)
>          if (clk->parent_table[i] == parent)
>              break;
>
>      if (i == clk->parent_num)
>
>
>

I don't think shmobile uses the CCF so this should be safe, but we
should probably fix them up to also use a clk_equal() function that just
does pointer comparisons.

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

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

* [Cocci] [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
@ 2015-02-06  1:49                       ` Stephen Boyd
  0 siblings, 0 replies; 186+ messages in thread
From: Stephen Boyd @ 2015-02-06  1:49 UTC (permalink / raw)
  To: linux-arm-kernel

On 02/05/15 08:02, Quentin Lambert wrote:
> Sorry let me do that properly.
>
> On 05/02/2015 16:45, Quentin Lambert wrote:
>>
>> On 05/02/2015 00:26, Stephen Boyd wrote:
>>>> If you want me to I can enlarge the search to other directories.
>>> Yes please do. And if you could share the coccinelle patch that
>>> would be
>>> great. Thanks.
>>>
>> structclk.cocci is the coccinelle patch
>> structclk-arm.patch is the result I got when applying it to the
>> arch/arm directory
>>
>> Is there anything else I can do to help?
>>
>>
>
> These are the new instances I found by applying the patch to arch/arm
> directory:
>
> ./arch/arm/mach-imx/mach-imx6q.c
> @@ -211,7 +211,6 @@ static void __init imx6q_1588_init(void)
>       * set bit IOMUXC_GPR1[21].  Or the PTP clock must be from pad
>       * (external OSC), and we need to clear the bit.
>       */
>      clksel = ptp_clk == enet_ref ? IMX6Q_GPR1_ENET_CLK_SEL_ANATOP :
>                         IMX6Q_GPR1_ENET_CLK_SEL_PAD;
>      gpr = syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
>      if (!IS_ERR(gpr))

This one looks like a real problem and it could probably use a
clk_equal(struct clk *a, struct clk *b) function.

>
> ./arch/arm/mach-shmobile/clock-r8a73a4.c
> @@ -139,7 +139,6 @@ static int pll_set_parent(struct clk *cl
>
>      /* Search the parent */
>      for (i = 0; i < clk->parent_num; i++)
>          if (clk->parent_table[i] == parent)
>              break;
>
>      if (i == clk->parent_num)
>
> ./arch/arm/mach-shmobile/clock-sh7372.c
> @@ -223,7 +223,6 @@ static int pllc2_set_parent(struct clk *
>
>      /* Search the parent */
>      for (i = 0; i < clk->parent_num; i++)
>          if (clk->parent_table[i] == parent)
>              break;
>
>      if (i == clk->parent_num)
>
> ./arch/arm/mach-shmobile/clock-r8a7740.c
> @@ -195,7 +195,6 @@ static int usb24s_set_parent(struct clk
>
>      /* Search the parent */
>      for (i = 0; i < clk->parent_num; i++)
>          if (clk->parent_table[i] == parent)
>              break;
>
>      if (i == clk->parent_num)
>
>
>

I don't think shmobile uses the CCF so this should be safe, but we
should probably fix them up to also use a clk_equal() function that just
does pointer comparisons.

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

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

* Re: [Cocci] [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
  2015-02-05 15:45                   ` Quentin Lambert
  (?)
@ 2015-02-06  2:15                     ` Stephen Boyd
  -1 siblings, 0 replies; 186+ messages in thread
From: Stephen Boyd @ 2015-02-06  2:15 UTC (permalink / raw)
  To: Quentin Lambert, Mike Turquette, Julia Lawall
  Cc: Paul Walmsley, Tomeu Vizoso, Tony Lindgren, linux-kernel,
	t-kristo, linux-omap, cocci, linux-arm-kernel

On 02/05/15 07:45, Quentin Lambert wrote:
>
> On 05/02/2015 00:26, Stephen Boyd wrote:
>>> If you want me to I can enlarge the search to other directories.
>> Yes please do. And if you could share the coccinelle patch that would be
>> great. Thanks.
>>
> structclk.cocci is the coccinelle patch
> structclk-arm.patch is the result I got when applying it to the
> arch/arm directory
>
> Is there anything else I can do to help?
>
>

Thanks for the coccinelle patch. Thinking more about it, I don't think
we care if the pointer is dereferenced because that would require a
definition of struct clk and that is most likely not the case outside of
the clock framework. Did you scan the entire kernel? I'm running it now
but it seems to be taking a while.

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


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

* [Cocci] [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
@ 2015-02-06  2:15                     ` Stephen Boyd
  0 siblings, 0 replies; 186+ messages in thread
From: Stephen Boyd @ 2015-02-06  2:15 UTC (permalink / raw)
  To: cocci

On 02/05/15 07:45, Quentin Lambert wrote:
>
> On 05/02/2015 00:26, Stephen Boyd wrote:
>>> If you want me to I can enlarge the search to other directories.
>> Yes please do. And if you could share the coccinelle patch that would be
>> great. Thanks.
>>
> structclk.cocci is the coccinelle patch
> structclk-arm.patch is the result I got when applying it to the
> arch/arm directory
>
> Is there anything else I can do to help?
>
>

Thanks for the coccinelle patch. Thinking more about it, I don't think
we care if the pointer is dereferenced because that would require a
definition of struct clk and that is most likely not the case outside of
the clock framework. Did you scan the entire kernel? I'm running it now
but it seems to be taking a while.

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

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

* [Cocci] [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
@ 2015-02-06  2:15                     ` Stephen Boyd
  0 siblings, 0 replies; 186+ messages in thread
From: Stephen Boyd @ 2015-02-06  2:15 UTC (permalink / raw)
  To: linux-arm-kernel

On 02/05/15 07:45, Quentin Lambert wrote:
>
> On 05/02/2015 00:26, Stephen Boyd wrote:
>>> If you want me to I can enlarge the search to other directories.
>> Yes please do. And if you could share the coccinelle patch that would be
>> great. Thanks.
>>
> structclk.cocci is the coccinelle patch
> structclk-arm.patch is the result I got when applying it to the
> arch/arm directory
>
> Is there anything else I can do to help?
>
>

Thanks for the coccinelle patch. Thinking more about it, I don't think
we care if the pointer is dereferenced because that would require a
definition of struct clk and that is most likely not the case outside of
the clock framework. Did you scan the entire kernel? I'm running it now
but it seems to be taking a while.

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

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

* Re: [Cocci] [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
  2015-02-06  2:15                     ` Stephen Boyd
  (?)
@ 2015-02-06  9:01                       ` Quentin Lambert
  -1 siblings, 0 replies; 186+ messages in thread
From: Quentin Lambert @ 2015-02-06  9:01 UTC (permalink / raw)
  To: Stephen Boyd, Mike Turquette, Julia Lawall
  Cc: Paul Walmsley, Tomeu Vizoso, Tony Lindgren, linux-kernel,
	t-kristo, linux-omap, cocci, linux-arm-kernel


On 06/02/2015 03:15, Stephen Boyd wrote:
> Thanks for the coccinelle patch. Thinking more about it, I don't think
> we care if the pointer is dereferenced because that would require a
> definition of struct clk and that is most likely not the case outside of
> the clock framework. Did you scan the entire kernel?
No I haven't.
> I'm running it now
> but it seems to be taking a while.
>
Yes, that's why, as a first step, I chose to limit the scan to the arm 
directory.

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

* [Cocci] [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
@ 2015-02-06  9:01                       ` Quentin Lambert
  0 siblings, 0 replies; 186+ messages in thread
From: Quentin Lambert @ 2015-02-06  9:01 UTC (permalink / raw)
  To: cocci


On 06/02/2015 03:15, Stephen Boyd wrote:
> Thanks for the coccinelle patch. Thinking more about it, I don't think
> we care if the pointer is dereferenced because that would require a
> definition of struct clk and that is most likely not the case outside of
> the clock framework. Did you scan the entire kernel?
No I haven't.
> I'm running it now
> but it seems to be taking a while.
>
Yes, that's why, as a first step, I chose to limit the scan to the arm 
directory.

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

* [Cocci] [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
@ 2015-02-06  9:01                       ` Quentin Lambert
  0 siblings, 0 replies; 186+ messages in thread
From: Quentin Lambert @ 2015-02-06  9:01 UTC (permalink / raw)
  To: linux-arm-kernel


On 06/02/2015 03:15, Stephen Boyd wrote:
> Thanks for the coccinelle patch. Thinking more about it, I don't think
> we care if the pointer is dereferenced because that would require a
> definition of struct clk and that is most likely not the case outside of
> the clock framework. Did you scan the entire kernel?
No I haven't.
> I'm running it now
> but it seems to be taking a while.
>
Yes, that's why, as a first step, I chose to limit the scan to the arm 
directory.

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

* Re: [Cocci] [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
  2015-02-06  9:01                       ` Quentin Lambert
  (?)
@ 2015-02-06  9:12                         ` Julia Lawall
  -1 siblings, 0 replies; 186+ messages in thread
From: Julia Lawall @ 2015-02-06  9:12 UTC (permalink / raw)
  To: Quentin Lambert
  Cc: Stephen Boyd, Mike Turquette, Julia Lawall, Paul Walmsley,
	Tomeu Vizoso, Tony Lindgren, linux-kernel, t-kristo, linux-omap,
	cocci, linux-arm-kernel



On Fri, 6 Feb 2015, Quentin Lambert wrote:

>
> On 06/02/2015 03:15, Stephen Boyd wrote:
> > Thanks for the coccinelle patch. Thinking more about it, I don't think
> > we care if the pointer is dereferenced because that would require a
> > definition of struct clk and that is most likely not the case outside of
> > the clock framework. Did you scan the entire kernel?
> No I haven't.
> > I'm running it now
> > but it seems to be taking a while.
> >
> Yes, that's why, as a first step, I chose to limit the scan to the arm
> directory.

Are you sure to be using all of the options provided:

// Options: --recursive-includes --relax-include-path
// Options: --include-headers-for-types

And are you using 1.0.0-rc23 or 1.0.0-rc24?  Those should save parsed
header files so that they don't have to be parsed over and over.

If you are using rc24, then you can use the -j option for parallelism.
But then you should also use an option like --chunksize 10 (I don't know
what number would be good), because the default is chunksize 1, and in
that case the saved parsed header files are not reused, because the fies
are all processed individually.  In general, it is only the files within a
chunk that will share parsed header files.

julia

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

* [Cocci] [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
@ 2015-02-06  9:12                         ` Julia Lawall
  0 siblings, 0 replies; 186+ messages in thread
From: Julia Lawall @ 2015-02-06  9:12 UTC (permalink / raw)
  To: cocci



On Fri, 6 Feb 2015, Quentin Lambert wrote:

>
> On 06/02/2015 03:15, Stephen Boyd wrote:
> > Thanks for the coccinelle patch. Thinking more about it, I don't think
> > we care if the pointer is dereferenced because that would require a
> > definition of struct clk and that is most likely not the case outside of
> > the clock framework. Did you scan the entire kernel?
> No I haven't.
> > I'm running it now
> > but it seems to be taking a while.
> >
> Yes, that's why, as a first step, I chose to limit the scan to the arm
> directory.

Are you sure to be using all of the options provided:

// Options: --recursive-includes --relax-include-path
// Options: --include-headers-for-types

And are you using 1.0.0-rc23 or 1.0.0-rc24?  Those should save parsed
header files so that they don't have to be parsed over and over.

If you are using rc24, then you can use the -j option for parallelism.
But then you should also use an option like --chunksize 10 (I don't know
what number would be good), because the default is chunksize 1, and in
that case the saved parsed header files are not reused, because the fies
are all processed individually.  In general, it is only the files within a
chunk that will share parsed header files.

julia

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

* [Cocci] [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
@ 2015-02-06  9:12                         ` Julia Lawall
  0 siblings, 0 replies; 186+ messages in thread
From: Julia Lawall @ 2015-02-06  9:12 UTC (permalink / raw)
  To: linux-arm-kernel



On Fri, 6 Feb 2015, Quentin Lambert wrote:

>
> On 06/02/2015 03:15, Stephen Boyd wrote:
> > Thanks for the coccinelle patch. Thinking more about it, I don't think
> > we care if the pointer is dereferenced because that would require a
> > definition of struct clk and that is most likely not the case outside of
> > the clock framework. Did you scan the entire kernel?
> No I haven't.
> > I'm running it now
> > but it seems to be taking a while.
> >
> Yes, that's why, as a first step, I chose to limit the scan to the arm
> directory.

Are you sure to be using all of the options provided:

// Options: --recursive-includes --relax-include-path
// Options: --include-headers-for-types

And are you using 1.0.0-rc23 or 1.0.0-rc24?  Those should save parsed
header files so that they don't have to be parsed over and over.

If you are using rc24, then you can use the -j option for parallelism.
But then you should also use an option like --chunksize 10 (I don't know
what number would be good), because the default is chunksize 1, and in
that case the saved parsed header files are not reused, because the fies
are all processed individually.  In general, it is only the files within a
chunk that will share parsed header files.

julia

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

* Re: [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
  2015-02-06  1:35             ` Stephen Boyd
@ 2015-02-06 13:39               ` Russell King - ARM Linux
  -1 siblings, 0 replies; 186+ messages in thread
From: Russell King - ARM Linux @ 2015-02-06 13:39 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Sylwester Nawrocki, Tomeu Vizoso, Paul Walmsley, Tony Lindgren,
	linux-kernel, Mike Turquette, linux-omap,
	Javier Martinez Canillas, linux-arm-kernel

On Thu, Feb 05, 2015 at 05:35:28PM -0800, Stephen Boyd wrote:
> On 02/05/15 16:42, Russell King - ARM Linux wrote:
> > On Thu, Feb 05, 2015 at 02:14:01PM -0800, Stephen Boyd wrote:
> >> Actually we can bury the __clk_create_clk() inside
> >> __of_clk_get_from_provider(). We should also move __clk_get() into there
> >> because right now we have a hole where whoever calls
> >> of_clk_get_from_provider() never calls __clk_get() on the clk, leading
> >> to possible badness. v2 coming soon.
> > There's some other issues here too...
> >
> > sound/soc/kirkwood/kirkwood-i2s.c:
> >
> >         priv->clk = devm_clk_get(&pdev->dev, np ? "internal" : NULL);
> > ...
> >         priv->extclk = devm_clk_get(&pdev->dev, "extclk");
> >         if (IS_ERR(priv->extclk)) {
> > ...
> > 	} else {
> >                 if (priv->extclk == priv->clk) {
> >                         devm_clk_put(&pdev->dev, priv->extclk);
> >                         priv->extclk = ERR_PTR(-EINVAL);
> >                 } else {
> >                         dev_info(&pdev->dev, "found external clock\n");
> >                         clk_prepare_enable(priv->extclk);
> >                         soc_dai = kirkwood_i2s_dai_extclk;
> >                 }
> >
> > It should be fine provided your "trick" is only done for DT clocks,
> > but not for legacy - with legacy, a NULL in the clkdev tables will
> > match both these requests, hence the need to compare the clk_get()
> > return value to tell whether we get the same clock.
> >
> 
> Are we still talking about of_clk_get_from_provider()? Or are we talking
> about comparing struct clk pointers?

Comparing struct clk pointers, and the implications of the patch changing
the clk_get() et.al. to be unique struct clk pointers.

> From what I can tell this code is
> now broken because we made all clk getting functions (there's quite a
> few...) return unique pointers every time they're called. It seems that
> the driver wants to know if extclk and clk are the same so it can do
> something differently in kirkwood_set_rate(). Do we need some sort of
> clk_equal(struct clk *a, struct clk *b) function for drivers like this?

Well, the clocks in question are the SoC internal clock (which is more or
less fixed, but has a programmable divider) and an externally supplied
clock, and the IP has a multiplexer on its input which allows us to select
between those two sources.

If it were possible to bind both to the same clock, it wouldn't be a
useful configuration - nothing would be gained from doing so in terms of
available rates.

What the comparison is there for is to catch the case with legacy lookups
where a clkdev lookup entry with a NULL connection ID results in matching
any connection ID passed to clk_get().  If the patch changes this, then
we will have a regression - and this is something which needs fixing
_before_ we do this "return unique clocks".

-- 
FTTC broadband for 0.8mile line: currently at 10.5Mbps down 400kbps up
according to speedtest.net.

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

* [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
@ 2015-02-06 13:39               ` Russell King - ARM Linux
  0 siblings, 0 replies; 186+ messages in thread
From: Russell King - ARM Linux @ 2015-02-06 13:39 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Feb 05, 2015 at 05:35:28PM -0800, Stephen Boyd wrote:
> On 02/05/15 16:42, Russell King - ARM Linux wrote:
> > On Thu, Feb 05, 2015 at 02:14:01PM -0800, Stephen Boyd wrote:
> >> Actually we can bury the __clk_create_clk() inside
> >> __of_clk_get_from_provider(). We should also move __clk_get() into there
> >> because right now we have a hole where whoever calls
> >> of_clk_get_from_provider() never calls __clk_get() on the clk, leading
> >> to possible badness. v2 coming soon.
> > There's some other issues here too...
> >
> > sound/soc/kirkwood/kirkwood-i2s.c:
> >
> >         priv->clk = devm_clk_get(&pdev->dev, np ? "internal" : NULL);
> > ...
> >         priv->extclk = devm_clk_get(&pdev->dev, "extclk");
> >         if (IS_ERR(priv->extclk)) {
> > ...
> > 	} else {
> >                 if (priv->extclk == priv->clk) {
> >                         devm_clk_put(&pdev->dev, priv->extclk);
> >                         priv->extclk = ERR_PTR(-EINVAL);
> >                 } else {
> >                         dev_info(&pdev->dev, "found external clock\n");
> >                         clk_prepare_enable(priv->extclk);
> >                         soc_dai = kirkwood_i2s_dai_extclk;
> >                 }
> >
> > It should be fine provided your "trick" is only done for DT clocks,
> > but not for legacy - with legacy, a NULL in the clkdev tables will
> > match both these requests, hence the need to compare the clk_get()
> > return value to tell whether we get the same clock.
> >
> 
> Are we still talking about of_clk_get_from_provider()? Or are we talking
> about comparing struct clk pointers?

Comparing struct clk pointers, and the implications of the patch changing
the clk_get() et.al. to be unique struct clk pointers.

> From what I can tell this code is
> now broken because we made all clk getting functions (there's quite a
> few...) return unique pointers every time they're called. It seems that
> the driver wants to know if extclk and clk are the same so it can do
> something differently in kirkwood_set_rate(). Do we need some sort of
> clk_equal(struct clk *a, struct clk *b) function for drivers like this?

Well, the clocks in question are the SoC internal clock (which is more or
less fixed, but has a programmable divider) and an externally supplied
clock, and the IP has a multiplexer on its input which allows us to select
between those two sources.

If it were possible to bind both to the same clock, it wouldn't be a
useful configuration - nothing would be gained from doing so in terms of
available rates.

What the comparison is there for is to catch the case with legacy lookups
where a clkdev lookup entry with a NULL connection ID results in matching
any connection ID passed to clk_get().  If the patch changes this, then
we will have a regression - and this is something which needs fixing
_before_ we do this "return unique clocks".

-- 
FTTC broadband for 0.8mile line: currently at 10.5Mbps down 400kbps up
according to speedtest.net.

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

* Re: [Cocci] [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
  2015-02-06  9:12                         ` Julia Lawall
  (?)
@ 2015-02-06 17:15                           ` Stephen Boyd
  -1 siblings, 0 replies; 186+ messages in thread
From: Stephen Boyd @ 2015-02-06 17:15 UTC (permalink / raw)
  To: Julia Lawall, Quentin Lambert
  Cc: Mike Turquette, Paul Walmsley, Tomeu Vizoso, Tony Lindgren,
	linux-kernel, t-kristo, linux-omap, cocci, linux-arm-kernel

On 02/06/15 01:12, Julia Lawall wrote:
>
> On Fri, 6 Feb 2015, Quentin Lambert wrote:
>
>> On 06/02/2015 03:15, Stephen Boyd wrote:
>>> Thanks for the coccinelle patch. Thinking more about it, I don't think
>>> we care if the pointer is dereferenced because that would require a
>>> definition of struct clk and that is most likely not the case outside of
>>> the clock framework. Did you scan the entire kernel?
>> No I haven't.
>>> I'm running it now
>>> but it seems to be taking a while.
>>>
>> Yes, that's why, as a first step, I chose to limit the scan to the arm
>> directory.
> Are you sure to be using all of the options provided:
>
> // Options: --recursive-includes --relax-include-path
> // Options: --include-headers-for-types
>
> And are you using 1.0.0-rc23 or 1.0.0-rc24?  Those should save parsed
> header files so that they don't have to be parsed over and over.
>
> If you are using rc24, then you can use the -j option for parallelism.
> But then you should also use an option like --chunksize 10 (I don't know
> what number would be good), because the default is chunksize 1, and in
> that case the saved parsed header files are not reused, because the fies
> are all processed individually.  In general, it is only the files within a
> chunk that will share parsed header files.

Thanks for the info.

$ spatch --version
spatch version 1.0.0-rc22 with Python support and with PCRE support

so I guess I need to update. I tried throwing it into
scripts/coccinelle/misc and then did

make O=../obj/ coccicheck
COCCI=../kernel/scripts/coccinelle/misc/structclk.cocci

at the toplevel but it didn't find anything.

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


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

* [Cocci] [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
@ 2015-02-06 17:15                           ` Stephen Boyd
  0 siblings, 0 replies; 186+ messages in thread
From: Stephen Boyd @ 2015-02-06 17:15 UTC (permalink / raw)
  To: cocci

On 02/06/15 01:12, Julia Lawall wrote:
>
> On Fri, 6 Feb 2015, Quentin Lambert wrote:
>
>> On 06/02/2015 03:15, Stephen Boyd wrote:
>>> Thanks for the coccinelle patch. Thinking more about it, I don't think
>>> we care if the pointer is dereferenced because that would require a
>>> definition of struct clk and that is most likely not the case outside of
>>> the clock framework. Did you scan the entire kernel?
>> No I haven't.
>>> I'm running it now
>>> but it seems to be taking a while.
>>>
>> Yes, that's why, as a first step, I chose to limit the scan to the arm
>> directory.
> Are you sure to be using all of the options provided:
>
> // Options: --recursive-includes --relax-include-path
> // Options: --include-headers-for-types
>
> And are you using 1.0.0-rc23 or 1.0.0-rc24?  Those should save parsed
> header files so that they don't have to be parsed over and over.
>
> If you are using rc24, then you can use the -j option for parallelism.
> But then you should also use an option like --chunksize 10 (I don't know
> what number would be good), because the default is chunksize 1, and in
> that case the saved parsed header files are not reused, because the fies
> are all processed individually.  In general, it is only the files within a
> chunk that will share parsed header files.

Thanks for the info.

$ spatch --version
spatch version 1.0.0-rc22 with Python support and with PCRE support

so I guess I need to update. I tried throwing it into
scripts/coccinelle/misc and then did

make O=../obj/ coccicheck
COCCI=../kernel/scripts/coccinelle/misc/structclk.cocci

at the toplevel but it didn't find anything.

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

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

* [Cocci] [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
@ 2015-02-06 17:15                           ` Stephen Boyd
  0 siblings, 0 replies; 186+ messages in thread
From: Stephen Boyd @ 2015-02-06 17:15 UTC (permalink / raw)
  To: linux-arm-kernel

On 02/06/15 01:12, Julia Lawall wrote:
>
> On Fri, 6 Feb 2015, Quentin Lambert wrote:
>
>> On 06/02/2015 03:15, Stephen Boyd wrote:
>>> Thanks for the coccinelle patch. Thinking more about it, I don't think
>>> we care if the pointer is dereferenced because that would require a
>>> definition of struct clk and that is most likely not the case outside of
>>> the clock framework. Did you scan the entire kernel?
>> No I haven't.
>>> I'm running it now
>>> but it seems to be taking a while.
>>>
>> Yes, that's why, as a first step, I chose to limit the scan to the arm
>> directory.
> Are you sure to be using all of the options provided:
>
> // Options: --recursive-includes --relax-include-path
> // Options: --include-headers-for-types
>
> And are you using 1.0.0-rc23 or 1.0.0-rc24?  Those should save parsed
> header files so that they don't have to be parsed over and over.
>
> If you are using rc24, then you can use the -j option for parallelism.
> But then you should also use an option like --chunksize 10 (I don't know
> what number would be good), because the default is chunksize 1, and in
> that case the saved parsed header files are not reused, because the fies
> are all processed individually.  In general, it is only the files within a
> chunk that will share parsed header files.

Thanks for the info.

$ spatch --version
spatch version 1.0.0-rc22 with Python support and with PCRE support

so I guess I need to update. I tried throwing it into
scripts/coccinelle/misc and then did

make O=../obj/ coccicheck
COCCI=../kernel/scripts/coccinelle/misc/structclk.cocci

at the toplevel but it didn't find anything.

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

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

* Re: [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
  2015-02-06 13:39               ` Russell King - ARM Linux
@ 2015-02-06 19:30                 ` Stephen Boyd
  -1 siblings, 0 replies; 186+ messages in thread
From: Stephen Boyd @ 2015-02-06 19:30 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: Sylwester Nawrocki, Tomeu Vizoso, Paul Walmsley, Tony Lindgren,
	linux-kernel, Mike Turquette, linux-omap,
	Javier Martinez Canillas, linux-arm-kernel

On 02/06/15 05:39, Russell King - ARM Linux wrote:
> On Thu, Feb 05, 2015 at 05:35:28PM -0800, Stephen Boyd wrote:
>
>> From what I can tell this code is
>> now broken because we made all clk getting functions (there's quite a
>> few...) return unique pointers every time they're called. It seems that
>> the driver wants to know if extclk and clk are the same so it can do
>> something differently in kirkwood_set_rate(). Do we need some sort of
>> clk_equal(struct clk *a, struct clk *b) function for drivers like this?
> Well, the clocks in question are the SoC internal clock (which is more or
> less fixed, but has a programmable divider) and an externally supplied
> clock, and the IP has a multiplexer on its input which allows us to select
> between those two sources.
>
> If it were possible to bind both to the same clock, it wouldn't be a
> useful configuration - nothing would be gained from doing so in terms of
> available rates.
>
> What the comparison is there for is to catch the case with legacy lookups
> where a clkdev lookup entry with a NULL connection ID results in matching
> any connection ID passed to clk_get().  If the patch changes this, then
> we will have a regression - and this is something which needs fixing
> _before_ we do this "return unique clocks".
>

Ok. It seems that we might need a clk_equal() or similar API after all.
My understanding is that this driver is calling clk_get() twice with
NULL for the con_id and then "extclk" in attempts to get the SoC
internal clock and the externally supplied clock. If we're using legacy
lookups then both clk_get() calls may map to the same clk_lookup entry
and before Tomeu's patch that returns unique clocks the driver could
detect this case and know that there isn't an external clock. Looking at
arch/arm/mach-dove/common.c it seems that there is only one lookup per
device and it has a wildcard NULL for con_id so both clk_get() calls
here are going to find the same lookup and get a unique struct clk pointer.

Why don't we make the legacy lookup more specific and actually indicate
"internal" for the con_id? Then the external clock would fail to be
found, but we can detect that case and figure out that it's not due to
probe defer, but instead due to the fact that there really isn't any
mapping. It looks like the code is already prepared for this anyway.

----8<----

From: Stephen Boyd <sboyd@codeaurora.org>
Subject: [PATCH] ARM: dove: Remove wildcard from mvebu-audio device clk lookup

This i2s driver is using the wildcard nature of clkdev lookups to
figure out if there's an external clock or not. It does this by
calling clk_get() twice with NULL for the con_id first and then
"external" for the con_id the second time around and then
compares the two pointers. With DT the wildcard feature of
clk_get() is gone and so the driver has to handle an error from
the second clk_get() call as meaning "no external clock
specified". Let's use that logic even with clk lookups to
simplify the code and remove the struct clk pointer comparisons
which may not work in the future when clk_get() returns unique
pointers.

Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 arch/arm/mach-dove/common.c       |  4 ++--
 sound/soc/kirkwood/kirkwood-i2s.c | 13 ++++---------
 2 files changed, 6 insertions(+), 11 deletions(-)

diff --git a/arch/arm/mach-dove/common.c b/arch/arm/mach-dove/common.c
index 0d1a89298ece..f290fc944cc1 100644
--- a/arch/arm/mach-dove/common.c
+++ b/arch/arm/mach-dove/common.c
@@ -124,8 +124,8 @@ static void __init dove_clk_init(void)
 	orion_clkdev_add(NULL, "sdhci-dove.1", sdio1);
 	orion_clkdev_add(NULL, "orion_nand", nand);
 	orion_clkdev_add(NULL, "cafe1000-ccic.0", camera);
-	orion_clkdev_add(NULL, "mvebu-audio.0", i2s0);
-	orion_clkdev_add(NULL, "mvebu-audio.1", i2s1);
+	orion_clkdev_add("internal", "mvebu-audio.0", i2s0);
+	orion_clkdev_add("internal", "mvebu-audio.1", i2s1);
 	orion_clkdev_add(NULL, "mv_crypto", crypto);
 	orion_clkdev_add(NULL, "dove-ac97", ac97);
 	orion_clkdev_add(NULL, "dove-pdma", pdma);
diff --git a/sound/soc/kirkwood/kirkwood-i2s.c b/sound/soc/kirkwood/kirkwood-i2s.c
index def7d8260c4e..0bfeb712a997 100644
--- a/sound/soc/kirkwood/kirkwood-i2s.c
+++ b/sound/soc/kirkwood/kirkwood-i2s.c
@@ -564,7 +564,7 @@ static int kirkwood_i2s_dev_probe(struct platform_device *pdev)
 		return -EINVAL;
 	}
 
-	priv->clk = devm_clk_get(&pdev->dev, np ? "internal" : NULL);
+	priv->clk = devm_clk_get(&pdev->dev, "internal");
 	if (IS_ERR(priv->clk)) {
 		dev_err(&pdev->dev, "no clock\n");
 		return PTR_ERR(priv->clk);
@@ -579,14 +579,9 @@ static int kirkwood_i2s_dev_probe(struct platform_device *pdev)
 		if (PTR_ERR(priv->extclk) == -EPROBE_DEFER)
 			return -EPROBE_DEFER;
 	} else {
-		if (priv->extclk == priv->clk) {
-			devm_clk_put(&pdev->dev, priv->extclk);
-			priv->extclk = ERR_PTR(-EINVAL);
-		} else {
-			dev_info(&pdev->dev, "found external clock\n");
-			clk_prepare_enable(priv->extclk);
-			soc_dai = kirkwood_i2s_dai_extclk;
-		}
+		dev_info(&pdev->dev, "found external clock\n");
+		clk_prepare_enable(priv->extclk);
+		soc_dai = kirkwood_i2s_dai_extclk;
 	}
 
 	/* Some sensible defaults - this reflects the powerup values */

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


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

* [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
@ 2015-02-06 19:30                 ` Stephen Boyd
  0 siblings, 0 replies; 186+ messages in thread
From: Stephen Boyd @ 2015-02-06 19:30 UTC (permalink / raw)
  To: linux-arm-kernel

On 02/06/15 05:39, Russell King - ARM Linux wrote:
> On Thu, Feb 05, 2015 at 05:35:28PM -0800, Stephen Boyd wrote:
>
>> From what I can tell this code is
>> now broken because we made all clk getting functions (there's quite a
>> few...) return unique pointers every time they're called. It seems that
>> the driver wants to know if extclk and clk are the same so it can do
>> something differently in kirkwood_set_rate(). Do we need some sort of
>> clk_equal(struct clk *a, struct clk *b) function for drivers like this?
> Well, the clocks in question are the SoC internal clock (which is more or
> less fixed, but has a programmable divider) and an externally supplied
> clock, and the IP has a multiplexer on its input which allows us to select
> between those two sources.
>
> If it were possible to bind both to the same clock, it wouldn't be a
> useful configuration - nothing would be gained from doing so in terms of
> available rates.
>
> What the comparison is there for is to catch the case with legacy lookups
> where a clkdev lookup entry with a NULL connection ID results in matching
> any connection ID passed to clk_get().  If the patch changes this, then
> we will have a regression - and this is something which needs fixing
> _before_ we do this "return unique clocks".
>

Ok. It seems that we might need a clk_equal() or similar API after all.
My understanding is that this driver is calling clk_get() twice with
NULL for the con_id and then "extclk" in attempts to get the SoC
internal clock and the externally supplied clock. If we're using legacy
lookups then both clk_get() calls may map to the same clk_lookup entry
and before Tomeu's patch that returns unique clocks the driver could
detect this case and know that there isn't an external clock. Looking at
arch/arm/mach-dove/common.c it seems that there is only one lookup per
device and it has a wildcard NULL for con_id so both clk_get() calls
here are going to find the same lookup and get a unique struct clk pointer.

Why don't we make the legacy lookup more specific and actually indicate
"internal" for the con_id? Then the external clock would fail to be
found, but we can detect that case and figure out that it's not due to
probe defer, but instead due to the fact that there really isn't any
mapping. It looks like the code is already prepared for this anyway.

----8<----

From: Stephen Boyd <sboyd@codeaurora.org>
Subject: [PATCH] ARM: dove: Remove wildcard from mvebu-audio device clk lookup

This i2s driver is using the wildcard nature of clkdev lookups to
figure out if there's an external clock or not. It does this by
calling clk_get() twice with NULL for the con_id first and then
"external" for the con_id the second time around and then
compares the two pointers. With DT the wildcard feature of
clk_get() is gone and so the driver has to handle an error from
the second clk_get() call as meaning "no external clock
specified". Let's use that logic even with clk lookups to
simplify the code and remove the struct clk pointer comparisons
which may not work in the future when clk_get() returns unique
pointers.

Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 arch/arm/mach-dove/common.c       |  4 ++--
 sound/soc/kirkwood/kirkwood-i2s.c | 13 ++++---------
 2 files changed, 6 insertions(+), 11 deletions(-)

diff --git a/arch/arm/mach-dove/common.c b/arch/arm/mach-dove/common.c
index 0d1a89298ece..f290fc944cc1 100644
--- a/arch/arm/mach-dove/common.c
+++ b/arch/arm/mach-dove/common.c
@@ -124,8 +124,8 @@ static void __init dove_clk_init(void)
 	orion_clkdev_add(NULL, "sdhci-dove.1", sdio1);
 	orion_clkdev_add(NULL, "orion_nand", nand);
 	orion_clkdev_add(NULL, "cafe1000-ccic.0", camera);
-	orion_clkdev_add(NULL, "mvebu-audio.0", i2s0);
-	orion_clkdev_add(NULL, "mvebu-audio.1", i2s1);
+	orion_clkdev_add("internal", "mvebu-audio.0", i2s0);
+	orion_clkdev_add("internal", "mvebu-audio.1", i2s1);
 	orion_clkdev_add(NULL, "mv_crypto", crypto);
 	orion_clkdev_add(NULL, "dove-ac97", ac97);
 	orion_clkdev_add(NULL, "dove-pdma", pdma);
diff --git a/sound/soc/kirkwood/kirkwood-i2s.c b/sound/soc/kirkwood/kirkwood-i2s.c
index def7d8260c4e..0bfeb712a997 100644
--- a/sound/soc/kirkwood/kirkwood-i2s.c
+++ b/sound/soc/kirkwood/kirkwood-i2s.c
@@ -564,7 +564,7 @@ static int kirkwood_i2s_dev_probe(struct platform_device *pdev)
 		return -EINVAL;
 	}
 
-	priv->clk = devm_clk_get(&pdev->dev, np ? "internal" : NULL);
+	priv->clk = devm_clk_get(&pdev->dev, "internal");
 	if (IS_ERR(priv->clk)) {
 		dev_err(&pdev->dev, "no clock\n");
 		return PTR_ERR(priv->clk);
@@ -579,14 +579,9 @@ static int kirkwood_i2s_dev_probe(struct platform_device *pdev)
 		if (PTR_ERR(priv->extclk) == -EPROBE_DEFER)
 			return -EPROBE_DEFER;
 	} else {
-		if (priv->extclk == priv->clk) {
-			devm_clk_put(&pdev->dev, priv->extclk);
-			priv->extclk = ERR_PTR(-EINVAL);
-		} else {
-			dev_info(&pdev->dev, "found external clock\n");
-			clk_prepare_enable(priv->extclk);
-			soc_dai = kirkwood_i2s_dai_extclk;
-		}
+		dev_info(&pdev->dev, "found external clock\n");
+		clk_prepare_enable(priv->extclk);
+		soc_dai = kirkwood_i2s_dai_extclk;
 	}
 
 	/* Some sensible defaults - this reflects the powerup values */

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

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

* Re: [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
  2015-02-06 19:30                 ` Stephen Boyd
@ 2015-02-06 19:37                   ` Russell King - ARM Linux
  -1 siblings, 0 replies; 186+ messages in thread
From: Russell King - ARM Linux @ 2015-02-06 19:37 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Sylwester Nawrocki, Tomeu Vizoso, Paul Walmsley, Tony Lindgren,
	linux-kernel, Mike Turquette, linux-omap,
	Javier Martinez Canillas, linux-arm-kernel

On Fri, Feb 06, 2015 at 11:30:18AM -0800, Stephen Boyd wrote:
> Why don't we make the legacy lookup more specific and actually indicate
> "internal" for the con_id? Then the external clock would fail to be
> found, but we can detect that case and figure out that it's not due to
> probe defer, but instead due to the fact that there really isn't any
> mapping. It looks like the code is already prepared for this anyway.

We _could_, and that would solve this specific issue, but I'd suggest
coccinelle is used to locate any other similar instances of this.

As I'm allergic to coccinelle (or coccinelle is allergic to me since
I never seem to be able to get it to do what I want...)

-- 
FTTC broadband for 0.8mile line: currently at 10.5Mbps down 400kbps up
according to speedtest.net.

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

* [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
@ 2015-02-06 19:37                   ` Russell King - ARM Linux
  0 siblings, 0 replies; 186+ messages in thread
From: Russell King - ARM Linux @ 2015-02-06 19:37 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Feb 06, 2015 at 11:30:18AM -0800, Stephen Boyd wrote:
> Why don't we make the legacy lookup more specific and actually indicate
> "internal" for the con_id? Then the external clock would fail to be
> found, but we can detect that case and figure out that it's not due to
> probe defer, but instead due to the fact that there really isn't any
> mapping. It looks like the code is already prepared for this anyway.

We _could_, and that would solve this specific issue, but I'd suggest
coccinelle is used to locate any other similar instances of this.

As I'm allergic to coccinelle (or coccinelle is allergic to me since
I never seem to be able to get it to do what I want...)

-- 
FTTC broadband for 0.8mile line: currently at 10.5Mbps down 400kbps up
according to speedtest.net.

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

* Re: [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
  2015-02-06 19:37                   ` Russell King - ARM Linux
@ 2015-02-06 19:41                     ` Stephen Boyd
  -1 siblings, 0 replies; 186+ messages in thread
From: Stephen Boyd @ 2015-02-06 19:41 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: Sylwester Nawrocki, Tomeu Vizoso, Paul Walmsley, Tony Lindgren,
	linux-kernel, Mike Turquette, linux-omap,
	Javier Martinez Canillas, linux-arm-kernel

On 02/06/15 11:37, Russell King - ARM Linux wrote:
> On Fri, Feb 06, 2015 at 11:30:18AM -0800, Stephen Boyd wrote:
>> Why don't we make the legacy lookup more specific and actually indicate
>> "internal" for the con_id? Then the external clock would fail to be
>> found, but we can detect that case and figure out that it's not due to
>> probe defer, but instead due to the fact that there really isn't any
>> mapping. It looks like the code is already prepared for this anyway.
> We _could_, and that would solve this specific issue, but I'd suggest
> coccinelle is used to locate any other similar instances of this.
>
> As I'm allergic to coccinelle (or coccinelle is allergic to me since
> I never seem to be able to get it to do what I want...)
>

Great. I'd like to avoid adding clk_equal() until we actually need it,
and I hope we don't ever need it. We've already got coccinelle in the
works to find similar issues and it seems you and I have the same
allergies because I can't get it to work for me right now.

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


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

* [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
@ 2015-02-06 19:41                     ` Stephen Boyd
  0 siblings, 0 replies; 186+ messages in thread
From: Stephen Boyd @ 2015-02-06 19:41 UTC (permalink / raw)
  To: linux-arm-kernel

On 02/06/15 11:37, Russell King - ARM Linux wrote:
> On Fri, Feb 06, 2015 at 11:30:18AM -0800, Stephen Boyd wrote:
>> Why don't we make the legacy lookup more specific and actually indicate
>> "internal" for the con_id? Then the external clock would fail to be
>> found, but we can detect that case and figure out that it's not due to
>> probe defer, but instead due to the fact that there really isn't any
>> mapping. It looks like the code is already prepared for this anyway.
> We _could_, and that would solve this specific issue, but I'd suggest
> coccinelle is used to locate any other similar instances of this.
>
> As I'm allergic to coccinelle (or coccinelle is allergic to me since
> I never seem to be able to get it to do what I want...)
>

Great. I'd like to avoid adding clk_equal() until we actually need it,
and I hope we don't ever need it. We've already got coccinelle in the
works to find similar issues and it seems you and I have the same
allergies because I can't get it to work for me right now.

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

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

* Re: [Cocci] [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
  2015-02-06  2:15                     ` Stephen Boyd
  (?)
@ 2015-02-17 22:01                       ` Stephen Boyd
  -1 siblings, 0 replies; 186+ messages in thread
From: Stephen Boyd @ 2015-02-17 22:01 UTC (permalink / raw)
  To: Quentin Lambert, Mike Turquette, Julia Lawall
  Cc: Paul Walmsley, Tomeu Vizoso, Tony Lindgren, linux-kernel,
	t-kristo, linux-omap, cocci, linux-arm-kernel

On 02/05/15 18:15, Stephen Boyd wrote:
> On 02/05/15 07:45, Quentin Lambert wrote:
>> On 05/02/2015 00:26, Stephen Boyd wrote:
>>>> If you want me to I can enlarge the search to other directories.
>>> Yes please do. And if you could share the coccinelle patch that would be
>>> great. Thanks.
>>>
>> structclk.cocci is the coccinelle patch
>> structclk-arm.patch is the result I got when applying it to the
>> arch/arm directory
>>
>> Is there anything else I can do to help?
>>
>>
> Thanks for the coccinelle patch. Thinking more about it, I don't think
> we care if the pointer is dereferenced because that would require a
> definition of struct clk and that is most likely not the case outside of
> the clock framework. Did you scan the entire kernel? I'm running it now
> but it seems to be taking a while.
>

I ran the script on all files that include <linux/clk.h>. I've also
trimmed out mips and unicore32 because they're not using the common
clock framework.

diff = 
--- arch/arm/mach-imx/mach-imx6q.c
+++ /tmp/cocci-output-11792-b62223-mach-imx6q.c
@@ -211,7 +211,6 @@ static void __init imx6q_1588_init(void)
 	 * set bit IOMUXC_GPR1[21].  Or the PTP clock must be from pad
 	 * (external OSC), and we need to clear the bit.
 	 */
-	clksel = ptp_clk == enet_ref ? IMX6Q_GPR1_ENET_CLK_SEL_ANATOP :
 				       IMX6Q_GPR1_ENET_CLK_SEL_PAD;
 	gpr = syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
 	if (!IS_ERR(gpr))
diff = 
--- drivers/gpu/drm/armada/armada_510.c
+++ /tmp/cocci-output-12321-a5f298-armada_510.c
@@ -53,7 +53,6 @@ static int armada510_crtc_compute_clock(
 	if (IS_ERR(clk))
 		return PTR_ERR(clk);
 
-	if (dcrtc->clk != clk) {
 		ret = clk_prepare_enable(clk);
 		if (ret)
 			return ret;
drivers/gpu/drm/armada/armada_510.c:56:5-15: WARNING trying to compare or dereference struct clk pointers.
diff = 
--- drivers/pwm/pwm-atmel-hlcdc.c
+++ /tmp/cocci-output-12679-3c5195-pwm-atmel-hlcdc.c
@@ -91,7 +91,6 @@ static int atmel_hlcdc_pwm_config(struct
 
 	pwmcfg = ATMEL_HLCDC_PWMPS(pres);
 
-	if (new_clk != chip->cur_clk) {
 		u32 gencfg = 0;
 		int ret;
 
drivers/pwm/pwm-atmel-hlcdc.c:94:5-12: WARNING trying to compare or dereference struct clk pointers.
diff = 
--- drivers/tty/serial/samsung.c
+++ /tmp/cocci-output-12827-715e72-samsung.c
@@ -750,7 +750,6 @@ static void s3c24xx_serial_set_termios(s
 
 	/* check to see if we need  to change clock source */
 
-	if (ourport->baudclk != clk) {
 		s3c24xx_serial_setsource(port, clk_sel);
 
 		if (!IS_ERR(ourport->baudclk)) {
drivers/tty/serial/samsung.c:753:5-21: WARNING trying to compare or dereference struct clk pointers.
diff = 
--- sound/soc/fsl/fsl_esai.c
+++ /tmp/cocci-output-13020-d518c3-fsl_esai.c
@@ -269,7 +269,6 @@ static int fsl_esai_set_dai_sysclk(struc
 	}
 
 	/* Only EXTAL source can be output directly without using PSR and PM */
-	if (ratio == 1 && clksrc == esai_priv->extalclk) {
 		/* Bypass all the dividers if not being needed */
 		ecr |= tx ? ESAI_ECR_ETO : ESAI_ECR_ERO;
 		goto out;
sound/soc/fsl/fsl_esai.c:272:19-25: WARNING trying to compare or dereference struct clk pointers.
diff = 
--- sound/soc/fsl/fsl_spdif.c
+++ /tmp/cocci-output-13024-7acb1d-fsl_spdif.c
@@ -1054,7 +1054,6 @@ static u32 fsl_spdif_txclk_caldiv(struct
 				enum spdif_txrate index, bool round)
 {
 	const u32 rate[] = { 32000, 44100, 48000, 96000, 192000 };
-	bool is_sysclk = clk == spdif_priv->sysclk;
 	u64 rate_ideal, rate_actual, sub;
 	u32 sysclk_dfmin, sysclk_dfmax;
 	u32 txclk_df, sysclk_df, arate;
@@ -1148,7 +1147,6 @@ static int fsl_spdif_probe_txclk(struct
 			spdif_priv->txclk_src[index], rate[index]);
 	dev_dbg(&pdev->dev, "use txclk df %d for %dHz sample rate\n",
 			spdif_priv->txclk_df[index], rate[index]);
-	if (spdif_priv->txclk[index] == spdif_priv->sysclk)
 		dev_dbg(&pdev->dev, "use sysclk df %d for %dHz sample rate\n",
 				spdif_priv->sysclk_df[index], rate[index]);
 	dev_dbg(&pdev->dev, "the best rate for %dHz sample rate is %dHz\n",
sound/soc/fsl/fsl_spdif.c:1151:5-29: WARNING trying to compare or dereference struct clk pointers.
sound/soc/fsl/fsl_spdif.c:1057:18-21: WARNING trying to compare or dereference struct clk pointers.
diff = 
--- sound/soc/kirkwood/kirkwood-i2s.c
+++ /tmp/cocci-output-13041-3200a6-kirkwood-i2s.c
@@ -579,7 +579,6 @@ static int kirkwood_i2s_dev_probe(struct
 		if (PTR_ERR(priv->extclk) == -EPROBE_DEFER)
 			return -EPROBE_DEFER;
 	} else {
-		if (priv->extclk == priv->clk) {
 			devm_clk_put(&pdev->dev, priv->extclk);
 			priv->extclk = ERR_PTR(-EINVAL);
 		} else {
sound/soc/kirkwood/kirkwood-i2s.c:582:6-18: WARNING trying to compare or dereference struct clk pointers.


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


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

* [Cocci] [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
@ 2015-02-17 22:01                       ` Stephen Boyd
  0 siblings, 0 replies; 186+ messages in thread
From: Stephen Boyd @ 2015-02-17 22:01 UTC (permalink / raw)
  To: cocci

On 02/05/15 18:15, Stephen Boyd wrote:
> On 02/05/15 07:45, Quentin Lambert wrote:
>> On 05/02/2015 00:26, Stephen Boyd wrote:
>>>> If you want me to I can enlarge the search to other directories.
>>> Yes please do. And if you could share the coccinelle patch that would be
>>> great. Thanks.
>>>
>> structclk.cocci is the coccinelle patch
>> structclk-arm.patch is the result I got when applying it to the
>> arch/arm directory
>>
>> Is there anything else I can do to help?
>>
>>
> Thanks for the coccinelle patch. Thinking more about it, I don't think
> we care if the pointer is dereferenced because that would require a
> definition of struct clk and that is most likely not the case outside of
> the clock framework. Did you scan the entire kernel? I'm running it now
> but it seems to be taking a while.
>

I ran the script on all files that include <linux/clk.h>. I've also
trimmed out mips and unicore32 because they're not using the common
clock framework.

diff = 
--- arch/arm/mach-imx/mach-imx6q.c
+++ /tmp/cocci-output-11792-b62223-mach-imx6q.c
@@ -211,7 +211,6 @@ static void __init imx6q_1588_init(void)
 	 * set bit IOMUXC_GPR1[21].  Or the PTP clock must be from pad
 	 * (external OSC), and we need to clear the bit.
 	 */
-	clksel = ptp_clk == enet_ref ? IMX6Q_GPR1_ENET_CLK_SEL_ANATOP :
 				       IMX6Q_GPR1_ENET_CLK_SEL_PAD;
 	gpr = syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
 	if (!IS_ERR(gpr))
diff = 
--- drivers/gpu/drm/armada/armada_510.c
+++ /tmp/cocci-output-12321-a5f298-armada_510.c
@@ -53,7 +53,6 @@ static int armada510_crtc_compute_clock(
 	if (IS_ERR(clk))
 		return PTR_ERR(clk);
 
-	if (dcrtc->clk != clk) {
 		ret = clk_prepare_enable(clk);
 		if (ret)
 			return ret;
drivers/gpu/drm/armada/armada_510.c:56:5-15: WARNING trying to compare or dereference struct clk pointers.
diff = 
--- drivers/pwm/pwm-atmel-hlcdc.c
+++ /tmp/cocci-output-12679-3c5195-pwm-atmel-hlcdc.c
@@ -91,7 +91,6 @@ static int atmel_hlcdc_pwm_config(struct
 
 	pwmcfg = ATMEL_HLCDC_PWMPS(pres);
 
-	if (new_clk != chip->cur_clk) {
 		u32 gencfg = 0;
 		int ret;
 
drivers/pwm/pwm-atmel-hlcdc.c:94:5-12: WARNING trying to compare or dereference struct clk pointers.
diff = 
--- drivers/tty/serial/samsung.c
+++ /tmp/cocci-output-12827-715e72-samsung.c
@@ -750,7 +750,6 @@ static void s3c24xx_serial_set_termios(s
 
 	/* check to see if we need  to change clock source */
 
-	if (ourport->baudclk != clk) {
 		s3c24xx_serial_setsource(port, clk_sel);
 
 		if (!IS_ERR(ourport->baudclk)) {
drivers/tty/serial/samsung.c:753:5-21: WARNING trying to compare or dereference struct clk pointers.
diff = 
--- sound/soc/fsl/fsl_esai.c
+++ /tmp/cocci-output-13020-d518c3-fsl_esai.c
@@ -269,7 +269,6 @@ static int fsl_esai_set_dai_sysclk(struc
 	}
 
 	/* Only EXTAL source can be output directly without using PSR and PM */
-	if (ratio == 1 && clksrc == esai_priv->extalclk) {
 		/* Bypass all the dividers if not being needed */
 		ecr |= tx ? ESAI_ECR_ETO : ESAI_ECR_ERO;
 		goto out;
sound/soc/fsl/fsl_esai.c:272:19-25: WARNING trying to compare or dereference struct clk pointers.
diff = 
--- sound/soc/fsl/fsl_spdif.c
+++ /tmp/cocci-output-13024-7acb1d-fsl_spdif.c
@@ -1054,7 +1054,6 @@ static u32 fsl_spdif_txclk_caldiv(struct
 				enum spdif_txrate index, bool round)
 {
 	const u32 rate[] = { 32000, 44100, 48000, 96000, 192000 };
-	bool is_sysclk = clk == spdif_priv->sysclk;
 	u64 rate_ideal, rate_actual, sub;
 	u32 sysclk_dfmin, sysclk_dfmax;
 	u32 txclk_df, sysclk_df, arate;
@@ -1148,7 +1147,6 @@ static int fsl_spdif_probe_txclk(struct
 			spdif_priv->txclk_src[index], rate[index]);
 	dev_dbg(&pdev->dev, "use txclk df %d for %dHz sample rate\n",
 			spdif_priv->txclk_df[index], rate[index]);
-	if (spdif_priv->txclk[index] == spdif_priv->sysclk)
 		dev_dbg(&pdev->dev, "use sysclk df %d for %dHz sample rate\n",
 				spdif_priv->sysclk_df[index], rate[index]);
 	dev_dbg(&pdev->dev, "the best rate for %dHz sample rate is %dHz\n",
sound/soc/fsl/fsl_spdif.c:1151:5-29: WARNING trying to compare or dereference struct clk pointers.
sound/soc/fsl/fsl_spdif.c:1057:18-21: WARNING trying to compare or dereference struct clk pointers.
diff = 
--- sound/soc/kirkwood/kirkwood-i2s.c
+++ /tmp/cocci-output-13041-3200a6-kirkwood-i2s.c
@@ -579,7 +579,6 @@ static int kirkwood_i2s_dev_probe(struct
 		if (PTR_ERR(priv->extclk) == -EPROBE_DEFER)
 			return -EPROBE_DEFER;
 	} else {
-		if (priv->extclk == priv->clk) {
 			devm_clk_put(&pdev->dev, priv->extclk);
 			priv->extclk = ERR_PTR(-EINVAL);
 		} else {
sound/soc/kirkwood/kirkwood-i2s.c:582:6-18: WARNING trying to compare or dereference struct clk pointers.


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

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

* [Cocci] [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
@ 2015-02-17 22:01                       ` Stephen Boyd
  0 siblings, 0 replies; 186+ messages in thread
From: Stephen Boyd @ 2015-02-17 22:01 UTC (permalink / raw)
  To: linux-arm-kernel

On 02/05/15 18:15, Stephen Boyd wrote:
> On 02/05/15 07:45, Quentin Lambert wrote:
>> On 05/02/2015 00:26, Stephen Boyd wrote:
>>>> If you want me to I can enlarge the search to other directories.
>>> Yes please do. And if you could share the coccinelle patch that would be
>>> great. Thanks.
>>>
>> structclk.cocci is the coccinelle patch
>> structclk-arm.patch is the result I got when applying it to the
>> arch/arm directory
>>
>> Is there anything else I can do to help?
>>
>>
> Thanks for the coccinelle patch. Thinking more about it, I don't think
> we care if the pointer is dereferenced because that would require a
> definition of struct clk and that is most likely not the case outside of
> the clock framework. Did you scan the entire kernel? I'm running it now
> but it seems to be taking a while.
>

I ran the script on all files that include <linux/clk.h>. I've also
trimmed out mips and unicore32 because they're not using the common
clock framework.

diff = 
--- arch/arm/mach-imx/mach-imx6q.c
+++ /tmp/cocci-output-11792-b62223-mach-imx6q.c
@@ -211,7 +211,6 @@ static void __init imx6q_1588_init(void)
 	 * set bit IOMUXC_GPR1[21].  Or the PTP clock must be from pad
 	 * (external OSC), and we need to clear the bit.
 	 */
-	clksel = ptp_clk == enet_ref ? IMX6Q_GPR1_ENET_CLK_SEL_ANATOP :
 				       IMX6Q_GPR1_ENET_CLK_SEL_PAD;
 	gpr = syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
 	if (!IS_ERR(gpr))
diff = 
--- drivers/gpu/drm/armada/armada_510.c
+++ /tmp/cocci-output-12321-a5f298-armada_510.c
@@ -53,7 +53,6 @@ static int armada510_crtc_compute_clock(
 	if (IS_ERR(clk))
 		return PTR_ERR(clk);
 
-	if (dcrtc->clk != clk) {
 		ret = clk_prepare_enable(clk);
 		if (ret)
 			return ret;
drivers/gpu/drm/armada/armada_510.c:56:5-15: WARNING trying to compare or dereference struct clk pointers.
diff = 
--- drivers/pwm/pwm-atmel-hlcdc.c
+++ /tmp/cocci-output-12679-3c5195-pwm-atmel-hlcdc.c
@@ -91,7 +91,6 @@ static int atmel_hlcdc_pwm_config(struct
 
 	pwmcfg = ATMEL_HLCDC_PWMPS(pres);
 
-	if (new_clk != chip->cur_clk) {
 		u32 gencfg = 0;
 		int ret;
 
drivers/pwm/pwm-atmel-hlcdc.c:94:5-12: WARNING trying to compare or dereference struct clk pointers.
diff = 
--- drivers/tty/serial/samsung.c
+++ /tmp/cocci-output-12827-715e72-samsung.c
@@ -750,7 +750,6 @@ static void s3c24xx_serial_set_termios(s
 
 	/* check to see if we need  to change clock source */
 
-	if (ourport->baudclk != clk) {
 		s3c24xx_serial_setsource(port, clk_sel);
 
 		if (!IS_ERR(ourport->baudclk)) {
drivers/tty/serial/samsung.c:753:5-21: WARNING trying to compare or dereference struct clk pointers.
diff = 
--- sound/soc/fsl/fsl_esai.c
+++ /tmp/cocci-output-13020-d518c3-fsl_esai.c
@@ -269,7 +269,6 @@ static int fsl_esai_set_dai_sysclk(struc
 	}
 
 	/* Only EXTAL source can be output directly without using PSR and PM */
-	if (ratio == 1 && clksrc == esai_priv->extalclk) {
 		/* Bypass all the dividers if not being needed */
 		ecr |= tx ? ESAI_ECR_ETO : ESAI_ECR_ERO;
 		goto out;
sound/soc/fsl/fsl_esai.c:272:19-25: WARNING trying to compare or dereference struct clk pointers.
diff = 
--- sound/soc/fsl/fsl_spdif.c
+++ /tmp/cocci-output-13024-7acb1d-fsl_spdif.c
@@ -1054,7 +1054,6 @@ static u32 fsl_spdif_txclk_caldiv(struct
 				enum spdif_txrate index, bool round)
 {
 	const u32 rate[] = { 32000, 44100, 48000, 96000, 192000 };
-	bool is_sysclk = clk == spdif_priv->sysclk;
 	u64 rate_ideal, rate_actual, sub;
 	u32 sysclk_dfmin, sysclk_dfmax;
 	u32 txclk_df, sysclk_df, arate;
@@ -1148,7 +1147,6 @@ static int fsl_spdif_probe_txclk(struct
 			spdif_priv->txclk_src[index], rate[index]);
 	dev_dbg(&pdev->dev, "use txclk df %d for %dHz sample rate\n",
 			spdif_priv->txclk_df[index], rate[index]);
-	if (spdif_priv->txclk[index] == spdif_priv->sysclk)
 		dev_dbg(&pdev->dev, "use sysclk df %d for %dHz sample rate\n",
 				spdif_priv->sysclk_df[index], rate[index]);
 	dev_dbg(&pdev->dev, "the best rate for %dHz sample rate is %dHz\n",
sound/soc/fsl/fsl_spdif.c:1151:5-29: WARNING trying to compare or dereference struct clk pointers.
sound/soc/fsl/fsl_spdif.c:1057:18-21: WARNING trying to compare or dereference struct clk pointers.
diff = 
--- sound/soc/kirkwood/kirkwood-i2s.c
+++ /tmp/cocci-output-13041-3200a6-kirkwood-i2s.c
@@ -579,7 +579,6 @@ static int kirkwood_i2s_dev_probe(struct
 		if (PTR_ERR(priv->extclk) == -EPROBE_DEFER)
 			return -EPROBE_DEFER;
 	} else {
-		if (priv->extclk == priv->clk) {
 			devm_clk_put(&pdev->dev, priv->extclk);
 			priv->extclk = ERR_PTR(-EINVAL);
 		} else {
sound/soc/kirkwood/kirkwood-i2s.c:582:6-18: WARNING trying to compare or dereference struct clk pointers.


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

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

* Re: [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
  2015-02-06 19:30                 ` Stephen Boyd
@ 2015-02-19 21:32                   ` Mike Turquette
  -1 siblings, 0 replies; 186+ messages in thread
From: Mike Turquette @ 2015-02-19 21:32 UTC (permalink / raw)
  To: Stephen Boyd, Russell King - ARM Linux
  Cc: Sylwester Nawrocki, Tomeu Vizoso, Paul Walmsley, Tony Lindgren,
	linux-kernel, linux-omap, Javier Martinez Canillas,
	linux-arm-kernel

Quoting Stephen Boyd (2015-02-06 11:30:18)
> On 02/06/15 05:39, Russell King - ARM Linux wrote:
> > On Thu, Feb 05, 2015 at 05:35:28PM -0800, Stephen Boyd wrote:
> >
> >> From what I can tell this code is
> >> now broken because we made all clk getting functions (there's quite a
> >> few...) return unique pointers every time they're called. It seems that
> >> the driver wants to know if extclk and clk are the same so it can do
> >> something differently in kirkwood_set_rate(). Do we need some sort of
> >> clk_equal(struct clk *a, struct clk *b) function for drivers like this?
> > Well, the clocks in question are the SoC internal clock (which is more or
> > less fixed, but has a programmable divider) and an externally supplied
> > clock, and the IP has a multiplexer on its input which allows us to select
> > between those two sources.
> >
> > If it were possible to bind both to the same clock, it wouldn't be a
> > useful configuration - nothing would be gained from doing so in terms of
> > available rates.
> >
> > What the comparison is there for is to catch the case with legacy lookups
> > where a clkdev lookup entry with a NULL connection ID results in matching
> > any connection ID passed to clk_get().  If the patch changes this, then
> > we will have a regression - and this is something which needs fixing
> > _before_ we do this "return unique clocks".
> >
> 
> Ok. It seems that we might need a clk_equal() or similar API after all.
> My understanding is that this driver is calling clk_get() twice with
> NULL for the con_id and then "extclk" in attempts to get the SoC
> internal clock and the externally supplied clock. If we're using legacy
> lookups then both clk_get() calls may map to the same clk_lookup entry
> and before Tomeu's patch that returns unique clocks the driver could
> detect this case and know that there isn't an external clock. Looking at
> arch/arm/mach-dove/common.c it seems that there is only one lookup per
> device and it has a wildcard NULL for con_id so both clk_get() calls
> here are going to find the same lookup and get a unique struct clk pointer.
> 
> Why don't we make the legacy lookup more specific and actually indicate
> "internal" for the con_id? Then the external clock would fail to be
> found, but we can detect that case and figure out that it's not due to
> probe defer, but instead due to the fact that there really isn't any
> mapping. It looks like the code is already prepared for this anyway.
> 
> ----8<----
> 
> From: Stephen Boyd <sboyd@codeaurora.org>
> Subject: [PATCH] ARM: dove: Remove wildcard from mvebu-audio device clk lookup
> 
> This i2s driver is using the wildcard nature of clkdev lookups to
> figure out if there's an external clock or not. It does this by
> calling clk_get() twice with NULL for the con_id first and then
> "external" for the con_id the second time around and then
> compares the two pointers. With DT the wildcard feature of
> clk_get() is gone and so the driver has to handle an error from
> the second clk_get() call as meaning "no external clock
> specified". Let's use that logic even with clk lookups to
> simplify the code and remove the struct clk pointer comparisons
> which may not work in the future when clk_get() returns unique
> pointers.
> 
> Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>

Russell et al,

I'm happy to take this patch through the clock tree (where the problem
shows up) with an ack.

Regards,
Mike

> ---
>  arch/arm/mach-dove/common.c       |  4 ++--
>  sound/soc/kirkwood/kirkwood-i2s.c | 13 ++++---------
>  2 files changed, 6 insertions(+), 11 deletions(-)
> 
> diff --git a/arch/arm/mach-dove/common.c b/arch/arm/mach-dove/common.c
> index 0d1a89298ece..f290fc944cc1 100644
> --- a/arch/arm/mach-dove/common.c
> +++ b/arch/arm/mach-dove/common.c
> @@ -124,8 +124,8 @@ static void __init dove_clk_init(void)
>         orion_clkdev_add(NULL, "sdhci-dove.1", sdio1);
>         orion_clkdev_add(NULL, "orion_nand", nand);
>         orion_clkdev_add(NULL, "cafe1000-ccic.0", camera);
> -       orion_clkdev_add(NULL, "mvebu-audio.0", i2s0);
> -       orion_clkdev_add(NULL, "mvebu-audio.1", i2s1);
> +       orion_clkdev_add("internal", "mvebu-audio.0", i2s0);
> +       orion_clkdev_add("internal", "mvebu-audio.1", i2s1);
>         orion_clkdev_add(NULL, "mv_crypto", crypto);
>         orion_clkdev_add(NULL, "dove-ac97", ac97);
>         orion_clkdev_add(NULL, "dove-pdma", pdma);
> diff --git a/sound/soc/kirkwood/kirkwood-i2s.c b/sound/soc/kirkwood/kirkwood-i2s.c
> index def7d8260c4e..0bfeb712a997 100644
> --- a/sound/soc/kirkwood/kirkwood-i2s.c
> +++ b/sound/soc/kirkwood/kirkwood-i2s.c
> @@ -564,7 +564,7 @@ static int kirkwood_i2s_dev_probe(struct platform_device *pdev)
>                 return -EINVAL;
>         }
>  
> -       priv->clk = devm_clk_get(&pdev->dev, np ? "internal" : NULL);
> +       priv->clk = devm_clk_get(&pdev->dev, "internal");
>         if (IS_ERR(priv->clk)) {
>                 dev_err(&pdev->dev, "no clock\n");
>                 return PTR_ERR(priv->clk);
> @@ -579,14 +579,9 @@ static int kirkwood_i2s_dev_probe(struct platform_device *pdev)
>                 if (PTR_ERR(priv->extclk) == -EPROBE_DEFER)
>                         return -EPROBE_DEFER;
>         } else {
> -               if (priv->extclk == priv->clk) {
> -                       devm_clk_put(&pdev->dev, priv->extclk);
> -                       priv->extclk = ERR_PTR(-EINVAL);
> -               } else {
> -                       dev_info(&pdev->dev, "found external clock\n");
> -                       clk_prepare_enable(priv->extclk);
> -                       soc_dai = kirkwood_i2s_dai_extclk;
> -               }
> +               dev_info(&pdev->dev, "found external clock\n");
> +               clk_prepare_enable(priv->extclk);
> +               soc_dai = kirkwood_i2s_dai_extclk;
>         }
>  
>         /* Some sensible defaults - this reflects the powerup values */
> 
> -- 
> Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
> a Linux Foundation Collaborative Project
> 

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

* [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
@ 2015-02-19 21:32                   ` Mike Turquette
  0 siblings, 0 replies; 186+ messages in thread
From: Mike Turquette @ 2015-02-19 21:32 UTC (permalink / raw)
  To: linux-arm-kernel

Quoting Stephen Boyd (2015-02-06 11:30:18)
> On 02/06/15 05:39, Russell King - ARM Linux wrote:
> > On Thu, Feb 05, 2015 at 05:35:28PM -0800, Stephen Boyd wrote:
> >
> >> From what I can tell this code is
> >> now broken because we made all clk getting functions (there's quite a
> >> few...) return unique pointers every time they're called. It seems that
> >> the driver wants to know if extclk and clk are the same so it can do
> >> something differently in kirkwood_set_rate(). Do we need some sort of
> >> clk_equal(struct clk *a, struct clk *b) function for drivers like this?
> > Well, the clocks in question are the SoC internal clock (which is more or
> > less fixed, but has a programmable divider) and an externally supplied
> > clock, and the IP has a multiplexer on its input which allows us to select
> > between those two sources.
> >
> > If it were possible to bind both to the same clock, it wouldn't be a
> > useful configuration - nothing would be gained from doing so in terms of
> > available rates.
> >
> > What the comparison is there for is to catch the case with legacy lookups
> > where a clkdev lookup entry with a NULL connection ID results in matching
> > any connection ID passed to clk_get().  If the patch changes this, then
> > we will have a regression - and this is something which needs fixing
> > _before_ we do this "return unique clocks".
> >
> 
> Ok. It seems that we might need a clk_equal() or similar API after all.
> My understanding is that this driver is calling clk_get() twice with
> NULL for the con_id and then "extclk" in attempts to get the SoC
> internal clock and the externally supplied clock. If we're using legacy
> lookups then both clk_get() calls may map to the same clk_lookup entry
> and before Tomeu's patch that returns unique clocks the driver could
> detect this case and know that there isn't an external clock. Looking at
> arch/arm/mach-dove/common.c it seems that there is only one lookup per
> device and it has a wildcard NULL for con_id so both clk_get() calls
> here are going to find the same lookup and get a unique struct clk pointer.
> 
> Why don't we make the legacy lookup more specific and actually indicate
> "internal" for the con_id? Then the external clock would fail to be
> found, but we can detect that case and figure out that it's not due to
> probe defer, but instead due to the fact that there really isn't any
> mapping. It looks like the code is already prepared for this anyway.
> 
> ----8<----
> 
> From: Stephen Boyd <sboyd@codeaurora.org>
> Subject: [PATCH] ARM: dove: Remove wildcard from mvebu-audio device clk lookup
> 
> This i2s driver is using the wildcard nature of clkdev lookups to
> figure out if there's an external clock or not. It does this by
> calling clk_get() twice with NULL for the con_id first and then
> "external" for the con_id the second time around and then
> compares the two pointers. With DT the wildcard feature of
> clk_get() is gone and so the driver has to handle an error from
> the second clk_get() call as meaning "no external clock
> specified". Let's use that logic even with clk lookups to
> simplify the code and remove the struct clk pointer comparisons
> which may not work in the future when clk_get() returns unique
> pointers.
> 
> Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>

Russell et al,

I'm happy to take this patch through the clock tree (where the problem
shows up) with an ack.

Regards,
Mike

> ---
>  arch/arm/mach-dove/common.c       |  4 ++--
>  sound/soc/kirkwood/kirkwood-i2s.c | 13 ++++---------
>  2 files changed, 6 insertions(+), 11 deletions(-)
> 
> diff --git a/arch/arm/mach-dove/common.c b/arch/arm/mach-dove/common.c
> index 0d1a89298ece..f290fc944cc1 100644
> --- a/arch/arm/mach-dove/common.c
> +++ b/arch/arm/mach-dove/common.c
> @@ -124,8 +124,8 @@ static void __init dove_clk_init(void)
>         orion_clkdev_add(NULL, "sdhci-dove.1", sdio1);
>         orion_clkdev_add(NULL, "orion_nand", nand);
>         orion_clkdev_add(NULL, "cafe1000-ccic.0", camera);
> -       orion_clkdev_add(NULL, "mvebu-audio.0", i2s0);
> -       orion_clkdev_add(NULL, "mvebu-audio.1", i2s1);
> +       orion_clkdev_add("internal", "mvebu-audio.0", i2s0);
> +       orion_clkdev_add("internal", "mvebu-audio.1", i2s1);
>         orion_clkdev_add(NULL, "mv_crypto", crypto);
>         orion_clkdev_add(NULL, "dove-ac97", ac97);
>         orion_clkdev_add(NULL, "dove-pdma", pdma);
> diff --git a/sound/soc/kirkwood/kirkwood-i2s.c b/sound/soc/kirkwood/kirkwood-i2s.c
> index def7d8260c4e..0bfeb712a997 100644
> --- a/sound/soc/kirkwood/kirkwood-i2s.c
> +++ b/sound/soc/kirkwood/kirkwood-i2s.c
> @@ -564,7 +564,7 @@ static int kirkwood_i2s_dev_probe(struct platform_device *pdev)
>                 return -EINVAL;
>         }
>  
> -       priv->clk = devm_clk_get(&pdev->dev, np ? "internal" : NULL);
> +       priv->clk = devm_clk_get(&pdev->dev, "internal");
>         if (IS_ERR(priv->clk)) {
>                 dev_err(&pdev->dev, "no clock\n");
>                 return PTR_ERR(priv->clk);
> @@ -579,14 +579,9 @@ static int kirkwood_i2s_dev_probe(struct platform_device *pdev)
>                 if (PTR_ERR(priv->extclk) == -EPROBE_DEFER)
>                         return -EPROBE_DEFER;
>         } else {
> -               if (priv->extclk == priv->clk) {
> -                       devm_clk_put(&pdev->dev, priv->extclk);
> -                       priv->extclk = ERR_PTR(-EINVAL);
> -               } else {
> -                       dev_info(&pdev->dev, "found external clock\n");
> -                       clk_prepare_enable(priv->extclk);
> -                       soc_dai = kirkwood_i2s_dai_extclk;
> -               }
> +               dev_info(&pdev->dev, "found external clock\n");
> +               clk_prepare_enable(priv->extclk);
> +               soc_dai = kirkwood_i2s_dai_extclk;
>         }
>  
>         /* Some sensible defaults - this reflects the powerup values */
> 
> -- 
> Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
> a Linux Foundation Collaborative Project
> 

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

* Re: [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
  2015-02-19 21:32                   ` Mike Turquette
@ 2015-02-24 14:08                     ` Russell King - ARM Linux
  -1 siblings, 0 replies; 186+ messages in thread
From: Russell King - ARM Linux @ 2015-02-24 14:08 UTC (permalink / raw)
  To: Mike Turquette
  Cc: Stephen Boyd, Sylwester Nawrocki, Tomeu Vizoso, Paul Walmsley,
	Tony Lindgren, linux-kernel, linux-omap,
	Javier Martinez Canillas, linux-arm-kernel

On Thu, Feb 19, 2015 at 01:32:33PM -0800, Mike Turquette wrote:
> Quoting Stephen Boyd (2015-02-06 11:30:18)
> > On 02/06/15 05:39, Russell King - ARM Linux wrote:
> > > On Thu, Feb 05, 2015 at 05:35:28PM -0800, Stephen Boyd wrote:
> > >
> > >> From what I can tell this code is
> > >> now broken because we made all clk getting functions (there's quite a
> > >> few...) return unique pointers every time they're called. It seems that
> > >> the driver wants to know if extclk and clk are the same so it can do
> > >> something differently in kirkwood_set_rate(). Do we need some sort of
> > >> clk_equal(struct clk *a, struct clk *b) function for drivers like this?
> > > Well, the clocks in question are the SoC internal clock (which is more or
> > > less fixed, but has a programmable divider) and an externally supplied
> > > clock, and the IP has a multiplexer on its input which allows us to select
> > > between those two sources.
> > >
> > > If it were possible to bind both to the same clock, it wouldn't be a
> > > useful configuration - nothing would be gained from doing so in terms of
> > > available rates.
> > >
> > > What the comparison is there for is to catch the case with legacy lookups
> > > where a clkdev lookup entry with a NULL connection ID results in matching
> > > any connection ID passed to clk_get().  If the patch changes this, then
> > > we will have a regression - and this is something which needs fixing
> > > _before_ we do this "return unique clocks".
> > >
> > 
> > Ok. It seems that we might need a clk_equal() or similar API after all.
> > My understanding is that this driver is calling clk_get() twice with
> > NULL for the con_id and then "extclk" in attempts to get the SoC
> > internal clock and the externally supplied clock. If we're using legacy
> > lookups then both clk_get() calls may map to the same clk_lookup entry
> > and before Tomeu's patch that returns unique clocks the driver could
> > detect this case and know that there isn't an external clock. Looking at
> > arch/arm/mach-dove/common.c it seems that there is only one lookup per
> > device and it has a wildcard NULL for con_id so both clk_get() calls
> > here are going to find the same lookup and get a unique struct clk pointer.
> > 
> > Why don't we make the legacy lookup more specific and actually indicate
> > "internal" for the con_id? Then the external clock would fail to be
> > found, but we can detect that case and figure out that it's not due to
> > probe defer, but instead due to the fact that there really isn't any
> > mapping. It looks like the code is already prepared for this anyway.
> > 
> > ----8<----
> > 
> > From: Stephen Boyd <sboyd@codeaurora.org>
> > Subject: [PATCH] ARM: dove: Remove wildcard from mvebu-audio device clk lookup
> > 
> > This i2s driver is using the wildcard nature of clkdev lookups to
> > figure out if there's an external clock or not. It does this by
> > calling clk_get() twice with NULL for the con_id first and then
> > "external" for the con_id the second time around and then
> > compares the two pointers. With DT the wildcard feature of
> > clk_get() is gone and so the driver has to handle an error from
> > the second clk_get() call as meaning "no external clock
> > specified". Let's use that logic even with clk lookups to
> > simplify the code and remove the struct clk pointer comparisons
> > which may not work in the future when clk_get() returns unique
> > pointers.
> > 
> > Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
> 
> Russell et al,
> 
> I'm happy to take this patch through the clock tree (where the problem
> shows up) with an ack.

It's not up to me - I don't maintain this driver.  I'm just an interested
party.

Note that much more than just this has now broken.  The iMX6 code has
broken as well, and it's not going to take such a simple fix there to
fix it either.

Please either revert the patches creating this breakage (and have another
attempt at the next merge window) or supply fixes for these places.

-- 
FTTC broadband for 0.8mile line: currently at 10.5Mbps down 400kbps up
according to speedtest.net.

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

* [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
@ 2015-02-24 14:08                     ` Russell King - ARM Linux
  0 siblings, 0 replies; 186+ messages in thread
From: Russell King - ARM Linux @ 2015-02-24 14:08 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Feb 19, 2015 at 01:32:33PM -0800, Mike Turquette wrote:
> Quoting Stephen Boyd (2015-02-06 11:30:18)
> > On 02/06/15 05:39, Russell King - ARM Linux wrote:
> > > On Thu, Feb 05, 2015 at 05:35:28PM -0800, Stephen Boyd wrote:
> > >
> > >> From what I can tell this code is
> > >> now broken because we made all clk getting functions (there's quite a
> > >> few...) return unique pointers every time they're called. It seems that
> > >> the driver wants to know if extclk and clk are the same so it can do
> > >> something differently in kirkwood_set_rate(). Do we need some sort of
> > >> clk_equal(struct clk *a, struct clk *b) function for drivers like this?
> > > Well, the clocks in question are the SoC internal clock (which is more or
> > > less fixed, but has a programmable divider) and an externally supplied
> > > clock, and the IP has a multiplexer on its input which allows us to select
> > > between those two sources.
> > >
> > > If it were possible to bind both to the same clock, it wouldn't be a
> > > useful configuration - nothing would be gained from doing so in terms of
> > > available rates.
> > >
> > > What the comparison is there for is to catch the case with legacy lookups
> > > where a clkdev lookup entry with a NULL connection ID results in matching
> > > any connection ID passed to clk_get().  If the patch changes this, then
> > > we will have a regression - and this is something which needs fixing
> > > _before_ we do this "return unique clocks".
> > >
> > 
> > Ok. It seems that we might need a clk_equal() or similar API after all.
> > My understanding is that this driver is calling clk_get() twice with
> > NULL for the con_id and then "extclk" in attempts to get the SoC
> > internal clock and the externally supplied clock. If we're using legacy
> > lookups then both clk_get() calls may map to the same clk_lookup entry
> > and before Tomeu's patch that returns unique clocks the driver could
> > detect this case and know that there isn't an external clock. Looking at
> > arch/arm/mach-dove/common.c it seems that there is only one lookup per
> > device and it has a wildcard NULL for con_id so both clk_get() calls
> > here are going to find the same lookup and get a unique struct clk pointer.
> > 
> > Why don't we make the legacy lookup more specific and actually indicate
> > "internal" for the con_id? Then the external clock would fail to be
> > found, but we can detect that case and figure out that it's not due to
> > probe defer, but instead due to the fact that there really isn't any
> > mapping. It looks like the code is already prepared for this anyway.
> > 
> > ----8<----
> > 
> > From: Stephen Boyd <sboyd@codeaurora.org>
> > Subject: [PATCH] ARM: dove: Remove wildcard from mvebu-audio device clk lookup
> > 
> > This i2s driver is using the wildcard nature of clkdev lookups to
> > figure out if there's an external clock or not. It does this by
> > calling clk_get() twice with NULL for the con_id first and then
> > "external" for the con_id the second time around and then
> > compares the two pointers. With DT the wildcard feature of
> > clk_get() is gone and so the driver has to handle an error from
> > the second clk_get() call as meaning "no external clock
> > specified". Let's use that logic even with clk lookups to
> > simplify the code and remove the struct clk pointer comparisons
> > which may not work in the future when clk_get() returns unique
> > pointers.
> > 
> > Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
> 
> Russell et al,
> 
> I'm happy to take this patch through the clock tree (where the problem
> shows up) with an ack.

It's not up to me - I don't maintain this driver.  I'm just an interested
party.

Note that much more than just this has now broken.  The iMX6 code has
broken as well, and it's not going to take such a simple fix there to
fix it either.

Please either revert the patches creating this breakage (and have another
attempt at the next merge window) or supply fixes for these places.

-- 
FTTC broadband for 0.8mile line: currently at 10.5Mbps down 400kbps up
according to speedtest.net.

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

* Re: [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
  2015-02-24 14:08                     ` Russell King - ARM Linux
@ 2015-02-25  2:18                       ` Mike Turquette
  -1 siblings, 0 replies; 186+ messages in thread
From: Mike Turquette @ 2015-02-25  2:18 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: Paul Walmsley, Tomeu Vizoso, Tony Lindgren, Stephen Boyd,
	linux-kernel, Sylwester Nawrocki, linux-omap,
	Javier Martinez Canillas, linux-arm-kernel

Quoting Russell King - ARM Linux (2015-02-24 06:08:08)
> On Thu, Feb 19, 2015 at 01:32:33PM -0800, Mike Turquette wrote:
> > Quoting Stephen Boyd (2015-02-06 11:30:18)
> > > On 02/06/15 05:39, Russell King - ARM Linux wrote:
> > > > On Thu, Feb 05, 2015 at 05:35:28PM -0800, Stephen Boyd wrote:
> > > >
> > > >> From what I can tell this code is
> > > >> now broken because we made all clk getting functions (there's quite a
> > > >> few...) return unique pointers every time they're called. It seems that
> > > >> the driver wants to know if extclk and clk are the same so it can do
> > > >> something differently in kirkwood_set_rate(). Do we need some sort of
> > > >> clk_equal(struct clk *a, struct clk *b) function for drivers like this?
> > > > Well, the clocks in question are the SoC internal clock (which is more or
> > > > less fixed, but has a programmable divider) and an externally supplied
> > > > clock, and the IP has a multiplexer on its input which allows us to select
> > > > between those two sources.
> > > >
> > > > If it were possible to bind both to the same clock, it wouldn't be a
> > > > useful configuration - nothing would be gained from doing so in terms of
> > > > available rates.
> > > >
> > > > What the comparison is there for is to catch the case with legacy lookups
> > > > where a clkdev lookup entry with a NULL connection ID results in matching
> > > > any connection ID passed to clk_get().  If the patch changes this, then
> > > > we will have a regression - and this is something which needs fixing
> > > > _before_ we do this "return unique clocks".
> > > >
> > > 
> > > Ok. It seems that we might need a clk_equal() or similar API after all.
> > > My understanding is that this driver is calling clk_get() twice with
> > > NULL for the con_id and then "extclk" in attempts to get the SoC
> > > internal clock and the externally supplied clock. If we're using legacy
> > > lookups then both clk_get() calls may map to the same clk_lookup entry
> > > and before Tomeu's patch that returns unique clocks the driver could
> > > detect this case and know that there isn't an external clock. Looking at
> > > arch/arm/mach-dove/common.c it seems that there is only one lookup per
> > > device and it has a wildcard NULL for con_id so both clk_get() calls
> > > here are going to find the same lookup and get a unique struct clk pointer.
> > > 
> > > Why don't we make the legacy lookup more specific and actually indicate
> > > "internal" for the con_id? Then the external clock would fail to be
> > > found, but we can detect that case and figure out that it's not due to
> > > probe defer, but instead due to the fact that there really isn't any
> > > mapping. It looks like the code is already prepared for this anyway.
> > > 
> > > ----8<----
> > > 
> > > From: Stephen Boyd <sboyd@codeaurora.org>
> > > Subject: [PATCH] ARM: dove: Remove wildcard from mvebu-audio device clk lookup
> > > 
> > > This i2s driver is using the wildcard nature of clkdev lookups to
> > > figure out if there's an external clock or not. It does this by
> > > calling clk_get() twice with NULL for the con_id first and then
> > > "external" for the con_id the second time around and then
> > > compares the two pointers. With DT the wildcard feature of
> > > clk_get() is gone and so the driver has to handle an error from
> > > the second clk_get() call as meaning "no external clock
> > > specified". Let's use that logic even with clk lookups to
> > > simplify the code and remove the struct clk pointer comparisons
> > > which may not work in the future when clk_get() returns unique
> > > pointers.
> > > 
> > > Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
> > 
> > Russell et al,
> > 
> > I'm happy to take this patch through the clock tree (where the problem
> > shows up) with an ack.
> 
> It's not up to me - I don't maintain this driver.  I'm just an interested
> party.

Sure.

> 
> Note that much more than just this has now broken.  The iMX6 code has
> broken as well, and it's not going to take such a simple fix there to
> fix it either.
> 
> Please either revert the patches creating this breakage (and have another
> attempt at the next merge window) or supply fixes for these places.

Let's try the latter. Stephen used coccinelle to find similar instances
of clk pointer comparisons[0]. As a stop-gap solution we can introduce a
clk_is_match(struct clk *a, struct clk *b) function and sub it for the
handful of drivers that do this behavior and use CCF.

[0] http://lkml.kernel.org/r/<54E3BA20.3080205@codeaurora.org>

Regards,
Mike

> 
> -- 
> FTTC broadband for 0.8mile line: currently at 10.5Mbps down 400kbps up
> according to speedtest.net.

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

* [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
@ 2015-02-25  2:18                       ` Mike Turquette
  0 siblings, 0 replies; 186+ messages in thread
From: Mike Turquette @ 2015-02-25  2:18 UTC (permalink / raw)
  To: linux-arm-kernel

Quoting Russell King - ARM Linux (2015-02-24 06:08:08)
> On Thu, Feb 19, 2015 at 01:32:33PM -0800, Mike Turquette wrote:
> > Quoting Stephen Boyd (2015-02-06 11:30:18)
> > > On 02/06/15 05:39, Russell King - ARM Linux wrote:
> > > > On Thu, Feb 05, 2015 at 05:35:28PM -0800, Stephen Boyd wrote:
> > > >
> > > >> From what I can tell this code is
> > > >> now broken because we made all clk getting functions (there's quite a
> > > >> few...) return unique pointers every time they're called. It seems that
> > > >> the driver wants to know if extclk and clk are the same so it can do
> > > >> something differently in kirkwood_set_rate(). Do we need some sort of
> > > >> clk_equal(struct clk *a, struct clk *b) function for drivers like this?
> > > > Well, the clocks in question are the SoC internal clock (which is more or
> > > > less fixed, but has a programmable divider) and an externally supplied
> > > > clock, and the IP has a multiplexer on its input which allows us to select
> > > > between those two sources.
> > > >
> > > > If it were possible to bind both to the same clock, it wouldn't be a
> > > > useful configuration - nothing would be gained from doing so in terms of
> > > > available rates.
> > > >
> > > > What the comparison is there for is to catch the case with legacy lookups
> > > > where a clkdev lookup entry with a NULL connection ID results in matching
> > > > any connection ID passed to clk_get().  If the patch changes this, then
> > > > we will have a regression - and this is something which needs fixing
> > > > _before_ we do this "return unique clocks".
> > > >
> > > 
> > > Ok. It seems that we might need a clk_equal() or similar API after all.
> > > My understanding is that this driver is calling clk_get() twice with
> > > NULL for the con_id and then "extclk" in attempts to get the SoC
> > > internal clock and the externally supplied clock. If we're using legacy
> > > lookups then both clk_get() calls may map to the same clk_lookup entry
> > > and before Tomeu's patch that returns unique clocks the driver could
> > > detect this case and know that there isn't an external clock. Looking at
> > > arch/arm/mach-dove/common.c it seems that there is only one lookup per
> > > device and it has a wildcard NULL for con_id so both clk_get() calls
> > > here are going to find the same lookup and get a unique struct clk pointer.
> > > 
> > > Why don't we make the legacy lookup more specific and actually indicate
> > > "internal" for the con_id? Then the external clock would fail to be
> > > found, but we can detect that case and figure out that it's not due to
> > > probe defer, but instead due to the fact that there really isn't any
> > > mapping. It looks like the code is already prepared for this anyway.
> > > 
> > > ----8<----
> > > 
> > > From: Stephen Boyd <sboyd@codeaurora.org>
> > > Subject: [PATCH] ARM: dove: Remove wildcard from mvebu-audio device clk lookup
> > > 
> > > This i2s driver is using the wildcard nature of clkdev lookups to
> > > figure out if there's an external clock or not. It does this by
> > > calling clk_get() twice with NULL for the con_id first and then
> > > "external" for the con_id the second time around and then
> > > compares the two pointers. With DT the wildcard feature of
> > > clk_get() is gone and so the driver has to handle an error from
> > > the second clk_get() call as meaning "no external clock
> > > specified". Let's use that logic even with clk lookups to
> > > simplify the code and remove the struct clk pointer comparisons
> > > which may not work in the future when clk_get() returns unique
> > > pointers.
> > > 
> > > Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
> > 
> > Russell et al,
> > 
> > I'm happy to take this patch through the clock tree (where the problem
> > shows up) with an ack.
> 
> It's not up to me - I don't maintain this driver.  I'm just an interested
> party.

Sure.

> 
> Note that much more than just this has now broken.  The iMX6 code has
> broken as well, and it's not going to take such a simple fix there to
> fix it either.
> 
> Please either revert the patches creating this breakage (and have another
> attempt at the next merge window) or supply fixes for these places.

Let's try the latter. Stephen used coccinelle to find similar instances
of clk pointer comparisons[0]. As a stop-gap solution we can introduce a
clk_is_match(struct clk *a, struct clk *b) function and sub it for the
handful of drivers that do this behavior and use CCF.

[0] http://lkml.kernel.org/r/<54E3BA20.3080205@codeaurora.org>

Regards,
Mike

> 
> -- 
> FTTC broadband for 0.8mile line: currently at 10.5Mbps down 400kbps up
> according to speedtest.net.

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

* Re: [Cocci] [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
  2015-02-17 22:01                       ` Stephen Boyd
  (?)
@ 2015-03-12 17:20                         ` Sebastian Andrzej Siewior
  -1 siblings, 0 replies; 186+ messages in thread
From: Sebastian Andrzej Siewior @ 2015-03-12 17:20 UTC (permalink / raw)
  To: Stephen Boyd, Shawn Guo
  Cc: Quentin Lambert, Mike Turquette, Julia Lawall, Paul Walmsley,
	Tomeu Vizoso, Tony Lindgren, linux-kernel, t-kristo, linux-omap,
	cocci, linux-arm-kernel

On 2015-02-17 14:01:04 [-0800], Stephen Boyd wrote:
> diff = 
> --- arch/arm/mach-imx/mach-imx6q.c
> +++ /tmp/cocci-output-11792-b62223-mach-imx6q.c
> @@ -211,7 +211,6 @@ static void __init imx6q_1588_init(void)
>  	 * set bit IOMUXC_GPR1[21].  Or the PTP clock must be from pad
>  	 * (external OSC), and we need to clear the bit.
>  	 */
> -	clksel = ptp_clk == enet_ref ? IMX6Q_GPR1_ENET_CLK_SEL_ANATOP :
>  				       IMX6Q_GPR1_ENET_CLK_SEL_PAD;
>  	gpr = syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
>  	if (!IS_ERR(gpr))

Any idea how to do the comparison here? Or should we rely that the bootloader
sets this properly (it managed already to select a frequency)? The phy has no
clock node in current DT's so we can check this.

Sebastian

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

* [Cocci] [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
@ 2015-03-12 17:20                         ` Sebastian Andrzej Siewior
  0 siblings, 0 replies; 186+ messages in thread
From: Sebastian Andrzej Siewior @ 2015-03-12 17:20 UTC (permalink / raw)
  To: cocci

On 2015-02-17 14:01:04 [-0800], Stephen Boyd wrote:
> diff = 
> --- arch/arm/mach-imx/mach-imx6q.c
> +++ /tmp/cocci-output-11792-b62223-mach-imx6q.c
> @@ -211,7 +211,6 @@ static void __init imx6q_1588_init(void)
>  	 * set bit IOMUXC_GPR1[21].  Or the PTP clock must be from pad
>  	 * (external OSC), and we need to clear the bit.
>  	 */
> -	clksel = ptp_clk == enet_ref ? IMX6Q_GPR1_ENET_CLK_SEL_ANATOP :
>  				       IMX6Q_GPR1_ENET_CLK_SEL_PAD;
>  	gpr = syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
>  	if (!IS_ERR(gpr))

Any idea how to do the comparison here? Or should we rely that the bootloader
sets this properly (it managed already to select a frequency)? The phy has no
clock node in current DT's so we can check this.

Sebastian

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

* [Cocci] [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
@ 2015-03-12 17:20                         ` Sebastian Andrzej Siewior
  0 siblings, 0 replies; 186+ messages in thread
From: Sebastian Andrzej Siewior @ 2015-03-12 17:20 UTC (permalink / raw)
  To: linux-arm-kernel

On 2015-02-17 14:01:04 [-0800], Stephen Boyd wrote:
> diff = 
> --- arch/arm/mach-imx/mach-imx6q.c
> +++ /tmp/cocci-output-11792-b62223-mach-imx6q.c
> @@ -211,7 +211,6 @@ static void __init imx6q_1588_init(void)
>  	 * set bit IOMUXC_GPR1[21].  Or the PTP clock must be from pad
>  	 * (external OSC), and we need to clear the bit.
>  	 */
> -	clksel = ptp_clk == enet_ref ? IMX6Q_GPR1_ENET_CLK_SEL_ANATOP :
>  				       IMX6Q_GPR1_ENET_CLK_SEL_PAD;
>  	gpr = syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
>  	if (!IS_ERR(gpr))

Any idea how to do the comparison here? Or should we rely that the bootloader
sets this properly (it managed already to select a frequency)? The phy has no
clock node in current DT's so we can check this.

Sebastian

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

* Re: [Cocci] [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
  2015-03-12 17:20                         ` Sebastian Andrzej Siewior
  (?)
@ 2015-03-12 19:43                           ` Stephen Boyd
  -1 siblings, 0 replies; 186+ messages in thread
From: Stephen Boyd @ 2015-03-12 19:43 UTC (permalink / raw)
  To: Sebastian Andrzej Siewior, Shawn Guo
  Cc: Quentin Lambert, Mike Turquette, Julia Lawall, Paul Walmsley,
	Tomeu Vizoso, Tony Lindgren, linux-kernel, t-kristo, linux-omap,
	cocci, linux-arm-kernel

On 03/12/15 10:20, Sebastian Andrzej Siewior wrote:
> On 2015-02-17 14:01:04 [-0800], Stephen Boyd wrote:
>> diff = 
>> --- arch/arm/mach-imx/mach-imx6q.c
>> +++ /tmp/cocci-output-11792-b62223-mach-imx6q.c
>> @@ -211,7 +211,6 @@ static void __init imx6q_1588_init(void)
>>  	 * set bit IOMUXC_GPR1[21].  Or the PTP clock must be from pad
>>  	 * (external OSC), and we need to clear the bit.
>>  	 */
>> -	clksel = ptp_clk == enet_ref ? IMX6Q_GPR1_ENET_CLK_SEL_ANATOP :
>>  				       IMX6Q_GPR1_ENET_CLK_SEL_PAD;
>>  	gpr = syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
>>  	if (!IS_ERR(gpr))
> Any idea how to do the comparison here? Or should we rely that the bootloader
> sets this properly (it managed already to select a frequency)? The phy has no
> clock node in current DT's so we can check this.
>

This has been fixed by adding a clk_is_match() helper and using that to
compare instead of comparing raw pointers. It would be nice if we could
replace the patch with something else that doesn't require this helper
though. It looks like this is static board configuration, so I wonder
why we didn't just have a DT property that indicates how the gpr should
be configured for this particular board.

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


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

* [Cocci] [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
@ 2015-03-12 19:43                           ` Stephen Boyd
  0 siblings, 0 replies; 186+ messages in thread
From: Stephen Boyd @ 2015-03-12 19:43 UTC (permalink / raw)
  To: cocci

On 03/12/15 10:20, Sebastian Andrzej Siewior wrote:
> On 2015-02-17 14:01:04 [-0800], Stephen Boyd wrote:
>> diff = 
>> --- arch/arm/mach-imx/mach-imx6q.c
>> +++ /tmp/cocci-output-11792-b62223-mach-imx6q.c
>> @@ -211,7 +211,6 @@ static void __init imx6q_1588_init(void)
>>  	 * set bit IOMUXC_GPR1[21].  Or the PTP clock must be from pad
>>  	 * (external OSC), and we need to clear the bit.
>>  	 */
>> -	clksel = ptp_clk == enet_ref ? IMX6Q_GPR1_ENET_CLK_SEL_ANATOP :
>>  				       IMX6Q_GPR1_ENET_CLK_SEL_PAD;
>>  	gpr = syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
>>  	if (!IS_ERR(gpr))
> Any idea how to do the comparison here? Or should we rely that the bootloader
> sets this properly (it managed already to select a frequency)? The phy has no
> clock node in current DT's so we can check this.
>

This has been fixed by adding a clk_is_match() helper and using that to
compare instead of comparing raw pointers. It would be nice if we could
replace the patch with something else that doesn't require this helper
though. It looks like this is static board configuration, so I wonder
why we didn't just have a DT property that indicates how the gpr should
be configured for this particular board.

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

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

* [Cocci] [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
@ 2015-03-12 19:43                           ` Stephen Boyd
  0 siblings, 0 replies; 186+ messages in thread
From: Stephen Boyd @ 2015-03-12 19:43 UTC (permalink / raw)
  To: linux-arm-kernel

On 03/12/15 10:20, Sebastian Andrzej Siewior wrote:
> On 2015-02-17 14:01:04 [-0800], Stephen Boyd wrote:
>> diff = 
>> --- arch/arm/mach-imx/mach-imx6q.c
>> +++ /tmp/cocci-output-11792-b62223-mach-imx6q.c
>> @@ -211,7 +211,6 @@ static void __init imx6q_1588_init(void)
>>  	 * set bit IOMUXC_GPR1[21].  Or the PTP clock must be from pad
>>  	 * (external OSC), and we need to clear the bit.
>>  	 */
>> -	clksel = ptp_clk == enet_ref ? IMX6Q_GPR1_ENET_CLK_SEL_ANATOP :
>>  				       IMX6Q_GPR1_ENET_CLK_SEL_PAD;
>>  	gpr = syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
>>  	if (!IS_ERR(gpr))
> Any idea how to do the comparison here? Or should we rely that the bootloader
> sets this properly (it managed already to select a frequency)? The phy has no
> clock node in current DT's so we can check this.
>

This has been fixed by adding a clk_is_match() helper and using that to
compare instead of comparing raw pointers. It would be nice if we could
replace the patch with something else that doesn't require this helper
though. It looks like this is static board configuration, so I wonder
why we didn't just have a DT property that indicates how the gpr should
be configured for this particular board.

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

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

* Re: [Cocci] [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
  2015-03-12 19:43                           ` Stephen Boyd
  (?)
@ 2015-03-13  3:29                             ` Shawn Guo
  -1 siblings, 0 replies; 186+ messages in thread
From: Shawn Guo @ 2015-03-13  3:29 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Sebastian Andrzej Siewior, Quentin Lambert, Mike Turquette,
	Julia Lawall, Paul Walmsley, Tomeu Vizoso, Tony Lindgren,
	linux-kernel, t-kristo, linux-omap, cocci, linux-arm-kernel

On Thu, Mar 12, 2015 at 12:43:40PM -0700, Stephen Boyd wrote:
> On 03/12/15 10:20, Sebastian Andrzej Siewior wrote:
> > On 2015-02-17 14:01:04 [-0800], Stephen Boyd wrote:
> >> diff = 
> >> --- arch/arm/mach-imx/mach-imx6q.c
> >> +++ /tmp/cocci-output-11792-b62223-mach-imx6q.c
> >> @@ -211,7 +211,6 @@ static void __init imx6q_1588_init(void)
> >>  	 * set bit IOMUXC_GPR1[21].  Or the PTP clock must be from pad
> >>  	 * (external OSC), and we need to clear the bit.
> >>  	 */
> >> -	clksel = ptp_clk == enet_ref ? IMX6Q_GPR1_ENET_CLK_SEL_ANATOP :
> >>  				       IMX6Q_GPR1_ENET_CLK_SEL_PAD;
> >>  	gpr = syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
> >>  	if (!IS_ERR(gpr))
> > Any idea how to do the comparison here? Or should we rely that the bootloader
> > sets this properly (it managed already to select a frequency)? The phy has no
> > clock node in current DT's so we can check this.
> >
> 
> This has been fixed by adding a clk_is_match() helper and using that to
> compare instead of comparing raw pointers. It would be nice if we could
> replace the patch with something else that doesn't require this helper
> though. It looks like this is static board configuration, so I wonder
> why we didn't just have a DT property that indicates how the gpr should
> be configured for this particular board.

We did not add a DT property for it, because there was already enough
info (clock configuration) in DT for kernel to figure it out.

Shawn

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

* [Cocci] [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
@ 2015-03-13  3:29                             ` Shawn Guo
  0 siblings, 0 replies; 186+ messages in thread
From: Shawn Guo @ 2015-03-13  3:29 UTC (permalink / raw)
  To: cocci

On Thu, Mar 12, 2015 at 12:43:40PM -0700, Stephen Boyd wrote:
> On 03/12/15 10:20, Sebastian Andrzej Siewior wrote:
> > On 2015-02-17 14:01:04 [-0800], Stephen Boyd wrote:
> >> diff = 
> >> --- arch/arm/mach-imx/mach-imx6q.c
> >> +++ /tmp/cocci-output-11792-b62223-mach-imx6q.c
> >> @@ -211,7 +211,6 @@ static void __init imx6q_1588_init(void)
> >>  	 * set bit IOMUXC_GPR1[21].  Or the PTP clock must be from pad
> >>  	 * (external OSC), and we need to clear the bit.
> >>  	 */
> >> -	clksel = ptp_clk == enet_ref ? IMX6Q_GPR1_ENET_CLK_SEL_ANATOP :
> >>  				       IMX6Q_GPR1_ENET_CLK_SEL_PAD;
> >>  	gpr = syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
> >>  	if (!IS_ERR(gpr))
> > Any idea how to do the comparison here? Or should we rely that the bootloader
> > sets this properly (it managed already to select a frequency)? The phy has no
> > clock node in current DT's so we can check this.
> >
> 
> This has been fixed by adding a clk_is_match() helper and using that to
> compare instead of comparing raw pointers. It would be nice if we could
> replace the patch with something else that doesn't require this helper
> though. It looks like this is static board configuration, so I wonder
> why we didn't just have a DT property that indicates how the gpr should
> be configured for this particular board.

We did not add a DT property for it, because there was already enough
info (clock configuration) in DT for kernel to figure it out.

Shawn

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

* [Cocci] [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
@ 2015-03-13  3:29                             ` Shawn Guo
  0 siblings, 0 replies; 186+ messages in thread
From: Shawn Guo @ 2015-03-13  3:29 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Mar 12, 2015 at 12:43:40PM -0700, Stephen Boyd wrote:
> On 03/12/15 10:20, Sebastian Andrzej Siewior wrote:
> > On 2015-02-17 14:01:04 [-0800], Stephen Boyd wrote:
> >> diff = 
> >> --- arch/arm/mach-imx/mach-imx6q.c
> >> +++ /tmp/cocci-output-11792-b62223-mach-imx6q.c
> >> @@ -211,7 +211,6 @@ static void __init imx6q_1588_init(void)
> >>  	 * set bit IOMUXC_GPR1[21].  Or the PTP clock must be from pad
> >>  	 * (external OSC), and we need to clear the bit.
> >>  	 */
> >> -	clksel = ptp_clk == enet_ref ? IMX6Q_GPR1_ENET_CLK_SEL_ANATOP :
> >>  				       IMX6Q_GPR1_ENET_CLK_SEL_PAD;
> >>  	gpr = syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
> >>  	if (!IS_ERR(gpr))
> > Any idea how to do the comparison here? Or should we rely that the bootloader
> > sets this properly (it managed already to select a frequency)? The phy has no
> > clock node in current DT's so we can check this.
> >
> 
> This has been fixed by adding a clk_is_match() helper and using that to
> compare instead of comparing raw pointers. It would be nice if we could
> replace the patch with something else that doesn't require this helper
> though. It looks like this is static board configuration, so I wonder
> why we didn't just have a DT property that indicates how the gpr should
> be configured for this particular board.

We did not add a DT property for it, because there was already enough
info (clock configuration) in DT for kernel to figure it out.

Shawn

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

* Re: [Cocci] [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
  2015-03-13  3:29                             ` Shawn Guo
  (?)
@ 2015-03-13  8:20                               ` Sebastian Andrzej Siewior
  -1 siblings, 0 replies; 186+ messages in thread
From: Sebastian Andrzej Siewior @ 2015-03-13  8:20 UTC (permalink / raw)
  To: Shawn Guo
  Cc: Stephen Boyd, Quentin Lambert, Mike Turquette, Julia Lawall,
	Paul Walmsley, Tomeu Vizoso, Tony Lindgren, linux-kernel,
	t-kristo, linux-omap, cocci, linux-arm-kernel

Hi Shawn,

On Fri, Mar 13, 2015 at 11:29:32AM +0800, Shawn Guo wrote:

> We did not add a DT property for it, because there was already enough
> info (clock configuration) in DT for kernel to figure it out.
Correct. My understanding is whatever can be figured out without DT should
be done that way.

Is there a way to get this clock-select bit set without
enable_fec_anatop_clock() in u-boot? Because this one selects the clock and
frequency and also sets the proper bit in gpr1. My question is simply why do
we need to do this here as well.

> Shawn

Sebastian

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

* [Cocci] [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
@ 2015-03-13  8:20                               ` Sebastian Andrzej Siewior
  0 siblings, 0 replies; 186+ messages in thread
From: Sebastian Andrzej Siewior @ 2015-03-13  8:20 UTC (permalink / raw)
  To: cocci

Hi Shawn,

On Fri, Mar 13, 2015 at 11:29:32AM +0800, Shawn Guo wrote:

> We did not add a DT property for it, because there was already enough
> info (clock configuration) in DT for kernel to figure it out.
Correct. My understanding is whatever can be figured out without DT should
be done that way.

Is there a way to get this clock-select bit set without
enable_fec_anatop_clock() in u-boot? Because this one selects the clock and
frequency and also sets the proper bit in gpr1. My question is simply why do
we need to do this here as well.

> Shawn

Sebastian

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

* [Cocci] [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
@ 2015-03-13  8:20                               ` Sebastian Andrzej Siewior
  0 siblings, 0 replies; 186+ messages in thread
From: Sebastian Andrzej Siewior @ 2015-03-13  8:20 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Shawn,

On Fri, Mar 13, 2015 at 11:29:32AM +0800, Shawn Guo wrote:

> We did not add a DT property for it, because there was already enough
> info (clock configuration) in DT for kernel to figure it out.
Correct. My understanding is whatever can be figured out without DT should
be done that way.

Is there a way to get this clock-select bit set without
enable_fec_anatop_clock() in u-boot? Because this one selects the clock and
frequency and also sets the proper bit in gpr1. My question is simply why do
we need to do this here as well.

> Shawn

Sebastian

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

* Re: [Cocci] [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
  2015-03-13  8:20                               ` Sebastian Andrzej Siewior
  (?)
@ 2015-03-13 13:42                                 ` Shawn Guo
  -1 siblings, 0 replies; 186+ messages in thread
From: Shawn Guo @ 2015-03-13 13:42 UTC (permalink / raw)
  To: Sebastian Andrzej Siewior
  Cc: Stephen Boyd, Quentin Lambert, Mike Turquette, Julia Lawall,
	Paul Walmsley, Tomeu Vizoso, Tony Lindgren, linux-kernel,
	t-kristo, linux-omap, cocci, linux-arm-kernel

On Fri, Mar 13, 2015 at 09:20:10AM +0100, Sebastian Andrzej Siewior wrote:
> Hi Shawn,
> 
> On Fri, Mar 13, 2015 at 11:29:32AM +0800, Shawn Guo wrote:
> 
> > We did not add a DT property for it, because there was already enough
> > info (clock configuration) in DT for kernel to figure it out.
> Correct. My understanding is whatever can be figured out without DT should
> be done that way.
> 
> Is there a way to get this clock-select bit set without
> enable_fec_anatop_clock() in u-boot? Because this one selects the clock and
> frequency and also sets the proper bit in gpr1. My question is simply why do
> we need to do this here as well.

I'm not sure I follow your question.  But we had been doing this setup
in kernel function imx6q_1588_init() for a while.  The problem we're
having now is that the clk core change broke it since v4.0-rc1.  And the
fix is already queued there [1].

Shawn

[1] https://git.kernel.org/cgit/linux/kernel/git/clk/linux.git/log/?h=clk-fixes

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

* [Cocci] [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
@ 2015-03-13 13:42                                 ` Shawn Guo
  0 siblings, 0 replies; 186+ messages in thread
From: Shawn Guo @ 2015-03-13 13:42 UTC (permalink / raw)
  To: cocci

On Fri, Mar 13, 2015 at 09:20:10AM +0100, Sebastian Andrzej Siewior wrote:
> Hi Shawn,
> 
> On Fri, Mar 13, 2015 at 11:29:32AM +0800, Shawn Guo wrote:
> 
> > We did not add a DT property for it, because there was already enough
> > info (clock configuration) in DT for kernel to figure it out.
> Correct. My understanding is whatever can be figured out without DT should
> be done that way.
> 
> Is there a way to get this clock-select bit set without
> enable_fec_anatop_clock() in u-boot? Because this one selects the clock and
> frequency and also sets the proper bit in gpr1. My question is simply why do
> we need to do this here as well.

I'm not sure I follow your question.  But we had been doing this setup
in kernel function imx6q_1588_init() for a while.  The problem we're
having now is that the clk core change broke it since v4.0-rc1.  And the
fix is already queued there [1].

Shawn

[1] https://git.kernel.org/cgit/linux/kernel/git/clk/linux.git/log/?h=clk-fixes

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

* [Cocci] [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
@ 2015-03-13 13:42                                 ` Shawn Guo
  0 siblings, 0 replies; 186+ messages in thread
From: Shawn Guo @ 2015-03-13 13:42 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Mar 13, 2015 at 09:20:10AM +0100, Sebastian Andrzej Siewior wrote:
> Hi Shawn,
> 
> On Fri, Mar 13, 2015 at 11:29:32AM +0800, Shawn Guo wrote:
> 
> > We did not add a DT property for it, because there was already enough
> > info (clock configuration) in DT for kernel to figure it out.
> Correct. My understanding is whatever can be figured out without DT should
> be done that way.
> 
> Is there a way to get this clock-select bit set without
> enable_fec_anatop_clock() in u-boot? Because this one selects the clock and
> frequency and also sets the proper bit in gpr1. My question is simply why do
> we need to do this here as well.

I'm not sure I follow your question.  But we had been doing this setup
in kernel function imx6q_1588_init() for a while.  The problem we're
having now is that the clk core change broke it since v4.0-rc1.  And the
fix is already queued there [1].

Shawn

[1] https://git.kernel.org/cgit/linux/kernel/git/clk/linux.git/log/?h=clk-fixes

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

* Re: [Cocci] [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
  2015-03-13  3:29                             ` Shawn Guo
  (?)
@ 2015-03-13 17:42                               ` Stephen Boyd
  -1 siblings, 0 replies; 186+ messages in thread
From: Stephen Boyd @ 2015-03-13 17:42 UTC (permalink / raw)
  To: Shawn Guo
  Cc: Sebastian Andrzej Siewior, Quentin Lambert, Mike Turquette,
	Julia Lawall, Paul Walmsley, Tomeu Vizoso, Tony Lindgren,
	linux-kernel, t-kristo, linux-omap, cocci, linux-arm-kernel

On 03/12/15 20:29, Shawn Guo wrote:
> On Thu, Mar 12, 2015 at 12:43:40PM -0700, Stephen Boyd wrote:
>> On 03/12/15 10:20, Sebastian Andrzej Siewior wrote:
>>> On 2015-02-17 14:01:04 [-0800], Stephen Boyd wrote:
>>>> diff = 
>>>> --- arch/arm/mach-imx/mach-imx6q.c
>>>> +++ /tmp/cocci-output-11792-b62223-mach-imx6q.c
>>>> @@ -211,7 +211,6 @@ static void __init imx6q_1588_init(void)
>>>>  	 * set bit IOMUXC_GPR1[21].  Or the PTP clock must be from pad
>>>>  	 * (external OSC), and we need to clear the bit.
>>>>  	 */
>>>> -	clksel = ptp_clk == enet_ref ? IMX6Q_GPR1_ENET_CLK_SEL_ANATOP :
>>>>  				       IMX6Q_GPR1_ENET_CLK_SEL_PAD;
>>>>  	gpr = syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
>>>>  	if (!IS_ERR(gpr))
>>> Any idea how to do the comparison here? Or should we rely that the bootloader
>>> sets this properly (it managed already to select a frequency)? The phy has no
>>> clock node in current DT's so we can check this.
>>>
>> This has been fixed by adding a clk_is_match() helper and using that to
>> compare instead of comparing raw pointers. It would be nice if we could
>> replace the patch with something else that doesn't require this helper
>> though. It looks like this is static board configuration, so I wonder
>> why we didn't just have a DT property that indicates how the gpr should
>> be configured for this particular board.
> We did not add a DT property for it, because there was already enough
> info (clock configuration) in DT for kernel to figure it out.

Ok well then if everything is in DT we don't need to be comparing clock
pointers at all, right? We should be able to write up some DT parsing
logic to figure it out?

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


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

* [Cocci] [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
@ 2015-03-13 17:42                               ` Stephen Boyd
  0 siblings, 0 replies; 186+ messages in thread
From: Stephen Boyd @ 2015-03-13 17:42 UTC (permalink / raw)
  To: cocci

On 03/12/15 20:29, Shawn Guo wrote:
> On Thu, Mar 12, 2015 at 12:43:40PM -0700, Stephen Boyd wrote:
>> On 03/12/15 10:20, Sebastian Andrzej Siewior wrote:
>>> On 2015-02-17 14:01:04 [-0800], Stephen Boyd wrote:
>>>> diff = 
>>>> --- arch/arm/mach-imx/mach-imx6q.c
>>>> +++ /tmp/cocci-output-11792-b62223-mach-imx6q.c
>>>> @@ -211,7 +211,6 @@ static void __init imx6q_1588_init(void)
>>>>  	 * set bit IOMUXC_GPR1[21].  Or the PTP clock must be from pad
>>>>  	 * (external OSC), and we need to clear the bit.
>>>>  	 */
>>>> -	clksel = ptp_clk == enet_ref ? IMX6Q_GPR1_ENET_CLK_SEL_ANATOP :
>>>>  				       IMX6Q_GPR1_ENET_CLK_SEL_PAD;
>>>>  	gpr = syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
>>>>  	if (!IS_ERR(gpr))
>>> Any idea how to do the comparison here? Or should we rely that the bootloader
>>> sets this properly (it managed already to select a frequency)? The phy has no
>>> clock node in current DT's so we can check this.
>>>
>> This has been fixed by adding a clk_is_match() helper and using that to
>> compare instead of comparing raw pointers. It would be nice if we could
>> replace the patch with something else that doesn't require this helper
>> though. It looks like this is static board configuration, so I wonder
>> why we didn't just have a DT property that indicates how the gpr should
>> be configured for this particular board.
> We did not add a DT property for it, because there was already enough
> info (clock configuration) in DT for kernel to figure it out.

Ok well then if everything is in DT we don't need to be comparing clock
pointers at all, right? We should be able to write up some DT parsing
logic to figure it out?

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

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

* [Cocci] [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances
@ 2015-03-13 17:42                               ` Stephen Boyd
  0 siblings, 0 replies; 186+ messages in thread
From: Stephen Boyd @ 2015-03-13 17:42 UTC (permalink / raw)
  To: linux-arm-kernel

On 03/12/15 20:29, Shawn Guo wrote:
> On Thu, Mar 12, 2015 at 12:43:40PM -0700, Stephen Boyd wrote:
>> On 03/12/15 10:20, Sebastian Andrzej Siewior wrote:
>>> On 2015-02-17 14:01:04 [-0800], Stephen Boyd wrote:
>>>> diff = 
>>>> --- arch/arm/mach-imx/mach-imx6q.c
>>>> +++ /tmp/cocci-output-11792-b62223-mach-imx6q.c
>>>> @@ -211,7 +211,6 @@ static void __init imx6q_1588_init(void)
>>>>  	 * set bit IOMUXC_GPR1[21].  Or the PTP clock must be from pad
>>>>  	 * (external OSC), and we need to clear the bit.
>>>>  	 */
>>>> -	clksel = ptp_clk == enet_ref ? IMX6Q_GPR1_ENET_CLK_SEL_ANATOP :
>>>>  				       IMX6Q_GPR1_ENET_CLK_SEL_PAD;
>>>>  	gpr = syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
>>>>  	if (!IS_ERR(gpr))
>>> Any idea how to do the comparison here? Or should we rely that the bootloader
>>> sets this properly (it managed already to select a frequency)? The phy has no
>>> clock node in current DT's so we can check this.
>>>
>> This has been fixed by adding a clk_is_match() helper and using that to
>> compare instead of comparing raw pointers. It would be nice if we could
>> replace the patch with something else that doesn't require this helper
>> though. It looks like this is static board configuration, so I wonder
>> why we didn't just have a DT property that indicates how the gpr should
>> be configured for this particular board.
> We did not add a DT property for it, because there was already enough
> info (clock configuration) in DT for kernel to figure it out.

Ok well then if everything is in DT we don't need to be comparing clock
pointers at all, right? We should be able to write up some DT parsing
logic to figure it out?

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

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

end of thread, other threads:[~2015-03-13 17:42 UTC | newest]

Thread overview: 186+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-01-23 11:03 [PATCH v13 0/6] Per-user clock constraints Tomeu Vizoso
2015-01-23 11:03 ` [PATCH v13 1/6] clk: Remove unneeded NULL checks Tomeu Vizoso
2015-01-23 11:03 ` [PATCH v13 2/6] clk: Remove __clk_register Tomeu Vizoso
2015-01-23 11:03 ` [PATCH v13 3/6] clk: Make clk API return per-user struct clk instances Tomeu Vizoso
2015-01-23 11:03   ` Tomeu Vizoso
2015-02-01 21:24   ` Mike Turquette
2015-02-01 21:24     ` Mike Turquette
2015-02-01 21:24     ` Mike Turquette
2015-02-02 17:04     ` Tony Lindgren
2015-02-02 17:04       ` Tony Lindgren
2015-02-02 17:32       ` Mike Turquette
2015-02-02 17:32         ` Mike Turquette
2015-02-02 19:32     ` Tero Kristo
2015-02-02 19:32       ` Tero Kristo
2015-02-02 19:32       ` Tero Kristo
2015-02-02 20:44       ` Tony Lindgren
2015-02-02 20:44         ` Tony Lindgren
2015-02-02 22:48         ` Mike Turquette
2015-02-02 22:48           ` Mike Turquette
2015-02-02 23:11           ` Tony Lindgren
2015-02-02 23:11             ` Tony Lindgren
2015-02-02 22:41       ` Mike Turquette
2015-02-02 22:41         ` Mike Turquette
2015-02-02 22:52         ` Stephen Boyd
2015-02-02 22:52           ` Stephen Boyd
2015-02-03  7:03         ` Tomeu Vizoso
2015-02-03  7:03           ` Tomeu Vizoso
2015-02-03  8:46           ` Tero Kristo
2015-02-03  8:46             ` Tero Kristo
2015-02-03  8:46             ` Tero Kristo
2015-02-03 15:22             ` Tony Lindgren
2015-02-03 15:22               ` Tony Lindgren
2015-02-02 20:45     ` Stephen Boyd
2015-02-02 20:45       ` Stephen Boyd
2015-02-02 20:45       ` [Cocci] " Stephen Boyd
2015-02-02 21:31       ` Julia Lawall
2015-02-02 21:31         ` Julia Lawall
2015-02-02 21:31         ` [Cocci] " Julia Lawall
2015-02-02 22:35         ` Stephen Boyd
2015-02-02 22:35           ` Stephen Boyd
2015-02-02 22:35           ` [Cocci] " Stephen Boyd
2015-02-02 22:50           ` Mike Turquette
2015-02-02 22:50             ` Mike Turquette
2015-02-02 22:50             ` [Cocci] " Mike Turquette
2015-02-03 16:04             ` Quentin Lambert
2015-02-03 16:04               ` Quentin Lambert
2015-02-03 16:04               ` Quentin Lambert
2015-02-04 23:26               ` Stephen Boyd
2015-02-04 23:26                 ` Stephen Boyd
2015-02-04 23:26                 ` Stephen Boyd
2015-02-05 15:45                 ` Quentin Lambert
2015-02-05 15:45                   ` Quentin Lambert
2015-02-05 15:45                   ` Quentin Lambert
2015-02-05 16:02                   ` Quentin Lambert
2015-02-05 16:02                     ` Quentin Lambert
2015-02-05 16:02                     ` Quentin Lambert
2015-02-06  1:49                     ` Stephen Boyd
2015-02-06  1:49                       ` Stephen Boyd
2015-02-06  1:49                       ` Stephen Boyd
2015-02-06  2:15                   ` Stephen Boyd
2015-02-06  2:15                     ` Stephen Boyd
2015-02-06  2:15                     ` Stephen Boyd
2015-02-06  9:01                     ` Quentin Lambert
2015-02-06  9:01                       ` Quentin Lambert
2015-02-06  9:01                       ` Quentin Lambert
2015-02-06  9:12                       ` Julia Lawall
2015-02-06  9:12                         ` Julia Lawall
2015-02-06  9:12                         ` Julia Lawall
2015-02-06 17:15                         ` Stephen Boyd
2015-02-06 17:15                           ` Stephen Boyd
2015-02-06 17:15                           ` Stephen Boyd
2015-02-17 22:01                     ` Stephen Boyd
2015-02-17 22:01                       ` Stephen Boyd
2015-02-17 22:01                       ` Stephen Boyd
2015-03-12 17:20                       ` Sebastian Andrzej Siewior
2015-03-12 17:20                         ` Sebastian Andrzej Siewior
2015-03-12 17:20                         ` Sebastian Andrzej Siewior
2015-03-12 19:43                         ` Stephen Boyd
2015-03-12 19:43                           ` Stephen Boyd
2015-03-12 19:43                           ` Stephen Boyd
2015-03-13  3:29                           ` Shawn Guo
2015-03-13  3:29                             ` Shawn Guo
2015-03-13  3:29                             ` Shawn Guo
2015-03-13  8:20                             ` Sebastian Andrzej Siewior
2015-03-13  8:20                               ` Sebastian Andrzej Siewior
2015-03-13  8:20                               ` Sebastian Andrzej Siewior
2015-03-13 13:42                               ` Shawn Guo
2015-03-13 13:42                                 ` Shawn Guo
2015-03-13 13:42                                 ` Shawn Guo
2015-03-13 17:42                             ` Stephen Boyd
2015-03-13 17:42                               ` Stephen Boyd
2015-03-13 17:42                               ` Stephen Boyd
2015-02-05 19:44   ` Sylwester Nawrocki
2015-02-05 19:44     ` Sylwester Nawrocki
2015-02-05 20:06     ` Sylwester Nawrocki
2015-02-05 20:06       ` Sylwester Nawrocki
2015-02-05 20:07     ` Stephen Boyd
2015-02-05 20:07       ` Stephen Boyd
2015-02-05 22:14       ` Stephen Boyd
2015-02-05 22:14         ` Stephen Boyd
2015-02-06  0:42         ` Russell King - ARM Linux
2015-02-06  0:42           ` Russell King - ARM Linux
2015-02-06  1:35           ` Stephen Boyd
2015-02-06  1:35             ` Stephen Boyd
2015-02-06 13:39             ` Russell King - ARM Linux
2015-02-06 13:39               ` Russell King - ARM Linux
2015-02-06 19:30               ` Stephen Boyd
2015-02-06 19:30                 ` Stephen Boyd
2015-02-06 19:37                 ` Russell King - ARM Linux
2015-02-06 19:37                   ` Russell King - ARM Linux
2015-02-06 19:41                   ` Stephen Boyd
2015-02-06 19:41                     ` Stephen Boyd
2015-02-19 21:32                 ` Mike Turquette
2015-02-19 21:32                   ` Mike Turquette
2015-02-24 14:08                   ` Russell King - ARM Linux
2015-02-24 14:08                     ` Russell King - ARM Linux
2015-02-25  2:18                     ` Mike Turquette
2015-02-25  2:18                       ` Mike Turquette
2015-01-23 11:03 ` [PATCH v13 4/6] clk: Add rate constraints to clocks Tomeu Vizoso
2015-01-23 11:03   ` Tomeu Vizoso
2015-01-23 11:03   ` Tomeu Vizoso
2015-01-29 13:31   ` Geert Uytterhoeven
2015-01-29 13:31     ` Geert Uytterhoeven
2015-01-29 13:31     ` Geert Uytterhoeven
2015-01-29 13:31     ` Geert Uytterhoeven
2015-01-29 19:13     ` Stephen Boyd
2015-01-29 19:13       ` Stephen Boyd
2015-01-29 19:13       ` Stephen Boyd
2015-01-29 19:13       ` Stephen Boyd
2015-01-31  1:31       ` Stephen Boyd
2015-01-31  1:31         ` Stephen Boyd
2015-01-31  1:31         ` Stephen Boyd
2015-01-31  1:31         ` Stephen Boyd
2015-01-31  1:31         ` Stephen Boyd
2015-01-31 18:36         ` Tomeu Vizoso
2015-01-31 18:36           ` Tomeu Vizoso
2015-01-31 18:36           ` Tomeu Vizoso
2015-01-31 18:36           ` Tomeu Vizoso
2015-01-31 18:36           ` Tomeu Vizoso
2015-02-01 22:18           ` Mike Turquette
2015-02-01 22:18             ` Mike Turquette
2015-02-01 22:18             ` Mike Turquette
2015-02-01 22:18             ` Mike Turquette
2015-02-01 22:18             ` Mike Turquette
2015-02-02  7:59             ` Geert Uytterhoeven
2015-02-02  7:59               ` Geert Uytterhoeven
2015-02-02  7:59               ` Geert Uytterhoeven
2015-02-02  7:59               ` Geert Uytterhoeven
2015-02-02  7:59               ` Geert Uytterhoeven
2015-02-02 16:12               ` Tony Lindgren
2015-02-02 16:12                 ` Tony Lindgren
2015-02-02 16:12                 ` Tony Lindgren
2015-02-02 16:12                 ` Tony Lindgren
2015-02-02 16:12                 ` Tony Lindgren
2015-02-02 17:46                 ` Mike Turquette
2015-02-02 17:46                   ` Mike Turquette
2015-02-02 17:46                   ` Mike Turquette
2015-02-02 17:46                   ` Mike Turquette
2015-02-02 17:46                   ` Mike Turquette
2015-02-02 17:49                   ` Russell King - ARM Linux
2015-02-02 17:49                     ` Russell King - ARM Linux
2015-02-02 17:49                     ` Russell King - ARM Linux
2015-02-02 17:49                     ` Russell King - ARM Linux
2015-02-02 17:49                     ` Russell King - ARM Linux
2015-02-02 19:21                   ` Tony Lindgren
2015-02-02 19:21                     ` Tony Lindgren
2015-02-02 19:21                     ` Tony Lindgren
2015-02-02 19:21                     ` Tony Lindgren
2015-02-02 19:21                     ` Tony Lindgren
2015-02-02 20:47                     ` Tony Lindgren
2015-02-02 20:47                       ` Tony Lindgren
2015-02-02 20:47                       ` Tony Lindgren
2015-02-02 20:47                       ` Tony Lindgren
2015-02-02 20:47                       ` Tony Lindgren
2015-01-23 11:03 ` [PATCH v13 5/6] clkdev: Export clk_register_clkdev Tomeu Vizoso
2015-01-23 11:03   ` Tomeu Vizoso
2015-02-03 17:35   ` Andy Shevchenko
2015-02-03 17:35     ` Andy Shevchenko
2015-02-03 17:43     ` Andy Shevchenko
2015-02-03 17:43       ` Andy Shevchenko
2015-01-23 11:03 ` [PATCH v13 6/6] clk: Add module for unit tests Tomeu Vizoso
2015-01-27  0:55 ` [PATCH v13 0/6] Per-user clock constraints Stephen Boyd
2015-01-27  6:29   ` Tomeu Vizoso
2015-01-28  6:59   ` Tomeu Vizoso
     [not found]     ` <20150129022633.22722.78592@quantum>
2015-01-29  6:41       ` Tomeu Vizoso
2015-01-29 14:29         ` Mike Turquette

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.