virtio: console: Move code around for future patches
We're going to use add_port() from handle_control_message() in the next patch. Move the add_port() and fill_queue(), which depends on it, above handle_control_message() to avoid forward declarations. Signed-off-by: Amit Shah <amit.shah@redhat.com> Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
@@ -855,6 +855,139 @@ static const struct file_operations port_debugfs_ops = {
|
|||||||
.read = debugfs_read,
|
.read = debugfs_read,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static unsigned int fill_queue(struct virtqueue *vq, spinlock_t *lock)
|
||||||
|
{
|
||||||
|
struct port_buffer *buf;
|
||||||
|
unsigned int nr_added_bufs;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
nr_added_bufs = 0;
|
||||||
|
do {
|
||||||
|
buf = alloc_buf(PAGE_SIZE);
|
||||||
|
if (!buf)
|
||||||
|
break;
|
||||||
|
|
||||||
|
spin_lock_irq(lock);
|
||||||
|
ret = add_inbuf(vq, buf);
|
||||||
|
if (ret < 0) {
|
||||||
|
spin_unlock_irq(lock);
|
||||||
|
free_buf(buf);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
nr_added_bufs++;
|
||||||
|
spin_unlock_irq(lock);
|
||||||
|
} while (ret > 0);
|
||||||
|
|
||||||
|
return nr_added_bufs;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int add_port(struct ports_device *portdev, u32 id)
|
||||||
|
{
|
||||||
|
char debugfs_name[16];
|
||||||
|
struct port *port;
|
||||||
|
struct port_buffer *buf;
|
||||||
|
dev_t devt;
|
||||||
|
unsigned int nr_added_bufs;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
port = kmalloc(sizeof(*port), GFP_KERNEL);
|
||||||
|
if (!port) {
|
||||||
|
err = -ENOMEM;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
port->portdev = portdev;
|
||||||
|
port->id = id;
|
||||||
|
|
||||||
|
port->name = NULL;
|
||||||
|
port->inbuf = NULL;
|
||||||
|
port->cons.hvc = NULL;
|
||||||
|
|
||||||
|
port->host_connected = port->guest_connected = false;
|
||||||
|
|
||||||
|
port->in_vq = portdev->in_vqs[port->id];
|
||||||
|
port->out_vq = portdev->out_vqs[port->id];
|
||||||
|
|
||||||
|
cdev_init(&port->cdev, &port_fops);
|
||||||
|
|
||||||
|
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->inbuf_lock);
|
||||||
|
init_waitqueue_head(&port->waitqueue);
|
||||||
|
|
||||||
|
/* Fill the in_vq with buffers so the host can send us data. */
|
||||||
|
nr_added_bufs = fill_queue(port->in_vq, &port->inbuf_lock);
|
||||||
|
if (!nr_added_bufs) {
|
||||||
|
dev_err(port->dev, "Error allocating inbufs\n");
|
||||||
|
err = -ENOMEM;
|
||||||
|
goto free_device;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If we're not using multiport support, this has to be a console port
|
||||||
|
*/
|
||||||
|
if (!use_multiport(port->portdev)) {
|
||||||
|
err = init_port_console(port);
|
||||||
|
if (err)
|
||||||
|
goto free_inbufs;
|
||||||
|
}
|
||||||
|
|
||||||
|
spin_lock_irq(&portdev->ports_lock);
|
||||||
|
list_add_tail(&port->list, &port->portdev->ports);
|
||||||
|
spin_unlock_irq(&portdev->ports_lock);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Tell the Host we're set so that it can send us various
|
||||||
|
* configuration parameters for this port (eg, port name,
|
||||||
|
* caching, whether this is a console port, etc.)
|
||||||
|
*/
|
||||||
|
send_control_msg(port, VIRTIO_CONSOLE_PORT_READY, 1);
|
||||||
|
|
||||||
|
if (pdrvdata.debugfs_dir) {
|
||||||
|
/*
|
||||||
|
* Finally, create the debugfs file that we can use to
|
||||||
|
* inspect a port's state at any time
|
||||||
|
*/
|
||||||
|
sprintf(debugfs_name, "vport%up%u",
|
||||||
|
port->portdev->drv_index, id);
|
||||||
|
port->debugfs_file = debugfs_create_file(debugfs_name, 0444,
|
||||||
|
pdrvdata.debugfs_dir,
|
||||||
|
port,
|
||||||
|
&port_debugfs_ops);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
free_inbufs:
|
||||||
|
while ((buf = virtqueue_detach_unused_buf(port->in_vq)))
|
||||||
|
free_buf(buf);
|
||||||
|
free_device:
|
||||||
|
device_destroy(pdrvdata.class, port->dev->devt);
|
||||||
|
free_cdev:
|
||||||
|
cdev_del(&port->cdev);
|
||||||
|
free_port:
|
||||||
|
kfree(port);
|
||||||
|
fail:
|
||||||
|
/* The host might want to notify management sw about port add failure */
|
||||||
|
send_control_msg(port, VIRTIO_CONSOLE_PORT_READY, 0);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
/* Remove all port-specific data. */
|
/* Remove all port-specific data. */
|
||||||
static int remove_port(struct port *port)
|
static int remove_port(struct port *port)
|
||||||
{
|
{
|
||||||
@@ -1093,139 +1226,6 @@ static void config_intr(struct virtio_device *vdev)
|
|||||||
resize_console(find_port_by_id(portdev, 0));
|
resize_console(find_port_by_id(portdev, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int fill_queue(struct virtqueue *vq, spinlock_t *lock)
|
|
||||||
{
|
|
||||||
struct port_buffer *buf;
|
|
||||||
unsigned int nr_added_bufs;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
nr_added_bufs = 0;
|
|
||||||
do {
|
|
||||||
buf = alloc_buf(PAGE_SIZE);
|
|
||||||
if (!buf)
|
|
||||||
break;
|
|
||||||
|
|
||||||
spin_lock_irq(lock);
|
|
||||||
ret = add_inbuf(vq, buf);
|
|
||||||
if (ret < 0) {
|
|
||||||
spin_unlock_irq(lock);
|
|
||||||
free_buf(buf);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
nr_added_bufs++;
|
|
||||||
spin_unlock_irq(lock);
|
|
||||||
} while (ret > 0);
|
|
||||||
|
|
||||||
return nr_added_bufs;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int add_port(struct ports_device *portdev, u32 id)
|
|
||||||
{
|
|
||||||
char debugfs_name[16];
|
|
||||||
struct port *port;
|
|
||||||
struct port_buffer *buf;
|
|
||||||
dev_t devt;
|
|
||||||
unsigned int nr_added_bufs;
|
|
||||||
int err;
|
|
||||||
|
|
||||||
port = kmalloc(sizeof(*port), GFP_KERNEL);
|
|
||||||
if (!port) {
|
|
||||||
err = -ENOMEM;
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
port->portdev = portdev;
|
|
||||||
port->id = id;
|
|
||||||
|
|
||||||
port->name = NULL;
|
|
||||||
port->inbuf = NULL;
|
|
||||||
port->cons.hvc = NULL;
|
|
||||||
|
|
||||||
port->host_connected = port->guest_connected = false;
|
|
||||||
|
|
||||||
port->in_vq = portdev->in_vqs[port->id];
|
|
||||||
port->out_vq = portdev->out_vqs[port->id];
|
|
||||||
|
|
||||||
cdev_init(&port->cdev, &port_fops);
|
|
||||||
|
|
||||||
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->inbuf_lock);
|
|
||||||
init_waitqueue_head(&port->waitqueue);
|
|
||||||
|
|
||||||
/* Fill the in_vq with buffers so the host can send us data. */
|
|
||||||
nr_added_bufs = fill_queue(port->in_vq, &port->inbuf_lock);
|
|
||||||
if (!nr_added_bufs) {
|
|
||||||
dev_err(port->dev, "Error allocating inbufs\n");
|
|
||||||
err = -ENOMEM;
|
|
||||||
goto free_device;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If we're not using multiport support, this has to be a console port
|
|
||||||
*/
|
|
||||||
if (!use_multiport(port->portdev)) {
|
|
||||||
err = init_port_console(port);
|
|
||||||
if (err)
|
|
||||||
goto free_inbufs;
|
|
||||||
}
|
|
||||||
|
|
||||||
spin_lock_irq(&portdev->ports_lock);
|
|
||||||
list_add_tail(&port->list, &port->portdev->ports);
|
|
||||||
spin_unlock_irq(&portdev->ports_lock);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Tell the Host we're set so that it can send us various
|
|
||||||
* configuration parameters for this port (eg, port name,
|
|
||||||
* caching, whether this is a console port, etc.)
|
|
||||||
*/
|
|
||||||
send_control_msg(port, VIRTIO_CONSOLE_PORT_READY, 1);
|
|
||||||
|
|
||||||
if (pdrvdata.debugfs_dir) {
|
|
||||||
/*
|
|
||||||
* Finally, create the debugfs file that we can use to
|
|
||||||
* inspect a port's state at any time
|
|
||||||
*/
|
|
||||||
sprintf(debugfs_name, "vport%up%u",
|
|
||||||
port->portdev->drv_index, id);
|
|
||||||
port->debugfs_file = debugfs_create_file(debugfs_name, 0444,
|
|
||||||
pdrvdata.debugfs_dir,
|
|
||||||
port,
|
|
||||||
&port_debugfs_ops);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
free_inbufs:
|
|
||||||
while ((buf = virtqueue_detach_unused_buf(port->in_vq)))
|
|
||||||
free_buf(buf);
|
|
||||||
free_device:
|
|
||||||
device_destroy(pdrvdata.class, port->dev->devt);
|
|
||||||
free_cdev:
|
|
||||||
cdev_del(&port->cdev);
|
|
||||||
free_port:
|
|
||||||
kfree(port);
|
|
||||||
fail:
|
|
||||||
/* The host might want to notify management sw about port add failure */
|
|
||||||
send_control_msg(port, VIRTIO_CONSOLE_PORT_READY, 0);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int init_vqs(struct ports_device *portdev)
|
static int init_vqs(struct ports_device *portdev)
|
||||||
{
|
{
|
||||||
vq_callback_t **io_callbacks;
|
vq_callback_t **io_callbacks;
|
||||||
|
Reference in New Issue
Block a user