[Lguest] [PATCH] lguest: Make sure the interrupt is allocated correctly by

Rusty Russell rusty at rustcorp.com.au
Tue Dec 20 13:53:10 EST 2011


On Fri, 24 Jun 2011 10:54:30 +0300, Stratos Psomadakis <psomas at ece.ntua.gr> wrote:
> From: Stratos Psomadakis <psomas at cslab.ece.ntua.gr>
> 
> 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 at cslab.ece.ntua.gr>

Oops, this got placed on my TODO list and then lost.  Sorry.

It will go into the next merge window.

Here is the cleanup I applied on top of your patch, after figuring out
what's going on.

1) Don't mention CONFIG_SPARSE_IRQ, it's always on for x86 now.
2) Note that we explictly ignore -EEXIST, since the boot code reserves
   low irqs.
3) Make lguest_setup_irq() return an error only on *unexpected* error.
4) Correct undo path.

Thanks!
Rusty.

diff --git a/arch/x86/lguest/boot.c b/arch/x86/lguest/boot.c
--- a/arch/x86/lguest/boot.c
+++ b/arch/x86/lguest/boot.c
@@ -856,20 +856,23 @@ static void __init lguest_init_IRQ(void)
 }
 
 /*
- * With CONFIG_SPARSE_IRQ, interrupt descriptors are allocated as-needed, so
- * rather than set them in lguest_init_IRQ we are called here every time an
- * lguest device needs an interrupt.
+ * Interrupt descriptors are allocated as-needed, but low-numbered ones are
+ * reserved by the generic x86 code.  So we ignore irq_alloc_desc_at if it
+ * tells us the irq is already used: other errors (ie. ENOMEM) we take
+ * seriously.
  */
 int lguest_setup_irq(unsigned int irq)
 {
 	int err;
 
+	/* Returns -ve error or vector number. */
 	err = irq_alloc_desc_at(irq, 0);
+	if (err < 0 && err != -EEXIST)
+		return err;
 
 	irq_set_chip_and_handler_name(irq, &lguest_irq_controller,
 				      handle_level_irq, "level");
-
-	return err;
+	return 0;
 }
 
 /*
diff --git a/drivers/lguest/lguest_device.c b/drivers/lguest/lguest_device.c
--- a/drivers/lguest/lguest_device.c
+++ b/drivers/lguest/lguest_device.c
@@ -305,7 +305,7 @@ static struct virtqueue *lg_find_vq(stru
 
 	/* Make sure the interrupt is allocated. */
 	err = lguest_setup_irq(lvq->config.irq);
-	if (err == -ENOMEM)
+	if (err)
 		goto destroy_vring;
 
 	/*
@@ -319,7 +319,7 @@ static struct virtqueue *lg_find_vq(stru
 	err = request_irq(lvq->config.irq, vring_interrupt, IRQF_SHARED,
 			  dev_name(&vdev->dev), vq);
 	if (err)
-		goto destroy_vring;
+		goto free_desc;
 
 	/*
 	 * Last of all we hook up our 'struct lguest_vq_info" to the
@@ -328,6 +328,8 @@ static struct virtqueue *lg_find_vq(stru
 	vq->priv = lvq;
 	return vq;
 
+free_desc:
+	irq_free_desc(lvq->config.irq);
 destroy_vring:
 	vring_del_virtqueue(vq);
 unmap:


More information about the Lguest mailing list