Skip to content

Commit

Permalink
virtio: console: Error out if we can't allocate buffers for control q…
Browse files Browse the repository at this point in the history
…ueue

With MULTIPORT support, the control queue is an integral part of the
functioning of the device. If we can't get any buffers allocated, the
host won't be able to relay important information and the device may not
function as intended.

Ensure 'probe' doesn't succeed until the control queue has at least one
buffer allocated for its ivq.

Signed-off-by: Amit Shah <amit.shah@redhat.com>
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
  • Loading branch information
Amit Shah authored and Rusty Russell committed Feb 24, 2010
1 parent 7177876 commit 22a29ea
Showing 1 changed file with 21 additions and 6 deletions.
27 changes: 21 additions & 6 deletions drivers/char/virtio_console.c
Original file line number Diff line number Diff line change
Expand Up @@ -1057,25 +1057,30 @@ static void config_intr(struct virtio_device *vdev)
resize_console(find_port_by_id(portdev, 0));
}

static void fill_queue(struct virtqueue *vq, spinlock_t *lock)
static unsigned int fill_queue(struct virtqueue *vq, spinlock_t *lock)
{
struct port_buffer *buf;
int ret;
unsigned int ret;
int err;

ret = 0;
do {
buf = alloc_buf(PAGE_SIZE);
if (!buf)
break;

spin_lock_irq(lock);
ret = add_inbuf(vq, buf);
if (ret < 0) {
err = add_inbuf(vq, buf);
if (err < 0) {
spin_unlock_irq(lock);
free_buf(buf);
break;
}
ret++;
spin_unlock_irq(lock);
} while (ret > 0);
} while (err > 0);

return ret;
}

static int add_port(struct ports_device *portdev, u32 id)
Expand Down Expand Up @@ -1430,7 +1435,13 @@ static int __devinit virtcons_probe(struct virtio_device *vdev)
INIT_WORK(&portdev->control_work, &control_work_handler);
INIT_WORK(&portdev->config_work, &config_work_handler);

fill_queue(portdev->c_ivq, &portdev->cvq_lock);
err = fill_queue(portdev->c_ivq, &portdev->cvq_lock);
if (!err) {
dev_err(&vdev->dev,
"Error allocating buffers for control queue\n");
err = -ENOMEM;
goto free_vqs;
}
}

for (i = 0; i < portdev->config.nr_ports; i++)
Expand All @@ -1440,6 +1451,10 @@ static int __devinit virtcons_probe(struct virtio_device *vdev)
early_put_chars = NULL;
return 0;

free_vqs:
vdev->config->del_vqs(vdev);
kfree(portdev->in_vqs);
kfree(portdev->out_vqs);
free_chrdev:
unregister_chrdev(portdev->chr_major, "virtio-portsdev");
free:
Expand Down

0 comments on commit 22a29ea

Please sign in to comment.