Skip to content

Commit 443f9e0

Browse files
committed
drm/nouveau: uapi: don't pass NO_PREFETCH flag implicitly
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@redhat.com> Reviewed-by: Faith Ekstrand <faith.ekstrand@collabora.com> Link: https://patchwork.freedesktop.org/patch/msgid/20230823181746.3446-1-dakr@redhat.com
1 parent c6b9075 commit 443f9e0

File tree

5 files changed

+38
-10
lines changed

5 files changed

+38
-10
lines changed

drivers/gpu/drm/nouveau/nouveau_dma.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,16 +69,19 @@ READ_GET(struct nouveau_channel *chan, uint64_t *prev_get, int *timeout)
6969
}
7070

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

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

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

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

drivers/gpu/drm/nouveau/nouveau_dma.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@
3131
#include "nouveau_chan.h"
3232

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

3637
/*
3738
* 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);
4546
*/
4647
#define NOUVEAU_DMA_SKIPS (128 / 4)
4748

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

9094
if (chan->dma.ib_max) {
9195
nv50_dma_push(chan, chan->push.addr + (chan->dma.put << 2),
92-
(chan->dma.cur - chan->dma.put) << 2);
96+
(chan->dma.cur - chan->dma.put) << 2, false);
9397
} else {
9498
WRITE_PUT(chan->dma.cur);
9599
}

drivers/gpu/drm/nouveau/nouveau_exec.c

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -164,8 +164,10 @@ nouveau_exec_job_run(struct nouveau_job *job)
164164
}
165165

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

171173
ret = nouveau_fence_emit(fence, chan);
@@ -223,7 +225,18 @@ nouveau_exec_job_init(struct nouveau_exec_job **pjob,
223225
{
224226
struct nouveau_exec_job *job;
225227
struct nouveau_job_args args = {};
226-
int ret;
228+
int i, ret;
229+
230+
for (i = 0; i < __args->push.count; i++) {
231+
struct drm_nouveau_exec_push *p = &__args->push.s[i];
232+
233+
if (unlikely(p->va_len > NV50_DMA_PUSH_MAX_LENGTH)) {
234+
NV_PRINTK(err, nouveau_cli(__args->file_priv),
235+
"pushbuf size exceeds limit: 0x%x max 0x%x\n",
236+
p->va_len, NV50_DMA_PUSH_MAX_LENGTH);
237+
return -EINVAL;
238+
}
239+
}
227240

228241
job = *pjob = kzalloc(sizeof(*job), GFP_KERNEL);
229242
if (!job)

drivers/gpu/drm/nouveau/nouveau_gem.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -856,9 +856,11 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data,
856856
for (i = 0; i < req->nr_push; i++) {
857857
struct nouveau_vma *vma = (void *)(unsigned long)
858858
bo[push[i].bo_index].user_priv;
859+
u64 addr = vma->addr + push[i].offset;
860+
u32 length = push[i].length & ~NOUVEAU_GEM_PUSHBUF_NO_PREFETCH;
861+
bool no_prefetch = push[i].length & NOUVEAU_GEM_PUSHBUF_NO_PREFETCH;
859862

860-
nv50_dma_push(chan, vma->addr + push[i].offset,
861-
push[i].length);
863+
nv50_dma_push(chan, addr, length, no_prefetch);
862864
}
863865
} else
864866
if (drm->client.device.info.chipset >= 0x25) {

include/uapi/drm/nouveau_drm.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ struct drm_nouveau_gem_pushbuf_push {
138138
__u32 pad;
139139
__u64 offset;
140140
__u64 length;
141+
#define NOUVEAU_GEM_PUSHBUF_NO_PREFETCH (1 << 23)
141142
};
142143

143144
struct drm_nouveau_gem_pushbuf {
@@ -338,7 +339,12 @@ struct drm_nouveau_exec_push {
338339
/**
339340
* @va_len: the length of the push buffer mapping
340341
*/
341-
__u64 va_len;
342+
__u32 va_len;
343+
/**
344+
* @flags: the flags for this push buffer mapping
345+
*/
346+
__u32 flags;
347+
#define DRM_NOUVEAU_EXEC_PUSH_NO_PREFETCH 0x1
342348
};
343349

344350
/**

0 commit comments

Comments
 (0)