|
@@ -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]);
|