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: Hold v3d_stats references in each job

Have each job hold its own references to the per-fd and global stats
objects. This eliminates the need for `queue_lock` protection in the
stats update path, since the job's stats pointers are guaranteed to
remain valid for the job's entire lifetime regardless of file descriptor
closure.

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-4-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
745cc3f9 266d4ba3

+34 -37
+5 -1
drivers/gpu/drm/v3d/v3d_drv.h
··· 326 326 */ 327 327 struct v3d_file_priv *file_priv; 328 328 329 + /* Pointers to this job's per-fd and global queue stats. */ 330 + struct v3d_stats *client_stats; 331 + struct v3d_stats *global_stats; 332 + 329 333 /* Callback for the freeing of the job on refcount going to 0. */ 330 334 void (*free)(struct kref *ref); 331 335 }; ··· 611 607 unsigned int count); 612 608 struct v3d_stats *v3d_stats_alloc(void); 613 609 void v3d_stats_release(struct kref *refcount); 614 - void v3d_job_update_stats(struct v3d_job *job, enum v3d_queue q); 610 + void v3d_job_update_stats(struct v3d_job *job); 615 611 int v3d_sched_init(struct v3d_dev *v3d); 616 612 void v3d_sched_fini(struct v3d_dev *v3d); 617 613
+1 -1
drivers/gpu/drm/v3d/v3d_irq.c
··· 92 92 struct v3d_queue_state *queue = &v3d->queue[q]; 93 93 struct v3d_fence *fence = to_v3d_fence(queue->active_job->irq_fence); 94 94 95 - v3d_job_update_stats(queue->active_job, q); 95 + v3d_job_update_stats(queue->active_job); 96 96 trace_irq(&v3d->drm, fence->seqno); 97 97 98 98 queue->active_job = NULL;
+22 -35
drivers/gpu/drm/v3d/v3d_sched.c
··· 158 158 } 159 159 160 160 static void 161 - v3d_job_start_stats(struct v3d_job *job, enum v3d_queue queue) 161 + v3d_stats_start(struct v3d_stats *stats, u64 now) 162 162 { 163 - struct v3d_dev *v3d = job->v3d; 164 - struct v3d_file_priv *file = job->file_priv; 165 - struct v3d_stats *global_stats = v3d->queue[queue].stats; 166 - struct v3d_stats *local_stats = file->stats[queue]; 163 + raw_write_seqcount_begin(&stats->lock); 164 + stats->start_ns = now; 165 + raw_write_seqcount_end(&stats->lock); 166 + } 167 + 168 + static void 169 + v3d_job_start_stats(struct v3d_job *job) 170 + { 167 171 u64 now = local_clock(); 168 172 169 173 preempt_disable(); 170 - 171 - raw_write_seqcount_begin(&local_stats->lock); 172 - local_stats->start_ns = now; 173 - raw_write_seqcount_end(&local_stats->lock); 174 - 175 - raw_write_seqcount_begin(&global_stats->lock); 176 - global_stats->start_ns = now; 177 - raw_write_seqcount_end(&global_stats->lock); 178 - 174 + v3d_stats_start(job->client_stats, now); 175 + v3d_stats_start(job->global_stats, now); 179 176 preempt_enable(); 180 177 } 181 178 ··· 187 190 } 188 191 189 192 void 190 - v3d_job_update_stats(struct v3d_job *job, enum v3d_queue q) 193 + v3d_job_update_stats(struct v3d_job *job) 191 194 { 192 - struct v3d_dev *v3d = job->v3d; 193 - struct v3d_queue_state *queue = &v3d->queue[q]; 194 - struct v3d_stats *global_stats = queue->stats; 195 195 u64 now = local_clock(); 196 196 197 197 preempt_disable(); 198 - 199 - /* Don't update the local stats if the file context has already closed */ 200 - spin_lock(&queue->queue_lock); 201 - if (job->file_priv) 202 - v3d_stats_update(job->file_priv->stats[q], now); 203 - spin_unlock(&queue->queue_lock); 204 - 205 - v3d_stats_update(global_stats, now); 206 - 198 + v3d_stats_update(job->client_stats, now); 199 + v3d_stats_update(job->global_stats, now); 207 200 preempt_enable(); 208 201 } 209 202 ··· 237 250 trace_v3d_submit_cl(dev, false, to_v3d_fence(fence)->seqno, 238 251 job->start, job->end); 239 252 240 - v3d_job_start_stats(&job->base, V3D_BIN); 253 + v3d_job_start_stats(&job->base); 241 254 v3d_switch_perfmon(v3d, &job->base); 242 255 243 256 /* Set the current and end address of the control list. ··· 291 304 trace_v3d_submit_cl(dev, true, to_v3d_fence(fence)->seqno, 292 305 job->start, job->end); 293 306 294 - v3d_job_start_stats(&job->base, V3D_RENDER); 307 + v3d_job_start_stats(&job->base); 295 308 v3d_switch_perfmon(v3d, &job->base); 296 309 297 310 /* XXX: Set the QCFG */ ··· 330 343 331 344 trace_v3d_submit_tfu(dev, to_v3d_fence(fence)->seqno); 332 345 333 - v3d_job_start_stats(&job->base, V3D_TFU); 346 + v3d_job_start_stats(&job->base); 334 347 335 348 V3D_WRITE(V3D_TFU_IIA(v3d->ver), job->args.iia); 336 349 V3D_WRITE(V3D_TFU_IIS(v3d->ver), job->args.iis); ··· 380 393 381 394 trace_v3d_submit_csd(dev, to_v3d_fence(fence)->seqno); 382 395 383 - v3d_job_start_stats(&job->base, V3D_CSD); 396 + v3d_job_start_stats(&job->base); 384 397 v3d_switch_perfmon(v3d, &job->base); 385 398 386 399 csd_cfg0_reg = V3D_CSD_QUEUED_CFG0(v3d->ver); ··· 668 681 return NULL; 669 682 } 670 683 671 - v3d_job_start_stats(&job->base, V3D_CPU); 684 + v3d_job_start_stats(&job->base); 672 685 trace_v3d_cpu_job_begin(&v3d->drm, job->job_type); 673 686 674 687 cpu_job_function[job->job_type](job); 675 688 676 689 trace_v3d_cpu_job_end(&v3d->drm, job->job_type); 677 - v3d_job_update_stats(&job->base, V3D_CPU); 690 + v3d_job_update_stats(&job->base); 678 691 679 692 /* Synchronous operation, so no fence to wait on. */ 680 693 return NULL; ··· 686 699 struct v3d_job *job = to_v3d_job(sched_job); 687 700 struct v3d_dev *v3d = job->v3d; 688 701 689 - v3d_job_start_stats(job, V3D_CACHE_CLEAN); 702 + v3d_job_start_stats(job); 690 703 691 704 v3d_clean_caches(v3d); 692 705 693 - v3d_job_update_stats(job, V3D_CACHE_CLEAN); 706 + v3d_job_update_stats(job); 694 707 695 708 /* Synchronous operation, so no fence to wait on. */ 696 709 return NULL;
+6
drivers/gpu/drm/v3d/v3d_submit.c
··· 103 103 if (job->perfmon) 104 104 v3d_perfmon_put(job->perfmon); 105 105 106 + v3d_stats_put(job->client_stats); 107 + v3d_stats_put(job->global_stats); 108 + 106 109 kfree(job); 107 110 } 108 111 ··· 205 202 } 206 203 207 204 kref_init(&job->refcount); 205 + 206 + job->client_stats = v3d_stats_get(v3d_priv->stats[queue]); 207 + job->global_stats = v3d_stats_get(v3d->queue[queue].stats); 208 208 209 209 return 0; 210 210