diff --git a/drivers/gpu/drm/v3d/v3d_drv.c b/drivers/gpu/drm/v3d/v3d_drv.c
index d7ff1f5fa481..4a5d3ab1281b 100644
--- a/drivers/gpu/drm/v3d/v3d_drv.c
+++ b/drivers/gpu/drm/v3d/v3d_drv.c
@@ -106,6 +106,8 @@ static int v3d_get_param_ioctl(struct drm_device *dev, void *data,
 static int
 v3d_open(struct drm_device *dev, struct drm_file *file)
 {
+	static struct lock_class_key v3d_stats_gpu_lock_class;
+	static struct lock_class_key v3d_stats_cpu_lock_class;
 	struct v3d_dev *v3d = to_v3d_dev(dev);
 	struct v3d_file_priv *v3d_priv;
 	struct drm_gpu_scheduler *sched;
@@ -118,13 +120,25 @@ v3d_open(struct drm_device *dev, struct drm_file *file)
 	v3d_priv->v3d = v3d;
 
 	for (i = 0; i < V3D_MAX_QUEUES; i++) {
+		struct lock_class_key *key;
+		char *name;
+
 		sched = &v3d->queue[i].sched;
 		drm_sched_entity_init(&v3d_priv->sched_entity[i],
 				      DRM_SCHED_PRIORITY_NORMAL, &sched,
 				      1, NULL);
 
 		memset(&v3d_priv->stats[i], 0, sizeof(v3d_priv->stats[i]));
-		seqcount_init(&v3d_priv->stats[i].lock);
+
+		if (i == V3D_CACHE_CLEAN || i == V3D_CPU) {
+			key = &v3d_stats_cpu_lock_class;
+			name = "v3d_client_stats_cpu_lock";
+		} else {
+			key = &v3d_stats_gpu_lock_class;
+			name = "v3d_client_stats_gpu_lock";
+		}
+
+		__seqcount_init(&v3d_priv->stats[i].lock, name, key);
 	}
 
 	v3d_perfmon_open_file(v3d_priv);
diff --git a/drivers/gpu/drm/v3d/v3d_gem.c b/drivers/gpu/drm/v3d/v3d_gem.c
index da8faf3b9011..3567a80e603d 100644
--- a/drivers/gpu/drm/v3d/v3d_gem.c
+++ b/drivers/gpu/drm/v3d/v3d_gem.c
@@ -242,16 +242,29 @@ v3d_invalidate_caches(struct v3d_dev *v3d)
 int
 v3d_gem_init(struct drm_device *dev)
 {
+	static struct lock_class_key v3d_stats_gpu_lock_class;
+	static struct lock_class_key v3d_stats_cpu_lock_class;
 	struct v3d_dev *v3d = to_v3d_dev(dev);
 	u32 pt_size = 4096 * 1024;
 	int ret, i;
 
 	for (i = 0; i < V3D_MAX_QUEUES; i++) {
 		struct v3d_queue_state *queue = &v3d->queue[i];
+		struct lock_class_key *key;
+		char *name;
 
 		queue->fence_context = dma_fence_context_alloc(1);
 		memset(&queue->stats, 0, sizeof(queue->stats));
-		seqcount_init(&queue->stats.lock);
+
+		if (i == V3D_CACHE_CLEAN || i == V3D_CPU) {
+			key = &v3d_stats_cpu_lock_class;
+			name = "v3d_stats_cpu_lock";
+		} else {
+			key = &v3d_stats_gpu_lock_class;
+			name = "v3d_stats_gpu_lock";
+		}
+
+		__seqcount_init(&queue->stats.lock, name, key);
 	}
 
 	spin_lock_init(&v3d->mm_lock);
diff --git a/drivers/gpu/drm/v3d/v3d_sched.c b/drivers/gpu/drm/v3d/v3d_sched.c
index cc2e5a89467b..b2540e20d30c 100644
--- a/drivers/gpu/drm/v3d/v3d_sched.c
+++ b/drivers/gpu/drm/v3d/v3d_sched.c
@@ -149,6 +149,27 @@ v3d_job_start_stats(struct v3d_job *job, enum v3d_queue queue)
 	preempt_enable();
 }
 
+/*
+ * We only need to disable local interrupts to appease lockdep who otherwise
+ * would think v3d_job_start_stats vs v3d_stats_update has an unsafe in-irq vs
+ * no-irq-off usage problem. This is a false positive becuase all the locks are
+ * per queue and stats type, and all jobs are completely one at a time
+ * serialised.
+ */
+static void
+v3d_job_start_stats_irqsave(struct v3d_job *job, enum v3d_queue queue)
+{
+#ifdef CONFIG_LOCKDEP
+	unsigned long flags;
+
+	local_irq_save(flags);
+#endif
+	v3d_job_start_stats(job, queue);
+#ifdef CONFIG_LOCKDEP
+	local_irq_restore(flags);
+#endif
+}
+
 static void
 v3d_stats_update(struct v3d_stats *stats, u64 now)
 {
@@ -194,6 +215,7 @@ static struct dma_fence *v3d_bin_job_run(struct drm_sched_job *sched_job)
 	 * reuse the overflow attached to a previous job.
 	 */
 	V3D_CORE_WRITE(0, V3D_PTB_BPOS, 0);
+	v3d_job_start_stats(&job->base, V3D_BIN); /* Piggy-back on existing irq-off section. */
 	spin_unlock_irqrestore(&v3d->job_lock, irqflags);
 
 	v3d_invalidate_caches(v3d);
@@ -209,7 +231,6 @@ static struct dma_fence *v3d_bin_job_run(struct drm_sched_job *sched_job)
 	trace_v3d_submit_cl(dev, false, to_v3d_fence(fence)->seqno,
 			    job->start, job->end);
 
-	v3d_job_start_stats(&job->base, V3D_BIN);
 	v3d_switch_perfmon(v3d, &job->base);
 
 	/* Set the current and end address of the control list.
@@ -261,7 +282,7 @@ static struct dma_fence *v3d_render_job_run(struct drm_sched_job *sched_job)
 	trace_v3d_submit_cl(dev, true, to_v3d_fence(fence)->seqno,
 			    job->start, job->end);
 
-	v3d_job_start_stats(&job->base, V3D_RENDER);
+	v3d_job_start_stats_irqsave(&job->base, V3D_RENDER);
 	v3d_switch_perfmon(v3d, &job->base);
 
 	/* XXX: Set the QCFG */
@@ -294,7 +315,7 @@ v3d_tfu_job_run(struct drm_sched_job *sched_job)
 
 	trace_v3d_submit_tfu(dev, to_v3d_fence(fence)->seqno);
 
-	v3d_job_start_stats(&job->base, V3D_TFU);
+	v3d_job_start_stats_irqsave(&job->base, V3D_TFU);
 
 	V3D_WRITE(V3D_TFU_IIA(v3d->ver), job->args.iia);
 	V3D_WRITE(V3D_TFU_IIS(v3d->ver), job->args.iis);
@@ -339,7 +360,7 @@ v3d_csd_job_run(struct drm_sched_job *sched_job)
 
 	trace_v3d_submit_csd(dev, to_v3d_fence(fence)->seqno);
 
-	v3d_job_start_stats(&job->base, V3D_CSD);
+	v3d_job_start_stats_irqsave(&job->base, V3D_CSD);
 	v3d_switch_perfmon(v3d, &job->base);
 
 	csd_cfg0_reg = V3D_CSD_QUEUED_CFG0(v3d->ver);
