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 u64 device_features[VIRTIO_FEATURES_DWORDS]; 12 struct virtio_device *dev = s->private; 13 unsigned int i; 14 15 virtio_get_features(dev, device_features); 16 for (i = 0; i < VIRTIO_FEATURES_MAX; i++) { 17 if (virtio_features_test_bit(device_features, 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 < VIRTIO_FEATURES_MAX; i++) { 30 if (virtio_features_test_bit(dev->debugfs_filter_features, 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 virtio_features_zero(dev->debugfs_filter_features); 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 >= VIRTIO_FEATURES_MAX) 54 return -EINVAL; 55 56 virtio_features_set_bit(dev->debugfs_filter_features, val); 57 return 0; 58 } 59 60 DEFINE_DEBUGFS_ATTRIBUTE(virtio_debug_filter_feature_add_fops, NULL, 61 virtio_debug_filter_feature_add, "%llu\n"); 62 63 static int virtio_debug_filter_feature_del(void *data, u64 val) 64 { 65 struct virtio_device *dev = data; 66 67 if (val >= VIRTIO_FEATURES_MAX) 68 return -EINVAL; 69 70 virtio_features_clear_bit(dev->debugfs_filter_features, val); 71 return 0; 72 } 73 74 DEFINE_DEBUGFS_ATTRIBUTE(virtio_debug_filter_feature_del_fops, NULL, 75 virtio_debug_filter_feature_del, "%llu\n"); 76 77 void virtio_debug_device_init(struct virtio_device *dev) 78 { 79 dev->debugfs_dir = debugfs_create_dir(dev_name(&dev->dev), 80 virtio_debugfs_dir); 81 debugfs_create_file("device_features", 0400, dev->debugfs_dir, dev, 82 &virtio_debug_device_features_fops); 83 debugfs_create_file("filter_features", 0400, dev->debugfs_dir, dev, 84 &virtio_debug_filter_features_fops); 85 debugfs_create_file("filter_features_clear", 0200, dev->debugfs_dir, dev, 86 &virtio_debug_filter_features_clear_fops); 87 debugfs_create_file("filter_feature_add", 0200, dev->debugfs_dir, dev, 88 &virtio_debug_filter_feature_add_fops); 89 debugfs_create_file("filter_feature_del", 0200, dev->debugfs_dir, dev, 90 &virtio_debug_filter_feature_del_fops); 91 } 92 EXPORT_SYMBOL_GPL(virtio_debug_device_init); 93 94 void virtio_debug_device_filter_features(struct virtio_device *dev) 95 { 96 virtio_features_andnot(dev->features_array, dev->features_array, 97 dev->debugfs_filter_features); 98 } 99 EXPORT_SYMBOL_GPL(virtio_debug_device_filter_features); 100 101 void virtio_debug_device_exit(struct virtio_device *dev) 102 { 103 debugfs_remove_recursive(dev->debugfs_dir); 104 } 105 EXPORT_SYMBOL_GPL(virtio_debug_device_exit); 106 107 void virtio_debug_init(void) 108 { 109 virtio_debugfs_dir = debugfs_create_dir("virtio", NULL); 110 } 111 EXPORT_SYMBOL_GPL(virtio_debug_init); 112 113 void virtio_debug_exit(void) 114 { 115 debugfs_remove_recursive(virtio_debugfs_dir); 116 } 117 EXPORT_SYMBOL_GPL(virtio_debug_exit); 118