aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/virtio_console.c
diff options
context:
space:
mode:
authorAmit Shah <amit.shah@redhat.com>2009-12-21 11:06:04 -0500
committerRusty Russell <rusty@rustcorp.com.au>2010-02-23 22:52:53 -0500
commitfb08bd274df61967f40d49c4625fe6ed75a69ab5 (patch)
tree911fa24e1b916ad70cff10feeed17bba1de037b1 /drivers/char/virtio_console.c
parentb766ceed5bbf04ae153389f5a15f53b9b6106a35 (diff)
virtio: console: Associate each port with a char device
The char device will be used as an interface by applications on the guest to communicate with apps on the host. The devices created are placed in /dev/vportNpn where N is the virtio-console device number and n is the port number for that device. One dynamic major device number is allocated for each device and minor numbers are allocated for the ports contained within that device. The file operation for the char devs will be added in the following commits. 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.c81
1 files changed, 74 insertions, 7 deletions
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);