mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-29 15:14:18 +08:00
dma-buf: make reservation_object_copy_fences rcu save
Stop requiring that the src reservation object is locked for this operation. Acked-by: Chunming Zhou <david1.zhou@amd.com> Signed-off-by: Christian König <christian.koenig@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> Link: https://patchwork.freedesktop.org/patch/msgid/1504551766-5093-1-git-send-email-deathsimple@vodafone.de
This commit is contained in:
parent
6d281b1f79
commit
39e16ba16c
@ -266,8 +266,7 @@ EXPORT_SYMBOL(reservation_object_add_excl_fence);
|
||||
* @dst: the destination reservation object
|
||||
* @src: the source reservation object
|
||||
*
|
||||
* Copy all fences from src to dst. Both src->lock as well as dst-lock must be
|
||||
* held.
|
||||
* Copy all fences from src to dst. dst-lock must be held.
|
||||
*/
|
||||
int reservation_object_copy_fences(struct reservation_object *dst,
|
||||
struct reservation_object *src)
|
||||
@ -277,33 +276,62 @@ int reservation_object_copy_fences(struct reservation_object *dst,
|
||||
size_t size;
|
||||
unsigned i;
|
||||
|
||||
src_list = reservation_object_get_list(src);
|
||||
rcu_read_lock();
|
||||
src_list = rcu_dereference(src->fence);
|
||||
|
||||
retry:
|
||||
if (src_list) {
|
||||
size = offsetof(typeof(*src_list),
|
||||
shared[src_list->shared_count]);
|
||||
unsigned shared_count = src_list->shared_count;
|
||||
|
||||
size = offsetof(typeof(*src_list), shared[shared_count]);
|
||||
rcu_read_unlock();
|
||||
|
||||
dst_list = kmalloc(size, GFP_KERNEL);
|
||||
if (!dst_list)
|
||||
return -ENOMEM;
|
||||
|
||||
dst_list->shared_count = src_list->shared_count;
|
||||
dst_list->shared_max = src_list->shared_count;
|
||||
for (i = 0; i < src_list->shared_count; ++i)
|
||||
dst_list->shared[i] =
|
||||
dma_fence_get(src_list->shared[i]);
|
||||
rcu_read_lock();
|
||||
src_list = rcu_dereference(src->fence);
|
||||
if (!src_list || src_list->shared_count > shared_count) {
|
||||
kfree(dst_list);
|
||||
goto retry;
|
||||
}
|
||||
|
||||
dst_list->shared_count = 0;
|
||||
dst_list->shared_max = shared_count;
|
||||
for (i = 0; i < src_list->shared_count; ++i) {
|
||||
struct dma_fence *fence;
|
||||
|
||||
fence = rcu_dereference(src_list->shared[i]);
|
||||
if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT,
|
||||
&fence->flags))
|
||||
continue;
|
||||
|
||||
if (!dma_fence_get_rcu(fence)) {
|
||||
kfree(dst_list);
|
||||
src_list = rcu_dereference(src->fence);
|
||||
goto retry;
|
||||
}
|
||||
|
||||
if (dma_fence_is_signaled(fence)) {
|
||||
dma_fence_put(fence);
|
||||
continue;
|
||||
}
|
||||
|
||||
dst_list->shared[dst_list->shared_count++] = fence;
|
||||
}
|
||||
} else {
|
||||
dst_list = NULL;
|
||||
}
|
||||
|
||||
new = dma_fence_get_rcu_safe(&src->fence_excl);
|
||||
rcu_read_unlock();
|
||||
|
||||
kfree(dst->staged);
|
||||
dst->staged = NULL;
|
||||
|
||||
src_list = reservation_object_get_list(dst);
|
||||
|
||||
old = reservation_object_get_excl(dst);
|
||||
new = reservation_object_get_excl(src);
|
||||
|
||||
dma_fence_get(new);
|
||||
|
||||
preempt_disable();
|
||||
write_seqcount_begin(&dst->seq);
|
||||
|
Loading…
Reference in New Issue
Block a user