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 at intel.com> Reviewed-by: Damien Lespiau <damien.lespiau at intel.com> Signed-off-by: Ben Widawsky <ben at bwidawsk.net> --- drivers/gpu/drm/i915/i915_irq.c | 31 +++++++++++++++++++++++++------ drivers/gpu/drm/i915/i915_reg.h | 3 +++ drivers/gpu/drm/i915/intel_ringbuffer.c | 3 ++- 3 files changed, 30 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 4f7a12f..560465d 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -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); diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index b740f0d..73348ba 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -886,6 +886,9 @@ #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) diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 8a6a0ee..0e72da6 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -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; -- 1.8.3