Skip to content

Commit 1a0013c

Browse files
cdleonardGeorgi Djakov
authored andcommitted
interconnect: Add interconnect_graph file to debugfs
The interconnect graphs can be difficult to understand and the current "interconnect_summary" file doesn't even display links in any way. Add a new "interconnect_graph" file to debugfs in the graphviz "dot" format which describes interconnect providers, nodes and links. The file is human-readable and can be visualized by piping through graphviz. Example: ssh $TARGET cat /sys/kernel/debug/interconnect/interconnect_graph \ | dot -Tsvg > interconnect_graph.svg Signed-off-by: Leonard Crestez <[email protected]> Reviewed-by: Greg Kroah-Hartman <[email protected]> Reviewed-by: Bjorn Andersson <[email protected]> Signed-off-by: Georgi Djakov <[email protected]>
1 parent b92c35e commit 1a0013c

File tree

2 files changed

+88
-0
lines changed

2 files changed

+88
-0
lines changed

Documentation/driver-api/interconnect.rst

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,3 +91,25 @@ Interconnect consumers are the clients which use the interconnect APIs to
9191
get paths between endpoints and set their bandwidth/latency/QoS requirements
9292
for these interconnect paths. These interfaces are not currently
9393
documented.
94+
95+
Interconnect debugfs interfaces
96+
-------------------------------
97+
98+
Like several other subsystems interconnect will create some files for debugging
99+
and introspection. Files in debugfs are not considered ABI so application
100+
software shouldn't rely on format details change between kernel versions.
101+
102+
``/sys/kernel/debug/interconnect/interconnect_summary``:
103+
104+
Show all interconnect nodes in the system with their aggregated bandwidth
105+
request. Indented under each node show bandwidth requests from each device.
106+
107+
``/sys/kernel/debug/interconnect/interconnect_graph``:
108+
109+
Show the interconnect graph in the graphviz dot format. It shows all
110+
interconnect nodes and links in the system and groups together nodes from the
111+
same provider as subgraphs. The format is human-readable and can also be piped
112+
through dot to generate diagrams in many graphical formats::
113+
114+
$ cat /sys/kernel/debug/interconnect/interconnect_graph | \
115+
dot -Tsvg > interconnect_graph.svg

drivers/interconnect/core.c

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,70 @@ static int icc_summary_show(struct seq_file *s, void *data)
7171
}
7272
DEFINE_SHOW_ATTRIBUTE(icc_summary);
7373

74+
static void icc_graph_show_link(struct seq_file *s, int level,
75+
struct icc_node *n, struct icc_node *m)
76+
{
77+
seq_printf(s, "%s\"%d:%s\" -> \"%d:%s\"\n",
78+
level == 2 ? "\t\t" : "\t",
79+
n->id, n->name, m->id, m->name);
80+
}
81+
82+
static void icc_graph_show_node(struct seq_file *s, struct icc_node *n)
83+
{
84+
seq_printf(s, "\t\t\"%d:%s\" [label=\"%d:%s",
85+
n->id, n->name, n->id, n->name);
86+
seq_printf(s, "\n\t\t\t|avg_bw=%ukBps", n->avg_bw);
87+
seq_printf(s, "\n\t\t\t|peak_bw=%ukBps", n->peak_bw);
88+
seq_puts(s, "\"]\n");
89+
}
90+
91+
static int icc_graph_show(struct seq_file *s, void *data)
92+
{
93+
struct icc_provider *provider;
94+
struct icc_node *n;
95+
int cluster_index = 0;
96+
int i;
97+
98+
seq_puts(s, "digraph {\n\trankdir = LR\n\tnode [shape = record]\n");
99+
mutex_lock(&icc_lock);
100+
101+
/* draw providers as cluster subgraphs */
102+
cluster_index = 0;
103+
list_for_each_entry(provider, &icc_providers, provider_list) {
104+
seq_printf(s, "\tsubgraph cluster_%d {\n", ++cluster_index);
105+
if (provider->dev)
106+
seq_printf(s, "\t\tlabel = \"%s\"\n",
107+
dev_name(provider->dev));
108+
109+
/* draw nodes */
110+
list_for_each_entry(n, &provider->nodes, node_list)
111+
icc_graph_show_node(s, n);
112+
113+
/* draw internal links */
114+
list_for_each_entry(n, &provider->nodes, node_list)
115+
for (i = 0; i < n->num_links; ++i)
116+
if (n->provider == n->links[i]->provider)
117+
icc_graph_show_link(s, 2, n,
118+
n->links[i]);
119+
120+
seq_puts(s, "\t}\n");
121+
}
122+
123+
/* draw external links */
124+
list_for_each_entry(provider, &icc_providers, provider_list)
125+
list_for_each_entry(n, &provider->nodes, node_list)
126+
for (i = 0; i < n->num_links; ++i)
127+
if (n->provider != n->links[i]->provider)
128+
icc_graph_show_link(s, 1, n,
129+
n->links[i]);
130+
131+
mutex_unlock(&icc_lock);
132+
seq_puts(s, "}");
133+
134+
return 0;
135+
}
136+
DEFINE_SHOW_ATTRIBUTE(icc_graph);
137+
74138
static struct icc_node *node_find(const int id)
75139
{
76140
return idr_find(&icc_idr, id);
@@ -827,6 +891,8 @@ static int __init icc_init(void)
827891
icc_debugfs_dir = debugfs_create_dir("interconnect", NULL);
828892
debugfs_create_file("interconnect_summary", 0444,
829893
icc_debugfs_dir, NULL, &icc_summary_fops);
894+
debugfs_create_file("interconnect_graph", 0444,
895+
icc_debugfs_dir, NULL, &icc_graph_fops);
830896
return 0;
831897
}
832898

0 commit comments

Comments
 (0)