On Tue, 10 Feb 2026 10:15:04 +0000
Alice Ryhl <[email protected]> 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?
>
> // enqueue the job
> wq.enqueue(item, wq);
>
> // The signature of DmaFenceWorkItem::run() promises to arrange
> // for it to be signalled.
> self.i_promise_it_will_be_signalled()
> }
> }