aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/char/Kconfig8
-rw-r--r--drivers/char/virtio_console.c81
2 files changed, 82 insertions, 7 deletions
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index e023682be2c4..3141dd3b6e53 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -666,6 +666,14 @@ config VIRTIO_CONSOLE
666 help 666 help
667 Virtio console for use with lguest and other hypervisors. 667 Virtio console for use with lguest and other hypervisors.
668 668
669 Also serves as a general-purpose serial device for data
670 transfer between the guest and host. Character devices at
671 /dev/vportNpn will be created when corresponding ports are
672 found, where N is the device number and n is the port number
673 within that device. If specified by the host, a sysfs
674 attribute called 'name' will be populated with a name for
675 the port which can be used by udev scripts to create a
676 symlink to the device.
669 677
670config HVCS 678config HVCS
671 tristate "IBM Hypervisor Virtual Console Server support" 679 tristate "IBM Hypervisor Virtual Console Server support"
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
index 8e447e1e12bc..64ef476d6557 100644
--- a/drivers/char/virtio_console.c
+++ b/drivers/char/virtio_console.c
@@ -16,6 +16,8 @@
16 * along with this program; if not, write to the Free Software 16 * along with this program; if not, write to the Free Software
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>
20#include <linux/device.h>
19#include <linux/err.h> 21#include <linux/err.h>
20#include <linux/init.h> 22#include <linux/init.h>
21#include <linux/list.h> 23#include <linux/list.h>
@@ -34,6 +36,12 @@
34 * across multiple devices and multiple ports per device. 36 * across multiple devices and multiple ports per device.
35 */ 37 */
36struct ports_driver_data { 38struct ports_driver_data {
39 /* Used for registering chardevs */
40 struct class *class;
41
42 /* Number of devices this driver is handling */
43 unsigned int index;
44
37 /* 45 /*
38 * This is used to keep track of the number of hvc consoles 46 * This is used to keep track of the number of hvc consoles
39 * spawned by this driver. This number is given as the first 47 * spawned by this driver. This number is given as the first
@@ -116,6 +124,12 @@ struct ports_device {
116 124
117 /* Array of per-port IO virtqueues */ 125 /* Array of per-port IO virtqueues */
118 struct virtqueue **in_vqs, **out_vqs; 126 struct virtqueue **in_vqs, **out_vqs;
127
128 /* Used for numbering devices for sysfs and debugfs */
129 unsigned int drv_index;
130
131 /* Major number for this device. Ports will be created as minors. */
132 int chr_major;
119}; 133};
120 134
121/* This struct holds the per-port data */ 135/* This struct holds the per-port data */
@@ -145,6 +159,10 @@ struct port {
145 */ 159 */
146 struct console cons; 160 struct console cons;
147 161
162 /* Each port associates with a separate char device */
163 struct cdev cdev;
164 struct device *dev;
165
148 /* The 'id' to identify the port with the Host */ 166 /* The 'id' to identify the port with the Host */
149 u32 id; 167 u32 id;
150}; 168};
@@ -391,7 +409,7 @@ static ssize_t fill_readbuf(struct port *port, char *out_buf, size_t out_count,
391 port->inbuf = NULL; 409 port->inbuf = NULL;
392 410
393 if (add_inbuf(port->in_vq, buf) < 0) 411 if (add_inbuf(port->in_vq, buf) < 0)
394 dev_warn(&port->portdev->vdev->dev, "failed add_buf\n"); 412 dev_warn(port->dev, "failed add_buf\n");
395 413
396 spin_unlock_irqrestore(&port->inbuf_lock, flags); 414 spin_unlock_irqrestore(&port->inbuf_lock, flags);
397 } 415 }
@@ -664,6 +682,7 @@ static int add_port(struct ports_device *portdev, u32 id)
664{ 682{
665 struct port *port; 683 struct port *port;
666 struct port_buffer *inbuf; 684 struct port_buffer *inbuf;
685 dev_t devt;
667 int err; 686 int err;
668 687
669 port = kmalloc(sizeof(*port), GFP_KERNEL); 688 port = kmalloc(sizeof(*port), GFP_KERNEL);
@@ -681,12 +700,32 @@ static int add_port(struct ports_device *portdev, u32 id)
681 port->in_vq = portdev->in_vqs[port->id]; 700 port->in_vq = portdev->in_vqs[port->id];
682 port->out_vq = portdev->out_vqs[port->id]; 701 port->out_vq = portdev->out_vqs[port->id];
683 702
703 cdev_init(&port->cdev, NULL);
704
705 devt = MKDEV(portdev->chr_major, id);
706 err = cdev_add(&port->cdev, devt, 1);
707 if (err < 0) {
708 dev_err(&port->portdev->vdev->dev,
709 "Error %d adding cdev for port %u\n", err, id);
710 goto free_port;
711 }
712 port->dev = device_create(pdrvdata.class, &port->portdev->vdev->dev,
713 devt, port, "vport%up%u",
714 port->portdev->drv_index, id);
715 if (IS_ERR(port->dev)) {
716 err = PTR_ERR(port->dev);
717 dev_err(&port->portdev->vdev->dev,
718 "Error %d creating device for port %u\n",
719 err, id);
720 goto free_cdev;
721 }
722
684 spin_lock_init(&port->inbuf_lock); 723 spin_lock_init(&port->inbuf_lock);
685 724
686 inbuf = alloc_buf(PAGE_SIZE); 725 inbuf = alloc_buf(PAGE_SIZE);
687 if (!inbuf) { 726 if (!inbuf) {
688 err = -ENOMEM; 727 err = -ENOMEM;
689 goto free_port; 728 goto free_device;
690 } 729 }
691 730
692 /* Register the input buffer the first time. */ 731 /* Register the input buffer the first time. */
@@ -716,6 +755,10 @@ static int add_port(struct ports_device *portdev, u32 id)
716 755
717free_inbuf: 756free_inbuf:
718 free_buf(inbuf); 757 free_buf(inbuf);
758free_device:
759 device_destroy(pdrvdata.class, port->dev->devt);
760free_cdev:
761 cdev_del(&port->cdev);
719free_port: 762free_port:
720 kfree(port); 763 kfree(port);
721fail: 764fail:
@@ -828,6 +871,10 @@ fail:
828 return err; 871 return err;
829} 872}
830 873
874static const struct file_operations portdev_fops = {
875 .owner = THIS_MODULE,
876};
877
831/* 878/*
832 * Once we're further in boot, we get probed like any other virtio 879 * Once we're further in boot, we get probed like any other virtio
833 * device. 880 * device.
@@ -853,6 +900,20 @@ static int __devinit virtcons_probe(struct virtio_device *vdev)
853 portdev->vdev = vdev; 900 portdev->vdev = vdev;
854 vdev->priv = portdev; 901 vdev->priv = portdev;
855 902
903 spin_lock_irq(&pdrvdata_lock);
904 portdev->drv_index = pdrvdata.index++;
905 spin_unlock_irq(&pdrvdata_lock);
906
907 portdev->chr_major = register_chrdev(0, "virtio-portsdev",
908 &portdev_fops);
909 if (portdev->chr_major < 0) {
910 dev_err(&vdev->dev,
911 "Error %d registering chrdev for device %u\n",
912 portdev->chr_major, portdev->drv_index);
913 err = portdev->chr_major;
914 goto free;
915 }
916
856 multiport = false; 917 multiport = false;
857 portdev->config.nr_ports = 1; 918 portdev->config.nr_ports = 1;
858 portdev->config.max_nr_ports = 1; 919 portdev->config.max_nr_ports = 1;
@@ -885,7 +946,7 @@ static int __devinit virtcons_probe(struct virtio_device *vdev)
885 err = init_vqs(portdev); 946 err = init_vqs(portdev);
886 if (err < 0) { 947 if (err < 0) {
887 dev_err(&vdev->dev, "Error %d initializing vqs\n", err); 948 dev_err(&vdev->dev, "Error %d initializing vqs\n", err);
888 goto free; 949 goto free_chrdev;
889 } 950 }
890 951
891 spin_lock_init(&portdev->ports_lock); 952 spin_lock_init(&portdev->ports_lock);
@@ -905,10 +966,8 @@ static int __devinit virtcons_probe(struct virtio_device *vdev)
905 early_put_chars = NULL; 966 early_put_chars = NULL;
906 return 0; 967 return 0;
907 968
908free_vqs: 969free_chrdev:
909 vdev->config->del_vqs(vdev); 970 unregister_chrdev(portdev->chr_major, "virtio-portsdev");
910 kfree(portdev->in_vqs);
911 kfree(portdev->out_vqs);
912free: 971free:
913 kfree(portdev); 972 kfree(portdev);
914fail: 973fail:
@@ -937,6 +996,14 @@ static struct virtio_driver virtio_console = {
937 996
938static int __init init(void) 997static int __init init(void)
939{ 998{
999 int err;
1000
1001 pdrvdata.class = class_create(THIS_MODULE, "virtio-ports");
1002 if (IS_ERR(pdrvdata.class)) {
1003 err = PTR_ERR(pdrvdata.class);
1004 pr_err("Error %d creating virtio-ports class\n", err);
1005 return err;
1006 }
940 INIT_LIST_HEAD(&pdrvdata.consoles); 1007 INIT_LIST_HEAD(&pdrvdata.consoles);
941 1008
942 return register_virtio_driver(&virtio_console); 1009 return register_virtio_driver(&virtio_console);