<div dir="ltr"><div class="gmail_quote"><div dir="ltr">On Thu, Jun 23, 2016 at 10:35 AM Chris Wilson <<a href="mailto:chris@chris-wilson.co.uk">chris@chris-wilson.co.uk</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">vGEM buffers are useful for passing data between software clients and<br>
hardware renders. By allowing the user to create and attach fences to<br>
the exported vGEM buffers (on the dma-buf), the user can implement a<br>
deferred renderer and queue hardware operations like flipping and then<br>
signal the buffer readiness (i.e. this allows the user to schedule<br>
operations out-of-order, but have them complete in-order).<br>
<br>
This also makes it much easier to write tightly controlled testcases for<br>
dma-buf fencing and signaling between hardware drivers.<br>
<br>
Testcase: igt/vgem_basic/dmabuf-fence<br>
Signed-off-by: Chris Wilson <<a href="mailto:chris@chris-wilson.co.uk" target="_blank">chris@chris-wilson.co.uk</a>><br>
Cc: Sean Paul <<a href="mailto:seanpaul@chromium.org" target="_blank">seanpaul@chromium.org</a>><br>
Cc: Zach Reizner <<a href="mailto:zachr@google.com" target="_blank">zachr@google.com</a>><br>
---<br>
drivers/gpu/drm/vgem/Makefile | 2 +-<br>
drivers/gpu/drm/vgem/vgem_drv.c | 34 ++++++<br>
drivers/gpu/drm/vgem/vgem_drv.h | 18 ++++<br>
drivers/gpu/drm/vgem/vgem_fence.c | 217 ++++++++++++++++++++++++++++++++++++++<br>
include/uapi/drm/vgem_drm.h | 62 +++++++++++<br>
5 files changed, 332 insertions(+), 1 deletion(-)<br>
create mode 100644 drivers/gpu/drm/vgem/vgem_fence.c<br>
create mode 100644 include/uapi/drm/vgem_drm.h<br>
<br>
diff --git a/drivers/gpu/drm/vgem/Makefile b/drivers/gpu/drm/vgem/Makefile<br>
index 3f4c7b842028..bfcdea1330e6 100644<br>
--- a/drivers/gpu/drm/vgem/Makefile<br>
+++ b/drivers/gpu/drm/vgem/Makefile<br>
@@ -1,4 +1,4 @@<br>
ccflags-y := -Iinclude/drm<br>
-vgem-y := vgem_drv.o<br>
+vgem-y := vgem_drv.o vgem_fence.o<br>
<br>
obj-$(CONFIG_DRM_VGEM) += vgem.o<br>
diff --git a/drivers/gpu/drm/vgem/vgem_drv.c b/drivers/gpu/drm/vgem/vgem_drv.c<br>
index 69468b5f3d82..56e348701382 100644<br>
--- a/drivers/gpu/drm/vgem/vgem_drv.c<br>
+++ b/drivers/gpu/drm/vgem/vgem_drv.c<br>
@@ -83,6 +83,34 @@ static const struct vm_operations_struct vgem_gem_vm_ops = {<br>
.close = drm_gem_vm_close,<br>
};<br>
<br>
+static int vgem_open(struct drm_device *dev, struct drm_file *file)<br>
+{<br>
+ struct vgem_file *vfile;<br>
+ int ret;<br>
+<br>
+ vfile = kzalloc(sizeof(*vfile), GFP_KERNEL);<br>
+ if (!vfile)<br>
+ return -ENOMEM;<br>
+<br>
+ file->driver_priv = vfile;<br>
+<br>
+ ret = vgem_fence_open(vfile);<br>
+ if (ret) {<br>
+ kfree(vfile);<br>
+ return ret;<br>
+ }<br>
+<br>
+ return 0;<br>
+}<br>
+<br>
+static void vgem_preclose(struct drm_device *dev, struct drm_file *file)<br>
+{<br>
+ struct vgem_file *vfile = file->driver_priv;<br>
+<br>
+ vgem_fence_close(vfile);<br>
+ kfree(vfile);<br>
+}<br>
+<br>
/* ioctls */<br>
<br>
static struct drm_gem_object *vgem_gem_create(struct drm_device *dev,<br>
@@ -164,6 +192,8 @@ unref:<br>
}<br>
<br>
static struct drm_ioctl_desc vgem_ioctls[] = {<br>
+ DRM_IOCTL_DEF_DRV(VGEM_FENCE_ATTACH, vgem_fence_attach_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),<br>
+ DRM_IOCTL_DEF_DRV(VGEM_FENCE_SIGNAL, vgem_fence_signal_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),<br>
};<br>
<br>
static int vgem_mmap(struct file *filp, struct vm_area_struct *vma)<br>
@@ -286,9 +316,12 @@ static int vgem_prime_mmap(struct drm_gem_object *obj,<br>
<br>
static struct drm_driver vgem_driver = {<br>
.driver_features = DRIVER_GEM | DRIVER_PRIME,<br>
+ .open = vgem_open,<br>
+ .preclose = vgem_preclose,<br>
.gem_free_object_unlocked = vgem_gem_free_object,<br>
.gem_vm_ops = &vgem_gem_vm_ops,<br>
.ioctls = vgem_ioctls,<br>
+ .num_ioctls = ARRAY_SIZE(vgem_ioctls),<br>
.fops = &vgem_driver_fops,<br>
<br>
.dumb_create = vgem_gem_dumb_create,<br>
@@ -343,5 +376,6 @@ module_init(vgem_init);<br>
module_exit(vgem_exit);<br>
<br>
MODULE_AUTHOR("Red Hat, Inc.");<br>
+MODULE_AUTHOR("Intel Corporation");<br>
MODULE_DESCRIPTION(DRIVER_DESC);<br>
MODULE_LICENSE("GPL and additional rights");<br>
diff --git a/drivers/gpu/drm/vgem/vgem_drv.h b/drivers/gpu/drm/vgem/vgem_drv.h<br>
index 988cbaae7588..88ce21010e28 100644<br>
--- a/drivers/gpu/drm/vgem/vgem_drv.h<br>
+++ b/drivers/gpu/drm/vgem/vgem_drv.h<br>
@@ -32,9 +32,27 @@<br>
#include <drm/drmP.h><br>
#include <drm/drm_gem.h><br>
<br>
+#include <uapi/drm/vgem_drm.h><br>
+<br>
+struct vgem_file {<br>
+ struct idr fence_idr;<br>
+ struct mutex fence_mutex;<br>
+ u64 fence_context;<br>
+ atomic_t fence_seqno;<br>
+};<br>
+<br>
#define to_vgem_bo(x) container_of(x, struct drm_vgem_gem_object, base)<br>
struct drm_vgem_gem_object {<br>
struct drm_gem_object base;<br>
};<br>
<br>
+int vgem_fence_open(struct vgem_file *file);<br>
+int vgem_fence_attach_ioctl(struct drm_device *dev,<br>
+ void *data,<br>
+ struct drm_file *file);<br>
+int vgem_fence_signal_ioctl(struct drm_device *dev,<br>
+ void *data,<br>
+ struct drm_file *file);<br>
+void vgem_fence_close(struct vgem_file *file);<br>
+<br>
#endif<br>
diff --git a/drivers/gpu/drm/vgem/vgem_fence.c b/drivers/gpu/drm/vgem/vgem_fence.c<br>
new file mode 100644<br>
index 000000000000..46130e4a3506<br>
--- /dev/null<br>
+++ b/drivers/gpu/drm/vgem/vgem_fence.c<br>
@@ -0,0 +1,217 @@<br>
+/*<br>
+ * Copyright 2016 Intel Corporation<br>
+ *<br>
+ * Permission is hereby granted, free of charge, to any person obtaining a<br>
+ * copy of this software and associated documentation files (the "Software")<br>
+ * to deal in the software without restriction, including without limitation<br>
+ * on the rights to use, copy, modify, merge, publish, distribute, sub<br>
+ * license, and/or sell copies of the Software, and to permit persons to whom<br>
+ * them Software is furnished to do so, subject to the following conditions:<br>
+ *<br>
+ * The above copyright notice and this permission notice (including the next<br>
+ * paragraph) shall be included in all copies or substantial portions of the<br>
+ * Software.<br>
+ *<br>
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR<br>
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTIBILITY,<br>
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL<br>
+ * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER LIABILITY, WHETHER<br>
+ * IN AN ACTION OF CONTRACT, TORT, OR OTHERWISE, ARISING FROM, OUT OF OR IN<br>
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.<br>
+ */<br>
+<br>
+#include <linux/dma-buf.h><br>
+#include <linux/reservation.h><br>
+<br>
+#include "vgem_drv.h"<br>
+<br>
+struct vgem_fence {<br>
+ struct fence base;<br>
+ struct spinlock lock;<br>
+};<br>
+<br>
+static const char *vgem_fence_get_driver_name(struct fence *fence)<br>
+{<br>
+ return "vgem";<br>
+}<br>
+<br>
+static const char *vgem_fence_get_timeline_name(struct fence *fence)<br>
+{<br>
+ return "file";<br>
+}<br>
+<br>
+static bool vgem_fence_signaled(struct fence *fence)<br>
+{<br>
+ return false;<br>
+}<br>
+<br>
+static bool vgem_fence_enable_signaling(struct fence *fence)<br>
+{<br>
+ return true;<br>
+}<br>
+<br>
+static void vgem_fence_value_str(struct fence *fence, char *str, int size)<br>
+{<br>
+ snprintf(str, size, "%u", fence->seqno);<br>
+}<br>
+<br>
+static void vgem_fence_timeline_value_str(struct fence *fence, char *str,<br>
+ int size)<br>
+{<br>
+ snprintf(str, size, "%u", 0);<br>
+}<br>
+<br>
+const struct fence_ops vgem_fence_ops = {<br>
+ .get_driver_name = vgem_fence_get_driver_name,<br>
+ .get_timeline_name = vgem_fence_get_timeline_name,<br>
+ .enable_signaling = vgem_fence_enable_signaling,<br>
+ .signaled = vgem_fence_signaled,<br>
+ .wait = fence_default_wait,<br>
+ .fence_value_str = vgem_fence_value_str,<br>
+ .timeline_value_str = vgem_fence_timeline_value_str,<br>
+};<br>
+<br>
+static u32 vgem_fence_next_seqno(struct vgem_file *vfile)<br>
+{<br>
+ u32 seqno;<br>
+<br>
+ seqno = atomic_inc_return(&vfile->fence_seqno);<br>
+ if (seqno == 0)<br>
+ seqno = atomic_inc_return(&vfile->fence_seqno);<br>
+<br>
+ return seqno;<br>
+}<br>
+<br>
+static struct fence *vgem_fence_create(struct vgem_file *vfile)<br>
+{<br>
+ struct vgem_fence *fence;<br>
+<br>
+ fence = kzalloc(sizeof(*fence), GFP_KERNEL);<br>
+ if (!fence)<br>
+ return NULL;<br>
+<br>
+ spin_lock_init(&fence->lock);<br>
+ fence_init(&fence->base,<br>
+ &vgem_fence_ops,<br>
+ &fence->lock,<br>
+ vfile->fence_context,<br>
+ vgem_fence_next_seqno(vfile));<br>
+<br>
+ return &fence->base;<br>
+}<br>
+<br>
+static int attach_dmabuf(struct drm_device *dev,<br>
+ struct drm_gem_object *obj)<br>
+{<br>
+ struct dma_buf *dmabuf;<br>
+<br>
+ if (obj->dma_buf)<br>
+ return 0;<br>
+<br>
+ dmabuf = dev->driver->gem_prime_export(dev, obj, 0);<br>
+ if (IS_ERR(dmabuf))<br>
+ return PTR_ERR(dmabuf);<br>
+<br>
+ obj->dma_buf = dmabuf;<br>
+ drm_gem_object_reference(obj);<br>
+ return 0;<br>
+}<br>
+<br>
+int vgem_fence_attach_ioctl(struct drm_device *dev,<br>
+ void *data,<br>
+ struct drm_file *file)<br>
+{<br>
+ struct drm_vgem_fence_attach *arg = data;<br>
+ struct vgem_file *vfile = file->driver_priv;<br>
+ struct reservation_object *resv;<br>
+ struct drm_gem_object *obj;<br>
+ struct fence *fence;<br>
+ int ret;<br>
+<br>
+ if (arg->flags & ~VGEM_FENCE_WRITE)<br>
+ return -EINVAL;<br>
+<br>
+ obj = drm_gem_object_lookup(file, arg->handle);<br>
+ if (!obj)<br>
+ return -ENOENT;<br>
+<br>
+ ret = attach_dmabuf(dev, obj);<br>
+ if (ret)<br>
+ goto out;<br>
+<br>
+ fence = vgem_fence_create(vfile);<br>
+ if (!fence) {<br>
+ ret = -ENOMEM;<br>
+ goto out;<br>
+ }<br>
+<br>
+ ret = 0;<br>
+ resv = obj->dma_buf->resv;<br>
+ mutex_lock(&resv->lock.base);<br>
+ if (arg->flags & VGEM_FENCE_WRITE)<br>
+ reservation_object_add_excl_fence(resv, fence);<br>
+ else if ((ret = reservation_object_reserve_shared(resv)) == 0)<br>
+ reservation_object_add_shared_fence(resv, fence);<br>
+ mutex_unlock(&resv->lock.base);<br>
+<br>
+ if (ret == 0) {<br>
+ mutex_lock(&vfile->fence_mutex);<br>
+ ret = idr_alloc(&vfile->fence_idr, fence, 1, 0, GFP_KERNEL);<br>
+ mutex_unlock(&vfile->fence_mutex);<br>
+ if (ret > 0) {<br>
+ arg->out_fence = ret;<br>
+ ret = 0;<br>
+ }<br>
+ }<br>
+ if (ret)<br>
+ fence_put(fence);<br>
+out:<br>
+ drm_gem_object_unreference_unlocked(obj);<br>
+ return ret;<br>
+}<br>
+<br>
+int vgem_fence_signal_ioctl(struct drm_device *dev,<br>
+ void *data,<br>
+ struct drm_file *file)<br>
+{<br>
+ struct vgem_file *vfile = file->driver_priv;<br>
+ struct drm_vgem_fence_signal *arg = data;<br>
+ struct fence *fence;<br>
+<br>
+ if (arg->flags)<br>
+ return -EINVAL;<br>
+<br>
+ mutex_lock(&vfile->fence_mutex);<br>
+ fence = idr_replace(&vfile->fence_idr, NULL, arg->fence);<br>
+ mutex_unlock(&vfile->fence_mutex);<br>
+ if (!fence)<br>
+ return -ENOENT;<br>
+ if (IS_ERR(fence))<br>
+ return PTR_ERR(fence);<br>
+<br>
+ fence_signal(fence);<br>
+ fence_put(fence);<br>
+ return 0;<br>
+}<br>
+<br>
+int vgem_fence_open(struct vgem_file *vfile)<br>
+{<br>
+ mutex_init(&vfile->fence_mutex);<br>
+ idr_init(&vfile->fence_idr);<br>
+ vfile->fence_context = fence_context_alloc(1);<br>
+<br>
+ return 0;<br>
+}<br>
+<br>
+static int __vgem_fence_idr_fini(int id, void *p, void *data)<br>
+{<br>
+ fence_signal(p);<br>
+ fence_put(p);<br>
+ return 0;<br>
+}<br>
+<br>
+void vgem_fence_close(struct vgem_file *vfile)<br>
+{<br>
+ idr_for_each(&vfile->fence_idr, __vgem_fence_idr_fini, vfile);<br>
+ idr_destroy(&vfile->fence_idr);<br>
+}<br>
diff --git a/include/uapi/drm/vgem_drm.h b/include/uapi/drm/vgem_drm.h<br>
new file mode 100644<br>
index 000000000000..352d2fae8de9<br>
--- /dev/null<br>
+++ b/include/uapi/drm/vgem_drm.h<br>
@@ -0,0 +1,62 @@<br>
+/*<br>
+ * Copyright 2016 Intel Corporation<br>
+ * All Rights Reserved.<br>
+ *<br>
+ * Permission is hereby granted, free of charge, to any person obtaining a<br>
+ * copy of this software and associated documentation files (the<br>
+ * "Software"), to deal in the Software without restriction, including<br>
+ * without limitation the rights to use, copy, modify, merge, publish,<br>
+ * distribute, sub license, and/or sell copies of the Software, and to<br>
+ * permit persons to whom the Software is furnished to do so, subject to<br>
+ * the following conditions:<br>
+ *<br>
+ * The above copyright notice and this permission notice (including the<br>
+ * next paragraph) shall be included in all copies or substantial portions<br>
+ * of the Software.<br>
+ *<br>
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS<br>
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF<br>
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.<br>
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR<br>
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,<br>
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE<br>
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.<br>
+ *<br>
+ */<br>
+<br>
+#ifndef _UAPI_VGEM_DRM_H_<br>
+#define _UAPI_VGEM_DRM_H_<br>
+<br>
+#include "drm.h"<br>
+<br>
+#if defined(__cplusplus)<br>
+extern "C" {<br>
+#endif<br>
+<br>
+/* Please note that modifications to all structs defined here are<br>
+ * subject to backwards-compatibility constraints.<br>
+ */<br>
+#define DRM_VGEM_FENCE_ATTACH 0x1<br>
+#define DRM_VGEM_FENCE_SIGNAL 0x2<br>
+<br>
+#define DRM_IOCTL_VGEM_FENCE_ATTACH DRM_IOWR( DRM_COMMAND_BASE + DRM_VGEM_FENCE_ATTACH, struct drm_vgem_fence_attach)<br>
+#define DRM_IOCTL_VGEM_FENCE_SIGNAL DRM_IOW( DRM_COMMAND_BASE + DRM_VGEM_FENCE_SIGNAL, struct drm_vgem_fence_signal)<br>
+<br>
+struct drm_vgem_fence_attach {<br>
+ __u32 handle;<br>
+ __u32 flags;<br>
+#define VGEM_FENCE_WRITE 0x1<br>
+ __u32 out_fence;<br>
+ __u32 pad;<br>
+};<br>
+<br>
+struct drm_vgem_fence_signal {<br>
+ __u32 fence;<br>
+ __u32 flags;<br>
+};<br>
+<br>
+#if defined(__cplusplus)<br>
+}<br>
+#endif<br>
+<br>
+#endif /* _UAPI_VGEM_DRM_H_ */<br>
--<br>
2.8.1<br></blockquote><div><span style="line-height:1.5;font-size:13px;color:rgb(33,33,33);font-family:"helvetica neue",helvetica,arial,sans-serif">Acked-by: Zach Reizner <</span><a href="mailto:zachr@google.com" target="_blank" style="line-height:1.5;font-size:13px;font-family:"helvetica neue",helvetica,arial,sans-serif">zachr@google.com</a><span style="line-height:1.5;font-size:13px;color:rgb(33,33,33);font-family:"helvetica neue",helvetica,arial,sans-serif">> </span><span style="line-height:1.5;font-size:13px;color:rgb(33,33,33);font-family:"helvetica neue",helvetica,arial,sans-serif"> </span> </div><div> </div></div></div>