diff options
Diffstat (limited to 'drivers/char')
-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) | |||
1057 | resize_console(find_port_by_id(portdev, 0)); | 1057 | resize_console(find_port_by_id(portdev, 0)); |
1058 | } | 1058 | } |
1059 | 1059 | ||
1060 | static void fill_queue(struct virtqueue *vq, spinlock_t *lock) | 1060 | static unsigned int fill_queue(struct virtqueue *vq, spinlock_t *lock) |
1061 | { | 1061 | { |
1062 | struct port_buffer *buf; | 1062 | struct port_buffer *buf; |
1063 | int ret; | 1063 | unsigned int ret; |
1064 | int err; | ||
1064 | 1065 | ||
1066 | ret = 0; | ||
1065 | do { | 1067 | do { |
1066 | buf = alloc_buf(PAGE_SIZE); | 1068 | buf = alloc_buf(PAGE_SIZE); |
1067 | if (!buf) | 1069 | if (!buf) |
1068 | break; | 1070 | break; |
1069 | 1071 | ||
1070 | spin_lock_irq(lock); | 1072 | spin_lock_irq(lock); |
1071 | ret = add_inbuf(vq, buf); | 1073 | err = add_inbuf(vq, buf); |
1072 | if (ret < 0) { | 1074 | if (err < 0) { |
1073 | spin_unlock_irq(lock); | 1075 | spin_unlock_irq(lock); |
1074 | free_buf(buf); | 1076 | free_buf(buf); |
1075 | break; | 1077 | break; |
1076 | } | 1078 | } |
1079 | ret++; | ||
1077 | spin_unlock_irq(lock); | 1080 | spin_unlock_irq(lock); |
1078 | } while (ret > 0); | 1081 | } while (err > 0); |
1082 | |||
1083 | return ret; | ||
1079 | } | 1084 | } |
1080 | 1085 | ||
1081 | static int add_port(struct ports_device *portdev, u32 id) | 1086 | static int add_port(struct ports_device *portdev, u32 id) |
@@ -1430,7 +1435,13 @@ static int __devinit virtcons_probe(struct virtio_device *vdev) | |||
1430 | INIT_WORK(&portdev->control_work, &control_work_handler); | 1435 | INIT_WORK(&portdev->control_work, &control_work_handler); |
1431 | INIT_WORK(&portdev->config_work, &config_work_handler); | 1436 | INIT_WORK(&portdev->config_work, &config_work_handler); |
1432 | 1437 | ||
1433 | fill_queue(portdev->c_ivq, &portdev->cvq_lock); | 1438 | err = fill_queue(portdev->c_ivq, &portdev->cvq_lock); |
1439 | if (!err) { | ||
1440 | dev_err(&vdev->dev, | ||
1441 | "Error allocating buffers for control queue\n"); | ||
1442 | err = -ENOMEM; | ||
1443 | goto free_vqs; | ||
1444 | } | ||
1434 | } | 1445 | } |
1435 | 1446 | ||
1436 | for (i = 0; i < portdev->config.nr_ports; i++) | 1447 | for (i = 0; i < portdev->config.nr_ports; i++) |
@@ -1440,6 +1451,10 @@ static int __devinit virtcons_probe(struct virtio_device *vdev) | |||
1440 | early_put_chars = NULL; | 1451 | early_put_chars = NULL; |
1441 | return 0; | 1452 | return 0; |
1442 | 1453 | ||
1454 | free_vqs: | ||
1455 | vdev->config->del_vqs(vdev); | ||
1456 | kfree(portdev->in_vqs); | ||
1457 | kfree(portdev->out_vqs); | ||
1443 | free_chrdev: | 1458 | free_chrdev: |
1444 | unregister_chrdev(portdev->chr_major, "virtio-portsdev"); | 1459 | unregister_chrdev(portdev->chr_major, "virtio-portsdev"); |
1445 | free: | 1460 | free: |