drm/i915: Extract the actual workload submission mechanism from execbuffer
authorOscar Mateo <oscar.mateo@intel.com>
Thu, 3 Jul 2014 15:28:05 +0000 (16:28 +0100)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Tue, 8 Jul 2014 10:31:06 +0000 (12:31 +0200)
So that we isolate the legacy ringbuffer submission mechanism, which becomes
a good candidate to be abstracted away. This is prep-work for Execlists (which
will its own workload submission mechanism).

No functional changes.

Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Oscar Mateo <oscar.mateo@intel.com>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
drivers/gpu/drm/i915/i915_gem_execbuffer.c

index c97178ebf2b50f574cb8fea7ed76fd07409f0815..60998fc4e5b22147687db554a4c80f27d08e1bea 100644 (file)
@@ -1026,6 +1026,163 @@ i915_reset_gen7_sol_offsets(struct drm_device *dev,
        return 0;
 }
 
+static int
+legacy_ringbuffer_submission(struct drm_device *dev, struct drm_file *file,
+                            struct intel_engine_cs *ring,
+                            struct intel_context *ctx,
+                            struct drm_i915_gem_execbuffer2 *args,
+                            struct list_head *vmas,
+                            struct drm_i915_gem_object *batch_obj,
+                            u64 exec_start, u32 flags)
+{
+       struct drm_clip_rect *cliprects = NULL;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       u64 exec_len;
+       int instp_mode;
+       u32 instp_mask;
+       int i, ret = 0;
+
+       if (args->num_cliprects != 0) {
+               if (ring != &dev_priv->ring[RCS]) {
+                       DRM_DEBUG("clip rectangles are only valid with the render ring\n");
+                       return -EINVAL;
+               }
+
+               if (INTEL_INFO(dev)->gen >= 5) {
+                       DRM_DEBUG("clip rectangles are only valid on pre-gen5\n");
+                       return -EINVAL;
+               }
+
+               if (args->num_cliprects > UINT_MAX / sizeof(*cliprects)) {
+                       DRM_DEBUG("execbuf with %u cliprects\n",
+                                 args->num_cliprects);
+                       return -EINVAL;
+               }
+
+               cliprects = kcalloc(args->num_cliprects,
+                                   sizeof(*cliprects),
+                                   GFP_KERNEL);
+               if (cliprects == NULL) {
+                       ret = -ENOMEM;
+                       goto error;
+               }
+
+               if (copy_from_user(cliprects,
+                                  to_user_ptr(args->cliprects_ptr),
+                                  sizeof(*cliprects)*args->num_cliprects)) {
+                       ret = -EFAULT;
+                       goto error;
+               }
+       } else {
+               if (args->DR4 == 0xffffffff) {
+                       DRM_DEBUG("UXA submitting garbage DR4, fixing up\n");
+                       args->DR4 = 0;
+               }
+
+               if (args->DR1 || args->DR4 || args->cliprects_ptr) {
+                       DRM_DEBUG("0 cliprects but dirt in cliprects fields\n");
+                       return -EINVAL;
+               }
+       }
+
+       ret = i915_gem_execbuffer_move_to_gpu(ring, vmas);
+       if (ret)
+               goto error;
+
+       ret = i915_switch_context(ring, ctx);
+       if (ret)
+               goto error;
+
+       instp_mode = args->flags & I915_EXEC_CONSTANTS_MASK;
+       instp_mask = I915_EXEC_CONSTANTS_MASK;
+       switch (instp_mode) {
+       case I915_EXEC_CONSTANTS_REL_GENERAL:
+       case I915_EXEC_CONSTANTS_ABSOLUTE:
+       case I915_EXEC_CONSTANTS_REL_SURFACE:
+               if (instp_mode != 0 && ring != &dev_priv->ring[RCS]) {
+                       DRM_DEBUG("non-0 rel constants mode on non-RCS\n");
+                       ret = -EINVAL;
+                       goto error;
+               }
+
+               if (instp_mode != dev_priv->relative_constants_mode) {
+                       if (INTEL_INFO(dev)->gen < 4) {
+                               DRM_DEBUG("no rel constants on pre-gen4\n");
+                               ret = -EINVAL;
+                               goto error;
+                       }
+
+                       if (INTEL_INFO(dev)->gen > 5 &&
+                           instp_mode == I915_EXEC_CONSTANTS_REL_SURFACE) {
+                               DRM_DEBUG("rel surface constants mode invalid on gen5+\n");
+                               ret = -EINVAL;
+                               goto error;
+                       }
+
+                       /* The HW changed the meaning on this bit on gen6 */
+                       if (INTEL_INFO(dev)->gen >= 6)
+                               instp_mask &= ~I915_EXEC_CONSTANTS_REL_SURFACE;
+               }
+               break;
+       default:
+               DRM_DEBUG("execbuf with unknown constants: %d\n", instp_mode);
+               ret = -EINVAL;
+               goto error;
+       }
+
+       if (ring == &dev_priv->ring[RCS] &&
+                       instp_mode != dev_priv->relative_constants_mode) {
+               ret = intel_ring_begin(ring, 4);
+               if (ret)
+                       goto error;
+
+               intel_ring_emit(ring, MI_NOOP);
+               intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1));
+               intel_ring_emit(ring, INSTPM);
+               intel_ring_emit(ring, instp_mask << 16 | instp_mode);
+               intel_ring_advance(ring);
+
+               dev_priv->relative_constants_mode = instp_mode;
+       }
+
+       if (args->flags & I915_EXEC_GEN7_SOL_RESET) {
+               ret = i915_reset_gen7_sol_offsets(dev, ring);
+               if (ret)
+                       goto error;
+       }
+
+       exec_len = args->batch_len;
+       if (cliprects) {
+               for (i = 0; i < args->num_cliprects; i++) {
+                       ret = i915_emit_box(dev, &cliprects[i],
+                                           args->DR1, args->DR4);
+                       if (ret)
+                               goto error;
+
+                       ret = ring->dispatch_execbuffer(ring,
+                                                       exec_start, exec_len,
+                                                       flags);
+                       if (ret)
+                               goto error;
+               }
+       } else {
+               ret = ring->dispatch_execbuffer(ring,
+                                               exec_start, exec_len,
+                                               flags);
+               if (ret)
+                       return ret;
+       }
+
+       trace_i915_gem_ring_dispatch(ring, intel_ring_get_seqno(ring), flags);
+
+       i915_gem_execbuffer_move_to_active(vmas, ring);
+       i915_gem_execbuffer_retire_commands(dev, file, ring, batch_obj);
+
+error:
+       kfree(cliprects);
+       return ret;
+}
+
 /**
  * Find one BSD ring to dispatch the corresponding BSD command.
  * The Ring ID is returned.
@@ -1085,14 +1242,13 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct eb_vmas *eb;
        struct drm_i915_gem_object *batch_obj;
-       struct drm_clip_rect *cliprects = NULL;
        struct intel_engine_cs *ring;
        struct intel_context *ctx;
        struct i915_address_space *vm;
        const u32 ctx_id = i915_execbuffer2_get_context_id(*args);
-       u64 exec_start = args->batch_start_offset, exec_len;
-       u32 mask, flags;
-       int ret, mode, i;
+       u64 exec_start = args->batch_start_offset;
+       u32 flags;
+       int ret;
        bool need_relocs;
 
        if (!i915_gem_check_execbuffer(args))
@@ -1136,87 +1292,11 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
                return -EINVAL;
        }
 
-       mode = args->flags & I915_EXEC_CONSTANTS_MASK;
-       mask = I915_EXEC_CONSTANTS_MASK;
-       switch (mode) {
-       case I915_EXEC_CONSTANTS_REL_GENERAL:
-       case I915_EXEC_CONSTANTS_ABSOLUTE:
-       case I915_EXEC_CONSTANTS_REL_SURFACE:
-               if (mode != 0 && ring != &dev_priv->ring[RCS]) {
-                       DRM_DEBUG("non-0 rel constants mode on non-RCS\n");
-                       return -EINVAL;
-               }
-
-               if (mode != dev_priv->relative_constants_mode) {
-                       if (INTEL_INFO(dev)->gen < 4) {
-                               DRM_DEBUG("no rel constants on pre-gen4\n");
-                               return -EINVAL;
-                       }
-
-                       if (INTEL_INFO(dev)->gen > 5 &&
-                           mode == I915_EXEC_CONSTANTS_REL_SURFACE) {
-                               DRM_DEBUG("rel surface constants mode invalid on gen5+\n");
-                               return -EINVAL;
-                       }
-
-                       /* The HW changed the meaning on this bit on gen6 */
-                       if (INTEL_INFO(dev)->gen >= 6)
-                               mask &= ~I915_EXEC_CONSTANTS_REL_SURFACE;
-               }
-               break;
-       default:
-               DRM_DEBUG("execbuf with unknown constants: %d\n", mode);
-               return -EINVAL;
-       }
-
        if (args->buffer_count < 1) {
                DRM_DEBUG("execbuf with %d buffers\n", args->buffer_count);
                return -EINVAL;
        }
 
-       if (args->num_cliprects != 0) {
-               if (ring != &dev_priv->ring[RCS]) {
-                       DRM_DEBUG("clip rectangles are only valid with the render ring\n");
-                       return -EINVAL;
-               }
-
-               if (INTEL_INFO(dev)->gen >= 5) {
-                       DRM_DEBUG("clip rectangles are only valid on pre-gen5\n");
-                       return -EINVAL;
-               }
-
-               if (args->num_cliprects > UINT_MAX / sizeof(*cliprects)) {
-                       DRM_DEBUG("execbuf with %u cliprects\n",
-                                 args->num_cliprects);
-                       return -EINVAL;
-               }
-
-               cliprects = kcalloc(args->num_cliprects,
-                                   sizeof(*cliprects),
-                                   GFP_KERNEL);
-               if (cliprects == NULL) {
-                       ret = -ENOMEM;
-                       goto pre_mutex_err;
-               }
-
-               if (copy_from_user(cliprects,
-                                  to_user_ptr(args->cliprects_ptr),
-                                  sizeof(*cliprects)*args->num_cliprects)) {
-                       ret = -EFAULT;
-                       goto pre_mutex_err;
-               }
-       } else {
-               if (args->DR4 == 0xffffffff) {
-                       DRM_DEBUG("UXA submitting garbage DR4, fixing up\n");
-                       args->DR4 = 0;
-               }
-
-               if (args->DR1 || args->DR4 || args->cliprects_ptr) {
-                       DRM_DEBUG("0 cliprects but dirt in cliprects fields\n");
-                       return -EINVAL;
-               }
-       }
-
        intel_runtime_pm_get(dev_priv);
 
        ret = i915_mutex_lock_interruptible(dev);
@@ -1320,63 +1400,11 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
        else
                exec_start += i915_gem_obj_offset(batch_obj, vm);
 
-       ret = i915_gem_execbuffer_move_to_gpu(ring, &eb->vmas);
+       ret = legacy_ringbuffer_submission(dev, file, ring, ctx,
+                       args, &eb->vmas, batch_obj, exec_start, flags);
        if (ret)
                goto err;
 
-       ret = i915_switch_context(ring, ctx);
-       if (ret)
-               goto err;
-
-       if (ring == &dev_priv->ring[RCS] &&
-           mode != dev_priv->relative_constants_mode) {
-               ret = intel_ring_begin(ring, 4);
-               if (ret)
-                               goto err;
-
-               intel_ring_emit(ring, MI_NOOP);
-               intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1));
-               intel_ring_emit(ring, INSTPM);
-               intel_ring_emit(ring, mask << 16 | mode);
-               intel_ring_advance(ring);
-
-               dev_priv->relative_constants_mode = mode;
-       }
-
-       if (args->flags & I915_EXEC_GEN7_SOL_RESET) {
-               ret = i915_reset_gen7_sol_offsets(dev, ring);
-               if (ret)
-                       goto err;
-       }
-
-
-       exec_len = args->batch_len;
-       if (cliprects) {
-               for (i = 0; i < args->num_cliprects; i++) {
-                       ret = i915_emit_box(dev, &cliprects[i],
-                                           args->DR1, args->DR4);
-                       if (ret)
-                               goto err;
-
-                       ret = ring->dispatch_execbuffer(ring,
-                                                       exec_start, exec_len,
-                                                       flags);
-                       if (ret)
-                               goto err;
-               }
-       } else {
-               ret = ring->dispatch_execbuffer(ring,
-                                               exec_start, exec_len,
-                                               flags);
-               if (ret)
-                       goto err;
-       }
-
-       trace_i915_gem_ring_dispatch(ring, intel_ring_get_seqno(ring), flags);
-
-       i915_gem_execbuffer_move_to_active(&eb->vmas, ring);
-       i915_gem_execbuffer_retire_commands(dev, file, ring, batch_obj);
-
 err:
        /* the request owns the ref now */
        i915_gem_context_unreference(ctx);
@@ -1385,8 +1413,6 @@ err:
        mutex_unlock(&dev->struct_mutex);
 
 pre_mutex_err:
-       kfree(cliprects);
-
        /* intel_gpu_busy should also get a ref, so it will free when the device
         * is really idle. */
        intel_runtime_pm_put(dev_priv);