drm/i915: Update ring->emit_bb_start() to take a request structure
[deliverable/linux.git] / drivers / gpu / drm / i915 / intel_lrc.c
index 2b65d29c48018e12256719f3750eae4c4cc26da8..9e99c6226b57e291ea1ab51b3e4fbcf78003cb82 100644 (file)
@@ -604,10 +604,9 @@ static int execlists_context_queue(struct intel_engine_cs *ring,
        return 0;
 }
 
-static int logical_ring_invalidate_all_caches(struct intel_ringbuffer *ringbuf,
-                                             struct intel_context *ctx)
+static int logical_ring_invalidate_all_caches(struct drm_i915_gem_request *req)
 {
-       struct intel_engine_cs *ring = ringbuf->ring;
+       struct intel_engine_cs *ring = req->ring;
        uint32_t flush_domains;
        int ret;
 
@@ -615,8 +614,7 @@ static int logical_ring_invalidate_all_caches(struct intel_ringbuffer *ringbuf,
        if (ring->gpu_caches_dirty)
                flush_domains = I915_GEM_GPU_DOMAINS;
 
-       ret = ring->emit_flush(ringbuf, ctx,
-                              I915_GEM_GPU_DOMAINS, flush_domains);
+       ret = ring->emit_flush(req, I915_GEM_GPU_DOMAINS, flush_domains);
        if (ret)
                return ret;
 
@@ -624,12 +622,10 @@ static int logical_ring_invalidate_all_caches(struct intel_ringbuffer *ringbuf,
        return 0;
 }
 
-static int execlists_move_to_gpu(struct intel_ringbuffer *ringbuf,
-                                struct intel_context *ctx,
+static int execlists_move_to_gpu(struct drm_i915_gem_request *req,
                                 struct list_head *vmas)
 {
-       struct intel_engine_cs *ring = ringbuf->ring;
-       const unsigned other_rings = ~intel_ring_flag(ring);
+       const unsigned other_rings = ~intel_ring_flag(req->ring);
        struct i915_vma *vma;
        uint32_t flush_domains = 0;
        bool flush_chipset = false;
@@ -639,7 +635,7 @@ static int execlists_move_to_gpu(struct intel_ringbuffer *ringbuf,
                struct drm_i915_gem_object *obj = vma->obj;
 
                if (obj->active & other_rings) {
-                       ret = i915_gem_object_sync(obj, ring);
+                       ret = i915_gem_object_sync(obj, req->ring, &req);
                        if (ret)
                                return ret;
                }
@@ -656,23 +652,20 @@ static int execlists_move_to_gpu(struct intel_ringbuffer *ringbuf,
        /* Unconditionally invalidate gpu caches and ensure that we do flush
         * any residual writes from the previous batch.
         */
-       return logical_ring_invalidate_all_caches(ringbuf, ctx);
+       return logical_ring_invalidate_all_caches(req);
 }
 
-int intel_logical_ring_alloc_request_extras(struct drm_i915_gem_request *request,
-                                           struct intel_context *ctx)
+int intel_logical_ring_alloc_request_extras(struct drm_i915_gem_request *request)
 {
        int ret;
 
-       if (ctx != request->ring->default_context) {
-               ret = intel_lr_context_pin(request->ring, ctx);
+       if (request->ctx != request->ring->default_context) {
+               ret = intel_lr_context_pin(request->ring, request->ctx);
                if (ret)
                        return ret;
        }
 
-       request->ringbuf = ctx->engine[request->ring->id].ringbuf;
-       request->ctx     = ctx;
-       i915_gem_context_reference(request->ctx);
+       request->ringbuf = request->ctx->engine[request->ring->id].ringbuf;
 
        return 0;
 }
@@ -686,6 +679,9 @@ static int logical_ring_wait_for_space(struct intel_ringbuffer *ringbuf,
        unsigned space;
        int ret;
 
+       /* The whole point of reserving space is to not wait! */
+       WARN_ON(ringbuf->reserved_in_use);
+
        if (intel_ring_space(ringbuf) >= bytes)
                return 0;
 
@@ -746,6 +742,9 @@ static int logical_ring_wrap_buffer(struct intel_ringbuffer *ringbuf,
        uint32_t __iomem *virt;
        int rem = ringbuf->size - ringbuf->tail;
 
+       /* Can't wrap if space has already been reserved! */
+       WARN_ON(ringbuf->reserved_in_use);
+
        if (ringbuf->space < rem) {
                int ret = logical_ring_wait_for_space(ringbuf, ctx, rem);
 
@@ -769,10 +768,25 @@ static int logical_ring_prepare(struct intel_ringbuffer *ringbuf,
 {
        int ret;
 
+       /*
+        * Add on the reserved size to the request to make sure that after
+        * the intended commands have been emitted, there is guaranteed to
+        * still be enough free space to send them to the hardware.
+        */
+       if (!ringbuf->reserved_in_use)
+               bytes += ringbuf->reserved_size;
+
        if (unlikely(ringbuf->tail + bytes > ringbuf->effective_size)) {
                ret = logical_ring_wrap_buffer(ringbuf, ctx);
                if (unlikely(ret))
                        return ret;
+
+               if(ringbuf->reserved_size) {
+                       uint32_t size = ringbuf->reserved_size;
+
+                       intel_ring_reserved_space_cancel(ringbuf);
+                       intel_ring_reserved_space_reserve(ringbuf, size);
+               }
        }
 
        if (unlikely(ringbuf->space < bytes)) {
@@ -800,6 +814,7 @@ static int logical_ring_prepare(struct intel_ringbuffer *ringbuf,
 static int intel_logical_ring_begin(struct intel_ringbuffer *ringbuf,
                                    struct intel_context *ctx, int num_dwords)
 {
+       struct drm_i915_gem_request *req;
        struct intel_engine_cs *ring = ringbuf->ring;
        struct drm_device *dev = ring->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
@@ -815,7 +830,7 @@ static int intel_logical_ring_begin(struct intel_ringbuffer *ringbuf,
                return ret;
 
        /* Preallocate the olr before touching the ring */
-       ret = i915_gem_request_alloc(ring, ctx);
+       ret = i915_gem_request_alloc(ring, ctx, &req);
        if (ret)
                return ret;
 
@@ -840,16 +855,15 @@ static int intel_logical_ring_begin(struct intel_ringbuffer *ringbuf,
  *
  * Return: non-zero if the submission fails.
  */
-int intel_execlists_submission(struct drm_device *dev, struct drm_file *file,
-                              struct intel_engine_cs *ring,
-                              struct intel_context *ctx,
+int intel_execlists_submission(struct i915_execbuffer_params *params,
                               struct drm_i915_gem_execbuffer2 *args,
-                              struct list_head *vmas,
-                              struct drm_i915_gem_object *batch_obj,
-                              u64 exec_start, u32 dispatch_flags)
+                              struct list_head *vmas)
 {
+       struct drm_device       *dev = params->dev;
+       struct intel_engine_cs  *ring = params->ring;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_ringbuffer *ringbuf = ctx->engine[ring->id].ringbuf;
+       struct intel_ringbuffer *ringbuf = params->ctx->engine[ring->id].ringbuf;
+       u64 exec_start;
        int instp_mode;
        u32 instp_mask;
        int ret;
@@ -900,13 +914,13 @@ int intel_execlists_submission(struct drm_device *dev, struct drm_file *file,
                return -EINVAL;
        }
 
-       ret = execlists_move_to_gpu(ringbuf, ctx, vmas);
+       ret = execlists_move_to_gpu(params->request, vmas);
        if (ret)
                return ret;
 
        if (ring == &dev_priv->ring[RCS] &&
            instp_mode != dev_priv->relative_constants_mode) {
-               ret = intel_logical_ring_begin(ringbuf, ctx, 4);
+               ret = intel_logical_ring_begin(ringbuf, params->ctx, 4);
                if (ret)
                        return ret;
 
@@ -919,14 +933,17 @@ int intel_execlists_submission(struct drm_device *dev, struct drm_file *file,
                dev_priv->relative_constants_mode = instp_mode;
        }
 
-       ret = ring->emit_bb_start(ringbuf, ctx, exec_start, dispatch_flags);
+       exec_start = params->batch_obj_vm_offset +
+                    args->batch_start_offset;
+
+       ret = ring->emit_bb_start(params->request, exec_start, params->dispatch_flags);
        if (ret)
                return ret;
 
-       trace_i915_gem_ring_dispatch(intel_ring_get_request(ring), dispatch_flags);
+       trace_i915_gem_ring_dispatch(params->request, params->dispatch_flags);
 
-       i915_gem_execbuffer_move_to_active(vmas, ring);
-       i915_gem_execbuffer_retire_commands(dev, file, ring, batch_obj);
+       i915_gem_execbuffer_move_to_active(vmas, params->request);
+       i915_gem_execbuffer_retire_commands(params);
 
        return 0;
 }
@@ -979,16 +996,15 @@ void intel_logical_ring_stop(struct intel_engine_cs *ring)
        I915_WRITE_MODE(ring, _MASKED_BIT_DISABLE(STOP_RING));
 }
 
-int logical_ring_flush_all_caches(struct intel_ringbuffer *ringbuf,
-                                 struct intel_context *ctx)
+int logical_ring_flush_all_caches(struct drm_i915_gem_request *req)
 {
-       struct intel_engine_cs *ring = ringbuf->ring;
+       struct intel_engine_cs *ring = req->ring;
        int ret;
 
        if (!ring->gpu_caches_dirty)
                return 0;
 
-       ret = ring->emit_flush(ringbuf, ctx, 0, I915_GEM_GPU_DOMAINS);
+       ret = ring->emit_flush(req, 0, I915_GEM_GPU_DOMAINS);
        if (ret)
                return ret;
 
@@ -1040,11 +1056,11 @@ void intel_lr_context_unpin(struct intel_engine_cs *ring,
        }
 }
 
-static int intel_logical_ring_workarounds_emit(struct intel_engine_cs *ring,
-                                              struct intel_context *ctx)
+static int intel_logical_ring_workarounds_emit(struct drm_i915_gem_request *req)
 {
        int ret, i;
-       struct intel_ringbuffer *ringbuf = ctx->engine[ring->id].ringbuf;
+       struct intel_engine_cs *ring = req->ring;
+       struct intel_ringbuffer *ringbuf = req->ringbuf;
        struct drm_device *dev = ring->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct i915_workarounds *w = &dev_priv->workarounds;
@@ -1053,11 +1069,11 @@ static int intel_logical_ring_workarounds_emit(struct intel_engine_cs *ring,
                return 0;
 
        ring->gpu_caches_dirty = true;
-       ret = logical_ring_flush_all_caches(ringbuf, ctx);
+       ret = logical_ring_flush_all_caches(req);
        if (ret)
                return ret;
 
-       ret = intel_logical_ring_begin(ringbuf, ctx, w->count * 2 + 2);
+       ret = intel_logical_ring_begin(ringbuf, req->ctx, w->count * 2 + 2);
        if (ret)
                return ret;
 
@@ -1071,7 +1087,7 @@ static int intel_logical_ring_workarounds_emit(struct intel_engine_cs *ring,
        intel_logical_ring_advance(ringbuf);
 
        ring->gpu_caches_dirty = true;
-       ret = logical_ring_flush_all_caches(ringbuf, ctx);
+       ret = logical_ring_flush_all_caches(req);
        if (ret)
                return ret;
 
@@ -1349,14 +1365,14 @@ static int gen9_init_render_ring(struct intel_engine_cs *ring)
        return init_workarounds_ring(ring);
 }
 
-static int gen8_emit_bb_start(struct intel_ringbuffer *ringbuf,
-                             struct intel_context *ctx,
+static int gen8_emit_bb_start(struct drm_i915_gem_request *req,
                              u64 offset, unsigned dispatch_flags)
 {
+       struct intel_ringbuffer *ringbuf = req->ringbuf;
        bool ppgtt = !(dispatch_flags & I915_DISPATCH_SECURE);
        int ret;
 
-       ret = intel_logical_ring_begin(ringbuf, ctx, 4);
+       ret = intel_logical_ring_begin(ringbuf, req->ctx, 4);
        if (ret)
                return ret;
 
@@ -1403,18 +1419,18 @@ static void gen8_logical_ring_put_irq(struct intel_engine_cs *ring)
        spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
 }
 
-static int gen8_emit_flush(struct intel_ringbuffer *ringbuf,
-                          struct intel_context *ctx,
+static int gen8_emit_flush(struct drm_i915_gem_request *request,
                           u32 invalidate_domains,
                           u32 unused)
 {
+       struct intel_ringbuffer *ringbuf = request->ringbuf;
        struct intel_engine_cs *ring = ringbuf->ring;
        struct drm_device *dev = ring->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        uint32_t cmd;
        int ret;
 
-       ret = intel_logical_ring_begin(ringbuf, ctx, 4);
+       ret = intel_logical_ring_begin(ringbuf, request->ctx, 4);
        if (ret)
                return ret;
 
@@ -1444,11 +1460,11 @@ static int gen8_emit_flush(struct intel_ringbuffer *ringbuf,
        return 0;
 }
 
-static int gen8_emit_flush_render(struct intel_ringbuffer *ringbuf,
-                                 struct intel_context *ctx,
+static int gen8_emit_flush_render(struct drm_i915_gem_request *request,
                                  u32 invalidate_domains,
                                  u32 flush_domains)
 {
+       struct intel_ringbuffer *ringbuf = request->ringbuf;
        struct intel_engine_cs *ring = ringbuf->ring;
        u32 scratch_addr = ring->scratch.gtt_offset + 2 * CACHELINE_BYTES;
        bool vf_flush_wa;
@@ -1480,7 +1496,7 @@ static int gen8_emit_flush_render(struct intel_ringbuffer *ringbuf,
        vf_flush_wa = INTEL_INFO(ring->dev)->gen >= 9 &&
                      flags & PIPE_CONTROL_VF_CACHE_INVALIDATE;
 
-       ret = intel_logical_ring_begin(ringbuf, ctx, vf_flush_wa ? 12 : 6);
+       ret = intel_logical_ring_begin(ringbuf, request->ctx, vf_flush_wa ? 12 : 6);
        if (ret)
                return ret;
 
@@ -1514,9 +1530,9 @@ static void gen8_set_seqno(struct intel_engine_cs *ring, u32 seqno)
        intel_write_status_page(ring, I915_GEM_HWS_INDEX, seqno);
 }
 
-static int gen8_emit_request(struct intel_ringbuffer *ringbuf,
-                            struct drm_i915_gem_request *request)
+static int gen8_emit_request(struct drm_i915_gem_request *request)
 {
+       struct intel_ringbuffer *ringbuf = request->ringbuf;
        struct intel_engine_cs *ring = ringbuf->ring;
        u32 cmd;
        int ret;
@@ -1538,8 +1554,7 @@ static int gen8_emit_request(struct intel_ringbuffer *ringbuf,
                                (ring->status_page.gfx_addr +
                                (I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT)));
        intel_logical_ring_emit(ringbuf, 0);
-       intel_logical_ring_emit(ringbuf,
-               i915_gem_request_get_seqno(ring->outstanding_lazy_request));
+       intel_logical_ring_emit(ringbuf, i915_gem_request_get_seqno(request));
        intel_logical_ring_emit(ringbuf, MI_USER_INTERRUPT);
        intel_logical_ring_emit(ringbuf, MI_NOOP);
        intel_logical_ring_advance_and_submit(ringbuf, request->ctx, request);
@@ -1555,49 +1570,39 @@ static int gen8_emit_request(struct intel_ringbuffer *ringbuf,
        return 0;
 }
 
-static int intel_lr_context_render_state_init(struct intel_engine_cs *ring,
-                                             struct intel_context *ctx)
+static int intel_lr_context_render_state_init(struct drm_i915_gem_request *req)
 {
-       struct intel_ringbuffer *ringbuf = ctx->engine[ring->id].ringbuf;
        struct render_state so;
-       struct drm_i915_file_private *file_priv = ctx->file_priv;
-       struct drm_file *file = file_priv ? file_priv->file : NULL;
        int ret;
 
-       ret = i915_gem_render_state_prepare(ring, &so);
+       ret = i915_gem_render_state_prepare(req->ring, &so);
        if (ret)
                return ret;
 
        if (so.rodata == NULL)
                return 0;
 
-       ret = ring->emit_bb_start(ringbuf,
-                       ctx,
-                       so.ggtt_offset,
-                       I915_DISPATCH_SECURE);
+       ret = req->ring->emit_bb_start(req, so.ggtt_offset,
+                                      I915_DISPATCH_SECURE);
        if (ret)
                goto out;
 
-       i915_vma_move_to_active(i915_gem_obj_to_ggtt(so.obj), ring);
+       i915_vma_move_to_active(i915_gem_obj_to_ggtt(so.obj), req);
 
-       ret = __i915_add_request(ring, file, so.obj);
-       /* intel_logical_ring_add_request moves object to inactive if it
-        * fails */
 out:
        i915_gem_render_state_fini(&so);
        return ret;
 }
 
-static int gen8_init_rcs_context(struct intel_engine_cs *ring,
-                      struct intel_context *ctx)
+static int gen8_init_rcs_context(struct drm_i915_gem_request *req)
 {
        int ret;
 
-       ret = intel_logical_ring_workarounds_emit(ring, ctx);
+       ret = intel_logical_ring_workarounds_emit(req);
        if (ret)
                return ret;
 
-       return intel_lr_context_render_state_init(ring, ctx);
+       return intel_lr_context_render_state_init(req);
 }
 
 /**
@@ -2216,13 +2221,22 @@ int intel_lr_context_deferred_create(struct intel_context *ctx,
                lrc_setup_hardware_status_page(ring, ctx_obj);
        else if (ring->id == RCS && !ctx->rcs_initialized) {
                if (ring->init_context) {
-                       ret = ring->init_context(ring, ctx);
+                       struct drm_i915_gem_request *req;
+
+                       ret = i915_gem_request_alloc(ring, ctx, &req);
+                       if (ret)
+                               return ret;
+
+                       ret = ring->init_context(req);
                        if (ret) {
                                DRM_ERROR("ring init context: %d\n", ret);
+                               i915_gem_request_cancel(req);
                                ctx->engine[ring->id].ringbuf = NULL;
                                ctx->engine[ring->id].state = NULL;
                                goto error;
                        }
+
+                       i915_add_request_no_flush(req);
                }
 
                ctx->rcs_initialized = true;
This page took 0.031155 seconds and 5 git commands to generate.