diff options
author | Peter De Schrijver <pdeschrijver@nvidia.com> | 2014-05-30 11:03:57 -0400 |
---|---|---|
committer | Mike Turquette <mturquette@linaro.org> | 2014-06-26 15:55:04 -0400 |
commit | 27b8d5f723e64b5f7beac45a4d5785906d0a2f9d (patch) | |
tree | cd0db0bbc908a71ac84016ba6beeb8363097039f /drivers/clk/clk.c | |
parent | d8e53c3deb46ec5b45bd7f5e1cc8ff8d35ec92ba (diff) |
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>
Diffstat (limited to 'drivers/clk/clk.c')
-rw-r--r-- | drivers/clk/clk.c | 114 |
1 files changed, 35 insertions, 79 deletions
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 8b73edef151d..7dfb2f308b35 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c | |||
@@ -36,6 +36,17 @@ static HLIST_HEAD(clk_root_list); | |||
36 | static HLIST_HEAD(clk_orphan_list); | 36 | static HLIST_HEAD(clk_orphan_list); |
37 | static LIST_HEAD(clk_notifier_list); | 37 | static LIST_HEAD(clk_notifier_list); |
38 | 38 | ||
39 | static struct hlist_head *all_lists[] = { | ||
40 | &clk_root_list, | ||
41 | &clk_orphan_list, | ||
42 | NULL, | ||
43 | }; | ||
44 | |||
45 | static struct hlist_head *orphan_list[] = { | ||
46 | &clk_orphan_list, | ||
47 | NULL, | ||
48 | }; | ||
49 | |||
39 | /*** locking ***/ | 50 | /*** locking ***/ |
40 | static void clk_prepare_lock(void) | 51 | static void clk_prepare_lock(void) |
41 | { | 52 | { |
@@ -98,7 +109,6 @@ static void clk_enable_unlock(unsigned long flags) | |||
98 | #include <linux/debugfs.h> | 109 | #include <linux/debugfs.h> |
99 | 110 | ||
100 | static struct dentry *rootdir; | 111 | static struct dentry *rootdir; |
101 | static struct dentry *orphandir; | ||
102 | static int inited = 0; | 112 | static int inited = 0; |
103 | 113 | ||
104 | static void clk_summary_show_one(struct seq_file *s, struct clk *c, int level) | 114 | 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, | |||
130 | static int clk_summary_show(struct seq_file *s, void *data) | 140 | static int clk_summary_show(struct seq_file *s, void *data) |
131 | { | 141 | { |
132 | struct clk *c; | 142 | struct clk *c; |
143 | struct hlist_head **lists = (struct hlist_head **)s->private; | ||
133 | 144 | ||
134 | seq_puts(s, " clock enable_cnt prepare_cnt rate accuracy\n"); | 145 | seq_puts(s, " clock enable_cnt prepare_cnt rate accuracy\n"); |
135 | seq_puts(s, "--------------------------------------------------------------------------------\n"); | 146 | seq_puts(s, "--------------------------------------------------------------------------------\n"); |
136 | 147 | ||
137 | clk_prepare_lock(); | 148 | clk_prepare_lock(); |
138 | 149 | ||
139 | hlist_for_each_entry(c, &clk_root_list, child_node) | 150 | for (; *lists; lists++) |
140 | clk_summary_show_subtree(s, c, 0); | 151 | hlist_for_each_entry(c, *lists, child_node) |
141 | 152 | clk_summary_show_subtree(s, c, 0); | |
142 | hlist_for_each_entry(c, &clk_orphan_list, child_node) | ||
143 | clk_summary_show_subtree(s, c, 0); | ||
144 | 153 | ||
145 | clk_prepare_unlock(); | 154 | clk_prepare_unlock(); |
146 | 155 | ||
@@ -193,21 +202,19 @@ static int clk_dump(struct seq_file *s, void *data) | |||
193 | { | 202 | { |
194 | struct clk *c; | 203 | struct clk *c; |
195 | bool first_node = true; | 204 | bool first_node = true; |
205 | struct hlist_head **lists = (struct hlist_head **)s->private; | ||
196 | 206 | ||
197 | seq_printf(s, "{"); | 207 | seq_printf(s, "{"); |
198 | 208 | ||
199 | clk_prepare_lock(); | 209 | clk_prepare_lock(); |
200 | 210 | ||
201 | hlist_for_each_entry(c, &clk_root_list, child_node) { | 211 | for (; *lists; lists++) { |
202 | if (!first_node) | 212 | hlist_for_each_entry(c, *lists, child_node) { |
203 | seq_printf(s, ","); | 213 | if (!first_node) |
204 | first_node = false; | 214 | seq_puts(s, ","); |
205 | clk_dump_subtree(s, c, 0); | 215 | first_node = false; |
206 | } | 216 | clk_dump_subtree(s, c, 0); |
207 | 217 | } | |
208 | hlist_for_each_entry(c, &clk_orphan_list, child_node) { | ||
209 | seq_printf(s, ","); | ||
210 | clk_dump_subtree(s, c, 0); | ||
211 | } | 218 | } |
212 | 219 | ||
213 | clk_prepare_unlock(); | 220 | clk_prepare_unlock(); |
@@ -305,7 +312,7 @@ static int clk_debug_create_subtree(struct clk *clk, struct dentry *pdentry) | |||
305 | goto out; | 312 | goto out; |
306 | 313 | ||
307 | hlist_for_each_entry(child, &clk->children, child_node) | 314 | hlist_for_each_entry(child, &clk->children, child_node) |
308 | clk_debug_create_subtree(child, clk->dentry); | 315 | clk_debug_create_subtree(child, pdentry); |
309 | 316 | ||
310 | ret = 0; | 317 | ret = 0; |
311 | out: | 318 | out: |
@@ -325,31 +332,12 @@ out: | |||
325 | */ | 332 | */ |
326 | static int clk_debug_register(struct clk *clk) | 333 | static int clk_debug_register(struct clk *clk) |
327 | { | 334 | { |
328 | struct clk *parent; | ||
329 | struct dentry *pdentry; | ||
330 | int ret = 0; | 335 | int ret = 0; |
331 | 336 | ||
332 | if (!inited) | 337 | if (!inited) |
333 | goto out; | 338 | goto out; |
334 | 339 | ||
335 | parent = clk->parent; | 340 | ret = clk_debug_create_subtree(clk, rootdir); |
336 | |||
337 | /* | ||
338 | * Check to see if a clk is a root clk. Also check that it is | ||
339 | * safe to add this clk to debugfs | ||
340 | */ | ||
341 | if (!parent) | ||
342 | if (clk->flags & CLK_IS_ROOT) | ||
343 | pdentry = rootdir; | ||
344 | else | ||
345 | pdentry = orphandir; | ||
346 | else | ||
347 | if (parent->dentry) | ||
348 | pdentry = parent->dentry; | ||
349 | else | ||
350 | goto out; | ||
351 | |||
352 | ret = clk_debug_create_subtree(clk, pdentry); | ||
353 | 341 | ||
354 | out: | 342 | out: |
355 | return ret; | 343 | return ret; |
@@ -371,39 +359,6 @@ static void clk_debug_unregister(struct clk *clk) | |||
371 | } | 359 | } |
372 | 360 | ||
373 | /** | 361 | /** |
374 | * clk_debug_reparent - reparent clk node in the debugfs clk tree | ||
375 | * @clk: the clk being reparented | ||
376 | * @new_parent: the new clk parent, may be NULL | ||
377 | * | ||
378 | * Rename clk entry in the debugfs clk tree if debugfs has been | ||
379 | * initialized. Otherwise it bails out early since the debugfs clk tree | ||
380 | * will be created lazily by clk_debug_init as part of a late_initcall. | ||
381 | * | ||
382 | * Caller must hold prepare_lock. | ||
383 | */ | ||
384 | static void clk_debug_reparent(struct clk *clk, struct clk *new_parent) | ||
385 | { | ||
386 | struct dentry *d; | ||
387 | struct dentry *new_parent_d; | ||
388 | |||
389 | if (!inited) | ||
390 | return; | ||
391 | |||
392 | if (new_parent) | ||
393 | new_parent_d = new_parent->dentry; | ||
394 | else | ||
395 | new_parent_d = orphandir; | ||
396 | |||
397 | d = debugfs_rename(clk->dentry->d_parent, clk->dentry, | ||
398 | new_parent_d, clk->name); | ||
399 | if (d) | ||
400 | clk->dentry = d; | ||
401 | else | ||
402 | pr_debug("%s: failed to rename debugfs entry for %s\n", | ||
403 | __func__, clk->name); | ||
404 | } | ||
405 | |||
406 | /** | ||
407 | * clk_debug_init - lazily create the debugfs clk tree visualization | 362 | * clk_debug_init - lazily create the debugfs clk tree visualization |
408 | * | 363 | * |
409 | * clks are often initialized very early during boot before memory can | 364 | * clks are often initialized very early during boot before memory can |
@@ -425,19 +380,24 @@ static int __init clk_debug_init(void) | |||
425 | if (!rootdir) | 380 | if (!rootdir) |
426 | return -ENOMEM; | 381 | return -ENOMEM; |
427 | 382 | ||
428 | d = debugfs_create_file("clk_summary", S_IRUGO, rootdir, NULL, | 383 | d = debugfs_create_file("clk_summary", S_IRUGO, rootdir, &all_lists, |
429 | &clk_summary_fops); | 384 | &clk_summary_fops); |
430 | if (!d) | 385 | if (!d) |
431 | return -ENOMEM; | 386 | return -ENOMEM; |
432 | 387 | ||
433 | d = debugfs_create_file("clk_dump", S_IRUGO, rootdir, NULL, | 388 | d = debugfs_create_file("clk_dump", S_IRUGO, rootdir, &all_lists, |
434 | &clk_dump_fops); | 389 | &clk_dump_fops); |
435 | if (!d) | 390 | if (!d) |
436 | return -ENOMEM; | 391 | return -ENOMEM; |
437 | 392 | ||
438 | orphandir = debugfs_create_dir("orphans", rootdir); | 393 | d = debugfs_create_file("clk_orphan_summary", S_IRUGO, rootdir, |
394 | &orphan_list, &clk_summary_fops); | ||
395 | if (!d) | ||
396 | return -ENOMEM; | ||
439 | 397 | ||
440 | if (!orphandir) | 398 | d = debugfs_create_file("clk_orphan_dump", S_IRUGO, rootdir, |
399 | &orphan_list, &clk_dump_fops); | ||
400 | if (!d) | ||
441 | return -ENOMEM; | 401 | return -ENOMEM; |
442 | 402 | ||
443 | clk_prepare_lock(); | 403 | clk_prepare_lock(); |
@@ -446,7 +406,7 @@ static int __init clk_debug_init(void) | |||
446 | clk_debug_create_subtree(clk, rootdir); | 406 | clk_debug_create_subtree(clk, rootdir); |
447 | 407 | ||
448 | hlist_for_each_entry(clk, &clk_orphan_list, child_node) | 408 | hlist_for_each_entry(clk, &clk_orphan_list, child_node) |
449 | clk_debug_create_subtree(clk, orphandir); | 409 | clk_debug_create_subtree(clk, rootdir); |
450 | 410 | ||
451 | inited = 1; | 411 | inited = 1; |
452 | 412 | ||
@@ -1284,9 +1244,6 @@ static void __clk_set_parent_after(struct clk *clk, struct clk *parent, | |||
1284 | clk_disable(old_parent); | 1244 | clk_disable(old_parent); |
1285 | __clk_unprepare(old_parent); | 1245 | __clk_unprepare(old_parent); |
1286 | } | 1246 | } |
1287 | |||
1288 | /* update debugfs with new clk tree topology */ | ||
1289 | clk_debug_reparent(clk, parent); | ||
1290 | } | 1247 | } |
1291 | 1248 | ||
1292 | static int __clk_set_parent(struct clk *clk, struct clk *parent, u8 p_index) | 1249 | static int __clk_set_parent(struct clk *clk, struct clk *parent, u8 p_index) |
@@ -1683,7 +1640,6 @@ out: | |||
1683 | void __clk_reparent(struct clk *clk, struct clk *new_parent) | 1640 | void __clk_reparent(struct clk *clk, struct clk *new_parent) |
1684 | { | 1641 | { |
1685 | clk_reparent(clk, new_parent); | 1642 | clk_reparent(clk, new_parent); |
1686 | clk_debug_reparent(clk, new_parent); | ||
1687 | __clk_recalc_accuracies(clk); | 1643 | __clk_recalc_accuracies(clk); |
1688 | __clk_recalc_rates(clk, POST_RATE_CHANGE); | 1644 | __clk_recalc_rates(clk, POST_RATE_CHANGE); |
1689 | } | 1645 | } |