From 427231bc6d585befe09ea793776f0ba4d032c3f8 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sun, 9 Jun 2019 12:00:02 +0100 Subject: [PATCH] dma-fence: Signal all callbacks from dma_fence_release() This is an illegal scenario, to free the fence whilst there are pending callbacks. Currently, we emit a WARN and then cast aside the callbacks leaving them dangling. Alternatively, we could set an error on the fence and then signal fence so that any dependency chains from the fence can be tidied up, and if they care they can check for the error. Signed-off-by: Chris Wilson Reviewed-by: Gustavo Padovan Link: https://patchwork.freedesktop.org/patch/msgid/20190609110002.31915-1-chris@chris-wilson.co.uk --- drivers/dma-buf/dma-fence.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/drivers/dma-buf/dma-fence.c b/drivers/dma-buf/dma-fence.c index 9bf06042619a..3eddfa0ad206 100644 --- a/drivers/dma-buf/dma-fence.c +++ b/drivers/dma-buf/dma-fence.c @@ -256,8 +256,25 @@ void dma_fence_release(struct kref *kref) trace_dma_fence_destroy(fence); - /* Failed to signal before release, could be a refcounting issue */ - WARN_ON(!list_empty(&fence->cb_list)); + if (WARN(!list_empty(&fence->cb_list), + "Fence %s:%s:%llx:%llx released with pending signals!\n", + fence->ops->get_driver_name(fence), + fence->ops->get_timeline_name(fence), + fence->context, fence->seqno)) { + unsigned long flags; + + /* + * Failed to signal before release, likely a refcounting issue. + * + * This should never happen, but if it does make sure that we + * don't leave chains dangling. We set the error flag first + * so that the callbacks know this signal is due to an error. + */ + spin_lock_irqsave(fence->lock, flags); + fence->error = -EDEADLK; + dma_fence_signal_locked(fence); + spin_unlock_irqrestore(fence->lock, flags); + } if (fence->ops->release) fence->ops->release(fence); -- 2.30.2