@@ -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,
@@ -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);
@@ -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);
@@ -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)