From: "Christian König" <christian.koenig@amd.com>
To: 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 13:53:46 +0200 [thread overview]
Message-ID: <d13d1a6e-bba2-4275-984b-145e0252eb0f@amd.com> (raw)
In-Reply-To: <4a7294da65c8744ba6355730e304b5250d0ca351.camel@mailbox.org>
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.
>>> IIUC in our past discussions, your wish has been that the driver can
>>> take its own locks with free locking-order in the callbacks.
>>>
>>> Thus, the callback is invoked under lock in any case, just a few
>>> instructions earlier or later. Thus, no callback ever truly executes
>>> concurrently.
>>
>> And that is fine. Taking the look when you actually need it to
>> protect data structures is perfectly correct.
>>
>> But what you propose here is to abuse the look as a barrier, e.g. to
>> find out if something has finished or not and that is a completely
>> different story.
>
> 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.
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.
>>>> 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.
> 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 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.
>> This pattern repeats multiple times all over the different dma_fence
>> implementation. Nouveu is just the tip of the iceberg, we have cases
>> of this in amdgpu as well as i915 as well as XE.
>
> I guess my question then becomes what complicated locked tasks someone
> has to do within its callback that locks are required, locks that
> cannot be partitioned in a smart way to avoid that.
Simple cleanup tasks, like just list_del() you need to take a spinlock for so.
>
> We have 3 callbacks that are relevant and not deprecated (the name-
> functions are trivially solved by copying the data):
>
> - is_signaled() ⇒ solved, see above
> - enable_signaling()
> - set_deadline()
>
> The latter two might want to talk to their hardware, either enabling an
> interrupt or telling it to clock the frequency up (see MSM). They might
> need a driver-lock for that, fair enough.
>
> Where does such a driver-lock need to be held while operating on a
> fence, opening the deadlock-path?
In the interrupt handler.
> 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.
> 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.
Or the dma_fence_chain and dma_fence_array containers, same problem there as well.
>>> Note that I pointed out that all callbacks are already invoked with the
>>> lock taken, which proofs that it's doable.
>>
>> Again, no it isn't. The shared lock was invented exactly because
>> drivers ran into this problem.
>>
>> The common pattern is the same, implementations just dance around the
>> fact that the callbacks are called with the fence lock held by
>> delegating cleanup work and/or using lockless containers etc...
>
> I suspect more that drivers attempt to do unnecessarily many things in
> their callbacks which are not supposed to be done there.
>
>> A common component like dma_fence should never enforce users to do
>> such workarounds just to solve it's own lifetime issues.
>
> Our common component forces all users to take our locks manually and
> plaster everything with RCU. If they forget an RCU delay, outside our
> API, things explode :(
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.
Regards,
Christian.
>
>
> P.
>
>
> [1] https://elixir.bootlin.com/linux/v7.3/source/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c#L2787
>
>>
next prev parent reply other threads:[~2026-10-21 11:53 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 [this message]
2026-10-21 12:49 ` Philipp Stanner
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=d13d1a6e-bba2-4275-984b-145e0252eb0f@amd.com \
--to=christian.koenig@amd.com \
--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=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®