From: Gustavo Padovan <gustavo.padovan@xxxxxxxxxxxxxxx> Create sync_file->fence to abstract the type of fence we are using for each sync_file. If only one fence is present we use a normal struct fence but if there is more fences to be added to the sync_file a fence_array is created. This behaviour is transparent all sync_file functions, but sync_file_set_fence() which sets the fence in the sync_file_merge(). It is this functions that decides to use a fence or fence_array based on num_fences. This change cleans up sync_file a bit. We don't need to have sync_file_cb array anymore. Instead, as we always have one fence, only one fence callback is registered per sync_file. Signed-off-by: Gustavo Padovan <gustavo.padovan@xxxxxxxxxxxxxxx> --- drivers/dma-buf/sync_file.c | 129 +++++++++++++++++++++++++---------- drivers/staging/android/sync_debug.c | 5 +- include/linux/sync_file.h | 12 ++-- 3 files changed, 100 insertions(+), 46 deletions(-) diff --git a/drivers/dma-buf/sync_file.c b/drivers/dma-buf/sync_file.c index 9aaa608..5044ef2 100644 --- a/drivers/dma-buf/sync_file.c +++ b/drivers/dma-buf/sync_file.c @@ -25,14 +25,15 @@ #include <linux/anon_inodes.h> #include <linux/sync_file.h> #include <uapi/linux/sync_file.h> +#include <linux/fence-array.h> static const struct file_operations sync_file_fops; -static struct sync_file *sync_file_alloc(int size) +static struct sync_file *sync_file_alloc(void) { struct sync_file *sync_file; - sync_file = kzalloc(size, GFP_KERNEL); + sync_file = kzalloc(sizeof(*sync_file), GFP_KERNEL); if (!sync_file) return NULL; @@ -45,6 +46,8 @@ static struct sync_file *sync_file_alloc(int size) init_waitqueue_head(&sync_file->wq); + INIT_LIST_HEAD(&sync_file->cb.node); + return sync_file; err: @@ -54,11 +57,9 @@ err: static void fence_check_cb_func(struct fence *f, struct fence_cb *cb) { - struct sync_file_cb *check; struct sync_file *sync_file; - check = container_of(cb, struct sync_file_cb, cb); - sync_file = check->sync_file; + sync_file = container_of(cb, struct sync_file, cb); if (atomic_dec_and_test(&sync_file->status)) wake_up_all(&sync_file->wq); @@ -76,21 +77,20 @@ struct sync_file *sync_file_create(struct fence *fence) { struct sync_file *sync_file; - sync_file = sync_file_alloc(offsetof(struct sync_file, cbs[1])); + sync_file = sync_file_alloc(); if (!sync_file) return NULL; + sync_file->fence = fence; sync_file->num_fences = 1; + atomic_set(&sync_file->status, 1); snprintf(sync_file->name, sizeof(sync_file->name), "%s-%s%llu-%d", fence->ops->get_driver_name(fence), fence->ops->get_timeline_name(fence), fence->context, fence->seqno); - sync_file->cbs[0].fence = fence; - sync_file->cbs[0].sync_file = sync_file; - if (fence_add_callback(fence, &sync_file->cbs[0].cb, - fence_check_cb_func)) + if (fence_add_callback(fence, &sync_file->cb, fence_check_cb_func)) atomic_dec(&sync_file->status); return sync_file; @@ -121,14 +121,31 @@ err: return NULL; } -static void sync_file_add_pt(struct sync_file *sync_file, int *i, +static int sync_file_set_fence(struct sync_file *sync_file, + struct fence **fences) +{ + struct fence_array *array; + + if (sync_file->num_fences == 1) { + sync_file->fence = fences[0]; + } else { + array = fence_array_create(sync_file->num_fences, fences, + fence_context_alloc(1), 1, false); + if (!array) + return -ENOMEM; + + sync_file->fence = &array->base; + } + + return 0; +} + +static void fences_add_fence(struct fence **fences, int *i, struct fence *fence) { - sync_file->cbs[*i].fence = fence; - sync_file->cbs[*i].sync_file = sync_file; + fences[*i] = fence; - if (!fence_add_callback(fence, &sync_file->cbs[*i].cb, - fence_check_cb_func)) { + if (!fence_is_signaled(fence)) { fence_get(fence); (*i)++; } @@ -149,14 +166,31 @@ static struct sync_file *sync_file_merge(const char *name, struct sync_file *a, { int num_fences = a->num_fences + b->num_fences; struct sync_file *sync_file; + struct fence **fences, **a_fences, **b_fences; int i, i_a, i_b; - unsigned long size = offsetof(struct sync_file, cbs[num_fences]); - sync_file = sync_file_alloc(size); + sync_file = sync_file_alloc(); if (!sync_file) return NULL; - atomic_set(&sync_file->status, num_fences); + fences = kcalloc(num_fences, sizeof(**fences), GFP_KERNEL); + if (!fences) + goto err; + + atomic_set(&sync_file->status, 1); + + a_fences = fence_get_fences(a->fence); + if (!a_fences) { + kfree(fences); + goto err; + } + + b_fences = fence_get_fences(b->fence); + if (!b_fences) { + kfree(a_fences); + kfree(fences); + goto err; + } /* * Assume sync_file a and b are both ordered and have no @@ -166,22 +200,22 @@ static struct sync_file *sync_file_merge(const char *name, struct sync_file *a, * and sync_file_create, this is a reasonable assumption. */ for (i = i_a = i_b = 0; i_a < a->num_fences && i_b < b->num_fences; ) { - struct fence *pt_a = a->cbs[i_a].fence; - struct fence *pt_b = b->cbs[i_b].fence; + struct fence *pt_a = a_fences[i_a]; + struct fence *pt_b = b_fences[i_b]; if (pt_a->context < pt_b->context) { - sync_file_add_pt(sync_file, &i, pt_a); + fences_add_fence(fences, &i, pt_a); i_a++; } else if (pt_a->context > pt_b->context) { - sync_file_add_pt(sync_file, &i, pt_b); + fences_add_fence(fences, &i, pt_b); i_b++; } else { if (pt_a->seqno - pt_b->seqno <= INT_MAX) - sync_file_add_pt(sync_file, &i, pt_a); + fences_add_fence(fences, &i, pt_a); else - sync_file_add_pt(sync_file, &i, pt_b); + fences_add_fence(fences, &i, pt_b); i_a++; i_b++; @@ -189,31 +223,49 @@ static struct sync_file *sync_file_merge(const char *name, struct sync_file *a, } for (; i_a < a->num_fences; i_a++) - sync_file_add_pt(sync_file, &i, a->cbs[i_a].fence); + fences_add_fence(fences, &i, a_fences[i_a]); for (; i_b < b->num_fences; i_b++) - sync_file_add_pt(sync_file, &i, b->cbs[i_b].fence); + fences_add_fence(fences, &i, b_fences[i_b]); - if (num_fences > i) - atomic_sub(num_fences - i, &sync_file->status); + if (num_fences > i) { + fences = krealloc(fences, i * sizeof(**fences), + GFP_KERNEL); + if (!fences) + goto ab_err; + } sync_file->num_fences = i; + if (sync_file_set_fence(sync_file, fences) < 0) { + kfree(fences); + goto ab_err; + } + + if (fence_add_callback(sync_file->fence, &sync_file->cb, + fence_check_cb_func)) + atomic_dec(&sync_file->status); + strlcpy(sync_file->name, name, sizeof(sync_file->name)); return sync_file; + +ab_err: + kfree(a_fences); + kfree(b_fences); + +err: + fput(sync_file->file); + return NULL; + } static void sync_file_free(struct kref *kref) { struct sync_file *sync_file = container_of(kref, struct sync_file, kref); - int i; - - for (i = 0; i < sync_file->num_fences; ++i) { - fence_remove_callback(sync_file->cbs[i].fence, - &sync_file->cbs[i].cb); - fence_put(sync_file->cbs[i].fence); - } + fence_remove_callback(sync_file->fence, &sync_file->cb); + fence_teardown(sync_file->fence); + fence_put(sync_file->fence); kfree(sync_file); } @@ -315,6 +367,7 @@ static long sync_file_ioctl_fence_info(struct sync_file *sync_file, { struct sync_file_info info; struct sync_fence_info *fence_info = NULL; + struct fence **fences; __u32 size; int ret, i; @@ -341,8 +394,10 @@ static long sync_file_ioctl_fence_info(struct sync_file *sync_file, if (!fence_info) return -ENOMEM; - for (i = 0; i < sync_file->num_fences; ++i) - sync_fill_fence_info(sync_file->cbs[i].fence, &fence_info[i]); + fences = fence_get_fences(sync_file->fence); + for (i = 0; i < sync_file->num_fences; i++) + sync_fill_fence_info(fences[i], &fence_info[i]); + kfree(fences); if (copy_to_user(u64_to_user_ptr(info.sync_fence_info), fence_info, size)) { diff --git a/drivers/staging/android/sync_debug.c b/drivers/staging/android/sync_debug.c index 5f57499..5fb6d3d 100644 --- a/drivers/staging/android/sync_debug.c +++ b/drivers/staging/android/sync_debug.c @@ -156,13 +156,16 @@ static void sync_print_obj(struct seq_file *s, struct sync_timeline *obj) static void sync_print_sync_file(struct seq_file *s, struct sync_file *sync_file) { + struct fence **fences; int i; seq_printf(s, "[%p] %s: %s\n", sync_file, sync_file->name, sync_status_str(atomic_read(&sync_file->status))); + fences = fence_get_fences(sync_file->fence); for (i = 0; i < sync_file->num_fences; ++i) - sync_print_fence(s, sync_file->cbs[i].fence, true); + sync_print_fence(s, fences[i], true); + kfree(fences); } static int sync_debugfs_show(struct seq_file *s, void *unused) diff --git a/include/linux/sync_file.h b/include/linux/sync_file.h index c6ffe8b..d13885f 100644 --- a/include/linux/sync_file.h +++ b/include/linux/sync_file.h @@ -20,12 +20,6 @@ #include <linux/spinlock.h> #include <linux/fence.h> -struct sync_file_cb { - struct fence_cb cb; - struct fence *fence; - struct sync_file *sync_file; -}; - /** * struct sync_file - sync file to export to the userspace * @file: file representing this fence @@ -35,7 +29,8 @@ struct sync_file_cb { * @num_fences: number of sync_pts in the fence * @wq: wait queue for fence signaling * @status: 0: signaled, >0:active, <0: error - * @cbs: sync_pts callback information + * @fence: fence with the fences in the sync_file + * @cb: fence callback information */ struct sync_file { struct file *file; @@ -49,7 +44,8 @@ struct sync_file { wait_queue_head_t wq; atomic_t status; - struct sync_file_cb cbs[]; + struct fence *fence; + struct fence_cb cb; }; struct sync_file *sync_file_create(struct fence *fence); -- 2.5.5 _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/dri-devel