linux-clk.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2] clk: Add clk_min/max_rate entries in debugfs
@ 2019-06-28  8:19 Leonard Crestez
  2019-06-28 11:58 ` Geert Uytterhoeven
  0 siblings, 1 reply; 4+ messages in thread
From: Leonard Crestez @ 2019-06-28  8:19 UTC (permalink / raw)
  To: Geert Uytterhoeven, Stephen Boyd
  Cc: Michael Turquette, linux-clk, linux-arm-kernel

Add two files to expose min/max clk rates as determined by
clk_core_get_boundaries, taking all consumer requests into account.

This information does not appear to be otherwise exposed to userspace.

Signed-off-by: Leonard Crestez <leonard.crestez@nxp.com>

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

Changes since v1:
* Call clk_prepare_lock/clk_prepare_unlock (Geert)
* Also include in clk_dump, but only with non-default values
Link to v1: https://patchwork.kernel.org/patch/11019873/

Didn't add to clk_summary because min/max rates are rarely used and
clk_summary already has too many columns.

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index efa593ecbfa9..8cec1954580b 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -591,10 +591,12 @@ static void clk_core_get_boundaries(struct clk_core *core,
 				    unsigned long *min_rate,
 				    unsigned long *max_rate)
 {
 	struct clk *clk_user;
 
+	lockdep_assert_held(&prepare_lock);
+
 	*min_rate = core->min_rate;
 	*max_rate = core->max_rate;
 
 	hlist_for_each_entry(clk_user, &core->clks, clks_node)
 		*min_rate = max(*min_rate, clk_user->min_rate);
@@ -2894,19 +2896,26 @@ static int clk_summary_show(struct seq_file *s, void *data)
 }
 DEFINE_SHOW_ATTRIBUTE(clk_summary);
 
 static void clk_dump_one(struct seq_file *s, struct clk_core *c, int level)
 {
+	unsigned long min_rate, max_rate;
+
 	if (!c)
 		return;
 
 	/* This should be JSON format, i.e. elements separated with a comma */
 	seq_printf(s, "\"%s\": { ", c->name);
 	seq_printf(s, "\"enable_count\": %d,", c->enable_count);
 	seq_printf(s, "\"prepare_count\": %d,", c->prepare_count);
 	seq_printf(s, "\"protect_count\": %d,", c->protect_count);
 	seq_printf(s, "\"rate\": %lu,", clk_core_get_rate(c));
+	clk_core_get_boundaries(c, &min_rate, &max_rate);
+	if (min_rate != 0)
+		seq_printf(s, "\"min_rate\": %lu,", min_rate);
+	if (max_rate != ULONG_MAX)
+		seq_printf(s, "\"max_rate\": %lu,", max_rate);
 	seq_printf(s, "\"accuracy\": %lu,", clk_core_get_accuracy(c));
 	seq_printf(s, "\"phase\": %d,", clk_core_get_phase(c));
 	seq_printf(s, "\"duty_cycle\": %u",
 		   clk_core_get_scaled_duty_cycle(c, 100000));
 }
@@ -3062,10 +3071,38 @@ static int clk_duty_cycle_show(struct seq_file *s, void *data)
 
 	return 0;
 }
 DEFINE_SHOW_ATTRIBUTE(clk_duty_cycle);
 
+static int clk_min_rate_show(struct seq_file *s, void *data)
+{
+	struct clk_core *core = s->private;
+	unsigned long min_rate, max_rate;
+
+	clk_prepare_lock();
+	clk_core_get_boundaries(core, &min_rate, &max_rate);
+	seq_printf(s, "%lu\n", min_rate);
+	clk_prepare_unlock();
+
+	return 0;
+}
+DEFINE_SHOW_ATTRIBUTE(clk_min_rate);
+
+static int clk_max_rate_show(struct seq_file *s, void *data)
+{
+	struct clk_core *core = s->private;
+	unsigned long min_rate, max_rate;
+
+	clk_prepare_lock();
+	clk_core_get_boundaries(core, &min_rate, &max_rate);
+	seq_printf(s, "%lu\n", max_rate);
+	clk_prepare_unlock();
+
+	return 0;
+}
+DEFINE_SHOW_ATTRIBUTE(clk_max_rate);
+
 static void clk_debug_create_one(struct clk_core *core, struct dentry *pdentry)
 {
 	struct dentry *root;
 
 	if (!core || !pdentry)
@@ -3073,10 +3110,12 @@ static void clk_debug_create_one(struct clk_core *core, struct dentry *pdentry)
 
 	root = debugfs_create_dir(core->name, pdentry);
 	core->dentry = root;
 
 	debugfs_create_ulong("clk_rate", 0444, root, &core->rate);
+	debugfs_create_file("clk_min_rate", 0444, root, core, &clk_min_rate_fops);
+	debugfs_create_file("clk_max_rate", 0444, root, core, &clk_max_rate_fops);
 	debugfs_create_ulong("clk_accuracy", 0444, root, &core->accuracy);
 	debugfs_create_u32("clk_phase", 0444, root, &core->phase);
 	debugfs_create_file("clk_flags", 0444, root, core, &clk_flags_fops);
 	debugfs_create_u32("clk_prepare_count", 0444, root, &core->prepare_count);
 	debugfs_create_u32("clk_enable_count", 0444, root, &core->enable_count);
-- 
2.17.1


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

* Re: [PATCH v2] clk: Add clk_min/max_rate entries in debugfs
  2019-06-28  8:19 [PATCH v2] clk: Add clk_min/max_rate entries in debugfs Leonard Crestez
@ 2019-06-28 11:58 ` Geert Uytterhoeven
  2019-06-28 19:35   ` Stephen Boyd
  0 siblings, 1 reply; 4+ messages in thread
From: Geert Uytterhoeven @ 2019-06-28 11:58 UTC (permalink / raw)
  To: Leonard Crestez
  Cc: Geert Uytterhoeven, Stephen Boyd, Michael Turquette, linux-clk,
	Linux ARM

Hi Leonard,

On Fri, Jun 28, 2019 at 10:19 AM Leonard Crestez
<leonard.crestez@nxp.com> wrote:
> Add two files to expose min/max clk rates as determined by
> clk_core_get_boundaries, taking all consumer requests into account.
>
> This information does not appear to be otherwise exposed to userspace.
>
> Signed-off-by: Leonard Crestez <leonard.crestez@nxp.com>

> Changes since v1:
> * Call clk_prepare_lock/clk_prepare_unlock (Geert)
> * Also include in clk_dump, but only with non-default values
> Link to v1: https://patchwork.kernel.org/patch/11019873/

Thanks for the update!

> Didn't add to clk_summary because min/max rates are rarely used and
> clk_summary already has too many columns.

Agreed.

> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> @@ -591,10 +591,12 @@ static void clk_core_get_boundaries(struct clk_core *core,
>                                     unsigned long *min_rate,
>                                     unsigned long *max_rate)
>  {
>         struct clk *clk_user;
>
> +       lockdep_assert_held(&prepare_lock);
> +

I guess the clock maintainers want to see the addition of this check
spun off into a separate patch....

> @@ -3062,10 +3071,38 @@ static int clk_duty_cycle_show(struct seq_file *s, void *data)
>
>         return 0;
>  }
>  DEFINE_SHOW_ATTRIBUTE(clk_duty_cycle);
>
> +static int clk_min_rate_show(struct seq_file *s, void *data)
> +{
> +       struct clk_core *core = s->private;
> +       unsigned long min_rate, max_rate;
> +
> +       clk_prepare_lock();
> +       clk_core_get_boundaries(core, &min_rate, &max_rate);
> +       seq_printf(s, "%lu\n", min_rate);
> +       clk_prepare_unlock();

You can move the release of the lock one line up.

> +
> +       return 0;
> +}
> +DEFINE_SHOW_ATTRIBUTE(clk_min_rate);
> +
> +static int clk_max_rate_show(struct seq_file *s, void *data)
> +{
> +       struct clk_core *core = s->private;
> +       unsigned long min_rate, max_rate;
> +
> +       clk_prepare_lock();
> +       clk_core_get_boundaries(core, &min_rate, &max_rate);
> +       seq_printf(s, "%lu\n", max_rate);
> +       clk_prepare_unlock();

You can move the release of the lock one line up.

> +
> +       return 0;
> +}

With the above fixed:
Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>

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] 4+ messages in thread

* Re: [PATCH v2] clk: Add clk_min/max_rate entries in debugfs
  2019-06-28 11:58 ` Geert Uytterhoeven
@ 2019-06-28 19:35   ` Stephen Boyd
  2019-07-01 13:13     ` Leonard Crestez
  0 siblings, 1 reply; 4+ messages in thread
From: Stephen Boyd @ 2019-06-28 19:35 UTC (permalink / raw)
  To: Geert Uytterhoeven, Leonard Crestez
  Cc: Geert Uytterhoeven, Michael Turquette, linux-clk, Linux ARM

Quoting Geert Uytterhoeven (2019-06-28 04:58:27)
> On Fri, Jun 28, 2019 at 10:19 AM Leonard Crestez
> 
> > --- a/drivers/clk/clk.c
> > +++ b/drivers/clk/clk.c
> > @@ -591,10 +591,12 @@ static void clk_core_get_boundaries(struct clk_core *core,
> >                                     unsigned long *min_rate,
> >                                     unsigned long *max_rate)
> >  {
> >         struct clk *clk_user;
> >
> > +       lockdep_assert_held(&prepare_lock);
> > +
> 
> I guess the clock maintainers want to see the addition of this check
> spun off into a separate patch....

Yes. I'm not sure we should have the assertion in there. I seem to
recall that we thought it might not always be necessary to have the
lock, but maybe that was wrong.


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

* Re: [PATCH v2] clk: Add clk_min/max_rate entries in debugfs
  2019-06-28 19:35   ` Stephen Boyd
@ 2019-07-01 13:13     ` Leonard Crestez
  0 siblings, 0 replies; 4+ messages in thread
From: Leonard Crestez @ 2019-07-01 13:13 UTC (permalink / raw)
  To: Stephen Boyd, Geert Uytterhoeven
  Cc: Geert Uytterhoeven, Michael Turquette, linux-clk, Linux ARM

On 6/28/2019 10:36 PM, Stephen Boyd wrote:
> Quoting Geert Uytterhoeven (2019-06-28 04:58:27)
>> On Fri, Jun 28, 2019 at 10:19 AM Leonard Crestez
>>
>>> --- a/drivers/clk/clk.c
>>> +++ b/drivers/clk/clk.c
>>> @@ -591,10 +591,12 @@ static void clk_core_get_boundaries(struct clk_core *core,
>>>                                      unsigned long *min_rate,
>>>                                      unsigned long *max_rate)
>>>   {
>>>          struct clk *clk_user;
>>>
>>> +       lockdep_assert_held(&prepare_lock);
>>> +
>>
>> I guess the clock maintainers want to see the addition of this check
>> spun off into a separate patch....
> 
> Yes. I'm not sure we should have the assertion in there. I seem to
> recall that we thought it might not always be necessary to have the
> lock, but maybe that was wrong.

The clk_core_get_boundaries function iterates consumers so locking is 
required. Looking at other functions manipulating clks_node (such as 
__clk_put, clk_core_link/unlink_consumer) this is always done under 
prepare_lock.

In theory without locking debugfs could read freed memory if it happens 
at the same time as device removal.

--
Regards,
Leonard

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

end of thread, other threads:[~2019-07-01 13:13 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-06-28  8:19 [PATCH v2] clk: Add clk_min/max_rate entries in debugfs Leonard Crestez
2019-06-28 11:58 ` Geert Uytterhoeven
2019-06-28 19:35   ` Stephen Boyd
2019-07-01 13:13     ` Leonard Crestez

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).