diff --git a/sys/dev/drm/include/linux/dma-fence.h b/sys/dev/drm/include/linux/dma-fence.h --- a/sys/dev/drm/include/linux/dma-fence.h +++ b/sys/dev/drm/include/linux/dma-fence.h @@ -97,9 +97,14 @@ static inline struct dma_fence * dma_fence_get_rcu(struct dma_fence *fence) { + /* Must use kref_get_unless_zero so that RCU readers in + * linux_reservation.c (reservation_object_get_fences_rcu etc.) can + * detect a fence mid-teardown (refcount already 0) and retry. + * Unconditional kref_get made their if(!dma_fence_get_rcu(..)) retry + * logic dead code and caused double-frees. */ if (fence) - kref_get(&fence->refcount); - return fence; + return kref_get_unless_zero(&fence->refcount) ? fence : NULL; + return NULL; } static inline void