Add a new NOUVEAU_GEM_PUSHBUF_2 ioctl that accepts and emits a sync
fence fd from/to user space if the user space requests it by passing
corresponding flags.

Signed-off-by: Lauri Peltonen <lpeltonen at nvidia.com>
---
 drm/nouveau_drm.c          |  1 +
 drm/nouveau_gem.c          | 46 ++++++++++++++++++++++++++++++++++++++++++----
 drm/nouveau_gem.h          |  2 ++
 drm/uapi/drm/nouveau_drm.h | 11 +++++++++++
 4 files changed, 56 insertions(+), 4 deletions(-)

diff --git a/drm/nouveau_drm.c b/drm/nouveau_drm.c
index 244d78f..74d5ac6 100644
--- a/drm/nouveau_drm.c
+++ b/drm/nouveau_drm.c
@@ -812,6 +812,7 @@ nouveau_ioctls[] = {
        DRM_IOCTL_DEF_DRV(NOUVEAU_GPUOBJ_FREE, nouveau_abi16_ioctl_gpuobj_free, 
DRM_UNLOCKED|DRM_AUTH|DRM_RENDER_ALLOW),
        DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_NEW, nouveau_gem_ioctl_new, 
DRM_UNLOCKED|DRM_AUTH|DRM_RENDER_ALLOW),
        DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_PUSHBUF, nouveau_gem_ioctl_pushbuf, 
DRM_UNLOCKED|DRM_AUTH|DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_PUSHBUF_2, nouveau_gem_ioctl_pushbuf_2, 
DRM_UNLOCKED|DRM_AUTH|DRM_RENDER_ALLOW),
        DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_CPU_PREP, nouveau_gem_ioctl_cpu_prep, 
DRM_UNLOCKED|DRM_AUTH|DRM_RENDER_ALLOW),
        DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_CPU_FINI, nouveau_gem_ioctl_cpu_fini, 
DRM_UNLOCKED|DRM_AUTH|DRM_RENDER_ALLOW),
        DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_INFO, nouveau_gem_ioctl_info, 
DRM_UNLOCKED|DRM_AUTH|DRM_RENDER_ALLOW),
diff --git a/drm/nouveau_gem.c b/drm/nouveau_gem.c
index 78398d4..ee5782c 100644
--- a/drm/nouveau_gem.c
+++ b/drm/nouveau_gem.c
@@ -636,15 +636,16 @@ nouveau_gem_pushbuf_reloc_apply(struct nouveau_cli *cli,
        return ret;
 }

-int
-nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data,
-                         struct drm_file *file_priv)
+static int
+__nouveau_gem_ioctl_pushbuf(struct drm_device *dev,
+                           struct drm_nouveau_gem_pushbuf *req,
+                           struct drm_nouveau_gem_pushbuf_2 *req_2,
+                           struct drm_file *file_priv)
 {
        struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv, dev);
        struct nouveau_cli *cli = nouveau_cli(file_priv);
        struct nouveau_abi16_chan *temp;
        struct nouveau_drm *drm = nouveau_drm(dev);
-       struct drm_nouveau_gem_pushbuf *req = data;
        struct drm_nouveau_gem_pushbuf_push *push;
        struct drm_nouveau_gem_pushbuf_bo *bo;
        struct nouveau_channel *chan = NULL;
@@ -725,6 +726,14 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void 
*data,
                }
        }

+       if (req_2 && (req_2->flags & NOUVEAU_GEM_PUSHBUF_2_FENCE_WAIT)) {
+               ret = nouveau_fence_sync_fd(req_2->fence, chan);
+               if (ret) {
+                       NV_PRINTK(error, cli, "fence wait: %d\n", ret);
+                       goto out;
+               }
+       }
+
        if (chan->dma.ib_max) {
                ret = nouveau_dma_wait(chan, req->nr_push + 1, 16);
                if (ret) {
@@ -800,6 +809,16 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void 
*data,
                goto out;
        }

+       if (req_2 && (req_2->flags & NOUVEAU_GEM_PUSHBUF_2_FENCE_EMIT)) {
+               ret = nouveau_fence_install(&fence->base, "nv-pushbuf",
+                                           &req_2->fence);
+               if (ret) {
+                       NV_PRINTK(error, cli, "fence install: %d\n", ret);
+                       WIND_RING(chan);
+                       goto out;
+               }
+       }
+
 out:
        validate_fini(&op, fence, bo);
        nouveau_fence_unref(&fence);
@@ -825,6 +844,25 @@ out_next:
        return nouveau_abi16_put(abi16, ret);
 }

+int
+nouveau_gem_ioctl_pushbuf_2(struct drm_device *dev, void *data,
+                           struct drm_file *file_priv)
+{
+       struct drm_nouveau_gem_pushbuf_2 *req_2 = data;
+       struct drm_nouveau_gem_pushbuf *req = &req_2->base;
+
+       return __nouveau_gem_ioctl_pushbuf(dev, req, req_2, file_priv);
+}
+
+int
+nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data,
+                         struct drm_file *file_priv)
+{
+       struct drm_nouveau_gem_pushbuf *req = data;
+
+       return __nouveau_gem_ioctl_pushbuf(dev, req, NULL, file_priv);
+}
+
 static inline uint32_t
 domain_to_ttm(struct nouveau_bo *nvbo, uint32_t domain)
 {
diff --git a/drm/nouveau_gem.h b/drm/nouveau_gem.h
index ddab762..7454dea 100644
--- a/drm/nouveau_gem.h
+++ b/drm/nouveau_gem.h
@@ -27,6 +27,8 @@ extern int nouveau_gem_ioctl_new(struct drm_device *, void *,
                                 struct drm_file *);
 extern int nouveau_gem_ioctl_pushbuf(struct drm_device *, void *,
                                     struct drm_file *);
+extern int nouveau_gem_ioctl_pushbuf_2(struct drm_device *, void *,
+                                      struct drm_file *);
 extern int nouveau_gem_ioctl_cpu_prep(struct drm_device *, void *,
                                      struct drm_file *);
 extern int nouveau_gem_ioctl_cpu_fini(struct drm_device *, void *,
diff --git a/drm/uapi/drm/nouveau_drm.h b/drm/uapi/drm/nouveau_drm.h
index 0d7608d..394cd94 100644
--- a/drm/uapi/drm/nouveau_drm.h
+++ b/drm/uapi/drm/nouveau_drm.h
@@ -115,6 +115,15 @@ struct drm_nouveau_gem_pushbuf {
        uint64_t gart_available;
 };

+#define NOUVEAU_GEM_PUSHBUF_2_FENCE_WAIT                             0x00000001
+#define NOUVEAU_GEM_PUSHBUF_2_FENCE_EMIT                             0x00000002
+struct drm_nouveau_gem_pushbuf_2 {
+       struct drm_nouveau_gem_pushbuf base;
+       uint32_t flags;
+       int32_t  fence;
+       uint64_t reserved;
+};
+
 #define NOUVEAU_GEM_CPU_PREP_NOWAIT                                  0x00000001
 #define NOUVEAU_GEM_CPU_PREP_WRITE                                   0x00000004
 struct drm_nouveau_gem_cpu_prep {
@@ -139,9 +148,11 @@ struct drm_nouveau_gem_cpu_fini {
 #define DRM_NOUVEAU_GEM_CPU_PREP       0x42
 #define DRM_NOUVEAU_GEM_CPU_FINI       0x43
 #define DRM_NOUVEAU_GEM_INFO           0x44
+#define DRM_NOUVEAU_GEM_PUSHBUF_2      0x45

 #define DRM_IOCTL_NOUVEAU_GEM_NEW            DRM_IOWR(DRM_COMMAND_BASE + 
DRM_NOUVEAU_GEM_NEW, struct drm_nouveau_gem_new)
 #define DRM_IOCTL_NOUVEAU_GEM_PUSHBUF        DRM_IOWR(DRM_COMMAND_BASE + 
DRM_NOUVEAU_GEM_PUSHBUF, struct drm_nouveau_gem_pushbuf)
+#define DRM_IOCTL_NOUVEAU_GEM_PUSHBUF_2      DRM_IOWR(DRM_COMMAND_BASE + 
DRM_NOUVEAU_GEM_PUSHBUF_2, struct drm_nouveau_gem_pushbuf_2)
 #define DRM_IOCTL_NOUVEAU_GEM_CPU_PREP       DRM_IOW (DRM_COMMAND_BASE + 
DRM_NOUVEAU_GEM_CPU_PREP, struct drm_nouveau_gem_cpu_prep)
 #define DRM_IOCTL_NOUVEAU_GEM_CPU_FINI       DRM_IOW (DRM_COMMAND_BASE + 
DRM_NOUVEAU_GEM_CPU_FINI, struct drm_nouveau_gem_cpu_fini)
 #define DRM_IOCTL_NOUVEAU_GEM_INFO           DRM_IOWR(DRM_COMMAND_BASE + 
DRM_NOUVEAU_GEM_INFO, struct drm_nouveau_gem_info)
-- 
1.8.1.5

Reply via email to