diff options
author | Amit Shah <amit.shah@redhat.com> | 2009-12-21 12:06:21 -0500 |
---|---|---|
committer | Rusty Russell <rusty@rustcorp.com.au> | 2010-02-23 22:53:01 -0500 |
commit | d99393effd76571cf2c4a07cbb6e86d41855a8fa (patch) | |
tree | 9c5b849aca2bbdde7293aefc4a0604743e68b7de /drivers/char/virtio_console.c | |
parent | 1f7aa42d166cd104b0700d61efe2064178a3f6da (diff) |
virtio: console: Add debugfs files for each port to expose debug info
This is helpful in examining ports' state.
Signed-off-by: Amit Shah <amit.shah@redhat.com>
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Diffstat (limited to 'drivers/char/virtio_console.c')
-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); |