@@ -260,15 +260,58 @@ static int vfio_intx_enable(struct vfio_pci_core_device *vdev)
return 0;
}
+static void vfio_intx_free_interrupt(struct vfio_pci_core_device *vdev,
+ struct vfio_pci_irq_ctx *ctx,
+ unsigned int vector)
+{
+ struct pci_dev *pdev = vdev->pdev;
+
+ free_irq(pdev->irq, vdev);
+}
+
+static int vfio_intx_request_interrupt(struct vfio_pci_core_device *vdev,
+ struct vfio_pci_irq_ctx *ctx,
+ unsigned int vector, unsigned int index)
+{
+ unsigned long irqflags = IRQF_SHARED;
+ struct pci_dev *pdev = vdev->pdev;
+ unsigned long flags;
+ int ret;
+
+ if (!vdev->pci_2_3)
+ irqflags = 0;
+
+ ret = request_irq(pdev->irq, vfio_intx_handler, irqflags,
+ ctx->name, vdev);
+ if (ret)
+ return ret;
+
+ /*
+ * INTx disable will stick across the new irq setup,
+ * disable_irq won't.
+ */
+ spin_lock_irqsave(&vdev->irqlock, flags);
+ if (!vdev->pci_2_3 && ctx->masked)
+ disable_irq_nosync(pdev->irq);
+ spin_unlock_irqrestore(&vdev->irqlock, flags);
+
+ return 0;
+}
+
+static char *vfio_intx_device_name(struct vfio_pci_core_device *vdev,
+ unsigned int vector, unsigned int index)
+{
+ struct pci_dev *pdev = vdev->pdev;
+
+ return kasprintf(GFP_KERNEL_ACCOUNT, "vfio-intx(%s)", pci_name(pdev));
+}
+
static int vfio_intx_set_signal(struct vfio_pci_core_device *vdev,
unsigned int vector, int fd,
unsigned int index)
{
- struct pci_dev *pdev = vdev->pdev;
- unsigned long irqflags = IRQF_SHARED;
struct vfio_pci_irq_ctx *ctx;
struct eventfd_ctx *trigger;
- unsigned long flags;
int ret;
ctx = vfio_irq_ctx_get(vdev, 0);
@@ -276,7 +319,7 @@ static int vfio_intx_set_signal(struct vfio_pci_core_device *vdev,
return -EINVAL;
if (ctx->trigger) {
- free_irq(pdev->irq, vdev);
+ vfio_intx_free_interrupt(vdev, ctx, vector);
kfree(ctx->name);
eventfd_ctx_put(ctx->trigger);
ctx->trigger = NULL;
@@ -285,8 +328,7 @@ static int vfio_intx_set_signal(struct vfio_pci_core_device *vdev,
if (fd < 0) /* Disable only */
return 0;
- ctx->name = kasprintf(GFP_KERNEL_ACCOUNT, "vfio-intx(%s)",
- pci_name(pdev));
+ ctx->name = vfio_intx_device_name(vdev, vector, index);
if (!ctx->name)
return -ENOMEM;
@@ -298,11 +340,7 @@ static int vfio_intx_set_signal(struct vfio_pci_core_device *vdev,
ctx->trigger = trigger;
- if (!vdev->pci_2_3)
- irqflags = 0;
-
- ret = request_irq(pdev->irq, vfio_intx_handler,
- irqflags, ctx->name, vdev);
+ ret = vfio_intx_request_interrupt(vdev, ctx, vector, index);
if (ret) {
ctx->trigger = NULL;
kfree(ctx->name);
@@ -310,15 +348,6 @@ static int vfio_intx_set_signal(struct vfio_pci_core_device *vdev,
return ret;
}
- /*
- * INTx disable will stick across the new irq setup,
- * disable_irq won't.
- */
- spin_lock_irqsave(&vdev->irqlock, flags);
- if (!vdev->pci_2_3 && ctx->masked)
- disable_irq_nosync(pdev->irq);
- spin_unlock_irqrestore(&vdev->irqlock, flags);
-
return 0;
}
vfio_intx_set_signal() and vfio_msi_set_vector_signal() use the same code flow for INTx, MSI, and MSI-X interrupt management. Extract the INTx specific code from vfio_intx_set_signal() to leave behind the same flow as vfio_msi_set_vector_signal(), ready for sharing. Signed-off-by: Reinette Chatre <reinette.chatre@intel.com> --- drivers/vfio/pci/vfio_pci_intrs.c | 69 ++++++++++++++++++++++--------- 1 file changed, 49 insertions(+), 20 deletions(-)