Re: [RFC PATCH 2/4] rust: sync: Add dma_fence abstractions
From: Alice Ryhl
Date: Tue Feb 10 2026 - 06:45:48 EST
On Tue, Feb 10, 2026 at 12:34:32PM +0100, Boris Brezillon wrote:
> On Tue, 10 Feb 2026 10:15:04 +0000
> Alice Ryhl <aliceryhl@xxxxxxxxxx> wrote:
>
> > impl MustBeSignalled<'_> {
> > /// Drivers generally should not use this one.
> > fn i_promise_it_will_be_signalled(self) -> WillBeSignalled { ... }
> >
> > /// One way to ensure the fence has been signalled is to signal it.
> > fn signal_fence(self) -> WillBeSignalled {
> > self.fence.signal();
> > self.i_promise_it_will_be_signalled()
> > }
> >
> > /// Another way to ensure the fence will be signalled is to spawn a
> > /// workqueue item that promises to signal it.
> > fn transfer_to_wq(
> > self,
> > wq: &Workqueue,
> > item: impl DmaFenceWorkItem,
> > ) -> WillBeSignalled {
> > // briefly obtain the lock class of the wq to indicate to
> > // lockdep that the signalling path "blocks" on arbitrary jobs
> > // from this wq completing
> > bindings::lock_acquire(&wq->key);
> > bindings::lock_release(&wq->key);
>
> Sorry, I'm still trying to connect the dots here. I get that the intent
> is to ensure the pseudo-lock ordering is always:
>
> -> dma_fence_lockdep_map
> -> wq->lockdep_map
>
> but how can this order be the same in the WorkItem execution path? My
> interpretation of process_one_work() makes me think we'll end up with
>
> -> wq->lockdep_map
> -> work->run()
> -> WorkItem::run()
> -> dma_fence_lockdep_map
> -> DmaFenceSignalingWorkItem::run()
> ...
>
> Am I missing something? Is there a way you can insert the
> dma_fence_lockdep_map acquisition before the wq->lockdep_map one in the
> execution path?
Conceptually, the dma_fence_lockdep_map is already taken by the time you
get to WorkItem::run() because it was taken all the way back in the
ioctl, so WorkItem::run() does not need to reacquire it.
Now, of course that does not translate cleanly to how lockdep does
things, so in lockdep we do have to re-acquire it in WorkItem::run().
You can do that by setting the trylock bit when calling lock_acquire()
on dma_fence_lockdep_map. This has the correct semantics because trylock
does not create an edge from wq->lockdep_map to dma_fence_lockdep_map.
Alice