drm/i915: Enable vebox interrupts
authorBen Widawsky <ben@bwidawsk.net>
Wed, 29 May 2013 02:22:31 +0000 (19:22 -0700)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Fri, 31 May 2013 18:54:20 +0000 (20:54 +0200)
Similar to a patch originally written by:

v2: Reversed the meanings of masked and enabled (Haihao)
Made non-destructive writes in case enable/disabler rps runs first
(Haihao)

v3: Reword error message (Damien)
Modify postinstall to do the right thing based on previous fixup. (Ben)

CC: Xiang, Haihao <haihao.xiang@intel.com>
Reviewed-by: Damien Lespiau <damien.lespiau@intel.com>
Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
drivers/gpu/drm/i915/i915_irq.c
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/i915/intel_ringbuffer.c

index 90ed599611cbc7156240f8a5f4fb4a7fea133aab..e17bbe201195e14d5f1503cf17b45a422e4ac1ea 100644 (file)
@@ -944,8 +944,15 @@ static void hsw_pm_irq_handler(struct drm_i915_private *dev_priv,
        }
        spin_unlock_irqrestore(&dev_priv->rps.lock, flags);
 
-       if (pm_iir & ~GEN6_PM_RPS_EVENTS)
-               DRM_ERROR("Unexpected PM interrupted\n");
+       if (pm_iir & ~GEN6_PM_RPS_EVENTS) {
+               if (pm_iir & PM_VEBOX_USER_INTERRUPT)
+                       notify_ring(dev_priv->dev, &dev_priv->ring[VECS]);
+
+               if (pm_iir & PM_VEBOX_CS_ERROR_INTERRUPT) {
+                       DRM_ERROR("VEBOX CS error interrupt 0x%08x\n", pm_iir);
+                       i915_handle_error(dev_priv->dev, false);
+               }
+       }
 }
 
 static irqreturn_t valleyview_irq_handler(int irq, void *arg)
@@ -2690,6 +2697,7 @@ static int ivybridge_irq_postinstall(struct drm_device *dev)
                DE_PLANEA_FLIP_DONE_IVB |
                DE_AUX_CHANNEL_A_IVB |
                DE_ERR_INT_IVB;
+       u32 pm_irqs = GEN6_PM_RPS_EVENTS;
        u32 gt_irqs;
 
        dev_priv->irq_mask = ~display_mask;
@@ -2715,10 +2723,21 @@ static int ivybridge_irq_postinstall(struct drm_device *dev)
        I915_WRITE(GTIER, gt_irqs);
        POSTING_READ(GTIER);
 
-       /* Power management */
-       I915_WRITE(GEN6_PMIMR, ~GEN6_PM_RPS_EVENTS);
-       I915_WRITE(GEN6_PMIER, GEN6_PM_RPS_EVENTS);
-       POSTING_READ(GEN6_PMIMR);
+       I915_WRITE(GEN6_PMIIR, I915_READ(GEN6_PMIIR));
+       if (HAS_VEBOX(dev))
+               pm_irqs |= PM_VEBOX_USER_INTERRUPT |
+                       PM_VEBOX_CS_ERROR_INTERRUPT;
+
+       /* Our enable/disable rps functions may touch these registers so
+        * make sure to set a known state for only the non-RPS bits.
+        * The RMW is extra paranoia since this should be called after being set
+        * to a known state in preinstall.
+        * */
+       I915_WRITE(GEN6_PMIMR,
+                  (I915_READ(GEN6_PMIMR) | ~GEN6_PM_RPS_EVENTS) & ~pm_irqs);
+       I915_WRITE(GEN6_PMIER,
+                  (I915_READ(GEN6_PMIER) & GEN6_PM_RPS_EVENTS) | pm_irqs);
+       POSTING_READ(GEN6_PMIER);
 
        ibx_irq_postinstall(dev);
 
index bdb2c1734da8762162347c3113810908c4669099..89fac19d3249eee8df570b4df919e4823e8b199d 100644 (file)
 #define GT_RENDER_DEBUG_INTERRUPT              (1 <<  1)
 #define GT_RENDER_USER_INTERRUPT               (1 <<  0)
 
+#define PM_VEBOX_CS_ERROR_INTERRUPT            (1 << 12) /* hsw+ */
+#define PM_VEBOX_USER_INTERRUPT                        (1 << 10) /* hsw+ */
+
 /* These are all the "old" interrupts */
 #define ILK_BSD_USER_INTERRUPT                         (1<<5)
 #define I915_PIPE_CONTROL_NOTIFY_INTERRUPT             (1<<18)
index 8a6a0ee6d3507a7362301718f9ab0e7dce9e744d..0e72da6ad0fa87c5864e102dc162f0ca9f080128 100644 (file)
@@ -1969,7 +1969,8 @@ int intel_init_vebox_ring_buffer(struct drm_device *dev)
        ring->add_request = gen6_add_request;
        ring->get_seqno = gen6_ring_get_seqno;
        ring->set_seqno = ring_set_seqno;
-       ring->irq_enable_mask = 0;
+       ring->irq_enable_mask = PM_VEBOX_USER_INTERRUPT |
+               PM_VEBOX_CS_ERROR_INTERRUPT;
        ring->irq_get = hsw_vebox_get_irq;
        ring->irq_put = hsw_vebox_put_irq;
        ring->dispatch_execbuffer = gen6_ring_dispatch_execbuffer;