[PATCH 094/131] irq

Chris Wilson chris at chris-wilson.co.uk
Sat Aug 6 07:37:01 UTC 2016


---
 drivers/gpu/drm/i915/i915_drv.h |   1 +
 drivers/gpu/drm/i915/i915_irq.c | 116 ++++++++++++++++------------------------
 2 files changed, 47 insertions(+), 70 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index e738ccf22551..c6c6a244a37e 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1806,6 +1806,7 @@ struct drm_i915_private {
 		u32 de_irq_mask[I915_MAX_PIPES];
 	};
 	u32 gt_irq_mask;
+	u32 sde_irq_mask;
 	u32 pm_irq_mask;
 	u32 pm_rps_events;
 	u32 pipestat_irq_mask[I915_MAX_PIPES];
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index ebb83d5a448b..140e068ef75b 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -239,37 +239,19 @@ void ilk_update_display_irq(struct drm_i915_private *dev_priv,
 	}
 }
 
-/**
- * ilk_update_gt_irq - update GTIMR
- * @dev_priv: driver private
- * @interrupt_mask: mask of interrupt bits to update
- * @enabled_irq_mask: mask of interrupt bits to enable
- */
-static void ilk_update_gt_irq(struct drm_i915_private *dev_priv,
-			      uint32_t interrupt_mask,
-			      uint32_t enabled_irq_mask)
+void gen5_enable_gt_irq(struct drm_i915_private *dev_priv, uint32_t mask)
 {
 	assert_spin_locked(&dev_priv->irq_lock);
-
-	WARN_ON(enabled_irq_mask & ~interrupt_mask);
-
-	if (WARN_ON(!intel_irqs_enabled(dev_priv)))
-		return;
-
-	dev_priv->gt_irq_mask &= ~interrupt_mask;
-	dev_priv->gt_irq_mask |= (~enabled_irq_mask & interrupt_mask);
+	dev_priv->gt_irq_mask &= ~mask;
 	I915_WRITE(GTIMR, dev_priv->gt_irq_mask);
-}
-
-void gen5_enable_gt_irq(struct drm_i915_private *dev_priv, uint32_t mask)
-{
-	ilk_update_gt_irq(dev_priv, mask, mask);
 	POSTING_READ_FW(GTIMR);
 }
 
 void gen5_disable_gt_irq(struct drm_i915_private *dev_priv, uint32_t mask)
 {
-	ilk_update_gt_irq(dev_priv, mask, 0);
+	assert_spin_locked(&dev_priv->irq_lock);
+	dev_priv->gt_irq_mask |= mask;
+	I915_WRITE(GTIMR, dev_priv->gt_irq_mask);
 }
 
 static i915_reg_t gen6_pm_iir(struct drm_i915_private *dev_priv)
@@ -1247,8 +1229,8 @@ static void ivybridge_parity_error_irq_handler(struct drm_i915_private *dev_priv
 	queue_work(dev_priv->wq, &dev_priv->l3_parity.error_work);
 }
 
-static void ilk_gt_irq_handler(struct drm_i915_private *dev_priv,
-			       u32 gt_iir)
+static __always_inline void
+ilk_gt_irq_handler(struct drm_i915_private *dev_priv, u32 gt_iir)
 {
 	if (gt_iir & GT_RENDER_USER_INTERRUPT)
 		notify_ring(&dev_priv->engine[RCS]);
@@ -1256,8 +1238,8 @@ static void ilk_gt_irq_handler(struct drm_i915_private *dev_priv,
 		notify_ring(&dev_priv->engine[VCS]);
 }
 
-static void snb_gt_irq_handler(struct drm_i915_private *dev_priv,
-			       u32 gt_iir)
+static __always_inline void
+snb_gt_irq_handler(struct drm_i915_private *dev_priv, u32 gt_iir)
 {
 	if (gt_iir & GT_RENDER_USER_INTERRUPT)
 		notify_ring(&dev_priv->engine[RCS]);
@@ -2206,8 +2188,9 @@ static irqreturn_t ironlake_irq_handler(int irq, void *arg)
 {
 	struct drm_device *dev = arg;
 	struct drm_i915_private *dev_priv = to_i915(dev);
-	u32 de_iir, gt_iir, de_ier, sde_ier = 0;
+	const int gen = INTEL_INFO(dev_priv)->gen;
 	irqreturn_t ret = IRQ_NONE;
+	u32 iir;
 
 	if (!intel_irqs_enabled(dev_priv))
 		return IRQ_NONE;
@@ -2216,60 +2199,52 @@ static irqreturn_t ironlake_irq_handler(int irq, void *arg)
 	disable_rpm_wakeref_asserts(dev_priv);
 
 	/* disable master interrupt before clearing iir  */
-	de_ier = I915_READ(DEIER);
-	I915_WRITE(DEIER, de_ier & ~DE_MASTER_IRQ_CONTROL);
-	POSTING_READ(DEIER);
-
-	/* Disable south interrupts. We'll only write to SDEIIR once, so further
-	 * interrupts will will be stored on its back queue, and then we'll be
-	 * able to process them after we restore SDEIER (as soon as we restore
-	 * it, we'll get an interrupt if SDEIIR still has something to process
-	 * due to its back queue). */
-	if (!HAS_PCH_NOP(dev_priv)) {
-		sde_ier = I915_READ(SDEIER);
-		I915_WRITE(SDEIER, 0);
-		POSTING_READ(SDEIER);
-	}
+	I915_WRITE_FW(DEIER, 0);
 
 	/* Find, clear, then process each source of interrupt */
 
-	gt_iir = I915_READ(GTIIR);
-	if (gt_iir) {
-		I915_WRITE(GTIIR, gt_iir);
-		ret = IRQ_HANDLED;
-		if (INTEL_GEN(dev_priv) >= 6)
-			snb_gt_irq_handler(dev_priv, gt_iir);
-		else
-			ilk_gt_irq_handler(dev_priv, gt_iir);
-	}
-
-	de_iir = I915_READ(DEIIR);
-	if (de_iir) {
-		I915_WRITE(DEIIR, de_iir);
+	iir = I915_READ_FW(GTIIR);
+	if (iir) {
+		I915_WRITE_FW(GTIIR, iir);
 		ret = IRQ_HANDLED;
-		if (INTEL_GEN(dev_priv) >= 7)
-			ivb_display_irq_handler(dev_priv, de_iir);
+		if (gen >= 6)
+			snb_gt_irq_handler(dev_priv, iir);
 		else
-			ilk_display_irq_handler(dev_priv, de_iir);
+			ilk_gt_irq_handler(dev_priv, iir);
 	}
-
-	if (INTEL_GEN(dev_priv) >= 6) {
-		u32 pm_iir = I915_READ(GEN6_PMIIR);
-		if (pm_iir) {
-			I915_WRITE(GEN6_PMIIR, pm_iir);
+	if (gen >= 6) {
+		iir = I915_READ_FW(GEN6_PMIIR);
+		if (iir) {
+			I915_WRITE_FW(GEN6_PMIIR, iir);
 			ret = IRQ_HANDLED;
-			gen6_rps_irq_handler(dev_priv, pm_iir);
+			gen6_rps_irq_handler(dev_priv, iir);
 		}
 	}
 
-	I915_WRITE(DEIER, de_ier);
-	POSTING_READ(DEIER);
-	if (!HAS_PCH_NOP(dev_priv)) {
-		I915_WRITE(SDEIER, sde_ier);
-		POSTING_READ(SDEIER);
+	if (ret == IRQ_NONE) {
+		iir = I915_READ_FW(DEIIR);
+		if (iir) {
+			/* Disable south interrupts. We'll only write to SDEIIR once, so further
+			 * interrupts will will be stored on its back queue, and then we'll be
+			 * able to process them after we restore SDEIER (as soon as we restore
+			 * it, we'll get an interrupt if SDEIIR still has something to process
+			 * due to its back queue). */
+			if (!HAS_PCH_NOP(dev_priv))
+				I915_WRITE_FW(SDEIER, 0);
+
+			I915_WRITE_FW(DEIIR, iir);
+			ret = IRQ_HANDLED;
+			if (gen >= 7)
+				ivb_display_irq_handler(dev_priv, iir);
+			else
+				ilk_display_irq_handler(dev_priv, iir);
+
+			if (!HAS_PCH_NOP(dev_priv))
+				I915_WRITE_FW(SDEIER, dev_priv->sde_irq_mask);
+		}
 	}
 
-	/* IRQs are synced during runtime_suspend, we don't require a wakeref */
+	I915_WRITE_FW(DEIER, dev_priv->gt_irq_mask);
 	enable_rpm_wakeref_asserts(dev_priv);
 
 	return ret;
@@ -3414,6 +3389,7 @@ static void ibx_hpd_irq_setup(struct drm_i915_private *dev_priv)
 	}
 
 	ibx_display_interrupt_update(dev_priv, hotplug_irqs, enabled_irqs);
+	dev_priv->sde_irq_mask = enabled_irqs;
 
 	/*
 	 * Enable digital hotplug on the PCH, and configure the DP short pulse
-- 
2.8.1



More information about the Intel-gfx-trybot mailing list