From: Gustavo Padovan <gustavo.padovan@xxxxxxxxxxxxxxx> De-stage the remaining bit of sync framework: sync_timeline and sw_sync plus some debugging routines. Signed-off-by: Gustavo Padovan <gustavo.padovan@xxxxxxxxxxxxxxx> --- drivers/dma-buf/Kconfig | 10 + drivers/dma-buf/Makefile | 3 +- drivers/dma-buf/sw_sync.h | 32 +++ drivers/dma-buf/sync_debug.c | 374 +++++++++++++++++++++++++++++++++ drivers/dma-buf/sync_debug.h | 35 +++ drivers/dma-buf/sync_timeline.c | 222 +++++++++++++++++++ drivers/staging/android/Kconfig | 20 -- drivers/staging/android/sync.c | 221 ------------------- drivers/staging/android/sync.h | 130 ------------ drivers/staging/android/sync_debug.c | 373 -------------------------------- drivers/staging/android/trace/sync.h | 32 --- drivers/staging/android/uapi/sw_sync.h | 32 --- include/linux/sync_timeline.h | 114 ++++++++++ include/trace/events/sync_timeline.h | 31 +++ 14 files changed, 820 insertions(+), 809 deletions(-) create mode 100644 drivers/dma-buf/sw_sync.h create mode 100644 drivers/dma-buf/sync_debug.c create mode 100644 drivers/dma-buf/sync_debug.h create mode 100644 drivers/dma-buf/sync_timeline.c delete mode 100644 drivers/staging/android/sync.c delete mode 100644 drivers/staging/android/sync.h delete mode 100644 drivers/staging/android/sync_debug.c delete mode 100644 drivers/staging/android/trace/sync.h delete mode 100644 drivers/staging/android/uapi/sw_sync.h create mode 100644 include/linux/sync_timeline.h create mode 100644 include/trace/events/sync_timeline.h diff --git a/drivers/dma-buf/Kconfig b/drivers/dma-buf/Kconfig index 9824bc4..73df024 100644 --- a/drivers/dma-buf/Kconfig +++ b/drivers/dma-buf/Kconfig @@ -8,4 +8,14 @@ config SYNC_FILE ---help--- This option enables the fence framework synchronization to export sync_files to userspace that can represent one or more fences. + +config SW_SYNC + bool "Software synchronization objects" + default n + 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 + the synchronization. + endmenu diff --git a/drivers/dma-buf/Makefile b/drivers/dma-buf/Makefile index 4a424ec..78d8ec4 100644 --- a/drivers/dma-buf/Makefile +++ b/drivers/dma-buf/Makefile @@ -1,2 +1,3 @@ obj-y := dma-buf.o fence.o reservation.o seqno-fence.o -obj-$(CONFIG_SYNC_FILE) += sync_file.o +obj-$(CONFIG_SYNC_FILE) += sync_file.o sync_debug.o +obj-$(CONFIG_SW_SYNC) += sync_timeline.o diff --git a/drivers/dma-buf/sw_sync.h b/drivers/dma-buf/sw_sync.h new file mode 100644 index 0000000..9b5d486 --- /dev/null +++ b/drivers/dma-buf/sw_sync.h @@ -0,0 +1,32 @@ +/* + * 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. + * + */ + +#ifndef _UAPI_LINUX_SW_SYNC_H +#define _UAPI_LINUX_SW_SYNC_H + +#include <linux/types.h> + +struct sw_sync_create_fence_data { + __u32 value; + char name[32]; + __s32 fence; /* fd of new fence */ +}; + +#define SW_SYNC_IOC_MAGIC 'W' + +#define SW_SYNC_IOC_CREATE_FENCE _IOWR(SW_SYNC_IOC_MAGIC, 0,\ + struct sw_sync_create_fence_data) +#define SW_SYNC_IOC_INC _IOW(SW_SYNC_IOC_MAGIC, 1, __u32) + +#endif /* _UAPI_LINUX_SW_SYNC_H */ diff --git a/drivers/dma-buf/sync_debug.c b/drivers/dma-buf/sync_debug.c new file mode 100644 index 0000000..7da9ff5 --- /dev/null +++ b/drivers/dma-buf/sync_debug.c @@ -0,0 +1,374 @@ +/* + * drivers/base/sync.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/debugfs.h> +#include <linux/module.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> +#include <linux/uaccess.h> +#include <linux/anon_inodes.h> +#include <linux/time64.h> +#include <linux/sync_file.h> +#include <linux/types.h> +#include <linux/kconfig.h> +#include <linux/sync_timeline.h> + +#include "sync_debug.h" +#include "sw_sync.h" + +#ifdef CONFIG_DEBUG_FS + +static struct dentry *dbgfs; + +static LIST_HEAD(sync_timeline_list_head); +static DEFINE_SPINLOCK(sync_timeline_list_lock); +static LIST_HEAD(sync_file_list_head); +static DEFINE_SPINLOCK(sync_file_list_lock); + +void sync_timeline_debug_add(struct sync_timeline *obj) +{ + unsigned long flags; + + spin_lock_irqsave(&sync_timeline_list_lock, flags); + list_add_tail(&obj->sync_timeline_list, &sync_timeline_list_head); + spin_unlock_irqrestore(&sync_timeline_list_lock, flags); +} + +void sync_timeline_debug_remove(struct sync_timeline *obj) +{ + unsigned long flags; + + spin_lock_irqsave(&sync_timeline_list_lock, flags); + list_del(&obj->sync_timeline_list); + spin_unlock_irqrestore(&sync_timeline_list_lock, flags); +} + +void sync_file_debug_add(struct sync_file *sync_file) +{ + unsigned long flags; + + spin_lock_irqsave(&sync_file_list_lock, flags); + list_add_tail(&sync_file->sync_file_list, &sync_file_list_head); + spin_unlock_irqrestore(&sync_file_list_lock, flags); +} + +void sync_file_debug_remove(struct sync_file *sync_file) +{ + unsigned long flags; + + spin_lock_irqsave(&sync_file_list_lock, flags); + list_del(&sync_file->sync_file_list); + spin_unlock_irqrestore(&sync_file_list_lock, flags); +} + +static const char *sync_status_str(int status) +{ + if (status == 0) + return "signaled"; + + if (status > 0) + return "active"; + + return "error"; +} + +static void sync_print_fence(struct seq_file *s, struct fence *fence, bool show) +{ + int status = 1; + struct sync_timeline *parent = fence_parent(fence); + + if (fence_is_signaled_locked(fence)) + status = fence->status; + + seq_printf(s, " %s%sfence %s", + show ? parent->name : "", + show ? "_" : "", + sync_status_str(status)); + + if (status <= 0) { + struct timespec64 ts64 = + ktime_to_timespec64(fence->timestamp); + + seq_printf(s, "@%lld.%09ld", (s64)ts64.tv_sec, ts64.tv_nsec); + } + + if ((!fence || fence->ops->timeline_value_str) && + fence->ops->fence_value_str) { + char value[64]; + bool success; + + fence->ops->fence_value_str(fence, value, sizeof(value)); + success = strlen(value); + + if (success) + seq_printf(s, ": %s", value); + + if (success && fence) { + fence->ops->timeline_value_str(fence, value, + sizeof(value)); + + if (strlen(value)) + seq_printf(s, " / %s", value); + } + } + + seq_puts(s, "\n"); +} + +static void sync_print_obj(struct seq_file *s, struct sync_timeline *obj) +{ + struct list_head *pos; + unsigned long flags; + + seq_printf(s, "%s %s: %d\n", obj->name, obj->drv_name, obj->value); + + spin_lock_irqsave(&obj->child_list_lock, flags); + list_for_each(pos, &obj->child_list_head) { + struct fence *fence = + container_of(pos, struct fence, child_list); + sync_print_fence(s, fence, false); + } + spin_unlock_irqrestore(&obj->child_list_lock, flags); +} + +static void sync_print_sync_file(struct seq_file *s, + struct sync_file *sync_file) +{ + int i; + + seq_printf(s, "[%p] %s: %s\n", sync_file, sync_file->name, + sync_status_str(atomic_read(&sync_file->status))); + + for (i = 0; i < sync_file->num_fences; ++i) { + sync_print_fence(s, sync_file->cbs[i].fence, true); + } +} + +static int sync_debugfs_show(struct seq_file *s, void *unused) +{ + unsigned long flags; + struct list_head *pos; + + seq_puts(s, "objs:\n--------------\n"); + + spin_lock_irqsave(&sync_timeline_list_lock, flags); + list_for_each(pos, &sync_timeline_list_head) { + struct sync_timeline *obj = + container_of(pos, struct sync_timeline, + sync_timeline_list); + + sync_print_obj(s, obj); + seq_puts(s, "\n"); + } + spin_unlock_irqrestore(&sync_timeline_list_lock, flags); + + seq_puts(s, "fences:\n--------------\n"); + + spin_lock_irqsave(&sync_file_list_lock, flags); + list_for_each(pos, &sync_file_list_head) { + struct sync_file *sync_file = + container_of(pos, struct sync_file, sync_file_list); + + sync_print_sync_file(s, sync_file); + seq_puts(s, "\n"); + } + spin_unlock_irqrestore(&sync_file_list_lock, flags); + return 0; +} + +static int sync_info_debugfs_open(struct inode *inode, struct file *file) +{ + return single_open(file, sync_debugfs_show, inode->i_private); +} + +static const struct file_operations sync_info_debugfs_fops = { + .open = sync_info_debugfs_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +#if IS_ENABLED(CONFIG_SW_SYNC) +/* + * *WARNING* + * + * improper use of this can result in deadlocking kernel drivers from userspace. + */ + +/* opening sw_sync create a new sync obj */ +static int sw_sync_debugfs_open(struct inode *inode, struct file *file) +{ + struct sync_timeline *obj; + char task_comm[TASK_COMM_LEN]; + + get_task_comm(task_comm, current); + + obj = sync_timeline_create(sizeof(*obj), "sw_sync", task_comm); + if (!obj) + return -ENOMEM; + + file->private_data = obj; + + return 0; +} + +static int sw_sync_debugfs_release(struct inode *inode, struct file *file) +{ + struct sync_timeline *obj = file->private_data; + + sync_timeline_destroy(obj); + return 0; +} + +static long sw_sync_ioctl_create_fence(struct sync_timeline *obj, + unsigned long arg) +{ + int fd = get_unused_fd_flags(O_CLOEXEC); + int err; + struct fence *fence; + struct sync_file *sync_file; + struct sw_sync_create_fence_data data; + + if (fd < 0) + return fd; + + if (copy_from_user(&data, (void __user *)arg, sizeof(data))) { + err = -EFAULT; + goto err; + } + + fence = sync_pt_create(obj, sizeof(*fence), data.value); + if (!fence) { + err = -ENOMEM; + goto err; + } + + data.name[sizeof(data.name) - 1] = '\0'; + sync_file = sync_file_create(data.name, fence); + if (!sync_file) { + fence_put(fence); + err = -ENOMEM; + goto err; + } + + data.fence = fd; + if (copy_to_user((void __user *)arg, &data, sizeof(data))) { + sync_file_put(sync_file); + err = -EFAULT; + goto err; + } + + sync_file_install(sync_file, fd); + + return 0; + +err: + put_unused_fd(fd); + return err; +} + +static long sw_sync_ioctl_inc(struct sync_timeline *obj, unsigned long arg) +{ + u32 value; + + if (copy_from_user(&value, (void __user *)arg, sizeof(value))) + return -EFAULT; + + sync_timeline_signal(obj, value); + + return 0; +} + +static long sw_sync_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + struct sync_timeline *obj = file->private_data; + + switch (cmd) { + case SW_SYNC_IOC_CREATE_FENCE: + return sw_sync_ioctl_create_fence(obj, arg); + + case SW_SYNC_IOC_INC: + return sw_sync_ioctl_inc(obj, arg); + + default: + return -ENOTTY; + } +} + +static const struct file_operations sw_sync_debugfs_fops = { + .open = sw_sync_debugfs_open, + .release = sw_sync_debugfs_release, + .unlocked_ioctl = sw_sync_ioctl, + .compat_ioctl = sw_sync_ioctl, +}; +#endif + +static __init int sync_debugfs_init(void) +{ + dbgfs = debugfs_create_dir("sync", NULL); + + debugfs_create_file("info", 0444, dbgfs, NULL, &sync_info_debugfs_fops); + +#if IS_ENABLED(CONFIG_SW_SYNC) + debugfs_create_file("sw_sync", 0644, dbgfs, NULL, + &sw_sync_debugfs_fops); +#endif + + return 0; +} +late_initcall(sync_debugfs_init); + +static __exit void sync_debugfs_exit(void) +{ + if (dbgfs) + debugfs_remove_recursive(dbgfs); +} +module_exit(sync_debugfs_exit); + +#define DUMP_CHUNK 256 +static char sync_dump_buf[64 * 1024]; +void sync_dump(void) +{ + struct seq_file s = { + .buf = sync_dump_buf, + .size = sizeof(sync_dump_buf) - 1, + }; + int i; + + sync_debugfs_show(&s, NULL); + + for (i = 0; i < s.count; i += DUMP_CHUNK) { + if ((s.count - i) > DUMP_CHUNK) { + char c = s.buf[i + DUMP_CHUNK]; + + s.buf[i + DUMP_CHUNK] = 0; + pr_cont("%s", s.buf + i); + s.buf[i + DUMP_CHUNK] = c; + } else { + s.buf[s.count] = 0; + pr_cont("%s", s.buf + i); + } + } +} + +#endif diff --git a/drivers/dma-buf/sync_debug.h b/drivers/dma-buf/sync_debug.h new file mode 100644 index 0000000..5b71685 --- /dev/null +++ b/drivers/dma-buf/sync_debug.h @@ -0,0 +1,35 @@ +/* + * drivers/dma-buf/sync_debug.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_DEBUG_H +#define _LINUX_SYNC_DEBUG_H + +#include <linux/types.h> +#include <linux/sync_timeline.h> +#include <linux/sync_file.h> + +#ifdef CONFIG_DEBUG_FS +void sync_timeline_debug_add(struct sync_timeline *obj); +void sync_timeline_debug_remove(struct sync_timeline *obj); +void sync_file_debug_add(struct sync_file *sync_file); +void sync_file_debug_remove(struct sync_file *sync_file); +void sync_dump(void); + +#else +#define sync_timeline_debug_add(obj) +#define sync_timeline_debug_remove(obj) +#define sync_file_debug_add(fence) +#define sync_file_debug_remove(fence) +#define sync_dump() +#endif + +#endif /* _LINUX_SYNC_DEBUG_H */ diff --git a/drivers/dma-buf/sync_timeline.c b/drivers/dma-buf/sync_timeline.c new file mode 100644 index 0000000..b354b0c --- /dev/null +++ b/drivers/dma-buf/sync_timeline.c @@ -0,0 +1,222 @@ +/* + * drivers/base/sync.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/debugfs.h> +#include <linux/export.h> +#include <linux/kernel.h> +#include <linux/sched.h> +#include <linux/seq_file.h> +#include <linux/slab.h> +#include <linux/uaccess.h> +#include <linux/anon_inodes.h> +#include <linux/sync_timeline.h> + +#define CREATE_TRACE_POINTS +#include <trace/events/sync_timeline.h> + +#include "sync_debug.h" + +static const struct fence_ops timeline_fence_ops; + +struct sync_timeline *sync_timeline_create(int size, const char *drv_name, + const char *name) +{ + struct sync_timeline *obj; + + if (size < sizeof(struct sync_timeline)) + return NULL; + + obj = kzalloc(size, GFP_KERNEL); + if (!obj) + return NULL; + + kref_init(&obj->kref); + obj->context = fence_context_alloc(1); + strlcpy(obj->name, name, sizeof(obj->name)); + strlcpy(obj->drv_name, drv_name, sizeof(obj->drv_name)); + + INIT_LIST_HEAD(&obj->child_list_head); + INIT_LIST_HEAD(&obj->active_list_head); + spin_lock_init(&obj->child_list_lock); + + sync_timeline_debug_add(obj); + + return obj; +} +EXPORT_SYMBOL(sync_timeline_create); + +static void sync_timeline_free(struct kref *kref) +{ + struct sync_timeline *obj = + container_of(kref, struct sync_timeline, kref); + + sync_timeline_debug_remove(obj); + + kfree(obj); +} + +static void sync_timeline_get(struct sync_timeline *obj) +{ + kref_get(&obj->kref); +} + +static void sync_timeline_put(struct sync_timeline *obj) +{ + kref_put(&obj->kref, sync_timeline_free); +} + +void sync_timeline_destroy(struct sync_timeline *obj) +{ + obj->destroyed = true; + /* + * Ensure timeline is marked as destroyed before + * changing timeline's fences status. + */ + smp_wmb(); + + sync_timeline_put(obj); +} +EXPORT_SYMBOL(sync_timeline_destroy); + +void sync_timeline_signal(struct sync_timeline *obj, unsigned int inc) +{ + unsigned long flags; + struct fence *fence, *next; + + trace_sync_timeline(obj); + + spin_lock_irqsave(&obj->child_list_lock, flags); + + obj->value += inc; + + list_for_each_entry_safe(fence, next, &obj->active_list_head, + active_list) { + if (fence_is_signaled_locked(fence)) + list_del_init(&fence->active_list); + } + + spin_unlock_irqrestore(&obj->child_list_lock, flags); +} +EXPORT_SYMBOL(sync_timeline_signal); + +struct fence *sync_pt_create(struct sync_timeline *obj, int size, + unsigned int value) +{ + unsigned long flags; + struct fence *fence; + + if (size < sizeof(*fence)) + return NULL; + + fence = kzalloc(size, GFP_KERNEL); + if (!fence) + return NULL; + + spin_lock_irqsave(&obj->child_list_lock, flags); + sync_timeline_get(obj); + fence_init(fence, &timeline_fence_ops, &obj->child_list_lock, + obj->context, value); + list_add_tail(&fence->child_list, &obj->child_list_head); + INIT_LIST_HEAD(&fence->active_list); + spin_unlock_irqrestore(&obj->child_list_lock, flags); + return fence; +} +EXPORT_SYMBOL(sync_pt_create); + +static const char *timeline_fence_get_driver_name(struct fence *fence) +{ + struct sync_timeline *parent = fence_parent(fence); + + return parent->drv_name; +} + +static const char *timeline_fence_get_timeline_name(struct fence *fence) +{ + struct sync_timeline *parent = fence_parent(fence); + + return parent->name; +} + +static void timeline_fence_release(struct fence *fence) +{ + struct sync_timeline *parent = fence_parent(fence); + unsigned long flags; + + spin_lock_irqsave(fence->lock, flags); + list_del(&fence->child_list); + if (WARN_ON_ONCE(!list_empty(&fence->active_list))) + list_del(&fence->active_list); + spin_unlock_irqrestore(fence->lock, flags); + + sync_timeline_put(parent); + fence_free(fence); +} + +static bool timeline_fence_signaled(struct fence *fence) +{ + struct sync_timeline *parent = fence_parent(fence); + + return (fence->seqno > parent->value) ? false : true; +} + +static bool timeline_fence_enable_signaling(struct fence *fence) +{ + struct sync_timeline *parent = fence_parent(fence); + + if (timeline_fence_signaled(fence)) + return false; + + list_add_tail(&fence->active_list, &parent->active_list_head); + return true; +} + +static int timeline_fence_fill_driver_data(struct fence *fence, + void *data, int size) +{ + if (size < sizeof(fence->seqno)) + return -ENOMEM; + + memcpy(data, &fence->seqno, sizeof(fence->seqno)); + + return sizeof(fence->seqno); +} + +static void timeline_fence_value_str(struct fence *fence, + char *str, int size) +{ + snprintf(str, size, "%d", fence->seqno); +} + +static void timeline_fence_timeline_value_str(struct fence *fence, + char *str, int size) +{ + struct sync_timeline *parent = fence_parent(fence); + + snprintf(str, size, "%d", parent->value); +} + +static const struct fence_ops timeline_fence_ops = { + .get_driver_name = timeline_fence_get_driver_name, + .get_timeline_name = timeline_fence_get_timeline_name, + .enable_signaling = timeline_fence_enable_signaling, + .signaled = timeline_fence_signaled, + .wait = fence_default_wait, + .release = timeline_fence_release, + .fill_driver_data = timeline_fence_fill_driver_data, + .fence_value_str = timeline_fence_value_str, + .timeline_value_str = timeline_fence_timeline_value_str, +}; + diff --git a/drivers/staging/android/Kconfig b/drivers/staging/android/Kconfig index 2756988..4b18fee 100644 --- a/drivers/staging/android/Kconfig +++ b/drivers/staging/android/Kconfig @@ -38,26 +38,6 @@ config ANDROID_LOW_MEMORY_KILLER scripts (/init.rc), and it defines priority values with minimum free memory size for each priority. -config SYNC - bool "Synchronization framework" - default n - select ANON_INODES - select DMA_SHARED_BUFFER - ---help--- - This option enables the framework for synchronization between multiple - drivers. Sync implementations can take advantage of hardware - synchronization built into devices like GPUs. - -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 - the synchronization. - source "drivers/staging/android/ion/Kconfig" endif # if ANDROID diff --git a/drivers/staging/android/sync.c b/drivers/staging/android/sync.c deleted file mode 100644 index ea816dd..0000000 --- a/drivers/staging/android/sync.c +++ /dev/null @@ -1,221 +0,0 @@ -/* - * drivers/base/sync.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/debugfs.h> -#include <linux/export.h> -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/seq_file.h> -#include <linux/slab.h> -#include <linux/uaccess.h> -#include <linux/anon_inodes.h> - -#include "sync.h" - -#define CREATE_TRACE_POINTS -#include "trace/sync.h" - -static const struct fence_ops timeline_fence_ops; - -struct sync_timeline *sync_timeline_create(int size, const char *drv_name, - const char *name) -{ - struct sync_timeline *obj; - - if (size < sizeof(struct sync_timeline)) - return NULL; - - obj = kzalloc(size, GFP_KERNEL); - if (!obj) - return NULL; - - kref_init(&obj->kref); - obj->context = fence_context_alloc(1); - strlcpy(obj->name, name, sizeof(obj->name)); - strlcpy(obj->drv_name, drv_name, sizeof(obj->drv_name)); - - INIT_LIST_HEAD(&obj->child_list_head); - INIT_LIST_HEAD(&obj->active_list_head); - spin_lock_init(&obj->child_list_lock); - - sync_timeline_debug_add(obj); - - return obj; -} -EXPORT_SYMBOL(sync_timeline_create); - -static void sync_timeline_free(struct kref *kref) -{ - struct sync_timeline *obj = - container_of(kref, struct sync_timeline, kref); - - sync_timeline_debug_remove(obj); - - kfree(obj); -} - -static void sync_timeline_get(struct sync_timeline *obj) -{ - kref_get(&obj->kref); -} - -static void sync_timeline_put(struct sync_timeline *obj) -{ - kref_put(&obj->kref, sync_timeline_free); -} - -void sync_timeline_destroy(struct sync_timeline *obj) -{ - obj->destroyed = true; - /* - * Ensure timeline is marked as destroyed before - * changing timeline's fences status. - */ - smp_wmb(); - - sync_timeline_put(obj); -} -EXPORT_SYMBOL(sync_timeline_destroy); - -void sync_timeline_signal(struct sync_timeline *obj, unsigned int inc) -{ - unsigned long flags; - struct fence *fence, *next; - - trace_sync_timeline(obj); - - spin_lock_irqsave(&obj->child_list_lock, flags); - - obj->value += inc; - - list_for_each_entry_safe(fence, next, &obj->active_list_head, - active_list) { - if (fence_is_signaled_locked(fence)) - list_del_init(&fence->active_list); - } - - spin_unlock_irqrestore(&obj->child_list_lock, flags); -} -EXPORT_SYMBOL(sync_timeline_signal); - -struct fence *sync_pt_create(struct sync_timeline *obj, int size, - unsigned int value) -{ - unsigned long flags; - struct fence *fence; - - if (size < sizeof(*fence)) - return NULL; - - fence = kzalloc(size, GFP_KERNEL); - if (!fence) - return NULL; - - spin_lock_irqsave(&obj->child_list_lock, flags); - sync_timeline_get(obj); - fence_init(fence, &timeline_fence_ops, &obj->child_list_lock, - obj->context, value); - list_add_tail(&fence->child_list, &obj->child_list_head); - INIT_LIST_HEAD(&fence->active_list); - spin_unlock_irqrestore(&obj->child_list_lock, flags); - return fence; -} -EXPORT_SYMBOL(sync_pt_create); - -static const char *timeline_fence_get_driver_name(struct fence *fence) -{ - struct sync_timeline *parent = fence_parent(fence); - - return parent->drv_name; -} - -static const char *timeline_fence_get_timeline_name(struct fence *fence) -{ - struct sync_timeline *parent = fence_parent(fence); - - return parent->name; -} - -static void timeline_fence_release(struct fence *fence) -{ - struct sync_timeline *parent = fence_parent(fence); - unsigned long flags; - - spin_lock_irqsave(fence->lock, flags); - list_del(&fence->child_list); - if (WARN_ON_ONCE(!list_empty(&fence->active_list))) - list_del(&fence->active_list); - spin_unlock_irqrestore(fence->lock, flags); - - sync_timeline_put(parent); - fence_free(fence); -} - -static bool timeline_fence_signaled(struct fence *fence) -{ - struct sync_timeline *parent = fence_parent(fence); - - return (fence->seqno > parent->value) ? false : true; -} - -static bool timeline_fence_enable_signaling(struct fence *fence) -{ - struct sync_timeline *parent = fence_parent(fence); - - if (timeline_fence_signaled(fence)) - return false; - - list_add_tail(&fence->active_list, &parent->active_list_head); - return true; -} - -static int timeline_fence_fill_driver_data(struct fence *fence, - void *data, int size) -{ - if (size < sizeof(fence->seqno)) - return -ENOMEM; - - memcpy(data, &fence->seqno, sizeof(fence->seqno)); - - return sizeof(fence->seqno); -} - -static void timeline_fence_value_str(struct fence *fence, - char *str, int size) -{ - snprintf(str, size, "%d", fence->seqno); -} - -static void timeline_fence_timeline_value_str(struct fence *fence, - char *str, int size) -{ - struct sync_timeline *parent = fence_parent(fence); - - snprintf(str, size, "%d", parent->value); -} - -static const struct fence_ops timeline_fence_ops = { - .get_driver_name = timeline_fence_get_driver_name, - .get_timeline_name = timeline_fence_get_timeline_name, - .enable_signaling = timeline_fence_enable_signaling, - .signaled = timeline_fence_signaled, - .wait = fence_default_wait, - .release = timeline_fence_release, - .fill_driver_data = timeline_fence_fill_driver_data, - .fence_value_str = timeline_fence_value_str, - .timeline_value_str = timeline_fence_timeline_value_str, -}; - diff --git a/drivers/staging/android/sync.h b/drivers/staging/android/sync.h deleted file mode 100644 index be94a80..0000000 --- a/drivers/staging/android/sync.h +++ /dev/null @@ -1,130 +0,0 @@ -/* - * include/linux/sync.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_H -#define _LINUX_SYNC_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> -#include <linux/sync_file.h> -#include <uapi/linux/sync.h> - -/** - * struct sync_timeline - sync object - * @kref: reference count on fence. - * @drv_name: drv_name of the driver using the sync_timeline - * @name: name of the sync_timeline. Useful for debugging - * @destroyed: set when sync_timeline is destroyed - * @child_list_head: list of children sync_pts for this sync_timeline - * @child_list_lock: lock protecting @child_list_head, destroyed, and - * fence.status - * @active_list_head: list of active (unsignaled/errored) sync_pts - * @sync_timeline_list: membership in global sync_timeline_list - */ -struct sync_timeline { - struct kref kref; - char drv_name[32]; - char name[32]; - - /* protected by child_list_lock */ - bool destroyed; - int context, value; - - struct list_head child_list_head; - spinlock_t child_list_lock; - - struct list_head active_list_head; - -#ifdef CONFIG_DEBUG_FS - struct list_head sync_timeline_list; -#endif -}; - -static inline struct sync_timeline *fence_parent(struct fence *fence) -{ - return container_of(fence->lock, struct sync_timeline, - child_list_lock); -} - -/* - * API for sync_timeline implementers - */ - -/** - * sync_timeline_create() - creates a sync object - * @size: size to allocate for this obj - * @drv_name: sync_timeline driver name - * @name: sync_timeline name - * - * Creates a new sync_timeline. @size bytes will be allocated allowing - * for implementation specific data to be kept after the generic - * sync_timeline struct. Returns the sync_timeline object or NULL in - * case of error. - */ -struct sync_timeline *sync_timeline_create(int size, const char *drv_name, - const char *name); - -/** - * sync_timeline_destroy() - destroys a sync object - * @obj: sync_timeline to destroy - * - * A sync implementation should call this when the @obj is going away - * (i.e. module unload.) @obj won't actually be freed until all its children - * fences are freed. - */ -void sync_timeline_destroy(struct sync_timeline *obj); - -/** - * sync_timeline_signal() - signal a status change on a sync_timeline - * @obj: sync_timeline to signal - * @inc: num to increment on timeline->value - * - * A sync implementation should call this any time one of it's fences - * has signaled or has an error condition. - */ -void sync_timeline_signal(struct sync_timeline *obj, unsigned int inc); - -/** - * sync_pt_create() - creates a sync pt - * @parent: fence's parent sync_timeline - * @size: size to allocate for this pt - * @inc: value of the fence - * - * Creates a new fence as a child of @parent. @size bytes will be - * allocated allowing for implementation specific data to be kept after - * the generic sync_timeline struct. Returns the fence object or - * NULL in case of error. - */ -struct fence *sync_pt_create(struct sync_timeline *parent, int size, - unsigned int inc); - -#ifdef CONFIG_DEBUG_FS - -void sync_timeline_debug_add(struct sync_timeline *obj); -void sync_timeline_debug_remove(struct sync_timeline *obj); -void sync_file_debug_add(struct sync_file *fence); -void sync_file_debug_remove(struct sync_file *fence); -void sync_dump(void); - -#else -# define sync_timeline_debug_add(obj) -# define sync_timeline_debug_remove(obj) -# define sync_file_debug_add(fence) -# define sync_file_debug_remove(fence) -# define sync_dump() -#endif - -#endif /* _LINUX_SYNC_H */ diff --git a/drivers/staging/android/sync_debug.c b/drivers/staging/android/sync_debug.c deleted file mode 100644 index 9312e6f..0000000 --- a/drivers/staging/android/sync_debug.c +++ /dev/null @@ -1,373 +0,0 @@ -/* - * drivers/base/sync.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/debugfs.h> -#include <linux/module.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> -#include <linux/uaccess.h> -#include <linux/anon_inodes.h> -#include <linux/time64.h> -#include <linux/sync_file.h> -#include <linux/types.h> -#include <linux/kconfig.h> - -#include "uapi/sw_sync.h" -#include "sync.h" - -#ifdef CONFIG_DEBUG_FS - -static struct dentry *dbgfs; - -static LIST_HEAD(sync_timeline_list_head); -static DEFINE_SPINLOCK(sync_timeline_list_lock); -static LIST_HEAD(sync_file_list_head); -static DEFINE_SPINLOCK(sync_file_list_lock); - -void sync_timeline_debug_add(struct sync_timeline *obj) -{ - unsigned long flags; - - spin_lock_irqsave(&sync_timeline_list_lock, flags); - list_add_tail(&obj->sync_timeline_list, &sync_timeline_list_head); - spin_unlock_irqrestore(&sync_timeline_list_lock, flags); -} - -void sync_timeline_debug_remove(struct sync_timeline *obj) -{ - unsigned long flags; - - spin_lock_irqsave(&sync_timeline_list_lock, flags); - list_del(&obj->sync_timeline_list); - spin_unlock_irqrestore(&sync_timeline_list_lock, flags); -} - -void sync_file_debug_add(struct sync_file *sync_file) -{ - unsigned long flags; - - spin_lock_irqsave(&sync_file_list_lock, flags); - list_add_tail(&sync_file->sync_file_list, &sync_file_list_head); - spin_unlock_irqrestore(&sync_file_list_lock, flags); -} - -void sync_file_debug_remove(struct sync_file *sync_file) -{ - unsigned long flags; - - spin_lock_irqsave(&sync_file_list_lock, flags); - list_del(&sync_file->sync_file_list); - spin_unlock_irqrestore(&sync_file_list_lock, flags); -} - -static const char *sync_status_str(int status) -{ - if (status == 0) - return "signaled"; - - if (status > 0) - return "active"; - - return "error"; -} - -static void sync_print_fence(struct seq_file *s, struct fence *fence, bool show) -{ - int status = 1; - struct sync_timeline *parent = fence_parent(fence); - - if (fence_is_signaled_locked(fence)) - status = fence->status; - - seq_printf(s, " %s%sfence %s", - show ? parent->name : "", - show ? "_" : "", - sync_status_str(status)); - - if (status <= 0) { - struct timespec64 ts64 = - ktime_to_timespec64(fence->timestamp); - - seq_printf(s, "@%lld.%09ld", (s64)ts64.tv_sec, ts64.tv_nsec); - } - - if ((!fence || fence->ops->timeline_value_str) && - fence->ops->fence_value_str) { - char value[64]; - bool success; - - fence->ops->fence_value_str(fence, value, sizeof(value)); - success = strlen(value); - - if (success) - seq_printf(s, ": %s", value); - - if (success && fence) { - fence->ops->timeline_value_str(fence, value, - sizeof(value)); - - if (strlen(value)) - seq_printf(s, " / %s", value); - } - } - - seq_puts(s, "\n"); -} - -static void sync_print_obj(struct seq_file *s, struct sync_timeline *obj) -{ - struct list_head *pos; - unsigned long flags; - - seq_printf(s, "%s %s: %d\n", obj->name, obj->drv_name, obj->value); - - spin_lock_irqsave(&obj->child_list_lock, flags); - list_for_each(pos, &obj->child_list_head) { - struct fence *fence = - container_of(pos, struct fence, child_list); - sync_print_fence(s, fence, false); - } - spin_unlock_irqrestore(&obj->child_list_lock, flags); -} - -static void sync_print_sync_file(struct seq_file *s, - struct sync_file *sync_file) -{ - int i; - - seq_printf(s, "[%p] %s: %s\n", sync_file, sync_file->name, - sync_status_str(atomic_read(&sync_file->status))); - - for (i = 0; i < sync_file->num_fences; ++i) { - sync_print_fence(s, sync_file->cbs[i].fence, true); - } -} - -static int sync_debugfs_show(struct seq_file *s, void *unused) -{ - unsigned long flags; - struct list_head *pos; - - seq_puts(s, "objs:\n--------------\n"); - - spin_lock_irqsave(&sync_timeline_list_lock, flags); - list_for_each(pos, &sync_timeline_list_head) { - struct sync_timeline *obj = - container_of(pos, struct sync_timeline, - sync_timeline_list); - - sync_print_obj(s, obj); - seq_puts(s, "\n"); - } - spin_unlock_irqrestore(&sync_timeline_list_lock, flags); - - seq_puts(s, "fences:\n--------------\n"); - - spin_lock_irqsave(&sync_file_list_lock, flags); - list_for_each(pos, &sync_file_list_head) { - struct sync_file *sync_file = - container_of(pos, struct sync_file, sync_file_list); - - sync_print_sync_file(s, sync_file); - seq_puts(s, "\n"); - } - spin_unlock_irqrestore(&sync_file_list_lock, flags); - return 0; -} - -static int sync_info_debugfs_open(struct inode *inode, struct file *file) -{ - return single_open(file, sync_debugfs_show, inode->i_private); -} - -static const struct file_operations sync_info_debugfs_fops = { - .open = sync_info_debugfs_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -#if IS_ENABLED(CONFIG_SW_SYNC) -/* - * *WARNING* - * - * improper use of this can result in deadlocking kernel drivers from userspace. - */ - -/* opening sw_sync create a new sync obj */ -static int sw_sync_debugfs_open(struct inode *inode, struct file *file) -{ - struct sync_timeline *obj; - char task_comm[TASK_COMM_LEN]; - - get_task_comm(task_comm, current); - - obj = sync_timeline_create(sizeof(*obj), "sw_sync", task_comm); - if (!obj) - return -ENOMEM; - - file->private_data = obj; - - return 0; -} - -static int sw_sync_debugfs_release(struct inode *inode, struct file *file) -{ - struct sync_timeline *obj = file->private_data; - - sync_timeline_destroy(obj); - return 0; -} - -static long sw_sync_ioctl_create_fence(struct sync_timeline *obj, - unsigned long arg) -{ - int fd = get_unused_fd_flags(O_CLOEXEC); - int err; - struct fence *fence; - struct sync_file *sync_file; - struct sw_sync_create_fence_data data; - - if (fd < 0) - return fd; - - if (copy_from_user(&data, (void __user *)arg, sizeof(data))) { - err = -EFAULT; - goto err; - } - - fence = sync_pt_create(obj, sizeof(*fence), data.value); - if (!fence) { - err = -ENOMEM; - goto err; - } - - data.name[sizeof(data.name) - 1] = '\0'; - sync_file = sync_file_create(data.name, fence); - if (!sync_file) { - fence_put(fence); - err = -ENOMEM; - goto err; - } - - data.fence = fd; - if (copy_to_user((void __user *)arg, &data, sizeof(data))) { - sync_file_put(sync_file); - err = -EFAULT; - goto err; - } - - sync_file_install(sync_file, fd); - - return 0; - -err: - put_unused_fd(fd); - return err; -} - -static long sw_sync_ioctl_inc(struct sync_timeline *obj, unsigned long arg) -{ - u32 value; - - if (copy_from_user(&value, (void __user *)arg, sizeof(value))) - return -EFAULT; - - sync_timeline_signal(obj, value); - - return 0; -} - -static long sw_sync_ioctl(struct file *file, unsigned int cmd, - unsigned long arg) -{ - struct sync_timeline *obj = file->private_data; - - switch (cmd) { - case SW_SYNC_IOC_CREATE_FENCE: - return sw_sync_ioctl_create_fence(obj, arg); - - case SW_SYNC_IOC_INC: - return sw_sync_ioctl_inc(obj, arg); - - default: - return -ENOTTY; - } -} - -static const struct file_operations sw_sync_debugfs_fops = { - .open = sw_sync_debugfs_open, - .release = sw_sync_debugfs_release, - .unlocked_ioctl = sw_sync_ioctl, - .compat_ioctl = sw_sync_ioctl, -}; -#endif - -static __init int sync_debugfs_init(void) -{ - dbgfs = debugfs_create_dir("sync", NULL); - - debugfs_create_file("info", 0444, dbgfs, NULL, &sync_info_debugfs_fops); - -#if IS_ENABLED(CONFIG_SW_SYNC) - debugfs_create_file("sw_sync", 0644, dbgfs, NULL, - &sw_sync_debugfs_fops); -#endif - - return 0; -} -late_initcall(sync_debugfs_init); - -static __exit void sync_debugfs_exit(void) -{ - if (dbgfs) - debugfs_remove_recursive(dbgfs); -} -module_exit(sync_debugfs_exit); - -#define DUMP_CHUNK 256 -static char sync_dump_buf[64 * 1024]; -void sync_dump(void) -{ - struct seq_file s = { - .buf = sync_dump_buf, - .size = sizeof(sync_dump_buf) - 1, - }; - int i; - - sync_debugfs_show(&s, NULL); - - for (i = 0; i < s.count; i += DUMP_CHUNK) { - if ((s.count - i) > DUMP_CHUNK) { - char c = s.buf[i + DUMP_CHUNK]; - - s.buf[i + DUMP_CHUNK] = 0; - pr_cont("%s", s.buf + i); - s.buf[i + DUMP_CHUNK] = c; - } else { - s.buf[s.count] = 0; - pr_cont("%s", s.buf + i); - } - } -} - -#endif diff --git a/drivers/staging/android/trace/sync.h b/drivers/staging/android/trace/sync.h deleted file mode 100644 index d7f6457f..0000000 --- a/drivers/staging/android/trace/sync.h +++ /dev/null @@ -1,32 +0,0 @@ -#undef TRACE_SYSTEM -#define TRACE_INCLUDE_PATH ../../drivers/staging/android/trace -#define TRACE_SYSTEM sync - -#if !defined(_TRACE_SYNC_H) || defined(TRACE_HEADER_MULTI_READ) -#define _TRACE_SYNC_H - -#include "../sync.h" -#include <linux/tracepoint.h> - -TRACE_EVENT(sync_timeline, - TP_PROTO(struct sync_timeline *timeline), - - TP_ARGS(timeline), - - TP_STRUCT__entry( - __string(name, timeline->name) - __field(u32, value) - ), - - TP_fast_assign( - __assign_str(name, timeline->name); - __entry->value = timeline->value; - ), - - TP_printk("name=%s value=%d", __get_str(name), __entry->value) -); - -#endif /* if !defined(_TRACE_SYNC_H) || defined(TRACE_HEADER_MULTI_READ) */ - -/* This part must be outside protection */ -#include <trace/define_trace.h> diff --git a/drivers/staging/android/uapi/sw_sync.h b/drivers/staging/android/uapi/sw_sync.h deleted file mode 100644 index 9b5d486..0000000 --- a/drivers/staging/android/uapi/sw_sync.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * 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. - * - */ - -#ifndef _UAPI_LINUX_SW_SYNC_H -#define _UAPI_LINUX_SW_SYNC_H - -#include <linux/types.h> - -struct sw_sync_create_fence_data { - __u32 value; - char name[32]; - __s32 fence; /* fd of new fence */ -}; - -#define SW_SYNC_IOC_MAGIC 'W' - -#define SW_SYNC_IOC_CREATE_FENCE _IOWR(SW_SYNC_IOC_MAGIC, 0,\ - struct sw_sync_create_fence_data) -#define SW_SYNC_IOC_INC _IOW(SW_SYNC_IOC_MAGIC, 1, __u32) - -#endif /* _UAPI_LINUX_SW_SYNC_H */ diff --git a/include/linux/sync_timeline.h b/include/linux/sync_timeline.h new file mode 100644 index 0000000..27a2eda --- /dev/null +++ b/include/linux/sync_timeline.h @@ -0,0 +1,114 @@ +/* + * include/linux/sync_timeline.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_TIMELINE_H +#define _LINUX_SYNC_TIMELINE_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> +#include <linux/sync_file.h> +#include <uapi/linux/sync.h> + +/** + * struct sync_timeline - sync object + * @kref: reference count on fence. + * @drv_name: drv_name of the driver using the sync_timeline + * @name: name of the sync_timeline. Useful for debugging + * @destroyed: set when sync_timeline is destroyed + * @child_list_head: list of children sync_pts for this sync_timeline + * @child_list_lock: lock protecting @child_list_head, destroyed, and + * fence.status + * @active_list_head: list of active (unsignaled/errored) sync_pts + * @sync_timeline_list: membership in global sync_timeline_list + */ +struct sync_timeline { + struct kref kref; + char drv_name[32]; + char name[32]; + + /* protected by child_list_lock */ + bool destroyed; + int context, value; + + struct list_head child_list_head; + spinlock_t child_list_lock; + + struct list_head active_list_head; + +#ifdef CONFIG_DEBUG_FS + struct list_head sync_timeline_list; +#endif +}; + +static inline struct sync_timeline *fence_parent(struct fence *fence) +{ + return container_of(fence->lock, struct sync_timeline, + child_list_lock); +} + +/* + * API for sync_timeline implementers + */ + +/** + * sync_timeline_create() - creates a sync object + * @size: size to allocate for this obj + * @drv_name: sync_timeline driver name + * @name: sync_timeline name + * + * Creates a new sync_timeline. @size bytes will be allocated allowing + * for implementation specific data to be kept after the generic + * sync_timeline struct. Returns the sync_timeline object or NULL in + * case of error. + */ +struct sync_timeline *sync_timeline_create(int size, const char *drv_name, + const char *name); + +/** + * sync_timeline_destroy() - destroys a sync object + * @obj: sync_timeline to destroy + * + * A sync implementation should call this when the @obj is going away + * (i.e. module unload.) @obj won't actually be freed until all its children + * fences are freed. + */ +void sync_timeline_destroy(struct sync_timeline *obj); + +/** + * sync_timeline_signal() - signal a status change on a sync_timeline + * @obj: sync_timeline to signal + * @inc: num to increment on timeline->value + * + * A sync implementation should call this any time one of it's fences + * has signaled or has an error condition. + */ +void sync_timeline_signal(struct sync_timeline *obj, unsigned int inc); + +/** + * sync_pt_create() - creates a sync pt + * @parent: fence's parent sync_timeline + * @size: size to allocate for this pt + * @inc: value of the fence + * + * Creates a new fence as a child of @parent. @size bytes will be + * allocated allowing for implementation specific data to be kept after + * the generic sync_timeline struct. Returns the fence object or + * NULL in case of error. + */ +struct fence *sync_pt_create(struct sync_timeline *parent, int size, + unsigned int inc); + +#endif /* _LINUX_SYNC_TIMELINE_H */ diff --git a/include/trace/events/sync_timeline.h b/include/trace/events/sync_timeline.h new file mode 100644 index 0000000..c4b769b --- /dev/null +++ b/include/trace/events/sync_timeline.h @@ -0,0 +1,31 @@ +#undef TRACE_SYSTEM +#define TRACE_SYSTEM sync_timeline + +#if !defined(_TRACE_SYNC_TIMELINE_H) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_SYNC_TIMELINE_H + +#include <linux/sync_timeline.h> +#include <linux/tracepoint.h> + +TRACE_EVENT(sync_timeline, + TP_PROTO(struct sync_timeline *timeline), + + TP_ARGS(timeline), + + TP_STRUCT__entry( + __string(name, timeline->name) + __field(u32, value) + ), + + TP_fast_assign( + __assign_str(name, timeline->name); + __entry->value = timeline->value; + ), + + TP_printk("name=%s value=%d", __get_str(name), __entry->value) +); + +#endif /* if !defined(_TRACE_SYNC_H) || defined(TRACE_HEADER_MULTI_READ) */ + +/* This part must be outside protection */ +#include <trace/define_trace.h> -- 2.5.0 _______________________________________________ devel mailing list devel@xxxxxxxxxxxxxxxxxxxxxx http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel