diff options
-rw-r--r-- | drivers/gpu/drm/i915/i915_irq.c | 27 |
1 files changed, 24 insertions, 3 deletions
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index d6bd0d7a7486..61cd87999df3 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c | |||
@@ -86,6 +86,8 @@ static void i915_hpd_irq_setup(struct drm_device *dev); | |||
86 | static void | 86 | static void |
87 | ironlake_enable_display_irq(drm_i915_private_t *dev_priv, u32 mask) | 87 | ironlake_enable_display_irq(drm_i915_private_t *dev_priv, u32 mask) |
88 | { | 88 | { |
89 | assert_spin_locked(&dev_priv->irq_lock); | ||
90 | |||
89 | if ((dev_priv->irq_mask & mask) != 0) { | 91 | if ((dev_priv->irq_mask & mask) != 0) { |
90 | dev_priv->irq_mask &= ~mask; | 92 | dev_priv->irq_mask &= ~mask; |
91 | I915_WRITE(DEIMR, dev_priv->irq_mask); | 93 | I915_WRITE(DEIMR, dev_priv->irq_mask); |
@@ -96,6 +98,8 @@ ironlake_enable_display_irq(drm_i915_private_t *dev_priv, u32 mask) | |||
96 | static void | 98 | static void |
97 | ironlake_disable_display_irq(drm_i915_private_t *dev_priv, u32 mask) | 99 | ironlake_disable_display_irq(drm_i915_private_t *dev_priv, u32 mask) |
98 | { | 100 | { |
101 | assert_spin_locked(&dev_priv->irq_lock); | ||
102 | |||
99 | if ((dev_priv->irq_mask & mask) != mask) { | 103 | if ((dev_priv->irq_mask & mask) != mask) { |
100 | dev_priv->irq_mask |= mask; | 104 | dev_priv->irq_mask |= mask; |
101 | I915_WRITE(DEIMR, dev_priv->irq_mask); | 105 | I915_WRITE(DEIMR, dev_priv->irq_mask); |
@@ -109,6 +113,8 @@ static bool ivb_can_enable_err_int(struct drm_device *dev) | |||
109 | struct intel_crtc *crtc; | 113 | struct intel_crtc *crtc; |
110 | enum pipe pipe; | 114 | enum pipe pipe; |
111 | 115 | ||
116 | assert_spin_locked(&dev_priv->irq_lock); | ||
117 | |||
112 | for_each_pipe(pipe) { | 118 | for_each_pipe(pipe) { |
113 | crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]); | 119 | crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]); |
114 | 120 | ||
@@ -1217,8 +1223,11 @@ static irqreturn_t ivybridge_irq_handler(int irq, void *arg) | |||
1217 | /* On Haswell, also mask ERR_INT because we don't want to risk | 1223 | /* On Haswell, also mask ERR_INT because we don't want to risk |
1218 | * generating "unclaimed register" interrupts from inside the interrupt | 1224 | * generating "unclaimed register" interrupts from inside the interrupt |
1219 | * handler. */ | 1225 | * handler. */ |
1220 | if (IS_HASWELL(dev)) | 1226 | if (IS_HASWELL(dev)) { |
1227 | spin_lock(&dev_priv->irq_lock); | ||
1221 | ironlake_disable_display_irq(dev_priv, DE_ERR_INT_IVB); | 1228 | ironlake_disable_display_irq(dev_priv, DE_ERR_INT_IVB); |
1229 | spin_unlock(&dev_priv->irq_lock); | ||
1230 | } | ||
1222 | 1231 | ||
1223 | gt_iir = I915_READ(GTIIR); | 1232 | gt_iir = I915_READ(GTIIR); |
1224 | if (gt_iir) { | 1233 | if (gt_iir) { |
@@ -1271,8 +1280,12 @@ static irqreturn_t ivybridge_irq_handler(int irq, void *arg) | |||
1271 | ret = IRQ_HANDLED; | 1280 | ret = IRQ_HANDLED; |
1272 | } | 1281 | } |
1273 | 1282 | ||
1274 | if (IS_HASWELL(dev) && ivb_can_enable_err_int(dev)) | 1283 | if (IS_HASWELL(dev)) { |
1275 | ironlake_enable_display_irq(dev_priv, DE_ERR_INT_IVB); | 1284 | spin_lock(&dev_priv->irq_lock); |
1285 | if (ivb_can_enable_err_int(dev)) | ||
1286 | ironlake_enable_display_irq(dev_priv, DE_ERR_INT_IVB); | ||
1287 | spin_unlock(&dev_priv->irq_lock); | ||
1288 | } | ||
1276 | 1289 | ||
1277 | I915_WRITE(DEIER, de_ier); | 1290 | I915_WRITE(DEIER, de_ier); |
1278 | POSTING_READ(DEIER); | 1291 | POSTING_READ(DEIER); |
@@ -2697,6 +2710,8 @@ static void ibx_irq_postinstall(struct drm_device *dev) | |||
2697 | 2710 | ||
2698 | static int ironlake_irq_postinstall(struct drm_device *dev) | 2711 | static int ironlake_irq_postinstall(struct drm_device *dev) |
2699 | { | 2712 | { |
2713 | unsigned long irqflags; | ||
2714 | |||
2700 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; | 2715 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; |
2701 | /* enable kind of interrupts always enabled */ | 2716 | /* enable kind of interrupts always enabled */ |
2702 | u32 display_mask = DE_MASTER_IRQ_CONTROL | DE_GSE | DE_PCH_EVENT | | 2717 | u32 display_mask = DE_MASTER_IRQ_CONTROL | DE_GSE | DE_PCH_EVENT | |
@@ -2735,7 +2750,13 @@ static int ironlake_irq_postinstall(struct drm_device *dev) | |||
2735 | /* Clear & enable PCU event interrupts */ | 2750 | /* Clear & enable PCU event interrupts */ |
2736 | I915_WRITE(DEIIR, DE_PCU_EVENT); | 2751 | I915_WRITE(DEIIR, DE_PCU_EVENT); |
2737 | I915_WRITE(DEIER, I915_READ(DEIER) | DE_PCU_EVENT); | 2752 | I915_WRITE(DEIER, I915_READ(DEIER) | DE_PCU_EVENT); |
2753 | |||
2754 | /* spinlocking not required here for correctness since interrupt | ||
2755 | * setup is guaranteed to run in single-threaded context. But we | ||
2756 | * need it to make the assert_spin_locked happy. */ | ||
2757 | spin_lock_irqsave(&dev_priv->irq_lock, irqflags); | ||
2738 | ironlake_enable_display_irq(dev_priv, DE_PCU_EVENT); | 2758 | ironlake_enable_display_irq(dev_priv, DE_PCU_EVENT); |
2759 | spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); | ||
2739 | } | 2760 | } |
2740 | 2761 | ||
2741 | return 0; | 2762 | return 0; |