From: Dmitry Osipenko <dmitry.osipenko@collabora.com>
To: "David Airlie" <airlied@redhat.com>,
"Gerd Hoffmann" <kraxel@redhat.com>,
"Gurchetan Singh" <gurchetansingh@chromium.org>,
"Chia-I Wu" <olvaffe@gmail.com>,
"Daniel Vetter" <daniel@ffwll.ch>,
"Rob Clark" <robdclark@gmail.com>,
"Marek Olšák" <maraeo@gmail.com>
Cc: dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org,
kernel@collabora.com, virtualization@lists.linux-foundation.org
Subject: [PATCH v1 1/1] drm/virtio: Support sync objects
Date: Thu, 19 Jan 2023 03:41:43 +0300 [thread overview]
Message-ID: <20230119004143.968942-2-dmitry.osipenko@collabora.com> (raw)
In-Reply-To: <20230119004143.968942-1-dmitry.osipenko@collabora.com>
Add sync object DRM UAPI support to VirtIO-GPU driver. It's required
for enabling full-featured Vulkan fencing by Venus and native context
VirtIO-GPU Mesa drivers.
Signed-off-by: Dmitry Osipenko <dmitry.osipenko@collabora.com>
---
drivers/gpu/drm/virtio/virtgpu_drv.c | 3 +-
drivers/gpu/drm/virtio/virtgpu_ioctl.c | 223 ++++++++++++++++++++++++-
include/uapi/drm/virtgpu_drm.h | 16 +-
3 files changed, 239 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.c b/drivers/gpu/drm/virtio/virtgpu_drv.c
index ae97b98750b6..af911f65f8a3 100644
--- a/drivers/gpu/drm/virtio/virtgpu_drv.c
+++ b/drivers/gpu/drm/virtio/virtgpu_drv.c
@@ -172,7 +172,8 @@ MODULE_AUTHOR("Alon Levy");
DEFINE_DRM_GEM_FOPS(virtio_gpu_driver_fops);
static const struct drm_driver driver = {
- .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_RENDER | DRIVER_ATOMIC,
+ .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_RENDER | DRIVER_ATOMIC |
+ DRIVER_SYNCOBJ | DRIVER_SYNCOBJ_TIMELINE,
.open = virtio_gpu_driver_open,
.postclose = virtio_gpu_driver_postclose,
diff --git a/drivers/gpu/drm/virtio/virtgpu_ioctl.c b/drivers/gpu/drm/virtio/virtgpu_ioctl.c
index 9f4a90493aea..b17822b833e1 100644
--- a/drivers/gpu/drm/virtio/virtgpu_ioctl.c
+++ b/drivers/gpu/drm/virtio/virtgpu_ioctl.c
@@ -30,6 +30,7 @@
#include <linux/uaccess.h>
#include <drm/drm_file.h>
+#include <drm/drm_syncobj.h>
#include <drm/virtgpu_drm.h>
#include "virtgpu_drv.h"
@@ -38,6 +39,12 @@
VIRTGPU_BLOB_FLAG_USE_SHAREABLE | \
VIRTGPU_BLOB_FLAG_USE_CROSS_DEVICE)
+struct virtio_gpu_submit_post_dep {
+ struct drm_syncobj *syncobj;
+ struct dma_fence_chain *chain;
+ uint64_t point;
+};
+
static int virtio_gpu_fence_event_create(struct drm_device *dev,
struct drm_file *file,
struct virtio_gpu_fence *fence,
@@ -108,6 +115,184 @@ static int virtio_gpu_map_ioctl(struct drm_device *dev, void *data,
&virtio_gpu_map->offset);
}
+static void virtio_gpu_free_syncobjs(struct drm_syncobj **syncobjs,
+ uint32_t nr_syncobjs)
+{
+ uint32_t i = nr_syncobjs;
+
+ while (i--) {
+ if (syncobjs[i])
+ drm_syncobj_put(syncobjs[i]);
+ }
+
+ kfree(syncobjs);
+}
+
+static struct drm_syncobj **
+virtio_gpu_parse_deps(struct drm_file *file,
+ uint64_t fence_ctx,
+ uint32_t ring_idx,
+ uint64_t in_syncobjs_addr,
+ uint32_t nr_in_syncobjs,
+ size_t syncobj_stride)
+{
+ struct drm_virtgpu_execbuffer_syncobj syncobj_desc;
+ struct drm_syncobj **syncobjs = NULL;
+ int ret = 0;
+ uint32_t i;
+
+ syncobjs = kcalloc(nr_in_syncobjs, sizeof(*syncobjs),
+ GFP_KERNEL | __GFP_NOWARN | __GFP_NORETRY);
+ if (!syncobjs)
+ return ERR_PTR(-ENOMEM);
+
+ for (i = 0; i < nr_in_syncobjs; i++) {
+ uint64_t address = in_syncobjs_addr + i * syncobj_stride;
+ struct dma_fence *in_fence;
+
+ if (copy_from_user(&syncobj_desc,
+ u64_to_user_ptr(address),
+ min(syncobj_stride, sizeof(syncobj_desc)))) {
+ ret = -EFAULT;
+ break;
+ }
+
+ if (syncobj_desc.flags & ~VIRTGPU_EXECBUF_SYNCOBJ_FLAGS) {
+ ret = -EINVAL;
+ break;
+ }
+
+ ret = drm_syncobj_find_fence(file, syncobj_desc.handle,
+ syncobj_desc.point, 0, &in_fence);
+ if (ret)
+ break;
+
+ if (!dma_fence_match_context(in_fence, fence_ctx + ring_idx))
+ ret = dma_fence_wait(in_fence, true);
+
+ dma_fence_put(in_fence);
+ if (ret)
+ break;
+
+ if (syncobj_desc.flags & VIRTGPU_EXECBUF_SYNCOBJ_RESET) {
+ syncobjs[i] =
+ drm_syncobj_find(file, syncobj_desc.handle);
+ if (!syncobjs[i]) {
+ ret = -EINVAL;
+ break;
+ }
+ }
+ }
+
+ if (ret) {
+ virtio_gpu_free_syncobjs(syncobjs, i);
+ return ERR_PTR(ret);
+ }
+ return syncobjs;
+}
+
+static void virtio_gpu_reset_syncobjs(struct drm_syncobj **syncobjs,
+ uint32_t nr_syncobjs)
+{
+ uint32_t i;
+
+ for (i = 0; syncobjs && i < nr_syncobjs; i++) {
+ if (syncobjs[i])
+ drm_syncobj_replace_fence(syncobjs[i], NULL);
+ }
+}
+
+static void
+virtio_gpu_free_post_deps(struct virtio_gpu_submit_post_dep *post_deps,
+ uint32_t nr_syncobjs)
+{
+ uint32_t i = nr_syncobjs;
+
+ while (i--) {
+ kfree(post_deps[i].chain);
+ drm_syncobj_put(post_deps[i].syncobj);
+ }
+
+ kfree(post_deps);
+}
+
+static struct virtio_gpu_submit_post_dep *
+virtio_gpu_parse_post_deps(struct drm_file *file,
+ uint64_t syncobjs_addr,
+ uint32_t nr_syncobjs,
+ size_t syncobj_stride)
+{
+ struct drm_virtgpu_execbuffer_syncobj syncobj_desc;
+ struct virtio_gpu_submit_post_dep *post_deps;
+ int ret = 0;
+ uint32_t i;
+
+ post_deps = kmalloc_array(nr_syncobjs, sizeof(*post_deps),
+ GFP_KERNEL | __GFP_NOWARN | __GFP_NORETRY);
+ if (!post_deps)
+ return ERR_PTR(-ENOMEM);
+
+ for (i = 0; i < nr_syncobjs; i++) {
+ uint64_t address = syncobjs_addr + i * syncobj_stride;
+
+ if (copy_from_user(&syncobj_desc,
+ u64_to_user_ptr(address),
+ min(syncobj_stride, sizeof(syncobj_desc)))) {
+ ret = -EFAULT;
+ break;
+ }
+
+ post_deps[i].point = syncobj_desc.point;
+ post_deps[i].chain = NULL;
+
+ if (syncobj_desc.flags) {
+ ret = -EINVAL;
+ break;
+ }
+
+ if (syncobj_desc.point) {
+ post_deps[i].chain = dma_fence_chain_alloc();
+ if (!post_deps[i].chain) {
+ ret = -ENOMEM;
+ break;
+ }
+ }
+
+ post_deps[i].syncobj =
+ drm_syncobj_find(file, syncobj_desc.handle);
+ if (!post_deps[i].syncobj) {
+ ret = -EINVAL;
+ break;
+ }
+ }
+
+ if (ret) {
+ virtio_gpu_free_post_deps(post_deps, i);
+ return ERR_PTR(ret);
+ }
+
+ return post_deps;
+}
+
+static void
+virtio_gpu_process_post_deps(struct virtio_gpu_submit_post_dep *post_deps,
+ uint32_t count,
+ struct dma_fence *fence)
+{
+ uint32_t i;
+
+ for (i = 0; post_deps && i < count; i++) {
+ if (post_deps[i].chain) {
+ drm_syncobj_add_point(post_deps[i].syncobj,
+ post_deps[i].chain,
+ fence, post_deps[i].point);
+ post_deps[i].chain = NULL;
+ } else {
+ drm_syncobj_replace_fence(post_deps[i].syncobj, fence);
+ }
+ }
+}
+
/*
* Usage of execbuffer:
* Relocations need to take into account the full VIRTIO_GPUDrawable size.
@@ -118,6 +303,8 @@ static int virtio_gpu_execbuffer_ioctl(struct drm_device *dev, void *data,
struct drm_file *file)
{
struct drm_virtgpu_execbuffer *exbuf = data;
+ struct drm_syncobj **syncobjs_to_reset = NULL;
+ struct virtio_gpu_submit_post_dep *post_deps = NULL;
struct virtio_gpu_device *vgdev = dev->dev_private;
struct virtio_gpu_fpriv *vfpriv = file->driver_priv;
struct virtio_gpu_fence *out_fence;
@@ -207,10 +394,33 @@ static int virtio_gpu_execbuffer_ioctl(struct drm_device *dev, void *data,
bo_handles = NULL;
}
+ if (exbuf->num_in_syncobjs) {
+ syncobjs_to_reset = virtio_gpu_parse_deps(file,
+ fence_ctx, ring_idx,
+ exbuf->in_syncobjs,
+ exbuf->num_in_syncobjs,
+ exbuf->syncobj_stride);
+ if (IS_ERR(syncobjs_to_reset)) {
+ ret = PTR_ERR(syncobjs_to_reset);
+ goto out_unused_fd;
+ }
+ }
+
+ if (exbuf->num_out_syncobjs) {
+ post_deps = virtio_gpu_parse_post_deps(file,
+ exbuf->out_syncobjs,
+ exbuf->num_out_syncobjs,
+ exbuf->syncobj_stride);
+ if (IS_ERR(post_deps)) {
+ ret = PTR_ERR(post_deps);
+ goto out_syncobjs;
+ }
+ }
+
buf = vmemdup_user(u64_to_user_ptr(exbuf->command), exbuf->size);
if (IS_ERR(buf)) {
ret = PTR_ERR(buf);
- goto out_unused_fd;
+ goto out_post_deps;
}
if (buflist) {
@@ -241,6 +451,13 @@ static int virtio_gpu_execbuffer_ioctl(struct drm_device *dev, void *data,
fd_install(out_fence_fd, sync_file->file);
}
+ virtio_gpu_reset_syncobjs(syncobjs_to_reset, exbuf->num_in_syncobjs);
+ virtio_gpu_free_syncobjs(syncobjs_to_reset, exbuf->num_in_syncobjs);
+
+ virtio_gpu_process_post_deps(post_deps, exbuf->num_out_syncobjs,
+ &out_fence->f);
+ virtio_gpu_free_post_deps(post_deps, exbuf->num_out_syncobjs);
+
virtio_gpu_cmd_submit(vgdev, buf, exbuf->size,
vfpriv->ctx_id, buflist, out_fence);
dma_fence_put(&out_fence->f);
@@ -252,6 +469,10 @@ static int virtio_gpu_execbuffer_ioctl(struct drm_device *dev, void *data,
virtio_gpu_array_unlock_resv(buflist);
out_memdup:
kvfree(buf);
+out_post_deps:
+ virtio_gpu_free_post_deps(post_deps, exbuf->num_out_syncobjs);
+out_syncobjs:
+ virtio_gpu_free_syncobjs(syncobjs_to_reset, exbuf->num_in_syncobjs);
out_unused_fd:
kvfree(bo_handles);
if (buflist)
diff --git a/include/uapi/drm/virtgpu_drm.h b/include/uapi/drm/virtgpu_drm.h
index 0512fde5e697..408a3237f3b4 100644
--- a/include/uapi/drm/virtgpu_drm.h
+++ b/include/uapi/drm/virtgpu_drm.h
@@ -64,6 +64,16 @@ struct drm_virtgpu_map {
__u32 pad;
};
+#define VIRTGPU_EXECBUF_SYNCOBJ_RESET 0x01
+#define VIRTGPU_EXECBUF_SYNCOBJ_FLAGS ( \
+ VIRTGPU_EXECBUF_SYNCOBJ_RESET | \
+ 0)
+struct drm_virtgpu_execbuffer_syncobj {
+ __u32 handle;
+ __u32 flags;
+ __u64 point;
+};
+
struct drm_virtgpu_execbuffer {
__u32 flags;
__u32 size;
@@ -72,7 +82,11 @@ struct drm_virtgpu_execbuffer {
__u32 num_bo_handles;
__s32 fence_fd; /* in/out fence fd (see VIRTGPU_EXECBUF_FENCE_FD_IN/OUT) */
__u32 ring_idx; /* command ring index (see VIRTGPU_EXECBUF_RING_IDX) */
- __u32 pad;
+ __u32 syncobj_stride;
+ __u32 num_in_syncobjs;
+ __u32 num_out_syncobjs;
+ __u64 in_syncobjs;
+ __u64 out_syncobjs;
};
#define VIRTGPU_PARAM_3D_FEATURES 1 /* do we have 3D features in the hw */
--
2.39.0
next prev parent reply other threads:[~2023-01-19 0:43 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-01-19 0:41 [PATCH v1 0/1] Add sync object UAPI support to VirtIO-GPU driver Dmitry Osipenko
2023-01-19 0:41 ` Dmitry Osipenko [this message]
2023-02-25 15:21 ` [PATCH v1 1/1] drm/virtio: Support sync objects Dmitry Osipenko
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=20230119004143.968942-2-dmitry.osipenko@collabora.com \
--to=dmitry.osipenko@collabora.com \
--cc=airlied@redhat.com \
--cc=daniel@ffwll.ch \
--cc=dri-devel@lists.freedesktop.org \
--cc=gurchetansingh@chromium.org \
--cc=kernel@collabora.com \
--cc=kraxel@redhat.com \
--cc=linux-kernel@vger.kernel.org \
--cc=maraeo@gmail.com \
--cc=olvaffe@gmail.com \
--cc=robdclark@gmail.com \
--cc=virtualization@lists.linux-foundation.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
all inboxes | Powered by JetHome®