Hi Amit,

That's a good reminding. About version number, I am using it in all my
code reviews in different mail list now. About this patch, I planed to
send out a 'v2', however it had been a while since last review, so I
expect a new start.
But I do need to mention the changes.
Changes from last round:
1. add memory free afte clock initialization
2. Move CLK_NAME_LEN into #ifdef.

Thanks
Yong

On Fri, Dec 3, 2010 at 5:06 PM, Amit Kucheria <amit.kuche...@linaro.org> wrote:
> On Fri, Dec 3, 2010 at 1:30 PM, Yong Shen <yong.s...@linaro.org> wrote
>> Hi Jeremy,
>>
>> This is latest one for review. I add some minor changes in.
>>
>> Cheers
>> Yong
>
> Yong,
>
> It helps reviewers if you version your patches (PATCHv1, PATCHv2,
> etc.) and you list the changes made in each version in the changelog.
>
> See http://kerneltrap.org/mailarchive/linux-kernel/2010/9/27/4624656/thread
> for a random example.
>
> Regards,
> Amit
>
>> From efe7fa8bea67f9bf532c0074a92d938e6d6f4c5d Mon Sep 17 00:00:00 2001
>> From: Yong Shen <yong.s...@linaro.org>
>> Date: Thu, 18 Nov 2010 14:54:49 +0800
>> Subject: [PATCH] export clock debug information to user space
>>
>> create a tree-like directory structure in debugfs so user space
>> tools like powerdebug can generate readable clock information.
>> more functions tend to be add in, like individual clock enable/disable
>> by writing to this debug interface.
>>
>> Signed-off-by: Yong Shen <yong.s...@linaro.org>
>> ---
>>  arch/arm/common/Kconfig  |    6 ++
>>  arch/arm/common/clkdev.c |    3 +
>>  include/linux/clk.h      |   18 +++++++
>>  kernel/clk.c             |  121 
>> ++++++++++++++++++++++++++++++++++++++++++++++
>>  4 files changed, 148 insertions(+), 0 deletions(-)
>>
>> diff --git a/arch/arm/common/Kconfig b/arch/arm/common/Kconfig
>> index 0a34c81..13d7cf9 100644
>> --- a/arch/arm/common/Kconfig
>> +++ b/arch/arm/common/Kconfig
>> @@ -41,3 +41,9 @@ config SHARP_SCOOP
>>  config COMMON_CLKDEV
>>        bool
>>        select HAVE_CLK
>> +
>> +config CLK_DEBUG
>> +       bool "clock debug information export to user space"
>> +       depends on USE_COMMON_STRUCT_CLK && PM_DEBUG && DEBUG_FS
>> +       help
>> +         export clk debug information to user space
>> diff --git a/arch/arm/common/clkdev.c b/arch/arm/common/clkdev.c
>> index 9e4c4d9..1d08fb3 100644
>> --- a/arch/arm/common/clkdev.c
>> +++ b/arch/arm/common/clkdev.c
>> @@ -19,6 +19,7 @@
>>  #include <linux/mutex.h>
>>  #include <linux/clk.h>
>>  #include <linux/slab.h>
>> +#include <linux/debugfs.h>
>>
>>  #include <asm/clkdev.h>
>>
>> @@ -104,6 +105,7 @@ EXPORT_SYMBOL(clk_put);
>>
>>  void clkdev_add(struct clk_lookup *cl)
>>  {
>> +       clk_debug_register(cl->clk);
>>        mutex_lock(&clocks_mutex);
>>        list_add_tail(&cl->node, &clocks);
>>        mutex_unlock(&clocks_mutex);
>> @@ -114,6 +116,7 @@ void __init clkdev_add_table(struct clk_lookup
>> *cl, size_t num)
>>  {
>>        mutex_lock(&clocks_mutex);
>>        while (num--) {
>> +               clk_debug_register(cl->clk);
>>                list_add_tail(&cl->node, &clocks);
>>                cl++;
>>        }
>> diff --git a/include/linux/clk.h b/include/linux/clk.h
>> index 56416b7..4aaddea 100644
>> --- a/include/linux/clk.h
>> +++ b/include/linux/clk.h
>> @@ -48,12 +48,24 @@ struct clk {
>>        const struct clk_ops    *ops;
>>        unsigned int            enable_count;
>>        struct mutex            mutex;
>> +#ifdef CONFIG_CLK_DEBUG
>> +#define CLK_NAME_LEN 32
>> +       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
>> +
>>  #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,10 @@ 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);
>>
>> +#ifdef CONFIG_CLK_DEBUG
>> +void clk_debug_register(struct clk *clk);
>> +#else
>> +static inline void clk_debug_register(struct clk *clk) {}
>> +#endif
>> +
>>  #endif
>> diff --git a/kernel/clk.c b/kernel/clk.c
>> index 32f25ef..7f8bea9 100644
>> --- a/kernel/clk.c
>> +++ b/kernel/clk.c
>> @@ -11,6 +11,8 @@
>>  #include <linux/clk.h>
>>  #include <linux/mutex.h>
>>  #include <linux/module.h>
>> +#include <linux/slab.h>
>> +#include <linux/debugfs.h>
>>
>>  int clk_enable(struct clk *clk)
>>  {
>> @@ -113,3 +115,122 @@ 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;
>> +}
>> +
>> +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)
>> +{
>> +       int err;
>> +       struct clk *pa;
>> +
>> +       if (init_done) {
>> +               pa = clk_get_parent(clk);
>> +
>> +               if (pa && !IS_ERR(pa) && !pa->dentry)
>> +                       clk_debug_register(pa);
>> +
>> +               if (!clk->dentry) {
>> +                       err = clk_debug_register_one(clk);
>> +                       if (err)
>> +                               return;
>> +               }
>> +       } else {
>> +               struct preinit_clk *p;
>> +               mutex_lock(&preinit_lock);
>> +               p = kmalloc(sizeof(*p), GFP_KERNEL);
>> +               if (!p)
>> +                       goto unlock;
>> +               p->clk = clk;
>> +               list_add(&p->list, &preinit_clks);
>> +unlock:
>> +               mutex_unlock(&preinit_lock);
>> +       }
>> +}
>> +EXPORT_SYMBOL_GPL(clk_debug_register);
>> +
>> +static int __init clk_debugfs_init(void)
>> +{
>> +       struct preinit_clk *pclk, *tmp;
>> +
>> +       if (debugfs_initialized())
>> +               init_done = 1;
>> +
>> +       list_for_each_entry(pclk, &preinit_clks, list) {
>> +               clk_debug_register(pclk->clk);
>> +       }
>> +
>> +       list_for_each_entry_safe(pclk, tmp, &preinit_clks, list) {
>> +               list_del(&pclk->list);
>> +               kfree(pclk);
>> +       }
>> +       return 0;
>> +}
>> +late_initcall(clk_debugfs_init);
>> +#endif
>> --
>> 1.7.0.4
>>
>> _______________________________________________
>> linaro-dev mailing list
>> linaro-dev@lists.linaro.org
>> http://lists.linaro.org/mailman/listinfo/linaro-dev
>>
>

_______________________________________________
linaro-dev mailing list
linaro-dev@lists.linaro.org
http://lists.linaro.org/mailman/listinfo/linaro-dev

Reply via email to