Hi Christian, Am Donnerstag, dem 09.07.2026 um 16:57 +0200 schrieb Christian Gmeiner: > From: Christian Gmeiner <[email protected]> > > The OpenGL and Vulkan robustness extensions let an application detect a > GPU reset and check if its own context caused it, so the application can > drop the broken context and build a new one. The kernel knows both > facts, but etnaviv has no way to report them to userspace. > > Add two counters and expose them through GET_PARAM: a per-GPU counter > that counts every reset of that GPU, and a per-context counter that only > counts the resets this context was guilty of. Userspace compares the > counters with saved values: if the context counter moved the context was > guilty, if only the GPU counter moved the context was an innocent > victim.
I don't really agree with the design of exposing this through GET_PARAM. First it assumes that each etnaviv_file_private can only have a single context, something that is true today but which I would very much like to change to rid of false dependencies when the application uses multiple GL contexts through the same screen. I have a rework to do this in the pipe, which I didn't get around to finish, yet. While I don't want to block any of your work on this rework, I also wouldn't like to see UAPI land which bakes in the single context per file private assumption. Second, with this design each userspace query incurs two roundtrips into the kernel, as userspace needs to know both counter values to tell innocent vs guilty resets apart. My vote would be on adding a new ioctl to query both reset counters at the same time, with a flags argument baked in, so it can be extended once I manage to finish the multi context rework. Regards, Lucas > > The GPU counter is per GPU core and not per device, so a hang on one > pipe does not look like an innocent reset to contexts that only use > another pipe. > > Bump the driver minor version so userspace can detect the feature. > > Signed-off-by: Christian Gmeiner <[email protected]> > --- > drivers/gpu/drm/etnaviv/etnaviv_drv.c | 5 +++-- > drivers/gpu/drm/etnaviv/etnaviv_drv.h | 1 + > drivers/gpu/drm/etnaviv/etnaviv_gpu.c | 12 +++++++++++- > drivers/gpu/drm/etnaviv/etnaviv_gpu.h | 6 +++++- > drivers/gpu/drm/etnaviv/etnaviv_sched.c | 3 +++ > include/uapi/drm/etnaviv_drm.h | 2 ++ > 6 files changed, 25 insertions(+), 4 deletions(-) > > diff --git a/drivers/gpu/drm/etnaviv/etnaviv_drv.c > b/drivers/gpu/drm/etnaviv/etnaviv_drv.c > index a27ed014fb4e..14f2fe5fb98c 100644 > --- a/drivers/gpu/drm/etnaviv/etnaviv_drv.c > +++ b/drivers/gpu/drm/etnaviv/etnaviv_drv.c > @@ -293,7 +293,8 @@ static int etnaviv_ioctl_get_param(struct drm_device > *dev, void *data, > if (!gpu) > return -ENXIO; > > - return etnaviv_gpu_get_param(gpu, args->param, &args->value); > + return etnaviv_gpu_get_param(gpu, file->driver_priv, args->param, > + &args->value); > } > > static int etnaviv_ioctl_gem_new(struct drm_device *dev, void *data, > @@ -530,7 +531,7 @@ static const struct drm_driver etnaviv_drm_driver = { > .name = "etnaviv", > .desc = "etnaviv DRM", > .major = 1, > - .minor = 4, > + .minor = 5, > }; > > /* > diff --git a/drivers/gpu/drm/etnaviv/etnaviv_drv.h > b/drivers/gpu/drm/etnaviv/etnaviv_drv.h > index cba4323ae589..fbbb0544130c 100644 > --- a/drivers/gpu/drm/etnaviv/etnaviv_drv.h > +++ b/drivers/gpu/drm/etnaviv/etnaviv_drv.h > @@ -34,6 +34,7 @@ struct etnaviv_file_private { > int id; > struct etnaviv_iommu_context *mmu; > struct drm_sched_entity sched_entity[ETNA_MAX_PIPES]; > + atomic_t reset_counter; > }; > > struct etnaviv_drm_private { > diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c > b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c > index c314b3cb5e70..4253560caa14 100644 > --- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c > +++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c > @@ -39,7 +39,9 @@ static const struct platform_device_id gpu_ids[] = { > * Driver functions: > */ > > -int etnaviv_gpu_get_param(struct etnaviv_gpu *gpu, u32 param, u64 *value) > +int etnaviv_gpu_get_param(struct etnaviv_gpu *gpu, > + struct etnaviv_file_private *ctx, > + u32 param, u64 *value) > { > struct etnaviv_drm_private *priv = gpu->drm->dev_private; > > @@ -167,6 +169,14 @@ int etnaviv_gpu_get_param(struct etnaviv_gpu *gpu, u32 > param, u64 *value) > *value = gpu->identity.eco_id; > break; > > + case ETNAVIV_PARAM_GLOBAL_RESET_COUNTER: > + *value = atomic_read(&gpu->reset_counter); > + break; > + > + case ETNAVIV_PARAM_CONTEXT_RESET_COUNTER: > + *value = atomic_read(&ctx->reset_counter); > + break; > + > default: > DBG("%s: invalid param: %u", dev_name(gpu->dev), param); > return -EINVAL; > diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.h > b/drivers/gpu/drm/etnaviv/etnaviv_gpu.h > index 5cb46c84e03a..a5d7c2158eb5 100644 > --- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.h > +++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.h > @@ -148,6 +148,8 @@ struct etnaviv_gpu { > u32 hangcheck_primid; > u32 hangcheck_fence; > > + atomic_t reset_counter; > + > void __iomem *mmio; > int irq; > > @@ -204,7 +206,9 @@ static inline u32 gpu_read_power(struct etnaviv_gpu *gpu, > u32 reg) > return readl(gpu->mmio + gpu_fix_power_address(gpu, reg)); > } > > -int etnaviv_gpu_get_param(struct etnaviv_gpu *gpu, u32 param, u64 *value); > +int etnaviv_gpu_get_param(struct etnaviv_gpu *gpu, > + struct etnaviv_file_private *ctx, > + u32 param, u64 *value); > > int etnaviv_gpu_init(struct etnaviv_gpu *gpu); > bool etnaviv_fill_identity_from_hwdb(struct etnaviv_gpu *gpu); > diff --git a/drivers/gpu/drm/etnaviv/etnaviv_sched.c > b/drivers/gpu/drm/etnaviv/etnaviv_sched.c > index 139e6e38784b..398608009924 100644 > --- a/drivers/gpu/drm/etnaviv/etnaviv_sched.c > +++ b/drivers/gpu/drm/etnaviv/etnaviv_sched.c > @@ -79,6 +79,9 @@ static enum drm_gpu_sched_stat > etnaviv_sched_timedout_job(struct drm_sched_job > if(sched_job) > drm_sched_increase_karma(sched_job); > > + atomic_inc(&gpu->reset_counter); > + atomic_inc(&submit->ctx->reset_counter); > + > /* get the GPU back into the init state */ > etnaviv_core_dump(submit); > etnaviv_gpu_recover_hang(submit); > diff --git a/include/uapi/drm/etnaviv_drm.h b/include/uapi/drm/etnaviv_drm.h > index af024d90453d..977f6ae82fae 100644 > --- a/include/uapi/drm/etnaviv_drm.h > +++ b/include/uapi/drm/etnaviv_drm.h > @@ -77,6 +77,8 @@ struct drm_etnaviv_timespec { > #define ETNAVIV_PARAM_GPU_PRODUCT_ID 0x1c > #define ETNAVIV_PARAM_GPU_CUSTOMER_ID 0x1d > #define ETNAVIV_PARAM_GPU_ECO_ID 0x1e > +#define ETNAVIV_PARAM_GLOBAL_RESET_COUNTER 0x1f > +#define ETNAVIV_PARAM_CONTEXT_RESET_COUNTER 0x20 > > #define ETNA_MAX_PIPES 4 >
