mirror of
https://github.com/torvalds/linux.git
synced 2026-05-25 07:33:19 +02:00
dma-buf: detach fence ops on signal v3
When neither a release nor a wait backend ops is specified it is possible to let the dma_fence live on independently of the module who issued it. This makes it possible to unload drivers and only wait for all their fences to signal. v2: fix typo in comment v3: fix sparse rcu warnings Signed-off-by: Christian König <christian.koenig@amd.com> Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com> Reviewed-by: Philipp Stanner <phasta@kernel.org> Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com> Link: https://lore.kernel.org/r/20260219160822.1529-3-christian.koenig@amd.com
This commit is contained in:
parent
f4cc3ab824
commit
541c8f2468
|
|
@ -362,6 +362,7 @@ void __dma_fence_might_wait(void)
|
||||||
void dma_fence_signal_timestamp_locked(struct dma_fence *fence,
|
void dma_fence_signal_timestamp_locked(struct dma_fence *fence,
|
||||||
ktime_t timestamp)
|
ktime_t timestamp)
|
||||||
{
|
{
|
||||||
|
const struct dma_fence_ops *ops;
|
||||||
struct dma_fence_cb *cur, *tmp;
|
struct dma_fence_cb *cur, *tmp;
|
||||||
struct list_head cb_list;
|
struct list_head cb_list;
|
||||||
|
|
||||||
|
|
@ -371,6 +372,15 @@ void dma_fence_signal_timestamp_locked(struct dma_fence *fence,
|
||||||
&fence->flags)))
|
&fence->flags)))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When neither a release nor a wait operation is specified set the ops
|
||||||
|
* pointer to NULL to allow the fence structure to become independent
|
||||||
|
* from who originally issued it.
|
||||||
|
*/
|
||||||
|
ops = rcu_dereference_protected(fence->ops, true);
|
||||||
|
if (!ops->release && !ops->wait)
|
||||||
|
RCU_INIT_POINTER(fence->ops, NULL);
|
||||||
|
|
||||||
/* Stash the cb_list before replacing it with the timestamp */
|
/* Stash the cb_list before replacing it with the timestamp */
|
||||||
list_replace(&fence->cb_list, &cb_list);
|
list_replace(&fence->cb_list, &cb_list);
|
||||||
|
|
||||||
|
|
@ -537,7 +547,7 @@ dma_fence_wait_timeout(struct dma_fence *fence, bool intr, signed long timeout)
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
ops = rcu_dereference(fence->ops);
|
ops = rcu_dereference(fence->ops);
|
||||||
trace_dma_fence_wait_start(fence);
|
trace_dma_fence_wait_start(fence);
|
||||||
if (ops->wait) {
|
if (ops && ops->wait) {
|
||||||
/*
|
/*
|
||||||
* Implementing the wait ops is deprecated and not supported for
|
* Implementing the wait ops is deprecated and not supported for
|
||||||
* issuers of fences who need their lifetime to be independent
|
* issuers of fences who need their lifetime to be independent
|
||||||
|
|
@ -603,7 +613,7 @@ void dma_fence_release(struct kref *kref)
|
||||||
}
|
}
|
||||||
|
|
||||||
ops = rcu_dereference(fence->ops);
|
ops = rcu_dereference(fence->ops);
|
||||||
if (ops->release)
|
if (ops && ops->release)
|
||||||
ops->release(fence);
|
ops->release(fence);
|
||||||
else
|
else
|
||||||
dma_fence_free(fence);
|
dma_fence_free(fence);
|
||||||
|
|
@ -639,7 +649,7 @@ static bool __dma_fence_enable_signaling(struct dma_fence *fence)
|
||||||
|
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
ops = rcu_dereference(fence->ops);
|
ops = rcu_dereference(fence->ops);
|
||||||
if (!was_set && ops->enable_signaling) {
|
if (!was_set && ops && ops->enable_signaling) {
|
||||||
trace_dma_fence_enable_signal(fence);
|
trace_dma_fence_enable_signal(fence);
|
||||||
|
|
||||||
if (!ops->enable_signaling(fence)) {
|
if (!ops->enable_signaling(fence)) {
|
||||||
|
|
@ -1025,7 +1035,7 @@ void dma_fence_set_deadline(struct dma_fence *fence, ktime_t deadline)
|
||||||
|
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
ops = rcu_dereference(fence->ops);
|
ops = rcu_dereference(fence->ops);
|
||||||
if (ops->set_deadline && !dma_fence_is_signaled(fence))
|
if (ops && ops->set_deadline && !dma_fence_is_signaled(fence))
|
||||||
ops->set_deadline(fence, deadline);
|
ops->set_deadline(fence, deadline);
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -472,7 +472,7 @@ dma_fence_is_signaled_locked(struct dma_fence *fence)
|
||||||
|
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
ops = rcu_dereference(fence->ops);
|
ops = rcu_dereference(fence->ops);
|
||||||
if (ops->signaled && ops->signaled(fence)) {
|
if (ops && ops->signaled && ops->signaled(fence)) {
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
dma_fence_signal_locked(fence);
|
dma_fence_signal_locked(fence);
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -508,7 +508,7 @@ dma_fence_is_signaled(struct dma_fence *fence)
|
||||||
|
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
ops = rcu_dereference(fence->ops);
|
ops = rcu_dereference(fence->ops);
|
||||||
if (ops->signaled && ops->signaled(fence)) {
|
if (ops && ops->signaled && ops->signaled(fence)) {
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
dma_fence_signal(fence);
|
dma_fence_signal(fence);
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user