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

Commit 71b76d00 authored by Ben Widawsky's avatar Ben Widawsky Committed by Daniel Vetter
Browse files

drm/i915: cleanup context fini



I had this lying around from he original PPGTT series, and thought we
might try to get it in by itself.

With the introduction of context refcounting we never explicitly
ref/unref the backing object. As such, the previous fix was a bit wonky.

Aside from fixing the above, this patch also puts us in good shape for
an upcoming patch which allows a failure to occur in between
context_init and the first do_switch.

CC: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Signed-off-by: default avatarBen Widawsky <ben@bwidawsk.net>
Reviewed-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
parent 3d57e5bd
Loading
Loading
Loading
Loading
+13 −4
Original line number Diff line number Diff line
@@ -220,7 +220,6 @@ static int create_default_context(struct drm_i915_private *dev_priv)
	 * may not be available. To avoid this we always pin the
	 * default context.
	 */
	dev_priv->ring[RCS].default_context = ctx;
	ret = i915_gem_obj_ggtt_pin(ctx->obj, CONTEXT_ALIGN, false, false);
	if (ret) {
		DRM_DEBUG_DRIVER("Couldn't pin %d\n", ret);
@@ -233,6 +232,8 @@ static int create_default_context(struct drm_i915_private *dev_priv)
		goto err_unpin;
	}

	dev_priv->ring[RCS].default_context = ctx;

	DRM_DEBUG_DRIVER("Default HW context loaded\n");
	return 0;

@@ -288,16 +289,24 @@ void i915_gem_context_fini(struct drm_device *dev)
	 * other code, leading to spurious errors. */
	intel_gpu_reset(dev);

	i915_gem_object_unpin(dctx->obj);

	/* When default context is created and switched to, base object refcount
	 * will be 2 (+1 from object creation and +1 from do_switch()).
	 * i915_gem_context_fini() will be called after gpu_idle() has switched
	 * to default context. So we need to unreference the base object once
	 * to offset the do_switch part, so that i915_gem_context_unreference()
	 * can then free the base object correctly. */
	drm_gem_object_unreference(&dctx->obj->base);
	WARN_ON(!dev_priv->ring[RCS].last_context);
	if (dev_priv->ring[RCS].last_context == dctx) {
		/* Fake switch to NULL context */
		WARN_ON(dctx->obj->active);
		i915_gem_object_unpin(dctx->obj);
		i915_gem_context_unreference(dctx);
	}

	i915_gem_object_unpin(dctx->obj);
	i915_gem_context_unreference(dctx);
	dev_priv->ring[RCS].default_context = NULL;
	dev_priv->ring[RCS].last_context = NULL;
}

static int context_idr_cleanup(int id, void *p, void *data)