diff options
| -rw-r--r-- | drivers/char/virtio_console.c | 71 |
1 files changed, 71 insertions, 0 deletions
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index 9f20fda9c56f..2a04daa9189e 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c | |||
| @@ -17,6 +17,7 @@ | |||
| 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 18 | */ | 18 | */ |
| 19 | #include <linux/cdev.h> | 19 | #include <linux/cdev.h> |
| 20 | #include <linux/debugfs.h> | ||
| 20 | #include <linux/device.h> | 21 | #include <linux/device.h> |
| 21 | #include <linux/err.h> | 22 | #include <linux/err.h> |
| 22 | #include <linux/fs.h> | 23 | #include <linux/fs.h> |
| @@ -43,6 +44,9 @@ struct ports_driver_data { | |||
| 43 | /* Used for registering chardevs */ | 44 | /* Used for registering chardevs */ |
| 44 | struct class *class; | 45 | struct class *class; |
| 45 | 46 | ||
| 47 | /* Used for exporting per-port information to debugfs */ | ||
| 48 | struct dentry *debugfs_dir; | ||
| 49 | |||
| 46 | /* Number of devices this driver is handling */ | 50 | /* Number of devices this driver is handling */ |
| 47 | unsigned int index; | 51 | unsigned int index; |
| 48 | 52 | ||
| @@ -158,6 +162,9 @@ struct port { | |||
| 158 | /* The IO vqs for this port */ | 162 | /* The IO vqs for this port */ |
| 159 | struct virtqueue *in_vq, *out_vq; | 163 | struct virtqueue *in_vq, *out_vq; |
| 160 | 164 | ||
| 165 | /* File in the debugfs directory that exposes this port's information */ | ||
| 166 | struct dentry *debugfs_file; | ||
| 167 | |||
| 161 | /* | 168 | /* |
| 162 | * The entries in this struct will be valid if this port is | 169 | * The entries in this struct will be valid if this port is |
| 163 | * hooked up to an hvc console | 170 | * hooked up to an hvc console |
| @@ -783,6 +790,49 @@ static struct attribute_group port_attribute_group = { | |||
| 783 | .attrs = port_sysfs_entries, | 790 | .attrs = port_sysfs_entries, |
| 784 | }; | 791 | }; |
| 785 | 792 | ||
| 793 | static int debugfs_open(struct inode *inode, struct file *filp) | ||
| 794 | { | ||
| 795 | filp->private_data = inode->i_private; | ||
| 796 | return 0; | ||
| 797 | } | ||
| 798 | |||
| 799 | static ssize_t debugfs_read(struct file *filp, char __user *ubuf, | ||
| 800 | size_t count, loff_t *offp) | ||
| 801 | { | ||
| 802 | struct port *port; | ||
| 803 | char *buf; | ||
| 804 | ssize_t ret, out_offset, out_count; | ||
| 805 | |||
| 806 | out_count = 1024; | ||
| 807 | buf = kmalloc(out_count, GFP_KERNEL); | ||
| 808 | if (!buf) | ||
| 809 | return -ENOMEM; | ||
| 810 | |||
| 811 | port = filp->private_data; | ||
| 812 | out_offset = 0; | ||
| 813 | out_offset += snprintf(buf + out_offset, out_count, | ||
| 814 | "name: %s\n", port->name ? port->name : ""); | ||
| 815 | out_offset += snprintf(buf + out_offset, out_count - out_offset, | ||
| 816 | "guest_connected: %d\n", port->guest_connected); | ||
| 817 | out_offset += snprintf(buf + out_offset, out_count - out_offset, | ||
| 818 | "host_connected: %d\n", port->host_connected); | ||
| 819 | out_offset += snprintf(buf + out_offset, out_count - out_offset, | ||
| 820 | "is_console: %s\n", | ||
| 821 | is_console_port(port) ? "yes" : "no"); | ||
| 822 | out_offset += snprintf(buf + out_offset, out_count - out_offset, | ||
| 823 | "console_vtermno: %u\n", port->cons.vtermno); | ||
| 824 | |||
| 825 | ret = simple_read_from_buffer(ubuf, count, offp, buf, out_offset); | ||
| 826 | kfree(buf); | ||
| 827 | return ret; | ||
| 828 | } | ||
| 829 | |||
| 830 | static const struct file_operations port_debugfs_ops = { | ||
| 831 | .owner = THIS_MODULE, | ||
| 832 | .open = debugfs_open, | ||
| 833 | .read = debugfs_read, | ||
| 834 | }; | ||
| 835 | |||
| 786 | /* Remove all port-specific data. */ | 836 | /* Remove all port-specific data. */ |
| 787 | static int remove_port(struct port *port) | 837 | static int remove_port(struct port *port) |
| 788 | { | 838 | { |
| @@ -809,6 +859,8 @@ static int remove_port(struct port *port) | |||
| 809 | discard_port_data(port); | 859 | discard_port_data(port); |
| 810 | kfree(port->name); | 860 | kfree(port->name); |
| 811 | 861 | ||
| 862 | debugfs_remove(port->debugfs_file); | ||
| 863 | |||
| 812 | kfree(port); | 864 | kfree(port); |
| 813 | return 0; | 865 | return 0; |
| 814 | } | 866 | } |
| @@ -1021,6 +1073,7 @@ static void fill_queue(struct virtqueue *vq, spinlock_t *lock) | |||
| 1021 | 1073 | ||
| 1022 | static int add_port(struct ports_device *portdev, u32 id) | 1074 | static int add_port(struct ports_device *portdev, u32 id) |
| 1023 | { | 1075 | { |
| 1076 | char debugfs_name[16]; | ||
| 1024 | struct port *port; | 1077 | struct port *port; |
| 1025 | struct port_buffer *inbuf; | 1078 | struct port_buffer *inbuf; |
| 1026 | dev_t devt; | 1079 | dev_t devt; |
| @@ -1096,6 +1149,18 @@ static int add_port(struct ports_device *portdev, u32 id) | |||
| 1096 | */ | 1149 | */ |
| 1097 | send_control_msg(port, VIRTIO_CONSOLE_PORT_READY, 1); | 1150 | send_control_msg(port, VIRTIO_CONSOLE_PORT_READY, 1); |
| 1098 | 1151 | ||
| 1152 | if (pdrvdata.debugfs_dir) { | ||
| 1153 | /* | ||
| 1154 | * Finally, create the debugfs file that we can use to | ||
| 1155 | * inspect a port's state at any time | ||
| 1156 | */ | ||
| 1157 | sprintf(debugfs_name, "vport%up%u", | ||
| 1158 | port->portdev->drv_index, id); | ||
| 1159 | port->debugfs_file = debugfs_create_file(debugfs_name, 0444, | ||
| 1160 | pdrvdata.debugfs_dir, | ||
| 1161 | port, | ||
| 1162 | &port_debugfs_ops); | ||
| 1163 | } | ||
| 1099 | return 0; | 1164 | return 0; |
| 1100 | 1165 | ||
| 1101 | free_inbuf: | 1166 | free_inbuf: |
| @@ -1406,6 +1471,12 @@ static int __init init(void) | |||
| 1406 | pr_err("Error %d creating virtio-ports class\n", err); | 1471 | pr_err("Error %d creating virtio-ports class\n", err); |
| 1407 | return err; | 1472 | return err; |
| 1408 | } | 1473 | } |
| 1474 | |||
| 1475 | pdrvdata.debugfs_dir = debugfs_create_dir("virtio-ports", NULL); | ||
| 1476 | if (!pdrvdata.debugfs_dir) { | ||
| 1477 | pr_warning("Error %ld creating debugfs dir for virtio-ports\n", | ||
| 1478 | PTR_ERR(pdrvdata.debugfs_dir)); | ||
| 1479 | } | ||
| 1409 | INIT_LIST_HEAD(&pdrvdata.consoles); | 1480 | INIT_LIST_HEAD(&pdrvdata.consoles); |
| 1410 | 1481 | ||
| 1411 | return register_virtio_driver(&virtio_console); | 1482 | return register_virtio_driver(&virtio_console); |
