[Intel-gfx] [PATCH v3] drm/i915: Consider HW CSB write pointer before resetting the sw read pointer

Daniel Vetter daniel at ffwll.ch
Mon Sep 28 07:12:03 PDT 2015


On Mon, Sep 28, 2015 at 05:00:12PM +0300, Mika Kuoppala wrote:
> Michel Thierry <michel.thierry at intel.com> writes:
> 
> > A previous commit resets the Context Status Buffer (CSB) read pointer in
> > ring init
> >     commit c0a03a2e4c4e ("drm/i915: Reset CSB read pointer in ring init")

This is in 4.0, so Cc: stable at vger.kernel.org and one for Jani.
-Daniel

> >
> > This is generally correct, but this pointer is not reset after
> > suspend/resume in some platforms (cht). In this case, the driver should
> > read the register value instead of resetting the sw read counter to 0.
> > Otherwise we process old events, leading to unwanted pre-emptions or
> > something worse.
> >
> > But in other platforms (bdw) and also during GPU reset or power up, the
> > CSBWP is reset to 0x7 (an invalid number), and in this case the read
> > pointer should be set to 5 (the interrupt code will increment this
> > counter one more time, and will start reading from CSB[0]).
> >
> > v2: When the CSB registers are reset, the read pointer needs to be set
> > to 5, otherwise the first write (CSB[0]) won't be read (Mika).
> > Replace magic numbers with GEN8_CSB_ENTRIES (6) and GEN8_CSB_PTR_MASK
> > (0x07).
> > v3: Rebased on top of "Parametrize LRC registers" patch.
> >
> > Cc: Mika Kuoppala <mika.kuoppala at linux.intel.com>
> > Signed-off-by: Lei Shen <lei.shen at intel.com>
> > Signed-off-by: Deepak S <deepak.s at intel.com>
> > Signed-off-by: Michel Thierry <michel.thierry at intel.com>
> > ---
> >  drivers/gpu/drm/i915/intel_lrc.c | 39 ++++++++++++++++++++++++++++++++-------
> >  drivers/gpu/drm/i915/intel_lrc.h |  2 ++
> >  2 files changed, 34 insertions(+), 7 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
> > index 256167b..825fa7a 100644
> > --- a/drivers/gpu/drm/i915/intel_lrc.c
> > +++ b/drivers/gpu/drm/i915/intel_lrc.c
> > @@ -511,16 +511,16 @@ void intel_lrc_irq_handler(struct intel_engine_cs *ring)
> >  	status_pointer = I915_READ(RING_CONTEXT_STATUS_PTR(ring));
> >  
> >  	read_pointer = ring->next_context_status_buffer;
> > -	write_pointer = status_pointer & 0x07;
> > +	write_pointer = status_pointer & GEN8_CSB_PTR_MASK;
> >  	if (read_pointer > write_pointer)
> > -		write_pointer += 6;
> > +		write_pointer += GEN8_CSB_ENTRIES;
> >  
> >  	spin_lock(&ring->execlist_lock);
> >  
> >  	while (read_pointer < write_pointer) {
> >  		read_pointer++;
> > -		status = I915_READ(RING_CONTEXT_STATUS_BUF_LO(ring, read_pointer % 6));
> > -		status_id = I915_READ(RING_CONTEXT_STATUS_BUF_HI(ring, read_pointer % 6));
> > +		status = I915_READ(RING_CONTEXT_STATUS_BUF_LO(ring, read_pointer % GEN8_CSB_ENTRIES));
> > +		status_id = I915_READ(RING_CONTEXT_STATUS_BUF_HI(ring, read_pointer % GEN8_CSB_ENTRIES));
> >  
> >  		if (status & GEN8_CTX_STATUS_IDLE_ACTIVE)
> >  			continue;
> > @@ -552,10 +552,12 @@ void intel_lrc_irq_handler(struct intel_engine_cs *ring)
> >  	spin_unlock(&ring->execlist_lock);
> >  
> >  	WARN(submit_contexts > 2, "More than two context complete events?\n");
> > -	ring->next_context_status_buffer = write_pointer % 6;
> > +	ring->next_context_status_buffer = write_pointer % GEN8_CSB_ENTRIES;
> >  
> >  	I915_WRITE(RING_CONTEXT_STATUS_PTR(ring),
> > -		   _MASKED_FIELD(0x07 << 8, ((u32)ring->next_context_status_buffer & 0x07) << 8));
> > +		   _MASKED_FIELD(GEN8_CSB_PTR_MASK << 8,
> > +				 ((u32)ring->next_context_status_buffer &
> > +				  GEN8_CSB_PTR_MASK) << 8));
> >  }
> >  
> >  static int execlists_context_queue(struct drm_i915_gem_request *request)
> > @@ -1477,6 +1479,7 @@ 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;
> > +	u8 next_context_status_buffer_hw;
> >  
> >  	lrc_setup_hardware_status_page(ring,
> >  				ring->default_context->engine[ring->id].state);
> > @@ -1494,7 +1497,29 @@ static int gen8_init_common_ring(struct intel_engine_cs *ring)
> >  		   _MASKED_BIT_DISABLE(GFX_REPLAY_MODE) |
> >  		   _MASKED_BIT_ENABLE(GFX_RUN_LIST_ENABLE));
> >  	POSTING_READ(RING_MODE_GEN7(ring));
> > -	ring->next_context_status_buffer = 0;
> > +
> > +	/*
> > +	 * Instead of resetting the Context Status Buffer (CSB) read pointer to
> > +	 * zero, we need to read the write pointer from hardware and use its
> > +	 * value because "this register is power context save restored".
> > +	 * Effectively, these states have been observed:
> > +	 *
> > +	 *      | Suspend-to-idle (freeze) | Suspend-to-RAM (mem) |
> > +	 * BDW  | CSB regs not reset       | CSB regs reset       |
> > +	 * CHT  | CSB regs not reset       | CSB regs not reset   |
> > +	 */
> 
> SKL acts similar to BDW.
> 
> > +	next_context_status_buffer_hw = (I915_READ(RING_CONTEXT_STATUS_PTR(ring))
> > +						   & GEN8_CSB_PTR_MASK);
> > +
> > +	/*
> > +	 * When the CSB registers are reset (also after power-up / gpu reset),
> > +	 * CSB write pointer is set to all 1's, which is not valid, use '5' in
> > +	 * this special case, so the first element read is CSB[0].
> > +	 */
> > +	if (next_context_status_buffer_hw == GEN8_CSB_PTR_MASK)
> > +		next_context_status_buffer_hw = (GEN8_CSB_ENTRIES - 1);
> > +
> 
> Now that this has been unravelled, I hope we can move towards
> of removing the driver state of next context buffer completely:
> 
> http://lists.freedesktop.org/archives/intel-gfx/2015-May/067313.html
> 
> Reviewed-by: Mika Kuoppala <mika.kuoppala at intel.com>
> 
> > +	ring->next_context_status_buffer = next_context_status_buffer_hw;
> >  	DRM_DEBUG_DRIVER("Execlists enabled for %s\n", ring->name);
> >  
> >  	memset(&ring->hangcheck, 0, sizeof(ring->hangcheck));
> > diff --git a/drivers/gpu/drm/i915/intel_lrc.h b/drivers/gpu/drm/i915/intel_lrc.h
> > index 8a08a27..4e60d54 100644
> > --- a/drivers/gpu/drm/i915/intel_lrc.h
> > +++ b/drivers/gpu/drm/i915/intel_lrc.h
> > @@ -25,6 +25,8 @@
> >  #define _INTEL_LRC_H_
> >  
> >  #define GEN8_LR_CONTEXT_ALIGN 4096
> > +#define GEN8_CSB_ENTRIES 6
> > +#define GEN8_CSB_PTR_MASK 0x07
> >  
> >  /* Execlists regs */
> >  #define RING_ELSP(ring)			((ring)->mmio_base+0x230)
> > -- 
> > 2.5.3
> 
> 
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch


More information about the Intel-gfx mailing list