From: Nicolas Frattaroli <nicolas.frattaroli@collabora.com>
To: Boris Brezillon <boris.brezillon@collabora.com>
Cc: Ingo Molnar <mingo@redhat.com>,
Peter Zijlstra <peterz@infradead.org>,
Juri Lelli <juri.lelli@redhat.com>,
Vincent Guittot <vincent.guittot@linaro.org>,
Dietmar Eggemann <dietmar.eggemann@arm.com>,
Steven Rostedt <rostedt@goodmis.org>,
Ben Segall <bsegall@google.com>, Mel Gorman <mgorman@suse.de>,
Valentin Schneider <vschneid@redhat.com>,
K Prateek Nayak <kprateek.nayak@amd.com>,
Steven Price <steven.price@arm.com>,
Liviu Dudau <liviu.dudau@arm.com>,
Maarten Lankhorst <maarten.lankhorst@linux.intel.com>,
Maxime Ripard <mripard@kernel.org>,
Thomas Zimmermann <tzimmermann@suse.de>,
David Airlie <airlied@gmail.com>, Simona Vetter <simona@ffwll.ch>,
Grant Likely <grant.likely@linaro.org>,
Heiko Stuebner <heiko@sntech.de>,
linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org,
kernel@collabora.com
Subject: Re: [PATCH v2 2/3] drm/panthor: Revisit reqs_lock handling in flush/reset paths
Date: Mon, 03 Aug 2026 15:13:25 +0200 [thread overview]
Message-ID: <fiUy-cD0Q9OOQiaEoz9UeA@collabora.com> (raw)
In-Reply-To: <20260803105324.478ed594@fedora1.home>
On Monday, 3 August 2026 10:53:24 Central European Summer Time Boris Brezillon wrote:
> Hello Nicolas,
>
> On Thu, 30 Jul 2026 13:45:15 +0200
> Nicolas Frattaroli <nicolas.frattaroli@collabora.com> wrote:
>
> > panthor_gpu_flush_caches() and panthor_gpu_soft_reset() would read (and
> > even reset) the contents of the pending_reqs register outside of holding
> > the reqs_lock.
>
> Can you elaborate a bit on the race being fixed here? If pending_reqs bits
> are truly cleared before the wake_up_all() call (which would require a
> WRITE_ONCE() to be enforced, admittedly), there's no risk for the
> wait_event() call to do a test before the bits have been updated,
> and this holds even if the test is done without the lock held.
>
> The other race I could think of is two threads calling
> panthor_gpu_flush_caches() concurrently, and the second one stealing
> the FLUSH_COMPLETED event the first thread waits on and re-issuing a
> second flush on top, thus delaying the completion for the first thread.
> But that should be covered by the cache_flush_lock.
panthor_gpu_flush_caches() is not the only thing that sets/gets
pending_reqs. Notably, the threaded interrupt handler does, as
well as any other functionality using the same member for reqs
tracking (e.g. the soft reset).
Consider the following serialisation of events:
1. T1 asks to flush caches by writing GPU_CMD and setting pending_reqs
2. T1 drops reqs_lock.
3. T2 enters IRQ handler for flush complete, spins lock waiting for
reqs_lock
4. T1 sleeps at wait_event_timeout
5. T2 updates pending_reqs and wakes up the waiter in any order, since
the effects of those two can't consistently be observed as sequential
logic without the outer reqs_lock being held by the observer
6. T1 wakes up, checks pending_reqs, but since pending_reqs is checked
without holding any lock, so we implictly depend on the synchronisation
point that is the waitqueue's lock rather than the reqs_lock spinlock,
which says nothing about whether the pending_reqs change materialised
on T1's side yet as far as I can tell?
7. T1 sees that pending_reqs & GPU_IRQ_CLEAN_CACHES_COMPLETED is still != 0,
so goes back to sleep for some future wake-up of reqs_acked or a timeout.
I'm not 100% sure, but I think 6. means that the memory model would permit
T1 to re-use the pending_reqs it previously set, rather than the updated
one set by T2, since there's nothing stopping us from being woken up before
the pending_reqs change has made itself known to observers not serialising
with the reqs_lock being released by T2 in panthor_gpu_irq_handler after.
If you check lock_stat before the change, you see that the reqs_lock is
actually never contended. This isn't a good sign because it means
whatever situation it exists to protect against never occurs, so either
the lock is pointless or the lock is non-functional.
> > Additionally, when it did hold the lock, it did so with
> > the irqsave/irqrestore variants, even though the spinlock was never
> > acquired in an atomic context, just the threaded handler.
> >
> > Use the new wait_event_lock_timeout() macro to check pending_reqs under
> > the lock, and only do so without disabling interrupts.
> >
> > Fixes: 5cd894e258c4 ("drm/panthor: Add the GPU logical block")
> > Signed-off-by: Nicolas Frattaroli <nicolas.frattaroli@collabora.com>
> > ---
> > drivers/gpu/drm/panthor/panthor_gpu.c | 25 +++++++++++--------------
> > 1 file changed, 11 insertions(+), 14 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/panthor/panthor_gpu.c b/drivers/gpu/drm/panthor/panthor_gpu.c
> > index c013d6bf9a59..f015bde80abf 100644
> > --- a/drivers/gpu/drm/panthor/panthor_gpu.c
> > +++ b/drivers/gpu/drm/panthor/panthor_gpu.c
> > @@ -330,35 +330,34 @@ int panthor_gpu_flush_caches(struct panthor_device *ptdev,
> > u32 l2, u32 lsc, u32 other)
> > {
> > struct panthor_gpu *gpu = ptdev->gpu;
> > - unsigned long flags;
> > int ret = 0;
> >
> > /* Serialize cache flush operations. */
> > guard(mutex)(&ptdev->gpu->cache_flush_lock);
> >
> > - spin_lock_irqsave(&ptdev->gpu->reqs_lock, flags);
> > + spin_lock(&ptdev->gpu->reqs_lock);
>
> Can we make the _irq{save,restore}-drop its own patch?
I'm not sure it's fine to drop the IRQ disabling without fixing the read of
pending_reqs outside its lock.
>
> > if (!(ptdev->gpu->pending_reqs & GPU_IRQ_CLEAN_CACHES_COMPLETED)) {
> > ptdev->gpu->pending_reqs |= GPU_IRQ_CLEAN_CACHES_COMPLETED;
> > gpu_write(gpu->iomem, GPU_CMD, GPU_FLUSH_CACHES(l2, lsc, other));
> > } else {
> > ret = -EIO;
> > }
> > - spin_unlock_irqrestore(&ptdev->gpu->reqs_lock, flags);
> >
> > - if (ret)
> > + if (ret) {
> > + spin_unlock(&ptdev->gpu->reqs_lock);
> > return ret;
> > + }
> >
> > - if (!wait_event_timeout(ptdev->gpu->reqs_acked,
> > + if (!wait_event_lock_timeout(ptdev->gpu->reqs_acked,
> > !(ptdev->gpu->pending_reqs & GPU_IRQ_CLEAN_CACHES_COMPLETED),
>
> Assuming we really need to do the test with the lock held, could we add
> a patch at the beginning of the series that fixes the race without depending
> on the new wait macro, so that we have a version that can easily be backported?
It's either backporting the prerequisite new macro or still doing this all
with IRQs disabled using the pre-existing wait_event_lock_irq_timeout macro,
and the IRQ disabled thing is what caused problems.
>
> > - msecs_to_jiffies(100))) {
> > - spin_lock_irqsave(&ptdev->gpu->reqs_lock, flags);
> > + ptdev->gpu->reqs_lock, msecs_to_jiffies(100))) {
> > if ((ptdev->gpu->pending_reqs & GPU_IRQ_CLEAN_CACHES_COMPLETED) != 0 &&
> > !(gpu_read(gpu->irq.iomem, INT_RAWSTAT) & GPU_IRQ_CLEAN_CACHES_COMPLETED))
> > ret = -ETIMEDOUT;
> > else
> > ptdev->gpu->pending_reqs &= ~GPU_IRQ_CLEAN_CACHES_COMPLETED;
> > - spin_unlock_irqrestore(&ptdev->gpu->reqs_lock, flags);
> > }
> > + spin_unlock(&ptdev->gpu->reqs_lock);
>
> I think a scoped_guard() could make things a bit cleaner, and given you
> already turn the regular lock/unlock sequence into a guard in
> panthor_gpu_soft_reset(), I'd do that here as well.
That would add an additional layer of indentation, which I'm wary of.
We can't use a non-scoped guard due to the reset at the end of the
function.
I'll see if I can reshuffle the code to make it not as ugly to use a
scoped_guard here. Will also slightly change the semantics of the
_end tracepoint, since it'll then fire it before dropping the lock,
but that's not much of a change.
Kind regards,
Nicolas Frattaroli
>
> Regards,
>
> Boris
>
> [1]https://elixir.bootlin.com/linux/v7.2-rc5/source/drivers/gpu/drm/panthor/panthor_gpu.c#L114
>
next prev parent reply other threads:[~2026-08-03 13:13 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-30 11:45 [PATCH v2 0/3] Rework panthor's cache flush and soft reset locking Nicolas Frattaroli
2026-07-30 11:45 ` [PATCH v2 1/3] wait: Introduce non-irq variants of wait_event_lock_timeout Nicolas Frattaroli
2026-07-30 11:53 ` sashiko-bot
2026-07-30 15:08 ` Liviu Dudau
2026-07-31 8:00 ` Steven Price
2026-07-30 11:45 ` [PATCH v2 2/3] drm/panthor: Revisit reqs_lock handling in flush/reset paths Nicolas Frattaroli
2026-07-30 12:02 ` sashiko-bot
2026-07-30 14:56 ` Liviu Dudau
2026-07-31 8:01 ` Steven Price
2026-08-03 8:53 ` Boris Brezillon
2026-08-03 13:13 ` Nicolas Frattaroli [this message]
2026-08-03 13:20 ` Nicolas Frattaroli
2026-08-03 15:59 ` Boris Brezillon
2026-07-30 11:45 ` [PATCH v2 3/3] drm/panthor: Add tracepoints for cache flushing Nicolas Frattaroli
2026-07-30 13:46 ` Steven Rostedt
2026-07-30 15:14 ` Liviu Dudau
2026-07-31 8:03 ` Steven Price
2026-08-03 9:03 ` Boris Brezillon
2026-08-04 14:44 ` Nicolas Frattaroli
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=fiUy-cD0Q9OOQiaEoz9UeA@collabora.com \
--to=nicolas.frattaroli@collabora.com \
--cc=airlied@gmail.com \
--cc=boris.brezillon@collabora.com \
--cc=bsegall@google.com \
--cc=dietmar.eggemann@arm.com \
--cc=dri-devel@lists.freedesktop.org \
--cc=grant.likely@linaro.org \
--cc=heiko@sntech.de \
--cc=juri.lelli@redhat.com \
--cc=kernel@collabora.com \
--cc=kprateek.nayak@amd.com \
--cc=linux-kernel@vger.kernel.org \
--cc=liviu.dudau@arm.com \
--cc=maarten.lankhorst@linux.intel.com \
--cc=mgorman@suse.de \
--cc=mingo@redhat.com \
--cc=mripard@kernel.org \
--cc=peterz@infradead.org \
--cc=rostedt@goodmis.org \
--cc=simona@ffwll.ch \
--cc=steven.price@arm.com \
--cc=tzimmermann@suse.de \
--cc=vincent.guittot@linaro.org \
--cc=vschneid@redhat.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.