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

Commit 0cb26a8e authored by Chris Wilson's avatar Chris Wilson
Browse files

drm/i915: Move legacy kernel context pinning to intel_ringbuffer.c



This is so that we have symmetry with intel_lrc.c and avoid a source of
if (i915.enable_execlists) layering violation within i915_gem_context.c -
that is we move the specific handling of the dev_priv->kernel_context
for legacy submission into the legacy submission code.

This depends upon the init/fini ordering between contexts and engines
already defined by intel_lrc.c, and also exporting the context alignment
required for pinning the legacy context.

v2: Separate out pin/unpin context funcs for greater symmetry with
intel_lrc. One more step towards unifying behaviour between the two
classes of engines and towards fixing another bug in i915_switch_context
vs requests.

Signed-off-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: default avatarJoonas Lahtinen <joonas.lahtinen@linux.intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/1466776558-21516-2-git-send-email-chris@chris-wilson.co.uk
parent 62e63007
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -872,6 +872,8 @@ struct i915_gem_context {
	u32 user_handle;
#define CONTEXT_NO_ZEROMAP		(1<<0)

	u32 ggtt_alignment;

	struct intel_context {
		struct drm_i915_gem_object *state;
		struct intel_ringbuffer *ringbuf;
+3 −24
Original line number Diff line number Diff line
@@ -268,6 +268,8 @@ __create_hw_context(struct drm_device *dev,
	list_add_tail(&ctx->link, &dev_priv->context_list);
	ctx->i915 = dev_priv;

	ctx->ggtt_alignment = get_context_alignment(dev_priv);

	if (dev_priv->hw_context_size) {
		struct drm_i915_gem_object *obj =
				i915_gem_alloc_context_obj(dev, dev_priv->hw_context_size);
@@ -451,26 +453,6 @@ int i915_gem_context_init(struct drm_device *dev)
		return PTR_ERR(ctx);
	}

	if (!i915.enable_execlists && ctx->engine[RCS].state) {
		int ret;

		/* We may need to do things with the shrinker which
		 * require us to immediately switch back to the default
		 * context. This can cause a problem as pinning the
		 * default context also requires GTT space which may not
		 * be available. To avoid this we always pin the default
		 * context.
		 */
		ret = i915_gem_obj_ggtt_pin(ctx->engine[RCS].state,
					    get_context_alignment(dev_priv), 0);
		if (ret) {
			DRM_ERROR("Failed to pinned default global context (error %d)\n",
				  ret);
			i915_gem_context_unreference(ctx);
			return ret;
		}
	}

	dev_priv->kernel_context = ctx;

	DRM_DEBUG_DRIVER("%s context support initialized\n",
@@ -507,9 +489,6 @@ void i915_gem_context_fini(struct drm_device *dev)

	lockdep_assert_held(&dev->struct_mutex);

	if (!i915.enable_execlists && dctx->engine[RCS].state)
		i915_gem_object_ggtt_unpin(dctx->engine[RCS].state);

	i915_gem_context_unreference(dctx);
	dev_priv->kernel_context = NULL;

@@ -759,7 +738,7 @@ static int do_rcs_switch(struct drm_i915_gem_request *req)

	/* Trying to pin first makes error handling easier. */
	ret = i915_gem_obj_ggtt_pin(to->engine[RCS].state,
				    get_context_alignment(engine->i915),
				    to->ggtt_alignment,
				    0);
	if (ret)
		return ret;
+55 −0
Original line number Diff line number Diff line
@@ -2321,6 +2321,47 @@ intel_ringbuffer_free(struct intel_ringbuffer *ring)
	kfree(ring);
}

static int intel_ring_context_pin(struct i915_gem_context *ctx,
				  struct intel_engine_cs *engine)
{
	struct intel_context *ce = &ctx->engine[engine->id];
	int ret;

	lockdep_assert_held(&ctx->i915->dev->struct_mutex);

	if (ce->pin_count++)
		return 0;

	if (ce->state) {
		ret = i915_gem_obj_ggtt_pin(ce->state, ctx->ggtt_alignment, 0);
		if (ret)
			goto error;
	}

	i915_gem_context_reference(ctx);
	return 0;

error:
	ce->pin_count = 0;
	return ret;
}

static void intel_ring_context_unpin(struct i915_gem_context *ctx,
				     struct intel_engine_cs *engine)
{
	struct intel_context *ce = &ctx->engine[engine->id];

	lockdep_assert_held(&ctx->i915->dev->struct_mutex);

	if (--ce->pin_count)
		return;

	if (ce->state)
		i915_gem_object_ggtt_unpin(ce->state);

	i915_gem_context_unreference(ctx);
}

static int intel_init_ring_buffer(struct drm_device *dev,
				  struct intel_engine_cs *engine)
{
@@ -2341,6 +2382,17 @@ static int intel_init_ring_buffer(struct drm_device *dev,

	init_waitqueue_head(&engine->irq_queue);

	/* We may need to do things with the shrinker which
	 * require us to immediately switch back to the default
	 * context. This can cause a problem as pinning the
	 * default context also requires GTT space which may not
	 * be available. To avoid this we always pin the default
	 * context.
	 */
	ret = intel_ring_context_pin(dev_priv->kernel_context, engine);
	if (ret)
		goto error;

	ringbuf = intel_engine_create_ringbuffer(engine, 32 * PAGE_SIZE);
	if (IS_ERR(ringbuf)) {
		ret = PTR_ERR(ringbuf);
@@ -2408,6 +2460,9 @@ void intel_cleanup_engine(struct intel_engine_cs *engine)

	i915_cmd_parser_fini_ring(engine);
	i915_gem_batch_pool_fini(&engine->batch_pool);

	intel_ring_context_unpin(dev_priv->kernel_context, engine);

	engine->i915 = NULL;
}