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