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

Commit a7fa7c77 authored by Antonios Motakis's avatar Antonios Motakis Committed by Alex Williamson
Browse files

vfio/platform: implement IRQ masking/unmasking via an eventfd



With this patch the VFIO user will be able to set an eventfd that can be
used in order to mask and unmask IRQs of platform devices.

Signed-off-by: default avatarAntonios Motakis <a.motakis@virtualopensystems.com>
Signed-off-by: default avatarBaptiste Reynal <b.reynal@virtualopensystems.com>
Reviewed-by: default avatarEric Auger <eric.auger@linaro.org>
Tested-by: default avatarEric Auger <eric.auger@linaro.org>
Signed-off-by: default avatarAlex Williamson <alex.williamson@redhat.com>
parent 42ac9bd1
Loading
Loading
Loading
Loading
+43 −4
Original line number Diff line number Diff line
@@ -37,6 +37,15 @@ static void vfio_platform_mask(struct vfio_platform_irq *irq_ctx)
	spin_unlock_irqrestore(&irq_ctx->lock, flags);
}

static int vfio_platform_mask_handler(void *opaque, void *unused)
{
	struct vfio_platform_irq *irq_ctx = opaque;

	vfio_platform_mask(irq_ctx);

	return 0;
}

static int vfio_platform_set_irq_mask(struct vfio_platform_device *vdev,
				      unsigned index, unsigned start,
				      unsigned count, uint32_t flags,
@@ -48,8 +57,18 @@ static int vfio_platform_set_irq_mask(struct vfio_platform_device *vdev,
	if (!(vdev->irqs[index].flags & VFIO_IRQ_INFO_MASKABLE))
		return -EINVAL;

	if (flags & VFIO_IRQ_SET_DATA_EVENTFD)
		return -EINVAL; /* not implemented yet */
	if (flags & VFIO_IRQ_SET_DATA_EVENTFD) {
		int32_t fd = *(int32_t *)data;

		if (fd >= 0)
			return vfio_virqfd_enable((void *) &vdev->irqs[index],
						  vfio_platform_mask_handler,
						  NULL, NULL,
						  &vdev->irqs[index].mask, fd);

		vfio_virqfd_disable(&vdev->irqs[index].mask);
		return 0;
	}

	if (flags & VFIO_IRQ_SET_DATA_NONE) {
		vfio_platform_mask(&vdev->irqs[index]);
@@ -78,6 +97,15 @@ static void vfio_platform_unmask(struct vfio_platform_irq *irq_ctx)
	spin_unlock_irqrestore(&irq_ctx->lock, flags);
}

static int vfio_platform_unmask_handler(void *opaque, void *unused)
{
	struct vfio_platform_irq *irq_ctx = opaque;

	vfio_platform_unmask(irq_ctx);

	return 0;
}

static int vfio_platform_set_irq_unmask(struct vfio_platform_device *vdev,
					unsigned index, unsigned start,
					unsigned count, uint32_t flags,
@@ -89,8 +117,19 @@ static int vfio_platform_set_irq_unmask(struct vfio_platform_device *vdev,
	if (!(vdev->irqs[index].flags & VFIO_IRQ_INFO_MASKABLE))
		return -EINVAL;

	if (flags & VFIO_IRQ_SET_DATA_EVENTFD)
		return -EINVAL; /* not implemented yet */
	if (flags & VFIO_IRQ_SET_DATA_EVENTFD) {
		int32_t fd = *(int32_t *)data;

		if (fd >= 0)
			return vfio_virqfd_enable((void *) &vdev->irqs[index],
						  vfio_platform_unmask_handler,
						  NULL, NULL,
						  &vdev->irqs[index].unmask,
						  fd);

		vfio_virqfd_disable(&vdev->irqs[index].unmask);
		return 0;
	}

	if (flags & VFIO_IRQ_SET_DATA_NONE) {
		vfio_platform_unmask(&vdev->irqs[index]);
+2 −0
Original line number Diff line number Diff line
@@ -35,6 +35,8 @@ struct vfio_platform_irq {
	struct eventfd_ctx	*trigger;
	bool			masked;
	spinlock_t		lock;
	struct virqfd		*unmask;
	struct virqfd		*mask;
};

struct vfio_platform_region {