El mar, 17-02-2026 a las 09:18 -0300, Maíra Canal escribió:
> From: Tvrtko Ursulin <[email protected]>
> 
> 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 <[email protected]>
> Co-developed-by: Maíra Canal <[email protected]>
> Signed-off-by: Maíra Canal <[email protected]>
> ---
>  drivers/gpu/drm/v3d/v3d_drv.c   | 20 ++++----------------
>  drivers/gpu/drm/v3d/v3d_drv.h   | 14 ++++----------
>  drivers/gpu/drm/v3d/v3d_sched.c |  9 ++-------
>  3 files changed, 10 insertions(+), 33 deletions(-)
> 
> diff --git a/drivers/gpu/drm/v3d/v3d_drv.c
> b/drivers/gpu/drm/v3d/v3d_drv.c
> index
> aafb402c6ac3118a57df9fc0a0d21d35d48e3b2c..4e77f4808145df21746ff4b7058
> 089d0d161e3fc 100644
> --- a/drivers/gpu/drm/v3d/v3d_drv.c
> +++ b/drivers/gpu/drm/v3d/v3d_drv.c
> @@ -110,13 +110,13 @@ 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);

Don't we still need to take the reset lock here? Otherwise there would
be a chance that we read the counter while a reset is in flight, no?

Iago

>               return 0;
>       case DRM_V3D_PARAM_CONTEXT_RESET_COUNTER:
>               mutex_lock(&v3d->reset_lock);
> -             args->value = v3d_priv->reset_counter;
> +             args->value = 0;
> +             for (enum v3d_queue q = 0; q < V3D_MAX_QUEUES; q++)
> +                     args->value += atomic_read(&v3d_priv-
> >stats[q]->reset_counter);
>               mutex_unlock(&v3d->reset_lock);
>               return 0;
>       default:
> @@ -173,23 +173,11 @@ v3d_open(struct drm_device *dev, struct
> drm_file *file)
>  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
> 72c3f40715dae6e86e0c8356cb997cdf1cf03fae..3de485abd8fc274b361cd17a00c
> ab189d8e69643 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
> 4adbf5175eb005b37d1feac1514150630ce6aab2..de6497741ff789b5de9212ae3e9
> 941a13cd0475d 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);
> 

Reply via email to