drm/i915: Allow i915_sw_fence_await_sw_fence() to allocate
authorChris Wilson <chris@chris-wilson.co.uk>
Fri, 28 Oct 2016 12:58:25 +0000 (13:58 +0100)
committerChris Wilson <chris@chris-wilson.co.uk>
Fri, 28 Oct 2016 19:53:42 +0000 (20:53 +0100)
In forthcoming patches, we want to be able to dynamically allocate the
wait_queue_t used whilst awaiting. This is more convenient if we extend
the i915_sw_fence_await_sw_fence() to perform the allocation for us if
we pass in a gfp mask as an alternative than a preallocated struct.

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/20161028125858.23563-2-chris@chris-wilson.co.uk
drivers/gpu/drm/i915/i915_sw_fence.c
drivers/gpu/drm/i915/i915_sw_fence.h

index 8185002d7ec8142c14a946e1b3dea02ab8ed4403..95f2f12e0917ea4339994a6c2fc2d5a78350a7ec 100644 (file)
@@ -13,6 +13,8 @@
 
 #include "i915_sw_fence.h"
 
+#define I915_SW_FENCE_FLAG_ALLOC BIT(3) /* after WQ_FLAG_* for safety */
+
 static DEFINE_SPINLOCK(i915_sw_fence_lock);
 
 static int __i915_sw_fence_notify(struct i915_sw_fence *fence,
@@ -135,6 +137,8 @@ static int i915_sw_fence_wake(wait_queue_t *wq, unsigned mode, int flags, void *
        list_del(&wq->task_list);
        __i915_sw_fence_complete(wq->private, key);
        i915_sw_fence_put(wq->private);
+       if (wq->flags & I915_SW_FENCE_FLAG_ALLOC)
+               kfree(wq);
        return 0;
 }
 
@@ -192,9 +196,9 @@ static bool i915_sw_fence_check_if_after(struct i915_sw_fence *fence,
        return err;
 }
 
-int i915_sw_fence_await_sw_fence(struct i915_sw_fence *fence,
-                                struct i915_sw_fence *signaler,
-                                wait_queue_t *wq)
+static int __i915_sw_fence_await_sw_fence(struct i915_sw_fence *fence,
+                                         struct i915_sw_fence *signaler,
+                                         wait_queue_t *wq, gfp_t gfp)
 {
        unsigned long flags;
        int pending;
@@ -206,8 +210,22 @@ int i915_sw_fence_await_sw_fence(struct i915_sw_fence *fence,
        if (unlikely(i915_sw_fence_check_if_after(fence, signaler)))
                return -EINVAL;
 
+       pending = 0;
+       if (!wq) {
+               wq = kmalloc(sizeof(*wq), gfp);
+               if (!wq) {
+                       if (!gfpflags_allow_blocking(gfp))
+                               return -ENOMEM;
+
+                       i915_sw_fence_wait(signaler);
+                       return 0;
+               }
+
+               pending |= I915_SW_FENCE_FLAG_ALLOC;
+       }
+
        INIT_LIST_HEAD(&wq->task_list);
-       wq->flags = 0;
+       wq->flags = pending;
        wq->func = i915_sw_fence_wake;
        wq->private = i915_sw_fence_get(fence);
 
@@ -226,6 +244,20 @@ int i915_sw_fence_await_sw_fence(struct i915_sw_fence *fence,
        return pending;
 }
 
+int i915_sw_fence_await_sw_fence(struct i915_sw_fence *fence,
+                                struct i915_sw_fence *signaler,
+                                wait_queue_t *wq)
+{
+       return __i915_sw_fence_await_sw_fence(fence, signaler, wq, 0);
+}
+
+int i915_sw_fence_await_sw_fence_gfp(struct i915_sw_fence *fence,
+                                    struct i915_sw_fence *signaler,
+                                    gfp_t gfp)
+{
+       return __i915_sw_fence_await_sw_fence(fence, signaler, NULL, gfp);
+}
+
 struct i915_sw_dma_fence_cb {
        struct dma_fence_cb base;
        struct i915_sw_fence *fence;
index cd239e92f67f9ade2ea8711acd0907877363939d..707dfc4f0da5d54b646224c475e30242c526249d 100644 (file)
@@ -46,6 +46,9 @@ void i915_sw_fence_commit(struct i915_sw_fence *fence);
 int i915_sw_fence_await_sw_fence(struct i915_sw_fence *fence,
                                 struct i915_sw_fence *after,
                                 wait_queue_t *wq);
+int i915_sw_fence_await_sw_fence_gfp(struct i915_sw_fence *fence,
+                                    struct i915_sw_fence *after,
+                                    gfp_t gfp);
 int i915_sw_fence_await_dma_fence(struct i915_sw_fence *fence,
                                  struct dma_fence *dma,
                                  unsigned long timeout,
@@ -62,4 +65,9 @@ static inline bool i915_sw_fence_done(const struct i915_sw_fence *fence)
        return atomic_read(&fence->pending) < 0;
 }
 
+static inline void i915_sw_fence_wait(struct i915_sw_fence *fence)
+{
+       wait_event(fence->wait, i915_sw_fence_done(fence));
+}
+
 #endif /* _I915_SW_FENCE_H_ */