All of lore.kernel.org
 help / color / mirror / Atom feed
From: Chris Wilson <chris@chris-wilson.co.uk>
To: dri-devel@lists.freedesktop.org
Cc: intel-gfx@lists.freedesktop.org, christian.koenig@amd.com
Subject: [PATCH 6/6] dma-fence: Store the timestamp in the same union as the cb_list
Date: Sat, 17 Aug 2019 15:47:36 +0100	[thread overview]
Message-ID: <20190817144736.7826-6-chris@chris-wilson.co.uk> (raw)
In-Reply-To: <20190817144736.7826-1-chris@chris-wilson.co.uk>

The timestamp and the cb_list are mutually exclusive, the cb_list can
only be added to prior to being signaled (and once signaled we drain),
while the timestamp is only valid upon being signaled. Both the
timestamp and the cb_list are only valid while the fence is alive, and
as soon as no references are held can be replaced by the rcu_head.

By reusing the union for the timestamp, we squeeze the base dma_fence
struct to 64 bytes on x86-64.

Suggested-by: Christian König <christian.koenig@amd.com>
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Christian König <christian.koenig@amd.com>
---
 drivers/dma-buf/dma-fence.c                 | 16 +++++++++-------
 drivers/gpu/drm/i915/gt/intel_breadcrumbs.c | 13 +++++++------
 drivers/gpu/drm/vmwgfx/vmwgfx_fence.c       |  3 +++
 include/linux/dma-fence.h                   | 17 +++++++++++++----
 4 files changed, 32 insertions(+), 17 deletions(-)

diff --git a/drivers/dma-buf/dma-fence.c b/drivers/dma-buf/dma-fence.c
index 89d96e3e6df6..2c21115b1a37 100644
--- a/drivers/dma-buf/dma-fence.c
+++ b/drivers/dma-buf/dma-fence.c
@@ -129,6 +129,7 @@ EXPORT_SYMBOL(dma_fence_context_alloc);
 int dma_fence_signal_locked(struct dma_fence *fence)
 {
 	struct dma_fence_cb *cur, *tmp;
+	struct list_head cb_list;
 
 	lockdep_assert_held(fence->lock);
 
@@ -136,16 +137,16 @@ int dma_fence_signal_locked(struct dma_fence *fence)
 				      &fence->flags)))
 		return -EINVAL;
 
+	/* Stash the cb_list before replacing it with the timestamp */
+	list_replace(&fence->cb_list, &cb_list);
+
 	fence->timestamp = ktime_get();
 	set_bit(DMA_FENCE_FLAG_TIMESTAMP_BIT, &fence->flags);
 	trace_dma_fence_signaled(fence);
 
-	if (!list_empty(&fence->cb_list)) {
-		list_for_each_entry_safe(cur, tmp, &fence->cb_list, node) {
-			INIT_LIST_HEAD(&cur->node);
-			cur->func(fence, cur);
-		}
-		INIT_LIST_HEAD(&fence->cb_list);
+	list_for_each_entry_safe(cur, tmp, &cb_list, node) {
+		INIT_LIST_HEAD(&cur->node);
+		cur->func(fence, cur);
 	}
 
 	return 0;
@@ -234,7 +235,8 @@ void dma_fence_release(struct kref *kref)
 
 	trace_dma_fence_destroy(fence);
 
-	if (WARN(!list_empty(&fence->cb_list),
+	if (WARN(!list_empty(&fence->cb_list) &&
+		 !test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags),
 		 "Fence %s:%s:%llx:%llx released with pending signals!\n",
 		 fence->ops->get_driver_name(fence),
 		 fence->ops->get_timeline_name(fence),
diff --git a/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c b/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c
index 2bc9c460e78d..09c68dda2098 100644
--- a/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c
+++ b/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c
@@ -114,18 +114,18 @@ __dma_fence_signal__timestamp(struct dma_fence *fence, ktime_t timestamp)
 }
 
 static void
-__dma_fence_signal__notify(struct dma_fence *fence)
+__dma_fence_signal__notify(struct dma_fence *fence,
+			   const struct list_head *list)
 {
 	struct dma_fence_cb *cur, *tmp;
 
 	lockdep_assert_held(fence->lock);
 	lockdep_assert_irqs_disabled();
 
-	list_for_each_entry_safe(cur, tmp, &fence->cb_list, node) {
+	list_for_each_entry_safe(cur, tmp, list, node) {
 		INIT_LIST_HEAD(&cur->node);
 		cur->func(fence, cur);
 	}
-	INIT_LIST_HEAD(&fence->cb_list);
 }
 
 void intel_engine_breadcrumbs_irq(struct intel_engine_cs *engine)
@@ -187,11 +187,12 @@ void intel_engine_breadcrumbs_irq(struct intel_engine_cs *engine)
 	list_for_each_safe(pos, next, &signal) {
 		struct i915_request *rq =
 			list_entry(pos, typeof(*rq), signal_link);
-
-		__dma_fence_signal__timestamp(&rq->fence, timestamp);
+		struct list_head cb_list;
 
 		spin_lock(&rq->lock);
-		__dma_fence_signal__notify(&rq->fence);
+		list_replace(&rq->fence.cb_list, &cb_list);
+		__dma_fence_signal__timestamp(&rq->fence, timestamp);
+		__dma_fence_signal__notify(&rq->fence, &cb_list);
 		spin_unlock(&rq->lock);
 
 		i915_request_put(rq);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c
index 434dfadb0e52..178a6cd1a06f 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c
@@ -185,6 +185,9 @@ static long vmw_fence_wait(struct dma_fence *f, bool intr, signed long timeout)
 
 	spin_lock(f->lock);
 
+	if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &f->flags))
+		goto out;
+
 	if (intr && signal_pending(current)) {
 		ret = -ERESTARTSYS;
 		goto out;
diff --git a/include/linux/dma-fence.h b/include/linux/dma-fence.h
index 2ce4d877d33e..6c36502a0562 100644
--- a/include/linux/dma-fence.h
+++ b/include/linux/dma-fence.h
@@ -65,17 +65,26 @@ struct dma_fence_cb;
 struct dma_fence {
 	spinlock_t *lock;
 	const struct dma_fence_ops *ops;
-	/* We clear the callback list on kref_put so that by the time we
-	 * release the fence it is unused. No one should be adding to the cb_list
-	 * that they don't themselves hold a reference for.
+	/*
+	 * We clear the callback list on kref_put so that by the time we
+	 * release the fence it is unused. No one should be adding to the
+	 * cb_list that they don't themselves hold a reference for.
+	 *
+	 * The lifetime of the timestamp is similarly tied to both the
+	 * rcu freelist and the cb_list. The timestamp is only set upon
+	 * signaling while simultaneously notifying the cb_list. Ergo, we
+	 * only use either the cb_list of timestamp. Upon destruction,
+	 * neither are accessible, and so we can use the rcu. This means
+	 * that the cb_list is *only* valid until the signal bit is set,
+	 * and to read either you *must* hold a reference to the fence.
 	 */
 	union {
 		struct rcu_head rcu;
 		struct list_head cb_list;
+		ktime_t timestamp;
 	};
 	u64 context;
 	u64 seqno;
-	ktime_t timestamp;
 	unsigned long flags;
 	struct kref refcount;
 	int error;
-- 
2.23.0.rc1

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

  parent reply	other threads:[~2019-08-17 14:47 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-08-17 14:47 [PATCH 1/6] dma-buf: Introduce selftesting framework Chris Wilson
2019-08-17 14:47 ` [PATCH 2/6] dma-buf: Add selftests for dma-fence Chris Wilson
2019-08-17 14:47 ` [PATCH 3/6] dma-fence: Shrink size of struct dma_fence Chris Wilson
2019-08-17 14:47 ` [PATCH 4/6] dma-fence: Avoid list_del during fence->cb_list iteration Chris Wilson
2019-08-17 14:47 ` [PATCH 5/6] dma-fence: Simply wrap dma_fence_signal_locked with dma_fence_signal Chris Wilson
2019-08-17 15:16   ` Koenig, Christian
2019-08-17 15:23   ` [PATCH v3] " Chris Wilson
2019-08-17 15:25     ` Koenig, Christian
2019-08-17 14:47 ` Chris Wilson [this message]
2019-08-17 15:20   ` [PATCH 6/6] dma-fence: Store the timestamp in the same union as the cb_list Koenig, Christian
2019-08-17 15:27     ` Chris Wilson
2019-08-17 15:31       ` Koenig, Christian
2019-08-17 15:30   ` [PATCH v2] " Chris Wilson
2019-08-17 15:40     ` Koenig, Christian
2019-08-17 15:30 ` ✗ Fi.CI.CHECKPATCH: warning for series starting with [1/6] dma-buf: Introduce selftesting framework (rev2) Patchwork
2019-08-17 15:53 ` ✓ Fi.CI.BAT: success " Patchwork
2019-08-17 15:56 ` ✗ Fi.CI.CHECKPATCH: warning for series starting with [1/6] dma-buf: Introduce selftesting framework (rev3) Patchwork
2019-08-17 16:18 ` ✓ Fi.CI.BAT: success " Patchwork
2019-08-18  9:08 ` ✗ Fi.CI.IGT: failure " Patchwork

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20190817144736.7826-6-chris@chris-wilson.co.uk \
    --to=chris@chris-wilson.co.uk \
    --cc=christian.koenig@amd.com \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=intel-gfx@lists.freedesktop.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.