@@ -767,7 +767,7 @@ static struct i915_vma *
i915_window_vma_init(struct drm_i915_private *i915,
struct intel_memory_region *mem)
{
- struct intel_context *ce = i915->gt.engine[BCS0]->blitter_context;
+ struct intel_context *ce = i915->gt.engine[BCS0]->evict_context;
struct i915_address_space *vm = ce->vm;
struct i915_vma *vma;
int ret;
@@ -984,7 +984,7 @@ int i915_window_blt_copy(struct drm_i915_gem_object *dst,
struct drm_i915_gem_object *src)
{
struct drm_i915_private *i915 = to_i915(src->base.dev);
- struct intel_context *ce = i915->gt.engine[BCS0]->blitter_context;
+ struct intel_context *ce = i915->gt.engine[BCS0]->evict_context;
bool src_is_lmem = i915_gem_object_is_lmem(src);
bool dst_is_lmem = i915_gem_object_is_lmem(dst);
u64 remain = src->base.size, offset = 0;
@@ -188,6 +188,8 @@ intel_write_status_page(struct intel_engine_cs *engine, int reg, u32 value)
#define I915_GEM_HWS_SEQNO_ADDR (I915_GEM_HWS_SEQNO * sizeof(u32))
#define I915_GEM_HWS_BLITTER 0x42
#define I915_GEM_HWS_BLITTER_ADDR (I915_GEM_HWS_BLITTER * sizeof(u32))
+#define I915_GEM_HWS_EVICT 0x44
+#define I915_GEM_HWS_EVICT_ADDR (I915_GEM_HWS_EVICT * sizeof(u32))
#define I915_GEM_HWS_SCRATCH 0x80
#define I915_HWS_CSB_BUF0_INDEX 0x10
@@ -874,6 +874,20 @@ create_blitter_context(struct intel_engine_cs *engine)
return ce;
}
+static struct intel_context *
+create_evict_context(struct intel_engine_cs *engine)
+{
+ static struct lock_class_key evict;
+ struct intel_context *ce;
+
+ ce = create_pinned_context(engine, I915_GEM_HWS_EVICT_ADDR, &evict,
+ "evict_context");
+ if (IS_ERR(ce))
+ return ce;
+
+ return ce;
+}
+
/**
* intel_engines_init_common - initialize cengine state which might require hw access
* @engine: Engine to initialize.
@@ -912,22 +926,35 @@ static int engine_init_common(struct intel_engine_cs *engine)
engine->emit_fini_breadcrumb_dw = ret;
/*
- * The blitter context is used to quickly memset or migrate objects
- * in local memory, so it has to always be available.
+ * The blitter and evict contexts are used to clear and migrate objects
+ * in local memory so they have to always be available.
*/
if (engine->class == COPY_ENGINE_CLASS) {
ce = create_blitter_context(engine);
if (IS_ERR(ce)) {
ret = PTR_ERR(ce);
- goto err_unpin;
+ goto err_blitter;
}
engine->blitter_context = ce;
+
+ if (HAS_LMEM(engine->i915)) {
+ ce = create_evict_context(engine);
+ if (IS_ERR(ce)) {
+ ret = PTR_ERR(ce);
+ goto err_evict;
+ }
+
+ engine->evict_context = ce;
+ }
}
return 0;
-err_unpin:
+err_evict:
+ intel_context_unpin(engine->blitter_context);
+ intel_context_put(engine->blitter_context);
+err_blitter:
intel_context_unpin(engine->kernel_context);
err_context:
intel_context_put(engine->kernel_context);
@@ -986,6 +1013,11 @@ void intel_engine_cleanup_common(struct intel_engine_cs *engine)
if (engine->default_state)
fput(engine->default_state);
+ if (engine->evict_context) {
+ intel_context_unpin(engine->evict_context);
+ intel_context_put(engine->evict_context);
+ }
+
if (engine->blitter_context) {
intel_context_unpin(engine->blitter_context);
intel_context_put(engine->blitter_context);
@@ -66,10 +66,13 @@ static int __engine_unpark(struct intel_wakeref *wf)
ce->ops->reset(ce);
}
- if (engine->class == COPY_ENGINE_CLASS) {
- ce = engine->blitter_context;
+ ce = engine->blitter_context;
+ if (ce)
+ ce->ops->reset(ce);
+
+ ce = engine->evict_context;
+ if (ce)
ce->ops->reset(ce);
- }
if (engine->unpark)
engine->unpark(engine);
@@ -348,6 +348,7 @@ struct intel_engine_cs {
struct intel_context *kernel_context; /* pinned */
struct intel_context *blitter_context; /* pinned; exists for BCS only */
+ struct intel_context *evict_context; /* pinned; exists for BCS only */
intel_engine_mask_t saturated; /* submitting semaphores too late? */