drm/i915: Extend execution fence to support a callback
authorChris Wilson <chris@chris-wilson.co.uk>
Tue, 21 May 2019 21:11:32 +0000 (22:11 +0100)
committerChris Wilson <chris@chris-wilson.co.uk>
Wed, 22 May 2019 07:40:45 +0000 (08:40 +0100)
In the next patch, we will want to configure the slave request
depending on which physical engine the master request is executed on.
For this, we introduce a callback from the execute fence to convey this
information.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20190521211134.16117-8-chris@chris-wilson.co.uk
drivers/gpu/drm/i915/i915_request.c
drivers/gpu/drm/i915/i915_request.h

index 809d6ee10da6633c1701575d5bfa74f50a5bb6be..18b34b0bf87255f9b1ec9fcc5c6f2f7b4668606c 100644 (file)
@@ -38,6 +38,8 @@ struct execute_cb {
        struct list_head link;
        struct irq_work work;
        struct i915_sw_fence *fence;
+       void (*hook)(struct i915_request *rq, struct dma_fence *signal);
+       struct i915_request *signal;
 };
 
 static struct i915_global_request {
@@ -329,6 +331,17 @@ static void irq_execute_cb(struct irq_work *wrk)
        kmem_cache_free(global.slab_execute_cbs, cb);
 }
 
+static void irq_execute_cb_hook(struct irq_work *wrk)
+{
+       struct execute_cb *cb = container_of(wrk, typeof(*cb), work);
+
+       cb->hook(container_of(cb->fence, struct i915_request, submit),
+                &cb->signal->fence);
+       i915_request_put(cb->signal);
+
+       irq_execute_cb(wrk);
+}
+
 static void __notify_execute_cb(struct i915_request *rq)
 {
        struct execute_cb *cb;
@@ -355,14 +368,19 @@ static void __notify_execute_cb(struct i915_request *rq)
 }
 
 static int
-i915_request_await_execution(struct i915_request *rq,
-                            struct i915_request *signal,
-                            gfp_t gfp)
+__i915_request_await_execution(struct i915_request *rq,
+                              struct i915_request *signal,
+                              void (*hook)(struct i915_request *rq,
+                                           struct dma_fence *signal),
+                              gfp_t gfp)
 {
        struct execute_cb *cb;
 
-       if (i915_request_is_active(signal))
+       if (i915_request_is_active(signal)) {
+               if (hook)
+                       hook(rq, &signal->fence);
                return 0;
+       }
 
        cb = kmem_cache_alloc(global.slab_execute_cbs, gfp);
        if (!cb)
@@ -372,8 +390,18 @@ i915_request_await_execution(struct i915_request *rq,
        i915_sw_fence_await(cb->fence);
        init_irq_work(&cb->work, irq_execute_cb);
 
+       if (hook) {
+               cb->hook = hook;
+               cb->signal = i915_request_get(signal);
+               cb->work.func = irq_execute_cb_hook;
+       }
+
        spin_lock_irq(&signal->lock);
        if (i915_request_is_active(signal)) {
+               if (hook) {
+                       hook(rq, &signal->fence);
+                       i915_request_put(signal);
+               }
                i915_sw_fence_complete(cb->fence);
                kmem_cache_free(global.slab_execute_cbs, cb);
        } else {
@@ -834,7 +862,7 @@ emit_semaphore_wait(struct i915_request *to,
                return err;
 
        /* Only submit our spinner after the signaler is running! */
-       err = i915_request_await_execution(to, from, gfp);
+       err = __i915_request_await_execution(to, from, NULL, gfp);
        if (err)
                return err;
 
@@ -970,6 +998,52 @@ i915_request_await_dma_fence(struct i915_request *rq, struct dma_fence *fence)
        return 0;
 }
 
+int
+i915_request_await_execution(struct i915_request *rq,
+                            struct dma_fence *fence,
+                            void (*hook)(struct i915_request *rq,
+                                         struct dma_fence *signal))
+{
+       struct dma_fence **child = &fence;
+       unsigned int nchild = 1;
+       int ret;
+
+       if (dma_fence_is_array(fence)) {
+               struct dma_fence_array *array = to_dma_fence_array(fence);
+
+               /* XXX Error for signal-on-any fence arrays */
+
+               child = array->fences;
+               nchild = array->num_fences;
+               GEM_BUG_ON(!nchild);
+       }
+
+       do {
+               fence = *child++;
+               if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags))
+                       continue;
+
+               /*
+                * We don't squash repeated fence dependencies here as we
+                * want to run our callback in all cases.
+                */
+
+               if (dma_fence_is_i915(fence))
+                       ret = __i915_request_await_execution(rq,
+                                                            to_request(fence),
+                                                            hook,
+                                                            I915_FENCE_GFP);
+               else
+                       ret = i915_sw_fence_await_dma_fence(&rq->submit, fence,
+                                                           I915_FENCE_TIMEOUT,
+                                                           GFP_KERNEL);
+               if (ret < 0)
+                       return ret;
+       } while (--nchild);
+
+       return 0;
+}
+
 /**
  * i915_request_await_object - set this request to (async) wait upon a bo
  * @to: request we are wishing to use
index d7f9b2194568be8d6143cc1f5f528212108af954..c9f7d07991c831fa1797bb68aa191ac67045e1d5 100644 (file)
@@ -283,6 +283,10 @@ int i915_request_await_object(struct i915_request *to,
                              bool write);
 int i915_request_await_dma_fence(struct i915_request *rq,
                                 struct dma_fence *fence);
+int i915_request_await_execution(struct i915_request *rq,
+                                struct dma_fence *fence,
+                                void (*hook)(struct i915_request *rq,
+                                             struct dma_fence *signal));
 
 void i915_request_add(struct i915_request *rq);