aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/virtio_console.c
diff options
context:
space:
mode:
authorAmit Shah <amit.shah@redhat.com>2010-02-12 00:02:17 -0500
committerRusty Russell <rusty@rustcorp.com.au>2010-02-23 22:53:04 -0500
commit22a29eacd2a17f22c8260a8106a4e36bae7fb6ea (patch)
tree1b07a3c9eb02b696f686bb63e82dd740877187db /drivers/char/virtio_console.c
parent7177876fea8306a6f49400d11f5913bf9b3b5e5f (diff)
virtio: console: Error out if we can't allocate buffers for control queue
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>
Diffstat (limited to 'drivers/char/virtio_console.c')
-rw-r--r--drivers/char/virtio_console.c27
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
1060static void fill_queue(struct virtqueue *vq, spinlock_t *lock) 1060static 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
1081static int add_port(struct ports_device *portdev, u32 id) 1086static 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
1454free_vqs:
1455 vdev->config->del_vqs(vdev);
1456 kfree(portdev->in_vqs);
1457 kfree(portdev->out_vqs);
1443free_chrdev: 1458free_chrdev:
1444 unregister_chrdev(portdev->chr_major, "virtio-portsdev"); 1459 unregister_chrdev(portdev->chr_major, "virtio-portsdev");
1445free: 1460free: