@@ -31,6 +31,21 @@ struct vfio_pci_irq_ctx {
struct irq_bypass_producer producer;
};
+struct vfio_pci_intr_ops {
+ int (*request_interrupt)(struct vfio_pci_core_device *vdev,
+ struct vfio_pci_irq_ctx *ctx,
+ unsigned int vector, unsigned int index);
+ void (*free_interrupt)(struct vfio_pci_core_device *vdev,
+ struct vfio_pci_irq_ctx *ctx,
+ unsigned int vector);
+ char *(*device_name)(struct vfio_pci_core_device *vdev,
+ unsigned int vector, unsigned int index);
+ void (*register_producer)(struct vfio_pci_core_device *vdev,
+ struct vfio_pci_irq_ctx *ctx,
+ unsigned int vector);
+ void (*unregister_producer)(struct vfio_pci_irq_ctx *ctx);
+};
+
static bool irq_is(struct vfio_pci_core_device *vdev, int type)
{
return vdev->irq_type == type;
@@ -525,6 +540,23 @@ static void vfio_msi_unregister_producer(struct vfio_pci_irq_ctx *ctx)
irq_bypass_unregister_producer(&ctx->producer);
}
+static struct vfio_pci_intr_ops intr_ops[] = {
+ [VFIO_PCI_MSI_IRQ_INDEX] = {
+ .request_interrupt = vfio_msi_request_interrupt,
+ .free_interrupt = vfio_msi_free_interrupt,
+ .device_name = vfio_msi_device_name,
+ .register_producer = vfio_msi_register_producer,
+ .unregister_producer = vfio_msi_unregister_producer,
+ },
+ [VFIO_PCI_MSIX_IRQ_INDEX] = {
+ .request_interrupt = vfio_msi_request_interrupt,
+ .free_interrupt = vfio_msi_free_interrupt,
+ .device_name = vfio_msi_device_name,
+ .register_producer = vfio_msi_register_producer,
+ .unregister_producer = vfio_msi_unregister_producer,
+ },
+};
+
static int vfio_msi_set_vector_signal(struct vfio_pci_core_device *vdev,
unsigned int vector, int fd,
unsigned int index)
@@ -536,8 +568,9 @@ static int vfio_msi_set_vector_signal(struct vfio_pci_core_device *vdev,
ctx = vfio_irq_ctx_get(vdev, vector);
if (ctx && ctx->trigger) {
- vfio_msi_unregister_producer(ctx);
- vfio_msi_free_interrupt(vdev, ctx, vector);
+ if (intr_ops[index].unregister_producer)
+ intr_ops[index].unregister_producer(ctx);
+ intr_ops[index].free_interrupt(vdev, ctx, vector);
kfree(ctx->name);
ctx->name = NULL;
eventfd_ctx_put(ctx->trigger);
@@ -554,7 +587,7 @@ static int vfio_msi_set_vector_signal(struct vfio_pci_core_device *vdev,
return -ENOMEM;
}
- ctx->name = vfio_msi_device_name(vdev, vector, index);
+ ctx->name = intr_ops[index].device_name(vdev, vector, index);
if (!ctx->name)
return -ENOMEM;
@@ -566,11 +599,12 @@ static int vfio_msi_set_vector_signal(struct vfio_pci_core_device *vdev,
ctx->trigger = trigger;
- ret = vfio_msi_request_interrupt(vdev, ctx, vector, index);
+ ret = intr_ops[index].request_interrupt(vdev, ctx, vector, index);
if (ret)
goto out_put_eventfd_ctx;
- vfio_msi_register_producer(vdev, ctx, vector);
+ if (intr_ops[index].register_producer)
+ intr_ops[index].register_producer(vdev, ctx, vector);
return 0;