diff mbox

[25/50] drm/i915/bdw: Deferred creation of user-created LRCs

Message ID 1399637360-4277-26-git-send-email-oscar.mateo@intel.com (mailing list archive)
State New, archived
Headers show

Commit Message

oscar.mateo@intel.com May 9, 2014, 12:08 p.m. UTC
From: Oscar Mateo <oscar.mateo@intel.com>

The backing objects for user-created contexts (either via open fd or
create context ioctl) are actually empty until the user starts sending
execbuffers to them. We do this because, at create time, we really
don't know which engine is going to be used with the context later on.

Signed-off-by: Oscar Mateo <oscar.mateo@intel.com>
---
 drivers/gpu/drm/i915/i915_drv.h            |  3 +++
 drivers/gpu/drm/i915/i915_gem_context.c    | 31 +++++++++++++++++----------
 drivers/gpu/drm/i915/i915_gem_execbuffer.c |  5 ++++-
 drivers/gpu/drm/i915/intel_lrc.c           | 34 ++++++++++++++++++++++++++++++
 4 files changed, 61 insertions(+), 12 deletions(-)
diff mbox

Patch

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 4d58167..7d06a66 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -2431,6 +2431,9 @@  int gen8_gem_context_init(struct drm_device *dev);
 int gen8_create_lr_context(struct i915_hw_context *ctx,
 			   struct intel_engine *ring,
 			   struct drm_i915_file_private *file_priv);
+struct i915_hw_context *
+gen8_gem_validate_context(struct drm_device *dev, struct drm_file *file,
+			  struct intel_engine *ring, const u32 ctx_id);
 
 /* i915_gem_evict.c */
 int __must_check i915_gem_evict_something(struct drm_device *dev,
diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c
index e4e616d..d4c6863 100644
--- a/drivers/gpu/drm/i915/i915_gem_context.c
+++ b/drivers/gpu/drm/i915/i915_gem_context.c
@@ -181,6 +181,7 @@  void i915_gem_context_free(struct kref *ctx_ref)
 	struct i915_hw_context *ctx = container_of(ctx_ref,
 						   typeof(*ctx), ref);
 	struct i915_hw_ppgtt *ppgtt = NULL;
+	bool ppgtt_unref = false;
 	int i;
 
 	for (i = 0; i < I915_NUM_RINGS; i++) {
@@ -188,12 +189,12 @@  void i915_gem_context_free(struct kref *ctx_ref)
 		struct intel_ringbuffer *ringbuf = ctx->engine[i].ringbuf;
 
 		if (ctx_obj) {
-			if (i == RCS) {
-				/* We refcount even the aliasing PPGTT to keep the
-				 * code symmetric */
-				if (USES_PPGTT(ctx_obj->base.dev))
-					ppgtt = ctx_to_ppgtt(ctx);
-			}
+			struct drm_device *dev = ctx_obj->base.dev;
+			struct drm_i915_private *dev_priv = to_i915(dev);
+			ppgtt_unref = USES_PPGTT(dev);
+
+			if (dev_priv->lrc_enabled && ctx->file_priv)
+				i915_gem_object_ggtt_unpin(ctx_obj);
 
 			/* XXX: Free up the object before tearing down the address
 			 * space, in case we're bound in the PPGTT */
@@ -207,8 +208,13 @@  void i915_gem_context_free(struct kref *ctx_ref)
 		}
 	}
 
-	if (ppgtt)
-		kref_put(&ppgtt->ref, ppgtt_release);
+	if (ppgtt_unref) {
+		/* We refcount even the aliasing PPGTT to keep the
+		 * code symmetric */
+		ppgtt = ctx_to_ppgtt(ctx);
+		if (ppgtt)
+			kref_put(&ppgtt->ref, ppgtt_release);
+	}
 	list_del(&ctx->link);
 	kfree(ctx);
 }
@@ -550,12 +556,13 @@  static int context_idr_cleanup(int id, void *p, void *data)
 int i915_gem_context_open(struct drm_device *dev, struct drm_file *file)
 {
 	struct drm_i915_file_private *file_priv = file->driver_priv;
+	struct drm_i915_private *dev_priv = to_i915(dev);
 
 	idr_init(&file_priv->context_idr);
 
 	mutex_lock(&dev->struct_mutex);
-	file_priv->private_default_ctx =
-		i915_gem_create_context(dev, file_priv, USES_FULL_PPGTT(dev), true);
+	file_priv->private_default_ctx = i915_gem_create_context(dev, file_priv,
+			USES_FULL_PPGTT(dev), !dev_priv->lrc_enabled);
 	mutex_unlock(&dev->struct_mutex);
 
 	if (IS_ERR(file_priv->private_default_ctx)) {
@@ -801,6 +808,7 @@  int i915_gem_context_create_ioctl(struct drm_device *dev, void *data,
 {
 	struct drm_i915_gem_context_create *args = data;
 	struct drm_i915_file_private *file_priv = file->driver_priv;
+	struct drm_i915_private *dev_priv = to_i915(dev);
 	struct i915_hw_context *ctx;
 	int ret;
 
@@ -811,7 +819,8 @@  int i915_gem_context_create_ioctl(struct drm_device *dev, void *data,
 	if (ret)
 		return ret;
 
-	ctx = i915_gem_create_context(dev, file_priv, USES_FULL_PPGTT(dev), true);
+	ctx = i915_gem_create_context(dev, file_priv, USES_FULL_PPGTT(dev),
+			!dev_priv->lrc_enabled);
 	mutex_unlock(&dev->struct_mutex);
 	if (IS_ERR(ctx))
 		return PTR_ERR(ctx);
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
index 823ad3d..f7dad8c 100644
--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
@@ -1190,7 +1190,10 @@  i915_gem_do_execbuffer(struct drm_device *dev, void *data,
 		goto pre_mutex_err;
 	}
 
-	ctx = i915_gem_validate_context(dev, file, ring, ctx_id);
+	if (dev_priv->lrc_enabled)
+		ctx = gen8_gem_validate_context(dev, file, ring, ctx_id);
+	else
+		ctx = i915_gem_validate_context(dev, file, ring, ctx_id);
 	if (IS_ERR(ctx)) {
 		mutex_unlock(&dev->struct_mutex);
 		ret = PTR_ERR(ctx);
diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
index 5a85496..a656b48 100644
--- a/drivers/gpu/drm/i915/intel_lrc.c
+++ b/drivers/gpu/drm/i915/intel_lrc.c
@@ -78,6 +78,40 @@ 
 #define CTX_R_PWR_CLK_STATE		0x42
 #define CTX_GPGPU_CSR_BASE_ADDRESS	0x44
 
+struct i915_hw_context *
+gen8_gem_validate_context(struct drm_device *dev, struct drm_file *file,
+			  struct intel_engine *ring, const u32 ctx_id)
+{
+	struct i915_hw_context *ctx = NULL;
+	struct i915_ctx_hang_stats *hs;
+
+	/* There is no reason why we cannot accept non-default, non-render contexts,
+	 * other than it changes the ABI (these kind of custom contexts have not been
+	 * allowed before) */
+	if (ring->id != RCS && ctx_id != DEFAULT_CONTEXT_ID)
+		return ERR_PTR(-EINVAL);
+
+	ctx = i915_gem_context_get(file->driver_priv, ctx_id);
+	if (IS_ERR(ctx))
+		return ctx;
+
+	hs = &ctx->hang_stats;
+	if (hs->banned) {
+		DRM_DEBUG("Context %u tried to submit while banned\n", ctx_id);
+		return ERR_PTR(-EIO);
+	}
+
+	if (!ctx->engine[ring->id].obj) {
+		int ret = gen8_create_lr_context(ctx, ring, file->driver_priv);
+		if (ret) {
+			DRM_DEBUG("Could not create LRC %u\n", ctx_id);
+			return ERR_PTR(ret);
+		}
+	}
+
+	return ctx;
+}
+
 static int
 intel_populate_lr_context(struct i915_hw_context *ctx,
 			  struct intel_engine *ring)