Hi Jeremy,

Your suggestion is better in the architecture view and it is clean and neat,
on the other side, mine is only concerning about the minimal changing
of previous code.
I will try your way and give your feedback.

Yong

On Mon, Nov 22, 2010 at 10:46 AM, Jeremy Kerr <jeremy.k...@canonical.com>wrote:

> Hi Yong,
>
> > diff --git a/arch/arm/common/clkdev.c b/arch/arm/common/clkdev.c
> > index 9e4c4d9..936684f 100644
> > --- a/arch/arm/common/clkdev.c
> > +++ b/arch/arm/common/clkdev.c
> > @@ -19,6 +19,9 @@
> >  #include <linux/mutex.h>
> >  #include <linux/clk.h>
> >  #include <linux/slab.h>
> > +#ifdef CONFIG_CLK_DEBUG
> > +#include <linux/debugfs.h>
> > +#endif
>
> With changes suggested below, we won't need this
>
> >
> >  #include <asm/clkdev.h>
> >
> > @@ -104,6 +107,10 @@ EXPORT_SYMBOL(clk_put);
> >
> >  void clkdev_add(struct clk_lookup *cl)
> >  {
> > +#ifdef CONFIG_CLK_DEBUG
> > + if (debugfs_initialized())
> > + clk_debug_register(cl->clk);
> > +#endif
>
> Don't make this conditional on CONFIG_CLK_DEBUG. the clk_debug_register
> should
> do this checking, and for the !CONFIG_CLK_DEBUG case, clk_debug_register
> should be an empty inline.
>
> >   mutex_lock(&clocks_mutex);
> >   list_add_tail(&cl->node, &clocks);
> >   mutex_unlock(&clocks_mutex);
> > @@ -114,6 +121,10 @@ void __init clkdev_add_table(struct clk_lookup *cl,
> > size_t num)
> >  {
> >   mutex_lock(&clocks_mutex);
> >   while (num--) {
> > +#ifdef CONFIG_CLK_DEBUG
> > + if (debugfs_initialized())
> > + clk_debug_register(cl->clk);
> > +#endif
>
> Same here.
>
> >   list_add_tail(&cl->node, &clocks);
> >   cl++;
> >   }
> > @@ -186,3 +197,20 @@ void clkdev_drop(struct clk_lookup *cl)
> >   kfree(cl);
> >  }
> >  EXPORT_SYMBOL(clkdev_drop);
> > +
> > +#ifdef CONFIG_CLK_DEBUG
> > +static int __init clk_debugfs_init(void)
> > +{
> > + struct clk_lookup *cl;
> > + int err;
> > +
> > + list_for_each_entry(cl, &clocks, node) {
> > + err = clk_debug_register(cl->clk);
> > + if (err)
> > + return err;
> > + }
> > + return 0;
> > +}
> > +late_initcall(clk_debugfs_init);
>
> Would be much better to contain all the debugging functionality in
> kernel/clk.c. I think we'd be better of exposing a single function:
>
> clk_debug_register(struct clk *);
>
> - and implementing the details in kernel/clk.c. The caller should not have
> to
> care about the internal implementation details of the debug code (ie, that
> debugfs is not initialised).
>
> So, this function must be able to register clocks at any time.
>
> > +
> > +#endif
> > diff --git a/include/linux/clk.h b/include/linux/clk.h
> > index 56416b7..5a0139c 100644
> > --- a/include/linux/clk.h
> > +++ b/include/linux/clk.h
> > @@ -44,16 +44,28 @@ struct device;
> >   * registered with the arch-specific clock management code; the clock
> > driver
> >   * code does not need to handle these.
> >   */
> > +#define CLK_NAME_LEN 32
>
> I'd put this before the above comment, so the kerneldoc is properly
> located.
>
> >  struct clk {
> >   const struct clk_ops *ops;
> >   unsigned int enable_count;
> >   struct mutex mutex;
> > +#ifdef CONFIG_CLK_DEBUG
> > + char name[CLK_NAME_LEN];
> > + struct dentry           *dentry;
> > +#endif
> >  };
> >
> > +#ifdef CONFIG_CLK_DEBUG
> > +#define __INIT_CLK_DEBUG(n) .name = #n,
> > +#else
> > +#define __INIT_CLK_DEBUG(n)
> > +#endif
>
> looks good :)
>
> > +
> >  #define INIT_CLK(name, o) { \
> >   .ops = &o, \
> >   .enable_count = 0, \
> >   .mutex = __MUTEX_INITIALIZER(name.mutex), \
> > + __INIT_CLK_DEBUG(name) \
> >  }
> >
> >  struct clk_ops {
> > @@ -245,4 +257,5 @@ struct clk *clk_get_sys(const char *dev_id, const
> char
> > *con_id);
> >  int clk_add_alias(const char *alias, const char *alias_dev_name, char
> *id,
> >   struct device *dev);
> >
> > +int clk_debug_register(struct clk *clk);
>
> We need the inline here too:
>
> #ifdef CONFIG_CLK_DEBUG
> extern int clk_debug_register(struct clk *clk);
> #else
> static inline int clk_debug_register(struct clk *clk) { return 0; }
> #endif
>
> Also, we should probably make this return void; it's unlikely that callers
> are
> going to check (or care about) the return value here.
>
>
> >  #endif
> > diff --git a/kernel/clk.c b/kernel/clk.c
> > index 32f25ef..df4da68 100644
> > --- a/kernel/clk.c
> > +++ b/kernel/clk.c
> > @@ -12,6 +12,10 @@
> >  #include <linux/mutex.h>
> >  #include <linux/module.h>
> >
> > +#ifdef CONFIG_CLK_DEBUG
> > +#include <linux/debugfs.h>
> > +#endif
>
> Just include unconditionally.
>
> > +
> >  int clk_enable(struct clk *clk)
> >  {
> >   int ret = 0;
> > @@ -113,3 +117,89 @@ struct clk_ops clk_fixed_ops = {
> >   .get_rate = clk_fixed_get_rate,
> >  };
> >  EXPORT_SYMBOL_GPL(clk_fixed_ops);
> > +
> > +#ifdef CONFIG_CLK_DEBUG
> > +/*
> > + * debugfs support to trace clock tree hierarchy and attributes
> > + */
> > +static int clk_debug_rate_get(void *data, u64 *val)
> > +{
> > + struct clk *clk = data;
> > +
> > + *val = (u64)clk_get_rate(clk);
> > + return 0;
> > +}
> > +DEFINE_SIMPLE_ATTRIBUTE(clk_debug_rate_fops, clk_debug_rate_get, NULL,
> > + "%llu\n");
> > +
> > +
> > +static struct dentry *clk_root;
> > +static int clk_debug_register_one(struct clk *clk)
> > +{
> > + int err;
> > + struct dentry *d, *child, *child_tmp;
> > + struct clk *pa = clk_get_parent(clk);
> > +
> > + if (pa && !IS_ERR(pa))
> > + d = debugfs_create_dir(clk->name, pa->dentry);
> > + else {
> > + if (!clk_root)
> > + clk_root = debugfs_create_dir("clocks", NULL);
> > + if (!clk_root)
> > + return -ENOMEM;
> > + d = debugfs_create_dir(clk->name, clk_root);
> > + }
> > +
> > + if (!d)
> > + return -ENOMEM;
> > +
> > + clk->dentry = d;
> > +
> > + d = debugfs_create_u32("enable_count", S_IRUGO, clk->dentry,
> > + (u32 *)&clk->enable_count);
> > + if (!d) {
> > + err = -ENOMEM;
> > + goto err_out;
> > + }
> > +
> > + d = debugfs_create_file("rate", S_IRUGO, clk->dentry, (void *)clk,
> > + &clk_debug_rate_fops);
> > + if (!d) {
> > + err = -ENOMEM;
> > + goto err_out;
> > + }
> > +
> > + return 0;
> > +
> > +err_out:
> > + d = clk->dentry;
> > + list_for_each_entry_safe(child, child_tmp, &d->d_subdirs, d_u.d_child)
> > + debugfs_remove(child);
> > + debugfs_remove(clk->dentry);
> > + return err;
> > +}
> > +
> > +int clk_debug_register(struct clk *clk)
> > +{
> > + int err;
> > + struct clk *pa;
> > +
> > + pa = clk_get_parent(clk);
> > +
> > + if (pa && !IS_ERR(pa) && !pa->dentry) {
> > + err = clk_debug_register(pa);
> > + if (err)
> > + return err;
> > + }
> > +
> > + if (!clk->dentry) {
> > + err = clk_debug_register_one(clk);
> > + if (err)
> > + return err;
> > + }
> > + return 0;
> > +}
>
> How about something like:
>
> struct preinit_clk {
>        struct list_head list;
>        struct clk *clk;
> };
>
> static LIST_HEAD(preinit_clks);
> static DEFINE_MUTEX(preinit_lock);
> static int init_done;
>
> void clk_debug_register(struct clk *clk)
> {
>        mutex_lock(&preinit_lock);
>        if (init_done) {
>                /* normal register path ... */
>        } else {
>                struct preinit_clk *p;
>
>                p = kmalloc(sizeof(*p), GFP_KERNEL);
>                if (!p)
>                        goto out_unlock;
>                p->clk = clk;
>                list_add(&p->list, &preinit_clks);
>        }
>
> out_unlock:
>        mutex_unlock(&preinit_lock);
> }
>
> and then in clk_debug_init, we add all the clocks from preinit_list, then
> set
> init_done = 1. Calls to clk_debug_register after clk_debug_init() will have
> the dentry set up directly.
>
> This way, the caller does not have to care about the state of the clk_debug
> code.
>
> How does this sound?
>
> > +#else /* defined CONFIG_CLK_DEBUG */
> > +inline int clk_debug_register(struct clk *clk) {}
>
> We'll define this in the header, so you can remove this definition.
>
> > +#endif
> > +EXPORT_SYMBOL_GPL(clk_debug_register);
>
> Cheers,
>
>
> Jeremy
>
_______________________________________________
linaro-dev mailing list
linaro-dev@lists.linaro.org
http://lists.linaro.org/mailman/listinfo/linaro-dev

Reply via email to