mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Philipp Stanner <phasta@mailbox.org>
To: "Christian König" <christian.koenig@amd.com>,
	phasta@kernel.org, "Sumit Semwal" <sumit.semwal@linaro.org>,
	"Jani Nikula" <jani.nikula@linux.intel.com>,
	"Joonas Lahtinen" <joonas.lahtinen@linux.intel.com>,
	"Rodrigo Vivi" <rodrigo.vivi@intel.com>,
	"Tvrtko Ursulin" <tursulin@ursulin.net>,
	"David Airlie" <airlied@gmail.com>,
	"Simona Vetter" <simona@ffwll.ch>,
	"Steven Rostedt" <rostedt@goodmis.org>,
	"Masami Hiramatsu" <mhiramat@kernel.org>,
	"Mathieu Desnoyers" <mathieu.desnoyers@efficios.com>,
	"Miguel Ojeda" <ojeda@kernel.org>,
	"Boqun Feng" <boqun@kernel.org>, "Gary Guo" <gary@garyguo.net>,
	"Björn Roy Baron" <bjorn3_gh@protonmail.com>,
	"Benno Lossin" <lossin@kernel.org>,
	"Andreas Hindborg" <a.hindborg@kernel.org>,
	"Alice Ryhl" <aliceryhl@google.com>,
	"Trevor Gross" <tmgross@umich.edu>,
	"Danilo Krummrich" <dakr@kernel.org>,
	"Daniel Almeida" <daniel.almeida@collabora.com>,
	"Tamir Duberstein" <tamird@kernel.org>,
	"Alexandre Courbot" <acourbot@nvidia.com>,
	"Onur Özkan" <work@onurozkan.dev>,
	"Boris Brezillon" <boris.brezillon@collabora.com>,
	"Alex Deucher" <alexdeucher@gmail.com>
Cc: linux-media@vger.kernel.org, dri-devel@lists.freedesktop.org,
	 linux-kernel@vger.kernel.org, intel-gfx@lists.freedesktop.org,
	 linux-trace-kernel@vger.kernel.org,
	rust-for-linux@vger.kernel.org
Subject: Re: [RFC PATCH v2 0/3] Solve dma_fence's problems by locking
Date: Wed, 21 Oct 2026 14:49:34 +0200	[thread overview]
Message-ID: <320b6e7c75da6f05c015e89df0e2c7d11f20d70a.camel@mailbox.org> (raw)
In-Reply-To: <d13d1a6e-bba2-4275-984b-145e0252eb0f@amd.com>

On Wed, 2026-10-21 at 13:53 +0200, Christian König wrote:
> On 10/20/26 17:36, Philipp Stanner wrote:
> ...
> > > > > First of all that prevents concurrent execution of the callbacks
> > > > > which for a lot of use cases is a must have.
> > > > 
> > > > Currently only set_deadline() can execute in parallel.
> > > 
> > > Especially the is_signaling() callback is executed in parallel by tons of use cases.
> > 
> > ops->signaled() you mean.
> > 
> > Anyways, only one will succeed at having the fence marked as signaled
> > anyways, and then all other callers of dma_fence_is_signaled() will be
> > guarded by the fastpath bit-check (which btw is also broken; but we
> > want to address that in a different patch. For now my series proposes
> > keeping the fastpath).
> 
> What should be broken here? As far as I know the signaling path works perfectly fine.
> 
> What we have problems with is the lifetime of things.

The signaled bit is set under lock-protection, fully ordered. Reading
is just racing. See my other patch series, I linked two bugs that could
have been avoided if it were ordered.

Anyways, I was just answering your point. These functions' parallelism
is unchanged.


> > > > 

[…]

> > 
> > Nope, I want to protect shared data, which is the signaled-state. Which
> > is currently a race-condition worked around with RCU (and sometimes
> > with manually doing the right thing (locking!)) [1], stemming from the
> > fact that the fence's spinlock is not used consistently.
> 
> The fence spinlock is consistently used for protecting the fence
> signaling, in other words it always happens with the spinlock held,
> same for adding callbacks.
> 
> The only thing which happens without the spinlock held is the fast
> path checking of the signaled and enable_signaling bits and as far as
> I can see that is ok as well.

No, it isn't. It makes the API fragile.

	commit c8a5d5ea3ba6 ("nouveau: fix client work fence deletion race")
	commit 7c703a7d3f2b ("drm/amdgpu: Fix one use-after-free of VM")

There are certainly more related bugs around.

Also think of the various ordering issues between signaled-bit and ops
pointer that you and I observed.

> The problem here is not about the state of the fence, but if the
> callbacks are still executed or not. And that is not a good task for
> a lock, instead what is usually used for that is a barrier and that
> is exactly what RCU provides.

Locks are for mutual exclusion. Which is what you want here: you want
to exclude someone from signaling the fence while you are working on
it.

Tell me one thing:
If locking is the wrong approach, then how come it was added to
literally all callbacks except for set_deadline()? Seems to me that it
must have solved some issues.


> 
> > > > > Then as I pointed out before the second problem is that this again
> > > > > makes the existing lock inversion between the signaling by polling
> > > > > and signaling by interrupts even worse than it already is.
> > > > 
> > > > We asked for examples in our last discussions, and the only one ever
> > > > presented was the list-access requiring the fctx-lock in
> > > > nouveau_fence_no_signaling(). Nouveau is often not a good example.
> > > > 
> > > > Can you provide examples in the kernel where deadlock would occur?
> > > 
> > > Just exercise the simple example of a driver supporting both pull and interrupt:
> > > 
> > > Interrupt: Handler takes lock protecting a linked list, finds fence
> > > and signals it.
> > > 
> > > Polling: is_signaled is called with fence lock held, can't take list
> > > lock and so needs to work around that somehow.
> > 
> > signaled() neither needs a list lock nor any other lock.
> 
> I don't think we should decide that inside the framework, this is up
> to the implementation of the dma_fence backend.
> 
> By taking the lock for the callbacks we just move the complexity of
> handling from the framework into the dma_fence_ops implementations,
> and that is something I would *really* like to avoid.

Of course the framework needs to specify exactly what the callbacks are
about and what the driver should do in them. That's btw why many expect
Rust to result in often better driver design, because by the type
system you can define how your API can and cannot be used.

> > It needs to read a sequence number from somewhere, so a u64. And then
> > it returns true or false to the fence_backend.
> > 
> > The u64 can easily be an atomic. Also ioremaped reads should work
> > locklessly.
> > 
> > No need for any lock.
> 
> It is perfectly possible that you need to take whatever lock you want
> to cleanup things. E.g. spinlock for list removal, common lock with
> the interrupt handler etc....

That's like saying it's perfectly possible that someone will want to
allocate memory in a callback. Yet we say No, you cannot do that.

> 
> That's also why I said that the whole approach with the signaling and
> enable_signaling callback returning a boolean is broken.
> 
> Instead what we should do is to forward the requests to the dma_fence
> implementation. And that dma_fence implementation calls
> dma_fence_signaled() as necessary.

dma_fence_signal() you mean?

I don't get your point. What you wish to happen is already the case:

dma_fence_is_signaled(struct dma_fence *fence)
{
	const struct dma_fence_ops *ops;

	if (dma_fence_test_signaled_flag(fence))
		return true;

	rcu_read_lock();
	ops = rcu_dereference(fence->ops);
	if (ops && ops->signaled && ops->signaled(fence)) {
		rcu_read_unlock();
		dma_fence_signal(fence);



> > > 
> > 
> > Where does such a driver-lock need to be held while operating on a
> > fence, opening the deadlock-path?
> 
> In the interrupt handler.

I don't see that either. In the interrupt you will want to do:

driver_lock();
seqno = get_seqno();
driver_unlock();

signal_fences_up_to(seqno);

> 
> > Note that, as I pointed out many times, all callbacks are already
> > called under lock-protection. Especially enable_signaling(), and
> > is_signaled() must be lock-resistant, proven by
> > dma_fence_is_signaled_locked() existing.
> 
> Yes, but we clearly want to get away from that.
> 
> See the calling order in the interrupt signaling path is driver ->
> framework.
> 
> While in the is_signaled/enable_signaling/set_deadline path it is
> framework -> driver.
> 
> The dma_fence framework solved this issue by using a shared external
> driver provided lock, and that lock is then taken before calling into
> the backend operations. But we want to get away from that and use an
> inline lock in each dma_fence.
> 
> So the only two possibilities I can see is to either call the backend
> without holding locks or force the backend operations to use a
> lockless approach for their internal handling.

Right now, we do both: call callbacks with a lock *and* force all API
users to do the RCU dance.

So we have the worst of both worlds.

> 
> > Regardless, what I propose would only make a potential difference for
> > *new* users, with inline-lock, who can then cleanly design to avoid
> > locking problems.
> 
> Yeah, but I'm desperately trying to avoid the complexity of using a
> lockless approach in the driver implementation.
> 
> Just take a look at amdgpu_fence.c and how complex the RCU handling
> there becomes because of this issue here.

AFAICS amdgpu only uses ops->enable_signaling(), and there it does
exactly what I would have expected: register a timer who will see the
fence gets signaled.

As I said, no reason to do list accesses like nouveau. That's just the
driver being misdesigned.

Interestingly btw amdgpu's ops->release() does a call_rcu() to free the
fence.

You do agree with me that our API being usable like this:

dma_fence_signal(f, err);
dma_fence_put(f);

would be robust and desirable, don't you?

> 

[…]

> 
> And I still think that this is the simpler and especially more defensive approach.
> 
> The dma_fence framework should not leak it's internal lock anywhere externally and that includes calls into the backend operations.
> 

Calling a callback while holding a lock is not leaking the lock. It's
sometimes necessary. All fence callbacks are being called under lock
protection, for the same reason as I propose here: prevent the fence's
state from changing while they execute.


P.

      reply	other threads:[~2026-10-21 12:49 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-20 10:00 Philipp Stanner
2026-10-20 10:00 ` [RFC PATCH v2 1/3] dma-fence: Remove RCU protection for fence->ops Philipp Stanner
2026-10-20 10:00 ` [RFC PATCH v2 2/3] dma-fence: use lock to protect against module-unload Philipp Stanner
2026-10-20 10:00 ` [RFC PATCH v2 3/3] dma-fence: Support unload for ops->get_XXX_name() Philipp Stanner
2026-10-20 12:02 ` [RFC PATCH v2 0/3] Solve dma_fence's problems by locking Christian König
2026-10-20 14:41   ` Philipp Stanner
2026-10-20 15:07     ` Christian König
2026-10-20 15:36       ` Philipp Stanner
2026-10-21 11:53         ` Christian König
2026-10-21 12:49           ` Philipp Stanner [this message]

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=320b6e7c75da6f05c015e89df0e2c7d11f20d70a.camel@mailbox.org \
    --to=phasta@mailbox.org \
    --cc=a.hindborg@kernel.org \
    --cc=acourbot@nvidia.com \
    --cc=airlied@gmail.com \
    --cc=alexdeucher@gmail.com \
    --cc=aliceryhl@google.com \
    --cc=bjorn3_gh@protonmail.com \
    --cc=boqun@kernel.org \
    --cc=boris.brezillon@collabora.com \
    --cc=christian.koenig@amd.com \
    --cc=dakr@kernel.org \
    --cc=daniel.almeida@collabora.com \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=gary@garyguo.net \
    --cc=intel-gfx@lists.freedesktop.org \
    --cc=jani.nikula@linux.intel.com \
    --cc=joonas.lahtinen@linux.intel.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-media@vger.kernel.org \
    --cc=linux-trace-kernel@vger.kernel.org \
    --cc=lossin@kernel.org \
    --cc=mathieu.desnoyers@efficios.com \
    --cc=mhiramat@kernel.org \
    --cc=ojeda@kernel.org \
    --cc=phasta@kernel.org \
    --cc=rodrigo.vivi@intel.com \
    --cc=rostedt@goodmis.org \
    --cc=rust-for-linux@vger.kernel.org \
    --cc=simona@ffwll.ch \
    --cc=sumit.semwal@linaro.org \
    --cc=tamird@kernel.org \
    --cc=tmgross@umich.edu \
    --cc=tursulin@ursulin.net \
    --cc=work@onurozkan.dev \
    /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

all inboxes | Powered by JetHome®