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