From: Thomas Daniel <thomas.daniel@xxxxxxxxx> We need to attend context switch interrupts from all rings. Also, fixed writing IMR/IER and added HWSTAM at ring init time. Notice that, if added to irq_enable_mask, the context switch interrupts would be incorrectly masked out when the user interrupts are due to no users waiting on a sequence number. Therefore, this commit adds a bitmask of interrupts to be kept unmasked at all times. Signed-off-by: Thomas Daniel <thomas.daniel@xxxxxxxxx> Acked-by: Oscar Mateo <oscar.mateo@xxxxxxxxx> --- drivers/gpu/drm/i915/i915_irq.c | 28 ++++++++++++++++++++-------- drivers/gpu/drm/i915/i915_reg.h | 2 ++ drivers/gpu/drm/i915/intel_ringbuffer.c | 33 +++++++++++++++++++-------------- drivers/gpu/drm/i915/intel_ringbuffer.h | 1 + 4 files changed, 42 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 1ba8bb3..56657b5 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1334,7 +1334,7 @@ static irqreturn_t gen8_gt_irq_handler(struct drm_device *dev, struct drm_i915_private *dev_priv, u32 master_ctl) { - u32 rcs, bcs, vcs; + u32 rcs, bcs, vcs, vecs; uint32_t tmp = 0; irqreturn_t ret = IRQ_NONE; @@ -1348,6 +1348,8 @@ static irqreturn_t gen8_gt_irq_handler(struct drm_device *dev, notify_ring(dev, &dev_priv->ring[RCS]); if (bcs & GT_RENDER_USER_INTERRUPT) notify_ring(dev, &dev_priv->ring[BCS]); + if ((rcs | bcs) & GEN8_GT_CONTEXT_SWITCH_INTERRUPT) + DRM_DEBUG_DRIVER("TODO: Context switch\n"); I915_WRITE(GEN8_GT_IIR(0), tmp); } else DRM_ERROR("The master control interrupt lied (GT0)!\n"); @@ -1360,6 +1362,8 @@ static irqreturn_t gen8_gt_irq_handler(struct drm_device *dev, vcs = tmp >> GEN8_VCS1_IRQ_SHIFT; if (vcs & GT_RENDER_USER_INTERRUPT) notify_ring(dev, &dev_priv->ring[VCS]); + if (vcs & GEN8_GT_CONTEXT_SWITCH_INTERRUPT) + DRM_DEBUG_DRIVER("TODO: Context switch\n"); I915_WRITE(GEN8_GT_IIR(1), tmp); } else DRM_ERROR("The master control interrupt lied (GT1)!\n"); @@ -1369,9 +1373,11 @@ static irqreturn_t gen8_gt_irq_handler(struct drm_device *dev, tmp = I915_READ(GEN8_GT_IIR(3)); if (tmp) { ret = IRQ_HANDLED; - vcs = tmp >> GEN8_VECS_IRQ_SHIFT; - if (vcs & GT_RENDER_USER_INTERRUPT) + vecs = tmp >> GEN8_VECS_IRQ_SHIFT; + if (vecs & GT_RENDER_USER_INTERRUPT) notify_ring(dev, &dev_priv->ring[VECS]); + if (vecs & GEN8_GT_CONTEXT_SWITCH_INTERRUPT) + DRM_DEBUG_DRIVER("TODO: Context switch\n"); I915_WRITE(GEN8_GT_IIR(3), tmp); } else DRM_ERROR("The master control interrupt lied (GT3)!\n"); @@ -3244,12 +3250,17 @@ static void gen8_gt_irq_postinstall(struct drm_i915_private *dev_priv) /* These are interrupts we'll toggle with the ring mask register */ uint32_t gt_interrupts[] = { GT_RENDER_USER_INTERRUPT << GEN8_RCS_IRQ_SHIFT | - GT_RENDER_L3_PARITY_ERROR_INTERRUPT | - GT_RENDER_USER_INTERRUPT << GEN8_BCS_IRQ_SHIFT, + GT_RENDER_L3_PARITY_ERROR_INTERRUPT | + GEN8_GT_CONTEXT_SWITCH_INTERRUPT << GEN8_RCS_IRQ_SHIFT | + GT_RENDER_USER_INTERRUPT << GEN8_BCS_IRQ_SHIFT | + GEN8_GT_CONTEXT_SWITCH_INTERRUPT << GEN8_BCS_IRQ_SHIFT, GT_RENDER_USER_INTERRUPT << GEN8_VCS1_IRQ_SHIFT | - GT_RENDER_USER_INTERRUPT << GEN8_VCS2_IRQ_SHIFT, + GEN8_GT_CONTEXT_SWITCH_INTERRUPT << GEN8_VCS1_IRQ_SHIFT | + GT_RENDER_USER_INTERRUPT << GEN8_VCS2_IRQ_SHIFT | + GEN8_GT_CONTEXT_SWITCH_INTERRUPT << GEN8_VCS2_IRQ_SHIFT, 0, - GT_RENDER_USER_INTERRUPT << GEN8_VECS_IRQ_SHIFT + GT_RENDER_USER_INTERRUPT << GEN8_VECS_IRQ_SHIFT | + GEN8_GT_CONTEXT_SWITCH_INTERRUPT << GEN8_VECS_IRQ_SHIFT, }; for (i = 0; i < ARRAY_SIZE(gt_interrupts); i++) { @@ -3258,9 +3269,10 @@ static void gen8_gt_irq_postinstall(struct drm_i915_private *dev_priv) DRM_ERROR("Interrupt (%d) should have been masked in pre-install 0x%08x\n", i, tmp); I915_WRITE(GEN8_GT_IMR(i), ~gt_interrupts[i]); + POSTING_READ(GEN8_GT_IMR(i)); I915_WRITE(GEN8_GT_IER(i), gt_interrupts[i]); + POSTING_READ(GEN8_GT_IER(i)); } - POSTING_READ(GEN8_GT_IER(0)); } static void gen8_de_irq_postinstall(struct drm_i915_private *dev_priv) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index adcb9c7..117825e 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -709,6 +709,7 @@ enum punit_power_well { #define RING_ACTHD(base) ((base)+0x74) #define RING_NOPID(base) ((base)+0x94) #define RING_IMR(base) ((base)+0xa8) +#define RING_HWSTAM(base) ((base)+0x98) #define RING_TIMESTAMP(base) ((base)+0x358) #define TAIL_ADDR 0x001FFFF8 #define HEAD_WRAP_COUNT 0xFFE00000 @@ -4100,6 +4101,7 @@ enum punit_power_well { #define GEN8_GT_IMR(which) (0x44304 + (0x10 * (which))) #define GEN8_GT_IIR(which) (0x44308 + (0x10 * (which))) #define GEN8_GT_IER(which) (0x4430c + (0x10 * (which))) +#define GEN8_GT_CONTEXT_SWITCH_INTERRUPT (1<<8) #define GEN8_BCS_IRQ_SHIFT 16 #define GEN8_RCS_IRQ_SHIFT 0 diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index fba9b05..230740e 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -536,6 +536,8 @@ out: static int init_ring_common_lrc(struct intel_engine *ring) { + struct drm_device *dev = ring->dev; + drm_i915_private_t *dev_priv = dev->dev_private; struct intel_ringbuffer *ringbuf = &ring->default_ringbuf; ringbuf->head = 0; @@ -543,6 +545,9 @@ static int init_ring_common_lrc(struct intel_engine *ring) ringbuf->space = ringbuf->size; ringbuf->last_retired_head = -1; + I915_WRITE_IMR(ring, ~(ring->irq_enable_mask | ring->irq_keep_mask)); + I915_WRITE(RING_HWSTAM(ring->mmio_base), ~(ring->irq_enable_mask | ring->irq_keep_mask)); + return 0; } @@ -1189,13 +1194,7 @@ gen8_ring_get_irq(struct intel_engine *ring) spin_lock_irqsave(&dev_priv->irq_lock, flags); if (ring->irq_refcount++ == 0) { - if (HAS_L3_DPF(dev) && ring->id == RCS) { - I915_WRITE_IMR(ring, - ~(ring->irq_enable_mask | - GT_RENDER_L3_PARITY_ERROR_INTERRUPT)); - } else { - I915_WRITE_IMR(ring, ~ring->irq_enable_mask); - } + I915_WRITE_IMR(ring, ~(ring->irq_enable_mask | ring->irq_keep_mask)); POSTING_READ(RING_IMR(ring->mmio_base)); } spin_unlock_irqrestore(&dev_priv->irq_lock, flags); @@ -1212,12 +1211,7 @@ gen8_ring_put_irq(struct intel_engine *ring) spin_lock_irqsave(&dev_priv->irq_lock, flags); if (--ring->irq_refcount == 0) { - if (HAS_L3_DPF(dev) && ring->id == RCS) { - I915_WRITE_IMR(ring, - ~GT_RENDER_L3_PARITY_ERROR_INTERRUPT); - } else { - I915_WRITE_IMR(ring, ~0); - } + I915_WRITE_IMR(ring, ~ring->irq_keep_mask); POSTING_READ(RING_IMR(ring->mmio_base)); } spin_unlock_irqrestore(&dev_priv->irq_lock, flags); @@ -2032,16 +2026,21 @@ int intel_init_render_ring(struct drm_device *dev) if (dev_priv->lrc_enabled) { ring->write_tail = gen8_write_tail_lrc; ring->init = init_render_ring_lrc; + ring->irq_keep_mask = + GEN8_GT_CONTEXT_SWITCH_INTERRUPT << GEN8_RCS_IRQ_SHIFT; } ring->add_request = gen8_add_request; ring->flush = gen8_render_ring_flush; ring->irq_get = gen8_ring_get_irq; ring->irq_put = gen8_ring_put_irq; + if (HAS_L3_DPF(dev)) + ring->irq_keep_mask |= GT_RENDER_L3_PARITY_ERROR_INTERRUPT; } else { ring->irq_get = gen6_ring_get_irq; ring->irq_put = gen6_ring_put_irq; } - ring->irq_enable_mask = GT_RENDER_USER_INTERRUPT; + ring->irq_enable_mask = + GT_RENDER_USER_INTERRUPT << GEN8_RCS_IRQ_SHIFT; ring->get_seqno = gen6_ring_get_seqno; ring->set_seqno = ring_set_seqno; ring->sync_to = gen6_ring_sync; @@ -2202,6 +2201,8 @@ int intel_init_bsd_ring(struct drm_device *dev) if (dev_priv->lrc_enabled) { ring->write_tail = gen8_write_tail_lrc; ring->init = init_ring_common_lrc; + ring->irq_keep_mask = + GEN8_GT_CONTEXT_SWITCH_INTERRUPT << GEN8_VCS1_IRQ_SHIFT; } ring->flush = gen8_ring_flush; ring->add_request = gen8_add_request; @@ -2262,6 +2263,8 @@ int intel_init_blt_ring(struct drm_device *dev) if (dev_priv->lrc_enabled) { ring->write_tail = gen8_write_tail_lrc; ring->init = init_ring_common_lrc; + ring->irq_keep_mask = + GEN8_GT_CONTEXT_SWITCH_INTERRUPT << GEN8_BCS_IRQ_SHIFT; } ring->flush = gen8_ring_flush; ring->add_request = gen8_add_request; @@ -2304,6 +2307,8 @@ int intel_init_vebox_ring(struct drm_device *dev) if (dev_priv->lrc_enabled) { ring->write_tail = gen8_write_tail_lrc; ring->init = init_ring_common_lrc; + ring->irq_keep_mask = + GEN8_GT_CONTEXT_SWITCH_INTERRUPT << GEN8_VECS_IRQ_SHIFT; } ring->flush = gen8_ring_flush; ring->add_request = gen8_add_request; diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 3b0f28b..9fbb2d5 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -93,6 +93,7 @@ struct intel_engine { unsigned irq_refcount; /* protected by dev_priv->irq_lock */ u32 irq_enable_mask; /* bitmask to enable ring interrupt */ + u32 irq_keep_mask; /* bitmask for interrupts that should not be masked */ u32 trace_irq_seqno; u32 sync_seqno[I915_NUM_RINGS-1]; bool __must_check (*irq_get)(struct intel_engine *ring); -- 1.9.0 _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/intel-gfx