From: Maíra Canal <mcanal@igalia.com>
To: Melissa Wen <mwen@igalia.com>,
Tvrtko Ursulin <tvrtko.ursulin@igalia.com>,
Maxime Ripard <mripard@kernel.org>
Cc: kernel-dev@igalia.com, dri-devel@lists.freedesktop.org,
Maíra Canal <mcanal@igalia.com>,
Iago Toral Quiroga <itoral@igalia.com>
Subject: [PATCH v3 2/6] drm/v3d: Use raw seqcount helpers instead of fighting with lockdep
Date: Fri, 06 Mar 2026 08:30:34 -0300 [thread overview]
Message-ID: <20260306-v3d-reset-locking-improv-v3-2-49864fe00692@igalia.com> (raw)
In-Reply-To: <20260306-v3d-reset-locking-improv-v3-0-49864fe00692@igalia.com>
From: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
The `v3d_stats` sequence counter uses regular seqcount helpers, which
carry lockdep annotations that expect a consistent IRQ context between
all writers. However, lockdep is unable to detect that v3d's readers
are never in IRQ or softirq context, and that for CPU job queues, even
the write side never is. This led to false positive that were previously
worked around by conditionally disabling local IRQs under
IS_ENABLED(CONFIG_LOCKDEP).
Switch to the raw seqcount helpers which skip lockdep tracking entirely.
This is safe because jobs are fully serialized per queue: the next job
can only be queued after the previous one has been signaled, so there is
no scope for the start and update paths to race on the same seqcount.
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
Co-developed-by: Maíra Canal <mcanal@igalia.com>
Signed-off-by: Maíra Canal <mcanal@igalia.com>
Reviewed-by: Iago Toral Quiroga <itoral@igalia.com>
---
drivers/gpu/drm/v3d/v3d_drv.c | 2 +-
drivers/gpu/drm/v3d/v3d_drv.h | 5 ++++
drivers/gpu/drm/v3d/v3d_sched.c | 54 ++++++++---------------------------------
3 files changed, 16 insertions(+), 45 deletions(-)
diff --git a/drivers/gpu/drm/v3d/v3d_drv.c b/drivers/gpu/drm/v3d/v3d_drv.c
index 86e05fcf6cf65638c4bf97ab3511ccac40f21e2f..6086c04629adbe8611b1f7297879feacec454b43 100644
--- a/drivers/gpu/drm/v3d/v3d_drv.c
+++ b/drivers/gpu/drm/v3d/v3d_drv.c
@@ -194,7 +194,7 @@ void v3d_get_stats(const struct v3d_stats *stats, u64 timestamp,
unsigned int seq;
do {
- seq = read_seqcount_begin(&stats->lock);
+ seq = raw_read_seqcount_begin(&stats->lock);
*active_runtime = stats->enabled_ns;
if (stats->start_ns)
*active_runtime += timestamp - stats->start_ns;
diff --git a/drivers/gpu/drm/v3d/v3d_drv.h b/drivers/gpu/drm/v3d/v3d_drv.h
index 314213c2671003862c486a1a7237af5480afa9e4..2e5520015e08c47fef4bfbf185eda15027992032 100644
--- a/drivers/gpu/drm/v3d/v3d_drv.h
+++ b/drivers/gpu/drm/v3d/v3d_drv.h
@@ -46,6 +46,11 @@ struct v3d_stats {
* This seqcount is used to protect the access to the GPU stats
* variables. It must be used as, while we are reading the stats,
* IRQs can happen and the stats can be updated.
+ *
+ * However, we use the raw seqcount helpers to interact with this lock
+ * to avoid false positives from lockdep, which is unable to detect that
+ * our readers are never from irq or softirq context, and that, for CPU
+ * job queues, even the write side never is.
*/
seqcount_t lock;
};
diff --git a/drivers/gpu/drm/v3d/v3d_sched.c b/drivers/gpu/drm/v3d/v3d_sched.c
index 6dc871fc9a62303da4fbc62b612c3a797fe762de..18265721c1d32158fa6f7e68fa3e70a77d265b9d 100644
--- a/drivers/gpu/drm/v3d/v3d_sched.c
+++ b/drivers/gpu/drm/v3d/v3d_sched.c
@@ -144,54 +144,28 @@ v3d_job_start_stats(struct v3d_job *job, enum v3d_queue queue)
struct v3d_stats *global_stats = &v3d->queue[queue].stats;
struct v3d_stats *local_stats = &file->stats[queue];
u64 now = local_clock();
- unsigned long flags;
- /*
- * 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
- * because all the locks are per queue and stats type, and all jobs are
- * completely one at a time serialised. More specifically:
- *
- * 1. Locks for GPU queues are updated from interrupt handlers under a
- * spin lock and started here with preemption disabled.
- *
- * 2. Locks for CPU queues are updated from the worker with preemption
- * disabled and equally started here with preemption disabled.
- *
- * Therefore both are consistent.
- *
- * 3. Because next job can only be queued after the previous one has
- * been signaled, and locks are per queue, there is also no scope for
- * the start part to race with the update part.
- */
- if (IS_ENABLED(CONFIG_LOCKDEP))
- local_irq_save(flags);
- else
- preempt_disable();
+ preempt_disable();
- write_seqcount_begin(&local_stats->lock);
+ raw_write_seqcount_begin(&local_stats->lock);
local_stats->start_ns = now;
- write_seqcount_end(&local_stats->lock);
+ raw_write_seqcount_end(&local_stats->lock);
- write_seqcount_begin(&global_stats->lock);
+ raw_write_seqcount_begin(&global_stats->lock);
global_stats->start_ns = now;
- write_seqcount_end(&global_stats->lock);
+ raw_write_seqcount_end(&global_stats->lock);
- if (IS_ENABLED(CONFIG_LOCKDEP))
- local_irq_restore(flags);
- else
- preempt_enable();
+ preempt_enable();
}
static void
v3d_stats_update(struct v3d_stats *stats, u64 now)
{
- write_seqcount_begin(&stats->lock);
+ raw_write_seqcount_begin(&stats->lock);
stats->enabled_ns += now - stats->start_ns;
stats->jobs_completed++;
stats->start_ns = 0;
- write_seqcount_end(&stats->lock);
+ raw_write_seqcount_end(&stats->lock);
}
void
@@ -201,13 +175,8 @@ v3d_job_update_stats(struct v3d_job *job, enum v3d_queue q)
struct v3d_queue_state *queue = &v3d->queue[q];
struct v3d_stats *global_stats = &queue->stats;
u64 now = local_clock();
- unsigned long flags;
- /* See comment in v3d_job_start_stats() */
- if (IS_ENABLED(CONFIG_LOCKDEP))
- local_irq_save(flags);
- else
- preempt_disable();
+ preempt_disable();
/* Don't update the local stats if the file context has already closed */
spin_lock(&queue->queue_lock);
@@ -217,10 +186,7 @@ v3d_job_update_stats(struct v3d_job *job, enum v3d_queue q)
v3d_stats_update(global_stats, now);
- if (IS_ENABLED(CONFIG_LOCKDEP))
- local_irq_restore(flags);
- else
- preempt_enable();
+ preempt_enable();
}
static struct dma_fence *v3d_bin_job_run(struct drm_sched_job *sched_job)
--
2.53.0
next prev parent reply other threads:[~2026-03-06 11:30 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-03-06 11:30 [PATCH v3 0/6] drm/v3d: Improve v3d_stats lifetime and locking Maíra Canal
2026-03-06 11:30 ` [PATCH v3 1/6] drm/v3d: Handle error from drm_sched_entity_init() Maíra Canal
2026-03-08 22:56 ` Claude review: " Claude Code Review Bot
2026-03-06 11:30 ` Maíra Canal [this message]
2026-03-08 22:56 ` Claude review: drm/v3d: Use raw seqcount helpers instead of fighting with lockdep Claude Code Review Bot
2026-03-06 11:30 ` [PATCH v3 3/6] drm/v3d: Refcount v3d_stats Maíra Canal
2026-03-08 22:56 ` Claude review: " Claude Code Review Bot
2026-03-06 11:30 ` [PATCH v3 4/6] drm/v3d: Hold v3d_stats references in each job Maíra Canal
2026-03-08 22:56 ` Claude review: " Claude Code Review Bot
2026-03-06 11:30 ` [PATCH v3 5/6] drm/v3d: Attach per-fd reset counters to v3d_stats Maíra Canal
2026-03-08 22:56 ` Claude review: " Claude Code Review Bot
2026-03-06 11:30 ` [PATCH v3 6/6] drm/v3d: Remove dedicated fence_lock Maíra Canal
2026-03-08 22:56 ` Claude review: " Claude Code Review Bot
2026-03-08 22:56 ` Claude review: drm/v3d: Improve v3d_stats lifetime and locking Claude Code Review Bot
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260306-v3d-reset-locking-improv-v3-2-49864fe00692@igalia.com \
--to=mcanal@igalia.com \
--cc=dri-devel@lists.freedesktop.org \
--cc=itoral@igalia.com \
--cc=kernel-dev@igalia.com \
--cc=mripard@kernel.org \
--cc=mwen@igalia.com \
--cc=tvrtko.ursulin@igalia.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox