[PATCH 68/74] drm/i915: Add asynchronous waits on a value to change from non-zero

Chris Wilson chris at chris-wilson.co.uk
Sun Jul 16 19:01:09 UTC 2017


Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
---
 drivers/gpu/drm/i915/i915_sw_fence.c | 58 ++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/i915_sw_fence.h |  4 +++
 2 files changed, 62 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_sw_fence.c b/drivers/gpu/drm/i915/i915_sw_fence.c
index 742ea4c5d2c9..27fdb3c5283a 100644
--- a/drivers/gpu/drm/i915/i915_sw_fence.c
+++ b/drivers/gpu/drm/i915/i915_sw_fence.c
@@ -533,6 +533,64 @@ int i915_sw_fence_await_completion(struct i915_sw_fence *fence,
 	return pending;
 }
 
+struct wait_value {
+	wait_queue_t base;
+	unsigned int *value;
+};
+
+static int i915_sw_fence_wake_value(wait_queue_t *wq,
+				    unsigned mode, int flags, void *key)
+{
+	struct wait_value *wv = container_of(wq, typeof(*wv), base);
+
+	if (!READ_ONCE(*wv->value))
+		return 0;
+
+	return i915_sw_fence_wake(wq, mode, flags, key);
+}
+
+int i915_sw_fence_await_value(struct i915_sw_fence *fence,
+			      wait_queue_head_t *wait,
+			      unsigned int *value,
+			      gfp_t gfp)
+{
+	struct wait_value *wv;
+	unsigned long flags;
+	int pending;
+
+	if (READ_ONCE(*value))
+		return 0;
+
+	wv = kmalloc(sizeof(*wv), gfp);
+	if (unlikely(!wv)) {
+		if (!gfpflags_allow_blocking(gfp))
+			return -ENOMEM;
+
+		wait_event(*wait, READ_ONCE(*value));
+		return 0;
+	}
+
+	INIT_LIST_HEAD(&wv->base.task_list);
+	wv->base.flags = I915_SW_FENCE_FLAG_ALLOC;
+	wv->base.func = i915_sw_fence_wake_value;
+	wv->base.private = fence;
+	wv->value = value;
+
+	i915_sw_fence_await(fence);
+
+	spin_lock_irqsave(&wait->lock, flags);
+	if (!READ_ONCE(*value)) {
+		__add_wait_queue_tail(wait, &wv->base);
+		pending = 1;
+	} else {
+		i915_sw_fence_wake(&wv->base, 0, 0, NULL);
+		pending = 0;
+	}
+	spin_unlock_irqrestore(&wait->lock, flags);
+
+	return pending;
+}
+
 #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
 #include "selftests/i915_sw_fence.c"
 #endif
diff --git a/drivers/gpu/drm/i915/i915_sw_fence.h b/drivers/gpu/drm/i915/i915_sw_fence.h
index 92832a07b8ee..2d2ac872ec86 100644
--- a/drivers/gpu/drm/i915/i915_sw_fence.h
+++ b/drivers/gpu/drm/i915/i915_sw_fence.h
@@ -69,6 +69,10 @@ int i915_sw_fence_await_sw_fence(struct i915_sw_fence *fence,
 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_value(struct i915_sw_fence *fence,
+			      wait_queue_head_t *wait,
+			      unsigned int *value,
+			      gfp_t gfp);
 int i915_sw_fence_await_completion(struct i915_sw_fence *fence,
 				   struct completion *x,
 				   gfp_t gfp);
-- 
2.13.2



More information about the Intel-gfx-trybot mailing list