From: Gustavo Padovan <gustavo@padovan.org>
To: "Christian König" <christian.koenig@amd.com>
Cc: dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org,
"Daniel Stone" <daniels@collabora.com>,
"Arve Hjønnevåg" <arve@android.com>,
"Riley Andrews" <riandrews@android.com>,
"Rob Clark" <robdclark@gmail.com>,
"Greg Hackmann" <ghackmann@google.com>,
"John Harrison" <John.C.Harrison@Intel.com>,
laurent.pinchart@ideasonboard.com, seanpaul@google.com,
marcheu@google.com, m.chehab@samsung.com,
"Maarten Lankhorst" <maarten.lankhorst@linux.intel.com>,
"Gustavo Padovan" <gustavo.padovan@collabora.co.uk>
Subject: Re: [RFC 1/8] dma-buf/fence: add fence_collection fences
Date: Fri, 15 Apr 2016 11:27:50 -0700 [thread overview]
Message-ID: <20160415182750.GA23954@joana> (raw)
In-Reply-To: <5710AE61.9040308@amd.com>
2016-04-15 Christian König <christian.koenig@amd.com>:
> Am 15.04.2016 um 10:02 schrieb Daniel Vetter:
> >On Thu, Apr 14, 2016 at 06:29:34PM -0700, Gustavo Padovan wrote:
> >>From: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
> >>
> >>struct fence_collection inherits from struct fence and carries a
> >>collection of fences that needs to be waited together.
> >>
> >>It is useful to translate a sync_file to a fence to remove the complexity
> >>of dealing with sync_files from DRM drivers. So even if there are many
> >>fences in the sync_file that needs to waited for a commit to happen
> >>drivers would only worry about a standard struct fence.That means that no
> >>changes needed to any driver besides supporting fences.
> >>
> >>fence_collection's fence doesn't belong to any timeline context.
> >>
> >>Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
> >>---
> >> drivers/dma-buf/Makefile | 2 +-
> >> drivers/dma-buf/fence-collection.c | 138 +++++++++++++++++++++++++++++++++++++
> >> drivers/dma-buf/fence.c | 2 +-
> >> include/linux/fence-collection.h | 56 +++++++++++++++
> >> include/linux/fence.h | 2 +
> >> 5 files changed, 198 insertions(+), 2 deletions(-)
> >> create mode 100644 drivers/dma-buf/fence-collection.c
> >> create mode 100644 include/linux/fence-collection.h
> >>
> >>diff --git a/drivers/dma-buf/Makefile b/drivers/dma-buf/Makefile
> >>index 43325a1..30b8464 100644
> >>--- a/drivers/dma-buf/Makefile
> >>+++ b/drivers/dma-buf/Makefile
> >>@@ -1,3 +1,3 @@
> >>-obj-y := dma-buf.o fence.o reservation.o seqno-fence.o
> >>+obj-y := dma-buf.o fence.o reservation.o seqno-fence.o fence-collection.o
> >> obj-$(CONFIG_SYNC_FILE) += sync_file.o sync_timeline.o sync_debug.o
> >> obj-$(CONFIG_SW_SYNC) += sw_sync.o
> >>diff --git a/drivers/dma-buf/fence-collection.c b/drivers/dma-buf/fence-collection.c
> >>new file mode 100644
> >>index 0000000..8a4ecb0
> >>--- /dev/null
> >>+++ b/drivers/dma-buf/fence-collection.c
> >>@@ -0,0 +1,138 @@
> >>+/*
> >>+ * fence-collection: aggregate fences to be waited together
> >>+ *
> >>+ * Copyright (C) 2016 Collabora Ltd
> >>+ * Authors:
> >>+ * Gustavo Padovan <gustavo@padovan.org>
> >>+ *
> >>+ * 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.
> >>+ */
> >>+
> >>+#include <linux/export.h>
> >>+#include <linux/slab.h>
> >>+#include <linux/fence-collection.h>
> >>+
> >>+static const char *fence_collection_get_driver_name(struct fence *fence)
> >>+{
> >>+ struct fence_collection *collection = to_fence_collection(fence);
> >>+ struct fence *f = collection->fences[0].fence;
> >>+
> >>+ return f->ops->get_driver_name(fence);
> >>+}
>
> I would rather return some constant name here instead of relying that the
> collection already has a fence added and that all fences are from the same
> driver.
If we merge _init and _add this will not be a problem anymore and we can
return the actual driver name.
>
> >>+
> >>+static const char *fence_collection_get_timeline_name(struct fence *fence)
> >>+{
> >>+ return "no context";
> >>+}
> >>+
> >>+static bool fence_collection_enable_signaling(struct fence *fence)
> >>+{
> >>+ struct fence_collection *collection = to_fence_collection(fence);
> >>+
> >>+ return atomic_read(&collection->num_pending_fences);
> >>+}
> >>+
> >>+static bool fence_collection_signaled(struct fence *fence)
> >>+{
> >>+ struct fence_collection *collection = to_fence_collection(fence);
> >>+
> >>+ return (atomic_read(&collection->num_pending_fences) == 0);
> >>+}
> >>+
> >>+static void fence_collection_release(struct fence *fence)
> >>+{
> >>+ struct fence_collection *collection = to_fence_collection(fence);
> >>+ int i;
> >>+
> >>+ for (i = 0 ; i < collection->num_fences ; i++) {
> >>+ fence_remove_callback(collection->fences[i].fence,
> >>+ &collection->fences[i].cb);
> >>+ fence_put(collection->fences[i].fence);
> >>+ }
> >>+
> >>+ fence_free(fence);
> >>+}
> >>+
> >>+static signed long fence_collection_wait(struct fence *fence, bool intr,
> >>+ signed long timeout)
> >>+{
> >>+ struct fence_collection *collection = to_fence_collection(fence);
> >>+ int i;
> >>+
> >>+ for (i = 0 ; i < collection->num_fences ; i++) {
> >>+ timeout = fence_wait(collection->fences[i].fence, intr);
> >>+ if (timeout < 0)
> >>+ return timeout;
> >>+ }
> >>+
> >>+ return timeout;
> >>+}
> >>+
> >>+static const struct fence_ops fence_collection_ops = {
> >>+ .get_driver_name = fence_collection_get_driver_name,
> >>+ .get_timeline_name = fence_collection_get_timeline_name,
> >>+ .enable_signaling = fence_collection_enable_signaling,
> >>+ .signaled = fence_collection_signaled,
> >>+ .wait = fence_collection_wait,
> >>+ .release = fence_collection_release,
> >>+};
> >>+
> >>+static void collection_check_cb_func(struct fence *fence, struct fence_cb *cb)
> >>+{
> >>+ struct fence_collection_cb *f_cb;
> >>+ struct fence_collection *collection;
> >>+
> >>+ f_cb = container_of(cb, struct fence_collection_cb, cb);
> >>+ collection = f_cb->collection;
> >>+
> >>+ if (atomic_dec_and_test(&collection->num_pending_fences))
> >>+ fence_signal(&collection->base);
> >>+}
> >>+
> >>+void fence_collection_add(struct fence_collection *collection,
> >>+ struct fence *fence)
> >>+{
> >>+ int n = collection->num_fences;
> >>+
> >>+ collection->fences[n].collection = collection;
> >>+ collection->fences[n].fence = fence;
> >>+
> >>+ if (fence_add_callback(fence, &collection->fences[n].cb,
> >>+ collection_check_cb_func))
> >>+ return;
> >>+
> >>+ fence_get(fence);
> >>+
> >>+ collection->num_fences++;
> >>+ atomic_inc(&collection->num_pending_fences);
> >>+}
> >For the interface I think we should not split it into _init and _add - it
> >shouldn't be allowed to change a collection once it's created. So probably
> >cleaner if we add an array of fence pointers to _init.
>
> Amdgpu also has an implementation for a fence collection which uses a a
> hashtable to keep the fences grouped by context (e.g. only the latest fence
> is keept for each context). See amdgpu_sync.c for reference.
>
> We should either make the collection similar in a way that you can add as
> many fences as you want (like the amdgpu implementation) or make it static
> and only add a fixed number of fences right from the beginning.
>
> I can certainly see use cases for both, but if you want to stick with a
> static approach you should probably call the new object fence_array instead
> of fence_collection and do as Daniel suggested.
Maybe we can go for something in between. Have fence_collection_init()
need at least two fences to create the fence_collection. Then
fence_collection_add() would add more dinamically.
>
> >Other nitpick: Adding the callback should (I think) only be done in
> >->enable_signalling.
>
> Yeah, I was about to complain on that as well.
>
> Enabling signaling can have a huge overhead for some fence implementations.
> So it should only be used when needed
Right, that makes sense.
>
> >
> >Finally: Have you looked into stitching together a few unit tests for
> >fence_collection?
Not yet. It is something I plan to work soon.
> >
> >Fence collections also break the assumption that every fence is on a
> >timeline. fence_later and fence_is_later need to be adjusted. We also need
> >a special collection context to filter these out. This means
> >fence_collection isn't perfectly opaque abstraction.
I'll fix this.
> >>+
> >>+struct fence_collection *fence_collection_init(int num_fences)
> >>+{
> >>+ struct fence_collection *collection;
> >>+
> >>+ collection = kzalloc(offsetof(struct fence_collection,
> >>+ fences[num_fences]), GFP_KERNEL);
> >>+ if (!collection)
> >>+ return NULL;
> >>+
> >>+ spin_lock_init(&collection->lock);
> >>+ fence_init(&collection->base, &fence_collection_ops, &collection->lock,
> >>+ FENCE_NO_CONTEXT, 0);
> >>+
> >>+ return collection;
> >>+}
> >>+EXPORT_SYMBOL(fence_collection_init);
> >>+
> >>+void fence_collection_put(struct fence_collection *collection)
> >>+{
> >>+ fence_put(&collection->base);
> >Not sure a specialized _put function is useful, I'd leave it out.
I've added this to let the user only deal with fence_collection, but
I'm fine leaving it out too.
Gustavo
next prev parent reply other threads:[~2016-04-15 18:28 UTC|newest]
Thread overview: 30+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-04-15 1:29 [RFC 0/8] drm: explicit fencing support Gustavo Padovan
2016-04-15 1:29 ` [RFC 1/8] dma-buf/fence: add fence_collection fences Gustavo Padovan
2016-04-15 8:02 ` Daniel Vetter
2016-04-15 9:03 ` Christian König
2016-04-15 11:44 ` Daniel Vetter
2016-04-15 18:29 ` Gustavo Padovan
2016-04-15 19:23 ` Daniel Vetter
2016-04-15 18:27 ` Gustavo Padovan [this message]
2016-04-15 19:25 ` Daniel Vetter
2016-05-18 7:07 ` Christian König
2016-05-18 14:30 ` Gustavo Padovan
2016-04-15 1:29 ` [RFC 2/8] dma-buf/sync_file: add sync_file_fences_get() Gustavo Padovan
2016-04-15 7:56 ` Daniel Vetter
2016-04-15 1:29 ` [RFC 3/8] drm/fence: allow fence waiting to be interrupted by userspace Gustavo Padovan
2016-04-15 7:47 ` Daniel Vetter
2016-04-15 1:29 ` [RFC 4/8] drm/fence: add in-fences support Gustavo Padovan
2016-04-15 8:05 ` Daniel Vetter
2016-04-15 18:40 ` Gustavo Padovan
2016-04-15 8:11 ` Daniel Vetter
2016-04-15 1:29 ` [RFC 5/8] drm/fence: add fence to drm_pending_event Gustavo Padovan
2016-04-15 8:09 ` Daniel Vetter
2016-04-15 18:59 ` Gustavo Padovan
2016-04-15 19:31 ` Daniel Vetter
2016-04-15 1:29 ` [RFC 6/8] drm/fence: create DRM_MODE_ATOMIC_OUT_FENCE flag Gustavo Padovan
2016-04-15 1:40 ` Rob Clark
2016-04-15 19:05 ` Gustavo Padovan
2016-04-15 1:29 ` [RFC 7/8] drm/fence: create per-crtc sync_timeline Gustavo Padovan
2016-04-15 1:29 ` [RFC 8/8] drm/fence: add out-fences support Gustavo Padovan
2016-04-15 8:18 ` Daniel Vetter
2016-04-15 19:15 ` Gustavo Padovan
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=20160415182750.GA23954@joana \
--to=gustavo@padovan.org \
--cc=John.C.Harrison@Intel.com \
--cc=arve@android.com \
--cc=christian.koenig@amd.com \
--cc=daniels@collabora.com \
--cc=dri-devel@lists.freedesktop.org \
--cc=ghackmann@google.com \
--cc=gustavo.padovan@collabora.co.uk \
--cc=laurent.pinchart@ideasonboard.com \
--cc=linux-kernel@vger.kernel.org \
--cc=m.chehab@samsung.com \
--cc=maarten.lankhorst@linux.intel.com \
--cc=marcheu@google.com \
--cc=riandrews@android.com \
--cc=robdclark@gmail.com \
--cc=seanpaul@google.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