[PATCH v4 01/11] drm/xe/irq: refactor irq flows to support also msix

Ilia Levi ilia.levi at intel.com
Thu Jul 25 10:22:03 UTC 2024


From: Dani Liberman <dliberman at habana.ai>

When enabling MSIX, there is no need for HW to aggregate interrupts.
Added a separate MSIX flow that skips unnecessary code in irq init,
reset, and fini.

Signed-off-by: Dani Liberman <dliberman at habana.ai>
---
 drivers/gpu/drm/xe/xe_device.h       |  5 ++
 drivers/gpu/drm/xe/xe_device_types.h |  5 ++
 drivers/gpu/drm/xe/xe_irq.c          | 97 +++++++++++++++++++++-------
 3 files changed, 83 insertions(+), 24 deletions(-)

diff --git a/drivers/gpu/drm/xe/xe_device.h b/drivers/gpu/drm/xe/xe_device.h
index db6cc8d0d6b8..d4c6ca1da8e8 100644
--- a/drivers/gpu/drm/xe/xe_device.h
+++ b/drivers/gpu/drm/xe/xe_device.h
@@ -159,6 +159,11 @@ static inline bool xe_device_has_memirq(struct xe_device *xe)
 	return GRAPHICS_VERx100(xe) >= 1250;
 }
 
+static inline bool xe_device_has_msix(struct xe_device *xe)
+{
+	return xe->irq.msix.enabled;
+}
+
 u32 xe_device_ccs_bytes(struct xe_device *xe, u64 size);
 
 void xe_device_snapshot_print(struct xe_device *xe, struct drm_printer *p);
diff --git a/drivers/gpu/drm/xe/xe_device_types.h b/drivers/gpu/drm/xe/xe_device_types.h
index 5b7292a9a66d..909c83651103 100644
--- a/drivers/gpu/drm/xe/xe_device_types.h
+++ b/drivers/gpu/drm/xe/xe_device_types.h
@@ -313,6 +313,11 @@ struct xe_device {
 
 		/** @irq.enabled: interrupts enabled on this device */
 		bool enabled;
+		/** @irq.msix: irq info for platforms that support MSI-X */
+		struct {
+			/** @irq.msix.enabled: msix interrupts enabled on this device */
+			bool enabled;
+		} msix;
 	} irq;
 
 	/** @ttm: ttm device */
diff --git a/drivers/gpu/drm/xe/xe_irq.c b/drivers/gpu/drm/xe/xe_irq.c
index 5f2c368c35ad..6230e4938004 100644
--- a/drivers/gpu/drm/xe/xe_irq.c
+++ b/drivers/gpu/drm/xe/xe_irq.c
@@ -668,28 +668,45 @@ static irq_handler_t xe_irq_handler(struct xe_device *xe)
 		return xelp_irq_handler;
 }
 
-static void irq_uninstall(void *arg)
+static void xe_irq_msi_free(struct xe_device *xe)
 {
-	struct xe_device *xe = arg;
 	struct pci_dev *pdev = to_pci_dev(xe->drm.dev);
 	int irq;
 
+	irq = pci_irq_vector(pdev, 0);
+	free_irq(irq, xe);
+}
+
+static void xe_irq_msix_free(struct xe_device *xe)
+{
+}
+
+static void xe_irq_free(struct xe_device *xe)
+{
+	if (xe_device_has_msix(xe))
+		xe_irq_msix_free(xe);
+	else
+		xe_irq_msi_free(xe);
+}
+
+static void irq_uninstall(void *arg)
+{
+	struct xe_device *xe = arg;
+
 	if (!xe->irq.enabled)
 		return;
 
 	xe->irq.enabled = false;
 	xe_irq_reset(xe);
 
-	irq = pci_irq_vector(pdev, 0);
-	free_irq(irq, xe);
+	xe_irq_free(xe);
 }
 
-int xe_irq_install(struct xe_device *xe)
+static int xe_irq_msi_request(struct xe_device *xe)
 {
 	struct pci_dev *pdev = to_pci_dev(xe->drm.dev);
-	unsigned int irq_flags = PCI_IRQ_MSIX;
 	irq_handler_t irq_handler;
-	int err, irq, nvec;
+	int irq, err;
 
 	irq_handler = xe_irq_handler(xe);
 	if (!irq_handler) {
@@ -697,32 +714,55 @@ int xe_irq_install(struct xe_device *xe)
 		return -EINVAL;
 	}
 
-	xe_irq_reset(xe);
+	irq = pci_irq_vector(pdev, 0);
+	err = request_irq(irq, irq_handler, IRQF_SHARED, DRIVER_NAME, xe);
+	if (err < 0) {
+		drm_err(&xe->drm, "Failed to request MSI IRQ %d\n", err);
+		return err;
+	}
+
+	return 0;
+}
+
+static int xe_irq_msix_request(struct xe_device *xe)
+{
+	return 0;
+}
+
+int xe_irq_install(struct xe_device *xe)
+{
+	struct pci_dev *pdev = to_pci_dev(xe->drm.dev);
+	unsigned int irq_flags = PCI_IRQ_MSIX;
+
+	int err, nvec;
 
 	nvec = pci_msix_vec_count(pdev);
-	if (nvec <= 0) {
-		if (nvec == -EINVAL) {
-			/* MSIX capability is not supported in the device, using MSI */
-			irq_flags = PCI_IRQ_MSI;
-			nvec = 1;
-		} else {
-			drm_err(&xe->drm, "MSIX: Failed getting count\n");
-			return nvec;
-		}
+	if (nvec > 0) {
+		xe->irq.msix.enabled = true;
+	} else if (nvec == -EINVAL) {
+		/* MSIX capability is not supported in the device, using MSI */
+		irq_flags = PCI_IRQ_MSI;
+		nvec = 1;
+	} else {
+		drm_err(&xe->drm, "MSIX: Failed getting count\n");
+		return nvec;
 	}
 
+	xe_irq_reset(xe);
+
 	err = pci_alloc_irq_vectors(pdev, nvec, nvec, irq_flags);
 	if (err < 0) {
 		drm_err(&xe->drm, "MSI/MSIX: Failed to enable support %d\n", err);
 		return err;
 	}
 
-	irq = pci_irq_vector(pdev, 0);
-	err = request_irq(irq, irq_handler, IRQF_SHARED, DRIVER_NAME, xe);
-	if (err < 0) {
-		drm_err(&xe->drm, "Failed to request MSI/MSIX IRQ %d\n", err);
+	if (xe_device_has_msix(xe))
+		err = xe_irq_msix_request(xe);
+	else
+		err = xe_irq_msi_request(xe);
+
+	if (err)
 		return err;
-	}
 
 	xe->irq.enabled = true;
 
@@ -735,11 +775,15 @@ int xe_irq_install(struct xe_device *xe)
 	return 0;
 
 free_irq_handler:
-	free_irq(irq, xe);
+	xe_irq_free(xe);
 
 	return err;
 }
 
+static void xe_irq_msix_synchronize_irq(struct xe_device *xe)
+{
+}
+
 void xe_irq_suspend(struct xe_device *xe)
 {
 	int irq = to_pci_dev(xe->drm.dev)->irq;
@@ -748,7 +792,12 @@ void xe_irq_suspend(struct xe_device *xe)
 	xe->irq.enabled = false; /* no new irqs */
 	spin_unlock_irq(&xe->irq.lock);
 
-	synchronize_irq(irq); /* flush irqs */
+	/* flush irqs */
+	if (xe_device_has_msix(xe))
+		xe_irq_msix_synchronize_irq(xe);
+	else
+		synchronize_irq(irq);
+
 	xe_irq_reset(xe); /* turn irqs off */
 }
 
-- 
2.43.2



More information about the Intel-xe mailing list