summaryrefslogtreecommitdiff
path: root/drivers/dma-buf/sync_file.c
diff options
context:
space:
mode:
authorChristian König <christian.koenig@amd.com>2022-04-25 15:22:12 +0300
committerChristian König <christian.koenig@amd.com>2022-05-30 15:24:04 +0300
commit245a4a7b531cffb41233a716497c25b06835cf4b (patch)
treed9da42cead12ac1cfc5583fd14751d99c4b39140 /drivers/dma-buf/sync_file.c
parent8f61973718485f3e89bc4f408f929048b7b47c83 (diff)
downloadlinux-245a4a7b531cffb41233a716497c25b06835cf4b.tar.xz
dma-buf: generalize dma_fence unwrap & merging v3
Introduce a dma_fence_unwrap_merge() macro which allows to unwrap fences which potentially can be containers as well and then merge them back together into a flat dma_fence_array. v2: rename the function, add some more comments about how the wrapper is used, move filtering of signaled fences into the unwrap iterator, add complex selftest which covers more cases. v3: fix signaled fence filtering once more Signed-off-by: Christian König <christian.koenig@amd.com> Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> Link: https://patchwork.freedesktop.org/patch/msgid/20220518135844.3338-5-christian.koenig@amd.com
Diffstat (limited to 'drivers/dma-buf/sync_file.c')
-rw-r--r--drivers/dma-buf/sync_file.c119
1 files changed, 6 insertions, 113 deletions
diff --git a/drivers/dma-buf/sync_file.c b/drivers/dma-buf/sync_file.c
index 0fe564539166..3ebec19a8e02 100644
--- a/drivers/dma-buf/sync_file.c
+++ b/drivers/dma-buf/sync_file.c
@@ -146,50 +146,6 @@ char *sync_file_get_name(struct sync_file *sync_file, char *buf, int len)
return buf;
}
-static int sync_file_set_fence(struct sync_file *sync_file,
- struct dma_fence **fences, int num_fences)
-{
- struct dma_fence_array *array;
-
- /*
- * The reference for the fences in the new sync_file and held
- * in add_fence() during the merge procedure, so for num_fences == 1
- * we already own a new reference to the fence. For num_fence > 1
- * we own the reference of the dma_fence_array creation.
- */
-
- if (num_fences == 0) {
- sync_file->fence = dma_fence_get_stub();
- kfree(fences);
-
- } else if (num_fences == 1) {
- sync_file->fence = fences[0];
- kfree(fences);
-
- } else {
- array = dma_fence_array_create(num_fences, fences,
- dma_fence_context_alloc(1),
- 1, false);
- if (!array)
- return -ENOMEM;
-
- sync_file->fence = &array->base;
- }
-
- return 0;
-}
-
-static void add_fence(struct dma_fence **fences,
- int *i, struct dma_fence *fence)
-{
- fences[*i] = fence;
-
- if (!dma_fence_is_signaled(fence)) {
- dma_fence_get(fence);
- (*i)++;
- }
-}
-
/**
* sync_file_merge() - merge two sync_files
* @name: name of new fence
@@ -203,84 +159,21 @@ static void add_fence(struct dma_fence **fences,
static struct sync_file *sync_file_merge(const char *name, struct sync_file *a,
struct sync_file *b)
{
- struct dma_fence *a_fence, *b_fence, **fences;
- struct dma_fence_unwrap a_iter, b_iter;
- unsigned int index, num_fences;
struct sync_file *sync_file;
+ struct dma_fence *fence;
sync_file = sync_file_alloc();
if (!sync_file)
return NULL;
- num_fences = 0;
- dma_fence_unwrap_for_each(a_fence, &a_iter, a->fence)
- ++num_fences;
- dma_fence_unwrap_for_each(b_fence, &b_iter, b->fence)
- ++num_fences;
-
- if (num_fences > INT_MAX)
- goto err_free_sync_file;
-
- fences = kcalloc(num_fences, sizeof(*fences), GFP_KERNEL);
- if (!fences)
- goto err_free_sync_file;
-
- /*
- * We can't guarantee that fences in both a and b are ordered, but it is
- * still quite likely.
- *
- * So attempt to order the fences as we pass over them and merge fences
- * with the same context.
- */
-
- index = 0;
- for (a_fence = dma_fence_unwrap_first(a->fence, &a_iter),
- b_fence = dma_fence_unwrap_first(b->fence, &b_iter);
- a_fence || b_fence; ) {
-
- if (!b_fence) {
- add_fence(fences, &index, a_fence);
- a_fence = dma_fence_unwrap_next(&a_iter);
-
- } else if (!a_fence) {
- add_fence(fences, &index, b_fence);
- b_fence = dma_fence_unwrap_next(&b_iter);
-
- } else if (a_fence->context < b_fence->context) {
- add_fence(fences, &index, a_fence);
- a_fence = dma_fence_unwrap_next(&a_iter);
-
- } else if (b_fence->context < a_fence->context) {
- add_fence(fences, &index, b_fence);
- b_fence = dma_fence_unwrap_next(&b_iter);
-
- } else if (__dma_fence_is_later(a_fence->seqno, b_fence->seqno,
- a_fence->ops)) {
- add_fence(fences, &index, a_fence);
- a_fence = dma_fence_unwrap_next(&a_iter);
- b_fence = dma_fence_unwrap_next(&b_iter);
-
- } else {
- add_fence(fences, &index, b_fence);
- a_fence = dma_fence_unwrap_next(&a_iter);
- b_fence = dma_fence_unwrap_next(&b_iter);
- }
+ fence = dma_fence_unwrap_merge(a->fence, b->fence);
+ if (!fence) {
+ fput(sync_file->file);
+ return NULL;
}
-
- if (sync_file_set_fence(sync_file, fences, index) < 0)
- goto err_put_fences;
-
+ sync_file->fence = fence;
strlcpy(sync_file->user_name, name, sizeof(sync_file->user_name));
return sync_file;
-
-err_put_fences:
- while (index)
- dma_fence_put(fences[--index]);
- kfree(fences);
-
-err_free_sync_file:
- fput(sync_file->file);
- return NULL;
}
static int sync_file_release(struct inode *inode, struct file *file)