forked from mirrors/linux
		
	dma-buf: add reservation_object_fences helper
Add a new helper to get a consistent set of pointers from the reservation object. While at it group all access helpers together in the header file. v2: correctly return shared_count as well Signed-off-by: Christian König <christian.koenig@amd.com> Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk> Link: https://patchwork.freedesktop.org/patch/322378/?series=64837&rev=1
This commit is contained in:
		
							parent
							
								
									0e2f733add
								
							
						
					
					
						commit
						67c97fb79a
					
				
					 3 changed files with 101 additions and 127 deletions
				
			
		| 
						 | 
					@ -199,7 +199,7 @@ static __poll_t dma_buf_poll(struct file *file, poll_table *poll)
 | 
				
			||||||
	struct reservation_object_list *fobj;
 | 
						struct reservation_object_list *fobj;
 | 
				
			||||||
	struct dma_fence *fence_excl;
 | 
						struct dma_fence *fence_excl;
 | 
				
			||||||
	__poll_t events;
 | 
						__poll_t events;
 | 
				
			||||||
	unsigned shared_count, seq;
 | 
						unsigned shared_count;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dmabuf = file->private_data;
 | 
						dmabuf = file->private_data;
 | 
				
			||||||
	if (!dmabuf || !dmabuf->resv)
 | 
						if (!dmabuf || !dmabuf->resv)
 | 
				
			||||||
| 
						 | 
					@ -213,21 +213,8 @@ static __poll_t dma_buf_poll(struct file *file, poll_table *poll)
 | 
				
			||||||
	if (!events)
 | 
						if (!events)
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
retry:
 | 
					 | 
				
			||||||
	seq = read_seqcount_begin(&resv->seq);
 | 
					 | 
				
			||||||
	rcu_read_lock();
 | 
						rcu_read_lock();
 | 
				
			||||||
 | 
						reservation_object_fences(resv, &fence_excl, &fobj, &shared_count);
 | 
				
			||||||
	fobj = rcu_dereference(resv->fence);
 | 
					 | 
				
			||||||
	if (fobj)
 | 
					 | 
				
			||||||
		shared_count = fobj->shared_count;
 | 
					 | 
				
			||||||
	else
 | 
					 | 
				
			||||||
		shared_count = 0;
 | 
					 | 
				
			||||||
	fence_excl = rcu_dereference(resv->fence_excl);
 | 
					 | 
				
			||||||
	if (read_seqcount_retry(&resv->seq, seq)) {
 | 
					 | 
				
			||||||
		rcu_read_unlock();
 | 
					 | 
				
			||||||
		goto retry;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (fence_excl && (!(events & EPOLLOUT) || shared_count == 0)) {
 | 
						if (fence_excl && (!(events & EPOLLOUT) || shared_count == 0)) {
 | 
				
			||||||
		struct dma_buf_poll_cb_t *dcb = &dmabuf->cb_excl;
 | 
							struct dma_buf_poll_cb_t *dcb = &dmabuf->cb_excl;
 | 
				
			||||||
		__poll_t pevents = EPOLLIN;
 | 
							__poll_t pevents = EPOLLIN;
 | 
				
			||||||
| 
						 | 
					@ -1157,7 +1144,6 @@ static int dma_buf_debug_show(struct seq_file *s, void *unused)
 | 
				
			||||||
	struct reservation_object *robj;
 | 
						struct reservation_object *robj;
 | 
				
			||||||
	struct reservation_object_list *fobj;
 | 
						struct reservation_object_list *fobj;
 | 
				
			||||||
	struct dma_fence *fence;
 | 
						struct dma_fence *fence;
 | 
				
			||||||
	unsigned seq;
 | 
					 | 
				
			||||||
	int count = 0, attach_count, shared_count, i;
 | 
						int count = 0, attach_count, shared_count, i;
 | 
				
			||||||
	size_t size = 0;
 | 
						size_t size = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1188,16 +1174,9 @@ static int dma_buf_debug_show(struct seq_file *s, void *unused)
 | 
				
			||||||
				buf_obj->name ?: "");
 | 
									buf_obj->name ?: "");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		robj = buf_obj->resv;
 | 
							robj = buf_obj->resv;
 | 
				
			||||||
		while (true) {
 | 
					 | 
				
			||||||
			seq = read_seqcount_begin(&robj->seq);
 | 
					 | 
				
			||||||
		rcu_read_lock();
 | 
							rcu_read_lock();
 | 
				
			||||||
			fobj = rcu_dereference(robj->fence);
 | 
							reservation_object_fences(robj, &fence, &fobj, &shared_count);
 | 
				
			||||||
			shared_count = fobj ? fobj->shared_count : 0;
 | 
					 | 
				
			||||||
			fence = rcu_dereference(robj->fence_excl);
 | 
					 | 
				
			||||||
			if (!read_seqcount_retry(&robj->seq, seq))
 | 
					 | 
				
			||||||
				break;
 | 
					 | 
				
			||||||
		rcu_read_unlock();
 | 
							rcu_read_unlock();
 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (fence)
 | 
							if (fence)
 | 
				
			||||||
			seq_printf(s, "\tExclusive fence: %s %s %ssignalled\n",
 | 
								seq_printf(s, "\tExclusive fence: %s %s %ssignalled\n",
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -317,17 +317,15 @@ int reservation_object_copy_fences(struct reservation_object *dst,
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct reservation_object_list *src_list, *dst_list;
 | 
						struct reservation_object_list *src_list, *dst_list;
 | 
				
			||||||
	struct dma_fence *old, *new;
 | 
						struct dma_fence *old, *new;
 | 
				
			||||||
	unsigned i;
 | 
						unsigned int i, shared_count;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	reservation_object_assert_held(dst);
 | 
						reservation_object_assert_held(dst);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	rcu_read_lock();
 | 
						rcu_read_lock();
 | 
				
			||||||
	src_list = rcu_dereference(src->fence);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
retry:
 | 
					retry:
 | 
				
			||||||
	if (src_list) {
 | 
						reservation_object_fences(src, &new, &src_list, &shared_count);
 | 
				
			||||||
		unsigned shared_count = src_list->shared_count;
 | 
						if (shared_count) {
 | 
				
			||||||
 | 
					 | 
				
			||||||
		rcu_read_unlock();
 | 
							rcu_read_unlock();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		dst_list = reservation_object_list_alloc(shared_count);
 | 
							dst_list = reservation_object_list_alloc(shared_count);
 | 
				
			||||||
| 
						 | 
					@ -335,14 +333,14 @@ int reservation_object_copy_fences(struct reservation_object *dst,
 | 
				
			||||||
			return -ENOMEM;
 | 
								return -ENOMEM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		rcu_read_lock();
 | 
							rcu_read_lock();
 | 
				
			||||||
		src_list = rcu_dereference(src->fence);
 | 
							reservation_object_fences(src, &new, &src_list, &shared_count);
 | 
				
			||||||
		if (!src_list || src_list->shared_count > shared_count) {
 | 
							if (!src_list || shared_count > dst_list->shared_max) {
 | 
				
			||||||
			kfree(dst_list);
 | 
								kfree(dst_list);
 | 
				
			||||||
			goto retry;
 | 
								goto retry;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		dst_list->shared_count = 0;
 | 
							dst_list->shared_count = 0;
 | 
				
			||||||
		for (i = 0; i < src_list->shared_count; ++i) {
 | 
							for (i = 0; i < shared_count; ++i) {
 | 
				
			||||||
			struct dma_fence *fence;
 | 
								struct dma_fence *fence;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			fence = rcu_dereference(src_list->shared[i]);
 | 
								fence = rcu_dereference(src_list->shared[i]);
 | 
				
			||||||
| 
						 | 
					@ -352,7 +350,6 @@ int reservation_object_copy_fences(struct reservation_object *dst,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (!dma_fence_get_rcu(fence)) {
 | 
								if (!dma_fence_get_rcu(fence)) {
 | 
				
			||||||
				reservation_object_list_free(dst_list);
 | 
									reservation_object_list_free(dst_list);
 | 
				
			||||||
				src_list = rcu_dereference(src->fence);
 | 
					 | 
				
			||||||
				goto retry;
 | 
									goto retry;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -367,7 +364,10 @@ int reservation_object_copy_fences(struct reservation_object *dst,
 | 
				
			||||||
		dst_list = NULL;
 | 
							dst_list = NULL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	new = dma_fence_get_rcu_safe(&src->fence_excl);
 | 
						if (new && !dma_fence_get_rcu(new)) {
 | 
				
			||||||
 | 
							reservation_object_list_free(dst_list);
 | 
				
			||||||
 | 
							goto retry;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	rcu_read_unlock();
 | 
						rcu_read_unlock();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	src_list = reservation_object_get_list(dst);
 | 
						src_list = reservation_object_get_list(dst);
 | 
				
			||||||
| 
						 | 
					@ -413,19 +413,18 @@ int reservation_object_get_fences_rcu(struct reservation_object *obj,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	do {
 | 
						do {
 | 
				
			||||||
		struct reservation_object_list *fobj;
 | 
							struct reservation_object_list *fobj;
 | 
				
			||||||
		unsigned int i, seq;
 | 
							unsigned int i;
 | 
				
			||||||
		size_t sz = 0;
 | 
							size_t sz = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		shared_count = i = 0;
 | 
							i = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		rcu_read_lock();
 | 
							rcu_read_lock();
 | 
				
			||||||
		seq = read_seqcount_begin(&obj->seq);
 | 
							reservation_object_fences(obj, &fence_excl, &fobj,
 | 
				
			||||||
 | 
										  &shared_count);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		fence_excl = rcu_dereference(obj->fence_excl);
 | 
					 | 
				
			||||||
		if (fence_excl && !dma_fence_get_rcu(fence_excl))
 | 
							if (fence_excl && !dma_fence_get_rcu(fence_excl))
 | 
				
			||||||
			goto unlock;
 | 
								goto unlock;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		fobj = rcu_dereference(obj->fence);
 | 
					 | 
				
			||||||
		if (fobj)
 | 
							if (fobj)
 | 
				
			||||||
			sz += sizeof(*shared) * fobj->shared_max;
 | 
								sz += sizeof(*shared) * fobj->shared_max;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -453,7 +452,6 @@ int reservation_object_get_fences_rcu(struct reservation_object *obj,
 | 
				
			||||||
				break;
 | 
									break;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			shared = nshared;
 | 
								shared = nshared;
 | 
				
			||||||
			shared_count = fobj ? fobj->shared_count : 0;
 | 
					 | 
				
			||||||
			for (i = 0; i < shared_count; ++i) {
 | 
								for (i = 0; i < shared_count; ++i) {
 | 
				
			||||||
				shared[i] = rcu_dereference(fobj->shared[i]);
 | 
									shared[i] = rcu_dereference(fobj->shared[i]);
 | 
				
			||||||
				if (!dma_fence_get_rcu(shared[i]))
 | 
									if (!dma_fence_get_rcu(shared[i]))
 | 
				
			||||||
| 
						 | 
					@ -461,7 +459,7 @@ int reservation_object_get_fences_rcu(struct reservation_object *obj,
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (i != shared_count || read_seqcount_retry(&obj->seq, seq)) {
 | 
							if (i != shared_count) {
 | 
				
			||||||
			while (i--)
 | 
								while (i--)
 | 
				
			||||||
				dma_fence_put(shared[i]);
 | 
									dma_fence_put(shared[i]);
 | 
				
			||||||
			dma_fence_put(fence_excl);
 | 
								dma_fence_put(fence_excl);
 | 
				
			||||||
| 
						 | 
					@ -505,18 +503,17 @@ long reservation_object_wait_timeout_rcu(struct reservation_object *obj,
 | 
				
			||||||
					 bool wait_all, bool intr,
 | 
										 bool wait_all, bool intr,
 | 
				
			||||||
					 unsigned long timeout)
 | 
										 unsigned long timeout)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						struct reservation_object_list *fobj;
 | 
				
			||||||
	struct dma_fence *fence;
 | 
						struct dma_fence *fence;
 | 
				
			||||||
	unsigned seq, shared_count;
 | 
						unsigned shared_count;
 | 
				
			||||||
	long ret = timeout ? timeout : 1;
 | 
						long ret = timeout ? timeout : 1;
 | 
				
			||||||
	int i;
 | 
						int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
retry:
 | 
					retry:
 | 
				
			||||||
	shared_count = 0;
 | 
					 | 
				
			||||||
	seq = read_seqcount_begin(&obj->seq);
 | 
					 | 
				
			||||||
	rcu_read_lock();
 | 
						rcu_read_lock();
 | 
				
			||||||
	i = -1;
 | 
						i = -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fence = rcu_dereference(obj->fence_excl);
 | 
						reservation_object_fences(obj, &fence, &fobj, &shared_count);
 | 
				
			||||||
	if (fence && !test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags)) {
 | 
						if (fence && !test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags)) {
 | 
				
			||||||
		if (!dma_fence_get_rcu(fence))
 | 
							if (!dma_fence_get_rcu(fence))
 | 
				
			||||||
			goto unlock_retry;
 | 
								goto unlock_retry;
 | 
				
			||||||
| 
						 | 
					@ -531,12 +528,6 @@ long reservation_object_wait_timeout_rcu(struct reservation_object *obj,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (wait_all) {
 | 
						if (wait_all) {
 | 
				
			||||||
		struct reservation_object_list *fobj =
 | 
					 | 
				
			||||||
						rcu_dereference(obj->fence);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (fobj)
 | 
					 | 
				
			||||||
			shared_count = fobj->shared_count;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		for (i = 0; !fence && i < shared_count; ++i) {
 | 
							for (i = 0; !fence && i < shared_count; ++i) {
 | 
				
			||||||
			struct dma_fence *lfence = rcu_dereference(fobj->shared[i]);
 | 
								struct dma_fence *lfence = rcu_dereference(fobj->shared[i]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -559,11 +550,6 @@ long reservation_object_wait_timeout_rcu(struct reservation_object *obj,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	rcu_read_unlock();
 | 
						rcu_read_unlock();
 | 
				
			||||||
	if (fence) {
 | 
						if (fence) {
 | 
				
			||||||
		if (read_seqcount_retry(&obj->seq, seq)) {
 | 
					 | 
				
			||||||
			dma_fence_put(fence);
 | 
					 | 
				
			||||||
			goto retry;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		ret = dma_fence_wait_timeout(fence, intr, ret);
 | 
							ret = dma_fence_wait_timeout(fence, intr, ret);
 | 
				
			||||||
		dma_fence_put(fence);
 | 
							dma_fence_put(fence);
 | 
				
			||||||
		if (ret > 0 && wait_all && (i + 1 < shared_count))
 | 
							if (ret > 0 && wait_all && (i + 1 < shared_count))
 | 
				
			||||||
| 
						 | 
					@ -608,24 +594,19 @@ reservation_object_test_signaled_single(struct dma_fence *passed_fence)
 | 
				
			||||||
bool reservation_object_test_signaled_rcu(struct reservation_object *obj,
 | 
					bool reservation_object_test_signaled_rcu(struct reservation_object *obj,
 | 
				
			||||||
					  bool test_all)
 | 
										  bool test_all)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	unsigned seq, shared_count;
 | 
						struct reservation_object_list *fobj;
 | 
				
			||||||
 | 
						struct dma_fence *fence_excl;
 | 
				
			||||||
 | 
						unsigned shared_count;
 | 
				
			||||||
	int ret;
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	rcu_read_lock();
 | 
						rcu_read_lock();
 | 
				
			||||||
retry:
 | 
					retry:
 | 
				
			||||||
	ret = true;
 | 
						ret = true;
 | 
				
			||||||
	shared_count = 0;
 | 
					 | 
				
			||||||
	seq = read_seqcount_begin(&obj->seq);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						reservation_object_fences(obj, &fence_excl, &fobj, &shared_count);
 | 
				
			||||||
	if (test_all) {
 | 
						if (test_all) {
 | 
				
			||||||
		unsigned i;
 | 
							unsigned i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		struct reservation_object_list *fobj =
 | 
					 | 
				
			||||||
						rcu_dereference(obj->fence);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (fobj)
 | 
					 | 
				
			||||||
			shared_count = fobj->shared_count;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		for (i = 0; i < shared_count; ++i) {
 | 
							for (i = 0; i < shared_count; ++i) {
 | 
				
			||||||
			struct dma_fence *fence = rcu_dereference(fobj->shared[i]);
 | 
								struct dma_fence *fence = rcu_dereference(fobj->shared[i]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -635,23 +616,12 @@ bool reservation_object_test_signaled_rcu(struct reservation_object *obj,
 | 
				
			||||||
			else if (!ret)
 | 
								else if (!ret)
 | 
				
			||||||
				break;
 | 
									break;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (read_seqcount_retry(&obj->seq, seq))
 | 
					 | 
				
			||||||
			goto retry;
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!shared_count) {
 | 
						if (!shared_count && fence_excl) {
 | 
				
			||||||
		struct dma_fence *fence_excl = rcu_dereference(obj->fence_excl);
 | 
							ret = reservation_object_test_signaled_single(fence_excl);
 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (fence_excl) {
 | 
					 | 
				
			||||||
			ret = reservation_object_test_signaled_single(
 | 
					 | 
				
			||||||
								fence_excl);
 | 
					 | 
				
			||||||
		if (ret < 0)
 | 
							if (ret < 0)
 | 
				
			||||||
			goto retry;
 | 
								goto retry;
 | 
				
			||||||
 | 
					 | 
				
			||||||
			if (read_seqcount_retry(&obj->seq, seq))
 | 
					 | 
				
			||||||
				goto retry;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	rcu_read_unlock();
 | 
						rcu_read_unlock();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -81,6 +81,25 @@ struct reservation_object {
 | 
				
			||||||
#define reservation_object_assert_held(obj) \
 | 
					#define reservation_object_assert_held(obj) \
 | 
				
			||||||
	lockdep_assert_held(&(obj)->lock.base)
 | 
						lockdep_assert_held(&(obj)->lock.base)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * reservation_object_get_excl - get the reservation object's
 | 
				
			||||||
 | 
					 * exclusive fence, with update-side lock held
 | 
				
			||||||
 | 
					 * @obj: the reservation object
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Returns the exclusive fence (if any).  Does NOT take a
 | 
				
			||||||
 | 
					 * reference. Writers must hold obj->lock, readers may only
 | 
				
			||||||
 | 
					 * hold a RCU read side lock.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * RETURNS
 | 
				
			||||||
 | 
					 * The exclusive fence or NULL
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static inline struct dma_fence *
 | 
				
			||||||
 | 
					reservation_object_get_excl(struct reservation_object *obj)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return rcu_dereference_protected(obj->fence_excl,
 | 
				
			||||||
 | 
										 reservation_object_held(obj));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * reservation_object_get_list - get the reservation object's
 | 
					 * reservation_object_get_list - get the reservation object's
 | 
				
			||||||
 * shared fence list, with update-side lock held
 | 
					 * shared fence list, with update-side lock held
 | 
				
			||||||
| 
						 | 
					@ -96,6 +115,57 @@ reservation_object_get_list(struct reservation_object *obj)
 | 
				
			||||||
					 reservation_object_held(obj));
 | 
										 reservation_object_held(obj));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * reservation_object_fences - read consistent fence pointers
 | 
				
			||||||
 | 
					 * @obj: reservation object where we get the fences from
 | 
				
			||||||
 | 
					 * @excl: pointer for the exclusive fence
 | 
				
			||||||
 | 
					 * @list: pointer for the shared fence list
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Make sure we have a consisten exclusive fence and shared fence list.
 | 
				
			||||||
 | 
					 * Must be called with rcu read side lock held.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static inline void
 | 
				
			||||||
 | 
					reservation_object_fences(struct reservation_object *obj,
 | 
				
			||||||
 | 
								  struct dma_fence **excl,
 | 
				
			||||||
 | 
								  struct reservation_object_list **list,
 | 
				
			||||||
 | 
								  u32 *shared_count)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned int seq;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						do {
 | 
				
			||||||
 | 
							seq = read_seqcount_begin(&obj->seq);
 | 
				
			||||||
 | 
							*excl = rcu_dereference(obj->fence_excl);
 | 
				
			||||||
 | 
							*list = rcu_dereference(obj->fence);
 | 
				
			||||||
 | 
							*shared_count = *list ? (*list)->shared_count : 0;
 | 
				
			||||||
 | 
						} while (read_seqcount_retry(&obj->seq, seq));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * reservation_object_get_excl_rcu - get the reservation object's
 | 
				
			||||||
 | 
					 * exclusive fence, without lock held.
 | 
				
			||||||
 | 
					 * @obj: the reservation object
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * If there is an exclusive fence, this atomically increments it's
 | 
				
			||||||
 | 
					 * reference count and returns it.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * RETURNS
 | 
				
			||||||
 | 
					 * The exclusive fence or NULL if none
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static inline struct dma_fence *
 | 
				
			||||||
 | 
					reservation_object_get_excl_rcu(struct reservation_object *obj)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct dma_fence *fence;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!rcu_access_pointer(obj->fence_excl))
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rcu_read_lock();
 | 
				
			||||||
 | 
						fence = dma_fence_get_rcu_safe(&obj->fence_excl);
 | 
				
			||||||
 | 
						rcu_read_unlock();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return fence;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * reservation_object_lock - lock the reservation object
 | 
					 * reservation_object_lock - lock the reservation object
 | 
				
			||||||
 * @obj: the reservation object
 | 
					 * @obj: the reservation object
 | 
				
			||||||
| 
						 | 
					@ -239,51 +309,6 @@ reservation_object_unlock(struct reservation_object *obj)
 | 
				
			||||||
	ww_mutex_unlock(&obj->lock);
 | 
						ww_mutex_unlock(&obj->lock);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * reservation_object_get_excl - get the reservation object's
 | 
					 | 
				
			||||||
 * exclusive fence, with update-side lock held
 | 
					 | 
				
			||||||
 * @obj: the reservation object
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Returns the exclusive fence (if any).  Does NOT take a
 | 
					 | 
				
			||||||
 * reference. Writers must hold obj->lock, readers may only
 | 
					 | 
				
			||||||
 * hold a RCU read side lock.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * RETURNS
 | 
					 | 
				
			||||||
 * The exclusive fence or NULL
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
static inline struct dma_fence *
 | 
					 | 
				
			||||||
reservation_object_get_excl(struct reservation_object *obj)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	return rcu_dereference_protected(obj->fence_excl,
 | 
					 | 
				
			||||||
					 reservation_object_held(obj));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * reservation_object_get_excl_rcu - get the reservation object's
 | 
					 | 
				
			||||||
 * exclusive fence, without lock held.
 | 
					 | 
				
			||||||
 * @obj: the reservation object
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * If there is an exclusive fence, this atomically increments it's
 | 
					 | 
				
			||||||
 * reference count and returns it.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * RETURNS
 | 
					 | 
				
			||||||
 * The exclusive fence or NULL if none
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
static inline struct dma_fence *
 | 
					 | 
				
			||||||
reservation_object_get_excl_rcu(struct reservation_object *obj)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct dma_fence *fence;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (!rcu_access_pointer(obj->fence_excl))
 | 
					 | 
				
			||||||
		return NULL;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	rcu_read_lock();
 | 
					 | 
				
			||||||
	fence = dma_fence_get_rcu_safe(&obj->fence_excl);
 | 
					 | 
				
			||||||
	rcu_read_unlock();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return fence;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void reservation_object_init(struct reservation_object *obj);
 | 
					void reservation_object_init(struct reservation_object *obj);
 | 
				
			||||||
void reservation_object_fini(struct reservation_object *obj);
 | 
					void reservation_object_fini(struct reservation_object *obj);
 | 
				
			||||||
int reservation_object_reserve_shared(struct reservation_object *obj,
 | 
					int reservation_object_reserve_shared(struct reservation_object *obj,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue