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 | |
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
-rw-r--r-- | drivers/dma-buf/reservation.c | 60 | ||||
-rw-r--r-- | include/linux/reservation.h | 3 |
2 files changed, 63 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, | |||
262 | EXPORT_SYMBOL(reservation_object_add_excl_fence); | 262 | EXPORT_SYMBOL(reservation_object_add_excl_fence); |
263 | 263 | ||
264 | /** | 264 | /** |
265 | * reservation_object_copy_fences - Copy all fences from src to dst. | ||
266 | * @dst: the destination reservation object | ||
267 | * @src: the source reservation object | ||
268 | * | ||
269 | * Copy all fences from src to dst. Both src->lock as well as dst-lock must be | ||
270 | * held. | ||
271 | */ | ||
272 | int reservation_object_copy_fences(struct reservation_object *dst, | ||
273 | struct reservation_object *src) | ||
274 | { | ||
275 | struct reservation_object_list *src_list, *dst_list; | ||
276 | struct dma_fence *old, *new; | ||
277 | size_t size; | ||
278 | unsigned i; | ||
279 | |||
280 | src_list = reservation_object_get_list(src); | ||
281 | |||
282 | if (src_list) { | ||
283 | size = offsetof(typeof(*src_list), | ||
284 | shared[src_list->shared_count]); | ||
285 | dst_list = kmalloc(size, GFP_KERNEL); | ||
286 | if (!dst_list) | ||
287 | return -ENOMEM; | ||
288 | |||
289 | dst_list->shared_count = src_list->shared_count; | ||
290 | dst_list->shared_max = src_list->shared_count; | ||
291 | for (i = 0; i < src_list->shared_count; ++i) | ||
292 | dst_list->shared[i] = | ||
293 | dma_fence_get(src_list->shared[i]); | ||
294 | } else { | ||
295 | dst_list = NULL; | ||
296 | } | ||
297 | |||
298 | kfree(dst->staged); | ||
299 | dst->staged = NULL; | ||
300 | |||
301 | src_list = reservation_object_get_list(dst); | ||
302 | |||
303 | old = reservation_object_get_excl(dst); | ||
304 | new = reservation_object_get_excl(src); | ||
305 | |||
306 | dma_fence_get(new); | ||
307 | |||
308 | preempt_disable(); | ||
309 | write_seqcount_begin(&dst->seq); | ||
310 | /* write_seqcount_begin provides the necessary memory barrier */ | ||
311 | RCU_INIT_POINTER(dst->fence_excl, new); | ||
312 | RCU_INIT_POINTER(dst->fence, dst_list); | ||
313 | write_seqcount_end(&dst->seq); | ||
314 | preempt_enable(); | ||
315 | |||
316 | if (src_list) | ||
317 | kfree_rcu(src_list, rcu); | ||
318 | dma_fence_put(old); | ||
319 | |||
320 | return 0; | ||
321 | } | ||
322 | EXPORT_SYMBOL(reservation_object_copy_fences); | ||
323 | |||
324 | /** | ||
265 | * reservation_object_get_fences_rcu - Get an object's shared and exclusive | 325 | * reservation_object_get_fences_rcu - Get an object's shared and exclusive |
266 | * fences without update side lock held | 326 | * fences without update side lock held |
267 | * @obj: the reservation object | 327 | * @obj: the reservation object |
diff --git a/include/linux/reservation.h b/include/linux/reservation.h index 156cfd330b66..21fc84d82d41 100644 --- a/include/linux/reservation.h +++ b/include/linux/reservation.h | |||
@@ -254,6 +254,9 @@ int reservation_object_get_fences_rcu(struct reservation_object *obj, | |||
254 | unsigned *pshared_count, | 254 | unsigned *pshared_count, |
255 | struct dma_fence ***pshared); | 255 | struct dma_fence ***pshared); |
256 | 256 | ||
257 | int reservation_object_copy_fences(struct reservation_object *dst, | ||
258 | struct reservation_object *src); | ||
259 | |||
257 | long reservation_object_wait_timeout_rcu(struct reservation_object *obj, | 260 | long reservation_object_wait_timeout_rcu(struct reservation_object *obj, |
258 | bool wait_all, bool intr, | 261 | bool wait_all, bool intr, |
259 | unsigned long timeout); | 262 | unsigned long timeout); |