Starting from Gen9 we can use IA-Coherent caches. Coherence may be not required in certain cases and can be disabled in an easy way. To do this we can set HDC_FORCE_NON_COHERENT bit in HDC_CHICKEN0 register. This register is part of HW context, however it is private and cannot be programmed from non-privileged batch buffer. New parameter is to override default programming and allow UMD to decide whether IA-Coherency is not needed for submitted batch buffer. When flag is set KMD emits commands to disable coherency before batch buffer execution starts. After execution finished state is restored. When WaForceEnableNonCoherent is programmed, it does not make sense to allow for coherency because this can lead to GPU hangs. In such situation flag is ignored. Signed-off-by: Artur Harasimiuk <artur.harasimiuk@xxxxxxxxx> --- drivers/gpu/drm/i915/i915_dma.c | 3 +++ drivers/gpu/drm/i915/i915_drv.h | 4 ++++ drivers/gpu/drm/i915/i915_gem_execbuffer.c | 8 ++++++++ drivers/gpu/drm/i915/intel_lrc.c | 28 ++++++++++++++++++++++++++++ drivers/gpu/drm/i915/intel_ringbuffer.c | 7 +++++++ include/uapi/drm/i915_drm.h | 8 +++++++- 6 files changed, 57 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 44a896c..79ecf20 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -172,6 +172,9 @@ static int i915_getparam(struct drm_device *dev, void *data, case I915_PARAM_HAS_EXEC_SOFTPIN: value = 1; break; + case I915_PARAM_HAS_EXEC_FORCE_NON_COHERENT: + value = INTEL_INFO(dev)->gen >= 9; + break; default: DRM_DEBUG("Unknown parameter %d\n", param->param); return -EINVAL; diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 104bd18..71d739c 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -886,6 +886,10 @@ struct intel_context { } engine[I915_NUM_RINGS]; struct list_head link; + + struct { + unsigned int WaForceEnableNonCoherent:1; + } wa; }; enum fb_op_origin { diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index d469c47..2997a58 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -1400,6 +1400,10 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, if (!i915_gem_check_execbuffer(args)) return -EINVAL; + if ((args->flags & I915_EXEC_FORCE_NON_COHERENT) && + INTEL_INFO(dev)->gen < 9) + return -EINVAL; + ret = validate_exec_list(dev, exec, args->buffer_count); if (ret) return ret; @@ -1494,6 +1498,10 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, i915_gem_context_reference(ctx); + /* Clear this flag when WA is programmed */ + if (ctx->wa.WaForceEnableNonCoherent) + args->flags &= ~I915_EXEC_FORCE_NON_COHERENT; + if (ctx->ppgtt) vm = &ctx->ppgtt->base; else diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index ab344e0..4482a6a 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -879,6 +879,24 @@ int intel_logical_ring_reserve_space(struct drm_i915_gem_request *request) return intel_logical_ring_begin(request, 0); } +static inline void +intel_lr_emit_force_non_coherent(struct i915_execbuffer_params *params, + struct drm_i915_gem_execbuffer2 *args, bool force) +{ + if (args->flags & I915_EXEC_FORCE_NON_COHERENT) { + struct intel_ringbuffer *ringbuf = + params->ctx->engine[params->ring->id].ringbuf; + + intel_logical_ring_emit(ringbuf, MI_NOOP); + intel_logical_ring_emit(ringbuf, MI_LOAD_REGISTER_IMM(1)); + intel_logical_ring_emit(ringbuf, HDC_CHICKEN0.reg); + intel_logical_ring_emit(ringbuf, force ? + _MASKED_BIT_ENABLE(HDC_FORCE_NON_COHERENT) : + _MASKED_BIT_DISABLE(HDC_FORCE_NON_COHERENT)); + intel_logical_ring_advance(ringbuf); + } +} + /** * execlists_submission() - submit a batchbuffer for execution, Execlists style * @dev: DRM device. @@ -959,6 +977,8 @@ int intel_execlists_submission(struct i915_execbuffer_params *params, dev_priv->relative_constants_mode = instp_mode; } + intel_lr_emit_force_non_coherent(params, args, true); + exec_start = params->batch_obj_vm_offset + args->batch_start_offset; @@ -966,6 +986,8 @@ int intel_execlists_submission(struct i915_execbuffer_params *params, if (ret) return ret; + intel_lr_emit_force_non_coherent(params, args, false); + trace_i915_gem_ring_dispatch(params->request, params->dispatch_flags); i915_gem_execbuffer_move_to_active(vmas, params->request); @@ -1112,6 +1134,9 @@ static int intel_logical_ring_workarounds_emit(struct drm_i915_gem_request *req) struct drm_device *dev = ring->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct i915_workarounds *w = &dev_priv->workarounds; + struct intel_context *ctx = req->ctx; + + ctx->wa.WaForceEnableNonCoherent = 0; if (w->count == 0) return 0; @@ -1129,6 +1154,9 @@ static int intel_logical_ring_workarounds_emit(struct drm_i915_gem_request *req) for (i = 0; i < w->count; i++) { intel_logical_ring_emit_reg(ringbuf, w->reg[i].addr); intel_logical_ring_emit(ringbuf, w->reg[i].value); + ctx->wa.WaForceEnableNonCoherent |= + (w->reg[i].addr.reg == HDC_CHICKEN0.reg) && + (w->reg[i].value & HDC_FORCE_NON_COHERENT); } intel_logical_ring_emit(ringbuf, MI_NOOP); diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 4060acf..a7e1f24 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -702,6 +702,9 @@ static int intel_ring_workarounds_emit(struct drm_i915_gem_request *req) struct drm_device *dev = ring->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct i915_workarounds *w = &dev_priv->workarounds; + struct intel_context *ctx = req->ctx; + + ctx->wa.WaForceEnableNonCoherent = 0; if (w->count == 0) return 0; @@ -719,6 +722,10 @@ static int intel_ring_workarounds_emit(struct drm_i915_gem_request *req) for (i = 0; i < w->count; i++) { intel_ring_emit_reg(ring, w->reg[i].addr); intel_ring_emit(ring, w->reg[i].value); + ctx->wa.WaForceEnableNonCoherent |= + (w->reg[i].addr.reg == HDC_CHICKEN0.reg) && + (w->reg[i].value & HDC_FORCE_NON_COHERENT); + } intel_ring_emit(ring, MI_NOOP); diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h index acf2102..c425e80 100644 --- a/include/uapi/drm/i915_drm.h +++ b/include/uapi/drm/i915_drm.h @@ -357,6 +357,7 @@ typedef struct drm_i915_irq_wait { #define I915_PARAM_HAS_GPU_RESET 35 #define I915_PARAM_HAS_RESOURCE_STREAMER 36 #define I915_PARAM_HAS_EXEC_SOFTPIN 37 +#define I915_PARAM_HAS_EXEC_FORCE_NON_COHERENT 38 typedef struct drm_i915_getparam { __s32 param; @@ -782,7 +783,12 @@ struct drm_i915_gem_execbuffer2 { */ #define I915_EXEC_RESOURCE_STREAMER (1<<15) -#define __I915_EXEC_UNKNOWN_FLAGS -(I915_EXEC_RESOURCE_STREAMER<<1) +/** + * Tell the kernel that the batch buffer requires to disable IA-Coherency + */ +#define I915_EXEC_FORCE_NON_COHERENT (1<<16) + +#define __I915_EXEC_UNKNOWN_FLAGS -(I915_EXEC_FORCE_NON_COHERENT<<1) #define I915_EXEC_CONTEXT_ID_MASK (0xffffffff) #define i915_execbuffer2_set_context_id(eb2, context) \ -- 1.9.1 _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/intel-gfx