clk: flatten clk tree in debugfs
This patch flattens the clk tree in CCF debugfs. Instead of representing the clocks and their hierarchy as a directory structure under /sys/kernel/debug/clk, each clock gets a single directory directly under /sys/kernel/debug/clk. The orphans directory is replaced by a file called clk_orphan_summary. Signed-off-by: Peter De Schrijver <pdeschrijver@nvidia.com> Signed-off-by: Mike Turquette <mturquette@linaro.org>
This commit is contained in:
parent
d8e53c3deb
commit
27b8d5f723
@ -36,6 +36,17 @@ static HLIST_HEAD(clk_root_list);
|
|||||||
static HLIST_HEAD(clk_orphan_list);
|
static HLIST_HEAD(clk_orphan_list);
|
||||||
static LIST_HEAD(clk_notifier_list);
|
static LIST_HEAD(clk_notifier_list);
|
||||||
|
|
||||||
|
static struct hlist_head *all_lists[] = {
|
||||||
|
&clk_root_list,
|
||||||
|
&clk_orphan_list,
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct hlist_head *orphan_list[] = {
|
||||||
|
&clk_orphan_list,
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
|
||||||
/*** locking ***/
|
/*** locking ***/
|
||||||
static void clk_prepare_lock(void)
|
static void clk_prepare_lock(void)
|
||||||
{
|
{
|
||||||
@ -98,7 +109,6 @@ static void clk_enable_unlock(unsigned long flags)
|
|||||||
#include <linux/debugfs.h>
|
#include <linux/debugfs.h>
|
||||||
|
|
||||||
static struct dentry *rootdir;
|
static struct dentry *rootdir;
|
||||||
static struct dentry *orphandir;
|
|
||||||
static int inited = 0;
|
static int inited = 0;
|
||||||
|
|
||||||
static void clk_summary_show_one(struct seq_file *s, struct clk *c, int level)
|
static void clk_summary_show_one(struct seq_file *s, struct clk *c, int level)
|
||||||
@ -130,17 +140,16 @@ static void clk_summary_show_subtree(struct seq_file *s, struct clk *c,
|
|||||||
static int clk_summary_show(struct seq_file *s, void *data)
|
static int clk_summary_show(struct seq_file *s, void *data)
|
||||||
{
|
{
|
||||||
struct clk *c;
|
struct clk *c;
|
||||||
|
struct hlist_head **lists = (struct hlist_head **)s->private;
|
||||||
|
|
||||||
seq_puts(s, " clock enable_cnt prepare_cnt rate accuracy\n");
|
seq_puts(s, " clock enable_cnt prepare_cnt rate accuracy\n");
|
||||||
seq_puts(s, "--------------------------------------------------------------------------------\n");
|
seq_puts(s, "--------------------------------------------------------------------------------\n");
|
||||||
|
|
||||||
clk_prepare_lock();
|
clk_prepare_lock();
|
||||||
|
|
||||||
hlist_for_each_entry(c, &clk_root_list, child_node)
|
for (; *lists; lists++)
|
||||||
clk_summary_show_subtree(s, c, 0);
|
hlist_for_each_entry(c, *lists, child_node)
|
||||||
|
clk_summary_show_subtree(s, c, 0);
|
||||||
hlist_for_each_entry(c, &clk_orphan_list, child_node)
|
|
||||||
clk_summary_show_subtree(s, c, 0);
|
|
||||||
|
|
||||||
clk_prepare_unlock();
|
clk_prepare_unlock();
|
||||||
|
|
||||||
@ -193,21 +202,19 @@ static int clk_dump(struct seq_file *s, void *data)
|
|||||||
{
|
{
|
||||||
struct clk *c;
|
struct clk *c;
|
||||||
bool first_node = true;
|
bool first_node = true;
|
||||||
|
struct hlist_head **lists = (struct hlist_head **)s->private;
|
||||||
|
|
||||||
seq_printf(s, "{");
|
seq_printf(s, "{");
|
||||||
|
|
||||||
clk_prepare_lock();
|
clk_prepare_lock();
|
||||||
|
|
||||||
hlist_for_each_entry(c, &clk_root_list, child_node) {
|
for (; *lists; lists++) {
|
||||||
if (!first_node)
|
hlist_for_each_entry(c, *lists, child_node) {
|
||||||
seq_printf(s, ",");
|
if (!first_node)
|
||||||
first_node = false;
|
seq_puts(s, ",");
|
||||||
clk_dump_subtree(s, c, 0);
|
first_node = false;
|
||||||
}
|
clk_dump_subtree(s, c, 0);
|
||||||
|
}
|
||||||
hlist_for_each_entry(c, &clk_orphan_list, child_node) {
|
|
||||||
seq_printf(s, ",");
|
|
||||||
clk_dump_subtree(s, c, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
clk_prepare_unlock();
|
clk_prepare_unlock();
|
||||||
@ -305,7 +312,7 @@ static int clk_debug_create_subtree(struct clk *clk, struct dentry *pdentry)
|
|||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
hlist_for_each_entry(child, &clk->children, child_node)
|
hlist_for_each_entry(child, &clk->children, child_node)
|
||||||
clk_debug_create_subtree(child, clk->dentry);
|
clk_debug_create_subtree(child, pdentry);
|
||||||
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
out:
|
out:
|
||||||
@ -325,31 +332,12 @@ out:
|
|||||||
*/
|
*/
|
||||||
static int clk_debug_register(struct clk *clk)
|
static int clk_debug_register(struct clk *clk)
|
||||||
{
|
{
|
||||||
struct clk *parent;
|
|
||||||
struct dentry *pdentry;
|
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
if (!inited)
|
if (!inited)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
parent = clk->parent;
|
ret = clk_debug_create_subtree(clk, rootdir);
|
||||||
|
|
||||||
/*
|
|
||||||
* Check to see if a clk is a root clk. Also check that it is
|
|
||||||
* safe to add this clk to debugfs
|
|
||||||
*/
|
|
||||||
if (!parent)
|
|
||||||
if (clk->flags & CLK_IS_ROOT)
|
|
||||||
pdentry = rootdir;
|
|
||||||
else
|
|
||||||
pdentry = orphandir;
|
|
||||||
else
|
|
||||||
if (parent->dentry)
|
|
||||||
pdentry = parent->dentry;
|
|
||||||
else
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
ret = clk_debug_create_subtree(clk, pdentry);
|
|
||||||
|
|
||||||
out:
|
out:
|
||||||
return ret;
|
return ret;
|
||||||
@ -370,39 +358,6 @@ static void clk_debug_unregister(struct clk *clk)
|
|||||||
debugfs_remove_recursive(clk->dentry);
|
debugfs_remove_recursive(clk->dentry);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* clk_debug_reparent - reparent clk node in the debugfs clk tree
|
|
||||||
* @clk: the clk being reparented
|
|
||||||
* @new_parent: the new clk parent, may be NULL
|
|
||||||
*
|
|
||||||
* Rename clk entry in the debugfs clk tree if debugfs has been
|
|
||||||
* initialized. Otherwise it bails out early since the debugfs clk tree
|
|
||||||
* will be created lazily by clk_debug_init as part of a late_initcall.
|
|
||||||
*
|
|
||||||
* Caller must hold prepare_lock.
|
|
||||||
*/
|
|
||||||
static void clk_debug_reparent(struct clk *clk, struct clk *new_parent)
|
|
||||||
{
|
|
||||||
struct dentry *d;
|
|
||||||
struct dentry *new_parent_d;
|
|
||||||
|
|
||||||
if (!inited)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (new_parent)
|
|
||||||
new_parent_d = new_parent->dentry;
|
|
||||||
else
|
|
||||||
new_parent_d = orphandir;
|
|
||||||
|
|
||||||
d = debugfs_rename(clk->dentry->d_parent, clk->dentry,
|
|
||||||
new_parent_d, clk->name);
|
|
||||||
if (d)
|
|
||||||
clk->dentry = d;
|
|
||||||
else
|
|
||||||
pr_debug("%s: failed to rename debugfs entry for %s\n",
|
|
||||||
__func__, clk->name);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* clk_debug_init - lazily create the debugfs clk tree visualization
|
* clk_debug_init - lazily create the debugfs clk tree visualization
|
||||||
*
|
*
|
||||||
@ -425,19 +380,24 @@ static int __init clk_debug_init(void)
|
|||||||
if (!rootdir)
|
if (!rootdir)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
d = debugfs_create_file("clk_summary", S_IRUGO, rootdir, NULL,
|
d = debugfs_create_file("clk_summary", S_IRUGO, rootdir, &all_lists,
|
||||||
&clk_summary_fops);
|
&clk_summary_fops);
|
||||||
if (!d)
|
if (!d)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
d = debugfs_create_file("clk_dump", S_IRUGO, rootdir, NULL,
|
d = debugfs_create_file("clk_dump", S_IRUGO, rootdir, &all_lists,
|
||||||
&clk_dump_fops);
|
&clk_dump_fops);
|
||||||
if (!d)
|
if (!d)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
orphandir = debugfs_create_dir("orphans", rootdir);
|
d = debugfs_create_file("clk_orphan_summary", S_IRUGO, rootdir,
|
||||||
|
&orphan_list, &clk_summary_fops);
|
||||||
|
if (!d)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
if (!orphandir)
|
d = debugfs_create_file("clk_orphan_dump", S_IRUGO, rootdir,
|
||||||
|
&orphan_list, &clk_dump_fops);
|
||||||
|
if (!d)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
clk_prepare_lock();
|
clk_prepare_lock();
|
||||||
@ -446,7 +406,7 @@ static int __init clk_debug_init(void)
|
|||||||
clk_debug_create_subtree(clk, rootdir);
|
clk_debug_create_subtree(clk, rootdir);
|
||||||
|
|
||||||
hlist_for_each_entry(clk, &clk_orphan_list, child_node)
|
hlist_for_each_entry(clk, &clk_orphan_list, child_node)
|
||||||
clk_debug_create_subtree(clk, orphandir);
|
clk_debug_create_subtree(clk, rootdir);
|
||||||
|
|
||||||
inited = 1;
|
inited = 1;
|
||||||
|
|
||||||
@ -1284,9 +1244,6 @@ static void __clk_set_parent_after(struct clk *clk, struct clk *parent,
|
|||||||
clk_disable(old_parent);
|
clk_disable(old_parent);
|
||||||
__clk_unprepare(old_parent);
|
__clk_unprepare(old_parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* update debugfs with new clk tree topology */
|
|
||||||
clk_debug_reparent(clk, parent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __clk_set_parent(struct clk *clk, struct clk *parent, u8 p_index)
|
static int __clk_set_parent(struct clk *clk, struct clk *parent, u8 p_index)
|
||||||
@ -1683,7 +1640,6 @@ out:
|
|||||||
void __clk_reparent(struct clk *clk, struct clk *new_parent)
|
void __clk_reparent(struct clk *clk, struct clk *new_parent)
|
||||||
{
|
{
|
||||||
clk_reparent(clk, new_parent);
|
clk_reparent(clk, new_parent);
|
||||||
clk_debug_reparent(clk, new_parent);
|
|
||||||
__clk_recalc_accuracies(clk);
|
__clk_recalc_accuracies(clk);
|
||||||
__clk_recalc_rates(clk, POST_RATE_CHANGE);
|
__clk_recalc_rates(clk, POST_RATE_CHANGE);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user