[PATCH v3] Common clock: To list active consumers of clocks

Vishal Badole posted 1 patch 3 years, 8 months ago
There is a newer version of this series
drivers/clk/clk.c | 46 +++++++++++++++++++++++++++++++++++-----------
1 file changed, 35 insertions(+), 11 deletions(-)
[PATCH v3] Common clock: To list active consumers of clocks
Posted by Vishal Badole 3 years, 8 months ago
This feature lists the clock consumer's name and per-user enable count
in clock summary. Using this feature user can easily check which device
has acquired a perticular clock and it is enabled by respective device
or not.
for example:
$ cat /sys/kernel/debug/clk/clk_summary
                      enable  prepare  protect                           duty  hardware                            per-user
   clock               count    count    count    rate   accuracy phase cycle    enable   consumer                    count
----------------------------------------------------------------------------------------------------------------------------
 clk_mcasp0_fixed         0        0        0    24576000      0     0  50000     Y      deviceless                      0
                                                                                         deviceless                      0
    clk_mcasp0            0        0        0    24576000      0     0  50000     N          simple-audio-card,cpu           0
                                                                                             deviceless                      0

Co-developed-by: Chinmoy Ghosh <chinmoyghosh2001@gmail.com>
Signed-off-by: Chinmoy Ghosh <chinmoyghosh2001@gmail.com>
Co-developed-by: Mintu Patel <mintupatel89@gmail.com>
Signed-off-by: Mintu Patel <mintupatel89@gmail.com>
Co-developed-by: Vimal Kumar <vimal.kumar32@gmail.com>
Signed-off-by: Vimal Kumar <vimal.kumar32@gmail.com>
Signed-off-by: Vishal Badole <badolevishal1116@gmail.com>
---
 drivers/clk/clk.c | 46 +++++++++++++++++++++++++++++++++++-----------
 1 file changed, 35 insertions(+), 11 deletions(-)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index f00d4c1..c96079f 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -102,6 +102,7 @@ struct clk {
 	unsigned long min_rate;
 	unsigned long max_rate;
 	unsigned int exclusive_count;
+	unsigned int enable_count;
 	struct hlist_node clks_node;
 };
 
@@ -1008,6 +1009,10 @@ void clk_disable(struct clk *clk)
 		return;
 
 	clk_core_disable_lock(clk->core);
+
+	if (clk->enable_count > 0)
+		clk->enable_count--;
+
 }
 EXPORT_SYMBOL_GPL(clk_disable);
 
@@ -1169,10 +1174,16 @@ EXPORT_SYMBOL_GPL(clk_restore_context);
  */
 int clk_enable(struct clk *clk)
 {
+	int ret;
+
 	if (!clk)
 		return 0;
 
-	return clk_core_enable_lock(clk->core);
+	ret = clk_core_enable_lock(clk->core);
+	if (!ret)
+		clk->enable_count++;
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(clk_enable);
 
@@ -2953,28 +2964,41 @@ static void clk_summary_show_one(struct seq_file *s, struct clk_core *c,
 				 int level)
 {
 	int phase;
+	struct clk *clk_user;
+	int multi_node = 0;
 
-	seq_printf(s, "%*s%-*s %7d %8d %8d %11lu %10lu ",
+	seq_printf(s, "%*s%-*s %-7d %-8d %-8d %-11lu %-10lu ",
 		   level * 3 + 1, "",
-		   30 - level * 3, c->name,
+		   35 - level * 3, c->name,
 		   c->enable_count, c->prepare_count, c->protect_count,
 		   clk_core_get_rate_recalc(c),
 		   clk_core_get_accuracy_recalc(c));
 
 	phase = clk_core_get_phase(c);
 	if (phase >= 0)
-		seq_printf(s, "%5d", phase);
+		seq_printf(s, "%-5d", phase);
 	else
 		seq_puts(s, "-----");
 
-	seq_printf(s, " %6d", clk_core_get_scaled_duty_cycle(c, 100000));
+	seq_printf(s, " %-6d", clk_core_get_scaled_duty_cycle(c, 100000));
 
 	if (c->ops->is_enabled)
-		seq_printf(s, " %9c\n", clk_core_is_enabled(c) ? 'Y' : 'N');
+		seq_printf(s, " %5c ", clk_core_is_enabled(c) ? 'Y' : 'N');
 	else if (!c->ops->enable)
-		seq_printf(s, " %9c\n", 'Y');
+		seq_printf(s, " %5c ", 'Y');
 	else
-		seq_printf(s, " %9c\n", '?');
+		seq_printf(s, " %5c ", '?');
+
+	hlist_for_each_entry(clk_user, &c->clks, clks_node) {
+		seq_printf(s, "%*s%-*s  %-4d\n",
+			   level * 3 + 2 + 105 * multi_node, "",
+			   30,
+			   clk_user->dev_id ? clk_user->dev_id : "deviceless",
+			   clk_user->enable_count);
+
+		multi_node = 1;
+	}
+
 }
 
 static void clk_summary_show_subtree(struct seq_file *s, struct clk_core *c,
@@ -2995,9 +3019,9 @@ static int clk_summary_show(struct seq_file *s, void *data)
 	struct clk_core *c;
 	struct hlist_head **lists = (struct hlist_head **)s->private;
 
-	seq_puts(s, "                                 enable  prepare  protect                                duty  hardware\n");
-	seq_puts(s, "   clock                          count    count    count        rate   accuracy phase  cycle    enable\n");
-	seq_puts(s, "-------------------------------------------------------------------------------------------------------\n");
+	seq_puts(s, "                                 enable  prepare  protect                                duty  hardware                            per-user\n");
+	seq_puts(s, "   clock                          count    count    count        rate   accuracy phase  cycle    enable   consumer                    count\n");
+	seq_puts(s, "-------------------------------------------------------------------------------------------------------------------------------------------\n");
 
 	clk_prepare_lock();
 
-- 
2.7.4
Re: [PATCH v3] Common clock: To list active consumers of clocks
Posted by Stephen Boyd 3 years, 7 months ago
Quoting Vishal Badole (2022-08-02 11:09:47)
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> index f00d4c1..c96079f 100644
> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> @@ -102,6 +102,7 @@ struct clk {
>         unsigned long min_rate;
>         unsigned long max_rate;
>         unsigned int exclusive_count;
> +       unsigned int enable_count;
>         struct hlist_node clks_node;
>  };
>  
> @@ -1008,6 +1009,10 @@ void clk_disable(struct clk *clk)
>                 return;
>  
>         clk_core_disable_lock(clk->core);
> +
> +       if (clk->enable_count > 0)
> +               clk->enable_count--;
> +
>  }
>  EXPORT_SYMBOL_GPL(clk_disable);
>  
> @@ -1169,10 +1174,16 @@ EXPORT_SYMBOL_GPL(clk_restore_context);
>   */
>  int clk_enable(struct clk *clk)
>  {
> +       int ret;
> +
>         if (!clk)
>                 return 0;
>  
> -       return clk_core_enable_lock(clk->core);
> +       ret = clk_core_enable_lock(clk->core);
> +       if (!ret)
> +               clk->enable_count++;
> +
> +       return ret;
>  }
>  EXPORT_SYMBOL_GPL(clk_enable);

We'll want the above three hunks to be a different patch so we can
discuss the merits of tracking per user enable counts. Do you have a
usecase for this or is it "just for fun"? By adding a count we have more
code, and we waste more memory to track this stat. I really would rather
not bloat just because, so please elaborate on your use case.

>  
> @@ -2953,28 +2964,41 @@ static void clk_summary_show_one(struct seq_file *s, struct clk_core *c,
>                                  int level)
>  {
>         int phase;
> +       struct clk *clk_user;
> +       int multi_node = 0;
>  
> -       seq_printf(s, "%*s%-*s %7d %8d %8d %11lu %10lu ",
> +       seq_printf(s, "%*s%-*s %-7d %-8d %-8d %-11lu %-10lu ",
>                    level * 3 + 1, "",
> -                  30 - level * 3, c->name,
> +                  35 - level * 3, c->name,
>                    c->enable_count, c->prepare_count, c->protect_count,
>                    clk_core_get_rate_recalc(c),
>                    clk_core_get_accuracy_recalc(c));
>  
>         phase = clk_core_get_phase(c);
>         if (phase >= 0)
> -               seq_printf(s, "%5d", phase);
> +               seq_printf(s, "%-5d", phase);
>         else
>                 seq_puts(s, "-----");
>  
> -       seq_printf(s, " %6d", clk_core_get_scaled_duty_cycle(c, 100000));
> +       seq_printf(s, " %-6d", clk_core_get_scaled_duty_cycle(c, 100000));
>  
>         if (c->ops->is_enabled)
> -               seq_printf(s, " %9c\n", clk_core_is_enabled(c) ? 'Y' : 'N');
> +               seq_printf(s, " %5c ", clk_core_is_enabled(c) ? 'Y' : 'N');
>         else if (!c->ops->enable)
> -               seq_printf(s, " %9c\n", 'Y');
> +               seq_printf(s, " %5c ", 'Y');
>         else
> -               seq_printf(s, " %9c\n", '?');
> +               seq_printf(s, " %5c ", '?');
> +
> +       hlist_for_each_entry(clk_user, &c->clks, clks_node) {
> +               seq_printf(s, "%*s%-*s  %-4d\n",
> +                          level * 3 + 2 + 105 * multi_node, "",
> +                          30,
> +                          clk_user->dev_id ? clk_user->dev_id : "deviceless",
> +                          clk_user->enable_count);
> +
> +               multi_node = 1;

This part that prints the dev_id might be useful and can be the first
patch in the series. In that same patch, please print the con_id so we
know which clk it is for the device. We should also improve of_clk_get()
so that the index is visible to the 'struct clk::con_id' somehow. Maybe
we can convert the integer index into a string and assign that to con_id
in that case as well.
Re: [PATCH v3] Common clock: To list active consumers of clocks
Posted by <Vishal Badole> 3 years, 4 months ago
Hi Stephen,
As per your suggestions, we have updated and sent another gerrit with
message Id <1669569799-8526-1-git-send-email-badolevishal1116@gmail.com>
In this new patch we are listing the clock consumers name along with
consumer id in clk_summary.

example:
cat /sys/kernel/debug/clk/clk_summary
                      enable  prepare  protect
                             		                             duty  hardware                                Connection
clock               count    count    count  rate   accuracy phase  cycle    enable       consumer                         Id
------------------------------------------------------------------------------------------------------------------------------
clk_mcasp0_fixed       0        0        0   24576000     0     0   50000     Y            deviceless                   of_clk_get_from_provider   
			                                                                   deviceless                   no_connection_id   
  clk_mcasp0           0        0        0   24576000     0     0   50000     N              simple-audio-card,cpu        deviceless
											     no_connection_id   	  no_connection_id

Please review the latest patch.

New patch details:

Message ID: <1669569799-8526-1-git-send-email-badolevishal1116@gmail.com>
Subject:	[PATCH v5] Common clock: To list active consumers of clocks

Regards,
Vishal
Re: [PATCH v3] Common clock: To list active consumers of clocks
Posted by <Vishal Badole> 3 years, 7 months ago
On Mon, Aug 22, 2022 at 04:50:12PM -0700, Stephen Boyd wrote:
> Quoting Vishal Badole (2022-08-02 11:09:47)
> > diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> > index f00d4c1..c96079f 100644
> > --- a/drivers/clk/clk.c
> > +++ b/drivers/clk/clk.c
> > @@ -102,6 +102,7 @@ struct clk {
> >         unsigned long min_rate;
> >         unsigned long max_rate;
> >         unsigned int exclusive_count;
> > +       unsigned int enable_count;
> >         struct hlist_node clks_node;
> >  };
> >  
> > @@ -1008,6 +1009,10 @@ void clk_disable(struct clk *clk)
> >                 return;
> >  
> >         clk_core_disable_lock(clk->core);
> > +
> > +       if (clk->enable_count > 0)
> > +               clk->enable_count--;
> > +
> >  }
> >  EXPORT_SYMBOL_GPL(clk_disable);
> >  
> > @@ -1169,10 +1174,16 @@ EXPORT_SYMBOL_GPL(clk_restore_context);
> >   */
> >  int clk_enable(struct clk *clk)
> >  {
> > +       int ret;
> > +
> >         if (!clk)
> >                 return 0;
> >  
> > -       return clk_core_enable_lock(clk->core);
> > +       ret = clk_core_enable_lock(clk->core);
> > +       if (!ret)
> > +               clk->enable_count++;
> > +
> > +       return ret;
> >  }
> >  EXPORT_SYMBOL_GPL(clk_enable);
> 
> We'll want the above three hunks to be a different patch so we can
> discuss the merits of tracking per user enable counts. 
Agreed, we will create a separate patch for the same.

> Do you have a usecase for this or is it "just for fun"? By adding a count we have more
> code, and we waste more memory to track this stat. I really would rather
> not bloat just because, so please elaborate on your use case.
> 
Use case for per user count: If a consumer acquires the clocks without 
calling clk_get() or devm_clk_get() and enables without calling clk_enable() 
or clk_prepare_enable() (by bypassing the common clock framework), then dev_id 
will not be sufficient to tell about how clk is acquired. Here per user enable 
count can be used to tell that how clk is acquired and it is enabled by
that particular device or not in case also where dev_id is NULL.

We referred regualtor framework suggested by you in one of review point
where they are also using enable count.
> >  
> > @@ -2953,28 +2964,41 @@ static void clk_summary_show_one(struct seq_file *s, struct clk_core *c,
> >                                  int level)
> >  {
> >         int phase;
> > +       struct clk *clk_user;
> > +       int multi_node = 0;
> >  
> > -       seq_printf(s, "%*s%-*s %7d %8d %8d %11lu %10lu ",
> > +       seq_printf(s, "%*s%-*s %-7d %-8d %-8d %-11lu %-10lu ",
> >                    level * 3 + 1, "",
> > -                  30 - level * 3, c->name,
> > +                  35 - level * 3, c->name,
> >                    c->enable_count, c->prepare_count, c->protect_count,
> >                    clk_core_get_rate_recalc(c),
> >                    clk_core_get_accuracy_recalc(c));
> >  
> >         phase = clk_core_get_phase(c);
> >         if (phase >= 0)
> > -               seq_printf(s, "%5d", phase);
> > +               seq_printf(s, "%-5d", phase);
> >         else
> >                 seq_puts(s, "-----");
> >  
> > -       seq_printf(s, " %6d", clk_core_get_scaled_duty_cycle(c, 100000));
> > +       seq_printf(s, " %-6d", clk_core_get_scaled_duty_cycle(c, 100000));
> >  
> >         if (c->ops->is_enabled)
> > -               seq_printf(s, " %9c\n", clk_core_is_enabled(c) ? 'Y' : 'N');
> > +               seq_printf(s, " %5c ", clk_core_is_enabled(c) ? 'Y' : 'N');
> >         else if (!c->ops->enable)
> > -               seq_printf(s, " %9c\n", 'Y');
> > +               seq_printf(s, " %5c ", 'Y');
> >         else
> > -               seq_printf(s, " %9c\n", '?');
> > +               seq_printf(s, " %5c ", '?');
> > +
> > +       hlist_for_each_entry(clk_user, &c->clks, clks_node) {
> > +               seq_printf(s, "%*s%-*s  %-4d\n",
> > +                          level * 3 + 2 + 105 * multi_node, "",
> > +                          30,
> > +                          clk_user->dev_id ? clk_user->dev_id : "deviceless",
> > +                          clk_user->enable_count);
> > +
> > +               multi_node = 1;
> 
> This part that prints the dev_id might be useful and can be the first
> patch in the series. In that same patch, please print the con_id so we
> know which clk it is for the device. We should also improve of_clk_get()
> so that the index is visible to the 'struct clk::con_id' somehow. Maybe
> we can convert the integer index into a string and assign that to con_id
> in that case as well.

Agreed, We will create a fresh patch where we will print dev_id and
consumer id in clock summary.
Re: [PATCH v3] Common clock: To list active consumers of clocks
Posted by <Vishal Badole> 3 years, 7 months ago
On Tue, Aug 02, 2022 at 11:39:47PM +0530, Vishal Badole wrote:
> This feature lists the clock consumer's name and per-user enable count
> in clock summary. Using this feature user can easily check which device
> has acquired a perticular clock and it is enabled by respective device
> or not.
> for example:
> $ cat /sys/kernel/debug/clk/clk_summary
>                       enable  prepare  protect                           duty  hardware                            per-user
>    clock               count    count    count    rate   accuracy phase cycle    enable   consumer                    count
> ----------------------------------------------------------------------------------------------------------------------------
>  clk_mcasp0_fixed         0        0        0    24576000      0     0  50000     Y      deviceless                      0
>                                                                                          deviceless                      0
>     clk_mcasp0            0        0        0    24576000      0     0  50000     N          simple-audio-card,cpu           0
>                                                                                              deviceless                      0
> 
> Co-developed-by: Chinmoy Ghosh <chinmoyghosh2001@gmail.com>
> Signed-off-by: Chinmoy Ghosh <chinmoyghosh2001@gmail.com>
> Co-developed-by: Mintu Patel <mintupatel89@gmail.com>
> Signed-off-by: Mintu Patel <mintupatel89@gmail.com>
> Co-developed-by: Vimal Kumar <vimal.kumar32@gmail.com>
> Signed-off-by: Vimal Kumar <vimal.kumar32@gmail.com>
> Signed-off-by: Vishal Badole <badolevishal1116@gmail.com>
> ---
>  drivers/clk/clk.c | 46 +++++++++++++++++++++++++++++++++++-----------
>  1 file changed, 35 insertions(+), 11 deletions(-)
> 
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> index f00d4c1..c96079f 100644
> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> @@ -102,6 +102,7 @@ struct clk {
>  	unsigned long min_rate;
>  	unsigned long max_rate;
>  	unsigned int exclusive_count;
> +	unsigned int enable_count;
>  	struct hlist_node clks_node;
>  };
>  
> @@ -1008,6 +1009,10 @@ void clk_disable(struct clk *clk)
>  		return;
>  
>  	clk_core_disable_lock(clk->core);
> +
> +	if (clk->enable_count > 0)
> +		clk->enable_count--;
> +
>  }
>  EXPORT_SYMBOL_GPL(clk_disable);
>  
> @@ -1169,10 +1174,16 @@ EXPORT_SYMBOL_GPL(clk_restore_context);
>   */
>  int clk_enable(struct clk *clk)
>  {
> +	int ret;
> +
>  	if (!clk)
>  		return 0;
>  
> -	return clk_core_enable_lock(clk->core);
> +	ret = clk_core_enable_lock(clk->core);
> +	if (!ret)
> +		clk->enable_count++;
> +
> +	return ret;
>  }
>  EXPORT_SYMBOL_GPL(clk_enable);
>  
> @@ -2953,28 +2964,41 @@ static void clk_summary_show_one(struct seq_file *s, struct clk_core *c,
>  				 int level)
>  {
>  	int phase;
> +	struct clk *clk_user;
> +	int multi_node = 0;
>  
> -	seq_printf(s, "%*s%-*s %7d %8d %8d %11lu %10lu ",
> +	seq_printf(s, "%*s%-*s %-7d %-8d %-8d %-11lu %-10lu ",
>  		   level * 3 + 1, "",
> -		   30 - level * 3, c->name,
> +		   35 - level * 3, c->name,
>  		   c->enable_count, c->prepare_count, c->protect_count,
>  		   clk_core_get_rate_recalc(c),
>  		   clk_core_get_accuracy_recalc(c));
>  
>  	phase = clk_core_get_phase(c);
>  	if (phase >= 0)
> -		seq_printf(s, "%5d", phase);
> +		seq_printf(s, "%-5d", phase);
>  	else
>  		seq_puts(s, "-----");
>  
> -	seq_printf(s, " %6d", clk_core_get_scaled_duty_cycle(c, 100000));
> +	seq_printf(s, " %-6d", clk_core_get_scaled_duty_cycle(c, 100000));
>  
>  	if (c->ops->is_enabled)
> -		seq_printf(s, " %9c\n", clk_core_is_enabled(c) ? 'Y' : 'N');
> +		seq_printf(s, " %5c ", clk_core_is_enabled(c) ? 'Y' : 'N');
>  	else if (!c->ops->enable)
> -		seq_printf(s, " %9c\n", 'Y');
> +		seq_printf(s, " %5c ", 'Y');
>  	else
> -		seq_printf(s, " %9c\n", '?');
> +		seq_printf(s, " %5c ", '?');
> +
> +	hlist_for_each_entry(clk_user, &c->clks, clks_node) {
> +		seq_printf(s, "%*s%-*s  %-4d\n",
> +			   level * 3 + 2 + 105 * multi_node, "",
> +			   30,
> +			   clk_user->dev_id ? clk_user->dev_id : "deviceless",
> +			   clk_user->enable_count);
> +
> +		multi_node = 1;
> +	}
> +
>  }
>  
>  static void clk_summary_show_subtree(struct seq_file *s, struct clk_core *c,
> @@ -2995,9 +3019,9 @@ static int clk_summary_show(struct seq_file *s, void *data)
>  	struct clk_core *c;
>  	struct hlist_head **lists = (struct hlist_head **)s->private;
>  
> -	seq_puts(s, "                                 enable  prepare  protect                                duty  hardware\n");
> -	seq_puts(s, "   clock                          count    count    count        rate   accuracy phase  cycle    enable\n");
> -	seq_puts(s, "-------------------------------------------------------------------------------------------------------\n");
> +	seq_puts(s, "                                 enable  prepare  protect                                duty  hardware                            per-user\n");
> +	seq_puts(s, "   clock                          count    count    count        rate   accuracy phase  cycle    enable   consumer                    count\n");
> +	seq_puts(s, "-------------------------------------------------------------------------------------------------------------------------------------------\n");
>  
>  	clk_prepare_lock();
>  
> -- 
> 2.7.4
>

Hi Stephen,
Please review the above patch. Here we have made the changes as per your
review points. 
Note: The example format in commit meassage is getting changed during
copy paste but we are getting proper formatted and parsable output on
actual target.


Regards,
Vishal
Re: [PATCH v3] Common clock: To list active consumers of clocks
Posted by <Vishal Badole> 3 years, 8 months ago
On Tue, Aug 02, 2022 at 11:39:47PM +0530, Vishal Badole wrote:
> This feature lists the clock consumer's name and per-user enable count
> in clock summary. Using this feature user can easily check which device
> has acquired a perticular clock and it is enabled by respective device
> or not.
> for example:
> $ cat /sys/kernel/debug/clk/clk_summary
>                       enable  prepare  protect                           duty  hardware                            per-user
>    clock               count    count    count    rate   accuracy phase cycle    enable   consumer                    count
> ----------------------------------------------------------------------------------------------------------------------------
>  clk_mcasp0_fixed         0        0        0    24576000      0     0  50000     Y      deviceless                      0
>                                                                                          deviceless                      0
>     clk_mcasp0            0        0        0    24576000      0     0  50000     N          simple-audio-card,cpu           0
>                                                                                              deviceless                      0
> 
> Co-developed-by: Chinmoy Ghosh <chinmoyghosh2001@gmail.com>
> Signed-off-by: Chinmoy Ghosh <chinmoyghosh2001@gmail.com>
> Co-developed-by: Mintu Patel <mintupatel89@gmail.com>
> Signed-off-by: Mintu Patel <mintupatel89@gmail.com>
> Co-developed-by: Vimal Kumar <vimal.kumar32@gmail.com>
> Signed-off-by: Vimal Kumar <vimal.kumar32@gmail.com>
> Signed-off-by: Vishal Badole <badolevishal1116@gmail.com>
> ---
>  drivers/clk/clk.c | 46 +++++++++++++++++++++++++++++++++++-----------
>  1 file changed, 35 insertions(+), 11 deletions(-)
> 
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> index f00d4c1..c96079f 100644
> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> @@ -102,6 +102,7 @@ struct clk {
>  	unsigned long min_rate;
>  	unsigned long max_rate;
>  	unsigned int exclusive_count;
> +	unsigned int enable_count;
>  	struct hlist_node clks_node;
>  };
>  
> @@ -1008,6 +1009,10 @@ void clk_disable(struct clk *clk)
>  		return;
>  
>  	clk_core_disable_lock(clk->core);
> +
> +	if (clk->enable_count > 0)
> +		clk->enable_count--;
> +
>  }
>  EXPORT_SYMBOL_GPL(clk_disable);
>  
> @@ -1169,10 +1174,16 @@ EXPORT_SYMBOL_GPL(clk_restore_context);
>   */
>  int clk_enable(struct clk *clk)
>  {
> +	int ret;
> +
>  	if (!clk)
>  		return 0;
>  
> -	return clk_core_enable_lock(clk->core);
> +	ret = clk_core_enable_lock(clk->core);
> +	if (!ret)
> +		clk->enable_count++;
> +
> +	return ret;
>  }
>  EXPORT_SYMBOL_GPL(clk_enable);
>  
> @@ -2953,28 +2964,41 @@ static void clk_summary_show_one(struct seq_file *s, struct clk_core *c,
>  				 int level)
>  {
>  	int phase;
> +	struct clk *clk_user;
> +	int multi_node = 0;
>  
> -	seq_printf(s, "%*s%-*s %7d %8d %8d %11lu %10lu ",
> +	seq_printf(s, "%*s%-*s %-7d %-8d %-8d %-11lu %-10lu ",
>  		   level * 3 + 1, "",
> -		   30 - level * 3, c->name,
> +		   35 - level * 3, c->name,
>  		   c->enable_count, c->prepare_count, c->protect_count,
>  		   clk_core_get_rate_recalc(c),
>  		   clk_core_get_accuracy_recalc(c));
>  
>  	phase = clk_core_get_phase(c);
>  	if (phase >= 0)
> -		seq_printf(s, "%5d", phase);
> +		seq_printf(s, "%-5d", phase);
>  	else
>  		seq_puts(s, "-----");
>  
> -	seq_printf(s, " %6d", clk_core_get_scaled_duty_cycle(c, 100000));
> +	seq_printf(s, " %-6d", clk_core_get_scaled_duty_cycle(c, 100000));
>  
>  	if (c->ops->is_enabled)
> -		seq_printf(s, " %9c\n", clk_core_is_enabled(c) ? 'Y' : 'N');
> +		seq_printf(s, " %5c ", clk_core_is_enabled(c) ? 'Y' : 'N');
>  	else if (!c->ops->enable)
> -		seq_printf(s, " %9c\n", 'Y');
> +		seq_printf(s, " %5c ", 'Y');
>  	else
> -		seq_printf(s, " %9c\n", '?');
> +		seq_printf(s, " %5c ", '?');
> +
> +	hlist_for_each_entry(clk_user, &c->clks, clks_node) {
> +		seq_printf(s, "%*s%-*s  %-4d\n",
> +			   level * 3 + 2 + 105 * multi_node, "",
> +			   30,
> +			   clk_user->dev_id ? clk_user->dev_id : "deviceless",
> +			   clk_user->enable_count);
> +
> +		multi_node = 1;
> +	}
> +
>  }
>  
>  static void clk_summary_show_subtree(struct seq_file *s, struct clk_core *c,
> @@ -2995,9 +3019,9 @@ static int clk_summary_show(struct seq_file *s, void *data)
>  	struct clk_core *c;
>  	struct hlist_head **lists = (struct hlist_head **)s->private;
>  
> -	seq_puts(s, "                                 enable  prepare  protect                                duty  hardware\n");
> -	seq_puts(s, "   clock                          count    count    count        rate   accuracy phase  cycle    enable\n");
> -	seq_puts(s, "-------------------------------------------------------------------------------------------------------\n");
> +	seq_puts(s, "                                 enable  prepare  protect                                duty  hardware                            per-user\n");
> +	seq_puts(s, "   clock                          count    count    count        rate   accuracy phase  cycle    enable   consumer                    count\n");
> +	seq_puts(s, "-------------------------------------------------------------------------------------------------------------------------------------------\n");
>  
>  	clk_prepare_lock();
>  
> -- 
> 2.7.4
>
Hi Stephen,
Have you got a chance to review the above patch? 
We have made the changes as per the reviews, please have a look on the
patch.

Regards,
Vishal