Re: [PATCH drm-misc-next v2] drm/nouveau: uapi: don't pass NO_PREFETCH flag implicitly

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wed, Aug 23, 2023 at 1:17 PM Danilo Krummrich <dakr@xxxxxxxxxx> wrote:
Currently, NO_PREFETCH is passed implicitly through
drm_nouveau_gem_pushbuf_push::length and drm_nouveau_exec_push::va_len.

Since this is a direct representation of how the HW is programmed it
isn't really future proof for a uAPI. Hence, fix this up for the new
uAPI and split up the va_len field of struct drm_nouveau_exec_push,
such that we keep 32bit for va_len and 32bit for flags.

For drm_nouveau_gem_pushbuf_push::length at least provide
NOUVEAU_GEM_PUSHBUF_NO_PREFETCH to indicate the bit shift.

While at it, fix up nv50_dma_push() as well, such that the caller
doesn't need to encode the NO_PREFETCH flag into the length parameter.

Signed-off-by: Danilo Krummrich <dakr@xxxxxxxxxx>

Still

Reviewed-by: Faith Ekstrand <faith.ekstrand@xxxxxxxxxxxxx>
 
---
Changes in v2:
  - dma: rename prefetch to no_prefetch in nv50_dma_push() (Faith)
  - exec: print error message when pushbuf size larger max pushbuf size (Faith)
---
 drivers/gpu/drm/nouveau/nouveau_dma.c  |  7 +++++--
 drivers/gpu/drm/nouveau/nouveau_dma.h  |  8 ++++++--
 drivers/gpu/drm/nouveau/nouveau_exec.c | 19 ++++++++++++++++---
 drivers/gpu/drm/nouveau/nouveau_gem.c  |  6 ++++--
 include/uapi/drm/nouveau_drm.h         |  8 +++++++-
 5 files changed, 38 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/nouveau_dma.c b/drivers/gpu/drm/nouveau/nouveau_dma.c
index b90cac6d5772..b01c029f3a90 100644
--- a/drivers/gpu/drm/nouveau/nouveau_dma.c
+++ b/drivers/gpu/drm/nouveau/nouveau_dma.c
@@ -69,16 +69,19 @@ READ_GET(struct nouveau_channel *chan, uint64_t *prev_get, int *timeout)
 }

 void
-nv50_dma_push(struct nouveau_channel *chan, u64 offset, int length)
+nv50_dma_push(struct nouveau_channel *chan, u64 offset, u32 length,
+             bool no_prefetch)
 {
        struct nvif_user *user = &chan->drm->client.device.user;
        struct nouveau_bo *pb = chan->push.buffer;
        int ip = (chan->dma.ib_put * 2) + chan->dma.ib_base;

        BUG_ON(chan->dma.ib_free < 1);
+       WARN_ON(length > NV50_DMA_PUSH_MAX_LENGTH);

        nouveau_bo_wr32(pb, ip++, lower_32_bits(offset));
-       nouveau_bo_wr32(pb, ip++, upper_32_bits(offset) | length << 8);
+       nouveau_bo_wr32(pb, ip++, upper_32_bits(offset) | length << 8 |
+                       (no_prefetch ? (1 << 31) : 0));

        chan->dma.ib_put = (chan->dma.ib_put + 1) & chan->dma.ib_max;

diff --git a/drivers/gpu/drm/nouveau/nouveau_dma.h b/drivers/gpu/drm/nouveau/nouveau_dma.h
index 035a709c7be1..1744d95b233e 100644
--- a/drivers/gpu/drm/nouveau/nouveau_dma.h
+++ b/drivers/gpu/drm/nouveau/nouveau_dma.h
@@ -31,7 +31,8 @@
 #include "nouveau_chan.h"

 int nouveau_dma_wait(struct nouveau_channel *, int slots, int size);
-void nv50_dma_push(struct nouveau_channel *, u64 addr, int length);
+void nv50_dma_push(struct nouveau_channel *, u64 addr, u32 length,
+                  bool no_prefetch);

 /*
  * There's a hw race condition where you can't jump to your PUT offset,
@@ -45,6 +46,9 @@ void nv50_dma_push(struct nouveau_channel *, u64 addr, int length);
  */
 #define NOUVEAU_DMA_SKIPS (128 / 4)

+/* Maximum push buffer size. */
+#define NV50_DMA_PUSH_MAX_LENGTH 0x7fffff
+
 /* Object handles - for stuff that's doesn't use handle == oclass. */
 enum {
        NvDmaFB         = 0x80000002,
@@ -89,7 +93,7 @@ FIRE_RING(struct nouveau_channel *chan)

        if (chan->dma.ib_max) {
                nv50_dma_push(chan, chan->push.addr + (chan->dma.put << 2),
-                             (chan->dma.cur - chan->dma.put) << 2);
+                             (chan->dma.cur - chan->dma.put) << 2, false);
        } else {
                WRITE_PUT(chan->dma.cur);
        }
diff --git a/drivers/gpu/drm/nouveau/nouveau_exec.c b/drivers/gpu/drm/nouveau/nouveau_exec.c
index 0f927adda4ed..a90c4cd8cbb2 100644
--- a/drivers/gpu/drm/nouveau/nouveau_exec.c
+++ b/drivers/gpu/drm/nouveau/nouveau_exec.c
@@ -164,8 +164,10 @@ nouveau_exec_job_run(struct nouveau_job *job)
        }

        for (i = 0; i < exec_job->push.count; i++) {
-               nv50_dma_push(chan, exec_job->push.s[i].va,
-                             exec_job->push.s[i].va_len);
+               struct drm_nouveau_exec_push *p = &exec_job->push.s[i];
+               bool no_prefetch = p->flags & DRM_NOUVEAU_EXEC_PUSH_NO_PREFETCH;
+
+               nv50_dma_push(chan, p->va, p->va_len, no_prefetch);
        }

        ret = nouveau_fence_emit(fence, chan);
@@ -223,7 +225,18 @@ nouveau_exec_job_init(struct nouveau_exec_job **pjob,
 {
        struct nouveau_exec_job *job;
        struct nouveau_job_args args = {};
-       int ret;
+       int i, ret;
+
+       for (i = 0; i < __args->push.count; i++) {
+               struct drm_nouveau_exec_push *p = &__args->push.s[i];
+
+               if (unlikely(p->va_len > NV50_DMA_PUSH_MAX_LENGTH)) {
+                       NV_PRINTK(err, nouveau_cli(__args->file_priv),
+                                 "pushbuf size exceeds limit: 0x%x max 0x%x\n",
+                                 p->va_len, NV50_DMA_PUSH_MAX_LENGTH);
+                       return -EINVAL;
+               }
+       }

        job = *pjob = kzalloc(sizeof(*job), GFP_KERNEL);
        if (!job)
diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c
index f39360870c70..c0b10d8d3d03 100644
--- a/drivers/gpu/drm/nouveau/nouveau_gem.c
+++ b/drivers/gpu/drm/nouveau/nouveau_gem.c
@@ -856,9 +856,11 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data,
                for (i = 0; i < req->nr_push; i++) {
                        struct nouveau_vma *vma = (void *)(unsigned long)
                                bo[push[i].bo_index].user_priv;
+                       u64 addr = vma->addr + push[i].offset;
+                       u32 length = push[i].length & ~NOUVEAU_GEM_PUSHBUF_NO_PREFETCH;
+                       bool no_prefetch = push[i].length & NOUVEAU_GEM_PUSHBUF_NO_PREFETCH;

-                       nv50_dma_push(chan, vma->addr + push[i].offset,
-                                     push[i].length);
+                       nv50_dma_push(chan, addr, length, no_prefetch);
                }
        } else
        if (drm->client.device.info.chipset >= 0x25) {
diff --git a/include/uapi/drm/nouveau_drm.h b/include/uapi/drm/nouveau_drm.h
index b1ad9d5ffce8..8f16724b5d05 100644
--- a/include/uapi/drm/nouveau_drm.h
+++ b/include/uapi/drm/nouveau_drm.h
@@ -138,6 +138,7 @@ struct drm_nouveau_gem_pushbuf_push {
        __u32 pad;
        __u64 offset;
        __u64 length;
+#define NOUVEAU_GEM_PUSHBUF_NO_PREFETCH (1 << 23)
 };

 struct drm_nouveau_gem_pushbuf {
@@ -338,7 +339,12 @@ struct drm_nouveau_exec_push {
        /**
         * @va_len: the length of the push buffer mapping
         */
-       __u64 va_len;
+       __u32 va_len;
+       /**
+        * flags: the flags for this push buffer mapping
+        */
+       __u32 flags;
+#define DRM_NOUVEAU_EXEC_PUSH_NO_PREFETCH 0x1
 };

 /**

base-commit: b4e9fa933551e51459c634dc4396171dc65284a6
--
2.41.0


[Index of Archives]     [Linux DRI Users]     [Linux Intel Graphics]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [XFree86]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux