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)
This commit is contained in:
parent
07fe9977b6
commit
b6c96c0214
|
@ -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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
|
Loading…
Reference in New Issue