OSDN Git Service

clk: Add support to dump state of all clocks into ftrace
authorAmit Nischal <anischal@codeaurora.org>
Mon, 6 Mar 2017 11:10:58 +0000 (16:40 +0530)
committerAmit Nischal <anischal@codeaurora.org>
Tue, 2 May 2017 03:51:47 +0000 (09:21 +0530)
Add clk_state event to record the state of all the clocks
into ftrace. The clock event could be triggered by using
the "trace_clocks" debugfs entry and it would dump the
current state of all clocks in ftrace logs.

Change-Id: I28b6574fe1d96472833a93e7b251dbba6c6eae49
Signed-off-by: Amit Nischal <anischal@codeaurora.org>
drivers/clk/clk.c
include/trace/events/clk.h

index 4a9e034..4996f4f 100644 (file)
@@ -2326,6 +2326,56 @@ static struct hlist_head *orphan_list[] = {
        NULL,
 };
 
+static void clk_state_subtree(struct clk_core *c)
+{
+       int vdd_level = 0;
+       struct clk_core *child;
+
+       if (!c)
+               return;
+
+       if (c->vdd_class) {
+               vdd_level = clk_find_vdd_level(c, c->rate);
+               if (vdd_level < 0)
+                       vdd_level = 0;
+       }
+
+       trace_clk_state(c->name, c->prepare_count, c->enable_count,
+                                               c->rate, vdd_level);
+
+       hlist_for_each_entry(child, &c->children, child_node)
+               clk_state_subtree(child);
+}
+
+static int clk_state_show(struct seq_file *s, void *data)
+{
+       struct clk_core *c;
+       struct hlist_head **lists = (struct hlist_head **)s->private;
+
+       clk_prepare_lock();
+
+       for (; *lists; lists++)
+               hlist_for_each_entry(c, *lists, child_node)
+                       clk_state_subtree(c);
+
+       clk_prepare_unlock();
+
+       return 0;
+}
+
+
+static int clk_state_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, clk_state_show, inode->i_private);
+}
+
+static const struct file_operations clk_state_fops = {
+       .open           = clk_state_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
 static void clk_summary_show_one(struct seq_file *s, struct clk_core *c,
                                 int level)
 {
@@ -3002,6 +3052,11 @@ static int __init clk_debug_init(void)
        if (!d)
                return -ENOMEM;
 
+       d = debugfs_create_file("trace_clocks", S_IRUGO, rootdir, &all_lists,
+                               &clk_state_fops);
+       if (!d)
+               return -ENOMEM;
+
        mutex_lock(&clk_debug_lock);
        hlist_for_each_entry(core, &clk_debug_list, debug_node)
                clk_debug_create_one(core, rootdir);
index 7586072..ad19e73 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2015, 2017, The Linux Foundation. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -192,6 +192,42 @@ DEFINE_EVENT(clk_phase, clk_set_phase_complete,
        TP_ARGS(core, phase)
 );
 
+DECLARE_EVENT_CLASS(clk_state_dump,
+
+       TP_PROTO(const char *name, unsigned int prepare_count,
+       unsigned int enable_count, unsigned long rate, unsigned int vdd_level),
+
+       TP_ARGS(name, prepare_count, enable_count, rate, vdd_level),
+
+       TP_STRUCT__entry(
+               __string(name,                  name)
+               __field(unsigned int,           prepare_count)
+               __field(unsigned int,           enable_count)
+               __field(unsigned long,          rate)
+               __field(unsigned int,           vdd_level)
+       ),
+
+       TP_fast_assign(
+               __assign_str(name, name);
+               __entry->prepare_count = prepare_count;
+               __entry->enable_count = enable_count;
+               __entry->rate = rate;
+               __entry->vdd_level = vdd_level;
+       ),
+
+       TP_printk("%s\tprepare:enable cnt [%u:%u]\trate: vdd_level [%lu:%u]",
+               __get_str(name), __entry->prepare_count, __entry->enable_count,
+               __entry->rate, __entry->vdd_level)
+);
+
+DEFINE_EVENT(clk_state_dump, clk_state,
+
+       TP_PROTO(const char *name, unsigned int prepare_count,
+       unsigned int enable_count, unsigned long rate, unsigned int vdd_level),
+
+       TP_ARGS(name, prepare_count, enable_count, rate, vdd_level)
+);
+
 #endif /* _TRACE_CLK_H */
 
 /* This part must be outside protection */