Skip to content

Commit d59e75e

Browse files
committed
drm/nouveau: exec: report max pushs through getparam
Report the maximum number of IBs that can be pushed with a single DRM_IOCTL_NOUVEAU_EXEC through DRM_IOCTL_NOUVEAU_GETPARAM. While the maximum number of IBs per ring might vary between chipsets, the kernel will make sure that userspace can only push a fraction of the maximum number of IBs per ring per job, such that we avoid a situation where there's only a single job occupying the ring, which could potentially lead to the ring run dry. Using DRM_IOCTL_NOUVEAU_GETPARAM to report the maximum number of IBs that can be pushed with a single DRM_IOCTL_NOUVEAU_EXEC implies that all channels of a given device have the same ring size. Reviewed-by: Dave Airlie <[email protected]> Reviewed-by: Lyude Paul <[email protected]> Acked-by: Faith Ekstrand <[email protected]> Signed-off-by: Danilo Krummrich <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected]
1 parent bbe08a0 commit d59e75e

File tree

6 files changed

+49
-4
lines changed

6 files changed

+49
-4
lines changed

drivers/gpu/drm/nouveau/nouveau_abi16.c

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131

3232
#include "nouveau_drv.h"
3333
#include "nouveau_dma.h"
34+
#include "nouveau_exec.h"
3435
#include "nouveau_gem.h"
3536
#include "nouveau_chan.h"
3637
#include "nouveau_abi16.h"
@@ -183,6 +184,20 @@ nouveau_abi16_fini(struct nouveau_abi16 *abi16)
183184
cli->abi16 = NULL;
184185
}
185186

187+
static inline int
188+
getparam_dma_ib_max(struct nvif_device *device)
189+
{
190+
const struct nvif_mclass dmas[] = {
191+
{ NV03_CHANNEL_DMA, 0 },
192+
{ NV10_CHANNEL_DMA, 0 },
193+
{ NV17_CHANNEL_DMA, 0 },
194+
{ NV40_CHANNEL_DMA, 0 },
195+
{}
196+
};
197+
198+
return nvif_mclass(&device->object, dmas) < 0 ? NV50_DMA_IB_MAX : 0;
199+
}
200+
186201
int
187202
nouveau_abi16_ioctl_getparam(ABI16_IOCTL_ARGS)
188203
{
@@ -247,6 +262,12 @@ nouveau_abi16_ioctl_getparam(ABI16_IOCTL_ARGS)
247262
case NOUVEAU_GETPARAM_GRAPH_UNITS:
248263
getparam->value = nvkm_gr_units(gr);
249264
break;
265+
case NOUVEAU_GETPARAM_EXEC_PUSH_MAX: {
266+
int ib_max = getparam_dma_ib_max(device);
267+
268+
getparam->value = nouveau_exec_push_max_from_ib_max(ib_max);
269+
break;
270+
}
250271
default:
251272
NV_PRINTK(dbg, cli, "unknown parameter %lld\n", getparam->param);
252273
return -EINVAL;

drivers/gpu/drm/nouveau/nouveau_chan.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -454,7 +454,7 @@ nouveau_channel_init(struct nouveau_channel *chan, u32 vram, u32 gart)
454454
chan->user_get = 0x44;
455455
chan->user_get_hi = 0x60;
456456
chan->dma.ib_base = 0x10000 / 4;
457-
chan->dma.ib_max = (0x02000 / 8) - 1;
457+
chan->dma.ib_max = NV50_DMA_IB_MAX;
458458
chan->dma.ib_put = 0;
459459
chan->dma.ib_free = chan->dma.ib_max - chan->dma.ib_put;
460460
chan->dma.max = chan->dma.ib_base;

drivers/gpu/drm/nouveau/nouveau_dma.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@ void nv50_dma_push(struct nouveau_channel *, u64 addr, u32 length,
4949
/* Maximum push buffer size. */
5050
#define NV50_DMA_PUSH_MAX_LENGTH 0x7fffff
5151

52+
/* Maximum IBs per ring. */
53+
#define NV50_DMA_IB_MAX ((0x02000 / 8) - 1)
54+
5255
/* Object handles - for stuff that's doesn't use handle == oclass. */
5356
enum {
5457
NvDmaFB = 0x80000002,

drivers/gpu/drm/nouveau/nouveau_exec.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -379,7 +379,7 @@ nouveau_exec_ioctl_exec(struct drm_device *dev,
379379
struct nouveau_channel *chan = NULL;
380380
struct nouveau_exec_job_args args = {};
381381
struct drm_nouveau_exec *req = data;
382-
int ret = 0;
382+
int push_max, ret = 0;
383383

384384
if (unlikely(!abi16))
385385
return -ENOMEM;
@@ -404,9 +404,10 @@ nouveau_exec_ioctl_exec(struct drm_device *dev,
404404
if (!chan->dma.ib_max)
405405
return nouveau_abi16_put(abi16, -ENOSYS);
406406

407-
if (unlikely(req->push_count > NOUVEAU_GEM_MAX_PUSH)) {
407+
push_max = nouveau_exec_push_max_from_ib_max(chan->dma.ib_max);
408+
if (unlikely(req->push_count > push_max)) {
408409
NV_PRINTK(err, cli, "pushbuf push count exceeds limit: %d max %d\n",
409-
req->push_count, NOUVEAU_GEM_MAX_PUSH);
410+
req->push_count, push_max);
410411
return nouveau_abi16_put(abi16, -EINVAL);
411412
}
412413

drivers/gpu/drm/nouveau/nouveau_exec.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,4 +51,14 @@ int nouveau_exec_job_init(struct nouveau_exec_job **job,
5151
int nouveau_exec_ioctl_exec(struct drm_device *dev, void *data,
5252
struct drm_file *file_priv);
5353

54+
static inline unsigned int
55+
nouveau_exec_push_max_from_ib_max(int ib_max)
56+
{
57+
/* Limit the number of IBs per job to half the size of the ring in order
58+
* to avoid the ring running dry between submissions and preserve one
59+
* more slot for the job's HW fence.
60+
*/
61+
return ib_max > 1 ? ib_max / 2 - 1 : 0;
62+
}
63+
5464
#endif

include/uapi/drm/nouveau_drm.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,16 @@ extern "C" {
4444
#define NOUVEAU_GETPARAM_PTIMER_TIME 14
4545
#define NOUVEAU_GETPARAM_HAS_BO_USAGE 15
4646
#define NOUVEAU_GETPARAM_HAS_PAGEFLIP 16
47+
48+
/**
49+
* @NOUVEAU_GETPARAM_EXEC_PUSH_MAX
50+
*
51+
* Query the maximum amount of IBs that can be pushed through a single
52+
* &drm_nouveau_exec structure and hence a single &DRM_IOCTL_NOUVEAU_EXEC
53+
* ioctl().
54+
*/
55+
#define NOUVEAU_GETPARAM_EXEC_PUSH_MAX 17
56+
4757
struct drm_nouveau_getparam {
4858
__u64 param;
4959
__u64 value;

0 commit comments

Comments
 (0)