Re: [PATCH v3 1/5] drm/nouveau/gsp/r535: Add support for INTERNAL_GCX_ENTRY_PREREQUISITE
From: David Airlie
Date: Tue Sep 15 2026 - 20:46:07 EST
On Wed, Sep 16, 2026 at 10:22 AM Lyude Paul <lyude@xxxxxxxxxx> wrote:
>
> OpenRM's runtime PM handling looks a bit different then nouveau's, one part
> in particular that differs from us: OpenRM actually consults GSP to ask
> whether the GPU should be allowed to enter Gc6 and/or GcOff before runtime
> suspending the GPU. In the event the card isn't ready, runtime suspend is
> simply delayed for a few seconds before retrying.
>
> Implement the command used for querying GSP about this,
> NV2080_CTRL_CMD_INTERNAL_GCX_ENTRY_PREREQUISITE, and check to ensure that
> the GPU is ready for runtime suspend in nouveau_pmops_runtime_suspend()
> using this query. If the GPU can't be runtime suspended, update the last
> busy counter of the device and then return -EBUSY from
> nouveau_pmops_runtime_suspend() - essentially delaying the runtime suspend
> process by whatever autosuspend_delay_ms is set to.
>
> Signed-off-by: Lyude Paul <lyude@xxxxxxxxxx>
>
> ---
>
> diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/user.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/user.c
> index 23d11d8221cb6..c47d6daa9e5aa 100644
> --- a/drivers/gpu/drm/nouveau/nvkm/engine/device/user.c
> +++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/user.c
> @@ -27,6 +27,8 @@
>
> #include <core/client.h>
> #include <subdev/fb.h>
> +#include <subdev/gsp.h>
> +#include <subdev/gsp/priv.h>
Including a priv.h seems like a layering violation.
I think you should define a nvkm_gsp_gcx_ready and then call the r535
via a function pointer in nvkm_gsp_func.
> #include <subdev/instmem.h>
> #include <subdev/timer.h>
>
> @@ -189,6 +191,41 @@ nvkm_udevice_time(struct nvkm_udevice *udev, void *data, u32 size)
> return ret;
> }
>
> +static int
> +nvkm_udevice_gcx_ready(struct nvkm_udevice *udev, void *data, u32 size)
> +{
> + struct nvkm_object *object = &udev->object;
> + struct nvkm_device *device = udev->device;
> + struct nvkm_gsp *gsp = device->gsp;
> + union {
> + struct nv_device_gcx_ready_v0 v0;
> + } *args = data;
> + int ret = -ENOSYS;
> +
> + /* XXX: We don't know any way of performing this check outside of GSP, so just assume
> + * things are ready for non-GSP clients.
> + */
> + if (!gsp) {
> + args->v0.ready = NV_DEVICE_GC6_READY | NV_DEVICE_GCOFF_READY;
> + return 0;
> + }
> +
> + nvif_ioctl(object, "device gcx ready size %d\n", size);
> + ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false);
> + if (!ret) {
> + nvif_ioctl(object, "device gcx ready vers %d\n", args->v0.version);
> +
> + ret = r535_gsp_gcx_ready(gsp);
> + if (ret < 0)
> + return ret;
> +
> + args->v0.ready = ret;
> + ret = 0;
> + }
> +
> + return ret;
> +}
> +
> static int
> nvkm_udevice_mthd(struct nvkm_object *object, u32 mthd, void *data, u32 size)
> {
> @@ -199,6 +236,8 @@ nvkm_udevice_mthd(struct nvkm_object *object, u32 mthd, void *data, u32 size)
> return nvkm_udevice_info(udev, data, size);
> case NV_DEVICE_V0_TIME:
> return nvkm_udevice_time(udev, data, size);
> + case NV_DEVICE_V0_GCX_READY:
> + return nvkm_udevice_gcx_ready(udev, data, size);
> default:
> break;
> }
> + return ret;
> +}
> +
> int
> r535_gsp_fini(struct nvkm_gsp *gsp, enum nvkm_suspend_state suspend)
> {
> diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/nvrm/gsp.h b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/nvrm/gsp.h
> index b6683a5bf870c..fd1170037c030 100644
> --- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/nvrm/gsp.h
> +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/nvrm/gsp.h
> @@ -782,6 +782,13 @@ typedef struct NV2080_CTRL_INTERNAL_INTR_GET_KERNEL_TABLE_PARAMS {
>
> #define GSP_FW_HEAP_PARAM_CLIENT_ALLOC_SIZE ((48 << 10) * 2048) // Support 2048 channels
>
> +#define NV2080_CTRL_CMD_INTERNAL_GCX_ENTRY_PREREQUISITE (0x2080a7d7)
> +
> +typedef struct NV2080_CTRL_INTERNAL_GCX_ENTRY_PREREQUISITE_PARAMS {
> + NvBool bIsGC6Satisfied;
> + NvBool bIsGCOFFSatisfied;
> +} NV2080_CTRL_INTERNAL_GCX_ENTRY_PREREQUISITE_PARAMS;
Have you confirmed this struct didn't change in r570,
Thanks,
Dave.