include/linux/dma-fence.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+)
dma_fence's backend_ops functions ops->wait() and ops->release() are
problematic because they prevent fence producers from unloading.
Moreover, they can easily be implemented through simpler means more
aligned with the dma_fence contract.
Since the declared goal of dma_fence is to move towards an
implementation that supports driver-unload in all circumstances, we must
prevent more parties from implementing those callbacks.
Deprecate ops->release() and ops->wait() and document what users should
do instead.
Signed-off-by: Philipp Stanner <phasta@kernel.org>
---
include/linux/dma-fence.h | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/include/linux/dma-fence.h b/include/linux/dma-fence.h
index dd07d128adc3..59af0159cd25 100644
--- a/include/linux/dma-fence.h
+++ b/include/linux/dma-fence.h
@@ -220,6 +220,8 @@ struct dma_fence_ops {
/**
* @wait:
*
+ * DEPRECATED!
+ *
* Custom wait implementation, defaults to dma_fence_default_wait() if
* not set.
*
@@ -236,6 +238,10 @@ struct dma_fence_ops {
* Implementing this callback prevents the fence from detaching after
* signaling and so it is necessary for the module providing the
* dma_fence_ops to stay loaded as long as the dma_fence exists.
+ *
+ * Deprecated for the reason mentioned above. No new users must be
+ * implemented. Consumers of a fence can instead notify themselves by
+ * registering a callback on the fence.
*/
signed long (*wait)(struct dma_fence *fence,
bool intr, signed long timeout);
@@ -243,6 +249,8 @@ struct dma_fence_ops {
/**
* @release:
*
+ * DEPRECATED!
+ *
* Called on destruction of fence to release additional resources.
* Can be called from irq context. This callback is optional. If it is
* NULL, then dma_fence_free() is instead called as the default
@@ -254,6 +262,12 @@ struct dma_fence_ops {
*
* If the callback is implemented the memory backing the dma_fence
* object must be freed RCU safe.
+ *
+ * Deprecated because it prevents the producer of a fence from
+ * unloading. No new users must be implemented. Parties with a
+ * hypothetical need for this callback can instead simply and directly
+ * perform their custom release operations one RCU grace period after
+ * they have signaled the fence.
*/
void (*release)(struct dma_fence *fence);
base-commit: 2302669bb4b52d581cc2589b90b3af7bb3783a28
--
2.55.0
On 9/23/26 17:03, Philipp Stanner wrote:
> dma_fence's backend_ops functions ops->wait() and ops->release() are
> problematic because they prevent fence producers from unloading.
> Moreover, they can easily be implemented through simpler means more
> aligned with the dma_fence contract.
>
> Since the declared goal of dma_fence is to move towards an
> implementation that supports driver-unload in all circumstances, we must
> prevent more parties from implementing those callbacks.
>
> Deprecate ops->release() and ops->wait() and document what users should
> do instead.
>
> Signed-off-by: Philipp Stanner <phasta@kernel.org>
> ---
> include/linux/dma-fence.h | 14 ++++++++++++++
> 1 file changed, 14 insertions(+)
>
> diff --git a/include/linux/dma-fence.h b/include/linux/dma-fence.h
> index dd07d128adc3..59af0159cd25 100644
> --- a/include/linux/dma-fence.h
> +++ b/include/linux/dma-fence.h
> @@ -220,6 +220,8 @@ struct dma_fence_ops {
> /**
> * @wait:
> *
> + * DEPRECATED!
> + *
> * Custom wait implementation, defaults to dma_fence_default_wait() if
> * not set.
> *
> @@ -236,6 +238,10 @@ struct dma_fence_ops {
> * Implementing this callback prevents the fence from detaching after
> * signaling and so it is necessary for the module providing the
> * dma_fence_ops to stay loaded as long as the dma_fence exists.
> + *
> + * Deprecated for the reason mentioned above. No new users must be
> + * implemented.
> Consumers of a fence can instead notify themselves by
> + * registering a callback on the fence.
Mhm, the wait callback is transparent to consumers it's just that implementations used it for quite a number of different hacks.
I would just drop that sentence.
> */
> signed long (*wait)(struct dma_fence *fence,
> bool intr, signed long timeout);
> @@ -243,6 +249,8 @@ struct dma_fence_ops {
> /**
> * @release:
> *
> + * DEPRECATED!
> + *
> * Called on destruction of fence to release additional resources.
> * Can be called from irq context. This callback is optional. If it is
> * NULL, then dma_fence_free() is instead called as the default
> @@ -254,6 +262,12 @@ struct dma_fence_ops {
> *
> * If the callback is implemented the memory backing the dma_fence
> * object must be freed RCU safe.
> + *
> + * Deprecated because it prevents the producer of a fence from
> + * unloading. No new users must be implemented. Parties with a
> + * hypothetical need for this callback can instead simply and directly
> + * perform their custom release operations one RCU grace period after
> + * they have signaled the fence.
Yeah that is a bit problematic.
We need my patch set to explicit signal fences instead of returning true/false from callback for that so that a backend can properly implement this.
It's on my TODO list, but not the highest priority at the moment.
Regards,
Christian.
> */
> void (*release)(struct dma_fence *fence);
>
>
> base-commit: 2302669bb4b52d581cc2589b90b3af7bb3783a28
On Wed, 2026-09-23 at 17:13 +0200, Christian König wrote:
> On 9/23/26 17:03, Philipp Stanner wrote:
> >
[…]
>
> > Consumers of a fence can instead notify themselves by
> > + * registering a callback on the fence.
>
> Mhm, the wait callback is transparent to consumers it's just that implementations used it for quite a number of different hacks.
Right…
but doesn't the question then become why dma_fence_wait_timeout() even
exists? IOW, shall we deprecate it, too?
It seems to be a reimplementation of waitqueues. The driver could get
this functionality by using a waitqueue whose event gets triggered by a
fence callback.
dma_fence_default_wait() interacts directly with the task state with
__XX_task() functions which looks very.. deep to me :)
>
> I would just drop that sentence.
>
> > */
> > signed long (*wait)(struct dma_fence *fence,
> > bool intr, signed long timeout);
> > @@ -243,6 +249,8 @@ struct dma_fence_ops {
> > /**
> > * @release:
> > *
> > + * DEPRECATED!
> > + *
> > * Called on destruction of fence to release additional resources.
> > * Can be called from irq context. This callback is optional. If it is
> > * NULL, then dma_fence_free() is instead called as the default
> > @@ -254,6 +262,12 @@ struct dma_fence_ops {
> > *
> > * If the callback is implemented the memory backing the dma_fence
> > * object must be freed RCU safe.
> > + *
> > + * Deprecated because it prevents the producer of a fence from
> > + * unloading. No new users must be implemented. Parties with a
> > + * hypothetical need for this callback can instead simply and directly
> > + * perform their custom release operations one RCU grace period after
> > + * they have signaled the fence.
>
> Yeah that is a bit problematic.
>
> We need my patch set to explicit signal fences instead of returning true/false from callback for that so that a backend can properly implement this.
Well, what I'm trying to say in this docu is that the driver can kick
off custom operations that shall be performed once everyone is "done"
with the fence after signaling it. Any driver data that might still be
around cannot be accessed by fence consumers after signaling anymore.
So the driver could trigger cleanup work after a graceperiod, as long
as it does not involve kfree()-ing the fence itself.
P.
On 9/23/26 17:27, Philipp Stanner wrote:
> On Wed, 2026-09-23 at 17:13 +0200, Christian König wrote:
>> On 9/23/26 17:03, Philipp Stanner wrote:
>>>
>
> […]
>
>>
>>> Consumers of a fence can instead notify themselves by
>>> + * registering a callback on the fence.
>>
>> Mhm, the wait callback is transparent to consumers it's just that implementations used it for quite a number of different hacks.
>
> Right…
>
> but doesn't the question then become why dma_fence_wait_timeout() even
> exists? IOW, shall we deprecate it, too?
Yes, without the wait callback it is only a wrapper to block the current thread for a dma_fence to signal using a callback.
It's still quite useful to have a common function for that I think.
> It seems to be a reimplementation of waitqueues. The driver could get
> this functionality by using a waitqueue whose event gets triggered by a
> fence callback.
>
> dma_fence_default_wait() interacts directly with the task state with
> __XX_task() functions which looks very.. deep to me :)
That is *exactly* what I pointed out as well >10 years ago before that stuff was merged upstream :)
A wait_event based implementation would be tons of cleaner if you ask me.
>>
>> I would just drop that sentence.
>>
>>> */
>>> signed long (*wait)(struct dma_fence *fence,
>>> bool intr, signed long timeout);
>>> @@ -243,6 +249,8 @@ struct dma_fence_ops {
>>> /**
>>> * @release:
>>> *
>>> + * DEPRECATED!
>>> + *
>>> * Called on destruction of fence to release additional resources.
>>> * Can be called from irq context. This callback is optional. If it is
>>> * NULL, then dma_fence_free() is instead called as the default
>>> @@ -254,6 +262,12 @@ struct dma_fence_ops {
>>> *
>>> * If the callback is implemented the memory backing the dma_fence
>>> * object must be freed RCU safe.
>>> + *
>>> + * Deprecated because it prevents the producer of a fence from
>>> + * unloading. No new users must be implemented. Parties with a
>>> + * hypothetical need for this callback can instead simply and directly
>>> + * perform their custom release operations one RCU grace period after
>>> + * they have signaled the fence.
>>
>> Yeah that is a bit problematic.
>>
>> We need my patch set to explicit signal fences instead of returning true/false from callback for that so that a backend can properly implement this.
>
> Well, what I'm trying to say in this docu is that the driver can kick
> off custom operations that shall be performed once everyone is "done"
> with the fence after signaling it. Any driver data that might still be
> around cannot be accessed by fence consumers after signaling anymore.
> So the driver could trigger cleanup work after a graceperiod, as long
> as it does not involve kfree()-ing the fence itself.
That sounds sane to me, but I'm not sure how to phrase it cleaner either.
For now I'm ok with it, maybe somebody else has a better idea to how write this.
Thanks,
Christian.
>
>
> P.
On Wed, 2026-09-23 at 17:35 +0200, Christian König wrote: > On 9/23/26 17:27, Philipp Stanner wrote: > > On Wed, 2026-09-23 at 17:13 +0200, Christian König wrote: > > > On 9/23/26 17:03, Philipp Stanner wrote: > > > > > > > > […] > > > > > > > > > Consumers of a fence can instead notify themselves by > > > > + * registering a callback on the fence. > > > > > > Mhm, the wait callback is transparent to consumers it's just that > > > implementations used it for quite a number of different hacks. > > > > Right… > > > > but doesn't the question then become why dma_fence_wait_timeout() even > > exists? IOW, shall we deprecate it, too? > > Yes, without the wait callback it is only a wrapper to block the > current thread for a dma_fence to signal using a callback. I agree that it's probably quite a common use-case. I'm not sure whether it's possible to write a convenient wrapper, though, since you need to carry a waitqueue around. Maybe we can put a task for it onto the DRM TODO list? > > It's still quite useful to have a common function for that I think. > > > It seems to be a reimplementation of waitqueues. The driver could get > > this functionality by using a waitqueue whose event gets triggered by a > > fence callback. > > > > dma_fence_default_wait() interacts directly with the task state with > > __XX_task() functions which looks very.. deep to me :) > > That is *exactly* what I pointed out as well >10 years ago before that stuff was merged upstream :) > > A wait_event based implementation would be tons of cleaner if you ask me. So you objected and it was merged anyways? With any rationale? I think I understand now why sometimes people apply a Nacked-by, so that it's documented that people objected against merging. […] > > > > > > Well, what I'm trying to say in this docu is that the driver can kick > > off custom operations that shall be performed once everyone is "done" > > with the fence after signaling it. Any driver data that might still be > > around cannot be accessed by fence consumers after signaling anymore. > > So the driver could trigger cleanup work after a graceperiod, as long > > as it does not involve kfree()-ing the fence itself. > > That sounds sane to me, but I'm not sure how to phrase it cleaner either. > > For now I'm ok with it, maybe somebody else has a better idea to how write this. I try to come up with something slightly better. P.
© 2016 - 2026 Red Hat, Inc.