Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1318950 > unrolled thread
| Started by | Gustavo Padovan <gustavo@padovan.org> |
|---|---|
| First post | 2016-01-27 14:40 +0100 |
| Last post | 2016-01-29 18:50 +0100 |
| Articles | 8 — 5 participants |
Back to article view | Back to linux.kernel
This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by
below is the oldest one visible, not the original post.
[PATCH v2 01/11] dma-buf/sync_file: de-stage sync_file Gustavo Padovan <gustavo@padovan.org> - 2016-01-27 14:40 +0100
Re: [PATCH v2 01/11] dma-buf/sync_file: de-stage sync_file Maarten Lankhorst <maarten.lankhorst@linux.intel.com> - 2016-01-27 15:40 +0100
Re: [PATCH v2 01/11] dma-buf/sync_file: de-stage sync_file Gustavo Padovan <gustavo@padovan.org> - 2016-01-27 18:10 +0100
Re: [PATCH v2 01/11] dma-buf/sync_file: de-stage sync_file Emil Velikov <emil.l.velikov@gmail.com> - 2016-01-27 19:20 +0100
Re: [PATCH v2 01/11] dma-buf/sync_file: de-stage sync_file Gustavo Padovan <gustavo@padovan.org> - 2016-01-27 21:30 +0100
Re: [PATCH v2 01/11] dma-buf/sync_file: de-stage sync_file Greg Hackmann <ghackmann@google.com> - 2016-01-27 22:50 +0100
Re: [PATCH v2 01/11] dma-buf/sync_file: de-stage sync_file Daniel Vetter <daniel@ffwll.ch> - 2016-01-28 10:30 +0100
Re: [PATCH v2 01/11] dma-buf/sync_file: de-stage sync_file Greg Hackmann <ghackmann@google.com> - 2016-01-29 18:50 +0100
| From | Gustavo Padovan <gustavo@padovan.org> |
|---|---|
| Date | 2016-01-27 14:40 +0100 |
| Subject | [PATCH v2 01/11] dma-buf/sync_file: de-stage sync_file |
| Message-ID | <qVyue-49M-5@gated-at.bofh.it> |
From: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
sync_file is useful to connect one or more fences to the file. The file is
used by userspace to track fences.
Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
---
drivers/Kconfig | 2 +
drivers/dma-buf/Kconfig | 11 +
drivers/dma-buf/Makefile | 1 +
drivers/dma-buf/sync_file.c | 440 +++++++++++++++++++++
drivers/staging/android/Kconfig | 1 +
drivers/staging/android/sync.c | 419 --------------------
drivers/staging/android/sync.h | 105 +----
drivers/staging/android/sync_debug.c | 1 +
drivers/staging/android/trace/sync.h | 44 ---
include/linux/sync_file.h | 123 ++++++
include/trace/events/sync_file.h | 57 +++
.../android/uapi => include/uapi/linux}/sync.h | 12 +-
12 files changed, 644 insertions(+), 572 deletions(-)
create mode 100644 drivers/dma-buf/Kconfig
create mode 100644 drivers/dma-buf/sync_file.c
create mode 100644 include/linux/sync_file.h
create mode 100644 include/trace/events/sync_file.h
rename {drivers/staging/android/uapi => include/uapi/linux}/sync.h (90%)
diff --git a/drivers/Kconfig b/drivers/Kconfig
index d2ac339..430f761 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -114,6 +114,8 @@ source "drivers/rtc/Kconfig"
source "drivers/dma/Kconfig"
+source "drivers/dma-buf/Kconfig"
+
source "drivers/dca/Kconfig"
source "drivers/auxdisplay/Kconfig"
diff --git a/drivers/dma-buf/Kconfig b/drivers/dma-buf/Kconfig
new file mode 100644
index 0000000..9824bc4
--- /dev/null
+++ b/drivers/dma-buf/Kconfig
@@ -0,0 +1,11 @@
+menu "DMABUF options"
+
+config SYNC_FILE
+ bool "sync_file support for fences"
+ default n
+ select ANON_INODES
+ select DMA_SHARED_BUFFER
+ ---help---
+ This option enables the fence framework synchronization to export
+ sync_files to userspace that can represent one or more fences.
+endmenu
diff --git a/drivers/dma-buf/Makefile b/drivers/dma-buf/Makefile
index 57a675f..4a424ec 100644
--- a/drivers/dma-buf/Makefile
+++ b/drivers/dma-buf/Makefile
@@ -1 +1,2 @@
obj-y := dma-buf.o fence.o reservation.o seqno-fence.o
+obj-$(CONFIG_SYNC_FILE) += sync_file.o
diff --git a/drivers/dma-buf/sync_file.c b/drivers/dma-buf/sync_file.c
new file mode 100644
index 0000000..92474dd
--- /dev/null
+++ b/drivers/dma-buf/sync_file.c
@@ -0,0 +1,440 @@
+/*
+ * drivers/dma-buf/sync_file.c
+ *
+ * Copyright (C) 2012 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/export.h>
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/poll.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include <linux/anon_inodes.h>
+#include <linux/sync_file.h>
+#include <uapi/linux/sync.h>
+
+#define CREATE_TRACE_POINTS
+#include <trace/events/sync_file.h>
+
+static const struct file_operations sync_file_fops;
+
+static struct sync_file *sync_file_alloc(int size, const char *name)
+{
+ struct sync_file *sync_file;
+
+ sync_file = kzalloc(size, GFP_KERNEL);
+ if (!sync_file)
+ return NULL;
+
+ sync_file->file = anon_inode_getfile("sync_file", &sync_file_fops,
+ sync_file, 0);
+ if (IS_ERR(sync_file->file))
+ goto err;
+
+ kref_init(&sync_file->kref);
+ strlcpy(sync_file->name, name, sizeof(sync_file->name));
+
+ init_waitqueue_head(&sync_file->wq);
+
+ return sync_file;
+
+err:
+ kfree(sync_file);
+ return NULL;
+}
+
+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;
+
+ if (atomic_dec_and_test(&sync_file->status))
+ wake_up_all(&sync_file->wq);
+}
+
+/* TODO: implement a create which takes more that one fence */
+struct sync_file *sync_file_create(const char *name, struct fence *fence)
+{
+ struct sync_file *sync_file;
+
+ sync_file = sync_file_alloc(offsetof(struct sync_file, cbs[1]),
+ name);
+ if (!sync_file)
+ return NULL;
+
+ sync_file->num_fences = 1;
+ atomic_set(&sync_file->status, 1);
+
+ 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))
+ atomic_dec(&sync_file->status);
+
+ return sync_file;
+}
+EXPORT_SYMBOL(sync_file_create);
+
+struct sync_file *sync_file_fdget(int fd)
+{
+ struct file *file = fget(fd);
+
+ if (!file)
+ return NULL;
+
+ if (file->f_op != &sync_file_fops)
+ goto err;
+
+ return file->private_data;
+
+err:
+ fput(file);
+ return NULL;
+}
+EXPORT_SYMBOL(sync_file_fdget);
+
+void sync_file_put(struct sync_file *sync_file)
+{
+ fput(sync_file->file);
+}
+EXPORT_SYMBOL(sync_file_put);
+
+void sync_file_install(struct sync_file *sync_file, int fd)
+{
+ fd_install(fd, sync_file->file);
+}
+EXPORT_SYMBOL(sync_file_install);
+
+static void sync_file_add_fence(struct sync_file *sync_file, int *i,
+ struct fence *fence)
+{
+ sync_file->cbs[*i].fence = fence;
+ sync_file->cbs[*i].sync_file = sync_file;
+
+ if (!fence_add_callback(fence, &sync_file->cbs[*i].cb,
+ fence_check_cb_func)) {
+ fence_get(fence);
+ (*i)++;
+ }
+}
+
+struct sync_file *sync_file_merge(const char *name,
+ struct sync_file *a, struct sync_file *b)
+{
+ int num_fences = a->num_fences + b->num_fences;
+ struct sync_file *sync_file;
+ int i, i_a, i_b;
+ unsigned long size = offsetof(struct sync_file, cbs[num_fences]);
+
+ sync_file = sync_file_alloc(size, name);
+ if (!sync_file)
+ return NULL;
+
+ atomic_set(&sync_file->status, num_fences);
+
+ /*
+ * Assume sync_file a and b are both ordered and have no
+ * duplicates with the same context.
+ *
+ * If a sync_file can only be created with sync_file_merge
+ * 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;
+
+ if (pt_a->context < pt_b->context) {
+ sync_file_add_fence(sync_file, &i, pt_a);
+
+ i_a++;
+ } else if (pt_a->context > pt_b->context) {
+ sync_file_add_fence(sync_file, &i, pt_b);
+
+ i_b++;
+ } else {
+ if (pt_a->seqno - pt_b->seqno <= INT_MAX)
+ sync_file_add_fence(sync_file, &i, pt_a);
+ else
+ sync_file_add_fence(sync_file, &i, pt_b);
+
+ i_a++;
+ i_b++;
+ }
+ }
+
+ for (; i_a < a->num_fences; i_a++)
+ sync_file_add_fence(sync_file, &i, a->cbs[i_a].fence);
+
+ for (; i_b < b->num_fences; i_b++)
+ sync_file_add_fence(sync_file, &i, b->cbs[i_b].fence);
+
+ if (num_fences > i)
+ atomic_sub(num_fences - i, &sync_file->status);
+ sync_file->num_fences = i;
+
+ return sync_file;
+}
+EXPORT_SYMBOL(sync_file_merge);
+
+int sync_file_wait(struct sync_file *sync_file, long timeout)
+{
+ long ret;
+ int i;
+
+ if (timeout < 0)
+ timeout = MAX_SCHEDULE_TIMEOUT;
+ else
+ timeout = msecs_to_jiffies(timeout);
+
+ trace_sync_wait(sync_file, 1);
+ for (i = 0; i < sync_file->num_fences; ++i)
+ trace_fence(sync_file->cbs[i].fence);
+ ret = wait_event_interruptible_timeout(sync_file->wq,
+ atomic_read(&sync_file->status) <= 0,
+ timeout);
+ trace_sync_wait(sync_file, 0);
+
+ if (ret < 0) {
+ return ret;
+ } else if (ret == 0) {
+ if (timeout)
+ pr_info("sync_file timeout on [%p] after %dms\n",
+ sync_file, jiffies_to_msecs(timeout));
+ return -ETIME;
+ }
+
+ ret = atomic_read(&sync_file->status);
+ if (ret)
+ pr_info("sync_file error %ld on [%p]\n", ret, sync_file);
+
+ return ret;
+}
+EXPORT_SYMBOL(sync_file_wait);
+
+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);
+ }
+
+ kfree(sync_file);
+}
+
+static int sync_file_release(struct inode *inode, struct file *file)
+{
+ struct sync_file *sync_file = file->private_data;
+
+ kref_put(&sync_file->kref, sync_file_free);
+ return 0;
+}
+
+static unsigned int sync_file_poll(struct file *file, poll_table *wait)
+{
+ struct sync_file *sync_file = file->private_data;
+ int status;
+
+ poll_wait(file, &sync_file->wq, wait);
+
+ status = atomic_read(&sync_file->status);
+
+ if (!status)
+ return POLLIN;
+ else if (status < 0)
+ return POLLERR;
+ return 0;
+}
+
+static long sync_file_ioctl_wait(struct sync_file *sync_file,
+ unsigned long arg)
+{
+ __s32 value;
+
+ if (copy_from_user(&value, (void __user *)arg, sizeof(value)))
+ return -EFAULT;
+
+ return sync_file_wait(sync_file, value);
+}
+
+static long sync_file_ioctl_merge(struct sync_file *sync_file,
+ unsigned long arg)
+{
+ int fd = get_unused_fd_flags(O_CLOEXEC);
+ int err;
+ struct sync_file *fence2, *fence3;
+ struct sync_merge_data data;
+
+ if (fd < 0)
+ return fd;
+
+ if (copy_from_user(&data, (void __user *)arg, sizeof(data))) {
+ err = -EFAULT;
+ goto err_put_fd;
+ }
+
+ fence2 = sync_file_fdget(data.fd2);
+ if (!fence2) {
+ err = -ENOENT;
+ goto err_put_fd;
+ }
+
+ data.name[sizeof(data.name) - 1] = '\0';
+ fence3 = sync_file_merge(data.name, sync_file, fence2);
+ if (!fence3) {
+ err = -ENOMEM;
+ goto err_put_fence2;
+ }
+
+ data.fence = fd;
+ if (copy_to_user((void __user *)arg, &data, sizeof(data))) {
+ err = -EFAULT;
+ goto err_put_fence3;
+ }
+
+ sync_file_install(fence3, fd);
+ sync_file_put(fence2);
+ return 0;
+
+err_put_fence3:
+ sync_file_put(fence3);
+
+err_put_fence2:
+ sync_file_put(fence2);
+
+err_put_fd:
+ put_unused_fd(fd);
+ return err;
+}
+
+static int sync_fill_pt_info(struct fence *fence, void *data, int size)
+{
+ struct fence_info *info = data;
+ int ret;
+
+ if (size < sizeof(struct fence_info))
+ return -ENOMEM;
+
+ info->len = sizeof(struct fence_info);
+
+ if (fence->ops->fill_driver_data) {
+ ret = fence->ops->fill_driver_data(fence, info->driver_data,
+ size - sizeof(*info));
+ if (ret < 0)
+ return ret;
+
+ info->len += ret;
+ }
+
+ strlcpy(info->obj_name, fence->ops->get_timeline_name(fence),
+ sizeof(info->obj_name));
+ strlcpy(info->driver_name, fence->ops->get_driver_name(fence),
+ sizeof(info->driver_name));
+ if (fence_is_signaled(fence))
+ info->status = fence->status >= 0 ? 1 : fence->status;
+ else
+ info->status = 0;
+ info->timestamp_ns = ktime_to_ns(fence->timestamp);
+
+ return info->len;
+}
+
+static long sync_file_ioctl_fence_info(struct sync_file *sync_file,
+ unsigned long arg)
+{
+ struct sync_file_info_data *data;
+ __u32 size;
+ __u32 len = 0;
+ int ret, i;
+
+ if (copy_from_user(&size, (void __user *)arg, sizeof(size)))
+ return -EFAULT;
+
+ if (size < sizeof(struct sync_file_info_data))
+ return -EINVAL;
+
+ if (size > 4096)
+ size = 4096;
+
+ data = kzalloc(size, GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ strlcpy(data->name, sync_file->name, sizeof(data->name));
+ data->status = atomic_read(&sync_file->status);
+ if (data->status >= 0)
+ data->status = !data->status;
+
+ len = sizeof(struct sync_file_info_data);
+
+ for (i = 0; i < sync_file->num_fences; ++i) {
+ struct fence *fence = sync_file->cbs[i].fence;
+
+ ret = sync_fill_pt_info(fence, (u8 *)data + len, size - len);
+
+ if (ret < 0)
+ goto out;
+
+ len += ret;
+ }
+
+ data->len = len;
+
+ if (copy_to_user((void __user *)arg, data, len))
+ ret = -EFAULT;
+ else
+ ret = 0;
+
+out:
+ kfree(data);
+
+ return ret;
+}
+
+static long sync_file_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ struct sync_file *sync_file = file->private_data;
+
+ switch (cmd) {
+ case SYNC_IOC_WAIT:
+ return sync_file_ioctl_wait(sync_file, arg);
+
+ case SYNC_IOC_MERGE:
+ return sync_file_ioctl_merge(sync_file, arg);
+
+ case SYNC_IOC_FENCE_INFO:
+ return sync_file_ioctl_fence_info(sync_file, arg);
+
+ default:
+ return -ENOTTY;
+ }
+}
+
+static const struct file_operations sync_file_fops = {
+ .release = sync_file_release,
+ .poll = sync_file_poll,
+ .unlocked_ioctl = sync_file_ioctl,
+ .compat_ioctl = sync_file_ioctl,
+};
+
diff --git a/drivers/staging/android/Kconfig b/drivers/staging/android/Kconfig
index bd90d20..2756988 100644
--- a/drivers/staging/android/Kconfig
+++ b/drivers/staging/android/Kconfig
@@ -52,6 +52,7 @@ config SW_SYNC
bool "Software synchronization objects"
default n
depends on SYNC
+ depends on SYNC_FILE
---help---
A sync object driver that uses a 32bit counter to coordinate
synchronization. Useful when there is no hardware primitive backing
diff --git a/drivers/staging/android/sync.c b/drivers/staging/android/sync.c
index 5fa4779..1e1c009 100644
--- a/drivers/staging/android/sync.c
+++ b/drivers/staging/android/sync.c
@@ -16,10 +16,7 @@
#include <linux/debugfs.h>
#include <linux/export.h>
-#include <linux/file.h>
-#include <linux/fs.h>
#include <linux/kernel.h>
-#include <linux/poll.h>
#include <linux/sched.h>
#include <linux/seq_file.h>
#include <linux/slab.h>
@@ -32,7 +29,6 @@
#include "trace/sync.h"
static const struct fence_ops android_fence_ops;
-static const struct file_operations sync_file_fops;
struct sync_timeline *sync_timeline_create(const struct sync_timeline_ops *ops,
int size, const char *name)
@@ -136,208 +132,6 @@ struct fence *sync_pt_create(struct sync_timeline *obj, int size)
}
EXPORT_SYMBOL(sync_pt_create);
-static struct sync_file *sync_file_alloc(int size, const char *name)
-{
- struct sync_file *sync_file;
-
- sync_file = kzalloc(size, GFP_KERNEL);
- if (!sync_file)
- return NULL;
-
- sync_file->file = anon_inode_getfile("sync_file", &sync_file_fops,
- sync_file, 0);
- if (IS_ERR(sync_file->file))
- goto err;
-
- kref_init(&sync_file->kref);
- strlcpy(sync_file->name, name, sizeof(sync_file->name));
-
- init_waitqueue_head(&sync_file->wq);
-
- return sync_file;
-
-err:
- kfree(sync_file);
- return NULL;
-}
-
-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;
-
- if (atomic_dec_and_test(&sync_file->status))
- wake_up_all(&sync_file->wq);
-}
-
-/* TODO: implement a create which takes more that one fence */
-struct sync_file *sync_file_create(const char *name, struct fence *fence)
-{
- struct sync_file *sync_file;
-
- sync_file = sync_file_alloc(offsetof(struct sync_file, cbs[1]),
- name);
- if (!sync_file)
- return NULL;
-
- sync_file->num_fences = 1;
- atomic_set(&sync_file->status, 1);
-
- 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))
- atomic_dec(&sync_file->status);
-
- sync_file_debug_add(sync_file);
-
- return sync_file;
-}
-EXPORT_SYMBOL(sync_file_create);
-
-struct sync_file *sync_file_fdget(int fd)
-{
- struct file *file = fget(fd);
-
- if (!file)
- return NULL;
-
- if (file->f_op != &sync_file_fops)
- goto err;
-
- return file->private_data;
-
-err:
- fput(file);
- return NULL;
-}
-EXPORT_SYMBOL(sync_file_fdget);
-
-void sync_file_put(struct sync_file *sync_file)
-{
- fput(sync_file->file);
-}
-EXPORT_SYMBOL(sync_file_put);
-
-void sync_file_install(struct sync_file *sync_file, int fd)
-{
- fd_install(fd, sync_file->file);
-}
-EXPORT_SYMBOL(sync_file_install);
-
-static void sync_file_add_pt(struct sync_file *sync_file, int *i,
- struct fence *fence)
-{
- sync_file->cbs[*i].fence = fence;
- sync_file->cbs[*i].sync_file = sync_file;
-
- if (!fence_add_callback(fence, &sync_file->cbs[*i].cb,
- fence_check_cb_func)) {
- fence_get(fence);
- (*i)++;
- }
-}
-
-struct sync_file *sync_file_merge(const char *name,
- struct sync_file *a, struct sync_file *b)
-{
- int num_fences = a->num_fences + b->num_fences;
- struct sync_file *sync_file;
- int i, i_a, i_b;
- unsigned long size = offsetof(struct sync_file, cbs[num_fences]);
-
- sync_file = sync_file_alloc(size, name);
- if (!sync_file)
- return NULL;
-
- atomic_set(&sync_file->status, num_fences);
-
- /*
- * Assume sync_file a and b are both ordered and have no
- * duplicates with the same context.
- *
- * If a sync_file can only be created with sync_file_merge
- * 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;
-
- if (pt_a->context < pt_b->context) {
- sync_file_add_pt(sync_file, &i, pt_a);
-
- i_a++;
- } else if (pt_a->context > pt_b->context) {
- sync_file_add_pt(sync_file, &i, pt_b);
-
- i_b++;
- } else {
- if (pt_a->seqno - pt_b->seqno <= INT_MAX)
- sync_file_add_pt(sync_file, &i, pt_a);
- else
- sync_file_add_pt(sync_file, &i, pt_b);
-
- i_a++;
- i_b++;
- }
- }
-
- for (; i_a < a->num_fences; i_a++)
- sync_file_add_pt(sync_file, &i, a->cbs[i_a].fence);
-
- for (; i_b < b->num_fences; i_b++)
- sync_file_add_pt(sync_file, &i, b->cbs[i_b].fence);
-
- if (num_fences > i)
- atomic_sub(num_fences - i, &sync_file->status);
- sync_file->num_fences = i;
-
- sync_file_debug_add(sync_file);
- return sync_file;
-}
-EXPORT_SYMBOL(sync_file_merge);
-
-int sync_file_wait(struct sync_file *sync_file, long timeout)
-{
- long ret;
- int i;
-
- if (timeout < 0)
- timeout = MAX_SCHEDULE_TIMEOUT;
- else
- timeout = msecs_to_jiffies(timeout);
-
- trace_sync_wait(sync_file, 1);
- for (i = 0; i < sync_file->num_fences; ++i)
- trace_fence(sync_file->cbs[i].fence);
- ret = wait_event_interruptible_timeout(sync_file->wq,
- atomic_read(&sync_file->status) <= 0,
- timeout);
- trace_sync_wait(sync_file, 0);
-
- if (ret < 0) {
- return ret;
- } else if (ret == 0) {
- if (timeout) {
- pr_info("sync_file timeout on [%p] after %dms\n",
- sync_file, jiffies_to_msecs(timeout));
- sync_dump();
- }
- return -ETIME;
- }
-
- ret = atomic_read(&sync_file->status);
- if (ret) {
- pr_info("sync_file error %ld on [%p]\n", ret, sync_file);
- sync_dump();
- }
- return ret;
-}
-EXPORT_SYMBOL(sync_file_wait);
-
static const char *android_fence_get_driver_name(struct fence *fence)
{
struct sync_timeline *parent = fence_parent(fence);
@@ -437,216 +231,3 @@ static const struct fence_ops android_fence_ops = {
.timeline_value_str = android_fence_timeline_value_str,
};
-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);
- }
-
- kfree(sync_file);
-}
-
-static int sync_file_release(struct inode *inode, struct file *file)
-{
- struct sync_file *sync_file = file->private_data;
-
- sync_file_debug_remove(sync_file);
-
- kref_put(&sync_file->kref, sync_file_free);
- return 0;
-}
-
-static unsigned int sync_file_poll(struct file *file, poll_table *wait)
-{
- struct sync_file *sync_file = file->private_data;
- int status;
-
- poll_wait(file, &sync_file->wq, wait);
-
- status = atomic_read(&sync_file->status);
-
- if (!status)
- return POLLIN;
- else if (status < 0)
- return POLLERR;
- return 0;
-}
-
-static long sync_file_ioctl_wait(struct sync_file *sync_file,
- unsigned long arg)
-{
- __s32 value;
-
- if (copy_from_user(&value, (void __user *)arg, sizeof(value)))
- return -EFAULT;
-
- return sync_file_wait(sync_file, value);
-}
-
-static long sync_file_ioctl_merge(struct sync_file *sync_file,
- unsigned long arg)
-{
- int fd = get_unused_fd_flags(O_CLOEXEC);
- int err;
- struct sync_file *fence2, *fence3;
- struct sync_merge_data data;
-
- if (fd < 0)
- return fd;
-
- if (copy_from_user(&data, (void __user *)arg, sizeof(data))) {
- err = -EFAULT;
- goto err_put_fd;
- }
-
- fence2 = sync_file_fdget(data.fd2);
- if (!fence2) {
- err = -ENOENT;
- goto err_put_fd;
- }
-
- data.name[sizeof(data.name) - 1] = '\0';
- fence3 = sync_file_merge(data.name, sync_file, fence2);
- if (!fence3) {
- err = -ENOMEM;
- goto err_put_fence2;
- }
-
- data.fence = fd;
- if (copy_to_user((void __user *)arg, &data, sizeof(data))) {
- err = -EFAULT;
- goto err_put_fence3;
- }
-
- sync_file_install(fence3, fd);
- sync_file_put(fence2);
- return 0;
-
-err_put_fence3:
- sync_file_put(fence3);
-
-err_put_fence2:
- sync_file_put(fence2);
-
-err_put_fd:
- put_unused_fd(fd);
- return err;
-}
-
-static int sync_fill_pt_info(struct fence *fence, void *data, int size)
-{
- struct sync_pt_info *info = data;
- int ret;
-
- if (size < sizeof(struct sync_pt_info))
- return -ENOMEM;
-
- info->len = sizeof(struct sync_pt_info);
-
- if (fence->ops->fill_driver_data) {
- ret = fence->ops->fill_driver_data(fence, info->driver_data,
- size - sizeof(*info));
- if (ret < 0)
- return ret;
-
- info->len += ret;
- }
-
- strlcpy(info->obj_name, fence->ops->get_timeline_name(fence),
- sizeof(info->obj_name));
- strlcpy(info->driver_name, fence->ops->get_driver_name(fence),
- sizeof(info->driver_name));
- if (fence_is_signaled(fence))
- info->status = fence->status >= 0 ? 1 : fence->status;
- else
- info->status = 0;
- info->timestamp_ns = ktime_to_ns(fence->timestamp);
-
- return info->len;
-}
-
-static long sync_file_ioctl_fence_info(struct sync_file *sync_file,
- unsigned long arg)
-{
- struct sync_file_info_data *data;
- __u32 size;
- __u32 len = 0;
- int ret, i;
-
- if (copy_from_user(&size, (void __user *)arg, sizeof(size)))
- return -EFAULT;
-
- if (size < sizeof(struct sync_file_info_data))
- return -EINVAL;
-
- if (size > 4096)
- size = 4096;
-
- data = kzalloc(size, GFP_KERNEL);
- if (!data)
- return -ENOMEM;
-
- strlcpy(data->name, sync_file->name, sizeof(data->name));
- data->status = atomic_read(&sync_file->status);
- if (data->status >= 0)
- data->status = !data->status;
-
- len = sizeof(struct sync_file_info_data);
-
- for (i = 0; i < sync_file->num_fences; ++i) {
- struct fence *fence = sync_file->cbs[i].fence;
-
- ret = sync_fill_pt_info(fence, (u8 *)data + len, size - len);
-
- if (ret < 0)
- goto out;
-
- len += ret;
- }
-
- data->len = len;
-
- if (copy_to_user((void __user *)arg, data, len))
- ret = -EFAULT;
- else
- ret = 0;
-
-out:
- kfree(data);
-
- return ret;
-}
-
-static long sync_file_ioctl(struct file *file, unsigned int cmd,
- unsigned long arg)
-{
- struct sync_file *sync_file = file->private_data;
-
- switch (cmd) {
- case SYNC_IOC_WAIT:
- return sync_file_ioctl_wait(sync_file, arg);
-
- case SYNC_IOC_MERGE:
- return sync_file_ioctl_merge(sync_file, arg);
-
- case SYNC_IOC_FENCE_INFO:
- return sync_file_ioctl_fence_info(sync_file, arg);
-
- default:
- return -ENOTTY;
- }
-}
-
-static const struct file_operations sync_file_fops = {
- .release = sync_file_release,
- .poll = sync_file_poll,
- .unlocked_ioctl = sync_file_ioctl,
- .compat_ioctl = sync_file_ioctl,
-};
-
diff --git a/drivers/staging/android/sync.h b/drivers/staging/android/sync.h
index 8980b55..fb209fc 100644
--- a/drivers/staging/android/sync.h
+++ b/drivers/staging/android/sync.h
@@ -18,13 +18,11 @@
#include <linux/ktime.h>
#include <linux/list.h>
#include <linux/spinlock.h>
-#include <linux/wait.h>
#include <linux/fence.h>
-
-#include "uapi/sync.h"
+#include <linux/sync_file.h>
+#include <uapi/linux/sync.h>
struct sync_timeline;
-struct sync_file;
/**
* struct sync_timeline_ops - sync object implementation ops
@@ -94,38 +92,6 @@ static inline struct sync_timeline *fence_parent(struct fence *fence)
child_list_lock);
}
-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
- * @kref: reference count on fence.
- * @name: name of sync_file. Useful for debugging
- * @sync_file_list: membership in global file list
- * @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
- */
-struct sync_file {
- struct file *file;
- struct kref kref;
- char name[32];
-#ifdef CONFIG_DEBUG_FS
- struct list_head sync_file_list;
-#endif
- int num_fences;
-
- wait_queue_head_t wq;
- atomic_t status;
-
- struct sync_file_cb cbs[];
-};
-
/*
* API for sync_timeline implementers
*/
@@ -175,73 +141,6 @@ void sync_timeline_signal(struct sync_timeline *obj);
*/
struct fence *sync_pt_create(struct sync_timeline *parent, int size);
-/**
- * sync_fence_create() - creates a sync fence
- * @name: name of fence to create
- * @fence: fence to add to the sync_fence
- *
- * Creates a sync_file containg @fence. Once this is called, the sync_file
- * takes ownership of @fence.
- */
-struct sync_file *sync_file_create(const char *name, struct fence *fence);
-
-/*
- * API for sync_file consumers
- */
-
-/**
- * sync_file_merge() - merge two sync_files
- * @name: name of new fence
- * @a: sync_file a
- * @b: sync_file b
- *
- * Creates a new sync_file which contains copies of all the fences in both
- * @a and @b. @a and @b remain valid, independent sync_file. Returns the
- * new merged sync_file or NULL in case of error.
- */
-struct sync_file *sync_file_merge(const char *name,
- struct sync_file *a, struct sync_file *b);
-
-/**
- * sync_file_fdget() - get a sync_file from an fd
- * @fd: fd referencing a fence
- *
- * Ensures @fd references a valid sync_file, increments the refcount of the
- * backing file. Returns the sync_file or NULL in case of error.
- */
-struct sync_file *sync_file_fdget(int fd);
-
-/**
- * sync_file_put() - puts a reference of a sync_file
- * @sync_file: sync_file to put
- *
- * Puts a reference on @sync_fence. If this is the last reference, the
- * sync_fil and all it's sync_pts will be freed
- */
-void sync_file_put(struct sync_file *sync_file);
-
-/**
- * sync_file_install() - installs a sync_file into a file descriptor
- * @sync_file: sync_file to install
- * @fd: file descriptor in which to install the fence
- *
- * Installs @sync_file into @fd. @fd's should be acquired through
- * get_unused_fd_flags(O_CLOEXEC).
- */
-void sync_file_install(struct sync_file *sync_file, int fd);
-
-/**
- * sync_file_wait() - wait on sync file
- * @sync_file: file to wait on
- * @tiemout: timeout in ms
- *
- * Wait for @sync_file to be signaled or have an error. Waits indefinitely
- * if @timeout < 0.
- *
- * Returns 0 if fence signaled, > 0 if it is still active and <0 on error
- */
-int sync_file_wait(struct sync_file *sync_file, long timeout);
-
#ifdef CONFIG_DEBUG_FS
void sync_timeline_debug_add(struct sync_timeline *obj);
diff --git a/drivers/staging/android/sync_debug.c b/drivers/staging/android/sync_debug.c
index 7e53da7..b37412d 100644
--- a/drivers/staging/android/sync_debug.c
+++ b/drivers/staging/android/sync_debug.c
@@ -27,6 +27,7 @@
#include <linux/uaccess.h>
#include <linux/anon_inodes.h>
#include <linux/time64.h>
+#include <linux/sync_file.h>
#include "sw_sync.h"
#ifdef CONFIG_DEBUG_FS
diff --git a/drivers/staging/android/trace/sync.h b/drivers/staging/android/trace/sync.h
index 87c60e9..a0f80f4 100644
--- a/drivers/staging/android/trace/sync.h
+++ b/drivers/staging/android/trace/sync.h
@@ -32,50 +32,6 @@ TRACE_EVENT(sync_timeline,
TP_printk("name=%s value=%s", __get_str(name), __entry->value)
);
-TRACE_EVENT(sync_wait,
- TP_PROTO(struct sync_file *sync_file, int begin),
-
- TP_ARGS(sync_file, begin),
-
- TP_STRUCT__entry(
- __string(name, sync_file->name)
- __field(s32, status)
- __field(u32, begin)
- ),
-
- TP_fast_assign(
- __assign_str(name, sync_file->name);
- __entry->status = atomic_read(&sync_file->status);
- __entry->begin = begin;
- ),
-
- TP_printk("%s name=%s state=%d", __entry->begin ? "begin" : "end",
- __get_str(name), __entry->status)
-);
-
-TRACE_EVENT(fence,
- TP_PROTO(struct fence *fence),
-
- TP_ARGS(fence),
-
- TP_STRUCT__entry(
- __string(timeline, fence->ops->get_timeline_name(fence))
- __array(char, value, 32)
- ),
-
- TP_fast_assign(
- __assign_str(timeline, fence->ops->get_timeline_name(fence));
- if (fence->ops->fence_value_str) {
- fence->ops->fence_value_str(fence, __entry->value,
- sizeof(__entry->value));
- } else {
- __entry->value[0] = '\0';
- }
- ),
-
- TP_printk("name=%s value=%s", __get_str(timeline), __entry->value)
-);
-
#endif /* if !defined(_TRACE_SYNC_H) || defined(TRACE_HEADER_MULTI_READ) */
/* This part must be outside protection */
diff --git a/include/linux/sync_file.h b/include/linux/sync_file.h
new file mode 100644
index 0000000..ac2b4c6
--- /dev/null
+++ b/include/linux/sync_file.h
@@ -0,0 +1,123 @@
+/*
+ * include/linux/sync_file.h
+ *
+ * Copyright (C) 2012 Google, Inc.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _LINUX_SYNC_FILE_H
+#define _LINUX_SYNC_FILE_H
+
+#include <linux/types.h>
+#include <linux/kref.h>
+#include <linux/ktime.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/wait.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
+ * @kref: reference count on fence.
+ * @name: name of sync_file. Useful for debugging
+ * @sync_file_list: membership in global file list
+ * @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
+ */
+struct sync_file {
+ struct file *file;
+ struct kref kref;
+ char name[32];
+#ifdef CONFIG_DEBUG_FS
+ struct list_head sync_file_list;
+#endif
+ int num_fences;
+
+ wait_queue_head_t wq;
+ atomic_t status;
+
+ struct sync_file_cb cbs[];
+};
+
+/**
+ * sync_file_create() - creates a sync fence
+ * @name: name of fence to create
+ * @fence: fence to add to the sync_fence
+ *
+ * Creates a sync_file containg @fence. Once this is called, the sync_file
+ * takes ownership of @fence.
+ */
+struct sync_file *sync_file_create(const char *name, struct fence *fence);
+
+/*
+ * API for sync_file consumers
+ */
+
+/**
+ * sync_file_merge() - merge two sync_files
+ * @name: name of new fence
+ * @a: sync_file a
+ * @b: sync_file b
+ *
+ * Creates a new sync_file which contains copies of all the fences in both
+ * @a and @b. @a and @b remain valid, independent sync_file. Returns the
+ * new merged sync_file or NULL in case of error.
+ */
+struct sync_file *sync_file_merge(const char *name,
+ struct sync_file *a, struct sync_file *b);
+
+/**
+ * sync_file_fdget() - get a sync_file from an fd
+ * @fd: fd referencing a fence
+ *
+ * Ensures @fd references a valid sync_file, increments the refcount of the
+ * backing file. Returns the sync_file or NULL in case of error.
+ */
+struct sync_file *sync_file_fdget(int fd);
+
+/**
+ * sync_file_put() - puts a reference of a sync_file
+ * @sync_file: sync_file to put
+ *
+ * Puts a reference on @sync_fence. If this is the last reference, the
+ * sync_fil and all it's sync_pts will be freed
+ */
+void sync_file_put(struct sync_file *sync_file);
+
+/**
+ * sync_file_install() - installs a sync_file into a file descriptor
+ * @sync_file: sync_file to install
+ * @fd: file descriptor in which to install the fence
+ *
+ * Installs @sync_file into @fd. @fd's should be acquired through
+ * get_unused_fd_flags(O_CLOEXEC).
+ */
+void sync_file_install(struct sync_file *sync_file, int fd);
+
+/**
+ * sync_file_wait() - wait on sync file
+ * @sync_file: file to wait on
+ * @tiemout: timeout in ms
+ *
+ * Wait for @sync_file to be signaled or have an error. Waits indefinitely
+ * if @timeout < 0.
+ *
+ * Returns 0 if fence signaled, > 0 if it is still active and <0 on error
+ */
+int sync_file_wait(struct sync_file *sync_file, long timeout);
+
+#endif /* _LINUX_SYNC_H */
diff --git a/include/trace/events/sync_file.h b/include/trace/events/sync_file.h
new file mode 100644
index 0000000..659b5f3
--- /dev/null
+++ b/include/trace/events/sync_file.h
@@ -0,0 +1,57 @@
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM sync_file
+
+#if !defined(_TRACE_SYNC_FILE_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_SYNC_FILE_H
+
+#include <linux/sync.h>
+#include <linux/tracepoint.h>
+
+TRACE_EVENT(sync_wait,
+ TP_PROTO(struct sync_file *sync_file, int begin),
+
+ TP_ARGS(sync_file, begin),
+
+ TP_STRUCT__entry(
+ __string(name, sync_file->name)
+ __field(s32, status)
+ __field(u32, begin)
+ ),
+
+ TP_fast_assign(
+ __assign_str(name, sync_file->name);
+ __entry->status = atomic_read(&sync_file->status);
+ __entry->begin = begin;
+ ),
+
+ TP_printk("%s name=%s state=%d", __entry->begin ? "begin" : "end",
+ __get_str(name), __entry->status)
+);
+
+TRACE_EVENT(fence,
+ TP_PROTO(struct fence *fence),
+
+ TP_ARGS(fence),
+
+ TP_STRUCT__entry(
+ __string(timeline, fence->ops->get_timeline_name(fence))
+ __array(char, value, 32)
+ ),
+
+ TP_fast_assign(
+ __assign_str(timeline, fence->ops->get_timeline_name(fence));
+ if (fence->ops->fence_value_str) {
+ fence->ops->fence_value_str(fence, __entry->value,
+ sizeof(__entry->value));
+ } else {
+ __entry->value[0] = '\0';
+ }
+ ),
+
+ TP_printk("name=%s value=%s", __get_str(timeline), __entry->value)
+);
+
+#endif /* if !defined(_TRACE_SYNC_FILE_H) || defined(TRACE_HEADER_MULTI_READ) */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
diff --git a/drivers/staging/android/uapi/sync.h b/include/uapi/linux/sync.h
similarity index 90%
rename from drivers/staging/android/uapi/sync.h
rename to include/uapi/linux/sync.h
index 73deb69..2a8ab04 100644
--- a/drivers/staging/android/uapi/sync.h
+++ b/include/uapi/linux/sync.h
@@ -27,15 +27,15 @@ struct sync_merge_data {
};
/**
- * struct sync_pt_info - detailed sync_pt information
- * @len: length of sync_pt_info including any driver_data
+ * struct fence_info - detailed fence information
+ * @len: length of fence_info including any driver_data
* @obj_name: name of parent sync_timeline
* @driver_name: name of driver implementing the parent
- * @status: status of the sync_pt 0:active 1:signaled <0:error
+ * @status: status of the fence 0:active 1:signaled <0:error
* @timestamp_ns: timestamp of status change in nanoseconds
* @driver_data: any driver dependent data
*/
-struct sync_pt_info {
+struct fence_info {
__u32 len;
char obj_name[32];
char driver_name[32];
@@ -52,14 +52,14 @@ struct sync_pt_info {
* userspace including pt_info.
* @name: name of fence
* @status: status of fence. 1: signaled 0:active <0:error
- * @pt_info: a sync_pt_info struct for every sync_pt in the fence
+ * @fence_info: a fence_info struct for every fence in the sync_file
*/
struct sync_file_info_data {
__u32 len;
char name[32];
__s32 status;
- __u8 pt_info[0];
+ __u8 fence_info[0];
};
#define SYNC_IOC_MAGIC '>'
--
2.5.0
[toc] | [next] | [standalone]
| From | Maarten Lankhorst <maarten.lankhorst@linux.intel.com> |
|---|---|
| Date | 2016-01-27 15:40 +0100 |
| Message-ID | <qVzqj-4RW-37@gated-at.bofh.it> |
| In reply to | #1318950 |
Hey, Op 27-01-16 om 14:30 schreef Gustavo Padovan: > From: Gustavo Padovan <gustavo.padovan@collabora.co.uk> > > sync_file is useful to connect one or more fences to the file. The file is > used by userspace to track fences. > > Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk> > Is there a value in keeping the abi unchanged? If not, then Documentation/ioctl/botching-up-ioctls.txt is worth a read. Looking at the patch, it seems you kept SYNC_IOC_WAIT, won't it be better to remove it, and only support waiting with polling? The code for polling should already work. It's very unclear what format @driver_data has. I kept it for compatibility with android, but it's not clear to me how a userspace consumer would print it. Is there a usecase for this, or could it be removed from fence and sync_file? ~Maarten
[toc] | [prev] | [next] | [standalone]
| From | Gustavo Padovan <gustavo@padovan.org> |
|---|---|
| Date | 2016-01-27 18:10 +0100 |
| Message-ID | <qVBLs-6NS-17@gated-at.bofh.it> |
| In reply to | #1319030 |
Hi Maarten, 2016-01-27 Maarten Lankhorst <maarten.lankhorst@linux.intel.com>: > Hey, > > Op 27-01-16 om 14:30 schreef Gustavo Padovan: > > From: Gustavo Padovan <gustavo.padovan@collabora.co.uk> > > > > sync_file is useful to connect one or more fences to the file. The file is > > used by userspace to track fences. > > > > Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk> > > > Is there a value in keeping the abi unchanged? > If not, then Documentation/ioctl/botching-up-ioctls.txt is worth a read. None from me. I'll look where we can improve the ABI. > > Looking at the patch, it seems you kept SYNC_IOC_WAIT, won't it be better to remove it, and only support waiting with polling? > The code for polling should already work. Sure, that makes sense for me. > > It's very unclear what format @driver_data has. I kept it for compatibility with android, but it's not clear to me how a userspace consumer would print it. > Is there a usecase for this, or could it be removed from fence and sync_file? I don't have any usecase for this. I'd say we remove it for now and if someone needs this in the future we can talk about this again. Gustavo
[toc] | [prev] | [next] | [standalone]
| From | Emil Velikov <emil.l.velikov@gmail.com> |
|---|---|
| Date | 2016-01-27 19:20 +0100 |
| Message-ID | <qVCRd-7CM-43@gated-at.bofh.it> |
| In reply to | #1319164 |
Hi Gustavo, On 27 January 2016 at 17:03, Gustavo Padovan <gustavo@padovan.org> wrote: > Hi Maarten, > > 2016-01-27 Maarten Lankhorst <maarten.lankhorst@linux.intel.com>: > >> Hey, >> >> Op 27-01-16 om 14:30 schreef Gustavo Padovan: >> > From: Gustavo Padovan <gustavo.padovan@collabora.co.uk> >> > >> > sync_file is useful to connect one or more fences to the file. The file is >> > used by userspace to track fences. >> > >> > Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk> >> > >> Is there a value in keeping the abi unchanged? >> If not, then Documentation/ioctl/botching-up-ioctls.txt is worth a read. > > None from me. I'll look where we can improve the ABI. > Speaking of ABI... there are a couple of things that rang bells here: - In most/all of the kernel a len/size named member variable indicates the length of the extra data (zero sized array). While here it includes the size of the struct as well. - struct sync_file_info_data::fence_info is of type __u8 yet it is "a fence_info struct for every fence in the sync_file". Thus shouldn't one use "struct fence_info" as the type ? -Emil
[toc] | [prev] | [next] | [standalone]
| From | Gustavo Padovan <gustavo@padovan.org> |
|---|---|
| Date | 2016-01-27 21:30 +0100 |
| Message-ID | <qVESZ-FR-3@gated-at.bofh.it> |
| In reply to | #1319219 |
Hi Emil, 2016-01-27 Emil Velikov <emil.l.velikov@gmail.com>: > Hi Gustavo, > > On 27 January 2016 at 17:03, Gustavo Padovan <gustavo@padovan.org> wrote: > > Hi Maarten, > > > > 2016-01-27 Maarten Lankhorst <maarten.lankhorst@linux.intel.com>: > > > >> Hey, > >> > >> Op 27-01-16 om 14:30 schreef Gustavo Padovan: > >> > From: Gustavo Padovan <gustavo.padovan@collabora.co.uk> > >> > > >> > sync_file is useful to connect one or more fences to the file. The file is > >> > used by userspace to track fences. > >> > > >> > Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk> > >> > > >> Is there a value in keeping the abi unchanged? > >> If not, then Documentation/ioctl/botching-up-ioctls.txt is worth a read. > > > > None from me. I'll look where we can improve the ABI. > > > Speaking of ABI... there are a couple of things that rang bells here: > - In most/all of the kernel a len/size named member variable > indicates the length of the extra data (zero sized array). While here > it includes the size of the struct as well. len in this case is the size of the buffer sent to the kernel, the total length (including the whole struct) is returned in the ioctl. > - struct sync_file_info_data::fence_info is of type __u8 yet it is "a > fence_info struct for every fence in the sync_file". Thus shouldn't > one use "struct fence_info" as the type ? Agreed. But I'm currently thinking if we really should keep this ioctl. Gustavo
[toc] | [prev] | [next] | [standalone]
| From | Greg Hackmann <ghackmann@google.com> |
|---|---|
| Date | 2016-01-27 22:50 +0100 |
| Message-ID | <qVG8q-1wI-3@gated-at.bofh.it> |
| In reply to | #1319668 |
On 01/27/2016 12:25 PM, Gustavo Padovan wrote: >>>> Is there a value in keeping the abi unchanged? >>>> If not, then Documentation/ioctl/botching-up-ioctls.txt is worth a read. >>> >>> None from me. I'll look where we can improve the ABI. Android has existing clients of the current ABI. Thankfully they're all contained in system services like SurfaceFlinger, since end-user apps don't get direct access to fence fds. As long the ABI breaks don't remove functionality we depend on, we can wrap around them in our userspace libsync. I'd rather not have to do that, but it's a price I'm willing to pay to get this moved out of staging. >> - struct sync_file_info_data::fence_info is of type __u8 yet it is "a >> fence_info struct for every fence in the sync_file". Thus shouldn't >> one use "struct fence_info" as the type ? > > Agreed. But I'm currently thinking if we really should keep this ioctl. > > Gustavo > I'm not seeing any consumers of driver_data in our tree. OTOH completely getting rid of the ioctl would be a problem, since SurfaceFlinger depends on the timestamp information for its own bookkeeping.
[toc] | [prev] | [next] | [standalone]
| From | Daniel Vetter <daniel@ffwll.ch> |
|---|---|
| Date | 2016-01-28 10:30 +0100 |
| Message-ID | <qVR3Q-1j6-19@gated-at.bofh.it> |
| In reply to | #1319956 |
On Wed, Jan 27, 2016 at 01:41:03PM -0800, Greg Hackmann wrote: > On 01/27/2016 12:25 PM, Gustavo Padovan wrote: > >>>>Is there a value in keeping the abi unchanged? > >>>>If not, then Documentation/ioctl/botching-up-ioctls.txt is worth a read. > >>> > >>>None from me. I'll look where we can improve the ABI. > > Android has existing clients of the current ABI. Thankfully they're all > contained in system services like SurfaceFlinger, since end-user apps don't > get direct access to fence fds. > > As long the ABI breaks don't remove functionality we depend on, we can wrap > around them in our userspace libsync. I'd rather not have to do that, but > it's a price I'm willing to pay to get this moved out of staging. > > >> - struct sync_file_info_data::fence_info is of type __u8 yet it is "a > >>fence_info struct for every fence in the sync_file". Thus shouldn't > >>one use "struct fence_info" as the type ? > > > >Agreed. But I'm currently thinking if we really should keep this ioctl. > > > > Gustavo > > > > I'm not seeing any consumers of driver_data in our tree. OTOH completely > getting rid of the ioctl would be a problem, since SurfaceFlinger depends on > the timestamp information for its own bookkeeping. If we remove driver_data (and len is superflous too), then I think we should also make the master struct use common ioctl pattern: - Add a num_fences field or similar that the kernel fills out. - Make pt_info an __u64 pointer instead of a variable-length array (and length) - ioctl payload sizes are somewhat limited. This way the interface is future-proofed for truly patalogical number of fences (which surface flinger won't do, but could happen in server/opencl/media workloads I'd imagine). And I think driver_data really shouldn't be there, it makes things complicated with the array of variable-sized objects, and generic userspace can't really use it - for debug output we already have obj/driver_name per fence point, which I think is good enough. Would that be ok for you from the Android side if Gustavo also provides a patch to update libsync? I don't think the ABI is fundamentally broken, but this light cleanup would be nice. Wrt keeping SYNC_WAIT: I think that's totally fine. Redundant since polling is supported, but not really an issue imo either. If we're totally lazy we could implement SYNC_WAIT internally using poll and shave off a few lines of the implementation. -Daniel -- Daniel Vetter Software Engineer, Intel Corporation http://blog.ffwll.ch
[toc] | [prev] | [next] | [standalone]
| From | Greg Hackmann <ghackmann@google.com> |
|---|---|
| Date | 2016-01-29 18:50 +0100 |
| Message-ID | <qWllg-6BJ-23@gated-at.bofh.it> |
| In reply to | #1320467 |
On 01/28/16 01:23, Daniel Vetter wrote: > And I think driver_data really shouldn't be there, it makes things > complicated with the array of variable-sized objects, and generic > userspace can't really use it - for debug output we already have > obj/driver_name per fence point, which I think is good enough. I looked at our device kernels, and some vendors actually are filling in driver_data. I'm just not seeing any accesses to them in our *userspace* tree. And in a lot of cases it looks like they're just filling in debugging information that they could get elsewhere. I'm checking with our vendor contacts to see what they're actually using this for (if anything). > Would that be ok for you from the Android side if Gustavo also provides a > patch to update libsync? I don't think the ABI is fundamentally broken, > but this light cleanup would be nice. No objections here. Just upload the changes to AOSP and add me as a reviewer. > Wrt keeping SYNC_WAIT: I think that's totally fine. Redundant since > polling is supported, but not really an issue imo either. If we're totally > lazy we could implement SYNC_WAIT internally using poll and shave off a > few lines of the implementation. Honestly this is the change I'm least worried about, since poll() will work with existing kernels too. The only difference would be that the SYNC_WAIT ioctl fails when given something that's not specifically a sync fence; but I'm skeptical that anything actually depends on that behavior.
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web