| From 174fb53dddc9f0348751ce4f2022b0c9b24d5e5d Mon Sep 17 00:00:00 2001 |
| From: Mika Kuoppala <mika.kuoppala@linux.intel.com> |
| Date: Thu, 22 Aug 2013 21:09:00 +0300 |
| Subject: drm/i915: Don't mask EI UP interrupt on IVB|SNB |
| |
| Submitting a batchbuffer which simulates a gpu |
| hang by doing MI_BATCH_BUFFER_START into itself, |
| to test hangcheck, started to hard hang the whole box |
| (IVB). Bisecting lead to this commit: |
| |
| commit 664b422c2966cd39b8f67e8d53a566ea8c877cd6 |
| Author: Vinit Azad <vinit.azad@intel.com> |
| Date: Wed Aug 14 13:34:33 2013 -0700 |
| |
| drm/i915: Only unmask required PM interrupts |
| |
| Experimenting with the mask register showed that |
| unmasking EI UP will prevent the hard hang in IVB and SNB. |
| HSW doesn't hang with EI UP masked. |
| |
| Considering we are just disabling interrupts that aren't even |
| delivered to driver, this change is more likely to paper over some |
| weirdness in gpu's internal state machine. But until better |
| explanation can be found, let's trade little bit of power |
| for stability on these architectures. |
| |
| v2: - Unmask EI_EXPIRED directly in I915_WRITE (Vinit) |
| v3: - Only unmask on SNB and IVB |
| |
| Cc: Vinit Azad <vinit.azad@intel.com> |
| Signed-off-by: Mika Kuoppala <mika.kuoppala@intel.com> |
| Acked-by: Vinit Azad <vinit.azad@intel.com> |
| Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> |
| (cherry picked from commit a9c1f90c8e1792127f8348c1cc2565b79b2ef20a) |
| Signed-off-by: Darren Hart <dvhart@linux.intel.com> |
| --- |
| drivers/gpu/drm/i915/intel_pm.c | 12 +++++++++++- |
| 1 file changed, 11 insertions(+), 1 deletion(-) |
| |
| diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c |
| index 46056820d1d2..6b1d00389952 100644 |
| --- a/drivers/gpu/drm/i915/intel_pm.c |
| +++ b/drivers/gpu/drm/i915/intel_pm.c |
| @@ -3447,14 +3447,24 @@ int intel_enable_rc6(const struct drm_device *dev) |
| static void gen6_enable_rps_interrupts(struct drm_device *dev) |
| { |
| struct drm_i915_private *dev_priv = dev->dev_private; |
| + u32 enabled_intrs; |
| |
| spin_lock_irq(&dev_priv->irq_lock); |
| WARN_ON(dev_priv->rps.pm_iir); |
| snb_enable_pm_irq(dev_priv, GEN6_PM_RPS_EVENTS); |
| I915_WRITE(GEN6_PMIIR, GEN6_PM_RPS_EVENTS); |
| spin_unlock_irq(&dev_priv->irq_lock); |
| + |
| /* only unmask PM interrupts we need. Mask all others. */ |
| - I915_WRITE(GEN6_PMINTRMSK, ~GEN6_PM_RPS_EVENTS); |
| + enabled_intrs = GEN6_PM_RPS_EVENTS; |
| + |
| + /* IVB and SNB hard hangs on looping batchbuffer |
| + * if GEN6_PM_UP_EI_EXPIRED is masked. |
| + */ |
| + if (INTEL_INFO(dev)->gen <= 7 && !IS_HASWELL(dev)) |
| + enabled_intrs |= GEN6_PM_RP_UP_EI_EXPIRED; |
| + |
| + I915_WRITE(GEN6_PMINTRMSK, ~enabled_intrs); |
| } |
| |
| static void gen6_enable_rps(struct drm_device *dev) |
| -- |
| 1.8.5.rc3 |
| |