From: Maarten Lankhorst <maarten.lankhorst@canonical.com>
To: gregkh@linuxfoundation.org
Cc: linux-arch@vger.kernel.org, thellstrom@vmware.com,
linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org,
linaro-mm-sig@lists.linaro.org, robdclark@gmail.com,
thierry.reding@gmail.com, ccross@google.com, daniel@ffwll.ch,
sumit.semwal@linaro.org, linux-media@vger.kernel.org
Subject: [REPOST PATCH 2/8] seqno-fence: Hardware dma-buf implementation of fencing (v5)
Date: Wed, 18 Jun 2014 12:37:00 +0200 [thread overview]
Message-ID: <20140618103659.15728.36087.stgit@patser> (raw)
In-Reply-To: <20140618102957.15728.43525.stgit@patser>
This type of fence can be used with hardware synchronization for simple
hardware that can block execution until the condition
(dma_buf[offset] - value) >= 0 has been met when WAIT_GEQUAL is used,
or (dma_buf[offset] != 0) has been met when WAIT_NONZERO is set.
A software fallback still has to be provided in case the fence is used
with a device that doesn't support this mechanism. It is useful to expose
this for graphics cards that have an op to support this.
Some cards like i915 can export those, but don't have an option to wait,
so they need the software fallback.
I extended the original patch by Rob Clark.
v1: Original
v2: Renamed from bikeshed to seqno, moved into dma-fence.c since
not much was left of the file. Lots of documentation added.
v3: Use fence_ops instead of custom callbacks. Moved to own file
to avoid circular dependency between dma-buf.h and fence.h
v4: Add spinlock pointer to seqno_fence_init
v5: Add condition member to allow wait for != 0.
Fix small style errors pointed out by checkpatch.
Signed-off-by: Maarten Lankhorst <maarten.lankhorst@canonical.com>
Reviewed-by: Rob Clark <robdclark@gmail.com> #v4
---
Documentation/DocBook/device-drivers.tmpl | 1
drivers/base/fence.c | 52 +++++++++++++
include/linux/seqno-fence.h | 119 +++++++++++++++++++++++++++++
3 files changed, 172 insertions(+)
create mode 100644 include/linux/seqno-fence.h
diff --git a/Documentation/DocBook/device-drivers.tmpl b/Documentation/DocBook/device-drivers.tmpl
index 7eef81069d1b..6ca7a11fb893 100644
--- a/Documentation/DocBook/device-drivers.tmpl
+++ b/Documentation/DocBook/device-drivers.tmpl
@@ -131,6 +131,7 @@ X!Edrivers/base/interface.c
!Edrivers/base/dma-buf.c
!Edrivers/base/fence.c
!Iinclude/linux/fence.h
+!Iinclude/linux/seqno-fence.h
!Edrivers/base/reservation.c
!Iinclude/linux/reservation.h
!Edrivers/base/dma-coherent.c
diff --git a/drivers/base/fence.c b/drivers/base/fence.c
index 1da7f4d6542a..752a2dfa505f 100644
--- a/drivers/base/fence.c
+++ b/drivers/base/fence.c
@@ -25,6 +25,7 @@
#include <linux/export.h>
#include <linux/atomic.h>
#include <linux/fence.h>
+#include <linux/seqno-fence.h>
#define CREATE_TRACE_POINTS
#include <trace/events/fence.h>
@@ -414,3 +415,54 @@ __fence_init(struct fence *fence, const struct fence_ops *ops,
trace_fence_init(fence);
}
EXPORT_SYMBOL(__fence_init);
+
+static const char *seqno_fence_get_driver_name(struct fence *fence)
+{
+ struct seqno_fence *seqno_fence = to_seqno_fence(fence);
+ return seqno_fence->ops->get_driver_name(fence);
+}
+
+static const char *seqno_fence_get_timeline_name(struct fence *fence)
+{
+ struct seqno_fence *seqno_fence = to_seqno_fence(fence);
+ return seqno_fence->ops->get_timeline_name(fence);
+}
+
+static bool seqno_enable_signaling(struct fence *fence)
+{
+ struct seqno_fence *seqno_fence = to_seqno_fence(fence);
+ return seqno_fence->ops->enable_signaling(fence);
+}
+
+static bool seqno_signaled(struct fence *fence)
+{
+ struct seqno_fence *seqno_fence = to_seqno_fence(fence);
+ return seqno_fence->ops->signaled && seqno_fence->ops->signaled(fence);
+}
+
+static void seqno_release(struct fence *fence)
+{
+ struct seqno_fence *f = to_seqno_fence(fence);
+
+ dma_buf_put(f->sync_buf);
+ if (f->ops->release)
+ f->ops->release(fence);
+ else
+ kfree(f);
+}
+
+static long seqno_wait(struct fence *fence, bool intr, signed long timeout)
+{
+ struct seqno_fence *f = to_seqno_fence(fence);
+ return f->ops->wait(fence, intr, timeout);
+}
+
+const struct fence_ops seqno_fence_ops = {
+ .get_driver_name = seqno_fence_get_driver_name,
+ .get_timeline_name = seqno_fence_get_timeline_name,
+ .enable_signaling = seqno_enable_signaling,
+ .signaled = seqno_signaled,
+ .wait = seqno_wait,
+ .release = seqno_release,
+};
+EXPORT_SYMBOL(seqno_fence_ops);
diff --git a/include/linux/seqno-fence.h b/include/linux/seqno-fence.h
new file mode 100644
index 000000000000..b4d4aad3cadc
--- /dev/null
+++ b/include/linux/seqno-fence.h
@@ -0,0 +1,119 @@
+/*
+ * seqno-fence, using a dma-buf to synchronize fencing
+ *
+ * Copyright (C) 2012 Texas Instruments
+ * Copyright (C) 2012 Canonical Ltd
+ * Authors:
+ * Rob Clark <robdclark@gmail.com>
+ * Maarten Lankhorst <maarten.lankhorst@canonical.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __LINUX_SEQNO_FENCE_H
+#define __LINUX_SEQNO_FENCE_H
+
+#include <linux/fence.h>
+#include <linux/dma-buf.h>
+
+enum seqno_fence_condition {
+ SEQNO_FENCE_WAIT_GEQUAL,
+ SEQNO_FENCE_WAIT_NONZERO
+};
+
+struct seqno_fence {
+ struct fence base;
+
+ const struct fence_ops *ops;
+ struct dma_buf *sync_buf;
+ uint32_t seqno_ofs;
+ enum seqno_fence_condition condition;
+};
+
+extern const struct fence_ops seqno_fence_ops;
+
+/**
+ * to_seqno_fence - cast a fence to a seqno_fence
+ * @fence: fence to cast to a seqno_fence
+ *
+ * Returns NULL if the fence is not a seqno_fence,
+ * or the seqno_fence otherwise.
+ */
+static inline struct seqno_fence *
+to_seqno_fence(struct fence *fence)
+{
+ if (fence->ops != &seqno_fence_ops)
+ return NULL;
+ return container_of(fence, struct seqno_fence, base);
+}
+
+/**
+ * seqno_fence_init - initialize a seqno fence
+ * @fence: seqno_fence to initialize
+ * @lock: pointer to spinlock to use for fence
+ * @sync_buf: buffer containing the memory location to signal on
+ * @context: the execution context this fence is a part of
+ * @seqno_ofs: the offset within @sync_buf
+ * @seqno: the sequence # to signal on
+ * @ops: the fence_ops for operations on this seqno fence
+ *
+ * This function initializes a struct seqno_fence with passed parameters,
+ * and takes a reference on sync_buf which is released on fence destruction.
+ *
+ * A seqno_fence is a dma_fence which can complete in software when
+ * enable_signaling is called, but it also completes when
+ * (s32)((sync_buf)[seqno_ofs] - seqno) >= 0 is true
+ *
+ * The seqno_fence will take a refcount on the sync_buf until it's
+ * destroyed, but actual lifetime of sync_buf may be longer if one of the
+ * callers take a reference to it.
+ *
+ * Certain hardware have instructions to insert this type of wait condition
+ * in the command stream, so no intervention from software would be needed.
+ * This type of fence can be destroyed before completed, however a reference
+ * on the sync_buf dma-buf can be taken. It is encouraged to re-use the same
+ * dma-buf for sync_buf, since mapping or unmapping the sync_buf to the
+ * device's vm can be expensive.
+ *
+ * It is recommended for creators of seqno_fence to call fence_signal
+ * before destruction. This will prevent possible issues from wraparound at
+ * time of issue vs time of check, since users can check fence_is_signaled
+ * before submitting instructions for the hardware to wait on the fence.
+ * However, when ops.enable_signaling is not called, it doesn't have to be
+ * done as soon as possible, just before there's any real danger of seqno
+ * wraparound.
+ */
+static inline void
+seqno_fence_init(struct seqno_fence *fence, spinlock_t *lock,
+ struct dma_buf *sync_buf, uint32_t context,
+ uint32_t seqno_ofs, uint32_t seqno,
+ enum seqno_fence_condition cond,
+ const struct fence_ops *ops)
+{
+ BUG_ON(!fence || !sync_buf || !ops);
+ BUG_ON(!ops->wait || !ops->enable_signaling ||
+ !ops->get_driver_name || !ops->get_timeline_name);
+
+ /*
+ * ops is used in __fence_init for get_driver_name, so needs to be
+ * initialized first
+ */
+ fence->ops = ops;
+ __fence_init(&fence->base, &seqno_fence_ops, lock, context, seqno);
+ get_dma_buf(sync_buf);
+ fence->sync_buf = sync_buf;
+ fence->seqno_ofs = seqno_ofs;
+ fence->condition = cond;
+}
+
+#endif /* __LINUX_SEQNO_FENCE_H */
next prev parent reply other threads:[~2014-06-18 10:37 UTC|newest]
Thread overview: 45+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-06-18 10:36 [REPOST PATCH 0/8] fence synchronization patches Maarten Lankhorst
2014-06-18 10:36 ` [REPOST PATCH 1/8] fence: dma-buf cross-device synchronization (v17) Maarten Lankhorst
2014-06-19 1:13 ` Greg KH
2014-06-19 1:23 ` Rob Clark
2014-06-19 1:44 ` Greg KH
2014-06-19 14:00 ` Rob Clark
2014-06-19 17:00 ` Greg KH
2014-06-19 17:45 ` Rob Clark
2014-06-19 18:19 ` Greg KH
2014-06-19 18:37 ` James Bottomley
2014-06-19 18:52 ` Rob Clark
2014-06-19 19:20 ` Daniel Vetter
2014-06-19 21:50 ` Dave Airlie
2014-06-19 23:21 ` Rob Clark
2014-06-19 19:15 ` Daniel Vetter
2014-06-19 20:01 ` Greg KH
2014-06-19 22:39 ` H. Peter Anvin
2014-06-19 23:08 ` James Bottomley
2014-06-19 23:42 ` Greg KH
2014-06-20 8:30 ` Daniel Vetter
2014-06-20 8:24 ` Daniel Vetter
2014-06-19 1:15 ` Greg KH
2014-06-19 1:16 ` Greg KH
2014-06-19 1:25 ` Rob Clark
2014-06-19 4:27 ` Sumit Semwal
2014-06-19 4:54 ` Greg KH
2014-06-19 5:26 ` Sumit Semwal
2014-06-18 10:37 ` Maarten Lankhorst [this message]
2014-06-18 10:37 ` [REPOST PATCH 3/8] dma-buf: use reservation objects Maarten Lankhorst
2014-06-18 10:37 ` [REPOST PATCH 4/8] android: convert sync to fence api, v5 Maarten Lankhorst
2014-06-19 1:15 ` Greg KH
2014-06-19 6:37 ` Daniel Vetter
2014-06-19 11:48 ` Thierry Reding
2014-06-19 12:28 ` Daniel Vetter
2014-06-19 15:35 ` Colin Cross
2014-06-19 16:34 ` Daniel Vetter
2014-06-20 20:52 ` Thierry Reding
2014-06-23 8:45 ` Maarten Lankhorst
2014-07-07 13:28 ` Daniel Vetter
2014-06-19 15:22 ` Colin Cross
2014-06-19 16:12 ` Maarten Lankhorst
2014-06-18 10:37 ` [REPOST PATCH 5/8] reservation: add support for fences to enable cross-device synchronisation Maarten Lankhorst
2014-06-18 10:37 ` [REPOST PATCH 6/8] dma-buf: add poll support, v3 Maarten Lankhorst
2014-06-18 10:37 ` [REPOST PATCH 7/8] reservation: update api and add some helpers Maarten Lankhorst
2014-06-18 10:37 ` [REPOST PATCH 8/8] reservation: add suppport for read-only access using rcu Maarten Lankhorst
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=20140618103659.15728.36087.stgit@patser \
--to=maarten.lankhorst@canonical.com \
--cc=ccross@google.com \
--cc=daniel@ffwll.ch \
--cc=dri-devel@lists.freedesktop.org \
--cc=gregkh@linuxfoundation.org \
--cc=linaro-mm-sig@lists.linaro.org \
--cc=linux-arch@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-media@vger.kernel.org \
--cc=robdclark@gmail.com \
--cc=sumit.semwal@linaro.org \
--cc=thellstrom@vmware.com \
--cc=thierry.reding@gmail.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).