diff options
| author | Tvrtko Ursulin <tvrtko.ursulin@igalia.com> | 2026-03-06 14:30:37 +0300 |
|---|---|---|
| committer | Maíra Canal <mcanal@igalia.com> | 2026-03-14 00:02:32 +0300 |
| commit | 2f0e110735a4e59e71e44d04b4f70e58f06c61c9 (patch) | |
| tree | 9fb6aac959f8a2b8d0d5adf532ee4daffa166794 /drivers/gpu | |
| parent | 745cc3f92a4b43606119b81d1f8bb1d1f5116049 (diff) | |
| download | linux-2f0e110735a4e59e71e44d04b4f70e58f06c61c9.tar.xz | |
drm/v3d: Attach per-fd reset counters to v3d_stats
To remove the file_priv NULL-ing dance needed to check if the file
descriptor is open, move the per-fd reset counter into v3d_stats, which
is heap-allocated and refcounted, outliving the fd as long as jobs
reference it.
This change allows the removal of the last `queue_lock` usage to protect
`job->file_priv` and avoids possible NULL ptr dereference issues due to
lifetime mismatches.
Also, to simplify locking, replace both the global and per-fd locked
reset counters with atomics.
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
Reviewed-by: Iago Toral Quiroga <itoral@igalia.com>
Link: https://patch.msgid.link/20260306-v3d-reset-locking-improv-v3-5-49864fe00692@igalia.com
Co-developed-by: Maíra Canal <mcanal@igalia.com>
Signed-off-by: Maíra Canal <mcanal@igalia.com>
Diffstat (limited to 'drivers/gpu')
| -rw-r--r-- | drivers/gpu/drm/v3d/v3d_drv.c | 22 | ||||
| -rw-r--r-- | drivers/gpu/drm/v3d/v3d_drv.h | 14 | ||||
| -rw-r--r-- | drivers/gpu/drm/v3d/v3d_sched.c | 9 |
3 files changed, 10 insertions, 35 deletions
diff --git a/drivers/gpu/drm/v3d/v3d_drv.c b/drivers/gpu/drm/v3d/v3d_drv.c index 0f5e29f57fa5..4b441afcb602 100644 --- a/drivers/gpu/drm/v3d/v3d_drv.c +++ b/drivers/gpu/drm/v3d/v3d_drv.c @@ -110,14 +110,12 @@ static int v3d_get_param_ioctl(struct drm_device *dev, void *data, args->value = !!drm_gem_get_huge_mnt(dev); return 0; case DRM_V3D_PARAM_GLOBAL_RESET_COUNTER: - mutex_lock(&v3d->reset_lock); - args->value = v3d->reset_counter; - mutex_unlock(&v3d->reset_lock); + args->value = atomic_read(&v3d->reset_counter); return 0; case DRM_V3D_PARAM_CONTEXT_RESET_COUNTER: - mutex_lock(&v3d->reset_lock); - args->value = v3d_priv->reset_counter; - mutex_unlock(&v3d->reset_lock); + args->value = 0; + for (enum v3d_queue q = 0; q < V3D_MAX_QUEUES; q++) + args->value += atomic_read(&v3d_priv->stats[q]->reset_counter); return 0; default: drm_dbg(dev, "Unknown parameter %d\n", args->param); @@ -173,23 +171,11 @@ err_stats: static void v3d_postclose(struct drm_device *dev, struct drm_file *file) { - struct v3d_dev *v3d = to_v3d_dev(dev); struct v3d_file_priv *v3d_priv = file->driver_priv; - unsigned long irqflags; enum v3d_queue q; for (q = 0; q < V3D_MAX_QUEUES; q++) { - struct v3d_queue_state *queue = &v3d->queue[q]; - struct v3d_job *job = queue->active_job; - drm_sched_entity_destroy(&v3d_priv->sched_entity[q]); - - if (job && job->base.entity == &v3d_priv->sched_entity[q]) { - spin_lock_irqsave(&queue->queue_lock, irqflags); - job->file_priv = NULL; - spin_unlock_irqrestore(&queue->queue_lock, irqflags); - } - v3d_stats_put(v3d_priv->stats[q]); } diff --git a/drivers/gpu/drm/v3d/v3d_drv.h b/drivers/gpu/drm/v3d/v3d_drv.h index 72c3f40715da..3de485abd8fc 100644 --- a/drivers/gpu/drm/v3d/v3d_drv.h +++ b/drivers/gpu/drm/v3d/v3d_drv.h @@ -55,6 +55,8 @@ struct v3d_stats { * job queues, even the write side never is. */ seqcount_t lock; + + atomic_t reset_counter; }; struct v3d_queue_state { @@ -203,10 +205,8 @@ struct v3d_dev { */ struct v3d_perfmon *global_perfmon; - /* Global reset counter. The counter must be incremented when - * a GPU reset happens. It must be protected by @reset_lock. - */ - unsigned int reset_counter; + /* Global reset counter incremented on each GPU reset. */ + atomic_t reset_counter; }; static inline struct v3d_dev * @@ -233,12 +233,6 @@ struct v3d_file_priv { /* Stores the GPU stats for a specific queue for this fd. */ struct v3d_stats *stats[V3D_MAX_QUEUES]; - - /* Per-fd reset counter, must be incremented when a job submitted - * by this fd causes a GPU reset. It must be protected by - * &struct v3d_dev->reset_lock. - */ - unsigned int reset_counter; }; struct v3d_bo { diff --git a/drivers/gpu/drm/v3d/v3d_sched.c b/drivers/gpu/drm/v3d/v3d_sched.c index 5c387a152e33..1855ef5b3b5f 100644 --- a/drivers/gpu/drm/v3d/v3d_sched.c +++ b/drivers/gpu/drm/v3d/v3d_sched.c @@ -701,8 +701,6 @@ v3d_gpu_reset_for_timeout(struct v3d_dev *v3d, struct drm_sched_job *sched_job, enum v3d_queue q) { struct v3d_job *job = to_v3d_job(sched_job); - struct v3d_file_priv *v3d_priv = job->file_priv; - unsigned long irqflags; enum v3d_queue i; mutex_lock(&v3d->reset_lock); @@ -717,11 +715,8 @@ v3d_gpu_reset_for_timeout(struct v3d_dev *v3d, struct drm_sched_job *sched_job, /* get the GPU back into the init state */ v3d_reset(v3d); - v3d->reset_counter++; - spin_lock_irqsave(&v3d->queue[q].queue_lock, irqflags); - if (v3d_priv) - v3d_priv->reset_counter++; - spin_unlock_irqrestore(&v3d->queue[q].queue_lock, irqflags); + atomic_inc(&v3d->reset_counter); + atomic_inc(&job->client_stats->reset_counter); for (i = 0; i < V3D_MAX_QUEUES; i++) drm_sched_resubmit_jobs(&v3d->queue[i].sched); |
