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