From: Jeff McGee <jeff.mcgee@xxxxxxxxx> In the next patch we are improving how we find the active request on an engine with a pending preemption. We need to know if the preemption has completed or not. This determination can be made most robustly by having the preemption context write a preemption finished indicator to the hardware status page. This patch is required to support the force preemption feature. Change-Id: I4123283aec02e21d13c7cb55f329cf3f553b5d2c Signed-off-by: Jeff McGee <jeff.mcgee@xxxxxxxxx> --- drivers/gpu/drm/i915/intel_lrc.c | 27 ++++++++++++++++++++++++--- drivers/gpu/drm/i915/intel_ringbuffer.h | 14 +++++++++++++- 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 5f63d1d6a2d6..b2f838c484b0 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -512,19 +512,37 @@ static void port_assign(struct execlist_port *port, port_set(port, port_pack(i915_gem_request_get(rq), port_count(port))); } +#define PREEMPT_BREADCRUMB_DWORDS 0x8 static void inject_preempt_context(struct intel_engine_cs *engine) { struct intel_context *ce = &engine->i915->preempt_context->engine[engine->id]; + u32 *cs = ce->ring->vaddr + ce->ring->tail; u32 __iomem *elsp = engine->i915->regs + i915_mmio_reg_offset(RING_ELSP(engine)); unsigned int n; GEM_BUG_ON(engine->i915->preempt_context->hw_id != PREEMPT_ID); - GEM_BUG_ON(!IS_ALIGNED(ce->ring->size, WA_TAIL_BYTES)); + GEM_BUG_ON(intel_engine_preempt_finished(engine)); - memset(ce->ring->vaddr + ce->ring->tail, 0, WA_TAIL_BYTES); - ce->ring->tail += WA_TAIL_BYTES; + if (engine->id == RCS) { + cs = gen8_emit_ggtt_write_rcs(cs, I915_GEM_HWS_PREEMPT_FINISHED, + intel_hws_preempt_done_address(engine)); + } else { + cs = gen8_emit_ggtt_write(cs, I915_GEM_HWS_PREEMPT_FINISHED, + intel_hws_preempt_done_address(engine)); + *cs++ = MI_NOOP; + *cs++ = MI_NOOP; + } + *cs++ = MI_NOOP; + *cs++ = MI_NOOP; + + GEM_BUG_ON(!IS_ALIGNED(ce->ring->size, + PREEMPT_BREADCRUMB_DWORDS * sizeof(u32))); + GEM_BUG_ON((void *)cs - (ce->ring->vaddr + ce->ring->tail) != + PREEMPT_BREADCRUMB_DWORDS * sizeof(u32)); + + ce->ring->tail += PREEMPT_BREADCRUMB_DWORDS * sizeof(u32); ce->ring->tail &= (ce->ring->size - 1); ce->lrc_reg_state[CTX_RING_TAIL+1] = ce->ring->tail; @@ -911,6 +929,8 @@ static void intel_lrc_irq_handler(unsigned long data) EXECLISTS_ACTIVE_PREEMPT)); execlists_clear_active(execlists, EXECLISTS_ACTIVE_PREEMPT); + GEM_BUG_ON(!intel_engine_preempt_finished(engine)); + intel_engine_clear_preempt(engine); continue; } @@ -1507,6 +1527,7 @@ static int gen8_init_common_ring(struct intel_engine_cs *engine) execlists->csb_head = -1; execlists->active = 0; + intel_engine_clear_preempt(engine); /* After a GPU reset, we may have requests to replay */ if (!i915_modparams.enable_guc_submission && execlists->first) diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 5b9117b3cba4..25eb23bc06eb 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -625,11 +625,12 @@ intel_write_status_page(struct intel_engine_cs *engine, int reg, u32 value) #define I915_GEM_HWS_INDEX_ADDR (I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT) #define I915_GEM_HWS_PREEMPT_INDEX 0x32 #define I915_GEM_HWS_PREEMPT_ADDR (I915_GEM_HWS_PREEMPT_INDEX << MI_STORE_DWORD_INDEX_SHIFT) +#define I915_GEM_HWS_PREEMPT_FINISHED 1 #define I915_GEM_HWS_PID_INDEX 0x40 #define I915_GEM_HWS_PID_ADDR (I915_GEM_HWS_PID_INDEX << MI_STORE_DWORD_INDEX_SHIFT) #define I915_GEM_HWS_CID_INDEX 0x48 #define I915_GEM_HWS_CID_ADDR (I915_GEM_HWS_CID_INDEX << MI_STORE_DWORD_INDEX_SHIFT) -#define I915_GEM_HWS_SCRATCH_INDEX 0x50 +#define I915_GEM_HWS_SCRATCH_INDEX 0x58 #define I915_GEM_HWS_SCRATCH_ADDR (I915_GEM_HWS_SCRATCH_INDEX << MI_STORE_DWORD_INDEX_SHIFT) #define I915_HWS_CSB_BUF0_INDEX 0x10 @@ -749,6 +750,17 @@ static inline u32 intel_engine_get_seqno(struct intel_engine_cs *engine) return intel_read_status_page(engine, I915_GEM_HWS_INDEX); } +static inline bool intel_engine_preempt_finished(struct intel_engine_cs *engine) +{ + return (intel_read_status_page(engine, I915_GEM_HWS_PREEMPT_INDEX) == + I915_GEM_HWS_PREEMPT_FINISHED); +} + +static inline void intel_engine_clear_preempt(struct intel_engine_cs *engine) +{ + intel_write_status_page(engine, I915_GEM_HWS_PREEMPT_INDEX, 0); +} + static inline u32 intel_engine_last_submit(struct intel_engine_cs *engine) { /* We are only peeking at the tail of the submit queue (and not the -- 2.16.2 _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/intel-gfx