summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/i915/i915_irq.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/i915/i915_irq.c')
-rw-r--r--drivers/gpu/drm/i915/i915_irq.c81
1 files changed, 59 insertions, 22 deletions
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index f75cbf5b8a1c..37ca4a35daf2 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -120,6 +120,29 @@ void gen2_irq_init(struct intel_uncore *uncore, struct i915_irq_regs regs,
intel_uncore_posting_read(uncore, regs.imr);
}
+void gen2_error_reset(struct intel_uncore *uncore, struct i915_error_regs regs)
+{
+ intel_uncore_write(uncore, regs.emr, 0xffffffff);
+ intel_uncore_posting_read(uncore, regs.emr);
+
+ intel_uncore_write(uncore, regs.eir, 0xffffffff);
+ intel_uncore_posting_read(uncore, regs.eir);
+ intel_uncore_write(uncore, regs.eir, 0xffffffff);
+ intel_uncore_posting_read(uncore, regs.eir);
+}
+
+void gen2_error_init(struct intel_uncore *uncore, struct i915_error_regs regs,
+ u32 emr_val)
+{
+ intel_uncore_write(uncore, regs.eir, 0xffffffff);
+ intel_uncore_posting_read(uncore, regs.eir);
+ intel_uncore_write(uncore, regs.eir, 0xffffffff);
+ intel_uncore_posting_read(uncore, regs.eir);
+
+ intel_uncore_write(uncore, regs.emr, emr_val);
+ intel_uncore_posting_read(uncore, regs.emr);
+}
+
/**
* ivb_parity_work - Workqueue called when a parity error interrupt
* occurred.
@@ -207,6 +230,7 @@ out:
static irqreturn_t valleyview_irq_handler(int irq, void *arg)
{
struct drm_i915_private *dev_priv = arg;
+ struct intel_display *display = &dev_priv->display;
irqreturn_t ret = IRQ_NONE;
if (!intel_irqs_enabled(dev_priv))
@@ -217,6 +241,7 @@ static irqreturn_t valleyview_irq_handler(int irq, void *arg)
do {
u32 iir, gt_iir, pm_iir;
+ u32 eir = 0, dpinvgtt = 0;
u32 pipe_stats[I915_MAX_PIPES] = {};
u32 hotplug_status = 0;
u32 ier = 0;
@@ -254,13 +279,16 @@ static irqreturn_t valleyview_irq_handler(int irq, void *arg)
if (iir & I915_DISPLAY_PORT_INTERRUPT)
hotplug_status = i9xx_hpd_irq_ack(dev_priv);
+ if (iir & I915_MASTER_ERROR_INTERRUPT)
+ vlv_display_error_irq_ack(display, &eir, &dpinvgtt);
+
/* Call regardless, as some status bits might not be
* signalled in IIR */
i9xx_pipestat_irq_ack(dev_priv, iir, pipe_stats);
if (iir & (I915_LPE_PIPE_A_INTERRUPT |
I915_LPE_PIPE_B_INTERRUPT))
- intel_lpe_audio_irq_handler(dev_priv);
+ intel_lpe_audio_irq_handler(display);
/*
* VLV_IIR is single buffered, and reflects the level
@@ -280,6 +308,9 @@ static irqreturn_t valleyview_irq_handler(int irq, void *arg)
if (hotplug_status)
i9xx_hpd_irq_handler(dev_priv, hotplug_status);
+ if (iir & I915_MASTER_ERROR_INTERRUPT)
+ vlv_display_error_irq_handler(display, eir, dpinvgtt);
+
valleyview_pipestat_irq_handler(dev_priv, pipe_stats);
} while (0);
@@ -293,6 +324,7 @@ static irqreturn_t valleyview_irq_handler(int irq, void *arg)
static irqreturn_t cherryview_irq_handler(int irq, void *arg)
{
struct drm_i915_private *dev_priv = arg;
+ struct intel_display *display = &dev_priv->display;
irqreturn_t ret = IRQ_NONE;
if (!intel_irqs_enabled(dev_priv))
@@ -303,6 +335,7 @@ static irqreturn_t cherryview_irq_handler(int irq, void *arg)
do {
u32 master_ctl, iir;
+ u32 eir = 0, dpinvgtt = 0;
u32 pipe_stats[I915_MAX_PIPES] = {};
u32 hotplug_status = 0;
u32 ier = 0;
@@ -336,6 +369,9 @@ static irqreturn_t cherryview_irq_handler(int irq, void *arg)
if (iir & I915_DISPLAY_PORT_INTERRUPT)
hotplug_status = i9xx_hpd_irq_ack(dev_priv);
+ if (iir & I915_MASTER_ERROR_INTERRUPT)
+ vlv_display_error_irq_ack(display, &eir, &dpinvgtt);
+
/* Call regardless, as some status bits might not be
* signalled in IIR */
i9xx_pipestat_irq_ack(dev_priv, iir, pipe_stats);
@@ -343,7 +379,7 @@ static irqreturn_t cherryview_irq_handler(int irq, void *arg)
if (iir & (I915_LPE_PIPE_A_INTERRUPT |
I915_LPE_PIPE_B_INTERRUPT |
I915_LPE_PIPE_C_INTERRUPT))
- intel_lpe_audio_irq_handler(dev_priv);
+ intel_lpe_audio_irq_handler(display);
/*
* VLV_IIR is single buffered, and reflects the level
@@ -358,6 +394,9 @@ static irqreturn_t cherryview_irq_handler(int irq, void *arg)
if (hotplug_status)
i9xx_hpd_irq_handler(dev_priv, hotplug_status);
+ if (iir & I915_MASTER_ERROR_INTERRUPT)
+ vlv_display_error_irq_handler(display, eir, dpinvgtt);
+
valleyview_pipestat_irq_handler(dev_priv, pipe_stats);
} while (0);
@@ -658,8 +697,7 @@ static void valleyview_irq_reset(struct drm_i915_private *dev_priv)
gen5_gt_irq_reset(to_gt(dev_priv));
spin_lock_irq(&dev_priv->irq_lock);
- if (dev_priv->display.irq.display_irqs_enabled)
- vlv_display_irq_reset(dev_priv);
+ vlv_display_irq_reset(dev_priv);
spin_unlock_irq(&dev_priv->irq_lock);
}
@@ -723,8 +761,7 @@ static void cherryview_irq_reset(struct drm_i915_private *dev_priv)
gen2_irq_reset(uncore, GEN8_PCU_IRQ_REGS);
spin_lock_irq(&dev_priv->irq_lock);
- if (dev_priv->display.irq.display_irqs_enabled)
- vlv_display_irq_reset(dev_priv);
+ vlv_display_irq_reset(dev_priv);
spin_unlock_irq(&dev_priv->irq_lock);
}
@@ -740,8 +777,7 @@ static void valleyview_irq_postinstall(struct drm_i915_private *dev_priv)
gen5_gt_irq_postinstall(to_gt(dev_priv));
spin_lock_irq(&dev_priv->irq_lock);
- if (dev_priv->display.irq.display_irqs_enabled)
- vlv_display_irq_postinstall(dev_priv);
+ vlv_display_irq_postinstall(dev_priv);
spin_unlock_irq(&dev_priv->irq_lock);
intel_uncore_write(&dev_priv->uncore, VLV_MASTER_IER, MASTER_INTERRUPT_ENABLE);
@@ -794,8 +830,7 @@ static void cherryview_irq_postinstall(struct drm_i915_private *dev_priv)
gen8_gt_irq_postinstall(to_gt(dev_priv));
spin_lock_irq(&dev_priv->irq_lock);
- if (dev_priv->display.irq.display_irqs_enabled)
- vlv_display_irq_postinstall(dev_priv);
+ vlv_display_irq_postinstall(dev_priv);
spin_unlock_irq(&dev_priv->irq_lock);
intel_uncore_write(&dev_priv->uncore, GEN8_MASTER_IRQ, GEN8_MASTER_IRQ_CONTROL);
@@ -817,10 +852,10 @@ static u32 i9xx_error_mask(struct drm_i915_private *i915)
* so we just have to mask off all page table errors via EMR.
*/
if (HAS_FBC(i915))
- return ~I915_ERROR_MEMORY_REFRESH;
+ return I915_ERROR_MEMORY_REFRESH;
else
- return ~(I915_ERROR_PAGE_TABLE |
- I915_ERROR_MEMORY_REFRESH);
+ return I915_ERROR_PAGE_TABLE |
+ I915_ERROR_MEMORY_REFRESH;
}
static void i9xx_error_irq_ack(struct drm_i915_private *dev_priv,
@@ -869,6 +904,7 @@ static void i915_irq_reset(struct drm_i915_private *dev_priv)
i9xx_display_irq_reset(dev_priv);
+ gen2_error_reset(uncore, GEN2_ERROR_REGS);
gen2_irq_reset(uncore, GEN2_IRQ_REGS);
dev_priv->irq_mask = ~0u;
}
@@ -878,7 +914,7 @@ static void i915_irq_postinstall(struct drm_i915_private *dev_priv)
struct intel_uncore *uncore = &dev_priv->uncore;
u32 enable_mask;
- intel_uncore_write(uncore, EMR, i9xx_error_mask(dev_priv));
+ gen2_error_init(uncore, GEN2_ERROR_REGS, ~i9xx_error_mask(dev_priv));
dev_priv->irq_mask =
~(I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |
@@ -974,6 +1010,7 @@ static void i965_irq_reset(struct drm_i915_private *dev_priv)
i9xx_display_irq_reset(dev_priv);
+ gen2_error_reset(uncore, GEN2_ERROR_REGS);
gen2_irq_reset(uncore, GEN2_IRQ_REGS);
dev_priv->irq_mask = ~0u;
}
@@ -988,13 +1025,13 @@ static u32 i965_error_mask(struct drm_i915_private *i915)
* so we can always enable the page table errors.
*/
if (IS_G4X(i915))
- return ~(GM45_ERROR_PAGE_TABLE |
- GM45_ERROR_MEM_PRIV |
- GM45_ERROR_CP_PRIV |
- I915_ERROR_MEMORY_REFRESH);
+ return GM45_ERROR_PAGE_TABLE |
+ GM45_ERROR_MEM_PRIV |
+ GM45_ERROR_CP_PRIV |
+ I915_ERROR_MEMORY_REFRESH;
else
- return ~(I915_ERROR_PAGE_TABLE |
- I915_ERROR_MEMORY_REFRESH);
+ return I915_ERROR_PAGE_TABLE |
+ I915_ERROR_MEMORY_REFRESH;
}
static void i965_irq_postinstall(struct drm_i915_private *dev_priv)
@@ -1002,7 +1039,7 @@ static void i965_irq_postinstall(struct drm_i915_private *dev_priv)
struct intel_uncore *uncore = &dev_priv->uncore;
u32 enable_mask;
- intel_uncore_write(uncore, EMR, i965_error_mask(dev_priv));
+ gen2_error_init(uncore, GEN2_ERROR_REGS, ~i965_error_mask(dev_priv));
dev_priv->irq_mask =
~(I915_ASLE_INTERRUPT |
@@ -1235,7 +1272,7 @@ int intel_irq_install(struct drm_i915_private *dev_priv)
}
/**
- * intel_irq_uninstall - finilizes all irq handling
+ * intel_irq_uninstall - finalizes all irq handling
* @dev_priv: i915 device instance
*
* This stops interrupt and hotplug handling and unregisters and frees all