aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/virtio_console.c
diff options
context:
space:
mode:
authorAmit Shah <amit.shah@redhat.com>2009-12-21 12:06:21 -0500
committerRusty Russell <rusty@rustcorp.com.au>2010-02-23 22:53:01 -0500
commitd99393effd76571cf2c4a07cbb6e86d41855a8fa (patch)
tree9c5b849aca2bbdde7293aefc4a0604743e68b7de /drivers/char/virtio_console.c
parent1f7aa42d166cd104b0700d61efe2064178a3f6da (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.c71
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
793static int debugfs_open(struct inode *inode, struct file *filp)
794{
795 filp->private_data = inode->i_private;
796 return 0;
797}
798
799static 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
830static 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. */
787static int remove_port(struct port *port) 837static 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
1022static int add_port(struct ports_device *portdev, u32 id) 1074static 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
1101free_inbuf: 1166free_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);