Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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>

authored by

Tvrtko Ursulin and committed by
Maíra Canal
2f0e1107 745cc3f9

+10 -35
+4 -18
drivers/gpu/drm/v3d/v3d_drv.c
··· 110 110 args->value = !!drm_gem_get_huge_mnt(dev); 111 111 return 0; 112 112 case DRM_V3D_PARAM_GLOBAL_RESET_COUNTER: 113 - mutex_lock(&v3d->reset_lock); 114 - args->value = v3d->reset_counter; 115 - mutex_unlock(&v3d->reset_lock); 113 + args->value = atomic_read(&v3d->reset_counter); 116 114 return 0; 117 115 case DRM_V3D_PARAM_CONTEXT_RESET_COUNTER: 118 - mutex_lock(&v3d->reset_lock); 119 - args->value = v3d_priv->reset_counter; 120 - mutex_unlock(&v3d->reset_lock); 116 + args->value = 0; 117 + for (enum v3d_queue q = 0; q < V3D_MAX_QUEUES; q++) 118 + args->value += atomic_read(&v3d_priv->stats[q]->reset_counter); 121 119 return 0; 122 120 default: 123 121 drm_dbg(dev, "Unknown parameter %d\n", args->param); ··· 171 173 static void 172 174 v3d_postclose(struct drm_device *dev, struct drm_file *file) 173 175 { 174 - struct v3d_dev *v3d = to_v3d_dev(dev); 175 176 struct v3d_file_priv *v3d_priv = file->driver_priv; 176 - unsigned long irqflags; 177 177 enum v3d_queue q; 178 178 179 179 for (q = 0; q < V3D_MAX_QUEUES; q++) { 180 - struct v3d_queue_state *queue = &v3d->queue[q]; 181 - struct v3d_job *job = queue->active_job; 182 - 183 180 drm_sched_entity_destroy(&v3d_priv->sched_entity[q]); 184 - 185 - if (job && job->base.entity == &v3d_priv->sched_entity[q]) { 186 - spin_lock_irqsave(&queue->queue_lock, irqflags); 187 - job->file_priv = NULL; 188 - spin_unlock_irqrestore(&queue->queue_lock, irqflags); 189 - } 190 - 191 181 v3d_stats_put(v3d_priv->stats[q]); 192 182 } 193 183
+4 -10
drivers/gpu/drm/v3d/v3d_drv.h
··· 55 55 * job queues, even the write side never is. 56 56 */ 57 57 seqcount_t lock; 58 + 59 + atomic_t reset_counter; 58 60 }; 59 61 60 62 struct v3d_queue_state { ··· 205 203 */ 206 204 struct v3d_perfmon *global_perfmon; 207 205 208 - /* Global reset counter. The counter must be incremented when 209 - * a GPU reset happens. It must be protected by @reset_lock. 210 - */ 211 - unsigned int reset_counter; 206 + /* Global reset counter incremented on each GPU reset. */ 207 + atomic_t reset_counter; 212 208 }; 213 209 214 210 static inline struct v3d_dev * ··· 233 233 234 234 /* Stores the GPU stats for a specific queue for this fd. */ 235 235 struct v3d_stats *stats[V3D_MAX_QUEUES]; 236 - 237 - /* Per-fd reset counter, must be incremented when a job submitted 238 - * by this fd causes a GPU reset. It must be protected by 239 - * &struct v3d_dev->reset_lock. 240 - */ 241 - unsigned int reset_counter; 242 236 }; 243 237 244 238 struct v3d_bo {
+2 -7
drivers/gpu/drm/v3d/v3d_sched.c
··· 701 701 enum v3d_queue q) 702 702 { 703 703 struct v3d_job *job = to_v3d_job(sched_job); 704 - struct v3d_file_priv *v3d_priv = job->file_priv; 705 - unsigned long irqflags; 706 704 enum v3d_queue i; 707 705 708 706 mutex_lock(&v3d->reset_lock); ··· 715 717 /* get the GPU back into the init state */ 716 718 v3d_reset(v3d); 717 719 718 - v3d->reset_counter++; 719 - spin_lock_irqsave(&v3d->queue[q].queue_lock, irqflags); 720 - if (v3d_priv) 721 - v3d_priv->reset_counter++; 722 - spin_unlock_irqrestore(&v3d->queue[q].queue_lock, irqflags); 720 + atomic_inc(&v3d->reset_counter); 721 + atomic_inc(&job->client_stats->reset_counter); 723 722 724 723 for (i = 0; i < V3D_MAX_QUEUES; i++) 725 724 drm_sched_resubmit_jobs(&v3d->queue[i].sched);