If we want to use contexts in more abstract terms (specifically with PPGTT in mind), we need to allow them to be specified for any ring. NOTE: This commit requires an update to intel-gpu-tools to make it not fail. Signed-off-by: Ben Widawsky <ben at bwidawsk.net> --- drivers/gpu/drm/i915/i915_gem_context.c | 56 ++++++++++++++++++++++-------- drivers/gpu/drm/i915/i915_gem_execbuffer.c | 16 --------- 2 files changed, 42 insertions(+), 30 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index a5ac6dd..74714e56 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -97,7 +97,8 @@ static struct i915_hw_context * i915_gem_context_get(struct drm_i915_file_private *file_priv, u32 id); -static int do_switch(struct i915_hw_context *to); +static int do_switch(struct intel_ring_buffer *ring, + struct i915_hw_context *to); static int get_context_size(struct drm_device *dev) { @@ -204,13 +205,19 @@ static inline bool is_default_context(struct i915_hw_context *ctx) * context state of the GPU for applications that don't utilize HW contexts, as * well as an idle case. */ -static int create_default_context(struct drm_i915_private *dev_priv) +static int create_default_context(struct drm_i915_private *dev_priv, + struct intel_ring_buffer *ring) { struct i915_hw_context *ctx; int ret; BUG_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex)); + if (dev_priv->ring[RCS].default_context) { + ring->default_context = dev_priv->ring[RCS].default_context; + return 0; + } + ctx = create_hw_context(dev_priv->dev, NULL); if (IS_ERR(ctx)) return PTR_ERR(ctx); @@ -241,6 +248,8 @@ err_destroy: void i915_gem_context_init(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_ring_buffer *ring; + int i; if (!HAS_HW_CONTEXTS(dev)) { dev_priv->hw_contexts_disabled = true; @@ -262,10 +271,17 @@ void i915_gem_context_init(struct drm_device *dev) return; } - if (create_default_context(dev_priv)) { - dev_priv->hw_contexts_disabled = true; - DRM_DEBUG_DRIVER("Disabling HW Contexts; create failed\n"); - return; + + for (i = 0; i < I915_NUM_RINGS; i++) { + if (!(INTEL_INFO(dev)->ring_mask & (1<<i))) + continue; + + ring = &dev_priv->ring[i]; + if (create_default_context(dev_priv, ring)) { + dev_priv->hw_contexts_disabled = true; + DRM_DEBUG_DRIVER("Disabling HW Contexts; create failed\n"); + return; + } } DRM_DEBUG_DRIVER("HW context support initialized\n"); @@ -310,7 +326,8 @@ int i915_gem_context_enable(struct drm_i915_private *dev_priv) if (dev_priv->hw_contexts_disabled) return 0; BUG_ON(!dev_priv->ring[RCS].default_context); - return do_switch(dev_priv->ring[RCS].default_context); + return do_switch(&dev_priv->ring[RCS], + dev_priv->ring[RCS].default_context); } static int context_idr_cleanup(int id, void *p, void *data) @@ -437,19 +454,32 @@ mi_set_context(struct intel_ring_buffer *ring, return ret; } -static int do_switch(struct i915_hw_context *to) +static int do_switch(struct intel_ring_buffer *ring, + struct i915_hw_context *to) { - struct intel_ring_buffer *ring = to->ring; struct drm_i915_private *dev_priv = ring->dev->dev_private; struct i915_hw_context *from = ring->last_context; u32 hw_flags = 0; int ret; - BUG_ON(from != NULL && from->obj != NULL && from->obj->pin_count == 0); + if (from != NULL && ring == &dev_priv->ring[RCS]) { + BUG_ON(from->obj == NULL); + BUG_ON(from->obj->pin_count == 0); + } if (from == to) return 0; + if (ring != &dev_priv->ring[RCS] && from) { + ret = i915_add_request(ring, NULL); + if (ret) + return ret; + i915_gem_context_unreference(from); + } + + if (ring != &dev_priv->ring[RCS]) + goto done; + ret = i915_gem_ggtt_pin(to->obj, CONTEXT_ALIGN, false, false); if (ret) return ret; @@ -514,6 +544,7 @@ static int do_switch(struct i915_hw_context *to) i915_gem_context_unreference(from); } +done: i915_gem_context_reference(to); ring->last_context = to; to->is_initialized = true; @@ -546,9 +577,6 @@ int i915_switch_context(struct intel_ring_buffer *ring, WARN_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex)); - if (ring != &dev_priv->ring[RCS]) - return 0; - if (to_id == DEFAULT_CONTEXT_ID) { to = ring->default_context; } else { @@ -560,7 +588,7 @@ int i915_switch_context(struct intel_ring_buffer *ring, return -ENOENT; } - return do_switch(to); + return do_switch(ring, to); } int i915_gem_context_create_ioctl(struct drm_device *dev, void *data, diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index 7e9823f..b3e3658 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -892,29 +892,13 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, break; case I915_EXEC_BSD: ring = &dev_priv->ring[VCS]; - if (ctx_id != 0) { - DRM_DEBUG("Ring %s doesn't support contexts\n", - ring->name); - return -EPERM; - } break; case I915_EXEC_BLT: ring = &dev_priv->ring[BCS]; - if (ctx_id != 0) { - DRM_DEBUG("Ring %s doesn't support contexts\n", - ring->name); - return -EPERM; - } break; case I915_EXEC_VEBOX: ring = &dev_priv->ring[VECS]; - if (ctx_id != 0) { - DRM_DEBUG("Ring %s doesn't support contexts\n", - ring->name); - return -EPERM; - } break; - default: DRM_DEBUG("execbuf with unknown ring: %d\n", (int)(args->flags & I915_EXEC_RING_MASK)); -- 1.8.3.1