diff options
-rw-r--r-- | drivers/char/virtio_console.c | 27 |
1 files changed, 21 insertions, 6 deletions
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index 0057bae2036f..c40703759e26 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c @@ -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) @@ -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++) @@ -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: |