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: Chris Wilson <chris@chris-wilson.co.uk> Reviewed-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> Link: http://patchwork.freedesktop.org/patch/msgid/1466776558-21516-2-git-send-email-chris@chris-wilson.co.uk
This commit is contained in:
parent
62e6300768
commit
0cb26a8ed1
|
@ -872,6 +872,8 @@ struct i915_gem_context {
|
||||||
u32 user_handle;
|
u32 user_handle;
|
||||||
#define CONTEXT_NO_ZEROMAP (1<<0)
|
#define CONTEXT_NO_ZEROMAP (1<<0)
|
||||||
|
|
||||||
|
u32 ggtt_alignment;
|
||||||
|
|
||||||
struct intel_context {
|
struct intel_context {
|
||||||
struct drm_i915_gem_object *state;
|
struct drm_i915_gem_object *state;
|
||||||
struct intel_ringbuffer *ringbuf;
|
struct intel_ringbuffer *ringbuf;
|
||||||
|
|
|
@ -268,6 +268,8 @@ __create_hw_context(struct drm_device *dev,
|
||||||
list_add_tail(&ctx->link, &dev_priv->context_list);
|
list_add_tail(&ctx->link, &dev_priv->context_list);
|
||||||
ctx->i915 = dev_priv;
|
ctx->i915 = dev_priv;
|
||||||
|
|
||||||
|
ctx->ggtt_alignment = get_context_alignment(dev_priv);
|
||||||
|
|
||||||
if (dev_priv->hw_context_size) {
|
if (dev_priv->hw_context_size) {
|
||||||
struct drm_i915_gem_object *obj =
|
struct drm_i915_gem_object *obj =
|
||||||
i915_gem_alloc_context_obj(dev, dev_priv->hw_context_size);
|
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);
|
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;
|
dev_priv->kernel_context = ctx;
|
||||||
|
|
||||||
DRM_DEBUG_DRIVER("%s context support initialized\n",
|
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);
|
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);
|
i915_gem_context_unreference(dctx);
|
||||||
dev_priv->kernel_context = NULL;
|
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. */
|
/* Trying to pin first makes error handling easier. */
|
||||||
ret = i915_gem_obj_ggtt_pin(to->engine[RCS].state,
|
ret = i915_gem_obj_ggtt_pin(to->engine[RCS].state,
|
||||||
get_context_alignment(engine->i915),
|
to->ggtt_alignment,
|
||||||
0);
|
0);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
@ -2321,6 +2321,47 @@ intel_ringbuffer_free(struct intel_ringbuffer *ring)
|
||||||
kfree(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,
|
static int intel_init_ring_buffer(struct drm_device *dev,
|
||||||
struct intel_engine_cs *engine)
|
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);
|
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);
|
ringbuf = intel_engine_create_ringbuffer(engine, 32 * PAGE_SIZE);
|
||||||
if (IS_ERR(ringbuf)) {
|
if (IS_ERR(ringbuf)) {
|
||||||
ret = PTR_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_cmd_parser_fini_ring(engine);
|
||||||
i915_gem_batch_pool_fini(&engine->batch_pool);
|
i915_gem_batch_pool_fini(&engine->batch_pool);
|
||||||
|
|
||||||
|
intel_ring_context_unpin(dev_priv->kernel_context, engine);
|
||||||
|
|
||||||
engine->i915 = NULL;
|
engine->i915 = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue