Thanks for the patch, Gustavo!
On 18 March 2016 at 19:49, Gustavo Padovan gustavo@padovan.org wrote:
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.
I think it is worthwhile to add relevant bits to the Documentation as well - care to add relevant stuff to either Documentation/dma_buf.txt, or to a file of its own? (I'd prefer the former, but would leave it upto you.)
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 | 382 +++++++++++++++++++++ drivers/staging/android/Kconfig | 1 + drivers/staging/android/sync.c | 362 ------------------- drivers/staging/android/sync.h | 92 +---- drivers/staging/android/sync_debug.c | 1 + include/linux/sync_file.h | 106 ++++++ .../uapi/sync.h => include/uapi/linux/sync_file.h | 0 10 files changed, 506 insertions(+), 452 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 rename drivers/staging/android/uapi/sync.h => include/uapi/linux/sync_file.h (100%)
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..df786a2 --- /dev/null +++ b/drivers/dma-buf/sync_file.c @@ -0,0 +1,382 @@ +/*
- 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_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_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;
return sync_file;
+} +EXPORT_SYMBOL(sync_file_merge);
+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;
if (status < 0)
return POLLERR;
return 0;
+}
+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;
}
if (data.flags || data.pad) {
err = -EINVAL;
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 void sync_fill_fence_info(struct fence *fence,
struct sync_fence_info *info)
+{
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);
+}
+static long sync_file_ioctl_fence_info(struct sync_file *sync_file,
unsigned long arg)
+{
struct sync_file_info info;
struct sync_fence_info *fence_info = NULL;
__u32 size;
int ret, i;
if (copy_from_user(&info, (void __user *)arg, sizeof(info)))
return -EFAULT;
if (info.flags || info.pad)
return -EINVAL;
/*
* Passing num_fences = 0 means that userspace doesn't want to
* retrieve any sync_fence_info. If num_fences = 0 we skip filling
* sync_fence_info and return the actual number of fences on
* info->num_fences.
*/
if (!info.num_fences)
goto no_fences;
if (info.num_fences < sync_file->num_fences)
return -EINVAL;
size = sync_file->num_fences * sizeof(*fence_info);
fence_info = kzalloc(size, GFP_KERNEL);
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]);
if (copy_to_user(u64_to_user_ptr(info.sync_fence_info), fence_info,
size)) {
ret = -EFAULT;
goto out;
}
+no_fences:
strlcpy(info.name, sync_file->name, sizeof(info.name));
info.status = atomic_read(&sync_file->status);
if (info.status >= 0)
info.status = !info.status;
info.num_fences = sync_file->num_fences;
if (copy_to_user((void __user *)arg, &info, sizeof(info)))
ret = -EFAULT;
else
ret = 0;
+out:
kfree(fence_info);
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_MERGE:
return sync_file_ioctl_merge(sync_file, arg);
case SYNC_IOC_FILE_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 f9c6094..1d14c83 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,170 +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);
static const char *android_fence_get_driver_name(struct fence *fence) { struct sync_timeline *parent = fence_parent(fence); @@ -387,197 +219,3 @@ static const struct fence_ops android_fence_ops = { .fence_value_str = android_fence_value_str, .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;
if (status < 0)
return POLLERR;
return 0;
-}
-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;
}
if (data.flags || data.pad) {
err = -EINVAL;
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 void sync_fill_fence_info(struct fence *fence,
struct sync_fence_info *info)
-{
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);
-}
-static long sync_file_ioctl_fence_info(struct sync_file *sync_file,
unsigned long arg)
-{
struct sync_file_info info;
struct sync_fence_info *fence_info = NULL;
__u32 size;
int ret, i;
if (copy_from_user(&info, (void __user *)arg, sizeof(info)))
return -EFAULT;
if (info.flags || info.pad)
return -EINVAL;
/*
* Passing num_fences = 0 means that userspace doesn't want to
* retrieve any sync_fence_info. If num_fences = 0 we skip filling
* sync_fence_info and return the actual number of fences on
* info->num_fences.
*/
if (!info.num_fences)
goto no_fences;
if (info.num_fences < sync_file->num_fences)
return -EINVAL;
size = sync_file->num_fences * sizeof(*fence_info);
fence_info = kzalloc(size, GFP_KERNEL);
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]);
if (copy_to_user(u64_to_user_ptr(info.sync_fence_info), fence_info,
size)) {
ret = -EFAULT;
goto out;
}
-no_fences:
strlcpy(info.name, sync_file->name, sizeof(info.name));
info.status = atomic_read(&sync_file->status);
if (info.status >= 0)
info.status = !info.status;
info.num_fences = sync_file->num_fences;
if (copy_to_user((void __user *)arg, &info, sizeof(info)))
ret = -EFAULT;
else
ret = 0;
-out:
kfree(fence_info);
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_MERGE:
return sync_file_ioctl_merge(sync_file, arg);
case SYNC_IOC_FILE_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 d2a1734..97574be 100644 --- a/drivers/staging/android/sync.h +++ b/drivers/staging/android/sync.h @@ -19,11 +19,10 @@ #include <linux/list.h> #include <linux/spinlock.h> #include <linux/fence.h>
-#include "uapi/sync.h" +#include <linux/sync_file.h> +#include <uapi/linux/sync_file.h>
struct sync_timeline; -struct sync_file;
/**
- struct sync_timeline_ops - sync object implementation ops
@@ -86,38 +85,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
*/ @@ -167,61 +134,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);
#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 5a7ec58..e5b14f0 100644 --- a/drivers/staging/android/sync_debug.c +++ b/drivers/staging/android/sync_debug.c @@ -26,6 +26,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/include/linux/sync_file.h b/include/linux/sync_file.h new file mode 100644 index 0000000..7b7a89d --- /dev/null +++ b/include/linux/sync_file.h @@ -0,0 +1,106 @@ +/*
- 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/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 file
- @name: name of fence to create
- @fence: fence to add to the sync_file
- 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);
+/**
- 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);
+#endif /* _LINUX_SYNC_H */ diff --git a/drivers/staging/android/uapi/sync.h b/include/uapi/linux/sync_file.h similarity index 100% rename from drivers/staging/android/uapi/sync.h rename to include/uapi/linux/sync_file.h -- 2.5.0
dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Best, Sumit.