aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStratos Psomadakis <psomas@cslab.ece.ntua.gr>2012-01-12 00:14:47 -0500
committerRusty Russell <rusty@rustcorp.com.au>2012-01-12 00:14:47 -0500
commitb6c96c0214138186f495e3ee73737c6fc5e4efa2 (patch)
tree991ed5cd8c219543fb32f2b919556d5634859c90
parent07fe9977b6234ede1bd29e10e0323e478860c871 (diff)
lguest: Make sure interrupt is allocated ok by lguest_setup_irq
Make sure the interrupt is allocated correctly by lguest_setup_irq (check the return value of irq_alloc_desc_at for -ENOMEM) Signed-off-by: Stratos Psomadakis <psomas@cslab.ece.ntua.gr> Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> (cleanups and commentry)
-rw-r--r--arch/x86/lguest/boot.c21
-rw-r--r--drivers/lguest/lguest_device.c10
2 files changed, 20 insertions, 11 deletions
diff --git a/arch/x86/lguest/boot.c b/arch/x86/lguest/boot.c
index cf4603ba866f..642d8805bc1b 100644
--- a/arch/x86/lguest/boot.c
+++ b/arch/x86/lguest/boot.c
@@ -856,18 +856,23 @@ static void __init lguest_init_IRQ(void)
856} 856}
857 857
858/* 858/*
859 * With CONFIG_SPARSE_IRQ, interrupt descriptors are allocated as-needed, so 859 * Interrupt descriptors are allocated as-needed, but low-numbered ones are
860 * rather than set them in lguest_init_IRQ we are called here every time an 860 * reserved by the generic x86 code. So we ignore irq_alloc_desc_at if it
861 * lguest device needs an interrupt. 861 * tells us the irq is already used: other errors (ie. ENOMEM) we take
862 * 862 * seriously.
863 * FIXME: irq_alloc_desc_at() can fail due to lack of memory, we should
864 * pass that up!
865 */ 863 */
866void lguest_setup_irq(unsigned int irq) 864int lguest_setup_irq(unsigned int irq)
867{ 865{
868 irq_alloc_desc_at(irq, 0); 866 int err;
867
868 /* Returns -ve error or vector number. */
869 err = irq_alloc_desc_at(irq, 0);
870 if (err < 0 && err != -EEXIST)
871 return err;
872
869 irq_set_chip_and_handler_name(irq, &lguest_irq_controller, 873 irq_set_chip_and_handler_name(irq, &lguest_irq_controller,
870 handle_level_irq, "level"); 874 handle_level_irq, "level");
875 return 0;
871} 876}
872 877
873/* 878/*
diff --git a/drivers/lguest/lguest_device.c b/drivers/lguest/lguest_device.c
index 6a1d6447b864..9e8388efd88e 100644
--- a/drivers/lguest/lguest_device.c
+++ b/drivers/lguest/lguest_device.c
@@ -241,7 +241,7 @@ static void lg_notify(struct virtqueue *vq)
241} 241}
242 242
243/* An extern declaration inside a C file is bad form. Don't do it. */ 243/* An extern declaration inside a C file is bad form. Don't do it. */
244extern void lguest_setup_irq(unsigned int irq); 244extern int lguest_setup_irq(unsigned int irq);
245 245
246/* 246/*
247 * This routine finds the Nth virtqueue described in the configuration of 247 * This routine finds the Nth virtqueue described in the configuration of
@@ -304,7 +304,9 @@ static struct virtqueue *lg_find_vq(struct virtio_device *vdev,
304 } 304 }
305 305
306 /* Make sure the interrupt is allocated. */ 306 /* Make sure the interrupt is allocated. */
307 lguest_setup_irq(lvq->config.irq); 307 err = lguest_setup_irq(lvq->config.irq);
308 if (err)
309 goto destroy_vring;
308 310
309 /* 311 /*
310 * Tell the interrupt for this virtqueue to go to the virtio_ring 312 * Tell the interrupt for this virtqueue to go to the virtio_ring
@@ -317,7 +319,7 @@ static struct virtqueue *lg_find_vq(struct virtio_device *vdev,
317 err = request_irq(lvq->config.irq, vring_interrupt, IRQF_SHARED, 319 err = request_irq(lvq->config.irq, vring_interrupt, IRQF_SHARED,
318 dev_name(&vdev->dev), vq); 320 dev_name(&vdev->dev), vq);
319 if (err) 321 if (err)
320 goto destroy_vring; 322 goto free_desc;
321 323
322 /* 324 /*
323 * Last of all we hook up our 'struct lguest_vq_info" to the 325 * Last of all we hook up our 'struct lguest_vq_info" to the
@@ -326,6 +328,8 @@ static struct virtqueue *lg_find_vq(struct virtio_device *vdev,
326 vq->priv = lvq; 328 vq->priv = lvq;
327 return vq; 329 return vq;
328 330
331free_desc:
332 irq_free_desc(lvq->config.irq);
329destroy_vring: 333destroy_vring:
330 vring_del_virtqueue(vq); 334 vring_del_virtqueue(vq);
331unmap: 335unmap: