1*96a8326dSJiri Pirko // SPDX-License-Identifier: GPL-2.0-or-later
2*96a8326dSJiri Pirko
3*96a8326dSJiri Pirko #include <linux/virtio.h>
4*96a8326dSJiri Pirko #include <linux/virtio_config.h>
5*96a8326dSJiri Pirko #include <linux/debugfs.h>
6*96a8326dSJiri Pirko
7*96a8326dSJiri Pirko static struct dentry *virtio_debugfs_dir;
8*96a8326dSJiri Pirko
virtio_debug_device_features_show(struct seq_file * s,void * data)9*96a8326dSJiri Pirko static int virtio_debug_device_features_show(struct seq_file *s, void *data)
10*96a8326dSJiri Pirko {
11*96a8326dSJiri Pirko struct virtio_device *dev = s->private;
12*96a8326dSJiri Pirko u64 device_features;
13*96a8326dSJiri Pirko unsigned int i;
14*96a8326dSJiri Pirko
15*96a8326dSJiri Pirko device_features = dev->config->get_features(dev);
16*96a8326dSJiri Pirko for (i = 0; i < BITS_PER_LONG_LONG; i++) {
17*96a8326dSJiri Pirko if (device_features & (1ULL << i))
18*96a8326dSJiri Pirko seq_printf(s, "%u\n", i);
19*96a8326dSJiri Pirko }
20*96a8326dSJiri Pirko return 0;
21*96a8326dSJiri Pirko }
22*96a8326dSJiri Pirko DEFINE_SHOW_ATTRIBUTE(virtio_debug_device_features);
23*96a8326dSJiri Pirko
virtio_debug_filter_features_show(struct seq_file * s,void * data)24*96a8326dSJiri Pirko static int virtio_debug_filter_features_show(struct seq_file *s, void *data)
25*96a8326dSJiri Pirko {
26*96a8326dSJiri Pirko struct virtio_device *dev = s->private;
27*96a8326dSJiri Pirko unsigned int i;
28*96a8326dSJiri Pirko
29*96a8326dSJiri Pirko for (i = 0; i < BITS_PER_LONG_LONG; i++) {
30*96a8326dSJiri Pirko if (dev->debugfs_filter_features & (1ULL << i))
31*96a8326dSJiri Pirko seq_printf(s, "%u\n", i);
32*96a8326dSJiri Pirko }
33*96a8326dSJiri Pirko return 0;
34*96a8326dSJiri Pirko }
35*96a8326dSJiri Pirko DEFINE_SHOW_ATTRIBUTE(virtio_debug_filter_features);
36*96a8326dSJiri Pirko
virtio_debug_filter_features_clear(void * data,u64 val)37*96a8326dSJiri Pirko static int virtio_debug_filter_features_clear(void *data, u64 val)
38*96a8326dSJiri Pirko {
39*96a8326dSJiri Pirko struct virtio_device *dev = data;
40*96a8326dSJiri Pirko
41*96a8326dSJiri Pirko if (val == 1)
42*96a8326dSJiri Pirko dev->debugfs_filter_features = 0;
43*96a8326dSJiri Pirko return 0;
44*96a8326dSJiri Pirko }
45*96a8326dSJiri Pirko
46*96a8326dSJiri Pirko DEFINE_DEBUGFS_ATTRIBUTE(virtio_debug_filter_features_clear_fops, NULL,
47*96a8326dSJiri Pirko virtio_debug_filter_features_clear, "%llu\n");
48*96a8326dSJiri Pirko
virtio_debug_filter_feature_add(void * data,u64 val)49*96a8326dSJiri Pirko static int virtio_debug_filter_feature_add(void *data, u64 val)
50*96a8326dSJiri Pirko {
51*96a8326dSJiri Pirko struct virtio_device *dev = data;
52*96a8326dSJiri Pirko
53*96a8326dSJiri Pirko if (val >= BITS_PER_LONG_LONG)
54*96a8326dSJiri Pirko return -EINVAL;
55*96a8326dSJiri Pirko dev->debugfs_filter_features |= BIT_ULL_MASK(val);
56*96a8326dSJiri Pirko return 0;
57*96a8326dSJiri Pirko }
58*96a8326dSJiri Pirko
59*96a8326dSJiri Pirko DEFINE_DEBUGFS_ATTRIBUTE(virtio_debug_filter_feature_add_fops, NULL,
60*96a8326dSJiri Pirko virtio_debug_filter_feature_add, "%llu\n");
61*96a8326dSJiri Pirko
virtio_debug_filter_feature_del(void * data,u64 val)62*96a8326dSJiri Pirko static int virtio_debug_filter_feature_del(void *data, u64 val)
63*96a8326dSJiri Pirko {
64*96a8326dSJiri Pirko struct virtio_device *dev = data;
65*96a8326dSJiri Pirko
66*96a8326dSJiri Pirko if (val >= BITS_PER_LONG_LONG)
67*96a8326dSJiri Pirko return -EINVAL;
68*96a8326dSJiri Pirko dev->debugfs_filter_features &= ~BIT_ULL_MASK(val);
69*96a8326dSJiri Pirko return 0;
70*96a8326dSJiri Pirko }
71*96a8326dSJiri Pirko
72*96a8326dSJiri Pirko DEFINE_DEBUGFS_ATTRIBUTE(virtio_debug_filter_feature_del_fops, NULL,
73*96a8326dSJiri Pirko virtio_debug_filter_feature_del, "%llu\n");
74*96a8326dSJiri Pirko
virtio_debug_device_init(struct virtio_device * dev)75*96a8326dSJiri Pirko void virtio_debug_device_init(struct virtio_device *dev)
76*96a8326dSJiri Pirko {
77*96a8326dSJiri Pirko dev->debugfs_dir = debugfs_create_dir(dev_name(&dev->dev),
78*96a8326dSJiri Pirko virtio_debugfs_dir);
79*96a8326dSJiri Pirko debugfs_create_file("device_features", 0400, dev->debugfs_dir, dev,
80*96a8326dSJiri Pirko &virtio_debug_device_features_fops);
81*96a8326dSJiri Pirko debugfs_create_file("filter_features", 0400, dev->debugfs_dir, dev,
82*96a8326dSJiri Pirko &virtio_debug_filter_features_fops);
83*96a8326dSJiri Pirko debugfs_create_file("filter_features_clear", 0200, dev->debugfs_dir, dev,
84*96a8326dSJiri Pirko &virtio_debug_filter_features_clear_fops);
85*96a8326dSJiri Pirko debugfs_create_file("filter_feature_add", 0200, dev->debugfs_dir, dev,
86*96a8326dSJiri Pirko &virtio_debug_filter_feature_add_fops);
87*96a8326dSJiri Pirko debugfs_create_file("filter_feature_del", 0200, dev->debugfs_dir, dev,
88*96a8326dSJiri Pirko &virtio_debug_filter_feature_del_fops);
89*96a8326dSJiri Pirko }
90*96a8326dSJiri Pirko EXPORT_SYMBOL_GPL(virtio_debug_device_init);
91*96a8326dSJiri Pirko
virtio_debug_device_filter_features(struct virtio_device * dev)92*96a8326dSJiri Pirko void virtio_debug_device_filter_features(struct virtio_device *dev)
93*96a8326dSJiri Pirko {
94*96a8326dSJiri Pirko dev->features &= ~dev->debugfs_filter_features;
95*96a8326dSJiri Pirko }
96*96a8326dSJiri Pirko EXPORT_SYMBOL_GPL(virtio_debug_device_filter_features);
97*96a8326dSJiri Pirko
virtio_debug_device_exit(struct virtio_device * dev)98*96a8326dSJiri Pirko void virtio_debug_device_exit(struct virtio_device *dev)
99*96a8326dSJiri Pirko {
100*96a8326dSJiri Pirko debugfs_remove_recursive(dev->debugfs_dir);
101*96a8326dSJiri Pirko }
102*96a8326dSJiri Pirko EXPORT_SYMBOL_GPL(virtio_debug_device_exit);
103*96a8326dSJiri Pirko
virtio_debug_init(void)104*96a8326dSJiri Pirko void virtio_debug_init(void)
105*96a8326dSJiri Pirko {
106*96a8326dSJiri Pirko virtio_debugfs_dir = debugfs_create_dir("virtio", NULL);
107*96a8326dSJiri Pirko }
108*96a8326dSJiri Pirko EXPORT_SYMBOL_GPL(virtio_debug_init);
109*96a8326dSJiri Pirko
virtio_debug_exit(void)110*96a8326dSJiri Pirko void virtio_debug_exit(void)
111*96a8326dSJiri Pirko {
112*96a8326dSJiri Pirko debugfs_remove_recursive(virtio_debugfs_dir);
113*96a8326dSJiri Pirko }
114*96a8326dSJiri Pirko EXPORT_SYMBOL_GPL(virtio_debug_exit);
115