All of lore.kernel.org
 help / color / mirror / Atom feed
From: Gustavo Padovan <gustavo@padovan.org>
To: dri-devel@lists.freedesktop.org
Cc: linux-kernel@vger.kernel.org,
	Daniel Stone <daniels@collabora.com>,
	Daniel Vetter <daniel.vetter@ffwll.ch>,
	Rob Clark <robdclark@gmail.com>,
	Greg Hackmann <ghackmann@google.com>,
	John Harrison <John.C.Harrison@Intel.com>,
	laurent.pinchart@ideasonboard.com, seanpaul@google.com,
	marcheu@google.com, m.chehab@samsung.com,
	Sumit Semwal <sumit.semwal@linaro.org>,
	Maarten Lankhorst <maarten.lankhorst@linux.intel.com>,
	Gustavo Padovan <gustavo.padovan@collabora.co.uk>
Subject: [RFC 5/5] dma-buf/sync_file: rework fence storage in struct file
Date: Thu, 23 Jun 2016 12:29:50 -0300	[thread overview]
Message-ID: <1466695790-2833-6-git-send-email-gustavo@padovan.org> (raw)
In-Reply-To: <1466695790-2833-1-git-send-email-gustavo@padovan.org>

From: Gustavo Padovan <gustavo.padovan@collabora.co.uk>

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@collabora.co.uk>
---
 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

  parent reply	other threads:[~2016-06-23 15:30 UTC|newest]

Thread overview: 35+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-06-23 15:29 [RFC 0/5] rework fences on struct sync_file Gustavo Padovan
2016-06-23 15:29 ` Gustavo Padovan
2016-06-23 15:29 ` [RFC 1/5] dma-buf/fence: add .teardown() ops Gustavo Padovan
2016-06-23 20:48   ` Chris Wilson
2016-06-23 20:48     ` Chris Wilson
2016-06-24 13:19     ` Gustavo Padovan
2016-06-24 13:19       ` Gustavo Padovan
2016-07-12 10:51       ` Daniel Vetter
2016-07-12 10:51         ` Daniel Vetter
2016-06-23 15:29 ` [RFC 2/5] dma-buf/fence-array: add fence_array_teardown() Gustavo Padovan
2016-06-23 15:29   ` Gustavo Padovan
2016-06-23 15:29 ` [RFC 3/5] dma-buf/fence: add .get_fences() ops Gustavo Padovan
2016-06-23 15:29   ` Gustavo Padovan
2016-06-23 20:40   ` Chris Wilson
2016-06-23 20:40     ` Chris Wilson
2016-07-12 10:52   ` Daniel Vetter
2016-07-12 10:52     ` Daniel Vetter
2016-06-23 15:29 ` [RFC 4/5] dma-buf/fence-array: add fence_array_get_fences() Gustavo Padovan
2016-06-23 20:35   ` Chris Wilson
2016-06-23 20:35     ` Chris Wilson
2016-06-23 15:29 ` Gustavo Padovan [this message]
2016-06-23 21:27   ` [RFC 5/5] dma-buf/sync_file: rework fence storage in struct file Chris Wilson
2016-06-23 21:27     ` Chris Wilson
2016-06-24 13:23     ` Gustavo Padovan
2016-06-24 13:23       ` Gustavo Padovan
2016-06-24  9:27 ` [RFC 0/5] rework fences on struct sync_file Christian König
2016-06-24  9:27   ` Christian König
2016-06-24 13:17   ` Gustavo Padovan
2016-06-24 13:17     ` Gustavo Padovan
2016-06-24 14:14     ` Christian König
2016-06-24 14:14       ` Christian König
2016-06-24 14:59       ` Gustavo Padovan
2016-06-24 15:09         ` Christian König
2016-06-24 15:09           ` Christian König
2016-06-24 15:19           ` Gustavo Padovan

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1466695790-2833-6-git-send-email-gustavo@padovan.org \
    --to=gustavo@padovan.org \
    --cc=John.C.Harrison@Intel.com \
    --cc=daniel.vetter@ffwll.ch \
    --cc=daniels@collabora.com \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=ghackmann@google.com \
    --cc=gustavo.padovan@collabora.co.uk \
    --cc=laurent.pinchart@ideasonboard.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=m.chehab@samsung.com \
    --cc=maarten.lankhorst@linux.intel.com \
    --cc=marcheu@google.com \
    --cc=robdclark@gmail.com \
    --cc=seanpaul@google.com \
    --cc=sumit.semwal@linaro.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.