Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7faf952a authored by Christian König's avatar Christian König Committed by Alex Deucher
Browse files

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: default avatarChristian König <christian.koenig@amd.com>
Reviewed-by: default avatarAlex Deucher <alexander.deucher@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
Link: https://patchwork.freedesktop.org/patch/msgid/1502384509-10465-2-git-send-email-alexander.deucher@amd.com
parent eac99d4a
Loading
Loading
Loading
Loading
+60 −0
Original line number Diff line number Diff line
@@ -261,6 +261,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
+3 −0
Original line number Diff line number Diff line
@@ -254,6 +254,9 @@ int reservation_object_get_fences_rcu(struct reservation_object *obj,
				      unsigned *pshared_count,
				      struct dma_fence ***pshared);

int reservation_object_copy_fences(struct reservation_object *dst,
				   struct reservation_object *src);

long reservation_object_wait_timeout_rcu(struct reservation_object *obj,
					 bool wait_all, bool intr,
					 unsigned long timeout);