Commit 0eea67eb authored by Ben Widawsky's avatar Ben Widawsky Committed by Daniel Vetter

drm/i915: Create a per file_priv default context

Every file will get it's own context, and we use this context instead of
the default context. The default context still exists for future
shrinker usage as well as reset handling.

v2: Updated to address Mika's recent context guilty changes
Some more changes around this come up in later patches as well.

v3: Use a fake context to avoid allocation for the !HAS_HW_CONTEXT case.
I've tried the alternatives. This looks the best to me.
Removed hangstat stuff from v2 - for a separate patch
Demote failed PPGTT set to DRM_DEBUG_DRIVER since it can now be invoked
easily from userspace.
Signed-off-by: default avatarBen Widawsky <ben@bwidawsk.net>
Signed-off-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
parent bdf4fd7e
...@@ -1758,6 +1758,7 @@ struct drm_i915_file_private { ...@@ -1758,6 +1758,7 @@ struct drm_i915_file_private {
struct idr context_idr; struct idr context_idr;
struct i915_ctx_hang_stats hang_stats; struct i915_ctx_hang_stats hang_stats;
struct i915_hw_context *private_default_ctx;
atomic_t rps_wait_boost; atomic_t rps_wait_boost;
}; };
...@@ -2231,6 +2232,7 @@ i915_gem_obj_ggtt_pin(struct drm_i915_gem_object *obj, ...@@ -2231,6 +2232,7 @@ i915_gem_obj_ggtt_pin(struct drm_i915_gem_object *obj,
} }
/* i915_gem_context.c */ /* i915_gem_context.c */
#define ctx_to_ppgtt(ctx) container_of((ctx)->vm, struct i915_hw_ppgtt, base)
int __must_check i915_gem_context_init(struct drm_device *dev); int __must_check i915_gem_context_init(struct drm_device *dev);
void i915_gem_context_fini(struct drm_device *dev); void i915_gem_context_fini(struct drm_device *dev);
void i915_gem_context_reset(struct drm_device *dev); void i915_gem_context_reset(struct drm_device *dev);
......
...@@ -145,7 +145,7 @@ void i915_gem_context_free(struct kref *ctx_ref) ...@@ -145,7 +145,7 @@ void i915_gem_context_free(struct kref *ctx_ref)
/* We refcount even the aliasing PPGTT to keep the code symmetric */ /* We refcount even the aliasing PPGTT to keep the code symmetric */
if (USES_ALIASING_PPGTT(ctx->obj->base.dev)) if (USES_ALIASING_PPGTT(ctx->obj->base.dev))
ppgtt = container_of(ctx->vm, struct i915_hw_ppgtt, base); ppgtt = ctx_to_ppgtt(ctx);
/* XXX: Free up the object before tearing down the address space, in /* XXX: Free up the object before tearing down the address space, in
* case we're bound in the PPGTT */ * case we're bound in the PPGTT */
...@@ -177,7 +177,7 @@ create_vm_for_ctx(struct drm_device *dev, struct i915_hw_context *ctx) ...@@ -177,7 +177,7 @@ create_vm_for_ctx(struct drm_device *dev, struct i915_hw_context *ctx)
} }
static struct i915_hw_context * static struct i915_hw_context *
create_hw_context(struct drm_device *dev, __create_hw_context(struct drm_device *dev,
struct drm_i915_file_private *file_priv) struct drm_i915_file_private *file_priv)
{ {
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
...@@ -211,7 +211,7 @@ create_hw_context(struct drm_device *dev, ...@@ -211,7 +211,7 @@ create_hw_context(struct drm_device *dev,
if (file_priv == NULL) if (file_priv == NULL)
return ctx; return ctx;
ret = idr_alloc(&file_priv->context_idr, ctx, DEFAULT_CONTEXT_ID + 1, 0, ret = idr_alloc(&file_priv->context_idr, ctx, DEFAULT_CONTEXT_ID, 0,
GFP_KERNEL); GFP_KERNEL);
if (ret < 0) if (ret < 0)
goto err_out; goto err_out;
...@@ -232,8 +232,7 @@ create_hw_context(struct drm_device *dev, ...@@ -232,8 +232,7 @@ create_hw_context(struct drm_device *dev,
static inline bool is_default_context(struct i915_hw_context *ctx) static inline bool is_default_context(struct i915_hw_context *ctx)
{ {
/* Cheap trick to determine default contexts */ return (ctx->id == DEFAULT_CONTEXT_ID);
return ctx->file_priv ? false : true;
} }
/** /**
...@@ -242,9 +241,9 @@ static inline bool is_default_context(struct i915_hw_context *ctx) ...@@ -242,9 +241,9 @@ static inline bool is_default_context(struct i915_hw_context *ctx)
* well as an idle case. * well as an idle case.
*/ */
static struct i915_hw_context * static struct i915_hw_context *
create_default_context(struct drm_device *dev, i915_gem_create_context(struct drm_device *dev,
struct drm_i915_file_private *file_priv, struct drm_i915_file_private *file_priv,
bool create_vm) bool create_vm)
{ {
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
struct i915_hw_context *ctx; struct i915_hw_context *ctx;
...@@ -252,10 +251,7 @@ create_default_context(struct drm_device *dev, ...@@ -252,10 +251,7 @@ create_default_context(struct drm_device *dev,
BUG_ON(!mutex_is_locked(&dev->struct_mutex)); BUG_ON(!mutex_is_locked(&dev->struct_mutex));
/* Not yet supported */ ctx = __create_hw_context(dev, file_priv);
BUG_ON(file_priv);
ctx = create_hw_context(dev, file_priv);
if (IS_ERR(ctx)) if (IS_ERR(ctx))
return ctx; return ctx;
...@@ -263,7 +259,8 @@ create_default_context(struct drm_device *dev, ...@@ -263,7 +259,8 @@ create_default_context(struct drm_device *dev,
struct i915_hw_ppgtt *ppgtt = create_vm_for_ctx(dev, ctx); struct i915_hw_ppgtt *ppgtt = create_vm_for_ctx(dev, ctx);
if (IS_ERR_OR_NULL(ppgtt)) { if (IS_ERR_OR_NULL(ppgtt)) {
DRM_ERROR("PPGTT setup failed (%ld)\n", PTR_ERR(ppgtt)); DRM_DEBUG_DRIVER("PPGTT setup failed (%ld)\n",
PTR_ERR(ppgtt));
ret = PTR_ERR(ppgtt); ret = PTR_ERR(ppgtt);
goto err_destroy; goto err_destroy;
} else } else
...@@ -378,7 +375,7 @@ int i915_gem_context_init(struct drm_device *dev) ...@@ -378,7 +375,7 @@ int i915_gem_context_init(struct drm_device *dev)
} }
dev_priv->ring[RCS].default_context = dev_priv->ring[RCS].default_context =
create_default_context(dev, NULL, USES_ALIASING_PPGTT(dev)); i915_gem_create_context(dev, NULL, USES_ALIASING_PPGTT(dev));
if (IS_ERR_OR_NULL(dev_priv->ring[RCS].default_context)) { if (IS_ERR_OR_NULL(dev_priv->ring[RCS].default_context)) {
DRM_DEBUG_DRIVER("Disabling HW Contexts; create failed %ld\n", DRM_DEBUG_DRIVER("Disabling HW Contexts; create failed %ld\n",
...@@ -480,7 +477,9 @@ static int context_idr_cleanup(int id, void *p, void *data) ...@@ -480,7 +477,9 @@ static int context_idr_cleanup(int id, void *p, void *data)
{ {
struct i915_hw_context *ctx = p; struct i915_hw_context *ctx = p;
BUG_ON(id == DEFAULT_CONTEXT_ID); /* Ignore the default context because close will handle it */
if (is_default_context(ctx))
return 0;
i915_gem_context_unreference(ctx); i915_gem_context_unreference(ctx);
return 0; return 0;
...@@ -516,6 +515,16 @@ int i915_gem_context_open(struct drm_device *dev, struct drm_file *file) ...@@ -516,6 +515,16 @@ int i915_gem_context_open(struct drm_device *dev, struct drm_file *file)
idr_init(&file_priv->context_idr); idr_init(&file_priv->context_idr);
mutex_lock(&dev->struct_mutex);
file_priv->private_default_ctx =
i915_gem_create_context(dev, file_priv, false);
mutex_unlock(&dev->struct_mutex);
if (IS_ERR(file_priv->private_default_ctx)) {
idr_destroy(&file_priv->context_idr);
return PTR_ERR(file_priv->private_default_ctx);
}
return 0; return 0;
} }
...@@ -528,6 +537,7 @@ void i915_gem_context_close(struct drm_device *dev, struct drm_file *file) ...@@ -528,6 +537,7 @@ void i915_gem_context_close(struct drm_device *dev, struct drm_file *file)
mutex_lock(&dev->struct_mutex); mutex_lock(&dev->struct_mutex);
idr_for_each(&file_priv->context_idr, context_idr_cleanup, NULL); idr_for_each(&file_priv->context_idr, context_idr_cleanup, NULL);
i915_gem_context_unreference(file_priv->private_default_ctx);
idr_destroy(&file_priv->context_idr); idr_destroy(&file_priv->context_idr);
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
} }
...@@ -702,21 +712,18 @@ int i915_switch_context(struct intel_ring_buffer *ring, ...@@ -702,21 +712,18 @@ int i915_switch_context(struct intel_ring_buffer *ring,
struct drm_i915_private *dev_priv = ring->dev->dev_private; struct drm_i915_private *dev_priv = ring->dev->dev_private;
struct i915_hw_context *to; struct i915_hw_context *to;
WARN_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex));
if (!HAS_HW_CONTEXTS(ring->dev)) if (!HAS_HW_CONTEXTS(ring->dev))
return 0; return 0;
WARN_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex)); if (file == NULL)
if (to_id == DEFAULT_CONTEXT_ID) {
to = ring->default_context; to = ring->default_context;
} else { else
if (file == NULL)
return -EINVAL;
to = i915_gem_context_get(file->driver_priv, to_id); to = i915_gem_context_get(file->driver_priv, to_id);
if (to == NULL)
return -ENOENT; if (to == NULL)
} return -ENOENT;
return do_switch(ring, to); return do_switch(ring, to);
} }
...@@ -739,7 +746,7 @@ int i915_gem_context_create_ioctl(struct drm_device *dev, void *data, ...@@ -739,7 +746,7 @@ int i915_gem_context_create_ioctl(struct drm_device *dev, void *data,
if (ret) if (ret)
return ret; return ret;
ctx = create_hw_context(dev, file_priv); ctx = i915_gem_create_context(dev, file_priv, false);
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
if (IS_ERR(ctx)) if (IS_ERR(ctx))
return PTR_ERR(ctx); return PTR_ERR(ctx);
...@@ -761,6 +768,9 @@ int i915_gem_context_destroy_ioctl(struct drm_device *dev, void *data, ...@@ -761,6 +768,9 @@ int i915_gem_context_destroy_ioctl(struct drm_device *dev, void *data,
if (!(dev->driver->driver_features & DRIVER_GEM)) if (!(dev->driver->driver_features & DRIVER_GEM))
return -ENODEV; return -ENODEV;
if (args->ctx_id == DEFAULT_CONTEXT_ID)
return -EPERM;
ret = i915_mutex_lock_interruptible(dev); ret = i915_mutex_lock_interruptible(dev);
if (ret) if (ret)
return ret; return ret;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment