[PATCH 3/3] drm/nouveau: exec: report max pushs through getparam
Faith Ekstrand
faith.ekstrand at collabora.com
Wed Sep 27 21:55:52 UTC 2023
On Wed, 2023-09-27 at 03:22 +0200, Danilo Krummrich wrote:
> 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.
There's a bunch of nouveau kernel details I don't know here but the
interface looks good and I prefer it to a #define in the header.
Acked-by: Faith Ekstrand <faith.ekstrand at collabora.com>
> Signed-off-by: Danilo Krummrich <dakr at redhat.com>
> ---
> drivers/gpu/drm/nouveau/nouveau_abi16.c | 19 +++++++++++++++++++
> drivers/gpu/drm/nouveau/nouveau_chan.c | 2 +-
> drivers/gpu/drm/nouveau/nouveau_dma.h | 3 +++
> drivers/gpu/drm/nouveau/nouveau_exec.c | 7 ++++---
> drivers/gpu/drm/nouveau/nouveau_exec.h | 5 +++++
> include/uapi/drm/nouveau_drm.h | 10 ++++++++++
> 6 files changed, 42 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/gpu/drm/nouveau/nouveau_abi16.c
> b/drivers/gpu/drm/nouveau/nouveau_abi16.c
> index 30afbec9e3b1..1a198689b391 100644
> --- a/drivers/gpu/drm/nouveau/nouveau_abi16.c
> +++ b/drivers/gpu/drm/nouveau/nouveau_abi16.c
> @@ -31,6 +31,7 @@
>
> #include "nouveau_drv.h"
> #include "nouveau_dma.h"
> +#include "nouveau_exec.h"
> #include "nouveau_gem.h"
> #include "nouveau_chan.h"
> #include "nouveau_abi16.h"
> @@ -183,6 +184,20 @@ nouveau_abi16_fini(struct nouveau_abi16 *abi16)
> cli->abi16 = NULL;
> }
>
> +static inline unsigned int
> +getparam_dma_ib_max(struct nvif_device *device)
> +{
> + const struct nvif_mclass dmas[] = {
> + { NV03_CHANNEL_DMA, 0 },
> + { NV10_CHANNEL_DMA, 0 },
> + { NV17_CHANNEL_DMA, 0 },
> + { NV40_CHANNEL_DMA, 0 },
> + {}
> + };
> +
> + return nvif_mclass(&device->object, dmas) < 0 ?
> NV50_DMA_IB_MAX : 0;
> +}
> +
> int
> nouveau_abi16_ioctl_getparam(ABI16_IOCTL_ARGS)
> {
> @@ -247,6 +262,10 @@ nouveau_abi16_ioctl_getparam(ABI16_IOCTL_ARGS)
> case NOUVEAU_GETPARAM_GRAPH_UNITS:
> getparam->value = nvkm_gr_units(gr);
> break;
> + case NOUVEAU_GETPARAM_EXEC_PUSH_MAX:
> + getparam->value = getparam_dma_ib_max(device) /
> + NOUVEAU_EXEC_PUSH_MAX_DIV;
> + break;
> default:
> NV_PRINTK(dbg, cli, "unknown parameter %lld\n",
> getparam->param);
> return -EINVAL;
> diff --git a/drivers/gpu/drm/nouveau/nouveau_chan.c
> b/drivers/gpu/drm/nouveau/nouveau_chan.c
> index ac56f4689ee3..c3c2ab887978 100644
> --- a/drivers/gpu/drm/nouveau/nouveau_chan.c
> +++ b/drivers/gpu/drm/nouveau/nouveau_chan.c
> @@ -456,7 +456,7 @@ nouveau_channel_init(struct nouveau_channel
> *chan, u32 vram, u32 gart)
> chan->user_get = 0x44;
> chan->user_get_hi = 0x60;
> chan->dma.ib_base = 0x10000 / 4;
> - chan->dma.ib_max = (0x02000 / 8) - 1;
> + chan->dma.ib_max = NV50_DMA_IB_MAX;
> chan->dma.ib_put = 0;
> chan->dma.ib_free = chan->dma.ib_max - chan-
> >dma.ib_put;
> chan->dma.max = chan->dma.ib_base;
> diff --git a/drivers/gpu/drm/nouveau/nouveau_dma.h
> b/drivers/gpu/drm/nouveau/nouveau_dma.h
> index 1744d95b233e..c52cda82353e 100644
> --- a/drivers/gpu/drm/nouveau/nouveau_dma.h
> +++ b/drivers/gpu/drm/nouveau/nouveau_dma.h
> @@ -49,6 +49,9 @@ void nv50_dma_push(struct nouveau_channel *, u64
> addr, u32 length,
> /* Maximum push buffer size. */
> #define NV50_DMA_PUSH_MAX_LENGTH 0x7fffff
>
> +/* Maximum IBs per ring. */
> +#define NV50_DMA_IB_MAX ((0x02000 / 8) - 1)
> +
> /* Object handles - for stuff that's doesn't use handle == oclass.
> */
> enum {
> NvDmaFB = 0x80000002,
> diff --git a/drivers/gpu/drm/nouveau/nouveau_exec.c
> b/drivers/gpu/drm/nouveau/nouveau_exec.c
> index ba6913a3efb6..5b5c4a77b8e6 100644
> --- a/drivers/gpu/drm/nouveau/nouveau_exec.c
> +++ b/drivers/gpu/drm/nouveau/nouveau_exec.c
> @@ -346,7 +346,7 @@ nouveau_exec_ioctl_exec(struct drm_device *dev,
> struct nouveau_channel *chan = NULL;
> struct nouveau_exec_job_args args = {};
> struct drm_nouveau_exec *req = data;
> - int ret = 0;
> + int push_max, ret = 0;
>
> if (unlikely(!abi16))
> return -ENOMEM;
> @@ -371,9 +371,10 @@ nouveau_exec_ioctl_exec(struct drm_device *dev,
> if (!chan->dma.ib_max)
> return nouveau_abi16_put(abi16, -ENOSYS);
>
> - if (unlikely(req->push_count > NOUVEAU_GEM_MAX_PUSH)) {
> + push_max = chan->dma.ib_max / NOUVEAU_EXEC_PUSH_MAX_DIV;
> + if (unlikely(req->push_count > push_max)) {
> NV_PRINTK(err, cli, "pushbuf push count exceeds
> limit: %d max %d\n",
> - req->push_count, NOUVEAU_GEM_MAX_PUSH);
> + req->push_count, push_max);
> return nouveau_abi16_put(abi16, -EINVAL);
> }
>
> diff --git a/drivers/gpu/drm/nouveau/nouveau_exec.h
> b/drivers/gpu/drm/nouveau/nouveau_exec.h
> index b815de2428f3..c6270452e4b5 100644
> --- a/drivers/gpu/drm/nouveau/nouveau_exec.h
> +++ b/drivers/gpu/drm/nouveau/nouveau_exec.h
> @@ -6,6 +6,11 @@
> #include "nouveau_drv.h"
> #include "nouveau_sched.h"
>
> +/* Divider to limit the number of IBs per job to half the size of
> the ring in
> + * order to avoid the ring running dry between submissions.
> + */
> +#define NOUVEAU_EXEC_PUSH_MAX_DIV 2
> +
> struct nouveau_exec_job_args {
> struct drm_file *file_priv;
> struct nouveau_sched_entity *sched_entity;
> diff --git a/include/uapi/drm/nouveau_drm.h
> b/include/uapi/drm/nouveau_drm.h
> index 8d7402c13e56..eaf9f248619f 100644
> --- a/include/uapi/drm/nouveau_drm.h
> +++ b/include/uapi/drm/nouveau_drm.h
> @@ -44,6 +44,16 @@ extern "C" {
> #define NOUVEAU_GETPARAM_PTIMER_TIME 14
> #define NOUVEAU_GETPARAM_HAS_BO_USAGE 15
> #define NOUVEAU_GETPARAM_HAS_PAGEFLIP 16
> +
> +/**
> + * @NOUVEAU_GETPARAM_EXEC_PUSH_MAX
> + *
> + * Query the maximum amount of IBs that can be pushed through a
> single
> + * &drm_nouveau_exec structure and hence a single
> &DRM_IOCTL_NOUVEAU_EXEC
> + * ioctl().
> + */
> +#define NOUVEAU_GETPARAM_EXEC_PUSH_MAX 17
> +
> struct drm_nouveau_getparam {
> __u64 param;
> __u64 value;
More information about the dri-devel
mailing list