Skip to content

Commit

Permalink
lguest: Make sure interrupt is allocated ok by lguest_setup_irq
Browse files Browse the repository at this point in the history
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)
  • Loading branch information
psomas authored and rustyrussell committed Jan 12, 2012
1 parent 07fe997 commit b6c96c0
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 11 deletions.
21 changes: 13 additions & 8 deletions arch/x86/lguest/boot.c
Expand Up @@ -856,18 +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.
*
* FIXME: irq_alloc_desc_at() can fail due to lack of memory, we should
* pass that up!
* 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.
*/
void lguest_setup_irq(unsigned int irq)
int lguest_setup_irq(unsigned int irq)
{
irq_alloc_desc_at(irq, 0);
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 0;
}

/*
Expand Down
10 changes: 7 additions & 3 deletions drivers/lguest/lguest_device.c
Expand Up @@ -241,7 +241,7 @@ static void lg_notify(struct virtqueue *vq)
}

/* An extern declaration inside a C file is bad form. Don't do it. */
extern void lguest_setup_irq(unsigned int irq);
extern int lguest_setup_irq(unsigned int irq);

/*
* This routine finds the Nth virtqueue described in the configuration of
Expand Down Expand Up @@ -304,7 +304,9 @@ static struct virtqueue *lg_find_vq(struct virtio_device *vdev,
}

/* Make sure the interrupt is allocated. */
lguest_setup_irq(lvq->config.irq);
err = lguest_setup_irq(lvq->config.irq);
if (err)
goto destroy_vring;

/*
* Tell the interrupt for this virtqueue to go to the virtio_ring
Expand All @@ -317,7 +319,7 @@ static struct virtqueue *lg_find_vq(struct virtio_device *vdev,
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
Expand All @@ -326,6 +328,8 @@ static struct virtqueue *lg_find_vq(struct virtio_device *vdev,
vq->priv = lvq;
return vq;

free_desc:
irq_free_desc(lvq->config.irq);
destroy_vring:
vring_del_virtqueue(vq);
unmap:
Expand Down

0 comments on commit b6c96c0

Please sign in to comment.