dri-devel.lists.freedesktop.org archive mirror
 help / color / mirror / Atom feed
From: Jason Ekstrand <jason@jlekstrand.net>
To: dri-devel@lists.freedesktop.org
Cc: Jason Ekstrand <jason@jlekstrand.net>
Subject: [PATCH 8/9] dma-buf/dma-fence: Add a mechanism for proxy fences
Date: Fri, 11 Aug 2017 15:39:33 -0700	[thread overview]
Message-ID: <1502491174-10913-9-git-send-email-jason.ekstrand@intel.com> (raw)
In-Reply-To: <1502491174-10913-1-git-send-email-jason.ekstrand@intel.com>

From: Chris Wilson <chris@chris-wilson.co.uk>

Proxy fences allow you to create a place-holder fence which you can
later assign to the "real" fence at which point the two look
indistinguishable to anyone other than the driver which created the
real fence.  These should be used with care as it is the responsibility
of proxy fences creator to ensure that it eventually gets assigned a
real fence so it gets signaled.

Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
---
 drivers/dma-buf/Makefile          |   4 +-
 drivers/dma-buf/dma-fence-proxy.c | 186 ++++++++++++++++++++++++++++++++++++++
 include/linux/dma-fence-proxy.h   |  25 +++++
 3 files changed, 214 insertions(+), 1 deletion(-)
 create mode 100644 drivers/dma-buf/dma-fence-proxy.c
 create mode 100644 include/linux/dma-fence-proxy.h

diff --git a/drivers/dma-buf/Makefile b/drivers/dma-buf/Makefile
index c33bf88..e468215 100644
--- a/drivers/dma-buf/Makefile
+++ b/drivers/dma-buf/Makefile
@@ -1,3 +1,5 @@
-obj-y := dma-buf.o dma-fence.o dma-fence-array.o reservation.o seqno-fence.o
+obj-y := dma-buf.o \
+	dma-fence.o dma-fence-array.o dma-fence-proxy.o \
+	reservation.o seqno-fence.o
 obj-$(CONFIG_SYNC_FILE)		+= sync_file.o
 obj-$(CONFIG_SW_SYNC)		+= sw_sync.o sync_debug.o
diff --git a/drivers/dma-buf/dma-fence-proxy.c b/drivers/dma-buf/dma-fence-proxy.c
new file mode 100644
index 0000000..61bf8e5
--- /dev/null
+++ b/drivers/dma-buf/dma-fence-proxy.c
@@ -0,0 +1,186 @@
+/*
+ * dma-fence-proxy: placeholder unsignaled fence
+ *
+ * Copyright (C) 2017 Intel Corporation
+ *
+ * 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/dma-fence.h>
+#include <linux/export.h>
+#include <linux/irq_work.h>
+#include <linux/slab.h>
+
+struct dma_fence_proxy {
+	struct dma_fence base;
+	spinlock_t lock;
+
+	const char *driver_name;
+	void *tag;
+
+	struct dma_fence *real;
+	struct dma_fence_cb cb;
+	struct irq_work work;
+};
+
+static const char *proxy_get_driver_name(struct dma_fence *fence)
+{
+	struct dma_fence_proxy *p = container_of(fence, typeof(*p), base);
+
+	return p->real ? p->real->ops->get_driver_name(p->real) : p->driver_name;
+}
+
+static const char *proxy_get_timeline_name(struct dma_fence *fence)
+{
+	struct dma_fence_proxy *p = container_of(fence, typeof(*p), base);
+
+	return p->real ? p->real->ops->get_timeline_name(p->real) : "unset";
+}
+
+static void proxy_irq_work(struct irq_work *work)
+{
+	struct dma_fence_proxy *p = container_of(work, typeof(*p), work);
+
+	dma_fence_signal(&p->base);
+	dma_fence_put(&p->base);
+}
+
+static void proxy_callback(struct dma_fence *fence, struct dma_fence_cb *cb)
+{
+	struct dma_fence_proxy *p = container_of(cb, typeof(*p), cb);
+
+	/* beware the alleged spinlock inversion */
+	irq_work_queue(&p->work);
+}
+
+static bool proxy_enable_signaling(struct dma_fence *fence)
+{
+	struct dma_fence_proxy *p = container_of(fence, typeof(*p), base);
+
+	if (!p->real)
+		return true;
+
+	if (dma_fence_add_callback(p->real, &p->cb, proxy_callback))
+		return false;
+
+	dma_fence_get(fence);
+	return true;
+}
+
+static bool proxy_signaled(struct dma_fence *fence)
+{
+	struct dma_fence_proxy *p = container_of(fence, typeof(*p), base);
+
+	return p->real ? dma_fence_is_signaled(p->real) : false;
+}
+
+static void proxy_release(struct dma_fence *fence)
+{
+	struct dma_fence_proxy *p = container_of(fence, typeof(*p), base);
+
+	if (!p->real)
+		dma_fence_signal(&p->base);
+
+	dma_fence_put(p->real);
+	dma_fence_free(&p->base);
+}
+
+static const struct dma_fence_ops dma_fence_proxy_ops = {
+	.get_driver_name = proxy_get_driver_name,
+	.get_timeline_name = proxy_get_timeline_name,
+	.enable_signaling = proxy_enable_signaling,
+	.signaled = proxy_signaled,
+	.wait = dma_fence_default_wait,
+	.release = proxy_release,
+};
+
+/**
+ * dma_fence_proy_create - Create an unset proxy dma-fence
+ * @driver_name: The driver name to report; must outlive the fence
+ * @tag: A pointer which uniquely identifies the creator
+ */
+struct dma_fence *dma_fence_create_proxy(const char *driver_name, void *tag)
+{
+	struct dma_fence_proxy *p;
+
+	p = kzalloc(sizeof(*p), GFP_KERNEL);
+	if (!p)
+		return NULL;
+
+	p->driver_name = driver_name;
+	p->tag = tag;
+	spin_lock_init(&p->lock);
+	dma_fence_init(&p->base, &dma_fence_proxy_ops, &p->lock, 0, 0);
+	init_irq_work(&p->work, proxy_irq_work);
+
+	return &p->base;
+}
+EXPORT_SYMBOL(dma_fence_create_proxy);
+
+static bool dma_fence_is_proxy(struct dma_fence *fence)
+{
+	return fence->ops == &dma_fence_proxy_ops;
+}
+
+/**
+ * dma_fence_is_proxy_tagged - identify a proxy fence
+ * @fence: The fence to identify
+ * @tag: The tag pointer provided to dma_fence_create_proxy
+ *
+ * This returns true if this is a proxy fence tag is the same pointer as
+ * the tag provided to dma_fence_create_proxy.
+ */
+bool dma_fence_is_proxy_tagged(struct dma_fence *fence, void *tag)
+{
+	struct dma_fence_proxy *p = container_of(fence, typeof(*p), base);
+
+	if (!dma_fence_is_proxy(fence))
+		return false;
+
+	return p->tag == tag;
+}
+EXPORT_SYMBOL(dma_fence_is_proxy_tagged);
+
+/**
+ * dma_fence_proxy_assign - assign a fence to a proxy fence
+ * @proxy: The proxy fence
+ * @real: The real fence to assign to proxy
+ *
+ * This assigns the given real fence to the proxy fence.  From this point
+ * forward, the proxy fence will be almost indistinguishable from the real
+ * fence.  It will report the same driver and timeline names and will
+ * signal when the real fence signals.  If the real fence is already
+ * signaled when this function is called, it will signal as soon as it has
+ * any listeners, possibly immediately.
+ */
+void dma_fence_proxy_assign(struct dma_fence *proxy, struct dma_fence *real)
+{
+	struct dma_fence_proxy *p = container_of(proxy, typeof(*p), base);
+	unsigned long flags;
+
+	BUG_ON(!dma_fence_is_proxy(proxy));
+	BUG_ON(p->real);
+
+	spin_lock_irqsave(p->base.lock, flags);
+
+	p->real = dma_fence_get(real);
+
+	if (test_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT, &p->base.flags)) {
+		if (dma_fence_add_callback(real, &p->cb, proxy_callback))
+			dma_fence_signal_locked(&p->base);
+		else
+			dma_fence_get(&p->base);
+	} else if (dma_fence_is_signaled(real)) {
+		dma_fence_signal_locked(&p->base);
+	}
+
+	spin_unlock_irqrestore(p->base.lock, flags);
+}
+EXPORT_SYMBOL(dma_fence_proxy_assign);
diff --git a/include/linux/dma-fence-proxy.h b/include/linux/dma-fence-proxy.h
new file mode 100644
index 0000000..177a5165
--- /dev/null
+++ b/include/linux/dma-fence-proxy.h
@@ -0,0 +1,25 @@
+/*
+ * dma-fence-proxy: allows waiting upon unset fences
+ *
+ * Copyright (C) 2017 Intel Corporation
+ *
+ * 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.
+ */
+
+#ifndef __LINUX_DMA_FENCE_PROXY_H
+#define __LINUX_DMA_FENCE_PROXY_H
+
+#include <linux/dma-fence.h>
+
+struct dma_fence *dma_fence_create_proxy(const char *driver_name, void *tag);
+bool dma_fence_is_proxy_tagged(struct dma_fence *fence, void *tag);
+void dma_fence_proxy_assign(struct dma_fence *proxy, struct dma_fence *real);
+
+#endif /* __LINUX_DMA_FENCE_PROXY_H */
-- 
2.5.0.400.gff86faf

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

  parent reply	other threads:[~2017-08-11 22:39 UTC|newest]

Thread overview: 55+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-08-08 22:46 [PATCH 0/9] drm/syncobj: Add full-featured wait support Jason Ekstrand
2017-08-08 22:46 ` [PATCH 1/9] drm/syncobj: Rename fence_get to find_fence Jason Ekstrand
2017-08-08 22:46 ` [PATCH 2/9] drm/syncobj: Lock around drm_syncobj::fence Jason Ekstrand
2017-08-09 21:21   ` Chris Wilson
2017-08-10  0:31     ` Jason Ekstrand
2017-08-10 10:55       ` Chris Wilson
2017-08-10 19:10       ` Chris Wilson
2017-08-08 22:46 ` [PATCH 3/9] drm/syncobj: Remove file_private from replace_fence Jason Ekstrand
2017-08-08 22:46 ` [PATCH 4/9] i915: Add support for drm syncobjs Jason Ekstrand
2017-08-08 22:46 ` [PATCH 5/9] drm/syncobj: add sync obj wait interface. (v8) Jason Ekstrand
2017-08-08 22:46 ` [PATCH 6/9] dma-buf/dma-fence: Allow wait_any_timeout without default_wait Jason Ekstrand
2017-08-08 22:46 ` [PATCH 7/9] drm/syncobj: Add a reset ioctl Jason Ekstrand
2017-08-08 22:46 ` [PATCH 8/9] drm/syncobj: Add a callback mechanism for replace_fence Jason Ekstrand
2017-08-08 22:46 ` [PATCH 9/9] drm/syncobj: Allow wait for submit and signal behavior Jason Ekstrand
2017-08-09 17:00   ` [PATCH] drm/syncobj: Allow wait for submit and signal behavior (v2) Jason Ekstrand
2017-08-09 17:57     ` Chris Wilson
2017-08-09 18:25       ` Christian König
2017-08-09 21:09         ` Jason Ekstrand
2017-08-09 22:41       ` Chris Wilson
2017-08-09 23:53         ` Jason Ekstrand
2017-08-10 11:00           ` Chris Wilson
2017-08-10 14:42             ` Jason Ekstrand
2017-08-10 12:26           ` Christian König
2017-08-10 14:32             ` Jason Ekstrand
2017-08-10 14:41               ` Christian König
2017-08-09 21:31     ` Chris Wilson
2017-08-09 21:54       ` Jason Ekstrand
2017-08-10 12:26       ` Christian König
2017-08-10  1:35     ` [PATCH v3 9/9] drm/syncobj: Allow wait for submit and signal behavior (v3) Jason Ekstrand
2017-08-11 22:39 ` [PATCH 0/9] drm/syncobj: Add full-featured wait support (v2) Jason Ekstrand
2017-08-11 22:39   ` [PATCH 1/9] drm/syncobj: Rename fence_get to find_fence Jason Ekstrand
2017-08-11 22:39   ` [PATCH 2/9] drm/syncobj: Add a race-free drm_syncobj_fence_get helper Jason Ekstrand
2017-08-14  2:03     ` kbuild test robot
2017-08-11 22:39   ` [PATCH 3/9] i915: Add support for drm syncobjs Jason Ekstrand
2017-08-14  2:58     ` Jason Ekstrand
2017-08-11 22:39   ` [PATCH 4/9] drm/syncobj: add sync obj wait interface. (v8) Jason Ekstrand
2017-08-11 22:39   ` [PATCH 5/9] dma-buf/dma-fence: Allow wait_any_timeout without default_wait (v2) Jason Ekstrand
2017-08-11 22:39   ` [PATCH 6/9] drm/syncobj: Add a reset ioctl Jason Ekstrand
2017-08-11 22:39   ` [PATCH 7/9] dma-buf/dma-fence: Signal all callbacks from dma_fence_release() Jason Ekstrand
2018-01-31 12:32     ` Gustavo Padovan
2018-01-31 15:53       ` Chris Wilson
2017-08-11 22:39   ` Jason Ekstrand [this message]
2017-08-11 22:39   ` [PATCH 9/9] drm/syncobj: Allow wait for submit and signal behavior (v4) Jason Ekstrand
2017-08-13 13:19   ` [PATCH 0/9] drm/syncobj: Add full-featured wait support (v2) Christian König
2017-08-13 15:26     ` Jason Ekstrand
2017-08-13 15:52       ` Christian König
2017-08-13 23:14         ` Jason Ekstrand
2017-08-14  5:49           ` Jason Ekstrand
2017-08-14  7:36           ` Christian König
2017-08-14 15:08             ` Jason Ekstrand
2017-08-16 15:52               ` Jason Ekstrand
2017-08-16 16:53                 ` Christian König
2017-08-16 20:10                   ` Jason Ekstrand
2017-08-21 21:42                     ` Jason Ekstrand
2017-08-22  8:30                       ` Christian König

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=1502491174-10913-9-git-send-email-jason.ekstrand@intel.com \
    --to=jason@jlekstrand.net \
    --cc=dri-devel@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 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).