mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH 0/2] drm/etnaviv: Add GPU reset counters for robustness
@ 2026-07-09 14:57 Christian Gmeiner
  2026-07-09 14:57 ` [PATCH 1/2] drm/etnaviv: Reference count struct etnaviv_file_private Christian Gmeiner
  2026-07-09 14:57 ` [PATCH 2/2] drm/etnaviv: Add GPU reset counters Christian Gmeiner
  0 siblings, 2 replies; 7+ messages in thread
From: Christian Gmeiner @ 2026-07-09 14:57 UTC (permalink / raw)
  To: Lucas Stach, Russell King, Christian Gmeiner, David Airlie,
	Simona Vetter, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann
  Cc: etnaviv, dri-devel, linux-kernel, kernel-dev, Christian Gmeiner

The OpenGL robustness extensions (GL_KHR_robustness) and Vulkan
(VK_ERROR_DEVICE_LOST) let an application detect a GPU reset and check
whether its own context caused it, so it can throw away the broken
context and build a new one. etnaviv already resets the GPU after a
hang, but userspace has no way to learn about it.

This series adds two counters, exposed through GET_PARAM, following the
model already used by msm and v3d:

- ETNAVIV_PARAM_GLOBAL_RESET_COUNTER counts every reset of a GPU core.
- ETNAVIV_PARAM_CONTEXT_RESET_COUNTER counts only the resets the
  calling context was guilty of.

Userspace samples both values and compares them later: if the context
counter moved the context was guilty, if only the global counter moved
the context was an innocent victim. That is all that is needed to
implement glGetGraphicsResetStatus() and Vulkan device loss.

The global counter is kept 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.

The first patch is preparation: the counters are updated from the
scheduler timeout worker, which can race with the DRM file being
closed, so struct etnaviv_file_private becomes reference counted and
every submit holds a reference.

Link to the Mesa MR implementing the userspace side:
https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/42826

Signed-off-by: Christian Gmeiner <cgmeiner@igalia.com>
---
Christian Gmeiner (2):
      drm/etnaviv: Reference count struct etnaviv_file_private
      drm/etnaviv: Add GPU reset counters

 drivers/gpu/drm/etnaviv/etnaviv_drv.c        | 22 +++++++++++++++++++---
 drivers/gpu/drm/etnaviv/etnaviv_drv.h        | 12 ++++++++++++
 drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c |  5 ++++-
 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 ++
 7 files changed, 56 insertions(+), 6 deletions(-)
---
base-commit: 8cdeaa50eae8dad34885515f62559ee83e7e8dda
change-id: 20260708-etnaviv-reset-notification-b037153a1aab

Best regards,
-- 
Christian Gmeiner <cgmeiner@igalia.com>


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 1/2] drm/etnaviv: Reference count struct etnaviv_file_private
  2026-07-09 14:57 [PATCH 0/2] drm/etnaviv: Add GPU reset counters for robustness Christian Gmeiner
@ 2026-07-09 14:57 ` Christian Gmeiner
  2026-07-09 14:57 ` [PATCH 2/2] drm/etnaviv: Add GPU reset counters Christian Gmeiner
  1 sibling, 0 replies; 7+ messages in thread
From: Christian Gmeiner @ 2026-07-09 14:57 UTC (permalink / raw)
  To: Lucas Stach, Russell King, Christian Gmeiner, David Airlie,
	Simona Vetter, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann
  Cc: etnaviv, dri-devel, linux-kernel, kernel-dev, Christian Gmeiner

From: Christian Gmeiner <cgmeiner@igalia.com>

The next commit updates per-context data from the GPU reset path, which
runs in the scheduler timeout worker. This can race with closing the DRM
file: drm_sched_entity_flush() only waits until the entity queue is
empty, it does not wait for jobs still running on the hardware. So the
context can already be freed while the reset path still needs it.

Reference count the context and let every submit hold a reference, the
same way a submit already keeps its mmu context and pid alive. No
functional change.

Signed-off-by: Christian Gmeiner <cgmeiner@igalia.com>
---
 drivers/gpu/drm/etnaviv/etnaviv_drv.c        | 17 ++++++++++++++++-
 drivers/gpu/drm/etnaviv/etnaviv_drv.h        | 11 +++++++++++
 drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c |  5 ++++-
 3 files changed, 31 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/etnaviv/etnaviv_drv.c b/drivers/gpu/drm/etnaviv/etnaviv_drv.c
index 08aca9035fc1..a27ed014fb4e 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_drv.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_drv.c
@@ -60,6 +60,19 @@ static void load_gpu(struct drm_device *dev)
 	}
 }
 
+static void etnaviv_file_private_release(struct kref *kref)
+{
+	struct etnaviv_file_private *ctx =
+		container_of(kref, struct etnaviv_file_private, refcount);
+
+	kfree(ctx);
+}
+
+void etnaviv_file_private_put(struct etnaviv_file_private *ctx)
+{
+	kref_put(&ctx->refcount, etnaviv_file_private_release);
+}
+
 static int etnaviv_open(struct drm_device *dev, struct drm_file *file)
 {
 	struct etnaviv_drm_private *priv = dev->dev_private;
@@ -70,6 +83,8 @@ static int etnaviv_open(struct drm_device *dev, struct drm_file *file)
 	if (!ctx)
 		return -ENOMEM;
 
+	kref_init(&ctx->refcount);
+
 	ret = xa_alloc_cyclic(&priv->active_contexts, &ctx->id, ctx,
 			      xa_limit_32b, &priv->next_context_id, GFP_KERNEL);
 	if (ret < 0)
@@ -120,7 +135,7 @@ static void etnaviv_postclose(struct drm_device *dev, struct drm_file *file)
 
 	xa_erase(&priv->active_contexts, ctx->id);
 
-	kfree(ctx);
+	etnaviv_file_private_put(ctx);
 }
 
 /*
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_drv.h b/drivers/gpu/drm/etnaviv/etnaviv_drv.h
index 55a9e745604d..cba4323ae589 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_drv.h
+++ b/drivers/gpu/drm/etnaviv/etnaviv_drv.h
@@ -7,6 +7,7 @@
 #define __ETNAVIV_DRV_H__
 
 #include <linux/io.h>
+#include <linux/kref.h>
 #include <linux/list.h>
 #include <linux/mm_types.h>
 #include <linux/sizes.h>
@@ -29,6 +30,7 @@ struct etnaviv_iommu_global;
 #define ETNAVIV_SOFTPIN_START_ADDRESS	SZ_4M /* must be >= SUBALLOC_SIZE */
 
 struct etnaviv_file_private {
+	struct kref refcount;
 	int id;
 	struct etnaviv_iommu_context	*mmu;
 	struct drm_sched_entity		sched_entity[ETNA_MAX_PIPES];
@@ -53,6 +55,15 @@ struct etnaviv_drm_private {
 	struct etnaviv_cmdbuf *flop_reset_data_ppu;
 };
 
+void etnaviv_file_private_put(struct etnaviv_file_private *ctx);
+
+static inline struct etnaviv_file_private *
+etnaviv_file_private_get(struct etnaviv_file_private *ctx)
+{
+	kref_get(&ctx->refcount);
+	return ctx;
+}
+
 int etnaviv_ioctl_gem_submit(struct drm_device *dev, void *data,
 		struct drm_file *file);
 
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c b/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c
index 1a77a09b3377..98f1f59a8b05 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c
@@ -398,6 +398,9 @@ static void submit_cleanup(struct kref *kref)
 
 	put_pid(submit->pid);
 
+	if (submit->ctx)
+		etnaviv_file_private_put(submit->ctx);
+
 	kfree(submit->pmrs);
 	kfree(submit);
 }
@@ -526,7 +529,7 @@ int etnaviv_ioctl_gem_submit(struct drm_device *dev, void *data,
 	if (ret)
 		goto err_submit_put;
 
-	submit->ctx = file->driver_priv;
+	submit->ctx = etnaviv_file_private_get(file->driver_priv);
 	submit->mmu_context = etnaviv_iommu_context_get(submit->ctx->mmu);
 	submit->exec_state = args->exec_state;
 	submit->flags = args->flags;

-- 
2.54.0


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 2/2] drm/etnaviv: Add GPU reset counters
  2026-07-09 14:57 [PATCH 0/2] drm/etnaviv: Add GPU reset counters for robustness Christian Gmeiner
  2026-07-09 14:57 ` [PATCH 1/2] drm/etnaviv: Reference count struct etnaviv_file_private Christian Gmeiner
@ 2026-07-09 14:57 ` Christian Gmeiner
  2026-07-09 15:48   ` Lucas Stach
  2026-07-10  8:02   ` Lucas Stach
  1 sibling, 2 replies; 7+ messages in thread
From: Christian Gmeiner @ 2026-07-09 14:57 UTC (permalink / raw)
  To: Lucas Stach, Russell King, Christian Gmeiner, David Airlie,
	Simona Vetter, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann
  Cc: etnaviv, dri-devel, linux-kernel, kernel-dev, Christian Gmeiner

From: Christian Gmeiner <cgmeiner@igalia.com>

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.

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 <cgmeiner@igalia.com>
---
 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
 

-- 
2.54.0


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 2/2] drm/etnaviv: Add GPU reset counters
  2026-07-09 14:57 ` [PATCH 2/2] drm/etnaviv: Add GPU reset counters Christian Gmeiner
@ 2026-07-09 15:48   ` Lucas Stach
  2026-07-09 19:41     ` Christian Gmeiner
  2026-07-10  8:02   ` Lucas Stach
  1 sibling, 1 reply; 7+ messages in thread
From: Lucas Stach @ 2026-07-09 15:48 UTC (permalink / raw)
  To: Christian Gmeiner, Russell King, David Airlie, Simona Vetter,
	Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann
  Cc: etnaviv, dri-devel, linux-kernel, kernel-dev, Christian Gmeiner

Hi Christian,

Am Donnerstag, dem 09.07.2026 um 16:57 +0200 schrieb Christian Gmeiner:
> From: Christian Gmeiner <cgmeiner@igalia.com>
> 
> 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 <cgmeiner@igalia.com>
> ---
>  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
>  

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 2/2] drm/etnaviv: Add GPU reset counters
  2026-07-09 15:48   ` Lucas Stach
@ 2026-07-09 19:41     ` Christian Gmeiner
  2026-07-10  8:10       ` Lucas Stach
  0 siblings, 1 reply; 7+ messages in thread
From: Christian Gmeiner @ 2026-07-09 19:41 UTC (permalink / raw)
  To: Lucas Stach
  Cc: Russell King, David Airlie, Simona Vetter, Maarten Lankhorst,
	Maxime Ripard, Thomas Zimmermann, etnaviv, dri-devel,
	linux-kernel, kernel-dev, Christian Gmeiner

Hi Lucas,

> > 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.
>

Makes sense. I only picked it because msm and v3d expose their fault
counters that way.

For v2 I have replaced the two params with a dedicated ioctl:

struct drm_etnaviv_reset_query {
    __u32 pipe;            /* in */
    __u32 flags;            /* in, must be 0 */
    __u64 global_reset_counter;    /* out */
    __u64 context_reset_counter;    /* out */
};

flags must be zero for now and is rejected with EINVAL otherwise, so
your multi context rework can later add a flag plus a context field to
query a specific context.

>
> 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.
>

One thing to note: the global counter is per GPU core, so a context
that uses more than one pipe still needs one query per pipe. I think
that is fine for the robustness use case, but tell me if you would
rather have a variant that returns all pipes at once.

Will send v2 shortly.

-- 
greets
--
Christian Gmeiner, MSc

https://christian-gmeiner.info/privacypolicy

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 2/2] drm/etnaviv: Add GPU reset counters
  2026-07-09 14:57 ` [PATCH 2/2] drm/etnaviv: Add GPU reset counters Christian Gmeiner
  2026-07-09 15:48   ` Lucas Stach
@ 2026-07-10  8:02   ` Lucas Stach
  1 sibling, 0 replies; 7+ messages in thread
From: Lucas Stach @ 2026-07-10  8:02 UTC (permalink / raw)
  To: Christian Gmeiner, Russell King, David Airlie, Simona Vetter,
	Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann
  Cc: etnaviv, dri-devel, linux-kernel, kernel-dev, Christian Gmeiner

Hi Christian,

Am Donnerstag, dem 09.07.2026 um 16:57 +0200 schrieb Christian Gmeiner:
> From: Christian Gmeiner <cgmeiner@igalia.com>
> 
> 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.
> 
> 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 <cgmeiner@igalia.com>
> ---
>  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_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);
> +

There is no reason for those to be atomics. We only have a single
submission channel per GPU, so there can never be more than a single
timeout handler active at the same time, so those variables can be
plain ints.

Regards,
Lucas

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 2/2] drm/etnaviv: Add GPU reset counters
  2026-07-09 19:41     ` Christian Gmeiner
@ 2026-07-10  8:10       ` Lucas Stach
  0 siblings, 0 replies; 7+ messages in thread
From: Lucas Stach @ 2026-07-10  8:10 UTC (permalink / raw)
  To: Christian Gmeiner
  Cc: Russell King, David Airlie, Simona Vetter, Maarten Lankhorst,
	Maxime Ripard, Thomas Zimmermann, etnaviv, dri-devel,
	linux-kernel, kernel-dev, Christian Gmeiner

Am Donnerstag, dem 09.07.2026 um 21:41 +0200 schrieb Christian Gmeiner:
> Hi Lucas,
> 
> > > 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.
> > 
> 
> Makes sense. I only picked it because msm and v3d expose their fault
> counters that way.
> 
> For v2 I have replaced the two params with a dedicated ioctl:
> 
> struct drm_etnaviv_reset_query {
>     __u32 pipe;            /* in */
>     __u32 flags;            /* in, must be 0 */
>     __u64 global_reset_counter;    /* out */
>     __u64 context_reset_counter;    /* out */
> };
> 
> flags must be zero for now and is rejected with EINVAL otherwise, so
> your multi context rework can later add a flag plus a context field to
> query a specific context.
> 
Looks good to me.

> > 
> > 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.
> > 
> 
> One thing to note: the global counter is per GPU core, so a context
> that uses more than one pipe still needs one query per pipe. I think
> that is fine for the robustness use case, but tell me if you would
> rather have a variant that returns all pipes at once.

I think the current design is fine. While there might be some
configurations where a context uses multiple pipes (2D GPU texture
upload or one of those chips with multiple 3D GPUs), I think that those
are sufficiently rare that we might want to deal with the additional
kernel transitions for those rather than complicating the ioctl for the
common case of a context using a single pipe.

Regards,
Lucas

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2026-07-10  8:10 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-07-09 14:57 [PATCH 0/2] drm/etnaviv: Add GPU reset counters for robustness Christian Gmeiner
2026-07-09 14:57 ` [PATCH 1/2] drm/etnaviv: Reference count struct etnaviv_file_private Christian Gmeiner
2026-07-09 14:57 ` [PATCH 2/2] drm/etnaviv: Add GPU reset counters Christian Gmeiner
2026-07-09 15:48   ` Lucas Stach
2026-07-09 19:41     ` Christian Gmeiner
2026-07-10  8:10       ` Lucas Stach
2026-07-10  8:02   ` Lucas Stach

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®