All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Thomas Hellström" <thomas.hellstrom@linux.intel.com>
To: intel-gfx@lists.freedesktop.org, dri-devel@lists.freedesktop.org
Cc: maarten.lankhorst@linux.intel.com, matthew.auld@intel.com,
	"Thomas Hellström" <thomas.hellstrom@linux.intel.com>
Subject: [Intel-gfx] [PATCH 4/6] drm/i915: Add a struct dma_fence_work timeline
Date: Fri,  8 Oct 2021 15:35:28 +0200	[thread overview]
Message-ID: <20211008133530.664509-5-thomas.hellstrom@linux.intel.com> (raw)
In-Reply-To: <20211008133530.664509-1-thomas.hellstrom@linux.intel.com>

The TTM managers and, possibly, the gtt address space managers will
need to be able to order fences for async operation.
Using dma_fence_is_later() for this will require that the fences we hand
them are from a single fence context and ordered.

Introduce a struct dma_fence_work_timeline, and a function to attach
struct dma_fence_work to such a timeline in a way that all previous
fences attached to the timeline will be signaled when the latest
attached struct dma_fence_work signals.

Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
---
 drivers/gpu/drm/i915/i915_sw_fence_work.c | 89 ++++++++++++++++++++++-
 drivers/gpu/drm/i915/i915_sw_fence_work.h | 58 +++++++++++++++
 2 files changed, 145 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_sw_fence_work.c b/drivers/gpu/drm/i915/i915_sw_fence_work.c
index 5b55cddafc9b..87cdb3158042 100644
--- a/drivers/gpu/drm/i915/i915_sw_fence_work.c
+++ b/drivers/gpu/drm/i915/i915_sw_fence_work.c
@@ -5,6 +5,66 @@
  */
 
 #include "i915_sw_fence_work.h"
+#include "i915_utils.h"
+
+/**
+ * dma_fence_work_timeline_attach - Attach a struct dma_fence_work to a
+ * timeline.
+ * @tl: The timeline to attach to.
+ * @f: The struct dma_fence_work.
+ * @tl_cb: The i915_sw_dma_fence_cb needed to attach to the
+ * timeline. This is typically embedded into the structure that also
+ * embeds the struct dma_fence_work.
+ *
+ * This function takes a timeline reference and associates it with the
+ * struct dma_fence_work. That reference is given up when the fence
+ * signals. Furthermore it assigns a fence context and a seqno to the
+ * dma-fence, and then chains upon the previous fence of the timeline
+ * if any, to make sure that the fence signals after that fence. The
+ * @tl_cb callback structure is needed for that chaining. Finally
+ * the registered last fence of the timeline is replaced by this fence, and
+ * the timeline takes a reference on the fence, which is released when
+ * the fence signals.
+ */
+void dma_fence_work_timeline_attach(struct dma_fence_work_timeline *tl,
+				    struct dma_fence_work *f,
+				    struct i915_sw_dma_fence_cb *tl_cb)
+{
+	struct dma_fence *await;
+
+	if (tl->ops->get)
+		tl->ops->get(tl);
+
+	spin_lock(&tl->lock);
+	await = tl->last_fence;
+	tl->last_fence = dma_fence_get(&f->dma);
+	f->dma.seqno = tl->seqno++;
+	f->dma.context = tl->context;
+	f->tl = tl;
+	spin_unlock(&tl->lock);
+
+	if (await) {
+		__i915_sw_fence_await_dma_fence(&f->chain, await, tl_cb);
+		dma_fence_put(await);
+	}
+}
+
+static void dma_fence_work_timeline_detach(struct dma_fence_work *f)
+{
+	struct dma_fence_work_timeline *tl = f->tl;
+	bool put = false;
+
+	spin_lock(&tl->lock);
+	if (tl->last_fence == &f->dma) {
+		put = true;
+		tl->last_fence = NULL;
+	}
+	spin_unlock(&tl->lock);
+	if (tl->ops->put)
+		tl->ops->put(tl);
+	if (put)
+		dma_fence_put(&f->dma);
+}
 
 static void dma_fence_work_complete(struct dma_fence_work *f)
 {
@@ -13,6 +73,9 @@ static void dma_fence_work_complete(struct dma_fence_work *f)
 	if (f->ops->release)
 		f->ops->release(f);
 
+	if (f->tl)
+		dma_fence_work_timeline_detach(f);
+
 	dma_fence_put(&f->dma);
 }
 
@@ -53,14 +116,17 @@ fence_notify(struct i915_sw_fence *fence, enum i915_sw_fence_notify state)
 
 static const char *get_driver_name(struct dma_fence *fence)
 {
-	return "dma-fence";
+	struct dma_fence_work *f = container_of(fence, typeof(*f), dma);
+
+	return (f->tl && f->tl->ops->name) ? f->tl->ops->name : "dma-fence";
 }
 
 static const char *get_timeline_name(struct dma_fence *fence)
 {
 	struct dma_fence_work *f = container_of(fence, typeof(*f), dma);
 
-	return f->ops->name ?: "work";
+	return (f->tl && f->tl->name) ? f->tl->name :
+		f->ops->name ?: "work";
 }
 
 static void fence_release(struct dma_fence *fence)
@@ -84,6 +150,7 @@ void dma_fence_work_init(struct dma_fence_work *f,
 {
 	f->ops = ops;
 	f->error = 0;
+	f->tl = NULL;
 	spin_lock_init(&f->lock);
 	dma_fence_init(&f->dma, &fence_ops, &f->lock, 0, 0);
 	i915_sw_fence_init(&f->chain, fence_notify);
@@ -97,3 +164,21 @@ int dma_fence_work_chain(struct dma_fence_work *f, struct dma_fence *signal)
 
 	return __i915_sw_fence_await_dma_fence(&f->chain, signal, &f->cb);
 }
+
+/**
+ * dma_fence_work_timeline_init - Initialize a dma_fence_work timeline
+ * @tl: The timeline to initialize,
+ * @name: The name of the timeline,
+ * @ops: The timeline operations.
+ */
+void dma_fence_work_timeline_init(struct dma_fence_work_timeline *tl,
+				  const char *name,
+				  const struct dma_fence_work_timeline_ops *ops)
+{
+	tl->name = name;
+	spin_lock_init(&tl->lock);
+	tl->context = dma_fence_context_alloc(1);
+	tl->seqno = 0;
+	tl->last_fence = NULL;
+	tl->ops = ops;
+}
diff --git a/drivers/gpu/drm/i915/i915_sw_fence_work.h b/drivers/gpu/drm/i915/i915_sw_fence_work.h
index caa59fb5252b..6f41ee360133 100644
--- a/drivers/gpu/drm/i915/i915_sw_fence_work.h
+++ b/drivers/gpu/drm/i915/i915_sw_fence_work.h
@@ -14,6 +14,53 @@
 #include "i915_sw_fence.h"
 
 struct dma_fence_work;
+struct dma_fence_work_timeline;
+
+/**
+ * struct dma_fence_work_timeline_ops - Timeline operations struct
+ * @name: Timeline ops name. This field is used if the timeline itself has
+ * a NULL name. Can be set to NULL in which case a default name is used.
+ *
+ * The struct dma_fence_work_timeline is intended to be embeddable.
+ * We use the ops to get and put the parent structure.
+ */
+struct dma_fence_work_timeline_ops {
+	/**
+	 * Timeline ops name. Used if the timeline itself has no name.
+	 */
+	const char *name;
+
+	/**
+	 * put() - Put the structure embedding the timeline
+	 * @tl: The timeline
+	 */
+	void (*put)(struct dma_fence_work_timeline *tl);
+
+	/**
+	 * get() - Get the structure embedding the timeline
+	 * @tl: The timeline
+	 */
+	void (*get)(struct dma_fence_work_timeline *tl);
+};
+
+/**
+ * struct dma_fence_work_timeline - Simple timeline struct for dma_fence_work
+ * @name: The name of the timeline. May be set to NULL. Immutable
+ * @lock: Protects mutable members of the structure.
+ * @context: The timeline fence context. Immutable.
+ * @seqno: The previous seqno used. Protected by @lock.
+ * @last_fence : The previous fence of the timeline. Protected by @lock.
+ * @ops: The timeline operations struct. Immutable.
+ */
+struct dma_fence_work_timeline {
+	const char *name;
+	/** Protects mutable members of the structure */
+	spinlock_t lock;
+	u64 context;
+	u64 seqno;
+	struct dma_fence *last_fence;
+	const struct dma_fence_work_timeline_ops *ops;
+};
 
 struct dma_fence_work_ops {
 	const char *name;
@@ -30,6 +77,9 @@ struct dma_fence_work {
 	struct i915_sw_dma_fence_cb cb;
 
 	struct work_struct work;
+
+	struct dma_fence_work_timeline *tl;
+
 	const struct dma_fence_work_ops *ops;
 };
 
@@ -65,4 +115,12 @@ static inline void dma_fence_work_commit_imm(struct dma_fence_work *f)
 	dma_fence_work_commit(f);
 }
 
+void dma_fence_work_timeline_attach(struct dma_fence_work_timeline *tl,
+				    struct dma_fence_work *f,
+				    struct i915_sw_dma_fence_cb *tl_cb);
+
+void dma_fence_work_timeline_init(struct dma_fence_work_timeline *tl,
+				  const char *name,
+				  const struct dma_fence_work_timeline_ops *ops);
+
 #endif /* I915_SW_FENCE_WORK_H */
-- 
2.31.1


WARNING: multiple messages have this Message-ID (diff)
From: "Thomas Hellström" <thomas.hellstrom@linux.intel.com>
To: intel-gfx@lists.freedesktop.org, dri-devel@lists.freedesktop.org
Cc: maarten.lankhorst@linux.intel.com, matthew.auld@intel.com,
	"Thomas Hellström" <thomas.hellstrom@linux.intel.com>
Subject: [PATCH 4/6] drm/i915: Add a struct dma_fence_work timeline
Date: Fri,  8 Oct 2021 15:35:28 +0200	[thread overview]
Message-ID: <20211008133530.664509-5-thomas.hellstrom@linux.intel.com> (raw)
In-Reply-To: <20211008133530.664509-1-thomas.hellstrom@linux.intel.com>

The TTM managers and, possibly, the gtt address space managers will
need to be able to order fences for async operation.
Using dma_fence_is_later() for this will require that the fences we hand
them are from a single fence context and ordered.

Introduce a struct dma_fence_work_timeline, and a function to attach
struct dma_fence_work to such a timeline in a way that all previous
fences attached to the timeline will be signaled when the latest
attached struct dma_fence_work signals.

Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
---
 drivers/gpu/drm/i915/i915_sw_fence_work.c | 89 ++++++++++++++++++++++-
 drivers/gpu/drm/i915/i915_sw_fence_work.h | 58 +++++++++++++++
 2 files changed, 145 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_sw_fence_work.c b/drivers/gpu/drm/i915/i915_sw_fence_work.c
index 5b55cddafc9b..87cdb3158042 100644
--- a/drivers/gpu/drm/i915/i915_sw_fence_work.c
+++ b/drivers/gpu/drm/i915/i915_sw_fence_work.c
@@ -5,6 +5,66 @@
  */
 
 #include "i915_sw_fence_work.h"
+#include "i915_utils.h"
+
+/**
+ * dma_fence_work_timeline_attach - Attach a struct dma_fence_work to a
+ * timeline.
+ * @tl: The timeline to attach to.
+ * @f: The struct dma_fence_work.
+ * @tl_cb: The i915_sw_dma_fence_cb needed to attach to the
+ * timeline. This is typically embedded into the structure that also
+ * embeds the struct dma_fence_work.
+ *
+ * This function takes a timeline reference and associates it with the
+ * struct dma_fence_work. That reference is given up when the fence
+ * signals. Furthermore it assigns a fence context and a seqno to the
+ * dma-fence, and then chains upon the previous fence of the timeline
+ * if any, to make sure that the fence signals after that fence. The
+ * @tl_cb callback structure is needed for that chaining. Finally
+ * the registered last fence of the timeline is replaced by this fence, and
+ * the timeline takes a reference on the fence, which is released when
+ * the fence signals.
+ */
+void dma_fence_work_timeline_attach(struct dma_fence_work_timeline *tl,
+				    struct dma_fence_work *f,
+				    struct i915_sw_dma_fence_cb *tl_cb)
+{
+	struct dma_fence *await;
+
+	if (tl->ops->get)
+		tl->ops->get(tl);
+
+	spin_lock(&tl->lock);
+	await = tl->last_fence;
+	tl->last_fence = dma_fence_get(&f->dma);
+	f->dma.seqno = tl->seqno++;
+	f->dma.context = tl->context;
+	f->tl = tl;
+	spin_unlock(&tl->lock);
+
+	if (await) {
+		__i915_sw_fence_await_dma_fence(&f->chain, await, tl_cb);
+		dma_fence_put(await);
+	}
+}
+
+static void dma_fence_work_timeline_detach(struct dma_fence_work *f)
+{
+	struct dma_fence_work_timeline *tl = f->tl;
+	bool put = false;
+
+	spin_lock(&tl->lock);
+	if (tl->last_fence == &f->dma) {
+		put = true;
+		tl->last_fence = NULL;
+	}
+	spin_unlock(&tl->lock);
+	if (tl->ops->put)
+		tl->ops->put(tl);
+	if (put)
+		dma_fence_put(&f->dma);
+}
 
 static void dma_fence_work_complete(struct dma_fence_work *f)
 {
@@ -13,6 +73,9 @@ static void dma_fence_work_complete(struct dma_fence_work *f)
 	if (f->ops->release)
 		f->ops->release(f);
 
+	if (f->tl)
+		dma_fence_work_timeline_detach(f);
+
 	dma_fence_put(&f->dma);
 }
 
@@ -53,14 +116,17 @@ fence_notify(struct i915_sw_fence *fence, enum i915_sw_fence_notify state)
 
 static const char *get_driver_name(struct dma_fence *fence)
 {
-	return "dma-fence";
+	struct dma_fence_work *f = container_of(fence, typeof(*f), dma);
+
+	return (f->tl && f->tl->ops->name) ? f->tl->ops->name : "dma-fence";
 }
 
 static const char *get_timeline_name(struct dma_fence *fence)
 {
 	struct dma_fence_work *f = container_of(fence, typeof(*f), dma);
 
-	return f->ops->name ?: "work";
+	return (f->tl && f->tl->name) ? f->tl->name :
+		f->ops->name ?: "work";
 }
 
 static void fence_release(struct dma_fence *fence)
@@ -84,6 +150,7 @@ void dma_fence_work_init(struct dma_fence_work *f,
 {
 	f->ops = ops;
 	f->error = 0;
+	f->tl = NULL;
 	spin_lock_init(&f->lock);
 	dma_fence_init(&f->dma, &fence_ops, &f->lock, 0, 0);
 	i915_sw_fence_init(&f->chain, fence_notify);
@@ -97,3 +164,21 @@ int dma_fence_work_chain(struct dma_fence_work *f, struct dma_fence *signal)
 
 	return __i915_sw_fence_await_dma_fence(&f->chain, signal, &f->cb);
 }
+
+/**
+ * dma_fence_work_timeline_init - Initialize a dma_fence_work timeline
+ * @tl: The timeline to initialize,
+ * @name: The name of the timeline,
+ * @ops: The timeline operations.
+ */
+void dma_fence_work_timeline_init(struct dma_fence_work_timeline *tl,
+				  const char *name,
+				  const struct dma_fence_work_timeline_ops *ops)
+{
+	tl->name = name;
+	spin_lock_init(&tl->lock);
+	tl->context = dma_fence_context_alloc(1);
+	tl->seqno = 0;
+	tl->last_fence = NULL;
+	tl->ops = ops;
+}
diff --git a/drivers/gpu/drm/i915/i915_sw_fence_work.h b/drivers/gpu/drm/i915/i915_sw_fence_work.h
index caa59fb5252b..6f41ee360133 100644
--- a/drivers/gpu/drm/i915/i915_sw_fence_work.h
+++ b/drivers/gpu/drm/i915/i915_sw_fence_work.h
@@ -14,6 +14,53 @@
 #include "i915_sw_fence.h"
 
 struct dma_fence_work;
+struct dma_fence_work_timeline;
+
+/**
+ * struct dma_fence_work_timeline_ops - Timeline operations struct
+ * @name: Timeline ops name. This field is used if the timeline itself has
+ * a NULL name. Can be set to NULL in which case a default name is used.
+ *
+ * The struct dma_fence_work_timeline is intended to be embeddable.
+ * We use the ops to get and put the parent structure.
+ */
+struct dma_fence_work_timeline_ops {
+	/**
+	 * Timeline ops name. Used if the timeline itself has no name.
+	 */
+	const char *name;
+
+	/**
+	 * put() - Put the structure embedding the timeline
+	 * @tl: The timeline
+	 */
+	void (*put)(struct dma_fence_work_timeline *tl);
+
+	/**
+	 * get() - Get the structure embedding the timeline
+	 * @tl: The timeline
+	 */
+	void (*get)(struct dma_fence_work_timeline *tl);
+};
+
+/**
+ * struct dma_fence_work_timeline - Simple timeline struct for dma_fence_work
+ * @name: The name of the timeline. May be set to NULL. Immutable
+ * @lock: Protects mutable members of the structure.
+ * @context: The timeline fence context. Immutable.
+ * @seqno: The previous seqno used. Protected by @lock.
+ * @last_fence : The previous fence of the timeline. Protected by @lock.
+ * @ops: The timeline operations struct. Immutable.
+ */
+struct dma_fence_work_timeline {
+	const char *name;
+	/** Protects mutable members of the structure */
+	spinlock_t lock;
+	u64 context;
+	u64 seqno;
+	struct dma_fence *last_fence;
+	const struct dma_fence_work_timeline_ops *ops;
+};
 
 struct dma_fence_work_ops {
 	const char *name;
@@ -30,6 +77,9 @@ struct dma_fence_work {
 	struct i915_sw_dma_fence_cb cb;
 
 	struct work_struct work;
+
+	struct dma_fence_work_timeline *tl;
+
 	const struct dma_fence_work_ops *ops;
 };
 
@@ -65,4 +115,12 @@ static inline void dma_fence_work_commit_imm(struct dma_fence_work *f)
 	dma_fence_work_commit(f);
 }
 
+void dma_fence_work_timeline_attach(struct dma_fence_work_timeline *tl,
+				    struct dma_fence_work *f,
+				    struct i915_sw_dma_fence_cb *tl_cb);
+
+void dma_fence_work_timeline_init(struct dma_fence_work_timeline *tl,
+				  const char *name,
+				  const struct dma_fence_work_timeline_ops *ops);
+
 #endif /* I915_SW_FENCE_WORK_H */
-- 
2.31.1


  parent reply	other threads:[~2021-10-08 13:36 UTC|newest]

Thread overview: 33+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-10-08 13:35 [Intel-gfx] [PATCH 0/6] drm/i915: Failsafe migration blits Thomas Hellström
2021-10-08 13:35 ` Thomas Hellström
2021-10-08 13:35 ` [Intel-gfx] [PATCH 1/6] drm/i915: Update dma_fence_work Thomas Hellström
2021-10-08 13:35   ` Thomas Hellström
2021-10-13 12:41   ` [Intel-gfx] " Daniel Vetter
2021-10-13 12:41     ` Daniel Vetter
2021-10-13 12:59     ` [Intel-gfx] " Thomas Hellström
2021-10-13 12:59       ` Thomas Hellström
2021-10-08 13:35 ` [Intel-gfx] [PATCH 2/6] drm/i915: Introduce refcounted sg-tables Thomas Hellström
2021-10-08 13:35   ` Thomas Hellström
2021-10-13 14:41   ` [Intel-gfx] " Daniel Vetter
2021-10-13 14:41     ` Daniel Vetter
2021-10-13 14:55     ` [Intel-gfx] " Thomas Hellström
2021-10-13 14:55       ` Thomas Hellström
2021-10-08 13:35 ` [Intel-gfx] [PATCH 3/6] drm/i915/ttm: Failsafe migration blits Thomas Hellström
2021-10-08 13:35   ` Thomas Hellström
2021-10-08 13:35 ` Thomas Hellström [this message]
2021-10-08 13:35   ` [PATCH 4/6] drm/i915: Add a struct dma_fence_work timeline Thomas Hellström
2021-10-13 12:43   ` [Intel-gfx] " Daniel Vetter
2021-10-13 14:21     ` Thomas Hellström
2021-10-13 14:33       ` Daniel Vetter
2021-10-13 14:39         ` Thomas Hellström
2021-10-08 13:35 ` [Intel-gfx] [PATCH 5/6] drm/i915/ttm: Attach the migration fence to a region timeline on eviction Thomas Hellström
2021-10-08 13:35   ` Thomas Hellström
2021-10-08 13:35 ` [Intel-gfx] [PATCH 6/6] drm/i915: Use irq work for coalescing-only dma-fence-work Thomas Hellström
2021-10-08 13:35   ` Thomas Hellström
2021-10-08 17:00 ` [Intel-gfx] ✗ Fi.CI.SPARSE: warning for drm/i915: Failsafe migration blits Patchwork
2021-10-08 17:29 ` [Intel-gfx] ✓ Fi.CI.BAT: success " Patchwork
2021-10-09  0:04 ` [Intel-gfx] ✗ Fi.CI.IGT: failure " Patchwork
2021-10-14  1:50 ` [Intel-gfx] [PATCH 0/6] " Dave Airlie
2021-10-14  1:50   ` Dave Airlie
2021-10-14  7:29   ` [Intel-gfx] " Thomas Hellström
2021-10-14  7:29     ` Thomas Hellström

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=20211008133530.664509-5-thomas.hellstrom@linux.intel.com \
    --to=thomas.hellstrom@linux.intel.com \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=intel-gfx@lists.freedesktop.org \
    --cc=maarten.lankhorst@linux.intel.com \
    --cc=matthew.auld@intel.com \
    /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.