[11/17] vfio/pci: Perform MSI/MSI-X interrupt management via callbacks

Message ID 4e04371e86722f8e2d867fe813a67c10f48222af.1706849424.git.reinette.chatre@intel.com
State New
Headers
Series vfio/pci: Remove duplicate code and logic from VFIO PCI interrupt management |

Commit Message

Reinette Chatre Feb. 2, 2024, 4:57 a.m. UTC
  vfio_msi_set_vector_signal() is specific to MSI and MSI-X interrupt
management but its flow is the same as vfio_intx_set_signal() that
manages the INTx interrupts.

Replace the MSI and MSI-X specific calls with callbacks in preparation
for vfio_msi_set_vector_signal() to manage INTx interrupts also.

In preparation for support of INTx only the IRQ bypass code is
made optional.

Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
---
Note to maintainers:
This change resembles "vfio/pci: Replace backend specific calls with
callbacks" that formed part of the IMS submission, but is not
specific to IMS.
https://lore.kernel.org/lkml/cover.1696609476.git.reinette.chatre@intel.com

 drivers/vfio/pci/vfio_pci_intrs.c | 44 +++++++++++++++++++++++++++----
 1 file changed, 39 insertions(+), 5 deletions(-)
  

Patch

diff --git a/drivers/vfio/pci/vfio_pci_intrs.c b/drivers/vfio/pci/vfio_pci_intrs.c
index 6eef4e2d7c13..07dc388c4513 100644
--- a/drivers/vfio/pci/vfio_pci_intrs.c
+++ b/drivers/vfio/pci/vfio_pci_intrs.c
@@ -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;