Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b6c96c02 authored by Stratos Psomadakis's avatar Stratos Psomadakis Committed by Rusty Russell
Browse files

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: default avatarStratos Psomadakis <psomas@cslab.ece.ntua.gr>
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> (cleanups and commentry)
parent 07fe9977
Loading
Loading
Loading
Loading
+13 −8
Original line number Diff line number Diff line
@@ -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;
}

/*
+7 −3
Original line number Diff line number Diff line
@@ -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: