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. The file operation for the char devs will be added in the following commits. Signed-off-by: Amit Shah <amit.shah@xxxxxxxxxx> --- drivers/char/virtio_console.c | 76 +++++++++++++++++++++++++++++++++++++++-- 1 files changed, 73 insertions(+), 3 deletions(-) diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index a26781b..56b7cfa 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c @@ -16,6 +16,8 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include <linux/cdev.h> +#include <linux/device.h> #include <linux/err.h> #include <linux/init.h> #include <linux/list.h> @@ -34,6 +36,12 @@ * across multiple devices and multiple ports per device. */ struct ports_driver_data { + /* Used for registering chardevs */ + struct class *class; + + /* Number of devices this driver is handling */ + unsigned int index; + /* * This is used to keep track of the number of hvc consoles * spawned by this driver. This number is given as the first @@ -100,6 +108,12 @@ struct ports_device { /* The current config space is stored here */ struct virtio_console_config config; + + /* Used for numbering devices for sysfs and debugfs */ + unsigned int drv_index; + + /* Major number for this device. Ports will be created as minors. */ + int chr_major; }; /* This struct holds individual buffers received for each port */ @@ -132,6 +146,10 @@ struct port { */ spinlock_t readbuf_list_lock; + /* Each port associates with a separate char device */ + struct cdev cdev; + struct device *dev; + /* * The entries in this struct will be valid if this port is * hooked up to an hvc console @@ -703,6 +721,7 @@ static void tx_intr(struct virtqueue *vq) static int __devinit add_port(struct ports_device *portdev, u32 id) { struct port *port; + dev_t devt; int err; err = -ENOMEM; @@ -713,6 +732,25 @@ static int __devinit add_port(struct ports_device *portdev, u32 id) port->portdev = portdev; port->id = id; + cdev_init(&port->cdev, NULL); + + devt = MKDEV(portdev->chr_major, id); + err = cdev_add(&port->cdev, devt, 1); + if (err < 0) { + dev_err(&port->portdev->vdev->dev, + "error %d adding cdev for port %u\n", err, id); + goto free_port; + } + port->dev = device_create(pdrvdata.class, &port->portdev->vdev->dev, + devt, port, "vport%up%u", + port->portdev->drv_index, id); + if (IS_ERR(port->dev)) { + err = PTR_ERR(port->dev); + dev_err(&port->portdev->vdev->dev, + "error %d creating device for port %u\n", + err, id); + goto free_cdev; + } spin_lock_init(&port->readbuf_list_lock); INIT_LIST_HEAD(&port->readbuf_head); @@ -722,7 +760,7 @@ static int __devinit add_port(struct ports_device *portdev, u32 id) if (!use_multiport(port->portdev)) { err = init_port_console(port); if (err) - goto free; + goto free_device; } spin_lock_irq(&portdev->ports_list_lock); list_add_tail(&port->list, &port->portdev->ports_head); @@ -737,12 +775,21 @@ static int __devinit add_port(struct ports_device *portdev, u32 id) send_control_msg(port, VIRTIO_CONSOLE_PORT_READY, 1); return 0; -free: + +free_device: + device_destroy(pdrvdata.class, port->dev->devt); +free_cdev: + cdev_del(&port->cdev); +free_port: kfree(port); fail: return err; } +static struct file_operations portdev_fops = { + .owner = THIS_MODULE, +}; + /* * Once we're further in boot, we get probed like any other virtio * device. @@ -770,6 +817,18 @@ static int __devinit virtcons_probe(struct virtio_device *vdev) portdev->vdev = vdev; vdev->priv = portdev; + spin_lock_irq(&pdrvdata_lock); + portdev->drv_index = pdrvdata.index++; + spin_unlock_irq(&pdrvdata_lock); + + portdev->chr_major = register_chrdev(0, "virtio-portsdev", + &portdev_fops); + if (portdev->chr_major < 0) { + dev_err(&vdev->dev, + "error %d registering chrdev for device %u\n", + portdev->chr_major, portdev->drv_index); + goto free; + } multiport = false; if (virtio_has_feature(vdev, VIRTIO_CONSOLE_F_MULTIPORT)) { multiport = true; @@ -785,7 +844,7 @@ static int __devinit virtcons_probe(struct virtio_device *vdev) /* Find the queues. */ err = vdev->config->find_vqs(vdev, 2, vqs, callbacks, names); if (err) - goto free; + goto free_chrdev; portdev->in_vq = vqs[0]; portdev->out_vq = vqs[1]; @@ -812,6 +871,8 @@ static int __devinit virtcons_probe(struct virtio_device *vdev) early_put_chars = NULL; return 0; +free_chrdev: + unregister_chrdev(portdev->chr_major, "virtio-portsdev"); free: kfree(portdev); fail: @@ -840,7 +901,16 @@ static struct virtio_driver virtio_console = { static int __init init(void) { + int err; + + pdrvdata.class = class_create(THIS_MODULE, "virtio-ports"); + if (IS_ERR(pdrvdata.class)) { + err = PTR_ERR(pdrvdata.class); + pr_err("Error %d creating virtio-ports class\n", err); + return err; + } INIT_LIST_HEAD(&pdrvdata.consoles); + return register_virtio_driver(&virtio_console); } module_init(init); -- 1.6.2.5 _______________________________________________ Virtualization mailing list Virtualization@xxxxxxxxxxxxxxxxxxxxxxxxxx https://lists.linux-foundation.org/mailman/listinfo/virtualization