aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base/component.c
diff options
context:
space:
mode:
authorMaciej Purski <m.purski@samsung.com>2017-12-01 08:23:16 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-12-18 10:51:11 -0500
commit59e73854b5fd1213fe90ae993d98c759786c3712 (patch)
tree7aeff8061dd2d355bb084d4279bf526ea265546b /drivers/base/component.c
parent0a006e864edc077451384bd28ac9be36e8d172e5 (diff)
component: add debugfs support
Currently there is no information in any vfs about which devices a master component consists of, what makes debugging hard if one of the component devices fails to register. Add 'device_component' directory to debugfs. Create a new file for each component master, when it has been added. Remove it on a master deletion. Show a list of devices required by the given master and their status (registered or not). This provides an easy way to check, which device has failed to register if the given master device is not available in the system. Signed-off-by: Maciej Purski <m.purski@samsung.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/base/component.c')
-rw-r--r--drivers/base/component.c78
1 files changed, 78 insertions, 0 deletions
diff --git a/drivers/base/component.c b/drivers/base/component.c
index 891f0e38647c..8946dfee4768 100644
--- a/drivers/base/component.c
+++ b/drivers/base/component.c
@@ -14,6 +14,7 @@
14#include <linux/module.h> 14#include <linux/module.h>
15#include <linux/mutex.h> 15#include <linux/mutex.h>
16#include <linux/slab.h> 16#include <linux/slab.h>
17#include <linux/debugfs.h>
17 18
18struct component; 19struct component;
19 20
@@ -38,6 +39,7 @@ struct master {
38 const struct component_master_ops *ops; 39 const struct component_master_ops *ops;
39 struct device *dev; 40 struct device *dev;
40 struct component_match *match; 41 struct component_match *match;
42 struct dentry *dentry;
41}; 43};
42 44
43struct component { 45struct component {
@@ -53,6 +55,80 @@ static DEFINE_MUTEX(component_mutex);
53static LIST_HEAD(component_list); 55static LIST_HEAD(component_list);
54static LIST_HEAD(masters); 56static LIST_HEAD(masters);
55 57
58#ifdef CONFIG_DEBUG_FS
59
60static struct dentry *component_debugfs_dir;
61
62static int component_devices_show(struct seq_file *s, void *data)
63{
64 struct master *m = s->private;
65 struct component_match *match = m->match;
66 size_t i;
67
68 mutex_lock(&component_mutex);
69 seq_printf(s, "%-40s %20s\n", "master name", "status");
70 seq_puts(s, "-------------------------------------------------------------\n");
71 seq_printf(s, "%-40s %20s\n\n",
72 dev_name(m->dev), m->bound ? "bound" : "not bound");
73
74 seq_printf(s, "%-40s %20s\n", "device name", "status");
75 seq_puts(s, "-------------------------------------------------------------\n");
76 for (i = 0; i < match->num; i++) {
77 struct device *d = (struct device *)match->compare[i].data;
78
79 seq_printf(s, "%-40s %20s\n", dev_name(d),
80 match->compare[i].component ?
81 "registered" : "not registered");
82 }
83 mutex_unlock(&component_mutex);
84
85 return 0;
86}
87
88static int component_devices_open(struct inode *inode, struct file *file)
89{
90 return single_open(file, component_devices_show, inode->i_private);
91}
92
93static const struct file_operations component_devices_fops = {
94 .open = component_devices_open,
95 .read = seq_read,
96 .llseek = seq_lseek,
97 .release = single_release,
98};
99
100static int __init component_debug_init(void)
101{
102 component_debugfs_dir = debugfs_create_dir("device_component", NULL);
103
104 return 0;
105}
106
107core_initcall(component_debug_init);
108
109static void component_master_debugfs_add(struct master *m)
110{
111 m->dentry = debugfs_create_file(dev_name(m->dev), 0444,
112 component_debugfs_dir,
113 m, &component_devices_fops);
114}
115
116static void component_master_debugfs_del(struct master *m)
117{
118 debugfs_remove(m->dentry);
119 m->dentry = NULL;
120}
121
122#else
123
124static void component_master_debugfs_add(struct master *m)
125{ }
126
127static void component_master_debugfs_del(struct master *m)
128{ }
129
130#endif
131
56static struct master *__master_find(struct device *dev, 132static struct master *__master_find(struct device *dev,
57 const struct component_master_ops *ops) 133 const struct component_master_ops *ops)
58{ 134{
@@ -287,6 +363,7 @@ static void free_master(struct master *master)
287 struct component_match *match = master->match; 363 struct component_match *match = master->match;
288 int i; 364 int i;
289 365
366 component_master_debugfs_del(master);
290 list_del(&master->node); 367 list_del(&master->node);
291 368
292 if (match) { 369 if (match) {
@@ -320,6 +397,7 @@ int component_master_add_with_match(struct device *dev,
320 master->ops = ops; 397 master->ops = ops;
321 master->match = match; 398 master->match = match;
322 399
400 component_master_debugfs_add(master);
323 /* Add to the list of available masters. */ 401 /* Add to the list of available masters. */
324 mutex_lock(&component_mutex); 402 mutex_lock(&component_mutex);
325 list_add(&master->node, &masters); 403 list_add(&master->node, &masters);