Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fe78742d authored by Chris Wilson's avatar Chris Wilson Committed by Joonas Lahtinen
Browse files

drm/i915: Allocate a common scratch page

Currently we allocate a scratch page for each engine, but since we only
ever write into it for post-sync operations, it is not exposed to
userspace nor do we care for coherency. As we then do not care about its
contents, we can use one page for all, reducing our allocations and
avoid complications by not assuming per-engine isolation.

For later use, it simplifies engine initialisation (by removing the
allocation that required struct_mutex!) and means that we can always rely
on there being a scratch page.

v2: Check that we allocated a large enough scratch for I830 w/a

Fixes: 06e562e7f515 ("drm/i915/ringbuffer: Delay after EMIT_INVALIDATE for gen4/gen5") # v4.18.20
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=108850


Signed-off-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Reviewed-by: default avatarMika Kuoppala <mika.kuoppala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20181204141522.13640-1-chris@chris-wilson.co.uk


Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Cc: <stable@vger.kernel.org> # v4.18.20+
(cherry picked from commit 51797499)
[Joonas: Use new function in gen9_init_indirectctx_bb too]
Signed-off-by: default avatarJoonas Lahtinen <joonas.lahtinen@linux.intel.com>
parent cf66b8a0
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -2150,6 +2150,8 @@ struct drm_i915_private {
		struct delayed_work idle_work;

		ktime_t last_init_time;

		struct i915_vma *scratch;
	} gt;

	/* perform PHY state sanity checks? */
@@ -3872,4 +3874,9 @@ static inline int intel_hws_csb_write_index(struct drm_i915_private *i915)
		return I915_HWS_CSB_WRITE_INDEX;
}

static inline u32 i915_scratch_offset(const struct drm_i915_private *i915)
{
	return i915_ggtt_offset(i915->gt.scratch);
}

#endif
+49 −1
Original line number Diff line number Diff line
@@ -5500,6 +5500,44 @@ static int __intel_engines_record_defaults(struct drm_i915_private *i915)
	goto out_ctx;
}

static int
i915_gem_init_scratch(struct drm_i915_private *i915, unsigned int size)
{
	struct drm_i915_gem_object *obj;
	struct i915_vma *vma;
	int ret;

	obj = i915_gem_object_create_stolen(i915, size);
	if (!obj)
		obj = i915_gem_object_create_internal(i915, size);
	if (IS_ERR(obj)) {
		DRM_ERROR("Failed to allocate scratch page\n");
		return PTR_ERR(obj);
	}

	vma = i915_vma_instance(obj, &i915->ggtt.vm, NULL);
	if (IS_ERR(vma)) {
		ret = PTR_ERR(vma);
		goto err_unref;
	}

	ret = i915_vma_pin(vma, 0, 0, PIN_GLOBAL | PIN_HIGH);
	if (ret)
		goto err_unref;

	i915->gt.scratch = vma;
	return 0;

err_unref:
	i915_gem_object_put(obj);
	return ret;
}

static void i915_gem_fini_scratch(struct drm_i915_private *i915)
{
	i915_vma_unpin_and_release(&i915->gt.scratch, 0);
}

int i915_gem_init(struct drm_i915_private *dev_priv)
{
	int ret;
@@ -5546,12 +5584,19 @@ int i915_gem_init(struct drm_i915_private *dev_priv)
		goto err_unlock;
	}

	ret = i915_gem_contexts_init(dev_priv);
	ret = i915_gem_init_scratch(dev_priv,
				    IS_GEN2(dev_priv) ? SZ_256K : PAGE_SIZE);
	if (ret) {
		GEM_BUG_ON(ret == -EIO);
		goto err_ggtt;
	}

	ret = i915_gem_contexts_init(dev_priv);
	if (ret) {
		GEM_BUG_ON(ret == -EIO);
		goto err_scratch;
	}

	ret = intel_engines_init(dev_priv);
	if (ret) {
		GEM_BUG_ON(ret == -EIO);
@@ -5624,6 +5669,8 @@ int i915_gem_init(struct drm_i915_private *dev_priv)
err_context:
	if (ret != -EIO)
		i915_gem_contexts_fini(dev_priv);
err_scratch:
	i915_gem_fini_scratch(dev_priv);
err_ggtt:
err_unlock:
	intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
@@ -5675,6 +5722,7 @@ void i915_gem_fini(struct drm_i915_private *dev_priv)
	intel_uc_fini(dev_priv);
	i915_gem_cleanup_engines(dev_priv);
	i915_gem_contexts_fini(dev_priv);
	i915_gem_fini_scratch(dev_priv);
	mutex_unlock(&dev_priv->drm.struct_mutex);

	intel_wa_list_free(&dev_priv->gt_wa_list);
+1 −1
Original line number Diff line number Diff line
@@ -1495,7 +1495,7 @@ static void gem_record_rings(struct i915_gpu_state *error)
			if (HAS_BROKEN_CS_TLB(i915))
				ee->wa_batchbuffer =
					i915_error_object_create(i915,
								 engine->scratch);
								 i915->gt.scratch);
			request_record_user_bo(request, ee);

			ee->ctx =
+0 −42
Original line number Diff line number Diff line
@@ -490,46 +490,6 @@ void intel_engine_setup_common(struct intel_engine_cs *engine)
	intel_engine_init_cmd_parser(engine);
}

int intel_engine_create_scratch(struct intel_engine_cs *engine,
				unsigned int size)
{
	struct drm_i915_gem_object *obj;
	struct i915_vma *vma;
	int ret;

	WARN_ON(engine->scratch);

	obj = i915_gem_object_create_stolen(engine->i915, size);
	if (!obj)
		obj = i915_gem_object_create_internal(engine->i915, size);
	if (IS_ERR(obj)) {
		DRM_ERROR("Failed to allocate scratch page\n");
		return PTR_ERR(obj);
	}

	vma = i915_vma_instance(obj, &engine->i915->ggtt.vm, NULL);
	if (IS_ERR(vma)) {
		ret = PTR_ERR(vma);
		goto err_unref;
	}

	ret = i915_vma_pin(vma, 0, 0, PIN_GLOBAL | PIN_HIGH);
	if (ret)
		goto err_unref;

	engine->scratch = vma;
	return 0;

err_unref:
	i915_gem_object_put(obj);
	return ret;
}

void intel_engine_cleanup_scratch(struct intel_engine_cs *engine)
{
	i915_vma_unpin_and_release(&engine->scratch, 0);
}

static void cleanup_status_page(struct intel_engine_cs *engine)
{
	if (HWS_NEEDS_PHYSICAL(engine->i915)) {
@@ -704,8 +664,6 @@ void intel_engine_cleanup_common(struct intel_engine_cs *engine)
{
	struct drm_i915_private *i915 = engine->i915;

	intel_engine_cleanup_scratch(engine);

	cleanup_status_page(engine);

	intel_engine_fini_breadcrumbs(engine);
+6 −13
Original line number Diff line number Diff line
@@ -1448,9 +1448,10 @@ static int execlists_request_alloc(struct i915_request *request)
static u32 *
gen8_emit_flush_coherentl3_wa(struct intel_engine_cs *engine, u32 *batch)
{
	/* NB no one else is allowed to scribble over scratch + 256! */
	*batch++ = MI_STORE_REGISTER_MEM_GEN8 | MI_SRM_LRM_GLOBAL_GTT;
	*batch++ = i915_mmio_reg_offset(GEN8_L3SQCREG4);
	*batch++ = i915_ggtt_offset(engine->scratch) + 256;
	*batch++ = i915_scratch_offset(engine->i915) + 256;
	*batch++ = 0;

	*batch++ = MI_LOAD_REGISTER_IMM(1);
@@ -1464,7 +1465,7 @@ gen8_emit_flush_coherentl3_wa(struct intel_engine_cs *engine, u32 *batch)

	*batch++ = MI_LOAD_REGISTER_MEM_GEN8 | MI_SRM_LRM_GLOBAL_GTT;
	*batch++ = i915_mmio_reg_offset(GEN8_L3SQCREG4);
	*batch++ = i915_ggtt_offset(engine->scratch) + 256;
	*batch++ = i915_scratch_offset(engine->i915) + 256;
	*batch++ = 0;

	return batch;
@@ -1501,7 +1502,7 @@ static u32 *gen8_init_indirectctx_bb(struct intel_engine_cs *engine, u32 *batch)
				       PIPE_CONTROL_GLOBAL_GTT_IVB |
				       PIPE_CONTROL_CS_STALL |
				       PIPE_CONTROL_QW_WRITE,
				       i915_ggtt_offset(engine->scratch) +
				       i915_scratch_offset(engine->i915) +
				       2 * CACHELINE_BYTES);

	*batch++ = MI_ARB_ON_OFF | MI_ARB_ENABLE;
@@ -1578,7 +1579,7 @@ static u32 *gen9_init_indirectctx_bb(struct intel_engine_cs *engine, u32 *batch)
					       PIPE_CONTROL_GLOBAL_GTT_IVB |
					       PIPE_CONTROL_CS_STALL |
					       PIPE_CONTROL_QW_WRITE,
					       i915_ggtt_offset(engine->scratch)
					       i915_scratch_offset(engine->i915)
					       + 2 * CACHELINE_BYTES);
	}

@@ -2146,7 +2147,7 @@ static int gen8_emit_flush_render(struct i915_request *request,
{
	struct intel_engine_cs *engine = request->engine;
	u32 scratch_addr =
		i915_ggtt_offset(engine->scratch) + 2 * CACHELINE_BYTES;
		i915_scratch_offset(engine->i915) + 2 * CACHELINE_BYTES;
	bool vf_flush_wa = false, dc_flush_wa = false;
	u32 *cs, flags = 0;
	int len;
@@ -2483,10 +2484,6 @@ int logical_render_ring_init(struct intel_engine_cs *engine)
	if (ret)
		return ret;

	ret = intel_engine_create_scratch(engine, PAGE_SIZE);
	if (ret)
		goto err_cleanup_common;

	ret = intel_init_workaround_bb(engine);
	if (ret) {
		/*
@@ -2501,10 +2498,6 @@ int logical_render_ring_init(struct intel_engine_cs *engine)
	intel_engine_init_workarounds(engine);

	return 0;

err_cleanup_common:
	intel_engine_cleanup_common(engine);
	return ret;
}

int logical_xcs_ring_init(struct intel_engine_cs *engine)
Loading