diff options
author | Christian König <christian.koenig@amd.com> | 2017-08-10 13:01:48 -0400 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2017-08-14 13:00:49 -0400 |
commit | 7faf952a3030d304334fe527be339b63e9e2745f (patch) | |
tree | b683adcf0d77b936849899e06e7b6f0054a26faa /drivers/dma-buf | |
parent | eac99d4a2013d9e68d12d8a5695b221593d3aa8d (diff) |
dma-buf: add reservation_object_copy_fences (v2)
Allows us to copy all the fences in a reservation object to another one.
v2: handle NULL src_list
Signed-off-by: Christian König <christian.koenig@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Link: https://patchwork.freedesktop.org/patch/msgid/1502384509-10465-2-git-send-email-alexander.deucher@amd.com
Diffstat (limited to 'drivers/dma-buf')
-rw-r--r-- | drivers/dma-buf/reservation.c | 60 |
1 files changed, 60 insertions, 0 deletions
diff --git a/drivers/dma-buf/reservation.c b/drivers/dma-buf/reservation.c index 87f8f5747500..d4881f91c43b 100644 --- a/drivers/dma-buf/reservation.c +++ b/drivers/dma-buf/reservation.c @@ -262,6 +262,66 @@ void reservation_object_add_excl_fence(struct reservation_object *obj, EXPORT_SYMBOL(reservation_object_add_excl_fence); /** +* reservation_object_copy_fences - Copy all fences from src to dst. +* @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. +*/ +int reservation_object_copy_fences(struct reservation_object *dst, + struct reservation_object *src) +{ + struct reservation_object_list *src_list, *dst_list; + struct dma_fence *old, *new; + size_t size; + unsigned i; + + src_list = reservation_object_get_list(src); + + if (src_list) { + size = offsetof(typeof(*src_list), + shared[src_list->shared_count]); + 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]); + } else { + dst_list = NULL; + } + + 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); + /* write_seqcount_begin provides the necessary memory barrier */ + RCU_INIT_POINTER(dst->fence_excl, new); + RCU_INIT_POINTER(dst->fence, dst_list); + write_seqcount_end(&dst->seq); + preempt_enable(); + + if (src_list) + kfree_rcu(src_list, rcu); + dma_fence_put(old); + + return 0; +} +EXPORT_SYMBOL(reservation_object_copy_fences); + +/** * reservation_object_get_fences_rcu - Get an object's shared and exclusive * fences without update side lock held * @obj: the reservation object |