aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/virtio_console.c
diff options
context:
space:
mode:
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);