Message ID | 1406217891-8912-24-git-send-email-thomas.daniel@intel.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Thu, Jul 24, 2014 at 05:04:31PM +0100, Thomas Daniel wrote: > From: Oscar Mateo <oscar.mateo@intel.com> > > 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. > > v2: Disable HWSTAM, as suggested by Damien (nobody listens to these interrupts, > anyway). > > v3: Add new get/put_irq functions. > > Signed-off-by: Thomas Daniel <thomas.daniel@intel.com> (v1) > Signed-off-by: Oscar Mateo <oscar.mateo@intel.com> (v2 & v3) irq_keep_mask is a nifty idea, would be pretty to roll it out for legacy rings too. But totally optional. -Daniel > --- > drivers/gpu/drm/i915/i915_irq.c | 19 ++++++++-- > drivers/gpu/drm/i915/i915_reg.h | 3 ++ > drivers/gpu/drm/i915/intel_lrc.c | 58 +++++++++++++++++++++++++++++++ > drivers/gpu/drm/i915/intel_ringbuffer.h | 1 + > 4 files changed, 78 insertions(+), 3 deletions(-) > > diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c > index a38b5c3..f77a4ca 100644 > --- a/drivers/gpu/drm/i915/i915_irq.c > +++ b/drivers/gpu/drm/i915/i915_irq.c > @@ -1643,6 +1643,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"); > } else > DRM_ERROR("The master control interrupt lied (GT0)!\n"); > } > @@ -1655,9 +1657,13 @@ 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"); > vcs = tmp >> GEN8_VCS2_IRQ_SHIFT; > if (vcs & GT_RENDER_USER_INTERRUPT) > notify_ring(dev, &dev_priv->ring[VCS2]); > + if (vcs & GEN8_GT_CONTEXT_SWITCH_INTERRUPT) > + DRM_DEBUG_DRIVER("TODO: Context switch\n"); > } else > DRM_ERROR("The master control interrupt lied (GT1)!\n"); > } > @@ -1681,6 +1687,8 @@ static irqreturn_t gen8_gt_irq_handler(struct drm_device *dev, > vcs = tmp >> GEN8_VECS_IRQ_SHIFT; > if (vcs & GT_RENDER_USER_INTERRUPT) > notify_ring(dev, &dev_priv->ring[VECS]); > + if (vcs & GEN8_GT_CONTEXT_SWITCH_INTERRUPT) > + DRM_DEBUG_DRIVER("TODO: Context switch\n"); > } else > DRM_ERROR("The master control interrupt lied (GT3)!\n"); > } > @@ -3768,12 +3776,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 | > + GEN8_GT_CONTEXT_SWITCH_INTERRUPT << GEN8_RCS_IRQ_SHIFT | > GT_RENDER_L3_PARITY_ERROR_INTERRUPT | > - GT_RENDER_USER_INTERRUPT << GEN8_BCS_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++) > diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h > index 70dddac..bfc0c01 100644 > --- a/drivers/gpu/drm/i915/i915_reg.h > +++ b/drivers/gpu/drm/i915/i915_reg.h > @@ -1062,6 +1062,7 @@ enum punit_power_well { > #define RING_ACTHD_UDW(base) ((base)+0x5c) > #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 > @@ -4590,6 +4591,8 @@ enum punit_power_well { > #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 > #define GEN8_VCS2_IRQ_SHIFT 16 > diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c > index c30518c..a6dcb3a 100644 > --- a/drivers/gpu/drm/i915/intel_lrc.c > +++ b/drivers/gpu/drm/i915/intel_lrc.c > @@ -343,6 +343,9 @@ static int gen8_init_common_ring(struct intel_engine_cs *ring) > struct drm_device *dev = ring->dev; > struct drm_i915_private *dev_priv = dev->dev_private; > > + I915_WRITE_IMR(ring, ~(ring->irq_enable_mask | ring->irq_keep_mask)); > + I915_WRITE(RING_HWSTAM(ring->mmio_base), 0xffffffff); > + > I915_WRITE(RING_MODE_GEN7(ring), > _MASKED_BIT_DISABLE(GFX_REPLAY_MODE) | > _MASKED_BIT_ENABLE(GFX_RUN_LIST_ENABLE)); > @@ -381,6 +384,39 @@ static int gen8_init_render_ring(struct intel_engine_cs *ring) > return ret; > } > > +static bool gen8_logical_ring_get_irq(struct intel_engine_cs *ring) > +{ > + struct drm_device *dev = ring->dev; > + struct drm_i915_private *dev_priv = dev->dev_private; > + unsigned long flags; > + > + if (!dev->irq_enabled) > + return false; > + > + spin_lock_irqsave(&dev_priv->irq_lock, flags); > + if (ring->irq_refcount++ == 0) { > + 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); > + > + return true; > +} > + > +static void gen8_logical_ring_put_irq(struct intel_engine_cs *ring) > +{ > + struct drm_device *dev = ring->dev; > + struct drm_i915_private *dev_priv = dev->dev_private; > + unsigned long flags; > + > + spin_lock_irqsave(&dev_priv->irq_lock, flags); > + if (--ring->irq_refcount == 0) { > + I915_WRITE_IMR(ring, ~ring->irq_keep_mask); > + POSTING_READ(RING_IMR(ring->mmio_base)); > + } > + spin_unlock_irqrestore(&dev_priv->irq_lock, flags); > +} > + > static int gen8_emit_flush(struct intel_ringbuffer *ringbuf, > u32 invalidate_domains, > u32 unused) > @@ -566,6 +602,10 @@ static int logical_render_ring_init(struct drm_device *dev) > ring->mmio_base = RENDER_RING_BASE; > ring->irq_enable_mask = > GT_RENDER_USER_INTERRUPT << GEN8_RCS_IRQ_SHIFT; > + ring->irq_keep_mask = > + GEN8_GT_CONTEXT_SWITCH_INTERRUPT << GEN8_RCS_IRQ_SHIFT; > + if (HAS_L3_DPF(dev)) > + ring->irq_keep_mask |= GT_RENDER_L3_PARITY_ERROR_INTERRUPT; > > ring->init = gen8_init_render_ring; > ring->cleanup = intel_fini_pipe_control; > @@ -573,6 +613,8 @@ static int logical_render_ring_init(struct drm_device *dev) > ring->set_seqno = gen8_set_seqno; > ring->emit_request = gen8_emit_request; > ring->emit_flush = gen8_emit_flush_render; > + ring->irq_get = gen8_logical_ring_get_irq; > + ring->irq_put = gen8_logical_ring_put_irq; > > return logical_ring_init(dev, ring); > } > @@ -587,12 +629,16 @@ static int logical_bsd_ring_init(struct drm_device *dev) > ring->mmio_base = GEN6_BSD_RING_BASE; > ring->irq_enable_mask = > GT_RENDER_USER_INTERRUPT << GEN8_VCS1_IRQ_SHIFT; > + ring->irq_keep_mask = > + GEN8_GT_CONTEXT_SWITCH_INTERRUPT << GEN8_VCS1_IRQ_SHIFT; > > ring->init = gen8_init_common_ring; > ring->get_seqno = gen8_get_seqno; > ring->set_seqno = gen8_set_seqno; > ring->emit_request = gen8_emit_request; > ring->emit_flush = gen8_emit_flush; > + ring->irq_get = gen8_logical_ring_get_irq; > + ring->irq_put = gen8_logical_ring_put_irq; > > return logical_ring_init(dev, ring); > } > @@ -607,12 +653,16 @@ static int logical_bsd2_ring_init(struct drm_device *dev) > ring->mmio_base = GEN8_BSD2_RING_BASE; > ring->irq_enable_mask = > GT_RENDER_USER_INTERRUPT << GEN8_VCS2_IRQ_SHIFT; > + ring->irq_keep_mask = > + GEN8_GT_CONTEXT_SWITCH_INTERRUPT << GEN8_VCS2_IRQ_SHIFT; > > ring->init = gen8_init_common_ring; > ring->get_seqno = gen8_get_seqno; > ring->set_seqno = gen8_set_seqno; > ring->emit_request = gen8_emit_request; > ring->emit_flush = gen8_emit_flush; > + ring->irq_get = gen8_logical_ring_get_irq; > + ring->irq_put = gen8_logical_ring_put_irq; > > return logical_ring_init(dev, ring); > } > @@ -627,12 +677,16 @@ static int logical_blt_ring_init(struct drm_device *dev) > ring->mmio_base = BLT_RING_BASE; > ring->irq_enable_mask = > GT_RENDER_USER_INTERRUPT << GEN8_BCS_IRQ_SHIFT; > + ring->irq_keep_mask = > + GEN8_GT_CONTEXT_SWITCH_INTERRUPT << GEN8_BCS_IRQ_SHIFT; > > ring->init = gen8_init_common_ring; > ring->get_seqno = gen8_get_seqno; > ring->set_seqno = gen8_set_seqno; > ring->emit_request = gen8_emit_request; > ring->emit_flush = gen8_emit_flush; > + ring->irq_get = gen8_logical_ring_get_irq; > + ring->irq_put = gen8_logical_ring_put_irq; > > return logical_ring_init(dev, ring); > } > @@ -647,12 +701,16 @@ static int logical_vebox_ring_init(struct drm_device *dev) > ring->mmio_base = VEBOX_RING_BASE; > ring->irq_enable_mask = > GT_RENDER_USER_INTERRUPT << GEN8_VECS_IRQ_SHIFT; > + ring->irq_keep_mask = > + GEN8_GT_CONTEXT_SWITCH_INTERRUPT << GEN8_VECS_IRQ_SHIFT; > > ring->init = gen8_init_common_ring; > ring->get_seqno = gen8_get_seqno; > ring->set_seqno = gen8_set_seqno; > ring->emit_request = gen8_emit_request; > ring->emit_flush = gen8_emit_flush; > + ring->irq_get = gen8_logical_ring_get_irq; > + ring->irq_put = gen8_logical_ring_put_irq; > > return logical_ring_init(dev, ring); > } > diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h > index 6e22866..09102b2 100644 > --- a/drivers/gpu/drm/i915/intel_ringbuffer.h > +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h > @@ -223,6 +223,7 @@ struct intel_engine_cs { > } semaphore; > > /* Execlists */ > + u32 irq_keep_mask; /* bitmask for interrupts that should not be masked */ > int (*emit_request)(struct intel_ringbuffer *ringbuf); > int (*emit_flush)(struct intel_ringbuffer *ringbuf, > u32 invalidate_domains, > -- > 1.7.9.5 > > _______________________________________________ > Intel-gfx mailing list > Intel-gfx@lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
On Thu, Jul 24, 2014 at 05:04:31PM +0100, Thomas Daniel wrote: > From: Oscar Mateo <oscar.mateo@intel.com> > > 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. > > v2: Disable HWSTAM, as suggested by Damien (nobody listens to these interrupts, > anyway). > > v3: Add new get/put_irq functions. > > Signed-off-by: Thomas Daniel <thomas.daniel@intel.com> (v1) > Signed-off-by: Oscar Mateo <oscar.mateo@intel.com> (v2 & v3) > --- > drivers/gpu/drm/i915/i915_irq.c | 19 ++++++++-- > drivers/gpu/drm/i915/i915_reg.h | 3 ++ > drivers/gpu/drm/i915/intel_lrc.c | 58 +++++++++++++++++++++++++++++++ > drivers/gpu/drm/i915/intel_ringbuffer.h | 1 + > 4 files changed, 78 insertions(+), 3 deletions(-) > > diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c > index a38b5c3..f77a4ca 100644 > --- a/drivers/gpu/drm/i915/i915_irq.c > +++ b/drivers/gpu/drm/i915/i915_irq.c > @@ -1643,6 +1643,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"); > } else > DRM_ERROR("The master control interrupt lied (GT0)!\n"); > } > @@ -1655,9 +1657,13 @@ 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"); > vcs = tmp >> GEN8_VCS2_IRQ_SHIFT; > if (vcs & GT_RENDER_USER_INTERRUPT) > notify_ring(dev, &dev_priv->ring[VCS2]); > + if (vcs & GEN8_GT_CONTEXT_SWITCH_INTERRUPT) > + DRM_DEBUG_DRIVER("TODO: Context switch\n"); > } else > DRM_ERROR("The master control interrupt lied (GT1)!\n"); > } > @@ -1681,6 +1687,8 @@ static irqreturn_t gen8_gt_irq_handler(struct drm_device *dev, > vcs = tmp >> GEN8_VECS_IRQ_SHIFT; > if (vcs & GT_RENDER_USER_INTERRUPT) > notify_ring(dev, &dev_priv->ring[VECS]); > + if (vcs & GEN8_GT_CONTEXT_SWITCH_INTERRUPT) > + DRM_DEBUG_DRIVER("TODO: Context switch\n"); > } else > DRM_ERROR("The master control interrupt lied (GT3)!\n"); > } > @@ -3768,12 +3776,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 | > + GEN8_GT_CONTEXT_SWITCH_INTERRUPT << GEN8_RCS_IRQ_SHIFT | > GT_RENDER_L3_PARITY_ERROR_INTERRUPT | > - GT_RENDER_USER_INTERRUPT << GEN8_BCS_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++) > diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h > index 70dddac..bfc0c01 100644 > --- a/drivers/gpu/drm/i915/i915_reg.h > +++ b/drivers/gpu/drm/i915/i915_reg.h > @@ -1062,6 +1062,7 @@ enum punit_power_well { > #define RING_ACTHD_UDW(base) ((base)+0x5c) > #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 > @@ -4590,6 +4591,8 @@ enum punit_power_well { > #define GEN8_GT_IIR(which) (0x44308 + (0x10 * (which))) > #define GEN8_GT_IER(which) (0x4430c + (0x10 * (which))) > > +#define GEN8_GT_CONTEXT_SWITCH_INTERRUPT (1 << 8) This looked misplaced - I've moved it to its brethren and dropped the GEN8_ prefix for consistency. -Daniel > + > #define GEN8_BCS_IRQ_SHIFT 16 > #define GEN8_RCS_IRQ_SHIFT 0 > #define GEN8_VCS2_IRQ_SHIFT 16 > diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c > index c30518c..a6dcb3a 100644 > --- a/drivers/gpu/drm/i915/intel_lrc.c > +++ b/drivers/gpu/drm/i915/intel_lrc.c > @@ -343,6 +343,9 @@ static int gen8_init_common_ring(struct intel_engine_cs *ring) > struct drm_device *dev = ring->dev; > struct drm_i915_private *dev_priv = dev->dev_private; > > + I915_WRITE_IMR(ring, ~(ring->irq_enable_mask | ring->irq_keep_mask)); > + I915_WRITE(RING_HWSTAM(ring->mmio_base), 0xffffffff); > + > I915_WRITE(RING_MODE_GEN7(ring), > _MASKED_BIT_DISABLE(GFX_REPLAY_MODE) | > _MASKED_BIT_ENABLE(GFX_RUN_LIST_ENABLE)); > @@ -381,6 +384,39 @@ static int gen8_init_render_ring(struct intel_engine_cs *ring) > return ret; > } > > +static bool gen8_logical_ring_get_irq(struct intel_engine_cs *ring) > +{ > + struct drm_device *dev = ring->dev; > + struct drm_i915_private *dev_priv = dev->dev_private; > + unsigned long flags; > + > + if (!dev->irq_enabled) > + return false; > + > + spin_lock_irqsave(&dev_priv->irq_lock, flags); > + if (ring->irq_refcount++ == 0) { > + 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); > + > + return true; > +} > + > +static void gen8_logical_ring_put_irq(struct intel_engine_cs *ring) > +{ > + struct drm_device *dev = ring->dev; > + struct drm_i915_private *dev_priv = dev->dev_private; > + unsigned long flags; > + > + spin_lock_irqsave(&dev_priv->irq_lock, flags); > + if (--ring->irq_refcount == 0) { > + I915_WRITE_IMR(ring, ~ring->irq_keep_mask); > + POSTING_READ(RING_IMR(ring->mmio_base)); > + } > + spin_unlock_irqrestore(&dev_priv->irq_lock, flags); > +} > + > static int gen8_emit_flush(struct intel_ringbuffer *ringbuf, > u32 invalidate_domains, > u32 unused) > @@ -566,6 +602,10 @@ static int logical_render_ring_init(struct drm_device *dev) > ring->mmio_base = RENDER_RING_BASE; > ring->irq_enable_mask = > GT_RENDER_USER_INTERRUPT << GEN8_RCS_IRQ_SHIFT; > + ring->irq_keep_mask = > + GEN8_GT_CONTEXT_SWITCH_INTERRUPT << GEN8_RCS_IRQ_SHIFT; > + if (HAS_L3_DPF(dev)) > + ring->irq_keep_mask |= GT_RENDER_L3_PARITY_ERROR_INTERRUPT; > > ring->init = gen8_init_render_ring; > ring->cleanup = intel_fini_pipe_control; > @@ -573,6 +613,8 @@ static int logical_render_ring_init(struct drm_device *dev) > ring->set_seqno = gen8_set_seqno; > ring->emit_request = gen8_emit_request; > ring->emit_flush = gen8_emit_flush_render; > + ring->irq_get = gen8_logical_ring_get_irq; > + ring->irq_put = gen8_logical_ring_put_irq; > > return logical_ring_init(dev, ring); > } > @@ -587,12 +629,16 @@ static int logical_bsd_ring_init(struct drm_device *dev) > ring->mmio_base = GEN6_BSD_RING_BASE; > ring->irq_enable_mask = > GT_RENDER_USER_INTERRUPT << GEN8_VCS1_IRQ_SHIFT; > + ring->irq_keep_mask = > + GEN8_GT_CONTEXT_SWITCH_INTERRUPT << GEN8_VCS1_IRQ_SHIFT; > > ring->init = gen8_init_common_ring; > ring->get_seqno = gen8_get_seqno; > ring->set_seqno = gen8_set_seqno; > ring->emit_request = gen8_emit_request; > ring->emit_flush = gen8_emit_flush; > + ring->irq_get = gen8_logical_ring_get_irq; > + ring->irq_put = gen8_logical_ring_put_irq; > > return logical_ring_init(dev, ring); > } > @@ -607,12 +653,16 @@ static int logical_bsd2_ring_init(struct drm_device *dev) > ring->mmio_base = GEN8_BSD2_RING_BASE; > ring->irq_enable_mask = > GT_RENDER_USER_INTERRUPT << GEN8_VCS2_IRQ_SHIFT; > + ring->irq_keep_mask = > + GEN8_GT_CONTEXT_SWITCH_INTERRUPT << GEN8_VCS2_IRQ_SHIFT; > > ring->init = gen8_init_common_ring; > ring->get_seqno = gen8_get_seqno; > ring->set_seqno = gen8_set_seqno; > ring->emit_request = gen8_emit_request; > ring->emit_flush = gen8_emit_flush; > + ring->irq_get = gen8_logical_ring_get_irq; > + ring->irq_put = gen8_logical_ring_put_irq; > > return logical_ring_init(dev, ring); > } > @@ -627,12 +677,16 @@ static int logical_blt_ring_init(struct drm_device *dev) > ring->mmio_base = BLT_RING_BASE; > ring->irq_enable_mask = > GT_RENDER_USER_INTERRUPT << GEN8_BCS_IRQ_SHIFT; > + ring->irq_keep_mask = > + GEN8_GT_CONTEXT_SWITCH_INTERRUPT << GEN8_BCS_IRQ_SHIFT; > > ring->init = gen8_init_common_ring; > ring->get_seqno = gen8_get_seqno; > ring->set_seqno = gen8_set_seqno; > ring->emit_request = gen8_emit_request; > ring->emit_flush = gen8_emit_flush; > + ring->irq_get = gen8_logical_ring_get_irq; > + ring->irq_put = gen8_logical_ring_put_irq; > > return logical_ring_init(dev, ring); > } > @@ -647,12 +701,16 @@ static int logical_vebox_ring_init(struct drm_device *dev) > ring->mmio_base = VEBOX_RING_BASE; > ring->irq_enable_mask = > GT_RENDER_USER_INTERRUPT << GEN8_VECS_IRQ_SHIFT; > + ring->irq_keep_mask = > + GEN8_GT_CONTEXT_SWITCH_INTERRUPT << GEN8_VECS_IRQ_SHIFT; > > ring->init = gen8_init_common_ring; > ring->get_seqno = gen8_get_seqno; > ring->set_seqno = gen8_set_seqno; > ring->emit_request = gen8_emit_request; > ring->emit_flush = gen8_emit_flush; > + ring->irq_get = gen8_logical_ring_get_irq; > + ring->irq_put = gen8_logical_ring_put_irq; > > return logical_ring_init(dev, ring); > } > diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h > index 6e22866..09102b2 100644 > --- a/drivers/gpu/drm/i915/intel_ringbuffer.h > +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h > @@ -223,6 +223,7 @@ struct intel_engine_cs { > } semaphore; > > /* Execlists */ > + u32 irq_keep_mask; /* bitmask for interrupts that should not be masked */ > int (*emit_request)(struct intel_ringbuffer *ringbuf); > int (*emit_flush)(struct intel_ringbuffer *ringbuf, > u32 invalidate_domains, > -- > 1.7.9.5 > > _______________________________________________ > Intel-gfx mailing list > Intel-gfx@lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index a38b5c3..f77a4ca 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1643,6 +1643,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"); } else DRM_ERROR("The master control interrupt lied (GT0)!\n"); } @@ -1655,9 +1657,13 @@ 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"); vcs = tmp >> GEN8_VCS2_IRQ_SHIFT; if (vcs & GT_RENDER_USER_INTERRUPT) notify_ring(dev, &dev_priv->ring[VCS2]); + if (vcs & GEN8_GT_CONTEXT_SWITCH_INTERRUPT) + DRM_DEBUG_DRIVER("TODO: Context switch\n"); } else DRM_ERROR("The master control interrupt lied (GT1)!\n"); } @@ -1681,6 +1687,8 @@ static irqreturn_t gen8_gt_irq_handler(struct drm_device *dev, vcs = tmp >> GEN8_VECS_IRQ_SHIFT; if (vcs & GT_RENDER_USER_INTERRUPT) notify_ring(dev, &dev_priv->ring[VECS]); + if (vcs & GEN8_GT_CONTEXT_SWITCH_INTERRUPT) + DRM_DEBUG_DRIVER("TODO: Context switch\n"); } else DRM_ERROR("The master control interrupt lied (GT3)!\n"); } @@ -3768,12 +3776,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 | + GEN8_GT_CONTEXT_SWITCH_INTERRUPT << GEN8_RCS_IRQ_SHIFT | GT_RENDER_L3_PARITY_ERROR_INTERRUPT | - GT_RENDER_USER_INTERRUPT << GEN8_BCS_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++) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 70dddac..bfc0c01 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1062,6 +1062,7 @@ enum punit_power_well { #define RING_ACTHD_UDW(base) ((base)+0x5c) #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 @@ -4590,6 +4591,8 @@ enum punit_power_well { #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 #define GEN8_VCS2_IRQ_SHIFT 16 diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index c30518c..a6dcb3a 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -343,6 +343,9 @@ static int gen8_init_common_ring(struct intel_engine_cs *ring) struct drm_device *dev = ring->dev; struct drm_i915_private *dev_priv = dev->dev_private; + I915_WRITE_IMR(ring, ~(ring->irq_enable_mask | ring->irq_keep_mask)); + I915_WRITE(RING_HWSTAM(ring->mmio_base), 0xffffffff); + I915_WRITE(RING_MODE_GEN7(ring), _MASKED_BIT_DISABLE(GFX_REPLAY_MODE) | _MASKED_BIT_ENABLE(GFX_RUN_LIST_ENABLE)); @@ -381,6 +384,39 @@ static int gen8_init_render_ring(struct intel_engine_cs *ring) return ret; } +static bool gen8_logical_ring_get_irq(struct intel_engine_cs *ring) +{ + struct drm_device *dev = ring->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + unsigned long flags; + + if (!dev->irq_enabled) + return false; + + spin_lock_irqsave(&dev_priv->irq_lock, flags); + if (ring->irq_refcount++ == 0) { + 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); + + return true; +} + +static void gen8_logical_ring_put_irq(struct intel_engine_cs *ring) +{ + struct drm_device *dev = ring->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + unsigned long flags; + + spin_lock_irqsave(&dev_priv->irq_lock, flags); + if (--ring->irq_refcount == 0) { + I915_WRITE_IMR(ring, ~ring->irq_keep_mask); + POSTING_READ(RING_IMR(ring->mmio_base)); + } + spin_unlock_irqrestore(&dev_priv->irq_lock, flags); +} + static int gen8_emit_flush(struct intel_ringbuffer *ringbuf, u32 invalidate_domains, u32 unused) @@ -566,6 +602,10 @@ static int logical_render_ring_init(struct drm_device *dev) ring->mmio_base = RENDER_RING_BASE; ring->irq_enable_mask = GT_RENDER_USER_INTERRUPT << GEN8_RCS_IRQ_SHIFT; + ring->irq_keep_mask = + GEN8_GT_CONTEXT_SWITCH_INTERRUPT << GEN8_RCS_IRQ_SHIFT; + if (HAS_L3_DPF(dev)) + ring->irq_keep_mask |= GT_RENDER_L3_PARITY_ERROR_INTERRUPT; ring->init = gen8_init_render_ring; ring->cleanup = intel_fini_pipe_control; @@ -573,6 +613,8 @@ static int logical_render_ring_init(struct drm_device *dev) ring->set_seqno = gen8_set_seqno; ring->emit_request = gen8_emit_request; ring->emit_flush = gen8_emit_flush_render; + ring->irq_get = gen8_logical_ring_get_irq; + ring->irq_put = gen8_logical_ring_put_irq; return logical_ring_init(dev, ring); } @@ -587,12 +629,16 @@ static int logical_bsd_ring_init(struct drm_device *dev) ring->mmio_base = GEN6_BSD_RING_BASE; ring->irq_enable_mask = GT_RENDER_USER_INTERRUPT << GEN8_VCS1_IRQ_SHIFT; + ring->irq_keep_mask = + GEN8_GT_CONTEXT_SWITCH_INTERRUPT << GEN8_VCS1_IRQ_SHIFT; ring->init = gen8_init_common_ring; ring->get_seqno = gen8_get_seqno; ring->set_seqno = gen8_set_seqno; ring->emit_request = gen8_emit_request; ring->emit_flush = gen8_emit_flush; + ring->irq_get = gen8_logical_ring_get_irq; + ring->irq_put = gen8_logical_ring_put_irq; return logical_ring_init(dev, ring); } @@ -607,12 +653,16 @@ static int logical_bsd2_ring_init(struct drm_device *dev) ring->mmio_base = GEN8_BSD2_RING_BASE; ring->irq_enable_mask = GT_RENDER_USER_INTERRUPT << GEN8_VCS2_IRQ_SHIFT; + ring->irq_keep_mask = + GEN8_GT_CONTEXT_SWITCH_INTERRUPT << GEN8_VCS2_IRQ_SHIFT; ring->init = gen8_init_common_ring; ring->get_seqno = gen8_get_seqno; ring->set_seqno = gen8_set_seqno; ring->emit_request = gen8_emit_request; ring->emit_flush = gen8_emit_flush; + ring->irq_get = gen8_logical_ring_get_irq; + ring->irq_put = gen8_logical_ring_put_irq; return logical_ring_init(dev, ring); } @@ -627,12 +677,16 @@ static int logical_blt_ring_init(struct drm_device *dev) ring->mmio_base = BLT_RING_BASE; ring->irq_enable_mask = GT_RENDER_USER_INTERRUPT << GEN8_BCS_IRQ_SHIFT; + ring->irq_keep_mask = + GEN8_GT_CONTEXT_SWITCH_INTERRUPT << GEN8_BCS_IRQ_SHIFT; ring->init = gen8_init_common_ring; ring->get_seqno = gen8_get_seqno; ring->set_seqno = gen8_set_seqno; ring->emit_request = gen8_emit_request; ring->emit_flush = gen8_emit_flush; + ring->irq_get = gen8_logical_ring_get_irq; + ring->irq_put = gen8_logical_ring_put_irq; return logical_ring_init(dev, ring); } @@ -647,12 +701,16 @@ static int logical_vebox_ring_init(struct drm_device *dev) ring->mmio_base = VEBOX_RING_BASE; ring->irq_enable_mask = GT_RENDER_USER_INTERRUPT << GEN8_VECS_IRQ_SHIFT; + ring->irq_keep_mask = + GEN8_GT_CONTEXT_SWITCH_INTERRUPT << GEN8_VECS_IRQ_SHIFT; ring->init = gen8_init_common_ring; ring->get_seqno = gen8_get_seqno; ring->set_seqno = gen8_set_seqno; ring->emit_request = gen8_emit_request; ring->emit_flush = gen8_emit_flush; + ring->irq_get = gen8_logical_ring_get_irq; + ring->irq_put = gen8_logical_ring_put_irq; return logical_ring_init(dev, ring); } diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 6e22866..09102b2 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -223,6 +223,7 @@ struct intel_engine_cs { } semaphore; /* Execlists */ + u32 irq_keep_mask; /* bitmask for interrupts that should not be masked */ int (*emit_request)(struct intel_ringbuffer *ringbuf); int (*emit_flush)(struct intel_ringbuffer *ringbuf, u32 invalidate_domains,